# -*- 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 FpBathLog(models.Model): """A daily / per-shift chemistry log for a bath. One log record represents one sampling event: an operator walks to a tank, runs titrations or reads instruments, and enters the results. Each log has one or more lines (one per parameter). Overall log status is rolled up from the lines: * ok — every line is within target * warning — at least one line is within warning tolerance * out_of_spec — at least one line is outside target """ _name = 'fusion.plating.bath.log' _description = 'Fusion Plating — Bath Chemistry Log' _inherit = ['mail.thread', 'mail.activity.mixin'] _order = 'log_date desc, id desc' _rec_name = 'display_name' name = fields.Char( string='Reference', required=True, copy=False, default=lambda self: self._default_name(), tracking=True, ) display_name = fields.Char( compute='_compute_display_name', store=True, ) bath_id = fields.Many2one( 'fusion.plating.bath', string='Bath', required=True, ondelete='cascade', tracking=True, ) tank_id = fields.Many2one( related='bath_id.tank_id', store=True, readonly=True, ) facility_id = fields.Many2one( related='bath_id.facility_id', store=True, readonly=True, ) process_type_id = fields.Many2one( related='bath_id.process_type_id', store=True, readonly=True, ) company_id = fields.Many2one( related='bath_id.company_id', store=True, readonly=True, ) log_date = fields.Datetime( string='Logged At', default=fields.Datetime.now, required=True, tracking=True, ) operator_id = fields.Many2one( 'res.users', string='Operator', default=lambda self: self.env.user, tracking=True, ) shift = fields.Selection( [ ('day', 'Day'), ('evening', 'Evening'), ('night', 'Night'), ], string='Shift', ) line_ids = fields.One2many( 'fusion.plating.bath.log.line', 'log_id', string='Readings', copy=True, ) status = fields.Selection( [ ('ok', 'OK'), ('warning', 'Warning'), ('out_of_spec', 'Out of Spec'), ], string='Status', compute='_compute_status', store=True, tracking=True, ) status_color = fields.Integer( compute='_compute_status_color', ) notes = fields.Text( string='Notes', ) # ========================================================================== @api.model def _default_name(self): seq = self.env['ir.sequence'].next_by_code('fusion.plating.bath.log') return seq or '/' @api.depends('name', 'bath_id', 'log_date') def _compute_display_name(self): for rec in self: parts = [] if rec.bath_id: parts.append(rec.bath_id.name) if rec.log_date: parts.append(fields.Datetime.to_string(rec.log_date)) rec.display_name = ' — '.join(parts) if parts else rec.name @api.depends('line_ids', 'line_ids.status') def _compute_status(self): for rec in self: statuses = set(rec.line_ids.mapped('status')) if 'out_of_spec' in statuses: rec.status = 'out_of_spec' elif 'warning' in statuses: rec.status = 'warning' else: rec.status = 'ok' @api.depends('status') def _compute_status_color(self): # Kanban color indexes: 0 default, 1 red, 3 yellow, 4 green mapping = {'ok': 4, 'warning': 3, 'out_of_spec': 1} for rec in self: rec.status_color = mapping.get(rec.status, 0)