@pisell/pisellos 2.3.39 → 2.3.41
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.d.ts +2 -0
- package/dist/core/index.js +7 -0
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
- package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/dist/model/strategy/adapter/promotion/examples.js +99 -0
- package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/dist/model/strategy/adapter/promotion/type.js +45 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -3
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +6 -3
- package/dist/modules/Discount/index.d.ts +0 -1
- package/dist/modules/Discount/index.js +11 -40
- package/dist/modules/Discount/types.d.ts +0 -1
- package/dist/modules/OpenData/index.d.ts +2 -0
- package/dist/modules/OpenData/index.js +10 -2
- package/dist/modules/Order/index.d.ts +29 -12
- package/dist/modules/Order/index.js +750 -509
- package/dist/modules/Order/payment-utils.d.ts +26 -0
- package/dist/modules/Order/payment-utils.js +225 -0
- package/dist/modules/Order/types.d.ts +33 -10
- package/dist/modules/Order/utils/orderCollectionIdentity.js +7 -2
- package/dist/modules/Order/utils.d.ts +0 -10
- package/dist/modules/Order/utils.js +13 -41
- package/dist/modules/Payment/index.d.ts +2 -0
- package/dist/modules/Payment/index.js +79 -50
- package/dist/modules/Payment/types.d.ts +99 -28
- package/dist/modules/Payment/types.js +20 -3
- package/dist/modules/Payment/walletpass.d.ts +25 -1
- package/dist/modules/Payment/walletpass.js +707 -157
- package/dist/modules/Product/types.d.ts +0 -1
- package/dist/modules/ProductList/index.js +14 -33
- package/dist/modules/Quotation/index.d.ts +1 -1
- package/dist/modules/Quotation/index.js +2 -2
- package/dist/modules/Rules/index.d.ts +1 -0
- package/dist/modules/Rules/index.js +89 -96
- package/dist/modules/SalesSummary/index.js +13 -12
- package/dist/modules/ScanOrderLogger/index.d.ts +0 -2
- package/dist/modules/ScanOrderLogger/index.js +2 -15
- package/dist/modules/ScanOrderLogger/providers/feishu.js +27 -45
- package/dist/modules/ScanOrderLogger/types.d.ts +0 -1
- package/dist/modules/Schedule/index.d.ts +1 -3
- package/dist/modules/Schedule/index.js +16 -21
- package/dist/modules/Summary/utils.js +13 -38
- package/dist/modules/index.d.ts +0 -2
- package/dist/modules/index.js +1 -3
- package/dist/plugins/window.d.ts +0 -1
- package/dist/server/index.d.ts +16 -14
- package/dist/server/index.js +1925 -1143
- package/dist/server/modules/order/index.d.ts +54 -4
- package/dist/server/modules/order/index.js +1600 -700
- package/dist/server/modules/order/types.d.ts +11 -3
- package/dist/server/modules/order/types.js +1 -1
- package/dist/solution/BaseSales/index.d.ts +109 -20
- package/dist/solution/BaseSales/index.js +1800 -480
- package/dist/solution/BaseSales/types.d.ts +52 -0
- package/dist/solution/BaseSales/types.js +2 -1
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/dist/solution/BookingByStep/index.d.ts +2 -17
- package/dist/solution/BookingByStep/index.js +215 -294
- package/dist/solution/BookingByStep/types.d.ts +1 -2
- package/dist/solution/BookingByStep/types.js +1 -3
- package/dist/solution/BookingByStep/utils/capacity.js +1 -17
- package/dist/solution/BookingByStep/utils/timeslots.d.ts +1 -3
- package/dist/solution/BookingByStep/utils/timeslots.js +12 -19
- package/dist/solution/BookingTicket/index.d.ts +7 -3
- package/dist/solution/BookingTicket/index.js +132 -49
- package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +172 -82
- package/dist/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/dist/solution/BookingTicket/utils/weighingProductSku.js +45 -0
- package/dist/solution/Sales/index.d.ts +1 -0
- package/dist/solution/Sales/index.js +10 -2
- package/dist/solution/ScanOrder/index.d.ts +14 -26
- package/dist/solution/ScanOrder/index.js +756 -1148
- package/dist/solution/ScanOrder/types.d.ts +1 -21
- package/dist/solution/ScanOrder/utils.d.ts +0 -8
- package/dist/solution/ScanOrder/utils.js +25 -66
- package/dist/solution/ShopDiscount/index.d.ts +0 -1
- package/dist/solution/ShopDiscount/index.js +87 -125
- package/dist/solution/VenueBooking/index.d.ts +11 -39
- package/dist/solution/VenueBooking/index.js +860 -1176
- package/dist/solution/VenueBooking/types.d.ts +0 -3
- package/dist/solution/VenueBooking/utils/resource.js +0 -1
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/dist/solution/VenueBooking/utils/slotMerge.js +5 -10
- package/dist/solution/index.d.ts +0 -1
- package/dist/solution/index.js +1 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
- package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/lib/model/strategy/adapter/promotion/examples.js +91 -0
- package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/lib/model/strategy/adapter/promotion/index.js +51 -0
- package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/lib/model/strategy/adapter/promotion/type.js +2 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/lib/modules/Discount/index.d.ts +0 -1
- package/lib/modules/Discount/index.js +0 -9
- package/lib/modules/Discount/types.d.ts +0 -1
- package/lib/modules/OpenData/index.d.ts +2 -0
- package/lib/modules/OpenData/index.js +6 -1
- package/lib/modules/Order/index.d.ts +29 -12
- package/lib/modules/Order/index.js +196 -86
- package/lib/modules/Order/payment-utils.d.ts +26 -0
- package/lib/modules/Order/payment-utils.js +224 -0
- package/lib/modules/Order/types.d.ts +33 -10
- package/lib/modules/Order/utils/orderCollectionIdentity.js +3 -0
- package/lib/modules/Order/utils.d.ts +0 -10
- package/lib/modules/Order/utils.js +16 -40
- package/lib/modules/Payment/index.d.ts +2 -0
- package/lib/modules/Payment/index.js +34 -13
- package/lib/modules/Payment/types.d.ts +99 -28
- package/lib/modules/Payment/types.js +4 -3
- package/lib/modules/Payment/walletpass.d.ts +25 -1
- package/lib/modules/Payment/walletpass.js +470 -21
- package/lib/modules/Product/types.d.ts +0 -1
- package/lib/modules/ProductList/index.js +31 -40
- package/lib/modules/Quotation/index.d.ts +1 -1
- package/lib/modules/Quotation/index.js +2 -2
- package/lib/modules/Rules/index.d.ts +1 -0
- package/lib/modules/Rules/index.js +47 -40
- package/lib/modules/SalesSummary/index.js +7 -6
- package/lib/modules/ScanOrderLogger/index.d.ts +0 -2
- package/lib/modules/ScanOrderLogger/index.js +1 -13
- package/lib/modules/ScanOrderLogger/providers/feishu.js +6 -15
- package/lib/modules/ScanOrderLogger/types.d.ts +0 -1
- package/lib/modules/Schedule/index.d.ts +1 -3
- package/lib/modules/Schedule/index.js +8 -10
- package/lib/modules/Summary/utils.js +1 -21
- package/lib/modules/index.d.ts +0 -2
- package/lib/modules/index.js +1 -5
- package/lib/plugins/window.d.ts +0 -1
- package/lib/server/index.d.ts +16 -14
- package/lib/server/index.js +675 -83
- package/lib/server/modules/order/index.d.ts +54 -4
- package/lib/server/modules/order/index.js +679 -66
- package/lib/server/modules/order/types.d.ts +11 -3
- package/lib/solution/BaseSales/index.d.ts +109 -20
- package/lib/solution/BaseSales/index.js +883 -70
- package/lib/solution/BaseSales/types.d.ts +52 -0
- package/lib/solution/BaseSales/types.js +2 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/lib/solution/BookingByStep/index.d.ts +2 -17
- package/lib/solution/BookingByStep/index.js +18 -60
- package/lib/solution/BookingByStep/types.d.ts +1 -2
- package/lib/solution/BookingByStep/types.js +0 -5
- package/lib/solution/BookingByStep/utils/capacity.js +1 -20
- package/lib/solution/BookingByStep/utils/timeslots.d.ts +1 -3
- package/lib/solution/BookingByStep/utils/timeslots.js +11 -19
- package/lib/solution/BookingTicket/index.d.ts +7 -3
- package/lib/solution/BookingTicket/index.js +62 -9
- package/lib/solution/BookingTicket/utils/addProductDecision.js +4 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +36 -4
- package/lib/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +63 -0
- package/lib/solution/Sales/index.d.ts +1 -0
- package/lib/solution/Sales/index.js +5 -3
- package/lib/solution/ScanOrder/index.d.ts +14 -26
- package/lib/solution/ScanOrder/index.js +190 -449
- package/lib/solution/ScanOrder/types.d.ts +1 -21
- package/lib/solution/ScanOrder/utils.d.ts +0 -8
- package/lib/solution/ScanOrder/utils.js +0 -31
- package/lib/solution/ShopDiscount/index.d.ts +0 -1
- package/lib/solution/ShopDiscount/index.js +0 -14
- package/lib/solution/VenueBooking/index.d.ts +11 -39
- package/lib/solution/VenueBooking/index.js +123 -328
- package/lib/solution/VenueBooking/types.d.ts +0 -3
- package/lib/solution/VenueBooking/utils/resource.js +0 -1
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +4 -4
- package/lib/solution/VenueBooking/utils/slotMerge.js +4 -6
- package/lib/solution/index.d.ts +0 -1
- package/lib/solution/index.js +1 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/utils/payment-number.d.ts +9 -0
- package/lib/utils/payment-number.js +64 -0
- package/package.json +1 -1
- package/dist/modules/Holder/index.d.ts +0 -48
- package/dist/modules/Holder/index.js +0 -640
- package/dist/modules/Holder/types.d.ts +0 -123
- package/dist/modules/Holder/types.js +0 -1
- package/dist/modules/Holder/utils.d.ts +0 -13
- package/dist/modules/Holder/utils.js +0 -34
- package/dist/modules/ResourcePlanner/index.d.ts +0 -24
- package/dist/modules/ResourcePlanner/index.js +0 -181
- package/dist/modules/ResourcePlanner/planner.d.ts +0 -14
- package/dist/modules/ResourcePlanner/planner.js +0 -1069
- package/dist/modules/ResourcePlanner/types.d.ts +0 -227
- package/dist/modules/ResourcePlanner/types.js +0 -1
- package/dist/solution/UnifiedBookingSales/index.d.ts +0 -183
- package/dist/solution/UnifiedBookingSales/index.js +0 -1871
- package/dist/solution/UnifiedBookingSales/types.d.ts +0 -143
- package/dist/solution/UnifiedBookingSales/types.js +0 -11
- package/lib/modules/Holder/index.d.ts +0 -48
- package/lib/modules/Holder/index.js +0 -402
- package/lib/modules/Holder/types.d.ts +0 -123
- package/lib/modules/Holder/types.js +0 -17
- package/lib/modules/Holder/utils.d.ts +0 -13
- package/lib/modules/Holder/utils.js +0 -71
- package/lib/modules/ResourcePlanner/index.d.ts +0 -24
- package/lib/modules/ResourcePlanner/index.js +0 -148
- package/lib/modules/ResourcePlanner/planner.d.ts +0 -14
- package/lib/modules/ResourcePlanner/planner.js +0 -933
- package/lib/modules/ResourcePlanner/types.d.ts +0 -227
- package/lib/modules/ResourcePlanner/types.js +0 -17
- package/lib/solution/UnifiedBookingSales/index.d.ts +0 -183
- package/lib/solution/UnifiedBookingSales/index.js +0 -1076
- package/lib/solution/UnifiedBookingSales/types.d.ts +0 -143
- package/lib/solution/UnifiedBookingSales/types.js +0 -33
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { OrderModule, ProductList, SalesSummaryModule, ScanOrderLogInput, ScanOrderLoggerModule, ScanOrderLoggerProviderConfig, ScanOrderLoggerProviderType, DateModule, ScheduleModule, QuotationModule, OpenDataModule } from '../../modules';
|
|
2
2
|
import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
3
|
-
import { HolderModule } from '../../modules/Holder';
|
|
4
3
|
export type { ScanOrderOrderProductIdentity, ScanOrderOrderProduct, ScanOrderSubmitProduct, ScanOrderSummary, ScanOrderTempOrder, ScanOrderSubmitPayload, } from '../ScanOrder/types';
|
|
5
4
|
export declare enum VenueBookingHooks {
|
|
6
5
|
onInited = "venueBooking:onInited",
|
|
@@ -97,7 +96,6 @@ export interface VenueResourceRawData {
|
|
|
97
96
|
export interface ResourceProductMapping {
|
|
98
97
|
productId: number;
|
|
99
98
|
productTitle: string;
|
|
100
|
-
formName?: string;
|
|
101
99
|
resourceName: string;
|
|
102
100
|
formId: number | string;
|
|
103
101
|
price: string;
|
|
@@ -146,7 +144,6 @@ export interface VenueBookingState {
|
|
|
146
144
|
passed: boolean | null;
|
|
147
145
|
failures: QuantityCheckResult[];
|
|
148
146
|
};
|
|
149
|
-
holder?: HolderModule;
|
|
150
147
|
}
|
|
151
148
|
export interface VenueBookingLoggerRuntimeConfig {
|
|
152
149
|
provider?: ScanOrderLoggerProviderType;
|
|
@@ -12,6 +12,10 @@ export declare function buildPriceBreakdown(params: {
|
|
|
12
12
|
}) => number;
|
|
13
13
|
};
|
|
14
14
|
}): PriceBreakdownEntry[];
|
|
15
|
+
export declare function buildVenueResourceMetadata(params: {
|
|
16
|
+
mapping: ResourceProductMapping;
|
|
17
|
+
rawResource: VenueResourceRawData | undefined;
|
|
18
|
+
}): Record<string, any>;
|
|
15
19
|
export interface BuildVenueBookingParams {
|
|
16
20
|
group: MergedSlotGroup;
|
|
17
21
|
resourceId: number | string;
|
|
@@ -25,10 +29,6 @@ export interface BuildVenueBookingParams {
|
|
|
25
29
|
*/
|
|
26
30
|
childResources?: VenueResourceRawData[];
|
|
27
31
|
}
|
|
28
|
-
export declare function buildVenueResourceMetadata(params: {
|
|
29
|
-
mapping: ResourceProductMapping;
|
|
30
|
-
rawResource: VenueResourceRawData | undefined;
|
|
31
|
-
}): Record<string, any>;
|
|
32
32
|
export declare function buildVenueBookingEntry(params: BuildVenueBookingParams): Record<string, any>;
|
|
33
33
|
/**
|
|
34
34
|
* 从一条已合并的订单商品还原出独立的时段列表。
|
|
@@ -90,15 +90,13 @@ export function buildPriceBreakdown(params) {
|
|
|
90
90
|
return entries;
|
|
91
91
|
}
|
|
92
92
|
export function buildVenueResourceMetadata(params) {
|
|
93
|
-
var
|
|
93
|
+
var _rawResource$form_nam, _ref, _rawResource$main_fie, _rawResource$combined;
|
|
94
94
|
var mapping = params.mapping,
|
|
95
95
|
rawResource = params.rawResource;
|
|
96
|
-
var combined = rawResource === null || rawResource === void 0 ? void 0 : rawResource.combined_resource;
|
|
97
|
-
var isCombined = !!(combined && combined.status === 1 && Array.isArray(combined.resource_ids));
|
|
98
96
|
return {
|
|
99
|
-
form_name: (
|
|
100
|
-
resource_name: (_rawResource$main_fie = rawResource === null || rawResource === void 0 ? void 0 : rawResource.main_field) !== null && _rawResource$main_fie !== void 0 ? _rawResource$main_fie : mapping.resourceName,
|
|
101
|
-
combined_resource:
|
|
97
|
+
form_name: (_rawResource$form_nam = rawResource === null || rawResource === void 0 ? void 0 : rawResource.form_name) !== null && _rawResource$form_nam !== void 0 ? _rawResource$form_nam : '',
|
|
98
|
+
resource_name: (_ref = (_rawResource$main_fie = rawResource === null || rawResource === void 0 ? void 0 : rawResource.main_field) !== null && _rawResource$main_fie !== void 0 ? _rawResource$main_fie : mapping.resourceName) !== null && _ref !== void 0 ? _ref : '',
|
|
99
|
+
combined_resource: (_rawResource$combined = rawResource === null || rawResource === void 0 ? void 0 : rawResource.combined_resource) !== null && _rawResource$combined !== void 0 ? _rawResource$combined : null
|
|
102
100
|
};
|
|
103
101
|
}
|
|
104
102
|
export function buildVenueBookingEntry(params) {
|
|
@@ -121,10 +119,7 @@ export function buildVenueBookingEntry(params) {
|
|
|
121
119
|
form_id: (_rawResource$form_id = rawResource === null || rawResource === void 0 ? void 0 : rawResource.form_id) !== null && _rawResource$form_id !== void 0 ? _rawResource$form_id : mapping.formId,
|
|
122
120
|
relation_id: resourceId,
|
|
123
121
|
capacity: 1,
|
|
124
|
-
metadata:
|
|
125
|
-
mapping: mapping,
|
|
126
|
-
rawResource: rawResource
|
|
127
|
-
})
|
|
122
|
+
metadata: {}
|
|
128
123
|
};
|
|
129
124
|
if (childResources && childResources.length) {
|
|
130
125
|
resourceEntry.children = childResources.map(function (child) {
|
package/dist/solution/index.d.ts
CHANGED
package/dist/solution/index.js
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export interface Plugin {
|
|
|
6
6
|
version: string;
|
|
7
7
|
initialize: () => Promise<void> | void;
|
|
8
8
|
destroy?: () => Promise<void> | void;
|
|
9
|
-
getLocalStorage?: (key: string) => string | null;
|
|
10
9
|
}
|
|
11
10
|
export interface PluginOptions {
|
|
12
11
|
dependencies?: string[];
|
|
@@ -48,6 +47,7 @@ export interface PisellCore {
|
|
|
48
47
|
getModule: <T extends Module>(name: string) => T | null;
|
|
49
48
|
getModuleExports: <T = any>(name: string) => T | null;
|
|
50
49
|
hasModule: (name: string) => boolean;
|
|
50
|
+
getModuleNames: () => string[];
|
|
51
51
|
effects: {
|
|
52
52
|
on: (event: string, callback: (payload: any) => void) => () => void;
|
|
53
53
|
once: (event: string, callback: (payload: any) => void) => () => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PaymentNumberAppDataGetter = (key: string) => unknown;
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the synchronous fallback without caching runtime device data.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resolvePaymentNumberDevicePrefixFromDeviceId(getAppData: PaymentNumberAppDataGetter): string;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the latest device segment when a new payment number is generated.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolvePaymentNumberDevicePrefix(getAppData: PaymentNumberAppDataGetter): Promise<string>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
3
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
4
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
5
|
+
function normalizeNonEmptyString(value) {
|
|
6
|
+
if (value === undefined || value === null) return null;
|
|
7
|
+
if (typeof value !== 'string' && typeof value !== 'number') return null;
|
|
8
|
+
if (typeof value === 'number' && !Number.isFinite(value)) return null;
|
|
9
|
+
var normalized = String(value).trim();
|
|
10
|
+
return normalized || null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the synchronous fallback without caching runtime device data.
|
|
15
|
+
*/
|
|
16
|
+
export function resolvePaymentNumberDevicePrefixFromDeviceId(getAppData) {
|
|
17
|
+
try {
|
|
18
|
+
var deviceId = normalizeNonEmptyString(getAppData('device_id'));
|
|
19
|
+
if (deviceId && deviceId !== '0') return deviceId.slice(-2);
|
|
20
|
+
} catch (_unused) {
|
|
21
|
+
// The stable LOCAL prefix is the final fallback.
|
|
22
|
+
}
|
|
23
|
+
return 'LOCAL';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the latest device segment when a new payment number is generated.
|
|
28
|
+
*/
|
|
29
|
+
export function resolvePaymentNumberDevicePrefix(_x) {
|
|
30
|
+
return _resolvePaymentNumberDevicePrefix.apply(this, arguments);
|
|
31
|
+
}
|
|
32
|
+
function _resolvePaymentNumberDevicePrefix() {
|
|
33
|
+
_resolvePaymentNumberDevicePrefix = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(getAppData) {
|
|
34
|
+
var getAsyncIotDeviceInfo, info, shortNumber;
|
|
35
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
36
|
+
while (1) switch (_context.prev = _context.next) {
|
|
37
|
+
case 0:
|
|
38
|
+
_context.prev = 0;
|
|
39
|
+
getAsyncIotDeviceInfo = getAppData('async_iot_device_info');
|
|
40
|
+
if (!(typeof getAsyncIotDeviceInfo === 'function')) {
|
|
41
|
+
_context.next = 9;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
_context.next = 5;
|
|
45
|
+
return getAsyncIotDeviceInfo();
|
|
46
|
+
case 5:
|
|
47
|
+
info = _context.sent;
|
|
48
|
+
shortNumber = normalizeNonEmptyString(info === null || info === void 0 ? void 0 : info.short_number);
|
|
49
|
+
if (!(shortNumber && shortNumber !== '0')) {
|
|
50
|
+
_context.next = 9;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
return _context.abrupt("return", shortNumber);
|
|
54
|
+
case 9:
|
|
55
|
+
_context.next = 13;
|
|
56
|
+
break;
|
|
57
|
+
case 11:
|
|
58
|
+
_context.prev = 11;
|
|
59
|
+
_context.t0 = _context["catch"](0);
|
|
60
|
+
case 13:
|
|
61
|
+
return _context.abrupt("return", resolvePaymentNumberDevicePrefixFromDeviceId(getAppData));
|
|
62
|
+
case 14:
|
|
63
|
+
case "end":
|
|
64
|
+
return _context.stop();
|
|
65
|
+
}
|
|
66
|
+
}, _callee, null, [[0, 11]]);
|
|
67
|
+
}));
|
|
68
|
+
return _resolvePaymentNumberDevicePrefix.apply(this, arguments);
|
|
69
|
+
}
|
package/lib/core/index.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ declare class PisellOSCore implements PisellCore {
|
|
|
28
28
|
getModule<T extends Module>(name: string): T | null;
|
|
29
29
|
getModuleExports<T = any>(name: string): T | null;
|
|
30
30
|
hasModule(name: string): boolean;
|
|
31
|
+
/** 返回当前已注册模块名,供宿主在切换店铺等生命周期中定向清理运行态。 */
|
|
32
|
+
getModuleNames(): string[];
|
|
31
33
|
destroy(): Promise<void>;
|
|
32
34
|
setContext(ctx: Partial<BusinessContext>): void;
|
|
33
35
|
/**
|
package/lib/core/index.js
CHANGED
|
@@ -210,6 +210,10 @@ var PisellOSCore = class {
|
|
|
210
210
|
hasModule(name) {
|
|
211
211
|
return this.modules.has(name);
|
|
212
212
|
}
|
|
213
|
+
/** 返回当前已注册模块名,供宿主在切换店铺等生命周期中定向清理运行态。 */
|
|
214
|
+
getModuleNames() {
|
|
215
|
+
return Array.from(this.modules.keys());
|
|
216
|
+
}
|
|
213
217
|
// 销毁方法
|
|
214
218
|
async destroy() {
|
|
215
219
|
for (const [name, module2] of this.modules.entries()) {
|
|
@@ -134,6 +134,8 @@ var PromotionAdapter = class {
|
|
|
134
134
|
return this.parseXItemsForYPriceAction(action);
|
|
135
135
|
case import_type.PROMOTION_ACTION_TYPES.BUY_X_GET_Y_FREE:
|
|
136
136
|
return this.parseBuyXGetYFreeAction(action);
|
|
137
|
+
case import_type.PROMOTION_ACTION_TYPES.ITEM_REWARD:
|
|
138
|
+
return this.parseItemRewardAction(action);
|
|
137
139
|
default:
|
|
138
140
|
return void 0;
|
|
139
141
|
}
|
|
@@ -167,6 +169,24 @@ var PromotionAdapter = class {
|
|
|
167
169
|
giftProducts: config.giftProducts || []
|
|
168
170
|
};
|
|
169
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* 解析 商品奖励 Action
|
|
174
|
+
*/
|
|
175
|
+
parseItemRewardAction(action) {
|
|
176
|
+
const value = action.value || {};
|
|
177
|
+
const config = action.config || {};
|
|
178
|
+
return {
|
|
179
|
+
type: import_type.PROMOTION_ACTION_TYPES.ITEM_REWARD,
|
|
180
|
+
rewardMethod: value.rewardMethod || "free",
|
|
181
|
+
rewardValue: Number(value.rewardValue || 0),
|
|
182
|
+
quantityRule: value.quantityRule || "per_condition_quantity",
|
|
183
|
+
triggerQuantity: Number(value.triggerQuantity || 1),
|
|
184
|
+
rewardQuantity: Number(value.rewardQuantity || 1),
|
|
185
|
+
maxRewardQuantity: value.maxRewardQuantity === void 0 || value.maxRewardQuantity === null ? void 0 : Number(value.maxRewardQuantity),
|
|
186
|
+
rewardTargets: Array.isArray(config.rewardTargets) ? config.rewardTargets : [],
|
|
187
|
+
targetSelection: config.targetSelection || "consumer_best"
|
|
188
|
+
};
|
|
189
|
+
}
|
|
170
190
|
/**
|
|
171
191
|
* 获取适用的商品列表
|
|
172
192
|
*
|
|
@@ -169,6 +169,21 @@ export declare class PromotionEvaluator {
|
|
|
169
169
|
* 支持 bundle 子商品的数量计算(主商品数量 × 子商品数量)
|
|
170
170
|
*/
|
|
171
171
|
private processBuyXGetYFree;
|
|
172
|
+
/**
|
|
173
|
+
* 处理 商品奖励 促销
|
|
174
|
+
*
|
|
175
|
+
* 1. 使用 group.products 统计触发条件商品数量
|
|
176
|
+
* 2. 按 quantityRule 计算最多奖励的目标商品数量
|
|
177
|
+
* 3. 在全购物车商品中筛选 rewardTargets
|
|
178
|
+
* 4. 按消费者最优(可节省金额从高到低)选择目标单位
|
|
179
|
+
* 5. 对目标商品拆分并写入 finalPrice,触发商品本身不改价
|
|
180
|
+
*/
|
|
181
|
+
private processItemReward;
|
|
182
|
+
private normalizePositiveInteger;
|
|
183
|
+
private getAvailablePromotionQuantity;
|
|
184
|
+
private buildItemRewardTargetUnits;
|
|
185
|
+
private resolveItemRewardFinalPrice;
|
|
186
|
+
private resolveItemRewardLimit;
|
|
172
187
|
/**
|
|
173
188
|
* 获取未参与任何促销的商品
|
|
174
189
|
*/
|
|
@@ -194,6 +209,8 @@ export declare class PromotionEvaluator {
|
|
|
194
209
|
* 检查商品是否在策略的适用范围内
|
|
195
210
|
*/
|
|
196
211
|
private isProductInStrategy;
|
|
212
|
+
private shouldSkipStrategyForProduct;
|
|
213
|
+
private hasActionType;
|
|
197
214
|
/**
|
|
198
215
|
* 查找商品匹配规则
|
|
199
216
|
*/
|
|
@@ -133,6 +133,9 @@ var PromotionEvaluator = class {
|
|
|
133
133
|
for (const product of products) {
|
|
134
134
|
const applicablePromotions = [];
|
|
135
135
|
for (const config of configs) {
|
|
136
|
+
if (this.shouldSkipStrategyForProduct(product, config)) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
136
139
|
const matchInfo = this.getProductMatchInfo(product, config);
|
|
137
140
|
if (!matchInfo.isMatch) {
|
|
138
141
|
continue;
|
|
@@ -296,6 +299,16 @@ var PromotionEvaluator = class {
|
|
|
296
299
|
if (result.giftInfo) {
|
|
297
300
|
gifts.push(result.giftInfo);
|
|
298
301
|
}
|
|
302
|
+
} else if (actionType === import_type.PROMOTION_ACTION_TYPES.ITEM_REWARD) {
|
|
303
|
+
const result = this.processItemReward(
|
|
304
|
+
group,
|
|
305
|
+
processedQuantityMap,
|
|
306
|
+
products,
|
|
307
|
+
matchedBundleIndexMap
|
|
308
|
+
);
|
|
309
|
+
pricedProducts.push(...result.products);
|
|
310
|
+
totalOriginalAmount = totalOriginalAmount.plus(result.originalAmount);
|
|
311
|
+
totalFinalAmount = totalFinalAmount.plus(result.finalAmount);
|
|
299
312
|
}
|
|
300
313
|
}
|
|
301
314
|
const remainingProducts = this.getRemainingProducts(
|
|
@@ -379,6 +392,9 @@ var PromotionEvaluator = class {
|
|
|
379
392
|
for (const product of products) {
|
|
380
393
|
const applicableStrategies = [];
|
|
381
394
|
for (const config of configs) {
|
|
395
|
+
if (this.shouldSkipStrategyForProduct(product, config)) {
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
382
398
|
let contextProduct = product;
|
|
383
399
|
if (!matchVariant) {
|
|
384
400
|
const productMatchRule = this.findProductMatchRule(config);
|
|
@@ -455,6 +471,9 @@ var PromotionEvaluator = class {
|
|
|
455
471
|
} else if (actionType === "X_ITEMS_FOR_Y_PRICE") {
|
|
456
472
|
const detail = actionDetail;
|
|
457
473
|
requiredQuantity = detail.x || 0;
|
|
474
|
+
} else if (actionType === "ITEM_REWARD") {
|
|
475
|
+
const detail = actionDetail;
|
|
476
|
+
requiredQuantity = detail.triggerQuantity || 1;
|
|
458
477
|
}
|
|
459
478
|
const productMatchRule = this.findProductMatchRule(config);
|
|
460
479
|
const eligibleProducts = (productMatchRule == null ? void 0 : productMatchRule.value) || [];
|
|
@@ -768,6 +787,213 @@ var PromotionEvaluator = class {
|
|
|
768
787
|
giftInfo
|
|
769
788
|
};
|
|
770
789
|
}
|
|
790
|
+
/**
|
|
791
|
+
* 处理 商品奖励 促销
|
|
792
|
+
*
|
|
793
|
+
* 1. 使用 group.products 统计触发条件商品数量
|
|
794
|
+
* 2. 按 quantityRule 计算最多奖励的目标商品数量
|
|
795
|
+
* 3. 在全购物车商品中筛选 rewardTargets
|
|
796
|
+
* 4. 按消费者最优(可节省金额从高到低)选择目标单位
|
|
797
|
+
* 5. 对目标商品拆分并写入 finalPrice,触发商品本身不改价
|
|
798
|
+
*/
|
|
799
|
+
processItemReward(group, processedQuantityMap, allProducts, matchedBundleIndexMap) {
|
|
800
|
+
const {
|
|
801
|
+
strategyId,
|
|
802
|
+
strategyMetadata,
|
|
803
|
+
actionDetail,
|
|
804
|
+
products: triggerProducts
|
|
805
|
+
} = group;
|
|
806
|
+
const detail = actionDetail;
|
|
807
|
+
const triggerQuantity = this.normalizePositiveInteger(detail.triggerQuantity, 1);
|
|
808
|
+
const rewardQuantity = this.normalizePositiveInteger(detail.rewardQuantity, 1);
|
|
809
|
+
const conditionQuantity = this.getAvailablePromotionQuantity(
|
|
810
|
+
triggerProducts,
|
|
811
|
+
processedQuantityMap,
|
|
812
|
+
matchedBundleIndexMap
|
|
813
|
+
);
|
|
814
|
+
if (conditionQuantity < triggerQuantity) {
|
|
815
|
+
return { products: [], originalAmount: 0, finalAmount: 0 };
|
|
816
|
+
}
|
|
817
|
+
const targetProducts = allProducts.filter(
|
|
818
|
+
(product) => this.isProductMatch(product, detail.rewardTargets || [])
|
|
819
|
+
);
|
|
820
|
+
const targetUnitCandidates = this.buildItemRewardTargetUnits(
|
|
821
|
+
targetProducts,
|
|
822
|
+
processedQuantityMap,
|
|
823
|
+
detail
|
|
824
|
+
);
|
|
825
|
+
if (targetUnitCandidates.length === 0) {
|
|
826
|
+
return { products: [], originalAmount: 0, finalAmount: 0 };
|
|
827
|
+
}
|
|
828
|
+
const rewardLimit = this.resolveItemRewardLimit(
|
|
829
|
+
detail,
|
|
830
|
+
conditionQuantity,
|
|
831
|
+
triggerQuantity,
|
|
832
|
+
rewardQuantity,
|
|
833
|
+
targetUnitCandidates.length
|
|
834
|
+
);
|
|
835
|
+
if (rewardLimit <= 0) {
|
|
836
|
+
return { products: [], originalAmount: 0, finalAmount: 0 };
|
|
837
|
+
}
|
|
838
|
+
const selectedUnits = [...targetUnitCandidates].sort((a, b) => {
|
|
839
|
+
const discountDiff = b.discountAmount.minus(a.discountAmount).toNumber();
|
|
840
|
+
if (discountDiff !== 0)
|
|
841
|
+
return discountDiff;
|
|
842
|
+
return b.originalPrice.minus(a.originalPrice).toNumber();
|
|
843
|
+
}).slice(0, rewardLimit);
|
|
844
|
+
const selectedByProductId = /* @__PURE__ */ new Map();
|
|
845
|
+
for (const unit of selectedUnits) {
|
|
846
|
+
const existing = selectedByProductId.get(unit.product.id);
|
|
847
|
+
if (existing) {
|
|
848
|
+
existing.quantity += 1;
|
|
849
|
+
} else {
|
|
850
|
+
selectedByProductId.set(unit.product.id, {
|
|
851
|
+
quantity: 1,
|
|
852
|
+
finalPrice: unit.finalPrice,
|
|
853
|
+
originalPrice: unit.originalPrice
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
const result = [];
|
|
858
|
+
let originalAmount = new import_decimal.default(0);
|
|
859
|
+
let finalAmount = new import_decimal.default(0);
|
|
860
|
+
for (const product of targetProducts) {
|
|
861
|
+
const key = this.getProductKey(product);
|
|
862
|
+
const processedQty = processedQuantityMap.get(key) || 0;
|
|
863
|
+
const availableQty = product.quantity - processedQty;
|
|
864
|
+
if (availableQty <= 0)
|
|
865
|
+
continue;
|
|
866
|
+
const selected = selectedByProductId.get(product.id);
|
|
867
|
+
const selectedQty = (selected == null ? void 0 : selected.quantity) || 0;
|
|
868
|
+
const remainingQty = availableQty - selectedQty;
|
|
869
|
+
if (selectedQty <= 0)
|
|
870
|
+
continue;
|
|
871
|
+
if (selectedQty > 0) {
|
|
872
|
+
result.push({
|
|
873
|
+
...product,
|
|
874
|
+
id: selectedQty === availableQty ? product.id : this.generateRandomId(),
|
|
875
|
+
originalId: product.id,
|
|
876
|
+
quantity: selectedQty,
|
|
877
|
+
finalPrice: this.formatPrice(selected.finalPrice),
|
|
878
|
+
strategyId,
|
|
879
|
+
strategyMetadata,
|
|
880
|
+
inPromotion: true,
|
|
881
|
+
isSplit: selectedQty !== product.quantity
|
|
882
|
+
});
|
|
883
|
+
originalAmount = originalAmount.plus(
|
|
884
|
+
selected.originalPrice.mul(selectedQty)
|
|
885
|
+
);
|
|
886
|
+
finalAmount = finalAmount.plus(selected.finalPrice.mul(selectedQty));
|
|
887
|
+
}
|
|
888
|
+
if (remainingQty > 0) {
|
|
889
|
+
result.push({
|
|
890
|
+
...product,
|
|
891
|
+
quantity: remainingQty,
|
|
892
|
+
finalPrice: this.formatPrice(product.price),
|
|
893
|
+
strategyId: void 0,
|
|
894
|
+
strategyMetadata: void 0,
|
|
895
|
+
inPromotion: false,
|
|
896
|
+
isSplit: selectedQty > 0
|
|
897
|
+
});
|
|
898
|
+
const remainingAmount = new import_decimal.default(product.price).mul(remainingQty);
|
|
899
|
+
originalAmount = originalAmount.plus(remainingAmount);
|
|
900
|
+
finalAmount = finalAmount.plus(remainingAmount);
|
|
901
|
+
}
|
|
902
|
+
processedQuantityMap.set(key, processedQty + availableQty);
|
|
903
|
+
}
|
|
904
|
+
return {
|
|
905
|
+
products: result,
|
|
906
|
+
originalAmount: originalAmount.toNumber(),
|
|
907
|
+
finalAmount: finalAmount.toNumber()
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
normalizePositiveInteger(value, fallback) {
|
|
911
|
+
const n = Math.floor(Number(value));
|
|
912
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
913
|
+
}
|
|
914
|
+
getAvailablePromotionQuantity(products, processedQuantityMap, matchedBundleIndexMap) {
|
|
915
|
+
let total = 0;
|
|
916
|
+
for (const product of products) {
|
|
917
|
+
const key = this.getProductKey(product);
|
|
918
|
+
const processedQty = processedQuantityMap.get(key) || 0;
|
|
919
|
+
const availableQty = product.quantity - processedQty;
|
|
920
|
+
if (availableQty <= 0)
|
|
921
|
+
continue;
|
|
922
|
+
const matchedBundleIndex = matchedBundleIndexMap == null ? void 0 : matchedBundleIndexMap.get(product.id);
|
|
923
|
+
if (matchedBundleIndex !== void 0 && product.bundle) {
|
|
924
|
+
const bundleItem = product.bundle[matchedBundleIndex];
|
|
925
|
+
total += availableQty * ((bundleItem == null ? void 0 : bundleItem.quantity) || 1);
|
|
926
|
+
} else {
|
|
927
|
+
total += availableQty;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
return total;
|
|
931
|
+
}
|
|
932
|
+
buildItemRewardTargetUnits(products, processedQuantityMap, detail) {
|
|
933
|
+
const units = [];
|
|
934
|
+
for (const product of products) {
|
|
935
|
+
const key = this.getProductKey(product);
|
|
936
|
+
const processedQty = processedQuantityMap.get(key) || 0;
|
|
937
|
+
const availableQty = product.quantity - processedQty;
|
|
938
|
+
if (availableQty <= 0)
|
|
939
|
+
continue;
|
|
940
|
+
const originalPrice = new import_decimal.default(product.price || 0);
|
|
941
|
+
const finalPrice = this.resolveItemRewardFinalPrice(originalPrice, detail);
|
|
942
|
+
const discountAmount = originalPrice.minus(finalPrice);
|
|
943
|
+
if (discountAmount.lte(0))
|
|
944
|
+
continue;
|
|
945
|
+
for (let i = 0; i < availableQty; i++) {
|
|
946
|
+
units.push({
|
|
947
|
+
product,
|
|
948
|
+
originalPrice,
|
|
949
|
+
finalPrice,
|
|
950
|
+
discountAmount
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return units;
|
|
955
|
+
}
|
|
956
|
+
resolveItemRewardFinalPrice(originalPrice, detail) {
|
|
957
|
+
const rewardValue = new import_decimal.default(Number(detail.rewardValue) || 0);
|
|
958
|
+
let finalPrice;
|
|
959
|
+
switch (detail.rewardMethod) {
|
|
960
|
+
case "percent_off": {
|
|
961
|
+
const percent = import_decimal.default.min(100, import_decimal.default.max(0, rewardValue));
|
|
962
|
+
finalPrice = originalPrice.mul(new import_decimal.default(100).minus(percent)).div(100);
|
|
963
|
+
break;
|
|
964
|
+
}
|
|
965
|
+
case "amount_off":
|
|
966
|
+
finalPrice = originalPrice.minus(import_decimal.default.max(0, rewardValue));
|
|
967
|
+
break;
|
|
968
|
+
case "fixed_price":
|
|
969
|
+
finalPrice = import_decimal.default.max(0, rewardValue);
|
|
970
|
+
break;
|
|
971
|
+
case "free":
|
|
972
|
+
default:
|
|
973
|
+
finalPrice = new import_decimal.default(0);
|
|
974
|
+
break;
|
|
975
|
+
}
|
|
976
|
+
return import_decimal.default.max(0, import_decimal.default.min(originalPrice, finalPrice)).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
|
|
977
|
+
}
|
|
978
|
+
resolveItemRewardLimit(detail, conditionQuantity, triggerQuantity, rewardQuantity, targetUnitCount) {
|
|
979
|
+
let limit = 0;
|
|
980
|
+
switch (detail.quantityRule) {
|
|
981
|
+
case "all_targets":
|
|
982
|
+
limit = targetUnitCount;
|
|
983
|
+
break;
|
|
984
|
+
case "max_per_order":
|
|
985
|
+
limit = this.normalizePositiveInteger(
|
|
986
|
+
detail.maxRewardQuantity ?? detail.rewardQuantity,
|
|
987
|
+
rewardQuantity
|
|
988
|
+
);
|
|
989
|
+
break;
|
|
990
|
+
case "per_condition_quantity":
|
|
991
|
+
default:
|
|
992
|
+
limit = Math.floor(conditionQuantity / triggerQuantity) * rewardQuantity;
|
|
993
|
+
break;
|
|
994
|
+
}
|
|
995
|
+
return Math.min(Math.max(0, limit), targetUnitCount);
|
|
996
|
+
}
|
|
771
997
|
/**
|
|
772
998
|
* 获取未参与任何促销的商品
|
|
773
999
|
*/
|
|
@@ -839,8 +1065,17 @@ var PromotionEvaluator = class {
|
|
|
839
1065
|
* 检查商品是否在策略的适用范围内
|
|
840
1066
|
*/
|
|
841
1067
|
isProductInStrategy(product, config) {
|
|
1068
|
+
if (this.shouldSkipStrategyForProduct(product, config)) {
|
|
1069
|
+
return false;
|
|
1070
|
+
}
|
|
842
1071
|
return this.getProductMatchInfo(product, config).isMatch;
|
|
843
1072
|
}
|
|
1073
|
+
shouldSkipStrategyForProduct(product, config) {
|
|
1074
|
+
return Boolean(product._promotionOnlyForItemReward) && !this.hasActionType(config, import_type.PROMOTION_ACTION_TYPES.ITEM_REWARD);
|
|
1075
|
+
}
|
|
1076
|
+
hasActionType(config, actionType) {
|
|
1077
|
+
return (config.actions || []).some((action) => (action == null ? void 0 : action.type) === actionType);
|
|
1078
|
+
}
|
|
844
1079
|
/**
|
|
845
1080
|
* 查找商品匹配规则
|
|
846
1081
|
*/
|