@pisell/pisellos 2.2.302 → 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/model/strategy/adapter/promotion/index.js +0 -9
- 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 +24 -3
- package/dist/solution/BaseSales/index.js +1484 -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 +22 -5
- 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 +24 -3
- package/lib/solution/BaseSales/index.js +433 -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 +22 -5
- 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 模块未初始化');
|
|
@@ -1453,6 +1641,14 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1453
1641
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1454
1642
|
return this.store.order.updateTempOrderDepositAmount(amount);
|
|
1455
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
|
+
}
|
|
1456
1652
|
updateTempOrderContactsInfo(contactsInfo) {
|
|
1457
1653
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1458
1654
|
return this.store.order.updateTempOrderContactsInfo(contactsInfo);
|
|
@@ -1556,6 +1752,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1556
1752
|
throw error;
|
|
1557
1753
|
}
|
|
1558
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
|
+
}
|
|
1559
1773
|
getOrderProducts() {
|
|
1560
1774
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1561
1775
|
const products = this.store.order.getOrderProducts();
|
|
@@ -1681,9 +1895,14 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1681
1895
|
const hasManualDiscountSelection = this.hasManualDiscountSelection || currentDiscountList.some(discount => discount.isManualSelect);
|
|
1682
1896
|
const discountAction = params?.action || (orderId ? 'edit' : 'create');
|
|
1683
1897
|
const discountConfigCacheKey = [customerId, discountAction, Number(orderId) || 0].join(':');
|
|
1684
|
-
|
|
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)))];
|
|
1685
1904
|
if (customerId && customerId !== 1) {
|
|
1686
|
-
if (this.discountConfigCacheKey === discountConfigCacheKey) {
|
|
1905
|
+
if (!params?.force && this.discountConfigCacheKey === discountConfigCacheKey) {
|
|
1687
1906
|
preparedDiscountList = originalDiscountList;
|
|
1688
1907
|
} else {
|
|
1689
1908
|
preparedDiscountList = await this.store.order.loadDiscountConfig({
|
|
@@ -1696,11 +1915,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1696
1915
|
await discountModule?.setOriginalDiscountList?.(preparedDiscountList);
|
|
1697
1916
|
}
|
|
1698
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
|
+
}
|
|
1699
1930
|
if (hasManualDiscountSelection && currentDiscountList.length) {
|
|
1700
1931
|
return {
|
|
1701
1932
|
productList: tempOrder.products || [],
|
|
1702
1933
|
discountList: currentDiscountList,
|
|
1703
|
-
availableWalletIds: this.getAvailableWalletIds()
|
|
1934
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
1935
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1704
1936
|
};
|
|
1705
1937
|
}
|
|
1706
1938
|
let nextDiscountList = this.mergeHistoricalDiscountList(preparedDiscountList || discountModule?.getDiscountList?.() || [], tempOrder.products || []);
|
|
@@ -1726,7 +1958,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1726
1958
|
return {
|
|
1727
1959
|
productList: tempOrder.products || [],
|
|
1728
1960
|
discountList: nextDiscountList,
|
|
1729
|
-
availableWalletIds: this.getAvailableWalletIds()
|
|
1961
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
1962
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1730
1963
|
};
|
|
1731
1964
|
}
|
|
1732
1965
|
if (rulesModule) {
|
|
@@ -1782,16 +2015,29 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1782
2015
|
return {
|
|
1783
2016
|
productList: tempOrder.products || [],
|
|
1784
2017
|
discountList: nextDiscountList,
|
|
1785
|
-
availableWalletIds: this.getAvailableWalletIds()
|
|
2018
|
+
availableWalletIds: this.getAvailableWalletIds(),
|
|
2019
|
+
virtualCurrencyList: this.store.order.getVirtualCurrencyList()
|
|
1786
2020
|
};
|
|
1787
2021
|
}
|
|
1788
2022
|
getAvailableWalletIds() {
|
|
1789
2023
|
if (!this.store.order?.getAvailableWalletIds) return [];
|
|
1790
2024
|
return this.store.order.getAvailableWalletIds();
|
|
1791
2025
|
}
|
|
2026
|
+
getVirtualCurrencyList() {
|
|
2027
|
+
if (!this.store.order?.getVirtualCurrencyList) return [];
|
|
2028
|
+
return this.store.order.getVirtualCurrencyList();
|
|
2029
|
+
}
|
|
1792
2030
|
async bestDiscount(cb) {
|
|
1793
2031
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
1794
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
|
+
}
|
|
1795
2041
|
const orderStore = this.store.order.store || {};
|
|
1796
2042
|
const discountModule = orderStore.discount;
|
|
1797
2043
|
const rulesModule = orderStore.rules;
|
|
@@ -1899,6 +2145,17 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
1899
2145
|
async setDiscountSelected(params) {
|
|
1900
2146
|
try {
|
|
1901
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
|
+
}
|
|
1902
2159
|
const list = this.store.order.getDiscountList();
|
|
1903
2160
|
const updated = list.map(d => d.id === params.discountId && !isBaseSalesHistoricalDiscountEntry(d) ? {
|
|
1904
2161
|
...d,
|
|
@@ -2037,6 +2294,101 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2037
2294
|
// Deprecated compatibility alias. New BaseSales callers should use submitSalesOrder.
|
|
2038
2295
|
return this.submitSalesOrder(params);
|
|
2039
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
|
+
}
|
|
2040
2392
|
|
|
2041
2393
|
/**
|
|
2042
2394
|
* 提交当前 Sales 订单。
|
|
@@ -2048,10 +2400,11 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2048
2400
|
if (!this.store.order) {
|
|
2049
2401
|
throw new Error('BaseSales 解决方案需要 order 模块支持');
|
|
2050
2402
|
}
|
|
2403
|
+
const virtualSettlement = await this.buildVirtualSettlementSubmitData();
|
|
2051
2404
|
// this.store.order.persistTempOrder();
|
|
2052
2405
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2053
2406
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2054
|
-
const enhancePayload = this.
|
|
2407
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params?.enhancePayload);
|
|
2055
2408
|
const submitParams = {
|
|
2056
2409
|
cacheId: this.cacheId,
|
|
2057
2410
|
platform: this.otherParams?.platform,
|
|
@@ -2059,7 +2412,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2059
2412
|
channel: this.getSubmitOrderSalesChannel(),
|
|
2060
2413
|
type: this.otherParams?.type,
|
|
2061
2414
|
request_unique_idempotency_token: this.store.order.generateIdempotencyToken(),
|
|
2062
|
-
...(
|
|
2415
|
+
...(virtualSettlement ? {
|
|
2416
|
+
payments: virtualSettlement.payments
|
|
2417
|
+
} : params?.payments !== undefined ? {
|
|
2063
2418
|
payments: params.payments
|
|
2064
2419
|
} : {}),
|
|
2065
2420
|
...(inferredPaymentStatus !== undefined ? {
|
|
@@ -2068,10 +2423,32 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2068
2423
|
...(smallTicketDataFlag !== undefined ? {
|
|
2069
2424
|
smallTicketDataFlag
|
|
2070
2425
|
} : {}),
|
|
2071
|
-
...(
|
|
2426
|
+
...(virtualSettlement ? {
|
|
2427
|
+
confirmPendingVoucherPayments: false
|
|
2428
|
+
} : params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2072
2429
|
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2073
2430
|
} : {}),
|
|
2074
|
-
...(
|
|
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 ? {
|
|
2075
2452
|
enhancePayload
|
|
2076
2453
|
} : {})
|
|
2077
2454
|
};
|
|
@@ -2098,7 +2475,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2098
2475
|
}
|
|
2099
2476
|
const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
|
|
2100
2477
|
const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
|
|
2101
|
-
const enhancePayload = this.
|
|
2478
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params?.enhancePayload);
|
|
2102
2479
|
const submitParams = {
|
|
2103
2480
|
cacheId: this.cacheId,
|
|
2104
2481
|
platform: this.otherParams?.platform,
|
|
@@ -2169,7 +2546,18 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2169
2546
|
channel: context.channel,
|
|
2170
2547
|
type: context.type
|
|
2171
2548
|
});
|
|
2172
|
-
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, {
|
|
2173
2561
|
osServer: true,
|
|
2174
2562
|
customToast: () => {}
|
|
2175
2563
|
});
|
|
@@ -2192,7 +2580,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2192
2580
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2193
2581
|
const businessCode = params.businessCode ?? this.otherParams?.businessCode ?? this.otherParams?.business_code;
|
|
2194
2582
|
const channel = params.channel ?? this.getSubmitOrderSalesChannel();
|
|
2195
|
-
const enhancePayload = this.
|
|
2583
|
+
const enhancePayload = this.buildSubmitPayloadEnhancerWithOpenDataConfig(params.enhancePayload);
|
|
2196
2584
|
const syncParams = {
|
|
2197
2585
|
...params,
|
|
2198
2586
|
checkoutSyncTaskEnabled: this.shouldUseCheckoutSyncTask(),
|
|
@@ -2483,7 +2871,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2483
2871
|
if (this.store.payment) {
|
|
2484
2872
|
const committed = this.getCommittedWalletAssets();
|
|
2485
2873
|
const state = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2486
|
-
void this.publishWalletAssetsState(state);
|
|
2874
|
+
void this.publishWalletAssetsState(state, 'local');
|
|
2487
2875
|
}
|
|
2488
2876
|
return payments;
|
|
2489
2877
|
}
|
|
@@ -2629,9 +3017,10 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2629
3017
|
})
|
|
2630
3018
|
};
|
|
2631
3019
|
}
|
|
2632
|
-
async publishWalletAssetsState(state) {
|
|
3020
|
+
async publishWalletAssetsState(state, changeSource = 'derived') {
|
|
2633
3021
|
await this.effectsEmit(_types.BaseSalesHookNames.onWalletAssetsStateChanged, {
|
|
2634
|
-
state
|
|
3022
|
+
state,
|
|
3023
|
+
changeSource
|
|
2635
3024
|
});
|
|
2636
3025
|
return state;
|
|
2637
3026
|
}
|
|
@@ -2764,7 +3153,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2764
3153
|
source: params.source
|
|
2765
3154
|
});
|
|
2766
3155
|
await this.syncSelectedWalletAssets(state);
|
|
2767
|
-
return this.publishWalletAssetsState(state);
|
|
3156
|
+
return this.publishWalletAssetsState(state, 'local');
|
|
2768
3157
|
}
|
|
2769
3158
|
|
|
2770
3159
|
/** 更新已选钱包资产的手动使用金额,并同步 pending payment。 */
|
|
@@ -2772,7 +3161,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2772
3161
|
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2773
3162
|
const state = this.store.payment.wallet.updateWalletAssetAmount(params.assetId, params.amount);
|
|
2774
3163
|
await this.syncSelectedWalletAssets(state);
|
|
2775
|
-
return this.publishWalletAssetsState(state);
|
|
3164
|
+
return this.publishWalletAssetsState(state, 'local');
|
|
2776
3165
|
}
|
|
2777
3166
|
|
|
2778
3167
|
/** 扫码精确查券;仅可用资产会被自动选中。 */
|
|
@@ -2787,7 +3176,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2787
3176
|
const result = await wallet.scanWalletAssetAsync(code);
|
|
2788
3177
|
if (result.type === 'normalCode') {
|
|
2789
3178
|
await this.syncSelectedWalletAssets(result.state);
|
|
2790
|
-
await this.publishWalletAssetsState(result.state);
|
|
3179
|
+
await this.publishWalletAssetsState(result.state, 'local');
|
|
2791
3180
|
}
|
|
2792
3181
|
return result;
|
|
2793
3182
|
}
|
|
@@ -2797,7 +3186,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2797
3186
|
if (!this.store.payment) throw new Error('payment 模块未初始化');
|
|
2798
3187
|
const state = this.store.payment.wallet.clearWalletAssetSelection();
|
|
2799
3188
|
await this.syncSelectedWalletAssets(state);
|
|
2800
|
-
return this.publishWalletAssetsState(state);
|
|
3189
|
+
return this.publishWalletAssetsState(state, 'local');
|
|
2801
3190
|
}
|
|
2802
3191
|
|
|
2803
3192
|
/**
|
|
@@ -2893,10 +3282,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2893
3282
|
if (!this.store.order) throw new Error('order 模块未初始化');
|
|
2894
3283
|
const beforePayments = (0, _lodashEs.cloneDeep)(this.store.order.getOrderPayments());
|
|
2895
3284
|
const pendingWalletAmount = this.getPendingWalletPaymentAmount(beforePayments);
|
|
3285
|
+
const amountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
2896
3286
|
if (pendingWalletAmount.lte(0)) {
|
|
2897
|
-
|
|
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
|
+
};
|
|
2898
3302
|
}
|
|
2899
|
-
const amountSnapshot = this.store.order.getOrderAmountSnapshot?.();
|
|
2900
3303
|
const effectiveAmountDue = _decimal.default.max(new _decimal.default(amountSnapshot?.amountGap || 0).minus(pendingWalletAmount), 0);
|
|
2901
3304
|
if (effectiveAmountDue.gt(0.01)) {
|
|
2902
3305
|
throw new Error('Wallet 支付尚未覆盖全部待支付金额');
|
|
@@ -2927,7 +3330,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
2927
3330
|
try {
|
|
2928
3331
|
const committed = this.getCommittedWalletAssets();
|
|
2929
3332
|
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
2930
|
-
await this.publishWalletAssetsState(walletState);
|
|
3333
|
+
await this.publishWalletAssetsState(walletState, 'local');
|
|
2931
3334
|
} catch (error) {
|
|
2932
3335
|
this.logWarning('confirmWalletPayment: Wallet committed 状态同步失败', {
|
|
2933
3336
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -3011,7 +3414,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3011
3414
|
if (this.store.payment) {
|
|
3012
3415
|
const committed = this.getCommittedWalletAssets();
|
|
3013
3416
|
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3014
|
-
await this.publishWalletAssetsState(walletState);
|
|
3417
|
+
await this.publishWalletAssetsState(walletState, 'local');
|
|
3015
3418
|
}
|
|
3016
3419
|
return {
|
|
3017
3420
|
payment: payment || {},
|
|
@@ -3117,7 +3520,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
|
|
|
3117
3520
|
if (this.store.payment) {
|
|
3118
3521
|
const committed = this.getCommittedWalletAssets();
|
|
3119
3522
|
const walletState = this.store.payment.wallet.setCommittedWalletAssets(committed.ids, committed.assets);
|
|
3120
|
-
await this.publishWalletAssetsState(walletState);
|
|
3523
|
+
await this.publishWalletAssetsState(walletState, 'local');
|
|
3121
3524
|
}
|
|
3122
3525
|
return {
|
|
3123
3526
|
payment: payment || {},
|