fleetfuel/shared.py
kianiadee 9943932200 Initial fleetfuel: rustfs fuel bucket → DB → FleetOps Fuel Log
Self-contained ingestion module (mirrors fleettickets) for the WhatsApp
fuel-record feed in the rustfs `fuel` bucket:

- import_fuel.py — snapshot/changes/file modes, raw-jsonb upsert on id
- migrations/01_fuel_schema.sql — fuel schema, plate/fuel-type/department
  normalizers, trigger-derived columns, reporting.v_fuel_fills +
  v_fuel_efficiency, grafana_ro grants
- s3util.py / shared.py / run_migrations.py — rustfs client + DB helpers
- docs/plan.html — implementation plan

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 23:24:33 +03:00

53 lines
1.5 KiB
Python

"""
shared.py — fleetfuel · minimal DB + helper utilities.
Self-contained (mirrors 16_fleettickets/shared.py) so fleetfuel stands alone.
The DB connection comes from DATABASE_URL (points at the shared `tracksolid_db`,
where the `fuel` schema lives alongside `tracksolid` / `reporting` / `tickets`).
"""
from __future__ import annotations
import logging
import os
from contextlib import contextmanager
from typing import Any, Optional
import psycopg2
def get_logger(name: str) -> logging.Logger:
logger = logging.getLogger(f"fleetfuel.{name}")
if not logger.handlers:
h = logging.StreamHandler()
h.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(name)s%(message)s",
datefmt="%Y-%m-%d %H:%M:%S"))
logger.addHandler(h)
logger.setLevel(os.getenv("LOG_LEVEL", "INFO"))
return logger
@contextmanager
def get_conn():
"""DB connection context manager. Auto-commits on success, rolls back on error."""
dsn = os.environ.get("DATABASE_URL")
if not dsn:
raise RuntimeError("DATABASE_URL is not set")
conn = psycopg2.connect(dsn)
try:
conn.autocommit = False
yield conn
conn.commit()
except Exception:
conn.rollback()
raise
finally:
conn.close()
def clean(v: Any) -> Optional[str]:
"""Trimmed string, or None if empty/None."""
if v is None:
return None
s = str(v).strip()
return s if s != "" else None