Add FunZone sync for sales and purchases, voucher filters, and event-name support.

Manual sync buttons pull customer payments and owner payouts into treasury, invoices, and accounting vouchers; voucher page gains category, date, status, and search filters; supplier vouchers dedupe against treasury-backed entries.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Shayan Azadi
2026-07-06 22:09:08 +03:30
parent 4508be582a
commit f6b6e27294
24 changed files with 1258 additions and 90 deletions

View File

@@ -4,7 +4,9 @@ import { useStore } from '../../store/AppStore'
import { Card, StatCard } from '../../components/ui'
import { formatMoney, toFa } from '../../utils/format'
import { salesNavItems } from './salesNavigation'
import { salesSummary } from './salesUtils'
import { salesDocuments, salesSummary } from './salesUtils'
import { FunZoneSalesSyncBanner } from './FunZoneSalesSyncBanner'
import { isFunZoneSalesInvoice } from './funzoneSalesSync'
const processSteps = [
{ step: 1, label: 'پیش‌فاکتور', desc: 'صدور پیشنهاد قیمت برای مشتری', to: '/sales/proforma', icon: '📋' },
@@ -16,11 +18,16 @@ const processSteps = [
export function SalesProcess() {
const { data } = useStore()
const summary = useMemo(() => salesSummary(data), [data])
const funzoneSyncedCount = useMemo(
() => salesDocuments(data.invoices).filter(isFunZoneSalesInvoice).length,
[data.invoices],
)
const quickLinks = salesNavItems.filter((item) => item.to !== '/sales')
return (
<div className="space-y-6">
<FunZoneSalesSyncBanner />
<Card className="p-5">
<h2 className="mb-1 text-lg font-bold text-slate-800">فرایند فروش</h2>
<p className="mb-6 text-sm text-slate-500">
@@ -51,11 +58,12 @@ export function SalesProcess() {
</div>
</Card>
<div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
<div className="grid grid-cols-2 gap-4 lg:grid-cols-5">
<StatCard label="پیش‌فاکتور" value={toFa(summary.proformaCount)} hint={`${toFa(summary.openProformas)} باز`} />
<StatCard label="فاکتور فروش" value={toFa(summary.invoiceCount)} hint={formatMoney(summary.totalSales)} />
<StatCard label="فاکتور برگشتی" value={toFa(summary.returnCount)} hint={formatMoney(summary.totalReturns)} />
<StatCard label="فروش خالص" value={formatMoney(summary.netSales)} hint={`${toFa(summary.unpaidCount)} تسویه‌نشده`} />
<StatCard label="همگام فان‌زون" value={toFa(funzoneSyncedCount)} hint="فاکتور از پرداخت رویداد" tone="brand" />
</div>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">