Skip to main content

datasynth_core/models/
bank_reconciliation.rs

1//! Bank reconciliation models for matching payments to bank statement lines.
2
3use chrono::NaiveDate;
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6
7/// Status of a bank reconciliation.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
9#[serde(rename_all = "snake_case")]
10pub enum ReconciliationStatus {
11    /// Reconciliation in progress
12    #[default]
13    InProgress,
14    /// Reconciliation completed and balanced
15    Completed,
16    /// Reconciliation completed with unresolved items
17    CompletedWithExceptions,
18}
19
20/// Direction of a bank statement line.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
22#[serde(rename_all = "snake_case")]
23pub enum Direction {
24    /// Money coming in (credit to bank)
25    Inflow,
26    /// Money going out (debit to bank)
27    Outflow,
28}
29
30/// Match status for a bank statement line.
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
32#[serde(rename_all = "snake_case")]
33pub enum MatchStatus {
34    /// Not yet matched
35    #[default]
36    Unmatched,
37    /// Auto-matched to a payment/receipt
38    AutoMatched,
39    /// Manually matched
40    ManuallyMatched,
41    /// Bank charge (no matching payment expected)
42    BankCharge,
43    /// Interest (no matching payment expected)
44    Interest,
45}
46
47/// A bank statement line item.
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct BankStatementLine {
50    /// Unique statement line identifier
51    pub line_id: String,
52    /// Bank account ID
53    pub bank_account_id: String,
54    /// Statement date
55    pub statement_date: NaiveDate,
56    /// Value date
57    pub value_date: NaiveDate,
58    /// Transaction amount (positive = inflow, negative = outflow)
59    #[serde(with = "rust_decimal::serde::str")]
60    pub amount: Decimal,
61    /// Direction
62    pub direction: Direction,
63    /// Transaction description from bank
64    pub description: String,
65    /// Bank reference number
66    pub bank_reference: String,
67    /// Match status
68    pub match_status: MatchStatus,
69    /// Matched internal document ID (payment/receipt)
70    pub matched_document_id: Option<String>,
71    /// Company code
72    pub company_code: String,
73}
74
75/// Type of reconciling item.
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
77#[serde(rename_all = "snake_case")]
78pub enum ReconcilingItemType {
79    /// Check written but not yet cleared at bank
80    OutstandingCheck,
81    /// Deposit recorded but not yet credited by bank
82    DepositInTransit,
83    /// Bank charge not yet recorded in books
84    BankCharge,
85    /// Interest earned not yet recorded
86    InterestEarned,
87    /// NSF/returned check
88    ReturnedCheck,
89    /// Error correction
90    ErrorCorrection,
91}
92
93/// A reconciling item that explains the difference between book and bank balance.
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct ReconcilingItem {
96    /// Item identifier
97    pub item_id: String,
98    /// Type of reconciling item
99    pub item_type: ReconcilingItemType,
100    /// Related document ID
101    pub document_id: Option<String>,
102    /// Amount
103    #[serde(with = "rust_decimal::serde::str")]
104    pub amount: Decimal,
105    /// Date of the item
106    pub date: NaiveDate,
107    /// Description
108    pub description: String,
109    /// Expected clearing date
110    pub expected_clearing_date: Option<NaiveDate>,
111}
112
113/// A bank reconciliation for a specific account and period.
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct BankReconciliation {
116    /// Unique reconciliation identifier
117    pub reconciliation_id: String,
118    /// Bank account ID
119    pub bank_account_id: String,
120    /// Company code
121    pub company_code: String,
122    /// Reconciliation date (as-of date)
123    pub reconciliation_date: NaiveDate,
124    /// Status
125    pub status: ReconciliationStatus,
126    /// Bank statement ending balance
127    #[serde(with = "rust_decimal::serde::str")]
128    pub bank_ending_balance: Decimal,
129    /// Book (GL) ending balance
130    #[serde(with = "rust_decimal::serde::str")]
131    pub book_ending_balance: Decimal,
132    /// Bank statement lines for this period
133    pub statement_lines: Vec<BankStatementLine>,
134    /// Reconciling items
135    pub reconciling_items: Vec<ReconcilingItem>,
136    /// Net difference after reconciling items (should be zero)
137    #[serde(with = "rust_decimal::serde::str")]
138    pub net_difference: Decimal,
139    /// Opening bank balance
140    #[serde(with = "rust_decimal::serde::str")]
141    pub opening_balance: Decimal,
142    /// Preparer ID
143    pub preparer_id: String,
144    /// Reviewer ID
145    pub reviewer_id: Option<String>,
146}