@pisell/pisellos 2.3.29 → 2.3.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/Order/index.d.ts +27 -8
- package/dist/modules/Order/index.js +736 -473
- package/dist/modules/Order/payment-utils.d.ts +23 -0
- package/dist/modules/Order/payment-utils.js +203 -0
- package/dist/modules/Order/types.d.ts +33 -1
- package/dist/modules/Order/utils.js +4 -4
- package/dist/modules/Payment/index.d.ts +2 -0
- package/dist/modules/Payment/index.js +78 -49
- package/dist/modules/Payment/types.d.ts +26 -24
- package/dist/modules/Payment/types.js +2 -0
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.js +1850 -1024
- package/dist/server/modules/order/index.d.ts +40 -3
- package/dist/server/modules/order/index.js +1200 -501
- package/dist/server/modules/order/types.d.ts +11 -3
- package/dist/server/modules/order/types.js +1 -1
- package/dist/solution/BaseSales/index.d.ts +33 -3
- package/dist/solution/BaseSales/index.js +609 -322
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +2 -1
- package/dist/utils/payment-number.d.ts +9 -0
- package/dist/utils/payment-number.js +69 -0
- package/lib/model/strategy/adapter/promotion/index.js +0 -49
- package/lib/modules/Order/index.d.ts +27 -8
- package/lib/modules/Order/index.js +180 -60
- package/lib/modules/Order/payment-utils.d.ts +23 -0
- package/lib/modules/Order/payment-utils.js +193 -0
- package/lib/modules/Order/types.d.ts +33 -1
- package/lib/modules/Order/utils.js +2 -3
- package/lib/modules/Payment/index.d.ts +2 -0
- package/lib/modules/Payment/index.js +33 -12
- package/lib/modules/Payment/types.d.ts +26 -24
- package/lib/server/index.d.ts +14 -0
- package/lib/server/index.js +604 -8
- package/lib/server/modules/order/index.d.ts +40 -3
- package/lib/server/modules/order/index.js +434 -31
- package/lib/server/modules/order/types.d.ts +11 -3
- package/lib/solution/BaseSales/index.d.ts +33 -3
- package/lib/solution/BaseSales/index.js +167 -7
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +2 -1
- 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,7 @@ __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"));
|
|
37
38
|
var import_products = require("./modules/products");
|
|
38
39
|
var import_menu = require("./modules/menu");
|
|
39
40
|
var import_quotation = require("./modules/quotation");
|
|
@@ -50,6 +51,7 @@ var import_types3 = require("./modules/order/types");
|
|
|
50
51
|
var import_filterOrders = require("./modules/order/utils/filterOrders");
|
|
51
52
|
var import_filterBookings = require("./modules/order/utils/filterBookings");
|
|
52
53
|
var import_small_ticket = require("./utils/small-ticket");
|
|
54
|
+
var import_BaseSales = require("../solution/BaseSales");
|
|
53
55
|
__reExport(server_exports, require("./modules"), module.exports);
|
|
54
56
|
var PRODUCT_TITLE_SNAPSHOT_KEYS = [
|
|
55
57
|
"en",
|
|
@@ -87,6 +89,7 @@ var Server = class {
|
|
|
87
89
|
this.BOOKING_REMOTE_CACHE_MAX_ENTRIES = 80;
|
|
88
90
|
this.salesSearchSubscribers = /* @__PURE__ */ new Map();
|
|
89
91
|
this.deviceTaskActionsRegistered = false;
|
|
92
|
+
this.localPaymentUpdateQueues = /* @__PURE__ */ new Map();
|
|
90
93
|
this.floorPlanQuerySubscribers = /* @__PURE__ */ new Map();
|
|
91
94
|
// 模块注册表 - 定义所有可用的模块配置
|
|
92
95
|
this.moduleRegistry = {
|
|
@@ -575,6 +578,128 @@ var Server = class {
|
|
|
575
578
|
title: "handleOrderSalesCheckout"
|
|
576
579
|
});
|
|
577
580
|
};
|
|
581
|
+
this.handleOrderSalesDraft = async ({ data }) => {
|
|
582
|
+
return this.handleOrderDraftSubmit({
|
|
583
|
+
data,
|
|
584
|
+
title: "handleOrderSalesDraft"
|
|
585
|
+
});
|
|
586
|
+
};
|
|
587
|
+
this.handleGetLocalPayment = async ({ data }) => {
|
|
588
|
+
const saleId = data == null ? void 0 : data.sale_id;
|
|
589
|
+
const paymentNumber = data == null ? void 0 : data.payment_number;
|
|
590
|
+
const operationId = this.createLocalPaymentOperationId("get");
|
|
591
|
+
const requestContext = {
|
|
592
|
+
operation_id: operationId,
|
|
593
|
+
sale_id: saleId ?? null,
|
|
594
|
+
payment_number: paymentNumber ?? null
|
|
595
|
+
};
|
|
596
|
+
this.logInfo("handleGetLocalPayment: 请求进入", requestContext);
|
|
597
|
+
if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "") {
|
|
598
|
+
this.logWarning("handleGetLocalPayment: 参数校验失败", {
|
|
599
|
+
...requestContext,
|
|
600
|
+
missing_fields: [
|
|
601
|
+
...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
|
|
602
|
+
...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : []
|
|
603
|
+
]
|
|
604
|
+
});
|
|
605
|
+
return {
|
|
606
|
+
code: 400,
|
|
607
|
+
status: false,
|
|
608
|
+
message: "sale_id 和 payment_number 必填",
|
|
609
|
+
data: null
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
if (!this.order) {
|
|
613
|
+
this.logError("handleGetLocalPayment: Order 模块未注册", requestContext);
|
|
614
|
+
return { code: 500, status: false, message: "Order 模块未注册", data: null };
|
|
615
|
+
}
|
|
616
|
+
const startedAt = Date.now();
|
|
617
|
+
try {
|
|
618
|
+
this.logInfo("handleGetLocalPayment: 开始查询本地支付项", requestContext);
|
|
619
|
+
const found = await this.order.getLocalPayment({
|
|
620
|
+
saleId,
|
|
621
|
+
paymentNumber,
|
|
622
|
+
operationId
|
|
623
|
+
});
|
|
624
|
+
if (!found) {
|
|
625
|
+
this.logWarning("handleGetLocalPayment: 本地支付项不存在", {
|
|
626
|
+
...requestContext,
|
|
627
|
+
duration_ms: Date.now() - startedAt
|
|
628
|
+
});
|
|
629
|
+
return { code: 404, status: false, message: "本地支付项不存在", data: null };
|
|
630
|
+
}
|
|
631
|
+
this.logInfo("handleGetLocalPayment: 查询命中", {
|
|
632
|
+
...requestContext,
|
|
633
|
+
duration_ms: Date.now() - startedAt,
|
|
634
|
+
matched_by: found.matchedBy,
|
|
635
|
+
payment_index: found.paymentIndex,
|
|
636
|
+
...this.buildLocalPaymentOrderLogContext(found.order),
|
|
637
|
+
payment: found.payment
|
|
638
|
+
});
|
|
639
|
+
return { code: 200, status: true, message: "", data: found.payment };
|
|
640
|
+
} catch (error) {
|
|
641
|
+
this.logError("handleGetLocalPayment: 查询异常", {
|
|
642
|
+
...requestContext,
|
|
643
|
+
duration_ms: Date.now() - startedAt,
|
|
644
|
+
error: error instanceof Error ? error.message : String(error),
|
|
645
|
+
error_detail: this.normalizeUnknownError(error)
|
|
646
|
+
});
|
|
647
|
+
throw error;
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
this.handleUpdateLocalPayment = async ({ data }) => {
|
|
651
|
+
const saleId = data == null ? void 0 : data.sale_id;
|
|
652
|
+
const paymentNumber = data == null ? void 0 : data.payment_number;
|
|
653
|
+
const number = data == null ? void 0 : data.number;
|
|
654
|
+
const status = data == null ? void 0 : data.status;
|
|
655
|
+
const serviceCharge = data == null ? void 0 : data.service_charge;
|
|
656
|
+
const cardReaderSurcharge = data == null ? void 0 : data.card_reader_surcharge;
|
|
657
|
+
const hasSurchargeInput = serviceCharge !== void 0 || cardReaderSurcharge !== void 0;
|
|
658
|
+
const invalidSurchargeFields = this.getInvalidLocalPaymentSurchargeFields(
|
|
659
|
+
serviceCharge,
|
|
660
|
+
cardReaderSurcharge
|
|
661
|
+
);
|
|
662
|
+
const operationId = this.createLocalPaymentOperationId("update");
|
|
663
|
+
const requestContext = {
|
|
664
|
+
operation_id: operationId,
|
|
665
|
+
sale_id: saleId ?? null,
|
|
666
|
+
payment_number: paymentNumber ?? null,
|
|
667
|
+
transaction_number: number ?? null,
|
|
668
|
+
requested_status: status ?? null,
|
|
669
|
+
service_charge: serviceCharge ?? null,
|
|
670
|
+
card_reader_surcharge: cardReaderSurcharge ?? null
|
|
671
|
+
};
|
|
672
|
+
this.logInfo("handleUpdateLocalPayment: 请求进入", requestContext);
|
|
673
|
+
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) {
|
|
674
|
+
this.logWarning("handleUpdateLocalPayment: 参数校验失败", {
|
|
675
|
+
...requestContext,
|
|
676
|
+
missing_or_invalid_fields: [
|
|
677
|
+
...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
|
|
678
|
+
...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : [],
|
|
679
|
+
...number === void 0 || number === null || number === "" ? ["number"] : [],
|
|
680
|
+
...status !== "success" && status !== "fail" ? ["status"] : [],
|
|
681
|
+
...invalidSurchargeFields
|
|
682
|
+
]
|
|
683
|
+
});
|
|
684
|
+
return {
|
|
685
|
+
code: 400,
|
|
686
|
+
status: false,
|
|
687
|
+
message: invalidSurchargeFields.length > 0 ? `手续费参数非法: ${invalidSurchargeFields.join(", ")}` : "sale_id、payment_number、number 必填,status 仅支持 success/fail",
|
|
688
|
+
data: null
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
const queueKey = `${String(saleId)}:${String(paymentNumber)}`;
|
|
692
|
+
return this.runLocalPaymentUpdateInQueue(queueKey, () => this.processLocalPaymentUpdate({
|
|
693
|
+
operationId,
|
|
694
|
+
saleId,
|
|
695
|
+
paymentNumber,
|
|
696
|
+
number: String(number),
|
|
697
|
+
status,
|
|
698
|
+
serviceCharge,
|
|
699
|
+
cardReaderSurcharge,
|
|
700
|
+
hasSurchargeInput
|
|
701
|
+
}), requestContext);
|
|
702
|
+
};
|
|
578
703
|
this.handleOrderCheckout = async ({ data }) => {
|
|
579
704
|
return this.handleOrderCheckoutSubmit({
|
|
580
705
|
backendPath: "/order/checkout",
|
|
@@ -1439,13 +1564,15 @@ var Server = class {
|
|
|
1439
1564
|
...checkoutData,
|
|
1440
1565
|
...fresh,
|
|
1441
1566
|
external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
|
|
1442
|
-
need_sync: 0
|
|
1567
|
+
need_sync: 0,
|
|
1568
|
+
is_draft_order: 0
|
|
1443
1569
|
} : {
|
|
1444
1570
|
...fresh,
|
|
1445
1571
|
external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
|
|
1446
|
-
need_sync: 0
|
|
1572
|
+
need_sync: 0,
|
|
1573
|
+
is_draft_order: 0
|
|
1447
1574
|
};
|
|
1448
|
-
await this.order.upsertOrdersFromRemote([syncedOrder]);
|
|
1575
|
+
await this.order.upsertOrdersFromRemote([syncedOrder], "checkoutSync");
|
|
1449
1576
|
this.logInfo(`${title}: sync_sales 完整订单已同步到本地`, {
|
|
1450
1577
|
order_id: fresh.order_id,
|
|
1451
1578
|
external_sale_number: syncedOrder.external_sale_number,
|
|
@@ -1463,7 +1590,8 @@ var Server = class {
|
|
|
1463
1590
|
...checkoutData,
|
|
1464
1591
|
...patch,
|
|
1465
1592
|
external_sale_number: externalSaleNumber,
|
|
1466
|
-
need_sync: 0
|
|
1593
|
+
need_sync: 0,
|
|
1594
|
+
is_draft_order: 0
|
|
1467
1595
|
};
|
|
1468
1596
|
this.logInfo(`${title}: sync_sales 已按 external_sale_number 标记本地订单`, {
|
|
1469
1597
|
order_id: (syncedOrder == null ? void 0 : syncedOrder.order_id) ?? null,
|
|
@@ -1843,6 +1971,11 @@ var Server = class {
|
|
|
1843
1971
|
path: "/shop/order/sales/checkout",
|
|
1844
1972
|
handler: this.handleOrderSalesCheckout.bind(this)
|
|
1845
1973
|
},
|
|
1974
|
+
{
|
|
1975
|
+
method: "post",
|
|
1976
|
+
path: "/shop/order/sales/draft",
|
|
1977
|
+
handler: this.handleOrderSalesDraft.bind(this)
|
|
1978
|
+
},
|
|
1846
1979
|
{
|
|
1847
1980
|
method: "post",
|
|
1848
1981
|
path: "/order/checkout",
|
|
@@ -1853,6 +1986,16 @@ var Server = class {
|
|
|
1853
1986
|
path: "/shop/local/print-order",
|
|
1854
1987
|
handler: this.handleLocalPrintOrder.bind(this)
|
|
1855
1988
|
},
|
|
1989
|
+
{
|
|
1990
|
+
method: "post",
|
|
1991
|
+
path: "/shop/local/getLocalPayment",
|
|
1992
|
+
handler: this.handleGetLocalPayment.bind(this)
|
|
1993
|
+
},
|
|
1994
|
+
{
|
|
1995
|
+
method: "post",
|
|
1996
|
+
path: "/shop/local/updateLocalPayment",
|
|
1997
|
+
handler: this.handleUpdateLocalPayment.bind(this)
|
|
1998
|
+
},
|
|
1856
1999
|
{
|
|
1857
2000
|
method: "post",
|
|
1858
2001
|
path: "/shop/machinecode/batch",
|
|
@@ -2694,6 +2837,403 @@ var Server = class {
|
|
|
2694
2837
|
};
|
|
2695
2838
|
}
|
|
2696
2839
|
}
|
|
2840
|
+
createLocalPaymentOperationId(action) {
|
|
2841
|
+
return `local_payment_${action}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2842
|
+
}
|
|
2843
|
+
buildLocalPaymentOrderLogContext(order) {
|
|
2844
|
+
if (!order)
|
|
2845
|
+
return {};
|
|
2846
|
+
return {
|
|
2847
|
+
order_id: order.order_id ?? null,
|
|
2848
|
+
external_sale_number: order.external_sale_number ?? null,
|
|
2849
|
+
order_number: order.order_number ?? null,
|
|
2850
|
+
shop_order_number: order.shop_order_number ?? null,
|
|
2851
|
+
shop_full_order_number: order.shop_full_order_number ?? null,
|
|
2852
|
+
order_status: order.status ?? null,
|
|
2853
|
+
payment_status: order.payment_status ?? null,
|
|
2854
|
+
is_draft_order: Number(order.is_draft_order || 0),
|
|
2855
|
+
need_sync: Number(order.need_sync || 0),
|
|
2856
|
+
platform: order.platform ?? null,
|
|
2857
|
+
business_code: order.business_code ?? null,
|
|
2858
|
+
order_sales_channel: order.order_sales_channel ?? null,
|
|
2859
|
+
sales_channel: order.sales_channel ?? null,
|
|
2860
|
+
order_type: order.type ?? null,
|
|
2861
|
+
payments_count: Array.isArray(order.payments) ? order.payments.length : 0
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
isValidLocalPaymentDecimal(value) {
|
|
2865
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
2866
|
+
return false;
|
|
2867
|
+
if (typeof value === "string" && value.trim() === "")
|
|
2868
|
+
return false;
|
|
2869
|
+
try {
|
|
2870
|
+
return new import_decimal.default(value).isFinite();
|
|
2871
|
+
} catch {
|
|
2872
|
+
return false;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
getInvalidLocalPaymentSurchargeFields(serviceCharge, cardReaderSurcharge) {
|
|
2876
|
+
const invalidFields = [];
|
|
2877
|
+
if (serviceCharge !== void 0) {
|
|
2878
|
+
if (serviceCharge === null || typeof serviceCharge !== "object" || Array.isArray(serviceCharge)) {
|
|
2879
|
+
invalidFields.push("service_charge");
|
|
2880
|
+
} else {
|
|
2881
|
+
const input = serviceCharge;
|
|
2882
|
+
if (input.fixed !== void 0 && !this.isValidLocalPaymentDecimal(input.fixed)) {
|
|
2883
|
+
invalidFields.push("service_charge.fixed");
|
|
2884
|
+
}
|
|
2885
|
+
if (input.percentage !== void 0 && !this.isValidLocalPaymentDecimal(input.percentage)) {
|
|
2886
|
+
invalidFields.push("service_charge.percentage");
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
if (cardReaderSurcharge !== void 0 && !this.isValidLocalPaymentDecimal(cardReaderSurcharge)) {
|
|
2891
|
+
invalidFields.push("card_reader_surcharge");
|
|
2892
|
+
}
|
|
2893
|
+
return invalidFields;
|
|
2894
|
+
}
|
|
2895
|
+
buildLocalPaymentSurchargeUpdate(params) {
|
|
2896
|
+
var _a, _b, _c;
|
|
2897
|
+
const amount = new import_decimal.default(((_a = params.serviceCharge) == null ? void 0 : _a.fixed) || 0).plus(params.cardReaderSurcharge || 0).toFixed(2);
|
|
2898
|
+
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);
|
|
2899
|
+
return {
|
|
2900
|
+
service_charge: {
|
|
2901
|
+
amount,
|
|
2902
|
+
...((_c = params.serviceCharge) == null ? void 0 : _c.percentage) !== void 0 ? { percentage: params.serviceCharge.percentage } : {}
|
|
2903
|
+
},
|
|
2904
|
+
service_fee: serviceFee
|
|
2905
|
+
};
|
|
2906
|
+
}
|
|
2907
|
+
async runLocalPaymentUpdateInQueue(key, task, context) {
|
|
2908
|
+
var _a;
|
|
2909
|
+
const queuedAt = Date.now();
|
|
2910
|
+
const hasPreviousTask = this.localPaymentUpdateQueues.has(key);
|
|
2911
|
+
const previous = this.localPaymentUpdateQueues.get(key) || Promise.resolve();
|
|
2912
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列入队", {
|
|
2913
|
+
...context,
|
|
2914
|
+
queue_key: key,
|
|
2915
|
+
waiting_for_previous: hasPreviousTask,
|
|
2916
|
+
active_queue_count: this.localPaymentUpdateQueues.size
|
|
2917
|
+
});
|
|
2918
|
+
const current = previous.catch(() => void 0).then(async () => {
|
|
2919
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列开始执行", {
|
|
2920
|
+
...context,
|
|
2921
|
+
queue_key: key,
|
|
2922
|
+
queue_wait_ms: Date.now() - queuedAt
|
|
2923
|
+
});
|
|
2924
|
+
return task();
|
|
2925
|
+
});
|
|
2926
|
+
const tail = current.then(() => void 0, () => void 0);
|
|
2927
|
+
this.localPaymentUpdateQueues.set(key, tail);
|
|
2928
|
+
try {
|
|
2929
|
+
const result = await current;
|
|
2930
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列执行完成", {
|
|
2931
|
+
...context,
|
|
2932
|
+
queue_key: key,
|
|
2933
|
+
total_duration_ms: Date.now() - queuedAt,
|
|
2934
|
+
result_code: result == null ? void 0 : result.code,
|
|
2935
|
+
result_status: result == null ? void 0 : result.status,
|
|
2936
|
+
payment: (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.payment
|
|
2937
|
+
});
|
|
2938
|
+
return result;
|
|
2939
|
+
} catch (error) {
|
|
2940
|
+
this.logError("handleUpdateLocalPayment: 串行队列执行失败", {
|
|
2941
|
+
...context,
|
|
2942
|
+
queue_key: key,
|
|
2943
|
+
total_duration_ms: Date.now() - queuedAt,
|
|
2944
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2945
|
+
error_detail: this.normalizeUnknownError(error)
|
|
2946
|
+
});
|
|
2947
|
+
throw error;
|
|
2948
|
+
} finally {
|
|
2949
|
+
let released = false;
|
|
2950
|
+
if (this.localPaymentUpdateQueues.get(key) === tail) {
|
|
2951
|
+
this.localPaymentUpdateQueues.delete(key);
|
|
2952
|
+
released = true;
|
|
2953
|
+
}
|
|
2954
|
+
this.logInfo("handleUpdateLocalPayment: 串行队列释放", {
|
|
2955
|
+
...context,
|
|
2956
|
+
queue_key: key,
|
|
2957
|
+
released,
|
|
2958
|
+
active_queue_count: this.localPaymentUpdateQueues.size
|
|
2959
|
+
});
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
async processLocalPaymentUpdate(params) {
|
|
2963
|
+
var _a, _b, _c;
|
|
2964
|
+
const requestContext = {
|
|
2965
|
+
operation_id: params.operationId,
|
|
2966
|
+
sale_id: params.saleId,
|
|
2967
|
+
payment_number: params.paymentNumber,
|
|
2968
|
+
transaction_number: params.number,
|
|
2969
|
+
requested_status: params.status,
|
|
2970
|
+
service_charge: params.serviceCharge ?? null,
|
|
2971
|
+
card_reader_surcharge: params.cardReaderSurcharge ?? null
|
|
2972
|
+
};
|
|
2973
|
+
this.logInfo("processLocalPaymentUpdate: 开始处理", requestContext);
|
|
2974
|
+
if (!this.order) {
|
|
2975
|
+
this.logError("processLocalPaymentUpdate: Order 模块未注册", requestContext);
|
|
2976
|
+
return { code: 500, status: false, message: "Order 模块未注册", data: null };
|
|
2977
|
+
}
|
|
2978
|
+
this.logInfo("processLocalPaymentUpdate: 开始查询本地支付项", requestContext);
|
|
2979
|
+
const found = await this.order.getLocalPayment({
|
|
2980
|
+
saleId: params.saleId,
|
|
2981
|
+
paymentNumber: params.paymentNumber,
|
|
2982
|
+
operationId: params.operationId
|
|
2983
|
+
});
|
|
2984
|
+
if (!found) {
|
|
2985
|
+
this.logWarning("processLocalPaymentUpdate: 本地支付项不存在", requestContext);
|
|
2986
|
+
return { code: 404, status: false, message: "本地支付项不存在", data: null };
|
|
2987
|
+
}
|
|
2988
|
+
const surchargeUpdate = params.status === "success" && params.hasSurchargeInput ? this.buildLocalPaymentSurchargeUpdate({
|
|
2989
|
+
paymentAmount: (_a = found.payment) == null ? void 0 : _a.amount,
|
|
2990
|
+
serviceCharge: params.serviceCharge,
|
|
2991
|
+
cardReaderSurcharge: params.cardReaderSurcharge
|
|
2992
|
+
}) : void 0;
|
|
2993
|
+
const incomingPaymentUpdate = params.status === "success" ? {
|
|
2994
|
+
status: "paid",
|
|
2995
|
+
...surchargeUpdate || {},
|
|
2996
|
+
metadata: {
|
|
2997
|
+
unique_payment_number: params.number,
|
|
2998
|
+
transactions: [{ number: params.number, status: "success" }]
|
|
2999
|
+
}
|
|
3000
|
+
} : {
|
|
3001
|
+
metadata: {
|
|
3002
|
+
transactions: [{ number: params.number, status: "fail" }]
|
|
3003
|
+
}
|
|
3004
|
+
};
|
|
3005
|
+
const transactions = Array.isArray((_c = (_b = found.payment) == null ? void 0 : _b.metadata) == null ? void 0 : _c.transactions) ? found.payment.metadata.transactions : [];
|
|
3006
|
+
const existingTransaction = transactions.find((item) => String((item == null ? void 0 : item.number) || "") === params.number);
|
|
3007
|
+
const hasRecordedSuccess = transactions.some((item) => (item == null ? void 0 : item.status) === "success");
|
|
3008
|
+
const orderIsDraft = Number(found.order.is_draft_order || 0) === 1;
|
|
3009
|
+
const foundContext = {
|
|
3010
|
+
...requestContext,
|
|
3011
|
+
matched_by: found.matchedBy,
|
|
3012
|
+
payment_index: found.paymentIndex,
|
|
3013
|
+
...this.buildLocalPaymentOrderLogContext(found.order),
|
|
3014
|
+
payment: found.payment,
|
|
3015
|
+
incoming_payment_update: incomingPaymentUpdate,
|
|
3016
|
+
existing_transaction: existingTransaction || null,
|
|
3017
|
+
has_recorded_success: hasRecordedSuccess
|
|
3018
|
+
};
|
|
3019
|
+
this.logInfo("processLocalPaymentUpdate: 查询命中", foundContext);
|
|
3020
|
+
if (params.status === "fail" && (found.payment.status === "paid" || hasRecordedSuccess)) {
|
|
3021
|
+
this.logInfo("processLocalPaymentUpdate: 幂等返回", {
|
|
3022
|
+
...foundContext,
|
|
3023
|
+
idempotent_reason: "ignore_failure_after_success"
|
|
3024
|
+
});
|
|
3025
|
+
return {
|
|
3026
|
+
code: 200,
|
|
3027
|
+
status: true,
|
|
3028
|
+
message: "",
|
|
3029
|
+
data: { payment: found.payment, order: found.order, idempotent: true }
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
const alreadyRecordedFailure = params.status === "fail" && (existingTransaction == null ? void 0 : existingTransaction.status) === "fail";
|
|
3033
|
+
if (alreadyRecordedFailure) {
|
|
3034
|
+
this.logInfo("processLocalPaymentUpdate: 幂等返回", {
|
|
3035
|
+
...foundContext,
|
|
3036
|
+
idempotent_reason: "failure_already_recorded"
|
|
3037
|
+
});
|
|
3038
|
+
return {
|
|
3039
|
+
code: 200,
|
|
3040
|
+
status: true,
|
|
3041
|
+
message: "",
|
|
3042
|
+
data: { payment: found.payment, order: found.order, idempotent: true }
|
|
3043
|
+
};
|
|
3044
|
+
}
|
|
3045
|
+
if (params.status === "success" && (existingTransaction == null ? void 0 : existingTransaction.status) === "success" && found.payment.status === "paid" && !orderIsDraft) {
|
|
3046
|
+
this.logInfo("processLocalPaymentUpdate: 幂等返回", {
|
|
3047
|
+
...foundContext,
|
|
3048
|
+
idempotent_reason: "success_already_committed"
|
|
3049
|
+
});
|
|
3050
|
+
return {
|
|
3051
|
+
code: 200,
|
|
3052
|
+
status: true,
|
|
3053
|
+
message: "",
|
|
3054
|
+
data: { payment: found.payment, order: found.order, idempotent: true }
|
|
3055
|
+
};
|
|
3056
|
+
}
|
|
3057
|
+
if (params.status === "success") {
|
|
3058
|
+
this.logInfo("processLocalPaymentUpdate: 进入 success 恢复分支", {
|
|
3059
|
+
...foundContext,
|
|
3060
|
+
force_submit_if_paid: found.payment.status === "paid" && orderIsDraft
|
|
3061
|
+
});
|
|
3062
|
+
return this.processSuccessfulLocalPayment({
|
|
3063
|
+
...params,
|
|
3064
|
+
order: found.order,
|
|
3065
|
+
payment: found.payment,
|
|
3066
|
+
matchBy: found.matchedBy === "payment_number" ? "payment_number" : "compat",
|
|
3067
|
+
forceSubmitIfPaid: found.payment.status === "paid" && orderIsDraft,
|
|
3068
|
+
paymentUpdate: incomingPaymentUpdate
|
|
3069
|
+
});
|
|
3070
|
+
}
|
|
3071
|
+
this.logInfo("processLocalPaymentUpdate: 进入 fail 本地更新分支", {
|
|
3072
|
+
...foundContext,
|
|
3073
|
+
incoming_payment_update: incomingPaymentUpdate
|
|
3074
|
+
});
|
|
3075
|
+
let updated;
|
|
3076
|
+
try {
|
|
3077
|
+
updated = await this.order.updateLocalPayment({
|
|
3078
|
+
saleId: params.saleId,
|
|
3079
|
+
paymentNumber: params.paymentNumber,
|
|
3080
|
+
operationId: params.operationId,
|
|
3081
|
+
updates: incomingPaymentUpdate
|
|
3082
|
+
});
|
|
3083
|
+
} catch (error) {
|
|
3084
|
+
this.logError("processLocalPaymentUpdate: fail 本地更新失败", {
|
|
3085
|
+
...foundContext,
|
|
3086
|
+
incoming_payment_update: incomingPaymentUpdate,
|
|
3087
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3088
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3089
|
+
});
|
|
3090
|
+
throw error;
|
|
3091
|
+
}
|
|
3092
|
+
if (!updated) {
|
|
3093
|
+
this.logWarning("processLocalPaymentUpdate: fail 本地更新未命中", foundContext);
|
|
3094
|
+
return { code: 404, status: false, message: "本地支付项不存在", data: null };
|
|
3095
|
+
}
|
|
3096
|
+
this.logInfo("processLocalPaymentUpdate: fail 本地更新完成", {
|
|
3097
|
+
...requestContext,
|
|
3098
|
+
...this.buildLocalPaymentOrderLogContext(updated.order),
|
|
3099
|
+
previous_payment: updated.previousPayment,
|
|
3100
|
+
payment: updated.payment
|
|
3101
|
+
});
|
|
3102
|
+
return {
|
|
3103
|
+
code: 200,
|
|
3104
|
+
status: true,
|
|
3105
|
+
message: "",
|
|
3106
|
+
data: {
|
|
3107
|
+
local_only: true,
|
|
3108
|
+
payment: updated.payment,
|
|
3109
|
+
order: updated.order
|
|
3110
|
+
}
|
|
3111
|
+
};
|
|
3112
|
+
}
|
|
3113
|
+
async processSuccessfulLocalPayment(params) {
|
|
3114
|
+
var _a, _b, _c, _d, _e;
|
|
3115
|
+
const moduleName = `local_payment_recovery_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
3116
|
+
const baseSales = new import_BaseSales.BaseSalesImpl(moduleName);
|
|
3117
|
+
const startedAt = Date.now();
|
|
3118
|
+
const recoveryContext = {
|
|
3119
|
+
operation_id: params.operationId,
|
|
3120
|
+
sale_id: params.saleId,
|
|
3121
|
+
payment_number: params.paymentNumber,
|
|
3122
|
+
transaction_number: params.number,
|
|
3123
|
+
requested_status: "success",
|
|
3124
|
+
match_by: params.matchBy,
|
|
3125
|
+
force_submit_if_paid: params.forceSubmitIfPaid,
|
|
3126
|
+
incoming_payment_update: params.paymentUpdate,
|
|
3127
|
+
base_sales_module_name: moduleName,
|
|
3128
|
+
...this.buildLocalPaymentOrderLogContext(params.order),
|
|
3129
|
+
payment: params.payment
|
|
3130
|
+
};
|
|
3131
|
+
this.logInfo("processSuccessfulLocalPayment: 创建临时 BaseSales", recoveryContext);
|
|
3132
|
+
try {
|
|
3133
|
+
const order = this.sanitizeLocalRecoveryOrder(params.order);
|
|
3134
|
+
this.logInfo("processSuccessfulLocalPayment: 本地订单清洗完成", {
|
|
3135
|
+
...recoveryContext,
|
|
3136
|
+
sanitized_order_id: order.order_id ?? null,
|
|
3137
|
+
removed_synthetic_order_id: params.order.order_id != null && order.order_id == null
|
|
3138
|
+
});
|
|
3139
|
+
await baseSales.initialize(this.core, {
|
|
3140
|
+
otherParams: {
|
|
3141
|
+
platform: order.platform,
|
|
3142
|
+
businessCode: order.business_code,
|
|
3143
|
+
business_code: order.business_code,
|
|
3144
|
+
channel: order.order_sales_channel || order.sales_channel,
|
|
3145
|
+
type: order.type,
|
|
3146
|
+
enableTempOrderPersist: false
|
|
3147
|
+
}
|
|
3148
|
+
});
|
|
3149
|
+
this.logInfo("processSuccessfulLocalPayment: BaseSales 初始化完成", recoveryContext);
|
|
3150
|
+
await baseSales.loadSalesDetail({
|
|
3151
|
+
externalSaleNumber: String(params.saleId),
|
|
3152
|
+
preloadedSalesDetail: order
|
|
3153
|
+
});
|
|
3154
|
+
this.logInfo("processSuccessfulLocalPayment: 本地订单 hydrate 完成", recoveryContext);
|
|
3155
|
+
this.logInfo("processSuccessfulLocalPayment: 开始更新支付项并提交", {
|
|
3156
|
+
...recoveryContext,
|
|
3157
|
+
incoming_payment_update: params.paymentUpdate
|
|
3158
|
+
});
|
|
3159
|
+
const result = await baseSales.updateOrderPayment(
|
|
3160
|
+
params.paymentNumber,
|
|
3161
|
+
params.paymentUpdate,
|
|
3162
|
+
{
|
|
3163
|
+
submitWhenPaid: true,
|
|
3164
|
+
matchBy: params.matchBy,
|
|
3165
|
+
forceSubmitIfPaid: params.forceSubmitIfPaid,
|
|
3166
|
+
applyUpdatesWhenPaid: params.forceSubmitIfPaid,
|
|
3167
|
+
smallTicketDataFlag: 1
|
|
3168
|
+
}
|
|
3169
|
+
);
|
|
3170
|
+
this.logInfo("processSuccessfulLocalPayment: 支付恢复完成", {
|
|
3171
|
+
...recoveryContext,
|
|
3172
|
+
duration_ms: Date.now() - startedAt,
|
|
3173
|
+
payment: result.payment,
|
|
3174
|
+
payments_count: ((_a = result.payments) == null ? void 0 : _a.length) || 0,
|
|
3175
|
+
summary: result.summary,
|
|
3176
|
+
sync_result: result.syncResult ? {
|
|
3177
|
+
is_fully_paid: result.syncResult.isFullyPaid,
|
|
3178
|
+
is_order_fully_paid: result.syncResult.isOrderFullyPaid,
|
|
3179
|
+
is_deposit_fully_paid: result.syncResult.isDepositFullyPaid,
|
|
3180
|
+
payment_stage: result.syncResult.paymentStage,
|
|
3181
|
+
deposit_amount: result.syncResult.depositAmount,
|
|
3182
|
+
order_expected_amount: result.syncResult.orderExpectedAmount,
|
|
3183
|
+
submit_result_code: (_b = result.syncResult.submitResult) == null ? void 0 : _b.code,
|
|
3184
|
+
submit_result_status: (_c = result.syncResult.submitResult) == null ? void 0 : _c.status
|
|
3185
|
+
} : null,
|
|
3186
|
+
draft_result: result.draftResult ? {
|
|
3187
|
+
code: (_d = result.draftResult) == null ? void 0 : _d.code,
|
|
3188
|
+
status: (_e = result.draftResult) == null ? void 0 : _e.status
|
|
3189
|
+
} : null,
|
|
3190
|
+
draft_error: result.draftError instanceof Error ? result.draftError.message : result.draftError
|
|
3191
|
+
});
|
|
3192
|
+
return {
|
|
3193
|
+
code: 200,
|
|
3194
|
+
status: true,
|
|
3195
|
+
message: "",
|
|
3196
|
+
data: {
|
|
3197
|
+
payment: result.payment,
|
|
3198
|
+
payments: result.payments,
|
|
3199
|
+
summary: result.summary,
|
|
3200
|
+
sync_result: result.syncResult
|
|
3201
|
+
}
|
|
3202
|
+
};
|
|
3203
|
+
} catch (error) {
|
|
3204
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3205
|
+
this.logError("processSuccessfulLocalPayment: 支付恢复失败", {
|
|
3206
|
+
...recoveryContext,
|
|
3207
|
+
duration_ms: Date.now() - startedAt,
|
|
3208
|
+
error: message,
|
|
3209
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3210
|
+
});
|
|
3211
|
+
return { code: 500, status: false, message, data: null };
|
|
3212
|
+
} finally {
|
|
3213
|
+
try {
|
|
3214
|
+
await baseSales.destroy();
|
|
3215
|
+
this.logInfo("processSuccessfulLocalPayment: 临时 BaseSales 销毁完成", {
|
|
3216
|
+
...recoveryContext,
|
|
3217
|
+
duration_ms: Date.now() - startedAt
|
|
3218
|
+
});
|
|
3219
|
+
} catch (error) {
|
|
3220
|
+
this.logError("processSuccessfulLocalPayment: 临时 BaseSales 销毁失败", {
|
|
3221
|
+
...recoveryContext,
|
|
3222
|
+
duration_ms: Date.now() - startedAt,
|
|
3223
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3224
|
+
error_detail: this.normalizeUnknownError(error)
|
|
3225
|
+
});
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
sanitizeLocalRecoveryOrder(order) {
|
|
3230
|
+
const next = { ...order };
|
|
3231
|
+
const externalSaleNumber = next.external_sale_number;
|
|
3232
|
+
if (Number(next.is_draft_order || 0) === 1 && next.order_id !== void 0 && externalSaleNumber !== void 0 && String(next.order_id) === String(externalSaleNumber)) {
|
|
3233
|
+
delete next.order_id;
|
|
3234
|
+
}
|
|
3235
|
+
return next;
|
|
3236
|
+
}
|
|
2697
3237
|
getDeviceTaskPlugin() {
|
|
2698
3238
|
var _a, _b;
|
|
2699
3239
|
return ((_b = (_a = this.app) == null ? void 0 : _a.getPlugin) == null ? void 0 : _b.call(_a, "deviceTask")) || null;
|
|
@@ -3214,6 +3754,59 @@ var Server = class {
|
|
|
3214
3754
|
};
|
|
3215
3755
|
}
|
|
3216
3756
|
}
|
|
3757
|
+
async handleOrderDraftSubmit(params) {
|
|
3758
|
+
var _a, _b, _c;
|
|
3759
|
+
const { data, title } = params;
|
|
3760
|
+
this.logInfo(`${title}: 开始处理`, {
|
|
3761
|
+
order_id: data == null ? void 0 : data.order_id,
|
|
3762
|
+
external_sale_number: data == null ? void 0 : data.external_sale_number,
|
|
3763
|
+
order_number: data == null ? void 0 : data.order_number
|
|
3764
|
+
});
|
|
3765
|
+
const normalizedData = await this.normalizeCheckoutSubmitData(data, title);
|
|
3766
|
+
const createdAt = normalizedData.created_at || normalizedData.create_date || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
|
|
3767
|
+
const draftOrder = {
|
|
3768
|
+
...normalizedData,
|
|
3769
|
+
external_sale_number: normalizedData.external_sale_number || `LOCAL_DRAFT_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
|
|
3770
|
+
created_at: createdAt,
|
|
3771
|
+
schedule_date: normalizedData.schedule_date || createdAt,
|
|
3772
|
+
need_sync: 0,
|
|
3773
|
+
is_draft_order: 1
|
|
3774
|
+
};
|
|
3775
|
+
if (!this.order || typeof this.order.upsertLocalDraftOrders !== "function") {
|
|
3776
|
+
this.logError(`${title}: Order 模块不支持本地草稿写入`);
|
|
3777
|
+
return {
|
|
3778
|
+
code: 500,
|
|
3779
|
+
status: false,
|
|
3780
|
+
message: "Order 模块不支持本地草稿写入",
|
|
3781
|
+
data: null
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
try {
|
|
3785
|
+
await this.order.upsertLocalDraftOrders([draftOrder]);
|
|
3786
|
+
this.logInfo(`${title}: 草稿订单已写入本地`, {
|
|
3787
|
+
order_id: draftOrder.order_id,
|
|
3788
|
+
external_sale_number: draftOrder.external_sale_number
|
|
3789
|
+
});
|
|
3790
|
+
return {
|
|
3791
|
+
code: 200,
|
|
3792
|
+
status: true,
|
|
3793
|
+
message: "",
|
|
3794
|
+
data: {
|
|
3795
|
+
...draftOrder,
|
|
3796
|
+
amount_gap: (_a = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _a.amount_gap,
|
|
3797
|
+
expect_amount: (_b = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _b.expect_amount,
|
|
3798
|
+
total_amount: (_c = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _c.total_amount,
|
|
3799
|
+
payment_status: draftOrder == null ? void 0 : draftOrder.payment_status
|
|
3800
|
+
}
|
|
3801
|
+
};
|
|
3802
|
+
} catch (error) {
|
|
3803
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3804
|
+
this.logError(`${title}: 写入本地草稿订单失败`, {
|
|
3805
|
+
error: errorMessage
|
|
3806
|
+
});
|
|
3807
|
+
return { code: 500, status: false, message: errorMessage, data: null };
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3217
3810
|
async handlePendingSyncCheckoutOrder(params) {
|
|
3218
3811
|
var _a, _b, _c, _d;
|
|
3219
3812
|
const { backendPath, data, title, reason } = params;
|
|
@@ -3289,7 +3882,8 @@ var Server = class {
|
|
|
3289
3882
|
return null;
|
|
3290
3883
|
const pendingOrder = {
|
|
3291
3884
|
...data,
|
|
3292
|
-
need_sync: 1
|
|
3885
|
+
need_sync: 1,
|
|
3886
|
+
is_draft_order: 0
|
|
3293
3887
|
};
|
|
3294
3888
|
const productMap = await this.buildSmallTicketProductMap(pendingOrder);
|
|
3295
3889
|
const orderWithProductTitles = this.withPendingSyncProductTitles(
|
|
@@ -3342,7 +3936,7 @@ var Server = class {
|
|
|
3342
3936
|
return 0;
|
|
3343
3937
|
return payments.reduce((sum, payment) => {
|
|
3344
3938
|
const status = String((payment == null ? void 0 : payment.status) || "").toLowerCase();
|
|
3345
|
-
if (status
|
|
3939
|
+
if (status !== "paid")
|
|
3346
3940
|
return sum;
|
|
3347
3941
|
return sum + this.toAmountNumber((payment == null ? void 0 : payment.amount) ?? (payment == null ? void 0 : payment.origin_amount));
|
|
3348
3942
|
}, 0);
|
|
@@ -3909,9 +4503,11 @@ var Server = class {
|
|
|
3909
4503
|
return value === void 0 ? void 0 : String(value);
|
|
3910
4504
|
}
|
|
3911
4505
|
buildCheckoutSyncSuccessPatch(fresh) {
|
|
4506
|
+
const patch = {
|
|
4507
|
+
is_draft_order: 0
|
|
4508
|
+
};
|
|
3912
4509
|
if (!fresh)
|
|
3913
|
-
return
|
|
3914
|
-
const patch = {};
|
|
4510
|
+
return patch;
|
|
3915
4511
|
if (fresh.order_id !== void 0 && fresh.order_id !== null)
|
|
3916
4512
|
patch.order_id = fresh.order_id;
|
|
3917
4513
|
if (fresh.order_number !== void 0 && fresh.order_number !== null) {
|