Add capacity test history and chart to battery detail

- New CapacityTest model (battery_id FK CASCADE, mah, date, notes)
- DB migration: create capacity_test table, migrate existing single-test data
- Two new routes: add and delete capacity test records
- Battery.tested_capacity_mah/tested_date kept in sync with latest test
  so dashboard display requires no changes
- Battery detail: Capacity History card with sortable table, health %
  per reading, and a canvas line chart (shown when >= 2 records)
- Chart uses CSS variables for colors — works in light and dark mode
- Remove tested_capacity_mah/tested_date from Edit Details form
- 3 new acceptance tests (48 total)
This commit is contained in:
2026-04-13 04:15:55 -05:00
parent 86fb342b0d
commit 2f8a8a2b77
4 changed files with 239 additions and 16 deletions
+20
View File
@@ -49,6 +49,11 @@ class Battery(Base):
storage_location = Column(String(100), nullable=True) # where stored when not installed
device = relationship("Device", back_populates="batteries")
capacity_tests = relationship(
"CapacityTest", back_populates="battery",
order_by="CapacityTest.tested_date",
cascade="all, delete-orphan",
)
def is_available(self):
return self.status == "available"
@@ -61,3 +66,18 @@ class Battery(Base):
def __repr__(self):
return f"<Battery {self.label}>"
class CapacityTest(Base):
__tablename__ = "capacity_test"
id = Column(Integer, primary_key=True, autoincrement=True)
battery_id = Column(Integer, ForeignKey("battery.id", ondelete="CASCADE"), nullable=False)
tested_capacity_mah = Column(Integer, nullable=False)
tested_date = Column(String(10), nullable=False) # YYYY-MM-DD
notes = Column(Text, nullable=True)
battery = relationship("Battery", back_populates="capacity_tests")
def __repr__(self):
return f"<CapacityTest {self.battery_id} {self.tested_date} {self.tested_capacity_mah}mAh>"