@shushed/helpers 0.0.202-bug-erp-770-20251203154925 → 0.0.202-main-20251208111718

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 (290) hide show
  1. package/dist/cjs/contracts/asset.schema.json +78 -0
  2. package/dist/cjs/contracts/category.schema.json +86 -0
  3. package/dist/cjs/contracts/country.schema.json +258 -0
  4. package/dist/cjs/contracts/currency.schema.json +177 -0
  5. package/dist/cjs/contracts/customer-segment.schema.json +32 -0
  6. package/dist/cjs/contracts/development-colour.schema.json +97 -0
  7. package/dist/cjs/contracts/index.js +48 -0
  8. package/dist/cjs/contracts/marketing-preferences.schema.json +41 -0
  9. package/dist/cjs/contracts/messages/ean-change.schema.json +22 -0
  10. package/dist/cjs/contracts/messages/index.js +29 -0
  11. package/dist/cjs/contracts/messages/order/delivered.schema.json +26 -0
  12. package/dist/cjs/contracts/messages/order/index.js +18 -0
  13. package/dist/cjs/contracts/messages/order/new.schema.json +32 -0
  14. package/dist/cjs/contracts/messages/order/processed.schema.json +15 -0
  15. package/dist/cjs/contracts/messages/order/return-initiated.schema.json +26 -0
  16. package/dist/cjs/contracts/messages/order/returned.schema.json +25 -0
  17. package/dist/cjs/contracts/messages/order/shipped.schema.json +26 -0
  18. package/dist/cjs/contracts/messages/product-category.schema.json +21 -0
  19. package/dist/cjs/contracts/messages/product-draft.schema.json +66 -0
  20. package/dist/cjs/contracts/messages/product.schema.json +29 -0
  21. package/dist/cjs/contracts/money.schema.json +54 -0
  22. package/dist/cjs/contracts/order/address.schema.json +127 -0
  23. package/dist/cjs/contracts/order/customer.schema.json +149 -0
  24. package/dist/cjs/contracts/order/index.js +31 -0
  25. package/dist/cjs/contracts/order/item.schema.json +98 -0
  26. package/dist/cjs/contracts/order/payment.schema.json +115 -0
  27. package/dist/cjs/contracts/order/shipment/index.js +29 -0
  28. package/dist/cjs/contracts/order/shipment/item/index.js +8 -0
  29. package/dist/cjs/contracts/order/shipment/item/returned.schema.json +30 -0
  30. package/dist/cjs/contracts/order/shipment/item.schema.json +22 -0
  31. package/dist/cjs/contracts/order/shipment/pos/index.js +10 -0
  32. package/dist/cjs/contracts/order/shipment/pos/outbound.schema.json +37 -0
  33. package/dist/cjs/contracts/order/shipment/pos/return.schema.json +31 -0
  34. package/dist/cjs/contracts/order/shipment/pos.schema.json +48 -0
  35. package/dist/cjs/contracts/order/shipment/shipped/index.js +10 -0
  36. package/dist/cjs/contracts/order/shipment/shipped/outbound.schema.json +34 -0
  37. package/dist/cjs/contracts/order/shipment/shipped/return.schema.json +43 -0
  38. package/dist/cjs/contracts/order/shipment/shipped.schema.json +52 -0
  39. package/dist/cjs/contracts/order/shipment.schema.json +58 -0
  40. package/dist/cjs/contracts/order.schema.json +231 -0
  41. package/dist/cjs/contracts/product-category.schema.json +34 -0
  42. package/dist/cjs/contracts/product-draft.schema.json +782 -0
  43. package/dist/cjs/contracts/product.schema.json +816 -0
  44. package/dist/cjs/contracts/total.schema.json +41 -0
  45. package/dist/cjs/dist-dereferenced/asset.js +4 -0
  46. package/dist/cjs/dist-dereferenced/category.js +4 -0
  47. package/dist/cjs/dist-dereferenced/country.js +4 -0
  48. package/dist/cjs/dist-dereferenced/currency.js +4 -0
  49. package/dist/cjs/dist-dereferenced/customer-segment.js +4 -0
  50. package/dist/cjs/dist-dereferenced/development-colour.js +4 -0
  51. package/dist/cjs/dist-dereferenced/index.js +69 -0
  52. package/dist/cjs/dist-dereferenced/marketing-preferences.js +4 -0
  53. package/dist/cjs/dist-dereferenced/messages/ean-change.js +4 -0
  54. package/dist/cjs/dist-dereferenced/messages/index.js +50 -0
  55. package/dist/cjs/dist-dereferenced/messages/order/delivered.js +4 -0
  56. package/dist/cjs/dist-dereferenced/messages/order/index.js +18 -0
  57. package/dist/cjs/dist-dereferenced/messages/order/new.js +4 -0
  58. package/dist/cjs/dist-dereferenced/messages/order/processed.js +4 -0
  59. package/dist/cjs/dist-dereferenced/messages/order/return-initiated.js +4 -0
  60. package/dist/cjs/dist-dereferenced/messages/order/returned.js +4 -0
  61. package/dist/cjs/dist-dereferenced/messages/order/shipped.js +4 -0
  62. package/dist/cjs/dist-dereferenced/messages/price-change.js +4 -0
  63. package/dist/cjs/dist-dereferenced/messages/product-category.js +4 -0
  64. package/dist/cjs/dist-dereferenced/messages/product-draft.js +4 -0
  65. package/dist/cjs/dist-dereferenced/messages/product.js +4 -0
  66. package/dist/cjs/dist-dereferenced/money.js +4 -0
  67. package/dist/cjs/dist-dereferenced/order/address.js +4 -0
  68. package/dist/cjs/dist-dereferenced/order/customer.js +4 -0
  69. package/dist/cjs/dist-dereferenced/order/index.js +51 -0
  70. package/dist/cjs/dist-dereferenced/order/item.js +4 -0
  71. package/dist/cjs/dist-dereferenced/order/orderMain.js +4 -0
  72. package/dist/cjs/dist-dereferenced/order/payment.js +4 -0
  73. package/dist/cjs/dist-dereferenced/order/shipment/index.js +45 -0
  74. package/dist/cjs/dist-dereferenced/order/shipment/item/index.js +11 -0
  75. package/dist/cjs/dist-dereferenced/order/shipment/item/itemMain.js +4 -0
  76. package/dist/cjs/dist-dereferenced/order/shipment/item/returned.js +4 -0
  77. package/dist/cjs/dist-dereferenced/order/shipment/pos/index.js +13 -0
  78. package/dist/cjs/dist-dereferenced/order/shipment/pos/outbound.js +4 -0
  79. package/dist/cjs/dist-dereferenced/order/shipment/pos/posMain.js +4 -0
  80. package/dist/cjs/dist-dereferenced/order/shipment/pos/return.js +4 -0
  81. package/dist/cjs/dist-dereferenced/order/shipment/shipmentMain.js +4 -0
  82. package/dist/cjs/dist-dereferenced/order/shipment/shipped/index.js +13 -0
  83. package/dist/cjs/dist-dereferenced/order/shipment/shipped/outbound.js +4 -0
  84. package/dist/cjs/dist-dereferenced/order/shipment/shipped/return.js +4 -0
  85. package/dist/cjs/dist-dereferenced/order/shipment/shipped/shippedMain.js +4 -0
  86. package/dist/cjs/dist-dereferenced/price.js +4 -0
  87. package/dist/cjs/dist-dereferenced/product-category.js +4 -0
  88. package/dist/cjs/dist-dereferenced/product-draft.js +4 -0
  89. package/dist/cjs/dist-dereferenced/product.js +4 -0
  90. package/dist/cjs/dist-dereferenced/stock.js +4 -0
  91. package/dist/cjs/dist-dereferenced/total.js +4 -0
  92. package/dist/cjs/dist-types/asset.js +2 -0
  93. package/dist/cjs/dist-types/category.js +2 -0
  94. package/dist/cjs/dist-types/country.js +2 -0
  95. package/dist/cjs/dist-types/currency.js +2 -0
  96. package/dist/cjs/dist-types/customer-segment.js +2 -0
  97. package/dist/cjs/dist-types/development-colour.js +2 -0
  98. package/dist/cjs/dist-types/index.js +38 -0
  99. package/dist/cjs/dist-types/marketing-preferences.js +2 -0
  100. package/dist/cjs/dist-types/messages/ean-change.js +2 -0
  101. package/dist/cjs/dist-types/messages/index.js +37 -0
  102. package/dist/cjs/dist-types/messages/order/delivered.js +2 -0
  103. package/dist/cjs/dist-types/messages/order/index.js +2 -0
  104. package/dist/cjs/dist-types/messages/order/new.js +2 -0
  105. package/dist/cjs/dist-types/messages/order/processed.js +2 -0
  106. package/dist/cjs/dist-types/messages/order/return-initiated.js +2 -0
  107. package/dist/cjs/dist-types/messages/order/returned.js +2 -0
  108. package/dist/cjs/dist-types/messages/order/shipped.js +2 -0
  109. package/dist/cjs/dist-types/messages/price-change.js +2 -0
  110. package/dist/cjs/dist-types/messages/product-category.js +2 -0
  111. package/dist/cjs/dist-types/messages/product-draft.js +2 -0
  112. package/dist/cjs/dist-types/messages/product.js +2 -0
  113. package/dist/cjs/dist-types/money.js +2 -0
  114. package/dist/cjs/dist-types/order/address.js +2 -0
  115. package/dist/cjs/dist-types/order/customer.js +2 -0
  116. package/dist/cjs/dist-types/order/index.js +37 -0
  117. package/dist/cjs/dist-types/order/item.js +2 -0
  118. package/dist/cjs/dist-types/order/orderMain.js +2 -0
  119. package/dist/cjs/dist-types/order/payment.js +2 -0
  120. package/dist/cjs/dist-types/order/shipment/index.js +39 -0
  121. package/dist/cjs/dist-types/order/shipment/item/index.js +2 -0
  122. package/dist/cjs/dist-types/order/shipment/item/itemMain.js +2 -0
  123. package/dist/cjs/dist-types/order/shipment/item/returned.js +2 -0
  124. package/dist/cjs/dist-types/order/shipment/pos/index.js +2 -0
  125. package/dist/cjs/dist-types/order/shipment/pos/outbound.js +2 -0
  126. package/dist/cjs/dist-types/order/shipment/pos/posMain.js +2 -0
  127. package/dist/cjs/dist-types/order/shipment/pos/return.js +2 -0
  128. package/dist/cjs/dist-types/order/shipment/shipmentMain.js +2 -0
  129. package/dist/cjs/dist-types/order/shipment/shipped/index.js +2 -0
  130. package/dist/cjs/dist-types/order/shipment/shipped/outbound.js +2 -0
  131. package/dist/cjs/dist-types/order/shipment/shipped/return.js +2 -0
  132. package/dist/cjs/dist-types/order/shipment/shipped/shippedMain.js +2 -0
  133. package/dist/cjs/dist-types/price.js +2 -0
  134. package/dist/cjs/dist-types/product-category.js +2 -0
  135. package/dist/cjs/dist-types/product-draft.js +2 -0
  136. package/dist/cjs/dist-types/product.js +2 -0
  137. package/dist/cjs/dist-types/stock.js +2 -0
  138. package/dist/cjs/dist-types/total.js +2 -0
  139. package/dist/cjs/index.js +39 -0
  140. package/dist/cjs/src-public/airtable.js +625 -0
  141. package/dist/cjs/src-public/bcOrder.js +943 -0
  142. package/dist/cjs/src-public/bigquery.js +59 -0
  143. package/dist/cjs/src-public/centra.js +1053 -0
  144. package/dist/cjs/src-public/cloudtasks.js +207 -0
  145. package/dist/cjs/src-public/dato.js +637 -0
  146. package/dist/cjs/src-public/env.js +900 -0
  147. package/dist/cjs/src-public/getEventTime.js +28 -0
  148. package/dist/cjs/src-public/index.js +54 -0
  149. package/dist/cjs/src-public/ipValidation.js +167 -0
  150. package/dist/cjs/src-public/jwks.js +108 -0
  151. package/dist/cjs/src-public/pubsub.js +423 -0
  152. package/dist/cjs/src-public/rateLimit.js +140 -0
  153. package/dist/cjs/src-public/redisClient.js +44 -0
  154. package/dist/cjs/src-public/runtime.js +145 -0
  155. package/dist/cjs/src-public/sanitize.js +25 -0
  156. package/dist/cjs/src-public/scheduler.js +247 -0
  157. package/dist/cjs/src-public/secret.js +16 -0
  158. package/dist/cjs/src-public/setHeaders.js +16 -0
  159. package/dist/cjs/src-public/types.js +2 -0
  160. package/dist/cjs/src-public/utils.js +457 -0
  161. package/dist/cjs/src-public/validate.js +74 -0
  162. package/dist/package.json +6 -3
  163. package/dist/types/contracts/index.d.ts +15 -0
  164. package/dist/types/contracts/messages/index.d.ts +5 -0
  165. package/dist/types/contracts/messages/order/index.d.ts +6 -0
  166. package/dist/types/contracts/order/index.d.ts +6 -0
  167. package/dist/types/contracts/order/shipment/index.d.ts +6 -0
  168. package/dist/types/contracts/order/shipment/item/index.d.ts +1 -0
  169. package/dist/types/contracts/order/shipment/pos/index.d.ts +2 -0
  170. package/dist/types/contracts/order/shipment/shipped/index.d.ts +2 -0
  171. package/dist/types/dist-dereferenced/asset.d.ts +51 -0
  172. package/dist/types/dist-dereferenced/category.d.ts +58 -0
  173. package/dist/types/dist-dereferenced/country.d.ts +8 -0
  174. package/dist/types/dist-dereferenced/currency.d.ts +8 -0
  175. package/dist/types/dist-dereferenced/customer-segment.d.ts +26 -0
  176. package/dist/types/dist-dereferenced/development-colour.d.ts +114 -0
  177. package/dist/types/dist-dereferenced/index.d.ts +16 -0
  178. package/dist/types/dist-dereferenced/marketing-preferences.d.ts +31 -0
  179. package/dist/types/dist-dereferenced/messages/ean-change.d.ts +17 -0
  180. package/dist/types/dist-dereferenced/messages/index.d.ts +6 -0
  181. package/dist/types/dist-dereferenced/messages/order/delivered.d.ts +3438 -0
  182. package/dist/types/dist-dereferenced/messages/order/index.d.ts +6 -0
  183. package/dist/types/dist-dereferenced/messages/order/new.d.ts +3438 -0
  184. package/dist/types/dist-dereferenced/messages/order/processed.d.ts +3432 -0
  185. package/dist/types/dist-dereferenced/messages/order/return-initiated.d.ts +3438 -0
  186. package/dist/types/dist-dereferenced/messages/order/returned.d.ts +3437 -0
  187. package/dist/types/dist-dereferenced/messages/order/shipped.d.ts +3436 -0
  188. package/dist/types/dist-dereferenced/messages/price-change.d.ts +67 -0
  189. package/dist/types/dist-dereferenced/messages/product-category.d.ts +33 -0
  190. package/dist/types/dist-dereferenced/messages/product-draft.d.ts +589 -0
  191. package/dist/types/dist-dereferenced/messages/product.d.ts +628 -0
  192. package/dist/types/dist-dereferenced/money.d.ts +41 -0
  193. package/dist/types/dist-dereferenced/order/address.d.ts +98 -0
  194. package/dist/types/dist-dereferenced/order/customer.d.ts +312 -0
  195. package/dist/types/dist-dereferenced/order/index.d.ts +3428 -0
  196. package/dist/types/dist-dereferenced/order/item.d.ts +339 -0
  197. package/dist/types/dist-dereferenced/order/orderMain.d.ts +3423 -0
  198. package/dist/types/dist-dereferenced/order/payment.d.ts +110 -0
  199. package/dist/types/dist-dereferenced/order/shipment/index.d.ts +253 -0
  200. package/dist/types/dist-dereferenced/order/shipment/item/index.d.ts +19 -0
  201. package/dist/types/dist-dereferenced/order/shipment/item/itemMain.d.ts +18 -0
  202. package/dist/types/dist-dereferenced/order/shipment/item/returned.d.ts +34 -0
  203. package/dist/types/dist-dereferenced/order/shipment/pos/index.d.ts +282 -0
  204. package/dist/types/dist-dereferenced/order/shipment/pos/outbound.d.ts +319 -0
  205. package/dist/types/dist-dereferenced/order/shipment/pos/posMain.d.ts +280 -0
  206. package/dist/types/dist-dereferenced/order/shipment/pos/return.d.ts +330 -0
  207. package/dist/types/dist-dereferenced/order/shipment/shipmentMain.d.ts +250 -0
  208. package/dist/types/dist-dereferenced/order/shipment/shipped/index.d.ts +288 -0
  209. package/dist/types/dist-dereferenced/order/shipment/shipped/outbound.d.ts +286 -0
  210. package/dist/types/dist-dereferenced/order/shipment/shipped/return.d.ts +287 -0
  211. package/dist/types/dist-dereferenced/order/shipment/shipped/shippedMain.d.ts +286 -0
  212. package/dist/types/dist-dereferenced/price.d.ts +58 -0
  213. package/dist/types/dist-dereferenced/product-category.d.ts +24 -0
  214. package/dist/types/dist-dereferenced/product-draft.d.ts +580 -0
  215. package/dist/types/dist-dereferenced/product.d.ts +619 -0
  216. package/dist/types/dist-dereferenced/stock.d.ts +74 -0
  217. package/dist/types/dist-dereferenced/total.d.ts +172 -0
  218. package/dist/types/dist-types/asset.d.ts +16 -0
  219. package/dist/types/dist-types/category.d.ts +20 -0
  220. package/dist/types/dist-types/country.d.ts +2 -0
  221. package/dist/types/dist-types/currency.d.ts +2 -0
  222. package/dist/types/dist-types/customer-segment.d.ts +6 -0
  223. package/dist/types/dist-types/development-colour.d.ts +31 -0
  224. package/dist/types/dist-types/index.d.ts +16 -0
  225. package/dist/types/dist-types/marketing-preferences.d.ts +9 -0
  226. package/dist/types/dist-types/messages/ean-change.d.ts +5 -0
  227. package/dist/types/dist-types/messages/index.d.ts +6 -0
  228. package/dist/types/dist-types/messages/order/delivered.d.ts +300 -0
  229. package/dist/types/dist-types/messages/order/index.d.ts +6 -0
  230. package/dist/types/dist-types/messages/order/new.d.ts +300 -0
  231. package/dist/types/dist-types/messages/order/processed.d.ts +300 -0
  232. package/dist/types/dist-types/messages/order/return-initiated.d.ts +300 -0
  233. package/dist/types/dist-types/messages/order/returned.d.ts +301 -0
  234. package/dist/types/dist-types/messages/order/shipped.d.ts +301 -0
  235. package/dist/types/dist-types/messages/price-change.d.ts +16 -0
  236. package/dist/types/dist-types/messages/product-category.d.ts +7 -0
  237. package/dist/types/dist-types/messages/product-draft.d.ts +136 -0
  238. package/dist/types/dist-types/messages/product.d.ts +144 -0
  239. package/dist/types/dist-types/money.d.ts +11 -0
  240. package/dist/types/dist-types/order/address.d.ts +27 -0
  241. package/dist/types/dist-types/order/customer.d.ts +82 -0
  242. package/dist/types/dist-types/order/index.d.ts +8 -0
  243. package/dist/types/dist-types/order/item.d.ts +86 -0
  244. package/dist/types/dist-types/order/orderMain.d.ts +297 -0
  245. package/dist/types/dist-types/order/payment.d.ts +30 -0
  246. package/dist/types/dist-types/order/shipment/index.d.ts +6 -0
  247. package/dist/types/dist-types/order/shipment/item/index.d.ts +4 -0
  248. package/dist/types/dist-types/order/shipment/item/itemMain.d.ts +6 -0
  249. package/dist/types/dist-types/order/shipment/item/returned.d.ts +11 -0
  250. package/dist/types/dist-types/order/shipment/pos/index.d.ts +5 -0
  251. package/dist/types/dist-types/order/shipment/pos/outbound.d.ts +76 -0
  252. package/dist/types/dist-types/order/shipment/pos/posMain.d.ts +71 -0
  253. package/dist/types/dist-types/order/shipment/pos/return.d.ts +75 -0
  254. package/dist/types/dist-types/order/shipment/shipmentMain.d.ts +62 -0
  255. package/dist/types/dist-types/order/shipment/shipped/index.d.ts +5 -0
  256. package/dist/types/dist-types/order/shipment/shipped/outbound.d.ts +68 -0
  257. package/dist/types/dist-types/order/shipment/shipped/return.d.ts +68 -0
  258. package/dist/types/dist-types/order/shipment/shipped/shippedMain.d.ts +69 -0
  259. package/dist/types/dist-types/price.d.ts +15 -0
  260. package/dist/types/dist-types/product-category.d.ts +6 -0
  261. package/dist/types/dist-types/product-draft.d.ts +135 -0
  262. package/dist/types/dist-types/product.d.ts +143 -0
  263. package/dist/types/dist-types/stock.d.ts +19 -0
  264. package/dist/types/dist-types/total.d.ts +44 -0
  265. package/dist/types/index.d.ts +3 -0
  266. package/dist/types/src-public/airtable.d.ts +227 -0
  267. package/dist/types/src-public/bcOrder.d.ts +84 -0
  268. package/dist/types/src-public/bigquery.d.ts +17 -0
  269. package/dist/types/src-public/centra.d.ts +176 -0
  270. package/dist/types/src-public/cloudtasks.d.ts +74 -0
  271. package/dist/types/src-public/dato.d.ts +88 -0
  272. package/dist/types/src-public/env.d.ts +144 -0
  273. package/dist/types/src-public/getEventTime.d.ts +1 -0
  274. package/dist/types/src-public/index.d.ts +19 -0
  275. package/dist/types/src-public/ipValidation.d.ts +15 -0
  276. package/dist/types/src-public/jwks.d.ts +15 -0
  277. package/dist/types/src-public/pubsub.d.ts +95 -0
  278. package/dist/types/src-public/rateLimit.d.ts +21 -0
  279. package/dist/types/src-public/redisClient.d.ts +6 -0
  280. package/dist/types/src-public/runtime.d.ts +58 -0
  281. package/dist/types/src-public/sanitize.d.ts +4 -0
  282. package/dist/types/src-public/scheduler.d.ts +71 -0
  283. package/dist/types/src-public/secret.d.ts +6 -0
  284. package/dist/types/src-public/setHeaders.d.ts +13 -0
  285. package/dist/types/src-public/types.d.ts +264 -0
  286. package/dist/types/src-public/utils.d.ts +101 -0
  287. package/dist/types/src-public/validate.d.ts +9 -0
  288. package/package.json +7 -4
  289. package/dist/index.d.ts +0 -34970
  290. package/dist/index.js +0 -113296
@@ -0,0 +1,943 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BCOrderHelper = void 0;
7
+ exports.buildLineGrouping = buildLineGrouping;
8
+ exports.transformMasterOrder = transformMasterOrder;
9
+ exports.validateOrder = validateOrder;
10
+ const order_schema_json_1 = __importDefault(require("../contracts/order.schema.json"));
11
+ const runtime_1 = __importDefault(require("./runtime"));
12
+ const validate_1 = __importDefault(require("./validate"));
13
+ const GBP = "GBP";
14
+ function toMinorUnits(amount) {
15
+ if (typeof amount !== "number" || !isFinite(amount))
16
+ return 0;
17
+ return Math.round(amount * 100);
18
+ }
19
+ function money(value) {
20
+ const v = toMinorUnits(value);
21
+ return {
22
+ value: v,
23
+ currency: GBP,
24
+ decimal_places: 2,
25
+ lcy_value: v,
26
+ lcy_currency: GBP,
27
+ lcy_decimal_places: 2,
28
+ };
29
+ }
30
+ function moneyFromMinor(minor) {
31
+ return {
32
+ value: Math.round(minor),
33
+ currency: GBP,
34
+ decimal_places: 2,
35
+ lcy_value: Math.round(minor),
36
+ lcy_currency: GBP,
37
+ lcy_decimal_places: 2,
38
+ };
39
+ }
40
+ function buildLineGrouping(payload) {
41
+ const group = {};
42
+ const makeKey = (orderNo, lineNo) => `${orderNo}:${lineNo}`;
43
+ (payload.sales || []).forEach((sale) => {
44
+ const orderNo = String(sale?.no || sale?.document_no || payload.no || "");
45
+ (sale.sale_lines || []).forEach((l) => {
46
+ if (String(l?.type || '').toLowerCase() !== 'item')
47
+ return;
48
+ const lineNo = Number(l?.line_no || 0);
49
+ if (!orderNo || !lineNo)
50
+ return;
51
+ const key = makeKey(orderNo, lineNo);
52
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
53
+ entry.sale = { document_no: orderNo };
54
+ group[key] = entry;
55
+ });
56
+ });
57
+ (payload.invoices || []).forEach((inv) => {
58
+ const documentNo = String(inv?.no || inv?.document_no || "");
59
+ (inv.invoice_lines || []).forEach((l) => {
60
+ if (String(l?.type || '').toLowerCase() !== 'item')
61
+ return;
62
+ const orderNo = String(l?.order_no || inv?.order_no || payload.no || "");
63
+ const lineNo = Number(l?.order_line_no || l?.line_no || 0);
64
+ if (!orderNo || !lineNo)
65
+ return;
66
+ const key = makeKey(orderNo, lineNo);
67
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
68
+ entry.invoice = { document_no: documentNo || orderNo };
69
+ group[key] = entry;
70
+ });
71
+ });
72
+ (payload.shipments || []).forEach((sh) => {
73
+ const documentNo = String(sh?.no || sh?.document_no || "");
74
+ (sh.shipment_lines || []).forEach((l) => {
75
+ const orderNo = String(l?.order_no || payload.no || "");
76
+ const lineNo = Number(l?.order_line_no || l?.line_no || 0);
77
+ if (!orderNo || !lineNo)
78
+ return;
79
+ const key = makeKey(orderNo, lineNo);
80
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
81
+ entry.shipment = { document_no: documentNo || orderNo };
82
+ group[key] = entry;
83
+ });
84
+ });
85
+ (payload.credit_memos || []).forEach((cm) => {
86
+ const documentNo = String(cm?.no || cm?.document_no || "");
87
+ (cm.credit_memo_lines || []).forEach((l) => {
88
+ const orderNo = String(l?.order_no || payload.no || "");
89
+ const lineNo = Number(l?.order_line_no || l?.line_no || 0);
90
+ if (!orderNo || !lineNo)
91
+ return;
92
+ const key = makeKey(orderNo, lineNo);
93
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
94
+ entry.credit_memo = { document_no: documentNo || orderNo };
95
+ group[key] = entry;
96
+ });
97
+ });
98
+ return group;
99
+ }
100
+ function transformMasterOrder(payload) {
101
+ const erp_order_id = payload.no || payload.system_id || "";
102
+ const sale0 = (payload.sales || [])[0];
103
+ const invoice0 = (payload.invoices || [])[0];
104
+ const ordered_at_candidates = [];
105
+ if (sale0?.system_created_at)
106
+ ordered_at_candidates.push(sale0.system_created_at);
107
+ if (Array.isArray(payload.invoices) && payload.invoices.length > 0) {
108
+ const invDates = payload.invoices.map((i) => i.system_created_at).filter(Boolean);
109
+ ordered_at_candidates.push(...invDates);
110
+ }
111
+ if (payload.ordered_at)
112
+ ordered_at_candidates.push(String(payload.ordered_at));
113
+ if (payload.created_at)
114
+ ordered_at_candidates.push(String(payload.created_at));
115
+ const orderedAtRaw = ordered_at_candidates.length > 0
116
+ ? ordered_at_candidates.sort()[0]
117
+ : new Date().toISOString();
118
+ let ordered_at;
119
+ try {
120
+ const dateStr = typeof orderedAtRaw === 'string' && orderedAtRaw.includes('T')
121
+ ? orderedAtRaw
122
+ : `${orderedAtRaw}T00:00:00Z`;
123
+ const date = new Date(dateStr);
124
+ if (isNaN(date.getTime())) {
125
+ ordered_at = new Date().toISOString();
126
+ }
127
+ else {
128
+ ordered_at = date.toISOString();
129
+ }
130
+ }
131
+ catch {
132
+ ordered_at = new Date().toISOString();
133
+ }
134
+ const created_by_raw = sale0?.created_by ?? invoice0?.created_by ?? "";
135
+ const system_created_by = created_by_raw === "SITOO" ? "POS" : created_by_raw === "STOREFRONT" ? "ECOMMERCE" : "SYSTEM";
136
+ const is_gift = Boolean((sale0?.gift_message && String(sale0.gift_message).trim().length > 0) ||
137
+ (payload.invoices?.some((i) => (i.gift_message || "").trim().length > 0)));
138
+ const invoiceLinesForReturn = payload.invoices?.flatMap((i) => i.invoice_lines || []) || [];
139
+ const salesLinesFallbackForReturn = (sale0?.sale_lines || []);
140
+ const sourceLinesForReturn = invoiceLinesForReturn.length > 0 ? invoiceLinesForReturn : salesLinesFallbackForReturn;
141
+ const skuByDescription = {};
142
+ sourceLinesForReturn.forEach((line) => {
143
+ if ((line?.type || "") !== "Item")
144
+ return;
145
+ const itemNo = String(line?.no || "");
146
+ const variant = String(line?.variant_code || "");
147
+ const desc = String(line?.description || "");
148
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
149
+ if (desc)
150
+ skuByDescription[desc] = sku;
151
+ });
152
+ const isItemish = (type, itemNo, desc) => {
153
+ const t = String(type || '').toLowerCase();
154
+ return t.includes('item') || itemNo.includes('-') || desc.includes(' - ');
155
+ };
156
+ const returnedQtyBySku = {};
157
+ (payload.credit_memos || []).forEach((cm) => {
158
+ (cm.credit_memo_lines || []).forEach((l) => {
159
+ const itemNo = String(l?.item_no || l?.no || '');
160
+ const desc = String(l?.description || '');
161
+ if (itemNo.toUpperCase() === 'X DELCHR' || itemNo.toUpperCase() === 'REFUND')
162
+ return;
163
+ if ((l?.quantity || 0) <= 0)
164
+ return;
165
+ const typeStr = String(l?.type || '').toLowerCase();
166
+ const isTypeItem = typeStr.includes('item');
167
+ if (isTypeItem) {
168
+ const variant = String(l?.variant_code || '');
169
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
170
+ returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
171
+ }
172
+ else if (desc && skuByDescription[desc]) {
173
+ const sku = skuByDescription[desc];
174
+ returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
175
+ }
176
+ });
177
+ });
178
+ (payload.sales || []).forEach((sale) => {
179
+ const docTypeRaw = String(sale?.document_type || sale?.documentType || '');
180
+ if (!docTypeRaw.toLowerCase().includes('return'))
181
+ return;
182
+ (sale.sale_lines || []).forEach((l) => {
183
+ const itemNo = String(l?.item_no || l?.no || '');
184
+ const desc = String(l?.description || '');
185
+ if (itemNo.toUpperCase() === 'X DELCHR' || itemNo.toUpperCase() === 'REFUND')
186
+ return;
187
+ if ((l?.quantity || 0) <= 0)
188
+ return;
189
+ if (!isItemish(l?.type, itemNo, desc))
190
+ return;
191
+ const variant = String(l?.variant_code || '');
192
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
193
+ returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
194
+ });
195
+ });
196
+ const invoiceLines = payload.invoices?.flatMap((i) => i.invoice_lines || []) || [];
197
+ const salesLinesFallback = (sale0?.sale_lines || []).map((l) => ({
198
+ type: l.type || "Item",
199
+ no: l.no,
200
+ variant_code: l.variant_code,
201
+ quantity: l.quantity,
202
+ amount: l.amount,
203
+ amount_including_vat: l.amount_including_vat,
204
+ price_update_reason: l.price_update_reason,
205
+ salesforce_promotion_id: l.salesforce_promotion_id,
206
+ line_discount_amount: l.line_discount_amount,
207
+ line_discount_percent: l.line_discount_percent,
208
+ unit_cost_lcy: l.unit_cost_lcy,
209
+ unit_price: l.unit_price,
210
+ vat_percent: l.vat_percent,
211
+ order_line_no: l.line_no,
212
+ }));
213
+ const sourceLines = invoiceLines.length > 0 ? invoiceLines : salesLinesFallback;
214
+ const headerPricesInclVat = invoiceLines.length > 0
215
+ ? Boolean(invoice0?.prices_including_vat)
216
+ : Boolean(sale0?.prices_including_vat);
217
+ const shippedQtyBySku = {};
218
+ (payload.shipments || []).forEach((s) => {
219
+ (s.shipment_lines || []).forEach((l) => {
220
+ const itemNo = String(l?.item_no || l?.no || "");
221
+ if (itemNo.toUpperCase() === 'X DELCHR')
222
+ return;
223
+ const desc = String(l?.description || '');
224
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
225
+ const qty = Number(l?.quantity || 0);
226
+ if (!looksProduct)
227
+ return;
228
+ if (qty <= 0)
229
+ return;
230
+ const variant = String(l?.variant_code || "");
231
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
232
+ shippedQtyBySku[sku] = (shippedQtyBySku[sku] || 0) + qty;
233
+ });
234
+ });
235
+ const shippedRemainingBySku = { ...shippedQtyBySku };
236
+ const returnedTotalBySkuCapped = {};
237
+ Object.keys(returnedQtyBySku).forEach((k) => {
238
+ const totalReturned = Number(returnedQtyBySku[k] || 0);
239
+ const totalShipped = Number(shippedQtyBySku[k] || 0);
240
+ returnedTotalBySkuCapped[k] = totalShipped ? Math.min(totalReturned, totalShipped) : totalReturned;
241
+ });
242
+ const returnedRemainingBySku = { ...returnedTotalBySkuCapped };
243
+ const itemsList = [];
244
+ sourceLines
245
+ .filter((line) => line.type === "Item")
246
+ .forEach((line) => {
247
+ const itemNo = line.no || "";
248
+ const variant = line.variant_code || "";
249
+ const quantity = Number(line.quantity || 0);
250
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
251
+ const parts = itemNo.split("-");
252
+ const style_id = parts.length >= 2 && parts[0] ? parts[0] : null;
253
+ const colour_id = parts.length >= 2 && parts[1] ? parts[1] : null;
254
+ const product_id = (() => {
255
+ const s = String(itemNo || "");
256
+ if (!s)
257
+ return null;
258
+ const parts = s.split("-");
259
+ return parts.length >= 2 ? `${parts[0]}-${parts[1]}` : s;
260
+ })();
261
+ const netTotal = Number(line.amount || 0);
262
+ const grossTotal = Number(line.amount_including_vat || 0);
263
+ const unitPriceRaw = Number(line.unit_price || 0);
264
+ const vatPercent = Number(line.vat_percent || 0);
265
+ let vatRate = 0;
266
+ if (vatPercent > 0) {
267
+ vatRate = vatPercent / 100;
268
+ }
269
+ else if (netTotal > 0 && grossTotal > 0) {
270
+ vatRate = Math.max(0, (grossTotal - netTotal) / netTotal);
271
+ }
272
+ let unitNet = 0;
273
+ let unitGross = 0;
274
+ if (unitPriceRaw > 0) {
275
+ if (headerPricesInclVat) {
276
+ unitGross = unitPriceRaw;
277
+ unitNet = vatRate > 0 ? (unitGross / (1 + vatRate)) : unitGross;
278
+ }
279
+ else {
280
+ unitNet = unitPriceRaw;
281
+ unitGross = vatRate > 0 ? (unitNet * (1 + vatRate)) : unitNet;
282
+ }
283
+ }
284
+ else {
285
+ unitNet = quantity > 0
286
+ ? (netTotal > 0
287
+ ? netTotal / quantity
288
+ : (grossTotal > 0 && vatRate > 0 ? (grossTotal / (1 + vatRate)) / quantity : 0))
289
+ : 0;
290
+ unitGross = quantity > 0
291
+ ? (grossTotal > 0
292
+ ? grossTotal / quantity
293
+ : (netTotal > 0 && vatRate > 0 ? (netTotal * (1 + vatRate)) / quantity : 0))
294
+ : 0;
295
+ }
296
+ const discountCode = (line.salesforce_promotion_id && line.salesforce_promotion_id.trim().length > 0)
297
+ ? line.salesforce_promotion_id.trim()
298
+ : null;
299
+ let unit_price_status = "rrp";
300
+ const reason = (line.price_update_reason || "").toUpperCase();
301
+ if (reason === "PERM")
302
+ unit_price_status = "perm";
303
+ else if (reason === "RRP")
304
+ unit_price_status = "rrp";
305
+ else if (reason === "POS")
306
+ unit_price_status = "pos";
307
+ const discountPercent = Number(line.line_discount_percent || 0);
308
+ const discountAmountRaw = Number(line.line_discount_amount || 0);
309
+ let discountNet = 0;
310
+ let discountGross = 0;
311
+ if (discountAmountRaw > 0) {
312
+ if (headerPricesInclVat) {
313
+ discountGross = discountAmountRaw;
314
+ discountNet = vatRate > 0 ? (discountGross / (1 + vatRate)) : discountGross;
315
+ }
316
+ else {
317
+ discountNet = discountAmountRaw;
318
+ discountGross = vatRate > 0 ? (discountNet * (1 + vatRate)) : discountNet;
319
+ }
320
+ }
321
+ else if (discountPercent > 0) {
322
+ if (netTotal > 0)
323
+ discountNet = (netTotal * discountPercent) / 100;
324
+ if (grossTotal > 0)
325
+ discountGross = (grossTotal * discountPercent) / 100;
326
+ if (grossTotal === 0 && discountNet > 0 && vatRate > 0)
327
+ discountGross = discountNet * (1 + vatRate);
328
+ if (netTotal === 0 && discountGross > 0 && vatRate > 0)
329
+ discountNet = discountGross / (1 + vatRate);
330
+ }
331
+ const take = Math.min(shippedRemainingBySku[sku] || 0, quantity);
332
+ const remaining = quantity - take;
333
+ const baseFields = {
334
+ sku,
335
+ linked_style_id: null,
336
+ colour_id,
337
+ style_id: (style_id || null),
338
+ unit_price_status,
339
+ unit_price_net: money(unitNet),
340
+ unit_price_gross: money(unitGross),
341
+ cost_net: money(line.unit_cost_lcy || 0),
342
+ size_name: (variant || undefined),
343
+ preorder_date: null,
344
+ discount_code: discountCode,
345
+ order_line_no: line.order_line_no || null,
346
+ product_id,
347
+ };
348
+ const pushItem = (qty, returnedQtyForLine) => {
349
+ itemsList.push({
350
+ ...baseFields,
351
+ quantity: qty,
352
+ returned_quantity: Math.max(0, Number(returnedQtyForLine || 0)),
353
+ amount_net: money(unitNet * qty),
354
+ amount_gross: money(unitGross * qty),
355
+ discount_amount_net: money(discountNet * (qty / Math.max(1, quantity))),
356
+ discount_amount_gross: money(discountGross * (qty / Math.max(1, quantity))),
357
+ discount_amount_percent: line.line_discount_percent || 0,
358
+ });
359
+ };
360
+ if (take > 0) {
361
+ const retForShipped = Math.min(Math.max(0, returnedRemainingBySku[sku] || 0), take);
362
+ pushItem(take, retForShipped);
363
+ shippedRemainingBySku[sku] = Math.max(0, (shippedRemainingBySku[sku] || 0) - take);
364
+ if (retForShipped > 0) {
365
+ returnedRemainingBySku[sku] = Math.max(0, (returnedRemainingBySku[sku] || 0) - retForShipped);
366
+ }
367
+ }
368
+ if (remaining > 0) {
369
+ pushItem(remaining, 0);
370
+ }
371
+ });
372
+ const itemsMap = {};
373
+ itemsList.forEach((it) => {
374
+ if (!itemsMap[it.sku])
375
+ itemsMap[it.sku] = [];
376
+ itemsMap[it.sku].push(it);
377
+ });
378
+ const invoicedLineNos = new Set((payload.invoices || []).flatMap((inv) => (inv?.invoice_lines || []).map((l) => Number(l?.order_line_no || -1))));
379
+ let invoicesNetMinor = toMinorUnits((payload.invoices || []).reduce((acc, inv) => acc + (inv.amount_excl_vat || 0), 0));
380
+ let invoicesGrossMinor = toMinorUnits((payload.invoices || []).reduce((acc, inv) => acc + (inv.amount_incl_vat || 0), 0));
381
+ if (invoicesGrossMinor === 0 && invoicedLineNos.size > 0 && sale0?.sale_lines) {
382
+ const invoicedSaleLines = (sale0.sale_lines || []).filter((l) => {
383
+ const lineNo = Number(l?.line_no || -1);
384
+ const itemNo = String(l?.item_no || l?.no || '').toUpperCase();
385
+ if (itemNo === 'X DELCHR')
386
+ return false;
387
+ if (String(l?.type || '').toLowerCase() !== 'item')
388
+ return false;
389
+ return invoicedLineNos.has(lineNo);
390
+ });
391
+ invoicesNetMinor = toMinorUnits(invoicedSaleLines.reduce((acc, l) => acc + (Number(l?.amount || 0)), 0));
392
+ invoicesGrossMinor = toMinorUnits(invoicedSaleLines.reduce((acc, l) => acc + (Number(l?.amount_including_vat || 0)), 0));
393
+ }
394
+ let nonInvSalesNetMinor = 0;
395
+ let nonInvSalesGrossMinor = 0;
396
+ if (sale0 && (sale0.amount_excl_vat || sale0.amount_incl_vat)) {
397
+ const saleNetMinor = toMinorUnits(sale0.amount_excl_vat || 0);
398
+ const saleGrossMinor = toMinorUnits(sale0.amount_incl_vat || 0);
399
+ if (invoicesGrossMinor > 0) {
400
+ nonInvSalesNetMinor = Math.max(0, saleNetMinor - invoicesNetMinor);
401
+ nonInvSalesGrossMinor = Math.max(0, saleGrossMinor - invoicesGrossMinor);
402
+ }
403
+ else {
404
+ nonInvSalesNetMinor = saleNetMinor;
405
+ nonInvSalesGrossMinor = saleGrossMinor;
406
+ }
407
+ }
408
+ else {
409
+ const nonInvoicedSales = (sale0?.sale_lines || []).filter((l) => {
410
+ const lineNo = Number(l?.line_no || -1);
411
+ const itemNo = String(l?.item_no || l?.no || '').toUpperCase();
412
+ if (itemNo === 'X DELCHR')
413
+ return false;
414
+ if (String(l?.type || '').toLowerCase() !== 'item')
415
+ return false;
416
+ return !invoicedLineNos.has(lineNo);
417
+ });
418
+ nonInvSalesNetMinor = toMinorUnits(nonInvoicedSales.reduce((acc, l) => acc + (Number(l?.amount || 0)), 0));
419
+ nonInvSalesGrossMinor = toMinorUnits(nonInvoicedSales.reduce((acc, l) => acc + (Number(l?.amount_including_vat || 0)), 0));
420
+ }
421
+ const returnsNetMinor = toMinorUnits((payload.credit_memos || []).reduce((acc, cm) => acc + (cm.amount_excl_vat || 0), 0));
422
+ const returnsGrossMinor = toMinorUnits((payload.credit_memos || []).reduce((acc, cm) => acc + (cm.amount_incl_vat || 0), 0));
423
+ const totalNetMinor = invoicesNetMinor + nonInvSalesNetMinor;
424
+ const totalGrossMinor = invoicesGrossMinor + nonInvSalesGrossMinor;
425
+ const total = {
426
+ amount_net: moneyFromMinor(totalNetMinor),
427
+ amount_gross: moneyFromMinor(totalGrossMinor),
428
+ discount_amount_net: money(0),
429
+ discount_amount_gross: money(0),
430
+ discount_amount_percent: 0,
431
+ };
432
+ const return_total = (payload.credit_memos && payload.credit_memos.length > 0)
433
+ ? {
434
+ amount_net: moneyFromMinor(returnsNetMinor),
435
+ amount_gross: moneyFromMinor(returnsGrossMinor),
436
+ discount_amount_net: money(0),
437
+ discount_amount_gross: money(0),
438
+ discount_amount_percent: 0,
439
+ }
440
+ : undefined;
441
+ const net_total = {
442
+ amount_net: moneyFromMinor(Math.max(0, totalNetMinor - returnsNetMinor)),
443
+ amount_gross: moneyFromMinor(Math.max(0, totalGrossMinor - returnsGrossMinor)),
444
+ discount_amount_net: money(0),
445
+ discount_amount_gross: money(0),
446
+ discount_amount_percent: 0,
447
+ };
448
+ const normalizeDateTime = (dateMaybe, fallbackIso) => {
449
+ const source = (typeof dateMaybe === "string" && dateMaybe.length > 0)
450
+ ? dateMaybe
451
+ : fallbackIso;
452
+ const d = new Date(source.includes("T") ? source : `${source}T00:00:00Z`);
453
+ return isNaN(d.getTime()) ? new Date().toISOString() : d.toISOString();
454
+ };
455
+ const mappedShipments = (payload.shipments || []).map((s) => {
456
+ const rawLines = (s.shipment_lines || [])
457
+ .filter((l) => (l?.quantity ?? 0) > 0)
458
+ .filter((l) => String(l?.item_no || '').toUpperCase() !== 'X DELCHR')
459
+ .filter((l) => {
460
+ const itemNo = String(l?.item_no || '');
461
+ const desc = String(l?.description || '');
462
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
463
+ return looksProduct;
464
+ });
465
+ const qtyBySku = new Map();
466
+ rawLines.forEach((l) => {
467
+ const itemNo = String(l?.item_no || '');
468
+ const variant = String(l?.variant_code || '');
469
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
470
+ const q = Number(l?.quantity || 0);
471
+ qtyBySku.set(sku, (qtyBySku.get(sku) || 0) + q);
472
+ });
473
+ const skus = Array.from(qtyBySku.keys()).sort();
474
+ const shipmentLines = skus.map((sku, idx) => ({
475
+ lineNumber: idx + 1,
476
+ sku,
477
+ quantity: Math.max(1, qtyBySku.get(sku) || 0),
478
+ }));
479
+ const statusVal = shipmentLines.length > 0 ? "SHIPPED" : "PENDING";
480
+ return {
481
+ erp_id: s.no || s.system_id || "",
482
+ shipped_at: normalizeDateTime(s.shipment_date, ordered_at),
483
+ status: statusVal,
484
+ type: statusVal === "SHIPPED" ? "SHIPPED-OUTBOUND" : undefined,
485
+ shipped_by: "TORQUE",
486
+ items: shipmentLines,
487
+ amount_net: money(0),
488
+ amount_gross: money(0),
489
+ discount_amount_net: money(0),
490
+ discount_amount_gross: money(0),
491
+ discount_amount_percent: 0,
492
+ };
493
+ });
494
+ const returnShipments = (payload.credit_memos || [])
495
+ .filter((cm) => {
496
+ const lines = cm?.credit_memo_lines || [];
497
+ return lines.some((l) => {
498
+ const itemNo = String(l?.item_no || l?.no || "");
499
+ const upper = itemNo.toUpperCase();
500
+ if (upper === 'X DELCHR' || upper === 'REFUND')
501
+ return false;
502
+ const looksProduct = itemNo.includes('-');
503
+ return (l?.quantity || 0) > 0 && looksProduct;
504
+ });
505
+ })
506
+ .map((cm, idx) => {
507
+ const rawLines = (cm.credit_memo_lines || [])
508
+ .filter((l) => (l?.quantity || 0) > 0)
509
+ .filter((l) => {
510
+ const itemNo = String(l?.item_no || l?.no || '');
511
+ const upper = itemNo.toUpperCase();
512
+ if (upper === 'X DELCHR' || upper === 'REFUND')
513
+ return false;
514
+ return itemNo.includes('-');
515
+ });
516
+ const qtyBySku = new Map();
517
+ rawLines.forEach((l) => {
518
+ const itemNo = String(l?.item_no || l?.no || '');
519
+ const variant = String(l?.variant_code || '');
520
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
521
+ const q = Number(l?.quantity || 0);
522
+ qtyBySku.set(sku, (qtyBySku.get(sku) || 0) + q);
523
+ });
524
+ const skus = Array.from(qtyBySku.keys()).sort();
525
+ const lines = skus.map((sku, i) => ({
526
+ lineNumber: i + 1,
527
+ sku,
528
+ quantity: Math.max(1, qtyBySku.get(sku) || 0),
529
+ returnReasonCode: "R1",
530
+ returnReason: "Return",
531
+ }));
532
+ return {
533
+ erp_id: cm.no || cm.system_id || `${erp_order_id}-RET-${idx + 1}`,
534
+ shipped_at: normalizeDateTime(cm.shipment_date, ordered_at),
535
+ status: "RECEIVED",
536
+ type: "SHIPPED-RETURN",
537
+ shipped_by: "CUSTOMER",
538
+ items: lines,
539
+ amount_net: money(0),
540
+ amount_gross: money(0),
541
+ discount_amount_net: money(0),
542
+ discount_amount_gross: money(0),
543
+ discount_amount_percent: 0,
544
+ };
545
+ });
546
+ const shipments = (mappedShipments.length || returnShipments.length)
547
+ ? [...mappedShipments, ...returnShipments]
548
+ : [];
549
+ const shipping_method = (payload.shipments?.[0]?.shipping_agent_service_code) || null;
550
+ const merchReturnGrossFromCreditMemos = (payload.credit_memos || []).reduce((acc, cm) => {
551
+ const lines = cm?.credit_memo_lines || [];
552
+ let hasQualifying = false;
553
+ const sum = lines.reduce((s, l) => {
554
+ const itemNo = String(l?.item_no || l?.no || "");
555
+ const desc = String(l?.description || "");
556
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
557
+ const typeStr = String(l?.type || "").toLowerCase();
558
+ const isItemish = typeStr.includes('item') || looksProduct;
559
+ const isRefund = itemNo.toUpperCase() === 'REFUND';
560
+ const isDelivery = itemNo.toUpperCase() === 'X DELCHR';
561
+ if ((l?.quantity || 0) > 0 && isItemish && !isRefund && !isDelivery) {
562
+ hasQualifying = true;
563
+ return s + (l?.amount_including_vat || 0);
564
+ }
565
+ return s;
566
+ }, 0);
567
+ const add = sum > 0 ? sum : (hasQualifying ? (cm?.amount_incl_vat || 0) : 0);
568
+ return acc + add;
569
+ }, 0);
570
+ const merchReturnGrossFromReturnSales = (payload.sales || []).reduce((acc, sale) => {
571
+ const docTypeRaw = String(sale?.document_type || sale?.documentType || "");
572
+ const isReturnOrder = docTypeRaw.toLowerCase().includes('return');
573
+ if (!isReturnOrder)
574
+ return acc;
575
+ const lines = sale?.sale_lines || [];
576
+ let hasQualifying = false;
577
+ const sum = lines.reduce((s, l) => {
578
+ const itemNo = String(l?.item_no || l?.no || "");
579
+ const desc = String(l?.description || "");
580
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
581
+ const typeStr = String(l?.type || "").toLowerCase();
582
+ const isItemish = typeStr.includes('item') || looksProduct;
583
+ const isRefund = itemNo.toUpperCase() === 'REFUND';
584
+ const isDelivery = itemNo.toUpperCase() === 'X DELCHR';
585
+ if ((l?.quantity || 0) > 0 && isItemish && !isRefund && !isDelivery) {
586
+ hasQualifying = true;
587
+ return s + (l?.amount_including_vat || 0);
588
+ }
589
+ return s;
590
+ }, 0);
591
+ const add = sum > 0 ? sum : (hasQualifying ? (sale?.amount_incl_vat || sale?.amount_including_vat || 0) : 0);
592
+ return acc + add;
593
+ }, 0);
594
+ const merchReturnGross = merchReturnGrossFromCreditMemos + merchReturnGrossFromReturnSales;
595
+ const hasMerchReturn = merchReturnGross > 0;
596
+ const totalOrderGrossMinor = totalGrossMinor;
597
+ const sourceLineMap = new Map();
598
+ sourceLines.forEach((line) => {
599
+ const lineNo = Number(line.order_line_no || line.line_no || -1);
600
+ if (lineNo > 0) {
601
+ sourceLineMap.set(lineNo, line);
602
+ }
603
+ });
604
+ (sale0?.sale_lines || []).forEach((line) => {
605
+ const lineNo = Number(line.line_no || -1);
606
+ if (lineNo > 0) {
607
+ const existing = sourceLineMap.get(lineNo);
608
+ if (!existing || (!existing.amount_including_vat && !existing.amount_incl_vat)) {
609
+ sourceLineMap.set(lineNo, {
610
+ ...line,
611
+ order_line_no: line.line_no,
612
+ amount_including_vat: line.amount_including_vat,
613
+ amount_incl_vat: line.amount_including_vat,
614
+ });
615
+ }
616
+ }
617
+ });
618
+ const sourceLineBySku = new Map();
619
+ sourceLines.forEach((line) => {
620
+ if (line.type === "Item") {
621
+ const itemNo = String(line.no || "");
622
+ const variant = String(line.variant_code || "");
623
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
624
+ if (!sourceLineBySku.has(sku)) {
625
+ sourceLineBySku.set(sku, line);
626
+ }
627
+ }
628
+ });
629
+ (sale0?.sale_lines || []).forEach((line) => {
630
+ if (line.type === "Item") {
631
+ const itemNo = String(line.no || "");
632
+ const variant = String(line.variant_code || "");
633
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
634
+ const existing = sourceLineBySku.get(sku);
635
+ if (!existing || (!existing.amount_including_vat && !existing.amount_incl_vat)) {
636
+ sourceLineBySku.set(sku, {
637
+ ...line,
638
+ order_line_no: line.line_no,
639
+ amount_including_vat: line.amount_including_vat,
640
+ amount_incl_vat: line.amount_including_vat,
641
+ });
642
+ }
643
+ }
644
+ });
645
+ const shippedGrossDecimal = (payload.shipments || []).reduce((acc, s) => {
646
+ if (s.amount_incl_vat != null && s.amount_incl_vat > 0) {
647
+ return acc + (s.amount_incl_vat || 0);
648
+ }
649
+ const lineAmounts = (s.shipment_lines || []).reduce((lineAcc, l) => {
650
+ const itemNo = String(l?.item_no || l?.no || "").toUpperCase();
651
+ if (itemNo === 'X DELCHR')
652
+ return lineAcc;
653
+ const orderLineNo = Number(l?.order_line_no || -1);
654
+ let sourceLine = orderLineNo > 0 ? sourceLineMap.get(orderLineNo) : null;
655
+ if (!sourceLine) {
656
+ const variant = String(l?.variant_code || "");
657
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
658
+ sourceLine = sourceLineBySku.get(sku);
659
+ }
660
+ if (sourceLine) {
661
+ const sourceQty = Number(sourceLine.quantity || 0);
662
+ const sourceGross = Number(sourceLine.amount_including_vat || sourceLine.amount_incl_vat || 0);
663
+ const shippedQty = Number(l?.quantity || 0);
664
+ if (sourceQty > 0 && sourceGross > 0) {
665
+ const unitPrice = sourceGross / sourceQty;
666
+ return lineAcc + (unitPrice * shippedQty);
667
+ }
668
+ }
669
+ return lineAcc + (l?.amount_including_vat || l?.amount_incl_vat || 0);
670
+ }, 0);
671
+ return acc + lineAmounts;
672
+ }, 0);
673
+ const shippedGrossMinor = toMinorUnits(shippedGrossDecimal);
674
+ let status = "PROCESSED";
675
+ if (hasMerchReturn) {
676
+ const totalOrderGrossDecimal = totalOrderGrossMinor / 100;
677
+ status = totalOrderGrossDecimal > 0 && merchReturnGross >= totalOrderGrossDecimal ? "RETURNED" : "PARTIALLY-RETURNED";
678
+ }
679
+ else if (shippedGrossMinor > 0 && totalOrderGrossMinor > 0) {
680
+ status = shippedGrossMinor >= totalOrderGrossMinor ? "SHIPPED" : "PARTIALLY-SHIPPED";
681
+ }
682
+ const sfcc_order_id = (sale0?.created_by === "STOREFRONT")
683
+ ? (sale0?.no || null)
684
+ : ((invoice0?.created_by === "STOREFRONT") ? (invoice0?.order_no || null) : null);
685
+ const billing_from = invoice0 || sale0 || null;
686
+ const shipping_from = invoice0 || sale0 || null;
687
+ const mapPaymentMethod = (code, card) => {
688
+ const c = String(code || '').toUpperCase();
689
+ if (/(GVOUCHER|VOUCHER|GIFT|EGIFT)/.test(c) || String(card?.service_type || '').toUpperCase().includes('VOUCHER'))
690
+ return 'GIFT-CARD';
691
+ if (c.includes('ADYEN') && !card?.card_number)
692
+ return 'APPLE-PAY';
693
+ if (c.includes('APPLE') || String(card?.service_type || '').toUpperCase().includes('APPLE'))
694
+ return 'APPLE-PAY';
695
+ if (card?.transaction_id || card?.card_number)
696
+ return 'CREDIT-CARD';
697
+ return 'OTHER';
698
+ };
699
+ const journeyFromCreatedBy = (createdBy) => {
700
+ const v = String(createdBy || '').toUpperCase();
701
+ if (v === 'SITOO')
702
+ return 'POS';
703
+ if (v === 'STOREFRONT')
704
+ return 'CHECKOUT';
705
+ if (v === 'CENTRA')
706
+ return 'CHECKOUT';
707
+ return 'SYSTEM';
708
+ };
709
+ const cardPays = (payload.card_payments || []).map((c) => ({
710
+ created_at: c.created_at,
711
+ amount: c.amount,
712
+ type: 'Payment',
713
+ payment_method_code: String(c.service_type || ''),
714
+ transaction_id: c.transaction_id,
715
+ card_number: c.card_number,
716
+ psp_reference: c.psp_reference,
717
+ created_by: invoice0?.created_by || sale0?.created_by,
718
+ }));
719
+ const normalPays = (payload.payments || []).map((p) => ({
720
+ created_at: p.created_at,
721
+ amount: p.amount,
722
+ type: p.type,
723
+ payment_method_code: p.payment_method_code,
724
+ transaction_id: p.ledger_entry_no ? String(p.ledger_entry_no) : undefined,
725
+ card_number: undefined,
726
+ psp_reference: p.psp_reference,
727
+ created_by: p.created_by || invoice0?.created_by || sale0?.created_by,
728
+ }));
729
+ const flat = [...cardPays, ...normalPays];
730
+ const groupsMap = new Map();
731
+ flat.forEach((p, idx) => {
732
+ const isRefund = String(p.type || '').toLowerCase() === 'refund';
733
+ const logicalType = isRefund ? 'REFUND' : 'CHARGE';
734
+ const keyBase = p.transaction_id || `${erp_order_id}-${logicalType}-${idx + 1}`;
735
+ const key = `${logicalType}:${keyBase}`;
736
+ const g = groupsMap.get(key) || { entries: [], type: logicalType, key };
737
+ g.entries.push(p);
738
+ groupsMap.set(key, g);
739
+ });
740
+ const payments = Array.from(groupsMap.values()).map((g, i) => {
741
+ const created_at = g.entries
742
+ .map(e => e.created_at)
743
+ .filter(Boolean)
744
+ .map(d => new Date(d).toISOString())
745
+ .sort()[0] || ordered_at;
746
+ const amount = Math.max(...g.entries.map(e => Number(e.amount || 0)), 0);
747
+ const any = g.entries[0] || {};
748
+ const pm = mapPaymentMethod(any.payment_method_code, any);
749
+ const transaction_id = (any.transaction_id) || `${erp_order_id}-PAY-${i + 1}`;
750
+ const psp_reference = any.psp_reference || transaction_id;
751
+ const created_by = 'CUSTOMER';
752
+ const journey_label = journeyFromCreatedBy(invoice0?.created_by || sale0?.created_by);
753
+ return {
754
+ type: g.type,
755
+ created_at,
756
+ payment_method: pm,
757
+ transaction_id,
758
+ card_number: any.card_number || null,
759
+ card_holder: null,
760
+ card_token: null,
761
+ expiration_month: null,
762
+ expiration_year: null,
763
+ journey_label,
764
+ psp_reference,
765
+ card_brand: null,
766
+ status: 'CAPTURED',
767
+ amount: money(amount),
768
+ created_by,
769
+ };
770
+ });
771
+ const shipmentsWithItems = shipments.filter((s) => s.items && s.items.length > 0);
772
+ shipmentsWithItems.forEach((shipment) => {
773
+ let shipmentNetMinor = 0;
774
+ let shipmentGrossMinor = 0;
775
+ let shipmentDiscountNetMinor = 0;
776
+ let shipmentDiscountGrossMinor = 0;
777
+ let maxDiscountPercent = 0;
778
+ (shipment.items || []).forEach((shipItem) => {
779
+ const sku = shipItem.sku;
780
+ const shipQty = Number(shipItem.quantity || 0);
781
+ const matchingItems = itemsList.filter((item) => item.sku === sku);
782
+ let remainingQty = shipQty;
783
+ for (const item of matchingItems) {
784
+ if (remainingQty <= 0)
785
+ break;
786
+ const itemQty = Number(item.quantity || 0);
787
+ if (itemQty > 0) {
788
+ const takeQty = Math.min(remainingQty, itemQty);
789
+ const ratio = takeQty / itemQty;
790
+ shipmentNetMinor += item.amount_net.value * ratio;
791
+ shipmentGrossMinor += item.amount_gross.value * ratio;
792
+ shipmentDiscountNetMinor += item.discount_amount_net.value * ratio;
793
+ shipmentDiscountGrossMinor += item.discount_amount_gross.value * ratio;
794
+ maxDiscountPercent = Math.max(maxDiscountPercent, item.discount_amount_percent || 0);
795
+ remainingQty -= takeQty;
796
+ }
797
+ }
798
+ });
799
+ shipment.amount_net = moneyFromMinor(shipmentNetMinor);
800
+ shipment.amount_gross = moneyFromMinor(shipmentGrossMinor);
801
+ shipment.discount_amount_net = moneyFromMinor(shipmentDiscountNetMinor);
802
+ shipment.discount_amount_gross = moneyFromMinor(shipmentDiscountGrossMinor);
803
+ shipment.discount_amount_percent = maxDiscountPercent;
804
+ });
805
+ let totalDiscountNetMinor = 0;
806
+ let totalDiscountGrossMinor = 0;
807
+ let maxTotalDiscountPercent = 0;
808
+ itemsList.forEach((item) => {
809
+ totalDiscountNetMinor += item.discount_amount_net.value;
810
+ totalDiscountGrossMinor += item.discount_amount_gross.value;
811
+ maxTotalDiscountPercent = Math.max(maxTotalDiscountPercent, item.discount_amount_percent || 0);
812
+ });
813
+ total.discount_amount_net = moneyFromMinor(totalDiscountNetMinor);
814
+ total.discount_amount_gross = moneyFromMinor(totalDiscountGrossMinor);
815
+ total.discount_amount_percent = maxTotalDiscountPercent;
816
+ net_total.discount_amount_net = moneyFromMinor(totalDiscountNetMinor);
817
+ net_total.discount_amount_gross = moneyFromMinor(totalDiscountGrossMinor);
818
+ net_total.discount_amount_percent = maxTotalDiscountPercent;
819
+ const result = {
820
+ status,
821
+ erp_order_id,
822
+ centra_order_id: null,
823
+ sfcc_order_id,
824
+ globale_order_id: (() => {
825
+ const v = (invoice0?.globale_order_id ?? sale0?.globale_order_id ?? null);
826
+ if (typeof v !== 'string')
827
+ return v;
828
+ const s = v.trim();
829
+ return s.length > 0 ? s : null;
830
+ })(),
831
+ sitoo_order_id: null,
832
+ system_created_by,
833
+ ordered_at,
834
+ is_gift,
835
+ is_pos: created_by_raw === "SITOO",
836
+ billing_address: billing_from ? (() => {
837
+ const billToName = billing_from.bill_to_name || "";
838
+ const firstName = billing_from.bill_to_first_name || (billToName ? billToName.split(' ')[0] : "");
839
+ const lastName = billing_from.bill_to_surname || (billToName ? billToName.split(' ').slice(1).join(' ') : "");
840
+ return {
841
+ first_name: firstName,
842
+ last_name: lastName,
843
+ address1: billing_from.bill_to_address || "",
844
+ address2: billing_from.bill_to_address_2 || null,
845
+ city: billing_from.bill_to_city || "",
846
+ post_code: billing_from.bill_to_post_code || null,
847
+ country_code: billing_from.bill_to_country_region_code || "",
848
+ phone: billing_from.sell_to_phone_no || null,
849
+ created_at: (typeof billing_from.system_created_at === 'string' && billing_from.system_created_at) || undefined,
850
+ };
851
+ })() : null,
852
+ shipping_address: shipping_from ? (() => {
853
+ const shipToName = shipping_from.ship_to_name || "";
854
+ const firstName = shipping_from.ship_to_first_name || (shipToName ? shipToName.split(' ')[0] : "");
855
+ const lastName = shipping_from.ship_to_surname || (shipToName ? shipToName.split(' ').slice(1).join(' ') : "");
856
+ return {
857
+ first_name: firstName,
858
+ last_name: lastName,
859
+ address1: shipping_from.ship_to_address || "",
860
+ address2: shipping_from.ship_to_address_2 || null,
861
+ city: shipping_from.ship_to_city || "",
862
+ post_code: shipping_from.ship_to_post_code || null,
863
+ country_code: shipping_from.ship_to_country_region_code || "",
864
+ phone: shipping_from.ship_to_phone_no || null,
865
+ created_at: (typeof shipping_from.system_created_at === 'string' && shipping_from.system_created_at) || undefined,
866
+ };
867
+ })() : null,
868
+ customer: (() => {
869
+ const normalizeEmailOrNull = (v) => {
870
+ const s = String(v || "").trim().toLowerCase();
871
+ if (!s)
872
+ return null;
873
+ return /.+@.+\..+/.test(s) ? s : null;
874
+ };
875
+ const c = payload.customer;
876
+ if (!c)
877
+ return undefined;
878
+ const mapped = {
879
+ first_name: c.first_name || "",
880
+ last_name: c.surname || "",
881
+ email: normalizeEmailOrNull(c.email),
882
+ };
883
+ if (c.no || payload.customer_no)
884
+ mapped.bc_customer_id = String(c.no || payload.customer_no);
885
+ const buildAddr = (src) => src ? {
886
+ first_name: src.bill_to_first_name || src.ship_to_first_name || "",
887
+ last_name: src.bill_to_surname || src.ship_to_surname || "",
888
+ address1: (src.bill_to_address || src.ship_to_address || ""),
889
+ address2: (src.bill_to_address_2 || src.ship_to_address_2 || null),
890
+ city: (src.bill_to_city || src.ship_to_city || ""),
891
+ post_code: (src.bill_to_post_code || src.ship_to_post_code || null),
892
+ country_code: (src.bill_to_country_region_code || src.ship_to_country_region_code || ""),
893
+ phone: (src.sell_to_phone_no || src.ship_to_phone_no || null),
894
+ created_at: (typeof src.system_created_at === 'string' && src.system_created_at) || undefined,
895
+ } : null;
896
+ const custBilling = buildAddr(billing_from);
897
+ const custShipping = buildAddr(shipping_from);
898
+ const addresses = [custBilling, custShipping].filter(Boolean);
899
+ if (addresses.length > 0)
900
+ mapped.addresses = addresses;
901
+ if (custShipping)
902
+ mapped.default_shipping_address = custShipping;
903
+ const addrPhone = (custShipping?.phone || custBilling?.phone || null);
904
+ const custPhone = (typeof c.phone_no === 'string' && c.phone_no.trim().length > 0) ? c.phone_no : null;
905
+ mapped.phone = custPhone || addrPhone || null;
906
+ const chosenAddr = custShipping || custBilling;
907
+ const custCreatedAt = (typeof c.system_created_at === 'string' && c.system_created_at) || null;
908
+ const addrCreatedAt = (chosenAddr && typeof chosenAddr.created_at === 'string') ? chosenAddr.created_at : null;
909
+ if (custCreatedAt)
910
+ mapped.registered_at = custCreatedAt;
911
+ else if (addrCreatedAt)
912
+ mapped.registered_at = addrCreatedAt;
913
+ return mapped;
914
+ })(),
915
+ items: itemsList,
916
+ total,
917
+ return_total,
918
+ net_total,
919
+ shipping_method,
920
+ payments,
921
+ };
922
+ if (shipmentsWithItems.length > 0) {
923
+ result.shipments = shipmentsWithItems;
924
+ }
925
+ return result;
926
+ }
927
+ function validateOrder(order) {
928
+ const log = { log: () => { }, error: () => { } };
929
+ (0, validate_1.default)(order, order_schema_json_1.default, { log });
930
+ }
931
+ class BCOrderHelper extends runtime_1.default {
932
+ constructor(opts) {
933
+ super(opts);
934
+ }
935
+ transformMasterOrder(payload) {
936
+ return transformMasterOrder(payload);
937
+ }
938
+ validateOrder(order) {
939
+ return validateOrder(order);
940
+ }
941
+ }
942
+ exports.BCOrderHelper = BCOrderHelper;
943
+ exports.default = BCOrderHelper;