@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.
Files changed (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +80 -0
  3. package/index.cjs.js +6479 -0
  4. package/index.d.ts +5 -0
  5. package/index.js +74 -0
  6. package/lib/constants/index.d.ts +1 -0
  7. package/lib/constants/stock-status.d.ts +30 -0
  8. package/lib/constants/stock-status.js +51 -0
  9. package/lib/core.module.d.ts +7 -0
  10. package/lib/core.module.js +102 -0
  11. package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-change.entity.d.ts +10 -0
  12. package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-change.entity.js +40 -0
  13. package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-item.entity.d.ts +20 -0
  14. package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order-item.entity.js +103 -0
  15. package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order.entity.d.ts +8 -0
  16. package/lib/models/extensions/allocate-inventory-order/allocate-inventory-order.entity.js +33 -0
  17. package/lib/models/extensions/hold-inventory-order/hold-inventory-order-change.entity.d.ts +10 -0
  18. package/lib/models/extensions/hold-inventory-order/hold-inventory-order-change.entity.js +40 -0
  19. package/lib/models/extensions/hold-inventory-order/hold-inventory-order-item.entity.d.ts +19 -0
  20. package/lib/models/extensions/hold-inventory-order/hold-inventory-order-item.entity.js +97 -0
  21. package/lib/models/extensions/hold-inventory-order/hold-inventory-order.entity.d.ts +10 -0
  22. package/lib/models/extensions/hold-inventory-order/hold-inventory-order.entity.js +43 -0
  23. package/lib/models/extensions/index.d.ts +37 -0
  24. package/lib/models/extensions/merge-batch-order/merge-batch-order-change.entity.d.ts +10 -0
  25. package/lib/models/extensions/merge-batch-order/merge-batch-order-change.entity.js +40 -0
  26. package/lib/models/extensions/merge-batch-order/merge-batch-order-item.entity.d.ts +15 -0
  27. package/lib/models/extensions/merge-batch-order/merge-batch-order-item.entity.js +74 -0
  28. package/lib/models/extensions/merge-batch-order/merge-batch-order.entity.d.ts +8 -0
  29. package/lib/models/extensions/merge-batch-order/merge-batch-order.entity.js +33 -0
  30. package/lib/models/extensions/quality-inspection-order/quality-inspection-order-change.entity.d.ts +11 -0
  31. package/lib/models/extensions/quality-inspection-order/quality-inspection-order-change.entity.js +45 -0
  32. package/lib/models/extensions/quality-inspection-order/quality-inspection-order-item.entity.d.ts +18 -0
  33. package/lib/models/extensions/quality-inspection-order/quality-inspection-order-item.entity.js +93 -0
  34. package/lib/models/extensions/quality-inspection-order/quality-inspection-order.entity.d.ts +9 -0
  35. package/lib/models/extensions/quality-inspection-order/quality-inspection-order.entity.js +38 -0
  36. package/lib/models/extensions/receive-inventory-order/receive-inventory-order-change.entity.d.ts +12 -0
  37. package/lib/models/extensions/receive-inventory-order/receive-inventory-order-change.entity.js +46 -0
  38. package/lib/models/extensions/receive-inventory-order/receive-inventory-order-item.entity.d.ts +19 -0
  39. package/lib/models/extensions/receive-inventory-order/receive-inventory-order-item.entity.js +89 -0
  40. package/lib/models/extensions/receive-inventory-order/receive-inventory-order.entity.d.ts +13 -0
  41. package/lib/models/extensions/receive-inventory-order/receive-inventory-order.entity.js +57 -0
  42. package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-change.entity.d.ts +10 -0
  43. package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-change.entity.js +40 -0
  44. package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-item.entity.d.ts +15 -0
  45. package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order-item.entity.js +74 -0
  46. package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order.entity.d.ts +8 -0
  47. package/lib/models/extensions/reclassify-inventory-order/reclassify-inventory-order.entity.js +33 -0
  48. package/lib/models/extensions/scrape-order/scrape-order-change.entity.d.ts +10 -0
  49. package/lib/models/extensions/scrape-order/scrape-order-change.entity.js +40 -0
  50. package/lib/models/extensions/scrape-order/scrape-order-item.entity.d.ts +18 -0
  51. package/lib/models/extensions/scrape-order/scrape-order-item.entity.js +93 -0
  52. package/lib/models/extensions/scrape-order/scrape-order.entity.d.ts +8 -0
  53. package/lib/models/extensions/scrape-order/scrape-order.entity.js +33 -0
  54. package/lib/models/extensions/ship-inventory-order/ship-inventory-order-change.entity.d.ts +12 -0
  55. package/lib/models/extensions/ship-inventory-order/ship-inventory-order-change.entity.js +46 -0
  56. package/lib/models/extensions/ship-inventory-order/ship-inventory-order-item.entity.d.ts +19 -0
  57. package/lib/models/extensions/ship-inventory-order/ship-inventory-order-item.entity.js +90 -0
  58. package/lib/models/extensions/ship-inventory-order/ship-inventory-order-reference.entity.d.ts +13 -0
  59. package/lib/models/extensions/ship-inventory-order/ship-inventory-order-reference.entity.js +65 -0
  60. package/lib/models/extensions/ship-inventory-order/ship-inventory-order.entity.d.ts +13 -0
  61. package/lib/models/extensions/ship-inventory-order/ship-inventory-order.entity.js +56 -0
  62. package/lib/models/extensions/split-batch-order/split-batch-order-change.entity.d.ts +10 -0
  63. package/lib/models/extensions/split-batch-order/split-batch-order-change.entity.js +40 -0
  64. package/lib/models/extensions/split-batch-order/split-batch-order-item.entity.d.ts +15 -0
  65. package/lib/models/extensions/split-batch-order/split-batch-order-item.entity.js +74 -0
  66. package/lib/models/extensions/split-batch-order/split-batch-order.entity.d.ts +8 -0
  67. package/lib/models/extensions/split-batch-order/split-batch-order.entity.js +33 -0
  68. package/lib/models/extensions/transfer-customer-order/transfer-customer-order-change.entity.d.ts +10 -0
  69. package/lib/models/extensions/transfer-customer-order/transfer-customer-order-change.entity.js +40 -0
  70. package/lib/models/extensions/transfer-customer-order/transfer-customer-order-item.entity.d.ts +19 -0
  71. package/lib/models/extensions/transfer-customer-order/transfer-customer-order-item.entity.js +98 -0
  72. package/lib/models/extensions/transfer-customer-order/transfer-customer-order.entity.d.ts +8 -0
  73. package/lib/models/extensions/transfer-customer-order/transfer-customer-order.entity.js +33 -0
  74. package/lib/models/extensions/transfer-order/transfer-order-change.entity.d.ts +10 -0
  75. package/lib/models/extensions/transfer-order/transfer-order-change.entity.js +40 -0
  76. package/lib/models/extensions/transfer-order/transfer-order-item.entity.d.ts +21 -0
  77. package/lib/models/extensions/transfer-order/transfer-order-item.entity.js +108 -0
  78. package/lib/models/extensions/transfer-order/transfer-order.entity.d.ts +12 -0
  79. package/lib/models/extensions/transfer-order/transfer-order.entity.js +53 -0
  80. package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-change.entity.d.ts +10 -0
  81. package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-change.entity.js +40 -0
  82. package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-item.entity.d.ts +19 -0
  83. package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order-item.entity.js +98 -0
  84. package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order.entity.d.ts +8 -0
  85. package/lib/models/extensions/transfer-vendor-order/transfer-vendor-order.entity.js +33 -0
  86. package/lib/models/index.d.ts +2 -0
  87. package/lib/models/metadata/batch-group.entity.d.ts +8 -0
  88. package/lib/models/metadata/batch-group.entity.js +31 -0
  89. package/lib/models/metadata/batch.entity.d.ts +15 -0
  90. package/lib/models/metadata/batch.entity.js +73 -0
  91. package/lib/models/metadata/index.d.ts +11 -0
  92. package/lib/models/metadata/loader-type.entity.d.ts +9 -0
  93. package/lib/models/metadata/loader-type.entity.js +43 -0
  94. package/lib/models/metadata/loader-unit.entity.d.ts +5 -0
  95. package/lib/models/metadata/loader-unit.entity.js +21 -0
  96. package/lib/models/metadata/loader.entity.d.ts +21 -0
  97. package/lib/models/metadata/loader.entity.js +98 -0
  98. package/lib/models/metadata/location.entity.d.ts +8 -0
  99. package/lib/models/metadata/location.entity.js +28 -0
  100. package/lib/models/metadata/material-unit.entity.d.ts +11 -0
  101. package/lib/models/metadata/material-unit.entity.js +51 -0
  102. package/lib/models/metadata/material.entity.d.ts +7 -0
  103. package/lib/models/metadata/material.entity.js +28 -0
  104. package/lib/models/metadata/sale-order.entity.d.ts +5 -0
  105. package/lib/models/metadata/sale-order.entity.js +21 -0
  106. package/lib/models/metadata/stock.entity.d.ts +8 -0
  107. package/lib/models/metadata/stock.entity.js +29 -0
  108. package/lib/models/metadata/unit.entity.d.ts +5 -0
  109. package/lib/models/metadata/unit.entity.js +21 -0
  110. package/lib/models/models.module.d.ts +6 -0
  111. package/lib/models/models.module.js +122 -0
  112. package/lib/services/allocate-inventory-order.service.d.ts +29 -0
  113. package/lib/services/allocate-inventory-order.service.js +299 -0
  114. package/lib/services/base-order.service.d.ts +41 -0
  115. package/lib/services/batch.service.d.ts +30 -0
  116. package/lib/services/batch.service.js +218 -0
  117. package/lib/services/helper.service.d.ts +6 -0
  118. package/lib/services/helper.service.js +28 -0
  119. package/lib/services/hold-inventory-order.service.d.ts +29 -0
  120. package/lib/services/hold-inventory-order.service.js +285 -0
  121. package/lib/services/index.d.ts +22 -0
  122. package/lib/services/loader.service.d.ts +43 -0
  123. package/lib/services/loader.service.js +282 -0
  124. package/lib/services/location.service.d.ts +13 -0
  125. package/lib/services/location.service.js +130 -0
  126. package/lib/services/material.service.d.ts +27 -0
  127. package/lib/services/material.service.js +172 -0
  128. package/lib/services/merge-batch-order.service.d.ts +19 -0
  129. package/lib/services/merge-batch-order.service.js +195 -0
  130. package/lib/services/quality-inspection-order.service.d.ts +19 -0
  131. package/lib/services/quality-inspection-order.service.js +135 -0
  132. package/lib/services/receive-inventory-order.service.d.ts +41 -0
  133. package/lib/services/receive-inventory-order.service.js +407 -0
  134. package/lib/services/reclassify-inventory-order.service.d.ts +19 -0
  135. package/lib/services/reclassify-inventory-order.service.js +181 -0
  136. package/lib/services/sale-order.service.d.ts +7 -0
  137. package/lib/services/sale-order.service.js +20 -0
  138. package/lib/services/scrape.service.d.ts +18 -0
  139. package/lib/services/scrape.service.js +139 -0
  140. package/lib/services/ship-inventory-order.service.d.ts +60 -0
  141. package/lib/services/ship-inventory-order.service.js +599 -0
  142. package/lib/services/split-batch-order.service.d.ts +19 -0
  143. package/lib/services/split-batch-order.service.js +161 -0
  144. package/lib/services/stock.service.d.ts +38 -0
  145. package/lib/services/stock.service.js +477 -0
  146. package/lib/services/transfer-customer-order.service.d.ts +35 -0
  147. package/lib/services/transfer-customer-order.service.js +279 -0
  148. package/lib/services/transfer-order.service.d.ts +44 -0
  149. package/lib/services/transfer-order.service.js +632 -0
  150. package/lib/services/transfer-vendor-order.service.d.ts +35 -0
  151. package/lib/services/transfer-vendor-order.service.js +279 -0
  152. package/lib/services/unit.service.d.ts +7 -0
  153. package/lib/services/unit.service.js +67 -0
  154. package/lib/services/warehouse-map.service.d.ts +10 -0
  155. package/lib/services/warehouse-map.service.js +38 -0
  156. package/lib/typings/aggregated-stock.d.ts +22 -0
  157. package/lib/typings/cancel-ship-inventory-order.input.d.ts +4 -0
  158. package/lib/typings/cancel-transfer-order.input.d.ts +4 -0
  159. package/lib/typings/core-module-options.d.ts +8 -0
  160. package/lib/typings/core-module-options.js +3 -0
  161. package/lib/typings/create-allocate-inventory-order.input.d.ts +25 -0
  162. package/lib/typings/create-hold-inventory-order.input.d.ts +21 -0
  163. package/lib/typings/create-inspection-order.input.d.ts +14 -0
  164. package/lib/typings/create-loader-type.input.d.ts +9 -0
  165. package/lib/typings/create-loader.input.d.ts +15 -0
  166. package/lib/typings/create-location.input.d.ts +12 -0
  167. package/lib/typings/create-material-unit.input.d.ts +5 -0
  168. package/lib/typings/create-material.input.d.ts +11 -0
  169. package/lib/typings/create-receive-inventory-order.input.d.ts +26 -0
  170. package/lib/typings/create-ship-inventory-order.input.d.ts +46 -0
  171. package/lib/typings/create-transfer-customer-order.input.d.ts +25 -0
  172. package/lib/typings/create-transfer-order.input.d.ts +25 -0
  173. package/lib/typings/create-transfer-vendor-order.input.d.ts +25 -0
  174. package/lib/typings/deallocate-inventory-order.d.ts +8 -0
  175. package/lib/typings/find-allocate-inventory-order.input.d.ts +13 -0
  176. package/lib/typings/find-batch.input.d.ts +8 -0
  177. package/lib/typings/find-hold-inventory-order.input.d.ts +13 -0
  178. package/lib/typings/find-loader.input.d.ts +33 -0
  179. package/lib/typings/find-location.input.d.ts +10 -0
  180. package/lib/typings/find-material.input.d.ts +10 -0
  181. package/lib/typings/find-receive-inventory-order.input.d.ts +26 -0
  182. package/lib/typings/find-receive-inventory-order.input.js +9 -0
  183. package/lib/typings/find-ship-inventory-order.input.d.ts +26 -0
  184. package/lib/typings/find-ship-inventory-order.input.js +9 -0
  185. package/lib/typings/find-stock.input.d.ts +21 -0
  186. package/lib/typings/find-transfer-order.input.d.ts +21 -0
  187. package/lib/typings/get-batch.input.d.ts +14 -0
  188. package/lib/typings/index.d.ts +18 -0
  189. package/lib/typings/merge-batch.input.d.ts +11 -0
  190. package/lib/typings/paginations.d.ts +4 -0
  191. package/lib/typings/receive-inventory-order.input.d.ts +8 -0
  192. package/lib/typings/reclassify-inventory-order.input.d.ts +11 -0
  193. package/lib/typings/release-inventory-order.input.d.ts +8 -0
  194. package/lib/typings/scrape.input.d.ts +8 -0
  195. package/lib/typings/ship-inventory-order.input.d.ts +4 -0
  196. package/lib/typings/split-batch.input.d.ts +10 -0
  197. package/lib/typings/transfer-order.input.d.ts +4 -0
  198. package/package.json +52 -0
  199. 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
+ }