@pisell/pisellos 0.10.14 → 0.10.16

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 (301) hide show
  1. package/dist/core/index.js +6 -9
  2. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  3. package/dist/model/strategy/strategy-example.js +5 -19
  4. package/dist/modules/Cart/index.js +0 -3
  5. package/dist/modules/Cart/utils/cartProduct.js +0 -1
  6. package/dist/modules/Date/index.js +1 -5
  7. package/dist/modules/Discount/index.js +2 -4
  8. package/dist/modules/OpenData/index.js +0 -2
  9. package/dist/modules/Order/index.d.ts +1 -1
  10. package/dist/modules/Order/index.js +75 -91
  11. package/dist/modules/Order/types.d.ts +5 -1
  12. package/dist/modules/Order/utils/virtualSettlement.d.ts +8 -1
  13. package/dist/modules/Order/utils/virtualSettlement.js +15 -2
  14. package/dist/modules/Order/utils.js +7 -1
  15. package/dist/modules/Payment/index.js +97 -162
  16. package/dist/modules/Product/types.d.ts +2 -0
  17. package/dist/modules/Rules/index.js +1 -4
  18. package/dist/modules/Schedule/index.js +0 -1
  19. package/dist/modules/Schedule/utils.js +0 -1
  20. package/dist/modules/Step/index.js +0 -1
  21. package/dist/plugins/request.js +1 -4
  22. package/dist/plugins/window.js +2 -6
  23. package/dist/server/index.js +97 -129
  24. package/dist/server/modules/menu/index.js +32 -41
  25. package/dist/server/modules/order/index.js +2 -4
  26. package/dist/server/modules/products/index.js +24 -42
  27. package/dist/server/modules/quotation/index.js +29 -38
  28. package/dist/server/modules/resource/index.js +3 -4
  29. package/dist/server/modules/schedule/index.js +27 -35
  30. package/dist/server/utils/product.js +0 -1
  31. package/dist/solution/BaseSales/index.js +107 -76
  32. package/dist/solution/BaseSales/types.d.ts +2 -0
  33. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
  34. package/dist/solution/BaseSales/utils/cartPromotion.js +15 -6
  35. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
  36. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +7 -1
  37. package/dist/solution/BaseSales/utils.js +6 -3
  38. package/dist/solution/BookingByStep/index.d.ts +2 -2
  39. package/dist/solution/BookingByStep/index.js +7 -59
  40. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  41. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  42. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  43. package/dist/solution/BookingTicket/index.js +8 -4
  44. package/dist/solution/BookingTicket/utils/addProductDecision.js +3 -1
  45. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
  46. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  47. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  48. package/dist/solution/BuyTickets/index.js +9 -12
  49. package/dist/solution/Checkout/index.js +177 -252
  50. package/dist/solution/Checkout/utils/index.js +4 -16
  51. package/dist/solution/RegisterAndLogin/index.js +30 -76
  52. package/dist/solution/ScanOrder/index.js +50 -60
  53. package/dist/solution/ScanOrder/types.d.ts +2 -0
  54. package/dist/solution/ScanOrder/utils.js +6 -3
  55. package/dist/solution/ShopDiscount/index.js +2 -7
  56. package/dist/solution/VenueBooking/index.js +45 -55
  57. package/dist/utils/task.js +15 -18
  58. package/dist/utils/watch.js +0 -1
  59. package/lib/apis/picoding.js +2 -0
  60. package/lib/core/index.js +131 -131
  61. package/lib/effects/index.js +46 -57
  62. package/lib/index.js +82 -49
  63. package/lib/model/index.js +14 -21
  64. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  65. package/lib/model/strategy/adapter/dataVariant/evaluator.js +209 -315
  66. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  67. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  68. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  69. package/lib/model/strategy/adapter/index.js +100 -64
  70. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  71. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  72. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  73. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  74. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  75. package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
  76. package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
  77. package/lib/model/strategy/adapter/promotion/examples.js +222 -234
  78. package/lib/model/strategy/adapter/promotion/index.js +43 -48
  79. package/lib/model/strategy/adapter/promotion/type.js +243 -36
  80. package/lib/model/strategy/adapter/type.js +4 -16
  81. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
  82. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  83. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  84. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  85. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  86. package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
  87. package/lib/model/strategy/engine.js +270 -168
  88. package/lib/model/strategy/index.js +49 -34
  89. package/lib/model/strategy/strategy-example.js +243 -239
  90. package/lib/model/strategy/type.js +100 -40
  91. package/lib/modules/Account/index.js +39 -53
  92. package/lib/modules/Account/types.js +20 -33
  93. package/lib/modules/AccountList/index.js +116 -154
  94. package/lib/modules/AccountList/types.js +30 -31
  95. package/lib/modules/AccountList/utils.js +18 -30
  96. package/lib/modules/BaseModule.js +23 -42
  97. package/lib/modules/BookingContext/index.js +158 -136
  98. package/lib/modules/BookingContext/types.js +46 -32
  99. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
  100. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
  101. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
  102. package/lib/modules/BookingContext/utils/flexible.js +38 -55
  103. package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
  104. package/lib/modules/BookingContext/utils/index.js +124 -41
  105. package/lib/modules/BookingContext/utils/noResource.js +58 -70
  106. package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
  107. package/lib/modules/BookingContext/utils/productExtend.js +202 -155
  108. package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
  109. package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
  110. package/lib/modules/BookingContext/utils/resources.js +209 -167
  111. package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
  112. package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
  113. package/lib/modules/Cart/index.js +170 -124
  114. package/lib/modules/Cart/types.js +46 -51
  115. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  116. package/lib/modules/Cart/utils/cartDate.js +56 -61
  117. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  118. package/lib/modules/Cart/utils/cartNote.js +27 -32
  119. package/lib/modules/Cart/utils/cartProduct.js +321 -251
  120. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  121. package/lib/modules/Cart/utils/cartResource.js +70 -78
  122. package/lib/modules/Cart/utils/changePrice.js +22 -50
  123. package/lib/modules/Cart/utils/index.js +106 -48
  124. package/lib/modules/Customer/constants.js +13 -34
  125. package/lib/modules/Customer/index.js +235 -172
  126. package/lib/modules/Customer/types.js +38 -35
  127. package/lib/modules/Date/index.js +116 -115
  128. package/lib/modules/Date/types.js +16 -28
  129. package/lib/modules/Date/utils.js +174 -123
  130. package/lib/modules/Discount/index.js +133 -143
  131. package/lib/modules/Discount/types.js +9 -31
  132. package/lib/modules/Guests/index.js +30 -56
  133. package/lib/modules/Guests/types.js +23 -33
  134. package/lib/modules/Holder/index.js +209 -189
  135. package/lib/modules/Holder/types.js +4 -16
  136. package/lib/modules/Holder/utils.js +20 -49
  137. package/lib/modules/OpenData/index.js +70 -76
  138. package/lib/modules/OpenData/types.js +4 -16
  139. package/lib/modules/OpenData/utils.js +44 -78
  140. package/lib/modules/Order/index.d.ts +1 -1
  141. package/lib/modules/Order/index.js +1810 -2238
  142. package/lib/modules/Order/payment-utils.js +77 -120
  143. package/lib/modules/Order/types.d.ts +5 -1
  144. package/lib/modules/Order/types.js +87 -35
  145. package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
  146. package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
  147. package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
  148. package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
  149. package/lib/modules/Order/utils/virtualSettlement.d.ts +8 -1
  150. package/lib/modules/Order/utils/virtualSettlement.js +126 -164
  151. package/lib/modules/Order/utils.js +834 -668
  152. package/lib/modules/Payment/cash.js +20 -33
  153. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  154. package/lib/modules/Payment/eftpos.js +16 -30
  155. package/lib/modules/Payment/index.js +532 -399
  156. package/lib/modules/Payment/mx51.js +1 -0
  157. package/lib/modules/Payment/types.js +230 -108
  158. package/lib/modules/Payment/utils.js +52 -51
  159. package/lib/modules/Payment/walletpass.js +485 -660
  160. package/lib/modules/Product/index.js +51 -46
  161. package/lib/modules/Product/types.d.ts +2 -0
  162. package/lib/modules/Product/types.js +4 -16
  163. package/lib/modules/Product/utils.js +32 -33
  164. package/lib/modules/ProductList/index.js +138 -161
  165. package/lib/modules/ProductList/types.js +9 -31
  166. package/lib/modules/Quotation/index.js +66 -100
  167. package/lib/modules/Quotation/types.js +4 -16
  168. package/lib/modules/Resource/index.js +27 -59
  169. package/lib/modules/Resource/types.js +22 -32
  170. package/lib/modules/Resource/utils.js +30 -38
  171. package/lib/modules/ResourcePlanner/index.js +25 -23
  172. package/lib/modules/ResourcePlanner/localClock.js +54 -119
  173. package/lib/modules/ResourcePlanner/planner.js +591 -772
  174. package/lib/modules/ResourcePlanner/types.js +10 -29
  175. package/lib/modules/Rules/index.js +1218 -959
  176. package/lib/modules/Rules/types.js +17 -40
  177. package/lib/modules/SalesSummary/index.js +78 -89
  178. package/lib/modules/SalesSummary/types.js +4 -16
  179. package/lib/modules/SalesSummary/utils.js +359 -442
  180. package/lib/modules/ScanOrderLogger/index.js +59 -79
  181. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  182. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  183. package/lib/modules/ScanOrderLogger/types.js +4 -16
  184. package/lib/modules/Schedule/getDateIsInSchedule.js +334 -163
  185. package/lib/modules/Schedule/index.js +100 -114
  186. package/lib/modules/Schedule/type.js +4 -16
  187. package/lib/modules/Schedule/types.js +4 -16
  188. package/lib/modules/Schedule/utils.js +433 -291
  189. package/lib/modules/Step/index.js +40 -52
  190. package/lib/modules/Step/tyeps.js +4 -16
  191. package/lib/modules/Summary/index.js +66 -71
  192. package/lib/modules/Summary/types.js +4 -16
  193. package/lib/modules/Summary/utils.js +773 -418
  194. package/lib/modules/SurchargeList/index.js +46 -60
  195. package/lib/modules/SurchargeList/types.js +4 -16
  196. package/lib/modules/index.js +245 -63
  197. package/lib/plugins/app.js +4 -16
  198. package/lib/plugins/index.js +36 -25
  199. package/lib/plugins/request.js +137 -126
  200. package/lib/plugins/shopStore.js +4 -16
  201. package/lib/plugins/user.js +4 -16
  202. package/lib/plugins/window.js +171 -179
  203. package/lib/server/index.js +3027 -2655
  204. package/lib/server/modules/floor-plan/index.js +102 -123
  205. package/lib/server/modules/floor-plan/types.js +15 -30
  206. package/lib/server/modules/index.js +106 -68
  207. package/lib/server/modules/menu/index.js +146 -122
  208. package/lib/server/modules/menu/types.js +18 -31
  209. package/lib/server/modules/order/index.js +758 -956
  210. package/lib/server/modules/order/types.js +122 -33
  211. package/lib/server/modules/order/utils/filterBookings.js +219 -194
  212. package/lib/server/modules/order/utils/filterOrders.js +118 -92
  213. package/lib/server/modules/payment/index.js +59 -83
  214. package/lib/server/modules/payment/types.js +4 -16
  215. package/lib/server/modules/products/index.js +575 -459
  216. package/lib/server/modules/products/types.js +44 -34
  217. package/lib/server/modules/quotation/index.js +137 -172
  218. package/lib/server/modules/quotation/types.js +21 -31
  219. package/lib/server/modules/resource/index.js +213 -184
  220. package/lib/server/modules/resource/types.js +42 -33
  221. package/lib/server/modules/schedule/index.js +135 -123
  222. package/lib/server/modules/schedule/types.js +14 -21
  223. package/lib/server/modules/schedule/utils.js +334 -163
  224. package/lib/server/types.js +4 -16
  225. package/lib/server/utils/index.js +25 -23
  226. package/lib/server/utils/product.js +196 -139
  227. package/lib/server/utils/schedule.js +34 -41
  228. package/lib/server/utils/small-ticket.js +479 -456
  229. package/lib/server/utils/time.js +40 -49
  230. package/lib/solution/BaseSales/index.js +1276 -1485
  231. package/lib/solution/BaseSales/types.d.ts +2 -0
  232. package/lib/solution/BaseSales/types.js +42 -38
  233. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
  234. package/lib/solution/BaseSales/utils/cartPromotion.js +652 -498
  235. package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
  236. package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
  237. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
  238. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +138 -180
  239. package/lib/solution/BaseSales/utils.js +161 -143
  240. package/lib/solution/BookingByStep/index.d.ts +2 -2
  241. package/lib/solution/BookingByStep/index.js +1527 -1340
  242. package/lib/solution/BookingByStep/types.js +40 -99
  243. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  244. package/lib/solution/BookingByStep/utils/products.js +42 -52
  245. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  246. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  247. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  248. package/lib/solution/BookingTicket/index.js +598 -514
  249. package/lib/solution/BookingTicket/types.js +99 -77
  250. package/lib/solution/BookingTicket/utils/addProductDecision.js +229 -190
  251. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
  252. package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
  253. package/lib/solution/BookingTicket/utils/cartView.js +114 -99
  254. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  255. package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
  256. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
  257. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
  258. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
  259. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
  260. package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
  261. package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
  262. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  263. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
  264. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
  265. package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
  266. package/lib/solution/BuyTickets/index.js +67 -70
  267. package/lib/solution/BuyTickets/types.js +22 -38
  268. package/lib/solution/Checkout/index.js +1451 -1158
  269. package/lib/solution/Checkout/types.js +91 -61
  270. package/lib/solution/Checkout/utils/index.js +228 -156
  271. package/lib/solution/PlaceOrder/index.js +55 -0
  272. package/lib/solution/RegisterAndLogin/config.js +493 -460
  273. package/lib/solution/RegisterAndLogin/index.js +633 -630
  274. package/lib/solution/RegisterAndLogin/types.js +189 -76
  275. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  276. package/lib/solution/Sales/index.js +328 -324
  277. package/lib/solution/Sales/types.js +27 -33
  278. package/lib/solution/ScanOrder/index.js +822 -852
  279. package/lib/solution/ScanOrder/types.d.ts +2 -0
  280. package/lib/solution/ScanOrder/types.js +33 -34
  281. package/lib/solution/ScanOrder/utils.js +412 -374
  282. package/lib/solution/ShopDiscount/index.js +226 -232
  283. package/lib/solution/ShopDiscount/types.js +15 -37
  284. package/lib/solution/ShopDiscount/utils.js +300 -172
  285. package/lib/solution/UnifiedBookingSales/index.js +1052 -1213
  286. package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
  287. package/lib/solution/UnifiedBookingSales/types.js +10 -32
  288. package/lib/solution/VenueBooking/index.js +811 -879
  289. package/lib/solution/VenueBooking/types.js +19 -39
  290. package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
  291. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  292. package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
  293. package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
  294. package/lib/solution/VenueBooking/utils.js +130 -67
  295. package/lib/solution/index.js +124 -41
  296. package/lib/store/createStore.js +32 -29
  297. package/lib/types/index.js +4 -16
  298. package/lib/utils/payment-number.js +26 -46
  299. package/lib/utils/task.js +36 -36
  300. package/lib/utils/watch.js +81 -47
  301. package/package.json +2 -1
@@ -1,93 +1,88 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ var _exportNames = {
7
+ buildPlannerDiscountResult: true,
8
+ normalizeProductForAvailability: true,
9
+ buildAvailabilityResourcesFromV2: true,
10
+ collectAvailabilityResourceIds: true,
11
+ buildAvailabilityLineIdentity: true,
12
+ buildBookingFromAvailabilityAssignment: true,
13
+ buildBookingFromAvailabilityAssignments: true,
14
+ UnifiedBookingSalesImpl: true,
15
+ UnifiedBookingSales: true,
16
+ AvailabilityError: true
10
17
  };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ Object.defineProperty(exports, "AvailabilityError", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _ResourcePlanner.AvailabilityError;
16
22
  }
17
- return to;
18
- };
19
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/solution/UnifiedBookingSales/index.ts
31
- var UnifiedBookingSales_exports = {};
32
- __export(UnifiedBookingSales_exports, {
33
- AvailabilityError: () => import_ResourcePlanner2.AvailabilityError,
34
- UnifiedBookingSales: () => UnifiedBookingSales,
35
- UnifiedBookingSalesImpl: () => UnifiedBookingSalesImpl,
36
- buildAvailabilityLineIdentity: () => buildAvailabilityLineIdentity,
37
- buildAvailabilityResourcesFromV2: () => buildAvailabilityResourcesFromV2,
38
- buildBookingFromAvailabilityAssignment: () => buildBookingFromAvailabilityAssignment,
39
- buildBookingFromAvailabilityAssignments: () => buildBookingFromAvailabilityAssignments,
40
- buildPlannerDiscountResult: () => buildPlannerDiscountResult,
41
- collectAvailabilityResourceIds: () => collectAvailabilityResourceIds,
42
- normalizeProductForAvailability: () => normalizeProductForAvailability
43
23
  });
44
- module.exports = __toCommonJS(UnifiedBookingSales_exports);
45
- var import_dayjs = __toESM(require("dayjs"));
46
- var import_lodash_es = require("lodash-es");
47
- var import_modules = require("../../modules");
48
- var import_getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
49
- var import_ResourcePlanner = require("../../modules/ResourcePlanner");
50
- var import_types = require("./types");
51
- var import_remoteOccupancyCache = require("./remoteOccupancyCache");
52
- var import_BookingTicket = require("../BookingTicket");
53
- var import_localClock = require("../../modules/ResourcePlanner/localClock");
54
- __reExport(UnifiedBookingSales_exports, require("./types"), module.exports);
55
- var import_ResourcePlanner2 = require("../../modules/ResourcePlanner");
56
- var OPEN_DATA_SECTION_CODES = ["sale", "reservation", "fulfillment", "menu", "workflow", "basic", "checkout", "availability"];
57
- var OPEN_DATA_CACHE_TTL = 5 * 60 * 1e3;
24
+ exports.UnifiedBookingSalesImpl = exports.UnifiedBookingSales = void 0;
25
+ exports.buildAvailabilityLineIdentity = buildAvailabilityLineIdentity;
26
+ exports.buildAvailabilityResourcesFromV2 = buildAvailabilityResourcesFromV2;
27
+ exports.buildBookingFromAvailabilityAssignment = buildBookingFromAvailabilityAssignment;
28
+ exports.buildBookingFromAvailabilityAssignments = buildBookingFromAvailabilityAssignments;
29
+ exports.buildPlannerDiscountResult = buildPlannerDiscountResult;
30
+ exports.collectAvailabilityResourceIds = collectAvailabilityResourceIds;
31
+ exports.normalizeProductForAvailability = normalizeProductForAvailability;
32
+ var _dayjs = _interopRequireDefault(require("dayjs"));
33
+ var _lodashEs = require("lodash-es");
34
+ var _modules = require("../../modules");
35
+ var _getDateIsInSchedule = require("../../modules/Schedule/getDateIsInSchedule");
36
+ var _ResourcePlanner = require("../../modules/ResourcePlanner");
37
+ var _types = require("./types");
38
+ Object.keys(_types).forEach(function (key) {
39
+ if (key === "default" || key === "__esModule") return;
40
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
41
+ if (key in exports && exports[key] === _types[key]) return;
42
+ Object.defineProperty(exports, key, {
43
+ enumerable: true,
44
+ get: function () {
45
+ return _types[key];
46
+ }
47
+ });
48
+ });
49
+ var _remoteOccupancyCache = require("./remoteOccupancyCache");
50
+ var _BookingTicket = require("../BookingTicket");
51
+ var _localClock = require("../../modules/ResourcePlanner/localClock");
52
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
53
+ const OPEN_DATA_SECTION_CODES = ['sale', 'reservation', 'fulfillment', 'menu', 'workflow', 'basic', 'checkout', 'availability'];
54
+ const OPEN_DATA_CACHE_TTL = 5 * 60 * 1000;
58
55
  function normalizePositiveInteger(value) {
59
56
  const normalized = Number(value);
60
- if (!Number.isInteger(normalized) || normalized <= 0)
61
- return void 0;
57
+ if (!Number.isInteger(normalized) || normalized <= 0) return undefined;
62
58
  return normalized;
63
59
  }
64
60
  function isRecord(value) {
65
- return !!value && typeof value === "object" && !Array.isArray(value);
61
+ return !!value && typeof value === 'object' && !Array.isArray(value);
66
62
  }
67
63
  function pickLocalizedText(value) {
68
- if (!value)
69
- return void 0;
70
- if (typeof value === "string")
71
- return value;
72
- if (typeof value === "object") {
64
+ if (!value) return undefined;
65
+ if (typeof value === 'string') return value;
66
+ if (typeof value === 'object') {
73
67
  return value.en || value.zh || value.default || Object.values(value)[0];
74
68
  }
75
69
  return String(value);
76
70
  }
77
71
  function resolvePlannerDiscountId(discount) {
78
- var _a;
79
- return ((_a = discount.discount) == null ? void 0 : _a.resource_id) ?? discount.resource_id ?? discount.id;
72
+ return discount.discount?.resource_id ?? discount.resource_id ?? discount.id;
80
73
  }
81
74
  function resolvePlannerDiscountTitle(discount) {
82
- var _a;
83
- return pickLocalizedText(
84
- discount.name || discount.format_title || ((_a = discount.discount) == null ? void 0 : _a.title) || discount.title
85
- );
75
+ return pickLocalizedText(discount.name || discount.format_title || discount.discount?.title || discount.title);
86
76
  }
87
77
  function isPlannerDiscountAvailable(discount) {
88
- var _a;
89
- return discount.isDisabled !== true && discount.isAvailable !== false && ((_a = discount.config) == null ? void 0 : _a.isAvailable) !== false;
78
+ return discount.isDisabled !== true && discount.isAvailable !== false && discount.config?.isAvailable !== false;
90
79
  }
80
+
81
+ /**
82
+ * Converts Rules/Order discount internals into a small UI-facing diagnostic. The result keeps
83
+ * candidate-card state separate from line-level applications: a selected card is not proof that
84
+ * it actually discounted a planner product.
85
+ */
91
86
  function buildPlannerDiscountResult(params) {
92
87
  const {
93
88
  customerId,
@@ -101,39 +96,34 @@ function buildPlannerDiscountResult(params) {
101
96
  } = params;
102
97
  const items = (discountList || []).reduce((result, discount) => {
103
98
  const id = resolvePlannerDiscountId(discount);
104
- if (id !== void 0 && id !== null) {
99
+ if (id !== undefined && id !== null) {
105
100
  result.push({
106
101
  id,
107
102
  name: resolvePlannerDiscountTitle(discount),
108
103
  type: discount.tag || discount.type,
109
104
  available: isPlannerDiscountAvailable(discount),
110
105
  selected: discount.isSelected === true,
111
- savedAmount: Number(discount.savedAmount || 0) || void 0,
106
+ savedAmount: Number(discount.savedAmount || 0) || undefined,
112
107
  unavailableReason: discount.unavailableReason || discount.reason
113
108
  });
114
109
  }
115
110
  return result;
116
111
  }, []);
117
- const discountNameById = new Map(items.map((item) => [String(item.id), item.name]));
112
+ const discountNameById = new Map(items.map(item => [String(item.id), item.name]));
118
113
  const applications = [];
119
- (products || []).forEach((product) => {
120
- const productDiscounts = [
121
- ...Array.isArray(product.discount_list) ? product.discount_list : [],
122
- ...Array.isArray(product.product_bundle) ? product.product_bundle.flatMap((bundle) => (bundle == null ? void 0 : bundle.discount_list) || []) : []
123
- ];
124
- productDiscounts.forEach((discount) => {
125
- var _a;
114
+ (products || []).forEach(product => {
115
+ const productDiscounts = [...(Array.isArray(product.discount_list) ? product.discount_list : []), ...(Array.isArray(product.product_bundle) ? product.product_bundle.flatMap(bundle => bundle?.discount_list || []) : [])];
116
+ productDiscounts.forEach(discount => {
126
117
  const type = discount.tag || discount.type;
127
- if (!["good_pass", "discount_card", "product_discount_card"].includes(type))
128
- return;
118
+ if (!['good_pass', 'discount_card', 'product_discount_card'].includes(type)) return;
129
119
  const discountId = resolvePlannerDiscountId(discount);
130
120
  applications.push({
131
121
  discountId,
132
- discountName: discountId === void 0 ? void 0 : discountNameById.get(String(discountId)),
122
+ discountName: discountId === undefined ? undefined : discountNameById.get(String(discountId)),
133
123
  discountType: type,
134
124
  productId: product.product_id ?? product.id,
135
125
  productTitle: pickLocalizedText(product.title || product.name || product.product_title),
136
- productUid: ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) || product.unique_identification_number,
126
+ productUid: product.metadata?.unique_identification_number || product.unique_identification_number,
137
127
  amount: Number(discount.amount || 0)
138
128
  });
139
129
  });
@@ -142,17 +132,16 @@ function buildPlannerDiscountResult(params) {
142
132
  status,
143
133
  customerId,
144
134
  preferredDiscountFound,
145
- preferredDiscountApplied: preferredDiscountId === void 0 || preferredDiscountId === null ? void 0 : items.some((item) => String(item.id) === String(preferredDiscountId) && item.selected) && applications.some((item) => String(item.discountId) === String(preferredDiscountId)),
146
- availableDiscounts: items.filter((item) => item.available),
147
- selectedDiscounts: items.filter((item) => item.selected),
135
+ preferredDiscountApplied: preferredDiscountId === undefined || preferredDiscountId === null ? undefined : items.some(item => String(item.id) === String(preferredDiscountId) && item.selected) && applications.some(item => String(item.discountId) === String(preferredDiscountId)),
136
+ availableDiscounts: items.filter(item => item.available),
137
+ selectedDiscounts: items.filter(item => item.selected),
148
138
  applications,
149
139
  summaryBefore,
150
140
  summaryAfter
151
141
  };
152
142
  }
153
143
  function toNumberId(value) {
154
- if (value === void 0 || value === null || value === "")
155
- return void 0;
144
+ if (value === undefined || value === null || value === '') return undefined;
156
145
  const parsed = Number(value);
157
146
  return Number.isFinite(parsed) ? parsed : String(value);
158
147
  }
@@ -161,51 +150,45 @@ function toCustomerId(value) {
161
150
  return Number.isFinite(parsed) && parsed > 1 ? parsed : null;
162
151
  }
163
152
  function resolveTempOrderCustomerId(tempOrder) {
164
- var _a, _b, _c, _d, _e;
165
- return toCustomerId(
166
- (tempOrder == null ? void 0 : tempOrder.customer_id) || ((_a = tempOrder == null ? void 0 : tempOrder.customer) == null ? void 0 : _a.id) || ((_c = (_b = tempOrder == null ? void 0 : tempOrder._extend) == null ? void 0 : _b.customerSnapshot) == null ? void 0 : _c.id) || ((_e = (_d = tempOrder == null ? void 0 : tempOrder._extend) == null ? void 0 : _d.customerSnapshot) == null ? void 0 : _e.customer_id)
167
- );
153
+ return toCustomerId(tempOrder?.customer_id || tempOrder?.customer?.id || tempOrder?._extend?.customerSnapshot?.id || tempOrder?._extend?.customerSnapshot?.customer_id);
168
154
  }
169
155
  function isLocalOrderId(orderId) {
170
- return typeof orderId === "string" && orderId.startsWith("local_order");
156
+ return typeof orderId === 'string' && orderId.startsWith('local_order');
171
157
  }
172
158
  function isCustomerBoundDiscount(discount) {
173
- const type = (discount == null ? void 0 : discount.type) ?? (discount == null ? void 0 : discount.tag);
174
- return type === "good_pass" || type === "discount_card" || type === "product_discount_card";
159
+ const type = discount?.type ?? discount?.tag;
160
+ return type === 'good_pass' || type === 'discount_card' || type === 'product_discount_card';
175
161
  }
176
162
  function filterCustomerBoundDiscounts(discountList) {
177
- if (!Array.isArray(discountList))
178
- return [];
179
- return discountList.filter((discount) => !isCustomerBoundDiscount(discount));
163
+ if (!Array.isArray(discountList)) return [];
164
+ return discountList.filter(discount => !isCustomerBoundDiscount(discount));
180
165
  }
181
- var DEFAULT_AVAILABILITY_SLOT_STEP_MINUTES = 30;
182
- var DEFAULT_AVAILABILITY_BUSINESS_HOURS = {
183
- startTime: "09:00",
184
- endTime: "18:00"
166
+ const DEFAULT_AVAILABILITY_SLOT_STEP_MINUTES = 30;
167
+ const DEFAULT_AVAILABILITY_BUSINESS_HOURS = {
168
+ startTime: '09:00',
169
+ endTime: '18:00'
185
170
  };
186
- var MAX_AVAILABILITY_RANGE_DAYS = 90;
187
- var MAX_AVAILABILITY_CONTEXT_REGISTRY = 128;
188
- var MAX_AVAILABILITY_PROJECTION_POOL = 16;
189
- var MAX_REMOTE_OCCUPANCY_RESOURCE_DATE_CELLS = 4096;
171
+ const MAX_AVAILABILITY_RANGE_DAYS = 90;
172
+ const MAX_AVAILABILITY_CONTEXT_REGISTRY = 128;
173
+ const MAX_AVAILABILITY_PROJECTION_POOL = 16;
174
+ const MAX_REMOTE_OCCUPANCY_RESOURCE_DATE_CELLS = 4096;
190
175
  function isValidClockTime(value) {
191
176
  const match = /^(\d{2}):(\d{2})$/.exec(value);
192
- if (!match)
193
- return false;
177
+ if (!match) return false;
194
178
  return Number(match[1]) < 24 && Number(match[2]) < 60;
195
179
  }
196
180
  function assertValidAvailabilityTimezone(timezoneName) {
197
- if (!String(timezoneName || "").trim()) {
198
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "timezone label 不能为空", {
181
+ if (!String(timezoneName || '').trim()) {
182
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'timezone label 不能为空', {
199
183
  timezone: timezoneName
200
184
  });
201
185
  }
202
186
  }
203
187
  function normalizeAvailabilityLocalDateTime(value, fixedOffsetMinutes) {
204
- if (value == null || value === "")
205
- return null;
188
+ if (value == null || value === '') return null;
206
189
  try {
207
- const localText = typeof (value == null ? void 0 : value.format) === "function" ? value.format("YYYY-MM-DDTHH:mm:ss") : String(value);
208
- return (0, import_localClock.formatLocalDateTime)((0, import_localClock.parseLocalDateTime)(localText), fixedOffsetMinutes);
190
+ const localText = typeof value?.format === 'function' ? value.format('YYYY-MM-DDTHH:mm:ss') : String(value);
191
+ return (0, _localClock.formatLocalDateTime)((0, _localClock.parseLocalDateTime)(localText), fixedOffsetMinutes);
209
192
  } catch {
210
193
  return null;
211
194
  }
@@ -213,46 +196,42 @@ function normalizeAvailabilityLocalDateTime(value, fixedOffsetMinutes) {
213
196
  function normalizeAvailabilityLocalDateTimeRange(params) {
214
197
  const startText = normalizeAvailabilityLocalDateTime(params.startAt, params.fixedOffsetMinutes);
215
198
  const endText = normalizeAvailabilityLocalDateTime(params.endAt, params.fixedOffsetMinutes);
216
- if (!startText || !endText)
217
- return null;
218
- const startScalar = (0, import_localClock.localDateTimeToScalar)((0, import_localClock.parseLocalDateTime)(startText));
219
- let endScalar = (0, import_localClock.localDateTimeToScalar)((0, import_localClock.parseLocalDateTime)(endText));
199
+ if (!startText || !endText) return null;
200
+ const startScalar = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(startText));
201
+ let endScalar = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(endText));
220
202
  if (endScalar <= startScalar && params.rollOverEnd) {
221
- endScalar = (0, import_localClock.addLocalCalendarDays)(endScalar, 1);
203
+ endScalar = (0, _localClock.addLocalCalendarDays)(endScalar, 1);
222
204
  }
223
- if (endScalar <= startScalar)
224
- return null;
205
+ if (endScalar <= startScalar) return null;
225
206
  return {
226
207
  startAt: startText,
227
- endAt: (0, import_localClock.formatLocalDateTime)(endScalar, params.fixedOffsetMinutes),
208
+ endAt: (0, _localClock.formatLocalDateTime)(endScalar, params.fixedOffsetMinutes),
228
209
  startScalar,
229
210
  endScalar
230
211
  };
231
212
  }
232
213
  function sameAvailabilityId(left, right) {
233
- return left !== void 0 && left !== null && right !== void 0 && right !== null && String(left) === String(right);
214
+ return left !== undefined && left !== null && right !== undefined && right !== null && String(left) === String(right);
234
215
  }
235
216
  function uniqueAvailabilityIds(values) {
236
- const result = /* @__PURE__ */ new Map();
237
- values.forEach((value) => {
217
+ const result = new Map();
218
+ values.forEach(value => {
238
219
  const id = toNumberId(value);
239
- if (id !== void 0)
240
- result.set(String(id), id);
220
+ if (id !== undefined) result.set(String(id), id);
241
221
  });
242
222
  return Array.from(result.values());
243
223
  }
244
224
  function assertAvailabilityCatalogProductIds(productIds, context) {
245
- if (productIds == null)
246
- return;
225
+ if (productIds == null) return;
247
226
  if (!Array.isArray(productIds)) {
248
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", `${context} 必须是 number[]`, {
227
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', `${context} 必须是 number[]`, {
249
228
  context,
250
229
  productIds
251
230
  });
252
231
  }
253
- const invalidIds = productIds.filter((id) => typeof id !== "number" || !Number.isFinite(id));
232
+ const invalidIds = productIds.filter(id => typeof id !== 'number' || !Number.isFinite(id));
254
233
  if (invalidIds.length > 0) {
255
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", `${context} 只能包含有限数值商品 ID`, {
234
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', `${context} 只能包含有限数值商品 ID`, {
256
235
  context,
257
236
  invalidIds,
258
237
  productIds
@@ -260,74 +239,63 @@ function assertAvailabilityCatalogProductIds(productIds, context) {
260
239
  }
261
240
  }
262
241
  function normalizeResourceType(_value) {
263
- return "single";
242
+ // 当前业务只支持每个资源组选择一个具体资源。
243
+ // 保留公共联合类型以兼容已有调用方,但暂不启用 multiple/capacity 分支。
244
+ return 'single';
264
245
  }
265
246
  function resolveProductKind(product) {
266
- var _a, _b, _c;
267
- if (product.duration || product.service_duration)
268
- return "duration";
269
- if (product.extension_type === "venue_slot")
270
- return "venue_slot";
271
- if (["session_product", "session_ticket"].includes(product.extension_type))
272
- return "session";
273
- if (((_a = product.cartDetailValue) == null ? void 0 : _a.session) || ((_c = (_b = product._extend) == null ? void 0 : _b.other) == null ? void 0 : _c.session) || product.session) {
274
- return "session";
275
- }
276
- const scheduleIds = product["schedule.ids"] || product.schedule_ids;
277
- if (Array.isArray(scheduleIds) && scheduleIds.length > 0)
278
- return "session";
279
- return "normal";
247
+ if (product.duration || product.service_duration) return 'duration';
248
+ if (product.extension_type === 'venue_slot') return 'venue_slot';
249
+ if (['session_product', 'session_ticket'].includes(product.extension_type)) return 'session';
250
+ if (product.cartDetailValue?.session || product._extend?.other?.session || product.session) {
251
+ return 'session';
252
+ }
253
+ const scheduleIds = product['schedule.ids'] || product.schedule_ids;
254
+ if (Array.isArray(scheduleIds) && scheduleIds.length > 0) return 'session';
255
+ return 'normal';
280
256
  }
281
257
  function expandScheduleDateRanges(values) {
282
- if (!Array.isArray(values))
283
- return [];
284
- const dates = /* @__PURE__ */ new Set();
285
- values.forEach((value) => {
286
- if (typeof value === "string") {
258
+ if (!Array.isArray(values)) return [];
259
+ const dates = new Set();
260
+ values.forEach(value => {
261
+ if (typeof value === 'string') {
287
262
  try {
288
- dates.add((0, import_localClock.formatLocalDate)((0, import_localClock.parseLocalDate)(value.slice(0, 10))));
263
+ dates.add((0, _localClock.formatLocalDate)((0, _localClock.parseLocalDate)(value.slice(0, 10))));
289
264
  } catch {
265
+ // Ignore invalid configuration entries.
290
266
  }
291
267
  return;
292
268
  }
293
- const startValue = (value == null ? void 0 : value.start) || (value == null ? void 0 : value.start_date) || (value == null ? void 0 : value.date);
294
- const endValue = (value == null ? void 0 : value.end) || (value == null ? void 0 : value.end_date) || startValue;
269
+ const startValue = value?.start || value?.start_date || value?.date;
270
+ const endValue = value?.end || value?.end_date || startValue;
295
271
  let start;
296
272
  let end;
297
273
  try {
298
- start = (0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(String(startValue).slice(0, 10)));
299
- end = (0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(String(endValue).slice(0, 10)));
274
+ start = (0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(String(startValue).slice(0, 10)));
275
+ end = (0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(String(endValue).slice(0, 10)));
300
276
  } catch {
301
277
  return;
302
278
  }
303
- if (end < start)
304
- return;
279
+ if (end < start) return;
305
280
  let cursor = start;
306
281
  let guard = 0;
307
282
  while (cursor <= end && guard < MAX_AVAILABILITY_RANGE_DAYS) {
308
- dates.add((0, import_localClock.formatLocalDate)(cursor));
309
- cursor = (0, import_localClock.addLocalCalendarDays)(cursor, 1);
283
+ dates.add((0, _localClock.formatLocalDate)(cursor));
284
+ cursor = (0, _localClock.addLocalCalendarDays)(cursor, 1);
310
285
  guard += 1;
311
286
  }
312
287
  });
313
288
  return Array.from(dates).sort();
314
289
  }
315
290
  function normalizeRequirementGroups(product) {
316
- var _a;
317
- const resources = (_a = product.product_resource) == null ? void 0 : _a.resources;
318
- if (!Array.isArray(resources))
319
- return [];
320
- return resources.filter((resource) => (resource == null ? void 0 : resource.status) !== 0).map((resource, index) => {
321
- var _a2, _b, _c;
291
+ const resources = product.product_resource?.resources;
292
+ if (!Array.isArray(resources)) return [];
293
+ return resources.filter(resource => resource?.status !== 0).map((resource, index) => {
322
294
  const formId = toNumberId(resource.id ?? resource.form_id);
323
295
  const required = resource.required ?? resource.status === 1;
324
296
  const resourceType = normalizeResourceType(resource.type);
325
- const combinedIds = ((_a2 = resource.combined_resource) == null ? void 0 : _a2.status) === 1 ? (_b = resource.combined_resource) == null ? void 0 : _b.resource_ids : [];
326
- const resourceIds = uniqueAvailabilityIds([
327
- ...Array.isArray(resource.default_resource) ? resource.default_resource : [],
328
- ...Array.isArray(resource.optional_resource) ? resource.optional_resource : [],
329
- ...Array.isArray(combinedIds) ? combinedIds : []
330
- ]);
297
+ const combinedIds = resource.combined_resource?.status === 1 ? resource.combined_resource?.resource_ids : [];
298
+ const resourceIds = uniqueAvailabilityIds([...(Array.isArray(resource.default_resource) ? resource.default_resource : []), ...(Array.isArray(resource.optional_resource) ? resource.optional_resource : []), ...(Array.isArray(combinedIds) ? combinedIds : [])]);
331
299
  const min = required ? 1 : 0;
332
300
  const max = 1;
333
301
  return {
@@ -340,30 +308,25 @@ function normalizeRequirementGroups(product) {
340
308
  min,
341
309
  max,
342
310
  resourceIds,
343
- capacityRequired: Math.max(1, Number(
344
- resource.capacity_required ?? ((_c = product.capacity) == null ? void 0 : _c.default) ?? product.capacity ?? 1
345
- ) || 1),
311
+ capacityRequired: Math.max(1, Number(resource.capacity_required ?? product.capacity?.default ?? product.capacity ?? 1) || 1),
346
312
  raw: resource
347
313
  };
348
314
  });
349
315
  }
350
316
  function normalizeScheduleRepeatType(value) {
351
- if (value === "daily" || value === 1 || value === "1")
352
- return "daily";
353
- if (value === "weekly" || value === 2 || value === "2")
354
- return "weekly";
355
- return "none";
317
+ if (value === 'daily' || value === 1 || value === '1') return 'daily';
318
+ if (value === 'weekly' || value === 2 || value === '2') return 'weekly';
319
+ return 'none';
356
320
  }
357
321
  function normalizeAbsoluteSessionRange(params) {
358
- const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, import_localClock.captureRuntimeOffsetMinutes)();
322
+ const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, _localClock.captureRuntimeOffsetMinutes)();
359
323
  const range = normalizeAvailabilityLocalDateTimeRange({
360
324
  startAt: params.startAt,
361
325
  endAt: params.endAt,
362
326
  fixedOffsetMinutes,
363
327
  rollOverEnd: true
364
328
  });
365
- if (!range)
366
- return null;
329
+ if (!range) return null;
367
330
  return {
368
331
  startAt: range.startAt,
369
332
  endAt: range.endAt,
@@ -375,7 +338,6 @@ function normalizeAbsoluteSessionRange(params) {
375
338
  };
376
339
  }
377
340
  function normalizeScheduleItem(schedule, fixedOffsetMinutes) {
378
- var _a, _b;
379
341
  const rules = [];
380
342
  const ranges = [];
381
343
  const scheduleId = toNumberId(schedule.id ?? schedule.schedule_id);
@@ -383,61 +345,61 @@ function normalizeScheduleItem(schedule, fixedOffsetMinutes) {
383
345
  const repeatRule = schedule.repeat_rule || {};
384
346
  const startAt = schedule.start_at || schedule.start || schedule.start_time;
385
347
  const endAt = schedule.end_at || schedule.end || schedule.end_time;
386
- const startDate = startAt ? String(startAt).slice(0, 10) : void 0;
387
- const configuredEndDate = ((_a = repeatRule.end) == null ? void 0 : _a.type) === "date" ? (_b = repeatRule.end) == null ? void 0 : _b.end_date : void 0;
388
- const endDate = configuredEndDate ? String(configuredEndDate).slice(0, 10) : void 0;
348
+ const startDate = startAt ? String(startAt).slice(0, 10) : undefined;
349
+ const configuredEndDate = repeatRule.end?.type === 'date' ? repeatRule.end?.end_date : undefined;
350
+ const endDate = configuredEndDate ? String(configuredEndDate).slice(0, 10) : undefined;
389
351
  const includedDates = expandScheduleDateRanges(repeatRule.included_date);
390
352
  const excludedDates = expandScheduleDateRanges(repeatRule.excluded_date);
391
- const addRule = (params) => {
392
- const mode = repeatType === "weekly" ? "weekly" : "daily";
353
+ const addRule = params => {
354
+ const mode = repeatType === 'weekly' ? 'weekly' : 'daily';
393
355
  rules.push({
394
- id: `${String(scheduleId ?? "schedule")}:${params.idSuffix}`,
356
+ id: `${String(scheduleId ?? 'schedule')}:${params.idSuffix}`,
395
357
  mode,
396
358
  startTime: params.startTime.slice(0, 5),
397
359
  endTime: params.endTime.slice(0, 5),
398
360
  startDate,
399
361
  endDate,
400
362
  frequency: Math.max(1, Number(repeatRule.frequency || 1)),
401
- weekdays: repeatType === "weekly" ? (repeatRule.frequency_date || []).map(Number).filter(Number.isFinite) : void 0,
363
+ weekdays: repeatType === 'weekly' ? (repeatRule.frequency_date || []).map(Number).filter(Number.isFinite) : undefined,
402
364
  includeDates: includedDates,
403
365
  excludeDates: excludedDates,
404
366
  scheduleRef: {
405
367
  scheduleId,
406
368
  timeSlotId: params.timeSlotId,
407
- source: `schedule_${schedule.type || "standard"}`
369
+ source: `schedule_${schedule.type || 'standard'}`
408
370
  }
409
371
  });
410
372
  };
411
- if (schedule.type === "designation") {
373
+ if (schedule.type === 'designation') {
412
374
  const designations = Array.isArray(schedule.designation) ? schedule.designation : schedule.designation ? [schedule.designation] : [];
413
- designations.forEach((designation) => {
375
+ designations.forEach(designation => {
414
376
  const range = normalizeAbsoluteSessionRange({
415
377
  startAt: `${designation.start_date} ${designation.start_time}`,
416
378
  endAt: `${designation.end_date || designation.start_date} ${designation.end_time}`,
417
379
  scheduleId,
418
- source: "schedule_designation",
380
+ source: 'schedule_designation',
419
381
  fixedOffsetMinutes
420
382
  });
421
- if (range)
422
- ranges.push(range);
383
+ if (range) ranges.push(range);
423
384
  });
424
- return { rules, ranges };
385
+ return {
386
+ rules,
387
+ ranges
388
+ };
425
389
  }
426
- if (schedule.type === "time-slots" && Array.isArray(schedule.time_slot)) {
390
+ if (schedule.type === 'time-slots' && Array.isArray(schedule.time_slot)) {
427
391
  schedule.time_slot.forEach((slot, index) => {
428
- if (!slot.start_time || !slot.end_time)
429
- return;
430
- if (repeatType === "none" && startDate) {
392
+ if (!slot.start_time || !slot.end_time) return;
393
+ if (repeatType === 'none' && startDate) {
431
394
  const range = normalizeAbsoluteSessionRange({
432
395
  startAt: `${startDate} ${slot.start_time}`,
433
396
  endAt: `${startDate} ${slot.end_time}`,
434
397
  scheduleId,
435
398
  timeSlotId: toNumberId(slot.id),
436
- source: "schedule_time_slot",
399
+ source: 'schedule_time_slot',
437
400
  fixedOffsetMinutes
438
401
  });
439
- if (range)
440
- ranges.push(range);
402
+ if (range) ranges.push(range);
441
403
  return;
442
404
  }
443
405
  addRule({
@@ -447,69 +409,70 @@ function normalizeScheduleItem(schedule, fixedOffsetMinutes) {
447
409
  timeSlotId: toNumberId(slot.id)
448
410
  });
449
411
  });
450
- return { rules, ranges };
412
+ return {
413
+ rules,
414
+ ranges
415
+ };
451
416
  }
452
417
  if (startAt && endAt) {
453
- if (repeatType === "none") {
418
+ if (repeatType === 'none') {
454
419
  const range = normalizeAbsoluteSessionRange({
455
420
  startAt,
456
421
  endAt,
457
422
  scheduleId,
458
- source: "schedule_standard",
423
+ source: 'schedule_standard',
459
424
  fixedOffsetMinutes
460
425
  });
461
- if (range)
462
- ranges.push(range);
426
+ if (range) ranges.push(range);
463
427
  } else {
464
428
  try {
465
429
  addRule({
466
- idSuffix: "standard",
467
- startTime: (0, import_localClock.formatLocalTime)(String(startAt), false),
468
- endTime: (0, import_localClock.formatLocalTime)(String(endAt), false)
430
+ idSuffix: 'standard',
431
+ startTime: (0, _localClock.formatLocalTime)(String(startAt), false),
432
+ endTime: (0, _localClock.formatLocalTime)(String(endAt), false)
469
433
  });
470
434
  } catch {
435
+ // Invalid schedule boundaries do not produce a recurring rule.
471
436
  }
472
437
  }
473
438
  }
474
- return { rules, ranges };
439
+ return {
440
+ rules,
441
+ ranges
442
+ };
475
443
  }
476
444
  function resolveProductScheduleItems(product, scheduleList) {
477
- const scheduleMap = new Map(scheduleList.map((schedule) => [String(schedule.id), schedule]));
478
- const rawSchedules = [product.schedules, product.schedule, product._schedule].flatMap((value) => Array.isArray(value) ? value : value ? [value] : []);
479
- const explicitIds = uniqueAvailabilityIds([
480
- ...Array.isArray(product["schedule.ids"]) ? product["schedule.ids"] : [],
481
- ...Array.isArray(product.schedule_ids) ? product.schedule_ids : [],
482
- ...rawSchedules.filter((item) => typeof item !== "object")
483
- ]);
484
- const result = /* @__PURE__ */ new Map();
485
- rawSchedules.filter((item) => item && typeof item === "object").forEach((schedule) => {
445
+ const scheduleMap = new Map(scheduleList.map(schedule => [String(schedule.id), schedule]));
446
+ const rawSchedules = [product.schedules, product.schedule, product._schedule].flatMap(value => Array.isArray(value) ? value : value ? [value] : []);
447
+ const explicitIds = uniqueAvailabilityIds([...(Array.isArray(product['schedule.ids']) ? product['schedule.ids'] : []), ...(Array.isArray(product.schedule_ids) ? product.schedule_ids : []), ...rawSchedules.filter(item => typeof item !== 'object')]);
448
+ const result = new Map();
449
+ rawSchedules.filter(item => item && typeof item === 'object').forEach(schedule => {
486
450
  result.set(String(schedule.id ?? JSON.stringify(schedule)), schedule);
487
451
  });
488
- explicitIds.forEach((id) => {
452
+ explicitIds.forEach(id => {
489
453
  const schedule = scheduleMap.get(String(id));
490
- if (schedule)
491
- result.set(String(id), schedule);
454
+ if (schedule) result.set(String(id), schedule);
492
455
  });
493
456
  return Array.from(result.values());
494
457
  }
495
- function normalizeProductForAvailability(product, scheduleList = [], fixedOffsetMinutes = (0, import_localClock.captureRuntimeOffsetMinutes)()) {
496
- var _a, _b, _c, _d, _e;
458
+
459
+ /** Converts ProductList and schedule records into the pure Availability vocabulary. */
460
+ function normalizeProductForAvailability(product, scheduleList = [], fixedOffsetMinutes = (0, _localClock.captureRuntimeOffsetMinutes)()) {
497
461
  const raw = product;
498
462
  const kind = resolveProductKind(raw);
499
463
  const sessionRules = [];
500
464
  const sessionRanges = [];
501
- const explicitSession = ((_a = raw.cartDetailValue) == null ? void 0 : _a.session) || ((_c = (_b = raw._extend) == null ? void 0 : _b.other) == null ? void 0 : _c.session) || raw.session;
465
+ const explicitSession = raw.cartDetailValue?.session || raw._extend?.other?.session || raw.session;
502
466
  const explicitRange = normalizeAbsoluteSessionRange({
503
- startAt: explicitSession == null ? void 0 : explicitSession.start_at,
504
- endAt: explicitSession == null ? void 0 : explicitSession.end_at,
505
- scheduleId: toNumberId(explicitSession == null ? void 0 : explicitSession.schedule_id),
506
- timeSlotId: toNumberId(explicitSession == null ? void 0 : explicitSession.time_slot_id),
507
- source: "product_session",
467
+ startAt: explicitSession?.start_at,
468
+ endAt: explicitSession?.end_at,
469
+ scheduleId: toNumberId(explicitSession?.schedule_id),
470
+ timeSlotId: toNumberId(explicitSession?.time_slot_id),
471
+ source: 'product_session',
508
472
  fixedOffsetMinutes
509
473
  });
510
- if (explicitRange)
511
- sessionRanges.push(explicitRange);
512
- resolveProductScheduleItems(raw, scheduleList).forEach((schedule) => {
474
+ if (explicitRange) sessionRanges.push(explicitRange);
475
+ resolveProductScheduleItems(raw, scheduleList).forEach(schedule => {
513
476
  const normalized = normalizeScheduleItem(schedule, fixedOffsetMinutes);
514
477
  sessionRules.push(...normalized.rules);
515
478
  sessionRanges.push(...normalized.ranges);
@@ -518,11 +481,11 @@ function normalizeProductForAvailability(product, scheduleList = [], fixedOffset
518
481
  id: raw.id ?? raw.product_id,
519
482
  title: pickLocalizedText(raw.title || raw.name || raw.product_title),
520
483
  kind,
521
- durationMinutes: kind === "duration" ? Math.max(1, Number(((_d = raw.duration) == null ? void 0 : _d.value) || raw.duration || raw.service_duration || 30) || 30) : void 0,
484
+ durationMinutes: kind === 'duration' ? Math.max(1, Number(raw.duration?.value || raw.duration || raw.service_duration || 30) || 30) : undefined,
522
485
  requirementGroups: normalizeRequirementGroups(raw),
523
486
  sessionRules,
524
487
  sessionRanges,
525
- capacityRequired: Math.max(1, Number(((_e = raw.capacity) == null ? void 0 : _e.default) || raw.capacity || 1) || 1),
488
+ capacityRequired: Math.max(1, Number(raw.capacity?.default || raw.capacity || 1) || 1),
526
489
  quantity: Math.max(1, Number(raw.num || raw.quantity || 1) || 1),
527
490
  cutOffPolicy: normalizeAvailabilityCutOffPolicy(raw.cut_off_time),
528
491
  raw
@@ -530,102 +493,121 @@ function normalizeProductForAvailability(product, scheduleList = [], fixedOffset
530
493
  }
531
494
  function normalizeAvailabilityCutOffNumber(value, context) {
532
495
  if (value == null) {
533
- return { reason: `${context} 缺失` };
496
+ return {
497
+ reason: `${context} 缺失`
498
+ };
534
499
  }
535
- if (typeof value === "string" && !value.trim()) {
536
- return { reason: `${context} 缺失` };
500
+ if (typeof value === 'string' && !value.trim()) {
501
+ return {
502
+ reason: `${context} 缺失`
503
+ };
537
504
  }
538
505
  const normalized = Number(value);
539
506
  if (!Number.isFinite(normalized) || normalized < 0) {
540
- return { reason: `${context} 必须是非负有限数` };
507
+ return {
508
+ reason: `${context} 必须是非负有限数`
509
+ };
541
510
  }
542
- return { value: normalized };
511
+ return {
512
+ value: normalized
513
+ };
543
514
  }
544
515
  function normalizeAvailabilityCutOffInteger(value, context) {
545
516
  const numeric = normalizeAvailabilityCutOffNumber(value, context);
546
- if (numeric.reason)
547
- return numeric;
517
+ if (numeric.reason) return numeric;
548
518
  if (!Number.isInteger(numeric.value)) {
549
- return { reason: `${context} 必须是非负整数` };
519
+ return {
520
+ reason: `${context} 必须是非负整数`
521
+ };
550
522
  }
551
- return { value: numeric.value };
523
+ return {
524
+ value: numeric.value
525
+ };
552
526
  }
553
527
  function invalidAvailabilityCutOffPolicy(reason) {
554
- return { type: "invalid", reason };
528
+ return {
529
+ type: 'invalid',
530
+ reason
531
+ };
555
532
  }
556
533
  function normalizeAvailabilityFutureDay(raw) {
557
- if (!Object.prototype.hasOwnProperty.call(raw, "future_day"))
558
- return {};
559
- const futureDay = normalizeAvailabilityCutOffInteger(raw.future_day, "cut_off_time.future_day");
560
- return futureDay.reason ? { reason: futureDay.reason } : { futureDay: futureDay.value };
534
+ if (!Object.prototype.hasOwnProperty.call(raw, 'future_day')) return {};
535
+ const futureDay = normalizeAvailabilityCutOffInteger(raw.future_day, 'cut_off_time.future_day');
536
+ return futureDay.reason ? {
537
+ reason: futureDay.reason
538
+ } : {
539
+ futureDay: futureDay.value
540
+ };
561
541
  }
562
542
  function normalizeAvailabilityCutOffPolicy(raw) {
563
- if (raw == null || raw === "")
564
- return void 0;
543
+ if (raw == null || raw === '') return undefined;
565
544
  if (!isRecord(raw)) {
566
- return invalidAvailabilityCutOffPolicy("cut_off_time 必须是对象");
545
+ return invalidAvailabilityCutOffPolicy('cut_off_time 必须是对象');
567
546
  }
568
547
  const futureDay = normalizeAvailabilityFutureDay(raw);
569
548
  if (futureDay.reason) {
570
549
  return invalidAvailabilityCutOffPolicy(futureDay.reason);
571
550
  }
572
- const type = String(raw.type ?? "").trim();
551
+ const type = String(raw.type ?? '').trim();
573
552
  if (!type) {
574
- return invalidAvailabilityCutOffPolicy("cut_off_time.type 缺失");
553
+ return invalidAvailabilityCutOffPolicy('cut_off_time.type 缺失');
575
554
  }
576
- if (type === "ongoing") {
555
+ if (type === 'ongoing') {
577
556
  if (!isRecord(raw.ongoing)) {
578
- return invalidAvailabilityCutOffPolicy("cut_off_time.ongoing 缺失");
557
+ return invalidAvailabilityCutOffPolicy('cut_off_time.ongoing 缺失');
579
558
  }
580
- const ongoingType = String(raw.ongoing.type ?? "").trim();
581
- if (ongoingType === "before_end") {
559
+ const ongoingType = String(raw.ongoing.type ?? '').trim();
560
+ if (ongoingType === 'before_end') {
582
561
  return {
583
- type: "ongoing",
584
- mode: "before_end",
585
- ...futureDay.futureDay === void 0 ? {} : { futureDay: futureDay.futureDay }
562
+ type: 'ongoing',
563
+ mode: 'before_end',
564
+ ...(futureDay.futureDay === undefined ? {} : {
565
+ futureDay: futureDay.futureDay
566
+ })
586
567
  };
587
568
  }
588
- if (ongoingType === "after_start") {
589
- const graceMinutes = normalizeAvailabilityCutOffNumber(
590
- raw.ongoing.unit,
591
- "cut_off_time.ongoing.unit"
592
- );
569
+ if (ongoingType === 'after_start') {
570
+ const graceMinutes = normalizeAvailabilityCutOffNumber(raw.ongoing.unit, 'cut_off_time.ongoing.unit');
593
571
  return graceMinutes.reason ? invalidAvailabilityCutOffPolicy(graceMinutes.reason) : {
594
- type: "ongoing",
595
- mode: "after_start",
572
+ type: 'ongoing',
573
+ mode: 'after_start',
596
574
  graceMinutes: graceMinutes.value,
597
- ...futureDay.futureDay === void 0 ? {} : { futureDay: futureDay.futureDay }
575
+ ...(futureDay.futureDay === undefined ? {} : {
576
+ futureDay: futureDay.futureDay
577
+ })
598
578
  };
599
579
  }
600
580
  return invalidAvailabilityCutOffPolicy(`未知的 cut_off_time.ongoing.type: ${ongoingType}`);
601
581
  }
602
- if (type === "before_start") {
582
+ if (type === 'before_start') {
603
583
  return {
604
- type: "before_start",
605
- ...futureDay.futureDay === void 0 ? {} : { futureDay: futureDay.futureDay }
584
+ type: 'before_start',
585
+ ...(futureDay.futureDay === undefined ? {} : {
586
+ futureDay: futureDay.futureDay
587
+ })
606
588
  };
607
589
  }
608
- if (type === "advance") {
609
- const unit = normalizeAvailabilityCutOffNumber(raw.unit, "cut_off_time.unit");
610
- if (unit.reason)
611
- return invalidAvailabilityCutOffPolicy(unit.reason);
612
- const unitType = String(raw.unit_type ?? "").trim();
613
- if (!["days", "hours", "minutes"].includes(unitType)) {
614
- return invalidAvailabilityCutOffPolicy("cut_off_time.unit_type 必须是 days|hours|minutes");
590
+ if (type === 'advance') {
591
+ const unit = normalizeAvailabilityCutOffNumber(raw.unit, 'cut_off_time.unit');
592
+ if (unit.reason) return invalidAvailabilityCutOffPolicy(unit.reason);
593
+ const unitType = String(raw.unit_type ?? '').trim();
594
+ if (!['days', 'hours', 'minutes'].includes(unitType)) {
595
+ return invalidAvailabilityCutOffPolicy('cut_off_time.unit_type 必须是 days|hours|minutes');
615
596
  }
616
597
  return {
617
- type: "advance",
598
+ type: 'advance',
618
599
  unit: unit.value,
619
- unitType,
620
- ...futureDay.futureDay === void 0 ? {} : { futureDay: futureDay.futureDay }
600
+ unitType: unitType,
601
+ ...(futureDay.futureDay === undefined ? {} : {
602
+ futureDay: futureDay.futureDay
603
+ })
621
604
  };
622
605
  }
623
606
  return invalidAvailabilityCutOffPolicy(`未知的 cut_off_time.type: ${type}`);
624
607
  }
625
- function normalizeResource(raw, fixedOffsetMinutes = (0, import_localClock.captureRuntimeOffsetMinutes)()) {
608
+ function normalizeResource(raw, fixedOffsetMinutes = (0, _localClock.captureRuntimeOffsetMinutes)()) {
626
609
  const id = raw.resourceId ?? raw.resource_id ?? raw.id;
627
- if (id === void 0 || id === null || id === "")
628
- return null;
610
+ if (id === undefined || id === null || id === '') return null;
629
611
  const rawWindows = raw.windows || raw.times || [];
630
612
  return {
631
613
  id,
@@ -634,123 +616,129 @@ function normalizeResource(raw, fixedOffsetMinutes = (0, import_localClock.captu
634
616
  code: raw.code,
635
617
  resourceType: normalizeResourceType(raw.type || raw.resourceType),
636
618
  capacity: Math.max(1, Number(raw.capacity || raw.max_capacity || 1) || 1),
637
- windows: (Array.isArray(rawWindows) ? rawWindows : []).flatMap((window) => {
619
+ windows: (Array.isArray(rawWindows) ? rawWindows : []).flatMap(window => {
638
620
  const range = normalizeAvailabilityLocalDateTimeRange({
639
621
  startAt: window.startAt || window.start_at || window.start,
640
622
  endAt: window.endAt || window.end_at || window.end,
641
623
  fixedOffsetMinutes,
642
624
  rollOverEnd: true
643
625
  });
644
- if (!range)
645
- return [];
646
- return [{ startAt: range.startAt, endAt: range.endAt, source: window.source, raw: window }];
626
+ if (!range) return [];
627
+ return [{
628
+ startAt: range.startAt,
629
+ endAt: range.endAt,
630
+ source: window.source,
631
+ raw: window
632
+ }];
647
633
  }),
648
634
  raw
649
635
  };
650
636
  }
651
637
  function normalizeScheduleIds(raw) {
652
638
  const ids = raw.schedule ?? raw.schedule_ids ?? raw.scheduleIds ?? [];
653
- return (Array.isArray(ids) ? ids : [ids]).map((id) => toNumberId(id)).filter((id) => id !== void 0);
639
+ return (Array.isArray(ids) ? ids : [ids]).map(id => toNumberId(id)).filter(id => id !== undefined);
654
640
  }
655
641
  function dateRangeDays(dateRange) {
656
- if (!(dateRange == null ? void 0 : dateRange.startDate) || !(dateRange == null ? void 0 : dateRange.endDate))
657
- return [];
642
+ if (!dateRange?.startDate || !dateRange?.endDate) return [];
658
643
  const dates = [];
659
- const startScalar = (0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(dateRange.startDate));
660
- const endScalar = (0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(dateRange.endDate));
661
- if (endScalar < startScalar)
662
- return dates;
663
- for (let cursor = startScalar; cursor <= endScalar; cursor = (0, import_localClock.addLocalCalendarDays)(cursor, 1)) {
664
- dates.push((0, import_localClock.formatLocalDate)(cursor));
644
+ const startScalar = (0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(dateRange.startDate));
645
+ const endScalar = (0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(dateRange.endDate));
646
+ if (endScalar < startScalar) return dates;
647
+ for (let cursor = startScalar; cursor <= endScalar; cursor = (0, _localClock.addLocalCalendarDays)(cursor, 1)) {
648
+ dates.push((0, _localClock.formatLocalDate)(cursor));
665
649
  }
666
650
  return dates;
667
651
  }
668
- function normalizeResourceOccupancy(rawEvent, resourceId, source = "remote", fixedOffsetMinutes = (0, import_localClock.captureRuntimeOffsetMinutes)()) {
669
- var _a, _b;
652
+ function normalizeResourceOccupancy(rawEvent, resourceId, source = 'remote', fixedOffsetMinutes = (0, _localClock.captureRuntimeOffsetMinutes)()) {
670
653
  const range = normalizeAvailabilityLocalDateTimeRange({
671
654
  startAt: rawEvent.start_at ?? rawEvent.startAt ?? rawEvent.start_time ?? rawEvent.startTime,
672
655
  endAt: rawEvent.end_at ?? rawEvent.endAt ?? rawEvent.end_time ?? rawEvent.endTime,
673
656
  fixedOffsetMinutes,
674
657
  rollOverEnd: false
675
658
  });
676
- if (!range)
677
- return null;
659
+ if (!range) return null;
678
660
  return {
679
- id: rawEvent.id == null ? void 0 : String(rawEvent.id),
661
+ id: rawEvent.id == null ? undefined : String(rawEvent.id),
680
662
  resourceId,
681
663
  startAt: range.startAt,
682
664
  endAt: range.endAt,
683
665
  pax: Number(rawEvent.pax ?? rawEvent.number ?? rawEvent.capacity ?? 1) || 1,
684
- source: rawEvent.source === "cart" || rawEvent.source === "selection" ? rawEvent.source : source,
666
+ source: rawEvent.source === 'cart' || rawEvent.source === 'selection' ? rawEvent.source : source,
685
667
  scheduleEventId: toNumberId(rawEvent.schedule_event_id ?? rawEvent.scheduleEventId),
686
668
  serverEventId: toNumberId(rawEvent.schedule_event_id ?? rawEvent.server_event_id ?? rawEvent.id),
687
- bookingUid: rawEvent.booking_uid ?? rawEvent.bookingUid ?? ((_a = rawEvent.metadata) == null ? void 0 : _a.unique_identification_number),
688
- productUid: rawEvent.product_uid ?? rawEvent.productUid ?? ((_b = rawEvent.metadata) == null ? void 0 : _b.product_uid),
669
+ bookingUid: rawEvent.booking_uid ?? rawEvent.bookingUid ?? rawEvent.metadata?.unique_identification_number,
670
+ productUid: rawEvent.product_uid ?? rawEvent.productUid ?? rawEvent.metadata?.product_uid,
689
671
  raw: rawEvent
690
672
  };
691
673
  }
692
674
  function buildResourceWindowFallbackTimes(params) {
693
- const { raw, dates, scheduleIds } = params;
694
- const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, import_localClock.captureRuntimeOffsetMinutes)();
675
+ const {
676
+ raw,
677
+ dates,
678
+ scheduleIds
679
+ } = params;
680
+ const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, _localClock.captureRuntimeOffsetMinutes)();
695
681
  const boundary = normalizeAvailabilityLocalDateTimeRange({
696
682
  startAt: raw.start_time || raw.start_at || raw.startTime,
697
683
  endAt: raw.end_time || raw.end_at || raw.endTime,
698
684
  fixedOffsetMinutes,
699
685
  rollOverEnd: true
700
686
  });
701
- if (!boundary)
702
- return [];
703
- return dates.flatMap((date) => {
704
- const dayStart = (0, import_localClock.localDateTimeToScalar)((0, import_localClock.parseLocalDateTime)(`${date}T00:00:00`));
705
- const dayEnd = (0, import_localClock.localDateTimeToScalar)((0, import_localClock.parseLocalDateTime)(`${date}T23:59:59`));
687
+ if (!boundary) return [];
688
+ return dates.flatMap(date => {
689
+ const dayStart = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(`${date}T00:00:00`));
690
+ const dayEnd = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(`${date}T23:59:59`));
706
691
  const start = Math.max(boundary.startScalar, dayStart);
707
692
  const end = Math.min(boundary.endScalar, dayEnd);
708
- if (end <= start)
709
- return [];
693
+ if (end <= start) return [];
710
694
  return [{
711
- start_at: (0, import_localClock.formatLocalDateTime)(start, fixedOffsetMinutes),
712
- end_at: (0, import_localClock.formatLocalDateTime)(end, fixedOffsetMinutes),
695
+ start_at: (0, _localClock.formatLocalDateTime)(start, fixedOffsetMinutes),
696
+ end_at: (0, _localClock.formatLocalDateTime)(end, fixedOffsetMinutes),
713
697
  schedule_ids: scheduleIds,
714
- source: "resource_window_fallback"
698
+ source: 'resource_window_fallback'
715
699
  }];
716
700
  });
717
701
  }
702
+
703
+ /**
704
+ * Materializes resource work windows locally from v2's schedule ids, then keeps its flat
705
+ * event_list as resource occupancy records. This deliberately avoids the older API's times -> event_list
706
+ * response nesting and lets one resource response serve any requested date range.
707
+ */
718
708
  function buildAvailabilityResourcesFromV2(params) {
719
- const scheduleMap = new Map(
720
- (params.scheduleList || []).map((schedule) => [String(schedule.id), schedule])
721
- );
709
+ const scheduleMap = new Map((params.scheduleList || []).map(schedule => [String(schedule.id), schedule]));
722
710
  const dates = dateRangeDays(params.dateRange);
723
711
  const resourceOccupancies = [];
724
- const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, import_localClock.captureRuntimeOffsetMinutes)();
725
- const resources = (params.rawResources || []).map((raw) => {
712
+ const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, _localClock.captureRuntimeOffsetMinutes)();
713
+ const resources = (params.rawResources || []).map(raw => {
726
714
  const resource = normalizeResource(raw, fixedOffsetMinutes);
727
- if (!resource)
728
- return null;
715
+ if (!resource) return null;
729
716
  const explicitWindows = [...resource.windows];
730
717
  const scheduleIds = normalizeScheduleIds(raw);
731
- const schedules = scheduleIds.map((id) => scheduleMap.get(String(id))).filter(Boolean);
732
- const matchedScheduleIds = new Set(schedules.map((schedule) => String(schedule.id)));
733
- const missingScheduleIds = scheduleIds.filter((id) => !matchedScheduleIds.has(String(id)));
718
+ const schedules = scheduleIds.map(id => scheduleMap.get(String(id))).filter(Boolean);
719
+ const matchedScheduleIds = new Set(schedules.map(schedule => String(schedule.id)));
720
+ const missingScheduleIds = scheduleIds.filter(id => !matchedScheduleIds.has(String(id)));
734
721
  if (missingScheduleIds.length > 0) {
735
722
  resource.raw = {
736
- ...resource.raw || raw,
723
+ ...(resource.raw || raw),
737
724
  _availabilityMissingScheduleIds: missingScheduleIds
738
725
  };
739
726
  }
740
- const materializedWindows = dates.flatMap((date) => schedules.flatMap((schedule) => (0, import_getDateIsInSchedule.getScheduleStartEndTimePoints)(date, [schedule]).flatMap((slot) => {
727
+ const materializedWindows = dates.flatMap(date => schedules.flatMap(schedule => (0, _getDateIsInSchedule.getScheduleStartEndTimePoints)(date, [schedule]).flatMap(slot => {
741
728
  const range = normalizeAvailabilityLocalDateTimeRange({
742
729
  startAt: slot.start_at,
743
730
  endAt: slot.end_at,
744
731
  fixedOffsetMinutes,
745
732
  rollOverEnd: true
746
733
  });
747
- if (!range)
748
- return [];
734
+ if (!range) return [];
749
735
  return [{
750
736
  startAt: range.startAt,
751
737
  endAt: range.endAt,
752
738
  source: `resource_schedule:${schedule.id}`,
753
- raw: { scheduleId: schedule.id }
739
+ raw: {
740
+ scheduleId: schedule.id
741
+ }
754
742
  }];
755
743
  })));
756
744
  resource.windows = materializedWindows.length > 0 ? materializedWindows : explicitWindows;
@@ -760,7 +748,7 @@ function buildAvailabilityResourcesFromV2(params) {
760
748
  dates,
761
749
  scheduleIds,
762
750
  fixedOffsetMinutes
763
- }).map((window) => ({
751
+ }).map(window => ({
764
752
  startAt: window.start_at,
765
753
  endAt: window.end_at,
766
754
  source: window.source,
@@ -768,40 +756,35 @@ function buildAvailabilityResourcesFromV2(params) {
768
756
  }));
769
757
  }
770
758
  const eventList = Array.isArray(raw.event_list) ? raw.event_list : [];
771
- eventList.forEach((event) => {
772
- const occupancy = normalizeResourceOccupancy(event, resource.id, "remote", fixedOffsetMinutes);
773
- if (occupancy)
774
- resourceOccupancies.push(occupancy);
759
+ eventList.forEach(event => {
760
+ const occupancy = normalizeResourceOccupancy(event, resource.id, 'remote', fixedOffsetMinutes);
761
+ if (occupancy) resourceOccupancies.push(occupancy);
775
762
  });
776
763
  return resource;
777
- }).filter((resource) => resource !== null);
764
+ }).filter(resource => resource !== null);
778
765
  return {
779
766
  resources,
780
767
  resourceOccupancies
781
768
  };
782
769
  }
770
+
771
+ /** Combines URL-locked resources with every resource referenced by the selected products. */
783
772
  function collectAvailabilityResourceIds(products, explicitResourceIds = []) {
784
- const ids = /* @__PURE__ */ new Map();
785
- const add = (value) => {
786
- if (value === void 0 || value === null || value === "")
787
- return;
773
+ const ids = new Map();
774
+ const add = value => {
775
+ if (value === undefined || value === null || value === '') return;
788
776
  ids.set(String(value), value);
789
777
  };
790
778
  explicitResourceIds.forEach(add);
791
- products.forEach((product) => {
792
- var _a;
793
- (_a = product.requirementGroups) == null ? void 0 : _a.forEach((requirement) => {
794
- var _a2;
795
- (_a2 = requirement.resourceIds) == null ? void 0 : _a2.forEach(add);
779
+ products.forEach(product => {
780
+ product.requirementGroups?.forEach(requirement => {
781
+ requirement.resourceIds?.forEach(add);
796
782
  });
797
783
  });
798
784
  return Array.from(ids.values());
799
785
  }
800
786
  function getProductLineUid(product) {
801
- var _a;
802
- return String(
803
- ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.unique_identification_number) ?? (product == null ? void 0 : product.unique_identification_number) ?? ""
804
- );
787
+ return String(product?.metadata?.unique_identification_number ?? product?.unique_identification_number ?? '');
805
788
  }
806
789
  function buildAvailabilityLineIdentity(product) {
807
790
  return {
@@ -821,25 +804,22 @@ function buildBookingFromAvailabilityAssignment(params) {
821
804
  });
822
805
  }
823
806
  function buildBookingFromAvailabilityAssignments(params) {
824
- const normalizedAssignments = (params.assignments || []).map((assignment) => {
807
+ const normalizedAssignments = (params.assignments || []).map(assignment => {
825
808
  const resourceId = assignment.resourceId ?? assignment.resource_id;
826
- const matchedGroup = (params.product.requirementGroups || []).find((group) => {
827
- var _a;
828
- return (_a = group.resourceIds) == null ? void 0 : _a.some((id) => sameAvailabilityId(id, resourceId));
829
- });
809
+ const matchedGroup = (params.product.requirementGroups || []).find(group => group.resourceIds?.some(id => sameAvailabilityId(id, resourceId)));
830
810
  return {
831
811
  productId: assignment.productId ?? assignment.product_id,
832
812
  resourceId,
833
- formId: assignment.formId ?? assignment.form_id ?? (matchedGroup == null ? void 0 : matchedGroup.formId),
813
+ formId: assignment.formId ?? assignment.form_id ?? matchedGroup?.formId,
834
814
  startAt: assignment.startAt ?? assignment.start_at,
835
815
  endAt: assignment.endAt ?? assignment.end_at,
836
- capacityRequired: assignment.capacityRequired ?? assignment.capacity_required ?? (matchedGroup == null ? void 0 : matchedGroup.capacityRequired),
816
+ capacityRequired: assignment.capacityRequired ?? assignment.capacity_required ?? matchedGroup?.capacityRequired,
837
817
  scheduleId: assignment.scheduleId ?? assignment.schedule_id,
838
818
  timeSlotId: assignment.timeSlotId ?? assignment.time_slot_id
839
819
  };
840
820
  });
841
821
  const first = normalizedAssignments[0];
842
- const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, import_localClock.captureRuntimeOffsetMinutes)();
822
+ const fixedOffsetMinutes = params.fixedOffsetMinutes ?? (0, _localClock.captureRuntimeOffsetMinutes)();
843
823
  const range = normalizeAvailabilityLocalDateTimeRange({
844
824
  startAt: first.startAt,
845
825
  endAt: first.endAt,
@@ -847,24 +827,24 @@ function buildBookingFromAvailabilityAssignments(params) {
847
827
  rollOverEnd: false
848
828
  });
849
829
  if (!range) {
850
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "assignment 时间范围非法", {
830
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'assignment 时间范围非法', {
851
831
  assignments: params.assignments
852
832
  });
853
833
  }
854
834
  const candidate = {
855
835
  key: `${String(first.productId)}:${range.startAt}:${range.endAt}`,
856
836
  productId: first.productId,
857
- source: "duration_window",
837
+ source: 'duration_window',
858
838
  startAt: range.startAt,
859
839
  endAt: range.endAt,
860
840
  bookingStartAt: range.startAt,
861
841
  bookingEndAt: range.endAt,
862
842
  date: range.startAt.slice(0, 10),
863
- startTime: (0, import_localClock.formatLocalTime)(range.startAt, false),
864
- endTime: (0, import_localClock.formatLocalTime)(range.endAt, false),
865
- timezone: String(params.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone || "runtime"),
843
+ startTime: (0, _localClock.formatLocalTime)(range.startAt, false),
844
+ endTime: (0, _localClock.formatLocalTime)(range.endAt, false),
845
+ timezone: String(params.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone || 'runtime'),
866
846
  scheduleRefs: [],
867
- primaryScheduleRef: void 0
847
+ primaryScheduleRef: undefined
868
848
  };
869
849
  return buildBookingFromAvailabilitySelection({
870
850
  assignments: normalizedAssignments,
@@ -873,18 +853,13 @@ function buildBookingFromAvailabilityAssignments(params) {
873
853
  });
874
854
  }
875
855
  function getBookingUid(booking) {
876
- var _a;
877
- return String(
878
- ((_a = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a.unique_identification_number) ?? (booking == null ? void 0 : booking.booking_uid) ?? ""
879
- );
856
+ return String(booking?.metadata?.unique_identification_number ?? booking?.booking_uid ?? '');
880
857
  }
881
858
  function stableValue(value) {
882
- if (Array.isArray(value))
883
- return value.map(stableValue);
884
- if (!value || typeof value !== "object")
885
- return value;
859
+ if (Array.isArray(value)) return value.map(stableValue);
860
+ if (!value || typeof value !== 'object') return value;
886
861
  return Object.keys(value).sort().reduce((result, key) => {
887
- if (value[key] !== void 0 && typeof value[key] !== "function") {
862
+ if (value[key] !== undefined && typeof value[key] !== 'function') {
888
863
  result[key] = stableValue(value[key]);
889
864
  }
890
865
  return result;
@@ -899,21 +874,17 @@ function hashText(value) {
899
874
  return (hash >>> 0).toString(36);
900
875
  }
901
876
  function resolveOrderRevision(tempOrder) {
902
- if (!tempOrder)
903
- return "order:none";
904
- const products = (Array.isArray(tempOrder.products) ? tempOrder.products : []).map((product) => {
905
- var _a;
906
- return {
907
- uid: getProductLineUid(product),
908
- productId: product.product_id ?? product.id,
909
- variantId: product.product_variant_id ?? 0,
910
- num: product.num ?? product.quantity ?? 1,
911
- bookingUid: product.booking_uid ?? ((_a = product.metadata) == null ? void 0 : _a.booking_uid),
912
- productSku: product.product_sku,
913
- productBundle: product.product_bundle
914
- };
915
- }).sort((left, right) => left.uid.localeCompare(right.uid));
916
- const bookings = (Array.isArray(tempOrder.bookings) ? tempOrder.bookings : []).map((booking) => ({
877
+ if (!tempOrder) return 'order:none';
878
+ const products = (Array.isArray(tempOrder.products) ? tempOrder.products : []).map(product => ({
879
+ uid: getProductLineUid(product),
880
+ productId: product.product_id ?? product.id,
881
+ variantId: product.product_variant_id ?? 0,
882
+ num: product.num ?? product.quantity ?? 1,
883
+ bookingUid: product.booking_uid ?? product.metadata?.booking_uid,
884
+ productSku: product.product_sku,
885
+ productBundle: product.product_bundle
886
+ })).sort((left, right) => left.uid.localeCompare(right.uid));
887
+ const bookings = (Array.isArray(tempOrder.bookings) ? tempOrder.bookings : []).map(booking => ({
917
888
  uid: getBookingUid(booking),
918
889
  scheduleEventId: booking.schedule_event_id,
919
890
  productUid: booking.product_uid,
@@ -924,10 +895,12 @@ function resolveOrderRevision(tempOrder) {
924
895
  endTime: booking.end_time,
925
896
  resources: booking.resources
926
897
  })).sort((left, right) => left.uid.localeCompare(right.uid));
927
- return `order:${hashText(JSON.stringify(stableValue({ products, bookings })))}`;
898
+ return `order:${hashText(JSON.stringify(stableValue({
899
+ products,
900
+ bookings
901
+ })))}`;
928
902
  }
929
903
  function buildBookingFromAvailabilitySelection(params) {
930
- var _a, _b, _c, _d;
931
904
  const {
932
905
  assignments,
933
906
  candidate,
@@ -939,144 +912,147 @@ function buildBookingFromAvailabilitySelection(params) {
939
912
  } = params;
940
913
  const bookingStartAt = candidate.bookingStartAt || candidate.startAt;
941
914
  const bookingEndAt = candidate.bookingEndAt || candidate.endAt;
942
- const startScalar = (0, import_localClock.localDateTimeToScalar)((0, import_localClock.parseLocalDateTime)(bookingStartAt));
943
- const endScalar = (0, import_localClock.localDateTimeToScalar)((0, import_localClock.parseLocalDateTime)(bookingEndAt));
944
- const scheduleId = ((_a = candidate.primaryScheduleRef) == null ? void 0 : _a.scheduleId) ?? ((_b = assignments.find((assignment) => assignment.scheduleId != null)) == null ? void 0 : _b.scheduleId);
945
- const timeSlotId = ((_c = candidate.primaryScheduleRef) == null ? void 0 : _c.timeSlotId) ?? ((_d = assignments.find((assignment) => assignment.timeSlotId != null)) == null ? void 0 : _d.timeSlotId);
946
- if (product.kind === "session" && scheduleId == null) {
947
- throw new import_ResourcePlanner.AvailabilityError("REVALIDATION_FAILED", "session 候选缺少真实 schedule identity", {
915
+ const startScalar = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(bookingStartAt));
916
+ const endScalar = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(bookingEndAt));
917
+ const scheduleId = candidate.primaryScheduleRef?.scheduleId ?? assignments.find(assignment => assignment.scheduleId != null)?.scheduleId;
918
+ const timeSlotId = candidate.primaryScheduleRef?.timeSlotId ?? assignments.find(assignment => assignment.timeSlotId != null)?.timeSlotId;
919
+ if (product.kind === 'session' && scheduleId == null) {
920
+ throw new _ResourcePlanner.AvailabilityError('REVALIDATION_FAILED', 'session 候选缺少真实 schedule identity', {
948
921
  productId: product.id,
949
922
  candidateKey: candidate.key,
950
923
  scheduleRefs: candidate.scheduleRefs
951
924
  });
952
925
  }
953
- const normalizedHolder = holder && typeof holder === "object" ? (0, import_lodash_es.cloneDeep)(holder) : void 0;
954
- const normalizedHolderIds = Array.isArray(holderIds) ? (0, import_lodash_es.cloneDeep)(holderIds) : holderIds;
926
+ const normalizedHolder = holder && typeof holder === 'object' ? (0, _lodashEs.cloneDeep)(holder) : undefined;
927
+ const normalizedHolderIds = Array.isArray(holderIds) ? (0, _lodashEs.cloneDeep)(holderIds) : holderIds;
955
928
  return {
956
929
  start_date: bookingStartAt.slice(0, 10),
957
930
  start_time: bookingStartAt.slice(11, 16),
958
931
  end_date: bookingEndAt.slice(0, 10),
959
932
  end_time: bookingEndAt.slice(11, 16),
960
- duration: Math.max(1, Math.trunc((endScalar - startScalar) / (60 * 1e3))),
961
- like_status: "common",
933
+ duration: Math.max(1, Math.trunc((endScalar - startScalar) / (60 * 1000))),
934
+ like_status: 'common',
962
935
  schedule_id: scheduleId ?? 0,
963
- ...normalizedHolder ? { holder: normalizedHolder } : {},
964
- resources: assignments.map((assignment) => {
965
- const matchedResource = resources.find((resource) => sameAvailabilityId(resource.id, assignment.resourceId));
966
- const resourceName = String((matchedResource == null ? void 0 : matchedResource.name) || "").trim();
936
+ ...(normalizedHolder ? {
937
+ holder: normalizedHolder
938
+ } : {}),
939
+ resources: assignments.map(assignment => {
940
+ // requirementSelections 的提交协议只携带资源 ID;购物车展示则需要名称。
941
+ // commit 此时仍持有本次不可变 projection,因此直接按 ID 取回名称并
942
+ // 固化到 booking,避免 UI 再依赖 legacy BookingContext resourcesOriginMap。
943
+ const matchedResource = resources.find(resource => sameAvailabilityId(resource.id, assignment.resourceId));
944
+ const resourceName = String(matchedResource?.name || '').trim();
967
945
  return {
968
946
  id: assignment.resourceId,
969
947
  resource_id: assignment.resourceId,
970
948
  form_id: assignment.formId,
971
- relation_type: "form",
949
+ relation_type: 'form',
972
950
  relation_id: assignment.resourceId,
973
- like_status: "common",
951
+ like_status: 'common',
974
952
  capacity: assignment.capacityRequired || 1,
975
- ...resourceName ? { metadata: { resource_name: resourceName } } : {}
953
+ ...(resourceName ? {
954
+ metadata: {
955
+ resource_name: resourceName
956
+ }
957
+ } : {})
976
958
  };
977
959
  }),
978
960
  metadata: {
979
- ...bookingUid ? { unique_identification_number: bookingUid } : {},
961
+ ...(bookingUid ? {
962
+ unique_identification_number: bookingUid
963
+ } : {}),
980
964
  unified_booking_sales: true,
981
965
  availability_candidate_key: candidate.key,
982
966
  availability_source: candidate.source,
983
967
  availability_slice_start_at: candidate.startAt,
984
968
  availability_slice_end_at: candidate.endAt,
985
969
  availability_schedule_refs: candidate.scheduleRefs,
986
- ...timeSlotId == null ? {} : { time_slot_id: timeSlotId },
970
+ ...(timeSlotId == null ? {} : {
971
+ time_slot_id: timeSlotId
972
+ }),
987
973
  product_kind: product.kind,
988
- ...normalizedHolderIds === void 0 ? {} : { holder_id: normalizedHolderIds },
989
- ...normalizedHolder ? { holder: (0, import_lodash_es.cloneDeep)(normalizedHolder) } : {}
974
+ ...(normalizedHolderIds === undefined ? {} : {
975
+ holder_id: normalizedHolderIds
976
+ }),
977
+ ...(normalizedHolder ? {
978
+ holder: (0, _lodashEs.cloneDeep)(normalizedHolder)
979
+ } : {})
990
980
  }
991
981
  };
992
982
  }
993
- var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
994
- constructor() {
995
- super(...arguments);
996
- this.defaultName = "unifiedBookingSales";
997
- this.defaultVersion = "1.0.0";
998
- this.store = {};
999
- this.unifiedProductCatalog = [];
1000
- this.openDataTarget = null;
1001
- this.loadOpenDataInFlight = null;
1002
- this.loadOpenDataInFlightTarget = null;
1003
- this.availabilityRuntimeOffsetMinutes = null;
1004
- this.availabilityScheduleCatalog = null;
1005
- this.availabilityProjectionSequence = 0;
1006
- this.availabilityContextSequence = 0;
1007
- this.availabilityLifecycleGeneration = 0;
1008
- this.availabilityContextRegistry = /* @__PURE__ */ new Map();
1009
- this.availabilityProjectionPool = /* @__PURE__ */ new Map();
1010
- this.availabilityPrepareInFlight = /* @__PURE__ */ new Map();
1011
- this.availabilityProjectionRefreshInFlight = /* @__PURE__ */ new Map();
1012
- this.availabilityRemoteOccupancyCache = new import_remoteOccupancyCache.AvailabilityRemoteOccupancyCache(
1013
- MAX_REMOTE_OCCUPANCY_RESOURCE_DATE_CELLS
1014
- );
1015
- this.availabilityRemoteResourceQueryInFlight = /* @__PURE__ */ new Map();
1016
- this.availabilityRemoteResourceQuerySequence = 0;
1017
- this.availabilityRemoteResourceEpoch = 0;
1018
- this.availabilityCommitLocks = /* @__PURE__ */ new Set();
1019
- }
983
+ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
984
+ defaultName = 'unifiedBookingSales';
985
+ defaultVersion = '1.0.0';
986
+ store = {};
987
+ unifiedProductCatalog = [];
988
+ openDataTarget = null;
989
+ loadOpenDataInFlight = null;
990
+ loadOpenDataInFlightTarget = null;
991
+ availabilityRuntimeOffsetMinutes = null;
992
+ availabilityScheduleCatalog = null;
993
+ availabilityProjectionSequence = 0;
994
+ availabilityContextSequence = 0;
995
+ availabilityLifecycleGeneration = 0;
996
+ availabilityContextRegistry = new Map();
997
+ availabilityProjectionPool = new Map();
998
+ availabilityPrepareInFlight = new Map();
999
+ availabilityProjectionRefreshInFlight = new Map();
1000
+ availabilityRemoteOccupancyCache = new _remoteOccupancyCache.AvailabilityRemoteOccupancyCache(MAX_REMOTE_OCCUPANCY_RESOURCE_DATE_CELLS);
1001
+ availabilityRemoteResourceQueryInFlight = new Map();
1002
+ availabilityRemoteResourceQuerySequence = 0;
1003
+ availabilityRemoteResourceEpoch = 0;
1004
+ availabilityCommitLocks = new Set();
1020
1005
  async initialize(core, options = {}) {
1021
- var _a, _b, _c, _d;
1022
1006
  this.availabilityScheduleCatalog = null;
1023
1007
  this.openDataTarget = null;
1024
- this.availabilityRuntimeOffsetMinutes = (0, import_localClock.captureRuntimeOffsetMinutes)();
1008
+ this.availabilityRuntimeOffsetMinutes = (0, _localClock.captureRuntimeOffsetMinutes)();
1025
1009
  this.clearAvailabilityRemoteResourceState();
1026
1010
  await super.initialize(core, options);
1027
- const openDataBusinessCode = String(
1028
- ((_a = this.otherParams) == null ? void 0 : _a.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.business_code) ?? ""
1029
- ).trim();
1030
- const openDataChannel = String(((_c = this.otherParams) == null ? void 0 : _c.channel) ?? "").trim();
1031
- if (((_d = this.otherParams) == null ? void 0 : _d.openData) && openDataBusinessCode && openDataChannel) {
1011
+ const openDataBusinessCode = String(this.otherParams?.businessCode ?? this.otherParams?.business_code ?? '').trim();
1012
+ const openDataChannel = String(this.otherParams?.channel ?? '').trim();
1013
+ if (this.otherParams?.openData && openDataBusinessCode && openDataChannel) {
1032
1014
  this.openDataTarget = `${openDataBusinessCode}+${openDataChannel}`;
1033
1015
  }
1034
1016
  this.captureAvailabilityScheduleCatalog();
1035
1017
  }
1036
1018
  getSubmitOrderSalesChannel() {
1037
- var _a;
1038
- const channel = String(((_a = this.otherParams) == null ? void 0 : _a.channel) ?? "").trim();
1019
+ const channel = String(this.otherParams?.channel ?? '').trim();
1039
1020
  return channel || super.getSubmitOrderSalesChannel();
1040
1021
  }
1041
1022
  createAvailabilityFacadeError(code, message, details) {
1042
- return new import_ResourcePlanner.AvailabilityError(code, message, details);
1023
+ return new _ResourcePlanner.AvailabilityError(code, message, details);
1043
1024
  }
1044
1025
  getAvailabilityScopeDescriptor(otherParams = this.otherParams || {}) {
1045
1026
  return {
1046
- cacheId: this.cacheId || "",
1047
- businessCode: String(otherParams.businessCode ?? otherParams.business_code ?? ""),
1048
- channel: String(otherParams.channel ?? ""),
1049
- platform: String(otherParams.platform ?? ""),
1050
- businessTimezone: String(otherParams.businessTimezone ?? "")
1027
+ cacheId: this.cacheId || '',
1028
+ businessCode: String(otherParams.businessCode ?? otherParams.business_code ?? ''),
1029
+ channel: String(otherParams.channel ?? ''),
1030
+ platform: String(otherParams.platform ?? ''),
1031
+ businessTimezone: String(otherParams.businessTimezone ?? '')
1051
1032
  };
1052
1033
  }
1053
1034
  normalizeAvailabilityIdList(values) {
1054
- if (!Array.isArray(values) || values.length === 0)
1055
- return void 0;
1056
- const uniqueMap = /* @__PURE__ */ new Map();
1057
- values.forEach((value) => {
1035
+ if (!Array.isArray(values) || values.length === 0) return undefined;
1036
+ const uniqueMap = new Map();
1037
+ values.forEach(value => {
1058
1038
  uniqueMap.set(String(value), value);
1059
1039
  });
1060
1040
  return Array.from(uniqueMap.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([, value]) => value);
1061
1041
  }
1062
1042
  normalizeAvailabilityStringList(values) {
1063
- if (!Array.isArray(values) || values.length === 0)
1064
- return void 0;
1043
+ if (!Array.isArray(values) || values.length === 0) return undefined;
1065
1044
  return Array.from(new Set(values.map(String))).sort((left, right) => left.localeCompare(right));
1066
1045
  }
1067
1046
  normalizeAvailabilityPrepareDescriptor(params) {
1068
- var _a;
1069
1047
  this.assertAvailabilityPrepareParams(params);
1070
- const timezone = String(
1071
- params.timezone || ((_a = this.otherParams) == null ? void 0 : _a.businessTimezone) || Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai"
1072
- );
1048
+ const timezone = String(params.timezone || this.otherParams?.businessTimezone || Intl.DateTimeFormat().resolvedOptions().timeZone || 'Asia/Shanghai');
1073
1049
  assertValidAvailabilityTimezone(timezone);
1074
1050
  const dateRange = this.normalizeAvailabilityDateRange(params, timezone);
1075
1051
  const slotStepMinutes = params.slotStepMinutes || DEFAULT_AVAILABILITY_SLOT_STEP_MINUTES;
1076
1052
  const businessHours = params.businessHours || DEFAULT_AVAILABILITY_BUSINESS_HOURS;
1077
- const mode = params.mode || "appointment";
1053
+ const mode = params.mode || 'appointment';
1078
1054
  if (!isValidClockTime(businessHours.startTime) || !isValidClockTime(businessHours.endTime)) {
1079
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "businessHours 必须使用 HH:mm", {
1055
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'businessHours 必须使用 HH:mm', {
1080
1056
  businessHours
1081
1057
  });
1082
1058
  }
@@ -1088,63 +1064,58 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1088
1064
  dateRange,
1089
1065
  timezone,
1090
1066
  slotStepMinutes,
1091
- businessHours: { ...businessHours },
1067
+ businessHours: {
1068
+ ...businessHours
1069
+ },
1092
1070
  _availabilityOperatingHours: params._availabilityOperatingHours ? {
1093
1071
  source: params._availabilityOperatingHours.source,
1094
1072
  scheduleIds: [...params._availabilityOperatingHours.scheduleIds]
1095
- } : void 0,
1073
+ } : undefined,
1096
1074
  mode
1097
1075
  });
1098
1076
  }
1099
1077
  async resolveAvailabilityPrepareDefaults(params) {
1100
- var _a, _b, _c, _d;
1101
- const needsOperatingHours = params.businessHours === void 0;
1102
- const needsTimeSlice = params.slotStepMinutes === void 0;
1078
+ const needsOperatingHours = params.businessHours === undefined;
1079
+ const needsTimeSlice = params.slotStepMinutes === undefined;
1103
1080
  if (!needsOperatingHours && !needsTimeSlice) {
1104
1081
  return {
1105
1082
  ...params,
1106
1083
  _availabilityOperatingHours: {
1107
- source: "prepare_business_hours",
1084
+ source: 'prepare_business_hours',
1108
1085
  scheduleIds: []
1109
1086
  }
1110
1087
  };
1111
1088
  }
1112
- const businessCode = String(
1113
- ((_a = this.otherParams) == null ? void 0 : _a.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.business_code) ?? ""
1114
- ).trim();
1115
- const channel = String(((_c = this.otherParams) == null ? void 0 : _c.channel) ?? "").trim();
1089
+ const businessCode = String(this.otherParams?.businessCode ?? this.otherParams?.business_code ?? '').trim();
1090
+ const channel = String(this.otherParams?.channel ?? '').trim();
1116
1091
  const currentTarget = businessCode && channel ? `${businessCode}+${channel}` : null;
1117
- let openData = !currentTarget || this.openDataTarget === currentTarget ? (_d = this.otherParams) == null ? void 0 : _d.openData : null;
1092
+ let openData = !currentTarget || this.openDataTarget === currentTarget ? this.otherParams?.openData : null;
1118
1093
  if (!openData && this.store.openData) {
1119
1094
  try {
1120
1095
  openData = await this.getOpenData();
1121
1096
  } catch (error) {
1122
1097
  if (needsOperatingHours) {
1123
- throw this.createAvailabilityFacadeError(
1124
- "OPERATING_HOURS_RESOLVE_FAILED",
1125
- "无法读取店铺营业时间配置,请重试",
1126
- {
1127
- businessCode,
1128
- channel,
1129
- cause: error instanceof Error ? error.message : String(error)
1130
- }
1131
- );
1098
+ throw this.createAvailabilityFacadeError('OPERATING_HOURS_RESOLVE_FAILED', '无法读取店铺营业时间配置,请重试', {
1099
+ businessCode,
1100
+ channel,
1101
+ cause: error instanceof Error ? error.message : String(error)
1102
+ });
1132
1103
  }
1133
- console.warn("[UnifiedBookingSales] OpenData 时间切片配置加载失败,回退为默认值", error);
1104
+ console.warn('[UnifiedBookingSales] OpenData 时间切片配置加载失败,回退为默认值', error);
1134
1105
  }
1135
1106
  }
1136
- const operatingScheduleIds = this.normalizeAvailabilityIdList(
1137
- Array.isArray(openData == null ? void 0 : openData["availability.operating_hours"]) ? openData == null ? void 0 : openData["availability.operating_hours"] : void 0
1138
- ) || [];
1139
- const configuredTimeSlice = needsTimeSlice ? normalizePositiveInteger(openData == null ? void 0 : openData["reservation.time_slice"]) : void 0;
1107
+ const operatingScheduleIds = this.normalizeAvailabilityIdList(Array.isArray(openData?.['availability.operating_hours']) ? openData?.['availability.operating_hours'] : undefined) || [];
1108
+ const configuredTimeSlice = needsTimeSlice ? normalizePositiveInteger(openData?.['reservation.time_slice']) : undefined;
1140
1109
  return {
1141
1110
  ...params,
1142
- ...configuredTimeSlice ? { slotStepMinutes: configuredTimeSlice } : {},
1111
+ ...(configuredTimeSlice ? {
1112
+ slotStepMinutes: configuredTimeSlice
1113
+ } : {}),
1143
1114
  _availabilityOperatingHours: needsOperatingHours ? {
1144
- source: operatingScheduleIds.length > 0 ? "open_data_schedule" : "default_business_hours",
1115
+ source: operatingScheduleIds.length > 0 ? 'open_data_schedule' : 'default_business_hours',
1145
1116
  scheduleIds: operatingScheduleIds
1146
1117
  } : {
1147
- source: "prepare_business_hours",
1118
+ source: 'prepare_business_hours',
1148
1119
  scheduleIds: []
1149
1120
  }
1150
1121
  };
@@ -1176,24 +1147,27 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1176
1147
  resourceIds: this.normalizeAvailabilityIdList(params.resourceIds) || []
1177
1148
  }));
1178
1149
  }
1179
- async setOtherParams(params, { cover = false } = {}) {
1180
- var _a;
1150
+ async setOtherParams(params, {
1151
+ cover = false
1152
+ } = {}) {
1181
1153
  const previousScope = this.getAvailabilityScopeDescriptor(this.otherParams || {});
1182
- const explicitlySetsOpenData = Object.prototype.hasOwnProperty.call(params, "openData");
1183
- await super.setOtherParams(params, { cover });
1154
+ const explicitlySetsOpenData = Object.prototype.hasOwnProperty.call(params, 'openData');
1155
+ await super.setOtherParams(params, {
1156
+ cover
1157
+ });
1184
1158
  const nextScope = this.getAvailabilityScopeDescriptor(this.otherParams || {});
1185
1159
  if (explicitlySetsOpenData) {
1186
- this.openDataTarget = ((_a = this.otherParams) == null ? void 0 : _a.openData) && nextScope.businessCode && nextScope.channel ? `${nextScope.businessCode}+${nextScope.channel}` : null;
1160
+ this.openDataTarget = this.otherParams?.openData && nextScope.businessCode && nextScope.channel ? `${nextScope.businessCode}+${nextScope.channel}` : null;
1187
1161
  }
1188
1162
  const shouldResetAvailabilityState = previousScope.cacheId !== nextScope.cacheId || previousScope.businessCode !== nextScope.businessCode || previousScope.channel !== nextScope.channel || previousScope.platform !== nextScope.platform || previousScope.businessTimezone !== nextScope.businessTimezone;
1189
1163
  if (shouldResetAvailabilityState) {
1190
- await this.resetAvailabilityProjectionState("set_other_params_reset");
1164
+ await this.resetAvailabilityProjectionState('set_other_params_reset');
1191
1165
  }
1192
1166
  }
1193
1167
  async destroy() {
1194
1168
  this.availabilityScheduleCatalog = null;
1195
1169
  this.availabilityRuntimeOffsetMinutes = null;
1196
- await this.resetAvailabilityProjectionState("destroy");
1170
+ await this.resetAvailabilityProjectionState('destroy');
1197
1171
  await super.destroy();
1198
1172
  }
1199
1173
  createAvailabilityContextId() {
@@ -1205,35 +1179,45 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1205
1179
  }
1206
1180
  getAvailabilityRuntimeOffsetMinutes() {
1207
1181
  if (this.availabilityRuntimeOffsetMinutes === null) {
1208
- this.availabilityRuntimeOffsetMinutes = (0, import_localClock.captureRuntimeOffsetMinutes)();
1182
+ this.availabilityRuntimeOffsetMinutes = (0, _localClock.captureRuntimeOffsetMinutes)();
1209
1183
  }
1210
1184
  return this.availabilityRuntimeOffsetMinutes;
1211
1185
  }
1212
- getAvailabilityRuntimeDateTime(value = /* @__PURE__ */ new Date()) {
1213
- return (0, import_localClock.formatLocalDateTime)((0, import_localClock.localDateToScalar)(value), this.getAvailabilityRuntimeOffsetMinutes());
1186
+ getAvailabilityRuntimeDateTime(value = new Date()) {
1187
+ return (0, _localClock.formatLocalDateTime)((0, _localClock.localDateToScalar)(value), this.getAvailabilityRuntimeOffsetMinutes());
1214
1188
  }
1215
1189
  cloneAvailabilityPrepareParams(params) {
1216
- var _a, _b;
1217
- return (0, import_lodash_es.cloneDeep)({
1190
+ return (0, _lodashEs.cloneDeep)({
1218
1191
  ...params,
1219
- productIds: params.productIds ? [...params.productIds] : void 0,
1220
- resourceIds: params.resourceIds ? [...params.resourceIds] : void 0,
1221
- rawProducts: params.rawProducts ? (0, import_lodash_es.cloneDeep)(params.rawProducts) : void 0,
1222
- rawResources: params.rawResources ? (0, import_lodash_es.cloneDeep)(params.rawResources) : void 0,
1223
- rawOccupancies: params.rawOccupancies ? (0, import_lodash_es.cloneDeep)(params.rawOccupancies) : void 0,
1224
- editingProductLineUids: params.editingProductLineUids ? [...params.editingProductLineUids] : void 0,
1225
- dateRange: params.dateRange ? { ...params.dateRange } : void 0,
1226
- businessHours: params.businessHours ? { ...params.businessHours } : void 0,
1192
+ productIds: params.productIds ? [...params.productIds] : undefined,
1193
+ resourceIds: params.resourceIds ? [...params.resourceIds] : undefined,
1194
+ rawProducts: params.rawProducts ? (0, _lodashEs.cloneDeep)(params.rawProducts) : undefined,
1195
+ rawResources: params.rawResources ? (0, _lodashEs.cloneDeep)(params.rawResources) : undefined,
1196
+ rawOccupancies: params.rawOccupancies ? (0, _lodashEs.cloneDeep)(params.rawOccupancies) : undefined,
1197
+ editingProductLineUids: params.editingProductLineUids ? [...params.editingProductLineUids] : undefined,
1198
+ dateRange: params.dateRange ? {
1199
+ ...params.dateRange
1200
+ } : undefined,
1201
+ businessHours: params.businessHours ? {
1202
+ ...params.businessHours
1203
+ } : undefined,
1227
1204
  _availabilityOperatingHours: params._availabilityOperatingHours ? {
1228
1205
  source: params._availabilityOperatingHours.source,
1229
1206
  scheduleIds: [...params._availabilityOperatingHours.scheduleIds]
1230
- } : void 0,
1231
- catalogScope: ((_a = params.catalogScope) == null ? void 0 : _a.type) === "schedule" ? { ...params.catalogScope } : ((_b = params.catalogScope) == null ? void 0 : _b.type) === "productList" ? { type: "productList", params: { ...params.catalogScope.params } } : void 0
1207
+ } : undefined,
1208
+ catalogScope: params.catalogScope?.type === 'schedule' ? {
1209
+ ...params.catalogScope
1210
+ } : params.catalogScope?.type === 'productList' ? {
1211
+ type: 'productList',
1212
+ params: {
1213
+ ...params.catalogScope.params
1214
+ }
1215
+ } : undefined
1232
1216
  });
1233
1217
  }
1234
1218
  getAvailabilityDurationCandidateAnchorAt(projection) {
1235
- const value = projection == null ? void 0 : projection.meta.durationCandidateAnchorAt;
1236
- return typeof value === "string" && value.trim() ? value : void 0;
1219
+ const value = projection?.meta.durationCandidateAnchorAt;
1220
+ return typeof value === 'string' && value.trim() ? value : undefined;
1237
1221
  }
1238
1222
  createAvailabilityContextRef(context) {
1239
1223
  return {
@@ -1241,19 +1225,14 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1241
1225
  };
1242
1226
  }
1243
1227
  async emitAvailabilityDiagnostic(payload) {
1244
- var _a, _b, _c;
1245
- await ((_c = (_b = (_a = this.core) == null ? void 0 : _a.effects) == null ? void 0 : _b.emit) == null ? void 0 : _c.call(
1246
- _b,
1247
- `${this.name}:${import_types.UnifiedBookingSalesHooks.onAvailabilityProjectionDiagnostic}`,
1248
- {
1249
- ...payload,
1250
- registrySize: this.availabilityContextRegistry.size,
1251
- projectionPoolSize: this.availabilityProjectionPool.size
1252
- }
1253
- ));
1228
+ await this.core?.effects?.emit?.(`${this.name}:${_types.UnifiedBookingSalesHooks.onAvailabilityProjectionDiagnostic}`, {
1229
+ ...payload,
1230
+ registrySize: this.availabilityContextRegistry.size,
1231
+ projectionPoolSize: this.availabilityProjectionPool.size
1232
+ });
1254
1233
  }
1255
1234
  touchAvailabilityContext(context) {
1256
- context.lastAccessedAt = (/* @__PURE__ */ new Date()).toISOString();
1235
+ context.lastAccessedAt = new Date().toISOString();
1257
1236
  this.availabilityContextRegistry.delete(context.contextId);
1258
1237
  this.availabilityContextRegistry.set(context.contextId, context);
1259
1238
  }
@@ -1263,14 +1242,12 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1263
1242
  return entry;
1264
1243
  }
1265
1244
  removeAvailabilityProjection(projectionKey) {
1266
- if (!projectionKey)
1267
- return;
1245
+ if (!projectionKey) return;
1268
1246
  this.availabilityProjectionPool.delete(projectionKey);
1269
1247
  }
1270
1248
  removeAvailabilityContext(contextId) {
1271
1249
  const context = this.availabilityContextRegistry.get(contextId);
1272
- if (!context)
1273
- return;
1250
+ if (!context) return;
1274
1251
  this.removeAvailabilityProjection(context.activeProjectionKey);
1275
1252
  this.availabilityProjectionRefreshInFlight.delete(contextId);
1276
1253
  this.availabilityCommitLocks.delete(contextId);
@@ -1279,12 +1256,11 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1279
1256
  evictAvailabilityProjectionPool() {
1280
1257
  while (this.availabilityProjectionPool.size > MAX_AVAILABILITY_PROJECTION_POOL) {
1281
1258
  const oldestEntry = this.availabilityProjectionPool.entries().next().value;
1282
- if (!oldestEntry)
1283
- break;
1259
+ if (!oldestEntry) break;
1284
1260
  const [projectionKey, projectionEntry] = oldestEntry;
1285
1261
  this.availabilityProjectionPool.delete(projectionKey);
1286
1262
  const context = this.availabilityContextRegistry.get(projectionEntry.contextId);
1287
- if ((context == null ? void 0 : context.activeProjectionKey) === projectionKey) {
1263
+ if (context?.activeProjectionKey === projectionKey) {
1288
1264
  context.activeProjectionKey = null;
1289
1265
  context.refreshNonce += 1;
1290
1266
  }
@@ -1293,8 +1269,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1293
1269
  evictAvailabilityContextRegistry() {
1294
1270
  while (this.availabilityContextRegistry.size > MAX_AVAILABILITY_CONTEXT_REGISTRY) {
1295
1271
  const oldestContext = this.availabilityContextRegistry.entries().next().value;
1296
- if (!oldestContext)
1297
- break;
1272
+ if (!oldestContext) break;
1298
1273
  this.removeAvailabilityContext(oldestContext[0]);
1299
1274
  }
1300
1275
  }
@@ -1304,7 +1279,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1304
1279
  this.availabilityProjectionPool.clear();
1305
1280
  this.availabilityPrepareInFlight.clear();
1306
1281
  this.availabilityProjectionRefreshInFlight.clear();
1307
- this.availabilityContextRegistry.forEach((context) => {
1282
+ this.availabilityContextRegistry.forEach(context => {
1308
1283
  context.activeVersion += 1;
1309
1284
  context.activeProjectionKey = null;
1310
1285
  context.lastKnownOrderRevision = nextOrderRevision;
@@ -1329,40 +1304,39 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1329
1304
  });
1330
1305
  }
1331
1306
  isSessionStoragePersistEnabled() {
1332
- var _a;
1333
- return Boolean(
1334
- this.cacheId && ((_a = this.otherParams) == null ? void 0 : _a.enableSessionStoragePersist) === true
1335
- );
1307
+ return Boolean(this.cacheId && this.otherParams?.enableSessionStoragePersist === true);
1336
1308
  }
1337
1309
  shouldUseSessionStorageForSubModule(moduleName) {
1338
- return this.isSessionStoragePersistEnabled() && moduleName === "order";
1310
+ return this.isSessionStoragePersistEnabled() && moduleName === 'order';
1339
1311
  }
1312
+
1340
1313
  /**
1341
1314
  * 读取与当前 cacheId 同分桶的 Solution 会话状态。
1342
1315
  * 该状态独立于 otherParams,适合页面皮肤保存短生命周期 UI 状态。
1343
1316
  */
1344
1317
  getSessionStateValue(key) {
1345
- if (!key || !this.isSessionStoragePersistEnabled())
1346
- return void 0;
1318
+ if (!key || !this.isSessionStoragePersistEnabled()) return undefined;
1347
1319
  const cacheData = this.readSessionCacheData();
1348
- const solutionCache = cacheData == null ? void 0 : cacheData[this.name];
1320
+ const solutionCache = cacheData?.[this.name];
1349
1321
  if (!isRecord(solutionCache) || !isRecord(solutionCache.sessionState)) {
1350
- return void 0;
1322
+ return undefined;
1351
1323
  }
1352
1324
  return solutionCache.sessionState[key];
1353
1325
  }
1326
+
1354
1327
  /**
1355
1328
  * 写入与当前 cacheId 同分桶的 Solution 会话状态。
1356
1329
  * value 为 undefined 时删除该 key;存储失败不阻断业务流程。
1357
1330
  */
1358
1331
  setSessionStateValue(key, value) {
1359
- if (!key || !this.isSessionStoragePersistEnabled())
1360
- return;
1332
+ if (!key || !this.isSessionStoragePersistEnabled()) return;
1361
1333
  const cacheData = this.readSessionCacheData();
1362
- const solutionCache = cacheData == null ? void 0 : cacheData[this.name];
1334
+ const solutionCache = cacheData?.[this.name];
1363
1335
  const currentSessionState = isRecord(solutionCache) && isRecord(solutionCache.sessionState) ? solutionCache.sessionState : {};
1364
- const nextSessionState = { ...currentSessionState };
1365
- if (value === void 0) {
1336
+ const nextSessionState = {
1337
+ ...currentSessionState
1338
+ };
1339
+ if (value === undefined) {
1366
1340
  delete nextSessionState[key];
1367
1341
  } else {
1368
1342
  nextSessionState[key] = value;
@@ -1370,52 +1344,54 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1370
1344
  this.checkSaveCache({
1371
1345
  cacheId: this.cacheId,
1372
1346
  fatherModule: this.name,
1373
- store: { sessionState: nextSessionState },
1374
- cacheKey: ["sessionState"]
1347
+ store: {
1348
+ sessionState: nextSessionState
1349
+ },
1350
+ cacheKey: ['sessionState']
1375
1351
  });
1376
1352
  }
1353
+
1377
1354
  /**
1378
1355
  * 清除当前 cacheId 的可恢复订单快照,同时保留 Solution UI sessionState。
1379
1356
  * 用于支付跳转等终态场景,避免浏览器返回时恢复已提交订单。
1380
1357
  */
1381
1358
  clearSessionStorageOrderSnapshot() {
1382
- var _a, _b;
1383
- (_b = (_a = this.store.order) == null ? void 0 : _a.clearSessionStoragePersistedTempOrder) == null ? void 0 : _b.call(_a);
1359
+ this.store.order?.clearSessionStoragePersistedTempOrder?.();
1384
1360
  }
1361
+
1385
1362
  /**
1386
1363
  * Kiosk 不能把已收款订单留在本地等待重试:默认直接等待云端 checkout。
1387
1364
  * 兼容仍需要 WebPOS 待同步模式的入口可显式传 checkoutSyncTaskEnabled: true。
1388
1365
  */
1389
1366
  shouldUseCheckoutSyncTask() {
1390
- var _a;
1391
- const configured = (_a = this.otherParams) == null ? void 0 : _a.checkoutSyncTaskEnabled;
1392
- return typeof configured === "boolean" ? configured : false;
1367
+ const configured = this.otherParams?.checkoutSyncTaskEnabled;
1368
+ return typeof configured === 'boolean' ? configured : false;
1393
1369
  }
1370
+
1394
1371
  /** UnifiedBookingSales 的真实结账默认请求收据数据,供云端确认后再本地打印。 */
1395
1372
  getDefaultCheckoutSmallTicketDataFlag() {
1396
1373
  return 1;
1397
1374
  }
1398
1375
  getRegisteredModuleNames() {
1399
- return [...super.getRegisteredModuleNames(), "openData"];
1376
+ return [...super.getRegisteredModuleNames(), 'openData'];
1400
1377
  }
1401
1378
  createSubModule(moduleName) {
1402
- if (moduleName === "openData") {
1403
- return new import_modules.OpenDataModule(`${this.name}_openData`);
1379
+ if (moduleName === 'openData') {
1380
+ return new _modules.OpenDataModule(`${this.name}_openData`);
1404
1381
  }
1405
1382
  return super.createSubModule(moduleName);
1406
1383
  }
1407
1384
  async addNewOrder() {
1408
- var _a, _b, _c, _d;
1409
- const sessionRecord = this.isSessionStoragePersistEnabled() ? (_b = (_a = this.store.order) == null ? void 0 : _a.consumeSessionStorageRestore) == null ? void 0 : _b.call(_a) : null;
1385
+ const sessionRecord = this.isSessionStoragePersistEnabled() ? this.store.order?.consumeSessionStorageRestore?.() : null;
1410
1386
  if (sessionRecord) {
1411
1387
  await this.loadSalesDetail({
1412
1388
  preloadedSalesDetail: sessionRecord,
1413
- hydrateSource: "sessionStorage"
1389
+ hydrateSource: 'sessionStorage'
1414
1390
  });
1415
1391
  }
1416
1392
  const tempOrder = await super.addNewOrder();
1417
1393
  if (sessionRecord) {
1418
- (_c = this.store.order) == null ? void 0 : _c.persistTempOrder();
1394
+ this.store.order?.persistTempOrder();
1419
1395
  }
1420
1396
  if (this.isAuthenticatedCustomerUserPlatform()) {
1421
1397
  try {
@@ -1424,102 +1400,82 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1424
1400
  await this.refreshLegacySessionCustomerDiscounts(tempOrder);
1425
1401
  }
1426
1402
  } catch (error) {
1427
- console.warn(
1428
- "[UnifiedBookingSales] Failed to sync authenticated order customer after addNewOrder",
1429
- error
1430
- );
1403
+ console.warn('[UnifiedBookingSales] Failed to sync authenticated order customer after addNewOrder', error);
1431
1404
  }
1432
1405
  } else if (sessionRecord) {
1433
1406
  try {
1434
1407
  await this.refreshLegacySessionCustomerDiscounts(tempOrder);
1435
1408
  } catch (error) {
1436
- console.warn(
1437
- "[UnifiedBookingSales] Failed to refresh cached customer discounts after addNewOrder",
1438
- error
1439
- );
1409
+ console.warn('[UnifiedBookingSales] Failed to refresh cached customer discounts after addNewOrder', error);
1440
1410
  }
1441
1411
  }
1442
- return ((_d = this.store.order) == null ? void 0 : _d.getTempOrder()) || tempOrder;
1412
+ return this.store.order?.getTempOrder() || tempOrder;
1443
1413
  }
1444
1414
  async syncAuthenticatedOrderCustomer() {
1445
- var _a, _b, _c, _d, _e, _f;
1446
- if (!this.isAuthenticatedCustomerUserPlatform())
1447
- return false;
1448
- const authenticatedCustomer = (_d = (_c = (_b = (_a = this.core) == null ? void 0 : _a.getPlugin) == null ? void 0 : _b.call(_a, "user")) == null ? void 0 : _c.get) == null ? void 0 : _d.call(_c);
1449
- const authenticatedCustomerId = toCustomerId(authenticatedCustomer == null ? void 0 : authenticatedCustomer.id);
1450
- if (!authenticatedCustomerId)
1451
- return false;
1415
+ if (!this.isAuthenticatedCustomerUserPlatform()) return false;
1416
+ const authenticatedCustomer = this.core?.getPlugin?.('user')?.get?.();
1417
+ const authenticatedCustomerId = toCustomerId(authenticatedCustomer?.id);
1418
+ if (!authenticatedCustomerId) return false;
1452
1419
  const tempOrder = this.getTempOrder();
1453
1420
  const cachedCustomerId = resolveTempOrderCustomerId(tempOrder);
1454
1421
  if (cachedCustomerId !== null && cachedCustomerId !== authenticatedCustomerId) {
1455
1422
  await this.resetCachedCustomerDiscountState();
1456
1423
  }
1457
- (_f = (_e = this.store.customer) == null ? void 0 : _e.setSelectedCustomer) == null ? void 0 : _f.call(_e, authenticatedCustomer);
1424
+ this.store.customer?.setSelectedCustomer?.(authenticatedCustomer);
1458
1425
  this.setOrderCustomer(authenticatedCustomer);
1459
- await Promise.all([
1460
- this.refreshDiscountConfigAfterOrderCustomerChange(authenticatedCustomerId),
1461
- this.waitForOrderCustomerPromotionRefresh()
1462
- ]);
1426
+ await Promise.all([this.refreshDiscountConfigAfterOrderCustomerChange(authenticatedCustomerId), this.waitForOrderCustomerPromotionRefresh()]);
1463
1427
  return true;
1464
1428
  }
1465
1429
  isAuthenticatedCustomerUserPlatform() {
1466
- var _a;
1467
- const platform = String(((_a = this.otherParams) == null ? void 0 : _a.platform) || "").toLowerCase();
1468
- return platform === "pc" || platform === "h5";
1430
+ const platform = String(this.otherParams?.platform || '').toLowerCase();
1431
+ return platform === 'pc' || platform === 'h5';
1469
1432
  }
1470
1433
  resolveDiscountOrderIdentity(tempOrder) {
1471
- var _a, _b, _c;
1472
- return (tempOrder == null ? void 0 : tempOrder.order_id) || ((_c = (_b = (_a = this.store.order) == null ? void 0 : _a.getOrderIdentity) == null ? void 0 : _b.call(_a)) == null ? void 0 : _c.orderId) || null;
1434
+ return tempOrder?.order_id || this.store.order?.getOrderIdentity?.()?.orderId || null;
1473
1435
  }
1474
1436
  resolveDiscountAction(orderId) {
1475
- if (!orderId || isLocalOrderId(orderId))
1476
- return "create";
1477
- return "edit";
1437
+ if (!orderId || isLocalOrderId(orderId)) return 'create';
1438
+ return 'edit';
1478
1439
  }
1479
1440
  async resetCachedCustomerDiscountState() {
1480
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
1481
- (_b = (_a = this.store.order) == null ? void 0 : _a.clearOrderCustomer) == null ? void 0 : _b.call(_a);
1482
- (_d = (_c = this.store.customer) == null ? void 0 : _c.setSelectedCustomer) == null ? void 0 : _d.call(_c, null);
1441
+ this.store.order?.clearOrderCustomer?.();
1442
+ this.store.customer?.setSelectedCustomer?.(null);
1483
1443
  this.discountConfigCacheKey = null;
1484
1444
  this.hasManualDiscountSelection = false;
1485
- const orderStore = ((_e = this.store.order) == null ? void 0 : _e.store) || {};
1445
+ const orderStore = this.store.order?.store || {};
1486
1446
  const discountModule = orderStore.discount;
1487
- const filteredOriginalDiscounts = filterCustomerBoundDiscounts(
1488
- ((_f = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _f.call(discountModule)) || []
1489
- );
1490
- const filteredCurrentDiscounts = filterCustomerBoundDiscounts(
1491
- ((_g = discountModule == null ? void 0 : discountModule.getDiscountList) == null ? void 0 : _g.call(discountModule)) || []
1492
- );
1493
- await ((_h = discountModule == null ? void 0 : discountModule.setOriginalDiscountList) == null ? void 0 : _h.call(discountModule, filteredOriginalDiscounts));
1494
- await ((_i = discountModule == null ? void 0 : discountModule.setDiscountList) == null ? void 0 : _i.call(discountModule, filteredCurrentDiscounts));
1495
- (_k = (_j = this.store.order) == null ? void 0 : _j.applyDiscount) == null ? void 0 : _k.call(_j);
1496
- await ((_m = (_l = this.store.order) == null ? void 0 : _l.recalculateSummary) == null ? void 0 : _m.call(_l, { createIfMissing: true }));
1497
- (_o = (_n = this.store.order) == null ? void 0 : _n.persistTempOrder) == null ? void 0 : _o.call(_n);
1447
+ const filteredOriginalDiscounts = filterCustomerBoundDiscounts(discountModule?.getOriginalDiscountList?.() || []);
1448
+ const filteredCurrentDiscounts = filterCustomerBoundDiscounts(discountModule?.getDiscountList?.() || []);
1449
+ await discountModule?.setOriginalDiscountList?.(filteredOriginalDiscounts);
1450
+ await discountModule?.setDiscountList?.(filteredCurrentDiscounts);
1451
+ this.store.order?.applyDiscount?.();
1452
+ await this.store.order?.recalculateSummary?.({
1453
+ createIfMissing: true
1454
+ });
1455
+ this.store.order?.persistTempOrder?.();
1498
1456
  }
1499
1457
  async refreshLegacySessionCustomerDiscounts(tempOrder) {
1500
1458
  const customerId = resolveTempOrderCustomerId(tempOrder);
1501
- if (!customerId)
1502
- return void 0;
1459
+ if (!customerId) return undefined;
1503
1460
  const loadDiscountConfig = super.loadDiscountConfig.bind(this);
1504
1461
  return await loadDiscountConfig({
1505
1462
  customerId,
1506
- action: this.resolveDiscountAction(
1507
- this.resolveDiscountOrderIdentity(tempOrder)
1508
- )
1463
+ action: this.resolveDiscountAction(this.resolveDiscountOrderIdentity(tempOrder))
1509
1464
  });
1510
1465
  }
1466
+
1511
1467
  /**
1512
1468
  * Loads OpenData without borrowing BookingTicket. Cache ownership is tied to the exact
1513
1469
  * business/channel target so a reused solution instance cannot leak another entry's menus.
1514
1470
  */
1515
1471
  async loadOpenData(params) {
1516
1472
  if (!this.store.openData) {
1517
- throw new Error("[UnifiedBookingSales] openData 模块未初始化");
1473
+ throw new Error('[UnifiedBookingSales] openData 模块未初始化');
1518
1474
  }
1519
- const businessCode = String(params.businessCode || "").trim();
1520
- const channel = String(params.channel || "").trim();
1475
+ const businessCode = String(params.businessCode || '').trim();
1476
+ const channel = String(params.channel || '').trim();
1521
1477
  if (!businessCode || !channel) {
1522
- throw new Error("[UnifiedBookingSales] OpenData 需要 businessCode 与 channel");
1478
+ throw new Error('[UnifiedBookingSales] OpenData 需要 businessCode 与 channel');
1523
1479
  }
1524
1480
  const target = `${businessCode}+${channel}`;
1525
1481
  const cachedData = this.store.openData.getOpenData();
@@ -1536,7 +1492,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1536
1492
  }
1537
1493
  this.loadOpenDataInFlightTarget = target;
1538
1494
  this.loadOpenDataInFlight = this.store.openData.fetchOpenData({
1539
- scope: "board",
1495
+ scope: 'board',
1540
1496
  target,
1541
1497
  section_code: [...OPEN_DATA_SECTION_CODES]
1542
1498
  });
@@ -1553,40 +1509,39 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1553
1509
  }
1554
1510
  }
1555
1511
  async getOpenData() {
1556
- var _a, _b, _c;
1557
- const businessCode = String(((_a = this.otherParams) == null ? void 0 : _a.businessCode) || "").trim();
1558
- const channel = String(((_b = this.otherParams) == null ? void 0 : _b.channel) || "").trim();
1559
- if (!businessCode || !channel)
1560
- return null;
1512
+ const businessCode = String(this.otherParams?.businessCode || '').trim();
1513
+ const channel = String(this.otherParams?.channel || '').trim();
1514
+ if (!businessCode || !channel) return null;
1561
1515
  const target = `${businessCode}+${channel}`;
1562
- const cachedData = ((_c = this.store.openData) == null ? void 0 : _c.getOpenData()) || null;
1563
- if (cachedData && this.openDataTarget === target)
1564
- return cachedData;
1565
- return this.loadOpenData({ businessCode, channel });
1516
+ const cachedData = this.store.openData?.getOpenData() || null;
1517
+ if (cachedData && this.openDataTarget === target) return cachedData;
1518
+ return this.loadOpenData({
1519
+ businessCode,
1520
+ channel
1521
+ });
1566
1522
  }
1523
+
1567
1524
  /**
1568
1525
  * Load a resource policy without depending on the legacy appointmentBooking solution.
1569
1526
  */
1570
1527
  async getProtocol(policyId) {
1571
- const normalizedPolicyId = String(policyId ?? "").trim();
1528
+ const normalizedPolicyId = String(policyId ?? '').trim();
1572
1529
  if (!normalizedPolicyId) {
1573
- throw new Error("[UnifiedBookingSales] getProtocol 需要 policyId");
1530
+ throw new Error('[UnifiedBookingSales] getProtocol 需要 policyId');
1574
1531
  }
1575
- return this.request.get(
1576
- `/shop-policy/${encodeURIComponent(normalizedPolicyId)}`
1577
- );
1532
+ return this.request.get(`/shop-policy/${encodeURIComponent(normalizedPolicyId)}`);
1578
1533
  }
1534
+
1579
1535
  /**
1580
1536
  * Loads the product catalog used by both UI and Planner. Schedule data is requested with each
1581
1537
  * product because session products carry their fixed intervals there.
1582
1538
  */
1583
1539
  async loadProducts(params = {}, options) {
1584
- if (!this.store.products)
1585
- throw new Error("[UnifiedBookingSales] products 模块未初始化");
1586
- const schedule_date = params.schedule_date || (0, import_dayjs.default)().format("YYYY-MM-DD");
1587
- const schedule_datetime = params.schedule_datetime || `${schedule_date} ${(0, import_dayjs.default)().format("HH:mm:ss")}`;
1540
+ if (!this.store.products) throw new Error('[UnifiedBookingSales] products 模块未初始化');
1541
+ const schedule_date = params.schedule_date || (0, _dayjs.default)().format('YYYY-MM-DD');
1542
+ const schedule_datetime = params.schedule_datetime || `${schedule_date} ${(0, _dayjs.default)().format('HH:mm:ss')}`;
1588
1543
  const result = await this.store.products.loadProducts({
1589
- with_count: ["bundleGroup", "optionGroup"],
1544
+ with_count: ['bundleGroup', 'optionGroup'],
1590
1545
  with_schedule: 1,
1591
1546
  ...params,
1592
1547
  schedule_date,
@@ -1597,19 +1552,19 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1597
1552
  await this.core.effects.emit(`${this.name}:onProductsLoaded`, result);
1598
1553
  return result;
1599
1554
  }
1555
+
1600
1556
  /** Date-first entry point. It delegates protocol details and cache ownership to ScheduleModule. */
1601
1557
  async loadScheduleAvailableDate(params) {
1602
- if (!this.store.schedule)
1603
- throw new Error("[UnifiedBookingSales] schedule 模块未初始化");
1558
+ if (!this.store.schedule) throw new Error('[UnifiedBookingSales] schedule 模块未初始化');
1604
1559
  return this.store.schedule.loadScheduleAvailableDate(params);
1605
1560
  }
1561
+
1606
1562
  /**
1607
1563
  * Implements the date-first product pool: the chosen date's product ids plus globally sellable
1608
1564
  * other_product_ids. If a batch product query is unexpectedly empty, retry one id at a time so
1609
1565
  * a partial backend incompatibility does not hide the entire date's catalog.
1610
1566
  */
1611
1567
  async loadProductsByScheduleDate(params) {
1612
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1613
1568
  const {
1614
1569
  date,
1615
1570
  custom_page_id,
@@ -1617,11 +1572,10 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1617
1572
  product_ids,
1618
1573
  ...productLoadParams
1619
1574
  } = params;
1620
- if (!this.store.schedule)
1621
- throw new Error("[UnifiedBookingSales] schedule 模块未初始化");
1622
- const cachedDates = ((_b = (_a = this.store.schedule).getAvailabilityScheduleDateList) == null ? void 0 : _b.call(_a)) || [];
1623
- const hasCachedDate = cachedDates.some((item) => item.date === date);
1624
- const hasOtherProducts = (((_d = (_c = this.store.schedule).getOtherProductsIds) == null ? void 0 : _d.call(_c)) || []).length > 0;
1575
+ if (!this.store.schedule) throw new Error('[UnifiedBookingSales] schedule 模块未初始化');
1576
+ const cachedDates = this.store.schedule.getAvailabilityScheduleDateList?.() || [];
1577
+ const hasCachedDate = cachedDates.some(item => item.date === date);
1578
+ const hasOtherProducts = (this.store.schedule.getOtherProductsIds?.() || []).length > 0;
1625
1579
  if (!hasCachedDate && !hasOtherProducts) {
1626
1580
  await this.loadScheduleAvailableDate({
1627
1581
  startDate: date,
@@ -1630,12 +1584,9 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1630
1584
  channel
1631
1585
  });
1632
1586
  }
1633
- const scheduleDate = (_g = (_f = (_e = this.store.schedule).getAvailabilityScheduleDateList) == null ? void 0 : _f.call(_e)) == null ? void 0 : _g.find((item) => item.date === date);
1634
- const productIdFilter = (product_ids == null ? void 0 : product_ids.length) ? new Set(product_ids.map((id) => String(id))) : null;
1635
- const availableProductIds = [
1636
- ...(scheduleDate == null ? void 0 : scheduleDate.product_ids) || [],
1637
- ...((_i = (_h = this.store.schedule).getOtherProductsIds) == null ? void 0 : _i.call(_h)) || []
1638
- ].filter((id, index, self) => self.indexOf(id) === index).filter((id) => !productIdFilter || productIdFilter.has(String(id)));
1587
+ const scheduleDate = this.store.schedule.getAvailabilityScheduleDateList?.()?.find(item => item.date === date);
1588
+ const productIdFilter = product_ids?.length ? new Set(product_ids.map(id => String(id))) : null;
1589
+ const availableProductIds = [...(scheduleDate?.product_ids || []), ...(this.store.schedule.getOtherProductsIds?.() || [])].filter((id, index, self) => self.indexOf(id) === index).filter(id => !productIdFilter || productIdFilter.has(String(id)));
1639
1590
  if (!availableProductIds.length) {
1640
1591
  this.unifiedProductCatalog = [];
1641
1592
  await this.core.effects.emit(`${this.name}:onProductsLoaded`, []);
@@ -1646,8 +1597,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1646
1597
  product_ids: availableProductIds,
1647
1598
  schedule_date: date
1648
1599
  });
1649
- if (products.length || availableProductIds.length <= 1)
1650
- return products;
1600
+ if (products.length || availableProductIds.length <= 1) return products;
1651
1601
  const fallbackProducts = [];
1652
1602
  for (const productId of availableProductIds) {
1653
1603
  const result = await this.loadProducts({
@@ -1655,9 +1605,9 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1655
1605
  product_ids: [productId],
1656
1606
  schedule_date: date
1657
1607
  });
1658
- result.forEach((product) => {
1659
- const id = (product == null ? void 0 : product.id) ?? (product == null ? void 0 : product.product_id);
1660
- if (!fallbackProducts.some((item) => String((item == null ? void 0 : item.id) ?? (item == null ? void 0 : item.product_id)) === String(id))) {
1608
+ result.forEach(product => {
1609
+ const id = product?.id ?? product?.product_id;
1610
+ if (!fallbackProducts.some(item => String(item?.id ?? item?.product_id) === String(id))) {
1661
1611
  fallbackProducts.push(product);
1662
1612
  }
1663
1613
  });
@@ -1666,10 +1616,14 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1666
1616
  await this.core.effects.emit(`${this.name}:onProductsLoaded`, fallbackProducts);
1667
1617
  return fallbackProducts;
1668
1618
  }
1619
+
1669
1620
  /** Returns a copy so UI consumers cannot accidentally mutate the solution's product cache. */
1670
1621
  getProductCatalog() {
1671
- return { products: [...this.unifiedProductCatalog] };
1622
+ return {
1623
+ products: [...this.unifiedProductCatalog]
1624
+ };
1672
1625
  }
1626
+
1673
1627
  /**
1674
1628
  * Read-only compatibility view for salesSdk skins. It reconnects a booking to its product but
1675
1629
  * must not be used to mutate tempOrder; all writes go through BaseSales / planner APIs.
@@ -1701,6 +1655,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1701
1655
  // }),
1702
1656
  // };
1703
1657
  // }
1658
+
1704
1659
  /**
1705
1660
  * Loads the current customer's product coupons and discount cards after planner lines exist,
1706
1661
  * then optionally lets the existing Rules engine select the best valid combination. This is a
@@ -1708,7 +1663,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1708
1663
  */
1709
1664
  async applyPlannerDiscounts(params = {}) {
1710
1665
  const tempOrder = this.getTempOrder();
1711
- const requestedCustomerId = params.customerId ?? (tempOrder == null ? void 0 : tempOrder.customer_id);
1666
+ const requestedCustomerId = params.customerId ?? tempOrder?.customer_id;
1712
1667
  const parsedCustomerId = Number(requestedCustomerId);
1713
1668
  const customerId = Number.isFinite(parsedCustomerId) && parsedCustomerId > 1 ? parsedCustomerId : null;
1714
1669
  const summaryBefore = await this.getSummary();
@@ -1716,31 +1671,39 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1716
1671
  return buildPlannerDiscountResult({
1717
1672
  customerId: null,
1718
1673
  discountList: this.getDiscountList(),
1719
- products: (tempOrder == null ? void 0 : tempOrder.products) || [],
1674
+ products: tempOrder?.products || [],
1720
1675
  summaryBefore,
1721
1676
  summaryAfter: summaryBefore,
1722
- status: "no_customer"
1677
+ status: 'no_customer'
1723
1678
  });
1724
1679
  }
1725
- await this.loadDiscountConfig({ customerId, action: "create" });
1680
+ await this.loadDiscountConfig({
1681
+ customerId,
1682
+ action: 'create'
1683
+ });
1726
1684
  const preferredDiscountId = params.preferredDiscountId;
1727
- const preferredDiscount = preferredDiscountId === void 0 || preferredDiscountId === null ? void 0 : this.getDiscountList().find((discount) => String(resolvePlannerDiscountId(discount) ?? "") === String(preferredDiscountId));
1685
+ const preferredDiscount = preferredDiscountId === undefined || preferredDiscountId === null ? undefined : this.getDiscountList().find(discount => String(resolvePlannerDiscountId(discount) ?? '') === String(preferredDiscountId));
1728
1686
  if (preferredDiscount) {
1687
+ // A requested card is an explicit UI choice, not a best-effort preference. Clear prior
1688
+ // automatic selections first; otherwise Rules may keep the old selected card and silently
1689
+ // apply it instead of the card the customer clicked.
1729
1690
  const preferredId = resolvePlannerDiscountId(preferredDiscount);
1730
- const selectedOtherDiscounts = this.getDiscountList().filter((discount) => discount.isSelected === true && String(resolvePlannerDiscountId(discount) ?? "") !== String(preferredId));
1691
+ const selectedOtherDiscounts = this.getDiscountList().filter(discount => discount.isSelected === true && String(resolvePlannerDiscountId(discount) ?? '') !== String(preferredId));
1731
1692
  for (const discount of selectedOtherDiscounts) {
1732
1693
  const discountId = Number(resolvePlannerDiscountId(discount));
1733
1694
  if (Number.isFinite(discountId)) {
1734
- await this.setDiscountSelected({ discountId, isSelected: false });
1695
+ await this.setDiscountSelected({
1696
+ discountId,
1697
+ isSelected: false
1698
+ });
1735
1699
  }
1736
1700
  }
1737
1701
  await this.setDiscountSelected({
1738
1702
  discountId: Number(preferredId),
1739
1703
  isSelected: true
1740
1704
  });
1741
- } else if (preferredDiscountId === void 0 || preferredDiscountId === null) {
1742
- if (params.applyBestDiscount !== false)
1743
- await this.bestDiscount();
1705
+ } else if (preferredDiscountId === undefined || preferredDiscountId === null) {
1706
+ if (params.applyBestDiscount !== false) await this.bestDiscount();
1744
1707
  } else if (params.applyBestDiscount !== false) {
1745
1708
  await this.bestDiscount();
1746
1709
  }
@@ -1748,206 +1711,204 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1748
1711
  return buildPlannerDiscountResult({
1749
1712
  customerId,
1750
1713
  discountList: this.getDiscountList(),
1751
- products: (nextTempOrder == null ? void 0 : nextTempOrder.products) || [],
1714
+ products: nextTempOrder?.products || [],
1752
1715
  summaryBefore,
1753
1716
  summaryAfter: await this.getSummary(),
1754
- status: params.applyBestDiscount === false && !preferredDiscount ? "loaded" : "applied",
1717
+ status: params.applyBestDiscount === false && !preferredDiscount ? 'loaded' : 'applied',
1755
1718
  preferredDiscountId,
1756
- preferredDiscountFound: preferredDiscountId === void 0 || preferredDiscountId === null ? void 0 : Boolean(preferredDiscount)
1719
+ preferredDiscountFound: preferredDiscountId === undefined || preferredDiscountId === null ? undefined : Boolean(preferredDiscount)
1757
1720
  });
1758
1721
  }
1759
1722
  buildUnifiedOrderProduct(sourceProduct, ownershipKey, product) {
1760
- const normalizedProductRaw = (product == null ? void 0 : product.raw) || {};
1723
+ const normalizedProductRaw = product?.raw || {};
1761
1724
  const orderProduct = this.transformBaseProductToOrderProduct({
1762
1725
  payload: {
1763
1726
  ...sourceProduct,
1764
- id: sourceProduct.id ?? (product == null ? void 0 : product.id),
1765
- product_id: sourceProduct.product_id ?? sourceProduct.id ?? (product == null ? void 0 : product.id),
1766
- quantity: sourceProduct.quantity ?? sourceProduct.num ?? (product == null ? void 0 : product.quantity) ?? 1,
1727
+ id: sourceProduct.id ?? product?.id,
1728
+ product_id: sourceProduct.product_id ?? sourceProduct.id ?? product?.id,
1729
+ quantity: sourceProduct.quantity ?? sourceProduct.num ?? product?.quantity ?? 1,
1767
1730
  price: sourceProduct.price ?? normalizedProductRaw.price,
1768
1731
  selling_price: sourceProduct.selling_price ?? sourceProduct.price ?? normalizedProductRaw.selling_price ?? normalizedProductRaw.price,
1769
1732
  metadata: {
1770
- ...sourceProduct.metadata || {},
1733
+ ...(sourceProduct.metadata || {}),
1771
1734
  [ownershipKey]: true
1772
1735
  }
1773
1736
  },
1774
1737
  sourceProduct
1775
1738
  });
1776
- if (orderProduct && typeof orderProduct === "object") {
1739
+ if (orderProduct && typeof orderProduct === 'object') {
1740
+ // BaseSales may rebuild metadata from its price source. Stamp ownership after that transform
1741
+ // so each UnifiedBookingSales entry point can replace only its own temporary lines.
1777
1742
  orderProduct.metadata = {
1778
- ...orderProduct.metadata || {},
1743
+ ...(orderProduct.metadata || {}),
1779
1744
  [ownershipKey]: true
1780
1745
  };
1781
1746
  }
1782
1747
  return orderProduct;
1783
1748
  }
1749
+
1784
1750
  /** Replacing a staged selection is idempotent and never removes unrelated cart lines. */
1785
1751
  async removeExistingStagedLines(ownershipKey) {
1786
- var _a;
1787
- const existingLines = (((_a = this.getTempOrder()) == null ? void 0 : _a.products) || []).filter((product) => {
1788
- var _a2;
1789
- return ((_a2 = product == null ? void 0 : product.metadata) == null ? void 0 : _a2[ownershipKey]) === true;
1790
- });
1752
+ const existingLines = (this.getTempOrder()?.products || []).filter(product => product?.metadata?.[ownershipKey] === true);
1791
1753
  if (existingLines.length > 0) {
1792
1754
  await this.removeProductsFromOrder(existingLines.map(buildAvailabilityLineIdentity));
1793
1755
  }
1794
1756
  }
1795
1757
  async stageProducts(params, ownershipKey) {
1796
- var _a;
1797
1758
  const productIds = params.productIds || [];
1798
- if (!productIds.length)
1799
- return this.getTempOrder();
1800
- if ((_a = params.rawProducts) == null ? void 0 : _a.length) {
1759
+ if (!productIds.length) return this.getTempOrder();
1760
+ if (params.rawProducts?.length) {
1801
1761
  this.unifiedProductCatalog = params.rawProducts;
1802
1762
  } else {
1803
- const existingIds = new Set((this.unifiedProductCatalog || []).map((product) => String(product.id ?? product.product_id)));
1804
- const missingIds = productIds.filter((id) => !existingIds.has(String(id)));
1763
+ const existingIds = new Set((this.unifiedProductCatalog || []).map(product => String(product.id ?? product.product_id)));
1764
+ const missingIds = productIds.filter(id => !existingIds.has(String(id)));
1805
1765
  if (missingIds.length || params.productLoadParams) {
1806
1766
  await this.loadProducts({
1807
- ...params.productLoadParams || {},
1767
+ ...(params.productLoadParams || {}),
1808
1768
  product_ids: productIds.map(Number).filter(Number.isFinite)
1809
1769
  });
1810
1770
  }
1811
1771
  }
1812
1772
  await this.removeExistingStagedLines(ownershipKey);
1813
- const productIdSet = new Set(productIds.map((id) => String(id)));
1814
- const selectedProducts = (this.unifiedProductCatalog || []).filter((product) => productIdSet.has(String(product.id ?? product.product_id)));
1773
+ const productIdSet = new Set(productIds.map(id => String(id)));
1774
+ const selectedProducts = (this.unifiedProductCatalog || []).filter(product => productIdSet.has(String(product.id ?? product.product_id)));
1815
1775
  for (const sourceProduct of selectedProducts) {
1816
1776
  const productInput = this.buildUnifiedOrderProduct(sourceProduct, ownershipKey);
1817
- if (productInput)
1818
- await this.addProductToOrder(productInput);
1777
+ if (productInput) await this.addProductToOrder(productInput);
1819
1778
  }
1820
1779
  return this.getTempOrder();
1821
1780
  }
1781
+
1822
1782
  /**
1823
1783
  * Adds ordinary retail products without asking ResourcePlanner for booking facts.
1824
1784
  * Its staged lines have separate ownership so planner and retail skins can coexist safely.
1825
1785
  */
1826
1786
  async stageRetailProducts(params) {
1827
- return this.stageProducts(params, "unified_booking_sales_retail");
1787
+ return this.stageProducts(params, 'unified_booking_sales_retail');
1828
1788
  }
1789
+
1829
1790
  /**
1830
1791
  * Adds one retail line without replacing the cart's existing retail selection.
1831
1792
  * This is intentionally separate from stageRetailProducts(), whose contract is
1832
1793
  * "replace the staged selection" for demo and wizard-like callers.
1833
1794
  */
1834
1795
  async addRetailProduct(params) {
1835
- var _a, _b;
1836
1796
  const quantity = Math.floor(Number(params.quantity ?? 1));
1837
1797
  if (!Number.isFinite(quantity) || quantity <= 0) {
1838
- throw new Error("[UnifiedBookingSales] retail 商品数量必须大于 0");
1798
+ throw new Error('[UnifiedBookingSales] retail 商品数量必须大于 0');
1839
1799
  }
1840
- const productId = params.productId ?? ((_a = params.product) == null ? void 0 : _a.id) ?? ((_b = params.product) == null ? void 0 : _b.product_id);
1800
+ const productId = params.productId ?? params.product?.id ?? params.product?.product_id;
1841
1801
  let sourceProduct = params.product;
1842
- if (!sourceProduct && productId !== void 0 && productId !== null) {
1843
- sourceProduct = this.unifiedProductCatalog.find(
1844
- (product) => String(product.id ?? product.product_id) === String(productId)
1845
- );
1802
+ if (!sourceProduct && productId !== undefined && productId !== null) {
1803
+ sourceProduct = this.unifiedProductCatalog.find(product => String(product.id ?? product.product_id) === String(productId));
1846
1804
  }
1847
- if (!sourceProduct && productId !== void 0 && productId !== null) {
1805
+ if (!sourceProduct && productId !== undefined && productId !== null) {
1848
1806
  const products = await this.loadProducts({
1849
- ...params.productLoadParams || {},
1807
+ ...(params.productLoadParams || {}),
1850
1808
  product_ids: [Number(productId)].filter(Number.isFinite)
1851
1809
  });
1852
- sourceProduct = products.find(
1853
- (product) => String(product.id ?? product.product_id) === String(productId)
1854
- );
1810
+ sourceProduct = products.find(product => String(product.id ?? product.product_id) === String(productId));
1855
1811
  }
1856
1812
  if (!sourceProduct) {
1857
- throw new Error(`[UnifiedBookingSales] 未找到零售商品 ${String(productId ?? "")}`.trim());
1813
+ throw new Error(`[UnifiedBookingSales] 未找到零售商品 ${String(productId ?? '')}`.trim());
1858
1814
  }
1859
- const orderProduct = this.buildUnifiedOrderProduct(
1860
- {
1861
- ...sourceProduct,
1862
- quantity
1863
- },
1864
- "unified_booking_sales_retail"
1865
- );
1815
+ const orderProduct = this.buildUnifiedOrderProduct({
1816
+ ...sourceProduct,
1817
+ quantity
1818
+ }, 'unified_booking_sales_retail');
1866
1819
  if (!orderProduct) {
1867
- throw new Error("[UnifiedBookingSales] 无法生成零售商品订单行");
1820
+ throw new Error('[UnifiedBookingSales] 无法生成零售商品订单行');
1868
1821
  }
1869
1822
  return this.addProductToOrder(orderProduct);
1870
1823
  }
1871
1824
  normalizeAvailabilityDateRange(params, timezone) {
1872
- var _a, _b;
1873
- const today = (0, import_localClock.formatLocalDate)((0, import_localClock.localDateToScalar)(/* @__PURE__ */ new Date()));
1874
- const startDate = ((_a = params.dateRange) == null ? void 0 : _a.startDate) || today;
1875
- const endDate = ((_b = params.dateRange) == null ? void 0 : _b.endDate) || (0, import_localClock.formatLocalDate)((0, import_localClock.addLocalCalendarDays)((0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(startDate)), 31));
1825
+ const today = (0, _localClock.formatLocalDate)((0, _localClock.localDateToScalar)(new Date()));
1826
+ const startDate = params.dateRange?.startDate || today;
1827
+ const endDate = params.dateRange?.endDate || (0, _localClock.formatLocalDate)((0, _localClock.addLocalCalendarDays)((0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(startDate)), 31));
1876
1828
  let startScalar;
1877
1829
  let endScalar;
1878
1830
  try {
1879
- startScalar = (0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(startDate));
1880
- endScalar = (0, import_localClock.localDateToScalarStart)((0, import_localClock.parseLocalDate)(endDate));
1831
+ startScalar = (0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(startDate));
1832
+ endScalar = (0, _localClock.localDateToScalarStart)((0, _localClock.parseLocalDate)(endDate));
1881
1833
  } catch (error) {
1882
- throw new import_ResourcePlanner.AvailabilityError("INVALID_DATE_RANGE", "日期范围必须是有效的 YYYY-MM-DD 且结束日期不早于开始日期", {
1883
- dateRange: { startDate, endDate },
1834
+ throw new _ResourcePlanner.AvailabilityError('INVALID_DATE_RANGE', '日期范围必须是有效的 YYYY-MM-DD 且结束日期不早于开始日期', {
1835
+ dateRange: {
1836
+ startDate,
1837
+ endDate
1838
+ },
1884
1839
  timezone,
1885
1840
  cause: error instanceof Error ? error.message : String(error)
1886
1841
  });
1887
1842
  }
1888
1843
  if (endScalar < startScalar) {
1889
- throw new import_ResourcePlanner.AvailabilityError("INVALID_DATE_RANGE", "日期范围必须是有效的 YYYY-MM-DD 且结束日期不早于开始日期", {
1890
- dateRange: { startDate, endDate },
1844
+ throw new _ResourcePlanner.AvailabilityError('INVALID_DATE_RANGE', '日期范围必须是有效的 YYYY-MM-DD 且结束日期不早于开始日期', {
1845
+ dateRange: {
1846
+ startDate,
1847
+ endDate
1848
+ },
1891
1849
  timezone
1892
1850
  });
1893
1851
  }
1894
- const inclusiveDays = Math.trunc((endScalar - startScalar) / (24 * 60 * 60 * 1e3)) + 1;
1852
+ const inclusiveDays = Math.trunc((endScalar - startScalar) / (24 * 60 * 60 * 1000)) + 1;
1895
1853
  if (inclusiveDays > MAX_AVAILABILITY_RANGE_DAYS) {
1896
- throw new import_ResourcePlanner.AvailabilityError("RANGE_TOO_LARGE", "日期范围最多包含 90 个自然日", {
1897
- dateRange: { startDate, endDate },
1854
+ throw new _ResourcePlanner.AvailabilityError('RANGE_TOO_LARGE', '日期范围最多包含 90 个自然日', {
1855
+ dateRange: {
1856
+ startDate,
1857
+ endDate
1858
+ },
1898
1859
  inclusiveDays
1899
1860
  });
1900
1861
  }
1901
- return { startDate, endDate };
1862
+ return {
1863
+ startDate,
1864
+ endDate
1865
+ };
1902
1866
  }
1903
1867
  assertAvailabilityPrepareParams(params) {
1904
- var _a, _b;
1905
- assertAvailabilityCatalogProductIds(params.productIds, "prepare.productIds");
1868
+ assertAvailabilityCatalogProductIds(params.productIds, 'prepare.productIds');
1906
1869
  const hasProductAnchor = Array.isArray(params.productIds) && params.productIds.length > 0;
1907
1870
  const hasResourceAnchor = Array.isArray(params.resourceIds) && params.resourceIds.length > 0;
1908
- const hasDateAnchor = Boolean(((_a = params.dateRange) == null ? void 0 : _a.startDate) || ((_b = params.dateRange) == null ? void 0 : _b.endDate));
1871
+ const hasDateAnchor = Boolean(params.dateRange?.startDate || params.dateRange?.endDate);
1909
1872
  if (!hasProductAnchor && !hasResourceAnchor && !hasDateAnchor) {
1910
- throw new import_ResourcePlanner.AvailabilityError("MISSING_ANCHOR", "prepare 至少需要 productIds、resourceIds 或 dateRange 之一", {
1873
+ throw new _ResourcePlanner.AvailabilityError('MISSING_ANCHOR', 'prepare 至少需要 productIds、resourceIds 或 dateRange 之一', {
1911
1874
  params
1912
1875
  });
1913
1876
  }
1914
1877
  if (!hasProductAnchor && !params.catalogScope) {
1915
- throw new import_ResourcePlanner.AvailabilityError("MISSING_CATALOG_SCOPE", "缺少 productIds 时必须提供 catalogScope", {
1878
+ throw new _ResourcePlanner.AvailabilityError('MISSING_CATALOG_SCOPE', '缺少 productIds 时必须提供 catalogScope', {
1916
1879
  params
1917
1880
  });
1918
1881
  }
1919
- if (params.slotStepMinutes !== void 0) {
1882
+ if (params.slotStepMinutes !== undefined) {
1920
1883
  const step = Number(params.slotStepMinutes);
1921
1884
  if (!Number.isInteger(step) || step <= 0) {
1922
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "slotStepMinutes 必须是正整数", {
1885
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'slotStepMinutes 必须是正整数', {
1923
1886
  slotStepMinutes: params.slotStepMinutes
1924
1887
  });
1925
1888
  }
1926
1889
  }
1927
1890
  }
1928
1891
  captureAvailabilityScheduleCatalog() {
1929
- var _a, _b;
1930
1892
  if (!this.store.schedule) {
1931
- throw new Error("[UnifiedBookingSales] schedule 模块未初始化");
1893
+ throw new Error('[UnifiedBookingSales] schedule 模块未初始化');
1932
1894
  }
1933
- this.availabilityScheduleCatalog = (0, import_lodash_es.cloneDeep)(
1934
- ((_b = (_a = this.store.schedule).getScheduleList) == null ? void 0 : _b.call(_a)) || []
1935
- );
1895
+ this.availabilityScheduleCatalog = (0, _lodashEs.cloneDeep)(this.store.schedule.getScheduleList?.() || []);
1936
1896
  }
1897
+
1937
1898
  /** Returns the solution-lifetime schedule snapshot captured after initialization. */
1938
1899
  getAvailabilityScheduleCatalog() {
1939
1900
  if (this.availabilityScheduleCatalog === null) {
1940
- throw new Error("[UnifiedBookingSales] schedule 快照未初始化");
1901
+ throw new Error('[UnifiedBookingSales] schedule 快照未初始化');
1941
1902
  }
1942
1903
  return this.availabilityScheduleCatalog;
1943
1904
  }
1944
1905
  buildAvailabilityOperatingHoursSnapshot(params) {
1945
1906
  const descriptor = params.prepare._availabilityOperatingHours || {
1946
- source: params.prepare.businessHours ? "prepare_business_hours" : "default_business_hours",
1907
+ source: params.prepare.businessHours ? 'prepare_business_hours' : 'default_business_hours',
1947
1908
  scheduleIds: []
1948
1909
  };
1949
- if (descriptor.source !== "open_data_schedule") {
1950
- const windows2 = dateRangeDays(params.dateRange).flatMap((date) => {
1910
+ if (descriptor.source !== 'open_data_schedule') {
1911
+ const windows = dateRangeDays(params.dateRange).flatMap(date => {
1951
1912
  const range = normalizeAvailabilityLocalDateTimeRange({
1952
1913
  startAt: `${date}T${params.businessHours.startTime}:00`,
1953
1914
  endAt: `${date}T${params.businessHours.endTime}:00`,
@@ -1964,18 +1925,14 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1964
1925
  source: descriptor.source,
1965
1926
  scheduleIds: [],
1966
1927
  missingScheduleIds: [],
1967
- windows: windows2
1928
+ windows
1968
1929
  };
1969
1930
  }
1970
- const scheduleMap = new Map(
1971
- params.scheduleList.map((schedule) => [String(schedule.id), schedule])
1972
- );
1973
- const schedules = descriptor.scheduleIds.map((scheduleId) => scheduleMap.get(String(scheduleId))).filter((schedule) => Boolean(schedule));
1974
- const matchedScheduleIds = new Set(schedules.map((schedule) => String(schedule.id)));
1975
- const missingScheduleIds = descriptor.scheduleIds.filter(
1976
- (scheduleId) => !matchedScheduleIds.has(String(scheduleId))
1977
- );
1978
- const windows = dateRangeDays(params.dateRange).flatMap((date) => (0, import_getDateIsInSchedule.getScheduleStartEndTimePoints)(date, schedules).flatMap((slot) => {
1931
+ const scheduleMap = new Map(params.scheduleList.map(schedule => [String(schedule.id), schedule]));
1932
+ const schedules = descriptor.scheduleIds.map(scheduleId => scheduleMap.get(String(scheduleId))).filter(schedule => Boolean(schedule));
1933
+ const matchedScheduleIds = new Set(schedules.map(schedule => String(schedule.id)));
1934
+ const missingScheduleIds = descriptor.scheduleIds.filter(scheduleId => !matchedScheduleIds.has(String(scheduleId)));
1935
+ const windows = dateRangeDays(params.dateRange).flatMap(date => (0, _getDateIsInSchedule.getScheduleStartEndTimePoints)(date, schedules).flatMap(slot => {
1979
1936
  const range = normalizeAvailabilityLocalDateTimeRange({
1980
1937
  startAt: slot.start_at,
1981
1938
  endAt: slot.end_at,
@@ -1985,7 +1942,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1985
1942
  return range ? [{
1986
1943
  startAt: range.startAt,
1987
1944
  endAt: range.endAt,
1988
- source: `operating_schedule:${descriptor.scheduleIds.map(String).join(",")}`
1945
+ source: `operating_schedule:${descriptor.scheduleIds.map(String).join(',')}`
1989
1946
  }] : [];
1990
1947
  }));
1991
1948
  return {
@@ -1996,8 +1953,10 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
1996
1953
  };
1997
1954
  }
1998
1955
  async loadAvailabilityProducts(params) {
1999
- var _a, _b, _c, _d, _e, _f, _g;
2000
- const { prepare, dateRange } = params;
1956
+ const {
1957
+ prepare,
1958
+ dateRange
1959
+ } = params;
2001
1960
  const explicitProductIds = prepare.productIds || [];
2002
1961
  let rawProducts = [];
2003
1962
  if (Array.isArray(prepare.rawProducts)) {
@@ -2008,21 +1967,18 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2008
1967
  product_ids: explicitProductIds,
2009
1968
  schedule_date: dateRange.startDate
2010
1969
  });
2011
- } else if (((_a = prepare.catalogScope) == null ? void 0 : _a.type) === "schedule") {
1970
+ } else if (prepare.catalogScope?.type === 'schedule') {
2012
1971
  await this.loadScheduleAvailableDate({
2013
1972
  startDate: dateRange.startDate,
2014
1973
  endDate: dateRange.endDate,
2015
- custom_page_id: Number(prepare.catalogScope.customPageId) || void 0,
1974
+ custom_page_id: Number(prepare.catalogScope.customPageId) || undefined,
2016
1975
  channel: prepare.catalogScope.channel
2017
1976
  });
2018
1977
  const dateSet = new Set(dateRangeDays(dateRange));
2019
- const scheduleProductIds = (((_c = (_b = this.store.schedule).getAvailabilityScheduleDateList) == null ? void 0 : _c.call(_b)) || []).filter((item) => dateSet.has(item.date)).flatMap((item) => item.product_ids || []);
2020
- const productIds = uniqueAvailabilityIds([
2021
- ...scheduleProductIds,
2022
- ...((_e = (_d = this.store.schedule).getOtherProductsIds) == null ? void 0 : _e.call(_d)) || []
2023
- ]);
1978
+ const scheduleProductIds = (this.store.schedule.getAvailabilityScheduleDateList?.() || []).filter(item => dateSet.has(item.date)).flatMap(item => item.product_ids || []);
1979
+ const productIds = uniqueAvailabilityIds([...scheduleProductIds, ...(this.store.schedule.getOtherProductsIds?.() || [])]);
2024
1980
  if (productIds.length > 0) {
2025
- assertAvailabilityCatalogProductIds(productIds, "prepare.catalogScope.scheduleProductIds");
1981
+ assertAvailabilityCatalogProductIds(productIds, 'prepare.catalogScope.scheduleProductIds');
2026
1982
  rawProducts = await this.loadProducts({
2027
1983
  product_ids: productIds,
2028
1984
  schedule_date: dateRange.startDate
@@ -2030,36 +1986,27 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2030
1986
  } else {
2031
1987
  this.unifiedProductCatalog = [];
2032
1988
  }
2033
- } else if (((_f = prepare.catalogScope) == null ? void 0 : _f.type) === "productList") {
1989
+ } else if (prepare.catalogScope?.type === 'productList') {
2034
1990
  rawProducts = await this.loadProducts({
2035
1991
  ...prepare.catalogScope.params,
2036
1992
  schedule_date: prepare.catalogScope.params.schedule_date || dateRange.startDate
2037
1993
  });
2038
1994
  }
2039
- const normalized = rawProducts.map((product) => normalizeProductForAvailability(
2040
- product,
2041
- params.scheduleList,
2042
- this.getAvailabilityRuntimeOffsetMinutes()
2043
- ));
2044
- if (!explicitProductIds.length && ((_g = prepare.resourceIds) == null ? void 0 : _g.length)) {
2045
- return normalized.filter((product) => {
2046
- var _a2;
2047
- return (_a2 = product.requirementGroups) == null ? void 0 : _a2.some((group) => {
2048
- var _a3;
2049
- return (_a3 = group.resourceIds) == null ? void 0 : _a3.some((resourceId) => prepare.resourceIds.some((id) => sameAvailabilityId(id, resourceId)));
2050
- });
2051
- });
1995
+ const normalized = rawProducts.map(product => normalizeProductForAvailability(product, params.scheduleList, this.getAvailabilityRuntimeOffsetMinutes()));
1996
+ if (!explicitProductIds.length && prepare.resourceIds?.length) {
1997
+ return normalized.filter(product => product.requirementGroups?.some(group => group.resourceIds?.some(resourceId => prepare.resourceIds.some(id => sameAvailabilityId(id, resourceId)))));
2052
1998
  }
2053
1999
  const productIdSet = explicitProductIds.length ? new Set(explicitProductIds.map(String)) : null;
2054
- return productIdSet ? normalized.filter((product) => productIdSet.has(String(product.id))) : normalized;
2000
+ return productIdSet ? normalized.filter(product => productIdSet.has(String(product.id))) : normalized;
2055
2001
  }
2002
+
2056
2003
  /**
2057
2004
  * Fetches resource metadata plus flat occupied events. Work windows are intentionally derived
2058
2005
  * locally in buildAvailabilityResourcesFromV2 from /schedule, rather than requested from the legacy
2059
2006
  * resource dates endpoint.
2060
2007
  */
2061
2008
  async fetchAvailabilityResourcesV2(params) {
2062
- const response = await this.request.get("/schedule/resource/list/v2", {
2009
+ const response = await this.request.get('/schedule/resource/list/v2', {
2063
2010
  start_date: params.dateRange.startDate,
2064
2011
  end_date: params.dateRange.endDate,
2065
2012
  resource_ids: params.resourceIds,
@@ -2067,17 +2014,14 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2067
2014
  }, {
2068
2015
  useCache: false
2069
2016
  });
2070
- const data = response == null ? void 0 : response.data;
2071
- if (Array.isArray(data))
2072
- return data;
2073
- if (Array.isArray(data == null ? void 0 : data.list))
2074
- return data.list;
2017
+ const data = response?.data;
2018
+ if (Array.isArray(data)) return data;
2019
+ if (Array.isArray(data?.list)) return data.list;
2075
2020
  return [];
2076
2021
  }
2077
2022
  async fetchAndPublishAvailabilityResourcesV2(params) {
2078
2023
  const normalizedResourceIds = this.normalizeAvailabilityIdList(params.resourceIds) || [];
2079
- if (normalizedResourceIds.length === 0)
2080
- return [];
2024
+ if (normalizedResourceIds.length === 0) return [];
2081
2025
  const scopeKey = this.buildAvailabilityRemoteResourceScopeKey(params.timezone);
2082
2026
  const cacheParams = {
2083
2027
  scopeKey,
@@ -2091,8 +2035,8 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2091
2035
  timezone: params.timezone,
2092
2036
  dateRange: params.dateRange,
2093
2037
  resourceIds: normalizedResourceIds
2094
- }).catch((error) => {
2095
- console.warn("[UnifiedBookingSales] Remote occupancy background refresh failed", error);
2038
+ }).catch(error => {
2039
+ console.warn('[UnifiedBookingSales] Remote occupancy background refresh failed', error);
2096
2040
  });
2097
2041
  }
2098
2042
  return cachedRawResources;
@@ -2105,8 +2049,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2105
2049
  }
2106
2050
  async refreshAvailabilityRemoteResourceQuery(params) {
2107
2051
  const normalizedResourceIds = this.normalizeAvailabilityIdList(params.resourceIds) || [];
2108
- if (normalizedResourceIds.length === 0)
2109
- return [];
2052
+ if (normalizedResourceIds.length === 0) return [];
2110
2053
  const queryKey = this.buildAvailabilityRemoteResourceQueryKey({
2111
2054
  timezone: params.timezone,
2112
2055
  dateRange: params.dateRange,
@@ -2114,7 +2057,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2114
2057
  });
2115
2058
  const epoch = this.availabilityRemoteResourceEpoch;
2116
2059
  const existing = this.availabilityRemoteResourceQueryInFlight.get(queryKey);
2117
- if ((existing == null ? void 0 : existing.epoch) === epoch) {
2060
+ if (existing?.epoch === epoch) {
2118
2061
  return await existing.promise;
2119
2062
  }
2120
2063
  this.availabilityRemoteResourceQuerySequence += 1;
@@ -2142,7 +2085,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2142
2085
  return rawResources;
2143
2086
  } finally {
2144
2087
  const current = this.availabilityRemoteResourceQueryInFlight.get(queryKey);
2145
- if ((current == null ? void 0 : current.promise) === promise) {
2088
+ if (current?.promise === promise) {
2146
2089
  this.availabilityRemoteResourceQueryInFlight.delete(queryKey);
2147
2090
  }
2148
2091
  }
@@ -2163,7 +2106,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2163
2106
  fixedOffsetMinutes: this.getAvailabilityRuntimeOffsetMinutes()
2164
2107
  });
2165
2108
  }
2166
- if (params.fetchPolicy === "cache_only") {
2109
+ if (params.fetchPolicy === 'cache_only') {
2167
2110
  const cachedRawResources = this.availabilityRemoteOccupancyCache.read({
2168
2111
  scopeKey: this.buildAvailabilityRemoteResourceScopeKey(params.timezone),
2169
2112
  resourceIds,
@@ -2177,7 +2120,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2177
2120
  fixedOffsetMinutes: this.getAvailabilityRuntimeOffsetMinutes()
2178
2121
  });
2179
2122
  }
2180
- return params.fallbackResources ? (0, import_lodash_es.cloneDeep)(params.fallbackResources) : {
2123
+ return params.fallbackResources ? (0, _lodashEs.cloneDeep)(params.fallbackResources) : {
2181
2124
  resources: [],
2182
2125
  resourceOccupancies: []
2183
2126
  };
@@ -2196,44 +2139,46 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2196
2139
  });
2197
2140
  }
2198
2141
  resolveEditingOccupancyExclusions(tempOrder, productLineUids = []) {
2199
- const productUids = /* @__PURE__ */ new Set();
2200
- const bookingUids = /* @__PURE__ */ new Set();
2201
- const scheduleEventIds = /* @__PURE__ */ new Set();
2202
- if (!productLineUids.length)
2203
- return { productUids, bookingUids, scheduleEventIds };
2204
- const products = Array.isArray(tempOrder == null ? void 0 : tempOrder.products) ? tempOrder.products : [];
2205
- const bookings = Array.isArray(tempOrder == null ? void 0 : tempOrder.bookings) ? tempOrder.bookings : [];
2206
- productLineUids.forEach((requestedUid) => {
2207
- var _a;
2208
- const product = products.find((line) => getProductLineUid(line) === String(requestedUid));
2142
+ const productUids = new Set();
2143
+ const bookingUids = new Set();
2144
+ const scheduleEventIds = new Set();
2145
+ if (!productLineUids.length) return {
2146
+ productUids,
2147
+ bookingUids,
2148
+ scheduleEventIds
2149
+ };
2150
+ const products = Array.isArray(tempOrder?.products) ? tempOrder.products : [];
2151
+ const bookings = Array.isArray(tempOrder?.bookings) ? tempOrder.bookings : [];
2152
+ productLineUids.forEach(requestedUid => {
2153
+ const product = products.find(line => getProductLineUid(line) === String(requestedUid));
2209
2154
  if (!product) {
2210
- throw new import_ResourcePlanner.AvailabilityError(
2211
- "SELF_EXCLUSION_RESOLVE_FAILED",
2212
- "无法解析编辑商品行,不能安全排除自身占用",
2213
- { productLineUid: requestedUid }
2214
- );
2155
+ throw new _ResourcePlanner.AvailabilityError('SELF_EXCLUSION_RESOLVE_FAILED', '无法解析编辑商品行,不能安全排除自身占用', {
2156
+ productLineUid: requestedUid
2157
+ });
2215
2158
  }
2216
2159
  const productUid = getProductLineUid(product);
2217
- const linkedBookingUid = String(product.booking_uid ?? ((_a = product.metadata) == null ? void 0 : _a.booking_uid) ?? "");
2218
- const linkedBookings = bookings.filter((booking) => linkedBookingUid && getBookingUid(booking) === linkedBookingUid || productUid && String(booking.product_uid ?? "") === productUid);
2160
+ const linkedBookingUid = String(product.booking_uid ?? product.metadata?.booking_uid ?? '');
2161
+ const linkedBookings = bookings.filter(booking => linkedBookingUid && getBookingUid(booking) === linkedBookingUid || productUid && String(booking.product_uid ?? '') === productUid);
2219
2162
  if (!productUid || !linkedBookings.length) {
2220
- throw new import_ResourcePlanner.AvailabilityError(
2221
- "SELF_EXCLUSION_RESOLVE_FAILED",
2222
- "编辑商品行缺少可验证的 booking 关联",
2223
- { productLineUid: requestedUid, linkedBookingUid }
2224
- );
2163
+ throw new _ResourcePlanner.AvailabilityError('SELF_EXCLUSION_RESOLVE_FAILED', '编辑商品行缺少可验证的 booking 关联', {
2164
+ productLineUid: requestedUid,
2165
+ linkedBookingUid
2166
+ });
2225
2167
  }
2226
2168
  productUids.add(productUid);
2227
- linkedBookings.forEach((booking) => {
2169
+ linkedBookings.forEach(booking => {
2228
2170
  const bookingUid = getBookingUid(booking);
2229
- if (bookingUid)
2230
- bookingUids.add(bookingUid);
2171
+ if (bookingUid) bookingUids.add(bookingUid);
2231
2172
  if (booking.schedule_event_id != null) {
2232
2173
  scheduleEventIds.add(String(booking.schedule_event_id));
2233
2174
  }
2234
2175
  });
2235
2176
  });
2236
- return { productUids, bookingUids, scheduleEventIds };
2177
+ return {
2178
+ productUids,
2179
+ bookingUids,
2180
+ scheduleEventIds
2181
+ };
2237
2182
  }
2238
2183
  occupancyIsExcluded(occupancy, exclusions) {
2239
2184
  if (occupancy.scheduleEventId != null) {
@@ -2248,37 +2193,37 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2248
2193
  return false;
2249
2194
  }
2250
2195
  collectCartResourceOccupancies(tempOrder, exclusions) {
2251
- const bookings = Array.isArray(tempOrder == null ? void 0 : tempOrder.bookings) ? tempOrder.bookings : [];
2252
- return bookings.flatMap((booking) => {
2253
- var _a;
2196
+ const bookings = Array.isArray(tempOrder?.bookings) ? tempOrder.bookings : [];
2197
+ return bookings.flatMap(booking => {
2254
2198
  const bookingUid = getBookingUid(booking);
2255
- const productUid = String(booking.product_uid ?? ((_a = booking.metadata) == null ? void 0 : _a.product_uid) ?? "");
2199
+ const productUid = String(booking.product_uid ?? booking.metadata?.product_uid ?? '');
2256
2200
  const scheduleEventId = toNumberId(booking.schedule_event_id);
2257
- const startAt = booking.start_at || `${booking.start_date || ""} ${booking.start_time || ""}`.trim();
2258
- const endAt = booking.end_at || `${booking.end_date || booking.start_date || ""} ${booking.end_time || ""}`.trim();
2201
+ const startAt = booking.start_at || `${booking.start_date || ''} ${booking.start_time || ''}`.trim();
2202
+ const endAt = booking.end_at || `${booking.end_date || booking.start_date || ''} ${booking.end_time || ''}`.trim();
2259
2203
  const resources = Array.isArray(booking.resources) ? booking.resources : [];
2260
- return resources.flatMap((resource) => {
2204
+ return resources.flatMap(resource => {
2261
2205
  const resourceId = resource.resource_id ?? resource.relation_id ?? resource.id;
2262
- if (resourceId == null || !startAt || !endAt)
2263
- return [];
2206
+ if (resourceId == null || !startAt || !endAt) return [];
2264
2207
  const range = normalizeAvailabilityLocalDateTimeRange({
2265
2208
  startAt,
2266
2209
  endAt,
2267
2210
  fixedOffsetMinutes: this.getAvailabilityRuntimeOffsetMinutes(),
2268
2211
  rollOverEnd: false
2269
2212
  });
2270
- if (!range)
2271
- return [];
2213
+ if (!range) return [];
2272
2214
  const occupancy = {
2273
2215
  resourceId,
2274
2216
  startAt: range.startAt,
2275
2217
  endAt: range.endAt,
2276
2218
  pax: Math.max(1, Number(resource.capacity ?? booking.capacity ?? 1) || 1),
2277
- source: "cart",
2219
+ source: 'cart',
2278
2220
  scheduleEventId,
2279
- bookingUid: bookingUid || void 0,
2280
- productUid: productUid || void 0,
2281
- raw: { booking, resource }
2221
+ bookingUid: bookingUid || undefined,
2222
+ productUid: productUid || undefined,
2223
+ raw: {
2224
+ booking,
2225
+ resource
2226
+ }
2282
2227
  };
2283
2228
  return this.occupancyIsExcluded(occupancy, exclusions) ? [] : [occupancy];
2284
2229
  });
@@ -2290,30 +2235,22 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2290
2235
  getAvailabilityContextEntry(contextId) {
2291
2236
  const context = this.availabilityContextRegistry.get(contextId);
2292
2237
  if (!context) {
2293
- throw this.createAvailabilityFacadeError(
2294
- "AVAILABILITY_CONTEXT_NOT_FOUND",
2295
- "availability context 不存在或已失效,请重新 prepare",
2296
- {
2297
- contextId,
2298
- lifecycleGeneration: this.availabilityLifecycleGeneration
2299
- }
2300
- );
2238
+ throw this.createAvailabilityFacadeError('AVAILABILITY_CONTEXT_NOT_FOUND', 'availability context 不存在或已失效,请重新 prepare', {
2239
+ contextId,
2240
+ lifecycleGeneration: this.availabilityLifecycleGeneration
2241
+ });
2301
2242
  }
2302
2243
  this.touchAvailabilityContext(context);
2303
2244
  return context;
2304
2245
  }
2305
2246
  getAvailabilityProjectionByKey(projectionKey) {
2306
- var _a;
2307
- if (!projectionKey)
2308
- return null;
2309
- return ((_a = this.availabilityProjectionPool.get(projectionKey)) == null ? void 0 : _a.projection) || null;
2247
+ if (!projectionKey) return null;
2248
+ return this.availabilityProjectionPool.get(projectionKey)?.projection || null;
2310
2249
  }
2311
2250
  getActiveAvailabilityProjectionEntry(context) {
2312
- if (!context.activeProjectionKey)
2313
- return null;
2251
+ if (!context.activeProjectionKey) return null;
2314
2252
  const entry = this.availabilityProjectionPool.get(context.activeProjectionKey);
2315
- if (!entry)
2316
- return null;
2253
+ if (!entry) return null;
2317
2254
  return this.touchAvailabilityProjection(entry);
2318
2255
  }
2319
2256
  decorateAvailabilityCandidate(contextId, contextVersion, candidate) {
@@ -2325,38 +2262,30 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2325
2262
  }
2326
2263
  assertAvailabilityCandidateFreshness(context, candidate) {
2327
2264
  if (candidate.availabilityContextId !== context.contextId) {
2328
- throw this.createAvailabilityFacadeError(
2329
- "AVAILABILITY_SELECTION_STALE",
2330
- "候选与 availability context 不匹配,请重新获取候选",
2331
- {
2332
- candidateContextId: candidate.availabilityContextId,
2333
- contextId: context.contextId
2334
- }
2335
- );
2265
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', '候选与 availability context 不匹配,请重新获取候选', {
2266
+ candidateContextId: candidate.availabilityContextId,
2267
+ contextId: context.contextId
2268
+ });
2336
2269
  }
2337
2270
  const currentContextVersion = context.activeVersion;
2338
2271
  if (candidate.availabilityContextVersion !== currentContextVersion) {
2339
- throw this.createAvailabilityFacadeError(
2340
- "AVAILABILITY_SELECTION_STALE",
2341
- "候选已过期,请重新获取最新时间段",
2342
- {
2343
- contextId: context.contextId,
2344
- candidateContextVersion: candidate.availabilityContextVersion,
2345
- currentContextVersion,
2346
- snapshotId: context.lastSnapshotId
2347
- }
2348
- );
2272
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', '候选已过期,请重新获取最新时间段', {
2273
+ contextId: context.contextId,
2274
+ candidateContextVersion: candidate.availabilityContextVersion,
2275
+ currentContextVersion,
2276
+ snapshotId: context.lastSnapshotId
2277
+ });
2349
2278
  }
2350
2279
  }
2351
2280
  assertContextualQueryFreshness(context, request) {
2352
- if (request.target === "time") {
2353
- request.candidates.forEach((candidate) => {
2281
+ if (request.target === 'time') {
2282
+ request.candidates.forEach(candidate => {
2354
2283
  this.assertAvailabilityCandidateFreshness(context, candidate);
2355
2284
  });
2356
2285
  return;
2357
2286
  }
2358
- if (request.target === "resource") {
2359
- request.selectedRanges.forEach((candidate) => {
2287
+ if (request.target === 'resource') {
2288
+ request.selectedRanges.forEach(candidate => {
2360
2289
  this.assertAvailabilityCandidateFreshness(context, candidate);
2361
2290
  });
2362
2291
  }
@@ -2374,7 +2303,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2374
2303
  preparedAt: params.projection.meta.preparedAt,
2375
2304
  snapshotId: params.projection.meta.snapshotId
2376
2305
  };
2377
- if ((previousContext == null ? void 0 : previousContext.activeProjectionKey) && previousContext.activeProjectionKey !== projectionKey) {
2306
+ if (previousContext?.activeProjectionKey && previousContext.activeProjectionKey !== projectionKey) {
2378
2307
  this.removeAvailabilityProjection(previousContext.activeProjectionKey);
2379
2308
  }
2380
2309
  this.availabilityProjectionPool.set(projectionKey, entry);
@@ -2385,13 +2314,13 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2385
2314
  prepareKey: params.prepareKey,
2386
2315
  activeVersion: contextVersion,
2387
2316
  activeProjectionKey: projectionKey,
2388
- createdAt: (previousContext == null ? void 0 : previousContext.createdAt) ?? params.projection.meta.preparedAt,
2389
- lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString(),
2317
+ createdAt: previousContext?.createdAt ?? params.projection.meta.preparedAt,
2318
+ lastAccessedAt: new Date().toISOString(),
2390
2319
  lastKnownOrderRevision: params.orderRevision,
2391
2320
  lastPreparedAt: params.projection.meta.preparedAt,
2392
2321
  lastSnapshotId: params.projection.meta.snapshotId,
2393
- durationCandidateAnchorAt: (previousContext == null ? void 0 : previousContext.durationCandidateAnchorAt) ?? this.getAvailabilityDurationCandidateAnchorAt(params.projection),
2394
- refreshNonce: (previousContext == null ? void 0 : previousContext.refreshNonce) ?? 0,
2322
+ durationCandidateAnchorAt: previousContext?.durationCandidateAnchorAt ?? this.getAvailabilityDurationCandidateAnchorAt(params.projection),
2323
+ refreshNonce: previousContext?.refreshNonce ?? 0,
2395
2324
  lifecycleGeneration: this.availabilityLifecycleGeneration
2396
2325
  };
2397
2326
  this.touchAvailabilityContext(nextContext);
@@ -2404,7 +2333,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2404
2333
  const dateRange = normalizedPrepareParams.dateRange;
2405
2334
  const slotStepMinutes = normalizedPrepareParams.slotStepMinutes || DEFAULT_AVAILABILITY_SLOT_STEP_MINUTES;
2406
2335
  const businessHours = normalizedPrepareParams.businessHours || DEFAULT_AVAILABILITY_BUSINESS_HOURS;
2407
- const mode = normalizedPrepareParams.mode || "appointment";
2336
+ const mode = normalizedPrepareParams.mode || 'appointment';
2408
2337
  const scheduleList = this.getAvailabilityScheduleCatalog();
2409
2338
  const operatingHours = this.buildAvailabilityOperatingHoursSnapshot({
2410
2339
  prepare: normalizedPrepareParams,
@@ -2424,39 +2353,32 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2424
2353
  products,
2425
2354
  rawResources: normalizedPrepareParams.rawResources,
2426
2355
  scheduleList,
2427
- fetchPolicy: options.resourceFetchPolicy || "default",
2356
+ fetchPolicy: options.resourceFetchPolicy || 'default',
2428
2357
  fallbackResources: options.fallbackResources
2429
2358
  });
2430
2359
  const tempOrder = this.getTempOrder();
2431
- const exclusions = this.resolveEditingOccupancyExclusions(
2432
- tempOrder,
2433
- normalizedPrepareParams.editingProductLineUids
2434
- );
2435
- const injectedRawOccupancies = (normalizedPrepareParams.rawOccupancies || []).flatMap((occupancy) => {
2360
+ const exclusions = this.resolveEditingOccupancyExclusions(tempOrder, normalizedPrepareParams.editingProductLineUids);
2361
+ const injectedRawOccupancies = (normalizedPrepareParams.rawOccupancies || []).flatMap(occupancy => {
2436
2362
  const range = normalizeAvailabilityLocalDateTimeRange({
2437
2363
  startAt: occupancy.startAt,
2438
2364
  endAt: occupancy.endAt,
2439
2365
  fixedOffsetMinutes: this.getAvailabilityRuntimeOffsetMinutes(),
2440
2366
  rollOverEnd: false
2441
2367
  });
2442
- if (!range)
2443
- return [];
2368
+ if (!range) return [];
2444
2369
  return [{
2445
2370
  ...occupancy,
2446
2371
  startAt: range.startAt,
2447
2372
  endAt: range.endAt
2448
2373
  }];
2449
2374
  });
2450
- const remoteOccupancies = [
2451
- ...loadedResources.resourceOccupancies,
2452
- ...loadedResources.includesInjectedRawOccupancies ? [] : injectedRawOccupancies
2453
- ].filter((occupancy) => !this.occupancyIsExcluded(occupancy, exclusions));
2375
+ const remoteOccupancies = [...loadedResources.resourceOccupancies, ...(loadedResources.includesInjectedRawOccupancies ? [] : injectedRawOccupancies)].filter(occupancy => !this.occupancyIsExcluded(occupancy, exclusions));
2454
2376
  const cartOccupancies = this.collectCartResourceOccupancies(tempOrder, exclusions);
2455
2377
  const preparedAt = this.getAvailabilityRuntimeDateTime();
2456
2378
  const durationCandidateAnchorAt = options.durationCandidateAnchorAt || preparedAt;
2457
2379
  this.availabilityProjectionSequence += 1;
2458
2380
  const orderRevision = this.getCurrentOrderRevision();
2459
- const projection = (0, import_ResourcePlanner.createAvailabilityProjection)({
2381
+ const projection = (0, _ResourcePlanner.createAvailabilityProjection)({
2460
2382
  products,
2461
2383
  resources: loadedResources.resources,
2462
2384
  resourceOccupancies: [...remoteOccupancies, ...cartOccupancies],
@@ -2487,38 +2409,37 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2487
2409
  async getSharedPreparedAvailabilitySnapshot(params) {
2488
2410
  const lifecycleGeneration = this.availabilityLifecycleGeneration;
2489
2411
  const normalizedParams = this.normalizeAvailabilityPrepareDescriptor(params);
2490
- const hasRawInputs = params.rawProducts !== void 0 || params.rawResources !== void 0 || params.rawOccupancies !== void 0;
2412
+ const hasRawInputs = params.rawProducts !== undefined || params.rawResources !== undefined || params.rawOccupancies !== undefined;
2491
2413
  const prepareKey = hasRawInputs ? JSON.stringify(stableValue({
2492
2414
  scope: this.getAvailabilityScopeDescriptor(),
2493
2415
  prepare: {
2494
2416
  ...normalizedParams,
2495
- rawProducts: void 0,
2496
- rawResources: void 0,
2497
- rawOccupancies: void 0
2417
+ rawProducts: undefined,
2418
+ rawResources: undefined,
2419
+ rawOccupancies: undefined
2498
2420
  },
2499
2421
  rawInputs: {
2500
- products: params.rawProducts !== void 0,
2501
- resources: params.rawResources !== void 0,
2502
- occupancies: params.rawOccupancies !== void 0
2422
+ products: params.rawProducts !== undefined,
2423
+ resources: params.rawResources !== undefined,
2424
+ occupancies: params.rawOccupancies !== undefined
2503
2425
  }
2504
2426
  })) : this.buildAvailabilityPrepareKey(normalizedParams);
2505
2427
  if (hasRawInputs) {
2506
2428
  const snapshot = await this.buildAvailabilityProjectionSnapshot(normalizedParams);
2507
2429
  if (lifecycleGeneration !== this.availabilityLifecycleGeneration) {
2508
- throw this.createAvailabilityFacadeError(
2509
- "AVAILABILITY_CONTEXT_NOT_FOUND",
2510
- "prepare 期间业务作用域或实例生命周期已变化,请重新 prepare",
2511
- {
2512
- prepareKey,
2513
- expectedLifecycleGeneration: lifecycleGeneration,
2514
- currentLifecycleGeneration: this.availabilityLifecycleGeneration
2515
- }
2516
- );
2430
+ throw this.createAvailabilityFacadeError('AVAILABILITY_CONTEXT_NOT_FOUND', 'prepare 期间业务作用域或实例生命周期已变化,请重新 prepare', {
2431
+ prepareKey,
2432
+ expectedLifecycleGeneration: lifecycleGeneration,
2433
+ currentLifecycleGeneration: this.availabilityLifecycleGeneration
2434
+ });
2517
2435
  }
2518
- return { prepareKey, snapshot };
2436
+ return {
2437
+ prepareKey,
2438
+ snapshot
2439
+ };
2519
2440
  }
2520
2441
  const existing = this.availabilityPrepareInFlight.get(prepareKey);
2521
- const promise = (existing == null ? void 0 : existing.lifecycleGeneration) === lifecycleGeneration ? existing.promise : this.buildAvailabilityProjectionSnapshot(normalizedParams);
2442
+ const promise = existing?.lifecycleGeneration === lifecycleGeneration ? existing.promise : this.buildAvailabilityProjectionSnapshot(normalizedParams);
2522
2443
  if (!existing || existing.lifecycleGeneration !== lifecycleGeneration) {
2523
2444
  this.availabilityPrepareInFlight.set(prepareKey, {
2524
2445
  lifecycleGeneration,
@@ -2529,42 +2450,36 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2529
2450
  try {
2530
2451
  const snapshot = await promise;
2531
2452
  if (lifecycleGeneration !== this.availabilityLifecycleGeneration) {
2532
- throw this.createAvailabilityFacadeError(
2533
- "AVAILABILITY_CONTEXT_NOT_FOUND",
2534
- "prepare 期间业务作用域或实例生命周期已变化,请重新 prepare",
2535
- {
2536
- prepareKey,
2537
- expectedLifecycleGeneration: lifecycleGeneration,
2538
- currentLifecycleGeneration: this.availabilityLifecycleGeneration
2539
- }
2540
- );
2453
+ throw this.createAvailabilityFacadeError('AVAILABILITY_CONTEXT_NOT_FOUND', 'prepare 期间业务作用域或实例生命周期已变化,请重新 prepare', {
2454
+ prepareKey,
2455
+ expectedLifecycleGeneration: lifecycleGeneration,
2456
+ currentLifecycleGeneration: this.availabilityLifecycleGeneration
2457
+ });
2541
2458
  }
2542
- return { prepareKey, snapshot };
2459
+ return {
2460
+ prepareKey,
2461
+ snapshot
2462
+ };
2543
2463
  } finally {
2544
2464
  const current = this.availabilityPrepareInFlight.get(prepareKey);
2545
- if ((current == null ? void 0 : current.promise) === promise) {
2465
+ if (current?.promise === promise) {
2546
2466
  this.availabilityPrepareInFlight.delete(prepareKey);
2547
2467
  }
2548
2468
  }
2549
2469
  }
2550
2470
  async refreshAvailabilityContextProjection(params) {
2551
2471
  const existingInFlight = this.availabilityProjectionRefreshInFlight.get(params.contextId);
2552
- if (existingInFlight)
2553
- return await existingInFlight;
2472
+ if (existingInFlight) return await existingInFlight;
2554
2473
  const context = this.getAvailabilityContextEntry(params.contextId);
2555
2474
  const expectedVersion = context.activeVersion;
2556
2475
  const expectedRefreshNonce = context.refreshNonce;
2557
2476
  const expectedLifecycleGeneration = this.availabilityLifecycleGeneration;
2558
2477
  const refreshPromise = (async () => {
2559
- const snapshot = await this.buildAvailabilityProjectionSnapshot(
2560
- this.cloneAvailabilityPrepareParams(context.prepareParams),
2561
- {
2562
- durationCandidateAnchorAt: context.durationCandidateAnchorAt
2563
- }
2564
- );
2478
+ const snapshot = await this.buildAvailabilityProjectionSnapshot(this.cloneAvailabilityPrepareParams(context.prepareParams), {
2479
+ durationCandidateAnchorAt: context.durationCandidateAnchorAt
2480
+ });
2565
2481
  const currentContext = this.availabilityContextRegistry.get(params.contextId);
2566
- if (!currentContext)
2567
- return null;
2482
+ if (!currentContext) return null;
2568
2483
  if (expectedLifecycleGeneration !== this.availabilityLifecycleGeneration || currentContext.activeVersion !== expectedVersion || currentContext.refreshNonce !== expectedRefreshNonce || currentContext.lifecycleGeneration !== expectedLifecycleGeneration) {
2569
2484
  return null;
2570
2485
  }
@@ -2577,7 +2492,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2577
2492
  incrementVersion: true
2578
2493
  });
2579
2494
  await this.emitAvailabilityDiagnostic({
2580
- action: "refresh",
2495
+ action: 'refresh',
2581
2496
  contextId: currentContext.contextId,
2582
2497
  contextVersion: projectionEntry.contextVersion,
2583
2498
  projection: projectionEntry.projection,
@@ -2605,7 +2520,11 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2605
2520
  const currentOrderRevision = this.getCurrentOrderRevision();
2606
2521
  const projectionEntry = this.getActiveAvailabilityProjectionEntry(context);
2607
2522
  if (projectionEntry && projectionEntry.orderRevision === currentOrderRevision) {
2608
- return { context, projectionEntry, refreshed: false };
2523
+ return {
2524
+ context,
2525
+ projectionEntry,
2526
+ refreshed: false
2527
+ };
2609
2528
  }
2610
2529
  const refreshedProjectionEntry = await this.refreshAvailabilityContextProjection({
2611
2530
  contextId,
@@ -2626,7 +2545,7 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2626
2545
  refreshed: true
2627
2546
  };
2628
2547
  }
2629
- throw new import_ResourcePlanner.AvailabilityError("STALE_PROJECTION", "availability projection 刷新期间购物车持续变化,请重新 prepare", {
2548
+ throw new _ResourcePlanner.AvailabilityError('STALE_PROJECTION', 'availability projection 刷新期间购物车持续变化,请重新 prepare', {
2630
2549
  contextId,
2631
2550
  reason
2632
2551
  });
@@ -2635,50 +2554,52 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2635
2554
  if (this.availabilityCommitLocks.has(contextId)) {
2636
2555
  const waitingContext = this.availabilityContextRegistry.get(contextId);
2637
2556
  await this.emitAvailabilityDiagnostic({
2638
- action: "commit_lock_wait",
2557
+ action: 'commit_lock_wait',
2639
2558
  contextId,
2640
- contextVersion: (waitingContext == null ? void 0 : waitingContext.activeVersion) ?? null,
2641
- projection: this.getAvailabilityProjectionByKey(waitingContext == null ? void 0 : waitingContext.activeProjectionKey),
2642
- snapshotId: waitingContext == null ? void 0 : waitingContext.lastSnapshotId,
2643
- orderRevision: waitingContext == null ? void 0 : waitingContext.lastKnownOrderRevision,
2644
- reason: "AVAILABILITY_COMMIT_IN_PROGRESS"
2559
+ contextVersion: waitingContext?.activeVersion ?? null,
2560
+ projection: this.getAvailabilityProjectionByKey(waitingContext?.activeProjectionKey),
2561
+ snapshotId: waitingContext?.lastSnapshotId,
2562
+ orderRevision: waitingContext?.lastKnownOrderRevision,
2563
+ reason: 'AVAILABILITY_COMMIT_IN_PROGRESS'
2564
+ });
2565
+ throw this.createAvailabilityFacadeError('AVAILABILITY_COMMIT_IN_PROGRESS', '同一 availability context 已有 commit 正在进行中', {
2566
+ contextId
2645
2567
  });
2646
- throw this.createAvailabilityFacadeError(
2647
- "AVAILABILITY_COMMIT_IN_PROGRESS",
2648
- "同一 availability context 已有 commit 正在进行中",
2649
- { contextId }
2650
- );
2651
2568
  }
2652
2569
  this.availabilityCommitLocks.add(contextId);
2653
2570
  const currentContext = this.availabilityContextRegistry.get(contextId);
2654
2571
  await this.emitAvailabilityDiagnostic({
2655
- action: "commit_lock_acquired",
2572
+ action: 'commit_lock_acquired',
2656
2573
  contextId,
2657
- contextVersion: (currentContext == null ? void 0 : currentContext.activeVersion) ?? null,
2658
- projection: this.getAvailabilityProjectionByKey(currentContext == null ? void 0 : currentContext.activeProjectionKey),
2659
- snapshotId: currentContext == null ? void 0 : currentContext.lastSnapshotId,
2660
- orderRevision: currentContext == null ? void 0 : currentContext.lastKnownOrderRevision,
2661
- reason: "commit_start"
2574
+ contextVersion: currentContext?.activeVersion ?? null,
2575
+ projection: this.getAvailabilityProjectionByKey(currentContext?.activeProjectionKey),
2576
+ snapshotId: currentContext?.lastSnapshotId,
2577
+ orderRevision: currentContext?.lastKnownOrderRevision,
2578
+ reason: 'commit_start'
2662
2579
  });
2663
2580
  }
2664
2581
  async releaseAvailabilityCommitLock(contextId) {
2665
2582
  this.availabilityCommitLocks.delete(contextId);
2666
2583
  const releasedContext = this.availabilityContextRegistry.get(contextId);
2667
2584
  await this.emitAvailabilityDiagnostic({
2668
- action: "commit_lock_released",
2585
+ action: 'commit_lock_released',
2669
2586
  contextId,
2670
- contextVersion: (releasedContext == null ? void 0 : releasedContext.activeVersion) ?? null,
2671
- projection: this.getAvailabilityProjectionByKey(releasedContext == null ? void 0 : releasedContext.activeProjectionKey),
2672
- snapshotId: releasedContext == null ? void 0 : releasedContext.lastSnapshotId,
2673
- orderRevision: releasedContext == null ? void 0 : releasedContext.lastKnownOrderRevision,
2674
- reason: "commit_end"
2587
+ contextVersion: releasedContext?.activeVersion ?? null,
2588
+ projection: this.getAvailabilityProjectionByKey(releasedContext?.activeProjectionKey),
2589
+ snapshotId: releasedContext?.lastSnapshotId,
2590
+ orderRevision: releasedContext?.lastKnownOrderRevision,
2591
+ reason: 'commit_end'
2675
2592
  });
2676
2593
  }
2594
+
2677
2595
  /** IO boundary: loads catalog, schedules, resources, occupancies, and registers one context. */
2678
2596
  async prepareAvailabilityProjection(params) {
2679
2597
  this.assertAvailabilityPrepareParams(params);
2680
2598
  const paramsWithDefaults = await this.resolveAvailabilityPrepareDefaults(params);
2681
- const { prepareKey, snapshot } = await this.getSharedPreparedAvailabilitySnapshot(paramsWithDefaults);
2599
+ const {
2600
+ prepareKey,
2601
+ snapshot
2602
+ } = await this.getSharedPreparedAvailabilitySnapshot(paramsWithDefaults);
2682
2603
  const contextId = this.createAvailabilityContextId();
2683
2604
  const projectionEntry = this.storeAvailabilityProjectionEntry({
2684
2605
  contextId,
@@ -2695,62 +2616,59 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2695
2616
  contextVersion: context.activeVersion,
2696
2617
  projection: projectionEntry.projection,
2697
2618
  refreshed: false,
2698
- reason: "prepare"
2619
+ reason: 'prepare'
2699
2620
  };
2700
2621
  await this.emitAvailabilityDiagnostic({
2701
- action: "prepare",
2622
+ action: 'prepare',
2702
2623
  contextId,
2703
2624
  contextVersion: context.activeVersion,
2704
2625
  projection: projectionEntry.projection,
2705
2626
  snapshotId: context.lastSnapshotId,
2706
2627
  orderRevision: context.lastKnownOrderRevision,
2707
- reason: "prepare"
2628
+ reason: 'prepare'
2708
2629
  });
2709
- await this.core.effects.emit(
2710
- `${this.name}:${import_types.UnifiedBookingSalesHooks.onAvailabilityProjectionPrepared}`,
2711
- payload
2712
- );
2630
+ await this.core.effects.emit(`${this.name}:${_types.UnifiedBookingSalesHooks.onAvailabilityProjectionPrepared}`, payload);
2713
2631
  return handle;
2714
2632
  }
2633
+
2715
2634
  /** Pure configuration calculation over the current context projection. */
2716
2635
  async getProductTimeRanges(contextId, request = {}) {
2717
- const { context, projectionEntry } = await this.ensureAvailabilityContextProjection(
2718
- contextId,
2719
- "get_product_time_ranges"
2720
- );
2636
+ const {
2637
+ context,
2638
+ projectionEntry
2639
+ } = await this.ensureAvailabilityContextProjection(contextId, 'get_product_time_ranges');
2721
2640
  const contextVersion = context.activeVersion;
2722
- return (0, import_ResourcePlanner.getProductTimeRanges)(projectionEntry.projection, request).map((group) => ({
2641
+ return (0, _ResourcePlanner.getProductTimeRanges)(projectionEntry.projection, request).map(group => ({
2723
2642
  ...group,
2724
- ranges: group.ranges.map((candidate) => this.decorateAvailabilityCandidate(context.contextId, contextVersion, candidate))
2643
+ ranges: group.ranges.map(candidate => this.decorateAvailabilityCandidate(context.contextId, contextVersion, candidate))
2725
2644
  }));
2726
2645
  }
2646
+
2727
2647
  /** Thin facade: auto-refresh on cart drift, then delegate to the pure projection query. */
2728
2648
  async queryBookingAvailability(contextId, request) {
2729
- const { context, projectionEntry, refreshed } = await this.ensureAvailabilityContextProjection(
2730
- contextId,
2731
- "query_booking_availability"
2732
- );
2649
+ const {
2650
+ context,
2651
+ projectionEntry,
2652
+ refreshed
2653
+ } = await this.ensureAvailabilityContextProjection(contextId, 'query_booking_availability');
2733
2654
  this.assertContextualQueryFreshness(context, request);
2734
- const result = (0, import_ResourcePlanner.queryAvailabilityProjection)(
2735
- projectionEntry.projection,
2736
- request
2737
- );
2655
+ const result = (0, _ResourcePlanner.queryAvailabilityProjection)(projectionEntry.projection, request);
2738
2656
  const contextVersion = context.activeVersion;
2739
- const contextualResult = result.target === "time" ? {
2657
+ const contextualResult = result.target === 'time' ? {
2740
2658
  ...result,
2741
- data: result.data.map((group) => ({
2659
+ data: result.data.map(group => ({
2742
2660
  ...group,
2743
- times: group.times.map((item) => ({
2661
+ times: group.times.map(item => ({
2744
2662
  ...item,
2745
2663
  availabilityContextId: context.contextId,
2746
2664
  availabilityContextVersion: contextVersion
2747
2665
  }))
2748
2666
  }))
2749
- } : result.target === "resource" ? {
2667
+ } : result.target === 'resource' ? {
2750
2668
  ...result,
2751
- data: result.data.map((group) => ({
2669
+ data: result.data.map(group => ({
2752
2670
  ...group,
2753
- ranges: group.ranges.map((rangeGroup) => ({
2671
+ ranges: group.ranges.map(rangeGroup => ({
2754
2672
  ...rangeGroup,
2755
2673
  range: {
2756
2674
  ...rangeGroup.range,
@@ -2768,65 +2686,55 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2768
2686
  };
2769
2687
  }
2770
2688
  releaseAvailabilityContext(contextId) {
2771
- var _a;
2772
2689
  const context = this.availabilityContextRegistry.get(contextId);
2773
- if (!context)
2774
- return;
2690
+ if (!context) return;
2775
2691
  this.removeAvailabilityContext(contextId);
2776
2692
  void this.emitAvailabilityDiagnostic({
2777
- action: "release",
2693
+ action: 'release',
2778
2694
  contextId,
2779
2695
  contextVersion: context.activeVersion,
2780
- projection: ((_a = this.getActiveAvailabilityProjectionEntry(context)) == null ? void 0 : _a.projection) || null,
2696
+ projection: this.getActiveAvailabilityProjectionEntry(context)?.projection || null,
2781
2697
  snapshotId: context.lastSnapshotId,
2782
2698
  orderRevision: context.lastKnownOrderRevision,
2783
- reason: "explicit_release"
2699
+ reason: 'explicit_release'
2784
2700
  });
2785
2701
  }
2786
2702
  assertAvailabilityCommitWriteCAS(params) {
2787
2703
  const context = this.availabilityContextRegistry.get(params.contextId);
2788
2704
  if (!context) {
2789
- throw this.createAvailabilityFacadeError(
2790
- "AVAILABILITY_CONTEXT_NOT_FOUND",
2791
- "availability context 不存在或已失效,请重新 prepare",
2792
- { contextId: params.contextId }
2793
- );
2705
+ throw this.createAvailabilityFacadeError('AVAILABILITY_CONTEXT_NOT_FOUND', 'availability context 不存在或已失效,请重新 prepare', {
2706
+ contextId: params.contextId
2707
+ });
2794
2708
  }
2795
2709
  if (this.availabilityLifecycleGeneration !== params.expectedLifecycleGeneration || context.lifecycleGeneration !== params.expectedLifecycleGeneration || context.activeVersion !== params.expectedVersion || context.refreshNonce !== params.expectedRefreshNonce || this.getCurrentOrderRevision() !== params.expectedOrderRevision) {
2796
- throw this.createAvailabilityFacadeError(
2797
- "AVAILABILITY_SELECTION_STALE",
2798
- "availability context 已变化,当前选择已失效,请重新获取候选",
2799
- {
2800
- contextId: params.contextId,
2801
- expectedVersion: params.expectedVersion,
2802
- currentVersion: context.activeVersion,
2803
- expectedRefreshNonce: params.expectedRefreshNonce,
2804
- currentRefreshNonce: context.refreshNonce,
2805
- expectedLifecycleGeneration: params.expectedLifecycleGeneration,
2806
- currentLifecycleGeneration: this.availabilityLifecycleGeneration,
2807
- expectedOrderRevision: params.expectedOrderRevision,
2808
- currentOrderRevision: this.getCurrentOrderRevision()
2809
- }
2810
- );
2710
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', 'availability context 已变化,当前选择已失效,请重新获取候选', {
2711
+ contextId: params.contextId,
2712
+ expectedVersion: params.expectedVersion,
2713
+ currentVersion: context.activeVersion,
2714
+ expectedRefreshNonce: params.expectedRefreshNonce,
2715
+ currentRefreshNonce: context.refreshNonce,
2716
+ expectedLifecycleGeneration: params.expectedLifecycleGeneration,
2717
+ currentLifecycleGeneration: this.availabilityLifecycleGeneration,
2718
+ expectedOrderRevision: params.expectedOrderRevision,
2719
+ currentOrderRevision: this.getCurrentOrderRevision()
2720
+ });
2811
2721
  }
2812
2722
  return context;
2813
2723
  }
2814
2724
  findProductLineByUid(productLineUid) {
2815
- var _a;
2816
- return (((_a = this.getTempOrder()) == null ? void 0 : _a.products) || []).find((product) => getProductLineUid(product) === String(productLineUid));
2725
+ return (this.getTempOrder()?.products || []).find(product => getProductLineUid(product) === String(productLineUid));
2817
2726
  }
2818
2727
  findLinkedBooking(product) {
2819
- var _a, _b;
2820
2728
  const productUid = getProductLineUid(product);
2821
- const bookingUid = String(product.booking_uid ?? ((_a = product.metadata) == null ? void 0 : _a.booking_uid) ?? "");
2822
- return (((_b = this.getTempOrder()) == null ? void 0 : _b.bookings) || []).find((booking) => bookingUid && getBookingUid(booking) === bookingUid || productUid && String(booking.product_uid ?? "") === productUid);
2729
+ const bookingUid = String(product.booking_uid ?? product.metadata?.booking_uid ?? '');
2730
+ return (this.getTempOrder()?.bookings || []).find(booking => bookingUid && getBookingUid(booking) === bookingUid || productUid && String(booking.product_uid ?? '') === productUid);
2823
2731
  }
2732
+
2824
2733
  /** Revalidates against the latest landed occupancy cache, then mutates exactly one product line. */
2825
2734
  async commitAvailabilitySelection(contextId, params) {
2826
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
2827
- const normalizedContextId = String(contextId || "").trim();
2735
+ const normalizedContextId = String(contextId || '').trim();
2828
2736
  if (!normalizedContextId) {
2829
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "commitAvailabilitySelection 缺少 contextId", {
2737
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'commitAvailabilitySelection 缺少 contextId', {
2830
2738
  candidate: params.candidate
2831
2739
  });
2832
2740
  }
@@ -2834,25 +2742,25 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2834
2742
  try {
2835
2743
  const bookingCount = Number(params.bookingCount ?? 1);
2836
2744
  if (!Number.isInteger(bookingCount) || bookingCount <= 0) {
2837
- throw new import_ResourcePlanner.AvailabilityError("INVALID_RESERVATION_QUANTITY", "bookingCount 必须是正整数", {
2745
+ throw new _ResourcePlanner.AvailabilityError('INVALID_RESERVATION_QUANTITY', 'bookingCount 必须是正整数', {
2838
2746
  bookingCount: params.bookingCount
2839
2747
  });
2840
2748
  }
2841
- if (params.mode === "edit" && bookingCount !== 1) {
2842
- throw new import_ResourcePlanner.AvailabilityError("INVALID_RESERVATION_QUANTITY", "编辑预约商品时 bookingCount 必须为 1", {
2749
+ if (params.mode === 'edit' && bookingCount !== 1) {
2750
+ throw new _ResourcePlanner.AvailabilityError('INVALID_RESERVATION_QUANTITY', '编辑预约商品时 bookingCount 必须为 1', {
2843
2751
  bookingCount
2844
2752
  });
2845
2753
  }
2846
- const orderProductQuantity = ((_a = params.orderProduct) == null ? void 0 : _a.num) ?? ((_b = params.orderProduct) == null ? void 0 : _b.quantity) ?? ((_d = (_c = params.orderProduct) == null ? void 0 : _c._extend) == null ? void 0 : _d.quantity);
2847
- if (orderProductQuantity !== void 0 && orderProductQuantity !== null && Number(orderProductQuantity) !== bookingCount) {
2848
- throw new import_ResourcePlanner.AvailabilityError("INVALID_RESERVATION_QUANTITY", "orderProduct 数量与 bookingCount 不一致", {
2754
+ const orderProductQuantity = params.orderProduct?.num ?? params.orderProduct?.quantity ?? params.orderProduct?._extend?.quantity;
2755
+ if (orderProductQuantity !== undefined && orderProductQuantity !== null && Number(orderProductQuantity) !== bookingCount) {
2756
+ throw new _ResourcePlanner.AvailabilityError('INVALID_RESERVATION_QUANTITY', 'orderProduct 数量与 bookingCount 不一致', {
2849
2757
  bookingCount,
2850
2758
  orderProductQuantity
2851
2759
  });
2852
2760
  }
2853
2761
  const partySize = Number(params.partySize);
2854
2762
  if (!Number.isInteger(partySize) || partySize <= 0) {
2855
- throw new import_ResourcePlanner.AvailabilityError("INVALID_RESERVATION_QUANTITY", "partySize 必须是正整数", {
2763
+ throw new _ResourcePlanner.AvailabilityError('INVALID_RESERVATION_QUANTITY', 'partySize 必须是正整数', {
2856
2764
  partySize: params.partySize
2857
2765
  });
2858
2766
  }
@@ -2860,104 +2768,77 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2860
2768
  context,
2861
2769
  projectionEntry,
2862
2770
  refreshed
2863
- } = await this.ensureAvailabilityContextProjection(
2864
- normalizedContextId,
2865
- "commit_precheck"
2866
- );
2771
+ } = await this.ensureAvailabilityContextProjection(normalizedContextId, 'commit_precheck');
2867
2772
  if (refreshed) {
2868
- throw this.createAvailabilityFacadeError(
2869
- "AVAILABILITY_SELECTION_STALE",
2870
- "availability context 已刷新,请重新获取候选",
2871
- {
2872
- contextId: normalizedContextId,
2873
- currentContextVersion: context.activeVersion,
2874
- candidateContextVersion: params.candidate.availabilityContextVersion
2875
- }
2876
- );
2773
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', 'availability context 已刷新,请重新获取候选', {
2774
+ contextId: normalizedContextId,
2775
+ currentContextVersion: context.activeVersion,
2776
+ candidateContextVersion: params.candidate.availabilityContextVersion
2777
+ });
2877
2778
  }
2878
2779
  const boundEditingUids = context.prepareParams.editingProductLineUids || [];
2879
- if (params.mode === "edit") {
2780
+ if (params.mode === 'edit') {
2880
2781
  if (!params.productLineUid || !boundEditingUids.includes(String(params.productLineUid))) {
2881
- throw this.createAvailabilityFacadeError(
2882
- "AVAILABILITY_SELECTION_STALE",
2883
- "edit context 与当前商品行不匹配,请重新 prepare 编辑上下文",
2884
- {
2885
- contextId: normalizedContextId,
2886
- productLineUid: params.productLineUid,
2887
- editingProductLineUids: boundEditingUids
2888
- }
2889
- );
2890
- }
2891
- } else if (boundEditingUids.length > 0) {
2892
- throw this.createAvailabilityFacadeError(
2893
- "AVAILABILITY_SELECTION_STALE",
2894
- "edit context 不能用于 add,请重新 prepare 新增上下文",
2895
- {
2782
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', 'edit context 与当前商品行不匹配,请重新 prepare 编辑上下文', {
2896
2783
  contextId: normalizedContextId,
2784
+ productLineUid: params.productLineUid,
2897
2785
  editingProductLineUids: boundEditingUids
2898
- }
2899
- );
2786
+ });
2787
+ }
2788
+ } else if (boundEditingUids.length > 0) {
2789
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', 'edit context 不能用于 add,请重新 prepare 新增上下文', {
2790
+ contextId: normalizedContextId,
2791
+ editingProductLineUids: boundEditingUids
2792
+ });
2900
2793
  }
2901
2794
  if (projectionEntry.contextVersion !== context.activeVersion) {
2902
- throw this.createAvailabilityFacadeError(
2903
- "AVAILABILITY_SELECTION_STALE",
2904
- "availability context 已刷新,请重新获取候选",
2905
- {
2906
- contextId: normalizedContextId,
2907
- currentContextVersion: context.activeVersion,
2908
- projectionContextVersion: projectionEntry.contextVersion
2909
- }
2910
- );
2795
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', 'availability context 已刷新,请重新获取候选', {
2796
+ contextId: normalizedContextId,
2797
+ currentContextVersion: context.activeVersion,
2798
+ projectionContextVersion: projectionEntry.contextVersion
2799
+ });
2911
2800
  }
2912
2801
  if (projectionEntry.orderRevision !== this.getCurrentOrderRevision()) {
2913
- throw this.createAvailabilityFacadeError(
2914
- "AVAILABILITY_SELECTION_STALE",
2915
- "购物车已变化,请重新获取候选",
2916
- {
2917
- contextId: normalizedContextId,
2918
- currentContextVersion: context.activeVersion,
2919
- projectionOrderRevision: projectionEntry.orderRevision,
2920
- currentOrderRevision: this.getCurrentOrderRevision()
2921
- }
2922
- );
2802
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', '购物车已变化,请重新获取候选', {
2803
+ contextId: normalizedContextId,
2804
+ currentContextVersion: context.activeVersion,
2805
+ projectionOrderRevision: projectionEntry.orderRevision,
2806
+ currentOrderRevision: this.getCurrentOrderRevision()
2807
+ });
2923
2808
  }
2924
2809
  if (projectionEntry.contextVersion !== params.candidate.availabilityContextVersion) {
2925
- throw this.createAvailabilityFacadeError(
2926
- "AVAILABILITY_SELECTION_STALE",
2927
- "候选已过期,请重新获取最新时间段",
2928
- {
2929
- contextId: normalizedContextId,
2930
- candidateContextVersion: params.candidate.availabilityContextVersion,
2931
- currentContextVersion: context.activeVersion
2932
- }
2933
- );
2810
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', '候选已过期,请重新获取最新时间段', {
2811
+ contextId: normalizedContextId,
2812
+ candidateContextVersion: params.candidate.availabilityContextVersion,
2813
+ currentContextVersion: context.activeVersion
2814
+ });
2934
2815
  }
2935
2816
  this.assertAvailabilityCandidateFreshness(context, params.candidate);
2936
- const orderProductId = ((_e = params.orderProduct) == null ? void 0 : _e.product_id) ?? ((_f = params.orderProduct) == null ? void 0 : _f.id);
2817
+ const orderProductId = params.orderProduct?.product_id ?? params.orderProduct?.id;
2937
2818
  if (!sameAvailabilityId(orderProductId, params.candidate.productId)) {
2938
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "orderProduct 与 candidate 商品不一致", {
2819
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'orderProduct 与 candidate 商品不一致', {
2939
2820
  orderProductId,
2940
2821
  candidateProductId: params.candidate.productId
2941
2822
  });
2942
2823
  }
2943
- if (params.mode === "edit" && !params.productLineUid) {
2944
- throw new import_ResourcePlanner.AvailabilityError("PRODUCT_LINE_NOT_FOUND", "edit 模式必须提供 productLineUid");
2824
+ if (params.mode === 'edit' && !params.productLineUid) {
2825
+ throw new _ResourcePlanner.AvailabilityError('PRODUCT_LINE_NOT_FOUND', 'edit 模式必须提供 productLineUid');
2945
2826
  }
2946
- const editingLine = params.mode === "edit" ? this.findProductLineByUid(String(params.productLineUid)) : void 0;
2947
- if (params.mode === "edit" && !editingLine) {
2948
- throw new import_ResourcePlanner.AvailabilityError("PRODUCT_LINE_NOT_FOUND", "找不到要编辑的预约商品行", {
2827
+ const editingLine = params.mode === 'edit' ? this.findProductLineByUid(String(params.productLineUid)) : undefined;
2828
+ if (params.mode === 'edit' && !editingLine) {
2829
+ throw new _ResourcePlanner.AvailabilityError('PRODUCT_LINE_NOT_FOUND', '找不到要编辑的预约商品行', {
2949
2830
  productLineUid: params.productLineUid
2950
2831
  });
2951
2832
  }
2952
2833
  if (editingLine && !sameAvailabilityId(editingLine.product_id ?? editingLine.id, params.candidate.productId)) {
2953
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "编辑商品行与 candidate 商品不一致", {
2834
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', '编辑商品行与 candidate 商品不一致', {
2954
2835
  productLineUid: params.productLineUid,
2955
2836
  productLineProductId: editingLine.product_id ?? editingLine.id,
2956
2837
  candidateProductId: params.candidate.productId
2957
2838
  });
2958
2839
  }
2959
2840
  if (!Array.isArray(params.requirementSelections)) {
2960
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "requirementSelections 必须是数组", {
2841
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'requirementSelections 必须是数组', {
2961
2842
  requirementSelections: params.requirementSelections
2962
2843
  });
2963
2844
  }
@@ -2967,82 +2848,75 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
2967
2848
  expectedVersion: context.activeVersion,
2968
2849
  expectedRefreshNonce: context.refreshNonce,
2969
2850
  expectedLifecycleGeneration: this.availabilityLifecycleGeneration,
2970
- expectedOrderRevision: String(baseProjection.meta.orderRevision ?? "")
2851
+ expectedOrderRevision: String(baseProjection.meta.orderRevision ?? '')
2971
2852
  };
2972
2853
  const prepareParams = baseProjection.meta.prepareParams;
2973
2854
  if (!prepareParams) {
2974
- throw new import_ResourcePlanner.AvailabilityError("REVALIDATION_FAILED", "projection 缺少 prepareParams,无法执行缓存重校验");
2855
+ throw new _ResourcePlanner.AvailabilityError('REVALIDATION_FAILED', 'projection 缺少 prepareParams,无法执行缓存重校验');
2975
2856
  }
2976
2857
  const fallbackResources = {
2977
- resources: (0, import_lodash_es.cloneDeep)([...baseProjection.resources || []]),
2978
- resourceOccupancies: (0, import_lodash_es.cloneDeep)(
2979
- [...baseProjection.resourceOccupancies || []].filter((occupancy) => occupancy.source !== "cart")
2980
- ),
2858
+ resources: (0, _lodashEs.cloneDeep)([...(baseProjection.resources || [])]),
2859
+ resourceOccupancies: (0, _lodashEs.cloneDeep)([...(baseProjection.resourceOccupancies || [])].filter(occupancy => occupancy.source !== 'cart')),
2981
2860
  includesInjectedRawOccupancies: true
2982
2861
  };
2983
2862
  const commitSnapshot = await this.buildAvailabilityProjectionSnapshot({
2984
2863
  ...this.cloneAvailabilityPrepareParams(prepareParams),
2985
- editingProductLineUids: params.mode === "edit" && params.productLineUid ? [params.productLineUid] : []
2864
+ editingProductLineUids: params.mode === 'edit' && params.productLineUid ? [params.productLineUid] : []
2986
2865
  }, {
2987
- resourceFetchPolicy: "cache_only",
2866
+ resourceFetchPolicy: 'cache_only',
2988
2867
  fallbackResources,
2989
2868
  durationCandidateAnchorAt: this.getAvailabilityDurationCandidateAnchorAt(baseProjection) || context.durationCandidateAnchorAt
2990
2869
  });
2991
2870
  const refreshedProjection = commitSnapshot.projection;
2992
- if (String(refreshedProjection.meta.orderRevision ?? "") !== String(baseProjection.meta.orderRevision ?? "")) {
2871
+ if (String(refreshedProjection.meta.orderRevision ?? '') !== String(baseProjection.meta.orderRevision ?? '')) {
2993
2872
  await this.refreshAvailabilityContextProjection({
2994
2873
  contextId: normalizedContextId,
2995
- reason: "commit_order_revision_changed",
2996
- previousOrderRevision: String(baseProjection.meta.orderRevision ?? "")
2874
+ reason: 'commit_order_revision_changed',
2875
+ previousOrderRevision: String(baseProjection.meta.orderRevision ?? '')
2997
2876
  });
2998
2877
  const latestContext = this.getAvailabilityContextEntry(normalizedContextId);
2999
- throw this.createAvailabilityFacadeError(
3000
- "AVAILABILITY_SELECTION_STALE",
3001
- "最终缓存重校验期间购物车已变化,请重新获取候选",
3002
- {
3003
- contextId: normalizedContextId,
3004
- candidateContextVersion: params.candidate.availabilityContextVersion,
3005
- currentContextVersion: latestContext.activeVersion,
3006
- projectionOrderRevision: baseProjection.meta.orderRevision,
3007
- refreshedOrderRevision: refreshedProjection.meta.orderRevision,
3008
- snapshotId: baseProjection.meta.snapshotId,
3009
- refreshedSnapshotId: refreshedProjection.meta.snapshotId
3010
- }
3011
- );
2878
+ throw this.createAvailabilityFacadeError('AVAILABILITY_SELECTION_STALE', '最终缓存重校验期间购物车已变化,请重新获取候选', {
2879
+ contextId: normalizedContextId,
2880
+ candidateContextVersion: params.candidate.availabilityContextVersion,
2881
+ currentContextVersion: latestContext.activeVersion,
2882
+ projectionOrderRevision: baseProjection.meta.orderRevision,
2883
+ refreshedOrderRevision: refreshedProjection.meta.orderRevision,
2884
+ snapshotId: baseProjection.meta.snapshotId,
2885
+ refreshedSnapshotId: refreshedProjection.meta.snapshotId
2886
+ });
3012
2887
  }
3013
2888
  this.assertAvailabilityCommitWriteCAS(commitWriteGuard);
3014
- const refreshedRanges = (0, import_ResourcePlanner.getProductTimeRanges)(refreshedProjection, {
2889
+ const refreshedRanges = (0, _ResourcePlanner.getProductTimeRanges)(refreshedProjection, {
3015
2890
  productIds: [params.candidate.productId],
3016
2891
  dateRange: {
3017
2892
  startDate: params.candidate.startAt.slice(0, 10),
3018
2893
  endDate: params.candidate.startAt.slice(0, 10)
3019
2894
  }
3020
- }).flatMap((group) => group.ranges);
3021
- const refreshedCandidateBase = refreshedRanges.find((candidate) => candidate.startAt === params.candidate.startAt && candidate.endAt === params.candidate.endAt && candidate.bookingStartAt === params.candidate.bookingStartAt && candidate.bookingEndAt === params.candidate.bookingEndAt);
2895
+ }).flatMap(group => group.ranges);
2896
+ const refreshedCandidateBase = refreshedRanges.find(candidate => candidate.startAt === params.candidate.startAt && candidate.endAt === params.candidate.endAt && candidate.bookingStartAt === params.candidate.bookingStartAt && candidate.bookingEndAt === params.candidate.bookingEndAt);
3022
2897
  if (!refreshedCandidateBase) {
3023
- throw new import_ResourcePlanner.AvailabilityError("REVALIDATION_FAILED", "缓存重校验后候选时间已不在商品配置中", {
2898
+ throw new _ResourcePlanner.AvailabilityError('REVALIDATION_FAILED', '缓存重校验后候选时间已不在商品配置中', {
3024
2899
  contextId: normalizedContextId,
3025
2900
  candidate: params.candidate,
3026
2901
  refreshedSnapshotId: refreshedProjection.meta.snapshotId
3027
2902
  });
3028
2903
  }
3029
- const validation = (0, import_ResourcePlanner.validateAvailabilitySelection)(refreshedProjection, {
2904
+ const validation = (0, _ResourcePlanner.validateAvailabilitySelection)(refreshedProjection, {
3030
2905
  candidate: refreshedCandidateBase,
3031
2906
  requirementSelections: params.requirementSelections,
3032
2907
  partySize,
3033
2908
  bookingCount
3034
2909
  });
3035
2910
  if (!validation.ok) {
3036
- const capacityConflict = validation.conflicts.find((conflict) => conflict.code === "resource_capacity_exceeded");
3037
- throw new import_ResourcePlanner.AvailabilityError(
3038
- "REVALIDATION_FAILED",
3039
- (capacityConflict == null ? void 0 : capacityConflict.message) || "缓存重校验后资源已不可提交",
3040
- {
3041
- validation,
3042
- refreshedSnapshotId: refreshedProjection.meta.snapshotId
3043
- }
3044
- );
2911
+ const capacityConflict = validation.conflicts.find(conflict => conflict.code === 'resource_capacity_exceeded');
2912
+ throw new _ResourcePlanner.AvailabilityError('REVALIDATION_FAILED', capacityConflict?.message || '缓存重校验后资源已不可提交', {
2913
+ validation,
2914
+ refreshedSnapshotId: refreshedProjection.meta.snapshotId
2915
+ });
3045
2916
  }
2917
+ // Revalidation failure must leave the caller's candidate reusable. Only publish the
2918
+ // refreshed projection/version after candidate and resource validation has passed;
2919
+ // otherwise a second Confirm from the still-open modal would incorrectly become stale.
3046
2920
  const revalidationEntry = this.storeAvailabilityProjectionEntry({
3047
2921
  contextId: normalizedContextId,
3048
2922
  prepareParams: commitSnapshot.prepareParams,
@@ -3053,14 +2927,14 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
3053
2927
  });
3054
2928
  const revalidatedContext = this.getAvailabilityContextEntry(normalizedContextId);
3055
2929
  await this.emitAvailabilityDiagnostic({
3056
- action: "refresh",
2930
+ action: 'refresh',
3057
2931
  contextId: normalizedContextId,
3058
2932
  contextVersion: revalidatedContext.activeVersion,
3059
2933
  projection: refreshedProjection,
3060
2934
  snapshotId: revalidationEntry.snapshotId,
3061
2935
  orderRevision: revalidationEntry.orderRevision,
3062
2936
  previousOrderRevision: baseProjection.meta.orderRevision,
3063
- reason: "commit_cached_occupancy_revalidation"
2937
+ reason: 'commit_cached_occupancy_revalidation'
3064
2938
  });
3065
2939
  commitWriteGuard = {
3066
2940
  contextId: normalizedContextId,
@@ -3069,21 +2943,17 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
3069
2943
  expectedLifecycleGeneration: this.availabilityLifecycleGeneration,
3070
2944
  expectedOrderRevision: revalidationEntry.orderRevision
3071
2945
  };
3072
- const refreshedCandidate = this.decorateAvailabilityCandidate(
3073
- normalizedContextId,
3074
- revalidatedContext.activeVersion,
3075
- refreshedCandidateBase
3076
- );
3077
- const product = refreshedProjection.products.find((item) => sameAvailabilityId(item.id, refreshedCandidate.productId));
2946
+ const refreshedCandidate = this.decorateAvailabilityCandidate(normalizedContextId, revalidatedContext.activeVersion, refreshedCandidateBase);
2947
+ const product = refreshedProjection.products.find(item => sameAvailabilityId(item.id, refreshedCandidate.productId));
3078
2948
  if (!product) {
3079
- throw new import_ResourcePlanner.AvailabilityError("REVALIDATION_FAILED", "缓存重校验后商品不在 projection 中", {
2949
+ throw new _ResourcePlanner.AvailabilityError('REVALIDATION_FAILED', '缓存重校验后商品不在 projection 中', {
3080
2950
  productId: refreshedCandidate.productId
3081
2951
  });
3082
2952
  }
3083
- const existingBooking = editingLine ? this.findLinkedBooking(editingLine) : void 0;
3084
- const existingBookingUid = existingBooking ? getBookingUid(existingBooking) : "";
3085
- if (params.mode === "edit" && !existingBookingUid) {
3086
- throw new import_ResourcePlanner.AvailabilityError("PRODUCT_LINE_NOT_FOUND", "编辑商品行缺少关联 booking", {
2953
+ const existingBooking = editingLine ? this.findLinkedBooking(editingLine) : undefined;
2954
+ const existingBookingUid = existingBooking ? getBookingUid(existingBooking) : '';
2955
+ if (params.mode === 'edit' && !existingBookingUid) {
2956
+ throw new _ResourcePlanner.AvailabilityError('PRODUCT_LINE_NOT_FOUND', '编辑商品行缺少关联 booking', {
3087
2957
  productLineUid: params.productLineUid
3088
2958
  });
3089
2959
  }
@@ -3093,39 +2963,39 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
3093
2963
  candidate: refreshedCandidate,
3094
2964
  product,
3095
2965
  resources: refreshedProjection.resources,
3096
- bookingUid: existingBookingUid || void 0,
3097
- holder: ((_h = (_g = params.orderProduct) == null ? void 0 : _g._extend) == null ? void 0 : _h.holder) ?? (existingBooking == null ? void 0 : existingBooking.holder) ?? ((_i = existingBooking == null ? void 0 : existingBooking.metadata) == null ? void 0 : _i.holder),
3098
- holderIds: ((_k = (_j = params.orderProduct) == null ? void 0 : _j._extend) == null ? void 0 : _k.holder_id) ?? ((_n = (_m = (_l = params.orderProduct) == null ? void 0 : _l._extend) == null ? void 0 : _m.holder) == null ? void 0 : _n.form_record) ?? ((_o = existingBooking == null ? void 0 : existingBooking.metadata) == null ? void 0 : _o.holder_id) ?? ((_p = existingBooking == null ? void 0 : existingBooking.holder) == null ? void 0 : _p.form_record)
2966
+ bookingUid: existingBookingUid || undefined,
2967
+ holder: params.orderProduct?._extend?.holder ?? existingBooking?.holder ?? existingBooking?.metadata?.holder,
2968
+ holderIds: params.orderProduct?._extend?.holder_id ?? params.orderProduct?._extend?.holder?.form_record ?? existingBooking?.metadata?.holder_id ?? existingBooking?.holder?.form_record
3099
2969
  });
3100
2970
  const transformed = this.buildUnifiedOrderProduct({
3101
2971
  ...params.orderProduct,
3102
2972
  num: bookingCount,
3103
2973
  quantity: bookingCount
3104
- }, "unified_booking_sales", product);
2974
+ }, 'unified_booking_sales', product);
3105
2975
  if (!transformed) {
3106
- throw new import_ResourcePlanner.AvailabilityError("INVALID_TARGET_FILTER", "orderProduct 无法转换为订单行", {
2976
+ throw new _ResourcePlanner.AvailabilityError('INVALID_TARGET_FILTER', 'orderProduct 无法转换为订单行', {
3107
2977
  orderProduct: params.orderProduct
3108
2978
  });
3109
2979
  }
3110
2980
  transformed.num = bookingCount;
3111
2981
  transformed.metadata = {
3112
- ...transformed.metadata || {},
2982
+ ...(transformed.metadata || {}),
3113
2983
  unified_booking_sales: true,
3114
2984
  availability_candidate_key: refreshedCandidate.key,
3115
2985
  availability_context_id: normalizedContextId,
3116
2986
  availability_context_version: refreshedCandidate.availabilityContextVersion
3117
2987
  };
3118
- let productLineUid = "";
3119
- let bookingUid = "";
2988
+ let productLineUid = '';
2989
+ let bookingUid = '';
3120
2990
  let productLineUids = [];
3121
2991
  let bookingUids = [];
3122
- if (params.mode === "edit" && editingLine && params.productLineUid) {
2992
+ if (params.mode === 'edit' && editingLine && params.productLineUid) {
3123
2993
  transformed.product_sku = transformed.product_sku ?? editingLine.product_sku;
3124
2994
  transformed.product_bundle = transformed.product_bundle ?? editingLine.product_bundle;
3125
2995
  transformed.booking_uid = existingBookingUid;
3126
2996
  transformed.metadata = {
3127
- ...editingLine.metadata || {},
3128
- ...transformed.metadata || {},
2997
+ ...(editingLine.metadata || {}),
2998
+ ...(transformed.metadata || {}),
3129
2999
  unique_identification_number: params.productLineUid,
3130
3000
  booking_uid: existingBookingUid
3131
3001
  };
@@ -3141,33 +3011,18 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
3141
3011
  productLineUids = [productLineUid];
3142
3012
  bookingUids = [bookingUid];
3143
3013
  } else {
3144
- const beforeProductLineUids = new Set(
3145
- (((_q = this.getTempOrder()) == null ? void 0 : _q.products) || []).map((line) => getProductLineUid(line)).filter(Boolean)
3146
- );
3147
- const beforeBookingUids = new Set(
3148
- (((_r = this.getTempOrder()) == null ? void 0 : _r.bookings) || []).map((item) => getBookingUid(item)).filter(Boolean)
3149
- );
3014
+ const beforeProductLineUids = new Set((this.getTempOrder()?.products || []).map(line => getProductLineUid(line)).filter(Boolean));
3015
+ const beforeBookingUids = new Set((this.getTempOrder()?.bookings || []).map(item => getBookingUid(item)).filter(Boolean));
3150
3016
  const products = await this.addProductToOrder(transformed, booking);
3151
- const addedLines = products.filter((line) => {
3152
- var _a2;
3153
- return sameAvailabilityId(line.product_id ?? line.id, refreshedCandidate.productId) && ((_a2 = line.metadata) == null ? void 0 : _a2.availability_candidate_key) === refreshedCandidate.key && !beforeProductLineUids.has(getProductLineUid(line));
3154
- });
3155
- productLineUids = addedLines.map((line) => getProductLineUid(line)).filter(Boolean);
3156
- const addedBookings = (((_s = this.getTempOrder()) == null ? void 0 : _s.bookings) || []).filter((item) => {
3157
- var _a2;
3158
- return ((_a2 = item.metadata) == null ? void 0 : _a2.availability_candidate_key) === refreshedCandidate.key && !beforeBookingUids.has(getBookingUid(item));
3159
- });
3160
- bookingUids = addedBookings.map((item) => getBookingUid(item)).filter(Boolean);
3017
+ const addedLines = products.filter(line => sameAvailabilityId(line.product_id ?? line.id, refreshedCandidate.productId) && line.metadata?.availability_candidate_key === refreshedCandidate.key && !beforeProductLineUids.has(getProductLineUid(line)));
3018
+ productLineUids = addedLines.map(line => getProductLineUid(line)).filter(Boolean);
3019
+ const addedBookings = (this.getTempOrder()?.bookings || []).filter(item => item.metadata?.availability_candidate_key === refreshedCandidate.key && !beforeBookingUids.has(getBookingUid(item)));
3020
+ bookingUids = addedBookings.map(item => getBookingUid(item)).filter(Boolean);
3161
3021
  if (bookingUids.length === 0) {
3162
- bookingUids = addedLines.map((line) => {
3163
- var _a2;
3164
- return String(
3165
- line.booking_uid ?? ((_a2 = line.metadata) == null ? void 0 : _a2.booking_uid) ?? ""
3166
- );
3167
- }).filter(Boolean);
3022
+ bookingUids = addedLines.map(line => String(line.booking_uid ?? line.metadata?.booking_uid ?? '')).filter(Boolean);
3168
3023
  }
3169
- productLineUid = productLineUids[productLineUids.length - 1] || "";
3170
- bookingUid = bookingUids[bookingUids.length - 1] || "";
3024
+ productLineUid = productLineUids[productLineUids.length - 1] || '';
3025
+ bookingUid = bookingUids[bookingUids.length - 1] || '';
3171
3026
  }
3172
3027
  this.invalidateAvailabilityContextsAfterCommit();
3173
3028
  const nextContext = this.getAvailabilityContextEntry(normalizedContextId);
@@ -3182,28 +3037,12 @@ var UnifiedBookingSalesImpl = class extends import_BookingTicket.BookingTicket {
3182
3037
  productLineUids,
3183
3038
  bookingUids
3184
3039
  };
3185
- await this.core.effects.emit(
3186
- `${this.name}:${import_types.UnifiedBookingSalesHooks.onAvailabilitySelectionCommitted}`,
3187
- result
3188
- );
3040
+ await this.core.effects.emit(`${this.name}:${_types.UnifiedBookingSalesHooks.onAvailabilitySelectionCommitted}`, result);
3189
3041
  return result;
3190
3042
  } finally {
3191
3043
  await this.releaseAvailabilityCommitLock(normalizedContextId);
3192
3044
  }
3193
3045
  }
3194
- };
3195
- var UnifiedBookingSales = UnifiedBookingSalesImpl;
3196
- // Annotate the CommonJS export names for ESM import in node:
3197
- 0 && (module.exports = {
3198
- AvailabilityError,
3199
- UnifiedBookingSales,
3200
- UnifiedBookingSalesImpl,
3201
- buildAvailabilityLineIdentity,
3202
- buildAvailabilityResourcesFromV2,
3203
- buildBookingFromAvailabilityAssignment,
3204
- buildBookingFromAvailabilityAssignments,
3205
- buildPlannerDiscountResult,
3206
- collectAvailabilityResourceIds,
3207
- normalizeProductForAvailability,
3208
- ...require("./types")
3209
- });
3046
+ }
3047
+ exports.UnifiedBookingSalesImpl = UnifiedBookingSalesImpl;
3048
+ const UnifiedBookingSales = exports.UnifiedBookingSales = UnifiedBookingSalesImpl;