#csv #transaction #parser #finance #amount

tktax-transaction

A Rust library for ingesting, parsing, and categorizing transaction data from CSV files. Part of the tktax project.

1 unstable release

new 0.2.2 Feb 1, 2025

#78 in #amount


Used in 13 crates (11 directly)

MIT/Apache

200KB
2.5K SLoC

tktax-transaction

tktax-transaction is a Rust library dedicated to parsing and categorizing bank transaction data in CSV format. It leverages serde for deserialization, supports multiple CSV schema variants, and provides a type-safe interface for representing monetary values, transaction types, dates, and more. This crate is part of the tktax project, aiming to unify financial data ingestion with robust, production-grade Rust paradigms.


Features

  1. Structured Transaction Model

    • The Transaction struct unifies fields found in diverse CSV exports, accommodating differences in column naming and optional fields.
  2. Comprehensive CSV Deserialization

    • Uses ReaderBuilder from the csv crate with trimming, flexible column counts, and varied record terminators.
    • Includes TryFromCsvContents trait to parse raw CSV bytes into typed transaction lists.
    • Advanced date deserialization via serde ensures consistent date handling.
  3. Typed Monetary Amounts

    • Monetary operations use a dedicated MonetaryAmount type to eliminate stringly-typed pitfalls.
    • Negative values and currency formats are safely parsed.
  4. Transaction Categorization

    • Extensible category prediction (CategorizeTransaction) with domain-specific categories (TxCat: TransactionCategory).
    • Facilitates machine-aided classification via transaction descriptions, suitable for budgeting or analytics.
  5. Edition 2024

    • Exploits the latest Rust language edition to deliver advanced trait, macro, and library features.

Usage

Add tktax-transaction to your Cargo.toml:

[dependencies]
tktax-transaction = "0.1.0"

Import and parse CSV contents:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    use tktax_transaction::TryFromCsvContents;

    // Acquire CSV data (for example, from a file or network stream).
    let csv_data = b"Date,Transaction Type,Check/Serial #,Description,Amount\n\
                     01/12/2023,Debit,,PAYMENT GAS DEBIT,($14.93)\n\
                     01/17/2023,Deposit,0,DEPOSIT,$400\n";

    // Parse into a list of typed Transaction values
    let transactions = Vec::<tktax_transaction::Transaction>::try_from_csv_contents(csv_data)?;

    // Iterate, display, or categorize transactions
    for txn in &transactions {
        println!("{}", txn); 
    }

    Ok(())
}

The library automatically handles multiple CSV layouts by employing untagged enums (TransactionInner). Optional columns (e.g., daily posted balances) are also correctly identified.


Example: Categorizing Transactions

use tktax_transaction::{
    Transaction,
    CategorizeTransaction,
    TransactionCategory,
    CategoryMap,
    TransactionCategoryPrediction
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExampleCategory {
    Utilities,
    Deposit,
    Food,
    Misc,
}

impl TransactionCategory for ExampleCategory {
    fn name(&self) -> &str {
        match self {
            Self::Utilities => "Utilities",
            Self::Deposit   => "Deposit",
            Self::Food      => "Food",
            Self::Misc      => "Misc",
        }
    }
}

fn categorize_txns(transactions: &[Transaction]) {
    // Construct a CategoryMap for demonstration
    let mut category_map = CategoryMap::default();
    // Populate category_map with known descriptors, patterns, etc.

    for txn in transactions {
        let guesses = txn.categorize(&category_map);
        println!("Predicted Categories for Txn: {:?}", guesses);
    }
}

This approach yields type-safe predictions and helps unify classification logic across different consumers.


Error Handling

All potential CSV parsing or deserialization failures use the ParseCsvError enum (CsvError variant for direct integration with csv::Error). This eliminates ambiguous string-based errors and provides a structured mechanism for handling I/O or schema mismatches gracefully.


Testing

Unit tests (#[cfg(test)]) are included, verifying compatibility with CSV files across different variations. Each test confirms successful deserialization of transactions with or without additional columns.


Contributing

Contributions that extend transaction classification or improve CSV-compatibility are welcome. File an issue or open a pull request in the main tktax repository.


License

This library is available under the terms of the MIT License or the Apache License (Version 2.0).

  • Choose whichever suits your project’s licensing requirements.

Contact

Enjoy building robust financial ingestion systems with tktax-transaction!

Dependencies

~26–37MB
~642K SLoC