diff --git a/fusion_iot/fusion_plating_iot/__manifest__.py b/fusion_iot/fusion_plating_iot/__manifest__.py index 6bdaab00..929ef302 100644 --- a/fusion_iot/fusion_plating_iot/__manifest__.py +++ b/fusion_iot/fusion_plating_iot/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — IoT Integration', - 'version': '19.0.0.1.0', + 'version': '19.0.0.2.0', 'category': 'Manufacturing/Plating', 'summary': 'Wire physical tank sensors to Fusion Plating — live ' 'temperature / chemistry readings with auto quality holds ' diff --git a/fusion_iot/fusion_plating_iot/models/fp_tank_reading.py b/fusion_iot/fusion_plating_iot/models/fp_tank_reading.py index 6e8cd708..0035eb8e 100644 --- a/fusion_iot/fusion_plating_iot/models/fp_tank_reading.py +++ b/fusion_iot/fusion_plating_iot/models/fp_tank_reading.py @@ -54,14 +54,47 @@ class FpTankReading(models.Model): default=fields.Datetime.now, index=True, ) value = fields.Float( - string='Value', required=True, digits=(12, 4), - help='Numeric reading in the parameter\'s native unit (°C, pH, ' - 'µS/cm, etc.).', + string='Value (raw)', required=True, digits=(12, 4), + help='Stored reading in the sensor\'s canonical unit (for ' + 'temperature sensors this is always °C — the DS18B20 and ' + 'every other temperature chip reports in Celsius natively; ' + 'keeping storage canonical lets us switch display units ' + 'per-company without re-migrating history).', ) unit = fields.Char( - string='Unit', related='parameter_id.uom', store=True, + string='Unit (raw)', related='parameter_id.uom', store=True, ) + # ------------------------------------------------------------------ + # Display-aware fields — converted to the company's preferred unit + # (res.company.x_fc_default_temp_uom = 'F' or 'C'). Only the list + # and form views should show these; internal spec comparisons use + # `value` so thresholds stay consistent across regions. + # ------------------------------------------------------------------ + display_value = fields.Float( + string='Value', compute='_compute_display', + digits=(12, 2), + help='Reading in the company-preferred unit (Settings → Plating → ' + 'Temperature Unit).', + ) + display_unit = fields.Char( + string='Unit', compute='_compute_display', + ) + + @api.depends('value', 'parameter_id', 'parameter_id.parameter_type', + 'parameter_id.uom') + def _compute_display(self): + # Read once per compute call — env.company rarely changes mid-batch. + pref = self.env.company.x_fc_default_temp_uom or 'C' + for r in self: + ptype = (r.parameter_id.parameter_type or '').lower() + if ptype == 'temperature' and pref == 'F': + r.display_value = r.value * 9.0 / 5.0 + 32.0 + r.display_unit = '°F' + else: + r.display_value = r.value + r.display_unit = r.parameter_id.uom or '' + source = fields.Selection( [ ('iot_proxy', 'IoT Proxy (Pi)'), @@ -86,13 +119,12 @@ class FpTankReading(models.Model): string='Display', compute='_compute_display_name', store=True, ) - @api.depends('sensor_id', 'value', 'reading_at') + @api.depends('sensor_id', 'display_value', 'display_unit', 'reading_at') def _compute_display_name(self): for r in self: sensor = r.sensor_id.name or 'sensor' at = fields.Datetime.to_string(r.reading_at) if r.reading_at else '' - unit = r.unit or '' - r.display_name = f'{sensor} — {r.value:.2f} {unit} @ {at}' + r.display_name = f'{sensor} — {r.display_value:.2f} {r.display_unit} @ {at}' # ------------------------------------------------------------------ # Create hook — evaluate against spec + raise a quality hold if we diff --git a/fusion_iot/fusion_plating_iot/models/fp_tank_sensor.py b/fusion_iot/fusion_plating_iot/models/fp_tank_sensor.py index 6ed86eaf..ee734cc7 100644 --- a/fusion_iot/fusion_plating_iot/models/fp_tank_sensor.py +++ b/fusion_iot/fusion_plating_iot/models/fp_tank_sensor.py @@ -98,13 +98,38 @@ class FpTankSensor(models.Model): # Cached latest-reading fields (for quick display in list views) # ------------------------------------------------------------------ last_reading_value = fields.Float( - string='Latest Value', readonly=True, digits=(12, 4), + string='Latest Value (raw)', readonly=True, digits=(12, 4), + help='Stored in the sensor\'s canonical unit (°C for temperature).', ) last_reading_at = fields.Datetime(string='Latest Reading', readonly=True) last_reading_in_spec = fields.Boolean( string='In Spec?', readonly=True, help='Computed from the last reading vs alert_min/alert_max.', ) + # Display-aware version of last_reading_value — converted to company + # preferred unit (res.company.x_fc_default_temp_uom). + last_reading_display = fields.Float( + string='Latest Value', + compute='_compute_last_reading_display', + digits=(12, 2), + ) + last_reading_display_unit = fields.Char( + string='Unit', + compute='_compute_last_reading_display', + ) + + @api.depends('last_reading_value', 'parameter_id', + 'parameter_id.parameter_type', 'parameter_id.uom') + def _compute_last_reading_display(self): + pref = self.env.company.x_fc_default_temp_uom or 'C' + for rec in self: + ptype = (rec.parameter_id.parameter_type or '').lower() + if ptype == 'temperature' and pref == 'F': + rec.last_reading_display = rec.last_reading_value * 9.0 / 5.0 + 32.0 + rec.last_reading_display_unit = '°F' + else: + rec.last_reading_display = rec.last_reading_value + rec.last_reading_display_unit = rec.parameter_id.uom or '' reading_ids = fields.One2many( 'fp.tank.reading', 'sensor_id', string='Reading History', diff --git a/fusion_iot/fusion_plating_iot/views/fp_tank_reading_views.xml b/fusion_iot/fusion_plating_iot/views/fp_tank_reading_views.xml index 9b5280c4..e2023b95 100644 --- a/fusion_iot/fusion_plating_iot/views/fp_tank_reading_views.xml +++ b/fusion_iot/fusion_plating_iot/views/fp_tank_reading_views.xml @@ -15,8 +15,9 @@ - - + + + @@ -39,8 +40,10 @@ - - + + + diff --git a/fusion_iot/fusion_plating_iot/views/fp_tank_sensor_views.xml b/fusion_iot/fusion_plating_iot/views/fp_tank_sensor_views.xml index 6c17944e..fe03d2ac 100644 --- a/fusion_iot/fusion_plating_iot/views/fp_tank_sensor_views.xml +++ b/fusion_iot/fusion_plating_iot/views/fp_tank_sensor_views.xml @@ -19,7 +19,9 @@ - + + + @@ -76,7 +78,11 @@ help="Leave 0 to inherit from the bath parameter's target_max."/> - + + + diff --git a/fusion_iot/fusion_plating_iot/views/fusion_plating_tank_views.xml b/fusion_iot/fusion_plating_iot/views/fusion_plating_tank_views.xml index b2d63ad7..d9a0c04c 100644 --- a/fusion_iot/fusion_plating_iot/views/fusion_plating_tank_views.xml +++ b/fusion_iot/fusion_plating_iot/views/fusion_plating_tank_views.xml @@ -24,7 +24,8 @@ - + +