Add feedback-aligned material efficiency KPI
This commit is contained in:
@@ -297,9 +297,80 @@ finished-product width:
|
||||
it belongs to the MAHLO measurement system and observed values differ from nominal
|
||||
article widths. Structured ERP product master data would be preferred when available.
|
||||
|
||||
These helpers are independent of database access and are not yet wired into live
|
||||
processing. No normalized context model, kg/m² or material-efficiency calculation,
|
||||
persistence, polling, runner, timeseries, or Grafana changes are introduced here.
|
||||
These helpers are independent of database access. The service below composes them
|
||||
for material efficiency; no background processing is attached.
|
||||
|
||||
## Feedback-aligned material efficiency
|
||||
|
||||
`MaterialEfficiencyService` in `service.material_efficiency` combines ERP good area
|
||||
with cumulative material consumption for one exact production order. Its
|
||||
`evaluate_current()` reads the existing ERP workplace adapter once; `evaluate(status)`
|
||||
evaluates an already supplied `CurrentWorkplaceStatus`. Both return an immutable
|
||||
`MaterialEfficiencySnapshot` or `None` when inputs are unavailable.
|
||||
|
||||
`PostgresMaterialSnapshotRepository(settings).latest_at_or_before(...)` in
|
||||
`service.postgres_material` takes keyword arguments `calculation_id`, `machine_id`,
|
||||
`production_order`, and an aware `timestamp`. A parameterized query selects the
|
||||
latest snapshot **at or before ERP feedback time**, matching calculation, machine,
|
||||
and mapped order exactly. It returns `MaterialConsumptionSnapshot` or `None`.
|
||||
Run IDs do not restrict this lookup: stored consumption is already cumulative
|
||||
across the order's runs. The service neither reintegrates nor sums snapshots and
|
||||
does not bridge run boundaries.
|
||||
|
||||
The result includes workplace/machine/calculation identifiers, both order identifiers,
|
||||
article context, nominal width, both original source timestamps, good area, aligned
|
||||
consumption, `material_consumption_kg_per_m2 = consumption_kg / good_quantity_m2`,
|
||||
and `material_consumption_g_per_m2 = material_consumption_kg_per_m2 * 1000`.
|
||||
Nominal width comes from generic ERP description parsing and is context only;
|
||||
ERP good square metres remain authoritative even when width cannot be parsed.
|
||||
|
||||
Missing ERP status, missing aligned material, missing/non-positive/non-finite good
|
||||
area, invalid consumption (negative or non-finite), or non-finite computed ratios
|
||||
produce `None`. Zero consumption is valid. Configuration errors, invalid timestamp
|
||||
alignment, and database failures raise rather than masquerading as missing data.
|
||||
|
||||
All machine/workplace settings are supplied explicitly. Example using the existing
|
||||
K7 material calculation (with previously constructed ERP gateway and PG settings):
|
||||
|
||||
```python
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from production_analytics.service.material_efficiency import MaterialEfficiencyService
|
||||
from production_analytics.service.postgres_material import PostgresMaterialSnapshotRepository
|
||||
|
||||
service = MaterialEfficiencyService(
|
||||
erp_gateway, PostgresMaterialSnapshotRepository(postgres_settings),
|
||||
workplace="K7",
|
||||
machine_id="c220f95c-a65e-4cb7-99b7-0626d6c7508c",
|
||||
calculation_id="k7-fiber-consumption",
|
||||
format_template="K 7-{production_order}",
|
||||
# Supply only after verifying the ERP timestamp's source timezone:
|
||||
erp_timezone=ZoneInfo("Europe/Berlin"),
|
||||
)
|
||||
result = service.evaluate_current()
|
||||
```
|
||||
|
||||
Aware ERP timestamps are compared as UTC instants. Naive ERP timestamps require
|
||||
explicit `erp_timezone`; there is no inferred system/database timezone. Ambiguous
|
||||
or nonexistent local times during DST transitions are rejected. The original ERP
|
||||
timestamp (including naivety) and selected material timestamp are preserved in the
|
||||
result; retain the source timezone configuration alongside it for interpretation.
|
||||
|
||||
This alignment avoids knowingly including future material consumption, but does
|
||||
not eliminate ERP roll-feedback timing uncertainty (feedback may be roughly one
|
||||
roll ahead or otherwise offset). Live values are plausibility indicators; final
|
||||
production-order values are more meaningful as relative timing error diminishes.
|
||||
There is no interpolation, lag correction, smoothing, freshness threshold, or
|
||||
estimated timestamp. Historical bootstrap snapshots are usable only when their
|
||||
stored timestamps satisfy the cutoff; a later cumulative total cannot reconstruct
|
||||
an earlier value. Reliable final evaluation requires retaining final ERP feedback;
|
||||
the current-workplace adapter alone does not provide historical completed orders.
|
||||
|
||||
Call on changed ERP feedback; no new runner or polling loop is provided. Results
|
||||
are returned in memory without modifying earlier results or material snapshots.
|
||||
No schema, Grafana, or timeseries changes are needed. Daily per-machine 24h reporting
|
||||
and aggregation remain future work. Repository SQL selection tests use an in-memory
|
||||
SQLite fixture with driver transport adaptation; they require no live PostgreSQL.
|
||||
|
||||
## Peak-cycle detection
|
||||
|
||||
|
||||
Reference in New Issue
Block a user