use chrono::NaiveDate;
use rust_decimal::Decimal;
#[derive(Debug, thiserror::Error)]
pub enum CamtError {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("Zip error: {0}")]
Zip(#[from] zip::result::ZipError),
#[error("Failed to parse camt.053 XML: {0}")]
Xml(#[from] quick_xml::DeError),
#[error("Failed to write camt.053 XML: {0}")]
XmlWrite(#[from] quick_xml::SeError),
#[error(
"Failed to parse camt.053 XML at line {line}, column {column} (byte {position}): {source}\n... {snippet} ..."
)]
XmlAt {
source: quick_xml::DeError,
position: u64,
line: usize,
column: usize,
snippet: String,
},
#[error("Statement has no account identification (neither IBAN nor Othr)")]
MissingIdentification,
#[error("Statement for account {account} has no {kind} balance")]
MissingBalance {
account: String,
kind: &'static str,
},
#[error("Invalid date: neither Dt nor DtTm is present")]
MissingDate,
#[error("Invalid DtTm date prefix: {0}")]
InvalidDateTime(String),
#[error("Entry for account {account} has no transaction details to derive a description from")]
MissingTransactionDetails {
account: String,
},
#[error("Entry for account {account} has {count} transaction detail(s), expected exactly one")]
UnexpectedTransactionDetailsCount {
account: String,
count: usize,
},
#[error(
"Overlapping camt.053 statements for account {account}: one closes on {prev_closing} \
but the next opens on {next_opening}"
)]
OverlappingStatements {
account: String,
prev_closing: NaiveDate,
next_opening: NaiveDate,
},
#[error(
"Balance gap in camt.053 statements for account {account}: closing balance {prev_closing_amount:.2} \
on {prev_closing_date} does not match opening balance {next_opening_amount:.2} on {next_opening_date}"
)]
BalanceGap {
account: String,
prev_closing_date: NaiveDate,
prev_closing_amount: Decimal,
next_opening_date: NaiveDate,
next_opening_amount: Decimal,
},
#[error(
"Currency mismatch in camt.053 statements for account {account}: previous statement has currency {prev_currency:?} \
but next statement has currency {next_currency:?}"
)]
CurrencyMismatch {
account: String,
prev_currency: Option<String>,
next_currency: Option<String>,
},
#[error(
"Inconsistent camt.053 statement for account {account}: opening balance {opening_amount:.2} on {opening_date} \
does not match closing balance {closing_amount:.2} on {closing_date}, with a transaction sum of {transaction_sum:.2}"
)]
InconsistentStatement {
account: String,
opening_date: NaiveDate,
opening_amount: Decimal,
closing_date: NaiveDate,
closing_amount: Decimal,
transaction_sum: Decimal,
},
}