diff --git a/mrp_production_request/README.rst b/mrp_production_request/README.rst index 7233d338a..e63bc8e24 100644 --- a/mrp_production_request/README.rst +++ b/mrp_production_request/README.rst @@ -53,7 +53,7 @@ to set it to *Done* state. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/129/9.0 + :target: https://runbot.odoo-community.org/runbot/129/10.0 Known issues / Roadmap ====================== diff --git a/mrp_production_request/__init__.py b/mrp_production_request/__init__.py index 64f004b89..84830dc8e 100644 --- a/mrp_production_request/__init__.py +++ b/mrp_production_request/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models diff --git a/mrp_production_request/__openerp__.py b/mrp_production_request/__manifest__.py similarity index 97% rename from mrp_production_request/__openerp__.py rename to mrp_production_request/__manifest__.py index fb376ecc1..59bf90042 100644 --- a/mrp_production_request/__openerp__.py +++ b/mrp_production_request/__manifest__.py @@ -6,7 +6,7 @@ "summary": "Allows you to use Manufacturing Request as a previous " "step to Manufacturing Orders for better manufacture " "planification.", - "version": "9.0.1.0.0", + "version": "10.0.1.0.0", "category": "Manufacturing", "website": "https://github.com/OCA/manufacture", "author": "Eficent," diff --git a/mrp_production_request/models/__init__.py b/mrp_production_request/models/__init__.py index 79a8a751e..ffa417603 100644 --- a/mrp_production_request/models/__init__.py +++ b/mrp_production_request/models/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import mrp_production_request diff --git a/mrp_production_request/models/mrp_production.py b/mrp_production_request/models/mrp_production.py index 5591a0143..f844a19ba 100644 --- a/mrp_production_request/models/mrp_production.py +++ b/mrp_production_request/models/mrp_production.py @@ -2,7 +2,7 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import fields, models +from odoo import fields, models class MrpProduction(models.Model): @@ -11,3 +11,9 @@ class MrpProduction(models.Model): mrp_production_request_id = fields.Many2one( comodel_name="mrp.production.request", string="Manufacturing Request", copy=False, readonly=True) + + def _generate_finished_moves(self): + move = super(MrpProduction, self)._generate_finished_moves() + mr_proc = self.mrp_production_request_id.procurement_id + if mr_proc and mr_proc.move_dest_id: + move.write({"move_dest_id": mr_proc.move_dest_id.id}) diff --git a/mrp_production_request/models/mrp_production_request.py b/mrp_production_request/models/mrp_production_request.py index 617e2ba2b..e4e2d7b6f 100644 --- a/mrp_production_request/models/mrp_production_request.py +++ b/mrp_production_request/models/mrp_production_request.py @@ -1,16 +1,17 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-18 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import api, fields, models, _ -import openerp.addons.decimal_precision as dp -from openerp.exceptions import UserError +from odoo import api, fields, models, _ +import odoo.addons.decimal_precision as dp +from odoo.exceptions import UserError class MrpProductionRequest(models.Model): _name = "mrp.production.request" _description = "Manufacturing Request" _inherit = "mail.thread" + _order = "id DESC" @api.model def _company_get(self): @@ -52,9 +53,10 @@ class MrpProductionRequest(models.Model): @api.onchange('product_id') def _onchange_product_id(self): - self.product_uom = self.product_id.uom_id + self.product_uom_id = self.product_id.uom_id self.bom_id = self.env['mrp.bom']._bom_find( - product_id=self.product_id.id, properties=[]) + product=self.product_id, company_id=self.company_id.id, + picking_type=self.picking_type_id) @api.model def _get_mo_valid_states(self): @@ -122,26 +124,26 @@ class MrpProductionRequest(models.Model): related='product_id.product_tmpl_id') product_qty = fields.Float( string="Required Quantity", required=True, track_visibility='onchange', - digits_compute=dp.get_precision('Product Unit of Measure'), + digits=dp.get_precision('Product Unit of Measure'), readonly=True, states={'draft': [('readonly', False)]}) - product_uom = fields.Many2one( + product_uom_id = fields.Many2one( comodel_name='product.uom', string='Unit of Measure', readonly=True, states={'draft': [('readonly', False)]}, domain="[('category_id', '=', category_uom_id)]") - category_uom_id = fields.Many2one(related="product_uom.category_id") + category_uom_id = fields.Many2one(related="product_uom_id.category_id") manufactured_qty = fields.Float( string="Quantity in Manufacturing Orders", compute=_compute_manufactured_qty, store=True, readonly=True, - digits_compute=dp.get_precision('Product Unit of Measure'), + digits=dp.get_precision('Product Unit of Measure'), help="Sum of the quantities in Manufacturing Orders (in any state).") done_qty = fields.Float( string="Quantity Done", store=True, readonly=True, compute=_compute_manufactured_qty, - digits_compute=dp.get_precision('Product Unit of Measure'), + digits=dp.get_precision('Product Unit of Measure'), help="Sum of the quantities in all done Manufacturing Orders.") pending_qty = fields.Float( string="Pending Quantity", compute=_compute_manufactured_qty, - store=True, digits_compute=dp.get_precision('Product Unit of Measure'), + store=True, digits=dp.get_precision('Product Unit of Measure'), readonly=True, help="Quantity pending to add to Manufacturing Orders " "to fulfill the Manufacturing Request requirement.") @@ -159,12 +161,17 @@ class MrpProductionRequest(models.Model): location_src_id = fields.Many2one( comodel_name='stock.location', string='Raw Materials Location', default=lambda self: self.env['stock.location'].browse( - self.env['mrp.production']._src_id_default()), + self.env['mrp.production']._get_default_location_src_id()), required=True, readonly=True, states={'draft': [('readonly', False)]}) location_dest_id = fields.Many2one( comodel_name='stock.location', string='Finished Products Location', default=lambda self: self.env['stock.location'].browse( - self.env['mrp.production']._dest_id_default()), + self.env['mrp.production']._get_default_location_dest_id()), + required=True, readonly=True, states={'draft': [('readonly', False)]}) + picking_type_id = fields.Many2one( + comodel_name='stock.picking.type', string='Picking Type', + default=lambda self: self.env['stock.picking.type'].browse( + self.env['mrp.production']._get_default_picking_type()), required=True, readonly=True, states={'draft': [('readonly', False)]}) @api.multi diff --git a/mrp_production_request/models/procurement.py b/mrp_production_request/models/procurement.py index cff54c446..b1a4114d6 100644 --- a/mrp_production_request/models/procurement.py +++ b/mrp_production_request/models/procurement.py @@ -2,7 +2,7 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import api, fields, models, _ +from odoo import api, fields, models, _ class ProcurementOrder(models.Model): @@ -12,31 +12,32 @@ class ProcurementOrder(models.Model): comodel_name="mrp.production.request", string="Manufacturing Request", copy=False) - @api.model - def _prepare_mrp_production_request(self, procurement): - data = self._prepare_mo_vals(procurement) - data['procurement_id'] = procurement.id + @api.multi + def _prepare_mrp_production_request(self): + self.ensure_one() + data = self._prepare_mo_vals(self._get_matching_bom()) + data['procurement_id'] = self.id data['state'] = 'to_approve' return data - @api.model - def _run(self, procurement): - if (procurement.rule_id and - procurement.rule_id.action == 'manufacture' and - procurement.product_id.mrp_production_request): - if not procurement.check_bom_exists(): - procurement.message_post( + @api.multi + def _run(self): + self.ensure_one() + if (self.rule_id and + self.rule_id.action == 'manufacture' and + self.product_id.mrp_production_request): + if not self._get_matching_bom(): + self.message_post( body=_("No BoM exists for this product!")) return False if not self.mrp_production_request_id: - request_data = self._prepare_mrp_production_request( - procurement) + request_data = self._prepare_mrp_production_request() req = self.env['mrp.production.request'].create(request_data) - procurement.message_post(body=_( + self.message_post(body=_( "Manufacturing Request created")) - procurement.mrp_production_request_id = req.id + self.mrp_production_request_id = req.id return True - return super(ProcurementOrder, self)._run(procurement) + return super(ProcurementOrder, self)._run() @api.multi def propagate_cancels(self): diff --git a/mrp_production_request/models/product.py b/mrp_production_request/models/product.py index 9dc0bb716..d051954c9 100644 --- a/mrp_production_request/models/product.py +++ b/mrp_production_request/models/product.py @@ -2,7 +2,7 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import fields, models +from odoo import fields, models class ProductTemplate(models.Model): diff --git a/mrp_production_request/models/stock_move.py b/mrp_production_request/models/stock_move.py index 093a928dd..c963ddc4d 100644 --- a/mrp_production_request/models/stock_move.py +++ b/mrp_production_request/models/stock_move.py @@ -2,7 +2,7 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import api, models +from odoo import api, models class StockMove(models.Model): diff --git a/mrp_production_request/tests/__init__.py b/mrp_production_request/tests/__init__.py index e8ae8f4dd..f544ff207 100644 --- a/mrp_production_request/tests/__init__.py +++ b/mrp_production_request/tests/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import test_mrp_production_request diff --git a/mrp_production_request/tests/test_mrp_production_request.py b/mrp_production_request/tests/test_mrp_production_request.py index 56c1be99c..5b480f6cc 100644 --- a/mrp_production_request/tests/test_mrp_production_request.py +++ b/mrp_production_request/tests/test_mrp_production_request.py @@ -2,9 +2,9 @@ # Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp.tests.common import TransactionCase -from openerp import fields -from openerp.exceptions import UserError +from odoo.tests.common import TransactionCase +from odoo import fields +from odoo.exceptions import UserError class TestMrpProductionRequest(TransactionCase): @@ -61,7 +61,6 @@ class TestMrpProductionRequest(TransactionCase): ('mrp_production_request_id', '=', request.id)]) self.assertTrue(mo, "No MO created.") self.assertEqual(request.pending_qty, 0.0) - mo.action_confirm() request.button_done() def test_cancellation_from_request(self): diff --git a/mrp_production_request/views/mrp_production_request_view.xml b/mrp_production_request/views/mrp_production_request_view.xml index fa0dec6b0..a1da0c212 100644 --- a/mrp_production_request/views/mrp_production_request_view.xml +++ b/mrp_production_request/views/mrp_production_request_view.xml @@ -53,7 +53,7 @@ - + @@ -80,6 +80,7 @@ + diff --git a/mrp_production_request/views/mrp_production_view.xml b/mrp_production_request/views/mrp_production_view.xml index 3a083d602..f7e89b9ca 100644 --- a/mrp_production_request/views/mrp_production_view.xml +++ b/mrp_production_request/views/mrp_production_view.xml @@ -9,7 +9,7 @@ - + diff --git a/mrp_production_request/wizards/__init__.py b/mrp_production_request/wizards/__init__.py index 364687612..247bc71ec 100644 --- a/mrp_production_request/wizards/__init__.py +++ b/mrp_production_request/wizards/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import mrp_production_request_create_mo diff --git a/mrp_production_request/wizards/mrp_production_request_create_mo.py b/mrp_production_request/wizards/mrp_production_request_create_mo.py index ef9529227..01ed9080c 100644 --- a/mrp_production_request/wizards/mrp_production_request_create_mo.py +++ b/mrp_production_request/wizards/mrp_production_request_create_mo.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# Copyright 2017-18 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from openerp import api, fields, models -import openerp.addons.decimal_precision as dp +from odoo import api, fields, models +import odoo.addons.decimal_precision as dp class MrpProductionRequestCreateMo(models.TransientModel): @@ -14,8 +14,7 @@ class MrpProductionRequestCreateMo(models.TransientModel): def compute_product_line_ids(self): self.product_line_ids.unlink() res = self._prepare_lines() - product_lines = res[0] - # TODO: expand with workcenter_lines: they are in res[1]. + product_lines = res[1] for line in product_lines: self.env['mrp.production.request.create.mo.line'].create( self._prepare_product_line(line)) @@ -23,27 +22,25 @@ class MrpProductionRequestCreateMo(models.TransientModel): return {"type": "ir.actions.do_nothing"} def _prepare_lines(self): - """Get the components (product_lines) and Work Centers Utilisation - (workcenter_lines) needed for manufacturing the given a BoM. - :return: product_lines, workcenter_lines + """Get the components (product_lines) needed for manufacturing the + given a BoM. + :return: boms_done, lines_done """ - bom_obj = self.env['mrp.bom'] - uom_obj = self.env['product.uom'] bom_point = self.bom_id - factor = uom_obj._compute_qty( - self.mrp_production_request_id.product_uom.id, self.pending_qty, - bom_point.product_uom.id) - return bom_obj._bom_explode( - bom_point, self.mrp_production_request_id.product_id, - factor / bom_point.product_qty, - routing_id=self.mrp_production_request_id.routing_id.id) + factor = self.mrp_production_request_id.product_uom_id.\ + _compute_quantity(self.pending_qty, bom_point.product_uom_id) + return bom_point.explode( + self.mrp_production_request_id.product_id, + factor / bom_point.product_qty) - @api.one + @api.multi def _get_mo_qty(self): """Propose a qty to create a MO available to produce.""" - bottle_neck = min(self.product_line_ids.mapped('bottle_neck_factor')) - bottle_neck = max(min(1, bottle_neck), 0) - self.mo_qty = self.pending_qty * bottle_neck + for rec in self: + bottle_neck = min(rec.product_line_ids.mapped( + 'bottle_neck_factor')) + bottle_neck = max(min(1, bottle_neck), 0) + rec.mo_qty = rec.pending_qty * bottle_neck mrp_production_request_id = fields.Many2one( comodel_name="mrp.production.request", readonly=True) @@ -51,12 +48,12 @@ class MrpProductionRequestCreateMo(models.TransientModel): related='mrp_production_request_id.bom_id', readonly=True) mo_qty = fields.Float( string="Quantity", - digits_compute=dp.get_precision("Product Unit of Measure")) + digits=dp.get_precision("Product Unit of Measure")) pending_qty = fields.Float( related="mrp_production_request_id.pending_qty", - digits_compute=dp.get_precision("Product Unit of Measure")) - product_uom = fields.Many2one( - related="mrp_production_request_id.product_uom") + digits=dp.get_precision("Product Unit of Measure")) + product_uom_id = fields.Many2one( + related="mrp_production_request_id.product_uom_id") product_line_ids = fields.One2many( comodel_name="mrp.production.request.create.mo.line", string="Products needed", @@ -64,9 +61,9 @@ class MrpProductionRequestCreateMo(models.TransientModel): def _prepare_product_line(self, pl): return { - 'product_id': pl['product_id'], - 'product_qty': pl['product_qty'], - 'product_uom': pl['product_uom'], + 'product_id': pl[0].product_id.id, + 'product_qty': pl[1]['qty'], + 'product_uom_id': pl[0].product_uom_id.id, 'mrp_production_request_create_mo_id': self.id, 'location_id': self.mrp_production_request_id.location_src_id.id, } @@ -79,13 +76,13 @@ class MrpProductionRequestCreateMo(models.TransientModel): 'product_id': request_id.product_id.id, 'bom_id': request_id.bom_id.id, 'product_qty': self.mo_qty, - 'product_uom': self.product_uom.id, + 'product_uom_id': self.product_uom_id.id, 'mrp_production_request_id': self.mrp_production_request_id.id, 'origin': request_id.origin, 'location_src_id': request_id.location_src_id.id, 'location_dest_id': request_id.location_dest_id.id, + 'picking_type_id': request_id.picking_type_id.id, 'routing_id': request_id.routing_id.id, - 'move_prod_id': request_id.procurement_id.move_dest_id.id or False, 'date_planned': request_id.date_planned, 'company_id': request_id.company_id.id, } @@ -108,33 +105,35 @@ class MrpProductionRequestCreateMo(models.TransientModel): class MrpProductionRequestCreateMoLine(models.TransientModel): _name = "mrp.production.request.create.mo.line" - @api.one + @api.multi def _compute_available_qty(self): - product_available = self.product_id.with_context( - location=self.location_id.id)._product_available()[ - self.product_id.id]['qty_available_not_res'] - res = self.product_uom._compute_qty( - self.product_id.product_tmpl_id.uom_id.id, product_available, - self.product_uom.id) - self.available_qty = res + for rec in self: + product_available = rec.product_id.with_context( + location=rec.location_id.id).\ + _compute_product_available_not_res_dict()[ + rec.product_id.id]['qty_available_not_res'] + res = rec.product_id.product_tmpl_id.uom_id._compute_quantity( + product_available, rec.product_uom_id) + rec.available_qty = res - @api.one + @api.multi def _compute_bottle_neck_factor(self): - if self.product_qty: - self.bottle_neck_factor = self.available_qty / self.product_qty + for rec in self: + if rec.product_qty: + rec.bottle_neck_factor = rec.available_qty / rec.product_qty product_id = fields.Many2one( comodel_name='product.product', string='Product', required=True) product_qty = fields.Float( string='Quantity Required', required=True, - digits_compute=dp.get_precision('Product Unit of Measure')) - product_uom = fields.Many2one( + digits=dp.get_precision('Product Unit of Measure')) + product_uom_id = fields.Many2one( comodel_name='product.uom', string='UoM', required=True) mrp_production_request_create_mo_id = fields.Many2one( comodel_name='mrp.production.request.create.mo') available_qty = fields.Float( string='Quantity Available', compute=_compute_available_qty, - digits_compute=dp.get_precision('Product Unit of Measure')) + digits=dp.get_precision('Product Unit of Measure')) bottle_neck_factor = fields.Float(compute=_compute_bottle_neck_factor) location_id = fields.Many2one(comodel_name='stock.location', required=True) diff --git a/mrp_production_request/wizards/mrp_production_request_create_mo_view.xml b/mrp_production_request/wizards/mrp_production_request_create_mo_view.xml index 9808a4bdb..fcb95d81e 100644 --- a/mrp_production_request/wizards/mrp_production_request_create_mo_view.xml +++ b/mrp_production_request/wizards/mrp_production_request_create_mo_view.xml @@ -21,7 +21,7 @@ - + @@ -31,7 +31,7 @@ -