From 080d76d7e3c7607d64074a94e62a394e549b368b Mon Sep 17 00:00:00 2001 From: carcaroff Date: Mon, 9 Apr 2018 17:17:09 -0300 Subject: [PATCH] [KINDA FEAT] Dynamic lines for BoM --- mrp_dynamic_bom/__init__.py | 1 + mrp_dynamic_bom/__manifest__.py | 24 +++++ mrp_dynamic_bom/models/__init__.py | 2 + mrp_dynamic_bom/models/mrp_bom.py | 37 ++++++++ mrp_dynamic_bom/models/mrp_production.py | 91 +++++++++++++++++++ mrp_dynamic_bom/security/ir.model.access.csv | 3 + .../views/mrp_dynamic_bom_views.xml | 36 ++++++++ 7 files changed, 194 insertions(+) create mode 100644 mrp_dynamic_bom/__init__.py create mode 100644 mrp_dynamic_bom/__manifest__.py create mode 100644 mrp_dynamic_bom/models/__init__.py create mode 100644 mrp_dynamic_bom/models/mrp_bom.py create mode 100644 mrp_dynamic_bom/models/mrp_production.py create mode 100644 mrp_dynamic_bom/security/ir.model.access.csv create mode 100644 mrp_dynamic_bom/views/mrp_dynamic_bom_views.xml diff --git a/mrp_dynamic_bom/__init__.py b/mrp_dynamic_bom/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/mrp_dynamic_bom/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/mrp_dynamic_bom/__manifest__.py b/mrp_dynamic_bom/__manifest__.py new file mode 100644 index 00000000..7a2e18e8 --- /dev/null +++ b/mrp_dynamic_bom/__manifest__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# © 2018 Johny Chen Jy, Trustcode +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ # pylint: disable=C8101,C8103 + 'name': 'MRP Dynamic BoM', + 'description': "Permite lista de material dinamica para o MRP", + 'summary': "MRP Dynamic BoM", + 'version': '11.0.1.0.0', + 'category': "account", + 'author': 'Trustcode', + 'license': 'AGPL-3', + 'website': 'http://www.trustcode.com.br', + 'contributors': [ + 'Johny Chen Jy ', + ], + 'depends': [ + 'mrp', + ], + 'data': [ + 'views/mrp_dynamic_bom_views.xml', + 'security/ir.model.access.csv', + ], +} diff --git a/mrp_dynamic_bom/models/__init__.py b/mrp_dynamic_bom/models/__init__.py new file mode 100644 index 00000000..9a394f76 --- /dev/null +++ b/mrp_dynamic_bom/models/__init__.py @@ -0,0 +1,2 @@ +from . import mrp_bom +from . import mrp_production diff --git a/mrp_dynamic_bom/models/mrp_bom.py b/mrp_dynamic_bom/models/mrp_bom.py new file mode 100644 index 00000000..a5725cfe --- /dev/null +++ b/mrp_dynamic_bom/models/mrp_bom.py @@ -0,0 +1,37 @@ +from odoo import fields, models +from odoo.tools.safe_eval import safe_eval + + +class MrpBom(models.Model): + _inherit = 'mrp.bom' + + bom_dynamic_line_ids = fields.Many2many('bom.dynamic.line') + + def retorna_lista_codigos(self, cod_atributos): + + # Recebe uma lista de códigos de atributos + eval_context = {"ATR": cod_atributos} + + # Dentro do safe_eval, é selecionado os códigos de produtos + codigos = [] + for item in self.bom_dynamic_line_ids: + safe_eval(item.codigo.strip(), + eval_context, mode="exec", nocopy=True) + + if 'result' in eval_context and eval_context['result']: + codigos.append(eval_context['result']) + return codigos + + +class BomDynamicLine(models.Model): + _name = "bom.dynamic.line" + _order = "id" + + bom_id = fields.Many2one( + 'mrp.bom', 'Parent BoM', + index=True, ondelete='cascade', + required=True) + + name = fields.Char(string="Nome") + + codigo = fields.Text(string="Código") diff --git a/mrp_dynamic_bom/models/mrp_production.py b/mrp_dynamic_bom/models/mrp_production.py new file mode 100644 index 00000000..e645a9e2 --- /dev/null +++ b/mrp_dynamic_bom/models/mrp_production.py @@ -0,0 +1,91 @@ +from odoo import models + + +class MrpProduction(models.Model): + _inherit = "mrp.production" + + def _generate_raw_moves(self, exploded_lines): + + moves = super(MrpProduction, self)._generate_raw_moves(exploded_lines) + + # Caso não haja atributos no produto, retorna os moves originais. + if not self.product_id.attribute_value_ids: + return moves + + # Formar lista de todos os atributos desse template de produto + atributos = self.env['product.attribute.value']\ + .search([( + 'product_ids.product_tmpl_id', '=', self.product_tmpl_id.id)]) + + # Formar uma lista dos nomes dos atributos do produto escolhido + product_attr_list = list(item.name for item in + self.product_id.attribute_value_ids) + + atributos_dict = {} + + for item in atributos: + atributos_dict[item.name] = False + + for item in product_attr_list: + atributos_dict[item] = True + + # Chamada de método que retorna a lista de codigos (default_code) + # os quais serão usados para procurar os ingredientes e suas + # respectivas unidades + lista_codigos = self.bom_id.retorna_lista_codigos(atributos_dict) + + # Iteração de cada cod/qty para criação de um move + for codigo, quantidade in lista_codigos: + + bom_line = self.env['mrp.bom.line'].browse(0) + product_id = self.env['product.product'].search( + [('default_code', '=', codigo)], limit=1) + line_data = { + 'original_qty': 1.0, + 'product': product_id, + 'parent_line': False, + 'qty': quantidade + } + # Criação dos moves com os dados acima. + # Usado apenas quando há linhas dinamicas a serem adicionadas + moves += self._generate_dynamic_raw_move(bom_line, line_data) + + return moves + + def _generate_dynamic_raw_move(self, bom_line, line_data): + quantity = line_data['qty'] + + if self.routing_id: + routing = self.routing_id + else: + routing = self.bom_id.routing_id + if routing and routing.location_id: + source_location = routing.location_id + else: + source_location = self.location_src_id + + original_quantity = self.product_qty - self.qty_produced + + data = { + 'sequence': bom_line.sequence, + 'name': self.name, + 'date': self.date_planned_start, + 'date_expected': self.date_planned_start, + 'bom_line_id': bom_line.id, + 'product_id': line_data['product'].id, + 'product_uom_qty': quantity, + 'product_uom': line_data['product'].uom_id.id, + 'location_id': source_location.id, + 'location_dest_id': self.product_id.property_stock_production.id, + 'raw_material_production_id': self.id, + 'company_id': self.company_id.id, + 'operation_id': bom_line.operation_id.id or False, + 'price_unit': bom_line.product_id.standard_price, + 'procure_method': 'make_to_stock', + 'origin': self.name, + 'warehouse_id': source_location.get_warehouse().id, + 'group_id': self.procurement_group_id.id, + 'propagate': self.propagate, + 'unit_factor': quantity / original_quantity, + } + return self.env['stock.move'].create(data) diff --git a/mrp_dynamic_bom/security/ir.model.access.csv b/mrp_dynamic_bom/security/ir.model.access.csv new file mode 100644 index 00000000..72a2a00a --- /dev/null +++ b/mrp_dynamic_bom/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_bom_dynamic_line,bom.dynamic.line,model_bom_dynamic_line,mrp.group_mrp_manager,1,1,1,1 +access_bom_dynamic_line,bom.dynamic.line,model_bom_dynamic_line,mrp.group_mrp_user,1,0,0,0 diff --git a/mrp_dynamic_bom/views/mrp_dynamic_bom_views.xml b/mrp_dynamic_bom/views/mrp_dynamic_bom_views.xml new file mode 100644 index 00000000..be5ac669 --- /dev/null +++ b/mrp_dynamic_bom/views/mrp_dynamic_bom_views.xml @@ -0,0 +1,36 @@ + + + + + mrp.dynamic.bom.form + mrp.bom + + + + + + + + + + + + + + + bom.dynamic.line.form + bom.dynamic.line + +
+ + + + + +
+
+
\ No newline at end of file