Require review before Tahesab wallet sync and harden accounting admin UX.

Single-customer and row sync preview balances with documents before overwrite/keep; bulk sync keeps confirm. Also ship Zarin wallet sync actions, field help, and get_user cache improvements.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-30 21:18:26 +03:30
co-authored by Cursor
parent 04cc03fe25
commit 1c4b2d4435
60 changed files with 2464 additions and 552 deletions
+97 -1
View File
@@ -89,6 +89,19 @@ export interface TahesabOnlyCustomer {
tel: string
gid: number | null
group: string
has_phone?: boolean
gold?: number | null
cash?: number | null
}
export interface AccountingPhoneMatch {
code: number
name: string
tel: string
panel_id: number
panel_name: string
panel_code?: string | null
error?: string
}
export interface CustomerSyncStatus {
@@ -97,6 +110,13 @@ export interface CustomerSyncStatus {
panel_only: number
tahesab_total: number
tahesab_only_count: number
tahesab_with_phone_count?: number | null
tahesab_without_phone_count?: number | null
tahesab_importable_count?: number | null
phone_match_count?: number | null
phone_conflict_count?: number | null
phone_matches?: AccountingPhoneMatch[]
phone_conflicts?: AccountingPhoneMatch[]
panel_only_list: {
data: PanelOnlyCustomer[]
current_page: number
@@ -115,6 +135,7 @@ export const getCustomerSyncStatus = async (params?: {
search?: string
page?: number
tahesab_page?: number
include_tahesab?: number | boolean
}) => await useAxios.get<CustomerSyncStatus>('/admin/tahesab/customer-sync/status', { params })
export interface SyncPanelResult {
@@ -132,6 +153,33 @@ export const importFromTahesab = async (customers: TahesabOnlyCustomer[]) =>
customers,
})
export const linkTahesabMatchingPhones = async () =>
await useAxios.post<{
ok: boolean
linked: number
conflicts: number
message: string
linked_rows: AccountingPhoneMatch[]
conflict_rows: AccountingPhoneMatch[]
}>('/admin/tahesab/customer-sync/link-by-phone')
export const fetchTahesabMandeByCodes = async (codes: number[]) =>
await useAxios.post<{ ok: boolean; mandes: Record<string, { gold: number; cash: number }> }>(
'/admin/tahesab/mande-by-codes',
{ codes },
)
export interface TahesabPreviewDoc {
id: number
title?: string
gold?: number
cash?: number
amount?: number
type?: string
date?: string
created_at?: string | null
}
export interface TahesabWalletSyncResult {
ok: boolean
needs_decision?: boolean
@@ -146,6 +194,10 @@ export interface TahesabWalletSyncResult {
app_cash?: number
tahesab_gold?: number
tahesab_cash?: number
zarin_gold?: number
zarin_cash?: number
wallet_docs?: TahesabPreviewDoc[]
tahesab_docs?: TahesabPreviewDoc[]
message: string
}
}
@@ -153,7 +205,7 @@ export interface TahesabWalletSyncResult {
/** همگام‌سازی مانده یک مشتری با ته‌حساب */
export const syncCustomerWalletFromTahesab = async (
customerId: number,
opts?: { overwrite?: boolean; keep?: boolean; ask_if_conflict?: boolean }
opts?: { overwrite?: boolean; keep?: boolean; ask_if_conflict?: boolean; always_ask?: boolean }
) =>
await useAxios.post<TahesabWalletSyncResult>(
`/admin/customer/${customerId}/tahesab/sync-wallet`,
@@ -161,9 +213,16 @@ export const syncCustomerWalletFromTahesab = async (
overwrite: opts?.overwrite ?? false,
keep: opts?.keep ?? false,
ask_if_conflict: opts?.ask_if_conflict ?? true,
always_ask: opts?.always_ask ?? false,
}
)
export const previewCustomerWalletFromTahesab = async (customerId: number, code?: string | number) =>
await useAxios.post<TahesabWalletSyncResult>(
`/admin/customer/${customerId}/tahesab/preview-wallet`,
{ code },
)
export interface TahesabBulkWalletSyncChunk {
ok: boolean
message: string
@@ -200,3 +259,40 @@ export const syncAllWalletsFromTahesabChunk = async (params?: {
limit: params?.limit ?? 20,
overwrite: params?.overwrite ?? false,
})
export interface TahesabWalletLinkedRow {
id: number
name: string
mobile: string
moshtari_code: number | null
app_gold: number
app_cash: number
tahesab_gold: number | null
tahesab_cash: number | null
gold_delta?: number | null
rial_delta?: number | null
status: 'same' | 'conflict' | 'ready' | 'missing'
message: string
}
export interface TahesabWalletLinkedList {
ok: boolean
total: number
page: number
per_page: number
last_page: number
rows: TahesabWalletLinkedRow[]
}
export const getTahesabWalletLinkedList = async (params?: {
search?: string
page?: number
per_page?: number
}) =>
await useAxios.get<TahesabWalletLinkedList>('/admin/tahesab/wallet-sync/list', {
params: {
search: params?.search || undefined,
page: params?.page ?? 1,
per_page: params?.per_page ?? 20,
},
})