@things-factory/sales-base 4.3.186 → 4.3.188
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/constants/order.js +10 -5
- package/dist-server/constants/order.js.map +1 -1
- package/dist-server/controllers/ecommerce/sellercraft-controller.js +5 -0
- package/dist-server/controllers/ecommerce/sellercraft-controller.js.map +1 -1
- package/dist-server/errors/validation-error.js +3 -3
- package/dist-server/errors/validation-error.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good-query.js +24 -2
- package/dist-server/service/draft-release-good/draft-release-good-query.js.map +1 -1
- package/dist-server/service/index.js +7 -0
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/order-inventory/order-inventory.js +14 -0
- package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
- package/dist-server/service/order-product/order-product.js +10 -0
- package/dist-server/service/order-product/order-product.js.map +1 -1
- package/dist-server/service/purchase-order/purchase-order-mutation.js +21 -35
- package/dist-server/service/purchase-order/purchase-order-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-query.js +3 -0
- package/dist-server/service/release-good/release-good-query.js.map +1 -1
- package/dist-server/service/release-good/release-good.js +6 -1
- package/dist-server/service/release-good/release-good.js.map +1 -1
- package/dist-server/service/replenishment/index.js +9 -0
- package/dist-server/service/replenishment/index.js.map +1 -0
- package/dist-server/service/replenishment/replenishment-mutation.js +226 -0
- package/dist-server/service/replenishment/replenishment-mutation.js.map +1 -0
- package/dist-server/service/replenishment/replenishment-query.js +114 -0
- package/dist-server/service/replenishment/replenishment-query.js.map +1 -0
- package/dist-server/service/replenishment/replenishment-type.js +119 -0
- package/dist-server/service/replenishment/replenishment-type.js.map +1 -0
- package/dist-server/service/replenishment/replenishment.js +104 -0
- package/dist-server/service/replenishment/replenishment.js.map +1 -0
- package/dist-server/utils/datetime-util.js +13 -1
- package/dist-server/utils/datetime-util.js.map +1 -1
- package/dist-server/utils/inventory-util.js +17 -2
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/dist-server/utils/order-no-generator.js +4 -0
- package/dist-server/utils/order-no-generator.js.map +1 -1
- package/package.json +3 -3
- package/server/constants/order.ts +10 -5
- package/server/controllers/ecommerce/sellercraft-controller.ts +9 -0
- package/server/service/draft-release-good/draft-release-good-query.ts +29 -2
- package/server/service/index.ts +7 -0
- package/server/service/order-inventory/order-inventory.ts +12 -1
- package/server/service/order-product/order-product.ts +8 -0
- package/server/service/release-good/release-good-query.ts +3 -0
- package/server/service/release-good/release-good.ts +6 -2
- package/server/service/replenishment/index.ts +6 -0
- package/server/service/replenishment/replenishment-mutation.ts +309 -0
- package/server/service/replenishment/replenishment-query.ts +76 -0
- package/server/service/replenishment/replenishment-type.ts +78 -0
- package/server/service/replenishment/replenishment.ts +87 -0
- package/server/utils/datetime-util.ts +14 -0
- package/server/utils/inventory-util.ts +19 -2
- package/server/utils/order-no-generator.ts +7 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { Replenishment, ReplenishmentStatus } from './replenishment'
|
|
4
|
+
|
|
5
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
6
|
+
import { ProductPatch, ProductDetailPatch } from '@things-factory/product-base'
|
|
7
|
+
|
|
8
|
+
@InputType()
|
|
9
|
+
export class NewReplenishment {
|
|
10
|
+
@Field()
|
|
11
|
+
name: string
|
|
12
|
+
|
|
13
|
+
@Field({ nullable: true })
|
|
14
|
+
description?: string
|
|
15
|
+
|
|
16
|
+
@Field(type => ReplenishmentStatus, { nullable: true })
|
|
17
|
+
state?: ReplenishmentStatus
|
|
18
|
+
|
|
19
|
+
@Field({ nullable: true })
|
|
20
|
+
active?: boolean
|
|
21
|
+
|
|
22
|
+
@Field({ nullable: true })
|
|
23
|
+
params?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@InputType()
|
|
27
|
+
export class ReplenishmentPatch {
|
|
28
|
+
@Field(type => ID, { nullable: true })
|
|
29
|
+
id?: string
|
|
30
|
+
|
|
31
|
+
@Field({ nullable: true })
|
|
32
|
+
name?: string
|
|
33
|
+
|
|
34
|
+
@Field({ nullable: true })
|
|
35
|
+
description?: string
|
|
36
|
+
|
|
37
|
+
@Field(type => ReplenishmentStatus, { nullable: true })
|
|
38
|
+
state?: ReplenishmentStatus
|
|
39
|
+
|
|
40
|
+
@Field({ nullable: true })
|
|
41
|
+
active?: boolean
|
|
42
|
+
|
|
43
|
+
@Field()
|
|
44
|
+
cuFlag: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@InputType()
|
|
48
|
+
export class ReplenishmentInventoryPatch {
|
|
49
|
+
@Field({ nullable: true })
|
|
50
|
+
bizplaceId?: string
|
|
51
|
+
|
|
52
|
+
@Field({ nullable: true })
|
|
53
|
+
releaseQty?: number
|
|
54
|
+
|
|
55
|
+
@Field({ nullable: true })
|
|
56
|
+
releaseUomValue?: number
|
|
57
|
+
|
|
58
|
+
@Field({ nullable: true })
|
|
59
|
+
packingType?: string
|
|
60
|
+
|
|
61
|
+
@Field({ nullable: true })
|
|
62
|
+
packingSize?: number
|
|
63
|
+
|
|
64
|
+
@Field({ nullable: true })
|
|
65
|
+
type?: string
|
|
66
|
+
|
|
67
|
+
@Field({ nullable: true })
|
|
68
|
+
productDetailId?: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@ObjectType()
|
|
72
|
+
export class ReplenishmentList {
|
|
73
|
+
@Field(type => [Replenishment])
|
|
74
|
+
items: Replenishment[]
|
|
75
|
+
|
|
76
|
+
@Field(type => Int)
|
|
77
|
+
total: number
|
|
78
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateDateColumn,
|
|
3
|
+
UpdateDateColumn,
|
|
4
|
+
Entity,
|
|
5
|
+
Index,
|
|
6
|
+
Column,
|
|
7
|
+
RelationId,
|
|
8
|
+
ManyToOne,
|
|
9
|
+
PrimaryGeneratedColumn,
|
|
10
|
+
OneToMany
|
|
11
|
+
} from 'typeorm'
|
|
12
|
+
import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
|
|
13
|
+
|
|
14
|
+
import { Domain } from '@things-factory/shell'
|
|
15
|
+
import { User } from '@things-factory/auth-base'
|
|
16
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
17
|
+
import { OrderInventory, OrderProduct } from '../'
|
|
18
|
+
|
|
19
|
+
export enum ReplenishmentStatus {
|
|
20
|
+
STATUS_A = 'STATUS_A',
|
|
21
|
+
STATUS_B = 'STATUS_B'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
registerEnumType(ReplenishmentStatus, {
|
|
25
|
+
name: 'ReplenishmentStatus',
|
|
26
|
+
description: 'state enumeration of a replenishment'
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
@Entity()
|
|
30
|
+
@Index('ix_replenishment_0', (replenishment: Replenishment) => [replenishment.domain, replenishment.name], {
|
|
31
|
+
unique: true
|
|
32
|
+
})
|
|
33
|
+
@ObjectType({ description: 'Entity for Replenishment' })
|
|
34
|
+
export class Replenishment {
|
|
35
|
+
@PrimaryGeneratedColumn('uuid')
|
|
36
|
+
@Field(type => ID)
|
|
37
|
+
readonly id: string
|
|
38
|
+
|
|
39
|
+
@Column()
|
|
40
|
+
@Field({ nullable: true })
|
|
41
|
+
name: string
|
|
42
|
+
|
|
43
|
+
@Column()
|
|
44
|
+
@Field({ nullable: true })
|
|
45
|
+
status: string
|
|
46
|
+
|
|
47
|
+
@ManyToOne(type => Domain)
|
|
48
|
+
@Field(type => Domain, { nullable: true })
|
|
49
|
+
domain: Domain
|
|
50
|
+
|
|
51
|
+
@RelationId((replenishment: Replenishment) => replenishment.domain)
|
|
52
|
+
domainId: string
|
|
53
|
+
|
|
54
|
+
@OneToMany(type => OrderInventory, orderInventory => orderInventory.replenishment)
|
|
55
|
+
@Field(type => [OrderInventory], { nullable: true })
|
|
56
|
+
orderInventories: OrderInventory[]
|
|
57
|
+
|
|
58
|
+
@OneToMany(type => OrderProduct, orderProduct => orderProduct.replenishment)
|
|
59
|
+
@Field(type => [OrderProduct], { nullable: true })
|
|
60
|
+
orderProducts: OrderProduct[]
|
|
61
|
+
|
|
62
|
+
@CreateDateColumn()
|
|
63
|
+
@Field({ nullable: true })
|
|
64
|
+
createdAt?: Date
|
|
65
|
+
|
|
66
|
+
@UpdateDateColumn()
|
|
67
|
+
@Field({ nullable: true })
|
|
68
|
+
updatedAt?: Date
|
|
69
|
+
|
|
70
|
+
@ManyToOne(type => User, {
|
|
71
|
+
nullable: true
|
|
72
|
+
})
|
|
73
|
+
@Field({ nullable: true })
|
|
74
|
+
creator?: User
|
|
75
|
+
|
|
76
|
+
@RelationId((replenishment: Replenishment) => replenishment.creator)
|
|
77
|
+
creatorId?: string
|
|
78
|
+
|
|
79
|
+
@ManyToOne(type => User, {
|
|
80
|
+
nullable: true
|
|
81
|
+
})
|
|
82
|
+
@Field({ nullable: true })
|
|
83
|
+
updater?: User
|
|
84
|
+
|
|
85
|
+
@RelationId((replenishment: Replenishment) => replenishment.creator)
|
|
86
|
+
updaterId?: string
|
|
87
|
+
}
|
|
@@ -52,3 +52,17 @@ export class DateTimeConverter {
|
|
|
52
52
|
return unloadDate
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
export class DateTimeDifference {
|
|
57
|
+
static timeDifferenceInSeconds(prevDateTime, curDateTime) {
|
|
58
|
+
let diffInSeconds: any = ''
|
|
59
|
+
if (prevDateTime && curDateTime) {
|
|
60
|
+
let dateA: any = new Date(prevDateTime)
|
|
61
|
+
let dateB: any = new Date(curDateTime)
|
|
62
|
+
|
|
63
|
+
diffInSeconds = (dateB.getTime() - dateA.getTime()) / 1000
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return diffInSeconds
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -106,6 +106,8 @@ export const InventoryUtil = {
|
|
|
106
106
|
COALESCE(SUM(COALESCE(i.qty, 0)) - SUM(COALESCE(i.locked_qty, 0)) - MAX(COALESCE(oi.release_qty, 0)) - MAX(COALESCE(bp.bundle_product_release_qty, 0)),0) AS "remainQty",
|
|
107
107
|
COALESCE(SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0)) - MAX(COALESCE(oi.release_uom_value, 0)) - MAX(COALESCE(bp.bundle_product_release_uom_value, 0)),0) AS "remainUomValue",
|
|
108
108
|
concat(SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0)) - MAX(COALESCE(oi.release_uom_value, 0)) - MAX(COALESCE(bp.bundle_product_release_uom_value, 0)), ' ', pd.uom) AS "remainUomValueWithUom",
|
|
109
|
+
COALESCE(SUM(COALESCE(i.transfer_qty, 0)), 0) AS "transferQty",
|
|
110
|
+
COALESCE(SUM(COALESCE(i.transfer_uom_value, 0)), 0) AS "transferUomValue",
|
|
109
111
|
'SINGLE' AS "groupType"
|
|
110
112
|
FROM products p
|
|
111
113
|
INNER join product_details pd on pd.product_id = p.id
|
|
@@ -148,12 +150,16 @@ export const InventoryUtil = {
|
|
|
148
150
|
COALESCE(MIN(FLOOR(pbs."availableQty")),0) AS "remainQty",
|
|
149
151
|
COALESCE(MIN(FLOOR(pbs."availableUomValue")),0) AS "remainUomValue",
|
|
150
152
|
CONCAT(COALESCE(MIN(FLOOR(pbs."availableUomValue")),0),' UNIT') AS "remainUomValueWithUom",
|
|
153
|
+
COALESCE(MIN(FLOOR(pbs."transferQty")),0) AS "transferQty",
|
|
154
|
+
COALESCE(MIN(FLOOR(pbs."transferUomValue")),0) AS "transferUomValue",
|
|
151
155
|
'BUNDLE' AS "groupType"
|
|
152
156
|
FROM product_bundles pb
|
|
153
157
|
LEFT JOIN (
|
|
154
158
|
SELECT pbs.product_id, pbs.product_bundle_id, min(pbs.bundle_qty),
|
|
155
159
|
(SUM(COALESCE(i2.qty, 0)) - SUM(COALESCE(i2.locked_qty, 0)) - MAX(COALESCE(oi.release_qty, 0))) / min(pbs.bundle_qty) AS "availableQty",
|
|
156
160
|
(SUM(COALESCE(i2.uom_value, 0)) - SUM(COALESCE(i2.locked_uom_value, 0)) - MAX(COALESCE(oi.release_uom_value, 0))) / min(pbs.bundle_qty) AS "availableUomValue",
|
|
161
|
+
(SUM(COALESCE(i2.transfer_qty, 0)) / min(pbs.bundle_qty)) AS "transferQty",
|
|
162
|
+
(SUM(COALESCE(i2.transfer_uom_value, 0)) / min(pbs.bundle_qty)) AS "transferUomValue",
|
|
157
163
|
pbs.product_detail_id
|
|
158
164
|
FROM product_bundle_settings pbs
|
|
159
165
|
LEFT JOIN inventories i2 ON i2.product_id = pbs.product_id AND i2.domain_id = $1 AND i2.status = 'STORED'
|
|
@@ -299,6 +305,8 @@ export const InventoryUtil = {
|
|
|
299
305
|
WHERE i.domain_id = $1
|
|
300
306
|
AND l2.type NOT IN ('${LOCATION_TYPE.QUARANTINE}', '${LOCATION_TYPE.RESERVE}')
|
|
301
307
|
AND i.obsolete = false
|
|
308
|
+
AND i.transfer_qty <= 0
|
|
309
|
+
AND i.transfer_uom_value <= 0
|
|
302
310
|
AND case when i.expiration_date is not null and p.shelf_life is not null then CURRENT_DATE < i.expiration_date - p.shelf_life else true end
|
|
303
311
|
${productWhereClause}
|
|
304
312
|
GROUP BY
|
|
@@ -601,7 +609,8 @@ export const InventoryUtil = {
|
|
|
601
609
|
customerBizplace: Bizplace,
|
|
602
610
|
domain: Domain,
|
|
603
611
|
trxMgr: EntityManager,
|
|
604
|
-
batchId?: string
|
|
612
|
+
batchId?: string,
|
|
613
|
+
preferLocation: string = null
|
|
605
614
|
): Promise<OrderInventory[]> {
|
|
606
615
|
let strictProduct = 'false'
|
|
607
616
|
|
|
@@ -627,6 +636,7 @@ export const InventoryUtil = {
|
|
|
627
636
|
|
|
628
637
|
let qb: SelectQueryBuilder<Inventory> = trxMgr.getRepository(Inventory).createQueryBuilder('iv')
|
|
629
638
|
qb.innerJoinAndSelect('iv.location', 'loc')
|
|
639
|
+
.innerJoin('warehouse_inventory_assignment_rankings', 'wiar', '"wiar"."location_type" = "loc"."type"')
|
|
630
640
|
.innerJoin('iv.product', 'p')
|
|
631
641
|
.andWhere('"iv"."domain_id" = :domainId')
|
|
632
642
|
.andWhere('"iv"."bizplace_id" = :bizplaceId')
|
|
@@ -634,6 +644,8 @@ export const InventoryUtil = {
|
|
|
634
644
|
.andWhere('"iv"."qty" - COALESCE("iv"."locked_qty", 0) > 0')
|
|
635
645
|
.andWhere('"loc"."type" NOT IN (:...locationTypes)')
|
|
636
646
|
.andWhere('"iv"."obsolete" = false')
|
|
647
|
+
.andWhere('"iv"."transfer_qty" <= 0')
|
|
648
|
+
.andWhere('"iv"."transfer_uom_value" <= 0')
|
|
637
649
|
.andWhere('"iv"."product_id" = :productId')
|
|
638
650
|
.andWhere(
|
|
639
651
|
'case when "iv"."expiration_date" is not null and "p"."shelf_life" is not null then CURRENT_DATE < "iv"."expiration_date" - "p"."shelf_life" else true end'
|
|
@@ -650,7 +662,10 @@ export const InventoryUtil = {
|
|
|
650
662
|
qb.andWhere('"iv"."batch_id" = :batchId', { batchId: batchId })
|
|
651
663
|
}
|
|
652
664
|
|
|
653
|
-
if (
|
|
665
|
+
if (preferLocation) {
|
|
666
|
+
qb.andWhere('"loc"."type" = :preferLocation', { preferLocation })
|
|
667
|
+
}
|
|
668
|
+
if (strictProduct == 'true' || preferLocation == 'STORAGE') {
|
|
654
669
|
qb.andWhere('"iv"."product_detail_id" = :productDetailId', { productDetailId: productDetail.id })
|
|
655
670
|
} else {
|
|
656
671
|
qb.andWhere('"iv"."packing_type" = :packingType', { packingType: orderInventory.packingType })
|
|
@@ -672,6 +687,8 @@ export const InventoryUtil = {
|
|
|
672
687
|
return qb
|
|
673
688
|
}
|
|
674
689
|
|
|
690
|
+
qb.addOrderBy('"wiar"."rank"', 'ASC')
|
|
691
|
+
|
|
675
692
|
switch (product?.pickingStrategy) {
|
|
676
693
|
case 'FIFO':
|
|
677
694
|
qb.addOrderBy('"iv"."created_at"', 'ASC')
|
|
@@ -78,6 +78,13 @@ export class OrderNoGenerator {
|
|
|
78
78
|
return `OTI-${uuidv4()}`
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
static replenishment() {
|
|
82
|
+
const currentDate = new Date()
|
|
83
|
+
return `RP-${currentDate.getFullYear()}${
|
|
84
|
+
currentDate.getMonth() + 1
|
|
85
|
+
}${currentDate.getDate()}${currentDate.getHours()}${currentDate.getMinutes()}${currentDate.getSeconds()}${currentDate.getMilliseconds()}`
|
|
86
|
+
}
|
|
87
|
+
|
|
81
88
|
static purchaseOrder() {
|
|
82
89
|
const currentDate = new Date()
|
|
83
90
|
return `PO-${currentDate.getFullYear()}${
|