@pisell/pisellos 2.3.74 → 2.3.76

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 (283) hide show
  1. package/dist/core/index.js +6 -10
  2. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  3. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  4. package/dist/model/strategy/strategy-example.js +5 -19
  5. package/dist/modules/Cart/index.js +0 -3
  6. package/dist/modules/Cart/utils/cartProduct.js +0 -1
  7. package/dist/modules/Date/index.js +1 -5
  8. package/dist/modules/Discount/index.js +2 -4
  9. package/dist/modules/OpenData/index.js +0 -2
  10. package/dist/modules/Order/index.d.ts +1 -1
  11. package/dist/modules/Order/index.js +75 -91
  12. package/dist/modules/Order/types.d.ts +3 -1
  13. package/dist/modules/Payment/index.js +97 -162
  14. package/dist/modules/Rules/index.js +1 -4
  15. package/dist/modules/Schedule/index.js +0 -1
  16. package/dist/modules/Schedule/utils.js +0 -1
  17. package/dist/modules/Step/index.js +0 -1
  18. package/dist/plugins/request.js +1 -4
  19. package/dist/plugins/window.js +2 -6
  20. package/dist/server/index.js +97 -129
  21. package/dist/server/modules/menu/index.js +32 -41
  22. package/dist/server/modules/order/index.js +2 -4
  23. package/dist/server/modules/products/index.js +24 -42
  24. package/dist/server/modules/quotation/index.js +29 -38
  25. package/dist/server/modules/resource/index.js +3 -4
  26. package/dist/server/modules/schedule/index.js +27 -35
  27. package/dist/server/utils/product.js +0 -1
  28. package/dist/solution/BaseSales/index.js +100 -72
  29. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
  30. package/dist/solution/BaseSales/utils/cartPromotion.js +15 -6
  31. package/dist/solution/BookingByStep/index.js +7 -59
  32. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  33. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  34. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  35. package/dist/solution/BookingTicket/index.js +0 -2
  36. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
  37. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  38. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  39. package/dist/solution/BuyTickets/index.js +9 -12
  40. package/dist/solution/Checkout/index.js +177 -252
  41. package/dist/solution/Checkout/utils/index.js +4 -16
  42. package/dist/solution/RegisterAndLogin/index.js +30 -76
  43. package/dist/solution/ScanOrder/index.js +50 -60
  44. package/dist/solution/ShopDiscount/index.js +2 -7
  45. package/dist/solution/VenueBooking/index.js +45 -55
  46. package/dist/utils/task.js +15 -18
  47. package/dist/utils/watch.js +0 -1
  48. package/lib/apis/picoding.js +2 -0
  49. package/lib/core/index.js +134 -134
  50. package/lib/effects/index.js +46 -57
  51. package/lib/index.js +82 -49
  52. package/lib/model/index.js +14 -21
  53. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  54. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  55. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  56. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  57. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  58. package/lib/model/strategy/adapter/index.js +100 -64
  59. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  60. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  61. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  62. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  63. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  64. package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
  65. package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
  66. package/lib/model/strategy/adapter/promotion/examples.js +222 -234
  67. package/lib/model/strategy/adapter/promotion/index.js +1 -0
  68. package/lib/model/strategy/adapter/promotion/type.js +243 -36
  69. package/lib/model/strategy/adapter/type.js +4 -16
  70. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
  71. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  72. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  73. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  74. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  75. package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
  76. package/lib/model/strategy/engine.js +270 -168
  77. package/lib/model/strategy/index.js +49 -34
  78. package/lib/model/strategy/strategy-example.js +243 -239
  79. package/lib/model/strategy/type.js +100 -40
  80. package/lib/modules/Account/index.js +39 -53
  81. package/lib/modules/Account/types.js +20 -33
  82. package/lib/modules/AccountList/index.js +116 -154
  83. package/lib/modules/AccountList/types.js +30 -31
  84. package/lib/modules/AccountList/utils.js +18 -30
  85. package/lib/modules/BaseModule.js +23 -42
  86. package/lib/modules/BookingContext/index.js +158 -136
  87. package/lib/modules/BookingContext/types.js +46 -32
  88. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
  89. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
  90. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
  91. package/lib/modules/BookingContext/utils/flexible.js +38 -55
  92. package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
  93. package/lib/modules/BookingContext/utils/index.js +124 -41
  94. package/lib/modules/BookingContext/utils/noResource.js +58 -70
  95. package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
  96. package/lib/modules/BookingContext/utils/productExtend.js +202 -155
  97. package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
  98. package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
  99. package/lib/modules/BookingContext/utils/resources.js +209 -167
  100. package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
  101. package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
  102. package/lib/modules/Cart/index.js +170 -124
  103. package/lib/modules/Cart/types.js +46 -51
  104. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  105. package/lib/modules/Cart/utils/cartDate.js +56 -61
  106. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  107. package/lib/modules/Cart/utils/cartNote.js +27 -32
  108. package/lib/modules/Cart/utils/cartProduct.js +321 -251
  109. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  110. package/lib/modules/Cart/utils/cartResource.js +70 -78
  111. package/lib/modules/Cart/utils/changePrice.js +22 -50
  112. package/lib/modules/Cart/utils/index.js +106 -48
  113. package/lib/modules/Customer/constants.js +13 -34
  114. package/lib/modules/Customer/index.js +235 -172
  115. package/lib/modules/Customer/types.js +38 -35
  116. package/lib/modules/Date/index.js +116 -115
  117. package/lib/modules/Date/types.js +16 -28
  118. package/lib/modules/Date/utils.js +174 -123
  119. package/lib/modules/Discount/index.js +122 -127
  120. package/lib/modules/Discount/types.js +9 -31
  121. package/lib/modules/Guests/index.js +30 -56
  122. package/lib/modules/Guests/types.js +23 -33
  123. package/lib/modules/Holder/index.js +209 -189
  124. package/lib/modules/Holder/types.js +4 -16
  125. package/lib/modules/Holder/utils.js +20 -49
  126. package/lib/modules/OpenData/index.js +70 -76
  127. package/lib/modules/OpenData/types.js +4 -16
  128. package/lib/modules/OpenData/utils.js +44 -78
  129. package/lib/modules/Order/index.d.ts +1 -1
  130. package/lib/modules/Order/index.js +1733 -2121
  131. package/lib/modules/Order/payment-utils.js +77 -120
  132. package/lib/modules/Order/types.d.ts +3 -1
  133. package/lib/modules/Order/types.js +88 -35
  134. package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
  135. package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
  136. package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
  137. package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
  138. package/lib/modules/Order/utils.js +814 -647
  139. package/lib/modules/Payment/cash.js +20 -33
  140. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  141. package/lib/modules/Payment/eftpos.js +16 -30
  142. package/lib/modules/Payment/index.js +532 -399
  143. package/lib/modules/Payment/mx51.js +1 -0
  144. package/lib/modules/Payment/types.js +230 -108
  145. package/lib/modules/Payment/utils.js +52 -51
  146. package/lib/modules/Payment/walletpass.js +485 -660
  147. package/lib/modules/Product/index.js +51 -46
  148. package/lib/modules/Product/types.js +4 -16
  149. package/lib/modules/Product/utils.js +32 -33
  150. package/lib/modules/ProductList/index.js +113 -123
  151. package/lib/modules/ProductList/types.js +9 -31
  152. package/lib/modules/Quotation/index.js +81 -118
  153. package/lib/modules/Quotation/types.js +4 -16
  154. package/lib/modules/Resource/index.js +27 -59
  155. package/lib/modules/Resource/types.js +22 -32
  156. package/lib/modules/Resource/utils.js +30 -38
  157. package/lib/modules/ResourcePlanner/index.js +25 -23
  158. package/lib/modules/ResourcePlanner/localClock.js +54 -119
  159. package/lib/modules/ResourcePlanner/planner.js +589 -770
  160. package/lib/modules/ResourcePlanner/types.js +10 -29
  161. package/lib/modules/Rules/index.js +1218 -959
  162. package/lib/modules/Rules/types.js +17 -40
  163. package/lib/modules/SalesSummary/index.js +85 -90
  164. package/lib/modules/SalesSummary/types.js +4 -16
  165. package/lib/modules/SalesSummary/utils.js +355 -430
  166. package/lib/modules/ScanOrderLogger/index.js +59 -79
  167. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  168. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  169. package/lib/modules/ScanOrderLogger/types.js +4 -16
  170. package/lib/modules/Schedule/getDateIsInSchedule.js +334 -163
  171. package/lib/modules/Schedule/index.js +100 -114
  172. package/lib/modules/Schedule/type.js +4 -16
  173. package/lib/modules/Schedule/types.js +4 -16
  174. package/lib/modules/Schedule/utils.js +433 -291
  175. package/lib/modules/Step/index.js +40 -52
  176. package/lib/modules/Step/tyeps.js +4 -16
  177. package/lib/modules/Summary/index.js +66 -71
  178. package/lib/modules/Summary/types.js +4 -16
  179. package/lib/modules/Summary/utils.js +773 -418
  180. package/lib/modules/SurchargeList/index.js +46 -60
  181. package/lib/modules/SurchargeList/types.js +4 -16
  182. package/lib/modules/index.js +245 -63
  183. package/lib/plugins/app.js +4 -16
  184. package/lib/plugins/index.js +36 -25
  185. package/lib/plugins/request.js +137 -126
  186. package/lib/plugins/shopStore.js +4 -16
  187. package/lib/plugins/user.js +4 -16
  188. package/lib/plugins/window.js +171 -179
  189. package/lib/server/index.js +3050 -2665
  190. package/lib/server/modules/floor-plan/index.js +118 -134
  191. package/lib/server/modules/floor-plan/types.js +15 -30
  192. package/lib/server/modules/index.js +106 -68
  193. package/lib/server/modules/menu/index.js +142 -122
  194. package/lib/server/modules/menu/types.js +18 -31
  195. package/lib/server/modules/order/index.js +784 -1002
  196. package/lib/server/modules/order/types.js +122 -33
  197. package/lib/server/modules/order/utils/filterBookings.js +219 -194
  198. package/lib/server/modules/order/utils/filterOrders.js +118 -92
  199. package/lib/server/modules/payment/index.js +59 -83
  200. package/lib/server/modules/payment/types.js +4 -16
  201. package/lib/server/modules/products/index.js +583 -471
  202. package/lib/server/modules/products/types.js +44 -34
  203. package/lib/server/modules/quotation/index.js +137 -172
  204. package/lib/server/modules/quotation/types.js +21 -31
  205. package/lib/server/modules/resource/index.js +220 -186
  206. package/lib/server/modules/resource/types.js +42 -33
  207. package/lib/server/modules/schedule/index.js +135 -123
  208. package/lib/server/modules/schedule/types.js +14 -21
  209. package/lib/server/modules/schedule/utils.js +334 -163
  210. package/lib/server/types.js +4 -16
  211. package/lib/server/utils/index.js +25 -23
  212. package/lib/server/utils/product.js +196 -139
  213. package/lib/server/utils/schedule.js +34 -41
  214. package/lib/server/utils/small-ticket.js +479 -456
  215. package/lib/server/utils/time.js +40 -49
  216. package/lib/solution/BaseSales/index.js +1220 -1412
  217. package/lib/solution/BaseSales/types.js +42 -38
  218. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
  219. package/lib/solution/BaseSales/utils/cartPromotion.js +652 -498
  220. package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
  221. package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
  222. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +108 -145
  223. package/lib/solution/BaseSales/utils.js +158 -143
  224. package/lib/solution/BookingByStep/index.js +1527 -1340
  225. package/lib/solution/BookingByStep/types.js +40 -99
  226. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  227. package/lib/solution/BookingByStep/utils/products.js +42 -52
  228. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  229. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  230. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  231. package/lib/solution/BookingTicket/index.js +607 -522
  232. package/lib/solution/BookingTicket/types.js +99 -77
  233. package/lib/solution/BookingTicket/utils/addProductDecision.js +226 -189
  234. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
  235. package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
  236. package/lib/solution/BookingTicket/utils/cartView.js +114 -99
  237. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  238. package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
  239. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
  240. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
  241. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
  242. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
  243. package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
  244. package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
  245. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  246. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
  247. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
  248. package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
  249. package/lib/solution/BuyTickets/index.js +67 -70
  250. package/lib/solution/BuyTickets/types.js +22 -38
  251. package/lib/solution/Checkout/index.js +1451 -1158
  252. package/lib/solution/Checkout/types.js +91 -61
  253. package/lib/solution/Checkout/utils/index.js +228 -156
  254. package/lib/solution/PlaceOrder/index.js +55 -0
  255. package/lib/solution/RegisterAndLogin/config.js +493 -460
  256. package/lib/solution/RegisterAndLogin/index.js +633 -630
  257. package/lib/solution/RegisterAndLogin/types.js +189 -76
  258. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  259. package/lib/solution/Sales/index.js +328 -324
  260. package/lib/solution/Sales/types.js +27 -33
  261. package/lib/solution/ScanOrder/index.js +832 -864
  262. package/lib/solution/ScanOrder/types.js +33 -34
  263. package/lib/solution/ScanOrder/utils.js +409 -374
  264. package/lib/solution/ShopDiscount/index.js +226 -232
  265. package/lib/solution/ShopDiscount/types.js +15 -37
  266. package/lib/solution/ShopDiscount/utils.js +300 -172
  267. package/lib/solution/UnifiedBookingSales/index.js +1035 -1201
  268. package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
  269. package/lib/solution/UnifiedBookingSales/types.js +10 -32
  270. package/lib/solution/VenueBooking/index.js +811 -879
  271. package/lib/solution/VenueBooking/types.js +19 -39
  272. package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
  273. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  274. package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
  275. package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
  276. package/lib/solution/VenueBooking/utils.js +130 -67
  277. package/lib/solution/index.js +124 -41
  278. package/lib/store/createStore.js +32 -29
  279. package/lib/types/index.js +4 -16
  280. package/lib/utils/payment-number.js +26 -46
  281. package/lib/utils/task.js +36 -36
  282. package/lib/utils/watch.js +81 -47
  283. package/package.json +2 -1
@@ -1,88 +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 });
10
- };
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 });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
-
29
- // src/solution/ShopDiscount/utils.ts
30
- var utils_exports = {};
31
- __export(utils_exports, {
32
- calculateOrderLevelDiscountAllocation: () => calculateOrderLevelDiscountAllocation,
33
- filterDiscountListByBookingTime: () => filterDiscountListByBookingTime,
34
- getDateIsInSchedule: () => getDateIsInSchedule,
35
- getDiscountAmount: () => getDiscountAmount,
36
- getDiscountListAmount: () => getDiscountListAmount,
37
- getDiscountListAmountTotal: () => getDiscountListAmountTotal,
38
- isAllNormalProduct: () => isAllNormalProduct,
39
- isNormalProductByDurationSchedule: () => isNormalProductByDurationSchedule,
40
- isOrderLevelFixedAmountDiscount: () => isOrderLevelFixedAmountDiscount,
41
- uniqueById: () => uniqueById
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
42
5
  });
43
- module.exports = __toCommonJS(utils_exports);
44
- var import_decimal = __toESM(require("decimal.js"));
45
- var import_dayjs = __toESM(require("dayjs"));
46
- var uniqueById = (arr, key = "id") => {
47
- const seen = /* @__PURE__ */ new Set();
48
- return arr.filter((item) => !seen.has(item[key]) && seen.add(item[key]));
6
+ exports.uniqueById = exports.isOrderLevelFixedAmountDiscount = exports.isNormalProductByDurationSchedule = exports.isAllNormalProduct = exports.getDiscountListAmountTotal = exports.getDiscountListAmount = exports.getDiscountAmount = exports.getDateIsInSchedule = exports.filterDiscountListByBookingTime = exports.calculateOrderLevelDiscountAllocation = void 0;
7
+ var _decimal = _interopRequireDefault(require("decimal.js"));
8
+ var _dayjs = _interopRequireDefault(require("dayjs"));
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ const uniqueById = (arr, key = 'id') => {
11
+ const seen = new Set();
12
+ return arr.filter(item => !seen.has(item[key]) && seen.add(item[key]));
49
13
  };
50
- var isNormalProductByDurationSchedule = (item) => {
51
- var _a, _b;
52
- return !(item == null ? void 0 : item.duration) && !((_a = item == null ? void 0 : item.schedules) == null ? void 0 : _a.length) && !((_b = item == null ? void 0 : item["schedule.ids"]) == null ? void 0 : _b.length);
14
+
15
+ // 非预约商品 通过时长和日程判断是否是普通商品
16
+ exports.uniqueById = uniqueById;
17
+ const isNormalProductByDurationSchedule = item => {
18
+ return !item?.duration && !item?.schedules?.length && !item?.['schedule.ids']?.length;
53
19
  };
54
- var isAllNormalProduct = (items) => {
55
- return items.every((item) => isNormalProductByDurationSchedule(item));
20
+
21
+ // 是否全部是普通商品
22
+ exports.isNormalProductByDurationSchedule = isNormalProductByDurationSchedule;
23
+ const isAllNormalProduct = items => {
24
+ return items.every(item => isNormalProductByDurationSchedule(item));
56
25
  };
57
- var getDiscountAmount = (discount, total, price) => {
58
- var _a;
59
- if (discount.tag === "good_pass") {
60
- return new import_decimal.default(price).minus(new import_decimal.default(price || 0)).toNumber();
26
+
27
+ /**
28
+ * 获取折扣金额 基于折扣卡类型计算
29
+ * 商品券:直接返回商品价格
30
+ * 折扣卡:根据折扣卡类型计算 固定金额:直接返回折扣卡金额 百分比:根据折扣卡金额计算
31
+ * @param discount
32
+ * @param total
33
+ * @param price
34
+ * @returns
35
+ */
36
+ exports.isAllNormalProduct = isAllNormalProduct;
37
+ const getDiscountAmount = (discount, total, price) => {
38
+ // 商品券
39
+ if (discount.tag === 'good_pass') {
40
+ return new _decimal.default(price).minus(new _decimal.default(price || 0)).toNumber();
61
41
  }
62
- const isFixedAmount = ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.discount_card_type) === "fixed_amount";
42
+
43
+ // 判断是否是固定金额
44
+ const isFixedAmount = discount?.metadata?.discount_card_type === 'fixed_amount';
45
+
46
+ // 固定金额 小于0时返回0
63
47
  if (isFixedAmount) {
64
- return Math.max(new import_decimal.default(price).minus(new import_decimal.default((discount.amount ?? discount.par_value) || 0)).toNumber(), 0);
48
+ return Math.max(new _decimal.default(price).minus(new _decimal.default((discount.amount ?? discount.par_value) || 0)).toNumber(), 0);
65
49
  }
66
- return new import_decimal.default(100).minus(discount.par_value || 0).div(100).mul(new import_decimal.default(price)).toNumber();
50
+
51
+ // 百分比:根据折扣卡金额计算
52
+ return new _decimal.default(100).minus(discount.par_value || 0).div(100).mul(new _decimal.default(price)).toNumber();
67
53
  };
68
- var getDiscountListAmountTotal = (discount) => {
54
+ exports.getDiscountAmount = getDiscountAmount;
55
+ const getDiscountListAmountTotal = discount => {
69
56
  return discount.reduce((acc, cur) => {
70
- return new import_decimal.default(acc).plus(new import_decimal.default(cur.num || 1).mul(new import_decimal.default(cur.amount || 0))).toNumber();
71
- }, new import_decimal.default(0));
57
+ return new _decimal.default(acc).plus(new _decimal.default(cur.num || 1).mul(new _decimal.default(cur.amount || 0))).toNumber();
58
+ }, new _decimal.default(0));
72
59
  };
73
- var getDiscountListAmount = (discount) => {
60
+
61
+ /**
62
+ * 获取折扣金额 计算每个折扣的金额
63
+ * @param discount
64
+ * @returns
65
+ */
66
+ exports.getDiscountListAmountTotal = getDiscountListAmountTotal;
67
+ const getDiscountListAmount = discount => {
74
68
  return discount.reduce((acc, cur) => {
75
- return new import_decimal.default(acc).plus(new import_decimal.default(cur.amount || 0)).toNumber();
76
- }, new import_decimal.default(0));
69
+ return new _decimal.default(acc).plus(new _decimal.default(cur.amount || 0)).toNumber();
70
+ }, new _decimal.default(0));
77
71
  };
78
- var getDateIsInSchedule = (dateTime, scheduleList) => {
72
+
73
+ // 日程项接口定义
74
+ exports.getDiscountListAmount = getDiscountListAmount;
75
+ // 获取时间是否在日程范围内
76
+ const getDateIsInSchedule = (dateTime, scheduleList) => {
79
77
  if (!dateTime || !scheduleList || scheduleList.length === 0) {
80
78
  return false;
81
79
  }
82
- const targetDate = (0, import_dayjs.default)(dateTime);
80
+ const targetDate = (0, _dayjs.default)(dateTime);
83
81
  if (!targetDate.isValid()) {
84
82
  return false;
85
83
  }
84
+
85
+ // 遍历所有日程项
86
86
  for (const schedule of scheduleList) {
87
87
  if (isTimeInScheduleItem(dateTime, schedule)) {
88
88
  return true;
@@ -90,284 +90,422 @@ var getDateIsInSchedule = (dateTime, scheduleList) => {
90
90
  }
91
91
  return false;
92
92
  };
93
- var isTimeInScheduleItem = (dateTime, schedule) => {
94
- const targetDate = (0, import_dayjs.default)(dateTime);
95
- const targetDateString = dateTime.split(" ")[0];
96
- const targetTimeString = dateTime.split(" ")[1] || "00:00:00";
93
+
94
+ // 判断时间是否在单个日程项范围内
95
+ exports.getDateIsInSchedule = getDateIsInSchedule;
96
+ const isTimeInScheduleItem = (dateTime, schedule) => {
97
+ const targetDate = (0, _dayjs.default)(dateTime);
98
+ const targetDateString = dateTime.split(' ')[0]; // YYYY-MM-DD
99
+ const targetTimeString = dateTime.split(' ')[1] || '00:00:00'; // HH:mm:ss
100
+
97
101
  switch (schedule.type) {
98
- case "standard":
102
+ case 'standard':
99
103
  return isInStandardSchedule(targetDate, targetDateString, targetTimeString, schedule);
100
- case "time-slots":
104
+ case 'time-slots':
101
105
  return isInTimeSlotsSchedule(targetDate, targetDateString, targetTimeString, schedule);
102
- case "designation":
106
+ case 'designation':
103
107
  return isInDesignationSchedule(targetDate, targetDateString, targetTimeString, schedule);
104
108
  default:
105
109
  return false;
106
110
  }
107
111
  };
108
- var isInStandardSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
112
+
113
+ // 处理标准类型日程
114
+ const isInStandardSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
109
115
  if (!schedule.start_time || !schedule.end_time) {
110
116
  return false;
111
117
  }
112
- const startDate = (0, import_dayjs.default)(schedule.start_time);
113
- const endDate = (0, import_dayjs.default)(schedule.end_time);
118
+ const startDate = (0, _dayjs.default)(schedule.start_time);
119
+ const endDate = (0, _dayjs.default)(schedule.end_time);
120
+
121
+ // 先检查是否在基础时间范围内(不考虑重复)
114
122
  const isInBasicRange = targetDate.isSameOrAfter(startDate) && targetDate.isSameOrBefore(endDate);
115
- if (schedule.repeat_type === "none") {
123
+ if (schedule.repeat_type === 'none') {
116
124
  return isInBasicRange;
117
125
  }
126
+
127
+ // 处理重复日程
118
128
  return isInRepeatingSchedule(targetDate, targetDateString, targetTimeString, schedule, startDate, endDate);
119
129
  };
120
- var isInTimeSlotsSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
130
+
131
+ // 处理时间段类型日程
132
+ const isInTimeSlotsSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
121
133
  if (!schedule.start_time) {
122
134
  return false;
123
135
  }
124
- if (schedule.repeat_type === "none") {
125
- const scheduleDate = schedule.start_time.split(" ")[0];
136
+
137
+ // 如果不重复,使用原有逻辑
138
+ if (schedule.repeat_type === 'none') {
139
+ const scheduleDate = schedule.start_time.split(' ')[0];
140
+
141
+ // 检查日期是否匹配
126
142
  if (targetDateString !== scheduleDate) {
127
143
  return false;
128
144
  }
145
+
146
+ // 检查是否在任一时间段内
129
147
  return checkTimeSlotsForDate(targetDate, targetDateString, schedule.time_slot);
130
148
  }
149
+
150
+ // 处理重复日程
131
151
  return isInTimeSlotsRepeatingSchedule(targetDate, targetDateString, targetTimeString, schedule);
132
152
  };
133
- var isInDesignationSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
153
+
154
+ // 处理指定类型日程
155
+ const isInDesignationSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
134
156
  if (!schedule.designation) {
135
157
  return false;
136
158
  }
137
159
  for (const designation of schedule.designation) {
138
160
  const startDateTime = `${designation.start_date} ${designation.start_time}:00`;
139
161
  const endDateTime = `${designation.end_date} ${designation.end_time}:00`;
140
- const startDate = (0, import_dayjs.default)(startDateTime);
141
- const endDate = (0, import_dayjs.default)(endDateTime);
162
+ const startDate = (0, _dayjs.default)(startDateTime);
163
+ const endDate = (0, _dayjs.default)(endDateTime);
142
164
  if (targetDate.isSameOrAfter(startDate) && targetDate.isSameOrBefore(endDate)) {
143
165
  return true;
144
166
  }
145
167
  }
146
168
  return false;
147
169
  };
148
- var isInRepeatingSchedule = (targetDate, targetDateString, targetTimeString, schedule, startDate, endDate) => {
170
+
171
+ // 处理重复日程逻辑
172
+ const isInRepeatingSchedule = (targetDate, targetDateString, targetTimeString, schedule, startDate, endDate) => {
149
173
  if (!schedule.repeat_rule) {
150
174
  return false;
151
175
  }
152
- const { repeat_rule, repeat_type } = schedule;
153
- const targetDateOnly = (0, import_dayjs.default)(targetDateString);
176
+ const {
177
+ repeat_rule,
178
+ repeat_type
179
+ } = schedule;
180
+ const targetDateOnly = (0, _dayjs.default)(targetDateString); // 只取日期部分
181
+
182
+ // 首先检查是否在包含日期中(包含日期是额外增加的有效日期)
154
183
  if (repeat_rule.included_date && repeat_rule.included_date.length > 0) {
155
184
  for (const includedDate of repeat_rule.included_date) {
156
- const includeStartDate = (0, import_dayjs.default)(includedDate.start);
157
- const includeEndDate = (0, import_dayjs.default)(includedDate.end);
158
- if (targetDateOnly.isSameOrAfter(includeStartDate, "day") && targetDateOnly.isSameOrBefore(includeEndDate, "day")) {
185
+ const includeStartDate = (0, _dayjs.default)(includedDate.start);
186
+ const includeEndDate = (0, _dayjs.default)(includedDate.end);
187
+ if (targetDateOnly.isSameOrAfter(includeStartDate, 'day') && targetDateOnly.isSameOrBefore(includeEndDate, 'day')) {
188
+ // 在包含日期中,直接返回true,无需检查其他条件
159
189
  return true;
160
190
  }
161
191
  }
162
192
  }
193
+
194
+ // 检查是否在排除日期中
163
195
  for (const excludedDate of repeat_rule.excluded_date) {
164
- const excludeStartDate = (0, import_dayjs.default)(excludedDate.start);
165
- const excludeEndDate = (0, import_dayjs.default)(excludedDate.end);
166
- if (targetDateOnly.isSameOrAfter(excludeStartDate, "day") && targetDateOnly.isSameOrBefore(excludeEndDate, "day")) {
196
+ const excludeStartDate = (0, _dayjs.default)(excludedDate.start);
197
+ const excludeEndDate = (0, _dayjs.default)(excludedDate.end);
198
+ // 检查目标日期是否在排除范围内(包含边界)
199
+ if (targetDateOnly.isSameOrAfter(excludeStartDate, 'day') && targetDateOnly.isSameOrBefore(excludeEndDate, 'day')) {
167
200
  return false;
168
201
  }
169
202
  }
170
- if (repeat_rule.end.type === "date" && repeat_rule.end.end_date) {
171
- const ruleEndDate = (0, import_dayjs.default)(repeat_rule.end.end_date);
203
+
204
+ // 检查重复规则的结束条件
205
+ if (repeat_rule.end.type === 'date' && repeat_rule.end.end_date) {
206
+ const ruleEndDate = (0, _dayjs.default)(repeat_rule.end.end_date);
172
207
  if (targetDate.isAfter(ruleEndDate)) {
173
208
  return false;
174
209
  }
175
210
  }
211
+
212
+ // 根据重复类型检查
176
213
  switch (repeat_type) {
177
- case "daily":
214
+ case 'daily':
178
215
  return isInDailyRepeat(targetDate, startDate, endDate, repeat_rule);
179
- case "weekly":
216
+ case 'weekly':
180
217
  return isInWeeklyRepeat(targetDate, startDate, endDate, repeat_rule);
181
218
  default:
182
219
  return false;
220
+ // 不支持月和年重复
183
221
  }
184
222
  };
185
- var isInDailyRepeat = (targetDate, startDate, endDate, repeatRule) => {
186
- const daysDiff = targetDate.diff(startDate, "day");
223
+
224
+ // 每日重复逻辑
225
+ const isInDailyRepeat = (targetDate, startDate, endDate, repeatRule) => {
226
+ const daysDiff = targetDate.diff(startDate, 'day');
187
227
  if (daysDiff < 0) {
188
228
  return false;
189
229
  }
230
+
231
+ // 检查频率
190
232
  if (daysDiff % repeatRule.frequency !== 0) {
191
233
  return false;
192
234
  }
235
+
236
+ // 检查时间是否在日程的时间范围内
193
237
  const targetTimeOfDay = targetDate.hour() * 3600 + targetDate.minute() * 60 + targetDate.second();
194
238
  const startTimeOfDay = startDate.hour() * 3600 + startDate.minute() * 60 + startDate.second();
195
239
  const endTimeOfDay = endDate.hour() * 3600 + endDate.minute() * 60 + endDate.second();
240
+
241
+ // 每日重复:每天都在相同的时间段内有效
242
+ // 例如:01:00:00 - 16:00:00,每天都是这个时间段
196
243
  return targetTimeOfDay >= startTimeOfDay && targetTimeOfDay <= endTimeOfDay;
197
244
  };
198
- var isInWeeklyRepeat = (targetDate, startDate, endDate, repeatRule) => {
199
- const targetDayOfWeek = targetDate.day();
245
+
246
+ // 每周重复逻辑
247
+ const isInWeeklyRepeat = (targetDate, startDate, endDate, repeatRule) => {
248
+ const targetDayOfWeek = targetDate.day(); // 0=周日, 1=周一, ..., 6=周六
249
+
250
+ // 检查是否在指定的星期几内
200
251
  if (!repeatRule.frequency_date.includes(targetDayOfWeek)) {
201
252
  return false;
202
253
  }
203
- const weeksDiff = targetDate.diff(startDate, "week");
254
+
255
+ // 计算周差
256
+ const weeksDiff = targetDate.diff(startDate, 'week');
204
257
  if (weeksDiff < 0) {
205
258
  return false;
206
259
  }
260
+
261
+ // 检查频率
207
262
  if (weeksDiff % repeatRule.frequency !== 0) {
208
263
  return false;
209
264
  }
265
+
266
+ // 检查时间是否在日程的时间范围内
210
267
  const targetTimeOfDay = targetDate.hour() * 3600 + targetDate.minute() * 60 + targetDate.second();
211
268
  const startTimeOfDay = startDate.hour() * 3600 + startDate.minute() * 60 + startDate.second();
212
269
  const endTimeOfDay = endDate.hour() * 3600 + endDate.minute() * 60 + endDate.second();
213
270
  return targetTimeOfDay >= startTimeOfDay && targetTimeOfDay <= endTimeOfDay;
214
271
  };
215
- var isInTimeSlotsRepeatingSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
272
+
273
+ // 处理 time-slots 类型的重复日程
274
+ const isInTimeSlotsRepeatingSchedule = (targetDate, targetDateString, targetTimeString, schedule) => {
216
275
  if (!schedule.repeat_rule || !schedule.start_time) {
217
276
  return false;
218
277
  }
219
- const { repeat_rule, repeat_type } = schedule;
220
- const startDate = (0, import_dayjs.default)(schedule.start_time);
221
- const targetDateOnly = (0, import_dayjs.default)(targetDateString);
278
+ const {
279
+ repeat_rule,
280
+ repeat_type
281
+ } = schedule;
282
+ const startDate = (0, _dayjs.default)(schedule.start_time);
283
+ const targetDateOnly = (0, _dayjs.default)(targetDateString);
284
+
285
+ // 检查包含日期
222
286
  if (repeat_rule.included_date && repeat_rule.included_date.length > 0) {
223
287
  for (const includedDate of repeat_rule.included_date) {
224
- const includeStartDate = (0, import_dayjs.default)(includedDate.start);
225
- const includeEndDate = (0, import_dayjs.default)(includedDate.end);
226
- if (targetDateOnly.isSameOrAfter(includeStartDate, "day") && targetDateOnly.isSameOrBefore(includeEndDate, "day")) {
288
+ const includeStartDate = (0, _dayjs.default)(includedDate.start);
289
+ const includeEndDate = (0, _dayjs.default)(includedDate.end);
290
+ if (targetDateOnly.isSameOrAfter(includeStartDate, 'day') && targetDateOnly.isSameOrBefore(includeEndDate, 'day')) {
291
+ // 在包含日期中,检查时间段
227
292
  return checkTimeSlotsForDate(targetDate, targetDateString, schedule.time_slot);
228
293
  }
229
294
  }
230
295
  }
296
+
297
+ // 检查排除日期
231
298
  for (const excludedDate of repeat_rule.excluded_date) {
232
- const excludeStartDate = (0, import_dayjs.default)(excludedDate.start);
233
- const excludeEndDate = (0, import_dayjs.default)(excludedDate.end);
234
- if (targetDateOnly.isSameOrAfter(excludeStartDate, "day") && targetDateOnly.isSameOrBefore(excludeEndDate, "day")) {
299
+ const excludeStartDate = (0, _dayjs.default)(excludedDate.start);
300
+ const excludeEndDate = (0, _dayjs.default)(excludedDate.end);
301
+ if (targetDateOnly.isSameOrAfter(excludeStartDate, 'day') && targetDateOnly.isSameOrBefore(excludeEndDate, 'day')) {
235
302
  return false;
236
303
  }
237
304
  }
238
- if (repeat_rule.end.type === "date" && repeat_rule.end.end_date) {
239
- const ruleEndDate = (0, import_dayjs.default)(repeat_rule.end.end_date);
240
- if (targetDateOnly.isAfter(ruleEndDate, "day")) {
305
+
306
+ // 检查重复规则的结束条件
307
+ if (repeat_rule.end.type === 'date' && repeat_rule.end.end_date) {
308
+ const ruleEndDate = (0, _dayjs.default)(repeat_rule.end.end_date);
309
+ if (targetDateOnly.isAfter(ruleEndDate, 'day')) {
241
310
  return false;
242
311
  }
243
312
  }
313
+
314
+ // 检查目标日期是否在重复规则范围内
244
315
  let isDateValid = false;
245
316
  switch (repeat_type) {
246
- case "daily":
317
+ case 'daily':
247
318
  isDateValid = isInDailyRepeatForDate(targetDateOnly, startDate, repeat_rule);
248
319
  break;
249
- case "weekly":
320
+ case 'weekly':
250
321
  isDateValid = isInWeeklyRepeatForDate(targetDateOnly, startDate, repeat_rule);
251
322
  break;
252
323
  default:
253
324
  return false;
254
325
  }
326
+
327
+ // 如果日期有效,检查时间段
255
328
  if (isDateValid) {
256
329
  return checkTimeSlotsForDate(targetDate, targetDateString, schedule.time_slot);
257
330
  }
258
331
  return false;
259
332
  };
260
- var checkTimeSlotsForDate = (targetDate, targetDateString, timeSlots) => {
333
+
334
+ // 检查目标时间是否在某个时间段内(使用目标日期 + time_slot 时间)
335
+ const checkTimeSlotsForDate = (targetDate, targetDateString, timeSlots) => {
261
336
  for (const timeSlot of timeSlots) {
262
337
  const slotStart = `${targetDateString} ${timeSlot.start_time}:00`;
263
338
  const slotEnd = `${targetDateString} ${timeSlot.end_time}:00`;
264
- const slotStartDate = (0, import_dayjs.default)(slotStart);
265
- const slotEndDate = (0, import_dayjs.default)(slotEnd);
339
+ const slotStartDate = (0, _dayjs.default)(slotStart);
340
+ const slotEndDate = (0, _dayjs.default)(slotEnd);
266
341
  if (targetDate.isSameOrAfter(slotStartDate) && targetDate.isSameOrBefore(slotEndDate)) {
267
342
  return true;
268
343
  }
269
344
  }
270
345
  return false;
271
346
  };
272
- var isInDailyRepeatForDate = (targetDate, startDate, repeatRule) => {
273
- const daysDiff = targetDate.diff(startDate, "day");
347
+
348
+ // 检查日期是否满足每日重复规则(只检查日期,不检查时间)
349
+ const isInDailyRepeatForDate = (targetDate, startDate, repeatRule) => {
350
+ const daysDiff = targetDate.diff(startDate, 'day');
274
351
  if (daysDiff < 0) {
275
352
  return false;
276
353
  }
354
+
355
+ // 检查频率
277
356
  return daysDiff % repeatRule.frequency === 0;
278
357
  };
279
- var isInWeeklyRepeatForDate = (targetDate, startDate, repeatRule) => {
280
- const targetDayOfWeek = targetDate.day();
358
+
359
+ // 检查日期是否满足每周重复规则(只检查日期,不检查时间)
360
+ const isInWeeklyRepeatForDate = (targetDate, startDate, repeatRule) => {
361
+ const targetDayOfWeek = targetDate.day(); // 0=周日, 1=周一, ..., 6=周六
362
+
363
+ // 检查是否在指定的星期几内
281
364
  if (!repeatRule.frequency_date.includes(targetDayOfWeek)) {
282
365
  return false;
283
366
  }
284
- const weeksDiff = targetDate.diff(startDate, "week");
367
+
368
+ // 计算周差
369
+ const weeksDiff = targetDate.diff(startDate, 'week');
285
370
  if (weeksDiff < 0) {
286
371
  return false;
287
372
  }
373
+
374
+ // 检查频率
288
375
  return weeksDiff % repeatRule.frequency === 0;
289
376
  };
290
- var filterDiscountListByBookingTime = (discountList, bookingTime) => {
377
+
378
+ /**
379
+ * 根据预约时间过滤优惠券列表
380
+ * @param discountList 优惠券列表
381
+ * @param bookingTime 预约时间 (格式: YYYY-MM-DD HH:mm:ss)
382
+ * @returns 过滤后的优惠券列表
383
+ */
384
+ const filterDiscountListByBookingTime = (discountList, bookingTime) => {
291
385
  if (!bookingTime) {
292
386
  return discountList;
293
387
  }
294
- return discountList.filter((discount) => {
295
- var _a, _b;
296
- if (((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.validity_type) === "custom_schedule_validity") {
297
- return getDateIsInSchedule(bookingTime, ((_b = discount.custom_schedule_snapshot) == null ? void 0 : _b.data) || []);
388
+ return discountList.filter(discount => {
389
+ if (discount?.metadata?.validity_type === "custom_schedule_validity") {
390
+ return getDateIsInSchedule(bookingTime, discount.custom_schedule_snapshot?.data || []);
298
391
  }
299
392
  try {
300
393
  const isHasStart = !!discount.start_date && !!discount.start_time;
301
- const startDate = (0, import_dayjs.default)(`${discount.start_date} ${discount.start_time}`);
302
- const bookingTimeDayjs = (0, import_dayjs.default)(bookingTime);
394
+ const startDate = (0, _dayjs.default)(`${discount.start_date} ${discount.start_time}`);
395
+ const bookingTimeDayjs = (0, _dayjs.default)(bookingTime);
396
+
397
+ // 判断预约时间是否在开始时间之后
303
398
  const isAfterStart = isHasStart ? bookingTimeDayjs.isSameOrAfter(startDate) : true;
304
- const isBeforeExpire = discount.expire_time ? bookingTimeDayjs.isSameOrBefore((0, import_dayjs.default)(discount.expire_time)) : true;
399
+
400
+ // 判断预约时间是否在过期时间之前(expire_time 为空时为长期有效)
401
+ const isBeforeExpire = discount.expire_time ? bookingTimeDayjs.isSameOrBefore((0, _dayjs.default)(discount.expire_time)) : true;
305
402
  return isAfterStart && isBeforeExpire;
306
403
  } catch (error) {
307
404
  return true;
308
405
  }
309
406
  });
310
407
  };
311
- var isOrderLevelFixedAmountDiscount = (discount) => {
312
- var _a, _b;
313
- return discount.tag === "product_discount_card" && ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.discount_card_type) === "fixed_amount" && ((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.discount_calculation_mode) === "order_level";
408
+ /**
409
+ * 判断是否是订单级别的固定金额折扣卡
410
+ * @param discount 折扣
411
+ * @returns 是否是订单级别的固定金额折扣卡
412
+ */
413
+ exports.filterDiscountListByBookingTime = filterDiscountListByBookingTime;
414
+ const isOrderLevelFixedAmountDiscount = discount => {
415
+ return discount.tag === 'product_discount_card' && discount?.metadata?.discount_card_type === 'fixed_amount' && discount?.metadata?.discount_calculation_mode === 'order_level';
314
416
  };
315
- var calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
316
- const result = /* @__PURE__ */ new Map();
417
+
418
+ /**
419
+ * 计算订单级别固定金额折扣卡的分摊结果
420
+ * @param discount 折扣卡
421
+ * @param applicableProducts 适用商品列表 { productId, amount, quantity, parentQuantity }
422
+ * @returns 分摊结果 Map<productId, { discountAmount, difference }>
423
+ * 注意:
424
+ * - discountAmount 是单价折扣金额(不是总折扣金额)
425
+ * - difference(总差值)优先直接加到数量为1的单商品折扣上,如果没有则存储在metadata中
426
+ */
427
+ exports.isOrderLevelFixedAmountDiscount = isOrderLevelFixedAmountDiscount;
428
+ const calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
429
+ const result = new Map();
317
430
  if (applicableProducts.length === 0) {
318
431
  return result;
319
432
  }
433
+
434
+ // 计算适用商品的总金额(数量 × 单价)
320
435
  const totalAmount = applicableProducts.reduce((acc, product) => {
321
- return new import_decimal.default(acc).plus(new import_decimal.default(product.amount).mul(product.quantity)).toNumber();
436
+ return new _decimal.default(acc).plus(new _decimal.default(product.amount).mul(product.quantity)).toNumber();
322
437
  }, 0);
323
438
  if (totalAmount <= 0) {
324
439
  return result;
325
440
  }
326
- const fixedAmount = new import_decimal.default(discount.par_value || 0).toNumber();
441
+
442
+ // 固定减免金额
443
+ const fixedAmount = new _decimal.default(discount.par_value || 0).toNumber();
444
+
445
+ // 如果固定金额 >= 商品总金额,折扣最高为商品金额(免费)
327
446
  const actualDiscountTotal = Math.min(fixedAmount, totalAmount);
328
- let allocatedTotal = new import_decimal.default(0);
329
- applicableProducts.forEach((product) => {
330
- const rawDiscountPerItem = new import_decimal.default(product.amount).div(totalAmount).mul(actualDiscountTotal);
331
- const discountAmountPerItem = rawDiscountPerItem.toDecimalPlaces(2, import_decimal.default.ROUND_DOWN).toNumber();
447
+
448
+ // 计算每个商品的单价折扣金额
449
+ let allocatedTotal = new _decimal.default(0);
450
+ applicableProducts.forEach(product => {
451
+ // 🔥 分摊公式改为:(单价 / 适用商品总金额) × 固定金额
452
+ // 这样只有一次取整,避免精度损失
453
+ const rawDiscountPerItem = new _decimal.default(product.amount).div(totalAmount).mul(actualDiscountTotal);
454
+
455
+ // 保留两位小数,向下取整(单价折扣)
456
+ const discountAmountPerItem = rawDiscountPerItem.toDecimalPlaces(2, _decimal.default.ROUND_DOWN).toNumber();
332
457
  result.set(product.productId, {
333
458
  discountAmount: discountAmountPerItem,
334
459
  // 单价折扣金额
335
- difference: 0
336
- // 默认差值为0
460
+ difference: 0 // 默认差值为0
337
461
  });
338
- allocatedTotal = allocatedTotal.plus(
339
- new import_decimal.default(discountAmountPerItem).mul(product.quantity)
340
- );
462
+
463
+ // 累加实际分配的总折扣金额(单价折扣 × 数量)
464
+ allocatedTotal = allocatedTotal.plus(new _decimal.default(discountAmountPerItem).mul(product.quantity));
341
465
  });
342
- const totalDifference = new import_decimal.default(actualDiscountTotal).minus(allocatedTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
466
+
467
+ // 🔥 计算总差值
468
+ // 总差值 = 固定金额 - 所有商品的 (单价折扣 × 数量) 之和
469
+ const totalDifference = new _decimal.default(actualDiscountTotal).minus(allocatedTotal).toDecimalPlaces(2, _decimal.default.ROUND_HALF_UP).toNumber();
343
470
  if (totalDifference > 0) {
344
- const isSingleQuantity = (product) => {
345
- if (product.parentQuantity !== void 0) {
471
+ // 🔥 判断商品是否是真正的"数量为1"
472
+ // 主商品:quantity === 1
473
+ // 子商品:quantity === 1 且 parentQuantity === 1
474
+ const isSingleQuantity = product => {
475
+ if (product.parentQuantity !== undefined) {
476
+ // 子商品:需要同时满足自身数量为1且主商品数量为1
346
477
  return product.quantity === 1 && product.parentQuantity === 1;
347
478
  }
479
+ // 主商品:只需要自身数量为1
348
480
  return product.quantity === 1;
349
481
  };
482
+
483
+ // 🔥 筛选出数量为1的商品
350
484
  const singleQuantityProducts = applicableProducts.filter(isSingleQuantity);
351
485
  if (singleQuantityProducts.length > 0) {
352
- const productsWithEnoughSpace = singleQuantityProducts.filter((product) => {
486
+ // 🔥 优先级1:找到有足够剩余空间且金额最大的商品
487
+ // 剩余空间 = 商品价格 - 当前折扣金额 >= 差值
488
+ const productsWithEnoughSpace = singleQuantityProducts.filter(product => {
353
489
  const allocation = result.get(product.productId);
354
- if (!allocation)
355
- return false;
356
- const remainingSpace = new import_decimal.default(product.amount).minus(allocation.discountAmount).toNumber();
490
+ if (!allocation) return false;
491
+ const remainingSpace = new _decimal.default(product.amount).minus(allocation.discountAmount).toNumber();
357
492
  return remainingSpace >= totalDifference;
358
493
  });
359
494
  if (productsWithEnoughSpace.length > 0) {
495
+ // 按金额降序排序,选择金额最大的
360
496
  productsWithEnoughSpace.sort((a, b) => b.amount - a.amount);
361
497
  const targetProduct = productsWithEnoughSpace[0];
362
498
  const targetAllocation = result.get(targetProduct.productId);
363
499
  if (targetAllocation) {
500
+ // 差值直接加到折扣金额上
364
501
  result.set(targetProduct.productId, {
365
- discountAmount: new import_decimal.default(targetAllocation.discountAmount).plus(totalDifference).toNumber(),
366
- difference: 0
367
- // 不需要存储差值
502
+ discountAmount: new _decimal.default(targetAllocation.discountAmount).plus(totalDifference).toNumber(),
503
+ difference: 0 // 不需要存储差值
368
504
  });
369
505
  }
370
506
  } else {
507
+ // 🔥 优先级2:所有数量为1的商品都没有足够剩余空间
508
+ // 选择金额最大的商品,差值存储在metadata中
371
509
  singleQuantityProducts.sort((a, b) => b.amount - a.amount);
372
510
  const targetProduct = singleQuantityProducts[0];
373
511
  const targetAllocation = result.get(targetProduct.productId);
@@ -379,6 +517,8 @@ var calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
379
517
  }
380
518
  }
381
519
  } else {
520
+ // 🔥 优先级3:没有数量为1的商品,走原有逻辑
521
+ // 差值存储在最后一个商品的metadata中
382
522
  const lastProduct = applicableProducts[applicableProducts.length - 1];
383
523
  const lastProductAllocation = result.get(lastProduct.productId);
384
524
  if (lastProductAllocation) {
@@ -391,16 +531,4 @@ var calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
391
531
  }
392
532
  return result;
393
533
  };
394
- // Annotate the CommonJS export names for ESM import in node:
395
- 0 && (module.exports = {
396
- calculateOrderLevelDiscountAllocation,
397
- filterDiscountListByBookingTime,
398
- getDateIsInSchedule,
399
- getDiscountAmount,
400
- getDiscountListAmount,
401
- getDiscountListAmountTotal,
402
- isAllNormalProduct,
403
- isNormalProductByDurationSchedule,
404
- isOrderLevelFixedAmountDiscount,
405
- uniqueById
406
- });
534
+ exports.calculateOrderLevelDiscountAllocation = calculateOrderLevelDiscountAllocation;