pub struct ExpenseAccountingService { /* private fields */ }Expand description
Service for automatically generating journal entries from expenses
This service implements Belgian accounting logic based on PCMN (AR 12/07/2012):
- Expense creates debit to expense account (class 6)
- VAT creates debit to VAT recoverable account (4110)
- Total amount creates credit to supplier account (4400)
Inspired by Noalyss’ automatic journal entry generation
Implementations§
Source§impl ExpenseAccountingService
impl ExpenseAccountingService
pub fn new(journal_entry_repo: Arc<dyn JournalEntryRepository>) -> Self
Sourcepub async fn generate_journal_entry_for_expense(
&self,
expense: &Expense,
created_by: Option<Uuid>,
) -> Result<JournalEntry, String>
pub async fn generate_journal_entry_for_expense( &self, expense: &Expense, created_by: Option<Uuid>, ) -> Result<JournalEntry, String>
Generate journal entry for an expense
§Belgian Accounting Logic (PCMN)
Example: 1,000€ HT + 210€ VAT (21%) = 1,210€ TTC
Debit: 6100 (Expense account) 1,000.00€
Debit: 4110 (VAT Recoverable) 210.00€
Credit: 4400 (Suppliers) 1,210.00€§Arguments
expense: The expense to generate journal entry forcreated_by: User who created the expense
§Returns
Ok(JournalEntry)if generation successfulErr(String)if validation fails or expense has no account_code
Sourcepub async fn generate_payment_entry(
&self,
expense: &Expense,
payment_account: Option<String>,
created_by: Option<Uuid>,
) -> Result<JournalEntry, String>
pub async fn generate_payment_entry( &self, expense: &Expense, payment_account: Option<String>, created_by: Option<Uuid>, ) -> Result<JournalEntry, String>
Generate journal entry for expense payment
When an expense is paid, we record the payment:
Debit: 4400 (Suppliers) 1,210.00€
Credit: 5500 (Bank) 1,210.00€§Arguments
expense: The expense being paidpayment_account: Account used for payment (default: 5500 Bank)created_by: User who recorded the payment
Sourcepub async fn generate_contribution_receipt_entry(
&self,
contribution: &OwnerContribution,
building_id: Option<Uuid>,
payment_account: Option<String>,
created_by: Option<Uuid>,
) -> Result<JournalEntry, String>
pub async fn generate_contribution_receipt_entry( &self, contribution: &OwnerContribution, building_id: Option<Uuid>, payment_account: Option<String>, created_by: Option<Uuid>, ) -> Result<JournalEntry, String>
Génère l’écriture d’ENCAISSEMENT d’une quote-part de copropriétaire.
§Logique comptable (PCMN belge)
Exemple : quote-part de 2 000 € reçue par virement.
Débit : 550 (Compte courant bancaire) 2 000,00 €
Crédit : 400 (Copropriétaires) 2 000,00 €L’argent entre (actif en hausse), la créance sur le copropriétaire s’éteint (actif en baisse). Journal FIN.
§Ce que cette écriture n’est PAS
Elle ne constate pas le PRODUIT. L’appel de fonds est un produit de classe 7 constaté à son émission, pas à son encaissement ; cette écriture-ci ne fait que solder une créance déjà comptabilisée. Générer un produit ici le compterait deux fois.
§Idempotence
Une quote-part peut être soldée par deux voies : mark-paid depuis
l’interface, ou la réussite d’un paiement portant contribution_id.
Sans ce contrôle, un même encaissement débiterait la banque deux fois.
Sourcepub async fn expense_has_journal_entries(
&self,
expense_id: Uuid,
) -> Result<bool, String>
pub async fn expense_has_journal_entries( &self, expense_id: Uuid, ) -> Result<bool, String>
Check if expense already has journal entries
Prevents duplicate journal entries for the same expense.
Sourcepub async fn get_expense_journal_entries(
&self,
expense_id: Uuid,
) -> Result<Vec<JournalEntry>, String>
pub async fn get_expense_journal_entries( &self, expense_id: Uuid, ) -> Result<Vec<JournalEntry>, String>
Get journal entries for an expense
Returns all entries (expense entry + payment entry if paid).
Auto Trait Implementations§
impl !RefUnwindSafe for ExpenseAccountingService
impl !UnwindSafe for ExpenseAccountingService
impl Freeze for ExpenseAccountingService
impl Send for ExpenseAccountingService
impl Sync for ExpenseAccountingService
impl Unpin for ExpenseAccountingService
impl UnsafeUnpin for ExpenseAccountingService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Fake for T
impl<T> Fake for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more