Skip to content

Models

domain.report.models

Summary

Report domain models: snapshot query, cube series, and API response.


Pure models plus date/period helpers consumed by the report service. Functions here are side-effect free; they only parse, normalize, and validate report definitions and period labels.

Classes

Report

Bases: BaseModel

API response for a sliced report view.

Attributes:

Name Type Description
id str

Snapshot ID the view was served from.

name str

Snapshot name.

query ReportQuery

Normalized query the snapshot was built from.

generated_at str

ISO-8601 timestamp of cube generation.

created_at str

ISO-8601 timestamp of snapshot creation.

flow str

Flow the view was sliced to.

granularities List[str]

Granularities present in the view.

period_ids List[str]

All period IDs available, sorted chronologically.

payees List[str]

Every payee present in the cube.

tags List[str]

Every tag path present in the cube.

buckets List[ReportBucket]

Buckets forming the sliced view.

ReportBucket

Bases: BaseModel

A flow x group-dimension slice of a report, keyed per granularity.

Attributes:

Name Type Description
flow str

Flow this bucket covers, e.g. "inflows".

group_key Dict[str, List[str]]

Dimension filters defining the bucket.

series Dict[str, List[ReportPeriod]]

Periods per granularity.

ReportMetrics

Bases: BaseModel

Aggregated metrics over a slice of transactions.

Attributes:

Name Type Description
outflows float

Sum of absolute negative amounts.

inflows float

Sum of positive amounts.

sum float

Net total of all amounts.

count int

Number of transactions contributing amounts.

avg float

Mean transaction amount.

min float

Minimum transaction amount.

max float

Maximum transaction amount.

first_date Optional[str]

Earliest transaction date, DD-MM-YYYY.

last_date Optional[str]

Latest transaction date, DD-MM-YYYY.

cadence Optional[float]

Mean gap in days between consecutive dates.

frequency Optional[float]

Frequency per day derived from cadence.

ReportPeriod

Bases: BaseModel

One period slice of a cube level: metrics plus the contributing transactions.

Attributes:

Name Type Description
period_id str

Canonical period label.

start Optional[str]

Inclusive ISO start boundary.

end Optional[str]

Exclusive ISO end boundary.

metrics ReportMetrics

Aggregated metrics for the period.

txns List[Any]

Transactions contributing to the period.

ReportQuery

Bases: BaseModel

Definition of a report snapshot. Bounds the data set; dimensions are sliced at read time.

Attributes:

Name Type Description
name str

Snapshot name; empty for an auto-generated name.

granularities List[str]

Granularities to precompute in the cube.

group_dims List[str]

Dimensions to group by, e.g. "payee", "tag".

flow str

Flow filter: inflows, outflows, or both.

accounts Optional[List[str]]

Account names to include; all when None.

ignore_self bool

Exclude self-transfer tagged expenses.

start_date str

Inclusive start boundary, DD-MM-YYYY.

end_date str

Inclusive end boundary, DD-MM-YYYY.

min_amount Optional[float]

Minimum absolute amount to include.

max_amount Optional[float]

Maximum absolute amount to include.

ReportSnapshot

Bases: BaseModel

Stored metadata for a precomputed report cube.

Attributes:

Name Type Description
name str

Snapshot name.

query ReportQuery

Normalized query the cube was built from.

signature str

Canonical fingerprint of the normalized query.

generated_at str

ISO-8601 timestamp of cube generation.

Functions

compute_metrics

compute_metrics(txns: List[dict]) -> ReportMetrics

Compute aggregate metrics over a list of transaction dicts.

Parameters:

Name Type Description Default
txns List[dict]

Transactions with amount and occurred_at keys.

required

Returns:

Name Type Description
ReportMetrics ReportMetrics

Aggregated metrics; empty (zeroed) metrics when no amounts are present.

expand_tag_hierarchy

expand_tag_hierarchy(tag_path: str) -> List[str]

Given 'food,restaurants' return ['food', 'food,restaurants'] (every ancestor prefix).

Parameters:

Name Type Description Default
tag_path str

Comma-joined tag hierarchy path, or "untagged".

required

Returns:

Type Description
List[str]

List[str]: Every ancestor prefix of the path, or ["untagged"].

normalize_date

normalize_date(value: str) -> str

Canonicalize a date to the DD-MM-YYYY format (no time).

Parameters:

Name Type Description Default
value str

Date string in any supported input format.

required

Returns:

Name Type Description
str str

Date in canonical DD-MM-YYYY form.

Raises:

Type Description
ValueError

When the value cannot be parsed as a date.

normalize_granularities

1
2
3
normalize_granularities(
    values: Optional[Union[str, Sequence[str]]] = None,
) -> List[str]

Canonicalize + validate the granularities to precompute. Empty/default -> all period types.

Parameters:

Name Type Description Default
values Optional[Union[str, Sequence[str]]]

Granularity names, a single name, or None for the defaults.

None

Returns:

Type Description
List[str]

List[str]: Deduplicated, canonical granularity names.

Raises:

Type Description
ValueError

When a value is not a supported granularity.

normalize_period_label

normalize_period_label(value: str, granularity: str) -> str

Canonicalize a period label to the period_key format for a granularity.

Parameters:

Name Type Description Default
value str

Raw period label, e.g. W03-2024 or Q2-2024.

required
granularity str

Granularity the label belongs to.

required

Returns:

Name Type Description
str str

Canonical period label, or the input unchanged when it cannot be normalized.

parse_date

parse_date(value: str) -> Optional[datetime.date]

Parse a date string into a date, else None.

Parameters:

Name Type Description Default
value str

Date string in DD-MM-YYYY, YYYY-MM-DD, or DD/MM/YYYY form.

required

Returns:

Type Description
Optional[date]

Optional[datetime.date]: The parsed date, or None when unparseable.

period_bounds

period_bounds(dt: datetime.date, period_type: str)

Calendar (start, end) boundaries for a period, as dates. end is exclusive.

Parameters:

Name Type Description Default
dt date

Any date inside the period.

required
period_type str

Granularity: daily, weekly, monthly, quarterly, or yearly.

required

Returns:

Name Type Description
tuple

(start, end) date boundaries; end is exclusive.

Raises:

Type Description
ValueError

When the period type is unknown.

period_key

period_key(dt: datetime.date, period_type: str) -> str

Return the period label containing dt for a granularity.

Parameters:

Name Type Description Default
dt date

Date to bucket.

required
period_type str

Granularity: daily, weekly, monthly, quarterly, yearly, or all.

required

Returns:

Name Type Description
str str

Canonical period label for the given granularity.

Raises:

Type Description
ValueError

When the period type is unknown.

period_sort_key

period_sort_key(label: str)

Chronological sort key for a concrete period label (within one granularity).

Parameters:

Name Type Description Default
label str

Period label, e.g. 2024-W03, 2024-Jun, or 2024.

required

Returns:

Name Type Description
tuple

Sort key of (year, sub) where sub ranks within the year.

quarterly_label

quarterly_label(year: int, quarter: int) -> str

Build the canonical label for a calendar quarter.

Parameters:

Name Type Description Default
year int

Four-digit calendar year.

required
quarter int

Quarter number in 1..4.

required

Returns:

Name Type Description
str str

Quarterly label, e.g. 2024-Apr-Jun.

range_label

1
2
3
range_label(
    start_date: str = "", end_date: str = ""
) -> str

Build the start:end range label for a date window ('' when unbounded).

Parameters:

Name Type Description Default
start_date str

Start boundary date; empty for unbounded start.

''
end_date str

End boundary date; empty for unbounded end.

''

Returns:

Name Type Description
str str

start:end label, or an empty string when both bounds are empty.

Raises:

Type Description
ValueError

When the start date is after the end date.