1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4pub use use_ach as ach;
12pub use use_amount as amount;
13pub use use_bai2 as bai2;
14pub use use_bank_account as bank_account;
15pub use use_bic as bic;
16pub use use_currency as currency;
17pub use use_iban as iban;
18pub use use_invoice as invoice;
19pub use use_ledger as ledger;
20pub use use_money as money;
21pub use use_payment as payment;
22pub use use_receipt as receipt;
23pub use use_reconciliation as reconciliation;
24pub use use_routing_number as routing_number;
25pub use use_transaction as transaction;
26
27pub mod prelude {
29 pub use crate::ach::{
30 AchAccountType, AchAddendaIndicator, AchCompanyId, AchEntry, AchEntryDirection, AchError,
31 AchIndividualId, AchStandardEntryClass, AchTraceNumber, AchTransactionCode,
32 };
33 pub use crate::amount::{Amount, AmountError};
34 pub use crate::bai2::{
35 AccountIdentifierRecord, Bai2Error, FileHeaderRecord, FileTrailerRecord, FundsTypeCode,
36 NormalizedTransaction, RawRecord, RecordCode, TransactionDetailRecord, TransactionTypeCode,
37 };
38 pub use crate::bank_account::{
39 AccountHolderName, AccountNumber, AccountType, BankAccount, MaskedAccountNumber,
40 };
41 pub use crate::bic::{Bic, BicError};
42 pub use crate::currency::{AUD, CAD, CurrencyCode, CurrencyCodeError, EUR, GBP, JPY, USD};
43 pub use crate::iban::{Iban, IbanError};
44 pub use crate::invoice::{
45 BalanceDue, DueDate, Invoice, InvoiceLine, InvoiceNumber, InvoiceStatus, Subtotal, Total,
46 };
47 pub use crate::ledger::{Balance, DebitCredit, JournalEntry, LedgerEntry, Posting};
48 pub use crate::money::{CurrencyMismatch, Money, MoneyError};
49 pub use crate::payment::{
50 Payment, PaymentDirection, PaymentMethod, PaymentReference, PaymentStatus,
51 };
52 pub use crate::receipt::{
53 AppliedAmount, Receipt, ReceiptNumber, ReceiptStatus, ReceivedAt, UnappliedAmount,
54 };
55 pub use crate::reconciliation::{
56 ExceptionReason, MatchConfidence, MatchScore, MatchStatus, ReconciliationCandidate,
57 ReconciliationResult,
58 };
59 pub use crate::routing_number::{RoutingNumber, RoutingNumberError};
60 pub use crate::transaction::{
61 EffectiveDate, PostedDate, Transaction, TransactionDate, TransactionDirection,
62 TransactionId, TransactionStatus,
63 };
64}
65
66#[cfg(test)]
67mod tests {
68 use super::{ach, amount, bai2, bic, currency, iban, money, reconciliation, routing_number};
69
70 #[test]
71 fn facade_exposes_composable_finance_primitives() -> Result<(), Box<dyn std::error::Error>> {
72 let usd = currency::CurrencyCode::new("USD")?;
73 let cents = amount::Amount::from_minor_units(12_345, 2)?;
74 let invoice_total = money::Money::new(cents, usd);
75
76 let routing = routing_number::RoutingNumber::new("021000021")?;
77 assert_eq!(routing.as_str(), "021000021");
78
79 let iban = iban::Iban::new("GB82 WEST 1234 5698 7654 32")?;
80 let bic = bic::Bic::new("DEUTDEFF500")?;
81 let ach_entry = ach::AchEntry::new(
82 ach::AchStandardEntryClass::Ppd,
83 ach::AchTransactionCode::CheckingCredit,
84 ach::AchTraceNumber::new("123456780000001")?,
85 ach::AchCompanyId::new("1234567890")?,
86 ach::AchIndividualId::new("EMPLOYEE001")?,
87 );
88
89 let records =
90 bai2::parse_logical_records("16,475,12345,Z,bank-ref,customer-ref,invoice payment/\n")?;
91 let detail = bai2::TransactionDetailRecord::try_from(&records[0])?;
92 let normalized = bai2::NormalizedTransaction::from_detail(&detail)?;
93
94 let candidate = reconciliation::ReconciliationCandidate::new(
95 "bank-ref",
96 "invoice-1001",
97 amount::Amount::zero(2)?,
98 reconciliation::MatchScore::exact(),
99 )?;
100
101 assert_eq!(invoice_total.currency().as_str(), "USD");
102 assert_eq!(iban.country_code(), "GB");
103 assert_eq!(bic.country_code(), "DE");
104 assert_eq!(
105 ach_entry.transaction_code().direction(),
106 ach::AchEntryDirection::Credit
107 );
108 assert_eq!(normalized.amount().minor_units(), 12_345);
109 assert_eq!(candidate.score(), reconciliation::MatchScore::exact());
110 Ok(())
111 }
112}