feat: mttr -> minutes; drop constant alarm/auto flags (migration 06)
mttr generated column is now integer minutes (source raw.mttr is decimal hours), analytics-friendly. Drop is_alarm/is_auto_created/is_auto_closed generated columns — all constant `false` in tickets.inc since alarms are filtered at ingest (still present in raw for audit; loader still filters on raw->>'is_alarm'). is_actionable kept. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
565cd592a0
commit
b86c0b2d13
2 changed files with 26 additions and 0 deletions
|
|
@ -16,6 +16,7 @@ Field-ops **INC ticket** ingestion, geocoding, and read-schema that powers the
|
||||||
| `migrations/03_inc_columns.sql` | Unpacks `tickets.inc.raw` into **typed STORED generated columns** (status, cluster, region, team, owner, sla_status, mttr, lat/lng, is_* booleans, and EAT→`timestamptz` timestamps via `tickets.eat_ts()`). Computed for all rows + auto-populated on every ingest; `raw` stays the source of truth |
|
| `migrations/03_inc_columns.sql` | Unpacks `tickets.inc.raw` into **typed STORED generated columns** (status, cluster, region, team, owner, sla_status, mttr, lat/lng, is_* booleans, and EAT→`timestamptz` timestamps via `tickets.eat_ts()`). Computed for all rows + auto-populated on every ingest; `raw` stays the source of truth |
|
||||||
| `migrations/04_inc_latlng.sql` | Redefines `latitude`/`longitude` to `COALESCE(feed, ST_Y/ST_X(geom))` so they're **populated from the geocoded position** (feed is always empty); precision per `geo_source` (`location` vs `cluster` centroid) |
|
| `migrations/04_inc_latlng.sql` | Redefines `latitude`/`longitude` to `COALESCE(feed, ST_Y/ST_X(geom))` so they're **populated from the geocoded position** (feed is always empty); precision per `geo_source` (`location` vs `cluster` centroid) |
|
||||||
| `migrations/05_inc_geography.sql` | Adds `geog geography(Point,4326)` (= `geom::geography`) + GiST index for **routing** — `ST_Distance`/`ST_DWithin`/KNN in real metres (nearest-vehicle, radius search) |
|
| `migrations/05_inc_geography.sql` | Adds `geog geography(Point,4326)` (= `geom::geography`) + GiST index for **routing** — `ST_Distance`/`ST_DWithin`/KNN in real metres (nearest-vehicle, radius search) |
|
||||||
|
| `migrations/06_inc_mttr_minutes.sql` | `mttr` generated column → integer **minutes** (source is decimal hours); drops the constant `is_alarm`/`is_auto_created`/`is_auto_closed` columns (kept in `raw`). `is_actionable` retained |
|
||||||
| `import_tickets.py` | Ingests the **newest INC CSV** from the rustfs `tickets` bucket (`automations/inc/<EAT-timestamp>.csv`) and upserts on `ticket_id`; geocodes clusters + INC locations |
|
| `import_tickets.py` | Ingests the **newest INC CSV** from the rustfs `tickets` bucket (`automations/inc/<EAT-timestamp>.csv`) and upserts on `ticket_id`; geocodes clusters + INC locations |
|
||||||
| `run_migrations.py` | Applies `migrations/*.sql` in order (ledger: `tickets.schema_migrations`) |
|
| `run_migrations.py` | Applies `migrations/*.sql` in order (ledger: `tickets.schema_migrations`) |
|
||||||
| `shared.py` | Minimal DB/logging helpers (self-contained — no tracksolid dependency) |
|
| `shared.py` | Minimal DB/logging helpers (self-contained — no tracksolid dependency) |
|
||||||
|
|
|
||||||
25
migrations/06_inc_mttr_minutes.sql
Normal file
25
migrations/06_inc_mttr_minutes.sql
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
-- 06_inc_mttr_minutes.sql — fleettickets · mttr -> minutes; drop constant flags
|
||||||
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
-- 1. Redefine the mttr generated column as integer MINUTES (source is decimal
|
||||||
|
-- hours) — numeric is the analytics-friendly type for avg/percentile/buckets.
|
||||||
|
-- 2. Drop the is_alarm / is_auto_created / is_auto_closed generated columns: we
|
||||||
|
-- filter is_alarm=true at ingest, so all three are constant `false` in
|
||||||
|
-- tickets.inc (zero information). They remain in `raw` (audit + the loader's
|
||||||
|
-- pre-insert filter still reads raw->>'is_alarm'); is_actionable is kept.
|
||||||
|
-- raw is untouched; only derived columns change. Idempotent.
|
||||||
|
-- ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
SET search_path = tickets, public;
|
||||||
|
|
||||||
|
-- mttr: hours -> integer minutes
|
||||||
|
ALTER TABLE tickets.inc DROP COLUMN IF EXISTS mttr;
|
||||||
|
ALTER TABLE tickets.inc
|
||||||
|
ADD COLUMN IF NOT EXISTS mttr numeric GENERATED ALWAYS AS
|
||||||
|
(round(NULLIF(raw->>'mttr','')::numeric * 60)) STORED;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN tickets.inc.mttr IS 'Mean time to resolve, in MINUTES (source raw.mttr is decimal hours).';
|
||||||
|
|
||||||
|
-- drop the constant boolean flags (still available in raw)
|
||||||
|
ALTER TABLE tickets.inc DROP COLUMN IF EXISTS is_alarm;
|
||||||
|
ALTER TABLE tickets.inc DROP COLUMN IF EXISTS is_auto_created;
|
||||||
|
ALTER TABLE tickets.inc DROP COLUMN IF EXISTS is_auto_closed;
|
||||||
Loading…
Reference in a new issue