@pisell/pisellos 2.3.164 → 2.3.166
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/evaluator.js +89 -104
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +3 -1
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +28 -4
- package/dist/modules/Holder/utils.d.ts +2 -0
- package/dist/modules/Holder/utils.js +32 -2
- package/dist/modules/OpenData/contactInfo.d.ts +20 -0
- package/dist/modules/OpenData/contactInfo.js +70 -0
- package/dist/modules/OpenData/index.d.ts +1 -0
- package/dist/modules/OpenData/index.js +1 -0
- package/dist/modules/OpenData/types.d.ts +9 -0
- package/dist/modules/Order/holderRelations.d.ts +14 -0
- package/dist/modules/Order/holderRelations.js +154 -0
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +89 -44
- package/dist/modules/Order/types.d.ts +19 -1
- package/dist/modules/Order/types.js +2 -0
- package/dist/modules/Order/utils/discountProductLineIdentity.d.ts +1 -1
- package/dist/modules/Order/utils/discountProductLineIdentity.js +142 -7
- package/dist/modules/Order/utils/orderCollectionIdentity.js +24 -10
- package/dist/modules/Order/utils.d.ts +1 -1
- package/dist/modules/Order/utils.js +35 -9
- package/dist/modules/Rules/index.js +62 -61
- package/dist/server/index.js +18 -12
- package/dist/server/modules/order/index.d.ts +4 -0
- package/dist/server/modules/order/index.js +255 -190
- package/dist/server/modules/order/types.d.ts +3 -0
- package/dist/server/modules/products/index.js +3 -2
- package/dist/shared/receipt/small-ticket.js +17 -6
- package/dist/shared/sales/loadSalesOrderSnapshot.js +1 -1
- package/dist/solution/BaseSales/index.d.ts +4 -0
- package/dist/solution/BaseSales/index.js +1116 -935
- package/dist/solution/BaseSales/types.d.ts +2 -1
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -1
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +7 -3
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +14 -4
- package/dist/solution/BookingTicket/index.d.ts +15 -1
- package/dist/solution/BookingTicket/index.js +784 -501
- package/dist/solution/UnifiedBookingSales/index.js +1 -1
- package/lib/model/strategy/adapter/promotion/evaluator.js +9 -14
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +3 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +17 -1
- package/lib/modules/Holder/utils.d.ts +2 -0
- package/lib/modules/Holder/utils.js +27 -1
- package/lib/modules/OpenData/contactInfo.d.ts +20 -0
- package/lib/modules/OpenData/contactInfo.js +56 -0
- package/lib/modules/OpenData/index.d.ts +1 -0
- package/lib/modules/OpenData/index.js +12 -0
- package/lib/modules/OpenData/types.d.ts +9 -0
- package/lib/modules/Order/holderRelations.d.ts +14 -0
- package/lib/modules/Order/holderRelations.js +98 -0
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +44 -12
- package/lib/modules/Order/types.d.ts +19 -1
- package/lib/modules/Order/types.js +1 -0
- package/lib/modules/Order/utils/discountProductLineIdentity.d.ts +1 -1
- package/lib/modules/Order/utils/discountProductLineIdentity.js +51 -2
- package/lib/modules/Order/utils/orderCollectionIdentity.js +5 -0
- package/lib/modules/Order/utils.d.ts +1 -1
- package/lib/modules/Order/utils.js +27 -6
- package/lib/modules/Rules/index.js +2 -1
- package/lib/server/index.js +6 -0
- package/lib/server/modules/order/index.d.ts +4 -0
- package/lib/server/modules/order/index.js +46 -4
- package/lib/server/modules/order/types.d.ts +3 -0
- package/lib/server/modules/products/index.js +2 -1
- package/lib/shared/receipt/small-ticket.js +15 -7
- package/lib/shared/sales/loadSalesOrderSnapshot.js +1 -1
- package/lib/solution/BaseSales/index.d.ts +4 -0
- package/lib/solution/BaseSales/index.js +68 -2
- package/lib/solution/BaseSales/types.d.ts +2 -1
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -1
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +16 -8
- package/lib/solution/BookingTicket/index.d.ts +15 -1
- package/lib/solution/BookingTicket/index.js +132 -3
- package/lib/solution/UnifiedBookingSales/index.js +1 -1
- package/package.json +1 -1
|
@@ -243,6 +243,11 @@ export interface OrderProduct extends OrderProductIdentity {
|
|
|
243
243
|
product_cover?: string;
|
|
244
244
|
metadata: Record<string, any>;
|
|
245
245
|
note?: string;
|
|
246
|
+
/** 仅作按行更新输入;正式数据保存于订单顶层。 */
|
|
247
|
+
_extend?: {
|
|
248
|
+
holder_relations?: OrderHolderRelation[];
|
|
249
|
+
[key: string]: any;
|
|
250
|
+
};
|
|
246
251
|
}
|
|
247
252
|
export interface OrderSummary {
|
|
248
253
|
product_quantity: number;
|
|
@@ -340,6 +345,17 @@ export interface SalesNotesMutationSnapshot {
|
|
|
340
345
|
}
|
|
341
346
|
export type SalesNoteProtocolRelation = SalesNoteRelation;
|
|
342
347
|
export type SalesNoteProtocol = SalesNote;
|
|
348
|
+
/** 后端关系及 metadata 均为开放对象,未知字段必须往返保留。 */
|
|
349
|
+
export interface OrderHolderRelation {
|
|
350
|
+
/** 关系自身的 UUID;新选择/旧草稿可缺省,入单与提交时由 OS 补齐。 */
|
|
351
|
+
uuid?: string;
|
|
352
|
+
relation_model: string;
|
|
353
|
+
relation_uuid: string;
|
|
354
|
+
holder_type: 'form' | 'customer';
|
|
355
|
+
holder_id: number;
|
|
356
|
+
metadata?: Record<string, any>;
|
|
357
|
+
[key: string]: any;
|
|
358
|
+
}
|
|
343
359
|
export interface OrderTempOrder {
|
|
344
360
|
order_id: number | null;
|
|
345
361
|
external_sale_number: string;
|
|
@@ -379,6 +395,7 @@ export interface OrderTempOrder {
|
|
|
379
395
|
created_at: string | undefined;
|
|
380
396
|
request_unique_idempotency_token?: string;
|
|
381
397
|
products: OrderProduct[];
|
|
398
|
+
holder_relations?: OrderHolderRelation[];
|
|
382
399
|
notes: SalesNote[];
|
|
383
400
|
bookings: any[];
|
|
384
401
|
payments: any[];
|
|
@@ -398,7 +415,7 @@ export interface OrderTempOrder {
|
|
|
398
415
|
[key: string]: any;
|
|
399
416
|
};
|
|
400
417
|
}
|
|
401
|
-
export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identification_number' | 'num'> {
|
|
418
|
+
export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identification_number' | 'num' | '_extend'> {
|
|
402
419
|
product_quantity: number;
|
|
403
420
|
payment_price: string;
|
|
404
421
|
product_sku: OrderProductSku;
|
|
@@ -607,6 +624,7 @@ export interface SubmitSalesOrderParams {
|
|
|
607
624
|
schedule_date: string;
|
|
608
625
|
created_at?: string | undefined;
|
|
609
626
|
products: OrderSubmitProduct[];
|
|
627
|
+
holder_relations?: OrderHolderRelation[];
|
|
610
628
|
bookings: OrderSubmitBooking[];
|
|
611
629
|
payments: any[];
|
|
612
630
|
vouchers: any[];
|
|
@@ -63,6 +63,7 @@ let OrderHooks = exports.OrderHooks = /*#__PURE__*/function (OrderHooks) {
|
|
|
63
63
|
* Sales Notes 乐观写入前的可恢复快照。
|
|
64
64
|
* 该对象应视为 opaque token,只用于原样传回 restoreSalesNotesMutationSnapshot。
|
|
65
65
|
*/
|
|
66
|
+
/** 后端关系及 metadata 均为开放对象,未知字段必须往返保留。 */
|
|
66
67
|
/**
|
|
67
68
|
* 添加商品行时的顺序控制。
|
|
68
69
|
* 默认追加到 products 尾部;预约数量同步可插入到既有预约组的最新行之后,
|
|
@@ -31,7 +31,7 @@ export declare const DISCOUNT_SPLIT_ORIGIN_UID_KEY = "discountSplitOriginUid";
|
|
|
31
31
|
* 没有 UID 的裸商品不会被补写 UID。这是为了兼容 Rules/mock 的历史协议形状;
|
|
32
32
|
* 正常 Order 写路径会在 normalize 阶段提前创建 UID。
|
|
33
33
|
*/
|
|
34
|
-
export declare function ensureUniqueProductLineUids(tempOrder: OrderTempOrder): void;
|
|
34
|
+
export declare function ensureUniqueProductLineUids(tempOrder: OrderTempOrder, discounts?: Array<Record<string, any>>): void;
|
|
35
35
|
/**
|
|
36
36
|
* 把券移除后已经恢复原价的同源折扣拆分行重新合并。
|
|
37
37
|
*
|
|
@@ -9,6 +9,7 @@ exports.ensureUniqueProductLineUids = ensureUniqueProductLineUids;
|
|
|
9
9
|
var _lodashEs = require("lodash-es");
|
|
10
10
|
var _utils = require("../../../solution/ScanOrder/utils");
|
|
11
11
|
var _orderCollectionIdentity = require("./orderCollectionIdentity");
|
|
12
|
+
var _holderRelations = require("../holderRelations");
|
|
12
13
|
/**
|
|
13
14
|
* 商品券拆行的身份与回并工具。
|
|
14
15
|
*
|
|
@@ -72,16 +73,20 @@ function ensureProductsByUid(tempOrder) {
|
|
|
72
73
|
* 没有 UID 的裸商品不会被补写 UID。这是为了兼容 Rules/mock 的历史协议形状;
|
|
73
74
|
* 正常 Order 写路径会在 normalize 阶段提前创建 UID。
|
|
74
75
|
*/
|
|
75
|
-
function ensureUniqueProductLineUids(tempOrder) {
|
|
76
|
+
function ensureUniqueProductLineUids(tempOrder, discounts = []) {
|
|
76
77
|
// usedUids 只描述本次 Rules 返回的商品集合,不能直接依赖 productsByUid:
|
|
77
78
|
// productsByUid 可能还保留已删除行的历史 runtime,历史 UID 不应导致当前行被改号。
|
|
78
79
|
const usedUids = new Set();
|
|
79
80
|
const productsByUid = ensureProductsByUid(tempOrder);
|
|
81
|
+
const splitGroups = new Map();
|
|
80
82
|
tempOrder.products = (tempOrder.products || []).map(product => {
|
|
81
83
|
const sourceUid = getProductLineUid(product);
|
|
82
84
|
// 单测 mock 或兼容旧 Rules 时可能返回没有 UID 的裸商品。
|
|
83
85
|
// 这里不主动补 UID,避免一个“校验重复”的工具意外改变旧协议对象形状。
|
|
84
86
|
if (!sourceUid) return product;
|
|
87
|
+
const group = splitGroups.get(sourceUid) || [];
|
|
88
|
+
group.push(product);
|
|
89
|
+
splitGroups.set(sourceUid, group);
|
|
85
90
|
|
|
86
91
|
// 实际场景:可乐 ×5 首次进入 Rules 时只有一行。
|
|
87
92
|
// 使用三张券后 Rules 可能返回「可乐 ×2 + 三条可乐 ×1」,但四条都复制原 UID。
|
|
@@ -122,6 +127,50 @@ function ensureUniqueProductLineUids(tempOrder) {
|
|
|
122
127
|
usedUids.add(splitUid);
|
|
123
128
|
return product;
|
|
124
129
|
});
|
|
130
|
+
|
|
131
|
+
// 仅按本次券上的明确 Holder 分配迁移。数组顺序不能代表券对应的人。
|
|
132
|
+
// 未能明确分配时保留原 UID,不把整组关系复制给每一个拆分行。
|
|
133
|
+
for (const [sourceUid, products] of splitGroups) {
|
|
134
|
+
if (products.length < 2) continue;
|
|
135
|
+
const relations = (0, _holderRelations.getProductHolderRelations)(tempOrder, {
|
|
136
|
+
metadata: {
|
|
137
|
+
unique_identification_number: sourceUid
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
if (!relations.length || relations.some(relation => relation.holder_type !== 'form')) continue;
|
|
141
|
+
const assignments = new Map();
|
|
142
|
+
let remaining = [...relations];
|
|
143
|
+
let ambiguous = false;
|
|
144
|
+
for (const product of products) {
|
|
145
|
+
const holderIds = new Set();
|
|
146
|
+
for (const item of product.discount_list || []) {
|
|
147
|
+
const discount = discounts.find(candidate => String(candidate.id) === String(item.discount?.resource_id));
|
|
148
|
+
if (discount?.holder?.holder_type !== 'form') continue;
|
|
149
|
+
const value = discount.holder.holder_id;
|
|
150
|
+
(Array.isArray(value) ? value : [value]).forEach(id => {
|
|
151
|
+
const recordId = id && typeof id === 'object' ? id.form_record_id : id;
|
|
152
|
+
if (recordId !== undefined && recordId !== null && recordId !== '') holderIds.add(String(recordId));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (!holderIds.size) continue;
|
|
156
|
+
const assigned = remaining.filter(relation => holderIds.has(String(relation.holder_id)));
|
|
157
|
+
if (assigned.length !== Number(product.num)) {
|
|
158
|
+
ambiguous = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
assignments.set(product, assigned);
|
|
162
|
+
remaining = remaining.filter(relation => !assigned.includes(relation));
|
|
163
|
+
}
|
|
164
|
+
const unassigned = products.filter(product => !assignments.has(product));
|
|
165
|
+
if (ambiguous || unassigned.length > 1) continue;
|
|
166
|
+
if (unassigned.length === 1) {
|
|
167
|
+
if (remaining.length !== Number(unassigned[0].num)) continue;
|
|
168
|
+
assignments.set(unassigned[0], remaining);
|
|
169
|
+
} else if (remaining.length) continue;
|
|
170
|
+
for (const [product, assigned] of assignments) {
|
|
171
|
+
for (const relation of assigned) relation.relation_uuid = String(getProductLineUid(product));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
125
174
|
}
|
|
126
175
|
|
|
127
176
|
/**
|
|
@@ -154,7 +203,7 @@ function consolidateDiscountFreeProductLines(tempOrder) {
|
|
|
154
203
|
// - 手动改价/备注:用户显式表达了不同价格或不同制作要求;
|
|
155
204
|
// - 称重商品:每次称重的净重和金额属于独立交易事实;
|
|
156
205
|
// - 预约/holder/历史订单行:分别关联预约、持有人或后端 order_detail。
|
|
157
|
-
const hasMergeBoundary = hasDiscount || Boolean(product.metadata?._giftInfo || product._giftInfo) || Boolean(product.metadata?._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(product.product_sku?.open_sold_weight || 0) === 1 || product.metadata?.is_edit_for_runtime === true || bookingId !== undefined && bookingId !== null && bookingId !== 0 && bookingId !== '0' || bookingUid !== undefined && bookingUid !== null && String(bookingUid) !== '' || holderId !== undefined && holderId !== null && String(holderId) !== '' || orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '';
|
|
206
|
+
const hasMergeBoundary = hasDiscount || Boolean(product.metadata?._giftInfo || product._giftInfo) || Boolean(product.metadata?._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(product.product_sku?.open_sold_weight || 0) === 1 || product.metadata?.is_edit_for_runtime === true || bookingId !== undefined && bookingId !== null && bookingId !== 0 && bookingId !== '0' || bookingUid !== undefined && bookingUid !== null && String(bookingUid) !== '' || (0, _holderRelations.getProductHolderRelations)(tempOrder, product).length > 0 || holderId !== undefined && holderId !== null && String(holderId) !== '' || orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '';
|
|
158
207
|
if (hasMergeBoundary) {
|
|
159
208
|
consolidatedProducts.push(product);
|
|
160
209
|
continue;
|
|
@@ -331,6 +331,11 @@ function applyOrderCollectionUidRemaps(sourceOrder, uidRemaps) {
|
|
|
331
331
|
}
|
|
332
332
|
// 冲突 UID 仍由第一条持有;赠品父引用缺少可用的持久化行定位时不能全局改写。
|
|
333
333
|
if (remap.scope !== 'linked-owner') {
|
|
334
|
+
for (const relation of order.holder_relations || []) {
|
|
335
|
+
if (relation.relation_model === 'order_detail' && String(relation.relation_uuid) === remap.from) {
|
|
336
|
+
relation.relation_uuid = remap.to;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
334
339
|
for (const product of order.products || []) {
|
|
335
340
|
if (String(product?.metadata?.parent_unique_identification_number || '') === remap.from) {
|
|
336
341
|
product.metadata = {
|
|
@@ -173,7 +173,7 @@ export declare function resolveManualOverrideLineOriginalPrice(params: {
|
|
|
173
173
|
* // => -4
|
|
174
174
|
*/
|
|
175
175
|
export declare function resolveEffectivePerUnitDiscount(product: Record<string, any>): number;
|
|
176
|
-
export declare function createDefaultOrderRulesHooks(getBookings?: () => OrderTempOrder['bookings']): RulesParamsHooks;
|
|
176
|
+
export declare function createDefaultOrderRulesHooks(getBookings?: () => OrderTempOrder['bookings'], getHolderRelations?: () => OrderTempOrder['holder_relations']): RulesParamsHooks;
|
|
177
177
|
/**
|
|
178
178
|
* 通过 session 类商品的开始时间结束时间生成商品的时长
|
|
179
179
|
* @param {CartItem} cartItem
|
|
@@ -129,6 +129,7 @@ Object.defineProperty(exports, "syncManualProductDiscountProductNum", {
|
|
|
129
129
|
return _manualProductDiscount.syncManualProductDiscountProductNum;
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
|
+
var _lodashEs = require("lodash-es");
|
|
132
133
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
133
134
|
var _customParseFormat = _interopRequireDefault(require("dayjs/plugin/customParseFormat"));
|
|
134
135
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
@@ -139,6 +140,7 @@ var _utils2 = require("../../solution/ScanOrder/utils");
|
|
|
139
140
|
var _orderCollectionIdentity = require("./utils/orderCollectionIdentity");
|
|
140
141
|
var _salesNotes = require("./salesNotes");
|
|
141
142
|
var _pickupTiming = require("./pickupTiming");
|
|
143
|
+
var _holderRelations = require("./holderRelations");
|
|
142
144
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
143
145
|
_dayjs.default.extend(_customParseFormat.default);
|
|
144
146
|
const POINT_CARD_SNAPSHOT_TAG = 'point_card';
|
|
@@ -833,7 +835,7 @@ function resolveEffectivePerUnitDiscount(product) {
|
|
|
833
835
|
if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice)) return fromList;
|
|
834
836
|
return fromList + (originalPrice - finalPrice);
|
|
835
837
|
}
|
|
836
|
-
function createDefaultOrderRulesHooks(getBookings) {
|
|
838
|
+
function createDefaultOrderRulesHooks(getBookings, getHolderRelations) {
|
|
837
839
|
const getProductStartDate = product => {
|
|
838
840
|
const productUid = String(product.metadata?.unique_identification_number ?? product.unique_identification_number ?? '');
|
|
839
841
|
const bookingUid = String(product.booking_uid ?? product.metadata?.booking_uid ?? '');
|
|
@@ -951,7 +953,9 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
951
953
|
// 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
|
|
952
954
|
// 无券时会把 bundle 价还原成 original_price(手动改价套餐会从 20 回到 30)。
|
|
953
955
|
isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
|
|
954
|
-
holder_id: product.metadata?.holder_id,
|
|
956
|
+
holder_id: (0, _holderRelations.hasProductBooking)(product) || !getHolderRelations ? product.metadata?.holder_id : (0, _holderRelations.getProductHolderRelations)({
|
|
957
|
+
holder_relations: getHolderRelations()
|
|
958
|
+
}, product).filter(relation => relation.holder_type === 'form').map(relation => relation.holder_id),
|
|
955
959
|
startDate: getProductStartDate(product),
|
|
956
960
|
main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString() : undefined,
|
|
957
961
|
inPromotion: metadataAny._promotion?.inPromotion === true,
|
|
@@ -1242,6 +1246,7 @@ function normalizeSubmitProduct(product, formatOptions = {}) {
|
|
|
1242
1246
|
} = product;
|
|
1243
1247
|
const {
|
|
1244
1248
|
num,
|
|
1249
|
+
_extend: _productExtend,
|
|
1245
1250
|
surcharge_fee: _productSurchargeFee,
|
|
1246
1251
|
discount_amount: _deprecatedDiscountAmount,
|
|
1247
1252
|
discount_type: _deprecatedDiscountType,
|
|
@@ -1428,6 +1433,7 @@ function createDefaultTempOrder(params) {
|
|
|
1428
1433
|
request_unique_idempotency_token: '',
|
|
1429
1434
|
vouchers: [],
|
|
1430
1435
|
products: [],
|
|
1436
|
+
holder_relations: [],
|
|
1431
1437
|
notes: [],
|
|
1432
1438
|
bookings: [],
|
|
1433
1439
|
payments: [],
|
|
@@ -1503,6 +1509,7 @@ function buildSubmitPayload(params) {
|
|
|
1503
1509
|
summary,
|
|
1504
1510
|
enhance
|
|
1505
1511
|
} = params;
|
|
1512
|
+
(0, _holderRelations.ensureHolderRelationUuids)(tempOrder);
|
|
1506
1513
|
const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
|
|
1507
1514
|
const bookingUuid = (0, _orderCollectionIdentity.createUuidV4)();
|
|
1508
1515
|
const virtualSettlementMode = tempOrder.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
|
|
@@ -1542,6 +1549,9 @@ function buildSubmitPayload(params) {
|
|
|
1542
1549
|
});
|
|
1543
1550
|
const payload = {
|
|
1544
1551
|
...tempOrderRest,
|
|
1552
|
+
...(tempOrder.holder_relations !== undefined ? {
|
|
1553
|
+
holder_relations: (0, _lodashEs.cloneDeep)(tempOrder.holder_relations)
|
|
1554
|
+
} : {}),
|
|
1545
1555
|
customer_id: tempOrder.customer_id ?? 1,
|
|
1546
1556
|
customer_name: tempOrder.customer_name || 'Walk-In',
|
|
1547
1557
|
country_calling_code: String(tempOrder.country_calling_code ?? ''),
|
|
@@ -1734,15 +1744,24 @@ function hasAssignedHolderId(value) {
|
|
|
1734
1744
|
* clearTempOrderHolderAssignments(tempOrder);
|
|
1735
1745
|
*/
|
|
1736
1746
|
function clearTempOrderHolderAssignments(tempOrder) {
|
|
1737
|
-
|
|
1747
|
+
const previousRelationCount = tempOrder.holder_relations?.length || 0;
|
|
1748
|
+
(0, _holderRelations.removeProductHolderRelations)(tempOrder, (tempOrder.products || []).filter(product => !(0, _holderRelations.hasProductBooking)(product)));
|
|
1749
|
+
let changed = previousRelationCount !== (tempOrder.holder_relations?.length || 0);
|
|
1738
1750
|
const resetHolderField = (target, key = 'holder_id') => {
|
|
1739
1751
|
if (!hasAssignedHolderId(target[key])) return;
|
|
1740
1752
|
target[key] = null;
|
|
1741
1753
|
changed = true;
|
|
1742
1754
|
};
|
|
1755
|
+
const clearHolder = target => {
|
|
1756
|
+
resetHolderField(target);
|
|
1757
|
+
if (target.holder !== undefined && target.holder !== null) {
|
|
1758
|
+
target.holder = null;
|
|
1759
|
+
changed = true;
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1743
1762
|
for (const product of tempOrder.products || []) {
|
|
1744
1763
|
if (product.metadata && typeof product.metadata === 'object') {
|
|
1745
|
-
|
|
1764
|
+
clearHolder(product.metadata);
|
|
1746
1765
|
}
|
|
1747
1766
|
}
|
|
1748
1767
|
for (const booking of tempOrder.bookings || []) {
|
|
@@ -1760,11 +1779,13 @@ function clearTempOrderHolderAssignments(tempOrder) {
|
|
|
1760
1779
|
for (const entry of Object.values(productsByUid)) {
|
|
1761
1780
|
const origin = entry?.origin;
|
|
1762
1781
|
if (!origin || typeof origin !== 'object') continue;
|
|
1782
|
+
clearHolder(origin);
|
|
1763
1783
|
if (origin.metadata && typeof origin.metadata === 'object') {
|
|
1764
|
-
|
|
1784
|
+
clearHolder(origin.metadata);
|
|
1765
1785
|
}
|
|
1766
1786
|
if (origin._extend && typeof origin._extend === 'object') {
|
|
1767
|
-
|
|
1787
|
+
clearHolder(origin._extend);
|
|
1788
|
+
delete origin._extend.holder_relations;
|
|
1768
1789
|
}
|
|
1769
1790
|
}
|
|
1770
1791
|
}
|
|
@@ -8,6 +8,7 @@ var _BaseModule = require("../BaseModule");
|
|
|
8
8
|
var _types = require("./types");
|
|
9
9
|
var _utils = require("../../solution/ShopDiscount/utils");
|
|
10
10
|
var _utils2 = require("../Cart/utils");
|
|
11
|
+
var _utils3 = require("../Holder/utils");
|
|
11
12
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
12
13
|
var _lodashEs = require("lodash-es");
|
|
13
14
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
@@ -59,7 +60,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
59
60
|
if (discount.holder?.holder_type !== 'form') return true;
|
|
60
61
|
|
|
61
62
|
// getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
|
|
62
|
-
const holderConfig =
|
|
63
|
+
const holderConfig = (0, _utils3.resolveProductHolderConfig)(holderSource);
|
|
63
64
|
const holderStatus = holderConfig?.status;
|
|
64
65
|
const holderEnabled = holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
|
|
65
66
|
if (!holderEnabled || holderConfig?.resource_id === undefined || holderConfig?.resource_id === null || holderConfig?.resource_id === '') {
|
package/lib/server/index.js
CHANGED
|
@@ -836,6 +836,9 @@ class Server {
|
|
|
836
836
|
need_sync: 0,
|
|
837
837
|
is_draft_order: 0
|
|
838
838
|
};
|
|
839
|
+
if (!Array.isArray(fresh.holder_relations) && Array.isArray(checkoutData?.holder_relations)) {
|
|
840
|
+
syncedOrder.holder_relations = (0, _lodashEs.cloneDeep)(checkoutData.holder_relations);
|
|
841
|
+
}
|
|
839
842
|
await this.order.upsertOrdersFromRemote([syncedOrder], 'checkoutSync');
|
|
840
843
|
this.logInfo(`${title}: sync_sales 完整订单已同步到本地`, {
|
|
841
844
|
order_id: fresh.order_id,
|
|
@@ -5502,6 +5505,9 @@ class Server {
|
|
|
5502
5505
|
if (fresh.order_number !== undefined && fresh.order_number !== null) {
|
|
5503
5506
|
patch.order_number = fresh.order_number;
|
|
5504
5507
|
}
|
|
5508
|
+
if (Array.isArray(fresh.holder_relations)) {
|
|
5509
|
+
patch.holder_relations = (0, _lodashEs.cloneDeep)(fresh.holder_relations);
|
|
5510
|
+
}
|
|
5505
5511
|
return patch;
|
|
5506
5512
|
}
|
|
5507
5513
|
buildSyncedOrderForPrint(params) {
|
|
@@ -326,6 +326,10 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
326
326
|
private getIdentifiedPendingPayments;
|
|
327
327
|
private shouldProtectLocalOrderFromRemoteSnapshot;
|
|
328
328
|
private getUnmatchedIdentifiedPendingPayments;
|
|
329
|
+
/** 关系数组是完整快照,不能拼接或按商品子项生成 UID;扩展字段整体保留。 */
|
|
330
|
+
private applyHolderRelationsSnapshot;
|
|
331
|
+
/** 全量拉取缺少关系字段时,仍保留同一订单已有的关系快照。 */
|
|
332
|
+
private preserveOmittedHolderRelations;
|
|
329
333
|
private mergeOrderRecords;
|
|
330
334
|
private summarizeDuplicateOrders;
|
|
331
335
|
private logDuplicateOrders;
|
|
@@ -289,6 +289,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
289
289
|
const existingRecord = existing;
|
|
290
290
|
const incomingRecord = incoming;
|
|
291
291
|
const uidRemaps = [];
|
|
292
|
+
this.applyHolderRelationsSnapshot(reconciled, existing, incoming);
|
|
292
293
|
for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
|
|
293
294
|
if (!Array.isArray(incomingRecord[field])) continue;
|
|
294
295
|
reconciled[field] = this.mergeAuthoritativeOrderCollection(field, existingRecord[field], incomingRecord[field], uidRemaps);
|
|
@@ -365,7 +366,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
365
366
|
continue;
|
|
366
367
|
}
|
|
367
368
|
|
|
368
|
-
//
|
|
369
|
+
// 远端商品成员或 Holder 关系确实变化时必须落库,避免被回声窗口跳过。
|
|
369
370
|
if (forceWriteStorageKeys.has(storageKey)) {
|
|
370
371
|
toWrite.push(order);
|
|
371
372
|
continue;
|
|
@@ -1339,6 +1340,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1339
1340
|
if (matchIndex >= 0) {
|
|
1340
1341
|
const existingOrder = updatedList[matchIndex];
|
|
1341
1342
|
const reconciledDraftOrder = this.preserveExistingBusinessCodeForDraft(existingOrder, draftOrder);
|
|
1343
|
+
this.applyHolderRelationsSnapshot(reconciledDraftOrder, existingOrder, draftOrder);
|
|
1342
1344
|
const mergedOrder = this.mergeOrderRecords(existingOrder, reconciledDraftOrder);
|
|
1343
1345
|
const nextOrder = {
|
|
1344
1346
|
...mergedOrder,
|
|
@@ -1617,7 +1619,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1617
1619
|
const hasSingleId = routeInfo.hasSingleId;
|
|
1618
1620
|
const normalizedBody = this.normalizeOrderSyncPayload(msg.body || msg.data);
|
|
1619
1621
|
if (routeInfo.route === 'bodyUpsert' && normalizedBody) {
|
|
1620
|
-
|
|
1622
|
+
const orderKey = this.getIdKey(normalizedBody.order_id);
|
|
1623
|
+
const previousBody = upsertOrders.get(orderKey);
|
|
1624
|
+
if (previousBody) this.applyHolderRelationsSnapshot(normalizedBody, previousBody, normalizedBody);
|
|
1625
|
+
upsertOrders.set(orderKey, normalizedBody);
|
|
1621
1626
|
return;
|
|
1622
1627
|
}
|
|
1623
1628
|
if (hasBatchIds) refreshIds.push(...routeInfo.batchIds);else if (routeInfo.route === 'httpRefresh.singleId' && singleId !== null) refreshIds.push(singleId);else if (routeInfo.route === 'httpRefresh.relationIds') refreshIds.push(...routeInfo.batchIds);
|
|
@@ -1810,6 +1815,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1810
1815
|
const mergedStorageKey = this.getOrderStorageKey(mergedOrder);
|
|
1811
1816
|
if (mergedStorageKey) forceWriteStorageKeys.add(mergedStorageKey);
|
|
1812
1817
|
}
|
|
1818
|
+
if (nextStorageKey && !(0, _lodashEs.isEqual)(existingOrder.holder_relations, mergedOrder.holder_relations)) {
|
|
1819
|
+
forceWriteStorageKeys.add(nextStorageKey);
|
|
1820
|
+
}
|
|
1813
1821
|
// 合并后身份字段可能新增(如挂单拿到 order_id),同步登记到索引,
|
|
1814
1822
|
// 供同批后续 fresh 命中同一槽位,避免重复插入
|
|
1815
1823
|
this.registerOrderIdentityKeys(identityKeyToIndex, mergedOrder, adjustedMatchIndex);
|
|
@@ -2110,6 +2118,38 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2110
2118
|
const incomingIdentityKeys = new Set(incomingPayments.flatMap(payment => (0, _paymentUtils.getOrderPaymentIdentityKeys)(payment)));
|
|
2111
2119
|
return existingPayments.filter(payment => (0, _paymentUtils.isIdentifiedPendingOrderPayment)(payment) && !(0, _paymentUtils.getOrderPaymentIdentityKeys)(payment).some(key => incomingIdentityKeys.has(key)));
|
|
2112
2120
|
}
|
|
2121
|
+
|
|
2122
|
+
/** 关系数组是完整快照,不能拼接或按商品子项生成 UID;扩展字段整体保留。 */
|
|
2123
|
+
applyHolderRelationsSnapshot(target, existing, incoming) {
|
|
2124
|
+
if (Array.isArray(incoming.holder_relations)) {
|
|
2125
|
+
target.holder_relations = (0, _lodashEs.cloneDeep)(incoming.holder_relations);
|
|
2126
|
+
} else if (Array.isArray(existing.holder_relations)) {
|
|
2127
|
+
target.holder_relations = (0, _lodashEs.cloneDeep)(existing.holder_relations);
|
|
2128
|
+
} else {
|
|
2129
|
+
delete target.holder_relations;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
/** 全量拉取缺少关系字段时,仍保留同一订单已有的关系快照。 */
|
|
2134
|
+
preserveOmittedHolderRelations(incomingOrders, existingOrders) {
|
|
2135
|
+
const existingByIdentity = new Map();
|
|
2136
|
+
for (const order of existingOrders) {
|
|
2137
|
+
if (!Array.isArray(order.holder_relations)) continue;
|
|
2138
|
+
for (const key of this.getOrderIdentityMatchKeys(order)) {
|
|
2139
|
+
existingByIdentity.set(key, order);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
return incomingOrders.map(order => {
|
|
2143
|
+
if (Array.isArray(order.holder_relations)) return order;
|
|
2144
|
+
const existingOrder = this.getOrderIdentityMatchKeys(order).map(key => existingByIdentity.get(key)).find(Boolean);
|
|
2145
|
+
if (!existingOrder) return order;
|
|
2146
|
+
const nextOrder = {
|
|
2147
|
+
...order
|
|
2148
|
+
};
|
|
2149
|
+
this.applyHolderRelationsSnapshot(nextOrder, existingOrder, order);
|
|
2150
|
+
return nextOrder;
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2113
2153
|
mergeOrderRecords(existing, incoming) {
|
|
2114
2154
|
const preferred = this.pickPreferredOrder(existing, incoming);
|
|
2115
2155
|
const secondary = preferred === existing ? incoming : existing;
|
|
@@ -2152,6 +2192,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2152
2192
|
if (Object.prototype.hasOwnProperty.call(incomingRecord, 'order_meta_list')) {
|
|
2153
2193
|
mergedRecord.order_meta_list = (0, _lodashEs.cloneDeep)(incomingRecord.order_meta_list);
|
|
2154
2194
|
}
|
|
2195
|
+
this.applyHolderRelationsSnapshot(merged, existing, incoming);
|
|
2155
2196
|
|
|
2156
2197
|
// 子项数组遵循完整快照语义:incoming 自有且为数组(包括 [])时权威替换;
|
|
2157
2198
|
// 字段缺席或不是数组时视为稀疏 patch,继续保留 existing。
|
|
@@ -2593,7 +2634,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2593
2634
|
async replaceOrdersSnapshotInSQLite(orderList, source, protectedOrdersBeforeRemoteFetch = []) {
|
|
2594
2635
|
if (!this.dbManager) {
|
|
2595
2636
|
return {
|
|
2596
|
-
orders: this.compactOrderListByIdentity(orderList.map(order => this.normalizeRemoteSyncedOrder(order)), `${source}.snapshotNoDb`).list,
|
|
2637
|
+
orders: this.compactOrderListByIdentity(this.preserveOmittedHolderRelations(orderList, this.store.list).map(order => this.normalizeRemoteSyncedOrder(order)), `${source}.snapshotNoDb`).list,
|
|
2597
2638
|
persisted: false
|
|
2598
2639
|
};
|
|
2599
2640
|
}
|
|
@@ -2603,6 +2644,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2603
2644
|
try {
|
|
2604
2645
|
await this.runInOrderSQLiteSaveQueue(async () => {
|
|
2605
2646
|
const existingOrders = typeof this.dbManager.getAll === 'function' ? await this.dbManager.getAll(INDEXDB_STORE_NAME) : [];
|
|
2647
|
+
const remoteSnapshotWithHolderRelations = this.preserveOmittedHolderRelations(remoteSnapshot, [...protectedOrdersBeforeRemoteFetch, ...(existingOrders || [])]);
|
|
2606
2648
|
const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map(order => this.normalizeOrderCollectionsForIngress(order, `${source}.protectedBeforeRemoteFetch`)).filter(order => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
|
|
2607
2649
|
for (const rawCurrentOrder of existingOrders || []) {
|
|
2608
2650
|
const currentOrder = this.normalizeOrderCollectionsForIngress(rawCurrentOrder, `${source}.currentSQLite`);
|
|
@@ -2618,7 +2660,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2618
2660
|
}
|
|
2619
2661
|
if (currentNeedsProtection) protectedLocalOrders.push(currentOrder);
|
|
2620
2662
|
}
|
|
2621
|
-
const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(
|
|
2663
|
+
const orderListSnapshot = this.mergeRemoteSnapshotWithPendingOrders(remoteSnapshotWithHolderRelations, protectedLocalOrders);
|
|
2622
2664
|
mergedSnapshot = this.compactOrderListByIdentity(orderListSnapshot, `${source}.sqliteSnapshot`).list;
|
|
2623
2665
|
this.logInfo('replaceOrdersSnapshotInSQLite-开始', {
|
|
2624
2666
|
source,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ScheduleEventResource } from '../resource/types';
|
|
2
|
+
import type { OrderHolderRelation } from '../../../modules/Order/types';
|
|
2
3
|
/**
|
|
3
4
|
* Order 模块主键类型(对齐标准 Sales 协议的 order_id)
|
|
4
5
|
*/
|
|
@@ -448,6 +449,8 @@ export interface OrderData {
|
|
|
448
449
|
contacts_info?: unknown[];
|
|
449
450
|
/** 订单级主体参数 */
|
|
450
451
|
holder?: Record<string, unknown> | null;
|
|
452
|
+
/** 非预约商品 Holder 关系完整快照;缺席表示本次回包未提供 */
|
|
453
|
+
holder_relations?: OrderHolderRelation[];
|
|
451
454
|
/** 订单前端扩展快照 */
|
|
452
455
|
order_meta_list?: {
|
|
453
456
|
point_cards_snapshot?: Array<{
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.ProductsModule = void 0;
|
|
7
7
|
var _BaseModule = require("../../../modules/BaseModule");
|
|
8
|
+
var _utils = require("../../../modules/Holder/utils");
|
|
8
9
|
var _Quotation = require("../../../modules/Quotation");
|
|
9
10
|
var _types = require("./types");
|
|
10
11
|
var _product = require("../../utils/product");
|
|
@@ -983,7 +984,7 @@ class ProductsModule extends _BaseModule.BaseModule {
|
|
|
983
984
|
if (!product) continue;
|
|
984
985
|
snapshots[String(id)] = {
|
|
985
986
|
cover: product.cover,
|
|
986
|
-
holder_config: product
|
|
987
|
+
holder_config: (0, _utils.resolveProductHolderConfig)(product) ?? undefined
|
|
987
988
|
};
|
|
988
989
|
}
|
|
989
990
|
return snapshots;
|
|
@@ -7,6 +7,7 @@ exports.buildSmallTicketData = buildSmallTicketData;
|
|
|
7
7
|
exports.hasSmallTicketData = hasSmallTicketData;
|
|
8
8
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
9
9
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
10
|
+
var _holderRelations = require("../../modules/Order/holderRelations");
|
|
10
11
|
var _pickupTiming = require("../../modules/Order/pickupTiming");
|
|
11
12
|
var _templateVisibility = require("./templateVisibility");
|
|
12
13
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -97,6 +98,7 @@ const LABELS = {
|
|
|
97
98
|
bookingDateTime: 'Date & time',
|
|
98
99
|
bookingResource: 'Resource',
|
|
99
100
|
bookingHolder: 'Holder',
|
|
101
|
+
productHolder: 'Holder',
|
|
100
102
|
orderDiscount: 'Order discount',
|
|
101
103
|
manualDiscount: 'Manual discount',
|
|
102
104
|
manualMarkup: 'Manual markup',
|
|
@@ -142,6 +144,7 @@ const LABELS = {
|
|
|
142
144
|
bookingDateTime: '日期和时间',
|
|
143
145
|
bookingResource: '资源',
|
|
144
146
|
bookingHolder: '预约人',
|
|
147
|
+
productHolder: '持有人',
|
|
145
148
|
orderDiscount: '整单折扣',
|
|
146
149
|
manualDiscount: '手动折扣',
|
|
147
150
|
manualMarkup: '手动加价',
|
|
@@ -187,6 +190,7 @@ const LABELS = {
|
|
|
187
190
|
bookingDateTime: '日期和時間',
|
|
188
191
|
bookingResource: '資源',
|
|
189
192
|
bookingHolder: '預約人',
|
|
193
|
+
productHolder: '持有人',
|
|
190
194
|
orderDiscount: '整單折扣',
|
|
191
195
|
manualDiscount: '手動折扣',
|
|
192
196
|
manualMarkup: '手動加價',
|
|
@@ -230,6 +234,7 @@ const LABELS = {
|
|
|
230
234
|
bookingDateTime: '日時',
|
|
231
235
|
bookingResource: 'リソース',
|
|
232
236
|
bookingHolder: '予約者',
|
|
237
|
+
productHolder: '利用者',
|
|
233
238
|
orderDiscount: '注文割引',
|
|
234
239
|
manualDiscount: '手動割引',
|
|
235
240
|
manualMarkup: '手動値上げ',
|
|
@@ -274,6 +279,7 @@ const LABELS = {
|
|
|
274
279
|
bookingDateTime: 'Data e hora',
|
|
275
280
|
bookingResource: 'Recurso',
|
|
276
281
|
bookingHolder: 'Titular',
|
|
282
|
+
productHolder: 'Titular',
|
|
277
283
|
orderDiscount: 'Desconto do pedido',
|
|
278
284
|
manualDiscount: 'Desconto manual',
|
|
279
285
|
manualMarkup: 'Acréscimo manual',
|
|
@@ -445,6 +451,15 @@ function buildProducts(order, locale, productMap) {
|
|
|
445
451
|
quantity,
|
|
446
452
|
originalPrice
|
|
447
453
|
});
|
|
454
|
+
const holderName = (0, _holderRelations.hasProductBooking)(product) ? '' : (0, _holderRelations.getProductHolderRelations)(order, product).map(relation => getLocalizedValue(relation.metadata?.name, locale).trim()).filter(Boolean).join(', ');
|
|
455
|
+
if (holderName) {
|
|
456
|
+
// 复用 Web Invoice / 原生均支持的文本扩展行,不混入金额或商品备注。
|
|
457
|
+
extensionList.push({
|
|
458
|
+
...receiptKey(rawProduct, 'product-holder'),
|
|
459
|
+
item: `${label(locale, 'productHolder')}: ${holderName}`,
|
|
460
|
+
value: ''
|
|
461
|
+
});
|
|
462
|
+
}
|
|
448
463
|
const productNote = resolveProductNote(product, locale);
|
|
449
464
|
const allergy = isPresentId(productUid) ? allergyByProductUid.get(String(productUid).trim()) || '' : '';
|
|
450
465
|
const basePrice = resolveProductBasePrice(product);
|
|
@@ -1165,13 +1180,6 @@ function buildFees(params) {
|
|
|
1165
1180
|
const isPriceIncludeTax = firstPresentValue(summary.is_price_include_tax, order.is_price_include_tax, shopInfo.is_price_include_tax);
|
|
1166
1181
|
const roundingAmount = firstPresentValue(summary.rounding_amount, order.rounding_amount);
|
|
1167
1182
|
const payProcessingFee = financials.payProcessingFee;
|
|
1168
|
-
if (isNonZero(payProcessingFee)) {
|
|
1169
|
-
fees.push({
|
|
1170
|
-
...receiptKey(order, 'payment-processing-fee'),
|
|
1171
|
-
item: label(locale, 'payProcessingFee'),
|
|
1172
|
-
value: formatMoney(payProcessingFee, currencySymbol)
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
1183
|
const productExpectAmount = firstPresentValue(summary.product_expect_amount, summary.product_amount, order.product_expect_amount);
|
|
1176
1184
|
const productOriginalAmount = firstPresentValue(summary.product_original_amount, order.product_original_amount) ?? calculateProductOriginalAmount(order);
|
|
1177
1185
|
const totalSavingsAmount = new _decimal.default(toMoneyNumber(productOriginalAmount)).minus(toMoneyNumber(productExpectAmount)).plus(toMoneyNumber(discountAmount));
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.SALES_ORDER_RELATIONS = void 0;
|
|
7
7
|
exports.loadSalesOrderSnapshot = loadSalesOrderSnapshot;
|
|
8
|
-
const SALES_ORDER_RELATIONS = exports.SALES_ORDER_RELATIONS = ['products', 'bookings', 'payments', 'customer', 'summary', 'contacts_info', 'order_meta_list', 'refunds', 'notes'];
|
|
8
|
+
const SALES_ORDER_RELATIONS = exports.SALES_ORDER_RELATIONS = ['products', 'bookings', 'payments', 'customer', 'summary', 'contacts_info', 'order_meta_list', 'refunds', 'notes', 'holder_relations'];
|
|
9
9
|
|
|
10
10
|
/** Shared transport contract; remote callers use their host's /h5 prefix. */
|
|
11
11
|
function loadSalesOrderSnapshot(request, params) {
|
|
@@ -5,6 +5,7 @@ import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentS
|
|
|
5
5
|
import { OrderModule } from '../../modules/Order';
|
|
6
6
|
import { type PickupTimingBookingInput } from '../../modules/Order/pickupTiming';
|
|
7
7
|
import type { PickupTimingAvailability, PickupTimingSelection, PickupTimingValidationResult } from '../../modules/FulfillmentTiming';
|
|
8
|
+
import { type ContactInfoConfig } from '../../modules/OpenData/contactInfo';
|
|
8
9
|
import type { AddProductBookingInput, AddProductToOrderOptions, LoadSalesDetailParams, OrderPaymentData, OrderPaymentUpdateOptions, OrderPaymentUpdateResult, OrderPaymentSource, SendCustomerPayLinkParams, SyncPaymentsToOrderParams, SyncPaymentsToOrderResult, UpdateTempOrderCustomerInput, UpdateOrderBookingParams, UpdateOrderProductParams, OrderTempOrder, OrderSummary, OrderPromotionEvaluator, OrderGiftSelectResolver, OrderUnfulfilledPromotion, OrderLastGiftActions, RemoveProductsFromOrderOptions, ReplaceTempOrderOptions, SalesNote, SalesNotesMutationSnapshot, SetSalesNoteInput, PickupReferenceMode, ShopServiceData, ShopServiceType } from '../../modules/Order/types';
|
|
9
10
|
import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
|
|
10
11
|
import type { Discount, VirtualCurrencyAsset } from '../../modules/Discount/types';
|
|
@@ -281,6 +282,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
281
282
|
setPickupTimingBooking(input: PickupTimingBookingInput): import("../../modules/Order").PickupTimingBooking;
|
|
282
283
|
clearPickupTimingBooking(): void;
|
|
283
284
|
updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
|
|
285
|
+
protected loadContactInfoOpenData(): Promise<OpenDataConfig | null>;
|
|
286
|
+
getContactInfoConfig(): Promise<ContactInfoConfig>;
|
|
287
|
+
validateContactInfo(): Promise<void>;
|
|
284
288
|
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
285
289
|
setEnableTempOrderPersist(enabled: boolean): void;
|
|
286
290
|
/** 是否允许 saveDraft 写入 IndexedDB 草稿。 */
|