@pisell/pisellos 2.2.283 → 2.2.284

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 (284) 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 +64 -86
  12. package/dist/modules/Order/types.d.ts +1 -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/modules/Summary/utils.d.ts +1 -1
  19. package/dist/plugins/request.js +1 -4
  20. package/dist/plugins/window.js +2 -6
  21. package/dist/server/index.js +97 -129
  22. package/dist/server/modules/menu/index.js +32 -41
  23. package/dist/server/modules/order/index.js +2 -4
  24. package/dist/server/modules/products/index.js +24 -42
  25. package/dist/server/modules/quotation/index.js +29 -38
  26. package/dist/server/modules/resource/index.js +3 -4
  27. package/dist/server/modules/schedule/index.js +27 -35
  28. package/dist/server/utils/product.js +0 -1
  29. package/dist/solution/BaseSales/index.js +100 -72
  30. package/dist/solution/BookingByStep/index.d.ts +1 -1
  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.d.ts +1 -13
  36. package/dist/solution/BookingTicket/index.js +0 -2
  37. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
  38. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  39. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  40. package/dist/solution/BuyTickets/index.js +9 -12
  41. package/dist/solution/Checkout/index.js +177 -252
  42. package/dist/solution/Checkout/utils/index.js +4 -16
  43. package/dist/solution/RegisterAndLogin/index.js +30 -76
  44. package/dist/solution/ScanOrder/index.js +50 -60
  45. package/dist/solution/ShopDiscount/index.js +2 -7
  46. package/dist/solution/VenueBooking/index.js +45 -55
  47. package/dist/utils/task.js +15 -18
  48. package/dist/utils/watch.js +0 -1
  49. package/lib/apis/picoding.js +2 -0
  50. package/lib/core/index.js +131 -132
  51. package/lib/effects/index.js +46 -57
  52. package/lib/index.js +82 -49
  53. package/lib/model/index.js +14 -21
  54. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  55. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  56. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  57. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  58. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  59. package/lib/model/strategy/adapter/index.js +100 -64
  60. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  61. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  62. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  63. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  64. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  65. package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
  66. package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
  67. package/lib/model/strategy/adapter/promotion/examples.js +222 -234
  68. package/lib/model/strategy/adapter/promotion/index.js +1 -0
  69. package/lib/model/strategy/adapter/promotion/type.js +243 -36
  70. package/lib/model/strategy/adapter/type.js +4 -16
  71. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
  72. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  73. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  74. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  75. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  76. package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
  77. package/lib/model/strategy/engine.js +270 -168
  78. package/lib/model/strategy/index.js +49 -34
  79. package/lib/model/strategy/strategy-example.js +243 -239
  80. package/lib/model/strategy/type.js +100 -40
  81. package/lib/modules/Account/index.js +39 -53
  82. package/lib/modules/Account/types.js +20 -33
  83. package/lib/modules/AccountList/index.js +116 -154
  84. package/lib/modules/AccountList/types.js +30 -31
  85. package/lib/modules/AccountList/utils.js +18 -30
  86. package/lib/modules/BaseModule.js +23 -42
  87. package/lib/modules/BookingContext/index.js +158 -136
  88. package/lib/modules/BookingContext/types.js +46 -32
  89. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
  90. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
  91. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
  92. package/lib/modules/BookingContext/utils/flexible.js +38 -55
  93. package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
  94. package/lib/modules/BookingContext/utils/index.js +124 -41
  95. package/lib/modules/BookingContext/utils/noResource.js +58 -70
  96. package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
  97. package/lib/modules/BookingContext/utils/productExtend.js +202 -155
  98. package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
  99. package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
  100. package/lib/modules/BookingContext/utils/resources.js +209 -167
  101. package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
  102. package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
  103. package/lib/modules/Cart/index.js +170 -124
  104. package/lib/modules/Cart/types.js +46 -51
  105. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  106. package/lib/modules/Cart/utils/cartDate.js +56 -61
  107. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  108. package/lib/modules/Cart/utils/cartNote.js +27 -32
  109. package/lib/modules/Cart/utils/cartProduct.js +321 -251
  110. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  111. package/lib/modules/Cart/utils/cartResource.js +70 -78
  112. package/lib/modules/Cart/utils/changePrice.js +22 -50
  113. package/lib/modules/Cart/utils/index.js +106 -48
  114. package/lib/modules/Customer/constants.js +13 -34
  115. package/lib/modules/Customer/index.js +235 -172
  116. package/lib/modules/Customer/types.js +38 -35
  117. package/lib/modules/Date/index.js +116 -115
  118. package/lib/modules/Date/types.js +16 -28
  119. package/lib/modules/Date/utils.js +174 -123
  120. package/lib/modules/Discount/index.js +122 -127
  121. package/lib/modules/Discount/types.js +9 -31
  122. package/lib/modules/Guests/index.js +30 -56
  123. package/lib/modules/Guests/types.js +23 -33
  124. package/lib/modules/Holder/index.js +209 -189
  125. package/lib/modules/Holder/types.js +4 -16
  126. package/lib/modules/Holder/utils.js +20 -49
  127. package/lib/modules/OpenData/index.js +70 -76
  128. package/lib/modules/OpenData/types.js +4 -16
  129. package/lib/modules/OpenData/utils.js +44 -78
  130. package/lib/modules/Order/index.d.ts +1 -1
  131. package/lib/modules/Order/index.js +1728 -2123
  132. package/lib/modules/Order/payment-utils.js +77 -120
  133. package/lib/modules/Order/types.d.ts +1 -1
  134. package/lib/modules/Order/types.js +87 -35
  135. package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
  136. package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
  137. package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
  138. package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
  139. package/lib/modules/Order/utils.js +814 -647
  140. package/lib/modules/Payment/cash.js +20 -33
  141. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  142. package/lib/modules/Payment/eftpos.js +16 -30
  143. package/lib/modules/Payment/index.js +532 -399
  144. package/lib/modules/Payment/mx51.js +1 -0
  145. package/lib/modules/Payment/types.js +230 -108
  146. package/lib/modules/Payment/utils.js +52 -51
  147. package/lib/modules/Payment/walletpass.js +485 -660
  148. package/lib/modules/Product/index.js +51 -46
  149. package/lib/modules/Product/types.js +4 -16
  150. package/lib/modules/Product/utils.js +32 -33
  151. package/lib/modules/ProductList/index.js +113 -123
  152. package/lib/modules/ProductList/types.js +9 -31
  153. package/lib/modules/Quotation/index.js +66 -100
  154. package/lib/modules/Quotation/types.js +4 -16
  155. package/lib/modules/Resource/index.js +27 -59
  156. package/lib/modules/Resource/types.js +22 -32
  157. package/lib/modules/Resource/utils.js +30 -38
  158. package/lib/modules/ResourcePlanner/index.js +60 -61
  159. package/lib/modules/ResourcePlanner/planner.js +346 -384
  160. package/lib/modules/ResourcePlanner/types.js +4 -16
  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.d.ts +1 -1
  180. package/lib/modules/Summary/utils.js +773 -418
  181. package/lib/modules/SurchargeList/index.js +46 -60
  182. package/lib/modules/SurchargeList/types.js +4 -16
  183. package/lib/modules/index.js +245 -63
  184. package/lib/plugins/app.js +4 -16
  185. package/lib/plugins/index.js +36 -25
  186. package/lib/plugins/request.js +137 -126
  187. package/lib/plugins/shopStore.js +4 -16
  188. package/lib/plugins/user.js +4 -16
  189. package/lib/plugins/window.js +171 -179
  190. package/lib/server/index.js +3027 -2655
  191. package/lib/server/modules/floor-plan/index.js +102 -123
  192. package/lib/server/modules/floor-plan/types.js +15 -30
  193. package/lib/server/modules/index.js +106 -68
  194. package/lib/server/modules/menu/index.js +146 -122
  195. package/lib/server/modules/menu/types.js +18 -31
  196. package/lib/server/modules/order/index.js +758 -956
  197. package/lib/server/modules/order/types.js +122 -33
  198. package/lib/server/modules/order/utils/filterBookings.js +219 -194
  199. package/lib/server/modules/order/utils/filterOrders.js +118 -92
  200. package/lib/server/modules/payment/index.js +59 -83
  201. package/lib/server/modules/payment/types.js +4 -16
  202. package/lib/server/modules/products/index.js +575 -459
  203. package/lib/server/modules/products/types.js +44 -34
  204. package/lib/server/modules/quotation/index.js +137 -172
  205. package/lib/server/modules/quotation/types.js +21 -31
  206. package/lib/server/modules/resource/index.js +213 -184
  207. package/lib/server/modules/resource/types.js +42 -33
  208. package/lib/server/modules/schedule/index.js +135 -123
  209. package/lib/server/modules/schedule/types.js +14 -21
  210. package/lib/server/modules/schedule/utils.js +334 -163
  211. package/lib/server/types.js +4 -16
  212. package/lib/server/utils/index.js +25 -23
  213. package/lib/server/utils/product.js +196 -139
  214. package/lib/server/utils/schedule.js +34 -41
  215. package/lib/server/utils/small-ticket.js +479 -456
  216. package/lib/server/utils/time.js +40 -49
  217. package/lib/solution/BaseSales/index.js +1209 -1412
  218. package/lib/solution/BaseSales/types.js +42 -38
  219. package/lib/solution/BaseSales/utils/cartPromotion.js +650 -502
  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.d.ts +1 -1
  225. package/lib/solution/BookingByStep/index.js +1527 -1340
  226. package/lib/solution/BookingByStep/types.js +40 -99
  227. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  228. package/lib/solution/BookingByStep/utils/products.js +42 -52
  229. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  230. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  231. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  232. package/lib/solution/BookingTicket/index.d.ts +1 -13
  233. package/lib/solution/BookingTicket/index.js +594 -514
  234. package/lib/solution/BookingTicket/types.js +99 -77
  235. package/lib/solution/BookingTicket/utils/addProductDecision.js +225 -187
  236. package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
  237. package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
  238. package/lib/solution/BookingTicket/utils/cartView.js +114 -99
  239. package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
  240. package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
  241. package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
  242. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
  243. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
  244. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
  245. package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
  246. package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
  247. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  248. package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
  249. package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
  250. package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
  251. package/lib/solution/BuyTickets/index.js +67 -70
  252. package/lib/solution/BuyTickets/types.js +22 -38
  253. package/lib/solution/Checkout/index.js +1451 -1158
  254. package/lib/solution/Checkout/types.js +91 -61
  255. package/lib/solution/Checkout/utils/index.js +228 -156
  256. package/lib/solution/PlaceOrder/index.js +55 -0
  257. package/lib/solution/RegisterAndLogin/config.js +493 -460
  258. package/lib/solution/RegisterAndLogin/index.js +633 -630
  259. package/lib/solution/RegisterAndLogin/types.js +189 -76
  260. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  261. package/lib/solution/Sales/index.js +328 -324
  262. package/lib/solution/Sales/types.js +27 -33
  263. package/lib/solution/ScanOrder/index.js +832 -864
  264. package/lib/solution/ScanOrder/types.js +33 -34
  265. package/lib/solution/ScanOrder/utils.js +409 -374
  266. package/lib/solution/ShopDiscount/index.js +226 -232
  267. package/lib/solution/ShopDiscount/types.js +15 -37
  268. package/lib/solution/ShopDiscount/utils.js +300 -172
  269. package/lib/solution/UnifiedBookingSales/index.js +437 -487
  270. package/lib/solution/UnifiedBookingSales/types.js +12 -31
  271. package/lib/solution/VenueBooking/index.js +811 -879
  272. package/lib/solution/VenueBooking/types.js +19 -39
  273. package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
  274. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  275. package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
  276. package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
  277. package/lib/solution/VenueBooking/utils.js +130 -67
  278. package/lib/solution/index.js +124 -41
  279. package/lib/store/createStore.js +32 -29
  280. package/lib/types/index.js +4 -16
  281. package/lib/utils/payment-number.js +26 -46
  282. package/lib/utils/task.js +36 -36
  283. package/lib/utils/watch.js +81 -47
  284. package/package.json +2 -1
@@ -1,80 +1,67 @@
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);
1
+ "use strict";
28
2
 
29
- // src/server/modules/order/index.ts
30
- var order_exports = {};
31
- __export(order_exports, {
32
- OrderModule: () => OrderModule
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
33
5
  });
34
- module.exports = __toCommonJS(order_exports);
35
- var import_lodash_es = require("lodash-es");
36
- var import_dayjs = __toESM(require("dayjs"));
37
- var import_BaseModule = require("../../../modules/BaseModule");
38
- var import_orderCollectionIdentity = require("../../../modules/Order/utils/orderCollectionIdentity");
39
- var import_types = require("./types");
40
- var import_payment_utils = require("../../../modules/Order/payment-utils");
41
- var INDEXDB_STORE_NAME = "orders";
42
- var ORDER_STORAGE_KEY_FIELD = "__order_storage_key";
43
- var ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY = "server_order_last_full_fetch_at";
44
- var ORDER_SYNC_THROTTLE_MS_STORAGE_KEY = "order_sync_throttle_ms";
45
- var DEFAULT_ORDER_SYNC_THROTTLE_MS = 2e3;
46
- var ORDER_SQLITE_DEDUPE_MS = 15e3;
47
- var ORDER_SILENT_REFRESH_MIN_INTERVAL_MS = 3e4;
48
- var ORDER_BUSINESS_WRITE_SOURCES = /* @__PURE__ */ new Set([
49
- "upsertOrdersFromRemote",
50
- "upsertPendingSyncOrders",
51
- "upsertLocalDraftOrders",
52
- "overwriteExistingOrder",
53
- "markOrderSyncedByExternalSaleNumber",
54
- "updateLocalPayment"
55
- ]);
56
- var ORDER_MERGE_SELF_CHECK = false;
57
- var PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER = "__pisell_os_pending_payment_without_unique_number__";
58
- var ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ["products", "bookings", "payments"];
59
- var ORDER_COLLECTION_KIND_BY_FIELD = {
60
- products: "product",
61
- bookings: "booking",
62
- payments: "payment"
6
+ exports.OrderModule = void 0;
7
+ var _lodashEs = require("lodash-es");
8
+ var _dayjs = _interopRequireDefault(require("dayjs"));
9
+ var _BaseModule = require("../../../modules/BaseModule");
10
+ var _orderCollectionIdentity = require("../../../modules/Order/utils/orderCollectionIdentity");
11
+ var _types = require("./types");
12
+ var _paymentUtils = require("../../../modules/Order/payment-utils");
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+ /**
15
+ * SQLite 存储名称
16
+ */
17
+ const INDEXDB_STORE_NAME = 'orders';
18
+ const ORDER_STORAGE_KEY_FIELD = '__order_storage_key';
19
+ const ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY = 'server_order_last_full_fetch_at';
20
+ const ORDER_SYNC_THROTTLE_MS_STORAGE_KEY = 'order_sync_throttle_ms';
21
+ const DEFAULT_ORDER_SYNC_THROTTLE_MS = 2_000;
22
+ /** pubsub 回声写入去重窗口:业务 API 刚写入后,跳过同单 SQLite patch */
23
+ const ORDER_SQLITE_DEDUPE_MS = 15_000;
24
+ /** silentRefresh 最小间隔,避免 preload 后立即全量重拉 */
25
+ const ORDER_SILENT_REFRESH_MIN_INTERVAL_MS = 30_000;
26
+ /** 视为「业务侧刚写入」的来源,pubsub 回声可跳过 SQLite */
27
+ const ORDER_BUSINESS_WRITE_SOURCES = new Set(['upsertOrdersFromRemote', 'upsertPendingSyncOrders', 'upsertLocalDraftOrders', 'overwriteExistingOrder', 'markOrderSyncedByExternalSaleNumber', 'updateLocalPayment']);
28
+
29
+ /**
30
+ * 合并热路径全表去重自检开关:默认关闭。
31
+ * 开启后每次合并会额外对整张 store 做一次 O(n^2) 重复检测并告警,
32
+ * 仅用于排查增量身份索引是否遗漏了重复订单,不应在生产常开。
33
+ */
34
+ const ORDER_MERGE_SELF_CHECK = false;
35
+ const PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER = '__pisell_os_pending_payment_without_unique_number__';
36
+ const ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ['products', 'bookings', 'payments'];
37
+ const ORDER_COLLECTION_KIND_BY_FIELD = {
38
+ products: 'product',
39
+ bookings: 'booking',
40
+ payments: 'payment'
63
41
  };
64
- var OrderModule = class extends import_BaseModule.BaseModule {
42
+ /**
43
+ * Order 模块 - 基础框架
44
+ */
45
+ class OrderModule extends _BaseModule.BaseModule {
46
+ defaultName = 'order';
47
+ defaultVersion = '1.0.0';
48
+ store;
49
+ dbManager;
50
+ orderDataSource;
51
+ pendingSyncMessages = [];
52
+ syncTimer;
53
+ isProcessingSyncBatch = false;
54
+ isIdlePhase = true;
55
+ logger; // LoggerManager 实例
56
+ storage;
57
+ orderSQLiteSaveQueue = Promise.resolve(); /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
58
+ recentSqliteWriteByStorageKey = new Map();
59
+ /** 最近一次 SSE 全量拉取完成时间 */
60
+ lastServerFullFetchAtMs = 0;
65
61
  constructor(name, version) {
66
62
  super(name, version);
67
- this.defaultName = "order";
68
- this.defaultVersion = "1.0.0";
69
- this.pendingSyncMessages = [];
70
- this.isProcessingSyncBatch = false;
71
- this.isIdlePhase = true;
72
- this.orderSQLiteSaveQueue = Promise.resolve();
73
- /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
74
- this.recentSqliteWriteByStorageKey = /* @__PURE__ */ new Map();
75
- /** 最近一次 SSE 全量拉取完成时间 */
76
- this.lastServerFullFetchAtMs = 0;
77
63
  }
64
+
78
65
  /**
79
66
  * 广播订单变更事件,兼容全量列表订阅并额外携带本次变更订单。
80
67
  *
@@ -82,23 +69,23 @@ var OrderModule = class extends import_BaseModule.BaseModule {
82
69
  * await this.emitOrdersChanged([freshOrder], 'pubsub.bodyUpsert')
83
70
  */
84
71
  async emitOrdersChanged(changedOrders = [], source) {
85
- console.log("触发emitOrdersChanged");
86
72
  const payload = {
87
73
  list: this.store.list,
88
- changedOrders: changedOrders.map((order) => this.normalizeOrderForMemoryList(order)),
74
+ changedOrders: changedOrders.map(order => this.normalizeOrderForMemoryList(order)),
89
75
  source
90
76
  };
91
- await this.core.effects.emit(import_types.OrderHooks.onOrdersChanged, payload);
77
+ await this.core.effects.emit(_types.OrderHooks.onOrdersChanged, payload);
92
78
  }
79
+
93
80
  /**
94
81
  * 广播远端商品成员增删。监听器异常必须与订单落库和原有订单广播隔离。
95
82
  */
96
83
  async emitRemoteProductMembershipChanges(changes) {
97
84
  for (const payload of changes) {
98
85
  try {
99
- await this.core.effects.emit(import_types.OrderHooks.onRemoteProductMembershipChanged, payload);
86
+ await this.core.effects.emit(_types.OrderHooks.onRemoteProductMembershipChanged, payload);
100
87
  } catch (error) {
101
- this.logError("广播远端订单商品成员变更失败", {
88
+ this.logError('广播远端订单商品成员变更失败', {
102
89
  order_id: payload.order_id,
103
90
  source: payload.source,
104
91
  added_product_count: payload.added_product_keys.length,
@@ -109,38 +96,34 @@ var OrderModule = class extends import_BaseModule.BaseModule {
109
96
  }
110
97
  }
111
98
  async initialize(core, options) {
112
- var _a;
113
99
  this.core = core;
114
- this.store = options == null ? void 0 : options.store;
115
- if (!this.store.map)
116
- this.store.map = /* @__PURE__ */ new Map();
117
- const appPlugin = core.getPlugin("app");
118
- const app = appPlugin == null ? void 0 : appPlugin.getApp();
100
+ this.store = options?.store;
101
+ if (!this.store.map) this.store.map = new Map();
102
+ const appPlugin = core.getPlugin('app');
103
+ const app = appPlugin?.getApp();
119
104
  if (app) {
120
105
  this.dbManager = app.sqlite;
121
106
  this.logger = app.logger;
122
107
  this.storage = app.storage;
123
108
  this.updateCreateStore();
124
109
  }
125
- if (Array.isArray((_a = options == null ? void 0 : options.initialState) == null ? void 0 : _a.list)) {
126
- this.store.list = this.normalizeOrdersForMemoryList(
127
- options.initialState.list,
128
- "initialState"
129
- );
110
+ if (Array.isArray(options?.initialState?.list)) {
111
+ this.store.list = this.normalizeOrdersForMemoryList(options.initialState.list, 'initialState');
130
112
  this.syncOrdersMap();
131
- this.emitOrdersChanged([], "initialState");
113
+ this.emitOrdersChanged([], 'initialState');
132
114
  } else {
133
115
  this.store.list = [];
134
- this.store.map = /* @__PURE__ */ new Map();
116
+ this.store.map = new Map();
135
117
  }
136
118
  this.initOrderDataSource();
137
119
  this.setupOrderSync();
138
- this.logInfo("OrderServer模块初始化完成", {
120
+ this.logInfo('OrderServer模块初始化完成', {
139
121
  hasDbManager: !!this.dbManager,
140
122
  hasLogger: !!this.logger,
141
123
  initialOrderCount: this.store.list.length
142
124
  });
143
125
  }
126
+
144
127
  /**
145
128
  * 记录信息日志
146
129
  * @param title 日志标题
@@ -150,14 +133,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
150
133
  try {
151
134
  if (this.logger) {
152
135
  this.logger.addLog({
153
- type: "info",
136
+ type: 'info',
154
137
  title: `[OrderServerModule] ${title}`,
155
138
  metadata: metadata || {}
156
139
  });
157
140
  }
158
141
  } catch {
142
+ // 日志记录失败不影响主流程
159
143
  }
160
144
  }
145
+
161
146
  /**
162
147
  * 记录错误日志
163
148
  * @param title 日志标题
@@ -167,36 +152,39 @@ var OrderModule = class extends import_BaseModule.BaseModule {
167
152
  try {
168
153
  if (this.logger) {
169
154
  this.logger.addLog({
170
- type: "error",
155
+ type: 'error',
171
156
  title: `[OrderServerModule] ${title}`,
172
157
  metadata: metadata || {}
173
158
  });
174
159
  }
175
160
  } catch {
161
+ // 日志记录失败不影响主流程
176
162
  }
177
163
  }
178
164
  logWarning(title, metadata) {
179
165
  try {
180
166
  if (this.logger) {
181
167
  this.logger.addLog({
182
- type: "warning",
168
+ type: 'warning',
183
169
  title: `[OrderServerModule] ${title}`,
184
170
  metadata: metadata || {}
185
171
  });
186
172
  }
187
173
  } catch {
174
+ // 日志记录失败不影响主流程
188
175
  }
189
176
  }
177
+
190
178
  /**
191
179
  * 在订单进入内存或 SQLite 前统一压缩子项强身份重复并补齐协议 UID。
192
180
  * 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
193
181
  */
194
182
  normalizeOrderCollectionsForIngress(order, source) {
195
- const sourceOrder = (0, import_lodash_es.cloneDeep)(order);
183
+ const sourceOrder = (0, _lodashEs.cloneDeep)(order);
196
184
  const sourceOrderRecord = sourceOrder;
197
185
  if (Array.isArray(sourceOrderRecord.payments)) {
198
- sourceOrderRecord.payments = sourceOrderRecord.payments.map((payment) => {
199
- if (!(0, import_payment_utils.isPendingOrderPayment)(payment) || (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => key.startsWith("unique_payment_number:"))) {
186
+ sourceOrderRecord.payments = sourceOrderRecord.payments.map(payment => {
187
+ if (!(0, _paymentUtils.isPendingOrderPayment)(payment) || (0, _paymentUtils.getOrderPaymentIdentityKeys)(payment).some(key => key.startsWith('unique_payment_number:'))) {
200
188
  return payment;
201
189
  }
202
190
  return {
@@ -205,29 +193,30 @@ var OrderModule = class extends import_BaseModule.BaseModule {
205
193
  };
206
194
  });
207
195
  }
208
- const result = (0, import_orderCollectionIdentity.normalizeOrderCollections)(sourceOrder);
196
+ const result = (0, _orderCollectionIdentity.normalizeOrderCollections)(sourceOrder);
209
197
  const normalizedOrderRecord = result.order;
210
198
  if (Array.isArray(normalizedOrderRecord.payments)) {
211
- normalizedOrderRecord.payments = normalizedOrderRecord.payments.map(
212
- (payment) => {
213
- if (!(payment == null ? void 0 : payment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]))
214
- return payment;
215
- const nextPayment = { ...payment };
216
- const metadata = { ...nextPayment.metadata || {} };
217
- delete metadata.unique_payment_number;
218
- delete nextPayment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER];
219
- nextPayment.metadata = metadata;
220
- return nextPayment;
221
- }
222
- );
199
+ normalizedOrderRecord.payments = normalizedOrderRecord.payments.map(payment => {
200
+ if (!payment?.[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]) return payment;
201
+ const nextPayment = {
202
+ ...payment
203
+ };
204
+ const metadata = {
205
+ ...(nextPayment.metadata || {})
206
+ };
207
+ delete metadata.unique_payment_number;
208
+ delete nextPayment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER];
209
+ nextPayment.metadata = metadata;
210
+ return nextPayment;
211
+ });
223
212
  }
224
- const kinds = ["product", "booking", "payment"];
225
- const hasChanges = kinds.some((kind) => {
213
+ const kinds = ['product', 'booking', 'payment'];
214
+ const hasChanges = kinds.some(kind => {
226
215
  const stats = result.stats[kind];
227
216
  return stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
228
217
  });
229
218
  if (hasChanges) {
230
- const summarize = (stats) => ({
219
+ const summarize = stats => ({
231
220
  backfilled_uid_count: stats.backfilledUidCount,
232
221
  collapsed_duplicate_count: stats.collapsedDuplicateCount,
233
222
  uid_conflict_count: stats.uidConflictCount,
@@ -235,57 +224,49 @@ var OrderModule = class extends import_BaseModule.BaseModule {
235
224
  });
236
225
  const context = {
237
226
  source,
238
- order_id: (order == null ? void 0 : order.order_id) ?? null,
239
- external_sale_number: (order == null ? void 0 : order.external_sale_number) ?? null,
227
+ order_id: order?.order_id ?? null,
228
+ external_sale_number: order?.external_sale_number ?? null,
240
229
  products: summarize(result.stats.product),
241
230
  bookings: summarize(result.stats.booking),
242
231
  payments: summarize(result.stats.payment)
243
232
  };
244
- const hasUnsafeIdentity = kinds.some((kind) => {
233
+ const hasUnsafeIdentity = kinds.some(kind => {
245
234
  const stats = result.stats[kind];
246
235
  return stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
247
236
  });
248
237
  if (hasUnsafeIdentity) {
249
- this.logWarning("订单子项身份存在冲突或匿名行", context);
238
+ this.logWarning('订单子项身份存在冲突或匿名行', context);
250
239
  } else {
251
- this.logInfo("订单子项身份已规范化", context);
240
+ this.logInfo('订单子项身份已规范化', context);
252
241
  }
253
242
  }
254
243
  return result.order;
255
244
  }
245
+
256
246
  /**
257
247
  * incoming 决定权威成员集合;同一持久化行仍从 existing 补齐 incoming 省略的本地展示字段。
258
248
  */
259
249
  mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = [], options = {}) {
260
250
  const kind = ORDER_COLLECTION_KIND_BY_FIELD[field];
261
251
  const existingItems = Array.isArray(existing) ? existing : [];
262
- if (field === "payments" && options.preserveIdentifiedPendingPayments) {
263
- return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
264
- existingItems,
265
- incoming,
266
- { preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
267
- );
268
- }
269
- return incoming.map((incomingItem) => {
270
- const existingItem = existingItems.find(
271
- (item) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, item, incomingItem)
272
- );
273
- if (!existingItem)
274
- return (0, import_lodash_es.cloneDeep)(incomingItem);
275
- const mergedItem = (0, import_orderCollectionIdentity.mergeOrderCollectionItems)(kind, existingItem, incomingItem);
276
- const mergedUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)(kind, mergedItem);
252
+ if (field === 'payments' && options.preserveIdentifiedPendingPayments) {
253
+ return (0, _paymentUtils.mergeOrderPaymentListsByIdentity)(existingItems, incoming, {
254
+ preserveUnmatchedExistingWhen: _paymentUtils.isIdentifiedPendingOrderPayment
255
+ });
256
+ }
257
+ return incoming.map(incomingItem => {
258
+ const existingItem = existingItems.find(item => (0, _orderCollectionIdentity.isSameOrderCollectionItem)(kind, item, incomingItem));
259
+ if (!existingItem) return (0, _lodashEs.cloneDeep)(incomingItem);
260
+ const mergedItem = (0, _orderCollectionIdentity.mergeOrderCollectionItems)(kind, existingItem, incomingItem);
261
+ const mergedUid = (0, _orderCollectionIdentity.getOrderCollectionUid)(kind, mergedItem);
277
262
  if (mergedUid) {
278
- for (const from of /* @__PURE__ */ new Set([
279
- (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, existingItem),
280
- (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, incomingItem)
281
- ])) {
282
- if (!from || from === mergedUid)
283
- continue;
263
+ for (const from of new Set([(0, _orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, existingItem), (0, _orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, incomingItem)])) {
264
+ if (!from || from === mergedUid) continue;
284
265
  uidRemaps.push({
285
266
  kind,
286
267
  from,
287
268
  to: mergedUid,
288
- persistentId: (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, incomingItem) || (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, existingItem)
269
+ persistentId: (0, _orderCollectionIdentity.getOrderCollectionPersistentId)(kind, incomingItem) || (0, _orderCollectionIdentity.getOrderCollectionPersistentId)(kind, existingItem)
289
270
  });
290
271
  }
291
272
  }
@@ -293,25 +274,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
293
274
  });
294
275
  }
295
276
  reconcileOverwriteOrderCollections(existing, incoming) {
296
- const reconciled = (0, import_lodash_es.cloneDeep)(incoming);
277
+ const reconciled = (0, _lodashEs.cloneDeep)(incoming);
297
278
  const existingRecord = existing;
298
279
  const incomingRecord = incoming;
299
280
  const uidRemaps = [];
300
281
  for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
301
- if (!Array.isArray(incomingRecord[field]))
302
- continue;
303
- reconciled[field] = this.mergeAuthoritativeOrderCollection(
304
- field,
305
- existingRecord[field],
306
- incomingRecord[field],
307
- uidRemaps
308
- );
309
- }
310
- return this.normalizeOrderCollectionsForIngress(
311
- (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(reconciled, uidRemaps),
312
- "overwriteExistingOrder.reconciled"
313
- );
282
+ if (!Array.isArray(incomingRecord[field])) continue;
283
+ reconciled[field] = this.mergeAuthoritativeOrderCollection(field, existingRecord[field], incomingRecord[field], uidRemaps);
284
+ }
285
+ return this.normalizeOrderCollectionsForIngress((0, _orderCollectionIdentity.applyOrderCollectionUidRemaps)(reconciled, uidRemaps), 'overwriteExistingOrder.reconciled');
314
286
  }
287
+
315
288
  /**
316
289
  * 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
317
290
  *
@@ -322,21 +295,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
322
295
  const now = Date.now();
323
296
  for (const order of orders) {
324
297
  const storageKey = this.getOrderStorageKey(order);
325
- if (!storageKey)
326
- continue;
327
- this.recentSqliteWriteByStorageKey.set(storageKey, { source, ts: now });
298
+ if (!storageKey) continue;
299
+ this.recentSqliteWriteByStorageKey.set(storageKey, {
300
+ source,
301
+ ts: now
302
+ });
328
303
  }
329
304
  }
305
+
330
306
  /**
331
307
  * 过滤 pubsub 触发的冗余 SQLite patch(业务 API 刚写入过的 update 回声)。
332
308
  *
333
309
  * @example
334
310
  * const { toWrite, skipped } = this.filterRedundantPatchOrders('pubsub.bodyUpsert', orders, mergeActions)
335
311
  */
336
- filterRedundantPatchOrders(source, orders, mergeActions, forceWriteStorageKeys = /* @__PURE__ */ new Set()) {
337
- const eligibleSkipSources = /* @__PURE__ */ new Set(["pubsub.bodyUpsert", "pubsub.httpRefresh"]);
312
+ filterRedundantPatchOrders(source, orders, mergeActions, forceWriteStorageKeys = new Set()) {
313
+ const eligibleSkipSources = new Set(['pubsub.bodyUpsert', 'pubsub.httpRefresh']);
338
314
  if (!eligibleSkipSources.has(source)) {
339
- return { toWrite: orders, skipped: [] };
315
+ return {
316
+ toWrite: orders,
317
+ skipped: []
318
+ };
340
319
  }
341
320
  const now = Date.now();
342
321
  const toWrite = [];
@@ -347,12 +326,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
347
326
  toWrite.push(order);
348
327
  continue;
349
328
  }
350
- const orderKey = order.order_id !== void 0 && order.order_id !== null ? this.getIdKey(order.order_id) : "";
351
- const mergeAction = orderKey ? mergeActions[orderKey] : void 0;
352
- if (mergeAction === "insert") {
329
+ const orderKey = order.order_id !== undefined && order.order_id !== null ? this.getIdKey(order.order_id) : '';
330
+ const mergeAction = orderKey ? mergeActions[orderKey] : undefined;
331
+
332
+ // 新增单必须落库,不参与去重
333
+ if (mergeAction === 'insert') {
353
334
  toWrite.push(order);
354
335
  continue;
355
336
  }
337
+
338
+ // 远端商品成员确实发生增删时必须落库,避免内存已更新但 SQLite 仍被回声窗口跳过。
356
339
  if (forceWriteStorageKeys.has(storageKey)) {
357
340
  toWrite.push(order);
358
341
  continue;
@@ -362,7 +345,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
362
345
  skipped.push({
363
346
  orderId: order.order_id ?? null,
364
347
  storageKey,
365
- reason: "skip_pubsub_echo_after_business_write",
348
+ reason: 'skip_pubsub_echo_after_business_write',
366
349
  lastSource: recent.source,
367
350
  elapsedMs: now - recent.ts
368
351
  });
@@ -370,8 +353,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
370
353
  }
371
354
  toWrite.push(order);
372
355
  }
373
- return { toWrite, skipped };
356
+ return {
357
+ toWrite,
358
+ skipped
359
+ };
374
360
  }
361
+
375
362
  /**
376
363
  * 过滤 pubsub HTTP 增量拉取 ids:本地刚由业务 API 写入的单可跳过 HTTP。
377
364
  *
@@ -389,8 +376,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
389
376
  continue;
390
377
  }
391
378
  const storageKey = this.getOrderStorageKey(existing);
392
- const recent = storageKey ? this.recentSqliteWriteByStorageKey.get(storageKey) : void 0;
393
- if (recent && recent.source === "upsertOrdersFromRemote" && now - recent.ts < ORDER_SQLITE_DEDUPE_MS) {
379
+ const recent = storageKey ? this.recentSqliteWriteByStorageKey.get(storageKey) : undefined;
380
+ if (recent && recent.source === 'upsertOrdersFromRemote' && now - recent.ts < ORDER_SQLITE_DEDUPE_MS) {
394
381
  skipped.push({
395
382
  orderId: id,
396
383
  lastSource: recent.source,
@@ -400,8 +387,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
400
387
  }
401
388
  toFetch.push(id);
402
389
  }
403
- return { toFetch, skipped };
390
+ return {
391
+ toFetch,
392
+ skipped
393
+ };
404
394
  }
395
+
405
396
  /**
406
397
  * 解析 pubsub 消息会走哪条同步分支,便于对照为何触发 HTTP 重拉或 body 直写。
407
398
  *
@@ -410,25 +401,24 @@ var OrderModule = class extends import_BaseModule.BaseModule {
410
401
  * // => { route: 'httpRefresh.batchIds', ... }
411
402
  */
412
403
  resolveSyncMessageRoute(msg) {
413
- var _a;
414
404
  const hasBatchIds = Array.isArray(msg.ids) && msg.ids.length > 0;
415
405
  const singleIdRaw = msg.id ?? msg.order_id;
416
- const hasSingleId = !hasBatchIds && singleIdRaw !== void 0 && singleIdRaw !== null;
406
+ const hasSingleId = !hasBatchIds && singleIdRaw !== undefined && singleIdRaw !== null;
417
407
  const normalizedBody = this.normalizeOrderSyncPayload(msg.body || msg.data);
418
408
  if (hasBatchIds) {
419
409
  return {
420
- route: "httpRefresh.batchIds",
410
+ route: 'httpRefresh.batchIds',
421
411
  hasBatchIds: true,
422
412
  hasSingleId: false,
423
413
  hasNormalizedBody: !!normalizedBody,
424
414
  singleId: null,
425
415
  batchIds: msg.ids || [],
426
- bodyOrderId: (normalizedBody == null ? void 0 : normalizedBody.order_id) ?? null
416
+ bodyOrderId: normalizedBody?.order_id ?? null
427
417
  };
428
418
  }
429
419
  if (hasSingleId && normalizedBody) {
430
420
  return {
431
- route: "bodyUpsert",
421
+ route: 'bodyUpsert',
432
422
  hasBatchIds: false,
433
423
  hasSingleId: true,
434
424
  hasNormalizedBody: true,
@@ -439,77 +429,70 @@ var OrderModule = class extends import_BaseModule.BaseModule {
439
429
  }
440
430
  if (hasSingleId) {
441
431
  return {
442
- route: "httpRefresh.singleId",
432
+ route: 'httpRefresh.singleId',
443
433
  hasBatchIds: false,
444
434
  hasSingleId: true,
445
435
  hasNormalizedBody: !!normalizedBody,
446
436
  singleId: singleIdRaw,
447
437
  batchIds: [],
448
- bodyOrderId: (normalizedBody == null ? void 0 : normalizedBody.order_id) ?? null
438
+ bodyOrderId: normalizedBody?.order_id ?? null
449
439
  };
450
440
  }
451
- if ((_a = msg.relation_order_ids) == null ? void 0 : _a.length) {
441
+ if (msg.relation_order_ids?.length) {
452
442
  return {
453
- route: "httpRefresh.relationIds",
443
+ route: 'httpRefresh.relationIds',
454
444
  hasBatchIds: false,
455
445
  hasSingleId: false,
456
446
  hasNormalizedBody: !!normalizedBody,
457
447
  singleId: null,
458
448
  batchIds: msg.relation_order_ids,
459
- bodyOrderId: (normalizedBody == null ? void 0 : normalizedBody.order_id) ?? null
449
+ bodyOrderId: normalizedBody?.order_id ?? null
460
450
  };
461
451
  }
462
452
  return {
463
- route: "noop",
453
+ route: 'noop',
464
454
  hasBatchIds: false,
465
455
  hasSingleId: false,
466
456
  hasNormalizedBody: !!normalizedBody,
467
457
  singleId: null,
468
458
  batchIds: [],
469
- bodyOrderId: (normalizedBody == null ? void 0 : normalizedBody.order_id) ?? null
459
+ bodyOrderId: normalizedBody?.order_id ?? null
470
460
  };
471
461
  }
472
462
  updateCreateStore() {
473
- const appPlugin = this.core.getPlugin("app");
474
- const app = appPlugin == null ? void 0 : appPlugin.getApp();
463
+ const appPlugin = this.core.getPlugin('app');
464
+ const app = appPlugin?.getApp();
475
465
  if (app) {
476
- const coreData = app.data.store.getStore().getDataByModel("core");
477
- if (coreData == null ? void 0 : coreData.core) {
478
- const today = (0, import_dayjs.default)();
479
- if (coreData == null ? void 0 : coreData.core.operating_day_boundary) {
466
+ const coreData = app.data.store.getStore().getDataByModel('core');
467
+ if (coreData?.core) {
468
+ const today = (0, _dayjs.default)();
469
+ if (coreData?.core.operating_day_boundary) {
480
470
  const operatingDayBoundary = coreData.core.operating_day_boundary;
481
- if (operatingDayBoundary.type === "start_time") {
482
- const boundaryTime = String(operatingDayBoundary.time || "").trim();
483
- const boundaryStart = (0, import_dayjs.default)(`${today.format("YYYY-MM-DD")} ${boundaryTime}`);
471
+ if (operatingDayBoundary.type === 'start_time') {
472
+ const boundaryTime = String(operatingDayBoundary.time || '').trim();
473
+ const boundaryStart = (0, _dayjs.default)(`${today.format('YYYY-MM-DD')} ${boundaryTime}`);
484
474
  if (boundaryStart.isValid()) {
485
475
  const isAfterBoundary = today.isAfter(boundaryStart);
486
- const queryStart = isAfterBoundary ? today.startOf("day") : today.subtract(1, "day").startOf("day");
487
- const queryEnd = isAfterBoundary ? today.add(1, "day").endOf("day") : today.endOf("day");
476
+ const queryStart = isAfterBoundary ? today.startOf('day') : today.subtract(1, 'day').startOf('day');
477
+ const queryEnd = isAfterBoundary ? today.add(1, 'day').endOf('day') : today.endOf('day');
488
478
  this.store.createdAtQuery = {
489
- sales_time_between: [
490
- queryStart.format("YYYY-MM-DD HH:mm:ss"),
491
- queryEnd.format("YYYY-MM-DD HH:mm:ss")
492
- ]
479
+ sales_time_between: [queryStart.format('YYYY-MM-DD HH:mm:ss'), queryEnd.format('YYYY-MM-DD HH:mm:ss')]
493
480
  };
494
481
  } else {
482
+ // 边界时间异常时回退到自然日,避免 createdAtQuery 为空导致后续查询异常
495
483
  this.store.createdAtQuery = {
496
- sales_time_between: [
497
- today.startOf("day").format("YYYY-MM-DD HH:mm:ss"),
498
- today.endOf("day").format("YYYY-MM-DD HH:mm:ss")
499
- ]
484
+ sales_time_between: [today.startOf('day').format('YYYY-MM-DD HH:mm:ss'), today.endOf('day').format('YYYY-MM-DD HH:mm:ss')]
500
485
  };
501
486
  }
502
487
  } else {
503
488
  this.store.createdAtQuery = {
504
- sales_time_between: [
505
- today.startOf("day").format("YYYY-MM-DD HH:mm:ss"),
506
- today.endOf("day").format("YYYY-MM-DD HH:mm:ss")
507
- ]
489
+ sales_time_between: [today.startOf('day').format('YYYY-MM-DD HH:mm:ss'), today.endOf('day').format('YYYY-MM-DD HH:mm:ss')]
508
490
  };
509
491
  }
510
492
  } else {
493
+ // TODO: 这里后续可能需要使用店铺营业时间查询
511
494
  this.store.createdAtQuery = {
512
- sales_time_between: [today.startOf("day").format("YYYY-MM-DD HH:mm:ss"), today.endOf("day").format("YYYY-MM-DD HH:mm:ss")]
495
+ sales_time_between: [today.startOf('day').format('YYYY-MM-DD HH:mm:ss'), today.endOf('day').format('YYYY-MM-DD HH:mm:ss')]
513
496
  };
514
497
  }
515
498
  }
@@ -519,17 +502,32 @@ var OrderModule = class extends import_BaseModule.BaseModule {
519
502
  const raw = localStorage.getItem(ORDER_SYNC_THROTTLE_MS_STORAGE_KEY);
520
503
  if (raw !== null) {
521
504
  const parsed = Number(raw);
522
- if (Number.isFinite(parsed) && parsed >= 0)
523
- return parsed;
505
+ if (Number.isFinite(parsed) && parsed >= 0) return parsed;
524
506
  }
525
507
  return DEFAULT_ORDER_SYNC_THROTTLE_MS;
526
508
  }
527
509
  async preload() {
510
+ // const hasPulledInCurrentWindow = this.hasPulledOrdersToday()
511
+ // // 仅当缓存属于当前统计窗口时才直接复用,避免跨天/跨营业日窗口继续使用旧数据
512
+ // if (cachedOrders.length > 0 && hasPulledInCurrentWindow) {
513
+ // this.store.list = cloneDeep(cachedOrders)
514
+ // this.syncOrdersMap()
515
+ // this.core.effects.emit(OrderHooks.onOrdersChanged, this.store.list)
516
+ // return
517
+ // }
518
+
519
+ // if (hasPulledInCurrentWindow) {
520
+ // this.logInfo('当天已完成全量订单拉取,跳过本次全量拉取', {
521
+ // lastFullFetchAt: this.getStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY),
522
+ // })
523
+ // return
524
+ // }
525
+
528
526
  const orders = await this.loadOrdersByServer();
529
- this.store.list = (0, import_lodash_es.cloneDeep)(orders);
527
+ this.store.list = (0, _lodashEs.cloneDeep)(orders);
530
528
  this.syncOrdersMap();
531
- await this.emitOrdersChanged([], "preload");
532
- await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
529
+ await this.emitOrdersChanged([], 'preload');
530
+ await this.core.effects.emit(_types.OrderHooks.onOrdersSyncCompleted, null);
533
531
  }
534
532
  getOrders() {
535
533
  return this.store.list;
@@ -537,13 +535,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
537
535
  getOrderById(id) {
538
536
  return this.store.map.get(this.getIdKey(id));
539
537
  }
538
+
540
539
  /** 按 order_id 查询内存订单。 */
541
540
  getOrderByOrderId(orderId) {
542
541
  return this.store.map.get(this.getIdKey(orderId));
543
542
  }
544
543
  buildLocalPaymentOrderLogContext(order) {
545
- if (!order)
546
- return {};
544
+ if (!order) return {};
547
545
  return {
548
546
  order_id: order.order_id ?? null,
549
547
  external_sale_number: order.external_sale_number ?? null,
@@ -565,9 +563,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
565
563
  getLocalOrderFromMemoryByLookup(lookup) {
566
564
  const key = this.getIdKey(lookup);
567
565
  const memoryOrderById = this.store.map.get(key);
568
- if (memoryOrderById)
569
- return memoryOrderById;
570
- const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
566
+ if (memoryOrderById) return memoryOrderById;
567
+ const memoryOrder = this.store.list.find(order => this.isOrderLookupMatch(order, key));
571
568
  return memoryOrder || null;
572
569
  }
573
570
  async getLocalOrderByLookup(lookup, options = {}) {
@@ -578,22 +575,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
578
575
  memory_order_count: this.store.list.length
579
576
  };
580
577
  if (options.operationId) {
581
- this.logInfo("getLocalOrderByLookup-localPayment-开始", logContext);
578
+ this.logInfo('getLocalOrderByLookup-localPayment-开始', logContext);
582
579
  }
583
580
  const memoryOrderById = this.store.map.get(key);
584
581
  if (memoryOrderById) {
585
582
  if (options.operationId) {
586
- this.logInfo("getLocalOrderByLookup-localPayment-命中内存映射", {
583
+ this.logInfo('getLocalOrderByLookup-localPayment-命中内存映射', {
587
584
  ...logContext,
588
585
  ...this.buildLocalPaymentOrderLogContext(memoryOrderById)
589
586
  });
590
587
  }
591
588
  return memoryOrderById;
592
589
  }
593
- const memoryOrder = this.store.list.find((order) => this.isOrderLookupMatch(order, key));
590
+ const memoryOrder = this.store.list.find(order => this.isOrderLookupMatch(order, key));
594
591
  if (memoryOrder) {
595
592
  if (options.operationId) {
596
- this.logInfo("getLocalOrderByLookup-localPayment-命中内存列表", {
593
+ this.logInfo('getLocalOrderByLookup-localPayment-命中内存列表', {
597
594
  ...logContext,
598
595
  ...this.buildLocalPaymentOrderLogContext(memoryOrder)
599
596
  });
@@ -601,27 +598,24 @@ var OrderModule = class extends import_BaseModule.BaseModule {
601
598
  return memoryOrder;
602
599
  }
603
600
  if (options.operationId) {
604
- this.logInfo("getLocalOrderByLookup-localPayment-开始读取SQLite", logContext);
601
+ this.logInfo('getLocalOrderByLookup-localPayment-开始读取SQLite', logContext);
605
602
  }
606
603
  const orders = await this.loadOrdersFromSQLite();
607
- const localOrder = orders.find((order) => this.isOrderLookupMatch(order, key));
604
+ const localOrder = orders.find(order => this.isOrderLookupMatch(order, key));
608
605
  if (!localOrder) {
609
606
  if (options.operationId) {
610
- this.logWarning("getLocalOrderByLookup-localPayment-SQLite未命中", {
607
+ this.logWarning('getLocalOrderByLookup-localPayment-SQLite未命中', {
611
608
  ...logContext,
612
609
  sqlite_order_count: orders.length
613
610
  });
614
611
  }
615
612
  return null;
616
613
  }
617
- this.store.list = this.normalizeOrdersForMemoryList(
618
- orders,
619
- "getLocalOrderByLookup.sqliteMemory"
620
- );
614
+ this.store.list = this.normalizeOrdersForMemoryList(orders, 'getLocalOrderByLookup.sqliteMemory');
621
615
  this.syncOrdersMap();
622
616
  const normalizedOrder = this.normalizeOrderForMemoryList(localOrder);
623
617
  if (options.operationId) {
624
- this.logInfo("getLocalOrderByLookup-localPayment-SQLite命中", {
618
+ this.logInfo('getLocalOrderByLookup-localPayment-SQLite命中', {
625
619
  ...logContext,
626
620
  sqlite_order_count: orders.length,
627
621
  ...this.buildLocalPaymentOrderLogContext(normalizedOrder)
@@ -635,30 +629,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
635
629
  sale_id: params.saleId,
636
630
  payment_number: params.paymentNumber
637
631
  };
638
- this.logInfo("getLocalPayment-开始", logContext);
632
+ this.logInfo('getLocalPayment-开始', logContext);
639
633
  try {
640
634
  const order = await this.getLocalOrderByLookup(params.saleId, {
641
635
  operationId: params.operationId
642
636
  });
643
637
  if (!order) {
644
- this.logWarning("getLocalPayment-订单未命中", logContext);
638
+ this.logWarning('getLocalPayment-订单未命中', logContext);
645
639
  return null;
646
640
  }
647
641
  const payments = order.payments || [];
648
- const match = (0, import_payment_utils.resolveOrderPaymentIdentity)(
649
- payments,
650
- params.paymentNumber,
651
- "compat"
652
- );
642
+ const match = (0, _paymentUtils.resolveOrderPaymentIdentity)(payments, params.paymentNumber, 'compat');
653
643
  if (!match) {
654
- this.logWarning("getLocalPayment-支付项未命中", {
644
+ this.logWarning('getLocalPayment-支付项未命中', {
655
645
  ...logContext,
656
646
  ...this.buildLocalPaymentOrderLogContext(order),
657
647
  payments
658
648
  });
659
649
  return null;
660
650
  }
661
- this.logInfo("getLocalPayment-支付项命中", {
651
+ this.logInfo('getLocalPayment-支付项命中', {
662
652
  ...logContext,
663
653
  ...this.buildLocalPaymentOrderLogContext(order),
664
654
  matched_by: match.matchedBy,
@@ -672,7 +662,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
672
662
  matchedBy: match.matchedBy
673
663
  };
674
664
  } catch (error) {
675
- this.logError("getLocalPayment-查询失败", {
665
+ this.logError('getLocalPayment-查询失败', {
676
666
  ...logContext,
677
667
  error: error instanceof Error ? error.message : String(error)
678
668
  });
@@ -686,21 +676,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
686
676
  payment_number: params.paymentNumber,
687
677
  incoming_payment_update: params.updates
688
678
  };
689
- this.logInfo("updateLocalPayment-开始", logContext);
679
+ this.logInfo('updateLocalPayment-开始', logContext);
690
680
  const found = await this.getLocalPayment(params);
691
681
  if (!found) {
692
- this.logWarning("updateLocalPayment-支付项未命中", logContext);
682
+ this.logWarning('updateLocalPayment-支付项未命中', logContext);
693
683
  return null;
694
684
  }
695
- const previousPayment = (0, import_lodash_es.cloneDeep)(found.payment);
696
- const nextPayment = (0, import_payment_utils.mergeOrderPaymentRecord)(found.payment, {
685
+ const previousPayment = (0, _lodashEs.cloneDeep)(found.payment);
686
+ const nextPayment = (0, _paymentUtils.mergeOrderPaymentRecord)(found.payment, {
697
687
  ...params.updates,
698
- updated_at: params.updates.updated_at || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
688
+ updated_at: params.updates.updated_at || (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss')
699
689
  });
700
690
  const nextOrder = {
701
691
  ...found.order,
702
692
  payments: (found.order.payments || []).map((payment, index) => index === found.paymentIndex ? nextPayment : payment),
703
- updated_at: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
693
+ updated_at: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss')
704
694
  };
705
695
  const paymentContext = {
706
696
  ...logContext,
@@ -710,11 +700,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
710
700
  previous_payment: previousPayment,
711
701
  payment: nextPayment
712
702
  };
713
- this.logInfo("updateLocalPayment-支付项合并完成", paymentContext);
703
+ this.logInfo('updateLocalPayment-支付项合并完成', paymentContext);
714
704
  const targetIndex = this.findOrderIndexByIdentity(this.store.list, found.order);
715
705
  const shouldKeepInMemory = this.shouldKeepOrderInMemory(nextOrder);
716
706
  if (targetIndex < 0 && shouldKeepInMemory) {
717
- this.logError("updateLocalPayment-订单Store索引未命中", paymentContext);
707
+ this.logError('updateLocalPayment-订单Store索引未命中', paymentContext);
718
708
  return null;
719
709
  }
720
710
  const previousList = this.store.list;
@@ -722,19 +712,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
722
712
  this.syncOrdersMap();
723
713
  const storageOrder = this.withoutSyntheticDraftOrderId(nextOrder);
724
714
  try {
725
- this.logInfo("updateLocalPayment-SQLite写入开始", {
715
+ this.logInfo('updateLocalPayment-SQLite写入开始', {
726
716
  ...paymentContext,
727
717
  storage_order_id: storageOrder.order_id ?? null
728
718
  });
729
- await this.updateOrderInSQLite(storageOrder, "updateLocalPayment", { throwOnError: true });
730
- this.logInfo("updateLocalPayment-SQLite写入完成", {
719
+ await this.updateOrderInSQLite(storageOrder, 'updateLocalPayment', {
720
+ throwOnError: true
721
+ });
722
+ this.logInfo('updateLocalPayment-SQLite写入完成', {
731
723
  ...paymentContext,
732
724
  storage_order_id: storageOrder.order_id ?? null
733
725
  });
734
726
  } catch (error) {
735
727
  this.store.list = previousList;
736
728
  this.syncOrdersMap();
737
- this.logError("updateLocalPayment-SQLite写入失败并回滚内存", {
729
+ this.logError('updateLocalPayment-SQLite写入失败并回滚内存', {
738
730
  ...paymentContext,
739
731
  storage_order_id: storageOrder.order_id ?? null,
740
732
  error: error instanceof Error ? error.message : String(error)
@@ -742,28 +734,23 @@ var OrderModule = class extends import_BaseModule.BaseModule {
742
734
  throw error;
743
735
  }
744
736
  if (shouldKeepInMemory || targetIndex >= 0) {
745
- await this.emitOrdersChanged(
746
- shouldKeepInMemory ? [nextOrder] : [],
747
- shouldKeepInMemory ? "updateLocalPayment" : "updateLocalPayment.sqliteOnlyDraft"
748
- );
737
+ await this.emitOrdersChanged(shouldKeepInMemory ? [nextOrder] : [], shouldKeepInMemory ? 'updateLocalPayment' : 'updateLocalPayment.sqliteOnlyDraft');
749
738
  }
750
- this.logInfo("updateLocalPayment-变更事件完成", paymentContext);
751
- return { order: nextOrder, payment: nextPayment, previousPayment };
739
+ this.logInfo('updateLocalPayment-变更事件完成', paymentContext);
740
+ return {
741
+ order: nextOrder,
742
+ payment: nextPayment,
743
+ previousPayment
744
+ };
752
745
  }
753
746
  async loadOrdersByServer() {
754
- var _a;
755
747
  let orderList = [];
756
- const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(
757
- (order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order)
758
- );
759
- this.logInfo("loadOrdersByServer-开始", {
748
+ const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(order => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
749
+ this.logInfo('loadOrdersByServer-开始', {
760
750
  hasOrderDataSource: !!this.orderDataSource,
761
- query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null,
751
+ query: this.store?.createdAtQuery || null,
762
752
  protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length,
763
- protectedPendingPaymentCount: protectedOrdersBeforeRemoteFetch.reduce(
764
- (count, order) => count + this.getIdentifiedPendingPayments(order).length,
765
- 0
766
- )
753
+ protectedPendingPaymentCount: protectedOrdersBeforeRemoteFetch.reduce((count, order) => count + this.getIdentifiedPendingPayments(order).length, 0)
767
754
  });
768
755
  if (this.orderDataSource) {
769
756
  try {
@@ -773,33 +760,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
773
760
  }
774
761
  });
775
762
  orderList = data || [];
776
- this.logInfo("loadOrdersByServer-SSE拉取成功", {
763
+ this.logInfo('loadOrdersByServer-SSE拉取成功', {
777
764
  count: orderList.length
778
765
  });
779
766
  this.markOrderPulledAtNow();
780
767
  this.lastServerFullFetchAtMs = Date.now();
781
768
  } catch {
782
- this.logInfo("loadOrdersByServer-SSE拉取失败,保持当前内存订单");
769
+ this.logInfo('loadOrdersByServer-SSE拉取失败,保持当前内存订单');
783
770
  return this.store.list;
784
771
  }
785
772
  }
786
- const mergedOrders = await this.replaceOrdersSnapshotInSQLite(
787
- orderList,
788
- "loadOrdersByServer",
789
- protectedOrdersBeforeRemoteFetch
790
- );
791
- const memoryOrders = this.normalizeOrdersForMemoryList(
792
- mergedOrders,
793
- "loadOrdersByServer.memory"
794
- );
795
- this.logInfo("loadOrdersByServer-结束", {
773
+ const mergedOrders = await this.replaceOrdersSnapshotInSQLite(orderList, 'loadOrdersByServer', protectedOrdersBeforeRemoteFetch);
774
+ const memoryOrders = this.normalizeOrdersForMemoryList(mergedOrders, 'loadOrdersByServer.memory');
775
+ this.logInfo('loadOrdersByServer-结束', {
796
776
  count: memoryOrders.length,
797
777
  persistedCount: mergedOrders.length,
798
778
  sqliteOnlyDraftCount: mergedOrders.length - memoryOrders.length
799
779
  });
800
- await this.core.effects.emit(import_types.OrderHooks.onOrdersLoaded, memoryOrders);
780
+ await this.core.effects.emit(_types.OrderHooks.onOrdersLoaded, memoryOrders);
801
781
  return memoryOrders;
802
782
  }
783
+
803
784
  /**
804
785
  * 静默全量刷新:后台重新拉取全量 SSE 订单数据并更新本地
805
786
  * 拿到完整数据后一次性替换 store,触发订单变更与同步完成事件
@@ -811,38 +792,39 @@ var OrderModule = class extends import_BaseModule.BaseModule {
811
792
  if (this.lastServerFullFetchAtMs > 0 && elapsedSinceFullFetch < ORDER_SILENT_REFRESH_MIN_INTERVAL_MS) {
812
793
  return this.store.list;
813
794
  }
814
- this.logInfo("silentRefresh 开始");
795
+ this.logInfo('silentRefresh 开始');
815
796
  try {
797
+ // 刷新前,需要更新当前营业日边界(store.createdAtQuery)
816
798
  this.updateCreateStore();
817
799
  const orders = await this.loadOrdersByServer();
818
- this.store.list = (0, import_lodash_es.cloneDeep)(orders);
800
+ this.store.list = (0, _lodashEs.cloneDeep)(orders);
819
801
  this.syncOrdersMap();
820
- await this.emitOrdersChanged([], "silentRefresh");
821
- await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
822
- this.logInfo("silentRefresh 完成", {
802
+ await this.emitOrdersChanged([], 'silentRefresh');
803
+ await this.core.effects.emit(_types.OrderHooks.onOrdersSyncCompleted, null);
804
+ this.logInfo('silentRefresh 完成', {
823
805
  orderCount: orders.length,
824
806
  duration: `${Date.now() - startTime}ms`
825
807
  });
826
808
  return this.store.list;
827
809
  } catch (error) {
828
810
  const errorMessage = error instanceof Error ? error.message : String(error);
829
- this.logError("silentRefresh 失败", {
811
+ this.logError('silentRefresh 失败', {
830
812
  duration: `${Date.now() - startTime}ms`,
831
813
  error: errorMessage
832
814
  });
833
815
  return this.store.list;
834
816
  }
835
817
  }
836
- normalizeOrderForMemoryList(order, source = "normalizeOrderForMemoryList") {
818
+ normalizeOrderForMemoryList(order, source = 'normalizeOrderForMemoryList') {
837
819
  const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, source);
838
- const externalSaleNumber = normalizedOrder == null ? void 0 : normalizedOrder.external_sale_number;
820
+ const externalSaleNumber = normalizedOrder?.external_sale_number;
839
821
  if (this.isDraftOrder(normalizedOrder) && !this.hasRealOrderId(normalizedOrder)) {
840
822
  return normalizedOrder;
841
823
  }
842
- if ((normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== void 0 && (normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== null && (normalizedOrder == null ? void 0 : normalizedOrder.order_id) !== "") {
824
+ if (normalizedOrder?.order_id !== undefined && normalizedOrder?.order_id !== null && normalizedOrder?.order_id !== '') {
843
825
  return normalizedOrder;
844
826
  }
845
- if (externalSaleNumber === void 0 || externalSaleNumber === null || externalSaleNumber === "") {
827
+ if (externalSaleNumber === undefined || externalSaleNumber === null || externalSaleNumber === '') {
846
828
  return normalizedOrder;
847
829
  }
848
830
  return {
@@ -851,11 +833,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
851
833
  };
852
834
  }
853
835
  normalizeOrdersForMemoryList(orders, source) {
854
- return orders.map((order) => this.normalizeOrderForMemoryList(order, source)).filter((order) => this.shouldKeepOrderInMemory(order));
836
+ return orders.map(order => this.normalizeOrderForMemoryList(order, source)).filter(order => this.shouldKeepOrderInMemory(order));
855
837
  }
856
838
  hasRealOrderId(order) {
857
- if (!order || this.isBlankIdentityValue(order.order_id))
858
- return false;
839
+ if (!order || this.isBlankIdentityValue(order.order_id)) return false;
859
840
  const externalSaleNumber = order.external_sale_number;
860
841
  return !(this.isDraftOrder(order) && !this.isBlankIdentityValue(externalSaleNumber) && String(order.order_id) === String(externalSaleNumber));
861
842
  }
@@ -864,67 +845,75 @@ var OrderModule = class extends import_BaseModule.BaseModule {
864
845
  }
865
846
  withoutSyntheticDraftOrderId(order) {
866
847
  const externalSaleNumber = order.external_sale_number;
867
- if (Number(order.is_draft_order || 0) !== 1 || order.order_id === void 0 || externalSaleNumber === void 0 || String(order.order_id) !== String(externalSaleNumber)) {
848
+ if (Number(order.is_draft_order || 0) !== 1 || order.order_id === undefined || externalSaleNumber === undefined || String(order.order_id) !== String(externalSaleNumber)) {
868
849
  return order;
869
850
  }
870
- const next = { ...order };
851
+ const next = {
852
+ ...order
853
+ };
871
854
  delete next.order_id;
872
855
  return next;
873
856
  }
857
+
874
858
  /**
875
859
  * 仅覆盖本地已存在的订单;不存在则直接跳过,不落库、不 emit。
876
860
  * 适用于"按 order_id 主动刷新本地订单详情"的代理场景。
877
861
  */
878
862
  async overwriteExistingOrder(fresh) {
879
- const orderId = fresh == null ? void 0 : fresh.order_id;
880
- if (orderId === void 0 || orderId === null) {
881
- this.logError("overwriteExistingOrder-入参缺少 order_id");
882
- return { overwritten: false };
863
+ const orderId = fresh?.order_id;
864
+ if (orderId === undefined || orderId === null) {
865
+ this.logError('overwriteExistingOrder-入参缺少 order_id');
866
+ return {
867
+ overwritten: false
868
+ };
883
869
  }
884
870
  const key = this.getIdKey(orderId);
885
871
  if (!this.store.map.has(key)) {
886
- this.logInfo("overwriteExistingOrder-本地不存在该订单,跳过", { orderId });
887
- return { overwritten: false };
872
+ this.logInfo('overwriteExistingOrder-本地不存在该订单,跳过', {
873
+ orderId
874
+ });
875
+ return {
876
+ overwritten: false
877
+ };
888
878
  }
889
- this.logInfo("overwriteExistingOrder-开始覆盖", {
879
+ this.logInfo('overwriteExistingOrder-开始覆盖', {
890
880
  orderId,
891
881
  storeOrderCountBefore: this.store.list.length
892
882
  });
893
- const normalizedFresh = this.normalizeOrderForMemoryList(
894
- fresh,
895
- "overwriteExistingOrder.incoming"
896
- );
883
+ const normalizedFresh = this.normalizeOrderForMemoryList(fresh, 'overwriteExistingOrder.incoming');
897
884
  const existingOrder = this.store.map.get(key);
898
- const reconciledFresh = this.reconcileOverwriteOrderCollections(
899
- existingOrder,
900
- normalizedFresh
901
- );
902
- this.store.list = this.store.list.map((order) => {
903
- const id = order == null ? void 0 : order.order_id;
904
- if (id === void 0 || id === null) {
905
- return this.normalizeOrderForMemoryList(order, "overwriteExistingOrder.existingMemory");
885
+ const reconciledFresh = this.reconcileOverwriteOrderCollections(existingOrder, normalizedFresh);
886
+ this.store.list = this.store.list.map(order => {
887
+ const id = order?.order_id;
888
+ if (id === undefined || id === null) {
889
+ return this.normalizeOrderForMemoryList(order, 'overwriteExistingOrder.existingMemory');
906
890
  }
907
- return this.getIdKey(id) === key ? reconciledFresh : this.normalizeOrderForMemoryList(order, "overwriteExistingOrder.existingMemory");
891
+ return this.getIdKey(id) === key ? reconciledFresh : this.normalizeOrderForMemoryList(order, 'overwriteExistingOrder.existingMemory');
908
892
  });
909
893
  this.syncOrdersMap();
910
- await this.updateOrderInSQLite(reconciledFresh, "overwriteExistingOrder");
911
- this.logInfo("overwriteExistingOrder-结束", {
894
+ await this.updateOrderInSQLite(reconciledFresh, 'overwriteExistingOrder');
895
+ this.logInfo('overwriteExistingOrder-结束', {
912
896
  orderId,
913
897
  storeOrderCountAfter: this.store.list.length
914
898
  });
915
- await this.emitOrdersChanged([reconciledFresh], "overwriteExistingOrder");
916
- return { overwritten: true };
899
+ await this.emitOrdersChanged([reconciledFresh], 'overwriteExistingOrder');
900
+ return {
901
+ overwritten: true
902
+ };
917
903
  }
904
+
918
905
  /**
919
906
  * 将远端拉取的订单合并进本地 store(已存在则更新,不存在则追加),落库并 emit onOrdersChanged。
920
907
  * 供 /update/localOrder 等在「本地尚无该单」时写入新建单。
921
908
  */
922
- async upsertOrdersFromRemote(freshOrders, source = "upsertOrdersFromRemote") {
923
- if (!(freshOrders == null ? void 0 : freshOrders.length)) {
924
- this.logInfo("upsertOrdersFromRemote-订单列表为空", { source });
909
+ async upsertOrdersFromRemote(freshOrders, source = 'upsertOrdersFromRemote') {
910
+ if (!freshOrders?.length) {
911
+ this.logInfo('upsertOrdersFromRemote-订单列表为空', {
912
+ source
913
+ });
925
914
  return;
926
915
  }
927
- this.logInfo("upsertOrdersFromRemote-开始", {
916
+ this.logInfo('upsertOrdersFromRemote-开始', {
928
917
  count: freshOrders.length,
929
918
  source
930
919
  });
@@ -932,106 +921,100 @@ var OrderModule = class extends import_BaseModule.BaseModule {
932
921
  }
933
922
  async markOrderSyncedByExternalSaleNumber(params) {
934
923
  const externalSaleNumber = params.externalSaleNumber;
935
- if (externalSaleNumber === void 0 || externalSaleNumber === null || externalSaleNumber === "") {
936
- this.logError("markOrderSyncedByExternalSaleNumber-缺少 external_sale_number");
937
- return { updated: false };
924
+ if (externalSaleNumber === undefined || externalSaleNumber === null || externalSaleNumber === '') {
925
+ this.logError('markOrderSyncedByExternalSaleNumber-缺少 external_sale_number');
926
+ return {
927
+ updated: false
928
+ };
938
929
  }
939
930
  const key = this.getIdKey(externalSaleNumber);
940
- const targetIndex = this.store.list.findIndex((order) => {
941
- const value = order == null ? void 0 : order.external_sale_number;
942
- if (value === void 0 || value === null || value === "")
943
- return false;
931
+ const targetIndex = this.store.list.findIndex(order => {
932
+ const value = order?.external_sale_number;
933
+ if (value === undefined || value === null || value === '') return false;
944
934
  return this.getIdKey(value) === key;
945
935
  });
946
936
  if (targetIndex < 0) {
947
- this.logInfo("markOrderSyncedByExternalSaleNumber-本地订单不存在,跳过", {
937
+ this.logInfo('markOrderSyncedByExternalSaleNumber-本地订单不存在,跳过', {
948
938
  external_sale_number: externalSaleNumber
949
939
  });
950
- return { updated: false };
940
+ return {
941
+ updated: false
942
+ };
951
943
  }
952
944
  const existing = this.store.list[targetIndex];
953
945
  const nextOrder = this.normalizeRemoteSyncedOrder({
954
946
  ...existing,
955
- ...params.patch || {},
947
+ ...(params.patch || {}),
956
948
  external_sale_number: existing.external_sale_number ?? externalSaleNumber,
957
949
  need_sync: 0,
958
950
  is_draft_order: 0
959
951
  });
960
952
  const storageKey = this.getOrderStorageKey(nextOrder) || key;
961
953
  this.store.list = this.store.list.map((order, index) => {
962
- if (index !== targetIndex)
963
- return order;
954
+ if (index !== targetIndex) return order;
964
955
  return nextOrder;
965
956
  });
966
957
  this.syncOrdersMap();
967
- await this.patchOrdersInSQLite(
968
- [nextOrder],
969
- "markOrderSyncedByExternalSaleNumber",
970
- { [storageKey]: "update" }
971
- );
972
- this.logInfo("markOrderSyncedByExternalSaleNumber-完成", {
958
+ await this.patchOrdersInSQLite([nextOrder], 'markOrderSyncedByExternalSaleNumber', {
959
+ [storageKey]: 'update'
960
+ });
961
+ this.logInfo('markOrderSyncedByExternalSaleNumber-完成', {
973
962
  external_sale_number: externalSaleNumber,
974
963
  order_id: nextOrder.order_id ?? null
975
964
  });
976
- await this.emitOrdersChanged([nextOrder], "markOrderSyncedByExternalSaleNumber");
977
- return { updated: true, order: nextOrder };
965
+ await this.emitOrdersChanged([nextOrder], 'markOrderSyncedByExternalSaleNumber');
966
+ return {
967
+ updated: true,
968
+ order: nextOrder
969
+ };
978
970
  }
971
+
979
972
  /**
980
973
  * 将本地待同步订单按 SQLite storage key 合并进 store 并落库。
981
974
  * checkout 离线兜底可能没有 order_id,但通常会有 external_sale_number。
982
975
  */
983
976
  async upsertPendingSyncOrders(pendingOrders, options = {}) {
984
- if (!(pendingOrders == null ? void 0 : pendingOrders.length)) {
985
- this.logInfo("upsertPendingSyncOrders-订单列表为空", {});
977
+ if (!pendingOrders?.length) {
978
+ this.logInfo('upsertPendingSyncOrders-订单列表为空', {});
986
979
  return;
987
980
  }
988
- const pendingMap = /* @__PURE__ */ new Map();
989
- const memoryPendingMap = /* @__PURE__ */ new Map();
981
+ const pendingMap = new Map();
982
+ const memoryPendingMap = new Map();
990
983
  for (const order of pendingOrders) {
991
- const normalizedOrder = this.normalizeOrderCollectionsForIngress(
992
- order,
993
- "upsertPendingSyncOrders.incoming"
994
- );
984
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, 'upsertPendingSyncOrders.incoming');
995
985
  const pendingOrder = {
996
986
  ...normalizedOrder,
997
987
  need_sync: 1,
998
988
  is_draft_order: 0
999
989
  };
1000
990
  const storageKey = this.getOrderStorageKey(pendingOrder);
1001
- if (!storageKey)
1002
- continue;
991
+ if (!storageKey) continue;
1003
992
  pendingMap.set(storageKey, pendingOrder);
1004
- memoryPendingMap.set(
1005
- storageKey,
1006
- this.normalizeOrderForMemoryList(
1007
- pendingOrder,
1008
- "upsertPendingSyncOrders.memory"
1009
- )
1010
- );
993
+ memoryPendingMap.set(storageKey, this.normalizeOrderForMemoryList(pendingOrder, 'upsertPendingSyncOrders.memory'));
1011
994
  }
1012
995
  if (pendingMap.size === 0) {
1013
- this.logError("upsertPendingSyncOrders-订单缺少可落库标识", {
996
+ this.logError('upsertPendingSyncOrders-订单缺少可落库标识', {
1014
997
  count: pendingOrders.length
1015
998
  });
1016
999
  return;
1017
1000
  }
1018
- this.logInfo("upsertPendingSyncOrders-开始", { count: pendingMap.size });
1001
+ this.logInfo('upsertPendingSyncOrders-开始', {
1002
+ count: pendingMap.size
1003
+ });
1019
1004
  const mergeActions = {};
1020
- const updatedList = this.store.list.map(
1021
- (order) => this.normalizeOrderForMemoryList(order, "upsertPendingSyncOrders.existingMemory")
1022
- );
1023
- const identityKeyToIndex = /* @__PURE__ */ new Map();
1005
+ const updatedList = this.store.list.map(order => this.normalizeOrderForMemoryList(order, 'upsertPendingSyncOrders.existingMemory'));
1006
+
1007
+ // 与 mergeOrdersToStore 一致:基于身份键(field:value)建立索引,把「查找已存在订单」
1008
+ // O(n) 线性扫描降为 O(1),整体复杂度由 O(n^2) 降为 O(n + m)
1009
+ const identityKeyToIndex = new Map();
1024
1010
  for (let index = 0; index < updatedList.length; index += 1) {
1025
1011
  for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1026
- if (!identityKeyToIndex.has(key))
1027
- identityKeyToIndex.set(key, index);
1012
+ // 同一 key 命中多张时保留最靠前的下标,与原 findIndex「取首个匹配」一致
1013
+ if (!identityKeyToIndex.has(key)) identityKeyToIndex.set(key, index);
1028
1014
  }
1029
1015
  }
1030
1016
  for (const [storageKey, pendingOrder] of memoryPendingMap.entries()) {
1031
- const matchIndex = this.lookupOrderIndexByIdentityKeys(
1032
- identityKeyToIndex,
1033
- this.getOrderIdentityMatchKeys(pendingOrder)
1034
- );
1017
+ const matchIndex = this.lookupOrderIndexByIdentityKeys(identityKeyToIndex, this.getOrderIdentityMatchKeys(pendingOrder));
1035
1018
  if (matchIndex >= 0) {
1036
1019
  const existingOrder = updatedList[matchIndex];
1037
1020
  const mergedOrder = this.mergeOrderRecords(existingOrder, pendingOrder);
@@ -1043,53 +1026,48 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1043
1026
  updatedList[matchIndex] = nextOrder;
1044
1027
  const pendingSnapshot = pendingMap.get(storageKey);
1045
1028
  if (pendingSnapshot) {
1046
- pendingMap.set(
1047
- storageKey,
1048
- this.reconcileOverwriteOrderCollections(existingOrder, pendingSnapshot)
1049
- );
1029
+ pendingMap.set(storageKey, this.reconcileOverwriteOrderCollections(existingOrder, pendingSnapshot));
1050
1030
  }
1031
+ // 合并后身份字段可能新增(如挂单拿到 order_id),同步登记,供同批后续 pending 命中同一槽位
1051
1032
  this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
1052
- mergeActions[storageKey] = "update";
1033
+ mergeActions[storageKey] = 'update';
1053
1034
  continue;
1054
1035
  }
1055
1036
  const insertIndex = updatedList.length;
1056
1037
  updatedList.push(pendingOrder);
1057
1038
  this.registerOrderIdentityKeys(identityKeyToIndex, pendingOrder, insertIndex);
1058
- mergeActions[storageKey] = "insert";
1039
+ mergeActions[storageKey] = 'insert';
1059
1040
  }
1060
1041
  const patchedOrders = [...pendingMap.values()];
1042
+ // 增量索引已保证 store 去重不变量,无需再对全表做 O(n^2) 压缩;仅自检开关开启时兜底。
1061
1043
  const previousList = this.store.list;
1062
- this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertPendingSyncOrders.store");
1044
+ this.store.list = this.runOrderStoreSelfCheck(updatedList, 'upsertPendingSyncOrders.store');
1063
1045
  this.syncOrdersMap();
1064
1046
  try {
1065
- await this.patchOrdersInSQLite(
1066
- patchedOrders,
1067
- "upsertPendingSyncOrders",
1068
- mergeActions,
1069
- options
1070
- );
1047
+ await this.patchOrdersInSQLite(patchedOrders, 'upsertPendingSyncOrders', mergeActions, options);
1071
1048
  } catch (error) {
1072
1049
  this.store.list = previousList;
1073
1050
  this.syncOrdersMap();
1074
1051
  throw error;
1075
1052
  }
1076
- this.logInfo("upsertPendingSyncOrders-结束", {
1053
+ this.logInfo('upsertPendingSyncOrders-结束', {
1077
1054
  count: patchedOrders.length,
1078
1055
  storeOrderCountAfter: this.store.list.length
1079
1056
  });
1080
- await this.emitOrdersChanged(patchedOrders, "upsertPendingSyncOrders");
1057
+ await this.emitOrdersChanged(patchedOrders, 'upsertPendingSyncOrders');
1081
1058
  }
1059
+
1082
1060
  /**
1083
1061
  * 将 POS 草稿订单按 SQLite storage key 落库。
1084
1062
  * 只有具备真实 order_id 的草稿进入 store;其余草稿仅供本地恢复查询。
1085
1063
  */
1086
1064
  async upsertLocalDraftOrders(draftOrders) {
1087
- if (!(draftOrders == null ? void 0 : draftOrders.length)) {
1088
- this.logInfo("upsertLocalDraftOrders-订单列表为空", {});
1065
+ if (!draftOrders?.length) {
1066
+ this.logInfo('upsertLocalDraftOrders-订单列表为空', {});
1089
1067
  return;
1090
1068
  }
1091
- const draftMap = /* @__PURE__ */ new Map();
1092
- const memoryDraftMap = /* @__PURE__ */ new Map();
1069
+ const draftMap = new Map();
1070
+ const memoryDraftMap = new Map();
1093
1071
  for (const order of draftOrders) {
1094
1072
  const draftOrder = {
1095
1073
  ...order,
@@ -1097,8 +1075,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1097
1075
  is_draft_order: 1
1098
1076
  };
1099
1077
  const storageKey = this.getOrderStorageKey(draftOrder);
1100
- if (!storageKey)
1101
- continue;
1078
+ if (!storageKey) continue;
1102
1079
  draftMap.set(storageKey, draftOrder);
1103
1080
  const memoryDraftOrder = this.normalizeOrderForMemoryList(draftOrder);
1104
1081
  if (this.shouldKeepOrderInMemory(memoryDraftOrder)) {
@@ -1106,36 +1083,29 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1106
1083
  }
1107
1084
  }
1108
1085
  if (draftMap.size === 0) {
1109
- this.logError("upsertLocalDraftOrders-订单缺少可落库标识", {
1086
+ this.logError('upsertLocalDraftOrders-订单缺少可落库标识', {
1110
1087
  count: draftOrders.length
1111
1088
  });
1112
1089
  return;
1113
1090
  }
1114
- this.logInfo("upsertLocalDraftOrders-开始", {
1091
+ this.logInfo('upsertLocalDraftOrders-开始', {
1115
1092
  count: draftMap.size,
1116
1093
  memoryDraftCount: memoryDraftMap.size,
1117
1094
  sqliteOnlyDraftCount: draftMap.size - memoryDraftMap.size
1118
1095
  });
1119
1096
  const mergeActions = {};
1120
- const updatedList = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
1121
- const identityKeyToIndex = /* @__PURE__ */ new Map();
1097
+ const updatedList = this.store.list.filter(order => this.shouldKeepOrderInMemory(order));
1098
+ const identityKeyToIndex = new Map();
1122
1099
  for (let index = 0; index < updatedList.length; index += 1) {
1123
1100
  for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1124
- if (!identityKeyToIndex.has(key))
1125
- identityKeyToIndex.set(key, index);
1101
+ if (!identityKeyToIndex.has(key)) identityKeyToIndex.set(key, index);
1126
1102
  }
1127
1103
  }
1128
1104
  for (const [storageKey, draftOrder] of memoryDraftMap.entries()) {
1129
- const matchIndex = this.lookupOrderIndexByIdentityKeys(
1130
- identityKeyToIndex,
1131
- this.getOrderIdentityMatchKeys(draftOrder)
1132
- );
1105
+ const matchIndex = this.lookupOrderIndexByIdentityKeys(identityKeyToIndex, this.getOrderIdentityMatchKeys(draftOrder));
1133
1106
  if (matchIndex >= 0) {
1134
1107
  const existingOrder = updatedList[matchIndex];
1135
- const reconciledDraftOrder = this.preserveExistingBusinessCodeForDraft(
1136
- existingOrder,
1137
- draftOrder
1138
- );
1108
+ const reconciledDraftOrder = this.preserveExistingBusinessCodeForDraft(existingOrder, draftOrder);
1139
1109
  const mergedOrder = this.mergeOrderRecords(existingOrder, reconciledDraftOrder);
1140
1110
  const nextOrder = {
1141
1111
  ...mergedOrder,
@@ -1143,57 +1113,54 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1143
1113
  is_draft_order: 1
1144
1114
  };
1145
1115
  updatedList[matchIndex] = nextOrder;
1116
+ // SQLite 必须与内存中的草稿保持同一份 business_code,避免下次 hydrate 再次丢失分类。
1146
1117
  draftMap.set(storageKey, reconciledDraftOrder);
1147
1118
  this.registerOrderIdentityKeys(identityKeyToIndex, nextOrder, matchIndex);
1148
- mergeActions[storageKey] = "update";
1119
+ mergeActions[storageKey] = 'update';
1149
1120
  continue;
1150
1121
  }
1151
1122
  const insertIndex = updatedList.length;
1152
1123
  updatedList.push(draftOrder);
1153
1124
  this.registerOrderIdentityKeys(identityKeyToIndex, draftOrder, insertIndex);
1154
- mergeActions[storageKey] = "insert";
1125
+ mergeActions[storageKey] = 'insert';
1155
1126
  }
1156
1127
  const patchedOrders = [...draftMap.values()];
1157
1128
  const previousList = this.store.list;
1158
- this.store.list = this.runOrderStoreSelfCheck(updatedList, "upsertLocalDraftOrders.store");
1129
+ this.store.list = this.runOrderStoreSelfCheck(updatedList, 'upsertLocalDraftOrders.store');
1159
1130
  this.syncOrdersMap();
1160
1131
  try {
1161
- await this.patchOrdersInSQLite(
1162
- patchedOrders,
1163
- "upsertLocalDraftOrders",
1164
- mergeActions,
1165
- { throwOnError: true }
1166
- );
1132
+ await this.patchOrdersInSQLite(patchedOrders, 'upsertLocalDraftOrders', mergeActions, {
1133
+ throwOnError: true
1134
+ });
1167
1135
  } catch (error) {
1168
1136
  this.store.list = previousList;
1169
1137
  this.syncOrdersMap();
1170
1138
  throw error;
1171
1139
  }
1172
- this.logInfo("upsertLocalDraftOrders-结束", {
1140
+ this.logInfo('upsertLocalDraftOrders-结束', {
1173
1141
  count: patchedOrders.length,
1174
1142
  storeOrderCountAfter: this.store.list.length
1175
1143
  });
1176
- const removedLegacyMemoryDraft = previousList.some(
1177
- (order) => !this.shouldKeepOrderInMemory(order)
1178
- );
1144
+ const removedLegacyMemoryDraft = previousList.some(order => !this.shouldKeepOrderInMemory(order));
1179
1145
  if (memoryDraftMap.size > 0 || removedLegacyMemoryDraft) {
1180
- await this.emitOrdersChanged(
1181
- patchedOrders.filter((order) => this.shouldKeepOrderInMemory(order)),
1182
- "upsertLocalDraftOrders"
1183
- );
1146
+ await this.emitOrdersChanged(patchedOrders.filter(order => this.shouldKeepOrderInMemory(order)), 'upsertLocalDraftOrders');
1184
1147
  }
1185
1148
  }
1149
+
1186
1150
  /**
1187
1151
  * 通过 SSE 按自定义 query 拉取订单(支持 select/with 精简字段)
1188
1152
  */
1189
1153
  async fetchOrdersBySSE(query = {}) {
1190
- if (!this.orderDataSource)
1191
- return [];
1154
+ if (!this.orderDataSource) return [];
1192
1155
  try {
1193
- const data = await this.orderDataSource.run({ sse: { query } });
1156
+ const data = await this.orderDataSource.run({
1157
+ sse: {
1158
+ query
1159
+ }
1160
+ });
1194
1161
  return data || [];
1195
1162
  } catch (error) {
1196
- this.logError("fetchOrdersBySSE-失败", {
1163
+ this.logError('fetchOrdersBySSE-失败', {
1197
1164
  error: error instanceof Error ? error.message : String(error)
1198
1165
  });
1199
1166
  return [];
@@ -1203,30 +1170,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1203
1170
  return [];
1204
1171
  }
1205
1172
  destroy() {
1206
- var _a;
1207
1173
  if (this.syncTimer) {
1208
1174
  clearTimeout(this.syncTimer);
1209
- this.syncTimer = void 0;
1175
+ this.syncTimer = undefined;
1210
1176
  }
1211
1177
  this.isProcessingSyncBatch = false;
1212
1178
  this.pendingSyncMessages = [];
1213
- if ((_a = this.orderDataSource) == null ? void 0 : _a.destroy)
1214
- this.orderDataSource.destroy();
1179
+ if (this.orderDataSource?.destroy) this.orderDataSource.destroy();
1215
1180
  super.destroy();
1216
1181
  }
1217
1182
  syncOrdersMap() {
1218
- this.store.list = this.store.list.filter((order) => this.shouldKeepOrderInMemory(order));
1183
+ this.store.list = this.store.list.filter(order => this.shouldKeepOrderInMemory(order));
1219
1184
  this.store.map.clear();
1220
1185
  for (const order of this.store.list) {
1221
1186
  const primaryIdentity = this.getOrderMapKey(order);
1222
- if (!primaryIdentity)
1223
- continue;
1187
+ if (!primaryIdentity) continue;
1224
1188
  this.store.map.set(primaryIdentity, order);
1225
1189
  }
1226
1190
  }
1227
1191
  getOrderMapKey(order) {
1228
- if (!order)
1229
- return "";
1192
+ if (!order) return '';
1230
1193
  if (!this.isBlankIdentityValue(order.order_id)) {
1231
1194
  return this.getIdKey(order.order_id);
1232
1195
  }
@@ -1234,11 +1197,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1234
1197
  if (!this.isBlankIdentityValue(externalSaleNumber)) {
1235
1198
  return this.getIdKey(externalSaleNumber);
1236
1199
  }
1237
- return "";
1200
+ return '';
1238
1201
  }
1239
1202
  isBlankIdentityValue(value) {
1240
- return value === void 0 || value === null || value === "";
1203
+ return value === undefined || value === null || value === '';
1241
1204
  }
1205
+
1242
1206
  /**
1243
1207
  * `/sales/draft` 的旧调用方可能把未设置的 business_code 传成空串。
1244
1208
  * 对同一真实订单,空值不能覆盖已有的分类,否则 booking 查询会把该订单从 Party 列表过滤掉。
@@ -1246,92 +1210,85 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1246
1210
  preserveExistingBusinessCodeForDraft(existingOrder, draftOrder) {
1247
1211
  const existingBusinessCode = existingOrder.business_code;
1248
1212
  const draftBusinessCode = draftOrder.business_code;
1249
- const hasExistingBusinessCode = typeof existingBusinessCode === "string" && existingBusinessCode.trim() !== "";
1250
- const hasDraftBusinessCode = typeof draftBusinessCode === "string" && draftBusinessCode.trim() !== "";
1251
- if (!hasExistingBusinessCode || hasDraftBusinessCode)
1252
- return draftOrder;
1213
+ const hasExistingBusinessCode = typeof existingBusinessCode === 'string' && existingBusinessCode.trim() !== '';
1214
+ const hasDraftBusinessCode = typeof draftBusinessCode === 'string' && draftBusinessCode.trim() !== '';
1215
+ if (!hasExistingBusinessCode || hasDraftBusinessCode) return draftOrder;
1253
1216
  return {
1254
1217
  ...draftOrder,
1255
1218
  business_code: existingBusinessCode
1256
1219
  };
1257
1220
  }
1258
1221
  getOrderIdentityEntries(order) {
1259
- if (!order)
1260
- return [];
1222
+ if (!order) return [];
1261
1223
  const record = order;
1262
- const candidates = [
1263
- { field: "order_id", value: order.order_id },
1264
- { field: "external_sale_number", value: record.external_sale_number },
1265
- { field: "order_number", value: record.order_number },
1266
- { field: "shop_order_number", value: record.shop_order_number }
1267
- ];
1224
+ const candidates = [{
1225
+ field: 'order_id',
1226
+ value: order.order_id
1227
+ }, {
1228
+ field: 'external_sale_number',
1229
+ value: record.external_sale_number
1230
+ }, {
1231
+ field: 'order_number',
1232
+ value: record.order_number
1233
+ }, {
1234
+ field: 'shop_order_number',
1235
+ value: record.shop_order_number
1236
+ }];
1268
1237
  const entries = [];
1269
1238
  for (const candidate of candidates) {
1270
- if (this.isBlankIdentityValue(candidate.value))
1271
- continue;
1239
+ if (this.isBlankIdentityValue(candidate.value)) continue;
1272
1240
  const key = this.getIdKey(candidate.value);
1273
- if (entries.some((entry) => entry.field === candidate.field && entry.key === key))
1274
- continue;
1275
- entries.push({ field: candidate.field, key });
1241
+ if (entries.some(entry => entry.field === candidate.field && entry.key === key)) continue;
1242
+ entries.push({
1243
+ field: candidate.field,
1244
+ key
1245
+ });
1276
1246
  }
1277
1247
  return entries;
1278
1248
  }
1279
1249
  getOrderIdentityKeys(order) {
1280
1250
  const keys = [];
1281
1251
  for (const entry of this.getOrderIdentityEntries(order)) {
1282
- if (!keys.includes(entry.key))
1283
- keys.push(entry.key);
1252
+ if (!keys.includes(entry.key)) keys.push(entry.key);
1284
1253
  }
1285
1254
  return keys;
1286
1255
  }
1287
1256
  getOrderDateKey(order) {
1288
- var _a, _b, _c, _d;
1289
- const candidates = [
1290
- order == null ? void 0 : order.schedule_date,
1291
- order == null ? void 0 : order.create_date,
1292
- order == null ? void 0 : order.created_at,
1293
- (_b = (_a = order == null ? void 0 : order.bookings) == null ? void 0 : _a[0]) == null ? void 0 : _b.start_date,
1294
- (_d = (_c = order == null ? void 0 : order.bookings) == null ? void 0 : _c[0]) == null ? void 0 : _d.select_date
1295
- ];
1257
+ const candidates = [order?.schedule_date, order?.create_date, order?.created_at, order?.bookings?.[0]?.start_date, order?.bookings?.[0]?.select_date];
1296
1258
  for (const v of candidates) {
1297
- if (!v)
1298
- continue;
1259
+ if (!v) continue;
1299
1260
  const text = String(v);
1300
- if (!text)
1301
- continue;
1302
- return text.split("T")[0].split(" ")[0];
1261
+ if (!text) continue;
1262
+ return text.split('T')[0].split(' ')[0];
1303
1263
  }
1304
- return void 0;
1264
+ return undefined;
1305
1265
  }
1266
+
1306
1267
  /**
1307
1268
  * 初始化 OrderDataSource 实例
1308
1269
  */
1309
1270
  initOrderDataSource() {
1310
- var _a, _b;
1311
- const OrderDataSourceClass = (_b = (_a = this.core.serverOptions) == null ? void 0 : _a.All_DATA_SOURCES) == null ? void 0 : _b.OrderDataSource;
1312
- if (!OrderDataSourceClass)
1313
- return;
1271
+ const OrderDataSourceClass = this.core.serverOptions?.All_DATA_SOURCES?.OrderDataSource;
1272
+ if (!OrderDataSourceClass) return;
1314
1273
  this.orderDataSource = new OrderDataSourceClass();
1315
1274
  }
1275
+
1316
1276
  /**
1317
1277
  * 初始化 pubsub 订阅,监听订单变更(纯订阅,不拉数据;全量 SSE 由 loadOrdersByServer 负责)
1318
1278
  */
1319
1279
  setupOrderSync() {
1320
- if (!this.orderDataSource)
1321
- return;
1280
+ if (!this.orderDataSource) return;
1322
1281
  this.orderDataSource.run({
1323
1282
  pubsub: {
1324
- callback: (res) => {
1325
- console.log("orderDataSource", res);
1283
+ callback: res => {
1326
1284
  const pubsubReceivedAt = Date.now();
1327
1285
  const message = this.normalizeOrderSyncMessage(res);
1328
- if (!message)
1329
- return;
1286
+ if (!message) return;
1330
1287
  message._pubsubReceivedAt = pubsubReceivedAt;
1331
1288
  this.pendingSyncMessages.push(message);
1332
1289
  const throttleMs = this.getOrderSyncThrottleMs();
1333
1290
  const routeInfo = this.resolveSyncMessageRoute(message);
1334
- this.logInfo("orderSync-收到消息并入队", {
1291
+ this.logInfo('orderSync-收到消息并入队', {
1335
1292
  id: message.id ?? null,
1336
1293
  order_id: message.order_id ?? null,
1337
1294
  type: message.type ?? null,
@@ -1344,8 +1301,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1344
1301
  }
1345
1302
  }
1346
1303
  }).catch(() => {
1304
+ // 忽略同步初始化异常,避免影响主流程
1347
1305
  });
1348
1306
  }
1307
+
1349
1308
  /**
1350
1309
  * 调度订单同步节流窗口(leading-edge throttle):
1351
1310
  * - 空闲状态下收到的第一条消息立即触发批处理,无需等待;
@@ -1353,29 +1312,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1353
1312
  * - 若当前批处理执行中,则由批处理结束后决定是否开启下一轮窗口。
1354
1313
  */
1355
1314
  scheduleOrderSyncThrottle() {
1356
- if (this.isProcessingSyncBatch)
1357
- return;
1315
+ if (this.isProcessingSyncBatch) return;
1358
1316
  if (this.isIdlePhase) {
1359
1317
  this.isIdlePhase = false;
1360
- this.logInfo("orderSync-首条消息立即触发处理");
1318
+ this.logInfo('orderSync-首条消息立即触发处理');
1361
1319
  void this.flushOrderSyncMessagesByThrottle();
1362
1320
  return;
1363
1321
  }
1364
- if (this.syncTimer)
1365
- return;
1322
+ if (this.syncTimer) return;
1366
1323
  const throttleMs = this.getOrderSyncThrottleMs();
1367
1324
  this.syncTimer = setTimeout(() => {
1368
- this.syncTimer = void 0;
1325
+ this.syncTimer = undefined;
1369
1326
  void this.flushOrderSyncMessagesByThrottle();
1370
1327
  }, throttleMs);
1371
1328
  }
1329
+
1372
1330
  /**
1373
1331
  * 执行一次节流批处理并在需要时续约下一轮窗口。
1374
1332
  * 批处理完成且无后续消息时恢复空闲状态,下一条消息将立即触发。
1375
1333
  */
1376
1334
  async flushOrderSyncMessagesByThrottle() {
1377
- if (this.isProcessingSyncBatch)
1378
- return;
1335
+ if (this.isProcessingSyncBatch) return;
1379
1336
  if (this.pendingSyncMessages.length === 0) {
1380
1337
  this.isIdlePhase = true;
1381
1338
  return;
@@ -1392,6 +1349,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1392
1349
  }
1393
1350
  }
1394
1351
  }
1352
+
1395
1353
  /**
1396
1354
  * 处理节流窗口内聚合后的同步消息批次
1397
1355
  *
@@ -1406,19 +1364,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1406
1364
  async processOrderSyncMessages() {
1407
1365
  const messages = [...this.pendingSyncMessages];
1408
1366
  this.pendingSyncMessages = [];
1409
- if (messages.length === 0)
1410
- return;
1367
+ if (messages.length === 0) return;
1411
1368
  const batchProcessStartAt = Date.now();
1412
- const earliestReceivedAt = Math.min(
1413
- ...messages.map((m) => m._pubsubReceivedAt ?? batchProcessStartAt)
1414
- );
1415
- this.logInfo("processOrderSyncMessages-开始", {
1369
+ const earliestReceivedAt = Math.min(...messages.map(m => m._pubsubReceivedAt ?? batchProcessStartAt));
1370
+ this.logInfo('processOrderSyncMessages-开始', {
1416
1371
  messageCount: messages.length,
1417
1372
  earliestReceivedAt: new Date(earliestReceivedAt).toISOString(),
1418
1373
  batchProcessStartAt: new Date(batchProcessStartAt).toISOString(),
1419
1374
  waitDurationMs: batchProcessStartAt - earliestReceivedAt
1420
1375
  });
1421
- const upsertOrders = /* @__PURE__ */ new Map();
1376
+ const upsertOrders = new Map();
1422
1377
  const refreshIds = [];
1423
1378
  messages.forEach((msg, msgIndex) => {
1424
1379
  const routeInfo = this.resolveSyncMessageRoute(msg);
@@ -1426,50 +1381,47 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1426
1381
  const singleId = routeInfo.singleId;
1427
1382
  const hasSingleId = routeInfo.hasSingleId;
1428
1383
  const normalizedBody = this.normalizeOrderSyncPayload(msg.body || msg.data);
1429
- if (routeInfo.route === "bodyUpsert" && normalizedBody) {
1384
+ if (routeInfo.route === 'bodyUpsert' && normalizedBody) {
1430
1385
  upsertOrders.set(this.getIdKey(normalizedBody.order_id), normalizedBody);
1431
1386
  return;
1432
1387
  }
1433
- if (hasBatchIds)
1434
- refreshIds.push(...routeInfo.batchIds);
1435
- else if (routeInfo.route === "httpRefresh.singleId" && singleId !== null)
1436
- refreshIds.push(singleId);
1437
- else if (routeInfo.route === "httpRefresh.relationIds")
1438
- refreshIds.push(...routeInfo.batchIds);
1388
+ if (hasBatchIds) refreshIds.push(...routeInfo.batchIds);else if (routeInfo.route === 'httpRefresh.singleId' && singleId !== null) refreshIds.push(singleId);else if (routeInfo.route === 'httpRefresh.relationIds') refreshIds.push(...routeInfo.batchIds);
1439
1389
  });
1440
1390
  const uniqueRefreshIds = this.uniqueOrderIds(refreshIds);
1441
1391
  const upsertList = [...upsertOrders.values()];
1442
- this.logInfo("processOrderSyncMessages-去重完成", {
1392
+ this.logInfo('processOrderSyncMessages-去重完成', {
1443
1393
  upsertCount: upsertList.length,
1444
1394
  refreshIdCount: uniqueRefreshIds.length
1445
1395
  });
1446
1396
  if (upsertList.length > 0) {
1447
- await this.mergeOrdersToStore(upsertList, "pubsub.bodyUpsert");
1397
+ await this.mergeOrdersToStore(upsertList, 'pubsub.bodyUpsert');
1448
1398
  }
1449
1399
  if (uniqueRefreshIds.length > 0) {
1450
- const { toFetch, skipped } = this.filterRedundantHttpRefreshIds(uniqueRefreshIds);
1451
- if (skipped.length > 0) {
1452
- }
1400
+ const {
1401
+ toFetch,
1402
+ skipped
1403
+ } = this.filterRedundantHttpRefreshIds(uniqueRefreshIds);
1404
+ if (skipped.length > 0) {}
1453
1405
  if (toFetch.length > 0) {
1454
1406
  const freshOrders = await this.fetchOrdersByHttp(toFetch);
1455
1407
  if (freshOrders.length > 0) {
1456
- await this.mergeOrdersToStore(freshOrders, "pubsub.httpRefresh");
1457
- } else {
1458
- }
1408
+ await this.mergeOrdersToStore(freshOrders, 'pubsub.httpRefresh');
1409
+ } else {}
1459
1410
  }
1460
1411
  }
1461
1412
  if (upsertList.length === 0 && uniqueRefreshIds.length === 0) {
1462
1413
  return;
1463
1414
  }
1464
1415
  const batchProcessEndAt = Date.now();
1465
- this.logInfo("processOrderSyncMessages-结束", {
1416
+ this.logInfo('processOrderSyncMessages-结束', {
1466
1417
  upsertCount: upsertList.length,
1467
1418
  refreshIdCount: uniqueRefreshIds.length,
1468
1419
  batchProcessDurationMs: batchProcessEndAt - batchProcessStartAt,
1469
1420
  totalFromPubsubToProcessedMs: batchProcessEndAt - earliestReceivedAt
1470
1421
  });
1471
- await this.core.effects.emit(import_types.OrderHooks.onOrdersSyncCompleted, null);
1422
+ await this.core.effects.emit(_types.OrderHooks.onOrdersSyncCompleted, null);
1472
1423
  }
1424
+
1473
1425
  /**
1474
1426
  * 通过 HTTP 按 ids 批量拉取订单详情(走 orderDataSource)。
1475
1427
  *
@@ -1481,16 +1433,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1481
1433
  * const fresh = await orderModule.fetchOrdersByHttp(['96971', '96972'])
1482
1434
  */
1483
1435
  async fetchOrdersByHttp(ids) {
1484
- if (!this.orderDataSource || ids.length === 0)
1485
- return [];
1436
+ if (!this.orderDataSource || ids.length === 0) return [];
1486
1437
  try {
1487
- if (typeof this.orderDataSource.fetchOrdersByIds === "function") {
1488
- const orderList2 = await this.orderDataSource.fetchOrdersByIds(ids);
1489
- return orderList2 || [];
1438
+ if (typeof this.orderDataSource.fetchOrdersByIds === 'function') {
1439
+ const orderList = await this.orderDataSource.fetchOrdersByIds(ids);
1440
+ return orderList || [];
1490
1441
  }
1491
1442
  const orderList = await this.orderDataSource.run({
1492
1443
  http: {
1493
- query: { ids }
1444
+ query: {
1445
+ ids
1446
+ }
1494
1447
  }
1495
1448
  });
1496
1449
  return orderList || [];
@@ -1498,70 +1451,63 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1498
1451
  return [];
1499
1452
  }
1500
1453
  }
1454
+
1501
1455
  /**
1502
1456
  * 将增量订单合并到 store
1503
1457
  */
1504
1458
  async mergeOrdersToStore(freshOrders, source) {
1505
1459
  const storeOrderCountBefore = this.store.list.length;
1506
- this.logInfo("mergeOrdersToStore-开始", {
1460
+ this.logInfo('mergeOrdersToStore-开始', {
1507
1461
  freshOrderCount: freshOrders.length,
1508
1462
  storeOrderCountBefore,
1509
1463
  source
1510
1464
  });
1511
1465
  this.logDuplicateOrders(`${source}.beforeMerge`, this.store.list);
1512
1466
  const normalizedFreshOrders = [];
1513
- const incomingProductsHaveStableIdentity = /* @__PURE__ */ new Map();
1467
+ const incomingProductsHaveStableIdentity = new Map();
1514
1468
  for (const order of freshOrders) {
1515
- const id = order == null ? void 0 : order.order_id;
1516
- if (id === void 0 || id === null)
1517
- continue;
1469
+ const id = order?.order_id;
1470
+ if (id === undefined || id === null) continue;
1518
1471
  const rawProducts = order.products;
1519
1472
  if (Array.isArray(rawProducts)) {
1520
1473
  const allProductsHaveStableIdentity = this.doProductsHaveStableMembershipIdentity(rawProducts);
1521
1474
  const orderIdKey = this.getIdKey(id);
1522
- incomingProductsHaveStableIdentity.set(
1523
- orderIdKey,
1524
- (incomingProductsHaveStableIdentity.get(orderIdKey) ?? true) && allProductsHaveStableIdentity
1525
- );
1475
+ incomingProductsHaveStableIdentity.set(orderIdKey, (incomingProductsHaveStableIdentity.get(orderIdKey) ?? true) && allProductsHaveStableIdentity);
1526
1476
  }
1527
1477
  normalizedFreshOrders.push(this.normalizeRemoteSyncedOrder(order));
1528
1478
  }
1529
- const uniqueFreshOrders = this.compactOrderListByIdentity(
1530
- normalizedFreshOrders,
1531
- `${source}.incoming`
1532
- ).list;
1479
+ // 先对本批新单做去重(批内规模 m 很小),保证每条 fresh 身份唯一
1480
+ const uniqueFreshOrders = this.compactOrderListByIdentity(normalizedFreshOrders, `${source}.incoming`).list;
1533
1481
  const uniqueFreshCount = uniqueFreshOrders.length;
1534
1482
  const patchedOrders = [];
1535
1483
  const remoteProductMembershipChanges = [];
1536
- const forceWriteStorageKeys = /* @__PURE__ */ new Set();
1484
+ const forceWriteStorageKeys = new Set();
1537
1485
  const storageKeyMigrations = [];
1538
1486
  const mergeActions = {};
1539
- const existingProductsHaveStableIdentity = this.store.list.map(
1540
- (order) => this.doProductsHaveStableMembershipIdentity(
1541
- order.products
1542
- )
1543
- );
1544
- const updatedList = this.store.list.map(
1545
- (order) => this.normalizeOrderForMemoryList(order, `${source}.existingMemory`)
1546
- );
1547
- const identityKeyToIndex = /* @__PURE__ */ new Map();
1487
+ const existingProductsHaveStableIdentity = this.store.list.map(order => this.doProductsHaveStableMembershipIdentity(order.products));
1488
+ const updatedList = this.store.list.map(order => this.normalizeOrderForMemoryList(order, `${source}.existingMemory`));
1489
+
1490
+ // 基于身份键(field:value)建立索引,把「查找已存在订单」从 O(n) 线性扫描降为 O(1),
1491
+ // 整体合并复杂度由 O(n^2) 降为 O(n + m)。索引语义与 doOrdersShareIdentity 完全一致:
1492
+ // 任一身份字段(order_id/external_sale_number/order_number/shop_order_number)同值即同一单。
1493
+ const identityKeyToIndex = new Map();
1548
1494
  for (let index = 0; index < updatedList.length; index += 1) {
1549
1495
  const identityKeys = this.getOrderIdentityMatchKeys(updatedList[index]);
1550
1496
  for (const key of identityKeys) {
1551
- if (!identityKeyToIndex.has(key))
1552
- identityKeyToIndex.set(key, index);
1497
+ // 同一 key 命中多张时保留最靠前的下标,与原 findIndex「取首个匹配」一致
1498
+ if (!identityKeyToIndex.has(key)) identityKeyToIndex.set(key, index);
1553
1499
  }
1554
1500
  }
1555
1501
  for (const fresh of uniqueFreshOrders) {
1556
1502
  const freshIdentityKeys = this.getOrderIdentityMatchKeys(fresh);
1557
1503
  const matchIndex = this.lookupOrderIndexByIdentityKeys(identityKeyToIndex, freshIdentityKeys);
1558
1504
  const storageKey = this.getOrderStorageKey(fresh);
1559
- const mergeKey = storageKey || (fresh.order_id !== void 0 && fresh.order_id !== null ? this.getIdKey(fresh.order_id) : "");
1505
+ const mergeKey = storageKey || (fresh.order_id !== undefined && fresh.order_id !== null ? this.getIdKey(fresh.order_id) : '');
1560
1506
  if (matchIndex >= 0) {
1561
1507
  const existingOrder = updatedList[matchIndex];
1562
1508
  const previousStorageKey = this.getPersistedOrderStorageKey(existingOrder);
1563
1509
  if (this.isPendingSyncOrder(existingOrder) && this.isRemoteEchoMergeSource(source)) {
1564
- this.logInfo("mergeOrdersToStore-跳过 pending 订单远端覆盖", {
1510
+ this.logInfo('mergeOrdersToStore-跳过 pending 订单远端覆盖', {
1565
1511
  source,
1566
1512
  order_id: existingOrder.order_id ?? fresh.order_id ?? null,
1567
1513
  external_sale_number: existingOrder.external_sale_number ?? fresh.external_sale_number ?? null,
@@ -1569,39 +1515,34 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1569
1515
  remote_payment_status: fresh.payment_status ?? null,
1570
1516
  local_need_sync: existingOrder.need_sync ?? null,
1571
1517
  remote_need_sync: fresh.need_sync ?? null,
1572
- reason: "protect_pending_sync_order_from_remote_echo"
1518
+ reason: 'protect_pending_sync_order_from_remote_echo'
1573
1519
  });
1574
1520
  continue;
1575
1521
  }
1576
1522
  if (this.isDraftOrder(existingOrder) && this.shouldProtectDraftOrderFromIncoming(source)) {
1577
- this.logInfo("mergeOrdersToStore-跳过 draft 订单远端覆盖", {
1523
+ this.logInfo('mergeOrdersToStore-跳过 draft 订单远端覆盖', {
1578
1524
  source,
1579
1525
  order_id: existingOrder.order_id ?? fresh.order_id ?? null,
1580
1526
  external_sale_number: existingOrder.external_sale_number ?? fresh.external_sale_number ?? null,
1581
1527
  local_is_draft_order: existingOrder.is_draft_order ?? null,
1582
1528
  remote_is_draft_order: fresh.is_draft_order ?? null,
1583
- reason: "protect_draft_order_from_remote_echo"
1529
+ reason: 'protect_draft_order_from_remote_echo'
1584
1530
  });
1585
1531
  continue;
1586
1532
  }
1587
1533
  let mergedOrder = this.mergeOrderRecords(existingOrder, fresh);
1588
1534
  const freshOrderId = fresh.order_id;
1589
- const incomingProductsAreStable = freshOrderId !== void 0 && freshOrderId !== null && incomingProductsHaveStableIdentity.get(this.getIdKey(freshOrderId)) !== false;
1535
+ const incomingProductsAreStable = freshOrderId !== undefined && freshOrderId !== null && incomingProductsHaveStableIdentity.get(this.getIdKey(freshOrderId)) !== false;
1590
1536
  let membershipChange = null;
1591
- if (Array.isArray(fresh.products) && freshOrderId !== void 0 && freshOrderId !== null && existingProductsHaveStableIdentity[matchIndex] !== false && incomingProductsAreStable) {
1592
- membershipChange = this.getRemoteProductMembershipChange(
1593
- existingOrder,
1594
- mergedOrder,
1595
- source
1596
- );
1537
+ if (Array.isArray(fresh.products) && freshOrderId !== undefined && freshOrderId !== null && existingProductsHaveStableIdentity[matchIndex] !== false && incomingProductsAreStable) {
1538
+ membershipChange = this.getRemoteProductMembershipChange(existingOrder, mergedOrder, source);
1597
1539
  }
1598
1540
  let mergedProductsHaveStableIdentity = existingProductsHaveStableIdentity[matchIndex] !== false && incomingProductsAreStable;
1599
1541
  let adjustedMatchIndex = matchIndex;
1600
- const duplicateIndexes = /* @__PURE__ */ new Set();
1542
+ const duplicateIndexes = new Set();
1601
1543
  for (const key of freshIdentityKeys) {
1602
1544
  const duplicateIndex = identityKeyToIndex.get(key);
1603
- if (duplicateIndex === void 0 || duplicateIndex === matchIndex)
1604
- continue;
1545
+ if (duplicateIndex === undefined || duplicateIndex === matchIndex) continue;
1605
1546
  duplicateIndexes.add(duplicateIndex);
1606
1547
  }
1607
1548
  if (duplicateIndexes.size > 0) {
@@ -1610,14 +1551,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1610
1551
  mergedProductsHaveStableIdentity = mergedProductsHaveStableIdentity && existingProductsHaveStableIdentity[duplicateIndex] !== false;
1611
1552
  updatedList.splice(duplicateIndex, 1);
1612
1553
  existingProductsHaveStableIdentity.splice(duplicateIndex, 1);
1613
- if (duplicateIndex < adjustedMatchIndex)
1614
- adjustedMatchIndex -= 1;
1554
+ if (duplicateIndex < adjustedMatchIndex) adjustedMatchIndex -= 1;
1615
1555
  }
1616
1556
  identityKeyToIndex.clear();
1617
1557
  for (let index = 0; index < updatedList.length; index += 1) {
1618
1558
  for (const key of this.getOrderIdentityMatchKeys(updatedList[index])) {
1619
- if (!identityKeyToIndex.has(key))
1620
- identityKeyToIndex.set(key, index);
1559
+ if (!identityKeyToIndex.has(key)) identityKeyToIndex.set(key, index);
1621
1560
  }
1622
1561
  }
1623
1562
  }
@@ -1634,42 +1573,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1634
1573
  if (membershipChange) {
1635
1574
  remoteProductMembershipChanges.push(membershipChange);
1636
1575
  const mergedStorageKey = this.getOrderStorageKey(mergedOrder);
1637
- if (mergedStorageKey)
1638
- forceWriteStorageKeys.add(mergedStorageKey);
1576
+ if (mergedStorageKey) forceWriteStorageKeys.add(mergedStorageKey);
1639
1577
  }
1578
+ // 合并后身份字段可能新增(如挂单拿到 order_id),同步登记到索引,
1579
+ // 供同批后续 fresh 命中同一槽位,避免重复插入
1640
1580
  this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, adjustedMatchIndex);
1641
1581
  patchedOrders.push(mergedOrder);
1642
- if (mergeKey)
1643
- mergeActions[mergeKey] = "update";
1582
+ if (mergeKey) mergeActions[mergeKey] = 'update';
1644
1583
  continue;
1645
1584
  }
1646
1585
  const insertIndex = updatedList.length;
1647
1586
  updatedList.push(fresh);
1648
- existingProductsHaveStableIdentity.push(
1649
- fresh.order_id !== void 0 && fresh.order_id !== null && incomingProductsHaveStableIdentity.get(this.getIdKey(fresh.order_id)) !== false
1650
- );
1587
+ existingProductsHaveStableIdentity.push(fresh.order_id !== undefined && fresh.order_id !== null && incomingProductsHaveStableIdentity.get(this.getIdKey(fresh.order_id)) !== false);
1651
1588
  this.registerOrderIdentityKeys(identityKeyToIndex, fresh, insertIndex);
1652
1589
  patchedOrders.push(fresh);
1653
- if (mergeKey)
1654
- mergeActions[mergeKey] = "insert";
1590
+ if (mergeKey) mergeActions[mergeKey] = 'insert';
1655
1591
  }
1656
- const insertCount = Object.values(mergeActions).filter((v) => v === "insert").length;
1657
- const updateCount = Object.values(mergeActions).filter((v) => v === "update").length;
1658
- this.logInfo("mergeOrdersToStore-合并完成", {
1592
+ const insertCount = Object.values(mergeActions).filter(v => v === 'insert').length;
1593
+ const updateCount = Object.values(mergeActions).filter(v => v === 'update').length;
1594
+ this.logInfo('mergeOrdersToStore-合并完成', {
1659
1595
  insertCount,
1660
1596
  updateCount,
1661
1597
  storeOrderCountAfter: this.store.list.length
1662
1598
  });
1599
+ // 增量索引已保证 store 去重不变量,无需再对全表做 O(n^2) 压缩;
1600
+ // 仅在自检开关开启时做一次兜底校验。
1663
1601
  this.store.list = this.runOrderStoreSelfCheck(updatedList, `${source}.store`);
1664
1602
  this.syncOrdersMap();
1665
- await this.patchOrdersInSQLite(
1666
- patchedOrders,
1667
- source,
1668
- mergeActions,
1669
- { storageKeyMigrations },
1670
- forceWriteStorageKeys
1671
- );
1672
- this.logInfo("mergeOrdersToStore-结束", {
1603
+ await this.patchOrdersInSQLite(patchedOrders, source, mergeActions, {
1604
+ storageKeyMigrations
1605
+ }, forceWriteStorageKeys);
1606
+ this.logInfo('mergeOrdersToStore-结束', {
1673
1607
  uniqueFreshCount,
1674
1608
  storeOrderCountAfter: this.store.list.length,
1675
1609
  insertCount,
@@ -1678,6 +1612,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1678
1612
  await this.emitRemoteProductMembershipChanges(remoteProductMembershipChanges);
1679
1613
  await this.emitOrdersChanged(patchedOrders, source);
1680
1614
  }
1615
+
1681
1616
  /**
1682
1617
  * 在身份索引中查找与目标订单共享任一身份键的已存在订单下标。
1683
1618
  * 返回所有命中键里最小的下标,等价于原 findOrderIndexByIdentity 的「取首个匹配」语义。
@@ -1689,76 +1624,64 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1689
1624
  let matchIndex = -1;
1690
1625
  for (const key of identityKeys) {
1691
1626
  const index = identityKeyToIndex.get(key);
1692
- if (index === void 0)
1693
- continue;
1694
- if (matchIndex < 0 || index < matchIndex)
1695
- matchIndex = index;
1627
+ if (index === undefined) continue;
1628
+ if (matchIndex < 0 || index < matchIndex) matchIndex = index;
1696
1629
  }
1697
1630
  return matchIndex;
1698
1631
  }
1699
1632
  isRemoteEchoMergeSource(source) {
1700
- return source === "pubsub.bodyUpsert" || source === "pubsub.httpRefresh";
1633
+ return source === 'pubsub.bodyUpsert' || source === 'pubsub.httpRefresh';
1701
1634
  }
1702
1635
  isRemoteProductMembershipChangeSource(source) {
1703
- return this.isRemoteEchoMergeSource(source) || source === "manual.editOpenRemoteCheck";
1636
+ return this.isRemoteEchoMergeSource(source) || source === 'manual.editOpenRemoteCheck';
1704
1637
  }
1705
1638
  getProductMembershipKey(product) {
1706
- const persistentId = (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("product", product);
1707
- if (persistentId)
1708
- return `order_detail_id:${persistentId}`;
1709
- const uid = (0, import_orderCollectionIdentity.getOrderCollectionUid)("product", product);
1710
- return uid ? `unique_identification_number:${uid}` : "";
1639
+ const persistentId = (0, _orderCollectionIdentity.getOrderCollectionPersistentId)('product', product);
1640
+ if (persistentId) return `order_detail_id:${persistentId}`;
1641
+ const uid = (0, _orderCollectionIdentity.getOrderCollectionUid)('product', product);
1642
+ return uid ? `unique_identification_number:${uid}` : '';
1711
1643
  }
1712
1644
  doProductsHaveStableMembershipIdentity(products) {
1713
- if (!Array.isArray(products))
1714
- return true;
1715
- return products.every(
1716
- (product) => Boolean(
1717
- (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("product", product) || (0, import_orderCollectionIdentity.getOrderCollectionUid)("product", product)
1718
- )
1719
- );
1645
+ if (!Array.isArray(products)) return true;
1646
+ return products.every(product => Boolean((0, _orderCollectionIdentity.getOrderCollectionPersistentId)('product', product) || (0, _orderCollectionIdentity.getOrderCollectionUid)('product', product)));
1720
1647
  }
1648
+
1721
1649
  /**
1722
1650
  * 冲突提示关注逻辑商品行,而不是服务端 checkout 过程中可能被重建的 detail 记录。
1723
1651
  * 通用集合合并仍以 order_detail_id 为事实主键;这里只允许相同稳定 UID 跨 detail id 对齐,
1724
1652
  * 避免本机 checkout 回声被误判成“一删一增”。
1725
1653
  */
1726
1654
  isSameProductMembershipItem(left, right) {
1727
- if ((0, import_orderCollectionIdentity.isSameOrderCollectionItem)("product", left, right))
1728
- return true;
1729
- const leftUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)("product", left);
1730
- const rightUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)("product", right);
1655
+ if ((0, _orderCollectionIdentity.isSameOrderCollectionItem)('product', left, right)) return true;
1656
+ const leftUid = (0, _orderCollectionIdentity.getOrderCollectionUid)('product', left);
1657
+ const rightUid = (0, _orderCollectionIdentity.getOrderCollectionUid)('product', right);
1731
1658
  return Boolean(leftUid && rightUid && leftUid === rightUid);
1732
1659
  }
1660
+
1733
1661
  /**
1734
1662
  * 对比合并前后的商品成员集合。商品字段修改与数组重排不会产生 diff。
1735
1663
  */
1736
1664
  getRemoteProductMembershipChange(existingOrder, mergedOrder, source) {
1737
- if (!this.isRemoteProductMembershipChangeSource(source))
1738
- return null;
1665
+ if (!this.isRemoteProductMembershipChangeSource(source)) return null;
1739
1666
  const previousProducts = Array.isArray(existingOrder.products) ? existingOrder.products : [];
1740
1667
  const currentProducts = Array.isArray(mergedOrder.products) ? mergedOrder.products : [];
1741
1668
  const unmatchedCurrentIndexes = new Set(currentProducts.map((_, index) => index));
1742
1669
  const removedProductKeys = [];
1743
1670
  for (const previousProduct of previousProducts) {
1744
- const matchedIndex = currentProducts.findIndex(
1745
- (currentProduct, index) => unmatchedCurrentIndexes.has(index) && this.isSameProductMembershipItem(previousProduct, currentProduct)
1746
- );
1671
+ const matchedIndex = currentProducts.findIndex((currentProduct, index) => unmatchedCurrentIndexes.has(index) && this.isSameProductMembershipItem(previousProduct, currentProduct));
1747
1672
  if (matchedIndex >= 0) {
1748
1673
  unmatchedCurrentIndexes.delete(matchedIndex);
1749
1674
  continue;
1750
1675
  }
1751
1676
  const productKey = this.getProductMembershipKey(previousProduct);
1752
- if (productKey)
1753
- removedProductKeys.push(productKey);
1677
+ if (productKey) removedProductKeys.push(productKey);
1754
1678
  }
1755
- const addedProductKeys = [...unmatchedCurrentIndexes].map((index) => this.getProductMembershipKey(currentProducts[index])).filter(Boolean);
1679
+ const addedProductKeys = [...unmatchedCurrentIndexes].map(index => this.getProductMembershipKey(currentProducts[index])).filter(Boolean);
1756
1680
  if (addedProductKeys.length === 0 && removedProductKeys.length === 0) {
1757
1681
  return null;
1758
1682
  }
1759
1683
  const orderId = mergedOrder.order_id ?? existingOrder.order_id;
1760
- if (orderId === void 0 || orderId === null)
1761
- return null;
1684
+ if (orderId === undefined || orderId === null) return null;
1762
1685
  return {
1763
1686
  order_id: orderId,
1764
1687
  source,
@@ -1768,6 +1691,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1768
1691
  current_product_count: currentProducts.length
1769
1692
  };
1770
1693
  }
1694
+
1771
1695
  /**
1772
1696
  * 将订单的全部身份键登记到索引并指向其在列表中的下标。
1773
1697
  * 合并后订单新增的身份字段(如挂单同步后拿到 order_id)也会被登记。
@@ -1781,54 +1705,53 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1781
1705
  identityKeyToIndex.set(key, index);
1782
1706
  }
1783
1707
  }
1708
+
1784
1709
  /**
1785
1710
  * 合并热路径去重兜底:默认直接返回原列表(增量索引已保证无重复)。
1786
1711
  * 仅当 ORDER_MERGE_SELF_CHECK 开启时,额外做一次全表压缩并在发现残留重复时告警。
1787
1712
  */
1788
1713
  runOrderStoreSelfCheck(orders, source) {
1789
- if (!ORDER_MERGE_SELF_CHECK)
1790
- return orders;
1791
- const { list, removedCount } = this.compactOrderListByIdentity(orders, source);
1714
+ if (!ORDER_MERGE_SELF_CHECK) return orders;
1715
+ const {
1716
+ list,
1717
+ removedCount
1718
+ } = this.compactOrderListByIdentity(orders, source);
1792
1719
  if (removedCount > 0) {
1793
- this.logWarning("合并自检发现残留重复订单,已压缩", { source, removedCount });
1720
+ this.logWarning('合并自检发现残留重复订单,已压缩', {
1721
+ source,
1722
+ removedCount
1723
+ });
1794
1724
  }
1795
1725
  return list;
1796
1726
  }
1797
1727
  normalizeOrderSyncMessage(res) {
1798
- const data = (res == null ? void 0 : res.data) || res;
1799
- if (!data)
1800
- return null;
1801
- const payload = (data == null ? void 0 : data.data) && typeof data.data === "object" ? data.data : void 0;
1728
+ const data = res?.data || res;
1729
+ if (!data) return null;
1730
+ const payload = data?.data && typeof data.data === 'object' ? data.data : undefined;
1802
1731
  const normalized = {
1803
1732
  ...data,
1804
- _channelKey: data.module || "sales_sync"
1733
+ _channelKey: data.module || 'sales_sync'
1805
1734
  };
1806
- if (!normalized.type && typeof data.event === "string")
1807
- normalized.type = data.event;
1808
- if (!normalized.id && data.id !== void 0)
1809
- normalized.id = data.id;
1810
- if (!normalized.id && data.order_id !== void 0)
1811
- normalized.id = data.order_id;
1812
- if (!normalized.order_id && data.order_id !== void 0)
1813
- normalized.order_id = data.order_id;
1814
- if (!normalized.order_id && (payload == null ? void 0 : payload.order_id) !== void 0)
1815
- normalized.order_id = payload.order_id;
1816
- if (!normalized.body && (payload == null ? void 0 : payload.order_id) !== void 0)
1817
- normalized.body = payload;
1818
- if (!normalized.data && (payload == null ? void 0 : payload.order_id) !== void 0)
1819
- normalized.data = payload;
1735
+ if (!normalized.type && typeof data.event === 'string') normalized.type = data.event;
1736
+ if (!normalized.id && data.id !== undefined) normalized.id = data.id;
1737
+ if (!normalized.id && data.order_id !== undefined) normalized.id = data.order_id;
1738
+ if (!normalized.order_id && data.order_id !== undefined) normalized.order_id = data.order_id;
1739
+ if (!normalized.order_id && payload?.order_id !== undefined) normalized.order_id = payload.order_id;
1740
+ if (!normalized.body && payload?.order_id !== undefined) normalized.body = payload;
1741
+ if (!normalized.data && payload?.order_id !== undefined) normalized.data = payload;
1820
1742
  return normalized;
1821
1743
  }
1822
1744
  normalizeOrderSyncPayload(payload) {
1823
- if (!payload)
1824
- return null;
1745
+ if (!payload) return null;
1825
1746
  const orderId = payload.order_id;
1826
- if (orderId === void 0 || orderId === null)
1827
- return null;
1828
- return { ...payload, order_id: orderId };
1747
+ if (orderId === undefined || orderId === null) return null;
1748
+ return {
1749
+ ...payload,
1750
+ order_id: orderId
1751
+ };
1829
1752
  }
1830
1753
  uniqueOrderIds(ids) {
1831
- const idMap = /* @__PURE__ */ new Map();
1754
+ const idMap = new Map();
1832
1755
  for (const id of ids) {
1833
1756
  idMap.set(this.getIdKey(id), id);
1834
1757
  }
@@ -1838,21 +1761,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1838
1761
  return String(id);
1839
1762
  }
1840
1763
  isOrderLookupMatch(order, lookupKey) {
1841
- if (!order || !lookupKey)
1842
- return false;
1843
- const candidates = [
1844
- order.order_id,
1845
- order.external_sale_number,
1846
- order.order_number,
1847
- order.shop_order_number,
1848
- order.shop_full_order_number
1849
- ];
1850
- return candidates.some((value) => {
1851
- if (value === void 0 || value === null || value === "")
1852
- return false;
1764
+ if (!order || !lookupKey) return false;
1765
+ const candidates = [order.order_id, order.external_sale_number, order.order_number, order.shop_order_number, order.shop_full_order_number];
1766
+ return candidates.some(value => {
1767
+ if (value === undefined || value === null || value === '') return false;
1853
1768
  return this.getIdKey(value) === lookupKey;
1854
1769
  });
1855
1770
  }
1771
+
1856
1772
  /**
1857
1773
  * 解析订单 SQLite 主键,规则与宿主 OrderDataSource.getOrderStorageKey 一致。
1858
1774
  *
@@ -1861,114 +1777,94 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1861
1777
  * // => 'S-1001'
1862
1778
  */
1863
1779
  getOrderStorageKey(order) {
1864
- const externalSaleNumber = order == null ? void 0 : order.external_sale_number;
1865
- if (externalSaleNumber !== void 0 && externalSaleNumber !== null && externalSaleNumber !== "") {
1780
+ const externalSaleNumber = order?.external_sale_number;
1781
+ if (externalSaleNumber !== undefined && externalSaleNumber !== null && externalSaleNumber !== '') {
1866
1782
  return String(externalSaleNumber);
1867
1783
  }
1868
- const orderId = order == null ? void 0 : order.order_id;
1869
- if (orderId !== void 0 && orderId !== null && orderId !== "") {
1784
+ const orderId = order?.order_id;
1785
+ if (orderId !== undefined && orderId !== null && orderId !== '') {
1870
1786
  return String(orderId);
1871
1787
  }
1872
- return "";
1788
+ return '';
1873
1789
  }
1874
1790
  getPersistedOrderStorageKey(order) {
1875
- const persistedStorageKey = order == null ? void 0 : order[ORDER_STORAGE_KEY_FIELD];
1876
- if (persistedStorageKey !== void 0 && persistedStorageKey !== null && persistedStorageKey !== "") {
1791
+ const persistedStorageKey = order?.[ORDER_STORAGE_KEY_FIELD];
1792
+ if (persistedStorageKey !== undefined && persistedStorageKey !== null && persistedStorageKey !== '') {
1877
1793
  return String(persistedStorageKey);
1878
1794
  }
1879
1795
  return this.getOrderStorageKey(order);
1880
1796
  }
1881
1797
  getOrderIdentityMatchKeys(order) {
1882
- return this.getOrderIdentityEntries(order).map((entry) => `${entry.field}:${entry.key}`);
1798
+ return this.getOrderIdentityEntries(order).map(entry => `${entry.field}:${entry.key}`);
1883
1799
  }
1884
1800
  doOrdersShareIdentity(left, right) {
1885
1801
  const leftKeys = new Set(this.getOrderIdentityMatchKeys(left));
1886
- if (leftKeys.size === 0)
1887
- return false;
1888
- return this.getOrderIdentityMatchKeys(right).some((key) => leftKeys.has(key));
1802
+ if (leftKeys.size === 0) return false;
1803
+ return this.getOrderIdentityMatchKeys(right).some(key => leftKeys.has(key));
1889
1804
  }
1890
1805
  findOrderIndexByIdentity(orders, target) {
1891
- if (this.getOrderIdentityMatchKeys(target).length === 0)
1892
- return -1;
1893
- return orders.findIndex((order) => this.doOrdersShareIdentity(order, target));
1806
+ if (this.getOrderIdentityMatchKeys(target).length === 0) return -1;
1807
+ return orders.findIndex(order => this.doOrdersShareIdentity(order, target));
1894
1808
  }
1895
1809
  getOrderCompletenessScore(order) {
1896
1810
  const record = order;
1897
1811
  let score = this.isPendingSyncOrder(order) ? 0 : 100;
1898
- if (!this.isBlankIdentityValue(order.order_id) && order.order_id !== record.external_sale_number)
1899
- score += 30;
1812
+ if (!this.isBlankIdentityValue(order.order_id) && order.order_id !== record.external_sale_number) score += 30;
1900
1813
  score += this.getOrderIdentityMatchKeys(order).length * 5;
1901
- if (Array.isArray(order.products))
1902
- score += Math.min(order.products.length, 10);
1903
- if (Array.isArray(order.bookings))
1904
- score += Math.min(order.bookings.length, 10);
1905
- if (Array.isArray(order.payments))
1906
- score += Math.min(order.payments.length, 10);
1907
- if (record.updated_at)
1908
- score += 1;
1814
+ if (Array.isArray(order.products)) score += Math.min(order.products.length, 10);
1815
+ if (Array.isArray(order.bookings)) score += Math.min(order.bookings.length, 10);
1816
+ if (Array.isArray(order.payments)) score += Math.min(order.payments.length, 10);
1817
+ if (record.updated_at) score += 1;
1909
1818
  return score;
1910
1819
  }
1911
1820
  pickPreferredOrder(left, right) {
1912
1821
  const leftScore = this.getOrderCompletenessScore(left);
1913
1822
  const rightScore = this.getOrderCompletenessScore(right);
1914
- if (rightScore >= leftScore)
1915
- return right;
1823
+ if (rightScore >= leftScore) return right;
1916
1824
  return left;
1917
1825
  }
1918
1826
  getProductIdentityKeys(product) {
1919
- var _a;
1920
1827
  const record = product;
1921
- if (!record)
1922
- return [];
1828
+ if (!record) return [];
1923
1829
  const keys = [];
1924
- const metadataUid = (_a = record.metadata) == null ? void 0 : _a.unique_identification_number;
1925
- if (!this.isBlankIdentityValue(metadataUid))
1926
- keys.push(`uid:${String(metadataUid)}`);
1830
+ const metadataUid = record.metadata?.unique_identification_number;
1831
+ if (!this.isBlankIdentityValue(metadataUid)) keys.push(`uid:${String(metadataUid)}`);
1927
1832
  const topLevelUid = record.unique_identification_number;
1928
- if (!this.isBlankIdentityValue(topLevelUid))
1929
- keys.push(`uid:${String(topLevelUid)}`);
1833
+ if (!this.isBlankIdentityValue(topLevelUid)) keys.push(`uid:${String(topLevelUid)}`);
1930
1834
  const orderDetailId = record.order_detail_id;
1931
- if (!this.isBlankIdentityValue(orderDetailId))
1932
- keys.push(`detail:${String(orderDetailId)}`);
1835
+ if (!this.isBlankIdentityValue(orderDetailId)) keys.push(`detail:${String(orderDetailId)}`);
1933
1836
  const bookingUid = record.booking_uid;
1934
- if (!this.isBlankIdentityValue(bookingUid))
1935
- keys.push(`booking:${String(bookingUid)}`);
1837
+ if (!this.isBlankIdentityValue(bookingUid)) keys.push(`booking:${String(bookingUid)}`);
1936
1838
  return keys;
1937
1839
  }
1938
1840
  mergeOrderProductLists(preferred, secondary) {
1939
1841
  const preferredList = Array.isArray(preferred) ? preferred : [];
1940
1842
  const secondaryList = Array.isArray(secondary) ? secondary : [];
1941
- if (secondaryList.length === 0)
1942
- return preferredList;
1943
- if (preferredList.length === 0)
1944
- return secondaryList;
1945
- const seenKeys = /* @__PURE__ */ new Set();
1843
+ if (secondaryList.length === 0) return preferredList;
1844
+ if (preferredList.length === 0) return secondaryList;
1845
+ const seenKeys = new Set();
1946
1846
  for (const item of preferredList) {
1947
1847
  const keys = this.getProductIdentityKeys(item);
1948
- for (const key of keys)
1949
- seenKeys.add(key);
1848
+ for (const key of keys) seenKeys.add(key);
1950
1849
  }
1951
1850
  const result = [...preferredList];
1952
1851
  for (const item of secondaryList) {
1953
1852
  const keys = this.getProductIdentityKeys(item);
1954
- if (keys.length === 0 || keys.some((key) => seenKeys.has(key)))
1955
- continue;
1956
- for (const key of keys)
1957
- seenKeys.add(key);
1958
- result.push((0, import_lodash_es.cloneDeep)(item));
1853
+ if (keys.length === 0 || keys.some(key => seenKeys.has(key))) continue;
1854
+ for (const key of keys) seenKeys.add(key);
1855
+ result.push((0, _lodashEs.cloneDeep)(item));
1959
1856
  }
1960
1857
  return result;
1961
1858
  }
1962
1859
  mergeOrderPaymentLists(existing, incoming) {
1963
1860
  const existingList = Array.isArray(existing) ? existing : [];
1964
1861
  const incomingList = Array.isArray(incoming) ? incoming : [];
1965
- if (incomingList.length === 0)
1966
- return (0, import_lodash_es.cloneDeep)(existingList);
1967
- return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
1862
+ if (incomingList.length === 0) return (0, _lodashEs.cloneDeep)(existingList);
1863
+ return (0, _paymentUtils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
1968
1864
  }
1969
1865
  getIdentifiedPendingPayments(order) {
1970
- const payments = Array.isArray(order == null ? void 0 : order.payments) ? order.payments : [];
1971
- return payments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment));
1866
+ const payments = Array.isArray(order?.payments) ? order.payments : [];
1867
+ return payments.filter(payment => (0, _paymentUtils.isIdentifiedPendingOrderPayment)(payment));
1972
1868
  }
1973
1869
  shouldProtectLocalOrderFromRemoteSnapshot(order) {
1974
1870
  return this.isPendingSyncOrder(order) || this.isDraftOrder(order) || this.getIdentifiedPendingPayments(order).length > 0;
@@ -1976,10 +1872,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1976
1872
  getUnmatchedIdentifiedPendingPayments(existing, incoming) {
1977
1873
  const existingPayments = Array.isArray(existing) ? existing : [];
1978
1874
  const incomingPayments = Array.isArray(incoming) ? incoming : [];
1979
- const incomingIdentityKeys = new Set(
1980
- incomingPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1981
- );
1982
- return existingPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => incomingIdentityKeys.has(key)));
1875
+ const incomingIdentityKeys = new Set(incomingPayments.flatMap(payment => (0, _paymentUtils.getOrderPaymentIdentityKeys)(payment)));
1876
+ return existingPayments.filter(payment => (0, _paymentUtils.isIdentifiedPendingOrderPayment)(payment) && !(0, _paymentUtils.getOrderPaymentIdentityKeys)(payment).some(key => incomingIdentityKeys.has(key)));
1983
1877
  }
1984
1878
  mergeOrderRecords(existing, incoming) {
1985
1879
  const preferred = this.pickPreferredOrder(existing, incoming);
@@ -1988,31 +1882,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1988
1882
  ...secondary,
1989
1883
  ...preferred
1990
1884
  };
1991
- const fieldsToPreserve = [
1992
- "order_id",
1993
- "external_sale_number",
1994
- "order_number",
1995
- "shop_order_number",
1996
- "shop_full_order_number"
1997
- ];
1998
- const incomingPatchFields = [
1999
- "payment_status",
2000
- "status",
2001
- "shipping_status",
2002
- "updated_at",
2003
- "shop_discount",
2004
- "summary",
2005
- "note",
2006
- "customer_id",
2007
- "customer_name",
2008
- "customer",
2009
- "holder",
2010
- "contacts_info",
2011
- "phone",
2012
- "email",
2013
- "relation_forms",
2014
- "is_draft_order"
2015
- ];
1885
+ const fieldsToPreserve = ['order_id', 'external_sale_number', 'order_number', 'shop_order_number', 'shop_full_order_number'];
1886
+ const incomingPatchFields = ['payment_status', 'status', 'shipping_status', 'updated_at', 'shop_discount', 'summary', 'note', 'customer_id', 'customer_name', 'customer', 'holder', 'contacts_info', 'phone', 'email', 'relation_forms', 'is_draft_order'];
2016
1887
  const mergedRecord = merged;
2017
1888
  const preferredRecord = preferred;
2018
1889
  const secondaryRecord = secondary;
@@ -2029,41 +1900,34 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2029
1900
  }
2030
1901
  }
2031
1902
  for (const field of incomingPatchFields) {
2032
- if (!Object.prototype.hasOwnProperty.call(incomingRecord, field))
2033
- continue;
2034
- if (incomingRecord[field] === void 0 || incomingRecord[field] === null)
2035
- continue;
2036
- if (typeof incomingRecord[field] === "string" && incomingRecord[field] === "")
2037
- continue;
2038
- mergedRecord[field] = (0, import_lodash_es.cloneDeep)(incomingRecord[field]);
1903
+ if (!Object.prototype.hasOwnProperty.call(incomingRecord, field)) continue;
1904
+ if (incomingRecord[field] === undefined || incomingRecord[field] === null) continue;
1905
+ if (typeof incomingRecord[field] === 'string' && incomingRecord[field] === '') continue;
1906
+ mergedRecord[field] = (0, _lodashEs.cloneDeep)(incomingRecord[field]);
2039
1907
  }
1908
+
1909
+ // 子项数组遵循完整快照语义:incoming 自有且为数组(包括 [])时权威替换;
1910
+ // 字段缺席或不是数组时视为稀疏 patch,继续保留 existing。
2040
1911
  for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
2041
1912
  if (Array.isArray(incomingRecord[field])) {
2042
- if (field === "payments") {
2043
- const preservedPending = this.getUnmatchedIdentifiedPendingPayments(
2044
- existingRecord[field],
2045
- incomingRecord[field]
2046
- );
1913
+ if (field === 'payments') {
1914
+ const preservedPending = this.getUnmatchedIdentifiedPendingPayments(existingRecord[field], incomingRecord[field]);
2047
1915
  if (preservedPending.length > 0) {
2048
- this.logInfo("mergeOrderRecords-保留本地 pending 支付项", {
1916
+ this.logInfo('mergeOrderRecords-保留本地 pending 支付项', {
2049
1917
  order_id: existing.order_id ?? incoming.order_id ?? null,
2050
1918
  external_sale_number: existingRecord.external_sale_number ?? incomingRecord.external_sale_number ?? null,
2051
1919
  preserved_pending_count: preservedPending.length,
2052
- preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1920
+ preserved_payment_identities: preservedPending.map(payment => (0, _paymentUtils.getOrderPaymentIdentityKeys)(payment))
2053
1921
  });
2054
1922
  }
2055
1923
  }
2056
- mergedRecord[field] = this.mergeAuthoritativeOrderCollection(
2057
- field,
2058
- existingRecord[field],
2059
- incomingRecord[field],
2060
- childUidRemaps,
2061
- { preserveIdentifiedPendingPayments: field === "payments" }
2062
- );
1924
+ mergedRecord[field] = this.mergeAuthoritativeOrderCollection(field, existingRecord[field], incomingRecord[field], childUidRemaps, {
1925
+ preserveIdentifiedPendingPayments: field === 'payments'
1926
+ });
2063
1927
  continue;
2064
1928
  }
2065
1929
  if (Object.prototype.hasOwnProperty.call(existingRecord, field)) {
2066
- mergedRecord[field] = (0, import_lodash_es.cloneDeep)(existingRecord[field]);
1930
+ mergedRecord[field] = (0, _lodashEs.cloneDeep)(existingRecord[field]);
2067
1931
  } else {
2068
1932
  delete mergedRecord[field];
2069
1933
  }
@@ -2071,13 +1935,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2071
1935
  if (!this.isPendingSyncOrder(preferred) || !this.isPendingSyncOrder(secondary)) {
2072
1936
  merged.need_sync = 0;
2073
1937
  }
2074
- return this.normalizeOrderCollectionsForIngress(
2075
- (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(merged, childUidRemaps),
2076
- "mergeOrderRecords"
2077
- );
1938
+ return this.normalizeOrderCollectionsForIngress((0, _orderCollectionIdentity.applyOrderCollectionUidRemaps)(merged, childUidRemaps), 'mergeOrderRecords');
2078
1939
  }
2079
1940
  summarizeDuplicateOrders(orders) {
2080
- const groups = /* @__PURE__ */ new Map();
1941
+ const groups = new Map();
2081
1942
  for (const order of orders) {
2082
1943
  for (const key of this.getOrderIdentityMatchKeys(order)) {
2083
1944
  const group = groups.get(key) || [];
@@ -2088,7 +1949,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2088
1949
  return [...groups.entries()].filter(([, group]) => group.length > 1).slice(0, 20).map(([key, group]) => ({
2089
1950
  key,
2090
1951
  count: group.length,
2091
- orders: group.map((order) => ({
1952
+ orders: group.map(order => ({
2092
1953
  order_id: order.order_id ?? null,
2093
1954
  external_sale_number: order.external_sale_number ?? null,
2094
1955
  shop_order_number: order.shop_order_number ?? null,
@@ -2100,9 +1961,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2100
1961
  }
2101
1962
  logDuplicateOrders(source, orders) {
2102
1963
  const duplicateGroups = this.summarizeDuplicateOrders(orders);
2103
- if (duplicateGroups.length === 0)
2104
- return;
2105
- this.logWarning("检测到重复订单身份键", {
1964
+ if (duplicateGroups.length === 0) return;
1965
+ this.logWarning('检测到重复订单身份键', {
2106
1966
  source,
2107
1967
  duplicateGroupCount: duplicateGroups.length,
2108
1968
  duplicateGroups
@@ -2112,10 +1972,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2112
1972
  const list = [];
2113
1973
  let removedCount = 0;
2114
1974
  for (const order of orders) {
2115
- const normalizedOrder = this.normalizeOrderCollectionsForIngress(
2116
- order,
2117
- `${source}.order`
2118
- );
1975
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, `${source}.order`);
2119
1976
  const matchIndex = this.findOrderIndexByIdentity(list, normalizedOrder);
2120
1977
  if (matchIndex < 0) {
2121
1978
  list.push(normalizedOrder);
@@ -2125,7 +1982,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2125
1982
  removedCount += 1;
2126
1983
  }
2127
1984
  if (removedCount > 0) {
2128
- this.logWarning("订单列表重复项已压缩", {
1985
+ this.logWarning('订单列表重复项已压缩', {
2129
1986
  source,
2130
1987
  beforeCount: orders.length,
2131
1988
  afterCount: list.length,
@@ -2134,99 +1991,101 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2134
1991
  } else {
2135
1992
  this.logDuplicateOrders(source, orders);
2136
1993
  }
2137
- return { list, removedCount };
1994
+ return {
1995
+ list,
1996
+ removedCount
1997
+ };
2138
1998
  }
1999
+
2139
2000
  /**
2140
2001
  * 当前订单拉取窗口:
2141
2002
  * - 优先使用 createdAtQuery.sales_time_between(已按营业日边界初始化)
2142
2003
  * - 无法解析时退化为自然日窗口
2143
2004
  */
2144
2005
  getCurrentPullWindow() {
2145
- var _a, _b;
2146
- const now = (0, import_dayjs.default)();
2147
- const range = (_b = (_a = this.store) == null ? void 0 : _a.createdAtQuery) == null ? void 0 : _b.sales_time_between;
2006
+ const now = (0, _dayjs.default)();
2007
+ const range = this.store?.createdAtQuery?.sales_time_between;
2148
2008
  if (Array.isArray(range) && range.length >= 2) {
2149
- const startAt2 = (0, import_dayjs.default)(range[0]);
2150
- const endExclusiveAt = (0, import_dayjs.default)(range[1]);
2151
- if (startAt2.isValid() && endExclusiveAt.isValid() && endExclusiveAt.isAfter(startAt2)) {
2152
- return { startAt: startAt2, endExclusiveAt };
2009
+ const startAt = (0, _dayjs.default)(range[0]);
2010
+ const endExclusiveAt = (0, _dayjs.default)(range[1]);
2011
+ if (startAt.isValid() && endExclusiveAt.isValid() && endExclusiveAt.isAfter(startAt)) {
2012
+ return {
2013
+ startAt,
2014
+ endExclusiveAt
2015
+ };
2153
2016
  }
2154
2017
  }
2155
- const startAt = now.startOf("day");
2156
- return { startAt, endExclusiveAt: startAt.add(1, "day") };
2018
+ const startAt = now.startOf('day');
2019
+ return {
2020
+ startAt,
2021
+ endExclusiveAt: startAt.add(1, 'day')
2022
+ };
2157
2023
  }
2158
2024
  hasPulledOrdersToday() {
2159
2025
  const lastFullFetchAt = this.getStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY);
2160
- if (!lastFullFetchAt)
2161
- return false;
2162
- const parsed = (0, import_dayjs.default)(lastFullFetchAt);
2163
- if (!parsed.isValid())
2164
- return false;
2165
- const { startAt, endExclusiveAt } = this.getCurrentPullWindow();
2026
+ if (!lastFullFetchAt) return false;
2027
+ const parsed = (0, _dayjs.default)(lastFullFetchAt);
2028
+ if (!parsed.isValid()) return false;
2029
+
2030
+ // 按当前拉取窗口判断,而不是自然日判断。
2031
+ // 这样在营业日跨日边界(start_time)场景下也能正确判定是否需要重新拉取。
2032
+ const {
2033
+ startAt,
2034
+ endExclusiveAt
2035
+ } = this.getCurrentPullWindow();
2166
2036
  return (parsed.isAfter(startAt) || parsed.isSame(startAt)) && parsed.isBefore(endExclusiveAt);
2167
2037
  }
2168
2038
  markOrderPulledAtNow() {
2169
- this.setStorageItem(
2170
- ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY,
2171
- (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
2172
- );
2039
+ this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'));
2173
2040
  }
2174
2041
  getStorageItem(key) {
2175
- var _a;
2176
2042
  try {
2177
- if ((_a = this.storage) == null ? void 0 : _a.getStorage)
2178
- return this.storage.getStorage(key);
2179
- if (typeof globalThis !== "undefined" && (globalThis == null ? void 0 : globalThis.localStorage)) {
2043
+ if (this.storage?.getStorage) return this.storage.getStorage(key);
2044
+ if (typeof globalThis !== 'undefined' && globalThis?.localStorage) {
2180
2045
  return globalThis.localStorage.getItem(key);
2181
2046
  }
2182
2047
  } catch {
2048
+ // 忽略存储异常,避免影响主流程
2183
2049
  }
2184
2050
  return null;
2185
2051
  }
2186
2052
  setStorageItem(key, value) {
2187
- var _a;
2188
2053
  try {
2189
- if ((_a = this.storage) == null ? void 0 : _a.setStorage) {
2054
+ if (this.storage?.setStorage) {
2190
2055
  this.storage.setStorage(key, value);
2191
2056
  return;
2192
2057
  }
2193
- if (typeof globalThis !== "undefined" && (globalThis == null ? void 0 : globalThis.localStorage)) {
2058
+ if (typeof globalThis !== 'undefined' && globalThis?.localStorage) {
2194
2059
  globalThis.localStorage.setItem(key, value);
2195
2060
  }
2196
2061
  } catch {
2062
+ // 忽略存储异常,避免影响主流程
2197
2063
  }
2198
2064
  }
2199
2065
  async loadOrdersFromSQLite() {
2200
- if (!this.dbManager)
2201
- return [];
2066
+ if (!this.dbManager) return [];
2202
2067
  try {
2203
2068
  const orders = await this.dbManager.getAll(INDEXDB_STORE_NAME);
2204
- return (orders || []).map(
2205
- (order) => this.normalizeOrderCollectionsForIngress(order, "loadOrdersFromSQLite")
2206
- );
2069
+ return (orders || []).map(order => this.normalizeOrderCollectionsForIngress(order, 'loadOrdersFromSQLite'));
2207
2070
  } catch {
2208
2071
  return [];
2209
2072
  }
2210
2073
  }
2211
2074
  isPendingSyncOrder(order) {
2212
- return Number(order == null ? void 0 : order.need_sync) === 1;
2075
+ return Number(order?.need_sync) === 1;
2213
2076
  }
2214
2077
  isDraftOrder(order) {
2215
- return Number(order == null ? void 0 : order.is_draft_order) === 1;
2078
+ return Number(order?.is_draft_order) === 1;
2216
2079
  }
2217
2080
  shouldProtectDraftOrderFromIncoming(source) {
2218
- return source !== "checkoutSync";
2081
+ return source !== 'checkoutSync';
2219
2082
  }
2220
2083
  normalizeRemoteSyncedOrder(order) {
2221
- const normalizedOrder = this.normalizeOrderCollectionsForIngress(
2222
- order,
2223
- "normalizeRemoteSyncedOrder"
2224
- );
2225
- if (this.isPendingSyncOrder(normalizedOrder))
2226
- return {
2227
- ...normalizedOrder,
2228
- is_draft_order: 0
2229
- };
2084
+ const normalizedOrder = this.normalizeOrderCollectionsForIngress(order, 'normalizeRemoteSyncedOrder');
2085
+ if (this.isPendingSyncOrder(normalizedOrder)) return {
2086
+ ...normalizedOrder,
2087
+ is_draft_order: 0
2088
+ };
2230
2089
  return {
2231
2090
  ...normalizedOrder,
2232
2091
  need_sync: 0,
@@ -2238,48 +2097,33 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2238
2097
  ...this.withoutSyntheticDraftOrderId(draftOrder)
2239
2098
  };
2240
2099
  const remote = remoteOrder;
2241
- for (const field of [
2242
- "order_id",
2243
- "order_number",
2244
- "shop_order_number",
2245
- "shop_full_order_number"
2246
- ]) {
2100
+ for (const field of ['order_id', 'order_number', 'shop_order_number', 'shop_full_order_number']) {
2247
2101
  if (this.isBlankIdentityValue(merged[field]) && !this.isBlankIdentityValue(remote[field])) {
2248
2102
  merged[field] = remote[field];
2249
2103
  }
2250
2104
  }
2251
- return this.normalizeOrderCollectionsForIngress(
2252
- merged,
2253
- "mergeRemoteIdentityIntoDraftOrder"
2254
- );
2105
+ return this.normalizeOrderCollectionsForIngress(merged, 'mergeRemoteIdentityIntoDraftOrder');
2255
2106
  }
2256
2107
  mergeRemoteSnapshotWithPendingOrders(remoteOrders, existingOrders) {
2257
- const merged = remoteOrders.map((order) => this.normalizeRemoteSyncedOrder(order));
2108
+ const merged = remoteOrders.map(order => this.normalizeRemoteSyncedOrder(order));
2258
2109
  for (const rawOrder of existingOrders) {
2259
- const order = this.normalizeOrderCollectionsForIngress(
2260
- rawOrder,
2261
- "mergeRemoteSnapshotWithPendingOrders.existingSQLite"
2262
- );
2263
- if (!this.shouldProtectLocalOrderFromRemoteSnapshot(order))
2264
- continue;
2110
+ const order = this.normalizeOrderCollectionsForIngress(rawOrder, 'mergeRemoteSnapshotWithPendingOrders.existingSQLite');
2111
+ if (!this.shouldProtectLocalOrderFromRemoteSnapshot(order)) continue;
2265
2112
  const matchIndex = this.findOrderIndexByIdentity(merged, order);
2266
2113
  if (matchIndex >= 0) {
2267
2114
  if (this.isDraftOrder(order)) {
2268
- merged[matchIndex] = this.mergeRemoteIdentityIntoDraftOrder(
2269
- order,
2270
- merged[matchIndex]
2271
- );
2115
+ merged[matchIndex] = this.mergeRemoteIdentityIntoDraftOrder(order, merged[matchIndex]);
2272
2116
  } else {
2273
2117
  merged[matchIndex] = this.mergeOrderRecords(order, merged[matchIndex]);
2274
2118
  }
2275
2119
  continue;
2276
2120
  }
2277
- if (!this.getOrderStorageKey(order))
2278
- continue;
2121
+ if (!this.getOrderStorageKey(order)) continue;
2279
2122
  merged.push(order);
2280
2123
  }
2281
- return this.compactOrderListByIdentity(merged, "mergeRemoteSnapshotWithPendingOrders").list;
2124
+ return this.compactOrderListByIdentity(merged, 'mergeRemoteSnapshotWithPendingOrders').list;
2282
2125
  }
2126
+
2283
2127
  /**
2284
2128
  * 串行执行订单 SQLite 写入任务,避免快照替换与增量 upsert 并发交错。
2285
2129
  *
@@ -2290,45 +2134,40 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2290
2134
  */
2291
2135
  async runInOrderSQLiteSaveQueue(task) {
2292
2136
  const queuedTask = this.orderSQLiteSaveQueue.then(task, task);
2293
- this.orderSQLiteSaveQueue = queuedTask.then(() => void 0, () => void 0);
2137
+ this.orderSQLiteSaveQueue = queuedTask.then(() => undefined, () => undefined);
2294
2138
  return queuedTask;
2295
2139
  }
2140
+
2296
2141
  /**
2297
2142
  * 批量增量 upsert 订单到 SQLite,不清空表;用于 pubsub / HTTP 增量合并。
2298
2143
  *
2299
2144
  * @example
2300
2145
  * await this.patchOrdersInSQLite(freshOrders)
2301
2146
  */
2302
- async patchOrdersInSQLite(orders, source, mergeActions = {}, options = {}, forceWriteStorageKeys = /* @__PURE__ */ new Set()) {
2147
+ async patchOrdersInSQLite(orders, source, mergeActions = {}, options = {}, forceWriteStorageKeys = new Set()) {
2303
2148
  if (orders.length === 0) {
2304
2149
  return;
2305
2150
  }
2306
2151
  if (!this.dbManager) {
2307
- if (options.throwOnError)
2308
- throw new Error("订单 SQLite 数据库未初始化");
2152
+ if (options.throwOnError) throw new Error('订单 SQLite 数据库未初始化');
2309
2153
  return;
2310
2154
  }
2311
- const migrationTargetStorageKeys = new Set(
2312
- (options.storageKeyMigrations || []).map((migration) => migration.to)
2313
- );
2314
- const ordersSnapshot = (0, import_lodash_es.cloneDeep)(orders).map((order) => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).map((order) => {
2155
+ const migrationTargetStorageKeys = new Set((options.storageKeyMigrations || []).map(migration => migration.to));
2156
+ const ordersSnapshot = (0, _lodashEs.cloneDeep)(orders).map(order => this.normalizeOrderCollectionsForIngress(order, `${source}.sqliteIngress`)).map(order => {
2315
2157
  const storageKey = this.getOrderStorageKey(order);
2316
- if (!storageKey || !migrationTargetStorageKeys.has(storageKey))
2317
- return order;
2158
+ if (!storageKey || !migrationTargetStorageKeys.has(storageKey)) return order;
2318
2159
  return {
2319
2160
  ...order,
2320
2161
  [ORDER_STORAGE_KEY_FIELD]: storageKey
2321
2162
  };
2322
- }).filter((order) => this.getOrderStorageKey(order));
2163
+ }).filter(order => this.getOrderStorageKey(order));
2323
2164
  if (ordersSnapshot.length === 0) {
2324
2165
  return;
2325
2166
  }
2326
- const { toWrite, skipped } = this.filterRedundantPatchOrders(
2327
- source,
2328
- ordersSnapshot,
2329
- mergeActions,
2330
- forceWriteStorageKeys
2331
- );
2167
+ const {
2168
+ toWrite,
2169
+ skipped
2170
+ } = this.filterRedundantPatchOrders(source, ordersSnapshot, mergeActions, forceWriteStorageKeys);
2332
2171
  if (toWrite.length === 0) {
2333
2172
  return;
2334
2173
  }
@@ -2336,55 +2175,49 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2336
2175
  if (compactedToWrite.length === 0) {
2337
2176
  return;
2338
2177
  }
2339
- const writtenStorageKeys = new Set(
2340
- compactedToWrite.map((order) => this.getOrderStorageKey(order)).filter(Boolean)
2341
- );
2342
- const storageKeyMigrations = /* @__PURE__ */ new Map();
2178
+ const writtenStorageKeys = new Set(compactedToWrite.map(order => this.getOrderStorageKey(order)).filter(Boolean));
2179
+ const storageKeyMigrations = new Map();
2343
2180
  for (const migration of options.storageKeyMigrations || []) {
2344
- if (!writtenStorageKeys.has(migration.to))
2345
- continue;
2346
- if (writtenStorageKeys.has(migration.from))
2347
- continue;
2181
+ if (!writtenStorageKeys.has(migration.to)) continue;
2182
+ if (writtenStorageKeys.has(migration.from)) continue;
2348
2183
  storageKeyMigrations.set(migration.from, migration);
2349
2184
  }
2350
2185
  try {
2351
2186
  await this.runInOrderSQLiteSaveQueue(async () => {
2352
- let writeMethod = "none";
2353
- this.logInfo("patchOrdersInSQLite-开始", {
2187
+ let writeMethod = 'none';
2188
+ this.logInfo('patchOrdersInSQLite-开始', {
2354
2189
  source,
2355
2190
  count: compactedToWrite.length,
2356
2191
  dedupedCount: skipped.length
2357
2192
  });
2358
- if (typeof this.dbManager.bulkUpdate === "function") {
2359
- writeMethod = "bulkUpdate";
2193
+ if (typeof this.dbManager.bulkUpdate === 'function') {
2194
+ writeMethod = 'bulkUpdate';
2360
2195
  await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, compactedToWrite);
2361
- } else if (typeof this.dbManager.bulkAdd === "function") {
2362
- writeMethod = "bulkAdd";
2196
+ } else if (typeof this.dbManager.bulkAdd === 'function') {
2197
+ writeMethod = 'bulkAdd';
2363
2198
  await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, compactedToWrite);
2364
- } else if (typeof this.dbManager.update === "function") {
2365
- writeMethod = "update";
2199
+ } else if (typeof this.dbManager.update === 'function') {
2200
+ writeMethod = 'update';
2366
2201
  for (const order of compactedToWrite) {
2367
2202
  await this.dbManager.update(INDEXDB_STORE_NAME, order);
2368
2203
  }
2369
2204
  } else if (options.throwOnError) {
2370
- throw new Error("订单 SQLite 数据库不支持写入");
2205
+ throw new Error('订单 SQLite 数据库不支持写入');
2371
2206
  }
2372
2207
  this.recordRecentSqliteWrite(source, compactedToWrite);
2373
- if (writeMethod !== "none") {
2208
+ if (writeMethod !== 'none') {
2374
2209
  for (const migration of storageKeyMigrations.values()) {
2375
2210
  try {
2376
2211
  await this.dbManager.delete(INDEXDB_STORE_NAME, migration.from);
2377
2212
  this.recentSqliteWriteByStorageKey.delete(migration.from);
2378
2213
  for (const order of orders) {
2379
- if (this.getOrderStorageKey(order) !== migration.to)
2380
- continue;
2214
+ if (this.getOrderStorageKey(order) !== migration.to) continue;
2381
2215
  const orderRecord = order;
2382
- if (String(orderRecord[ORDER_STORAGE_KEY_FIELD] ?? "") !== migration.from)
2383
- continue;
2216
+ if (String(orderRecord[ORDER_STORAGE_KEY_FIELD] ?? '') !== migration.from) continue;
2384
2217
  orderRecord[ORDER_STORAGE_KEY_FIELD] = migration.to;
2385
2218
  }
2386
2219
  } catch (error) {
2387
- this.logError("删除订单旧 SQLite storage key 失败", {
2220
+ this.logError('删除订单旧 SQLite storage key 失败', {
2388
2221
  source,
2389
2222
  order_id: migration.orderId,
2390
2223
  oldStorageKey: migration.from,
@@ -2394,7 +2227,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2394
2227
  }
2395
2228
  }
2396
2229
  }
2397
- this.logInfo("patchOrdersInSQLite-完成", {
2230
+ this.logInfo('patchOrdersInSQLite-完成', {
2398
2231
  source,
2399
2232
  count: compactedToWrite.length,
2400
2233
  writeMethod,
@@ -2402,14 +2235,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2402
2235
  });
2403
2236
  });
2404
2237
  } catch (error) {
2405
- this.logError("增量保存订单到 SQLite 失败", {
2238
+ this.logError('增量保存订单到 SQLite 失败', {
2406
2239
  error: error instanceof Error ? error.message : String(error),
2407
2240
  orderCount: ordersSnapshot.length
2408
2241
  });
2409
- if (options.throwOnError)
2410
- throw error;
2242
+ if (options.throwOnError) throw error;
2411
2243
  }
2412
2244
  }
2245
+
2413
2246
  /**
2414
2247
  * 单条 upsert 订单到 SQLite;用于 overwriteExistingOrder 等单条覆盖场景。
2415
2248
  *
@@ -2418,55 +2251,50 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2418
2251
  */
2419
2252
  async updateOrderInSQLite(order, source, options = {}) {
2420
2253
  if (!this.getOrderStorageKey(order)) {
2421
- if (options.throwOnError)
2422
- throw new Error("订单缺少可用的 SQLite 存储主键");
2254
+ if (options.throwOnError) throw new Error('订单缺少可用的 SQLite 存储主键');
2423
2255
  return;
2424
2256
  }
2425
2257
  if (!this.dbManager) {
2426
- if (options.throwOnError)
2427
- throw new Error("订单 SQLite 数据库未初始化");
2258
+ if (options.throwOnError) throw new Error('订单 SQLite 数据库未初始化');
2428
2259
  return;
2429
2260
  }
2430
- const orderSnapshot = this.normalizeOrderCollectionsForIngress(
2431
- (0, import_lodash_es.cloneDeep)(order),
2432
- `${source}.sqliteIngress`
2433
- );
2261
+ const orderSnapshot = this.normalizeOrderCollectionsForIngress((0, _lodashEs.cloneDeep)(order), `${source}.sqliteIngress`);
2434
2262
  try {
2435
2263
  await this.runInOrderSQLiteSaveQueue(async () => {
2436
- let writeMethod = "none";
2437
- this.logInfo("updateOrderInSQLite-开始", {
2264
+ let writeMethod = 'none';
2265
+ this.logInfo('updateOrderInSQLite-开始', {
2438
2266
  source,
2439
2267
  orderId: orderSnapshot.order_id ?? null,
2440
2268
  storageKey: this.getOrderStorageKey(orderSnapshot)
2441
2269
  });
2442
- if (typeof this.dbManager.update === "function") {
2443
- writeMethod = "update";
2270
+ if (typeof this.dbManager.update === 'function') {
2271
+ writeMethod = 'update';
2444
2272
  await this.dbManager.update(INDEXDB_STORE_NAME, orderSnapshot);
2445
- } else if (typeof this.dbManager.bulkUpdate === "function") {
2446
- writeMethod = "bulkUpdate";
2273
+ } else if (typeof this.dbManager.bulkUpdate === 'function') {
2274
+ writeMethod = 'bulkUpdate';
2447
2275
  await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, [orderSnapshot]);
2448
- } else if (typeof this.dbManager.bulkAdd === "function") {
2449
- writeMethod = "bulkAdd";
2276
+ } else if (typeof this.dbManager.bulkAdd === 'function') {
2277
+ writeMethod = 'bulkAdd';
2450
2278
  await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, [orderSnapshot]);
2451
2279
  } else if (options.throwOnError) {
2452
- throw new Error("订单 SQLite 数据库不支持写入");
2280
+ throw new Error('订单 SQLite 数据库不支持写入');
2453
2281
  }
2454
2282
  this.recordRecentSqliteWrite(source, [orderSnapshot]);
2455
- this.logInfo("updateOrderInSQLite-完成", {
2283
+ this.logInfo('updateOrderInSQLite-完成', {
2456
2284
  source,
2457
2285
  orderId: orderSnapshot.order_id ?? null,
2458
2286
  writeMethod
2459
2287
  });
2460
2288
  });
2461
2289
  } catch (error) {
2462
- this.logError("单条保存订单到 SQLite 失败", {
2290
+ this.logError('单条保存订单到 SQLite 失败', {
2463
2291
  error: error instanceof Error ? error.message : String(error),
2464
2292
  orderId: orderSnapshot.order_id ?? null
2465
2293
  });
2466
- if (options.throwOnError)
2467
- throw error;
2294
+ if (options.throwOnError) throw error;
2468
2295
  }
2469
2296
  }
2297
+
2470
2298
  /**
2471
2299
  * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
2472
2300
  * 用于 SSE 全量拉取与营业日窗口裁剪。
@@ -2476,34 +2304,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2476
2304
  */
2477
2305
  async replaceOrdersSnapshotInSQLite(orderList, source, protectedOrdersBeforeRemoteFetch = []) {
2478
2306
  if (!this.dbManager) {
2479
- return this.compactOrderListByIdentity(
2480
- orderList.map((order) => this.normalizeRemoteSyncedOrder(order)),
2481
- `${source}.snapshotNoDb`
2482
- ).list;
2483
- }
2484
- const remoteSnapshot = (0, import_lodash_es.cloneDeep)(orderList).map(
2485
- (order) => this.normalizeOrderCollectionsForIngress(order, `${source}.remoteIngress`)
2486
- );
2487
- let mergedSnapshot = this.compactOrderListByIdentity(
2488
- remoteSnapshot.map((order) => this.normalizeRemoteSyncedOrder(order)),
2489
- `${source}.remoteSnapshot`
2490
- ).list;
2307
+ return this.compactOrderListByIdentity(orderList.map(order => this.normalizeRemoteSyncedOrder(order)), `${source}.snapshotNoDb`).list;
2308
+ }
2309
+ const remoteSnapshot = (0, _lodashEs.cloneDeep)(orderList).map(order => this.normalizeOrderCollectionsForIngress(order, `${source}.remoteIngress`));
2310
+ let mergedSnapshot = this.compactOrderListByIdentity(remoteSnapshot.map(order => this.normalizeRemoteSyncedOrder(order)), `${source}.remoteSnapshot`).list;
2491
2311
  try {
2492
2312
  await this.runInOrderSQLiteSaveQueue(async () => {
2493
- const existingOrders = typeof this.dbManager.getAll === "function" ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
2494
- const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map((order) => this.normalizeOrderCollectionsForIngress(
2495
- order,
2496
- `${source}.protectedBeforeRemoteFetch`
2497
- )).filter((order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
2313
+ const existingOrders = typeof this.dbManager.getAll === 'function' ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
2314
+ const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map(order => this.normalizeOrderCollectionsForIngress(order, `${source}.protectedBeforeRemoteFetch`)).filter(order => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
2498
2315
  for (const rawCurrentOrder of existingOrders || []) {
2499
- const currentOrder = this.normalizeOrderCollectionsForIngress(
2500
- rawCurrentOrder,
2501
- `${source}.currentSQLite`
2502
- );
2503
- const protectedIndex = this.findOrderIndexByIdentity(
2504
- protectedLocalOrders,
2505
- currentOrder
2506
- );
2316
+ const currentOrder = this.normalizeOrderCollectionsForIngress(rawCurrentOrder, `${source}.currentSQLite`);
2317
+ const protectedIndex = this.findOrderIndexByIdentity(protectedLocalOrders, currentOrder);
2507
2318
  const currentNeedsProtection = this.shouldProtectLocalOrderFromRemoteSnapshot(currentOrder);
2508
2319
  if (protectedIndex >= 0) {
2509
2320
  if (currentNeedsProtection) {
@@ -2513,33 +2324,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2513
2324
  }
2514
2325
  continue;
2515
2326
  }
2516
- if (currentNeedsProtection)
2517
- protectedLocalOrders.push(currentOrder);
2327
+ if (currentNeedsProtection) protectedLocalOrders.push(currentOrder);
2518
2328
  }
2519
- const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(
2520
- remoteSnapshot,
2521
- protectedLocalOrders
2522
- );
2329
+ const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(remoteSnapshot, protectedLocalOrders);
2523
2330
  mergedSnapshot = this.compactOrderListByIdentity(orderListSnapshot, `${source}.sqliteSnapshot`).list;
2524
- this.logInfo("replaceOrdersSnapshotInSQLite-开始", {
2331
+ this.logInfo('replaceOrdersSnapshotInSQLite-开始', {
2525
2332
  source,
2526
2333
  count: mergedSnapshot.length,
2527
2334
  remoteCount: remoteSnapshot.length,
2528
2335
  protectedBeforeRemoteFetchCount: protectedOrdersBeforeRemoteFetch.length,
2529
2336
  protectedLocalOrderCount: protectedLocalOrders.length,
2530
2337
  preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length,
2531
- protectedPendingPaymentCount: protectedLocalOrders.reduce(
2532
- (count, order) => count + this.getIdentifiedPendingPayments(order).length,
2533
- 0
2534
- ),
2535
- protectedPendingPaymentIdentities: protectedLocalOrders.flatMap((order) => this.getIdentifiedPendingPayments(order).map((payment) => ({
2338
+ protectedPendingPaymentCount: protectedLocalOrders.reduce((count, order) => count + this.getIdentifiedPendingPayments(order).length, 0),
2339
+ protectedPendingPaymentIdentities: protectedLocalOrders.flatMap(order => this.getIdentifiedPendingPayments(order).map(payment => ({
2536
2340
  order_id: order.order_id ?? null,
2537
2341
  external_sale_number: order.external_sale_number ?? null,
2538
- payment_identities: (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment)
2342
+ payment_identities: (0, _paymentUtils.getOrderPaymentIdentityKeys)(payment)
2539
2343
  })))
2540
2344
  });
2541
2345
  await this.dbManager.clear(INDEXDB_STORE_NAME);
2542
- this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {
2346
+ this.logInfo('replaceOrdersSnapshotInSQLite-clear完成', {
2543
2347
  count: mergedSnapshot.length
2544
2348
  });
2545
2349
  if (mergedSnapshot.length === 0) {
@@ -2547,19 +2351,20 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2547
2351
  }
2548
2352
  await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, mergedSnapshot);
2549
2353
  this.recordRecentSqliteWrite(source, mergedSnapshot);
2550
- this.logInfo("replaceOrdersSnapshotInSQLite-bulkAdd完成", {
2354
+ this.logInfo('replaceOrdersSnapshotInSQLite-bulkAdd完成', {
2551
2355
  source,
2552
2356
  count: mergedSnapshot.length
2553
2357
  });
2554
2358
  });
2555
2359
  } catch (error) {
2556
- this.logError("全量保存订单到 SQLite 失败", {
2360
+ this.logError('全量保存订单到 SQLite 失败', {
2557
2361
  error: error instanceof Error ? error.message : String(error),
2558
2362
  orderList: remoteSnapshot.length
2559
2363
  });
2560
2364
  }
2561
2365
  return mergedSnapshot;
2562
2366
  }
2367
+
2563
2368
  /**
2564
2369
  * 清空订单模块的内存数据和本地 SQLite 订单表。
2565
2370
  *
@@ -2568,17 +2373,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2568
2373
  */
2569
2374
  async clear() {
2570
2375
  this.store.list = [];
2571
- this.store.map = /* @__PURE__ */ new Map();
2376
+ this.store.map = new Map();
2572
2377
  if (this.dbManager) {
2573
2378
  await this.runInOrderSQLiteSaveQueue(async () => {
2574
2379
  await this.dbManager.clear(INDEXDB_STORE_NAME);
2575
2380
  });
2576
2381
  }
2577
- this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, "");
2578
- this.emitOrdersChanged([], "clear");
2382
+ this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, '');
2383
+ this.emitOrdersChanged([], 'clear');
2579
2384
  }
2580
- };
2581
- // Annotate the CommonJS export names for ESM import in node:
2582
- 0 && (module.exports = {
2583
- OrderModule
2584
- });
2385
+ }
2386
+ exports.OrderModule = OrderModule;