@things-factory/warehouse-base 4.1.18 → 4.1.27
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/service/inventory/inventory-mutation.js +18 -8
- package/dist-server/service/inventory/inventory-mutation.js.map +1 -1
- package/dist-server/service/inventory/inventory-types.js +7 -7
- package/dist-server/service/inventory/inventory-types.js.map +1 -1
- package/dist-server/service/inventory/inventory.js +6 -0
- package/dist-server/service/inventory/inventory.js.map +1 -1
- package/dist-server/service/inventory-change/inventory-change-mutation.js +45 -20
- package/dist-server/service/inventory-change/inventory-change-mutation.js.map +1 -1
- package/dist-server/service/inventory-change/inventory-change.js +5 -0
- package/dist-server/service/inventory-change/inventory-change.js.map +1 -1
- package/dist-server/service/inventory-history/inventory-history-query.js +104 -0
- package/dist-server/service/inventory-history/inventory-history-query.js.map +1 -1
- package/dist-server/service/inventory-history/inventory-history-types.js +121 -1
- package/dist-server/service/inventory-history/inventory-history-types.js.map +1 -1
- package/dist-server/service/inventory-history/inventory-history.js +7 -2
- package/dist-server/service/inventory-history/inventory-history.js.map +1 -1
- package/dist-server/utils/inventory-util.js +106 -4
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +8 -8
- package/server/service/inventory/inventory-mutation.ts +49 -13
- package/server/service/inventory/inventory-types.ts +6 -6
- package/server/service/inventory/inventory.ts +5 -0
- package/server/service/inventory-change/inventory-change-mutation.ts +41 -12
- package/server/service/inventory-change/inventory-change.ts +4 -0
- package/server/service/inventory-history/inventory-history-query.ts +124 -1
- package/server/service/inventory-history/inventory-history-types.ts +86 -0
- package/server/service/inventory-history/inventory-history.ts +6 -2
- package/server/utils/inventory-util.ts +136 -13
|
@@ -267,3 +267,89 @@ export class NewInventoryHistory {
|
|
|
267
267
|
@Field(type => Float, { nullable: true })
|
|
268
268
|
unitCost?: number
|
|
269
269
|
}
|
|
270
|
+
|
|
271
|
+
@ObjectType()
|
|
272
|
+
export class RawInventoryHistoryList {
|
|
273
|
+
@Field(type => [RawInventoryHistory], { nullable: true })
|
|
274
|
+
items?: RawInventoryHistory[]
|
|
275
|
+
|
|
276
|
+
@Field(type => Int, { nullable: true })
|
|
277
|
+
total?: number
|
|
278
|
+
}
|
|
279
|
+
@ObjectType()
|
|
280
|
+
export class RawInventoryHistory {
|
|
281
|
+
@Field({ nullable: true })
|
|
282
|
+
sku?: string
|
|
283
|
+
|
|
284
|
+
@Field({ nullable: true })
|
|
285
|
+
productName?: string
|
|
286
|
+
|
|
287
|
+
@Field({ nullable: true })
|
|
288
|
+
productDescription?: string
|
|
289
|
+
|
|
290
|
+
@Field({ nullable: true })
|
|
291
|
+
brand?: string
|
|
292
|
+
|
|
293
|
+
@Field(type => Int, { nullable: true })
|
|
294
|
+
seq?: number
|
|
295
|
+
|
|
296
|
+
@Field({ nullable: true })
|
|
297
|
+
palletId?: string
|
|
298
|
+
|
|
299
|
+
@Field({ nullable: true })
|
|
300
|
+
cartonId?: string
|
|
301
|
+
|
|
302
|
+
@Field({ nullable: true })
|
|
303
|
+
batchId?: string
|
|
304
|
+
|
|
305
|
+
@Field({ nullable: true })
|
|
306
|
+
batchIdRef?: string
|
|
307
|
+
|
|
308
|
+
@Field(type => Int, { nullable: true })
|
|
309
|
+
openingQty?: number
|
|
310
|
+
|
|
311
|
+
@Field(type => Int, { nullable: true })
|
|
312
|
+
qty?: number
|
|
313
|
+
|
|
314
|
+
@Field(type => Float, { nullable: true })
|
|
315
|
+
openingUomValue?: number
|
|
316
|
+
|
|
317
|
+
@Field(type => Float, { nullable: true })
|
|
318
|
+
uomValue?: number
|
|
319
|
+
|
|
320
|
+
@Field({ nullable: true })
|
|
321
|
+
uom?: string
|
|
322
|
+
|
|
323
|
+
@Field({ nullable: true })
|
|
324
|
+
zone?: string
|
|
325
|
+
|
|
326
|
+
@Field({ nullable: true })
|
|
327
|
+
orderNo?: string
|
|
328
|
+
|
|
329
|
+
@Field({ nullable: true })
|
|
330
|
+
refNo?: string
|
|
331
|
+
|
|
332
|
+
@Field({ nullable: true })
|
|
333
|
+
status?: string
|
|
334
|
+
|
|
335
|
+
@Field({ nullable: true })
|
|
336
|
+
transactionType?: string
|
|
337
|
+
|
|
338
|
+
@Field({ nullable: true })
|
|
339
|
+
bizplace?: string
|
|
340
|
+
|
|
341
|
+
@Field({ nullable: true })
|
|
342
|
+
warehouse?: string
|
|
343
|
+
|
|
344
|
+
@Field({ nullable: true })
|
|
345
|
+
location?: string
|
|
346
|
+
|
|
347
|
+
@Field({ nullable: true })
|
|
348
|
+
createdAt?: Date
|
|
349
|
+
|
|
350
|
+
@Field({ nullable: true })
|
|
351
|
+
updatedAt?: Date
|
|
352
|
+
|
|
353
|
+
@Field({ nullable: true })
|
|
354
|
+
updater?: string
|
|
355
|
+
}
|
|
@@ -68,8 +68,8 @@ export class InventoryHistory {
|
|
|
68
68
|
@Field()
|
|
69
69
|
name: string
|
|
70
70
|
|
|
71
|
-
@Column(
|
|
72
|
-
@Field(
|
|
71
|
+
@Column()
|
|
72
|
+
@Field()
|
|
73
73
|
palletId: string
|
|
74
74
|
|
|
75
75
|
@Column({ nullable: true })
|
|
@@ -171,6 +171,10 @@ export class InventoryHistory {
|
|
|
171
171
|
@Field({ nullable: true })
|
|
172
172
|
manufactureYear: number
|
|
173
173
|
|
|
174
|
+
@Column('date', { nullable: true })
|
|
175
|
+
@Field(type => ScalarDate, { nullable: true })
|
|
176
|
+
manufactureDate: Date
|
|
177
|
+
|
|
174
178
|
@ManyToOne(type => User, { nullable: true })
|
|
175
179
|
@Field({ nullable: true })
|
|
176
180
|
creator: User
|
|
@@ -5,7 +5,7 @@ import { Bizplace } from '@things-factory/biz-base'
|
|
|
5
5
|
import { Product } from '@things-factory/product-base'
|
|
6
6
|
import { Domain } from '@things-factory/shell'
|
|
7
7
|
|
|
8
|
-
import { INVENTORY_STATUS, INVENTORY_TRANSACTION_TYPE, LOCATION_STATUS } from '../constants'
|
|
8
|
+
import { INVENTORY_STATUS, INVENTORY_TRANSACTION_TYPE, LOCATION_STATUS, LOCATION_TYPE } from '../constants'
|
|
9
9
|
import { Inventory, InventoryHistory, Location } from '../service'
|
|
10
10
|
import { InventoryNoGenerator } from '../utils'
|
|
11
11
|
|
|
@@ -90,15 +90,7 @@ export class InventoryUtil {
|
|
|
90
90
|
inventory = await this.createInventory(inventory)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
await generateInventoryHistory(
|
|
94
|
-
inventory,
|
|
95
|
-
refOrder,
|
|
96
|
-
transactionType,
|
|
97
|
-
changedQty,
|
|
98
|
-
changedUom,
|
|
99
|
-
this.user,
|
|
100
|
-
this.trxMgr
|
|
101
|
-
)
|
|
93
|
+
await generateInventoryHistory(inventory, refOrder, transactionType, changedQty, changedUom, this.user, this.trxMgr)
|
|
102
94
|
|
|
103
95
|
return inventory
|
|
104
96
|
}
|
|
@@ -148,11 +140,11 @@ export async function generateInventoryHistory(
|
|
|
148
140
|
const lastInvHistory: InventoryHistory = await invHistoryRepo.findOne({
|
|
149
141
|
where: {
|
|
150
142
|
domain: inventory.domain,
|
|
151
|
-
palletId: inventory.palletId
|
|
143
|
+
palletId: inventory.palletId
|
|
152
144
|
},
|
|
153
145
|
order: {
|
|
154
146
|
seq: 'DESC'
|
|
155
|
-
}
|
|
147
|
+
}
|
|
156
148
|
})
|
|
157
149
|
|
|
158
150
|
let seq: number = 0
|
|
@@ -165,7 +157,7 @@ export async function generateInventoryHistory(
|
|
|
165
157
|
seq = lastInvHistory.seq + 1
|
|
166
158
|
}
|
|
167
159
|
|
|
168
|
-
let remainQty = (
|
|
160
|
+
let remainQty = (openingQty || 0) + (qty || 0)
|
|
169
161
|
|
|
170
162
|
let inventoryHistory: any = new InventoryHistory()
|
|
171
163
|
|
|
@@ -373,3 +365,134 @@ export async function getProductBundleInventory(
|
|
|
373
365
|
|
|
374
366
|
return result
|
|
375
367
|
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* @description This function will return multiple products
|
|
371
|
+
* and it is different with @inventoriesByStrategy that returns
|
|
372
|
+
* inventories for one product only
|
|
373
|
+
* @param {string} bizplaceId
|
|
374
|
+
* @param {string} worksheetId
|
|
375
|
+
* @param {any[]} orderProducts
|
|
376
|
+
* @param {string} pickingStrategy
|
|
377
|
+
* @param {[Object]} locationSortingRules
|
|
378
|
+
* @param {EntityManager} trxMgr
|
|
379
|
+
* @returns inventories for multiple products
|
|
380
|
+
*/
|
|
381
|
+
export async function getInventoriesByStrategy(
|
|
382
|
+
domainId: string,
|
|
383
|
+
bizplaceId: string,
|
|
384
|
+
worksheetId: string,
|
|
385
|
+
orderProducts: any[],
|
|
386
|
+
pickingStrategy: string,
|
|
387
|
+
locationSortingRules: any[],
|
|
388
|
+
trxMgr: EntityManager
|
|
389
|
+
): Promise<Inventory[]> {
|
|
390
|
+
let orderProductsJSON: string = JSON.stringify(orderProducts)
|
|
391
|
+
let orderBy: string = 'ORDER BY op."productId"'
|
|
392
|
+
|
|
393
|
+
let locationSortings: string[] = (locationSortingRules || []).map((rule: { name: string; descOrder: boolean }) => {
|
|
394
|
+
return `, l.${rule.name} ${rule.descOrder ? 'DESC' : ''}`
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
switch (pickingStrategy.toUpperCase()) {
|
|
398
|
+
case 'FIFO':
|
|
399
|
+
orderBy += ', i.created_at'
|
|
400
|
+
if (locationSortingRules?.length) {
|
|
401
|
+
orderBy += locationSortings.join('')
|
|
402
|
+
}
|
|
403
|
+
break
|
|
404
|
+
|
|
405
|
+
case 'LIFO':
|
|
406
|
+
orderBy += ', i.created_at DESC'
|
|
407
|
+
if (locationSortingRules?.length) {
|
|
408
|
+
orderBy += locationSortings.join('')
|
|
409
|
+
}
|
|
410
|
+
break
|
|
411
|
+
|
|
412
|
+
case 'FEFO':
|
|
413
|
+
orderBy += ', i.expiration_date'
|
|
414
|
+
if (locationSortingRules?.length) {
|
|
415
|
+
orderBy += locationSortings.join('')
|
|
416
|
+
}
|
|
417
|
+
break
|
|
418
|
+
|
|
419
|
+
case 'LOCATION':
|
|
420
|
+
if (locationSortingRules?.length) {
|
|
421
|
+
orderBy += locationSortings.join('')
|
|
422
|
+
} else orderBy += ', l.name DESC'
|
|
423
|
+
break
|
|
424
|
+
|
|
425
|
+
default:
|
|
426
|
+
orderBy += ', i.created_at'
|
|
427
|
+
break
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
await trxMgr.query(
|
|
431
|
+
`
|
|
432
|
+
CREATE TEMP TABLE temp_op2(
|
|
433
|
+
"productId" VARCHAR(50),
|
|
434
|
+
"batchId" VARCHAR(50),
|
|
435
|
+
"packingType" VARCHAR(50),
|
|
436
|
+
"packingSize" INT,
|
|
437
|
+
"uom" VARCHAR(10),
|
|
438
|
+
"releaseQty" INT
|
|
439
|
+
);
|
|
440
|
+
`
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
await trxMgr.query(
|
|
444
|
+
`
|
|
445
|
+
INSERT INTO temp_op2
|
|
446
|
+
SELECT "productId", "batchId", "packingType", "packingSize", "uom", "releaseQty"
|
|
447
|
+
FROM JSON_POPULATE_RECORDSET(NULL::temp_op2, $1) js
|
|
448
|
+
`,
|
|
449
|
+
[orderProductsJSON]
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
await trxMgr.query(
|
|
453
|
+
`
|
|
454
|
+
CREATE TEMP TABLE acc_oi2 AS (
|
|
455
|
+
SELECT oi.inventory_id, SUM(oi.release_qty) AS total_release_qty, SUM(oi.release_uom_value) AS total_release_uom_value
|
|
456
|
+
FROM order_inventories oi
|
|
457
|
+
WHERE oi.status IN ('PENDING','PENDING_RECEIVE','PENDING_WORKSHEET','PENDING_SPLIT')
|
|
458
|
+
AND oi.bizplace_id = $1
|
|
459
|
+
AND oi.inventory_id NOTNULL
|
|
460
|
+
AND oi.ref_worksheet_id != $2
|
|
461
|
+
GROUP BY oi.inventory_id
|
|
462
|
+
)
|
|
463
|
+
`,
|
|
464
|
+
[bizplaceId, worksheetId]
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
// get inventories
|
|
468
|
+
let inventories = await trxMgr.query(
|
|
469
|
+
`
|
|
470
|
+
SELECT
|
|
471
|
+
i.id,
|
|
472
|
+
op."productId",
|
|
473
|
+
op."batchId",
|
|
474
|
+
i.qty - COALESCE(i.locked_qty,0) - COALESCE(foo.total_release_qty,0) AS "remainQty",
|
|
475
|
+
i.uom_value - COALESCE(i.locked_uom_value,0) - COALESCE(foo.total_release_uom_value,0) AS "remainUomValue",
|
|
476
|
+
op."packingType",
|
|
477
|
+
op."packingSize",
|
|
478
|
+
op."uom"
|
|
479
|
+
FROM inventories i
|
|
480
|
+
INNER JOIN locations l ON i.location_id = l.id
|
|
481
|
+
AND l.TYPE NOT IN ($1, $2)
|
|
482
|
+
INNER JOIN temp_op2 op ON i.product_id = op."productId"::uuid
|
|
483
|
+
AND i.batch_id = op."batchId"
|
|
484
|
+
AND i.packing_type = op."packingType"
|
|
485
|
+
AND i.packing_size = op."packingSize"
|
|
486
|
+
LEFT JOIN acc_oi2 foo ON i.id = foo.inventory_id
|
|
487
|
+
WHERE i.domain_id = $3
|
|
488
|
+
AND i.bizplace_id = $4
|
|
489
|
+
AND i.status = $5
|
|
490
|
+
${orderBy}
|
|
491
|
+
`,
|
|
492
|
+
[LOCATION_TYPE.QUARANTINE, LOCATION_TYPE.RESERVE, domainId, bizplaceId, INVENTORY_STATUS.STORED]
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
await trxMgr.query('DROP TABLE temp_op2, acc_oi2')
|
|
496
|
+
|
|
497
|
+
return inventories
|
|
498
|
+
}
|