@things-factory/worksheet-base 4.1.38 → 4.2.0

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 (83) hide show
  1. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +2 -0
  2. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  3. package/dist-server/controllers/outbound/packing-worksheet-controller.js +166 -8
  4. package/dist-server/controllers/outbound/packing-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/outbound/picking-worksheet-controller.js +22 -22
  6. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/outbound/sorting-worksheet-controller.js +110 -3
  8. package/dist-server/controllers/outbound/sorting-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/render-grn.js +27 -3
  10. package/dist-server/controllers/render-grn.js.map +1 -1
  11. package/dist-server/controllers/render-orientage-do.js.map +1 -1
  12. package/dist-server/controllers/render-orientage-grn.js.map +1 -1
  13. package/dist-server/controllers/render-ro-do.js +65 -1
  14. package/dist-server/controllers/render-ro-do.js.map +1 -1
  15. package/dist-server/controllers/worksheet-controller.js +2 -1
  16. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  17. package/dist-server/graphql/resolvers/worksheet/find-release-orders-by-task-no.js +30 -1
  18. package/dist-server/graphql/resolvers/worksheet/find-release-orders-by-task-no.js.map +1 -1
  19. package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js +3 -0
  20. package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js.map +1 -1
  21. package/dist-server/graphql/resolvers/worksheet/packing/index.js +2 -1
  22. package/dist-server/graphql/resolvers/worksheet/packing/index.js.map +1 -1
  23. package/dist-server/graphql/resolvers/worksheet/packing/packing.js +4 -4
  24. package/dist-server/graphql/resolvers/worksheet/packing/packing.js.map +1 -1
  25. package/dist-server/graphql/resolvers/worksheet/packing/scan-product-packing.js +4 -4
  26. package/dist-server/graphql/resolvers/worksheet/packing/scan-product-packing.js.map +1 -1
  27. package/dist-server/graphql/resolvers/worksheet/packing/undo-serial-number-packing.js +15 -0
  28. package/dist-server/graphql/resolvers/worksheet/packing/undo-serial-number-packing.js.map +1 -0
  29. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +152 -133
  30. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  31. package/dist-server/graphql/resolvers/worksheet/picking/assign-picking-worker.js +13 -10
  32. package/dist-server/graphql/resolvers/worksheet/picking/assign-picking-worker.js.map +1 -1
  33. package/dist-server/graphql/resolvers/worksheet/picking/picking-assignment-status-by-user.js +4 -7
  34. package/dist-server/graphql/resolvers/worksheet/picking/picking-assignment-status-by-user.js.map +1 -1
  35. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js +4 -4
  36. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js.map +1 -1
  37. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js +4 -4
  38. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js.map +1 -1
  39. package/dist-server/graphql/resolvers/worksheet/sorting-worksheet.js +6 -0
  40. package/dist-server/graphql/resolvers/worksheet/sorting-worksheet.js.map +1 -1
  41. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js +4 -5
  42. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js.map +1 -1
  43. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js +4 -2
  44. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js.map +1 -1
  45. package/dist-server/graphql/types/worksheet/find-release-orders-by-task-no.js +11 -0
  46. package/dist-server/graphql/types/worksheet/find-release-orders-by-task-no.js.map +1 -0
  47. package/dist-server/graphql/types/worksheet/index.js +14 -4
  48. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  49. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +2 -0
  50. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
  51. package/dist-server/graphql/types/worksheet-detail/index.js +0 -2
  52. package/dist-server/graphql/types/worksheet-detail/index.js.map +1 -1
  53. package/dist-server/utils/inventory-util.js +14 -25
  54. package/dist-server/utils/inventory-util.js.map +1 -1
  55. package/package.json +17 -17
  56. package/server/controllers/inbound/unloading-worksheet-controller.ts +2 -0
  57. package/server/controllers/outbound/packing-worksheet-controller.ts +217 -11
  58. package/server/controllers/outbound/picking-worksheet-controller.ts +23 -24
  59. package/server/controllers/outbound/sorting-worksheet-controller.ts +149 -4
  60. package/server/controllers/render-grn.ts +39 -5
  61. package/server/controllers/render-orientage-do.ts +11 -11
  62. package/server/controllers/render-orientage-grn.ts +11 -11
  63. package/server/controllers/render-ro-do.ts +93 -8
  64. package/server/controllers/worksheet-controller.ts +2 -1
  65. package/server/graphql/resolvers/worksheet/find-release-orders-by-task-no.ts +35 -2
  66. package/server/graphql/resolvers/worksheet/inventories-by-pallet.ts +2 -0
  67. package/server/graphql/resolvers/worksheet/packing/index.ts +3 -1
  68. package/server/graphql/resolvers/worksheet/packing/packing.ts +5 -4
  69. package/server/graphql/resolvers/worksheet/packing/scan-product-packing.ts +9 -4
  70. package/server/graphql/resolvers/worksheet/packing/undo-serial-number-packing.ts +24 -0
  71. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +166 -144
  72. package/server/graphql/resolvers/worksheet/picking/assign-picking-worker.ts +15 -11
  73. package/server/graphql/resolvers/worksheet/picking/picking-assignment-status-by-user.ts +5 -7
  74. package/server/graphql/resolvers/worksheet/sorting/scan-product-sorting.ts +5 -4
  75. package/server/graphql/resolvers/worksheet/sorting/sorting-product.ts +5 -4
  76. package/server/graphql/resolvers/worksheet/sorting-worksheet.ts +6 -0
  77. package/server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.ts +10 -12
  78. package/server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.ts +4 -2
  79. package/server/graphql/types/worksheet/find-release-orders-by-task-no.ts +8 -0
  80. package/server/graphql/types/worksheet/index.ts +14 -4
  81. package/server/graphql/types/worksheet/worksheet-detail-info.ts +2 -0
  82. package/server/graphql/types/worksheet-detail/index.ts +0 -2
  83. package/server/utils/inventory-util.ts +15 -23
@@ -1,6 +1,15 @@
1
+ import { Equal, Not } from 'typeorm'
2
+
1
3
  import { Product, ProductDetail } from '@things-factory/product-base'
2
4
  import { ORDER_INVENTORY_STATUS, ORDER_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
3
- import { Inventory, INVENTORY_TRANSACTION_TYPE } from '@things-factory/warehouse-base'
5
+ import {
6
+ Inventory,
7
+ INVENTORY_ITEM_SOURCE,
8
+ INVENTORY_STATUS,
9
+ INVENTORY_TRANSACTION_TYPE,
10
+ InventoryItem,
11
+ InventoryNoGenerator
12
+ } from '@things-factory/warehouse-base'
4
13
 
5
14
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
6
15
  import { Worksheet, WorksheetDetail } from '../../entities'
@@ -70,7 +79,7 @@ export class PackingWorksheetController extends VasWorksheetController {
70
79
  return worksheet
71
80
  }
72
81
 
73
- async packing(worksheetDetailName: string, packedQty: number): Promise<WorksheetDetail> {
82
+ async packing(worksheetDetailName: string, packedQty: number, serialNumber: string): Promise<WorksheetDetail> {
74
83
  let worksheetDetail: WorksheetDetail = await this.findExecutableWorksheetDetailByName(
75
84
  worksheetDetailName,
76
85
  WORKSHEET_TYPE.PACKING,
@@ -81,11 +90,13 @@ export class PackingWorksheetController extends VasWorksheetController {
81
90
  'targetInventory',
82
91
  'targetInventory.releaseGood',
83
92
  'targetInventory.inventory',
84
- 'targetInventory.inventory.location'
93
+ 'targetInventory.inventory.location',
94
+ 'targetInventory.product'
85
95
  ]
86
96
  )
87
97
  const releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
88
98
  let targetInventory: OrderInventory = worksheetDetail.targetInventory
99
+ const product: Product = targetInventory.product
89
100
  let inventory: Inventory = targetInventory.inventory
90
101
  const pickedQty: number = targetInventory.releaseQty
91
102
 
@@ -93,19 +104,81 @@ export class PackingWorksheetController extends VasWorksheetController {
93
104
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('pack', `packed quantity can't exceed release qty`))
94
105
  }
95
106
 
96
- targetInventory.packedQty = packedQty
97
- targetInventory.status = ORDER_INVENTORY_STATUS.PACKED
98
- await this.updateOrderTargets([targetInventory])
107
+ // Serial Number scanning for batch picking
108
+ if (targetInventory?.refWorksheetId) {
109
+ if (product?.isRequireSerialNumberScanningOutbound) {
110
+ if (!serialNumber || serialNumber == '') {
111
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('packing', `require serial number`))
112
+ }
113
+
114
+ let foundSerialNumber: InventoryItem = await this.trxMgr.getRepository(InventoryItem).findOne({
115
+ where: { domain: this.domain, serialNumber: serialNumber, product },
116
+ relations: ['product', 'inventory']
117
+ })
99
118
 
100
- await this.transactionInventory(inventory, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.PACKING)
119
+ if (foundSerialNumber) {
120
+ if (foundSerialNumber.outboundOrderId) {
121
+ let releaseGood: ReleaseGood = await this.trxMgr
122
+ .getRepository(ReleaseGood)
123
+ .findOne({ where: { id: foundSerialNumber.outboundOrderId } })
124
+ throw new Error(`Inventory Item is already picked/packed in ${releaseGood.name}`)
125
+ }
126
+
127
+ foundSerialNumber.status = INVENTORY_STATUS.PACKING
128
+ foundSerialNumber.updater = this.user
129
+ foundSerialNumber.outboundOrderId = releaseGood.id
130
+
131
+ await this.trxMgr.getRepository(InventoryItem).save(foundSerialNumber)
132
+ } else {
133
+ let inventoryItem: InventoryItem = new InventoryItem()
134
+ inventoryItem.name = InventoryNoGenerator.inventoryItemName()
135
+ inventoryItem.serialNumber = serialNumber
136
+ inventoryItem.status = INVENTORY_STATUS.PACKING
137
+ inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
138
+ inventoryItem.outboundOrderId = releaseGood.id
139
+ inventoryItem.product = product
140
+ inventoryItem.inventory = inventory
141
+ inventoryItem.domain = this.domain
142
+
143
+ foundSerialNumber = await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
144
+ }
145
+ }
146
+ }
147
+
148
+ targetInventory.packedQty = Boolean(targetInventory.packedQty) ? targetInventory.packedQty + packedQty : packedQty
149
+ if (targetInventory.packedQty == targetInventory.releaseQty) {
150
+ targetInventory.status = ORDER_INVENTORY_STATUS.PACKED
151
+
152
+ let inventoryItems: InventoryItem = await this.trxMgr
153
+ .getRepository(InventoryItem)
154
+ .find({ where: { outboundOrderId: releaseGood.id } })
155
+
156
+ if (inventoryItems.length > 0) {
157
+ inventoryItems.forEach((itm: InventoryItem) => {
158
+ itm.status = INVENTORY_STATUS.PACKED
159
+ itm.updater = this.user
160
+ })
161
+
162
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
163
+ }
164
+
165
+ await this.transactionInventory(inventory, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.PACKING)
166
+
167
+ worksheetDetail.status = WORKSHEET_STATUS.DONE
168
+ }
169
+
170
+ await this.updateOrderTargets([targetInventory])
101
171
 
102
- worksheetDetail.status = WORKSHEET_STATUS.DONE
103
172
  worksheetDetail.updater = this.user
104
173
  worksheetDetail = await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetail)
105
174
  return worksheetDetail
106
175
  }
107
176
 
108
- async scanProductPacking(worksheetDetailName: string, productBarcode: string): Promise<WorksheetDetail> {
177
+ async scanProductPacking(
178
+ worksheetDetailName: string,
179
+ productBarcode: string,
180
+ serialNumber?: string
181
+ ): Promise<WorksheetDetail> {
109
182
  let worksheetDetail: WorksheetDetail = await this.findExecutableWorksheetDetailByName(
110
183
  worksheetDetailName,
111
184
  WORKSHEET_TYPE.PACKING,
@@ -139,15 +212,59 @@ export class PackingWorksheetController extends VasWorksheetController {
139
212
  )
140
213
  if (!productDetail) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
141
214
 
215
+ // Serial Number scanning for batch picking
216
+ if (targetInventory?.refWorksheetId) {
217
+ if (product?.isRequireSerialNumberScanningOutbound) {
218
+ if (!serialNumber || serialNumber == '') {
219
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('packing', `require serial number`))
220
+ }
221
+
222
+ let foundSerialNumber: InventoryItem = await this.trxMgr
223
+ .getRepository(InventoryItem)
224
+ .findOne({ where: { domain: this.domain, serialNumber: serialNumber, product } })
225
+
226
+ if (foundSerialNumber) {
227
+ if (foundSerialNumber.inventoryId !== inventory.id) {
228
+ throw new Error('Serial Number scanned is in another inventory')
229
+ }
230
+
231
+ if (foundSerialNumber.outboundOrderId) {
232
+ let releaseGood: ReleaseGood = await this.trxMgr
233
+ .getRepository(ReleaseGood)
234
+ .findOne({ where: { id: foundSerialNumber.outboundOrderId } })
235
+ throw new Error(`Inventory Item is already picked/packed in ${releaseGood.name}`)
236
+ }
237
+
238
+ foundSerialNumber.status = INVENTORY_STATUS.PACKING
239
+ foundSerialNumber.updater = this.user
240
+ foundSerialNumber.outboundOrderId = releaseGood.id
241
+
242
+ await this.trxMgr.getRepository(InventoryItem).save(foundSerialNumber)
243
+ } else {
244
+ let inventoryItem: InventoryItem = new InventoryItem()
245
+ inventoryItem.name = InventoryNoGenerator.inventoryItemName()
246
+ inventoryItem.serialNumber = serialNumber
247
+ inventoryItem.status = INVENTORY_STATUS.PACKING
248
+ inventoryItem.outboundOrderId = releaseGood.id
249
+ inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
250
+ inventoryItem.product = product
251
+ inventoryItem.inventory = inventory
252
+ inventoryItem.domain = this.domain
253
+
254
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
255
+ }
256
+ }
257
+ }
258
+
142
259
  targetInventory.packedQty = Boolean(targetInventory?.packedQty) ? targetInventory.packedQty + packedQty : packedQty
143
260
  if (targetInventory.packedQty > pickedQty) {
144
261
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('pack', `packed quantity can't exceed release qty`))
145
262
  }
146
263
 
147
264
  targetInventory.packedAt = new Date()
148
- targetInventory.packedByUser = this.user;
265
+ targetInventory.packedByUser = this.user
149
266
 
150
- let packedBy: string[] = targetInventory.packedBy ? (targetInventory.packedBy).split(',') : []
267
+ let packedBy: string[] = targetInventory.packedBy ? targetInventory.packedBy.split(',') : []
151
268
  if (!packedBy.find(x => x == this.user.name)) {
152
269
  packedBy.push(this.user.name)
153
270
  targetInventory.packedBy = packedBy.join(',')
@@ -161,6 +278,19 @@ export class PackingWorksheetController extends VasWorksheetController {
161
278
  worksheetDetail.status = WORKSHEET_STATUS.DONE
162
279
  worksheetDetail.updater = this.user
163
280
  await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetail)
281
+
282
+ let inventoryItems: InventoryItem = await this.trxMgr
283
+ .getRepository(InventoryItem)
284
+ .find({ where: { outboundOrderId: releaseGood.id } })
285
+
286
+ if (inventoryItems.length > 0) {
287
+ inventoryItems.forEach((itm: InventoryItem) => {
288
+ itm.status = INVENTORY_STATUS.PACKED
289
+ itm.updater = this.user
290
+ })
291
+
292
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
293
+ }
164
294
  } else {
165
295
  await this.trxMgr.getRepository(OrderInventory).save(targetInventory)
166
296
  }
@@ -181,10 +311,86 @@ export class PackingWorksheetController extends VasWorksheetController {
181
311
  ])
182
312
  this.checkRecordValidity(worksheet, { status: WORKSHEET_STATUS.EXECUTING })
183
313
 
314
+ let inventoryItems: InventoryItem = await this.trxMgr
315
+ .getRepository(InventoryItem)
316
+ .find({ where: { outboundOrderId: releaseGood.id } })
317
+
318
+ if (inventoryItems.length > 0) {
319
+ inventoryItems.forEach((itm: InventoryItem) => {
320
+ itm.status = INVENTORY_STATUS.TERMINATED
321
+ itm.updater = this.user
322
+ })
323
+
324
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
325
+ }
326
+
184
327
  let orderStatus: string
185
328
  if (releaseGood?.courierOption) orderStatus = ORDER_STATUS.DONE
186
329
  else orderStatus = ORDER_STATUS.LOADING
187
330
 
188
331
  return await this.completeWorksheet(worksheet, orderStatus)
189
332
  }
333
+
334
+ async undoSerialNumberPacking(worksheetDetailName: string, inventoryItemId: string): Promise<void> {
335
+ const worksheetDetail: WorksheetDetail = await this.trxMgr.getRepository(WorksheetDetail).findOne({
336
+ where: { name: worksheetDetailName, domain: this.domain, status: Not(Equal(WORKSHEET_STATUS.DEACTIVATED)) },
337
+ relations: [
338
+ 'worksheet',
339
+ 'worksheet.releaseGood',
340
+ 'targetInventory',
341
+ 'targetInventory.product',
342
+ 'targetInventory.inventory'
343
+ ]
344
+ })
345
+
346
+ let targetInventory: OrderInventory = worksheetDetail.targetInventory
347
+ let releaseGood: ReleaseGood = worksheetDetail.worksheet.releaseGood
348
+
349
+ if (
350
+ targetInventory.releaseQty == targetInventory.packedQty &&
351
+ targetInventory.status == ORDER_INVENTORY_STATUS.PACKED
352
+ ) {
353
+ targetInventory.status = INVENTORY_STATUS.PACKING
354
+
355
+ await this.trxMgr
356
+ .getRepository(WorksheetDetail)
357
+ .update({ id: worksheetDetail.id }, { status: WORKSHEET_STATUS.EXECUTING })
358
+ }
359
+
360
+ let inventoryItems: InventoryItem = await this.trxMgr
361
+ .getRepository(InventoryItem)
362
+ .find({ where: { outboundOrderId: releaseGood.id } })
363
+
364
+ let removeInventoryItem: InventoryItem = await this.trxMgr
365
+ .getRepository(InventoryItem)
366
+ .findOne({ where: { id: inventoryItemId } })
367
+
368
+ if (inventoryItems.length > 0) {
369
+ inventoryItems.forEach((itm: InventoryItem) => {
370
+ itm.status = INVENTORY_STATUS.PACKING
371
+ itm.updater = this.user
372
+ })
373
+
374
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
375
+ }
376
+
377
+ if (removeInventoryItem.source == INVENTORY_ITEM_SOURCE.OUTBOUND) {
378
+ await this.trxMgr.getRepository(InventoryItem).delete(removeInventoryItem.id)
379
+ } else {
380
+ await this.trxMgr.getRepository(InventoryItem).update(
381
+ {
382
+ id: inventoryItemId
383
+ },
384
+ {
385
+ status: INVENTORY_STATUS.STORED,
386
+ outboundOrderId: null,
387
+ updater: this.user
388
+ }
389
+ )
390
+ }
391
+
392
+ targetInventory.packedQty--
393
+ targetInventory.updater = this.user
394
+ await this.updateOrderTargets([targetInventory])
395
+ }
190
396
  }
@@ -453,7 +453,7 @@ export class PickingWorksheetController extends VasWorksheetController {
453
453
  )
454
454
 
455
455
  pickedQty = await this.getChildQty(productDetails, productBarcode, roProductDetail)
456
- if (pickedQty > releaseQty) {
456
+ if (pickedQty + targetInventory.pickedQty > releaseQty) {
457
457
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
458
458
  }
459
459
  } else if (!foundProductDetail) {
@@ -555,8 +555,7 @@ export class PickingWorksheetController extends VasWorksheetController {
555
555
  //validation to prevent over release
556
556
  if (inventory.qty <= 0) throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
557
557
 
558
- if (inventory.palletId !== palletId /*&& !product?.isRequireSerialNumberScanningOutbound*/)
559
- //to be changed
558
+ if (inventory.palletId !== palletId && !product?.isRequireSerialNumberScanningOutbound)
560
559
  throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Pallet ID', palletId, inventory.palletId))
561
560
 
562
561
  if (product?.isRequireSerialNumberScanningOutbound) {
@@ -566,7 +565,8 @@ export class PickingWorksheetController extends VasWorksheetController {
566
565
 
567
566
  let totalInventoryItems = await this.trxMgr.getRepository(InventoryItem).count({
568
567
  where: {
569
- inventory
568
+ inventory,
569
+ status: Not(In([INVENTORY_STATUS.TERMINATED, INVENTORY_STATUS.PICKED]))
570
570
  }
571
571
  })
572
572
 
@@ -580,13 +580,11 @@ export class PickingWorksheetController extends VasWorksheetController {
580
580
  .findOne({ where: { domain: this.domain, palletId }, relations: ['product'] })
581
581
 
582
582
  if (foundSerialNumber) {
583
- if (
584
- foundSerialNumber.status !== INVENTORY_STATUS.STORED ||
585
- foundSerialNumber.outboundOrderId ||
586
- foundSerialNumber.inventory !== inventory
587
- /*to be changed for replacement && inventory.palletId == palletId*/
588
- ) {
589
- throw new Error('Inventory Item is not available')
583
+ if (foundSerialNumber.outboundOrderId) {
584
+ let releaseGood: ReleaseGood = await this.trxMgr
585
+ .getRepository(ReleaseGood)
586
+ .findOne({ where: { id: foundSerialNumber.outboundOrderId } })
587
+ throw new Error(`Inventory Item is already picked in ${releaseGood.name}`)
590
588
  }
591
589
 
592
590
  foundSerialNumber.status = INVENTORY_STATUS.PICKING
@@ -603,12 +601,13 @@ export class PickingWorksheetController extends VasWorksheetController {
603
601
  inventoryItem.name = InventoryNoGenerator.inventoryItemName()
604
602
  inventoryItem.serialNumber = serialNumber
605
603
  inventoryItem.status = INVENTORY_STATUS.PICKING
604
+ inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
606
605
  inventoryItem.outboundOrderId = releaseGood.id
607
606
  inventoryItem.product = product
608
607
  inventoryItem.inventory = scannedPalletIdInventory
609
608
  inventoryItem.domain = this.domain
610
609
 
611
- await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
610
+ foundSerialNumber = await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
612
611
  }
613
612
 
614
613
  if (inventory.palletId !== palletId) {
@@ -648,10 +647,10 @@ export class PickingWorksheetController extends VasWorksheetController {
648
647
  }
649
648
  }
650
649
 
651
- await this.updatePickingTransaction(releaseGood, targetInventory, worksheetDetail, inventory, pickedQty)
652
-
653
650
  targetInventory = await this.checkAndSetBinPicking(targetInventory, binLocation)
654
651
 
652
+ await this.updatePickingTransaction(releaseGood, targetInventory, worksheetDetail, inventory, pickedQty)
653
+
655
654
  const fromLocation: Location = targetInventory.inventory.location
656
655
  if (locationName) {
657
656
  const toLocation: Location = await this.trxMgr.getRepository(Location).findOne({
@@ -954,12 +953,12 @@ export class PickingWorksheetController extends VasWorksheetController {
954
953
  ])
955
954
  await this.checkRecordValidity(worksheet, { status: WORKSHEET_STATUS.EXECUTING })
956
955
 
957
- let InventoryItems: InventoryItem = await this.trxMgr
956
+ let inventoryItems: InventoryItem = await this.trxMgr
958
957
  .getRepository(InventoryItem)
959
958
  .find({ where: { outboundOrderId: releaseGood.id } })
960
959
 
961
- if (InventoryItems.length > 0) {
962
- InventoryItems.forEach((itm: InventoryItem) => {
960
+ if (inventoryItems.length > 0) {
961
+ inventoryItems.forEach((itm: InventoryItem) => {
963
962
  itm.status = INVENTORY_STATUS.TERMINATED
964
963
  itm.updater = this.user
965
964
  })
@@ -973,7 +972,7 @@ export class PickingWorksheetController extends VasWorksheetController {
973
972
  // this.transactionInventory(itm, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.TERMINATED)
974
973
  // })
975
974
 
976
- await this.trxMgr.getRepository(InventoryItem).save(InventoryItems)
975
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
977
976
  }
978
977
 
979
978
  let orderStatus: string
@@ -1126,17 +1125,17 @@ export class PickingWorksheetController extends VasWorksheetController {
1126
1125
  worksheetDetail.updater = this.user
1127
1126
  await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetail)
1128
1127
 
1129
- let InventoryItems: InventoryItem = await this.trxMgr
1128
+ let inventoryItems: InventoryItem = await this.trxMgr
1130
1129
  .getRepository(InventoryItem)
1131
1130
  .find({ where: { outboundOrderId: releaseGood.id } })
1132
1131
 
1133
- if (InventoryItems.length > 0) {
1134
- InventoryItems.forEach((itm: InventoryItem) => {
1132
+ if (inventoryItems.length > 0) {
1133
+ inventoryItems.forEach((itm: InventoryItem) => {
1135
1134
  itm.status = INVENTORY_STATUS.PICKED
1136
1135
  itm.updater = this.user
1137
1136
  })
1138
1137
 
1139
- await this.trxMgr.getRepository(InventoryItem).save(InventoryItems)
1138
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
1140
1139
  }
1141
1140
 
1142
1141
  if (leftQty === 0) {
@@ -1247,8 +1246,8 @@ export class PickingWorksheetController extends VasWorksheetController {
1247
1246
  }
1248
1247
  )
1249
1248
  } else {
1250
- await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1251
1249
  await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetail.ild)
1250
+ await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1252
1251
  }
1253
1252
  } catch (e) {}
1254
1253
  }
@@ -1362,8 +1361,8 @@ export class PickingWorksheetController extends VasWorksheetController {
1362
1361
  }
1363
1362
  )
1364
1363
  } else {
1365
- await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1366
1364
  await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetail.id)
1365
+ await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1367
1366
  }
1368
1367
  } catch (e) {}
1369
1368
  }
@@ -1,6 +1,13 @@
1
1
  import { VasWorksheetController } from '../vas/vas-worksheet-controller'
2
2
  import { Product, ProductDetail } from '@things-factory/product-base'
3
- import { Inventory, INVENTORY_TRANSACTION_TYPE } from '@things-factory/warehouse-base'
3
+ import {
4
+ Inventory,
5
+ INVENTORY_TRANSACTION_TYPE,
6
+ InventoryItem,
7
+ INVENTORY_STATUS,
8
+ InventoryNoGenerator,
9
+ INVENTORY_ITEM_SOURCE
10
+ } from '@things-factory/warehouse-base'
4
11
  import { ReleaseGood, OrderInventory, ORDER_INVENTORY_STATUS, ORDER_STATUS } from '@things-factory/sales-base'
5
12
  import { Worksheet, WorksheetDetail } from '../../entities'
6
13
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
@@ -51,7 +58,12 @@ export class SortingWorksheetController extends VasWorksheetController {
51
58
  return await this.activateWorksheet(worksheet, worksheetDetails, sortingWorksheetDetails)
52
59
  }
53
60
 
54
- async scanProductSorting(taskNo: string, releaseGoodNo: string, productBarcode: string): Promise<void> {
61
+ async scanProductSorting(
62
+ taskNo: string,
63
+ releaseGoodNo: string,
64
+ productBarcode: string,
65
+ serialNumber: string
66
+ ): Promise<void> {
55
67
  const worksheet: Worksheet = await this.trxMgr.getRepository(Worksheet).findOne({
56
68
  where: {
57
69
  domain: this.domain,
@@ -113,8 +125,53 @@ export class SortingWorksheetController extends VasWorksheetController {
113
125
  const releaseQty: number = matchingOI.releaseQty
114
126
  const inventory: Inventory = matchingOI.inventory
115
127
  const releaseGood: ReleaseGood = matchingOI.releaseGood
128
+ const product: Product = inventory.product
116
129
 
117
130
  if (releaseQty != matchingOI?.sortedQty && sortedQty == 1) {
131
+ // Serial Number scanning for batch picking
132
+ if (matchingOI?.refWorksheetId) {
133
+ if (product?.isRequireSerialNumberScanningOutbound) {
134
+ if (!serialNumber || serialNumber == '') {
135
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('sorting', `require serial number`))
136
+ }
137
+
138
+ let foundSerialNumber: InventoryItem = await this.trxMgr
139
+ .getRepository(InventoryItem)
140
+ .findOne({ where: { domain: this.domain, serialNumber: serialNumber, product } })
141
+
142
+ if (foundSerialNumber) {
143
+ if (foundSerialNumber.inventoryId !== inventory.id) {
144
+ throw new Error('Serial Number scanned is in another inventory')
145
+ }
146
+
147
+ if (foundSerialNumber.outboundOrderId) {
148
+ let releaseGood: ReleaseGood = await this.trxMgr
149
+ .getRepository(ReleaseGood)
150
+ .findOne({ where: { id: foundSerialNumber.outboundOrderId } })
151
+ throw new Error(`Inventory Item is already picked/sorted in ${releaseGood.name}`)
152
+ }
153
+
154
+ foundSerialNumber.status = INVENTORY_STATUS.SORTING
155
+ foundSerialNumber.updater = this.user
156
+ foundSerialNumber.outboundOrderId = releaseGood.id
157
+
158
+ await this.trxMgr.getRepository(InventoryItem).save(foundSerialNumber)
159
+ } else {
160
+ let inventoryItem: InventoryItem = new InventoryItem()
161
+ inventoryItem.name = InventoryNoGenerator.inventoryItemName()
162
+ inventoryItem.serialNumber = serialNumber
163
+ inventoryItem.status = INVENTORY_STATUS.SORTING
164
+ inventoryItem.outboundOrderId = releaseGood.id
165
+ inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
166
+ inventoryItem.product = product
167
+ inventoryItem.inventory = inventory
168
+ inventoryItem.domain = this.domain
169
+
170
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
171
+ }
172
+ }
173
+ }
174
+
118
175
  matchingOI.sortedQty = Boolean(matchingOI?.sortedQty) ? matchingOI.sortedQty + sortedQty : sortedQty
119
176
  sortedQty -= 1
120
177
  if (matchingOI.sortedQty == releaseQty) {
@@ -128,6 +185,19 @@ export class SortingWorksheetController extends VasWorksheetController {
128
185
  worksheetDetail.status = WORKSHEET_STATUS.DONE
129
186
  worksheetDetail.updater = this.user
130
187
  await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetail)
188
+
189
+ let inventoryItems: InventoryItem = await this.trxMgr
190
+ .getRepository(InventoryItem)
191
+ .find({ where: { outboundOrderId: releaseGood.id } })
192
+
193
+ if (inventoryItems.length > 0) {
194
+ inventoryItems.forEach((itm: InventoryItem) => {
195
+ itm.status = INVENTORY_STATUS.SORTED
196
+ itm.updater = this.user
197
+ })
198
+
199
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
200
+ }
131
201
  } else if (matchingOI?.sortedQty > releaseQty) {
132
202
  const product: Product = matchingOI.inventory.product
133
203
  throw new Error(this.ERROR_MSG.ORDER_ITEM.EXCESS_QTY(product.sku, packingType, packingSize))
@@ -141,7 +211,13 @@ export class SortingWorksheetController extends VasWorksheetController {
141
211
  }
142
212
  }
143
213
 
144
- async sortingProduct(taskNo: string, releaseGoodNo: string, productId: string, sortingQty: number): Promise<void> {
214
+ async sortingProduct(
215
+ taskNo: string,
216
+ releaseGoodNo: string,
217
+ productId: string,
218
+ sortingQty: number,
219
+ serialNumber: string
220
+ ): Promise<void> {
145
221
  const worksheet: Worksheet = await this.trxMgr.getRepository(Worksheet).findOne({
146
222
  where: {
147
223
  domain: this.domain,
@@ -180,14 +256,70 @@ export class SortingWorksheetController extends VasWorksheetController {
180
256
  const packingType: string = matchingOI.packingType
181
257
  const packingSize: number = matchingOI.packingSize
182
258
 
259
+ if (product?.isRequireSerialNumberScanningOutbound) {
260
+ if (!serialNumber || serialNumber == '') {
261
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('sorting', `require serial number`))
262
+ }
263
+
264
+ let foundSerialNumber: InventoryItem = await this.trxMgr.getRepository(InventoryItem).findOne({
265
+ where: { domain: this.domain, serialNumber: serialNumber, product },
266
+ relations: ['product', 'inventory']
267
+ })
268
+
269
+ if (foundSerialNumber) {
270
+ if (foundSerialNumber.outboundOrderId) {
271
+ let releaseGood: ReleaseGood = await this.trxMgr
272
+ .getRepository(ReleaseGood)
273
+ .findOne({ where: { id: foundSerialNumber.outboundOrderId } })
274
+ throw new Error(`Inventory Item is already picked/sorted in ${releaseGood.name}`)
275
+ }
276
+
277
+ foundSerialNumber.status = INVENTORY_STATUS.SORTING
278
+ foundSerialNumber.updater = this.user
279
+ foundSerialNumber.outboundOrderId = releaseGood.id
280
+
281
+ await this.trxMgr.getRepository(InventoryItem).save(foundSerialNumber)
282
+ } else {
283
+ let inventoryItem: InventoryItem = new InventoryItem()
284
+ inventoryItem.name = InventoryNoGenerator.inventoryItemName()
285
+ inventoryItem.serialNumber = serialNumber
286
+ inventoryItem.status = INVENTORY_STATUS.SORTING
287
+ inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
288
+ inventoryItem.outboundOrderId = releaseGood.id
289
+ inventoryItem.product = product
290
+ inventoryItem.inventory = inventory
291
+ inventoryItem.domain = this.domain
292
+
293
+ foundSerialNumber = await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
294
+ }
295
+ }
296
+
183
297
  if (releaseQty != matchingOI?.sortedQty && sortingQty != 0) {
184
- matchingOI.sortedQty = releaseQty
298
+ if (product?.isRequireSerialNumberScanningOutbound) {
299
+ matchingOI.sortedQty += sortingQty
300
+ } else {
301
+ matchingOI.sortedQty = releaseQty
302
+ }
303
+
185
304
  sortingQty -= releaseQty
186
305
  if (matchingOI.sortedQty == releaseQty) {
187
306
  matchingOI.status = ORDER_INVENTORY_STATUS.SORTED
188
307
  await this.updateOrderTargets([matchingOI])
189
308
  await this.transactionInventory(inventory, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.SORTING)
190
309
 
310
+ let inventoryItems: InventoryItem = await this.trxMgr
311
+ .getRepository(InventoryItem)
312
+ .find({ where: { outboundOrderId: releaseGood.id } })
313
+
314
+ if (inventoryItems.length > 0) {
315
+ inventoryItems.forEach((itm: InventoryItem) => {
316
+ itm.status = INVENTORY_STATUS.PACKED
317
+ itm.updater = this.user
318
+ })
319
+
320
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
321
+ }
322
+
191
323
  let worksheetDetail: WorksheetDetail = worksheetDetails.find(
192
324
  wsd => wsd.targetInventory.id === matchingOI.id
193
325
  )
@@ -220,6 +352,19 @@ export class SortingWorksheetController extends VasWorksheetController {
220
352
  releaseGood.updater = this.user
221
353
  await this.trxMgr.getRepository(ReleaseGood).save(releaseGood)
222
354
 
355
+ let inventoryItems: InventoryItem = await this.trxMgr
356
+ .getRepository(InventoryItem)
357
+ .find({ where: { outboundOrderId: releaseGood.id } })
358
+
359
+ if (inventoryItems.length > 0) {
360
+ inventoryItems.forEach((itm: InventoryItem) => {
361
+ itm.status = INVENTORY_STATUS.TERMINATED
362
+ itm.updater = this.user
363
+ })
364
+
365
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItems)
366
+ }
367
+
223
368
  return releaseGood
224
369
  }
225
370