114 lines
4.3 KiB
Python
114 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
from ast import literal_eval
|
|
from collections import defaultdict
|
|
|
|
from odoo import fields, models, _, api
|
|
from odoo.tools import float_round
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class MrpProduction(models.Model):
|
|
_inherit = 'mrp.production'
|
|
|
|
|
|
|
|
|
|
def _get_moves_raw_values(self):
|
|
moves = []
|
|
for production in self:
|
|
if not production.bom_id:
|
|
continue
|
|
factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) / production.bom_id.product_qty
|
|
_boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id, never_attribute_values=production.never_product_template_attribute_value_ids)
|
|
for bom_line, line_data in lines:
|
|
# if bom_line.child_bom_id and bom_line.child_bom_id.type == 'phantom' or\
|
|
# bom_line.product_id.type != 'consu':
|
|
if bom_line.child_bom_id and bom_line.child_bom_id.type == 'phantom':
|
|
continue
|
|
operation = bom_line.operation_id.id or line_data['parent_line'] and line_data['parent_line'].operation_id.id
|
|
moves.append(production._get_move_raw_values(
|
|
bom_line.product_id,
|
|
line_data['qty'],
|
|
bom_line.product_uom_id,
|
|
operation,
|
|
bom_line
|
|
))
|
|
return moves
|
|
|
|
|
|
def action_confirm(self):
|
|
res = super(MrpProduction,self).action_confirm()
|
|
for rec in self:
|
|
rec.product_id.button_bom_cost()
|
|
return res
|
|
|
|
|
|
class MrpBomLine(models.Model):
|
|
_inherit = 'mrp.bom.line'
|
|
|
|
unit_cost = fields.Float(compute='_compute_product_price', digits=(16, 2), string="Unit Cost")
|
|
total_price = fields.Float(compute='_compute_total_price', string="Total Cost")
|
|
is_service_product = fields.Float(compute='_compute_is_service_product', default=False)
|
|
|
|
|
|
@api.depends('product_id')
|
|
def _compute_product_price(self):
|
|
for rec in self:
|
|
if rec.product_id:
|
|
# Get product cost in the company context
|
|
standard_price = rec.product_id.with_company(rec.env.company).standard_price
|
|
|
|
# Convert cost from product's UoM to BoM line UoM
|
|
unit_cost = rec.product_id.uom_id._compute_price(
|
|
standard_price, rec.product_uom_id
|
|
)
|
|
rec.unit_cost = unit_cost
|
|
else:
|
|
rec.unit_cost = 0.0
|
|
|
|
@api.depends('unit_cost', 'product_qty')
|
|
def _compute_total_price(self):
|
|
for rec in self:
|
|
if rec.product_id:
|
|
# Get product cost in the company context
|
|
standard_price = rec.product_id.with_company(rec.env.company).standard_price
|
|
|
|
# Convert cost from product's UoM to BoM line UoM
|
|
unit_cost = rec.product_id.uom_id._compute_price(
|
|
standard_price, rec.product_uom_id
|
|
)
|
|
else:
|
|
unit_cost = 0.0
|
|
rec.total_price = unit_cost * rec.product_qty
|
|
|
|
@api.depends('product_id')
|
|
def _compute_is_service_product(self):
|
|
for rec in self:
|
|
rec.is_service_product = True if rec.product_id.type == 'service' else False
|
|
|
|
@api.constrains('product_id', 'bom_id')
|
|
@api.onchange('product_id', 'bom_id')
|
|
def _check_unique_product_in_bom(self):
|
|
for line in self:
|
|
# Find all lines in the same BoM with the same product
|
|
duplicate_lines = line.bom_id.bom_line_ids.filtered(
|
|
lambda l: l.product_id == line.product_id
|
|
)
|
|
if len(duplicate_lines) > 1:
|
|
raise ValidationError(
|
|
f"The product '{line.product_id.display_name}' is already used in this BoM."
|
|
)
|
|
|
|
|
|
|
|
class StockMove(models.Model):
|
|
_inherit = 'stock.move'
|
|
|
|
|
|
is_service_product = fields.Float(compute='_compute_is_service_product', default=False)
|
|
@api.depends('product_id')
|
|
def _compute_is_service_product(self):
|
|
for rec in self:
|
|
rec.is_service_product = True if rec.product_id.type == 'service' else False
|