@pisell/pisellos 0.0.568 → 0.0.569

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 (413) hide show
  1. package/dist/model/strategy/adapter/promotion/evaluator.js +3 -2
  2. package/dist/model/strategy/adapter/walletPass/utils.js +7 -4
  3. package/dist/modules/BaseModule.d.ts +2 -2
  4. package/dist/modules/BaseModule.js +4 -4
  5. package/dist/modules/BookingContext/index.d.ts +48 -0
  6. package/dist/modules/BookingContext/index.js +566 -0
  7. package/dist/modules/BookingContext/types.d.ts +102 -0
  8. package/dist/modules/BookingContext/types.js +51 -0
  9. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  10. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +302 -0
  11. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  12. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +149 -0
  13. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +76 -0
  14. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +249 -0
  15. package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
  16. package/dist/modules/BookingContext/utils/flexible.js +56 -0
  17. package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  18. package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
  19. package/dist/modules/BookingContext/utils/index.d.ts +11 -0
  20. package/dist/modules/BookingContext/utils/index.js +11 -0
  21. package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
  22. package/dist/modules/BookingContext/utils/noResource.js +77 -0
  23. package/dist/modules/BookingContext/utils/orderLineDisplay.d.ts +1 -0
  24. package/dist/modules/BookingContext/utils/orderLineDisplay.js +36 -0
  25. package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
  26. package/dist/modules/BookingContext/utils/productExtend.js +339 -0
  27. package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  28. package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
  29. package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  30. package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
  31. package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
  32. package/dist/modules/BookingContext/utils/resources.js +486 -0
  33. package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  34. package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
  35. package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  36. package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
  37. package/dist/modules/Cart/utils/cartProduct.js +26 -5
  38. package/dist/modules/Cart/utils/changePrice.js +27 -20
  39. package/dist/modules/Customer/index.d.ts +20 -0
  40. package/dist/modules/Customer/index.js +172 -83
  41. package/dist/modules/Customer/types.d.ts +2 -0
  42. package/dist/modules/Discount/index.d.ts +2 -1
  43. package/dist/modules/Discount/index.js +37 -9
  44. package/dist/modules/Discount/types.d.ts +1 -0
  45. package/dist/modules/OpenData/index.d.ts +8 -0
  46. package/dist/modules/OpenData/index.js +36 -16
  47. package/dist/modules/Order/index.d.ts +448 -23
  48. package/dist/modules/Order/index.js +5417 -561
  49. package/dist/modules/Order/types.d.ts +693 -88
  50. package/dist/modules/Order/types.js +68 -1
  51. package/dist/modules/Order/utils/bundleDiscountHydration.d.ts +5 -0
  52. package/dist/modules/Order/utils/bundleDiscountHydration.js +144 -0
  53. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  54. package/dist/modules/Order/utils/manualProductDiscount.js +210 -0
  55. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  56. package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
  57. package/dist/modules/Order/utils.d.ts +167 -18
  58. package/dist/modules/Order/utils.js +960 -165
  59. package/dist/modules/Payment/index.d.ts +10 -9
  60. package/dist/modules/Payment/index.js +465 -703
  61. package/dist/modules/Payment/types.d.ts +40 -16
  62. package/dist/modules/Payment/utils.d.ts +1 -1
  63. package/dist/modules/Payment/utils.js +4 -3
  64. package/dist/modules/Payment/walletpass.js +44 -29
  65. package/dist/modules/Product/types.d.ts +29 -7
  66. package/dist/modules/ProductList/index.d.ts +17 -13
  67. package/dist/modules/ProductList/index.js +184 -74
  68. package/dist/modules/ProductList/types.d.ts +17 -0
  69. package/dist/modules/Quotation/index.d.ts +22 -2
  70. package/dist/modules/Quotation/index.js +108 -42
  71. package/dist/modules/Quotation/types.d.ts +19 -0
  72. package/dist/modules/ResourcePlanner/index.d.ts +24 -0
  73. package/dist/modules/ResourcePlanner/index.js +181 -0
  74. package/dist/modules/ResourcePlanner/planner.d.ts +14 -0
  75. package/dist/modules/ResourcePlanner/planner.js +1069 -0
  76. package/dist/modules/ResourcePlanner/types.d.ts +227 -0
  77. package/dist/modules/ResourcePlanner/types.js +1 -0
  78. package/dist/modules/Rules/index.d.ts +8 -10
  79. package/dist/modules/Rules/index.js +221 -109
  80. package/dist/modules/Rules/types.d.ts +14 -3
  81. package/dist/modules/SalesSummary/index.d.ts +23 -26
  82. package/dist/modules/SalesSummary/index.js +152 -46
  83. package/dist/modules/SalesSummary/types.d.ts +9 -1
  84. package/dist/modules/SalesSummary/utils.d.ts +3 -22
  85. package/dist/modules/SalesSummary/utils.js +803 -163
  86. package/dist/modules/Schedule/getDateIsInSchedule.js +14 -7
  87. package/dist/modules/Schedule/index.d.ts +18 -5
  88. package/dist/modules/Schedule/index.js +78 -24
  89. package/dist/modules/Schedule/types.d.ts +2 -0
  90. package/dist/modules/Summary/index.js +4 -3
  91. package/dist/modules/SurchargeList/index.d.ts +18 -0
  92. package/dist/modules/SurchargeList/index.js +185 -0
  93. package/dist/modules/SurchargeList/types.d.ts +15 -0
  94. package/dist/modules/SurchargeList/types.js +1 -0
  95. package/dist/modules/index.d.ts +3 -0
  96. package/dist/modules/index.js +4 -1
  97. package/dist/plugins/app.d.ts +2 -0
  98. package/dist/plugins/request.d.ts +1 -0
  99. package/dist/server/index.d.ts +462 -8
  100. package/dist/server/index.js +6112 -656
  101. package/dist/server/modules/floor-plan/index.d.ts +39 -0
  102. package/dist/server/modules/floor-plan/index.js +595 -0
  103. package/dist/server/modules/floor-plan/types.d.ts +43 -0
  104. package/dist/server/modules/floor-plan/types.js +13 -0
  105. package/dist/server/modules/index.d.ts +7 -2
  106. package/dist/server/modules/index.js +6 -0
  107. package/dist/server/modules/order/index.d.ts +207 -14
  108. package/dist/server/modules/order/index.js +2326 -379
  109. package/dist/server/modules/order/types.d.ts +76 -5
  110. package/dist/server/modules/order/types.js +14 -1
  111. package/dist/server/modules/order/utils/filterBookings.d.ts +7 -1
  112. package/dist/server/modules/order/utils/filterBookings.js +118 -11
  113. package/dist/server/modules/order/utils/filterOrders.js +242 -14
  114. package/dist/server/modules/payment/index.d.ts +28 -0
  115. package/dist/server/modules/payment/index.js +305 -0
  116. package/dist/server/modules/payment/types.d.ts +9 -0
  117. package/dist/server/modules/payment/types.js +1 -0
  118. package/dist/server/modules/products/index.d.ts +105 -14
  119. package/dist/server/modules/products/index.js +1393 -516
  120. package/dist/server/modules/products/types.d.ts +34 -1
  121. package/dist/server/modules/products/types.js +4 -0
  122. package/dist/server/modules/quotation/index.d.ts +39 -0
  123. package/dist/server/modules/quotation/index.js +278 -66
  124. package/dist/server/modules/resource/index.d.ts +2 -3
  125. package/dist/server/modules/resource/index.js +108 -86
  126. package/dist/server/modules/schedule/index.d.ts +6 -4
  127. package/dist/server/modules/schedule/index.js +116 -85
  128. package/dist/server/test.json +713 -0
  129. package/dist/server/types.d.ts +2 -0
  130. package/dist/server/utils/product.js +2 -2
  131. package/dist/server/utils/small-ticket.d.ts +71 -0
  132. package/dist/server/utils/small-ticket.js +963 -0
  133. package/dist/solution/BaseSales/index.d.ts +378 -0
  134. package/dist/solution/BaseSales/index.js +4006 -0
  135. package/dist/solution/BaseSales/types.d.ts +394 -0
  136. package/dist/solution/BaseSales/types.js +40 -0
  137. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +287 -0
  138. package/dist/solution/BaseSales/utils/cartPromotion.js +1450 -0
  139. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +144 -0
  140. package/dist/solution/BaseSales/utils/parseSalesResponse.js +157 -0
  141. package/dist/solution/BaseSales/utils/quotationPrice.d.ts +18 -0
  142. package/dist/solution/BaseSales/utils/quotationPrice.js +250 -0
  143. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +63 -0
  144. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +218 -0
  145. package/dist/solution/BaseSales/utils.d.ts +40 -0
  146. package/dist/solution/BaseSales/utils.js +263 -0
  147. package/dist/solution/BookingByStep/index.d.ts +1 -1
  148. package/dist/solution/BookingTicket/index.d.ts +394 -25
  149. package/dist/solution/BookingTicket/index.js +2506 -443
  150. package/dist/solution/BookingTicket/types.d.ts +191 -6
  151. package/dist/solution/BookingTicket/types.js +83 -10
  152. package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +117 -0
  153. package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
  154. package/dist/solution/BookingTicket/utils/addTimeAvailability.d.ts +35 -0
  155. package/dist/solution/BookingTicket/utils/addTimeAvailability.js +95 -0
  156. package/dist/solution/BookingTicket/utils/bookingStatus.d.ts +77 -0
  157. package/dist/solution/BookingTicket/utils/bookingStatus.js +136 -0
  158. package/dist/solution/BookingTicket/utils/cartView.d.ts +29 -0
  159. package/dist/solution/BookingTicket/utils/cartView.js +209 -0
  160. package/dist/solution/BookingTicket/utils/exampleData.d.ts +123 -0
  161. package/dist/solution/BookingTicket/utils/exampleData.js +183 -0
  162. package/dist/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
  163. package/dist/solution/BookingTicket/utils/orderCustomer.js +31 -0
  164. package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +185 -0
  165. package/dist/solution/BookingTicket/utils/resolveBestAddTimePlan.js +438 -0
  166. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  167. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +400 -0
  168. package/dist/solution/BookingTicket/utils/scan/cloudSearch.d.ts +4 -0
  169. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +41 -1
  170. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  171. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.js +56 -0
  172. package/dist/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
  173. package/dist/solution/BookingTicket/utils/scan/handleScan.js +11 -3
  174. package/dist/solution/BookingTicket/utils/scan/index.d.ts +5 -0
  175. package/dist/solution/BookingTicket/utils/scan/index.js +20 -8
  176. package/dist/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  177. package/dist/solution/BookingTicket/utils/scan/scanProductValues.js +150 -0
  178. package/dist/solution/BookingTicket/utils/sessionCatalogStale.d.ts +23 -0
  179. package/dist/solution/BookingTicket/utils/sessionCatalogStale.js +78 -0
  180. package/dist/solution/Checkout/index.d.ts +1 -0
  181. package/dist/solution/Checkout/index.js +25 -34
  182. package/dist/solution/Checkout/utils/index.js +4 -4
  183. package/dist/solution/RegisterAndLogin/config.js +2 -10
  184. package/dist/solution/Sales/index.d.ts +50 -5
  185. package/dist/solution/Sales/index.js +484 -92
  186. package/dist/solution/Sales/types.d.ts +26 -2
  187. package/dist/solution/ScanOrder/index.d.ts +27 -21
  188. package/dist/solution/ScanOrder/index.js +499 -434
  189. package/dist/solution/ScanOrder/types.d.ts +33 -11
  190. package/dist/solution/ScanOrder/types.js +4 -5
  191. package/dist/solution/ScanOrder/utils.d.ts +4 -1
  192. package/dist/solution/ScanOrder/utils.js +109 -34
  193. package/dist/solution/ShopDiscount/index.js +4 -4
  194. package/dist/solution/UnifiedBookingSales/index.d.ts +183 -0
  195. package/dist/solution/UnifiedBookingSales/index.js +1871 -0
  196. package/dist/solution/UnifiedBookingSales/types.d.ts +143 -0
  197. package/dist/solution/UnifiedBookingSales/types.js +11 -0
  198. package/dist/solution/VenueBooking/index.d.ts +29 -20
  199. package/dist/solution/VenueBooking/index.js +301 -213
  200. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  201. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  202. package/dist/solution/VenueBooking/utils/slotMerge.js +9 -3
  203. package/dist/solution/index.d.ts +2 -0
  204. package/dist/solution/index.js +3 -1
  205. package/dist/types/index.d.ts +11 -1
  206. package/lib/model/strategy/adapter/promotion/evaluator.js +3 -2
  207. package/lib/model/strategy/adapter/walletPass/utils.js +6 -4
  208. package/lib/modules/BaseModule.d.ts +2 -2
  209. package/lib/modules/BaseModule.js +4 -4
  210. package/lib/modules/BookingContext/index.d.ts +48 -0
  211. package/lib/modules/BookingContext/index.js +390 -0
  212. package/lib/modules/BookingContext/types.d.ts +102 -0
  213. package/lib/modules/BookingContext/types.js +48 -0
  214. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
  215. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +286 -0
  216. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
  217. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +148 -0
  218. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +76 -0
  219. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +242 -0
  220. package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
  221. package/lib/modules/BookingContext/utils/flexible.js +63 -0
  222. package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
  223. package/lib/modules/BookingContext/utils/formatResourceList.js +35 -0
  224. package/lib/modules/BookingContext/utils/index.d.ts +11 -0
  225. package/lib/modules/BookingContext/utils/index.js +126 -0
  226. package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
  227. package/lib/modules/BookingContext/utils/noResource.js +78 -0
  228. package/lib/modules/BookingContext/utils/orderLineDisplay.d.ts +1 -0
  229. package/lib/modules/BookingContext/utils/orderLineDisplay.js +29 -0
  230. package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
  231. package/lib/modules/BookingContext/utils/productExtend.js +330 -0
  232. package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
  233. package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
  234. package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
  235. package/lib/modules/BookingContext/utils/resourceSelection.js +24 -0
  236. package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
  237. package/lib/modules/BookingContext/utils/resources.js +419 -0
  238. package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
  239. package/lib/modules/BookingContext/utils/serviceTimes.js +161 -0
  240. package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
  241. package/lib/modules/BookingContext/utils/timeSlices.js +114 -0
  242. package/lib/modules/Cart/utils/cartProduct.js +27 -5
  243. package/lib/modules/Cart/utils/changePrice.js +20 -14
  244. package/lib/modules/Customer/index.d.ts +20 -0
  245. package/lib/modules/Customer/index.js +63 -10
  246. package/lib/modules/Customer/types.d.ts +2 -0
  247. package/lib/modules/Discount/index.d.ts +2 -1
  248. package/lib/modules/Discount/index.js +18 -2
  249. package/lib/modules/Discount/types.d.ts +1 -0
  250. package/lib/modules/OpenData/index.d.ts +8 -0
  251. package/lib/modules/OpenData/index.js +21 -3
  252. package/lib/modules/Order/index.d.ts +448 -23
  253. package/lib/modules/Order/index.js +3641 -308
  254. package/lib/modules/Order/types.d.ts +693 -88
  255. package/lib/modules/Order/types.js +55 -1
  256. package/lib/modules/Order/utils/bundleDiscountHydration.d.ts +5 -0
  257. package/lib/modules/Order/utils/bundleDiscountHydration.js +106 -0
  258. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  259. package/lib/modules/Order/utils/manualProductDiscount.js +207 -0
  260. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  261. package/lib/modules/Order/utils/orderCollectionIdentity.js +353 -0
  262. package/lib/modules/Order/utils.d.ts +167 -18
  263. package/lib/modules/Order/utils.js +974 -138
  264. package/lib/modules/Payment/index.d.ts +10 -9
  265. package/lib/modules/Payment/index.js +30 -124
  266. package/lib/modules/Payment/types.d.ts +40 -16
  267. package/lib/modules/Payment/utils.d.ts +1 -1
  268. package/lib/modules/Payment/utils.js +4 -3
  269. package/lib/modules/Payment/walletpass.js +16 -6
  270. package/lib/modules/Product/types.d.ts +29 -7
  271. package/lib/modules/ProductList/index.d.ts +17 -13
  272. package/lib/modules/ProductList/index.js +92 -51
  273. package/lib/modules/ProductList/types.d.ts +17 -0
  274. package/lib/modules/Quotation/index.d.ts +22 -2
  275. package/lib/modules/Quotation/index.js +76 -20
  276. package/lib/modules/Quotation/types.d.ts +19 -0
  277. package/lib/modules/ResourcePlanner/index.d.ts +24 -0
  278. package/lib/modules/ResourcePlanner/index.js +147 -0
  279. package/lib/modules/ResourcePlanner/planner.d.ts +14 -0
  280. package/lib/modules/ResourcePlanner/planner.js +895 -0
  281. package/lib/modules/ResourcePlanner/types.d.ts +227 -0
  282. package/lib/modules/ResourcePlanner/types.js +5 -0
  283. package/lib/modules/Rules/index.d.ts +8 -10
  284. package/lib/modules/Rules/index.js +152 -60
  285. package/lib/modules/Rules/types.d.ts +14 -3
  286. package/lib/modules/SalesSummary/index.d.ts +23 -26
  287. package/lib/modules/SalesSummary/index.js +84 -16
  288. package/lib/modules/SalesSummary/types.d.ts +9 -1
  289. package/lib/modules/SalesSummary/utils.d.ts +3 -22
  290. package/lib/modules/SalesSummary/utils.js +616 -111
  291. package/lib/modules/Schedule/getDateIsInSchedule.js +14 -7
  292. package/lib/modules/Schedule/index.d.ts +18 -5
  293. package/lib/modules/Schedule/index.js +49 -14
  294. package/lib/modules/Schedule/types.d.ts +2 -0
  295. package/lib/modules/Summary/index.js +2 -2
  296. package/lib/modules/SurchargeList/index.d.ts +18 -0
  297. package/lib/modules/SurchargeList/index.js +95 -0
  298. package/lib/modules/SurchargeList/types.d.ts +15 -0
  299. package/lib/modules/SurchargeList/types.js +5 -0
  300. package/lib/modules/index.d.ts +3 -0
  301. package/lib/modules/index.js +33 -0
  302. package/lib/plugins/app.d.ts +2 -0
  303. package/lib/plugins/request.d.ts +1 -0
  304. package/lib/server/index.d.ts +462 -8
  305. package/lib/server/index.js +3901 -205
  306. package/lib/server/modules/floor-plan/index.d.ts +39 -0
  307. package/lib/server/modules/floor-plan/index.js +306 -0
  308. package/lib/server/modules/floor-plan/types.d.ts +43 -0
  309. package/lib/server/modules/floor-plan/types.js +19 -0
  310. package/lib/server/modules/index.d.ts +7 -2
  311. package/lib/server/modules/index.js +21 -0
  312. package/lib/server/modules/order/index.d.ts +207 -14
  313. package/lib/server/modules/order/index.js +1324 -141
  314. package/lib/server/modules/order/types.d.ts +76 -5
  315. package/lib/server/modules/order/types.js +11 -1
  316. package/lib/server/modules/order/utils/filterBookings.d.ts +7 -1
  317. package/lib/server/modules/order/utils/filterBookings.js +119 -11
  318. package/lib/server/modules/order/utils/filterOrders.js +238 -13
  319. package/lib/server/modules/payment/index.d.ts +28 -0
  320. package/lib/server/modules/payment/index.js +168 -0
  321. package/lib/server/modules/payment/types.d.ts +9 -0
  322. package/lib/server/modules/payment/types.js +5 -0
  323. package/lib/server/modules/products/index.d.ts +105 -14
  324. package/lib/server/modules/products/index.js +588 -97
  325. package/lib/server/modules/products/types.d.ts +34 -1
  326. package/lib/server/modules/products/types.js +3 -0
  327. package/lib/server/modules/quotation/index.d.ts +39 -0
  328. package/lib/server/modules/quotation/index.js +145 -1
  329. package/lib/server/modules/resource/index.d.ts +2 -3
  330. package/lib/server/modules/resource/index.js +71 -45
  331. package/lib/server/modules/schedule/index.d.ts +6 -4
  332. package/lib/server/modules/schedule/index.js +55 -44
  333. package/lib/server/test.json +713 -0
  334. package/lib/server/types.d.ts +2 -0
  335. package/lib/server/utils/product.js +2 -2
  336. package/lib/server/utils/small-ticket.d.ts +71 -0
  337. package/lib/server/utils/small-ticket.js +926 -0
  338. package/lib/solution/BaseSales/index.d.ts +378 -0
  339. package/lib/solution/BaseSales/index.js +2367 -0
  340. package/lib/solution/BaseSales/types.d.ts +394 -0
  341. package/lib/solution/BaseSales/types.js +47 -0
  342. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +287 -0
  343. package/lib/solution/BaseSales/utils/cartPromotion.js +1155 -0
  344. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +144 -0
  345. package/lib/solution/BaseSales/utils/parseSalesResponse.js +140 -0
  346. package/lib/solution/BaseSales/utils/quotationPrice.d.ts +18 -0
  347. package/lib/solution/BaseSales/utils/quotationPrice.js +231 -0
  348. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +63 -0
  349. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +215 -0
  350. package/lib/solution/BaseSales/utils.d.ts +40 -0
  351. package/lib/solution/BaseSales/utils.js +259 -0
  352. package/lib/solution/BookingByStep/index.d.ts +1 -1
  353. package/lib/solution/BookingTicket/index.d.ts +394 -25
  354. package/lib/solution/BookingTicket/index.js +1350 -76
  355. package/lib/solution/BookingTicket/types.d.ts +191 -6
  356. package/lib/solution/BookingTicket/types.js +71 -10
  357. package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +117 -0
  358. package/lib/solution/BookingTicket/utils/addProductDecision.js +353 -0
  359. package/lib/solution/BookingTicket/utils/addTimeAvailability.d.ts +35 -0
  360. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +94 -0
  361. package/lib/solution/BookingTicket/utils/bookingStatus.d.ts +77 -0
  362. package/lib/solution/BookingTicket/utils/bookingStatus.js +136 -0
  363. package/lib/solution/BookingTicket/utils/cartView.d.ts +29 -0
  364. package/lib/solution/BookingTicket/utils/cartView.js +200 -0
  365. package/lib/solution/BookingTicket/utils/exampleData.d.ts +123 -0
  366. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  367. package/lib/solution/BookingTicket/utils/orderCustomer.d.ts +4 -0
  368. package/lib/solution/BookingTicket/utils/orderCustomer.js +35 -0
  369. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.d.ts +185 -0
  370. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +387 -0
  371. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +36 -0
  372. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +220 -0
  373. package/lib/solution/BookingTicket/utils/scan/cloudSearch.d.ts +4 -0
  374. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +24 -3
  375. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +32 -0
  376. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +64 -0
  377. package/lib/solution/BookingTicket/utils/scan/handleScan.d.ts +3 -1
  378. package/lib/solution/BookingTicket/utils/scan/handleScan.js +4 -2
  379. package/lib/solution/BookingTicket/utils/scan/index.d.ts +5 -0
  380. package/lib/solution/BookingTicket/utils/scan/index.js +14 -2
  381. package/lib/solution/BookingTicket/utils/scan/scanProductValues.d.ts +21 -0
  382. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +115 -0
  383. package/lib/solution/BookingTicket/utils/sessionCatalogStale.d.ts +23 -0
  384. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +83 -0
  385. package/lib/solution/Checkout/index.d.ts +1 -0
  386. package/lib/solution/Checkout/index.js +18 -19
  387. package/lib/solution/Checkout/utils/index.js +4 -4
  388. package/lib/solution/RegisterAndLogin/config.js +2 -10
  389. package/lib/solution/Sales/index.d.ts +50 -5
  390. package/lib/solution/Sales/index.js +296 -39
  391. package/lib/solution/Sales/types.d.ts +26 -2
  392. package/lib/solution/ScanOrder/index.d.ts +27 -21
  393. package/lib/solution/ScanOrder/index.js +144 -103
  394. package/lib/solution/ScanOrder/types.d.ts +33 -11
  395. package/lib/solution/ScanOrder/types.js +4 -5
  396. package/lib/solution/ScanOrder/utils.d.ts +4 -1
  397. package/lib/solution/ScanOrder/utils.js +98 -26
  398. package/lib/solution/ShopDiscount/index.js +3 -3
  399. package/lib/solution/UnifiedBookingSales/index.d.ts +183 -0
  400. package/lib/solution/UnifiedBookingSales/index.js +1050 -0
  401. package/lib/solution/UnifiedBookingSales/types.d.ts +143 -0
  402. package/lib/solution/UnifiedBookingSales/types.js +14 -0
  403. package/lib/solution/VenueBooking/index.d.ts +29 -20
  404. package/lib/solution/VenueBooking/index.js +169 -94
  405. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  406. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +6 -0
  407. package/lib/solution/VenueBooking/utils/slotMerge.js +9 -3
  408. package/lib/solution/index.d.ts +2 -0
  409. package/lib/solution/index.js +22 -0
  410. package/lib/types/index.d.ts +11 -1
  411. package/package.json +1 -1
  412. package/dist/solution/Checkout/appointmentDemo.json +0 -1
  413. package/lib/solution/Checkout/appointmentDemo.json +0 -1
@@ -0,0 +1,1050 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _exportNames = {
7
+ buildPlannerDiscountResult: true,
8
+ normalizeProductForPlanner: true,
9
+ buildPlannerResourcesFromV2: true,
10
+ collectPlannerResourceIds: true,
11
+ buildBookingFromAssignment: true,
12
+ buildBookingFromAssignments: true,
13
+ buildPlannerLineIdentity: true,
14
+ UnifiedBookingSalesImpl: true,
15
+ UnifiedBookingSales: true
16
+ };
17
+ exports.UnifiedBookingSalesImpl = exports.UnifiedBookingSales = void 0;
18
+ exports.buildBookingFromAssignment = buildBookingFromAssignment;
19
+ exports.buildBookingFromAssignments = buildBookingFromAssignments;
20
+ exports.buildPlannerDiscountResult = buildPlannerDiscountResult;
21
+ exports.buildPlannerLineIdentity = buildPlannerLineIdentity;
22
+ exports.buildPlannerResourcesFromV2 = buildPlannerResourcesFromV2;
23
+ exports.collectPlannerResourceIds = collectPlannerResourceIds;
24
+ exports.normalizeProductForPlanner = normalizeProductForPlanner;
25
+ var _dayjs = _interopRequireDefault(require("dayjs"));
26
+ var _modules = require("../../modules");
27
+ var _getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
28
+ var _types = require("./types");
29
+ Object.keys(_types).forEach(function (key) {
30
+ if (key === "default" || key === "__esModule") return;
31
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
32
+ if (key in exports && exports[key] === _types[key]) return;
33
+ Object.defineProperty(exports, key, {
34
+ enumerable: true,
35
+ get: function () {
36
+ return _types[key];
37
+ }
38
+ });
39
+ });
40
+ var _BookingTicket = require("../BookingTicket");
41
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
42
+ // import { BaseSalesImpl } from '../BaseSales';
43
+
44
+ const OPEN_DATA_SECTION_CODES = ['sale', 'reservation', 'fulfillment', 'menu', 'workflow'];
45
+ const OPEN_DATA_CACHE_TTL = 5 * 60 * 1000;
46
+ function pickLocalizedText(value) {
47
+ if (!value) return undefined;
48
+ if (typeof value === 'string') return value;
49
+ if (typeof value === 'object') {
50
+ return value.en || value.zh || value.default || Object.values(value)[0];
51
+ }
52
+ return String(value);
53
+ }
54
+ function resolvePlannerDiscountId(discount) {
55
+ return discount.discount?.resource_id ?? discount.resource_id ?? discount.id;
56
+ }
57
+ function resolvePlannerDiscountTitle(discount) {
58
+ return pickLocalizedText(discount.name || discount.format_title || discount.discount?.title || discount.title);
59
+ }
60
+ function isPlannerDiscountAvailable(discount) {
61
+ return discount.isDisabled !== true && discount.isAvailable !== false && discount.config?.isAvailable !== false;
62
+ }
63
+
64
+ /**
65
+ * Converts Rules/Order discount internals into a small UI-facing diagnostic. The result keeps
66
+ * candidate-card state separate from line-level applications: a selected card is not proof that
67
+ * it actually discounted a planner product.
68
+ */
69
+ function buildPlannerDiscountResult(params) {
70
+ const {
71
+ customerId,
72
+ discountList,
73
+ products,
74
+ summaryBefore,
75
+ summaryAfter,
76
+ status,
77
+ preferredDiscountId,
78
+ preferredDiscountFound
79
+ } = params;
80
+ const items = (discountList || []).reduce((result, discount) => {
81
+ const id = resolvePlannerDiscountId(discount);
82
+ if (id !== undefined && id !== null) {
83
+ result.push({
84
+ id,
85
+ name: resolvePlannerDiscountTitle(discount),
86
+ type: discount.tag || discount.type,
87
+ available: isPlannerDiscountAvailable(discount),
88
+ selected: discount.isSelected === true,
89
+ savedAmount: Number(discount.savedAmount || 0) || undefined,
90
+ unavailableReason: discount.unavailableReason || discount.reason
91
+ });
92
+ }
93
+ return result;
94
+ }, []);
95
+ const discountNameById = new Map(items.map(item => [String(item.id), item.name]));
96
+ const applications = [];
97
+ (products || []).forEach(product => {
98
+ const productDiscounts = [...(Array.isArray(product.discount_list) ? product.discount_list : []), ...(Array.isArray(product.product_bundle) ? product.product_bundle.flatMap(bundle => bundle?.discount_list || []) : [])];
99
+ productDiscounts.forEach(discount => {
100
+ const type = discount.tag || discount.type;
101
+ if (!['good_pass', 'discount_card', 'product_discount_card'].includes(type)) return;
102
+ const discountId = resolvePlannerDiscountId(discount);
103
+ applications.push({
104
+ discountId,
105
+ discountName: discountId === undefined ? undefined : discountNameById.get(String(discountId)),
106
+ discountType: type,
107
+ productId: product.product_id ?? product.id,
108
+ productTitle: pickLocalizedText(product.title || product.name || product.product_title),
109
+ productUid: product.metadata?.unique_identification_number || product.unique_identification_number,
110
+ amount: Number(discount.amount || 0)
111
+ });
112
+ });
113
+ });
114
+ return {
115
+ status,
116
+ customerId,
117
+ preferredDiscountFound,
118
+ preferredDiscountApplied: preferredDiscountId === undefined || preferredDiscountId === null ? undefined : items.some(item => String(item.id) === String(preferredDiscountId) && item.selected) && applications.some(item => String(item.discountId) === String(preferredDiscountId)),
119
+ availableDiscounts: items.filter(item => item.available),
120
+ selectedDiscounts: items.filter(item => item.selected),
121
+ applications,
122
+ summaryBefore,
123
+ summaryAfter
124
+ };
125
+ }
126
+ function toNumberId(value) {
127
+ if (value === undefined || value === null || value === '') return undefined;
128
+ const parsed = Number(value);
129
+ return Number.isFinite(parsed) ? parsed : String(value);
130
+ }
131
+
132
+ /** Maps several legacy product shapes into the Planner's small, stable vocabulary. */
133
+ function resolveProductKind(product) {
134
+ if (product.duration) return 'duration';
135
+ if (['session_product', 'session_ticket'].includes(product.extension_type)) return 'session';
136
+ if (product.cartDetailValue?.session || product._extend?.other?.session) return 'session';
137
+ if (Array.isArray(product['schedule.ids']) && product['schedule.ids'].length > 0) return 'session';
138
+ return 'normal';
139
+ }
140
+ function normalizeSchedule(product) {
141
+ const session = product.cartDetailValue?.session || product._extend?.other?.session || product.session;
142
+ if (session?.start_at && session?.end_at) {
143
+ return [{
144
+ start_at: session.start_at,
145
+ end_at: session.end_at
146
+ }];
147
+ }
148
+ const schedules = product.schedules || product.schedule || product._schedule;
149
+ if (Array.isArray(schedules)) {
150
+ return schedules.map(item => ({
151
+ start_at: item.start_at || item.start || item.start_time,
152
+ end_at: item.end_at || item.end || item.end_time
153
+ })).filter(item => item.start_at && item.end_at);
154
+ }
155
+ return [];
156
+ }
157
+
158
+ /**
159
+ * Preserves form ownership while flattening default/optional resource ids.
160
+ * `formId` must survive because the order API requires it under booking.resources[].
161
+ */
162
+ function normalizeRequirements(product) {
163
+ const resources = product.product_resource?.resources;
164
+ if (!Array.isArray(resources)) return [];
165
+ return resources.filter(resource => resource?.status !== 0).map(resource => ({
166
+ formId: toNumberId(resource.id),
167
+ resourceIds: [...(Array.isArray(resource.default_resource) ? resource.default_resource : []), ...(Array.isArray(resource.optional_resource) ? resource.optional_resource : [])].map(id => toNumberId(id)).filter(id => id !== undefined),
168
+ resourceType: resource.type || resource.select_type?.type || 'single',
169
+ required: resource.status === 1,
170
+ capacityRequired: Number(product.capacity?.default || product.capacity || 1) || 1
171
+ }));
172
+ }
173
+
174
+ /** Converts a ProductList record into the pure input shape consumed by ResourcePlanner. */
175
+ function normalizeProductForPlanner(product) {
176
+ const raw = product;
177
+ const kind = resolveProductKind(raw);
178
+ return {
179
+ id: raw.id ?? raw.product_id,
180
+ title: pickLocalizedText(raw.title || raw.name || raw.product_title),
181
+ kind,
182
+ durationMinutes: Number(raw.duration?.value || raw.duration || raw.service_duration || 30) || 30,
183
+ schedule: normalizeSchedule(raw),
184
+ resourceRequirements: normalizeRequirements(raw),
185
+ capacityRequired: Number(raw.capacity?.default || raw.capacity || 1) || 1,
186
+ quantity: Number(raw.num || raw.quantity || 1) || 1,
187
+ price: raw.price ?? raw.selling_price ?? raw.base_price,
188
+ raw
189
+ };
190
+ }
191
+ function normalizeResourceType(value) {
192
+ if (value === 'multiple' || value === 'capacity') return value;
193
+ return 'single';
194
+ }
195
+ function normalizeResource(raw) {
196
+ const id = raw.resourceId ?? raw.resource_id ?? raw.id;
197
+ if (id === undefined || id === null || id === '') return null;
198
+ const combinedResourceIds = raw.combined_resource?.resource_ids;
199
+ return {
200
+ id,
201
+ formId: raw.formId ?? raw.form_id ?? raw.resource_form_id,
202
+ name: raw.resourceName || raw.main_field || raw.name || raw.title,
203
+ resourceType: normalizeResourceType(raw.type || raw.resourceType || raw.select_type?.type),
204
+ capacity: Number(raw.capacity || raw.max_capacity || 1) || 1,
205
+ times: Array.isArray(raw.times) ? raw.times : [],
206
+ childResourceIds: Array.isArray(combinedResourceIds) ? combinedResourceIds : undefined,
207
+ raw
208
+ };
209
+ }
210
+ function normalizeScheduleIds(raw) {
211
+ const ids = raw.schedule ?? raw.schedule_ids ?? raw.scheduleIds ?? [];
212
+ return (Array.isArray(ids) ? ids : [ids]).map(id => toNumberId(id)).filter(id => id !== undefined);
213
+ }
214
+ function collectRawScheduleIds(rawResources) {
215
+ const ids = new Map();
216
+ (rawResources || []).forEach(resource => {
217
+ normalizeScheduleIds(resource).forEach(id => {
218
+ ids.set(String(id), id);
219
+ });
220
+ });
221
+ return Array.from(ids.values());
222
+ }
223
+ function scheduleListHasIds(scheduleList, scheduleIds) {
224
+ if (!scheduleIds.length) return true;
225
+ const existingIds = new Set((scheduleList || []).map(schedule => String(schedule.id)));
226
+ return scheduleIds.every(id => existingIds.has(String(id)));
227
+ }
228
+ function dateRangeDays(dateRange) {
229
+ if (!dateRange?.start || !dateRange?.end) return [];
230
+ const dates = [];
231
+ let cursor = (0, _dayjs.default)(dateRange.start);
232
+ const end = (0, _dayjs.default)(dateRange.end);
233
+ if (!cursor.isValid() || !end.isValid() || end.isBefore(cursor, 'day')) return dates;
234
+ while (cursor.isSame(end, 'day') || cursor.isBefore(end, 'day')) {
235
+ dates.push(cursor.format('YYYY-MM-DD'));
236
+ cursor = cursor.add(1, 'day');
237
+ }
238
+ return dates;
239
+ }
240
+ function normalizePlannerEvent(rawEvent, resourceId) {
241
+ const startAt = rawEvent.start_at ?? rawEvent.startAt ?? rawEvent.start_time ?? rawEvent.startTime;
242
+ const endAt = rawEvent.end_at ?? rawEvent.endAt ?? rawEvent.end_time ?? rawEvent.endTime;
243
+ if (!startAt || !endAt) return null;
244
+ const rawSource = rawEvent.source;
245
+ const source = rawSource === 'remote' || rawSource === 'cart' || rawSource === 'selection' ? rawSource : 'remote';
246
+ return {
247
+ ...rawEvent,
248
+ resourceId,
249
+ resource_id: rawEvent.resource_id ?? rawEvent.resourceId ?? resourceId,
250
+ start_at: startAt,
251
+ end_at: endAt,
252
+ pax: Number(rawEvent.pax ?? rawEvent.number ?? rawEvent.capacity ?? 1) || 1,
253
+ source
254
+ };
255
+ }
256
+ function normalizeResourceV2(raw) {
257
+ const normalized = normalizeResource({
258
+ ...raw,
259
+ times: []
260
+ });
261
+ if (!normalized) return null;
262
+ return normalized;
263
+ }
264
+ function buildResourceWindowFallbackTimes(params) {
265
+ const {
266
+ raw,
267
+ dates,
268
+ scheduleIds
269
+ } = params;
270
+ const rawStart = raw.start_time || raw.start_at || raw.startTime;
271
+ const rawEnd = raw.end_time || raw.end_at || raw.endTime;
272
+ if (!rawStart || !rawEnd) return [];
273
+ const startBoundary = (0, _dayjs.default)(rawStart);
274
+ const endBoundary = (0, _dayjs.default)(rawEnd);
275
+ if (!startBoundary.isValid() || !endBoundary.isValid() || !endBoundary.isAfter(startBoundary)) {
276
+ return [];
277
+ }
278
+ return dates.flatMap(date => {
279
+ const dayStart = (0, _dayjs.default)(`${date} 00:00:00`);
280
+ const dayEnd = (0, _dayjs.default)(`${date} 23:59:59`);
281
+ const start = startBoundary.isAfter(dayStart) ? startBoundary : dayStart;
282
+ const end = endBoundary.isBefore(dayEnd) ? endBoundary : dayEnd;
283
+ if (!end.isAfter(start)) return [];
284
+ return [{
285
+ start_at: start.format('YYYY-MM-DD HH:mm:ss'),
286
+ end_at: end.format('YYYY-MM-DD HH:mm:ss'),
287
+ schedule_ids: scheduleIds,
288
+ source: 'resource_window_fallback'
289
+ }];
290
+ });
291
+ }
292
+
293
+ /**
294
+ * Materializes resource work windows locally from v2's schedule ids, then keeps its flat
295
+ * event_list as planner events. This deliberately avoids the older API's times -> event_list
296
+ * response nesting and lets one resource response serve any requested date range.
297
+ */
298
+ function buildPlannerResourcesFromV2(params) {
299
+ const scheduleMap = new Map((params.scheduleList || []).map(schedule => [String(schedule.id), schedule]));
300
+ const dates = dateRangeDays(params.dateRange);
301
+ const externalEvents = [];
302
+ const resources = (params.rawResources || []).map(raw => {
303
+ const resource = normalizeResourceV2(raw);
304
+ if (!resource) return null;
305
+ const scheduleIds = normalizeScheduleIds(raw);
306
+ const schedules = scheduleIds.map(id => scheduleMap.get(String(id))).filter(Boolean);
307
+ const matchedScheduleIds = new Set(schedules.map(schedule => String(schedule.id)));
308
+ const missingScheduleIds = scheduleIds.filter(id => !matchedScheduleIds.has(String(id)));
309
+ if (missingScheduleIds.length > 0) {
310
+ resource.raw = {
311
+ ...(resource.raw || raw),
312
+ _plannerMissingScheduleIds: missingScheduleIds
313
+ };
314
+ }
315
+ resource.times = dates.flatMap(date => (0, _getDateIsInSchedule.getScheduleStartEndTimePoints)(date, schedules).map(slot => ({
316
+ start_at: (0, _dayjs.default)(slot.start_at).format('YYYY-MM-DD HH:mm:ss'),
317
+ end_at: (0, _dayjs.default)(slot.end_at).format('YYYY-MM-DD HH:mm:ss'),
318
+ schedule_ids: scheduleIds
319
+ })));
320
+ if (resource.times.length === 0 && missingScheduleIds.length > 0) {
321
+ resource.times = buildResourceWindowFallbackTimes({
322
+ raw,
323
+ dates,
324
+ scheduleIds
325
+ });
326
+ }
327
+ const eventList = Array.isArray(raw.event_list) ? raw.event_list : [];
328
+ eventList.forEach(event => {
329
+ const normalizedEvent = normalizePlannerEvent(event, resource.id);
330
+ if (normalizedEvent) externalEvents.push(normalizedEvent);
331
+ });
332
+ return resource;
333
+ }).filter(resource => resource !== null);
334
+ return {
335
+ resources,
336
+ externalEvents
337
+ };
338
+ }
339
+
340
+ /** Combines URL-locked resources with every resource referenced by the selected products. */
341
+ function collectPlannerResourceIds(products, explicitResourceIds = []) {
342
+ const ids = new Map();
343
+ const add = value => {
344
+ if (value === undefined || value === null || value === '') return;
345
+ ids.set(String(value), value);
346
+ };
347
+ explicitResourceIds.forEach(add);
348
+ products.forEach(product => {
349
+ product.resourceRequirements?.forEach(requirement => {
350
+ requirement.resourceIds?.forEach(add);
351
+ });
352
+ });
353
+ return Array.from(ids.values());
354
+ }
355
+ function samePlannerId(left, right) {
356
+ if (left === undefined || right === undefined) return false;
357
+ return String(left) === String(right);
358
+ }
359
+ function findRequirementForAssignment(product, assignment) {
360
+ const requirements = product.resourceRequirements || [];
361
+ return requirements.find(requirement => (requirement.resourceIds || []).some(id => samePlannerId(id, assignment.resourceId))) || (requirements.length === 1 ? requirements[0] : undefined) || requirements.find(requirement => requirement.required) || requirements[0];
362
+ }
363
+
364
+ /** Convenience wrapper for the usual one-resource booking case. */
365
+ function buildBookingFromAssignment(params) {
366
+ return buildBookingFromAssignments({
367
+ assignments: [params.assignment],
368
+ product: params.product
369
+ });
370
+ }
371
+
372
+ /**
373
+ * Converts all resources needed by one product/time interval into the one booking expected by
374
+ * OrderModule. Callers must group assignments before this function so a multi-form booking does
375
+ * not become several competing bookings.
376
+ */
377
+ function buildBookingFromAssignments(params) {
378
+ const {
379
+ assignments,
380
+ product
381
+ } = params;
382
+ const firstAssignment = assignments[0];
383
+ const start = (0, _dayjs.default)(firstAssignment.start_at);
384
+ const end = (0, _dayjs.default)(firstAssignment.end_at);
385
+ return {
386
+ start_date: start.format('YYYY-MM-DD'),
387
+ start_time: start.format('HH:mm'),
388
+ end_date: end.format('YYYY-MM-DD'),
389
+ end_time: end.format('HH:mm'),
390
+ duration: Math.max(1, end.diff(start, 'minute')),
391
+ like_status: 'common',
392
+ schedule_id: 0,
393
+ resources: assignments.map(assignment => {
394
+ const requirement = findRequirementForAssignment(product, assignment);
395
+ return {
396
+ id: assignment.resourceId,
397
+ resource_id: assignment.resourceId,
398
+ form_id: requirement?.formId,
399
+ relation_type: 'form',
400
+ relation_id: assignment.resourceId,
401
+ like_status: 'common',
402
+ capacity: assignment.capacityRequired || product.capacityRequired || 1
403
+ };
404
+ }),
405
+ metadata: {
406
+ unified_booking_sales: true,
407
+ planner_source: product.kind
408
+ }
409
+ };
410
+ }
411
+ function buildAssignmentGroupKey(assignment) {
412
+ return [assignment.productId, assignment.start_at, assignment.end_at].join(':');
413
+ }
414
+
415
+ /** Builds the exact identity BaseSales needs to remove only this solution's order lines. */
416
+ function buildPlannerLineIdentity(product) {
417
+ return {
418
+ product_id: product.product_id,
419
+ product_variant_id: product.product_variant_id ?? 0,
420
+ unique_identification_number: product.metadata?.unique_identification_number || product.unique_identification_number,
421
+ product_sku: product.product_sku,
422
+ product_bundle: product.product_bundle
423
+ };
424
+ }
425
+ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
426
+ defaultName = 'unifiedBookingSales';
427
+ defaultVersion = '1.0.0';
428
+ store = {};
429
+ unifiedProductCatalog = [];
430
+ openDataTarget = null;
431
+ loadOpenDataInFlight = null;
432
+ loadOpenDataInFlightTarget = null;
433
+
434
+ /**
435
+ * Kiosk 不能把已收款订单留在本地等待重试:默认直接等待云端 checkout。
436
+ * 兼容仍需要 WebPOS 待同步模式的入口可显式传 checkoutSyncTaskEnabled: true。
437
+ */
438
+ shouldUseCheckoutSyncTask() {
439
+ const configured = this.otherParams?.checkoutSyncTaskEnabled;
440
+ return typeof configured === 'boolean' ? configured : false;
441
+ }
442
+
443
+ /** UnifiedBookingSales 的真实结账默认请求收据数据,供云端确认后再本地打印。 */
444
+ getDefaultCheckoutSmallTicketDataFlag() {
445
+ return 1;
446
+ }
447
+ getRegisteredModuleNames() {
448
+ return [...super.getRegisteredModuleNames(), 'resourcePlanner', 'openData'];
449
+ }
450
+ createSubModule(moduleName) {
451
+ if (moduleName === 'resourcePlanner') {
452
+ return new _modules.ResourcePlannerModule(`${this.name}_resourcePlanner`);
453
+ }
454
+ if (moduleName === 'openData') {
455
+ return new _modules.OpenDataModule(`${this.name}_openData`);
456
+ }
457
+ return super.createSubModule(moduleName);
458
+ }
459
+
460
+ /**
461
+ * Loads OpenData without borrowing BookingTicket. Cache ownership is tied to the exact
462
+ * business/channel target so a reused solution instance cannot leak another entry's menus.
463
+ */
464
+ async loadOpenData(params) {
465
+ if (!this.store.openData) {
466
+ throw new Error('[UnifiedBookingSales] openData 模块未初始化');
467
+ }
468
+ const businessCode = String(params.businessCode || '').trim();
469
+ const channel = String(params.channel || '').trim();
470
+ if (!businessCode || !channel) {
471
+ throw new Error('[UnifiedBookingSales] OpenData 需要 businessCode 与 channel');
472
+ }
473
+ const target = `${businessCode}+${channel}`;
474
+ const cachedData = this.store.openData.getOpenData();
475
+ const lastFetchedAt = this.store.openData.getLastFetchedAt();
476
+ if (!params.force && this.openDataTarget === target && cachedData && lastFetchedAt && Date.now() - lastFetchedAt < OPEN_DATA_CACHE_TTL) {
477
+ return cachedData;
478
+ }
479
+ if (this.loadOpenDataInFlight) {
480
+ if (this.loadOpenDataInFlightTarget === target) {
481
+ return await this.loadOpenDataInFlight;
482
+ }
483
+ await this.loadOpenDataInFlight;
484
+ return this.loadOpenData(params);
485
+ }
486
+ this.loadOpenDataInFlightTarget = target;
487
+ this.loadOpenDataInFlight = this.store.openData.fetchOpenData({
488
+ scope: 'board',
489
+ target,
490
+ section_code: [...OPEN_DATA_SECTION_CODES]
491
+ });
492
+ try {
493
+ const openData = await this.loadOpenDataInFlight;
494
+ this.openDataTarget = target;
495
+ this.otherParams.openData = openData;
496
+ this.otherParams.businessCode = businessCode;
497
+ this.otherParams.channel = channel;
498
+ return openData;
499
+ } finally {
500
+ this.loadOpenDataInFlight = null;
501
+ this.loadOpenDataInFlightTarget = null;
502
+ }
503
+ }
504
+ async getOpenData() {
505
+ return this.store.openData?.getOpenData() || null;
506
+ }
507
+
508
+ /**
509
+ * Loads the product catalog used by both UI and Planner. Schedule data is requested with each
510
+ * product because session products carry their fixed intervals there.
511
+ */
512
+ async loadProducts(params = {}, options) {
513
+ if (!this.store.products) throw new Error('[UnifiedBookingSales] products 模块未初始化');
514
+ const schedule_date = params.schedule_date || (0, _dayjs.default)().format('YYYY-MM-DD');
515
+ const schedule_datetime = params.schedule_datetime || `${schedule_date} ${(0, _dayjs.default)().format('HH:mm:ss')}`;
516
+ const result = await this.store.products.loadProducts({
517
+ with_count: ['bundleGroup', 'optionGroup'],
518
+ with_schedule: 1,
519
+ ...params,
520
+ schedule_date,
521
+ schedule_datetime,
522
+ cacheId: this.cacheId
523
+ }, options);
524
+ this.unifiedProductCatalog = Array.isArray(result) ? [...result] : [];
525
+ await this.core.effects.emit(`${this.name}:onProductsLoaded`, result);
526
+ return result;
527
+ }
528
+
529
+ /** Date-first entry point. It delegates protocol details and cache ownership to ScheduleModule. */
530
+ async loadScheduleAvailableDate(params) {
531
+ if (!this.store.schedule) throw new Error('[UnifiedBookingSales] schedule 模块未初始化');
532
+ return this.store.schedule.loadScheduleAvailableDate(params);
533
+ }
534
+
535
+ /**
536
+ * Implements the date-first product pool: the chosen date's product ids plus globally sellable
537
+ * other_product_ids. If a batch product query is unexpectedly empty, retry one id at a time so
538
+ * a partial backend incompatibility does not hide the entire date's catalog.
539
+ */
540
+ async loadProductsByScheduleDate(params) {
541
+ const {
542
+ date,
543
+ custom_page_id,
544
+ channel,
545
+ product_ids,
546
+ ...productLoadParams
547
+ } = params;
548
+ if (!this.store.schedule) throw new Error('[UnifiedBookingSales] schedule 模块未初始化');
549
+ const cachedDates = this.store.schedule.getAvailabilityScheduleDateList?.() || [];
550
+ const hasCachedDate = cachedDates.some(item => item.date === date);
551
+ const hasOtherProducts = (this.store.schedule.getOtherProductsIds?.() || []).length > 0;
552
+ if (!hasCachedDate && !hasOtherProducts) {
553
+ await this.loadScheduleAvailableDate({
554
+ startDate: date,
555
+ endDate: date,
556
+ custom_page_id,
557
+ channel
558
+ });
559
+ }
560
+ const scheduleDate = this.store.schedule.getAvailabilityScheduleDateList?.()?.find(item => item.date === date);
561
+ const productIdFilter = product_ids?.length ? new Set(product_ids.map(id => String(id))) : null;
562
+ const availableProductIds = [...(scheduleDate?.product_ids || []), ...(this.store.schedule.getOtherProductsIds?.() || [])].filter((id, index, self) => self.indexOf(id) === index).filter(id => !productIdFilter || productIdFilter.has(String(id)));
563
+ if (!availableProductIds.length) {
564
+ this.unifiedProductCatalog = [];
565
+ await this.core.effects.emit(`${this.name}:onProductsLoaded`, []);
566
+ return [];
567
+ }
568
+ const products = await this.loadProducts({
569
+ ...productLoadParams,
570
+ product_ids: availableProductIds,
571
+ schedule_date: date
572
+ });
573
+ if (products.length || availableProductIds.length <= 1) return products;
574
+ const fallbackProducts = [];
575
+ for (const productId of availableProductIds) {
576
+ const result = await this.loadProducts({
577
+ ...productLoadParams,
578
+ product_ids: [productId],
579
+ schedule_date: date
580
+ });
581
+ result.forEach(product => {
582
+ const id = product?.id ?? product?.product_id;
583
+ if (!fallbackProducts.some(item => String(item?.id ?? item?.product_id) === String(id))) {
584
+ fallbackProducts.push(product);
585
+ }
586
+ });
587
+ }
588
+ this.unifiedProductCatalog = [...fallbackProducts];
589
+ await this.core.effects.emit(`${this.name}:onProductsLoaded`, fallbackProducts);
590
+ return fallbackProducts;
591
+ }
592
+
593
+ /** Returns a copy so UI consumers cannot accidentally mutate the solution's product cache. */
594
+ getProductCatalog() {
595
+ return {
596
+ products: [...this.unifiedProductCatalog]
597
+ };
598
+ }
599
+
600
+ /**
601
+ * Read-only compatibility view for salesSdk skins. It reconnects a booking to its product but
602
+ * must not be used to mutate tempOrder; all writes go through BaseSales / planner APIs.
603
+ */
604
+ getCart() {
605
+ const tempOrder = this.getTempOrder();
606
+ const salesDetail = this.getSalesOrder();
607
+ const items = tempOrder?.products || [];
608
+ const bookings = salesDetail?.bookings || tempOrder?.bookings || [];
609
+ return {
610
+ items,
611
+ bookings: bookings.map(booking => {
612
+ const productUid = booking?.product_uid;
613
+ const product = productUid ? items.find(item => {
614
+ const uid = item?.metadata?.unique_identification_number || item?.unique_identification_number;
615
+ return String(uid || '') === String(productUid);
616
+ }) || null : null;
617
+ return {
618
+ ...booking,
619
+ _extend: {
620
+ ...(booking?._extend || {}),
621
+ product,
622
+ addTimeProduct: [],
623
+ canAddTime: false
624
+ }
625
+ };
626
+ })
627
+ };
628
+ }
629
+
630
+ /**
631
+ * Loads the current customer's product coupons and discount cards after planner lines exist,
632
+ * then optionally lets the existing Rules engine select the best valid combination. This is a
633
+ * diagnostic boundary for new booking skins: no pricing logic is duplicated in the planner.
634
+ */
635
+ async applyPlannerDiscounts(params = {}) {
636
+ const tempOrder = this.getTempOrder();
637
+ const requestedCustomerId = params.customerId ?? tempOrder?.customer_id;
638
+ const parsedCustomerId = Number(requestedCustomerId);
639
+ const customerId = Number.isFinite(parsedCustomerId) && parsedCustomerId > 1 ? parsedCustomerId : null;
640
+ const summaryBefore = await this.getSummary();
641
+ if (!customerId) {
642
+ return buildPlannerDiscountResult({
643
+ customerId: null,
644
+ discountList: this.getDiscountList(),
645
+ products: tempOrder?.products || [],
646
+ summaryBefore,
647
+ summaryAfter: summaryBefore,
648
+ status: 'no_customer'
649
+ });
650
+ }
651
+ await this.loadDiscountConfig({
652
+ customerId,
653
+ action: 'create'
654
+ });
655
+ const preferredDiscountId = params.preferredDiscountId;
656
+ const preferredDiscount = preferredDiscountId === undefined || preferredDiscountId === null ? undefined : this.getDiscountList().find(discount => String(resolvePlannerDiscountId(discount) ?? '') === String(preferredDiscountId));
657
+ if (preferredDiscount) {
658
+ // A requested card is an explicit UI choice, not a best-effort preference. Clear prior
659
+ // automatic selections first; otherwise Rules may keep the old selected card and silently
660
+ // apply it instead of the card the customer clicked.
661
+ const preferredId = resolvePlannerDiscountId(preferredDiscount);
662
+ const selectedOtherDiscounts = this.getDiscountList().filter(discount => discount.isSelected === true && String(resolvePlannerDiscountId(discount) ?? '') !== String(preferredId));
663
+ for (const discount of selectedOtherDiscounts) {
664
+ const discountId = Number(resolvePlannerDiscountId(discount));
665
+ if (Number.isFinite(discountId)) {
666
+ await this.setDiscountSelected({
667
+ discountId,
668
+ isSelected: false
669
+ });
670
+ }
671
+ }
672
+ await this.setDiscountSelected({
673
+ discountId: Number(preferredId),
674
+ isSelected: true
675
+ });
676
+ } else if (preferredDiscountId === undefined || preferredDiscountId === null) {
677
+ if (params.applyBestDiscount !== false) await this.bestDiscount();
678
+ } else if (params.applyBestDiscount !== false) {
679
+ await this.bestDiscount();
680
+ }
681
+ const nextTempOrder = this.getTempOrder();
682
+ return buildPlannerDiscountResult({
683
+ customerId,
684
+ discountList: this.getDiscountList(),
685
+ products: nextTempOrder?.products || [],
686
+ summaryBefore,
687
+ summaryAfter: await this.getSummary(),
688
+ status: params.applyBestDiscount === false && !preferredDiscount ? 'loaded' : 'applied',
689
+ preferredDiscountId,
690
+ preferredDiscountFound: preferredDiscountId === undefined || preferredDiscountId === null ? undefined : Boolean(preferredDiscount)
691
+ });
692
+ }
693
+
694
+ /** ResourcePlanner is a required child module; fail early instead of producing partial availability. */
695
+ getPlanner() {
696
+ if (!this.store.resourcePlanner) {
697
+ throw new Error('[UnifiedBookingSales] resourcePlanner 模块未初始化');
698
+ }
699
+ return this.store.resourcePlanner;
700
+ }
701
+ buildUnifiedOrderProduct(sourceProduct, ownershipKey, product) {
702
+ const orderProduct = this.transformBaseProductToOrderProduct({
703
+ payload: {
704
+ ...sourceProduct,
705
+ id: sourceProduct.id ?? product?.id,
706
+ product_id: sourceProduct.product_id ?? sourceProduct.id ?? product?.id,
707
+ quantity: sourceProduct.quantity ?? sourceProduct.num ?? product?.quantity ?? 1,
708
+ price: sourceProduct.price ?? product?.price,
709
+ selling_price: sourceProduct.selling_price ?? sourceProduct.price ?? product?.price,
710
+ metadata: {
711
+ ...(sourceProduct.metadata || {}),
712
+ [ownershipKey]: true
713
+ }
714
+ },
715
+ sourceProduct
716
+ });
717
+ if (orderProduct && typeof orderProduct === 'object') {
718
+ // BaseSales may rebuild metadata from its price source. Stamp ownership after that transform
719
+ // so each UnifiedBookingSales entry point can replace only its own temporary lines.
720
+ orderProduct.metadata = {
721
+ ...(orderProduct.metadata || {}),
722
+ [ownershipKey]: true
723
+ };
724
+ }
725
+ return orderProduct;
726
+ }
727
+
728
+ /** Replacing a staged selection is idempotent and never removes unrelated cart lines. */
729
+ async removeExistingStagedLines(ownershipKey) {
730
+ const existingLines = (this.getTempOrder()?.products || []).filter(product => product?.metadata?.[ownershipKey] === true);
731
+ if (existingLines.length > 0) {
732
+ await this.removeProductsFromOrder(existingLines.map(buildPlannerLineIdentity));
733
+ }
734
+ }
735
+ async stageProducts(params, ownershipKey) {
736
+ const productIds = params.productIds || [];
737
+ if (!productIds.length) return this.getTempOrder();
738
+ if (params.rawProducts?.length) {
739
+ this.unifiedProductCatalog = params.rawProducts;
740
+ } else {
741
+ const existingIds = new Set((this.unifiedProductCatalog || []).map(product => String(product.id ?? product.product_id)));
742
+ const missingIds = productIds.filter(id => !existingIds.has(String(id)));
743
+ if (missingIds.length || params.productLoadParams) {
744
+ await this.loadProducts({
745
+ ...(params.productLoadParams || {}),
746
+ product_ids: productIds.map(Number).filter(Number.isFinite)
747
+ });
748
+ }
749
+ }
750
+ await this.removeExistingStagedLines(ownershipKey);
751
+ const productIdSet = new Set(productIds.map(id => String(id)));
752
+ const selectedProducts = (this.unifiedProductCatalog || []).filter(product => productIdSet.has(String(product.id ?? product.product_id)));
753
+ for (const sourceProduct of selectedProducts) {
754
+ const productInput = this.buildUnifiedOrderProduct(sourceProduct, ownershipKey);
755
+ if (productInput) await this.addProductToOrder(productInput);
756
+ }
757
+ return this.getTempOrder();
758
+ }
759
+
760
+ /**
761
+ * Adds the current product choice to an otherwise clean planner cart without creating bookings.
762
+ * This separates "what the customer wants" from the later time/resource confirmation step.
763
+ */
764
+ async stagePlannerProducts(params) {
765
+ return this.stageProducts(params, 'unified_booking_sales');
766
+ }
767
+
768
+ /**
769
+ * Adds ordinary retail products without asking ResourcePlanner for booking facts.
770
+ * Its staged lines have separate ownership so planner and retail skins can coexist safely.
771
+ */
772
+ async stageRetailProducts(params) {
773
+ return this.stageProducts(params, 'unified_booking_sales_retail');
774
+ }
775
+
776
+ /**
777
+ * Adds one retail line without replacing the cart's existing retail selection.
778
+ * This is intentionally separate from stageRetailProducts(), whose contract is
779
+ * "replace the staged selection" for demo and wizard-like callers.
780
+ */
781
+ async addRetailProduct(params) {
782
+ const quantity = Math.floor(Number(params.quantity ?? 1));
783
+ if (!Number.isFinite(quantity) || quantity <= 0) {
784
+ throw new Error('[UnifiedBookingSales] retail 商品数量必须大于 0');
785
+ }
786
+ const productId = params.productId ?? params.product?.id ?? params.product?.product_id;
787
+ let sourceProduct = params.product;
788
+ if (!sourceProduct && productId !== undefined && productId !== null) {
789
+ sourceProduct = this.unifiedProductCatalog.find(product => String(product.id ?? product.product_id) === String(productId));
790
+ }
791
+ if (!sourceProduct && productId !== undefined && productId !== null) {
792
+ const products = await this.loadProducts({
793
+ ...(params.productLoadParams || {}),
794
+ product_ids: [Number(productId)].filter(Number.isFinite)
795
+ });
796
+ sourceProduct = products.find(product => String(product.id ?? product.product_id) === String(productId));
797
+ }
798
+ if (!sourceProduct) {
799
+ throw new Error(`[UnifiedBookingSales] 未找到零售商品 ${String(productId ?? '')}`.trim());
800
+ }
801
+ const orderProduct = this.buildUnifiedOrderProduct({
802
+ ...sourceProduct,
803
+ quantity
804
+ }, 'unified_booking_sales_retail');
805
+ if (!orderProduct) {
806
+ throw new Error('[UnifiedBookingSales] 无法生成零售商品订单行');
807
+ }
808
+ return this.addProductToOrder(orderProduct);
809
+ }
810
+
811
+ /** Normalizes caller-provided products or loads the catalog before any resource request is made. */
812
+ async loadPlannerProducts(params) {
813
+ if (params.context?.products?.length) return params.context.products;
814
+ if (params.rawProducts?.length) return params.rawProducts.map(normalizeProductForPlanner);
815
+ const productIds = params.productIds || params.productLoadParams?.product_ids || [];
816
+ if (productIds.length > 0 || params.productLoadParams) {
817
+ await this.loadProducts({
818
+ ...(params.date ? {
819
+ schedule_date: params.date
820
+ } : {}),
821
+ ...(params.productLoadParams || {}),
822
+ product_ids: productIds.length ? productIds.map(Number).filter(Number.isFinite) : params.productLoadParams?.product_ids
823
+ });
824
+ }
825
+ return (this.getProductCatalog?.().products || []).map(normalizeProductForPlanner);
826
+ }
827
+
828
+ /** Loads the reusable store-level schedule catalog on demand. */
829
+ async ensurePlannerSchedulesLoaded() {
830
+ if (!this.store.schedule) throw new Error('[UnifiedBookingSales] schedule 模块未初始化');
831
+ const scheduleList = this.store.schedule.getScheduleList?.() || [];
832
+ if (!this.store.schedule.isScheduleListLoaded?.() || scheduleList.length === 0) {
833
+ await this.store.schedule.loadAllSchedule();
834
+ }
835
+ return this.store.schedule.getScheduleList?.() || [];
836
+ }
837
+
838
+ /**
839
+ * v2 resources reference schedule ids rather than expanded work times. Refresh once when the
840
+ * cached schedule catalog cannot materialize all referenced ids.
841
+ */
842
+ async ensurePlannerSchedulesForResources(rawResources) {
843
+ let scheduleList = await this.ensurePlannerSchedulesLoaded();
844
+ const scheduleIds = collectRawScheduleIds(rawResources);
845
+ if (!scheduleListHasIds(scheduleList, scheduleIds)) {
846
+ await this.store.schedule.loadAllSchedule({
847
+ useCache: false
848
+ });
849
+ scheduleList = this.store.schedule.getScheduleList?.() || [];
850
+ }
851
+ return scheduleList;
852
+ }
853
+
854
+ /**
855
+ * Fetches resource metadata plus flat occupied events. Work windows are intentionally derived
856
+ * locally in buildPlannerResourcesFromV2 from /schedule, rather than requested from the legacy
857
+ * resource dates endpoint.
858
+ */
859
+ async fetchPlannerResourcesV2(params) {
860
+ const response = await this.request.get('/schedule/resource/list/v2', {
861
+ start_date: params.dateRange.start,
862
+ end_date: params.dateRange.end,
863
+ resource_ids: params.resourceIds,
864
+ front_end_cache_id: false
865
+ }, {
866
+ useCache: false
867
+ });
868
+ const data = response?.data;
869
+ if (Array.isArray(data)) return data;
870
+ if (Array.isArray(data?.list)) return data.list;
871
+ return [];
872
+ }
873
+
874
+ /**
875
+ * Resolves the Planner context in precedence order: explicit normalized context, test raw data,
876
+ * then the v2 resource API inferred from selected product requirements and any URL lock.
877
+ */
878
+ async loadPlannerResources(params, products = []) {
879
+ if (params.context?.resources?.length) {
880
+ return {
881
+ resources: params.context.resources,
882
+ externalEvents: params.context.externalEvents || []
883
+ };
884
+ }
885
+ if (params.rawResources?.length) {
886
+ return {
887
+ resources: params.rawResources.map(normalizeResource).filter(resource => resource !== null),
888
+ externalEvents: params.context?.externalEvents || []
889
+ };
890
+ }
891
+ const resourceIds = collectPlannerResourceIds(products, params.resourceIds || []);
892
+ if (!params.useResourceDateApi || !params.dateRange || resourceIds.length === 0) {
893
+ return {
894
+ resources: [],
895
+ externalEvents: params.context?.externalEvents || []
896
+ };
897
+ }
898
+ const rawResources = await this.fetchPlannerResourcesV2({
899
+ dateRange: params.dateRange,
900
+ resourceIds
901
+ });
902
+ const scheduleList = await this.ensurePlannerSchedulesForResources(rawResources);
903
+ const materialized = buildPlannerResourcesFromV2({
904
+ rawResources,
905
+ scheduleList,
906
+ dateRange: params.dateRange
907
+ });
908
+ return {
909
+ resources: materialized.resources,
910
+ externalEvents: [...(params.context?.externalEvents || []), ...materialized.externalEvents]
911
+ };
912
+ }
913
+
914
+ /**
915
+ * Boundary between IO and pure planning. Once this returns, all later availability/slot calls
916
+ * operate on the ResourcePlanner snapshot and do not issue resource requests themselves.
917
+ */
918
+ async loadPlannerContext(params = {}) {
919
+ const products = await this.loadPlannerProducts(params);
920
+ const plannerResources = await this.loadPlannerResources(params, products);
921
+ const context = {
922
+ ...(params.context || {}),
923
+ products,
924
+ resources: plannerResources.resources,
925
+ externalEvents: plannerResources.externalEvents
926
+ };
927
+ const snapshot = this.getPlanner().setContext(context);
928
+ this.getPlanner().setSelectionPatch({
929
+ mode: params.mode,
930
+ productIds: params.productIds || [],
931
+ date: params.date,
932
+ startTime: params.startTime,
933
+ endTime: params.endTime,
934
+ resourceIds: params.resourceIds || []
935
+ });
936
+ await this.core.effects.emit(`${this.name}:${_types.UnifiedBookingSalesHooks.onPlannerContextLoaded}`, snapshot);
937
+ return this.getPlanner().getSnapshot();
938
+ }
939
+
940
+ /** Returns cells, date summaries and a derived grid; cells are continuous ranges, not UI slots. */
941
+ async queryPlannerAvailability(query = {}) {
942
+ return this.getPlanner().queryAvailability(query);
943
+ }
944
+
945
+ /** Turns compatible availability ranges into user-selectable intervals and ready-to-commit assignments. */
946
+ resolveAssignableSlots(query = {}) {
947
+ return this.getPlanner().resolveAssignableSlots(query);
948
+ }
949
+
950
+ /** Stores a UI choice only. It is deliberately side-effect free with respect to tempOrder. */
951
+ setPlannerSelection(patch) {
952
+ return this.getPlanner().setSelectionPatch(patch);
953
+ }
954
+
955
+ /**
956
+ * Legacy-friendly automatic assignment for already fixed intervals. Duration products without a
957
+ * start time intentionally remain unresolved; callers offering a picker should use slots.
958
+ */
959
+ async autoAssignPlanner(query = {}) {
960
+ const result = this.getPlanner().autoAssign(query);
961
+ if (result.conflicts.length) {
962
+ console.warn('[UnifiedBookingSales] autoAssignPlanner 存在未分配项', result.conflicts);
963
+ }
964
+ return this.getPlanner().getSnapshot();
965
+ }
966
+
967
+ /** Rechecks remote events, capacity and conflicts among the current selection before committing. */
968
+ validatePlannerSelection() {
969
+ return this.getPlanner().validateSelection();
970
+ }
971
+
972
+ /** Read-only snapshot for UI diagnostics and progressive flow steps. */
973
+ getPlannerSnapshot() {
974
+ return this.getPlanner().getSnapshot();
975
+ }
976
+
977
+ /**
978
+ * Validates then writes assignments to tempOrder. Real order submission is opt-in so UI callers
979
+ * can safely preview the cart; pass submitAfterCommit only after an explicit confirmation.
980
+ */
981
+ async commitPlannerSelection(params = {}) {
982
+ if (params.selection) {
983
+ this.setPlannerSelection(params.selection);
984
+ }
985
+ if (params.assignments) {
986
+ this.setPlannerSelection({
987
+ assignments: params.assignments
988
+ });
989
+ }
990
+ const snapshot = this.getPlannerSnapshot();
991
+ const assignments = snapshot.selection.assignments || [];
992
+ if (assignments.length === 0) {
993
+ return {
994
+ tempOrder: this.getTempOrder(),
995
+ assignments,
996
+ validation: {
997
+ ok: false,
998
+ conflicts: [{
999
+ type: 'missing_assignment',
1000
+ message: '没有可提交的 planner assignment,请先执行 autoAssignPlanner 或传入 assignments'
1001
+ }]
1002
+ }
1003
+ };
1004
+ }
1005
+ const validation = this.validatePlannerSelection();
1006
+ if (!validation.ok) {
1007
+ return {
1008
+ tempOrder: this.getTempOrder(),
1009
+ assignments,
1010
+ validation
1011
+ };
1012
+ }
1013
+ const productsById = new Map(snapshot.context.products.map(product => [String(product.id), product]));
1014
+ await this.removeExistingStagedLines('unified_booking_sales');
1015
+ const assignmentGroups = new Map();
1016
+ assignments.forEach(assignment => {
1017
+ const key = buildAssignmentGroupKey(assignment);
1018
+ assignmentGroups.set(key, [...(assignmentGroups.get(key) || []), assignment]);
1019
+ });
1020
+ for (const groupAssignments of assignmentGroups.values()) {
1021
+ const product = productsById.get(String(groupAssignments[0].productId));
1022
+ if (!product) continue;
1023
+ const sourceProduct = product.raw || {
1024
+ id: product.id,
1025
+ title: product.title,
1026
+ price: product.price
1027
+ };
1028
+ const productInput = this.buildUnifiedOrderProduct(sourceProduct, 'unified_booking_sales', product);
1029
+ if (!productInput) continue;
1030
+ await this.addProductToOrder(productInput, buildBookingFromAssignments({
1031
+ assignments: groupAssignments,
1032
+ product
1033
+ }));
1034
+ }
1035
+ let submitResult;
1036
+ if (params.submitAfterCommit) {
1037
+ submitResult = await this.submitSalesOrder();
1038
+ }
1039
+ const result = {
1040
+ tempOrder: this.getTempOrder(),
1041
+ assignments,
1042
+ validation,
1043
+ submitResult
1044
+ };
1045
+ await this.core.effects.emit(`${this.name}:${_types.UnifiedBookingSalesHooks.onPlannerCommitted}`, result);
1046
+ return result;
1047
+ }
1048
+ }
1049
+ exports.UnifiedBookingSalesImpl = UnifiedBookingSalesImpl;
1050
+ const UnifiedBookingSales = exports.UnifiedBookingSales = UnifiedBookingSalesImpl;