@pisell/pisellos 3.0.90 → 3.0.91

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 (240) hide show
  1. package/dist/apis/picoding.d.ts +0 -0
  2. package/dist/apis/picoding.js +1 -0
  3. package/dist/model/index.d.ts +1 -0
  4. package/dist/model/index.js +1 -0
  5. package/dist/model/strategy/adapter/index.d.ts +7 -0
  6. package/dist/model/strategy/adapter/index.js +7 -0
  7. package/dist/model/strategy/adapter/itemRule/adapter.d.ts +67 -0
  8. package/dist/model/strategy/adapter/itemRule/adapter.js +483 -0
  9. package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +43 -0
  10. package/dist/model/strategy/adapter/itemRule/evaluator.js +169 -0
  11. package/dist/model/strategy/adapter/itemRule/examples.d.ts +79 -0
  12. package/dist/model/strategy/adapter/itemRule/examples.js +382 -0
  13. package/dist/model/strategy/adapter/itemRule/index.d.ts +5 -0
  14. package/dist/model/strategy/adapter/itemRule/index.js +5 -0
  15. package/dist/model/strategy/adapter/itemRule/type.d.ts +225 -0
  16. package/dist/model/strategy/adapter/itemRule/type.js +101 -0
  17. package/dist/model/strategy/adapter/promotion/adapter.d.ts +66 -0
  18. package/dist/model/strategy/adapter/promotion/adapter.js +271 -0
  19. package/dist/model/strategy/adapter/promotion/evaluator.d.ts +213 -0
  20. package/dist/model/strategy/adapter/promotion/evaluator.js +1206 -0
  21. package/dist/model/strategy/adapter/promotion/examples.d.ts +138 -0
  22. package/dist/model/strategy/adapter/promotion/examples.js +166 -0
  23. package/dist/model/strategy/adapter/promotion/index.d.ts +4 -0
  24. package/dist/model/strategy/adapter/promotion/index.js +0 -0
  25. package/dist/model/strategy/adapter/promotion/type.d.ts +447 -0
  26. package/dist/model/strategy/adapter/promotion/type.js +209 -0
  27. package/dist/model/strategy/adapter/type.d.ts +28 -0
  28. package/dist/model/strategy/adapter/type.js +1 -0
  29. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
  30. package/dist/model/strategy/adapter/walletPass/evaluator.js +502 -0
  31. package/dist/model/strategy/adapter/walletPass/example.d.ts +4 -0
  32. package/dist/model/strategy/adapter/walletPass/example.js +258 -0
  33. package/dist/model/strategy/adapter/walletPass/index.d.ts +32 -0
  34. package/dist/model/strategy/adapter/walletPass/index.js +182 -0
  35. package/dist/model/strategy/adapter/walletPass/locales.d.ts +1 -0
  36. package/dist/model/strategy/adapter/walletPass/locales.js +26 -0
  37. package/dist/model/strategy/adapter/walletPass/type.d.ts +187 -0
  38. package/dist/model/strategy/adapter/walletPass/type.js +1 -0
  39. package/dist/model/strategy/adapter/walletPass/utils.d.ts +50 -0
  40. package/dist/model/strategy/adapter/walletPass/utils.js +1104 -0
  41. package/dist/model/strategy/engine.d.ts +106 -0
  42. package/dist/model/strategy/engine.js +611 -0
  43. package/dist/model/strategy/index.d.ts +3 -0
  44. package/dist/model/strategy/index.js +8 -0
  45. package/dist/model/strategy/strategy-example.d.ts +5 -0
  46. package/dist/model/strategy/strategy-example.js +331 -0
  47. package/dist/model/strategy/type.d.ts +228 -0
  48. package/dist/model/strategy/type.js +94 -0
  49. package/dist/modules/Cart/utils/cartProduct.js +1 -0
  50. package/dist/modules/Discount/index.d.ts +4 -2
  51. package/dist/modules/Discount/index.js +90 -3
  52. package/dist/modules/Discount/types.d.ts +6 -0
  53. package/dist/modules/OpenData/index.d.ts +24 -0
  54. package/dist/modules/OpenData/index.js +173 -0
  55. package/dist/modules/OpenData/types.d.ts +73 -0
  56. package/dist/modules/OpenData/types.js +1 -0
  57. package/dist/modules/OpenData/utils.d.ts +2 -0
  58. package/dist/modules/OpenData/utils.js +75 -0
  59. package/dist/modules/Order/index.d.ts +66 -1
  60. package/dist/modules/Order/index.js +884 -10
  61. package/dist/modules/Order/types.d.ts +174 -12
  62. package/dist/modules/Order/types.js +2 -0
  63. package/dist/modules/Order/utils.d.ts +118 -0
  64. package/dist/modules/Order/utils.js +586 -2
  65. package/dist/modules/Product/utils.js +2 -2
  66. package/dist/modules/ProductList/index.d.ts +3 -1
  67. package/dist/modules/ProductList/index.js +19 -11
  68. package/dist/modules/Quotation/index.d.ts +48 -0
  69. package/dist/modules/Quotation/index.js +248 -0
  70. package/dist/modules/Quotation/types.d.ts +42 -0
  71. package/dist/modules/Quotation/types.js +1 -0
  72. package/dist/modules/Rules/index.js +17 -18
  73. package/dist/modules/SalesSummary/index.d.ts +63 -0
  74. package/dist/modules/SalesSummary/index.js +174 -0
  75. package/dist/modules/SalesSummary/types.d.ts +60 -0
  76. package/dist/modules/SalesSummary/types.js +1 -0
  77. package/dist/modules/SalesSummary/utils.d.ts +30 -0
  78. package/dist/modules/SalesSummary/utils.js +480 -0
  79. package/dist/modules/ScanOrderLogger/index.d.ts +23 -0
  80. package/dist/modules/ScanOrderLogger/index.js +174 -0
  81. package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
  82. package/dist/modules/ScanOrderLogger/providers/feishu.js +221 -0
  83. package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
  84. package/dist/modules/ScanOrderLogger/providers/grafana.js +50 -0
  85. package/dist/modules/ScanOrderLogger/types.d.ts +53 -0
  86. package/dist/modules/ScanOrderLogger/types.js +1 -0
  87. package/dist/modules/Schedule/getDateIsInSchedule.js +11 -18
  88. package/dist/modules/Schedule/utils.d.ts +1 -1
  89. package/dist/modules/Summary/utils.d.ts +3 -3
  90. package/dist/modules/Summary/utils.js +41 -31
  91. package/dist/modules/index.d.ts +4 -0
  92. package/dist/modules/index.js +5 -1
  93. package/dist/solution/BookingByStep/index.d.ts +2 -2
  94. package/dist/solution/BookingByStep/types.d.ts +3 -1
  95. package/dist/solution/BookingByStep/types.js +5 -1
  96. package/dist/solution/ScanOrder/index.d.ts +158 -0
  97. package/dist/solution/ScanOrder/index.js +3474 -0
  98. package/dist/solution/ScanOrder/types.d.ts +306 -0
  99. package/dist/solution/ScanOrder/types.js +35 -0
  100. package/dist/solution/ScanOrder/utils.d.ts +172 -0
  101. package/dist/solution/ScanOrder/utils.js +796 -0
  102. package/dist/solution/ShopDiscount/index.d.ts +1 -0
  103. package/dist/solution/ShopDiscount/index.js +23 -18
  104. package/dist/solution/VenueBooking/index.d.ts +201 -0
  105. package/dist/solution/VenueBooking/index.js +3472 -0
  106. package/dist/solution/VenueBooking/sales-section-4-annotated.json +343 -0
  107. package/dist/solution/VenueBooking/types.d.ts +154 -0
  108. package/dist/solution/VenueBooking/types.js +21 -0
  109. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +11 -0
  110. package/dist/solution/VenueBooking/utils/dateSummary.js +104 -0
  111. package/dist/solution/VenueBooking/utils/resource.d.ts +14 -0
  112. package/dist/solution/VenueBooking/utils/resource.js +131 -0
  113. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +38 -0
  114. package/dist/solution/VenueBooking/utils/slotMerge.js +239 -0
  115. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
  116. package/dist/solution/VenueBooking/utils/timeSlot.js +453 -0
  117. package/dist/solution/VenueBooking/utils.d.ts +1 -0
  118. package/dist/solution/VenueBooking/utils.js +1 -0
  119. package/dist/solution/index.d.ts +2 -0
  120. package/dist/solution/index.js +3 -1
  121. package/lib/apis/picoding.d.ts +0 -0
  122. package/lib/apis/picoding.js +0 -0
  123. package/lib/model/index.d.ts +1 -0
  124. package/lib/model/index.js +23 -0
  125. package/lib/model/strategy/adapter/index.d.ts +7 -0
  126. package/lib/model/strategy/adapter/index.js +57 -0
  127. package/lib/model/strategy/adapter/itemRule/adapter.d.ts +67 -0
  128. package/lib/model/strategy/adapter/itemRule/adapter.js +377 -0
  129. package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +43 -0
  130. package/lib/model/strategy/adapter/itemRule/evaluator.js +124 -0
  131. package/lib/model/strategy/adapter/itemRule/examples.d.ts +79 -0
  132. package/lib/model/strategy/adapter/itemRule/examples.js +316 -0
  133. package/lib/model/strategy/adapter/itemRule/index.d.ts +5 -0
  134. package/lib/model/strategy/adapter/itemRule/index.js +60 -0
  135. package/lib/model/strategy/adapter/itemRule/type.d.ts +225 -0
  136. package/lib/model/strategy/adapter/itemRule/type.js +46 -0
  137. package/lib/model/strategy/adapter/promotion/adapter.d.ts +66 -0
  138. package/lib/model/strategy/adapter/promotion/adapter.js +217 -0
  139. package/lib/model/strategy/adapter/promotion/evaluator.d.ts +213 -0
  140. package/lib/model/strategy/adapter/promotion/evaluator.js +844 -0
  141. package/lib/model/strategy/adapter/promotion/examples.d.ts +138 -0
  142. package/lib/model/strategy/adapter/promotion/examples.js +192 -0
  143. package/lib/model/strategy/adapter/promotion/index.d.ts +4 -0
  144. package/lib/model/strategy/adapter/promotion/index.js +0 -0
  145. package/lib/model/strategy/adapter/promotion/type.d.ts +447 -0
  146. package/lib/model/strategy/adapter/promotion/type.js +51 -0
  147. package/lib/model/strategy/adapter/type.d.ts +28 -0
  148. package/lib/model/strategy/adapter/type.js +17 -0
  149. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
  150. package/lib/model/strategy/adapter/walletPass/evaluator.js +424 -0
  151. package/lib/model/strategy/adapter/walletPass/example.d.ts +4 -0
  152. package/lib/model/strategy/adapter/walletPass/example.js +207 -0
  153. package/lib/model/strategy/adapter/walletPass/index.d.ts +32 -0
  154. package/lib/model/strategy/adapter/walletPass/index.js +142 -0
  155. package/lib/model/strategy/adapter/walletPass/locales.d.ts +1 -0
  156. package/lib/model/strategy/adapter/walletPass/locales.js +54 -0
  157. package/lib/model/strategy/adapter/walletPass/type.d.ts +187 -0
  158. package/lib/model/strategy/adapter/walletPass/type.js +17 -0
  159. package/lib/model/strategy/adapter/walletPass/utils.d.ts +50 -0
  160. package/lib/model/strategy/adapter/walletPass/utils.js +791 -0
  161. package/lib/model/strategy/engine.d.ts +106 -0
  162. package/lib/model/strategy/engine.js +450 -0
  163. package/lib/model/strategy/index.d.ts +3 -0
  164. package/lib/model/strategy/index.js +38 -0
  165. package/lib/model/strategy/strategy-example.d.ts +5 -0
  166. package/lib/model/strategy/strategy-example.js +318 -0
  167. package/lib/model/strategy/type.d.ts +228 -0
  168. package/lib/model/strategy/type.js +44 -0
  169. package/lib/modules/Cart/utils/cartProduct.js +1 -0
  170. package/lib/modules/Discount/index.d.ts +4 -2
  171. package/lib/modules/Discount/index.js +60 -2
  172. package/lib/modules/Discount/types.d.ts +6 -0
  173. package/lib/modules/OpenData/index.d.ts +24 -0
  174. package/lib/modules/OpenData/index.js +119 -0
  175. package/lib/modules/OpenData/types.d.ts +73 -0
  176. package/lib/modules/OpenData/types.js +17 -0
  177. package/lib/modules/OpenData/utils.d.ts +2 -0
  178. package/lib/modules/OpenData/utils.js +111 -0
  179. package/lib/modules/Order/index.d.ts +66 -1
  180. package/lib/modules/Order/index.js +525 -0
  181. package/lib/modules/Order/types.d.ts +174 -12
  182. package/lib/modules/Order/utils.d.ts +118 -0
  183. package/lib/modules/Order/utils.js +483 -2
  184. package/lib/modules/Product/utils.js +2 -2
  185. package/lib/modules/ProductList/index.d.ts +3 -1
  186. package/lib/modules/ProductList/index.js +45 -34
  187. package/lib/modules/Quotation/index.d.ts +48 -0
  188. package/lib/modules/Quotation/index.js +152 -0
  189. package/lib/modules/Quotation/types.d.ts +42 -0
  190. package/lib/modules/Quotation/types.js +17 -0
  191. package/lib/modules/Rules/index.js +17 -18
  192. package/lib/modules/SalesSummary/index.d.ts +63 -0
  193. package/lib/modules/SalesSummary/index.js +105 -0
  194. package/lib/modules/SalesSummary/types.d.ts +60 -0
  195. package/lib/modules/SalesSummary/types.js +17 -0
  196. package/lib/modules/SalesSummary/utils.d.ts +30 -0
  197. package/lib/modules/SalesSummary/utils.js +420 -0
  198. package/lib/modules/ScanOrderLogger/index.d.ts +23 -0
  199. package/lib/modules/ScanOrderLogger/index.js +147 -0
  200. package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +2 -0
  201. package/lib/modules/ScanOrderLogger/providers/feishu.js +157 -0
  202. package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +2 -0
  203. package/lib/modules/ScanOrderLogger/providers/grafana.js +52 -0
  204. package/lib/modules/ScanOrderLogger/types.d.ts +53 -0
  205. package/lib/modules/ScanOrderLogger/types.js +17 -0
  206. package/lib/modules/Schedule/getDateIsInSchedule.js +9 -11
  207. package/lib/modules/Schedule/utils.d.ts +1 -1
  208. package/lib/modules/Summary/utils.d.ts +3 -3
  209. package/lib/modules/Summary/utils.js +22 -16
  210. package/lib/modules/index.d.ts +4 -0
  211. package/lib/modules/index.js +9 -1
  212. package/lib/solution/BookingByStep/index.d.ts +2 -2
  213. package/lib/solution/BookingByStep/types.d.ts +3 -1
  214. package/lib/solution/BookingByStep/types.js +10 -0
  215. package/lib/solution/ScanOrder/index.d.ts +158 -0
  216. package/lib/solution/ScanOrder/index.js +2135 -0
  217. package/lib/solution/ScanOrder/types.d.ts +306 -0
  218. package/lib/solution/ScanOrder/types.js +36 -0
  219. package/lib/solution/ScanOrder/utils.d.ts +172 -0
  220. package/lib/solution/ScanOrder/utils.js +658 -0
  221. package/lib/solution/ShopDiscount/index.d.ts +1 -0
  222. package/lib/solution/ShopDiscount/index.js +4 -2
  223. package/lib/solution/VenueBooking/index.d.ts +201 -0
  224. package/lib/solution/VenueBooking/index.js +1937 -0
  225. package/lib/solution/VenueBooking/sales-section-4-annotated.json +343 -0
  226. package/lib/solution/VenueBooking/types.d.ts +154 -0
  227. package/lib/solution/VenueBooking/types.js +44 -0
  228. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +11 -0
  229. package/lib/solution/VenueBooking/utils/dateSummary.js +110 -0
  230. package/lib/solution/VenueBooking/utils/resource.d.ts +14 -0
  231. package/lib/solution/VenueBooking/utils/resource.js +92 -0
  232. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +38 -0
  233. package/lib/solution/VenueBooking/utils/slotMerge.js +237 -0
  234. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +32 -0
  235. package/lib/solution/VenueBooking/utils/timeSlot.js +339 -0
  236. package/lib/solution/VenueBooking/utils.d.ts +1 -0
  237. package/lib/solution/VenueBooking/utils.js +69 -0
  238. package/lib/solution/index.d.ts +2 -0
  239. package/lib/solution/index.js +5 -1
  240. package/package.json +1 -1
@@ -29,12 +29,152 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/modules/Order/utils.ts
30
30
  var utils_exports = {};
31
31
  __export(utils_exports, {
32
+ buildSubmitPayload: () => buildSubmitPayload,
33
+ composeLinePrice: () => composeLinePrice,
34
+ createDefaultOrderRulesHooks: () => createDefaultOrderRulesHooks,
35
+ createDefaultTempOrder: () => createDefaultTempOrder,
36
+ createEmptySummary: () => import_utils2.createEmptySummary,
37
+ createUuidV4: () => createUuidV4,
38
+ filterProductsForScanOrderMore: () => filterProductsForScanOrderMore,
39
+ formatDateTime: () => formatDateTime,
40
+ formatV1Product: () => formatV1Product,
32
41
  generateDuration: () => generateDuration,
33
42
  getAllDiscountList: () => getAllDiscountList,
34
- mergeRelationForms: () => mergeRelationForms
43
+ isTempOrder: () => isTempOrder,
44
+ mergeRelationForms: () => mergeRelationForms,
45
+ normalizeSubmitBooking: () => normalizeSubmitBooking,
46
+ normalizeSubmitCollectPaxValue: () => normalizeSubmitCollectPaxValue,
47
+ resolveSubmitCollectPax: () => resolveSubmitCollectPax,
48
+ sumOptionUnitPrice: () => sumOptionUnitPrice
35
49
  });
36
50
  module.exports = __toCommonJS(utils_exports);
37
51
  var import_dayjs = __toESM(require("dayjs"));
52
+ var import_decimal = __toESM(require("decimal.js"));
53
+ var import_utils = require("../../solution/ScanOrder/utils");
54
+ var import_utils2 = require("../../solution/ScanOrder/utils");
55
+ function composeLinePrice(params) {
56
+ const { mainPrice, bundle, useOriginalBundle } = params;
57
+ let total = new import_decimal.default(Number(mainPrice) || 0);
58
+ if (Array.isArray(bundle)) {
59
+ for (const item of bundle) {
60
+ const rawPrice = useOriginalBundle ? (item == null ? void 0 : item.original_price) ?? (item == null ? void 0 : item.product_price) ?? (item == null ? void 0 : item.price) : (item == null ? void 0 : item.bundle_selling_price) ?? (item == null ? void 0 : item.price);
61
+ const price = new import_decimal.default(Number(rawPrice) || 0);
62
+ const rawNum = (item == null ? void 0 : item.num) ?? (item == null ? void 0 : item.quantity) ?? 1;
63
+ const num = new import_decimal.default(Number(rawNum) || 0);
64
+ total = total.plus(price.times(num));
65
+ }
66
+ }
67
+ return total.toDecimalPlaces(2).toFixed(2);
68
+ }
69
+ function sumOptionUnitPrice(options) {
70
+ let total = new import_decimal.default(0);
71
+ if (!Array.isArray(options))
72
+ return total;
73
+ for (const opt of options) {
74
+ const price = new import_decimal.default(Number(opt == null ? void 0 : opt.price) || 0);
75
+ const num = new import_decimal.default(Number(opt == null ? void 0 : opt.num) || 0);
76
+ total = total.plus(price.times(num));
77
+ }
78
+ return total;
79
+ }
80
+ function createDefaultOrderRulesHooks() {
81
+ const toUnitPriceString = (totalLike, num) => {
82
+ const effectiveNum = Number(num) > 0 ? Number(num) : 1;
83
+ return new import_decimal.default(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
84
+ };
85
+ return {
86
+ getProduct: (product) => {
87
+ var _a, _b, _c, _d;
88
+ const metadataAny = product.metadata || {};
89
+ const optionSum = sumOptionUnitPrice(product.product_option_item);
90
+ let sourcePrice;
91
+ if (metadataAny.source_product_price !== void 0) {
92
+ sourcePrice = String(metadataAny.source_product_price);
93
+ } else if (metadataAny.main_product_selling_price !== void 0) {
94
+ sourcePrice = new import_decimal.default(
95
+ Number(metadataAny.main_product_selling_price) || 0
96
+ ).minus(optionSum).toDecimalPlaces(2).toString();
97
+ } else {
98
+ sourcePrice = String(product.selling_price ?? 0);
99
+ }
100
+ let sourceOriginalPrice;
101
+ if (metadataAny.source_product_price !== void 0) {
102
+ sourceOriginalPrice = String(metadataAny.source_product_price);
103
+ } else if (metadataAny.main_product_original_price !== void 0) {
104
+ sourceOriginalPrice = new import_decimal.default(
105
+ Number(metadataAny.main_product_original_price) || 0
106
+ ).minus(optionSum).toDecimalPlaces(2).toString();
107
+ } else {
108
+ sourceOriginalPrice = sourcePrice;
109
+ }
110
+ return {
111
+ id: product.product_id,
112
+ // Rules 引擎用 _id 作为 processedProductsMap 键;必须与购物车行级 identity 一致,
113
+ // 否则同 SKU 不同小料会在 calcDiscount 重组时互相覆盖。
114
+ // 不透明 identity 契约下,normalizeOrderProduct / restoreTempOrderFromStorage 已保证 identity_key 必存在;
115
+ // 留 fingerprint 分支仅作 Rules 单测里直接传裸 product 时的兜底。
116
+ _id: product.identity_key ? `${product.product_id}_${product.product_variant_id}_${product.identity_key}` : `${product.product_id}_${product.product_variant_id}_${(0, import_utils.buildProductLineFingerprint)(
117
+ product.product_option_item,
118
+ product.product_bundle
119
+ )}`,
120
+ // Rules 内部 getProductTotalPrice / getProductOriginTotalPrice 会各自再叠加 bundle + option,
121
+ // 所以这里必须喂 source-level(不含 option、不含 bundle、不含折扣)单价,避免双加 option。
122
+ price: sourcePrice,
123
+ // total / origin_total 使用 composite × num,跟 Rules 内部产出的 total 对齐(含 option + bundle)。
124
+ total: new import_decimal.default(product.selling_price || 0).times(product.num || 1).toNumber(),
125
+ origin_total: new import_decimal.default(
126
+ product.original_price || product.selling_price || 0
127
+ ).times(product.num || 1).toNumber(),
128
+ original_price: sourceOriginalPrice,
129
+ quantity: product.num || 1,
130
+ num: product.num || 1,
131
+ discount_list: product.discount_list || [],
132
+ bundle: product.product_bundle || [],
133
+ booking_id: ((_a = product._origin) == null ? void 0 : _a.booking_id) || null,
134
+ isClient: false,
135
+ isManualDiscount: ((_b = product._origin) == null ? void 0 : _b.isManualDiscount) || false,
136
+ holder_id: (_c = product._origin) == null ? void 0 : _c.holder_id,
137
+ startDate: (_d = product._origin) == null ? void 0 : _d.startDate
138
+ };
139
+ },
140
+ setProduct: (product, values) => {
141
+ const nextNum = Number(values.quantity ?? product.num ?? 1) || 1;
142
+ const metadataAny = product.metadata || {};
143
+ const existedSource = metadataAny.source_product_price ?? product.selling_price ?? "0";
144
+ const nextOptions = product.product_option_item;
145
+ const optionSum = sumOptionUnitPrice(nextOptions);
146
+ const nextSourceSellingPrice = values.main_product_selling_price !== void 0 ? String(values.main_product_selling_price) : values.price !== void 0 ? String(values.price) : values.total !== void 0 ? toUnitPriceString(values.total, nextNum) : String(existedSource);
147
+ const nextSourceOriginalPrice = values.original_price !== void 0 ? String(values.original_price) : String(existedSource);
148
+ const nextMainSellingPrice = new import_decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
149
+ const nextMainOriginalPrice = new import_decimal.default(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
150
+ const nextBundle = values.bundle ?? product.product_bundle;
151
+ const composedSellingPrice = composeLinePrice({
152
+ mainPrice: nextMainSellingPrice,
153
+ bundle: nextBundle
154
+ });
155
+ const composedOriginalPrice = composeLinePrice({
156
+ mainPrice: nextMainOriginalPrice,
157
+ bundle: nextBundle,
158
+ useOriginalBundle: true
159
+ });
160
+ return {
161
+ ...product,
162
+ selling_price: composedSellingPrice,
163
+ original_price: composedOriginalPrice,
164
+ discount_list: values.discount_list ?? product.discount_list,
165
+ num: values.quantity ?? product.num,
166
+ product_bundle: nextBundle,
167
+ metadata: {
168
+ ...metadataAny,
169
+ source_product_price: nextSourceOriginalPrice,
170
+ main_product_selling_price: nextMainSellingPrice,
171
+ main_product_original_price: nextMainOriginalPrice,
172
+ price_schema_version: 2
173
+ }
174
+ };
175
+ }
176
+ };
177
+ }
38
178
  var generateDuration = (cartItem) => {
39
179
  const startDate = (0, import_dayjs.default)(`${cartItem.start_date} ${cartItem.start_time}`);
40
180
  const endDate = (0, import_dayjs.default)(`${cartItem.end_date} ${cartItem.end_time}`);
@@ -65,9 +205,350 @@ var getAllDiscountList = (cartItem) => {
65
205
  });
66
206
  return discountList;
67
207
  };
208
+ function createUuidV4() {
209
+ const template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
210
+ return template.replace(/[xy]/g, (char) => {
211
+ const randomValue = Math.floor(Math.random() * 16);
212
+ const value = char === "x" ? randomValue : randomValue & 3 | 8;
213
+ return value.toString(16);
214
+ });
215
+ }
216
+ function isTempOrder(data) {
217
+ if (!data || typeof data !== "object")
218
+ return false;
219
+ if (!Array.isArray(data.products))
220
+ return false;
221
+ return true;
222
+ }
223
+ function formatDateTime(date) {
224
+ const pad = (value) => value.toString().padStart(2, "0");
225
+ const year = date.getFullYear();
226
+ const month = pad(date.getMonth() + 1);
227
+ const day = pad(date.getDate());
228
+ const hours = pad(date.getHours());
229
+ const minutes = pad(date.getMinutes());
230
+ const seconds = pad(date.getSeconds());
231
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
232
+ }
233
+ function normalizeSubmitPlatform(platform) {
234
+ return (platform == null ? void 0 : platform.toLowerCase()) === "pc" ? "PC" : "H5";
235
+ }
236
+ function formatSubmitOptionItems(options) {
237
+ if (!Array.isArray(options))
238
+ return [];
239
+ return options.map((d) => ({
240
+ num: d == null ? void 0 : d.num,
241
+ option_group_item_id: (d == null ? void 0 : d.option_group_item_id) ?? (d == null ? void 0 : d.product_option_item_id),
242
+ option_group_id: d == null ? void 0 : d.option_group_id
243
+ }));
244
+ }
245
+ function toBundleNumber(value, fallback = 0) {
246
+ const parsed = Number(value);
247
+ return Number.isFinite(parsed) ? parsed : fallback;
248
+ }
249
+ function formatSubmitBundleItems(bundle) {
250
+ if (!Array.isArray(bundle))
251
+ return [];
252
+ return bundle.map((b) => {
253
+ const rawBundle = b && typeof b === "object" ? b : {};
254
+ const existedMetadata = rawBundle.metadata && typeof rawBundle.metadata === "object" ? rawBundle.metadata : {};
255
+ const sellingPriceNum = toBundleNumber(
256
+ rawBundle.bundle_selling_price ?? rawBundle.price,
257
+ 0
258
+ );
259
+ const priceNum = toBundleNumber(rawBundle.price, sellingPriceNum);
260
+ const priceType = rawBundle.price_type ?? "";
261
+ const relationSurchargeIds = Array.isArray(rawBundle.relation_surcharge_ids) ? rawBundle.relation_surcharge_ids : Array.isArray(existedMetadata.relation_surcharge_ids) ? existedMetadata.relation_surcharge_ids : [];
262
+ const surchargeFee = toBundleNumber(
263
+ rawBundle.surcharge_fee ?? existedMetadata.surcharge_fee,
264
+ 0
265
+ );
266
+ const productDiscountDifference = toBundleNumber(
267
+ existedMetadata.product_discount_difference,
268
+ 0
269
+ );
270
+ return {
271
+ ...rawBundle,
272
+ is_charge_tax: rawBundle.is_charge_tax ?? 0,
273
+ tax_fee: toBundleNumber(rawBundle.tax_fee, 0),
274
+ bundle_variant_id: rawBundle.bundle_variant_id ?? 0,
275
+ num: toBundleNumber(rawBundle.num, 1),
276
+ extension_id: rawBundle.extension_id ?? 0,
277
+ extension_type: rawBundle.extension_type ?? "normal",
278
+ price: priceNum,
279
+ price_type: priceType,
280
+ price_type_ext: rawBundle.price_type_ext ?? "",
281
+ // custom_price: customPriceStr,
282
+ custom_price_type: rawBundle.custom_price_type ?? priceType ?? "",
283
+ bundle_selling_price: sellingPriceNum,
284
+ option: formatSubmitOptionItems(rawBundle.option),
285
+ bundle_group_id: rawBundle == null ? void 0 : rawBundle.group_id,
286
+ bundle_id: rawBundle == null ? void 0 : rawBundle.id,
287
+ metadata: {
288
+ ...existedMetadata,
289
+ surcharge_fee: surchargeFee,
290
+ relation_surcharge_ids: relationSurchargeIds,
291
+ product_discount_difference: productDiscountDifference
292
+ }
293
+ };
294
+ });
295
+ }
296
+ function normalizeSubmitProduct(product) {
297
+ const { _origin, identity_key, ...submitProduct } = product;
298
+ const rawMetadata = submitProduct.metadata || {};
299
+ const bookingUid = rawMetadata.booking_uid;
300
+ const cleanMetadata = {};
301
+ if (rawMetadata.unique_identification_number) {
302
+ cleanMetadata.unique_identification_number = rawMetadata.unique_identification_number;
303
+ }
304
+ const priceMetaKeys = [
305
+ "main_product_original_price",
306
+ "main_product_selling_price",
307
+ "source_product_price",
308
+ "price_schema_version"
309
+ ];
310
+ for (const key of priceMetaKeys) {
311
+ if (rawMetadata[key] !== void 0) {
312
+ cleanMetadata[key] = rawMetadata[key];
313
+ }
314
+ }
315
+ if (rawMetadata.price_breakdown) {
316
+ cleanMetadata.price_breakdown = rawMetadata.price_breakdown;
317
+ }
318
+ if (rawMetadata.is_rule !== void 0) {
319
+ cleanMetadata.is_rule = rawMetadata.is_rule;
320
+ }
321
+ return {
322
+ ...submitProduct,
323
+ ...bookingUid ? { booking_uid: bookingUid } : {},
324
+ product_option_item: formatSubmitOptionItems(submitProduct.product_option_item),
325
+ discount_list: submitProduct.discount_list || [],
326
+ product_bundle: formatSubmitBundleItems(submitProduct.product_bundle),
327
+ metadata: cleanMetadata,
328
+ // 出站兼容:后端消费 payment_price 字段,这里从 selling_price 直接派生。
329
+ // 新语义下 selling_price 是 composite(含 option/bundle),payment_price 同语义。
330
+ payment_price: submitProduct.selling_price
331
+ };
332
+ }
333
+ var SUBMIT_BOOKING_METADATA_WHITELIST = [
334
+ "unique_identification_number",
335
+ "collect_pax"
336
+ ];
337
+ function normalizeSubmitBooking(booking) {
338
+ const rawMetadata = booking.metadata || {};
339
+ const cleanMetadata = {};
340
+ for (const key of SUBMIT_BOOKING_METADATA_WHITELIST) {
341
+ if (rawMetadata[key] !== void 0) {
342
+ cleanMetadata[key] = rawMetadata[key];
343
+ }
344
+ }
345
+ return {
346
+ ...booking,
347
+ metadata: cleanMetadata
348
+ };
349
+ }
350
+ var DEFAULT_TABLE_OCCUPANCY_DURATION = 20;
351
+ function resolveTableOccupancyDuration(tempOrder) {
352
+ var _a, _b, _c, _d;
353
+ const metadata = tempOrder.metadata || {};
354
+ const candidates = [
355
+ metadata.table_occupancy_duration,
356
+ metadata.booking_duration,
357
+ metadata.table_duration,
358
+ metadata.duration,
359
+ (_a = metadata.table_config) == null ? void 0 : _a.occupancy_duration,
360
+ (_b = metadata.tableConfig) == null ? void 0 : _b.occupancy_duration,
361
+ (_c = metadata.resource_config) == null ? void 0 : _c.occupancy_duration,
362
+ (_d = metadata.resourceConfig) == null ? void 0 : _d.occupancy_duration
363
+ ];
364
+ for (const value of candidates) {
365
+ const duration = Number(value);
366
+ if (Number.isFinite(duration) && duration > 0) {
367
+ return Math.floor(duration);
368
+ }
369
+ }
370
+ return DEFAULT_TABLE_OCCUPANCY_DURATION;
371
+ }
372
+ function normalizeSubmitCollectPaxValue(value) {
373
+ const n = Number(value);
374
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : 1;
375
+ }
376
+ function resolveSubmitCollectPax(tempOrder) {
377
+ var _a;
378
+ return normalizeSubmitCollectPaxValue((_a = tempOrder.metadata) == null ? void 0 : _a.collect_pax);
379
+ }
380
+ function createDefaultTempOrder(params) {
381
+ const summary = params.summary || (0, import_utils.createEmptySummary)();
382
+ return {
383
+ order_id: null,
384
+ relation_id: void 0,
385
+ table_form_id: void 0,
386
+ resource_id: void 0,
387
+ order_number: "",
388
+ shop_order_number: "",
389
+ type: "appointment_booking",
390
+ business_code: "appointment_booking",
391
+ platform: "h5",
392
+ sales_channel: "my_pisel",
393
+ order_sales_channel: "online_store",
394
+ status: "normal",
395
+ payment_status: "payment_processing",
396
+ shipping_status: "unfulfilled",
397
+ customer_id: null,
398
+ customer_name: "",
399
+ country_calling_code: "",
400
+ phone: "",
401
+ email: "",
402
+ is_price_include_tax: 1,
403
+ tax_title: "",
404
+ tax_country_code: "",
405
+ currency_code: "",
406
+ currency_symbol: "",
407
+ currency_format: "symbol_first",
408
+ is_deposit: 0,
409
+ deposit_amount: "0.00",
410
+ shop_discount: "0.00",
411
+ surcharge_fee: "0.00",
412
+ note: "",
413
+ schedule_date: params.now,
414
+ created_at: params.now,
415
+ products: [],
416
+ bookings: [],
417
+ payments: [],
418
+ surcharges: [],
419
+ discount_list: [],
420
+ relation_forms: [],
421
+ contacts: [],
422
+ contacts_info: [],
423
+ holder: null,
424
+ summary,
425
+ metadata: {}
426
+ };
427
+ }
428
+ function buildSubmitPayload(params) {
429
+ const {
430
+ tempOrder,
431
+ cacheId,
432
+ now = /* @__PURE__ */ new Date(),
433
+ platform,
434
+ businessCode,
435
+ channel,
436
+ type,
437
+ enhance
438
+ } = params;
439
+ const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
440
+ const summary = tempOrder.summary || (0, import_utils.createEmptySummary)();
441
+ const relationId = tempOrder.relation_id;
442
+ const tableFormId = tempOrder.table_form_id;
443
+ const bookingUuid = createUuidV4();
444
+ const bookingStart = (0, import_dayjs.default)(now);
445
+ const bookingDuration = resolveTableOccupancyDuration(tempOrder);
446
+ const bookingEnd = bookingStart.add(bookingDuration, "minute");
447
+ const bookings = relationId && tableFormId ? [{
448
+ relation_id: 0,
449
+ form_id: 0,
450
+ start_time: bookingStart.format("HH:mm"),
451
+ start_date: bookingStart.format("YYYY-MM-DD"),
452
+ end_time: bookingEnd.format("HH:mm"),
453
+ end_date: bookingEnd.format("YYYY-MM-DD"),
454
+ duration: bookingDuration,
455
+ metadata: {
456
+ unique_identification_number: bookingUuid,
457
+ collect_pax: resolveSubmitCollectPax(tempOrder)
458
+ },
459
+ select_date: bookingStart.format("YYYY-MM-DD"),
460
+ is_all: false,
461
+ like_status: "common",
462
+ schedule_id: 0,
463
+ relation_type: "",
464
+ number: 1
465
+ }] : tempOrder.bookings || [];
466
+ const formRecordIds = relationId && tableFormId ? [{
467
+ form_id: tableFormId,
468
+ form_record_id: relationId
469
+ }] : void 0;
470
+ const { created_at: _createdAt, summary: _summary, surcharges: _surcharges, ...tempOrderRest } = tempOrder;
471
+ const payload = {
472
+ ...tempOrderRest,
473
+ platform: normalizeSubmitPlatform(platform ?? tempOrder.platform),
474
+ request_unique_idempotency_token: cacheId,
475
+ type: type ?? tempOrder.type ?? "table-order",
476
+ business_code: businessCode ?? tempOrder.business_code ?? "table-order",
477
+ sales_channel: tempOrder.sales_channel || "my_pisel",
478
+ order_sales_channel: channel ?? tempOrder.order_sales_channel ?? "online_store",
479
+ status: tempOrder.status || "normal",
480
+ payment_status: tempOrder.payment_status || "payment_processing",
481
+ // shipping_status: tempOrder.shipping_status || 'unfulfilled',
482
+ is_price_include_tax: tempOrder.is_price_include_tax ?? 1,
483
+ currency_format: tempOrder.currency_format || "symbol_first",
484
+ is_deposit: tempOrder.is_deposit ?? 0,
485
+ deposit_amount: tempOrder.deposit_amount || "0.00",
486
+ shop_discount: tempOrder.shop_discount || "0.00",
487
+ surcharge_fee: summary.surcharge_fee || tempOrder.surcharge_fee || "0.00",
488
+ note: tempOrder.note || "",
489
+ schedule_date: scheduleDate,
490
+ bookings: bookings.map((booking) => normalizeSubmitBooking(booking)),
491
+ payments: tempOrder.payments || [],
492
+ // discount_list: tempOrder.discount_list || [],
493
+ relation_forms: tempOrder.relation_forms || [],
494
+ form_record_ids: formRecordIds,
495
+ // contacts: tempOrder.contacts || [],
496
+ contacts_info: tempOrder.contacts_info || [],
497
+ // holder: tempOrder.holder || null,
498
+ // summary,
499
+ metadata: (() => {
500
+ const {
501
+ collect_pax: _collectPax,
502
+ table_occupancy_duration: _tableOccupancyDuration,
503
+ ...rest
504
+ } = tempOrder.metadata || {};
505
+ return { ...rest };
506
+ })(),
507
+ products: (tempOrder.products || []).map(
508
+ (product) => normalizeSubmitProduct(product)
509
+ )
510
+ };
511
+ return enhance ? enhance(payload, { tempOrder, bookingUuid, now }) : payload;
512
+ }
513
+ function filterProductsForScanOrderMore(products) {
514
+ return (products || []).filter((p) => {
515
+ var _a;
516
+ return ((_a = p.metadata) == null ? void 0 : _a.is_rule) !== true;
517
+ });
518
+ }
519
+ function formatV1Product(products) {
520
+ return products.map((product) => {
521
+ return {
522
+ bundle: product.product_bundle,
523
+ key: product.product_id,
524
+ option: product.product_option_item,
525
+ product_id: product.product_id,
526
+ product_variant_id: product.product_variant_id,
527
+ num: product.num,
528
+ note: String(product.note ?? ""),
529
+ rowKey: product.product_id,
530
+ session: null,
531
+ unique: createUuidV4()
532
+ };
533
+ });
534
+ }
68
535
  // Annotate the CommonJS export names for ESM import in node:
69
536
  0 && (module.exports = {
537
+ buildSubmitPayload,
538
+ composeLinePrice,
539
+ createDefaultOrderRulesHooks,
540
+ createDefaultTempOrder,
541
+ createEmptySummary,
542
+ createUuidV4,
543
+ filterProductsForScanOrderMore,
544
+ formatDateTime,
545
+ formatV1Product,
70
546
  generateDuration,
71
547
  getAllDiscountList,
72
- mergeRelationForms
548
+ isTempOrder,
549
+ mergeRelationForms,
550
+ normalizeSubmitBooking,
551
+ normalizeSubmitCollectPaxValue,
552
+ resolveSubmitCollectPax,
553
+ sumOptionUnitPrice
73
554
  });
@@ -25,10 +25,10 @@ __export(utils_exports, {
25
25
  module.exports = __toCommonJS(utils_exports);
26
26
  function isNormalProduct(product) {
27
27
  var _a;
28
- if (product.duration) {
28
+ if (product == null ? void 0 : product.duration) {
29
29
  return false;
30
30
  }
31
- if ((_a = product["schedule.ids"]) == null ? void 0 : _a.length) {
31
+ if ((_a = product == null ? void 0 : product["schedule.ids"]) == null ? void 0 : _a.length) {
32
32
  return false;
33
33
  }
34
34
  return true;
@@ -11,12 +11,14 @@ export declare class ProductList extends BaseModule implements Module {
11
11
  constructor(name?: string, version?: string);
12
12
  initialize(core: PisellCore, options: any): Promise<void>;
13
13
  storeChange(path?: string, value?: any): Promise<void>;
14
- loadProducts({ category_ids, product_ids, collection, schedule_date, cacheId }: {
14
+ loadProducts({ category_ids, product_ids, collection, schedule_date, schedule_datetime, cacheId, menu_list_ids, }: {
15
15
  category_ids?: number[];
16
16
  product_ids?: number[];
17
17
  collection?: number | string[];
18
18
  schedule_date?: string;
19
+ schedule_datetime?: string;
19
20
  cacheId?: string;
21
+ menu_list_ids?: number[];
20
22
  }): Promise<any>;
21
23
  loadProductsPrice({ ids, customer_id, schedule_date, channel, }: {
22
24
  ids?: number[];
@@ -55,9 +55,11 @@ var ProductList = class extends import_BaseModule.BaseModule {
55
55
  product_ids = [],
56
56
  collection = [],
57
57
  schedule_date,
58
- cacheId
58
+ schedule_datetime,
59
+ cacheId,
60
+ menu_list_ids = []
59
61
  }) {
60
- var _a, _b;
62
+ var _a;
61
63
  let userPlugin = this.core.getPlugin("user");
62
64
  let customer_id = void 0;
63
65
  try {
@@ -65,38 +67,47 @@ var ProductList = class extends import_BaseModule.BaseModule {
65
67
  } catch (error) {
66
68
  console.error(error);
67
69
  }
68
- const productsData = await this.request.post(
69
- `/product/query`,
70
- {
71
- open_quotation: 1,
72
- open_bundle: 0,
73
- exclude_extension_type: [
74
- "product_party",
75
- "product_event",
76
- "product_series_event",
77
- "product_package_ticket",
78
- "ticket",
79
- "event_item"
80
- ],
81
- with: ["category", "collection", "resourceRelation"],
82
- status: "published",
83
- num: 500,
84
- skip: 1,
85
- customer_id,
86
- category_ids,
87
- ids: product_ids,
88
- collection,
89
- front_end_cache_id: cacheId,
90
- // client_schedule_ids: schedule_ids,
91
- schedule_date,
92
- application_code: (_b = this.otherParams) == null ? void 0 : _b.channel,
93
- is_eject: 1
94
- },
95
- { useCache: true }
96
- );
97
- const sortedList = (productsData.data.list || []).slice().sort((a, b) => Number(b.sort) - Number(a.sort));
98
- this.addProduct(sortedList);
99
- return sortedList;
70
+ try {
71
+ const productsData = await this.request.post(
72
+ `/product/query`,
73
+ {
74
+ open_quotation: 1,
75
+ open_bundle: 0,
76
+ exclude_extension_type: [
77
+ "product_party",
78
+ "product_event",
79
+ "product_series_event",
80
+ "product_package_ticket",
81
+ "ticket",
82
+ "event_item"
83
+ ],
84
+ with: ["category", "collection", "resourceRelation"],
85
+ status: "published",
86
+ num: 500,
87
+ skip: 1,
88
+ customer_id,
89
+ category_ids,
90
+ ids: product_ids,
91
+ collection,
92
+ front_end_cache_id: cacheId,
93
+ // client_schedule_ids: schedule_ids,
94
+ schedule_date,
95
+ schedule_datetime,
96
+ // application_code: this.otherParams?.channel === 'online_store' ? 'online-store' : this.otherParams?.channel,
97
+ application_code: "online-store",
98
+ is_eject: 1,
99
+ menu_list_ids,
100
+ open_deposit: 1
101
+ },
102
+ { useCache: true, customToast: () => {
103
+ } }
104
+ );
105
+ const sortedList = (productsData.data.list || []).slice().sort((a, b) => Number(b.sort) - Number(a.sort));
106
+ this.addProduct(sortedList);
107
+ return sortedList;
108
+ } catch (error) {
109
+ return error;
110
+ }
100
111
  }
101
112
  async loadProductsPrice({
102
113
  ids = [],
@@ -0,0 +1,48 @@
1
+ import { Module, PisellCore, ModuleOptions } from '../../types';
2
+ import { BaseModule } from '../BaseModule';
3
+ import type { ScheduleItem } from '../Schedule/types';
4
+ import type { QuotationItem } from './types';
5
+ export type { QuotationItem, QuotationProductData, QuotationSchedule, QuotationState } from './types';
6
+ export declare class QuotationModule extends BaseModule implements Module {
7
+ protected defaultName: string;
8
+ protected defaultVersion: string;
9
+ private request;
10
+ private store;
11
+ private scheduleResolver?;
12
+ constructor(name?: string, version?: string);
13
+ initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
14
+ loadQuotations(params?: {
15
+ channel?: string;
16
+ }): Promise<void>;
17
+ getQuotationList(): QuotationItem[];
18
+ /**
19
+ * Look up the quotation price for a specific product (+ optional variant) at a given datetime.
20
+ * Returns the price as a string (e.g. "300.00"), or null if no quotation applies.
21
+ *
22
+ * Priority: iterates quotations already sorted by `sort` ascending (lowest = highest priority).
23
+ * First matching quotation whose schedule covers `datetime` and whose product_data contains
24
+ * the requested productId wins.
25
+ */
26
+ getPriceForProduct(params: {
27
+ productId: number;
28
+ variantId?: number;
29
+ datetime: string;
30
+ }): string | null;
31
+ getQuotationShelfId(params: {
32
+ productId: number;
33
+ variantId?: number;
34
+ datetime: string;
35
+ }): number;
36
+ /**
37
+ * Batch pre-compute quotation prices for a set of products across multiple time points.
38
+ * Key format: `${productId}:${timePoint}`
39
+ * This avoids repeated schedule matching when the same product appears in multiple resource rows.
40
+ */
41
+ buildProductPriceMap(params: {
42
+ productIds: number[];
43
+ timePoints: string[];
44
+ }): Map<string, string | null>;
45
+ setScheduleResolver(resolver: (id: number) => ScheduleItem | undefined): void;
46
+ private isQuotationActiveAt;
47
+ private findProductData;
48
+ }