@things-factory/worksheet-base 4.3.753 → 4.3.756
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/outbound/picking-worksheet-controller.js +97 -27
- package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/outbound/sorting-worksheet-controller.js +117 -24
- package/dist-server/controllers/outbound/sorting-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/render-ro-do.js +324 -96
- package/dist-server/controllers/render-ro-do.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.js +244 -123
- package/dist-server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/index.js +1 -1
- package/dist-server/graphql/resolvers/worksheet/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/loading/index.js +3 -1
- package/dist-server/graphql/resolvers/worksheet/loading/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/loading/validate-qc-seals.js +79 -0
- package/dist-server/graphql/resolvers/worksheet/loading/validate-qc-seals.js.map +1 -0
- package/dist-server/graphql/types/worksheet/index.js +5 -1
- package/dist-server/graphql/types/worksheet/index.js.map +1 -1
- package/dist-server/graphql/types/worksheet/validate-qc-seals-result.js +12 -0
- package/dist-server/graphql/types/worksheet/validate-qc-seals-result.js.map +1 -0
- package/dist-server/graphql/types/worksheet/worksheet-info.js +1 -0
- package/dist-server/graphql/types/worksheet/worksheet-info.js.map +1 -1
- package/package.json +21 -21
- package/server/controllers/outbound/picking-worksheet-controller.ts +105 -31
- package/server/controllers/outbound/sorting-worksheet-controller.ts +137 -25
- package/server/controllers/render-ro-do.ts +378 -136
- package/server/graphql/resolvers/worksheet/find-sorting-release-orders-by-task-no.ts +305 -128
- package/server/graphql/resolvers/worksheet/index.ts +3 -2
- package/server/graphql/resolvers/worksheet/loading/index.ts +5 -0
- package/server/graphql/resolvers/worksheet/loading/validate-qc-seals.ts +91 -0
- package/server/graphql/types/worksheet/index.ts +5 -1
- package/server/graphql/types/worksheet/validate-qc-seals-result.ts +9 -0
- package/server/graphql/types/worksheet/worksheet-info.ts +1 -0
|
@@ -1,46 +1,27 @@
|
|
|
1
1
|
import FormData from 'form-data'
|
|
2
2
|
import fetch from 'node-fetch'
|
|
3
|
-
import {
|
|
4
|
-
EntityManager,
|
|
5
|
-
getManager,
|
|
6
|
-
getRepository
|
|
7
|
-
} from 'typeorm'
|
|
3
|
+
import { EntityManager, getManager, getRepository, In } from 'typeorm'
|
|
8
4
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from '@things-factory/attachment-base'
|
|
13
|
-
import {
|
|
14
|
-
Partner,
|
|
15
|
-
User
|
|
16
|
-
} from '@things-factory/auth-base'
|
|
17
|
-
import {
|
|
18
|
-
Bizplace,
|
|
19
|
-
ContactPoint
|
|
20
|
-
} from '@things-factory/biz-base'
|
|
5
|
+
import { Attachment, STORAGE } from '@things-factory/attachment-base'
|
|
6
|
+
import { Partner, User } from '@things-factory/auth-base'
|
|
7
|
+
import { Bizplace, ContactPoint } from '@things-factory/biz-base'
|
|
21
8
|
import { config } from '@things-factory/env'
|
|
22
9
|
import { ProductDetail } from '@things-factory/product-base'
|
|
23
10
|
import {
|
|
24
11
|
DeliveryOrder,
|
|
25
12
|
ORDER_STATUS,
|
|
26
13
|
OrderInventory,
|
|
27
|
-
|
|
14
|
+
OrderTote,
|
|
15
|
+
OrderToteItem,
|
|
16
|
+
OrderToteSeal,
|
|
17
|
+
ReleaseGood,
|
|
18
|
+
OrderProduct
|
|
28
19
|
} from '@things-factory/sales-base'
|
|
29
20
|
import { Domain } from '@things-factory/shell'
|
|
30
|
-
import {
|
|
31
|
-
Inventory,
|
|
32
|
-
Pallet
|
|
33
|
-
} from '@things-factory/warehouse-base'
|
|
21
|
+
import { Inventory, Pallet } from '@things-factory/warehouse-base'
|
|
34
22
|
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
WORKSHEET_STATUS,
|
|
38
|
-
WORKSHEET_TYPE
|
|
39
|
-
} from '../constants'
|
|
40
|
-
import {
|
|
41
|
-
Worksheet,
|
|
42
|
-
WorksheetDetail
|
|
43
|
-
} from '../entities'
|
|
23
|
+
import { TEMPLATE_TYPE, WORKSHEET_STATUS, WORKSHEET_TYPE } from '../constants'
|
|
24
|
+
import { Worksheet, WorksheetDetail } from '../entities'
|
|
44
25
|
import { DateTimeConverter } from '../utils/datetime-util'
|
|
45
26
|
|
|
46
27
|
const REPORT_API_URL = config.get('reportApiUrl', 'http://localhost:8888/rest/report/show_html')
|
|
@@ -166,6 +147,55 @@ export async function renderRODO({ doNo }, context: any) {
|
|
|
166
147
|
|
|
167
148
|
const foundWSD: WorksheetDetail[] = await wdQb.getMany()
|
|
168
149
|
|
|
150
|
+
// Find order tote items linked to the order inventories in this DO
|
|
151
|
+
const foundOrderToteItems: OrderToteItem[] =
|
|
152
|
+
orderInvIds.length > 0
|
|
153
|
+
? await getRepository(OrderToteItem).find({
|
|
154
|
+
where: {
|
|
155
|
+
domain,
|
|
156
|
+
orderInventory: In(orderInvIds)
|
|
157
|
+
},
|
|
158
|
+
relations: [
|
|
159
|
+
'orderTote',
|
|
160
|
+
'orderTote.tote',
|
|
161
|
+
'orderTote.orderToteSeals',
|
|
162
|
+
'orderInventory',
|
|
163
|
+
'orderInventory.product'
|
|
164
|
+
]
|
|
165
|
+
})
|
|
166
|
+
: []
|
|
167
|
+
|
|
168
|
+
// Create a map of orderInventoryId -> OrderToteItem[] for quick lookup (multiple items can be in same tote)
|
|
169
|
+
const toteItemMap = new Map<string, OrderToteItem[]>()
|
|
170
|
+
foundOrderToteItems.forEach(item => {
|
|
171
|
+
if (item.orderInventory?.id) {
|
|
172
|
+
const existing = toteItemMap.get(item.orderInventory.id) || []
|
|
173
|
+
existing.push(item)
|
|
174
|
+
toteItemMap.set(item.orderInventory.id, existing)
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// Extract unique order totes from order tote items (eliminates separate query)
|
|
179
|
+
const uniqueOrderTotes: OrderTote[] = [
|
|
180
|
+
...new Map(
|
|
181
|
+
foundOrderToteItems
|
|
182
|
+
.filter(item => item.orderTote?.id)
|
|
183
|
+
.map(item => [item.orderTote.id, item.orderTote])
|
|
184
|
+
).values()
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
// Create a map of tote name -> count for total tote qty calculation
|
|
188
|
+
const toteCountMap = new Map<string, number>()
|
|
189
|
+
uniqueOrderTotes.forEach(tote => {
|
|
190
|
+
const toteName = tote.tote?.name || tote.name
|
|
191
|
+
if (toteName) {
|
|
192
|
+
toteCountMap.set(toteName, (toteCountMap.get(toteName) || 0) + 1)
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// Calculate total tote qty
|
|
197
|
+
const totalToteQty = uniqueOrderTotes.length
|
|
198
|
+
|
|
169
199
|
const foundTemplate: Attachment = await getRepository(Attachment).findOne({
|
|
170
200
|
where: { domain, category: TEMPLATE_TYPE.DO_TEMPLATE }
|
|
171
201
|
})
|
|
@@ -196,8 +226,15 @@ export async function renderRODO({ doNo }, context: any) {
|
|
|
196
226
|
}
|
|
197
227
|
|
|
198
228
|
let productList: any[] = []
|
|
199
|
-
|
|
200
|
-
|
|
229
|
+
|
|
230
|
+
// Check if there are totes - if yes, group by tote; if no, use original logic
|
|
231
|
+
const hasTotes = uniqueOrderTotes.length > 0 && foundOrderToteItems.length > 0
|
|
232
|
+
|
|
233
|
+
if (hasTotes) {
|
|
234
|
+
// Group products by tote
|
|
235
|
+
const toteProductMap = new Map<string, any[]>()
|
|
236
|
+
|
|
237
|
+
foundWSD.forEach((wsd: WorksheetDetail) => {
|
|
201
238
|
const targetInventory: OrderInventory = wsd.targetInventory
|
|
202
239
|
const inventory: Inventory = targetInventory.inventory
|
|
203
240
|
const productDetails: ProductDetail[] = inventory.product.productDetails
|
|
@@ -205,110 +242,281 @@ export async function renderRODO({ doNo }, context: any) {
|
|
|
205
242
|
const matchedProductDetail: ProductDetail = productDetails.find(
|
|
206
243
|
productDetail => productDetail.packingType === inventory.packingType
|
|
207
244
|
)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
245
|
+
|
|
246
|
+
// Get tote information for this order inventory
|
|
247
|
+
const toteItems = toteItemMap.get(targetInventory.id) || []
|
|
248
|
+
|
|
249
|
+
if (toteItems.length > 0) {
|
|
250
|
+
// Group by tote name
|
|
251
|
+
toteItems.forEach(toteItem => {
|
|
252
|
+
const toteName = toteItem.orderTote?.tote?.name || toteItem.orderTote?.name || ''
|
|
253
|
+
|
|
254
|
+
if (!toteProductMap.has(toteName)) {
|
|
255
|
+
toteProductMap.set(toteName, [])
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const productSku =
|
|
259
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
260
|
+
? inventory.product.sku
|
|
261
|
+
: wsd.targetInventory.product.sku
|
|
262
|
+
const productName =
|
|
263
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
264
|
+
? `${inventory.product.name} (${inventory.product.description})`
|
|
265
|
+
: `${wsd.targetInventory.product.name} (${wsd.targetInventory.product.description})`
|
|
266
|
+
|
|
267
|
+
toteProductMap.get(toteName).push({
|
|
268
|
+
tote_name: toteName,
|
|
269
|
+
product_sku: productSku,
|
|
270
|
+
product_name: productName,
|
|
271
|
+
product_qty: toteItem.qty || targetInventory.releaseQty,
|
|
272
|
+
product_type: inventory.packingType,
|
|
273
|
+
targetInventoryId: targetInventory.id,
|
|
274
|
+
wsd: wsd,
|
|
275
|
+
inventory: inventory,
|
|
276
|
+
productDetails: productDetails,
|
|
277
|
+
orderProduct: orderProduct,
|
|
278
|
+
matchedProductDetail: matchedProductDetail
|
|
279
|
+
})
|
|
280
|
+
})
|
|
281
|
+
} else {
|
|
282
|
+
// No tote assigned - add to a special "NO_TOTE" group
|
|
283
|
+
const toteName = 'NO_TOTE'
|
|
284
|
+
if (!toteProductMap.has(toteName)) {
|
|
285
|
+
toteProductMap.set(toteName, [])
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const productSku =
|
|
222
289
|
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
223
|
-
?
|
|
224
|
-
:
|
|
225
|
-
|
|
226
|
-
product_size: matchedProductDetail ? matchedProductDetail.packingSize : inventory.packingSize,
|
|
227
|
-
product_batch: inventory.batchId,
|
|
228
|
-
product_volume: matchedProductDetail ? matchedProductDetail.volume : 0,
|
|
229
|
-
product_batch_ref: inventory.batchIdRef,
|
|
230
|
-
product_qty: targetInventory.releaseQty,
|
|
231
|
-
product_weight: targetInventory.releaseWeight,
|
|
232
|
-
product_gross_weight: inventory.product.grossWeight,
|
|
233
|
-
product_uom_value: targetInventory.releaseUomValue,
|
|
234
|
-
product_uom: inventory.uom,
|
|
235
|
-
product_brand_sku:
|
|
290
|
+
? inventory.product.sku
|
|
291
|
+
: wsd.targetInventory.product.sku
|
|
292
|
+
const productName =
|
|
236
293
|
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
237
|
-
? `${inventory.product
|
|
238
|
-
: `${wsd.targetInventory.product
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
294
|
+
? `${inventory.product.name} (${inventory.product.description})`
|
|
295
|
+
: `${wsd.targetInventory.product.name} (${wsd.targetInventory.product.description})`
|
|
296
|
+
|
|
297
|
+
toteProductMap.get(toteName).push({
|
|
298
|
+
tote_name: '',
|
|
299
|
+
product_sku: productSku,
|
|
300
|
+
product_name: productName,
|
|
301
|
+
product_qty: targetInventory.releaseQty,
|
|
302
|
+
product_type: inventory.packingType,
|
|
303
|
+
targetInventoryId: targetInventory.id,
|
|
304
|
+
wsd: wsd,
|
|
305
|
+
inventory: inventory,
|
|
306
|
+
productDetails: productDetails,
|
|
307
|
+
orderProduct: orderProduct,
|
|
308
|
+
matchedProductDetail: matchedProductDetail
|
|
309
|
+
})
|
|
248
310
|
}
|
|
249
311
|
})
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
product_uom: item.product_uom,
|
|
274
|
-
product_desc: item.product_desc,
|
|
275
|
-
product_nameOnly: item.product_nameOnly,
|
|
276
|
-
product_brand_sku: item.product_brand_sku,
|
|
277
|
-
remark: item.remark,
|
|
278
|
-
inventory_remark: item.inventory_remark,
|
|
279
|
-
expiry_date: item.expiry_date,
|
|
280
|
-
palletQty: 1,
|
|
281
|
-
cross_docking: item.cross_docking,
|
|
282
|
-
pallet: item.pallet,
|
|
283
|
-
avgSellingPrice: item.avgSellingPrice,
|
|
284
|
-
product_volume: item.product_volume,
|
|
312
|
+
|
|
313
|
+
// Process each tote group
|
|
314
|
+
toteProductMap.forEach((products, toteName) => {
|
|
315
|
+
// Group products within each tote by sku, name, type
|
|
316
|
+
const groupedProducts = new Map<string, any>()
|
|
317
|
+
|
|
318
|
+
products.forEach(product => {
|
|
319
|
+
const key = `${product.product_sku}_${product.product_name}_${product.product_type}`
|
|
320
|
+
|
|
321
|
+
if (!groupedProducts.has(key)) {
|
|
322
|
+
groupedProducts.set(key, {
|
|
323
|
+
tote_name: product.tote_name,
|
|
324
|
+
product_sku: product.product_sku,
|
|
325
|
+
product_name: product.product_name,
|
|
326
|
+
product_qty: 0,
|
|
327
|
+
product_type: product.product_type,
|
|
328
|
+
no_of_tote: 0, // Count of items of this product in this tote
|
|
329
|
+
wsd: product.wsd,
|
|
330
|
+
inventory: product.inventory,
|
|
331
|
+
productDetails: product.productDetails,
|
|
332
|
+
orderProduct: product.orderProduct,
|
|
333
|
+
matchedProductDetail: product.matchedProductDetail
|
|
334
|
+
})
|
|
285
335
|
}
|
|
286
336
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
337
|
+
const existing = groupedProducts.get(key)
|
|
338
|
+
existing.product_qty += product.product_qty
|
|
339
|
+
existing.no_of_tote += 1 // Increment count for each occurrence in this tote
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
// Add grouped products to productList
|
|
343
|
+
groupedProducts.forEach(product => {
|
|
344
|
+
const wsd = product.wsd
|
|
345
|
+
const inventory = product.inventory
|
|
346
|
+
const productDetails = product.productDetails
|
|
347
|
+
const orderProduct = product.orderProduct
|
|
348
|
+
const matchedProductDetail = product.matchedProductDetail
|
|
349
|
+
const targetInventory = wsd.targetInventory
|
|
350
|
+
|
|
351
|
+
productList.push({
|
|
352
|
+
tote_name: product.tote_name,
|
|
353
|
+
product_sku: product.product_sku,
|
|
354
|
+
product_name: product.product_name,
|
|
355
|
+
product_qty: product.product_qty,
|
|
356
|
+
product_type: product.product_type,
|
|
357
|
+
no_of_tote: product.no_of_tote,
|
|
358
|
+
product_desc:
|
|
359
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
360
|
+
? `${inventory.product?.description || ''}`
|
|
361
|
+
: `${wsd.targetInventory.product.description || ''}`,
|
|
362
|
+
product_nameOnly:
|
|
363
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
364
|
+
? `${inventory.product.name}`
|
|
365
|
+
: `${wsd.targetInventory.product.name}`,
|
|
366
|
+
product_size: matchedProductDetail ? matchedProductDetail.packingSize : inventory.packingSize,
|
|
367
|
+
product_batch: inventory.batchId,
|
|
368
|
+
product_volume: matchedProductDetail ? matchedProductDetail.volume : 0,
|
|
369
|
+
product_batch_ref: inventory.batchIdRef,
|
|
370
|
+
product_weight: targetInventory.releaseWeight,
|
|
371
|
+
product_gross_weight: inventory.product.grossWeight,
|
|
372
|
+
product_uom_value: targetInventory.releaseUomValue,
|
|
373
|
+
product_uom: inventory.uom,
|
|
374
|
+
product_brand_sku:
|
|
375
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
376
|
+
? `${inventory.product?.brandSku || ''}`
|
|
377
|
+
: `${wsd.targetInventory.product?.brandSku || ''}`,
|
|
378
|
+
remark: targetInventory.remark,
|
|
379
|
+
inventory_remark: inventory.remark,
|
|
380
|
+
cross_docking: targetInventory.crossDocking,
|
|
381
|
+
pallet: inventory?.reusablePallet && inventory?.reusablePallet?.name ? inventory.reusablePallet.name : '',
|
|
382
|
+
avgSellingPrice:
|
|
383
|
+
orderProduct?.sellingPrice > 0 && orderProduct?.releaseQty > 0
|
|
384
|
+
? orderProduct?.sellingPrice / orderProduct?.releaseQty
|
|
385
|
+
: 0,
|
|
386
|
+
expiry_date: inventory?.expirationDate ? inventory?.expirationDate : ''
|
|
309
387
|
})
|
|
388
|
+
})
|
|
389
|
+
})
|
|
390
|
+
} else {
|
|
391
|
+
// Original logic when no totes
|
|
392
|
+
productList = foundWSD
|
|
393
|
+
.map((wsd: WorksheetDetail) => {
|
|
394
|
+
const targetInventory: OrderInventory = wsd.targetInventory
|
|
395
|
+
const inventory: Inventory = targetInventory.inventory
|
|
396
|
+
const productDetails: ProductDetail[] = inventory.product.productDetails
|
|
397
|
+
const orderProduct: OrderProduct = targetInventory.orderProduct
|
|
398
|
+
const matchedProductDetail: ProductDetail = productDetails.find(
|
|
399
|
+
productDetail => productDetail.packingType === inventory.packingType
|
|
400
|
+
)
|
|
401
|
+
return {
|
|
402
|
+
product_name:
|
|
403
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
404
|
+
? `${inventory.product.name} (${inventory.product.description})`
|
|
405
|
+
: `${wsd.targetInventory.product.name} (${wsd.targetInventory.product.description})`,
|
|
406
|
+
product_desc:
|
|
407
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
408
|
+
? `${inventory.product?.description || ''}`
|
|
409
|
+
: `${wsd.targetInventory.product.description || ''}`,
|
|
410
|
+
product_nameOnly:
|
|
411
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
412
|
+
? `${inventory.product.name}`
|
|
413
|
+
: `${wsd.targetInventory.product.name}`,
|
|
414
|
+
product_sku:
|
|
415
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
416
|
+
? `${inventory.product.sku}`
|
|
417
|
+
: `${wsd.targetInventory.product.sku}`,
|
|
418
|
+
product_type: inventory.packingType,
|
|
419
|
+
product_size: matchedProductDetail ? matchedProductDetail.packingSize : inventory.packingSize,
|
|
420
|
+
product_batch: inventory.batchId,
|
|
421
|
+
product_volume: matchedProductDetail ? matchedProductDetail.volume : 0,
|
|
422
|
+
product_batch_ref: inventory.batchIdRef,
|
|
423
|
+
product_qty: targetInventory.releaseQty,
|
|
424
|
+
product_weight: targetInventory.releaseWeight,
|
|
425
|
+
product_gross_weight: inventory.product.grossWeight,
|
|
426
|
+
product_uom_value: targetInventory.releaseUomValue,
|
|
427
|
+
product_uom: inventory.uom,
|
|
428
|
+
product_brand_sku:
|
|
429
|
+
wsd.targetInventory.product.id === wsd.targetInventory.inventory.product.id
|
|
430
|
+
? `${inventory.product?.brandSku || ''}`
|
|
431
|
+
: `${wsd.targetInventory.product?.brandSku || ''}`,
|
|
432
|
+
remark: targetInventory.remark,
|
|
433
|
+
inventory_remark: inventory.remark,
|
|
434
|
+
cross_docking: targetInventory.crossDocking,
|
|
435
|
+
pallet: inventory?.reusablePallet && inventory?.reusablePallet?.name ? inventory.reusablePallet.name : '',
|
|
436
|
+
avgSellingPrice:
|
|
437
|
+
orderProduct?.sellingPrice > 0 && orderProduct?.releaseQty > 0
|
|
438
|
+
? orderProduct?.sellingPrice / orderProduct?.releaseQty
|
|
439
|
+
: 0,
|
|
440
|
+
expiry_date: inventory?.expirationDate ? inventory?.expirationDate : ''
|
|
441
|
+
}
|
|
442
|
+
})
|
|
443
|
+
.reduce((newItem, item) => {
|
|
444
|
+
var foundItem = newItem.find(
|
|
445
|
+
newItem =>
|
|
446
|
+
newItem.product_sku === item.product_sku &&
|
|
447
|
+
newItem.product_name === item.product_name &&
|
|
448
|
+
newItem.product_type === item.product_type &&
|
|
449
|
+
newItem.product_batch === item.product_batch &&
|
|
450
|
+
newItem.product_batch_ref === item.product_batch_ref &&
|
|
451
|
+
newItem.cross_docking === item.cross_docking &&
|
|
452
|
+
newItem.pallet === item.pallet
|
|
453
|
+
)
|
|
454
|
+
if (!foundItem) {
|
|
455
|
+
foundItem = {
|
|
456
|
+
product_sku: item.product_sku,
|
|
457
|
+
product_name: item.product_name,
|
|
458
|
+
product_type: item.product_type,
|
|
459
|
+
product_size: item.product_size,
|
|
460
|
+
product_batch: item.product_batch,
|
|
461
|
+
product_batch_ref: item.product_batch_ref,
|
|
462
|
+
product_qty: item.product_qty,
|
|
463
|
+
product_weight: item.product_weight,
|
|
464
|
+
product_gross_weight: item.product_gross_weight,
|
|
465
|
+
product_uom_value: item.product_uom_value,
|
|
466
|
+
product_uom: item.product_uom,
|
|
467
|
+
product_desc: item.product_desc,
|
|
468
|
+
product_nameOnly: item.product_nameOnly,
|
|
469
|
+
product_brand_sku: item.product_brand_sku,
|
|
470
|
+
remark: item.remark,
|
|
471
|
+
inventory_remark: item.inventory_remark,
|
|
472
|
+
expiry_date: item.expiry_date,
|
|
473
|
+
palletQty: 1,
|
|
474
|
+
cross_docking: item.cross_docking,
|
|
475
|
+
pallet: item.pallet,
|
|
476
|
+
avgSellingPrice: item.avgSellingPrice,
|
|
477
|
+
product_volume: item.product_volume
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
newItem.push(foundItem)
|
|
481
|
+
return newItem
|
|
482
|
+
} else {
|
|
483
|
+
return newItem.map(ni => {
|
|
484
|
+
if (
|
|
485
|
+
ni.product_sku === item.product_sku &&
|
|
486
|
+
ni.product_name === item.product_name &&
|
|
487
|
+
ni.product_batch === item.product_batch &&
|
|
488
|
+
ni.product_batch_ref === item.product_batch_ref &&
|
|
489
|
+
ni.cross_docking === item.cross_docking &&
|
|
490
|
+
ni.pallet === item.pallet
|
|
491
|
+
) {
|
|
492
|
+
return {
|
|
493
|
+
...ni,
|
|
494
|
+
palletQty: ni.palletQty + 1,
|
|
495
|
+
product_qty: ni.product_qty + item.product_qty,
|
|
496
|
+
product_weight: ni.product_weight + item.product_weight,
|
|
497
|
+
product_uom_value: ni.product_uom_value + item.product_uom_value
|
|
498
|
+
}
|
|
499
|
+
} else {
|
|
500
|
+
return ni
|
|
501
|
+
}
|
|
502
|
+
})
|
|
503
|
+
}
|
|
504
|
+
}, [])
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Sort productList by tote_name in ascending order if totes exist
|
|
508
|
+
if (hasTotes) {
|
|
509
|
+
productList.sort((a, b) => {
|
|
510
|
+
const toteNameA = (a.tote_name || '').trim()
|
|
511
|
+
const toteNameB = (b.tote_name || '').trim()
|
|
512
|
+
|
|
513
|
+
// Sort by tote_name first (ascending), then by product_sku (ascending)
|
|
514
|
+
if (toteNameA !== toteNameB) {
|
|
515
|
+
return toteNameA.localeCompare(toteNameB, undefined, { numeric: true, sensitivity: 'base' })
|
|
310
516
|
}
|
|
311
|
-
|
|
517
|
+
return (a.product_sku || '').localeCompare(b.product_sku || '', undefined, { numeric: true, sensitivity: 'base' })
|
|
518
|
+
})
|
|
519
|
+
}
|
|
312
520
|
|
|
313
521
|
const data = {
|
|
314
522
|
logo_url: logo,
|
|
@@ -440,7 +648,7 @@ export async function renderRODO({ doNo }, context: any) {
|
|
|
440
648
|
product_uom_value: `${Math.round(prod.product_uom_value * 100) / 100} ${prod.product_uom}`,
|
|
441
649
|
selling_price:
|
|
442
650
|
prod?.avgSellingPrice > 0 ? parseFloat((prod?.avgSellingPrice * prod.product_qty).toFixed(2)) : 0,
|
|
443
|
-
product_volume: (Math.round(prod.product_volume * prod.product_qty * 10000)/10000).toFixed(4),
|
|
651
|
+
product_volume: (Math.round(prod.product_volume * prod.product_qty * 10000) / 10000).toFixed(4),
|
|
444
652
|
remark: prod?.remark
|
|
445
653
|
? prod.remark
|
|
446
654
|
: prod.cross_docking
|
|
@@ -453,16 +661,50 @@ export async function renderRODO({ doNo }, context: any) {
|
|
|
453
661
|
inventory_remark: prod?.inventory_remark ? prod.inventory_remark : '',
|
|
454
662
|
batch_id_ref: prod.product_batch_ref,
|
|
455
663
|
product_serial_number:
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
664
|
+
foundInventoryItem.length === 0 || !foundInventoryItem.some(item => item.sku === prod.product_sku)
|
|
665
|
+
? ''
|
|
666
|
+
: foundInventoryItem
|
|
667
|
+
.filter(item => item.sku === prod.product_sku)
|
|
668
|
+
.map((item: any, idx) => item.serial_number)
|
|
669
|
+
.join(', ')
|
|
670
|
+
}
|
|
461
671
|
}),
|
|
462
672
|
serialNumber:
|
|
463
673
|
foundInventoryItem.map((item: any, idx) => {
|
|
464
674
|
return { ...item, delivery_to: foundDO.to }
|
|
465
|
-
}) || ''
|
|
675
|
+
}) || '',
|
|
676
|
+
order_tote_items: foundOrderToteItems.map(item => {
|
|
677
|
+
// Get product information from orderInventory or orderProduct
|
|
678
|
+
const productFromInventory = item.orderInventory?.product || item.orderInventory?.inventory?.product
|
|
679
|
+
const product = productFromInventory
|
|
680
|
+
|
|
681
|
+
// Get packingType from orderInventory.inventory or item itself
|
|
682
|
+
const packingType = item.orderInventory?.inventory?.packingType
|
|
683
|
+
|
|
684
|
+
// Get tote information
|
|
685
|
+
const toteName = item.orderTote?.tote?.name || item.orderTote?.name || ''
|
|
686
|
+
|
|
687
|
+
// Get seals for this tote and join by comma
|
|
688
|
+
const seals = item.orderTote?.orderToteSeals || []
|
|
689
|
+
const sealNames = seals.map((seal: OrderToteSeal) => seal.name).filter(Boolean)
|
|
690
|
+
const sealsString = sealNames.length > 0 ? sealNames.join(', ') : null
|
|
691
|
+
|
|
692
|
+
return {
|
|
693
|
+
id: item.id,
|
|
694
|
+
name: item.name,
|
|
695
|
+
tote_id: item.orderTote?.id,
|
|
696
|
+
tote_name: toteName,
|
|
697
|
+
order_tote_id: item.orderTote?.id,
|
|
698
|
+
product_qty: item.qty,
|
|
699
|
+
product_sku: product?.sku,
|
|
700
|
+
product_brand_sku: product?.brandSku,
|
|
701
|
+
product_name: product?.name,
|
|
702
|
+
product_type: packingType,
|
|
703
|
+
closed_date: item.orderTote?.closedAt,
|
|
704
|
+
seals: sealsString
|
|
705
|
+
}
|
|
706
|
+
}),
|
|
707
|
+
total_tote_qty: totalToteQty
|
|
466
708
|
} //.. make data from do
|
|
467
709
|
const formData = new FormData()
|
|
468
710
|
|