@shushed/helpers 0.0.203-bug-erp-770-20251208112219 → 0.0.203-bug-erp-770-20251208155429

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 +1275 -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 -113321
@@ -0,0 +1,1275 @@
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
+ if (Math.abs(amount) > Number.MAX_SAFE_INTEGER / 100) {
18
+ return Math.round(Number((amount * 100).toPrecision(15)));
19
+ }
20
+ return Math.round(amount * 100);
21
+ }
22
+ function money(value) {
23
+ const v = toMinorUnits(value);
24
+ return {
25
+ value: v,
26
+ currency: GBP,
27
+ decimal_places: 2,
28
+ lcy_value: v,
29
+ lcy_currency: GBP,
30
+ lcy_decimal_places: 2,
31
+ };
32
+ }
33
+ function moneyFromMinor(minor) {
34
+ return {
35
+ value: Math.round(minor),
36
+ currency: GBP,
37
+ decimal_places: 2,
38
+ lcy_value: Math.round(minor),
39
+ lcy_currency: GBP,
40
+ lcy_decimal_places: 2,
41
+ };
42
+ }
43
+ function buildLineGrouping(payload) {
44
+ const group = {};
45
+ const makeKey = (orderNo, lineNo) => `${orderNo}:${lineNo}`;
46
+ (payload.sales || []).forEach((sale) => {
47
+ const orderNo = String(sale?.no || sale?.document_no || payload.no || "");
48
+ (sale.sale_lines || []).forEach((l) => {
49
+ if (String(l?.type || '').toLowerCase() !== 'item')
50
+ return;
51
+ const lineNo = Number(l?.line_no || 0);
52
+ if (!orderNo || !lineNo)
53
+ return;
54
+ const key = makeKey(orderNo, lineNo);
55
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
56
+ entry.sale = { document_no: orderNo };
57
+ group[key] = entry;
58
+ });
59
+ });
60
+ (payload.invoices || []).forEach((inv) => {
61
+ const documentNo = String(inv?.no || inv?.document_no || "");
62
+ (inv.invoice_lines || []).forEach((l) => {
63
+ if (String(l?.type || '').toLowerCase() !== 'item')
64
+ return;
65
+ const orderNo = String(l?.order_no || inv?.order_no || payload.no || "");
66
+ const lineNo = Number(l?.order_line_no || l?.line_no || 0);
67
+ if (!orderNo || !lineNo)
68
+ return;
69
+ const key = makeKey(orderNo, lineNo);
70
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
71
+ entry.invoice = { document_no: documentNo || orderNo };
72
+ group[key] = entry;
73
+ });
74
+ });
75
+ (payload.shipments || []).forEach((sh) => {
76
+ const documentNo = String(sh?.no || sh?.document_no || "");
77
+ (sh.shipment_lines || []).forEach((l) => {
78
+ const orderNo = String(l?.order_no || payload.no || "");
79
+ const lineNo = Number(l?.order_line_no || l?.line_no || 0);
80
+ if (!orderNo || !lineNo)
81
+ return;
82
+ const key = makeKey(orderNo, lineNo);
83
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
84
+ entry.shipment = { document_no: documentNo || orderNo };
85
+ group[key] = entry;
86
+ });
87
+ });
88
+ (payload.credit_memos || []).forEach((cm) => {
89
+ const documentNo = String(cm?.no || cm?.document_no || "");
90
+ (cm.credit_memo_lines || []).forEach((l) => {
91
+ const orderNo = String(l?.order_no || payload.no || "");
92
+ const lineNo = Number(l?.order_line_no || l?.line_no || 0);
93
+ if (!orderNo || !lineNo)
94
+ return;
95
+ const key = makeKey(orderNo, lineNo);
96
+ const entry = group[key] || { order_no: orderNo, order_line_no: lineNo };
97
+ entry.credit_memo = { document_no: documentNo || orderNo };
98
+ group[key] = entry;
99
+ });
100
+ });
101
+ return group;
102
+ }
103
+ function transformMasterOrder(payload) {
104
+ const erp_order_id = payload.no || payload.system_id || "";
105
+ const sale0 = Array.isArray(payload.sales) && payload.sales.length > 0 ? payload.sales[0] : undefined;
106
+ const invoice0 = Array.isArray(payload.invoices) && payload.invoices.length > 0 ? payload.invoices[0] : undefined;
107
+ const normalizeDateForSort = (dateStr) => {
108
+ if (!dateStr || typeof dateStr !== 'string')
109
+ return '';
110
+ if (dateStr.includes('T'))
111
+ return dateStr;
112
+ if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr))
113
+ return `${dateStr}T00:00:00Z`;
114
+ try {
115
+ const date = new Date(dateStr);
116
+ if (!isNaN(date.getTime()))
117
+ return date.toISOString();
118
+ }
119
+ catch {
120
+ }
121
+ return dateStr;
122
+ };
123
+ const ordered_at_candidates = [];
124
+ if (sale0?.system_created_at)
125
+ ordered_at_candidates.push(normalizeDateForSort(String(sale0.system_created_at)));
126
+ if (Array.isArray(payload.invoices) && payload.invoices.length > 0) {
127
+ const invDates = payload.invoices
128
+ .map((i) => i.system_created_at)
129
+ .filter(Boolean)
130
+ .map((d) => normalizeDateForSort(String(d)));
131
+ ordered_at_candidates.push(...invDates);
132
+ }
133
+ if (payload.ordered_at)
134
+ ordered_at_candidates.push(normalizeDateForSort(String(payload.ordered_at)));
135
+ if (payload.created_at)
136
+ ordered_at_candidates.push(normalizeDateForSort(String(payload.created_at)));
137
+ const validDates = ordered_at_candidates.filter(d => d.length > 0);
138
+ const orderedAtRaw = validDates.length > 0
139
+ ? validDates.sort()[0]
140
+ : new Date().toISOString();
141
+ let ordered_at;
142
+ try {
143
+ const date = new Date(orderedAtRaw);
144
+ if (isNaN(date.getTime())) {
145
+ ordered_at = new Date().toISOString();
146
+ }
147
+ else {
148
+ ordered_at = date.toISOString();
149
+ }
150
+ }
151
+ catch {
152
+ ordered_at = new Date().toISOString();
153
+ }
154
+ const created_by_raw = sale0?.created_by ?? invoice0?.created_by ?? "";
155
+ const system_created_by = created_by_raw === "SITOO" ? "POS" : created_by_raw === "STOREFRONT" ? "ECOMMERCE" : "SYSTEM";
156
+ const is_gift = Boolean((sale0?.gift_message && String(sale0?.gift_message).trim().length > 0) ||
157
+ (payload.invoices?.some((i) => (i.gift_message || "").trim().length > 0)));
158
+ const invoiceLinesForReturn = payload.invoices?.flatMap((i) => i.invoice_lines || []) || [];
159
+ const salesLinesFallbackForReturn = (sale0?.sale_lines || []);
160
+ const sourceLinesForReturn = invoiceLinesForReturn.length > 0 ? invoiceLinesForReturn : salesLinesFallbackForReturn;
161
+ const skuByDescription = {};
162
+ sourceLinesForReturn.forEach((line) => {
163
+ if ((line?.type || "") !== "Item")
164
+ return;
165
+ const itemNo = String(line?.no || "");
166
+ const variant = String(line?.variant_code || "");
167
+ const desc = String(line?.description || "");
168
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
169
+ if (desc)
170
+ skuByDescription[desc] = sku;
171
+ });
172
+ const isItemish = (type, itemNo, desc) => {
173
+ const t = String(type || '').toLowerCase();
174
+ return t.includes('item') || itemNo.includes('-') || desc.includes(' - ');
175
+ };
176
+ const returnedQtyBySku = {};
177
+ (payload.credit_memos || []).forEach((cm) => {
178
+ (cm.credit_memo_lines || []).forEach((l) => {
179
+ const itemNo = String(l?.item_no || l?.no || '');
180
+ const desc = String(l?.description || '');
181
+ if (itemNo.toUpperCase() === 'X DELCHR' || itemNo.toUpperCase() === 'REFUND')
182
+ return;
183
+ if ((l?.quantity || 0) <= 0)
184
+ return;
185
+ const typeStr = String(l?.type || '').toLowerCase();
186
+ const isTypeItem = typeStr.includes('item');
187
+ if (isTypeItem) {
188
+ const variant = String(l?.variant_code || '');
189
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
190
+ returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
191
+ }
192
+ else if (desc && skuByDescription[desc]) {
193
+ const sku = skuByDescription[desc];
194
+ returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
195
+ }
196
+ });
197
+ });
198
+ (payload.sales || []).forEach((sale) => {
199
+ const docTypeRaw = String(sale?.document_type || sale?.documentType || '');
200
+ if (!docTypeRaw.toLowerCase().includes('return'))
201
+ return;
202
+ (sale.sale_lines || []).forEach((l) => {
203
+ const itemNo = String(l?.item_no || l?.no || '');
204
+ const desc = String(l?.description || '');
205
+ if (itemNo.toUpperCase() === 'X DELCHR' || itemNo.toUpperCase() === 'REFUND')
206
+ return;
207
+ if ((l?.quantity || 0) <= 0)
208
+ return;
209
+ if (!isItemish(l?.type, itemNo, desc))
210
+ return;
211
+ const variant = String(l?.variant_code || '');
212
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
213
+ returnedQtyBySku[sku] = (returnedQtyBySku[sku] || 0) + (l.quantity || 0);
214
+ });
215
+ });
216
+ const invoiceLines = payload.invoices?.flatMap((i) => i.invoice_lines || []) || [];
217
+ const salesLinesFallback = (sale0?.sale_lines || []).map((l) => ({
218
+ type: l.type || "Item",
219
+ no: l.no,
220
+ variant_code: l.variant_code,
221
+ quantity: l.quantity,
222
+ amount: l.amount,
223
+ amount_including_vat: l.amount_including_vat,
224
+ price_update_reason: l.price_update_reason,
225
+ salesforce_promotion_id: l.salesforce_promotion_id,
226
+ line_discount_amount: l.line_discount_amount,
227
+ line_discount_percent: l.line_discount_percent,
228
+ unit_cost_lcy: l.unit_cost_lcy,
229
+ unit_price: l.unit_price,
230
+ vat_percent: l.vat_percent,
231
+ order_line_no: l.line_no,
232
+ }));
233
+ const sourceLines = invoiceLines.length > 0 ? invoiceLines : salesLinesFallback;
234
+ const headerPricesInclVat = invoiceLines.length > 0
235
+ ? Boolean(invoice0?.prices_including_vat)
236
+ : Boolean(sale0?.prices_including_vat);
237
+ const shippedQtyBySku = {};
238
+ (payload.shipments || []).forEach((s) => {
239
+ (s.shipment_lines || []).forEach((l) => {
240
+ const itemNo = String(l?.item_no || l?.no || "");
241
+ if (itemNo.toUpperCase() === 'X DELCHR')
242
+ return;
243
+ const desc = String(l?.description || '');
244
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
245
+ const qty = Number(l?.quantity || 0);
246
+ if (!looksProduct)
247
+ return;
248
+ if (qty <= 0)
249
+ return;
250
+ const variant = String(l?.variant_code || "");
251
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
252
+ shippedQtyBySku[sku] = (shippedQtyBySku[sku] || 0) + qty;
253
+ });
254
+ });
255
+ const shippedRemainingBySku = { ...shippedQtyBySku };
256
+ const returnedTotalBySkuCapped = {};
257
+ Object.keys(returnedQtyBySku).forEach((k) => {
258
+ const totalReturned = Number(returnedQtyBySku[k] || 0);
259
+ const totalShipped = Number(shippedQtyBySku[k] || 0);
260
+ returnedTotalBySkuCapped[k] = totalShipped ? Math.min(totalReturned, totalShipped) : totalReturned;
261
+ });
262
+ const returnedRemainingBySku = { ...returnedTotalBySkuCapped };
263
+ const itemsList = [];
264
+ sourceLines
265
+ .filter((line) => line.type === "Item")
266
+ .forEach((line) => {
267
+ const itemNo = line.no || "";
268
+ const variant = line.variant_code || "";
269
+ const quantity = Number(line.quantity || 0);
270
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
271
+ const parts = itemNo.split("-");
272
+ const style_id = parts.length >= 2 && parts[0] ? parts[0] : null;
273
+ const colour_id = parts.length >= 2 && parts[1] ? parts[1] : null;
274
+ const product_id = (() => {
275
+ const s = String(itemNo || "");
276
+ if (!s)
277
+ return null;
278
+ const parts = s.split("-");
279
+ return parts.length >= 2 ? `${parts[0]}-${parts[1]}` : s;
280
+ })();
281
+ const netTotal = Number(line.amount || 0);
282
+ const grossTotal = Number(line.amount_including_vat || 0);
283
+ const unitPriceRaw = Number(line.unit_price || 0);
284
+ const vatPercent = Number(line.vat_percent || 0);
285
+ let vatRate = 0;
286
+ if (vatPercent > 0) {
287
+ vatRate = vatPercent / 100;
288
+ }
289
+ else if (netTotal > 0 && grossTotal > 0) {
290
+ vatRate = Math.max(0, (grossTotal - netTotal) / netTotal);
291
+ }
292
+ let unitNet = 0;
293
+ let unitGross = 0;
294
+ if (unitPriceRaw > 0) {
295
+ if (headerPricesInclVat) {
296
+ unitGross = unitPriceRaw;
297
+ unitNet = vatRate > 0 ? (unitGross / (1 + vatRate)) : unitGross;
298
+ }
299
+ else {
300
+ unitNet = unitPriceRaw;
301
+ unitGross = vatRate > 0 ? (unitNet * (1 + vatRate)) : unitNet;
302
+ }
303
+ }
304
+ else {
305
+ unitNet = quantity > 0
306
+ ? (netTotal > 0
307
+ ? netTotal / quantity
308
+ : (grossTotal > 0 && vatRate > 0 ? (grossTotal / (1 + vatRate)) / quantity : 0))
309
+ : 0;
310
+ unitGross = quantity > 0
311
+ ? (grossTotal > 0
312
+ ? grossTotal / quantity
313
+ : (netTotal > 0 && vatRate > 0 ? (netTotal * (1 + vatRate)) / quantity : 0))
314
+ : 0;
315
+ }
316
+ const discountCode = (line.salesforce_promotion_id && line.salesforce_promotion_id.trim().length > 0)
317
+ ? line.salesforce_promotion_id.trim()
318
+ : null;
319
+ let unit_price_status = "rrp";
320
+ const reason = (line.price_update_reason || "").toUpperCase();
321
+ if (reason === "PERM")
322
+ unit_price_status = "perm";
323
+ else if (reason === "RRP")
324
+ unit_price_status = "rrp";
325
+ else if (reason === "POS")
326
+ unit_price_status = "pos";
327
+ const discountPercent = Number(line.line_discount_percent || 0);
328
+ const discountAmountRaw = Number(line.line_discount_amount || 0);
329
+ let discountNet = 0;
330
+ let discountGross = 0;
331
+ if (discountAmountRaw > 0) {
332
+ if (headerPricesInclVat) {
333
+ discountGross = discountAmountRaw;
334
+ discountNet = vatRate > 0 ? (discountGross / (1 + vatRate)) : discountGross;
335
+ }
336
+ else {
337
+ discountNet = discountAmountRaw;
338
+ discountGross = vatRate > 0 ? (discountNet * (1 + vatRate)) : discountNet;
339
+ }
340
+ }
341
+ else if (discountPercent > 0) {
342
+ if (netTotal > 0)
343
+ discountNet = (netTotal * discountPercent) / 100;
344
+ if (grossTotal > 0)
345
+ discountGross = (grossTotal * discountPercent) / 100;
346
+ if (grossTotal === 0 && discountNet > 0 && vatRate > 0)
347
+ discountGross = discountNet * (1 + vatRate);
348
+ if (netTotal === 0 && discountGross > 0 && vatRate > 0)
349
+ discountNet = discountGross / (1 + vatRate);
350
+ }
351
+ const take = Math.min(shippedRemainingBySku[sku] || 0, quantity);
352
+ const remaining = quantity - take;
353
+ const baseFields = {
354
+ sku,
355
+ linked_style_id: null,
356
+ colour_id,
357
+ style_id: (style_id || null),
358
+ unit_price_status,
359
+ unit_price_net: money(unitNet),
360
+ unit_price_gross: money(unitGross),
361
+ cost_net: money(line.unit_cost_lcy || 0),
362
+ size_name: (variant || undefined),
363
+ preorder_date: null,
364
+ discount_code: discountCode,
365
+ order_line_no: line.order_line_no || null,
366
+ product_id,
367
+ };
368
+ const pushItem = (qty, returnedQtyForLine) => {
369
+ itemsList.push({
370
+ ...baseFields,
371
+ quantity: qty,
372
+ returned_quantity: Math.max(0, Number(returnedQtyForLine || 0)),
373
+ amount_net: money(unitNet * qty),
374
+ amount_gross: money(unitGross * qty),
375
+ discount_amount_net: money(discountNet * (qty / Math.max(1, quantity))),
376
+ discount_amount_gross: money(discountGross * (qty / Math.max(1, quantity))),
377
+ discount_amount_percent: line.line_discount_percent || 0,
378
+ });
379
+ };
380
+ if (take > 0) {
381
+ const retForShipped = Math.min(Math.max(0, returnedRemainingBySku[sku] || 0), take);
382
+ pushItem(take, retForShipped);
383
+ shippedRemainingBySku[sku] = Math.max(0, (shippedRemainingBySku[sku] || 0) - take);
384
+ if (retForShipped > 0) {
385
+ returnedRemainingBySku[sku] = Math.max(0, (returnedRemainingBySku[sku] || 0) - retForShipped);
386
+ }
387
+ }
388
+ if (remaining > 0) {
389
+ pushItem(remaining, 0);
390
+ }
391
+ });
392
+ const itemsMap = {};
393
+ itemsList.forEach((it) => {
394
+ if (!itemsMap[it.sku])
395
+ itemsMap[it.sku] = [];
396
+ itemsMap[it.sku].push(it);
397
+ });
398
+ const invoicedLineNos = new Set((payload.invoices || []).flatMap((inv) => (inv?.invoice_lines || []).map((l) => Number(l?.order_line_no || -1))));
399
+ const isDeliveryItem = (line) => {
400
+ const desc = String(line?.description || '').trim().toLowerCase();
401
+ return desc === 'delivery';
402
+ };
403
+ let invoicesNetMinor = 0;
404
+ let invoicesGrossMinor = 0;
405
+ (payload.invoices || []).forEach((inv) => {
406
+ (inv.invoice_lines || []).forEach((line) => {
407
+ if (!isDeliveryItem(line)) {
408
+ invoicesNetMinor += toMinorUnits(Number(line?.amount || line?.amount_excl_vat || 0));
409
+ invoicesGrossMinor += toMinorUnits(Number(line?.amount_including_vat || line?.amount_incl_vat || 0));
410
+ }
411
+ });
412
+ });
413
+ if (invoicesGrossMinor === 0 && (payload.invoices || []).length > 0) {
414
+ invoicesNetMinor = toMinorUnits((payload.invoices || []).reduce((acc, inv) => acc + (inv.amount_excl_vat || 0), 0));
415
+ invoicesGrossMinor = toMinorUnits((payload.invoices || []).reduce((acc, inv) => acc + (inv.amount_incl_vat || 0), 0));
416
+ }
417
+ if (invoicesGrossMinor === 0 && invoicedLineNos.size > 0 && sale0?.sale_lines) {
418
+ const invoicedSaleLines = (sale0?.sale_lines || []).filter((l) => {
419
+ if (isDeliveryItem(l))
420
+ return false;
421
+ if (String(l?.type || '').toLowerCase() !== 'item')
422
+ return false;
423
+ const lineNo = Number(l?.line_no || -1);
424
+ return invoicedLineNos.has(lineNo);
425
+ });
426
+ invoicesNetMinor = toMinorUnits(invoicedSaleLines.reduce((acc, l) => acc + (Number(l?.amount || 0)), 0));
427
+ invoicesGrossMinor = toMinorUnits(invoicedSaleLines.reduce((acc, l) => acc + (Number(l?.amount_including_vat || 0)), 0));
428
+ }
429
+ let nonInvSalesNetMinor = 0;
430
+ let nonInvSalesGrossMinor = 0;
431
+ if (sale0?.sale_lines && sale0.sale_lines.length > 0) {
432
+ const allSaleLines = (sale0.sale_lines || []).filter((l) => {
433
+ if (isDeliveryItem(l))
434
+ return false;
435
+ if (String(l?.type || '').toLowerCase() !== 'item')
436
+ return false;
437
+ return true;
438
+ });
439
+ const totalSaleNetMinor = toMinorUnits(allSaleLines.reduce((acc, l) => acc + (Number(l?.amount || 0)), 0));
440
+ const totalSaleGrossMinor = toMinorUnits(allSaleLines.reduce((acc, l) => acc + (Number(l?.amount_including_vat || 0)), 0));
441
+ if (invoicesGrossMinor > 0) {
442
+ nonInvSalesNetMinor = Math.max(0, totalSaleNetMinor - invoicesNetMinor);
443
+ nonInvSalesGrossMinor = Math.max(0, totalSaleGrossMinor - invoicesGrossMinor);
444
+ }
445
+ else {
446
+ nonInvSalesNetMinor = totalSaleNetMinor;
447
+ nonInvSalesGrossMinor = totalSaleGrossMinor;
448
+ }
449
+ }
450
+ else if (sale0 && (sale0.amount_excl_vat || sale0.amount_incl_vat)) {
451
+ const saleNetMinor = toMinorUnits(sale0.amount_excl_vat || 0);
452
+ const saleGrossMinor = toMinorUnits(sale0.amount_incl_vat || 0);
453
+ if (invoicesGrossMinor > 0) {
454
+ nonInvSalesNetMinor = Math.max(0, saleNetMinor - invoicesNetMinor);
455
+ nonInvSalesGrossMinor = Math.max(0, saleGrossMinor - invoicesGrossMinor);
456
+ }
457
+ else {
458
+ nonInvSalesNetMinor = saleNetMinor;
459
+ nonInvSalesGrossMinor = saleGrossMinor;
460
+ }
461
+ }
462
+ else {
463
+ const nonInvoicedSales = (sale0?.sale_lines || []).filter((l) => {
464
+ if (isDeliveryItem(l))
465
+ return false;
466
+ if (String(l?.type || '').toLowerCase() !== 'item')
467
+ return false;
468
+ const lineNo = Number(l?.line_no || -1);
469
+ return !invoicedLineNos.has(lineNo);
470
+ });
471
+ nonInvSalesNetMinor = toMinorUnits(nonInvoicedSales.reduce((acc, l) => acc + (Number(l?.amount || 0)), 0));
472
+ nonInvSalesGrossMinor = toMinorUnits(nonInvoicedSales.reduce((acc, l) => acc + (Number(l?.amount_including_vat || 0)), 0));
473
+ }
474
+ const returnsNetMinor = toMinorUnits((payload.credit_memos || []).reduce((acc, cm) => acc + (cm.amount_excl_vat || 0), 0));
475
+ const returnsGrossMinor = toMinorUnits((payload.credit_memos || []).reduce((acc, cm) => acc + (cm.amount_incl_vat || 0), 0));
476
+ const totalNetMinor = invoicesNetMinor + nonInvSalesNetMinor;
477
+ const totalGrossMinor = invoicesGrossMinor + nonInvSalesGrossMinor;
478
+ const total = {
479
+ amount_net: moneyFromMinor(totalNetMinor),
480
+ amount_gross: moneyFromMinor(totalGrossMinor),
481
+ discount_amount_net: money(0),
482
+ discount_amount_gross: money(0),
483
+ discount_amount_percent: 0,
484
+ };
485
+ const return_total = (payload.credit_memos && payload.credit_memos.length > 0)
486
+ ? {
487
+ amount_net: moneyFromMinor(returnsNetMinor),
488
+ amount_gross: moneyFromMinor(returnsGrossMinor),
489
+ discount_amount_net: money(0),
490
+ discount_amount_gross: money(0),
491
+ discount_amount_percent: 0,
492
+ }
493
+ : undefined;
494
+ const net_total = {
495
+ amount_net: moneyFromMinor(Math.max(0, totalNetMinor - returnsNetMinor)),
496
+ amount_gross: moneyFromMinor(Math.max(0, totalGrossMinor - returnsGrossMinor)),
497
+ discount_amount_net: money(0),
498
+ discount_amount_gross: money(0),
499
+ discount_amount_percent: 0,
500
+ };
501
+ const normalizeDateTime = (dateMaybe, fallbackIso) => {
502
+ const source = (typeof dateMaybe === "string" && dateMaybe.length > 0)
503
+ ? dateMaybe
504
+ : fallbackIso;
505
+ const d = new Date(source.includes("T") ? source : `${source}T00:00:00Z`);
506
+ return isNaN(d.getTime()) ? new Date().toISOString() : d.toISOString();
507
+ };
508
+ const mappedShipments = (payload.shipments || []).map((s) => {
509
+ const rawLines = (s.shipment_lines || [])
510
+ .filter((l) => (l?.quantity ?? 0) > 0)
511
+ .filter((l) => String(l?.item_no || '').toUpperCase() !== 'X DELCHR')
512
+ .filter((l) => {
513
+ const itemNo = String(l?.item_no || '');
514
+ const desc = String(l?.description || '');
515
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
516
+ return looksProduct;
517
+ });
518
+ const qtyBySku = new Map();
519
+ rawLines.forEach((l) => {
520
+ const itemNo = String(l?.item_no || '');
521
+ const variant = String(l?.variant_code || '');
522
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
523
+ const q = Number(l?.quantity || 0);
524
+ qtyBySku.set(sku, (qtyBySku.get(sku) || 0) + q);
525
+ });
526
+ const skus = Array.from(qtyBySku.keys()).sort();
527
+ const shipmentLines = skus.map((sku, idx) => ({
528
+ lineNumber: idx + 1,
529
+ sku,
530
+ quantity: Math.max(1, qtyBySku.get(sku) || 0),
531
+ }));
532
+ const statusVal = shipmentLines.length > 0 ? "SHIPPED" : "PENDING";
533
+ return {
534
+ erp_id: s.no || s.system_id || "",
535
+ shipped_at: normalizeDateTime(s.shipment_date, ordered_at),
536
+ status: statusVal,
537
+ type: statusVal === "SHIPPED" ? "SHIPPED-OUTBOUND" : undefined,
538
+ shipped_by: "TORQUE",
539
+ items: shipmentLines,
540
+ amount_net: money(0),
541
+ amount_gross: money(0),
542
+ discount_amount_net: money(0),
543
+ discount_amount_gross: money(0),
544
+ discount_amount_percent: 0,
545
+ };
546
+ });
547
+ const returnShipments = (payload.credit_memos || [])
548
+ .filter((cm) => {
549
+ const lines = cm?.credit_memo_lines || [];
550
+ return lines.some((l) => {
551
+ const itemNo = String(l?.item_no || l?.no || "");
552
+ const upper = itemNo.toUpperCase();
553
+ if (upper === 'X DELCHR' || upper === 'REFUND')
554
+ return false;
555
+ const looksProduct = itemNo.includes('-');
556
+ return (l?.quantity || 0) > 0 && looksProduct;
557
+ });
558
+ })
559
+ .map((cm, idx) => {
560
+ const rawLines = (cm.credit_memo_lines || [])
561
+ .filter((l) => (l?.quantity || 0) > 0)
562
+ .filter((l) => {
563
+ const itemNo = String(l?.item_no || l?.no || '');
564
+ const upper = itemNo.toUpperCase();
565
+ if (upper === 'X DELCHR' || upper === 'REFUND')
566
+ return false;
567
+ return itemNo.includes('-');
568
+ });
569
+ const qtyBySku = new Map();
570
+ rawLines.forEach((l) => {
571
+ const itemNo = String(l?.item_no || l?.no || '');
572
+ const variant = String(l?.variant_code || '');
573
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
574
+ const q = Number(l?.quantity || 0);
575
+ qtyBySku.set(sku, (qtyBySku.get(sku) || 0) + q);
576
+ });
577
+ const skus = Array.from(qtyBySku.keys()).sort();
578
+ const lines = skus.map((sku, i) => ({
579
+ lineNumber: i + 1,
580
+ sku,
581
+ quantity: Math.max(1, qtyBySku.get(sku) || 0),
582
+ returnReasonCode: "R1",
583
+ returnReason: "Return",
584
+ }));
585
+ return {
586
+ erp_id: cm.no || cm.system_id || `${erp_order_id}-RET-${idx + 1}`,
587
+ shipped_at: normalizeDateTime(cm.shipment_date, ordered_at),
588
+ status: "RECEIVED",
589
+ type: "SHIPPED-RETURN",
590
+ shipped_by: "CUSTOMER",
591
+ items: lines,
592
+ amount_net: money(0),
593
+ amount_gross: money(0),
594
+ discount_amount_net: money(0),
595
+ discount_amount_gross: money(0),
596
+ discount_amount_percent: 0,
597
+ };
598
+ });
599
+ const shipments = (mappedShipments.length || returnShipments.length)
600
+ ? [...mappedShipments, ...returnShipments]
601
+ : [];
602
+ const shipping_method = (payload.shipments?.[0]?.shipping_agent_service_code) || null;
603
+ const merchReturnGrossFromCreditMemos = (payload.credit_memos || []).reduce((acc, cm) => {
604
+ const lines = cm?.credit_memo_lines || [];
605
+ let hasQualifying = false;
606
+ const sum = lines.reduce((s, l) => {
607
+ const itemNo = String(l?.item_no || l?.no || "");
608
+ const desc = String(l?.description || "");
609
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
610
+ const typeStr = String(l?.type || "").toLowerCase();
611
+ const isItemish = typeStr.includes('item') || looksProduct;
612
+ const isRefund = itemNo.toUpperCase() === 'REFUND';
613
+ if ((l?.quantity || 0) > 0 && isItemish && !isRefund && !isDeliveryItem(l)) {
614
+ hasQualifying = true;
615
+ return s + (l?.amount_including_vat || 0);
616
+ }
617
+ return s;
618
+ }, 0);
619
+ if (!hasQualifying)
620
+ return acc;
621
+ if (cm?.amount_incl_vat != null && cm.amount_incl_vat > 0) {
622
+ return acc + cm.amount_incl_vat;
623
+ }
624
+ return acc + sum;
625
+ }, 0);
626
+ const merchReturnGrossFromReturnSales = (payload.sales || []).reduce((acc, sale) => {
627
+ const docTypeRaw = String(sale?.document_type || sale?.documentType || "");
628
+ const isReturnOrder = docTypeRaw.toLowerCase().includes('return');
629
+ if (!isReturnOrder)
630
+ return acc;
631
+ if (sale?.amount_incl_vat != null && sale.amount_incl_vat > 0) {
632
+ return acc + sale.amount_incl_vat;
633
+ }
634
+ const lines = sale?.sale_lines || [];
635
+ let hasQualifying = false;
636
+ const sum = lines.reduce((s, l) => {
637
+ const itemNo = String(l?.item_no || l?.no || "");
638
+ const desc = String(l?.description || "");
639
+ const looksProduct = itemNo.includes('-') || desc.includes(' - ');
640
+ const typeStr = String(l?.type || "").toLowerCase();
641
+ const isItemish = typeStr.includes('item') || looksProduct;
642
+ const isRefund = itemNo.toUpperCase() === 'REFUND';
643
+ if ((l?.quantity || 0) > 0 && isItemish && !isRefund && !isDeliveryItem(l)) {
644
+ hasQualifying = true;
645
+ return s + (l?.amount_including_vat || 0);
646
+ }
647
+ return s;
648
+ }, 0);
649
+ return acc + (sum > 0 ? sum : (hasQualifying ? (sale?.amount_incl_vat || sale?.amount_including_vat || 0) : 0));
650
+ }, 0);
651
+ const merchReturnGross = merchReturnGrossFromCreditMemos + merchReturnGrossFromReturnSales;
652
+ const hasMerchReturn = merchReturnGross > 0;
653
+ const totalOrderGrossMinor = totalGrossMinor;
654
+ const sourceLineMap = new Map();
655
+ sourceLines.forEach((line) => {
656
+ const lineNo = Number(line.order_line_no || line.line_no || -1);
657
+ if (lineNo > 0) {
658
+ sourceLineMap.set(lineNo, line);
659
+ }
660
+ });
661
+ (sale0?.sale_lines || []).forEach((line) => {
662
+ const lineNo = Number(line.line_no || -1);
663
+ if (lineNo > 0) {
664
+ const existing = sourceLineMap.get(lineNo);
665
+ if (!existing || (!existing.amount_including_vat && !existing.amount_incl_vat)) {
666
+ sourceLineMap.set(lineNo, {
667
+ ...line,
668
+ order_line_no: line.line_no,
669
+ amount_including_vat: line.amount_including_vat,
670
+ amount_incl_vat: line.amount_including_vat,
671
+ });
672
+ }
673
+ }
674
+ });
675
+ const sourceLineBySku = new Map();
676
+ sourceLines.forEach((line) => {
677
+ if (line.type === "Item") {
678
+ const itemNo = String(line.no || "");
679
+ const variant = String(line.variant_code || "");
680
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
681
+ if (!sourceLineBySku.has(sku)) {
682
+ sourceLineBySku.set(sku, line);
683
+ }
684
+ }
685
+ });
686
+ (sale0?.sale_lines || []).forEach((line) => {
687
+ if (line.type === "Item") {
688
+ const itemNo = String(line.no || "");
689
+ const variant = String(line.variant_code || "");
690
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
691
+ const existing = sourceLineBySku.get(sku);
692
+ if (!existing || (!existing.amount_including_vat && !existing.amount_incl_vat)) {
693
+ sourceLineBySku.set(sku, {
694
+ ...line,
695
+ order_line_no: line.line_no,
696
+ amount_including_vat: line.amount_including_vat,
697
+ amount_incl_vat: line.amount_including_vat,
698
+ });
699
+ }
700
+ }
701
+ });
702
+ const shippedGrossDecimal = (payload.shipments || []).reduce((acc, s) => {
703
+ if (s.amount_incl_vat != null && s.amount_incl_vat > 0) {
704
+ return acc + (s.amount_incl_vat || 0);
705
+ }
706
+ const lineAmounts = (s.shipment_lines || []).reduce((lineAcc, l) => {
707
+ if (isDeliveryItem(l))
708
+ return lineAcc;
709
+ const orderLineNo = Number(l?.order_line_no || -1);
710
+ let sourceLine = orderLineNo > 0 ? sourceLineMap.get(orderLineNo) : null;
711
+ if (!sourceLine) {
712
+ const itemNo = String(l?.item_no || l?.no || "").toUpperCase();
713
+ const variant = String(l?.variant_code || "");
714
+ const sku = variant ? `${itemNo}-${variant}` : itemNo;
715
+ sourceLine = sourceLineBySku.get(sku);
716
+ }
717
+ if (sourceLine) {
718
+ const sourceQty = Number(sourceLine.quantity || 0);
719
+ const sourceGross = Number(sourceLine.amount_including_vat || sourceLine.amount_incl_vat || 0);
720
+ const shippedQty = Number(l?.quantity || 0);
721
+ if (sourceQty > 0 && sourceGross > 0) {
722
+ const unitPrice = sourceGross / sourceQty;
723
+ return lineAcc + (unitPrice * shippedQty);
724
+ }
725
+ }
726
+ return lineAcc + (l?.amount_including_vat || l?.amount_incl_vat || 0);
727
+ }, 0);
728
+ return acc + lineAmounts;
729
+ }, 0);
730
+ const shippedGrossMinor = toMinorUnits(shippedGrossDecimal);
731
+ let status = "PROCESSED";
732
+ if (hasMerchReturn) {
733
+ const totalOrderGrossDecimal = totalOrderGrossMinor / 100;
734
+ status = totalOrderGrossDecimal > 0 && merchReturnGross >= totalOrderGrossDecimal ? "RETURNED" : "PARTIALLY-RETURNED";
735
+ }
736
+ else if (shippedGrossMinor > 0 && totalOrderGrossMinor > 0) {
737
+ status = shippedGrossMinor >= totalOrderGrossMinor ? "SHIPPED" : "PARTIALLY-SHIPPED";
738
+ }
739
+ const sfcc_order_id = (sale0?.created_by === "STOREFRONT")
740
+ ? (sale0?.no || null)
741
+ : ((invoice0?.created_by === "STOREFRONT") ? (invoice0?.order_no || null) : null);
742
+ const billing_from = invoice0 || sale0 || null;
743
+ const shipping_from = invoice0 || sale0 || null;
744
+ const mapPaymentMethod = (code, card) => {
745
+ const c = String(code || '').toUpperCase();
746
+ const processorId = String(card?.processor_id || '').toUpperCase();
747
+ const giftCertId = String(card?.gift_certificate_id || '').trim();
748
+ const cardType = String(card?.type || '').trim().toLowerCase();
749
+ if (giftCertId.length > 0)
750
+ return 'GIFT-CARD';
751
+ if (cardType === 'gift certificate')
752
+ return 'GIFT-CARD';
753
+ if (processorId.includes('GIFT_CERTIFICATE') || processorId.includes('GIFT-CERTIFICATE'))
754
+ return 'GIFT-CARD';
755
+ if (/(GVOUCHER|VOUCHER|GIFT|EGIFT)/.test(c))
756
+ return 'GIFT-CARD';
757
+ if (c.includes('APPLE'))
758
+ return 'APPLE-PAY';
759
+ if ((c.includes('PAYPAL') || processorId === 'PAYPAL') && giftCertId.length === 0) {
760
+ return 'PAYPAL';
761
+ }
762
+ if (c.includes('MOTO'))
763
+ return 'MOTO';
764
+ if (c.includes('ADYEN') && cardType === 'credit card' && giftCertId.length === 0) {
765
+ return 'CREDIT-CARD';
766
+ }
767
+ const serviceType = String(card?.service_type || '').toUpperCase();
768
+ if (serviceType.includes('VOUCHER') && giftCertId.length === 0 && processorId !== 'PAYPAL') {
769
+ return 'GIFT-CARD';
770
+ }
771
+ if (card?.card_number)
772
+ return 'CREDIT-CARD';
773
+ return 'OTHER';
774
+ };
775
+ const cardPays = (payload.card_payments || []).map((c) => ({
776
+ created_at: c.created_at,
777
+ amount: c.mount || c.amount,
778
+ type: c.type || 'Payment',
779
+ payment_method_code: String(c.service_type || ''),
780
+ transaction_id: c.transaction_id,
781
+ card_number: c.card_number,
782
+ psp_reference: c.psp_reference,
783
+ gift_certificate_id: c.gift_certificate_id,
784
+ service_type: c.service_type,
785
+ processor_id: c.processor_id,
786
+ created_by: invoice0?.created_by || sale0?.created_by,
787
+ source: 'card_payment',
788
+ order_no: c.order_no,
789
+ captured: c.captured,
790
+ }));
791
+ const normalPays = (payload.payments || []).map((p) => ({
792
+ created_at: p.created_at,
793
+ amount: p.amount,
794
+ type: p.type,
795
+ payment_method_code: p.payment_method_code,
796
+ transaction_id: p.transaction_id,
797
+ card_number: undefined,
798
+ psp_reference: p.psp_reference,
799
+ payment_gateway_token: p.payment_gateway_token,
800
+ payment_number: p.payment_number,
801
+ payment_refund_number: p.payment_refund_number,
802
+ original_payment_refund_id: p.original_payment_refund_id,
803
+ created_by: p.created_by || invoice0?.created_by || sale0?.created_by,
804
+ source: 'payment',
805
+ order_no: p.master_order_no,
806
+ ledger_entry_no: p.ledger_entry_no,
807
+ }));
808
+ const flat = [...cardPays, ...normalPays];
809
+ const groupsMap = new Map();
810
+ flat.forEach((p) => {
811
+ try {
812
+ const isRefund = String(p.type || '').toLowerCase() === 'refund';
813
+ const logicalType = isRefund ? 'REFUND' : 'CHARGE';
814
+ let keyBase;
815
+ const unifiedId = p.transaction_id || p.payment_gateway_token;
816
+ if (unifiedId) {
817
+ keyBase = unifiedId;
818
+ }
819
+ else if (p.payment_number) {
820
+ keyBase = `PN:${p.payment_number}`;
821
+ }
822
+ else if (!isRefund) {
823
+ const paymentType = String(p.type || '').toUpperCase();
824
+ const amount = Number(p.amount || 0);
825
+ const paymentMethod = String(p.payment_method_code || '').toUpperCase().trim();
826
+ const orderNo = p.order_no || erp_order_id;
827
+ if (paymentType === 'CAPTURE' || paymentType === 'AUTHORISATION') {
828
+ keyBase = `CHARGE-${orderNo}-${amount}-${paymentMethod}`;
829
+ }
830
+ else if (p.gift_certificate_id) {
831
+ keyBase = `GIFT:${p.gift_certificate_id}`;
832
+ }
833
+ else {
834
+ const orderNo = p.order_no || erp_order_id;
835
+ const paymentMethod = String(p.payment_method_code || '').toUpperCase().trim();
836
+ keyBase = `${orderNo}-${amount}-${paymentMethod}`;
837
+ }
838
+ }
839
+ else {
840
+ if (p.payment_refund_number) {
841
+ keyBase = `PRN:${p.payment_refund_number}`;
842
+ }
843
+ else {
844
+ const orderNo = p.order_no || erp_order_id;
845
+ const amount = Number(p.amount || 0);
846
+ const paymentMethod = String(p.payment_method_code || '').toUpperCase().trim();
847
+ keyBase = `${orderNo}-${amount}-${paymentMethod}`;
848
+ }
849
+ }
850
+ const key = `${logicalType}:${keyBase}`;
851
+ const g = groupsMap.get(key) || { entries: [], type: logicalType, key };
852
+ g.entries.push(p);
853
+ groupsMap.set(key, g);
854
+ }
855
+ catch (error) {
856
+ console.error(`Error processing payment entry:`, {
857
+ error: error instanceof Error ? error.message : String(error),
858
+ payment_type: p?.type,
859
+ amount: p?.amount,
860
+ order_no: p?.order_no || erp_order_id,
861
+ transaction_id: p?.transaction_id,
862
+ payment_gateway_token: p?.payment_gateway_token,
863
+ });
864
+ }
865
+ });
866
+ const allPaymentEntriesByOrder = new Map();
867
+ flat.forEach(p => {
868
+ const orderNo = p.order_no || erp_order_id;
869
+ const amount = Number(p.amount || 0);
870
+ const key = `${orderNo}-${amount}`;
871
+ if (!allPaymentEntriesByOrder.has(key)) {
872
+ allPaymentEntriesByOrder.set(key, []);
873
+ }
874
+ allPaymentEntriesByOrder.get(key).push(p);
875
+ });
876
+ const cardPaymentsByToken = new Map();
877
+ cardPays.forEach(cp => {
878
+ if (cp.transaction_id) {
879
+ cardPaymentsByToken.set(cp.transaction_id, cp);
880
+ }
881
+ });
882
+ const paymentsByOriginalRefundId = new Map();
883
+ const paymentsByPaymentNumber = new Map();
884
+ const paymentsByPaymentRefundNumber = new Map();
885
+ normalPays.forEach(p => {
886
+ const isRefund = String(p.type || '').toLowerCase() === 'refund';
887
+ if (!isRefund) {
888
+ if (p.original_payment_refund_id) {
889
+ paymentsByOriginalRefundId.set(p.original_payment_refund_id, p);
890
+ }
891
+ if (p.payment_number) {
892
+ paymentsByPaymentNumber.set(p.payment_number, p);
893
+ }
894
+ if (p.payment_refund_number) {
895
+ paymentsByPaymentRefundNumber.set(p.payment_refund_number, p);
896
+ }
897
+ }
898
+ });
899
+ const payments = Array.from(groupsMap.values()).map((g) => {
900
+ const sortedEntries = [...g.entries].sort((a, b) => {
901
+ if (a.source === 'card_payment' && b.source !== 'card_payment')
902
+ return -1;
903
+ if (b.source === 'card_payment' && a.source !== 'card_payment')
904
+ return 1;
905
+ if (a.source === 'payment' && b.source === 'payment') {
906
+ const aType = String(a.type || '').toUpperCase();
907
+ const bType = String(b.type || '').toUpperCase();
908
+ if (aType === 'AUTHORISATION' && bType !== 'AUTHORISATION')
909
+ return -1;
910
+ if (bType === 'AUTHORISATION' && aType !== 'AUTHORISATION')
911
+ return 1;
912
+ if (aType === 'CAPTURE' && bType !== 'CAPTURE' && bType !== 'AUTHORISATION')
913
+ return -1;
914
+ if (bType === 'CAPTURE' && aType !== 'CAPTURE' && aType !== 'AUTHORISATION')
915
+ return 1;
916
+ }
917
+ return 0;
918
+ });
919
+ const created_at = g.entries
920
+ .map(e => e.created_at)
921
+ .filter(Boolean)
922
+ .map(d => new Date(d).toISOString())
923
+ .sort()[0] || ordered_at;
924
+ const amountInclVat = Math.max(...g.entries.map(e => Number(e.amount || 0)), 0);
925
+ const amount = money(amountInclVat);
926
+ const primary = sortedEntries[0] || {};
927
+ const paymentEntryForMethod = sortedEntries.find(e => e.source === 'payment' && e.payment_method_code);
928
+ const paymentMethodCode = paymentEntryForMethod?.payment_method_code || primary.payment_method_code;
929
+ let cardPaymentEntryForMethod = sortedEntries.find(e => e.source === 'card_payment');
930
+ const groupCardData = {
931
+ card_number: cardPaymentEntryForMethod?.card_number || sortedEntries.find(e => e.card_number)?.card_number,
932
+ transaction_id: cardPaymentEntryForMethod?.transaction_id || sortedEntries.find(e => e.transaction_id)?.transaction_id,
933
+ service_type: cardPaymentEntryForMethod?.service_type || sortedEntries.find(e => e.service_type)?.service_type,
934
+ processor_id: cardPaymentEntryForMethod?.processor_id || sortedEntries.find(e => e.processor_id)?.processor_id,
935
+ gift_certificate_id: cardPaymentEntryForMethod?.gift_certificate_id || sortedEntries.find(e => e.gift_certificate_id)?.gift_certificate_id,
936
+ type: cardPaymentEntryForMethod?.type || sortedEntries.find(e => e.type && e.source === 'card_payment')?.type,
937
+ };
938
+ let pm;
939
+ if (cardPaymentEntryForMethod?.type && String(cardPaymentEntryForMethod.type).trim().toLowerCase() === 'apple pay') {
940
+ pm = 'APPLE-PAY';
941
+ }
942
+ else {
943
+ pm = mapPaymentMethod(paymentMethodCode, groupCardData);
944
+ }
945
+ let cardPaymentEntryForTransaction = sortedEntries.find(e => e.source === 'card_payment' && e.transaction_id);
946
+ if (!cardPaymentEntryForTransaction && primary.payment_gateway_token) {
947
+ cardPaymentEntryForTransaction = cardPaymentsByToken.get(primary.payment_gateway_token);
948
+ }
949
+ if (!cardPaymentEntryForTransaction && g.type === 'REFUND') {
950
+ let originalPayment;
951
+ const refundEntryWithPaymentNumber = sortedEntries.find(e => e.payment_number && String(e.payment_number).trim().length > 0);
952
+ if (refundEntryWithPaymentNumber?.payment_number) {
953
+ originalPayment = paymentsByPaymentNumber.get(refundEntryWithPaymentNumber.payment_number);
954
+ }
955
+ if (!originalPayment) {
956
+ const refundEntryWithOriginalId = sortedEntries.find(e => e.original_payment_refund_id);
957
+ if (refundEntryWithOriginalId?.original_payment_refund_id) {
958
+ originalPayment = Array.from(normalPays).find(p => p.ledger_entry_no === refundEntryWithOriginalId.original_payment_refund_id &&
959
+ String(p.type || '').toLowerCase() !== 'refund');
960
+ }
961
+ }
962
+ if (!originalPayment) {
963
+ const refundEntryWithRefundNumber = sortedEntries.find(e => e.payment_refund_number && String(e.payment_refund_number).trim().length > 0);
964
+ if (refundEntryWithRefundNumber?.payment_refund_number) {
965
+ originalPayment = paymentsByPaymentRefundNumber.get(refundEntryWithRefundNumber.payment_refund_number);
966
+ }
967
+ }
968
+ if (originalPayment?.payment_gateway_token) {
969
+ cardPaymentEntryForTransaction = cardPaymentsByToken.get(originalPayment.payment_gateway_token);
970
+ if (!cardPaymentEntryForMethod && cardPaymentEntryForTransaction) {
971
+ cardPaymentEntryForMethod = cardPaymentEntryForTransaction;
972
+ if (cardPaymentEntryForMethod?.type && String(cardPaymentEntryForMethod.type).trim().toLowerCase() === 'apple pay') {
973
+ pm = 'APPLE-PAY';
974
+ }
975
+ else {
976
+ const refundCardData = {
977
+ card_number: cardPaymentEntryForMethod?.card_number,
978
+ transaction_id: cardPaymentEntryForMethod?.transaction_id,
979
+ service_type: cardPaymentEntryForMethod?.service_type,
980
+ processor_id: cardPaymentEntryForMethod?.processor_id,
981
+ gift_certificate_id: cardPaymentEntryForMethod?.gift_certificate_id,
982
+ type: cardPaymentEntryForMethod?.type,
983
+ };
984
+ pm = mapPaymentMethod(paymentMethodCode, refundCardData);
985
+ }
986
+ }
987
+ }
988
+ }
989
+ let transaction_id = null;
990
+ if (g.type === 'REFUND' && !cardPaymentEntryForTransaction && !primary.transaction_id && !primary.payment_gateway_token) {
991
+ let originalPaymentForTransaction;
992
+ const refundEntryWithPaymentNumber = sortedEntries.find(e => e.payment_number && String(e.payment_number).trim().length > 0);
993
+ if (refundEntryWithPaymentNumber?.payment_number) {
994
+ originalPaymentForTransaction = paymentsByPaymentNumber.get(refundEntryWithPaymentNumber.payment_number);
995
+ }
996
+ if (!originalPaymentForTransaction && primary.original_payment_refund_id) {
997
+ originalPaymentForTransaction = Array.from(normalPays).find(p => p.ledger_entry_no === primary.original_payment_refund_id &&
998
+ String(p.type || '').toLowerCase() !== 'refund');
999
+ }
1000
+ if (!originalPaymentForTransaction && primary.payment_refund_number) {
1001
+ const refundEntryWithRefundNumber = sortedEntries.find(e => e.payment_refund_number && String(e.payment_refund_number).trim().length > 0);
1002
+ if (refundEntryWithRefundNumber?.payment_refund_number) {
1003
+ originalPaymentForTransaction = paymentsByPaymentRefundNumber.get(refundEntryWithRefundNumber.payment_refund_number);
1004
+ }
1005
+ }
1006
+ if (originalPaymentForTransaction?.payment_gateway_token) {
1007
+ const originalCardPayment = cardPaymentsByToken.get(originalPaymentForTransaction.payment_gateway_token);
1008
+ transaction_id = originalCardPayment?.transaction_id || null;
1009
+ }
1010
+ }
1011
+ else {
1012
+ transaction_id = cardPaymentEntryForTransaction?.transaction_id || primary.transaction_id || null;
1013
+ }
1014
+ const psp_reference = transaction_id;
1015
+ const paymentCreatedByRaw = invoice0?.created_by || primary.created_by || sale0?.created_by || "";
1016
+ const paymentCreatedByUpper = String(paymentCreatedByRaw).toUpperCase();
1017
+ const isEmail = typeof paymentCreatedByRaw === 'string' && paymentCreatedByRaw.includes('@');
1018
+ const validEnumValues = ['CUSTOMER', 'SYSTEM', 'CENTRA', 'SITOO', 'STOREFRONT', 'MOTO'];
1019
+ const isValidEnum = validEnumValues.includes(paymentCreatedByUpper);
1020
+ const created_by = isEmail
1021
+ ? paymentCreatedByRaw
1022
+ : isValidEnum
1023
+ ? paymentCreatedByUpper
1024
+ : 'MOTO';
1025
+ const journey_label = null;
1026
+ let card_number = sortedEntries.find(e => e.source === 'card_payment' && e.card_number)?.card_number
1027
+ || primary.card_number
1028
+ || null;
1029
+ if (!card_number && g.type === 'REFUND' && cardPaymentEntryForTransaction) {
1030
+ card_number = cardPaymentEntryForTransaction.card_number || null;
1031
+ }
1032
+ let cardPaymentForBrand = sortedEntries.find(e => e.source === 'card_payment' && e.service_type);
1033
+ if (!cardPaymentForBrand && g.type === 'REFUND' && cardPaymentEntryForTransaction) {
1034
+ cardPaymentForBrand = cardPaymentEntryForTransaction;
1035
+ }
1036
+ const card_brand = cardPaymentForBrand?.service_type
1037
+ ? String(cardPaymentForBrand.service_type).trim() || null
1038
+ : null;
1039
+ let status = 'CAPTURED';
1040
+ const isVoucher = pm === 'GIFT-CARD' ||
1041
+ sortedEntries.some(e => e.gift_certificate_id) ||
1042
+ sortedEntries.some(e => /(GVOUCHER|VOUCHER|GIFT|EGIFT)/.test(String(e.payment_method_code || '').toUpperCase())) ||
1043
+ sortedEntries.some(e => String(e.service_type || '').toUpperCase().includes('VOUCHER'));
1044
+ const cardPaymentEntry = sortedEntries.find(e => e.source === 'card_payment');
1045
+ if (isVoucher) {
1046
+ let paymentEntry = g.entries.find(e => e.source === 'payment' &&
1047
+ (String(e.type || '').toUpperCase() === 'PAYMENT' || String(e.type || '').toUpperCase() === 'CAPTURE'));
1048
+ let paymentType = paymentEntry ? String(paymentEntry.type || '').toUpperCase() : '';
1049
+ if (!paymentEntry && g.entries.length > 0) {
1050
+ const firstEntry = g.entries[0];
1051
+ const orderNo = firstEntry.order_no || erp_order_id;
1052
+ const amount = Number(firstEntry.amount || 0);
1053
+ const lookupKey = `${orderNo}-${amount}`;
1054
+ const relatedEntries = allPaymentEntriesByOrder.get(lookupKey) || [];
1055
+ paymentEntry = relatedEntries.find(e => e.source === 'payment' &&
1056
+ (String(e.type || '').toUpperCase() === 'PAYMENT' || String(e.type || '').toUpperCase() === 'CAPTURE'));
1057
+ paymentType = paymentEntry ? String(paymentEntry.type || '').toUpperCase() : '';
1058
+ }
1059
+ if (paymentType === 'PAYMENT' || paymentType === 'CAPTURE') {
1060
+ status = 'CAPTURED';
1061
+ }
1062
+ else {
1063
+ status = 'FAILED';
1064
+ }
1065
+ }
1066
+ else {
1067
+ if (cardPaymentEntry?.captured === true) {
1068
+ status = 'CAPTURED';
1069
+ }
1070
+ else if (cardPaymentEntry?.captured === false) {
1071
+ status = 'FAILED';
1072
+ }
1073
+ else {
1074
+ const paymentType = String(primary.type || '').toUpperCase();
1075
+ if (paymentType === 'CAPTURE' || paymentType === 'PAYMENT') {
1076
+ status = 'CAPTURED';
1077
+ }
1078
+ else {
1079
+ status = 'CAPTURED';
1080
+ }
1081
+ }
1082
+ }
1083
+ return {
1084
+ type: g.type,
1085
+ created_at,
1086
+ payment_method: pm,
1087
+ transaction_id,
1088
+ card_number,
1089
+ card_holder: null,
1090
+ card_token: null,
1091
+ expiration_month: null,
1092
+ expiration_year: null,
1093
+ journey_label,
1094
+ psp_reference,
1095
+ card_brand,
1096
+ status,
1097
+ amount,
1098
+ created_by,
1099
+ };
1100
+ });
1101
+ const shipmentsWithItems = shipments.filter((s) => s.items && s.items.length > 0);
1102
+ shipmentsWithItems.forEach((shipment) => {
1103
+ let shipmentNetMinor = 0;
1104
+ let shipmentGrossMinor = 0;
1105
+ let shipmentDiscountNetMinor = 0;
1106
+ let shipmentDiscountGrossMinor = 0;
1107
+ let maxDiscountPercent = 0;
1108
+ (shipment.items || []).forEach((shipItem) => {
1109
+ const sku = shipItem.sku;
1110
+ const shipQty = Number(shipItem.quantity || 0);
1111
+ const matchingItems = itemsList.filter((item) => item.sku === sku);
1112
+ let remainingQty = shipQty;
1113
+ for (const item of matchingItems) {
1114
+ if (remainingQty <= 0)
1115
+ break;
1116
+ const itemQty = Number(item.quantity || 0);
1117
+ if (itemQty > 0) {
1118
+ const takeQty = Math.min(remainingQty, itemQty);
1119
+ const ratio = takeQty / itemQty;
1120
+ shipmentNetMinor += item.amount_net.value * ratio;
1121
+ shipmentGrossMinor += item.amount_gross.value * ratio;
1122
+ shipmentDiscountNetMinor += item.discount_amount_net.value * ratio;
1123
+ shipmentDiscountGrossMinor += item.discount_amount_gross.value * ratio;
1124
+ maxDiscountPercent = Math.max(maxDiscountPercent, item.discount_amount_percent || 0);
1125
+ remainingQty -= takeQty;
1126
+ }
1127
+ }
1128
+ });
1129
+ shipment.amount_net = moneyFromMinor(shipmentNetMinor);
1130
+ shipment.amount_gross = moneyFromMinor(shipmentGrossMinor);
1131
+ shipment.discount_amount_net = moneyFromMinor(shipmentDiscountNetMinor);
1132
+ shipment.discount_amount_gross = moneyFromMinor(shipmentDiscountGrossMinor);
1133
+ shipment.discount_amount_percent = maxDiscountPercent;
1134
+ });
1135
+ let totalDiscountNetMinor = 0;
1136
+ let totalDiscountGrossMinor = 0;
1137
+ let maxTotalDiscountPercent = 0;
1138
+ itemsList.forEach((item) => {
1139
+ totalDiscountNetMinor += item.discount_amount_net.value;
1140
+ totalDiscountGrossMinor += item.discount_amount_gross.value;
1141
+ maxTotalDiscountPercent = Math.max(maxTotalDiscountPercent, item.discount_amount_percent || 0);
1142
+ });
1143
+ total.discount_amount_net = moneyFromMinor(totalDiscountNetMinor);
1144
+ total.discount_amount_gross = moneyFromMinor(totalDiscountGrossMinor);
1145
+ total.discount_amount_percent = maxTotalDiscountPercent;
1146
+ net_total.discount_amount_net = moneyFromMinor(totalDiscountNetMinor);
1147
+ net_total.discount_amount_gross = moneyFromMinor(totalDiscountGrossMinor);
1148
+ net_total.discount_amount_percent = maxTotalDiscountPercent;
1149
+ const result = {
1150
+ status,
1151
+ erp_order_id,
1152
+ centra_order_id: null,
1153
+ sfcc_order_id,
1154
+ globale_order_id: (() => {
1155
+ const v = (invoice0?.globale_order_id ?? sale0?.globale_order_id ?? null);
1156
+ if (typeof v !== 'string')
1157
+ return v;
1158
+ const s = v.trim();
1159
+ return s.length > 0 ? s : null;
1160
+ })(),
1161
+ sitoo_order_id: null,
1162
+ system_created_by,
1163
+ ordered_at,
1164
+ is_gift,
1165
+ is_pos: created_by_raw === "SITOO",
1166
+ billing_address: billing_from ? (() => {
1167
+ const billToName = billing_from.bill_to_name || "";
1168
+ const firstName = billing_from.bill_to_first_name || (billToName ? billToName.split(' ')[0] : "");
1169
+ const lastName = billing_from.bill_to_surname || (billToName ? billToName.split(' ').slice(1).join(' ') : "");
1170
+ return {
1171
+ first_name: firstName,
1172
+ last_name: lastName,
1173
+ address1: billing_from.bill_to_address || "",
1174
+ address2: billing_from.bill_to_address_2 || null,
1175
+ city: billing_from.bill_to_city || "",
1176
+ post_code: billing_from.bill_to_post_code || null,
1177
+ country_code: billing_from.bill_to_country_region_code || "",
1178
+ phone: billing_from.sell_to_phone_no || null,
1179
+ created_at: (typeof billing_from.system_created_at === 'string' && billing_from.system_created_at) || undefined,
1180
+ };
1181
+ })() : null,
1182
+ shipping_address: shipping_from ? (() => {
1183
+ const shipToName = shipping_from.ship_to_name || "";
1184
+ const firstName = shipping_from.ship_to_first_name || (shipToName ? shipToName.split(' ')[0] : "");
1185
+ const lastName = shipping_from.ship_to_surname || (shipToName ? shipToName.split(' ').slice(1).join(' ') : "");
1186
+ return {
1187
+ first_name: firstName,
1188
+ last_name: lastName,
1189
+ address1: shipping_from.ship_to_address || "",
1190
+ address2: shipping_from.ship_to_address_2 || null,
1191
+ city: shipping_from.ship_to_city || "",
1192
+ post_code: shipping_from.ship_to_post_code || null,
1193
+ country_code: shipping_from.ship_to_country_region_code || "",
1194
+ phone: shipping_from.ship_to_phone_no || null,
1195
+ created_at: (typeof shipping_from.system_created_at === 'string' && shipping_from.system_created_at) || undefined,
1196
+ };
1197
+ })() : null,
1198
+ customer: (() => {
1199
+ const normalizeEmailOrNull = (v) => {
1200
+ const s = String(v || "").trim().toLowerCase();
1201
+ if (!s)
1202
+ return null;
1203
+ return /.+@.+\..+/.test(s) ? s : null;
1204
+ };
1205
+ const c = payload.customer;
1206
+ if (!c)
1207
+ return undefined;
1208
+ const mapped = {
1209
+ first_name: c.first_name || "",
1210
+ last_name: c.surname || "",
1211
+ email: normalizeEmailOrNull(c.email),
1212
+ };
1213
+ if (c.no || payload.customer_no)
1214
+ mapped.bc_customer_id = String(c.no || payload.customer_no);
1215
+ const buildAddr = (src) => src ? {
1216
+ first_name: src.bill_to_first_name || src.ship_to_first_name || "",
1217
+ last_name: src.bill_to_surname || src.ship_to_surname || "",
1218
+ address1: (src.bill_to_address || src.ship_to_address || ""),
1219
+ address2: (src.bill_to_address_2 || src.ship_to_address_2 || null),
1220
+ city: (src.bill_to_city || src.ship_to_city || ""),
1221
+ post_code: (src.bill_to_post_code || src.ship_to_post_code || null),
1222
+ country_code: (src.bill_to_country_region_code || src.ship_to_country_region_code || ""),
1223
+ phone: (src.sell_to_phone_no || src.ship_to_phone_no || null),
1224
+ created_at: (typeof src.system_created_at === 'string' && src.system_created_at) || undefined,
1225
+ } : null;
1226
+ const custBilling = buildAddr(billing_from);
1227
+ const custShipping = buildAddr(shipping_from);
1228
+ const addresses = [custBilling, custShipping].filter(Boolean);
1229
+ if (addresses.length > 0)
1230
+ mapped.addresses = addresses;
1231
+ if (custShipping)
1232
+ mapped.default_shipping_address = custShipping;
1233
+ const addrPhone = (custShipping?.phone || custBilling?.phone || null);
1234
+ const custPhone = (typeof c.phone_no === 'string' && c.phone_no.trim().length > 0) ? c.phone_no : null;
1235
+ mapped.phone = custPhone || addrPhone || null;
1236
+ const chosenAddr = custShipping || custBilling;
1237
+ const custCreatedAt = (typeof c.system_created_at === 'string' && c.system_created_at) || null;
1238
+ const addrCreatedAt = (chosenAddr && typeof chosenAddr.created_at === 'string') ? chosenAddr.created_at : null;
1239
+ if (custCreatedAt)
1240
+ mapped.registered_at = custCreatedAt;
1241
+ else if (addrCreatedAt)
1242
+ mapped.registered_at = addrCreatedAt;
1243
+ return mapped;
1244
+ })(),
1245
+ items: itemsList,
1246
+ total,
1247
+ return_total,
1248
+ net_total,
1249
+ shipping_method,
1250
+ };
1251
+ if (payments.length > 0) {
1252
+ result.payments = payments;
1253
+ }
1254
+ if (shipmentsWithItems.length > 0) {
1255
+ result.shipments = shipmentsWithItems;
1256
+ }
1257
+ return result;
1258
+ }
1259
+ function validateOrder(order) {
1260
+ const log = { log: () => { }, error: () => { } };
1261
+ (0, validate_1.default)(order, order_schema_json_1.default, { log });
1262
+ }
1263
+ class BCOrderHelper extends runtime_1.default {
1264
+ constructor(opts) {
1265
+ super(opts);
1266
+ }
1267
+ transformMasterOrder(payload) {
1268
+ return transformMasterOrder(payload);
1269
+ }
1270
+ validateOrder(order) {
1271
+ return validateOrder(order);
1272
+ }
1273
+ }
1274
+ exports.BCOrderHelper = BCOrderHelper;
1275
+ exports.default = BCOrderHelper;