# -*- 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 FpExposureMonitoring(models.Model): """An exposure monitoring sample. A monitoring event captures one measurement of a worker's or area's exposure to a hazardous agent — air contaminant, biological marker, noise or vibration. The result is compared against an Occupational Exposure Limit (OEL), most commonly the time-weighted average (TWA) or short-term exposure limit (STEL) published by the relevant jurisdiction (e.g. Ontario Reg. 833 in Canada). The percent-of-OEL is calculated automatically and the record is classified as below, approaching or exceeding the limit, providing an early warning when controls need to be tightened. """ _name = 'fusion.plating.exposure.monitoring' _description = 'Fusion Plating — Exposure Monitoring' _inherit = ['mail.thread', 'mail.activity.mixin'] _order = 'sample_date desc, id desc' _rec_name = 'name' name = fields.Char( string='Reference', required=True, copy=False, readonly=True, default=lambda self: self._default_name(), tracking=True, ) employee_id = fields.Many2one( 'hr.employee', string='Employee', ondelete='set null', tracking=True, ) facility_id = fields.Many2one( 'fusion.plating.facility', string='Facility', tracking=True, ) sample_date = fields.Date( string='Sample Date', required=True, default=fields.Date.context_today, tracking=True, ) sample_type = fields.Selection( [ ('personal_air', 'Personal Air'), ('area_air', 'Area Air'), ('biological', 'Biological'), ('noise', 'Noise'), ('vibration', 'Vibration'), ], string='Sample Type', default='personal_air', required=True, tracking=True, ) substance = fields.Char( string='Substance / Agent', tracking=True, ) concentration = fields.Float( string='Concentration', tracking=True, ) uom = fields.Char( string='Unit of Measure', help='Free-text unit, e.g. mg/m3, ppm, dBA.', ) oel_reference = fields.Char( string='OEL Reference', help='Citation for the exposure limit, e.g. "Ontario Reg. 833 TWA".', ) oel_limit = fields.Float( string='OEL Limit', ) percent_of_oel = fields.Float( string='% of OEL', compute='_compute_percent_of_oel', store=True, ) result = fields.Selection( [ ('below', 'Below'), ('approaching', 'Approaching'), ('exceed', 'Exceeds'), ], string='Result', compute='_compute_result', store=True, tracking=True, ) notes = fields.Html( string='Notes', ) company_id = fields.Many2one( 'res.company', string='Company', default=lambda self: self.env.company, ) active = fields.Boolean(default=True) # ========================================================================== # Defaults # ========================================================================== @api.model def _default_name(self): seq = self.env['ir.sequence'].next_by_code('fusion.plating.exposure.monitoring') return seq or '/' # ========================================================================== # Computes # ========================================================================== @api.depends('concentration', 'oel_limit') def _compute_percent_of_oel(self): for rec in self: if rec.oel_limit: rec.percent_of_oel = (rec.concentration / rec.oel_limit) * 100.0 else: rec.percent_of_oel = 0.0 @api.depends('percent_of_oel') def _compute_result(self): for rec in self: if rec.percent_of_oel >= 100.0: rec.result = 'exceed' elif rec.percent_of_oel >= 50.0: rec.result = 'approaching' else: rec.result = 'below'