102 lines
3.4 KiB
Python
102 lines
3.4 KiB
Python
# -*- 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
|
|
|
|
from odoo.addons.fusion_plating.models._fp_uom_selection import FP_UOM_SELECTION
|
|
|
|
|
|
class FpChemical(models.Model):
|
|
"""Physical chemical container in the shop's chemical inventory.
|
|
|
|
A chemical record represents a managed container — drum, tote, jug,
|
|
cylinder — of a specific product, stored in a specific facility and
|
|
location, with on-hand quantity and reorder thresholds. It links to the
|
|
Safety Data Sheet that governs handling, and may optionally link to the
|
|
Odoo product/stock record when the same chemistry is also tracked as
|
|
inventory.
|
|
|
|
Storage compatibility (acid vs base, oxidizer vs flammable, etc.) is
|
|
captured via a self-referential many2many of incompatible chemicals so
|
|
a future workflow can warn on co-located storage.
|
|
"""
|
|
_name = 'fusion.plating.chemical'
|
|
_description = 'Fusion Plating — Chemical'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_order = 'name'
|
|
|
|
name = fields.Char(
|
|
string='Chemical',
|
|
required=True,
|
|
tracking=True,
|
|
)
|
|
sds_id = fields.Many2one(
|
|
'fusion.plating.sds',
|
|
string='Safety Data Sheet',
|
|
tracking=True,
|
|
)
|
|
product_id = fields.Many2one(
|
|
'product.product',
|
|
string='Stock Product',
|
|
help='Optional link to the Odoo product when the chemistry is also '
|
|
'tracked as inventory.',
|
|
)
|
|
facility_id = fields.Many2one(
|
|
'fusion.plating.facility',
|
|
string='Facility',
|
|
tracking=True,
|
|
)
|
|
location = fields.Char(
|
|
string='Storage Location',
|
|
help='Free-text storage location, e.g. "Acid Cabinet 2" or "Drum bay B".',
|
|
)
|
|
container_size = fields.Float(
|
|
string='Container Size',
|
|
help='Numerical size of one container, expressed in the unit '
|
|
'selected below (e.g. 200 with unit "L" for a 200 L drum).',
|
|
)
|
|
container_uom = fields.Selection(
|
|
FP_UOM_SELECTION,
|
|
string='Container UoM',
|
|
help='Unit of measure for the container size — pick from the '
|
|
'curated list to keep inventory consistent (L, kg, lb, gal).',
|
|
)
|
|
quantity_on_hand = fields.Float(
|
|
string='Quantity On Hand',
|
|
tracking=True,
|
|
)
|
|
reorder_point = fields.Float(
|
|
string='Reorder Point',
|
|
help='When quantity on hand falls below this level, the chemical '
|
|
'should be reordered.',
|
|
)
|
|
incompatible_with_ids = fields.Many2many(
|
|
'fusion.plating.chemical',
|
|
'fp_chemical_incompat_rel',
|
|
'chemical_id',
|
|
'incompatible_id',
|
|
string='Incompatible With',
|
|
help='Chemicals that must not be stored next to this one.',
|
|
)
|
|
needs_reorder = fields.Boolean(
|
|
string='Needs Reorder',
|
|
compute='_compute_needs_reorder',
|
|
store=True,
|
|
)
|
|
company_id = fields.Many2one(
|
|
'res.company',
|
|
string='Company',
|
|
default=lambda self: self.env.company,
|
|
)
|
|
active = fields.Boolean(default=True)
|
|
notes = fields.Html(string='Notes')
|
|
|
|
@api.depends('quantity_on_hand', 'reorder_point')
|
|
def _compute_needs_reorder(self):
|
|
for rec in self:
|
|
rec.needs_reorder = bool(
|
|
rec.reorder_point and rec.quantity_on_hand <= rec.reorder_point
|
|
)
|