@pisell/pisellos 0.10.16 → 0.10.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/OpenData/index.d.ts +5 -2
- package/dist/modules/OpenData/index.js +27 -12
- package/dist/modules/OpenData/types.d.ts +42 -0
- package/dist/modules/OpenData/types.js +7 -1
- package/dist/modules/OpenData/utils.d.ts +15 -1
- package/dist/modules/OpenData/utils.js +85 -0
- package/dist/modules/Order/index.d.ts +3 -1
- package/dist/modules/Order/index.js +68 -44
- package/dist/modules/Order/types.d.ts +3 -0
- package/dist/modules/Order/types.js +1 -0
- package/dist/modules/ProductList/index.js +96 -74
- package/dist/modules/Rules/index.js +11 -8
- package/dist/modules/SalesSummary/index.js +6 -4
- package/dist/server/index.d.ts +11 -0
- package/dist/server/index.js +845 -481
- package/dist/server/modules/order/index.d.ts +8 -0
- package/dist/server/modules/order/index.js +251 -215
- package/dist/server/utils/small-ticket.d.ts +9 -1
- package/dist/server/utils/small-ticket.js +117 -43
- package/dist/solution/BaseSales/index.d.ts +7 -0
- package/dist/solution/BaseSales/index.js +251 -144
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/BookingTicket/index.d.ts +14 -19
- package/dist/solution/BookingTicket/index.js +545 -429
- package/dist/solution/Sales/index.d.ts +20 -4
- package/dist/solution/Sales/index.js +348 -75
- package/dist/solution/Sales/types.d.ts +10 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +5 -4
- package/dist/solution/UnifiedBookingSales/index.js +495 -422
- package/dist/solution/UnifiedBookingSales/types.d.ts +7 -1
- package/lib/model/strategy/adapter/promotion/index.js +1 -46
- package/lib/modules/OpenData/index.d.ts +5 -2
- package/lib/modules/OpenData/index.js +50 -3
- package/lib/modules/OpenData/types.d.ts +42 -0
- package/lib/modules/OpenData/types.js +9 -1
- package/lib/modules/OpenData/utils.d.ts +15 -1
- package/lib/modules/OpenData/utils.js +85 -0
- package/lib/modules/Order/index.d.ts +3 -1
- package/lib/modules/Order/index.js +41 -21
- package/lib/modules/Order/types.d.ts +3 -0
- package/lib/modules/Order/types.js +1 -0
- package/lib/modules/ProductList/index.js +9 -6
- package/lib/modules/Rules/index.js +8 -6
- package/lib/modules/SalesSummary/index.js +3 -1
- package/lib/server/index.d.ts +11 -0
- package/lib/server/index.js +395 -96
- package/lib/server/modules/order/index.d.ts +8 -0
- package/lib/server/modules/order/index.js +23 -0
- package/lib/server/utils/small-ticket.d.ts +9 -1
- package/lib/server/utils/small-ticket.js +107 -35
- package/lib/solution/BaseSales/index.d.ts +7 -0
- package/lib/solution/BaseSales/index.js +125 -28
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/BookingTicket/index.d.ts +14 -19
- package/lib/solution/BookingTicket/index.js +70 -17
- package/lib/solution/Sales/index.d.ts +20 -4
- package/lib/solution/Sales/index.js +183 -15
- package/lib/solution/Sales/types.d.ts +10 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +5 -4
- package/lib/solution/UnifiedBookingSales/index.js +41 -15
- package/lib/solution/UnifiedBookingSales/types.d.ts +7 -1
- package/package.json +1 -1
|
@@ -20,6 +20,8 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
20
20
|
private storage;
|
|
21
21
|
private orderSQLiteSaveQueue; /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
|
|
22
22
|
private recentSqliteWriteByStorageKey;
|
|
23
|
+
/** 最近一次清理过期 SQLite 去重记录的时间,避免每次写入都遍历 Map */
|
|
24
|
+
private lastRecentSqliteWriteCleanupAtMs;
|
|
23
25
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
24
26
|
private lastServerFullFetchAtMs;
|
|
25
27
|
constructor(name?: string, version?: string);
|
|
@@ -58,6 +60,12 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
58
60
|
*/
|
|
59
61
|
private mergeAuthoritativeOrderCollection;
|
|
60
62
|
private reconcileOverwriteOrderCollections;
|
|
63
|
+
/**
|
|
64
|
+
* 惰性清理已经超过去重窗口的 SQLite 写入记录。
|
|
65
|
+
*
|
|
66
|
+
* 清理频率与去重窗口一致,既限制 Map 长期增长,也不会移除仍参与去重的记录。
|
|
67
|
+
*/
|
|
68
|
+
private cleanupExpiredRecentSqliteWrites;
|
|
61
69
|
/**
|
|
62
70
|
* 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
|
|
63
71
|
*
|
|
@@ -56,6 +56,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
56
56
|
storage;
|
|
57
57
|
orderSQLiteSaveQueue = Promise.resolve(); /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
|
|
58
58
|
recentSqliteWriteByStorageKey = new Map();
|
|
59
|
+
/** 最近一次清理过期 SQLite 去重记录的时间,避免每次写入都遍历 Map */
|
|
60
|
+
lastRecentSqliteWriteCleanupAtMs = 0;
|
|
59
61
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
60
62
|
lastServerFullFetchAtMs = 0;
|
|
61
63
|
constructor(name, version) {
|
|
@@ -285,6 +287,24 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
285
287
|
return this.normalizeOrderCollectionsForIngress((0, _orderCollectionIdentity.applyOrderCollectionUidRemaps)(reconciled, uidRemaps), 'overwriteExistingOrder.reconciled');
|
|
286
288
|
}
|
|
287
289
|
|
|
290
|
+
/**
|
|
291
|
+
* 惰性清理已经超过去重窗口的 SQLite 写入记录。
|
|
292
|
+
*
|
|
293
|
+
* 清理频率与去重窗口一致,既限制 Map 长期增长,也不会移除仍参与去重的记录。
|
|
294
|
+
*/
|
|
295
|
+
cleanupExpiredRecentSqliteWrites(now) {
|
|
296
|
+
const elapsedSinceCleanup = now - this.lastRecentSqliteWriteCleanupAtMs;
|
|
297
|
+
if (this.lastRecentSqliteWriteCleanupAtMs > 0 && elapsedSinceCleanup >= 0 && elapsedSinceCleanup < ORDER_SQLITE_DEDUPE_MS) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
for (const [storageKey, recentWrite] of this.recentSqliteWriteByStorageKey) {
|
|
301
|
+
if (now - recentWrite.ts >= ORDER_SQLITE_DEDUPE_MS) {
|
|
302
|
+
this.recentSqliteWriteByStorageKey.delete(storageKey);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
this.lastRecentSqliteWriteCleanupAtMs = now;
|
|
306
|
+
}
|
|
307
|
+
|
|
288
308
|
/**
|
|
289
309
|
* 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
|
|
290
310
|
*
|
|
@@ -293,6 +313,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
293
313
|
*/
|
|
294
314
|
recordRecentSqliteWrite(source, orders) {
|
|
295
315
|
const now = Date.now();
|
|
316
|
+
this.cleanupExpiredRecentSqliteWrites(now);
|
|
296
317
|
for (const order of orders) {
|
|
297
318
|
const storageKey = this.getOrderStorageKey(order);
|
|
298
319
|
if (!storageKey) continue;
|
|
@@ -1176,6 +1197,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1176
1197
|
}
|
|
1177
1198
|
this.isProcessingSyncBatch = false;
|
|
1178
1199
|
this.pendingSyncMessages = [];
|
|
1200
|
+
this.recentSqliteWriteByStorageKey.clear();
|
|
1201
|
+
this.lastRecentSqliteWriteCleanupAtMs = 0;
|
|
1179
1202
|
if (this.orderDataSource?.destroy) this.orderDataSource.destroy();
|
|
1180
1203
|
super.destroy();
|
|
1181
1204
|
}
|
|
@@ -35,6 +35,8 @@ export interface SmallTicketProduct {
|
|
|
35
35
|
original_price: string;
|
|
36
36
|
total_original_price: string;
|
|
37
37
|
extension_list: any[];
|
|
38
|
+
product_uid?: string | number;
|
|
39
|
+
booking_uid?: string | number;
|
|
38
40
|
options?: Array<{
|
|
39
41
|
name: string;
|
|
40
42
|
num?: number;
|
|
@@ -44,6 +46,11 @@ export interface SmallTicketProduct {
|
|
|
44
46
|
variant?: string;
|
|
45
47
|
combinations?: any[];
|
|
46
48
|
}
|
|
49
|
+
export interface SmallTicketBookingSnapshot extends Record<string, any> {
|
|
50
|
+
product_uid?: string | number;
|
|
51
|
+
booking_uid?: string | number;
|
|
52
|
+
}
|
|
53
|
+
export type SmallTicketAppointment = SmallTicketItem[] | SmallTicketBookingSnapshot[];
|
|
47
54
|
export interface SmallTicketLocaleData {
|
|
48
55
|
base_data: Record<string, any>;
|
|
49
56
|
products: SmallTicketProduct[];
|
|
@@ -52,7 +59,7 @@ export interface SmallTicketLocaleData {
|
|
|
52
59
|
countFee: Record<string, any>;
|
|
53
60
|
};
|
|
54
61
|
customer: SmallTicketItem[];
|
|
55
|
-
appointment:
|
|
62
|
+
appointment: SmallTicketAppointment;
|
|
56
63
|
delivery?: SmallTicketItem[];
|
|
57
64
|
resources: Array<{
|
|
58
65
|
id: string | number;
|
|
@@ -61,6 +68,7 @@ export interface SmallTicketLocaleData {
|
|
|
61
68
|
form_title: string;
|
|
62
69
|
}>;
|
|
63
70
|
payment_data: SmallTicketItem[][];
|
|
71
|
+
wallets: SmallTicketItem[][];
|
|
64
72
|
tickets: any[];
|
|
65
73
|
source_shop: any[];
|
|
66
74
|
refund_data: any[];
|
|
@@ -141,6 +141,11 @@ function buildLocaleData(params) {
|
|
|
141
141
|
locale,
|
|
142
142
|
currencySymbol
|
|
143
143
|
}),
|
|
144
|
+
wallets: buildWallets({
|
|
145
|
+
order,
|
|
146
|
+
locale,
|
|
147
|
+
currencySymbol
|
|
148
|
+
}),
|
|
144
149
|
tickets: Array.isArray(order.tickets) ? order.tickets : [],
|
|
145
150
|
source_shop: [],
|
|
146
151
|
refund_data: [],
|
|
@@ -161,12 +166,15 @@ function buildBaseData(params) {
|
|
|
161
166
|
order_number: orderNumber,
|
|
162
167
|
shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
|
|
163
168
|
shop_phone: stringify(shopInfo.phone || order.shop_phone),
|
|
164
|
-
shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
169
|
+
shop_address: stringify(shopInfo.receipt_address || shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
165
170
|
original_payment_status: stringify(order.payment_status),
|
|
166
171
|
is_repeat: 0,
|
|
167
172
|
buzzer: stringify(order.buzzer || order.pickup_number || order.metadata?.buzzer),
|
|
168
173
|
order_no: orderNumber,
|
|
169
|
-
order_time: formatDateTime(order.created_at || order.sales_time || new Date(), locale)
|
|
174
|
+
order_time: formatDateTime(order.created_at || order.sales_time || new Date(), locale),
|
|
175
|
+
...(isPresentId(order.updated_at) ? {
|
|
176
|
+
updated_at: formatDateTime(order.updated_at, locale)
|
|
177
|
+
} : {})
|
|
170
178
|
};
|
|
171
179
|
}
|
|
172
180
|
function buildProducts(order, locale, productMap) {
|
|
@@ -200,6 +208,8 @@ function buildProducts(order, locale, productMap) {
|
|
|
200
208
|
parentProduct,
|
|
201
209
|
locale
|
|
202
210
|
});
|
|
211
|
+
const productUid = firstPresentValue(product.metadata?.unique_identification_number, product.unique_identification_number);
|
|
212
|
+
const bookingUid = firstPresentValue(product.booking_uid, product.metadata?.booking_uid);
|
|
203
213
|
const extensionList = buildProductExtensionList({
|
|
204
214
|
product,
|
|
205
215
|
locale,
|
|
@@ -214,6 +224,12 @@ function buildProducts(order, locale, productMap) {
|
|
|
214
224
|
original_price: formatMoney(originalPrice, currencySymbol),
|
|
215
225
|
total_original_price: formatMoney(new _decimal.default(toMoneyNumber(originalPrice)).mul(quantity), currencySymbol),
|
|
216
226
|
extension_list: extensionList,
|
|
227
|
+
...(isPresentId(productUid) ? {
|
|
228
|
+
product_uid: productUid
|
|
229
|
+
} : {}),
|
|
230
|
+
...(isPresentId(bookingUid) ? {
|
|
231
|
+
booking_uid: bookingUid
|
|
232
|
+
} : {}),
|
|
217
233
|
...(options.length ? {
|
|
218
234
|
options
|
|
219
235
|
} : {}),
|
|
@@ -579,6 +595,9 @@ function isNonZeroId(value) {
|
|
|
579
595
|
function isPresentId(value) {
|
|
580
596
|
return value !== undefined && value !== null && value !== '';
|
|
581
597
|
}
|
|
598
|
+
function firstPresentValue(...values) {
|
|
599
|
+
return values.find(value => isPresentId(value));
|
|
600
|
+
}
|
|
582
601
|
function isSameId(left, right) {
|
|
583
602
|
if (!isPresentId(left) || !isPresentId(right)) return false;
|
|
584
603
|
return String(left) === String(right);
|
|
@@ -647,12 +666,13 @@ function buildFees(params) {
|
|
|
647
666
|
});
|
|
648
667
|
}
|
|
649
668
|
const productExpectAmount = summary.product_expect_amount || summary.product_amount || order.product_expect_amount;
|
|
650
|
-
const productOriginalAmount = summary.product_original_amount
|
|
669
|
+
const productOriginalAmount = firstPresentValue(summary.product_original_amount, order.product_original_amount) ?? calculateProductOriginalAmount(order);
|
|
651
670
|
const totalSavingsAmount = new _decimal.default(toMoneyNumber(productOriginalAmount)).minus(toMoneyNumber(productExpectAmount)).plus(toMoneyNumber(discountAmount));
|
|
652
671
|
return {
|
|
653
672
|
fees,
|
|
654
673
|
countFee: {
|
|
655
674
|
total_amount: formatMoney(summary.total_amount || order.total_amount, currencySymbol),
|
|
675
|
+
original_item_amount: formatMoney(productOriginalAmount, currencySymbol),
|
|
656
676
|
product_expect_amount: formatMoney(productExpectAmount, currencySymbol),
|
|
657
677
|
expect_amount: formatMoney(summary.expect_amount || order.expect_amount || summary.total_amount || order.total_amount, currencySymbol),
|
|
658
678
|
product_quantity: toNumber(summary.product_quantity || products.reduce((sum, product) => sum + product.product_quantity, 0), 0),
|
|
@@ -675,6 +695,13 @@ function buildFees(params) {
|
|
|
675
695
|
}
|
|
676
696
|
};
|
|
677
697
|
}
|
|
698
|
+
function calculateProductOriginalAmount(order) {
|
|
699
|
+
return normalizeArray(order.products).reduce((total, product) => {
|
|
700
|
+
const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
|
|
701
|
+
const originalPrice = product.original_price ?? product.selling_price ?? product.payment_price ?? product.price ?? 0;
|
|
702
|
+
return total.plus(new _decimal.default(toMoneyNumber(originalPrice)).mul(quantity));
|
|
703
|
+
}, new _decimal.default(0));
|
|
704
|
+
}
|
|
678
705
|
function buildCustomer(order, locale) {
|
|
679
706
|
return [{
|
|
680
707
|
item: label(locale, 'contactName'),
|
|
@@ -712,6 +739,27 @@ function buildDelivery(order, locale) {
|
|
|
712
739
|
return items;
|
|
713
740
|
}
|
|
714
741
|
function buildAppointment(order, locale) {
|
|
742
|
+
const bookings = normalizeArray(order.bookings);
|
|
743
|
+
if (bookings.length) {
|
|
744
|
+
return bookings.map(booking => {
|
|
745
|
+
const snapshot = {
|
|
746
|
+
...booking
|
|
747
|
+
};
|
|
748
|
+
delete snapshot.product_uid;
|
|
749
|
+
delete snapshot.booking_uid;
|
|
750
|
+
const productUid = firstPresentValue(booking.product_uid, booking.metadata?.product_uid);
|
|
751
|
+
const bookingUid = firstPresentValue(booking.metadata?.unique_identification_number, booking.booking_uid);
|
|
752
|
+
return {
|
|
753
|
+
...snapshot,
|
|
754
|
+
...(isPresentId(productUid) ? {
|
|
755
|
+
product_uid: productUid
|
|
756
|
+
} : {}),
|
|
757
|
+
...(isPresentId(bookingUid) ? {
|
|
758
|
+
booking_uid: bookingUid
|
|
759
|
+
} : {})
|
|
760
|
+
};
|
|
761
|
+
});
|
|
762
|
+
}
|
|
715
763
|
const tableName = order.table_name || order.metadata?.table_name || order.metadata?.table?.name || order.form_data?.table_name;
|
|
716
764
|
if (!tableName) return [];
|
|
717
765
|
return [{
|
|
@@ -729,41 +777,63 @@ function buildResources(order, locale) {
|
|
|
729
777
|
}
|
|
730
778
|
function buildPaymentData(params) {
|
|
731
779
|
const payments = normalizeArray(params.order.payments);
|
|
732
|
-
return payments.filter(payment => isPrintablePayment(payment)).map(payment => {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
780
|
+
return payments.filter(payment => isPrintablePayment(payment)).map(payment => buildPaymentItems({
|
|
781
|
+
payment,
|
|
782
|
+
locale: params.locale,
|
|
783
|
+
currencySymbol: params.currencySymbol,
|
|
784
|
+
includeFundRecordBalance: false
|
|
785
|
+
}));
|
|
786
|
+
}
|
|
787
|
+
function buildWallets(params) {
|
|
788
|
+
return normalizeArray(params.order.payments).filter(payment => isPrintablePayment(payment) && !!getFundRecord(payment)).map(payment => buildPaymentItems({
|
|
789
|
+
payment,
|
|
790
|
+
locale: params.locale,
|
|
791
|
+
currencySymbol: params.currencySymbol,
|
|
792
|
+
includeFundRecordBalance: true
|
|
793
|
+
}));
|
|
794
|
+
}
|
|
795
|
+
function buildPaymentItems(params) {
|
|
796
|
+
const {
|
|
797
|
+
payment,
|
|
798
|
+
locale,
|
|
799
|
+
currencySymbol,
|
|
800
|
+
includeFundRecordBalance
|
|
801
|
+
} = params;
|
|
802
|
+
const items = [{
|
|
803
|
+
item: paymentMethodName(payment, locale),
|
|
804
|
+
value: formatMoney(payment.amount ?? payment.origin_amount, currencySymbol)
|
|
805
|
+
}];
|
|
806
|
+
const fundRecord = getFundRecord(payment);
|
|
807
|
+
if (fundRecord) {
|
|
808
|
+
items.push(...buildFundRecordPaymentItems({
|
|
809
|
+
payment,
|
|
810
|
+
fundRecord,
|
|
811
|
+
locale,
|
|
812
|
+
currencySymbol,
|
|
813
|
+
includeBalance: includeFundRecordBalance
|
|
814
|
+
}));
|
|
815
|
+
} else {
|
|
816
|
+
const remainingAmount = payment.remaining_amount ?? payment.balance ?? payment.metadata?.remaining_amount;
|
|
817
|
+
if (remainingAmount !== undefined && remainingAmount !== null) {
|
|
818
|
+
items.push({
|
|
819
|
+
item: label(locale, 'remainingAmount'),
|
|
820
|
+
value: formatMoney(remainingAmount, currencySymbol)
|
|
821
|
+
});
|
|
753
822
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
return items;
|
|
823
|
+
}
|
|
824
|
+
items.push({
|
|
825
|
+
item: formatDateTime(payment.paid_at || payment.created_at || payment.updated_at || new Date(), locale),
|
|
826
|
+
value: ''
|
|
759
827
|
});
|
|
828
|
+
return items;
|
|
760
829
|
}
|
|
761
830
|
function buildFundRecordPaymentItems(params) {
|
|
762
831
|
const {
|
|
763
832
|
payment,
|
|
764
833
|
fundRecord,
|
|
765
834
|
locale,
|
|
766
|
-
currencySymbol
|
|
835
|
+
currencySymbol,
|
|
836
|
+
includeBalance
|
|
767
837
|
} = params;
|
|
768
838
|
const items = [];
|
|
769
839
|
const usingBeforeValue = fundRecord.using_before_value;
|
|
@@ -774,13 +844,15 @@ function buildFundRecordPaymentItems(params) {
|
|
|
774
844
|
item: label(locale, 'redeemPoints'),
|
|
775
845
|
value: trimDecimal(usedPoints)
|
|
776
846
|
});
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
847
|
+
if (includeBalance) {
|
|
848
|
+
items.push({
|
|
849
|
+
item: label(locale, 'remainingPoints'),
|
|
850
|
+
value: trimDecimal(new _decimal.default(toMoneyNumber(usingAfterValue)))
|
|
851
|
+
});
|
|
852
|
+
}
|
|
781
853
|
return items;
|
|
782
854
|
}
|
|
783
|
-
if (usingAfterValue !== undefined && usingAfterValue !== null) {
|
|
855
|
+
if (includeBalance && usingAfterValue !== undefined && usingAfterValue !== null) {
|
|
784
856
|
items.push({
|
|
785
857
|
item: label(locale, 'remainingAmount'),
|
|
786
858
|
value: formatMoney(usingAfterValue, currencySymbol)
|
|
@@ -136,6 +136,13 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
136
136
|
private getAuthoritativeBundleUnitPrice;
|
|
137
137
|
private mergeProductForPriceQuery;
|
|
138
138
|
protected getSubmitOrderSalesChannel(): string | undefined;
|
|
139
|
+
/** Subclasses with target-scoped OpenData override this guard before reusing the cache. */
|
|
140
|
+
protected isInvoiceOpenDataCacheCurrent(): boolean;
|
|
141
|
+
private getFulfillmentRefModeConfigs;
|
|
142
|
+
private getFulfillmentRefMode;
|
|
143
|
+
private getCachedInvoiceLayoutConfig;
|
|
144
|
+
private getCachedInvoiceTemplateSettings;
|
|
145
|
+
private buildSubmitPayloadEnhancerWithOpenDataConfig;
|
|
139
146
|
/**
|
|
140
147
|
* 工厂入口:根据子模块名实例化对应模块。
|
|
141
148
|
* 默认使用 BookingByStep 公共 `createModule`。子类若需引入额外类型(如 customer),
|
|
@@ -35,6 +35,9 @@ var _transformBaseProductToOrderProduct = require("./utils/transformBaseProductT
|
|
|
35
35
|
var _quotationPrice = require("./utils/quotationPrice");
|
|
36
36
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
37
37
|
const SERVER_ORDER_CHANGED_EVENT = 'order:onOrdersChanged';
|
|
38
|
+
const OS_FULFILLMENT_REF_MODE_FIELD = '_os_fulfillment_ref_mode';
|
|
39
|
+
const OS_INVOICE_LAYOUT_CONFIG_FIELD = '_os_invoice_layout_config';
|
|
40
|
+
const OS_INVOICE_TEMPLATE_SETTINGS_FIELD = '_os_invoice_template_settings';
|
|
38
41
|
const WALLET_PAYMENT_CODE_BY_TAG = {
|
|
39
42
|
product_voucher: 'PRODUCTVOUCHER',
|
|
40
43
|
gift_card: 'GIFTCARD',
|
|
@@ -847,6 +850,73 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
847
850
|
return this.otherParams?.channel;
|
|
848
851
|
}
|
|
849
852
|
|
|
853
|
+
/** Subclasses with target-scoped OpenData override this guard before reusing the cache. */
|
|
854
|
+
isInvoiceOpenDataCacheCurrent() {
|
|
855
|
+
return true;
|
|
856
|
+
}
|
|
857
|
+
getFulfillmentRefModeConfigs() {
|
|
858
|
+
const candidates = [this.otherParams?.openData, this.otherParams?.dineInConfig, this.store?.openData?.getOpenData?.()];
|
|
859
|
+
return candidates.filter(candidate => candidate && typeof candidate === 'object' && !Array.isArray(candidate));
|
|
860
|
+
}
|
|
861
|
+
getFulfillmentRefMode() {
|
|
862
|
+
for (const config of this.getFulfillmentRefModeConfigs()) {
|
|
863
|
+
const mode = config['fulfillment.fulfillment_ref_mode'];
|
|
864
|
+
if (mode === undefined || mode === null) continue;
|
|
865
|
+
const normalized = String(mode).trim();
|
|
866
|
+
if (normalized) return normalized;
|
|
867
|
+
}
|
|
868
|
+
return undefined;
|
|
869
|
+
}
|
|
870
|
+
getCachedInvoiceLayoutConfig() {
|
|
871
|
+
const openDataModule = this.store?.openData;
|
|
872
|
+
if (typeof openDataModule?.getInvoiceLayoutConfig !== 'function') return undefined;
|
|
873
|
+
if (!this.isInvoiceOpenDataCacheCurrent()) return undefined;
|
|
874
|
+
try {
|
|
875
|
+
return openDataModule.getInvoiceLayoutConfig();
|
|
876
|
+
} catch (error) {
|
|
877
|
+
this.logWarning('读取 Invoice OpenData 布局失败,提交时不注入布局配置', {
|
|
878
|
+
error: error instanceof Error ? error.message : String(error)
|
|
879
|
+
});
|
|
880
|
+
return undefined;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
getCachedInvoiceTemplateSettings() {
|
|
884
|
+
const openDataModule = this.store?.openData;
|
|
885
|
+
if (typeof openDataModule?.getInvoiceTemplateSettings !== 'function') return undefined;
|
|
886
|
+
if (!this.isInvoiceOpenDataCacheCurrent()) return undefined;
|
|
887
|
+
try {
|
|
888
|
+
return openDataModule.getInvoiceTemplateSettings();
|
|
889
|
+
} catch (error) {
|
|
890
|
+
this.logWarning('读取 Invoice OpenData 模板配置失败,提交时不注入模板配置', {
|
|
891
|
+
error: error instanceof Error ? error.message : String(error)
|
|
892
|
+
});
|
|
893
|
+
return undefined;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
buildSubmitPayloadEnhancerWithOpenDataConfig(enhancePayload) {
|
|
897
|
+
const fulfillmentRefMode = this.getFulfillmentRefMode();
|
|
898
|
+
const invoiceLayoutConfig = this.getCachedInvoiceLayoutConfig();
|
|
899
|
+
const invoiceTemplateSettings = this.getCachedInvoiceTemplateSettings();
|
|
900
|
+
if (!fulfillmentRefMode && !invoiceLayoutConfig && !invoiceTemplateSettings) {
|
|
901
|
+
return enhancePayload;
|
|
902
|
+
}
|
|
903
|
+
return (payload, ctx) => {
|
|
904
|
+
const enhancedPayload = enhancePayload ? enhancePayload(payload, ctx) : payload;
|
|
905
|
+
return {
|
|
906
|
+
...enhancedPayload,
|
|
907
|
+
...(fulfillmentRefMode ? {
|
|
908
|
+
[OS_FULFILLMENT_REF_MODE_FIELD]: fulfillmentRefMode
|
|
909
|
+
} : {}),
|
|
910
|
+
...(invoiceLayoutConfig ? {
|
|
911
|
+
[OS_INVOICE_LAYOUT_CONFIG_FIELD]: (0, _lodashEs.cloneDeep)(invoiceLayoutConfig)
|
|
912
|
+
} : {}),
|
|
913
|
+
...(invoiceTemplateSettings ? {
|
|
914
|
+
[OS_INVOICE_TEMPLATE_SETTINGS_FIELD]: (0, _lodashEs.cloneDeep)(invoiceTemplateSettings)
|
|
915
|
+
} : {})
|
|
916
|
+
};
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
|
|
850
920
|
/**
|
|
851
921
|
* 工厂入口:根据子模块名实例化对应模块。
|
|
852
922
|
* 默认使用 BookingByStep 公共 `createModule`。子类若需引入额外类型(如 customer),
|
|
@@ -1442,9 +1512,20 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1442
1512
|
if (!params.products.length) return false;
|
|
1443
1513
|
const hasDraftProduct = params.products.some(product => !this.isPersistedOrderProduct(product));
|
|
1444
1514
|
if (hasDraftProduct) return false;
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1515
|
+
|
|
1516
|
+
// 编辑详情 hydrate 时,商品行上的历史券卡会被还原为 isEditMode=true、
|
|
1517
|
+
// isSelected=true 的只读记录。它们表示“该折扣已在原订单结算”,不是用户在
|
|
1518
|
+
// 当前编辑会话中新做的选择,不能据此放行刚从 prepare/config 拉回来的折扣。
|
|
1519
|
+
// 否则后续 Rules.calcDiscount 会把没有 isManualSelect 标记的可用 runtime 卡
|
|
1520
|
+
// 当作自动候选,再次写入 tempOrder。这里只识别非 isEditMode 的 runtime 状态;
|
|
1521
|
+
// 新建单、编辑态新增商品以及用户本次明确选择/取消折扣的原有流程保持不变。
|
|
1522
|
+
const hasRuntimeDiscountSelection = params.currentDiscountList.some(discount => !discount.isEditMode && (discount.isSelected || discount.isManualSelect));
|
|
1523
|
+
if (hasRuntimeDiscountSelection) return false;
|
|
1524
|
+
|
|
1525
|
+
// nextDiscountList 已经合并了历史只读折扣与本次获取的 runtime 折扣,
|
|
1526
|
+
// 因此这里同样必须排除 isEditMode;只有 runtime 条目已有明确选择状态时,
|
|
1527
|
+
// 才允许继续进入折扣重算。
|
|
1528
|
+
return !params.nextDiscountList.some(discount => !discount.isEditMode && (discount.isSelected || discount.isManualSelect));
|
|
1448
1529
|
}
|
|
1449
1530
|
mergeCurrentDiscountSelectionState(discountList, currentDiscountList) {
|
|
1450
1531
|
if (!currentDiscountList.length) return discountList;
|
|
@@ -1989,6 +2070,26 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1989
2070
|
// this.store.order.persistTempOrder();
|
|
1990
2071
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
1991
2072
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2073
|
+
const virtualSettlementEnhancePayload = virtualSettlement ? (payload, ctx) => {
|
|
2074
|
+
const callerPayload = params?.enhancePayload ? params.enhancePayload(payload, ctx) : payload;
|
|
2075
|
+
const currencySettlementConfig = callerPayload.metadata?.currency_settlement_config || {};
|
|
2076
|
+
return {
|
|
2077
|
+
...callerPayload,
|
|
2078
|
+
metadata: {
|
|
2079
|
+
...(callerPayload.metadata || {}),
|
|
2080
|
+
currency_settlement_config: {
|
|
2081
|
+
...currencySettlementConfig,
|
|
2082
|
+
settlement_type: 'virtual_currency',
|
|
2083
|
+
settlement_ids: [virtualSettlement.currencyProductId],
|
|
2084
|
+
currency_display_snapshot: (0, _lodashEs.cloneDeep)(currencySettlementConfig.currency_display_snapshot ?? (0, _virtualSettlement.buildCurrencyDisplaySnapshot)(virtualSettlement.snapshot))
|
|
2085
|
+
}
|
|
2086
|
+
},
|
|
2087
|
+
currency_code: virtualSettlement.currencyCode,
|
|
2088
|
+
currency_symbol: virtualSettlement.currencySymbol,
|
|
2089
|
+
currency_format: virtualSettlement.currencyFormat
|
|
2090
|
+
};
|
|
2091
|
+
} : params?.enhancePayload;
|
|
2092
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(virtualSettlementEnhancePayload);
|
|
1992
2093
|
const submitParams = {
|
|
1993
2094
|
cacheId: this.cacheId,
|
|
1994
2095
|
platform: this.otherParams?.platform,
|
|
@@ -2012,28 +2113,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2012
2113
|
} : params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2013
2114
|
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2014
2115
|
} : {}),
|
|
2015
|
-
...(
|
|
2016
|
-
enhancePayload
|
|
2017
|
-
const callerPayload = params?.enhancePayload ? params.enhancePayload(payload, ctx) : payload;
|
|
2018
|
-
const currencySettlementConfig = callerPayload.metadata?.currency_settlement_config || {};
|
|
2019
|
-
return {
|
|
2020
|
-
...callerPayload,
|
|
2021
|
-
metadata: {
|
|
2022
|
-
...(callerPayload.metadata || {}),
|
|
2023
|
-
currency_settlement_config: {
|
|
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))
|
|
2028
|
-
}
|
|
2029
|
-
},
|
|
2030
|
-
currency_code: virtualSettlement.currencyCode,
|
|
2031
|
-
currency_symbol: virtualSettlement.currencySymbol,
|
|
2032
|
-
currency_format: virtualSettlement.currencyFormat
|
|
2033
|
-
};
|
|
2034
|
-
}
|
|
2035
|
-
} : params?.enhancePayload !== undefined ? {
|
|
2036
|
-
enhancePayload: params.enhancePayload
|
|
2116
|
+
...(enhancePayload !== undefined ? {
|
|
2117
|
+
enhancePayload
|
|
2037
2118
|
} : {})
|
|
2038
2119
|
};
|
|
2039
2120
|
return this.shouldUseCheckoutSyncTask() ? this.store.order.submitTempOrder(submitParams) : this.store.order.submitTempOrderAsync(submitParams);
|
|
@@ -2059,6 +2140,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2059
2140
|
}
|
|
2060
2141
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2061
2142
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2143
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params?.enhancePayload);
|
|
2062
2144
|
const submitParams = {
|
|
2063
2145
|
cacheId: this.cacheId,
|
|
2064
2146
|
platform: this.otherParams?.platform,
|
|
@@ -2078,8 +2160,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2078
2160
|
...(params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2079
2161
|
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2080
2162
|
} : {}),
|
|
2081
|
-
...(
|
|
2082
|
-
enhancePayload
|
|
2163
|
+
...(enhancePayload !== undefined ? {
|
|
2164
|
+
enhancePayload
|
|
2083
2165
|
} : {})
|
|
2084
2166
|
};
|
|
2085
2167
|
return this.store.order.submitTempOrderAsync(submitParams);
|
|
@@ -2129,7 +2211,18 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2129
2211
|
channel: context.channel,
|
|
2130
2212
|
type: context.type
|
|
2131
2213
|
});
|
|
2132
|
-
const
|
|
2214
|
+
const invoiceLayoutConfig = this.getCachedInvoiceLayoutConfig();
|
|
2215
|
+
const invoiceTemplateSettings = this.getCachedInvoiceTemplateSettings();
|
|
2216
|
+
const printPayload = {
|
|
2217
|
+
...payload,
|
|
2218
|
+
...(invoiceLayoutConfig ? {
|
|
2219
|
+
invoice: (0, _lodashEs.cloneDeep)(invoiceLayoutConfig)
|
|
2220
|
+
} : {}),
|
|
2221
|
+
...(invoiceTemplateSettings ? {
|
|
2222
|
+
template_settings: (0, _lodashEs.cloneDeep)(invoiceTemplateSettings)
|
|
2223
|
+
} : {})
|
|
2224
|
+
};
|
|
2225
|
+
const response = await this.request.post('/local/print-order', printPayload, {
|
|
2133
2226
|
osServer: true,
|
|
2134
2227
|
customToast: () => {}
|
|
2135
2228
|
});
|
|
@@ -2152,6 +2245,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2152
2245
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2153
2246
|
const businessCode = params.businessCode ?? this.otherParams?.businessCode ?? this.otherParams?.business_code;
|
|
2154
2247
|
const channel = params.channel ?? this.getSubmitOrderSalesChannel();
|
|
2248
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params.enhancePayload);
|
|
2155
2249
|
const syncParams = {
|
|
2156
2250
|
...params,
|
|
2157
2251
|
checkoutSyncTaskEnabled: this.shouldUseCheckoutSyncTask(),
|
|
@@ -2160,6 +2254,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2160
2254
|
} : {}),
|
|
2161
2255
|
...(channel !== undefined ? {
|
|
2162
2256
|
channel
|
|
2257
|
+
} : {}),
|
|
2258
|
+
...(enhancePayload !== undefined ? {
|
|
2259
|
+
enhancePayload
|
|
2163
2260
|
} : {})
|
|
2164
2261
|
};
|
|
2165
2262
|
const syncState = this.store.order.getOrderSyncState();
|
|
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
326
326
|
date: string;
|
|
327
327
|
status: string;
|
|
328
328
|
week: string;
|
|
329
|
-
weekNum: 0 |
|
|
329
|
+
weekNum: 0 | 1 | 2 | 5 | 4 | 3 | 6;
|
|
330
330
|
}[]>;
|
|
331
331
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
332
332
|
private getScheduleDataByIds;
|
|
@@ -345,7 +345,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
|
|
|
345
345
|
count: number;
|
|
346
346
|
left: number;
|
|
347
347
|
summaryCount: number;
|
|
348
|
-
status: "
|
|
348
|
+
status: "sold_out" | "lots_of_space" | "filling_up_fast";
|
|
349
349
|
}[];
|
|
350
350
|
/**
|
|
351
351
|
* 找到多个资源的公共可用时间段
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Module, ModuleOptions, PisellCore } from '../../types';
|
|
2
2
|
import { BookingTicketCartView, BookingTicketProductCatalogView, BookingTicketState, IGetCustomerListParams, ICustomer, ILoadProductsParams, ILoadProductDetailParams, IScanResult } from './types';
|
|
3
3
|
import type { ProductData } from '../../modules';
|
|
4
|
-
import type
|
|
4
|
+
import { type InvoiceLayoutConfig, type InvoiceTemplateSettings, type OpenDataConfig } from '../../modules/OpenData';
|
|
5
5
|
import { type BookingContextConfig, type BookingContextDateInput, type BookingContextResource, type BookingContextResourceMap, type BookingContextState, type InitBookingContextParams, type LoadBookingConfigParams, type LoadBookingResourcesParams, type ResourceError, type BookingCalcContext } from '../../modules/BookingContext';
|
|
6
|
-
import type { OrderCustomerView } from '../../modules/Order/types';
|
|
6
|
+
import type { OrderCustomerView, OrderCustomerChangePayload } from '../../modules/Order/types';
|
|
7
7
|
import { BaseSalesImpl } from '../BaseSales';
|
|
8
8
|
import type { BaseSalesScanCodeResult } from '../BaseSales/types';
|
|
9
9
|
import type { ISalesDetail } from '../BaseSales/utils/parseSalesResponse';
|
|
@@ -30,7 +30,9 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
30
30
|
private orderCustomerDiscountRefreshInFlight;
|
|
31
31
|
private orderCustomerDiscountRefreshCustomerId;
|
|
32
32
|
private orderCustomerPromotionRefreshInFlight;
|
|
33
|
-
|
|
33
|
+
protected loadOpenDataInFlight: Promise<OpenDataConfig> | null;
|
|
34
|
+
protected loadOpenDataInFlightTarget: string | null;
|
|
35
|
+
protected openDataTarget: string | null;
|
|
34
36
|
/**
|
|
35
37
|
* 在 BaseSales 默认模块清单(products/order/salesSummary/schedule)基础上追加 customer + bookingContext。
|
|
36
38
|
* bookingContext 是 SalesSdk 加车下沉所需的「预约 UI 上下文」(bookingConfig / resourcesOrigin / date)。
|
|
@@ -43,10 +45,13 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
43
45
|
*/
|
|
44
46
|
protected createSubModule(moduleName: string): Module | null;
|
|
45
47
|
initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
|
|
46
|
-
|
|
48
|
+
protected getBookingTicketBusinessCode(): string | null;
|
|
47
49
|
private getIdGeneratorPlugin;
|
|
48
50
|
private loadOpenDataConfig;
|
|
49
51
|
getOpenData(): Promise<OpenDataConfig | null>;
|
|
52
|
+
getInvoiceLayoutConfig(): Promise<InvoiceLayoutConfig>;
|
|
53
|
+
getInvoiceTemplateSettings(): Promise<InvoiceTemplateSettings>;
|
|
54
|
+
protected isInvoiceOpenDataCacheCurrent(): boolean;
|
|
50
55
|
/** 清除店铺级 OpenData;下一次 getOpenData 时会重新拉取。 */
|
|
51
56
|
clearOpenDataCache(): void;
|
|
52
57
|
private getShortNumberOrDeviceId;
|
|
@@ -260,7 +265,9 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
260
265
|
* 同时透传 OrderModule 内部 emit 的 `order:onOrderCustomerChange` 之外,
|
|
261
266
|
* 在 BookingTicket 命名空间也 emit 一次,方便上层统一从 Solution 订阅。
|
|
262
267
|
*/
|
|
263
|
-
setOrderCustomer(customer: ICustomer | null
|
|
268
|
+
setOrderCustomer(customer: ICustomer | null, options?: {
|
|
269
|
+
source?: OrderCustomerChangePayload['source'];
|
|
270
|
+
}): void;
|
|
264
271
|
/**
|
|
265
272
|
* 读取 tempOrder 上的下单客户协议字段;customer_id 缺失时返回 null。
|
|
266
273
|
*/
|
|
@@ -332,7 +339,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
332
339
|
* 获取当前的客户搜索条件
|
|
333
340
|
* @returns 当前搜索条件
|
|
334
341
|
*/
|
|
335
|
-
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "
|
|
342
|
+
getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
|
|
336
343
|
/**
|
|
337
344
|
* 获取客户列表状态(包含滚动加载相关状态)
|
|
338
345
|
* @returns 客户状态
|
|
@@ -451,19 +458,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
|
|
|
451
458
|
* 加车两阶段主决策(规格弹窗 / 资源编辑 / 直接加车)。
|
|
452
459
|
* 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
|
|
453
460
|
*/
|
|
454
|
-
decideAddProduct(item: any, options?: Partial<AddProductDecideContext>):
|
|
455
|
-
action: "reloadCatalog";
|
|
456
|
-
} | {
|
|
457
|
-
action: "add";
|
|
458
|
-
cacheItem: any;
|
|
459
|
-
} | {
|
|
460
|
-
action: "requiresDetail";
|
|
461
|
-
payload: AddProductRequiresDetailPayload;
|
|
462
|
-
} | {
|
|
463
|
-
action: "requiresBookingEdit";
|
|
464
|
-
cacheItem: any;
|
|
465
|
-
payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
|
|
466
|
-
};
|
|
461
|
+
decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
|
|
467
462
|
/** 规格弹窗 callback 后的第二段决策。 */
|
|
468
463
|
decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
|
|
469
464
|
/**
|