@pisell/pisellos 2.2.301 → 2.2.303
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/dataVariant/evaluator.d.ts +18 -2
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +135 -35
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +25 -1
- package/dist/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/dist/model/strategy/adapter/itemRule/type.js +19 -1
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +10 -7
- package/dist/modules/Discount/index.d.ts +2 -0
- package/dist/modules/Discount/index.js +41 -5
- package/dist/modules/Discount/types.d.ts +21 -0
- package/dist/modules/OpenData/index.d.ts +15 -2
- package/dist/modules/OpenData/index.js +307 -19
- package/dist/modules/OpenData/types.d.ts +55 -0
- package/dist/modules/OpenData/types.js +7 -1
- package/dist/modules/OpenData/utils.d.ts +21 -1
- package/dist/modules/OpenData/utils.js +138 -0
- package/dist/modules/Order/index.d.ts +50 -7
- package/dist/modules/Order/index.js +1690 -815
- package/dist/modules/Order/salesNotes.d.ts +31 -0
- package/dist/modules/Order/salesNotes.js +492 -0
- package/dist/modules/Order/types.d.ts +117 -10
- package/dist/modules/Order/types.js +6 -1
- package/dist/modules/Order/utils/virtualSettlement.d.ts +63 -0
- package/dist/modules/Order/utils/virtualSettlement.js +284 -0
- package/dist/modules/Order/utils.d.ts +5 -1
- package/dist/modules/Order/utils.js +138 -33
- package/dist/modules/Payment/walletpass.js +20 -21
- package/dist/modules/Product/types.d.ts +23 -0
- package/dist/modules/ProductList/index.d.ts +2 -1
- package/dist/modules/ProductList/index.js +100 -20
- package/dist/modules/ProductList/types.d.ts +10 -0
- package/dist/modules/Rules/index.d.ts +5 -0
- package/dist/modules/Rules/index.js +30 -14
- package/dist/modules/SalesSummary/index.d.ts +1 -0
- package/dist/modules/SalesSummary/index.js +4 -3
- package/dist/modules/SalesSummary/types.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.js +21 -1
- package/dist/plugins/request.d.ts +2 -1
- package/dist/plugins/request.js +4 -2
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.js +1774 -1285
- package/dist/server/modules/order/types.d.ts +50 -0
- package/dist/server/modules/order/types.js +2 -0
- package/dist/server/utils/small-ticket.d.ts +4 -1
- package/dist/server/utils/small-ticket.js +461 -96
- package/dist/solution/BaseSales/index.d.ts +26 -3
- package/dist/solution/BaseSales/index.js +1492 -873
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +2 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +1 -1
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +72 -9
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +8 -3
- package/dist/solution/BookingTicket/index.js +558 -443
- package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
- package/dist/solution/BookingTicket/utils/orderCustomer.js +3 -2
- package/dist/solution/RegisterAndLogin/config.d.ts +9 -3
- package/dist/solution/RegisterAndLogin/config.js +95 -40
- package/dist/solution/RegisterAndLogin/index.js +4 -1
- package/dist/solution/Sales/index.d.ts +16 -1
- package/dist/solution/Sales/index.js +338 -63
- package/dist/solution/Sales/types.d.ts +10 -0
- package/dist/solution/ScanOrder/index.d.ts +1 -0
- package/dist/solution/ScanOrder/index.js +31 -27
- package/dist/solution/ScanOrder/utils.d.ts +1 -0
- package/dist/solution/ScanOrder/utils.js +2 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +20 -6
- package/dist/solution/UnifiedBookingSales/index.js +874 -527
- package/dist/solution/UnifiedBookingSales/types.d.ts +21 -2
- package/dist/solution/VenueBooking/index.d.ts +1 -0
- package/dist/solution/VenueBooking/index.js +8 -4
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +137 -6
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +73 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +23 -1
- package/lib/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/lib/model/strategy/adapter/itemRule/type.js +19 -1
- package/lib/model/strategy/adapter/promotion/index.js +1 -46
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +4 -0
- package/lib/modules/Discount/index.d.ts +2 -0
- package/lib/modules/Discount/index.js +34 -2
- package/lib/modules/Discount/types.d.ts +21 -0
- package/lib/modules/OpenData/index.d.ts +15 -2
- package/lib/modules/OpenData/index.js +230 -3
- package/lib/modules/OpenData/types.d.ts +55 -0
- package/lib/modules/OpenData/types.js +9 -1
- package/lib/modules/OpenData/utils.d.ts +21 -1
- package/lib/modules/OpenData/utils.js +126 -0
- package/lib/modules/Order/index.d.ts +50 -7
- package/lib/modules/Order/index.js +704 -64
- package/lib/modules/Order/salesNotes.d.ts +31 -0
- package/lib/modules/Order/salesNotes.js +382 -0
- package/lib/modules/Order/types.d.ts +117 -10
- package/lib/modules/Order/types.js +5 -1
- package/lib/modules/Order/utils/virtualSettlement.d.ts +63 -0
- package/lib/modules/Order/utils/virtualSettlement.js +262 -0
- package/lib/modules/Order/utils.d.ts +5 -1
- package/lib/modules/Order/utils.js +127 -21
- package/lib/modules/Payment/walletpass.js +14 -11
- package/lib/modules/Product/types.d.ts +23 -0
- package/lib/modules/ProductList/index.d.ts +2 -1
- package/lib/modules/ProductList/index.js +47 -2
- package/lib/modules/ProductList/types.d.ts +10 -0
- package/lib/modules/Rules/index.d.ts +5 -0
- package/lib/modules/Rules/index.js +22 -12
- package/lib/modules/SalesSummary/index.d.ts +1 -0
- package/lib/modules/SalesSummary/index.js +4 -2
- package/lib/modules/SalesSummary/types.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.js +17 -1
- package/lib/plugins/request.d.ts +2 -1
- package/lib/plugins/request.js +3 -2
- package/lib/server/index.d.ts +21 -0
- package/lib/server/index.js +492 -108
- package/lib/server/modules/order/types.d.ts +50 -0
- package/lib/server/modules/order/types.js +1 -0
- package/lib/server/utils/small-ticket.d.ts +4 -1
- package/lib/server/utils/small-ticket.js +427 -72
- package/lib/solution/BaseSales/index.d.ts +26 -3
- package/lib/solution/BaseSales/index.js +439 -30
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +2 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +1 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +38 -0
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +8 -3
- package/lib/solution/BookingTicket/index.js +60 -15
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -0
- package/lib/solution/BookingTicket/utils/orderCustomer.js +2 -1
- package/lib/solution/RegisterAndLogin/config.d.ts +9 -3
- package/lib/solution/RegisterAndLogin/config.js +49 -8
- package/lib/solution/RegisterAndLogin/index.js +4 -1
- package/lib/solution/Sales/index.d.ts +16 -1
- package/lib/solution/Sales/index.js +168 -1
- package/lib/solution/Sales/types.d.ts +10 -0
- package/lib/solution/ScanOrder/index.d.ts +1 -0
- package/lib/solution/ScanOrder/index.js +5 -1
- package/lib/solution/ScanOrder/utils.d.ts +1 -0
- package/lib/solution/ScanOrder/utils.js +1 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +20 -6
- package/lib/solution/UnifiedBookingSales/index.js +169 -16
- package/lib/solution/UnifiedBookingSales/types.d.ts +21 -2
- package/lib/solution/VenueBooking/index.d.ts +1 -0
- package/lib/solution/VenueBooking/index.js +5 -1
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
|
25
25
|
var _lodashEs = require("lodash-es");
|
|
26
26
|
var _types2 = require("../BookingByStep/types");
|
|
27
27
|
var _utils = require("../../modules/Order/utils");
|
|
28
|
+
var _virtualSettlement = require("../../modules/Order/utils/virtualSettlement");
|
|
28
29
|
var _paymentUtils = require("../../modules/Order/payment-utils");
|
|
29
30
|
var _paymentNumber = require("../../utils/payment-number");
|
|
30
31
|
var _orderCollectionIdentity = require("../../modules/Order/utils/orderCollectionIdentity");
|
|
@@ -37,6 +38,8 @@ var _quotationPrice = require("./utils/quotationPrice");
|
|
|
37
38
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
38
39
|
const SERVER_ORDER_CHANGED_EVENT = 'order:onOrdersChanged';
|
|
39
40
|
const OS_FULFILLMENT_REF_MODE_FIELD = '_os_fulfillment_ref_mode';
|
|
41
|
+
const OS_INVOICE_LAYOUT_CONFIG_FIELD = '_os_invoice_layout_config';
|
|
42
|
+
const OS_INVOICE_TEMPLATE_SETTINGS_FIELD = '_os_invoice_template_settings';
|
|
40
43
|
const WALLET_PAYMENT_CODE_BY_TAG = {
|
|
41
44
|
product_voucher: 'PRODUCTVOUCHER',
|
|
42
45
|
gift_card: 'GIFTCARD',
|
|
@@ -256,6 +259,22 @@ function normalizeBaseSalesRecordCollections(sourceRecord, options) {
|
|
|
256
259
|
}
|
|
257
260
|
return normalizedRecord;
|
|
258
261
|
}
|
|
262
|
+
function isValidBaseSalesSmallTicketDataSnapshot(value) {
|
|
263
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
264
|
+
const localeSnapshots = Object.values(value);
|
|
265
|
+
return localeSnapshots.length > 0 && localeSnapshots.some(localeSnapshot => localeSnapshot !== null && typeof localeSnapshot === 'object' && !Array.isArray(localeSnapshot));
|
|
266
|
+
}
|
|
267
|
+
function mergeBaseSalesSmallTicketDataSnapshot(currentValue, loadedValue) {
|
|
268
|
+
if (isValidBaseSalesSmallTicketDataSnapshot(loadedValue)) {
|
|
269
|
+
return (0, _lodashEs.cloneDeep)(loadedValue);
|
|
270
|
+
}
|
|
271
|
+
if (isValidBaseSalesSmallTicketDataSnapshot(currentValue)) {
|
|
272
|
+
return (0, _lodashEs.cloneDeep)(currentValue);
|
|
273
|
+
}
|
|
274
|
+
if (loadedValue !== undefined) return (0, _lodashEs.cloneDeep)(loadedValue);
|
|
275
|
+
if (currentValue !== undefined) return (0, _lodashEs.cloneDeep)(currentValue);
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
259
278
|
function getBaseSalesMetadataUid(item, metadataKey) {
|
|
260
279
|
const uid = item?.metadata?.[metadataKey] ?? item?.[metadataKey];
|
|
261
280
|
if (uid === undefined || uid === null || uid === '') return null;
|
|
@@ -283,7 +302,56 @@ function mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey) {
|
|
|
283
302
|
loadedValue.forEach(appendOrReplaceByUid);
|
|
284
303
|
return result;
|
|
285
304
|
}
|
|
305
|
+
|
|
306
|
+
// checkout / realtime snapshots may reorder protocol arrays or append persistence fields.
|
|
307
|
+
// Compare only the Sales Note protocol fields so a matching remote echo can acknowledge dirty state.
|
|
308
|
+
function normalizeBaseSalesNotesForComparison(value, options) {
|
|
309
|
+
if (!Array.isArray(value)) return null;
|
|
310
|
+
const unresolvedOrderTargetUuid = String(options?.unresolvedOrderTargetUuid ?? '').trim();
|
|
311
|
+
return value.map(note => {
|
|
312
|
+
if (!note || typeof note !== 'object' || Array.isArray(note)) {
|
|
313
|
+
return (0, _lodashEs.cloneDeep)(note);
|
|
314
|
+
}
|
|
315
|
+
const noteRecord = note;
|
|
316
|
+
const relations = Array.isArray(noteRecord.note_relations) ? noteRecord.note_relations.map(relation => {
|
|
317
|
+
if (!relation || typeof relation !== 'object' || Array.isArray(relation)) {
|
|
318
|
+
return (0, _lodashEs.cloneDeep)(relation);
|
|
319
|
+
}
|
|
320
|
+
const shouldResolveOrderTarget = relation.is_primary === 0 && relation.relation_type === 'related_to' && relation.target_type === 'order' && String(relation.target_uuid ?? '').trim() === '' && unresolvedOrderTargetUuid.length > 0;
|
|
321
|
+
return {
|
|
322
|
+
uuid: relation.uuid,
|
|
323
|
+
relation_type: relation.relation_type,
|
|
324
|
+
target_type: relation.target_type,
|
|
325
|
+
target_uuid: shouldResolveOrderTarget ? unresolvedOrderTargetUuid : relation.target_uuid,
|
|
326
|
+
is_primary: relation.is_primary
|
|
327
|
+
};
|
|
328
|
+
}).sort((left, right) => String(left?.uuid ?? '').localeCompare(String(right?.uuid ?? ''))) : (0, _lodashEs.cloneDeep)(noteRecord.note_relations);
|
|
329
|
+
return {
|
|
330
|
+
uuid: noteRecord.uuid,
|
|
331
|
+
note_type: noteRecord.note_type,
|
|
332
|
+
content: {
|
|
333
|
+
text: (0, _lodashEs.cloneDeep)(noteRecord.content?.text)
|
|
334
|
+
},
|
|
335
|
+
importance: noteRecord.importance,
|
|
336
|
+
note_relations: relations
|
|
337
|
+
};
|
|
338
|
+
}).sort((left, right) => String(left?.uuid ?? '').localeCompare(String(right?.uuid ?? '')));
|
|
339
|
+
}
|
|
340
|
+
function areBaseSalesNotesEquivalent(currentValue, loadedValue, options) {
|
|
341
|
+
const currentNotes = normalizeBaseSalesNotesForComparison(currentValue, {
|
|
342
|
+
unresolvedOrderTargetUuid: options?.currentOrderTargetUuid
|
|
343
|
+
});
|
|
344
|
+
const loadedNotes = normalizeBaseSalesNotesForComparison(loadedValue);
|
|
345
|
+
return currentNotes !== null && loadedNotes !== null && (0, _lodashEs.isEqual)(currentNotes, loadedNotes);
|
|
346
|
+
}
|
|
286
347
|
function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord, strategy) {
|
|
348
|
+
const loadedHasSalesNotes = Object.prototype.hasOwnProperty.call(loadedRecord || {}, 'notes');
|
|
349
|
+
const hasDirtyLocalSalesNotes = currentTempOrder?._extend?.salesNotesState?.dirty === true;
|
|
350
|
+
const incomingSalesNotesMatchLocal = loadedHasSalesNotes && areBaseSalesNotesEquivalent(currentTempOrder?.notes, loadedRecord.notes, {
|
|
351
|
+
currentOrderTargetUuid: loadedRecord?.shop_order_number || currentTempOrder?.shop_order_number
|
|
352
|
+
});
|
|
353
|
+
const shouldAwaitAuthoritativeSalesNotes = strategy === 'authoritative-incoming' && hasDirtyLocalSalesNotes && (Number(loadedRecord?.need_sync) === 1 || !incomingSalesNotesMatchLocal);
|
|
354
|
+
const preserveDirtyLocalSalesNotes = hasDirtyLocalSalesNotes && (strategy === 'preserve-local' || shouldAwaitAuthoritativeSalesNotes);
|
|
287
355
|
const normalizedLoadedRecord = normalizeBaseSalesRecordCollections(loadedRecord || {}, {
|
|
288
356
|
ensureUid: false
|
|
289
357
|
});
|
|
@@ -295,6 +363,17 @@ function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord, str
|
|
|
295
363
|
});
|
|
296
364
|
const uidRemaps = [];
|
|
297
365
|
const mergedRecord = (0, _lodashEs.mergeWith)(normalizedCurrentTempOrder, normalizedLoadedRecord, (currentValue, loadedValue, key) => {
|
|
366
|
+
if (key === 'notes') {
|
|
367
|
+
if (preserveDirtyLocalSalesNotes && Array.isArray(currentValue)) {
|
|
368
|
+
return (0, _lodashEs.cloneDeep)(currentValue);
|
|
369
|
+
}
|
|
370
|
+
if (Array.isArray(loadedValue)) return (0, _lodashEs.cloneDeep)(loadedValue);
|
|
371
|
+
}
|
|
372
|
+
// small_ticket_data 是由 Server 一次性生成的完整展示快照,不能递归进入
|
|
373
|
+
// locale 内部继续套用订单集合或普通数组的合并规则。
|
|
374
|
+
if (key === 'small_ticket_data') {
|
|
375
|
+
return mergeBaseSalesSmallTicketDataSnapshot(currentValue, loadedValue);
|
|
376
|
+
}
|
|
298
377
|
const collectionKind = getBaseSalesOrderCollectionKind(key);
|
|
299
378
|
if (collectionKind && Array.isArray(loadedValue)) {
|
|
300
379
|
return mergeBaseSalesOrderCollection(collectionKind, Array.isArray(currentValue) ? currentValue : [], loadedValue, strategy, uidRemaps);
|
|
@@ -318,7 +397,24 @@ function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord, str
|
|
|
318
397
|
return undefined;
|
|
319
398
|
});
|
|
320
399
|
delete mergedRecord.request_unique_idempotency_token;
|
|
321
|
-
|
|
400
|
+
const normalizedMergedRecord = normalizeBaseSalesRecordCollections((0, _orderCollectionIdentity.applyOrderCollectionUidRemaps)(mergedRecord, uidRemaps));
|
|
401
|
+
normalizedMergedRecord._extend = {
|
|
402
|
+
...(normalizedMergedRecord._extend || {}),
|
|
403
|
+
salesNotesState: preserveDirtyLocalSalesNotes ? {
|
|
404
|
+
loaded: true,
|
|
405
|
+
dirty: true
|
|
406
|
+
} : loadedHasSalesNotes ? {
|
|
407
|
+
loaded: true,
|
|
408
|
+
dirty: normalizedLoadedRecord._extend?.salesNotesState?.dirty === true
|
|
409
|
+
} : {
|
|
410
|
+
loaded: false,
|
|
411
|
+
dirty: false
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
if (!loadedHasSalesNotes && !preserveDirtyLocalSalesNotes) {
|
|
415
|
+
delete normalizedMergedRecord.notes;
|
|
416
|
+
}
|
|
417
|
+
return normalizedMergedRecord;
|
|
322
418
|
}
|
|
323
419
|
function filterPendingPaymentsFromLoadedSalesDetail(sourceRecord) {
|
|
324
420
|
if (!sourceRecord || typeof sourceRecord !== 'object') return sourceRecord;
|
|
@@ -1042,6 +1138,11 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1042
1138
|
getSubmitOrderSalesChannel() {
|
|
1043
1139
|
return this.otherParams?.channel;
|
|
1044
1140
|
}
|
|
1141
|
+
|
|
1142
|
+
/** Subclasses with target-scoped OpenData override this guard before reusing the cache. */
|
|
1143
|
+
isInvoiceOpenDataCacheCurrent() {
|
|
1144
|
+
return true;
|
|
1145
|
+
}
|
|
1045
1146
|
getFulfillmentRefModeConfigs() {
|
|
1046
1147
|
const candidates = [this.otherParams?.openData, this.otherParams?.dineInConfig, this.store?.openData?.getOpenData?.()];
|
|
1047
1148
|
return candidates.filter(candidate => candidate && typeof candidate === 'object' && !Array.isArray(candidate));
|
|
@@ -1055,14 +1156,52 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1055
1156
|
}
|
|
1056
1157
|
return undefined;
|
|
1057
1158
|
}
|
|
1058
|
-
|
|
1159
|
+
getCachedInvoiceLayoutConfig() {
|
|
1160
|
+
const openDataModule = this.store?.openData;
|
|
1161
|
+
if (typeof openDataModule?.getInvoiceLayoutConfig !== 'function') return undefined;
|
|
1162
|
+
if (!this.isInvoiceOpenDataCacheCurrent()) return undefined;
|
|
1163
|
+
try {
|
|
1164
|
+
return openDataModule.getInvoiceLayoutConfig();
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
this.logWarning('读取 Invoice OpenData 布局失败,提交时不注入布局配置', {
|
|
1167
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1168
|
+
});
|
|
1169
|
+
return undefined;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
getCachedInvoiceTemplateSettings() {
|
|
1173
|
+
const openDataModule = this.store?.openData;
|
|
1174
|
+
if (typeof openDataModule?.getInvoiceTemplateSettings !== 'function') return undefined;
|
|
1175
|
+
if (!this.isInvoiceOpenDataCacheCurrent()) return undefined;
|
|
1176
|
+
try {
|
|
1177
|
+
return openDataModule.getInvoiceTemplateSettings();
|
|
1178
|
+
} catch (error) {
|
|
1179
|
+
this.logWarning('读取 Invoice OpenData 模板配置失败,提交时不注入模板配置', {
|
|
1180
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1181
|
+
});
|
|
1182
|
+
return undefined;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
buildSubmitPayloadEnhancerWithOpenDataConfig(enhancePayload) {
|
|
1059
1186
|
const fulfillmentRefMode = this.getFulfillmentRefMode();
|
|
1060
|
-
|
|
1187
|
+
const invoiceLayoutConfig = this.getCachedInvoiceLayoutConfig();
|
|
1188
|
+
const invoiceTemplateSettings = this.getCachedInvoiceTemplateSettings();
|
|
1189
|
+
if (!fulfillmentRefMode && !invoiceLayoutConfig && !invoiceTemplateSettings) {
|
|
1190
|
+
return enhancePayload;
|
|
1191
|
+
}
|
|
1061
1192
|
return (payload, ctx) => {
|
|
1062
1193
|
const enhancedPayload = enhancePayload ? enhancePayload(payload, ctx) : payload;
|
|
1063
1194
|
return {
|
|
1064
1195
|
...enhancedPayload,
|
|
1065
|
-
|
|
1196
|
+
...(fulfillmentRefMode ? {
|
|
1197
|
+
[OS_FULFILLMENT_REF_MODE_FIELD]: fulfillmentRefMode
|
|
1198
|
+
} : {}),
|
|
1199
|
+
...(invoiceLayoutConfig ? {
|
|
1200
|
+
[OS_INVOICE_LAYOUT_CONFIG_FIELD]: (0, _lodashEs.cloneDeep)(invoiceLayoutConfig)
|
|
1201
|
+
} : {}),
|
|
1202
|
+
...(invoiceTemplateSettings ? {
|
|
1203
|
+
[OS_INVOICE_TEMPLATE_SETTINGS_FIELD]: (0, _lodashEs.cloneDeep)(invoiceTemplateSettings)
|
|
1204
|
+
} : {})
|
|
1066
1205
|
};
|
|
1067
1206
|
};
|
|
1068
1207
|
}
|
|
@@ -1181,11 +1320,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1181
1320
|
}
|
|
1182
1321
|
return (0, _paymentNumber.resolvePaymentNumberDevicePrefix)(key => this.getAppData(key));
|
|
1183
1322
|
}
|
|
1323
|
+
isMultiCurrencySettlementEnabled() {
|
|
1324
|
+
return this.otherParams?.enableMultiCurrencySettlement === true;
|
|
1325
|
+
}
|
|
1326
|
+
isActiveVirtualSettlementOrder(tempOrder) {
|
|
1327
|
+
return this.isMultiCurrencySettlementEnabled() && (0, _virtualSettlement.isVirtualSettlementOrder)(tempOrder);
|
|
1328
|
+
}
|
|
1329
|
+
isHistoricalVirtualSettlementOrder(tempOrder) {
|
|
1330
|
+
return tempOrder?.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
|
|
1331
|
+
}
|
|
1184
1332
|
syncAppDataToTempOrder(tempOrder) {
|
|
1185
1333
|
const isPriceIncludeTax = this.getAppData('is_price_include_tax');
|
|
1186
1334
|
const taxCountryCode = this.getAppData('tax_country_code');
|
|
1187
1335
|
const currencyCode = this.getAppData('shop_currency_code');
|
|
1188
1336
|
const currencySymbol = this.getAppData('shop_symbol');
|
|
1337
|
+
// 历史虚拟币订单不依赖交易开关;普通 POS 不从商品行残留快照推断订单币种。
|
|
1338
|
+
const isHistoricalVirtualSettlement = this.isHistoricalVirtualSettlementOrder(tempOrder);
|
|
1339
|
+
const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder) || isHistoricalVirtualSettlement;
|
|
1340
|
+
const shouldManageLegalCurrencySnapshot = this.isMultiCurrencySettlementEnabled() || isHistoricalVirtualSettlement;
|
|
1189
1341
|
let isChanged = false;
|
|
1190
1342
|
if (isPriceIncludeTax !== undefined) {
|
|
1191
1343
|
const nextIsPriceIncludeTax = Number(isPriceIncludeTax);
|
|
@@ -1201,14 +1353,26 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1201
1353
|
isChanged = true;
|
|
1202
1354
|
}
|
|
1203
1355
|
}
|
|
1204
|
-
|
|
1356
|
+
tempOrder.metadata = tempOrder.metadata || {};
|
|
1357
|
+
if (shouldManageLegalCurrencySnapshot) {
|
|
1358
|
+
const legalCurrencySnapshot = {
|
|
1359
|
+
currency_code: String(currencyCode ?? tempOrder.metadata.legal_currency_snapshot?.currency_code ?? tempOrder.currency_code ?? ''),
|
|
1360
|
+
currency_symbol: String(currencySymbol ?? tempOrder.metadata.legal_currency_snapshot?.currency_symbol ?? tempOrder.currency_symbol ?? ''),
|
|
1361
|
+
currency_format: String(tempOrder.metadata.legal_currency_snapshot?.currency_format || (isVirtualSettlement ? 'symbol_first' : tempOrder.currency_format) || 'symbol_first')
|
|
1362
|
+
};
|
|
1363
|
+
if (JSON.stringify(tempOrder.metadata.legal_currency_snapshot || {}) !== JSON.stringify(legalCurrencySnapshot)) {
|
|
1364
|
+
tempOrder.metadata.legal_currency_snapshot = legalCurrencySnapshot;
|
|
1365
|
+
isChanged = true;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
if (!isVirtualSettlement && currencyCode !== undefined) {
|
|
1205
1369
|
const nextCurrencyCode = String(currencyCode || '');
|
|
1206
1370
|
if (tempOrder.currency_code !== nextCurrencyCode) {
|
|
1207
1371
|
tempOrder.currency_code = nextCurrencyCode;
|
|
1208
1372
|
isChanged = true;
|
|
1209
1373
|
}
|
|
1210
1374
|
}
|
|
1211
|
-
if (currencySymbol !== undefined) {
|
|
1375
|
+
if (!isVirtualSettlement && currencySymbol !== undefined) {
|
|
1212
1376
|
const nextCurrencySymbol = String(currencySymbol || '');
|
|
1213
1377
|
if (tempOrder.currency_symbol !== nextCurrencySymbol) {
|
|
1214
1378
|
tempOrder.currency_symbol = nextCurrencySymbol;
|
|
@@ -1426,6 +1590,30 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1426
1590
|
if (!this.store.order) return '';
|
|
1427
1591
|
return this.store.order.getTempOrderNote();
|
|
1428
1592
|
}
|
|
1593
|
+
getSalesNotes() {
|
|
1594
|
+
if (!this.store.order) return [];
|
|
1595
|
+
return this.store.order.getSalesNotes();
|
|
1596
|
+
}
|
|
1597
|
+
createSalesNotesMutationSnapshot() {
|
|
1598
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1599
|
+
return this.store.order.createSalesNotesMutationSnapshot();
|
|
1600
|
+
}
|
|
1601
|
+
restoreSalesNotesMutationSnapshot(snapshot) {
|
|
1602
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1603
|
+
this.store.order.restoreSalesNotesMutationSnapshot(snapshot);
|
|
1604
|
+
}
|
|
1605
|
+
async setSalesNote(input) {
|
|
1606
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1607
|
+
return this.store.order.setSalesNote(input);
|
|
1608
|
+
}
|
|
1609
|
+
async removeSalesNote(uuid) {
|
|
1610
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1611
|
+
await this.store.order.removeSalesNote(uuid);
|
|
1612
|
+
}
|
|
1613
|
+
async clearSalesNotes() {
|
|
1614
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1615
|
+
await this.store.order.clearSalesNotes();
|
|
1616
|
+
}
|
|
1429
1617
|
updateTempOrderNote(note, sync = false) {
|
|
1430
1618
|
try {
|
|
1431
1619
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
@@ -1439,6 +1627,12 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1439
1627
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1440
1628
|
this.store.order.syncTempOrderNoteToRemote(orderId, note);
|
|
1441
1629
|
}
|
|
1630
|
+
|
|
1631
|
+
/** 存储用户自定义取餐标识到当前 tempOrder.buzzer。 */
|
|
1632
|
+
setPickupRef(buzzer) {
|
|
1633
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1634
|
+
return this.store.order.updateTempOrderBuzzer(buzzer);
|
|
1635
|
+
}
|
|
1442
1636
|
updateTempOrderShopDiscount(amount) {
|
|
1443
1637
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1444
1638
|
return this.store.order.updateTempOrderShopDiscount(amount);
|
|
@@ -1447,6 +1641,14 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1447
1641
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1448
1642
|
return this.store.order.updateTempOrderDepositAmount(amount);
|
|
1449
1643
|
}
|
|
1644
|
+
setPickupReferenceMode(mode) {
|
|
1645
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1646
|
+
return this.store.order.updateTempOrderPickupReferenceMode(mode);
|
|
1647
|
+
}
|
|
1648
|
+
setServiceType(serviceType) {
|
|
1649
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1650
|
+
return this.store.order.updateTempOrderServiceType(serviceType);
|
|
1651
|
+
}
|
|
1450
1652
|
updateTempOrderContactsInfo(contactsInfo) {
|
|
1451
1653
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1452
1654
|
return this.store.order.updateTempOrderContactsInfo(contactsInfo);
|
|
@@ -1550,6 +1752,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1550
1752
|
throw error;
|
|
1551
1753
|
}
|
|
1552
1754
|
}
|
|
1755
|
+
|
|
1756
|
+
/** 切换法币 / WalletPass 单位时清空商品、折扣与支付状态,保留客户。 */
|
|
1757
|
+
async clearOrderForSettlementSwitch() {
|
|
1758
|
+
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1759
|
+
const tempOrder = await this.store.order.clearOrderForSettlementSwitch();
|
|
1760
|
+
if (this.currentSalesDetail) {
|
|
1761
|
+
this.currentSalesDetail = {
|
|
1762
|
+
...this.currentSalesDetail,
|
|
1763
|
+
products: [],
|
|
1764
|
+
bookings: [],
|
|
1765
|
+
rootBooking: null,
|
|
1766
|
+
bookingsByProductUid: {},
|
|
1767
|
+
discount_list: [],
|
|
1768
|
+
payments: []
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
return tempOrder;
|
|
1772
|
+
}
|
|
1553
1773
|
getOrderProducts() {
|
|
1554
1774
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1555
1775
|
const products = this.store.order.getOrderProducts();
|
|
@@ -1675,9 +1895,14 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1675
1895
|
const hasManualDiscountSelection = this.hasManualDiscountSelection || currentDiscountList.some(discount => discount.isManualSelect);
|
|
1676
1896
|
const discountAction = params?.action || (orderId ? 'edit' : 'create');
|
|
1677
1897
|
const discountConfigCacheKey = [customerId, discountAction, Number(orderId) || 0].join(':');
|
|
1678
|
-
|
|
1898
|
+
|
|
1899
|
+
// Walk-In 不请求 prepare config;当前搜索/扫码券必须继续参与本次重算。
|
|
1900
|
+
// current 优先于 original,保留搜索后的最新选择与可用状态。
|
|
1901
|
+
const searchedDiscountList = currentDiscountList.filter(discount => discount.isScan);
|
|
1902
|
+
const searchedDiscountIds = new Set(searchedDiscountList.map(discount => String(discount.id)));
|
|
1903
|
+
let preparedDiscountList = [...searchedDiscountList, ...originalDiscountList.filter(discount => !searchedDiscountIds.has(String(discount.id)))];
|
|
1679
1904
|
if (customerId && customerId !== 1) {
|
|
1680
|
-
if (this.discountConfigCacheKey === discountConfigCacheKey) {
|
|
1905
|
+
if (!params?.force && this.discountConfigCacheKey === discountConfigCacheKey) {
|
|
1681
1906
|
preparedDiscountList = originalDiscountList;
|
|
1682
1907
|
} else {
|
|
1683
1908
|
preparedDiscountList = await this.store.order.loadDiscountConfig({
|
|
@@ -1690,11 +1915,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1690
1915
|
await discountModule?.setOriginalDiscountList?.(preparedDiscountList);
|
|
1691
1916
|
}
|
|
1692
1917
|
}
|
|
1918
|
+
if (this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
1919
|
+
await discountModule?.setOriginalDiscountList?.([]);
|
|
1920
|
+
await discountModule?.setDiscountList?.([]);
|
|
1921
|
+
tempOrder.discount_list = [];
|
|
1922
|
+
tempOrder.shop_discount = '0.00';
|
|
1923
|
+
return {
|
|
1924
|
+
productList: tempOrder.products || [],
|
|
1925
|
+
discountList: [],
|
|
1926
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
1927
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1693
1930
|
if (hasManualDiscountSelection && currentDiscountList.length) {
|
|
1694
1931
|
return {
|
|
1695
1932
|
productList: tempOrder.products || [],
|
|
1696
1933
|
discountList: currentDiscountList,
|
|
1697
|
-
availableWalletIds: this.getAvailableWalletIds()
|
|
1934
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
1935
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1698
1936
|
};
|
|
1699
1937
|
}
|
|
1700
1938
|
let nextDiscountList = this.mergeHistoricalDiscountList(preparedDiscountList || discountModule?.getDiscountList?.() || [], tempOrder.products || []);
|
|
@@ -1720,7 +1958,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1720
1958
|
return {
|
|
1721
1959
|
productList: tempOrder.products || [],
|
|
1722
1960
|
discountList: nextDiscountList,
|
|
1723
|
-
availableWalletIds: this.getAvailableWalletIds()
|
|
1961
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
1962
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1724
1963
|
};
|
|
1725
1964
|
}
|
|
1726
1965
|
if (rulesModule) {
|
|
@@ -1776,16 +2015,29 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1776
2015
|
return {
|
|
1777
2016
|
productList: tempOrder.products || [],
|
|
1778
2017
|
discountList: nextDiscountList,
|
|
1779
|
-
availableWalletIds: this.getAvailableWalletIds()
|
|
2018
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
2019
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1780
2020
|
};
|
|
1781
2021
|
}
|
|
1782
2022
|
getAvailableWalletIds() {
|
|
1783
2023
|
if (!this.store.order?.getAvailableWalletIds) return [];
|
|
1784
2024
|
return this.store.order.getAvailableWalletIds();
|
|
1785
2025
|
}
|
|
2026
|
+
getVirtualCurrencyList() {
|
|
2027
|
+
if (!this.store.order?.getVirtualCurrencyList) return [];
|
|
2028
|
+
return this.store.order.getVirtualCurrencyList();
|
|
2029
|
+
}
|
|
1786
2030
|
async bestDiscount(cb) {
|
|
1787
2031
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1788
2032
|
const tempOrder = this.store.order.ensureTempOrder();
|
|
2033
|
+
if (this.isActiveVirtualSettlementOrder(tempOrder)) {
|
|
2034
|
+
const result = {
|
|
2035
|
+
productList: tempOrder.products || [],
|
|
2036
|
+
discountList: []
|
|
2037
|
+
};
|
|
2038
|
+
cb?.(result);
|
|
2039
|
+
return result;
|
|
2040
|
+
}
|
|
1789
2041
|
const orderStore = this.store.order.store || {};
|
|
1790
2042
|
const discountModule = orderStore.discount;
|
|
1791
2043
|
const rulesModule = orderStore.rules;
|
|
@@ -1893,6 +2145,17 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1893
2145
|
async setDiscountSelected(params) {
|
|
1894
2146
|
try {
|
|
1895
2147
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2148
|
+
const currentOrder = this.store.order.ensureTempOrder();
|
|
2149
|
+
if (this.isActiveVirtualSettlementOrder(currentOrder)) {
|
|
2150
|
+
currentOrder.discount_list = [];
|
|
2151
|
+
currentOrder.shop_discount = '0.00';
|
|
2152
|
+
await this.store.order.store?.discount?.setDiscountList?.([]);
|
|
2153
|
+
await this.store.order.recalculateSummary({
|
|
2154
|
+
createIfMissing: true
|
|
2155
|
+
});
|
|
2156
|
+
this.store.order.persistTempOrder();
|
|
2157
|
+
return;
|
|
2158
|
+
}
|
|
1896
2159
|
const list = this.store.order.getDiscountList();
|
|
1897
2160
|
const updated = list.map(d => d.id === params.discountId && !isBaseSalesHistoricalDiscountEntry(d) ? {
|
|
1898
2161
|
...d,
|
|
@@ -2031,6 +2294,101 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2031
2294
|
// Deprecated compatibility alias. New BaseSales callers should use submitSalesOrder.
|
|
2032
2295
|
return this.submitSalesOrder(params);
|
|
2033
2296
|
}
|
|
2297
|
+
async buildVirtualSettlementSubmitData() {
|
|
2298
|
+
if (!this.store.order) return null;
|
|
2299
|
+
const tempOrder = this.store.order.getTempOrder();
|
|
2300
|
+
if (!this.isActiveVirtualSettlementOrder(tempOrder)) return null;
|
|
2301
|
+
const snapshot = (0, _virtualSettlement.getTempOrderSettlementSnapshot)(tempOrder);
|
|
2302
|
+
const currencyProductId = Number(tempOrder?.metadata?.currency_settlement_config?.settlement_ids?.[0] ?? snapshot?.currency_product_id);
|
|
2303
|
+
if (!snapshot || !Number.isFinite(currencyProductId) || currencyProductId <= 0) {
|
|
2304
|
+
throw new Error('Virtual currency settlement configuration is invalid.');
|
|
2305
|
+
}
|
|
2306
|
+
const summary = await this.store.order.recalculateSummary({
|
|
2307
|
+
createIfMissing: true
|
|
2308
|
+
});
|
|
2309
|
+
const amount = new _decimal.default(summary?.total_amount || 0).toDecimalPlaces(2);
|
|
2310
|
+
const customerId = Number(tempOrder?.customer_id || 0);
|
|
2311
|
+
if (amount.gt(0) && customerId > 0 && customerId !== 1) {
|
|
2312
|
+
await this.store.order.loadDiscountConfig({
|
|
2313
|
+
customerId,
|
|
2314
|
+
action: tempOrder?.order_id ? 'edit' : 'create',
|
|
2315
|
+
orderId: Number(tempOrder?.order_id) || undefined,
|
|
2316
|
+
apply: false
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
const asset = this.store.order.getVirtualCurrencyList().find(item => Number(item?.product_id) === currencyProductId);
|
|
2320
|
+
const currencyCode = String(tempOrder?.currency_code || '');
|
|
2321
|
+
const currencySymbol = String(tempOrder?.currency_symbol || '');
|
|
2322
|
+
const currencyFormat = String(tempOrder?.currency_format || 'symbol_first');
|
|
2323
|
+
if (amount.lte(0)) {
|
|
2324
|
+
return {
|
|
2325
|
+
payments: [],
|
|
2326
|
+
snapshot,
|
|
2327
|
+
currencyProductId,
|
|
2328
|
+
currencyCode,
|
|
2329
|
+
currencySymbol,
|
|
2330
|
+
currencyFormat
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2333
|
+
if (!asset) {
|
|
2334
|
+
throw new Error('No matching virtual currency card is available.');
|
|
2335
|
+
}
|
|
2336
|
+
const balance = new _decimal.default(asset.balance || 0);
|
|
2337
|
+
if (balance.lt(amount)) {
|
|
2338
|
+
throw new Error('Insufficient virtual currency balance.');
|
|
2339
|
+
}
|
|
2340
|
+
const amountText = amount.toFixed(2);
|
|
2341
|
+
const paymentNumber = `LOCAL_${(0, _utils.createUuidV4)()}`;
|
|
2342
|
+
let payment;
|
|
2343
|
+
if (this.store.order.isOnlineStorePlatform()) {
|
|
2344
|
+
payment = {
|
|
2345
|
+
payment_number: paymentNumber,
|
|
2346
|
+
amount: amount.toNumber(),
|
|
2347
|
+
metadata: {
|
|
2348
|
+
unique_payment_number: (0, _utils.createUuidV4)()
|
|
2349
|
+
},
|
|
2350
|
+
tag: asset.tag,
|
|
2351
|
+
voucher_id: asset.id,
|
|
2352
|
+
wallet_pass_usage_unit: {
|
|
2353
|
+
price: 1,
|
|
2354
|
+
points: 1
|
|
2355
|
+
},
|
|
2356
|
+
wallet_pass_use_value: amountText
|
|
2357
|
+
};
|
|
2358
|
+
} else {
|
|
2359
|
+
const paymentMethods = await this.getPaymentMethodsAsync();
|
|
2360
|
+
const paymentMethod = paymentMethods.find(method => String(method.code || '').toUpperCase() === 'PRODUCTVOUCHER');
|
|
2361
|
+
if (!paymentMethod) {
|
|
2362
|
+
throw new Error('PRODUCTVOUCHER payment method is unavailable.');
|
|
2363
|
+
}
|
|
2364
|
+
payment = {
|
|
2365
|
+
payment_number: paymentNumber,
|
|
2366
|
+
amount: amountText,
|
|
2367
|
+
origin_amount: amountText,
|
|
2368
|
+
code: paymentMethod.code,
|
|
2369
|
+
custom_payment_id: paymentMethod.id,
|
|
2370
|
+
custom_payment_type: paymentMethod.custom_payment_type ?? paymentMethod.type,
|
|
2371
|
+
name: paymentMethod.name,
|
|
2372
|
+
type: 'normal',
|
|
2373
|
+
voucher_id: asset.id,
|
|
2374
|
+
order_payment_type: 'normal',
|
|
2375
|
+
wallet_pass_usage_unit: {
|
|
2376
|
+
price: 1,
|
|
2377
|
+
points: 1
|
|
2378
|
+
},
|
|
2379
|
+
wallet_pass_use_value: amountText,
|
|
2380
|
+
metadata: {}
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
return {
|
|
2384
|
+
payments: [payment],
|
|
2385
|
+
snapshot,
|
|
2386
|
+
currencyProductId,
|
|
2387
|
+
currencyCode,
|
|
2388
|
+
currencySymbol,
|
|
2389
|
+
currencyFormat
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2034
2392
|
|
|
2035
2393
|
/**
|
|
2036
2394
|
* 提交当前 Sales 订单。
|
|
@@ -2042,10 +2400,11 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2042
2400
|
if (!this.store.order) {
|
|
2043
2401
|
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2044
2402
|
}
|
|
2403
|
+
const virtualSettlement = await this.buildVirtualSettlementSubmitData();
|
|
2045
2404
|
// this.store.order.persistTempOrder();
|
|
2046
2405
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2047
2406
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2048
|
-
const enhancePayload = this.
|
|
2407
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params?.enhancePayload);
|
|
2049
2408
|
const submitParams = {
|
|
2050
2409
|
cacheId: this.cacheId,
|
|
2051
2410
|
platform: this.otherParams?.platform,
|
|
@@ -2053,7 +2412,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2053
2412
|
channel: this.getSubmitOrderSalesChannel(),
|
|
2054
2413
|
type: this.otherParams?.type,
|
|
2055
2414
|
request_unique_idempotency_token: this.store.order.generateIdempotencyToken(),
|
|
2056
|
-
...(
|
|
2415
|
+
...(virtualSettlement ? {
|
|
2416
|
+
payments: virtualSettlement.payments
|
|
2417
|
+
} : params?.payments !== undefined ? {
|
|
2057
2418
|
payments: params.payments
|
|
2058
2419
|
} : {}),
|
|
2059
2420
|
...(inferredPaymentStatus !== undefined ? {
|
|
@@ -2062,10 +2423,32 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2062
2423
|
...(smallTicketDataFlag !== undefined ? {
|
|
2063
2424
|
smallTicketDataFlag
|
|
2064
2425
|
} : {}),
|
|
2065
|
-
...(
|
|
2426
|
+
...(virtualSettlement ? {
|
|
2427
|
+
confirmPendingVoucherPayments: false
|
|
2428
|
+
} : params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2066
2429
|
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2067
2430
|
} : {}),
|
|
2068
|
-
...(
|
|
2431
|
+
...(virtualSettlement ? {
|
|
2432
|
+
enhancePayload: (payload, ctx) => {
|
|
2433
|
+
const callerPayload = enhancePayload ? enhancePayload(payload, ctx) : payload;
|
|
2434
|
+
const currencySettlementConfig = callerPayload.metadata?.currency_settlement_config || {};
|
|
2435
|
+
return {
|
|
2436
|
+
...callerPayload,
|
|
2437
|
+
metadata: {
|
|
2438
|
+
...(callerPayload.metadata || {}),
|
|
2439
|
+
currency_settlement_config: {
|
|
2440
|
+
...currencySettlementConfig,
|
|
2441
|
+
settlement_type: 'virtual_currency',
|
|
2442
|
+
settlement_ids: [virtualSettlement.currencyProductId],
|
|
2443
|
+
currency_display_snapshot: (0, _lodashEs.cloneDeep)(currencySettlementConfig.currency_display_snapshot ?? (0, _virtualSettlement.buildCurrencyDisplaySnapshot)(virtualSettlement.snapshot))
|
|
2444
|
+
}
|
|
2445
|
+
},
|
|
2446
|
+
currency_code: virtualSettlement.currencyCode,
|
|
2447
|
+
currency_symbol: virtualSettlement.currencySymbol,
|
|
2448
|
+
currency_format: virtualSettlement.currencyFormat
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2451
|
+
} : enhancePayload !== undefined ? {
|
|
2069
2452
|
enhancePayload
|
|
2070
2453
|
} : {})
|
|
2071
2454
|
};
|
|
@@ -2092,7 +2475,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2092
2475
|
}
|
|
2093
2476
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2094
2477
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2095
|
-
const enhancePayload = this.
|
|
2478
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params?.enhancePayload);
|
|
2096
2479
|
const submitParams = {
|
|
2097
2480
|
cacheId: this.cacheId,
|
|
2098
2481
|
platform: this.otherParams?.platform,
|
|
@@ -2163,7 +2546,18 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2163
2546
|
channel: context.channel,
|
|
2164
2547
|
type: context.type
|
|
2165
2548
|
});
|
|
2166
|
-
const
|
|
2549
|
+
const invoiceLayoutConfig = this.getCachedInvoiceLayoutConfig();
|
|
2550
|
+
const invoiceTemplateSettings = this.getCachedInvoiceTemplateSettings();
|
|
2551
|
+
const printPayload = {
|
|
2552
|
+
...payload,
|
|
2553
|
+
...(invoiceLayoutConfig ? {
|
|
2554
|
+
invoice: (0, _lodashEs.cloneDeep)(invoiceLayoutConfig)
|
|
2555
|
+
} : {}),
|
|
2556
|
+
...(invoiceTemplateSettings ? {
|
|
2557
|
+
template_settings: (0, _lodashEs.cloneDeep)(invoiceTemplateSettings)
|
|
2558
|
+
} : {})
|
|
2559
|
+
};
|
|
2560
|
+
const response = await this.request.post('/local/print-order', printPayload, {
|
|
2167
2561
|
osServer: true,
|
|
2168
2562
|
customToast: () => {}
|
|
2169
2563
|
});
|
|
@@ -2186,7 +2580,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2186
2580
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2187
2581
|
const businessCode = params.businessCode ?? this.otherParams?.businessCode ?? this.otherParams?.business_code;
|
|
2188
2582
|
const channel = params.channel ?? this.getSubmitOrderSalesChannel();
|
|
2189
|
-
const enhancePayload = this.
|
|
2583
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params.enhancePayload);
|
|
2190
2584
|
const syncParams = {
|
|
2191
2585
|
...params,
|
|
2192
2586
|
checkoutSyncTaskEnabled: this.shouldUseCheckoutSyncTask(),
|
|
@@ -2477,7 +2871,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2477
2871
|
if (this.store.payment) {
|
|
2478
2872
|
const committed = this.getCommittedWalletAssets();
|
|
2479
2873
|
const state = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2480
|
-
void this.publishWalletAssetsState(state);
|
|
2874
|
+
void this.publishWalletAssetsState(state, 'local');
|
|
2481
2875
|
}
|
|
2482
2876
|
return payments;
|
|
2483
2877
|
}
|
|
@@ -2623,9 +3017,10 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2623
3017
|
})
|
|
2624
3018
|
};
|
|
2625
3019
|
}
|
|
2626
|
-
async publishWalletAssetsState(state) {
|
|
3020
|
+
async publishWalletAssetsState(state, changeSource = 'derived') {
|
|
2627
3021
|
await this.effectsEmit(_types.BaseSalesHookNames.onWalletAssetsStateChanged, {
|
|
2628
|
-
state
|
|
3022
|
+
state,
|
|
3023
|
+
changeSource
|
|
2629
3024
|
});
|
|
2630
3025
|
return state;
|
|
2631
3026
|
}
|
|
@@ -2758,7 +3153,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2758
3153
|
source: params.source
|
|
2759
3154
|
});
|
|
2760
3155
|
await this.syncSelectedWalletAssets(state);
|
|
2761
|
-
return this.publishWalletAssetsState(state);
|
|
3156
|
+
return this.publishWalletAssetsState(state, 'local');
|
|
2762
3157
|
}
|
|
2763
3158
|
|
|
2764
3159
|
/** 更新已选钱包资产的手动使用金额,并同步 pending payment。 */
|
|
@@ -2766,7 +3161,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2766
3161
|
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2767
3162
|
const state = this.store.payment.wallet.updateWalletAssetAmount(params.assetId, params.amount);
|
|
2768
3163
|
await this.syncSelectedWalletAssets(state);
|
|
2769
|
-
return this.publishWalletAssetsState(state);
|
|
3164
|
+
return this.publishWalletAssetsState(state, 'local');
|
|
2770
3165
|
}
|
|
2771
3166
|
|
|
2772
3167
|
/** 扫码精确查券;仅可用资产会被自动选中。 */
|
|
@@ -2781,7 +3176,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2781
3176
|
const result = await wallet.scanWalletAssetAsync(code);
|
|
2782
3177
|
if (result.type === 'normalCode') {
|
|
2783
3178
|
await this.syncSelectedWalletAssets(result.state);
|
|
2784
|
-
await this.publishWalletAssetsState(result.state);
|
|
3179
|
+
await this.publishWalletAssetsState(result.state, 'local');
|
|
2785
3180
|
}
|
|
2786
3181
|
return result;
|
|
2787
3182
|
}
|
|
@@ -2791,7 +3186,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2791
3186
|
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2792
3187
|
const state = this.store.payment.wallet.clearWalletAssetSelection();
|
|
2793
3188
|
await this.syncSelectedWalletAssets(state);
|
|
2794
|
-
return this.publishWalletAssetsState(state);
|
|
3189
|
+
return this.publishWalletAssetsState(state, 'local');
|
|
2795
3190
|
}
|
|
2796
3191
|
|
|
2797
3192
|
/**
|
|
@@ -2887,10 +3282,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2887
3282
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2888
3283
|
const beforePayments = (0, _lodashEs.cloneDeep)(this.store.order.getOrderPayments());
|
|
2889
3284
|
const pendingWalletAmount = this.getPendingWalletPaymentAmount(beforePayments);
|
|
3285
|
+
const amountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
2890
3286
|
if (pendingWalletAmount.lte(0)) {
|
|
2891
|
-
|
|
3287
|
+
this.logWarning('confirmWalletPayment: 未发现待确认 Wallet 支付,跳过 Wallet 确认并按普通订单提交', {
|
|
3288
|
+
amountGap: amountSnapshot?.amountGap
|
|
3289
|
+
});
|
|
3290
|
+
const submitResult = await this.submitSalesOrder({
|
|
3291
|
+
smallTicketDataFlag: 1
|
|
3292
|
+
});
|
|
3293
|
+
if (isRejectedSalesSubmitResult(submitResult)) {
|
|
3294
|
+
throw new Error(getSalesSubmitErrorMessage(submitResult, '订单提交失败'));
|
|
3295
|
+
}
|
|
3296
|
+
const latestAmountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
3297
|
+
return {
|
|
3298
|
+
submitResult,
|
|
3299
|
+
payments: this.store.order.getOrderPayments(),
|
|
3300
|
+
isOrderFullyPaid: new _decimal.default(latestAmountSnapshot?.amountGap || 0).lte(0)
|
|
3301
|
+
};
|
|
2892
3302
|
}
|
|
2893
|
-
const amountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
2894
3303
|
const effectiveAmountDue = _decimal.default.max(new _decimal.default(amountSnapshot?.amountGap || 0).minus(pendingWalletAmount), 0);
|
|
2895
3304
|
if (effectiveAmountDue.gt(0.01)) {
|
|
2896
3305
|
throw new Error('Wallet 支付尚未覆盖全部待支付金额');
|
|
@@ -2921,7 +3330,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2921
3330
|
try {
|
|
2922
3331
|
const committed = this.getCommittedWalletAssets();
|
|
2923
3332
|
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2924
|
-
await this.publishWalletAssetsState(walletState);
|
|
3333
|
+
await this.publishWalletAssetsState(walletState, 'local');
|
|
2925
3334
|
} catch (error) {
|
|
2926
3335
|
this.logWarning('confirmWalletPayment: Wallet committed 状态同步失败', {
|
|
2927
3336
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -3005,7 +3414,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3005
3414
|
if (this.store.payment) {
|
|
3006
3415
|
const committed = this.getCommittedWalletAssets();
|
|
3007
3416
|
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3008
|
-
await this.publishWalletAssetsState(walletState);
|
|
3417
|
+
await this.publishWalletAssetsState(walletState, 'local');
|
|
3009
3418
|
}
|
|
3010
3419
|
return {
|
|
3011
3420
|
payment: payment || {},
|
|
@@ -3111,7 +3520,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3111
3520
|
if (this.store.payment) {
|
|
3112
3521
|
const committed = this.getCommittedWalletAssets();
|
|
3113
3522
|
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3114
|
-
await this.publishWalletAssetsState(walletState);
|
|
3523
|
+
await this.publishWalletAssetsState(walletState, 'local');
|
|
3115
3524
|
}
|
|
3116
3525
|
return {
|
|
3117
3526
|
payment: payment || {},
|