feat(settlement): add idempotency keys to bill operations and enhance credit ledger filtering
Some checks failed
lotteryadmin CI / build (push) Has been cancelled

Added idempotency_key parameter to settlement bill payment and adjustment API calls to prevent duplicate transactions. Enhanced credit ledger panel with expanded reason filters including bet_hold_release, game_settlement_win/loss/reversal, and settlement_confirm/payout. Updated localization files to include new game_settlement_reversal labels across English, Nepali, and Chinese. Improved credit ledger reason
This commit is contained in:
2026-06-23 16:50:14 +08:00
parent c6119da9f8
commit ce38995546
8 changed files with 34 additions and 4 deletions

View File

@@ -300,7 +300,7 @@ export async function postSettlementBillConfirm(billId: number): Promise<{ bill_
export async function postSettlementBillPayment(
billId: number,
body: { amount: number; method?: string; proof?: string; remark?: string },
body: { amount: number; method?: string; proof?: string; remark?: string; idempotency_key?: string },
): Promise<{ bill: SettlementBillRow }> {
return adminRequest.post(`${A}/settlement-bills/${billId}/payments`, body);
}
@@ -324,7 +324,7 @@ export async function getAgentSettlementReport(params: {
export async function postSettlementBillAdjustment(
billId: number,
body: { amount: number; adjustment_type?: "adjustment" | "reversal"; reason?: string },
body: { amount: number; adjustment_type?: "adjustment" | "reversal"; reason?: string; idempotency_key?: string },
): Promise<{ adjustment_bill_id: number; bill: SettlementBillRow }> {
return adminRequest.post(`${A}/settlement-bills/${billId}/adjustments`, body);
}

View File

@@ -146,6 +146,7 @@
"payment_record": "Bill payment",
"bet_hold": "Bet hold",
"game_settlement": "Draw settlement",
"game_settlement_reversal": "Draw reversal",
"game_settlement_win": "Draw settlement credit",
"bet_hold_release": "Hold release",
"game_settlement_loss": "Draw settlement debit",

View File

@@ -146,6 +146,7 @@
"payment_record": "Bill payment",
"bet_hold": "Bet hold",
"game_settlement": "Draw settlement",
"game_settlement_reversal": "Draw reversal",
"game_settlement_win": "Draw settlement credit",
"bet_hold_release": "Hold release",
"game_settlement_loss": "Draw settlement debit",

View File

@@ -132,6 +132,7 @@
"bet_hold": "下注冻结",
"freezeAmount": "冻结 {{amount}}",
"game_settlement": "开奖结算",
"game_settlement_reversal": "开奖冲正",
"game_settlement_win": "开奖结算入账",
"bet_hold_release": "占用释放",
"game_settlement_loss": "开奖结算扣款",

View File

@@ -1011,7 +1011,7 @@ export function AgentsConsole(): React.ReactElement {
{canViewAgents && err ? <p className="px-1 text-sm text-destructive">{err}</p> : null}
{canViewAgents ? (
<div className="flex max-h-[calc(100dvh-14rem)] min-h-[28rem] flex-1 flex-col overflow-hidden rounded-2xl border border-border/70 bg-card shadow-sm lg:flex-row">
<div className="flex max-h-[calc(100dvh-14rem)] min-h-0 flex-1 flex-col overflow-hidden rounded-2xl border border-border/70 bg-card shadow-sm lg:flex-row">
{showAgentSidebar ? (
<AgentLineSidebar
siteLabel={selectedSiteLabel}

View File

@@ -182,6 +182,7 @@ export function AgentBillDetail({
return;
}
const idempotencyKey = `pay-${billId}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
requestConfirm({
title: t("settlementBills.paymentConfirmTitle", { defaultValue: "确认登记收付?" }),
description: t("settlementBills.paymentConfirmDescription", {
@@ -195,6 +196,7 @@ export function AgentBillDetail({
amount,
method: payMethod.trim() || undefined,
proof: payProof.trim() || undefined,
idempotency_key: idempotencyKey,
});
await load();
await onUpdated?.();
@@ -251,6 +253,7 @@ export function AgentBillDetail({
return;
}
const idempotencyKey = `adj-${billId}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
requestConfirm({
title: t("settlementBills.adjustmentConfirmTitle", { defaultValue: "确认创建补差/冲正单?" }),
description: t("settlementBills.adjustmentConfirmDescription", {
@@ -264,6 +267,7 @@ export function AgentBillDetail({
amount,
adjustment_type: amount < 0 ? "reversal" : "adjustment",
reason,
idempotency_key: idempotencyKey,
});
setAdjustAmount("");
setAdjustReason("");

View File

@@ -42,12 +42,17 @@ import { creditLedgerReasonLabel, settlementBillStatusLabel } from "@/modules/se
const REASON_FILTERS = [
"all",
"bet_hold",
"bet_hold_release",
"game_settlement",
"game_settlement_win",
"game_settlement_loss",
"game_settlement_reversal",
"settlement_confirm",
"settlement_payout",
"payment_record",
"adjustment",
"reversal",
"bad_debt",
"settlement_payout",
"share_ledger",
] as const;

View File

@@ -55,9 +55,27 @@ export function creditLedgerReasonLabel(
if (reason === "game_settlement") {
return t("creditLedger.reason.game_settlement", { defaultValue: "开奖结算" });
}
if (reason === "game_settlement_reversal") {
return t("creditLedger.reason.game_settlement_reversal", { defaultValue: "开奖冲正" });
}
if (reason === "bet_hold") {
return t("creditLedger.reason.bet_hold", { defaultValue: "下注冻结" });
}
if (reason === "bet_hold_release") {
return t("creditLedger.reason.bet_hold_release", { defaultValue: "占用释放" });
}
if (reason === "game_settlement_win") {
return t("creditLedger.reason.game_settlement_win", { defaultValue: "开奖结算入账" });
}
if (reason === "game_settlement_loss") {
return t("creditLedger.reason.game_settlement_loss", { defaultValue: "开奖结算扣款" });
}
if (reason === "settlement_confirm") {
return t("creditLedger.reason.settlement_confirm", { defaultValue: "账期结算确认" });
}
if (reason === "settlement_payout") {
return t("creditLedger.reason.settlement_payout", { defaultValue: "结算收付入账" });
}
const key = `creditLedger.reason.${reason}` as const;
return t(key, { defaultValue: reason });