@things-factory/warehouse-base 4.2.12 → 4.3.0
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/index.js +1 -0
- package/dist-server/constants/index.js.map +1 -1
- package/dist-server/constants/tote.js +9 -0
- package/dist-server/constants/tote.js.map +1 -0
- package/dist-server/index.js +3 -1
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/index.js +7 -2
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/inventory/inventory-query.js +2 -1
- package/dist-server/service/inventory/inventory-query.js.map +1 -1
- package/dist-server/service/inventory-change/inventory-change-mutation.js +334 -273
- package/dist-server/service/inventory-change/inventory-change-mutation.js.map +1 -1
- package/dist-server/service/inventory-history/inventory-history-query.js +23 -2
- package/dist-server/service/inventory-history/inventory-history-query.js.map +1 -1
- package/dist-server/service/tote/index.js +9 -0
- package/dist-server/service/tote/index.js.map +1 -0
- package/dist-server/service/tote/tote-mutation.js +192 -0
- package/dist-server/service/tote/tote-mutation.js.map +1 -0
- package/dist-server/service/tote/tote-query.js +146 -0
- package/dist-server/service/tote/tote-query.js.map +1 -0
- package/dist-server/service/tote/tote-types.js +75 -0
- package/dist-server/service/tote/tote-types.js.map +1 -0
- package/dist-server/service/tote/tote.js +98 -0
- package/dist-server/service/tote/tote.js.map +1 -0
- package/dist-server/utils/inventory-util.js +5 -3
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +8 -8
- package/server/constants/index.ts +1 -0
- package/server/constants/tote.ts +5 -0
- package/server/index.ts +2 -0
- package/server/service/index.ts +7 -2
- package/server/service/inventory/inventory-query.ts +2 -1
- package/server/service/inventory-change/index.ts +1 -1
- package/server/service/inventory-change/inventory-change-mutation.ts +471 -407
- package/server/service/inventory-history/inventory-history-query.ts +23 -2
- package/server/service/tote/index.ts +6 -0
- package/server/service/tote/tote-mutation.ts +200 -0
- package/server/service/tote/tote-query.ts +102 -0
- package/server/service/tote/tote-types.ts +44 -0
- package/server/service/tote/tote.ts +77 -0
- package/server/utils/inventory-util.ts +5 -3
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
|
2
2
|
import { EntityManager, In, MoreThan, Not } from 'typeorm'
|
|
3
3
|
|
|
4
|
-
import { User } from '@things-factory/auth-base'
|
|
4
|
+
import { Privilege, User } from '@things-factory/auth-base'
|
|
5
5
|
import { Bizplace } from '@things-factory/biz-base'
|
|
6
6
|
import { generateId } from '@things-factory/id-rule-base'
|
|
7
7
|
import { MarketplaceStore } from '@things-factory/integration-marketplace'
|
|
8
8
|
import { Sellercraft, SellercraftStatus } from '@things-factory/integration-sellercraft'
|
|
9
|
+
import { sendNotification } from '@things-factory/notification'
|
|
9
10
|
import { Product } from '@things-factory/product-base'
|
|
10
11
|
import { PartnerSetting, Setting } from '@things-factory/setting-base'
|
|
11
12
|
import { Domain } from '@things-factory/shell'
|
|
@@ -69,7 +70,6 @@ export class InventoryChangeMutation {
|
|
|
69
70
|
@Ctx() context: any
|
|
70
71
|
): Promise<InventoryChange[]> {
|
|
71
72
|
const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
|
|
72
|
-
|
|
73
73
|
let results = []
|
|
74
74
|
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
|
75
75
|
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
|
@@ -152,6 +152,14 @@ export class InventoryChangeMutation {
|
|
|
152
152
|
})
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
const invLockedQty: number = foundExistingPallet?.lockedQty == null ? 0 : foundExistingPallet?.lockedQty
|
|
156
|
+
|
|
157
|
+
if (patches[i]?.qty < invLockedQty) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
'Adjusted qty value should not be lower than released qty, kindly contact our support if you have difficulties'
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
155
163
|
if (foundExistingPallet) {
|
|
156
164
|
delete patches[i].serialNumbers
|
|
157
165
|
_updateRecords.push(patches[i])
|
|
@@ -286,8 +294,11 @@ export class InventoryChangeMutation {
|
|
|
286
294
|
product = existingRecord.product
|
|
287
295
|
}
|
|
288
296
|
|
|
297
|
+
updateRecord.transactionType == 'MISSING'
|
|
298
|
+
? (updateRecord.transactionType = 'MISSING')
|
|
299
|
+
: (updateRecord.transactionType = 'CHANGES')
|
|
300
|
+
|
|
289
301
|
updateRecord.status = 'PENDING'
|
|
290
|
-
updateRecord.transactionType = 'CHANGES'
|
|
291
302
|
|
|
292
303
|
updateRecord.expirationDate =
|
|
293
304
|
((updateRecord?.expirationDate && new Date(updateRecord.expirationDate).getFullYear()) || 0) < 2000
|
|
@@ -345,6 +356,47 @@ export class InventoryChangeMutation {
|
|
|
345
356
|
}
|
|
346
357
|
}
|
|
347
358
|
|
|
359
|
+
const notificationApprover: any = await tx
|
|
360
|
+
.getRepository(Privilege)
|
|
361
|
+
.createQueryBuilder('p')
|
|
362
|
+
.select('u.*')
|
|
363
|
+
.innerJoin('p.roles', 'r')
|
|
364
|
+
.innerJoin('r.users', 'u')
|
|
365
|
+
.where('p.name = :name', { name: 'mutation' })
|
|
366
|
+
.andWhere('p.category = :category', { category: 'inventory' })
|
|
367
|
+
.andWhere('r.domain_id = :domainId', { domainId: domain.id })
|
|
368
|
+
.groupBy('u.id')
|
|
369
|
+
.getRawMany()
|
|
370
|
+
if (_updateRecords.some(res => res.transactionType == 'MISSING')) {
|
|
371
|
+
if (notificationApprover?.length && context.header?.referer) {
|
|
372
|
+
const receivers: any[] = notificationApprover.map(user => user.id)
|
|
373
|
+
const msg = {
|
|
374
|
+
title: `Missing stock identified. Review this transaction in Inventory Adjustment Approval.`,
|
|
375
|
+
body: ``,
|
|
376
|
+
url: context.header.referer,
|
|
377
|
+
data: { url: context.header.referer }
|
|
378
|
+
}
|
|
379
|
+
await sendNotification({
|
|
380
|
+
receivers,
|
|
381
|
+
message: { ...msg }
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
if (notificationApprover?.length && context.header?.referer) {
|
|
386
|
+
const receivers: any[] = notificationApprover.map(user => user.id)
|
|
387
|
+
const msg = {
|
|
388
|
+
title: `There is an inventory adjustment pending for approval, kindly review within 1 hour to avoid any operation conflict.`,
|
|
389
|
+
body: ``,
|
|
390
|
+
url: context.header.referer,
|
|
391
|
+
data: { url: context.header.referer }
|
|
392
|
+
}
|
|
393
|
+
await sendNotification({
|
|
394
|
+
receivers,
|
|
395
|
+
message: { ...msg }
|
|
396
|
+
})
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
348
400
|
return true
|
|
349
401
|
}
|
|
350
402
|
|
|
@@ -355,411 +407,9 @@ export class InventoryChangeMutation {
|
|
|
355
407
|
@Arg('patches', type => [InventoryChangePatch]) patches: InventoryChangePatch[],
|
|
356
408
|
@Ctx() context: any
|
|
357
409
|
): Promise<InventoryChangeList> {
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
// Get Selected Inventory Change Data
|
|
361
|
-
const _inventoryChanges = await tx.getRepository(InventoryChange).find({
|
|
362
|
-
where: { id: In(patches.map(item => item.id)) },
|
|
363
|
-
relations: [
|
|
364
|
-
'inventory',
|
|
365
|
-
'inventory.bizplace',
|
|
366
|
-
'inventory.bizplace.domain',
|
|
367
|
-
'inventory.product',
|
|
368
|
-
'inventory.location',
|
|
369
|
-
'inventory.warehouse',
|
|
370
|
-
'bizplace',
|
|
371
|
-
'bizplace.domain',
|
|
372
|
-
'bizplace.company',
|
|
373
|
-
'bizplace.company.domain',
|
|
374
|
-
'product',
|
|
375
|
-
'product.productDetails',
|
|
376
|
-
'product.productDetails.childProductDetail',
|
|
377
|
-
'location'
|
|
378
|
-
],
|
|
379
|
-
order: {
|
|
380
|
-
createdAt: 'ASC'
|
|
381
|
-
}
|
|
382
|
-
})
|
|
383
|
-
|
|
384
|
-
let arrLockedInventory: InventoryChange[] = []
|
|
385
|
-
|
|
386
|
-
if (_inventoryChanges.length > 0) {
|
|
387
|
-
let today = new Date(),
|
|
388
|
-
year = today.getFullYear(),
|
|
389
|
-
month = today.getMonth(),
|
|
390
|
-
date = today.getDate()
|
|
391
|
-
|
|
392
|
-
for (let i = 0; i < _inventoryChanges.length; i++) {
|
|
393
|
-
if (_inventoryChanges[i].status.toLocaleLowerCase() != 'pending') continue
|
|
394
|
-
|
|
395
|
-
const newRecord: any = { ..._inventoryChanges[i] },
|
|
396
|
-
newHistoryRecord: any = { ..._inventoryChanges[i] }
|
|
397
|
-
|
|
398
|
-
// Adjustment of existing Inventory
|
|
399
|
-
if (_inventoryChanges[i].inventory != null) {
|
|
400
|
-
let inventoryId = _inventoryChanges[i].inventory.id
|
|
401
|
-
let inventory: Inventory = await tx.getRepository(Inventory).findOne({
|
|
402
|
-
where: { id: inventoryId },
|
|
403
|
-
relations: [
|
|
404
|
-
'domain',
|
|
405
|
-
'bizplace',
|
|
406
|
-
'bizplace.domain',
|
|
407
|
-
'bizplace.company',
|
|
408
|
-
'bizplace.company.domain',
|
|
409
|
-
'product',
|
|
410
|
-
'product.productDetails',
|
|
411
|
-
'product.productDetails.childProductDetail',
|
|
412
|
-
'warehouse',
|
|
413
|
-
'location',
|
|
414
|
-
'creator',
|
|
415
|
-
'updater'
|
|
416
|
-
]
|
|
417
|
-
})
|
|
418
|
-
|
|
419
|
-
const customerDomain: Domain = inventory.bizplace.domain
|
|
420
|
-
|
|
421
|
-
// Check for locked inventory, and stop from udpating inventory
|
|
422
|
-
if (inventory.lockedQty > 0) {
|
|
423
|
-
arrLockedInventory.push(_inventoryChanges[i])
|
|
424
|
-
continue
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Check for Terminated inventory, then update InventoryChange entity, and stop from udpating inventory
|
|
428
|
-
if (inventory.status == INVENTORY_STATUS.TERMINATED) {
|
|
429
|
-
_inventoryChanges[i] = { ..._inventoryChanges[i], status: 'TERMINATED' }
|
|
430
|
-
continue
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
let lastSeq = inventory.lastSeq,
|
|
434
|
-
transactionType = ''
|
|
435
|
-
|
|
436
|
-
newHistoryRecord.openingQty = inventory.qty
|
|
437
|
-
newHistoryRecord.openingUomValue = inventory.uomValue
|
|
438
|
-
|
|
439
|
-
// Get last row of InventoryHistory
|
|
440
|
-
let latestEntry = await tx.getRepository(InventoryHistory).findOne({
|
|
441
|
-
where: { palletId: inventory.palletId, domain: domain },
|
|
442
|
-
order: { seq: 'DESC' }
|
|
443
|
-
})
|
|
444
|
-
_inventoryChanges[i].lastInventoryHistory = latestEntry
|
|
445
|
-
|
|
446
|
-
// Check Change of existing inventory location
|
|
447
|
-
if (newRecord.location && newRecord.location.id != inventory.location.id) {
|
|
448
|
-
newRecord.zone = newRecord.location.zone
|
|
449
|
-
newRecord.warehouse = newRecord.location.warehouse
|
|
450
|
-
transactionType = 'ADJUSTMENT'
|
|
451
|
-
|
|
452
|
-
// Check and set current location status
|
|
453
|
-
let currentLocationInventoryCount = await tx.getRepository(Inventory).count({
|
|
454
|
-
where: { location: inventory.location, status: 'STORED', id: Not(inventory.id) }
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
if (currentLocationInventoryCount == 0) {
|
|
458
|
-
let currentLocation = await tx.getRepository(Location).findOne({
|
|
459
|
-
where: { id: inventory.location.id }
|
|
460
|
-
})
|
|
461
|
-
await tx.getRepository(Location).save({
|
|
462
|
-
...currentLocation,
|
|
463
|
-
status: LOCATION_STATUS.EMPTY
|
|
464
|
-
})
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
// Check Change of existing inventory quantity
|
|
469
|
-
if (newRecord.qty != null && newRecord.qty != inventory.qty) {
|
|
470
|
-
newHistoryRecord.qty = newRecord.qty - inventory.qty
|
|
471
|
-
if (newRecord.qty < 1) {
|
|
472
|
-
newRecord.qty = 0
|
|
473
|
-
newRecord.uomValue = 0
|
|
474
|
-
}
|
|
475
|
-
transactionType = 'ADJUSTMENT'
|
|
476
|
-
} else {
|
|
477
|
-
newHistoryRecord.qty = 0
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// Check Change of existing inventory uomValue
|
|
481
|
-
if (newRecord.uomValue != null && newRecord.uomValue != inventory.uomValue) {
|
|
482
|
-
newHistoryRecord.uomValue = newRecord.uomValue - inventory.uomValue
|
|
483
|
-
Math.round(newHistoryRecord.uomValue * 100) / 100
|
|
484
|
-
transactionType = 'ADJUSTMENT'
|
|
485
|
-
} else {
|
|
486
|
-
newHistoryRecord.uomValue = 0
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// Terminate current inventory history if there is change of bizplace, product, batchId, packingType, or uom
|
|
490
|
-
if (
|
|
491
|
-
(newRecord.bizplace && inventory.bizplace.id !== newRecord.bizplace.id) ||
|
|
492
|
-
(newRecord.product && inventory.product.id !== newRecord.product.id) ||
|
|
493
|
-
(newRecord.batchId && inventory.batchId !== newRecord.batchId) ||
|
|
494
|
-
(newRecord.packingType && inventory.packingType !== newRecord.packingType) ||
|
|
495
|
-
(newRecord.uom && inventory.uom !== newRecord.uom)
|
|
496
|
-
) {
|
|
497
|
-
transactionType = 'ADJUSTMENT'
|
|
498
|
-
lastSeq = lastSeq + 1
|
|
499
|
-
let inventoryHistory = {
|
|
500
|
-
...inventory,
|
|
501
|
-
domain: domain,
|
|
502
|
-
bizplace: inventory.bizplace.id,
|
|
503
|
-
openingQty: inventory.qty,
|
|
504
|
-
openingUomValue: inventory.uomValue,
|
|
505
|
-
qty: -inventory.qty || 0,
|
|
506
|
-
uom: inventory.uom,
|
|
507
|
-
uomValue: -inventory.uomValue || 0,
|
|
508
|
-
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
509
|
-
seq: lastSeq,
|
|
510
|
-
transactionType: transactionType,
|
|
511
|
-
status: INVENTORY_STATUS.TERMINATED,
|
|
512
|
-
productId: inventory.product.id,
|
|
513
|
-
warehouseId: inventory.warehouse.id,
|
|
514
|
-
locationId: inventory.location.id,
|
|
515
|
-
packingType: inventory.packingType,
|
|
516
|
-
creator: user,
|
|
517
|
-
updater: user
|
|
518
|
-
}
|
|
519
|
-
delete inventoryHistory.id
|
|
520
|
-
delete inventoryHistory.createdAt
|
|
521
|
-
delete inventoryHistory.updatedAt
|
|
522
|
-
await tx.getRepository(InventoryHistory).save(inventoryHistory)
|
|
523
|
-
newHistoryRecord.qty = newRecord.qty != null ? newRecord.qty : inventory.qty || 0
|
|
524
|
-
newHistoryRecord.uomValue = newRecord.uomValue != null ? newRecord.uomValue : inventory.uomValue || 0
|
|
525
|
-
newHistoryRecord.openingQty = 0
|
|
526
|
-
newHistoryRecord.openingUomValue = 0
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// Set and update inventory and inventory history data
|
|
530
|
-
lastSeq = lastSeq + 1
|
|
531
|
-
clean(newHistoryRecord)
|
|
532
|
-
let inventoryHistory = {
|
|
533
|
-
...inventory,
|
|
534
|
-
...newHistoryRecord,
|
|
535
|
-
domain: domain,
|
|
536
|
-
creator: user,
|
|
537
|
-
updater: user,
|
|
538
|
-
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
539
|
-
status: 'STORED',
|
|
540
|
-
seq: lastSeq,
|
|
541
|
-
transactionType: transactionType == '' ? 'ADJUSTMENT' : transactionType,
|
|
542
|
-
productId: newRecord.product ? newRecord.product.id : inventory.product.id,
|
|
543
|
-
warehouseId: newRecord.warehouse ? newRecord.warehouse.id : inventory.warehouse.id,
|
|
544
|
-
locationId:
|
|
545
|
-
newRecord.location && newRecord.location.id != inventory.location.id
|
|
546
|
-
? newRecord.location.id
|
|
547
|
-
: inventory.location.id,
|
|
548
|
-
uom: newRecord.uom != null ? newRecord.uom : inventory.uom
|
|
549
|
-
}
|
|
550
|
-
delete inventoryHistory.id
|
|
551
|
-
delete inventoryHistory.createdAt
|
|
552
|
-
delete inventoryHistory.updatedAt
|
|
553
|
-
await tx.getRepository(InventoryHistory).save(inventoryHistory)
|
|
554
|
-
|
|
555
|
-
if (newRecord.qty != null && newRecord.qty == 0) {
|
|
556
|
-
++lastSeq
|
|
557
|
-
delete inventoryHistory.id
|
|
558
|
-
inventoryHistory = {
|
|
559
|
-
...inventoryHistory,
|
|
560
|
-
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
561
|
-
qty: 0,
|
|
562
|
-
uomValue: 0,
|
|
563
|
-
openingQty: 0,
|
|
564
|
-
openingUomValue: 0,
|
|
565
|
-
seq: lastSeq,
|
|
566
|
-
transactionType: 'TERMINATED',
|
|
567
|
-
status: 'TERMINATED'
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
await tx.getRepository(InventoryHistory).save(inventoryHistory)
|
|
571
|
-
}
|
|
410
|
+
const inventoryChangeList = await approveInventoryChanges(patches, context)
|
|
572
411
|
|
|
573
|
-
|
|
574
|
-
await tx.getRepository(Inventory).save({
|
|
575
|
-
...inventory,
|
|
576
|
-
...newRecord,
|
|
577
|
-
id: inventoryId,
|
|
578
|
-
status: (newRecord.qty != null ? newRecord.qty : inventory.qty) > 0 ? 'STORED' : 'TERMINATED',
|
|
579
|
-
updater: user,
|
|
580
|
-
lastSeq: lastSeq
|
|
581
|
-
})
|
|
582
|
-
|
|
583
|
-
//Check and set latest location status
|
|
584
|
-
if (newRecord.qty != null ? newRecord.qty : inventory.qty > 0) {
|
|
585
|
-
var location = await tx.getRepository(Location).findOne({
|
|
586
|
-
where: { id: newRecord.location ? newRecord.location.id : inventory.location.id }
|
|
587
|
-
})
|
|
588
|
-
await tx.getRepository(Location).save({
|
|
589
|
-
...location,
|
|
590
|
-
status: LOCATION_STATUS.OCCUPIED
|
|
591
|
-
})
|
|
592
|
-
} else {
|
|
593
|
-
let latestLocationInventoryCount = await tx.getRepository(Inventory).count({
|
|
594
|
-
where: {
|
|
595
|
-
location: newRecord.location ? newRecord.location.id : inventory.location.id,
|
|
596
|
-
status: 'STORED',
|
|
597
|
-
id: Not(inventory.id)
|
|
598
|
-
}
|
|
599
|
-
})
|
|
600
|
-
if (latestLocationInventoryCount == 0) {
|
|
601
|
-
let latestLocation = await tx.getRepository(Location).findOne({
|
|
602
|
-
where: { id: newRecord.location ? newRecord.location.id : inventory.location.id }
|
|
603
|
-
})
|
|
604
|
-
await tx.getRepository(Location).save({
|
|
605
|
-
...latestLocation,
|
|
606
|
-
status: LOCATION_STATUS.EMPTY
|
|
607
|
-
})
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
await upsertInventoryItems(context, _inventoryChanges[i], 'APPROVED', tx)
|
|
612
|
-
|
|
613
|
-
const sellercraft: Sellercraft = await tx
|
|
614
|
-
.getRepository(Sellercraft)
|
|
615
|
-
.findOne({ domain: customerDomain, status: SellercraftStatus.ACTIVE })
|
|
616
|
-
|
|
617
|
-
const companyDomain: Domain = inventory.bizplace?.company.domain
|
|
618
|
-
|
|
619
|
-
if (sellercraft) {
|
|
620
|
-
const sellercraftCtrl: SellercraftController = new SellercraftController(tx, domain, user)
|
|
621
|
-
await sellercraftCtrl.updateSellercraftStock(sellercraft, inventory)
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// check for any existing active marketplace connection, update marketplace selling qty
|
|
625
|
-
const marketplaceStores: MarketplaceStore[] = await tx.getRepository(MarketplaceStore).find({
|
|
626
|
-
where: { domain: companyDomain, status: 'ACTIVE', isAutoUpdateStockQty: true },
|
|
627
|
-
relations: ['marketplaceDistributors']
|
|
628
|
-
})
|
|
629
|
-
|
|
630
|
-
if (marketplaceStores?.length && marketplaceStores.some(store => store.isAutoUpdateStockQty)) {
|
|
631
|
-
const ecommerceCtrl: EcommerceController = new EcommerceController(tx, domain, user)
|
|
632
|
-
await ecommerceCtrl.updateProductVariationStock(marketplaceStores, inventory.product.id, companyDomain)
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// Adding Inventory
|
|
637
|
-
else {
|
|
638
|
-
const total = await tx.getRepository(Inventory).count({
|
|
639
|
-
createdAt: MoreThan(new Date(year, month, date))
|
|
640
|
-
})
|
|
641
|
-
|
|
642
|
-
const yy = String(year).substr(String(year).length - 2)
|
|
643
|
-
const mm = String(month + 1).padStart(2, '0')
|
|
644
|
-
const dd = String(date).padStart(2, '0')
|
|
645
|
-
|
|
646
|
-
const dateStr = yy + mm + dd
|
|
647
|
-
|
|
648
|
-
let palletId = newRecord.palletId
|
|
649
|
-
|
|
650
|
-
if (!newRecord.palletId?.trim()) {
|
|
651
|
-
palletId = await generateId({
|
|
652
|
-
domain: domain,
|
|
653
|
-
type: 'adjustment_pallet_id',
|
|
654
|
-
seed: {
|
|
655
|
-
batchId: newRecord.batchId,
|
|
656
|
-
date: dateStr
|
|
657
|
-
}
|
|
658
|
-
})
|
|
659
|
-
if (!palletId) throw new Error('No adjustment pallet id setting rule found')
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
var location = await tx.getRepository(Location).findOne({
|
|
663
|
-
where: { id: newRecord.location.id },
|
|
664
|
-
relations: ['warehouse']
|
|
665
|
-
})
|
|
666
|
-
newRecord.location = location
|
|
667
|
-
newRecord.zone = location.zone
|
|
668
|
-
newRecord.warehouse = location.warehouse
|
|
669
|
-
|
|
670
|
-
newRecord.status = INVENTORY_STATUS.STORED
|
|
671
|
-
newRecord.name = palletId
|
|
672
|
-
newRecord.palletId = palletId
|
|
673
|
-
|
|
674
|
-
const warehouseCartonSetting: Setting = await tx.getRepository(Setting).findOne({
|
|
675
|
-
where: { domain, category: 'id-rule', name: 'enable-carton-label' }
|
|
676
|
-
})
|
|
677
|
-
|
|
678
|
-
const partnerCartonSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
|
|
679
|
-
where: { setting: warehouseCartonSetting, domain, partnerDomain: newRecord.bizplace?.domain }
|
|
680
|
-
})
|
|
681
|
-
|
|
682
|
-
if (partnerCartonSetting?.value) {
|
|
683
|
-
let cartonId = await generateId({
|
|
684
|
-
domain: domain,
|
|
685
|
-
type: 'adjustment_carton_id',
|
|
686
|
-
seed: { date: dateStr }
|
|
687
|
-
})
|
|
688
|
-
if (!cartonId) throw new Error('No adjustment carton id setting rule found')
|
|
689
|
-
|
|
690
|
-
newRecord.cartonId = cartonId
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
let expirationDate =
|
|
694
|
-
((newRecord?.expirationDate && new Date(newRecord.expirationDate).getFullYear()) || 0) < 2000
|
|
695
|
-
? null
|
|
696
|
-
: newRecord.expirationDate
|
|
697
|
-
|
|
698
|
-
let savedInventory = await tx.getRepository(Inventory).save({
|
|
699
|
-
...newRecord,
|
|
700
|
-
expirationDate,
|
|
701
|
-
domain: domain,
|
|
702
|
-
creator: user,
|
|
703
|
-
updater: user,
|
|
704
|
-
lastSeq: 0
|
|
705
|
-
})
|
|
706
|
-
|
|
707
|
-
await tx.getRepository(InventoryHistory).save({
|
|
708
|
-
...newRecord,
|
|
709
|
-
domain: domain,
|
|
710
|
-
creator: user,
|
|
711
|
-
updater: user,
|
|
712
|
-
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
713
|
-
seq: 0,
|
|
714
|
-
transactionType: 'NEW',
|
|
715
|
-
productId: newRecord.product.id,
|
|
716
|
-
warehouseId: newRecord.warehouse.id,
|
|
717
|
-
locationId: newRecord.location.id,
|
|
718
|
-
inventory: savedInventory,
|
|
719
|
-
expirationDate: expirationDate
|
|
720
|
-
})
|
|
721
|
-
|
|
722
|
-
await tx.getRepository(Location).save({
|
|
723
|
-
...location,
|
|
724
|
-
status: LOCATION_STATUS.OCCUPIED
|
|
725
|
-
})
|
|
726
|
-
|
|
727
|
-
_inventoryChanges[i].inventory = savedInventory
|
|
728
|
-
_inventoryChanges[i].palletId = savedInventory.palletId
|
|
729
|
-
|
|
730
|
-
await upsertInventoryItems(context, _inventoryChanges[i], 'APPROVED', tx)
|
|
731
|
-
|
|
732
|
-
const sellercraft: Sellercraft = await tx
|
|
733
|
-
.getRepository(Sellercraft)
|
|
734
|
-
.findOne({ domain: newRecord.bizplace.domain, status: SellercraftStatus.ACTIVE })
|
|
735
|
-
|
|
736
|
-
const companyDomain: Domain = newRecord.bizplace?.company.domain
|
|
737
|
-
|
|
738
|
-
if (sellercraft) {
|
|
739
|
-
const sellercraftCtrl: SellercraftController = new SellercraftController(tx, domain, user)
|
|
740
|
-
await sellercraftCtrl.updateSellercraftStock(sellercraft, newRecord)
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
// update marketplace store qty
|
|
744
|
-
// check for any existing active marketplace connection, update marketplace selling qty
|
|
745
|
-
const marketplaceStores: MarketplaceStore[] = await tx.getRepository(MarketplaceStore).find({
|
|
746
|
-
where: { domain: companyDomain, status: 'ACTIVE', isAutoUpdateStockQty: true },
|
|
747
|
-
relations: ['marketplaceDistributors']
|
|
748
|
-
})
|
|
749
|
-
|
|
750
|
-
if (marketplaceStores?.length && marketplaceStores.some(store => store.isAutoUpdateStockQty)) {
|
|
751
|
-
const ecommerceCtrl: EcommerceController = new EcommerceController(tx, domain, user)
|
|
752
|
-
await ecommerceCtrl.updateProductVariationStock(marketplaceStores, newRecord.product.id, companyDomain)
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
_inventoryChanges[i].status = 'APPROVED'
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
await tx.getRepository(InventoryChange).save(_inventoryChanges)
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
return { items: arrLockedInventory, total: arrLockedInventory.length }
|
|
412
|
+
return inventoryChangeList
|
|
763
413
|
}
|
|
764
414
|
|
|
765
415
|
@Directive('@privilege(category: "inventory_adjustment_approval", privilege: "mutation")')
|
|
@@ -883,3 +533,417 @@ async function upsertInventoryItems(context, inventoryChange, approvalStatus, tx
|
|
|
883
533
|
})
|
|
884
534
|
)
|
|
885
535
|
}
|
|
536
|
+
|
|
537
|
+
export async function approveInventoryChanges(patches: any, context: any) {
|
|
538
|
+
const { domain, user, tx }: { domain: Domain; user: User; tx: EntityManager } = context.state
|
|
539
|
+
|
|
540
|
+
// Get Selected Inventory Change Data
|
|
541
|
+
const _inventoryChanges = await tx.getRepository(InventoryChange).find({
|
|
542
|
+
where: { id: In(patches.map(item => item.id)) },
|
|
543
|
+
relations: [
|
|
544
|
+
'inventory',
|
|
545
|
+
'inventory.bizplace',
|
|
546
|
+
'inventory.bizplace.domain',
|
|
547
|
+
'inventory.product',
|
|
548
|
+
'inventory.location',
|
|
549
|
+
'inventory.warehouse',
|
|
550
|
+
'bizplace',
|
|
551
|
+
'bizplace.domain',
|
|
552
|
+
'bizplace.company',
|
|
553
|
+
'bizplace.company.domain',
|
|
554
|
+
'product',
|
|
555
|
+
'product.productDetails',
|
|
556
|
+
'product.productDetails.childProductDetail',
|
|
557
|
+
'location'
|
|
558
|
+
],
|
|
559
|
+
order: {
|
|
560
|
+
createdAt: 'ASC'
|
|
561
|
+
}
|
|
562
|
+
})
|
|
563
|
+
|
|
564
|
+
let arrLockedInventory: InventoryChange[] = []
|
|
565
|
+
|
|
566
|
+
if (_inventoryChanges.length > 0) {
|
|
567
|
+
let today = new Date(),
|
|
568
|
+
year = today.getFullYear(),
|
|
569
|
+
month = today.getMonth(),
|
|
570
|
+
date = today.getDate()
|
|
571
|
+
|
|
572
|
+
for (let i = 0; i < _inventoryChanges.length; i++) {
|
|
573
|
+
if (_inventoryChanges[i].status.toLocaleLowerCase() != 'pending') continue
|
|
574
|
+
|
|
575
|
+
const newRecord: any = { ..._inventoryChanges[i] },
|
|
576
|
+
newHistoryRecord: any = { ..._inventoryChanges[i] }
|
|
577
|
+
|
|
578
|
+
// Adjustment of existing Inventory
|
|
579
|
+
if (_inventoryChanges[i].inventory != null) {
|
|
580
|
+
let inventoryId = _inventoryChanges[i].inventory.id
|
|
581
|
+
let inventory: Inventory = await tx.getRepository(Inventory).findOne({
|
|
582
|
+
where: { id: inventoryId },
|
|
583
|
+
relations: [
|
|
584
|
+
'domain',
|
|
585
|
+
'bizplace',
|
|
586
|
+
'bizplace.domain',
|
|
587
|
+
'bizplace.company',
|
|
588
|
+
'bizplace.company.domain',
|
|
589
|
+
'product',
|
|
590
|
+
'product.productDetails',
|
|
591
|
+
'product.productDetails.childProductDetail',
|
|
592
|
+
'warehouse',
|
|
593
|
+
'location',
|
|
594
|
+
'creator',
|
|
595
|
+
'updater'
|
|
596
|
+
]
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
const customerDomain: Domain = inventory.bizplace.domain
|
|
600
|
+
|
|
601
|
+
// Check for locked inventory, and stop from udpating inventory
|
|
602
|
+
if (inventory.qty < inventory.lockedQty) {
|
|
603
|
+
arrLockedInventory.push(_inventoryChanges[i])
|
|
604
|
+
continue
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Check for Terminated inventory, then update InventoryChange entity, and stop from udpating inventory
|
|
608
|
+
if (inventory.status == INVENTORY_STATUS.TERMINATED) {
|
|
609
|
+
_inventoryChanges[i] = { ..._inventoryChanges[i], status: 'TERMINATED' }
|
|
610
|
+
continue
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
let lastSeq = inventory.lastSeq,
|
|
614
|
+
transactionType = ''
|
|
615
|
+
|
|
616
|
+
newHistoryRecord.openingQty = inventory.qty
|
|
617
|
+
newHistoryRecord.openingUomValue = inventory.uomValue
|
|
618
|
+
|
|
619
|
+
// Get last row of InventoryHistory
|
|
620
|
+
let latestEntry = await tx.getRepository(InventoryHistory).findOne({
|
|
621
|
+
where: { palletId: inventory.palletId, domain: domain },
|
|
622
|
+
order: { seq: 'DESC' }
|
|
623
|
+
})
|
|
624
|
+
_inventoryChanges[i].lastInventoryHistory = latestEntry
|
|
625
|
+
|
|
626
|
+
// Check Change of existing inventory location
|
|
627
|
+
if (newRecord.location && newRecord.location.id != inventory.location.id) {
|
|
628
|
+
newRecord.zone = newRecord.location.zone
|
|
629
|
+
newRecord.warehouse = newRecord.location.warehouse
|
|
630
|
+
transactionType = 'ADJUSTMENT'
|
|
631
|
+
|
|
632
|
+
// Check and set current location status
|
|
633
|
+
let currentLocationInventoryCount = await tx.getRepository(Inventory).count({
|
|
634
|
+
where: { location: inventory.location, status: 'STORED', id: Not(inventory.id) }
|
|
635
|
+
})
|
|
636
|
+
|
|
637
|
+
if (currentLocationInventoryCount == 0) {
|
|
638
|
+
let currentLocation = await tx.getRepository(Location).findOne({
|
|
639
|
+
where: { id: inventory.location.id }
|
|
640
|
+
})
|
|
641
|
+
await tx.getRepository(Location).save({
|
|
642
|
+
...currentLocation,
|
|
643
|
+
status: LOCATION_STATUS.EMPTY
|
|
644
|
+
})
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Check Change of existing inventory quantity
|
|
649
|
+
if (newRecord.qty != null && newRecord.qty != inventory.qty) {
|
|
650
|
+
newHistoryRecord.qty = newRecord.qty - inventory.qty
|
|
651
|
+
if (newRecord.qty < 1) {
|
|
652
|
+
newRecord.qty = 0
|
|
653
|
+
newRecord.uomValue = 0
|
|
654
|
+
}
|
|
655
|
+
transactionType = 'ADJUSTMENT'
|
|
656
|
+
} else {
|
|
657
|
+
newHistoryRecord.qty = 0
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Check Change of existing inventory uomValue
|
|
661
|
+
if (newRecord.uomValue != null && newRecord.uomValue != inventory.uomValue) {
|
|
662
|
+
newHistoryRecord.uomValue = newRecord.uomValue - inventory.uomValue
|
|
663
|
+
Math.round(newHistoryRecord.uomValue * 100) / 100
|
|
664
|
+
transactionType = 'ADJUSTMENT'
|
|
665
|
+
} else {
|
|
666
|
+
newHistoryRecord.uomValue = 0
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Terminate current inventory history if there is change of bizplace, product, batchId, packingType, or uom
|
|
670
|
+
if (
|
|
671
|
+
(newRecord.bizplace && inventory.bizplace.id !== newRecord.bizplace.id) ||
|
|
672
|
+
(newRecord.product && inventory.product.id !== newRecord.product.id) ||
|
|
673
|
+
(newRecord.batchId && inventory.batchId !== newRecord.batchId) ||
|
|
674
|
+
(newRecord.packingType && inventory.packingType !== newRecord.packingType) ||
|
|
675
|
+
(newRecord.uom && inventory.uom !== newRecord.uom)
|
|
676
|
+
) {
|
|
677
|
+
transactionType = 'ADJUSTMENT'
|
|
678
|
+
lastSeq = lastSeq + 1
|
|
679
|
+
let inventoryHistory = {
|
|
680
|
+
...inventory,
|
|
681
|
+
domain: domain,
|
|
682
|
+
bizplace: inventory.bizplace.id,
|
|
683
|
+
openingQty: inventory.qty,
|
|
684
|
+
openingUomValue: inventory.uomValue,
|
|
685
|
+
qty: -inventory.qty || 0,
|
|
686
|
+
uom: inventory.uom,
|
|
687
|
+
uomValue: -inventory.uomValue || 0,
|
|
688
|
+
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
689
|
+
seq: lastSeq,
|
|
690
|
+
transactionType: transactionType,
|
|
691
|
+
status: INVENTORY_STATUS.TERMINATED,
|
|
692
|
+
productId: inventory.product.id,
|
|
693
|
+
warehouseId: inventory.warehouse.id,
|
|
694
|
+
locationId: inventory.location.id,
|
|
695
|
+
packingType: inventory.packingType,
|
|
696
|
+
creator: user,
|
|
697
|
+
updater: user
|
|
698
|
+
}
|
|
699
|
+
delete inventoryHistory.id
|
|
700
|
+
delete inventoryHistory.createdAt
|
|
701
|
+
delete inventoryHistory.updatedAt
|
|
702
|
+
await tx.getRepository(InventoryHistory).save(inventoryHistory)
|
|
703
|
+
newHistoryRecord.qty = newRecord.qty != null ? newRecord.qty : inventory.qty || 0
|
|
704
|
+
newHistoryRecord.uomValue = newRecord.uomValue != null ? newRecord.uomValue : inventory.uomValue || 0
|
|
705
|
+
newHistoryRecord.openingQty = 0
|
|
706
|
+
newHistoryRecord.openingUomValue = 0
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Set and update inventory and inventory history data
|
|
710
|
+
lastSeq = lastSeq + 1
|
|
711
|
+
clean(newHistoryRecord)
|
|
712
|
+
let inventoryHistory = {
|
|
713
|
+
...inventory,
|
|
714
|
+
...newHistoryRecord,
|
|
715
|
+
domain: domain,
|
|
716
|
+
creator: user,
|
|
717
|
+
updater: user,
|
|
718
|
+
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
719
|
+
status: newHistoryRecord.transactionType == 'MISSING' ? 'MISSING' : 'STORED',
|
|
720
|
+
seq: lastSeq,
|
|
721
|
+
transactionType: transactionType == '' ? 'ADJUSTMENT' : transactionType,
|
|
722
|
+
productId: newRecord.product ? newRecord.product.id : inventory.product.id,
|
|
723
|
+
warehouseId: newRecord.warehouse ? newRecord.warehouse.id : inventory.warehouse.id,
|
|
724
|
+
locationId:
|
|
725
|
+
newRecord.location && newRecord.location.id != inventory.location.id
|
|
726
|
+
? newRecord.location.id
|
|
727
|
+
: inventory.location.id,
|
|
728
|
+
uom: newRecord.uom != null ? newRecord.uom : inventory.uom
|
|
729
|
+
}
|
|
730
|
+
delete inventoryHistory.id
|
|
731
|
+
delete inventoryHistory.createdAt
|
|
732
|
+
delete inventoryHistory.updatedAt
|
|
733
|
+
await tx.getRepository(InventoryHistory).save(inventoryHistory)
|
|
734
|
+
|
|
735
|
+
if (newRecord.qty != null && newRecord.qty == 0) {
|
|
736
|
+
++lastSeq
|
|
737
|
+
delete inventoryHistory.id
|
|
738
|
+
inventoryHistory = {
|
|
739
|
+
...inventoryHistory,
|
|
740
|
+
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
741
|
+
qty: 0,
|
|
742
|
+
uomValue: 0,
|
|
743
|
+
openingQty: 0,
|
|
744
|
+
openingUomValue: 0,
|
|
745
|
+
seq: lastSeq,
|
|
746
|
+
transactionType: 'TERMINATED',
|
|
747
|
+
status: 'TERMINATED'
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
await tx.getRepository(InventoryHistory).save(inventoryHistory)
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
clean(newRecord)
|
|
754
|
+
let statusFilter = ''
|
|
755
|
+
if (newRecord.transactionType == 'MISSING') {
|
|
756
|
+
statusFilter = 'MISSING'
|
|
757
|
+
} else {
|
|
758
|
+
statusFilter = (newRecord.qty != null ? newRecord.qty : inventory.qty) > 0 ? 'STORED' : 'TERMINATED'
|
|
759
|
+
}
|
|
760
|
+
await tx.getRepository(Inventory).save({
|
|
761
|
+
...inventory,
|
|
762
|
+
...newRecord,
|
|
763
|
+
id: inventoryId,
|
|
764
|
+
status: statusFilter,
|
|
765
|
+
updater: user,
|
|
766
|
+
lastSeq: lastSeq
|
|
767
|
+
})
|
|
768
|
+
|
|
769
|
+
//Check and set latest location status
|
|
770
|
+
if (newRecord.qty != null ? newRecord.qty : inventory.qty > 0) {
|
|
771
|
+
var location = await tx.getRepository(Location).findOne({
|
|
772
|
+
where: { id: newRecord.location ? newRecord.location.id : inventory.location.id }
|
|
773
|
+
})
|
|
774
|
+
await tx.getRepository(Location).save({
|
|
775
|
+
...location,
|
|
776
|
+
status: LOCATION_STATUS.OCCUPIED
|
|
777
|
+
})
|
|
778
|
+
} else {
|
|
779
|
+
let latestLocationInventoryCount = await tx.getRepository(Inventory).count({
|
|
780
|
+
where: {
|
|
781
|
+
location: newRecord.location ? newRecord.location.id : inventory.location.id,
|
|
782
|
+
status: 'STORED',
|
|
783
|
+
id: Not(inventory.id)
|
|
784
|
+
}
|
|
785
|
+
})
|
|
786
|
+
if (latestLocationInventoryCount == 0) {
|
|
787
|
+
let latestLocation = await tx.getRepository(Location).findOne({
|
|
788
|
+
where: { id: newRecord.location ? newRecord.location.id : inventory.location.id }
|
|
789
|
+
})
|
|
790
|
+
await tx.getRepository(Location).save({
|
|
791
|
+
...latestLocation,
|
|
792
|
+
status: LOCATION_STATUS.EMPTY
|
|
793
|
+
})
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
await upsertInventoryItems(context, _inventoryChanges[i], 'APPROVED', tx)
|
|
798
|
+
|
|
799
|
+
const sellercraft: Sellercraft = await tx
|
|
800
|
+
.getRepository(Sellercraft)
|
|
801
|
+
.findOne({ domain: customerDomain, status: SellercraftStatus.ACTIVE })
|
|
802
|
+
|
|
803
|
+
const companyDomain: Domain = inventory.bizplace?.company.domain
|
|
804
|
+
|
|
805
|
+
if (sellercraft) {
|
|
806
|
+
const sellercraftCtrl: SellercraftController = new SellercraftController(tx, domain, user)
|
|
807
|
+
await sellercraftCtrl.updateSellercraftStock(sellercraft, inventory)
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// check for any existing active marketplace connection, update marketplace selling qty
|
|
811
|
+
const marketplaceStores: MarketplaceStore[] = await tx.getRepository(MarketplaceStore).find({
|
|
812
|
+
where: { domain: companyDomain, status: 'ACTIVE', isAutoUpdateStockQty: true },
|
|
813
|
+
relations: ['marketplaceDistributors']
|
|
814
|
+
})
|
|
815
|
+
|
|
816
|
+
if (marketplaceStores?.length && marketplaceStores.some(store => store.isAutoUpdateStockQty)) {
|
|
817
|
+
const ecommerceCtrl: EcommerceController = new EcommerceController(tx, domain, user)
|
|
818
|
+
await ecommerceCtrl.updateProductVariationStock(marketplaceStores, inventory.product.id, companyDomain)
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Adding Inventory
|
|
823
|
+
else {
|
|
824
|
+
const total = await tx.getRepository(Inventory).count({
|
|
825
|
+
createdAt: MoreThan(new Date(year, month, date))
|
|
826
|
+
})
|
|
827
|
+
|
|
828
|
+
const yy = String(year).substr(String(year).length - 2)
|
|
829
|
+
const mm = String(month + 1).padStart(2, '0')
|
|
830
|
+
const dd = String(date).padStart(2, '0')
|
|
831
|
+
|
|
832
|
+
const dateStr = yy + mm + dd
|
|
833
|
+
|
|
834
|
+
let palletId = newRecord.palletId
|
|
835
|
+
|
|
836
|
+
if (!newRecord.palletId?.trim()) {
|
|
837
|
+
palletId = await generateId({
|
|
838
|
+
domain: domain,
|
|
839
|
+
type: 'adjustment_pallet_id',
|
|
840
|
+
seed: {
|
|
841
|
+
batchId: newRecord.batchId,
|
|
842
|
+
date: dateStr
|
|
843
|
+
}
|
|
844
|
+
})
|
|
845
|
+
if (!palletId) throw new Error('No adjustment pallet id setting rule found')
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
var location = await tx.getRepository(Location).findOne({
|
|
849
|
+
where: { id: newRecord.location.id },
|
|
850
|
+
relations: ['warehouse']
|
|
851
|
+
})
|
|
852
|
+
newRecord.location = location
|
|
853
|
+
newRecord.zone = location.zone
|
|
854
|
+
newRecord.warehouse = location.warehouse
|
|
855
|
+
|
|
856
|
+
newRecord.status = INVENTORY_STATUS.STORED
|
|
857
|
+
newRecord.name = palletId
|
|
858
|
+
newRecord.palletId = palletId
|
|
859
|
+
|
|
860
|
+
const warehouseCartonSetting: Setting = await tx.getRepository(Setting).findOne({
|
|
861
|
+
where: { domain, category: 'id-rule', name: 'enable-carton-label' }
|
|
862
|
+
})
|
|
863
|
+
|
|
864
|
+
const partnerCartonSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
|
|
865
|
+
where: { setting: warehouseCartonSetting, domain, partnerDomain: newRecord.bizplace?.domain }
|
|
866
|
+
})
|
|
867
|
+
|
|
868
|
+
if (partnerCartonSetting?.value) {
|
|
869
|
+
let cartonId = await generateId({
|
|
870
|
+
domain: domain,
|
|
871
|
+
type: 'adjustment_carton_id',
|
|
872
|
+
seed: { date: dateStr }
|
|
873
|
+
})
|
|
874
|
+
if (!cartonId) throw new Error('No adjustment carton id setting rule found')
|
|
875
|
+
|
|
876
|
+
newRecord.cartonId = cartonId
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
let expirationDate =
|
|
880
|
+
((newRecord?.expirationDate && new Date(newRecord.expirationDate).getFullYear()) || 0) < 2000
|
|
881
|
+
? null
|
|
882
|
+
: newRecord.expirationDate
|
|
883
|
+
|
|
884
|
+
let savedInventory = await tx.getRepository(Inventory).save({
|
|
885
|
+
...newRecord,
|
|
886
|
+
expirationDate,
|
|
887
|
+
domain: domain,
|
|
888
|
+
creator: user,
|
|
889
|
+
updater: user,
|
|
890
|
+
lastSeq: 0
|
|
891
|
+
})
|
|
892
|
+
|
|
893
|
+
await tx.getRepository(InventoryHistory).save({
|
|
894
|
+
...newRecord,
|
|
895
|
+
domain: domain,
|
|
896
|
+
creator: user,
|
|
897
|
+
updater: user,
|
|
898
|
+
name: InventoryNoGenerator.inventoryHistoryName(),
|
|
899
|
+
seq: 0,
|
|
900
|
+
transactionType: 'NEW',
|
|
901
|
+
productId: newRecord.product.id,
|
|
902
|
+
warehouseId: newRecord.warehouse.id,
|
|
903
|
+
locationId: newRecord.location.id,
|
|
904
|
+
inventory: savedInventory,
|
|
905
|
+
expirationDate: expirationDate
|
|
906
|
+
})
|
|
907
|
+
|
|
908
|
+
await tx.getRepository(Location).save({
|
|
909
|
+
...location,
|
|
910
|
+
status: LOCATION_STATUS.OCCUPIED
|
|
911
|
+
})
|
|
912
|
+
|
|
913
|
+
_inventoryChanges[i].inventory = savedInventory
|
|
914
|
+
_inventoryChanges[i].palletId = savedInventory.palletId
|
|
915
|
+
|
|
916
|
+
await upsertInventoryItems(context, _inventoryChanges[i], 'APPROVED', tx)
|
|
917
|
+
|
|
918
|
+
const sellercraft: Sellercraft = await tx
|
|
919
|
+
.getRepository(Sellercraft)
|
|
920
|
+
.findOne({ domain: newRecord.bizplace.domain, status: SellercraftStatus.ACTIVE })
|
|
921
|
+
|
|
922
|
+
const companyDomain: Domain = newRecord.bizplace?.company.domain
|
|
923
|
+
|
|
924
|
+
if (sellercraft) {
|
|
925
|
+
const sellercraftCtrl: SellercraftController = new SellercraftController(tx, domain, user)
|
|
926
|
+
await sellercraftCtrl.updateSellercraftStock(sellercraft, newRecord)
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// update marketplace store qty
|
|
930
|
+
// check for any existing active marketplace connection, update marketplace selling qty
|
|
931
|
+
const marketplaceStores: MarketplaceStore[] = await tx.getRepository(MarketplaceStore).find({
|
|
932
|
+
where: { domain: companyDomain, status: 'ACTIVE', isAutoUpdateStockQty: true },
|
|
933
|
+
relations: ['marketplaceDistributors']
|
|
934
|
+
})
|
|
935
|
+
|
|
936
|
+
if (marketplaceStores?.length && marketplaceStores.some(store => store.isAutoUpdateStockQty)) {
|
|
937
|
+
const ecommerceCtrl: EcommerceController = new EcommerceController(tx, domain, user)
|
|
938
|
+
await ecommerceCtrl.updateProductVariationStock(marketplaceStores, newRecord.product.id, companyDomain)
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
_inventoryChanges[i].status = 'APPROVED'
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
await tx.getRepository(InventoryChange).save(_inventoryChanges)
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
return { items: arrLockedInventory, total: arrLockedInventory.length }
|
|
949
|
+
}
|