fix(funds): 结算幂等键复用与转账冲正按钮对齐 API
Some checks failed
lotteryadmin CI / build (push) Has been cancelled

- 账单收付/补差幂等键在首次操作时生成并复用至成功
- 冲正按钮仅当 API 返回 can_reverse=true 时展示
This commit is contained in:
2026-06-26 15:19:17 +08:00
parent 0d984b00f0
commit 2d80127b08
2 changed files with 26 additions and 3 deletions

View File

@@ -11,7 +11,7 @@ export type TransferOrderActionRow = {
};
export function canReverseTransferOrder(row: TransferOrderActionRow, canWriteWallet: boolean): boolean {
return canWriteWallet && (row.can_reverse ?? row.status === "pending_reconcile");
return canWriteWallet && row.can_reverse === true;
}
export function canCompleteTransferInCredit(row: TransferOrderActionRow, canWriteWallet: boolean): boolean {

View File

@@ -67,8 +67,23 @@ export function AgentBillDetail({
const [advancedOpen, setAdvancedOpen] = useState(false);
const confirmRef = useRef<HTMLDivElement>(null);
const paymentRef = useRef<HTMLDivElement>(null);
const paymentIdempotencyKeyRef = useRef<string | null>(null);
const adjustmentIdempotencyKeyRef = useRef<string | null>(null);
const { request: requestConfirm, ConfirmDialog, busy: confirmBusy } = useConfirmAction();
const createIdempotencyKey = useCallback((prefix: string): string => {
const random =
typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
? crypto.randomUUID()
: Math.random().toString(36).slice(2, 10);
return `${prefix}-${billId}-${Date.now()}-${random}`;
}, [billId]);
useEffect(() => {
paymentIdempotencyKeyRef.current = null;
adjustmentIdempotencyKeyRef.current = null;
}, [billId]);
const load = useCallback(async () => {
setLoading(true);
setLoadErr(null);
@@ -202,7 +217,10 @@ export function AgentBillDetail({
return;
}
const idempotencyKey = `pay-${billId}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
if (!paymentIdempotencyKeyRef.current) {
paymentIdempotencyKeyRef.current = createIdempotencyKey("pay");
}
const idempotencyKey = paymentIdempotencyKeyRef.current;
requestConfirm({
title: t("settlementBills.paymentConfirmTitle", { defaultValue: "确认登记收付?" }),
description: t("settlementBills.paymentConfirmDescription", {
@@ -218,6 +236,7 @@ export function AgentBillDetail({
proof: payProof.trim() || undefined,
idempotency_key: idempotencyKey,
});
paymentIdempotencyKeyRef.current = null;
await load();
await onUpdated?.();
toast.success(t("settlementBills.paid", { defaultValue: "已登记收付" }));
@@ -273,7 +292,10 @@ export function AgentBillDetail({
return;
}
const idempotencyKey = `adj-${billId}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
if (!adjustmentIdempotencyKeyRef.current) {
adjustmentIdempotencyKeyRef.current = createIdempotencyKey("adj");
}
const idempotencyKey = adjustmentIdempotencyKeyRef.current;
requestConfirm({
title: t("settlementBills.adjustmentConfirmTitle", { defaultValue: "确认创建补差/冲正单?" }),
description: t("settlementBills.adjustmentConfirmDescription", {
@@ -289,6 +311,7 @@ export function AgentBillDetail({
reason,
idempotency_key: idempotencyKey,
});
adjustmentIdempotencyKeyRef.current = null;
setAdjustAmount("");
setAdjustReason("");
toast.success(t("settlementBills.adjustmentCreated", { defaultValue: "已创建补差单" }));