feat(filament): add spool count and total remaining weight columns

Adds computed spool statistics to filament list:
- spool_count: Number of non-archived spools of this filament
- total_remaining_weight: Sum of remaining weight across all spools

Backend changes:
- Modified database/filament.py find() to compute stats via subquery
- Added fields to Filament pydantic model in api/v1/models.py
- Updated filament API endpoint to include stats in response

Frontend changes:
- Added fields to IFilament interface
- Added columns to filament list table
- Added translation keys

Closes #15

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-15 23:31:47 -06:00
parent 0a741c9712
commit 48bd516c0f
6 changed files with 75 additions and 7 deletions

View File

@@ -221,9 +221,25 @@ class Filament(BaseModel):
"Query the /fields endpoint for more details about the fields."
),
)
spool_count: Optional[int] = Field(
None,
ge=0,
description="Number of spools of this filament (excluding archived). Computed field.",
examples=[5],
)
total_remaining_weight: Optional[float] = Field(
None,
ge=0,
description="Total remaining weight across all spools of this filament (excluding archived), in grams. Computed field.",
examples=[2500.0],
)
@staticmethod
def from_db(item: models.Filament) -> "Filament":
def from_db(
item: models.Filament,
spool_count: Optional[int] = None,
total_remaining_weight: Optional[float] = None,
) -> "Filament":
"""Create a new Pydantic filament object from a database filament object."""
return Filament(
id=item.id,
@@ -251,6 +267,8 @@ class Filament(BaseModel):
),
external_id=item.external_id,
extra={field.key: field.value for field in item.extra},
spool_count=spool_count,
total_remaining_weight=total_remaining_weight,
)