@things-factory/worksheet-base 4.1.31 → 4.1.35

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 (51) hide show
  1. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +235 -0
  2. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  3. package/dist-server/controllers/outbound/picking-worksheet-controller.js +327 -39
  4. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/render-invoices.js +15 -13
  6. package/dist-server/controllers/render-invoices.js.map +1 -1
  7. package/dist-server/controllers/worksheet-controller.js +14 -0
  8. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  9. package/dist-server/graphql/resolvers/worksheet/loading/complete-loading.js +16 -2
  10. package/dist-server/graphql/resolvers/worksheet/loading/complete-loading.js.map +1 -1
  11. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +0 -17
  12. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  13. package/dist-server/graphql/resolvers/worksheet/picking/index.js +2 -1
  14. package/dist-server/graphql/resolvers/worksheet/picking/index.js.map +1 -1
  15. package/dist-server/graphql/resolvers/worksheet/picking/undo-serial-number-picking.js +15 -0
  16. package/dist-server/graphql/resolvers/worksheet/picking/undo-serial-number-picking.js.map +1 -0
  17. package/dist-server/graphql/resolvers/worksheet/unloaded-inventories.js +3 -2
  18. package/dist-server/graphql/resolvers/worksheet/unloaded-inventories.js.map +1 -1
  19. package/dist-server/graphql/resolvers/worksheet/unloading/index.js +3 -1
  20. package/dist-server/graphql/resolvers/worksheet/unloading/index.js.map +1 -1
  21. package/dist-server/graphql/resolvers/worksheet/unloading/scan-serial-number-unload.js +15 -0
  22. package/dist-server/graphql/resolvers/worksheet/unloading/scan-serial-number-unload.js.map +1 -0
  23. package/dist-server/graphql/resolvers/worksheet/unloading/undo-serial-number-unload.js +15 -0
  24. package/dist-server/graphql/resolvers/worksheet/unloading/undo-serial-number-unload.js.map +1 -0
  25. package/dist-server/graphql/resolvers/worksheet/unloading/unload.js.map +1 -1
  26. package/dist-server/graphql/resolvers/worksheet/unloading-worksheet.js +3 -1
  27. package/dist-server/graphql/resolvers/worksheet/unloading-worksheet.js.map +1 -1
  28. package/dist-server/graphql/types/worksheet/index.js +16 -0
  29. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  30. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js +1 -0
  31. package/dist-server/graphql/types/worksheet/worksheet-detail-info.js.map +1 -1
  32. package/dist-server/graphql/types/worksheet/worksheet-info.js +1 -0
  33. package/dist-server/graphql/types/worksheet/worksheet-info.js.map +1 -1
  34. package/package.json +7 -7
  35. package/server/controllers/inbound/unloading-worksheet-controller.ts +277 -1
  36. package/server/controllers/outbound/picking-worksheet-controller.ts +433 -52
  37. package/server/controllers/render-invoices.ts +23 -26
  38. package/server/controllers/worksheet-controller.ts +17 -2
  39. package/server/graphql/resolvers/worksheet/loading/complete-loading.ts +25 -6
  40. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +0 -18
  41. package/server/graphql/resolvers/worksheet/picking/index.ts +3 -1
  42. package/server/graphql/resolvers/worksheet/picking/undo-serial-number-picking.ts +24 -0
  43. package/server/graphql/resolvers/worksheet/unloaded-inventories.ts +6 -2
  44. package/server/graphql/resolvers/worksheet/unloading/index.ts +4 -0
  45. package/server/graphql/resolvers/worksheet/unloading/scan-serial-number-unload.ts +26 -0
  46. package/server/graphql/resolvers/worksheet/unloading/undo-serial-number-unload.ts +24 -0
  47. package/server/graphql/resolvers/worksheet/unloading/unload.ts +3 -1
  48. package/server/graphql/resolvers/worksheet/unloading-worksheet.ts +3 -1
  49. package/server/graphql/types/worksheet/index.ts +16 -0
  50. package/server/graphql/types/worksheet/worksheet-detail-info.ts +1 -0
  51. package/server/graphql/types/worksheet/worksheet-info.ts +1 -0
@@ -1,4 +1,4 @@
1
- import { In } from 'typeorm'
1
+ import { Equal, In, Not } from 'typeorm'
2
2
 
3
3
  import { Bizplace } from '@things-factory/biz-base'
4
4
  import { generateId } from '@things-factory/id-rule-base'
@@ -14,8 +14,11 @@ import {
14
14
  import { Setting } from '@things-factory/setting-base'
15
15
  import {
16
16
  Inventory,
17
+ INVENTORY_ITEM_SOURCE,
17
18
  INVENTORY_STATUS,
18
19
  INVENTORY_TRANSACTION_TYPE,
20
+ InventoryItem,
21
+ InventoryNoGenerator,
19
22
  Location,
20
23
  LOCATION_TYPE
21
24
  } from '@things-factory/warehouse-base'
@@ -190,7 +193,7 @@ export class PickingWorksheetController extends VasWorksheetController {
190
193
  if (vasWorksheet) {
191
194
  await this.activateVAS(vasWorksheet.name, vasWorksheet.worksheetDetails)
192
195
  }
193
- } catch (e) { }
196
+ } catch (e) {}
194
197
 
195
198
  const pendingSplitOIs: OrderInventory[] = await this.trxMgr.getRepository(OrderInventory).find({
196
199
  where: { domain: this.domain, releaseGood, status: ORDER_INVENTORY_STATUS.PENDING_SPLIT }
@@ -443,7 +446,7 @@ export class PickingWorksheetController extends VasWorksheetController {
443
446
  detail.product?.id === product.id
444
447
  )
445
448
 
446
- if (!foundProductDetail) {
449
+ if (!foundProductDetail && !product?.isRequireSerialNumberScanningOutbound) {
447
450
  const roProductDetail: ProductDetail = productDetails.find(
448
451
  (parentDetail: ProductDetail) =>
449
452
  parentDetail.packingType === packingType && parentDetail.packingSize == packingSize
@@ -453,26 +456,57 @@ export class PickingWorksheetController extends VasWorksheetController {
453
456
  if (pickedQty > releaseQty) {
454
457
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
455
458
  }
459
+ } else if (!foundProductDetail) {
460
+ throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
456
461
  }
457
462
 
458
- if (product?.isRequireSerialNumberScanning) {
459
- if (!serialNumber || serialNumber == '')
463
+ if (product?.isRequireSerialNumberScanningOutbound) {
464
+ if (!serialNumber || serialNumber == '') {
460
465
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `require serial number`))
461
-
462
- if (serialNumber) {
463
- targetInventory.serialNumber = JSON.stringify(
464
- targetInventory.serialNumber ? [...JSON.parse(targetInventory.serialNumber), serialNumber] : [serialNumber]
465
- )
466
466
  }
467
- }
468
467
 
469
- targetInventory.pickedAt = new Date()
470
- targetInventory.pickedByUser = this.user
468
+ let totalInventoryItems = await this.trxMgr.getRepository(InventoryItem).count({
469
+ where: {
470
+ inventory,
471
+ status: Not(Equal(INVENTORY_STATUS.TERMINATED))
472
+ }
473
+ })
474
+
475
+ let foundSerialNumber: InventoryItem = await this.trxMgr
476
+ .getRepository(InventoryItem)
477
+ .findOne({ where: { domain: this.domain, serialNumber: serialNumber, product } })
478
+
479
+ if (foundSerialNumber) {
480
+ if (foundSerialNumber.inventoryId !== inventory.id) {
481
+ throw new Error('Serial Number scanned is in another inventory')
482
+ }
483
+
484
+ if (foundSerialNumber.status !== INVENTORY_STATUS.STORED || foundSerialNumber.outboundOrderId) {
485
+ throw new Error('Inventory Item is not available')
486
+ }
487
+
488
+ foundSerialNumber.status = INVENTORY_STATUS.PICKED
489
+ foundSerialNumber.updater = this.user
490
+ foundSerialNumber.outboundOrderId = releaseGood.id
471
491
 
472
- let pickedBy: string[] = targetInventory.pickedBy ? (targetInventory.pickedBy).split(',') : []
473
- if (!pickedBy.find(x => x == this.user.name)) {
474
- pickedBy.push(this.user.name)
475
- targetInventory.pickedBy = pickedBy.join(',')
492
+ await this.trxMgr.getRepository(InventoryItem).save(foundSerialNumber)
493
+ } else {
494
+ if (totalInventoryItems >= inventory.qty) {
495
+ throw new Error('Insufficient inventory quantity to scan new serial number')
496
+ }
497
+
498
+ let inventoryItem: InventoryItem = new InventoryItem()
499
+ inventoryItem.name = InventoryNoGenerator.inventoryItemName()
500
+ inventoryItem.serialNumber = serialNumber
501
+ inventoryItem.status = INVENTORY_STATUS.PICKED
502
+ inventoryItem.outboundOrderId = releaseGood.id
503
+ inventoryItem.source = INVENTORY_ITEM_SOURCE.OUTBOUND
504
+ inventoryItem.product = product
505
+ inventoryItem.inventory = inventory
506
+ inventoryItem.domain = this.domain
507
+
508
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
509
+ }
476
510
  }
477
511
 
478
512
  await this.updatePickingTransaction(releaseGood, targetInventory, worksheetDetail, inventory, pickedQty)
@@ -518,32 +552,103 @@ export class PickingWorksheetController extends VasWorksheetController {
518
552
  //validation to prevent over release
519
553
  if (inventory.qty <= 0) throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
520
554
 
521
- if (inventory.palletId !== palletId)
555
+ if (inventory.palletId !== palletId /*&& !product?.isRequireSerialNumberScanningOutbound*/)
556
+ //to be changed
522
557
  throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Pallet ID', palletId, inventory.palletId))
523
558
 
524
- if (product?.isRequireSerialNumberScanning) {
525
- if (!serialNumber || serialNumber == '')
559
+ if (product?.isRequireSerialNumberScanningOutbound) {
560
+ if (!serialNumber || serialNumber == '') {
526
561
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `require serial number`))
562
+ }
527
563
 
528
- if (serialNumber) {
529
- targetInventory.serialNumber = JSON.stringify(
530
- targetInventory.serialNumber ? [...JSON.parse(targetInventory.serialNumber), serialNumber] : [serialNumber]
531
- )
564
+ let totalInventoryItems = await this.trxMgr.getRepository(InventoryItem).count({
565
+ where: {
566
+ inventory
567
+ }
568
+ })
569
+
570
+ let foundSerialNumber: InventoryItem = await this.trxMgr.getRepository(InventoryItem).findOne({
571
+ where: { domain: this.domain, serialNumber: serialNumber, product },
572
+ relations: ['product', 'inventory']
573
+ })
574
+
575
+ let scannedPalletIdInventory: Inventory = await this.trxMgr
576
+ .getRepository(Inventory)
577
+ .findOne({ where: { domain: this.domain, palletId }, relations: ['product'] })
578
+
579
+ if (foundSerialNumber) {
580
+ if (
581
+ foundSerialNumber.status !== INVENTORY_STATUS.STORED ||
582
+ foundSerialNumber.outboundOrderId ||
583
+ foundSerialNumber.inventory !== inventory
584
+ /*to be changed for replacement && inventory.palletId == palletId*/
585
+ ) {
586
+ throw new Error('Inventory Item is not available')
587
+ }
588
+
589
+ foundSerialNumber.status = INVENTORY_STATUS.PICKED
590
+ foundSerialNumber.updater = this.user
591
+ foundSerialNumber.outboundOrderId = releaseGood.id
592
+
593
+ await this.trxMgr.getRepository(InventoryItem).save(foundSerialNumber)
594
+ } else {
595
+ if (totalInventoryItems >= inventory.qty) {
596
+ throw new Error('Insufficient inventory quantity to scan new serial number')
597
+ }
598
+
599
+ let inventoryItem: InventoryItem = new InventoryItem()
600
+ inventoryItem.name = InventoryNoGenerator.inventoryItemName()
601
+ inventoryItem.serialNumber = serialNumber
602
+ inventoryItem.status = INVENTORY_STATUS.PICKED
603
+ inventoryItem.outboundOrderId = releaseGood.id
604
+ inventoryItem.product = product
605
+ inventoryItem.inventory = scannedPalletIdInventory
606
+ inventoryItem.domain = this.domain
607
+
608
+ await this.trxMgr.getRepository(InventoryItem).save(inventoryItem)
532
609
  }
533
- }
534
- targetInventory.pickedAt = new Date()
535
- targetInventory.pickedByUser = this.user;
536
610
 
537
- let pickedBy: string[] = targetInventory.pickedBy ? (targetInventory.pickedBy).split(',') : []
538
- if (!pickedBy.find(x => x == this.user.name)) {
539
- pickedBy.push(this.user.name)
540
- targetInventory.pickedBy = pickedBy.join(',')
541
- }
611
+ if (inventory.palletId !== palletId) {
612
+ let existingOrderInv = await this.trxMgr.getRepository(OrderInventory).findOne({
613
+ where: {
614
+ domain: this.domain,
615
+ inventory: scannedPalletIdInventory,
616
+ releaseGood: releaseGood
617
+ }
618
+ })
542
619
 
543
- targetInventory = await this.checkAndSetBinPicking(targetInventory, binLocation)
620
+ if (existingOrderInv) {
621
+ //if replacement order inventory already existed in worksheet detail
622
+ await this.serialNumberReplacementForExistingOrderInv(
623
+ existingOrderInv,
624
+ targetInventory,
625
+ worksheetDetail,
626
+ foundSerialNumber
627
+ )
628
+ } else if (
629
+ scannedPalletIdInventory.batchId == inventory.batchId &&
630
+ scannedPalletIdInventory.product.id == product.id &&
631
+ scannedPalletIdInventory.product.packingType == product.packingType
632
+ ) {
633
+ //if replacement order inventory does not exist
634
+ await this.serialNumberReplacement(
635
+ targetInventory,
636
+ scannedPalletIdInventory,
637
+ releaseGood,
638
+ product,
639
+ worksheetDetail,
640
+ foundSerialNumber
641
+ )
642
+ } else {
643
+ throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Pallet ID', palletId, inventory.palletId))
644
+ }
645
+ }
646
+ }
544
647
 
545
648
  await this.updatePickingTransaction(releaseGood, targetInventory, worksheetDetail, inventory, pickedQty)
546
649
 
650
+ targetInventory = await this.checkAndSetBinPicking(targetInventory, binLocation)
651
+
547
652
  const fromLocation: Location = targetInventory.inventory.location
548
653
  if (locationName) {
549
654
  const toLocation: Location = await this.trxMgr.getRepository(Location).findOne({
@@ -638,16 +743,6 @@ export class PickingWorksheetController extends VasWorksheetController {
638
743
 
639
744
  targetInventory.pickedQty = targetInventory.releaseQty
640
745
  targetInventory.status = ORDER_INVENTORY_STATUS.PICKED
641
-
642
- targetInventory.pickedAt = new Date()
643
- targetInventory.pickedByUser = this.user;
644
-
645
- let pickedBy: string[] = targetInventory.pickedBy ? (targetInventory.pickedBy).split(',') : []
646
- if (!pickedBy.find(x => x == this.user.name)) {
647
- pickedBy.push(this.user.name)
648
- targetInventory.pickedBy = pickedBy.join(',')
649
- }
650
-
651
746
  await this.updateOrderTargets([targetInventory])
652
747
 
653
748
  inventory.qty -= targetInventory.releaseQty
@@ -802,15 +897,6 @@ export class PickingWorksheetController extends VasWorksheetController {
802
897
  targetInventory.pickedQty += pickedQty > gapQtyRemaining ? gapQtyRemaining : pickedQty
803
898
  remainingAssignedQty = remainingAssignedQty < 0 ? 0 : remainingAssignedQty
804
899
 
805
- targetInventory.pickedAt = new Date()
806
- targetInventory.pickedByUser = this.user;
807
-
808
- let pickedBy: string[] = targetInventory.pickedBy ? (targetInventory.pickedBy).split(',') : []
809
- if (!pickedBy.find(x => x == this.user.name)) {
810
- pickedBy.push(this.user.name)
811
- targetInventory.pickedBy = pickedBy.join(',')
812
- }
813
-
814
900
  if (targetInventory.pickedQty == targetReleaseQty) {
815
901
  const leftQty: number = inventory.qty - targetInventory.releaseQty
816
902
  if (leftQty < 0) {
@@ -865,6 +951,28 @@ export class PickingWorksheetController extends VasWorksheetController {
865
951
  ])
866
952
  await this.checkRecordValidity(worksheet, { status: WORKSHEET_STATUS.EXECUTING })
867
953
 
954
+ let InventoryItems: InventoryItem = await this.trxMgr
955
+ .getRepository(InventoryItem)
956
+ .find({ where: { outboundOrderId: releaseGood.id } })
957
+
958
+ if (InventoryItems.length > 0) {
959
+ InventoryItems.forEach((itm: InventoryItem) => {
960
+ itm.status = INVENTORY_STATUS.TERMINATED
961
+ itm.updater = this.user
962
+ })
963
+
964
+ // let inventoryLists = InventoryItems.filter(
965
+ // (value, index, self) => index === self.findIndex(itm => itm.inventory.id === value.inventory.id)
966
+ // )
967
+
968
+ // inventoryLists.forEach((itm: Inventory) => {
969
+ // if (itm.inventory.qty - itm.releaseQty == 0)
970
+ // this.transactionInventory(itm, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.TERMINATED)
971
+ // })
972
+
973
+ await this.trxMgr.getRepository(InventoryItem).save(InventoryItems)
974
+ }
975
+
868
976
  let orderStatus: string
869
977
  if (releaseGood?.packingOption) {
870
978
  orderStatus = ORDER_STATUS.READY_TO_PACK
@@ -1025,4 +1133,277 @@ export class PickingWorksheetController extends VasWorksheetController {
1025
1133
 
1026
1134
  return orderInventory
1027
1135
  }
1136
+
1137
+ private async serialNumberReplacementForExistingOrderInv(
1138
+ existingOrderInv,
1139
+ targetInventory,
1140
+ worksheetDetail,
1141
+ foundSerialNumber
1142
+ ) {
1143
+ try {
1144
+ //1. update replacement inventory, order inventory, old inventory, old order inventory quantity
1145
+ let newInventory: Inventory = await this.trxMgr
1146
+ .getRepository(Inventory)
1147
+ .findOne({ where: { domain: this.domain, id: existingOrderInv?.inventoryId } })
1148
+
1149
+ let newOrderInventory: OrderInventory = await this.trxMgr
1150
+ .getRepository(OrderInventory)
1151
+ .findOne({ where: { domain: this.domain, id: existingOrderInv?.id } })
1152
+
1153
+ let oldInventory: Inventory = await this.trxMgr
1154
+ .getRepository(Inventory)
1155
+ .findOne({ where: { domain: this.domain, id: targetInventory?.inventory.id } })
1156
+
1157
+ let oldOrderInventory: OrderInventory = await this.trxMgr
1158
+ .getRepository(OrderInventory)
1159
+ .findOne({ where: { domain: this.domain, id: targetInventory?.id } })
1160
+
1161
+ //if replacement inventory quantity insufficient
1162
+ if (newInventory.qty - newInventory.lockedQty < targetInventory.releaseQty - targetInventory.pickedQty) {
1163
+ newOrderInventory.releaseQty += newInventory.qty - newInventory.lockedQty
1164
+ newOrderInventory.releaseUomValue += newInventory.uomValue - newInventory.lockedUomValue
1165
+
1166
+ oldOrderInventory.releaseQty -= newOrderInventory.releaseQty
1167
+ oldOrderInventory.releaseUomValue -= newOrderInventory.releaseUomValue
1168
+
1169
+ oldInventory.lockedQty -= newOrderInventory.releaseQty
1170
+ oldInventory.lockedUomValue -= newOrderInventory.releaseUomValue
1171
+
1172
+ newInventory.lockedQty = newInventory.qty
1173
+ newInventory.lockedUomValue = newInventory.uomValue
1174
+ } else {
1175
+ newOrderInventory.releaseQty += targetInventory.releaseQty - targetInventory.pickedQty
1176
+ newOrderInventory.releaseUomValue +=
1177
+ newOrderInventory.releaseQty * (targetInventory.releaseUomValue / targetInventory.releaseQty)
1178
+
1179
+ oldOrderInventory.releaseQty = targetInventory.pickedQty
1180
+ oldOrderInventory.status = INVENTORY_STATUS.PICKED
1181
+ oldOrderInventory.releaseUomValue =
1182
+ (targetInventory.releaseUomValue / targetInventory.releaseQty) * oldOrderInventory.releaseQty
1183
+
1184
+ oldInventory.lockedQty -= targetInventory.releaseQty - targetInventory.pickedQty
1185
+ oldInventory.lockedUomValue =
1186
+ oldInventory.lockedQty * (targetInventory.releaseUomValue / targetInventory.releaseQty)
1187
+
1188
+ newInventory.lockedQty = newInventory.lockedQty + (targetInventory.releaseQty - targetInventory.pickedQty)
1189
+ newInventory.lockedUomValue =
1190
+ (targetInventory.releaseUomValue / targetInventory.releaseQty) * newInventory.lockedQty
1191
+ }
1192
+
1193
+ newInventory = await this.trxMgr.getRepository(Inventory).save({ ...newInventory, updater: this.user })
1194
+
1195
+ newOrderInventory = await this.trxMgr.getRepository(OrderInventory).save({
1196
+ ...newOrderInventory,
1197
+ status: INVENTORY_STATUS.PICKING,
1198
+ pickedQty: existingOrderInv.pickedQty++,
1199
+ updater: this.user
1200
+ })
1201
+
1202
+ oldInventory = await this.trxMgr.getRepository(Inventory).save({ ...oldInventory, updater: this.user })
1203
+
1204
+ foundSerialNumber = await this.trxMgr
1205
+ .getRepository(InventoryItem)
1206
+ .save({ ...foundSerialNumber, inventory: newInventory })
1207
+
1208
+ //2. update replacement worksheet detail
1209
+ await this.trxMgr.getRepository(WorksheetDetail).update(
1210
+ {
1211
+ targetInventory: existingOrderInv
1212
+ },
1213
+ {
1214
+ status: WORKSHEET_STATUS.EXECUTING,
1215
+ updater: this.user
1216
+ }
1217
+ )
1218
+
1219
+ if (oldOrderInventory.releaseQty !== 0) {
1220
+ oldOrderInventory = await this.trxMgr
1221
+ .getRepository(OrderInventory)
1222
+ .save({ ...oldOrderInventory, updater: this.user })
1223
+
1224
+ await this.trxMgr.getRepository(WorksheetDetail).update(
1225
+ {
1226
+ name: worksheetDetail.name
1227
+ },
1228
+ {
1229
+ status: WORKSHEET_STATUS.DONE,
1230
+ updater: this.user
1231
+ }
1232
+ )
1233
+ } else {
1234
+ await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1235
+ await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetail.ild)
1236
+ }
1237
+ } catch (e) {}
1238
+ }
1239
+
1240
+ private async serialNumberReplacement(
1241
+ targetInventory,
1242
+ scannedPalletIdInventory,
1243
+ releaseGood,
1244
+ product,
1245
+ worksheetDetail,
1246
+ foundSerialNumber
1247
+ ) {
1248
+ try {
1249
+ //1. create new inventory, new order inventory, update old inventory, old order inventory quantity
1250
+ let newInventory: Inventory = await this.trxMgr
1251
+ .getRepository(Inventory)
1252
+ .findOne({ where: { id: scannedPalletIdInventory?.id } })
1253
+
1254
+ let oldInventory: Inventory = await this.trxMgr
1255
+ .getRepository(Inventory)
1256
+ .findOne({ where: { domain: this.domain, id: targetInventory?.inventory.id } })
1257
+
1258
+ let oldOrderInventory: OrderInventory = await this.trxMgr
1259
+ .getRepository(OrderInventory)
1260
+ .findOne({ where: { domain: this.domain, id: targetInventory?.id } })
1261
+
1262
+ let newOrderInventoryReleaseQty = 0
1263
+ let newOrderInventoryReleaseUomValue = 0
1264
+
1265
+ //if replacement inventory quantity insufficient
1266
+ if (newInventory.qty - newInventory.lockedQty < targetInventory.releaseQty - targetInventory.pickedQty) {
1267
+ newOrderInventoryReleaseQty = newInventory.qty - newInventory.lockedQty
1268
+ newOrderInventoryReleaseUomValue = newInventory.uomValue - newInventory.lockedUomValue
1269
+
1270
+ oldOrderInventory.releaseQty -= newOrderInventoryReleaseQty
1271
+ oldOrderInventory.releaseUomValue -= newOrderInventoryReleaseUomValue
1272
+
1273
+ oldInventory.lockedQty -= newOrderInventoryReleaseQty
1274
+ oldInventory.lockedUomValue -= newOrderInventoryReleaseUomValue
1275
+
1276
+ newInventory.lockedQty = newInventory.qty
1277
+ newInventory.lockedUomValue = newInventory.uomValue
1278
+ } else {
1279
+ newOrderInventoryReleaseQty = targetInventory.releaseQty - targetInventory.pickedQty
1280
+ newOrderInventoryReleaseUomValue =
1281
+ newOrderInventoryReleaseQty * (targetInventory.releaseUomValue / targetInventory.releaseQty)
1282
+
1283
+ oldOrderInventory.releaseQty = targetInventory.pickedQty
1284
+ oldOrderInventory.status = INVENTORY_STATUS.PICKED
1285
+ oldOrderInventory.releaseUomValue =
1286
+ (targetInventory.releaseUomValue / targetInventory.releaseQty) * oldOrderInventory.releaseQty
1287
+
1288
+ oldInventory.lockedQty -= newOrderInventoryReleaseQty
1289
+ oldInventory.lockedUomValue -= newOrderInventoryReleaseUomValue
1290
+
1291
+ newInventory.lockedQty = newInventory.lockedQty + (targetInventory.releaseQty - targetInventory.pickedQty)
1292
+ newInventory.lockedUomValue =
1293
+ (targetInventory.releaseUomValue / targetInventory.releaseQty) * newInventory.lockedQty
1294
+ }
1295
+
1296
+ newInventory = await this.trxMgr.getRepository(Inventory).save({ ...newInventory, updater: this.user })
1297
+
1298
+ let newTargetInventory = (({ id, ...targetInventory }) => targetInventory)(targetInventory)
1299
+
1300
+ let newOrderInventory = await this.trxMgr.getRepository(OrderInventory).save({
1301
+ ...newTargetInventory,
1302
+ domain: this.domain,
1303
+ name: OrderNoGenerator.orderInventory(),
1304
+ releaseGood,
1305
+ releaseQty: newOrderInventoryReleaseQty,
1306
+ releaseUomValue: newOrderInventoryReleaseUomValue,
1307
+ pickedQty: 1,
1308
+ product,
1309
+ inventory: scannedPalletIdInventory,
1310
+ creator: this.user,
1311
+ updater: this.user
1312
+ })
1313
+
1314
+ oldInventory = await this.trxMgr.getRepository(Inventory).save({ ...oldInventory, updater: this.user })
1315
+
1316
+ foundSerialNumber = await this.trxMgr
1317
+ .getRepository(InventoryItem)
1318
+ .save({ ...foundSerialNumber, inventory: newInventory })
1319
+
1320
+ //3. create new worksheet detail
1321
+ let NewWorksheetDetail = (({ id, ...worksheetDetail }) => worksheetDetail)(worksheetDetail)
1322
+ await this.trxMgr.getRepository(WorksheetDetail).save({
1323
+ ...NewWorksheetDetail,
1324
+ domain: this.domain,
1325
+ name: WorksheetNoGenerator.pickingDetail(),
1326
+ targetInventory: newOrderInventory,
1327
+ status: WORKSHEET_STATUS.EXECUTING,
1328
+ creator: this.user,
1329
+ updater: this.user
1330
+ })
1331
+
1332
+ //if old order inventory release quantity is 0 then delete
1333
+ if (oldOrderInventory.releaseQty !== 0) {
1334
+ oldOrderInventory = await this.trxMgr
1335
+ .getRepository(OrderInventory)
1336
+ .save({ ...oldOrderInventory, updater: this.user })
1337
+
1338
+ //4. update old worksheet detail
1339
+ worksheetDetail = await this.trxMgr.getRepository(WorksheetDetail).update(
1340
+ {
1341
+ name: worksheetDetail.name
1342
+ },
1343
+ {
1344
+ status: WORKSHEET_STATUS.DONE,
1345
+ updater: this.user
1346
+ }
1347
+ )
1348
+ } else {
1349
+ await this.trxMgr.getRepository(OrderInventory).delete(targetInventory.id)
1350
+ await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetail.id)
1351
+ }
1352
+ } catch (e) {}
1353
+ }
1354
+
1355
+ async undoSerialNumberPicking(worksheetDetailName: string, inventoryItemId: string): Promise<void> {
1356
+ const worksheetDetail: WorksheetDetail = await this.trxMgr.getRepository(WorksheetDetail).findOne({
1357
+ where: { name: worksheetDetailName, domain: this.domain, status: Not(Equal(WORKSHEET_STATUS.DEACTIVATED)) },
1358
+ relations: [
1359
+ 'worksheet',
1360
+ 'worksheet.releaseGood',
1361
+ 'targetInventory',
1362
+ 'targetInventory.product',
1363
+ 'targetInventory.inventory'
1364
+ ]
1365
+ })
1366
+
1367
+ let targetInventory: OrderInventory = worksheetDetail.targetInventory
1368
+
1369
+ if (targetInventory.releaseQty == targetInventory.pickedQty && targetInventory.status == INVENTORY_STATUS.PICKED) {
1370
+ targetInventory.status = INVENTORY_STATUS.PICKING
1371
+
1372
+ await this.trxMgr
1373
+ .getRepository(WorksheetDetail)
1374
+ .update({ id: worksheetDetail.id }, { status: WORKSHEET_STATUS.EXECUTING })
1375
+
1376
+ targetInventory.inventory.qty += targetInventory.releaseQty
1377
+ targetInventory.inventory.uomValue =
1378
+ Math.round((targetInventory.inventory.uomValue + targetInventory.releaseUomValue) * 100) / 100
1379
+ targetInventory.inventory.lockedQty = targetInventory.inventory.lockedQty + targetInventory.releaseQty
1380
+ targetInventory.inventory.lockedUomValue =
1381
+ Math.round((targetInventory.inventory.lockedUomValue + targetInventory.releaseUomValue) * 100) / 100
1382
+
1383
+ await this.trxMgr.getRepository(Inventory).save(targetInventory.inventory)
1384
+ }
1385
+
1386
+ let removeInventoryItem: InventoryItem = await this.trxMgr
1387
+ .getRepository(InventoryItem)
1388
+ .findOne({ where: { id: inventoryItemId } })
1389
+
1390
+ if (removeInventoryItem.source == 'OUTBOUND') {
1391
+ await this.trxMgr.getRepository(InventoryItem).delete(removeInventoryItem.id)
1392
+ } else {
1393
+ await this.trxMgr.getRepository(InventoryItem).update(
1394
+ {
1395
+ id: inventoryItemId
1396
+ },
1397
+ {
1398
+ status: INVENTORY_STATUS.STORED,
1399
+ outboundOrderId: null,
1400
+ updater: this.user
1401
+ }
1402
+ )
1403
+ }
1404
+
1405
+ targetInventory.pickedQty--
1406
+ targetInventory.updater = this.user
1407
+ await this.updateOrderTargets([targetInventory])
1408
+ }
1028
1409
  }
@@ -1,17 +1,11 @@
1
1
  import FormData from 'form-data'
2
2
  import fetch from 'node-fetch'
3
- import {
4
- getRepository,
5
- SelectQueryBuilder
6
- } from 'typeorm'
7
-
8
- import {
9
- Attachment,
10
- STORAGE
11
- } from '@things-factory/attachment-base'
3
+ import { getRepository, SelectQueryBuilder } from 'typeorm'
4
+
5
+ import { Attachment, STORAGE } from '@things-factory/attachment-base'
12
6
  import { Bizplace } from '@things-factory/biz-base'
13
7
  import { config } from '@things-factory/env'
14
- import { ReleaseGood } from '@things-factory/sales-base'
8
+ import { InvoiceProduct, ReleaseGood } from '@things-factory/sales-base'
15
9
  import { Domain } from '@things-factory/shell'
16
10
 
17
11
  import { TEMPLATE_TYPE } from '../constants'
@@ -28,31 +22,24 @@ export async function renderInvoices({ req, timezoneOffSet }, context: any) {
28
22
  let result = await Promise.all(
29
23
  req.roIds.map(async roId => {
30
24
  try {
31
- const qb: SelectQueryBuilder<ReleaseGood> = getRepository(ReleaseGood)
25
+ const qb: SelectQueryBuilder<ReleaseGood> = await getRepository(ReleaseGood)
32
26
  .createQueryBuilder('rg')
33
27
  .innerJoinAndSelect('rg.domain', 'domain')
34
28
  .innerJoinAndSelect('rg.bizplace', 'bizplace')
35
29
  .innerJoinAndSelect('bizplace.domain', 'bizplace_domain')
36
30
  .innerJoinAndSelect('bizplace.company', 'company')
37
31
  .innerJoinAndSelect('company.domain', 'company_domain')
38
- .innerJoinAndSelect('invoices', 'iv', 'rg.id = iv.release_good_id')
39
- .innerJoinAndSelect('iv.invoiceProducts', 'ip')
32
+ .innerJoinAndSelect('invoices', 'iv', 'rg.ref_no = iv.ref_no_1')
40
33
  .leftJoinAndSelect('marketplace_orders', 'mo', 'rg.id = mo.release_order_id::uuid')
41
- .leftJoinAndSelect('mo.marketplaceOrderItems', 'moi')
42
- .leftJoinAndSelect('marketplace_product_variations', 'mpv', 'moi.marketplace_product_variation_id = mpv.id')
43
- .leftJoinAndSelect('products', 'p', 'mpv.sku = p.sku and p.domain_id = company.domain_id')
44
34
  .leftJoinAndSelect('marketplace_order_shippings', 'mos', 'rg.id = mos.release_order_id::uuid')
45
35
  .leftJoinAndSelect('mo.fulfillmentCenter', 'fc')
46
36
  .where('rg.id = :roId')
47
- .andWhere('ip.sku = p.sku')
48
37
  .andWhere('rg.domain = :domainId')
49
38
  .setParameters({ roId, domainId: domain.id })
50
39
 
51
- let items: any[] = await qb.getRawMany()
52
-
53
- if (items.length) {
54
- let record: any = items[0]
40
+ let record: any = await qb.getRawOne()
55
41
 
42
+ if (record) {
56
43
  const partnerBiz: Partial<Bizplace> = {
57
44
  id: record.bizplace_id,
58
45
  name: record.bizplace_name,
@@ -86,6 +73,16 @@ export async function renderInvoices({ req, timezoneOffSet }, context: any) {
86
73
  record.iv_delivery_address_5
87
74
  ]
88
75
 
76
+ const qb: SelectQueryBuilder<InvoiceProduct> = await getRepository(InvoiceProduct)
77
+ .createQueryBuilder('ip')
78
+ .innerJoin('invoices', 'iv', 'iv.id = ip.invoice_id')
79
+ .leftJoin('release_goods', 'rg', 'rg.ref_no = iv.ref_no_1')
80
+ .where('rg.id = :roId')
81
+ .andWhere('rg.domain = :domainId')
82
+ .setParameters({ roId, domainId: domain.id })
83
+
84
+ let items: any[] = await qb.getRawMany()
85
+
89
86
  const product_list = items.map((item, idx) => {
90
87
  return {
91
88
  list_no: idx + 1,
@@ -100,9 +97,9 @@ export async function renderInvoices({ req, timezoneOffSet }, context: any) {
100
97
  (item.ip_paid_price || item.ip_unit_price) * parseInt(item.ip_qty || 0)
101
98
  ),
102
99
  product_total_unit_price: getRoundedValue(item.ip_unit_price * parseInt(item.ip_qty || 0)),
103
- original_price: getRoundedValue(parseFloat(item.moi_original_price || 0)),
104
- product_discount: getRoundedValue(parseFloat(item.moi_discount || 0)),
105
- shipping_fee_paid_by_customer: getRoundedValue(parseFloat(item.moi_shipping_fee_paid_by_customer || 0))
100
+ original_price: getRoundedValue(parseFloat(item.ip_unit_price || 0)),
101
+ product_discount: getRoundedValue(parseFloat(item.ip_discount || 0)),
102
+ shipping_fee_paid_by_customer: getRoundedValue(parseFloat(item.ip_shipping_fee_paid_by_customer || 0))
106
103
  }
107
104
  })
108
105
 
@@ -165,8 +162,8 @@ export async function renderInvoices({ req, timezoneOffSet }, context: any) {
165
162
  sub_total: sumProductTotalPaidPrice,
166
163
  grand_total: getRoundedValue(
167
164
  sumProductTotalPaidPrice -
168
- parseFloat(record.mo_voucher_amount || 0) +
169
- parseFloat(record.mos_actual_shipping_fee || 0)
165
+ parseFloat(record.mo_voucher_amount || 0) +
166
+ parseFloat(record.mos_actual_shipping_fee || 0)
170
167
  ),
171
168
  product_list
172
169
  }