200 lines
6.5 KiB
TypeScript
200 lines
6.5 KiB
TypeScript
import type { PargarRecord } from '@/api/pargar'
|
|
|
|
export interface PargarTransactionRow {
|
|
docId?: string
|
|
date?: string
|
|
docType?: string
|
|
desc?: string
|
|
by?: string
|
|
bedGold?: number | string
|
|
besGold?: number | string
|
|
bedRial?: number | string
|
|
besRial?: number | string
|
|
remainGold?: number | string
|
|
remainRial?: number | string
|
|
}
|
|
|
|
export interface PargarParsedPayload {
|
|
accountId?: string
|
|
accountName?: string
|
|
transactions: PargarTransactionRow[]
|
|
}
|
|
|
|
const TYPE_LABELS: Record<string, string> = {
|
|
document: 'سند ورودی از پرگار',
|
|
order: 'سفارش',
|
|
mande: 'مانده حساب',
|
|
customer: 'ثبت مشتری',
|
|
wallet_cash: 'کیف ریالی',
|
|
wallet_gold: 'کیف طلا'
|
|
}
|
|
|
|
function parseNum(value: unknown): number {
|
|
if (value == null || value === '') return 0
|
|
const n = Number(String(value).replace('/', '.'))
|
|
return Number.isFinite(n) ? n : 0
|
|
}
|
|
|
|
export function pargarTypeLabel(type?: string | null): string {
|
|
if (!type) return '-'
|
|
return TYPE_LABELS[type] ?? type
|
|
}
|
|
|
|
export function parsePargarPayload(data?: string | null): PargarParsedPayload | null {
|
|
if (!data?.trim()) return null
|
|
try {
|
|
const raw = JSON.parse(data) as Record<string, unknown>
|
|
let transactions: PargarTransactionRow[] = []
|
|
if (Array.isArray(raw.transactions)) {
|
|
transactions = raw.transactions as PargarTransactionRow[]
|
|
} else if (raw.transaction && typeof raw.transaction === 'object') {
|
|
transactions = [raw.transaction as PargarTransactionRow]
|
|
}
|
|
|
|
return {
|
|
accountId: raw.accountId != null ? String(raw.accountId) : undefined,
|
|
accountName: raw.accountName != null ? String(raw.accountName) : undefined,
|
|
transactions
|
|
}
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function pargarCustomerLabel(record: PargarRecord): string {
|
|
if (record.customer?.name?.trim()) return record.customer.name.trim()
|
|
const payload = parsePargarPayload(record.data)
|
|
if (payload?.accountName?.trim()) return payload.accountName.trim()
|
|
if (record.pargar_ref) return `کد پرگار ${record.pargar_ref}`
|
|
return '-'
|
|
}
|
|
|
|
export function pargarAmountLabel(record: PargarRecord): string {
|
|
const metal = pargarMetalAmountLabel(record)
|
|
const rial = pargarRialAmountLabel(record)
|
|
if (metal !== '-' && rial !== '-') return `${metal} / ${rial}`
|
|
if (metal !== '-') return metal
|
|
if (rial !== '-') return rial
|
|
return '-'
|
|
}
|
|
|
|
function resolvePargarSummaryUnit(record: PargarRecord): 'rial' | 'gold' | null {
|
|
try {
|
|
const raw = record.data ? (JSON.parse(record.data) as { _summary?: { amount_unit?: string } }) : null
|
|
const unit = raw?._summary?.amount_unit
|
|
if (unit === 'rial' || unit === 'gold') return unit
|
|
} catch {
|
|
// ignore
|
|
}
|
|
if (record.type === 'wallet_cash') return 'rial'
|
|
if (record.type === 'wallet_gold' || record.type === 'mande') return 'gold'
|
|
return null
|
|
}
|
|
|
|
function maxGoldFromPayload(record: PargarRecord): number {
|
|
const payload = parsePargarPayload(record.data)
|
|
if (!payload?.transactions.length) return 0
|
|
let maxGold = 0
|
|
for (const tx of payload.transactions) {
|
|
maxGold = Math.max(maxGold, Math.abs(parseNum(tx.bedGold)), Math.abs(parseNum(tx.besGold)))
|
|
}
|
|
return maxGold
|
|
}
|
|
|
|
function maxRialFromPayload(record: PargarRecord): number {
|
|
const payload = parsePargarPayload(record.data)
|
|
if (!payload?.transactions.length) return 0
|
|
let maxRial = 0
|
|
for (const tx of payload.transactions) {
|
|
maxRial = Math.max(maxRial, Math.abs(parseNum(tx.bedRial)), Math.abs(parseNum(tx.besRial)))
|
|
}
|
|
return maxRial
|
|
}
|
|
|
|
/** ستون مقدار — فلز/گرم (نه ریال) */
|
|
export function pargarMetalAmountLabel(record: PargarRecord): string {
|
|
if (record.type === 'wallet_cash') return '-'
|
|
|
|
const unit = resolvePargarSummaryUnit(record)
|
|
if (record.amount != null && record.amount !== 0) {
|
|
if (unit === 'rial') {
|
|
// amount ریالی است؛ فلز را از تراکنشها بگیر
|
|
} else if (unit === 'gold' || unit == null) {
|
|
if (unit === 'gold' || record.type !== 'document') {
|
|
const n = Number(record.amount)
|
|
if (Number.isFinite(n) && Math.abs(n) >= 0.000001) {
|
|
return Math.abs(n - Math.round(n)) < 1e-9 ? String(Math.round(n)) : String(Number(n.toFixed(6)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const maxGold = maxGoldFromPayload(record)
|
|
if (maxGold >= 0.01) {
|
|
return Math.abs(maxGold - Math.round(maxGold)) < 1e-9
|
|
? String(Math.round(maxGold))
|
|
: String(Number(maxGold.toFixed(6)))
|
|
}
|
|
return '-'
|
|
}
|
|
|
|
/** ستون مبلغ ریالی */
|
|
export function pargarRialAmountLabel(record: PargarRecord): string {
|
|
const unit = resolvePargarSummaryUnit(record)
|
|
if (record.amount != null && record.amount !== 0) {
|
|
if (unit === 'rial' || record.type === 'wallet_cash') {
|
|
return Math.round(Number(record.amount)).toLocaleString('fa-IR')
|
|
}
|
|
}
|
|
|
|
const maxRial = maxRialFromPayload(record)
|
|
if (maxRial >= 1) return Math.round(maxRial).toLocaleString('fa-IR')
|
|
return '-'
|
|
}
|
|
|
|
export function pargarDescLabel(record: PargarRecord): string {
|
|
const desc = record.desc?.trim()
|
|
if (desc && desc !== 'دریافت اسناد از پرگار') return desc
|
|
|
|
try {
|
|
const raw = record.data ? JSON.parse(record.data) : null
|
|
if (raw?.wallet_applied === false && raw?.skip_reason === 'echo_outbound') {
|
|
return 'سند پرگار — از پنل ارسال شده (بدون اعمال مجدد)'
|
|
}
|
|
if (raw?.wallet_applied === true) {
|
|
return desc || 'اعمالشده روی کیف'
|
|
}
|
|
} catch {
|
|
// ignore
|
|
}
|
|
|
|
const payload = parsePargarPayload(record.data)
|
|
if (!payload?.transactions.length) return desc || '-'
|
|
|
|
const lines = payload.transactions
|
|
.map((tx) => tx.desc?.trim() || tx.docType?.trim() || '')
|
|
.filter(Boolean)
|
|
|
|
if (lines.length) {
|
|
const head = lines.slice(0, 2).join(' | ')
|
|
return lines.length > 2 ? `${head} (+${lines.length - 2} سند دیگر)` : head
|
|
}
|
|
|
|
return desc || '-'
|
|
}
|
|
|
|
export function formatTransactionAmount(tx: PargarTransactionRow): string {
|
|
const parts: string[] = []
|
|
const bedGold = parseNum(tx.bedGold)
|
|
const besGold = parseNum(tx.besGold)
|
|
const bedRial = parseNum(tx.bedRial)
|
|
const besRial = parseNum(tx.besRial)
|
|
|
|
if (bedGold >= 0.01) parts.push(`بدهکار طلا: ${bedGold}`)
|
|
if (besGold >= 0.01) parts.push(`بستانکار طلا: ${besGold}`)
|
|
if (bedRial >= 1) parts.push(`بدهکار ریال: ${bedRial.toLocaleString('fa-IR')}`)
|
|
if (besRial >= 1) parts.push(`بستانکار ریال: ${besRial.toLocaleString('fa-IR')}`)
|
|
|
|
return parts.length ? parts.join(' — ') : '-'
|
|
}
|