@pisell/pisellos 0.0.567 → 0.0.568

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 (228) hide show
  1. package/dist/core/index.js +6 -9
  2. package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -2
  3. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  4. package/dist/model/strategy/adapter/walletPass/utils.js +0 -3
  5. package/dist/model/strategy/strategy-example.js +5 -19
  6. package/dist/modules/Cart/index.js +0 -3
  7. package/dist/modules/Cart/utils/cartProduct.js +0 -1
  8. package/dist/modules/Date/index.js +1 -5
  9. package/dist/modules/Discount/index.js +1 -4
  10. package/dist/modules/OpenData/index.js +0 -2
  11. package/dist/modules/Order/index.d.ts +1 -1
  12. package/dist/modules/Order/index.js +14 -41
  13. package/dist/modules/Payment/index.js +142 -270
  14. package/dist/modules/Payment/walletpass.js +4 -5
  15. package/dist/modules/Rules/index.js +0 -7
  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 +88 -121
  21. package/dist/server/modules/menu/index.js +32 -41
  22. package/dist/server/modules/products/index.js +29 -49
  23. package/dist/server/modules/quotation/index.js +29 -38
  24. package/dist/server/modules/resource/index.js +3 -4
  25. package/dist/server/modules/schedule/index.js +32 -40
  26. package/dist/server/utils/product.js +0 -1
  27. package/dist/solution/BookingByStep/index.d.ts +1 -1
  28. package/dist/solution/BookingByStep/index.js +7 -59
  29. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  30. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  31. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  32. package/dist/solution/BookingTicket/index.d.ts +1 -1
  33. package/dist/solution/BookingTicket/index.js +5 -7
  34. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  35. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  36. package/dist/solution/BuyTickets/index.js +9 -12
  37. package/dist/solution/Checkout/index.js +177 -246
  38. package/dist/solution/Checkout/utils/index.js +4 -16
  39. package/dist/solution/RegisterAndLogin/index.js +30 -76
  40. package/dist/solution/ScanOrder/index.js +50 -60
  41. package/dist/solution/ShopDiscount/index.js +2 -7
  42. package/dist/solution/VenueBooking/index.d.ts +5 -0
  43. package/dist/solution/VenueBooking/index.js +364 -327
  44. package/dist/utils/task.js +15 -18
  45. package/dist/utils/watch.js +0 -1
  46. package/lib/apis/picoding.js +2 -0
  47. package/lib/core/index.js +130 -131
  48. package/lib/effects/index.js +46 -57
  49. package/lib/index.js +92 -53
  50. package/lib/model/index.js +14 -21
  51. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  52. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  53. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  54. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  55. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  56. package/lib/model/strategy/adapter/index.js +100 -64
  57. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  58. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  59. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  60. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  61. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  62. package/lib/model/strategy/adapter/promotion/adapter.js +84 -63
  63. package/lib/model/strategy/adapter/promotion/evaluator.js +381 -231
  64. package/lib/model/strategy/adapter/promotion/examples.js +139 -159
  65. package/lib/model/strategy/adapter/promotion/index.js +1 -49
  66. package/lib/model/strategy/adapter/promotion/type.js +199 -35
  67. package/lib/model/strategy/adapter/type.js +4 -16
  68. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -152
  69. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  70. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  71. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  72. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  73. package/lib/model/strategy/adapter/walletPass/utils.js +652 -402
  74. package/lib/model/strategy/engine.js +270 -168
  75. package/lib/model/strategy/index.js +49 -34
  76. package/lib/model/strategy/strategy-example.js +243 -239
  77. package/lib/model/strategy/type.js +100 -40
  78. package/lib/modules/Account/index.js +39 -53
  79. package/lib/modules/Account/types.js +20 -33
  80. package/lib/modules/AccountList/index.js +116 -154
  81. package/lib/modules/AccountList/types.js +30 -31
  82. package/lib/modules/AccountList/utils.js +18 -30
  83. package/lib/modules/BaseModule.js +22 -45
  84. package/lib/modules/Cart/index.js +170 -124
  85. package/lib/modules/Cart/types.js +46 -51
  86. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  87. package/lib/modules/Cart/utils/cartDate.js +56 -61
  88. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  89. package/lib/modules/Cart/utils/cartNote.js +27 -32
  90. package/lib/modules/Cart/utils/cartProduct.js +306 -241
  91. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  92. package/lib/modules/Cart/utils/cartResource.js +72 -78
  93. package/lib/modules/Cart/utils/changePrice.js +26 -62
  94. package/lib/modules/Cart/utils/index.js +106 -48
  95. package/lib/modules/Customer/constants.js +13 -34
  96. package/lib/modules/Customer/index.js +216 -153
  97. package/lib/modules/Customer/types.js +38 -35
  98. package/lib/modules/Date/index.js +116 -115
  99. package/lib/modules/Date/types.js +16 -28
  100. package/lib/modules/Date/utils.js +174 -123
  101. package/lib/modules/Discount/index.js +117 -113
  102. package/lib/modules/Discount/types.js +9 -31
  103. package/lib/modules/Guests/index.js +30 -56
  104. package/lib/modules/Guests/types.js +23 -33
  105. package/lib/modules/Holder/index.js +209 -189
  106. package/lib/modules/Holder/types.js +4 -16
  107. package/lib/modules/Holder/utils.js +20 -49
  108. package/lib/modules/OpenData/index.js +63 -74
  109. package/lib/modules/OpenData/types.js +4 -16
  110. package/lib/modules/OpenData/utils.js +44 -78
  111. package/lib/modules/Order/index.d.ts +1 -1
  112. package/lib/modules/Order/index.js +332 -320
  113. package/lib/modules/Order/types.js +24 -33
  114. package/lib/modules/Order/utils.js +350 -284
  115. package/lib/modules/Payment/cash.js +20 -33
  116. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  117. package/lib/modules/Payment/eftpos.js +16 -30
  118. package/lib/modules/Payment/index.js +566 -432
  119. package/lib/modules/Payment/mx51.js +1 -0
  120. package/lib/modules/Payment/types.js +216 -107
  121. package/lib/modules/Payment/utils.js +50 -47
  122. package/lib/modules/Payment/walletpass.js +221 -203
  123. package/lib/modules/Product/index.js +51 -46
  124. package/lib/modules/Product/types.js +4 -16
  125. package/lib/modules/Product/utils.js +32 -33
  126. package/lib/modules/ProductList/index.js +111 -110
  127. package/lib/modules/ProductList/types.js +9 -31
  128. package/lib/modules/Quotation/index.js +60 -82
  129. package/lib/modules/Quotation/types.js +4 -16
  130. package/lib/modules/Resource/index.js +27 -59
  131. package/lib/modules/Resource/types.js +22 -32
  132. package/lib/modules/Resource/utils.js +30 -38
  133. package/lib/modules/Rules/index.js +1172 -872
  134. package/lib/modules/Rules/types.js +17 -40
  135. package/lib/modules/SalesSummary/index.js +59 -68
  136. package/lib/modules/SalesSummary/types.js +4 -16
  137. package/lib/modules/SalesSummary/utils.js +176 -193
  138. package/lib/modules/ScanOrderLogger/index.js +59 -79
  139. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  140. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  141. package/lib/modules/ScanOrderLogger/types.js +4 -16
  142. package/lib/modules/Schedule/getDateIsInSchedule.js +334 -167
  143. package/lib/modules/Schedule/index.js +97 -107
  144. package/lib/modules/Schedule/type.js +4 -16
  145. package/lib/modules/Schedule/types.js +4 -16
  146. package/lib/modules/Schedule/utils.js +433 -291
  147. package/lib/modules/Step/index.js +40 -52
  148. package/lib/modules/Step/tyeps.js +4 -16
  149. package/lib/modules/Summary/index.js +66 -70
  150. package/lib/modules/Summary/types.js +4 -16
  151. package/lib/modules/Summary/utils.js +782 -429
  152. package/lib/modules/index.js +212 -57
  153. package/lib/plugins/app.js +4 -16
  154. package/lib/plugins/index.js +36 -25
  155. package/lib/plugins/request.js +137 -126
  156. package/lib/plugins/shopStore.js +4 -16
  157. package/lib/plugins/user.js +4 -16
  158. package/lib/plugins/window.js +171 -179
  159. package/lib/server/index.js +882 -623
  160. package/lib/server/modules/index.js +85 -59
  161. package/lib/server/modules/menu/index.js +146 -122
  162. package/lib/server/modules/menu/types.js +18 -31
  163. package/lib/server/modules/order/index.js +195 -231
  164. package/lib/server/modules/order/types.js +107 -32
  165. package/lib/server/modules/order/utils/filterBookings.js +174 -140
  166. package/lib/server/modules/order/utils/filterOrders.js +89 -60
  167. package/lib/server/modules/products/index.js +430 -335
  168. package/lib/server/modules/products/types.js +41 -34
  169. package/lib/server/modules/quotation/index.js +76 -77
  170. package/lib/server/modules/quotation/types.js +21 -31
  171. package/lib/server/modules/resource/index.js +216 -187
  172. package/lib/server/modules/resource/types.js +42 -33
  173. package/lib/server/modules/schedule/index.js +134 -119
  174. package/lib/server/modules/schedule/types.js +14 -21
  175. package/lib/server/modules/schedule/utils.js +334 -163
  176. package/lib/server/types.js +4 -16
  177. package/lib/server/utils/index.js +25 -23
  178. package/lib/server/utils/product.js +196 -139
  179. package/lib/server/utils/schedule.js +34 -41
  180. package/lib/server/utils/time.js +40 -49
  181. package/lib/solution/BookingByStep/index.d.ts +1 -1
  182. package/lib/solution/BookingByStep/index.js +1530 -1343
  183. package/lib/solution/BookingByStep/types.js +40 -99
  184. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  185. package/lib/solution/BookingByStep/utils/products.js +42 -52
  186. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  187. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  188. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  189. package/lib/solution/BookingTicket/index.d.ts +1 -1
  190. package/lib/solution/BookingTicket/index.js +147 -122
  191. package/lib/solution/BookingTicket/types.js +38 -64
  192. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +64 -80
  193. package/lib/solution/BookingTicket/utils/scan/handleScan.js +82 -80
  194. package/lib/solution/BookingTicket/utils/scan/index.js +90 -94
  195. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  196. package/lib/solution/BuyTickets/index.js +67 -70
  197. package/lib/solution/BuyTickets/types.js +22 -38
  198. package/lib/solution/Checkout/index.js +1451 -1158
  199. package/lib/solution/Checkout/types.js +91 -61
  200. package/lib/solution/Checkout/utils/index.js +227 -158
  201. package/lib/solution/PlaceOrder/index.js +55 -0
  202. package/lib/solution/RegisterAndLogin/config.js +493 -460
  203. package/lib/solution/RegisterAndLogin/index.js +633 -630
  204. package/lib/solution/RegisterAndLogin/types.js +189 -76
  205. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  206. package/lib/solution/Sales/index.js +218 -200
  207. package/lib/solution/Sales/types.js +27 -33
  208. package/lib/solution/ScanOrder/index.js +803 -840
  209. package/lib/solution/ScanOrder/types.js +34 -34
  210. package/lib/solution/ScanOrder/utils.js +372 -331
  211. package/lib/solution/ShopDiscount/index.js +230 -236
  212. package/lib/solution/ShopDiscount/types.js +15 -37
  213. package/lib/solution/ShopDiscount/utils.js +309 -172
  214. package/lib/solution/VenueBooking/index.d.ts +5 -0
  215. package/lib/solution/VenueBooking/index.js +886 -929
  216. package/lib/solution/VenueBooking/types.js +20 -40
  217. package/lib/solution/VenueBooking/utils/dateSummary.js +22 -54
  218. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  219. package/lib/solution/VenueBooking/utils/slotMerge.js +88 -106
  220. package/lib/solution/VenueBooking/utils/smartPricing.js +112 -100
  221. package/lib/solution/VenueBooking/utils/timeSlot.js +133 -132
  222. package/lib/solution/VenueBooking/utils.js +130 -67
  223. package/lib/solution/index.js +102 -37
  224. package/lib/store/createStore.js +32 -29
  225. package/lib/types/index.js +4 -16
  226. package/lib/utils/task.js +36 -36
  227. package/lib/utils/watch.js +81 -47
  228. package/package.json +2 -1
@@ -1,122 +1,142 @@
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 __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);
1
+ "use strict";
29
2
 
30
- // src/solution/Sales/index.ts
31
- var Sales_exports = {};
32
- __export(Sales_exports, {
33
- Sales: () => SalesImpl,
34
- SalesImpl: () => SalesImpl,
35
- default: () => Sales_default
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
36
5
  });
37
- module.exports = __toCommonJS(Sales_exports);
38
- var import_dayjs = __toESM(require("dayjs"));
39
- var import_BaseModule = require("../../modules/BaseModule");
40
- var import_types = require("./types");
41
- __reExport(Sales_exports, require("./types"), module.exports);
42
- var SalesImpl = class extends import_BaseModule.BaseModule {
6
+ var _exportNames = {
7
+ SalesImpl: true,
8
+ Sales: true
9
+ };
10
+ exports.default = exports.SalesImpl = exports.Sales = void 0;
11
+ var _dayjs = _interopRequireDefault(require("dayjs"));
12
+ var _BaseModule = require("../../modules/BaseModule");
13
+ var _types = require("./types");
14
+ Object.keys(_types).forEach(function (key) {
15
+ if (key === "default" || key === "__esModule") return;
16
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
17
+ if (key in exports && exports[key] === _types[key]) return;
18
+ Object.defineProperty(exports, key, {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _types[key];
22
+ }
23
+ });
24
+ });
25
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
+ /**
27
+ * Sales 解决方案基础骨架
28
+ *
29
+ * 当前阶段仅提供:
30
+ * - solution 目录结构
31
+ * - 标准入口导出
32
+ * - 基础生命周期占位
33
+ *
34
+ * 不提前实现 store 编排、初始化流程细节、状态计算逻辑。
35
+ */
36
+ class SalesImpl extends _BaseModule.BaseModule {
37
+ defaultName = 'sales';
38
+ defaultVersion = '1.0.0';
39
+ defaultTimelineBucketMinutes = 15;
40
+ isSolution = true;
41
+ store;
42
+ options = {};
43
+ otherParams = {};
44
+ request;
43
45
  constructor(name, version) {
44
46
  super(name, version);
45
- this.defaultName = "sales";
46
- this.defaultVersion = "1.0.0";
47
- this.defaultTimelineBucketMinutes = 15;
48
- this.isSolution = true;
49
- this.options = {};
50
- this.otherParams = {};
51
47
  }
52
48
  async initialize(core, options = {}) {
53
49
  this.core = core;
54
50
  this.options = options;
55
51
  this.otherParams = options.otherParams || {};
56
- const appPlugin = this.core.getPlugin("app");
57
- this.request = appPlugin == null ? void 0 : appPlugin.getApp().request;
52
+ const appPlugin = this.core.getPlugin('app');
53
+ // @ts-ignore
54
+ this.request = appPlugin?.getApp().request;
58
55
  if (!this.request) {
59
- throw new Error("Sales 解决方案需要 request 插件支持");
56
+ throw new Error('Sales 解决方案需要 request 插件支持');
60
57
  }
58
+
59
+ // 初始化 store 状态
61
60
  this.store = {
62
- currentDay: (0, import_dayjs.default)().startOf("day"),
61
+ currentDay: (0, _dayjs.default)().startOf('day'),
63
62
  reservationList: []
64
63
  };
64
+
65
+ // TODO(Rolo): 等领导提供 reservationList 的目标结构后,
66
+ // 在这里补充从 Server/Order 读取 currentDay 原始数据并转换为预约列表。
67
+
65
68
  await this.core.effects.emit(`${this.name}:onInited`, {});
66
69
  }
70
+
67
71
  // -------------------------------------------------------------------------
68
72
  // SalesModuleAPI 实现
69
73
  // -------------------------------------------------------------------------
74
+
70
75
  /** 获取当前 store 快照 */
71
76
  getState() {
72
- return { ...this.store };
77
+ return {
78
+ ...this.store
79
+ };
73
80
  }
81
+
74
82
  /** 获取当前选择日期 */
75
83
  getCurrentDay() {
76
84
  return this.store.currentDay;
77
85
  }
86
+
78
87
  /** 设置当前选择日期,会自动归一到当天 00:00:00 */
79
88
  setCurrentDay(currentDay) {
80
- const normalized = (0, import_dayjs.default)(currentDay).startOf("day");
89
+ const normalized = (0, _dayjs.default)(currentDay).startOf('day');
81
90
  this.store.currentDay = normalized;
82
- this.core.effects.emit(import_types.SalesHooks.onCurrentDayChanged, { currentDay: normalized });
91
+ this.core.effects.emit(_types.SalesHooks.onCurrentDayChanged, {
92
+ currentDay: normalized
93
+ });
83
94
  return normalized;
84
95
  }
96
+
85
97
  /** 获取当前预约列表 */
86
98
  getReservationList() {
87
99
  return [...this.store.reservationList];
88
100
  }
101
+
89
102
  /** 覆盖设置当前预约列表 */
90
103
  setReservationList(reservationList) {
91
104
  this.store.reservationList = reservationList;
92
- this.core.effects.emit(import_types.SalesHooks.onReservationListChanged, { reservationList });
105
+ this.core.effects.emit(_types.SalesHooks.onReservationListChanged, {
106
+ reservationList
107
+ });
93
108
  return reservationList;
94
109
  }
110
+
95
111
  /** 重置预约列表为空 */
96
112
  resetReservationList() {
97
113
  this.store.reservationList = [];
98
- this.core.effects.emit(import_types.SalesHooks.onReservationListChanged, { reservationList: [] });
114
+ this.core.effects.emit(_types.SalesHooks.onReservationListChanged, {
115
+ reservationList: []
116
+ });
99
117
  return [];
100
118
  }
119
+
101
120
  // -------------------------------------------------------------------------
102
121
  // 生命周期
103
122
  // -------------------------------------------------------------------------
123
+
104
124
  async destroy() {
105
125
  await this.core.effects.emit(`${this.name}:onDestroy`, {});
106
126
  super.destroy();
107
127
  }
128
+
108
129
  /**
109
130
  * 时间轴粒度(分钟)
110
131
  * - 默认 15 分钟
111
132
  * - 可通过 registerModule 时的 options.otherParams.timelineBucketMinutes 覆盖
112
133
  */
113
134
  getTimelineBucketMinutes() {
114
- var _a;
115
- const dynamicBucket = Number((_a = this.otherParams) == null ? void 0 : _a.timelineBucketMinutes);
116
- if (!Number.isFinite(dynamicBucket) || dynamicBucket <= 0)
117
- return this.defaultTimelineBucketMinutes;
135
+ const dynamicBucket = Number(this.otherParams?.timelineBucketMinutes);
136
+ if (!Number.isFinite(dynamicBucket) || dynamicBucket <= 0) return this.defaultTimelineBucketMinutes;
118
137
  return Math.floor(dynamicBucket);
119
138
  }
139
+
120
140
  /**
121
141
  * 解析营业日统计窗口:
122
142
  * - 当 operating_day_boundary.type === 'start_time'
@@ -124,23 +144,32 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
124
144
  * - 否则回退自然日(00:00 到次日 00:00)
125
145
  */
126
146
  getTimelineRangeByOperatingBoundary() {
127
- var _a, _b, _c, _d, _e, _f, _g;
128
- const today = (0, import_dayjs.default)();
129
- const defaultStart = today.startOf("day");
130
- const defaultEndExclusive = defaultStart.add(1, "day");
131
- const appPlugin = this.core.getPlugin("app");
132
- const coreData = (_f = (_d = (_c = (_b = (_a = appPlugin == null ? void 0 : appPlugin.getApp()) == null ? void 0 : _a.data) == null ? void 0 : _b.store) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core");
133
- const operatingDayBoundary = (_g = coreData == null ? void 0 : coreData.core) == null ? void 0 : _g.operating_day_boundary;
134
- if ((operatingDayBoundary == null ? void 0 : operatingDayBoundary.type) !== "start_time") {
135
- return { startAt: defaultStart, endExclusiveAt: defaultEndExclusive };
147
+ const today = (0, _dayjs.default)();
148
+ const defaultStart = today.startOf('day');
149
+ const defaultEndExclusive = defaultStart.add(1, 'day');
150
+ const appPlugin = this.core.getPlugin('app');
151
+ const coreData = appPlugin?.getApp()?.data?.store?.getStore?.().getDataByModel?.('core');
152
+ const operatingDayBoundary = coreData?.core?.operating_day_boundary;
153
+ if (operatingDayBoundary?.type !== 'start_time') {
154
+ return {
155
+ startAt: defaultStart,
156
+ endExclusiveAt: defaultEndExclusive
157
+ };
136
158
  }
137
- const boundaryTime = String(operatingDayBoundary.time || "").trim();
138
- const startAt = (0, import_dayjs.default)(`${today.format("YYYY-MM-DD")} ${boundaryTime}`);
159
+ const boundaryTime = String(operatingDayBoundary.time || '').trim();
160
+ const startAt = (0, _dayjs.default)(`${today.format('YYYY-MM-DD')} ${boundaryTime}`);
139
161
  if (!startAt.isValid()) {
140
- return { startAt: defaultStart, endExclusiveAt: defaultEndExclusive };
162
+ return {
163
+ startAt: defaultStart,
164
+ endExclusiveAt: defaultEndExclusive
165
+ };
141
166
  }
142
- return { startAt, endExclusiveAt: startAt.add(1, "day") };
167
+ return {
168
+ startAt,
169
+ endExclusiveAt: startAt.add(1, 'day')
170
+ };
143
171
  }
172
+
144
173
  /**
145
174
  * 统计时间轴每个时间片的预约数量。
146
175
  * 算法使用差分数组,复杂度 O(n + s):
@@ -149,36 +178,35 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
149
178
  */
150
179
  getTimelineHighlights(bookingList = [], startDateTime, endDateTime) {
151
180
  const bucketMinutes = this.getTimelineBucketMinutes();
152
- const bucketMs = bucketMinutes * 60 * 1e3;
153
- const customStartAt = startDateTime ? (0, import_dayjs.default)(startDateTime) : (0, import_dayjs.default)("");
154
- const customEndExclusiveAt = endDateTime ? (0, import_dayjs.default)(endDateTime) : (0, import_dayjs.default)("");
181
+ const bucketMs = bucketMinutes * 60 * 1000;
182
+ const customStartAt = startDateTime ? (0, _dayjs.default)(startDateTime) : (0, _dayjs.default)('');
183
+ const customEndExclusiveAt = endDateTime ? (0, _dayjs.default)(endDateTime) : (0, _dayjs.default)('');
155
184
  const hasValidCustomRange = customStartAt.isValid() && customEndExclusiveAt.isValid();
156
- const { startAt, endExclusiveAt } = hasValidCustomRange ? { startAt: customStartAt, endExclusiveAt: customEndExclusiveAt } : this.getTimelineRangeByOperatingBoundary();
185
+ const {
186
+ startAt,
187
+ endExclusiveAt
188
+ } = hasValidCustomRange ? {
189
+ startAt: customStartAt,
190
+ endExclusiveAt: customEndExclusiveAt
191
+ } : this.getTimelineRangeByOperatingBoundary();
157
192
  const startAtMs = startAt.valueOf();
158
193
  const endExclusiveAtMs = endExclusiveAt.valueOf();
159
- if (!startAt.isValid() || !endExclusiveAt.isValid() || endExclusiveAtMs <= startAtMs)
160
- return [];
194
+ if (!startAt.isValid() || !endExclusiveAt.isValid() || endExclusiveAtMs <= startAtMs) return [];
161
195
  const slotCount = Math.ceil((endExclusiveAtMs - startAtMs) / bucketMs);
162
- if (slotCount <= 0)
163
- return [];
196
+ if (slotCount <= 0) return [];
164
197
  const diff = new Int32Array(slotCount + 1);
165
198
  for (let i = 0; i < bookingList.length; i++) {
166
199
  const booking = bookingList[i];
167
200
  const bookingStartAt = this.toBookingDateTime(booking.start_date, booking.start_time);
168
201
  const bookingEndAt = this.toBookingDateTime(booking.end_date, booking.end_time);
169
- if (!bookingStartAt.isValid() || !bookingEndAt.isValid())
170
- continue;
202
+ if (!bookingStartAt.isValid() || !bookingEndAt.isValid()) continue;
171
203
  const overlapStartMs = Math.max(bookingStartAt.valueOf(), startAtMs);
204
+ // 结束时间按 <= 处理:转成右开区间时 +1ms,保证命中 end_time 所在时间片
172
205
  const overlapEndExclusiveMs = Math.min(bookingEndAt.valueOf() + 1, endExclusiveAtMs);
173
- if (overlapStartMs >= overlapEndExclusiveMs)
174
- continue;
206
+ if (overlapStartMs >= overlapEndExclusiveMs) continue;
175
207
  const startIdx = Math.max(0, Math.ceil((overlapStartMs - startAtMs) / bucketMs));
176
- const endIdx = Math.min(
177
- slotCount - 1,
178
- Math.floor((overlapEndExclusiveMs - 1 - startAtMs) / bucketMs)
179
- );
180
- if (startIdx > endIdx)
181
- continue;
208
+ const endIdx = Math.min(slotCount - 1, Math.floor((overlapEndExclusiveMs - 1 - startAtMs) / bucketMs));
209
+ if (startIdx > endIdx) continue;
182
210
  diff[startIdx] += 1;
183
211
  diff[endIdx + 1] -= 1;
184
212
  }
@@ -190,14 +218,17 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
190
218
  }
191
219
  return timeline;
192
220
  }
221
+
193
222
  /** dayjs 未启用插件时,手动封装 >= 判断 */
194
223
  isSameOrAfter(left, right) {
195
224
  return left.isAfter(right) || left.isSame(right);
196
225
  }
226
+
197
227
  /** dayjs 未启用插件时,手动封装 <= 判断 */
198
228
  isSameOrBefore(left, right) {
199
229
  return left.isBefore(right) || left.isSame(right);
200
230
  }
231
+
201
232
  /**
202
233
  * 将 booking 的日期/时间字段统一组装为 dayjs
203
234
  * - date + time 都有:按完整时间解析
@@ -205,29 +236,28 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
205
236
  * - 都没有:返回 invalid
206
237
  */
207
238
  toBookingDateTime(date, time) {
208
- if (!date && !time)
209
- return (0, import_dayjs.default)("");
210
- if (date && time)
211
- return (0, import_dayjs.default)(`${date} ${time}`);
212
- return (0, import_dayjs.default)(date || time);
239
+ if (!date && !time) return (0, _dayjs.default)('');
240
+ if (date && time) return (0, _dayjs.default)(`${date} ${time}`);
241
+ return (0, _dayjs.default)(date || time);
213
242
  }
243
+
214
244
  /**
215
245
  * 预约状态映射(面向 UI 的统一状态)
216
246
  * 说明:locked 逻辑后续会补业务规则,这里先保留分支占位。
217
247
  */
218
248
  getBookingStatus(appointmentStatus) {
219
- if (appointmentStatus === "started")
220
- return "occupied";
221
- if (appointmentStatus === "new" || appointmentStatus === "confirmed" || appointmentStatus === "arrived") {
222
- return "reserved";
249
+ if (appointmentStatus === 'started') return 'occupied';
250
+ if (appointmentStatus === 'new' || appointmentStatus === 'confirmed' || appointmentStatus === 'arrived') {
251
+ return 'reserved';
223
252
  }
224
- if (appointmentStatus === "locked")
225
- return "locked";
226
- return void 0;
253
+ // TODO: locked 的业务规则后续补充。
254
+ if (appointmentStatus === 'locked') return 'locked';
255
+ return undefined;
227
256
  }
228
257
  getResourceId(resource) {
229
- return resource.id ?? resource.form_record_id ?? "";
258
+ return resource.id ?? resource.form_record_id ?? '';
230
259
  }
260
+
231
261
  /**
232
262
  * 资源下 bookings 的返回裁剪策略:
233
263
  * 1) 优先返回当前时刻正在进行中的预约(允许并发返回多条)
@@ -236,119 +266,105 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
236
266
  * 4) 最后兜底返回一条(避免资源有历史预约时完全无反馈)
237
267
  */
238
268
  pickBookingsForCurrentPoint(current, bookings) {
239
- if (bookings.length === 0)
240
- return [];
241
- const currentDayStart = current.startOf("day");
242
- const currentDayEnd = current.endOf("day");
243
- const dayScopedBookings = bookings.filter((booking) => {
269
+ if (bookings.length === 0) return [];
270
+ const currentDayStart = current.startOf('day');
271
+ const currentDayEnd = current.endOf('day');
272
+
273
+ // 仅保留与 current 当天有时间交集的预约,避免跨天误命中
274
+ const dayScopedBookings = bookings.filter(booking => {
244
275
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
245
276
  const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
246
- if (!startAt.isValid() || !endAt.isValid())
247
- return false;
277
+ if (!startAt.isValid() || !endAt.isValid()) return false;
248
278
  return this.isSameOrBefore(startAt, currentDayEnd) && this.isSameOrAfter(endAt, currentDayStart);
249
279
  });
250
- if (dayScopedBookings.length === 0)
251
- return [];
252
- const appendNextStartGroupIfNeeded = (selectedBookings) => {
253
- if (selectedBookings.length === 0)
254
- return selectedBookings;
255
- const shouldAppendNextGroup = selectedBookings.some(
256
- (booking) => booking.status === "reserved" || booking.status === "occupied"
257
- );
258
- if (!shouldAppendNextGroup)
259
- return selectedBookings;
260
- const selectedStartValues = new Set(
261
- selectedBookings.map((booking) => this.toBookingDateTime(booking.start_date, booking.start_time)).filter((startAt) => startAt.isValid()).map((startAt) => startAt.valueOf())
262
- );
263
- const futureCandidates = dayScopedBookings.filter((booking) => {
280
+ if (dayScopedBookings.length === 0) return [];
281
+ const appendNextStartGroupIfNeeded = selectedBookings => {
282
+ if (selectedBookings.length === 0) return selectedBookings;
283
+ const shouldAppendNextGroup = selectedBookings.some(booking => booking.status === 'reserved' || booking.status === 'occupied');
284
+ if (!shouldAppendNextGroup) return selectedBookings;
285
+ const selectedStartValues = new Set(selectedBookings.map(booking => this.toBookingDateTime(booking.start_date, booking.start_time)).filter(startAt => startAt.isValid()).map(startAt => startAt.valueOf()));
286
+ const futureCandidates = dayScopedBookings.filter(booking => {
264
287
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
265
- if (!startAt.isValid())
266
- return false;
288
+ if (!startAt.isValid()) return false;
267
289
  return startAt.isAfter(current) && !selectedStartValues.has(startAt.valueOf());
268
290
  });
269
- if (futureCandidates.length === 0)
270
- return selectedBookings;
271
- const nextStartAt = this.toBookingDateTime(
272
- futureCandidates[0].start_date,
273
- futureCandidates[0].start_time
274
- ).valueOf();
275
- const nextStartGroup = futureCandidates.filter((booking) => {
291
+ if (futureCandidates.length === 0) return selectedBookings;
292
+ const nextStartAt = this.toBookingDateTime(futureCandidates[0].start_date, futureCandidates[0].start_time).valueOf();
293
+ const nextStartGroup = futureCandidates.filter(booking => {
276
294
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
277
295
  return startAt.isValid() && startAt.valueOf() === nextStartAt;
278
296
  });
279
- if (nextStartGroup.length === 0)
280
- return selectedBookings;
297
+ if (nextStartGroup.length === 0) return selectedBookings;
281
298
  return [...selectedBookings, ...nextStartGroup];
282
299
  };
283
- const activeBookings = dayScopedBookings.filter((booking) => {
300
+
301
+ // active: current 处于 [startAt, endAt] 区间
302
+ const activeBookings = dayScopedBookings.filter(booking => {
284
303
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
285
304
  const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
286
- if (!startAt.isValid() || !endAt.isValid())
287
- return false;
305
+ if (!startAt.isValid() || !endAt.isValid()) return false;
288
306
  return this.isSameOrAfter(current, startAt) && this.isSameOrBefore(current, endAt);
289
307
  });
290
- if (activeBookings.length > 0)
291
- return appendNextStartGroupIfNeeded(activeBookings);
292
- const timeoutOccupied = dayScopedBookings.filter(
293
- (booking) => booking.status === "occupied" && booking.isTimeout
294
- );
295
- if (timeoutOccupied.length > 0)
296
- return appendNextStartGroupIfNeeded(timeoutOccupied);
297
- const upcoming = dayScopedBookings.filter((booking) => {
308
+ if (activeBookings.length > 0) return appendNextStartGroupIfNeeded(activeBookings);
309
+
310
+ // timeout occupied: 占用中且超时
311
+ const timeoutOccupied = dayScopedBookings.filter(booking => booking.status === 'occupied' && booking.isTimeout);
312
+ if (timeoutOccupied.length > 0) return appendNextStartGroupIfNeeded(timeoutOccupied);
313
+
314
+ // upcoming: 从未来预约里只取最早那一组(同 start_time)
315
+ const upcoming = dayScopedBookings.filter(booking => {
298
316
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
299
- return startAt.isValid() && startAt.isAfter(current) && startAt.isSame(current, "day");
317
+ return startAt.isValid() && startAt.isAfter(current) && startAt.isSame(current, 'day');
300
318
  });
301
319
  if (upcoming.length > 0) {
302
320
  const firstStartAt = this.toBookingDateTime(upcoming[0].start_date, upcoming[0].start_time).valueOf();
303
- const upcomingStartGroup = upcoming.filter((booking) => {
321
+ const upcomingStartGroup = upcoming.filter(booking => {
304
322
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
305
323
  return startAt.valueOf() === firstStartAt;
306
324
  });
307
325
  return appendNextStartGroupIfNeeded(upcomingStartGroup);
308
326
  }
327
+
328
+ // fallback: 全部是过去且非 timeout 的场景,保留末条便于前端兜底展示
309
329
  const fallback = dayScopedBookings[dayScopedBookings.length - 1];
310
330
  return fallback ? [fallback] : [];
311
331
  }
332
+
312
333
  /**
313
334
  * 标准化单条 booking:
314
335
  * - 过滤终态(rejected/cancelled/completed)
315
336
  * - 注入 status / isTimeout / reserved_status
316
337
  */
317
338
  normalizeMatchedBooking(current, booking) {
318
- const appointmentStatus = String(booking.appointment_status ?? booking.status ?? "");
319
- if (appointmentStatus === "rejected" || appointmentStatus === "cancelled" || appointmentStatus === "completed") {
339
+ const appointmentStatus = String(booking.appointment_status ?? booking.status ?? '');
340
+ if (appointmentStatus === 'rejected' || appointmentStatus === 'cancelled' || appointmentStatus === 'completed') {
320
341
  return null;
321
342
  }
322
343
  const bookingStatus = this.getBookingStatus(appointmentStatus);
323
344
  const endAt = this.toBookingDateTime(booking.end_date, booking.end_time);
324
345
  const startAt = this.toBookingDateTime(booking.start_date, booking.start_time);
325
- const isTimeout = bookingStatus === "occupied" && endAt.isValid() && current.isAfter(endAt);
326
- const timeoutTime = isTimeout ? current.diff(endAt, "minute") : void 0;
346
+ const isTimeout = bookingStatus === 'occupied' && endAt.isValid() && current.isAfter(endAt);
347
+ const timeoutTime = isTimeout ? current.diff(endAt, 'minute') : undefined;
327
348
  const progressPercent = (() => {
328
- if (bookingStatus !== "occupied")
329
- return 0;
330
- if (!startAt.isValid() || !endAt.isValid())
331
- return 0;
332
- const totalMinutes = endAt.diff(startAt, "minute");
333
- if (totalMinutes <= 0)
334
- return 0;
335
- const elapsedMinutes = current.diff(startAt, "minute");
336
- if (elapsedMinutes <= 0)
337
- return 0;
338
- if (elapsedMinutes >= totalMinutes)
339
- return 100;
349
+ if (bookingStatus !== 'occupied') return 0;
350
+ if (!startAt.isValid() || !endAt.isValid()) return 0;
351
+ const totalMinutes = endAt.diff(startAt, 'minute');
352
+ if (totalMinutes <= 0) return 0;
353
+ const elapsedMinutes = current.diff(startAt, 'minute');
354
+ if (elapsedMinutes <= 0) return 0;
355
+ if (elapsedMinutes >= totalMinutes) return 100;
340
356
  return Math.floor(elapsedMinutes / totalMinutes * 100);
341
357
  })();
342
358
  let reservedStatus;
343
359
  let lateTime;
344
360
  let remainingReserveTime;
345
- if (bookingStatus === "reserved" && startAt.isValid()) {
361
+ if (bookingStatus === 'reserved' && startAt.isValid()) {
346
362
  if (current.isBefore(startAt)) {
347
- reservedStatus = "not_arrived";
348
- remainingReserveTime = startAt.diff(current, "minute");
363
+ reservedStatus = 'not_arrived';
364
+ remainingReserveTime = startAt.diff(current, 'minute');
349
365
  } else {
350
- reservedStatus = "late";
351
- lateTime = Math.max(current.diff(startAt, "minute"), 0);
366
+ reservedStatus = 'late';
367
+ lateTime = Math.max(current.diff(startAt, 'minute'), 0);
352
368
  }
353
369
  }
354
370
  return {
@@ -363,39 +379,46 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
363
379
  };
364
380
  }
365
381
  async getResourceBookingList(currentTime, bookingList = []) {
366
- var _a;
367
- const current = (0, import_dayjs.default)(currentTime);
368
- if (!current.isValid())
369
- return [];
370
- const resourceResponse = await this.request.get(
371
- "/shop/form/resource/page",
372
- { skip: 1, num: 999 },
373
- // @ts-ignore
374
- { osServer: true, isShopApi: true }
375
- );
376
- const resourceList = ((_a = resourceResponse == null ? void 0 : resourceResponse.data) == null ? void 0 : _a.list) ?? [];
377
- if (!Array.isArray(resourceList) || resourceList.length === 0)
378
- return [];
379
- const normalizedBookings = bookingList.map((booking) => this.normalizeMatchedBooking(current, booking)).filter((booking) => Boolean(booking)).sort((left, right) => {
382
+ // currentTime 约定为完整 datetime;非法值直接返回空,避免误判
383
+ const current = (0, _dayjs.default)(currentTime);
384
+ if (!current.isValid()) return [];
385
+
386
+ // 资源列表来源:Server 路由 /shop/form/resource/page
387
+ const resourceResponse = await this.request.get('/shop/form/resource/page', {
388
+ skip: 1,
389
+ num: 999
390
+ },
391
+ // @ts-ignore
392
+ {
393
+ osServer: true,
394
+ isShopApi: true
395
+ });
396
+ const resourceList = resourceResponse?.data?.list ?? [];
397
+ if (!Array.isArray(resourceList) || resourceList.length === 0) return [];
398
+
399
+ // 全局先做 booking 标准化 + start_time 升序,后续映射直接复用
400
+ const normalizedBookings = bookingList.map(booking => this.normalizeMatchedBooking(current, booking)).filter(booking => Boolean(booking)).sort((left, right) => {
380
401
  const leftStartAt = this.toBookingDateTime(left.start_date, left.start_time).valueOf();
381
402
  const rightStartAt = this.toBookingDateTime(right.start_date, right.start_time).valueOf();
382
403
  return leftStartAt - rightStartAt;
383
404
  });
384
- const bookingMap = /* @__PURE__ */ new Map();
385
- normalizedBookings.forEach((booking) => {
386
- if (!Array.isArray(booking.resources))
387
- return;
388
- booking.resources.forEach((resource) => {
389
- const relationId = resource == null ? void 0 : resource.relation_id;
390
- if (relationId === void 0 || relationId === null)
391
- return;
405
+
406
+ // 建立 resourceId -> bookings[] 倒排索引,加速资源匹配
407
+ const bookingMap = new Map();
408
+ normalizedBookings.forEach(booking => {
409
+ if (!Array.isArray(booking.resources)) return;
410
+ booking.resources.forEach(resource => {
411
+ const relationId = resource?.relation_id;
412
+ if (relationId === undefined || relationId === null) return;
392
413
  const key = String(relationId);
393
414
  const list = bookingMap.get(key) || [];
394
415
  list.push(booking);
395
416
  bookingMap.set(key, list);
396
417
  });
397
418
  });
398
- return resourceList.map((resource) => {
419
+
420
+ // 输出:每个资源都返回;bookings 可能是 0 / 1 / 多条(并发场景)
421
+ return resourceList.map(resource => {
399
422
  const resourceId = this.getResourceId(resource);
400
423
  const matchedBookings = bookingMap.get(String(resourceId)) || [];
401
424
  const bookings = this.pickBookingsForCurrentPoint(current, matchedBookings);
@@ -406,11 +429,6 @@ var SalesImpl = class extends import_BaseModule.BaseModule {
406
429
  };
407
430
  });
408
431
  }
409
- };
410
- var Sales_default = SalesImpl;
411
- // Annotate the CommonJS export names for ESM import in node:
412
- 0 && (module.exports = {
413
- Sales,
414
- SalesImpl,
415
- ...require("./types")
416
- });
432
+ }
433
+ exports.Sales = exports.SalesImpl = SalesImpl;
434
+ var _default = exports.default = SalesImpl;