@pisell/pisellos 0.10.14 → 0.10.16
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/core/index.js +6 -9
- package/dist/model/strategy/adapter/walletPass/example.js +3 -26
- package/dist/model/strategy/strategy-example.js +5 -19
- package/dist/modules/Cart/index.js +0 -3
- package/dist/modules/Cart/utils/cartProduct.js +0 -1
- package/dist/modules/Date/index.js +1 -5
- package/dist/modules/Discount/index.js +2 -4
- package/dist/modules/OpenData/index.js +0 -2
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +75 -91
- package/dist/modules/Order/types.d.ts +5 -1
- package/dist/modules/Order/utils/virtualSettlement.d.ts +8 -1
- package/dist/modules/Order/utils/virtualSettlement.js +15 -2
- package/dist/modules/Order/utils.js +7 -1
- package/dist/modules/Payment/index.js +97 -162
- package/dist/modules/Product/types.d.ts +2 -0
- package/dist/modules/Rules/index.js +1 -4
- package/dist/modules/Schedule/index.js +0 -1
- package/dist/modules/Schedule/utils.js +0 -1
- package/dist/modules/Step/index.js +0 -1
- package/dist/plugins/request.js +1 -4
- package/dist/plugins/window.js +2 -6
- package/dist/server/index.js +97 -129
- package/dist/server/modules/menu/index.js +32 -41
- package/dist/server/modules/order/index.js +2 -4
- package/dist/server/modules/products/index.js +24 -42
- package/dist/server/modules/quotation/index.js +29 -38
- package/dist/server/modules/resource/index.js +3 -4
- package/dist/server/modules/schedule/index.js +27 -35
- package/dist/server/utils/product.js +0 -1
- package/dist/solution/BaseSales/index.js +107 -76
- package/dist/solution/BaseSales/types.d.ts +2 -0
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
- package/dist/solution/BaseSales/utils/cartPromotion.js +15 -6
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +7 -1
- package/dist/solution/BaseSales/utils.js +6 -3
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/BookingByStep/index.js +7 -59
- package/dist/solution/BookingByStep/utils/capacity.js +1 -11
- package/dist/solution/BookingByStep/utils/resources.js +1 -3
- package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
- package/dist/solution/BookingTicket/index.js +8 -4
- package/dist/solution/BookingTicket/utils/addProductDecision.js +3 -1
- package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +6 -7
- package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
- package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
- package/dist/solution/BuyTickets/index.js +9 -12
- package/dist/solution/Checkout/index.js +177 -252
- package/dist/solution/Checkout/utils/index.js +4 -16
- package/dist/solution/RegisterAndLogin/index.js +30 -76
- package/dist/solution/ScanOrder/index.js +50 -60
- package/dist/solution/ScanOrder/types.d.ts +2 -0
- package/dist/solution/ScanOrder/utils.js +6 -3
- package/dist/solution/ShopDiscount/index.js +2 -7
- package/dist/solution/VenueBooking/index.js +45 -55
- package/dist/utils/task.js +15 -18
- package/dist/utils/watch.js +0 -1
- package/lib/apis/picoding.js +2 -0
- package/lib/core/index.js +131 -131
- package/lib/effects/index.js +46 -57
- package/lib/index.js +82 -49
- package/lib/model/index.js +14 -21
- package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +209 -315
- package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
- package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
- package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
- package/lib/model/strategy/adapter/index.js +100 -64
- package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
- package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
- package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
- package/lib/model/strategy/adapter/itemRule/index.js +83 -57
- package/lib/model/strategy/adapter/itemRule/type.js +97 -36
- package/lib/model/strategy/adapter/promotion/adapter.js +91 -69
- package/lib/model/strategy/adapter/promotion/evaluator.js +444 -310
- package/lib/model/strategy/adapter/promotion/examples.js +222 -234
- package/lib/model/strategy/adapter/promotion/index.js +43 -48
- package/lib/model/strategy/adapter/promotion/type.js +243 -36
- package/lib/model/strategy/adapter/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -150
- package/lib/model/strategy/adapter/walletPass/example.js +217 -190
- package/lib/model/strategy/adapter/walletPass/index.js +75 -51
- package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
- package/lib/model/strategy/adapter/walletPass/type.js +4 -16
- package/lib/model/strategy/adapter/walletPass/utils.js +588 -378
- package/lib/model/strategy/engine.js +270 -168
- package/lib/model/strategy/index.js +49 -34
- package/lib/model/strategy/strategy-example.js +243 -239
- package/lib/model/strategy/type.js +100 -40
- package/lib/modules/Account/index.js +39 -53
- package/lib/modules/Account/types.js +20 -33
- package/lib/modules/AccountList/index.js +116 -154
- package/lib/modules/AccountList/types.js +30 -31
- package/lib/modules/AccountList/utils.js +18 -30
- package/lib/modules/BaseModule.js +23 -42
- package/lib/modules/BookingContext/index.js +158 -136
- package/lib/modules/BookingContext/types.js +46 -32
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +138 -146
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +78 -83
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +170 -150
- package/lib/modules/BookingContext/utils/flexible.js +38 -55
- package/lib/modules/BookingContext/utils/formatResourceList.js +19 -34
- package/lib/modules/BookingContext/utils/index.js +124 -41
- package/lib/modules/BookingContext/utils/noResource.js +58 -70
- package/lib/modules/BookingContext/utils/orderLineDisplay.js +14 -41
- package/lib/modules/BookingContext/utils/productExtend.js +202 -155
- package/lib/modules/BookingContext/utils/resourceErrors.js +53 -53
- package/lib/modules/BookingContext/utils/resourceSelection.js +19 -41
- package/lib/modules/BookingContext/utils/resources.js +209 -167
- package/lib/modules/BookingContext/utils/serviceTimes.js +115 -116
- package/lib/modules/BookingContext/utils/timeSlices.js +76 -86
- package/lib/modules/Cart/index.js +170 -124
- package/lib/modules/Cart/types.js +46 -51
- package/lib/modules/Cart/utils/cartAccount.js +40 -39
- package/lib/modules/Cart/utils/cartDate.js +56 -61
- package/lib/modules/Cart/utils/cartDiscount.js +28 -33
- package/lib/modules/Cart/utils/cartNote.js +27 -32
- package/lib/modules/Cart/utils/cartProduct.js +321 -251
- package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
- package/lib/modules/Cart/utils/cartResource.js +70 -78
- package/lib/modules/Cart/utils/changePrice.js +22 -50
- package/lib/modules/Cart/utils/index.js +106 -48
- package/lib/modules/Customer/constants.js +13 -34
- package/lib/modules/Customer/index.js +235 -172
- package/lib/modules/Customer/types.js +38 -35
- package/lib/modules/Date/index.js +116 -115
- package/lib/modules/Date/types.js +16 -28
- package/lib/modules/Date/utils.js +174 -123
- package/lib/modules/Discount/index.js +133 -143
- package/lib/modules/Discount/types.js +9 -31
- package/lib/modules/Guests/index.js +30 -56
- package/lib/modules/Guests/types.js +23 -33
- package/lib/modules/Holder/index.js +209 -189
- package/lib/modules/Holder/types.js +4 -16
- package/lib/modules/Holder/utils.js +20 -49
- package/lib/modules/OpenData/index.js +70 -76
- package/lib/modules/OpenData/types.js +4 -16
- package/lib/modules/OpenData/utils.js +44 -78
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +1810 -2238
- package/lib/modules/Order/payment-utils.js +77 -120
- package/lib/modules/Order/types.d.ts +5 -1
- package/lib/modules/Order/types.js +87 -35
- package/lib/modules/Order/utils/bundleDiscountHydration.js +41 -74
- package/lib/modules/Order/utils/discountProductLineIdentity.js +142 -100
- package/lib/modules/Order/utils/manualProductDiscount.js +124 -123
- package/lib/modules/Order/utils/orderCollectionIdentity.js +184 -244
- package/lib/modules/Order/utils/virtualSettlement.d.ts +8 -1
- package/lib/modules/Order/utils/virtualSettlement.js +126 -164
- package/lib/modules/Order/utils.js +834 -668
- package/lib/modules/Payment/cash.js +20 -33
- package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
- package/lib/modules/Payment/eftpos.js +16 -30
- package/lib/modules/Payment/index.js +532 -399
- package/lib/modules/Payment/mx51.js +1 -0
- package/lib/modules/Payment/types.js +230 -108
- package/lib/modules/Payment/utils.js +52 -51
- package/lib/modules/Payment/walletpass.js +485 -660
- package/lib/modules/Product/index.js +51 -46
- package/lib/modules/Product/types.d.ts +2 -0
- package/lib/modules/Product/types.js +4 -16
- package/lib/modules/Product/utils.js +32 -33
- package/lib/modules/ProductList/index.js +138 -161
- package/lib/modules/ProductList/types.js +9 -31
- package/lib/modules/Quotation/index.js +66 -100
- package/lib/modules/Quotation/types.js +4 -16
- package/lib/modules/Resource/index.js +27 -59
- package/lib/modules/Resource/types.js +22 -32
- package/lib/modules/Resource/utils.js +30 -38
- package/lib/modules/ResourcePlanner/index.js +25 -23
- package/lib/modules/ResourcePlanner/localClock.js +54 -119
- package/lib/modules/ResourcePlanner/planner.js +591 -772
- package/lib/modules/ResourcePlanner/types.js +10 -29
- package/lib/modules/Rules/index.js +1218 -959
- package/lib/modules/Rules/types.js +17 -40
- package/lib/modules/SalesSummary/index.js +78 -89
- package/lib/modules/SalesSummary/types.js +4 -16
- package/lib/modules/SalesSummary/utils.js +359 -442
- package/lib/modules/ScanOrderLogger/index.js +59 -79
- package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
- package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
- package/lib/modules/ScanOrderLogger/types.js +4 -16
- package/lib/modules/Schedule/getDateIsInSchedule.js +334 -163
- package/lib/modules/Schedule/index.js +100 -114
- package/lib/modules/Schedule/type.js +4 -16
- package/lib/modules/Schedule/types.js +4 -16
- package/lib/modules/Schedule/utils.js +433 -291
- package/lib/modules/Step/index.js +40 -52
- package/lib/modules/Step/tyeps.js +4 -16
- package/lib/modules/Summary/index.js +66 -71
- package/lib/modules/Summary/types.js +4 -16
- package/lib/modules/Summary/utils.js +773 -418
- package/lib/modules/SurchargeList/index.js +46 -60
- package/lib/modules/SurchargeList/types.js +4 -16
- package/lib/modules/index.js +245 -63
- package/lib/plugins/app.js +4 -16
- package/lib/plugins/index.js +36 -25
- package/lib/plugins/request.js +137 -126
- package/lib/plugins/shopStore.js +4 -16
- package/lib/plugins/user.js +4 -16
- package/lib/plugins/window.js +171 -179
- package/lib/server/index.js +3027 -2655
- package/lib/server/modules/floor-plan/index.js +102 -123
- package/lib/server/modules/floor-plan/types.js +15 -30
- package/lib/server/modules/index.js +106 -68
- package/lib/server/modules/menu/index.js +146 -122
- package/lib/server/modules/menu/types.js +18 -31
- package/lib/server/modules/order/index.js +758 -956
- package/lib/server/modules/order/types.js +122 -33
- package/lib/server/modules/order/utils/filterBookings.js +219 -194
- package/lib/server/modules/order/utils/filterOrders.js +118 -92
- package/lib/server/modules/payment/index.js +59 -83
- package/lib/server/modules/payment/types.js +4 -16
- package/lib/server/modules/products/index.js +575 -459
- package/lib/server/modules/products/types.js +44 -34
- package/lib/server/modules/quotation/index.js +137 -172
- package/lib/server/modules/quotation/types.js +21 -31
- package/lib/server/modules/resource/index.js +213 -184
- package/lib/server/modules/resource/types.js +42 -33
- package/lib/server/modules/schedule/index.js +135 -123
- package/lib/server/modules/schedule/types.js +14 -21
- package/lib/server/modules/schedule/utils.js +334 -163
- package/lib/server/types.js +4 -16
- package/lib/server/utils/index.js +25 -23
- package/lib/server/utils/product.js +196 -139
- package/lib/server/utils/schedule.js +34 -41
- package/lib/server/utils/small-ticket.js +479 -456
- package/lib/server/utils/time.js +40 -49
- package/lib/solution/BaseSales/index.js +1276 -1485
- package/lib/solution/BaseSales/types.d.ts +2 -0
- package/lib/solution/BaseSales/types.js +42 -38
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +5 -0
- package/lib/solution/BaseSales/utils/cartPromotion.js +652 -498
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +85 -105
- package/lib/solution/BaseSales/utils/quotationPrice.js +56 -114
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +138 -180
- package/lib/solution/BaseSales/utils.js +161 -143
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/BookingByStep/index.js +1527 -1340
- package/lib/solution/BookingByStep/types.js +40 -99
- package/lib/solution/BookingByStep/utils/capacity.js +192 -160
- package/lib/solution/BookingByStep/utils/products.js +42 -52
- package/lib/solution/BookingByStep/utils/resources.js +527 -330
- package/lib/solution/BookingByStep/utils/stock.js +65 -44
- package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
- package/lib/solution/BookingTicket/index.js +598 -514
- package/lib/solution/BookingTicket/types.js +99 -77
- package/lib/solution/BookingTicket/utils/addProductDecision.js +229 -190
- package/lib/solution/BookingTicket/utils/addTimeAvailability.js +58 -89
- package/lib/solution/BookingTicket/utils/bookingStatus.js +107 -78
- package/lib/solution/BookingTicket/utils/cartView.js +114 -99
- package/lib/solution/BookingTicket/utils/exampleData.js +185 -0
- package/lib/solution/BookingTicket/utils/orderCustomer.js +18 -41
- package/lib/solution/BookingTicket/utils/resolveBestAddTimePlan.js +219 -86
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +168 -116
- package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +79 -91
- package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +54 -41
- package/lib/solution/BookingTicket/utils/scan/handleScan.js +84 -81
- package/lib/solution/BookingTicket/utils/scan/index.js +98 -104
- package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
- package/lib/solution/BookingTicket/utils/scan/scanProductValues.js +52 -64
- package/lib/solution/BookingTicket/utils/sessionCatalogStale.js +56 -58
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +34 -48
- package/lib/solution/BuyTickets/index.js +67 -70
- package/lib/solution/BuyTickets/types.js +22 -38
- package/lib/solution/Checkout/index.js +1451 -1158
- package/lib/solution/Checkout/types.js +91 -61
- package/lib/solution/Checkout/utils/index.js +228 -156
- package/lib/solution/PlaceOrder/index.js +55 -0
- package/lib/solution/RegisterAndLogin/config.js +493 -460
- package/lib/solution/RegisterAndLogin/index.js +633 -630
- package/lib/solution/RegisterAndLogin/types.js +189 -76
- package/lib/solution/RegisterAndLogin/utils.js +183 -125
- package/lib/solution/Sales/index.js +328 -324
- package/lib/solution/Sales/types.js +27 -33
- package/lib/solution/ScanOrder/index.js +822 -852
- package/lib/solution/ScanOrder/types.d.ts +2 -0
- package/lib/solution/ScanOrder/types.js +33 -34
- package/lib/solution/ScanOrder/utils.js +412 -374
- package/lib/solution/ShopDiscount/index.js +226 -232
- package/lib/solution/ShopDiscount/types.js +15 -37
- package/lib/solution/ShopDiscount/utils.js +300 -172
- package/lib/solution/UnifiedBookingSales/index.js +1052 -1213
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +99 -159
- package/lib/solution/UnifiedBookingSales/types.js +10 -32
- package/lib/solution/VenueBooking/index.js +811 -879
- package/lib/solution/VenueBooking/types.js +19 -39
- package/lib/solution/VenueBooking/utils/dateSummary.js +27 -56
- package/lib/solution/VenueBooking/utils/resource.js +31 -54
- package/lib/solution/VenueBooking/utils/slotMerge.js +94 -107
- package/lib/solution/VenueBooking/utils/timeSlot.js +132 -132
- package/lib/solution/VenueBooking/utils.js +130 -67
- package/lib/solution/index.js +124 -41
- package/lib/store/createStore.js +32 -29
- package/lib/types/index.js +4 -16
- package/lib/utils/payment-number.js +26 -46
- package/lib/utils/task.js +36 -36
- package/lib/utils/watch.js +81 -47
- package/package.json +2 -1
|
@@ -1,335 +1,276 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
BaseSalesImpl: true
|
|
18
8
|
};
|
|
19
|
-
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
__export(BaseSales_exports, {
|
|
33
|
-
BaseSalesImpl: () => BaseSalesImpl
|
|
9
|
+
exports.BaseSalesImpl = void 0;
|
|
10
|
+
var _BaseModule = require("../../modules/BaseModule");
|
|
11
|
+
var _types = require("./types");
|
|
12
|
+
Object.keys(_types).forEach(function (key) {
|
|
13
|
+
if (key === "default" || key === "__esModule") return;
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
15
|
+
if (key in exports && exports[key] === _types[key]) return;
|
|
16
|
+
Object.defineProperty(exports, key, {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () {
|
|
19
|
+
return _types[key];
|
|
20
|
+
}
|
|
21
|
+
});
|
|
34
22
|
});
|
|
35
|
-
|
|
36
|
-
var
|
|
37
|
-
var
|
|
38
|
-
var
|
|
39
|
-
var
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var
|
|
46
|
-
var
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
product_voucher: "PRODUCTVOUCHER",
|
|
55
|
-
gift_card: "GIFTCARD",
|
|
56
|
-
point_card: "POINTCARD"
|
|
23
|
+
var _Order = require("../../modules/Order");
|
|
24
|
+
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
25
|
+
var _lodashEs = require("lodash-es");
|
|
26
|
+
var _types2 = require("../BookingByStep/types");
|
|
27
|
+
var _utils = require("../../modules/Order/utils");
|
|
28
|
+
var _virtualSettlement = require("../../modules/Order/utils/virtualSettlement");
|
|
29
|
+
var _paymentUtils = require("../../modules/Order/payment-utils");
|
|
30
|
+
var _paymentNumber = require("../../utils/payment-number");
|
|
31
|
+
var _orderCollectionIdentity = require("../../modules/Order/utils/orderCollectionIdentity");
|
|
32
|
+
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
33
|
+
var _Quotation = require("../../modules/Quotation");
|
|
34
|
+
var _transformBaseProductToOrderProduct = require("./utils/transformBaseProductToOrderProduct");
|
|
35
|
+
var _quotationPrice = require("./utils/quotationPrice");
|
|
36
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
37
|
+
const SERVER_ORDER_CHANGED_EVENT = 'order:onOrdersChanged';
|
|
38
|
+
const WALLET_PAYMENT_CODE_BY_TAG = {
|
|
39
|
+
product_voucher: 'PRODUCTVOUCHER',
|
|
40
|
+
gift_card: 'GIFTCARD',
|
|
41
|
+
point_card: 'POINTCARD'
|
|
57
42
|
};
|
|
58
43
|
function getSharedWalletAssetId(asset) {
|
|
59
|
-
return
|
|
44
|
+
return asset?.id ?? asset?.voucher_id ?? asset?.code;
|
|
60
45
|
}
|
|
61
46
|
function getSharedWalletAssetAmount(asset) {
|
|
62
|
-
const value =
|
|
47
|
+
const value = asset?.edit_current_amount ?? asset?._available_max_amount ?? (asset?.tag === 'point_card' ? asset?.recommended_usage_amount : asset?.available_max_amount) ?? asset?.actualDeduction ?? asset?.amount ?? 0;
|
|
63
48
|
const amount = Number(value);
|
|
64
49
|
return Number.isFinite(amount) && amount > 0 ? amount : 0;
|
|
65
50
|
}
|
|
66
51
|
function isRejectedSalesSubmitResult(result) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
(_a = result == null ? void 0 : result.response) == null ? void 0 : _a.data,
|
|
72
|
-
(_b = result == null ? void 0 : result.response) == null ? void 0 : _b.body
|
|
73
|
-
];
|
|
74
|
-
return candidates.some((candidate) => {
|
|
75
|
-
if (!candidate || typeof candidate !== "object")
|
|
76
|
-
return false;
|
|
77
|
-
if (candidate.code !== void 0 && candidate.code !== 200 && candidate.code !== "200") {
|
|
52
|
+
const candidates = [result, result?.data, result?.response?.data, result?.response?.body];
|
|
53
|
+
return candidates.some(candidate => {
|
|
54
|
+
if (!candidate || typeof candidate !== 'object') return false;
|
|
55
|
+
if (candidate.code !== undefined && candidate.code !== 200 && candidate.code !== '200') {
|
|
78
56
|
return true;
|
|
79
57
|
}
|
|
80
58
|
const statusCode = Number(candidate.statusCode);
|
|
81
|
-
if (Number.isFinite(statusCode) && statusCode >= 400)
|
|
82
|
-
return true;
|
|
59
|
+
if (Number.isFinite(statusCode) && statusCode >= 400) return true;
|
|
83
60
|
if (candidate.status === false || candidate.success === false || candidate.result === false) {
|
|
84
61
|
return true;
|
|
85
62
|
}
|
|
86
|
-
return [
|
|
87
|
-
String(candidate.status || "").toLowerCase()
|
|
88
|
-
);
|
|
63
|
+
return ['failed', 'error'].includes(String(candidate.status || '').toLowerCase());
|
|
89
64
|
});
|
|
90
65
|
}
|
|
91
66
|
function getSalesSubmitErrorMessage(result, fallbackMessage) {
|
|
92
|
-
|
|
93
|
-
return (result == null ? void 0 : result.message) || (result == null ? void 0 : result.msg) || ((_a = result == null ? void 0 : result.data) == null ? void 0 : _a.message) || ((_b = result == null ? void 0 : result.data) == null ? void 0 : _b.msg) || fallbackMessage;
|
|
67
|
+
return result?.message || result?.msg || result?.data?.message || result?.data?.msg || fallbackMessage;
|
|
94
68
|
}
|
|
95
69
|
function toWalletFundValue(value) {
|
|
96
70
|
try {
|
|
97
|
-
return new
|
|
71
|
+
return new _decimal.default(value || 0).toDecimalPlaces(2).toFixed(2);
|
|
98
72
|
} catch {
|
|
99
|
-
return
|
|
73
|
+
return '0.00';
|
|
100
74
|
}
|
|
101
75
|
}
|
|
102
76
|
function subtractWalletFundValue(left, right) {
|
|
103
77
|
try {
|
|
104
|
-
return new
|
|
78
|
+
return new _decimal.default(left || 0).minus(right || 0).toDecimalPlaces(2).toFixed(2);
|
|
105
79
|
} catch {
|
|
106
|
-
return
|
|
80
|
+
return '0.00';
|
|
107
81
|
}
|
|
108
82
|
}
|
|
109
83
|
function getSharedWalletPassUseValue(params) {
|
|
110
|
-
const {
|
|
111
|
-
|
|
84
|
+
const {
|
|
85
|
+
asset,
|
|
86
|
+
amount,
|
|
87
|
+
paymentMethod
|
|
88
|
+
} = params;
|
|
89
|
+
const configuredValue = Number(asset?.wallet_pass_use_value);
|
|
112
90
|
if (Number.isFinite(configuredValue) && configuredValue > 0) {
|
|
113
91
|
return configuredValue;
|
|
114
92
|
}
|
|
115
|
-
const isPointCard =
|
|
116
|
-
const usageUnit = asset
|
|
117
|
-
if (isPointCard &&
|
|
118
|
-
return new
|
|
93
|
+
const isPointCard = asset?.tag === 'point_card' || paymentMethod.code === 'POINTCARD';
|
|
94
|
+
const usageUnit = asset?.wallet_pass_usage_unit;
|
|
95
|
+
if (isPointCard && usageUnit?.points && usageUnit?.price) {
|
|
96
|
+
return new _decimal.default(amount).div(usageUnit.price).mul(usageUnit.points).toDecimalPlaces(2, _decimal.default.ROUND_DOWN).toNumber();
|
|
119
97
|
}
|
|
120
98
|
return amount;
|
|
121
99
|
}
|
|
122
100
|
function buildSharedWalletFundRecord(params) {
|
|
123
|
-
const {
|
|
124
|
-
|
|
125
|
-
|
|
101
|
+
const {
|
|
102
|
+
asset,
|
|
103
|
+
amount,
|
|
104
|
+
paymentMethod
|
|
105
|
+
} = params;
|
|
106
|
+
const isPointCard = asset?.tag === 'point_card' || paymentMethod.code === 'POINTCARD';
|
|
107
|
+
const usingBeforeValue = asset?.balance_par_value ?? asset?.balance ?? asset?.using_before_value ?? 0;
|
|
126
108
|
const walletPassUseValue = getSharedWalletPassUseValue(params);
|
|
127
109
|
const usingValue = isPointCard ? walletPassUseValue : amount;
|
|
128
|
-
const walletPassName =
|
|
110
|
+
const walletPassName = asset?.wallet_pass_name || asset?.format_title || asset?.product_name || asset?.name || paymentMethod.name;
|
|
129
111
|
return {
|
|
130
|
-
voucher_id:
|
|
131
|
-
wallet_pass_name: walletPassName && typeof walletPassName ===
|
|
132
|
-
|
|
133
|
-
|
|
112
|
+
voucher_id: asset?.voucher_id ?? asset?.id,
|
|
113
|
+
wallet_pass_name: walletPassName && typeof walletPassName === 'object' ? walletPassName : {
|
|
114
|
+
default: walletPassName || ''
|
|
115
|
+
},
|
|
116
|
+
code: asset?.code || asset?.tag,
|
|
117
|
+
encoded: asset?.encoded,
|
|
134
118
|
using_before_value: toWalletFundValue(usingBeforeValue),
|
|
135
119
|
using_after_value: subtractWalletFundValue(usingBeforeValue, usingValue)
|
|
136
120
|
};
|
|
137
121
|
}
|
|
138
122
|
function isBaseSalesManualProductDiscountProduct(product) {
|
|
139
|
-
|
|
140
|
-
return ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.is_manual_discount) === true || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.is_manual_discount) === 1 || ((product == null ? void 0 : product.discount_list) || []).some((item) => (item == null ? void 0 : item.type) === "product");
|
|
123
|
+
return product?.metadata?.is_manual_discount === true || product?.metadata?.is_manual_discount === 1 || (product?.discount_list || []).some(item => item?.type === 'product');
|
|
141
124
|
}
|
|
142
125
|
function getBaseSalesProductUid(product) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (uid === void 0 || uid === null || uid === "")
|
|
146
|
-
return null;
|
|
126
|
+
const uid = product?.metadata?.unique_identification_number || product?.unique_identification_number;
|
|
127
|
+
if (uid === undefined || uid === null || uid === '') return null;
|
|
147
128
|
return String(uid);
|
|
148
129
|
}
|
|
149
130
|
function preserveManualProductDiscountProducts(previousProducts, nextProducts) {
|
|
150
|
-
const previousByUid =
|
|
131
|
+
const previousByUid = new Map();
|
|
151
132
|
(previousProducts || []).forEach((product, index) => {
|
|
152
133
|
const uid = getBaseSalesProductUid(product);
|
|
153
|
-
if (uid)
|
|
154
|
-
previousByUid.set(uid, product);
|
|
134
|
+
if (uid) previousByUid.set(uid, product);
|
|
155
135
|
previousByUid.set(`__index__:${index}`, product);
|
|
156
136
|
});
|
|
157
137
|
return (nextProducts || []).map((product, index) => {
|
|
158
138
|
const uid = getBaseSalesProductUid(product);
|
|
159
|
-
const previous = (uid ? previousByUid.get(uid) :
|
|
139
|
+
const previous = (uid ? previousByUid.get(uid) : undefined) || previousByUid.get(`__index__:${index}`);
|
|
160
140
|
return previous && isBaseSalesManualProductDiscountProduct(previous) ? previous : product;
|
|
161
141
|
});
|
|
162
142
|
}
|
|
163
143
|
function isBaseSalesHistoricalDiscountEntry(discount) {
|
|
164
|
-
return Boolean(
|
|
165
|
-
(discount == null ? void 0 : discount.isEditMode) || (discount == null ? void 0 : discount.isDisabled) || (discount == null ? void 0 : discount.order_discount_id) != null
|
|
166
|
-
);
|
|
144
|
+
return Boolean(discount?.isEditMode || discount?.isDisabled || discount?.order_discount_id != null);
|
|
167
145
|
}
|
|
168
146
|
function getBaseSalesUniqueArrayMetadataKey(key) {
|
|
169
|
-
if (key ===
|
|
170
|
-
return "unique_identification_number";
|
|
147
|
+
if (key === 'products' || key === 'bookings') return 'unique_identification_number';
|
|
171
148
|
return null;
|
|
172
149
|
}
|
|
173
|
-
|
|
174
|
-
product:
|
|
175
|
-
booking:
|
|
176
|
-
payment:
|
|
150
|
+
const BASE_SALES_PERSISTENT_ID_FIELD_BY_KIND = {
|
|
151
|
+
product: 'order_detail_id',
|
|
152
|
+
booking: 'schedule_event_id',
|
|
153
|
+
payment: 'order_payment_id'
|
|
177
154
|
};
|
|
178
155
|
function getBaseSalesOrderCollectionKind(key) {
|
|
179
|
-
if (key ===
|
|
180
|
-
|
|
181
|
-
if (key ===
|
|
182
|
-
return "booking";
|
|
183
|
-
if (key === "payments" || key === "payment")
|
|
184
|
-
return "payment";
|
|
156
|
+
if (key === 'products') return 'product';
|
|
157
|
+
if (key === 'bookings') return 'booking';
|
|
158
|
+
if (key === 'payments' || key === 'payment') return 'payment';
|
|
185
159
|
return null;
|
|
186
160
|
}
|
|
187
161
|
function isSameBaseSalesOrderRecord(left, right) {
|
|
188
|
-
if (!left || !right || typeof left !==
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
);
|
|
193
|
-
if (leftIdentities.size === 0)
|
|
194
|
-
return false;
|
|
195
|
-
return [right.order_id, right.id, right.external_sale_number, right.order_number].some(
|
|
196
|
-
(value) => value !== void 0 && value !== null && value !== "" && leftIdentities.has(String(value))
|
|
197
|
-
);
|
|
162
|
+
if (!left || !right || typeof left !== 'object' || typeof right !== 'object') return false;
|
|
163
|
+
const leftIdentities = new Set([left.order_id, left.id, left.external_sale_number, left.order_number].filter(value => value !== undefined && value !== null && value !== '').map(String));
|
|
164
|
+
if (leftIdentities.size === 0) return false;
|
|
165
|
+
return [right.order_id, right.id, right.external_sale_number, right.order_number].some(value => value !== undefined && value !== null && value !== '' && leftIdentities.has(String(value)));
|
|
198
166
|
}
|
|
199
167
|
function isBaseSalesBlankValue(value) {
|
|
200
|
-
return value ===
|
|
168
|
+
return value === undefined || value === null || value === '';
|
|
201
169
|
}
|
|
202
170
|
function mergeBaseSalesProductSnapshotFields(currentItem, loadedItem) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (isBaseSalesBlankValue(mergedItem.product_cover) && !isBaseSalesBlankValue(currentItem == null ? void 0 : currentItem.product_cover)) {
|
|
171
|
+
const mergedItem = (0, _lodashEs.cloneDeep)(loadedItem);
|
|
172
|
+
if (isBaseSalesBlankValue(mergedItem.product_cover) && !isBaseSalesBlankValue(currentItem?.product_cover)) {
|
|
206
173
|
mergedItem.product_cover = currentItem.product_cover;
|
|
207
174
|
}
|
|
208
|
-
const currentHolderConfig =
|
|
209
|
-
if ((
|
|
175
|
+
const currentHolderConfig = currentItem?.metadata?.holder_config;
|
|
176
|
+
if ((mergedItem.metadata?.holder_config === undefined || mergedItem.metadata?.holder_config === null) && currentHolderConfig !== undefined && currentHolderConfig !== null) {
|
|
210
177
|
mergedItem.metadata = {
|
|
211
|
-
...mergedItem.metadata || {},
|
|
178
|
+
...(mergedItem.metadata || {}),
|
|
212
179
|
holder_config: currentHolderConfig
|
|
213
180
|
};
|
|
214
181
|
}
|
|
215
182
|
return mergedItem;
|
|
216
183
|
}
|
|
217
184
|
function mergeBaseSalesCollectionItem(kind, currentItem, incomingItem, uidRemaps) {
|
|
218
|
-
const currentReferenceUid = (0,
|
|
219
|
-
const incomingReferenceUid = (0,
|
|
220
|
-
const identityMergedItem = (0,
|
|
221
|
-
|
|
222
|
-
currentItem,
|
|
223
|
-
incomingItem
|
|
224
|
-
);
|
|
225
|
-
const mergedUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)(kind, identityMergedItem);
|
|
185
|
+
const currentReferenceUid = (0, _orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, currentItem);
|
|
186
|
+
const incomingReferenceUid = (0, _orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, incomingItem);
|
|
187
|
+
const identityMergedItem = (0, _orderCollectionIdentity.mergeOrderCollectionItems)(kind, currentItem, incomingItem);
|
|
188
|
+
const mergedUid = (0, _orderCollectionIdentity.getOrderCollectionUid)(kind, identityMergedItem);
|
|
226
189
|
if (mergedUid) {
|
|
227
|
-
for (const from of
|
|
228
|
-
if (!from || from === mergedUid)
|
|
229
|
-
continue;
|
|
190
|
+
for (const from of new Set([currentReferenceUid, incomingReferenceUid])) {
|
|
191
|
+
if (!from || from === mergedUid) continue;
|
|
230
192
|
uidRemaps.push({
|
|
231
193
|
kind,
|
|
232
194
|
from,
|
|
233
195
|
to: mergedUid,
|
|
234
|
-
persistentId: (0,
|
|
196
|
+
persistentId: (0, _orderCollectionIdentity.getOrderCollectionPersistentId)(kind, incomingItem) || (0, _orderCollectionIdentity.getOrderCollectionPersistentId)(kind, currentItem)
|
|
235
197
|
});
|
|
236
198
|
}
|
|
237
199
|
}
|
|
238
|
-
const mergedItem = mergedUid ? (0,
|
|
200
|
+
const mergedItem = mergedUid ? (0, _orderCollectionIdentity.setOrderCollectionUid)(kind, incomingItem, mergedUid) : (0, _lodashEs.cloneDeep)(incomingItem);
|
|
239
201
|
const persistentIdField = BASE_SALES_PERSISTENT_ID_FIELD_BY_KIND[kind];
|
|
240
202
|
if (isBaseSalesBlankValue(mergedItem[persistentIdField]) && !isBaseSalesBlankValue(identityMergedItem[persistentIdField])) {
|
|
241
203
|
mergedItem[persistentIdField] = identityMergedItem[persistentIdField];
|
|
242
204
|
}
|
|
243
|
-
return kind ===
|
|
205
|
+
return kind === 'product' ? mergeBaseSalesProductSnapshotFields(currentItem, mergedItem) : mergedItem;
|
|
244
206
|
}
|
|
245
207
|
function mergeBaseSalesOrderCollection(kind, currentValue, incomingValue, strategy, uidRemaps) {
|
|
246
|
-
if (kind ===
|
|
247
|
-
return (0,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
);
|
|
208
|
+
if (kind === 'payment') {
|
|
209
|
+
return (0, _paymentUtils.mergeOrderPaymentListsByIdentity)(currentValue, incomingValue, strategy === 'preserve-local' ? {
|
|
210
|
+
preserveUnmatchedExisting: true
|
|
211
|
+
} : {
|
|
212
|
+
preserveUnmatchedExistingWhen: payment => (0, _paymentUtils.isIdentifiedPendingOrderPayment)(payment) || !(0, _orderCollectionIdentity.getOrderCollectionPersistentId)('payment', payment)
|
|
213
|
+
});
|
|
254
214
|
}
|
|
255
|
-
const currentItems = (0,
|
|
215
|
+
const currentItems = (0, _orderCollectionIdentity.normalizeOrderCollection)(kind, currentValue, {
|
|
256
216
|
ensureUid: false
|
|
257
217
|
}).items;
|
|
258
|
-
const incomingItems = (0,
|
|
218
|
+
const incomingItems = (0, _orderCollectionIdentity.normalizeOrderCollection)(kind, incomingValue, {
|
|
259
219
|
ensureUid: false
|
|
260
220
|
}).items;
|
|
261
|
-
if (strategy ===
|
|
262
|
-
const
|
|
263
|
-
currentItems.forEach(
|
|
264
|
-
const incomingIndex =
|
|
265
|
-
(incomingItem) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, currentItem, incomingItem)
|
|
266
|
-
);
|
|
221
|
+
if (strategy === 'authoritative-incoming') {
|
|
222
|
+
const result = (0, _lodashEs.cloneDeep)(incomingItems);
|
|
223
|
+
currentItems.forEach(currentItem => {
|
|
224
|
+
const incomingIndex = result.findIndex(incomingItem => (0, _orderCollectionIdentity.isSameOrderCollectionItem)(kind, currentItem, incomingItem));
|
|
267
225
|
if (incomingIndex !== -1) {
|
|
268
|
-
|
|
269
|
-
kind,
|
|
270
|
-
currentItem,
|
|
271
|
-
result2[incomingIndex],
|
|
272
|
-
uidRemaps
|
|
273
|
-
);
|
|
226
|
+
result[incomingIndex] = mergeBaseSalesCollectionItem(kind, currentItem, result[incomingIndex], uidRemaps);
|
|
274
227
|
return;
|
|
275
228
|
}
|
|
276
|
-
|
|
277
|
-
|
|
229
|
+
|
|
230
|
+
// 完整服务端快照负责已落库行;仅保留尚未提交的本地新行。
|
|
231
|
+
if (!(0, _orderCollectionIdentity.getOrderCollectionPersistentId)(kind, currentItem)) {
|
|
232
|
+
result.push((0, _lodashEs.cloneDeep)(currentItem));
|
|
278
233
|
}
|
|
279
234
|
});
|
|
280
|
-
return
|
|
235
|
+
return result;
|
|
281
236
|
}
|
|
282
|
-
const result = (0,
|
|
283
|
-
incomingItems.forEach(
|
|
284
|
-
const currentIndex = result.findIndex(
|
|
285
|
-
(currentItem) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, currentItem, incomingItem)
|
|
286
|
-
);
|
|
237
|
+
const result = (0, _lodashEs.cloneDeep)(currentItems);
|
|
238
|
+
incomingItems.forEach(incomingItem => {
|
|
239
|
+
const currentIndex = result.findIndex(currentItem => (0, _orderCollectionIdentity.isSameOrderCollectionItem)(kind, currentItem, incomingItem));
|
|
287
240
|
if (currentIndex !== -1) {
|
|
288
|
-
result[currentIndex] = mergeBaseSalesCollectionItem(
|
|
289
|
-
kind,
|
|
290
|
-
result[currentIndex],
|
|
291
|
-
incomingItem,
|
|
292
|
-
uidRemaps
|
|
293
|
-
);
|
|
241
|
+
result[currentIndex] = mergeBaseSalesCollectionItem(kind, result[currentIndex], incomingItem, uidRemaps);
|
|
294
242
|
return;
|
|
295
243
|
}
|
|
296
|
-
result.push((0,
|
|
244
|
+
result.push((0, _lodashEs.cloneDeep)(incomingItem));
|
|
297
245
|
});
|
|
298
246
|
return result;
|
|
299
247
|
}
|
|
300
248
|
function normalizeBaseSalesRecordCollections(sourceRecord, options) {
|
|
301
|
-
const normalizedRecord = (0,
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
).order;
|
|
249
|
+
const normalizedRecord = (0, _orderCollectionIdentity.normalizeOrderCollections)((0, _lodashEs.cloneDeep)(sourceRecord || {}), options).order;
|
|
250
|
+
|
|
251
|
+
// 兼容旧调用方偶尔使用的单数 payment 字段。
|
|
305
252
|
if (Array.isArray(normalizedRecord.payment)) {
|
|
306
|
-
normalizedRecord.payment = (0,
|
|
307
|
-
"payment",
|
|
308
|
-
normalizedRecord.payment,
|
|
309
|
-
options
|
|
310
|
-
).items;
|
|
253
|
+
normalizedRecord.payment = (0, _orderCollectionIdentity.normalizeOrderCollection)('payment', normalizedRecord.payment, options).items;
|
|
311
254
|
}
|
|
312
255
|
return normalizedRecord;
|
|
313
256
|
}
|
|
314
257
|
function getBaseSalesMetadataUid(item, metadataKey) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (uid === void 0 || uid === null || uid === "")
|
|
318
|
-
return null;
|
|
258
|
+
const uid = item?.metadata?.[metadataKey] ?? item?.[metadataKey];
|
|
259
|
+
if (uid === undefined || uid === null || uid === '') return null;
|
|
319
260
|
return String(uid);
|
|
320
261
|
}
|
|
321
262
|
function mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey) {
|
|
322
263
|
const result = [];
|
|
323
|
-
const indexByUid =
|
|
324
|
-
const appendOrReplaceByUid =
|
|
325
|
-
const clonedItem = (0,
|
|
264
|
+
const indexByUid = new Map();
|
|
265
|
+
const appendOrReplaceByUid = item => {
|
|
266
|
+
const clonedItem = (0, _lodashEs.cloneDeep)(item);
|
|
326
267
|
const uid = getBaseSalesMetadataUid(clonedItem, metadataKey);
|
|
327
268
|
if (!uid) {
|
|
328
269
|
result.push(clonedItem);
|
|
329
270
|
return;
|
|
330
271
|
}
|
|
331
272
|
const existingIndex = indexByUid.get(uid);
|
|
332
|
-
if (existingIndex !==
|
|
273
|
+
if (existingIndex !== undefined) {
|
|
333
274
|
result[existingIndex] = clonedItem;
|
|
334
275
|
return;
|
|
335
276
|
}
|
|
@@ -341,130 +282,142 @@ function mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey) {
|
|
|
341
282
|
return result;
|
|
342
283
|
}
|
|
343
284
|
function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord, strategy) {
|
|
344
|
-
const normalizedLoadedRecord = normalizeBaseSalesRecordCollections(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
);
|
|
285
|
+
const normalizedLoadedRecord = normalizeBaseSalesRecordCollections(loadedRecord || {}, {
|
|
286
|
+
ensureUid: false
|
|
287
|
+
});
|
|
348
288
|
if (!currentTempOrder) {
|
|
349
289
|
return normalizeBaseSalesRecordCollections(normalizedLoadedRecord);
|
|
350
290
|
}
|
|
351
|
-
const normalizedCurrentTempOrder = normalizeBaseSalesRecordCollections(
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
);
|
|
291
|
+
const normalizedCurrentTempOrder = normalizeBaseSalesRecordCollections(currentTempOrder, {
|
|
292
|
+
ensureUid: false
|
|
293
|
+
});
|
|
355
294
|
const uidRemaps = [];
|
|
356
|
-
const mergedRecord = (0,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
strategy,
|
|
367
|
-
uidRemaps
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
if (Array.isArray(currentValue) && Array.isArray(loadedValue)) {
|
|
371
|
-
if (key === "payments" || key === "payment") {
|
|
372
|
-
return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(currentValue, loadedValue, {
|
|
373
|
-
preserveUnmatchedExisting: true
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
const metadataKey = getBaseSalesUniqueArrayMetadataKey(key);
|
|
377
|
-
if (metadataKey) {
|
|
378
|
-
return mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey);
|
|
379
|
-
}
|
|
380
|
-
return [
|
|
381
|
-
...(0, import_lodash_es.cloneDeep)(currentValue),
|
|
382
|
-
...(0, import_lodash_es.cloneDeep)(loadedValue)
|
|
383
|
-
];
|
|
295
|
+
const mergedRecord = (0, _lodashEs.mergeWith)(normalizedCurrentTempOrder, normalizedLoadedRecord, (currentValue, loadedValue, key) => {
|
|
296
|
+
const collectionKind = getBaseSalesOrderCollectionKind(key);
|
|
297
|
+
if (collectionKind && Array.isArray(loadedValue)) {
|
|
298
|
+
return mergeBaseSalesOrderCollection(collectionKind, Array.isArray(currentValue) ? currentValue : [], loadedValue, strategy, uidRemaps);
|
|
299
|
+
}
|
|
300
|
+
if (Array.isArray(currentValue) && Array.isArray(loadedValue)) {
|
|
301
|
+
if (key === 'payments' || key === 'payment') {
|
|
302
|
+
return (0, _paymentUtils.mergeOrderPaymentListsByIdentity)(currentValue, loadedValue, {
|
|
303
|
+
preserveUnmatchedExisting: true
|
|
304
|
+
});
|
|
384
305
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return (0, import_lodash_es.cloneDeep)(currentValue);
|
|
306
|
+
const metadataKey = getBaseSalesUniqueArrayMetadataKey(key);
|
|
307
|
+
if (metadataKey) {
|
|
308
|
+
return mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey);
|
|
389
309
|
}
|
|
390
|
-
return
|
|
310
|
+
return [...(0, _lodashEs.cloneDeep)(currentValue), ...(0, _lodashEs.cloneDeep)(loadedValue)];
|
|
311
|
+
}
|
|
312
|
+
if (Array.isArray(loadedValue)) return (0, _lodashEs.cloneDeep)(loadedValue);
|
|
313
|
+
if (Array.isArray(currentValue) && loadedValue === undefined) {
|
|
314
|
+
return (0, _lodashEs.cloneDeep)(currentValue);
|
|
391
315
|
}
|
|
392
|
-
|
|
316
|
+
return undefined;
|
|
317
|
+
});
|
|
393
318
|
delete mergedRecord.request_unique_idempotency_token;
|
|
394
|
-
return normalizeBaseSalesRecordCollections(
|
|
395
|
-
(0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(mergedRecord, uidRemaps)
|
|
396
|
-
);
|
|
319
|
+
return normalizeBaseSalesRecordCollections((0, _orderCollectionIdentity.applyOrderCollectionUidRemaps)(mergedRecord, uidRemaps));
|
|
397
320
|
}
|
|
398
321
|
function filterPendingPaymentsFromLoadedSalesDetail(sourceRecord) {
|
|
399
|
-
if (!sourceRecord || typeof sourceRecord !==
|
|
400
|
-
|
|
401
|
-
|
|
322
|
+
if (!sourceRecord || typeof sourceRecord !== 'object') return sourceRecord;
|
|
323
|
+
const record = {
|
|
324
|
+
...sourceRecord
|
|
325
|
+
};
|
|
402
326
|
if (Array.isArray(sourceRecord.payments)) {
|
|
403
|
-
record.payments = sourceRecord.payments.filter(
|
|
327
|
+
record.payments = sourceRecord.payments.filter(payment => !(0, _paymentUtils.isPendingOrderPayment)(payment));
|
|
404
328
|
}
|
|
329
|
+
// 兼容少量历史详情数据使用的单数 payment 字段。
|
|
405
330
|
if (Array.isArray(sourceRecord.payment)) {
|
|
406
|
-
record.payment = sourceRecord.payment.filter(
|
|
331
|
+
record.payment = sourceRecord.payment.filter(payment => !(0, _paymentUtils.isPendingOrderPayment)(payment));
|
|
407
332
|
}
|
|
408
333
|
return record;
|
|
409
334
|
}
|
|
410
|
-
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* merge hydrate 不会统一给所有商品补 saved 标记,因此先只标记远端已保存商品。
|
|
338
|
+
* 当前 tempOrder 中尚未提交的本地商品会在 merge 后继续保持 current item 语义。
|
|
339
|
+
*/
|
|
340
|
+
function markLoadedSalesDetailProductsAsSaved(sourceRecord) {
|
|
341
|
+
if (!sourceRecord || typeof sourceRecord !== 'object') return sourceRecord;
|
|
342
|
+
if (!Array.isArray(sourceRecord.products)) return sourceRecord;
|
|
343
|
+
return {
|
|
344
|
+
...sourceRecord,
|
|
345
|
+
products: sourceRecord.products.map(product => ({
|
|
346
|
+
...(product || {}),
|
|
347
|
+
metadata: {
|
|
348
|
+
...(product?.metadata && typeof product.metadata === 'object' ? product.metadata : {}),
|
|
349
|
+
is_edit_for_runtime: true
|
|
350
|
+
}
|
|
351
|
+
}))
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
355
|
+
defaultName = 'baseSales';
|
|
356
|
+
defaultVersion = '1.0.0';
|
|
357
|
+
isSolution = true;
|
|
358
|
+
initializeOptions = {};
|
|
359
|
+
logger; // LoggerManager 实例
|
|
360
|
+
appPlugin;
|
|
361
|
+
store = {
|
|
362
|
+
order: undefined
|
|
363
|
+
};
|
|
364
|
+
otherParams = {};
|
|
365
|
+
cacheId;
|
|
366
|
+
/**
|
|
367
|
+
* 由已在初始化阶段解析过设备短号的业务解决方案写入。
|
|
368
|
+
* 未设置时,支付编号仍按原逻辑实时读取设备信息。
|
|
369
|
+
*/
|
|
370
|
+
paymentNumberDevicePrefix = null;
|
|
371
|
+
/**
|
|
372
|
+
* window / request 暴露为 public:现存外部工具(如 BookingTicket Scan)通过
|
|
373
|
+
* `solution.window` / `solution.request` 直接访问插件,保持原有契约不破坏。
|
|
374
|
+
*/
|
|
375
|
+
window;
|
|
376
|
+
request;
|
|
377
|
+
|
|
378
|
+
// 当前缓存中已加载的最新 SalesDetail;只读 getter 走它对外暴露详情数据。
|
|
379
|
+
currentSalesDetail = null;
|
|
380
|
+
discountConfigCacheKey = null;
|
|
381
|
+
hasManualDiscountSelection = false;
|
|
382
|
+
reusedSharedSubModuleNames = new Set();
|
|
383
|
+
paymentMethodsCache = [];
|
|
384
|
+
queuedAutoPaymentSync = false;
|
|
385
|
+
autoPaymentSyncFlushing = false;
|
|
386
|
+
autoPaymentSyncTimer = null;
|
|
387
|
+
salesDetailLoadInFlightCount = 0;
|
|
388
|
+
salesDetailLoadSequence = 0;
|
|
389
|
+
walletAssetsRefreshSequence = 0;
|
|
390
|
+
salesDetailHydrateQueue = Promise.resolve();
|
|
391
|
+
serverOrderChangeUnsubscribe = null;
|
|
392
|
+
serverOrderChangeHydrateInFlight = null;
|
|
393
|
+
queuedServerOrderChanges = [];
|
|
394
|
+
serverOrderChangeSyncEnabled = false;
|
|
411
395
|
constructor(name, version) {
|
|
412
396
|
super(name, version);
|
|
413
|
-
this.defaultName = "baseSales";
|
|
414
|
-
this.defaultVersion = "1.0.0";
|
|
415
|
-
this.isSolution = true;
|
|
416
|
-
this.initializeOptions = {};
|
|
417
|
-
this.store = {
|
|
418
|
-
order: void 0
|
|
419
|
-
};
|
|
420
|
-
this.otherParams = {};
|
|
421
|
-
/**
|
|
422
|
-
* 由已在初始化阶段解析过设备短号的业务解决方案写入。
|
|
423
|
-
* 未设置时,支付编号仍按原逻辑实时读取设备信息。
|
|
424
|
-
*/
|
|
425
|
-
this.paymentNumberDevicePrefix = null;
|
|
426
|
-
// 当前缓存中已加载的最新 SalesDetail;只读 getter 走它对外暴露详情数据。
|
|
427
|
-
this.currentSalesDetail = null;
|
|
428
|
-
this.discountConfigCacheKey = null;
|
|
429
|
-
this.hasManualDiscountSelection = false;
|
|
430
|
-
this.reusedSharedSubModuleNames = /* @__PURE__ */ new Set();
|
|
431
|
-
this.paymentMethodsCache = [];
|
|
432
|
-
this.queuedAutoPaymentSync = false;
|
|
433
|
-
this.autoPaymentSyncFlushing = false;
|
|
434
|
-
this.autoPaymentSyncTimer = null;
|
|
435
|
-
this.salesDetailLoadInFlightCount = 0;
|
|
436
|
-
this.salesDetailLoadSequence = 0;
|
|
437
|
-
this.walletAssetsRefreshSequence = 0;
|
|
438
|
-
this.salesDetailHydrateQueue = Promise.resolve();
|
|
439
|
-
this.serverOrderChangeUnsubscribe = null;
|
|
440
|
-
this.serverOrderChangeHydrateInFlight = null;
|
|
441
|
-
this.queuedServerOrderChanges = [];
|
|
442
|
-
this.serverOrderChangeSyncEnabled = false;
|
|
443
397
|
}
|
|
398
|
+
|
|
444
399
|
/**
|
|
445
400
|
* 子类可覆盖此方法以追加/收敛要注册的子模块。
|
|
446
401
|
* 默认包含通用销售模块:products / order / salesSummary / schedule / payment / quotation。
|
|
447
402
|
*/
|
|
448
403
|
getRegisteredModuleNames() {
|
|
449
|
-
return [
|
|
404
|
+
return ['products', 'order', 'salesSummary', 'schedule', 'payment', 'quotation'];
|
|
450
405
|
}
|
|
451
406
|
getReusableSharedSubModule(moduleName) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
return null;
|
|
455
|
-
return ((_b = (_a = this.core) == null ? void 0 : _a.getModule) == null ? void 0 : _b.call(_a, moduleName)) || null;
|
|
407
|
+
if (moduleName !== 'schedule' && moduleName !== 'quotation') return null;
|
|
408
|
+
return this.core?.getModule?.(moduleName) || null;
|
|
456
409
|
}
|
|
457
410
|
isScheduleListLoaded(scheduleModule) {
|
|
458
|
-
if (!scheduleModule)
|
|
459
|
-
|
|
460
|
-
if (typeof scheduleModule.isScheduleListLoaded === "function") {
|
|
411
|
+
if (!scheduleModule) return false;
|
|
412
|
+
if (typeof scheduleModule.isScheduleListLoaded === 'function') {
|
|
461
413
|
return scheduleModule.isScheduleListLoaded();
|
|
462
414
|
}
|
|
463
|
-
if (typeof scheduleModule.getScheduleList ===
|
|
415
|
+
if (typeof scheduleModule.getScheduleList === 'function') {
|
|
464
416
|
return Array.isArray(scheduleModule.getScheduleList());
|
|
465
417
|
}
|
|
466
418
|
return false;
|
|
467
419
|
}
|
|
420
|
+
|
|
468
421
|
/**
|
|
469
422
|
* 记录信息日志
|
|
470
423
|
*/
|
|
@@ -472,12 +425,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
472
425
|
if (this.logger) {
|
|
473
426
|
const tempOrder = this.getTempOrder();
|
|
474
427
|
this.logger.addLog({
|
|
475
|
-
type:
|
|
476
|
-
title: `[BaseSales] ${tempOrder
|
|
428
|
+
type: 'info',
|
|
429
|
+
title: `[BaseSales] ${tempOrder?.order_id} ${tempOrder?.external_sale_number} ${title}`,
|
|
477
430
|
metadata: metadata || {}
|
|
478
431
|
});
|
|
479
432
|
}
|
|
480
433
|
}
|
|
434
|
+
|
|
481
435
|
/**
|
|
482
436
|
* 记录警告日志
|
|
483
437
|
*/
|
|
@@ -485,12 +439,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
485
439
|
if (this.logger) {
|
|
486
440
|
const tempOrder = this.getTempOrder();
|
|
487
441
|
this.logger.addLog({
|
|
488
|
-
type:
|
|
489
|
-
title: `[BaseSales] ${tempOrder
|
|
442
|
+
type: 'warning',
|
|
443
|
+
title: `[BaseSales] ${tempOrder?.order_id} ${tempOrder?.external_sale_number} ${title}`,
|
|
490
444
|
metadata: metadata || {}
|
|
491
445
|
});
|
|
492
446
|
}
|
|
493
447
|
}
|
|
448
|
+
|
|
494
449
|
/**
|
|
495
450
|
* 记录错误日志
|
|
496
451
|
*/
|
|
@@ -498,31 +453,24 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
498
453
|
if (this.logger) {
|
|
499
454
|
const tempOrder = this.getTempOrder();
|
|
500
455
|
this.logger.addLog({
|
|
501
|
-
type:
|
|
502
|
-
title: `[BaseSales] ${tempOrder
|
|
456
|
+
type: 'error',
|
|
457
|
+
title: `[BaseSales] ${tempOrder?.order_id} ${tempOrder?.external_sale_number} ${title}`,
|
|
503
458
|
metadata: metadata || {}
|
|
504
459
|
});
|
|
505
460
|
}
|
|
506
461
|
}
|
|
507
462
|
isCurrentSalesOrderRecord(order) {
|
|
508
|
-
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
currentTempOrder,
|
|
512
|
-
this.currentSalesDetail
|
|
513
|
-
].filter(Boolean);
|
|
514
|
-
return currentRecords.some((record) => isSameBaseSalesOrderRecord(record, order));
|
|
463
|
+
const currentTempOrder = this.store.order?.getTempOrder?.();
|
|
464
|
+
const currentRecords = [currentTempOrder, this.currentSalesDetail].filter(Boolean);
|
|
465
|
+
return currentRecords.some(record => isSameBaseSalesOrderRecord(record, order));
|
|
515
466
|
}
|
|
516
467
|
setServerOrderChangeSyncEnabled(enabled) {
|
|
517
468
|
this.serverOrderChangeSyncEnabled = enabled;
|
|
518
|
-
if (!enabled)
|
|
519
|
-
this.queuedServerOrderChanges = [];
|
|
469
|
+
if (!enabled) this.queuedServerOrderChanges = [];
|
|
520
470
|
}
|
|
521
471
|
queueLatestServerOrderChange(order) {
|
|
522
|
-
const snapshot = (0,
|
|
523
|
-
const existingIndex = this.queuedServerOrderChanges.findIndex(
|
|
524
|
-
(queued) => isSameBaseSalesOrderRecord(queued, snapshot)
|
|
525
|
-
);
|
|
472
|
+
const snapshot = (0, _lodashEs.cloneDeep)(order);
|
|
473
|
+
const existingIndex = this.queuedServerOrderChanges.findIndex(queued => isSameBaseSalesOrderRecord(queued, snapshot));
|
|
526
474
|
if (existingIndex >= 0) {
|
|
527
475
|
this.queuedServerOrderChanges[existingIndex] = snapshot;
|
|
528
476
|
return;
|
|
@@ -530,46 +478,40 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
530
478
|
this.queuedServerOrderChanges.push(snapshot);
|
|
531
479
|
}
|
|
532
480
|
async drainQueuedServerOrderChanges() {
|
|
533
|
-
if (!this.serverOrderChangeSyncEnabled || this.salesDetailLoadInFlightCount > 0 || this.serverOrderChangeHydrateInFlight || this.queuedServerOrderChanges.length === 0)
|
|
534
|
-
return;
|
|
481
|
+
if (!this.serverOrderChangeSyncEnabled || this.salesDetailLoadInFlightCount > 0 || this.serverOrderChangeHydrateInFlight || this.queuedServerOrderChanges.length === 0) return;
|
|
535
482
|
const changedOrders = this.queuedServerOrderChanges;
|
|
536
483
|
this.queuedServerOrderChanges = [];
|
|
537
|
-
await this.syncCurrentSalesDetailFromServerOrderChange({
|
|
484
|
+
await this.syncCurrentSalesDetailFromServerOrderChange({
|
|
485
|
+
changedOrders
|
|
486
|
+
});
|
|
538
487
|
}
|
|
539
488
|
async syncCurrentSalesDetailFromServerOrderChange(payload) {
|
|
540
|
-
const changedOrders = Array.isArray(payload) ? payload : Array.isArray(payload
|
|
541
|
-
if (!this.serverOrderChangeSyncEnabled)
|
|
542
|
-
|
|
489
|
+
const changedOrders = Array.isArray(payload) ? payload : Array.isArray(payload?.changedOrders) ? payload.changedOrders : payload?.data && typeof payload.data === 'object' ? [payload.data] : [];
|
|
490
|
+
if (!this.serverOrderChangeSyncEnabled) return;
|
|
491
|
+
|
|
492
|
+
// 显式详情加载期间 current 可能仍是上一单,先按订单身份 latest-only 缓存;
|
|
493
|
+
// load 完成后再用新的 current 过滤,避免恰好到达的最新支付快照丢失。
|
|
543
494
|
if (this.salesDetailLoadInFlightCount > 0) {
|
|
544
|
-
changedOrders.forEach(
|
|
545
|
-
(order) => this.queueLatestServerOrderChange(order)
|
|
546
|
-
);
|
|
495
|
+
changedOrders.forEach(order => this.queueLatestServerOrderChange(order));
|
|
547
496
|
return;
|
|
548
497
|
}
|
|
549
|
-
const changedOrder = changedOrders.find(
|
|
550
|
-
|
|
551
|
-
);
|
|
552
|
-
if (!changedOrder)
|
|
553
|
-
return;
|
|
498
|
+
const changedOrder = changedOrders.find(order => this.isCurrentSalesOrderRecord(order));
|
|
499
|
+
if (!changedOrder) return;
|
|
554
500
|
if (this.serverOrderChangeHydrateInFlight) {
|
|
555
501
|
this.queueLatestServerOrderChange(changedOrder);
|
|
556
502
|
return;
|
|
557
503
|
}
|
|
558
|
-
if (!this.store.order)
|
|
559
|
-
return;
|
|
504
|
+
if (!this.store.order) return;
|
|
560
505
|
this.serverOrderChangeHydrateInFlight = (async () => {
|
|
561
|
-
|
|
562
|
-
const
|
|
563
|
-
const record = mergeSalesDetailRecordWithTempOrder(
|
|
564
|
-
currentTempOrder,
|
|
565
|
-
changedOrder,
|
|
566
|
-
"authoritative-incoming"
|
|
567
|
-
);
|
|
506
|
+
const currentTempOrder = this.store.order.getTempOrder?.();
|
|
507
|
+
const record = mergeSalesDetailRecordWithTempOrder(currentTempOrder, changedOrder, 'authoritative-incoming');
|
|
568
508
|
const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
|
|
569
509
|
recalcOnHydrate: false
|
|
570
510
|
});
|
|
571
511
|
this.currentSalesDetail = sales;
|
|
572
|
-
await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, {
|
|
512
|
+
await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, {
|
|
513
|
+
sales
|
|
514
|
+
});
|
|
573
515
|
})();
|
|
574
516
|
try {
|
|
575
517
|
await this.serverOrderChangeHydrateInFlight;
|
|
@@ -579,72 +521,81 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
579
521
|
}
|
|
580
522
|
}
|
|
581
523
|
registerServerOrderChangeSync() {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
return
|
|
587
|
-
|
|
588
|
-
return this.syncCurrentSalesDetailFromServerOrderChange(payload).catch((error) => {
|
|
589
|
-
this.logError("sync sales detail from server order change failed", {
|
|
524
|
+
this.serverOrderChangeUnsubscribe?.();
|
|
525
|
+
const effects = this.core?.effects;
|
|
526
|
+
if (!effects || typeof effects.on !== 'function') return;
|
|
527
|
+
this.serverOrderChangeUnsubscribe = effects.on(SERVER_ORDER_CHANGED_EVENT, payload => {
|
|
528
|
+
return this.syncCurrentSalesDetailFromServerOrderChange(payload).catch(error => {
|
|
529
|
+
this.logError('sync sales detail from server order change failed', {
|
|
590
530
|
error: error instanceof Error ? error.message : String(error)
|
|
591
531
|
});
|
|
592
532
|
});
|
|
593
533
|
});
|
|
594
534
|
}
|
|
595
|
-
async hydrateLatestLoadedSalesDetail(record, loadSequence,
|
|
535
|
+
async hydrateLatestLoadedSalesDetail(record, loadSequence, options) {
|
|
596
536
|
let hydratedSales = null;
|
|
597
537
|
let skippedBeforeHydrate = false;
|
|
598
538
|
const hydrateTask = async () => {
|
|
539
|
+
// 网络返回顺序可能倒置;只有当前最新显式加载可以进入共享 tempOrder。
|
|
599
540
|
if (loadSequence !== this.salesDetailLoadSequence) {
|
|
600
541
|
skippedBeforeHydrate = true;
|
|
601
542
|
return;
|
|
602
543
|
}
|
|
603
|
-
if (!this.store.order)
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
544
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
545
|
+
let hydrateOptions = {
|
|
546
|
+
recalcOnHydrate: false
|
|
547
|
+
};
|
|
548
|
+
if (options?.hydrateSource === 'sessionStorage') {
|
|
549
|
+
hydrateOptions = {
|
|
550
|
+
recalcOnHydrate: true,
|
|
551
|
+
source: 'sessionStorage'
|
|
552
|
+
};
|
|
553
|
+
} else if (options?.merge) {
|
|
554
|
+
hydrateOptions = {
|
|
555
|
+
recalcOnHydrate: true,
|
|
556
|
+
source: 'mergedSalesDetail'
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
const sales = await this.store.order.hydrateTempOrderFromRecord(record, hydrateOptions);
|
|
609
560
|
hydratedSales = sales;
|
|
610
|
-
|
|
611
|
-
|
|
561
|
+
|
|
562
|
+
// hydrate 期间可能又发起了更新请求;后续任务已串行排队,将负责最终状态。
|
|
563
|
+
if (loadSequence !== this.salesDetailLoadSequence) return;
|
|
612
564
|
this.currentSalesDetail = sales;
|
|
613
|
-
await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, {
|
|
565
|
+
await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, {
|
|
566
|
+
sales
|
|
567
|
+
});
|
|
614
568
|
};
|
|
615
569
|
const queuedTask = this.salesDetailHydrateQueue.then(hydrateTask, hydrateTask);
|
|
616
|
-
this.salesDetailHydrateQueue = queuedTask.then(
|
|
617
|
-
() => void 0,
|
|
618
|
-
() => void 0
|
|
619
|
-
);
|
|
570
|
+
this.salesDetailHydrateQueue = queuedTask.then(() => undefined, () => undefined);
|
|
620
571
|
await queuedTask;
|
|
621
|
-
if (skippedBeforeHydrate)
|
|
622
|
-
return record;
|
|
572
|
+
if (skippedBeforeHydrate) return record;
|
|
623
573
|
return hydratedSales || this.currentSalesDetail || record;
|
|
624
574
|
}
|
|
625
575
|
hydrateOrderPaymentNames(payments) {
|
|
626
|
-
if (!payments.length)
|
|
627
|
-
return [];
|
|
576
|
+
if (!payments.length) return [];
|
|
628
577
|
if (!this.paymentMethodsCache.length) {
|
|
629
|
-
return payments.map(
|
|
578
|
+
return payments.map(payment => ({
|
|
579
|
+
...payment
|
|
580
|
+
}));
|
|
630
581
|
}
|
|
631
|
-
const paymentMethodById =
|
|
632
|
-
const paymentMethodByCode =
|
|
633
|
-
this.paymentMethodsCache.forEach(
|
|
634
|
-
if (
|
|
582
|
+
const paymentMethodById = new Map();
|
|
583
|
+
const paymentMethodByCode = new Map();
|
|
584
|
+
this.paymentMethodsCache.forEach(method => {
|
|
585
|
+
if (method?.id !== undefined && method?.id !== null) {
|
|
635
586
|
paymentMethodById.set(String(method.id), method);
|
|
636
587
|
}
|
|
637
|
-
if (method
|
|
588
|
+
if (method?.code) {
|
|
638
589
|
paymentMethodByCode.set(String(method.code), method);
|
|
639
590
|
}
|
|
640
591
|
});
|
|
641
|
-
return payments.map(
|
|
642
|
-
const nextPayment = {
|
|
643
|
-
|
|
644
|
-
|
|
592
|
+
return payments.map(payment => {
|
|
593
|
+
const nextPayment = {
|
|
594
|
+
...payment
|
|
595
|
+
};
|
|
596
|
+
if (nextPayment.name) return nextPayment;
|
|
645
597
|
const paymentMethod = paymentMethodById.get(String(nextPayment.custom_payment_id)) || paymentMethodByCode.get(String(nextPayment.code));
|
|
646
|
-
if (!
|
|
647
|
-
return nextPayment;
|
|
598
|
+
if (!paymentMethod?.name) return nextPayment;
|
|
648
599
|
return {
|
|
649
600
|
...nextPayment,
|
|
650
601
|
name: paymentMethod.name
|
|
@@ -655,68 +606,58 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
655
606
|
return this.store.payment;
|
|
656
607
|
}
|
|
657
608
|
getCurrentOrderCustomerId() {
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
if (customerId === null || customerId === void 0)
|
|
662
|
-
return void 0;
|
|
609
|
+
const tempOrder = this.store.order?.getTempOrder?.();
|
|
610
|
+
const customerId = tempOrder?.customer_id;
|
|
611
|
+
if (customerId === null || customerId === undefined) return undefined;
|
|
663
612
|
return customerId;
|
|
664
613
|
}
|
|
665
614
|
normalizePriceContextCustomerId(customerId) {
|
|
666
|
-
if (customerId ===
|
|
667
|
-
return null;
|
|
615
|
+
if (customerId === undefined || customerId === null || customerId === '') return null;
|
|
668
616
|
return String(customerId);
|
|
669
617
|
}
|
|
670
618
|
applyQuotationScheduleResolver(quotation) {
|
|
671
619
|
const scheduleModule = this.store.schedule;
|
|
672
|
-
if (!scheduleModule)
|
|
673
|
-
|
|
674
|
-
const
|
|
675
|
-
const scheduleList = typeof scheduleModule.getScheduleList === "function" ? scheduleModule.getScheduleList() : [];
|
|
620
|
+
if (!scheduleModule) return;
|
|
621
|
+
const scheduleById = new Map();
|
|
622
|
+
const scheduleList = typeof scheduleModule.getScheduleList === 'function' ? scheduleModule.getScheduleList() : [];
|
|
676
623
|
if (Array.isArray(scheduleList)) {
|
|
677
|
-
scheduleList.forEach(
|
|
678
|
-
if (
|
|
624
|
+
scheduleList.forEach(schedule => {
|
|
625
|
+
if (schedule?.id !== undefined && schedule?.id !== null) {
|
|
679
626
|
scheduleById.set(String(schedule.id), schedule);
|
|
680
627
|
}
|
|
681
628
|
});
|
|
682
629
|
}
|
|
683
|
-
quotation.setScheduleResolver(
|
|
684
|
-
var _a, _b;
|
|
630
|
+
quotation.setScheduleResolver(id => {
|
|
685
631
|
const scheduleId = String(id);
|
|
686
|
-
if (scheduleById.has(scheduleId))
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
if (schedules[0])
|
|
690
|
-
scheduleById.set(scheduleId, schedules[0]);
|
|
632
|
+
if (scheduleById.has(scheduleId)) return scheduleById.get(scheduleId);
|
|
633
|
+
const schedules = scheduleModule.getScheduleListByIds?.([id]) || scheduleModule.getScheduleByIds?.([id]) || [];
|
|
634
|
+
if (schedules[0]) scheduleById.set(scheduleId, schedules[0]);
|
|
691
635
|
return schedules[0];
|
|
692
636
|
});
|
|
693
637
|
}
|
|
694
638
|
async loadQuotationForPriceQuery(params) {
|
|
695
|
-
|
|
696
|
-
if (!params.quotation)
|
|
697
|
-
return;
|
|
639
|
+
if (!params.quotation) return;
|
|
698
640
|
this.applyQuotationScheduleResolver(params.quotation);
|
|
699
641
|
await params.quotation.loadQuotations({
|
|
700
|
-
channel: params.channel ||
|
|
642
|
+
channel: params.channel || this.otherParams?.channel,
|
|
701
643
|
customer_id: params.customer_id
|
|
702
644
|
});
|
|
703
645
|
}
|
|
704
646
|
getPriceQueryProductId(product) {
|
|
705
|
-
const productId = Number(
|
|
706
|
-
if (!Number.isFinite(productId))
|
|
707
|
-
return null;
|
|
647
|
+
const productId = Number(product?.product_id ?? product?.id);
|
|
648
|
+
if (!Number.isFinite(productId)) return null;
|
|
708
649
|
return productId;
|
|
709
650
|
}
|
|
651
|
+
|
|
710
652
|
/**
|
|
711
653
|
* Change Time / customer reprice 必须沿用商品列表的渠道口径。
|
|
712
654
|
* SalesSdk Provider 通常将渠道存为 platform,因此不能只读取 otherParams.channel。
|
|
713
655
|
*/
|
|
714
656
|
getPriceQueryChannel(channel) {
|
|
715
|
-
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
return void 0;
|
|
657
|
+
const strategyContext = this.otherParams?.strategy_context && typeof this.otherParams.strategy_context === 'object' ? this.otherParams.strategy_context : {};
|
|
658
|
+
const value = channel ?? strategyContext.channel ?? this.otherParams?.channel ?? this.otherParams?.platform;
|
|
659
|
+
if (value === undefined || value === null || String(value).trim() === '') {
|
|
660
|
+
return undefined;
|
|
720
661
|
}
|
|
721
662
|
return String(value).trim();
|
|
722
663
|
}
|
|
@@ -725,14 +666,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
725
666
|
* application_code 仅作为接口兼容字段,不能替代 channel / business_code。
|
|
726
667
|
*/
|
|
727
668
|
getPriceQueryStrategyContext(channel) {
|
|
728
|
-
|
|
729
|
-
const
|
|
730
|
-
|
|
669
|
+
const inherited = this.otherParams?.strategy_context && typeof this.otherParams.strategy_context === 'object' ? this.otherParams.strategy_context : {};
|
|
670
|
+
const strategyContext = {
|
|
671
|
+
...inherited
|
|
672
|
+
};
|
|
731
673
|
const resolvedChannel = this.getPriceQueryChannel(channel);
|
|
732
|
-
const businessCode = strategyContext.business_code ??
|
|
733
|
-
if (resolvedChannel)
|
|
734
|
-
|
|
735
|
-
if (businessCode !== void 0 && businessCode !== null && String(businessCode).trim() !== "") {
|
|
674
|
+
const businessCode = strategyContext.business_code ?? this.otherParams?.businessCode ?? this.otherParams?.business_code;
|
|
675
|
+
if (resolvedChannel) strategyContext.channel = resolvedChannel;
|
|
676
|
+
if (businessCode !== undefined && businessCode !== null && String(businessCode).trim() !== '') {
|
|
736
677
|
strategyContext.business_code = String(businessCode).trim();
|
|
737
678
|
}
|
|
738
679
|
const availableWalletIds = this.getAvailableWalletIds();
|
|
@@ -741,11 +682,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
741
682
|
}
|
|
742
683
|
return strategyContext;
|
|
743
684
|
}
|
|
685
|
+
|
|
744
686
|
/**
|
|
745
687
|
* 子类可在商品重报价前准备客户维度的策略上下文,例如等待 Wallet/优惠资产加载。
|
|
746
688
|
*/
|
|
747
|
-
async prepareProductPriceQueryContext(_customerId) {
|
|
748
|
-
|
|
689
|
+
async prepareProductPriceQueryContext(_customerId) {}
|
|
690
|
+
|
|
749
691
|
/**
|
|
750
692
|
* 默认保留 BaseSales 的 legacy quotation 行为;已由 /product/query 统一完成
|
|
751
693
|
* 智能定价与报价合并的业务可在子类中覆盖,避免二次覆盖权威价格。
|
|
@@ -755,69 +697,64 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
755
697
|
}
|
|
756
698
|
getPriceQuerySchedule(params) {
|
|
757
699
|
const booking = params.booking || {};
|
|
758
|
-
if (typeof booking.start_date ===
|
|
700
|
+
if (typeof booking.start_date === 'string' && booking.start_date.trim()) {
|
|
759
701
|
const scheduleDate = booking.start_date.trim();
|
|
760
|
-
const startTime = typeof booking.start_time ===
|
|
761
|
-
const datetime = (0,
|
|
702
|
+
const startTime = typeof booking.start_time === 'string' && booking.start_time.trim() ? booking.start_time.trim() : '00:00:00';
|
|
703
|
+
const datetime = (0, _dayjs.default)(`${scheduleDate} ${startTime}`);
|
|
762
704
|
return {
|
|
763
705
|
schedule_date: scheduleDate,
|
|
764
|
-
schedule_datetime: datetime.isValid() ? datetime.format(
|
|
706
|
+
schedule_datetime: datetime.isValid() ? datetime.format('YYYY-MM-DD HH:mm:ss') : `${scheduleDate} ${startTime}`
|
|
765
707
|
};
|
|
766
708
|
}
|
|
767
|
-
if (typeof params.datetime ===
|
|
768
|
-
const datetime = (0,
|
|
709
|
+
if (typeof params.datetime === 'string' && params.datetime.trim()) {
|
|
710
|
+
const datetime = (0, _dayjs.default)(params.datetime.trim());
|
|
769
711
|
if (datetime.isValid()) {
|
|
770
712
|
return {
|
|
771
|
-
schedule_date: datetime.format(
|
|
772
|
-
schedule_datetime: datetime.format(
|
|
713
|
+
schedule_date: datetime.format('YYYY-MM-DD'),
|
|
714
|
+
schedule_datetime: datetime.format('YYYY-MM-DD HH:mm:ss')
|
|
773
715
|
};
|
|
774
716
|
}
|
|
775
717
|
}
|
|
776
|
-
const now = (0,
|
|
718
|
+
const now = (0, _dayjs.default)();
|
|
777
719
|
return {
|
|
778
|
-
schedule_date: now.format(
|
|
779
|
-
schedule_datetime: now.format(
|
|
720
|
+
schedule_date: now.format('YYYY-MM-DD'),
|
|
721
|
+
schedule_datetime: now.format('YYYY-MM-DD HH:mm:ss')
|
|
780
722
|
};
|
|
781
723
|
}
|
|
782
724
|
async loadProductsForPriceQuery(params) {
|
|
783
|
-
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
));
|
|
787
|
-
const productsById = /* @__PURE__ */ new Map();
|
|
788
|
-
if (!ids.length || !this.request)
|
|
789
|
-
return productsById;
|
|
725
|
+
const ids = Array.from(new Set(params.ids.filter(id => Number.isFinite(id))));
|
|
726
|
+
const productsById = new Map();
|
|
727
|
+
if (!ids.length || !this.request) return productsById;
|
|
790
728
|
const channel = this.getPriceQueryChannel(params.channel);
|
|
791
729
|
const strategyContext = this.getPriceQueryStrategyContext(channel);
|
|
792
730
|
try {
|
|
793
|
-
const response = await this.request.post(
|
|
731
|
+
const response = await this.request.post('/product/query', {
|
|
794
732
|
ids,
|
|
795
733
|
open_quotation: 1,
|
|
796
734
|
open_bundle: 1,
|
|
797
|
-
status:
|
|
735
|
+
status: 'published',
|
|
798
736
|
num: 1,
|
|
799
737
|
skip: 1,
|
|
800
738
|
customer_id: params.customerId,
|
|
801
739
|
schedule_date: params.schedule.schedule_date,
|
|
802
740
|
schedule_datetime: params.schedule.schedule_datetime,
|
|
803
741
|
application_code: channel,
|
|
804
|
-
...Object.keys(strategyContext).length ? {
|
|
742
|
+
...(Object.keys(strategyContext).length ? {
|
|
743
|
+
strategy_context: strategyContext
|
|
744
|
+
} : {})
|
|
805
745
|
}, {
|
|
806
746
|
osServer: true,
|
|
807
|
-
customToast: () => {
|
|
808
|
-
}
|
|
747
|
+
customToast: () => {}
|
|
809
748
|
});
|
|
810
|
-
const list =
|
|
811
|
-
if (!Array.isArray(list))
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
if (Number.isFinite(productId))
|
|
816
|
-
productsById.set(productId, item);
|
|
749
|
+
const list = response?.data?.list || response?.list || [];
|
|
750
|
+
if (!Array.isArray(list)) return productsById;
|
|
751
|
+
list.forEach(item => {
|
|
752
|
+
const productId = Number(item?.id ?? item?.product_id);
|
|
753
|
+
if (Number.isFinite(productId)) productsById.set(productId, item);
|
|
817
754
|
});
|
|
818
755
|
return productsById;
|
|
819
756
|
} catch (error) {
|
|
820
|
-
this.logWarning(
|
|
757
|
+
this.logWarning('loadProductsForPriceQuery: 商品批量重查失败,使用入参 fallback', {
|
|
821
758
|
ids,
|
|
822
759
|
error: error instanceof Error ? error.message : String(error)
|
|
823
760
|
});
|
|
@@ -827,8 +764,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
827
764
|
async loadProductForPriceQuery(params, customerId) {
|
|
828
765
|
const product = params.product || {};
|
|
829
766
|
const productId = this.getPriceQueryProductId(product);
|
|
830
|
-
if (productId === null || !this.request)
|
|
831
|
-
return null;
|
|
767
|
+
if (productId === null || !this.request) return null;
|
|
832
768
|
const schedule = this.getPriceQuerySchedule(params);
|
|
833
769
|
const productsById = await this.loadProductsForPriceQuery({
|
|
834
770
|
ids: [productId],
|
|
@@ -839,34 +775,30 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
839
775
|
return productsById.get(productId) || null;
|
|
840
776
|
}
|
|
841
777
|
getAuthoritativeBundleItems(product) {
|
|
842
|
-
if (Array.isArray(product
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
return items.map((item) => ({
|
|
778
|
+
if (Array.isArray(product?.product_bundle)) return product.product_bundle;
|
|
779
|
+
const groups = Array.isArray(product?.bundle_group) ? product.bundle_group : Array.isArray(product?.bundleGroup) ? product.bundleGroup : [];
|
|
780
|
+
return groups.flatMap(group => {
|
|
781
|
+
const items = Array.isArray(group?.bundle_item) ? group.bundle_item : Array.isArray(group?.bundleItem) ? group.bundleItem : [];
|
|
782
|
+
return items.map(item => ({
|
|
848
783
|
...item,
|
|
849
|
-
group_id:
|
|
850
|
-
bundle_group_id:
|
|
784
|
+
group_id: item?.group_id ?? group?.id,
|
|
785
|
+
bundle_group_id: item?.bundle_group_id ?? item?.group_id ?? group?.id
|
|
851
786
|
}));
|
|
852
787
|
});
|
|
853
788
|
}
|
|
854
789
|
findAuthoritativeBundleItem(bundle, candidates) {
|
|
855
790
|
const bundleId = bundle.bundle_id ?? bundle.id;
|
|
856
791
|
if (bundleId != null) {
|
|
857
|
-
const matchedById = candidates.find(
|
|
858
|
-
if (matchedById)
|
|
859
|
-
return matchedById;
|
|
792
|
+
const matchedById = candidates.find(item => String(item?.bundle_id ?? item?.id) === String(bundleId));
|
|
793
|
+
if (matchedById) return matchedById;
|
|
860
794
|
}
|
|
861
795
|
const productId = bundle.bundle_product_id ?? bundle._bundle_product_id;
|
|
862
796
|
const groupId = bundle.bundle_group_id ?? bundle.group_id;
|
|
863
|
-
return candidates.find(
|
|
864
|
-
const itemProductId =
|
|
865
|
-
const itemGroupId =
|
|
866
|
-
if (productId == null || String(itemProductId) !== String(productId))
|
|
867
|
-
|
|
868
|
-
if (groupId == null)
|
|
869
|
-
return true;
|
|
797
|
+
return candidates.find(item => {
|
|
798
|
+
const itemProductId = item?.bundle_product_id ?? item?._bundle_product_id;
|
|
799
|
+
const itemGroupId = item?.bundle_group_id ?? item?.group_id;
|
|
800
|
+
if (productId == null || String(itemProductId) !== String(productId)) return false;
|
|
801
|
+
if (groupId == null) return true;
|
|
870
802
|
return String(itemGroupId) === String(groupId);
|
|
871
803
|
}) || null;
|
|
872
804
|
}
|
|
@@ -874,21 +806,19 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
874
806
|
return bundle.price ?? bundle.bundle_selling_price ?? bundle.custom_price ?? bundle.product_price ?? bundle.base_price;
|
|
875
807
|
}
|
|
876
808
|
mergeProductForPriceQuery(product, authoritativeProduct) {
|
|
877
|
-
if (!authoritativeProduct)
|
|
878
|
-
return product;
|
|
809
|
+
if (!authoritativeProduct) return product;
|
|
879
810
|
const selectedBundles = Array.isArray(product.product_bundle) ? product.product_bundle : [];
|
|
880
811
|
const authoritativeBundles = this.getAuthoritativeBundleItems(authoritativeProduct);
|
|
881
|
-
const productBundle = selectedBundles.map(
|
|
812
|
+
const productBundle = selectedBundles.map(bundle => {
|
|
882
813
|
const authoritativeBundle = this.findAuthoritativeBundleItem(bundle, authoritativeBundles);
|
|
883
|
-
const unitPrice = authoritativeBundle ? this.getAuthoritativeBundleUnitPrice(authoritativeBundle) :
|
|
884
|
-
if (unitPrice ===
|
|
885
|
-
return bundle;
|
|
814
|
+
const unitPrice = authoritativeBundle ? this.getAuthoritativeBundleUnitPrice(authoritativeBundle) : undefined;
|
|
815
|
+
if (unitPrice === undefined || unitPrice === null || unitPrice === '') return bundle;
|
|
886
816
|
return {
|
|
887
817
|
...bundle,
|
|
888
818
|
price: unitPrice,
|
|
889
819
|
bundle_selling_price: unitPrice,
|
|
890
|
-
base_price:
|
|
891
|
-
product_price:
|
|
820
|
+
base_price: authoritativeBundle?.base_price ?? bundle.base_price,
|
|
821
|
+
product_price: authoritativeBundle?.product_price ?? bundle.product_price
|
|
892
822
|
};
|
|
893
823
|
});
|
|
894
824
|
return {
|
|
@@ -900,9 +830,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
900
830
|
num: product.num ?? product.quantity ?? authoritativeProduct.num,
|
|
901
831
|
quantity: product.quantity ?? product.num ?? authoritativeProduct.quantity,
|
|
902
832
|
product_sku: (() => {
|
|
903
|
-
const authoritativeSku = (0,
|
|
904
|
-
const productSku = (0,
|
|
905
|
-
const hasProductSku = product.product_sku && typeof product.product_sku ===
|
|
833
|
+
const authoritativeSku = (0, _utils.ensureProductSku)(authoritativeProduct);
|
|
834
|
+
const productSku = (0, _utils.ensureProductSku)(product);
|
|
835
|
+
const hasProductSku = product.product_sku && typeof product.product_sku === 'object';
|
|
906
836
|
return {
|
|
907
837
|
...authoritativeSku,
|
|
908
838
|
...productSku,
|
|
@@ -914,30 +844,30 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
914
844
|
};
|
|
915
845
|
}
|
|
916
846
|
getSubmitOrderSalesChannel() {
|
|
917
|
-
|
|
918
|
-
return (_a = this.otherParams) == null ? void 0 : _a.channel;
|
|
847
|
+
return this.otherParams?.channel;
|
|
919
848
|
}
|
|
849
|
+
|
|
920
850
|
/**
|
|
921
851
|
* 工厂入口:根据子模块名实例化对应模块。
|
|
922
852
|
* 默认使用 BookingByStep 公共 `createModule`。子类若需引入额外类型(如 customer),
|
|
923
853
|
* 可覆盖此方法并把未识别的 name 委托给 `super.createSubModule(name)`。
|
|
924
854
|
*/
|
|
925
855
|
createSubModule(moduleName) {
|
|
926
|
-
if (moduleName ===
|
|
927
|
-
return new
|
|
856
|
+
if (moduleName === 'quotation') {
|
|
857
|
+
return new _Quotation.QuotationModule(`${this.name}_quotation`);
|
|
928
858
|
}
|
|
929
|
-
return (0,
|
|
859
|
+
return (0, _types2.createModule)(moduleName, this.name);
|
|
930
860
|
}
|
|
931
861
|
getSubModuleHooks(moduleName) {
|
|
932
|
-
var _a, _b;
|
|
933
862
|
const optionHooks = this.initializeOptions.hooks || {};
|
|
934
863
|
const otherHooks = this.otherParams.hooks || {};
|
|
935
|
-
if (moduleName ===
|
|
864
|
+
if (moduleName === 'order') {
|
|
936
865
|
const directOrderHooks = optionHooks;
|
|
937
|
-
return optionHooks.order ||
|
|
866
|
+
return optionHooks.order || this.otherParams.order?.hooks || otherHooks.order || (directOrderHooks.onBeforeMergeProductToOrder ? directOrderHooks : undefined);
|
|
938
867
|
}
|
|
939
|
-
return optionHooks[moduleName] ||
|
|
868
|
+
return optionHooks[moduleName] || this.otherParams[moduleName]?.hooks || otherHooks[moduleName];
|
|
940
869
|
}
|
|
870
|
+
|
|
941
871
|
/**
|
|
942
872
|
* 构造传给 BaseSales 子模块的完整运行态参数,保证初始化和后续同步语义一致。
|
|
943
873
|
*
|
|
@@ -960,30 +890,32 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
960
890
|
cacheId: this.cacheId
|
|
961
891
|
};
|
|
962
892
|
}
|
|
893
|
+
|
|
963
894
|
/**
|
|
964
895
|
* 将父级 otherParams 的变更显式同步给已注册的子模块。
|
|
965
896
|
*
|
|
966
897
|
* @example
|
|
967
898
|
* await this.syncOtherParamsToSubModules({ channel: 'pos' });
|
|
968
899
|
*/
|
|
969
|
-
async syncOtherParamsToSubModules(changedParams, {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
})
|
|
985
|
-
);
|
|
900
|
+
async syncOtherParamsToSubModules(changedParams, {
|
|
901
|
+
cover = false
|
|
902
|
+
} = {}) {
|
|
903
|
+
await Promise.all(Object.entries(this.store).map(async ([moduleName, subModule]) => {
|
|
904
|
+
if (this.reusedSharedSubModuleNames.has(moduleName)) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
const targetModule = subModule;
|
|
908
|
+
if (!targetModule || typeof targetModule.updateOtherParams !== 'function') {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
const nextSubModuleOtherParams = this.buildSubModuleOtherParams(moduleName);
|
|
912
|
+
await targetModule.updateOtherParams(nextSubModuleOtherParams, {
|
|
913
|
+
changedParams,
|
|
914
|
+
cover
|
|
915
|
+
});
|
|
916
|
+
}));
|
|
986
917
|
}
|
|
918
|
+
|
|
987
919
|
/**
|
|
988
920
|
* 读取 sessionStorage[this.name][cacheId],作为子模块 initialState 的来源。
|
|
989
921
|
* sessionStorage 损坏时静默忽略,按空状态注册。
|
|
@@ -995,8 +927,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
995
927
|
}
|
|
996
928
|
try {
|
|
997
929
|
const sessionData = this.window.sessionStorage.getItem(this.name);
|
|
998
|
-
if (!sessionData)
|
|
999
|
-
return {};
|
|
930
|
+
if (!sessionData) return {};
|
|
1000
931
|
const data = JSON.parse(sessionData);
|
|
1001
932
|
return data && data[cacheId] || {};
|
|
1002
933
|
} catch {
|
|
@@ -1004,65 +935,60 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1004
935
|
}
|
|
1005
936
|
}
|
|
1006
937
|
getAppData(key) {
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
if (typeof getData === "function")
|
|
1010
|
-
return getData(key);
|
|
938
|
+
const getData = this.appPlugin.getData?.();
|
|
939
|
+
if (typeof getData === 'function') return getData(key);
|
|
1011
940
|
const app = this.appPlugin.getApp();
|
|
1012
|
-
const coreData =
|
|
1013
|
-
return coreData
|
|
941
|
+
const coreData = app?.models?.getStore?.().getDataByModel?.('core', 'core');
|
|
942
|
+
return coreData?.[key];
|
|
1014
943
|
}
|
|
944
|
+
|
|
1015
945
|
/**
|
|
1016
946
|
* 复用业务解决方案初始化时已解析的支付设备短号。
|
|
1017
947
|
* 空值会清除缓存,使后续支付恢复实时读取设备信息的兼容路径。
|
|
1018
948
|
*/
|
|
1019
949
|
setPaymentNumberDevicePrefix(prefix) {
|
|
1020
|
-
const normalized = String(prefix ??
|
|
950
|
+
const normalized = String(prefix ?? '').trim();
|
|
1021
951
|
this.paymentNumberDevicePrefix = normalized || null;
|
|
1022
952
|
}
|
|
1023
953
|
getPaymentNumberDevicePrefixSync() {
|
|
1024
|
-
if (!this.appPlugin)
|
|
1025
|
-
|
|
1026
|
-
return (0, import_payment_number.resolvePaymentNumberDevicePrefixFromDeviceId)((key) => this.getAppData(key));
|
|
954
|
+
if (!this.appPlugin) return 'LOCAL';
|
|
955
|
+
return (0, _paymentNumber.resolvePaymentNumberDevicePrefixFromDeviceId)(key => this.getAppData(key));
|
|
1027
956
|
}
|
|
1028
957
|
getPaymentNumberDevicePrefixAsync() {
|
|
1029
|
-
if (!this.appPlugin)
|
|
1030
|
-
return Promise.resolve("LOCAL");
|
|
958
|
+
if (!this.appPlugin) return Promise.resolve('LOCAL');
|
|
1031
959
|
if (this.paymentNumberDevicePrefix) {
|
|
1032
960
|
return Promise.resolve(this.paymentNumberDevicePrefix);
|
|
1033
961
|
}
|
|
1034
|
-
return (0,
|
|
962
|
+
return (0, _paymentNumber.resolvePaymentNumberDevicePrefix)(key => this.getAppData(key));
|
|
1035
963
|
}
|
|
1036
964
|
isMultiCurrencySettlementEnabled() {
|
|
1037
|
-
|
|
1038
|
-
return ((_a = this.otherParams) == null ? void 0 : _a.enableMultiCurrencySettlement) === true;
|
|
965
|
+
return this.otherParams?.enableMultiCurrencySettlement === true;
|
|
1039
966
|
}
|
|
1040
967
|
isActiveVirtualSettlementOrder(tempOrder) {
|
|
1041
|
-
return this.isMultiCurrencySettlementEnabled() && (0,
|
|
968
|
+
return this.isMultiCurrencySettlementEnabled() && (0, _virtualSettlement.isVirtualSettlementOrder)(tempOrder);
|
|
1042
969
|
}
|
|
1043
970
|
isHistoricalVirtualSettlementOrder(tempOrder) {
|
|
1044
|
-
|
|
1045
|
-
return ((_b = (_a = tempOrder == null ? void 0 : tempOrder.metadata) == null ? void 0 : _a.currency_settlement_config) == null ? void 0 : _b.settlement_type) === "virtual_currency";
|
|
971
|
+
return tempOrder?.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
|
|
1046
972
|
}
|
|
1047
973
|
syncAppDataToTempOrder(tempOrder) {
|
|
1048
|
-
|
|
1049
|
-
const
|
|
1050
|
-
const
|
|
1051
|
-
const
|
|
1052
|
-
|
|
974
|
+
const isPriceIncludeTax = this.getAppData('is_price_include_tax');
|
|
975
|
+
const taxCountryCode = this.getAppData('tax_country_code');
|
|
976
|
+
const currencyCode = this.getAppData('shop_currency_code');
|
|
977
|
+
const currencySymbol = this.getAppData('shop_symbol');
|
|
978
|
+
// 历史虚拟币订单不依赖交易开关;普通 POS 不从商品行残留快照推断订单币种。
|
|
1053
979
|
const isHistoricalVirtualSettlement = this.isHistoricalVirtualSettlementOrder(tempOrder);
|
|
1054
980
|
const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder) || isHistoricalVirtualSettlement;
|
|
1055
981
|
const shouldManageLegalCurrencySnapshot = this.isMultiCurrencySettlementEnabled() || isHistoricalVirtualSettlement;
|
|
1056
982
|
let isChanged = false;
|
|
1057
|
-
if (isPriceIncludeTax !==
|
|
983
|
+
if (isPriceIncludeTax !== undefined) {
|
|
1058
984
|
const nextIsPriceIncludeTax = Number(isPriceIncludeTax);
|
|
1059
985
|
if ((nextIsPriceIncludeTax === 0 || nextIsPriceIncludeTax === 1) && tempOrder.is_price_include_tax !== nextIsPriceIncludeTax) {
|
|
1060
986
|
tempOrder.is_price_include_tax = nextIsPriceIncludeTax;
|
|
1061
987
|
isChanged = true;
|
|
1062
988
|
}
|
|
1063
989
|
}
|
|
1064
|
-
if (taxCountryCode !==
|
|
1065
|
-
const nextTaxCountryCode = String(taxCountryCode ||
|
|
990
|
+
if (taxCountryCode !== undefined) {
|
|
991
|
+
const nextTaxCountryCode = String(taxCountryCode || '');
|
|
1066
992
|
if (tempOrder.tax_country_code !== nextTaxCountryCode) {
|
|
1067
993
|
tempOrder.tax_country_code = nextTaxCountryCode;
|
|
1068
994
|
isChanged = true;
|
|
@@ -1071,30 +997,24 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1071
997
|
tempOrder.metadata = tempOrder.metadata || {};
|
|
1072
998
|
if (shouldManageLegalCurrencySnapshot) {
|
|
1073
999
|
const legalCurrencySnapshot = {
|
|
1074
|
-
currency_code: String(
|
|
1075
|
-
|
|
1076
|
-
)
|
|
1077
|
-
currency_symbol: String(
|
|
1078
|
-
currencySymbol ?? ((_b = tempOrder.metadata.legal_currency_snapshot) == null ? void 0 : _b.currency_symbol) ?? tempOrder.currency_symbol ?? ""
|
|
1079
|
-
),
|
|
1080
|
-
currency_format: String(
|
|
1081
|
-
((_c = tempOrder.metadata.legal_currency_snapshot) == null ? void 0 : _c.currency_format) || (isVirtualSettlement ? "symbol_first" : tempOrder.currency_format) || "symbol_first"
|
|
1082
|
-
)
|
|
1000
|
+
currency_code: String(currencyCode ?? tempOrder.metadata.legal_currency_snapshot?.currency_code ?? tempOrder.currency_code ?? ''),
|
|
1001
|
+
currency_symbol: String(currencySymbol ?? tempOrder.metadata.legal_currency_snapshot?.currency_symbol ?? tempOrder.currency_symbol ?? ''),
|
|
1002
|
+
currency_format: String(tempOrder.metadata.legal_currency_snapshot?.currency_format || (isVirtualSettlement ? 'symbol_first' : tempOrder.currency_format) || 'symbol_first')
|
|
1083
1003
|
};
|
|
1084
1004
|
if (JSON.stringify(tempOrder.metadata.legal_currency_snapshot || {}) !== JSON.stringify(legalCurrencySnapshot)) {
|
|
1085
1005
|
tempOrder.metadata.legal_currency_snapshot = legalCurrencySnapshot;
|
|
1086
1006
|
isChanged = true;
|
|
1087
1007
|
}
|
|
1088
1008
|
}
|
|
1089
|
-
if (!isVirtualSettlement && currencyCode !==
|
|
1090
|
-
const nextCurrencyCode = String(currencyCode ||
|
|
1009
|
+
if (!isVirtualSettlement && currencyCode !== undefined) {
|
|
1010
|
+
const nextCurrencyCode = String(currencyCode || '');
|
|
1091
1011
|
if (tempOrder.currency_code !== nextCurrencyCode) {
|
|
1092
1012
|
tempOrder.currency_code = nextCurrencyCode;
|
|
1093
1013
|
isChanged = true;
|
|
1094
1014
|
}
|
|
1095
1015
|
}
|
|
1096
|
-
if (!isVirtualSettlement && currencySymbol !==
|
|
1097
|
-
const nextCurrencySymbol = String(currencySymbol ||
|
|
1016
|
+
if (!isVirtualSettlement && currencySymbol !== undefined) {
|
|
1017
|
+
const nextCurrencySymbol = String(currencySymbol || '');
|
|
1098
1018
|
if (tempOrder.currency_symbol !== nextCurrencySymbol) {
|
|
1099
1019
|
tempOrder.currency_symbol = nextCurrencySymbol;
|
|
1100
1020
|
isChanged = true;
|
|
@@ -1103,23 +1023,26 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1103
1023
|
return isChanged;
|
|
1104
1024
|
}
|
|
1105
1025
|
async initialize(core, options = {}) {
|
|
1106
|
-
var _a, _b, _c, _d;
|
|
1107
1026
|
this.core = core;
|
|
1108
1027
|
this.initializeOptions = options || {};
|
|
1109
1028
|
this.paymentNumberDevicePrefix = null;
|
|
1029
|
+
// this.store = { ...this.store, ...(options.store as Partial<BaseSalesState>) };
|
|
1110
1030
|
this.otherParams = options.otherParams || {};
|
|
1111
|
-
this.cacheId =
|
|
1031
|
+
this.cacheId = this.otherParams?.cacheId;
|
|
1112
1032
|
this.reusedSharedSubModuleNames.clear();
|
|
1113
|
-
this.window = core.getPlugin(
|
|
1114
|
-
this.request = core.getPlugin(
|
|
1115
|
-
|
|
1033
|
+
this.window = core.getPlugin('window');
|
|
1034
|
+
this.request = core.getPlugin('request');
|
|
1035
|
+
|
|
1036
|
+
// 获取 logger 实例
|
|
1037
|
+
this.appPlugin = core.getPlugin('app');
|
|
1116
1038
|
if (!this.appPlugin) {
|
|
1039
|
+
// throw new Error('Checkout 解决方案需要 app 插件支持');
|
|
1117
1040
|
}
|
|
1118
|
-
const app =
|
|
1119
|
-
this.logger = app
|
|
1041
|
+
const app = this.appPlugin?.getApp?.();
|
|
1042
|
+
this.logger = app?.logger;
|
|
1120
1043
|
const targetCacheData = this.readSessionCacheData();
|
|
1121
1044
|
const moduleNames = this.getRegisteredModuleNames();
|
|
1122
|
-
moduleNames.forEach(
|
|
1045
|
+
moduleNames.forEach(step => {
|
|
1123
1046
|
const reusedModule = this.getReusableSharedSubModule(step);
|
|
1124
1047
|
if (reusedModule) {
|
|
1125
1048
|
this.store[step] = reusedModule;
|
|
@@ -1133,32 +1056,30 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1133
1056
|
const hooks = this.getSubModuleHooks(step);
|
|
1134
1057
|
this.store[step] = targetModule;
|
|
1135
1058
|
this.core.registerModule(targetModule, {
|
|
1136
|
-
initialState: this.shouldUseSessionStorageForSubModule(step) ?
|
|
1137
|
-
...hooks ? {
|
|
1059
|
+
initialState: this.shouldUseSessionStorageForSubModule(step) ? targetCacheData?.[targetModule.name] || {} : {},
|
|
1060
|
+
...(hooks ? {
|
|
1061
|
+
hooks
|
|
1062
|
+
} : {}),
|
|
1138
1063
|
otherParams: this.buildSubModuleOtherParams(step)
|
|
1139
1064
|
});
|
|
1140
1065
|
});
|
|
1141
1066
|
if (this.store.schedule && !this.isScheduleListLoaded(this.store.schedule)) {
|
|
1142
1067
|
await this.store.schedule.loadAllSchedule();
|
|
1143
1068
|
}
|
|
1144
|
-
if (this.store.order && typeof
|
|
1145
|
-
this.store.order.setEnableTempOrderPersist(
|
|
1146
|
-
this.otherParams.enableTempOrderPersist
|
|
1147
|
-
);
|
|
1069
|
+
if (this.store.order && typeof this.otherParams?.enableTempOrderPersist === 'boolean') {
|
|
1070
|
+
this.store.order.setEnableTempOrderPersist(this.otherParams.enableTempOrderPersist);
|
|
1148
1071
|
}
|
|
1149
1072
|
await this.getPaymentMethodsAsync();
|
|
1150
1073
|
this.registerServerOrderChangeSync();
|
|
1151
1074
|
this.core.effects.emit(`${this.name}:onInited`, {});
|
|
1152
1075
|
}
|
|
1153
1076
|
async destroy() {
|
|
1154
|
-
|
|
1155
|
-
(_a = this.serverOrderChangeUnsubscribe) == null ? void 0 : _a.call(this);
|
|
1077
|
+
this.serverOrderChangeUnsubscribe?.();
|
|
1156
1078
|
this.serverOrderChangeUnsubscribe = null;
|
|
1157
|
-
Object.keys(this.store).forEach(
|
|
1158
|
-
if (this.reusedSharedSubModuleNames.has(key))
|
|
1159
|
-
return;
|
|
1079
|
+
Object.keys(this.store).forEach(key => {
|
|
1080
|
+
if (this.reusedSharedSubModuleNames.has(key)) return;
|
|
1160
1081
|
const sub = this.store[key];
|
|
1161
|
-
if (sub && typeof sub.destroy ===
|
|
1082
|
+
if (sub && typeof sub.destroy === 'function') {
|
|
1162
1083
|
try {
|
|
1163
1084
|
sub.destroy();
|
|
1164
1085
|
} catch (error) {
|
|
@@ -1174,6 +1095,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1174
1095
|
await this.core.effects.emit(`${this.name}:onDestroy`, {});
|
|
1175
1096
|
super.destroy();
|
|
1176
1097
|
}
|
|
1098
|
+
|
|
1177
1099
|
/**
|
|
1178
1100
|
* 加载销售订单到统一 tempOrder 工作区。
|
|
1179
1101
|
* 统一通过 OrderModule 的 sales detail lookup 加载订单详情。
|
|
@@ -1182,149 +1104,136 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1182
1104
|
* (比如把 `sales.customer` 写入 CustomerModule、emit 业务 hook 等)。
|
|
1183
1105
|
*/
|
|
1184
1106
|
async loadSalesDetail(orderIdOrParams) {
|
|
1185
|
-
if (!this.store.order)
|
|
1186
|
-
throw new Error("order 模块未初始化");
|
|
1107
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1187
1108
|
const loadSequence = ++this.salesDetailLoadSequence;
|
|
1188
1109
|
this.salesDetailLoadInFlightCount += 1;
|
|
1189
1110
|
try {
|
|
1190
|
-
const params = typeof orderIdOrParams ===
|
|
1111
|
+
const params = typeof orderIdOrParams === 'object' ? orderIdOrParams : {
|
|
1112
|
+
orderId: orderIdOrParams
|
|
1113
|
+
};
|
|
1191
1114
|
const externalSaleNumber = params.externalSaleNumber || params.external_sale_number;
|
|
1192
1115
|
const preloadedSalesDetail = params.preloadedSalesDetail;
|
|
1193
|
-
const lookup = params.orderId ?? externalSaleNumber ?? params.orderNumber ??
|
|
1194
|
-
if (!preloadedSalesDetail && (lookup ===
|
|
1195
|
-
throw new Error(
|
|
1116
|
+
const lookup = params.orderId ?? externalSaleNumber ?? params.orderNumber ?? preloadedSalesDetail?.order_id ?? preloadedSalesDetail?.external_sale_number ?? preloadedSalesDetail?.order_number;
|
|
1117
|
+
if (!preloadedSalesDetail && (lookup === undefined || lookup === null || lookup === '')) {
|
|
1118
|
+
throw new Error('加载销售详情需要 orderId、externalSaleNumber 或 orderNumber');
|
|
1196
1119
|
}
|
|
1197
|
-
|
|
1120
|
+
// GlobalSearch 等调用方已拿到完整详情时,直接进入查询成功后的 hydrate 流程,避免按 id 二次请求。
|
|
1121
|
+
const loadedRecord = preloadedSalesDetail ?? (await this.store.order.getSalesOrderByLookup({
|
|
1198
1122
|
lookup,
|
|
1199
1123
|
forceRemote: params.forceRemote
|
|
1200
|
-
});
|
|
1124
|
+
}));
|
|
1201
1125
|
if (!preloadedSalesDetail && (!loadedRecord || loadedRecord.code !== 200)) {
|
|
1202
1126
|
const message = loadedRecord && (loadedRecord.message || loadedRecord.msg) || `加载销售详情失败: ${lookup}`;
|
|
1203
1127
|
throw new Error(message);
|
|
1204
1128
|
}
|
|
1205
1129
|
const loadedSalesDetail = preloadedSalesDetail ?? loadedRecord.data;
|
|
1206
|
-
|
|
1130
|
+
// payment_pending 只存在于本地;远端详情需过滤,但会话快照必须完整恢复。
|
|
1131
|
+
const shouldFilterPendingPayments = params.hydrateSource !== 'sessionStorage';
|
|
1207
1132
|
const remoteRecord = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(loadedSalesDetail) : loadedSalesDetail;
|
|
1133
|
+
const mergeSourceRecord = params.merge ? markLoadedSalesDetailProductsAsSaved(remoteRecord) : remoteRecord;
|
|
1208
1134
|
const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
|
|
1209
|
-
const mergedRecord = params.merge ? mergeSalesDetailRecordWithTempOrder(
|
|
1210
|
-
currentTempOrder,
|
|
1211
|
-
remoteRecord,
|
|
1212
|
-
"preserve-local"
|
|
1213
|
-
) : remoteRecord;
|
|
1135
|
+
const mergedRecord = params.merge ? mergeSalesDetailRecordWithTempOrder(currentTempOrder, mergeSourceRecord, 'preserve-local') : mergeSourceRecord;
|
|
1214
1136
|
const record = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(mergedRecord) : mergedRecord;
|
|
1215
|
-
return await this.hydrateLatestLoadedSalesDetail(
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
);
|
|
1137
|
+
return await this.hydrateLatestLoadedSalesDetail(record, loadSequence, {
|
|
1138
|
+
hydrateSource: params.hydrateSource,
|
|
1139
|
+
merge: params.merge
|
|
1140
|
+
});
|
|
1220
1141
|
} finally {
|
|
1221
|
-
this.salesDetailLoadInFlightCount = Math.max(
|
|
1222
|
-
0,
|
|
1223
|
-
this.salesDetailLoadInFlightCount - 1
|
|
1224
|
-
);
|
|
1142
|
+
this.salesDetailLoadInFlightCount = Math.max(0, this.salesDetailLoadInFlightCount - 1);
|
|
1225
1143
|
if (this.salesDetailLoadInFlightCount === 0) {
|
|
1226
1144
|
try {
|
|
1227
1145
|
await this.drainQueuedServerOrderChanges();
|
|
1228
1146
|
} catch (error) {
|
|
1229
|
-
this.logError(
|
|
1147
|
+
this.logError('drain queued server order changes failed', {
|
|
1230
1148
|
error: error instanceof Error ? error.message : String(error)
|
|
1231
1149
|
});
|
|
1232
1150
|
}
|
|
1233
1151
|
}
|
|
1234
1152
|
}
|
|
1235
1153
|
}
|
|
1154
|
+
|
|
1236
1155
|
/** 获取当前已加载的销售详情(只读快照)。未加载过则返回 null。 */
|
|
1237
1156
|
getSalesOrder() {
|
|
1238
1157
|
return this.currentSalesDetail;
|
|
1239
1158
|
}
|
|
1159
|
+
|
|
1240
1160
|
/** 获取销售详情顶部业务字段(订单号/状态/金额等通用字段集合)。 */
|
|
1241
1161
|
getOrderHeader() {
|
|
1242
|
-
if (!this.currentSalesDetail)
|
|
1243
|
-
return null;
|
|
1162
|
+
if (!this.currentSalesDetail) return null;
|
|
1244
1163
|
return this.currentSalesDetail.header || this.currentSalesDetail;
|
|
1245
1164
|
}
|
|
1165
|
+
|
|
1246
1166
|
/** 获取所有 booking(含 root + children),按服务端原始顺序输出。 */
|
|
1247
1167
|
getBookings() {
|
|
1248
|
-
|
|
1249
|
-
return ((_a = this.currentSalesDetail) == null ? void 0 : _a.bookings) || [];
|
|
1168
|
+
return this.currentSalesDetail?.bookings || [];
|
|
1250
1169
|
}
|
|
1170
|
+
|
|
1251
1171
|
/** 获取根 booking(is_next === 0 / is_root === 1),多个时取第一个。 */
|
|
1252
1172
|
getRootBooking() {
|
|
1253
|
-
if (!this.currentSalesDetail)
|
|
1254
|
-
|
|
1255
|
-
if (this.currentSalesDetail.rootBooking)
|
|
1256
|
-
return this.currentSalesDetail.rootBooking;
|
|
1173
|
+
if (!this.currentSalesDetail) return null;
|
|
1174
|
+
if (this.currentSalesDetail.rootBooking) return this.currentSalesDetail.rootBooking;
|
|
1257
1175
|
const bookings = this.currentSalesDetail.bookings || [];
|
|
1258
|
-
return bookings.find(
|
|
1259
|
-
const parentId = booking
|
|
1260
|
-
return parentId === 0 || parentId === null || parentId ===
|
|
1176
|
+
return bookings.find(booking => {
|
|
1177
|
+
const parentId = booking?.parent_id;
|
|
1178
|
+
return parentId === 0 || parentId === null || parentId === undefined;
|
|
1261
1179
|
}) || null;
|
|
1262
1180
|
}
|
|
1181
|
+
|
|
1263
1182
|
/** 按 product_uid 反查 booking 列表(用于商品行 ↔ booking 映射)。 */
|
|
1264
1183
|
getChildBookingsByProductUid(productUid) {
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
return
|
|
1271
|
-
return (this.currentSalesDetail.bookings || []).filter((booking) => {
|
|
1272
|
-
var _a2;
|
|
1273
|
-
const uid = (booking == null ? void 0 : booking.product_uid) || ((_a2 = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a2.product_uid);
|
|
1274
|
-
return String(uid || "") === String(productUid);
|
|
1184
|
+
if (!this.currentSalesDetail || !productUid) return [];
|
|
1185
|
+
const indexed = this.currentSalesDetail.bookingsByProductUid?.[productUid];
|
|
1186
|
+
if (indexed) return indexed;
|
|
1187
|
+
return (this.currentSalesDetail.bookings || []).filter(booking => {
|
|
1188
|
+
const uid = booking?.product_uid || booking?.metadata?.product_uid;
|
|
1189
|
+
return String(uid || '') === String(productUid);
|
|
1275
1190
|
});
|
|
1276
1191
|
}
|
|
1192
|
+
|
|
1277
1193
|
/** 获取支付列表(已支付/退款等明细)。 */
|
|
1278
1194
|
getPayments() {
|
|
1279
|
-
|
|
1280
|
-
return ((_a = this.currentSalesDetail) == null ? void 0 : _a.payments) || [];
|
|
1195
|
+
return this.currentSalesDetail?.payments || [];
|
|
1281
1196
|
}
|
|
1197
|
+
|
|
1282
1198
|
/** 获取附加费用(运费/服务费/税费等)。 */
|
|
1283
1199
|
getSurcharges() {
|
|
1284
|
-
|
|
1285
|
-
return ((_a = this.currentSalesDetail) == null ? void 0 : _a.surcharges) || [];
|
|
1200
|
+
return this.currentSalesDetail?.surcharges || [];
|
|
1286
1201
|
}
|
|
1287
1202
|
getTempOrder() {
|
|
1288
|
-
|
|
1289
|
-
const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
|
|
1203
|
+
const result = this.store.order?.getTempOrder() || null;
|
|
1290
1204
|
return result;
|
|
1291
1205
|
}
|
|
1292
1206
|
async replaceTempOrder(tempOrder, options) {
|
|
1293
|
-
if (!this.store.order)
|
|
1294
|
-
throw new Error("order 模块未初始化");
|
|
1207
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1295
1208
|
const nextTempOrder = await this.store.order.replaceTempOrder(tempOrder, options);
|
|
1296
|
-
await this.effectsEmit(
|
|
1209
|
+
await this.effectsEmit('onTempOrderReplaced', {
|
|
1210
|
+
tempOrder: nextTempOrder
|
|
1211
|
+
});
|
|
1297
1212
|
return nextTempOrder;
|
|
1298
1213
|
}
|
|
1299
1214
|
getOrderIdentity() {
|
|
1300
|
-
if (!this.store.order)
|
|
1301
|
-
return null;
|
|
1215
|
+
if (!this.store.order) return null;
|
|
1302
1216
|
return this.store.order.getOrderIdentity();
|
|
1303
1217
|
}
|
|
1304
1218
|
getOrderSnapshot() {
|
|
1305
|
-
if (!this.store.order)
|
|
1306
|
-
return null;
|
|
1219
|
+
if (!this.store.order) return null;
|
|
1307
1220
|
return this.store.order.getOrderSnapshot();
|
|
1308
1221
|
}
|
|
1309
1222
|
getOrderSyncState() {
|
|
1310
|
-
if (!this.store.order)
|
|
1311
|
-
return "local";
|
|
1223
|
+
if (!this.store.order) return 'local';
|
|
1312
1224
|
return this.store.order.getOrderSyncState();
|
|
1313
1225
|
}
|
|
1314
1226
|
getOrderAmountSnapshot() {
|
|
1315
|
-
if (!this.store.order)
|
|
1316
|
-
return null;
|
|
1227
|
+
if (!this.store.order) return null;
|
|
1317
1228
|
return this.store.order.getOrderAmountSnapshot();
|
|
1318
1229
|
}
|
|
1319
1230
|
getTempOrderNote() {
|
|
1320
|
-
if (!this.store.order)
|
|
1321
|
-
return "";
|
|
1231
|
+
if (!this.store.order) return '';
|
|
1322
1232
|
return this.store.order.getTempOrderNote();
|
|
1323
1233
|
}
|
|
1324
1234
|
updateTempOrderNote(note, sync = false) {
|
|
1325
1235
|
try {
|
|
1326
|
-
if (!this.store.order)
|
|
1327
|
-
throw new Error("order 模块未初始化");
|
|
1236
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1328
1237
|
const result = this.store.order.updateTempOrderNote(note, sync);
|
|
1329
1238
|
return result;
|
|
1330
1239
|
} catch (error) {
|
|
@@ -1332,47 +1241,42 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1332
1241
|
}
|
|
1333
1242
|
}
|
|
1334
1243
|
updateRemoteOrderNote(orderId, note) {
|
|
1335
|
-
if (!this.store.order)
|
|
1336
|
-
throw new Error("order 模块未初始化");
|
|
1244
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1337
1245
|
this.store.order.syncTempOrderNoteToRemote(orderId, note);
|
|
1338
1246
|
}
|
|
1339
1247
|
updateTempOrderShopDiscount(amount) {
|
|
1340
|
-
if (!this.store.order)
|
|
1341
|
-
throw new Error("order 模块未初始化");
|
|
1248
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1342
1249
|
return this.store.order.updateTempOrderShopDiscount(amount);
|
|
1343
1250
|
}
|
|
1344
1251
|
updateTempOrderDepositAmount(amount) {
|
|
1345
|
-
if (!this.store.order)
|
|
1346
|
-
throw new Error("order 模块未初始化");
|
|
1252
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1347
1253
|
return this.store.order.updateTempOrderDepositAmount(amount);
|
|
1348
1254
|
}
|
|
1349
1255
|
updateTempOrderContactsInfo(contactsInfo) {
|
|
1350
|
-
if (!this.store.order)
|
|
1351
|
-
throw new Error("order 模块未初始化");
|
|
1256
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1352
1257
|
return this.store.order.updateTempOrderContactsInfo(contactsInfo);
|
|
1353
1258
|
}
|
|
1259
|
+
|
|
1354
1260
|
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
1355
1261
|
setEnableTempOrderPersist(enabled) {
|
|
1356
|
-
if (!this.store.order)
|
|
1357
|
-
throw new Error("order 模块未初始化");
|
|
1262
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1358
1263
|
this.store.order.setEnableTempOrderPersist(enabled);
|
|
1359
1264
|
}
|
|
1265
|
+
|
|
1360
1266
|
/** 是否允许 saveDraft 写入 IndexedDB 草稿。 */
|
|
1361
1267
|
isTempOrderPersistEnabled() {
|
|
1362
|
-
if (!this.store.order)
|
|
1363
|
-
return false;
|
|
1268
|
+
if (!this.store.order) return false;
|
|
1364
1269
|
return this.store.order.isTempOrderPersistEnabled();
|
|
1365
1270
|
}
|
|
1366
1271
|
ensureTempOrder() {
|
|
1367
|
-
if (!this.store.order)
|
|
1368
|
-
throw new Error("order 模块未初始化");
|
|
1272
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1369
1273
|
return this.store.order.ensureTempOrder();
|
|
1370
1274
|
}
|
|
1275
|
+
|
|
1371
1276
|
// 主动创建临时订单;若已存在则直接返回已有订单
|
|
1372
1277
|
async addNewOrder() {
|
|
1373
1278
|
try {
|
|
1374
|
-
if (!this.store.order)
|
|
1375
|
-
throw new Error("order 模块未初始化");
|
|
1279
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1376
1280
|
const tempOrder = await this.store.order.addNewOrder();
|
|
1377
1281
|
if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
|
|
1378
1282
|
this.store.order.persistTempOrder();
|
|
@@ -1384,29 +1288,31 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1384
1288
|
}
|
|
1385
1289
|
}
|
|
1386
1290
|
async saveDraft() {
|
|
1387
|
-
if (!this.store.order)
|
|
1388
|
-
throw new Error("order 模块未初始化");
|
|
1291
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1389
1292
|
return this.store.order.saveDraft();
|
|
1390
1293
|
}
|
|
1294
|
+
|
|
1391
1295
|
// 重置 tempOrder 与与上一单强相关的运行态(resource/entryPaxNumber/enabledReservationRuleProducts),
|
|
1392
1296
|
// 适用于从支付页通过 react-router 跳回继续下单时清理残留数据
|
|
1393
1297
|
async restoreOrder() {
|
|
1394
|
-
var _a;
|
|
1395
1298
|
try {
|
|
1396
1299
|
if (!this.store.order) {
|
|
1397
|
-
throw new Error(
|
|
1300
|
+
throw new Error('scanOrder 解决方案需要 order 模块支持');
|
|
1398
1301
|
}
|
|
1302
|
+
// this.store.resource = null;
|
|
1399
1303
|
const tempOrder = this.store.order.restoreOrder();
|
|
1400
1304
|
this.currentSalesDetail = null;
|
|
1401
1305
|
this.discountConfigCacheKey = null;
|
|
1402
1306
|
this.hasManualDiscountSelection = false;
|
|
1403
|
-
const wallet =
|
|
1307
|
+
const wallet = this.store.payment?.wallet;
|
|
1404
1308
|
if (wallet) {
|
|
1405
1309
|
this.walletAssetsRefreshSequence += 1;
|
|
1406
1310
|
wallet.clearAllCache();
|
|
1407
1311
|
await this.publishWalletAssetsState(wallet.getWalletAssetsState());
|
|
1408
1312
|
}
|
|
1409
|
-
await this.effectsEmit(
|
|
1313
|
+
await this.effectsEmit('onTempOrderReplaced', {
|
|
1314
|
+
tempOrder
|
|
1315
|
+
});
|
|
1410
1316
|
if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
|
|
1411
1317
|
this.store.order.persistTempOrder();
|
|
1412
1318
|
await this.store.order.saveDraft();
|
|
@@ -1416,14 +1322,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1416
1322
|
throw error;
|
|
1417
1323
|
}
|
|
1418
1324
|
}
|
|
1325
|
+
|
|
1419
1326
|
/**
|
|
1420
1327
|
* 仅清空 tempOrder 购物车行(products / bookings / discount_list)。
|
|
1421
1328
|
* 同步清空内存中的 salesDetail 商品/预约视图,避免编辑态仍读到旧 bookings。
|
|
1422
1329
|
*/
|
|
1423
1330
|
async clearOrderCartLines() {
|
|
1424
1331
|
try {
|
|
1425
|
-
if (!this.store.order)
|
|
1426
|
-
throw new Error("order 模块未初始化");
|
|
1332
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1427
1333
|
const tempOrder = await this.store.order.clearOrderCartLines();
|
|
1428
1334
|
if (this.currentSalesDetail) {
|
|
1429
1335
|
this.currentSalesDetail = {
|
|
@@ -1435,7 +1341,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1435
1341
|
discount_list: []
|
|
1436
1342
|
};
|
|
1437
1343
|
}
|
|
1438
|
-
await this.effectsEmit(
|
|
1344
|
+
await this.effectsEmit('onTempOrderReplaced', {
|
|
1345
|
+
tempOrder
|
|
1346
|
+
});
|
|
1439
1347
|
if (this.syncAppDataToTempOrder(tempOrder) && this.isTempOrderPersistEnabled()) {
|
|
1440
1348
|
this.store.order.persistTempOrder();
|
|
1441
1349
|
await this.store.order.saveDraft();
|
|
@@ -1445,10 +1353,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1445
1353
|
throw error;
|
|
1446
1354
|
}
|
|
1447
1355
|
}
|
|
1356
|
+
|
|
1448
1357
|
/** 切换法币 / WalletPass 单位时清空商品、折扣与支付状态,保留客户。 */
|
|
1449
1358
|
async clearOrderForSettlementSwitch() {
|
|
1450
|
-
if (!this.store.order)
|
|
1451
|
-
throw new Error("order 模块未初始化");
|
|
1359
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1452
1360
|
const tempOrder = await this.store.order.clearOrderForSettlementSwitch();
|
|
1453
1361
|
if (this.currentSalesDetail) {
|
|
1454
1362
|
this.currentSalesDetail = {
|
|
@@ -1464,15 +1372,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1464
1372
|
return tempOrder;
|
|
1465
1373
|
}
|
|
1466
1374
|
getOrderProducts() {
|
|
1467
|
-
if (!this.store.order)
|
|
1468
|
-
throw new Error("order 模块未初始化");
|
|
1375
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1469
1376
|
const products = this.store.order.getOrderProducts();
|
|
1470
1377
|
return products;
|
|
1471
1378
|
}
|
|
1472
1379
|
async getSummary() {
|
|
1473
1380
|
try {
|
|
1474
|
-
if (!this.store.order)
|
|
1475
|
-
throw new Error("order 模块未初始化");
|
|
1381
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1476
1382
|
const summary = await this.store.order.getOrderSummary();
|
|
1477
1383
|
return summary;
|
|
1478
1384
|
} catch (error) {
|
|
@@ -1481,21 +1387,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1481
1387
|
}
|
|
1482
1388
|
getHistoricalProductDiscountList(products) {
|
|
1483
1389
|
const historyDiscountList = [];
|
|
1484
|
-
products.forEach(
|
|
1485
|
-
if (!this.isPersistedOrderProduct(item))
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
const discountId = ((_a = discount.discount) == null ? void 0 : _a.resource_id) || discount.id;
|
|
1490
|
-
if (!discountId || !["good_pass", "discount_card"].includes(discount.type))
|
|
1491
|
-
return;
|
|
1390
|
+
products.forEach(item => {
|
|
1391
|
+
if (!this.isPersistedOrderProduct(item)) return;
|
|
1392
|
+
(item.discount_list || []).forEach(discount => {
|
|
1393
|
+
const discountId = discount.discount?.resource_id || discount.id;
|
|
1394
|
+
if (!discountId || !['good_pass', 'discount_card'].includes(discount.type)) return;
|
|
1492
1395
|
const quantity = item.quantity || item.num || item.product_quantity || 1;
|
|
1493
|
-
const savedAmount = new
|
|
1494
|
-
const index = historyDiscountList.findIndex(
|
|
1396
|
+
const savedAmount = new _decimal.default(discount.amount || 0).times(quantity).plus(discount?.metadata?.product_discount_difference || 0);
|
|
1397
|
+
const index = historyDiscountList.findIndex(n => n.id === discountId);
|
|
1495
1398
|
if (index !== -1) {
|
|
1496
1399
|
historyDiscountList[index] = {
|
|
1497
1400
|
...historyDiscountList[index],
|
|
1498
|
-
amount: new
|
|
1401
|
+
amount: new _decimal.default(historyDiscountList[index].amount || 0).plus(discount.amount || 0).toNumber(),
|
|
1499
1402
|
savedAmount: savedAmount.plus(historyDiscountList[index].savedAmount || 0).toNumber()
|
|
1500
1403
|
};
|
|
1501
1404
|
return;
|
|
@@ -1504,15 +1407,15 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1504
1407
|
...discount,
|
|
1505
1408
|
id: discountId,
|
|
1506
1409
|
tag: discount.tag || discount.type,
|
|
1507
|
-
name: discount.name ||
|
|
1508
|
-
format_title:
|
|
1410
|
+
name: discount.name || discount.discount?.title?.auto,
|
|
1411
|
+
format_title: discount.discount?.title || discount.format_title,
|
|
1509
1412
|
isEditMode: true,
|
|
1510
1413
|
limited_relation_product_data: {},
|
|
1511
1414
|
savedAmount: savedAmount.toNumber(),
|
|
1512
1415
|
isAvailable: true,
|
|
1513
1416
|
isDisabled: true,
|
|
1514
1417
|
isSelected: true,
|
|
1515
|
-
product_id:
|
|
1418
|
+
product_id: discount.discount?.product_id || discount.product_id
|
|
1516
1419
|
});
|
|
1517
1420
|
});
|
|
1518
1421
|
});
|
|
@@ -1520,57 +1423,38 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1520
1423
|
}
|
|
1521
1424
|
isPersistedOrderProduct(product) {
|
|
1522
1425
|
const orderDetailId = product.order_detail_id ?? product.orderDetailId;
|
|
1523
|
-
if (orderDetailId !==
|
|
1426
|
+
if (orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '') {
|
|
1524
1427
|
return true;
|
|
1525
1428
|
}
|
|
1526
1429
|
const bookingId = product.booking_id ?? product.bookingId;
|
|
1527
|
-
return bookingId !==
|
|
1430
|
+
return bookingId !== undefined && bookingId !== null && bookingId !== '';
|
|
1528
1431
|
}
|
|
1529
1432
|
mergeHistoricalDiscountList(discountList, products) {
|
|
1530
1433
|
const historyDiscountList = this.getHistoricalProductDiscountList(products);
|
|
1531
|
-
const historyIds = new Set(historyDiscountList.map(
|
|
1532
|
-
return [
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
return true;
|
|
1537
|
-
return !isBaseSalesHistoricalDiscountEntry(discount);
|
|
1538
|
-
})
|
|
1539
|
-
];
|
|
1434
|
+
const historyIds = new Set(historyDiscountList.map(discount => discount.id));
|
|
1435
|
+
return [...historyDiscountList, ...(discountList || []).filter(discount => {
|
|
1436
|
+
if (!historyIds.has(discount.id)) return true;
|
|
1437
|
+
return !isBaseSalesHistoricalDiscountEntry(discount);
|
|
1438
|
+
})];
|
|
1540
1439
|
}
|
|
1541
1440
|
shouldSkipAutoApplyFetchedDiscountsInEditMode(params) {
|
|
1542
|
-
if (params.discountAction !==
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
const
|
|
1547
|
-
if (
|
|
1548
|
-
|
|
1549
|
-
const hasSelectedDiscount = params.currentDiscountList.some(
|
|
1550
|
-
(discount) => discount.isSelected || discount.isEditMode || discount.isManualSelect
|
|
1551
|
-
);
|
|
1552
|
-
if (hasSelectedDiscount)
|
|
1553
|
-
return false;
|
|
1554
|
-
return !params.nextDiscountList.some(
|
|
1555
|
-
(discount) => discount.isSelected || discount.isEditMode || discount.isManualSelect
|
|
1556
|
-
);
|
|
1441
|
+
if (params.discountAction !== 'edit') return false;
|
|
1442
|
+
if (!params.products.length) return false;
|
|
1443
|
+
const hasDraftProduct = params.products.some(product => !this.isPersistedOrderProduct(product));
|
|
1444
|
+
if (hasDraftProduct) return false;
|
|
1445
|
+
const hasSelectedDiscount = params.currentDiscountList.some(discount => discount.isSelected || discount.isEditMode || discount.isManualSelect);
|
|
1446
|
+
if (hasSelectedDiscount) return false;
|
|
1447
|
+
return !params.nextDiscountList.some(discount => discount.isSelected || discount.isEditMode || discount.isManualSelect);
|
|
1557
1448
|
}
|
|
1558
1449
|
mergeCurrentDiscountSelectionState(discountList, currentDiscountList) {
|
|
1559
|
-
if (!currentDiscountList.length)
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
currentDiscountMap.set(
|
|
1564
|
-
`${discount.id}:${isBaseSalesHistoricalDiscountEntry(discount) ? "historical" : "runtime"}`,
|
|
1565
|
-
discount
|
|
1566
|
-
);
|
|
1450
|
+
if (!currentDiscountList.length) return discountList;
|
|
1451
|
+
const currentDiscountMap = new Map();
|
|
1452
|
+
currentDiscountList.forEach(discount => {
|
|
1453
|
+
currentDiscountMap.set(`${discount.id}:${isBaseSalesHistoricalDiscountEntry(discount) ? 'historical' : 'runtime'}`, discount);
|
|
1567
1454
|
});
|
|
1568
|
-
return discountList.map(
|
|
1569
|
-
const currentDiscount = currentDiscountMap.get(
|
|
1570
|
-
|
|
1571
|
-
);
|
|
1572
|
-
if (!currentDiscount)
|
|
1573
|
-
return discount;
|
|
1455
|
+
return discountList.map(discount => {
|
|
1456
|
+
const currentDiscount = currentDiscountMap.get(`${discount.id}:${isBaseSalesHistoricalDiscountEntry(discount) ? 'historical' : 'runtime'}`);
|
|
1457
|
+
if (!currentDiscount) return discount;
|
|
1574
1458
|
if (currentDiscount.isManualSelect) {
|
|
1575
1459
|
return {
|
|
1576
1460
|
...discount,
|
|
@@ -1589,46 +1473,38 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1589
1473
|
});
|
|
1590
1474
|
}
|
|
1591
1475
|
async loadDiscountConfig(params) {
|
|
1592
|
-
|
|
1593
|
-
if (!this.store.order)
|
|
1594
|
-
throw new Error("order 模块未初始化");
|
|
1476
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1595
1477
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
1596
1478
|
const orderStore = this.store.order.store || {};
|
|
1597
1479
|
const discountModule = orderStore.discount;
|
|
1598
1480
|
const rulesModule = orderStore.rules;
|
|
1599
|
-
const orderId = tempOrder.order_id ||
|
|
1600
|
-
const customerId = Number(
|
|
1601
|
-
|
|
1602
|
-
);
|
|
1603
|
-
const
|
|
1604
|
-
const
|
|
1605
|
-
const
|
|
1606
|
-
const discountAction = (params == null ? void 0 : params.action) || (orderId ? "edit" : "create");
|
|
1607
|
-
const discountConfigCacheKey = [
|
|
1608
|
-
customerId,
|
|
1609
|
-
discountAction,
|
|
1610
|
-
Number(orderId) || 0
|
|
1611
|
-
].join(":");
|
|
1481
|
+
const orderId = tempOrder.order_id || this.getOrderIdentity?.()?.orderId;
|
|
1482
|
+
const customerId = Number(params?.customerId || tempOrder.customer_id || tempOrder.customer?.id || tempOrder._extend?.customerSnapshot?.id || tempOrder._extend?.customerSnapshot?.customer_id || 0);
|
|
1483
|
+
const currentDiscountList = discountModule?.getDiscountList?.() || [];
|
|
1484
|
+
const originalDiscountList = discountModule?.getOriginalDiscountList?.() || [];
|
|
1485
|
+
const hasManualDiscountSelection = this.hasManualDiscountSelection || currentDiscountList.some(discount => discount.isManualSelect);
|
|
1486
|
+
const discountAction = params?.action || (orderId ? 'edit' : 'create');
|
|
1487
|
+
const discountConfigCacheKey = [customerId, discountAction, Number(orderId) || 0].join(':');
|
|
1612
1488
|
let preparedDiscountList = [];
|
|
1613
1489
|
if (customerId && customerId !== 1) {
|
|
1614
|
-
if (!
|
|
1490
|
+
if (!params?.force && this.discountConfigCacheKey === discountConfigCacheKey) {
|
|
1615
1491
|
preparedDiscountList = originalDiscountList;
|
|
1616
1492
|
} else {
|
|
1617
1493
|
preparedDiscountList = await this.store.order.loadDiscountConfig({
|
|
1618
1494
|
customerId,
|
|
1619
1495
|
action: discountAction,
|
|
1620
|
-
orderId: Number(orderId) ||
|
|
1496
|
+
orderId: Number(orderId) || undefined,
|
|
1621
1497
|
apply: false
|
|
1622
1498
|
});
|
|
1623
1499
|
this.discountConfigCacheKey = discountConfigCacheKey;
|
|
1624
|
-
await
|
|
1500
|
+
await discountModule?.setOriginalDiscountList?.(preparedDiscountList);
|
|
1625
1501
|
}
|
|
1626
1502
|
}
|
|
1627
1503
|
if (this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
1628
|
-
await
|
|
1629
|
-
await
|
|
1504
|
+
await discountModule?.setOriginalDiscountList?.([]);
|
|
1505
|
+
await discountModule?.setDiscountList?.([]);
|
|
1630
1506
|
tempOrder.discount_list = [];
|
|
1631
|
-
tempOrder.shop_discount =
|
|
1507
|
+
tempOrder.shop_discount = '0.00';
|
|
1632
1508
|
return {
|
|
1633
1509
|
productList: tempOrder.products || [],
|
|
1634
1510
|
discountList: [],
|
|
@@ -1644,15 +1520,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1644
1520
|
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1645
1521
|
};
|
|
1646
1522
|
}
|
|
1647
|
-
let nextDiscountList = this.mergeHistoricalDiscountList(
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
);
|
|
1651
|
-
nextDiscountList = this.mergeCurrentDiscountSelectionState(
|
|
1652
|
-
nextDiscountList,
|
|
1653
|
-
currentDiscountList
|
|
1654
|
-
);
|
|
1655
|
-
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
1523
|
+
let nextDiscountList = this.mergeHistoricalDiscountList(preparedDiscountList || discountModule?.getDiscountList?.() || [], tempOrder.products || []);
|
|
1524
|
+
nextDiscountList = this.mergeCurrentDiscountSelectionState(nextDiscountList, currentDiscountList);
|
|
1525
|
+
await discountModule?.setDiscountList(nextDiscountList);
|
|
1656
1526
|
const shouldSkipAutoApplyFetchedDiscounts = this.shouldSkipAutoApplyFetchedDiscountsInEditMode({
|
|
1657
1527
|
discountAction,
|
|
1658
1528
|
products: tempOrder.products || [],
|
|
@@ -1660,9 +1530,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1660
1530
|
nextDiscountList
|
|
1661
1531
|
});
|
|
1662
1532
|
if (shouldSkipAutoApplyFetchedDiscounts) {
|
|
1663
|
-
const
|
|
1533
|
+
const summary = await this.store.order.recalculateSummary({
|
|
1534
|
+
createIfMissing: true
|
|
1535
|
+
});
|
|
1664
1536
|
this.store.order.persistTempOrder();
|
|
1665
|
-
await this.effectsEmit(
|
|
1537
|
+
await this.effectsEmit('onDiscountApplied', {
|
|
1666
1538
|
productList: tempOrder.products || [],
|
|
1667
1539
|
discountList: nextDiscountList,
|
|
1668
1540
|
selectedDiscountList: tempOrder.discount_list || [],
|
|
@@ -1676,56 +1548,50 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1676
1548
|
};
|
|
1677
1549
|
}
|
|
1678
1550
|
if (rulesModule) {
|
|
1679
|
-
const orderTotalAmount = Number(
|
|
1680
|
-
console.log("[BaseSales.applyDiscountConfig.calcDiscount]");
|
|
1551
|
+
const orderTotalAmount = Number(orderStore.summary?.total_amount || 0);
|
|
1681
1552
|
const result = rulesModule.calcDiscount({
|
|
1682
1553
|
productList: tempOrder.products,
|
|
1683
1554
|
discountList: nextDiscountList,
|
|
1684
1555
|
holders: [],
|
|
1685
|
-
isFormSubject:
|
|
1556
|
+
isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
|
|
1686
1557
|
orderTotalAmount
|
|
1687
|
-
}) || {
|
|
1558
|
+
}) || {
|
|
1559
|
+
productList: tempOrder.products,
|
|
1560
|
+
discountList: nextDiscountList
|
|
1561
|
+
};
|
|
1688
1562
|
if (result.productList) {
|
|
1689
|
-
tempOrder.products = preserveManualProductDiscountProducts(
|
|
1690
|
-
tempOrder.products,
|
|
1691
|
-
result.productList
|
|
1692
|
-
);
|
|
1563
|
+
tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
|
|
1693
1564
|
}
|
|
1694
1565
|
for (const product of tempOrder.products || []) {
|
|
1695
|
-
const productUid =
|
|
1696
|
-
const runtimeOrigin = productUid ?
|
|
1697
|
-
if (
|
|
1698
|
-
|
|
1699
|
-
const
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
);
|
|
1703
|
-
const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(product));
|
|
1704
|
-
const sourcePrice = ((_s = product.metadata) == null ? void 0 : _s.source_product_price) ?? (((_t = product.metadata) == null ? void 0 : _t.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");
|
|
1705
|
-
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1706
|
-
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1566
|
+
const productUid = product.metadata?.unique_identification_number;
|
|
1567
|
+
const runtimeOrigin = productUid ? tempOrder._extend?.productsByUid?.[productUid]?.origin : undefined;
|
|
1568
|
+
if (runtimeOrigin?.isManualDiscount || isBaseSalesManualProductDiscountProduct(product)) continue;
|
|
1569
|
+
const totalPerUnitDiscount = (product.discount_list || []).reduce((sum, pd) => sum + Number(pd.amount || 0), 0);
|
|
1570
|
+
const optionSum = (0, _utils.sumOptionUnitPrice)((0, _utils.getProductSkuOptions)(product));
|
|
1571
|
+
const sourcePrice = product.metadata?.source_product_price ?? (product.metadata?.main_product_original_price != null ? new _decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? '0');
|
|
1572
|
+
const newSourceSellingPrice = new _decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1573
|
+
const newMainSellingPrice = new _decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1707
1574
|
if (product.metadata) {
|
|
1708
1575
|
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
1709
1576
|
product.metadata.price_schema_version = 2;
|
|
1710
1577
|
}
|
|
1711
|
-
product.selling_price = (0,
|
|
1578
|
+
product.selling_price = (0, _utils.composeLinePrice)({
|
|
1712
1579
|
mainPrice: newMainSellingPrice,
|
|
1713
1580
|
bundle: product.product_bundle
|
|
1714
1581
|
});
|
|
1715
1582
|
}
|
|
1716
1583
|
if (result.discountList) {
|
|
1717
|
-
nextDiscountList = this.mergeHistoricalDiscountList(
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
);
|
|
1721
|
-
import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1722
|
-
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
1723
|
-
tempOrder.discount_list = nextDiscountList.filter((discount) => discount.isSelected);
|
|
1584
|
+
nextDiscountList = this.mergeHistoricalDiscountList(result.discountList, tempOrder.products || []);
|
|
1585
|
+
_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1586
|
+
await discountModule?.setDiscountList(nextDiscountList);
|
|
1587
|
+
tempOrder.discount_list = nextDiscountList.filter(discount => discount.isSelected);
|
|
1724
1588
|
}
|
|
1725
1589
|
}
|
|
1726
|
-
const summary = await this.store.order.recalculateSummary({
|
|
1590
|
+
const summary = await this.store.order.recalculateSummary({
|
|
1591
|
+
createIfMissing: true
|
|
1592
|
+
});
|
|
1727
1593
|
this.store.order.persistTempOrder();
|
|
1728
|
-
await this.effectsEmit(
|
|
1594
|
+
await this.effectsEmit('onDiscountApplied', {
|
|
1729
1595
|
productList: tempOrder.products || [],
|
|
1730
1596
|
discountList: nextDiscountList,
|
|
1731
1597
|
selectedDiscountList: tempOrder.discount_list || [],
|
|
@@ -1739,109 +1605,91 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1739
1605
|
};
|
|
1740
1606
|
}
|
|
1741
1607
|
getAvailableWalletIds() {
|
|
1742
|
-
|
|
1743
|
-
if (!((_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds))
|
|
1744
|
-
return [];
|
|
1608
|
+
if (!this.store.order?.getAvailableWalletIds) return [];
|
|
1745
1609
|
return this.store.order.getAvailableWalletIds();
|
|
1746
1610
|
}
|
|
1747
1611
|
getVirtualCurrencyList() {
|
|
1748
|
-
|
|
1749
|
-
if (!((_a = this.store.order) == null ? void 0 : _a.getVirtualCurrencyList))
|
|
1750
|
-
return [];
|
|
1612
|
+
if (!this.store.order?.getVirtualCurrencyList) return [];
|
|
1751
1613
|
return this.store.order.getVirtualCurrencyList();
|
|
1752
1614
|
}
|
|
1753
1615
|
async bestDiscount(cb) {
|
|
1754
|
-
|
|
1755
|
-
if (!this.store.order)
|
|
1756
|
-
throw new Error("order 模块未初始化");
|
|
1616
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1757
1617
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
1758
1618
|
if (this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
1759
|
-
const
|
|
1619
|
+
const result = {
|
|
1760
1620
|
productList: tempOrder.products || [],
|
|
1761
1621
|
discountList: []
|
|
1762
1622
|
};
|
|
1763
|
-
cb
|
|
1764
|
-
return
|
|
1623
|
+
cb?.(result);
|
|
1624
|
+
return result;
|
|
1765
1625
|
}
|
|
1766
1626
|
const orderStore = this.store.order.store || {};
|
|
1767
1627
|
const discountModule = orderStore.discount;
|
|
1768
1628
|
const rulesModule = orderStore.rules;
|
|
1769
|
-
const originalDiscountList =
|
|
1770
|
-
const currentDiscountList =
|
|
1771
|
-
let nextDiscountList = this.mergeHistoricalDiscountList(
|
|
1772
|
-
originalDiscountList || [],
|
|
1773
|
-
tempOrder.products || []
|
|
1774
|
-
);
|
|
1629
|
+
const originalDiscountList = discountModule?.getOriginalDiscountList?.() || this.getDiscountList();
|
|
1630
|
+
const currentDiscountList = discountModule?.getDiscountList?.() || [];
|
|
1631
|
+
let nextDiscountList = this.mergeHistoricalDiscountList(originalDiscountList || [], tempOrder.products || []);
|
|
1775
1632
|
let result = {
|
|
1776
1633
|
productList: tempOrder.products || [],
|
|
1777
1634
|
discountList: nextDiscountList
|
|
1778
1635
|
};
|
|
1779
|
-
await
|
|
1636
|
+
await discountModule?.setDiscountList(nextDiscountList);
|
|
1780
1637
|
if (rulesModule) {
|
|
1781
|
-
const orderTotalAmount = Number(
|
|
1782
|
-
console.log("[BaseSales.bestDiscount.calcDiscount]");
|
|
1638
|
+
const orderTotalAmount = Number(orderStore.summary?.total_amount || 0);
|
|
1783
1639
|
result = rulesModule.calcDiscount({
|
|
1784
1640
|
productList: tempOrder.products,
|
|
1785
1641
|
discountList: nextDiscountList,
|
|
1786
1642
|
holders: [],
|
|
1787
|
-
isFormSubject:
|
|
1643
|
+
isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
|
|
1788
1644
|
orderTotalAmount
|
|
1789
1645
|
}) || result;
|
|
1790
1646
|
if (result.productList) {
|
|
1791
|
-
tempOrder.products = preserveManualProductDiscountProducts(
|
|
1792
|
-
tempOrder.products,
|
|
1793
|
-
result.productList
|
|
1794
|
-
);
|
|
1647
|
+
tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
|
|
1795
1648
|
}
|
|
1796
1649
|
if (result.discountList) {
|
|
1797
|
-
nextDiscountList = this.mergeHistoricalDiscountList(
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
);
|
|
1801
|
-
import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1802
|
-
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
1803
|
-
tempOrder.discount_list = nextDiscountList.filter((discount) => discount.isSelected);
|
|
1650
|
+
nextDiscountList = this.mergeHistoricalDiscountList(result.discountList, tempOrder.products || []);
|
|
1651
|
+
_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1652
|
+
await discountModule?.setDiscountList(nextDiscountList);
|
|
1653
|
+
tempOrder.discount_list = nextDiscountList.filter(discount => discount.isSelected);
|
|
1804
1654
|
result = {
|
|
1805
1655
|
productList: tempOrder.products,
|
|
1806
1656
|
discountList: nextDiscountList
|
|
1807
1657
|
};
|
|
1808
1658
|
}
|
|
1809
1659
|
}
|
|
1810
|
-
await this.store.order.recalculateSummary({
|
|
1660
|
+
await this.store.order.recalculateSummary({
|
|
1661
|
+
createIfMissing: true
|
|
1662
|
+
});
|
|
1811
1663
|
this.store.order.persistTempOrder();
|
|
1812
|
-
await this.effectsEmit(
|
|
1664
|
+
await this.effectsEmit('onDiscountApplied', {
|
|
1813
1665
|
productList: tempOrder.products || [],
|
|
1814
1666
|
discountList: nextDiscountList,
|
|
1815
1667
|
selectedDiscountList: tempOrder.discount_list || [],
|
|
1816
1668
|
tempOrder
|
|
1817
1669
|
});
|
|
1818
|
-
cb
|
|
1670
|
+
cb?.(result);
|
|
1819
1671
|
return result;
|
|
1820
1672
|
}
|
|
1821
1673
|
getDiscountList() {
|
|
1822
|
-
if (!this.store.order)
|
|
1823
|
-
return [];
|
|
1674
|
+
if (!this.store.order) return [];
|
|
1824
1675
|
return this.store.order.getDiscountList();
|
|
1825
1676
|
}
|
|
1677
|
+
|
|
1826
1678
|
/** 读取 Discount 模块原始券列表(未经过 bookingTime 等过滤)。 */
|
|
1827
1679
|
getOriginalDiscountList() {
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
|
|
1832
|
-
return ((_b = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
|
|
1680
|
+
if (!this.store.order) return [];
|
|
1681
|
+
const discountModule = this.store.order.store?.discount;
|
|
1682
|
+
return discountModule?.getOriginalDiscountList?.() || [];
|
|
1833
1683
|
}
|
|
1684
|
+
|
|
1834
1685
|
/**
|
|
1835
1686
|
* 同步写入 Discount 模块的 discountList / originalDiscountList。
|
|
1836
1687
|
* 供 Holder 补全等场景在 OS store 层更新 machinecode holder 字段。
|
|
1837
1688
|
*/
|
|
1838
1689
|
async replaceDiscountStoreLists(params) {
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
|
|
1843
|
-
if (!discountModule)
|
|
1844
|
-
return;
|
|
1690
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1691
|
+
const discountModule = this.store.order.store?.discount;
|
|
1692
|
+
if (!discountModule) return;
|
|
1845
1693
|
if (params.originalDiscountList) {
|
|
1846
1694
|
await discountModule.setOriginalDiscountList(params.originalDiscountList);
|
|
1847
1695
|
}
|
|
@@ -1849,14 +1697,15 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1849
1697
|
}
|
|
1850
1698
|
async scanPromotionCode(code, customerId) {
|
|
1851
1699
|
try {
|
|
1852
|
-
if (!this.store.order)
|
|
1853
|
-
throw new Error("order 模块未初始化");
|
|
1700
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1854
1701
|
const raw = await this.store.order.scanCode(code, customerId);
|
|
1855
1702
|
if (raw.isAvailable) {
|
|
1856
|
-
await this.store.order.recalculateSummary({
|
|
1703
|
+
await this.store.order.recalculateSummary({
|
|
1704
|
+
createIfMissing: true
|
|
1705
|
+
});
|
|
1857
1706
|
this.store.order.persistTempOrder();
|
|
1858
1707
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
1859
|
-
await this.effectsEmit(
|
|
1708
|
+
await this.effectsEmit('onDiscountApplied', {
|
|
1860
1709
|
productList: tempOrder.products || [],
|
|
1861
1710
|
discountList: this.store.order.getDiscountList(),
|
|
1862
1711
|
selectedDiscountList: tempOrder.discount_list || [],
|
|
@@ -1865,7 +1714,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1865
1714
|
}
|
|
1866
1715
|
return {
|
|
1867
1716
|
isAvailable: raw.isAvailable,
|
|
1868
|
-
...raw.isAccepted !==
|
|
1717
|
+
...(raw.isAccepted !== undefined ? {
|
|
1718
|
+
isAccepted: raw.isAccepted
|
|
1719
|
+
} : {}),
|
|
1869
1720
|
type: raw.type,
|
|
1870
1721
|
unavailableReason: raw.unavailableReason,
|
|
1871
1722
|
scannedDiscountList: raw.scannedDiscountList
|
|
@@ -1874,64 +1725,57 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1874
1725
|
throw error;
|
|
1875
1726
|
}
|
|
1876
1727
|
}
|
|
1728
|
+
|
|
1877
1729
|
// TODO 需要优化,这段逻辑太长了,里面应该有些历史遗留问题
|
|
1878
1730
|
async setDiscountSelected(params) {
|
|
1879
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1880
1731
|
try {
|
|
1881
|
-
if (!this.store.order)
|
|
1882
|
-
throw new Error("order 模块未初始化");
|
|
1732
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1883
1733
|
const currentOrder = this.store.order.ensureTempOrder();
|
|
1884
1734
|
if (this.isActiveVirtualSettlementOrder(currentOrder)) {
|
|
1885
1735
|
currentOrder.discount_list = [];
|
|
1886
|
-
currentOrder.shop_discount =
|
|
1887
|
-
await
|
|
1888
|
-
await this.store.order.recalculateSummary({
|
|
1736
|
+
currentOrder.shop_discount = '0.00';
|
|
1737
|
+
await this.store.order.store?.discount?.setDiscountList?.([]);
|
|
1738
|
+
await this.store.order.recalculateSummary({
|
|
1739
|
+
createIfMissing: true
|
|
1740
|
+
});
|
|
1889
1741
|
this.store.order.persistTempOrder();
|
|
1890
1742
|
return;
|
|
1891
1743
|
}
|
|
1892
1744
|
const list = this.store.order.getDiscountList();
|
|
1893
|
-
const updated = list.map(
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
} : d
|
|
1899
|
-
);
|
|
1745
|
+
const updated = list.map(d => d.id === params.discountId && !isBaseSalesHistoricalDiscountEntry(d) ? {
|
|
1746
|
+
...d,
|
|
1747
|
+
isSelected: params.isSelected,
|
|
1748
|
+
isManualSelect: !params.isSelected
|
|
1749
|
+
} : d);
|
|
1900
1750
|
this.hasManualDiscountSelection = true;
|
|
1901
1751
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
1902
1752
|
const orderStore = this.store.order.store || {};
|
|
1903
1753
|
const discountModule = orderStore.discount;
|
|
1904
1754
|
const rulesModule = orderStore.rules;
|
|
1905
1755
|
let nextDiscountList = updated;
|
|
1906
|
-
await
|
|
1756
|
+
await discountModule?.setDiscountList(updated);
|
|
1907
1757
|
if (rulesModule) {
|
|
1908
|
-
const orderTotalAmount = Number(
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
)
|
|
1923
|
-
|
|
1924
|
-
tempOrder.products = preserveManualProductDiscountProducts(
|
|
1925
|
-
tempOrder.products,
|
|
1926
|
-
result.productList
|
|
1927
|
-
);
|
|
1758
|
+
const orderTotalAmount = Number(orderStore.summary?.total_amount || 0);
|
|
1759
|
+
const result = rulesModule.calcDiscount({
|
|
1760
|
+
productList: tempOrder.products,
|
|
1761
|
+
discountList: updated,
|
|
1762
|
+
holders: [],
|
|
1763
|
+
isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
|
|
1764
|
+
orderTotalAmount
|
|
1765
|
+
}, {
|
|
1766
|
+
discountId: params.discountId,
|
|
1767
|
+
isSelected: params.isSelected
|
|
1768
|
+
}) || {
|
|
1769
|
+
productList: tempOrder.products,
|
|
1770
|
+
discountList: updated
|
|
1771
|
+
};
|
|
1772
|
+
if (result?.productList) {
|
|
1773
|
+
tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
|
|
1928
1774
|
}
|
|
1929
|
-
if (result
|
|
1775
|
+
if (result?.discountList) {
|
|
1930
1776
|
nextDiscountList = result.discountList;
|
|
1931
1777
|
if (!params.isSelected) {
|
|
1932
|
-
const beforeSelectedIds = new Set(
|
|
1933
|
-
updated.filter((d) => d.isSelected).map((d) => d.id)
|
|
1934
|
-
);
|
|
1778
|
+
const beforeSelectedIds = new Set(updated.filter(d => d.isSelected).map(d => d.id));
|
|
1935
1779
|
for (const d of nextDiscountList) {
|
|
1936
1780
|
if (d.isSelected && !beforeSelectedIds.has(d.id)) {
|
|
1937
1781
|
d.isSelected = false;
|
|
@@ -1942,58 +1786,57 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1942
1786
|
}
|
|
1943
1787
|
}
|
|
1944
1788
|
}
|
|
1945
|
-
const selectedResourceIds = new Set(
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
const filterSelectedDiscountDetails = (discountList) => (discountList || []).filter((pd) => {
|
|
1949
|
-
var _a2;
|
|
1950
|
-
const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
|
|
1789
|
+
const selectedResourceIds = new Set(nextDiscountList.filter(d => d.isSelected).map(d => d.id));
|
|
1790
|
+
const filterSelectedDiscountDetails = discountList => (discountList || []).filter(pd => {
|
|
1791
|
+
const rid = pd.discount?.resource_id ?? pd.id;
|
|
1951
1792
|
return rid != null && selectedResourceIds.has(rid);
|
|
1952
1793
|
});
|
|
1953
1794
|
for (const product of tempOrder.products) {
|
|
1954
|
-
const productUid =
|
|
1955
|
-
const runtimeOrigin = productUid ?
|
|
1956
|
-
if (
|
|
1957
|
-
continue;
|
|
1795
|
+
const productUid = product.metadata?.unique_identification_number;
|
|
1796
|
+
const runtimeOrigin = productUid ? tempOrder._extend?.productsByUid?.[productUid]?.origin : undefined;
|
|
1797
|
+
if (runtimeOrigin?.isManualDiscount || isBaseSalesManualProductDiscountProduct(product)) continue;
|
|
1958
1798
|
product.discount_list = filterSelectedDiscountDetails(product.discount_list);
|
|
1959
1799
|
if (Array.isArray(product.product_bundle)) {
|
|
1960
|
-
product.product_bundle = product.product_bundle.map(
|
|
1961
|
-
const nextBundleDiscountList = filterSelectedDiscountDetails(bundle
|
|
1800
|
+
product.product_bundle = product.product_bundle.map(bundle => {
|
|
1801
|
+
const nextBundleDiscountList = filterSelectedDiscountDetails(bundle?.discount_list);
|
|
1962
1802
|
const shouldRestoreBundlePrice = nextBundleDiscountList.length === 0;
|
|
1963
|
-
const restoredBundlePrice =
|
|
1803
|
+
const restoredBundlePrice = bundle?.original_price ?? bundle?.product_price ?? bundle?.price;
|
|
1964
1804
|
return {
|
|
1965
1805
|
...bundle,
|
|
1966
|
-
...shouldRestoreBundlePrice ? {
|
|
1806
|
+
...(shouldRestoreBundlePrice ? {
|
|
1967
1807
|
price: restoredBundlePrice,
|
|
1968
1808
|
bundle_selling_price: restoredBundlePrice
|
|
1969
|
-
} : {},
|
|
1809
|
+
} : {}),
|
|
1970
1810
|
discount_list: nextBundleDiscountList
|
|
1971
1811
|
};
|
|
1972
1812
|
});
|
|
1973
1813
|
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
);
|
|
1978
|
-
|
|
1979
|
-
const
|
|
1980
|
-
const
|
|
1981
|
-
const
|
|
1814
|
+
|
|
1815
|
+
// 券作用于 source(不含 option、不含 bundle);算出新 source 折后价后补回 options
|
|
1816
|
+
// 写入含 option 的 main_product_selling_price,再合成 composite 回写 selling_price。
|
|
1817
|
+
const totalPerUnitDiscount = (product.discount_list || []).reduce((sum, pd) => sum + (pd.amount || 0), 0);
|
|
1818
|
+
// TODO 这块逻辑需要拿掉
|
|
1819
|
+
const optionSum = (0, _utils.sumOptionUnitPrice)((0, _utils.getProductSkuOptions)(product));
|
|
1820
|
+
const sourcePrice = product.metadata?.source_product_price ?? (product.metadata?.main_product_original_price != null ? new _decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? '0');
|
|
1821
|
+
const newSourceSellingPrice = new _decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1822
|
+
const newMainSellingPrice = new _decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1982
1823
|
if (product.metadata) {
|
|
1983
1824
|
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
1984
1825
|
product.metadata.price_schema_version = 2;
|
|
1985
1826
|
}
|
|
1986
|
-
product.selling_price = (0,
|
|
1827
|
+
product.selling_price = (0, _utils.composeLinePrice)({
|
|
1987
1828
|
mainPrice: newMainSellingPrice,
|
|
1988
1829
|
bundle: product.product_bundle
|
|
1989
1830
|
});
|
|
1990
1831
|
}
|
|
1991
|
-
|
|
1992
|
-
await
|
|
1993
|
-
tempOrder.discount_list = (nextDiscountList || []).filter(
|
|
1994
|
-
await this.store.order.recalculateSummary({
|
|
1832
|
+
_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
1833
|
+
await discountModule?.setDiscountList(nextDiscountList);
|
|
1834
|
+
tempOrder.discount_list = (nextDiscountList || []).filter(d => d.isSelected);
|
|
1835
|
+
await this.store.order.recalculateSummary({
|
|
1836
|
+
createIfMissing: true
|
|
1837
|
+
});
|
|
1995
1838
|
this.store.order.persistTempOrder();
|
|
1996
|
-
this.effectsEmit(
|
|
1839
|
+
this.effectsEmit('onDiscountApplied', {
|
|
1997
1840
|
productList: tempOrder.products,
|
|
1998
1841
|
discountList: nextDiscountList,
|
|
1999
1842
|
selectedDiscountList: tempOrder.discount_list,
|
|
@@ -2005,32 +1848,24 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2005
1848
|
}
|
|
2006
1849
|
async applyDiscountCalculationResult(result) {
|
|
2007
1850
|
try {
|
|
2008
|
-
if (!this.store.order)
|
|
2009
|
-
|
|
2010
|
-
if (!result)
|
|
2011
|
-
return;
|
|
1851
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1852
|
+
if (!result) return;
|
|
2012
1853
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
2013
1854
|
const orderStore = this.store.order.store || {};
|
|
2014
1855
|
const discountModule = orderStore.discount;
|
|
2015
1856
|
if (result.productList) {
|
|
2016
|
-
tempOrder.products = preserveManualProductDiscountProducts(
|
|
2017
|
-
tempOrder.products,
|
|
2018
|
-
result.productList
|
|
2019
|
-
);
|
|
1857
|
+
tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
|
|
2020
1858
|
}
|
|
2021
1859
|
if (result.discountList) {
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
);
|
|
2030
|
-
}
|
|
2031
|
-
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
1860
|
+
_Order.OrderModule.populateSavedAmounts(tempOrder.products, result.discountList);
|
|
1861
|
+
await discountModule?.setDiscountList(result.discountList);
|
|
1862
|
+
tempOrder.discount_list = result.discountList.filter(discount => discount.isSelected);
|
|
1863
|
+
}
|
|
1864
|
+
await this.store.order.recalculateSummary({
|
|
1865
|
+
createIfMissing: true
|
|
1866
|
+
});
|
|
2032
1867
|
this.store.order.persistTempOrder();
|
|
2033
|
-
await this.effectsEmit(
|
|
1868
|
+
await this.effectsEmit('onDiscountApplied', {
|
|
2034
1869
|
productList: tempOrder.products || [],
|
|
2035
1870
|
discountList: result.discountList || [],
|
|
2036
1871
|
selectedDiscountList: tempOrder.discount_list || [],
|
|
@@ -2041,41 +1876,35 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2041
1876
|
}
|
|
2042
1877
|
}
|
|
2043
1878
|
async submitScanOrder(params) {
|
|
1879
|
+
// Deprecated compatibility alias. New BaseSales callers should use submitSalesOrder.
|
|
2044
1880
|
return this.submitSalesOrder(params);
|
|
2045
1881
|
}
|
|
2046
1882
|
async buildVirtualSettlementSubmitData() {
|
|
2047
|
-
|
|
2048
|
-
if (!this.store.order)
|
|
2049
|
-
return null;
|
|
1883
|
+
if (!this.store.order) return null;
|
|
2050
1884
|
const tempOrder = this.store.order.getTempOrder();
|
|
2051
|
-
if (!this.isActiveVirtualSettlementOrder(tempOrder))
|
|
2052
|
-
|
|
2053
|
-
const
|
|
2054
|
-
const currencyProductId = Number(
|
|
2055
|
-
((_c = (_b = (_a = tempOrder == null ? void 0 : tempOrder.metadata) == null ? void 0 : _a.currency_settlement_config) == null ? void 0 : _b.settlement_ids) == null ? void 0 : _c[0]) ?? (snapshot == null ? void 0 : snapshot.currency_product_id)
|
|
2056
|
-
);
|
|
1885
|
+
if (!this.isActiveVirtualSettlementOrder(tempOrder)) return null;
|
|
1886
|
+
const snapshot = (0, _virtualSettlement.getTempOrderSettlementSnapshot)(tempOrder);
|
|
1887
|
+
const currencyProductId = Number(tempOrder?.metadata?.currency_settlement_config?.settlement_ids?.[0] ?? snapshot?.currency_product_id);
|
|
2057
1888
|
if (!snapshot || !Number.isFinite(currencyProductId) || currencyProductId <= 0) {
|
|
2058
|
-
throw new Error(
|
|
1889
|
+
throw new Error('Virtual currency settlement configuration is invalid.');
|
|
2059
1890
|
}
|
|
2060
|
-
const summary = await this.store.order.recalculateSummary({
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
).toDecimalPlaces(2);
|
|
2064
|
-
const customerId = Number(
|
|
1891
|
+
const summary = await this.store.order.recalculateSummary({
|
|
1892
|
+
createIfMissing: true
|
|
1893
|
+
});
|
|
1894
|
+
const amount = new _decimal.default(summary?.total_amount || 0).toDecimalPlaces(2);
|
|
1895
|
+
const customerId = Number(tempOrder?.customer_id || 0);
|
|
2065
1896
|
if (amount.gt(0) && customerId > 0 && customerId !== 1) {
|
|
2066
1897
|
await this.store.order.loadDiscountConfig({
|
|
2067
1898
|
customerId,
|
|
2068
|
-
action:
|
|
2069
|
-
orderId: Number(tempOrder
|
|
1899
|
+
action: tempOrder?.order_id ? 'edit' : 'create',
|
|
1900
|
+
orderId: Number(tempOrder?.order_id) || undefined,
|
|
2070
1901
|
apply: false
|
|
2071
1902
|
});
|
|
2072
1903
|
}
|
|
2073
|
-
const asset = this.store.order.getVirtualCurrencyList().find(
|
|
2074
|
-
|
|
2075
|
-
);
|
|
2076
|
-
const
|
|
2077
|
-
const currencySymbol = String((tempOrder == null ? void 0 : tempOrder.currency_symbol) || "");
|
|
2078
|
-
const currencyFormat = String((tempOrder == null ? void 0 : tempOrder.currency_format) || "symbol_first");
|
|
1904
|
+
const asset = this.store.order.getVirtualCurrencyList().find(item => Number(item?.product_id) === currencyProductId);
|
|
1905
|
+
const currencyCode = String(tempOrder?.currency_code || '');
|
|
1906
|
+
const currencySymbol = String(tempOrder?.currency_symbol || '');
|
|
1907
|
+
const currencyFormat = String(tempOrder?.currency_format || 'symbol_first');
|
|
2079
1908
|
if (amount.lte(0)) {
|
|
2080
1909
|
return {
|
|
2081
1910
|
payments: [],
|
|
@@ -2087,34 +1916,35 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2087
1916
|
};
|
|
2088
1917
|
}
|
|
2089
1918
|
if (!asset) {
|
|
2090
|
-
throw new Error(
|
|
1919
|
+
throw new Error('No matching virtual currency card is available.');
|
|
2091
1920
|
}
|
|
2092
|
-
const balance = new
|
|
1921
|
+
const balance = new _decimal.default(asset.balance || 0);
|
|
2093
1922
|
if (balance.lt(amount)) {
|
|
2094
|
-
throw new Error(
|
|
1923
|
+
throw new Error('Insufficient virtual currency balance.');
|
|
2095
1924
|
}
|
|
2096
1925
|
const amountText = amount.toFixed(2);
|
|
2097
|
-
const paymentNumber = `LOCAL_${(0,
|
|
1926
|
+
const paymentNumber = `LOCAL_${(0, _utils.createUuidV4)()}`;
|
|
2098
1927
|
let payment;
|
|
2099
1928
|
if (this.store.order.isOnlineStorePlatform()) {
|
|
2100
1929
|
payment = {
|
|
2101
1930
|
payment_number: paymentNumber,
|
|
2102
1931
|
amount: amount.toNumber(),
|
|
2103
1932
|
metadata: {
|
|
2104
|
-
unique_payment_number: (0,
|
|
1933
|
+
unique_payment_number: (0, _utils.createUuidV4)()
|
|
2105
1934
|
},
|
|
2106
1935
|
tag: asset.tag,
|
|
2107
1936
|
voucher_id: asset.id,
|
|
2108
|
-
wallet_pass_usage_unit: {
|
|
1937
|
+
wallet_pass_usage_unit: {
|
|
1938
|
+
price: 1,
|
|
1939
|
+
points: 1
|
|
1940
|
+
},
|
|
2109
1941
|
wallet_pass_use_value: amountText
|
|
2110
1942
|
};
|
|
2111
1943
|
} else {
|
|
2112
1944
|
const paymentMethods = await this.getPaymentMethodsAsync();
|
|
2113
|
-
const paymentMethod = paymentMethods.find(
|
|
2114
|
-
(method) => String(method.code || "").toUpperCase() === "PRODUCTVOUCHER"
|
|
2115
|
-
);
|
|
1945
|
+
const paymentMethod = paymentMethods.find(method => String(method.code || '').toUpperCase() === 'PRODUCTVOUCHER');
|
|
2116
1946
|
if (!paymentMethod) {
|
|
2117
|
-
throw new Error(
|
|
1947
|
+
throw new Error('PRODUCTVOUCHER payment method is unavailable.');
|
|
2118
1948
|
}
|
|
2119
1949
|
payment = {
|
|
2120
1950
|
payment_number: paymentNumber,
|
|
@@ -2124,10 +1954,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2124
1954
|
custom_payment_id: paymentMethod.id,
|
|
2125
1955
|
custom_payment_type: paymentMethod.custom_payment_type ?? paymentMethod.type,
|
|
2126
1956
|
name: paymentMethod.name,
|
|
2127
|
-
type:
|
|
1957
|
+
type: 'normal',
|
|
2128
1958
|
voucher_id: asset.id,
|
|
2129
|
-
order_payment_type:
|
|
2130
|
-
wallet_pass_usage_unit: {
|
|
1959
|
+
order_payment_type: 'normal',
|
|
1960
|
+
wallet_pass_usage_unit: {
|
|
1961
|
+
price: 1,
|
|
1962
|
+
points: 1
|
|
1963
|
+
},
|
|
2131
1964
|
wallet_pass_use_value: amountText,
|
|
2132
1965
|
metadata: {}
|
|
2133
1966
|
};
|
|
@@ -2141,6 +1974,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2141
1974
|
currencyFormat
|
|
2142
1975
|
};
|
|
2143
1976
|
}
|
|
1977
|
+
|
|
2144
1978
|
/**
|
|
2145
1979
|
* 提交当前 Sales 订单。
|
|
2146
1980
|
*
|
|
@@ -2148,36 +1982,49 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2148
1982
|
* payments 会交给 OrderModule 统一映射为 Sales 协议支付项。
|
|
2149
1983
|
*/
|
|
2150
1984
|
async submitSalesOrder(params) {
|
|
2151
|
-
var _a, _b, _c, _d;
|
|
2152
1985
|
if (!this.store.order) {
|
|
2153
|
-
throw new Error(
|
|
1986
|
+
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2154
1987
|
}
|
|
2155
1988
|
const virtualSettlement = await this.buildVirtualSettlementSubmitData();
|
|
2156
|
-
|
|
2157
|
-
const
|
|
1989
|
+
// this.store.order.persistTempOrder();
|
|
1990
|
+
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
1991
|
+
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2158
1992
|
const submitParams = {
|
|
2159
1993
|
cacheId: this.cacheId,
|
|
2160
|
-
platform:
|
|
2161
|
-
businessCode:
|
|
1994
|
+
platform: this.otherParams?.platform,
|
|
1995
|
+
businessCode: this.otherParams?.businessCode || this.otherParams?.business_code,
|
|
2162
1996
|
channel: this.getSubmitOrderSalesChannel(),
|
|
2163
|
-
type:
|
|
1997
|
+
type: this.otherParams?.type,
|
|
2164
1998
|
request_unique_idempotency_token: this.store.order.generateIdempotencyToken(),
|
|
2165
|
-
...virtualSettlement ? {
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
1999
|
+
...(virtualSettlement ? {
|
|
2000
|
+
payments: virtualSettlement.payments
|
|
2001
|
+
} : params?.payments !== undefined ? {
|
|
2002
|
+
payments: params.payments
|
|
2003
|
+
} : {}),
|
|
2004
|
+
...(inferredPaymentStatus !== undefined ? {
|
|
2005
|
+
paymentStatus: inferredPaymentStatus
|
|
2006
|
+
} : {}),
|
|
2007
|
+
...(smallTicketDataFlag !== undefined ? {
|
|
2008
|
+
smallTicketDataFlag
|
|
2009
|
+
} : {}),
|
|
2010
|
+
...(virtualSettlement ? {
|
|
2169
2011
|
confirmPendingVoucherPayments: false
|
|
2170
|
-
} :
|
|
2171
|
-
|
|
2012
|
+
} : params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2013
|
+
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2014
|
+
} : {}),
|
|
2015
|
+
...(virtualSettlement ? {
|
|
2172
2016
|
enhancePayload: (payload, ctx) => {
|
|
2173
|
-
const callerPayload =
|
|
2017
|
+
const callerPayload = params?.enhancePayload ? params.enhancePayload(payload, ctx) : payload;
|
|
2018
|
+
const currencySettlementConfig = callerPayload.metadata?.currency_settlement_config || {};
|
|
2174
2019
|
return {
|
|
2175
2020
|
...callerPayload,
|
|
2176
2021
|
metadata: {
|
|
2177
|
-
...callerPayload.metadata || {},
|
|
2022
|
+
...(callerPayload.metadata || {}),
|
|
2178
2023
|
currency_settlement_config: {
|
|
2179
|
-
|
|
2180
|
-
|
|
2024
|
+
...currencySettlementConfig,
|
|
2025
|
+
settlement_type: 'virtual_currency',
|
|
2026
|
+
settlement_ids: [virtualSettlement.currencyProductId],
|
|
2027
|
+
currency_display_snapshot: (0, _lodashEs.cloneDeep)(currencySettlementConfig.currency_display_snapshot ?? (0, _virtualSettlement.buildCurrencyDisplaySnapshot)(virtualSettlement.snapshot))
|
|
2181
2028
|
}
|
|
2182
2029
|
},
|
|
2183
2030
|
currency_code: virtualSettlement.currencyCode,
|
|
@@ -2185,71 +2032,87 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2185
2032
|
currency_format: virtualSettlement.currencyFormat
|
|
2186
2033
|
};
|
|
2187
2034
|
}
|
|
2188
|
-
} :
|
|
2035
|
+
} : params?.enhancePayload !== undefined ? {
|
|
2036
|
+
enhancePayload: params.enhancePayload
|
|
2037
|
+
} : {})
|
|
2189
2038
|
};
|
|
2190
2039
|
return this.shouldUseCheckoutSyncTask() ? this.store.order.submitTempOrder(submitParams) : this.store.order.submitTempOrderAsync(submitParams);
|
|
2191
2040
|
}
|
|
2192
2041
|
async saveSalesOrderDraft(params) {
|
|
2193
|
-
var _a, _b, _c, _d;
|
|
2194
2042
|
if (!this.store.order) {
|
|
2195
|
-
throw new Error(
|
|
2043
|
+
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2196
2044
|
}
|
|
2197
2045
|
return this.store.order.saveTempOrderAsDraft({
|
|
2198
2046
|
cacheId: this.cacheId,
|
|
2199
|
-
platform:
|
|
2200
|
-
businessCode:
|
|
2201
|
-
channel:
|
|
2202
|
-
type:
|
|
2203
|
-
...(params
|
|
2047
|
+
platform: params?.platform ?? this.otherParams?.platform,
|
|
2048
|
+
businessCode: params?.businessCode || this.otherParams?.businessCode || this.otherParams?.business_code,
|
|
2049
|
+
channel: params?.channel ?? this.getSubmitOrderSalesChannel(),
|
|
2050
|
+
type: params?.type ?? this.otherParams?.type,
|
|
2051
|
+
...(params?.enhancePayload !== undefined ? {
|
|
2052
|
+
enhancePayload: params.enhancePayload
|
|
2053
|
+
} : {})
|
|
2204
2054
|
});
|
|
2205
2055
|
}
|
|
2206
2056
|
async submitTempOrderAsync(params) {
|
|
2207
|
-
var _a, _b, _c, _d;
|
|
2208
2057
|
if (!this.store.order) {
|
|
2209
|
-
throw new Error(
|
|
2058
|
+
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2210
2059
|
}
|
|
2211
|
-
const inferredPaymentStatus = this.getSubmitPaymentStatus(params
|
|
2212
|
-
const smallTicketDataFlag =
|
|
2060
|
+
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2061
|
+
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2213
2062
|
const submitParams = {
|
|
2214
2063
|
cacheId: this.cacheId,
|
|
2215
|
-
platform:
|
|
2216
|
-
businessCode:
|
|
2064
|
+
platform: this.otherParams?.platform,
|
|
2065
|
+
businessCode: this.otherParams?.businessCode || this.otherParams?.business_code,
|
|
2217
2066
|
channel: this.getSubmitOrderSalesChannel(),
|
|
2218
|
-
type:
|
|
2067
|
+
type: this.otherParams?.type,
|
|
2219
2068
|
request_unique_idempotency_token: this.store.order.generateIdempotencyToken(),
|
|
2220
|
-
...(params
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
...(
|
|
2224
|
-
|
|
2069
|
+
...(params?.payments !== undefined ? {
|
|
2070
|
+
payments: params.payments
|
|
2071
|
+
} : {}),
|
|
2072
|
+
...(inferredPaymentStatus !== undefined ? {
|
|
2073
|
+
paymentStatus: inferredPaymentStatus
|
|
2074
|
+
} : {}),
|
|
2075
|
+
...(smallTicketDataFlag !== undefined ? {
|
|
2076
|
+
smallTicketDataFlag
|
|
2077
|
+
} : {}),
|
|
2078
|
+
...(params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2079
|
+
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2080
|
+
} : {}),
|
|
2081
|
+
...(params?.enhancePayload !== undefined ? {
|
|
2082
|
+
enhancePayload: params.enhancePayload
|
|
2083
|
+
} : {})
|
|
2225
2084
|
};
|
|
2226
2085
|
return this.store.order.submitTempOrderAsync(submitParams);
|
|
2227
2086
|
}
|
|
2087
|
+
|
|
2228
2088
|
/**
|
|
2229
2089
|
* 默认保持 WebPOS 的本地待同步订单模式;需要云端确认后才算成功的渠道可覆盖此策略。
|
|
2230
2090
|
* otherParams.checkoutSyncTaskEnabled 优先,便于同一 solution 按入口恢复旧行为。
|
|
2231
2091
|
*/
|
|
2232
2092
|
shouldUseCheckoutSyncTask() {
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
return typeof configured === "boolean" ? configured : true;
|
|
2093
|
+
const configured = this.otherParams?.checkoutSyncTaskEnabled;
|
|
2094
|
+
return typeof configured === 'boolean' ? configured : true;
|
|
2236
2095
|
}
|
|
2096
|
+
|
|
2237
2097
|
/** 可由特定 solution 为真实 checkout 补充默认收据数据请求。 */
|
|
2238
2098
|
getDefaultCheckoutSmallTicketDataFlag() {
|
|
2239
|
-
return
|
|
2099
|
+
return undefined;
|
|
2240
2100
|
}
|
|
2241
2101
|
async printLocalOrderReceipt(lookup) {
|
|
2242
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
2243
2102
|
if (!this.store.order) {
|
|
2244
|
-
throw new Error(
|
|
2103
|
+
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2245
2104
|
}
|
|
2246
|
-
const hasLookup = lookup !==
|
|
2247
|
-
const lookupPayload = typeof lookup ===
|
|
2105
|
+
const hasLookup = lookup !== undefined && lookup !== null && lookup !== '';
|
|
2106
|
+
const lookupPayload = typeof lookup === 'number' ? {
|
|
2107
|
+
order_id: lookup
|
|
2108
|
+
} : {
|
|
2109
|
+
external_sale_number: lookup
|
|
2110
|
+
};
|
|
2248
2111
|
const context = {
|
|
2249
|
-
platform:
|
|
2250
|
-
businessCode:
|
|
2112
|
+
platform: this.otherParams?.platform,
|
|
2113
|
+
businessCode: this.otherParams?.businessCode || this.otherParams?.business_code,
|
|
2251
2114
|
channel: this.getSubmitOrderSalesChannel(),
|
|
2252
|
-
type:
|
|
2115
|
+
type: this.otherParams?.type
|
|
2253
2116
|
};
|
|
2254
2117
|
const payload = hasLookup ? {
|
|
2255
2118
|
...lookupPayload,
|
|
@@ -2266,48 +2129,46 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2266
2129
|
channel: context.channel,
|
|
2267
2130
|
type: context.type
|
|
2268
2131
|
});
|
|
2269
|
-
const response = await this.request.post(
|
|
2132
|
+
const response = await this.request.post('/local/print-order', payload, {
|
|
2270
2133
|
osServer: true,
|
|
2271
|
-
customToast: () => {
|
|
2272
|
-
}
|
|
2134
|
+
customToast: () => {}
|
|
2273
2135
|
});
|
|
2274
2136
|
if (!hasLookup) {
|
|
2275
|
-
await
|
|
2137
|
+
await this.store.order.applyLocalPrintOrderNumbers?.(response?.data?.order);
|
|
2276
2138
|
}
|
|
2277
2139
|
return response;
|
|
2278
2140
|
}
|
|
2279
2141
|
getSubmitPaymentStatus(paymentStatus) {
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
const amountSnapshot = (_b = (_a = this.store.order) == null ? void 0 : _a.getOrderAmountSnapshot) == null ? void 0 : _b.call(_a);
|
|
2284
|
-
if (!amountSnapshot)
|
|
2285
|
-
return void 0;
|
|
2142
|
+
if (paymentStatus !== undefined) return paymentStatus;
|
|
2143
|
+
const amountSnapshot = this.store.order?.getOrderAmountSnapshot?.();
|
|
2144
|
+
if (!amountSnapshot) return undefined;
|
|
2286
2145
|
try {
|
|
2287
|
-
return new
|
|
2146
|
+
return new _decimal.default(amountSnapshot.amountGap || 0).lte(0) ? 'paid' : undefined;
|
|
2288
2147
|
} catch {
|
|
2289
|
-
return
|
|
2148
|
+
return undefined;
|
|
2290
2149
|
}
|
|
2291
2150
|
}
|
|
2292
2151
|
async syncPaymentsToOrder(params) {
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
throw new Error("order 模块未初始化");
|
|
2296
|
-
const businessCode = params.businessCode ?? ((_a = this.otherParams) == null ? void 0 : _a.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.business_code);
|
|
2152
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2153
|
+
const businessCode = params.businessCode ?? this.otherParams?.businessCode ?? this.otherParams?.business_code;
|
|
2297
2154
|
const channel = params.channel ?? this.getSubmitOrderSalesChannel();
|
|
2298
2155
|
const syncParams = {
|
|
2299
2156
|
...params,
|
|
2300
2157
|
checkoutSyncTaskEnabled: this.shouldUseCheckoutSyncTask(),
|
|
2301
|
-
...businessCode !==
|
|
2302
|
-
|
|
2158
|
+
...(businessCode !== undefined ? {
|
|
2159
|
+
businessCode
|
|
2160
|
+
} : {}),
|
|
2161
|
+
...(channel !== undefined ? {
|
|
2162
|
+
channel
|
|
2163
|
+
} : {})
|
|
2303
2164
|
};
|
|
2304
2165
|
const syncState = this.store.order.getOrderSyncState();
|
|
2305
|
-
if (params.submitWhenPaid && syncState ===
|
|
2166
|
+
if (params.submitWhenPaid && syncState === 'submitting') {
|
|
2306
2167
|
this.queueLatestAutoPaymentSync();
|
|
2307
2168
|
return this.store.order.syncPaymentsToOrder(syncParams);
|
|
2308
2169
|
}
|
|
2309
2170
|
const payments = params.payments || [];
|
|
2310
|
-
await this.effectsEmit(
|
|
2171
|
+
await this.effectsEmit(_types.BaseSalesHookNames.onPaymentSyncStart, {
|
|
2311
2172
|
payments,
|
|
2312
2173
|
params: syncParams,
|
|
2313
2174
|
amountSnapshot: this.store.order.getOrderAmountSnapshot(),
|
|
@@ -2332,14 +2193,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2332
2193
|
depositAmount: syncResult.depositAmount,
|
|
2333
2194
|
orderExpectedAmount: syncResult.orderExpectedAmount
|
|
2334
2195
|
};
|
|
2335
|
-
await this.effectsEmit(
|
|
2196
|
+
await this.effectsEmit(_types.BaseSalesHookNames.onPaymentSyncEnd, syncPayload);
|
|
2336
2197
|
if (syncResult.isDepositFullyPaid && !syncResult.isOrderFullyPaid) {
|
|
2337
|
-
await this.effectsEmit(
|
|
2198
|
+
await this.effectsEmit(_types.BaseSalesHookNames.onDepositPaymentSyncEnd, syncPayload);
|
|
2338
2199
|
}
|
|
2339
2200
|
this.scheduleQueuedAutoPaymentSyncFlush(0);
|
|
2340
2201
|
return syncResult;
|
|
2341
2202
|
} catch (error) {
|
|
2342
|
-
await this.effectsEmit(
|
|
2203
|
+
await this.effectsEmit(_types.BaseSalesHookNames.onPaymentSyncEnd, {
|
|
2343
2204
|
ok: false,
|
|
2344
2205
|
error,
|
|
2345
2206
|
payments: this.store.order.getOrderPayments(),
|
|
@@ -2351,46 +2212,41 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2351
2212
|
throw error;
|
|
2352
2213
|
}
|
|
2353
2214
|
}
|
|
2215
|
+
|
|
2354
2216
|
/** 读取当前 BaseSales 订单上下文中的 Sales 协议支付项。 */
|
|
2355
2217
|
getOrderPayments() {
|
|
2356
|
-
if (!this.store.order)
|
|
2357
|
-
return [];
|
|
2218
|
+
if (!this.store.order) return [];
|
|
2358
2219
|
const payments = this.store.order.getOrderPayments();
|
|
2359
2220
|
return this.hydrateOrderPaymentNames(payments);
|
|
2360
2221
|
}
|
|
2222
|
+
|
|
2361
2223
|
/** 覆盖当前订单支付项,内部由 OrderModule 清洗为 Sales 协议字段。 */
|
|
2362
2224
|
setOrderPayments(payments) {
|
|
2363
|
-
if (!this.store.order)
|
|
2364
|
-
throw new Error("order 模块未初始化");
|
|
2225
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2365
2226
|
return this.store.order.setOrderPayments(payments);
|
|
2366
2227
|
}
|
|
2367
2228
|
getPaymentStatusForSync(payments) {
|
|
2368
2229
|
const order = this.store.order;
|
|
2369
|
-
if (!order)
|
|
2370
|
-
throw new Error("order 模块未初始化");
|
|
2230
|
+
if (!order) throw new Error('order 模块未初始化');
|
|
2371
2231
|
const completion = order.getPaymentCompletion(payments);
|
|
2372
|
-
return completion.isOrderFullyPaid ?
|
|
2232
|
+
return completion.isOrderFullyPaid ? 'paid' : 'partially_paid';
|
|
2373
2233
|
}
|
|
2374
2234
|
queueLatestAutoPaymentSync() {
|
|
2375
2235
|
this.queuedAutoPaymentSync = true;
|
|
2376
2236
|
this.scheduleQueuedAutoPaymentSyncFlush();
|
|
2377
2237
|
}
|
|
2378
2238
|
scheduleQueuedAutoPaymentSyncFlush(delay = 100) {
|
|
2379
|
-
if (!this.queuedAutoPaymentSync)
|
|
2380
|
-
|
|
2381
|
-
if (this.autoPaymentSyncTimer)
|
|
2382
|
-
return;
|
|
2239
|
+
if (!this.queuedAutoPaymentSync) return;
|
|
2240
|
+
if (this.autoPaymentSyncTimer) return;
|
|
2383
2241
|
this.autoPaymentSyncTimer = setTimeout(() => {
|
|
2384
2242
|
this.autoPaymentSyncTimer = null;
|
|
2385
2243
|
void this.flushQueuedAutoPaymentSync();
|
|
2386
2244
|
}, delay);
|
|
2387
2245
|
}
|
|
2388
2246
|
async flushQueuedAutoPaymentSync() {
|
|
2389
|
-
if (!this.store.order)
|
|
2390
|
-
|
|
2391
|
-
if (
|
|
2392
|
-
return;
|
|
2393
|
-
if (this.store.order.getOrderSyncState() === "submitting") {
|
|
2247
|
+
if (!this.store.order) return;
|
|
2248
|
+
if (!this.queuedAutoPaymentSync || this.autoPaymentSyncFlushing) return;
|
|
2249
|
+
if (this.store.order.getOrderSyncState() === 'submitting') {
|
|
2394
2250
|
this.scheduleQueuedAutoPaymentSyncFlush();
|
|
2395
2251
|
return;
|
|
2396
2252
|
}
|
|
@@ -2399,8 +2255,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2399
2255
|
while (this.queuedAutoPaymentSync) {
|
|
2400
2256
|
this.queuedAutoPaymentSync = false;
|
|
2401
2257
|
const payments = this.store.order.getOrderPayments();
|
|
2402
|
-
if (!payments.length)
|
|
2403
|
-
continue;
|
|
2258
|
+
if (!payments.length) continue;
|
|
2404
2259
|
await this.syncPaymentsToOrder({
|
|
2405
2260
|
payments,
|
|
2406
2261
|
paymentStatus: this.getPaymentStatusForSync(payments),
|
|
@@ -2409,7 +2264,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2409
2264
|
});
|
|
2410
2265
|
}
|
|
2411
2266
|
} catch (error) {
|
|
2412
|
-
this.logError(
|
|
2267
|
+
this.logError('queued auto sync payments failed', {
|
|
2413
2268
|
error: error instanceof Error ? error.message : String(error)
|
|
2414
2269
|
});
|
|
2415
2270
|
} finally {
|
|
@@ -2419,69 +2274,64 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2419
2274
|
}
|
|
2420
2275
|
}
|
|
2421
2276
|
}
|
|
2277
|
+
|
|
2422
2278
|
/**
|
|
2423
2279
|
* 同步兼容入口。无法等待 IoT 短号时,按调用当下的 device_id 或 LOCAL 生成。
|
|
2424
2280
|
*/
|
|
2425
2281
|
addOrderPayment(payment) {
|
|
2426
|
-
const hasPaymentNumber = String(
|
|
2427
|
-
|
|
2428
|
-
).trim() !== "";
|
|
2429
|
-
return this.addOrderPaymentWithDevicePrefix(
|
|
2430
|
-
payment,
|
|
2431
|
-
hasPaymentNumber ? "LOCAL" : this.getPaymentNumberDevicePrefixSync()
|
|
2432
|
-
);
|
|
2282
|
+
const hasPaymentNumber = String(payment.payment_number || '').trim() !== '';
|
|
2283
|
+
return this.addOrderPaymentWithDevicePrefix(payment, hasPaymentNumber ? 'LOCAL' : this.getPaymentNumberDevicePrefixSync());
|
|
2433
2284
|
}
|
|
2285
|
+
|
|
2434
2286
|
/**
|
|
2435
2287
|
* 创建新支付项时优先使用业务解决方案初始化阶段缓存的设备短号;
|
|
2436
2288
|
* 未缓存的通用 BaseSales 保持实时读取设备信息的兼容语义。
|
|
2437
2289
|
*/
|
|
2438
2290
|
async addOrderPaymentAsync(payment) {
|
|
2439
2291
|
const paymentRecord = payment;
|
|
2440
|
-
const hasPaymentNumber = String(paymentRecord.payment_number ||
|
|
2441
|
-
const devicePrefix = hasPaymentNumber ?
|
|
2292
|
+
const hasPaymentNumber = String(paymentRecord.payment_number || '').trim() !== '';
|
|
2293
|
+
const devicePrefix = hasPaymentNumber ? 'LOCAL' : await this.getPaymentNumberDevicePrefixAsync();
|
|
2442
2294
|
return this.addOrderPaymentWithDevicePrefix(payment, devicePrefix);
|
|
2443
2295
|
}
|
|
2444
2296
|
addOrderPaymentWithDevicePrefix(payment, devicePrefix) {
|
|
2445
|
-
|
|
2446
|
-
if (!this.store.order)
|
|
2447
|
-
throw new Error("order 模块未初始化");
|
|
2297
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2448
2298
|
const paymentRecord = payment;
|
|
2449
|
-
const paymentAmount = new
|
|
2299
|
+
const paymentAmount = new _decimal.default(paymentRecord.amount || 0);
|
|
2450
2300
|
if (paymentAmount.isZero()) {
|
|
2451
|
-
this.logWarning(
|
|
2301
|
+
this.logWarning('addOrderPayment: 支付金额为 0,跳过添加支付项', {
|
|
2452
2302
|
payment: paymentRecord
|
|
2453
2303
|
});
|
|
2454
2304
|
return this.store.order.getOrderPayments();
|
|
2455
2305
|
}
|
|
2456
|
-
const metadata = paymentRecord.metadata && typeof paymentRecord.metadata ===
|
|
2457
|
-
|
|
2458
|
-
|
|
2306
|
+
const metadata = paymentRecord.metadata && typeof paymentRecord.metadata === 'object' ? {
|
|
2307
|
+
...paymentRecord.metadata
|
|
2308
|
+
} : {};
|
|
2309
|
+
const shopWalletPassId = this.otherParams?.shop_wallet_pass_id;
|
|
2310
|
+
if (shopWalletPassId !== undefined && shopWalletPassId !== null) {
|
|
2459
2311
|
metadata.shop_wallet_pass_id = shopWalletPassId;
|
|
2460
2312
|
}
|
|
2461
|
-
const normalizedPaymentRecord = (0,
|
|
2462
|
-
|
|
2463
|
-
devicePrefix,
|
|
2464
|
-
import_utils.createUuidV4
|
|
2465
|
-
);
|
|
2466
|
-
const paymentTimestamp = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
2313
|
+
const normalizedPaymentRecord = (0, _paymentUtils.ensureOrderPaymentNumber)(paymentRecord, devicePrefix, _utils.createUuidV4);
|
|
2314
|
+
const paymentTimestamp = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
|
|
2467
2315
|
const paymentTime = paymentRecord.payment_time ?? paymentTimestamp;
|
|
2468
2316
|
const createdAt = paymentRecord.created_at ?? paymentTimestamp;
|
|
2469
|
-
const serviceCharge = paymentRecord.service_charge && typeof paymentRecord.service_charge ===
|
|
2470
|
-
const calculatedServiceFee = serviceCharge ? new
|
|
2317
|
+
const serviceCharge = paymentRecord.service_charge && typeof paymentRecord.service_charge === 'object' ? paymentRecord.service_charge : null;
|
|
2318
|
+
const calculatedServiceFee = serviceCharge ? new _decimal.default(paymentRecord.origin_amount ?? paymentRecord.amount ?? 0).times(serviceCharge.percentage || 0).plus(serviceCharge.amount || 0).toDecimalPlaces(2).toFixed(2) : undefined;
|
|
2471
2319
|
const payments = this.store.order.addOrderPayment({
|
|
2472
2320
|
...normalizedPaymentRecord,
|
|
2473
|
-
...calculatedServiceFee !==
|
|
2321
|
+
...(calculatedServiceFee !== undefined ? {
|
|
2322
|
+
service_fee: calculatedServiceFee
|
|
2323
|
+
} : {}),
|
|
2474
2324
|
metadata,
|
|
2475
2325
|
payment_time: paymentTime,
|
|
2476
2326
|
created_at: createdAt
|
|
2477
2327
|
});
|
|
2478
|
-
if (paymentRecord.status ===
|
|
2328
|
+
if (paymentRecord.status === 'payment_pending') {
|
|
2479
2329
|
return payments;
|
|
2480
2330
|
}
|
|
2481
2331
|
const amountSnapshot = this.store.order.getOrderAmountSnapshot();
|
|
2482
2332
|
const syncState = this.store.order.getOrderSyncState();
|
|
2483
2333
|
if (amountSnapshot) {
|
|
2484
|
-
if (syncState ===
|
|
2334
|
+
if (syncState === 'submitting') {
|
|
2485
2335
|
this.queueLatestAutoPaymentSync();
|
|
2486
2336
|
return payments;
|
|
2487
2337
|
}
|
|
@@ -2490,31 +2340,26 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2490
2340
|
paymentStatus: this.getPaymentStatusForSync(payments),
|
|
2491
2341
|
submitWhenPaid: true,
|
|
2492
2342
|
smallTicketDataFlag: 1
|
|
2493
|
-
}).catch(
|
|
2494
|
-
this.logError(
|
|
2343
|
+
}).catch(error => {
|
|
2344
|
+
this.logError('auto sync payments failed', {
|
|
2495
2345
|
error: error instanceof Error ? error.message : String(error)
|
|
2496
2346
|
});
|
|
2497
2347
|
});
|
|
2498
2348
|
}
|
|
2499
2349
|
return payments;
|
|
2500
2350
|
}
|
|
2351
|
+
|
|
2501
2352
|
/** 更新当前订单中的指定支付项。 */
|
|
2502
2353
|
async updateOrderPayment(paymentIdentity, updates, options = {}) {
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
const
|
|
2507
|
-
|
|
2508
|
-
this.store.order.getOrderPayments(),
|
|
2509
|
-
paymentIdentity,
|
|
2510
|
-
matchMode
|
|
2511
|
-
);
|
|
2512
|
-
const previousPayment = previousMatch == null ? void 0 : previousMatch.payment;
|
|
2513
|
-
if ((previousPayment == null ? void 0 : previousPayment.status) === "paid" && !options.applyUpdatesWhenPaid) {
|
|
2354
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2355
|
+
const matchMode = options.matchBy === 'compat' || options.matchBy === 'legacy' ? 'compat' : 'payment_number';
|
|
2356
|
+
const previousMatch = (0, _paymentUtils.resolveOrderPaymentIdentity)(this.store.order.getOrderPayments(), paymentIdentity, matchMode);
|
|
2357
|
+
const previousPayment = previousMatch?.payment;
|
|
2358
|
+
if (previousPayment?.status === 'paid' && !options.applyUpdatesWhenPaid) {
|
|
2514
2359
|
const currentPayments = this.store.order.getOrderPayments();
|
|
2515
|
-
let
|
|
2360
|
+
let syncResult;
|
|
2516
2361
|
if (options.submitWhenPaid && options.forceSubmitIfPaid) {
|
|
2517
|
-
|
|
2362
|
+
syncResult = await this.syncPaymentsToOrder({
|
|
2518
2363
|
payments: currentPayments,
|
|
2519
2364
|
paymentStatus: this.getPaymentStatusForSync(currentPayments),
|
|
2520
2365
|
submitWhenPaid: true,
|
|
@@ -2525,8 +2370,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2525
2370
|
updated: false,
|
|
2526
2371
|
payment: previousPayment,
|
|
2527
2372
|
payments: currentPayments,
|
|
2528
|
-
summary:
|
|
2529
|
-
...
|
|
2373
|
+
summary: this.store.order.getOrderAmountSnapshot()?.summary || null,
|
|
2374
|
+
...(syncResult !== undefined ? {
|
|
2375
|
+
syncResult
|
|
2376
|
+
} : {})
|
|
2530
2377
|
};
|
|
2531
2378
|
}
|
|
2532
2379
|
const result = await this.store.order.updateOrderPayment(paymentIdentity, updates, {
|
|
@@ -2539,18 +2386,15 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2539
2386
|
draftResult = await this.saveSalesOrderDraft();
|
|
2540
2387
|
} catch (error) {
|
|
2541
2388
|
draftError = error;
|
|
2542
|
-
this.logError(
|
|
2389
|
+
this.logError('updateOrderPayment: 保存支付草稿失败', {
|
|
2543
2390
|
paymentIdentity,
|
|
2544
2391
|
error: error instanceof Error ? error.message : String(error)
|
|
2545
2392
|
});
|
|
2546
|
-
if (!options.submitWhenPaid)
|
|
2547
|
-
throw error;
|
|
2393
|
+
if (!options.submitWhenPaid) throw error;
|
|
2548
2394
|
}
|
|
2549
2395
|
}
|
|
2550
|
-
const becamePaid =
|
|
2551
|
-
const shouldSubmit = Boolean(
|
|
2552
|
-
options.submitWhenPaid && ((_c = result.payment) == null ? void 0 : _c.status) === "paid" && (becamePaid || options.forceSubmitIfPaid)
|
|
2553
|
-
);
|
|
2396
|
+
const becamePaid = previousPayment?.status !== 'paid' && result.payment?.status === 'paid';
|
|
2397
|
+
const shouldSubmit = Boolean(options.submitWhenPaid && result.payment?.status === 'paid' && (becamePaid || options.forceSubmitIfPaid));
|
|
2554
2398
|
let syncResult;
|
|
2555
2399
|
if (shouldSubmit) {
|
|
2556
2400
|
syncResult = await this.syncPaymentsToOrder({
|
|
@@ -2562,60 +2406,62 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2562
2406
|
}
|
|
2563
2407
|
return {
|
|
2564
2408
|
...result,
|
|
2565
|
-
...draftResult !==
|
|
2566
|
-
|
|
2567
|
-
|
|
2409
|
+
...(draftResult !== undefined ? {
|
|
2410
|
+
draftResult
|
|
2411
|
+
} : {}),
|
|
2412
|
+
...(draftError !== undefined ? {
|
|
2413
|
+
draftError
|
|
2414
|
+
} : {}),
|
|
2415
|
+
...(syncResult !== undefined ? {
|
|
2416
|
+
syncResult
|
|
2417
|
+
} : {})
|
|
2568
2418
|
};
|
|
2569
2419
|
}
|
|
2420
|
+
|
|
2570
2421
|
/** 删除当前订单中的指定支付项。 */
|
|
2571
2422
|
deleteOrderPayment(paymentIdentity) {
|
|
2572
|
-
if (!this.store.order)
|
|
2573
|
-
throw new Error("order 模块未初始化");
|
|
2423
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2574
2424
|
return this.store.order.deleteOrderPayment(paymentIdentity);
|
|
2575
2425
|
}
|
|
2426
|
+
|
|
2576
2427
|
/** 覆盖 wallet pass 支付项,同时保留普通支付项。 */
|
|
2577
2428
|
updateVoucherOrderPayments(payments, options) {
|
|
2578
|
-
if (!this.store.order)
|
|
2579
|
-
throw new Error("order 模块未初始化");
|
|
2429
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2580
2430
|
return this.store.order.updateVoucherOrderPayments(payments, options);
|
|
2581
2431
|
}
|
|
2582
2432
|
async updateVoucherOrderPaymentsAsync(payments, options) {
|
|
2583
|
-
if (!this.store.order)
|
|
2584
|
-
throw new Error("order 模块未初始化");
|
|
2433
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2585
2434
|
return this.store.order.updateVoucherOrderPaymentsAsync(payments, options);
|
|
2586
2435
|
}
|
|
2587
2436
|
confirmPendingVoucherPayments() {
|
|
2588
|
-
if (!this.store.order)
|
|
2589
|
-
throw new Error("order 模块未初始化");
|
|
2437
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2590
2438
|
const payments = this.store.order.confirmPendingVoucherPayments();
|
|
2591
2439
|
if (this.store.payment) {
|
|
2592
2440
|
const committed = this.getCommittedWalletAssets();
|
|
2593
|
-
const state = this.store.payment.wallet.setCommittedWalletAssets(
|
|
2594
|
-
committed.ids,
|
|
2595
|
-
committed.assets
|
|
2596
|
-
);
|
|
2441
|
+
const state = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2597
2442
|
void this.publishWalletAssetsState(state);
|
|
2598
2443
|
}
|
|
2599
2444
|
return payments;
|
|
2600
2445
|
}
|
|
2601
2446
|
discardPendingVoucherPayments() {
|
|
2602
|
-
if (!this.store.order)
|
|
2603
|
-
throw new Error("order 模块未初始化");
|
|
2447
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2604
2448
|
return this.store.order.discardPendingVoucherPayments();
|
|
2605
2449
|
}
|
|
2606
2450
|
getWalletProductList() {
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
const
|
|
2451
|
+
const tempOrder = this.store.order?.getTempOrder();
|
|
2452
|
+
if (!tempOrder?.products?.length) return [];
|
|
2453
|
+
// 过滤出有 product_id的商品来,如果没有代表他是自定义商品,不需要参与 wallet
|
|
2454
|
+
// debugger
|
|
2455
|
+
// const products = tempOrder?.products?.filter(n => n.product_id)
|
|
2456
|
+
|
|
2457
|
+
const walletProducts = tempOrder?.products.map(product => {
|
|
2612
2458
|
const metadata = product.metadata || {};
|
|
2613
2459
|
const rawHolderId = product.holder_id ?? metadata.holder_id;
|
|
2614
2460
|
const holderIdValue = Array.isArray(rawHolderId) ? rawHolderId[0] : rawHolderId;
|
|
2615
|
-
const holder_id = Number.isInteger(Number(holderIdValue)) ? Number(holderIdValue) :
|
|
2461
|
+
const holder_id = Number.isInteger(Number(holderIdValue)) ? Number(holderIdValue) : undefined;
|
|
2616
2462
|
return {
|
|
2617
2463
|
product_id: product.product_id || 0,
|
|
2618
|
-
product_variant_id: String(product.product_variant_id ??
|
|
2464
|
+
product_variant_id: String(product.product_variant_id ?? ''),
|
|
2619
2465
|
quantity: product.num || 1,
|
|
2620
2466
|
is_price_include_tax: tempOrder.is_price_include_tax,
|
|
2621
2467
|
is_charge_tax: product.is_charge_tax ?? 0,
|
|
@@ -2631,7 +2477,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2631
2477
|
main_product_attached_bundle_surcharge_fee: metadata.main_product_attached_bundle_surcharge_fee,
|
|
2632
2478
|
surcharge_rounding_remainder: metadata.surcharge_rounding_remainder
|
|
2633
2479
|
},
|
|
2634
|
-
product_bundle: (product.product_bundle || []).map(
|
|
2480
|
+
product_bundle: (product.product_bundle || []).map(bundle => {
|
|
2635
2481
|
const bundleMetadata = bundle.metadata || {};
|
|
2636
2482
|
return {
|
|
2637
2483
|
is_price_include_tax: tempOrder.is_price_include_tax,
|
|
@@ -2658,14 +2504,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2658
2504
|
return walletProducts;
|
|
2659
2505
|
}
|
|
2660
2506
|
buildWalletInitBusinessData(params) {
|
|
2661
|
-
|
|
2662
|
-
const
|
|
2663
|
-
const
|
|
2664
|
-
|
|
2665
|
-
if (!tempOrder || !amount)
|
|
2666
|
-
return null;
|
|
2507
|
+
const snapshot = this.store.order?.getOrderSnapshot();
|
|
2508
|
+
const tempOrder = snapshot?.tempOrder;
|
|
2509
|
+
const amount = snapshot?.amount;
|
|
2510
|
+
if (!tempOrder || !amount) return null;
|
|
2667
2511
|
return {
|
|
2668
|
-
customer_id: tempOrder.customer_id ? Number(tempOrder.customer_id) :
|
|
2512
|
+
customer_id: tempOrder.customer_id ? Number(tempOrder.customer_id) : undefined,
|
|
2669
2513
|
holder: tempOrder.holder,
|
|
2670
2514
|
amountInfo: {
|
|
2671
2515
|
totalAmount: amount.totalAmount,
|
|
@@ -2674,17 +2518,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2674
2518
|
isDeposit: tempOrder.is_deposit
|
|
2675
2519
|
},
|
|
2676
2520
|
products: this.getWalletProductList(),
|
|
2677
|
-
order_wait_pay_amount:
|
|
2521
|
+
order_wait_pay_amount: params?.order_wait_pay_amount ?? Number(amount.amountGap || 0),
|
|
2678
2522
|
is_price_include_tax: tempOrder.is_price_include_tax ?? this.otherParams.is_price_include_tax ?? 1,
|
|
2679
|
-
...snapshot.identity.orderId ? {
|
|
2523
|
+
...(snapshot.identity.orderId ? {
|
|
2524
|
+
payment_order_id: String(snapshot.identity.orderId)
|
|
2525
|
+
} : {})
|
|
2680
2526
|
};
|
|
2681
2527
|
}
|
|
2682
2528
|
async initWalletData(params) {
|
|
2683
|
-
|
|
2684
|
-
if (!this.store.
|
|
2685
|
-
throw new Error("order 模块未初始化");
|
|
2686
|
-
if (!this.store.payment)
|
|
2687
|
-
throw new Error("payment 模块未初始化");
|
|
2529
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2530
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2688
2531
|
const snapshot = this.store.order.getOrderSnapshot();
|
|
2689
2532
|
const walletBusinessData = this.buildWalletInitBusinessData(params);
|
|
2690
2533
|
if (!walletBusinessData) {
|
|
@@ -2696,11 +2539,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2696
2539
|
products: []
|
|
2697
2540
|
};
|
|
2698
2541
|
}
|
|
2699
|
-
const result = await this.store.payment.wallet.initializeWalletDataFromBusinessAsync(
|
|
2700
|
-
walletBusinessData
|
|
2701
|
-
);
|
|
2542
|
+
const result = await this.store.payment.wallet.initializeWalletDataFromBusinessAsync(walletBusinessData);
|
|
2702
2543
|
await this.core.effects.emit(`${this.name}:onWalletDataInitialized`, {
|
|
2703
|
-
orderId:
|
|
2544
|
+
orderId: snapshot?.identity?.orderId,
|
|
2704
2545
|
customerId: walletBusinessData.customer_id,
|
|
2705
2546
|
walletBusinessData: {
|
|
2706
2547
|
customer_id: walletBusinessData.customer_id,
|
|
@@ -2712,26 +2553,22 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2712
2553
|
return result;
|
|
2713
2554
|
}
|
|
2714
2555
|
getCommittedWalletAssets() {
|
|
2715
|
-
|
|
2716
|
-
const
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
if (voucherId === void 0 || voucherId === null || voucherId === 0) {
|
|
2556
|
+
const payments = this.store.order?.getOrderPayments?.() || [];
|
|
2557
|
+
const committed = payments.filter(payment => {
|
|
2558
|
+
const voucherId = payment?.voucher_id;
|
|
2559
|
+
if (voucherId === undefined || voucherId === null || voucherId === 0) {
|
|
2720
2560
|
return false;
|
|
2721
2561
|
}
|
|
2722
|
-
return
|
|
2562
|
+
return payment?.status === 'paid' || payment?.isSynced === true || payment?.order_payment_id !== undefined && payment?.order_payment_id !== null && payment?.order_payment_id !== '';
|
|
2723
2563
|
});
|
|
2724
2564
|
return {
|
|
2725
|
-
ids: committed.map(
|
|
2726
|
-
assets: committed.map(
|
|
2727
|
-
|
|
2728
|
-
const fundRecord = (payment == null ? void 0 : payment.fund_record) || {};
|
|
2565
|
+
ids: committed.map(payment => payment.voucher_id),
|
|
2566
|
+
assets: committed.map(payment => {
|
|
2567
|
+
const fundRecord = payment?.fund_record || {};
|
|
2729
2568
|
const walletPassName = fundRecord.wallet_pass_name;
|
|
2730
|
-
const title = walletPassName && typeof walletPassName ===
|
|
2731
|
-
const code = String(
|
|
2732
|
-
const tag =
|
|
2733
|
-
([, paymentCode]) => paymentCode === code
|
|
2734
|
-
)) == null ? void 0 : _a2[0]) || fundRecord.tag;
|
|
2569
|
+
const title = walletPassName && typeof walletPassName === 'object' ? walletPassName.default || Object.values(walletPassName)[0] : walletPassName;
|
|
2570
|
+
const code = String(payment?.code || '').toUpperCase();
|
|
2571
|
+
const tag = Object.entries(WALLET_PAYMENT_CODE_BY_TAG).find(([, paymentCode]) => paymentCode === code)?.[0] || fundRecord.tag;
|
|
2735
2572
|
return {
|
|
2736
2573
|
id: payment.voucher_id,
|
|
2737
2574
|
voucher_id: payment.voucher_id,
|
|
@@ -2749,34 +2586,25 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2749
2586
|
};
|
|
2750
2587
|
}
|
|
2751
2588
|
async publishWalletAssetsState(state) {
|
|
2752
|
-
await this.effectsEmit(
|
|
2589
|
+
await this.effectsEmit(_types.BaseSalesHookNames.onWalletAssetsStateChanged, {
|
|
2753
2590
|
state
|
|
2754
2591
|
});
|
|
2755
2592
|
return state;
|
|
2756
2593
|
}
|
|
2757
2594
|
async syncSelectedWalletAssets(state) {
|
|
2758
2595
|
if (!this.store.order || !this.store.payment) {
|
|
2759
|
-
throw new Error(
|
|
2596
|
+
throw new Error('订单或支付模块未初始化');
|
|
2760
2597
|
}
|
|
2761
2598
|
let paymentMethods = this.getPaymentMethods();
|
|
2762
2599
|
if (!paymentMethods.length && state.selectedItems.length) {
|
|
2763
2600
|
paymentMethods = await this.getPaymentMethodsAsync();
|
|
2764
2601
|
}
|
|
2765
|
-
const methodByCode = new Map(
|
|
2766
|
-
|
|
2767
|
-
);
|
|
2768
|
-
const
|
|
2769
|
-
state.selectedItems
|
|
2770
|
-
);
|
|
2771
|
-
const selectedAssetById = new Map(
|
|
2772
|
-
state.selectedItems.map((asset) => [
|
|
2773
|
-
String(getSharedWalletAssetId(asset)),
|
|
2774
|
-
asset
|
|
2775
|
-
])
|
|
2776
|
-
);
|
|
2777
|
-
const voucherPayments = preparePayments.flatMap((item) => {
|
|
2602
|
+
const methodByCode = new Map(paymentMethods.map(method => [String(method.code || '').toUpperCase(), method]));
|
|
2603
|
+
const preparePayments = this.store.payment.wallet.formatWalletPassList2PreparePayments(state.selectedItems);
|
|
2604
|
+
const selectedAssetById = new Map(state.selectedItems.map(asset => [String(getSharedWalletAssetId(asset)), asset]));
|
|
2605
|
+
const voucherPayments = preparePayments.flatMap(item => {
|
|
2778
2606
|
const asset = selectedAssetById.get(String(item.voucher_id));
|
|
2779
|
-
const paymentCode = WALLET_PAYMENT_CODE_BY_TAG[String(item.tag ||
|
|
2607
|
+
const paymentCode = WALLET_PAYMENT_CODE_BY_TAG[String(item.tag || asset?.tag || '')] || String(item.tag || asset?.tag || '').toUpperCase();
|
|
2780
2608
|
const paymentMethod = methodByCode.get(paymentCode);
|
|
2781
2609
|
const formattedAmount = Number(item.amount);
|
|
2782
2610
|
const amount = Number.isFinite(formattedAmount) && formattedAmount > 0 ? formattedAmount : getSharedWalletAssetAmount(asset);
|
|
@@ -2788,105 +2616,105 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2788
2616
|
amount,
|
|
2789
2617
|
paymentMethod
|
|
2790
2618
|
});
|
|
2791
|
-
return [
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
}
|
|
2807
|
-
];
|
|
2619
|
+
return [{
|
|
2620
|
+
amount: amount.toFixed(2),
|
|
2621
|
+
code: paymentMethod.code,
|
|
2622
|
+
custom_payment_id: paymentMethod.id,
|
|
2623
|
+
name: paymentMethod.name,
|
|
2624
|
+
type: paymentMethod.type,
|
|
2625
|
+
voucher_id: item.voucher_id,
|
|
2626
|
+
wallet_pass_usage_unit: item.wallet_pass_usage_unit,
|
|
2627
|
+
wallet_pass_use_value: walletPassUseValue,
|
|
2628
|
+
fund_record: buildSharedWalletFundRecord({
|
|
2629
|
+
asset,
|
|
2630
|
+
amount,
|
|
2631
|
+
paymentMethod
|
|
2632
|
+
})
|
|
2633
|
+
}];
|
|
2808
2634
|
});
|
|
2809
2635
|
const payments = this.updateVoucherOrderPayments(voucherPayments, {
|
|
2810
|
-
status:
|
|
2636
|
+
status: 'payment_pending'
|
|
2637
|
+
});
|
|
2638
|
+
await this.store.order.recalculateSummary({
|
|
2639
|
+
createIfMissing: true
|
|
2811
2640
|
});
|
|
2812
|
-
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
2813
2641
|
return payments;
|
|
2814
2642
|
}
|
|
2643
|
+
|
|
2815
2644
|
/** 读取购物车与 Shared Checkout 共用的钱包资产状态。 */
|
|
2816
2645
|
getWalletAssetsState() {
|
|
2817
|
-
if (!this.store.payment)
|
|
2818
|
-
throw new Error("payment 模块未初始化");
|
|
2646
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2819
2647
|
return this.store.payment.wallet.getWalletAssetsState();
|
|
2820
2648
|
}
|
|
2649
|
+
|
|
2821
2650
|
/** 导出 Shared Checkout 跨运行时恢复所需的钱包状态与搜索缓存。 */
|
|
2822
2651
|
exportWalletAssetsSnapshot() {
|
|
2823
|
-
if (!this.store.payment)
|
|
2824
|
-
throw new Error("payment 模块未初始化");
|
|
2652
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2825
2653
|
return this.store.payment.wallet.exportWalletAssetsSnapshot();
|
|
2826
2654
|
}
|
|
2655
|
+
|
|
2827
2656
|
/** 配置仅影响 Wallet Assets,不改变 Promotion/Voucher 选择流程。 */
|
|
2828
2657
|
configureWalletAssetsBehavior(options) {
|
|
2829
|
-
if (!this.store.payment)
|
|
2830
|
-
throw new Error("payment 模块未初始化");
|
|
2658
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2831
2659
|
this.store.payment.wallet.configureWalletAssetsBehavior(options);
|
|
2832
2660
|
}
|
|
2661
|
+
|
|
2833
2662
|
/**
|
|
2834
2663
|
* 恢复 Shared Checkout 钱包快照,并把选择重新同步为订单 pending payment。
|
|
2835
2664
|
*/
|
|
2836
2665
|
async importWalletAssetsSnapshot(snapshot) {
|
|
2837
|
-
if (!this.store.payment)
|
|
2838
|
-
throw new Error("payment 模块未初始化");
|
|
2666
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2839
2667
|
const state = this.store.payment.wallet.importWalletAssetsSnapshot(snapshot);
|
|
2840
2668
|
await this.syncSelectedWalletAssets(state);
|
|
2841
2669
|
return this.publishWalletAssetsState(state);
|
|
2842
2670
|
}
|
|
2671
|
+
|
|
2843
2672
|
/**
|
|
2844
2673
|
* 基于当前订单快照刷新钱包资产。商品变化保留并重验选择;客户变化强制清空。
|
|
2845
2674
|
*/
|
|
2846
2675
|
async refreshWalletAssets(params) {
|
|
2847
|
-
if (!this.store.order)
|
|
2848
|
-
|
|
2849
|
-
if (!this.store.payment)
|
|
2850
|
-
throw new Error("payment 模块未初始化");
|
|
2676
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2677
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2851
2678
|
const refreshSequence = ++this.walletAssetsRefreshSequence;
|
|
2852
2679
|
const wallet = this.store.payment.wallet;
|
|
2853
2680
|
const businessData = this.buildWalletInitBusinessData(params);
|
|
2854
2681
|
if (!businessData) {
|
|
2855
2682
|
wallet.clearAllCache();
|
|
2856
2683
|
const emptyState = wallet.getWalletAssetsState();
|
|
2857
|
-
this.updateVoucherOrderPayments([], {
|
|
2684
|
+
this.updateVoucherOrderPayments([], {
|
|
2685
|
+
status: 'payment_pending'
|
|
2686
|
+
});
|
|
2858
2687
|
return this.publishWalletAssetsState(emptyState);
|
|
2859
2688
|
}
|
|
2860
2689
|
const previousState = wallet.getWalletAssetsState();
|
|
2861
|
-
const hasPreviousWalletContext = previousState.status !==
|
|
2862
|
-
const customerChanged = hasPreviousWalletContext && String(previousState.customerId ??
|
|
2690
|
+
const hasPreviousWalletContext = previousState.status !== 'idle' || previousState.items.length > 0 || previousState.selectedIds.length > 0 || previousState.customerId !== undefined;
|
|
2691
|
+
const customerChanged = hasPreviousWalletContext && String(previousState.customerId ?? '') !== String(businessData.customer_id ?? '');
|
|
2863
2692
|
if (customerChanged) {
|
|
2864
2693
|
const clearedState = wallet.clearWalletAssetSelection();
|
|
2865
|
-
this.updateVoucherOrderPayments([], {
|
|
2694
|
+
this.updateVoucherOrderPayments([], {
|
|
2695
|
+
status: 'payment_pending'
|
|
2696
|
+
});
|
|
2866
2697
|
await this.publishWalletAssetsState(clearedState);
|
|
2867
2698
|
}
|
|
2868
|
-
const refreshTask = wallet.refreshWalletAssetsFromBusinessAsync(
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
preserveSelection: (params == null ? void 0 : params.preserveSelection) !== false && !customerChanged
|
|
2872
|
-
}
|
|
2873
|
-
);
|
|
2699
|
+
const refreshTask = wallet.refreshWalletAssetsFromBusinessAsync(businessData, {
|
|
2700
|
+
preserveSelection: params?.preserveSelection !== false && !customerChanged
|
|
2701
|
+
});
|
|
2874
2702
|
await this.publishWalletAssetsState(wallet.getWalletAssetsState());
|
|
2875
2703
|
let state = await refreshTask;
|
|
2876
2704
|
if (refreshSequence !== this.walletAssetsRefreshSequence) {
|
|
2877
2705
|
return wallet.getWalletAssetsState();
|
|
2878
2706
|
}
|
|
2879
|
-
if (state.status !==
|
|
2707
|
+
if (state.status !== 'error') {
|
|
2880
2708
|
const committed = this.getCommittedWalletAssets();
|
|
2881
2709
|
state = wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2882
2710
|
}
|
|
2883
2711
|
await this.syncSelectedWalletAssets(state);
|
|
2884
2712
|
return this.publishWalletAssetsState(state);
|
|
2885
2713
|
}
|
|
2714
|
+
|
|
2886
2715
|
/** 选择或取消单张钱包资产,并立即同步 pending wallet payments。 */
|
|
2887
2716
|
async selectWalletAsset(params) {
|
|
2888
|
-
if (!this.store.payment)
|
|
2889
|
-
throw new Error("payment 模块未初始化");
|
|
2717
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2890
2718
|
const state = this.store.payment.wallet.selectWalletAsset(params.assetId, {
|
|
2891
2719
|
selected: params.selected,
|
|
2892
2720
|
source: params.source
|
|
@@ -2894,41 +2722,40 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2894
2722
|
await this.syncSelectedWalletAssets(state);
|
|
2895
2723
|
return this.publishWalletAssetsState(state);
|
|
2896
2724
|
}
|
|
2725
|
+
|
|
2897
2726
|
/** 更新已选钱包资产的手动使用金额,并同步 pending payment。 */
|
|
2898
2727
|
async updateWalletAssetAmount(params) {
|
|
2899
|
-
if (!this.store.payment)
|
|
2900
|
-
|
|
2901
|
-
const state = this.store.payment.wallet.updateWalletAssetAmount(
|
|
2902
|
-
params.assetId,
|
|
2903
|
-
params.amount
|
|
2904
|
-
);
|
|
2728
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2729
|
+
const state = this.store.payment.wallet.updateWalletAssetAmount(params.assetId, params.amount);
|
|
2905
2730
|
await this.syncSelectedWalletAssets(state);
|
|
2906
2731
|
return this.publishWalletAssetsState(state);
|
|
2907
2732
|
}
|
|
2733
|
+
|
|
2908
2734
|
/** 扫码精确查券;仅可用资产会被自动选中。 */
|
|
2909
2735
|
async scanWalletAsset(code) {
|
|
2910
|
-
if (!this.store.payment)
|
|
2911
|
-
throw new Error("payment 模块未初始化");
|
|
2736
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2912
2737
|
const wallet = this.store.payment.wallet;
|
|
2738
|
+
// 扫码可能早于后台 Wallet 刷新,搜索参数必须以当前订单为准。
|
|
2913
2739
|
const businessData = this.buildWalletInitBusinessData();
|
|
2914
2740
|
if (businessData) {
|
|
2915
2741
|
wallet.generateWalletParams(businessData);
|
|
2916
2742
|
}
|
|
2917
2743
|
const result = await wallet.scanWalletAssetAsync(code);
|
|
2918
|
-
if (result.type ===
|
|
2744
|
+
if (result.type === 'normalCode') {
|
|
2919
2745
|
await this.syncSelectedWalletAssets(result.state);
|
|
2920
2746
|
await this.publishWalletAssetsState(result.state);
|
|
2921
2747
|
}
|
|
2922
2748
|
return result;
|
|
2923
2749
|
}
|
|
2750
|
+
|
|
2924
2751
|
/** 清空全部未确认钱包选择,已支付钱包项由 Order 模块继续保留。 */
|
|
2925
2752
|
async clearWalletAssetSelection() {
|
|
2926
|
-
if (!this.store.payment)
|
|
2927
|
-
throw new Error("payment 模块未初始化");
|
|
2753
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2928
2754
|
const state = this.store.payment.wallet.clearWalletAssetSelection();
|
|
2929
2755
|
await this.syncSelectedWalletAssets(state);
|
|
2930
2756
|
return this.publishWalletAssetsState(state);
|
|
2931
2757
|
}
|
|
2758
|
+
|
|
2932
2759
|
/**
|
|
2933
2760
|
* 更新当前订单客户字段。
|
|
2934
2761
|
*
|
|
@@ -2936,46 +2763,50 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2936
2763
|
* 调用方通过 onCustomerChange 回调完成。
|
|
2937
2764
|
*/
|
|
2938
2765
|
updateOrderCustomer(customer) {
|
|
2939
|
-
if (!this.store.order)
|
|
2940
|
-
throw new Error("order 模块未初始化");
|
|
2766
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2941
2767
|
const result = this.store.order.updateTempOrderCustomer(customer);
|
|
2942
|
-
this.store.order.recalculateSummary({
|
|
2768
|
+
this.store.order.recalculateSummary({
|
|
2769
|
+
createIfMissing: true
|
|
2770
|
+
});
|
|
2943
2771
|
this.store.order.persistTempOrder();
|
|
2944
2772
|
return result;
|
|
2945
2773
|
}
|
|
2774
|
+
|
|
2946
2775
|
/** 获取可用支付方式列表,供 PaymentModal 渲染支付选项。 */
|
|
2947
2776
|
async getPaymentMethodsAsync() {
|
|
2777
|
+
// if (this.store.payment) {
|
|
2778
|
+
// return this.store.payment.getPayMethodListAsync();
|
|
2779
|
+
// }
|
|
2948
2780
|
try {
|
|
2949
|
-
const response = await this.request.get(
|
|
2781
|
+
const response = await this.request.get('/pay/custom-payment/all', {
|
|
2950
2782
|
filterPaymentMethods: true
|
|
2951
2783
|
}, {
|
|
2952
2784
|
osServer: true
|
|
2953
2785
|
});
|
|
2954
|
-
const paymentMethods =
|
|
2786
|
+
const paymentMethods = response?.data || [];
|
|
2955
2787
|
this.paymentMethodsCache = Array.isArray(paymentMethods) ? [...paymentMethods] : [];
|
|
2956
2788
|
return this.getPaymentMethods();
|
|
2957
2789
|
} catch (error) {
|
|
2958
|
-
this.logWarning(
|
|
2790
|
+
this.logWarning('getPaymentMethodsAsync: 获取支付方式列表失败,使用缓存列表', {
|
|
2959
2791
|
error: error instanceof Error ? error.message : String(error)
|
|
2960
2792
|
});
|
|
2961
2793
|
return this.getPaymentMethods();
|
|
2962
2794
|
}
|
|
2963
2795
|
}
|
|
2796
|
+
|
|
2964
2797
|
/** 同步读取初始化时缓存的支付方式列表。 */
|
|
2965
2798
|
getPaymentMethods() {
|
|
2966
2799
|
return [...this.paymentMethodsCache];
|
|
2967
2800
|
}
|
|
2968
2801
|
findCashPaymentMethod(paymentMethods) {
|
|
2969
|
-
return paymentMethods.find(
|
|
2970
|
-
const identifiers = [method
|
|
2971
|
-
|
|
2972
|
-
);
|
|
2973
|
-
return identifiers.includes("CASHMANUAL") && (method == null ? void 0 : method.enabled) !== false && (method == null ? void 0 : method.enable) !== false;
|
|
2802
|
+
return paymentMethods.find(method => {
|
|
2803
|
+
const identifiers = [method?.code, method?.type, method?.tag].map(value => String(value || '').toUpperCase());
|
|
2804
|
+
return identifiers.includes('CASHMANUAL') && method?.enabled !== false && method?.enable !== false;
|
|
2974
2805
|
});
|
|
2975
2806
|
}
|
|
2976
|
-
getPendingWalletPaymentAmount(payments =
|
|
2807
|
+
getPendingWalletPaymentAmount(payments = this.store.order?.getOrderPayments?.() || []) {
|
|
2977
2808
|
return payments.reduce((total, payment) => {
|
|
2978
|
-
if (
|
|
2809
|
+
if (payment?.status !== 'payment_pending' || payment?.voucher_id === undefined || Number(payment.voucher_id) === 0) {
|
|
2979
2810
|
return total;
|
|
2980
2811
|
}
|
|
2981
2812
|
try {
|
|
@@ -2983,26 +2814,22 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
2983
2814
|
} catch {
|
|
2984
2815
|
return total;
|
|
2985
2816
|
}
|
|
2986
|
-
}, new
|
|
2817
|
+
}, new _decimal.default(0));
|
|
2987
2818
|
}
|
|
2819
|
+
|
|
2988
2820
|
/** 读取现金 action 所需的支付方式、待付金额和快捷金额。 */
|
|
2989
2821
|
async getCashPaymentConfig() {
|
|
2990
|
-
|
|
2991
|
-
if (!this.store.payment)
|
|
2992
|
-
throw new Error("payment 模块未初始化");
|
|
2822
|
+
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2993
2823
|
let paymentMethods = this.getPaymentMethods();
|
|
2994
2824
|
let paymentMethod = this.findCashPaymentMethod(paymentMethods);
|
|
2995
2825
|
if (!paymentMethod) {
|
|
2996
2826
|
paymentMethods = await this.getPaymentMethodsAsync();
|
|
2997
2827
|
paymentMethod = this.findCashPaymentMethod(paymentMethods);
|
|
2998
2828
|
}
|
|
2999
|
-
const amountSnapshot =
|
|
2829
|
+
const amountSnapshot = this.store.order?.getOrderAmountSnapshot?.();
|
|
3000
2830
|
const pendingWalletAmount = this.getPendingWalletPaymentAmount();
|
|
3001
|
-
const amountDue =
|
|
3002
|
-
|
|
3003
|
-
0
|
|
3004
|
-
).toDecimalPlaces(2).toNumber();
|
|
3005
|
-
const currency = ((_e = (_d = (_c = this.store.order) == null ? void 0 : _c.getTempOrder) == null ? void 0 : _d.call(_c)) == null ? void 0 : _e.currency_code) || ((_f = this.otherParams) == null ? void 0 : _f.currency) || "USD";
|
|
2831
|
+
const amountDue = _decimal.default.max(new _decimal.default(amountSnapshot?.amountGap || 0).minus(pendingWalletAmount), 0).toDecimalPlaces(2).toNumber();
|
|
2832
|
+
const currency = this.store.order?.getTempOrder?.()?.currency_code || this.otherParams?.currency || 'USD';
|
|
3006
2833
|
const recommendedAmounts = amountDue > 0 ? this.store.payment.cash.getRecommendedAmount(amountDue, currency) : [];
|
|
3007
2834
|
return {
|
|
3008
2835
|
available: Boolean(paymentMethod && amountDue > 0),
|
|
@@ -3011,6 +2838,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3011
2838
|
recommendedAmounts
|
|
3012
2839
|
};
|
|
3013
2840
|
}
|
|
2841
|
+
|
|
3014
2842
|
/**
|
|
3015
2843
|
* 确认足额覆盖订单的 pending Wallet 支付并提交订单。
|
|
3016
2844
|
*
|
|
@@ -3018,23 +2846,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3018
2846
|
* 才同步 Wallet committed 状态。失败时恢复调用前 payments,允许用户重试。
|
|
3019
2847
|
*/
|
|
3020
2848
|
async confirmWalletPayment() {
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
throw new Error("order 模块未初始化");
|
|
3024
|
-
const beforePayments = (0, import_lodash_es.cloneDeep)(this.store.order.getOrderPayments());
|
|
2849
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2850
|
+
const beforePayments = (0, _lodashEs.cloneDeep)(this.store.order.getOrderPayments());
|
|
3025
2851
|
const pendingWalletAmount = this.getPendingWalletPaymentAmount(beforePayments);
|
|
3026
2852
|
if (pendingWalletAmount.lte(0)) {
|
|
3027
|
-
throw new Error(
|
|
2853
|
+
throw new Error('当前订单没有待确认的 Wallet 支付');
|
|
3028
2854
|
}
|
|
3029
|
-
const amountSnapshot =
|
|
3030
|
-
const effectiveAmountDue =
|
|
3031
|
-
new import_decimal.default((amountSnapshot == null ? void 0 : amountSnapshot.amountGap) || 0).minus(pendingWalletAmount),
|
|
3032
|
-
0
|
|
3033
|
-
);
|
|
2855
|
+
const amountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
2856
|
+
const effectiveAmountDue = _decimal.default.max(new _decimal.default(amountSnapshot?.amountGap || 0).minus(pendingWalletAmount), 0);
|
|
3034
2857
|
if (effectiveAmountDue.gt(0.01)) {
|
|
3035
|
-
throw new Error(
|
|
2858
|
+
throw new Error('Wallet 支付尚未覆盖全部待支付金额');
|
|
3036
2859
|
}
|
|
3037
|
-
const beforePaymentStatus =
|
|
2860
|
+
const beforePaymentStatus = this.store.order.getTempOrder()?.payment_status;
|
|
3038
2861
|
let submitResult;
|
|
3039
2862
|
try {
|
|
3040
2863
|
submitResult = await this.submitSalesOrder({
|
|
@@ -3042,80 +2865,74 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3042
2865
|
confirmPendingVoucherPayments: true
|
|
3043
2866
|
});
|
|
3044
2867
|
if (isRejectedSalesSubmitResult(submitResult)) {
|
|
3045
|
-
throw new Error(
|
|
3046
|
-
getSalesSubmitErrorMessage(submitResult, "Wallet 支付确认失败")
|
|
3047
|
-
);
|
|
2868
|
+
throw new Error(getSalesSubmitErrorMessage(submitResult, 'Wallet 支付确认失败'));
|
|
3048
2869
|
}
|
|
3049
2870
|
} catch (error) {
|
|
3050
2871
|
this.store.order.setOrderPayments(beforePayments);
|
|
3051
2872
|
const restoredTempOrder = this.store.order.getTempOrder();
|
|
3052
|
-
if (restoredTempOrder && beforePaymentStatus !==
|
|
2873
|
+
if (restoredTempOrder && beforePaymentStatus !== undefined) {
|
|
3053
2874
|
restoredTempOrder.payment_status = beforePaymentStatus;
|
|
3054
2875
|
this.store.order.persistTempOrder();
|
|
3055
2876
|
}
|
|
3056
|
-
await this.store.order.recalculateSummary({
|
|
2877
|
+
await this.store.order.recalculateSummary({
|
|
2878
|
+
createIfMissing: true
|
|
2879
|
+
});
|
|
3057
2880
|
throw error;
|
|
3058
2881
|
}
|
|
3059
2882
|
if (this.store.payment) {
|
|
3060
2883
|
try {
|
|
3061
2884
|
const committed = this.getCommittedWalletAssets();
|
|
3062
|
-
const walletState = this.store.payment.wallet.setCommittedWalletAssets(
|
|
3063
|
-
committed.ids,
|
|
3064
|
-
committed.assets
|
|
3065
|
-
);
|
|
2885
|
+
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3066
2886
|
await this.publishWalletAssetsState(walletState);
|
|
3067
2887
|
} catch (error) {
|
|
3068
|
-
this.logWarning(
|
|
2888
|
+
this.logWarning('confirmWalletPayment: Wallet committed 状态同步失败', {
|
|
3069
2889
|
error: error instanceof Error ? error.message : String(error)
|
|
3070
2890
|
});
|
|
3071
2891
|
}
|
|
3072
2892
|
}
|
|
3073
|
-
const latestAmountSnapshot =
|
|
2893
|
+
const latestAmountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
3074
2894
|
return {
|
|
3075
2895
|
submitResult,
|
|
3076
2896
|
payments: this.store.order.getOrderPayments(),
|
|
3077
|
-
isOrderFullyPaid: new
|
|
3078
|
-
(latestAmountSnapshot == null ? void 0 : latestAmountSnapshot.amountGap) || 0
|
|
3079
|
-
).lte(0)
|
|
2897
|
+
isOrderFullyPaid: new _decimal.default(latestAmountSnapshot?.amountGap || 0).lte(0)
|
|
3080
2898
|
};
|
|
3081
2899
|
}
|
|
2900
|
+
|
|
3082
2901
|
/**
|
|
3083
2902
|
* 购物车现金直付:写入现金记录并等待支付同步完成。
|
|
3084
2903
|
* 同步失败会恢复调用前 payments(包含 Wallet pending 状态)。
|
|
3085
2904
|
*/
|
|
3086
2905
|
async payCash(params) {
|
|
3087
|
-
|
|
3088
|
-
if (!this.store.order)
|
|
3089
|
-
throw new Error("order 模块未初始化");
|
|
2906
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3090
2907
|
const amount = Number(params.amount || 0);
|
|
3091
2908
|
if (!Number.isFinite(amount) || amount <= 0) {
|
|
3092
|
-
throw new Error(
|
|
2909
|
+
throw new Error('现金支付金额必须大于 0');
|
|
3093
2910
|
}
|
|
3094
2911
|
const config = await this.getCashPaymentConfig();
|
|
3095
2912
|
const paymentMethod = config.paymentMethod;
|
|
3096
|
-
if (!paymentMethod)
|
|
3097
|
-
|
|
3098
|
-
if (config.amountDue <= 0)
|
|
3099
|
-
throw new Error("当前订单没有待支付金额");
|
|
2913
|
+
if (!paymentMethod) throw new Error('未找到可用的 CASHMANUAL 支付方式');
|
|
2914
|
+
if (config.amountDue <= 0) throw new Error('当前订单没有待支付金额');
|
|
3100
2915
|
const roundingAmount = Number(params.roundingAmount || 0);
|
|
3101
|
-
const effectivePaymentAmount = new
|
|
3102
|
-
if (effectivePaymentAmount.gt(new
|
|
3103
|
-
throw new Error(
|
|
3104
|
-
}
|
|
3105
|
-
const beforePayments = (0,
|
|
3106
|
-
const beforePaymentStatus =
|
|
3107
|
-
const uniquePaymentNumber = (0,
|
|
3108
|
-
const paymentTimestamp = (0,
|
|
2916
|
+
const effectivePaymentAmount = new _decimal.default(amount).minus(roundingAmount);
|
|
2917
|
+
if (effectivePaymentAmount.gt(new _decimal.default(config.amountDue).plus(0.01))) {
|
|
2918
|
+
throw new Error('现金支付金额超过当前待支付金额');
|
|
2919
|
+
}
|
|
2920
|
+
const beforePayments = (0, _lodashEs.cloneDeep)(this.store.order.getOrderPayments());
|
|
2921
|
+
const beforePaymentStatus = this.store.order.getTempOrder()?.payment_status;
|
|
2922
|
+
const uniquePaymentNumber = (0, _utils.createUuidV4)();
|
|
2923
|
+
const paymentTimestamp = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
|
|
3109
2924
|
const actualPaidAmount = Number(params.actualPaidAmount ?? amount);
|
|
3110
2925
|
const changeAmount = Number(params.changeAmount || 0);
|
|
3111
|
-
const shopWalletPassId =
|
|
2926
|
+
const shopWalletPassId = this.otherParams?.shop_wallet_pass_id;
|
|
3112
2927
|
if (!Number.isFinite(actualPaidAmount) || actualPaidAmount + 0.01 < amount) {
|
|
3113
|
-
throw new Error(
|
|
2928
|
+
throw new Error('顾客实收现金不能小于支付金额');
|
|
3114
2929
|
}
|
|
3115
|
-
|
|
3116
|
-
module:
|
|
3117
|
-
key:
|
|
3118
|
-
data: {
|
|
2930
|
+
this.window?.interaction?.utils?.postMessageToApp?.({
|
|
2931
|
+
module: 'till',
|
|
2932
|
+
key: 'open_till',
|
|
2933
|
+
data: {
|
|
2934
|
+
type: 'cash'
|
|
2935
|
+
}
|
|
3119
2936
|
});
|
|
3120
2937
|
const payments = this.store.order.addOrderPayment({
|
|
3121
2938
|
amount: amount.toFixed(2),
|
|
@@ -3127,19 +2944,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3127
2944
|
rounding_amount: roundingAmount.toFixed(2),
|
|
3128
2945
|
metadata: {
|
|
3129
2946
|
unique_payment_number: uniquePaymentNumber,
|
|
3130
|
-
...shopWalletPassId !==
|
|
2947
|
+
...(shopWalletPassId !== undefined && shopWalletPassId !== null ? {
|
|
2948
|
+
shop_wallet_pass_id: shopWalletPassId
|
|
2949
|
+
} : {}),
|
|
3131
2950
|
actual_paid_amount: Number.isFinite(actualPaidAmount) ? actualPaidAmount : amount,
|
|
3132
2951
|
change_given_amount: Number.isFinite(changeAmount) ? changeAmount : 0
|
|
3133
2952
|
},
|
|
3134
2953
|
payment_time: paymentTimestamp,
|
|
3135
2954
|
created_at: paymentTimestamp
|
|
3136
2955
|
});
|
|
3137
|
-
const payment = payments.find(
|
|
3138
|
-
(item) => {
|
|
3139
|
-
var _a2;
|
|
3140
|
-
return ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.unique_payment_number) === uniquePaymentNumber;
|
|
3141
|
-
}
|
|
3142
|
-
);
|
|
2956
|
+
const payment = payments.find(item => item?.metadata?.unique_payment_number === uniquePaymentNumber);
|
|
3143
2957
|
try {
|
|
3144
2958
|
const syncResult = await this.syncPaymentsToOrder({
|
|
3145
2959
|
payments,
|
|
@@ -3148,35 +2962,33 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3148
2962
|
confirmPendingVoucherPayments: true
|
|
3149
2963
|
});
|
|
3150
2964
|
if (isRejectedSalesSubmitResult(syncResult.submitResult)) {
|
|
3151
|
-
throw new Error(
|
|
3152
|
-
getSalesSubmitErrorMessage(syncResult.submitResult, "订单提交失败")
|
|
3153
|
-
);
|
|
2965
|
+
throw new Error(getSalesSubmitErrorMessage(syncResult.submitResult, '订单提交失败'));
|
|
3154
2966
|
}
|
|
3155
2967
|
if (this.store.payment) {
|
|
3156
2968
|
const committed = this.getCommittedWalletAssets();
|
|
3157
|
-
const walletState = this.store.payment.wallet.setCommittedWalletAssets(
|
|
3158
|
-
committed.ids,
|
|
3159
|
-
committed.assets
|
|
3160
|
-
);
|
|
2969
|
+
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3161
2970
|
await this.publishWalletAssetsState(walletState);
|
|
3162
2971
|
}
|
|
3163
2972
|
return {
|
|
3164
2973
|
payment: payment || {},
|
|
3165
2974
|
payments: this.store.order.getOrderPayments(),
|
|
3166
|
-
syncResult,
|
|
2975
|
+
syncResult: syncResult,
|
|
3167
2976
|
isOrderFullyPaid: syncResult.isOrderFullyPaid
|
|
3168
2977
|
};
|
|
3169
2978
|
} catch (error) {
|
|
3170
2979
|
this.store.order.setOrderPayments(beforePayments);
|
|
3171
2980
|
const restoredTempOrder = this.store.order.getTempOrder();
|
|
3172
|
-
if (restoredTempOrder && beforePaymentStatus !==
|
|
2981
|
+
if (restoredTempOrder && beforePaymentStatus !== undefined) {
|
|
3173
2982
|
restoredTempOrder.payment_status = beforePaymentStatus;
|
|
3174
2983
|
this.store.order.persistTempOrder();
|
|
3175
2984
|
}
|
|
3176
|
-
await this.store.order.recalculateSummary({
|
|
2985
|
+
await this.store.order.recalculateSummary({
|
|
2986
|
+
createIfMissing: true
|
|
2987
|
+
});
|
|
3177
2988
|
throw error;
|
|
3178
2989
|
}
|
|
3179
2990
|
}
|
|
2991
|
+
|
|
3180
2992
|
/**
|
|
3181
2993
|
* 提交一次已由支付设备确认成功的非 Wallet 支付。
|
|
3182
2994
|
*
|
|
@@ -3185,19 +2997,17 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3185
2997
|
* 调用前的 payments 与 payment_status,便于 UI 安全解锁并重试。
|
|
3186
2998
|
*/
|
|
3187
2999
|
async commitPaymentMethodPayment(params) {
|
|
3188
|
-
|
|
3189
|
-
if (!this.store.order)
|
|
3190
|
-
throw new Error("order 模块未初始化");
|
|
3000
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3191
3001
|
const amount = Number(params.amount || 0);
|
|
3192
3002
|
if (!Number.isFinite(amount) || amount <= 0) {
|
|
3193
|
-
throw new Error(
|
|
3003
|
+
throw new Error('支付金额必须大于 0');
|
|
3194
3004
|
}
|
|
3195
3005
|
let paymentMethods = this.getPaymentMethods();
|
|
3196
3006
|
const findPaymentMethod = () => {
|
|
3197
|
-
const methodCode = String(params.paymentMethodCode ||
|
|
3198
|
-
return paymentMethods.find(
|
|
3199
|
-
const idMatched = params.paymentMethodId !==
|
|
3200
|
-
const codeMatched = Boolean(methodCode) && String(method.code ||
|
|
3007
|
+
const methodCode = String(params.paymentMethodCode || '').toUpperCase();
|
|
3008
|
+
return paymentMethods.find(method => {
|
|
3009
|
+
const idMatched = params.paymentMethodId !== undefined && String(method.id) === String(params.paymentMethodId);
|
|
3010
|
+
const codeMatched = Boolean(methodCode) && String(method.code || '').toUpperCase() === methodCode;
|
|
3201
3011
|
return (idMatched || codeMatched) && method.enabled !== false && method.enable !== false;
|
|
3202
3012
|
});
|
|
3203
3013
|
};
|
|
@@ -3207,54 +3017,49 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3207
3017
|
paymentMethod = findPaymentMethod();
|
|
3208
3018
|
}
|
|
3209
3019
|
if (!paymentMethod) {
|
|
3210
|
-
throw new Error(
|
|
3211
|
-
`未找到可用的支付方式:${params.paymentMethodCode || params.paymentMethodId || ""}`
|
|
3212
|
-
);
|
|
3020
|
+
throw new Error(`未找到可用的支付方式:${params.paymentMethodCode || params.paymentMethodId || ''}`);
|
|
3213
3021
|
}
|
|
3214
|
-
const amountSnapshot =
|
|
3022
|
+
const amountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
3215
3023
|
const pendingWalletAmount = this.getPendingWalletPaymentAmount();
|
|
3216
|
-
const amountDue =
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
}
|
|
3225
|
-
const beforePayments = (0, import_lodash_es.cloneDeep)(this.store.order.getOrderPayments());
|
|
3226
|
-
const beforePaymentStatus = (_c = this.store.order.getTempOrder()) == null ? void 0 : _c.payment_status;
|
|
3227
|
-
const paymentTimestamp = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
3024
|
+
const amountDue = _decimal.default.max(new _decimal.default(amountSnapshot?.amountGap || 0).minus(pendingWalletAmount), 0);
|
|
3025
|
+
if (amountDue.lte(0)) throw new Error('当前订单没有待支付金额');
|
|
3026
|
+
if (new _decimal.default(amount).gt(amountDue.plus(0.01))) {
|
|
3027
|
+
throw new Error('支付金额超过当前待支付金额');
|
|
3028
|
+
}
|
|
3029
|
+
const beforePayments = (0, _lodashEs.cloneDeep)(this.store.order.getOrderPayments());
|
|
3030
|
+
const beforePaymentStatus = this.store.order.getTempOrder()?.payment_status;
|
|
3031
|
+
const paymentTimestamp = (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss');
|
|
3228
3032
|
const metadata = {
|
|
3229
|
-
...params.metadata || {},
|
|
3230
|
-
unique_payment_number:
|
|
3033
|
+
...(params.metadata || {}),
|
|
3034
|
+
unique_payment_number: params.metadata?.unique_payment_number || (0, _utils.createUuidV4)()
|
|
3231
3035
|
};
|
|
3232
3036
|
const serviceCharge = params.serviceCharge ? {
|
|
3233
3037
|
amount: String(params.serviceCharge.amount || 0),
|
|
3234
3038
|
percentage: String(params.serviceCharge.percentage || 0)
|
|
3235
|
-
} :
|
|
3236
|
-
const serviceFee = serviceCharge ? new
|
|
3039
|
+
} : undefined;
|
|
3040
|
+
const serviceFee = serviceCharge ? new _decimal.default(params.originAmount ?? amount).times(serviceCharge.percentage || 0).plus(serviceCharge.amount || 0).toDecimalPlaces(2).toFixed(2) : undefined;
|
|
3237
3041
|
const payments = this.store.order.addOrderPayment({
|
|
3238
|
-
...params.paymentData || {},
|
|
3042
|
+
...(params.paymentData || {}),
|
|
3239
3043
|
amount: amount.toFixed(2),
|
|
3240
|
-
...params.originAmount !==
|
|
3044
|
+
...(params.originAmount !== undefined ? {
|
|
3045
|
+
origin_amount: Number(params.originAmount).toFixed(2)
|
|
3046
|
+
} : {}),
|
|
3241
3047
|
code: paymentMethod.code,
|
|
3242
3048
|
custom_payment_id: paymentMethod.id,
|
|
3243
3049
|
name: paymentMethod.name,
|
|
3244
3050
|
custom_payment_type: paymentMethod.type,
|
|
3245
3051
|
voucher_id: 0,
|
|
3246
|
-
...serviceCharge ? {
|
|
3247
|
-
|
|
3052
|
+
...(serviceCharge ? {
|
|
3053
|
+
service_charge: serviceCharge
|
|
3054
|
+
} : {}),
|
|
3055
|
+
...(serviceFee !== undefined ? {
|
|
3056
|
+
service_fee: serviceFee
|
|
3057
|
+
} : {}),
|
|
3248
3058
|
metadata,
|
|
3249
3059
|
payment_time: paymentTimestamp,
|
|
3250
3060
|
created_at: paymentTimestamp
|
|
3251
3061
|
});
|
|
3252
|
-
const payment = payments.find(
|
|
3253
|
-
(item) => {
|
|
3254
|
-
var _a2;
|
|
3255
|
-
return ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.unique_payment_number) === metadata.unique_payment_number;
|
|
3256
|
-
}
|
|
3257
|
-
);
|
|
3062
|
+
const payment = payments.find(item => item?.metadata?.unique_payment_number === metadata.unique_payment_number);
|
|
3258
3063
|
try {
|
|
3259
3064
|
const syncResult = await this.syncPaymentsToOrder({
|
|
3260
3065
|
payments,
|
|
@@ -3263,35 +3068,33 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3263
3068
|
confirmPendingVoucherPayments: true
|
|
3264
3069
|
});
|
|
3265
3070
|
if (isRejectedSalesSubmitResult(syncResult.submitResult)) {
|
|
3266
|
-
throw new Error(
|
|
3267
|
-
getSalesSubmitErrorMessage(syncResult.submitResult, "订单提交失败")
|
|
3268
|
-
);
|
|
3071
|
+
throw new Error(getSalesSubmitErrorMessage(syncResult.submitResult, '订单提交失败'));
|
|
3269
3072
|
}
|
|
3270
3073
|
if (this.store.payment) {
|
|
3271
3074
|
const committed = this.getCommittedWalletAssets();
|
|
3272
|
-
const walletState = this.store.payment.wallet.setCommittedWalletAssets(
|
|
3273
|
-
committed.ids,
|
|
3274
|
-
committed.assets
|
|
3275
|
-
);
|
|
3075
|
+
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3276
3076
|
await this.publishWalletAssetsState(walletState);
|
|
3277
3077
|
}
|
|
3278
3078
|
return {
|
|
3279
3079
|
payment: payment || {},
|
|
3280
3080
|
payments: this.store.order.getOrderPayments(),
|
|
3281
|
-
syncResult,
|
|
3081
|
+
syncResult: syncResult,
|
|
3282
3082
|
isOrderFullyPaid: syncResult.isOrderFullyPaid
|
|
3283
3083
|
};
|
|
3284
3084
|
} catch (error) {
|
|
3285
3085
|
this.store.order.setOrderPayments(beforePayments);
|
|
3286
3086
|
const restoredTempOrder = this.store.order.getTempOrder();
|
|
3287
|
-
if (restoredTempOrder && beforePaymentStatus !==
|
|
3087
|
+
if (restoredTempOrder && beforePaymentStatus !== undefined) {
|
|
3288
3088
|
restoredTempOrder.payment_status = beforePaymentStatus;
|
|
3289
3089
|
this.store.order.persistTempOrder();
|
|
3290
3090
|
}
|
|
3291
|
-
await this.store.order.recalculateSummary({
|
|
3091
|
+
await this.store.order.recalculateSummary({
|
|
3092
|
+
createIfMissing: true
|
|
3093
|
+
});
|
|
3292
3094
|
throw error;
|
|
3293
3095
|
}
|
|
3294
3096
|
}
|
|
3097
|
+
|
|
3295
3098
|
/**
|
|
3296
3099
|
* 按当前店铺的现金舍入配置计算金额,供现金支付 UI 使用。
|
|
3297
3100
|
*
|
|
@@ -3299,27 +3102,21 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3299
3102
|
* otherParams.order_rounding_setting,金额算法统一由 PaymentModule 维护。
|
|
3300
3103
|
*/
|
|
3301
3104
|
async roundAmount(params) {
|
|
3302
|
-
var _a, _b, _c;
|
|
3303
3105
|
const amount = params.amount;
|
|
3304
|
-
const cashManualPayment = this.paymentMethodsCache.find(
|
|
3305
|
-
|
|
3306
|
-
);
|
|
3307
|
-
if (!((_a = cashManualPayment == null ? void 0 : cashManualPayment.metadata) == null ? void 0 : _a.order_rounding_switch)) {
|
|
3106
|
+
const cashManualPayment = this.paymentMethodsCache.find(paymentMethod => paymentMethod.code === 'CASHMANUAL');
|
|
3107
|
+
if (!cashManualPayment?.metadata?.order_rounding_switch) {
|
|
3308
3108
|
return {
|
|
3309
3109
|
originalAmount: amount.toString(),
|
|
3310
3110
|
roundedAmount: amount.toString(),
|
|
3311
|
-
roundingDifference:
|
|
3111
|
+
roundingDifference: '0.00'
|
|
3312
3112
|
};
|
|
3313
3113
|
}
|
|
3314
3114
|
if (!this.payment) {
|
|
3315
|
-
throw new Error(
|
|
3115
|
+
throw new Error('payment 模块未初始化');
|
|
3316
3116
|
}
|
|
3317
|
-
return this.payment.roundAmountAsync(
|
|
3318
|
-
amount,
|
|
3319
|
-
(_b = this.otherParams.order_rounding_setting) == null ? void 0 : _b.interval,
|
|
3320
|
-
(_c = this.otherParams.order_rounding_setting) == null ? void 0 : _c.type
|
|
3321
|
-
);
|
|
3117
|
+
return this.payment.roundAmountAsync(amount, this.otherParams.order_rounding_setting?.interval, this.otherParams.order_rounding_setting?.type);
|
|
3322
3118
|
}
|
|
3119
|
+
|
|
3323
3120
|
/**
|
|
3324
3121
|
* 发送支付链接。
|
|
3325
3122
|
*
|
|
@@ -3327,17 +3124,15 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3327
3124
|
* 只有成功拿到远端 order_id 后才调用 OrderModule 发送邮件。
|
|
3328
3125
|
*/
|
|
3329
3126
|
async sendCustomerPayLink(params) {
|
|
3330
|
-
|
|
3331
|
-
if (!this.store.order)
|
|
3332
|
-
throw new Error("order 模块未初始化");
|
|
3127
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3333
3128
|
let orderIds = params.order_ids || params.orderIds || [];
|
|
3334
3129
|
if (!orderIds.length || params.submitBeforeSend) {
|
|
3335
3130
|
const submitResult = await this.submitSalesOrder({
|
|
3336
3131
|
smallTicketDataFlag: 1
|
|
3337
3132
|
});
|
|
3338
|
-
const orderId =
|
|
3133
|
+
const orderId = submitResult?.data?.order_id ?? submitResult?.order_id ?? submitResult?.data?.id ?? submitResult?.id;
|
|
3339
3134
|
if (!orderId) {
|
|
3340
|
-
throw new Error(
|
|
3135
|
+
throw new Error('本地订单提交云端失败,无法发送支付链接');
|
|
3341
3136
|
}
|
|
3342
3137
|
orderIds = [orderId];
|
|
3343
3138
|
}
|
|
@@ -3348,7 +3143,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3348
3143
|
});
|
|
3349
3144
|
}
|
|
3350
3145
|
transformBaseProductToOrderProduct(params) {
|
|
3351
|
-
return (0,
|
|
3146
|
+
return (0, _transformBaseProductToOrderProduct.transformBaseProductToOrderProduct)(params);
|
|
3352
3147
|
}
|
|
3353
3148
|
async calculateProductBookingPrice(params) {
|
|
3354
3149
|
const quotation = this.store.quotation;
|
|
@@ -3361,36 +3156,34 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3361
3156
|
customer_id: customerId,
|
|
3362
3157
|
channel: params.channel
|
|
3363
3158
|
});
|
|
3364
|
-
return (0,
|
|
3159
|
+
return (0, _quotationPrice.calculateBaseSalesProductBookingPrice)({
|
|
3365
3160
|
...params,
|
|
3366
3161
|
product,
|
|
3367
|
-
fallback_price: authoritativeProduct ?
|
|
3162
|
+
fallback_price: authoritativeProduct ? undefined : params.fallback_price,
|
|
3368
3163
|
customer_id: customerId,
|
|
3369
|
-
quotation: authoritativeProduct && this.preferAuthoritativeProductQueryPrice() ?
|
|
3164
|
+
quotation: authoritativeProduct && this.preferAuthoritativeProductQueryPrice() ? undefined : quotation
|
|
3370
3165
|
});
|
|
3371
3166
|
}
|
|
3372
3167
|
getQuotationCustomerScopeInfo() {
|
|
3373
3168
|
const quotation = this.store.quotation;
|
|
3374
|
-
if (quotation && typeof quotation.getQuotationCustomerScopeInfo ===
|
|
3169
|
+
if (quotation && typeof quotation.getQuotationCustomerScopeInfo === 'function') {
|
|
3375
3170
|
return quotation.getQuotationCustomerScopeInfo();
|
|
3376
3171
|
}
|
|
3377
|
-
const list = typeof
|
|
3378
|
-
const customerById =
|
|
3379
|
-
const quotationScopes = (Array.isArray(list) ? list : []).filter(
|
|
3380
|
-
const localSeen =
|
|
3381
|
-
const customers = item.customer.filter(
|
|
3382
|
-
const customerId = this.normalizePriceContextCustomerId(customer
|
|
3383
|
-
if (!customerId || localSeen.has(customerId))
|
|
3384
|
-
return false;
|
|
3172
|
+
const list = typeof quotation?.getQuotationList === 'function' ? quotation.getQuotationList() : [];
|
|
3173
|
+
const customerById = new Map();
|
|
3174
|
+
const quotationScopes = (Array.isArray(list) ? list : []).filter(item => Array.isArray(item?.customer) && item.customer.length > 0).map(item => {
|
|
3175
|
+
const localSeen = new Set();
|
|
3176
|
+
const customers = item.customer.filter(customer => {
|
|
3177
|
+
const customerId = this.normalizePriceContextCustomerId(customer?.id);
|
|
3178
|
+
if (!customerId || localSeen.has(customerId)) return false;
|
|
3385
3179
|
localSeen.add(customerId);
|
|
3386
|
-
if (!customerById.has(customerId))
|
|
3387
|
-
customerById.set(customerId, customer);
|
|
3180
|
+
if (!customerById.has(customerId)) customerById.set(customerId, customer);
|
|
3388
3181
|
return true;
|
|
3389
3182
|
});
|
|
3390
3183
|
return {
|
|
3391
3184
|
quotationId: item.id,
|
|
3392
3185
|
quotationName: item.name,
|
|
3393
|
-
customerIds: customers.map(
|
|
3186
|
+
customerIds: customers.map(customer => String(customer.id)),
|
|
3394
3187
|
customers
|
|
3395
3188
|
};
|
|
3396
3189
|
});
|
|
@@ -3404,9 +3197,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3404
3197
|
};
|
|
3405
3198
|
}
|
|
3406
3199
|
hasSmartPricingStrategies() {
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
if (!evaluator || typeof evaluator.getStrategyConfigs !== "function") {
|
|
3200
|
+
const evaluator = this.core?.context?.dataVariantEvaluator;
|
|
3201
|
+
if (!evaluator || typeof evaluator.getStrategyConfigs !== 'function') {
|
|
3410
3202
|
return false;
|
|
3411
3203
|
}
|
|
3412
3204
|
const configs = evaluator.getStrategyConfigs();
|
|
@@ -3414,7 +3206,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3414
3206
|
}
|
|
3415
3207
|
shouldRecalculateProductBookingPricesForContextChange(params) {
|
|
3416
3208
|
const scopeInfo = this.getQuotationCustomerScopeInfo();
|
|
3417
|
-
const scopedCustomerIds = new Set(scopeInfo.customerIds.map(
|
|
3209
|
+
const scopedCustomerIds = new Set(scopeInfo.customerIds.map(id => String(id)));
|
|
3418
3210
|
const previousCustomerId = this.normalizePriceContextCustomerId(params.previousCustomerId);
|
|
3419
3211
|
const nextCustomerId = this.normalizePriceContextCustomerId(params.nextCustomerId);
|
|
3420
3212
|
if (this.hasSmartPricingStrategies()) {
|
|
@@ -3435,78 +3227,73 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3435
3227
|
return shouldRecalculate;
|
|
3436
3228
|
}
|
|
3437
3229
|
async calculateProductBookingPrices(paramsList) {
|
|
3438
|
-
|
|
3439
|
-
if (!paramsList.length)
|
|
3440
|
-
return [];
|
|
3230
|
+
if (!paramsList.length) return [];
|
|
3441
3231
|
const quotation = this.store.quotation;
|
|
3442
|
-
const customerId =
|
|
3232
|
+
const customerId = paramsList[0]?.customer_id ?? this.getCurrentOrderCustomerId();
|
|
3443
3233
|
await this.prepareProductPriceQueryContext(customerId);
|
|
3444
|
-
const productMapsByGroup =
|
|
3445
|
-
const groups =
|
|
3446
|
-
paramsList.forEach(
|
|
3447
|
-
var _a2;
|
|
3234
|
+
const productMapsByGroup = new Map();
|
|
3235
|
+
const groups = new Map();
|
|
3236
|
+
paramsList.forEach(params => {
|
|
3448
3237
|
const product = params.product || {};
|
|
3449
3238
|
const productId = this.getPriceQueryProductId(product);
|
|
3450
|
-
if (productId === null)
|
|
3451
|
-
return;
|
|
3239
|
+
if (productId === null) return;
|
|
3452
3240
|
const schedule = this.getPriceQuerySchedule(params);
|
|
3453
|
-
const channel = params.channel ||
|
|
3454
|
-
const groupKey = [
|
|
3455
|
-
schedule.schedule_date,
|
|
3456
|
-
schedule.schedule_datetime,
|
|
3457
|
-
channel || ""
|
|
3458
|
-
].join("|");
|
|
3241
|
+
const channel = params.channel || this.otherParams?.channel;
|
|
3242
|
+
const groupKey = [schedule.schedule_date, schedule.schedule_datetime, channel || ''].join('|');
|
|
3459
3243
|
const group = groups.get(groupKey) || {
|
|
3460
|
-
ids:
|
|
3244
|
+
ids: new Set(),
|
|
3461
3245
|
schedule,
|
|
3462
3246
|
channel
|
|
3463
3247
|
};
|
|
3464
3248
|
group.ids.add(productId);
|
|
3465
3249
|
groups.set(groupKey, group);
|
|
3466
3250
|
});
|
|
3467
|
-
await Promise.all(
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
})
|
|
3477
|
-
);
|
|
3251
|
+
await Promise.all(Array.from(groups.entries()).map(async ([groupKey, group]) => {
|
|
3252
|
+
const productsById = await this.loadProductsForPriceQuery({
|
|
3253
|
+
ids: Array.from(group.ids),
|
|
3254
|
+
schedule: group.schedule,
|
|
3255
|
+
customerId,
|
|
3256
|
+
channel: group.channel
|
|
3257
|
+
});
|
|
3258
|
+
productMapsByGroup.set(groupKey, productsById);
|
|
3259
|
+
}));
|
|
3478
3260
|
await this.loadQuotationForPriceQuery({
|
|
3479
3261
|
quotation,
|
|
3480
3262
|
customer_id: customerId,
|
|
3481
|
-
channel:
|
|
3263
|
+
channel: paramsList[0]?.channel
|
|
3482
3264
|
});
|
|
3483
|
-
return paramsList.map(
|
|
3484
|
-
var _a2, _b2;
|
|
3265
|
+
return paramsList.map(params => {
|
|
3485
3266
|
const productInput = params.product || {};
|
|
3486
3267
|
const productId = this.getPriceQueryProductId(productInput);
|
|
3487
3268
|
const schedule = this.getPriceQuerySchedule(params);
|
|
3488
|
-
const channel = params.channel ||
|
|
3489
|
-
const groupKey = [
|
|
3490
|
-
|
|
3491
|
-
schedule.schedule_datetime,
|
|
3492
|
-
channel || ""
|
|
3493
|
-
].join("|");
|
|
3494
|
-
const authoritativeProduct = productId === null ? null : ((_b2 = productMapsByGroup.get(groupKey)) == null ? void 0 : _b2.get(productId)) || null;
|
|
3269
|
+
const channel = params.channel || this.otherParams?.channel;
|
|
3270
|
+
const groupKey = [schedule.schedule_date, schedule.schedule_datetime, channel || ''].join('|');
|
|
3271
|
+
const authoritativeProduct = productId === null ? null : productMapsByGroup.get(groupKey)?.get(productId) || null;
|
|
3495
3272
|
const product = this.mergeProductForPriceQuery(productInput, authoritativeProduct);
|
|
3496
|
-
return (0,
|
|
3273
|
+
return (0, _quotationPrice.calculateBaseSalesProductBookingPrice)({
|
|
3497
3274
|
...params,
|
|
3498
3275
|
product,
|
|
3499
|
-
fallback_price: authoritativeProduct ?
|
|
3276
|
+
fallback_price: authoritativeProduct ? undefined : params.fallback_price,
|
|
3500
3277
|
customer_id: customerId,
|
|
3501
|
-
quotation: authoritativeProduct && this.preferAuthoritativeProductQueryPrice() ?
|
|
3278
|
+
quotation: authoritativeProduct && this.preferAuthoritativeProductQueryPrice() ? undefined : quotation
|
|
3502
3279
|
});
|
|
3503
3280
|
});
|
|
3504
3281
|
}
|
|
3505
3282
|
async addProductToOrder(product, booking, options) {
|
|
3506
3283
|
try {
|
|
3507
|
-
if (!this.store.order)
|
|
3508
|
-
throw new Error("order 模块未初始化");
|
|
3284
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3509
3285
|
const products = await this.store.order.addProductToOrder(product, booking, options);
|
|
3286
|
+
// // 需要叠加
|
|
3287
|
+
// if (this.hooks.onAddProductOverlay) {
|
|
3288
|
+
// const res = this.hooks.onAddProductOverlay(是否叠加, product)
|
|
3289
|
+
// if (!res) {
|
|
3290
|
+
// 单独添加商品
|
|
3291
|
+
// } else {
|
|
3292
|
+
// 叠加
|
|
3293
|
+
// }
|
|
3294
|
+
// } else {
|
|
3295
|
+
// 叠加
|
|
3296
|
+
// }
|
|
3510
3297
|
return products;
|
|
3511
3298
|
} catch (error) {
|
|
3512
3299
|
throw error;
|
|
@@ -3514,8 +3301,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3514
3301
|
}
|
|
3515
3302
|
async updateOrderProduct(params) {
|
|
3516
3303
|
try {
|
|
3517
|
-
if (!this.store.order)
|
|
3518
|
-
throw new Error("order 模块未初始化");
|
|
3304
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3519
3305
|
const products = await this.store.order.updateOrderProduct(params);
|
|
3520
3306
|
return products;
|
|
3521
3307
|
} catch (error) {
|
|
@@ -3524,8 +3310,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3524
3310
|
}
|
|
3525
3311
|
async updateOrderProducts(paramsList) {
|
|
3526
3312
|
try {
|
|
3527
|
-
if (!this.store.order)
|
|
3528
|
-
throw new Error("order 模块未初始化");
|
|
3313
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3529
3314
|
const products = await this.store.order.updateOrderProducts(paramsList);
|
|
3530
3315
|
return products;
|
|
3531
3316
|
} catch (error) {
|
|
@@ -3534,8 +3319,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3534
3319
|
}
|
|
3535
3320
|
async updateOrderProductQuantity(params) {
|
|
3536
3321
|
try {
|
|
3537
|
-
if (!this.store.order)
|
|
3538
|
-
throw new Error("order 模块未初始化");
|
|
3322
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3539
3323
|
const products = await this.store.order.updateOrderProductQuantity(params);
|
|
3540
3324
|
return products;
|
|
3541
3325
|
} catch (error) {
|
|
@@ -3544,13 +3328,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3544
3328
|
}
|
|
3545
3329
|
updateOrderBooking(params) {
|
|
3546
3330
|
try {
|
|
3547
|
-
if (!this.store.order)
|
|
3548
|
-
throw new Error("order 模块未初始化");
|
|
3331
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3549
3332
|
return this.store.order.updateOrderBooking(params);
|
|
3550
3333
|
} catch (error) {
|
|
3551
3334
|
throw error;
|
|
3552
3335
|
}
|
|
3553
3336
|
}
|
|
3337
|
+
|
|
3554
3338
|
/**
|
|
3555
3339
|
* 设置单行商品备注(与整单 `updateTempOrderNote` 区分)。
|
|
3556
3340
|
* 多行同 SKU 时必须传入与删除/更新一致的 unique_identification_number。
|
|
@@ -3560,22 +3344,24 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3560
3344
|
const params = {
|
|
3561
3345
|
product_id: identity.product_id,
|
|
3562
3346
|
product_variant_id: identity.product_variant_id,
|
|
3563
|
-
updates: {
|
|
3347
|
+
updates: {
|
|
3348
|
+
note: String(note || '')
|
|
3349
|
+
}
|
|
3564
3350
|
};
|
|
3565
|
-
if (identity.unique_identification_number !==
|
|
3351
|
+
if (identity.unique_identification_number !== undefined) {
|
|
3566
3352
|
params.unique_identification_number = identity.unique_identification_number;
|
|
3567
3353
|
}
|
|
3568
|
-
if (identity.product_sku !==
|
|
3354
|
+
if (identity.product_sku !== undefined) {
|
|
3569
3355
|
params.product_sku = identity.product_sku;
|
|
3570
3356
|
}
|
|
3571
|
-
if (identity.product_bundle !==
|
|
3572
|
-
params.product_bundle = identity.product_bundle;
|
|
3357
|
+
if (identity.product_bundle !== undefined) params.product_bundle = identity.product_bundle;
|
|
3573
3358
|
const products = await this.updateOrderProduct(params);
|
|
3574
3359
|
return products;
|
|
3575
3360
|
} catch (error) {
|
|
3576
3361
|
throw error;
|
|
3577
3362
|
}
|
|
3578
3363
|
}
|
|
3364
|
+
|
|
3579
3365
|
/**
|
|
3580
3366
|
* 批量删除购物车行,末尾仅一次促销重算。
|
|
3581
3367
|
*
|
|
@@ -3584,8 +3370,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3584
3370
|
*/
|
|
3585
3371
|
async removeProductsFromOrder(identities, options) {
|
|
3586
3372
|
try {
|
|
3587
|
-
if (!this.store.order)
|
|
3588
|
-
throw new Error("order 模块未初始化");
|
|
3373
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3589
3374
|
return await this.store.order.removeProductsFromOrder(identities, options);
|
|
3590
3375
|
} catch (error) {
|
|
3591
3376
|
throw error;
|
|
@@ -3594,7 +3379,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3594
3379
|
async removeProductFromOrder(identity, options) {
|
|
3595
3380
|
return this.removeProductsFromOrder([identity], options);
|
|
3596
3381
|
}
|
|
3382
|
+
|
|
3597
3383
|
// ─── 促销/赠品 透传(迁移自 booking usePromotion) ────────────────
|
|
3384
|
+
|
|
3598
3385
|
/**
|
|
3599
3386
|
* 注入促销评估器到底层 OrderModule。
|
|
3600
3387
|
*
|
|
@@ -3602,10 +3389,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3602
3389
|
* solution.setPromotionEvaluator(appHelper.utils.promotionEvaluator);
|
|
3603
3390
|
*/
|
|
3604
3391
|
setPromotionEvaluator(evaluator) {
|
|
3605
|
-
if (!this.store.order)
|
|
3606
|
-
throw new Error("order 模块未初始化");
|
|
3392
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3607
3393
|
this.store.order.setPromotionEvaluator(evaluator);
|
|
3608
3394
|
}
|
|
3395
|
+
|
|
3609
3396
|
/**
|
|
3610
3397
|
* 注入赠品选择 resolver。UI 层(SalesSdk)通过 bridge 提供。
|
|
3611
3398
|
*
|
|
@@ -3613,10 +3400,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3613
3400
|
* solution.setGiftSelectResolver(async (ctx) => bridge.request(ctx));
|
|
3614
3401
|
*/
|
|
3615
3402
|
setGiftSelectResolver(resolver) {
|
|
3616
|
-
if (!this.store.order)
|
|
3617
|
-
throw new Error("order 模块未初始化");
|
|
3403
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3618
3404
|
this.store.order.setGiftSelectResolver(resolver);
|
|
3619
3405
|
}
|
|
3406
|
+
|
|
3620
3407
|
/**
|
|
3621
3408
|
* 为商品目录追加促销标签,供 SalesSdkProductProvider 等商品列表入口复用。
|
|
3622
3409
|
*
|
|
@@ -3624,40 +3411,40 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3624
3411
|
* const products = solution.appendPromotionTags(catalogProducts);
|
|
3625
3412
|
*/
|
|
3626
3413
|
appendPromotionTags(products) {
|
|
3627
|
-
if (!this.store.order)
|
|
3628
|
-
throw new Error("order 模块未初始化");
|
|
3414
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3629
3415
|
return this.store.order.appendPromotionTags(products);
|
|
3630
3416
|
}
|
|
3417
|
+
|
|
3631
3418
|
/**
|
|
3632
3419
|
* 主动触发一次促销应用(一般写路径会自动触发,少数场景如客户切换后可手动调)。
|
|
3633
3420
|
*/
|
|
3634
3421
|
async applyPromotion() {
|
|
3635
|
-
if (!this.store.order)
|
|
3636
|
-
throw new Error("order 模块未初始化");
|
|
3422
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
3637
3423
|
await this.store.order.applyPromotion();
|
|
3638
3424
|
}
|
|
3425
|
+
|
|
3639
3426
|
/** 最近一次促销计算输出的未满足提示。 */
|
|
3640
3427
|
getUnfulfilledPromotions() {
|
|
3641
|
-
|
|
3642
|
-
return ((_a = this.store.order) == null ? void 0 : _a.getUnfulfilledPromotions()) || [];
|
|
3428
|
+
return this.store.order?.getUnfulfilledPromotions() || [];
|
|
3643
3429
|
}
|
|
3430
|
+
|
|
3644
3431
|
/** 最近一次促销计算输出的赠品操作 diff。 */
|
|
3645
3432
|
getLastGiftActions() {
|
|
3646
|
-
|
|
3647
|
-
return ((_a = this.store.order) == null ? void 0 : _a.getLastGiftActions()) || null;
|
|
3433
|
+
return this.store.order?.getLastGiftActions() || null;
|
|
3648
3434
|
}
|
|
3435
|
+
|
|
3649
3436
|
// 获取商品列表
|
|
3650
3437
|
// TODO 需要跟 webpos 内的对齐一下
|
|
3651
3438
|
async getProductList() {
|
|
3652
|
-
|
|
3653
|
-
const menu_list_ids =
|
|
3439
|
+
// 可以直接通过配置里的 menu 读取
|
|
3440
|
+
const menu_list_ids = this.otherParams?.dineInConfig?.['menu.associated_menus'].map(n => Number(n.value)) || [];
|
|
3654
3441
|
try {
|
|
3655
|
-
const res = await
|
|
3442
|
+
const res = await this.store.products?.loadProducts({
|
|
3656
3443
|
menu_list_ids,
|
|
3657
3444
|
cacheId: this.cacheId,
|
|
3658
|
-
schedule_date: (0,
|
|
3659
|
-
schedule_datetime: (0,
|
|
3660
|
-
})
|
|
3445
|
+
schedule_date: (0, _dayjs.default)().format('YYYY-MM-DD'),
|
|
3446
|
+
schedule_datetime: (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss')
|
|
3447
|
+
});
|
|
3661
3448
|
return res;
|
|
3662
3449
|
} catch (error) {
|
|
3663
3450
|
throw error;
|
|
@@ -3666,19 +3453,23 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
3666
3453
|
getOtherParams() {
|
|
3667
3454
|
return this.otherParams;
|
|
3668
3455
|
}
|
|
3669
|
-
async setOtherParams(params, {
|
|
3670
|
-
|
|
3456
|
+
async setOtherParams(params, {
|
|
3457
|
+
cover = false
|
|
3458
|
+
} = {}) {
|
|
3671
3459
|
if (cover) {
|
|
3672
|
-
this.otherParams = {
|
|
3460
|
+
this.otherParams = {
|
|
3461
|
+
...params
|
|
3462
|
+
};
|
|
3673
3463
|
} else {
|
|
3674
|
-
this.otherParams = {
|
|
3464
|
+
this.otherParams = {
|
|
3465
|
+
...this.otherParams,
|
|
3466
|
+
...params
|
|
3467
|
+
};
|
|
3675
3468
|
}
|
|
3676
|
-
this.cacheId =
|
|
3677
|
-
await this.syncOtherParamsToSubModules(params, {
|
|
3469
|
+
this.cacheId = this.otherParams?.cacheId;
|
|
3470
|
+
await this.syncOtherParamsToSubModules(params, {
|
|
3471
|
+
cover
|
|
3472
|
+
});
|
|
3678
3473
|
}
|
|
3679
|
-
}
|
|
3680
|
-
|
|
3681
|
-
0 && (module.exports = {
|
|
3682
|
-
BaseSalesImpl,
|
|
3683
|
-
...require("./types")
|
|
3684
|
-
});
|
|
3474
|
+
}
|
|
3475
|
+
exports.BaseSalesImpl = BaseSalesImpl;
|