"""Immutable PostgreSQL history of feedback-aligned KPI points.""" from typing import Protocol import psycopg from production_analytics.calculations.config import finite_number from production_analytics.service.material_efficiency import MaterialEfficiencySnapshot from production_analytics.service.postgres_material import PostgresSettings class MaterialEfficiencyWriter(Protocol): def write(self, snapshot: MaterialEfficiencySnapshot) -> bool: ... class PostgresMaterialEfficiencyWriter: def __init__(self, settings: PostgresSettings) -> None: self.settings = settings def write(self, snapshot: MaterialEfficiencySnapshot) -> bool: for name in ("erp_feedback_timestamp", "material_snapshot_timestamp"): if getattr(snapshot, name).utcoffset() is None: raise ValueError(f"{name} must be timezone-aware") for name in ( "good_quantity_m2", "material_consumption_kg", "material_consumption_kg_per_m2", "material_consumption_g_per_m2", ): finite_number(getattr(snapshot, name), name) if snapshot.nominal_width_m is not None: finite_number(snapshot.nominal_width_m, "nominal_width_m") # Context exit commits/rolls back and closes; later cycles reconnect after outages. with psycopg.connect( host=self.settings.host, port=self.settings.port, dbname=self.settings.dbname, user=self.settings.user, password=self.settings.password, connect_timeout=10, options="-c statement_timeout=10000", ) as connection: row = connection.execute( """INSERT INTO material_efficiency_snapshots ( erp_feedback_timestamp, material_snapshot_timestamp, calculation_id, machine_id, workplace, erp_production_order, enlyze_production_order, article_number, article_description, nominal_width_m, good_quantity_m2, material_consumption_kg, material_consumption_kg_per_m2, material_consumption_g_per_m2 ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) ON CONFLICT (calculation_id, machine_id, enlyze_production_order, erp_feedback_timestamp) DO NOTHING RETURNING 1""", ( snapshot.erp_feedback_timestamp, snapshot.material_snapshot_timestamp, snapshot.calculation_id, snapshot.machine_id, snapshot.workplace, snapshot.erp_production_order, snapshot.enlyze_production_order, snapshot.article_number, snapshot.article_description, snapshot.nominal_width_m, snapshot.good_quantity_m2, snapshot.material_consumption_kg, snapshot.material_consumption_kg_per_m2, snapshot.material_consumption_g_per_m2, ), ).fetchone() return row is not None