@pisell/pisellos 2.3.73 → 2.3.75

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