@rytass/wms-module-core 0.1.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/LICENSE +21 -0
- package/README.md +80 -0
- package/index.cjs.js +6479 -0
- package/index.d.ts +5 -0
- package/index.js +74 -0
- package/lib/constants/index.d.ts +1 -0
- package/lib/constants/stock-status.d.ts +30 -0
- package/lib/constants/stock-status.js +51 -0
- package/lib/core.module.d.ts +7 -0
- package/lib/core.module.js +102 -0
- package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-change.entity.js +40 -0
- package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-item.entity.d.ts +20 -0
- package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-item.entity.js +103 -0
- package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order.entity.d.ts +8 -0
- package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order.entity.js +33 -0
- package/lib/models/extensions/hold-inventory-order/hold-inventory-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/hold-inventory-order/hold-inventory-order-change.entity.js +40 -0
- package/lib/models/extensions/hold-inventory-order/hold-inventory-order-item.entity.d.ts +19 -0
- package/lib/models/extensions/hold-inventory-order/hold-inventory-order-item.entity.js +97 -0
- package/lib/models/extensions/hold-inventory-order/hold-inventory-order.entity.d.ts +10 -0
- package/lib/models/extensions/hold-inventory-order/hold-inventory-order.entity.js +43 -0
- package/lib/models/extensions/index.d.ts +37 -0
- package/lib/models/extensions/merge-batch-order/merge-batch-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/merge-batch-order/merge-batch-order-change.entity.js +40 -0
- package/lib/models/extensions/merge-batch-order/merge-batch-order-item.entity.d.ts +15 -0
- package/lib/models/extensions/merge-batch-order/merge-batch-order-item.entity.js +74 -0
- package/lib/models/extensions/merge-batch-order/merge-batch-order.entity.d.ts +8 -0
- package/lib/models/extensions/merge-batch-order/merge-batch-order.entity.js +33 -0
- package/lib/models/extensions/quality-inspection-order/quality-inspection-order-change.entity.d.ts +11 -0
- package/lib/models/extensions/quality-inspection-order/quality-inspection-order-change.entity.js +45 -0
- package/lib/models/extensions/quality-inspection-order/quality-inspection-order-item.entity.d.ts +18 -0
- package/lib/models/extensions/quality-inspection-order/quality-inspection-order-item.entity.js +93 -0
- package/lib/models/extensions/quality-inspection-order/quality-inspection-order.entity.d.ts +9 -0
- package/lib/models/extensions/quality-inspection-order/quality-inspection-order.entity.js +38 -0
- package/lib/models/extensions/receive-inventory-order/receive-inventory-order-change.entity.d.ts +12 -0
- package/lib/models/extensions/receive-inventory-order/receive-inventory-order-change.entity.js +46 -0
- package/lib/models/extensions/receive-inventory-order/receive-inventory-order-item.entity.d.ts +19 -0
- package/lib/models/extensions/receive-inventory-order/receive-inventory-order-item.entity.js +89 -0
- package/lib/models/extensions/receive-inventory-order/receive-inventory-order.entity.d.ts +13 -0
- package/lib/models/extensions/receive-inventory-order/receive-inventory-order.entity.js +57 -0
- package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-change.entity.js +40 -0
- package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-item.entity.d.ts +15 -0
- package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-item.entity.js +74 -0
- package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order.entity.d.ts +8 -0
- package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order.entity.js +33 -0
- package/lib/models/extensions/scrape-order/scrape-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/scrape-order/scrape-order-change.entity.js +40 -0
- package/lib/models/extensions/scrape-order/scrape-order-item.entity.d.ts +18 -0
- package/lib/models/extensions/scrape-order/scrape-order-item.entity.js +93 -0
- package/lib/models/extensions/scrape-order/scrape-order.entity.d.ts +8 -0
- package/lib/models/extensions/scrape-order/scrape-order.entity.js +33 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order-change.entity.d.ts +12 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order-change.entity.js +46 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order-item.entity.d.ts +19 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order-item.entity.js +90 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order-reference.entity.d.ts +13 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order-reference.entity.js +65 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order.entity.d.ts +13 -0
- package/lib/models/extensions/ship-inventory-order/ship-inventory-order.entity.js +56 -0
- package/lib/models/extensions/split-batch-order/split-batch-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/split-batch-order/split-batch-order-change.entity.js +40 -0
- package/lib/models/extensions/split-batch-order/split-batch-order-item.entity.d.ts +15 -0
- package/lib/models/extensions/split-batch-order/split-batch-order-item.entity.js +74 -0
- package/lib/models/extensions/split-batch-order/split-batch-order.entity.d.ts +8 -0
- package/lib/models/extensions/split-batch-order/split-batch-order.entity.js +33 -0
- package/lib/models/extensions/transfer-customer-order/transfer-customer-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/transfer-customer-order/transfer-customer-order-change.entity.js +40 -0
- package/lib/models/extensions/transfer-customer-order/transfer-customer-order-item.entity.d.ts +19 -0
- package/lib/models/extensions/transfer-customer-order/transfer-customer-order-item.entity.js +98 -0
- package/lib/models/extensions/transfer-customer-order/transfer-customer-order.entity.d.ts +8 -0
- package/lib/models/extensions/transfer-customer-order/transfer-customer-order.entity.js +33 -0
- package/lib/models/extensions/transfer-order/transfer-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/transfer-order/transfer-order-change.entity.js +40 -0
- package/lib/models/extensions/transfer-order/transfer-order-item.entity.d.ts +21 -0
- package/lib/models/extensions/transfer-order/transfer-order-item.entity.js +108 -0
- package/lib/models/extensions/transfer-order/transfer-order.entity.d.ts +12 -0
- package/lib/models/extensions/transfer-order/transfer-order.entity.js +53 -0
- package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-change.entity.d.ts +10 -0
- package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-change.entity.js +40 -0
- package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-item.entity.d.ts +19 -0
- package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-item.entity.js +98 -0
- package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order.entity.d.ts +8 -0
- package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order.entity.js +33 -0
- package/lib/models/index.d.ts +2 -0
- package/lib/models/metadata/batch-group.entity.d.ts +8 -0
- package/lib/models/metadata/batch-group.entity.js +31 -0
- package/lib/models/metadata/batch.entity.d.ts +15 -0
- package/lib/models/metadata/batch.entity.js +73 -0
- package/lib/models/metadata/index.d.ts +11 -0
- package/lib/models/metadata/loader-type.entity.d.ts +9 -0
- package/lib/models/metadata/loader-type.entity.js +43 -0
- package/lib/models/metadata/loader-unit.entity.d.ts +5 -0
- package/lib/models/metadata/loader-unit.entity.js +21 -0
- package/lib/models/metadata/loader.entity.d.ts +21 -0
- package/lib/models/metadata/loader.entity.js +98 -0
- package/lib/models/metadata/location.entity.d.ts +8 -0
- package/lib/models/metadata/location.entity.js +28 -0
- package/lib/models/metadata/material-unit.entity.d.ts +11 -0
- package/lib/models/metadata/material-unit.entity.js +51 -0
- package/lib/models/metadata/material.entity.d.ts +7 -0
- package/lib/models/metadata/material.entity.js +28 -0
- package/lib/models/metadata/sale-order.entity.d.ts +5 -0
- package/lib/models/metadata/sale-order.entity.js +21 -0
- package/lib/models/metadata/stock.entity.d.ts +8 -0
- package/lib/models/metadata/stock.entity.js +29 -0
- package/lib/models/metadata/unit.entity.d.ts +5 -0
- package/lib/models/metadata/unit.entity.js +21 -0
- package/lib/models/models.module.d.ts +6 -0
- package/lib/models/models.module.js +122 -0
- package/lib/services/allocate-inventory-order.service.d.ts +29 -0
- package/lib/services/allocate-inventory-order.service.js +299 -0
- package/lib/services/base-order.service.d.ts +41 -0
- package/lib/services/batch.service.d.ts +30 -0
- package/lib/services/batch.service.js +218 -0
- package/lib/services/helper.service.d.ts +6 -0
- package/lib/services/helper.service.js +28 -0
- package/lib/services/hold-inventory-order.service.d.ts +29 -0
- package/lib/services/hold-inventory-order.service.js +285 -0
- package/lib/services/index.d.ts +22 -0
- package/lib/services/loader.service.d.ts +43 -0
- package/lib/services/loader.service.js +282 -0
- package/lib/services/location.service.d.ts +13 -0
- package/lib/services/location.service.js +130 -0
- package/lib/services/material.service.d.ts +27 -0
- package/lib/services/material.service.js +172 -0
- package/lib/services/merge-batch-order.service.d.ts +19 -0
- package/lib/services/merge-batch-order.service.js +195 -0
- package/lib/services/quality-inspection-order.service.d.ts +19 -0
- package/lib/services/quality-inspection-order.service.js +135 -0
- package/lib/services/receive-inventory-order.service.d.ts +41 -0
- package/lib/services/receive-inventory-order.service.js +407 -0
- package/lib/services/reclassify-inventory-order.service.d.ts +19 -0
- package/lib/services/reclassify-inventory-order.service.js +181 -0
- package/lib/services/sale-order.service.d.ts +7 -0
- package/lib/services/sale-order.service.js +20 -0
- package/lib/services/scrape.service.d.ts +18 -0
- package/lib/services/scrape.service.js +139 -0
- package/lib/services/ship-inventory-order.service.d.ts +60 -0
- package/lib/services/ship-inventory-order.service.js +599 -0
- package/lib/services/split-batch-order.service.d.ts +19 -0
- package/lib/services/split-batch-order.service.js +161 -0
- package/lib/services/stock.service.d.ts +38 -0
- package/lib/services/stock.service.js +477 -0
- package/lib/services/transfer-customer-order.service.d.ts +35 -0
- package/lib/services/transfer-customer-order.service.js +279 -0
- package/lib/services/transfer-order.service.d.ts +44 -0
- package/lib/services/transfer-order.service.js +632 -0
- package/lib/services/transfer-vendor-order.service.d.ts +35 -0
- package/lib/services/transfer-vendor-order.service.js +279 -0
- package/lib/services/unit.service.d.ts +7 -0
- package/lib/services/unit.service.js +67 -0
- package/lib/services/warehouse-map.service.d.ts +10 -0
- package/lib/services/warehouse-map.service.js +38 -0
- package/lib/typings/aggregated-stock.d.ts +22 -0
- package/lib/typings/cancel-ship-inventory-order.input.d.ts +4 -0
- package/lib/typings/cancel-transfer-order.input.d.ts +4 -0
- package/lib/typings/core-module-options.d.ts +8 -0
- package/lib/typings/core-module-options.js +3 -0
- package/lib/typings/create-allocate-inventory-order.input.d.ts +25 -0
- package/lib/typings/create-hold-inventory-order.input.d.ts +21 -0
- package/lib/typings/create-inspection-order.input.d.ts +14 -0
- package/lib/typings/create-loader-type.input.d.ts +9 -0
- package/lib/typings/create-loader.input.d.ts +15 -0
- package/lib/typings/create-location.input.d.ts +12 -0
- package/lib/typings/create-material-unit.input.d.ts +5 -0
- package/lib/typings/create-material.input.d.ts +11 -0
- package/lib/typings/create-receive-inventory-order.input.d.ts +26 -0
- package/lib/typings/create-ship-inventory-order.input.d.ts +46 -0
- package/lib/typings/create-transfer-customer-order.input.d.ts +25 -0
- package/lib/typings/create-transfer-order.input.d.ts +25 -0
- package/lib/typings/create-transfer-vendor-order.input.d.ts +25 -0
- package/lib/typings/deallocate-inventory-order.d.ts +8 -0
- package/lib/typings/find-allocate-inventory-order.input.d.ts +13 -0
- package/lib/typings/find-batch.input.d.ts +8 -0
- package/lib/typings/find-hold-inventory-order.input.d.ts +13 -0
- package/lib/typings/find-loader.input.d.ts +33 -0
- package/lib/typings/find-location.input.d.ts +10 -0
- package/lib/typings/find-material.input.d.ts +10 -0
- package/lib/typings/find-receive-inventory-order.input.d.ts +26 -0
- package/lib/typings/find-receive-inventory-order.input.js +9 -0
- package/lib/typings/find-ship-inventory-order.input.d.ts +26 -0
- package/lib/typings/find-ship-inventory-order.input.js +9 -0
- package/lib/typings/find-stock.input.d.ts +21 -0
- package/lib/typings/find-transfer-order.input.d.ts +21 -0
- package/lib/typings/get-batch.input.d.ts +14 -0
- package/lib/typings/index.d.ts +18 -0
- package/lib/typings/merge-batch.input.d.ts +11 -0
- package/lib/typings/paginations.d.ts +4 -0
- package/lib/typings/receive-inventory-order.input.d.ts +8 -0
- package/lib/typings/reclassify-inventory-order.input.d.ts +11 -0
- package/lib/typings/release-inventory-order.input.d.ts +8 -0
- package/lib/typings/scrape.input.d.ts +8 -0
- package/lib/typings/ship-inventory-order.input.d.ts +4 -0
- package/lib/typings/split-batch.input.d.ts +10 -0
- package/lib/typings/transfer-order.input.d.ts +4 -0
- package/package.json +52 -0
- package/src/lib/models/extensions/README.md +219 -0
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
import { __decorate, __param, __metadata } from 'tslib';
|
|
2
|
+
import { Injectable, Inject } from '@nestjs/common';
|
|
3
|
+
import { ShipInventoryOrderEntity } from '../models/extensions/ship-inventory-order/ship-inventory-order.entity.js';
|
|
4
|
+
import { ShipInventoryOrderItemEntity } from '../models/extensions/ship-inventory-order/ship-inventory-order-item.entity.js';
|
|
5
|
+
import { DataSource, IsNull, In } from 'typeorm';
|
|
6
|
+
import { ShipInventoryOrderStatus } from '../typings/find-ship-inventory-order.input.js';
|
|
7
|
+
import { OrderEntity } from '@rytass/wms-base-nestjs-module';
|
|
8
|
+
import '../models/metadata/batch.entity.js';
|
|
9
|
+
import '../models/metadata/batch-group.entity.js';
|
|
10
|
+
import '../models/metadata/loader.entity.js';
|
|
11
|
+
import '../models/metadata/loader-type.entity.js';
|
|
12
|
+
import '../models/metadata/loader-unit.entity.js';
|
|
13
|
+
import '../models/metadata/location.entity.js';
|
|
14
|
+
import { MaterialEntityClass } from '../models/metadata/material.entity.js';
|
|
15
|
+
import '../models/metadata/material-unit.entity.js';
|
|
16
|
+
import { SaleOrderEntity } from '../models/metadata/sale-order.entity.js';
|
|
17
|
+
import { StockEntityClass } from '../models/metadata/stock.entity.js';
|
|
18
|
+
import '../models/metadata/unit.entity.js';
|
|
19
|
+
import '../models/extensions/receive-inventory-order/receive-inventory-order-item.entity.js';
|
|
20
|
+
import '../models/extensions/receive-inventory-order/receive-inventory-order.entity.js';
|
|
21
|
+
import '../models/extensions/receive-inventory-order/receive-inventory-order-change.entity.js';
|
|
22
|
+
import { ShipInventoryOrderReferenceEntity } from '../models/extensions/ship-inventory-order/ship-inventory-order-reference.entity.js';
|
|
23
|
+
import { ShipInventoryOrderChangeEntityClass } from '../models/extensions/ship-inventory-order/ship-inventory-order-change.entity.js';
|
|
24
|
+
import '../models/extensions/transfer-order/transfer-order.entity.js';
|
|
25
|
+
import '../models/extensions/transfer-order/transfer-order-item.entity.js';
|
|
26
|
+
import '../models/extensions/transfer-order/transfer-order-change.entity.js';
|
|
27
|
+
import '../models/extensions/hold-inventory-order/hold-inventory-order.entity.js';
|
|
28
|
+
import '../models/extensions/hold-inventory-order/hold-inventory-order-item.entity.js';
|
|
29
|
+
import '../models/extensions/hold-inventory-order/hold-inventory-order-change.entity.js';
|
|
30
|
+
import '../models/extensions/allocate-inventory-order/allocate-inventory-order.entity.js';
|
|
31
|
+
import '../models/extensions/allocate-inventory-order/allocate-inventory-order-item.entity.js';
|
|
32
|
+
import '../models/extensions/allocate-inventory-order/allocate-inventory-order-change.entity.js';
|
|
33
|
+
import '../models/extensions/split-batch-order/split-batch-order.entity.js';
|
|
34
|
+
import '../models/extensions/split-batch-order/split-batch-order-item.entity.js';
|
|
35
|
+
import '../models/extensions/split-batch-order/split-batch-order-change.entity.js';
|
|
36
|
+
import '../models/extensions/merge-batch-order/merge-batch-order.entity.js';
|
|
37
|
+
import '../models/extensions/merge-batch-order/merge-batch-order-item.entity.js';
|
|
38
|
+
import '../models/extensions/merge-batch-order/merge-batch-order-change.entity.js';
|
|
39
|
+
import '../models/extensions/reclassify-inventory-order/reclassify-inventory-order.entity.js';
|
|
40
|
+
import '../models/extensions/reclassify-inventory-order/reclassify-inventory-order-item.entity.js';
|
|
41
|
+
import '../models/extensions/reclassify-inventory-order/reclassify-inventory-order-change.entity.js';
|
|
42
|
+
import '../models/extensions/transfer-vendor-order/transfer-vendor-order.entity.js';
|
|
43
|
+
import '../models/extensions/transfer-vendor-order/transfer-vendor-order-item.entity.js';
|
|
44
|
+
import '../models/extensions/transfer-vendor-order/transfer-vendor-order-change.entity.js';
|
|
45
|
+
import '../models/extensions/quality-inspection-order/quality-inspection-order.entity.js';
|
|
46
|
+
import '../models/extensions/quality-inspection-order/quality-inspection-order-item.entity.js';
|
|
47
|
+
import '../models/extensions/quality-inspection-order/quality-inspection-order-change.entity.js';
|
|
48
|
+
import '../models/extensions/transfer-customer-order/transfer-customer-order.entity.js';
|
|
49
|
+
import '../models/extensions/transfer-customer-order/transfer-customer-order-item.entity.js';
|
|
50
|
+
import '../models/extensions/transfer-customer-order/transfer-customer-order-change.entity.js';
|
|
51
|
+
import '../models/extensions/scrape-order/scrape-order.entity.js';
|
|
52
|
+
import '../models/extensions/scrape-order/scrape-order-item.entity.js';
|
|
53
|
+
import '../models/extensions/scrape-order/scrape-order-change.entity.js';
|
|
54
|
+
import { MaterialService } from './material.service.js';
|
|
55
|
+
import { BatchService } from './batch.service.js';
|
|
56
|
+
import { StockService } from './stock.service.js';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Service for managing ship inventory orders and their items
|
|
60
|
+
* Supports dynamic entity injection for customization
|
|
61
|
+
* T - Ship Inventory Order entity type
|
|
62
|
+
* K - Ship Inventory Order Item entity type
|
|
63
|
+
*/
|
|
64
|
+
let ShipInventoryOrderService = class ShipInventoryOrderService {
|
|
65
|
+
dataSource;
|
|
66
|
+
materialService;
|
|
67
|
+
batchService;
|
|
68
|
+
stockService;
|
|
69
|
+
shipInventoryOrderEntity;
|
|
70
|
+
shipInventoryOrderItemEntity;
|
|
71
|
+
shipInventoryOrderReferenceEntity;
|
|
72
|
+
saleOrderEntity;
|
|
73
|
+
selectQueryBuilder;
|
|
74
|
+
constructor(dataSource, materialService, batchService, stockService, shipInventoryOrderEntity, shipInventoryOrderItemEntity, shipInventoryOrderReferenceEntity, saleOrderEntity) {
|
|
75
|
+
this.dataSource = dataSource;
|
|
76
|
+
this.materialService = materialService;
|
|
77
|
+
this.batchService = batchService;
|
|
78
|
+
this.stockService = stockService;
|
|
79
|
+
this.shipInventoryOrderEntity = shipInventoryOrderEntity;
|
|
80
|
+
this.shipInventoryOrderItemEntity = shipInventoryOrderItemEntity;
|
|
81
|
+
this.shipInventoryOrderReferenceEntity = shipInventoryOrderReferenceEntity;
|
|
82
|
+
this.saleOrderEntity = saleOrderEntity;
|
|
83
|
+
this.selectQueryBuilder = (alias) => {
|
|
84
|
+
return this.dataSource
|
|
85
|
+
.getRepository(this.shipInventoryOrderEntity)
|
|
86
|
+
.createQueryBuilder(alias)
|
|
87
|
+
.leftJoin((subQuery) => subQuery
|
|
88
|
+
.select(`CASE
|
|
89
|
+
WHEN o."removedAt" IS NOT NULL THEN '${ShipInventoryOrderStatus.REMOVED}'
|
|
90
|
+
WHEN COALESCE(change_sums.shippedsum, 0) >= COALESCE(target_sum.targetsum, 0) AND COALESCE(target_sum.targetsum, 0) > 0 THEN '${ShipInventoryOrderStatus.SHIPPED}'
|
|
91
|
+
WHEN COALESCE(change_sums.shippedsum, 0) > 0 AND COALESCE(change_sums.shippedsum, 0) < COALESCE(target_sum.targetsum, 0) THEN '${ShipInventoryOrderStatus.PARTIAL_SHIPPED}'
|
|
92
|
+
ELSE '${ShipInventoryOrderStatus.PENDING}'
|
|
93
|
+
END`, 'status')
|
|
94
|
+
.addSelect('o.id', 'orderid')
|
|
95
|
+
.from('ship_inventory_orders', 'o')
|
|
96
|
+
.leftJoin((sumQuery) => sumQuery
|
|
97
|
+
.select('i."orderId"', 'orderid')
|
|
98
|
+
.addSelect(`SUM(CAST(i."targetShippedQuantity" AS NUMERIC))`, 'targetsum')
|
|
99
|
+
.from('ship_inventory_order_items', 'i')
|
|
100
|
+
.groupBy('i."orderId"'), 'target_sum', 'target_sum.orderid = o.id')
|
|
101
|
+
.leftJoin((sumQuery) => sumQuery
|
|
102
|
+
.select('i."orderId"', 'orderid')
|
|
103
|
+
.addSelect(`SUM(CASE WHEN CAST(c."quantityChanged" AS NUMERIC) < 0 THEN ABS(CAST(c."quantityChanged" AS NUMERIC)) ELSE 0 END)`, 'shippedsum')
|
|
104
|
+
.from('ship_inventory_order_changes', 'c')
|
|
105
|
+
.innerJoin('ship_inventory_order_items', 'i', 'c."itemId" = i.id')
|
|
106
|
+
.groupBy('i."orderId"'), 'change_sums', 'change_sums.orderid = o.id'), 'order_status', `${alias}.id = order_status.orderid`)
|
|
107
|
+
.select('orders.id', 'id')
|
|
108
|
+
.addSelect('orders.key', 'key')
|
|
109
|
+
.addSelect('orders.description', 'description')
|
|
110
|
+
.addSelect('orders."createdBy"', 'createdBy')
|
|
111
|
+
.addSelect('orders."createdAt"', 'createdAt')
|
|
112
|
+
.addSelect('orders."removedAt"', 'removedAt')
|
|
113
|
+
.addSelect('order_status.status', `status`);
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
processShipInventoryOrderReferences(references, manager) {
|
|
117
|
+
const materialRepository = manager.getRepository(MaterialEntityClass);
|
|
118
|
+
const saleOrderRepository = manager.getRepository(this.saleOrderEntity);
|
|
119
|
+
return references.reduce(async (accPromise, reference) => {
|
|
120
|
+
const acc = await accPromise;
|
|
121
|
+
try {
|
|
122
|
+
const material = await materialRepository.findOneBy({
|
|
123
|
+
key: reference.materialKey,
|
|
124
|
+
});
|
|
125
|
+
if (!material)
|
|
126
|
+
return acc;
|
|
127
|
+
if (reference.saleId && reference.saleSerialId)
|
|
128
|
+
await saleOrderRepository.save(saleOrderRepository.create({
|
|
129
|
+
id: reference.saleId,
|
|
130
|
+
serialId: reference.saleSerialId,
|
|
131
|
+
}));
|
|
132
|
+
return [
|
|
133
|
+
...acc,
|
|
134
|
+
{
|
|
135
|
+
...reference,
|
|
136
|
+
materialId: material.id,
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return acc;
|
|
142
|
+
}
|
|
143
|
+
}, Promise.resolve([]));
|
|
144
|
+
}
|
|
145
|
+
async processShipInventoryOrderItems(items, manager) {
|
|
146
|
+
const shipInventoryOrderItemRepository = manager.getRepository(this.shipInventoryOrderItemEntity);
|
|
147
|
+
const shipInventoryOrderChangeRepository = manager.getRepository(ShipInventoryOrderChangeEntityClass);
|
|
148
|
+
const orderRepository = manager.getRepository(OrderEntity);
|
|
149
|
+
const stockRepository = manager.getRepository(StockEntityClass);
|
|
150
|
+
await Promise.all(items.map(async (data) => {
|
|
151
|
+
// Ensure required fields are present
|
|
152
|
+
if (!data.batchId || !data.materialId)
|
|
153
|
+
return;
|
|
154
|
+
// Split batch first with inShipment flag to track shipment state
|
|
155
|
+
const splittedBatch = await this.batchService.splitBatch({
|
|
156
|
+
id: data.batchId,
|
|
157
|
+
inShipment: true,
|
|
158
|
+
manager,
|
|
159
|
+
});
|
|
160
|
+
// Save item with ORIGINAL batch id to maintain source state
|
|
161
|
+
const item = await shipInventoryOrderItemRepository.save(shipInventoryOrderItemRepository.create(data));
|
|
162
|
+
const base = await orderRepository.save(orderRepository.create());
|
|
163
|
+
const conversionFactor = await this.materialService.getConversionFactor(item.materialId, item.unitId || undefined);
|
|
164
|
+
await shipInventoryOrderChangeRepository.save(shipInventoryOrderChangeRepository.create({
|
|
165
|
+
itemId: item.id,
|
|
166
|
+
id: base.id,
|
|
167
|
+
quantityChanged: item.targetShippedQuantity * conversionFactor,
|
|
168
|
+
}));
|
|
169
|
+
// Stock movements track the shipment through splitted batch
|
|
170
|
+
await this.stockService.validateStockAvailability({
|
|
171
|
+
materialId: item.materialId,
|
|
172
|
+
batchId: item.batchId,
|
|
173
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
174
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
175
|
+
quantity: item.targetShippedQuantity * conversionFactor,
|
|
176
|
+
}, manager);
|
|
177
|
+
await stockRepository.save(stockRepository.create([
|
|
178
|
+
// deduct from original batch available stock
|
|
179
|
+
{
|
|
180
|
+
orderId: base.id,
|
|
181
|
+
materialId: item.materialId,
|
|
182
|
+
batchId: item.batchId, // original batch
|
|
183
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
184
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
185
|
+
quantity: -1 * item.targetShippedQuantity * conversionFactor,
|
|
186
|
+
},
|
|
187
|
+
// add to splitted batch in shipment state
|
|
188
|
+
{
|
|
189
|
+
orderId: base.id,
|
|
190
|
+
materialId: item.materialId,
|
|
191
|
+
batchId: splittedBatch.id, // splitted batch marked inShipment
|
|
192
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
193
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
194
|
+
quantity: item.targetShippedQuantity * conversionFactor,
|
|
195
|
+
},
|
|
196
|
+
]));
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
async createShipInventoryOrder({ manager = this.dataSource.manager, ...options }) {
|
|
200
|
+
const orderRepository = manager.getRepository(OrderEntity);
|
|
201
|
+
const shipInventoryOrderRepository = manager.getRepository(this.shipInventoryOrderEntity);
|
|
202
|
+
const shipInventoryOrderReferenceRepository = manager.getRepository(this.shipInventoryOrderReferenceEntity);
|
|
203
|
+
// create base order
|
|
204
|
+
const { id } = await orderRepository.save(orderRepository.create());
|
|
205
|
+
// create ship inventory order
|
|
206
|
+
const order = await shipInventoryOrderRepository.save(shipInventoryOrderRepository.create({ id, ...options }));
|
|
207
|
+
// create ship inventory order references
|
|
208
|
+
if (options.references && options.references.length > 0) {
|
|
209
|
+
const processedReferences = await this.processShipInventoryOrderReferences(options.references, manager);
|
|
210
|
+
if (processedReferences.length > 0) {
|
|
211
|
+
const references = shipInventoryOrderReferenceRepository.create(processedReferences.map((reference) => ({
|
|
212
|
+
...reference,
|
|
213
|
+
orderId: order.id,
|
|
214
|
+
})));
|
|
215
|
+
await shipInventoryOrderReferenceRepository.save(references);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return order;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Update a ship inventory order and its items
|
|
222
|
+
* update existing item when id is provided, otherwise create new item, remove behaviour controlled by removedAt field
|
|
223
|
+
*/
|
|
224
|
+
async updateShipInventoryOrder({ id, manager = this.dataSource.manager, ...options }) {
|
|
225
|
+
const shipInventoryOrderRepository = manager.getRepository(this.shipInventoryOrderEntity);
|
|
226
|
+
const shipInventoryOrderReferenceRepository = manager.getRepository(this.shipInventoryOrderReferenceEntity);
|
|
227
|
+
const shipInventoryOrderItemRepository = manager.getRepository(this.shipInventoryOrderItemEntity);
|
|
228
|
+
const materialRepository = manager.getRepository(MaterialEntityClass);
|
|
229
|
+
const order = await shipInventoryOrderRepository.findOneByOrFail({
|
|
230
|
+
id,
|
|
231
|
+
removedAt: IsNull(),
|
|
232
|
+
});
|
|
233
|
+
const { references, items, ...orderOptions } = options;
|
|
234
|
+
const updated = await shipInventoryOrderRepository.save(shipInventoryOrderRepository.create({
|
|
235
|
+
...order,
|
|
236
|
+
...orderOptions,
|
|
237
|
+
}));
|
|
238
|
+
if (references?.length) {
|
|
239
|
+
const newItems = [];
|
|
240
|
+
const existingItems = [];
|
|
241
|
+
const items = await shipInventoryOrderReferenceRepository.find({
|
|
242
|
+
where: { orderId: id, removedAt: IsNull() },
|
|
243
|
+
});
|
|
244
|
+
const itemSet = new Set(items.map((i) => i.id));
|
|
245
|
+
const results = await Promise.all((references || []).map(async (item) => {
|
|
246
|
+
let batch = null;
|
|
247
|
+
if (item.batchKey) {
|
|
248
|
+
const material = await materialRepository.findOneByOrFail({
|
|
249
|
+
key: item.materialKey,
|
|
250
|
+
});
|
|
251
|
+
batch = await this.batchService.getBatch({
|
|
252
|
+
manager,
|
|
253
|
+
materialId: material.id,
|
|
254
|
+
key: item.batchKey,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return { item, batch };
|
|
258
|
+
}));
|
|
259
|
+
// Now process results after all async operations are complete
|
|
260
|
+
results.forEach((result) => {
|
|
261
|
+
if (!result)
|
|
262
|
+
return;
|
|
263
|
+
const { item, batch } = result;
|
|
264
|
+
if (!item.id)
|
|
265
|
+
newItems.push({ ...item, batchId: batch?.id || null });
|
|
266
|
+
else if (itemSet.has(item.id))
|
|
267
|
+
existingItems.push({ ...item, batchId: batch?.id || null });
|
|
268
|
+
});
|
|
269
|
+
if (newItems.length) {
|
|
270
|
+
const processedNewItems = await this.processShipInventoryOrderReferences(newItems, manager);
|
|
271
|
+
if (processedNewItems.length > 0) {
|
|
272
|
+
await shipInventoryOrderReferenceRepository.save(shipInventoryOrderReferenceRepository.create(processedNewItems.map((item) => ({ ...item, orderId: id }))));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (existingItems.length)
|
|
276
|
+
await shipInventoryOrderReferenceRepository.save(existingItems.map((item) => shipInventoryOrderReferenceRepository.create({
|
|
277
|
+
...item,
|
|
278
|
+
id: item.id,
|
|
279
|
+
})));
|
|
280
|
+
}
|
|
281
|
+
if (items?.length) {
|
|
282
|
+
const newItems = [];
|
|
283
|
+
const existingItems = [];
|
|
284
|
+
await shipInventoryOrderItemRepository
|
|
285
|
+
.find({ where: { orderId: id, removedAt: IsNull() } })
|
|
286
|
+
.then((dbItems) => {
|
|
287
|
+
const itemSet = new Set(dbItems.map((i) => i.id));
|
|
288
|
+
items?.forEach((item) => {
|
|
289
|
+
if (!item.id)
|
|
290
|
+
newItems.push({ ...item, orderId: id });
|
|
291
|
+
else if (itemSet.has(item.id))
|
|
292
|
+
existingItems.push(item);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
if (newItems.length)
|
|
296
|
+
await this.processShipInventoryOrderItems(newItems, manager);
|
|
297
|
+
if (existingItems.length)
|
|
298
|
+
await shipInventoryOrderItemRepository.save(existingItems.map((item) => shipInventoryOrderItemRepository.create({
|
|
299
|
+
...item,
|
|
300
|
+
id: item.id,
|
|
301
|
+
})));
|
|
302
|
+
}
|
|
303
|
+
return updated;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Remove a ship inventory order
|
|
307
|
+
* Automatically cancels all remaining prepared (but not shipped) items to release stock
|
|
308
|
+
*/
|
|
309
|
+
async removeShipInventoryOrder(id) {
|
|
310
|
+
return this.dataSource.transaction(async (manager) => {
|
|
311
|
+
const shipInventoryOrderRepository = manager.getRepository(this.shipInventoryOrderEntity);
|
|
312
|
+
const itemRepository = manager.getRepository(this.shipInventoryOrderItemEntity);
|
|
313
|
+
// Find order
|
|
314
|
+
const order = await shipInventoryOrderRepository.findOne({
|
|
315
|
+
where: { id },
|
|
316
|
+
});
|
|
317
|
+
if (!order || order.removedAt)
|
|
318
|
+
return false;
|
|
319
|
+
// Find all items with changes to calculate cancellable quantities
|
|
320
|
+
const items = await itemRepository.find({
|
|
321
|
+
where: { orderId: id },
|
|
322
|
+
relations: ['changes'],
|
|
323
|
+
});
|
|
324
|
+
// Build cancel inputs for items with remaining prepared quantity
|
|
325
|
+
const cancelInputs = [];
|
|
326
|
+
for (const item of items) {
|
|
327
|
+
const conversionFactor = await this.materialService.getConversionFactor(item.materialId, item.unitId || undefined);
|
|
328
|
+
const preparedQuantity = item.changes.reduce((sum, change) => {
|
|
329
|
+
const qty = Number(change.quantityChanged);
|
|
330
|
+
return qty > 0 ? sum + qty : sum;
|
|
331
|
+
}, 0);
|
|
332
|
+
const shippedQuantity = item.changes.reduce((sum, change) => {
|
|
333
|
+
const qty = Number(change.quantityChanged);
|
|
334
|
+
return qty < 0 ? sum + Math.abs(qty) : sum;
|
|
335
|
+
}, 0);
|
|
336
|
+
const cancellableQuantity = preparedQuantity - shippedQuantity;
|
|
337
|
+
if (cancellableQuantity > 0) {
|
|
338
|
+
// Use base quantity (without conversion) since cancelShip will apply conversion
|
|
339
|
+
cancelInputs.push({
|
|
340
|
+
itemId: item.id,
|
|
341
|
+
quantity: cancellableQuantity / conversionFactor,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Cancel all remaining prepared items
|
|
346
|
+
if (cancelInputs.length > 0) {
|
|
347
|
+
await this.cancelShipInternal(cancelInputs, manager);
|
|
348
|
+
}
|
|
349
|
+
// Mark order as removed
|
|
350
|
+
await shipInventoryOrderRepository.update({ id }, { removedAt: new Date() });
|
|
351
|
+
return true;
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Internal cancel method that accepts a manager for transaction support
|
|
356
|
+
*/
|
|
357
|
+
async cancelShipInternal(options, manager) {
|
|
358
|
+
const changeRepository = manager.getRepository(ShipInventoryOrderChangeEntityClass);
|
|
359
|
+
const itemRepository = manager.getRepository(this.shipInventoryOrderItemEntity);
|
|
360
|
+
const orderRepository = manager.getRepository(OrderEntity);
|
|
361
|
+
const stockRepository = manager.getRepository(StockEntityClass);
|
|
362
|
+
const items = await itemRepository.find({
|
|
363
|
+
where: { id: In(options.map((o) => o.itemId)) },
|
|
364
|
+
relations: ['changes'],
|
|
365
|
+
});
|
|
366
|
+
const itemMap = new Map(items.map((item) => [item.id, item]));
|
|
367
|
+
await Promise.all(options.map(async (option) => {
|
|
368
|
+
const item = itemMap.get(option.itemId);
|
|
369
|
+
if (!item)
|
|
370
|
+
return;
|
|
371
|
+
const conversionFactor = await this.materialService.getConversionFactor(item.materialId, item.unitId || undefined);
|
|
372
|
+
const preparedQuantity = item.changes.reduce((sum, change) => {
|
|
373
|
+
const qty = Number(change.quantityChanged);
|
|
374
|
+
return qty > 0 ? sum + qty : sum;
|
|
375
|
+
}, 0);
|
|
376
|
+
const shippedQuantity = item.changes.reduce((sum, change) => {
|
|
377
|
+
const qty = Number(change.quantityChanged);
|
|
378
|
+
return qty < 0 ? sum + Math.abs(qty) : sum;
|
|
379
|
+
}, 0);
|
|
380
|
+
const cancellableQuantity = preparedQuantity - shippedQuantity;
|
|
381
|
+
const cancelQuantity = option.quantity != null
|
|
382
|
+
? option.quantity * conversionFactor
|
|
383
|
+
: cancellableQuantity;
|
|
384
|
+
if (cancellableQuantity - cancelQuantity < 0) {
|
|
385
|
+
throw new Error(`Cancel quantity exceeds prepared quantity for item ${option.itemId}`);
|
|
386
|
+
}
|
|
387
|
+
if (cancelQuantity <= 0)
|
|
388
|
+
return;
|
|
389
|
+
const inShipmentBatch = await this.batchService.splitBatch({
|
|
390
|
+
id: item.batchId,
|
|
391
|
+
inShipment: true,
|
|
392
|
+
manager,
|
|
393
|
+
});
|
|
394
|
+
const reverseOrder = await orderRepository.save(orderRepository.create());
|
|
395
|
+
await this.stockService.validateStockAvailability({
|
|
396
|
+
materialId: item.materialId,
|
|
397
|
+
batchId: inShipmentBatch.id,
|
|
398
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
399
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
400
|
+
quantity: cancelQuantity,
|
|
401
|
+
}, manager);
|
|
402
|
+
await Promise.all([
|
|
403
|
+
changeRepository.save(changeRepository.create({
|
|
404
|
+
itemId: option.itemId,
|
|
405
|
+
id: reverseOrder.id,
|
|
406
|
+
quantityChanged: -1 * cancelQuantity,
|
|
407
|
+
})),
|
|
408
|
+
stockRepository.save(stockRepository.create([
|
|
409
|
+
{
|
|
410
|
+
orderId: reverseOrder.id,
|
|
411
|
+
materialId: item.materialId,
|
|
412
|
+
batchId: item.batchId,
|
|
413
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
414
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
415
|
+
quantity: cancelQuantity,
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
orderId: reverseOrder.id,
|
|
419
|
+
materialId: item.materialId,
|
|
420
|
+
batchId: inShipmentBatch.id,
|
|
421
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
422
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
423
|
+
quantity: -1 * cancelQuantity,
|
|
424
|
+
},
|
|
425
|
+
])),
|
|
426
|
+
]);
|
|
427
|
+
}));
|
|
428
|
+
}
|
|
429
|
+
async findMany(options) {
|
|
430
|
+
const queryBuilder = this.selectQueryBuilder('orders');
|
|
431
|
+
if (options.id)
|
|
432
|
+
queryBuilder.andWhere('orders.id = :id', { id: options.id });
|
|
433
|
+
if (options.createdBy)
|
|
434
|
+
queryBuilder.andWhere('orders."createdBy" ILIKE :createdBy', {
|
|
435
|
+
createdBy: `%${options.createdBy}%`,
|
|
436
|
+
});
|
|
437
|
+
if (options.description)
|
|
438
|
+
queryBuilder.andWhere('orders.description ILIKE :description', {
|
|
439
|
+
description: `%${options.description}%`,
|
|
440
|
+
});
|
|
441
|
+
if (options.dateRange)
|
|
442
|
+
queryBuilder.andWhere('orders."createdAt" BETWEEN :from AND :to', {
|
|
443
|
+
from: options.dateRange.from,
|
|
444
|
+
to: options.dateRange.to,
|
|
445
|
+
});
|
|
446
|
+
if (options.status)
|
|
447
|
+
queryBuilder.andWhere(`status = :status`, {
|
|
448
|
+
status: options.status,
|
|
449
|
+
});
|
|
450
|
+
if (options.statuses && options.statuses.length > 0)
|
|
451
|
+
queryBuilder.andWhere(`status IN (:...statuses)`, {
|
|
452
|
+
statuses: options.statuses,
|
|
453
|
+
});
|
|
454
|
+
if (options.materialKey)
|
|
455
|
+
queryBuilder.andWhere(`EXISTS (
|
|
456
|
+
SELECT 1 FROM ship_inventory_order_items si_items
|
|
457
|
+
INNER JOIN materials si_mat ON si_mat.id = si_items."materialId"
|
|
458
|
+
WHERE si_items."orderId" = orders.id
|
|
459
|
+
AND si_mat.key ILIKE :materialKey
|
|
460
|
+
)`, { materialKey: `%${options.materialKey}%` });
|
|
461
|
+
if (options.batchKey)
|
|
462
|
+
queryBuilder.andWhere(`EXISTS (
|
|
463
|
+
SELECT 1 FROM ship_inventory_order_items si_items
|
|
464
|
+
INNER JOIN batches si_batch ON si_batch.id = si_items."batchId"
|
|
465
|
+
WHERE si_items."orderId" = orders.id
|
|
466
|
+
AND si_batch.key ILIKE :batchKey
|
|
467
|
+
)`, { batchKey: `%${options.batchKey}%` });
|
|
468
|
+
if (options.locationKey)
|
|
469
|
+
queryBuilder.andWhere(`EXISTS (
|
|
470
|
+
SELECT 1 FROM ship_inventory_order_items si_items
|
|
471
|
+
INNER JOIN locations si_loc ON si_loc.id = si_items."locationId"
|
|
472
|
+
WHERE si_items."orderId" = orders.id
|
|
473
|
+
AND si_loc.key ILIKE :locationKey
|
|
474
|
+
)`, { locationKey: `%${options.locationKey}%` });
|
|
475
|
+
if (options.loaderKey)
|
|
476
|
+
queryBuilder.andWhere(`EXISTS (
|
|
477
|
+
SELECT 1 FROM ship_inventory_order_items si_items
|
|
478
|
+
INNER JOIN loaders si_ldr ON si_ldr.id = si_items."loaderId"
|
|
479
|
+
WHERE si_items."orderId" = orders.id
|
|
480
|
+
AND si_ldr."serialId" ILIKE :loaderKey
|
|
481
|
+
)`, { loaderKey: `%${options.loaderKey}%` });
|
|
482
|
+
if (options.wildcard) {
|
|
483
|
+
const { key, value } = options.wildcard;
|
|
484
|
+
queryBuilder.andWhere(`orders."${String(key)}" ILIKE :value`, {
|
|
485
|
+
value: `%${value}%`,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
const total = await queryBuilder.getCount();
|
|
489
|
+
if (options.offset !== undefined && options.offset >= 0)
|
|
490
|
+
queryBuilder.skip(options.offset);
|
|
491
|
+
if (options.limit !== undefined && options.limit > 0)
|
|
492
|
+
queryBuilder.take(options.limit);
|
|
493
|
+
const items = await queryBuilder.getRawMany();
|
|
494
|
+
return [items, total];
|
|
495
|
+
}
|
|
496
|
+
async addShipInventoryOrderItems(options, manager = this.dataSource.manager) {
|
|
497
|
+
const shipInventoryOrderRepository = manager.getRepository(this.shipInventoryOrderEntity);
|
|
498
|
+
const order = await shipInventoryOrderRepository.findOneByOrFail({
|
|
499
|
+
id: options.orderId,
|
|
500
|
+
removedAt: IsNull(),
|
|
501
|
+
});
|
|
502
|
+
if (options.items.length) {
|
|
503
|
+
const items = options.items.map((item) => ({
|
|
504
|
+
...item,
|
|
505
|
+
orderId: options.orderId,
|
|
506
|
+
}));
|
|
507
|
+
await this.processShipInventoryOrderItems(items, manager);
|
|
508
|
+
}
|
|
509
|
+
return order;
|
|
510
|
+
}
|
|
511
|
+
ship(options) {
|
|
512
|
+
if (!Array.isArray(options))
|
|
513
|
+
options = [options];
|
|
514
|
+
return this.dataSource.transaction(async (manager) => {
|
|
515
|
+
const changeRepository = manager.getRepository(ShipInventoryOrderChangeEntityClass);
|
|
516
|
+
const itemRepository = manager.getRepository(this.shipInventoryOrderItemEntity);
|
|
517
|
+
const orderRepository = manager.getRepository(OrderEntity);
|
|
518
|
+
const stockRepository = manager.getRepository(StockEntityClass);
|
|
519
|
+
const items = await itemRepository.find({
|
|
520
|
+
where: { id: In(options.map((option) => option.itemId)) },
|
|
521
|
+
relations: ['changes'],
|
|
522
|
+
});
|
|
523
|
+
const itemMap = new Map(items.map((item) => [item.id, item]));
|
|
524
|
+
await Promise.all(options.map(async (option) => {
|
|
525
|
+
const item = itemMap.get(option.itemId);
|
|
526
|
+
if (!item)
|
|
527
|
+
return;
|
|
528
|
+
const conversionFactor = await this.materialService.getConversionFactor(item.materialId, item.unitId || undefined);
|
|
529
|
+
const totalShipped = item.changes.reduce((sum, change) => {
|
|
530
|
+
const qty = Number(change.quantityChanged);
|
|
531
|
+
return qty < 0 ? sum + Math.abs(qty) : sum;
|
|
532
|
+
}, 0);
|
|
533
|
+
const remainingQuantity = conversionFactor * item.targetShippedQuantity - totalShipped;
|
|
534
|
+
if (remainingQuantity - option.quantity * conversionFactor < 0) {
|
|
535
|
+
throw new Error(`Shipping quantity exceeds target for item ${option.itemId}`);
|
|
536
|
+
}
|
|
537
|
+
// Create splitted batch for ship completion
|
|
538
|
+
const shippedBatch = await this.batchService.splitBatch({
|
|
539
|
+
id: item.batchId,
|
|
540
|
+
inShipment: true,
|
|
541
|
+
manager,
|
|
542
|
+
});
|
|
543
|
+
const newOrder = await orderRepository.save(orderRepository.create());
|
|
544
|
+
await this.stockService.validateStockAvailability({
|
|
545
|
+
materialId: item.materialId,
|
|
546
|
+
batchId: item.batchId,
|
|
547
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
548
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
549
|
+
quantity: option.quantity * conversionFactor,
|
|
550
|
+
}, manager);
|
|
551
|
+
await Promise.all([
|
|
552
|
+
changeRepository.save(changeRepository.create({
|
|
553
|
+
itemId: option.itemId,
|
|
554
|
+
quantityChanged: -1 * option.quantity * conversionFactor,
|
|
555
|
+
id: newOrder.id,
|
|
556
|
+
})),
|
|
557
|
+
stockRepository.save(stockRepository.create([
|
|
558
|
+
{
|
|
559
|
+
batchId: shippedBatch.id,
|
|
560
|
+
materialId: item.materialId,
|
|
561
|
+
locationId: this.stockService.resolveLocationId(item.locationId),
|
|
562
|
+
loaderId: this.stockService.resolveLoaderId(item.loaderId),
|
|
563
|
+
quantity: -1 * option.quantity * conversionFactor,
|
|
564
|
+
orderId: newOrder.id,
|
|
565
|
+
},
|
|
566
|
+
])),
|
|
567
|
+
]);
|
|
568
|
+
}));
|
|
569
|
+
return true;
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Cancel prepared ship inventory order items
|
|
574
|
+
* Reverses the prepare step by moving stock from IN_SHIPMENT back to FREE
|
|
575
|
+
* Can only cancel prepared quantity that hasn't been shipped yet
|
|
576
|
+
* If quantity is not provided, cancels all remaining cancellable quantity
|
|
577
|
+
*/
|
|
578
|
+
cancelShip(options) {
|
|
579
|
+
if (!Array.isArray(options))
|
|
580
|
+
options = [options];
|
|
581
|
+
return this.dataSource.transaction(async (manager) => {
|
|
582
|
+
await this.cancelShipInternal(options, manager);
|
|
583
|
+
return true;
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
ShipInventoryOrderService = __decorate([
|
|
588
|
+
Injectable(),
|
|
589
|
+
__param(4, Inject(ShipInventoryOrderEntity)),
|
|
590
|
+
__param(5, Inject(ShipInventoryOrderItemEntity)),
|
|
591
|
+
__param(6, Inject(ShipInventoryOrderReferenceEntity)),
|
|
592
|
+
__param(7, Inject(SaleOrderEntity)),
|
|
593
|
+
__metadata("design:paramtypes", [DataSource,
|
|
594
|
+
MaterialService,
|
|
595
|
+
BatchService,
|
|
596
|
+
StockService, Object, Object, Object, Object])
|
|
597
|
+
], ShipInventoryOrderService);
|
|
598
|
+
|
|
599
|
+
export { ShipInventoryOrderService };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SplitBatchOrderEntityClass, SplitBatchOrderItemEntityClass } from '../models';
|
|
2
|
+
import { DataSource, EntityTarget } from 'typeorm';
|
|
3
|
+
import { SplitBatchInput } from '../typings/split-batch.input';
|
|
4
|
+
import { MaterialService } from './material.service';
|
|
5
|
+
import { BatchService } from './batch.service';
|
|
6
|
+
import { HelperService } from './helper.service';
|
|
7
|
+
import { StockService } from './stock.service';
|
|
8
|
+
export declare class SplitBatchOrderService<T extends SplitBatchOrderEntityClass = SplitBatchOrderEntityClass, K extends SplitBatchOrderItemEntityClass = SplitBatchOrderItemEntityClass> {
|
|
9
|
+
private readonly dataSource;
|
|
10
|
+
private readonly materialService;
|
|
11
|
+
private readonly batchService;
|
|
12
|
+
private readonly helperService;
|
|
13
|
+
private readonly stockService;
|
|
14
|
+
readonly splitBatchOrderEntity: EntityTarget<T>;
|
|
15
|
+
readonly splitBatchOrderItemEntity: EntityTarget<K>;
|
|
16
|
+
private readonly seqPrefix;
|
|
17
|
+
constructor(dataSource: DataSource, materialService: MaterialService, batchService: BatchService, helperService: HelperService, stockService: StockService, splitBatchOrderEntity: EntityTarget<T>, splitBatchOrderItemEntity: EntityTarget<K>);
|
|
18
|
+
split(options: SplitBatchInput): Promise<T>;
|
|
19
|
+
}
|