@things-factory/worksheet-base 4.3.701 → 4.3.708
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.
- package/dist-server/controllers/inbound/putaway-worksheet-controller.js +14 -2
- package/dist-server/controllers/inbound/putaway-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/inbound/unloading-worksheet-controller.js +10 -2
- package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/outbound/picking-worksheet-controller.js +14 -5
- package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/render-fm-grn.js +132 -58
- package/dist-server/controllers/render-fm-grn.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js +27 -2
- package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js.map +1 -1
- package/dist-server/utils/inventory-util.js +15 -3
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +21 -21
- package/server/controllers/inbound/putaway-worksheet-controller.ts +17 -2
- package/server/controllers/inbound/unloading-worksheet-controller.ts +10 -2
- package/server/controllers/outbound/picking-worksheet-controller.ts +14 -2
- package/server/controllers/render-fm-grn.ts +149 -74
- package/server/graphql/resolvers/worksheet/inventories-by-pallet.ts +48 -22
- package/server/utils/inventory-util.ts +16 -3
|
@@ -239,6 +239,7 @@ export class PickingWorksheetController extends VasWorksheetController {
|
|
|
239
239
|
'releaseGood',
|
|
240
240
|
'releaseGood.bizplace',
|
|
241
241
|
'releaseGood.domain',
|
|
242
|
+
'releaseGood.deliverTo',
|
|
242
243
|
'releaseGood.lastMileDelivery',
|
|
243
244
|
'releaseGood.bizplace.domain',
|
|
244
245
|
'domain',
|
|
@@ -517,6 +518,7 @@ export class PickingWorksheetController extends VasWorksheetController {
|
|
|
517
518
|
'worksheetDetails.targetProduct.product',
|
|
518
519
|
'worksheetDetails.targetProduct.productDetail',
|
|
519
520
|
'worksheetDetails.targetProduct.releaseGood',
|
|
521
|
+
'worksheetDetails.targetProduct.releaseGood.deliverTo',
|
|
520
522
|
'worksheetDetails.targetInventory',
|
|
521
523
|
'worksheetDetails.targetInventory.releaseGood',
|
|
522
524
|
'worksheetDetails.targetInventory.releaseGood.domain',
|
|
@@ -2423,6 +2425,11 @@ export class PickingWorksheetController extends VasWorksheetController {
|
|
|
2423
2425
|
}
|
|
2424
2426
|
}
|
|
2425
2427
|
|
|
2428
|
+
// if deliverTo contact point exists and has releaseShelfLife, use it as override for outbound shelf life
|
|
2429
|
+
const releaseShelfLife = (releaseGood?.deliverTo as any)?.releaseShelfLife
|
|
2430
|
+
const outboundShelfLifeOverride =
|
|
2431
|
+
releaseGood?.deliverTo && releaseShelfLife != null && releaseShelfLife !== 0 ? Number(releaseShelfLife) : null
|
|
2432
|
+
|
|
2426
2433
|
let assignedOrderInventories: OrderInventory[] = await InventoryUtil.autoAssignInventoryForRelease(
|
|
2427
2434
|
op,
|
|
2428
2435
|
op.productDetail.product,
|
|
@@ -2436,7 +2443,8 @@ export class PickingWorksheetController extends VasWorksheetController {
|
|
|
2436
2443
|
undefined,
|
|
2437
2444
|
undefined,
|
|
2438
2445
|
undefined,
|
|
2439
|
-
(op as any)?.warehouseCode
|
|
2446
|
+
(op as any)?.warehouseCode,
|
|
2447
|
+
outboundShelfLifeOverride
|
|
2440
2448
|
)
|
|
2441
2449
|
|
|
2442
2450
|
assignedOrderInventories = assignedOrderInventories.map(aoi => {
|
|
@@ -2522,7 +2530,11 @@ export class PickingWorksheetController extends VasWorksheetController {
|
|
|
2522
2530
|
locationSortingRules: inventoryAssignmentSetting ? JSON.parse(inventoryAssignmentSetting.value) : false,
|
|
2523
2531
|
pickingStrategy: orderProducts[i].product.pickingStrategy,
|
|
2524
2532
|
warehouseName:
|
|
2525
|
-
(orderProducts[i] as any)?.warehouseCode || (orderProducts[i] as any)?.warehouse?.name || undefined
|
|
2533
|
+
(orderProducts[i] as any)?.warehouseCode || (orderProducts[i] as any)?.warehouse?.name || undefined,
|
|
2534
|
+
releaseShelfLifeOverride: (() => {
|
|
2535
|
+
const releaseShelfLife = (orderProducts[i]?.releaseGood as any)?.deliverTo?.releaseShelfLife
|
|
2536
|
+
return releaseShelfLife != null && releaseShelfLife !== 0 ? Number(releaseShelfLife) : null
|
|
2537
|
+
})()
|
|
2526
2538
|
},
|
|
2527
2539
|
this.domain,
|
|
2528
2540
|
this.trxMgr
|
|
@@ -26,15 +26,34 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
26
26
|
// 2. find grn
|
|
27
27
|
const foundGRN: GoodsReceivalNote = await getRepository(GoodsReceivalNote).findOne({
|
|
28
28
|
where: { domain, name: grnNo },
|
|
29
|
-
relations: [
|
|
29
|
+
relations: [
|
|
30
|
+
'domain',
|
|
31
|
+
'bizplace',
|
|
32
|
+
'bizplace.domain',
|
|
33
|
+
'bizplace.company',
|
|
34
|
+
'arrivalNotice',
|
|
35
|
+
'arrivalNotice.creator',
|
|
36
|
+
'updater'
|
|
37
|
+
]
|
|
30
38
|
})
|
|
31
39
|
|
|
40
|
+
if (!foundGRN) {
|
|
41
|
+
throw new Error(`GRN not found for no: ${grnNo}`)
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
// 3. find GAN
|
|
33
45
|
const foundGAN: ArrivalNotice = foundGRN.arrivalNotice
|
|
34
46
|
const ownRefNo = foundGAN.refNo
|
|
35
47
|
|
|
36
48
|
const foundInventoryItem: InventoryItem[] = await getRepository(InventoryItem).query(
|
|
37
|
-
`select row_number() over (partition by p.sku) as "seq",
|
|
49
|
+
`select row_number() over (partition by p.sku) as "seq",
|
|
50
|
+
p.sku,
|
|
51
|
+
p.brand_sku,
|
|
52
|
+
ii.serial_number
|
|
53
|
+
from inventory_items ii
|
|
54
|
+
left join products p on ii.product_id = p.id
|
|
55
|
+
where inbound_order_id = '${foundGAN.id}'
|
|
56
|
+
group by p.sku, ii.serial_number, p.brand_sku`
|
|
38
57
|
)
|
|
39
58
|
|
|
40
59
|
// 4. find customer bizplace
|
|
@@ -51,27 +70,29 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
51
70
|
relations: ['company']
|
|
52
71
|
})
|
|
53
72
|
|
|
54
|
-
|
|
73
|
+
// ReducedInventoryHistory -> ONE ROW PER PALLET
|
|
74
|
+
const inboundInventories: any[] = await getRepository(ReducedInventoryHistory)
|
|
55
75
|
.createQueryBuilder('ivh')
|
|
56
|
-
.select('product_id', 'productId')
|
|
57
|
-
.addSelect('batch_id', 'batchId')
|
|
58
|
-
.addSelect('reusable_pallet_id', 'reusablePalletId')
|
|
59
|
-
.addSelect('packing_type', 'packingType')
|
|
60
|
-
.addSelect('
|
|
61
|
-
.addSelect('
|
|
62
|
-
.addSelect('
|
|
63
|
-
.addSelect('
|
|
64
|
-
.addSelect('
|
|
65
|
-
.addSelect(
|
|
76
|
+
.select('ivh.product_id', 'productId')
|
|
77
|
+
.addSelect('ivh.batch_id', 'batchId')
|
|
78
|
+
.addSelect('ivh.reusable_pallet_id', 'reusablePalletId')
|
|
79
|
+
.addSelect('ivh.packing_type', 'packingType')
|
|
80
|
+
.addSelect('ivh.uom', 'uom')
|
|
81
|
+
.addSelect('ivh.pallet_id', 'palletId')
|
|
82
|
+
.addSelect('ivh.expiration_date', 'expiryDate')
|
|
83
|
+
.addSelect('SUM(ivh.qty)', 'qty')
|
|
84
|
+
.addSelect('SUM(ivh.uom_value)', 'uomValue')
|
|
85
|
+
.addSelect('1', 'palletQty') // one pallet per row
|
|
66
86
|
.where('ivh.domain_id = :domainId', { domainId: domain.id })
|
|
67
87
|
.andWhere('ivh.ref_order_id = :refOrderId', { refOrderId: foundGAN.id })
|
|
68
88
|
.andWhere(`ivh.transaction_type = 'UNLOADING'`)
|
|
69
|
-
.groupBy('
|
|
70
|
-
.addGroupBy('
|
|
71
|
-
.addGroupBy('
|
|
72
|
-
.addGroupBy('packing_type')
|
|
73
|
-
.addGroupBy('uom')
|
|
74
|
-
.addGroupBy('
|
|
89
|
+
.groupBy('ivh.product_id')
|
|
90
|
+
.addGroupBy('ivh.batch_id')
|
|
91
|
+
.addGroupBy('ivh.reusable_pallet_id')
|
|
92
|
+
.addGroupBy('ivh.packing_type')
|
|
93
|
+
.addGroupBy('ivh.uom')
|
|
94
|
+
.addGroupBy('ivh.pallet_id')
|
|
95
|
+
.addGroupBy('ivh.expiration_date')
|
|
75
96
|
.getRawMany()
|
|
76
97
|
|
|
77
98
|
// 5. find domain contact point
|
|
@@ -79,7 +100,6 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
79
100
|
where: { domain, bizplace: domainBizplace }
|
|
80
101
|
})
|
|
81
102
|
|
|
82
|
-
// 5. find domain contact point
|
|
83
103
|
const foundPartnerCP: ContactPoint = await getRepository(ContactPoint).findOne({
|
|
84
104
|
where: { domain, bizplace: partnerBiz }
|
|
85
105
|
})
|
|
@@ -98,7 +118,7 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
98
118
|
|
|
99
119
|
const targetProducts: OrderProduct[] = await getRepository(OrderProduct).find({
|
|
100
120
|
where: { domain, arrivalNotice: foundGAN, actualPalletQty: Not(IsNull()), actualPackQty: Not(IsNull()) },
|
|
101
|
-
relations: ['product']
|
|
121
|
+
relations: ['product', 'productDetail']
|
|
102
122
|
})
|
|
103
123
|
|
|
104
124
|
// 7. find grn template based on category
|
|
@@ -129,8 +149,6 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
129
149
|
}
|
|
130
150
|
})
|
|
131
151
|
|
|
132
|
-
const inboundInventories: any[] = await qbReducedInventory
|
|
133
|
-
|
|
134
152
|
const template = await STORAGE.readFile(foundTemplate.path, 'utf-8')
|
|
135
153
|
|
|
136
154
|
let logo = null
|
|
@@ -148,28 +166,122 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
148
166
|
cop = 'data:' + foundSignature.mimetype + ';base64,' + (await STORAGE.readFile(foundCop.path, 'base64'))
|
|
149
167
|
}
|
|
150
168
|
|
|
169
|
+
// serial number aggregation
|
|
151
170
|
const filterInventoryItem = _.groupBy(foundInventoryItem, i => i.sku)
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
const tempTotalQuantity = []
|
|
171
|
+
const tempIndexArr: number[] = []
|
|
172
|
+
const tempTotalQuantity: number[] = []
|
|
156
173
|
|
|
157
174
|
Object.keys(filterInventoryItem).forEach(k => {
|
|
158
175
|
const tempIndex = foundInventoryItem.findIndex(i => {
|
|
159
176
|
return i.sku == k
|
|
160
177
|
})
|
|
161
|
-
|
|
162
178
|
tempIndexArr.push(tempIndex)
|
|
163
179
|
})
|
|
164
180
|
|
|
165
181
|
Object.values(filterInventoryItem).forEach(k => {
|
|
166
|
-
const tempQuantity = k.length
|
|
167
|
-
|
|
182
|
+
const tempQuantity = (k as any[]).length
|
|
168
183
|
tempTotalQuantity.push(tempQuantity)
|
|
169
184
|
})
|
|
170
185
|
|
|
171
186
|
tempIndexArr.forEach((t, index) => {
|
|
172
|
-
if (t >= 0) foundInventoryItem[t].totalQuantity = tempTotalQuantity[index]
|
|
187
|
+
if (t >= 0) (foundInventoryItem[t] as any).totalQuantity = tempTotalQuantity[index]
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
// =========================
|
|
191
|
+
// Build pallet_list (per pallet)
|
|
192
|
+
// =========================
|
|
193
|
+
|
|
194
|
+
const pallet_list = inboundInventories.map((inv, idx) => {
|
|
195
|
+
const item = targetProducts.find(
|
|
196
|
+
tp =>
|
|
197
|
+
tp.product.id === inv.productId &&
|
|
198
|
+
tp.batchId === inv.batchId &&
|
|
199
|
+
tp.packingType === inv.packingType &&
|
|
200
|
+
tp.uom === inv.uom &&
|
|
201
|
+
tp.palletId === inv.palletId
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
const qty = Number(inv.qty) || (item ? item.actualPackQty : 0)
|
|
205
|
+
const uomValue = Number(inv.uomValue) || (item ? item.uomValue * qty : 0)
|
|
206
|
+
const volume = item && item.productDetail.volume ? item.productDetail.volume * qty : 0
|
|
207
|
+
const expiryDate = inv.expiryDate ? new Date(inv.expiryDate).toISOString().split('T')[0] : ''
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
list_no: idx + 1,
|
|
211
|
+
_uomValue: uomValue, // internal for grouping later
|
|
212
|
+
product_sku: item ? `${item.product.sku}` : '',
|
|
213
|
+
product_brand_sku: item ? `${item.product.brandSku}` : '',
|
|
214
|
+
product_name: item ? `${item.product.name}(${item.product.description})` : '',
|
|
215
|
+
product_desc: item ? item.product.description : '',
|
|
216
|
+
product_nameOnly: item ? item.product.name : '',
|
|
217
|
+
product_type: inv.packingType,
|
|
218
|
+
product_size: item ? item.packingSize : null,
|
|
219
|
+
product_batch: inv.batchId,
|
|
220
|
+
product_volume: volume,
|
|
221
|
+
batch_id_ref: item?.batchIdRef || '',
|
|
222
|
+
pallet_id: inv.palletId,
|
|
223
|
+
pallet_qty: Number(inv.palletQty) || (item?.actualPalletQty ?? 1),
|
|
224
|
+
pack_qty: qty,
|
|
225
|
+
product_qty: qty,
|
|
226
|
+
discrepancy_qty: item ? item.packQty - item.actualPackQty : 0,
|
|
227
|
+
product_unit_uom_value: item ? `${Math.round(item.uomValue * 100) / 100}` : '',
|
|
228
|
+
product_total_uom_value: `${Math.round(uomValue * 100) / 100}`,
|
|
229
|
+
product_uom: inv.uom,
|
|
230
|
+
product_gross_weight: item ? item.product.grossWeight : null,
|
|
231
|
+
unit_price: item ? item.unitPrice : null,
|
|
232
|
+
expiry_date: expiryDate,
|
|
233
|
+
manufacture_date: item ? item.manufactureDate : null,
|
|
234
|
+
reusable_pallet_id: inv.reusablePalletId || '',
|
|
235
|
+
remark: item ? (item.remark ? item.remark : '') + (item.issue ? ' [Issue]: ' + item.issue : '') : ''
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
// =========================
|
|
240
|
+
// Build product_list (grouped view)
|
|
241
|
+
// =========================
|
|
242
|
+
|
|
243
|
+
const groupedByProduct = _.groupBy(pallet_list, pl =>
|
|
244
|
+
[
|
|
245
|
+
pl.product_sku,
|
|
246
|
+
pl.product_batch,
|
|
247
|
+
pl.product_type,
|
|
248
|
+
pl.product_uom,
|
|
249
|
+
pl.expiry_date // keep expiries separate; remove from key if you want to merge
|
|
250
|
+
].join('|')
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
const product_list = Object.values(groupedByProduct).map((rows: any[], idx) => {
|
|
254
|
+
const first = rows[0]
|
|
255
|
+
const totalQty = rows.reduce((sum, r) => sum + (r.product_qty || 0), 0)
|
|
256
|
+
const totalPalletQty = rows.reduce((sum, r) => sum + (r.pallet_qty || 0), 0)
|
|
257
|
+
const totalUomValue = rows.reduce((sum, r) => sum + (r._uomValue || 0), 0)
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
list_no: idx + 1,
|
|
261
|
+
product_sku: first.product_sku,
|
|
262
|
+
product_brand_sku: first.product_brand_sku,
|
|
263
|
+
product_name: first.product_name,
|
|
264
|
+
product_desc: first.product_desc,
|
|
265
|
+
product_nameOnly: first.product_nameOnly,
|
|
266
|
+
product_type: first.product_type,
|
|
267
|
+
product_size: first.product_size,
|
|
268
|
+
product_batch: first.product_batch,
|
|
269
|
+
product_volume: first.product_volume,
|
|
270
|
+
batch_id_ref: first.batch_id_ref,
|
|
271
|
+
pallet_qty: totalPalletQty,
|
|
272
|
+
pack_qty: totalQty,
|
|
273
|
+
product_qty: totalQty,
|
|
274
|
+
discrepancy_qty: first.discrepancy_qty, // per-product discrepancy if needed
|
|
275
|
+
product_unit_uom_value: first.product_unit_uom_value,
|
|
276
|
+
product_total_uom_value: `${Math.round(totalUomValue * 100) / 100}`,
|
|
277
|
+
product_uom: first.product_uom,
|
|
278
|
+
product_gross_weight: first.product_gross_weight,
|
|
279
|
+
unit_price: first.unit_price,
|
|
280
|
+
expiry_date: first.expiry_date,
|
|
281
|
+
manufacture_date: first.manufacture_date,
|
|
282
|
+
reusable_pallet_id: first.reusable_pallet_id,
|
|
283
|
+
remark: first.remark
|
|
284
|
+
}
|
|
173
285
|
})
|
|
174
286
|
|
|
175
287
|
const data = {
|
|
@@ -192,7 +304,11 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
192
304
|
warehouse_fax: foundCP.fax,
|
|
193
305
|
warehouse_email: foundCP.email,
|
|
194
306
|
order_no: foundGRN.name,
|
|
307
|
+
grn_received_by: foundGRN.updater.name,
|
|
308
|
+
grn_received_date: foundGRN.createdAt ? DateTimeConverter.date(foundGRN.createdAt) : '',
|
|
195
309
|
gan_no: foundGAN.name,
|
|
310
|
+
gan_created_by: foundGAN.creator.name,
|
|
311
|
+
gan_created_date: foundGAN.createdAt ? DateTimeConverter.date(foundGAN.createdAt) : '',
|
|
196
312
|
gan_accepted_at: foundGAN.acceptedAt ? DateTimeConverter.datetime(foundGAN.acceptedAt, timezoneOffSet) : '',
|
|
197
313
|
unload_date: DateTimeConverter.date(foundWS.endedAt),
|
|
198
314
|
ref_no: ownRefNo ? `${foundGAN.name} / ${foundGAN.refNo}` : `${foundGAN.name}`,
|
|
@@ -207,49 +323,8 @@ export async function renderFmGRN({ grnNo, timezoneOffSet }, context: any) {
|
|
|
207
323
|
account_no: foundPartnerCP ? foundPartnerCP.accountNo : '',
|
|
208
324
|
unloaded_by: foundWS ? foundWS.updater.name : '',
|
|
209
325
|
putaway_by: foundPutawayWS ? foundPutawayWS.updater.name : '',
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
acc.push(
|
|
213
|
-
...inboundInventories
|
|
214
|
-
.filter(
|
|
215
|
-
ih =>
|
|
216
|
-
ih.productId == item.product.id &&
|
|
217
|
-
ih.batchId == item.batchId &&
|
|
218
|
-
ih.packingType == item.packingType &&
|
|
219
|
-
ih.uom == item.uom
|
|
220
|
-
)
|
|
221
|
-
.map(unloadInvHistory => {
|
|
222
|
-
return {
|
|
223
|
-
product_sku: `${item.product.sku}`,
|
|
224
|
-
product_brand_sku: `${item.product.brandSku}`,
|
|
225
|
-
product_name: `${item.product.name}(${item.product.description})`,
|
|
226
|
-
product_desc: item.product.description,
|
|
227
|
-
product_nameOnly: item.product.name,
|
|
228
|
-
product_type: item.packingType,
|
|
229
|
-
product_size: item.packingSize,
|
|
230
|
-
product_batch: item.batchId,
|
|
231
|
-
batch_id_ref: item?.batchIdRef ? item.batchIdRef : '',
|
|
232
|
-
pallet_qty: item.actualPalletQty,
|
|
233
|
-
product_qty: unloadInvHistory.qty || item.actualPackQty,
|
|
234
|
-
product_pack_qty: item.packQty,
|
|
235
|
-
descrepancy_qty: (unloadInvHistory.qty || item.actualPackQty) - item.packQty,
|
|
236
|
-
product_unit_uom_value: `${Math.round(item.uomValue * 100) / 100}`,
|
|
237
|
-
product_total_uom_value: `${
|
|
238
|
-
Math.round((unloadInvHistory.uomValue || item.uomValue * item.actualPackQty) * 100) / 100
|
|
239
|
-
}`,
|
|
240
|
-
product_uom: `${unloadInvHistory.uom || item.uom}`,
|
|
241
|
-
product_gross_weight: item.product.grossWeight || null,
|
|
242
|
-
unit_price: item.unitPrice || null,
|
|
243
|
-
expiry_date: unloadInvHistory.expiryDate && unloadInvHistory.expiryDate != '' ? new Date(unloadInvHistory.expiryDate).toISOString().split('T')[0] : '',
|
|
244
|
-
manufacture_date: item.manufactureDate,
|
|
245
|
-
reusable_pallet_id: unloadInvHistory.reusablePalletId || '',
|
|
246
|
-
remark: (item.remark ? item.remark : '') + (item.issue ? ' [Issue]: ' + item.issue : '')
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
)
|
|
250
|
-
return acc
|
|
251
|
-
}, [])
|
|
252
|
-
.map((item, idx) => ({ list_no: idx + 1, ...item })),
|
|
326
|
+
pallet_list,
|
|
327
|
+
product_list,
|
|
253
328
|
serialNumber: foundInventoryItem
|
|
254
329
|
}
|
|
255
330
|
|
|
@@ -10,23 +10,29 @@ export const inventoriesByPalletResolver = {
|
|
|
10
10
|
const { domain, user }: { domain: Domain; user: User } = context.state
|
|
11
11
|
const params = { filters, pagination }
|
|
12
12
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
const bizplaceId = params.filters.find(x => x.name == 'bizplace_id')
|
|
14
|
+
const releaseShelfLifeOverrideFilter = params.filters.find(x => x.name == 'releaseShelfLifeOverride')
|
|
15
|
+
const releaseShelfLifeOverride =
|
|
16
|
+
releaseShelfLifeOverrideFilter && releaseShelfLifeOverrideFilter.value != null
|
|
17
|
+
? Number(releaseShelfLifeOverrideFilter.value)
|
|
18
|
+
: null
|
|
19
|
+
params.filters = params.filters.filter(x => x.name != 'releaseShelfLifeOverride')
|
|
20
|
+
const productFilters = params.filters.filter(x => x.name == 'productName')
|
|
21
|
+
const inventoriesFilters = params.filters.find(x => x.name == 'invFilter')
|
|
22
|
+
const recallFilters = params.filters.find(x => x.name === 'recall')
|
|
23
|
+
const skipLockCheckFilters = params.filters.find(x => x.name === 'skipLockCheck')
|
|
24
|
+
let skipLockCheck: Boolean =
|
|
25
|
+
skipLockCheckFilters && skipLockCheckFilters?.value ? skipLockCheckFilters?.value : false
|
|
26
|
+
const productFilterColumns = ['sku', 'brandSku', 'name', 'description', 'brand', 'subBrand']
|
|
27
|
+
params.filters = params.filters.filter(x => x.name != 'productName' && x.name != 'invFilter')
|
|
28
|
+
const batchIdFilters = params.filters.find(x => x.name == 'batchId')
|
|
29
|
+
|
|
30
|
+
if (!params.filters.find((filter: any) => filter.name === 'bizplace_id')) {
|
|
31
|
+
throw new Error('No Bizplace found')
|
|
32
|
+
}
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
const locationFilters = params.filters.find(x => x.name == 'locationName')
|
|
35
|
+
params.filters = params.filters.filter(x => x.name != 'locationName')
|
|
30
36
|
|
|
31
37
|
const qb: SelectQueryBuilder<Inventory> = getRepository(Inventory).createQueryBuilder('iv')
|
|
32
38
|
buildQuery(qb, params, context)
|
|
@@ -43,7 +49,7 @@ export const inventoriesByPalletResolver = {
|
|
|
43
49
|
.andWhere('iv.qty > 0')
|
|
44
50
|
.andWhere('iv.transfer_qty <= 0')
|
|
45
51
|
.andWhere('iv.transfer_uom_value <= 0')
|
|
46
|
-
|
|
52
|
+
.andWhere('iv.lock_inventory is not true')
|
|
47
53
|
.andWhere(
|
|
48
54
|
`location.type ${recallFilters?.value === true ? '' : 'NOT'} IN ('${LOCATION_TYPE.QUARANTINE}', '${
|
|
49
55
|
LOCATION_TYPE.RESERVE
|
|
@@ -72,10 +78,8 @@ export const inventoriesByPalletResolver = {
|
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
if (inventoriesFilters?.value?.length > 0) {
|
|
75
|
-
|
|
76
81
|
qb.andWhere('iv.id NOT IN (:...inventoriesIds)', {
|
|
77
82
|
inventoriesIds: inventoriesFilters.value
|
|
78
|
-
|
|
79
83
|
})
|
|
80
84
|
}
|
|
81
85
|
|
|
@@ -132,12 +136,34 @@ export const inventoriesByPalletResolver = {
|
|
|
132
136
|
qb.andWhere(`iv.batch_id ilike '${batchIdFilters.value}'`)
|
|
133
137
|
}
|
|
134
138
|
qb.andWhere(
|
|
135
|
-
|
|
139
|
+
`iv.obsolete = true AND iv.expiration_date IS NOT NULL AND (
|
|
140
|
+
CASE
|
|
141
|
+
WHEN :releaseOverride::integer IS NOT NULL AND :releaseOverride::integer > 0 THEN
|
|
142
|
+
CURRENT_DATE >= iv.expiration_date - :releaseOverride::integer
|
|
143
|
+
WHEN product.min_outbound_shelf_life IS NOT NULL AND product.min_outbound_shelf_life > 0 THEN
|
|
144
|
+
CURRENT_DATE >= iv.expiration_date - product.min_outbound_shelf_life
|
|
145
|
+
ELSE
|
|
146
|
+
FALSE
|
|
147
|
+
END
|
|
148
|
+
)`,
|
|
149
|
+
{ releaseOverride: releaseShelfLifeOverride ?? null }
|
|
136
150
|
)
|
|
137
151
|
} else {
|
|
138
152
|
qb.andWhere('iv.obsolete = false')
|
|
139
153
|
qb.andWhere(
|
|
140
|
-
|
|
154
|
+
`(
|
|
155
|
+
iv.expiration_date IS NULL
|
|
156
|
+
OR
|
|
157
|
+
CASE
|
|
158
|
+
WHEN :releaseOverride::integer IS NOT NULL AND :releaseOverride::integer > 0 THEN
|
|
159
|
+
CURRENT_DATE < iv.expiration_date - :releaseOverride::integer
|
|
160
|
+
WHEN product.min_outbound_shelf_life IS NOT NULL AND product.min_outbound_shelf_life > 0 THEN
|
|
161
|
+
CURRENT_DATE < iv.expiration_date - product.min_outbound_shelf_life
|
|
162
|
+
ELSE
|
|
163
|
+
TRUE
|
|
164
|
+
END
|
|
165
|
+
)`,
|
|
166
|
+
{ releaseOverride: releaseShelfLifeOverride ?? null }
|
|
141
167
|
)
|
|
142
168
|
}
|
|
143
169
|
|
|
@@ -181,7 +207,7 @@ export const inventoriesByPalletResolver = {
|
|
|
181
207
|
productBrand: item.product.brand,
|
|
182
208
|
productId: item.product.id,
|
|
183
209
|
productDetailId: item.productDetail.id,
|
|
184
|
-
isInventoryDecimal: item.product.isInventoryDecimal
|
|
210
|
+
isInventoryDecimal: item.product.isInventoryDecimal
|
|
185
211
|
}
|
|
186
212
|
})
|
|
187
213
|
)
|
|
@@ -121,7 +121,8 @@ export async function inventoriesByStrategy(
|
|
|
121
121
|
uom,
|
|
122
122
|
pickingStrategy,
|
|
123
123
|
locationSortingRules,
|
|
124
|
-
warehouseName
|
|
124
|
+
warehouseName,
|
|
125
|
+
releaseShelfLifeOverride
|
|
125
126
|
},
|
|
126
127
|
domain: Domain,
|
|
127
128
|
trxMgr: EntityManager
|
|
@@ -158,14 +159,26 @@ export async function inventoriesByStrategy(
|
|
|
158
159
|
})
|
|
159
160
|
.andWhere('"INV"."obsolete" = false')
|
|
160
161
|
.andWhere(
|
|
161
|
-
|
|
162
|
+
`(
|
|
163
|
+
"INV"."expiration_date" IS NULL
|
|
164
|
+
OR
|
|
165
|
+
CASE
|
|
166
|
+
WHEN :releaseShelfLifeOverride::integer IS NOT NULL AND :releaseShelfLifeOverride::integer > 0 THEN
|
|
167
|
+
CURRENT_DATE < ("INV"."expiration_date" - :releaseShelfLifeOverride::integer)
|
|
168
|
+
WHEN "PROD"."min_outbound_shelf_life" IS NOT NULL AND "PROD"."min_outbound_shelf_life" > 0 THEN
|
|
169
|
+
CURRENT_DATE < ("INV"."expiration_date" - "PROD"."min_outbound_shelf_life")
|
|
170
|
+
ELSE
|
|
171
|
+
TRUE
|
|
172
|
+
END
|
|
173
|
+
)`
|
|
162
174
|
)
|
|
163
175
|
.setParameters({
|
|
164
176
|
domainId: domain.id,
|
|
165
177
|
productId,
|
|
166
178
|
packingType,
|
|
167
179
|
packingSize,
|
|
168
|
-
uom
|
|
180
|
+
uom,
|
|
181
|
+
releaseShelfLifeOverride: releaseShelfLifeOverride ?? null
|
|
169
182
|
})
|
|
170
183
|
|
|
171
184
|
if (batchId !== '') {
|