Skip to content

Data Model

Entity-Relationship Diagram (Database / ORM)

👉 Persistence-oriented

erDiagram
    PORTFOLIO ||--o{ ASSET : owns
    PORTFOLIO ||--o{ PORTFOLIO_SNAPSHOT : "has (auto-calculated)"

    ASSET ||--o{ TRANSACTION : has
    ASSET ||--o{ ASSET_SNAPSHOT : "has (manually entered)"
    ASSET }o--|| ASSET_TYPE : "typed as"
    ASSET }o--o{ ASSET_CATEGORY : ""
    ASSET_CATEGORY }o--|| CATEGORY : ""
    ASSET }o--o{ ASSET_TAG : ""
    ASSET_TAG }o--|| TAG : ""

    PORTFOLIO {
        uuid id PK
        string name
        string base_currency
        datetime created_at
        datetime updated_at
    }

    PORTFOLIO_SNAPSHOT {
        uuid id PK
        uuid portfolio_id FK
        decimal value
        datetime observed_at
    }

    ASSET {
        uuid id PK
        uuid portfolio_id FK
        uuid asset_type_id FK
        string name
        decimal quantity
        boolean disposed
        datetime created_at
        datetime updated_at
        string created_by
        string updated_by
    }

    ASSET_SNAPSHOT {
        uuid id PK
        uuid asset_id FK
        decimal value
        datetime observed_at
    }

    TRANSACTION {
        uuid id PK
        uuid asset_id FK
        string type
        decimal unit_price
        decimal quantity
        string currency
        datetime occurred_at
    }

    ASSET_TYPE {
        uuid id PK
        string code UK
        string label
        datetime created_at
        datetime updated_at
    }

    CATEGORY {
        uuid id PK
        string name UK
        uuid parent_id FK
    }

    TAG {
        uuid id PK
        string name UK
    }

    ASSET_CATEGORY {
        uuid asset_id FK
        uuid category_id FK
    }

    ASSET_TAG {
        uuid asset_id FK
        uuid tag_id FK
    }

Conceptual Data Model

👉 Behavior-oriented

classDiagram

    class Portfolio {
        +id: UUID
        +name: str
        +base_currency: str
        +assets: List[Asset]
        +snapshots: List[PortfolioSnapshot]

        +total_value(at: datetime): Decimal
        +take_snapshot(at: datetime): PortfolioSnapshot
        +get_currency(): str
    }

    class AssetType {
        +id: UUID
        +code: str
        +label: str
    }

    class Category {
        +id: UUID
        +name: str
        +parent: Category?

        +get_hierarchy(): List[Category]
        +get_all_assets(): List[Asset]
    }

    class Asset {
        +id: UUID
        +name: str
        +asset_type: AssetType
        +portfolio: Portfolio
        +categories: Set[Category]
        +quantity: Decimal?
        +disposed: bool
        +created_at: datetime
        +updated_at: datetime
        +created_by: str
        +updated_by: str

        +transactions: List[Transaction]
        +snapshots: List[AssetSnapshot]
        +tags: Set[Tag]

        +current_value(at: datetime): Decimal
        +get_currency(): str
        +dispose(at: datetime): void
        +add_category(category: Category): void
        +remove_category(category: Category): void
    }

    class Transaction {
        +id: UUID
        +type: str
        +quantity: Decimal
        +unit_price: Decimal
        +currency: str
        +occurred_at: datetime
    }

    class AssetSnapshot {
        +id: UUID
        +value: Decimal
        +observed_at: datetime

        +get_currency(): str
    }

    class PortfolioSnapshot {
        +id: UUID
        +value: Decimal
        +observed_at: datetime

        +get_currency(): str
    }

    class Tag {
        +id: UUID
        +name: str
    }

    Portfolio "1" --> "*" Asset : owns
    Portfolio "1" --> "*" PortfolioSnapshot : tracks
    Asset "*" --> "1" AssetType : typed_as
    Asset "*" --> "1" Portfolio : belongs_to
    Asset "*" --> "*" Category : categorized_as
    Asset "1" --> "*" Transaction : has
    Asset "1" --> "*" AssetSnapshot : has
    Asset "*" --> "*" Tag : tagged_with
    Category "1" --> "*" Category : parent_of

Transaction Types

  • ACQUIRE: Buying/receiving an asset (increases quantity)
  • DISPOSE: Selling/giving away an asset (decreases quantity)
  • ADJUST: Manual correction/adjustment