This commit is contained in:
gsinghpal
2026-04-26 15:05:17 -04:00
parent 160198edb1
commit d9f58b9851
110 changed files with 6210 additions and 1182 deletions

View File

@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
#
# Phase 1 (Sub 11) — relocated from fusion_plating_bridge_mrp.
# MRP-flavoured fields (production_id, workorder_id) replaced by their
# native fp.job / fp.job.step equivalents.
from odoo import api, fields, models, _
class FpJobConsumption(models.Model):
"""A single consumable drawdown charged to a plating job.
Sources include bath replenishment applied against a job, masking tape
rolls, PPE, nickel salts — anything that has a cost and should roll
into job costing.
Kept deliberately lightweight: one row per event, cost derived from
`product.standard_price` at log time (snapshot, not reactive).
"""
_name = 'fp.job.consumption'
_description = 'Fusion Plating — Job Consumption'
_order = 'logged_date desc, id desc'
job_id = fields.Many2one(
'fp.job', string='Plating Job',
required=True, ondelete='cascade', index=True,
)
step_id = fields.Many2one(
'fp.job.step', string='Job Step',
domain="[('job_id', '=', job_id)]",
ondelete='set null',
)
product_id = fields.Many2one(
'product.product', string='Product', required=True,
domain="[('sale_ok', '=', False)]",
)
product_name = fields.Char(
string='Product Name (snapshot)',
help='Free-text product label if no inventory product is linked.',
)
quantity = fields.Float(string='Quantity', required=True, digits=(12, 3))
uom_id = fields.Many2one(
'uom.uom', string='UoM',
)
currency_id = fields.Many2one(
'res.currency', required=True,
default=lambda self: self.env.company.currency_id,
)
unit_cost = fields.Monetary(
string='Unit Cost (snapshot)', currency_field='currency_id',
help='Taken from product.standard_price at log time.',
)
total_cost = fields.Monetary(
string='Total Cost', currency_field='currency_id',
compute='_compute_total_cost', store=True,
)
logged_date = fields.Datetime(
string='Logged', default=fields.Datetime.now,
)
logged_by_id = fields.Many2one(
'res.users', string='Logged By', default=lambda self: self.env.user,
)
source = fields.Selection(
[('replenishment', 'Bath Replenishment'),
('masking', 'Masking Material'),
('ppe', 'PPE / Consumables'),
('chemistry', 'Process Chemistry'),
('other', 'Other')],
string='Source', default='other', required=True,
)
replenishment_id = fields.Many2one(
'fusion.plating.bath.replenishment.suggestion',
string='Replenishment Suggestion',
ondelete='set null',
)
notes = fields.Char(string='Notes')
@api.depends('quantity', 'unit_cost')
def _compute_total_cost(self):
for rec in self:
rec.total_cost = round((rec.quantity or 0) * (rec.unit_cost or 0), 2)
@api.depends('product_id', 'product_name', 'quantity', 'job_id')
def _compute_display_name(self):
for rec in self:
label = rec.product_id.display_name or rec.product_name or 'Consumption'
qty = ('%g' % rec.quantity) if rec.quantity else ''
job = rec.job_id.name or ''
bits = [label]
if qty:
bits.append('×' + qty)
if job:
bits.append('(%s)' % job)
rec.display_name = ' '.join(bits)
@api.onchange('product_id')
def _onchange_product(self):
if self.product_id:
self.product_name = self.product_id.display_name
self.unit_cost = self.product_id.standard_price or 0.0
self.uom_id = self.product_id.uom_id or False