from __future__ import annotations from enum import Enum from typing import Any from pydantic import BaseModel, Field class ComponentCategory(str, Enum): capacitor = "capacitor" resistor = "resistor" inductor = "inductor" diode = "diode" led = "led" ic = "ic" connector = "connector" crystal = "crystal" mosfet = "mosfet" sensor = "sensor" other = "other" class RowState(str, Enum): pending = "pending" scouting = "scouting" filtering = "filtering" confirmed = "confirmed" flagged = "flagged" class NormalizedParams(BaseModel): package: str | None = None value: float | None = None # SI base: F / Ω / H / Hz value_str: str | None = None # human-readable: "100nF", "10kΩ" unit: str | None = None # "F" | "Ω" | "H" | "Hz" voltage_rating: float | None = None current_rating: float | None = None power_rating: float | None = None tolerance: str | None = None # "5%", "10ppm" part_number: str | None = None # MPN if found in BOM manufacturer: str | None = None class BomRow(BaseModel): row_id: str designators: list[str] = Field(default_factory=list) quantity: int = 1 raw_value: str footprint: str | None = None category: ComponentCategory normalized_params: NormalizedParams state: RowState = RowState.pending applied_filters: dict[str, Any] = Field(default_factory=dict) facet_groups: dict[str, Any] = Field(default_factory=dict) confirmed_pick: dict[str, Any] | None = None scout_candidates: list[dict[str, Any]] | None = None class BomSession(BaseModel): session_id: str created_at: str filename: str preferred_suppliers: list[str] = Field(default_factory=list) rows: list[BomRow] = Field(default_factory=list)