@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.
- package/dist-server/controllers/ecommerce/sellercraft-controller.js +3 -3
- package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
- package/dist-server/controllers/inbound/unloading-worksheet-controller.js +48 -25
- package/dist-server/controllers/inbound/unloading-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/outbound/loading-worksheet-controller.js +4 -0
- package/dist-server/controllers/outbound/loading-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/outbound/picking-worksheet-controller.js +121 -67
- package/dist-server/controllers/outbound/picking-worksheet-controller.js.map +1 -1
- package/dist-server/controllers/worksheet-controller.js +27 -2
- package/dist-server/controllers/worksheet-controller.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js +27 -2
- package/dist-server/graphql/resolvers/worksheet/loading-worksheet.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js +26 -0
- package/dist-server/graphql/resolvers/worksheet/packing-worksheet.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +27 -5
- package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js +72 -0
- package/dist-server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.js.map +1 -0
- package/dist-server/graphql/resolvers/worksheet/picking/index.js +2 -1
- package/dist-server/graphql/resolvers/worksheet/picking/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking/picking.js +4 -4
- package/dist-server/graphql/resolvers/worksheet/picking/picking.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js +86 -57
- package/dist-server/graphql/resolvers/worksheet/picking-worksheet.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/unloading-return-worksheet.js +2 -2
- package/dist-server/graphql/resolvers/worksheet/unloading-return-worksheet.js.map +1 -1
- package/dist-server/graphql/types/worksheet/index.js +5 -1
- package/dist-server/graphql/types/worksheet/index.js.map +1 -1
- package/dist-server/utils/inventory-util.js +29 -2
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +16 -16
- package/server/controllers/ecommerce/sellercraft-controller.ts +3 -3
- package/server/controllers/inbound/unloading-worksheet-controller.ts +67 -30
- package/server/controllers/outbound/loading-worksheet-controller.ts +20 -0
- package/server/controllers/outbound/picking-worksheet-controller.ts +148 -83
- package/server/controllers/worksheet-controller.ts +40 -2
- package/server/graphql/resolvers/worksheet/loading-worksheet.ts +33 -4
- package/server/graphql/resolvers/worksheet/packing-worksheet.ts +31 -3
- package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +37 -5
- package/server/graphql/resolvers/worksheet/picking/fetch-and-assign-picking-task.ts +78 -0
- package/server/graphql/resolvers/worksheet/picking/index.ts +3 -1
- package/server/graphql/resolvers/worksheet/picking/picking.ts +5 -4
- package/server/graphql/resolvers/worksheet/picking-worksheet.ts +102 -62
- package/server/graphql/resolvers/worksheet/unloading-return-worksheet.ts +6 -4
- package/server/graphql/types/worksheet/index.ts +5 -1
- 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
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
415
|
-
|
|
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
|
-
|
|
418
|
-
|
|
418
|
+
const packingType: string = inventory.packingType
|
|
419
|
+
const packingSize: number = inventory.packingSize
|
|
419
420
|
|
|
420
|
-
|
|
421
|
-
|
|
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
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
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
|
-
|
|
435
|
-
|
|
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
|
-
|
|
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
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
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
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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
|
-
|
|
461
|
-
|
|
469
|
+
if (!foundProductDetail) {
|
|
470
|
+
const roProductDetail: ProductDetail = productDetails.find(
|
|
471
|
+
(parentDetail: ProductDetail) =>
|
|
472
|
+
parentDetail.packingType === packingType && parentDetail.packingSize == packingSize
|
|
473
|
+
)
|
|
462
474
|
|
|
463
|
-
|
|
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
|
-
|
|
480
|
+
console.log('')
|
|
466
481
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
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
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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
|
-
|
|
484
|
-
|
|
485
|
-
await this.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
975
|
+
childQty = scannedProductDetail.packingSize
|
|
938
976
|
} else {
|
|
939
977
|
while (hasChildRelation && !hasMatchingChild) {
|
|
940
978
|
hasChildRelation = Boolean(currentProductDetail?.childProductDetail)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
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
|
}
|