Files
accounting-frontend/docs/جریان-سیستم-و-شماره‌گذاری.md
2026-07-11 16:53:03 +03:30

512 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# مستند کامل سامانه حسابداری FunZone
این سند توضیح می‌دهد **اعداد و شماره‌ها چطور ساخته می‌شوند**، و **هر بخش منو چطور به بقیه وصل است** — از داشبورد تا تنظیمات.
---
## ۱. نمای کلی معماری
| لایه | تکنولوژی | آدرس تقریبی |
|------|----------|-------------|
| فرانت‌اند حسابداری | React + TypeScript + Vite | اپ `funzone-accounting` |
| API حسابداری | Django REST | معمولاً `localhost:8010/api` |
| API اصلی FunZone | Django (مشتری، پرداخت، مالک، رویداد) | معمولاً `localhost:8000/api` |
**منبع حقیقت داده‌ها:** `AppStore` همه موجودیت‌ها را از API حسابداری بارگذاری می‌کند و CRUD را از همان‌جا انجام می‌دهد. همگام‌سازی با FunZone (بلیت، کیف پول، برداشت) از API اصلی می‌خواند و در دفتر حسابداری ثبت می‌کند.
```
┌─────────────────┐ همگام‌سازی ┌──────────────────────┐
│ FunZone API │ ──────────────────► │ Accounting Frontend │
│ پرداخت/کیف‌پول │ │ AppStore + صفحات │
└─────────────────┘ └──────────┬───────────┘
│ REST
┌──────────────────────┐
│ Accounting Backend │
│ جداول دفتر / شماره سند│
└──────────────────────┘
```
---
## ۲. ساختار منو و مسیرها
| گروه | برچسب منو | مسیر | صفحه اصلی |
|------|-----------|------|-----------|
| اصلی | داشبورد | `/` | `Dashboard.tsx` |
| حسابداری | حساب‌ها (کدینگ) | `/accounts` | `Accounts.tsx` |
| حسابداری | اسناد حسابداری | `/vouchers` | `Vouchers.tsx` |
| عملیات | مشتریان و فروش | `/sales/*` | `Sales.tsx` + زیرصفحات |
| عملیات | تأمین‌کنندگان و خرید | `/purchases/*` | `Purchases.tsx` |
| عملیات | انبارداری | `/inventory` | `Inventory.tsx` |
| عملیات | دریافت و پرداخت | `/treasury` | `Treasury.tsx` |
| عملیات | حقوق و دستمزد | `/payroll` | `Payroll.tsx` |
| تحلیل | گزارش‌ها | `/reports` | `Reports.tsx` |
| سیستم | تنظیمات | `/settings` | `Settings.tsx` |
### زیرمنوی فروش
| مسیر | نقش |
|------|-----|
| `/sales` | فرایند فروش |
| `/sales/proforma` | پیش‌فاکتور |
| `/sales/invoice` | فاکتور فروش |
| `/sales/return` | برداشت‌ها و لغو شده |
| `/sales/adjustments` | اعلامیه بدهکار/بستانکار |
| `/sales/sales-types` | نوع فروش |
| `/sales/customers` | مشتریان |
| `/sales/review` | مرور فروش |
تعریف منو: `src/components/layout/navigation.ts`
---
## ۳. تولید اعداد و شماره‌ها (قلب سیستم)
### ۳.۱ الگوریتم مشترک فرانت‌اند
فایل: `src/utils/id.ts`
```ts
// شناسه موقت کلاینت (قبل از UUID سرور)
createId(prefix) مثلاً "v-" + زمان + تصادفی
// شماره ترتیبی سند/فاکتور/…
nextNumber(items) max(item.number) + 1
```
**نکات مهم:**
- هیچ جدول Sequence / سری شماره‌گذاری جدا در دیتابیس نیست.
- **سال مالی (`fiscalYear`) فقط نمایشی است** و شماره‌ها را ریست یا جدا نمی‌کند.
- برای بیشتر اسناد، شماره را **کلاینت** با `nextNumber` روی لیست فیلترشده می‌سازد و سرور همان عدد را ذخیره می‌کند.
- **استثنا: شماره سند حسابداری (`Voucher.number`)** — سرور شماره کلاینت را نادیده می‌گیرد و خودش اختصاص می‌دهد.
---
### ۳.۲ ماتریس شماره‌گذاری
| نوع سند | فیلد | محدوده سری | کی می‌سازد؟ | فایل / منطق |
|---------|------|------------|-------------|-------------|
| **سند حسابداری** | `number` | همه اسناد | **سرور** (`_next_number` + قفل ردیف) | `serializers.py` |
| **پیش‌فاکتور فروش** | `number` | فقط `documentType=proforma` و `kind=sale` | کلاینت | `SalesDocumentSection` |
| **فاکتور فروش** | `number` | فقط `documentType=invoice` و `kind=sale` | کلاینت | `SalesDocumentSection` + سینک FunZone |
| **فاکتور خرید** | `number` | همه `kind=purchase` | کلاینت | `TradeModule` |
| **دریافت** | `number` | فقط `kind=receipt` | کلاینت | `Treasury.tsx` / سینک خزانه |
| **پرداخت** | `number` | فقط `kind=payment` | کلاینت | `Treasury.tsx` / سینک |
| **برداشت کیف پول** | `number` | **کل** لیست `treasury` (نه فقط payment) | کلاینت | `withdrawalTreasury.ts` |
| **اعلامیه بدهکار/بستانکار** | `number` | همه اعلامیه‌ها | کلاینت | `PartyAdjustmentsPage` |
| **کد حساب** | `code` | دستی / یکتا در DB | کاربر | `Accounts.tsx` + seed |
| **کد کالا / نوع فروش / پرسنل** | `code` | دستی | کاربر | بدون auto |
| **فیش حقوقی** | — | ندارد | — | با `id` و `period` |
---
### ۳.۳ شماره سند حسابداری (تنها شماره قطعی سمت سرور)
در `funzone-accounting-backend/accounting/serializers.py`:
1. فیلد `number` در `VoucherSerializer` **read-only** است.
2. هنگام `create`، سرور با `select_for_update` آخرین شماره را می‌گیرد و `+1` می‌کند.
3. بعد از ایجاد، شماره تغییر نمی‌کند (`update` فیلد `number` را حذف می‌کند).
4. اگر سندی با `number <= 0` باشد، در update می‌تواند شماره بگیرد.
فرانت قبل از POST ممکن است شماره موقت با `nextNumber(data.vouchers)` نشان دهد؛ بعد از ذخیره، شماره واقعی همانی است که سرور برمی‌گرداند.
---
### ۳.۴ شناسه‌های داخلی (`createId`)
| پیشوند | موجودیت |
|--------|---------|
| `v-` | سند |
| `vl-` | سطر سند |
| `inv-` | فاکتور |
| `il-` | سطر فاکتور |
| `tr-` | دریافت/پرداخت |
| `acc-` | حساب |
| `prod-` | کالا |
| `party-` | طرف‌حساب |
| `st-` | نوع فروش |
| `adj-` | اعلامیه |
| `emp-` | کارمند |
| `ps-` | فیش حقوقی |
این‌ها شناسه موقت UI هستند؛ بعد از ایجاد در بک‌اند معمولاً با UUID سرور جایگزین می‌شوند.
---
### ۳.۵ تگ‌های پایدار `source` (برای جلوگیری از دوباره‌ثبتی)
| الگو | معنی |
|------|------|
| `invoice:{uuid}` | فاکتور دستی |
| `funzone:invoice:{paymentId}` | سند بلیت درگاه |
| `funzone:invoice:wallet:{paymentId}` | سند بلیت از کیف پول |
| `adjustment:{id}` | اعلامیه |
| `treasury:{id}` | خزانه دستی |
| `funzone:cust-pay:{id}` | پرداخت مشتری (قدیمی/خزانه) |
| `funzone:wallet-pay:{id}` | تراکنش کیف پول |
| `funzone:owner-txn:{id}` | تراکنش مالک |
| `withdrawal:{id}` | برداشت IBAN |
فایل کلیدی لینک بلیت↔خزانه: `src/pages/sales/funzoneVoucherLink.ts`
منبع حقیقت تقسیم کارمزد بلیت = **سند فاکتور فروش**؛ اگر سند خزانه تکراری برای همان پرداخت بماند، حذف می‌شود.
---
## ۴. کدینگ حساب‌ها و نقش هر کد
حساب‌های پیش‌فرض از `seeding.py` (نمونه مهم‌ها):
| کد | نام | نقش در سیستم |
|----|-----|--------------|
| 1001 | صندوق | نقدینگی داشبورد |
| 1002 | بانک ملت | بدهکار/بستانکار نقد در اسناد خودکار |
| 1003 | بانک سامان | نقدینگی |
| 1004 | دریافتنی مشتریان | فروش عادی، اعلامیه، تسویه خزانه |
| 1005 | موجودی کالا | فاکتور خرید |
| 2001 | پرداختنی تأمین‌کنندگان | خرید |
| 2002 | مالیات پرداختنی | ۱۰٪ بلیت FunZone |
| 2003 / 2004 | حقوق / بیمه | در کدینگ هست؛ حقوق هنوز سند نمی‌زند |
| 2005 | بدهی به مالکان (کیف پول) | ۷۶٪ سهم مالک |
| 2006 | بدهی به مشتریان (کیف پول) | شارژ/برداشت/بلیت از کیف |
| 4001 | درآمد فروش | فروش عادی + ۱۴٪ سود پلتفرم |
| 5002 | هزینه حقوق | رزرو شده؛ Payroll وصل نیست |
| 5007 | سهم مالکان | در تنظیمات مپ شده؛ مسیر فعلی بلیت بیشتر از 2005/4001/2002 استفاده می‌کند |
**تنظیمات نگاشت حساب‌ها** (`Settings``voucherAccounts`): بانک، بدهی مالک، بدهی مشتری، سهم مالک، درآمد فروش.
بدون کدینگ درست، `buildSalesVoucher` / `buildPurchaseVoucher` / `buildTreasuryVoucher` سند نمی‌سازند (`null`).
---
## ۵. فلوچارت اتصال ماژول‌ها
### ۵.۱ نمای کلی ارتباطات
```mermaid
flowchart TB
subgraph سیستم["سیستم"]
SET[تنظیمات<br/>نگاشت حساب‌ها / سال مالی نمایشی]
end
subgraph حسابداری["حسابداری"]
ACC[حساب‌ها / کدینگ]
VOC[اسناد حسابداری]
end
subgraph عملیات["عملیات"]
SAL[مشتریان و فروش]
PUR[تأمین‌کنندگان و خرید]
INV[انبارداری]
TRE[دریافت و پرداخت]
PAY[حقوق و دستمزد]
end
subgraph تحلیل["تحلیل"]
REP[گزارش‌ها]
DAS[داشبورد]
end
subgraph خارجی["خارج از اپ"]
FZ[FunZone API]
end
SET --> ACC
SET --> SAL
SET --> TRE
ACC --> VOC
ACC --> SAL
ACC --> PUR
ACC --> TRE
FZ -->|سینک طرف‌حساب| SAL
FZ -->|سینک بلیت / لغو| SAL
FZ -->|شارژ کیف / پرداخت مالک| TRE
FZ -->|رویداد / رزرو| INV
SAL -->|buildSalesVoucher + موجودی| VOC
SAL -->|اعلامیه| VOC
PUR -->|buildPurchaseVoucher + موجودی| VOC
PUR -->|افزایش stock| INV
SAL -->|کاهش stock| INV
TRE -->|buildTreasuryVoucher + تسویه فاکتور| VOC
TRE -->|reconcile paid/confirmed| SAL
PAY -.->|فعلاً بدون سند| VOC
VOC --> REP
VOC --> DAS
SAL --> DAS
PUR --> DAS
INV --> DAS
TRE --> DAS
```
### ۵.۲ جریان تولید سند از عملیات
```mermaid
flowchart LR
A[عملیات کاربر یا سینک FunZone] --> B{نوع؟}
B -->|فاکتور فروش/خرید| C[ذخیره Invoice]
B -->|دریافت/پرداخت| D[ذخیره TreasuryTxn]
B -->|اعلامیه| E[ذخیره PartyAdjustment]
B -->|سند دستی| F[Vouchers UI]
C --> G[invoiceSideEffects]
G --> H[تغییر موجودی کالا]
G --> I[buildInvoiceVoucher]
D --> J[buildTreasuryVoucher]
D --> K[reconcileInvoicePaymentStatus]
E --> L[buildAdjustmentVoucher]
F --> M[createDraft + nextNumber کلاینت]
I --> N[POST سند]
J --> N
L --> N
M --> N
N --> O[سرور: شماره قطعی Voucher]
O --> P[دفتر کل / تراز / داشبورد / گزارش]
```
### ۵.۳ جریان بلیت FunZone (تقسیم مبالغ)
برای مبلغ ناخالص `G`:
| جزء | نرخ | حساب بستانکار معمول |
|-----|-----|---------------------|
| مالیات | ۱۰٪ | 2002 |
| سود پلتفرم | ۱۴٪ | 4001 |
| سهم مالک | ۷۶٪ (باقیمانده) | 2005 |
**بدهکار:**
- درگاه: 1002 بانک
- کیف پول مشتری: 2006
تابع: `splitEventPayment` در `src/utils/funzoneFees.ts`
سند: `buildSalesVoucher` وقتی note شامل `funzone:pay:` است.
```mermaid
flowchart TB
P[پرداخت بلیت در FunZone] --> S[funzoneSalesSync]
S --> I[فاکتور فروش status=paid]
I --> V[سند با source=funzone:invoice:…]
V --> L1[بدهکار بانک یا کیف 2006]
V --> L2[بستانکار مالک 2005]
V --> L3[بستانکار درآمد 4001]
V --> L4[بستانکار مالیات 2002]
T[سند خزانه تکراری همان پرداخت] -.->|حذف توسط funzoneVoucherLink| X[حذف]
```
### ۵.۴ ترتیب همگام‌سازی یکپارچه
`unifiedVoucherSync.ts`:
1. سینک خزانه از FunZone (شارژ کیف، تراکنش مالک، …)
2. سینک فاکتورهای فروش بلیت + ثبت سند فاکتور
3. حذف اسناد تکراری / منسوخ (`supersededVoucherIds` + لینک بلیت)
---
## ۶. جزئیات هر بخش منو
### ۶.۱ داشبورد
**می‌خواند از:** اسناد posted، فاکتورها، موجودی کالا، حساب‌های نقدی.
**نمایش تقریبی:**
- نقدینگی (کدهای 10011003)
- جمع فروش / خرید از فاکتورها
- سود و زیان و تراز از `trialBalance` روی اسناد
- موجودی کم / فاکتورهای تسویه‌نشده
- نمودار چندماهه
**تولید عدد:** خودش شماره سند نمی‌سازد؛ فقط تجمیع می‌کند.
---
### ۶.۲ حساب‌ها (کدینگ)
**نقش:** درخت حساب‌ها (`parentId`)، مانده افتتاحیه، نوع (دارایی/بدهی/درآمد/هزینه).
**اتصال:** پایه همه سطرهای سند (`VoucherLine.accountId`). بدون حساب‌های اجباری، اسناد خودکار ساخته نمی‌شوند.
**شماره:** کد حساب دستی و یکتا — بدون `nextNumber`.
---
### ۶.۳ اسناد حسابداری
**ورودی‌ها:**
| منبع | چگونه |
|------|--------|
| دستی در همین صفحه | پیش‌نویس + ثبت |
| فروش | `buildSalesVoucher` |
| خرید | `buildPurchaseVoucher` |
| خزانه | `buildTreasuryVoucher` |
| اعلامیه | `buildAdjustmentVoucher` |
| دکمه همگام FunZone | `unifiedVoucherSync` |
**شماره:** سرور قطعی می‌کند.
**وضعیت:** `draft` | `posted` — گزارش‌ها معمولاً روی posted (منهای اسناد حذف‌شده/منسوخ).
---
### ۶.۴ مشتریان و فروش
**موجودیت‌ها:** Party (مشتری)، Invoice فروش، نوع فروش، اعلامیه، سینک FunZone.
| عمل | اثر حسابداری | اثر انبار |
|-----|--------------|-----------|
| پیش‌فاکتور | بدون سند | معمولاً بدون تغییر قطعی موجودی مسیر اصلی سند |
| فاکتور فروش عادی confirmed | بدهکار 1004 / بستانکار درآمد | کاهش stock |
| بلیت FunZone | تقسیم ۱۰/۱۴/۷۶ | — |
| لغو بلیت درگاه | بانک بدهکار / 2006 بستانکار | — |
| لغو بلیت کیف پول | حذف/بازگردانی سند قبلی | — |
| اعلامیه بدهکار | ↑ مطالبات / ↑ درآمد | — |
| اعلامیه بستانکار | عکس بالا | — |
**شماره فاکتور:** سری جدا برای پیش‌فاکتور و فاکتور (`nextNumber` روی همان `documentType`).
**تسویه:** خزانه با `reconcileInvoicePaymentStatus` به صورت FIFO وضعیت `confirmed``paid` را عوض می‌کند (بلیت‌های FunZone prepaid می‌مانند).
---
### ۶.۵ تأمین‌کنندگان و خرید
**موجودیت‌ها:** Party (supplier)، Invoice خرید.
**سند خودکار (confirmed):**
- بدهکار 1005 موجودی
- بستانکار 2001 پرداختنی
**شماره:** یک سری برای همه فاکتورهای خرید.
**اتصال به خزانه:** پرداخت به تأمین‌کننده از ماژول دریافت/پرداخت؛ تسویه فاکتور خرید از همان منطق reconcile.
---
### ۶.۶ انبارداری
**دو لایه:**
1. **موجودی کالا در حسابداری** — فیلد `Product.stock`؛ با تأیید فاکتور خرید/فروش عوض می‌شود (`applyStockChanges` / `stockDeltas`).
2. **نمای عملیاتی FunZone** — رویداد/رزرو زنده (`funzoneInventory.ts`**سند حسابداری نمی‌زند**.
یعنی انبار «دفتر انبار جدا» ندارد؛ موجودی از فاکتورها مشتق می‌شود + نمای FunZone برای عملیات.
---
### ۶.۷ دریافت و پرداخت (خزانه)
| نوع تراکنش | سند تقریبی |
|------------|------------|
| شارژ کیف پول مشتری | بدهکار بانک / بستانکار 2006 |
| برداشت کیف پول | بدهکار 2006 / بستانکار بانک |
| دریافت عادی از مشتری | بدهکار بانک / بستانکار 1004 |
| پرداخت به تأمین‌کننده/مالک | بدهکار 2005 یا 2001 / بستانکار بانک |
| مسیر قدیمی split روی خزانه | همان ۱۰/۱۴/۷۶ (امروز ترجیح با سند فاکتور بلیت است) |
**شماره:** دریافت و پرداخت سری جدا در UI؛ مسیر برداشت ممکن است از `nextNumber` روی **کل** خزانه استفاده کند.
---
### ۶.۸ حقوق و دستمزد
CRUD کارمند و فیش حقوقی.
**اتصال به اسناد: فعلاً وجود ندارد.** حساب‌های 2003/2004/5002 در کدینگ آماده هستند ولی Payroll سند ثبت نمی‌کند.
---
### ۶.۹ گزارش‌ها
از توابع `src/utils/accounting.ts`:
- تراز آزمایشی (`trialBalance`)
- دفتر حساب (`accountLedger`)
- سود و زیان (`incomeStatement`)
- ترازنامه (`balanceSheet`)
ورودی: حساب‌ها (مانده افتتاحیه) + اسناد posted (فیلتر اسناد منسوخ).
---
### ۶.۱۰ تنظیمات
- اطلاعات شرکت و **سال مالی نمایشی**
- نگاشت حساب‌های پیش‌فرض اسناد خودکار
- ریست/seed داده‌ها (در صورت فعال بودن در UI)
بدون نگاشت درست، زنجیره فروش/خزانه/بلیت می‌شکند.
---
## ۷. موجودیت‌ها و روابط
```
Account (درخت)
└── VoucherLine.accountId → Voucher
Party (customer | supplier ، گاهی externalId از FunZone)
├── Invoice.partyId
├── PartyAdjustment.partyId
└── TreasuryTxn.partyId
Invoice (sale | purchase)
└── Voucher با source پایدار
TreasuryTxn
└── Voucher با source خزانه / FunZone / withdrawal
Employee → Payslip (بدون Voucher)
CompanySettings (singleton) → FKs به Account
```
**وضعیت فاکتور:** `draft` | `confirmed` | `paid` | `cancelled`
**وضعیت سند:** `draft` | `posted`
---
## ۸. فایل‌های کلیدی (مرجع سریع)
| فایل | نقش |
|------|-----|
| `src/utils/id.ts` | `createId` / `nextNumber` |
| `src/pages/sales/salesUtils.ts` | همه سازنده‌های سند + تسویه + source |
| `src/pages/sales/invoiceEffects.ts` | اثر جانبی ذخیره فاکتور |
| `src/utils/funzoneFees.ts` | تقسیم ۱۰٪ / ۱۴٪ / ۷۶٪ |
| `src/pages/sales/funzoneVoucherLink.ts` | لینک بلیت و حذف سند تکراری خزانه |
| `src/accounting/unifiedVoucherSync.ts` | ارکستراسیون سینک |
| `src/accounting/voucherDedupe.ts` | حذف/مخفی اسناد تکراری |
| `src/pages/sales/funzoneSalesSync.ts` | پرداخت FunZone → فاکتور |
| `src/pages/treasury/funzoneTreasurySync.ts` | کیف پول / مالک → خزانه |
| `src/utils/accounting.ts` | محاسبات گزارش و تراز |
| `src/store/AppStore.tsx` | بارگذاری و CRUD |
| `backend/.../serializers.py` | شماره قطعی سند |
| `backend/.../seeding.py` | کدینگ اولیه |
> ⚠️ `voucherSync.ts` مسیر قدیمی است؛ برای جلوگیری از دوباره‌ثبتی از مسیر یکپارچه (`unifiedVoucherSync`) استفاده شود.
---
## ۹. جمع‌بندی قوانین شماره‌گذاری (برای تیم)
1. **فقط شماره سند حسابداری روی سرور قطعی است**؛ بقیه `max+1` سمت کلاینت روی لیست فیلترشده.
2. **سال مالی شماره‌ها را جدا یا ریست نمی‌کند.**
3. **پیش‌فاکتور و فاکتور فروش سری جدا** دارند؛ **خرید یک سری** دارد.
4. **دریافت و پرداخت در UI سری جدا** دارند؛ مسیر برداشت ممکن است با سری دیگر هم‌پوشانی عددی داشته باشد.
5. **بلیت FunZone:** فاکتور + سند با تگ `funzone:invoice:…`؛ تقسیم کارمزد روی همان سند؛ خزانه برای همان بلیت نباید دوبار ثبت شود.
6. **حقوق هنوز به دفتر کل وصل نیست.**
---
*آخرین به‌روزرسانی بر اساس کدبیس `funzone-accounting` و `funzone-accounting-backend`.*