@pisell/pisellos 2.3.20 → 2.3.22
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/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +16 -10
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/dist/modules/Order/index.js +17 -7
- package/dist/modules/Order/types.d.ts +1 -0
- package/dist/modules/Order/utils.js +16 -4
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +428 -255
- package/dist/server/modules/order/types.d.ts +4 -0
- package/dist/server/modules/products/index.d.ts +5 -1
- package/dist/server/modules/products/index.js +383 -315
- package/dist/server/modules/products/types.d.ts +4 -0
- package/dist/solution/BaseSales/index.d.ts +10 -0
- package/dist/solution/BaseSales/index.js +503 -428
- package/dist/solution/BaseSales/types.d.ts +6 -1
- package/dist/solution/BaseSales/types.js +1 -1
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +14 -1
- package/dist/solution/BookingTicket/index.js +42 -24
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -0
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +1 -0
- package/lib/modules/Order/index.js +22 -7
- package/lib/modules/Order/types.d.ts +1 -0
- package/lib/modules/Order/utils.js +17 -3
- package/lib/server/index.d.ts +5 -0
- package/lib/server/index.js +121 -2
- package/lib/server/modules/order/types.d.ts +4 -0
- package/lib/server/modules/products/index.d.ts +5 -1
- package/lib/server/modules/products/index.js +20 -0
- package/lib/server/modules/products/types.d.ts +4 -0
- package/lib/solution/BaseSales/index.d.ts +10 -0
- package/lib/solution/BaseSales/index.js +66 -23
- package/lib/solution/BaseSales/types.d.ts +6 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +8 -0
- package/lib/solution/BookingTicket/index.js +15 -7
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { Module, PisellCore } from '../../../types';
|
|
|
2
2
|
import { BaseModule } from '../../../modules/BaseModule';
|
|
3
3
|
import { ProductData } from '../../../modules/Product/types';
|
|
4
4
|
import type { RouteDefinition } from '../../types';
|
|
5
|
-
import { ProductIdScope, ProductFormatter, ProductFormatterContext } from './types';
|
|
5
|
+
import { ProductIdScope, type ProductSnapshot, ProductFormatter, ProductFormatterContext } from './types';
|
|
6
6
|
/**
|
|
7
7
|
* Products 模块 - 用于获取和管理完整的商品详细数据
|
|
8
8
|
* 相比 ProductList 模块,Products 会获取所有详细信息并缓存
|
|
@@ -185,6 +185,10 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
185
185
|
* 获取商品列表(深拷贝,供外部安全使用)
|
|
186
186
|
*/
|
|
187
187
|
getProducts(): Promise<ProductData[]>;
|
|
188
|
+
/**
|
|
189
|
+
* 批量获取商品轻量快照,供订单详情等响应补齐展示协议字段。
|
|
190
|
+
*/
|
|
191
|
+
getProductSnapshotsByIds(ids: number[]): Promise<Record<string, ProductSnapshot>>;
|
|
188
192
|
/**
|
|
189
193
|
* 内部获取商品列表的直接引用(无拷贝)
|
|
190
194
|
* 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
|
|
@@ -860,6 +860,26 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
860
860
|
(0, import_product.perfMark)("ProductsModule.getProducts(structuredClone)", performance.now() - t0, { count: result.length });
|
|
861
861
|
return result;
|
|
862
862
|
}
|
|
863
|
+
/**
|
|
864
|
+
* 批量获取商品轻量快照,供订单详情等响应补齐展示协议字段。
|
|
865
|
+
*/
|
|
866
|
+
async getProductSnapshotsByIds(ids) {
|
|
867
|
+
const snapshots = {};
|
|
868
|
+
const seen = /* @__PURE__ */ new Set();
|
|
869
|
+
for (const id of ids) {
|
|
870
|
+
if (!Number.isFinite(id) || seen.has(id))
|
|
871
|
+
continue;
|
|
872
|
+
seen.add(id);
|
|
873
|
+
const product = this.store.map.get(id);
|
|
874
|
+
if (!product)
|
|
875
|
+
continue;
|
|
876
|
+
snapshots[String(id)] = {
|
|
877
|
+
cover: product.cover,
|
|
878
|
+
holder_config: product.holder_config
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
return snapshots;
|
|
882
|
+
}
|
|
863
883
|
/**
|
|
864
884
|
* 内部获取商品列表的直接引用(无拷贝)
|
|
865
885
|
* 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
|
|
@@ -191,6 +191,16 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
191
191
|
discountList: Discount[];
|
|
192
192
|
}>;
|
|
193
193
|
getDiscountList(): Discount[];
|
|
194
|
+
/** 读取 Discount 模块原始券列表(未经过 bookingTime 等过滤)。 */
|
|
195
|
+
getOriginalDiscountList(): Discount[];
|
|
196
|
+
/**
|
|
197
|
+
* 同步写入 Discount 模块的 discountList / originalDiscountList。
|
|
198
|
+
* 供 Holder 补全等场景在 OS store 层更新 machinecode holder 字段。
|
|
199
|
+
*/
|
|
200
|
+
replaceDiscountStoreLists(params: {
|
|
201
|
+
discountList: Discount[];
|
|
202
|
+
originalDiscountList?: Discount[];
|
|
203
|
+
}): Promise<void>;
|
|
194
204
|
scanPromotionCode(code: string, customerId?: number): Promise<BaseSalesScanCodeResult>;
|
|
195
205
|
setDiscountSelected(params: {
|
|
196
206
|
discountId: number;
|
|
@@ -102,7 +102,25 @@ function getBaseSalesMetadataUid(item, metadataKey) {
|
|
|
102
102
|
return null;
|
|
103
103
|
return String(uid);
|
|
104
104
|
}
|
|
105
|
-
function
|
|
105
|
+
function isBaseSalesBlankValue(value) {
|
|
106
|
+
return value === void 0 || value === null || value === "";
|
|
107
|
+
}
|
|
108
|
+
function mergeBaseSalesProductSnapshotFields(currentItem, loadedItem) {
|
|
109
|
+
var _a, _b, _c;
|
|
110
|
+
const mergedItem = (0, import_lodash_es.cloneDeep)(loadedItem);
|
|
111
|
+
if (isBaseSalesBlankValue(mergedItem.product_cover) && !isBaseSalesBlankValue(currentItem == null ? void 0 : currentItem.product_cover)) {
|
|
112
|
+
mergedItem.product_cover = currentItem.product_cover;
|
|
113
|
+
}
|
|
114
|
+
const currentHolderConfig = (_a = currentItem == null ? void 0 : currentItem.metadata) == null ? void 0 : _a.holder_config;
|
|
115
|
+
if ((((_b = mergedItem.metadata) == null ? void 0 : _b.holder_config) === void 0 || ((_c = mergedItem.metadata) == null ? void 0 : _c.holder_config) === null) && currentHolderConfig !== void 0 && currentHolderConfig !== null) {
|
|
116
|
+
mergedItem.metadata = {
|
|
117
|
+
...mergedItem.metadata || {},
|
|
118
|
+
holder_config: currentHolderConfig
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return mergedItem;
|
|
122
|
+
}
|
|
123
|
+
function mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey, arrayKey) {
|
|
106
124
|
const result = [];
|
|
107
125
|
const indexByUid = /* @__PURE__ */ new Map();
|
|
108
126
|
const appendOrReplaceByUid = (item) => {
|
|
@@ -114,7 +132,7 @@ function mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey) {
|
|
|
114
132
|
}
|
|
115
133
|
const existingIndex = indexByUid.get(uid);
|
|
116
134
|
if (existingIndex !== void 0) {
|
|
117
|
-
result[existingIndex] = clonedItem;
|
|
135
|
+
result[existingIndex] = arrayKey === "products" ? mergeBaseSalesProductSnapshotFields(result[existingIndex], clonedItem) : clonedItem;
|
|
118
136
|
return;
|
|
119
137
|
}
|
|
120
138
|
indexByUid.set(uid, result.length);
|
|
@@ -134,7 +152,7 @@ function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord) {
|
|
|
134
152
|
if (Array.isArray(currentValue) && Array.isArray(loadedValue)) {
|
|
135
153
|
const metadataKey = getBaseSalesUniqueArrayMetadataKey(key);
|
|
136
154
|
if (metadataKey) {
|
|
137
|
-
return mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey);
|
|
155
|
+
return mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey, key);
|
|
138
156
|
}
|
|
139
157
|
return [
|
|
140
158
|
...(0, import_lodash_es.cloneDeep)(currentValue),
|
|
@@ -260,7 +278,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
260
278
|
if (!this.store.order)
|
|
261
279
|
return;
|
|
262
280
|
this.serverOrderChangeHydrateInFlight = (async () => {
|
|
263
|
-
|
|
281
|
+
var _a, _b;
|
|
282
|
+
const currentTempOrder = (_b = (_a = this.store.order).getTempOrder) == null ? void 0 : _b.call(_a);
|
|
283
|
+
const record = mergeSalesDetailRecordWithTempOrder(currentTempOrder, changedOrder);
|
|
284
|
+
const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
|
|
264
285
|
recalcOnHydrate: false
|
|
265
286
|
});
|
|
266
287
|
this.currentSalesDetail = sales;
|
|
@@ -1094,7 +1115,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1094
1115
|
});
|
|
1095
1116
|
}
|
|
1096
1117
|
async loadDiscountConfig(params) {
|
|
1097
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r
|
|
1118
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
1098
1119
|
if (!this.store.order)
|
|
1099
1120
|
throw new Error("order 模块未初始化");
|
|
1100
1121
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
@@ -1165,13 +1186,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1165
1186
|
};
|
|
1166
1187
|
}
|
|
1167
1188
|
if (rulesModule) {
|
|
1168
|
-
const
|
|
1169
|
-
const orderTotalAmount = Number(((_m = orderStore.summary) == null ? void 0 : _m.total_amount) || 0);
|
|
1189
|
+
const orderTotalAmount = Number(((_l = orderStore.summary) == null ? void 0 : _l.total_amount) || 0);
|
|
1170
1190
|
console.log("[BaseSales.applyDiscountConfig.calcDiscount]");
|
|
1171
1191
|
const result = rulesModule.calcDiscount({
|
|
1172
1192
|
productList: tempOrder.products,
|
|
1173
1193
|
discountList: nextDiscountList,
|
|
1174
|
-
holders,
|
|
1194
|
+
holders: [],
|
|
1175
1195
|
isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
|
|
1176
1196
|
orderTotalAmount
|
|
1177
1197
|
}) || { productList: tempOrder.products, discountList: nextDiscountList };
|
|
@@ -1182,8 +1202,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1182
1202
|
);
|
|
1183
1203
|
}
|
|
1184
1204
|
for (const product of tempOrder.products || []) {
|
|
1185
|
-
const productUid = (
|
|
1186
|
-
const runtimeOrigin = productUid ? (
|
|
1205
|
+
const productUid = (_m = product.metadata) == null ? void 0 : _m.unique_identification_number;
|
|
1206
|
+
const runtimeOrigin = productUid ? (_p = (_o = (_n = tempOrder._extend) == null ? void 0 : _n.productsByUid) == null ? void 0 : _o[productUid]) == null ? void 0 : _p.origin : void 0;
|
|
1187
1207
|
if ((runtimeOrigin == null ? void 0 : runtimeOrigin.isManualDiscount) || isBaseSalesManualProductDiscountProduct(product))
|
|
1188
1208
|
continue;
|
|
1189
1209
|
const totalPerUnitDiscount = (product.discount_list || []).reduce(
|
|
@@ -1191,7 +1211,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1191
1211
|
0
|
|
1192
1212
|
);
|
|
1193
1213
|
const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(product));
|
|
1194
|
-
const sourcePrice = ((
|
|
1214
|
+
const sourcePrice = ((_q = product.metadata) == null ? void 0 : _q.source_product_price) ?? (((_r = product.metadata) == null ? void 0 : _r.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
|
|
1195
1215
|
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1196
1216
|
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1197
1217
|
if (product.metadata) {
|
|
@@ -1227,7 +1247,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1227
1247
|
};
|
|
1228
1248
|
}
|
|
1229
1249
|
async bestDiscount(cb) {
|
|
1230
|
-
var _a, _b, _c
|
|
1250
|
+
var _a, _b, _c;
|
|
1231
1251
|
if (!this.store.order)
|
|
1232
1252
|
throw new Error("order 模块未初始化");
|
|
1233
1253
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
@@ -1246,13 +1266,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1246
1266
|
};
|
|
1247
1267
|
await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
|
|
1248
1268
|
if (rulesModule) {
|
|
1249
|
-
const
|
|
1250
|
-
const orderTotalAmount = Number(((_d = orderStore.summary) == null ? void 0 : _d.total_amount) || 0);
|
|
1269
|
+
const orderTotalAmount = Number(((_c = orderStore.summary) == null ? void 0 : _c.total_amount) || 0);
|
|
1251
1270
|
console.log("[BaseSales.bestDiscount.calcDiscount]");
|
|
1252
1271
|
result = rulesModule.calcDiscount({
|
|
1253
1272
|
productList: tempOrder.products,
|
|
1254
1273
|
discountList: nextDiscountList,
|
|
1255
|
-
holders,
|
|
1274
|
+
holders: [],
|
|
1256
1275
|
isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
|
|
1257
1276
|
orderTotalAmount
|
|
1258
1277
|
}) || result;
|
|
@@ -1286,6 +1305,30 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1286
1305
|
return [];
|
|
1287
1306
|
return this.store.order.getDiscountList();
|
|
1288
1307
|
}
|
|
1308
|
+
/** 读取 Discount 模块原始券列表(未经过 bookingTime 等过滤)。 */
|
|
1309
|
+
getOriginalDiscountList() {
|
|
1310
|
+
var _a, _b;
|
|
1311
|
+
if (!this.store.order)
|
|
1312
|
+
return [];
|
|
1313
|
+
const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
|
|
1314
|
+
return ((_b = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* 同步写入 Discount 模块的 discountList / originalDiscountList。
|
|
1318
|
+
* 供 Holder 补全等场景在 OS store 层更新 machinecode holder 字段。
|
|
1319
|
+
*/
|
|
1320
|
+
async replaceDiscountStoreLists(params) {
|
|
1321
|
+
var _a;
|
|
1322
|
+
if (!this.store.order)
|
|
1323
|
+
throw new Error("order 模块未初始化");
|
|
1324
|
+
const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
|
|
1325
|
+
if (!discountModule)
|
|
1326
|
+
return;
|
|
1327
|
+
if (params.originalDiscountList) {
|
|
1328
|
+
await discountModule.setOriginalDiscountList(params.originalDiscountList);
|
|
1329
|
+
}
|
|
1330
|
+
await discountModule.setDiscountList(params.discountList);
|
|
1331
|
+
}
|
|
1289
1332
|
async scanPromotionCode(code, customerId) {
|
|
1290
1333
|
try {
|
|
1291
1334
|
if (!this.store.order)
|
|
@@ -1298,7 +1341,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1298
1341
|
return {
|
|
1299
1342
|
isAvailable: raw.isAvailable,
|
|
1300
1343
|
type: raw.type,
|
|
1301
|
-
unavailableReason: raw.unavailableReason
|
|
1344
|
+
unavailableReason: raw.unavailableReason,
|
|
1345
|
+
scannedDiscountList: raw.scannedDiscountList
|
|
1302
1346
|
};
|
|
1303
1347
|
} catch (error) {
|
|
1304
1348
|
throw error;
|
|
@@ -1306,7 +1350,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1306
1350
|
}
|
|
1307
1351
|
// TODO 需要优化,这段逻辑太长了,里面应该有些历史遗留问题
|
|
1308
1352
|
async setDiscountSelected(params) {
|
|
1309
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
1353
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1310
1354
|
try {
|
|
1311
1355
|
if (!this.store.order)
|
|
1312
1356
|
throw new Error("order 模块未初始化");
|
|
@@ -1323,17 +1367,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1323
1367
|
const orderStore = this.store.order.store || {};
|
|
1324
1368
|
const discountModule = orderStore.discount;
|
|
1325
1369
|
const rulesModule = orderStore.rules;
|
|
1326
|
-
const holders = ((_a = tempOrder.holder) == null ? void 0 : _a.form_record) || [];
|
|
1327
1370
|
let nextDiscountList = updated;
|
|
1328
1371
|
await (discountModule == null ? void 0 : discountModule.setDiscountList(updated));
|
|
1329
1372
|
if (rulesModule) {
|
|
1330
|
-
const orderTotalAmount = Number(((
|
|
1373
|
+
const orderTotalAmount = Number(((_a = orderStore.summary) == null ? void 0 : _a.total_amount) || 0);
|
|
1331
1374
|
console.log("[BaseSales.setDiscountSelected.calcDiscount]");
|
|
1332
1375
|
const result = rulesModule.calcDiscount(
|
|
1333
1376
|
{
|
|
1334
1377
|
productList: tempOrder.products,
|
|
1335
1378
|
discountList: updated,
|
|
1336
|
-
holders,
|
|
1379
|
+
holders: [],
|
|
1337
1380
|
isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
|
|
1338
1381
|
orderTotalAmount
|
|
1339
1382
|
},
|
|
@@ -1373,8 +1416,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1373
1416
|
return rid != null && selectedResourceIds.has(rid);
|
|
1374
1417
|
});
|
|
1375
1418
|
for (const product of tempOrder.products) {
|
|
1376
|
-
const productUid = (
|
|
1377
|
-
const runtimeOrigin = productUid ? (
|
|
1419
|
+
const productUid = (_b = product.metadata) == null ? void 0 : _b.unique_identification_number;
|
|
1420
|
+
const runtimeOrigin = productUid ? (_e = (_d = (_c = tempOrder._extend) == null ? void 0 : _c.productsByUid) == null ? void 0 : _d[productUid]) == null ? void 0 : _e.origin : void 0;
|
|
1378
1421
|
if ((runtimeOrigin == null ? void 0 : runtimeOrigin.isManualDiscount) || isBaseSalesManualProductDiscountProduct(product))
|
|
1379
1422
|
continue;
|
|
1380
1423
|
product.discount_list = filterSelectedDiscountDetails(product.discount_list);
|
|
@@ -1398,7 +1441,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
|
|
|
1398
1441
|
0
|
|
1399
1442
|
);
|
|
1400
1443
|
const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(product));
|
|
1401
|
-
const sourcePrice = ((
|
|
1444
|
+
const sourcePrice = ((_f = product.metadata) == null ? void 0 : _f.source_product_price) ?? (((_g = product.metadata) == null ? void 0 : _g.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
|
|
1402
1445
|
const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
1403
1446
|
const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
1404
1447
|
if (product.metadata) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Discount } from '../../modules/Discount/types';
|
|
1
2
|
import { OrderModule, ProductList, QuotationModule, SalesSummaryModule, ScanOrderLoggerModule as BaseSalesLoggerModule, ScheduleModule } from '../../modules';
|
|
2
3
|
import type { ScanOrderLogInput as BaseSalesLogInput, ScanOrderLoggerProviderConfig as BaseSalesLoggerProviderConfig, ScanOrderLoggerProviderType as BaseSalesLoggerProviderType } from '../../modules/ScanOrderLogger/types';
|
|
3
4
|
import type { QuantityCheckResult, QuantityLimitResult } from '../../model/strategy/adapter/itemRule';
|
|
@@ -85,6 +86,8 @@ export interface BaseSalesOrderProduct extends BaseSalesOrderProductIdentity {
|
|
|
85
86
|
booking_uid?: string;
|
|
86
87
|
/** 多语言商品标题快照,随 tempOrder 提交到 checkout。 */
|
|
87
88
|
product_title?: BaseSalesLocalizedText;
|
|
89
|
+
/** 商品封面图快照,随 tempOrder 提交到 checkout。 */
|
|
90
|
+
product_cover?: string;
|
|
88
91
|
/**
|
|
89
92
|
* 行级扩展 metadata。价格相关的权威字段:
|
|
90
93
|
*
|
|
@@ -381,9 +384,11 @@ export interface BaseSalesLoggerRuntimeConfig {
|
|
|
381
384
|
}
|
|
382
385
|
export interface BaseSalesAddLogParams extends BaseSalesLogInput {
|
|
383
386
|
}
|
|
384
|
-
/** BaseSales.scanPromotionCode
|
|
387
|
+
/** BaseSales.scanPromotionCode 对外的轻量结果(UI 可用 getDiscountList 或 scannedDiscountList 补 Holder) */
|
|
385
388
|
export interface BaseSalesScanCodeResult {
|
|
386
389
|
isAvailable: boolean;
|
|
387
390
|
type?: 'server' | string;
|
|
388
391
|
unavailableReason?: 'time_limit' | string;
|
|
392
|
+
/** batchSearch 原始结果;isAvailable=false 时 discountList 可能未写入 store,Holder 补全需读此字段 */
|
|
393
|
+
scannedDiscountList?: Discount[];
|
|
389
394
|
}
|
|
@@ -50,6 +50,12 @@ function toPriceString(value, fallback = "0.00") {
|
|
|
50
50
|
return fallback;
|
|
51
51
|
return parsedValue.toFixed(2);
|
|
52
52
|
}
|
|
53
|
+
function isBlankValue(value) {
|
|
54
|
+
return value === void 0 || value === null || typeof value === "string" && value.trim() === "";
|
|
55
|
+
}
|
|
56
|
+
function firstNonBlank(...values) {
|
|
57
|
+
return values.find((value) => !isBlankValue(value));
|
|
58
|
+
}
|
|
53
59
|
function normalizeOptionItems(optionItems) {
|
|
54
60
|
if (!Array.isArray(optionItems))
|
|
55
61
|
return [];
|
|
@@ -198,6 +204,7 @@ function transformBaseProductToOrderProduct(params) {
|
|
|
198
204
|
main_product_selling_price: mainProductSellingPrice,
|
|
199
205
|
main_product_original_price: mainProductOriginalPrice,
|
|
200
206
|
price_schema_version: 2,
|
|
207
|
+
holder_config: sourceProduct == null ? void 0 : sourceProduct.holder_config,
|
|
201
208
|
...hasPriceOverride ? {
|
|
202
209
|
price_override: String(payload.price_override),
|
|
203
210
|
is_manual_discount: 1
|
|
@@ -236,6 +243,7 @@ function transformBaseProductToOrderProduct(params) {
|
|
|
236
243
|
metadata,
|
|
237
244
|
note: payload.note != null ? String(payload.note) : "",
|
|
238
245
|
product_title: productTitle,
|
|
246
|
+
product_cover: firstNonBlank(matchedVariant == null ? void 0 : matchedVariant.cover, sourceProduct == null ? void 0 : sourceProduct.cover),
|
|
239
247
|
_origin: {
|
|
240
248
|
...sourceProduct || {},
|
|
241
249
|
callbackData: payload
|
|
@@ -341,15 +341,21 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
341
341
|
if (!this.store.order)
|
|
342
342
|
throw new Error("order 模块未初始化");
|
|
343
343
|
const raw = await this.store.order.scanCode(code, customerId);
|
|
344
|
+
const scannedList = raw.scannedDiscountList || [];
|
|
345
|
+
const extractedCustomerId = this.getDiscountCustomerId(scannedList);
|
|
346
|
+
const hasOrderCustomer = Boolean(this.store.order.getOrderCustomer());
|
|
347
|
+
if (!hasOrderCustomer && extractedCustomerId) {
|
|
348
|
+
await this.hydrateOrderCustomerFromScanDiscounts(scannedList);
|
|
349
|
+
}
|
|
344
350
|
if (raw.isAvailable) {
|
|
345
|
-
await this.hydrateOrderCustomerFromScanDiscounts(raw.scannedDiscountList || []);
|
|
346
351
|
await this.store.order.recalculateSummary({ createIfMissing: true });
|
|
347
352
|
this.store.order.persistTempOrder();
|
|
348
353
|
}
|
|
349
354
|
return {
|
|
350
355
|
isAvailable: raw.isAvailable,
|
|
351
356
|
type: raw.type,
|
|
352
|
-
unavailableReason: raw.unavailableReason
|
|
357
|
+
unavailableReason: raw.unavailableReason,
|
|
358
|
+
scannedDiscountList: raw.scannedDiscountList
|
|
353
359
|
};
|
|
354
360
|
}
|
|
355
361
|
async hydrateOrderCustomerFromScanDiscounts(discounts) {
|
|
@@ -366,11 +372,13 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
|
|
|
366
372
|
this.setOrderCustomer(customer);
|
|
367
373
|
}
|
|
368
374
|
getDiscountCustomerId(discounts) {
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
375
|
+
for (const item of discounts) {
|
|
376
|
+
const topLevelId = Number(item.customer_id);
|
|
377
|
+
if (Number.isFinite(topLevelId) && topLevelId > 0) {
|
|
378
|
+
return topLevelId;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
374
382
|
}
|
|
375
383
|
async resolveCustomerByDiscountCustomerId(customerId) {
|
|
376
384
|
var _a;
|