From 4b33357ebf85f02b3834e987c8d834086d248201 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Sat, 2 May 2026 06:52:21 +0200 Subject: [PATCH] Add Splitwise clone backend --- app/schemas.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 app/schemas.py diff --git a/app/schemas.py b/app/schemas.py new file mode 100644 index 0000000..bc4b368 --- /dev/null +++ b/app/schemas.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from decimal import Decimal +from uuid import UUID + +from pydantic import BaseModel, Field, model_validator + + +class ExpenseItemCreate(BaseModel): + description: str + amount: Decimal + participants: list[str] + shares: dict[str, float] | None = None + + @model_validator(mode="after") + def validate_shares(self) -> ExpenseItemCreate: + if self.shares is not None: + if set(self.shares.keys()) != set(self.participants): + raise ValueError("shares keys must match participants exactly") + total = sum(self.shares.values()) + if abs(total - 100.0) > 0.01: + raise ValueError(f"shares must sum to 100, got {total}") + if len(self.participants) != len(set(self.participants)): + raise ValueError("participants must be unique") + return self + + +class ExpenseReportCreate(BaseModel): + title: str + items: list[ExpenseItemCreate] + + +class ExpenseShareOut(BaseModel): + user_sub: str + user_name: str | None + percentage: float + + +class ExpenseItemOut(BaseModel): + id: UUID + description: str + amount: Decimal + shares: list[ExpenseShareOut] + + +class ExpenseReportOut(BaseModel): + id: UUID + title: str + creator_sub: str + creator_name: str | None + created_at: str + items: list[ExpenseItemOut] + participants: list[dict[str, str | None]] + + +class ExpenseReportListOut(BaseModel): + reports: list[ExpenseReportOut] + total_count: int + + +class ErrorResponse(BaseModel): + detail: str