@pisell/pisellos 0.10.2 → 0.10.3
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/core/index.d.ts +2 -0
- package/dist/core/index.js +7 -0
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
- package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/dist/model/strategy/adapter/promotion/examples.js +99 -0
- package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/dist/model/strategy/adapter/promotion/type.js +45 -0
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -3
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +6 -3
- package/dist/modules/OpenData/index.d.ts +2 -0
- package/dist/modules/OpenData/index.js +8 -0
- package/dist/modules/Order/index.d.ts +28 -8
- package/dist/modules/Order/index.js +818 -503
- package/dist/modules/Order/payment-utils.d.ts +26 -0
- package/dist/modules/Order/payment-utils.js +225 -0
- package/dist/modules/Order/types.d.ts +35 -1
- package/dist/modules/Order/utils/orderCollectionIdentity.js +7 -2
- package/dist/modules/Order/utils.js +10 -6
- package/dist/modules/Payment/index.d.ts +2 -0
- package/dist/modules/Payment/index.js +79 -50
- package/dist/modules/Payment/types.d.ts +107 -28
- package/dist/modules/Payment/types.js +20 -3
- package/dist/modules/Payment/walletpass.d.ts +38 -1
- package/dist/modules/Payment/walletpass.js +917 -114
- package/dist/modules/ProductList/index.js +1 -1
- package/dist/modules/Rules/index.d.ts +3 -0
- package/dist/modules/Rules/index.js +130 -99
- package/dist/server/index.d.ts +16 -0
- package/dist/server/index.js +2084 -1188
- package/dist/server/modules/index.d.ts +1 -1
- package/dist/server/modules/order/index.d.ts +70 -4
- package/dist/server/modules/order/index.js +1816 -728
- package/dist/server/modules/order/types.d.ts +25 -3
- package/dist/server/modules/order/types.js +7 -1
- package/dist/solution/BaseSales/index.d.ts +111 -13
- package/dist/solution/BaseSales/index.js +1799 -446
- package/dist/solution/BaseSales/types.d.ts +55 -1
- package/dist/solution/BaseSales/types.js +2 -1
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -3
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +7 -3
- package/dist/solution/BookingTicket/index.js +138 -52
- package/dist/solution/BookingTicket/types.d.ts +1 -0
- package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +173 -83
- package/dist/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/dist/solution/BookingTicket/utils/weighingProductSku.js +45 -0
- package/dist/solution/Sales/index.d.ts +1 -0
- package/dist/solution/Sales/index.js +10 -2
- package/dist/solution/ScanOrder/index.js +31 -20
- package/dist/solution/UnifiedBookingSales/index.js +23 -3
- package/dist/solution/VenueBooking/index.d.ts +1 -0
- package/dist/solution/VenueBooking/index.js +34 -24
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
- package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
- package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
- package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
- package/lib/model/strategy/adapter/promotion/examples.js +91 -0
- package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/lib/model/strategy/adapter/promotion/index.js +0 -49
- package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
- package/lib/model/strategy/adapter/promotion/type.js +2 -0
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/lib/modules/OpenData/index.d.ts +2 -0
- package/lib/modules/OpenData/index.js +5 -0
- package/lib/modules/Order/index.d.ts +28 -8
- package/lib/modules/Order/index.js +233 -68
- package/lib/modules/Order/payment-utils.d.ts +26 -0
- package/lib/modules/Order/payment-utils.js +224 -0
- package/lib/modules/Order/types.d.ts +35 -1
- package/lib/modules/Order/utils/orderCollectionIdentity.js +3 -0
- package/lib/modules/Order/utils.js +11 -4
- package/lib/modules/Payment/index.d.ts +2 -0
- package/lib/modules/Payment/index.js +34 -13
- package/lib/modules/Payment/types.d.ts +107 -28
- package/lib/modules/Payment/types.js +4 -3
- package/lib/modules/Payment/walletpass.d.ts +38 -1
- package/lib/modules/Payment/walletpass.js +730 -21
- package/lib/modules/ProductList/index.js +9 -1
- package/lib/modules/Rules/index.d.ts +3 -0
- package/lib/modules/Rules/index.js +39 -10
- package/lib/server/index.d.ts +16 -0
- package/lib/server/index.js +677 -28
- package/lib/server/modules/index.d.ts +1 -1
- package/lib/server/modules/order/index.d.ts +70 -4
- package/lib/server/modules/order/index.js +818 -69
- package/lib/server/modules/order/types.d.ts +25 -3
- package/lib/server/modules/order/types.js +1 -0
- package/lib/solution/BaseSales/index.d.ts +111 -13
- package/lib/solution/BaseSales/index.js +882 -46
- package/lib/solution/BaseSales/types.d.ts +55 -1
- package/lib/solution/BaseSales/types.js +2 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
- package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +7 -3
- package/lib/solution/BookingTicket/index.js +63 -9
- package/lib/solution/BookingTicket/types.d.ts +1 -0
- package/lib/solution/BookingTicket/utils/addProductDecision.js +4 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
- package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +37 -5
- package/lib/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
- package/lib/solution/BookingTicket/utils/weighingProductSku.js +63 -0
- package/lib/solution/Sales/index.d.ts +1 -0
- package/lib/solution/Sales/index.js +5 -3
- package/lib/solution/ScanOrder/index.js +8 -0
- package/lib/solution/UnifiedBookingSales/index.js +10 -2
- package/lib/solution/VenueBooking/index.d.ts +1 -0
- package/lib/solution/VenueBooking/index.js +13 -6
- package/lib/types/index.d.ts +1 -0
- package/lib/utils/payment-number.d.ts +9 -0
- package/lib/utils/payment-number.js +64 -0
- package/package.json +1 -1
package/lib/server/index.js
CHANGED
|
@@ -34,6 +34,8 @@ __export(server_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(server_exports);
|
|
36
36
|
var import_dayjs = __toESM(require("dayjs"));
|
|
37
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
38
|
+
var import_lodash_es = require("lodash-es");
|
|
37
39
|
var import_products = require("./modules/products");
|
|
38
40
|
var import_menu = require("./modules/menu");
|
|
39
41
|
var import_quotation = require("./modules/quotation");
|
|
@@ -50,6 +52,8 @@ var import_types3 = require("./modules/order/types");
|
|
|
50
52
|
var import_filterOrders = require("./modules/order/utils/filterOrders");
|
|
51
53
|
var import_filterBookings = require("./modules/order/utils/filterBookings");
|
|
52
54
|
var import_small_ticket = require("./utils/small-ticket");
|
|
55
|
+
var import_BaseSales = require("../solution/BaseSales");
|
|
56
|
+
var import_payment_utils = require("../modules/Order/payment-utils");
|
|
53
57
|
__reExport(server_exports, require("./modules"), module.exports);
|
|
54
58
|
var PRODUCT_TITLE_SNAPSHOT_KEYS = [
|
|
55
59
|
"en",
|
|
@@ -91,6 +95,7 @@ var Server = class {
|
|
|
91
95
|
this.BOOKING_REMOTE_CACHE_MAX_ENTRIES = 80;
|
|
92
96
|
this.salesSearchSubscribers = /* @__PURE__ */ new Map();
|
|
93
97
|
this.deviceTaskActionsRegistered = false;
|
|
98
|
+
this.localPaymentUpdateQueues = /* @__PURE__ */ new Map();
|
|
94
99
|
this.floorPlanQuerySubscribers = /* @__PURE__ */ new Map();
|
|
95
100
|
// 模块注册表 - 定义所有可用的模块配置
|
|
96
101
|
this.moduleRegistry = {
|
|
@@ -583,6 +588,128 @@ var Server = class {
|
|
|
583
588
|
title: "handleOrderSalesCheckout"
|
|
584
589
|
});
|
|
585
590
|
};
|
|
591
|
+
this.handleOrderSalesDraft = async ({ data }) => {
|
|
592
|
+
return this.handleOrderDraftSubmit({
|
|
593
|
+
data,
|
|
594
|
+
title: "handleOrderSalesDraft"
|
|
595
|
+
});
|
|
596
|
+
};
|
|
597
|
+
this.handleGetLocalPayment = async ({ data }) => {
|
|
598
|
+
const saleId = data == null ? void 0 : data.sale_id;
|
|
599
|
+
const paymentNumber = data == null ? void 0 : data.payment_number;
|
|
600
|
+
const operationId = this.createLocalPaymentOperationId("get");
|
|
601
|
+
const requestContext = {
|
|
602
|
+
operation_id: operationId,
|
|
603
|
+
sale_id: saleId ?? null,
|
|
604
|
+
payment_number: paymentNumber ?? null
|
|
605
|
+
};
|
|
606
|
+
this.logInfo("handleGetLocalPayment: 请求进入", requestContext);
|
|
607
|
+
if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "") {
|
|
608
|
+
this.logWarning("handleGetLocalPayment: 参数校验失败", {
|
|
609
|
+
...requestContext,
|
|
610
|
+
missing_fields: [
|
|
611
|
+
...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
|
|
612
|
+
...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : []
|
|
613
|
+
]
|
|
614
|
+
});
|
|
615
|
+
return {
|
|
616
|
+
code: 400,
|
|
617
|
+
status: false,
|
|
618
|
+
message: "sale_id 和 payment_number 必填",
|
|
619
|
+
data: null
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
if (!this.order) {
|
|
623
|
+
this.logError("handleGetLocalPayment: Order 模块未注册", requestContext);
|
|
624
|
+
return { code: 500, status: false, message: "Order 模块未注册", data: null };
|
|
625
|
+
}
|
|
626
|
+
const startedAt = Date.now();
|
|
627
|
+
try {
|
|
628
|
+
this.logInfo("handleGetLocalPayment: 开始查询本地支付项", requestContext);
|
|
629
|
+
const found = await this.order.getLocalPayment({
|
|
630
|
+
saleId,
|
|
631
|
+
paymentNumber,
|
|
632
|
+
operationId
|
|
633
|
+
});
|
|
634
|
+
if (!found) {
|
|
635
|
+
this.logWarning("handleGetLocalPayment: 本地支付项不存在", {
|
|
636
|
+
...requestContext,
|
|
637
|
+
duration_ms: Date.now() - startedAt
|
|
638
|
+
});
|
|
639
|
+
return { code: 404, status: false, message: "本地支付项不存在", data: null };
|
|
640
|
+
}
|
|
641
|
+
this.logInfo("handleGetLocalPayment: 查询命中", {
|
|
642
|
+
...requestContext,
|
|
643
|
+
duration_ms: Date.now() - startedAt,
|
|
644
|
+
matched_by: found.matchedBy,
|
|
645
|
+
payment_index: found.paymentIndex,
|
|
646
|
+
...this.buildLocalPaymentOrderLogContext(found.order),
|
|
647
|
+
payment: found.payment
|
|
648
|
+
});
|
|
649
|
+
return { code: 200, status: true, message: "", data: found.payment };
|
|
650
|
+
} catch (error) {
|
|
651
|
+
this.logError("handleGetLocalPayment: 查询异常", {
|
|
652
|
+
...requestContext,
|
|
653
|
+
duration_ms: Date.now() - startedAt,
|
|
654
|
+
error: error instanceof Error ? error.message : String(error),
|
|
655
|
+
error_detail: this.normalizeUnknownError(error)
|
|
656
|
+
});
|
|
657
|
+
throw error;
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
this.handleUpdateLocalPayment = async ({ data }) => {
|
|
661
|
+
const saleId = data == null ? void 0 : data.sale_id;
|
|
662
|
+
const paymentNumber = data == null ? void 0 : data.payment_number;
|
|
663
|
+
const number = data == null ? void 0 : data.number;
|
|
664
|
+
const status = data == null ? void 0 : data.status;
|
|
665
|
+
const serviceCharge = data == null ? void 0 : data.service_charge;
|
|
666
|
+
const cardReaderSurcharge = data == null ? void 0 : data.card_reader_surcharge;
|
|
667
|
+
const hasSurchargeInput = serviceCharge !== void 0 || cardReaderSurcharge !== void 0;
|
|
668
|
+
const invalidSurchargeFields = this.getInvalidLocalPaymentSurchargeFields(
|
|
669
|
+
serviceCharge,
|
|
670
|
+
cardReaderSurcharge
|
|
671
|
+
);
|
|
672
|
+
const operationId = this.createLocalPaymentOperationId("update");
|
|
673
|
+
const requestContext = {
|
|
674
|
+
operation_id: operationId,
|
|
675
|
+
sale_id: saleId ?? null,
|
|
676
|
+
payment_number: paymentNumber ?? null,
|
|
677
|
+
transaction_number: number ?? null,
|
|
678
|
+
requested_status: status ?? null,
|
|
679
|
+
service_charge: serviceCharge ?? null,
|
|
680
|
+
card_reader_surcharge: cardReaderSurcharge ?? null
|
|
681
|
+
};
|
|
682
|
+
this.logInfo("handleUpdateLocalPayment: 请求进入", requestContext);
|
|
683
|
+
if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" || number === void 0 || number === null || number === "" || status !== "success" && status !== "fail" || invalidSurchargeFields.length > 0) {
|
|
684
|
+
this.logWarning("handleUpdateLocalPayment: 参数校验失败", {
|
|
685
|
+
...requestContext,
|
|
686
|
+
missing_or_invalid_fields: [
|
|
687
|
+
...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
|
|
688
|
+
...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : [],
|
|
689
|
+
...number === void 0 || number === null || number === "" ? ["number"] : [],
|
|
690
|
+
...status !== "success" && status !== "fail" ? ["status"] : [],
|
|
691
|
+
...invalidSurchargeFields
|
|
692
|
+
]
|
|
693
|
+
});
|
|
694
|
+
return {
|
|
695
|
+
code: 400,
|
|
696
|
+
status: false,
|
|
697
|
+
message: invalidSurchargeFields.length > 0 ? `手续费参数非法: ${invalidSurchargeFields.join(", ")}` : "sale_id、payment_number、number 必填,status 仅支持 success/fail",
|
|
698
|
+
data: null
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
const queueKey = `${String(saleId)}:${String(paymentNumber)}`;
|
|
702
|
+
return this.runLocalPaymentUpdateInQueue(queueKey, () => this.processLocalPaymentUpdate({
|
|
703
|
+
operationId,
|
|
704
|
+
saleId,
|
|
705
|
+
paymentNumber,
|
|
706
|
+
number: String(number),
|
|
707
|
+
status,
|
|
708
|
+
serviceCharge,
|
|
709
|
+
cardReaderSurcharge,
|
|
710
|
+
hasSurchargeInput
|
|
711
|
+
}), requestContext);
|
|
712
|
+
};
|
|
586
713
|
this.handleOrderCheckout = async ({ data }) => {
|
|
587
714
|
return this.handleOrderCheckoutSubmit({
|
|
588
715
|
backendPath: "/order/checkout",
|
|
@@ -1364,7 +1491,7 @@ var Server = class {
|
|
|
1364
1491
|
const { backendPath, title } = params;
|
|
1365
1492
|
const normalizedData = await this.normalizeCheckoutSubmitData(params.data, title);
|
|
1366
1493
|
const checkoutData = await this.ensureCheckoutOrderNumbers(normalizedData, title);
|
|
1367
|
-
const remoteCheckoutData = this.
|
|
1494
|
+
const remoteCheckoutData = this.buildRemoteCheckoutData(checkoutData, title);
|
|
1368
1495
|
if (!((_b = (_a = this.app) == null ? void 0 : _a.request) == null ? void 0 : _b.post)) {
|
|
1369
1496
|
throw new Error("app.request 不可用");
|
|
1370
1497
|
}
|
|
@@ -1380,20 +1507,20 @@ var Server = class {
|
|
|
1380
1507
|
errorResponse: response,
|
|
1381
1508
|
response,
|
|
1382
1509
|
normalizedResponse: this.normalizeCheckoutResponse(response),
|
|
1383
|
-
checkoutData
|
|
1510
|
+
checkoutData
|
|
1384
1511
|
};
|
|
1385
1512
|
}
|
|
1386
1513
|
const fresh = this.extractOrderDataFromCheckoutResponse(response);
|
|
1387
1514
|
const externalSaleNumber = this.getCheckoutExternalSaleNumber(
|
|
1388
|
-
|
|
1515
|
+
checkoutData,
|
|
1389
1516
|
{
|
|
1390
1517
|
external_sale_number: params.externalSaleNumber,
|
|
1391
|
-
data:
|
|
1518
|
+
data: checkoutData
|
|
1392
1519
|
}
|
|
1393
1520
|
);
|
|
1394
1521
|
const syncedOrder = await this.persistSyncedCheckoutOrder({
|
|
1395
1522
|
backendPath,
|
|
1396
|
-
checkoutData
|
|
1523
|
+
checkoutData,
|
|
1397
1524
|
externalSaleNumber,
|
|
1398
1525
|
fresh,
|
|
1399
1526
|
title,
|
|
@@ -1404,11 +1531,11 @@ var Server = class {
|
|
|
1404
1531
|
checkoutResponseOrder: fresh
|
|
1405
1532
|
}) : void 0;
|
|
1406
1533
|
if (printableSyncedOrder && this.shouldPrintSyncedOrder({
|
|
1407
|
-
checkoutData
|
|
1534
|
+
checkoutData,
|
|
1408
1535
|
syncedOrder: printableSyncedOrder
|
|
1409
1536
|
})) {
|
|
1410
1537
|
await this.dispatchPrintOtherReceiptTask({
|
|
1411
|
-
checkoutData
|
|
1538
|
+
checkoutData,
|
|
1412
1539
|
syncedOrder: printableSyncedOrder,
|
|
1413
1540
|
response,
|
|
1414
1541
|
deviceId: params.deviceId
|
|
@@ -1418,7 +1545,7 @@ var Server = class {
|
|
|
1418
1545
|
rejected: false,
|
|
1419
1546
|
response,
|
|
1420
1547
|
normalizedResponse: this.normalizeCheckoutResponse(response),
|
|
1421
|
-
checkoutData
|
|
1548
|
+
checkoutData,
|
|
1422
1549
|
syncedOrder,
|
|
1423
1550
|
fresh
|
|
1424
1551
|
};
|
|
@@ -1431,6 +1558,54 @@ var Server = class {
|
|
|
1431
1558
|
delete next.syncMode;
|
|
1432
1559
|
return next;
|
|
1433
1560
|
}
|
|
1561
|
+
buildRemoteCheckoutData(data, title) {
|
|
1562
|
+
const next = (0, import_lodash_es.cloneDeep)(this.omitCheckoutSyncMode(data));
|
|
1563
|
+
if (!next || typeof next !== "object")
|
|
1564
|
+
return next;
|
|
1565
|
+
const record = next;
|
|
1566
|
+
if (!Array.isArray(record.payments))
|
|
1567
|
+
return next;
|
|
1568
|
+
const originalPayments = record.payments;
|
|
1569
|
+
const filteredPayments = originalPayments.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
|
|
1570
|
+
const removedPayments = originalPayments.filter((payment) => (0, import_payment_utils.isPendingOrderPayment)(payment));
|
|
1571
|
+
record.payments = filteredPayments;
|
|
1572
|
+
this.logInfo(`${title}: checkout 云端支付项已过滤`, {
|
|
1573
|
+
external_sale_number: record.external_sale_number,
|
|
1574
|
+
original_payment_count: originalPayments.length,
|
|
1575
|
+
remote_payment_count: filteredPayments.length,
|
|
1576
|
+
filtered_pending_count: removedPayments.length,
|
|
1577
|
+
filtered_payment_identities: removedPayments.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
|
|
1578
|
+
});
|
|
1579
|
+
return next;
|
|
1580
|
+
}
|
|
1581
|
+
mergeCheckoutSyncPayments(checkoutData, fresh, title) {
|
|
1582
|
+
const localPayments = Array.isArray(checkoutData == null ? void 0 : checkoutData.payments) ? checkoutData.payments : [];
|
|
1583
|
+
const freshRecord = fresh;
|
|
1584
|
+
if (!Array.isArray(freshRecord.payments)) {
|
|
1585
|
+
return localPayments.length > 0 ? { ...freshRecord, payments: (0, import_lodash_es.cloneDeep)(localPayments) } : freshRecord;
|
|
1586
|
+
}
|
|
1587
|
+
const freshPayments = freshRecord.payments;
|
|
1588
|
+
const mergedPayments = (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
|
|
1589
|
+
localPayments,
|
|
1590
|
+
freshPayments,
|
|
1591
|
+
{ preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
|
|
1592
|
+
);
|
|
1593
|
+
const remoteIdentityKeys = new Set(
|
|
1594
|
+
freshPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
|
|
1595
|
+
);
|
|
1596
|
+
const preservedPending = localPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => remoteIdentityKeys.has(key)));
|
|
1597
|
+
if (preservedPending.length > 0) {
|
|
1598
|
+
this.logInfo(`${title}: checkout 响应合并保留本地 pending 支付项`, {
|
|
1599
|
+
external_sale_number: checkoutData == null ? void 0 : checkoutData.external_sale_number,
|
|
1600
|
+
preserved_pending_count: preservedPending.length,
|
|
1601
|
+
preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
return {
|
|
1605
|
+
...freshRecord,
|
|
1606
|
+
payments: mergedPayments
|
|
1607
|
+
};
|
|
1608
|
+
}
|
|
1434
1609
|
async persistSyncedCheckoutOrder(params) {
|
|
1435
1610
|
const {
|
|
1436
1611
|
backendPath,
|
|
@@ -1445,15 +1620,17 @@ var Server = class {
|
|
|
1445
1620
|
if (this.order && fresh && (shouldMergeRemoteOrder || persistCheckoutDataWithResponse)) {
|
|
1446
1621
|
syncedOrder = persistCheckoutDataWithResponse ? {
|
|
1447
1622
|
...checkoutData,
|
|
1448
|
-
...fresh,
|
|
1623
|
+
...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
|
|
1449
1624
|
external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
|
|
1450
|
-
need_sync: 0
|
|
1625
|
+
need_sync: 0,
|
|
1626
|
+
is_draft_order: 0
|
|
1451
1627
|
} : {
|
|
1452
|
-
...fresh,
|
|
1628
|
+
...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
|
|
1453
1629
|
external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
|
|
1454
|
-
need_sync: 0
|
|
1630
|
+
need_sync: 0,
|
|
1631
|
+
is_draft_order: 0
|
|
1455
1632
|
};
|
|
1456
|
-
await this.order.upsertOrdersFromRemote([syncedOrder]);
|
|
1633
|
+
await this.order.upsertOrdersFromRemote([syncedOrder], "checkoutSync");
|
|
1457
1634
|
this.logInfo(`${title}: sync_sales 完整订单已同步到本地`, {
|
|
1458
1635
|
order_id: fresh.order_id,
|
|
1459
1636
|
external_sale_number: syncedOrder.external_sale_number,
|
|
@@ -1471,7 +1648,8 @@ var Server = class {
|
|
|
1471
1648
|
...checkoutData,
|
|
1472
1649
|
...patch,
|
|
1473
1650
|
external_sale_number: externalSaleNumber,
|
|
1474
|
-
need_sync: 0
|
|
1651
|
+
need_sync: 0,
|
|
1652
|
+
is_draft_order: 0
|
|
1475
1653
|
};
|
|
1476
1654
|
this.logInfo(`${title}: sync_sales 已按 external_sale_number 标记本地订单`, {
|
|
1477
1655
|
order_id: (syncedOrder == null ? void 0 : syncedOrder.order_id) ?? null,
|
|
@@ -1851,6 +2029,11 @@ var Server = class {
|
|
|
1851
2029
|
path: "/shop/order/sales/checkout",
|
|
1852
2030
|
handler: this.handleOrderSalesCheckout.bind(this)
|
|
1853
2031
|
},
|
|
2032
|
+
{
|
|
2033
|
+
method: "post",
|
|
2034
|
+
path: "/shop/order/sales/draft",
|
|
2035
|
+
handler: this.handleOrderSalesDraft.bind(this)
|
|
2036
|
+
},
|
|
1854
2037
|
{
|
|
1855
2038
|
method: "post",
|
|
1856
2039
|
path: "/order/checkout",
|
|
@@ -1861,6 +2044,16 @@ var Server = class {
|
|
|
1861
2044
|
path: "/shop/local/print-order",
|
|
1862
2045
|
handler: this.handleLocalPrintOrder.bind(this)
|
|
1863
2046
|
},
|
|
2047
|
+
{
|
|
2048
|
+
method: "post",
|
|
2049
|
+
path: "/shop/local/getLocalPayment",
|
|
2050
|
+
handler: this.handleGetLocalPayment.bind(this)
|
|
2051
|
+
},
|
|
2052
|
+
{
|
|
2053
|
+
method: "post",
|
|
2054
|
+
path: "/shop/local/updateLocalPayment",
|
|
2055
|
+
handler: this.handleUpdateLocalPayment.bind(this)
|
|
2056
|
+
},
|
|
1864
2057
|
{
|
|
1865
2058
|
method: "post",
|
|
1866
2059
|
path: "/shop/machinecode/batch",
|
|
@@ -2026,15 +2219,12 @@ var Server = class {
|
|
|
2026
2219
|
return;
|
|
2027
2220
|
const scheduleDate = subscriber.context.schedule_date || (0, import_dayjs.default)().format("YYYY-MM-DD");
|
|
2028
2221
|
const timerIds = [];
|
|
2029
|
-
|
|
2030
|
-
const
|
|
2031
|
-
if (
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
}, delayMs);
|
|
2036
|
-
timerIds.push(timerId);
|
|
2037
|
-
}
|
|
2222
|
+
setInterval(() => {
|
|
2223
|
+
const currentTime = (0, import_dayjs.default)().format("hh:mm");
|
|
2224
|
+
if (timePoints.includes(currentTime)) {
|
|
2225
|
+
this.onScheduleTimePointTimerFire(subscriberId);
|
|
2226
|
+
}
|
|
2227
|
+
}, 6e4);
|
|
2038
2228
|
if (timerIds.length > 0) {
|
|
2039
2229
|
this.productQueryScheduleTimers.set(subscriberId, timerIds);
|
|
2040
2230
|
subscriber.scheduleTimerIds = timerIds;
|
|
@@ -2049,7 +2239,7 @@ var Server = class {
|
|
|
2049
2239
|
* schedule 变价时间点定时器触发:刷新 schedule_datetime 后重算并 callback。
|
|
2050
2240
|
*/
|
|
2051
2241
|
async onScheduleTimePointTimerFire(subscriberId, timerId) {
|
|
2052
|
-
this.removeScheduleTimerRef(subscriberId, timerId);
|
|
2242
|
+
timerId && this.removeScheduleTimerRef(subscriberId, timerId);
|
|
2053
2243
|
if (!this.productQuerySubscribers.has(subscriberId))
|
|
2054
2244
|
return;
|
|
2055
2245
|
const subscriber = this.productQuerySubscribers.get(subscriberId);
|
|
@@ -2739,6 +2929,405 @@ var Server = class {
|
|
|
2739
2929
|
};
|
|
2740
2930
|
}
|
|
2741
2931
|
}
|
|
2932
|
+
createLocalPaymentOperationId(action) {
|
|
2933
|
+
return `local_payment_${action}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2934
|
+
}
|
|
2935
|
+
buildLocalPaymentOrderLogContext(order) {
|
|
2936
|
+
if (!order)
|
|
2937
|
+
return {};
|
|
2938
|
+
return {
|
|
2939
|
+
order_id: order.order_id ?? null,
|
|
2940
|
+
external_sale_number: order.external_sale_number ?? null,
|
|
2941
|
+
order_number: order.order_number ?? null,
|
|
2942
|
+
shop_order_number: order.shop_order_number ?? null,
|
|
2943
|
+
shop_full_order_number: order.shop_full_order_number ?? null,
|
|
2944
|
+
order_status: order.status ?? null,
|
|
2945
|
+
payment_status: order.payment_status ?? null,
|
|
2946
|
+
is_draft_order: Number(order.is_draft_order || 0),
|
|
2947
|
+
need_sync: Number(order.need_sync || 0),
|
|
2948
|
+
platform: order.platform ?? null,
|
|
2949
|
+
business_code: order.business_code ?? null,
|
|
2950
|
+
order_sales_channel: order.order_sales_channel ?? null,
|
|
2951
|
+
sales_channel: order.sales_channel ?? null,
|
|
2952
|
+
order_type: order.type ?? null,
|
|
2953
|
+
payments_count: Array.isArray(order.payments) ? order.payments.length : 0
|
|
2954
|
+
};
|
|
2955
|
+
}
|
|
2956
|
+
isValidLocalPaymentDecimal(value) {
|
|
2957
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
2958
|
+
return false;
|
|
2959
|
+
if (typeof value === "string" && value.trim() === "")
|
|
2960
|
+
return false;
|
|
2961
|
+
try {
|
|
2962
|
+
return new import_decimal.default(value).isFinite();
|
|
2963
|
+
} catch {
|
|
2964
|
+
return false;
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
getInvalidLocalPaymentSurchargeFields(serviceCharge, cardReaderSurcharge) {
|
|
2968
|
+
const invalidFields = [];
|
|
2969
|
+
if (serviceCharge !== void 0) {
|
|
2970
|
+
if (serviceCharge === null || typeof serviceCharge !== "object" || Array.isArray(serviceCharge)) {
|
|
2971
|
+
invalidFields.push("service_charge");
|
|
2972
|
+
} else {
|
|
2973
|
+
const input = serviceCharge;
|
|
2974
|
+
if (input.fixed !== void 0 && !this.isValidLocalPaymentDecimal(input.fixed)) {
|
|
2975
|
+
invalidFields.push("service_charge.fixed");
|
|
2976
|
+
}
|
|
2977
|
+
if (input.percentage !== void 0 && !this.isValidLocalPaymentDecimal(input.percentage)) {
|
|
2978
|
+
invalidFields.push("service_charge.percentage");
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
if (cardReaderSurcharge !== void 0 && !this.isValidLocalPaymentDecimal(cardReaderSurcharge)) {
|
|
2983
|
+
invalidFields.push("card_reader_surcharge");
|
|
2984
|
+
}
|
|
2985
|
+
return invalidFields;
|
|
2986
|
+
}
|
|
2987
|
+
buildLocalPaymentSurchargeUpdate(params) {
|
|
2988
|
+
var _a, _b, _c;
|
|
2989
|
+
const amount = new import_decimal.default(((_a = params.serviceCharge) == null ? void 0 : _a.fixed) || 0).plus(params.cardReaderSurcharge || 0).toFixed(2);
|
|
2990
|
+
const serviceFee = new import_decimal.default(params.paymentAmount || 0).times(((_b = params.serviceCharge) == null ? void 0 : _b.percentage) || 0).plus(amount).toDecimalPlaces(2).toFixed(2);
|
|
2991
|
+
return {
|
|
2992
|
+
service_charge: {
|
|
2993
|
+
amount,
|
|
2994
|
+
...((_c = params.serviceCharge) == null ? void 0 : _c.percentage) !== void 0 ? { percentage: params.serviceCharge.percentage } : {}
|
|
2995
|
+
},
|
|
2996
|
+
service_fee: serviceFee
|
|
2997
|
+
};
|
|
2998
|
+
}
|
|
2999
|
+
async runLocalPaymentUpdateInQueue(key, task, context) {
|
|
3000
|
+
var _a;
|
|
3001
|
+
const queuedAt = Date.now();
|
|
3002
|
+
const hasPreviousTask = this.localPaymentUpdateQueues.has(key);
|
|
3003
|
+
const previous = this.localPaymentUpdateQueues.get(key) || Promise.resolve();
|
|
3004
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列入队", {
|
|
3005
|
+
...context,
|
|
3006
|
+
queue_key: key,
|
|
3007
|
+
waiting_for_previous: hasPreviousTask,
|
|
3008
|
+
active_queue_count: this.localPaymentUpdateQueues.size
|
|
3009
|
+
});
|
|
3010
|
+
const current = previous.catch(() => void 0).then(async () => {
|
|
3011
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列开始执行", {
|
|
3012
|
+
...context,
|
|
3013
|
+
queue_key: key,
|
|
3014
|
+
queue_wait_ms: Date.now() - queuedAt
|
|
3015
|
+
});
|
|
3016
|
+
return task();
|
|
3017
|
+
});
|
|
3018
|
+
const tail = current.then(() => void 0, () => void 0);
|
|
3019
|
+
this.localPaymentUpdateQueues.set(key, tail);
|
|
3020
|
+
try {
|
|
3021
|
+
const result = await current;
|
|
3022
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列执行完成", {
|
|
3023
|
+
...context,
|
|
3024
|
+
queue_key: key,
|
|
3025
|
+
total_duration_ms: Date.now() - queuedAt,
|
|
3026
|
+
result_code: result == null ? void 0 : result.code,
|
|
3027
|
+
result_status: result == null ? void 0 : result.status,
|
|
3028
|
+
payment: (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.payment
|
|
3029
|
+
});
|
|
3030
|
+
return result;
|
|
3031
|
+
} catch (error) {
|
|
3032
|
+
this.logError("handleUpdateLocalPayment: 串行队列执行失败", {
|
|
3033
|
+
...context,
|
|
3034
|
+
queue_key: key,
|
|
3035
|
+
total_duration_ms: Date.now() - queuedAt,
|
|
3036
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3037
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3038
|
+
});
|
|
3039
|
+
throw error;
|
|
3040
|
+
} finally {
|
|
3041
|
+
let released = false;
|
|
3042
|
+
if (this.localPaymentUpdateQueues.get(key) === tail) {
|
|
3043
|
+
this.localPaymentUpdateQueues.delete(key);
|
|
3044
|
+
released = true;
|
|
3045
|
+
}
|
|
3046
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列释放", {
|
|
3047
|
+
...context,
|
|
3048
|
+
queue_key: key,
|
|
3049
|
+
released,
|
|
3050
|
+
active_queue_count: this.localPaymentUpdateQueues.size
|
|
3051
|
+
});
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
async processLocalPaymentUpdate(params) {
|
|
3055
|
+
var _a, _b, _c;
|
|
3056
|
+
const requestContext = {
|
|
3057
|
+
operation_id: params.operationId,
|
|
3058
|
+
sale_id: params.saleId,
|
|
3059
|
+
payment_number: params.paymentNumber,
|
|
3060
|
+
transaction_number: params.number,
|
|
3061
|
+
requested_status: params.status,
|
|
3062
|
+
service_charge: params.serviceCharge ?? null,
|
|
3063
|
+
card_reader_surcharge: params.cardReaderSurcharge ?? null
|
|
3064
|
+
};
|
|
3065
|
+
this.logInfo("processLocalPaymentUpdate: 开始处理", requestContext);
|
|
3066
|
+
if (!this.order) {
|
|
3067
|
+
this.logError("processLocalPaymentUpdate: Order 模块未注册", requestContext);
|
|
3068
|
+
return { code: 500, status: false, message: "Order 模块未注册", data: null };
|
|
3069
|
+
}
|
|
3070
|
+
this.logInfo("processLocalPaymentUpdate: 开始查询本地支付项", requestContext);
|
|
3071
|
+
const found = await this.order.getLocalPayment({
|
|
3072
|
+
saleId: params.saleId,
|
|
3073
|
+
paymentNumber: params.paymentNumber,
|
|
3074
|
+
operationId: params.operationId
|
|
3075
|
+
});
|
|
3076
|
+
if (!found) {
|
|
3077
|
+
this.logWarning("processLocalPaymentUpdate: 本地支付项不存在", requestContext);
|
|
3078
|
+
return { code: 404, status: false, message: "本地支付项不存在", data: null };
|
|
3079
|
+
}
|
|
3080
|
+
const surchargeUpdate = params.status === "success" && params.hasSurchargeInput ? this.buildLocalPaymentSurchargeUpdate({
|
|
3081
|
+
paymentAmount: (_a = found.payment) == null ? void 0 : _a.amount,
|
|
3082
|
+
serviceCharge: params.serviceCharge,
|
|
3083
|
+
cardReaderSurcharge: params.cardReaderSurcharge
|
|
3084
|
+
}) : void 0;
|
|
3085
|
+
const incomingPaymentUpdate = params.status === "success" ? {
|
|
3086
|
+
status: "paid",
|
|
3087
|
+
...surchargeUpdate || {},
|
|
3088
|
+
metadata: {
|
|
3089
|
+
unique_payment_number: params.number,
|
|
3090
|
+
transactions: [{ number: params.number, status: "success" }]
|
|
3091
|
+
}
|
|
3092
|
+
} : {
|
|
3093
|
+
metadata: {
|
|
3094
|
+
transactions: [{ number: params.number, status: "fail" }]
|
|
3095
|
+
}
|
|
3096
|
+
};
|
|
3097
|
+
const transactions = Array.isArray((_c = (_b = found.payment) == null ? void 0 : _b.metadata) == null ? void 0 : _c.transactions) ? found.payment.metadata.transactions : [];
|
|
3098
|
+
const existingTransaction = transactions.find((item) => String((item == null ? void 0 : item.number) || "") === params.number);
|
|
3099
|
+
const hasRecordedSuccess = transactions.some((item) => (item == null ? void 0 : item.status) === "success");
|
|
3100
|
+
const orderIsDraft = Number(found.order.is_draft_order || 0) === 1;
|
|
3101
|
+
const foundContext = {
|
|
3102
|
+
...requestContext,
|
|
3103
|
+
matched_by: found.matchedBy,
|
|
3104
|
+
payment_index: found.paymentIndex,
|
|
3105
|
+
...this.buildLocalPaymentOrderLogContext(found.order),
|
|
3106
|
+
payment: found.payment,
|
|
3107
|
+
incoming_payment_update: incomingPaymentUpdate,
|
|
3108
|
+
existing_transaction: existingTransaction || null,
|
|
3109
|
+
has_recorded_success: hasRecordedSuccess
|
|
3110
|
+
};
|
|
3111
|
+
this.logInfo("processLocalPaymentUpdate: 查询命中", foundContext);
|
|
3112
|
+
if (params.status === "fail" && (found.payment.status === "paid" || hasRecordedSuccess)) {
|
|
3113
|
+
this.logInfo("processLocalPaymentUpdate: 幂等返回", {
|
|
3114
|
+
...foundContext,
|
|
3115
|
+
idempotent_reason: "ignore_failure_after_success"
|
|
3116
|
+
});
|
|
3117
|
+
return {
|
|
3118
|
+
code: 200,
|
|
3119
|
+
status: true,
|
|
3120
|
+
message: "",
|
|
3121
|
+
data: { payment: found.payment, order: found.order, idempotent: true }
|
|
3122
|
+
};
|
|
3123
|
+
}
|
|
3124
|
+
const alreadyRecordedFailure = params.status === "fail" && (existingTransaction == null ? void 0 : existingTransaction.status) === "fail";
|
|
3125
|
+
if (alreadyRecordedFailure) {
|
|
3126
|
+
this.logInfo("processLocalPaymentUpdate: 幂等返回", {
|
|
3127
|
+
...foundContext,
|
|
3128
|
+
idempotent_reason: "failure_already_recorded"
|
|
3129
|
+
});
|
|
3130
|
+
return {
|
|
3131
|
+
code: 200,
|
|
3132
|
+
status: true,
|
|
3133
|
+
message: "",
|
|
3134
|
+
data: { payment: found.payment, order: found.order, idempotent: true }
|
|
3135
|
+
};
|
|
3136
|
+
}
|
|
3137
|
+
if (params.status === "success" && (existingTransaction == null ? void 0 : existingTransaction.status) === "success" && found.payment.status === "paid" && !orderIsDraft) {
|
|
3138
|
+
this.logInfo("processLocalPaymentUpdate: 幂等返回", {
|
|
3139
|
+
...foundContext,
|
|
3140
|
+
idempotent_reason: "success_already_committed"
|
|
3141
|
+
});
|
|
3142
|
+
return {
|
|
3143
|
+
code: 200,
|
|
3144
|
+
status: true,
|
|
3145
|
+
message: "",
|
|
3146
|
+
data: { payment: found.payment, order: found.order, idempotent: true }
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
3149
|
+
if (params.status === "success") {
|
|
3150
|
+
this.logInfo("processLocalPaymentUpdate: 进入 success 恢复分支", {
|
|
3151
|
+
...foundContext,
|
|
3152
|
+
force_submit_if_paid: found.payment.status === "paid" && orderIsDraft
|
|
3153
|
+
});
|
|
3154
|
+
return this.processSuccessfulLocalPayment({
|
|
3155
|
+
...params,
|
|
3156
|
+
order: found.order,
|
|
3157
|
+
payment: found.payment,
|
|
3158
|
+
matchBy: found.matchedBy === "payment_number" ? "payment_number" : "compat",
|
|
3159
|
+
forceSubmitIfPaid: found.payment.status === "paid" && orderIsDraft,
|
|
3160
|
+
paymentUpdate: incomingPaymentUpdate
|
|
3161
|
+
});
|
|
3162
|
+
}
|
|
3163
|
+
this.logInfo("processLocalPaymentUpdate: 进入 fail 本地更新分支", {
|
|
3164
|
+
...foundContext,
|
|
3165
|
+
incoming_payment_update: incomingPaymentUpdate
|
|
3166
|
+
});
|
|
3167
|
+
let updated;
|
|
3168
|
+
try {
|
|
3169
|
+
updated = await this.order.updateLocalPayment({
|
|
3170
|
+
saleId: params.saleId,
|
|
3171
|
+
paymentNumber: params.paymentNumber,
|
|
3172
|
+
operationId: params.operationId,
|
|
3173
|
+
updates: incomingPaymentUpdate
|
|
3174
|
+
});
|
|
3175
|
+
} catch (error) {
|
|
3176
|
+
this.logError("processLocalPaymentUpdate: fail 本地更新失败", {
|
|
3177
|
+
...foundContext,
|
|
3178
|
+
incoming_payment_update: incomingPaymentUpdate,
|
|
3179
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3180
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3181
|
+
});
|
|
3182
|
+
throw error;
|
|
3183
|
+
}
|
|
3184
|
+
if (!updated) {
|
|
3185
|
+
this.logWarning("processLocalPaymentUpdate: fail 本地更新未命中", foundContext);
|
|
3186
|
+
return { code: 404, status: false, message: "本地支付项不存在", data: null };
|
|
3187
|
+
}
|
|
3188
|
+
this.logInfo("processLocalPaymentUpdate: fail 本地更新完成", {
|
|
3189
|
+
...requestContext,
|
|
3190
|
+
...this.buildLocalPaymentOrderLogContext(updated.order),
|
|
3191
|
+
previous_payment: updated.previousPayment,
|
|
3192
|
+
payment: updated.payment
|
|
3193
|
+
});
|
|
3194
|
+
return {
|
|
3195
|
+
code: 200,
|
|
3196
|
+
status: true,
|
|
3197
|
+
message: "",
|
|
3198
|
+
data: {
|
|
3199
|
+
local_only: true,
|
|
3200
|
+
payment: updated.payment,
|
|
3201
|
+
order: updated.order
|
|
3202
|
+
}
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
3205
|
+
async processSuccessfulLocalPayment(params) {
|
|
3206
|
+
var _a, _b, _c, _d, _e;
|
|
3207
|
+
const moduleName = `local_payment_recovery_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
3208
|
+
const baseSales = new import_BaseSales.BaseSalesImpl(moduleName);
|
|
3209
|
+
const startedAt = Date.now();
|
|
3210
|
+
const recoveryContext = {
|
|
3211
|
+
operation_id: params.operationId,
|
|
3212
|
+
sale_id: params.saleId,
|
|
3213
|
+
payment_number: params.paymentNumber,
|
|
3214
|
+
transaction_number: params.number,
|
|
3215
|
+
requested_status: "success",
|
|
3216
|
+
match_by: params.matchBy,
|
|
3217
|
+
force_submit_if_paid: params.forceSubmitIfPaid,
|
|
3218
|
+
incoming_payment_update: params.paymentUpdate,
|
|
3219
|
+
base_sales_module_name: moduleName,
|
|
3220
|
+
...this.buildLocalPaymentOrderLogContext(params.order),
|
|
3221
|
+
payment: params.payment
|
|
3222
|
+
};
|
|
3223
|
+
this.logInfo("processSuccessfulLocalPayment: 创建临时 BaseSales", recoveryContext);
|
|
3224
|
+
try {
|
|
3225
|
+
const order = this.sanitizeLocalRecoveryOrder(params.order);
|
|
3226
|
+
this.logInfo("processSuccessfulLocalPayment: 本地订单清洗完成", {
|
|
3227
|
+
...recoveryContext,
|
|
3228
|
+
sanitized_order_id: order.order_id ?? null,
|
|
3229
|
+
removed_synthetic_order_id: params.order.order_id != null && order.order_id == null
|
|
3230
|
+
});
|
|
3231
|
+
await baseSales.initialize(this.core, {
|
|
3232
|
+
otherParams: {
|
|
3233
|
+
platform: order.platform,
|
|
3234
|
+
businessCode: order.business_code,
|
|
3235
|
+
business_code: order.business_code,
|
|
3236
|
+
channel: order.order_sales_channel || order.sales_channel,
|
|
3237
|
+
type: order.type,
|
|
3238
|
+
enableTempOrderPersist: false
|
|
3239
|
+
}
|
|
3240
|
+
});
|
|
3241
|
+
this.logInfo("processSuccessfulLocalPayment: BaseSales 初始化完成", recoveryContext);
|
|
3242
|
+
await baseSales.replaceTempOrder(order);
|
|
3243
|
+
this.logInfo("processSuccessfulLocalPayment: 本地订单 tempOrder 恢复完成", recoveryContext);
|
|
3244
|
+
this.logInfo("processSuccessfulLocalPayment: 开始更新支付项并提交", {
|
|
3245
|
+
...recoveryContext,
|
|
3246
|
+
incoming_payment_update: params.paymentUpdate
|
|
3247
|
+
});
|
|
3248
|
+
const result = await baseSales.updateOrderPayment(
|
|
3249
|
+
params.paymentNumber,
|
|
3250
|
+
params.paymentUpdate,
|
|
3251
|
+
{
|
|
3252
|
+
submitWhenPaid: true,
|
|
3253
|
+
matchBy: params.matchBy,
|
|
3254
|
+
forceSubmitIfPaid: params.forceSubmitIfPaid,
|
|
3255
|
+
applyUpdatesWhenPaid: params.forceSubmitIfPaid,
|
|
3256
|
+
smallTicketDataFlag: 1
|
|
3257
|
+
}
|
|
3258
|
+
);
|
|
3259
|
+
this.logInfo("processSuccessfulLocalPayment: 支付恢复完成", {
|
|
3260
|
+
...recoveryContext,
|
|
3261
|
+
duration_ms: Date.now() - startedAt,
|
|
3262
|
+
payment: result.payment,
|
|
3263
|
+
payments_count: ((_a = result.payments) == null ? void 0 : _a.length) || 0,
|
|
3264
|
+
summary: result.summary,
|
|
3265
|
+
sync_result: result.syncResult ? {
|
|
3266
|
+
is_fully_paid: result.syncResult.isFullyPaid,
|
|
3267
|
+
is_order_fully_paid: result.syncResult.isOrderFullyPaid,
|
|
3268
|
+
is_deposit_fully_paid: result.syncResult.isDepositFullyPaid,
|
|
3269
|
+
payment_stage: result.syncResult.paymentStage,
|
|
3270
|
+
deposit_amount: result.syncResult.depositAmount,
|
|
3271
|
+
order_expected_amount: result.syncResult.orderExpectedAmount,
|
|
3272
|
+
submit_result_code: (_b = result.syncResult.submitResult) == null ? void 0 : _b.code,
|
|
3273
|
+
submit_result_status: (_c = result.syncResult.submitResult) == null ? void 0 : _c.status
|
|
3274
|
+
} : null,
|
|
3275
|
+
draft_result: result.draftResult ? {
|
|
3276
|
+
code: (_d = result.draftResult) == null ? void 0 : _d.code,
|
|
3277
|
+
status: (_e = result.draftResult) == null ? void 0 : _e.status
|
|
3278
|
+
} : null,
|
|
3279
|
+
draft_error: result.draftError instanceof Error ? result.draftError.message : result.draftError
|
|
3280
|
+
});
|
|
3281
|
+
return {
|
|
3282
|
+
code: 200,
|
|
3283
|
+
status: true,
|
|
3284
|
+
message: "",
|
|
3285
|
+
data: {
|
|
3286
|
+
payment: result.payment,
|
|
3287
|
+
payments: result.payments,
|
|
3288
|
+
summary: result.summary,
|
|
3289
|
+
sync_result: result.syncResult
|
|
3290
|
+
}
|
|
3291
|
+
};
|
|
3292
|
+
} catch (error) {
|
|
3293
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3294
|
+
this.logError("processSuccessfulLocalPayment: 支付恢复失败", {
|
|
3295
|
+
...recoveryContext,
|
|
3296
|
+
duration_ms: Date.now() - startedAt,
|
|
3297
|
+
error: message,
|
|
3298
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3299
|
+
});
|
|
3300
|
+
return { code: 500, status: false, message, data: null };
|
|
3301
|
+
} finally {
|
|
3302
|
+
try {
|
|
3303
|
+
await baseSales.destroy();
|
|
3304
|
+
this.logInfo("processSuccessfulLocalPayment: 临时 BaseSales 销毁完成", {
|
|
3305
|
+
...recoveryContext,
|
|
3306
|
+
duration_ms: Date.now() - startedAt
|
|
3307
|
+
});
|
|
3308
|
+
} catch (error) {
|
|
3309
|
+
this.logError("processSuccessfulLocalPayment: 临时 BaseSales 销毁失败", {
|
|
3310
|
+
...recoveryContext,
|
|
3311
|
+
duration_ms: Date.now() - startedAt,
|
|
3312
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3313
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
sanitizeLocalRecoveryOrder(order) {
|
|
3319
|
+
const next = {
|
|
3320
|
+
...order,
|
|
3321
|
+
country_calling_code: String(order.country_calling_code ?? ""),
|
|
3322
|
+
phone: String(order.phone ?? ""),
|
|
3323
|
+
email: String(order.email ?? "")
|
|
3324
|
+
};
|
|
3325
|
+
const externalSaleNumber = next.external_sale_number;
|
|
3326
|
+
if (Number(next.is_draft_order || 0) === 1 && next.order_id !== void 0 && externalSaleNumber !== void 0 && String(next.order_id) === String(externalSaleNumber)) {
|
|
3327
|
+
delete next.order_id;
|
|
3328
|
+
}
|
|
3329
|
+
return next;
|
|
3330
|
+
}
|
|
2742
3331
|
getDeviceTaskPlugin() {
|
|
2743
3332
|
var _a, _b;
|
|
2744
3333
|
return ((_b = (_a = this.app) == null ? void 0 : _a.getPlugin) == null ? void 0 : _b.call(_a, "deviceTask")) || null;
|
|
@@ -3273,6 +3862,59 @@ var Server = class {
|
|
|
3273
3862
|
};
|
|
3274
3863
|
}
|
|
3275
3864
|
}
|
|
3865
|
+
async handleOrderDraftSubmit(params) {
|
|
3866
|
+
var _a, _b, _c;
|
|
3867
|
+
const { data, title } = params;
|
|
3868
|
+
this.logInfo(`${title}: 开始处理`, {
|
|
3869
|
+
order_id: data == null ? void 0 : data.order_id,
|
|
3870
|
+
external_sale_number: data == null ? void 0 : data.external_sale_number,
|
|
3871
|
+
order_number: data == null ? void 0 : data.order_number
|
|
3872
|
+
});
|
|
3873
|
+
const normalizedData = await this.normalizeCheckoutSubmitData(data, title);
|
|
3874
|
+
const createdAt = normalizedData.created_at || normalizedData.create_date || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
3875
|
+
const draftOrder = {
|
|
3876
|
+
...normalizedData,
|
|
3877
|
+
external_sale_number: normalizedData.external_sale_number || `LOCAL_DRAFT_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
|
|
3878
|
+
created_at: createdAt,
|
|
3879
|
+
schedule_date: normalizedData.schedule_date || createdAt,
|
|
3880
|
+
need_sync: 0,
|
|
3881
|
+
is_draft_order: 1
|
|
3882
|
+
};
|
|
3883
|
+
if (!this.order || typeof this.order.upsertLocalDraftOrders !== "function") {
|
|
3884
|
+
this.logError(`${title}: Order 模块不支持本地草稿写入`);
|
|
3885
|
+
return {
|
|
3886
|
+
code: 500,
|
|
3887
|
+
status: false,
|
|
3888
|
+
message: "Order 模块不支持本地草稿写入",
|
|
3889
|
+
data: null
|
|
3890
|
+
};
|
|
3891
|
+
}
|
|
3892
|
+
try {
|
|
3893
|
+
await this.order.upsertLocalDraftOrders([draftOrder]);
|
|
3894
|
+
this.logInfo(`${title}: 草稿订单已写入本地`, {
|
|
3895
|
+
order_id: draftOrder.order_id,
|
|
3896
|
+
external_sale_number: draftOrder.external_sale_number
|
|
3897
|
+
});
|
|
3898
|
+
return {
|
|
3899
|
+
code: 200,
|
|
3900
|
+
status: true,
|
|
3901
|
+
message: "",
|
|
3902
|
+
data: {
|
|
3903
|
+
...draftOrder,
|
|
3904
|
+
amount_gap: (_a = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _a.amount_gap,
|
|
3905
|
+
expect_amount: (_b = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _b.expect_amount,
|
|
3906
|
+
total_amount: (_c = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _c.total_amount,
|
|
3907
|
+
payment_status: draftOrder == null ? void 0 : draftOrder.payment_status
|
|
3908
|
+
}
|
|
3909
|
+
};
|
|
3910
|
+
} catch (error) {
|
|
3911
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3912
|
+
this.logError(`${title}: 写入本地草稿订单失败`, {
|
|
3913
|
+
error: errorMessage
|
|
3914
|
+
});
|
|
3915
|
+
return { code: 500, status: false, message: errorMessage, data: null };
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3276
3918
|
async handlePendingSyncCheckoutOrder(params) {
|
|
3277
3919
|
var _a, _b, _c, _d;
|
|
3278
3920
|
const { backendPath, data, title, reason } = params;
|
|
@@ -3348,7 +3990,8 @@ var Server = class {
|
|
|
3348
3990
|
return null;
|
|
3349
3991
|
const pendingOrder = {
|
|
3350
3992
|
...data,
|
|
3351
|
-
need_sync: 1
|
|
3993
|
+
need_sync: 1,
|
|
3994
|
+
is_draft_order: 0
|
|
3352
3995
|
};
|
|
3353
3996
|
const productMap = await this.buildSmallTicketProductMap(pendingOrder);
|
|
3354
3997
|
const orderWithProductTitles = this.withPendingSyncProductTitles(
|
|
@@ -3401,7 +4044,7 @@ var Server = class {
|
|
|
3401
4044
|
return 0;
|
|
3402
4045
|
return payments.reduce((sum, payment) => {
|
|
3403
4046
|
const status = String((payment == null ? void 0 : payment.status) || "").toLowerCase();
|
|
3404
|
-
if (status
|
|
4047
|
+
if (status !== "paid")
|
|
3405
4048
|
return sum;
|
|
3406
4049
|
return sum + this.toAmountNumber((payment == null ? void 0 : payment.amount) ?? (payment == null ? void 0 : payment.origin_amount));
|
|
3407
4050
|
}, 0);
|
|
@@ -3968,9 +4611,11 @@ var Server = class {
|
|
|
3968
4611
|
return value === void 0 ? void 0 : String(value);
|
|
3969
4612
|
}
|
|
3970
4613
|
buildCheckoutSyncSuccessPatch(fresh) {
|
|
4614
|
+
const patch = {
|
|
4615
|
+
is_draft_order: 0
|
|
4616
|
+
};
|
|
3971
4617
|
if (!fresh)
|
|
3972
|
-
return
|
|
3973
|
-
const patch = {};
|
|
4618
|
+
return patch;
|
|
3974
4619
|
if (fresh.order_id !== void 0 && fresh.order_id !== null)
|
|
3975
4620
|
patch.order_id = fresh.order_id;
|
|
3976
4621
|
if (fresh.order_number !== void 0 && fresh.order_number !== null) {
|
|
@@ -4251,6 +4896,10 @@ var Server = class {
|
|
|
4251
4896
|
const rawList = this.order.getOrders();
|
|
4252
4897
|
this.logInfo("computeOrderQueryResult: 本地订单数量", { rawCount: rawList.length });
|
|
4253
4898
|
const result = (0, import_filterOrders.filterOrders)(rawList, data);
|
|
4899
|
+
result.list.forEach((order) => {
|
|
4900
|
+
var _a;
|
|
4901
|
+
order.payments = (_a = order.payments) == null ? void 0 : _a.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
|
|
4902
|
+
});
|
|
4254
4903
|
this.logInfo("computeOrderQueryResult: 过滤结果", {
|
|
4255
4904
|
rawCount: rawList.length,
|
|
4256
4905
|
filteredCount: result.count,
|