@things-factory/worksheet-base 4.1.41 → 4.2.2

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 (67) 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/worksheet-controller.js +2 -1
  10. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  11. package/dist-server/graphql/resolvers/worksheet/find-release-orders-by-task-no.js +30 -1
  12. package/dist-server/graphql/resolvers/worksheet/find-release-orders-by-task-no.js.map +1 -1
  13. package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js +3 -0
  14. package/dist-server/graphql/resolvers/worksheet/inventories-by-pallet.js.map +1 -1
  15. package/dist-server/graphql/resolvers/worksheet/packing/index.js +2 -1
  16. package/dist-server/graphql/resolvers/worksheet/packing/index.js.map +1 -1
  17. package/dist-server/graphql/resolvers/worksheet/packing/packing.js +4 -4
  18. package/dist-server/graphql/resolvers/worksheet/packing/packing.js.map +1 -1
  19. package/dist-server/graphql/resolvers/worksheet/packing/scan-product-packing.js +4 -4
  20. package/dist-server/graphql/resolvers/worksheet/packing/scan-product-packing.js.map +1 -1
  21. package/dist-server/graphql/resolvers/worksheet/packing/undo-serial-number-packing.js +15 -0
  22. package/dist-server/graphql/resolvers/worksheet/packing/undo-serial-number-packing.js.map +1 -0
  23. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +152 -133
  24. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  25. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js +4 -4
  26. package/dist-server/graphql/resolvers/worksheet/sorting/scan-product-sorting.js.map +1 -1
  27. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js +4 -4
  28. package/dist-server/graphql/resolvers/worksheet/sorting/sorting-product.js.map +1 -1
  29. package/dist-server/graphql/resolvers/worksheet/sorting-worksheet.js +6 -0
  30. package/dist-server/graphql/resolvers/worksheet/sorting-worksheet.js.map +1 -1
  31. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js +4 -5
  32. package/dist-server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.js.map +1 -1
  33. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js +4 -2
  34. package/dist-server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.js.map +1 -1
  35. package/dist-server/graphql/types/worksheet/find-release-orders-by-task-no.js +11 -0
  36. package/dist-server/graphql/types/worksheet/find-release-orders-by-task-no.js.map +1 -0
  37. package/dist-server/graphql/types/worksheet/index.js +13 -2
  38. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  39. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +2 -0
  40. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
  41. package/dist-server/graphql/types/worksheet-detail/index.js +0 -2
  42. package/dist-server/graphql/types/worksheet-detail/index.js.map +1 -1
  43. package/dist-server/utils/inventory-util.js +14 -25
  44. package/dist-server/utils/inventory-util.js.map +1 -1
  45. package/package.json +9 -9
  46. package/server/controllers/inbound/unloading-worksheet-controller.ts +2 -0
  47. package/server/controllers/outbound/packing-worksheet-controller.ts +217 -11
  48. package/server/controllers/outbound/picking-worksheet-controller.ts +23 -24
  49. package/server/controllers/outbound/sorting-worksheet-controller.ts +149 -4
  50. package/server/controllers/worksheet-controller.ts +2 -1
  51. package/server/graphql/resolvers/worksheet/find-release-orders-by-task-no.ts +35 -2
  52. package/server/graphql/resolvers/worksheet/inventories-by-pallet.ts +2 -0
  53. package/server/graphql/resolvers/worksheet/packing/index.ts +3 -1
  54. package/server/graphql/resolvers/worksheet/packing/packing.ts +5 -4
  55. package/server/graphql/resolvers/worksheet/packing/scan-product-packing.ts +9 -4
  56. package/server/graphql/resolvers/worksheet/packing/undo-serial-number-packing.ts +24 -0
  57. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +166 -144
  58. package/server/graphql/resolvers/worksheet/sorting/scan-product-sorting.ts +5 -4
  59. package/server/graphql/resolvers/worksheet/sorting/sorting-product.ts +5 -4
  60. package/server/graphql/resolvers/worksheet/sorting-worksheet.ts +6 -0
  61. package/server/graphql/resolvers/worksheet-detail/generate-batch-picking-worksheet-details-by-bulk.ts +10 -12
  62. package/server/graphql/resolvers/worksheet-detail/generate-picking-worksheet-details.ts +4 -2
  63. package/server/graphql/types/worksheet/find-release-orders-by-task-no.ts +8 -0
  64. package/server/graphql/types/worksheet/index.ts +13 -2
  65. package/server/graphql/types/worksheet/worksheet-detail-info.ts +2 -0
  66. package/server/graphql/types/worksheet-detail/index.ts +0 -2
  67. package/server/utils/inventory-util.ts +15 -23
@@ -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
 
@@ -950,7 +950,8 @@ export class WorksheetController {
950
950
  const duplicatedSerialNumberCnt: number = await this.trxMgr.getRepository(InventoryItem).count({
951
951
  domain: this.domain,
952
952
  product,
953
- serialNumber
953
+ serialNumber,
954
+ status: Not(Equal(INVENTORY_STATUS.DELETED))
954
955
  })
955
956
 
956
957
  if (duplicatedSerialNumberCnt) throw new Error(this.ERROR_MSG.VALIDITY.DUPLICATED('Serial Number', serialNumber))
@@ -1,11 +1,12 @@
1
1
  import { EntityManager, SelectQueryBuilder } from 'typeorm'
2
2
 
3
3
  import {
4
- ORDER_STATUS,
4
+ ORDER_STATUS, ORDER_INVENTORY_STATUS,
5
5
  OrderInventory as OrderInventoryEntity,
6
6
  ReleaseGood as ReleaseGoodEntity
7
7
  } from '@things-factory/sales-base'
8
8
  import { Domain } from '@things-factory/shell'
9
+ import { Location } from '@things-factory/warehouse-base'
9
10
 
10
11
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../constants'
11
12
  import { Worksheet as WorksheetEntity, WorksheetDetail as WorksheetDetailEntity } from '../../../entities'
@@ -16,6 +17,38 @@ export const findReleaseOrdersByTaskNoResolver = {
16
17
  let task = await tx.getRepository(WorksheetEntity).findOne({
17
18
  where: { taskNo, status: WORKSHEET_STATUS.EXECUTING, type: WORKSHEET_TYPE.SORTING }
18
19
  })
20
+
21
+ // Find Task based on Bin
22
+ if (!task) {
23
+ const binLocation: Location = await tx.getRepository(Location).findOne({
24
+ where: { domain, name: taskNo }
25
+ })
26
+
27
+ const qb: SelectQueryBuilder<OrderInventoryEntity> = tx.getRepository(OrderInventoryEntity).createQueryBuilder('orderInventory')
28
+
29
+ qb.innerJoinAndSelect('orderInventory.releaseGood', 'releaseGood')
30
+ .innerJoinAndSelect('worksheets', 'ws', `orderInventory.ref_worksheet_id = ws.id AND ws.type = 'BATCH_PICKING'`)
31
+ .innerJoinAndSelect('worksheets', 'ws2', `ws2.task_no = ws.task_no AND ws2.type = 'SORTING'`)
32
+ .innerJoinAndSelect('releaseGood.bizplace', 'bizplace')
33
+ .innerJoinAndSelect('bizplace.domain', 'domain')
34
+ .where('orderInventory.domain_id = :domainId', { domainId: domain.id })
35
+ .andWhere('orderInventory.status IN (:...orderInventoryStatus)', {
36
+ orderInventoryStatus: [ORDER_INVENTORY_STATUS.SORTING]
37
+ })
38
+ .andWhere('orderInventory.bin_location_id = :locationId', { locationId: binLocation.id })
39
+ .andWhere('releaseGood.status = :status', { status: ORDER_STATUS.SORTING })
40
+
41
+ const orderInventoryByBin = await qb.getRawOne()
42
+ if (orderInventoryByBin?.releaseGood_id) {
43
+ taskNo = orderInventoryByBin.ws_task_no
44
+ task = await tx.getRepository(WorksheetEntity).findOne({
45
+ where: { taskNo, status: WORKSHEET_STATUS.EXECUTING, type: WORKSHEET_TYPE.SORTING }
46
+ })
47
+ } else {
48
+ throw new Error(`Bin do not have any batch picking order.`)
49
+ }
50
+ }
51
+
19
52
  if (!task) throw new Error('Unable to find task no.')
20
53
 
21
54
  const qb: SelectQueryBuilder<WorksheetEntity> = tx
@@ -38,6 +71,6 @@ export const findReleaseOrdersByTaskNoResolver = {
38
71
  .addGroupBy('rg.status')
39
72
 
40
73
  const releaseGoods: ReleaseGoodEntity[] = await qb.getRawMany()
41
- return releaseGoods
74
+ return { releaseGoods, taskNo }
42
75
  }
43
76
  }
@@ -78,6 +78,8 @@ export const inventoriesByPalletResolver = {
78
78
  locationSortingRules.forEach((rule: { name: string; desc: boolean }) => {
79
79
  qb.addOrderBy(`location.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
80
80
  })
81
+ } else {
82
+ qb.addOrderBy('location.name', 'DESC')
81
83
  }
82
84
 
83
85
  if (productFilters && productFilters.length > 0) {
@@ -2,10 +2,12 @@ import { activatePackingResolver } from './activate-packing'
2
2
  import { completePackingResolver } from './complete-packing'
3
3
  import { packingResolver } from './packing'
4
4
  import { scanProductPackingResolver } from './scan-product-packing'
5
+ import { undoSerialNumberPackingResolver } from './undo-serial-number-packing'
5
6
 
6
7
  export const Mutations = {
7
8
  ...activatePackingResolver,
8
9
  ...completePackingResolver,
9
10
  ...packingResolver,
10
- ...scanProductPackingResolver
11
+ ...scanProductPackingResolver,
12
+ ...undoSerialNumberPackingResolver
11
13
  }
@@ -9,9 +9,9 @@ import { PackingWorksheetController, SellercraftController } from '../../../../c
9
9
  import { Worksheet } from '../../../../entities'
10
10
 
11
11
  export const packingResolver = {
12
- async packing(_: any, { worksheetDetailName, releaseQty }, context: any) {
12
+ async packing(_: any, { worksheetDetailName, releaseQty, serialNumber }, context: any) {
13
13
  const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
14
- await packing(tx, domain, user, worksheetDetailName, releaseQty)
14
+ await packing(tx, domain, user, worksheetDetailName, releaseQty, serialNumber)
15
15
  }
16
16
  }
17
17
 
@@ -20,10 +20,11 @@ export async function packing(
20
20
  domain: Domain,
21
21
  user: User,
22
22
  worksheetDetailName: string,
23
- releaseQty: number
23
+ releaseQty: number,
24
+ serialNumber: string
24
25
  ) {
25
26
  const worksheetController: PackingWorksheetController = new PackingWorksheetController(tx, domain, user)
26
- const worksheetDetail = await worksheetController.packing(worksheetDetailName, releaseQty)
27
+ const worksheetDetail = await worksheetController.packing(worksheetDetailName, releaseQty, serialNumber)
27
28
 
28
29
  let releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
29
30
  const worksheet: Worksheet = worksheetDetail.worksheet
@@ -9,9 +9,9 @@ import { PackingWorksheetController, SellercraftController } from '../../../../c
9
9
  import { Worksheet } from '../../../../entities'
10
10
 
11
11
  export const scanProductPackingResolver = {
12
- async scanProductPacking(_: any, { worksheetDetailName, productBarcode }, context: any) {
12
+ async scanProductPacking(_: any, { worksheetDetailName, productBarcode, serialNumber }, context: any) {
13
13
  const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
14
- await scanProductPacking(tx, domain, user, worksheetDetailName, productBarcode)
14
+ await scanProductPacking(tx, domain, user, worksheetDetailName, productBarcode, serialNumber)
15
15
  }
16
16
  }
17
17
 
@@ -20,10 +20,15 @@ export async function scanProductPacking(
20
20
  domain: Domain,
21
21
  user: User,
22
22
  worksheetDetailName: string,
23
- productBarcode: string
23
+ productBarcode: string,
24
+ serialNumber?: string
24
25
  ) {
25
26
  const worksheetController: PackingWorksheetController = new PackingWorksheetController(tx, domain, user)
26
- const worksheetDetail = await worksheetController.scanProductPacking(worksheetDetailName, productBarcode)
27
+ const worksheetDetail = await worksheetController.scanProductPacking(
28
+ worksheetDetailName,
29
+ productBarcode,
30
+ serialNumber
31
+ )
27
32
 
28
33
  let releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
29
34
  const worksheet: Worksheet = worksheetDetail.worksheet
@@ -0,0 +1,24 @@
1
+ import { EntityManager } from 'typeorm'
2
+
3
+ import { User } from '@things-factory/auth-base'
4
+ import { Domain } from '@things-factory/shell'
5
+
6
+ import { PackingWorksheetController } from '../../../../controllers'
7
+
8
+ export const undoSerialNumberPackingResolver = {
9
+ async undoSerialNumberPacking(_: any, { worksheetDetailName, inventoryItemId }, context: any) {
10
+ const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
11
+ await undoSerialNumberPacking(tx, domain, user, worksheetDetailName, inventoryItemId)
12
+ }
13
+ }
14
+
15
+ async function undoSerialNumberPacking(
16
+ tx: EntityManager,
17
+ domain: Domain,
18
+ user: User,
19
+ worksheetDetailName: string,
20
+ inventoryItemId: string
21
+ ): Promise<void> {
22
+ const worksheetController: PackingWorksheetController = new PackingWorksheetController(tx, domain, user)
23
+ await worksheetController.undoSerialNumberPacking(worksheetDetailName, inventoryItemId)
24
+ }