A production-grade, cryptographically secure, and pure Python double-entry accounting engine for automated financial reporting, multi-currency ledger management, cost centers, sub-ledger analytics, and multi-entity consolidation.
Taraz (imported as taraz) is a robust, zero-dependency Python library designed to serve as the core accounting and financial engineering infrastructure for enterprise applications.
With the release of v1.0.0, Taraz matures into a stable, production-ready ledger kernel. It implements high-precision mathematics with Python's native Decimal to eliminate floating-point rounding bugs, and encapsulates advanced sub-ledger functionalities like perpetual inventory costing, invoice matching, year-end currency revaluation, and group consolidations. Additionally, it guarantees audit-trail integrity through automated sequence gap-checking, abnormal balance detection, and SHA-256 cryptographic chain verification.
Taraz was developed incrementally, adding advanced accounting, managerial, and forensic features while preserving full backward compatibility.
- Introduced basic double-entry bookkeeping entities:
AccountType,Account,Posting, andJournalEntry. - Enforced standard balancing rules (sum of normalized debits must equal credits).
- Implemented basic trial balance and account balance lookups.
- Added support for hierarchical charts of accounts (General, Ledger, Sub-ledger, and Subsidiary levels).
- Enabled automatic recursive balance rollups from child accounts to parent accounts without double-counting.
- Introduced a clean, fluent transaction builder (
engine.new_entry().debit().credit().post()) for ease of typing.
- Added standard liquidity and leverage metrics as native engine properties (
working_capital,current_ratio,quick_ratio,debt_to_equity_ratio). - Introduced period locking (
set_lock_date) to prevent tampering or back-posting into closed books.
- Introduced Cost Centers (
cost_center) to track expenses and revenues by projects or departments. - Enabled segmented P&L generation (department-wise Income Statements).
- Integrated automated value-added tax (VAT) split posting utilities inside the fluent builder.
- Added native Multi-Currency support, translating foreign currency transactions into the base ledger currency on the fly.
- Implemented Red Storno Reversals to legally offset incorrect transactions with negative values instead of inflating turnover volume.
- Introduced unique posting IDs and matching states (
reconciled) for bank statement matching. - Added Accounts Receivable (A/R) Aging Reports grouping outstanding balances into
0-30,31-60,61-90, and90+day brackets. - Integrated sequential document numbering verification to scan for gaps in transaction ranges.
- Added transaction Tagging (
tags) to filter balances and reports by arbitrary projects or campaigns. - Introduced budget management and automatic Variance Analysis detecting Favorable (F) and Unfavorable (UF) performance on revenues and expenses.
- Created recurring entry templates to quickly duplicate common operations.
- Added advanced corporate finance metrics: Net Present Value (NPV), Internal Rate of Return (IRR), WACC, Loan Amortization Schedule generator, and SL/DDB Depreciation methods.
- Built GUI tree structure bridges converting hierarchical charts of accounts (COA) into JSON-ready tree representations suitable for PyQt/PySide
QTreeViewor Tkinterttk.Treeview. - Lazily integrated Matplotlib figure generators to easily embed charts inside desktop screens.
- Introduced an independent perpetual Inventory Valuation Engine supporting FIFO, LIFO, and WAVCO (Weighted Average Cost) methods.
- Integrated an automated Statement of Cash Flows (Operating, Investing, Financing activities) based on double-entry balance sheet sheet migrations.
- Introduced Invoice-to-Payment Clearing allowing developers to match cash postings against outstanding invoice postings.
- Added automated end-of-period Forex Revaluation adjusting currency balances at a target year-end rate and offsetting variances to Exchange Gain/Loss.
- Created the
LedgerConsolidatorengine to aggregate independent branch ledgers into a consolidated parent entity.
- Enforced SHA-256 Cryptographic Immutability on the journal ledger. Every transaction stores its own hash combined with the hash of the preceding entry, making any manual database tampering instantly detectable via
.verify_ledger_cryptographically(). - Redesigned financial reports to align with official IFRS (IAS 1) standards, distinguishing Current vs Non-Current assets and liabilities.
- Built a robust Bulk CSV Importer to easily ingest transaction tables from other systems (Odoo, ERP systems, Excel templates).
pip install tarazRequires Python 3.8+
All exceptions thrown by Taraz inherit from a structured, clean exceptions tree:
import taraz
from taraz.engine import UnbalancedEntryError, LockedPeriodError
engine = taraz.AccountingEngine()
try:
# Attempting to post an unbalanced entry
engine.new_entry("TXN-01", "Imbalanced") \
.debit("1001", 100) \
.credit("4001", 50) \
.post()
except UnbalancedEntryError as e:
print(f"Post failed: {e}")Taraz provides a chainable API to speed up manual transaction coding.
from taraz import AccountingEngine, AccountType
engine = AccountingEngine()
# Register Accounts
engine.register_account("1001", "Bank Cash Account", AccountType.ASSET, is_current=True)
engine.register_account("4001", "Sales Revenue", AccountType.REVENUE)
# Record a transaction using the chainable fluent builder API
engine.new_entry("TXN-001", "SaaS License Sale") \
.debit("1001", "1500.00") \
.credit("4001", "1500.00") \
.post()
# Verify balance
print(engine.get_account_balance("1001")) # Output: 1500.00Track parent-child relationships easily. When querying a parent account, Taraz automatically gathers and summarizes all child account balances dynamically.
from taraz import AccountingEngine, AccountType
engine = AccountingEngine()
# Parent Asset account
engine.register_account("1000", "Total Assets", AccountType.ASSET)
# Child Accounts (inherits Asset type from parent)
engine.register_account("1001", "Bank cash", AccountType.ASSET, parent_code="1000")
engine.register_account("1002", "Petty cash", AccountType.ASSET, parent_code="1000")
# Post a debit to petty cash
engine.new_entry("TXN-001", "Replenish petty cash") \
.debit("1002", "200.00") \
.credit("1001", "200.00") \
.post()
# Query parent account balance - it automatically sums up child balances!
print(engine.get_account_balance("1000")) # Output: 0.00 (Total assets didn't change, cash moved within children)Generate IFRS-compliant reports classified under Current vs Non-Current listings automatically.
from taraz import AccountingEngine, AccountType
engine = AccountingEngine()
# Register IFRS-tagged accounts
engine.register_account("1001", "Cash at Bank", AccountType.ASSET, is_current=True)
engine.register_account("1500", "Warehouse Property", AccountType.ASSET, is_current=False)
engine.register_account("2001", "Accounts Payable", AccountType.LIABILITY, is_current=True)
engine.register_account("3000", "Capital Equity", AccountType.EQUITY)
# Post Investment
engine.new_entry("TXN-01", "Equity Funding") \
.debit("1001", "10000.00") \
.credit("3000", "10000.00") \
.post()
# Generate the Structured IFRS Balance Sheet
balance_sheet = engine.generate_balance_sheet()
print(balance_sheet["total_current_assets"]) # Output: 10000.00
print(balance_sheet["total_non_current_assets"]) # Output: 0.00
print(balance_sheet["is_balanced"]) # Output: TrueMonitor departmental profitability and compare actual performance against predefined budget boundaries.
from taraz import AccountingEngine, AccountType
from datetime import datetime
engine = AccountingEngine()
engine.register_account("1001", "Bank", AccountType.ASSET)
engine.register_account("5001", "Advertising Costs", AccountType.EXPENSE)
# Set budget bounds for marketing
start_date = datetime(2026, 1, 1)
end_date = datetime(2026, 1, 31)
engine.set_budget("5001", "500.00", start_date, end_date)
# Record actual expense associated with Marketing department cost center
engine.new_entry("ADV-JAN", "Google Ad campaign", date=datetime(2026, 1, 15)) \
.debit("5001", "600.00", cost_center="MKT-DEPT") \
.credit("1001", "600.00") \
.post()
# Perform Variance Analysis
report = engine.get_budget_variance("5001", start_date, end_date)
print(report["variance"]) # Output: 100.00
print(report["status"]) # Output: "Unfavorable" (spent more than budgeted)Record transactions in arbitrary currencies. Taraz automatically evaluates balances and recalculates assets based on new rates in closed periods.
from taraz import AccountingEngine, AccountType
engine = AccountingEngine()
engine.register_account("1001", "Bank EUR Account", AccountType.ASSET)
engine.register_account("4001", "Revenue", AccountType.REVENUE)
engine.register_account("8001", "Exchange Gain/Loss", AccountType.REVENUE) # Normal Credit
# Received 1000 EUR @ 1.10 rate = $1100 historical base value
engine.new_entry("TXN-EUR", "European invoice payment") \
.debit("1001", "1000.00", currency="EUR", exchange_rate="1.10") \
.credit("4001", "1100.00") \
.post()
# At year-end, the EUR exchange rate increases to 1.15. Revalue!
engine.revalue_currency_account(
account_code="1001",
target_currency="EUR",
current_rate="1.15",
gain_loss_account_code="8001",
entry_id="YREND-REVAL"
)
# Valuation must now reflect current exchange rates
print(engine.get_account_balance("1001")) # Output: 1150.00
print(engine.get_account_balance("8001")) # Output: 50.00 (Gain recognized)Match cash payment postings against target invoice postings.
from taraz import AccountingEngine, AccountType
engine = AccountingEngine()
engine.register_account("1200", "Receivables", AccountType.ASSET)
engine.register_account("1001", "Bank", AccountType.ASSET)
engine.register_account("4001", "Revenue", AccountType.REVENUE)
# 1. Post Sale Invoice
inv_entry = engine.new_entry("INV-01", "Invoice 1") \
.debit("1200", "500.00") \
.credit("4001", "500.00") \
.post()
invoice_posting_id = inv_entry.postings[0].posting_id
# 2. Post Cash Receipt
pay_entry = engine.new_entry("PAY-01", "Partial Payment") \
.debit("1001", "300.00") \
.credit("1200", "300.00") \
.post()
payment_posting_id = pay_entry.postings[1].posting_id
# Match postings (clear partial payment against invoice)
engine.match_postings(invoice_posting_id, payment_posting_id, "300.00")
# Check remaining unmatched amount on invoice
print(engine.get_unmatched_amount(invoice_posting_id)) # Output: 200.00The separate valuation module manages inventory costing methods natively.
from taraz import InventoryValuationEngine
inv = InventoryValuationEngine()
# Buy Batch 1: 10 units @ $10.00
inv.record_purchase("SKU-PRO", 10, "10.00")
# Buy Batch 2: 10 units @ $15.00
inv.record_purchase("SKU-PRO", 10, "15.00")
# Sell 12 units using FIFO method
cogs, ending_value = inv.record_sale("SKU-PRO", 12, method="FIFO")
# FIFO logic consumes: 10 units @ 10 + 2 units @ 15 = $130
print(cogs) # Output: 130.00
print(ending_value) # Output: 120.00 (8 remaining units @ 15)Prevent SQL tampering or back-posting.
from taraz import AccountingEngine, AccountType
engine = AccountingEngine()
engine.register_account("1001", "Bank", AccountType.ASSET)
engine.register_account("4001", "Revenue", AccountType.REVENUE)
# Post genuine transaction
engine.new_entry("INV-1", "Genuine Sale").debit("1001", 100).credit("4001", 100).post()
# Verify cryptographic ledger state
print(engine.verify_ledger_cryptographically()) # Output: True
# Malicious modification bypassing the engine
engine.journal[0].postings[0].debit = 9999.00
# Verification fails instantly!
print(engine.verify_ledger_cryptographically()) # Output: FalseEasily import historical data and consolidate group companies.
from taraz import AccountingEngine, LedgerConsolidator, DevUtils
# Import transactions from a standard formatted CSV file
engine_subsidiary = AccountingEngine()
engine_subsidiary.register_account("1001", "Bank USD", taraz.AccountType.ASSET)
engine_subsidiary.register_account("4001", "Revenue", taraz.AccountType.REVENUE)
DevUtils.import_journal_from_csv(engine_subsidiary, "historical_data.csv")
# Consolidate multiple corporate entities into a parent ledger
engine_parent = AccountingEngine()
consolidated_engine = LedgerConsolidator.consolidate([engine_subsidiary], parent_engine=engine_parent)Taraz ships with a robust unit testing suite covering all accounting, analytics, and cryptographic functionalities:
python -m unittest tests/test_taraz.pyAli Kamrani
- GitHub: @MRThugh
- Email: kamrani.exe@gmail.com
This project is licensed under the MIT License. You are free to copy, modify, and distribute Taraz in your commercial or open-source products.
Taraz β High-precision cryptographic accounting infrastructure for Python developers. π