########################################
# PURCHASES ENHANCEMENTS + EXPENSES MODULE
########################################

We want to enhance the Purchases module and add a new Expenses module.

========================================
# A) PURCHASES ENHANCEMENTS (المشتريات)
========================================

We already have:
- suppliers
- purchase_invoices
- purchase_payments
- journal_entries

We now want to add:

1) Agreement / monthly terms per supplier
2) Payment terms in days per supplier and auto due dates
3) Debts / Payables dashboard for suppliers
4) Detailed statement of account per supplier


----------------------------------------
## A.1 Supplier Agreement & Payment Terms
----------------------------------------

### Update suppliers table:

Add the following fields:

- agreement_text (string, nullable)
  // نص الاتفاقية الشهرية أو شروط التعامل مع المورد
  // مثال: "يتم السداد خلال 30 يوم من تاريخ الفاتورة، مع خصم 5% في حال السداد خلال 10 أيام."

- payment_term_days (integer, nullable)
  // مدة السداد بالأيام، مثل 30، 45، 60...
  // إذا كانت null يعني لا يوجد شرط ثابت، ويمكن تحديد الاستحقاق يدويًا في الفاتورة.

### Supplier API updates:

- When creating/updating a supplier (POST/PUT /suppliers):
  - Allow sending `agreement_text` and `payment_term_days`.
  - Validate payment_term_days:
    - must be >= 0 if provided.
    - If invalid: return "مدة السداد يجب أن تكون رقمًا صحيحًا أكبر من أو يساوي صفر".

----------------------------------------
## A.2 Auto Due Date on Purchase Invoices
----------------------------------------

We already have purchase_invoices with:
- invoice_date
- due_date (nullable)
- payment_status

We now want:

- When creating a new purchase invoice (POST /purchase-invoices):
  - If the request body does NOT explicitly provide `due_date` AND
    the supplier has a `payment_term_days` value:
    - Automatically set:
      - due_date = invoice_date + payment_term_days (in days).
  - If the invoice is "cash" (fully paid immediately) you may keep due_date = invoice_date or null, depending on existing logic.
  - If user explicitly passes `due_date` in the request, use that and DO NOT override it.

Validation:
- If payment_term_days exists but invoice_date is missing → return error "تاريخ الفاتورة مطلوب لحساب تاريخ الاستحقاق".


----------------------------------------
## A.3 Debts / Payables Dashboard (صفحة الديون)
----------------------------------------

We want a dedicated "Debts / Payables" page that shows:

- Total outstanding payables (إجمالي الديون على الموردين)
- Total overdue invoices (فواتير متأخرة عن تاريخ الاستحقاق)
- Totals by aging buckets:
  - 0–30 days
  - 31–60 days
  - 61–90 days
  - > 90 days
- List of suppliers with:
  - total outstanding balance
  - overdue amount
  - number of unpaid/overdue invoices

### New endpoint: GET /reports/payables-summary

Response should include:

- global_summary:
  - total_outstanding            // إجمالي الرصيد الدائن للموردين
  - total_overdue                // إجمالي الفواتير المتأخرة
  - aging_buckets:
    - "0_30": amount
    - "31_60": amount
    - "61_90": amount
    - "90_plus": amount

- suppliers: [
    {
      "supplier_id": 1,
      "supplier_name_ar": "مورد أ",
      "total_outstanding": 5000,
      "overdue_amount": 2000,
      "invoice_count_unpaid": 3,
      "invoice_count_overdue": 1
    },
    ...
  ]

Implementation:

- Use purchase_invoices and purchase_payments, OR journal_entries (if supplier control account is used).
- For a simpler version:
  - total_invoice_amount = sum(invoice.total_amount)
  - total_payments_for_invoice = sum(payments.amount)
  - remaining = total_invoice_amount - total_payments_for_invoice
  - If remaining > 0 → this amount is outstanding.
  - If invoice.due_date < today → outstanding portion is considered overdue.
  - Use (today - due_date) to determine aging bucket.


----------------------------------------
## A.4 Supplier Statement of Account (كشف حساب المورد)
----------------------------------------

We want an endpoint to generate a full statement for a supplier:

- Opening balance
- Detailed transactions (invoices, payments, manual adjustments, journal entries)
- Running balance
- Closing balance

### New endpoint: GET /suppliers/:id/statement

Query parameters:
- ?from_date=YYYY-MM-DD (optional)
- ?to_date=YYYY-MM-DD (optional)

Response:

- supplier info:
  - id, name_ar, agreement_text, payment_term_days

- opening_balance:
  - amount (could be 0 if not defined)
  - direction ( "debit" or "credit" ) or simply positive/negative, with explanation:
    - Positive means we owe the supplier.
    - Negative means supplier has debit balance.

- transactions: ordered by date
  Each transaction item should include:
  - date
  - type: "invoice", "payment", "adjustment"
  - reference_number (e.g. invoice id/number, payment id)
  - description (Arabic)
  - debit_amount    // مبلغ مدين
  - credit_amount   // مبلغ دائن
  - balance_after   // الرصيد بعد الحركة (رصيد تراكمي)

Example:
- Invoice 1150 SAR:
  - debit: 0
  - credit: 1150
  - balance increases by 1150 (we owe more).
- Payment 500 SAR:
  - debit: 500
  - credit: 0
  - balance decreases by 500.

- closing_balance:
  - amount
  - explanation: "رصيد نهائي للمورد حتى تاريخ [to_date]"

Implementation options:

- If journal_entries and journal_lines are already used for suppliers:
  - Use account_code = supplier_control_account_code and filter by supplier.
- For a simpler approach:
  - Combine:
    - purchase_invoices (as credit)
    - purchase_payments (as debit)
  - And any manual adjustments if implemented.

Return Arabic errors:
- "المورد غير موجود"
- "لا توجد حركات لهذا المورد في الفترة المحددة"


========================================
# B) EXPENSES MODULE (النفقات)
========================================

We want to add a full Expenses module with:

- Expense Types (أنواع النفقات)
- Expenses (النفقات)
- Expense reports

Expenses may or may not be linked to suppliers.
Expenses can have VAT inclusive or exclusive.
Some expense types have fixed amounts.

We also want to link expenses later to accounting (journal entries), but first we define the data model and APIs.


----------------------------------------
## B.1 Expense Types (أنواع النفقات)
----------------------------------------

### Table: expense_types
Fields:
- id (integer, primary key, auto increment)
- name_ar (string, not null, unique)         // اسم نوع النفقة (مثال: "بنزين", "إيجار", "إنترنت")
- description_ar (string, nullable)          // وصف نوع النفقة
- is_fixed_amount (boolean, not null, default false)
- fixed_amount (real, nullable)              // إذا كانت النفقة ثابتة، يتم تخزين المبلغ هنا
- is_active (boolean, default true)
- created_at (datetime)
- updated_at (datetime)

Behavior:

- If is_fixed_amount = true, fixed_amount must be > 0.
- When creating an expense, if a fixed amount type is selected, default the amount from fixed_amount (but allow override or keep as non-editable based on implementation).

### APIs:

- GET /expenses/types
- POST /expenses/types
- GET /expenses/types/:id
- PUT /expenses/types/:id
- DELETE /expenses/types/:id (soft delete: is_active = false)

Validation messages (Arabic):
- "اسم النفقة مطلوب"
- "اسم النفقة موجود مسبقاً"
- "المبلغ الثابت مطلوب لهذا النوع"
- "المبلغ الثابت يجب أن يكون أكبر من صفر"


----------------------------------------
## B.2 Expenses (النفقات)
----------------------------------------

An expense represents a spending transaction, such as fuel, rent, subscription, etc.

### Table: expenses
Fields:
- id (integer, primary key, auto increment)
- expense_type_id (integer, foreign key to expense_types.id, not null)
- supplier_id (integer, foreign key to suppliers.id, nullable)   // if expense is linked to a supplier (e.g. rent company)
- invoice_reference (string, nullable)          // رقم فاتورة (غير إجباري) – يمكن إدخاله يدويًا
- description_ar (string, nullable)             // وصف النفقة
- amount_without_vat (real, not null)           // المبلغ بدون ضريبة
- vat_type (string, not null)                   // "inclusive", "exclusive", "exempt"
- vat_rate (real, not null)                     // مثال: 0.15
- vat_amount (real, not null, default 0)
- total_amount (real, not null)                 // المبلغ الإجمالي مع الضريبة
- payment_method_id (integer, foreign key to payment_methods.id, nullable)
- payment_date (date, not null)
- is_paid (boolean, not null, default true)     // حالياً نفترض النفقات تُسجل بعد الدفع، لكن يمكن جعله آجلاً لاحقاً
- attachment_url (string, nullable)             // رابط ملف مرفق (صورة الفاتورة، PDF…)
- created_by_employee_id (integer, nullable, foreign key to employees.id)
- created_at (datetime)
- updated_at (datetime)

VAT behavior (similar to purchases):

- If vat_type = "inclusive":
  - total_amount = user-entered amount (input total)
  - amount_without_vat = total_amount / (1 + vat_rate)
  - vat_amount = total_amount - amount_without_vat

- If vat_type = "exclusive":
  - amount_without_vat = user-entered amount
  - vat_amount = amount_without_vat * vat_rate
  - total_amount = amount_without_vat + vat_amount

- If vat_type = "exempt":
  - amount_without_vat = user-entered amount
  - vat_amount = 0
  - total_amount = amount_without_vat

API design:

### POST /expenses
Create a new expense.

Request JSON example:

{
  "expense_type_id": 1,
  "supplier_id": null,
  "invoice_reference": "INV-EXP-001",
  "description_ar": "شراء بنزين للسيارة",
  "amount": 50,
  "vat_type": "inclusive",         // "inclusive" | "exclusive" | "exempt"
  "vat_rate": 0.15,
  "payment_method_id": 1,
  "payment_date": "2025-10-01",
  "attachment_url": null
}

Behavior:

- If `expense_type_id` refers to an expense_type where is_fixed_amount = true:
  - Ignore the incoming `amount` from client if you want strict behavior and set it to fixed_amount,
    OR use fixed_amount as default if amount is null.
- Compute amount_without_vat, vat_amount, total_amount based on vat_type.
- Set is_paid = true for now.
- created_by_employee_id can be taken from the current authenticated user (if available).

### GET /expenses
- Filters:
  - ?from_date=
  - ?to_date=
  - ?expense_type_id=
  - ?supplier_id=
  - ?payment_method_id=
- Return basic list with totals.

### GET /expenses/:id
- Return full details including:
  - expense_type name
  - supplier name (if any)
  - payment method name

### PUT /expenses/:id
- Update fields and recompute VAT if amount/vat_type/vat_rate changed.

### DELETE /expenses/:id
- Soft delete: keep record but mark as deleted if you maintain such a flag, or actually delete if simpler.


----------------------------------------
## B.3 Expense Reports (تقارير النفقات)
----------------------------------------

We need some useful statistical reports.

### Endpoint: GET /reports/expenses-summary

Filters:
- ?from_date=
- ?to_date=
- ?expense_type_id=
- ?supplier_id=

Response:

- total_expenses_without_vat
- total_vat
- total_expenses_with_vat

- by_type: [
    {
      "expense_type_id": 1,
      "expense_type_name_ar": "بنزين",
      "total_amount": 1500,
      "count": 30
    },
    ...
  ]

- by_month: [
    {
      "year": 2025,
      "month": 10,
      "total_amount": 5000
    },
    ...
  ]

This will help show trends over time.

Optionally, another endpoint:

### GET /reports/expenses-detailed

- Return the list of expenses with all details for export (e.g. to CSV/Excel) – date, type, supplier, amount, VAT, payment method.


----------------------------------------
## B.4 Linking Expenses to Accounting (اختياري مبدئياً)
----------------------------------------

For now, you can just prepare for future integration:

- Later, when we finalize the chart of accounts (الحسابات), we will:
  - Create journal_entries for each expense:
    - Debit expense account (e.g. "مصروف إيجار", "مصروف بنزين")
    - Credit cash/bank according to payment_method.

But for this phase, focus on:
- Data model
- APIs
- Reports


========================================
# GENERAL NOTES
========================================

- Use Arabic error messages where possible:
  - "نوع النفقة غير موجود"
  - "المبلغ يجب أن يكون أكبر من صفر"
  - "تاريخ الدفع مطلوب"
- Keep the code structured:
  - Routes: `src/routes/purchases`, `src/routes/expenses`, `src/routes/reports`
  - Controllers/Services under corresponding folders.

- Do NOT break existing purchases or suppliers functionality; only extend with the new fields and endpoints.
