hesabixArc/docs/RECEIPT_PAYMENT_SYSTEM.md
2025-10-14 23:16:28 +03:30

14 KiB
Raw Blame History

📝 سیستم دریافت و پرداخت (Receipt & Payment System)

📌 مقدمه

سیستم دریافت و پرداخت یک سیستم حسابداری است که برای ثبت تراکنش‌های مالی بین کسب‌وکار و اشخاص (مشتریان و تامین‌کنندگان) استفاده می‌شود.

🎯 هدف

این سیستم برای ثبت دو نوع سند طراحی شده است:

  1. دریافت (Receipt): دریافت وجه از اشخاص (مشتریان)
  2. پرداخت (Payment): پرداخت به اشخاص (تامین‌کنندگان/فروشندگان)

📊 ساختار داده

سند (Document)

هر سند دریافت یا پرداخت شامل موارد زیر است:

{
  "id": 123,
  "code": "RC-20250115-0001",
  "business_id": 1,
  "document_type": "receipt",  // یا "payment"
  "document_date": "2025-01-15",
  "currency_id": 1,
  "created_by_user_id": 5,
  "person_lines": [
    {
      "person_id": 10,
      "person_name": "علی احمدی",
      "amount": 1000000,
      "description": "تسویه حساب"
    }
  ],
  "account_lines": [
    {
      "account_id": 456,
      "account_name": "صندوق",
      "amount": 1000000,
      "description": ""
    }
  ]
}

خطوط سند (Document Lines)

هر سند شامل دو نوع خط است:

  1. خطوط اشخاص (Person Lines): تراکنش‌های مربوط به اشخاص
  2. خطوط حساب‌ها (Account Lines): تراکنش‌های مربوط به حساب‌ها (صندوق، بانک، چک، ...)

🧮 منطق حسابداری

1 دریافت وجه از اشخاص (Receipt)

سناریو: دریافت ۱,۰۰۰,۰۰۰ تومان از مشتری "علی احمدی" به صندوق

ثبت در حساب‌ها:

صندوق (10202)                    بدهکار: 1,000,000
حساب دریافتنی - علی احمدی (10401) بستانکار: 1,000,000

منطق:

  • صندوق: بدهکار می‌شود (چون دارایی افزایش یافته)
  • حساب دریافتنی شخص: بستانکار می‌شود (چون بدهی مشتری کم شده)

کد نمونه (Frontend):

await service.createReceipt(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 10,
      'person_name': 'علی احمدی',
      'amount': 1000000,
      'description': 'تسویه حساب',
    }
  ],
  accountLines: [
    {
      'account_id': 456,  // شناسه حساب صندوق
      'amount': 1000000,
      'description': '',
    }
  ],
);

2 پرداخت به اشخاص (Payment)

سناریو: پرداخت ۵۰۰,۰۰۰ تومان به تامین‌کننده "رضا محمدی" از بانک

ثبت در حساب‌ها:

حساب پرداختنی - رضا محمدی (20201) بدهکار: 500,000
بانک (10203)                         بستانکار: 500,000

منطق:

  • حساب پرداختنی شخص: بدهکار می‌شود (چون بدهی ما به تامین‌کننده کم شده)
  • بانک: بستانکار می‌شود (چون دارایی کاهش یافته)

کد نمونه (Frontend):

await service.createPayment(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 20,
      'person_name': 'رضا محمدی',
      'amount': 500000,
      'description': 'پرداخت بدهی',
    }
  ],
  accountLines: [
    {
      'account_id': 789,  // شناسه حساب بانک
      'amount': 500000,
      'description': 'انتقال بانکی',
    }
  ],
);

🔧 نحوه استفاده از API

1. ایجاد سند دریافت/پرداخت

Endpoint: POST /api/v1/businesses/{business_id}/receipts-payments/create

Request Body:

{
  "document_type": "receipt",
  "document_date": "2025-01-15",
  "currency_id": 1,
  "person_lines": [
    {
      "person_id": 10,
      "person_name": "علی احمدی",
      "amount": 1000000,
      "description": "تسویه حساب"
    }
  ],
  "account_lines": [
    {
      "account_id": 456,
      "amount": 1000000,
      "description": ""
    }
  ],
  "extra_info": {}
}

Response:

{
  "success": true,
  "message": "RECEIPT_PAYMENT_CREATED",
  "data": {
    "id": 123,
    "code": "RC-20250115-0001",
    "business_id": 1,
    "document_type": "receipt",
    "document_date": "2025-01-15",
    "person_lines": [...],
    "account_lines": [...]
  }
}

2. دریافت لیست اسناد

Endpoint: POST /api/v1/businesses/{business_id}/receipts-payments

Request Body:

{
  "skip": 0,
  "take": 20,
  "sort_by": "document_date",
  "sort_desc": true,
  "document_type": "receipt",
  "from_date": "2025-01-01",
  "to_date": "2025-01-31",
  "search": ""
}

3. دریافت جزئیات یک سند

Endpoint: GET /api/v1/receipts-payments/{document_id}

4. حذف سند

Endpoint: DELETE /api/v1/receipts-payments/{document_id}


📱 نحوه استفاده در Flutter

1. Import کردن سرویس:

import 'package:hesabix_ui/services/receipt_payment_service.dart';

2. ایجاد instance:

final service = ReceiptPaymentService(apiClient);

3. ایجاد سند دریافت:

try {
  final result = await service.createReceipt(
    businessId: 1,
    documentDate: DateTime.now(),
    currencyId: 1,
    personLines: [
      {
        'person_id': 10,
        'person_name': 'علی احمدی',
        'amount': 1000000,
        'description': 'تسویه حساب',
      }
    ],
    accountLines: [
      {
        'account_id': 456,
        'amount': 1000000,
        'description': '',
      }
    ],
  );
  
  print('سند با موفقیت ثبت شد: ${result['code']}');
} catch (e) {
  print('خطا در ثبت سند: $e');
}

🗂️ انواع حساب‌های مورد استفاده

کد حساب نام حساب نوع توضیحات
10401 حساب دریافتنی 4 طلب از مشتریان
20201 حساب پرداختنی 9 بدهی به تامین‌کنندگان
10202 صندوق 1 صندوق
10203 بانک 3 حساب بانکی
10403 اسناد دریافتنی 5 چک دریافتی
20202 اسناد پرداختنی 10 چک پرداختی

قوانین و محدودیت‌ها

1. تعادل سند:

  • مجموع مبالغ person_lines باید برابر مجموع مبالغ account_lines باشد
  • در غیر این صورت خطای UNBALANCED_AMOUNTS برگردانده می‌شود

2. اعتبارسنجی:

  • حداقل یک خط برای اشخاص الزامی است
  • حداقل یک خط برای حساب‌ها الزامی است
  • تمام مبالغ باید مثبت باشند
  • ارز باید معتبر باشد

3. ایجاد خودکار حساب شخص:

  • اگر حساب شخص وجود نداشته باشد، به صورت خودکار ایجاد می‌شود
  • کد حساب: {parent_code}-{person_id}
    • برای دریافت: 10401-{person_id}
    • برای پرداخت: 20201-{person_id}

🔄 جریان کار (Workflow)

graph TD
    A[شروع] --> B[کاربر وارد صفحه دریافت/پرداخت می‌شود]
    B --> C[انتخاب نوع: دریافت یا پرداخت]
    C --> D[کلیک بر روی دکمه افزودن]
    D --> E[باز شدن دیالوگ]
    E --> F[وارد کردن اطلاعات اشخاص]
    F --> G[وارد کردن اطلاعات حساب‌ها]
    G --> H{تعادل برقرار است؟}
    H -->|خیر| I[نمایش اختلاف]
    I --> F
    H -->|بله| J[فعال شدن دکمه ذخیره]
    J --> K[کلیک بر روی ذخیره]
    K --> L[ارسال به سرور]
    L --> M{موفق؟}
    M -->|بله| N[نمایش پیام موفقیت]
    M -->|خیر| O[نمایش پیام خطا]
    N --> P[بستن دیالوگ]
    O --> E
    P --> Q[به‌روزرسانی لیست]
    Q --> R[پایان]

🧪 مثال‌های کاربردی

مثال 1: دریافت نقدی از مشتری

await service.createReceipt(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 10,
      'person_name': 'شرکت ABC',
      'amount': 5000000,
      'description': 'دریافت بابت فاکتور شماره 123',
    }
  ],
  accountLines: [
    {
      'account_id': 456,  // صندوق
      'amount': 5000000,
    }
  ],
);

نتیجه در حساب‌ها:

صندوق (10202)              بدهکار: 5,000,000
حساب دریافتنی - شرکت ABC  بستانکار: 5,000,000

مثال 2: دریافت با چک از مشتری

await service.createReceipt(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 15,
      'person_name': 'علی رضایی',
      'amount': 3000000,
      'description': 'دریافت بابت فاکتور 456',
    }
  ],
  accountLines: [
    {
      'account_id': 789,  // اسناد دریافتنی (چک)
      'amount': 3000000,
      'description': 'چک شماره 12345678',
    }
  ],
);

نتیجه در حساب‌ها:

اسناد دریافتنی (10403)      بدهکار: 3,000,000
حساب دریافتنی - علی رضایی  بستانکار: 3,000,000

مثال 3: دریافت مختلط (نقد + چک)

await service.createReceipt(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 20,
      'person_name': 'محمد حسینی',
      'amount': 10000000,
      'description': 'تسویه کامل',
    }
  ],
  accountLines: [
    {
      'account_id': 456,  // صندوق
      'amount': 4000000,
      'description': 'نقد',
    },
    {
      'account_id': 789,  // چک دریافتنی
      'amount': 6000000,
      'description': 'چک شماره 87654321',
    }
  ],
);

نتیجه در حساب‌ها:

صندوق (10202)                بدهکار: 4,000,000
اسناد دریافتنی (10403)        بدهکار: 6,000,000
حساب دریافتنی - محمد حسینی   بستانکار: 10,000,000

مثال 4: پرداخت نقدی به تامین‌کننده

await service.createPayment(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 30,
      'person_name': 'شرکت XYZ',
      'amount': 8000000,
      'description': 'پرداخت بابت خرید کالا',
    }
  ],
  accountLines: [
    {
      'account_id': 456,  // صندوق
      'amount': 8000000,
    }
  ],
);

نتیجه در حساب‌ها:

حساب پرداختنی - شرکت XYZ  بدهکار: 8,000,000
صندوق (10202)             بستانکار: 8,000,000

مثال 5: پرداخت به چند تامین‌کننده

await service.createPayment(
  businessId: 1,
  documentDate: DateTime.now(),
  currencyId: 1,
  personLines: [
    {
      'person_id': 35,
      'person_name': 'تامین‌کننده A',
      'amount': 2000000,
    },
    {
      'person_id': 40,
      'person_name': 'تامین‌کننده B',
      'amount': 3000000,
    }
  ],
  accountLines: [
    {
      'account_id': 890,  // بانک
      'amount': 5000000,
    }
  ],
);

نتیجه در حساب‌ها:

حساب پرداختنی - تامین‌کننده A  بدهکار: 2,000,000
حساب پرداختنی - تامین‌کننده B  بدهکار: 3,000,000
بانک (10203)                   بستانکار: 5,000,000

🐛 خطاهای رایج و راه‌حل

کد خطا توضیحات راه‌حل
INVALID_DOCUMENT_TYPE نوع سند نامعتبر از "receipt" یا "payment" استفاده کنید
CURRENCY_REQUIRED ارز الزامی است currency_id را ارسال کنید
PERSON_LINES_REQUIRED حداقل یک خط شخص الزامی person_lines را پر کنید
ACCOUNT_LINES_REQUIRED حداقل یک خط حساب الزامی account_lines را پر کنید
UNBALANCED_AMOUNTS عدم تعادل مبالغ مجموع person_lines و account_lines باید برابر باشد
PERSON_NOT_FOUND شخص یافت نشد شناسه شخص را بررسی کنید
ACCOUNT_NOT_FOUND حساب یافت نشد شناسه حساب را بررسی کنید

📝 نکات مهم

  1. تعادل سند: همیشه مطمئن شوید که مجموع مبالغ اشخاص با مجموع مبالغ حساب‌ها برابر است.

  2. ایجاد خودکار حساب: اگر حساب شخص وجود نداشته باشد، به صورت خودکار ایجاد می‌شود.

  3. کد سند: کد سند به صورت خودکار با فرمت زیر تولید می‌شود:

    • دریافت: RC-YYYYMMDD-NNNN
    • پرداخت: PY-YYYYMMDD-NNNN
  4. منطق حسابداری:

    • دریافت: شخص بستانکار، حساب (صندوق/بانک) بدهکار
    • پرداخت: شخص بدهکار، حساب (صندوق/بانک) بستانکار
  5. چند شخص/چند حساب: می‌توانید در یک سند چند شخص و چند حساب داشته باشید.


📚 منابع مرتبط


تاریخ ایجاد: 2025-01-13
نسخه: 1.0.0
توسعه‌دهنده: تیم Hesabix