changes
This commit is contained in:
114
fusion-plating/fusion_plating/models/fp_bath_log_line.py
Normal file
114
fusion-plating/fusion_plating/models/fp_bath_log_line.py
Normal file
@@ -0,0 +1,114 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
# Part of the Fusion Plating product family.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class FpBathLogLine(models.Model):
|
||||
"""A single parameter reading on a bath log.
|
||||
|
||||
Each line = one titration result or one sensor reading. Target ranges
|
||||
are pulled from the bath's per-bath overrides if present, otherwise
|
||||
from the parameter's defaults on fusion.plating.bath.parameter.
|
||||
Status is computed per line (ok / warning / out_of_spec) and rolled
|
||||
up to the parent log.
|
||||
"""
|
||||
_name = 'fusion.plating.bath.log.line'
|
||||
_description = 'Fusion Plating — Bath Log Reading'
|
||||
_order = 'log_id, sequence, id'
|
||||
|
||||
log_id = fields.Many2one(
|
||||
'fusion.plating.bath.log',
|
||||
string='Log',
|
||||
required=True,
|
||||
ondelete='cascade',
|
||||
index=True,
|
||||
)
|
||||
bath_id = fields.Many2one(
|
||||
related='log_id.bath_id',
|
||||
store=True,
|
||||
readonly=True,
|
||||
)
|
||||
sequence = fields.Integer(
|
||||
string='Sequence',
|
||||
default=10,
|
||||
)
|
||||
parameter_id = fields.Many2one(
|
||||
'fusion.plating.bath.parameter',
|
||||
string='Parameter',
|
||||
required=True,
|
||||
ondelete='restrict',
|
||||
)
|
||||
parameter_code = fields.Char(
|
||||
related='parameter_id.code',
|
||||
store=True,
|
||||
readonly=True,
|
||||
)
|
||||
uom = fields.Char(
|
||||
related='parameter_id.uom',
|
||||
readonly=True,
|
||||
)
|
||||
value = fields.Float(
|
||||
string='Value',
|
||||
required=True,
|
||||
)
|
||||
target_min = fields.Float(
|
||||
string='Target Min',
|
||||
compute='_compute_targets',
|
||||
store=True,
|
||||
)
|
||||
target_max = fields.Float(
|
||||
string='Target Max',
|
||||
compute='_compute_targets',
|
||||
store=True,
|
||||
)
|
||||
status = fields.Selection(
|
||||
[
|
||||
('ok', 'OK'),
|
||||
('warning', 'Warning'),
|
||||
('out_of_spec', 'Out of Spec'),
|
||||
],
|
||||
string='Status',
|
||||
compute='_compute_status',
|
||||
store=True,
|
||||
)
|
||||
notes = fields.Char(
|
||||
string='Notes',
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
@api.depends('parameter_id', 'log_id.bath_id')
|
||||
def _compute_targets(self):
|
||||
"""Resolve target range: per-bath override first, parameter default second."""
|
||||
for rec in self:
|
||||
tmin = tmax = 0.0
|
||||
if rec.log_id.bath_id and rec.parameter_id:
|
||||
override = rec.log_id.bath_id.target_line_ids.filtered(
|
||||
lambda t: t.parameter_id.id == rec.parameter_id.id
|
||||
)[:1]
|
||||
if override:
|
||||
tmin, tmax = override.target_min, override.target_max
|
||||
else:
|
||||
tmin = rec.parameter_id.target_min
|
||||
tmax = rec.parameter_id.target_max
|
||||
rec.target_min = tmin
|
||||
rec.target_max = tmax
|
||||
|
||||
@api.depends('value', 'target_min', 'target_max', 'parameter_id.warning_tolerance')
|
||||
def _compute_status(self):
|
||||
for rec in self:
|
||||
if rec.target_min == 0.0 and rec.target_max == 0.0:
|
||||
rec.status = 'ok'
|
||||
continue
|
||||
v, lo, hi = rec.value, rec.target_min, rec.target_max
|
||||
if v < lo or v > hi:
|
||||
rec.status = 'out_of_spec'
|
||||
continue
|
||||
tol_pct = (rec.parameter_id.warning_tolerance or 0.0) / 100.0
|
||||
span = max(hi - lo, 1e-9)
|
||||
if tol_pct > 0 and (v - lo < span * tol_pct or hi - v < span * tol_pct):
|
||||
rec.status = 'warning'
|
||||
else:
|
||||
rec.status = 'ok'
|
||||
Reference in New Issue
Block a user