@pisell/pisellos 2.2.180 → 2.2.182
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.
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/BookingContext/index.d.ts +37 -0
- package/dist/modules/BookingContext/index.js +436 -0
- package/dist/modules/BookingContext/types.d.ts +102 -0
- package/dist/modules/BookingContext/types.js +51 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +276 -0
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +137 -0
- package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
- package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +215 -0
- package/dist/modules/BookingContext/utils/flexible.d.ts +28 -0
- package/dist/modules/BookingContext/utils/flexible.js +56 -0
- package/dist/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
- package/dist/modules/BookingContext/utils/formatResourceList.js +38 -0
- package/dist/modules/BookingContext/utils/index.d.ts +11 -0
- package/dist/modules/BookingContext/utils/index.js +11 -0
- package/dist/modules/BookingContext/utils/noResource.d.ts +13 -0
- package/dist/modules/BookingContext/utils/noResource.js +77 -0
- package/dist/modules/BookingContext/utils/productExtend.d.ts +72 -0
- package/dist/modules/BookingContext/utils/productExtend.js +339 -0
- package/dist/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
- package/dist/modules/BookingContext/utils/resourceErrors.js +74 -0
- package/dist/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
- package/dist/modules/BookingContext/utils/resourceSelection.js +24 -0
- package/dist/modules/BookingContext/utils/resources.d.ts +80 -0
- package/dist/modules/BookingContext/utils/resources.js +486 -0
- package/dist/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
- package/dist/modules/BookingContext/utils/serviceTimes.js +151 -0
- package/dist/modules/BookingContext/utils/timeSlices.d.ts +42 -0
- package/dist/modules/BookingContext/utils/timeSlices.js +100 -0
- package/dist/modules/Customer/index.d.ts +6 -0
- package/dist/modules/Customer/index.js +129 -83
- package/dist/modules/Customer/types.d.ts +2 -0
- package/dist/modules/Discount/index.js +4 -3
- package/dist/modules/Discount/types.d.ts +1 -0
- package/dist/modules/Order/index.d.ts +101 -10
- package/dist/modules/Order/index.js +1444 -490
- package/dist/modules/Order/types.d.ts +201 -18
- package/dist/modules/Order/types.js +31 -0
- package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
- package/dist/modules/Order/utils/manualProductDiscount.js +210 -0
- package/dist/modules/Order/utils.d.ts +83 -1
- package/dist/modules/Order/utils.js +405 -61
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/Quotation/index.d.ts +0 -1
- package/dist/modules/Quotation/index.js +23 -21
- package/dist/modules/Rules/index.d.ts +4 -0
- package/dist/modules/Rules/index.js +43 -39
- package/dist/modules/Rules/types.d.ts +1 -0
- package/dist/modules/SalesSummary/index.js +4 -2
- package/dist/modules/SalesSummary/utils.js +21 -7
- package/dist/modules/Schedule/index.js +6 -2
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +2 -1
- package/dist/server/index.js +87 -29
- package/dist/server/modules/order/index.d.ts +23 -0
- package/dist/server/modules/order/index.js +123 -46
- package/dist/server/modules/order/utils/filterOrders.js +20 -6
- package/dist/server/modules/products/index.d.ts +1 -1
- package/dist/server/modules/products/index.js +130 -113
- package/dist/server/modules/schedule/index.js +13 -6
- package/dist/solution/BaseSales/index.d.ts +89 -7
- package/dist/solution/BaseSales/index.js +1489 -366
- package/dist/solution/BaseSales/types.d.ts +67 -1
- package/dist/solution/BaseSales/types.js +3 -1
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
- package/dist/solution/BaseSales/utils/cartPromotion.js +1258 -0
- package/dist/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
- package/dist/solution/BaseSales/utils/quotationPrice.js +237 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +68 -16
- package/dist/solution/BaseSales/utils.js +46 -8
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +152 -2
- package/dist/solution/BookingTicket/index.js +848 -184
- package/dist/solution/BookingTicket/types.d.ts +2 -0
- package/dist/solution/BookingTicket/types.js +3 -0
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
- package/dist/solution/BookingTicket/utils/addProductDecision.js +346 -0
- package/dist/solution/BookingTicket/utils/cartView.js +4 -2
- package/dist/solution/ScanOrder/index.d.ts +9 -3
- package/dist/solution/ScanOrder/index.js +231 -128
- package/dist/solution/ScanOrder/utils.js +46 -8
- package/dist/solution/VenueBooking/index.d.ts +5 -2
- package/dist/solution/VenueBooking/index.js +103 -55
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +10 -0
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/BookingContext/index.d.ts +37 -0
- package/lib/modules/BookingContext/index.js +297 -0
- package/lib/modules/BookingContext/types.d.ts +102 -0
- package/lib/modules/BookingContext/types.js +34 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.d.ts +16 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +271 -0
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +8 -0
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +141 -0
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +75 -0
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +198 -0
- package/lib/modules/BookingContext/utils/flexible.d.ts +28 -0
- package/lib/modules/BookingContext/utils/flexible.js +80 -0
- package/lib/modules/BookingContext/utils/formatResourceList.d.ts +8 -0
- package/lib/modules/BookingContext/utils/formatResourceList.js +50 -0
- package/lib/modules/BookingContext/utils/index.d.ts +11 -0
- package/lib/modules/BookingContext/utils/index.js +43 -0
- package/lib/modules/BookingContext/utils/noResource.d.ts +13 -0
- package/lib/modules/BookingContext/utils/noResource.js +90 -0
- package/lib/modules/BookingContext/utils/productExtend.d.ts +72 -0
- package/lib/modules/BookingContext/utils/productExtend.js +283 -0
- package/lib/modules/BookingContext/utils/resourceErrors.d.ts +41 -0
- package/lib/modules/BookingContext/utils/resourceErrors.js +80 -0
- package/lib/modules/BookingContext/utils/resourceSelection.d.ts +7 -0
- package/lib/modules/BookingContext/utils/resourceSelection.js +46 -0
- package/lib/modules/BookingContext/utils/resources.d.ts +80 -0
- package/lib/modules/BookingContext/utils/resources.js +377 -0
- package/lib/modules/BookingContext/utils/serviceTimes.d.ts +55 -0
- package/lib/modules/BookingContext/utils/serviceTimes.js +162 -0
- package/lib/modules/BookingContext/utils/timeSlices.d.ts +42 -0
- package/lib/modules/BookingContext/utils/timeSlices.js +124 -0
- package/lib/modules/Customer/index.d.ts +6 -0
- package/lib/modules/Customer/index.js +26 -11
- package/lib/modules/Customer/types.d.ts +2 -0
- package/lib/modules/Discount/index.js +5 -1
- package/lib/modules/Discount/types.d.ts +1 -0
- package/lib/modules/Order/index.d.ts +101 -10
- package/lib/modules/Order/index.js +751 -114
- package/lib/modules/Order/types.d.ts +201 -18
- package/lib/modules/Order/types.js +1 -0
- package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
- package/lib/modules/Order/utils/manualProductDiscount.js +206 -0
- package/lib/modules/Order/utils.d.ts +83 -1
- package/lib/modules/Order/utils.js +340 -22
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/Quotation/index.d.ts +0 -1
- package/lib/modules/Quotation/index.js +18 -15
- package/lib/modules/Rules/index.d.ts +4 -0
- package/lib/modules/Rules/index.js +26 -27
- package/lib/modules/Rules/types.d.ts +1 -0
- package/lib/modules/SalesSummary/index.js +4 -2
- package/lib/modules/SalesSummary/utils.js +21 -7
- package/lib/modules/Schedule/index.js +3 -1
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +3 -1
- package/lib/server/index.js +41 -4
- package/lib/server/modules/order/index.d.ts +23 -0
- package/lib/server/modules/order/index.js +46 -14
- package/lib/server/modules/order/utils/filterOrders.js +12 -4
- package/lib/server/modules/products/index.d.ts +1 -1
- package/lib/server/modules/products/index.js +30 -20
- package/lib/server/modules/schedule/index.js +2 -1
- package/lib/solution/BaseSales/index.d.ts +89 -7
- package/lib/solution/BaseSales/index.js +742 -23
- package/lib/solution/BaseSales/types.d.ts +67 -1
- package/lib/solution/BaseSales/types.js +3 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +275 -0
- package/lib/solution/BaseSales/utils/cartPromotion.js +836 -0
- package/lib/solution/BaseSales/utils/quotationPrice.d.ts +7 -0
- package/lib/solution/BaseSales/utils/quotationPrice.js +277 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +71 -12
- package/lib/solution/BaseSales/utils.js +46 -6
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +152 -2
- package/lib/solution/BookingTicket/index.js +389 -9
- package/lib/solution/BookingTicket/types.d.ts +2 -0
- package/lib/solution/BookingTicket/types.js +6 -0
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +113 -0
- package/lib/solution/BookingTicket/utils/addProductDecision.js +318 -0
- package/lib/solution/BookingTicket/utils/cartView.js +4 -2
- package/lib/solution/ScanOrder/index.d.ts +9 -3
- package/lib/solution/ScanOrder/index.js +147 -66
- package/lib/solution/ScanOrder/utils.js +46 -6
- package/lib/solution/VenueBooking/index.d.ts +5 -2
- package/lib/solution/VenueBooking/index.js +50 -14
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +10 -0
- package/package.json +1 -1
|
@@ -37,7 +37,9 @@ var import_types = require("./types");
|
|
|
37
37
|
var import_utils = require("./utils");
|
|
38
38
|
var import_utils2 = require("../Product/utils");
|
|
39
39
|
var import_dayjs = __toESM(require("dayjs"));
|
|
40
|
+
var import_cartPromotion = require("../../solution/BaseSales/utils/cartPromotion");
|
|
40
41
|
var import_utils3 = require("../../solution/ScanOrder/utils");
|
|
42
|
+
var import_manualProductDiscount = require("./utils/manualProductDiscount");
|
|
41
43
|
var import_Discount = require("../Discount");
|
|
42
44
|
var import_Rules = require("../Rules");
|
|
43
45
|
var import_types2 = require("../Rules/types");
|
|
@@ -49,25 +51,51 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
49
51
|
super(name || "order", version);
|
|
50
52
|
this.defaultName = "order";
|
|
51
53
|
this.defaultVersion = "1.0.0";
|
|
54
|
+
// ─── 促销/赠品 ────────────────────────────────────
|
|
55
|
+
/** 评估器引用;由 SalesSdkProvider 注入,未注入时 applyPromotion 静默跳过 */
|
|
56
|
+
this.promotionEvaluator = null;
|
|
57
|
+
/** 赠品选择 resolver;由 SDK host bridge 注入 */
|
|
58
|
+
this.giftSelectResolver = null;
|
|
59
|
+
/** applyPromotion 递归保护 flag(写路径同步调 applyPromotion,禁止重入) */
|
|
60
|
+
this.isApplyingPromotion = false;
|
|
61
|
+
/** 最近一次 applyPromotion 的未满足促销提示 */
|
|
62
|
+
this.lastUnfulfilledPromotions = [];
|
|
63
|
+
/** 最近一次 applyPromotion 的赠品操作 diff(debug / SDK 读取使用) */
|
|
64
|
+
this.lastGiftActions = null;
|
|
65
|
+
/**
|
|
66
|
+
* 是否将 tempOrder 写入 IndexedDB 草稿(orders store)。
|
|
67
|
+
* BigSale 弹窗等短生命周期场景通过 setEnableTempOrderPersist(false) 关闭。
|
|
68
|
+
*/
|
|
69
|
+
this.draftPersistEnabled = true;
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
72
|
* Populate `savedAmount` on each discount based on product-level discount details.
|
|
55
73
|
* Only selected discounts get a non-zero value.
|
|
56
74
|
*/
|
|
57
75
|
static populateSavedAmounts(productList, discountList) {
|
|
58
|
-
var _a, _b;
|
|
59
76
|
const savedMap = /* @__PURE__ */ new Map();
|
|
77
|
+
const addDiscountAmount = (discount, quantity) => {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
const discountKey = ((_a = discount.discount) == null ? void 0 : _a.resource_id) || discount.id;
|
|
80
|
+
if (discountKey == null)
|
|
81
|
+
return;
|
|
82
|
+
const qty = Number(quantity) || 1;
|
|
83
|
+
const amount = new import_decimal.default(discount.amount || 0).times(qty).plus(((_b = discount.metadata) == null ? void 0 : _b.product_discount_difference) || 0);
|
|
84
|
+
savedMap.set(
|
|
85
|
+
discountKey,
|
|
86
|
+
(savedMap.get(discountKey) || new import_decimal.default(0)).plus(amount)
|
|
87
|
+
);
|
|
88
|
+
};
|
|
60
89
|
for (const product of productList) {
|
|
61
90
|
const qty = product.num || 1;
|
|
62
91
|
for (const pd of product.discount_list || []) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
);
|
|
92
|
+
addDiscountAmount(pd, qty);
|
|
93
|
+
}
|
|
94
|
+
for (const bundle of product.product_bundle || []) {
|
|
95
|
+
const bundleQty = new import_decimal.default(Number(qty) || 1).times(Number((bundle == null ? void 0 : bundle.num) ?? (bundle == null ? void 0 : bundle.quantity) ?? 1) || 1).toNumber();
|
|
96
|
+
for (const pd of (bundle == null ? void 0 : bundle.discount_list) || []) {
|
|
97
|
+
addDiscountAmount(pd, bundleQty);
|
|
98
|
+
}
|
|
71
99
|
}
|
|
72
100
|
}
|
|
73
101
|
for (const d of discountList) {
|
|
@@ -75,6 +103,27 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
75
103
|
d.savedAmount = d.isSelected && key != null && savedMap.has(key) ? savedMap.get(key).toNumber() : 0;
|
|
76
104
|
}
|
|
77
105
|
}
|
|
106
|
+
applyProductDiscountPrices(products) {
|
|
107
|
+
return (products || []).map((product) => {
|
|
108
|
+
var _a, _b, _c;
|
|
109
|
+
if ((_a = product.metadata) == null ? void 0 : _a.is_manual_discount)
|
|
110
|
+
return product;
|
|
111
|
+
const totalPerUnitDiscount = (0, import_utils.resolveEffectivePerUnitDiscount)(product);
|
|
112
|
+
const optionSum = (0, import_utils.sumOptionUnitPrice)(product.product_option_item);
|
|
113
|
+
const sourcePrice = ((_b = product.metadata) == null ? void 0 : _b.source_product_price) ?? (((_c = product.metadata) == null ? void 0 : _c.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
|
|
114
|
+
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
115
|
+
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
116
|
+
if (product.metadata) {
|
|
117
|
+
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
118
|
+
product.metadata.price_schema_version = 2;
|
|
119
|
+
}
|
|
120
|
+
product.selling_price = (0, import_utils.composeLinePrice)({
|
|
121
|
+
mainPrice: newMainSellingPrice,
|
|
122
|
+
bundle: product.product_bundle
|
|
123
|
+
});
|
|
124
|
+
return product;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
78
127
|
async initialize(core, options) {
|
|
79
128
|
var _a, _b, _c;
|
|
80
129
|
this.core = core;
|
|
@@ -101,7 +150,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
101
150
|
this.orderHooks = options.hooks || ((_b = otherParams.order) == null ? void 0 : _b.hooks) || ((_c = otherParams.hooks) == null ? void 0 : _c.order);
|
|
102
151
|
this.otherParams = otherParams;
|
|
103
152
|
this.registerDiscountModules(options);
|
|
104
|
-
this.restoreTempOrderFromStorage();
|
|
105
153
|
this.logInfo("OrderModule initialized successfully");
|
|
106
154
|
}
|
|
107
155
|
/**
|
|
@@ -174,21 +222,25 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
174
222
|
}
|
|
175
223
|
// ─── Discount: 公共 API ───
|
|
176
224
|
async loadDiscountConfig(params) {
|
|
177
|
-
var _a, _b, _c, _d;
|
|
178
|
-
const
|
|
225
|
+
var _a, _b, _c, _d, _e, _f;
|
|
226
|
+
const orderId = params.orderId || ((_a = this.store.tempOrder) == null ? void 0 : _a.order_id) || void 0;
|
|
227
|
+
const discountList = await ((_b = this.store.discount) == null ? void 0 : _b.loadPrepareConfig({
|
|
179
228
|
customer_id: params.customerId,
|
|
180
|
-
action: params.action || "create",
|
|
229
|
+
action: params.action || (orderId ? "edit" : "create"),
|
|
181
230
|
with_good_pass: 1,
|
|
182
231
|
with_discount_card: 1,
|
|
183
232
|
with_wallet_pass_holder: 1,
|
|
184
|
-
request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
233
|
+
request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
234
|
+
...orderId ? { order_id: orderId } : {}
|
|
185
235
|
}));
|
|
186
236
|
if (discountList) {
|
|
187
|
-
(
|
|
237
|
+
await ((_c = this.store.discount) == null ? void 0 : _c.setOriginalDiscountList(discountList));
|
|
238
|
+
await ((_d = this.store.discount) == null ? void 0 : _d.setDiscountList(discountList));
|
|
188
239
|
}
|
|
189
|
-
if ((
|
|
240
|
+
if (params.apply !== false && ((_f = (_e = this.store.tempOrder) == null ? void 0 : _e.products) == null ? void 0 : _f.length)) {
|
|
190
241
|
this.applyDiscount();
|
|
191
242
|
}
|
|
243
|
+
return this.getDiscountList();
|
|
192
244
|
}
|
|
193
245
|
getDiscountList() {
|
|
194
246
|
var _a;
|
|
@@ -204,6 +256,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
204
256
|
type: "clientCalc",
|
|
205
257
|
isAvailable: false,
|
|
206
258
|
discountList: this.getDiscountList(),
|
|
259
|
+
scannedDiscountList: resultDiscountList,
|
|
207
260
|
unavailableReason: import_types2.UnavailableReason.Unknown
|
|
208
261
|
};
|
|
209
262
|
}
|
|
@@ -212,6 +265,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
212
265
|
type: "server",
|
|
213
266
|
isAvailable: false,
|
|
214
267
|
discountList: this.getDiscountList(),
|
|
268
|
+
scannedDiscountList: resultDiscountList,
|
|
215
269
|
unavailableReasonKey
|
|
216
270
|
};
|
|
217
271
|
}
|
|
@@ -224,7 +278,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
224
278
|
return {
|
|
225
279
|
type: "clientCalc",
|
|
226
280
|
isAvailable: true,
|
|
227
|
-
discountList: this.getDiscountList()
|
|
281
|
+
discountList: this.getDiscountList(),
|
|
282
|
+
scannedDiscountList: resultDiscountList
|
|
228
283
|
};
|
|
229
284
|
}
|
|
230
285
|
const tempOrder = this.store.tempOrder;
|
|
@@ -245,6 +300,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
245
300
|
type: "clientCalc",
|
|
246
301
|
isAvailable: isAvailable || false,
|
|
247
302
|
discountList: newDiscountList || this.getDiscountList(),
|
|
303
|
+
scannedDiscountList: resultDiscountList,
|
|
248
304
|
unavailableReason
|
|
249
305
|
};
|
|
250
306
|
}
|
|
@@ -253,6 +309,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
253
309
|
const tempOrder = this.store.tempOrder;
|
|
254
310
|
if (!tempOrder)
|
|
255
311
|
return;
|
|
312
|
+
delete tempOrder.discount_list;
|
|
256
313
|
const rulesModule = this.store.rules;
|
|
257
314
|
if (!rulesModule)
|
|
258
315
|
return;
|
|
@@ -266,7 +323,23 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
266
323
|
orderTotalAmount: Number(((_d = this.store.summary) == null ? void 0 : _d.total_amount) || 0)
|
|
267
324
|
});
|
|
268
325
|
if (result == null ? void 0 : result.productList) {
|
|
269
|
-
|
|
326
|
+
const previousProductsByUid = (0, import_utils.indexOrderProductsByUid)(tempOrder.products);
|
|
327
|
+
tempOrder.products = this.applyProductDiscountPrices(
|
|
328
|
+
(result.productList || []).map((product, index) => {
|
|
329
|
+
const uid = (0, import_utils.getOrderProductLineUid)(product);
|
|
330
|
+
const previous = (uid ? previousProductsByUid.get(uid) : void 0) ?? previousProductsByUid.get(`__index__:${index}`);
|
|
331
|
+
const mergedProduct = previous ? (0, import_utils.mergeOrderProductDisplayFields)(previous, product) : product;
|
|
332
|
+
return {
|
|
333
|
+
...mergedProduct,
|
|
334
|
+
discount_list: (0, import_utils.normalizeOrderProductDiscountList)(
|
|
335
|
+
(0, import_manualProductDiscount.syncManualProductDiscountProductNum)(
|
|
336
|
+
mergedProduct.discount_list,
|
|
337
|
+
mergedProduct.num
|
|
338
|
+
)
|
|
339
|
+
)
|
|
340
|
+
};
|
|
341
|
+
})
|
|
342
|
+
);
|
|
270
343
|
}
|
|
271
344
|
if (result == null ? void 0 : result.discountList) {
|
|
272
345
|
OrderModule.populateSavedAmounts(
|
|
@@ -274,80 +347,185 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
274
347
|
result.discountList
|
|
275
348
|
);
|
|
276
349
|
(_e = this.store.discount) == null ? void 0 : _e.setDiscountList(result.discountList);
|
|
277
|
-
tempOrder.discount_list = result.discountList.filter(
|
|
278
|
-
(d) => d.isSelected
|
|
279
|
-
);
|
|
280
350
|
}
|
|
281
351
|
}
|
|
282
|
-
// ───
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
352
|
+
// ─── 促销/赠品 ──────────────────────────────────────
|
|
353
|
+
/**
|
|
354
|
+
* 注入促销评估器。
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* order.setPromotionEvaluator(appHelper.utils.promotionEvaluator);
|
|
358
|
+
*/
|
|
359
|
+
setPromotionEvaluator(evaluator) {
|
|
360
|
+
this.promotionEvaluator = evaluator || null;
|
|
289
361
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
362
|
+
/**
|
|
363
|
+
* 注入赠品选择 resolver。OS 需要补赠品时会 await 调用 resolver;缺省时跳过新增并 console.warn。
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* order.setGiftSelectResolver(async (ctx) => {
|
|
367
|
+
* // SDK 内部决定弹窗 or 自动选第一项,返回完整 OrderProduct[]
|
|
368
|
+
* return giftSelectBridge.request(ctx);
|
|
369
|
+
* });
|
|
370
|
+
*/
|
|
371
|
+
setGiftSelectResolver(resolver) {
|
|
372
|
+
this.giftSelectResolver = resolver || null;
|
|
295
373
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
374
|
+
/**
|
|
375
|
+
* 为商品目录追加促销标签,供上层 Sales 门面复用。
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* const products = order.appendPromotionTags(catalogProducts);
|
|
379
|
+
*/
|
|
380
|
+
appendPromotionTags(products) {
|
|
381
|
+
return (0, import_cartPromotion.appendPromotionTags)(products, this.promotionEvaluator);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* 应用购物车促销:计算 → 差异化赠品 → 写回 tempOrder.products → emit onPromotionApplied。
|
|
385
|
+
*
|
|
386
|
+
* 调用时机:写路径(add/update/remove/clear/setCustomer)末尾自动触发;外部一般无需手动调。
|
|
387
|
+
*
|
|
388
|
+
* 关键约束:
|
|
389
|
+
* - 不调用任何公开 CRUD API(如 removeProductFromOrder),全部内部 mutate tempOrder.products,避免事件风暴;
|
|
390
|
+
* - 用 `isApplyingPromotion` 防递归;
|
|
391
|
+
* - 多选项赠品依赖 giftSelectResolver,未注入则跳过且 console.warn;
|
|
392
|
+
* - 不主动调用 applyDiscount / recalculateSummary,调用方负责跟进。
|
|
393
|
+
*/
|
|
394
|
+
async applyPromotion() {
|
|
395
|
+
if (this.isApplyingPromotion)
|
|
300
396
|
return;
|
|
301
|
-
if (!this.
|
|
397
|
+
if (!this.promotionEvaluator)
|
|
302
398
|
return;
|
|
303
|
-
const
|
|
304
|
-
if (!
|
|
399
|
+
const tempOrder = this.store.tempOrder;
|
|
400
|
+
if (!tempOrder)
|
|
305
401
|
return;
|
|
402
|
+
this.isApplyingPromotion = true;
|
|
306
403
|
try {
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
this.
|
|
310
|
-
|
|
404
|
+
const result = (0, import_cartPromotion.processCartPromotion)(
|
|
405
|
+
tempOrder.products,
|
|
406
|
+
this.promotionEvaluator
|
|
407
|
+
);
|
|
408
|
+
if (result.giftActions.toRemove.length > 0) {
|
|
409
|
+
const removeSet = new Set(result.giftActions.toRemove.map(String));
|
|
410
|
+
result.products = result.products.filter((p) => {
|
|
411
|
+
const uid = (0, import_cartPromotion.getOrderProductUid)(p);
|
|
412
|
+
return uid ? !removeSet.has(String(uid)) : true;
|
|
413
|
+
});
|
|
311
414
|
}
|
|
312
|
-
|
|
313
|
-
for (
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
if (!Array.isArray(p.product_bundle)) {
|
|
321
|
-
p.product_bundle = [];
|
|
415
|
+
for (const reduce of result.giftActions.toReduce) {
|
|
416
|
+
for (const item of reduce.items) {
|
|
417
|
+
const product = result.products.find(
|
|
418
|
+
(p) => (0, import_cartPromotion.getOrderProductUid)(p) === item.uid
|
|
419
|
+
);
|
|
420
|
+
if (product) {
|
|
421
|
+
product.num = item.newQuantity;
|
|
322
422
|
}
|
|
323
|
-
const row = p;
|
|
324
|
-
parsedData.products[i] = (0, import_utils3.normalizeOrderProduct)(row);
|
|
325
423
|
}
|
|
326
424
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
425
|
+
if (result.giftActions.toAdd.length > 0) {
|
|
426
|
+
if (!this.giftSelectResolver) {
|
|
427
|
+
if (result.giftActions.toAdd.some((g) => g.giftOptions.length > 1)) {
|
|
428
|
+
console.warn(
|
|
429
|
+
"[OrderModule] giftSelectResolver not set, skip applying gifts",
|
|
430
|
+
result.giftActions.toAdd
|
|
431
|
+
);
|
|
432
|
+
} else {
|
|
433
|
+
console.warn(
|
|
434
|
+
"[OrderModule] giftSelectResolver not set, skip applying single-option gifts",
|
|
435
|
+
result.giftActions.toAdd
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
for (const addAction of result.giftActions.toAdd) {
|
|
440
|
+
if (addAction.giftOptions.length === 1) {
|
|
441
|
+
const sameStrategy = result.products.find(
|
|
442
|
+
(p) => {
|
|
443
|
+
var _a, _b;
|
|
444
|
+
return ((_b = (_a = p.metadata) == null ? void 0 : _a._giftInfo) == null ? void 0 : _b.strategyId) === addAction.strategyId;
|
|
445
|
+
}
|
|
446
|
+
);
|
|
447
|
+
if (sameStrategy) {
|
|
448
|
+
sameStrategy.num = (Number(sameStrategy.num) || 0) + (addAction.giftCount || 1);
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
try {
|
|
453
|
+
const giftProducts = await this.giftSelectResolver({
|
|
454
|
+
strategyId: addAction.strategyId,
|
|
455
|
+
strategyName: addAction.strategyName,
|
|
456
|
+
giftCount: addAction.giftCount,
|
|
457
|
+
giftOptions: addAction.giftOptions,
|
|
458
|
+
sourceProductIds: addAction.sourceProductIds
|
|
459
|
+
});
|
|
460
|
+
if (Array.isArray(giftProducts) && giftProducts.length > 0) {
|
|
461
|
+
for (const gp of giftProducts) {
|
|
462
|
+
if (!gp)
|
|
463
|
+
continue;
|
|
464
|
+
result.products.push(gp);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
} catch (error) {
|
|
468
|
+
console.warn(
|
|
469
|
+
"[OrderModule] giftSelectResolver rejected, skip add gift",
|
|
470
|
+
addAction.strategyId,
|
|
471
|
+
error
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
338
476
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
477
|
+
tempOrder.products = result.products;
|
|
478
|
+
this.lastUnfulfilledPromotions = result.unfulfilledPromotions;
|
|
479
|
+
this.lastGiftActions = result.giftActions;
|
|
480
|
+
const payload = {
|
|
481
|
+
unfulfilledPromotions: result.unfulfilledPromotions,
|
|
482
|
+
giftActions: result.giftActions,
|
|
483
|
+
gifts: result.gifts.map((g) => ({
|
|
484
|
+
strategyId: g.strategyId,
|
|
485
|
+
strategyName: g.strategyName,
|
|
486
|
+
giftCount: g.giftCount,
|
|
487
|
+
giftOptions: g.giftOptions
|
|
488
|
+
})),
|
|
489
|
+
products: tempOrder.products
|
|
490
|
+
};
|
|
491
|
+
this.effectsEmit("onPromotionApplied", payload);
|
|
492
|
+
} catch (error) {
|
|
493
|
+
console.error("[OrderModule] applyPromotion failed", error);
|
|
494
|
+
} finally {
|
|
495
|
+
this.isApplyingPromotion = false;
|
|
342
496
|
}
|
|
343
497
|
}
|
|
498
|
+
/** 最近一次 applyPromotion 输出的未满足促销列表 */
|
|
499
|
+
getUnfulfilledPromotions() {
|
|
500
|
+
return this.lastUnfulfilledPromotions;
|
|
501
|
+
}
|
|
502
|
+
/** 最近一次 applyPromotion 输出的赠品操作 diff */
|
|
503
|
+
getLastGiftActions() {
|
|
504
|
+
return this.lastGiftActions;
|
|
505
|
+
}
|
|
506
|
+
// ─── TempOrder: 初始化入口 ───
|
|
507
|
+
initTempOrder(params) {
|
|
508
|
+
if (params.cacheId !== void 0)
|
|
509
|
+
this.cacheId = params.cacheId;
|
|
510
|
+
if (params.salesSummaryModuleName !== void 0)
|
|
511
|
+
this.salesSummaryModuleName = params.salesSummaryModuleName;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* 控制 IndexedDB 草稿(saveDraft)是否写入。
|
|
515
|
+
* localStorage 版 tempOrder 持久化已废弃,此方法仅影响 saveDraft。
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* order.setEnableTempOrderPersist(false); // BigSale 弹窗:跳过 ~1s 的 dbUpdate
|
|
519
|
+
*/
|
|
520
|
+
setEnableTempOrderPersist(enabled) {
|
|
521
|
+
this.draftPersistEnabled = enabled;
|
|
522
|
+
}
|
|
523
|
+
/** 是否允许 saveDraft 写入 IndexedDB 草稿。 */
|
|
524
|
+
isTempOrderPersistEnabled() {
|
|
525
|
+
return this.draftPersistEnabled;
|
|
526
|
+
}
|
|
527
|
+
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化;草稿保存请使用 IndexedDB saveDraft。 */
|
|
344
528
|
persistTempOrder() {
|
|
345
|
-
const key = this.getTempOrderStorageKey();
|
|
346
|
-
if (!key || !this.store.tempOrder)
|
|
347
|
-
return;
|
|
348
|
-
if (!this.window)
|
|
349
|
-
return;
|
|
350
|
-
this.window.localStorage.setItem(key, JSON.stringify(this.store.tempOrder));
|
|
351
529
|
}
|
|
352
530
|
// ─── TempOrder: 创建 & 获取 ───
|
|
353
531
|
createDefaultTempOrderInstance() {
|
|
@@ -391,6 +569,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
391
569
|
}
|
|
392
570
|
return tempOrder.request_unique_idempotency_token;
|
|
393
571
|
}
|
|
572
|
+
buildPaymentSyncIdempotencyToken(tempOrder, payments) {
|
|
573
|
+
const baseToken = this.ensureRequestUniqueIdempotencyToken(tempOrder);
|
|
574
|
+
const paidPaymentsCount = (payments || []).filter((payment) => {
|
|
575
|
+
return String((payment == null ? void 0 : payment.status) || "").toLowerCase() === "paid";
|
|
576
|
+
}).length;
|
|
577
|
+
const paidCount = paidPaymentsCount > 0 ? paidPaymentsCount : payments.length;
|
|
578
|
+
return `${baseToken}_payment_${paidCount}`;
|
|
579
|
+
}
|
|
394
580
|
hasLocalDatabase() {
|
|
395
581
|
return !!this.dbManager;
|
|
396
582
|
}
|
|
@@ -478,8 +664,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
478
664
|
}
|
|
479
665
|
async saveDraft() {
|
|
480
666
|
var _a, _b;
|
|
481
|
-
if (!this.dbManager)
|
|
667
|
+
if (!this.draftPersistEnabled || !this.dbManager) {
|
|
482
668
|
return;
|
|
669
|
+
}
|
|
483
670
|
const tempOrder = this.ensureTempOrder();
|
|
484
671
|
const record = this.buildLocalOrderRecord(tempOrder);
|
|
485
672
|
try {
|
|
@@ -493,6 +680,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
493
680
|
});
|
|
494
681
|
}
|
|
495
682
|
}
|
|
683
|
+
saveDraftInBackground() {
|
|
684
|
+
void this.saveDraft();
|
|
685
|
+
}
|
|
496
686
|
async hydrateTempOrderFromLocalRecord(record) {
|
|
497
687
|
return this.hydrateTempOrderFromRecord(record);
|
|
498
688
|
}
|
|
@@ -509,6 +699,33 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
509
699
|
return sum.plus(amount.minus(rounding));
|
|
510
700
|
}, new import_decimal.default(0));
|
|
511
701
|
}
|
|
702
|
+
normalizePaymentSource(payment, options) {
|
|
703
|
+
const paymentRecord = payment;
|
|
704
|
+
const metadata = paymentRecord.metadata && typeof paymentRecord.metadata === "object" ? { ...paymentRecord.metadata } : {};
|
|
705
|
+
if (!metadata.unique_identification_number) {
|
|
706
|
+
metadata.unique_identification_number = (0, import_utils.createUuidV4)();
|
|
707
|
+
}
|
|
708
|
+
const normalized = {
|
|
709
|
+
...paymentRecord,
|
|
710
|
+
metadata,
|
|
711
|
+
origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
|
|
712
|
+
};
|
|
713
|
+
if (paymentRecord.status !== void 0) {
|
|
714
|
+
normalized.status = paymentRecord.status;
|
|
715
|
+
} else if ((options == null ? void 0 : options.defaultPaid) !== false) {
|
|
716
|
+
normalized.status = "paid";
|
|
717
|
+
}
|
|
718
|
+
return normalized;
|
|
719
|
+
}
|
|
720
|
+
updateTempOrderPaymentStatus(tempOrder) {
|
|
721
|
+
const paymentTotal = this.calculatePaymentTotal(tempOrder.payments || []);
|
|
722
|
+
if (paymentTotal.lte(0)) {
|
|
723
|
+
tempOrder.payment_status = tempOrder.payment_status || "payment_processing";
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
const targetAmount = this.getPaymentTargetAmount();
|
|
727
|
+
tempOrder.payment_status = targetAmount.gt(0) && paymentTotal.gte(targetAmount) ? "paid" : "partially_paid";
|
|
728
|
+
}
|
|
512
729
|
calculatePaidPaymentSummary(payments) {
|
|
513
730
|
return (payments || []).reduce(
|
|
514
731
|
(summary, payment) => {
|
|
@@ -537,6 +754,66 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
537
754
|
const fixedAmount = new import_decimal.default(serviceCharge.amount || 0);
|
|
538
755
|
return new import_decimal.default(payment.amount || 0).times(percentage).plus(fixedAmount);
|
|
539
756
|
}
|
|
757
|
+
formatSummaryMetadataMoney(value) {
|
|
758
|
+
if (value === void 0 || value === null || value === "")
|
|
759
|
+
return void 0;
|
|
760
|
+
if (value instanceof import_decimal.default)
|
|
761
|
+
return value.toFixed(2);
|
|
762
|
+
return new import_decimal.default(String(value || 0)).toFixed(2);
|
|
763
|
+
}
|
|
764
|
+
syncSummaryProductMetadata(products) {
|
|
765
|
+
const moneyKeys = [
|
|
766
|
+
"main_product_attached_bundle_surcharge_fee",
|
|
767
|
+
"main_product_attached_bundle_tax_fee",
|
|
768
|
+
"surcharge_rounding_remainder",
|
|
769
|
+
"tax_fee_rounding_remainder"
|
|
770
|
+
];
|
|
771
|
+
for (const product of products || []) {
|
|
772
|
+
const productRecord = product;
|
|
773
|
+
const metadata = productRecord.metadata && typeof productRecord.metadata === "object" ? { ...productRecord.metadata } : {};
|
|
774
|
+
let hasMetadataPatch = false;
|
|
775
|
+
for (const key of moneyKeys) {
|
|
776
|
+
const value = this.formatSummaryMetadataMoney(productRecord[key]);
|
|
777
|
+
if (value === void 0)
|
|
778
|
+
continue;
|
|
779
|
+
metadata[key] = value;
|
|
780
|
+
hasMetadataPatch = true;
|
|
781
|
+
}
|
|
782
|
+
if (Array.isArray(productRecord.relation_surcharge_ids)) {
|
|
783
|
+
metadata.relation_surcharge_ids = productRecord.relation_surcharge_ids;
|
|
784
|
+
hasMetadataPatch = true;
|
|
785
|
+
}
|
|
786
|
+
if (hasMetadataPatch)
|
|
787
|
+
productRecord.metadata = metadata;
|
|
788
|
+
if (!Array.isArray(productRecord.product_bundle))
|
|
789
|
+
continue;
|
|
790
|
+
for (const bundle of productRecord.product_bundle) {
|
|
791
|
+
const bundleRecord = bundle;
|
|
792
|
+
const bundleMetadata = bundleRecord.metadata && typeof bundleRecord.metadata === "object" ? { ...bundleRecord.metadata } : {};
|
|
793
|
+
let hasBundleMetadataPatch = false;
|
|
794
|
+
const bundleSurchargeFee = this.formatSummaryMetadataMoney(
|
|
795
|
+
bundleRecord.surcharge_fee
|
|
796
|
+
);
|
|
797
|
+
if (bundleSurchargeFee !== void 0) {
|
|
798
|
+
bundleMetadata.surcharge_fee = bundleSurchargeFee;
|
|
799
|
+
hasBundleMetadataPatch = true;
|
|
800
|
+
}
|
|
801
|
+
if (Array.isArray(bundleRecord.relation_surcharge_ids)) {
|
|
802
|
+
bundleMetadata.relation_surcharge_ids = bundleRecord.relation_surcharge_ids;
|
|
803
|
+
hasBundleMetadataPatch = true;
|
|
804
|
+
}
|
|
805
|
+
if (hasBundleMetadataPatch)
|
|
806
|
+
bundleRecord.metadata = bundleMetadata;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
calculateSummaryAmountGap(params) {
|
|
811
|
+
const { tempOrder, summary, orderPaidAmount } = params;
|
|
812
|
+
const depositAmount = summary.deposit_amount || tempOrder.deposit_amount || "0.00";
|
|
813
|
+
const isDeposit = tempOrder.is_deposit === 1 || new import_decimal.default(depositAmount || 0).gt(0);
|
|
814
|
+
const targetAmount = isDeposit ? new import_decimal.default(depositAmount || 0) : new import_decimal.default(summary.total_amount || summary.expect_amount || 0);
|
|
815
|
+
return targetAmount.minus(orderPaidAmount).toFixed(2);
|
|
816
|
+
}
|
|
540
817
|
getPaymentTargetAmount() {
|
|
541
818
|
const tempOrder = this.ensureTempOrder();
|
|
542
819
|
const summary = this.store.summary || (0, import_utils.createEmptySummary)();
|
|
@@ -559,17 +836,43 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
559
836
|
return newOrder;
|
|
560
837
|
}
|
|
561
838
|
restoreOrder() {
|
|
839
|
+
var _a, _b;
|
|
562
840
|
const freshTempOrder = this.createDefaultTempOrderInstance();
|
|
563
841
|
this.ensureExternalSaleNumber(freshTempOrder);
|
|
564
842
|
this.store.tempOrder = freshTempOrder;
|
|
565
843
|
this.store.summary = (0, import_utils.createEmptySummary)();
|
|
566
844
|
this.store.lastOrderInfo = void 0;
|
|
845
|
+
this.store.syncState = void 0;
|
|
846
|
+
void ((_a = this.store.discount) == null ? void 0 : _a.setOriginalDiscountList([]));
|
|
847
|
+
void ((_b = this.store.discount) == null ? void 0 : _b.setDiscountList([]));
|
|
567
848
|
this.persistTempOrder();
|
|
568
849
|
return freshTempOrder;
|
|
569
850
|
}
|
|
570
851
|
getTempOrder() {
|
|
571
852
|
return this.store.tempOrder;
|
|
572
853
|
}
|
|
854
|
+
async replaceTempOrder(tempOrder, options) {
|
|
855
|
+
if (!(0, import_utils.isTempOrder)(tempOrder)) {
|
|
856
|
+
throw new Error("无效的 tempOrder 数据");
|
|
857
|
+
}
|
|
858
|
+
const nextTempOrder = this.normalizeTempOrderForRuntime(
|
|
859
|
+
(0, import_lodash_es.cloneDeep)(tempOrder),
|
|
860
|
+
{ ensureIdentity: false }
|
|
861
|
+
);
|
|
862
|
+
this.store.tempOrder = nextTempOrder;
|
|
863
|
+
if ((options == null ? void 0 : options.recalculateSummary) !== false) {
|
|
864
|
+
await this.recalculateSummary({ createIfMissing: false });
|
|
865
|
+
} else {
|
|
866
|
+
this.store.summary = (0, import_utils.createEmptySummary)();
|
|
867
|
+
}
|
|
868
|
+
if ((options == null ? void 0 : options.persist) !== false) {
|
|
869
|
+
this.persistTempOrder();
|
|
870
|
+
}
|
|
871
|
+
if (options == null ? void 0 : options.saveDraft) {
|
|
872
|
+
await this.saveDraft();
|
|
873
|
+
}
|
|
874
|
+
return nextTempOrder;
|
|
875
|
+
}
|
|
573
876
|
getOrderIdentity() {
|
|
574
877
|
var _a;
|
|
575
878
|
const tempOrder = this.store.tempOrder;
|
|
@@ -607,7 +910,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
607
910
|
const depositAmount = tempOrder.deposit_amount || summary.deposit_amount || "0.00";
|
|
608
911
|
const targetAmount = tempOrder.is_deposit === 1 ? new import_decimal.default(depositAmount || 0) : new import_decimal.default(summary.total_amount || summary.expect_amount || 0);
|
|
609
912
|
const paymentTotal = this.calculatePaymentTotal(tempOrder.payments || []);
|
|
610
|
-
const amountGap =
|
|
913
|
+
const amountGap = targetAmount.minus(paymentTotal).toFixed(2);
|
|
611
914
|
return {
|
|
612
915
|
isDeposit: tempOrder.is_deposit === 1 || depositAmount !== "0.00",
|
|
613
916
|
depositAmount,
|
|
@@ -650,7 +953,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
650
953
|
this.ensureExternalSaleNumber(tempOrder);
|
|
651
954
|
await this.recalculateSummary({ createIfMissing: true });
|
|
652
955
|
this.persistTempOrder();
|
|
653
|
-
|
|
956
|
+
if (this.draftPersistEnabled) {
|
|
957
|
+
await this.saveDraft();
|
|
958
|
+
}
|
|
654
959
|
return tempOrder;
|
|
655
960
|
}
|
|
656
961
|
getOrderProducts() {
|
|
@@ -718,6 +1023,33 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
718
1023
|
}
|
|
719
1024
|
};
|
|
720
1025
|
}
|
|
1026
|
+
getBookingUniqueIdentificationNumber(booking) {
|
|
1027
|
+
var _a;
|
|
1028
|
+
const uid = (_a = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a.unique_identification_number;
|
|
1029
|
+
if (uid === void 0 || uid === null || uid === "")
|
|
1030
|
+
return null;
|
|
1031
|
+
return String(uid);
|
|
1032
|
+
}
|
|
1033
|
+
findBookingIndexByUniqueIdentificationNumber(tempOrder, uniqueIdentificationNumber) {
|
|
1034
|
+
return (tempOrder.bookings || []).findIndex((booking) => {
|
|
1035
|
+
return this.getBookingUniqueIdentificationNumber(booking) === uniqueIdentificationNumber;
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
removeLinkedBookingsForProduct(tempOrder, product) {
|
|
1039
|
+
var _a, _b;
|
|
1040
|
+
const productUid = ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.unique_identification_number) || (product == null ? void 0 : product.unique_identification_number);
|
|
1041
|
+
const bookingUid = (product == null ? void 0 : product.booking_uid) || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.booking_uid);
|
|
1042
|
+
if (!productUid && !bookingUid)
|
|
1043
|
+
return;
|
|
1044
|
+
tempOrder.bookings = (tempOrder.bookings || []).filter((booking) => {
|
|
1045
|
+
const currentBookingUid = this.getBookingUniqueIdentificationNumber(booking);
|
|
1046
|
+
if (bookingUid && currentBookingUid === String(bookingUid))
|
|
1047
|
+
return false;
|
|
1048
|
+
if (productUid && String((booking == null ? void 0 : booking.product_uid) || "") === String(productUid))
|
|
1049
|
+
return false;
|
|
1050
|
+
return true;
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
721
1053
|
// ─── TempOrder: 金额汇总 ───
|
|
722
1054
|
getSalesSummary() {
|
|
723
1055
|
if (!this.salesSummaryModuleName)
|
|
@@ -739,6 +1071,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
739
1071
|
total_refund_amount: existedSummary.total_refund_amount || "0.00",
|
|
740
1072
|
customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
|
|
741
1073
|
order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
|
|
1074
|
+
amount_gap: this.calculateSummaryAmountGap({
|
|
1075
|
+
tempOrder,
|
|
1076
|
+
summary: (0, import_utils.createEmptySummary)(),
|
|
1077
|
+
orderPaidAmount: paidPaymentSummary.orderPaidAmount
|
|
1078
|
+
}),
|
|
742
1079
|
pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
|
|
743
1080
|
};
|
|
744
1081
|
this.store.summary = emptySummary;
|
|
@@ -750,11 +1087,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
750
1087
|
isPriceIncludeTax: tempOrder.is_price_include_tax,
|
|
751
1088
|
shopDiscount: tempOrder.shop_discount
|
|
752
1089
|
});
|
|
1090
|
+
this.syncSummaryProductMetadata(tempOrder.products || []);
|
|
753
1091
|
const summary = {
|
|
754
1092
|
...salesSummaryResult,
|
|
755
1093
|
total_refund_amount: existedSummary.total_refund_amount || "0.00",
|
|
756
1094
|
customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
|
|
757
1095
|
order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
|
|
1096
|
+
amount_gap: this.calculateSummaryAmountGap({
|
|
1097
|
+
tempOrder,
|
|
1098
|
+
summary: salesSummaryResult,
|
|
1099
|
+
orderPaidAmount: paidPaymentSummary.orderPaidAmount
|
|
1100
|
+
}),
|
|
758
1101
|
pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
|
|
759
1102
|
};
|
|
760
1103
|
this.store.summary = summary;
|
|
@@ -777,13 +1120,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
777
1120
|
this.persistTempOrder();
|
|
778
1121
|
return summary;
|
|
779
1122
|
}
|
|
780
|
-
|
|
781
|
-
updateTempOrderNote(note) {
|
|
1123
|
+
updateTempOrderNote(note, sync = false) {
|
|
782
1124
|
const tempOrder = this.ensureTempOrder();
|
|
783
1125
|
tempOrder.note = String(note || "");
|
|
784
1126
|
this.persistTempOrder();
|
|
1127
|
+
if (sync) {
|
|
1128
|
+
const orderId = tempOrder.order_id;
|
|
1129
|
+
if (!orderId)
|
|
1130
|
+
return tempOrder.note;
|
|
1131
|
+
return this.syncTempOrderNoteToRemote(orderId, tempOrder.note);
|
|
1132
|
+
}
|
|
785
1133
|
return tempOrder.note;
|
|
786
1134
|
}
|
|
1135
|
+
async syncTempOrderNoteToRemote(orderId, note) {
|
|
1136
|
+
await this.request.put(`/order/order/${orderId}/note`, { note });
|
|
1137
|
+
return note;
|
|
1138
|
+
}
|
|
787
1139
|
getTempOrderNote() {
|
|
788
1140
|
var _a;
|
|
789
1141
|
return ((_a = this.store.tempOrder) == null ? void 0 : _a.note) || "";
|
|
@@ -807,10 +1159,29 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
807
1159
|
this.persistTempOrder();
|
|
808
1160
|
return tempOrder.contacts_info;
|
|
809
1161
|
}
|
|
1162
|
+
buildTempOrderCustomer(params) {
|
|
1163
|
+
if (!params.customerId)
|
|
1164
|
+
return null;
|
|
1165
|
+
const source = params.source ? (0, import_lodash_es.cloneDeep)(params.source) : {};
|
|
1166
|
+
const name = source.name ?? source.display_name ?? source.customerName ?? source.customer_name ?? params.customerName;
|
|
1167
|
+
const customerName = source.customer_name ?? source.customerName ?? source.display_name ?? source.name ?? params.customerName;
|
|
1168
|
+
return {
|
|
1169
|
+
...source,
|
|
1170
|
+
id: source.id ?? params.customerId,
|
|
1171
|
+
customer_id: source.customer_id ?? params.customerId,
|
|
1172
|
+
name: String(name || ""),
|
|
1173
|
+
customer_name: String(customerName || ""),
|
|
1174
|
+
country_calling_code: String(
|
|
1175
|
+
source.country_calling_code ?? source.countryCallingCode ?? params.countryCallingCode
|
|
1176
|
+
),
|
|
1177
|
+
phone: String(source.phone ?? params.phone),
|
|
1178
|
+
email: String(source.email ?? params.email)
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
810
1181
|
/**
|
|
811
1182
|
* 更新当前 tempOrder 的客户协议字段。
|
|
812
1183
|
*
|
|
813
|
-
* PaymentModal
|
|
1184
|
+
* PaymentModal 只需要修改订单里的客户事实;如果外部还有客户模块需要同步,
|
|
814
1185
|
* 应由调用方通过回调处理,不能把外部 UI 状态写进 tempOrder。
|
|
815
1186
|
*/
|
|
816
1187
|
updateTempOrderCustomer(customer) {
|
|
@@ -824,6 +1195,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
824
1195
|
);
|
|
825
1196
|
tempOrder.phone = String(customer.phone || "");
|
|
826
1197
|
tempOrder.email = String(customer.email || "");
|
|
1198
|
+
tempOrder.customer = this.buildTempOrderCustomer({
|
|
1199
|
+
source: customer,
|
|
1200
|
+
customerId: tempOrder.customer_id,
|
|
1201
|
+
customerName: tempOrder.customer_name,
|
|
1202
|
+
countryCallingCode: tempOrder.country_calling_code,
|
|
1203
|
+
phone: tempOrder.phone,
|
|
1204
|
+
email: tempOrder.email
|
|
1205
|
+
});
|
|
827
1206
|
this.persistTempOrder();
|
|
828
1207
|
return {
|
|
829
1208
|
customerId: tempOrder.customer_id,
|
|
@@ -838,11 +1217,20 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
838
1217
|
return;
|
|
839
1218
|
}
|
|
840
1219
|
const tempOrder = this.ensureTempOrder();
|
|
1220
|
+
const previousCustomerId = tempOrder.customer_id ?? null;
|
|
841
1221
|
tempOrder.customer_id = patch.customer_id || patch.id || null;
|
|
842
1222
|
tempOrder.customer_name = String(patch.customer_name || "");
|
|
843
1223
|
tempOrder.country_calling_code = String(patch.country_calling_code || "");
|
|
844
1224
|
tempOrder.phone = String(patch.phone || "");
|
|
845
1225
|
tempOrder.email = String(patch.email || "");
|
|
1226
|
+
tempOrder.customer = this.buildTempOrderCustomer({
|
|
1227
|
+
source: snapshot || null,
|
|
1228
|
+
customerId: tempOrder.customer_id,
|
|
1229
|
+
customerName: tempOrder.customer_name,
|
|
1230
|
+
countryCallingCode: tempOrder.country_calling_code,
|
|
1231
|
+
phone: tempOrder.phone,
|
|
1232
|
+
email: tempOrder.email
|
|
1233
|
+
});
|
|
846
1234
|
if (snapshot !== void 0) {
|
|
847
1235
|
const extend = this.ensureExtend(tempOrder);
|
|
848
1236
|
if (snapshot === null)
|
|
@@ -850,12 +1238,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
850
1238
|
else
|
|
851
1239
|
extend.customerSnapshot = (0, import_lodash_es.cloneDeep)(snapshot);
|
|
852
1240
|
}
|
|
1241
|
+
const nextCustomerId = tempOrder.customer_id ?? null;
|
|
1242
|
+
if (String(previousCustomerId ?? "") !== String(nextCustomerId ?? "")) {
|
|
1243
|
+
(0, import_utils.clearTempOrderHolderAssignments)(tempOrder);
|
|
1244
|
+
}
|
|
853
1245
|
this.persistTempOrder();
|
|
854
|
-
this.
|
|
1246
|
+
this.saveDraftInBackground();
|
|
1247
|
+
if (String(previousCustomerId ?? "") !== String(nextCustomerId ?? "")) {
|
|
1248
|
+
this.emitOrderCustomerChange();
|
|
1249
|
+
}
|
|
855
1250
|
}
|
|
856
1251
|
getOrderCustomer() {
|
|
857
1252
|
const tempOrder = this.store.tempOrder;
|
|
858
|
-
if (!tempOrder || tempOrder.customer_id
|
|
1253
|
+
if (!tempOrder || !tempOrder.customer_id) {
|
|
859
1254
|
return null;
|
|
860
1255
|
}
|
|
861
1256
|
return {
|
|
@@ -873,14 +1268,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
873
1268
|
}
|
|
874
1269
|
clearOrderCustomer() {
|
|
875
1270
|
const tempOrder = this.ensureTempOrder();
|
|
1271
|
+
(0, import_utils.clearTempOrderHolderAssignments)(tempOrder);
|
|
876
1272
|
tempOrder.customer_id = null;
|
|
877
1273
|
tempOrder.customer_name = "";
|
|
878
1274
|
tempOrder.country_calling_code = "";
|
|
879
1275
|
tempOrder.phone = "";
|
|
880
1276
|
tempOrder.email = "";
|
|
1277
|
+
tempOrder.customer = null;
|
|
881
1278
|
if (tempOrder._extend)
|
|
882
1279
|
delete tempOrder._extend.customerSnapshot;
|
|
883
1280
|
this.persistTempOrder();
|
|
1281
|
+
this.saveDraftInBackground();
|
|
884
1282
|
this.core.effects.emit(import_types.OrderHooks.OnOrderCustomerChange, null);
|
|
885
1283
|
}
|
|
886
1284
|
emitOrderCustomerChange() {
|
|
@@ -920,10 +1318,20 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
920
1318
|
}
|
|
921
1319
|
/** 追加单个支付项,并立即持久化当前 tempOrder。 */
|
|
922
1320
|
addOrderPayment(payment) {
|
|
1321
|
+
this.logInfo("addOrderPayment", {
|
|
1322
|
+
payment
|
|
1323
|
+
});
|
|
923
1324
|
const tempOrder = this.ensureTempOrder();
|
|
924
|
-
const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([
|
|
1325
|
+
const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([
|
|
1326
|
+
this.normalizePaymentSource(payment, { defaultPaid: true })
|
|
1327
|
+
]);
|
|
925
1328
|
tempOrder.payments = [...tempOrder.payments || [], ...mapped];
|
|
926
1329
|
this.persistTempOrder();
|
|
1330
|
+
void this.recalculateSummary({ createIfMissing: true }).catch((error) => {
|
|
1331
|
+
this.logError("recalculate summary after addOrderPayment failed", {
|
|
1332
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1333
|
+
});
|
|
1334
|
+
});
|
|
927
1335
|
return tempOrder.payments;
|
|
928
1336
|
}
|
|
929
1337
|
/**
|
|
@@ -989,14 +1397,24 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
989
1397
|
*/
|
|
990
1398
|
updateVoucherOrderPayments(payments) {
|
|
991
1399
|
const tempOrder = this.ensureTempOrder();
|
|
992
|
-
const mappedVouchers = (0, import_utils.mapPaymentItemsToOrderPayments)(
|
|
993
|
-
|
|
994
|
-
|
|
1400
|
+
const mappedVouchers = (0, import_utils.mapPaymentItemsToOrderPayments)(
|
|
1401
|
+
payments.map(
|
|
1402
|
+
(payment) => this.normalizePaymentSource(payment, { defaultPaid: false })
|
|
1403
|
+
)
|
|
1404
|
+
).filter((payment) => {
|
|
1405
|
+
return payment.voucher_id !== void 0 && Number(payment.voucher_id) !== 0;
|
|
1406
|
+
});
|
|
995
1407
|
const nonVoucherPayments = (tempOrder.payments || []).filter((payment) => {
|
|
996
1408
|
return payment.voucher_id === void 0 || Number(payment.voucher_id) === 0;
|
|
997
1409
|
});
|
|
998
1410
|
tempOrder.payments = [...nonVoucherPayments, ...mappedVouchers];
|
|
1411
|
+
this.updateTempOrderPaymentStatus(tempOrder);
|
|
999
1412
|
this.persistTempOrder();
|
|
1413
|
+
void this.recalculateSummary({ createIfMissing: true }).catch((error) => {
|
|
1414
|
+
this.logError("recalculate summary after updateVoucherOrderPayments failed", {
|
|
1415
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1416
|
+
});
|
|
1417
|
+
});
|
|
1000
1418
|
return tempOrder.payments;
|
|
1001
1419
|
}
|
|
1002
1420
|
async shouldMergeProductToOrder(params) {
|
|
@@ -1026,6 +1444,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1026
1444
|
productToAdd.product_bundle
|
|
1027
1445
|
);
|
|
1028
1446
|
const normalizedIncoming = (0, import_utils3.normalizeOrderProduct)(productToAdd);
|
|
1447
|
+
normalizedIncoming.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1448
|
+
normalizedIncoming.discount_list
|
|
1449
|
+
);
|
|
1029
1450
|
const hasIncomingGoodPass = this.hasGoodPassDiscount(
|
|
1030
1451
|
normalizedIncoming
|
|
1031
1452
|
);
|
|
@@ -1082,6 +1503,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1082
1503
|
unique_identification_number: targetUid
|
|
1083
1504
|
}
|
|
1084
1505
|
});
|
|
1506
|
+
normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1507
|
+
normalizedProduct.discount_list
|
|
1508
|
+
);
|
|
1085
1509
|
tempOrder.products[matchedIndex] = {
|
|
1086
1510
|
...targetProduct,
|
|
1087
1511
|
...normalizedProduct,
|
|
@@ -1104,6 +1528,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1104
1528
|
if (linked) {
|
|
1105
1529
|
tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
|
|
1106
1530
|
}
|
|
1531
|
+
await this.applyPromotion();
|
|
1107
1532
|
this.applyDiscount();
|
|
1108
1533
|
await this.recalculateSummary({ createIfMissing: true });
|
|
1109
1534
|
this.persistTempOrder();
|
|
@@ -1127,15 +1552,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1127
1552
|
(item) => (item == null ? void 0 : item.type) === "good_pass" || (item == null ? void 0 : item.tag) === "good_pass"
|
|
1128
1553
|
);
|
|
1129
1554
|
}
|
|
1130
|
-
async
|
|
1131
|
-
var _a, _b, _c, _d, _e;
|
|
1555
|
+
async updateOrderProduct(params) {
|
|
1556
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1132
1557
|
const {
|
|
1133
1558
|
product_id,
|
|
1134
1559
|
product_variant_id,
|
|
1135
1560
|
updates,
|
|
1136
1561
|
unique_identification_number,
|
|
1562
|
+
identity_key,
|
|
1137
1563
|
product_option_item,
|
|
1138
|
-
product_bundle
|
|
1564
|
+
product_bundle,
|
|
1565
|
+
booking
|
|
1139
1566
|
} = params;
|
|
1140
1567
|
const tempOrder = this.ensureTempOrder();
|
|
1141
1568
|
const identityLookup = {
|
|
@@ -1144,12 +1571,30 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1144
1571
|
};
|
|
1145
1572
|
if (unique_identification_number !== void 0) {
|
|
1146
1573
|
identityLookup.unique_identification_number = unique_identification_number;
|
|
1574
|
+
if (identity_key === void 0) {
|
|
1575
|
+
identityLookup.identity_key = unique_identification_number;
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
if (identity_key !== void 0) {
|
|
1579
|
+
identityLookup.identity_key = identity_key;
|
|
1147
1580
|
}
|
|
1148
1581
|
if (product_option_item !== void 0)
|
|
1149
1582
|
identityLookup.product_option_item = product_option_item;
|
|
1150
1583
|
if (product_bundle !== void 0)
|
|
1151
1584
|
identityLookup.product_bundle = product_bundle;
|
|
1152
|
-
|
|
1585
|
+
let productIndex = -1;
|
|
1586
|
+
if (unique_identification_number !== void 0) {
|
|
1587
|
+
const targetUid = String(unique_identification_number);
|
|
1588
|
+
productIndex = tempOrder.products.findIndex((item) => {
|
|
1589
|
+
var _a2;
|
|
1590
|
+
return String(
|
|
1591
|
+
((_a2 = item.metadata) == null ? void 0 : _a2.unique_identification_number) || item.unique_identification_number || ""
|
|
1592
|
+
) === targetUid;
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
if (productIndex === -1) {
|
|
1596
|
+
productIndex = (0, import_utils3.getProductIdentityIndex)(tempOrder.products, identityLookup);
|
|
1597
|
+
}
|
|
1153
1598
|
if (productIndex === -1) {
|
|
1154
1599
|
throw new Error("[Order] 目标商品不存在,无法更新");
|
|
1155
1600
|
}
|
|
@@ -1176,28 +1621,178 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1176
1621
|
delete nextProduct.metadata.main_product_original_price;
|
|
1177
1622
|
delete nextProduct.metadata.price_schema_version;
|
|
1178
1623
|
}
|
|
1179
|
-
|
|
1624
|
+
let normalizedProduct = (0, import_utils3.normalizeOrderProduct)(nextProduct);
|
|
1625
|
+
normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1626
|
+
normalizedProduct.discount_list
|
|
1627
|
+
);
|
|
1628
|
+
if (booking) {
|
|
1629
|
+
const productUid = String(
|
|
1630
|
+
((_e = normalizedProduct.metadata) == null ? void 0 : _e.unique_identification_number) || ((_f = targetProduct.metadata) == null ? void 0 : _f.unique_identification_number) || unique_identification_number || (0, import_utils.createUuidV4)()
|
|
1631
|
+
);
|
|
1632
|
+
normalizedProduct.metadata = {
|
|
1633
|
+
...normalizedProduct.metadata || {},
|
|
1634
|
+
unique_identification_number: productUid
|
|
1635
|
+
};
|
|
1636
|
+
const linked = this.createLinkedProductAndBooking({
|
|
1637
|
+
product: {
|
|
1638
|
+
...normalizedProduct,
|
|
1639
|
+
unique_identification_number: productUid
|
|
1640
|
+
},
|
|
1641
|
+
booking
|
|
1642
|
+
});
|
|
1643
|
+
this.removeLinkedBookingsForProduct(tempOrder, targetProduct);
|
|
1644
|
+
normalizedProduct = {
|
|
1645
|
+
...normalizedProduct,
|
|
1646
|
+
booking_uid: linked.bookingUid,
|
|
1647
|
+
metadata: {
|
|
1648
|
+
...normalizedProduct.metadata || {},
|
|
1649
|
+
booking_uid: linked.bookingUid,
|
|
1650
|
+
unique_identification_number: productUid
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
tempOrder.bookings = [...tempOrder.bookings || [], linked.booking];
|
|
1654
|
+
}
|
|
1655
|
+
tempOrder.products[productIndex] = normalizedProduct;
|
|
1180
1656
|
this.captureProductRuntime(
|
|
1181
1657
|
tempOrder,
|
|
1182
1658
|
updates,
|
|
1183
1659
|
tempOrder.products[productIndex],
|
|
1184
|
-
(
|
|
1660
|
+
(_g = tempOrder.products[productIndex].metadata) == null ? void 0 : _g.unique_identification_number
|
|
1185
1661
|
);
|
|
1662
|
+
await this.applyPromotion();
|
|
1186
1663
|
this.applyDiscount();
|
|
1187
1664
|
await this.recalculateSummary({ createIfMissing: true });
|
|
1188
1665
|
this.persistTempOrder();
|
|
1189
1666
|
return tempOrder.products;
|
|
1190
1667
|
}
|
|
1191
|
-
async
|
|
1668
|
+
async updateOrderProductQuantity(params) {
|
|
1669
|
+
var _a;
|
|
1670
|
+
const {
|
|
1671
|
+
product_id,
|
|
1672
|
+
product_variant_id,
|
|
1673
|
+
num,
|
|
1674
|
+
unique_identification_number,
|
|
1675
|
+
identity_key,
|
|
1676
|
+
product_option_item,
|
|
1677
|
+
product_bundle
|
|
1678
|
+
} = params;
|
|
1192
1679
|
const tempOrder = this.ensureTempOrder();
|
|
1193
|
-
|
|
1194
|
-
|
|
1680
|
+
const identityLookup = {
|
|
1681
|
+
product_id,
|
|
1682
|
+
product_variant_id
|
|
1683
|
+
};
|
|
1684
|
+
if (unique_identification_number !== void 0) {
|
|
1685
|
+
identityLookup.unique_identification_number = unique_identification_number;
|
|
1686
|
+
if (identity_key === void 0) {
|
|
1687
|
+
identityLookup.identity_key = unique_identification_number;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
if (identity_key !== void 0)
|
|
1691
|
+
identityLookup.identity_key = identity_key;
|
|
1692
|
+
if (product_option_item !== void 0)
|
|
1693
|
+
identityLookup.product_option_item = product_option_item;
|
|
1694
|
+
if (product_bundle !== void 0)
|
|
1695
|
+
identityLookup.product_bundle = product_bundle;
|
|
1696
|
+
let productIndex = -1;
|
|
1697
|
+
if (unique_identification_number !== void 0) {
|
|
1698
|
+
const targetUid = String(unique_identification_number);
|
|
1699
|
+
productIndex = tempOrder.products.findIndex((item) => {
|
|
1700
|
+
var _a2;
|
|
1701
|
+
return String(
|
|
1702
|
+
((_a2 = item.metadata) == null ? void 0 : _a2.unique_identification_number) || item.unique_identification_number || ""
|
|
1703
|
+
) === targetUid;
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
if (productIndex === -1) {
|
|
1707
|
+
productIndex = (0, import_utils3.getProductIdentityIndex)(tempOrder.products, identityLookup);
|
|
1708
|
+
}
|
|
1709
|
+
if (productIndex === -1) {
|
|
1710
|
+
throw new Error("[Order] 目标商品不存在,无法更新数量");
|
|
1711
|
+
}
|
|
1712
|
+
const targetProduct = tempOrder.products[productIndex];
|
|
1713
|
+
const normalizedProduct = (0, import_utils3.normalizeOrderProduct)({
|
|
1714
|
+
...targetProduct,
|
|
1715
|
+
num: (0, import_utils3.getSafeProductNum)(num),
|
|
1716
|
+
metadata: {
|
|
1717
|
+
...targetProduct.metadata || {},
|
|
1718
|
+
unique_identification_number: ((_a = targetProduct.metadata) == null ? void 0 : _a.unique_identification_number) || unique_identification_number
|
|
1719
|
+
}
|
|
1720
|
+
});
|
|
1721
|
+
normalizedProduct.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
1722
|
+
normalizedProduct.discount_list
|
|
1195
1723
|
);
|
|
1724
|
+
tempOrder.products[productIndex] = normalizedProduct;
|
|
1725
|
+
await this.applyPromotion();
|
|
1196
1726
|
this.applyDiscount();
|
|
1197
1727
|
await this.recalculateSummary({ createIfMissing: true });
|
|
1198
1728
|
this.persistTempOrder();
|
|
1199
1729
|
return tempOrder.products;
|
|
1200
1730
|
}
|
|
1731
|
+
updateOrderBooking(params) {
|
|
1732
|
+
const { unique_identification_number, updates } = params;
|
|
1733
|
+
const tempOrder = this.ensureTempOrder();
|
|
1734
|
+
const bookingUid = String(unique_identification_number || "");
|
|
1735
|
+
const bookingIndex = this.findBookingIndexByUniqueIdentificationNumber(
|
|
1736
|
+
tempOrder,
|
|
1737
|
+
bookingUid
|
|
1738
|
+
);
|
|
1739
|
+
if (!bookingUid || bookingIndex === -1) {
|
|
1740
|
+
throw new Error("[Order] 目标 booking 不存在,无法更新");
|
|
1741
|
+
}
|
|
1742
|
+
const targetBooking = tempOrder.bookings[bookingIndex] || {};
|
|
1743
|
+
const nextBooking = {
|
|
1744
|
+
...targetBooking,
|
|
1745
|
+
...updates,
|
|
1746
|
+
metadata: {
|
|
1747
|
+
...targetBooking.metadata || {},
|
|
1748
|
+
...updates.metadata || {},
|
|
1749
|
+
unique_identification_number: bookingUid
|
|
1750
|
+
}
|
|
1751
|
+
};
|
|
1752
|
+
nextBooking.is_all = (0, import_utils.normalizeBookingIsAll)(nextBooking);
|
|
1753
|
+
nextBooking.sub_type = (0, import_utils.normalizeBookingSubType)(nextBooking);
|
|
1754
|
+
tempOrder.bookings[bookingIndex] = nextBooking;
|
|
1755
|
+
this.persistTempOrder();
|
|
1756
|
+
return tempOrder.bookings;
|
|
1757
|
+
}
|
|
1758
|
+
async removeProductFromOrder(identity) {
|
|
1759
|
+
const tempOrder = this.ensureTempOrder();
|
|
1760
|
+
const removedProducts = [];
|
|
1761
|
+
tempOrder.products = tempOrder.products.filter((item) => {
|
|
1762
|
+
const shouldRemove = (0, import_utils3.isIdentityMatch)(item, identity);
|
|
1763
|
+
if (shouldRemove)
|
|
1764
|
+
removedProducts.push(item);
|
|
1765
|
+
return !shouldRemove;
|
|
1766
|
+
});
|
|
1767
|
+
for (const product of removedProducts) {
|
|
1768
|
+
this.removeLinkedBookingsForProduct(tempOrder, product);
|
|
1769
|
+
}
|
|
1770
|
+
await this.applyPromotion();
|
|
1771
|
+
this.applyDiscount();
|
|
1772
|
+
await this.recalculateSummary({ createIfMissing: true });
|
|
1773
|
+
this.persistTempOrder();
|
|
1774
|
+
return tempOrder.products;
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* 仅清空购物车行(products / bookings),不重置整单。
|
|
1778
|
+
* 用于「仅清空商品」;客户、备注、支付等协议字段保持不变。
|
|
1779
|
+
*/
|
|
1780
|
+
async clearOrderCartLines() {
|
|
1781
|
+
const tempOrder = this.ensureTempOrder();
|
|
1782
|
+
tempOrder.products = [];
|
|
1783
|
+
tempOrder.bookings = [];
|
|
1784
|
+
if (tempOrder._extend && typeof tempOrder._extend === "object") {
|
|
1785
|
+
tempOrder._extend = {
|
|
1786
|
+
...tempOrder._extend,
|
|
1787
|
+
productsByUid: {}
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
await this.applyPromotion();
|
|
1791
|
+
this.applyDiscount();
|
|
1792
|
+
await this.recalculateSummary({ createIfMissing: true });
|
|
1793
|
+
this.persistTempOrder();
|
|
1794
|
+
return tempOrder;
|
|
1795
|
+
}
|
|
1201
1796
|
// ─── TempOrder: 提交 ───
|
|
1202
1797
|
/**
|
|
1203
1798
|
* 提交当前 Sales tempOrder。
|
|
@@ -1224,7 +1819,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1224
1819
|
...hasPaymentStatusOverride ? { payment_status: params == null ? void 0 : params.paymentStatus } : {},
|
|
1225
1820
|
...hasSmallTicketDataFlagOverride ? { small_ticket_data_flag: params == null ? void 0 : params.smallTicketDataFlag } : {}
|
|
1226
1821
|
};
|
|
1227
|
-
|
|
1822
|
+
const enhancedPayload = (params == null ? void 0 : params.enhancePayload) ? params.enhancePayload(nextPayload, ctx) : nextPayload;
|
|
1823
|
+
return enhancedPayload;
|
|
1228
1824
|
} : void 0;
|
|
1229
1825
|
const payload = (0, import_utils.buildSubmitPayload)({
|
|
1230
1826
|
tempOrder,
|
|
@@ -1241,6 +1837,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1241
1837
|
this.logInfo("submitTempOrder calling sales checkout", {
|
|
1242
1838
|
orderId: payload.order_id,
|
|
1243
1839
|
externalSaleNumber: payload.external_sale_number,
|
|
1840
|
+
requestUniqueIdempotencyToken: payload.request_unique_idempotency_token,
|
|
1244
1841
|
paymentStatus: payload.payment_status,
|
|
1245
1842
|
paymentsCount: ((_b = payload.payments) == null ? void 0 : _b.length) || 0,
|
|
1246
1843
|
smallTicketDataFlag: payload.small_ticket_data_flag
|
|
@@ -1327,21 +1924,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1327
1924
|
const mappedPayments = (0, import_utils.mapPaymentItemsToOrderPayments)(
|
|
1328
1925
|
params.payments || []
|
|
1329
1926
|
);
|
|
1330
|
-
tempOrder.payments = mappedPayments;
|
|
1331
|
-
if (params.paymentStatus)
|
|
1332
|
-
tempOrder.payment_status = params.paymentStatus;
|
|
1333
|
-
this.persistTempOrder();
|
|
1334
|
-
await this.saveDraft();
|
|
1335
1927
|
const paymentTotal = this.calculatePaymentTotal(mappedPayments);
|
|
1336
1928
|
const targetAmount = this.getPaymentTargetAmount();
|
|
1337
1929
|
const isFullyPaid = targetAmount.lte(0) ? false : paymentTotal.gte(targetAmount);
|
|
1338
|
-
|
|
1930
|
+
const paymentStatus = isFullyPaid ? params.paymentStatus || "paid" : "partially_paid";
|
|
1931
|
+
tempOrder.payments = mappedPayments;
|
|
1932
|
+
tempOrder.payment_status = paymentStatus;
|
|
1933
|
+
this.persistTempOrder();
|
|
1934
|
+
await this.saveDraft();
|
|
1935
|
+
if (!params.submitWhenPaid) {
|
|
1339
1936
|
return { isFullyPaid };
|
|
1340
1937
|
}
|
|
1938
|
+
if (this.store.syncState === "submitting") {
|
|
1939
|
+
return { isFullyPaid };
|
|
1940
|
+
}
|
|
1941
|
+
this.store.syncState = "submitting";
|
|
1942
|
+
const paymentSyncIdempotencyToken = this.buildPaymentSyncIdempotencyToken(
|
|
1943
|
+
tempOrder,
|
|
1944
|
+
mappedPayments
|
|
1945
|
+
);
|
|
1341
1946
|
const submitResult = await this.submitTempOrder({
|
|
1342
1947
|
payments: mappedPayments,
|
|
1343
|
-
paymentStatus
|
|
1344
|
-
smallTicketDataFlag: params.smallTicketDataFlag
|
|
1948
|
+
paymentStatus,
|
|
1949
|
+
smallTicketDataFlag: params.smallTicketDataFlag,
|
|
1950
|
+
channel: params.channel,
|
|
1951
|
+
enhancePayload: (payload) => {
|
|
1952
|
+
const nextPayload = {
|
|
1953
|
+
...payload,
|
|
1954
|
+
request_unique_idempotency_token: paymentSyncIdempotencyToken
|
|
1955
|
+
};
|
|
1956
|
+
return nextPayload;
|
|
1957
|
+
}
|
|
1345
1958
|
});
|
|
1346
1959
|
return { isFullyPaid, submitResult };
|
|
1347
1960
|
}
|
|
@@ -1689,6 +2302,33 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1689
2302
|
nextTempOrder[key] = raw[key];
|
|
1690
2303
|
}
|
|
1691
2304
|
});
|
|
2305
|
+
this.store.tempOrder = nextTempOrder;
|
|
2306
|
+
this.store.summary = raw.summary && typeof raw.summary === "object" ? { ...(0, import_utils.createEmptySummary)(), ...raw.summary } : (0, import_utils.createEmptySummary)();
|
|
2307
|
+
this.store.lastOrderInfo = raw.lastOrderInfo || raw;
|
|
2308
|
+
if (options == null ? void 0 : options.recalcOnHydrate) {
|
|
2309
|
+
await this.recalculateSummary({ createIfMissing: false });
|
|
2310
|
+
}
|
|
2311
|
+
this.persistTempOrder();
|
|
2312
|
+
return nextTempOrder;
|
|
2313
|
+
}
|
|
2314
|
+
normalizeTempOrderForRuntime(raw, options) {
|
|
2315
|
+
const nextTempOrder = {
|
|
2316
|
+
...this.createDefaultTempOrderInstance(),
|
|
2317
|
+
...raw || {}
|
|
2318
|
+
};
|
|
2319
|
+
delete nextTempOrder.summary;
|
|
2320
|
+
delete nextTempOrder.lastOrderInfo;
|
|
2321
|
+
delete nextTempOrder.discount_list;
|
|
2322
|
+
delete nextTempOrder.shop_id;
|
|
2323
|
+
delete nextTempOrder.create_date;
|
|
2324
|
+
delete nextTempOrder.total_amount;
|
|
2325
|
+
delete nextTempOrder.expect_amount;
|
|
2326
|
+
delete nextTempOrder.paid_amount;
|
|
2327
|
+
delete nextTempOrder.shop_note;
|
|
2328
|
+
delete nextTempOrder.start_time;
|
|
2329
|
+
delete nextTempOrder.tax_fee;
|
|
2330
|
+
delete nextTempOrder.total_refund_amount;
|
|
2331
|
+
delete nextTempOrder.holder_id;
|
|
1692
2332
|
nextTempOrder.metadata = raw.metadata && typeof raw.metadata === "object" ? { ...raw.metadata } : {};
|
|
1693
2333
|
nextTempOrder.holder = raw.holder && typeof raw.holder === "object" ? { ...raw.holder } : null;
|
|
1694
2334
|
nextTempOrder.products = Array.isArray(raw.products) ? raw.products.map((p) => this.normalizeHydratedOrderProduct(p)) : [];
|
|
@@ -1699,7 +2339,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1699
2339
|
})) : [];
|
|
1700
2340
|
nextTempOrder.payments = Array.isArray(raw.payments) ? raw.payments.map((p) => ({ ...p || {} })) : [];
|
|
1701
2341
|
nextTempOrder.surcharges = Array.isArray(raw.surcharges) ? raw.surcharges.map((s) => ({ ...s || {} })) : [];
|
|
1702
|
-
nextTempOrder.discount_list = Array.isArray(raw.discount_list) ? raw.discount_list.map((d) => ({ ...d || {} })) : [];
|
|
1703
2342
|
nextTempOrder.relation_forms = Array.isArray(raw.relation_forms) ? raw.relation_forms.map((f) => ({ ...f || {} })) : [];
|
|
1704
2343
|
nextTempOrder.contacts = Array.isArray(raw.contacts) ? raw.contacts.map((c) => ({ ...c || {} })) : [];
|
|
1705
2344
|
nextTempOrder.contacts_info = raw.contacts_info && typeof raw.contacts_info === "object" && !Array.isArray(raw.contacts_info) ? { ...raw.contacts_info } : null;
|
|
@@ -1707,14 +2346,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1707
2346
|
...raw._extend,
|
|
1708
2347
|
productsByUid: raw._extend.productsByUid || {}
|
|
1709
2348
|
} : { productsByUid: {} };
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
this.store.summary = raw.summary && typeof raw.summary === "object" ? { ...(0, import_utils.createEmptySummary)(), ...raw.summary } : (0, import_utils.createEmptySummary)();
|
|
1713
|
-
this.store.lastOrderInfo = raw.lastOrderInfo || raw;
|
|
1714
|
-
if (options == null ? void 0 : options.recalcOnHydrate) {
|
|
1715
|
-
await this.recalculateSummary({ createIfMissing: false });
|
|
2349
|
+
if ((options == null ? void 0 : options.ensureIdentity) !== false) {
|
|
2350
|
+
this.ensureExternalSaleNumber(nextTempOrder);
|
|
1716
2351
|
}
|
|
1717
|
-
this.persistTempOrder();
|
|
1718
2352
|
return nextTempOrder;
|
|
1719
2353
|
}
|
|
1720
2354
|
normalizeHydratedOrderProduct(product) {
|
|
@@ -1733,6 +2367,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
1733
2367
|
row.metadata.unique_identification_number = (0, import_utils.createUuidV4)();
|
|
1734
2368
|
}
|
|
1735
2369
|
const normalized = (0, import_utils3.normalizeOrderProduct)(row);
|
|
2370
|
+
normalized.discount_list = (0, import_utils.normalizeOrderProductDiscountList)(
|
|
2371
|
+
normalized.discount_list
|
|
2372
|
+
);
|
|
1736
2373
|
const result = {
|
|
1737
2374
|
...row,
|
|
1738
2375
|
...normalized,
|