"use client"; import { useMemo, useState, Suspense } from "react"; import { useSearchParams } from "next/navigation"; import { useMutation, useQuery } from "@tanstack/react-query"; import { toast } from "sonner"; import { accountingApi } from "@/lib/accounting-api"; import { useTenantId } from "@/hooks/useTenantId"; import { formatMoney } from "@/lib/utils"; import { BusinessDocsPage } from "@/components/accounting/BusinessDocsPage"; import { PageHeader, Button, LoadingState, ErrorState, Card, CardContent, CardHeader, CardTitle, Badge, Select, FormField, DataTable, EmptyState, } from "@/components/ds"; type ReportKind = "trial-balance" | "balance-sheet" | "income-statement"; const LABELS: Record = { "trial-balance": "تراز آزمایشی", "balance-sheet": "ترازنامه", "income-statement": "سود و زیان", }; const OPS_REPORTS: Record = { "cash-flow": { title: "جریان وجوه نقد", module: "reports", docType: "cash_flow" }, equity: { title: "تغییرات حقوق صاحبان سهام", module: "reports", docType: "equity" }, subsidiary: { title: "گزارش معین", module: "reports", docType: "subsidiary" }, detail: { title: "گزارش تفصیلی", module: "reports", docType: "detail" }, analytical: { title: "گزارش تحلیلی", module: "reports", docType: "analytical" }, }; const FIELD_LABELS: Record = { total_debit: "جمع بدهکار", total_credit: "جمع بستانکار", difference: "اختلاف", is_balanced: "متوازن", total_assets: "جمع دارایی‌ها", account_count: "تعداد حساب", total_revenue: "جمع درآمد", total_expense: "جمع هزینه", net: "خالص", }; function parseReportData(data: unknown): Record | null { if (!data) return null; if (typeof data === "string") { try { return JSON.parse(data) as Record; } catch { return { raw: data }; } } if (typeof data === "object" && !Array.isArray(data)) { return data as Record; } return { value: data }; } function formatCellValue(key: string, value: unknown): React.ReactNode { if (value === null || value === undefined) return "—"; if (typeof value === "boolean") return value ? "بله" : "خیر"; if (key.includes("total") || key.includes("difference") || key === "net" || key.includes("amount")) { return formatMoney(String(value)); } return String(value); } function EngineReports({ initialKind }: { initialKind?: string }) { const { tenantId } = useTenantId(); const [periodId, setPeriodId] = useState(""); const [result, setResult] = useState<{ kind: ReportKind; payload: { id: string; data: unknown } } | null>( null ); const periodsQ = useQuery({ queryKey: ["accounting", tenantId, "fiscal-periods"], queryFn: () => accountingApi.fiscal.listPeriods(tenantId!), enabled: !!tenantId, }); const runM = useMutation({ mutationFn: async (kind: ReportKind) => { if (!periodId) throw new Error("دوره مالی را انتخاب کنید"); if (kind === "trial-balance") { const payload = await accountingApi.reporting.trialBalance(tenantId!, periodId); return { kind, payload }; } if (kind === "balance-sheet") { const payload = await accountingApi.reporting.balanceSheet(tenantId!, periodId); return { kind, payload }; } const payload = await accountingApi.reporting.incomeStatement(tenantId!, periodId); return { kind, payload }; }, onSuccess: (data) => { setResult(data); toast.success("گزارش تولید شد"); }, onError: (e: Error) => toast.error(e.message), }); const exportM = useMutation({ mutationFn: (format: "json" | "csv") => accountingApi.reporting.export(tenantId!, result!.payload.id, format), onSuccess: (data) => { toast.success(`خروجی ${data.format} ثبت شد`); if (data.file_path) toast.message(data.file_path); if (result) { const blob = new Blob([JSON.stringify(result.payload, null, 2)], { type: "application/json", }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `report-${result.payload.id}.json`; a.click(); URL.revokeObjectURL(url); } }, onError: (e: Error) => toast.error(e.message), }); const parsed = useMemo( () => (result ? parseReportData(result.payload.data) : null), [result] ); const tableRows = useMemo(() => { if (!parsed) return []; return Object.entries(parsed).map(([key, value]) => ({ id: key, field: FIELD_LABELS[key] ?? key, value, rawKey: key, })); }, [parsed]); if (!tenantId || periodsQ.isLoading) return ; if (periodsQ.error) { return periodsQ.refetch()} />; } const highlight = initialKind === "trial-balance" || initialKind === "balance-sheet" || initialKind === "income-statement" ? (initialKind as ReportKind) : null; return (
{(Object.keys(LABELS) as ReportKind[]).map((kind) => ( ))}
{result ? ( {LABELS[result.kind]} زنده ID: {result.payload.id} {parsed && tableRows.length > 0 ? ( formatCellValue(String(r.rawKey), r.value), }, ]} rows={tableRows as unknown as Record[]} /> ) : ( )}
JSON خام
                {JSON.stringify(result.payload, null, 2)}
              
) : (

یک دوره انتخاب کنید و گزارش را اجرا کنید.

)}
); } function ReportsRouter() { const sp = useSearchParams(); const type = sp.get("type") || ""; const ops = OPS_REPORTS[type]; if (ops) { return ; } return ; } export default function ReportsPage() { return ( }> ); }