Fix tombstone bug in stats and add cost statistics to forms
All checks were successful
Deploy / deploy (push) Successful in 1m38s

Bug fix: Stats queries (eggs/day, feed/bird/day, etc.) were not excluding
tombstoned (deleted) events. Updated EventStore.list_events() to exclude
tombstoned events by default via LEFT JOIN, and updated direct SQL queries
in stats.py with the same tombstone exclusion.

New stats added:
- Harvest form: cost/egg (global, 30-day avg)
- Sell form: avg price/egg (30-day)
- Give feed form: cost/bird/day (global, 30-day avg)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-09 06:19:30 +00:00
parent e42eede010
commit d91ee362fa
7 changed files with 299 additions and 39 deletions

View File

@@ -359,3 +359,66 @@ class TestTombstoneChecking:
)
assert event_store.is_tombstoned(event.id) is True
def test_list_events_excludes_tombstoned_by_default(self, migrated_db, event_store, now_utc):
"""list_events excludes tombstoned events by default."""
event1 = event_store.append_event(
event_type=PRODUCT_COLLECTED,
ts_utc=now_utc,
actor="ppetru",
entity_refs={},
payload={"order": 1},
)
event2 = event_store.append_event(
event_type=PRODUCT_COLLECTED,
ts_utc=now_utc + 1000,
actor="ppetru",
entity_refs={},
payload={"order": 2},
)
# Tombstone event1
tombstone_id = generate_id()
migrated_db.execute(
"""INSERT INTO event_tombstones (id, ts_utc, actor, target_event_id, reason)
VALUES (?, ?, ?, ?, ?)""",
(tombstone_id, now_utc + 2000, "admin", event1.id, "Test deletion"),
)
events = event_store.list_events()
assert len(events) == 1
assert events[0].id == event2.id
def test_list_events_includes_tombstoned_when_requested(
self, migrated_db, event_store, now_utc
):
"""list_events includes tombstoned events when include_tombstoned=True."""
event1 = event_store.append_event(
event_type=PRODUCT_COLLECTED,
ts_utc=now_utc,
actor="ppetru",
entity_refs={},
payload={"order": 1},
)
event2 = event_store.append_event(
event_type=PRODUCT_COLLECTED,
ts_utc=now_utc + 1000,
actor="ppetru",
entity_refs={},
payload={"order": 2},
)
# Tombstone event1
tombstone_id = generate_id()
migrated_db.execute(
"""INSERT INTO event_tombstones (id, ts_utc, actor, target_event_id, reason)
VALUES (?, ?, ?, ?, ?)""",
(tombstone_id, now_utc + 2000, "admin", event1.id, "Test deletion"),
)
events = event_store.list_events(include_tombstoned=True)
assert len(events) == 2
assert events[0].id == event1.id
assert events[1].id == event2.id