diff --git a/tests/unit/test_package_queries.py b/tests/unit/test_package_queries.py new file mode 100644 index 0000000..bc8746d --- /dev/null +++ b/tests/unit/test_package_queries.py @@ -0,0 +1,21 @@ +import time +import pytest +from vigilar.storage.queries import insert_package_event, get_active_packages, update_package_status + +def test_insert_package_event(test_db): + pkg_id = insert_package_event(test_db, camera_id="front", detected_at=time.time(), status="PRESENT") + assert pkg_id > 0 + +def test_get_active_packages(test_db): + now = time.time() + insert_package_event(test_db, camera_id="front", detected_at=now, status="PRESENT") + insert_package_event(test_db, camera_id="back", detected_at=now, status="COLLECTED") + active = get_active_packages(test_db) + assert len(active) == 1 + assert active[0]["camera_id"] == "front" + +def test_update_package_status(test_db): + pkg_id = insert_package_event(test_db, camera_id="front", detected_at=time.time(), status="PRESENT") + update_package_status(test_db, pkg_id, "REMINDED", reminded_at=time.time()) + active = get_active_packages(test_db) + assert active[0]["status"] == "REMINDED" diff --git a/vigilar/alerts/sender.py b/vigilar/alerts/sender.py index 9478680..f630d4d 100644 --- a/vigilar/alerts/sender.py +++ b/vigilar/alerts/sender.py @@ -20,6 +20,8 @@ _CONTENT_MAP: dict[str, tuple[str, str]] = { EventType.UNKNOWN_VEHICLE_DETECTED: ("Unknown Vehicle", "Unknown vehicle on {source}"), EventType.POWER_LOSS: ("Power Alert", "UPS on battery"), EventType.LOW_BATTERY: ("Battery Critical", "UPS battery low"), + EventType.PACKAGE_DELIVERED: ("Package Delivered", "Package delivered — {source}"), + EventType.PACKAGE_REMINDER: ("Package Reminder", "Package still on porch — {source}"), } diff --git a/vigilar/storage/queries.py b/vigilar/storage/queries.py index 973d647..76373f2 100644 --- a/vigilar/storage/queries.py +++ b/vigilar/storage/queries.py @@ -516,3 +516,33 @@ def get_training_images( .order_by(desc(pet_training_images.c.created_at)) ).fetchall() return [dict(r._mapping) for r in rows] + + +# --- Package Events --- + +def insert_package_event( + engine: Engine, camera_id: str, detected_at: float, status: str, + crop_path: str | None = None, event_id: int | None = None, +) -> int: + from vigilar.storage.schema import package_events + with engine.begin() as conn: + result = conn.execute(package_events.insert().values( + camera_id=camera_id, detected_at=detected_at, status=status, + crop_path=crop_path, event_id=event_id)) + return result.inserted_primary_key[0] + + +def get_active_packages(engine: Engine) -> list[dict[str, Any]]: + from vigilar.storage.schema import package_events + with engine.connect() as conn: + rows = conn.execute( + select(package_events).where(package_events.c.status.in_(["PRESENT", "REMINDED"])) + .order_by(desc(package_events.c.detected_at))).mappings().all() + return [dict(r) for r in rows] + + +def update_package_status(engine: Engine, package_id: int, status: str, **kwargs: Any) -> None: + from vigilar.storage.schema import package_events + with engine.begin() as conn: + conn.execute(package_events.update().where(package_events.c.id == package_id) + .values(status=status, **kwargs))