creates webhook and cron job to update inventory

This commit is contained in:
Sebastian Rindom committed 2020-08-03 14:05:56 +02:00
1 parent c18677d5f2
commit e69c3aba01
10 files changed
+317 -22

No files matched your search

@@ -0,0 +1,15 @@
import { Router } from "express"
import bodyParser from "body-parser"
export default (container) => {
const app = Router()
app.post("/brightpearl/inventory-update", bodyParser.json(), async (req, res) => {
const { id } = req.body
const brightpearlService = req.scope.resolve("brightpearlService")
await brightpearlService.updateInventory(id)
res.sendStatus(200)
})
return app
}
@@ -0,0 +1,8 @@
const inventorySync = container => {
const brightpearlService = container.resolve("brightpearlService")
const eventBus = container.resolve("eventBusService")
const pattern = "43 4,10,14,20 * * *" // nice for tests "*/10 * * * * *"
eventBus.createCronJob("inventory-sync", {}, pattern, brightpearlService.syncInventory())
}
export default inventorySync
@@ -0,0 +1,6 @@
const webhookLoader = async (container) => {
const brightpearlService = container.resolve("brightpearlService")
await brightpearlService.verifyWebhooks()
}
export default webhookLoader
@@ -2,10 +2,11 @@ import { BaseService } from "medusa-interfaces"
import Brightpearl from "../utils/brightpearl"
class BrightpearlService extends BaseService {
constructor({ totalsService, regionService, orderService, discountService }, options) {
constructor({ totalsService, productVariantService, regionService, orderService, discountService }, options) {
super()
this.options = options
this.productVariantService_ = productVariantService
this.regionService_ = regionService
this.orderService_ = orderService
this.totalsService_ = totalsService
@@ -19,6 +20,69 @@ class BrightpearlService extends BaseService {
})
}
async verifyWebhooks() {
const hooks = [
{
subscribeTo: "product.modified.on-hand-modified",
httpMethod: "POST",
uriTemplate: `${this.options.backend_url}/brightpearl/inventory-update`,
bodyTemplate: '{"account": "${account-code}", "lifecycleEvent": "${lifecycle-event}", "resourceType": "${resource-type}", "id": "${resource-id}" }',
contentType: "application/json",
idSetAccepted: false,
}
]
const installedHooks = await this.brightpearl_.webhooks.list().catch(() => [])
for (const hook of hooks) {
const isInstalled = installedHooks.find(i =>
i.subscribeTo === hook.subscribeTo &&
i.httpMethod === hook.httpMethod &&
i.uriTemplate === hook.uriTemplate &&
i.bodyTemplate === hook.bodyTemplate &&
i.contentType === hook.contentType &&
i.idSetAccepted === hook.idSetAccepted
)
if (!isInstalled) {
await this.brightpearl_.webhooks.create(hook)
}
}
}
async syncInventory() {
const variants = await this.productVariantService_.list()
return Promise.all(variants.map(async v => {
const brightpearlProduct = await this.retrieveProductBySKU(v.sku)
if (!brightpearlProduct) {
return
}
const { productId } = brightpearlProduct
const availability = await this.brightpearl_.products.retrieveAvailability(productId)
const onHand = availability[productId].total.onHand
return this.productVariantService_.update(v._id, {
inventory_quantity: onHand
})
}))
}
async updateInventory(productId) {
const brightpearlProduct = await this.brightpearl_.products.retrieve(productId)
const availability = await this.brightpearl_.products.retrieveAvailability(productId)
const onHand = availability[productId].total.onHand
const sku = brightpearlProduct.identity.sku
const [ variant ] = await this.productVariantService_.list({ sku })
if (variant && variant.manage_inventory) {
await this.productVariantService_.update(variant._id, {
inventory_quantity: onHand
})
}
}
async createGoodsOutNote(fromOrder, shipment) {
const id = fromOrder.metadata && fromOrder.metadata.brightpearl_sales_order_id
@@ -10,6 +10,7 @@ class BrightpearlClient {
},
})
this.webhooks = this.buildWebhookEndpoints()
this.payments = this.buildPaymentEndpoints()
this.warehouses = this.buildWarehouseEndpoints()
this.orders = this.buildOrderEndpoints()
@@ -31,6 +32,25 @@ class BrightpearlClient {
})
}
buildWebhookEndpoints = () => {
return {
list: () => {
return this.client_.request({
url: `/integration-service/webhook`,
method: "GET",
})
.then(({ data }) => data.response)
},
create: (data) => {
return this.client_.request({
url: `/integration-service/webhook`,
method: "POST",
data
})
}
}
}
buildPaymentEndpoints = () => {
return {
create: (payment) => {
@@ -128,6 +148,18 @@ class BrightpearlClient {
buildProductEndpoints = () => {
return {
retrieveAvailability: productId => {
return this.client_.request({
url: `/warehouse-service/product-availability/${productId}`,
})
.then(({ data }) => data.response && data.response)
},
retrieve: (productId) => {
return this.client_.request({
url: `/product-service/product/${productId}`,
})
.then(({ data }) => data.response && data.response[0])
},
retrieveBySKU: (sku) => {
return this.client_.request({
url: `/product-service/product-search?SKU=${sku}`,