addio-admin-sdk 1.7.144 → 1.7.145

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 (575) hide show
  1. package/.babelrc +17 -17
  2. package/.claude/settings.local.json +7 -0
  3. package/.env +14 -0
  4. package/.env.dev +14 -14
  5. package/.github/workflows/run_unit_test.yaml +48 -48
  6. package/addio-sdk-doc.md +1473 -1473
  7. package/changelog.md +564 -564
  8. package/dist/Interfaces/Address/index.d.ts +21 -21
  9. package/dist/Interfaces/Address/index.js +16 -16
  10. package/dist/Interfaces/Algolia/index.d.ts +177 -177
  11. package/dist/Interfaces/Algolia/index.js +2 -2
  12. package/dist/Interfaces/Attachement/index.d.ts +5 -5
  13. package/dist/Interfaces/Attachement/index.js +2 -2
  14. package/dist/Interfaces/Attribute/index.d.ts +53 -53
  15. package/dist/Interfaces/Attribute/index.js +10 -10
  16. package/dist/Interfaces/BGJob/index.d.ts +56 -56
  17. package/dist/Interfaces/BGJob/index.js +25 -25
  18. package/dist/Interfaces/BaseClass/index.d.ts +8 -8
  19. package/dist/Interfaces/BaseClass/index.js +2 -2
  20. package/dist/Interfaces/Blog/IBlogArticle.d.ts +18 -18
  21. package/dist/Interfaces/Blog/IBlogArticle.js +2 -2
  22. package/dist/Interfaces/Blog/IBlogAuthor.d.ts +7 -7
  23. package/dist/Interfaces/Blog/IBlogAuthor.js +2 -2
  24. package/dist/Interfaces/Blog/IBlogCategory.d.ts +9 -9
  25. package/dist/Interfaces/Blog/IBlogCategory.js +2 -2
  26. package/dist/Interfaces/Blog/IBlogComment.d.ts +13 -13
  27. package/dist/Interfaces/Blog/IBlogComment.js +2 -2
  28. package/dist/Interfaces/Blog/IBlogKeywords.d.ts +9 -9
  29. package/dist/Interfaces/Blog/IBlogKeywords.js +2 -2
  30. package/dist/Interfaces/Booking/index.d.ts +74 -74
  31. package/dist/Interfaces/Booking/index.js +17 -17
  32. package/dist/Interfaces/Brand/index.d.ts +15 -15
  33. package/dist/Interfaces/Brand/index.js +2 -2
  34. package/dist/Interfaces/CMS/index.d.ts +28 -28
  35. package/dist/Interfaces/CMS/index.js +5 -5
  36. package/dist/Interfaces/Cart/IElavonPayload.d.ts +93 -93
  37. package/dist/Interfaces/Cart/IElavonPayload.js +17 -17
  38. package/dist/Interfaces/Cart/IPandaPayload.d.ts +64 -64
  39. package/dist/Interfaces/Cart/IPandaPayload.js +18 -18
  40. package/dist/Interfaces/Cart/IPaymentCard.d.ts +22 -22
  41. package/dist/Interfaces/Cart/IPaymentCard.js +44 -44
  42. package/dist/Interfaces/Cart/IPaypalPayload.d.ts +9 -9
  43. package/dist/Interfaces/Cart/IPaypalPayload.js +2 -2
  44. package/dist/Interfaces/Cart/IPaysafePayload.d.ts +72 -72
  45. package/dist/Interfaces/Cart/IPaysafePayload.js +2 -2
  46. package/dist/Interfaces/Cart/IStripePayload.d.ts +66 -66
  47. package/dist/Interfaces/Cart/IStripePayload.js +2 -2
  48. package/dist/Interfaces/Cart/index.d.ts +444 -444
  49. package/dist/Interfaces/Cart/index.js +197 -197
  50. package/dist/Interfaces/CartReservedQuantities/index.d.ts +10 -10
  51. package/dist/Interfaces/CartReservedQuantities/index.js +2 -2
  52. package/dist/Interfaces/CashDrawers/index.d.ts +37 -37
  53. package/dist/Interfaces/CashDrawers/index.js +19 -19
  54. package/dist/Interfaces/Catalogue/index.d.ts +68 -68
  55. package/dist/Interfaces/Catalogue/index.js +37 -37
  56. package/dist/Interfaces/Category/index.d.ts +33 -33
  57. package/dist/Interfaces/Category/index.js +2 -2
  58. package/dist/Interfaces/Chart/index.d.ts +11 -11
  59. package/dist/Interfaces/Chart/index.js +2 -2
  60. package/dist/Interfaces/Class/index.d.ts +8 -8
  61. package/dist/Interfaces/Class/index.js +2 -2
  62. package/dist/Interfaces/Consent/index.d.ts +6 -6
  63. package/dist/Interfaces/Consent/index.js +2 -2
  64. package/dist/Interfaces/Context/IContextProps.d.ts +4 -4
  65. package/dist/Interfaces/Context/IContextProps.js +2 -2
  66. package/dist/Interfaces/Context/IContextState.d.ts +15 -15
  67. package/dist/Interfaces/Context/IContextState.js +2 -2
  68. package/dist/Interfaces/Customer/ICustomerBadge.d.ts +2 -2
  69. package/dist/Interfaces/Customer/ICustomerBadge.js +2 -2
  70. package/dist/Interfaces/Customer/ICustomerRating.d.ts +10 -10
  71. package/dist/Interfaces/Customer/ICustomerRating.js +2 -2
  72. package/dist/Interfaces/Customer/IStoreCredit.d.ts +13 -13
  73. package/dist/Interfaces/Customer/IStoreCredit.js +2 -2
  74. package/dist/Interfaces/Customer/index.d.ts +104 -104
  75. package/dist/Interfaces/Customer/index.js +148 -148
  76. package/dist/Interfaces/Declination/index.d.ts +117 -117
  77. package/dist/Interfaces/Declination/index.js +66 -66
  78. package/dist/Interfaces/Document/index.d.ts +8 -8
  79. package/dist/Interfaces/Document/index.js +2 -2
  80. package/dist/Interfaces/Elastic/index.d.ts +89 -89
  81. package/dist/Interfaces/Elastic/index.js +2 -2
  82. package/dist/Interfaces/Email/CustomGR/I3DPrintEmail.d.ts +11 -11
  83. package/dist/Interfaces/Email/CustomGR/I3DPrintEmail.js +2 -2
  84. package/dist/Interfaces/Email/CustomGR/IBorrowToolsEmail.d.ts +15 -15
  85. package/dist/Interfaces/Email/CustomGR/IBorrowToolsEmail.js +2 -2
  86. package/dist/Interfaces/Email/CustomGR/IPickupMaterialsEmail.d.ts +12 -12
  87. package/dist/Interfaces/Email/CustomGR/IPickupMaterialsEmail.js +2 -2
  88. package/dist/Interfaces/Email/CustomGR/IPreMeetingFormEmail.d.ts +36 -36
  89. package/dist/Interfaces/Email/CustomGR/IPreMeetingFormEmail.js +2 -2
  90. package/dist/Interfaces/Email/CustomGR/ISponsorRequestEmail.d.ts +12 -12
  91. package/dist/Interfaces/Email/CustomGR/ISponsorRequestEmail.js +2 -2
  92. package/dist/Interfaces/Email/CustomGR/ITransportEmail.d.ts +12 -12
  93. package/dist/Interfaces/Email/CustomGR/ITransportEmail.js +2 -2
  94. package/dist/Interfaces/Email/CustomGR/ITransportQuoteEmail.d.ts +12 -12
  95. package/dist/Interfaces/Email/CustomGR/ITransportQuoteEmail.js +2 -2
  96. package/dist/Interfaces/Email/CustomGR/IVegetalsEmail.d.ts +16 -16
  97. package/dist/Interfaces/Email/CustomGR/IVegetalsEmail.js +2 -2
  98. package/dist/Interfaces/Email/CustomGR/IWishlistEmail.d.ts +15 -15
  99. package/dist/Interfaces/Email/CustomGR/IWishlistEmail.js +2 -2
  100. package/dist/Interfaces/Email/IAbandonnedCartEmail.d.ts +29 -29
  101. package/dist/Interfaces/Email/IAbandonnedCartEmail.js +2 -2
  102. package/dist/Interfaces/Email/IAccountConfirmationEmail.d.ts +22 -22
  103. package/dist/Interfaces/Email/IAccountConfirmationEmail.js +2 -2
  104. package/dist/Interfaces/Email/IApplicationEmail.d.ts +19 -19
  105. package/dist/Interfaces/Email/IApplicationEmail.js +2 -2
  106. package/dist/Interfaces/Email/IBackInStockEmail.d.ts +21 -21
  107. package/dist/Interfaces/Email/IBackInStockEmail.js +2 -2
  108. package/dist/Interfaces/Email/IContactEmail.d.ts +20 -20
  109. package/dist/Interfaces/Email/IContactEmail.js +2 -2
  110. package/dist/Interfaces/Email/ICustomerBookingAdminEmail.d.ts +15 -15
  111. package/dist/Interfaces/Email/ICustomerBookingAdminEmail.js +2 -2
  112. package/dist/Interfaces/Email/ICustomerBookingEmail.d.ts +14 -14
  113. package/dist/Interfaces/Email/ICustomerBookingEmail.js +2 -2
  114. package/dist/Interfaces/Email/IEmail.d.ts +20 -20
  115. package/dist/Interfaces/Email/IEmail.js +60 -60
  116. package/dist/Interfaces/Email/IOrderConfirmationEmail.d.ts +47 -47
  117. package/dist/Interfaces/Email/IOrderConfirmationEmail.js +2 -2
  118. package/dist/Interfaces/Email/IPasswordResetEmail.d.ts +17 -17
  119. package/dist/Interfaces/Email/IPasswordResetEmail.js +2 -2
  120. package/dist/Interfaces/Email/IPhotoShootEmail.d.ts +14 -14
  121. package/dist/Interfaces/Email/IPhotoShootEmail.js +2 -2
  122. package/dist/Interfaces/Email/IPickupConfirmation.d.ts +23 -23
  123. package/dist/Interfaces/Email/IPickupConfirmation.js +2 -2
  124. package/dist/Interfaces/Email/IShippingConfirmation.d.ts +23 -23
  125. package/dist/Interfaces/Email/IShippingConfirmation.js +2 -2
  126. package/dist/Interfaces/Email/IWelcomeEmail.d.ts +19 -19
  127. package/dist/Interfaces/Email/IWelcomeEmail.js +2 -2
  128. package/dist/Interfaces/ExportSchema/index.d.ts +7 -7
  129. package/dist/Interfaces/ExportSchema/index.js +2 -2
  130. package/dist/Interfaces/ExternalService/BaseExternalService.d.ts +12 -12
  131. package/dist/Interfaces/ExternalService/BaseExternalService.js +2 -2
  132. package/dist/Interfaces/ExternalService/ExternalProductsService.d.ts +4 -4
  133. package/dist/Interfaces/ExternalService/ExternalProductsService.js +2 -2
  134. package/dist/Interfaces/ExternalService/index.d.ts +9 -9
  135. package/dist/Interfaces/ExternalService/index.js +2 -2
  136. package/dist/Interfaces/FirstOrderTracking/index.d.ts +5 -5
  137. package/dist/Interfaces/FirstOrderTracking/index.js +2 -2
  138. package/dist/Interfaces/G2/index.d.ts +556 -556
  139. package/dist/Interfaces/G2/index.js +38 -38
  140. package/dist/Interfaces/Indexed/Product/IIndexedLastSavedProduct.d.ts +20 -20
  141. package/dist/Interfaces/Indexed/Product/IIndexedLastSavedProduct.js +2 -2
  142. package/dist/Interfaces/Indexed/Product/index.d.ts +105 -105
  143. package/dist/Interfaces/Indexed/Product/index.js +253 -253
  144. package/dist/Interfaces/Inventory/index.d.ts +19 -19
  145. package/dist/Interfaces/Inventory/index.js +8 -8
  146. package/dist/Interfaces/Invoice/index.d.ts +4 -4
  147. package/dist/Interfaces/Invoice/index.js +2 -2
  148. package/dist/Interfaces/MarketplacePublication/MarketplaceOrderData.d.ts +3 -3
  149. package/dist/Interfaces/MarketplacePublication/MarketplaceOrderData.js +2 -2
  150. package/dist/Interfaces/MarketplacePublication/index.d.ts +23 -23
  151. package/dist/Interfaces/MarketplacePublication/index.js +22 -22
  152. package/dist/Interfaces/Menu/index.d.ts +40 -40
  153. package/dist/Interfaces/Menu/index.js +16 -16
  154. package/dist/Interfaces/Note/index.d.ts +10 -10
  155. package/dist/Interfaces/Note/index.js +7 -7
  156. package/dist/Interfaces/Operations/ICreatedBy.d.ts +6 -6
  157. package/dist/Interfaces/Operations/ICreatedBy.js +2 -2
  158. package/dist/Interfaces/Operations/IUpdate.d.ts +5 -5
  159. package/dist/Interfaces/Operations/IUpdate.js +2 -2
  160. package/dist/Interfaces/Order/index.d.ts +4 -4
  161. package/dist/Interfaces/Order/index.js +2 -2
  162. package/dist/Interfaces/Org/IRelUser.d.ts +9 -9
  163. package/dist/Interfaces/Org/IRelUser.js +2 -2
  164. package/dist/Interfaces/Org/index.d.ts +29 -29
  165. package/dist/Interfaces/Org/index.js +12 -12
  166. package/dist/Interfaces/Payment/index.d.ts +26 -26
  167. package/dist/Interfaces/Payment/index.js +14 -14
  168. package/dist/Interfaces/Product/IAttributeFamily.d.ts +6 -6
  169. package/dist/Interfaces/Product/IAttributeFamily.js +2 -2
  170. package/dist/Interfaces/Product/IImportProduct.d.ts +42 -42
  171. package/dist/Interfaces/Product/IImportProduct.js +882 -882
  172. package/dist/Interfaces/Product/IInventoryItem.d.ts +74 -74
  173. package/dist/Interfaces/Product/IInventoryItem.js +38 -38
  174. package/dist/Interfaces/Product/IPricing.d.ts +177 -177
  175. package/dist/Interfaces/Product/IPricing.js +180 -180
  176. package/dist/Interfaces/Product/index.d.ts +138 -138
  177. package/dist/Interfaces/Product/index.js +64 -64
  178. package/dist/Interfaces/ProductAttribute/index.d.ts +11 -11
  179. package/dist/Interfaces/ProductAttribute/index.js +2 -2
  180. package/dist/Interfaces/PromiseToPurchase/BankType.d.ts +41 -41
  181. package/dist/Interfaces/PromiseToPurchase/BankType.js +41 -41
  182. package/dist/Interfaces/PromiseToPurchase/IIndexedBankUsed.d.ts +33 -33
  183. package/dist/Interfaces/PromiseToPurchase/IIndexedBankUsed.js +15 -15
  184. package/dist/Interfaces/PromiseToPurchase/IIndexedCustomerPromiseToPurchase.d.ts +19 -19
  185. package/dist/Interfaces/PromiseToPurchase/IIndexedCustomerPromiseToPurchase.js +2 -2
  186. package/dist/Interfaces/PromiseToPurchase/index.d.ts +50 -50
  187. package/dist/Interfaces/PromiseToPurchase/index.js +13 -13
  188. package/dist/Interfaces/PurchaseOrder/index.d.ts +17 -17
  189. package/dist/Interfaces/PurchaseOrder/index.js +2 -2
  190. package/dist/Interfaces/Query/IBrandQueryOptions.d.ts +11 -11
  191. package/dist/Interfaces/Query/IBrandQueryOptions.js +2 -2
  192. package/dist/Interfaces/Query/ICategoryQueryOptions.d.ts +11 -11
  193. package/dist/Interfaces/Query/ICategoryQueryOptions.js +2 -2
  194. package/dist/Interfaces/Query/IProductQueryOptions.d.ts +16 -16
  195. package/dist/Interfaces/Query/IProductQueryOptions.js +2 -2
  196. package/dist/Interfaces/Quote/index.d.ts +5 -5
  197. package/dist/Interfaces/Quote/index.js +2 -2
  198. package/dist/Interfaces/Refunds/index.d.ts +106 -106
  199. package/dist/Interfaces/Refunds/index.js +2 -2
  200. package/dist/Interfaces/Rules/IDiscountRule.d.ts +155 -155
  201. package/dist/Interfaces/Rules/IDiscountRule.js +114 -114
  202. package/dist/Interfaces/Schedule/index.d.ts +48 -48
  203. package/dist/Interfaces/Schedule/index.js +2 -2
  204. package/dist/Interfaces/Services/IAddServiceResponse.d.ts +4 -4
  205. package/dist/Interfaces/Services/IAddServiceResponse.js +2 -2
  206. package/dist/Interfaces/Services/IService.d.ts +16 -16
  207. package/dist/Interfaces/Services/IService.js +2 -2
  208. package/dist/Interfaces/Services/IServiceSecret.d.ts +8 -8
  209. package/dist/Interfaces/Services/IServiceSecret.js +2 -2
  210. package/dist/Interfaces/Shipping/Shipstation/carriers.d.ts +10 -10
  211. package/dist/Interfaces/Shipping/Shipstation/carriers.js +2 -2
  212. package/dist/Interfaces/Shipping/Shipstation/order.d.ts +227 -227
  213. package/dist/Interfaces/Shipping/Shipstation/order.js +2 -2
  214. package/dist/Interfaces/Shipping/Shipstation/quote.d.ts +31 -31
  215. package/dist/Interfaces/Shipping/Shipstation/quote.js +2 -2
  216. package/dist/Interfaces/Shipping/Shiptime/order.d.ts +54 -54
  217. package/dist/Interfaces/Shipping/Shiptime/order.js +71 -71
  218. package/dist/Interfaces/Shipping/Shiptime/quote.d.ts +111 -111
  219. package/dist/Interfaces/Shipping/Shiptime/quote.js +2 -2
  220. package/dist/Interfaces/Slider/GR.d.ts +114 -114
  221. package/dist/Interfaces/Slider/GR.js +271 -271
  222. package/dist/Interfaces/Slider/index.d.ts +30 -30
  223. package/dist/Interfaces/Slider/index.js +2 -2
  224. package/dist/Interfaces/Space/IExternalService.d.ts +53 -53
  225. package/dist/Interfaces/Space/IExternalService.js +44 -44
  226. package/dist/Interfaces/Space/IMember.d.ts +16 -16
  227. package/dist/Interfaces/Space/IMember.js +9 -9
  228. package/dist/Interfaces/Space/index.d.ts +407 -405
  229. package/dist/Interfaces/Space/index.js +174 -174
  230. package/dist/Interfaces/Space/index.js.map +1 -1
  231. package/dist/Interfaces/Specials/gr.d.ts +61 -61
  232. package/dist/Interfaces/Specials/gr.js +2 -2
  233. package/dist/Interfaces/StockNotification/index.d.ts +7 -7
  234. package/dist/Interfaces/StockNotification/index.js +2 -2
  235. package/dist/Interfaces/Store/index.d.ts +63 -63
  236. package/dist/Interfaces/Store/index.js +27 -27
  237. package/dist/Interfaces/Supplier/ICommand.d.ts +11 -11
  238. package/dist/Interfaces/Supplier/ICommand.js +2 -2
  239. package/dist/Interfaces/Supplier/index.d.ts +36 -36
  240. package/dist/Interfaces/Supplier/index.js +24 -24
  241. package/dist/Interfaces/TCG/index.d.ts +161 -161
  242. package/dist/Interfaces/TCG/index.js +54 -54
  243. package/dist/Interfaces/Tag/index.d.ts +18 -18
  244. package/dist/Interfaces/Tag/index.js +2 -2
  245. package/dist/Interfaces/Tax/index.d.ts +13 -13
  246. package/dist/Interfaces/Tax/index.js +2 -2
  247. package/dist/Interfaces/TransferRequest/index.d.ts +103 -103
  248. package/dist/Interfaces/TransferRequest/index.js +46 -46
  249. package/dist/Interfaces/Translation/index.d.ts +8 -8
  250. package/dist/Interfaces/Translation/index.js +5 -5
  251. package/dist/Interfaces/Update/index.d.ts +10 -10
  252. package/dist/Interfaces/Update/index.js +2 -2
  253. package/dist/Interfaces/User/IUser.d.ts +65 -65
  254. package/dist/Interfaces/User/IUser.js +8 -8
  255. package/dist/Interfaces/Version/index.d.ts +11 -11
  256. package/dist/Interfaces/Version/index.js +2 -2
  257. package/dist/Interfaces/Wishlist/index.d.ts +7 -7
  258. package/dist/Interfaces/Wishlist/index.js +2 -2
  259. package/dist/constants/Interfaces/IBaseApi.d.ts +15 -15
  260. package/dist/constants/Interfaces/IBaseApi.js +2 -2
  261. package/dist/constants/Interfaces/IEndpointResult.d.ts +9 -9
  262. package/dist/constants/Interfaces/IEndpointResult.js +2 -2
  263. package/dist/constants/enums.d.ts +6 -6
  264. package/dist/constants/enums.js +10 -10
  265. package/dist/constants/services.d.ts +2 -2
  266. package/dist/constants/services.js +117 -117
  267. package/dist/constants/version.d.ts +2 -2
  268. package/dist/constants/version.js +5 -5
  269. package/dist/index.d.ts +50 -50
  270. package/dist/index.js +266 -266
  271. package/dist/lib/Attribute/index.d.ts +14 -14
  272. package/dist/lib/Attribute/index.js +186 -186
  273. package/dist/lib/BGJob/index.d.ts +9 -9
  274. package/dist/lib/BGJob/index.js +216 -216
  275. package/dist/lib/BackgroundWorker/index.d.ts +34 -34
  276. package/dist/lib/BackgroundWorker/index.js +59 -59
  277. package/dist/lib/Blog/BlogArticle.d.ts +5 -5
  278. package/dist/lib/Blog/BlogArticle.js +10 -10
  279. package/dist/lib/Blog/BlogAuthor.d.ts +5 -5
  280. package/dist/lib/Blog/BlogAuthor.js +10 -10
  281. package/dist/lib/Blog/BlogCategory.d.ts +5 -5
  282. package/dist/lib/Blog/BlogCategory.js +10 -10
  283. package/dist/lib/Blog/BlogKeyword.d.ts +5 -5
  284. package/dist/lib/Blog/BlogKeyword.js +10 -10
  285. package/dist/lib/Booking/index.d.ts +85 -85
  286. package/dist/lib/Booking/index.js +596 -596
  287. package/dist/lib/Brand/index.d.ts +26 -26
  288. package/dist/lib/Brand/index.js +131 -131
  289. package/dist/lib/Cart/index.d.ts +335 -335
  290. package/dist/lib/Cart/index.js +3977 -3977
  291. package/dist/lib/CartReservedQuantities/index.d.ts +49 -49
  292. package/dist/lib/CartReservedQuantities/index.js +159 -159
  293. package/dist/lib/CashDrawerShift/index.d.ts +83 -83
  294. package/dist/lib/CashDrawerShift/index.js +205 -205
  295. package/dist/lib/Catalogue/index.d.ts +15 -15
  296. package/dist/lib/Catalogue/index.js +78 -78
  297. package/dist/lib/Category/index.d.ts +34 -34
  298. package/dist/lib/Category/index.js +230 -230
  299. package/dist/lib/Class/index.d.ts +16 -16
  300. package/dist/lib/Class/index.js +66 -66
  301. package/dist/lib/Consent/index.d.ts +4 -4
  302. package/dist/lib/Consent/index.js +29 -29
  303. package/dist/lib/Customer/index.d.ts +30 -30
  304. package/dist/lib/Customer/index.js +92 -92
  305. package/dist/lib/Declination/index.d.ts +9 -9
  306. package/dist/lib/Declination/index.js +26 -26
  307. package/dist/lib/Discount/index.d.ts +27 -27
  308. package/dist/lib/Discount/index.js +493 -493
  309. package/dist/lib/ElasticSearch/index.d.ts +13 -13
  310. package/dist/lib/ElasticSearch/index.js +50 -50
  311. package/dist/lib/Elavon/index.d.ts +18 -18
  312. package/dist/lib/Elavon/index.js +135 -135
  313. package/dist/lib/Email/AbandonedCartEmail.d.ts +16 -16
  314. package/dist/lib/Email/AbandonedCartEmail.js +24 -24
  315. package/dist/lib/Email/AccountConfirmationEmail.d.ts +19 -19
  316. package/dist/lib/Email/AccountConfirmationEmail.js +30 -30
  317. package/dist/lib/Email/AdminOrderConfirmationEmail.d.ts +16 -16
  318. package/dist/lib/Email/AdminOrderConfirmationEmail.js +24 -24
  319. package/dist/lib/Email/ApplicationEmail.d.ts +16 -16
  320. package/dist/lib/Email/ApplicationEmail.js +24 -24
  321. package/dist/lib/Email/BackInStockEmail.d.ts +16 -16
  322. package/dist/lib/Email/BackInStockEmail.js +24 -24
  323. package/dist/lib/Email/ContactEmail.d.ts +16 -16
  324. package/dist/lib/Email/ContactEmail.js +24 -24
  325. package/dist/lib/Email/CustomerBookingAdminEmail.d.ts +16 -16
  326. package/dist/lib/Email/CustomerBookingAdminEmail.js +24 -24
  327. package/dist/lib/Email/CustomerBookingEmail.d.ts +16 -16
  328. package/dist/lib/Email/CustomerBookingEmail.js +24 -24
  329. package/dist/lib/Email/OrderConfirmationEmail.d.ts +16 -16
  330. package/dist/lib/Email/OrderConfirmationEmail.js +24 -24
  331. package/dist/lib/Email/OrderDenounciationEmail.d.ts +16 -16
  332. package/dist/lib/Email/OrderDenounciationEmail.js +24 -24
  333. package/dist/lib/Email/OrderSampleEmail.d.ts +16 -16
  334. package/dist/lib/Email/OrderSampleEmail.js +24 -24
  335. package/dist/lib/Email/OtherTypeEmails.d.ts +16 -16
  336. package/dist/lib/Email/OtherTypeEmails.js +27 -27
  337. package/dist/lib/Email/PasswordResetEmail.d.ts +16 -16
  338. package/dist/lib/Email/PasswordResetEmail.js +24 -24
  339. package/dist/lib/Email/PhotoShootEmail.d.ts +16 -16
  340. package/dist/lib/Email/PhotoShootEmail.js +24 -24
  341. package/dist/lib/Email/PickUpConfirmation.d.ts +16 -16
  342. package/dist/lib/Email/PickUpConfirmation.js +24 -24
  343. package/dist/lib/Email/ShippingConfirmation.d.ts +16 -16
  344. package/dist/lib/Email/ShippingConfirmation.js +24 -24
  345. package/dist/lib/Email/WelcomeEmail.d.ts +16 -16
  346. package/dist/lib/Email/WelcomeEmail.js +24 -24
  347. package/dist/lib/Email/index.d.ts +16 -16
  348. package/dist/lib/Email/index.js +31 -31
  349. package/dist/lib/ExternalService/Ebay.d.ts +74 -74
  350. package/dist/lib/ExternalService/Ebay.js +124 -124
  351. package/dist/lib/ExternalService/index.d.ts +5 -5
  352. package/dist/lib/ExternalService/index.js +10 -10
  353. package/dist/lib/FirstOrderTracking/index.d.ts +5 -5
  354. package/dist/lib/FirstOrderTracking/index.js +10 -10
  355. package/dist/lib/Indexed/IndexedCart.d.ts +13 -13
  356. package/dist/lib/Indexed/IndexedCart.js +91 -91
  357. package/dist/lib/Indexed/Product.d.ts +17 -17
  358. package/dist/lib/Indexed/Product.js +98 -98
  359. package/dist/lib/Inventory/index.d.ts +112 -112
  360. package/dist/lib/Inventory/index.js +492 -492
  361. package/dist/lib/Invoice/index.d.ts +16 -16
  362. package/dist/lib/Invoice/index.js +21 -21
  363. package/dist/lib/MarketplacePublication/index.d.ts +9 -9
  364. package/dist/lib/MarketplacePublication/index.js +426 -426
  365. package/dist/lib/Menu/index.d.ts +11 -11
  366. package/dist/lib/Menu/index.js +107 -107
  367. package/dist/lib/MongoDB/BaseAPI.d.ts +18 -18
  368. package/dist/lib/MongoDB/BaseAPI.js +200 -200
  369. package/dist/lib/Note/index.d.ts +4 -4
  370. package/dist/lib/Note/index.js +6 -6
  371. package/dist/lib/Order/index.d.ts +27 -27
  372. package/dist/lib/Order/index.js +56 -56
  373. package/dist/lib/Org/index.d.ts +68 -68
  374. package/dist/lib/Org/index.js +216 -216
  375. package/dist/lib/PandaPay/index.d.ts +16 -16
  376. package/dist/lib/PandaPay/index.js +176 -176
  377. package/dist/lib/Paysafe/index.d.ts +11 -11
  378. package/dist/lib/Paysafe/index.js +41 -41
  379. package/dist/lib/Product/index.d.ts +182 -182
  380. package/dist/lib/Product/index.js +847 -847
  381. package/dist/lib/ProductAttribute/index.d.ts +15 -15
  382. package/dist/lib/ProductAttribute/index.js +45 -45
  383. package/dist/lib/PromiseToPurchase/index.d.ts +109 -109
  384. package/dist/lib/PromiseToPurchase/index.js +343 -343
  385. package/dist/lib/PurchaseOrder/index.d.ts +20 -20
  386. package/dist/lib/PurchaseOrder/index.js +28 -28
  387. package/dist/lib/Schedule/index.d.ts +5 -5
  388. package/dist/lib/Schedule/index.js +12 -12
  389. package/dist/lib/Service/Enum/ServiceEnum.d.ts +3 -3
  390. package/dist/lib/Service/Enum/ServiceEnum.js +7 -7
  391. package/dist/lib/Service/index.d.ts +13 -13
  392. package/dist/lib/Service/index.js +21 -21
  393. package/dist/lib/Shipment/index.d.ts +28 -28
  394. package/dist/lib/Shipment/index.js +370 -370
  395. package/dist/lib/Slider/index.d.ts +22 -22
  396. package/dist/lib/Slider/index.js +119 -119
  397. package/dist/lib/Space/index.d.ts +1150 -1150
  398. package/dist/lib/Space/index.js +5792 -5792
  399. package/dist/lib/StockNotification/index.d.ts +4 -4
  400. package/dist/lib/StockNotification/index.js +6 -6
  401. package/dist/lib/Store/index.d.ts +5 -5
  402. package/dist/lib/Store/index.js +12 -12
  403. package/dist/lib/Supplier/Command.d.ts +5 -5
  404. package/dist/lib/Supplier/Command.js +10 -10
  405. package/dist/lib/Supplier/index.d.ts +25 -25
  406. package/dist/lib/Supplier/index.js +27 -27
  407. package/dist/lib/Tags/index.d.ts +6 -6
  408. package/dist/lib/Tags/index.js +26 -26
  409. package/dist/lib/Tax/index.d.ts +8 -8
  410. package/dist/lib/Tax/index.js +54 -54
  411. package/dist/lib/TransferRequest/index.d.ts +290 -290
  412. package/dist/lib/TransferRequest/index.js +1026 -1026
  413. package/dist/lib/Update/index.d.ts +10 -10
  414. package/dist/lib/Update/index.js +22 -22
  415. package/dist/lib/User/index.d.ts +89 -89
  416. package/dist/lib/User/index.js +328 -328
  417. package/dist/lib/Wishlist/index.d.ts +5 -5
  418. package/dist/lib/Wishlist/index.js +10 -10
  419. package/dist/lib/base.d.ts +14 -14
  420. package/dist/lib/base.js +62 -62
  421. package/dist/lib/baseService.d.ts +17 -17
  422. package/dist/lib/baseService.js +69 -69
  423. package/dist/rules/GR/constants/data.d.ts +26 -26
  424. package/dist/rules/GR/constants/data.js +81 -81
  425. package/dist/rules/GR/constants/expedition.d.ts +4 -4
  426. package/dist/rules/GR/constants/expedition.js +9 -9
  427. package/dist/rules/GR/constants/products.d.ts +22 -22
  428. package/dist/rules/GR/constants/products.js +263 -263
  429. package/dist/rules/GR/interfaces/cart.d.ts +84 -84
  430. package/dist/rules/GR/interfaces/cart.js +41 -41
  431. package/dist/rules/GR/interfaces/data.d.ts +101 -101
  432. package/dist/rules/GR/interfaces/data.js +114 -114
  433. package/dist/rules/GR/interfaces/products.d.ts +61 -61
  434. package/dist/rules/GR/interfaces/products.js +10 -10
  435. package/dist/rules/GR/utils/cart.d.ts +95 -95
  436. package/dist/rules/GR/utils/cart.js +839 -836
  437. package/dist/rules/GR/utils/cart.js.map +1 -1
  438. package/dist/rules/GR/utils/data.d.ts +3 -3
  439. package/dist/rules/GR/utils/data.js +28 -28
  440. package/dist/rules/GR/utils/expedition.d.ts +140 -140
  441. package/dist/rules/GR/utils/expedition.js +2016 -2016
  442. package/dist/rules/GR/utils/g2.d.ts +209 -209
  443. package/dist/rules/GR/utils/g2.js +999 -999
  444. package/dist/rules/GR/utils/invoices.d.ts +51 -51
  445. package/dist/rules/GR/utils/invoices.js +215 -215
  446. package/dist/rules/GR/utils/products.d.ts +277 -277
  447. package/dist/rules/GR/utils/products.js +1350 -1350
  448. package/dist/rules/GR/utils/upsells.d.ts +111 -111
  449. package/dist/rules/GR/utils/upsells.js +215 -215
  450. package/dist/services/database/BaseProvider.d.ts +29 -29
  451. package/dist/services/database/BaseProvider.js +28 -28
  452. package/dist/services/database/BatchUtils.d.ts +14 -14
  453. package/dist/services/database/BatchUtils.js +43 -43
  454. package/dist/services/database/Config.d.ts +2 -2
  455. package/dist/services/database/Config.js +5 -5
  456. package/dist/services/database/DatabaseService.d.ts +125 -125
  457. package/dist/services/database/DatabaseService.js +237 -237
  458. package/dist/services/database/FirebaseProvider.d.ts +17 -17
  459. package/dist/services/database/FirebaseProvider.js +235 -235
  460. package/dist/services/database/NotFirebaseProvider.d.ts +49 -49
  461. package/dist/services/database/NotFirebaseProvider.js +262 -262
  462. package/dist/services/g2/G2OrderSlip.d.ts +49 -49
  463. package/dist/services/g2/G2OrderSlip.js +228 -228
  464. package/dist/services/g2/utils.d.ts +19 -19
  465. package/dist/services/g2/utils.js +953 -953
  466. package/dist/services/logs/index.d.ts +23 -23
  467. package/dist/services/logs/index.js +66 -66
  468. package/dist/services/marketplace/BaseMarketServiceClass.d.ts +52 -52
  469. package/dist/services/marketplace/BaseMarketServiceClass.js +111 -111
  470. package/dist/services/marketplace/CardtraderServiceClass.d.ts +17 -17
  471. package/dist/services/marketplace/CardtraderServiceClass.js +139 -139
  472. package/dist/services/marketplace/utils.d.ts +14 -14
  473. package/dist/services/marketplace/utils.js +29 -29
  474. package/dist/services/products/BaseClass.d.ts +50 -50
  475. package/dist/services/products/BaseClass.js +66 -66
  476. package/dist/services/products/TCGService.d.ts +32 -32
  477. package/dist/services/products/TCGService.js +555 -555
  478. package/dist/services/products/utils.d.ts +31 -31
  479. package/dist/services/products/utils.js +144 -144
  480. package/dist/utils/algolia.d.ts +46 -46
  481. package/dist/utils/algolia.js +21 -21
  482. package/dist/utils/anonymisation.d.ts +54 -54
  483. package/dist/utils/anonymisation.js +280 -280
  484. package/dist/utils/array.d.ts +5 -5
  485. package/dist/utils/array.js +14 -14
  486. package/dist/utils/aws.d.ts +36 -36
  487. package/dist/utils/aws.js +154 -154
  488. package/dist/utils/booking.d.ts +30 -30
  489. package/dist/utils/booking.js +127 -127
  490. package/dist/utils/cart.d.ts +259 -259
  491. package/dist/utils/cart.js +1145 -1145
  492. package/dist/utils/categories.d.ts +2 -2
  493. package/dist/utils/categories.js +54 -54
  494. package/dist/utils/cmv.d.ts +10 -10
  495. package/dist/utils/cmv.js +107 -107
  496. package/dist/utils/console.d.ts +6 -6
  497. package/dist/utils/console.js +59 -59
  498. package/dist/utils/context.d.ts +20 -20
  499. package/dist/utils/context.js +61 -61
  500. package/dist/utils/currency.d.ts +6 -6
  501. package/dist/utils/currency.js +91 -91
  502. package/dist/utils/data.d.ts +31 -31
  503. package/dist/utils/data.js +296 -296
  504. package/dist/utils/date.d.ts +1 -1
  505. package/dist/utils/date.js +16 -16
  506. package/dist/utils/dimensions.d.ts +3 -3
  507. package/dist/utils/dimensions.js +16 -16
  508. package/dist/utils/discount.d.ts +164 -164
  509. package/dist/utils/discount.js +1111 -1111
  510. package/dist/utils/errors.d.ts +113 -113
  511. package/dist/utils/errors.js +113 -113
  512. package/dist/utils/file-admin.d.ts +8 -8
  513. package/dist/utils/file-admin.js +39 -39
  514. package/dist/utils/file.d.ts +39 -39
  515. package/dist/utils/file.js +208 -208
  516. package/dist/utils/firebase-admin.d.ts +11 -11
  517. package/dist/utils/firebase-admin.js +73 -73
  518. package/dist/utils/firebase.d.ts +58 -58
  519. package/dist/utils/firebase.js +148 -148
  520. package/dist/utils/import.d.ts +1 -1
  521. package/dist/utils/import.js +21 -21
  522. package/dist/utils/inventories.d.ts +101 -101
  523. package/dist/utils/inventories.js +467 -467
  524. package/dist/utils/locale.d.ts +24 -24
  525. package/dist/utils/locale.js +89 -89
  526. package/dist/utils/mailchimp.d.ts +58 -58
  527. package/dist/utils/mailchimp.js +531 -531
  528. package/dist/utils/mathUtils.d.ts +17 -17
  529. package/dist/utils/mathUtils.js +324 -324
  530. package/dist/utils/mongodb.d.ts +1 -1
  531. package/dist/utils/mongodb.js +22 -22
  532. package/dist/utils/object.d.ts +32 -32
  533. package/dist/utils/object.js +133 -133
  534. package/dist/utils/payment.d.ts +10 -10
  535. package/dist/utils/payment.js +23 -23
  536. package/dist/utils/products.d.ts +39 -39
  537. package/dist/utils/products.js +195 -195
  538. package/dist/utils/promiseToPurchase.d.ts +88 -88
  539. package/dist/utils/promiseToPurchase.js +229 -229
  540. package/dist/utils/prosprsearch.d.ts +42 -42
  541. package/dist/utils/prosprsearch.js +216 -216
  542. package/dist/utils/refunds.d.ts +2 -2
  543. package/dist/utils/refunds.js +21 -21
  544. package/dist/utils/sdc.d.ts +10 -10
  545. package/dist/utils/sdc.js +1309 -1309
  546. package/dist/utils/searchIndexes.d.ts +58 -58
  547. package/dist/utils/searchIndexes.js +247 -247
  548. package/dist/utils/services.d.ts +42 -42
  549. package/dist/utils/services.js +409 -409
  550. package/dist/utils/shipment.d.ts +110 -110
  551. package/dist/utils/shipment.js +345 -345
  552. package/dist/utils/simpletexting.d.ts +2 -2
  553. package/dist/utils/simpletexting.js +45 -45
  554. package/dist/utils/sliders.d.ts +4 -4
  555. package/dist/utils/sliders.js +24 -24
  556. package/dist/utils/string.d.ts +16 -16
  557. package/dist/utils/string.js +192 -192
  558. package/dist/utils/tcgService.d.ts +74 -74
  559. package/dist/utils/tcgService.js +308 -308
  560. package/dist/utils/tools.d.ts +5 -5
  561. package/dist/utils/tools.js +13 -13
  562. package/dist/utils/transferRequests.d.ts +43 -43
  563. package/dist/utils/transferRequests.js +67 -67
  564. package/dist/utils/update.d.ts +7 -7
  565. package/dist/utils/update.js +137 -137
  566. package/dist/utils/weight.d.ts +3 -3
  567. package/dist/utils/weight.js +16 -16
  568. package/dist/utils/zones.d.ts +11 -11
  569. package/dist/utils/zones.js +218 -218
  570. package/package.json +107 -107
  571. package/publish.sh +143 -143
  572. package/readme.md +182 -182
  573. package/dist/lib/Queue/index.d.ts +0 -40
  574. package/dist/lib/Queue/index.js +0 -255
  575. package/dist/lib/Queue/index.js.map +0 -1
@@ -1,1351 +1,1351 @@
1
- "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.shouldHideItemIfRegPriceIs0 = exports.getFormattedProdGR = exports.applyProCustomPromo = exports.shouldShowProCustomPromo = exports.fetchFeesBeforeCart = exports.getVracType = exports.getConcreteItemsByAvailability = exports.getConcreteQteText = exports.getInstallItemPrice = exports.getInstallationArray = exports.matchesFuelSurchargeParent = exports.shouldHideItemInCheckout = exports.applyAllInclusiveOverrides = exports.isInstallAllInclusiveActive = exports.getInstallationAllInclusiveFromPriceList = exports.roundGrassQte = exports.handleGrassProductQtyRoundForShipping = exports.getGrassSubQuestionsByType = exports.getGrassServicesFees = exports.getGrassQteText = exports.getMinQtyFeeAmountText = exports.getMinQtyFeeText = exports.getAllMinGrassQuantities = exports.isMinQtyFee = exports.fuseGrassProducts = exports.getAllInstallFromItems = exports.checkIfProductIsInstallation = exports.checkIfIsNonSpecialityGrass = exports.checkIfProductIsOfType = exports.getProductFormOptions = exports.getParentProductCategoryGroup = exports.getProdName = exports.splitOnDashes = exports.getRoundedUnitProductQuantities = exports.getRoundedSellUnitProductQuantities = exports.getDescriptionString = exports.getDescriptionLength = exports.getProductAttributes = exports.productUnitSupportsDecimals = exports.getCorrectPluralSellUnit = exports.getPluralUnitLabelWithSlug = exports.getUnitLabelWithSlug = exports.getProductUnitLabel = exports.getProductSellUnitLabel = void 0;
18
- const ceil_1 = __importDefault(require("lodash/ceil"));
19
- const maxBy_1 = __importDefault(require("lodash/maxBy"));
20
- const orderBy_1 = __importDefault(require("lodash/orderBy"));
21
- const toNumber_1 = __importDefault(require("lodash/toNumber"));
22
- const round_1 = __importDefault(require("lodash/round"));
23
- const flatten_1 = __importDefault(require("lodash/flatten"));
24
- const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
25
- const sumBy_1 = __importDefault(require("lodash/sumBy"));
26
- const floor_1 = __importDefault(require("lodash/floor"));
27
- const Cart_1 = require("../../../Interfaces/Cart");
28
- const G2_1 = require("../../../Interfaces/G2");
29
- const IDiscountRule_1 = require("../../../Interfaces/Rules/IDiscountRule");
30
- // General utils
31
- const string_1 = require("../../../utils/string");
32
- const locale_1 = require("../../../utils/locale");
33
- const inventories_1 = require("../../../utils/inventories");
34
- const products_1 = require("../../../utils/products");
35
- // Specitic utils
36
- const expedition_1 = require("./expedition");
37
- const products_2 = require("../constants/products");
38
- const g2_1 = require("./g2");
39
- const cart_1 = require("./cart");
40
- // Specific interfaces
41
- const products_3 = require("../interfaces/products");
42
- const data_1 = require("../interfaces/data");
43
- const cart_2 = require("../interfaces/cart");
44
- const upsells_1 = require("./upsells");
45
- const object_1 = require("../../../utils/object");
46
- // ----------------------------------------------------------------------------------------------------------
47
- // #region PRODUCT UNITS
48
- const pluralSellUnits = {
49
- p2: { fr: 'pi²', en: 'sqft' },
50
- sac: { fr: 'sacs', en: 'bags' },
51
- unite: { fr: 'unités', en: 'units' },
52
- tonne: { fr: 'tonnes', en: 'tons' },
53
- rouleau: { fr: 'rouleaux', en: 'rolls' }
54
- };
55
- const pluralSellUnitsBySlug = {
56
- p2: { fr: 'pi²', en: 'sqft' },
57
- sac: { fr: 'sacs', en: 'bags' },
58
- unite: { fr: 'unités', en: 'units' },
59
- tonne: { fr: 'tonnes', en: 'tons' },
60
- roul: { fr: 'rouleaux', en: 'rolls' },
61
- pal: { fr: 'palettes', en: 'pallets' },
62
- rg: { fr: 'rangs', en: 'rows' },
63
- ensemble: { fr: 'ensembles', en: 'kits' },
64
- pl: { fr: 'pL', en: 'linear feet' },
65
- mcx: { fr: 'morceaux', en: 'pieces' },
66
- vg3: { fr: 'vg³', en: 'yd³' },
67
- demipalsm: { fr: 'Demi-palettes (petite)', en: 'Half-pallets (small)' },
68
- demipallg: { fr: 'Demi-palettes (lg)', en: 'Half-pallets (lg)' },
69
- tonnes: { fr: 'tonnes', en: 'tons' },
70
- bte: { fr: 'boîtes', en: 'boxes' },
71
- pqt: { fr: 'paquets', en: 'bundles' },
72
- '': { fr: 'unités', en: 'units' }
73
- };
74
- const sellUnitsBySlug = {
75
- p2: { fr: 'pi²', en: 'sqft' },
76
- sac: { fr: 'sac', en: 'bag' },
77
- unite: { fr: 'unité', en: 'unit' },
78
- tonne: { fr: 'tonne', en: 'ton' },
79
- roul: { fr: 'rouleau', en: 'roll' },
80
- pal: { fr: 'palette', en: 'pallet' },
81
- rg: { fr: 'rang', en: 'row' },
82
- ensemble: { fr: 'ensemble', en: 'kit' },
83
- pl: { fr: 'pL', en: 'linear feet' },
84
- mcx: { fr: 'morceau', en: 'piece' },
85
- vg3: { fr: 'vg³', en: 'yd³' },
86
- demipalsm: { fr: 'Demi-palette (petite)', en: 'Half-pallet (small)' },
87
- demipallg: { fr: 'Demi-palette (lg)', en: 'Half-pallet (lg)' },
88
- tonnes: { fr: 'tonne', en: 'ton' },
89
- bte: { fr: 'boîte', en: 'box' },
90
- pqt: { fr: 'paquet', en: 'bundle' },
91
- '': { fr: 'unité', en: 'unit' }
92
- };
93
- /**
94
- * @description Returns sell unit label in correct language for a specific product's other_units
95
- * @param {IFilledDimensionUnits[] | undefined} otherUnits The unit array we have to check to get the sell unit
96
- * @param {string | undefined} locale The language in which we want to return the label
97
- * @param {string[]} returnUnitForSlugs An array of the slugs we want to return the unit label for
98
- * @param {boolean} options.returnPlural If plural version should be returned
99
- * @param {boolean} options.returnShortByDefault If short version should be prioritized
100
- */
101
- const getProductSellUnitLabel = (otherUnits, locale = 'fr', returnUnitForSlugs, options = {}) => {
102
- if (!!!otherUnits)
103
- return '';
104
- const sellingUnit = otherUnits.find((unit) => !!unit.is_sale_unit);
105
- if (!!!sellingUnit)
106
- return '';
107
- return (0, exports.getUnitLabelWithSlug)(sellingUnit.unit_slug, locale, options.returnPlural, returnUnitForSlugs, options.returnShortByDefault);
108
- };
109
- exports.getProductSellUnitLabel = getProductSellUnitLabel;
110
- /**
111
- * @description Returns unit label in correct language for a specific product's other_units
112
- * @param {IFilledDimensionUnits[] | undefined} otherUnits The unit array we have to check to get the sell unit
113
- * @param {string} type The unit type to check
114
- * @param {string | undefined} locale The language in which we want to return the label
115
- * @param {string[]} returnUnitForSlugs An array of the slugs we want to return the unit label for
116
- * @param {boolean} options.returnPlural If plural version should be returned
117
- * @param {boolean} options.returnShortByDefault If short version should be prioritized
118
- */
119
- const getProductUnitLabel = (otherUnits, type, locale = 'fr', returnUnitForSlugs, options = {}) => {
120
- if (!!!otherUnits)
121
- return '';
122
- const unitToUse = otherUnits.find((unit) => (type == 'sale_unit' ? unit.is_sale_unit : unit.is_inventory_unit));
123
- if (!!!unitToUse)
124
- return '';
125
- return (0, exports.getUnitLabelWithSlug)(unitToUse.unit_slug, locale, options.returnPlural, returnUnitForSlugs, options.returnShortByDefault);
126
- };
127
- exports.getProductUnitLabel = getProductUnitLabel;
128
- /**
129
- * Returns the unit label for a specific slug
130
- * @param {string} unitSlug The slug of the unit for which we want to get the label
131
- * @param {string | undefined} locale The language in which we want to get the label
132
- * @param {boolean} getPluralVersion Optionnal - If the plural version should be returned instead.
133
- * @param {string[]} returnUnitForSlugs The slugs for which we want to return a default value, in this case the unit slug for unit
134
- * @param {boolean} returnShortByDefault Optionnal - If the short version should be prioritized
135
- */
136
- const getUnitLabelWithSlug = (unitSlug, locale = 'fr', getPluralVersion = false, returnUnitForSlugs, returnShortByDefault) => {
137
- if (!!returnUnitForSlugs && !!returnUnitForSlugs.includes(unitSlug)) {
138
- return (0, exports.getUnitLabelWithSlug)('unite', locale, getPluralVersion);
139
- }
140
- if (!!getPluralVersion)
141
- return (0, exports.getPluralUnitLabelWithSlug)(unitSlug, locale, returnUnitForSlugs, returnShortByDefault);
142
- const shortVersion = !!(0, inventories_1.getUnitShortDict)(unitSlug) ? (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)(unitSlug), locale) : '';
143
- const longVersion = !!sellUnitsBySlug[unitSlug] ? (0, locale_1.translateILang)(sellUnitsBySlug[unitSlug], locale) : '';
144
- if (!!returnShortByDefault)
145
- return shortVersion;
146
- return longVersion || shortVersion || unitSlug;
147
- };
148
- exports.getUnitLabelWithSlug = getUnitLabelWithSlug;
149
- /**
150
- * Returns the plural unit label for a specific slug
151
- * @deprecated Should use getUnitLabelWithSlug instead (with props getPluralVersion=true)
152
- * @param {string} unitSlug The slug of the unit for which we want to get the label
153
- * @param {string | undefined} locale The language in which we want to get the label
154
- * @param {string[]} returnUnitForSlugs The slugs for which we want to return a default value, in this case the unit slug for unit
155
- */
156
- const getPluralUnitLabelWithSlug = (unitSlug, locale = 'fr', returnUnitForSlugs, useShortIfDifferent) => {
157
- if (!!returnUnitForSlugs && !!returnUnitForSlugs.includes(unitSlug)) {
158
- return (0, locale_1.translateILang)(pluralSellUnitsBySlug['unite'], locale);
159
- }
160
- const shortVersion = !!(0, inventories_1.getUnitShortDict)(unitSlug) ? (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)(unitSlug), locale) : '';
161
- const normalVersion = !!sellUnitsBySlug[unitSlug] ? (0, locale_1.translateILang)(sellUnitsBySlug[unitSlug], locale) : '';
162
- const pluralVersion = !!pluralSellUnitsBySlug[unitSlug] ? (0, locale_1.translateILang)(pluralSellUnitsBySlug[unitSlug], locale) : '';
163
- // If useShowIfDifferent is defined, and short version is different from the "normal" version, return short value
164
- if (useShortIfDifferent && shortVersion != normalVersion)
165
- return shortVersion;
166
- return pluralVersion || shortVersion || unitSlug;
167
- };
168
- exports.getPluralUnitLabelWithSlug = getPluralUnitLabelWithSlug;
169
- const getCorrectPluralSellUnit = (sellUnit, locale = 'fr') => {
170
- if (!!!sellUnit.unit)
171
- return '';
172
- const frSellUnit = (0, string_1.string_to_slug)((0, locale_1.translateILang)(sellUnit.unit, 'fr'));
173
- return !!pluralSellUnits[frSellUnit]
174
- ? (0, locale_1.translateILang)(pluralSellUnits[frSellUnit], locale)
175
- : (0, locale_1.translateILang)(sellUnit.unit, locale);
176
- };
177
- exports.getCorrectPluralSellUnit = getCorrectPluralSellUnit;
178
- const productUnitSupportsDecimals = (unitSlug, isService) => {
179
- return !!isService || !!['p2', 'pl', 'vg3', 'tonne'].includes(unitSlug);
180
- };
181
- exports.productUnitSupportsDecimals = productUnitSupportsDecimals;
182
- // #endregion
183
- // ----------------------------------------------------------------------------------------------------------
184
- // ----------------------------------------------------------------------------------------------------------
185
- // #region GENERAL
186
- const getProductAttributes = (product) => {
187
- const arrColor = !!product.attributes[data_1.AttributesIdEnumGR.SUBCOLOR]
188
- ? product.attributes[data_1.AttributesIdEnumGR.SUBCOLOR]
189
- : [];
190
- const arrDimensions = !!product.attributes[data_1.AttributesIdEnumGR.DIMENSIONS]
191
- ? product.attributes[data_1.AttributesIdEnumGR.DIMENSIONS]
192
- : [];
193
- const arrFormats = !!product.attributes[data_1.AttributesIdEnumGR.FORMATS]
194
- ? product.attributes[data_1.AttributesIdEnumGR.FORMATS]
195
- : [];
196
- return { colors: arrColor, dimensions: arrDimensions, formats: arrFormats };
197
- };
198
- exports.getProductAttributes = getProductAttributes;
199
- const getDescriptionLength = (description, locale = 'fr') => {
200
- if (!!!description || !!!(0, locale_1.getLocaleOfDictionnary)(description, locale))
201
- return 0;
202
- return (0, string_1.stripHTML)((0, locale_1.getLocaleOfDictionnary)(description, locale)).length;
203
- };
204
- exports.getDescriptionLength = getDescriptionLength;
205
- const getDescriptionString = (showFullDesc, maxLength, description, locale = 'fr') => {
206
- if (!!showFullDesc || (0, exports.getDescriptionLength)(description, locale) <= maxLength) {
207
- return (0, string_1.stripHTML)((0, locale_1.getLocaleOfDictionnary)(description, locale));
208
- }
209
- let truncated = (0, string_1.stripHTML)((0, locale_1.getLocaleOfDictionnary)(description, locale)).slice(0, maxLength).split(' ');
210
- truncated.pop();
211
- return truncated.join(' ') + ' [...]';
212
- };
213
- exports.getDescriptionString = getDescriptionString;
214
- /**
215
- * Returns rounded product sell_unit quantities depending on current value, value of secondary input if existant and sale unit per command step ratio found in product.
216
- * @param value {number} - Current quantity as entered by user in first input
217
- * @param otherUnits {IFilledDimensionUnits[] | undefined} - FilledDimensionUnits found in product (possibly undefined)
218
- * @param value2 {number | undefined} - Current quantity as entered by user in second input (possibly undefined)
219
- * @param targetIsSecondaryInput {boolean} - If action was triggered from secondary input (defaults to false)
220
- */
221
- const getRoundedSellUnitProductQuantities = (value, otherUnits = [], value2, targetIsSecondaryInput = false) => {
222
- var _a;
223
- const saleUnit = otherUnits.find((unit) => unit.is_sale_unit);
224
- const commandUnit = otherUnits.find((unit) => unit.is_command_unit);
225
- const commandStep = otherUnits.find((unit) => unit.is_command_step);
226
- let roundedQuantities = {
227
- qte1: value,
228
- qte2: value2
229
- };
230
- // Now rounds quantities in calculations to 2 or 0 decimals (depending on what the unit supports)
231
- if (!!targetIsSecondaryInput && typeof value2 === 'number') {
232
- if (!!commandStep && !!commandStep.fitting_unit && !!commandUnit && !!commandUnit.fitting_unit && !!saleUnit) {
233
- const nbCmdUnitPerCmdStep = (0, round_1.default)(commandStep.fitting_unit / commandUnit.fitting_unit, 5);
234
- const nbSaleUnitPerCmdStep = (0, round_1.default)(commandStep.fitting_unit / ((_a = saleUnit.fitting_unit) !== null && _a !== void 0 ? _a : 1), (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0);
235
- // Round value2 to command step
236
- const roundedValue = value2 === 0
237
- ? 0
238
- : _roundNbUnitPerCmdStep(value2, nbCmdUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 2 : 0);
239
- // Calculate amount of current command units by dividing roundedValue with nbCmdUnitPerCmdStep
240
- const nbOfRoundedCmdUnits = roundedValue / nbCmdUnitPerCmdStep;
241
- // Then multiply result by amount of sale units in one command step
242
- const nbOfRoundedSaleUnits = nbOfRoundedCmdUnits * nbSaleUnitPerCmdStep;
243
- roundedQuantities = {
244
- qte1: value2 === 0
245
- ? 0
246
- : (0, round_1.default)(nbOfRoundedSaleUnits, !!saleUnit && (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 2 : 0),
247
- qte2: roundedValue
248
- };
249
- }
250
- }
251
- else if (!!commandStep && !!commandStep.fitting_unit && !!saleUnit && !!saleUnit.fitting_unit) {
252
- const cmdStepFittingUnit = commandStep.fitting_unit;
253
- const saleFittingUnit = saleUnit.fitting_unit;
254
- const nbSaleUnitPerCmdStep = (0, round_1.default)(cmdStepFittingUnit / saleFittingUnit, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0);
255
- const roundedValue = value === 0
256
- ? 0
257
- : _roundNbUnitPerCmdStep(value, nbSaleUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 2 : 0);
258
- let commandUnitQty = undefined;
259
- if (!!commandUnit && !!commandUnit.fitting_unit) {
260
- if (value === 0) {
261
- commandUnitQty = 0;
262
- }
263
- // ** NOTE - Commented section here to fix rounding bug - Commented on 10-09-2025, in relation to bug GR-I540
264
- // if sell_unit has a fitting unit of 1, we can simply divide the command_unit from roundedValue to get result
265
- // else if (saleFittingUnit == 1) {
266
- // console.log('YO YO YO are we HERE&&????')
267
- // commandUnitQty = round(
268
- // roundedValue / commandUnit.fitting_unit,
269
- // productUnitSupportsDecimals(commandUnit.unit_slug) ? 2 : 0
270
- // )
271
- // }
272
- else {
273
- // Calculate amount of current command steps by dividing roundedValue with saleUnitsPerCommandStep
274
- // ** NOTE - Added round here on 10-09-2025 in relation to bug GR-I540
275
- const nbOfCmdSteps = (0, round_1.default)(roundedValue / nbSaleUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0);
276
- // Then multiply result by amount of command unit in one command step
277
- commandUnitQty =
278
- nbOfCmdSteps *
279
- (0, round_1.default)(cmdStepFittingUnit / commandUnit.fitting_unit, (0, exports.productUnitSupportsDecimals)(commandUnit.unit_slug) ? 5 : 0);
280
- commandUnitQty = (0, round_1.default)(commandUnitQty, (0, exports.productUnitSupportsDecimals)(commandUnit.unit_slug) ? 2 : 0);
281
- }
282
- }
283
- roundedQuantities = {
284
- qte1: roundedValue,
285
- qte2: commandUnitQty
286
- };
287
- }
288
- return roundedQuantities;
289
- };
290
- exports.getRoundedSellUnitProductQuantities = getRoundedSellUnitProductQuantities;
291
- /**
292
- * Returns rounded product quantities depending on current value per command step ratio found in product.
293
- * @param value {number} - Current quantity as entered by user in first input
294
- * @param otherUnits {IFilledDimensionUnits[] | undefined} - FilledDimensionUnits found in product (possibly undefined)
295
- * @param type {'sale_unit' | 'inventory_unit'} - Quantity type for computing
296
- */
297
- const getRoundedUnitProductQuantities = (value, otherUnits = [], type) => {
298
- const unitToTest = type == 'sale_unit'
299
- ? otherUnits.find((unit) => unit.is_sale_unit)
300
- : otherUnits.find((unit) => unit.is_inventory_unit);
301
- const commandStep = otherUnits.find((unit) => unit.is_command_step);
302
- let roundedQuantities = value;
303
- if (!!commandStep && !!commandStep.fitting_unit && unitToTest && unitToTest.fitting_unit) {
304
- const cmdStepFittingUnit = commandStep.fitting_unit;
305
- const fittingUnit = unitToTest.fitting_unit;
306
- const nbUnitPerCmdStep = cmdStepFittingUnit / fittingUnit;
307
- const roundedValue = value === 0
308
- ? 0
309
- : _roundNbUnitPerCmdStepV2(value, nbUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(unitToTest.unit_slug) ? 5 : 0);
310
- roundedQuantities = roundedValue;
311
- }
312
- return roundedQuantities;
313
- };
314
- exports.getRoundedUnitProductQuantities = getRoundedUnitProductQuantities;
315
- const _roundNbUnitPerCmdStepV2 = (value, nbUnitPerCmdStep, decimalsToCheck = 0) => {
316
- const currentFittingValue = (0, floor_1.default)(value / nbUnitPerCmdStep, 5); // Rounds unsignificant quantities to lower value (ex. if result is 0.000007, we don't want it to round up to 1)
317
- const roundedUp = (0, round_1.default)((0, ceil_1.default)(currentFittingValue) * nbUnitPerCmdStep, decimalsToCheck);
318
- // retrun roundedUp as default value.
319
- return roundedUp;
320
- };
321
- const _roundNbUnitPerCmdStep = (value, nbUnitPerCmdStep, decimalsToCheck = 0) => {
322
- let numberBuffer = 0;
323
- if (decimalsToCheck > 0) {
324
- let buffer = '';
325
- buffer = buffer.padStart(decimalsToCheck - 1, '0');
326
- numberBuffer = (0, toNumber_1.default)(`0.${buffer}1`);
327
- }
328
- const rounded = (0, round_1.default)(value / nbUnitPerCmdStep, decimalsToCheck) * nbUnitPerCmdStep;
329
- const roundedUp = Math.ceil(value / nbUnitPerCmdStep) * nbUnitPerCmdStep;
330
- // if rounded value is 0, but roundedUp is > 0, return roundedUp
331
- if (rounded == 0 && roundedUp > 0)
332
- return roundedUp;
333
- // ** NEW - Added on 10-09-2025 in relation to bug GR-I540
334
- // if provided value is already a multiple of cmdStep, return value
335
- if ((0, round_1.default)(value % nbUnitPerCmdStep, decimalsToCheck) == 0)
336
- return rounded;
337
- // if provided value is larger than rounded, and roundedUp is an exact multiple of rounded, return roundedUp
338
- if ((0, round_1.default)(value, decimalsToCheck) > rounded + numberBuffer)
339
- return roundedUp;
340
- // if rounded value is an exact multiple of cmdStep, return rounded
341
- if ((0, round_1.default)(rounded, decimalsToCheck) % nbUnitPerCmdStep <= numberBuffer)
342
- return rounded;
343
- // retrun roundedUp as default value.
344
- return roundedUp;
345
- };
346
- /**
347
- *
348
- * @param {string} stringToSplit
349
- * @param {string} dummyStringToReplace.currentValue, optionnal, default : '%%-%%'. Used to provide general replace values for a specific string. Is applied to both sections of the splitted string.
350
- * @param {string} dummyStringToReplace.newValue, optionnal, default : ' - '. Used to provide general replace values for a specific string. Is applied to both sections of the splitted string.
351
- * @returns {string[]}
352
- */
353
- const splitOnDashes = (stringToSplit, dummyStringToReplace = { currentValue: '%%-%%', newValue: ' - ' }) => {
354
- let splited = stringToSplit.split(' - ');
355
- if (splited.length === 1)
356
- splited = stringToSplit.split(' -');
357
- if (splited.length === 1)
358
- splited = stringToSplit.split('- ');
359
- return [
360
- splited[0].replace(dummyStringToReplace.currentValue, dummyStringToReplace.newValue),
361
- ...(!!splited[1]
362
- ? [splited.slice(1).join(' - ').replace(dummyStringToReplace.currentValue, dummyStringToReplace.newValue)]
363
- : [])
364
- ];
365
- };
366
- exports.splitOnDashes = splitOnDashes;
367
- /**
368
- * Get product name as array. Array created mostly by splitting name on dash symbol (and variations).
369
- * @param {IIndexedVariationAlgolia | IIndexedProduct} product
370
- * @param {string | undefined} locale
371
- * @returns {string[]} - Position 0 is the "commum section" of the name, and position 1 should contain all specifics (ex. color, size, etc...)
372
- */
373
- const getProdName = (product, locale, platform, attributes) => {
374
- var _a;
375
- let name;
376
- if (!!product.full_name) {
377
- name = (0, locale_1.getLocaleOfDictionnary)(product.full_name, locale);
378
- }
379
- else {
380
- name = (0, locale_1.getLocaleOfDictionnary)(product.name, locale);
381
- if (!!product.use_parent && !!product.parent_name) {
382
- if (typeof product.parent_name === 'string') {
383
- name = product.parent_name;
384
- }
385
- }
386
- }
387
- let newNameArray = [];
388
- const dashesToFind = [' - ', '- ', ' -'];
389
- // If name includes parenthesis...
390
- if (name.includes('(')) {
391
- let newStr = '';
392
- let strWithParenthesisToCheck = name;
393
- // a. Replace all occurences of dashesToFind found between parenthesis with '-'
394
- while (strWithParenthesisToCheck.includes('(')) {
395
- let positionStart = strWithParenthesisToCheck.indexOf('(');
396
- let positionEnd = strWithParenthesisToCheck.indexOf(')');
397
- // When first string between paranthesis found, replace dashesToFind
398
- let substrToCheck = strWithParenthesisToCheck.substring(positionStart, positionEnd + 1);
399
- for (let dash of dashesToFind) {
400
- substrToCheck = substrToCheck.replace(dash, '-');
401
- }
402
- // Add updated string to newStr from the beginning to the end of section with parenthesis
403
- newStr += strWithParenthesisToCheck.substring(0, positionStart) + substrToCheck;
404
- // Strip checked string to remove section added to newStr.
405
- // This will mean next time we go through the loop, logic will check for next section with parenthesis. If not found, loop ends.
406
- strWithParenthesisToCheck =
407
- positionEnd === strWithParenthesisToCheck.length - 1 ? '' : strWithParenthesisToCheck.substring(positionEnd + 1);
408
- }
409
- // Add ending of string to newly formatted string after loop done (in case last parenthesis found was not at the end of the string)
410
- newStr += strWithParenthesisToCheck;
411
- // b. Isolate "first part" of string
412
- const positionOfFirst = newStr.indexOf(')');
413
- let firstPart = newStr.substring(0, positionOfFirst);
414
- // If first closing parenthesis is not at end of string and firstPart contains dashesToFind, it means the ' - ' should be keep intact.
415
- // Replace ' - ' found with uncommon string so we can put it back later, then call splitOnDashes function
416
- if (positionOfFirst !== newStr.length - 1 && dashesToFind.some((str) => firstPart.includes(str))) {
417
- const secondPart = newStr.substring(positionOfFirst);
418
- for (let str of dashesToFind) {
419
- firstPart.replace(str, '%%-%%');
420
- }
421
- newNameArray = (0, exports.splitOnDashes)(`${firstPart}${secondPart}`);
422
- }
423
- // Else, simply call splitOnDashes function
424
- else {
425
- newNameArray = (0, exports.splitOnDashes)(newStr);
426
- }
427
- }
428
- // Else, no parenthesis found, call splitOnDashes function
429
- else {
430
- newNameArray = (0, exports.splitOnDashes)(name);
431
- }
432
- if (platform === 'pos' && !!attributes) {
433
- for (const attribute of attributes) {
434
- if (!!!attribute.id)
435
- continue;
436
- const productAttributeSlugs = (_a = product.attributes) === null || _a === void 0 ? void 0 : _a[attribute.id];
437
- if (!!productAttributeSlugs) {
438
- for (const attrValue of attribute.values) {
439
- if (productAttributeSlugs.includes(attrValue.slug)) {
440
- const label = (0, locale_1.getLocaleOfDictionnary)(attrValue.value, locale);
441
- if (label) {
442
- newNameArray[0] = newNameArray[0] + ` (${label})`;
443
- }
444
- }
445
- }
446
- }
447
- }
448
- }
449
- return newNameArray;
450
- };
451
- exports.getProdName = getProdName;
452
- /**
453
- * Function getParentProductCategoryGroup
454
- * @param prod - Product to check
455
- */
456
- const getParentProductCategoryGroup = (prod) => {
457
- let type = 'other';
458
- if (!!prod.categories && !!prod.categories['lvl0']) {
459
- const categorySlug = prod.categories['lvl0'];
460
- switch (categorySlug) {
461
- case 'gazon':
462
- if (!!(0, exports.checkIfProductIsOfType)(prod, 'gazon')) {
463
- type = 'gazon';
464
- }
465
- break;
466
- case 'amenagement-paysager':
467
- if (!!(0, exports.checkIfProductIsOfType)(prod, 'beton')) {
468
- type = 'beton';
469
- }
470
- break;
471
- default:
472
- if (!!(0, exports.checkIfProductIsOfType)(prod, 'vrac')) {
473
- type = 'vrac';
474
- }
475
- break;
476
- }
477
- }
478
- return type;
479
- };
480
- exports.getParentProductCategoryGroup = getParentProductCategoryGroup;
481
- /**
482
- * Function getProductFormOptions - Returns all AttributeValues for product to construct options in add to cart form
483
- * @param product - Product to check
484
- * @param attributes - Array of IAttributes to fetch info from
485
- */
486
- const getProductFormOptions = (product, attributes) => {
487
- let allColorOptions = [];
488
- let allDimensionOptions = [];
489
- let allFormatOptions = [];
490
- //Product Attributes
491
- const product_attributes = (0, exports.getProductAttributes)(product);
492
- //Overridden attr
493
- let overridenAttributes = product.declinations
494
- .map((declination) => declination.overriden_attributes)
495
- .filter((ova) => !!ova);
496
- overridenAttributes = (0, flatten_1.default)(overridenAttributes);
497
- overridenAttributes = (0, uniqBy_1.default)(overridenAttributes, 'slug');
498
- const getOverriddenValues = (prodAttributes, attrId) => {
499
- const overridenOptions = !!overridenAttributes.length
500
- ? overridenAttributes.filter((attr) => attr.id === attrId)
501
- : [];
502
- let finalOptions = [];
503
- for (const attr of prodAttributes) {
504
- let isOverridden = false;
505
- for (const ovOption of overridenOptions) {
506
- if (!isOverridden) {
507
- if (!!attr && attr.slug === ovOption.slug) {
508
- isOverridden = true;
509
- finalOptions = [
510
- ...finalOptions,
511
- Object.assign(Object.assign({}, attr), { other_details: Object.assign(Object.assign({}, attr.other_details), { image: ovOption.overriden_values }) })
512
- ];
513
- }
514
- }
515
- }
516
- if (!isOverridden) {
517
- finalOptions = [...finalOptions, attr];
518
- }
519
- }
520
- return finalOptions;
521
- };
522
- // ----------------------------------------------------------
523
- // #region colors
524
- const subColorsAttr = attributes.find((attr) => attr.id === data_1.AttributesIdEnumGR.SUBCOLOR);
525
- if (!!subColorsAttr) {
526
- const subColors = subColorsAttr.values;
527
- const colorsAttributes = subColors.filter((sub) => product_attributes.colors.includes(sub.slug));
528
- const finalColors = getOverriddenValues(colorsAttributes, data_1.AttributesIdEnumGR.SUBCOLOR);
529
- allColorOptions = (0, orderBy_1.default)(finalColors, (color) => product.declinations.findIndex((d) => d.attributes[data_1.AttributesIdEnumGR.SUBCOLOR].includes(color.slug)));
530
- }
531
- // #endregion
532
- // ----------------------------------------------------------
533
- // ----------------------------------------------------------
534
- // #region dimensions
535
- const dimensionsAttr = attributes.find((attr) => attr.id === data_1.AttributesIdEnumGR.DIMENSIONS);
536
- if (!!dimensionsAttr) {
537
- const dimensions = dimensionsAttr.values;
538
- const dimensionsAttributes = dimensions.filter((d) => product_attributes.dimensions.includes(d.slug));
539
- const finalDimensions = getOverriddenValues(dimensionsAttributes, data_1.AttributesIdEnumGR.DIMENSIONS);
540
- allDimensionOptions = finalDimensions;
541
- }
542
- // #endregion
543
- // ----------------------------------------------------------
544
- // ----------------------------------------------------------
545
- // #region formats
546
- const formatsAttr = attributes.find((attr) => attr.id === data_1.AttributesIdEnumGR.FORMATS);
547
- if (!!formatsAttr) {
548
- const formats = formatsAttr.values;
549
- allFormatOptions = formats.filter((f) => product_attributes.formats.includes(f.slug));
550
- }
551
- // #endregion
552
- // ----------------------------------------------------------
553
- return {
554
- allColors: allColorOptions,
555
- allDimensions: allDimensionOptions,
556
- allFormats: allFormatOptions
557
- };
558
- };
559
- exports.getProductFormOptions = getProductFormOptions;
560
- /**
561
- * @description Checks if product is of type by checking TYPE attribute value. Works with indexed product or cart item.
562
- * @param product
563
- * @param type
564
- * @param excludeUndefined If excludeUndefined is true, products without the "type" attribute will return true
565
- * @returns boolean
566
- */
567
- const checkIfProductIsOfType = (product, type, excludeUndefined) => {
568
- const attr = !!product && !!product.attributes ? product.attributes : {};
569
- if (!!!attr[data_1.AttributesIdEnumGR.TYPE] && !!excludeUndefined)
570
- return true;
571
- return (!!attr[data_1.AttributesIdEnumGR.TYPE] &&
572
- Array.isArray(attr[data_1.AttributesIdEnumGR.TYPE]) &&
573
- attr[data_1.AttributesIdEnumGR.TYPE].includes(type));
574
- };
575
- exports.checkIfProductIsOfType = checkIfProductIsOfType;
576
- // #endregion
577
- // ----------------------------------------------------------------------------------------------------------
578
- // ----------------------------------------------------------------------------------------------------------
579
- // #region GRASS
580
- /**
581
- * Check if provided sku/slug corresponds to a non-speciality grass item
582
- * @param sku Grass item's sku
583
- * @param slug Grass item's parent product slug
584
- * @param onlyBaseGrass Optionnal. If provided data should only be compared to base grass (aka Kentucky)
585
- */
586
- const checkIfIsNonSpecialityGrass = (sku, slug, onlyBaseGrass) => {
587
- const skusToCheck = [products_2.kentucky, ...(!onlyBaseGrass ? [products_2.prestige] : [])];
588
- const slugsToCheck = ['kentucky', ...(!onlyBaseGrass ? ['prestige'] : [])];
589
- return skusToCheck.includes(sku) || slugsToCheck.includes(slug);
590
- };
591
- exports.checkIfIsNonSpecialityGrass = checkIfIsNonSpecialityGrass;
592
- const checkIfProductIsInstallation = (item) => {
593
- return !!item.is_service && !!item.parent_slug && !!item.parent_slug.includes('installation');
594
- };
595
- exports.checkIfProductIsInstallation = checkIfProductIsInstallation;
596
- /**
597
- * Returns array of installation items found in provided array
598
- * @param items - Array of cart items or IIndexedDeclinations to check
599
- */
600
- const getAllInstallFromItems = (items) => {
601
- return items.filter((i) => (!!i.parent_slug && products_2.installationProductsSlugs.includes(i.parent_slug)) ||
602
- Object.values(products_2.installationProSpecSkus).includes(i.sku));
603
- };
604
- exports.getAllInstallFromItems = getAllInstallFromItems;
605
- /**
606
- * Function fuseGrassProducts
607
- * @description - Returns items with only one apparent grass product (used for detail customers).
608
- * ** FOR DISPLAY PURPOSES ONLY - Always save grass products separatly in ICart **
609
- * @param recursiveItems - ICartItems with subitems (object created for display purposes)
610
- */
611
- const fuseGrassProducts = (recursiveItems, isPro) => {
612
- const specialityGrass = recursiveItems[0];
613
- const kentuckyGrass = (specialityGrass.sub_items || []).find((sub) => sub.sku === products_2.kentucky || sub.parent_slug == 'kentucky');
614
- let newItems = [];
615
- if (!!kentuckyGrass) {
616
- const kentuckyPrice = (0, products_1.getLowestPrice)(kentuckyGrass);
617
- const regPriceKentucky = kentuckyGrass.regular_price.amount;
618
- const newGrassRegPrice = !!kentuckyPrice.promo ? regPriceKentucky : kentuckyPrice.price.amount;
619
- const newGrassDiscountPrice = (!!specialityGrass.discount_price
620
- ? specialityGrass.discount_price.amount
621
- : specialityGrass.regular_price.amount) +
622
- (!!kentuckyPrice.promo ? kentuckyPrice.price.amount : regPriceKentucky);
623
- const getLowestPriceSpecialityGrass = (0, products_1.getLowestPrice)(specialityGrass);
624
- newItems = [
625
- Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, specialityGrass), { regular_price: Object.assign(Object.assign({}, specialityGrass.regular_price), { amount: newGrassRegPrice + specialityGrass.regular_price.amount }) }), (!!newGrassDiscountPrice
626
- ? {
627
- discount_price: Object.assign(Object.assign({}, (specialityGrass.discount_price || { currency: 'CAD' })), { amount: newGrassDiscountPrice })
628
- }
629
- : {})), (!!specialityGrass.promo_price
630
- ? {
631
- promo_price: Object.assign(Object.assign({}, specialityGrass.promo_price), { amount: specialityGrass.promo_price.amount + kentuckyPrice.price.amount })
632
- }
633
- : {})), (!!!isPro && !!kentuckyGrass.tier_pricing
634
- ? {
635
- tier_pricing: kentuckyGrass.tier_pricing.map((t) => (Object.assign(Object.assign({}, t), { price: Object.assign(Object.assign({}, t.price), { amount: t.price.amount + getLowestPriceSpecialityGrass.price.amount }) })))
636
- }
637
- : {})), { sub_items: [
638
- Object.assign(Object.assign({}, kentuckyGrass), { hide_from_summary: true }),
639
- ...(specialityGrass.sub_items || []).slice(1)
640
- ] }),
641
- ...recursiveItems.slice(1)
642
- ];
643
- }
644
- return newItems;
645
- };
646
- exports.fuseGrassProducts = fuseGrassProducts;
647
- const isMinQtyFee = (slug) => {
648
- return ['minimum-facturable-commande', 'frais-minimum-gazon-pour-installation'].includes(slug);
649
- };
650
- exports.isMinQtyFee = isMinQtyFee;
651
- const getAllMinGrassQuantities = (grassProduct, isPro) => {
652
- return {
653
- pickup: (0, expedition_1.getMinGrassQte)(grassProduct, 'pickup', isPro),
654
- shipping: (0, expedition_1.getMinGrassQte)(grassProduct, 'shipping', isPro),
655
- install: (0, expedition_1.getMinQteInstall)(isPro)
656
- };
657
- };
658
- exports.getAllMinGrassQuantities = getAllMinGrassQuantities;
659
- const getMinQtyFeeText = (parent_slug = '', grassProduct, isPro, locale = 'fr', expeditionMethod, shortVersion) => {
660
- const type = parent_slug === 'frais-minimum-gazon-pour-installation' ? 'install' : 'order';
661
- const minQuantities = (0, exports.getAllMinGrassQuantities)(grassProduct, isPro);
662
- const localeSellUnit = (0, locale_1.translateILang)(pluralSellUnits.p2, locale);
663
- const localeStepUnit = (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)('roul'), locale).toLowerCase();
664
- const localeMinUnit = (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)('pal'), locale).toLowerCase();
665
- let str = '';
666
- const endStr = (0, locale_1.translateILang)({
667
- fr: ` Ce frais correspond au prix du gazon choisi multiplié par la différence entre la quantité choisie et le minimum.`,
668
- en: ` Ce frais correspond au prix du gazon choisi multiplié par la différence entre la quantité choisie et le minimum.`
669
- }, locale);
670
- // If expedition method not chosen yet, and pickup & shipping quantities are different, show both
671
- if (!!!expeditionMethod && type === 'order' && minQuantities.pickup !== minQuantities.shipping) {
672
- const strMinShipping = `${minQuantities.shipping}${localeSellUnit} (${minQuantities.shipping / 740} ${localeMinUnit})`;
673
- const strMinPickup = !!minQuantities.pickup
674
- ? `${minQuantities.pickup}${localeSellUnit} (${minQuantities.pickup / 740} ${localeMinUnit})`
675
- : '';
676
- str = (0, locale_1.translateILang)({
677
- fr: `Les commandes de gazon sont disponibles à partir de 10${localeSellUnit} (1 ${localeStepUnit}), mais le minimum facturable pour la livraison est de ${strMinShipping}${!!strMinPickup ? ` et de ${strMinPickup} pour la cueillette.` : ``}`,
678
- en: `Sod orders are available starting at 10${localeSellUnit} (1 ${localeStepUnit}), but the minimum chargeable for delivery is ${strMinShipping}${!!strMinPickup ? ` and ${strMinPickup} for pick-up.` : ``}`
679
- }, locale);
680
- if (!!!shortVersion) {
681
- str += endStr;
682
- }
683
- return str;
684
- }
685
- // Show specific quantity for expedition type
686
- const minBillableQty = type === 'install'
687
- ? minQuantities.install
688
- : expeditionMethod === 'pickup'
689
- ? minQuantities.pickup
690
- : minQuantities.shipping;
691
- const minQtyPallets = minBillableQty !== 0 ? minBillableQty / 740 : 0;
692
- const minBillableStr = `${minBillableQty}${localeSellUnit}${type === 'order' ? ' (' + minQtyPallets + ' ' + localeMinUnit + ')' : ''}`;
693
- str = (0, locale_1.translateILang)({
694
- fr: `${type === 'install'
695
- ? "L'installation"
696
- : expeditionMethod === 'pickup'
697
- ? 'La cueillette'
698
- : expeditionMethod === 'delivery'
699
- ? 'La livraison'
700
- : 'La commande'} de gazon est disponible à partir de 10${localeSellUnit} (1 ${localeStepUnit}), mais le minimum facturable est de ${minBillableStr}.`,
701
- en: `Sod ${type === 'install'
702
- ? 'installation'
703
- : expeditionMethod === 'pickup'
704
- ? 'pick-up'
705
- : expeditionMethod === 'delivery'
706
- ? 'delivery'
707
- : 'ordering'} is available starting at 10${localeSellUnit} (1 ${localeStepUnit}), but the minimum billable is ${minBillableStr}.`
708
- }, locale);
709
- if (!!!shortVersion) {
710
- str += endStr;
711
- }
712
- return str;
713
- };
714
- exports.getMinQtyFeeText = getMinQtyFeeText;
715
- const getMinQtyFeeAmountText = (parent_slug = '', locale = 'fr', servicesFees, showMinFeeAmount = true) => {
716
- const serviceOrFee = servicesFees.find((i) => i.parent_slug === parent_slug);
717
- if (!!!serviceOrFee)
718
- return '';
719
- const amount = (0, toNumber_1.default)(serviceOrFee.regular_price.amount) * serviceOrFee.qte;
720
- return (0, locale_1.translateILang)({
721
- fr: `Une différence de ${!!showMinFeeAmount ? amount.toFixed(2) + '$' : '%LOADER%'}%BOLD% vous sera chargée si la quantité de gazon au panier est plus petite que le minimum requis.`,
722
- en: `A difference of ${!!showMinFeeAmount ? amount.toFixed(2) + '$' : '%LOADER%'}%BOLD% will be charged if the quantity of sod in the cart is less than the minimum required.`
723
- }, locale);
724
- };
725
- exports.getMinQtyFeeAmountText = getMinQtyFeeAmountText;
726
- const getGrassQteText = (chosenDeclination, locale = 'fr') => {
727
- let txt = '';
728
- let nbRolls = 0;
729
- let nbSquareFeet = 0;
730
- const units = !!!chosenDeclination ? [] : chosenDeclination.other_units;
731
- if (!!units && !!units.length) {
732
- const itemRolls = units.find((measure) => measure.unit_slug === 'roul');
733
- const itemSquareFeet = units.find((measure) => measure.unit_slug === 'pal');
734
- if (!!itemSquareFeet && !!itemSquareFeet.fitting_unit) {
735
- nbSquareFeet = itemSquareFeet.fitting_unit;
736
- }
737
- if (!!itemRolls && !!itemRolls.fitting_unit && nbSquareFeet !== 0) {
738
- nbRolls = nbSquareFeet / itemRolls.fitting_unit;
739
- }
740
- }
741
- txt = (0, locale_1.translateILang)({
742
- fr: 'Pour ce produit, vous devez commander par pieds carrés. Une palette = *nbRolls* rouleaux (*nbSquareFeet*pi2)',
743
- en: 'For this product, you have to order by square feet. A pallet = *nbRolls* rolls (*nbSquareFeet*pi2)'
744
- }, locale);
745
- txt = txt.replace('*nbRolls*', String(nbRolls));
746
- txt = txt.replace('*nbSquareFeet*', String(nbSquareFeet));
747
- return txt;
748
- };
749
- exports.getGrassQteText = getGrassQteText;
750
- const getGrassServicesFees = async (grassProduct, isPro, useFees, expeditionMethod, fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, locale, allStores, chosenGrass, baseGrass, customPriceList) => {
751
- const installItems = await (0, exports.getInstallationArray)(grassProduct.qte, (!!baseGrass ? baseGrass : chosenGrass).product_upsells, fetchProduct, locale, isPro, chosenGrass.sku, customPriceList, { engrais: true, roulage: true });
752
- const cart = Object.assign(Object.assign({}, (0, Cart_1.getDefaultCart)()), { items: [
753
- chosenGrass,
754
- ...(!!baseGrass ? [baseGrass] : []),
755
- ...installItems.filter((item) => !!!(0, exports.isMinQtyFee)(item.parent_slug || ''))
756
- ] });
757
- const applied = await (0, exports.fetchFeesBeforeCart)(!!useFees, cart, expeditionMethod, fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, locale, allStores, isPro, grassProduct, undefined, { useStoreAddress: 'sainte-julie' }, customPriceList);
758
- return [...installItems, ...applied.itemsToAdd];
759
- };
760
- exports.getGrassServicesFees = getGrassServicesFees;
761
- const getGrassSubQuestionsByType = (type) => {
762
- if (type === 'pro') {
763
- return products_2.otherGrassSubQuestions.filter((sub) => !!sub.proOnly);
764
- }
765
- return products_2.otherGrassSubQuestions.filter((sub) => 'installation-gazon' === sub.associatedProductSlug || (!!sub.installOnly && !!!sub.proOnly));
766
- };
767
- exports.getGrassSubQuestionsByType = getGrassSubQuestionsByType;
768
- /**
769
- * @description For grass products. Over 1480pi2, if installation, quantities are rounded to rolls (10pi2) if pickup, and to half pal. if shipping
770
- * @param grassProduct
771
- * @param cartData
772
- * @returns quantity rounded to rolls with items to change or undefined
773
- */
774
- const handleGrassProductQtyRoundForShipping = (cartData, grassProduct) => {
775
- if (!!!cartData || !!!grassProduct)
776
- return;
777
- const product = cartData.items.find((item) => item.sku === grassProduct.sku);
778
- if (!!!product)
779
- return;
780
- const productOtherUnits = product.other_units;
781
- if (!!!productOtherUnits)
782
- return;
783
- // get new rounded qte
784
- const palUnit = productOtherUnits.find((u) => u.unit_slug === 'pal');
785
- const rounded = (0, exports.roundGrassQte)(product.qte, !!!cartData.is_pickup, palUnit);
786
- if (!!!rounded || rounded === grassProduct.qte)
787
- return;
788
- // ajust items with new quantity
789
- let itemsToChange = [];
790
- const recursiveGrassItem = (0, cart_1.getRecursiveItems)(cartData.items).find((item) => item.sku === grassProduct.sku);
791
- const getItemsToChange = (item) => {
792
- if (!!item.sub_items) {
793
- item.sub_items.forEach((subItem) => getItemsToChange(subItem));
794
- }
795
- if (item.parent_slug === 'frais-de-mobilisation') {
796
- const totalPallet = (0, expedition_1.getPalletQty)(cartData.items.map((i) => {
797
- if ((0, exports.checkIfProductIsOfType)(i, 'gazon')) {
798
- return Object.assign(Object.assign({}, i), { qte: rounded });
799
- }
800
- return i;
801
- }), 'grass');
802
- itemsToChange.push({
803
- sku: item.sku,
804
- qte: (0, ceil_1.default)(totalPallet / expedition_1.installationFeePalletTier)
805
- });
806
- return;
807
- }
808
- if (!!item.is_upsell_of_sku) {
809
- const parentUpsellProd = cartData.items.find((i) => i.sku === item.is_upsell_of_sku);
810
- if (!!parentUpsellProd) {
811
- const sameUpsell = (parentUpsellProd.product_upsells || []).find((up) => up.recommendation_sku === item.sku);
812
- if (!!sameUpsell) {
813
- const anUpsellProduct = Object.assign(Object.assign(Object.assign(Object.assign({}, item), { parent_slug: sameUpsell.recommendation_parent_slug, recommended_qte: sameUpsell.recommendation_qty, recommended_sku: sameUpsell.recommendation_sku, matching_qte: !!sameUpsell.matching_qty, auto_add: sameUpsell.auto_add, auto_add_exceptions: sameUpsell.auto_add_exceptions, actual_qte: sameUpsell.actual_qty }), (!!sameUpsell.is_recommendation ? { is_recommendation: true } : {})), (!!sameUpsell.show_recommendation_msg ? { show_recommendation_msg: true } : {}));
814
- const ratio = (0, upsells_1.calculateUpsellQte)(anUpsellProduct, rounded);
815
- if (!!ratio) {
816
- itemsToChange.push({
817
- sku: item.sku,
818
- qte: ratio
819
- });
820
- return;
821
- }
822
- }
823
- }
824
- }
825
- itemsToChange.push({
826
- sku: item.sku,
827
- qte: rounded
828
- });
829
- return;
830
- };
831
- if (!!recursiveGrassItem) {
832
- getItemsToChange(recursiveGrassItem);
833
- }
834
- return { rounded, itemsToChange };
835
- };
836
- exports.handleGrassProductQtyRoundForShipping = handleGrassProductQtyRoundForShipping;
837
- /**
838
- * Function roundGrassQte
839
- * @description Returns rounded grass quantity depending on current qty, if customer selected installation and pallet unit (if defined)
840
- * @param currentQte {number} - Current quantity as entered by user in input
841
- * @param isShipping {boolean} - Whether customer has selected installation option
842
- * @param palUnit {IFilledDimensionUnits | undefined} - Pallet FilledDimensionUnit (possibly undefined)
843
- */
844
- const roundGrassQte = (currentQte, isShipping, palUnit) => {
845
- let newQte = currentQte;
846
- switch (true) {
847
- case currentQte < 1480:
848
- const rest1480 = currentQte % 10;
849
- if (rest1480 !== 0) {
850
- newQte = currentQte - rest1480 + 10;
851
- }
852
- break;
853
- case currentQte >= 1480 && !!!isShipping:
854
- const rest1480Install = currentQte % 10;
855
- if (rest1480Install !== 0) {
856
- newQte = currentQte - rest1480Install + 10;
857
- }
858
- break;
859
- case currentQte >= 1480:
860
- if (!!palUnit && !!palUnit.fitting_unit) {
861
- let rest1480 = currentQte % palUnit.fitting_unit;
862
- if (rest1480 !== 0 && !!((rest1480 - 400) % palUnit.fitting_unit)) {
863
- newQte = currentQte - rest1480;
864
- if (newQte + 400 > currentQte) {
865
- newQte = newQte + 400;
866
- }
867
- else if (newQte + palUnit.fitting_unit > currentQte) {
868
- newQte = newQte + palUnit.fitting_unit;
869
- }
870
- }
871
- }
872
- break;
873
- }
874
- return newQte;
875
- };
876
- exports.roundGrassQte = roundGrassQte;
877
- /**
878
- * Detects if customer has "Installation tout inclus".
879
- * @param customPriceList - Customer custom price list
880
- * @return All inclusive installation if exists, undefined otherwise
881
- */
882
- const getInstallationAllInclusiveFromPriceList = (customPriceList) => {
883
- if (!!!customPriceList || !!!customPriceList.length)
884
- return;
885
- const item = customPriceList.find((i) => i.sku === products_2.installationAllInclusiveSku);
886
- const active = !!item && !!item.price;
887
- if (!active)
888
- return;
889
- return item;
890
- };
891
- exports.getInstallationAllInclusiveFromPriceList = getInstallationAllInclusiveFromPriceList;
892
- /**
893
- * Checks if all-inclusive installation is active.
894
- * @param hasInstallation - Whether the cart/form contains an installation
895
- * @param isPro - Whether the customer is a pro
896
- * @param customPriceList - Customer custom price list
897
- * @returns true if all-inclusive installation is active
898
- */
899
- const isInstallAllInclusiveActive = (hasInstallation, isPro, customPriceList) => {
900
- return !!hasInstallation && !!isPro && !!(0, exports.getInstallationAllInclusiveFromPriceList)(customPriceList);
901
- };
902
- exports.isInstallAllInclusiveActive = isInstallAllInclusiveActive;
903
- /**
904
- * Force )$ to kentucky base grass and sod delivery fee if install all-inclusive.
905
- * @param item - The cart item to potentially override
906
- * @returns The item with zeroed price if applicable, or the original item
907
- */
908
- const applyAllInclusiveOverrides = (item) => {
909
- const isKentucky = item.parent_slug === 'kentucky' || item.sku === products_2.kentucky;
910
- const isSodDelivery = item.parent_slug === 'livraison-gazon' && products_2.sodDeliverySkus.includes(item.sku);
911
- if (isKentucky || isSodDelivery) {
912
- return Object.assign(Object.assign({}, item), { regular_price: Object.assign(Object.assign({}, item.regular_price), { amount: 0 }), discount_price: null, promo_price: null, price_override: true });
913
- }
914
- return item;
915
- };
916
- exports.applyAllInclusiveOverrides = applyAllInclusiveOverrides;
917
- // Determines if a cart item should be hidden from checkout display. Used for all-inclusive installation
918
- const shouldHideItemInCheckout = (item, allItems) => {
919
- const hasAllInclusive = allItems.some((i) => i.sku === products_2.installationAllInclusiveSku);
920
- if (!hasAllInclusive)
921
- return false;
922
- if (item.regular_price.amount !== 0)
923
- return false;
924
- // Hide installation upsells at $0 (mobilisation, fertilisation, roulage, etc.)
925
- const installationSkus = allItems.filter((i) => i.parent_slug === 'installation-gazon').map((i) => i.sku);
926
- if (!!item.is_upsell_of_sku && installationSkus.includes(item.is_upsell_of_sku))
927
- return true;
928
- // Hide sod delivery at $0
929
- if (item.parent_slug === 'livraison-gazon')
930
- return true;
931
- // Hide installation surcharges at $0 (e.g. surcharge mobilisation île de Montréal)
932
- if (item.parent_slug === 'surcharges-installation-gazon')
933
- return true;
934
- return false;
935
- };
936
- exports.shouldHideItemInCheckout = shouldHideItemInCheckout;
937
- // Check si la surcharge carburant match l'item
938
- const matchesFuelSurchargeParent = (surchargeSku, item) => {
939
- switch (surchargeSku) {
940
- case products_2.fuelSurchargeGazonSku:
941
- return item.sku === products_2.kentucky || item.parent_slug === 'kentucky';
942
- case products_2.fuelSurchargeLivraisonSku:
943
- return (!!item.parent_slug &&
944
- ['livraison-gazon', 'livraison-beton-accessoires'].includes(item.parent_slug));
945
- case products_2.fuelSurchargeMobilisationSku:
946
- return item.parent_slug === 'frais-de-mobilisation';
947
- default:
948
- return false;
949
- }
950
- };
951
- exports.matchesFuelSurchargeParent = matchesFuelSurchargeParent;
952
- const getInstallationArray = async (qte, baseGrassUpsells, fetchProduct, locale, isPro, chosenSku, customPriceList, returnOtherFees) => {
953
- var _a;
954
- const upsell = baseGrassUpsells;
955
- if (!!!upsell)
956
- return [];
957
- const installation_upsell = upsell.filter((upsell) => upsell.recommendation_parent_slug === 'installation-gazon');
958
- const installation_parent = await fetchProduct('installation-gazon', locale, true, true);
959
- let installation_decli;
960
- const minQteInstall = (0, expedition_1.getMinQteInstall)(isPro);
961
- // Variable pour vérifier si une déclinaison d'installation existe déjà dans le cart
962
- // ** Utile pour la modification des items du cart, vu que la props is_upsell_of_sku ne peut pas se modifier on update
963
- let arrayFinal = [];
964
- if (!!installation_parent && !!installation_upsell && !!installation_upsell.length) {
965
- let installation_array = [];
966
- if (!!isPro) {
967
- installation_array = installation_parent.declinations.filter((decli) => !!decli.attributes &&
968
- !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE] &&
969
- !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE].includes('pro'));
970
- }
971
- else {
972
- installation_array = installation_parent.declinations.filter((decli) => !!decli.attributes &&
973
- !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE] &&
974
- !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE].includes('au-detail'));
975
- }
976
- const installation_qte_array = installation_upsell.filter((upsell) => installation_array.find((decli) => decli.sku === upsell.recommendation_sku));
977
- const closestQte = (0, maxBy_1.default)(installation_qte_array.filter((upsell) => {
978
- return upsell.actual_qty <= qte;
979
- }), 'actual_qty');
980
- // MODIFS. FRAIS 2024 - On n'ajoute pas les frais au panier si leur prix régulier est de 0.00$
981
- // Vérification faite à chaque ajout de déclinaison au arrayFinal
982
- if (!!closestQte) {
983
- installation_decli = installation_parent.declinations.find((decli) => decli.sku === closestQte.recommendation_sku);
984
- // Check if customer has installation all-inclusive
985
- const allInclusivePriceItem = !!isPro && !!customPriceList ? (0, exports.getInstallationAllInclusiveFromPriceList)(customPriceList) : undefined;
986
- if (!!installation_decli) {
987
- const allInclusiveDecli = !!allInclusivePriceItem && !!installation_parent
988
- ? installation_parent.declinations.find((d) => d.sku === allInclusivePriceItem.sku)
989
- : undefined;
990
- if (!!allInclusivePriceItem && !!allInclusiveDecli) {
991
- const priceAmount = (_a = allInclusivePriceItem.price) !== null && _a !== void 0 ? _a : allInclusivePriceItem.reg;
992
- installation_decli = Object.assign(Object.assign({}, allInclusiveDecli), { regular_price: Object.assign(Object.assign({}, allInclusiveDecli.regular_price), { amount: priceAmount }) });
993
- }
994
- else {
995
- if (!!isPro && !!customPriceList) {
996
- installation_decli = (0, g2_1.checkForCustomPriceEquivalent)(installation_decli, customPriceList);
997
- }
998
- }
999
- // Add the correct installation option depending on whether the customer has "Installation tout inclus"
1000
- if (!(0, exports.shouldHideItemIfRegPriceIs0)(installation_decli, installation_parent.slug)) {
1001
- arrayFinal.push(Object.assign(Object.assign({}, installation_decli), { parent_slug: 'installation-gazon', qte: qte, is_upsell_of_sku: chosenSku, product_upsells: installation_parent.product_upsells }));
1002
- }
1003
- }
1004
- // Frais minimum d'installation
1005
- if (qte < minQteInstall) {
1006
- const minimum_installation_fee = await fetchProduct('frais-minimum-gazon-pour-installation', locale, true, true);
1007
- if (!!minimum_installation_fee) {
1008
- let minInstallDecli = minimum_installation_fee.declinations[0];
1009
- minInstallDecli = Object.assign(Object.assign({}, minInstallDecli), { regular_price: Object.assign(Object.assign({}, minInstallDecli.regular_price), { amount: installation_decli.regular_price.amount }) });
1010
- if (!!isPro && !!customPriceList) {
1011
- minInstallDecli = (0, g2_1.checkForCustomPriceEquivalent)(Object.assign(Object.assign({}, minInstallDecli), { price_override: true }), customPriceList);
1012
- }
1013
- if (!(0, exports.shouldHideItemIfRegPriceIs0)(minInstallDecli, minimum_installation_fee.slug)) {
1014
- arrayFinal.push(Object.assign(Object.assign({}, minInstallDecli), { parent_slug: 'frais-minimum-gazon-pour-installation', qte: minQteInstall - qte, is_upsell_of_sku: installation_decli.sku, price_override: true }));
1015
- }
1016
- }
1017
- }
1018
- // Frais de mobilisation (pour l'installation)
1019
- const mobilisation_fee = await fetchProduct('frais-de-mobilisation', locale, true, true);
1020
- if (!!mobilisation_fee && !!isPro) {
1021
- let mobilisationDecli = mobilisation_fee.declinations[0];
1022
- if (!!customPriceList) {
1023
- mobilisationDecli = (0, g2_1.checkForCustomPriceEquivalent)(mobilisationDecli, customPriceList);
1024
- }
1025
- if (!(0, exports.shouldHideItemIfRegPriceIs0)(mobilisationDecli, mobilisation_fee.slug, true)) {
1026
- arrayFinal.push(Object.assign(Object.assign({}, mobilisationDecli), { parent_slug: 'frais-de-mobilisation', qte: (0, ceil_1.default)(qte > minQteInstall
1027
- ? qte / (740 * expedition_1.installationFeePalletTier)
1028
- : minQteInstall / (740 * expedition_1.installationFeePalletTier)), is_upsell_of_sku: installation_decli.sku, product_upsells: mobilisation_fee.product_upsells }));
1029
- }
1030
- }
1031
- // -----------------------------------------------------------------------
1032
- // AUTRES FRAIS CONNEXES
1033
- if (!!returnOtherFees) {
1034
- if (!!returnOtherFees.engrais) {
1035
- // fertilisation
1036
- const fertilisation = await fetchProduct('installation-fertilisation', locale, true, true);
1037
- if (!!fertilisation) {
1038
- let minFertilisationDecli = fertilisation.declinations[0];
1039
- if (!!isPro && !!customPriceList) {
1040
- minFertilisationDecli = (0, g2_1.checkForCustomPriceEquivalent)(minFertilisationDecli, customPriceList);
1041
- }
1042
- if (!(0, exports.shouldHideItemIfRegPriceIs0)(minFertilisationDecli, fertilisation.slug, true)) {
1043
- arrayFinal.push(Object.assign(Object.assign({}, minFertilisationDecli), { parent_slug: fertilisation.slug, qte: qte < minQteInstall ? minQteInstall : qte, is_upsell_of_sku: installation_decli.sku, product_upsells: fertilisation.product_upsells }));
1044
- }
1045
- }
1046
- }
1047
- if (returnOtherFees.roulage) {
1048
- // roullage
1049
- const roullage = await fetchProduct('installation-roulage', locale, true, true);
1050
- if (!!roullage) {
1051
- let minRoulageDecli = roullage.declinations[0];
1052
- if (!!isPro && !!customPriceList) {
1053
- minRoulageDecli = (0, g2_1.checkForCustomPriceEquivalent)(minRoulageDecli, customPriceList);
1054
- }
1055
- if (!(0, exports.shouldHideItemIfRegPriceIs0)(minRoulageDecli, roullage.slug, true)) {
1056
- arrayFinal.push(Object.assign(Object.assign({}, minRoulageDecli), { parent_slug: roullage.slug, qte: qte < minQteInstall ? minQteInstall : qte, is_upsell_of_sku: installation_decli.sku, product_upsells: roullage.product_upsells }));
1057
- }
1058
- }
1059
- }
1060
- }
1061
- }
1062
- }
1063
- return arrayFinal;
1064
- };
1065
- exports.getInstallationArray = getInstallationArray;
1066
- const getInstallItemPrice = (parentSlug, servicesFees) => {
1067
- let price = 0;
1068
- switch (parentSlug) {
1069
- case 'installation-gazon':
1070
- const itemsToUse = servicesFees.filter((i) => i.parent_slug && ['installation-gazon', 'frais-de-mobilisation'].includes(i.parent_slug));
1071
- if (!!itemsToUse) {
1072
- price = (0, sumBy_1.default)(itemsToUse, (item) => (0, products_1.getLowestPrice)(item).price.amount * item.qte);
1073
- }
1074
- break;
1075
- default:
1076
- const itemToUse = servicesFees.find((i) => i.parent_slug === parentSlug);
1077
- if (!!itemToUse) {
1078
- price = (0, products_1.getLowestPrice)(itemToUse).price.amount * itemToUse.qte;
1079
- }
1080
- break;
1081
- }
1082
- return price;
1083
- };
1084
- exports.getInstallItemPrice = getInstallItemPrice;
1085
- // #endregion
1086
- // ----------------------------------------------------------------------------------------------------------
1087
- // ----------------------------------------------------------------------------------------------------------
1088
- // #region CONCRETE
1089
- const getConcreteQteText = (declination, locale = 'fr') => {
1090
- let txt = '';
1091
- if (!!!declination)
1092
- return txt;
1093
- let nbSaleUnitsPerCmdStep = 0;
1094
- let nbUnitsPerPal = 0;
1095
- const other_units = declination.other_units;
1096
- if (!!!other_units || !!!other_units.length) {
1097
- return '';
1098
- }
1099
- else {
1100
- const commandStep = other_units.find((unit) => unit.is_command_step);
1101
- const commandUnit = other_units.find((unit) => unit.is_command_unit);
1102
- const saleUnit = other_units.find((unit) => unit.is_sale_unit);
1103
- const unitsPerPal = other_units.find((unit) => unit.unit_slug === 'pal');
1104
- if (!!commandStep &&
1105
- !!commandStep.fitting_unit &&
1106
- !!commandUnit &&
1107
- !!commandUnit.fitting_unit &&
1108
- !!saleUnit &&
1109
- !!saleUnit.fitting_unit &&
1110
- !!unitsPerPal &&
1111
- !!unitsPerPal.fitting_unit) {
1112
- const cmdSameAsSale = commandStep.unit_slug === saleUnit.unit_slug;
1113
- const nbP2PerRgSlug = !!cmdSameAsSale ? commandUnit.unit_slug : saleUnit.unit_slug;
1114
- nbSaleUnitsPerCmdStep = !!cmdSameAsSale
1115
- ? commandStep.fitting_unit / commandUnit.fitting_unit
1116
- : commandStep.fitting_unit / saleUnit.fitting_unit;
1117
- // Round at correct decimals for products where commandStep.fitting_unit is 1 (meaning value calculated before is correct sell units per step)
1118
- nbUnitsPerPal =
1119
- commandStep.fitting_unit == 1 && !!!commandStep.is_sale_unit
1120
- ? unitsPerPal.fitting_unit *
1121
- (0, round_1.default)(nbSaleUnitsPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0)
1122
- : unitsPerPal.fitting_unit / saleUnit.fitting_unit;
1123
- txt = (0, locale_1.translateILang)({
1124
- fr: 'Pour ce produit, vous devez commander par *cmdStep* (*nbUnitsPerCmdStep*).',
1125
- en: 'For this product, you have to order by *cmdStep* (*nbUnitsPerCmdStep*).'
1126
- }, locale);
1127
- if (unitsPerPal.unit_slug != commandStep.unit_slug) {
1128
- txt += (0, locale_1.translateILang)({
1129
- fr: ' Une palette = *nbUnitsPerPal*.',
1130
- en: ' A pallet = *nbUnitsPerPal*.'
1131
- }, locale);
1132
- }
1133
- txt = txt.replace('*cmdStep*', String(`${(0, locale_1.translateILang)(inventories_1.unitDict[commandStep.unit_slug], locale).toLowerCase()}`));
1134
- txt = txt.replace('*nbUnitsPerCmdStep*', String(`${(0, round_1.default)(nbSaleUnitsPerCmdStep, 2)} ${(0, locale_1.translateILang)(inventories_1.unitDict[nbP2PerRgSlug], locale).toLowerCase()}`));
1135
- txt = txt.replace('*nbUnitsPerPal*', String(`${(0, round_1.default)(nbUnitsPerPal, 2)} ${(0, locale_1.translateILang)(inventories_1.unitDict[saleUnit.unit_slug], locale).toLowerCase()}`));
1136
- }
1137
- else {
1138
- return '';
1139
- }
1140
- }
1141
- return txt;
1142
- };
1143
- exports.getConcreteQteText = getConcreteQteText;
1144
- /**
1145
- * @description returns all items in cart where attribute AVAILABILITY contains wanted type.
1146
- * @param cartData
1147
- * @param availabilityType
1148
- */
1149
- const getConcreteItemsByAvailability = (cartData, availabilityType, returnTrueIfUndefined) => {
1150
- return cartData.items.filter((i) => {
1151
- return ((i.attributes[data_1.AttributesIdEnumGR.AVAILABILITY] &&
1152
- i.attributes[data_1.AttributesIdEnumGR.AVAILABILITY][0] === availabilityType) ||
1153
- !!returnTrueIfUndefined);
1154
- });
1155
- };
1156
- exports.getConcreteItemsByAvailability = getConcreteItemsByAvailability;
1157
- // #endregion
1158
- // ----------------------------------------------------------------------------------------------------------
1159
- // ----------------------------------------------------------------------------------------------------------
1160
- // #region VRAC
1161
- /**
1162
- * Function getVracType - constructs vrac helper object is cart contains vrac or vrac associated items.
1163
- * @param stores
1164
- * @param cartData
1165
- * @param getInventoryItemCallback
1166
- * @param inventoryItemArray
1167
- * @returns IVracType object containing vrac_type enum value and vrac_store_ids where vrac items are available
1168
- */
1169
- const getVracType = async (stores, cartData, getInventoryItemCallback, inventoyItemArray) => {
1170
- const items = cartData.items;
1171
- // If cart does not contain vrac or vrac-agacent accessories (.is_other_type==='vrac)), return
1172
- if (!!!items ||
1173
- !!!items.length ||
1174
- (!!!(0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.VRAC, cartData) &&
1175
- !!!cartData.items.find((item) => !!item.is_other_type && item.is_other_type === 'vrac')))
1176
- return;
1177
- let allStoreIds = stores.map((store) => store.id);
1178
- let itemFormat = '';
1179
- await Promise.all(items.map(async (item) => {
1180
- const productInventory = !!!item.is_service
1181
- ? !!inventoyItemArray && !!inventoyItemArray.length
1182
- ? inventoyItemArray.find((i) => i.sku === item.sku)
1183
- : await getInventoryItemCallback(item.sku)
1184
- : undefined;
1185
- if (!!!productInventory)
1186
- return;
1187
- allStoreIds = allStoreIds.filter((id) => {
1188
- const sameStoreInProdInventory = productInventory.inventories.find((i) => i.store_id === id);
1189
- if (!!!sameStoreInProdInventory)
1190
- return true;
1191
- return !!!sameStoreInProdInventory.unavailable_in_store;
1192
- });
1193
- if (!!!itemFormat && !!item.attributes && !!item.attributes[data_1.AttributesIdEnumGR.FORMATS]) {
1194
- itemFormat = item.attributes[data_1.AttributesIdEnumGR.FORMATS][0];
1195
- }
1196
- }));
1197
- const onlySteJulieNobel = allStoreIds.length === 1 && allStoreIds[0] === 'sainte-julie-nobel';
1198
- if (!!itemFormat.includes('sac')) {
1199
- return {
1200
- vrac_type: !!onlySteJulieNobel ? products_3.VracTypeEnum.NOBEL_SAC : products_3.VracTypeEnum.AUTRE_SAC,
1201
- vrac_store_ids: allStoreIds
1202
- };
1203
- }
1204
- else {
1205
- return {
1206
- vrac_type: !!onlySteJulieNobel ? products_3.VracTypeEnum.NOBEL_TONNE : products_3.VracTypeEnum.AUTRE_TONNE,
1207
- vrac_store_ids: allStoreIds
1208
- };
1209
- }
1210
- };
1211
- exports.getVracType = getVracType;
1212
- // #endregion
1213
- // ----------------------------------------------------------------------------------------------------------
1214
- // ----------------------------------------------------------------------------------------------------------
1215
- // #region FEES
1216
- /**
1217
- * Get all possible fees for a cart with basic info, to show approx. fee total before all data is saved in cart
1218
- *
1219
- * @param useFees If local fee array should be used, to save database calls
1220
- * @param newCart Current cart data
1221
- * @param deliveryType If fees should be checked for a pick-up or shipping order
1222
- * @param fetchProduct Callback function for product fetch
1223
- * @param getIfAddressIsInsideZones Callback function for zone check
1224
- * @param getDistanceFromAddress Callback function to check distance with provided address
1225
- * @param locale User's locale (fr or en)
1226
- * @param allStores Full store array for space
1227
- * @param isPro If customer associated with cart is a pro customer
1228
- * @param grassProduct Constructed grass product from cart (with extra data for checks)
1229
- * @param concreteOrder Constructed concrete products from cart (with extra data for checks)
1230
- * @param settings.addOnePalletToPickup Optionnal - If additionnal pal. should be added for order
1231
- * @param settings.saveToShippingPayload Optional - If data collected should be saved to cart's shipping_payload
1232
- * @param settings.useStoreAddress Optionnal - Provided store ID for which the address should be used for check
1233
- * @param settings.useDeliveryAddress Optionnal - If current carts shipping address should be used for check
1234
- * @param settings.useAvailableVracStores Optionnal - Provided array of store IDs available for vrac order
1235
- * @param customPriceList Optionnal - If pro customer with G2 custom price list and custom prices should be checked
1236
- */
1237
- const fetchFeesBeforeCart = async (useFees, newCart, deliveryType, fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, locale, allStores, isPro, grassProduct, concreteOrder, settings, customPriceList) => {
1238
- const cartContainsVrac = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.VRAC, newCart);
1239
- const cartContainsInstallation = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.INSTALLATION, newCart);
1240
- const cartContainsSample = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.SAMPLE, newCart);
1241
- const cartContainsAccessoriesOnly = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.ONLY_ACCESSORIES, newCart);
1242
- const storeToUse = !!settings && !!settings.useStoreAddress ? allStores.find((s) => s.id == settings.useStoreAddress) : undefined;
1243
- const storeAddressToUse = !!storeToUse ? storeToUse.address : undefined;
1244
- return await (0, expedition_1.applyFeesToCart)(fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, newCart, deliveryType, grassProduct, concreteOrder, deliveryType === 'pickup' ? false : cartContainsInstallation, cartContainsVrac, (0, object_1.recursiveCheckObject)(settings, 'useAvailableVracStores'), isPro, deliveryType === 'pickup' ? !!settings && !!settings.addOnePalletToPickup : false, cartContainsSample, !!settings ? !!settings.saveToShippingPayload : false, !!!settings
1245
- ? undefined
1246
- : !!settings.useStoreAddress && !!storeAddressToUse
1247
- ? storeAddressToUse
1248
- : !!settings.useDeliveryAddress && !!newCart.shipping_address
1249
- ? newCart.shipping_address.address
1250
- : undefined, locale, undefined, false, cartContainsAccessoriesOnly, undefined, allStores, customPriceList, !!useFees);
1251
- };
1252
- exports.fetchFeesBeforeCart = fetchFeesBeforeCart;
1253
- // #endregion
1254
- // ----------------------------------------------------------------------------------------------------------
1255
- // ----------------------------------------------------------------------------------------------------------
1256
- // #region PRO SPECIFICITIES
1257
- /**
1258
- * Check if pro custom promo info should be shown for customer for a specific product.
1259
- * @param userData
1260
- * @param isPro
1261
- * @param product
1262
- * @param customMinPrice
1263
- */
1264
- const shouldShowProCustomPromo = (userData, isPro, product, customMinPrice) => {
1265
- if (!!!product || !!!isPro || !!!userData)
1266
- return false;
1267
- // If customMinPrice is defined (meaning customer has custom price list), and the price type is not REG or has type NET, always return true
1268
- if (!!customMinPrice) {
1269
- if (customMinPrice.type === G2_1.CustomPriceItemTypeEnum.REG && customMinPrice.code2 !== 'NET')
1270
- return false;
1271
- return true;
1272
- }
1273
- // Check customer group. If promo exists and should apply for customer group, return true
1274
- const customerGroup = (0, object_1.recursiveCheckObject)(userData, 'userData.basic_info.customer_professionnal_info.external_customer_group');
1275
- const customerType = !!customerGroup ? (0, g2_1.getG2CustomerTypeFromCode)(customerGroup) : undefined;
1276
- const prodPriceClass = !!product.price_classes_range
1277
- ? product.price_classes_range.find((range) => !!customerType && range.external_slug ? range.external_slug === customerType : range.class === 'aspirant')
1278
- : !!product.prices_list
1279
- ? product.prices_list.find((range) => !!customerType && range.external_slug ? range.external_slug === customerType : range.group_id === 'aspirant')
1280
- : undefined;
1281
- return !!prodPriceClass && !!prodPriceClass.custom_promo_applies;
1282
- };
1283
- exports.shouldShowProCustomPromo = shouldShowProCustomPromo;
1284
- const applyProCustomPromo = (decli, userData) => {
1285
- const customerCode = userData.basic_info.customer_professionnal_info &&
1286
- userData.basic_info.customer_professionnal_info.external_customer_group;
1287
- if (!!!customerCode)
1288
- return {};
1289
- const customerCustomPromo = (0, g2_1.getG2DiscountFromCode)(customerCode);
1290
- if (!!!customerCustomPromo)
1291
- return {};
1292
- const regPrice = decli.regular_price.amount;
1293
- const newDiscountAmount = (0, toNumber_1.default)(regPrice) * ((100 - customerCustomPromo) / 100);
1294
- let newPromoObj = (0, IDiscountRule_1.getDefaultDiscountRule)('product');
1295
- newPromoObj = Object.assign(Object.assign({}, newPromoObj), { appliesTo: Object.assign(Object.assign({}, newPromoObj.appliesTo), { label: IDiscountRule_1.AppliesToEnum.PRODUCT, value: decli.sku }), rules: [
1296
- {
1297
- field: IDiscountRule_1.RuleFieldEnum.CUSTOMER,
1298
- condition: IDiscountRule_1.RuleConditionEnum.AND,
1299
- ruleDetails: [
1300
- {
1301
- operator: '==',
1302
- value: [userData.id],
1303
- condition: IDiscountRule_1.RuleConditionEnum.AND
1304
- }
1305
- ]
1306
- }
1307
- ], result: {
1308
- action: IDiscountRule_1.ResultActionEnum.PERCENT,
1309
- action_value: customerCustomPromo
1310
- } });
1311
- return {
1312
- discount_rules: [newPromoObj],
1313
- promo_price: {
1314
- currency: 'CAD',
1315
- amount: (0, round_1.default)(newDiscountAmount, 3)
1316
- }
1317
- };
1318
- };
1319
- exports.applyProCustomPromo = applyProCustomPromo;
1320
- // Indexed products - Custom prices if pro
1321
- const getFormattedProdGR = (decli, productSlug, isPro) => {
1322
- const { promo_price, discount_price, tier_pricing } = decli, rest = __rest(decli, ["promo_price", "discount_price", "tier_pricing"]);
1323
- return !!isPro ? Object.assign(Object.assign({}, rest), (productSlug !== 'kentucky' ? { tier_pricing } : {})) : decli;
1324
- };
1325
- exports.getFormattedProdGR = getFormattedProdGR;
1326
- /**
1327
- * Checks if a 0.00$ reg_price item should be considered "hidden" or not.
1328
- * @param item - The indexedDecli or cartItem to check
1329
- * @param productSlug - The parent product's slug (in case it is not found in item)
1330
- * @param isUpsellOfInstallProd - Optionnal. If item is upsell of install product (additionnal fee for installation)
1331
- */
1332
- const shouldHideItemIfRegPriceIs0 = (item, productSlug, isUpsellOfInstallProd) => {
1333
- // A. Check if reg price is 0. If not, should not hide item
1334
- const regPriceIs0 = item.regular_price.amount == 0;
1335
- if (!regPriceIs0)
1336
- return false;
1337
- // B. Check if item is fee or service. If not, should not hide item
1338
- if (!item.is_service)
1339
- return false;
1340
- // C. Check if item is an upsell of an installation product (additionnal install fees). If so, should not hide item
1341
- if (!!isUpsellOfInstallProd)
1342
- return false;
1343
- // D. Check if item is a shipping fee. If so, should not hide item
1344
- if (expedition_1.slugsToCheckFromExpeditionFees.shipping.includes(productSlug))
1345
- return false;
1346
- return true;
1347
- };
1348
- exports.shouldHideItemIfRegPriceIs0 = shouldHideItemIfRegPriceIs0;
1349
- // #endregion
1350
- // ----------------------------------------------------------------------------------------------------------
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.shouldHideItemIfRegPriceIs0 = exports.getFormattedProdGR = exports.applyProCustomPromo = exports.shouldShowProCustomPromo = exports.fetchFeesBeforeCart = exports.getVracType = exports.getConcreteItemsByAvailability = exports.getConcreteQteText = exports.getInstallItemPrice = exports.getInstallationArray = exports.matchesFuelSurchargeParent = exports.shouldHideItemInCheckout = exports.applyAllInclusiveOverrides = exports.isInstallAllInclusiveActive = exports.getInstallationAllInclusiveFromPriceList = exports.roundGrassQte = exports.handleGrassProductQtyRoundForShipping = exports.getGrassSubQuestionsByType = exports.getGrassServicesFees = exports.getGrassQteText = exports.getMinQtyFeeAmountText = exports.getMinQtyFeeText = exports.getAllMinGrassQuantities = exports.isMinQtyFee = exports.fuseGrassProducts = exports.getAllInstallFromItems = exports.checkIfProductIsInstallation = exports.checkIfIsNonSpecialityGrass = exports.checkIfProductIsOfType = exports.getProductFormOptions = exports.getParentProductCategoryGroup = exports.getProdName = exports.splitOnDashes = exports.getRoundedUnitProductQuantities = exports.getRoundedSellUnitProductQuantities = exports.getDescriptionString = exports.getDescriptionLength = exports.getProductAttributes = exports.productUnitSupportsDecimals = exports.getCorrectPluralSellUnit = exports.getPluralUnitLabelWithSlug = exports.getUnitLabelWithSlug = exports.getProductUnitLabel = exports.getProductSellUnitLabel = void 0;
18
+ const ceil_1 = __importDefault(require("lodash/ceil"));
19
+ const maxBy_1 = __importDefault(require("lodash/maxBy"));
20
+ const orderBy_1 = __importDefault(require("lodash/orderBy"));
21
+ const toNumber_1 = __importDefault(require("lodash/toNumber"));
22
+ const round_1 = __importDefault(require("lodash/round"));
23
+ const flatten_1 = __importDefault(require("lodash/flatten"));
24
+ const uniqBy_1 = __importDefault(require("lodash/uniqBy"));
25
+ const sumBy_1 = __importDefault(require("lodash/sumBy"));
26
+ const floor_1 = __importDefault(require("lodash/floor"));
27
+ const Cart_1 = require("../../../Interfaces/Cart");
28
+ const G2_1 = require("../../../Interfaces/G2");
29
+ const IDiscountRule_1 = require("../../../Interfaces/Rules/IDiscountRule");
30
+ // General utils
31
+ const string_1 = require("../../../utils/string");
32
+ const locale_1 = require("../../../utils/locale");
33
+ const inventories_1 = require("../../../utils/inventories");
34
+ const products_1 = require("../../../utils/products");
35
+ // Specitic utils
36
+ const expedition_1 = require("./expedition");
37
+ const products_2 = require("../constants/products");
38
+ const g2_1 = require("./g2");
39
+ const cart_1 = require("./cart");
40
+ // Specific interfaces
41
+ const products_3 = require("../interfaces/products");
42
+ const data_1 = require("../interfaces/data");
43
+ const cart_2 = require("../interfaces/cart");
44
+ const upsells_1 = require("./upsells");
45
+ const object_1 = require("../../../utils/object");
46
+ // ----------------------------------------------------------------------------------------------------------
47
+ // #region PRODUCT UNITS
48
+ const pluralSellUnits = {
49
+ p2: { fr: 'pi²', en: 'sqft' },
50
+ sac: { fr: 'sacs', en: 'bags' },
51
+ unite: { fr: 'unités', en: 'units' },
52
+ tonne: { fr: 'tonnes', en: 'tons' },
53
+ rouleau: { fr: 'rouleaux', en: 'rolls' }
54
+ };
55
+ const pluralSellUnitsBySlug = {
56
+ p2: { fr: 'pi²', en: 'sqft' },
57
+ sac: { fr: 'sacs', en: 'bags' },
58
+ unite: { fr: 'unités', en: 'units' },
59
+ tonne: { fr: 'tonnes', en: 'tons' },
60
+ roul: { fr: 'rouleaux', en: 'rolls' },
61
+ pal: { fr: 'palettes', en: 'pallets' },
62
+ rg: { fr: 'rangs', en: 'rows' },
63
+ ensemble: { fr: 'ensembles', en: 'kits' },
64
+ pl: { fr: 'pL', en: 'linear feet' },
65
+ mcx: { fr: 'morceaux', en: 'pieces' },
66
+ vg3: { fr: 'vg³', en: 'yd³' },
67
+ demipalsm: { fr: 'Demi-palettes (petite)', en: 'Half-pallets (small)' },
68
+ demipallg: { fr: 'Demi-palettes (lg)', en: 'Half-pallets (lg)' },
69
+ tonnes: { fr: 'tonnes', en: 'tons' },
70
+ bte: { fr: 'boîtes', en: 'boxes' },
71
+ pqt: { fr: 'paquets', en: 'bundles' },
72
+ '': { fr: 'unités', en: 'units' }
73
+ };
74
+ const sellUnitsBySlug = {
75
+ p2: { fr: 'pi²', en: 'sqft' },
76
+ sac: { fr: 'sac', en: 'bag' },
77
+ unite: { fr: 'unité', en: 'unit' },
78
+ tonne: { fr: 'tonne', en: 'ton' },
79
+ roul: { fr: 'rouleau', en: 'roll' },
80
+ pal: { fr: 'palette', en: 'pallet' },
81
+ rg: { fr: 'rang', en: 'row' },
82
+ ensemble: { fr: 'ensemble', en: 'kit' },
83
+ pl: { fr: 'pL', en: 'linear feet' },
84
+ mcx: { fr: 'morceau', en: 'piece' },
85
+ vg3: { fr: 'vg³', en: 'yd³' },
86
+ demipalsm: { fr: 'Demi-palette (petite)', en: 'Half-pallet (small)' },
87
+ demipallg: { fr: 'Demi-palette (lg)', en: 'Half-pallet (lg)' },
88
+ tonnes: { fr: 'tonne', en: 'ton' },
89
+ bte: { fr: 'boîte', en: 'box' },
90
+ pqt: { fr: 'paquet', en: 'bundle' },
91
+ '': { fr: 'unité', en: 'unit' }
92
+ };
93
+ /**
94
+ * @description Returns sell unit label in correct language for a specific product's other_units
95
+ * @param {IFilledDimensionUnits[] | undefined} otherUnits The unit array we have to check to get the sell unit
96
+ * @param {string | undefined} locale The language in which we want to return the label
97
+ * @param {string[]} returnUnitForSlugs An array of the slugs we want to return the unit label for
98
+ * @param {boolean} options.returnPlural If plural version should be returned
99
+ * @param {boolean} options.returnShortByDefault If short version should be prioritized
100
+ */
101
+ const getProductSellUnitLabel = (otherUnits, locale = 'fr', returnUnitForSlugs, options = {}) => {
102
+ if (!!!otherUnits)
103
+ return '';
104
+ const sellingUnit = otherUnits.find((unit) => !!unit.is_sale_unit);
105
+ if (!!!sellingUnit)
106
+ return '';
107
+ return (0, exports.getUnitLabelWithSlug)(sellingUnit.unit_slug, locale, options.returnPlural, returnUnitForSlugs, options.returnShortByDefault);
108
+ };
109
+ exports.getProductSellUnitLabel = getProductSellUnitLabel;
110
+ /**
111
+ * @description Returns unit label in correct language for a specific product's other_units
112
+ * @param {IFilledDimensionUnits[] | undefined} otherUnits The unit array we have to check to get the sell unit
113
+ * @param {string} type The unit type to check
114
+ * @param {string | undefined} locale The language in which we want to return the label
115
+ * @param {string[]} returnUnitForSlugs An array of the slugs we want to return the unit label for
116
+ * @param {boolean} options.returnPlural If plural version should be returned
117
+ * @param {boolean} options.returnShortByDefault If short version should be prioritized
118
+ */
119
+ const getProductUnitLabel = (otherUnits, type, locale = 'fr', returnUnitForSlugs, options = {}) => {
120
+ if (!!!otherUnits)
121
+ return '';
122
+ const unitToUse = otherUnits.find((unit) => (type == 'sale_unit' ? unit.is_sale_unit : unit.is_inventory_unit));
123
+ if (!!!unitToUse)
124
+ return '';
125
+ return (0, exports.getUnitLabelWithSlug)(unitToUse.unit_slug, locale, options.returnPlural, returnUnitForSlugs, options.returnShortByDefault);
126
+ };
127
+ exports.getProductUnitLabel = getProductUnitLabel;
128
+ /**
129
+ * Returns the unit label for a specific slug
130
+ * @param {string} unitSlug The slug of the unit for which we want to get the label
131
+ * @param {string | undefined} locale The language in which we want to get the label
132
+ * @param {boolean} getPluralVersion Optionnal - If the plural version should be returned instead.
133
+ * @param {string[]} returnUnitForSlugs The slugs for which we want to return a default value, in this case the unit slug for unit
134
+ * @param {boolean} returnShortByDefault Optionnal - If the short version should be prioritized
135
+ */
136
+ const getUnitLabelWithSlug = (unitSlug, locale = 'fr', getPluralVersion = false, returnUnitForSlugs, returnShortByDefault) => {
137
+ if (!!returnUnitForSlugs && !!returnUnitForSlugs.includes(unitSlug)) {
138
+ return (0, exports.getUnitLabelWithSlug)('unite', locale, getPluralVersion);
139
+ }
140
+ if (!!getPluralVersion)
141
+ return (0, exports.getPluralUnitLabelWithSlug)(unitSlug, locale, returnUnitForSlugs, returnShortByDefault);
142
+ const shortVersion = !!(0, inventories_1.getUnitShortDict)(unitSlug) ? (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)(unitSlug), locale) : '';
143
+ const longVersion = !!sellUnitsBySlug[unitSlug] ? (0, locale_1.translateILang)(sellUnitsBySlug[unitSlug], locale) : '';
144
+ if (!!returnShortByDefault)
145
+ return shortVersion;
146
+ return longVersion || shortVersion || unitSlug;
147
+ };
148
+ exports.getUnitLabelWithSlug = getUnitLabelWithSlug;
149
+ /**
150
+ * Returns the plural unit label for a specific slug
151
+ * @deprecated Should use getUnitLabelWithSlug instead (with props getPluralVersion=true)
152
+ * @param {string} unitSlug The slug of the unit for which we want to get the label
153
+ * @param {string | undefined} locale The language in which we want to get the label
154
+ * @param {string[]} returnUnitForSlugs The slugs for which we want to return a default value, in this case the unit slug for unit
155
+ */
156
+ const getPluralUnitLabelWithSlug = (unitSlug, locale = 'fr', returnUnitForSlugs, useShortIfDifferent) => {
157
+ if (!!returnUnitForSlugs && !!returnUnitForSlugs.includes(unitSlug)) {
158
+ return (0, locale_1.translateILang)(pluralSellUnitsBySlug['unite'], locale);
159
+ }
160
+ const shortVersion = !!(0, inventories_1.getUnitShortDict)(unitSlug) ? (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)(unitSlug), locale) : '';
161
+ const normalVersion = !!sellUnitsBySlug[unitSlug] ? (0, locale_1.translateILang)(sellUnitsBySlug[unitSlug], locale) : '';
162
+ const pluralVersion = !!pluralSellUnitsBySlug[unitSlug] ? (0, locale_1.translateILang)(pluralSellUnitsBySlug[unitSlug], locale) : '';
163
+ // If useShowIfDifferent is defined, and short version is different from the "normal" version, return short value
164
+ if (useShortIfDifferent && shortVersion != normalVersion)
165
+ return shortVersion;
166
+ return pluralVersion || shortVersion || unitSlug;
167
+ };
168
+ exports.getPluralUnitLabelWithSlug = getPluralUnitLabelWithSlug;
169
+ const getCorrectPluralSellUnit = (sellUnit, locale = 'fr') => {
170
+ if (!!!sellUnit.unit)
171
+ return '';
172
+ const frSellUnit = (0, string_1.string_to_slug)((0, locale_1.translateILang)(sellUnit.unit, 'fr'));
173
+ return !!pluralSellUnits[frSellUnit]
174
+ ? (0, locale_1.translateILang)(pluralSellUnits[frSellUnit], locale)
175
+ : (0, locale_1.translateILang)(sellUnit.unit, locale);
176
+ };
177
+ exports.getCorrectPluralSellUnit = getCorrectPluralSellUnit;
178
+ const productUnitSupportsDecimals = (unitSlug, isService) => {
179
+ return !!isService || !!['p2', 'pl', 'vg3', 'tonne'].includes(unitSlug);
180
+ };
181
+ exports.productUnitSupportsDecimals = productUnitSupportsDecimals;
182
+ // #endregion
183
+ // ----------------------------------------------------------------------------------------------------------
184
+ // ----------------------------------------------------------------------------------------------------------
185
+ // #region GENERAL
186
+ const getProductAttributes = (product) => {
187
+ const arrColor = !!product.attributes[data_1.AttributesIdEnumGR.SUBCOLOR]
188
+ ? product.attributes[data_1.AttributesIdEnumGR.SUBCOLOR]
189
+ : [];
190
+ const arrDimensions = !!product.attributes[data_1.AttributesIdEnumGR.DIMENSIONS]
191
+ ? product.attributes[data_1.AttributesIdEnumGR.DIMENSIONS]
192
+ : [];
193
+ const arrFormats = !!product.attributes[data_1.AttributesIdEnumGR.FORMATS]
194
+ ? product.attributes[data_1.AttributesIdEnumGR.FORMATS]
195
+ : [];
196
+ return { colors: arrColor, dimensions: arrDimensions, formats: arrFormats };
197
+ };
198
+ exports.getProductAttributes = getProductAttributes;
199
+ const getDescriptionLength = (description, locale = 'fr') => {
200
+ if (!!!description || !!!(0, locale_1.getLocaleOfDictionnary)(description, locale))
201
+ return 0;
202
+ return (0, string_1.stripHTML)((0, locale_1.getLocaleOfDictionnary)(description, locale)).length;
203
+ };
204
+ exports.getDescriptionLength = getDescriptionLength;
205
+ const getDescriptionString = (showFullDesc, maxLength, description, locale = 'fr') => {
206
+ if (!!showFullDesc || (0, exports.getDescriptionLength)(description, locale) <= maxLength) {
207
+ return (0, string_1.stripHTML)((0, locale_1.getLocaleOfDictionnary)(description, locale));
208
+ }
209
+ let truncated = (0, string_1.stripHTML)((0, locale_1.getLocaleOfDictionnary)(description, locale)).slice(0, maxLength).split(' ');
210
+ truncated.pop();
211
+ return truncated.join(' ') + ' [...]';
212
+ };
213
+ exports.getDescriptionString = getDescriptionString;
214
+ /**
215
+ * Returns rounded product sell_unit quantities depending on current value, value of secondary input if existant and sale unit per command step ratio found in product.
216
+ * @param value {number} - Current quantity as entered by user in first input
217
+ * @param otherUnits {IFilledDimensionUnits[] | undefined} - FilledDimensionUnits found in product (possibly undefined)
218
+ * @param value2 {number | undefined} - Current quantity as entered by user in second input (possibly undefined)
219
+ * @param targetIsSecondaryInput {boolean} - If action was triggered from secondary input (defaults to false)
220
+ */
221
+ const getRoundedSellUnitProductQuantities = (value, otherUnits = [], value2, targetIsSecondaryInput = false) => {
222
+ var _a;
223
+ const saleUnit = otherUnits.find((unit) => unit.is_sale_unit);
224
+ const commandUnit = otherUnits.find((unit) => unit.is_command_unit);
225
+ const commandStep = otherUnits.find((unit) => unit.is_command_step);
226
+ let roundedQuantities = {
227
+ qte1: value,
228
+ qte2: value2
229
+ };
230
+ // Now rounds quantities in calculations to 2 or 0 decimals (depending on what the unit supports)
231
+ if (!!targetIsSecondaryInput && typeof value2 === 'number') {
232
+ if (!!commandStep && !!commandStep.fitting_unit && !!commandUnit && !!commandUnit.fitting_unit && !!saleUnit) {
233
+ const nbCmdUnitPerCmdStep = (0, round_1.default)(commandStep.fitting_unit / commandUnit.fitting_unit, 5);
234
+ const nbSaleUnitPerCmdStep = (0, round_1.default)(commandStep.fitting_unit / ((_a = saleUnit.fitting_unit) !== null && _a !== void 0 ? _a : 1), (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0);
235
+ // Round value2 to command step
236
+ const roundedValue = value2 === 0
237
+ ? 0
238
+ : _roundNbUnitPerCmdStep(value2, nbCmdUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 2 : 0);
239
+ // Calculate amount of current command units by dividing roundedValue with nbCmdUnitPerCmdStep
240
+ const nbOfRoundedCmdUnits = roundedValue / nbCmdUnitPerCmdStep;
241
+ // Then multiply result by amount of sale units in one command step
242
+ const nbOfRoundedSaleUnits = nbOfRoundedCmdUnits * nbSaleUnitPerCmdStep;
243
+ roundedQuantities = {
244
+ qte1: value2 === 0
245
+ ? 0
246
+ : (0, round_1.default)(nbOfRoundedSaleUnits, !!saleUnit && (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 2 : 0),
247
+ qte2: roundedValue
248
+ };
249
+ }
250
+ }
251
+ else if (!!commandStep && !!commandStep.fitting_unit && !!saleUnit && !!saleUnit.fitting_unit) {
252
+ const cmdStepFittingUnit = commandStep.fitting_unit;
253
+ const saleFittingUnit = saleUnit.fitting_unit;
254
+ const nbSaleUnitPerCmdStep = (0, round_1.default)(cmdStepFittingUnit / saleFittingUnit, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0);
255
+ const roundedValue = value === 0
256
+ ? 0
257
+ : _roundNbUnitPerCmdStep(value, nbSaleUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 2 : 0);
258
+ let commandUnitQty = undefined;
259
+ if (!!commandUnit && !!commandUnit.fitting_unit) {
260
+ if (value === 0) {
261
+ commandUnitQty = 0;
262
+ }
263
+ // ** NOTE - Commented section here to fix rounding bug - Commented on 10-09-2025, in relation to bug GR-I540
264
+ // if sell_unit has a fitting unit of 1, we can simply divide the command_unit from roundedValue to get result
265
+ // else if (saleFittingUnit == 1) {
266
+ // console.log('YO YO YO are we HERE&&????')
267
+ // commandUnitQty = round(
268
+ // roundedValue / commandUnit.fitting_unit,
269
+ // productUnitSupportsDecimals(commandUnit.unit_slug) ? 2 : 0
270
+ // )
271
+ // }
272
+ else {
273
+ // Calculate amount of current command steps by dividing roundedValue with saleUnitsPerCommandStep
274
+ // ** NOTE - Added round here on 10-09-2025 in relation to bug GR-I540
275
+ const nbOfCmdSteps = (0, round_1.default)(roundedValue / nbSaleUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0);
276
+ // Then multiply result by amount of command unit in one command step
277
+ commandUnitQty =
278
+ nbOfCmdSteps *
279
+ (0, round_1.default)(cmdStepFittingUnit / commandUnit.fitting_unit, (0, exports.productUnitSupportsDecimals)(commandUnit.unit_slug) ? 5 : 0);
280
+ commandUnitQty = (0, round_1.default)(commandUnitQty, (0, exports.productUnitSupportsDecimals)(commandUnit.unit_slug) ? 2 : 0);
281
+ }
282
+ }
283
+ roundedQuantities = {
284
+ qte1: roundedValue,
285
+ qte2: commandUnitQty
286
+ };
287
+ }
288
+ return roundedQuantities;
289
+ };
290
+ exports.getRoundedSellUnitProductQuantities = getRoundedSellUnitProductQuantities;
291
+ /**
292
+ * Returns rounded product quantities depending on current value per command step ratio found in product.
293
+ * @param value {number} - Current quantity as entered by user in first input
294
+ * @param otherUnits {IFilledDimensionUnits[] | undefined} - FilledDimensionUnits found in product (possibly undefined)
295
+ * @param type {'sale_unit' | 'inventory_unit'} - Quantity type for computing
296
+ */
297
+ const getRoundedUnitProductQuantities = (value, otherUnits = [], type) => {
298
+ const unitToTest = type == 'sale_unit'
299
+ ? otherUnits.find((unit) => unit.is_sale_unit)
300
+ : otherUnits.find((unit) => unit.is_inventory_unit);
301
+ const commandStep = otherUnits.find((unit) => unit.is_command_step);
302
+ let roundedQuantities = value;
303
+ if (!!commandStep && !!commandStep.fitting_unit && unitToTest && unitToTest.fitting_unit) {
304
+ const cmdStepFittingUnit = commandStep.fitting_unit;
305
+ const fittingUnit = unitToTest.fitting_unit;
306
+ const nbUnitPerCmdStep = cmdStepFittingUnit / fittingUnit;
307
+ const roundedValue = value === 0
308
+ ? 0
309
+ : _roundNbUnitPerCmdStepV2(value, nbUnitPerCmdStep, (0, exports.productUnitSupportsDecimals)(unitToTest.unit_slug) ? 5 : 0);
310
+ roundedQuantities = roundedValue;
311
+ }
312
+ return roundedQuantities;
313
+ };
314
+ exports.getRoundedUnitProductQuantities = getRoundedUnitProductQuantities;
315
+ const _roundNbUnitPerCmdStepV2 = (value, nbUnitPerCmdStep, decimalsToCheck = 0) => {
316
+ const currentFittingValue = (0, floor_1.default)(value / nbUnitPerCmdStep, 5); // Rounds unsignificant quantities to lower value (ex. if result is 0.000007, we don't want it to round up to 1)
317
+ const roundedUp = (0, round_1.default)((0, ceil_1.default)(currentFittingValue) * nbUnitPerCmdStep, decimalsToCheck);
318
+ // retrun roundedUp as default value.
319
+ return roundedUp;
320
+ };
321
+ const _roundNbUnitPerCmdStep = (value, nbUnitPerCmdStep, decimalsToCheck = 0) => {
322
+ let numberBuffer = 0;
323
+ if (decimalsToCheck > 0) {
324
+ let buffer = '';
325
+ buffer = buffer.padStart(decimalsToCheck - 1, '0');
326
+ numberBuffer = (0, toNumber_1.default)(`0.${buffer}1`);
327
+ }
328
+ const rounded = (0, round_1.default)(value / nbUnitPerCmdStep, decimalsToCheck) * nbUnitPerCmdStep;
329
+ const roundedUp = Math.ceil(value / nbUnitPerCmdStep) * nbUnitPerCmdStep;
330
+ // if rounded value is 0, but roundedUp is > 0, return roundedUp
331
+ if (rounded == 0 && roundedUp > 0)
332
+ return roundedUp;
333
+ // ** NEW - Added on 10-09-2025 in relation to bug GR-I540
334
+ // if provided value is already a multiple of cmdStep, return value
335
+ if ((0, round_1.default)(value % nbUnitPerCmdStep, decimalsToCheck) == 0)
336
+ return rounded;
337
+ // if provided value is larger than rounded, and roundedUp is an exact multiple of rounded, return roundedUp
338
+ if ((0, round_1.default)(value, decimalsToCheck) > rounded + numberBuffer)
339
+ return roundedUp;
340
+ // if rounded value is an exact multiple of cmdStep, return rounded
341
+ if ((0, round_1.default)(rounded, decimalsToCheck) % nbUnitPerCmdStep <= numberBuffer)
342
+ return rounded;
343
+ // retrun roundedUp as default value.
344
+ return roundedUp;
345
+ };
346
+ /**
347
+ *
348
+ * @param {string} stringToSplit
349
+ * @param {string} dummyStringToReplace.currentValue, optionnal, default : '%%-%%'. Used to provide general replace values for a specific string. Is applied to both sections of the splitted string.
350
+ * @param {string} dummyStringToReplace.newValue, optionnal, default : ' - '. Used to provide general replace values for a specific string. Is applied to both sections of the splitted string.
351
+ * @returns {string[]}
352
+ */
353
+ const splitOnDashes = (stringToSplit, dummyStringToReplace = { currentValue: '%%-%%', newValue: ' - ' }) => {
354
+ let splited = stringToSplit.split(' - ');
355
+ if (splited.length === 1)
356
+ splited = stringToSplit.split(' -');
357
+ if (splited.length === 1)
358
+ splited = stringToSplit.split('- ');
359
+ return [
360
+ splited[0].replace(dummyStringToReplace.currentValue, dummyStringToReplace.newValue),
361
+ ...(!!splited[1]
362
+ ? [splited.slice(1).join(' - ').replace(dummyStringToReplace.currentValue, dummyStringToReplace.newValue)]
363
+ : [])
364
+ ];
365
+ };
366
+ exports.splitOnDashes = splitOnDashes;
367
+ /**
368
+ * Get product name as array. Array created mostly by splitting name on dash symbol (and variations).
369
+ * @param {IIndexedVariationAlgolia | IIndexedProduct} product
370
+ * @param {string | undefined} locale
371
+ * @returns {string[]} - Position 0 is the "commum section" of the name, and position 1 should contain all specifics (ex. color, size, etc...)
372
+ */
373
+ const getProdName = (product, locale, platform, attributes) => {
374
+ var _a;
375
+ let name;
376
+ if (!!product.full_name) {
377
+ name = (0, locale_1.getLocaleOfDictionnary)(product.full_name, locale);
378
+ }
379
+ else {
380
+ name = (0, locale_1.getLocaleOfDictionnary)(product.name, locale);
381
+ if (!!product.use_parent && !!product.parent_name) {
382
+ if (typeof product.parent_name === 'string') {
383
+ name = product.parent_name;
384
+ }
385
+ }
386
+ }
387
+ let newNameArray = [];
388
+ const dashesToFind = [' - ', '- ', ' -'];
389
+ // If name includes parenthesis...
390
+ if (name.includes('(')) {
391
+ let newStr = '';
392
+ let strWithParenthesisToCheck = name;
393
+ // a. Replace all occurences of dashesToFind found between parenthesis with '-'
394
+ while (strWithParenthesisToCheck.includes('(')) {
395
+ let positionStart = strWithParenthesisToCheck.indexOf('(');
396
+ let positionEnd = strWithParenthesisToCheck.indexOf(')');
397
+ // When first string between paranthesis found, replace dashesToFind
398
+ let substrToCheck = strWithParenthesisToCheck.substring(positionStart, positionEnd + 1);
399
+ for (let dash of dashesToFind) {
400
+ substrToCheck = substrToCheck.replace(dash, '-');
401
+ }
402
+ // Add updated string to newStr from the beginning to the end of section with parenthesis
403
+ newStr += strWithParenthesisToCheck.substring(0, positionStart) + substrToCheck;
404
+ // Strip checked string to remove section added to newStr.
405
+ // This will mean next time we go through the loop, logic will check for next section with parenthesis. If not found, loop ends.
406
+ strWithParenthesisToCheck =
407
+ positionEnd === strWithParenthesisToCheck.length - 1 ? '' : strWithParenthesisToCheck.substring(positionEnd + 1);
408
+ }
409
+ // Add ending of string to newly formatted string after loop done (in case last parenthesis found was not at the end of the string)
410
+ newStr += strWithParenthesisToCheck;
411
+ // b. Isolate "first part" of string
412
+ const positionOfFirst = newStr.indexOf(')');
413
+ let firstPart = newStr.substring(0, positionOfFirst);
414
+ // If first closing parenthesis is not at end of string and firstPart contains dashesToFind, it means the ' - ' should be keep intact.
415
+ // Replace ' - ' found with uncommon string so we can put it back later, then call splitOnDashes function
416
+ if (positionOfFirst !== newStr.length - 1 && dashesToFind.some((str) => firstPart.includes(str))) {
417
+ const secondPart = newStr.substring(positionOfFirst);
418
+ for (let str of dashesToFind) {
419
+ firstPart.replace(str, '%%-%%');
420
+ }
421
+ newNameArray = (0, exports.splitOnDashes)(`${firstPart}${secondPart}`);
422
+ }
423
+ // Else, simply call splitOnDashes function
424
+ else {
425
+ newNameArray = (0, exports.splitOnDashes)(newStr);
426
+ }
427
+ }
428
+ // Else, no parenthesis found, call splitOnDashes function
429
+ else {
430
+ newNameArray = (0, exports.splitOnDashes)(name);
431
+ }
432
+ if (platform === 'pos' && !!attributes) {
433
+ for (const attribute of attributes) {
434
+ if (!!!attribute.id)
435
+ continue;
436
+ const productAttributeSlugs = (_a = product.attributes) === null || _a === void 0 ? void 0 : _a[attribute.id];
437
+ if (!!productAttributeSlugs) {
438
+ for (const attrValue of attribute.values) {
439
+ if (productAttributeSlugs.includes(attrValue.slug)) {
440
+ const label = (0, locale_1.getLocaleOfDictionnary)(attrValue.value, locale);
441
+ if (label) {
442
+ newNameArray[0] = newNameArray[0] + ` (${label})`;
443
+ }
444
+ }
445
+ }
446
+ }
447
+ }
448
+ }
449
+ return newNameArray;
450
+ };
451
+ exports.getProdName = getProdName;
452
+ /**
453
+ * Function getParentProductCategoryGroup
454
+ * @param prod - Product to check
455
+ */
456
+ const getParentProductCategoryGroup = (prod) => {
457
+ let type = 'other';
458
+ if (!!prod.categories && !!prod.categories['lvl0']) {
459
+ const categorySlug = prod.categories['lvl0'];
460
+ switch (categorySlug) {
461
+ case 'gazon':
462
+ if (!!(0, exports.checkIfProductIsOfType)(prod, 'gazon')) {
463
+ type = 'gazon';
464
+ }
465
+ break;
466
+ case 'amenagement-paysager':
467
+ if (!!(0, exports.checkIfProductIsOfType)(prod, 'beton')) {
468
+ type = 'beton';
469
+ }
470
+ break;
471
+ default:
472
+ if (!!(0, exports.checkIfProductIsOfType)(prod, 'vrac')) {
473
+ type = 'vrac';
474
+ }
475
+ break;
476
+ }
477
+ }
478
+ return type;
479
+ };
480
+ exports.getParentProductCategoryGroup = getParentProductCategoryGroup;
481
+ /**
482
+ * Function getProductFormOptions - Returns all AttributeValues for product to construct options in add to cart form
483
+ * @param product - Product to check
484
+ * @param attributes - Array of IAttributes to fetch info from
485
+ */
486
+ const getProductFormOptions = (product, attributes) => {
487
+ let allColorOptions = [];
488
+ let allDimensionOptions = [];
489
+ let allFormatOptions = [];
490
+ //Product Attributes
491
+ const product_attributes = (0, exports.getProductAttributes)(product);
492
+ //Overridden attr
493
+ let overridenAttributes = product.declinations
494
+ .map((declination) => declination.overriden_attributes)
495
+ .filter((ova) => !!ova);
496
+ overridenAttributes = (0, flatten_1.default)(overridenAttributes);
497
+ overridenAttributes = (0, uniqBy_1.default)(overridenAttributes, 'slug');
498
+ const getOverriddenValues = (prodAttributes, attrId) => {
499
+ const overridenOptions = !!overridenAttributes.length
500
+ ? overridenAttributes.filter((attr) => attr.id === attrId)
501
+ : [];
502
+ let finalOptions = [];
503
+ for (const attr of prodAttributes) {
504
+ let isOverridden = false;
505
+ for (const ovOption of overridenOptions) {
506
+ if (!isOverridden) {
507
+ if (!!attr && attr.slug === ovOption.slug) {
508
+ isOverridden = true;
509
+ finalOptions = [
510
+ ...finalOptions,
511
+ Object.assign(Object.assign({}, attr), { other_details: Object.assign(Object.assign({}, attr.other_details), { image: ovOption.overriden_values }) })
512
+ ];
513
+ }
514
+ }
515
+ }
516
+ if (!isOverridden) {
517
+ finalOptions = [...finalOptions, attr];
518
+ }
519
+ }
520
+ return finalOptions;
521
+ };
522
+ // ----------------------------------------------------------
523
+ // #region colors
524
+ const subColorsAttr = attributes.find((attr) => attr.id === data_1.AttributesIdEnumGR.SUBCOLOR);
525
+ if (!!subColorsAttr) {
526
+ const subColors = subColorsAttr.values;
527
+ const colorsAttributes = subColors.filter((sub) => product_attributes.colors.includes(sub.slug));
528
+ const finalColors = getOverriddenValues(colorsAttributes, data_1.AttributesIdEnumGR.SUBCOLOR);
529
+ allColorOptions = (0, orderBy_1.default)(finalColors, (color) => product.declinations.findIndex((d) => d.attributes[data_1.AttributesIdEnumGR.SUBCOLOR].includes(color.slug)));
530
+ }
531
+ // #endregion
532
+ // ----------------------------------------------------------
533
+ // ----------------------------------------------------------
534
+ // #region dimensions
535
+ const dimensionsAttr = attributes.find((attr) => attr.id === data_1.AttributesIdEnumGR.DIMENSIONS);
536
+ if (!!dimensionsAttr) {
537
+ const dimensions = dimensionsAttr.values;
538
+ const dimensionsAttributes = dimensions.filter((d) => product_attributes.dimensions.includes(d.slug));
539
+ const finalDimensions = getOverriddenValues(dimensionsAttributes, data_1.AttributesIdEnumGR.DIMENSIONS);
540
+ allDimensionOptions = finalDimensions;
541
+ }
542
+ // #endregion
543
+ // ----------------------------------------------------------
544
+ // ----------------------------------------------------------
545
+ // #region formats
546
+ const formatsAttr = attributes.find((attr) => attr.id === data_1.AttributesIdEnumGR.FORMATS);
547
+ if (!!formatsAttr) {
548
+ const formats = formatsAttr.values;
549
+ allFormatOptions = formats.filter((f) => product_attributes.formats.includes(f.slug));
550
+ }
551
+ // #endregion
552
+ // ----------------------------------------------------------
553
+ return {
554
+ allColors: allColorOptions,
555
+ allDimensions: allDimensionOptions,
556
+ allFormats: allFormatOptions
557
+ };
558
+ };
559
+ exports.getProductFormOptions = getProductFormOptions;
560
+ /**
561
+ * @description Checks if product is of type by checking TYPE attribute value. Works with indexed product or cart item.
562
+ * @param product
563
+ * @param type
564
+ * @param excludeUndefined If excludeUndefined is true, products without the "type" attribute will return true
565
+ * @returns boolean
566
+ */
567
+ const checkIfProductIsOfType = (product, type, excludeUndefined) => {
568
+ const attr = !!product && !!product.attributes ? product.attributes : {};
569
+ if (!!!attr[data_1.AttributesIdEnumGR.TYPE] && !!excludeUndefined)
570
+ return true;
571
+ return (!!attr[data_1.AttributesIdEnumGR.TYPE] &&
572
+ Array.isArray(attr[data_1.AttributesIdEnumGR.TYPE]) &&
573
+ attr[data_1.AttributesIdEnumGR.TYPE].includes(type));
574
+ };
575
+ exports.checkIfProductIsOfType = checkIfProductIsOfType;
576
+ // #endregion
577
+ // ----------------------------------------------------------------------------------------------------------
578
+ // ----------------------------------------------------------------------------------------------------------
579
+ // #region GRASS
580
+ /**
581
+ * Check if provided sku/slug corresponds to a non-speciality grass item
582
+ * @param sku Grass item's sku
583
+ * @param slug Grass item's parent product slug
584
+ * @param onlyBaseGrass Optionnal. If provided data should only be compared to base grass (aka Kentucky)
585
+ */
586
+ const checkIfIsNonSpecialityGrass = (sku, slug, onlyBaseGrass) => {
587
+ const skusToCheck = [products_2.kentucky, ...(!onlyBaseGrass ? [products_2.prestige] : [])];
588
+ const slugsToCheck = ['kentucky', ...(!onlyBaseGrass ? ['prestige'] : [])];
589
+ return skusToCheck.includes(sku) || slugsToCheck.includes(slug);
590
+ };
591
+ exports.checkIfIsNonSpecialityGrass = checkIfIsNonSpecialityGrass;
592
+ const checkIfProductIsInstallation = (item) => {
593
+ return !!item.is_service && !!item.parent_slug && !!item.parent_slug.includes('installation');
594
+ };
595
+ exports.checkIfProductIsInstallation = checkIfProductIsInstallation;
596
+ /**
597
+ * Returns array of installation items found in provided array
598
+ * @param items - Array of cart items or IIndexedDeclinations to check
599
+ */
600
+ const getAllInstallFromItems = (items) => {
601
+ return items.filter((i) => (!!i.parent_slug && products_2.installationProductsSlugs.includes(i.parent_slug)) ||
602
+ Object.values(products_2.installationProSpecSkus).includes(i.sku));
603
+ };
604
+ exports.getAllInstallFromItems = getAllInstallFromItems;
605
+ /**
606
+ * Function fuseGrassProducts
607
+ * @description - Returns items with only one apparent grass product (used for detail customers).
608
+ * ** FOR DISPLAY PURPOSES ONLY - Always save grass products separatly in ICart **
609
+ * @param recursiveItems - ICartItems with subitems (object created for display purposes)
610
+ */
611
+ const fuseGrassProducts = (recursiveItems, isPro) => {
612
+ const specialityGrass = recursiveItems[0];
613
+ const kentuckyGrass = (specialityGrass.sub_items || []).find((sub) => sub.sku === products_2.kentucky || sub.parent_slug == 'kentucky');
614
+ let newItems = [];
615
+ if (!!kentuckyGrass) {
616
+ const kentuckyPrice = (0, products_1.getLowestPrice)(kentuckyGrass);
617
+ const regPriceKentucky = kentuckyGrass.regular_price.amount;
618
+ const newGrassRegPrice = !!kentuckyPrice.promo ? regPriceKentucky : kentuckyPrice.price.amount;
619
+ const newGrassDiscountPrice = (!!specialityGrass.discount_price
620
+ ? specialityGrass.discount_price.amount
621
+ : specialityGrass.regular_price.amount) +
622
+ (!!kentuckyPrice.promo ? kentuckyPrice.price.amount : regPriceKentucky);
623
+ const getLowestPriceSpecialityGrass = (0, products_1.getLowestPrice)(specialityGrass);
624
+ newItems = [
625
+ Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, specialityGrass), { regular_price: Object.assign(Object.assign({}, specialityGrass.regular_price), { amount: newGrassRegPrice + specialityGrass.regular_price.amount }) }), (!!newGrassDiscountPrice
626
+ ? {
627
+ discount_price: Object.assign(Object.assign({}, (specialityGrass.discount_price || { currency: 'CAD' })), { amount: newGrassDiscountPrice })
628
+ }
629
+ : {})), (!!specialityGrass.promo_price
630
+ ? {
631
+ promo_price: Object.assign(Object.assign({}, specialityGrass.promo_price), { amount: specialityGrass.promo_price.amount + kentuckyPrice.price.amount })
632
+ }
633
+ : {})), (!!!isPro && !!kentuckyGrass.tier_pricing
634
+ ? {
635
+ tier_pricing: kentuckyGrass.tier_pricing.map((t) => (Object.assign(Object.assign({}, t), { price: Object.assign(Object.assign({}, t.price), { amount: t.price.amount + getLowestPriceSpecialityGrass.price.amount }) })))
636
+ }
637
+ : {})), { sub_items: [
638
+ Object.assign(Object.assign({}, kentuckyGrass), { hide_from_summary: true }),
639
+ ...(specialityGrass.sub_items || []).slice(1)
640
+ ] }),
641
+ ...recursiveItems.slice(1)
642
+ ];
643
+ }
644
+ return newItems;
645
+ };
646
+ exports.fuseGrassProducts = fuseGrassProducts;
647
+ const isMinQtyFee = (slug) => {
648
+ return ['minimum-facturable-commande', 'frais-minimum-gazon-pour-installation'].includes(slug);
649
+ };
650
+ exports.isMinQtyFee = isMinQtyFee;
651
+ const getAllMinGrassQuantities = (grassProduct, isPro) => {
652
+ return {
653
+ pickup: (0, expedition_1.getMinGrassQte)(grassProduct, 'pickup', isPro),
654
+ shipping: (0, expedition_1.getMinGrassQte)(grassProduct, 'shipping', isPro),
655
+ install: (0, expedition_1.getMinQteInstall)(isPro)
656
+ };
657
+ };
658
+ exports.getAllMinGrassQuantities = getAllMinGrassQuantities;
659
+ const getMinQtyFeeText = (parent_slug = '', grassProduct, isPro, locale = 'fr', expeditionMethod, shortVersion) => {
660
+ const type = parent_slug === 'frais-minimum-gazon-pour-installation' ? 'install' : 'order';
661
+ const minQuantities = (0, exports.getAllMinGrassQuantities)(grassProduct, isPro);
662
+ const localeSellUnit = (0, locale_1.translateILang)(pluralSellUnits.p2, locale);
663
+ const localeStepUnit = (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)('roul'), locale).toLowerCase();
664
+ const localeMinUnit = (0, locale_1.translateILang)((0, inventories_1.getUnitShortDict)('pal'), locale).toLowerCase();
665
+ let str = '';
666
+ const endStr = (0, locale_1.translateILang)({
667
+ fr: ` Ce frais correspond au prix du gazon choisi multiplié par la différence entre la quantité choisie et le minimum.`,
668
+ en: ` Ce frais correspond au prix du gazon choisi multiplié par la différence entre la quantité choisie et le minimum.`
669
+ }, locale);
670
+ // If expedition method not chosen yet, and pickup & shipping quantities are different, show both
671
+ if (!!!expeditionMethod && type === 'order' && minQuantities.pickup !== minQuantities.shipping) {
672
+ const strMinShipping = `${minQuantities.shipping}${localeSellUnit} (${minQuantities.shipping / 740} ${localeMinUnit})`;
673
+ const strMinPickup = !!minQuantities.pickup
674
+ ? `${minQuantities.pickup}${localeSellUnit} (${minQuantities.pickup / 740} ${localeMinUnit})`
675
+ : '';
676
+ str = (0, locale_1.translateILang)({
677
+ fr: `Les commandes de gazon sont disponibles à partir de 10${localeSellUnit} (1 ${localeStepUnit}), mais le minimum facturable pour la livraison est de ${strMinShipping}${!!strMinPickup ? ` et de ${strMinPickup} pour la cueillette.` : ``}`,
678
+ en: `Sod orders are available starting at 10${localeSellUnit} (1 ${localeStepUnit}), but the minimum chargeable for delivery is ${strMinShipping}${!!strMinPickup ? ` and ${strMinPickup} for pick-up.` : ``}`
679
+ }, locale);
680
+ if (!!!shortVersion) {
681
+ str += endStr;
682
+ }
683
+ return str;
684
+ }
685
+ // Show specific quantity for expedition type
686
+ const minBillableQty = type === 'install'
687
+ ? minQuantities.install
688
+ : expeditionMethod === 'pickup'
689
+ ? minQuantities.pickup
690
+ : minQuantities.shipping;
691
+ const minQtyPallets = minBillableQty !== 0 ? minBillableQty / 740 : 0;
692
+ const minBillableStr = `${minBillableQty}${localeSellUnit}${type === 'order' ? ' (' + minQtyPallets + ' ' + localeMinUnit + ')' : ''}`;
693
+ str = (0, locale_1.translateILang)({
694
+ fr: `${type === 'install'
695
+ ? "L'installation"
696
+ : expeditionMethod === 'pickup'
697
+ ? 'La cueillette'
698
+ : expeditionMethod === 'delivery'
699
+ ? 'La livraison'
700
+ : 'La commande'} de gazon est disponible à partir de 10${localeSellUnit} (1 ${localeStepUnit}), mais le minimum facturable est de ${minBillableStr}.`,
701
+ en: `Sod ${type === 'install'
702
+ ? 'installation'
703
+ : expeditionMethod === 'pickup'
704
+ ? 'pick-up'
705
+ : expeditionMethod === 'delivery'
706
+ ? 'delivery'
707
+ : 'ordering'} is available starting at 10${localeSellUnit} (1 ${localeStepUnit}), but the minimum billable is ${minBillableStr}.`
708
+ }, locale);
709
+ if (!!!shortVersion) {
710
+ str += endStr;
711
+ }
712
+ return str;
713
+ };
714
+ exports.getMinQtyFeeText = getMinQtyFeeText;
715
+ const getMinQtyFeeAmountText = (parent_slug = '', locale = 'fr', servicesFees, showMinFeeAmount = true) => {
716
+ const serviceOrFee = servicesFees.find((i) => i.parent_slug === parent_slug);
717
+ if (!!!serviceOrFee)
718
+ return '';
719
+ const amount = (0, toNumber_1.default)(serviceOrFee.regular_price.amount) * serviceOrFee.qte;
720
+ return (0, locale_1.translateILang)({
721
+ fr: `Une différence de ${!!showMinFeeAmount ? amount.toFixed(2) + '$' : '%LOADER%'}%BOLD% vous sera chargée si la quantité de gazon au panier est plus petite que le minimum requis.`,
722
+ en: `A difference of ${!!showMinFeeAmount ? amount.toFixed(2) + '$' : '%LOADER%'}%BOLD% will be charged if the quantity of sod in the cart is less than the minimum required.`
723
+ }, locale);
724
+ };
725
+ exports.getMinQtyFeeAmountText = getMinQtyFeeAmountText;
726
+ const getGrassQteText = (chosenDeclination, locale = 'fr') => {
727
+ let txt = '';
728
+ let nbRolls = 0;
729
+ let nbSquareFeet = 0;
730
+ const units = !!!chosenDeclination ? [] : chosenDeclination.other_units;
731
+ if (!!units && !!units.length) {
732
+ const itemRolls = units.find((measure) => measure.unit_slug === 'roul');
733
+ const itemSquareFeet = units.find((measure) => measure.unit_slug === 'pal');
734
+ if (!!itemSquareFeet && !!itemSquareFeet.fitting_unit) {
735
+ nbSquareFeet = itemSquareFeet.fitting_unit;
736
+ }
737
+ if (!!itemRolls && !!itemRolls.fitting_unit && nbSquareFeet !== 0) {
738
+ nbRolls = nbSquareFeet / itemRolls.fitting_unit;
739
+ }
740
+ }
741
+ txt = (0, locale_1.translateILang)({
742
+ fr: 'Pour ce produit, vous devez commander par pieds carrés. Une palette = *nbRolls* rouleaux (*nbSquareFeet*pi2)',
743
+ en: 'For this product, you have to order by square feet. A pallet = *nbRolls* rolls (*nbSquareFeet*pi2)'
744
+ }, locale);
745
+ txt = txt.replace('*nbRolls*', String(nbRolls));
746
+ txt = txt.replace('*nbSquareFeet*', String(nbSquareFeet));
747
+ return txt;
748
+ };
749
+ exports.getGrassQteText = getGrassQteText;
750
+ const getGrassServicesFees = async (grassProduct, isPro, useFees, expeditionMethod, fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, locale, allStores, chosenGrass, baseGrass, customPriceList) => {
751
+ const installItems = await (0, exports.getInstallationArray)(grassProduct.qte, (!!baseGrass ? baseGrass : chosenGrass).product_upsells, fetchProduct, locale, isPro, chosenGrass.sku, customPriceList, { engrais: true, roulage: true });
752
+ const cart = Object.assign(Object.assign({}, (0, Cart_1.getDefaultCart)()), { items: [
753
+ chosenGrass,
754
+ ...(!!baseGrass ? [baseGrass] : []),
755
+ ...installItems.filter((item) => !!!(0, exports.isMinQtyFee)(item.parent_slug || ''))
756
+ ] });
757
+ const applied = await (0, exports.fetchFeesBeforeCart)(!!useFees, cart, expeditionMethod, fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, locale, allStores, isPro, grassProduct, undefined, { useStoreAddress: 'sainte-julie' }, customPriceList);
758
+ return [...installItems, ...applied.itemsToAdd];
759
+ };
760
+ exports.getGrassServicesFees = getGrassServicesFees;
761
+ const getGrassSubQuestionsByType = (type) => {
762
+ if (type === 'pro') {
763
+ return products_2.otherGrassSubQuestions.filter((sub) => !!sub.proOnly);
764
+ }
765
+ return products_2.otherGrassSubQuestions.filter((sub) => 'installation-gazon' === sub.associatedProductSlug || (!!sub.installOnly && !!!sub.proOnly));
766
+ };
767
+ exports.getGrassSubQuestionsByType = getGrassSubQuestionsByType;
768
+ /**
769
+ * @description For grass products. Over 1480pi2, if installation, quantities are rounded to rolls (10pi2) if pickup, and to half pal. if shipping
770
+ * @param grassProduct
771
+ * @param cartData
772
+ * @returns quantity rounded to rolls with items to change or undefined
773
+ */
774
+ const handleGrassProductQtyRoundForShipping = (cartData, grassProduct) => {
775
+ if (!!!cartData || !!!grassProduct)
776
+ return;
777
+ const product = cartData.items.find((item) => item.sku === grassProduct.sku);
778
+ if (!!!product)
779
+ return;
780
+ const productOtherUnits = product.other_units;
781
+ if (!!!productOtherUnits)
782
+ return;
783
+ // get new rounded qte
784
+ const palUnit = productOtherUnits.find((u) => u.unit_slug === 'pal');
785
+ const rounded = (0, exports.roundGrassQte)(product.qte, !!!cartData.is_pickup, palUnit);
786
+ if (!!!rounded || rounded === grassProduct.qte)
787
+ return;
788
+ // ajust items with new quantity
789
+ let itemsToChange = [];
790
+ const recursiveGrassItem = (0, cart_1.getRecursiveItems)(cartData.items).find((item) => item.sku === grassProduct.sku);
791
+ const getItemsToChange = (item) => {
792
+ if (!!item.sub_items) {
793
+ item.sub_items.forEach((subItem) => getItemsToChange(subItem));
794
+ }
795
+ if (item.parent_slug === 'frais-de-mobilisation') {
796
+ const totalPallet = (0, expedition_1.getPalletQty)(cartData.items.map((i) => {
797
+ if ((0, exports.checkIfProductIsOfType)(i, 'gazon')) {
798
+ return Object.assign(Object.assign({}, i), { qte: rounded });
799
+ }
800
+ return i;
801
+ }), 'grass');
802
+ itemsToChange.push({
803
+ sku: item.sku,
804
+ qte: (0, ceil_1.default)(totalPallet / expedition_1.installationFeePalletTier)
805
+ });
806
+ return;
807
+ }
808
+ if (!!item.is_upsell_of_sku) {
809
+ const parentUpsellProd = cartData.items.find((i) => i.sku === item.is_upsell_of_sku);
810
+ if (!!parentUpsellProd) {
811
+ const sameUpsell = (parentUpsellProd.product_upsells || []).find((up) => up.recommendation_sku === item.sku);
812
+ if (!!sameUpsell) {
813
+ const anUpsellProduct = Object.assign(Object.assign(Object.assign(Object.assign({}, item), { parent_slug: sameUpsell.recommendation_parent_slug, recommended_qte: sameUpsell.recommendation_qty, recommended_sku: sameUpsell.recommendation_sku, matching_qte: !!sameUpsell.matching_qty, auto_add: sameUpsell.auto_add, auto_add_exceptions: sameUpsell.auto_add_exceptions, actual_qte: sameUpsell.actual_qty }), (!!sameUpsell.is_recommendation ? { is_recommendation: true } : {})), (!!sameUpsell.show_recommendation_msg ? { show_recommendation_msg: true } : {}));
814
+ const ratio = (0, upsells_1.calculateUpsellQte)(anUpsellProduct, rounded);
815
+ if (!!ratio) {
816
+ itemsToChange.push({
817
+ sku: item.sku,
818
+ qte: ratio
819
+ });
820
+ return;
821
+ }
822
+ }
823
+ }
824
+ }
825
+ itemsToChange.push({
826
+ sku: item.sku,
827
+ qte: rounded
828
+ });
829
+ return;
830
+ };
831
+ if (!!recursiveGrassItem) {
832
+ getItemsToChange(recursiveGrassItem);
833
+ }
834
+ return { rounded, itemsToChange };
835
+ };
836
+ exports.handleGrassProductQtyRoundForShipping = handleGrassProductQtyRoundForShipping;
837
+ /**
838
+ * Function roundGrassQte
839
+ * @description Returns rounded grass quantity depending on current qty, if customer selected installation and pallet unit (if defined)
840
+ * @param currentQte {number} - Current quantity as entered by user in input
841
+ * @param isShipping {boolean} - Whether customer has selected installation option
842
+ * @param palUnit {IFilledDimensionUnits | undefined} - Pallet FilledDimensionUnit (possibly undefined)
843
+ */
844
+ const roundGrassQte = (currentQte, isShipping, palUnit) => {
845
+ let newQte = currentQte;
846
+ switch (true) {
847
+ case currentQte < 1480:
848
+ const rest1480 = currentQte % 10;
849
+ if (rest1480 !== 0) {
850
+ newQte = currentQte - rest1480 + 10;
851
+ }
852
+ break;
853
+ case currentQte >= 1480 && !!!isShipping:
854
+ const rest1480Install = currentQte % 10;
855
+ if (rest1480Install !== 0) {
856
+ newQte = currentQte - rest1480Install + 10;
857
+ }
858
+ break;
859
+ case currentQte >= 1480:
860
+ if (!!palUnit && !!palUnit.fitting_unit) {
861
+ let rest1480 = currentQte % palUnit.fitting_unit;
862
+ if (rest1480 !== 0 && !!((rest1480 - 400) % palUnit.fitting_unit)) {
863
+ newQte = currentQte - rest1480;
864
+ if (newQte + 400 > currentQte) {
865
+ newQte = newQte + 400;
866
+ }
867
+ else if (newQte + palUnit.fitting_unit > currentQte) {
868
+ newQte = newQte + palUnit.fitting_unit;
869
+ }
870
+ }
871
+ }
872
+ break;
873
+ }
874
+ return newQte;
875
+ };
876
+ exports.roundGrassQte = roundGrassQte;
877
+ /**
878
+ * Detects if customer has "Installation tout inclus".
879
+ * @param customPriceList - Customer custom price list
880
+ * @return All inclusive installation if exists, undefined otherwise
881
+ */
882
+ const getInstallationAllInclusiveFromPriceList = (customPriceList) => {
883
+ if (!!!customPriceList || !!!customPriceList.length)
884
+ return;
885
+ const item = customPriceList.find((i) => i.sku === products_2.installationAllInclusiveSku);
886
+ const active = !!item && !!item.price;
887
+ if (!active)
888
+ return;
889
+ return item;
890
+ };
891
+ exports.getInstallationAllInclusiveFromPriceList = getInstallationAllInclusiveFromPriceList;
892
+ /**
893
+ * Checks if all-inclusive installation is active.
894
+ * @param hasInstallation - Whether the cart/form contains an installation
895
+ * @param isPro - Whether the customer is a pro
896
+ * @param customPriceList - Customer custom price list
897
+ * @returns true if all-inclusive installation is active
898
+ */
899
+ const isInstallAllInclusiveActive = (hasInstallation, isPro, customPriceList) => {
900
+ return !!hasInstallation && !!isPro && !!(0, exports.getInstallationAllInclusiveFromPriceList)(customPriceList);
901
+ };
902
+ exports.isInstallAllInclusiveActive = isInstallAllInclusiveActive;
903
+ /**
904
+ * Force )$ to kentucky base grass and sod delivery fee if install all-inclusive.
905
+ * @param item - The cart item to potentially override
906
+ * @returns The item with zeroed price if applicable, or the original item
907
+ */
908
+ const applyAllInclusiveOverrides = (item) => {
909
+ const isKentucky = item.parent_slug === 'kentucky' || item.sku === products_2.kentucky;
910
+ const isSodDelivery = item.parent_slug === 'livraison-gazon' && products_2.sodDeliverySkus.includes(item.sku);
911
+ if (isKentucky || isSodDelivery) {
912
+ return Object.assign(Object.assign({}, item), { regular_price: Object.assign(Object.assign({}, item.regular_price), { amount: 0 }), discount_price: null, promo_price: null, price_override: true });
913
+ }
914
+ return item;
915
+ };
916
+ exports.applyAllInclusiveOverrides = applyAllInclusiveOverrides;
917
+ // Determines if a cart item should be hidden from checkout display. Used for all-inclusive installation
918
+ const shouldHideItemInCheckout = (item, allItems) => {
919
+ const hasAllInclusive = allItems.some((i) => i.sku === products_2.installationAllInclusiveSku);
920
+ if (!hasAllInclusive)
921
+ return false;
922
+ if (item.regular_price.amount !== 0)
923
+ return false;
924
+ // Hide installation upsells at $0 (mobilisation, fertilisation, roulage, etc.)
925
+ const installationSkus = allItems.filter((i) => i.parent_slug === 'installation-gazon').map((i) => i.sku);
926
+ if (!!item.is_upsell_of_sku && installationSkus.includes(item.is_upsell_of_sku))
927
+ return true;
928
+ // Hide sod delivery at $0
929
+ if (item.parent_slug === 'livraison-gazon')
930
+ return true;
931
+ // Hide installation surcharges at $0 (e.g. surcharge mobilisation île de Montréal)
932
+ if (item.parent_slug === 'surcharges-installation-gazon')
933
+ return true;
934
+ return false;
935
+ };
936
+ exports.shouldHideItemInCheckout = shouldHideItemInCheckout;
937
+ // Check si la surcharge carburant match l'item
938
+ const matchesFuelSurchargeParent = (surchargeSku, item) => {
939
+ switch (surchargeSku) {
940
+ case products_2.fuelSurchargeGazonSku:
941
+ return item.sku === products_2.kentucky || item.parent_slug === 'kentucky';
942
+ case products_2.fuelSurchargeLivraisonSku:
943
+ return (!!item.parent_slug &&
944
+ ['livraison-gazon', 'livraison-beton-accessoires'].includes(item.parent_slug));
945
+ case products_2.fuelSurchargeMobilisationSku:
946
+ return item.parent_slug === 'frais-de-mobilisation';
947
+ default:
948
+ return false;
949
+ }
950
+ };
951
+ exports.matchesFuelSurchargeParent = matchesFuelSurchargeParent;
952
+ const getInstallationArray = async (qte, baseGrassUpsells, fetchProduct, locale, isPro, chosenSku, customPriceList, returnOtherFees) => {
953
+ var _a;
954
+ const upsell = baseGrassUpsells;
955
+ if (!!!upsell)
956
+ return [];
957
+ const installation_upsell = upsell.filter((upsell) => upsell.recommendation_parent_slug === 'installation-gazon');
958
+ const installation_parent = await fetchProduct('installation-gazon', locale, true, true);
959
+ let installation_decli;
960
+ const minQteInstall = (0, expedition_1.getMinQteInstall)(isPro);
961
+ // Variable pour vérifier si une déclinaison d'installation existe déjà dans le cart
962
+ // ** Utile pour la modification des items du cart, vu que la props is_upsell_of_sku ne peut pas se modifier on update
963
+ let arrayFinal = [];
964
+ if (!!installation_parent && !!installation_upsell && !!installation_upsell.length) {
965
+ let installation_array = [];
966
+ if (!!isPro) {
967
+ installation_array = installation_parent.declinations.filter((decli) => !!decli.attributes &&
968
+ !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE] &&
969
+ !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE].includes('pro'));
970
+ }
971
+ else {
972
+ installation_array = installation_parent.declinations.filter((decli) => !!decli.attributes &&
973
+ !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE] &&
974
+ !!decli.attributes[data_1.AttributesIdEnumGR.CLIENT_TYPE].includes('au-detail'));
975
+ }
976
+ const installation_qte_array = installation_upsell.filter((upsell) => installation_array.find((decli) => decli.sku === upsell.recommendation_sku));
977
+ const closestQte = (0, maxBy_1.default)(installation_qte_array.filter((upsell) => {
978
+ return upsell.actual_qty <= qte;
979
+ }), 'actual_qty');
980
+ // MODIFS. FRAIS 2024 - On n'ajoute pas les frais au panier si leur prix régulier est de 0.00$
981
+ // Vérification faite à chaque ajout de déclinaison au arrayFinal
982
+ if (!!closestQte) {
983
+ installation_decli = installation_parent.declinations.find((decli) => decli.sku === closestQte.recommendation_sku);
984
+ // Check if customer has installation all-inclusive
985
+ const allInclusivePriceItem = !!isPro && !!customPriceList ? (0, exports.getInstallationAllInclusiveFromPriceList)(customPriceList) : undefined;
986
+ if (!!installation_decli) {
987
+ const allInclusiveDecli = !!allInclusivePriceItem && !!installation_parent
988
+ ? installation_parent.declinations.find((d) => d.sku === allInclusivePriceItem.sku)
989
+ : undefined;
990
+ if (!!allInclusivePriceItem && !!allInclusiveDecli) {
991
+ const priceAmount = (_a = allInclusivePriceItem.price) !== null && _a !== void 0 ? _a : allInclusivePriceItem.reg;
992
+ installation_decli = Object.assign(Object.assign({}, allInclusiveDecli), { regular_price: Object.assign(Object.assign({}, allInclusiveDecli.regular_price), { amount: priceAmount }) });
993
+ }
994
+ else {
995
+ if (!!isPro && !!customPriceList) {
996
+ installation_decli = (0, g2_1.checkForCustomPriceEquivalent)(installation_decli, customPriceList);
997
+ }
998
+ }
999
+ // Add the correct installation option depending on whether the customer has "Installation tout inclus"
1000
+ if (!(0, exports.shouldHideItemIfRegPriceIs0)(installation_decli, installation_parent.slug)) {
1001
+ arrayFinal.push(Object.assign(Object.assign({}, installation_decli), { parent_slug: 'installation-gazon', qte: qte, is_upsell_of_sku: chosenSku, product_upsells: installation_parent.product_upsells }));
1002
+ }
1003
+ }
1004
+ // Frais minimum d'installation
1005
+ if (qte < minQteInstall) {
1006
+ const minimum_installation_fee = await fetchProduct('frais-minimum-gazon-pour-installation', locale, true, true);
1007
+ if (!!minimum_installation_fee) {
1008
+ let minInstallDecli = minimum_installation_fee.declinations[0];
1009
+ minInstallDecli = Object.assign(Object.assign({}, minInstallDecli), { regular_price: Object.assign(Object.assign({}, minInstallDecli.regular_price), { amount: installation_decli.regular_price.amount }) });
1010
+ if (!!isPro && !!customPriceList) {
1011
+ minInstallDecli = (0, g2_1.checkForCustomPriceEquivalent)(Object.assign(Object.assign({}, minInstallDecli), { price_override: true }), customPriceList);
1012
+ }
1013
+ if (!(0, exports.shouldHideItemIfRegPriceIs0)(minInstallDecli, minimum_installation_fee.slug)) {
1014
+ arrayFinal.push(Object.assign(Object.assign({}, minInstallDecli), { parent_slug: 'frais-minimum-gazon-pour-installation', qte: minQteInstall - qte, is_upsell_of_sku: installation_decli.sku, price_override: true }));
1015
+ }
1016
+ }
1017
+ }
1018
+ // Frais de mobilisation (pour l'installation)
1019
+ const mobilisation_fee = await fetchProduct('frais-de-mobilisation', locale, true, true);
1020
+ if (!!mobilisation_fee && !!isPro) {
1021
+ let mobilisationDecli = mobilisation_fee.declinations[0];
1022
+ if (!!customPriceList) {
1023
+ mobilisationDecli = (0, g2_1.checkForCustomPriceEquivalent)(mobilisationDecli, customPriceList);
1024
+ }
1025
+ if (!(0, exports.shouldHideItemIfRegPriceIs0)(mobilisationDecli, mobilisation_fee.slug, true)) {
1026
+ arrayFinal.push(Object.assign(Object.assign({}, mobilisationDecli), { parent_slug: 'frais-de-mobilisation', qte: (0, ceil_1.default)(qte > minQteInstall
1027
+ ? qte / (740 * expedition_1.installationFeePalletTier)
1028
+ : minQteInstall / (740 * expedition_1.installationFeePalletTier)), is_upsell_of_sku: installation_decli.sku, product_upsells: mobilisation_fee.product_upsells }));
1029
+ }
1030
+ }
1031
+ // -----------------------------------------------------------------------
1032
+ // AUTRES FRAIS CONNEXES
1033
+ if (!!returnOtherFees) {
1034
+ if (!!returnOtherFees.engrais) {
1035
+ // fertilisation
1036
+ const fertilisation = await fetchProduct('installation-fertilisation', locale, true, true);
1037
+ if (!!fertilisation) {
1038
+ let minFertilisationDecli = fertilisation.declinations[0];
1039
+ if (!!isPro && !!customPriceList) {
1040
+ minFertilisationDecli = (0, g2_1.checkForCustomPriceEquivalent)(minFertilisationDecli, customPriceList);
1041
+ }
1042
+ if (!(0, exports.shouldHideItemIfRegPriceIs0)(minFertilisationDecli, fertilisation.slug, true)) {
1043
+ arrayFinal.push(Object.assign(Object.assign({}, minFertilisationDecli), { parent_slug: fertilisation.slug, qte: qte < minQteInstall ? minQteInstall : qte, is_upsell_of_sku: installation_decli.sku, product_upsells: fertilisation.product_upsells }));
1044
+ }
1045
+ }
1046
+ }
1047
+ if (returnOtherFees.roulage) {
1048
+ // roullage
1049
+ const roullage = await fetchProduct('installation-roulage', locale, true, true);
1050
+ if (!!roullage) {
1051
+ let minRoulageDecli = roullage.declinations[0];
1052
+ if (!!isPro && !!customPriceList) {
1053
+ minRoulageDecli = (0, g2_1.checkForCustomPriceEquivalent)(minRoulageDecli, customPriceList);
1054
+ }
1055
+ if (!(0, exports.shouldHideItemIfRegPriceIs0)(minRoulageDecli, roullage.slug, true)) {
1056
+ arrayFinal.push(Object.assign(Object.assign({}, minRoulageDecli), { parent_slug: roullage.slug, qte: qte < minQteInstall ? minQteInstall : qte, is_upsell_of_sku: installation_decli.sku, product_upsells: roullage.product_upsells }));
1057
+ }
1058
+ }
1059
+ }
1060
+ }
1061
+ }
1062
+ }
1063
+ return arrayFinal;
1064
+ };
1065
+ exports.getInstallationArray = getInstallationArray;
1066
+ const getInstallItemPrice = (parentSlug, servicesFees) => {
1067
+ let price = 0;
1068
+ switch (parentSlug) {
1069
+ case 'installation-gazon':
1070
+ const itemsToUse = servicesFees.filter((i) => i.parent_slug && ['installation-gazon', 'frais-de-mobilisation'].includes(i.parent_slug));
1071
+ if (!!itemsToUse) {
1072
+ price = (0, sumBy_1.default)(itemsToUse, (item) => (0, products_1.getLowestPrice)(item).price.amount * item.qte);
1073
+ }
1074
+ break;
1075
+ default:
1076
+ const itemToUse = servicesFees.find((i) => i.parent_slug === parentSlug);
1077
+ if (!!itemToUse) {
1078
+ price = (0, products_1.getLowestPrice)(itemToUse).price.amount * itemToUse.qte;
1079
+ }
1080
+ break;
1081
+ }
1082
+ return price;
1083
+ };
1084
+ exports.getInstallItemPrice = getInstallItemPrice;
1085
+ // #endregion
1086
+ // ----------------------------------------------------------------------------------------------------------
1087
+ // ----------------------------------------------------------------------------------------------------------
1088
+ // #region CONCRETE
1089
+ const getConcreteQteText = (declination, locale = 'fr') => {
1090
+ let txt = '';
1091
+ if (!!!declination)
1092
+ return txt;
1093
+ let nbSaleUnitsPerCmdStep = 0;
1094
+ let nbUnitsPerPal = 0;
1095
+ const other_units = declination.other_units;
1096
+ if (!!!other_units || !!!other_units.length) {
1097
+ return '';
1098
+ }
1099
+ else {
1100
+ const commandStep = other_units.find((unit) => unit.is_command_step);
1101
+ const commandUnit = other_units.find((unit) => unit.is_command_unit);
1102
+ const saleUnit = other_units.find((unit) => unit.is_sale_unit);
1103
+ const unitsPerPal = other_units.find((unit) => unit.unit_slug === 'pal');
1104
+ if (!!commandStep &&
1105
+ !!commandStep.fitting_unit &&
1106
+ !!commandUnit &&
1107
+ !!commandUnit.fitting_unit &&
1108
+ !!saleUnit &&
1109
+ !!saleUnit.fitting_unit &&
1110
+ !!unitsPerPal &&
1111
+ !!unitsPerPal.fitting_unit) {
1112
+ const cmdSameAsSale = commandStep.unit_slug === saleUnit.unit_slug;
1113
+ const nbP2PerRgSlug = !!cmdSameAsSale ? commandUnit.unit_slug : saleUnit.unit_slug;
1114
+ nbSaleUnitsPerCmdStep = !!cmdSameAsSale
1115
+ ? commandStep.fitting_unit / commandUnit.fitting_unit
1116
+ : commandStep.fitting_unit / saleUnit.fitting_unit;
1117
+ // Round at correct decimals for products where commandStep.fitting_unit is 1 (meaning value calculated before is correct sell units per step)
1118
+ nbUnitsPerPal =
1119
+ commandStep.fitting_unit == 1 && !!!commandStep.is_sale_unit
1120
+ ? unitsPerPal.fitting_unit *
1121
+ (0, round_1.default)(nbSaleUnitsPerCmdStep, (0, exports.productUnitSupportsDecimals)(saleUnit.unit_slug) ? 5 : 0)
1122
+ : unitsPerPal.fitting_unit / saleUnit.fitting_unit;
1123
+ txt = (0, locale_1.translateILang)({
1124
+ fr: 'Pour ce produit, vous devez commander par *cmdStep* (*nbUnitsPerCmdStep*).',
1125
+ en: 'For this product, you have to order by *cmdStep* (*nbUnitsPerCmdStep*).'
1126
+ }, locale);
1127
+ if (unitsPerPal.unit_slug != commandStep.unit_slug) {
1128
+ txt += (0, locale_1.translateILang)({
1129
+ fr: ' Une palette = *nbUnitsPerPal*.',
1130
+ en: ' A pallet = *nbUnitsPerPal*.'
1131
+ }, locale);
1132
+ }
1133
+ txt = txt.replace('*cmdStep*', String(`${(0, locale_1.translateILang)(inventories_1.unitDict[commandStep.unit_slug], locale).toLowerCase()}`));
1134
+ txt = txt.replace('*nbUnitsPerCmdStep*', String(`${(0, round_1.default)(nbSaleUnitsPerCmdStep, 2)} ${(0, locale_1.translateILang)(inventories_1.unitDict[nbP2PerRgSlug], locale).toLowerCase()}`));
1135
+ txt = txt.replace('*nbUnitsPerPal*', String(`${(0, round_1.default)(nbUnitsPerPal, 2)} ${(0, locale_1.translateILang)(inventories_1.unitDict[saleUnit.unit_slug], locale).toLowerCase()}`));
1136
+ }
1137
+ else {
1138
+ return '';
1139
+ }
1140
+ }
1141
+ return txt;
1142
+ };
1143
+ exports.getConcreteQteText = getConcreteQteText;
1144
+ /**
1145
+ * @description returns all items in cart where attribute AVAILABILITY contains wanted type.
1146
+ * @param cartData
1147
+ * @param availabilityType
1148
+ */
1149
+ const getConcreteItemsByAvailability = (cartData, availabilityType, returnTrueIfUndefined) => {
1150
+ return cartData.items.filter((i) => {
1151
+ return ((i.attributes[data_1.AttributesIdEnumGR.AVAILABILITY] &&
1152
+ i.attributes[data_1.AttributesIdEnumGR.AVAILABILITY][0] === availabilityType) ||
1153
+ !!returnTrueIfUndefined);
1154
+ });
1155
+ };
1156
+ exports.getConcreteItemsByAvailability = getConcreteItemsByAvailability;
1157
+ // #endregion
1158
+ // ----------------------------------------------------------------------------------------------------------
1159
+ // ----------------------------------------------------------------------------------------------------------
1160
+ // #region VRAC
1161
+ /**
1162
+ * Function getVracType - constructs vrac helper object is cart contains vrac or vrac associated items.
1163
+ * @param stores
1164
+ * @param cartData
1165
+ * @param getInventoryItemCallback
1166
+ * @param inventoryItemArray
1167
+ * @returns IVracType object containing vrac_type enum value and vrac_store_ids where vrac items are available
1168
+ */
1169
+ const getVracType = async (stores, cartData, getInventoryItemCallback, inventoyItemArray) => {
1170
+ const items = cartData.items;
1171
+ // If cart does not contain vrac or vrac-agacent accessories (.is_other_type==='vrac)), return
1172
+ if (!!!items ||
1173
+ !!!items.length ||
1174
+ (!!!(0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.VRAC, cartData) &&
1175
+ !!!cartData.items.find((item) => !!item.is_other_type && item.is_other_type === 'vrac')))
1176
+ return;
1177
+ let allStoreIds = stores.map((store) => store.id);
1178
+ let itemFormat = '';
1179
+ await Promise.all(items.map(async (item) => {
1180
+ const productInventory = !!!item.is_service
1181
+ ? !!inventoyItemArray && !!inventoyItemArray.length
1182
+ ? inventoyItemArray.find((i) => i.sku === item.sku)
1183
+ : await getInventoryItemCallback(item.sku)
1184
+ : undefined;
1185
+ if (!!!productInventory)
1186
+ return;
1187
+ allStoreIds = allStoreIds.filter((id) => {
1188
+ const sameStoreInProdInventory = productInventory.inventories.find((i) => i.store_id === id);
1189
+ if (!!!sameStoreInProdInventory)
1190
+ return true;
1191
+ return !!!sameStoreInProdInventory.unavailable_in_store;
1192
+ });
1193
+ if (!!!itemFormat && !!item.attributes && !!item.attributes[data_1.AttributesIdEnumGR.FORMATS]) {
1194
+ itemFormat = item.attributes[data_1.AttributesIdEnumGR.FORMATS][0];
1195
+ }
1196
+ }));
1197
+ const onlySteJulieNobel = allStoreIds.length === 1 && allStoreIds[0] === 'sainte-julie-nobel';
1198
+ if (!!itemFormat.includes('sac')) {
1199
+ return {
1200
+ vrac_type: !!onlySteJulieNobel ? products_3.VracTypeEnum.NOBEL_SAC : products_3.VracTypeEnum.AUTRE_SAC,
1201
+ vrac_store_ids: allStoreIds
1202
+ };
1203
+ }
1204
+ else {
1205
+ return {
1206
+ vrac_type: !!onlySteJulieNobel ? products_3.VracTypeEnum.NOBEL_TONNE : products_3.VracTypeEnum.AUTRE_TONNE,
1207
+ vrac_store_ids: allStoreIds
1208
+ };
1209
+ }
1210
+ };
1211
+ exports.getVracType = getVracType;
1212
+ // #endregion
1213
+ // ----------------------------------------------------------------------------------------------------------
1214
+ // ----------------------------------------------------------------------------------------------------------
1215
+ // #region FEES
1216
+ /**
1217
+ * Get all possible fees for a cart with basic info, to show approx. fee total before all data is saved in cart
1218
+ *
1219
+ * @param useFees If local fee array should be used, to save database calls
1220
+ * @param newCart Current cart data
1221
+ * @param deliveryType If fees should be checked for a pick-up or shipping order
1222
+ * @param fetchProduct Callback function for product fetch
1223
+ * @param getIfAddressIsInsideZones Callback function for zone check
1224
+ * @param getDistanceFromAddress Callback function to check distance with provided address
1225
+ * @param locale User's locale (fr or en)
1226
+ * @param allStores Full store array for space
1227
+ * @param isPro If customer associated with cart is a pro customer
1228
+ * @param grassProduct Constructed grass product from cart (with extra data for checks)
1229
+ * @param concreteOrder Constructed concrete products from cart (with extra data for checks)
1230
+ * @param settings.addOnePalletToPickup Optionnal - If additionnal pal. should be added for order
1231
+ * @param settings.saveToShippingPayload Optional - If data collected should be saved to cart's shipping_payload
1232
+ * @param settings.useStoreAddress Optionnal - Provided store ID for which the address should be used for check
1233
+ * @param settings.useDeliveryAddress Optionnal - If current carts shipping address should be used for check
1234
+ * @param settings.useAvailableVracStores Optionnal - Provided array of store IDs available for vrac order
1235
+ * @param customPriceList Optionnal - If pro customer with G2 custom price list and custom prices should be checked
1236
+ */
1237
+ const fetchFeesBeforeCart = async (useFees, newCart, deliveryType, fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, locale, allStores, isPro, grassProduct, concreteOrder, settings, customPriceList) => {
1238
+ const cartContainsVrac = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.VRAC, newCart);
1239
+ const cartContainsInstallation = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.INSTALLATION, newCart);
1240
+ const cartContainsSample = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.SAMPLE, newCart);
1241
+ const cartContainsAccessoriesOnly = (0, cart_1.checkIfCartContainsType)(cart_2.CartGeneralTypeEnum.ONLY_ACCESSORIES, newCart);
1242
+ const storeToUse = !!settings && !!settings.useStoreAddress ? allStores.find((s) => s.id == settings.useStoreAddress) : undefined;
1243
+ const storeAddressToUse = !!storeToUse ? storeToUse.address : undefined;
1244
+ return await (0, expedition_1.applyFeesToCart)(fetchProduct, getIfAddressIsInsideZones, getDistanceFromAddress, newCart, deliveryType, grassProduct, concreteOrder, deliveryType === 'pickup' ? false : cartContainsInstallation, cartContainsVrac, (0, object_1.recursiveCheckObject)(settings, 'useAvailableVracStores'), isPro, deliveryType === 'pickup' ? !!settings && !!settings.addOnePalletToPickup : false, cartContainsSample, !!settings ? !!settings.saveToShippingPayload : false, !!!settings
1245
+ ? undefined
1246
+ : !!settings.useStoreAddress && !!storeAddressToUse
1247
+ ? storeAddressToUse
1248
+ : !!settings.useDeliveryAddress && !!newCart.shipping_address
1249
+ ? newCart.shipping_address.address
1250
+ : undefined, locale, undefined, false, cartContainsAccessoriesOnly, undefined, allStores, customPriceList, !!useFees);
1251
+ };
1252
+ exports.fetchFeesBeforeCart = fetchFeesBeforeCart;
1253
+ // #endregion
1254
+ // ----------------------------------------------------------------------------------------------------------
1255
+ // ----------------------------------------------------------------------------------------------------------
1256
+ // #region PRO SPECIFICITIES
1257
+ /**
1258
+ * Check if pro custom promo info should be shown for customer for a specific product.
1259
+ * @param userData
1260
+ * @param isPro
1261
+ * @param product
1262
+ * @param customMinPrice
1263
+ */
1264
+ const shouldShowProCustomPromo = (userData, isPro, product, customMinPrice) => {
1265
+ if (!!!product || !!!isPro || !!!userData)
1266
+ return false;
1267
+ // If customMinPrice is defined (meaning customer has custom price list), and the price type is not REG or has type NET, always return true
1268
+ if (!!customMinPrice) {
1269
+ if (customMinPrice.type === G2_1.CustomPriceItemTypeEnum.REG && customMinPrice.code2 !== 'NET')
1270
+ return false;
1271
+ return true;
1272
+ }
1273
+ // Check customer group. If promo exists and should apply for customer group, return true
1274
+ const customerGroup = (0, object_1.recursiveCheckObject)(userData, 'userData.basic_info.customer_professionnal_info.external_customer_group');
1275
+ const customerType = !!customerGroup ? (0, g2_1.getG2CustomerTypeFromCode)(customerGroup) : undefined;
1276
+ const prodPriceClass = !!product.price_classes_range
1277
+ ? product.price_classes_range.find((range) => !!customerType && range.external_slug ? range.external_slug === customerType : range.class === 'aspirant')
1278
+ : !!product.prices_list
1279
+ ? product.prices_list.find((range) => !!customerType && range.external_slug ? range.external_slug === customerType : range.group_id === 'aspirant')
1280
+ : undefined;
1281
+ return !!prodPriceClass && !!prodPriceClass.custom_promo_applies;
1282
+ };
1283
+ exports.shouldShowProCustomPromo = shouldShowProCustomPromo;
1284
+ const applyProCustomPromo = (decli, userData) => {
1285
+ const customerCode = userData.basic_info.customer_professionnal_info &&
1286
+ userData.basic_info.customer_professionnal_info.external_customer_group;
1287
+ if (!!!customerCode)
1288
+ return {};
1289
+ const customerCustomPromo = (0, g2_1.getG2DiscountFromCode)(customerCode);
1290
+ if (!!!customerCustomPromo)
1291
+ return {};
1292
+ const regPrice = decli.regular_price.amount;
1293
+ const newDiscountAmount = (0, toNumber_1.default)(regPrice) * ((100 - customerCustomPromo) / 100);
1294
+ let newPromoObj = (0, IDiscountRule_1.getDefaultDiscountRule)('product');
1295
+ newPromoObj = Object.assign(Object.assign({}, newPromoObj), { appliesTo: Object.assign(Object.assign({}, newPromoObj.appliesTo), { label: IDiscountRule_1.AppliesToEnum.PRODUCT, value: decli.sku }), rules: [
1296
+ {
1297
+ field: IDiscountRule_1.RuleFieldEnum.CUSTOMER,
1298
+ condition: IDiscountRule_1.RuleConditionEnum.AND,
1299
+ ruleDetails: [
1300
+ {
1301
+ operator: '==',
1302
+ value: [userData.id],
1303
+ condition: IDiscountRule_1.RuleConditionEnum.AND
1304
+ }
1305
+ ]
1306
+ }
1307
+ ], result: {
1308
+ action: IDiscountRule_1.ResultActionEnum.PERCENT,
1309
+ action_value: customerCustomPromo
1310
+ } });
1311
+ return {
1312
+ discount_rules: [newPromoObj],
1313
+ promo_price: {
1314
+ currency: 'CAD',
1315
+ amount: (0, round_1.default)(newDiscountAmount, 3)
1316
+ }
1317
+ };
1318
+ };
1319
+ exports.applyProCustomPromo = applyProCustomPromo;
1320
+ // Indexed products - Custom prices if pro
1321
+ const getFormattedProdGR = (decli, productSlug, isPro) => {
1322
+ const { promo_price, discount_price, tier_pricing } = decli, rest = __rest(decli, ["promo_price", "discount_price", "tier_pricing"]);
1323
+ return !!isPro ? Object.assign(Object.assign({}, rest), (productSlug !== 'kentucky' ? { tier_pricing } : {})) : decli;
1324
+ };
1325
+ exports.getFormattedProdGR = getFormattedProdGR;
1326
+ /**
1327
+ * Checks if a 0.00$ reg_price item should be considered "hidden" or not.
1328
+ * @param item - The indexedDecli or cartItem to check
1329
+ * @param productSlug - The parent product's slug (in case it is not found in item)
1330
+ * @param isUpsellOfInstallProd - Optionnal. If item is upsell of install product (additionnal fee for installation)
1331
+ */
1332
+ const shouldHideItemIfRegPriceIs0 = (item, productSlug, isUpsellOfInstallProd) => {
1333
+ // A. Check if reg price is 0. If not, should not hide item
1334
+ const regPriceIs0 = item.regular_price.amount == 0;
1335
+ if (!regPriceIs0)
1336
+ return false;
1337
+ // B. Check if item is fee or service. If not, should not hide item
1338
+ if (!item.is_service)
1339
+ return false;
1340
+ // C. Check if item is an upsell of an installation product (additionnal install fees). If so, should not hide item
1341
+ if (!!isUpsellOfInstallProd)
1342
+ return false;
1343
+ // D. Check if item is a shipping fee. If so, should not hide item
1344
+ if (expedition_1.slugsToCheckFromExpeditionFees.shipping.includes(productSlug))
1345
+ return false;
1346
+ return true;
1347
+ };
1348
+ exports.shouldHideItemIfRegPriceIs0 = shouldHideItemIfRegPriceIs0;
1349
+ // #endregion
1350
+ // ----------------------------------------------------------------------------------------------------------
1351
1351
  //# sourceMappingURL=products.js.map