fix(occupancy): orphan camera code — group code written as a fake camera when a group has no exit camera #51

Closed
opened 2026-09-22 14:52:21 +00:00 by gabogg · 1 comment
Owner

Blocked by: #28

Problem

When a resource group has no exit-typed camera, the sync falls back to writing counting events keyed by the resource-group code as if it were a camera:

# app/services/occupancy_service.py:1826
"out_cams": out_cams or [(g_code, g_name)]

Those events land in the per-camera counting table with camera_index_code = <resource group code> — an orphan camera code that matches no real camera. It pollutes portal/zone attribution and any per-camera roll-up with a phantom "camera" that is actually a group.

This was referenced as "the separate orphan-camera-code issue" in #28 but had never been filed.

Dependency

Blocked by #28. #28 makes counting_cameras.direction_type authoritative and rewrites the in_cams/out_cams derivation, and adds the guard that stops new orphan rows being written. This issue must land after #28 — it owns the cleanup of existing orphan rows and the assertion that no group code is ever written as a camera code. Starting before #28 would rework the same lines twice.

Suggested fix (after #28)

  1. Guard: never synthesize a camera from a group code. A group with zero exit cameras is a configuration gap — surface it (log / operator flag), don't fabricate a camera.
  2. Migration: identify existing counting_events / per-camera rows whose camera_index_code equals a known resource-group code, and either re-attribute to the group level or quarantine them.
  3. Add a data-integrity check: camera_index_code in the counting table must resolve to a row in counting_cameras.

Acceptance criteria

  • No new counting event is ever written with a camera_index_code equal to a resource-group code.
  • A group with no exit camera raises a configuration flag instead of fabricating a camera.
  • Existing orphan rows identified and re-attributed or quarantined.
  • Integrity check: every camera_index_code in the counting table resolves to a counting_cameras row.

Surfaced during the grilling session on #28.

> **Blocked by: #28** ## Problem When a resource group has no exit-typed camera, the sync falls back to writing counting events keyed by the **resource-group code** as if it were a camera: ```python # app/services/occupancy_service.py:1826 "out_cams": out_cams or [(g_code, g_name)] ``` Those events land in the per-camera counting table with `camera_index_code = <resource group code>` — an **orphan camera code** that matches no real camera. It pollutes portal/zone attribution and any per-camera roll-up with a phantom "camera" that is actually a group. This was referenced as "the separate orphan-camera-code issue" in #28 but had never been filed. ## Dependency **Blocked by #28.** #28 makes `counting_cameras.direction_type` authoritative and rewrites the `in_cams`/`out_cams` derivation, and adds the guard that stops new orphan rows being written. This issue must land **after** #28 — it owns the **cleanup of existing orphan rows** and the assertion that no group code is ever written as a camera code. Starting before #28 would rework the same lines twice. ## Suggested fix (after #28) 1. Guard: never synthesize a camera from a group code. A group with zero exit cameras is a **configuration gap** — surface it (log / operator flag), don't fabricate a camera. 2. Migration: identify existing `counting_events` / per-camera rows whose `camera_index_code` equals a known resource-group code, and either re-attribute to the group level or quarantine them. 3. Add a data-integrity check: `camera_index_code` in the counting table must resolve to a row in `counting_cameras`. ## Acceptance criteria - [ ] No new counting event is ever written with a `camera_index_code` equal to a resource-group code. - [ ] A group with no exit camera raises a configuration flag instead of fabricating a camera. - [ ] Existing orphan rows identified and re-attributed or quarantined. - [ ] Integrity check: every `camera_index_code` in the counting table resolves to a `counting_cameras` row. Surfaced during the grilling session on #28.
Author
Owner

Closing as a duplicate of #29, which is older and describes the same orphan resource-group-code bug more completely (invisible rows + 3 s re-injection). The fix is folded into PR #53 (Closes #29). Kept the dependency reasoning there.

Closing as a **duplicate of #29**, which is older and describes the same orphan resource-group-code bug more completely (invisible rows + 3 s re-injection). The fix is folded into PR #53 (Closes #29). Kept the dependency reasoning there.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gabogg/hikcentral#51
No description provided.