@things-factory/operato-hub 6.0.0 → 6.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist-server/tsconfig.tsbuildinfo +1 -1
  2. package/package.json +46 -46
  3. package/dist-server/entities/email-attachment.js +0 -77
  4. package/dist-server/entities/email-attachment.js.map +0 -1
  5. package/dist-server/entities/email-recipient.js +0 -69
  6. package/dist-server/entities/email-recipient.js.map +0 -1
  7. package/dist-server/entities/email.js +0 -90
  8. package/dist-server/entities/email.js.map +0 -1
  9. package/dist-server/graphql/resolvers/email/index.js +0 -6
  10. package/dist-server/graphql/resolvers/email/index.js.map +0 -1
  11. package/dist-server/graphql/resolvers/email/send-emails.js +0 -197
  12. package/dist-server/graphql/resolvers/email/send-emails.js.map +0 -1
  13. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js +0 -200
  14. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js.map +0 -1
  15. package/dist-server/graphql/resolvers/reports/index.js +0 -7
  16. package/dist-server/graphql/resolvers/reports/index.js.map +0 -1
  17. package/dist-server/graphql/resolvers/reports/outbound-order-details-report.js +0 -231
  18. package/dist-server/graphql/resolvers/reports/outbound-order-details-report.js.map +0 -1
  19. package/dist-server/graphql/types/reports/inbound-order-details-report-list.js +0 -14
  20. package/dist-server/graphql/types/reports/inbound-order-details-report-list.js.map +0 -1
  21. package/dist-server/graphql/types/reports/inbound-order-details-report.js +0 -59
  22. package/dist-server/graphql/types/reports/inbound-order-details-report.js.map +0 -1
  23. package/dist-server/graphql/types/reports/index.js +0 -13
  24. package/dist-server/graphql/types/reports/index.js.map +0 -1
  25. package/dist-server/graphql/types/reports/outbound-order-details-report-list.js +0 -14
  26. package/dist-server/graphql/types/reports/outbound-order-details-report-list.js.map +0 -1
  27. package/dist-server/graphql/types/reports/outbound-order-details-report.js +0 -76
  28. package/dist-server/graphql/types/reports/outbound-order-details-report.js.map +0 -1
  29. package/dist-server/routers/api/restful-apis/v1/company/add-contact-points.js +0 -105
  30. package/dist-server/routers/api/restful-apis/v1/company/add-contact-points.js.map +0 -1
  31. package/dist-server/routers/api/restful-apis/v1/company/add-marketplace-order.js +0 -197
  32. package/dist-server/routers/api/restful-apis/v1/company/add-marketplace-order.js.map +0 -1
  33. package/dist-server/routers/api/restful-apis/v1/company/add-products.js +0 -79
  34. package/dist-server/routers/api/restful-apis/v1/company/add-products.js.map +0 -1
  35. package/dist-server/routers/api/restful-apis/v1/company/cancel-marketplace-order.js +0 -90
  36. package/dist-server/routers/api/restful-apis/v1/company/cancel-marketplace-order.js.map +0 -1
  37. package/dist-server/routers/api/restful-apis/v1/company/get-bizplace-list.js +0 -49
  38. package/dist-server/routers/api/restful-apis/v1/company/get-bizplace-list.js.map +0 -1
  39. package/dist-server/routers/api/restful-apis/v1/company/get-contact-point-list.js +0 -62
  40. package/dist-server/routers/api/restful-apis/v1/company/get-contact-point-list.js.map +0 -1
  41. package/dist-server/routers/api/restful-apis/v1/company/get-marketplace-order-shipping-list.js +0 -98
  42. package/dist-server/routers/api/restful-apis/v1/company/get-marketplace-order-shipping-list.js.map +0 -1
  43. package/dist-server/routers/api/restful-apis/v1/company/get-marketplace-store-list.js +0 -51
  44. package/dist-server/routers/api/restful-apis/v1/company/get-marketplace-store-list.js.map +0 -1
  45. package/dist-server/routers/api/restful-apis/v1/company/get-partner-list.js +0 -88
  46. package/dist-server/routers/api/restful-apis/v1/company/get-partner-list.js.map +0 -1
  47. package/dist-server/routers/api/restful-apis/v1/company/get-product-list.js +0 -99
  48. package/dist-server/routers/api/restful-apis/v1/company/get-product-list.js.map +0 -1
  49. package/dist-server/routers/api/restful-apis/v1/company/index.js +0 -15
  50. package/dist-server/routers/api/restful-apis/v1/company/index.js.map +0 -1
  51. package/dist-server/routers/api/restful-apis/v1/company/update-marketplace-order-delivered.js +0 -62
  52. package/dist-server/routers/api/restful-apis/v1/company/update-marketplace-order-delivered.js.map +0 -1
  53. package/dist-server/routers/api/restful-apis/v1/company/update-marketplace-shipping-order.js +0 -40
  54. package/dist-server/routers/api/restful-apis/v1/company/update-marketplace-shipping-order.js.map +0 -1
  55. package/dist-server/routers/api/restful-apis/v1/middlewares/business-middleware.js +0 -70
  56. package/dist-server/routers/api/restful-apis/v1/middlewares/business-middleware.js.map +0 -1
  57. package/dist-server/routers/api/restful-apis/v1/middlewares/index.js +0 -40
  58. package/dist-server/routers/api/restful-apis/v1/middlewares/index.js.map +0 -1
  59. package/dist-server/routers/api/restful-apis/v1/middlewares/logging-middleware.js +0 -23
  60. package/dist-server/routers/api/restful-apis/v1/middlewares/logging-middleware.js.map +0 -1
  61. package/dist-server/routers/api/restful-apis/v1/middlewares/store-middleware.js +0 -32
  62. package/dist-server/routers/api/restful-apis/v1/middlewares/store-middleware.js.map +0 -1
  63. package/dist-server/routers/api/restful-apis/v1/middlewares/validation-middleware.js +0 -118
  64. package/dist-server/routers/api/restful-apis/v1/middlewares/validation-middleware.js.map +0 -1
  65. package/dist-server/routers/api/restful-apis/v1/middlewares/warehouse-middleware.js +0 -31
  66. package/dist-server/routers/api/restful-apis/v1/middlewares/warehouse-middleware.js.map +0 -1
  67. package/dist-server/routers/api/restful-apis/v1/utils/error-util.js +0 -71
  68. package/dist-server/routers/api/restful-apis/v1/utils/error-util.js.map +0 -1
  69. package/dist-server/routers/api/restful-apis/v1/utils/params.js +0 -563
  70. package/dist-server/routers/api/restful-apis/v1/utils/params.js.map +0 -1
  71. package/dist-server/routers/api/restful-apis/v1/utils/validate-util.js +0 -66
  72. package/dist-server/routers/api/restful-apis/v1/utils/validate-util.js.map +0 -1
  73. package/dist-server/routers/api/restful-apis/v1/warehouse/add-inbound-order.js +0 -236
  74. package/dist-server/routers/api/restful-apis/v1/warehouse/add-inbound-order.js.map +0 -1
  75. package/dist-server/routers/api/restful-apis/v1/warehouse/add-release-order.js +0 -801
  76. package/dist-server/routers/api/restful-apis/v1/warehouse/add-release-order.js.map +0 -1
  77. package/dist-server/routers/api/restful-apis/v1/warehouse/cancel-inbound-order.js +0 -199
  78. package/dist-server/routers/api/restful-apis/v1/warehouse/cancel-inbound-order.js.map +0 -1
  79. package/dist-server/routers/api/restful-apis/v1/warehouse/cancel-release-order.js +0 -192
  80. package/dist-server/routers/api/restful-apis/v1/warehouse/cancel-release-order.js.map +0 -1
  81. package/dist-server/routers/api/restful-apis/v1/warehouse/get-delivery-order-list.js +0 -138
  82. package/dist-server/routers/api/restful-apis/v1/warehouse/get-delivery-order-list.js.map +0 -1
  83. package/dist-server/routers/api/restful-apis/v1/warehouse/get-goods-received-note-list.js +0 -97
  84. package/dist-server/routers/api/restful-apis/v1/warehouse/get-goods-received-note-list.js.map +0 -1
  85. package/dist-server/routers/api/restful-apis/v1/warehouse/get-inbound-order-details.js +0 -81
  86. package/dist-server/routers/api/restful-apis/v1/warehouse/get-inbound-order-details.js.map +0 -1
  87. package/dist-server/routers/api/restful-apis/v1/warehouse/get-inbound-order-list.js +0 -94
  88. package/dist-server/routers/api/restful-apis/v1/warehouse/get-inbound-order-list.js.map +0 -1
  89. package/dist-server/routers/api/restful-apis/v1/warehouse/get-inventory-product-group-list.js +0 -87
  90. package/dist-server/routers/api/restful-apis/v1/warehouse/get-inventory-product-group-list.js.map +0 -1
  91. package/dist-server/routers/api/restful-apis/v1/warehouse/get-onhand-inventory-list.js +0 -87
  92. package/dist-server/routers/api/restful-apis/v1/warehouse/get-onhand-inventory-list.js.map +0 -1
  93. package/dist-server/routers/api/restful-apis/v1/warehouse/get-release-order-details.js +0 -96
  94. package/dist-server/routers/api/restful-apis/v1/warehouse/get-release-order-details.js.map +0 -1
  95. package/dist-server/routers/api/restful-apis/v1/warehouse/get-release-order-list.js +0 -110
  96. package/dist-server/routers/api/restful-apis/v1/warehouse/get-release-order-list.js.map +0 -1
  97. package/dist-server/routers/api/restful-apis/v1/warehouse/index.js +0 -16
  98. package/dist-server/routers/api/restful-apis/v1/warehouse/index.js.map +0 -1
  99. package/dist-server/routers/api/restful-apis/v1/warehouse/update-release-order-details.js +0 -71
  100. package/dist-server/routers/api/restful-apis/v1/warehouse/update-release-order-details.js.map +0 -1
  101. package/dist-server/routers/xilnex-router.js +0 -1104
  102. package/dist-server/routers/xilnex-router.js.map +0 -1
  103. package/dist-server/utils/report-query-util.js +0 -42
  104. package/dist-server/utils/report-query-util.js.map +0 -1
@@ -1,1104 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.xilnexRouter = void 0;
7
- const koa_router_1 = __importDefault(require("koa-router"));
8
- const typeorm_1 = require("typeorm");
9
- const uuid_1 = require("uuid");
10
- const biz_base_1 = require("@things-factory/biz-base");
11
- const env_1 = require("@things-factory/env");
12
- const id_rule_base_1 = require("@things-factory/id-rule-base");
13
- const integration_accounting_1 = require("@things-factory/integration-accounting");
14
- // import { createPayloadLog, PayloadType } from '@things-factory/integration-base'
15
- const product_base_1 = require("@things-factory/product-base");
16
- const sales_base_1 = require("@things-factory/sales-base");
17
- const setting_base_1 = require("@things-factory/setting-base");
18
- const shell_1 = require("@things-factory/shell");
19
- const warehouse_base_1 = require("@things-factory/warehouse-base");
20
- const index_1 = require("../errors/index");
21
- const debug = require('debug')('things-factory:integration-accounting:xilnex-router');
22
- exports.xilnexRouter = new koa_router_1.default();
23
- exports.xilnexRouter.post('/webhook-xilnex-po', async (context, next) => {
24
- const originalContext = context;
25
- try {
26
- await (0, typeorm_1.getConnection)().transaction(async (tx) => {
27
- const { id, warehouseId } = context.query;
28
- const { body, header } = context.request;
29
- const data = (body === null || body === void 0 ? void 0 : body.Data) ? JSON.parse(body.Data) : {};
30
- const account = await integration_accounting_1.AccountingAPI.getAccounting(id);
31
- if (!account) {
32
- context.throw(400, `${id} not found in Account`);
33
- }
34
- const { webhookKey } = account;
35
- const signature = header['xilnex-webhook-signature'];
36
- const xilnex = new integration_accounting_1.Xilnex({});
37
- if (!xilnex.isValidSignature(body, webhookKey, signature)) {
38
- let errBody = JSON.stringify({
39
- body,
40
- webhookKey,
41
- signature
42
- });
43
- context.throw(400, `Signature validation failed: ${errBody}`);
44
- }
45
- const customerDomain = account.domain;
46
- const customerBizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({
47
- where: { domain: customerDomain }
48
- });
49
- const custCompanyBizplace = await (0, biz_base_1.getCompanyBizplace)(null, null, customerBizplace.id, tx);
50
- const warehouseDomain = await tx.getRepository(shell_1.Domain).findOne({
51
- where: { id: warehouseId, extType: 'warehouse' }
52
- });
53
- if (!warehouseDomain) {
54
- context.throw(400, `${warehouseId} not found in warehouse domain`);
55
- }
56
- let accountWebhookOrder = {
57
- name: (0, uuid_1.v4)(),
58
- request: body,
59
- platform: integration_accounting_1.ACCOUNT_PLATFORM.XILNEX,
60
- domain: account.domain,
61
- status: integration_accounting_1.ACCOUNT_SYNC_STATUS.FAILED
62
- };
63
- if (data === null || data === void 0 ? void 0 : data.id) {
64
- const purchaseOrder = await integration_accounting_1.AccountingAPI.getPurchaseOrder(account, { orderId: data.id });
65
- const { orderInfo, orderItems } = purchaseOrder;
66
- let accountInfo = (account === null || account === void 0 ? void 0 : account.accountInfo) ? JSON.parse(account.accountInfo) : {};
67
- if (accountInfo.outlet == orderInfo.toOutlet) {
68
- const poNoSetting = await tx.getRepository(setting_base_1.Setting).findOne({
69
- where: {
70
- domain: warehouseDomain,
71
- name: sales_base_1.ORDER_NUMBER_SETTING_KEY.PO_NUMBER_RULE
72
- }
73
- });
74
- let orderNo = poNoSetting
75
- ? await (0, id_rule_base_1.generateId)({ domain: warehouseDomain, type: sales_base_1.ORDER_NUMBER_RULE_TYPE.PO_NUMBER, seed: {} })
76
- : sales_base_1.OrderNoGenerator.purchaseOrder();
77
- let purchaseOrder = {
78
- name: orderNo,
79
- refNo: orderInfo.orderId,
80
- refNo2: null,
81
- refNo3: null,
82
- etaDate: orderInfo.etaDate,
83
- ownTransport: orderInfo.ownTransport,
84
- importCargo: orderInfo.importCargo,
85
- container: orderInfo.container,
86
- remark: orderInfo.remark,
87
- currency: (orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.currency) || 'MYR',
88
- source: 'XILNEX',
89
- orderSourceType: 'XILNEX_PO',
90
- domain: warehouseDomain,
91
- bizplace: customerBizplace,
92
- status: sales_base_1.PURCHASE_ORDER_STATUS.DRAFT
93
- };
94
- purchaseOrder = await tx.getRepository(sales_base_1.PurchaseOrder).save(purchaseOrder);
95
- let orderProducts = [];
96
- await Promise.all(orderItems.map(async (item) => {
97
- const refCode = item.product.refCode;
98
- let productDetail = await tx.getRepository(product_base_1.ProductDetail).findOne({
99
- where: { domain: custCompanyBizplace.domain, refCode: refCode },
100
- relations: ['product']
101
- });
102
- if (!productDetail) {
103
- const sku = item.product.sku;
104
- const product = await tx.getRepository(product_base_1.Product).findOne({
105
- where: { domain: custCompanyBizplace.domain, sku }
106
- });
107
- if (product) {
108
- productDetail = await tx.getRepository(product_base_1.ProductDetail).findOne({
109
- where: { domain: custCompanyBizplace.domain, product },
110
- relations: ['product']
111
- });
112
- }
113
- else {
114
- context.throw(404, `error.sku ${sku} and refCode ${refCode} not exist in product master`);
115
- }
116
- }
117
- let orderProduct = {
118
- name: sales_base_1.OrderNoGenerator.orderProduct(),
119
- product: productDetail === null || productDetail === void 0 ? void 0 : productDetail.product,
120
- productDetail,
121
- batchId: (item === null || item === void 0 ? void 0 : item.batchId) || '-',
122
- packingType: productDetail === null || productDetail === void 0 ? void 0 : productDetail.packingType,
123
- packingSize: productDetail === null || productDetail === void 0 ? void 0 : productDetail.packingSize,
124
- uom: productDetail === null || productDetail === void 0 ? void 0 : productDetail.uom,
125
- uomValue: productDetail === null || productDetail === void 0 ? void 0 : productDetail.uomValue,
126
- packQty: item.confirmedQty,
127
- palletQty: 1,
128
- totalUomValue: `${(productDetail.uomValue * item.confirmedQty).toFixed(2)} ${productDetail.uom}`,
129
- status: sales_base_1.PURCHASE_ORDER_STATUS.DRAFT,
130
- unitPrice: item.unitCost || 1,
131
- taxRate: item.taxAmount,
132
- refItemId: item.refItemId,
133
- purchaseOrder,
134
- domain: warehouseDomain,
135
- bizplace: customerBizplace
136
- };
137
- orderProducts.push(orderProduct);
138
- }));
139
- await tx.getRepository(sales_base_1.OrderProduct).save(orderProducts);
140
- }
141
- accountWebhookOrder.status = integration_accounting_1.ACCOUNT_SYNC_STATUS.SUCCESS;
142
- await tx.getRepository(integration_accounting_1.AccountWebhookOrder).save(accountWebhookOrder);
143
- }
144
- });
145
- context.status = 200;
146
- }
147
- catch (err) {
148
- env_1.logger.error(`xilnex-router[webhook-xilnex-po-original-context]: ${JSON.stringify(originalContext)}`);
149
- env_1.logger.error(`xilnex-router[webhook-xilnex-po]: ${err}`);
150
- context.status = 400;
151
- context.throw(400, err);
152
- }
153
- });
154
- exports.xilnexRouter.post('/webhook-xilnex-transfer-note', async (context, next) => {
155
- const originalContext = context;
156
- try {
157
- await (0, typeorm_1.getConnection)().transaction(async (tx) => {
158
- const { id, warehouseId } = context.query;
159
- const { body, header } = context.request;
160
- const data = (body === null || body === void 0 ? void 0 : body.Data) ? JSON.parse(body.Data) : {};
161
- const account = await integration_accounting_1.AccountingAPI.getAccounting(id);
162
- if (!account) {
163
- context.throw(400, `${id} not found in Account`);
164
- }
165
- const { webhookKey } = account;
166
- const signature = header['xilnex-webhook-signature'];
167
- const xilnex = new integration_accounting_1.Xilnex({});
168
- if (!xilnex.isValidSignature(body, webhookKey, signature)) {
169
- let errBody = JSON.stringify({
170
- body,
171
- webhookKey,
172
- signature
173
- });
174
- context.throw(400, `Signature validation failed: ${errBody}`);
175
- }
176
- const customerDomain = account.domain;
177
- const customerBizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({
178
- where: { domain: customerDomain }
179
- });
180
- const custCompanyBizplace = await (0, biz_base_1.getCompanyBizplace)(null, null, customerBizplace.id, tx);
181
- const warehouseDomain = await tx.getRepository(shell_1.Domain).findOne({
182
- where: { id: warehouseId, extType: 'warehouse' }
183
- });
184
- if (!warehouseDomain) {
185
- context.throw(400, `${warehouseId} not found in warehouse domain`);
186
- }
187
- let accountWebhookOrder = {
188
- name: (0, uuid_1.v4)(),
189
- request: body,
190
- platform: integration_accounting_1.ACCOUNT_PLATFORM.XILNEX,
191
- domain: account.domain,
192
- status: integration_accounting_1.ACCOUNT_SYNC_STATUS.FAILED
193
- };
194
- let accountInfo = (account === null || account === void 0 ? void 0 : account.accountInfo) ? JSON.parse(account.accountInfo) : {};
195
- if (data === null || data === void 0 ? void 0 : data.id) {
196
- const transferNote = await integration_accounting_1.AccountingAPI.getTransferNote(account, { orderId: data.id });
197
- const { orderInfo, orderItems } = transferNote;
198
- if (orderInfo.fromLocation == accountInfo.outlet || orderInfo.toLocation == accountInfo.outlet) {
199
- // VDC release
200
- if (accountInfo.outlet == orderInfo.fromLocation) {
201
- let releaseGood = {
202
- domain: warehouseDomain,
203
- bizplace: customerBizplace,
204
- companyBizplace: custCompanyBizplace,
205
- courierOption: false,
206
- collectionOrderNo: orderInfo.orderId,
207
- exportOption: false,
208
- ownTransport: orderInfo.ownTransport,
209
- packingOption: false,
210
- refNo: orderInfo.orderId,
211
- refNo2: orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.fromLocation,
212
- refNo3: orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.toLocation,
213
- releaseDate: orderInfo.issueDate,
214
- type: 'b2b',
215
- source: 'XILNEX',
216
- orderSourceType: 'XILNEX_TRANSFER_NOTE',
217
- marketplaceOrderStatus: orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.status,
218
- remark: (orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.remark) || null
219
- };
220
- // check existing order
221
- await checkExistingOrder(releaseGood, customerBizplace, true, context, tx);
222
- //massage data
223
- let massagedData = await massageOrderItems(releaseGood, orderItems, context);
224
- // validation
225
- let errorList = [];
226
- await Promise.all(massagedData.combinedItems.map(async (item) => {
227
- let itemList = await tx.query(`
228
- select wboi.* from warehouse_bizplace_onhand_inventories wboi
229
- where wboi."domain_id"= $1 and
230
- wboi."bizplace_id" = $2 and
231
- wboi."group_type" = 'SINGLE' and
232
- wboi."product_id" = $3 and
233
- wboi."packing_type" = $4 and
234
- wboi."packing_size" = $5 and
235
- wboi."uom" = $6 and
236
- wboi."remain_qty" >= $7 and
237
- wboi."remain_uom_value" >= $8
238
- `, [
239
- warehouseDomain.id,
240
- customerBizplace.id,
241
- item.product.id,
242
- item.packingType,
243
- item.packingSize,
244
- item.uom,
245
- item.releaseQty,
246
- item.releaseUomValue
247
- ]);
248
- if (itemList.length <= 0) {
249
- errorList.push(JSON.stringify({
250
- code: 'insufficient stock',
251
- sku: item.product.sku,
252
- packingType: item.packingType,
253
- packingSize: item.packingSize,
254
- uom: item.uom,
255
- qty: item.releaseQty,
256
- uom_value: item.releaseUomValue
257
- }));
258
- }
259
- console.log();
260
- }));
261
- if (errorList.length > 0) {
262
- context.throw(404, errorList.join(', '));
263
- }
264
- let assignedOrderProducts = await assignToInventory(massagedData.orderProducts, customerBizplace, warehouseDomain, context, tx);
265
- let result = await createReleaseGood(releaseGood, assignedOrderProducts, customerBizplace, warehouseDomain, context, tx);
266
- let addReleaseGood = {
267
- id: result.id,
268
- name: result.name,
269
- refNo: result.refNo,
270
- refNo2: result.refNo2,
271
- refNo3: result.refNo3,
272
- status: result.status,
273
- truckNo: result.truckNo,
274
- ownTransport: result.ownTransport,
275
- crossDocking: result.crossDocking,
276
- type: result.type,
277
- exportOption: result.exportOption,
278
- releaseDate: result.releaseDate,
279
- collectionOrderNo: result.collectionOrderNo,
280
- paidAmount: result === null || result === void 0 ? void 0 : result.paidAmount,
281
- discountAmount: result === null || result === void 0 ? void 0 : result.discountAmount,
282
- taxAmount: result === null || result === void 0 ? void 0 : result.taxAmount,
283
- shippingFee: result === null || result === void 0 ? void 0 : result.shippingFee,
284
- bizplace: { name: result.bizplace.name },
285
- domain: { name: result.domain.name },
286
- orderInventories: result.orderInventories
287
- };
288
- context.body = { result: { addReleaseGood } };
289
- // createPayloadLog(
290
- // customerBizplace.id,
291
- // `/webhook-xilnex-stock-request`,
292
- // stockRequest,
293
- // context.body,
294
- // context,
295
- // PayloadType.INGESTION
296
- // )
297
- }
298
- // VDC inbound
299
- if (accountInfo.outlet == orderInfo.toLocation) {
300
- const ganNoSetting = await tx.getRepository(setting_base_1.Setting).findOne({
301
- where: {
302
- domain: warehouseDomain,
303
- name: sales_base_1.ORDER_NUMBER_SETTING_KEY.GAN_NUMBER_RULE
304
- }
305
- });
306
- let orderNo = '';
307
- if (ganNoSetting) {
308
- orderNo = await (0, id_rule_base_1.generateId)({ domain: warehouseDomain, type: sales_base_1.ORDER_NUMBER_RULE_TYPE.GAN_NUMBER, seed: {} });
309
- }
310
- else {
311
- orderNo = sales_base_1.OrderNoGenerator.arrivalNotice();
312
- }
313
- let arrivalNotice = {
314
- name: orderNo,
315
- refNo: orderInfo.orderId,
316
- refNo2: orderInfo.fromLocation,
317
- refNo3: orderInfo.toLocation,
318
- etaDate: orderInfo.etaDate,
319
- ownTransport: orderInfo.ownTransport,
320
- importCargo: orderInfo.importCargo,
321
- container: orderInfo.container,
322
- remark: orderInfo.remark,
323
- source: 'XILNEX',
324
- orderSourceType: 'XILNEX_TRANSFER_NOTE',
325
- domain: warehouseDomain,
326
- bizplace: customerBizplace,
327
- status: 'INTRANSIT'
328
- };
329
- arrivalNotice = await tx.getRepository(sales_base_1.ArrivalNotice).save(arrivalNotice);
330
- let orderProducts = [];
331
- await Promise.all(orderItems.map(async (item) => {
332
- const refCode = item.product.refCode;
333
- let productDetail = await tx.getRepository(product_base_1.ProductDetail).findOne({
334
- where: { domain: custCompanyBizplace.domain, refCode: refCode },
335
- relations: ['product']
336
- });
337
- if (!productDetail) {
338
- const sku = item.product.sku;
339
- const product = await tx.getRepository(product_base_1.Product).findOne({
340
- where: { domain: custCompanyBizplace.domain, sku }
341
- });
342
- if (product) {
343
- productDetail = await tx.getRepository(product_base_1.ProductDetail).findOne({
344
- where: { domain: custCompanyBizplace.domain, product },
345
- relations: ['product']
346
- });
347
- }
348
- else {
349
- context.throw(404, `error.sku ${sku} and refCode ${refCode} not exist in product master`);
350
- }
351
- }
352
- let orderProduct = {
353
- name: sales_base_1.OrderNoGenerator.orderProduct(),
354
- product: productDetail === null || productDetail === void 0 ? void 0 : productDetail.product,
355
- productDetail,
356
- batchId: (item === null || item === void 0 ? void 0 : item.batchId) || '-',
357
- packingType: productDetail === null || productDetail === void 0 ? void 0 : productDetail.packingType,
358
- packingSize: productDetail === null || productDetail === void 0 ? void 0 : productDetail.packingSize,
359
- uom: productDetail === null || productDetail === void 0 ? void 0 : productDetail.uom,
360
- uomValue: productDetail === null || productDetail === void 0 ? void 0 : productDetail.uomValue,
361
- packQty: item.confirmedQty,
362
- palletQty: 1,
363
- totalUomValue: `${(productDetail.uomValue * item.confirmedQty).toFixed(2)} ${productDetail.uom}`,
364
- status: 'PENDING',
365
- arrivalNotice,
366
- domain: warehouseDomain,
367
- bizplace: customerBizplace
368
- };
369
- orderProducts.push(orderProduct);
370
- }));
371
- await tx.getRepository(sales_base_1.OrderProduct).save(orderProducts);
372
- }
373
- }
374
- }
375
- accountWebhookOrder.status = integration_accounting_1.ACCOUNT_SYNC_STATUS.SUCCESS;
376
- await tx.getRepository(integration_accounting_1.AccountWebhookOrder).save(accountWebhookOrder);
377
- });
378
- context.status = 200;
379
- }
380
- catch (err) {
381
- env_1.logger.error(`xilnex-router[webhook-xilnex-transfer-note-original-context]: ${JSON.stringify(originalContext)}`);
382
- env_1.logger.error(`xilnex-router[webhook-xilnex-transfer-note]: ${err}`);
383
- context.status = 400;
384
- context.throw(400, err);
385
- }
386
- });
387
- exports.xilnexRouter.post('/webhook-xilnex-stock-request', async (context, next) => {
388
- try {
389
- await (0, typeorm_1.getConnection)().transaction(async (tx) => {
390
- const { id, warehouseId } = context.query;
391
- const { body, headers } = context.request;
392
- const data = (body === null || body === void 0 ? void 0 : body.Data) ? JSON.parse(body.Data) : {};
393
- const account = await integration_accounting_1.AccountingAPI.getAccounting(id);
394
- if (!account) {
395
- throw new Error(`${id} not found in Account`);
396
- }
397
- const { webhookKey } = account;
398
- const signature = headers['xilnex-webhook-signature'];
399
- const xilnex = new integration_accounting_1.Xilnex({});
400
- if (!xilnex.isValidSignature(body, webhookKey, signature)) {
401
- context.throw(400, 'Signature validation failed');
402
- }
403
- const customerDomain = account.domain;
404
- const customerBizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({
405
- where: { domain: customerDomain }
406
- });
407
- const custCompanyBizplace = await (0, biz_base_1.getCompanyBizplace)(null, null, customerBizplace.id, tx);
408
- const warehouseDomain = await tx.getRepository(shell_1.Domain).findOne({
409
- where: { id: warehouseId, extType: 'warehouse' }
410
- });
411
- if (!warehouseDomain) {
412
- context.throw(400, `${warehouseId} not found in warehouse domain`);
413
- }
414
- let accountWebhookOrder = {
415
- name: (0, uuid_1.v4)(),
416
- request: body,
417
- platform: integration_accounting_1.ACCOUNT_PLATFORM.XILNEX,
418
- domain: account.domain,
419
- status: integration_accounting_1.ACCOUNT_SYNC_STATUS.FAILED
420
- };
421
- let accountInfo = (account === null || account === void 0 ? void 0 : account.accountInfo) ? JSON.parse(account.accountInfo) : {};
422
- if (data === null || data === void 0 ? void 0 : data.id) {
423
- const stockRequest = await integration_accounting_1.AccountingAPI.getStockRequest(account, { orderId: data.id });
424
- const { orderInfo, orderItems } = stockRequest;
425
- if (orderInfo.fromLocation == accountInfo.outlet || orderInfo.toLocation == accountInfo.outlet) {
426
- // VDC release
427
- if (accountInfo.outlet == orderInfo.toLocation) {
428
- let releaseGood = {
429
- domain: warehouseDomain,
430
- bizplace: customerBizplace,
431
- companyBizplace: custCompanyBizplace,
432
- courierOption: false,
433
- collectionOrderNo: orderInfo.orderId,
434
- exportOption: false,
435
- ownTransport: orderInfo.ownTransport,
436
- packingOption: false,
437
- refNo: orderInfo.orderId,
438
- refNo2: orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.fromLocation,
439
- refNo3: orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.toLocation,
440
- releaseDate: orderInfo.issueDate,
441
- type: 'b2b',
442
- source: 'XILNEX',
443
- orderSourceType: 'XILNEX_STOCK_REQUEST',
444
- marketplaceOrderStatus: orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.status,
445
- remark: (orderInfo === null || orderInfo === void 0 ? void 0 : orderInfo.remark) || null
446
- };
447
- // check existing order
448
- await checkExistingOrder(releaseGood, customerBizplace, true, context, tx);
449
- //massage data
450
- let massagedData = await massageOrderItems(releaseGood, orderItems, context);
451
- // validation
452
- let errorList = [];
453
- await Promise.all(massagedData.combinedItems.map(async (item) => {
454
- let itemList = await tx.query(`
455
- select wboi.* from warehouse_bizplace_onhand_inventories wboi
456
- where wboi."domain_id"= $1 and
457
- wboi."bizplace_id" = $2 and
458
- wboi."group_type" = 'SINGLE' and
459
- wboi."product_id" = $3 and
460
- wboi."packing_type" = $4 and
461
- wboi."packing_size" = $5 and
462
- wboi."uom" = $6 and
463
- wboi."remain_qty" >= $7 and
464
- wboi."remain_uom_value" >= $8
465
- `, [
466
- warehouseDomain.id,
467
- customerBizplace.id,
468
- item.product.id,
469
- item.packingType,
470
- item.packingSize,
471
- item.uom,
472
- item.releaseQty,
473
- item.releaseUomValue
474
- ]);
475
- if (itemList.length <= 0) {
476
- errorList.push(JSON.stringify({
477
- code: 'insufficient stock',
478
- sku: item.product.sku,
479
- packingType: item.packingType,
480
- packingSize: item.packingSize,
481
- uom: item.uom,
482
- qty: item.releaseQty,
483
- uom_value: item.releaseUomValue
484
- }));
485
- }
486
- console.log();
487
- }));
488
- if (errorList.length > 0) {
489
- context.throw(404, errorList.join(', '));
490
- }
491
- let assignedOrderProducts = await assignToInventory(massagedData.orderProducts, customerBizplace, warehouseDomain, context, tx);
492
- let result = await createReleaseGood(releaseGood, assignedOrderProducts, customerBizplace, warehouseDomain, context, tx);
493
- let addReleaseGood = {
494
- id: result.id,
495
- name: result.name,
496
- refNo: result.refNo,
497
- refNo2: result.refNo2,
498
- refNo3: result.refNo3,
499
- status: result.status,
500
- truckNo: result.truckNo,
501
- ownTransport: result.ownTransport,
502
- crossDocking: result.crossDocking,
503
- type: result.type,
504
- exportOption: result.exportOption,
505
- releaseDate: result.releaseDate,
506
- collectionOrderNo: result.collectionOrderNo,
507
- paidAmount: result === null || result === void 0 ? void 0 : result.paidAmount,
508
- discountAmount: result === null || result === void 0 ? void 0 : result.discountAmount,
509
- taxAmount: result === null || result === void 0 ? void 0 : result.taxAmount,
510
- shippingFee: result === null || result === void 0 ? void 0 : result.shippingFee,
511
- bizplace: { name: result.bizplace.name },
512
- domain: { name: result.domain.name },
513
- orderInventories: result.orderInventories
514
- };
515
- context.body = { result: { addReleaseGood } };
516
- // createPayloadLog(
517
- // customerBizplace.id,
518
- // `/webhook-xilnex-stock-request`,
519
- // stockRequest,
520
- // context.body,
521
- // context,
522
- // PayloadType.INGESTION
523
- // )
524
- }
525
- // VDC inbound
526
- if (accountInfo.outlet == orderInfo.fromLocation) {
527
- const ganNoSetting = await tx.getRepository(setting_base_1.Setting).findOne({
528
- where: {
529
- domain: warehouseDomain,
530
- name: sales_base_1.ORDER_NUMBER_SETTING_KEY.GAN_NUMBER_RULE
531
- }
532
- });
533
- let orderNo = '';
534
- if (ganNoSetting) {
535
- orderNo = await (0, id_rule_base_1.generateId)({ domain: warehouseDomain, type: sales_base_1.ORDER_NUMBER_RULE_TYPE.GAN_NUMBER, seed: {} });
536
- }
537
- else {
538
- orderNo = sales_base_1.OrderNoGenerator.arrivalNotice();
539
- }
540
- let arrivalNotice = {
541
- name: orderNo,
542
- refNo: orderInfo.orderId,
543
- refNo2: orderInfo.fromLocation,
544
- refNo3: orderInfo.toLocation,
545
- etaDate: orderInfo.etaDate,
546
- ownTransport: orderInfo.ownTransport,
547
- importCargo: orderInfo.importCargo,
548
- container: orderInfo.container,
549
- remark: orderInfo.remark,
550
- source: 'XILNEX',
551
- orderSourceType: 'XILNEX_STOCK_REQUEST',
552
- domain: warehouseDomain,
553
- bizplace: customerBizplace,
554
- status: 'INTRANSIT'
555
- };
556
- arrivalNotice = await tx.getRepository(sales_base_1.ArrivalNotice).save(arrivalNotice);
557
- let orderProducts = [];
558
- await Promise.all(orderItems.map(async (item) => {
559
- const productDetail = await (0, typeorm_1.getRepository)(product_base_1.ProductDetail).findOne({
560
- where: { domain: custCompanyBizplace.domain, refCode: item.product.refCode },
561
- relations: ['product']
562
- });
563
- if (!productDetail) {
564
- context.throw(404, `no matching product found`);
565
- }
566
- let orderProduct = {
567
- name: sales_base_1.OrderNoGenerator.orderProduct(),
568
- product: productDetail === null || productDetail === void 0 ? void 0 : productDetail.product,
569
- productDetail,
570
- batchId: (item === null || item === void 0 ? void 0 : item.batchId) || '-',
571
- packingType: productDetail === null || productDetail === void 0 ? void 0 : productDetail.packingType,
572
- packingSize: productDetail === null || productDetail === void 0 ? void 0 : productDetail.packingSize,
573
- uom: productDetail === null || productDetail === void 0 ? void 0 : productDetail.uom,
574
- uomValue: productDetail === null || productDetail === void 0 ? void 0 : productDetail.uomValue,
575
- packQty: item.confirmedQty,
576
- totalUomValue: `${(productDetail.uomValue * item.confirmedQty).toFixed(2)} ${productDetail.uom}`,
577
- status: 'PENDING',
578
- arrivalNotice,
579
- domain: warehouseDomain,
580
- bizplace: customerBizplace
581
- };
582
- orderProducts.push(orderProduct);
583
- }));
584
- await tx.getRepository(sales_base_1.OrderProduct).save(orderProducts);
585
- }
586
- }
587
- }
588
- accountWebhookOrder.status = integration_accounting_1.ACCOUNT_SYNC_STATUS.SUCCESS;
589
- await tx.getRepository(integration_accounting_1.AccountWebhookOrder).save(accountWebhookOrder);
590
- });
591
- context.status = 200;
592
- }
593
- catch (err) {
594
- env_1.logger.error(`xilnex-router[webhook-xilnex-stock-request]: ${err}`);
595
- }
596
- });
597
- async function checkExistingOrder(releaseGood, bizplace, checkDuplicationValidation = true, context, tx) {
598
- const { domain } = context.state;
599
- const refNo = releaseGood.refNo;
600
- const refNo2 = releaseGood.refNo2;
601
- const refNo3 = releaseGood.refNo3;
602
- if (checkDuplicationValidation) {
603
- const foundDraftReleaseGood = await tx.getRepository(sales_base_1.DraftReleaseGood).findOne({
604
- where: {
605
- domain,
606
- refNo: refNo || null,
607
- refNo2: refNo2 || null,
608
- refNo3: refNo3 || null,
609
- status: (0, typeorm_1.Not)((0, typeorm_1.In)([sales_base_1.DRAFT_RELEASE_ORDER_STATUS.CANCELLED]))
610
- }
611
- });
612
- if (foundDraftReleaseGood) {
613
- throw new index_1.ValidationError({
614
- errorCode: 'EXISTING_ORDER',
615
- message: 'existing draft release order found',
616
- detail: foundDraftReleaseGood.name
617
- });
618
- }
619
- const foundReleaseGood = await tx.getRepository(sales_base_1.ReleaseGood).findOne({
620
- where: {
621
- domain: domain,
622
- refNo,
623
- status: (0, typeorm_1.Not)((0, typeorm_1.In)([sales_base_1.ORDER_STATUS.CANCELLED, sales_base_1.ORDER_STATUS.PENDING_CANCEL]))
624
- },
625
- relations: ['bizplace', 'bizplace.domain', 'bizplace.company', 'bizplace.company.domain']
626
- });
627
- if (foundReleaseGood) {
628
- throw new index_1.ValidationError({
629
- errorCode: 'EXISTING_ORDER',
630
- message: 'existing release order found',
631
- detail: foundReleaseGood.name
632
- });
633
- }
634
- }
635
- }
636
- async function massageOrderItems(releaseGood, inputOrderProducts, context) {
637
- try {
638
- let orderProducts = [];
639
- let errorList = [];
640
- let totalReleaseQty = 0;
641
- //combine any repeated skus
642
- inputOrderProducts = inputOrderProducts.reduce((acc, itm, idx) => {
643
- let { sku, refCode } = itm.product;
644
- let { packingType, packingSize, confirmedQty, orderItemId } = itm;
645
- if (!sku && !refCode) {
646
- errorList.push(JSON.stringify({
647
- code: 'INVALID_DATA',
648
- message: 'sku or refCode not found',
649
- sku: sku,
650
- refCode: refCode,
651
- packingType: packingType === null || packingType === void 0 ? void 0 : packingType.trim(),
652
- packingSize: packingSize,
653
- qty: confirmedQty
654
- }));
655
- }
656
- if (confirmedQty <= 0) {
657
- errorList.push(JSON.stringify({
658
- code: 'INVALID_DATA',
659
- message: 'negative stock request',
660
- sku: sku,
661
- refCode: refCode,
662
- packingType: packingType === null || packingType === void 0 ? void 0 : packingType.trim(),
663
- packingSize: packingSize,
664
- qty: confirmedQty
665
- }));
666
- }
667
- let existingIndex = acc.findIndex(itm => (itm === null || itm === void 0 ? void 0 : itm.sku) == (sku === null || sku === void 0 ? void 0 : sku.trim()) &&
668
- (itm === null || itm === void 0 ? void 0 : itm.refCode) == (refCode === null || refCode === void 0 ? void 0 : refCode.trim()) &&
669
- (itm === null || itm === void 0 ? void 0 : itm.packingType) == (packingType === null || packingType === void 0 ? void 0 : packingType.trim()) &&
670
- (itm === null || itm === void 0 ? void 0 : itm.packingSize) == packingSize &&
671
- (itm === null || itm === void 0 ? void 0 : itm.refItemId) == orderItemId.trim());
672
- if (existingIndex >= 0 && confirmedQty > 0) {
673
- acc[existingIndex].confirmedQty = acc[existingIndex].confirmedQty + confirmedQty;
674
- totalReleaseQty += confirmedQty;
675
- }
676
- else {
677
- acc.push({
678
- sku: sku === null || sku === void 0 ? void 0 : sku.trim(),
679
- refCode: refCode === null || refCode === void 0 ? void 0 : refCode.trim(),
680
- packingType: packingType === null || packingType === void 0 ? void 0 : packingType.trim(),
681
- packingSize: packingSize,
682
- releaseQty: confirmedQty,
683
- refItemId: orderItemId
684
- });
685
- totalReleaseQty += confirmedQty;
686
- }
687
- return acc;
688
- }, []);
689
- if (errorList.length > 0) {
690
- throw new index_1.ValidationError({
691
- errorCode: 'INVALID_DATA',
692
- message: 'invalid data',
693
- detail: errorList.join(', ')
694
- });
695
- }
696
- //find customer sku in system
697
- await Promise.all(inputOrderProducts.map(async (inputOrderItem) => {
698
- const sku = inputOrderItem.sku;
699
- const refCode = inputOrderItem.refCode;
700
- const packingType = inputOrderItem.packingType;
701
- const packingSize = inputOrderItem.packingSize;
702
- const qb = (0, typeorm_1.getRepository)(product_base_1.ProductDetail)
703
- .createQueryBuilder('PD')
704
- .innerJoinAndSelect('PD.product', 'PROD')
705
- .where('PROD.bizplace_id = :bizplaceId', { bizplaceId: releaseGood.companyBizplace.id });
706
- if (!sku && !refCode) {
707
- context.throw(404, `error.sku ${sku} or refCode ${refCode} not found`);
708
- }
709
- if (refCode) {
710
- qb.andWhere('PD.ref_code = :refCode', { refCode });
711
- }
712
- if (sku) {
713
- qb.andWhere('PROD.sku = :sku', { sku });
714
- }
715
- if (packingType) {
716
- qb.andWhere('PD.packing_type = :packingType', { packingType });
717
- }
718
- if ((!packingType && !refCode) || !packingSize) {
719
- qb.andWhere('PD.is_default = :isDefault', { isDefault: true });
720
- }
721
- const productDetail = await qb.getOne();
722
- // order Product based on product detail
723
- if (productDetail) {
724
- let newOrderProduct = Object.assign({}, inputOrderItem);
725
- newOrderProduct = Object.assign(Object.assign({}, newOrderProduct), { product: productDetail.product, productDetail: productDetail, packingType: productDetail.packingType, packingSize: packingSize || productDetail.packingSize, uom: productDetail.uom, uomValue: productDetail.uomValue, refCode: inputOrderItem.refCode, releaseQty: inputOrderItem.releaseQty, releaseUomValue: inputOrderItem.releaseQty * (productDetail.uomValue || 1), packQty: 0, actualPackQty: 0, palletQty: 0, actualPalletQty: 0, type: 'RELEASE_OF_GOODS', status: sales_base_1.ORDER_PRODUCT_STATUS.ASSIGNED, batchId: '-', sellingPrice: inputOrderItem === null || inputOrderItem === void 0 ? void 0 : inputOrderItem.sellingPrice });
726
- newOrderProduct.orderInventories = [
727
- Object.assign(Object.assign({}, newOrderProduct), { packQty: 0, actualPackQty: 0, palletQty: 0, actualPalletQty: 0, type: 'RELEASE_OF_GOODS', status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET })
728
- ];
729
- orderProducts.push(newOrderProduct);
730
- }
731
- if (!productDetail) {
732
- const qb = (0, typeorm_1.getRepository)(product_base_1.ProductBundle)
733
- .createQueryBuilder('PB')
734
- .innerJoinAndSelect('PB.productBundleSettings', 'PBS')
735
- .innerJoinAndSelect('PBS.productDetail', 'PBD')
736
- .innerJoinAndSelect('PBD.product', 'PROD')
737
- .where('PB.bizplace_id = :bizplaceId', { bizplaceId: releaseGood.companyBizplace.id });
738
- if (!sku && !refCode) {
739
- context.throw(404, `error.sku ${sku} or refCode ${refCode} not found`);
740
- }
741
- if (refCode) {
742
- qb.andWhere('PB.ref_code = :refCode', { refCode });
743
- }
744
- if (sku) {
745
- qb.andWhere('PB.sku = :sku', { sku });
746
- }
747
- if (packingType) {
748
- qb.andWhere('PB.packing_type = :packingType', { packingType });
749
- }
750
- const foundProductBundle = await qb.getOne();
751
- if (foundProductBundle) {
752
- let orderProduct = {
753
- productBundle: foundProductBundle,
754
- refCode,
755
- packingType: foundProductBundle.packingType,
756
- packingSize: packingSize || 1,
757
- uom: inputOrderItem === null || inputOrderItem === void 0 ? void 0 : inputOrderItem.uom,
758
- releaseQty: inputOrderItem.releaseQty,
759
- releaseUomValue: inputOrderItem.releaseQty,
760
- packQty: 0,
761
- actualPackQty: 0,
762
- palletQty: 0,
763
- actualPalletQty: 0,
764
- orderInventories: [],
765
- type: 'RELEASE_OF_GOODS',
766
- status: sales_base_1.ORDER_PRODUCT_STATUS.ASSIGNED,
767
- batchId: '-',
768
- sellingPrice: inputOrderItem === null || inputOrderItem === void 0 ? void 0 : inputOrderItem.sellingPrice
769
- };
770
- const bundleProductSettings = foundProductBundle.productBundleSettings;
771
- bundleProductSettings.map(bundleProductSetting => {
772
- const productDetailBundle = bundleProductSetting.productDetail;
773
- let newOrderInventory = {
774
- product: productDetailBundle.product,
775
- productDetail: productDetailBundle,
776
- sku: productDetailBundle.product.sku,
777
- packingType: productDetailBundle.packingType,
778
- packingSize: productDetailBundle.packingSize,
779
- uom: productDetailBundle.uom,
780
- packQty: 0,
781
- actualPackQty: 0,
782
- palletQty: 0,
783
- actualPalletQty: 0,
784
- releaseQty: inputOrderItem.confirmedQty * bundleProductSetting.bundleQty,
785
- releaseUomValue: inputOrderItem.confirmedQty *
786
- bundleProductSetting.bundleQty *
787
- (productDetailBundle.uomValue <= 0 ? 1 : productDetailBundle.uomValue),
788
- type: 'RELEASE_OF_GOODS',
789
- status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET
790
- };
791
- orderProduct.orderInventories.push(newOrderInventory);
792
- });
793
- orderProducts.push(orderProduct);
794
- }
795
- else {
796
- if (sku && refCode) {
797
- context.throw(404, `error.sku ${sku} and refCode ${refCode} not exist in product / bundle master`);
798
- }
799
- if (sku) {
800
- context.throw(404, `error.sku ${sku} not exist in product / bundle master`);
801
- }
802
- if (refCode) {
803
- context.throw(404, `error.refCode ${refCode} not exist in product / bundle master`);
804
- }
805
- }
806
- }
807
- }));
808
- //combine any repeated skus
809
- let combinedItems = orderProducts.reduce((acc, op, idx) => {
810
- let oi = (op === null || op === void 0 ? void 0 : op.orderInventories) || [];
811
- oi.forEach(itm => {
812
- let { sku, refCode } = itm.product;
813
- let { packingType, packingSize, batchId, releaseQty, product, productDetail, uom } = itm;
814
- if (!sku && !refCode) {
815
- context.throw(404, `sku ${sku} or refCode ${refCode} not found`);
816
- }
817
- let existingIndex = acc.findIndex(itm => (itm === null || itm === void 0 ? void 0 : itm.sku) == (sku === null || sku === void 0 ? void 0 : sku.trim()) &&
818
- (itm === null || itm === void 0 ? void 0 : itm.refCode) == (refCode === null || refCode === void 0 ? void 0 : refCode.trim()) &&
819
- (itm === null || itm === void 0 ? void 0 : itm.packingType) == (packingType === null || packingType === void 0 ? void 0 : packingType.trim()) &&
820
- (itm === null || itm === void 0 ? void 0 : itm.packingSize) == packingSize &&
821
- (itm === null || itm === void 0 ? void 0 : itm.batchId) == (batchId === null || batchId === void 0 ? void 0 : batchId.trim()) &&
822
- (itm === null || itm === void 0 ? void 0 : itm.uom) == (uom === null || uom === void 0 ? void 0 : uom.trim()));
823
- if (existingIndex >= 0 && releaseQty > 0) {
824
- acc[existingIndex].releaseQty = acc[existingIndex].releaseQty + releaseQty;
825
- acc[existingIndex].releaseUomValue =
826
- acc[existingIndex].releaseUomValue + releaseQty * (productDetail.uomValue <= 0 ? 1 : productDetail.uomValue);
827
- }
828
- else {
829
- let updateObj = {
830
- sku: sku === null || sku === void 0 ? void 0 : sku.trim(),
831
- packingType: packingType === null || packingType === void 0 ? void 0 : packingType.trim(),
832
- packingSize: packingSize,
833
- uom: uom === null || uom === void 0 ? void 0 : uom.trim(),
834
- releaseQty: releaseQty,
835
- releaseUomValue: releaseQty * (productDetail.uomValue <= 0 ? 1 : productDetail.uomValue),
836
- product,
837
- productDetail
838
- };
839
- if (refCode)
840
- updateObj['refCode'] = refCode.trim();
841
- updateObj['batchId'] = batchId ? batchId === null || batchId === void 0 ? void 0 : batchId.trim() : '-';
842
- acc.push(updateObj);
843
- }
844
- });
845
- return acc;
846
- }, []);
847
- return { orderProducts, combinedItems };
848
- }
849
- catch (error) {
850
- throw error;
851
- }
852
- }
853
- async function assignToInventory(orderProducts, customerBizplace, warehouseDomain, context, tx) {
854
- const { client, domain, user } = context.state;
855
- for (let opIdx = 0; opIdx < orderProducts.length; opIdx++) {
856
- let orderProduct = orderProducts[opIdx];
857
- let assignedOrderInventories = [];
858
- const pickingProductSetting = await tx.getRepository(setting_base_1.Setting).findOne({
859
- where: { domain, name: 'rule-for-picking-product' }
860
- });
861
- for (let oiIdx = 0; oiIdx < orderProducts[opIdx].orderInventories.length; oiIdx++) {
862
- const orderInventory = orderProduct.orderInventories[oiIdx];
863
- let sortings = [];
864
- switch (orderInventory.product.pickingStrategy) {
865
- case 'LIFO':
866
- sortings.push({ name: 'iv.created_at', desc: true });
867
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
868
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
869
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
870
- }
871
- }
872
- else {
873
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
874
- }
875
- break;
876
- case 'FEFO':
877
- sortings.push({ name: 'iv.expiration_date', desc: false }, { name: 'iv.created_at', desc: false });
878
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
879
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
880
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
881
- }
882
- }
883
- else {
884
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
885
- }
886
- break;
887
- case 'FMFO':
888
- sortings.push({ name: 'iv.manufacture_date', desc: false }, { name: 'iv.created_at', desc: false });
889
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
890
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
891
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
892
- }
893
- }
894
- else {
895
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
896
- }
897
- break;
898
- case 'LOCATION':
899
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
900
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
901
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
902
- }
903
- }
904
- else {
905
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
906
- }
907
- break;
908
- //Every other case includes 'FIFO' will be applicable for this case
909
- default:
910
- sortings.push({ name: 'iv.created_at', desc: false });
911
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
912
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
913
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
914
- }
915
- }
916
- else {
917
- sortings.push({ name: 'loc.name', desc: false });
918
- sortings.push({ name: 'iv.pallet_id', desc: false });
919
- }
920
- break;
921
- }
922
- let queryFilters = [];
923
- let queryStrings = queryFilters.reduce((acc, itm, idx, arr) => {
924
- acc.values.push(itm.filters);
925
- switch (itm === null || itm === void 0 ? void 0 : itm.operator) {
926
- case 'notin':
927
- case 'in':
928
- acc.query.push(`${itm.query} ${itm.operator == 'notin' ? 'NOT IN' : 'IN'} (${itm.filtes
929
- .map((itm, idx) => {
930
- return `$${acc.values.length + 1}`;
931
- })
932
- .join(',')})`);
933
- break;
934
- default:
935
- acc.query.push(`${itm.query} ${(itm === null || itm === void 0 ? void 0 : itm.operator) ? itm.operator : '='} $${acc.values.length + 1}`);
936
- break;
937
- }
938
- acc.query.push(`${itm.query} ${(itm === null || itm === void 0 ? void 0 : itm.operator) ? itm.operator : '='} $${acc.values.length + 1}`);
939
- }, {
940
- query: [],
941
- values: []
942
- });
943
- let sortQuery = sortings
944
- .map(itm => {
945
- return `${itm.name} ${itm.desc ? 'DESC' : 'ASC'}`;
946
- })
947
- .join(`,`);
948
- let updatedInventories = await tx.getRepository(warehouse_base_1.Inventory).query(`
949
- update inventories tgt set locked_qty = coalesce(locked_qty,0) + src.reserve_qty,
950
- locked_uom_value = coalesce(locked_uom_value,0) + src.reserve_uom_value,
951
- updated_at = NOW(),
952
- updater_id = $1
953
- from (
954
- select "id", "pallet_id","carton_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year",
955
- "reserve_qty", (("uom_value"/"qty") * "reserve_qty") as "reserve_uom_value" from (
956
- select "sort_seq", "id", "pallet_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year", "carton_id", "uom_value", "locked_uom_value", "qty", "locked_qty", "created_at",
957
- "release_qty", "release_uom_value", lock_amount,
958
- case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end as "reserve_qty"
959
- from (
960
- select *,
961
- qty - locked_qty as available_qty,
962
- sum(qty - locked_qty - release_qty) over (order by sort_seq asc rows between unbounded preceding and current row) as lock_amount
963
- from (
964
- SELECT 0 as sort_seq, null as id, null as pallet_id, null as batch_id, null as batch_id_ref,
965
- null as unit, '${orderInventory.uom}' as uom, '${orderInventory.packingType}' as packing_type, '${orderInventory.packingSize}' as packing_size,
966
- null as manufacture_year, null as carton_id, 0 as uom_value, 0 as locked_uom_value, 0 as qty, 0 as locked_qty, null as created_at,
967
- '${orderInventory.releaseQty}' as release_qty, '${orderInventory.releaseUomValue}' as release_uom_value
968
- UNION
969
- (
970
- SELECT ROW_NUMBER() OVER(PARTITION BY iv.domain_id ORDER BY ${sortQuery}) as sort_seq,
971
- iv.id, iv.pallet_id, iv.batch_id, iv.batch_id_ref,
972
- iv.unit, iv.uom, iv.packing_type, iv.packing_size,
973
- iv.manufacture_year, iv.carton_id, iv.uom_value,
974
- coalesce(iv.locked_uom_value,0) as locked_uom_value, iv.qty, coalesce(iv.locked_qty,0) as locked_qty, iv.created_at,
975
- 0 as release_qty, 0 as release_uom_value
976
- FROM "inventories" "iv"
977
- INNER JOIN "locations" "loc" ON "loc"."id"="iv"."location_id"
978
- INNER JOIN "products" "p" ON "p"."id"="iv"."product_id"
979
- WHERE case when coalesce("iv"."locked_qty",0) < 0 then 0 else ("iv"."qty" - coalesce("iv"."locked_qty",0)) end > 0 AND
980
- "iv"."domain_id" = $2 AND "iv"."bizplace_id" = $3 AND "iv"."packing_type" = $4 AND "iv"."packing_size" = $5 AND "iv"."product_id" = $6 AND "iv"."status" = $7 AND "loc"."type" NOT IN ($8, $9)
981
- AND "iv"."obsolete" = false AND case when "iv"."expiration_date" is not null and "p"."shelf_life" is not null then CURRENT_DATE < "iv"."expiration_date" - "p"."shelf_life" else true end
982
- ${queryStrings.query.length > 0 ? `AND ${queryStrings.join(' AND ')}` : ''}
983
- ORDER BY ${sortQuery}
984
- )
985
- ) dt1
986
- ) dt2 where case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end > 0
987
- ) dt3 where sort_seq > 0
988
- ) src where src.id = tgt.id
989
- returning
990
- tgt."id", tgt."qty", tgt."pallet_id", tgt."carton_id", tgt."batch_id", tgt."batch_id_ref", tgt."unit",
991
- tgt."uom", tgt."packing_type", tgt."packing_size", tgt."manufacture_year",
992
- tgt."locked_qty", tgt."uom_value", tgt."locked_uom_value", src."reserve_qty", src."reserve_uom_value";`, [
993
- (user === null || user === void 0 ? void 0 : user.id) || null,
994
- warehouseDomain.id,
995
- customerBizplace.id,
996
- orderInventory.packingType,
997
- orderInventory.packingSize,
998
- orderInventory.product.id,
999
- warehouse_base_1.INVENTORY_STATUS.STORED,
1000
- warehouse_base_1.LOCATION_TYPE.QUARANTINE,
1001
- warehouse_base_1.LOCATION_TYPE.RESERVE,
1002
- ...queryStrings.values
1003
- ]);
1004
- let totalAssigned = updatedInventories[0].reduce((acc, inv) => {
1005
- return acc + inv.reserve_qty;
1006
- }, 0);
1007
- if (orderInventory.releaseQty != totalAssigned) {
1008
- throw new index_1.ValidationError({
1009
- errorCode: 'INSUFFICIENT_STOCK',
1010
- message: 'insufficient stock',
1011
- detail: JSON.stringify({
1012
- code: 'insufficient stock',
1013
- sku: orderInventory.product.sku,
1014
- packingType: orderInventory.packingType,
1015
- packingSize: orderInventory.packingSize,
1016
- uom: orderInventory.uom,
1017
- qty: orderInventory.releaseQty,
1018
- uom_value: orderInventory.releaseUomValue
1019
- })
1020
- });
1021
- }
1022
- updatedInventories[0].forEach(inv => {
1023
- let oi = Object.assign(Object.assign({}, orderInventory), { inventory: { id: inv.id }, uom: inv.uom, packingType: inv.packing_type, batchId: inv.batch_id, releaseQty: inv.reserve_qty, releaseUomValue: inv.reserve_uom_value, pickedQty: 0, packedQty: 0, type: sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS, status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET, domain: { id: warehouseDomain.id }, bizplace: { id: customerBizplace.id } });
1024
- assignedOrderInventories.push(oi);
1025
- });
1026
- }
1027
- orderProducts[opIdx].orderInventories = assignedOrderInventories;
1028
- }
1029
- return orderProducts;
1030
- }
1031
- async function createReleaseGood(releaseGood, orderProducts, bizplace, domain, context, tx) {
1032
- try {
1033
- if (orderProducts.length <= 0) {
1034
- throw new index_1.ValidationError({
1035
- errorCode: 'ITEM_NOT_FOUND',
1036
- message: 'no order items found',
1037
- detail: JSON.stringify(releaseGood)
1038
- });
1039
- }
1040
- let newReleaseGood = new sales_base_1.ReleaseGood();
1041
- // find RO number rule setting
1042
- const roNoSetting = await tx.getRepository(setting_base_1.Setting).findOne({
1043
- where: {
1044
- domain,
1045
- name: sales_base_1.ORDER_NUMBER_SETTING_KEY.RO_NUMBER_RULE
1046
- }
1047
- });
1048
- newReleaseGood = {
1049
- name: roNoSetting
1050
- ? await (0, id_rule_base_1.generateId)({ domain, type: sales_base_1.ORDER_NUMBER_RULE_TYPE.RO_NUMBER, seed: {} })
1051
- : sales_base_1.OrderNoGenerator.releaseGood(),
1052
- domain: domain,
1053
- bizplace: bizplace,
1054
- collectionOrderNo: releaseGood.collectionOrderNo,
1055
- courierOption: releaseGood.courierOption,
1056
- exportOption: releaseGood.exportOption,
1057
- ownTransport: releaseGood.ownTransport,
1058
- packingOption: releaseGood.packingOption,
1059
- marketplaceOrderStatus: (releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.marketplaceOrderStatus) || null,
1060
- refNo: releaseGood.refNo,
1061
- refNo2: releaseGood.refNo2 || null,
1062
- refNo3: releaseGood.refNo3 || null,
1063
- remark: (releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.remark) || null,
1064
- releaseDate: releaseGood.releaseDate,
1065
- truckNo: releaseGood.truckNo,
1066
- type: (releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.type) ? releaseGood.type : 'b2b',
1067
- status: sales_base_1.ORDER_STATUS.PENDING_WORKSHEET,
1068
- noOfItems: orderProducts.length,
1069
- source: releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.source,
1070
- paidAmount: releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.paidAmount,
1071
- discountAmount: releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.discountAmount,
1072
- taxAmount: releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.taxAmount,
1073
- shippingFee: releaseGood === null || releaseGood === void 0 ? void 0 : releaseGood.shippingFee,
1074
- acceptedAt: new Date()
1075
- };
1076
- let resultReleaseGood = await tx.getRepository(sales_base_1.ReleaseGood).save(newReleaseGood);
1077
- let combinedOrderInventories = [];
1078
- let savedOrderProducts = await Promise.all(orderProducts.map(async (orderProduct) => {
1079
- let orderInventories = orderProduct.orderInventories;
1080
- orderProduct = Object.assign(new sales_base_1.OrderProduct(), Object.assign(Object.assign({}, orderProduct), { name: (0, uuid_1.v4)(), domain: domain, bizplace: bizplace, releaseGood: resultReleaseGood, type: sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS, status: sales_base_1.ORDER_PRODUCT_STATUS.ASSIGNED }));
1081
- let result = await tx.getRepository(sales_base_1.OrderProduct).save(orderProduct);
1082
- for (let oiIdx = 0; oiIdx < orderInventories.length; oiIdx++) {
1083
- let orderInventory = Object.assign(new sales_base_1.OrderInventory(), Object.assign(Object.assign({}, orderInventories[oiIdx]), { name: (0, uuid_1.v4)(), domain: domain, bizplace: bizplace, releaseGood: resultReleaseGood, type: sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS, status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET }));
1084
- await tx.getRepository(sales_base_1.OrderInventory).save(orderInventory);
1085
- combinedOrderInventories.push({
1086
- product: { name: orderInventory.product.name, sku: orderInventory.product.sku },
1087
- batchId: orderInventory.batchId,
1088
- packingType: orderInventory.packingType,
1089
- packingSize: orderInventory.packingSize,
1090
- releaseQty: orderInventory.releaseQty,
1091
- releaseUomValue: orderInventory.releaseUomValue
1092
- });
1093
- }
1094
- return result;
1095
- }));
1096
- newReleaseGood.orderProducts = savedOrderProducts;
1097
- newReleaseGood.orderInventories = combinedOrderInventories;
1098
- return newReleaseGood;
1099
- }
1100
- catch (error) {
1101
- throw error;
1102
- }
1103
- }
1104
- //# sourceMappingURL=xilnex-router.js.map