diff --git a/src/api/admin-agent-settlement.ts b/src/api/admin-agent-settlement.ts
index 601333e..64b00ac 100644
--- a/src/api/admin-agent-settlement.ts
+++ b/src/api/admin-agent-settlement.ts
@@ -102,8 +102,10 @@ export async function postSettlementPeriod(body: {
export type SettlementPeriodOpenHints = {
suggested_start: string;
suggested_end: string;
+ settlement_timezone: string;
occupied_period_dates: string[];
pending_activity_dates: string[];
+ orphan_activity_dates?: string[];
unpaid_bill_dates: string[];
};
diff --git a/src/components/admin/admin-date-range-field.tsx b/src/components/admin/admin-date-range-field.tsx
index 7c8a939..2bcbce3 100644
--- a/src/components/admin/admin-date-range-field.tsx
+++ b/src/components/admin/admin-date-range-field.tsx
@@ -19,6 +19,8 @@ export type AdminDateRangeCalendarMarkers = {
occupiedPeriod?: string[];
/** 本地日历 `yyyy-MM-dd` */
pendingActivity?: string[];
+ /** 本地日历 `yyyy-MM-dd` — 已关账账期内仍有未归属流水 */
+ orphanActivity?: string[];
/** 本地日历 `yyyy-MM-dd` — 已有账期内的未结清日 */
unpaidBill?: string[];
};
@@ -113,6 +115,13 @@ export function AdminDateRangeField({
.filter((d): d is Date => d instanceof Date),
[calendarMarkers?.unpaidBill],
);
+ const orphanActivityDates = React.useMemo(
+ () =>
+ (calendarMarkers?.orphanActivity ?? [])
+ .map((ymd) => parseYmd(ymd))
+ .filter((d): d is Date => d instanceof Date),
+ [calendarMarkers?.orphanActivity],
+ );
return (
@@ -166,6 +175,7 @@ export function AdminDateRangeField({
modifiers={{
occupiedPeriod: occupiedPeriodDates,
pendingActivity: pendingActivityDates,
+ orphanActivity: orphanActivityDates,
unpaidBill: unpaidBillDates,
}}
modifiersClassNames={{
@@ -173,6 +183,8 @@ export function AdminDateRangeField({
"[&>button]:cursor-not-allowed [&>button]:bg-muted/80 [&>button]:text-muted-foreground [&>button]:line-through [&>button]:opacity-70",
pendingActivity:
"[&:not([data-disabled=true])>button]:relative [&:not([data-disabled=true])>button]:after:absolute [&:not([data-disabled=true])>button]:after:bottom-0.5 [&:not([data-disabled=true])>button]:after:left-1/2 [&:not([data-disabled=true])>button]:after:size-1 [&:not([data-disabled=true])>button]:after:-translate-x-1/2 [&:not([data-disabled=true])>button]:after:rounded-full [&:not([data-disabled=true])>button]:after:bg-amber-500 [&:not([data-disabled=true])>button]:after:content-['']",
+ orphanActivity:
+ "[&>button]:relative [&>button]:after:absolute [&>button]:after:bottom-0.5 [&>button]:after:left-1/2 [&>button]:after:size-1.5 [&>button]:after:-translate-x-1/2 [&>button]:after:rounded-full [&>button]:after:bg-violet-600 [&>button]:after:content-['']",
unpaidBill:
"[&>button]:relative [&>button]:before:absolute [&>button]:before:top-0.5 [&>button]:before:right-0.5 [&>button]:before:size-1.5 [&>button]:before:rounded-full [&>button]:before:bg-rose-500 [&>button]:before:content-['']",
}}
diff --git a/src/i18n/locales/en/agents.json b/src/i18n/locales/en/agents.json
index 116cda1..16fb33c 100644
--- a/src/i18n/locales/en/agents.json
+++ b/src/i18n/locales/en/agents.json
@@ -295,11 +295,13 @@
"manageTitle": "Period management",
"markerOccupied": "Occupied period",
"markerPending": "Pending turnover",
+ "markerOrphan": "Closed-period orphan turnover",
"markerUnpaid": "Unsettled period",
"open": "Open period",
- "openDesc": "Select the start and end dates; gray strikethrough dates are occupied, amber dots indicate pending turnover, red dots at top-right indicate unsettled periods.",
+ "openDesc": "Select the start and end dates; gray strikethrough dates are occupied, amber dots indicate pending turnover, violet dots indicate closed-period orphan turnover, red dots at top-right indicate unsettled periods.",
"openFailed": "Failed to open period",
"openHint": "Local dates ({{tz}})",
+ "timezoneHint": "Period dates are calculated in site timezone {{tz}}.",
"openWithPreset": "Apply quick preset",
"opened": "Period opened",
"overlapsOccupied": "The selected range overlaps with existing periods. Please avoid dates with gray strikethrough lines.",
diff --git a/src/i18n/locales/en/config.json b/src/i18n/locales/en/config.json
index 111096c..70c76dc 100644
--- a/src/i18n/locales/en/config.json
+++ b/src/i18n/locales/en/config.json
@@ -131,6 +131,7 @@
"lotteryH5BaseUrl": "Lottery H5 base URL (optional)",
"name": "Site name",
"notes": "Notes",
+ "settlementTimezone": "Settlement timezone",
"ssoSecret": "SSO secret",
"status": "Status",
"walletApiKey": "Wallet API key",
@@ -161,6 +162,7 @@
"lotteryH5BaseUrl": "Enter H5 URL",
"name": "Enter site name",
"notes": "Enter notes",
+ "settlementTimezone": "Enter IANA timezone, for example Asia/Kathmandu",
"walletApiUrl": "Enter wallet API URL"
},
"rotateConfirm": "Rotate",
diff --git a/src/i18n/locales/en/draws.json b/src/i18n/locales/en/draws.json
index c2855e6..9e3cfca 100644
--- a/src/i18n/locales/en/draws.json
+++ b/src/i18n/locales/en/draws.json
@@ -20,6 +20,7 @@
"failed": "Create failed"
},
"drawNo": "Draw no.",
+ "provider": "Provider",
"status": "Status",
"startTime": "Start time",
"closeTime": "Close time",
diff --git a/src/i18n/locales/en/settlementCenter.json b/src/i18n/locales/en/settlementCenter.json
index 5fb0a9e..bf87aff 100644
--- a/src/i18n/locales/en/settlementCenter.json
+++ b/src/i18n/locales/en/settlementCenter.json
@@ -14,7 +14,7 @@
"closeDialogTitle": "Close period",
"closeDialogDesc": "Summarize {{range}} and generate bills.",
"closeDialogShare": "{{count}} ledger entries",
- "closeDialogUnsettled": "{{count}} tickets still unsettled",
+ "closeDialogUnsettled": "{{count}} ticket(s) still unsettled. Finish draw settlement before closing.",
"closeDialogIrreversible": "Cannot undo. Use adjustments or reversals to fix errors.",
"closeDialogConfirm": "Close period",
"closeDialogEmpty": "No share ledger this period; closing will not generate bills."
diff --git a/src/i18n/locales/en/tickets.json b/src/i18n/locales/en/tickets.json
index 92bb4ec..4600dd6 100644
--- a/src/i18n/locales/en/tickets.json
+++ b/src/i18n/locales/en/tickets.json
@@ -19,6 +19,8 @@
"player": "Player",
"orderNo": "Order no.",
"drawNo": "Draw no.",
+ "provider": "Provider",
+ "allProviders": "All providers",
"playCode": "Play",
"number": "Number",
"betAmount": "Bet amount",
diff --git a/src/i18n/locales/ne/agents.json b/src/i18n/locales/ne/agents.json
index 65018ec..d69d4a9 100644
--- a/src/i18n/locales/ne/agents.json
+++ b/src/i18n/locales/ne/agents.json
@@ -311,11 +311,13 @@
"closed": "अवधि बन्द भयो, बिल सिर्जना भयो",
"closeFailed": "अवधि बन्द गर्न असफल",
"hintsFailed": "खोल्ने सुझाव लोड गर्न असफल",
- "openDesc": "सुरु र अन्त्य मिति चयन गर्नुहोस्; खैरो स्ट्राइकथ्रु भएका मितिहरू अधिकृत अवधि हुन्, एम्बर बिन्दुहरू पेन्डिङ कारोबार हुन्, माथि-दायाँ रातो बिन्दुहरू नबुझिएको अवधि हुन्।",
+ "openDesc": "सुरु र अन्त्य मिति चयन गर्नुहोस्; खैरो स्ट्राइकथ्रु भएका मितिहरू अधिकृत अवधि हुन्, एम्बर बिन्दुहरू पेन्डिङ कारोबार हुन्, बैजनी बिन्दुहरू बन्द अवधिमा छुटेका कारोबार हुन्, माथि-दायाँ रातो बिन्दुहरू नबुझिएको अवधि हुन्।",
+ "timezoneHint": "अवधि मिति साइट समयक्षेत्र {{tz}} अनुसार गणना हुन्छ।",
"rangeLabel": "अवधि दायरा",
"rangeHint": "पहिले सुरु मिति चयन गर्नुहोस्, त्यसपछि अन्त्य मिति; एकल-दिन अवधिको लागि एउटै मिति दुई पटक क्लिक गर्नुहोस्।",
"markerOccupied": "अधिकृत अवधि",
"markerPending": "पेन्डिङ कारोबार",
+ "markerOrphan": "बन्द अवधिमा छुटेको कारोबार",
"markerUnpaid": "नबुझिएको अवधि",
"overlapsOccupied": "चयन गरिएको दायरा अवस्थित अवधिसँग ओभरल्याप हुन्छ। कृपया खैरो स्ट्राइकथ्रु भएका मितिहरू नछान्नुहोस्।"
},
diff --git a/src/i18n/locales/ne/config.json b/src/i18n/locales/ne/config.json
index fabb0ba..a50769d 100644
--- a/src/i18n/locales/ne/config.json
+++ b/src/i18n/locales/ne/config.json
@@ -131,6 +131,7 @@
"lotteryH5BaseUrl": "लटरी H5 आधार URL (वैकल्पिक)",
"name": "साइट नाम",
"notes": "टिप्पणी",
+ "settlementTimezone": "सेटलमेन्ट समयक्षेत्र",
"ssoSecret": "SSO गोप्य",
"status": "स्थिति",
"walletApiKey": "वालेट API कुञ्जी",
@@ -159,6 +160,7 @@
"lotteryH5BaseUrl": "H5 ठेगाना प्रविष्ट गर्नुहोस्",
"name": "साइट नाम प्रविष्ट गर्नुहोस्",
"notes": "टिप्पणी प्रविष्ट गर्नुहोस्",
+ "settlementTimezone": "IANA समयक्षेत्र प्रविष्ट गर्नुहोस्, जस्तै Asia/Kathmandu",
"walletApiUrl": "वालेट API ठेगाना प्रविष्ट गर्नुहोस्"
},
"rotateConfirm": "पुष्टि",
diff --git a/src/i18n/locales/ne/draws.json b/src/i18n/locales/ne/draws.json
index 4704bf8..787da23 100644
--- a/src/i18n/locales/ne/draws.json
+++ b/src/i18n/locales/ne/draws.json
@@ -100,6 +100,7 @@
"drawDetail": "ड्रअ विवरण",
"drawNo": "ड्रअ नं.",
"drawTime": "ड्रअ समय",
+ "provider": "Provider",
"editDraw": {
"action": "सम्पादन",
"description": "ड्रअ {{drawNo}} · स्थानीय समयक्षेत्र {{tz}} मा सम्पादन",
diff --git a/src/i18n/locales/ne/settlementCenter.json b/src/i18n/locales/ne/settlementCenter.json
index be24b81..0eeba69 100644
--- a/src/i18n/locales/ne/settlementCenter.json
+++ b/src/i18n/locales/ne/settlementCenter.json
@@ -14,7 +14,7 @@
"closeDialogTitle": "अवधि बन्द गर्नुहोस्",
"closeDialogDesc": "{{range}} भित्रको लेजर संक्षेप गरी बिल सिर्जना गर्नुहोस्।",
"closeDialogShare": "{{count}} लेजर प्रविष्टिहरू",
- "closeDialogUnsettled": "{{count}} टिकटहरू अझै नसेटल",
+ "closeDialogUnsettled": "{{count}} टिकटहरू अझै नसेटल छन्। बन्द गर्नु अघि ड्र सेटलमेन्ट पूरा गर्नुहोस्।",
"closeDialogIrreversible": "पूर्ववत गर्न सकिँदैन। त्रुटि सच्याउन समायोजन वा रिभर्सल प्रयोग गर्नुहोस्।",
"closeDialogConfirm": "अवधि बन्द गर्नुहोस्",
"closeDialogEmpty": "यस अवधिमा शेयर लेजर छैन; बन्द गर्दा बिल सिर्जना हुँदैन।"
diff --git a/src/i18n/locales/ne/tickets.json b/src/i18n/locales/ne/tickets.json
index 194f0a9..6a48269 100644
--- a/src/i18n/locales/ne/tickets.json
+++ b/src/i18n/locales/ne/tickets.json
@@ -13,6 +13,8 @@
"detailLoadFailed": "टिकट विवरण लोड असफल",
"detailTitle": "टिकट विवरण",
"drawNo": "ड्रअ नं.",
+ "provider": "Provider",
+ "allProviders": "सबै provider",
"drawNoOptional": "ड्रअ नम्बर (वैकल्पिक)",
"drawNoPlaceholder": "जस्तै 20260520-001",
"failReason": "असफल कारण",
diff --git a/src/i18n/locales/zh/agents.json b/src/i18n/locales/zh/agents.json
index d8fff97..e69e305 100644
--- a/src/i18n/locales/zh/agents.json
+++ b/src/i18n/locales/zh/agents.json
@@ -326,11 +326,13 @@
"closeFailed": "关账失败",
"datesRequired": "请填写账期起止日期",
"invalidRange": "结束日期不能早于开始日期",
- "openDesc": "选择账期起止日期;灰色删除线为已有账期不可再开,琥珀点为待入账,右上角红点为未结清。",
+ "openDesc": "选择账期起止日期;灰色删除线为已有账期不可再开,琥珀点为待入账,紫点为已关账漏账,右上角红点为未结清。",
+ "timezoneHint": "账期日期按站点时区 {{tz}} 计算。",
"rangeLabel": "账期范围",
"rangeHint": "先选开始日期,再选结束日期;单日账期可点同一天两次。",
"markerOccupied": "已有账期",
"markerPending": "待入账流水",
+ "markerOrphan": "已关账漏账",
"markerUnpaid": "未结清账期",
"overlapsOccupied": "所选范围与已有账期重叠,请避开灰色删除线的日期。",
"hintsFailed": "无法加载开账建议"
diff --git a/src/i18n/locales/zh/config.json b/src/i18n/locales/zh/config.json
index bc9b559..1ec901b 100644
--- a/src/i18n/locales/zh/config.json
+++ b/src/i18n/locales/zh/config.json
@@ -127,6 +127,7 @@
"adminPassword": "初始密码",
"adminEmail": "邮箱(可选)",
"currency": "默认币种",
+ "settlementTimezone": "结算时区",
"status": "状态",
"walletApiUrl": "主站钱包根 URL",
"lotteryH5BaseUrl": "彩票 H5 基址(可选)",
@@ -143,6 +144,7 @@
"adminPassword": "至少 6 位",
"adminEmail": "请输入邮箱",
"currency": "请输入币种代码,如 NPR",
+ "settlementTimezone": "例如 Asia/Kathmandu",
"walletApiUrl": "请输入钱包接口地址",
"lotteryH5BaseUrl": "请输入 H5 地址",
"iframeOrigins": "请输入允许的来源地址,如 https://www.example.com",
diff --git a/src/i18n/locales/zh/draws.json b/src/i18n/locales/zh/draws.json
index 8054cec..47c5ceb 100644
--- a/src/i18n/locales/zh/draws.json
+++ b/src/i18n/locales/zh/draws.json
@@ -20,6 +20,7 @@
"failed": "创建失败"
},
"drawNo": "期号",
+ "provider": "开注商",
"status": "状态",
"startTime": "开始时间",
"closeTime": "封盘时间",
diff --git a/src/i18n/locales/zh/settlementCenter.json b/src/i18n/locales/zh/settlementCenter.json
index 0ceab9c..89aef6c 100644
--- a/src/i18n/locales/zh/settlementCenter.json
+++ b/src/i18n/locales/zh/settlementCenter.json
@@ -15,7 +15,7 @@
"closeDialogDesc": "将汇总 {{range}} 内的流水并生成账单。",
"closeDialogShare": "流水 {{count}} 笔",
"closeDialogEmpty": "本期暂无占成流水,关账后不会生成账单。",
- "closeDialogUnsettled": "仍有 {{count}} 笔注单未结算",
+ "closeDialogUnsettled": "仍有 {{count}} 笔注单未结算,需先完成开奖结算后才能关账",
"closeDialogIrreversible": "关账后不可撤销,差错请通过调账或冲正处理。",
"closeDialogConfirm": "确认关账"
},
@@ -52,6 +52,7 @@
"periods": "账期",
"pendingWorkbench": "待处理",
"allBills": "全部账单",
+ "billWorkbench": "账单处理",
"bills": "账单",
"operations": "收付与调账",
"aria": "账期视图",
diff --git a/src/i18n/locales/zh/tickets.json b/src/i18n/locales/zh/tickets.json
index 2588531..2b223fa 100644
--- a/src/i18n/locales/zh/tickets.json
+++ b/src/i18n/locales/zh/tickets.json
@@ -19,6 +19,8 @@
"player": "玩家",
"orderNo": "订单号",
"drawNo": "期号",
+ "provider": "开注商",
+ "allProviders": "全部开注商",
"playCode": "玩法",
"number": "号码",
"betAmount": "下注",
diff --git a/src/lib/agent-settlement-period-range.ts b/src/lib/agent-settlement-period-range.ts
index c483f9a..7c38792 100644
--- a/src/lib/agent-settlement-period-range.ts
+++ b/src/lib/agent-settlement-period-range.ts
@@ -73,7 +73,10 @@ export function localDateRangeToUtcPeriodBounds(
}
/** UTC 账期时刻 → 本地日历 `YYYY-MM-DD`(列表展示) */
-export function utcPeriodInstantToLocalYmd(iso: string | null | undefined): string {
+export function utcPeriodInstantToLocalYmd(
+ iso: string | null | undefined,
+ timeZone?: string | null,
+): string {
if (iso == null || iso === "") {
return "—";
}
@@ -81,6 +84,24 @@ export function utcPeriodInstantToLocalYmd(iso: string | null | undefined): stri
if (Number.isNaN(ms)) {
return iso.slice(0, 10);
}
+ if (timeZone && typeof Intl !== "undefined") {
+ try {
+ const parts = new Intl.DateTimeFormat("en-US", {
+ timeZone,
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ }).formatToParts(new Date(ms));
+ const y = parts.find((part) => part.type === "year")?.value;
+ const m = parts.find((part) => part.type === "month")?.value;
+ const d = parts.find((part) => part.type === "day")?.value;
+ if (y && m && d) {
+ return `${y}-${m}-${d}`;
+ }
+ } catch {
+ // Fall back to browser-local formatting below.
+ }
+ }
return toDateYmdValue(new Date(ms));
}
@@ -107,9 +128,10 @@ export function utcStorageDateToLocalFormYmd(utcYmd: string): string {
export function formatSettlementPeriodSpan(
periodStart: string | undefined,
periodEnd: string | undefined,
+ timeZone?: string | null,
): string {
- const start = utcPeriodInstantToLocalYmd(periodStart);
- const end = utcPeriodInstantToLocalYmd(periodEnd);
+ const start = utcPeriodInstantToLocalYmd(periodStart, timeZone);
+ const end = utcPeriodInstantToLocalYmd(periodEnd, timeZone);
return `${start} ~ ${end}`;
}
diff --git a/src/modules/draws/draw-publish-dialog.tsx b/src/modules/draws/draw-publish-dialog.tsx
index 13bd630..786f3e0 100644
--- a/src/modules/draws/draw-publish-dialog.tsx
+++ b/src/modules/draws/draw-publish-dialog.tsx
@@ -37,6 +37,7 @@ export function DrawPublishDialog({
{t("publishTitle")}
{batch ? ` · v${batch.result_version}` : ""}
+ {batch?.provider_name || batch?.provider_code ? ` · ${batch.provider_name || batch.provider_code}` : ""}
@@ -58,4 +59,4 @@ export function DrawPublishDialog({
);
-}
\ No newline at end of file
+}
diff --git a/src/modules/draws/draw-publish-panel.tsx b/src/modules/draws/draw-publish-panel.tsx
index cd00b6b..4a79c25 100644
--- a/src/modules/draws/draw-publish-panel.tsx
+++ b/src/modules/draws/draw-publish-panel.tsx
@@ -82,6 +82,12 @@ export function DrawPublishPanel({
return (
+
+ {t("provider")}:
+
+ {batch.provider_name || batch.provider_code || "—"}
+
+
@@ -144,4 +150,4 @@ export function DrawPublishPanel({
);
-}
\ No newline at end of file
+}
diff --git a/src/modules/draws/draw-results-console.tsx b/src/modules/draws/draw-results-console.tsx
index af3dcd3..68b1522 100644
--- a/src/modules/draws/draw-results-console.tsx
+++ b/src/modules/draws/draw-results-console.tsx
@@ -72,7 +72,7 @@ export function DrawResultsConsole({ drawId }: { drawId: string }) {
) : (
published.map((batch) => (
-
+
))
)}
@@ -85,7 +85,9 @@ function BatchTable({ batch }: { batch: AdminDrawBatchRow }) {
return (
- {t("version", { version: batch.result_version })}
+
+ {batch.provider_name || batch.provider_code || t("provider")} · {t("version", { version: batch.result_version })}
+
{formatDt(batch.confirmed_at)}
diff --git a/src/modules/draws/draw-review-console.tsx b/src/modules/draws/draw-review-console.tsx
index e364f99..f3eef6e 100644
--- a/src/modules/draws/draw-review-console.tsx
+++ b/src/modules/draws/draw-review-console.tsx
@@ -12,9 +12,17 @@ import {
getAdminDrawResultBatches,
postAdminCreateManualResultBatch,
} from "@/api/admin-draws";
+import { getAdminBetProviders } from "@/api/admin-bet-providers";
import { AdminRowActionsMenu } from "@/components/admin/admin-row-actions-menu";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
import { AdminNoResourceState } from "@/components/admin/admin-no-resource-state";
import { AdminLoadingState } from "@/components/admin/admin-loading-state";
import {
@@ -31,6 +39,7 @@ import { adminHasAnyPermission } from "@/lib/admin-permissions";
import { useAdminProfile } from "@/stores/admin-session";
import { LotteryApiBizError } from "@/types/api/errors";
import type { AdminDrawBatchRow, AdminDrawBatchesData } from "@/types/api/admin-draws";
+import type { AdminBetProviderRow } from "@/types/api/admin-bet-provider";
import { DrawPublishDialog } from "@/modules/draws/draw-publish-dialog";
import { useDrawDetail } from "@/modules/draws/draw-detail-context";
@@ -69,6 +78,9 @@ export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactEl
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
const [savingManual, setSavingManual] = useState(false);
+ const [providersLoading, setProvidersLoading] = useState(false);
+ const [betProviders, setBetProviders] = useState([]);
+ const [manualProviderCode, setManualProviderCode] = useState("");
const [discardingBatchId, setDiscardingBatchId] = useState(null);
const [manualOpen, setManualOpen] = useState(false);
const [publishBatch, setPublishBatch] = useState(null);
@@ -97,6 +109,19 @@ export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactEl
void load();
}, [load]);
+ useAsyncEffect(async () => {
+ setProvidersLoading(true);
+ try {
+ const res = await getAdminBetProviders();
+ setBetProviders(res.items);
+ setManualProviderCode((current) => current || res.items.find((item) => item.is_default)?.code || res.items[0]?.code || "");
+ } catch {
+ setBetProviders([]);
+ } finally {
+ setProvidersLoading(false);
+ }
+ }, []);
+
const pending = useMemo(() => data?.batches.filter((b) => b.status === "pending_review") ?? [], [data]);
function fillRandomManualNumbers(): void {
@@ -129,6 +154,7 @@ export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactEl
setSavingManual(true);
try {
const res = await postAdminCreateManualResultBatch(idNum, {
+ provider_code: manualProviderCode || undefined,
items: RESULT_SLOTS.map((slot, i) => ({
prize_type: slot.prize_type,
prize_index: slot.prize_index,
@@ -177,6 +203,7 @@ export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactEl
{t("version", { version: "" }).replace(" v", "").trim()}
+ {t("provider")}
{t("numberCount")}
{t("table.actions", { ns: "common" })}
@@ -185,6 +212,9 @@ export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactEl
{pending.map((b) => (
v{b.result_version}
+
+ {b.provider_name || b.provider_code || "—"}
+
{b.items.length}
{canManageDraw ? (
@@ -241,6 +271,28 @@ export function DrawReviewConsole({ drawId }: { drawId: string }): React.ReactEl
{manualOpen ? (
+
+ {t("provider")}
+
+
{RESULT_SLOTS.map((slot, i) => (
);
-}
\ No newline at end of file
+}
diff --git a/src/modules/integration/integration-sites-console.tsx b/src/modules/integration/integration-sites-console.tsx
index 55e1954..e6228be 100644
--- a/src/modules/integration/integration-sites-console.tsx
+++ b/src/modules/integration/integration-sites-console.tsx
@@ -120,6 +120,7 @@ type FormState = {
admin_password: string;
admin_email: string;
currency_code: string;
+ settlement_timezone: string;
status: number;
wallet_api_url: string;
wallet_debit_path: string;
@@ -139,6 +140,7 @@ const EMPTY_FORM: FormState = {
admin_password: "",
admin_email: "",
currency_code: "NPR",
+ settlement_timezone: "UTC",
status: 1,
wallet_api_url: "",
wallet_debit_path: "/wallet/debit-for-lottery",
@@ -170,6 +172,7 @@ function rowToForm(row: AdminIntegrationSiteDetail): FormState {
admin_password: "",
admin_email: "",
currency_code: row.currency_code,
+ settlement_timezone: row.settlement_timezone || "UTC",
status: row.status,
wallet_api_url: row.wallet_api_url ?? "",
wallet_debit_path: row.wallet_debit_path ?? "/wallet/debit-for-lottery",
@@ -191,6 +194,7 @@ function formToPayload(
const base = {
name: form.name.trim(),
currency_code: form.currency_code.trim() || "NPR",
+ settlement_timezone: form.settlement_timezone.trim() || "UTC",
status: form.status,
wallet_api_url: form.wallet_api_url.trim() || null,
wallet_debit_path: form.wallet_debit_path.trim(),
@@ -795,7 +799,7 @@ export function IntegrationSitesConsole({
>
) : null}
-
+
updateForm("currency_code", e.target.value)}
/>
+
+
+ updateForm("settlement_timezone", e.target.value)}
+ />
+
) : null}
+
+
+ {
+ const next = (v ?? "all") as SettlementBillScopeFilter;
+ setDraft((d) => ({
+ ...d,
+ statusScope: next,
+ }));
+ setApplied((d) => ({
+ ...d,
+ statusScope: next,
+ }));
+ setPage(1);
+ }}
+ >
+
+ {() => statusScopeLabel(draft.statusScope)}
+
+
+ {statusScopeOptions.map((value) => (
+
+ {statusScopeLabel(value)}
+
+ ))}
+
+
+