@things-factory/worksheet-base 3.6.46 → 3.6.50
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/render-grn.js +8 -0
- package/dist-server/controllers/render-grn.js.map +1 -1
- package/dist-server/controllers/render-ro-do.js +18 -5
- package/dist-server/controllers/render-ro-do.js.map +1 -1
- package/dist-server/controllers/vas/vas-worksheet-controller.js +75 -14
- package/dist-server/controllers/vas/vas-worksheet-controller.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js +8 -7
- package/dist-server/graphql/resolvers/worksheet/picking/complete-picking.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/common-utils.js +302 -11
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/common-utils.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/interfaces/index.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/interfaces/repackaging.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/complete-repackaging.js +137 -31
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/complete-repackaging.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/repackaging.js +157 -42
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/repackaging.js.map +1 -1
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/undo-repackaging.js +35 -21
- package/dist-server/graphql/resolvers/worksheet/vas-transactions/repackaging/undo-repackaging.js.map +1 -1
- package/dist-server/utils/inventory-util.js +3 -2
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +14 -14
- package/server/controllers/render-grn.ts +8 -0
- package/server/controllers/render-ro-do.ts +21 -6
- package/server/controllers/vas/vas-worksheet-controller.ts +104 -23
- package/server/graphql/resolvers/worksheet/picking/complete-picking.ts +8 -13
- package/server/graphql/resolvers/worksheet/vas-transactions/common-utils.ts +452 -14
- package/server/graphql/resolvers/worksheet/vas-transactions/interfaces/index.ts +36 -1
- package/server/graphql/resolvers/worksheet/vas-transactions/interfaces/repackaging.ts +8 -2
- package/server/graphql/resolvers/worksheet/vas-transactions/repackaging/complete-repackaging.ts +185 -56
- package/server/graphql/resolvers/worksheet/vas-transactions/repackaging/repackaging.ts +210 -54
- package/server/graphql/resolvers/worksheet/vas-transactions/repackaging/undo-repackaging.ts +64 -32
- package/server/utils/inventory-util.ts +10 -5
package/server/graphql/resolvers/worksheet/vas-transactions/repackaging/complete-repackaging.ts
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
1
|
+
import { EntityManager } from 'typeorm'
|
|
2
|
+
|
|
1
3
|
import { User } from '@things-factory/auth-base'
|
|
2
4
|
import { Bizplace } from '@things-factory/biz-base'
|
|
3
|
-
import {
|
|
5
|
+
import { Product } from '@things-factory/product-base'
|
|
6
|
+
import { OrderVas } from '@things-factory/sales-base'
|
|
4
7
|
import { Domain } from '@things-factory/shell'
|
|
5
8
|
import { Inventory, INVENTORY_TRANSACTION_TYPE } from '@things-factory/warehouse-base'
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
createLoadingWorksheet,
|
|
9
|
-
createPutawayWorksheet,
|
|
10
|
-
deductProductAmount,
|
|
11
|
-
getCurrentAmount,
|
|
12
|
-
upsertInventory
|
|
13
|
-
} from '../common-utils'
|
|
9
|
+
|
|
10
|
+
import { deductProductAmount, temporaryGetCurrentAmount, upsertInventory } from '../common-utils'
|
|
14
11
|
import {
|
|
12
|
+
FeaturedInventoryInterface,
|
|
15
13
|
OperationGuideInterface,
|
|
16
14
|
PackingUnits,
|
|
17
|
-
PalletChangesInterface,
|
|
18
15
|
RefOrderType,
|
|
19
16
|
RepackagingGuide,
|
|
20
|
-
RepackedInvInfo
|
|
17
|
+
RepackedInvInfo,
|
|
18
|
+
TemporaryPalletChangesInterface
|
|
21
19
|
} from '../interfaces'
|
|
22
20
|
|
|
23
21
|
export async function completeRepackaging(trxMgr: EntityManager, orderVas: OrderVas, user: User): Promise<void> {
|
|
24
22
|
orderVas = await trxMgr.getRepository(OrderVas).findOne(orderVas.id, {
|
|
25
|
-
relations: [
|
|
23
|
+
relations: [
|
|
24
|
+
'domain',
|
|
25
|
+
'bizplace',
|
|
26
|
+
'inventory',
|
|
27
|
+
'inventory.product',
|
|
28
|
+
'inventory.productDetail',
|
|
29
|
+
'arrivalNotice',
|
|
30
|
+
'releaseGood',
|
|
31
|
+
'vasOrder',
|
|
32
|
+
'vas'
|
|
33
|
+
]
|
|
26
34
|
})
|
|
27
35
|
const domain: Domain = orderVas.domain
|
|
28
36
|
const bizplace: Bizplace = orderVas.bizplace
|
|
29
37
|
let originInv: Inventory = orderVas.inventory
|
|
38
|
+
let transactionType: string = INVENTORY_TRANSACTION_TYPE.REPACKAGING
|
|
30
39
|
const operationGuide: OperationGuideInterface<RepackagingGuide> = JSON.parse(orderVas.operationGuide)
|
|
31
40
|
const operationGuideData: RepackagingGuide = operationGuide.data
|
|
32
41
|
const packingUnit: string = operationGuideData.packingUnit
|
|
@@ -34,20 +43,43 @@ export async function completeRepackaging(trxMgr: EntityManager, orderVas: Order
|
|
|
34
43
|
const toPackingType: string = operationGuideData.toPackingType
|
|
35
44
|
const { arrivalNotice, releaseGood, vasOrder } = orderVas
|
|
36
45
|
const refOrder: RefOrderType = arrivalNotice || releaseGood || vasOrder
|
|
46
|
+
const repackedInvs: RepackedInvInfo[] = operationGuideData.repackedInvs
|
|
47
|
+
const repackedFroms: TemporaryPalletChangesInterface[] = extractRepackedFroms(
|
|
48
|
+
operationGuideData,
|
|
49
|
+
orderVas,
|
|
50
|
+
packingUnit
|
|
51
|
+
)
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
if (orderVas.vas && orderVas.vas.operationGuide === 'vas-repack-relabel') {
|
|
54
|
+
transactionType = INVENTORY_TRANSACTION_TYPE.REPACKAGING_RELABELING
|
|
55
|
+
const toProduct: any = operationGuideData.toProduct
|
|
56
|
+
|
|
57
|
+
// please add domain filter as well
|
|
58
|
+
const foundProduct: Product = await trxMgr.getRepository(Product).findOne({
|
|
59
|
+
where: {
|
|
60
|
+
id: toProduct.product.id,
|
|
61
|
+
sku: toProduct.product.sku,
|
|
62
|
+
name: toProduct.product.name
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
if (!foundProduct) {
|
|
67
|
+
throw new Error(`Cannot find product with SKU ${toProduct.product.sku}`)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
originInv.product = foundProduct
|
|
71
|
+
originInv.batchId = operationGuideData.toBatchId
|
|
72
|
+
originInv.productDetail = toProduct.productDetailId
|
|
73
|
+
}
|
|
41
74
|
|
|
42
75
|
// create repacked inventories based on repackedInvs
|
|
43
76
|
for (const ri of repackedInvs) {
|
|
44
|
-
const repackedFromList:
|
|
45
|
-
(rf:
|
|
77
|
+
const repackedFromList: TemporaryPalletChangesInterface[] = ri.repackedFrom.filter(
|
|
78
|
+
(rf: TemporaryPalletChangesInterface) => rf.toPalletId === ri.palletId
|
|
46
79
|
)
|
|
47
|
-
const { qty, uomValue } = getCurrentAmount(repackedFromList, ri.palletId)
|
|
48
|
-
const repackedPkgQty: number = packingUnit === PackingUnits.QTY ? qty / stdAmount : uomValue / stdAmount
|
|
49
80
|
|
|
50
|
-
const
|
|
81
|
+
const { qty, uomValue } = temporaryGetCurrentAmount(repackedFromList, ri.palletId, packingUnit, stdAmount)
|
|
82
|
+
/* const changedInv: Inventory = */ await upsertInventory(
|
|
51
83
|
trxMgr,
|
|
52
84
|
domain,
|
|
53
85
|
bizplace,
|
|
@@ -57,49 +89,146 @@ export async function completeRepackaging(trxMgr: EntityManager, orderVas: Order
|
|
|
57
89
|
ri.palletId,
|
|
58
90
|
ri.locationName,
|
|
59
91
|
toPackingType,
|
|
60
|
-
repackedPkgQty,
|
|
92
|
+
packingUnit == PackingUnits.QTY ? qty : ri.repackedPkgQty,
|
|
61
93
|
uomValue,
|
|
62
|
-
|
|
94
|
+
transactionType,
|
|
95
|
+
stdAmount,
|
|
96
|
+
packingUnit
|
|
63
97
|
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (const rf of repackedFroms) {
|
|
101
|
+
let foundInventory: Inventory = await trxMgr.getRepository(Inventory).findOne({
|
|
102
|
+
where: {
|
|
103
|
+
domain,
|
|
104
|
+
bizplace,
|
|
105
|
+
palletId: rf.fromPalletId
|
|
106
|
+
}
|
|
107
|
+
})
|
|
64
108
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
109
|
+
if (foundInventory) {
|
|
110
|
+
let reducedQty: number
|
|
111
|
+
let reducedUomValue: number
|
|
112
|
+
|
|
113
|
+
if (packingUnit == PackingUnits.QTY) {
|
|
114
|
+
reducedQty = rf.reducedUnitQty / rf.packingSize
|
|
115
|
+
reducedUomValue = rf.reducedUomValue
|
|
116
|
+
} else if (packingUnit == PackingUnits.UOM) {
|
|
117
|
+
// reducedQty will remain 0 if there is remaining uomValue
|
|
118
|
+
reducedQty = foundInventory.uomValue - rf.reducedUomValue == 0 ? 1 : 0
|
|
119
|
+
reducedUomValue = rf.reducedUomValue
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
foundInventory = await deductProductAmount(
|
|
123
|
+
trxMgr,
|
|
124
|
+
domain,
|
|
125
|
+
bizplace,
|
|
126
|
+
user,
|
|
127
|
+
refOrder,
|
|
128
|
+
foundInventory,
|
|
129
|
+
reducedQty,
|
|
130
|
+
getRoundedAmount(reducedUomValue, 1000),
|
|
131
|
+
transactionType,
|
|
132
|
+
rf.originalQty,
|
|
133
|
+
getRoundedAmount(rf.originalUomValue, 1000),
|
|
134
|
+
rf.currentUnitQty,
|
|
135
|
+
rf.currentUomValue
|
|
136
|
+
)
|
|
76
137
|
}
|
|
77
138
|
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function extractRepackedFroms(
|
|
142
|
+
operationGuideData: RepackagingGuide,
|
|
143
|
+
orderVas: OrderVas,
|
|
144
|
+
packingUnit: string
|
|
145
|
+
): Partial<TemporaryPalletChangesInterface[]> {
|
|
146
|
+
return (
|
|
147
|
+
operationGuideData.repackedInvs
|
|
148
|
+
.reduce((acc, ri: RepackedInvInfo) => {
|
|
149
|
+
acc = [...acc, ...ri.repackedFrom]
|
|
150
|
+
return acc
|
|
151
|
+
}, [])
|
|
152
|
+
// .flat()
|
|
153
|
+
.reduce((acc, inv) => {
|
|
154
|
+
let foundInv = acc.find(a => a.fromPalletId == inv.fromPalletId)
|
|
155
|
+
if (foundInv) {
|
|
156
|
+
if (packingUnit == PackingUnits.QTY) {
|
|
157
|
+
foundInv.reducedUnitQty += inv.reducedUnitQty
|
|
158
|
+
foundInv.reducedUomValue += inv.reducedUomValue
|
|
159
|
+
} else if (packingUnit == PackingUnits.UOM) {
|
|
160
|
+
foundInv.reducedQty += inv.reducedQty
|
|
161
|
+
foundInv.reducedUomValue += inv.reducedUomValue
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
if (packingUnit == PackingUnits.QTY) {
|
|
165
|
+
acc.push({
|
|
166
|
+
fromPalletId: inv.fromPalletId,
|
|
167
|
+
reducedUnitQty: inv.reducedUnitQty,
|
|
168
|
+
reducedUomValue: inv.reducedUomValue,
|
|
169
|
+
packingSize: inv.packingSize
|
|
170
|
+
})
|
|
171
|
+
} else if (packingUnit == PackingUnits.UOM) {
|
|
172
|
+
acc.push({
|
|
173
|
+
fromPalletId: inv.fromPalletId,
|
|
174
|
+
reducedQty: inv.reducedQty,
|
|
175
|
+
reducedUomValue: inv.reducedUomValue,
|
|
176
|
+
packingSize: inv.packingSize
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return acc
|
|
182
|
+
}, [])
|
|
183
|
+
.map((pc: TemporaryPalletChangesInterface) => {
|
|
184
|
+
const featuredInvs: FeaturedInventoryInterface[] = operationGuideData.featuredInvs || []
|
|
185
|
+
const foundFeaturedInv = featuredInvs.find(
|
|
186
|
+
(inv: FeaturedInventoryInterface) => inv.palletId === pc.fromPalletId
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
let originalQty: number
|
|
190
|
+
let originalUomValue: number
|
|
78
191
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
192
|
+
if (foundFeaturedInv) {
|
|
193
|
+
originalQty = foundFeaturedInv.originalQty
|
|
194
|
+
originalUomValue = foundFeaturedInv.originalUomValue
|
|
195
|
+
|
|
196
|
+
if (packingUnit == PackingUnits.QTY) {
|
|
197
|
+
pc.currentUnitQty = foundFeaturedInv.currentUnitQty
|
|
198
|
+
} else if (packingUnit == PackingUnits.UOM) {
|
|
199
|
+
pc.currentUomValue = foundFeaturedInv.currentUomValue
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
originalQty =
|
|
203
|
+
packingUnit == PackingUnits.UOM
|
|
204
|
+
? orderVas.qty
|
|
205
|
+
: orderVas.qty -
|
|
206
|
+
featuredInvs.reduce((qty: number, inv: FeaturedInventoryInterface) => {
|
|
207
|
+
return qty + inv.originalQty
|
|
208
|
+
}, 0)
|
|
209
|
+
|
|
210
|
+
originalUomValue =
|
|
211
|
+
orderVas.uomValue -
|
|
212
|
+
featuredInvs.reduce((uomValue: number, inv: FeaturedInventoryInterface) => {
|
|
213
|
+
return uomValue + inv.originalUomValue
|
|
214
|
+
}, 0)
|
|
215
|
+
|
|
216
|
+
if (packingUnit == PackingUnits.QTY) {
|
|
217
|
+
pc.currentUnitQty = originalQty - pc.reducedUnitQty / pc.packingSize
|
|
218
|
+
} else if (packingUnit == PackingUnits.UOM) {
|
|
219
|
+
pc.currentUomValue = getRoundedAmount(originalUomValue - pc.reducedUomValue)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
...pc,
|
|
225
|
+
originalQty,
|
|
226
|
+
originalUomValue
|
|
227
|
+
}
|
|
228
|
+
})
|
|
90
229
|
)
|
|
91
230
|
}
|
|
92
231
|
|
|
93
|
-
function
|
|
94
|
-
return
|
|
95
|
-
.filter((ri: RepackedInvInfo) => {
|
|
96
|
-
const isPalletIncluded: boolean = Boolean(
|
|
97
|
-
ri.repackedFrom.find((rf: PalletChangesInterface) => rf.fromPalletId === originInv.palletId)
|
|
98
|
-
)
|
|
99
|
-
if (isPalletIncluded) return ri
|
|
100
|
-
})
|
|
101
|
-
.map((ri: RepackedInvInfo) => {
|
|
102
|
-
ri.repackedFrom = ri.repackedFrom.filter((rf: PalletChangesInterface) => rf.fromPalletId === originInv.palletId)
|
|
103
|
-
return ri
|
|
104
|
-
})
|
|
232
|
+
function getRoundedAmount(value: number, decimalPlace: number = 100): number {
|
|
233
|
+
return Math.round((value + Number.EPSILON) * decimalPlace) / decimalPlace
|
|
105
234
|
}
|
|
@@ -1,25 +1,28 @@
|
|
|
1
|
+
import { EntityManager } from 'typeorm'
|
|
2
|
+
|
|
1
3
|
import { User } from '@things-factory/auth-base'
|
|
2
4
|
import { Bizplace } from '@things-factory/biz-base'
|
|
3
5
|
import { OrderVas } from '@things-factory/sales-base'
|
|
4
6
|
import { Domain } from '@things-factory/shell'
|
|
5
7
|
import { Inventory, Location, Warehouse } from '@things-factory/warehouse-base'
|
|
6
|
-
|
|
8
|
+
|
|
7
9
|
import { Worksheet, WorksheetDetail } from '../../../../../entities'
|
|
8
10
|
import { checkPalletDuplication, checkPalletIdenticallity } from '../../../../../utils'
|
|
9
11
|
import { executeVas } from '../../vas/execute-vas'
|
|
10
12
|
import {
|
|
11
13
|
assignInventory,
|
|
12
|
-
getRemainInventoryAmount,
|
|
13
14
|
getWorksheetDetailByName,
|
|
15
|
+
temporaryGetRemainInventoryAmount,
|
|
14
16
|
updateRelatedOrderVas
|
|
15
17
|
} from '../common-utils'
|
|
16
18
|
import {
|
|
19
|
+
FeaturedInventoryInterface,
|
|
17
20
|
OperationGuideInterface,
|
|
18
21
|
PackingUnits,
|
|
19
|
-
PalletChangesInterface,
|
|
20
22
|
RefOrderType,
|
|
21
23
|
RepackagingGuide,
|
|
22
|
-
RepackedInvInfo
|
|
24
|
+
RepackedInvInfo,
|
|
25
|
+
TemporaryPalletChangesInterface
|
|
23
26
|
} from '../interfaces'
|
|
24
27
|
|
|
25
28
|
export const repackagingResolver = {
|
|
@@ -52,7 +55,7 @@ export const repackagingResolver = {
|
|
|
52
55
|
|
|
53
56
|
// Check whether there's duplicated inventory in warehouse.
|
|
54
57
|
if (await checkPalletDuplication(domain, bizplace, toPalletId, tx))
|
|
55
|
-
throw new Error(`The
|
|
58
|
+
throw new Error(`The lot ID (${toPalletId}) is duplicated.`)
|
|
56
59
|
|
|
57
60
|
// Init refOrder
|
|
58
61
|
const { arrivalNotice, releaseGood, vasOrder }: { [key: string]: RefOrderType } = targetVas
|
|
@@ -69,65 +72,142 @@ export const repackagingResolver = {
|
|
|
69
72
|
|
|
70
73
|
let operationGuide: OperationGuideInterface<RepackagingGuide> = JSON.parse(targetVas.operationGuide)
|
|
71
74
|
let operationGuideData: RepackagingGuide = operationGuide.data
|
|
72
|
-
|
|
73
|
-
// const palletChanges: PalletChangesInterface[] = operationGuideData.repackedInvs
|
|
74
|
-
// .map((ri: RepackedInvInfo) => ri.repackedFrom)
|
|
75
|
-
// .flat()
|
|
76
|
-
|
|
77
|
-
const palletChanges: PalletChangesInterface[] = []
|
|
78
|
-
|
|
79
|
-
const { remainQty, remainUomValue } = await getRemainInventoryAmount(
|
|
80
|
-
tx,
|
|
81
|
-
refOrder,
|
|
82
|
-
domain,
|
|
83
|
-
bizplace,
|
|
84
|
-
originInv,
|
|
85
|
-
palletChanges,
|
|
86
|
-
fromPalletId
|
|
87
|
-
)
|
|
88
|
-
const unitUomValue: number = remainUomValue / remainQty
|
|
75
|
+
let featuredInvs: FeaturedInventoryInterface[] = operationGuideData.featuredInvs
|
|
89
76
|
const packingUnit: string = operationGuideData.packingUnit
|
|
90
77
|
const stdAmount: number = operationGuideData.stdAmount
|
|
78
|
+
|
|
79
|
+
let repackedInvs: RepackedInvInfo[] = operationGuideData.repackedInvs
|
|
80
|
+
|
|
81
|
+
if (repackedInvs?.length && repackedInvs.some((inv: RepackedInvInfo) => inv.palletId == toPalletId))
|
|
82
|
+
throw new Error(`Unable to repack into the same lot ID ${toPalletId}`)
|
|
83
|
+
|
|
84
|
+
let palletChanges: TemporaryPalletChangesInterface[] = []
|
|
85
|
+
|
|
86
|
+
if (repackedInvs && repackedInvs.length) {
|
|
87
|
+
palletChanges = repackedInvs.reduce((acc, ri: RepackedInvInfo) => {
|
|
88
|
+
acc = [...acc, ...ri.repackedFrom]
|
|
89
|
+
return acc
|
|
90
|
+
}, [])
|
|
91
|
+
// .map((ri: RepackedInvInfo) => ri.repackedFrom).flat()
|
|
92
|
+
} else if (!repackedInvs) {
|
|
93
|
+
operationGuideData.repackedInvs = []
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// get remainUnitQty of originInv (from previous repackaging actions)
|
|
97
|
+
let remainOriginInv: { remainUomValue: number; remainUnitQty: number } = {
|
|
98
|
+
remainUomValue: 0,
|
|
99
|
+
remainUnitQty: 0
|
|
100
|
+
}
|
|
101
|
+
let remainUomValue: number = 0
|
|
102
|
+
let remainUnitQty: number = 0
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
remainOriginInv = await temporaryGetRemainInventoryAmount(
|
|
106
|
+
tx,
|
|
107
|
+
refOrder,
|
|
108
|
+
domain,
|
|
109
|
+
bizplace,
|
|
110
|
+
originInv,
|
|
111
|
+
palletChanges,
|
|
112
|
+
fromPalletId
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
remainUomValue = remainOriginInv.remainUomValue
|
|
116
|
+
remainUnitQty = remainOriginInv.remainUnitQty
|
|
117
|
+
} catch (err) {}
|
|
118
|
+
|
|
119
|
+
let repackedFroms: TemporaryPalletChangesInterface[] = []
|
|
91
120
|
let repackedInv: RepackedInvInfo = getRepackedInv(operationGuideData, toPalletId, locationName)
|
|
121
|
+
let isCompleted: boolean = false
|
|
122
|
+
const repackagingAmount: number = stdAmount * packageQty
|
|
92
123
|
|
|
93
|
-
let isCompleted: boolean = false // Flag for calling executeVas function to change status of worksheet detail
|
|
94
124
|
if (packingUnit === PackingUnits.QTY) {
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
125
|
+
const singleUnitUomValue: number = originInv.uomValue / (originInv.qty * originInv.packingSize)
|
|
126
|
+
// const singleUnitUomValue: number = getRoundedAmount(
|
|
127
|
+
// originInv.uomValue / (originInv.qty * originInv.packingSize),
|
|
128
|
+
// 10000
|
|
129
|
+
// )
|
|
130
|
+
|
|
131
|
+
if (featuredInvs?.length && repackagingAmount > remainUnitQty) {
|
|
132
|
+
const inventoriesChanges = deductedFeaturedInventories(
|
|
133
|
+
featuredInvs,
|
|
134
|
+
repackagingAmount,
|
|
135
|
+
remainUnitQty,
|
|
136
|
+
toPalletId,
|
|
137
|
+
'currentUnitQty'
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
operationGuideData.featuredInvs = inventoriesChanges.featuredInvs
|
|
141
|
+
repackedFroms = [...repackedFroms, ...inventoriesChanges.repackedFroms]
|
|
142
|
+
|
|
143
|
+
if (remainUnitQty > 0) {
|
|
144
|
+
repackedFroms.push({
|
|
145
|
+
fromPalletId,
|
|
146
|
+
toPalletId,
|
|
147
|
+
reducedUnitQty: remainUnitQty,
|
|
148
|
+
reducedUomValue: remainUnitQty * singleUnitUomValue,
|
|
149
|
+
packingSize: originInv.packingSize
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
} else if (remainUnitQty >= repackagingAmount) {
|
|
153
|
+
repackedFroms.push({
|
|
154
|
+
fromPalletId,
|
|
155
|
+
toPalletId,
|
|
156
|
+
reducedUnitQty: repackagingAmount,
|
|
157
|
+
reducedUomValue: repackagingAmount * singleUnitUomValue,
|
|
158
|
+
packingSize: originInv.packingSize
|
|
159
|
+
})
|
|
103
160
|
}
|
|
104
161
|
|
|
105
|
-
repackedInv.repackedFrom
|
|
162
|
+
repackedInv.repackedFrom = repackedFroms
|
|
106
163
|
const totalPackedQty: number = repackedInv.repackedFrom.reduce(
|
|
107
|
-
(qty: number, rf:
|
|
164
|
+
(qty: number, rf: TemporaryPalletChangesInterface) => (qty += rf.reducedUnitQty),
|
|
108
165
|
0
|
|
109
166
|
)
|
|
110
|
-
repackedInv.repackedPkgQty =
|
|
111
|
-
isCompleted =
|
|
167
|
+
repackedInv.repackedPkgQty = totalPackedQty / stdAmount
|
|
168
|
+
isCompleted = operationGuideData.requiredPackageQty == 0
|
|
112
169
|
} else if (packingUnit === PackingUnits.UOM) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
170
|
+
if (featuredInvs?.length && repackagingAmount > remainUomValue) {
|
|
171
|
+
const inventoriesChanges = deductedFeaturedInventories(
|
|
172
|
+
featuredInvs,
|
|
173
|
+
repackagingAmount,
|
|
174
|
+
remainUomValue,
|
|
175
|
+
toPalletId,
|
|
176
|
+
'currentUomValue'
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
operationGuideData.featuredInvs = inventoriesChanges.featuredInvs
|
|
180
|
+
repackedFroms = [...repackedFroms, ...inventoriesChanges.repackedFroms]
|
|
181
|
+
|
|
182
|
+
if (remainUomValue > 0) {
|
|
183
|
+
repackedFroms.push({
|
|
184
|
+
fromPalletId,
|
|
185
|
+
toPalletId,
|
|
186
|
+
reducedQty: 0,
|
|
187
|
+
reducedUomValue: remainUomValue,
|
|
188
|
+
// reducedUomValue: getRoundedAmount(remainUomValue),
|
|
189
|
+
packingSize: originInv.packingSize
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
} else if (remainUomValue >= repackagingAmount) {
|
|
193
|
+
repackedFroms.push({
|
|
194
|
+
fromPalletId,
|
|
195
|
+
toPalletId,
|
|
196
|
+
reducedQty: 0,
|
|
197
|
+
reducedUomValue: repackagingAmount,
|
|
198
|
+
// reducedUomValue: getRoundedAmount(repackagingAmount),
|
|
199
|
+
packingSize: originInv.packingSize
|
|
200
|
+
})
|
|
122
201
|
}
|
|
123
202
|
|
|
124
|
-
repackedInv.repackedFrom
|
|
203
|
+
repackedInv.repackedFrom = repackedFroms
|
|
125
204
|
const totalPackedUomValue: number = repackedInv.repackedFrom.reduce(
|
|
126
|
-
(
|
|
205
|
+
(qty: number, rf: TemporaryPalletChangesInterface) => (qty += rf.reducedUomValue),
|
|
127
206
|
0
|
|
128
207
|
)
|
|
129
208
|
repackedInv.repackedPkgQty = totalPackedUomValue / stdAmount
|
|
130
|
-
|
|
209
|
+
// repackedInv.repackedPkgQty = getRoundedAmount(totalPackedUomValue / stdAmount)
|
|
210
|
+
isCompleted = operationGuideData.requiredPackageQty == 0
|
|
131
211
|
}
|
|
132
212
|
|
|
133
213
|
// Get total required package qty to complete this VAS Task
|
|
@@ -138,18 +218,24 @@ export const repackagingResolver = {
|
|
|
138
218
|
wsd.worksheet,
|
|
139
219
|
targetVas,
|
|
140
220
|
packingUnit,
|
|
141
|
-
stdAmount
|
|
221
|
+
stdAmount,
|
|
222
|
+
operationGuideData?.remainder || 0
|
|
142
223
|
)
|
|
143
224
|
// Get total repacked package qty until this transaction
|
|
144
225
|
const repackedPackageQty: number = getRepackedPackageQty(operationGuideData.repackedInvs)
|
|
145
|
-
const remainRequiredPackageQty: number = requiredPackageQty - repackedPackageQty
|
|
226
|
+
const remainRequiredPackageQty: number = getRoundedAmount(requiredPackageQty - repackedPackageQty)
|
|
146
227
|
|
|
147
|
-
|
|
148
|
-
|
|
228
|
+
// const requiredPackageQty: number = operationGuideData.requiredPackageQty - repackedPackageQty
|
|
229
|
+
|
|
230
|
+
operationGuide.data = {
|
|
231
|
+
...operationGuideData,
|
|
232
|
+
requiredPackageQty: remainRequiredPackageQty
|
|
233
|
+
}
|
|
149
234
|
|
|
150
235
|
// Update every order vas to share same operation guide
|
|
151
236
|
await updateRelatedOrderVas<RepackagingGuide>(tx, domain, bizplace, wsd, targetVas, operationGuide, user)
|
|
152
237
|
|
|
238
|
+
// ######################### KIV DULU YANG NI #########################
|
|
153
239
|
if (isCompleted || remainRequiredPackageQty === 0) {
|
|
154
240
|
await executeVas(tx, domain, user, wsd)
|
|
155
241
|
}
|
|
@@ -182,7 +268,8 @@ async function getRequiredPackageQty(
|
|
|
182
268
|
worksheet: Worksheet,
|
|
183
269
|
currentOV: OrderVas,
|
|
184
270
|
packingUnit: string,
|
|
185
|
-
stdAmount: number
|
|
271
|
+
stdAmount: number,
|
|
272
|
+
remainder: number
|
|
186
273
|
): Promise<number> {
|
|
187
274
|
const relatedWSDs: WorksheetDetail[] = await tx.getRepository(WorksheetDetail).find({
|
|
188
275
|
where: { domain, bizplace, worksheet },
|
|
@@ -206,9 +293,9 @@ async function getRequiredPackageQty(
|
|
|
206
293
|
)
|
|
207
294
|
|
|
208
295
|
if (packingUnit === PackingUnits.QTY) {
|
|
209
|
-
return qty / stdAmount
|
|
296
|
+
return (qty - remainder) / stdAmount
|
|
210
297
|
} else if (packingUnit === PackingUnits.UOM) {
|
|
211
|
-
return uomValue / stdAmount
|
|
298
|
+
return Math.floor(uomValue / stdAmount)
|
|
212
299
|
}
|
|
213
300
|
}
|
|
214
301
|
|
|
@@ -236,3 +323,72 @@ function getRepackedInv(operationGuideData: RepackagingGuide, palletId: string,
|
|
|
236
323
|
|
|
237
324
|
return repackedInv
|
|
238
325
|
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @description To transfer qty or uom value from featured inventories into origin inventory
|
|
329
|
+
* If and only if the origin inventory has insufficient amount
|
|
330
|
+
*
|
|
331
|
+
* @param {FeaturedInventoryInterface} featuredInvs
|
|
332
|
+
* @param {Number} repackagingAmount
|
|
333
|
+
* @param {Number} remainingAmount
|
|
334
|
+
* @param {String} packingUnit -- value is strictly for qty / uomValue
|
|
335
|
+
*/
|
|
336
|
+
function deductedFeaturedInventories(
|
|
337
|
+
featuredInvs: FeaturedInventoryInterface[],
|
|
338
|
+
repackagingAmount: number,
|
|
339
|
+
remainingAmount: number,
|
|
340
|
+
toPalletId: string,
|
|
341
|
+
packingUnit: string
|
|
342
|
+
): { featuredInvs: FeaturedInventoryInterface[]; repackedFroms: TemporaryPalletChangesInterface[] } {
|
|
343
|
+
let requiredAmount: number = getRoundedAmount(repackagingAmount - remainingAmount)
|
|
344
|
+
const repackedFroms: TemporaryPalletChangesInterface[] = []
|
|
345
|
+
|
|
346
|
+
featuredInvs = featuredInvs.map(inv => {
|
|
347
|
+
if (requiredAmount > 0 && inv[packingUnit] > 0) {
|
|
348
|
+
let reducedAmount: number = requiredAmount
|
|
349
|
+
|
|
350
|
+
if (inv[packingUnit] >= requiredAmount) {
|
|
351
|
+
inv[packingUnit] = inv[packingUnit] - requiredAmount
|
|
352
|
+
// inv[packingUnit] = getRoundedAmount(inv[packingUnit] - requiredAmount)
|
|
353
|
+
requiredAmount = 0
|
|
354
|
+
} else {
|
|
355
|
+
requiredAmount = requiredAmount - inv[packingUnit]
|
|
356
|
+
// requiredAmount = getRoundedAmount(requiredAmount - inv[packingUnit])
|
|
357
|
+
reducedAmount = inv[packingUnit]
|
|
358
|
+
inv[packingUnit] = 0
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
switch (packingUnit) {
|
|
362
|
+
case 'currentUnitQty':
|
|
363
|
+
repackedFroms.push({
|
|
364
|
+
fromPalletId: inv.palletId,
|
|
365
|
+
toPalletId,
|
|
366
|
+
reducedUnitQty: reducedAmount,
|
|
367
|
+
reducedUomValue: reducedAmount * inv.uomValuePerQty,
|
|
368
|
+
// reducedUomValue: getRoundedAmount(reducedAmount * inv.uomValuePerQty),
|
|
369
|
+
packingSize: featuredInvs.find(inv => inv.palletId == inv.palletId).packingSize
|
|
370
|
+
})
|
|
371
|
+
break
|
|
372
|
+
|
|
373
|
+
case 'currentUomValue':
|
|
374
|
+
repackedFroms.push({
|
|
375
|
+
fromPalletId: inv.palletId,
|
|
376
|
+
toPalletId,
|
|
377
|
+
reducedQty: 0,
|
|
378
|
+
reducedUomValue: reducedAmount,
|
|
379
|
+
// reducedUomValue: getRoundedAmount(reducedAmount),
|
|
380
|
+
packingSize: featuredInvs.find(inv => inv.palletId == inv.palletId).packingSize
|
|
381
|
+
})
|
|
382
|
+
break
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return inv
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
return { featuredInvs, repackedFroms }
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function getRoundedAmount(value, decimalPlace = 100) {
|
|
393
|
+
return Math.round((value + Number.EPSILON) * decimalPlace) / decimalPlace
|
|
394
|
+
}
|