@things-factory/worksheet-base 3.7.1 → 3.7.6

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 (46) hide show
  1. package/dist-server/controllers/ecommerce/sellercraft-controller.js +3 -3
  2. package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
  3. package/dist-server/controllers/inbound/unloading-worksheet-controller.js +48 -25
  4. package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/outbound/loading-worksheet-controller.js +4 -0
  6. package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/outbound/picking-worksheet-controller.js +121 -67
  8. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/worksheet-controller.js +27 -2
  10. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  11. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js +27 -2
  12. package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js.map +1 -1
  13. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +26 -0
  14. package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
  15. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +27 -5
  16. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  17. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js +72 -0
  18. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js.map +1 -0
  19. package/dist-server/graphql/resolvers/worksheet/picking/index.js +2 -1
  20. package/dist-server/graphql/resolvers/worksheet/picking/index.js.map +1 -1
  21. package/dist-server/graphql/resolvers/worksheet/picking/picking.js +4 -4
  22. package/dist-server/graphql/resolvers/worksheet/picking/picking.js.map +1 -1
  23. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +86 -57
  24. package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
  25. package/dist-server/graphql/resolvers/worksheet/unloading-return-worksheet.js +2 -2
  26. package/dist-server/graphql/resolvers/worksheet/unloading-return-worksheet.js.map +1 -1
  27. package/dist-server/graphql/types/worksheet/index.js +5 -1
  28. package/dist-server/graphql/types/worksheet/index.js.map +1 -1
  29. package/dist-server/utils/inventory-util.js +29 -2
  30. package/dist-server/utils/inventory-util.js.map +1 -1
  31. package/package.json +16 -16
  32. package/server/controllers/ecommerce/sellercraft-controller.ts +3 -3
  33. package/server/controllers/inbound/unloading-worksheet-controller.ts +67 -30
  34. package/server/controllers/outbound/loading-worksheet-controller.ts +20 -0
  35. package/server/controllers/outbound/picking-worksheet-controller.ts +148 -83
  36. package/server/controllers/worksheet-controller.ts +40 -2
  37. package/server/graphql/resolvers/worksheet/loading-worksheet.ts +33 -4
  38. package/server/graphql/resolvers/worksheet/packing-worksheet.ts +31 -3
  39. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +37 -5
  40. package/server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.ts +78 -0
  41. package/server/graphql/resolvers/worksheet/picking/index.ts +3 -1
  42. package/server/graphql/resolvers/worksheet/picking/picking.ts +5 -4
  43. package/server/graphql/resolvers/worksheet/picking-worksheet.ts +102 -62
  44. package/server/graphql/resolvers/worksheet/unloading-return-worksheet.ts +6 -4
  45. package/server/graphql/types/worksheet/index.ts +5 -1
  46. package/server/utils/inventory-util.ts +31 -7
@@ -17,7 +17,8 @@ import {
17
17
  INVENTORY_STATUS,
18
18
  INVENTORY_TRANSACTION_TYPE,
19
19
  Location,
20
- LOCATION_TYPE
20
+ LOCATION_TYPE,
21
+ LOCATION_STATUS
21
22
  } from '@things-factory/warehouse-base'
22
23
 
23
24
  import { TASK_NUMBER_RULE_TYPE, TASK_NUMBER_SETTING_KEY, WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
@@ -190,7 +191,7 @@ export class PickingWorksheetController extends VasWorksheetController {
190
191
  if (vasWorksheet) {
191
192
  await this.activateVAS(vasWorksheet.name, vasWorksheet.worksheetDetails)
192
193
  }
193
- } catch (e) {}
194
+ } catch (e) { }
194
195
 
195
196
  const pendingSplitOIs: OrderInventory[] = await this.trxMgr.getRepository(OrderInventory).find({
196
197
  where: { domain: this.domain, releaseGood, status: ORDER_INVENTORY_STATUS.PENDING_SPLIT }
@@ -388,104 +389,138 @@ export class PickingWorksheetController extends VasWorksheetController {
388
389
  cartonId: string,
389
390
  binLocation?: string
390
391
  ): Promise<void> {
391
- let worksheetDetail: WorksheetDetail = await this.findExecutableWorksheetDetailByName(
392
- worksheetDetailName,
393
- worksheetType,
394
- [
395
- 'worksheet',
396
- 'worksheet.bizplace',
397
- 'targetInventory',
398
- 'targetInventory.releaseGood',
399
- 'targetInventory.inventory',
400
- 'targetInventory.product',
401
- 'targetInventory.product.productDetails',
402
- 'targetInventory.product.productDetails.product',
403
- 'targetInventory.product.productDetails.childProductDetail'
404
- ]
405
- )
392
+ try {
393
+ let worksheetDetail: WorksheetDetail = await this.findExecutableWorksheetDetailByName(
394
+ worksheetDetailName,
395
+ worksheetType,
396
+ [
397
+ 'worksheet',
398
+ 'worksheet.bizplace',
399
+ 'targetInventory',
400
+ 'targetInventory.releaseGood',
401
+ 'targetInventory.inventory',
402
+ 'targetInventory.product',
403
+ 'targetInventory.product.productDetails',
404
+ 'targetInventory.product.productDetails.product',
405
+ 'targetInventory.product.productDetails.childProductDetail'
406
+ ]
407
+ )
406
408
 
407
- const releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
408
- let targetInventory: OrderInventory = worksheetDetail.targetInventory
409
- const product: Product = targetInventory.product
410
- let inventory: Inventory = targetInventory.inventory
411
- const packingType: string = inventory.packingType
412
- const packingSize: number = inventory.packingSize
409
+ const releaseGood: ReleaseGood = worksheetDetail.targetInventory.releaseGood
410
+ let targetInventory: OrderInventory = worksheetDetail.targetInventory
411
+ const product: Product = targetInventory.product
412
+ let inventory: Inventory = targetInventory.inventory
413
413
 
414
- let pickedQty: number = 1
415
- const releaseQty: number = targetInventory.releaseQty
414
+ //validation to prevent over release
415
+ if (inventory.qty <= 0)
416
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
416
417
 
417
- if (inventory.cartonId !== cartonId)
418
- throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Carton ID', cartonId, inventory.cartonId))
418
+ const packingType: string = inventory.packingType
419
+ const packingSize: number = inventory.packingSize
419
420
 
420
- // search for matching product barcode
421
- const productDetails: ProductDetail[] = product?.productDetails.filter(detail => !detail.deletedAt)
422
- const isMatchingBarcode: boolean = productDetails.map(detail => detail.gtin).includes(productBarcode)
423
- if (!isMatchingBarcode) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
421
+ let pickedQty: number = 1
422
+ const releaseQty: number = targetInventory.releaseQty
424
423
 
425
- // case for scanning parent packing type, packing size
426
- const foundProductDetail: ProductDetail = productDetails.find(
427
- (detail: ProductDetail) =>
428
- detail.gtin === productBarcode &&
429
- detail.packingType === packingType &&
430
- detail.packingSize == packingSize &&
431
- detail.product?.id === product.id
432
- )
424
+ // bin picking validation
425
+ const binPickingSetting: Setting = await this.trxMgr.getRepository(Setting).findOne({
426
+ where: {
427
+ domain: this.domain,
428
+ name: 'enable-bin-picking'
429
+ }
430
+ })
431
+ if (binPickingSetting != undefined && (binPickingSetting.value).toLowerCase() == 'true') {
432
+ if (binLocation) {
433
+ const foundBinLocation: Location = await this.trxMgr.getRepository(Location).findOne({
434
+ where: { domain: this.domain, name: binLocation, type: LOCATION_TYPE.BIN }
435
+ })
433
436
 
434
- if (!foundProductDetail) {
435
- const roProductDetail: ProductDetail = productDetails.find(
436
- (parentDetail: ProductDetail) =>
437
- parentDetail.packingType === packingType && parentDetail.packingSize == packingSize
438
- )
437
+ if (!foundBinLocation)
438
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `invalid bin location id`))
439
439
 
440
- pickedQty = await this.getChildQty(productDetails, productBarcode, roProductDetail)
441
- if (pickedQty > releaseQty) {
442
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
443
- }
444
- }
440
+ targetInventory.binLocation = foundBinLocation
445
441
 
446
- targetInventory.pickedQty = Boolean(targetInventory?.pickedQty) ? targetInventory.pickedQty + pickedQty : pickedQty
447
- if (targetInventory.pickedQty == releaseQty) {
448
- const leftQty: number = inventory.qty - releaseQty
449
- if (leftQty < 0) {
450
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `quantity can't exceed limitation`))
442
+ //// Temporarily disable Bin Usage Tracking
443
+ // await this.trxMgr.getRepository(Location).update(
444
+ // { domain: this.domain, name: binLocation, type: LOCATION_TYPE.BIN },
445
+ // { status: LOCATION_STATUS.OCCUPIED }
446
+ // )
447
+ } else {
448
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `invalid bin location id`))
449
+ }
451
450
  }
452
451
 
453
- targetInventory.status = ORDER_INVENTORY_STATUS.PICKED
454
-
455
- if (binLocation) {
456
- const foundBinLocation: Location = await this.trxMgr.getRepository(Location).findOne({
457
- where: { domain: this.domain, name: binLocation, type: LOCATION_TYPE.BIN }
458
- })
452
+ if (inventory.cartonId !== cartonId)
453
+ throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Carton ID', cartonId, inventory.cartonId))
454
+
455
+ // search for matching product barcode
456
+ const productDetails: ProductDetail[] = product?.productDetails.filter(detail => !detail.deletedAt)
457
+ const isMatchingBarcode: boolean = productDetails.map(detail => detail.gtin).includes(productBarcode)
458
+ if (!isMatchingBarcode) throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
459
+
460
+ // case for scanning parent packing type, packing size
461
+ const foundProductDetail: ProductDetail = productDetails.find(
462
+ (detail: ProductDetail) =>
463
+ detail.gtin === productBarcode &&
464
+ detail.packingType === packingType &&
465
+ detail.packingSize == packingSize &&
466
+ detail.product?.id === product.id
467
+ )
459
468
 
460
- if (!foundBinLocation)
461
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `invalid bin location id`))
469
+ if (!foundProductDetail) {
470
+ const roProductDetail: ProductDetail = productDetails.find(
471
+ (parentDetail: ProductDetail) =>
472
+ parentDetail.packingType === packingType && parentDetail.packingSize == packingSize
473
+ )
462
474
 
463
- targetInventory.binLocation = foundBinLocation
475
+ pickedQty = await this.getChildQty(productDetails, productBarcode, roProductDetail)
476
+ if (pickedQty > releaseQty) {
477
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
478
+ }
464
479
  }
465
- await this.updateOrderTargets([targetInventory])
480
+ console.log('')
466
481
 
467
- inventory.qty -= targetInventory.releaseQty
468
- inventory.uomValue = Math.round((inventory.uomValue - targetInventory.releaseUomValue) * 100) / 100
469
- inventory.lockedQty = inventory.lockedQty - targetInventory.releaseQty
470
- inventory.lockedUomValue = Math.round((inventory.lockedUomValue - targetInventory.releaseUomValue) * 100) / 100
471
- inventory = await this.transactionInventory(
472
- inventory,
473
- releaseGood,
474
- -targetInventory.releaseQty,
475
- -targetInventory.releaseUomValue,
476
- INVENTORY_TRANSACTION_TYPE.PICKING
477
- )
482
+ targetInventory.pickedQty = Boolean(targetInventory?.pickedQty) ? targetInventory.pickedQty + pickedQty : pickedQty
483
+ if (targetInventory.pickedQty == releaseQty) {
484
+ const leftQty: number = inventory.qty - releaseQty
485
+ if (leftQty < 0) {
486
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `quantity can't exceed limitation`))
487
+ }
478
488
 
479
- worksheetDetail.status = WORKSHEET_STATUS.DONE
480
- worksheetDetail.updater = this.user
481
- await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetail)
489
+ targetInventory.status = ORDER_INVENTORY_STATUS.PICKED
490
+
491
+ inventory.qty -= targetInventory.releaseQty
492
+ inventory.uomValue = Math.round((inventory.uomValue - targetInventory.releaseUomValue) * 100) / 100
493
+ inventory.lockedQty = inventory.lockedQty - targetInventory.releaseQty
494
+ inventory.lockedUomValue = Math.round((inventory.lockedUomValue - targetInventory.releaseUomValue) * 100) / 100
495
+ inventory = await this.transactionInventory(
496
+ inventory,
497
+ releaseGood,
498
+ -targetInventory.releaseQty,
499
+ -targetInventory.releaseUomValue,
500
+ INVENTORY_TRANSACTION_TYPE.PICKING
501
+ )
482
502
 
483
- if (leftQty === 0) {
484
- inventory.status = INVENTORY_STATUS.TERMINATED
485
- await this.transactionInventory(inventory, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.TERMINATED)
503
+ worksheetDetail.status = WORKSHEET_STATUS.DONE
504
+ worksheetDetail.updater = this.user
505
+ await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetail)
506
+
507
+ if (leftQty === 0) {
508
+ inventory.status = INVENTORY_STATUS.TERMINATED
509
+ await this.transactionInventory(inventory, releaseGood, 0, 0, INVENTORY_TRANSACTION_TYPE.TERMINATED)
510
+ }
486
511
  }
487
- } else {
512
+
513
+ //validation to prevent duplicated picking
514
+ let oiValidate: OrderInventory = await this.trxMgr.getRepository(OrderInventory).findOne({
515
+ where: { domain: this.domain, id: targetInventory.id, status: ORDER_INVENTORY_STATUS.PICKING }
516
+ })
517
+ if (!oiValidate)
518
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`))
519
+
488
520
  await this.updateOrderTargets([targetInventory])
521
+
522
+ } catch (error) {
523
+ throw error
489
524
  }
490
525
  }
491
526
 
@@ -494,7 +529,8 @@ export class PickingWorksheetController extends VasWorksheetController {
494
529
  worksheetType: string,
495
530
  palletId: string,
496
531
  locationName: string,
497
- releaseQty: number
532
+ releaseQty: number,
533
+ binLocation?: string
498
534
  ): Promise<void> {
499
535
  let worksheetDetail: WorksheetDetail = await this.findExecutableWorksheetDetailByName(
500
536
  worksheetDetailName,
@@ -518,6 +554,35 @@ export class PickingWorksheetController extends VasWorksheetController {
518
554
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `quantity can't exceed limitation`))
519
555
  }
520
556
 
557
+
558
+ // bin picking validation
559
+ const binPickingSetting: Setting = await this.trxMgr.getRepository(Setting).findOne({
560
+ where: {
561
+ domain: this.domain,
562
+ name: 'enable-bin-picking'
563
+ }
564
+ })
565
+ if (binPickingSetting != undefined && (binPickingSetting.value).toLowerCase() == 'true') {
566
+ if (binLocation) {
567
+ const foundBinLocation: Location = await this.trxMgr.getRepository(Location).findOne({
568
+ where: { domain: this.domain, name: binLocation, type: LOCATION_TYPE.BIN }
569
+ })
570
+
571
+ if (!foundBinLocation)
572
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `invalid bin location id`))
573
+
574
+ targetInventory.binLocation = foundBinLocation
575
+
576
+ //// Temporarily disable Bin Usage Tracking
577
+ // await this.trxMgr.getRepository(Location).update(
578
+ // { domain: this.domain, name: binLocation, type: LOCATION_TYPE.BIN },
579
+ // { status: LOCATION_STATUS.OCCUPIED }
580
+ // )
581
+ } else {
582
+ throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `invalid bin location id`))
583
+ }
584
+ }
585
+
521
586
  targetInventory.pickedQty = releaseQty
522
587
  targetInventory.status = ORDER_INVENTORY_STATUS.PICKED
523
588
  await this.updateOrderTargets([targetInventory])
@@ -555,6 +555,44 @@ export class WorksheetController {
555
555
  return worksheet
556
556
  }
557
557
 
558
+ // @chernhaoee I think the naming of this function is not proper. Seems like it should be something like "updateLoadingWorksheet" since the logic targets only Loading Order Target
559
+ async updateWorksheet(
560
+ worksheetType: string,
561
+ refOrder: ReferenceOrderType,
562
+ worksheet: Worksheet,
563
+ orderTargets: OrderTargetTypes[],
564
+ refOrderStatus: string,
565
+ orderTargetStatus: string,
566
+ ): Promise<Worksheet> {
567
+ let newOrderTarget = []
568
+
569
+ orderTargets.forEach((orderTarget: OrderTargetTypes) => {
570
+ orderTarget.status = orderTargetStatus
571
+ })
572
+ orderTargets = await this.updateOrderTargets(orderTargets)
573
+
574
+ for (let orderTarget of orderTargets) {
575
+ try {
576
+ await this.findWorksheetDetail({
577
+ targetInventory: orderTarget.id,
578
+ type: WORKSHEET_TYPE.LOADING
579
+ })
580
+ } catch (e) {
581
+ newOrderTarget.push(orderTarget)
582
+ }
583
+ }
584
+
585
+ worksheet.worksheetDetails = await this.createWorksheetDetails(worksheet, worksheetType, newOrderTarget)
586
+
587
+ // find worksheet details that doesnt exist based on order inventory
588
+ //worksheet.worksheetDetails = await this.findWorksheetDetail(worksheet.id)
589
+
590
+ refOrder.status = refOrderStatus
591
+ await this.updateRefOrder(refOrder)
592
+
593
+ return worksheet
594
+ }
595
+
558
596
  async generateBatchWorksheet(
559
597
  worksheetType: string,
560
598
  batchPickingWorksheet: Worksheet,
@@ -928,13 +966,13 @@ export class WorksheetController {
928
966
  )
929
967
  if (!currentProductDetail)
930
968
  throw new Error(this.ERROR_MSG.FIND.NOT_MATCH('inner pack', `GTIN (${productBarcode})`))
931
- childQty = scannedProductDetail.childQty
969
+ childQty = scannedProductDetail.packingSize
932
970
  } else {
933
971
  throw new Error(this.ERROR_MSG.FIND.NO_RESULT(productBarcode))
934
972
  }
935
973
 
936
974
  if (hasMatchingChild) {
937
- childQty = scannedProductDetail.childQty
975
+ childQty = scannedProductDetail.packingSize
938
976
  } else {
939
977
  while (hasChildRelation && !hasMatchingChild) {
940
978
  hasChildRelation = Boolean(currentProductDetail?.childProductDetail)
@@ -1,7 +1,9 @@
1
- import { OrderInventory, ReleaseGood } from '@things-factory/sales-base'
1
+ import { Equal, getRepository, In, Not } from 'typeorm'
2
+
3
+ import { ORDER_INVENTORY_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
2
4
  import { Domain } from '@things-factory/shell'
3
- import { Inventory } from '@things-factory/warehouse-base'
4
- import { Equal, getRepository, Not } from 'typeorm'
5
+ import { Inventory, Location } from '@things-factory/warehouse-base'
6
+
5
7
  import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../constants'
6
8
  import { Worksheet, WorksheetDetail } from '../../../entities'
7
9
  import { fetchExecutingWorksheet } from '../../../utils'
@@ -9,11 +11,37 @@ import { fetchExecutingWorksheet } from '../../../utils'
9
11
  export const loadingWorksheetResolver = {
10
12
  async loadingWorksheet(_: any, { releaseGoodNo }, context: any) {
11
13
  const { domain }: { domain: Domain } = context.state
12
- const releaseGood: ReleaseGood = await getRepository(ReleaseGood).findOne({
14
+ let releaseGood: ReleaseGood = await getRepository(ReleaseGood).findOne({
13
15
  where: { domain, name: releaseGoodNo /*status: ORDER_STATUS.LOADING*/ },
14
16
  relations: ['bizplace']
15
17
  })
16
18
 
19
+ // Find Release Order based on Bin
20
+ if (!releaseGood) {
21
+ const binLocation: Location = await getRepository(Location).findOne({
22
+ where: { domain, name: releaseGoodNo }
23
+ })
24
+
25
+ const orderInventoryByBin: OrderInventory = await getRepository(OrderInventory).findOne({
26
+ where: {
27
+ domain, binLocation, status: In([ORDER_INVENTORY_STATUS.LOADING, ORDER_INVENTORY_STATUS.LOADED])
28
+ },
29
+ order: {
30
+ createdAt: 'ASC'
31
+ },
32
+ relations: [
33
+ 'releaseGood',
34
+ 'releaseGood.bizplace',
35
+ 'releaseGood.bizplace.domain'
36
+ ]
37
+ })
38
+
39
+ if (orderInventoryByBin?.releaseGood) {
40
+ releaseGoodNo = orderInventoryByBin.releaseGood.name
41
+ releaseGood = orderInventoryByBin.releaseGood
42
+ }
43
+ }
44
+
17
45
  if (!releaseGood) throw new Error(`Release good doesn't exists.`)
18
46
 
19
47
  const foundWorksheet: Worksheet = await fetchExecutingWorksheet(
@@ -40,6 +68,7 @@ export const loadingWorksheetResolver = {
40
68
 
41
69
  return {
42
70
  worksheetInfo: {
71
+ releaseGood,
43
72
  bizplaceName: releaseGood.bizplace.name,
44
73
  startedAt: foundWorksheet.startedAt,
45
74
  refNo: releaseGood.refNo,
@@ -1,11 +1,11 @@
1
- import { EntityManager } from 'typeorm'
1
+ import { EntityManager, In } from 'typeorm'
2
2
 
3
3
  import { User } from '@things-factory/auth-base'
4
4
  import { Sellercraft, SellercraftStatus } from '@things-factory/integration-sellercraft'
5
5
  import { MarketplaceOrder, MarketplaceOrderItem, MarketplaceOrderShipping } from '@things-factory/marketplace-base'
6
- import { OrderInventory, ReleaseGood } from '@things-factory/sales-base'
6
+ import { ORDER_INVENTORY_STATUS, OrderInventory, ReleaseGood } from '@things-factory/sales-base'
7
7
  import { Domain } from '@things-factory/shell'
8
- import { Inventory } from '@things-factory/warehouse-base'
8
+ import { Inventory, Location } from '@things-factory/warehouse-base'
9
9
 
10
10
  import { WORKSHEET_TYPE } from '../../../constants'
11
11
  import { SellercraftController } from '../../../controllers'
@@ -23,7 +23,34 @@ export const packingWorksheetResolver = {
23
23
  relations: ['bizplace', 'bizplace.domain']
24
24
  })
25
25
 
26
+ // Find Release Order based on Bin
27
+ if (!releaseGood) {
28
+ const binLocation: Location = await tx.getRepository(Location).findOne({
29
+ where: { domain, name: releaseGoodNo }
30
+ })
31
+
32
+ const orderInventoryByBin: OrderInventory = await tx.getRepository(OrderInventory).findOne({
33
+ where: {
34
+ domain, binLocation, status: In([ORDER_INVENTORY_STATUS.PACKING, ORDER_INVENTORY_STATUS.PACKED])
35
+ },
36
+ order: {
37
+ createdAt: 'ASC'
38
+ },
39
+ relations: [
40
+ 'releaseGood',
41
+ 'releaseGood.bizplace',
42
+ 'releaseGood.bizplace.domain'
43
+ ]
44
+ })
45
+
46
+ if (orderInventoryByBin?.releaseGood) {
47
+ releaseGoodNo = orderInventoryByBin.releaseGood.name
48
+ releaseGood = orderInventoryByBin.releaseGood
49
+ }
50
+ }
51
+
26
52
  if (!releaseGood) throw new Error(`Release good dosen't exist.`)
53
+
27
54
  const worksheet: Worksheet = await fetchExecutingWorksheet(
28
55
  domain,
29
56
  releaseGood.bizplace,
@@ -110,6 +137,7 @@ export const packingWorksheetResolver = {
110
137
 
111
138
  return {
112
139
  worksheetInfo: {
140
+ releaseGood,
113
141
  bizplaceName: releaseGood.bizplace.name,
114
142
  refNo: releaseGood.refNo,
115
143
  refNo2: releaseGood.refNo2,
@@ -19,6 +19,7 @@ import {
19
19
  import { EcommerceController } from '../../../../controllers/ecommerce'
20
20
  import { WorksheetController } from '../../../../controllers/worksheet-controller'
21
21
  import { Worksheet, WorksheetDetail } from '../../../../entities'
22
+ import { Setting, PartnerSetting } from '@things-factory/setting-base'
22
23
 
23
24
  export const completePickingResolver = {
24
25
  async completePicking(_: any, { releaseGoodNo }, context: any) {
@@ -187,10 +188,30 @@ export async function completePicking(
187
188
 
188
189
  if (releaseGood.packingOption) {
189
190
  const packingWSCtrl: PackingWorksheetController = new PackingWorksheetController(tx, domain, user)
190
- await packingWSCtrl.generatePackingWorksheet(releaseGoodNo)
191
+
192
+ const directActivatePackingWorksheet: Setting = await tx.getRepository(Setting).findOne({
193
+ where: { domain: domain, category: 'id-rule', name: 'enable-direct-activate-packing-worksheet' }
194
+ })
195
+ const partnerDirectActivatePackingWorksheetSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
196
+ where: { setting: directActivatePackingWorksheet, domain: domain, partnerDomain: releaseGood.bizplace?.domain }
197
+ })
198
+
199
+ let packingWorksheet: Worksheet = await packingWSCtrl.generatePackingWorksheet(releaseGoodNo)
200
+
201
+ if (
202
+ directActivatePackingWorksheet != undefined && (directActivatePackingWorksheet.value).toLowerCase() == 'true'
203
+ ) {
204
+ if (partnerDirectActivatePackingWorksheetSetting != undefined) {
205
+ if ((partnerDirectActivatePackingWorksheetSetting.value).toLowerCase() == 'true')
206
+ await packingWSCtrl.activatePacking(packingWorksheet.name)
207
+ } else {
208
+ await packingWSCtrl.activatePacking(packingWorksheet.name)
209
+ }
210
+ }
211
+
191
212
  } else {
192
213
  // Find Existing Loading Worksheet if any
193
- const existLoadingWorksheet: Worksheet = await tx.getRepository(Worksheet).findOne({
214
+ let existLoadingWorksheet: Worksheet = await tx.getRepository(Worksheet).findOne({
194
215
  where: {
195
216
  releaseGood,
196
217
  type: WORKSHEET_TYPE.LOADING,
@@ -211,10 +232,21 @@ export async function completePicking(
211
232
 
212
233
  const loadingWorksheetDetails: WorksheetDetail[] = loadingWorksheet.worksheetDetails
213
234
  await loadingWSCtrl.activateLoading(loadingWorksheet.name, loadingWorksheetDetails)
214
- } else {
215
- throw new Error(
216
- 'Picking completion has been triggered twice, loading worksheet has been generated. Kindly proceed to loading.'
235
+ }
236
+ else {
237
+ const loadingWSCtrl: LoadingWorksheetController = new LoadingWorksheetController(tx, domain, user)
238
+ let loadingWorksheet: Worksheet = await loadingWSCtrl.updateLoadingWorksheet(
239
+ releaseGoodNo,
240
+ pickedTargetInventories,
241
+ existLoadingWorksheet
217
242
  )
243
+
244
+ if (!loadingWorksheet.worksheetDetails?.length) {
245
+ loadingWorksheet = await pickingWSCtrl.findWorksheetById(loadingWorksheet.id)
246
+ }
247
+
248
+ const loadingWorksheetDetails: WorksheetDetail[] = loadingWorksheet.worksheetDetails
249
+ await loadingWSCtrl.activateLoading(loadingWorksheet.name, loadingWorksheetDetails)
218
250
  }
219
251
  }
220
252
  }
@@ -0,0 +1,78 @@
1
+ import { EntityManager, getRepository } from 'typeorm'
2
+
3
+ import { User } from '@things-factory/auth-base'
4
+ import { Setting } from '@things-factory/setting-base'
5
+ import { Domain } from '@things-factory/shell'
6
+
7
+ import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../../../constants'
8
+ import { Worksheet } from '../../../../entities'
9
+ import { pickingWorksheet } from '../picking-worksheet'
10
+ import { activatePicking } from './activate-picking'
11
+
12
+ export const fetchAndAssignPickingTaskResolver = {
13
+ async fetchAndAssignPickingTask(_: any, {}, context: any) {
14
+ const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
15
+ const assignee: User = await tx.getRepository(User).findOne(user.id, { relations: ['domains'] })
16
+ if ((assignee?.domains || []).every((userDomain: Domain) => userDomain.id !== domain.id))
17
+ throw new Error('Target user is not belong to current domain')
18
+
19
+ if (!assignee) throw new Error('failed to find target user')
20
+
21
+ let worksheet: Worksheet
22
+ worksheet = await tx.getRepository(Worksheet).findOne({
23
+ relations: ['releaseGood'],
24
+ where: [
25
+ {
26
+ domain,
27
+ type: WORKSHEET_TYPE.PICKING,
28
+ status: WORKSHEET_STATUS.EXECUTING,
29
+ assignee: assignee
30
+ },
31
+ {
32
+ domain,
33
+ type: WORKSHEET_TYPE.PICKING,
34
+ status: WORKSHEET_STATUS.DEACTIVATED,
35
+ assignee: assignee
36
+ }
37
+ ],
38
+ order: {
39
+ name: 'ASC'
40
+ }
41
+ })
42
+
43
+ if (!worksheet) {
44
+ worksheet = await tx.getRepository(Worksheet).findOne({
45
+ relations: ['releaseGood'],
46
+ where: [
47
+ {
48
+ domain,
49
+ type: WORKSHEET_TYPE.PICKING,
50
+ status: WORKSHEET_STATUS.EXECUTING,
51
+ assignee: null
52
+ },
53
+ {
54
+ domain,
55
+ type: WORKSHEET_TYPE.PICKING,
56
+ status: WORKSHEET_STATUS.DEACTIVATED,
57
+ assignee: null
58
+ }
59
+ ]
60
+ })
61
+
62
+ await getRepository(Worksheet).update({ id: worksheet.id }, { assignee: assignee })
63
+ }
64
+
65
+ if (worksheet.status == WORKSHEET_STATUS.DEACTIVATED) await activatePicking(tx, domain, user, worksheet.name)
66
+
67
+ const locationSortingRules: Setting = await tx.getRepository(Setting).findOne({
68
+ where: { domain, name: 'rule-for-picking-product' }
69
+ })
70
+
71
+ const sortingRule = JSON.parse(locationSortingRules.value)
72
+ const locationSortingRule = Object.keys(sortingRule).map(field => {
73
+ return { name: field, desc: sortingRule[field] === 'DESC' }
74
+ })
75
+
76
+ return await pickingWorksheet(domain, worksheet.releaseGood.name, locationSortingRule, tx)
77
+ }
78
+ }
@@ -2,6 +2,7 @@ import { activateBatchPickingResolver } from './activate-batch-picking'
2
2
  import { activatePickingResolver } from './activate-picking'
3
3
  import { assignPickingInventoriesResolver } from './assign-picking-inventories'
4
4
  import { assignPickingWorkerResolver } from './assign-picking-worker'
5
+ import { fetchAndAssignPickingTaskResolver } from './fetch-and-assign-picking-task'
5
6
  import { batchPickingResolver } from './batch-picking'
6
7
  import { completeBatchPickingResolver } from './complete-batch-picking'
7
8
  import { completePickingResolver } from './complete-picking'
@@ -21,5 +22,6 @@ export const Mutations = {
21
22
  ...batchPickingResolver,
22
23
  ...completePickingResolver,
23
24
  ...completeBatchPickingResolver,
24
- ...assignPickingWorkerResolver
25
+ ...assignPickingWorkerResolver,
26
+ ...fetchAndAssignPickingTaskResolver
25
27
  }
@@ -4,9 +4,9 @@ import { EntityManager } from 'typeorm'
4
4
  import { PickingWorksheetController } from '../../../../controllers'
5
5
 
6
6
  export const pickingResolver = {
7
- async picking(_: any, { worksheetDetailName, worksheetType, palletId, locationName, releaseQty }, context: any) {
7
+ async picking(_: any, { worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation }, context: any) {
8
8
  const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
9
- await picking(tx, domain, user, worksheetDetailName, worksheetType, palletId, locationName, releaseQty)
9
+ await picking(tx, domain, user, worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation)
10
10
  }
11
11
  }
12
12
 
@@ -18,8 +18,9 @@ export async function picking(
18
18
  worksheetType: string,
19
19
  palletId: string,
20
20
  locationName: string,
21
- releaseQty: number
21
+ releaseQty: number,
22
+ binLocation?: string
22
23
  ) {
23
24
  const worksheetController: PickingWorksheetController = new PickingWorksheetController(tx, domain, user)
24
- await worksheetController.picking(worksheetDetailName, worksheetType, palletId, locationName, releaseQty)
25
+ await worksheetController.picking(worksheetDetailName, worksheetType, palletId, locationName, releaseQty, binLocation)
25
26
  }