Commit graph

15 commits

Author SHA1 Message Date
kianiadee
6eb6b4716c Fix camera/tracker dedup (device_type at provision + backfill) and finish refresh-token flow
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 00:08:56 +03:00
kianiadee
de34103f18 UI tweaks + city case fix
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
- Migration 20: collapse `Nairobi`/`nairobi` in domain.vehicles → 'nairobi'
- Remove the SLO panel from the top band (filter + tile rows stay)
- Offline vehicles render as solid grey instead of dim-cost-centre tint;
  opacity now only differentiates moving (1.0) vs parked (0.75) vs
  offline (0.55) so colour carries identity + state cleanly
2026-05-27 22:07:03 +03:00
kianiadee
0265477f46 fix: fn_vehicle_trips takes bigint (domain.vehicles.vehicle_id is bigserial)
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
PG function overloading is type-strict: integer→bigint isn't implicit. The
prior signature (integer, date) didn't match callers passing vehicle_id
directly. Also prepends a DROP for the integer-signature in case the
previous migration ran and left a now-orphan function around.
2026-05-27 14:36:45 +03:00
kianiadee
7d63c03191 Trip detection: add nofix_stop rule (5-min reporting silence ends trip)
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
Calibrated against a full-day legacy report for vehicle KDE 638J:
without this rule we collapsed 15 dispatcher-visible trips into 3
(the algorithm waited for explicit ACC_OFF + stationary fixes that never
came in the polled data — the device just stops reporting between trips).

New rule: if mid-trip and the next fix arrives >=5 min after the previous
one (but <=30 min, which is still long_gap), close the trip at the prior
fix with end_reason='nofix_stop'.

Validation:
  638J full day: legacy 15 trips, mine 15 trips, perfect alignment
  728K half day: legacy 33 noisy trips, mine 9 clean trips
                 (stop-and-go traffic still consolidates because fixes
                  keep coming, just slow/stationary — not silence)

Also commits scripts/simulate_trips_from_legacy.py which runs the same
state machine in Python against REPORTS/*.json dumps for offline tuning.
2026-05-27 12:57:01 +03:00
kianiadee
419c030761 Trip detection backend: serve.fn_vehicle_trips + JSON/CSV endpoints
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
Migration 19: serve.fn_vehicle_trips(vehicle_id, date) — PL/pgSQL state
machine that walks state.position_history for one vehicle on one EAT day
and emits the trip breakdown. Rules:

  - reporting_time = first ACC_ON of the day
  - trip starts at ACC_ON (or first fix if already ACC_ON / moving)
  - trip ends:
      * ACC_OFF + stationary (<5 km/h) for >=5 min  → end_reason 'work_stop'
      * fix gap >30 min                              → end_reason 'long_gap'
      * end of day's data                            → end_reason 'day_end'
  - within a trip, ACC_ON + stationary >=5 min is logged as an idling
    segment (no trip split — engine still on)
  - distance only accumulates when speed >= 5 km/h (excludes GPS jitter)
  - falls back to movement-only segmentation when acc_state is null
    across the day (has_acc_data=false in the response)

Returns one jsonb document: vehicle, date, reporting_time, day totals
(distance, driving/idling/stopped/unknown minutes), data_quality flags,
trips[] with start/end/duration/distance/idling/end_reason/stops/path
where path is a GeoJSON LineString ready for the map.

New endpoints (read:fleet, rate-limited):
  GET /api/views/vehicle/{id}/trips?date=YYYY-MM-DD       JSON
  GET /api/views/vehicle/{id}/trips.csv?date=YYYY-MM-DD   one row per trip

Defaults date to today in EAT (UTC+3) regardless of host TZ.
2026-05-27 12:24:00 +03:00
kianiadee
0f91668256 Contract checker (#13, PRD F1.10) + contract_drift_days SLO
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
Migration 18: ops.contract_check_log table — append-only log of probes
against the Tracksolid Pro endpoints we depend on.

New worker app/workers/contract_check.py — per run:
  - jimi.oauth.token.get   (token refresh succeeds)
  - jimi.user.device.location.list per configured target (parse first item
    with JimiPollFix)
  - jimi.device.location.get with a sample IMEI from the list (parse first
    item with JimiPollFix)
Each probe logs success or {error_class, error_detail, sample}; failures
are recorded, not raised.

slo_metrics now also computes contract_drift_days = days since the most-
recent successful probe of the laggard endpoint. With threshold 1d (from
mig 5), a single failed daily run flips the badge red within 24h.

cron entrypoint registers the check daily at 02:00 UTC plus once on
startup, gated on TRACKSOLID_APP_KEY + a configured target.
2026-05-27 11:58:29 +03:00
kianiadee
495bb2bd71 Rollback CSV roster import (mig 17): re-split vehicles, drop CSV columns
Some checks failed
build / lint-test (push) Has been cancelled
build / build-push (push) Has been cancelled
The CSV-based roster import (mig 15+16 and scripts/import_csv_roster.py)
merged vehicle rows that differed only by _Track / _CAM suffix, dropping
the active fleet count from 144 to 124. Reverting the whole thing.

Mig 17 in one transaction:
  - Re-splits devices by parsed plate from device_name (same regex as
    mig 14, preserving _Track as separate vehicle)
  - Restores serve.fn_live_view to its v3 body (no d.driver_name/phone
    refs that would break once the columns are gone)
  - Drops the six CSV-only columns from domain.devices
  - Deletes schema_migrations rows for the deleted 15/16
  - Logs final counts via RAISE NOTICE

Apply on VPS: psql -f db/migrations/20260601000017_rollback_csv_import.sql
2026-05-25 00:41:32 +03:00
kianiadee
4cc0ef0535 Roster import: COALESCE-fill API-managed fields (device_type/lifecycle/activation_at/model) on existing rows; CSV is authoritative only for driver/phone/iccid/expiration/device_group
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-24 03:59:32 +03:00
kianiadee
6fd0d84560 Plate consolidation migration + projector links new devices to existing plates; SLO measurement worker (task #12)
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-23 23:42:45 +03:00
kianiadee
8323f94a19 _driver_name: also exclude garage/workshop/service placeholders
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-23 23:16:17 +03:00
kianiadee
9852eff985 Popup: pre-emptive driver-name extraction from device_name (until P3 roster lands)
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-23 23:13:46 +03:00
kianiadee
2b428e8058 Migration: serve._label_short() extracts plate-tail (handles 'Driver - KDW 573B_cam' patterns)
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-23 23:11:20 +03:00
kianiadee
45974b3810 Geocoder: cron job + state.geocoded_positions; label uses device_name last 4 (fallback plate); popup address row
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-23 23:06:25 +03:00
kianiadee
6c5ba3b22b UI: arrow + plate-short label + cost-centre marker palette + hover popup; richer state.live_positions + serve.fn_live_view v2; multi-target poll plumbing
Some checks are pending
build / lint-test (push) Waiting to run
build / build-push (push) Blocked by required conditions
2026-05-23 09:29:04 +03:00
kianiadee
1fb2a5be5e Phase 1 — foundation, push gateway, parser, projector, live view, frontend 2026-05-23 00:53:42 +03:00