Files
karung-counting-feedmill-se…/ERD.md
T
2026-09-25 14:22:25 +07:00

4.7 KiB
Raw Blame History

ERD — karung counter (SQLite)

Data model for the karung feedmill counter. SQLite DB at $OUTPUT_DIR/jetson_counter.db (config.yaml output.dir, default /opt/jetson-counter/; env override DB_PATH).

No DB foreign keys enforced (zero FOREIGN KEY in code) — all relationships are soft, by naming/best-effort writes.

erDiagram
    batches ||--o{ delivery_orders : "soft via batch_id / do_numbers"
    batches ||--o{ daily_summaries : "rollup by counting_date"

    batches {
        INTEGER id PK
        TEXT counting_date "NOT NULL, YYYY-MM-DD, cutoff-shifted"
        INTEGER batch_number "NOT NULL, per date+camera+label"
        TEXT camera_name "NOT NULL, default CC1"
        TEXT object_label "NOT NULL, default karung-pakan"
        INTEGER count "NOT NULL, gross sack loading"
        TEXT start_time "NOT NULL, ISO datetime"
        TEXT end_time "NOT NULL, ISO datetime"
        TIMESTAMP created_at "default CURRENT_TIMESTAMP"
        INTEGER box_loading "NOT NULL, default 0"
        INTEGER box_unloading "NOT NULL, default 0"
        TEXT model_mode "NOT NULL, default A"
        TEXT plate "NOT NULL, default ''"
        TEXT do_numbers "NOT NULL, JSON array of No. DO"
        INTEGER expected_sack "NOT NULL, default 0"
        INTEGER expected_box "NOT NULL, default 0"
        INTEGER net_sack "NOT NULL, default 0"
        INTEGER net_box "NOT NULL, default 0"
    }

    delivery_orders {
        INTEGER id PK
        TEXT counting_date "NOT NULL"
        TEXT photo_path "NOT NULL, relative under do_photos/"
        TEXT no_do "default ''"
        TEXT plate "default ''"
        INTEGER expected_sack "default 0"
        INTEGER expected_box "default 0"
        TEXT ocr_raw "nullable JSON: no_do, plate, ocr_text, engine, ocr_ok, ocr_error"
        TEXT status "default 'draft'"
        INTEGER batch_id "soft ref to batches.id, nullable"
        TIMESTAMP created_at "default CURRENT_TIMESTAMP"
        TIMESTAMP updated_at "default CURRENT_TIMESTAMP"
    }

    daily_summaries {
        INTEGER id PK
        TEXT counting_date "NOT NULL"
        TEXT camera_name "NOT NULL"
        TEXT object_label "NOT NULL"
        INTEGER total_count "NOT NULL, default 0, SUM(batches.count)"
        INTEGER total_batches "NOT NULL, default 0, COUNT(batches.id)"
        TIMESTAMP updated_at "default CURRENT_TIMESTAMP"
    }

Keys

  • batches: UNIQUE(counting_date, batch_number, camera_name, object_label)
  • daily_summaries: UNIQUE(counting_date, camera_name, object_label)
  • delivery_orders: idx_do_date_status on (counting_date, status)

Relationships (logical)

From To How
delivery_orders → batches N—1 On stop: batches.do_numbers JSON array of No. DO; delivery_orders.batch_id set best-effort. Active batch: current_batch.json.do_ids.
batches → daily_summaries N—1 Same (counting_date, camera_name, object_label); stop recompute SUM(count), COUNT(id).

Derived columns

  • net_sack = count − sack unloading, net_box = box_loading − box_unloading (src/do_batch.py:37).
  • Sack unloading has no column — it only survives inside net_sack (legacy rows with net_sack=0 from the ALTER TABLE ... DEFAULT 0 migration are not backfillable).
  • History UI shows gross count / box_loading only (no Net).

Status (delivery_orders.status)

draft (photo upload) → staged (saved/edited) → attached (in active/stopped batch). Discard stop with both nets 0 returns DOs to staged. discarded appears in older notes but no code writes it — discard is a DELETE.

Hazards

  • INSERT OR REPLACE on batches (UNIQUE match = delete+insert) changes id on re-stop → can orphan delivery_orders.batch_id.
  • Schema divergence: predict.py init_db() creates only batches + daily_summaries (3 extra cols, no delivery_orders); full 3-table schema (9 extra batches cols) comes from counter_dashboard.py _ensure_db() at import. Fresh DB touched only by predict.py is incomplete; its DO updates fail silently (try/except: pass).

JSON sidecars + photo tree (not in SQLite)

Path Role
$OUTPUT_DIR/batch_mode.json {mode: auto|do_manual|manual}
$OUTPUT_DIR/current_batch.json active batch + do_ids, plate, expected_*, nets inputs
$OUTPUT_DIR/do_settings.json require_plate, require_do, ocr_engine
$OUTPUT_DIR/do_photos/YYYY-MM-DD/do_<uuid>.jpg source photos (7-day retention)

Sources

  • DDL: counter_dashboard.py:123-198 (_ensure_db, superset), predict.py:117-166 (init_db, partial).
  • Writes: predict.py:249-306, counter_dashboard.py:610-668.
  • Doc flow: docs/do-erd.md (merged into this file).