Skip to content

Repository files navigation

Python Ledger (Hexagonal Architecture & CQRS)

This is an asynchronous, high-integrity Financial Ledger microservice developed in Python using FastAPI, SQLAlchemy, and PostgreSQL. The architecture of this project is strongly based on the principles of Hexagonal Architecture (Ports & Adapters) and CQRS, porting the solid concepts from the original Rust project.


🏛️ Architectural Design

This project follows a strict division of responsibilities to keep the core business rules (Domain) 100% isolated from external technologies (such as web frameworks, database drivers, or ORMs).

graph TD
    subgraph Presentation Layer [Inbound Ports / Presentation]
        A[FastAPI Controllers] -->|DTOs| B[Application Ports]
    end

    subgraph Core Domain & Application [The Hexagon]
        B --> C[Use Cases - Commands]
        B --> D[Queries - Read]
        C --> E[Domain Entities & Value Objects]
        D --> E
    end

    subgraph Infrastructure Layer [Outbound Ports / Infrastructure]
        C -->|Port Contracts| F[PostgresLedgerRepo Adapter]
        D -->|Port Contracts| F
        F -->|SQLAlchemy| G[(PostgreSQL Database)]
    end
Loading

1. CQRS Separation (Command Query Responsibility Segregation)

The data flow is cleanly segregated between write operations (Commands) and read operations (Queries):

  • Command Side (Write): Represented by the TransferUseCase, focused on validating double-entry bookkeeping rules, ensuring idempotency, and persisting new states.
  • Query Side (Read): Represented by GetBalanceQuery and GetStatementQuery, responsible for fetching aggregated states efficiently directly from the database.

2. Layers of the Hexagon

  • Domain (domain/): Contains pure domain entities (Transaction, EntryLine), Value Objects (AccountId, TransactionId), and math/balancing validations (where debits must equal credits). No external dependencies are imported here.
  • Application (application/): Contains the orchestration of use cases, error handling, and the definition of abstract interface contracts (Ports / ABCs).
  • Infrastructure (infrastructure/): The database adapter implementing the application contracts using asynchronous PostgreSQL.
  • Presentation (presentation/): Inbound HTTP adapter managed by FastAPI that translates JSON payloads into system objects and formats HTTP responses.

🚀 Quick Start

1. Prerequisites

  • Python 3.12+ (for native uuid.uuid7 support)
  • Docker and Docker Compose installed

2. Installation and Virtualenv Creation

Create and activate an isolated virtual environment for the application:

python3 -m venv venv
source venv/bin/activate

Install the dependencies listed in requirements.txt:

pip install -r requirements.txt

3. Spin Up the Database (Docker Compose)

To start the PostgreSQL instance configured in compose.yml, run:

docker compose up -d

4. Configure Environment Variables

Make sure the .env file is present in the python-ledger/ folder with the connection URL:

cp .env.example .env

5. Start the Server

With the database up and the virtualenv active, start the application:

python3 main.py

The API will be available at http://localhost:3000.


🧪 Automated Tests

The project has a suite of unit tests located in tests/test_ledger.py that validate transaction business rules and use case flows using repository mocks.

To run the tests, activate your virtual environment and run the command below in the python-ledger/ root folder:

PYTHONPATH=. pytest

About

Ledger built with Python and FastAPI, with hexagonal architecture.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages