Harden resource cost evidence contract

This commit is contained in:
tegwick 2026-08-11 10:25:03 +02:00
parent 080f756fff
commit 00343307fd
22 changed files with 1623 additions and 130 deletions

View file

@ -0,0 +1,203 @@
"""Persistence boundary for non-booked resource-control evidence."""
from __future__ import annotations
import json
import sqlite3
from calendar import monthrange
from datetime import date
from pathlib import Path
from pydantic import TypeAdapter
from fin_hub.money import minor_money, money
from fin_hub.schemas.exchange import BookedCostEvidence, PlanningEvidence
from fin_hub.services.ledger import _connect, default_ledger_path
_PLANNING_ADAPTER = TypeAdapter(PlanningEvidence)
def _ensure_planning_schema(conn: sqlite3.Connection) -> None:
conn.execute(
"""
CREATE TABLE IF NOT EXISTS planning_evidence (
record_id TEXT PRIMARY KEY,
record_type TEXT NOT NULL,
revision_of TEXT REFERENCES planning_evidence(record_id),
payload_json TEXT NOT NULL,
is_current INTEGER NOT NULL DEFAULT 1,
received_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
)
"""
)
conn.execute(
"CREATE INDEX IF NOT EXISTS ix_planning_evidence_type_current "
"ON planning_evidence (record_type, is_current)"
)
conn.commit()
def ingest_planning_evidence(
payload: dict,
*,
ledger_path: Path | None = None,
) -> PlanningEvidence:
"""Validate and idempotently retain planning evidence outside booked spend."""
record = _PLANNING_ADAPTER.validate_python(payload)
canonical = record.model_dump_json()
ledger = ledger_path or default_ledger_path()
with _connect(ledger) as conn:
_ensure_planning_schema(conn)
conn.execute("BEGIN IMMEDIATE")
existing = conn.execute(
"SELECT payload_json FROM planning_evidence WHERE record_id = ?",
(record.record_id,),
).fetchone()
if existing is not None:
if json.loads(existing["payload_json"]) != json.loads(canonical):
raise ValueError("record_id already exists with different content")
return record
if record.revision_of is not None:
predecessor = conn.execute(
"SELECT record_type, is_current FROM planning_evidence WHERE record_id = ?",
(record.revision_of,),
).fetchone()
if predecessor is None or predecessor["record_type"] != record.record_type:
raise ValueError("revision_of must reference an existing record of the same type")
if predecessor["is_current"] != 1:
raise ValueError("revision_of must reference the current record")
conn.execute(
"UPDATE planning_evidence SET is_current = 0 WHERE record_id = ?",
(record.revision_of,),
)
conn.execute(
"INSERT INTO planning_evidence "
"(record_id, record_type, revision_of, payload_json, is_current) "
"VALUES (?, ?, ?, ?, 1)",
(record.record_id, record.record_type, record.revision_of, canonical),
)
conn.commit()
return record
def booked_cost_projection(*, ledger_path: Path | None = None) -> list[BookedCostEvidence]:
"""Project current authoritative facts without exposing raw invoice content."""
ledger = ledger_path or default_ledger_path()
with _connect(ledger) as conn:
rows = conn.execute(
"SELECT * FROM ledger_entries WHERE is_current = 1 ORDER BY id"
).fetchall()
projected: list[BookedCostEvidence] = []
for row in rows:
amount = minor_money(int(row["amount_minor"]))
adjustment_kind = row["adjustment_kind"]
gross_amount = amount
adjustment_amount = minor_money(0)
if adjustment_kind == "reversal":
with _connect(ledger) as conn:
predecessor = conn.execute(
"SELECT amount_minor FROM ledger_entries WHERE financial_fact_id = ?",
(row["correction_of"],),
).fetchone()
if predecessor is None:
raise ValueError("reversal predecessor is missing")
gross_amount = minor_money(int(predecessor["amount_minor"]))
adjustment_amount = -gross_amount
projected.append(
BookedCostEvidence(
financial_fact_id=row["financial_fact_id"],
correction_of=row["correction_of"],
adjustment_kind=adjustment_kind,
source_type=row["source_type"],
source_document_id=row["source_document_id"],
source_line_id=row["source_line_id"],
content_fingerprint=row["content_fingerprint"],
provider=row["source_type"],
accounting_period=row["period_month"],
service_period_start=row["incurred_on"],
service_period_end=row["incurred_on"],
currency=row["currency"],
net_amount="0.00",
discount_amount="0.00",
tax_status="unknown",
tax_amount=None,
gross_amount=gross_amount,
adjustment_amount=adjustment_amount,
effective_amount=amount,
service_id=row["category"],
environment=row["environment"],
cost_attribution_key=row["cost_attribution_key"],
source_evidence_ref=row["correction_source"] or row["source_document_id"],
recorded_at=row["imported_at"],
)
)
return projected
def ingest_resource_forecast(
payload: dict,
*,
resource_id: str,
source_evidence_ref: str,
ledger_path: Path | None = None,
) -> list[PlanningEvidence]:
"""Adapt resource-control's v0.1 monthly forecast into typed evidence."""
if payload.get("record_type") != "forecast":
raise ValueError("resource forecast payload must have record_type=forecast")
created_at = payload["created_at"]
version = f"{payload['provider_id']}:{created_at}"
records: list[PlanningEvidence] = []
for row in payload["rows"]:
expected_total = money(row["infrastructure_eur"]) + money(row["internal_labor_eur"])
if money(row["total_eur"]) != expected_total:
raise ValueError("resource forecast total_eur does not match its cost breakdown")
year, month = (int(part) for part in row["period"].split("-"))
period_start = date(year, month, 1)
period_end = date(year, month, monthrange(year, month)[1])
record = ingest_planning_evidence(
{
"schema_version": "0.1",
"record_type": "forecast",
"record_id": (
f"forecast:{payload['provider_id']}:"
f"{payload['cost_attribution_key']}:{row['period']}:{created_at}"
),
"revision_of": payload.get("forecast_ref"),
"resource_id": resource_id,
"service_id": payload["provider_id"],
"workload_id": payload["workload"],
"tenant_id": None,
"environment": "production",
"cost_attribution_key": payload["cost_attribution_key"],
"period_start": period_start.isoformat(),
"period_end": period_end.isoformat(),
"currency": "EUR",
"source_evidence": [source_evidence_ref, *row.get("evidence", [])],
"created_at": created_at,
"scenario": payload.get("scenario") or "base",
"forecast_version": version,
"costs": {
"infrastructure": row["infrastructure_eur"],
"internal_labor": row["internal_labor_eur"],
"external_services": 0,
"setup": 0,
"other": 0,
},
"uncertainty": None,
"assumptions": [
f"database_gb={row['database_gb']}",
f"stored_gb={row['stored_gb']}",
f"wal_gb={row['wal_gb']}",
f"restore_egress_gb={row['restore_egress_gb']}",
f"write_requests={row['write_requests']}",
f"read_requests={row['read_requests']}",
f"internal_labor_hours={row['internal_labor_hours']}",
],
},
ledger_path=ledger_path,
)
records.append(record)
return records

View file

@ -3,15 +3,25 @@
from __future__ import annotations
import json
import hashlib
import sqlite3
import uuid
from dataclasses import asdict, dataclass
from datetime import date, datetime, timezone
from decimal import Decimal
from pathlib import Path
from fin_hub.ingest.anthropic import parse_anthropic_billing_csv
from fin_hub.ingest.cloud import parse_cloud_cost_csv
from fin_hub.ingest.hosteurope import parse_hosteurope_csv
from fin_hub.money import (
EngagementPriceTerms,
currency_code,
minor_money,
money,
money_minor,
reporting_month,
)
DEFAULT_LEDGER_PATH = Path(".fin-hub/ledger.db")
@ -21,16 +31,26 @@ class LedgerEntry:
source_type: str
category: str
label: str
amount: float
amount: Decimal
currency: str
period_month: str
incurred_on: date | None
source_path: str
environment: str = "production"
client_id: str | None = None
application_id: str | None = None
app_instance_id: str | None = None
cost_attribution_key: str | None = None
def __post_init__(self) -> None:
object.__setattr__(self, "amount", money(self.amount))
object.__setattr__(self, "currency", currency_code(self.currency))
object.__setattr__(self, "period_month", reporting_month(self.period_month))
normalized_environment = self.environment.strip()
if not normalized_environment:
raise ValueError("environment is required")
object.__setattr__(self, "environment", normalized_environment)
@dataclass(frozen=True)
class MonthlyRollup:
@ -62,7 +82,7 @@ class EngagementPriceRecord:
app_instance_id: str
cost_attribution_key: str
period_month: str
amount: float
amount: Decimal
currency: str
source: str
revision_of: str | None
@ -77,9 +97,9 @@ class ClientMargin:
app_instance_id: str
period_month: str
currency: str
revenue: float
attributed_cost: float
margin: float
revenue: Decimal
attributed_cost: Decimal
margin: Decimal
price_id: str
def as_dict(self) -> dict:
@ -136,14 +156,14 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
cost_attribution_key TEXT NOT NULL,
period_month TEXT NOT NULL,
amount REAL NOT NULL,
amount_minor INTEGER,
currency TEXT NOT NULL,
source TEXT NOT NULL,
revision_of TEXT REFERENCES engagement_prices(id),
is_current INTEGER NOT NULL DEFAULT 1,
recorded_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS ix_engagement_prices_basis
ON engagement_prices (cost_attribution_key, period_month, currency);
"""
)
columns = {row["name"] for row in conn.execute("PRAGMA table_info(ledger_entries)")}
@ -152,15 +172,99 @@ def _ensure_schema(conn: sqlite3.Connection) -> None:
"application_id",
"app_instance_id",
"cost_attribution_key",
"environment",
):
if name not in columns:
conn.execute(f"ALTER TABLE ledger_entries ADD COLUMN {name} TEXT")
entry_columns = {row["name"] for row in conn.execute("PRAGMA table_info(ledger_entries)")}
if "amount_minor" not in entry_columns:
conn.execute("ALTER TABLE ledger_entries ADD COLUMN amount_minor INTEGER")
for name, definition in (
("financial_fact_id", "TEXT"),
("source_document_id", "TEXT"),
("source_line_id", "TEXT"),
("content_fingerprint", "TEXT"),
("correction_of", "TEXT"),
("adjustment_kind", "TEXT NOT NULL DEFAULT 'charge'"),
("correction_source", "TEXT"),
("is_current", "INTEGER NOT NULL DEFAULT 1"),
):
if name not in entry_columns:
conn.execute(f"ALTER TABLE ledger_entries ADD COLUMN {name} {definition}")
conn.execute(
"UPDATE ledger_entries SET amount_minor = ROUND(amount * 100) "
"WHERE amount_minor IS NULL"
)
conn.execute(
"UPDATE ledger_entries SET financial_fact_id = 'legacy:' || id, "
"source_document_id = 'legacy:' || source_path, "
"source_line_id = 'legacy:' || id, "
"content_fingerprint = 'legacy:' || id "
"WHERE financial_fact_id IS NULL"
)
conn.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS uq_ledger_financial_fact_id "
"ON ledger_entries (financial_fact_id)"
)
conn.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS uq_ledger_current_source_line "
"ON ledger_entries (source_line_id) WHERE is_current = 1"
)
price_columns = {
row["name"] for row in conn.execute("PRAGMA table_info(engagement_prices)")
}
if "amount_minor" not in price_columns:
conn.execute("ALTER TABLE engagement_prices ADD COLUMN amount_minor INTEGER")
if "is_current" not in price_columns:
conn.execute(
"ALTER TABLE engagement_prices ADD COLUMN is_current INTEGER NOT NULL DEFAULT 1"
)
conn.execute(
"UPDATE engagement_prices SET amount_minor = ROUND(amount * 100) "
"WHERE amount_minor IS NULL"
)
conn.execute(
"UPDATE engagement_prices SET is_current = 0 WHERE id IN ("
"SELECT revision_of FROM engagement_prices WHERE revision_of IS NOT NULL)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS ix_engagement_prices_basis "
"ON engagement_prices (cost_attribution_key, period_month, currency)"
)
conn.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS uq_engagement_prices_current_basis "
"ON engagement_prices (cost_attribution_key, period_month, currency) "
"WHERE is_current = 1"
)
conn.commit()
def _utc_now() -> str:
return datetime.now(timezone.utc).isoformat()
def _digest(*parts: object) -> str:
payload = "\x1f".join("" if part is None else str(part) for part in parts)
return hashlib.sha256(payload.encode("utf-8")).hexdigest()
def _entry_business_key(entry: LedgerEntry) -> str:
return _digest(
entry.source_type,
entry.category,
entry.label,
entry.currency,
entry.period_month,
entry.incurred_on.isoformat() if entry.incurred_on else None,
entry.environment,
entry.cost_attribution_key,
)
def _entry_fingerprint(entry: LedgerEntry) -> str:
return _digest(_entry_business_key(entry), money_minor(entry.amount))
def set_opening_balance(path: Path, balance: float, *, currency: str = "EUR") -> None:
with _connect(path) as conn:
conn.execute(
@ -234,6 +338,7 @@ def _entries_from_hosteurope(path: Path) -> list[LedgerEntry]:
period_month=row.period_month,
incurred_on=row.incurred_on,
source_path=resolved,
environment=row.environment,
client_id=row.client_id,
application_id=row.application_id,
app_instance_id=row.app_instance_id,
@ -279,20 +384,50 @@ def import_csv(
skipped=True,
)
for entry in entries:
business_keys = [_entry_business_key(entry) for entry in entries]
source_document_id = f"{source_type}:{_digest(*sorted(business_keys))}"
occurrences: dict[str, int] = {}
rows_imported = 0
for entry, business_key in zip(entries, business_keys, strict=True):
occurrence = occurrences.get(business_key, 0) + 1
occurrences[business_key] = occurrence
source_line_id = f"{source_type}:{business_key}:{occurrence}"
fingerprint = _entry_fingerprint(entry)
current = conn.execute(
"SELECT financial_fact_id, content_fingerprint FROM ledger_entries "
"WHERE source_line_id = ? AND is_current = 1",
(source_line_id,),
).fetchone()
if current is not None and current["content_fingerprint"] == fingerprint:
continue
if current is not None and not force:
raise ValueError(
"changed financial fact requires force=True to append an explicit correction: "
f"{current['financial_fact_id']}"
)
correction_of = current["financial_fact_id"] if current is not None else None
financial_fact_id = f"fact:{_digest(source_line_id, fingerprint)}"
if current is not None:
conn.execute(
"UPDATE ledger_entries SET is_current = 0 WHERE financial_fact_id = ?",
(correction_of,),
)
conn.execute(
"""
INSERT INTO ledger_entries (
source_type, category, label, amount, currency,
period_month, incurred_on, source_path, imported_at,
client_id, application_id, app_instance_id, cost_attribution_key
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
client_id, application_id, app_instance_id, cost_attribution_key,
environment, amount_minor, financial_fact_id, source_document_id,
source_line_id, content_fingerprint, correction_of,
adjustment_kind, correction_source, is_current
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
""",
(
entry.source_type,
entry.category,
entry.label,
entry.amount,
float(entry.amount),
entry.currency,
entry.period_month,
entry.incurred_on.isoformat() if entry.incurred_on else None,
@ -302,33 +437,108 @@ def import_csv(
entry.application_id,
entry.app_instance_id,
entry.cost_attribution_key,
entry.environment,
money_minor(entry.amount),
financial_fact_id,
source_document_id,
source_line_id,
fingerprint,
correction_of,
"correction" if correction_of else "charge",
entry.source_path if correction_of else None,
),
)
rows_imported += 1
conn.execute(
"""
INSERT OR REPLACE INTO ledger_imports (
source_path, source_mtime, source_type, row_count, imported_at
) VALUES (?, ?, ?, ?, ?)
""",
(resolved, mtime, source_type, len(entries), imported_at),
(resolved, mtime, source_type, rows_imported, imported_at),
)
conn.commit()
return ImportResult(
source_type=source_type,
source_path=resolved,
rows_imported=len(entries),
skipped=False,
rows_imported=rows_imported,
skipped=rows_imported == 0,
)
def reverse_financial_fact(
financial_fact_id: str,
*,
source: str,
ledger_path: Path | None = None,
) -> str:
"""Append a zero-effective reversal and retain the reversed predecessor."""
normalized_source = source.strip()
if not normalized_source:
raise ValueError("source is required")
ledger = ledger_path or default_ledger_path()
with _connect(ledger) as conn:
conn.execute("BEGIN IMMEDIATE")
current = conn.execute(
"SELECT * FROM ledger_entries WHERE financial_fact_id = ? AND is_current = 1",
(financial_fact_id,),
).fetchone()
if current is None:
raise ValueError("financial_fact_id must reference a current fact")
fingerprint = _digest(current["content_fingerprint"], "reversal", normalized_source)
reversal_id = f"fact:{_digest(current['source_line_id'], fingerprint)}"
conn.execute(
"UPDATE ledger_entries SET is_current = 0 WHERE financial_fact_id = ?",
(financial_fact_id,),
)
conn.execute(
"""
INSERT INTO ledger_entries (
source_type, category, label, amount, currency, period_month,
incurred_on, source_path, imported_at, client_id, application_id,
app_instance_id, cost_attribution_key, environment, amount_minor,
financial_fact_id, source_document_id, source_line_id,
content_fingerprint, correction_of, adjustment_kind,
correction_source, is_current
) VALUES (?, ?, ?, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, 'reversal', ?, 1)
""",
(
current["source_type"],
current["category"],
current["label"],
current["currency"],
current["period_month"],
current["incurred_on"],
current["source_path"],
_utc_now(),
current["client_id"],
current["application_id"],
current["app_instance_id"],
current["cost_attribution_key"],
current["environment"],
reversal_id,
current["source_document_id"],
current["source_line_id"],
fingerprint,
financial_fact_id,
normalized_source,
),
)
conn.commit()
return reversal_id
def monthly_summary(*, ledger_path: Path | None = None) -> list[MonthlyRollup]:
ledger = ledger_path or default_ledger_path()
with _connect(ledger) as conn:
rows = conn.execute(
"""
SELECT period_month, currency, SUM(amount) AS total, COUNT(*) AS entry_count
SELECT period_month, currency, SUM(amount_minor) AS total_minor,
COUNT(*) AS entry_count
FROM ledger_entries
WHERE is_current = 1
GROUP BY period_month, currency
ORDER BY period_month, currency
"""
@ -337,7 +547,7 @@ def monthly_summary(*, ledger_path: Path | None = None) -> list[MonthlyRollup]:
MonthlyRollup(
period_month=row["period_month"],
currency=row["currency"],
total=float(row["total"]),
total=float(minor_money(int(row["total_minor"]))),
entry_count=int(row["entry_count"]),
)
for row in rows
@ -367,31 +577,25 @@ def record_engagement_price(
price_id: str | None = None,
revision_of: str | None = None,
) -> EngagementPriceRecord:
from fin_hub.attribution import ClientAttribution
attribution = ClientAttribution(client_id, application_id, app_instance_id)
if len(period_month) != 7 or period_month[4] != "-":
raise ValueError("period_month must use YYYY-MM")
try:
date.fromisoformat(f"{period_month}-01")
except ValueError as exc:
raise ValueError("period_month must use YYYY-MM") from exc
normalized_currency = currency.strip().upper()
if len(normalized_currency) != 3 or not normalized_currency.isalpha():
raise ValueError("currency must be a three-letter code")
if amount < 0:
raise ValueError("engagement price amount cannot be negative")
if not source.strip():
raise ValueError("source is required")
terms = EngagementPriceTerms.validate(
client_id=client_id,
application_id=application_id,
app_instance_id=app_instance_id,
period_month=period_month,
amount=amount,
currency=currency,
source=source,
)
ledger = ledger_path or default_ledger_path()
identifier = price_id or str(uuid.uuid4())
recorded_at = _utc_now()
with _connect(ledger) as conn:
basis = (attribution.key, period_month, normalized_currency)
conn.execute("BEGIN IMMEDIATE")
basis = (terms.attribution.key, terms.period_month, terms.currency)
current = conn.execute(
"SELECT id FROM engagement_prices WHERE cost_attribution_key = ? "
"AND period_month = ? AND currency = ? "
"AND period_month = ? AND currency = ? AND is_current = 1 "
"ORDER BY recorded_at DESC, rowid DESC LIMIT 1",
basis,
).fetchone()
@ -399,21 +603,28 @@ def record_engagement_price(
raise ValueError(f"revision_of must reference current price {current['id']}")
if current is None and revision_of is not None:
raise ValueError("revision_of cannot be used without an existing price")
if current is not None:
conn.execute(
"UPDATE engagement_prices SET is_current = 0 WHERE id = ?",
(current["id"],),
)
conn.execute(
"INSERT INTO engagement_prices ("
"id, client_id, application_id, app_instance_id, cost_attribution_key, "
"period_month, amount, currency, source, revision_of, recorded_at"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"period_month, amount, amount_minor, currency, source, revision_of, "
"is_current, recorded_at"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)",
(
identifier,
attribution.client_id,
attribution.application_id,
attribution.app_instance_id,
attribution.key,
period_month,
amount,
normalized_currency,
source.strip(),
terms.attribution.client_id,
terms.attribution.application_id,
terms.attribution.app_instance_id,
terms.attribution.key,
terms.period_month,
float(terms.amount),
money_minor(terms.amount),
terms.currency,
terms.source,
revision_of,
recorded_at,
),
@ -421,14 +632,14 @@ def record_engagement_price(
conn.commit()
return EngagementPriceRecord(
id=identifier,
client_id=attribution.client_id,
application_id=attribution.application_id,
app_instance_id=attribution.app_instance_id,
cost_attribution_key=attribution.key,
period_month=period_month,
amount=amount,
currency=normalized_currency,
source=source.strip(),
client_id=terms.attribution.client_id,
application_id=terms.attribution.application_id,
app_instance_id=terms.attribution.app_instance_id,
cost_attribution_key=terms.attribution.key,
period_month=terms.period_month,
amount=terms.amount,
currency=terms.currency,
source=terms.source,
revision_of=revision_of,
recorded_at=recorded_at,
)
@ -440,23 +651,18 @@ def client_margin_report(*, ledger_path: Path | None = None) -> list[ClientMargi
rows = conn.execute(
"""
WITH latest_prices AS (
SELECT p.*
FROM engagement_prices p
WHERE NOT EXISTS (
SELECT 1 FROM engagement_prices revision
WHERE revision.revision_of = p.id
)
SELECT p.* FROM engagement_prices p WHERE p.is_current = 1
), attributed_costs AS (
SELECT cost_attribution_key, period_month, currency,
SUM(amount) AS attributed_cost
SUM(amount_minor) AS attributed_cost_minor
FROM ledger_entries
WHERE cost_attribution_key IS NOT NULL
WHERE cost_attribution_key IS NOT NULL AND is_current = 1
GROUP BY cost_attribution_key, period_month, currency
)
SELECT p.id AS price_id, p.client_id, p.application_id,
p.app_instance_id, p.cost_attribution_key, p.period_month,
p.currency, p.amount AS revenue,
COALESCE(c.attributed_cost, 0) AS attributed_cost
p.currency, p.amount_minor AS revenue_minor,
COALESCE(c.attributed_cost_minor, 0) AS attributed_cost_minor
FROM latest_prices p
LEFT JOIN attributed_costs c
ON c.cost_attribution_key = p.cost_attribution_key
@ -473,9 +679,11 @@ def client_margin_report(*, ledger_path: Path | None = None) -> list[ClientMargi
app_instance_id=row["app_instance_id"],
period_month=row["period_month"],
currency=row["currency"],
revenue=float(row["revenue"]),
attributed_cost=float(row["attributed_cost"]),
margin=float(row["revenue"]) - float(row["attributed_cost"]),
revenue=minor_money(int(row["revenue_minor"])),
attributed_cost=minor_money(int(row["attributed_cost_minor"])),
margin=minor_money(
int(row["revenue_minor"]) - int(row["attributed_cost_minor"])
),
price_id=row["price_id"],
)
for row in rows