Skip to content

Extract shared _SpendingTotals base for spending summary models #111

@Aureliolo

Description

@Aureliolo

Problem

AgentSpending, DepartmentSpending, and PeriodSpending in budget/spending_summary.py each independently define the same 4 fields:

total_cost: Decimal
total_input_tokens: int
total_output_tokens: int
record_count: int

This is ~48 lines of duplicated field definitions + docstrings across 3 models. Changes to field constraints, types, or descriptions must be made in 3 places.

Proposed Solution

Extract a shared _SpendingTotals base:

class _SpendingTotals(BaseModel):
    model_config = ConfigDict(frozen=True)

    total_cost: Decimal = Field(ge=0, description="Sum of cost_usd across records")
    total_input_tokens: int = Field(ge=0, description="Sum of input tokens")
    total_output_tokens: int = Field(ge=0, description="Sum of output tokens")
    record_count: int = Field(ge=0, description="Number of cost records")

class AgentSpending(_SpendingTotals):
    agent_id: NotBlankStr = Field(description="Agent identifier")

class DepartmentSpending(_SpendingTotals):
    department: NotBlankStr = Field(description="Department name")

class PeriodSpending(_SpendingTotals):
    start: datetime = Field(description="Period start (inclusive)")
    end: datetime = Field(description="Period end (exclusive)")

Acceptance Criteria

  • _SpendingTotals base class with the 4 shared fields
  • AgentSpending, DepartmentSpending, PeriodSpending extend it
  • Individual whitespace validators replaced with NotBlankStr (depends on NotBlankStr adoption issue)
  • Net reduction of ~30-40 lines
  • All existing tests pass
  • Public API unchanged (model_dump() output identical)
  • Verify DESIGN_SPEC.md §10.2 implementation note and §15.5 remain consistent after implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    prio:mediumShould do, but not blockingscope:smallLess than 1 day of workspec:budgetDESIGN_SPEC Section 10 - Cost & Budget Managementtype:refactorCode restructuring, cleanup

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions