Skip to content

Architecture

Overview

Portfolio Manager uses a layered Model-View-Controller (MVC) architecture augmented with a Service Layer for business logic and a Repository Layer for data access. This separation ensures views contain no business logic and all SQL is confined to repositories.

graph TD
    subgraph "Presentation Layer"
        V1[DashboardView]
        V2[SessionView]
        V3[ProjectView]
        V4[MilestoneView]
        V5[WeeklyReviewView]
        V6[SettingsView]
    end

    subgraph "Controller Layer"
        C1[DashboardController]
        C2[SessionController]
        C3[ProjectController]
        C4[MilestoneController]
        C5[ReviewController]
        C6[SettingsController]
    end

    subgraph "Service Layer"
        S1[ProjectService]
        S2[SessionService]
        S3[ScoringService]
        S4[PlanService]
        S5[WeekService]
    end

    subgraph "Repository Layer"
        R1[ProjectRepository]
        R2[SessionRepository]
        R3[MilestoneRepository]
        R4[ReviewRepository]
        R5[ScoreRepository]
    end

    subgraph "Infrastructure"
        DB[(SQLite Database)]
        LOG[Logger]
        CFG[Config / Settings]
        BUS[EventBus]
    end

    V1 --> C1
    V2 --> C2
    V3 --> C3
    V4 --> C4
    V5 --> C5
    V6 --> C6

    C1 --> S1
    C1 --> S3
    C2 --> S2
    C3 --> S1
    C3 --> S4
    C4 --> R3
    C5 --> R4
    C6 --> CFG

    S1 --> R1
    S2 --> R2
    S3 --> R2
    S3 --> R3
    S3 --> R5
    S4 --> R1
    S5 -.-> BUS

    R1 --> DB
    R2 --> DB
    R3 --> DB
    R4 --> DB
    R5 --> DB

Layer Responsibilities

Layer Responsibility
Views Render Tkinter widgets; fire user events; call controller methods
Controllers Translate UI actions to service calls; bind views to event bus
Services Enforce business rules; orchestrate repositories; emit domain events
Repositories Execute SQL; map rows to domain objects; enforce transaction boundaries
Infrastructure Singleton DB connection; logging setup; TOML config; event bus

Application Startup Sequence

sequenceDiagram
    participant L as launch.sh
    participant A as app.py
    participant CFG as Settings
    participant DB as DatabaseConnection
    participant MIG as migrations.py
    participant GUI as MainWindow

    L->>A: python -m portfolio_manager
    A->>CFG: load_settings()
    CFG-->>A: Settings object (or defaults)
    A->>DB: DatabaseConnection.initialise(path)
    DB-->>A: connection ready
    A->>MIG: run_migrations(db)
    MIG-->>A: schema up to date
    A->>GUI: build MainWindow(controllers)
    GUI->>GUI: DashboardView.refresh()
    GUI-->>A: Tk mainloop

Project Lifecycle

stateDiagram-v2
    [*] --> Active : create project
    Active --> Backlog : deprioritize
    Backlog --> Active : reactivate
    Active --> Archive : complete or stop
    Backlog --> Archive : abandon
    Archive --> [*] : read-only history

Session Lifecycle

stateDiagram-v2
    [*] --> Backlog : create session
    Backlog --> Planned : plan
    Planned --> Doing : start
    Doing --> Done : complete
    Planned --> Done : mark done
    Backlog --> Cancelled : cancel
    Planned --> Cancelled : cancel
    Doing --> Cancelled : cancel
    Done --> [*] : archived with project
    Cancelled --> [*] : delete

Milestone Lifecycle

stateDiagram-v2
    [*] --> Backlog : create milestone
    Backlog --> Planned : plan
    Planned --> Doing : start work
    Doing --> Done : complete
    Planned --> Done : mark done directly
    Backlog --> Cancelled : cancel
    Planned --> Cancelled : cancel
    Doing --> Cancelled : cancel
    Done --> [*] : (remains in history)

Source Structure

src/portfolio_manager/
├── __main__.py          # python -m portfolio_manager entry point
├── app.py               # Bootstrap: wires all layers, returns MainWindow
├── exceptions.py        # Custom exception hierarchy
│
├── config/
│   └── settings.py      # Settings dataclass + TOML loader
│
├── db/
│   ├── connection.py    # Singleton DatabaseConnection
│   ├── migrations.py    # Versioned migration runner
│   └── schema.sql       # Initial DDL
│
├── models/              # Dataclass domain objects (no DB logic)
├── repositories/        # SQL access (one per entity)
├── services/            # Business logic (one per domain)
├── controllers/         # UI ↔ service mediation
├── views/               # Tkinter frames and widgets
├── events/              # EventBus (Observer pattern)
└── utils/               # Date helpers, logging setup