@things-factory/worksheet-base 3.8.1 → 3.8.5

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 (24) hide show
  1. package/dist-server/controllers/ecommerce/sellercraft-controller.js +1 -1
  2. package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
  3. package/dist-server/controllers/inbound/putaway-returning-worksheet-controller.js +16 -4
  4. package/dist-server/controllers/inbound/putaway-returning-worksheet-controller.js.map +1 -1
  5. package/dist-server/controllers/outbound/packing-worksheet-controller.js +2 -6
  6. package/dist-server/controllers/outbound/packing-worksheet-controller.js.map +1 -1
  7. package/dist-server/controllers/outbound/picking-worksheet-controller.js +12 -14
  8. package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
  9. package/dist-server/controllers/worksheet-controller.js +5 -5
  10. package/dist-server/controllers/worksheet-controller.js.map +1 -1
  11. package/dist-server/graphql/resolvers/worksheet/generate-worksheet/generate-release-good-worksheet.js.map +1 -1
  12. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +3 -2
  13. package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
  14. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js +64 -54
  15. package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js.map +1 -1
  16. package/package.json +7 -7
  17. package/server/controllers/ecommerce/sellercraft-controller.ts +2 -2
  18. package/server/controllers/inbound/putaway-returning-worksheet-controller.ts +32 -8
  19. package/server/controllers/outbound/packing-worksheet-controller.ts +2 -7
  20. package/server/controllers/outbound/picking-worksheet-controller.ts +32 -38
  21. package/server/controllers/worksheet-controller.ts +5 -5
  22. package/server/graphql/resolvers/worksheet/generate-worksheet/generate-release-good-worksheet.ts +3 -1
  23. package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +3 -2
  24. package/server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.ts +67 -56
@@ -17,8 +17,7 @@ import {
17
17
  INVENTORY_STATUS,
18
18
  INVENTORY_TRANSACTION_TYPE,
19
19
  Location,
20
- LOCATION_TYPE,
21
- LOCATION_STATUS
20
+ LOCATION_TYPE
22
21
  } from '@things-factory/warehouse-base'
23
22
 
24
23
  import { TASK_NUMBER_RULE_TYPE, TASK_NUMBER_SETTING_KEY, WORKSHEET_STATUS, WORKSHEET_TYPE } from '../../constants'
@@ -191,7 +190,7 @@ export class PickingWorksheetController extends VasWorksheetController {
191
190
  if (vasWorksheet) {
192
191
  await this.activateVAS(vasWorksheet.name, vasWorksheet.worksheetDetails)
193
192
  }
194
- } catch (e) { }
193
+ } catch (e) {}
195
194
 
196
195
  const pendingSplitOIs: OrderInventory[] = await this.trxMgr.getRepository(OrderInventory).find({
197
196
  where: { domain: this.domain, releaseGood, status: ORDER_INVENTORY_STATUS.PENDING_SPLIT }
@@ -367,19 +366,17 @@ export class PickingWorksheetController extends VasWorksheetController {
367
366
  await this.trxMgr.getRepository(WorksheetDetail).delete(worksheetDetailIds)
368
367
  await this.trxMgr.getRepository(OrderInventory).delete(targetInventoryIds)
369
368
 
370
- await this.trxMgr
371
- .getRepository(OrderInventory)
372
- .update(
373
- {
374
- refWorksheetId: worksheet.id,
375
- batchId,
376
- product: { id: productId },
377
- packingType,
378
- packingSize,
379
- status: ORDER_INVENTORY_STATUS.COMPLETE_SPLIT
380
- },
381
- { status: ORDER_INVENTORY_STATUS.PENDING_SPLIT, updater: this.user, updatedAt: new Date() }
382
- )
369
+ await this.trxMgr.getRepository(OrderInventory).update(
370
+ {
371
+ refWorksheetId: worksheet.id,
372
+ batchId,
373
+ product: { id: productId },
374
+ packingType,
375
+ packingSize,
376
+ status: ORDER_INVENTORY_STATUS.COMPLETE_SPLIT
377
+ },
378
+ { status: ORDER_INVENTORY_STATUS.PENDING_SPLIT, updater: this.user, updatedAt: new Date() }
379
+ )
383
380
  }
384
381
 
385
382
  async scanProductPicking(
@@ -412,16 +409,14 @@ export class PickingWorksheetController extends VasWorksheetController {
412
409
  const product: Product = targetInventory.product
413
410
  let inventory: Inventory = targetInventory.inventory
414
411
 
415
- //validation to prevent duplicated picking
412
+ //validation to prevent duplicated picking
416
413
  let oiValidate: OrderInventory = await this.trxMgr.getRepository(OrderInventory).findOne({
417
414
  where: { domain: this.domain, id: targetInventory.id, status: ORDER_INVENTORY_STATUS.PICKING }
418
415
  })
419
- if (!oiValidate)
420
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`))
416
+ if (!oiValidate) throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`))
421
417
 
422
418
  //validation to prevent over release
423
- if (inventory.qty <= 0)
424
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
419
+ if (inventory.qty <= 0) throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
425
420
 
426
421
  if (inventory.cartonId !== cartonId)
427
422
  throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Carton ID', cartonId, inventory.cartonId))
@@ -461,16 +456,17 @@ export class PickingWorksheetController extends VasWorksheetController {
461
456
  }
462
457
 
463
458
  if (product?.isRequireSerialNumberScanning) {
464
- if ((!serialNumber || serialNumber == ''))
459
+ if (!serialNumber || serialNumber == '')
465
460
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `require serial number`))
466
461
 
467
462
  if (serialNumber) {
468
- targetInventory.serialNumber = JSON.stringify(targetInventory.serialNumber ? [...(JSON.parse(targetInventory.serialNumber)), serialNumber] : [serialNumber])
463
+ targetInventory.serialNumber = JSON.stringify(
464
+ targetInventory.serialNumber ? [...JSON.parse(targetInventory.serialNumber), serialNumber] : [serialNumber]
465
+ )
469
466
  }
470
467
  }
471
468
 
472
469
  await this.updatePickingTransaction(releaseGood, targetInventory, worksheetDetail, inventory, pickedQty)
473
-
474
470
  } catch (error) {
475
471
  throw error
476
472
  }
@@ -495,7 +491,7 @@ export class PickingWorksheetController extends VasWorksheetController {
495
491
  'targetInventory.releaseGood',
496
492
  'targetInventory.inventory',
497
493
  'targetInventory.inventory.location',
498
- 'targetInventory.product',
494
+ 'targetInventory.product'
499
495
  ]
500
496
  )
501
497
 
@@ -504,27 +500,26 @@ export class PickingWorksheetController extends VasWorksheetController {
504
500
  const product: Product = targetInventory.product
505
501
  let inventory: Inventory = targetInventory.inventory
506
502
 
507
- //validation to prevent duplicated picking
503
+ //validation to prevent duplicated picking
508
504
  let oiValidate: OrderInventory = await this.trxMgr.getRepository(OrderInventory).findOne({
509
505
  where: { domain: this.domain, id: targetInventory.id, status: ORDER_INVENTORY_STATUS.PICKING }
510
506
  })
511
- if (!oiValidate)
512
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`))
507
+ if (!oiValidate) throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `is done`))
513
508
 
514
509
  //validation to prevent over release
515
- if (inventory.qty <= 0)
516
- throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
510
+ if (inventory.qty <= 0) throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `over release`))
517
511
 
518
512
  if (inventory.palletId !== palletId)
519
513
  throw new Error(this.ERROR_MSG.VALIDITY.UNEXPECTED_FIELD_VALUE('Pallet ID', palletId, inventory.palletId))
520
514
 
521
-
522
515
  if (product?.isRequireSerialNumberScanning) {
523
- if ((!serialNumber || serialNumber == ''))
516
+ if (!serialNumber || serialNumber == '')
524
517
  throw new Error(this.ERROR_MSG.VALIDITY.CANT_PROCEED_STEP_BY('picking', `require serial number`))
525
518
 
526
519
  if (serialNumber) {
527
- targetInventory.serialNumber = JSON.stringify(targetInventory.serialNumber ? [...(JSON.parse(targetInventory.serialNumber)), serialNumber] : [serialNumber])
520
+ targetInventory.serialNumber = JSON.stringify(
521
+ targetInventory.serialNumber ? [...JSON.parse(targetInventory.serialNumber), serialNumber] : [serialNumber]
522
+ )
528
523
  }
529
524
  }
530
525
 
@@ -828,16 +823,16 @@ export class PickingWorksheetController extends VasWorksheetController {
828
823
  status: ORDER_STATUS.PICKING
829
824
  })
830
825
 
831
- const worksheet: Worksheet = await this.findWorksheetByRefOrder(releaseGood, WORKSHEET_TYPE.PICKING, [
826
+ let worksheet: Worksheet = await this.findWorksheetByRefOrder(releaseGood, WORKSHEET_TYPE.PICKING, [
832
827
  'worksheetDetails',
833
828
  'worksheetDetails.targetInventory'
834
829
  ])
835
- this.checkRecordValidity(worksheet, { status: WORKSHEET_STATUS.EXECUTING })
830
+ await this.checkRecordValidity(worksheet, { status: WORKSHEET_STATUS.EXECUTING })
836
831
 
837
832
  let orderStatus: string
838
833
  if (releaseGood?.packingOption) {
839
834
  orderStatus = ORDER_STATUS.READY_TO_PACK
840
- } else if (!releaseGood?.courierOption && !releaseGood?.packingOption) {
835
+ } else {
841
836
  orderStatus = ORDER_STATUS.LOADING
842
837
  }
843
838
 
@@ -938,7 +933,7 @@ export class PickingWorksheetController extends VasWorksheetController {
938
933
  name: 'enable-bin-picking'
939
934
  }
940
935
  })
941
- if (binPickingSetting != undefined && (binPickingSetting.value).toLowerCase() == 'true') {
936
+ if (binPickingSetting != undefined && binPickingSetting.value.toLowerCase() == 'true') {
942
937
  if (binLocation) {
943
938
  const foundBinLocation: Location = await this.trxMgr.getRepository(Location).findOne({
944
939
  where: { domain: this.domain, name: binLocation, type: LOCATION_TYPE.BIN }
@@ -995,4 +990,3 @@ export class PickingWorksheetController extends VasWorksheetController {
995
990
  return orderInventory
996
991
  }
997
992
  }
998
-
@@ -387,7 +387,7 @@ export class WorksheetController {
387
387
  type: string,
388
388
  additionalProps: Partial<Worksheet> = {}
389
389
  ): Promise<Worksheet> {
390
- let refOrderType: string = this.getRefOrderField(refOrder)
390
+ let refOrderType: string = await this.getRefOrderField(refOrder)
391
391
  const bizplace: Bizplace = await this.extractBizplaceFromRefOrder(refOrder)
392
392
 
393
393
  const worksheet: Partial<Worksheet> = {
@@ -676,7 +676,7 @@ export class WorksheetController {
676
676
  'worksheetDetails.targetVas'
677
677
  ])
678
678
 
679
- const worksheetDetails: WorksheetDetail[] = worksheet.worksheetDetails
679
+ let worksheetDetails: WorksheetDetail[] = worksheet.worksheetDetails
680
680
 
681
681
  worksheetDetails
682
682
  .filter((wsd: WorksheetDetail) => wsd.status !== ORDER_INVENTORY_STATUS.REPLACED)
@@ -687,7 +687,7 @@ export class WorksheetController {
687
687
  await this.trxMgr.getRepository(WorksheetDetail).save(worksheetDetails)
688
688
 
689
689
  if (worksheetType === WORKSHEET_TYPE.UNLOADING) {
690
- const targetProducts: OrderProduct[] = worksheet.worksheetDetails.map((wsd: WorksheetDetail) => {
690
+ let targetProducts: OrderProduct[] = worksheet.worksheetDetails.map((wsd: WorksheetDetail) => {
691
691
  let targetProduct: OrderProduct = wsd.targetProduct
692
692
  targetProduct.status = ORDER_PRODUCT_STATUS.TERMINATED
693
693
  targetProduct.updater = this.user
@@ -696,7 +696,7 @@ export class WorksheetController {
696
696
 
697
697
  await this.updateOrderTargets(targetProducts)
698
698
  } else if (worksheetType === WORKSHEET_TYPE.VAS) {
699
- const targetVASs: OrderVas[] = worksheet.worksheetDetails.map((wsd: WorksheetDetail) => {
699
+ let targetVASs: OrderVas[] = worksheet.worksheetDetails.map((wsd: WorksheetDetail) => {
700
700
  let targetVAS: OrderVas = wsd.targetVas
701
701
  targetVAS.status = ORDER_VAS_STATUS.TERMINATED
702
702
  targetVAS.updater = this.user
@@ -712,7 +712,7 @@ export class WorksheetController {
712
712
  worksheetType === WORKSHEET_TYPE.WAREHOUSE_RETURN ||
713
713
  worksheetType === WORKSHEET_TYPE.UNLOADING_RETURN
714
714
  ) {
715
- const targetInventories: OrderInventory[] = worksheet.worksheetDetails
715
+ let targetInventories: OrderInventory[] = worksheet.worksheetDetails
716
716
  .filter((wsd: WorksheetDetail) => wsd.status !== ORDER_INVENTORY_STATUS.REPLACED)
717
717
  .map((wsd: WorksheetDetail) => {
718
718
  let targetInventory: OrderInventory = wsd.targetInventory
@@ -1,7 +1,9 @@
1
+ import { EntityManager } from 'typeorm'
2
+
1
3
  import { User } from '@things-factory/auth-base'
2
4
  import { OrderInventory } from '@things-factory/sales-base'
3
5
  import { Domain } from '@things-factory/shell'
4
- import { EntityManager } from 'typeorm'
6
+
5
7
  import { PickingWorksheetController } from '../../../../controllers/'
6
8
  import { Worksheet, WorksheetDetail } from '../../../../entities'
7
9
 
@@ -45,7 +45,7 @@ export async function completePicking(
45
45
  releaseGoodNo: string
46
46
  ): Promise<void> {
47
47
  const pickingWSCtrl: PickingWorksheetController = new PickingWorksheetController(tx, domain, user)
48
- const releaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).findOne({
48
+ let releaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).findOne({
49
49
  where: { domain, name: releaseGoodNo },
50
50
  relations: [
51
51
  'bizplace',
@@ -53,6 +53,7 @@ export async function completePicking(
53
53
  'bizplace.company',
54
54
  'bizplace.company.domain',
55
55
  'orderInventories',
56
+ 'orderInventories.inventory',
56
57
  'orderInventories.product'
57
58
  ]
58
59
  })
@@ -84,7 +85,7 @@ export async function completePicking(
84
85
 
85
86
  if (sellercraft) {
86
87
  const sellercraftCtrl: SellercraftController = new SellercraftController(tx, domain, user)
87
- await sellercraftCtrl.initiateOrderShipment(sellercraft, releaseGood)
88
+ releaseGood = await sellercraftCtrl.initiateOrderShipment(sellercraft, releaseGood)
88
89
  await sellercraftCtrl.initiateOrderDocument(sellercraft, releaseGood)
89
90
  } else {
90
91
  const companyDomain: Domain = releaseGood.bizplace.company.domain
@@ -1,6 +1,7 @@
1
1
  import { EntityManager, getRepository } from 'typeorm'
2
2
 
3
3
  import { User } from '@things-factory/auth-base'
4
+ import { ReleaseGood, OrderInventory } from '@things-factory/sales-base'
4
5
  import { Setting } from '@things-factory/setting-base'
5
6
  import { Domain } from '@things-factory/shell'
6
7
 
@@ -10,69 +11,79 @@ import { pickingWorksheet } from '../picking-worksheet'
10
11
  import { activatePicking } from './activate-picking'
11
12
 
12
13
  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')
14
+ async fetchAndAssignPickingTask(_: any, { }, context: any) {
15
+ try {
16
+ const { tx, domain, user }: { tx: EntityManager; domain: Domain; user: User } = context.state
17
+ const assignee: User = await tx.getRepository(User).findOne(user.id, { relations: ['domains'] })
18
+ if ((assignee?.domains || []).every((userDomain: Domain) => userDomain.id !== domain.id))
19
+ throw new Error('Target user is not belong to current domain')
18
20
 
19
- if (!assignee) throw new Error('failed to find target user')
21
+ if (!assignee) throw new Error('failed to find target user')
20
22
 
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
- })
23
+ let worksheet: any
24
+ let worksheetQb = await tx.getRepository(Worksheet).createQueryBuilder('ws')
25
+ .select('ws.id')
26
+ .addSelect('ws.name')
27
+ .addSelect('ws.status')
28
+ .addSelect('ws.release_good_id')
29
+ .where('(ws.domain_id = :domain_id AND ws.type = :type AND ws.assignee_id =:assignee AND (ws.status = :status1 OR ws.status = :status2))', { domain_id: domain.id, type: WORKSHEET_TYPE.PICKING, assignee: assignee.id, status1: WORKSHEET_STATUS.EXECUTING, status2: WORKSHEET_STATUS.DEACTIVATED })
30
+ .andWhere(qb => {
31
+ const subQuery = qb
32
+ .subQuery()
33
+ .select('COUNT(*) AS totalPS')
34
+ .from(OrderInventory, 'OrderInventory')
35
+ .where('OrderInventory.release_good_id = ws.release_good_id')
36
+ .andWhere(`OrderInventory.status = 'PENDING_SPLIT'`)
37
+ .groupBy('OrderInventory.release_good_id')
38
+ .having('COUNT(*) > 0')
39
+ .getQuery()
40
+ return 'NOT EXISTS ' + subQuery
41
+ })
42
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
- })
43
+ worksheet = await worksheetQb.getRawOne();
61
44
 
62
- await getRepository(Worksheet).update({ id: worksheet.id }, { assignee: assignee })
63
- }
45
+ if (!worksheet) {
46
+ let worksheetQb = await tx.getRepository(Worksheet).createQueryBuilder('ws')
47
+ .select('ws.id')
48
+ .addSelect('ws.name')
49
+ .addSelect('ws.status')
50
+ .addSelect('ws.release_good_id')
51
+ .where('(ws.domain_id = :domain_id AND ws.type = :type AND ws.assignee_id IS NULL AND (ws.status = :status1 OR ws.status = :status2))', { domain_id: domain.id, type: WORKSHEET_TYPE.PICKING, status1: WORKSHEET_STATUS.EXECUTING, status2: WORKSHEET_STATUS.DEACTIVATED })
52
+ .andWhere(qb => {
53
+ const subQuery = qb
54
+ .subQuery()
55
+ .select('COUNT(*) AS totalPS')
56
+ .from(OrderInventory, 'OrderInventory')
57
+ .where('OrderInventory.release_good_id = ws.release_good_id')
58
+ .andWhere(`OrderInventory.status = 'PENDING_SPLIT'`)
59
+ .groupBy('OrderInventory.release_good_id')
60
+ .having('COUNT(*) > 0')
61
+ .getQuery()
62
+ return 'NOT EXISTS ' + subQuery
63
+ })
64
+
65
+ worksheet = await worksheetQb.getRawOne();
66
+
67
+ if (!worksheet) throw new Error('no suitable worksheet found')
68
+ await getRepository(Worksheet).update({ id: worksheet.id }, { assignee: assignee })
69
+ }
64
70
 
65
- if (worksheet.status == WORKSHEET_STATUS.DEACTIVATED) await activatePicking(tx, domain, user, worksheet.name)
71
+ if (worksheet.status == WORKSHEET_STATUS.DEACTIVATED) await activatePicking(tx, domain, user, worksheet.ws_name)
66
72
 
67
- const locationSortingRules: Setting = await tx.getRepository(Setting).findOne({
68
- where: { domain, name: 'rule-for-picking-product' }
69
- })
73
+ const locationSortingRules: Setting = await tx.getRepository(Setting).findOne({
74
+ where: { domain, name: 'rule-for-picking-product' }
75
+ })
70
76
 
71
- const sortingRule = JSON.parse(locationSortingRules.value)
72
- const locationSortingRule = Object.keys(sortingRule).map(field => {
73
- return { name: field, desc: sortingRule[field] === 'DESC' }
74
- })
77
+ const sortingRule = JSON.parse(locationSortingRules.value)
78
+ const locationSortingRule = Object.keys(sortingRule).map(field => {
79
+ return { name: field, desc: sortingRule[field] === 'DESC' }
80
+ })
75
81
 
76
- return await pickingWorksheet(domain, worksheet.releaseGood.name, locationSortingRule, tx)
82
+ const releaseGood: ReleaseGood = await tx.getRepository(ReleaseGood).findOne(worksheet.release_good_id)
83
+
84
+ return await pickingWorksheet(domain, releaseGood.name, locationSortingRule, tx)
85
+ } catch (error) {
86
+ throw error
87
+ }
77
88
  }
78
89
  }