@pisell/pisellos 2.2.313 → 2.2.315
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/index.d.ts +2 -0
- package/dist/index.js +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +74 -7
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +13 -0
- package/dist/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/dist/model/strategy/adapter/itemRule/type.js +10 -0
- package/dist/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/dist/modules/BookingContext/utils/productExtend.js +62 -18
- package/dist/modules/BookingContext/utils/resources.js +1 -1
- package/dist/modules/BusinessAvailability/index.d.ts +30 -0
- package/dist/modules/BusinessAvailability/index.js +204 -0
- package/dist/modules/Cart/index.js +4 -3
- package/dist/modules/Cart/types.d.ts +2 -0
- package/dist/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/dist/modules/Cart/utils/cartProduct.js +59 -32
- package/dist/modules/FulfillmentTiming/index.d.ts +11 -0
- package/dist/modules/FulfillmentTiming/index.js +407 -0
- package/dist/modules/FulfillmentTiming/types.d.ts +67 -0
- package/dist/modules/FulfillmentTiming/types.js +1 -0
- package/dist/modules/OpenData/types.d.ts +14 -0
- package/dist/modules/Order/index.d.ts +14 -2
- package/dist/modules/Order/index.js +856 -486
- package/dist/modules/Order/localEftposState.d.ts +13 -0
- package/dist/modules/Order/localEftposState.js +39 -0
- package/dist/modules/Order/pickupTiming.d.ts +46 -0
- package/dist/modules/Order/pickupTiming.js +53 -0
- package/dist/modules/Order/types.d.ts +30 -2
- package/dist/modules/Order/utils.js +25 -7
- package/dist/modules/Payment/index.js +9 -10
- package/dist/modules/Product/types.d.ts +11 -0
- package/dist/modules/ProductList/index.js +1 -1
- package/dist/modules/ResourcePlanner/planner.d.ts +2 -0
- package/dist/modules/ResourcePlanner/planner.js +332 -23
- package/dist/modules/ResourcePlanner/types.d.ts +29 -0
- package/dist/modules/Schedule/index.d.ts +8 -0
- package/dist/modules/Schedule/index.js +141 -39
- package/dist/modules/index.d.ts +1 -0
- package/dist/modules/index.js +1 -0
- package/dist/plugins/request.d.ts +7 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1536 -1309
- package/dist/server/modules/form/index.d.ts +19 -0
- package/dist/server/modules/form/index.js +205 -0
- package/dist/server/modules/form/types.d.ts +13 -0
- package/dist/server/modules/form/types.js +3 -0
- package/dist/server/modules/index.d.ts +3 -0
- package/dist/server/modules/index.js +4 -0
- package/dist/server/modules/order/index.d.ts +15 -0
- package/dist/server/modules/order/index.js +920 -688
- package/dist/server/modules/order/types.d.ts +1 -0
- package/dist/server/test.json +1 -1
- package/dist/server/utils/small-ticket.d.ts +1 -85
- package/dist/server/utils/small-ticket.js +2 -2542
- package/dist/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/dist/shared/payment/loadPaymentMethods.js +66 -0
- package/dist/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/dist/shared/receipt/customerInvoiceLanguages.js +60 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.js +184 -0
- package/dist/shared/receipt/small-ticket.d.ts +96 -0
- package/dist/shared/receipt/small-ticket.js +2751 -0
- package/dist/shared/receipt/templateVisibility.d.ts +23 -0
- package/dist/shared/receipt/templateVisibility.js +64 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/dist/shared/sales/loadSalesOrderSnapshot.js +21 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/dist/solution/BaseSales/fulfillmentItemRules.js +750 -0
- package/dist/solution/BaseSales/index.d.ts +39 -16
- package/dist/solution/BaseSales/index.js +1754 -1154
- package/dist/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/dist/solution/BaseSales/pickupTiming.js +616 -0
- package/dist/solution/BaseSales/types.d.ts +11 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/dist/solution/BookingByStep/index.d.ts +4 -2
- package/dist/solution/BookingByStep/index.js +8 -3
- package/dist/solution/BookingTicket/index.d.ts +8 -2
- package/dist/solution/BookingTicket/index.js +513 -436
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/dist/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/dist/solution/BookingTicket/utils/cartView.js +3 -1
- package/dist/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/dist/solution/OrderInvoicePreview/index.js +340 -0
- package/dist/solution/RegisterAndLogin/config.js +54 -11
- package/dist/solution/RegisterAndLogin/index.d.ts +2 -0
- package/dist/solution/RegisterAndLogin/index.js +1 -1
- package/dist/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/dist/solution/RegisterAndLogin/utils.js +36 -16
- package/dist/solution/Sales/index.js +1 -1
- package/dist/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/dist/solution/UnifiedBookingSales/businessAvailability.js +292 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/dist/solution/UnifiedBookingSales/index.js +1714 -905
- package/dist/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/dist/solution/VenueBooking/index.d.ts +15 -2
- package/dist/solution/VenueBooking/index.js +1062 -785
- package/dist/solution/VenueBooking/types.d.ts +2 -1
- package/dist/solution/VenueBooking/types.js +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +273 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +6 -3
- package/dist/solution/index.d.ts +1 -0
- package/dist/solution/index.js +2 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +21 -1
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +54 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +3 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +9 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +40 -1
- package/lib/model/strategy/adapter/itemRule/type.js +10 -0
- package/lib/modules/BookingContext/utils/productExtend.d.ts +7 -0
- package/lib/modules/BookingContext/utils/productExtend.js +45 -2
- package/lib/modules/BookingContext/utils/resources.js +1 -1
- package/lib/modules/BusinessAvailability/index.d.ts +30 -0
- package/lib/modules/BusinessAvailability/index.js +146 -0
- package/lib/modules/Cart/index.js +4 -2
- package/lib/modules/Cart/types.d.ts +2 -0
- package/lib/modules/Cart/utils/cartProduct.d.ts +3 -1
- package/lib/modules/Cart/utils/cartProduct.js +39 -20
- package/lib/modules/FulfillmentTiming/index.d.ts +11 -0
- package/lib/modules/FulfillmentTiming/index.js +359 -0
- package/lib/modules/FulfillmentTiming/types.d.ts +67 -0
- package/lib/modules/FulfillmentTiming/types.js +5 -0
- package/lib/modules/OpenData/types.d.ts +14 -0
- package/lib/modules/Order/index.d.ts +14 -2
- package/lib/modules/Order/index.js +240 -38
- package/lib/modules/Order/localEftposState.d.ts +13 -0
- package/lib/modules/Order/localEftposState.js +44 -0
- package/lib/modules/Order/pickupTiming.d.ts +46 -0
- package/lib/modules/Order/pickupTiming.js +61 -0
- package/lib/modules/Order/types.d.ts +30 -2
- package/lib/modules/Order/utils.js +21 -5
- package/lib/modules/Payment/index.js +3 -4
- package/lib/modules/Product/types.d.ts +11 -0
- package/lib/modules/ProductList/index.js +1 -1
- package/lib/modules/ResourcePlanner/planner.d.ts +2 -0
- package/lib/modules/ResourcePlanner/planner.js +252 -8
- package/lib/modules/ResourcePlanner/types.d.ts +29 -0
- package/lib/modules/Schedule/index.d.ts +8 -0
- package/lib/modules/Schedule/index.js +68 -12
- package/lib/modules/index.d.ts +1 -0
- package/lib/modules/index.js +11 -0
- package/lib/plugins/request.d.ts +7 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +158 -37
- package/lib/server/modules/form/index.d.ts +19 -0
- package/lib/server/modules/form/index.js +73 -0
- package/lib/server/modules/form/types.d.ts +13 -0
- package/lib/server/modules/form/types.js +9 -0
- package/lib/server/modules/index.d.ts +3 -0
- package/lib/server/modules/index.js +15 -1
- package/lib/server/modules/order/index.d.ts +15 -0
- package/lib/server/modules/order/index.js +114 -3
- package/lib/server/modules/order/types.d.ts +1 -0
- package/lib/server/test.json +1 -1
- package/lib/server/utils/small-ticket.d.ts +1 -85
- package/lib/server/utils/small-ticket.js +9 -2305
- package/lib/shared/payment/loadPaymentMethods.d.ts +9 -0
- package/lib/shared/payment/loadPaymentMethods.js +40 -0
- package/lib/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/lib/shared/receipt/customerInvoiceLanguages.js +58 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.d.ts +27 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.js +124 -0
- package/lib/shared/receipt/small-ticket.d.ts +96 -0
- package/lib/shared/receipt/small-ticket.js +2546 -0
- package/lib/shared/receipt/templateVisibility.d.ts +23 -0
- package/lib/shared/receipt/templateVisibility.js +63 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.d.ts +9 -0
- package/lib/shared/sales/loadSalesOrderSnapshot.js +22 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.d.ts +27 -0
- package/lib/solution/BaseSales/fulfillmentItemRules.js +259 -0
- package/lib/solution/BaseSales/index.d.ts +39 -16
- package/lib/solution/BaseSales/index.js +333 -31
- package/lib/solution/BaseSales/pickupTiming.d.ts +47 -0
- package/lib/solution/BaseSales/pickupTiming.js +290 -0
- package/lib/solution/BaseSales/types.d.ts +11 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +4 -2
- package/lib/solution/BookingByStep/index.js +7 -3
- package/lib/solution/BookingTicket/index.d.ts +8 -2
- package/lib/solution/BookingTicket/index.js +65 -6
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +0 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -1
- package/lib/solution/BookingTicket/utils/cartView.js +3 -1
- package/lib/solution/OrderInvoicePreview/index.d.ts +66 -0
- package/lib/solution/OrderInvoicePreview/index.js +246 -0
- package/lib/solution/RegisterAndLogin/config.js +57 -11
- package/lib/solution/RegisterAndLogin/index.d.ts +2 -0
- package/lib/solution/RegisterAndLogin/index.js +9 -1
- package/lib/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/lib/solution/RegisterAndLogin/utils.js +24 -17
- package/lib/solution/Sales/index.js +1 -1
- package/lib/solution/UnifiedBookingSales/businessAvailability.d.ts +27 -0
- package/lib/solution/UnifiedBookingSales/businessAvailability.js +138 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +36 -4
- package/lib/solution/UnifiedBookingSales/index.js +561 -74
- package/lib/solution/UnifiedBookingSales/types.d.ts +16 -2
- package/lib/solution/VenueBooking/index.d.ts +15 -2
- package/lib/solution/VenueBooking/index.js +243 -96
- package/lib/solution/VenueBooking/types.d.ts +2 -1
- package/lib/solution/VenueBooking/types.js +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +224 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +5 -2
- package/lib/solution/index.d.ts +1 -0
- package/lib/solution/index.js +11 -0
- package/package.json +1 -1
|
@@ -4,11 +4,20 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.OrderModule = void 0;
|
|
7
|
+
Object.defineProperty(exports, "isFulfillmentTimingBooking", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return _pickupTiming.isFulfillmentTimingBooking;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
var _loadSalesOrderSnapshot = require("../../shared/sales/loadSalesOrderSnapshot");
|
|
14
|
+
var _localEftposState = require("./localEftposState");
|
|
7
15
|
var _BaseModule = require("../BaseModule");
|
|
8
16
|
var _types = require("./types");
|
|
9
17
|
var _utils = require("./utils");
|
|
10
18
|
var _utils2 = require("../Product/utils");
|
|
11
19
|
var _weighedProduct = require("./utils/weighedProduct");
|
|
20
|
+
var _pickupTiming = require("./pickupTiming");
|
|
12
21
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
13
22
|
var _availability = require("../Discount/availability");
|
|
14
23
|
var _osPrivatePayload = require("../../utils/os-private-payload");
|
|
@@ -433,6 +442,29 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
433
442
|
this.otherParams = otherParams;
|
|
434
443
|
}
|
|
435
444
|
|
|
445
|
+
/** Internal intent boundary shared with asynchronous scanner/detail flows. */
|
|
446
|
+
createCartIntentCommitGuard(action, tempOrder = this.store.tempOrder) {
|
|
447
|
+
const hook = this.orderHooks?.beforeCartIntentCommit;
|
|
448
|
+
if (!hook) return () => {};
|
|
449
|
+
const getScope = this.orderHooks?.getCartIntentScope;
|
|
450
|
+
const scope = getScope?.();
|
|
451
|
+
const otherParams = this.otherParams;
|
|
452
|
+
let committed = false;
|
|
453
|
+
return () => {
|
|
454
|
+
if (this.store.tempOrder !== tempOrder || this.otherParams !== otherParams || this.orderHooks?.beforeCartIntentCommit !== hook || this.orderHooks?.getCartIntentScope !== getScope || getScope?.() !== scope) {
|
|
455
|
+
throw new Error('[Order] Cart intent belongs to a previous order or business');
|
|
456
|
+
}
|
|
457
|
+
// Derived gifts, discounts and persistence belong to the accepted intent,
|
|
458
|
+
// but an asynchronous continuation must never target a different cart.
|
|
459
|
+
if (committed) return;
|
|
460
|
+
hook({
|
|
461
|
+
action,
|
|
462
|
+
tempOrder
|
|
463
|
+
});
|
|
464
|
+
committed = true;
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
436
468
|
/** PC/H5 属于在线店铺;其它或缺失平台统一沿用 POS 行为。 */
|
|
437
469
|
isOnlineStorePlatform() {
|
|
438
470
|
const platform = String(this.otherParams?.platform || '').trim().toLowerCase();
|
|
@@ -661,6 +693,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
661
693
|
});
|
|
662
694
|
}
|
|
663
695
|
async scanCode(code, customerId) {
|
|
696
|
+
const beforeCommit = this.createCartIntentCommitGuard('scan_promotion');
|
|
664
697
|
if (this.isActiveVirtualSettlementOrder(this.store.tempOrder)) {
|
|
665
698
|
return {
|
|
666
699
|
type: 'clientCalc',
|
|
@@ -708,6 +741,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
708
741
|
}));
|
|
709
742
|
const currentSelected = this.getDiscountList().filter(n => n.isSelected);
|
|
710
743
|
if (currentSelected.length && currentSelected.some(n => withScanList.some(m => m.id === n.id))) {
|
|
744
|
+
beforeCommit();
|
|
711
745
|
await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
|
|
712
746
|
return {
|
|
713
747
|
type: 'clientCalc',
|
|
@@ -741,6 +775,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
741
775
|
const normalizedNewDiscountList = newDiscountList ? markScannedDiscounts(newDiscountList, withScanList) : undefined;
|
|
742
776
|
let resolvedDiscountList = normalizedNewDiscountList || this.getDiscountList();
|
|
743
777
|
if (isAvailable && normalizedNewDiscountList) {
|
|
778
|
+
beforeCommit();
|
|
744
779
|
await this.store.discount?.setDiscountList(normalizedNewDiscountList);
|
|
745
780
|
// 实际写回商品时沿用扫码试算的优先级,避免旧商品行的选卡覆盖本次扫码。
|
|
746
781
|
this.applyDiscount({
|
|
@@ -749,6 +784,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
749
784
|
await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
|
|
750
785
|
resolvedDiscountList = this.getDiscountList();
|
|
751
786
|
} else if (shouldRetainForLater) {
|
|
787
|
+
beforeCommit();
|
|
752
788
|
// 只合并本次识别的卡券;不把试算产生的其他选券状态写回订单。
|
|
753
789
|
const retainedDiscounts = new Map(this.getDiscountList().map(discount => [String(discount.id), discount]));
|
|
754
790
|
evaluatedScannedDiscounts.forEach(discount => {
|
|
@@ -878,7 +914,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
878
914
|
* - 不主动调用 applyDiscount / recalculateSummary,调用方负责跟进;
|
|
879
915
|
* - 返回的 payload 只能在 applyDiscount(商品写路径还需 summary/persist)完成后发布。
|
|
880
916
|
*/
|
|
881
|
-
async evaluatePromotion() {
|
|
917
|
+
async evaluatePromotion(options) {
|
|
918
|
+
if (options?.isCurrentOrder && !options.isCurrentOrder()) return null;
|
|
882
919
|
if (this.isApplyingPromotion || this.isEmittingPromotionApplied) {
|
|
883
920
|
return null;
|
|
884
921
|
}
|
|
@@ -939,6 +976,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
939
976
|
continue;
|
|
940
977
|
}
|
|
941
978
|
}
|
|
979
|
+
const giftMutationBaseline = options?.isCurrentOrder ? (0, _lodashEs.cloneDeep)({
|
|
980
|
+
products: tempOrder.products,
|
|
981
|
+
bookings: tempOrder.bookings
|
|
982
|
+
}) : null;
|
|
942
983
|
try {
|
|
943
984
|
const giftResult = await this.giftSelectResolver({
|
|
944
985
|
strategyId: addAction.strategyId,
|
|
@@ -947,6 +988,11 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
947
988
|
giftOptions: addAction.giftOptions,
|
|
948
989
|
sourceProductIds: addAction.sourceProductIds
|
|
949
990
|
});
|
|
991
|
+
if (options?.isCurrentOrder && !options.isCurrentOrder()) return null;
|
|
992
|
+
if (options?.isCurrentOrder && !(0, _lodashEs.isEqual)({
|
|
993
|
+
products: tempOrder.products,
|
|
994
|
+
bookings: tempOrder.bookings
|
|
995
|
+
}, giftMutationBaseline)) return null;
|
|
950
996
|
const giftProducts = Array.isArray(giftResult) ? giftResult : giftResult?.products;
|
|
951
997
|
const giftBookings = Array.isArray(giftResult) ? [] : giftResult?.bookings || [];
|
|
952
998
|
if (Array.isArray(giftProducts) && giftProducts.length > 0) {
|
|
@@ -967,12 +1013,18 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
967
1013
|
}
|
|
968
1014
|
}
|
|
969
1015
|
} catch (error) {
|
|
1016
|
+
if (options?.isCurrentOrder && !options.isCurrentOrder()) return null;
|
|
1017
|
+
if (options?.isCurrentOrder && !(0, _lodashEs.isEqual)({
|
|
1018
|
+
products: tempOrder.products,
|
|
1019
|
+
bookings: tempOrder.bookings
|
|
1020
|
+
}, giftMutationBaseline)) return null;
|
|
970
1021
|
// 用户取消 / 选择失败 → 视为放弃本次新增
|
|
971
1022
|
console.warn('[OrderModule] giftSelectResolver rejected, skip add gift', addAction.strategyId, error);
|
|
972
1023
|
}
|
|
973
1024
|
}
|
|
974
1025
|
}
|
|
975
1026
|
}
|
|
1027
|
+
if (options?.isCurrentOrder && !options.isCurrentOrder()) return null;
|
|
976
1028
|
tempOrder.products = result.products;
|
|
977
1029
|
this.lastUnfulfilledPromotions = result.unfulfilledPromotions;
|
|
978
1030
|
this.lastGiftActions = result.giftActions;
|
|
@@ -2275,6 +2327,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2275
2327
|
const bookingByBookingUid = new Map();
|
|
2276
2328
|
bookings.forEach(booking => {
|
|
2277
2329
|
if (!booking || typeof booking !== 'object') return;
|
|
2330
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(booking)) return;
|
|
2278
2331
|
const productUid = booking.product_uid || booking.metadata?.product_uid;
|
|
2279
2332
|
if (productUid !== undefined && productUid !== null && String(productUid) !== '') {
|
|
2280
2333
|
bookingByProductUid.set(String(productUid), booking);
|
|
@@ -2325,6 +2378,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2325
2378
|
let baseHolder = null;
|
|
2326
2379
|
const seen = new Set();
|
|
2327
2380
|
for (const booking of tempOrder.bookings || []) {
|
|
2381
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(booking)) continue;
|
|
2328
2382
|
const holder = booking?.holder && typeof booking.holder === 'object' ? booking.holder : null;
|
|
2329
2383
|
if (!baseHolder && holder) {
|
|
2330
2384
|
baseHolder = holder;
|
|
@@ -2365,7 +2419,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2365
2419
|
* this.syncTempOrderHolderFromBookings(tempOrder);
|
|
2366
2420
|
*/
|
|
2367
2421
|
syncTempOrderHolderFromBookings(tempOrder) {
|
|
2368
|
-
const bookings = tempOrder.bookings || [];
|
|
2422
|
+
const bookings = (tempOrder.bookings || []).filter(booking => !(0, _pickupTiming.isFulfillmentTimingBooking)(booking));
|
|
2369
2423
|
const hasHolderSource = bookings.some(booking => {
|
|
2370
2424
|
return booking?.holder !== undefined || booking?.metadata?.holder_id !== undefined;
|
|
2371
2425
|
});
|
|
@@ -2390,6 +2444,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2390
2444
|
const bookingUid = product?.booking_uid || product?.metadata?.booking_uid;
|
|
2391
2445
|
if (!productUid && !bookingUid) return;
|
|
2392
2446
|
tempOrder.bookings = (tempOrder.bookings || []).filter(booking => {
|
|
2447
|
+
if ((0, _pickupTiming.isFulfillmentTimingBooking)(booking)) return true;
|
|
2393
2448
|
const currentBookingUid = this.getBookingUniqueIdentificationNumber(booking);
|
|
2394
2449
|
if (bookingUid && currentBookingUid === String(bookingUid)) return false;
|
|
2395
2450
|
if (productUid && String(booking?.product_uid || '') === String(productUid)) return false;
|
|
@@ -2431,6 +2486,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2431
2486
|
return shouldUseManualDepositOverride ? nextSummary : this.applyLastOrderDepositSnapshot(tempOrder, nextSummary);
|
|
2432
2487
|
}
|
|
2433
2488
|
async recalculateSummary(options) {
|
|
2489
|
+
if (options?.isCurrentOrder && !options.isCurrentOrder()) return null;
|
|
2434
2490
|
const tempOrder = options?.createIfMissing ? this.ensureTempOrder() : this.store.tempOrder;
|
|
2435
2491
|
if (!tempOrder) return null;
|
|
2436
2492
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
@@ -2440,7 +2496,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2440
2496
|
const snapshotSummary = shouldReuseOriginalSnapshot ? this.restoreOriginalSnapshotIfProductsUnchanged(tempOrder, originalSnapshot) : null;
|
|
2441
2497
|
if (snapshotSummary) return snapshotSummary;
|
|
2442
2498
|
const shouldFullRecalculateFromSnapshot = Boolean(originalSnapshot);
|
|
2443
|
-
const summaryProducts = shouldFullRecalculateFromSnapshot ? (0, _lodashEs.cloneDeep)(tempOrder.products || []) : tempOrder.products;
|
|
2499
|
+
const summaryProducts = shouldFullRecalculateFromSnapshot || options?.isCurrentOrder ? (0, _lodashEs.cloneDeep)(tempOrder.products || []) : tempOrder.products;
|
|
2444
2500
|
if (shouldFullRecalculateFromSnapshot) {
|
|
2445
2501
|
this.clearPersistedAmountFieldsForFullRecalc(summaryProducts || []);
|
|
2446
2502
|
}
|
|
@@ -2478,6 +2534,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2478
2534
|
});
|
|
2479
2535
|
return this.store.summary;
|
|
2480
2536
|
}
|
|
2537
|
+
const summaryMutationBaseline = options?.isCurrentOrder ? (0, _lodashEs.cloneDeep)({
|
|
2538
|
+
tempOrder,
|
|
2539
|
+
summary: this.store.summary
|
|
2540
|
+
}) : null;
|
|
2481
2541
|
const salesSummaryResult = await salesSummary.getSummary({
|
|
2482
2542
|
products: summaryProducts,
|
|
2483
2543
|
isPriceIncludeTax: tempOrder.is_price_include_tax,
|
|
@@ -2487,7 +2547,12 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2487
2547
|
channel: this.otherParams.channel
|
|
2488
2548
|
} : {})
|
|
2489
2549
|
});
|
|
2490
|
-
if (
|
|
2550
|
+
if (options?.isCurrentOrder && !options.isCurrentOrder()) return null;
|
|
2551
|
+
if (options?.isCurrentOrder && !(0, _lodashEs.isEqual)({
|
|
2552
|
+
tempOrder,
|
|
2553
|
+
summary: this.store.summary
|
|
2554
|
+
}, summaryMutationBaseline)) return null;
|
|
2555
|
+
if (shouldFullRecalculateFromSnapshot || options?.isCurrentOrder) {
|
|
2491
2556
|
tempOrder.products = summaryProducts;
|
|
2492
2557
|
}
|
|
2493
2558
|
this.syncSummaryProductMetadata(tempOrder.products || []);
|
|
@@ -2803,10 +2868,33 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2803
2868
|
});
|
|
2804
2869
|
}
|
|
2805
2870
|
updateTempOrderServiceType(serviceType) {
|
|
2871
|
+
if (serviceType !== 'pick_up') {
|
|
2872
|
+
const tempOrder = this.ensureTempOrder();
|
|
2873
|
+
tempOrder.bookings = (tempOrder.bookings || []).filter(booking => !(0, _pickupTiming.isFulfillmentTimingBooking)(booking));
|
|
2874
|
+
}
|
|
2806
2875
|
return this.updateTempOrderShopServiceData({
|
|
2807
2876
|
service_type: serviceType
|
|
2808
2877
|
});
|
|
2809
2878
|
}
|
|
2879
|
+
getPickupTimingBooking() {
|
|
2880
|
+
return (this.store.tempOrder?.bookings || []).find(_pickupTiming.isFulfillmentTimingBooking) || null;
|
|
2881
|
+
}
|
|
2882
|
+
setPickupTimingBooking(input) {
|
|
2883
|
+
const tempOrder = this.ensureTempOrder();
|
|
2884
|
+
const bookings = tempOrder.bookings || [];
|
|
2885
|
+
const firstIndex = bookings.findIndex(_pickupTiming.isFulfillmentTimingBooking);
|
|
2886
|
+
const nextBooking = (0, _pickupTiming.buildPickupTimingBooking)(input, bookings[firstIndex]);
|
|
2887
|
+
// Keep the first row's identity and position; repair duplicate marked rows only.
|
|
2888
|
+
tempOrder.bookings = firstIndex === -1 ? [...bookings, nextBooking] : bookings.flatMap((booking, index) => index === firstIndex ? [nextBooking] : (0, _pickupTiming.isFulfillmentTimingBooking)(booking) ? [] : [booking]);
|
|
2889
|
+
this.notifyTempOrderChanged();
|
|
2890
|
+
return nextBooking;
|
|
2891
|
+
}
|
|
2892
|
+
clearPickupTimingBooking() {
|
|
2893
|
+
const tempOrder = this.store.tempOrder;
|
|
2894
|
+
if (!tempOrder?.bookings?.some(_pickupTiming.isFulfillmentTimingBooking)) return;
|
|
2895
|
+
tempOrder.bookings = tempOrder.bookings.filter(booking => !(0, _pickupTiming.isFulfillmentTimingBooking)(booking));
|
|
2896
|
+
this.notifyTempOrderChanged();
|
|
2897
|
+
}
|
|
2810
2898
|
updateTempOrderContactsInfo(contactsInfo) {
|
|
2811
2899
|
const tempOrder = this.ensureTempOrder();
|
|
2812
2900
|
tempOrder.contacts_info = contactsInfo && typeof contactsInfo === 'object' && !Array.isArray(contactsInfo) ? contactsInfo : null;
|
|
@@ -3086,6 +3174,18 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3086
3174
|
const matchMode = options.matchBy === 'compat' || options.matchBy === 'legacy' ? 'compat' : 'payment_number';
|
|
3087
3175
|
const matchedPayment = (0, _paymentUtils.resolveOrderPaymentIdentity)(tempOrder.payments || [], identity, matchMode);
|
|
3088
3176
|
if (!matchedPayment) {
|
|
3177
|
+
try {
|
|
3178
|
+
void Promise.resolve(this.logger?.addLog?.({
|
|
3179
|
+
type: 'warning',
|
|
3180
|
+
title: '[PaymentTrace] payment-missing',
|
|
3181
|
+
metadata: {
|
|
3182
|
+
moduleName: this.name,
|
|
3183
|
+
saleId: tempOrder.external_sale_number,
|
|
3184
|
+
paymentNumber: identity,
|
|
3185
|
+
currentPaymentNumbers: (tempOrder.payments || []).map(p => p.payment_number)
|
|
3186
|
+
}
|
|
3187
|
+
})).catch(() => {});
|
|
3188
|
+
} catch {/* 日志失败不影响原异常。 */}
|
|
3089
3189
|
throw new Error(`未找到支付项: ${identity}`);
|
|
3090
3190
|
}
|
|
3091
3191
|
let updatedPayment = null;
|
|
@@ -3393,20 +3493,30 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3393
3493
|
* await this.finalizeProductOrderMutation(tempOrder);
|
|
3394
3494
|
*/
|
|
3395
3495
|
async finalizeProductOrderMutation(tempOrder, options) {
|
|
3496
|
+
const isCurrentOrder = options?.isCurrentOrder;
|
|
3497
|
+
if (isCurrentOrder && !isCurrentOrder()) return;
|
|
3396
3498
|
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
3397
3499
|
this.prepareVirtualSettlementTempOrder(tempOrder);
|
|
3398
3500
|
const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder);
|
|
3399
3501
|
if (!options?.skipEditDiscountConfigRefresh && !isVirtualSettlement) {
|
|
3400
3502
|
await this.ensureEditDiscountConfigForProductChange(tempOrder);
|
|
3401
3503
|
}
|
|
3402
|
-
|
|
3504
|
+
if (isCurrentOrder && !isCurrentOrder()) return;
|
|
3505
|
+
const promotionPayload = !options?.skipDiscountRecalculation && !isVirtualSettlement ? await this.evaluatePromotion(isCurrentOrder ? {
|
|
3506
|
+
isCurrentOrder
|
|
3507
|
+
} : undefined) : null;
|
|
3508
|
+
if (isCurrentOrder && !isCurrentOrder()) return;
|
|
3403
3509
|
if (!options?.skipDiscountRecalculation && !isVirtualSettlement) {
|
|
3404
3510
|
this.applyDiscount();
|
|
3405
3511
|
}
|
|
3406
3512
|
this.sanitizeTempOrderProducts(tempOrder);
|
|
3407
|
-
await this.recalculateSummary({
|
|
3408
|
-
createIfMissing: true
|
|
3513
|
+
const summary = await this.recalculateSummary({
|
|
3514
|
+
createIfMissing: true,
|
|
3515
|
+
...(isCurrentOrder ? {
|
|
3516
|
+
isCurrentOrder
|
|
3517
|
+
} : {})
|
|
3409
3518
|
});
|
|
3519
|
+
if (isCurrentOrder && (!isCurrentOrder() || !summary)) return;
|
|
3410
3520
|
this.persistTempOrder();
|
|
3411
3521
|
this.emitPromotionApplied(promotionPayload);
|
|
3412
3522
|
}
|
|
@@ -3429,7 +3539,6 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3429
3539
|
booking
|
|
3430
3540
|
}) : null;
|
|
3431
3541
|
const productToAdd = linked?.product || product;
|
|
3432
|
-
this.assertAndLockProductSettlement(tempOrder, productToAdd);
|
|
3433
3542
|
const disableMerge = options?.disableMerge === true;
|
|
3434
3543
|
const incomingFingerprint = disableMerge ? '' : (0, _utils3.buildProductLineFingerprint)((0, _utils.getProductSkuOptions)(productToAdd), productToAdd.product_bundle);
|
|
3435
3544
|
const normalizedIncoming = this.normalizeVirtualSettlementProductIfEnabled((0, _utils.mergeOrderProductDisplayFields)(productToAdd, (0, _utils3.normalizeOrderProduct)(productToAdd)));
|
|
@@ -3491,6 +3600,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3491
3600
|
const matchedProduct = matchedIndex === -1 ? null : tempOrder.products[matchedIndex];
|
|
3492
3601
|
const existedFingerprint = matchedProduct ? (0, _utils3.buildProductLineFingerprint)((0, _utils.getProductSkuOptions)(matchedProduct), matchedProduct.product_bundle) : '';
|
|
3493
3602
|
const commitProductLine = shouldMerge => {
|
|
3603
|
+
options?.beforeCommit?.();
|
|
3604
|
+
this.assertAndLockProductSettlement(tempOrder, productToAdd);
|
|
3494
3605
|
let committedProduct;
|
|
3495
3606
|
if (matchedIndex === -1 || !matchedProduct || !shouldMerge) {
|
|
3496
3607
|
this.captureProductRuntime(tempOrder, productToAdd, normalizedIncoming);
|
|
@@ -3642,7 +3753,16 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3642
3753
|
* // → tempOrder.products 新增 3 行,每行 num=1,bookings 3 条
|
|
3643
3754
|
*/
|
|
3644
3755
|
async addProductToOrder(product, booking, options) {
|
|
3645
|
-
const
|
|
3756
|
+
const availabilityCommitGuard = options?.availabilityCommitGuard;
|
|
3757
|
+
availabilityCommitGuard?.();
|
|
3758
|
+
const liveTempOrder = this.ensureTempOrder();
|
|
3759
|
+
const beforeCommit = this.createCartIntentCommitGuard('add_product', liveTempOrder);
|
|
3760
|
+
// 自动预约在草稿上准备完整批次,避免拆票期间暴露半成品,或在失败时
|
|
3761
|
+
// 用整单快照回滚而抹掉其他入口的并发修改。人工路径保持原有写入行为。
|
|
3762
|
+
const tempOrder = availabilityCommitGuard ? (0, _lodashEs.cloneDeep)(liveTempOrder) : liveTempOrder;
|
|
3763
|
+
const guardedMutationFields = ['products', 'bookings', 'notes', '_extend', 'metadata', 'currency_code', 'currency_symbol', 'currency_format'];
|
|
3764
|
+
const readGuardedMutationFields = order => Object.fromEntries(guardedMutationFields.map(key => [key, order[key]]));
|
|
3765
|
+
const guardedMutationBaseline = availabilityCommitGuard ? (0, _lodashEs.cloneDeep)(readGuardedMutationFields(liveTempOrder)) : null;
|
|
3646
3766
|
const salesNoteDrafts = (options?.salesNotes || []).map(draft => ({
|
|
3647
3767
|
note_type: String(draft.note_type || '').trim(),
|
|
3648
3768
|
text: {
|
|
@@ -3685,7 +3805,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3685
3805
|
const uid = line.metadata?.unique_identification_number || line.unique_identification_number;
|
|
3686
3806
|
return uid !== undefined && uid !== null && String(uid) === String(insertAfterProductUid);
|
|
3687
3807
|
}) : -1;
|
|
3688
|
-
let insertAtIndex = anchorIndex >= 0 ? anchorIndex + 1 : undefined;
|
|
3808
|
+
let insertAtIndex = options?.insertAtStart ? 0 : anchorIndex >= 0 ? anchorIndex + 1 : undefined;
|
|
3689
3809
|
try {
|
|
3690
3810
|
if (booking) {
|
|
3691
3811
|
const productRecord = product;
|
|
@@ -3713,35 +3833,76 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3713
3833
|
}
|
|
3714
3834
|
const committedProduct = await this.appendProductLineToTempOrder(tempOrder, splitLine.product, splitLine.booking, {
|
|
3715
3835
|
insertAtIndex,
|
|
3716
|
-
disableMerge: options?.disableMerge
|
|
3836
|
+
disableMerge: options?.disableMerge,
|
|
3837
|
+
beforeCommit
|
|
3717
3838
|
});
|
|
3839
|
+
availabilityCommitGuard?.();
|
|
3718
3840
|
attachSalesNoteDrafts(committedProduct);
|
|
3719
3841
|
if (insertAtIndex !== undefined) insertAtIndex += 1;
|
|
3720
3842
|
}
|
|
3721
3843
|
} else {
|
|
3722
3844
|
const committedProduct = await this.appendProductLineToTempOrder(tempOrder, product, (0, _lodashEs.cloneDeep)(booking), {
|
|
3723
3845
|
insertAtIndex,
|
|
3724
|
-
disableMerge: options?.disableMerge
|
|
3846
|
+
disableMerge: options?.disableMerge,
|
|
3847
|
+
beforeCommit
|
|
3725
3848
|
});
|
|
3849
|
+
availabilityCommitGuard?.();
|
|
3726
3850
|
attachSalesNoteDrafts(committedProduct);
|
|
3727
3851
|
}
|
|
3728
3852
|
} else {
|
|
3729
3853
|
const committedProduct = await this.appendProductLineToTempOrder(tempOrder, product, undefined, {
|
|
3730
3854
|
insertAtIndex,
|
|
3731
|
-
disableMerge: options?.disableMerge
|
|
3855
|
+
disableMerge: options?.disableMerge,
|
|
3856
|
+
beforeCommit
|
|
3732
3857
|
});
|
|
3858
|
+
availabilityCommitGuard?.();
|
|
3733
3859
|
attachSalesNoteDrafts(committedProduct);
|
|
3734
3860
|
}
|
|
3861
|
+
if (availabilityCommitGuard) {
|
|
3862
|
+
availabilityCommitGuard();
|
|
3863
|
+
beforeCommit();
|
|
3864
|
+
// 调用方的结构 revision 可能不包括备注、价格或结算元数据。
|
|
3865
|
+
// 本次会覆盖的字段也要保持原值,不能让草稿覆盖并发编辑。
|
|
3866
|
+
if (!(0, _lodashEs.isEqual)(readGuardedMutationFields(liveTempOrder), guardedMutationBaseline)) {
|
|
3867
|
+
throw Object.assign(new Error('预约加购期间订单已变化,请重新选择'), {
|
|
3868
|
+
code: 'AVAILABILITY_SELECTION_STALE'
|
|
3869
|
+
});
|
|
3870
|
+
}
|
|
3871
|
+
// 从最后一次门禁到真正新增之间不再 await。只发布本次新增会改写的
|
|
3872
|
+
// 字段;其余订单字段继续使用 live 对象,外部持有的订单引用也不变。
|
|
3873
|
+
Object.assign(liveTempOrder, readGuardedMutationFields(tempOrder));
|
|
3874
|
+
}
|
|
3735
3875
|
} catch (error) {
|
|
3736
3876
|
rollbackProductAndNotesMutation();
|
|
3737
3877
|
throw error;
|
|
3738
3878
|
}
|
|
3739
|
-
|
|
3879
|
+
// 发布后预约已加购;后续促销/summary 沿用既有收尾,不用自身新增后的
|
|
3880
|
+
// revision 再执行提交 CAS,也不会把已加购预约因收尾耗时而撤回。
|
|
3881
|
+
if (availabilityCommitGuard) {
|
|
3882
|
+
const committedIdentity = [liveTempOrder.order_id, liveTempOrder.external_sale_number];
|
|
3883
|
+
const isCurrentOrder = () => this.store.tempOrder === liveTempOrder && liveTempOrder.order_id === committedIdentity[0] && liveTempOrder.external_sale_number === committedIdentity[1] && (options?.availabilityCommitTargetGuard?.() ?? true);
|
|
3884
|
+
try {
|
|
3885
|
+
// 新增已发布,即使后续报价/促销收尾失败,也不能向调用方报告未加购。
|
|
3886
|
+
// 先保存已提交行;异步结果只允许写回仍属于本次提交的订单。
|
|
3887
|
+
if (isCurrentOrder()) this.persistTempOrder();
|
|
3888
|
+
await this.finalizeProductOrderMutation(liveTempOrder, {
|
|
3889
|
+
isCurrentOrder
|
|
3890
|
+
});
|
|
3891
|
+
} catch (error) {
|
|
3892
|
+
this.logWarning('addProductToOrder committed; finalization failed', {
|
|
3893
|
+
product_id: product.product_id,
|
|
3894
|
+
committed: true,
|
|
3895
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3896
|
+
});
|
|
3897
|
+
}
|
|
3898
|
+
} else {
|
|
3899
|
+
await this.finalizeProductOrderMutation(liveTempOrder);
|
|
3900
|
+
}
|
|
3740
3901
|
this.logInfo('addProductToOrder success', {
|
|
3741
3902
|
product_id: product.product_id,
|
|
3742
3903
|
with_booking: !!booking
|
|
3743
3904
|
});
|
|
3744
|
-
return
|
|
3905
|
+
return liveTempOrder.products;
|
|
3745
3906
|
}
|
|
3746
3907
|
|
|
3747
3908
|
/**
|
|
@@ -3756,6 +3917,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3756
3917
|
async addProductsToOrder(items, options) {
|
|
3757
3918
|
const tempOrder = this.ensureTempOrder();
|
|
3758
3919
|
if (!Array.isArray(items) || items.length === 0) return tempOrder.products;
|
|
3920
|
+
const beforeCommit = this.createCartIntentCommitGuard('add_product', tempOrder);
|
|
3759
3921
|
for (const item of items || []) {
|
|
3760
3922
|
const {
|
|
3761
3923
|
product,
|
|
@@ -3768,13 +3930,17 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3768
3930
|
if (splitCount > 1) {
|
|
3769
3931
|
for (let i = 0; i < splitCount; i += 1) {
|
|
3770
3932
|
const splitLine = this.createSplitBookingLine(productRecord, booking, i, splitCount);
|
|
3771
|
-
const appendResult = this.appendProductLineToTempOrder(tempOrder, splitLine.product, splitLine.booking
|
|
3933
|
+
const appendResult = this.appendProductLineToTempOrder(tempOrder, splitLine.product, splitLine.booking, {
|
|
3934
|
+
beforeCommit
|
|
3935
|
+
});
|
|
3772
3936
|
if (appendResult) await appendResult;
|
|
3773
3937
|
}
|
|
3774
3938
|
continue;
|
|
3775
3939
|
}
|
|
3776
3940
|
}
|
|
3777
|
-
const appendResult = this.appendProductLineToTempOrder(tempOrder, product, booking
|
|
3941
|
+
const appendResult = this.appendProductLineToTempOrder(tempOrder, product, booking, {
|
|
3942
|
+
beforeCommit
|
|
3943
|
+
});
|
|
3778
3944
|
if (appendResult) await appendResult;
|
|
3779
3945
|
}
|
|
3780
3946
|
await this.finalizeProductOrderMutation(tempOrder, options);
|
|
@@ -3859,6 +4025,16 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3859
4025
|
};
|
|
3860
4026
|
});
|
|
3861
4027
|
}
|
|
4028
|
+
isRestrictedCartProductUpdate(tempOrder, params) {
|
|
4029
|
+
if (!this.orderHooks?.beforeCartIntentCommit) return false;
|
|
4030
|
+
if (params.booking || Object.keys(params.updates || {}).some(key => key !== 'num')) {
|
|
4031
|
+
return true;
|
|
4032
|
+
}
|
|
4033
|
+
if (params.updates?.num === undefined) return false;
|
|
4034
|
+
const uid = params.unique_identification_number;
|
|
4035
|
+
const product = uid !== undefined ? tempOrder.products.find(item => String(item.metadata?.unique_identification_number || item.unique_identification_number || '') === String(uid)) : tempOrder.products[(0, _utils3.getProductIdentityIndex)(tempOrder.products, params)];
|
|
4036
|
+
return !product || (0, _utils3.getSafeProductNum)(params.updates.num) > product.num;
|
|
4037
|
+
}
|
|
3862
4038
|
applyOrderProductUpdateToTempOrder(tempOrder, params, reapplyWeighedDiscountProductUids) {
|
|
3863
4039
|
const {
|
|
3864
4040
|
product_id,
|
|
@@ -4110,6 +4286,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4110
4286
|
}
|
|
4111
4287
|
async updateOrderProduct(params) {
|
|
4112
4288
|
const tempOrder = this.ensureTempOrder();
|
|
4289
|
+
if (this.isRestrictedCartProductUpdate(tempOrder, params)) {
|
|
4290
|
+
this.createCartIntentCommitGuard('update_product', tempOrder)();
|
|
4291
|
+
}
|
|
4113
4292
|
const reapplyWeighedDiscountProductUids = [];
|
|
4114
4293
|
const updatedProductUid = this.applyOrderProductUpdateToTempOrder(tempOrder, params, reapplyWeighedDiscountProductUids);
|
|
4115
4294
|
const promotionPayload = await this.evaluatePromotion();
|
|
@@ -4133,6 +4312,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4133
4312
|
if (!paramsList.length) {
|
|
4134
4313
|
return tempOrder.products;
|
|
4135
4314
|
}
|
|
4315
|
+
if (paramsList.some(params => this.isRestrictedCartProductUpdate(tempOrder, params))) {
|
|
4316
|
+
this.createCartIntentCommitGuard('update_product', tempOrder)();
|
|
4317
|
+
}
|
|
4136
4318
|
const reapplyWeighedDiscountProductUids = [];
|
|
4137
4319
|
const reapplyBookingDiscountProductUids = paramsList.reduce((acc, params) => {
|
|
4138
4320
|
const updatedProductUid = this.applyOrderProductUpdateToTempOrder(tempOrder, params, reapplyWeighedDiscountProductUids);
|
|
@@ -4151,7 +4333,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4151
4333
|
});
|
|
4152
4334
|
return tempOrder.products;
|
|
4153
4335
|
}
|
|
4154
|
-
async updateOrderProductQuantity(params) {
|
|
4336
|
+
async updateOrderProductQuantity(params, options) {
|
|
4337
|
+
const isCurrentOrder = options?.isCurrentOrder;
|
|
4338
|
+
if (isCurrentOrder && !isCurrentOrder()) return this.store.tempOrder?.products || [];
|
|
4155
4339
|
const {
|
|
4156
4340
|
product_id,
|
|
4157
4341
|
product_variant_id,
|
|
@@ -4217,19 +4401,30 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4217
4401
|
throw new _virtualSettlement.VirtualCurrencyBalanceError(balance.toFixed(2), requiredAmount.toFixed(2));
|
|
4218
4402
|
}
|
|
4219
4403
|
}
|
|
4404
|
+
if (normalizedProduct.num > targetProduct.num) {
|
|
4405
|
+
this.createCartIntentCommitGuard('increase_quantity', tempOrder)();
|
|
4406
|
+
}
|
|
4407
|
+
if (isCurrentOrder && !isCurrentOrder()) return tempOrder.products;
|
|
4220
4408
|
tempOrder.products[productIndex] = normalizedProduct;
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4409
|
+
if (isCurrentOrder) {
|
|
4410
|
+
await this.finalizeProductOrderMutation(tempOrder, {
|
|
4411
|
+
skipEditDiscountConfigRefresh: true,
|
|
4412
|
+
isCurrentOrder
|
|
4413
|
+
});
|
|
4414
|
+
} else {
|
|
4415
|
+
this.prepareVirtualSettlementTempOrder(tempOrder);
|
|
4416
|
+
const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder);
|
|
4417
|
+
const promotionPayload = !isVirtualSettlement ? await this.evaluatePromotion() : null;
|
|
4418
|
+
if (!isVirtualSettlement) {
|
|
4419
|
+
this.applyDiscount();
|
|
4420
|
+
}
|
|
4421
|
+
this.sanitizeTempOrderProducts(tempOrder);
|
|
4422
|
+
await this.recalculateSummary({
|
|
4423
|
+
createIfMissing: true
|
|
4424
|
+
});
|
|
4425
|
+
this.persistTempOrder();
|
|
4426
|
+
this.emitPromotionApplied(promotionPayload);
|
|
4226
4427
|
}
|
|
4227
|
-
this.sanitizeTempOrderProducts(tempOrder);
|
|
4228
|
-
await this.recalculateSummary({
|
|
4229
|
-
createIfMissing: true
|
|
4230
|
-
});
|
|
4231
|
-
this.persistTempOrder();
|
|
4232
|
-
this.emitPromotionApplied(promotionPayload);
|
|
4233
4428
|
this.logInfo('updateOrderProductQuantity success', {
|
|
4234
4429
|
params
|
|
4235
4430
|
});
|
|
@@ -4294,6 +4489,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4294
4489
|
* await order.removeProductsFromOrder([identityA, identityB]);
|
|
4295
4490
|
*/
|
|
4296
4491
|
async removeProductsFromOrder(identities, options) {
|
|
4492
|
+
const isCurrentOrder = options?.isCurrentOrder;
|
|
4493
|
+
if (isCurrentOrder && !isCurrentOrder()) return this.store.tempOrder?.products || [];
|
|
4297
4494
|
const tempOrder = this.ensureTempOrder();
|
|
4298
4495
|
if (!identities.length) {
|
|
4299
4496
|
return tempOrder.products;
|
|
@@ -4361,7 +4558,14 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4361
4558
|
}
|
|
4362
4559
|
}
|
|
4363
4560
|
this.removeSalesNotesForMissingProductLines(tempOrder);
|
|
4364
|
-
|
|
4561
|
+
if (isCurrentOrder) {
|
|
4562
|
+
await this.finalizeProductOrderMutation(tempOrder, {
|
|
4563
|
+
skipEditDiscountConfigRefresh: true,
|
|
4564
|
+
isCurrentOrder
|
|
4565
|
+
});
|
|
4566
|
+
} else {
|
|
4567
|
+
await this.finalizeAfterProductsMutation(tempOrder);
|
|
4568
|
+
}
|
|
4365
4569
|
this.logInfo('removeProductsFromOrder success', {
|
|
4366
4570
|
identities
|
|
4367
4571
|
});
|
|
@@ -4525,6 +4729,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4525
4729
|
}
|
|
4526
4730
|
async runSubmitTempOrder(params) {
|
|
4527
4731
|
const tempOrder = this.ensureTempOrder();
|
|
4732
|
+
if ((0, _localEftposState.requiresLocalPaymentRefresh)(tempOrder)) throw new Error(_localEftposState.PAYMENT_REFRESH_MESSAGE);
|
|
4528
4733
|
this.prepareVirtualSettlementTempOrder(tempOrder);
|
|
4529
4734
|
const isOnlineStorePlatform = this.isOnlineStorePlatform();
|
|
4530
4735
|
const shouldConfirmPendingVoucherPayments = params?.confirmPendingVoucherPayments !== false;
|
|
@@ -4999,7 +5204,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4999
5204
|
query
|
|
5000
5205
|
} = params;
|
|
5001
5206
|
const fetchUrl = url || '/order/sales/checkout';
|
|
5002
|
-
const requestQuery = this.isSalesCheckoutHandledByOsServer(fetchUrl) ? query : (0, _osPrivatePayload.stripOsPrivatePayloadFields)(query);
|
|
5207
|
+
const requestQuery = this.isSalesCheckoutHandledByOsServer(fetchUrl) ? query : (0, _localEftposState.stripLocalEftposState)((0, _osPrivatePayload.stripOsPrivatePayloadFields)(query));
|
|
5003
5208
|
return this.request.post(fetchUrl, requestQuery, {
|
|
5004
5209
|
osServer: true,
|
|
5005
5210
|
customToast: () => {}
|
|
@@ -5044,13 +5249,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
5044
5249
|
if (lookup.startsWith('LOCAL_')) {
|
|
5045
5250
|
params.forceRemote = false;
|
|
5046
5251
|
}
|
|
5047
|
-
const res = await this.request
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
} : {})
|
|
5052
|
-
}, {
|
|
5053
|
-
osServer: true
|
|
5252
|
+
const res = await (0, _loadSalesOrderSnapshot.loadSalesOrderSnapshot)(this.request, {
|
|
5253
|
+
lookup,
|
|
5254
|
+
transport: 'os-server',
|
|
5255
|
+
forceRemote: params.forceRemote
|
|
5054
5256
|
});
|
|
5055
5257
|
if (res.code === 200) {
|
|
5056
5258
|
this.store.lastOrderInfo = res.data;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Local reconciliation state; never part of a cloud checkout payload. */
|
|
2
|
+
export declare const LOCAL_EFTPOS_REFRESH_REQUIRED = "_local_eftpos_refresh_required";
|
|
3
|
+
export declare const LOCAL_EFTPOS_FINALIZED = "_local_eftpos_finalized";
|
|
4
|
+
export declare const PAYMENT_REFRESH_MESSAGE = "\u8BA2\u5355\u9700\u8981\u5237\u65B0\uFF0C\u8BF7\u8054\u7F51\u5237\u65B0\u8BA2\u5355\u540E\u518D\u4ED8\u6B3E";
|
|
5
|
+
export interface LocalEftposFinalization {
|
|
6
|
+
saleId: string | number;
|
|
7
|
+
paymentNumber: string;
|
|
8
|
+
result: 'failed' | 'not_started';
|
|
9
|
+
failedTransactionNumbers: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function requiresLocalPaymentRefresh(order: any): boolean;
|
|
12
|
+
export declare function isLocalFinalizedPayment(payment: any): boolean;
|
|
13
|
+
export declare function stripLocalEftposState<T extends Record<string, any>>(order: T): T;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PAYMENT_REFRESH_MESSAGE = exports.LOCAL_EFTPOS_REFRESH_REQUIRED = exports.LOCAL_EFTPOS_FINALIZED = void 0;
|
|
7
|
+
exports.isLocalFinalizedPayment = isLocalFinalizedPayment;
|
|
8
|
+
exports.requiresLocalPaymentRefresh = requiresLocalPaymentRefresh;
|
|
9
|
+
exports.stripLocalEftposState = stripLocalEftposState;
|
|
10
|
+
/** Local reconciliation state; never part of a cloud checkout payload. */
|
|
11
|
+
const LOCAL_EFTPOS_REFRESH_REQUIRED = exports.LOCAL_EFTPOS_REFRESH_REQUIRED = '_local_eftpos_refresh_required';
|
|
12
|
+
const LOCAL_EFTPOS_FINALIZED = exports.LOCAL_EFTPOS_FINALIZED = '_local_eftpos_finalized';
|
|
13
|
+
const PAYMENT_REFRESH_MESSAGE = exports.PAYMENT_REFRESH_MESSAGE = '订单需要刷新,请联网刷新订单后再付款';
|
|
14
|
+
function requiresLocalPaymentRefresh(order) {
|
|
15
|
+
return order?.metadata?.[LOCAL_EFTPOS_REFRESH_REQUIRED] === true;
|
|
16
|
+
}
|
|
17
|
+
function isLocalFinalizedPayment(payment) {
|
|
18
|
+
return payment?.status === 'voided' && payment?.metadata?.[LOCAL_EFTPOS_FINALIZED] === true;
|
|
19
|
+
}
|
|
20
|
+
function stripLocalEftposState(order) {
|
|
21
|
+
const result = {
|
|
22
|
+
...order
|
|
23
|
+
};
|
|
24
|
+
if (order.metadata) {
|
|
25
|
+
result.metadata = {
|
|
26
|
+
...order.metadata
|
|
27
|
+
};
|
|
28
|
+
delete result.metadata[LOCAL_EFTPOS_REFRESH_REQUIRED];
|
|
29
|
+
}
|
|
30
|
+
if (Array.isArray(order.payments)) {
|
|
31
|
+
result.payments = order.payments.filter(payment => !isLocalFinalizedPayment(payment)).map(payment => {
|
|
32
|
+
if (!payment.metadata?.[LOCAL_EFTPOS_FINALIZED]) return payment;
|
|
33
|
+
const metadata = {
|
|
34
|
+
...payment.metadata
|
|
35
|
+
};
|
|
36
|
+
delete metadata[LOCAL_EFTPOS_FINALIZED];
|
|
37
|
+
return {
|
|
38
|
+
...payment,
|
|
39
|
+
metadata
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|