Перейти до змісту

Cash Transfer — Перекази коштів між своїми рахунками

Тип: horizontal, в складі essentials (не окремий модуль) Backend: backend/essentials/models/cash_transfer.py Frontend: frontend/erp/src/components/Essentials/CashTransfer/ API: /api/v1/essentials/cash-transfers/ Доданий: 2026-04-23, Phase F-6

Призначення

Уніфікований документ для переказу коштів між власними рахунками організації. Покриває всі 4 напрями:

  • Каса → Банк
  • Банк → Каса
  • Банк → Банк
  • Каса → Каса

Архітектурне рішення

Згідно з project-memory western_accounting_approach: каса і банк — не окремі типи документів, а типи рахунків (Cashbox vs SettlementAccount). UA-вимоги (РКО/ПКО, Касова книга, ліміт готівки 50 000 грн/день) — шарами над цим уніфікованим документом, не окремі сутності.

Модель

class CashTransfer(TransactionModel):
    organization           # FK → Organization
    amount, currency
    from_cashbox           # FK (null)  ┐ exactly one of
    from_settlement_account # FK (null) ┘
    to_cashbox             # FK (null)  ┐ exactly one of
    to_settlement_account  # FK (null)  ┘
    business_operation     # FK → BusinessOperation (для головної проводки)
    fee_amount             # комісія банку (опційно)
    fee_business_operation # FK → BusinessOperation (для комісії, required якщо fee>0)

State від TransactionModel: draftposted → (опц.) marked.

Посту-логіка

Service: backend/essentials/services/cash_transfer_service.py

post_cash_transfer(transfer):
  1. validate_before_post()  # див. нижче
  2. reverse_accounting_entries(transfer)  # rule: re-post має очищувати
  3. post_accounting_entry(..., business_operation=main)  # Dt/Ct з BO
  4. if fee > 0:
         post_accounting_entry(..., business_operation=fee_bo)
  5. state = 'posted'

Все під @transaction.atomic — частковий результат неможливий.

Типові Дт/Кт (через pre-configured BusinessOperation):

Напрям Dt Ct
Каса → Банк 311 (Banking) 301 (Cashbox)
Банк → Каса 301 311
Банк → Банк 311 (target) 311 (source)
Каса → Каса 301 (target) 301 (source)
Комісія (fee>0) 92 або 949 (expense) 311 (source)

Валідація (validate_before_post)

  1. Рівно один source-FK (cashbox або settlement_account)
  2. Рівно один dest-FK
  3. Source != Destination
  4. amount > 0
  5. Валюта source / dest збігається з currency документа (різна валюта → використати BankExchangeProcess)
  6. business_operation має обидва debit_account і credit_account
  7. Якщо fee_amount > 0fee_business_operation обов'язкове і має обидва рахунки
  8. date > posting_lock_date (якщо налаштовано)

Endpoints

Стандартний ModelViewSet з двома custom actions:

Endpoint Method Призначення
/cash-transfers/ GET, POST Список / створити
/cash-transfers/{id}/ GET, PUT, PATCH, DELETE Деталь / edit / видалити
/cash-transfers/{id}/form-data/ GET Запис + refs для форми
/cash-transfers/form-refs/ GET Refs для нового запису
/cash-transfers/{id}/post_document/ POST Провести документ
/cash-transfers/{id}/unpost_document/ POST Скасувати проведення

Відповідність правилам

Слідує .claude/rules/document-posting.md: - ✅ state у read_only_fields серіалізатора - ✅ validate() блокує edit коли state='posted' (якщо context не має allow_posted_edit) - ✅ Re-post видаляє старі PostingGroup через reverse_accounting_entries перед створенням нових - ✅ Unpost видаляє всі PostingGroup - ✅ Записи регістру створюються тільки через post_accounting_entry, не прямою вставкою - ✅ Post/unpost обгорнуті в @transaction.atomic - ✅ validate_before_post перевіряє posting_lock_date

MVP обмеження (Phase 1)

  • Тільки одна організація per документ (intercompany — пізніше)
  • Однакова валюта source=dest (різна валюта → BankExchangeProcess)
  • Immediate transfer — без «грошей в дорозі» (рах. 333)
  • Single transfer — без масових операцій

🔮 Deferred

  • Money in transit (333) — опціональний двоетапний флоу: списання сьогодні, зарахування через N днів
  • Cross-currency transfer — інтеграція з BankExchangeProcess як source+destination
  • Bulk transfer — масове перерахування зарплат на різні банки одним документом
  • UA print forms: РКО (КО-1) для касових напрямів, платіжне доручення для банківських
  • UA cash limit validation — блокувати касові перекази понад 50 000 грн/день між юр.особами
  • AI: anomaly detection — попередження про нетиповий за розміром переказ (розглянуто під A.6 checkpoint, відкладено)
  • Bank Reconciliation integration — matching bank statement rows до posted CashTransfers

Status

MVP Phase 1 — завершено 2026-04-23. Бекенд + фронтенд + docs. Smoke-тести ручні. Unit-тести — TODO.