diff --git a/mrp_multi_level/__manifest__.py b/mrp_multi_level/__manifest__.py index 7504f1284..a01fd421f 100644 --- a/mrp_multi_level/__manifest__.py +++ b/mrp_multi_level/__manifest__.py @@ -4,6 +4,7 @@ { 'name': 'MRP Multi Level', 'version': '11.0.1.0.0', + 'license': 'AGPL-3', 'author': 'Ucamco, ' 'Eficent, ' 'Odoo Community Association (OCA)', diff --git a/mrp_multi_level/data/mrp_multi_level_cron.xml b/mrp_multi_level/data/mrp_multi_level_cron.xml index 83c2417ca..40ec42e6d 100755 --- a/mrp_multi_level/data/mrp_multi_level_cron.xml +++ b/mrp_multi_level/data/mrp_multi_level_cron.xml @@ -1,17 +1,16 @@ - - - Multi Level MRP - - - 1 - days - -1 - - - - - + + + Multi Level MRP + + + 1 + days + -1 + + code + model.run_mrp_multi_level() + diff --git a/mrp_multi_level/demo/initial_on_hand_demo.xml b/mrp_multi_level/demo/initial_on_hand_demo.xml index a2cd4991c..2edf4c4b7 100644 --- a/mrp_multi_level/demo/initial_on_hand_demo.xml +++ b/mrp_multi_level/demo/initial_on_hand_demo.xml @@ -29,4 +29,4 @@ - \ No newline at end of file + diff --git a/mrp_multi_level/models/mrp_area.py b/mrp_multi_level/models/mrp_area.py index 2111dcd4a..2b3be32e5 100644 --- a/mrp_multi_level/models/mrp_area.py +++ b/mrp_multi_level/models/mrp_area.py @@ -8,12 +8,14 @@ from odoo import fields, models class MrpArea(models.Model): _name = 'mrp.area' - + name = fields.Char('Name') warehouse_id = fields.Many2one( comodel_name='stock.warehouse', string='Warehouse', - required=True) + required=True, + ) location_id = fields.Many2one( comodel_name='stock.location', string='Location', - required=True) + required=True, + ) active = fields.Boolean(default=True) diff --git a/mrp_multi_level/models/mrp_inventory.py b/mrp_multi_level/models/mrp_inventory.py index 3115b6e29..360a86069 100644 --- a/mrp_multi_level/models/mrp_inventory.py +++ b/mrp_multi_level/models/mrp_inventory.py @@ -15,7 +15,8 @@ class MrpInventory(models.Model): _rec_name = 'mrp_product_id' # TODO: name to pass to procurements? - # TODO: compute procurement_date to pass to the wizard? not needed for PO at least. Check for MO and moves + # TODO: compute procurement_date to pass to the wizard? not needed for + # PO at least. Check for MO and moves # TODO: substract qty already procured. # TODO: show a LT based on the procure method? diff --git a/mrp_multi_level/models/mrp_move.py b/mrp_multi_level/models/mrp_move.py index 126d08741..c04049096 100644 --- a/mrp_multi_level/models/mrp_move.py +++ b/mrp_multi_level/models/mrp_move.py @@ -2,8 +2,7 @@ # © 2016-18 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import models, fields, api, _ -from odoo import exceptions +from odoo import models, fields class MrpMove(models.Model): @@ -12,22 +11,22 @@ class MrpMove(models.Model): # TODO: too many indexes... - mrp_area_id = fields.Many2one('mrp.area', 'MRP Area') - current_date = fields.Date('Current Date') - current_qty = fields.Float('Current Qty') - # TODO: remove purchase request and move to other module? + mrp_area_id = fields.Many2one( + comodel_name='mrp.area', + string='MRP Area', + ) + current_date = fields.Date(string='Current Date') + current_qty = fields.Float(string='Current Qty') # TODO: cancel is not needed I think... mrp_action = fields.Selection( selection=[('mo', 'Manufacturing Order'), ('po', 'Purchase Order'), - ('pr', 'Purchase Request'), - ('so', 'Sale Order'), ('cancel', 'Cancel'), ('none', 'None')], string='Action', ) - mrp_action_date = fields.Date('MRP Action Date') - mrp_date = fields.Date('MRP Date') + mrp_action_date = fields.Date(string='MRP Action Date') + mrp_date = fields.Date(string='MRP Date') mrp_move_down_ids = fields.Many2many( comodel_name='mrp.move', relation='mrp_move_rel', @@ -46,40 +45,46 @@ class MrpMove(models.Model): string='Minimum Stock', related='product_id.mrp_minimum_stock', ) - mrp_order_number = fields.Char('Order Number') - # TODO: move purchase request to another module + mrp_order_number = fields.Char(string='Order Number') + # TODO: replace by a char origin? mrp_origin = fields.Selection( selection=[('mo', 'Manufacturing Order'), ('po', 'Purchase Order'), - ('pr', 'Purchase Request'), - ('so', 'Sale Order'), ('mv', 'Move'), ('fc', 'Forecast'), ('mrp', 'MRP')], string='Origin') - mrp_processed = fields.Boolean('Processed') - mrp_product_id = fields.Many2one('mrp.product', 'Product', index=True) - mrp_qty = fields.Float('MRP Quantity') + mrp_processed = fields.Boolean(string='Processed') + mrp_product_id = fields.Many2one( + comodel_name='mrp.product', + string='Product', index=True, + ) + mrp_qty = fields.Float(string='MRP Quantity') mrp_type = fields.Selection( selection=[('s', 'Supply'), ('d', 'Demand')], string='Type', ) - name = fields.Char('Description') + name = fields.Char(string='Description') parent_product_id = fields.Many2one( comodel_name='product.product', string='Parent Product', index=True, ) - product_id = fields.Many2one('product.product', - 'Product', index=True) - production_id = fields.Many2one('mrp.production', - 'Manufacturing Order', index=True) - purchase_line_id = fields.Many2one('purchase.order.line', - 'Purchase Order Line', index=True) - purchase_order_id = fields.Many2one('purchase.order', - 'Purchase Order', index=True) - running_availability = fields.Float('Running Availability') - sale_line_id = fields.Many2one('sale.order.line', - 'Sale Order Line', index=True) - sale_order_id = fields.Many2one('sale.order', 'Sale Order', index=True) + product_id = fields.Many2one( + comodel_name='product.product', + string='Product', index=True, + ) + production_id = fields.Many2one( + comodel_name='mrp.production', + string='Manufacturing Order', index=True, + ) + purchase_line_id = fields.Many2one( + comodel_name='purchase.order.line', + string='Purchase Order Line', index=True, + ) + purchase_order_id = fields.Many2one( + comodel_name='purchase.order', + string='Purchase Order', index=True, + ) + running_availability = fields.Float(string='Running Availability') state = fields.Selection( selection=[('draft', 'Draft'), ('assigned', 'Assigned'), @@ -92,82 +97,7 @@ class MrpMove(models.Model): ('approved', 'Approved')], string='State', ) - stock_move_id = fields.Many2one('stock.move', 'Stock Move', index=True) - - @api.model - def mrp_production_prepare(self, bom_id, routing_id): - return { - 'product_uos_qty': 0.00, - 'product_uom': self.product_id.product_tmpl_id.uom_id.id, - 'product_qty': self.mrp_qty, - 'product_id': self.product_id.id, - 'location_src_id': 12, - 'date_planned': self.mrp_date, - 'cycle_total': 0.00, - 'company_id': 1, - 'state': 'draft', - 'hour_total': 0.00, - 'bom_id': bom_id, - 'routing_id': routing_id, - 'allow_reorder': False - } - - @api.model - def mrp_process_mo(self): - if self.mrp_action != 'mo': - return True - bom_id = False - routing_id = False - mrp_boms = self.env['mrp.bom'].search( - [('product_id', '=', self.product_id.id), - ('type', '=', 'normal')], limit=1) - for mrp_bom in mrp_boms: - bom_id = mrp_bom.id - routing_id = mrp_bom.routing_id.id - - if self.product_id.track_production and self.mrp_qty > 1: - raise exceptions.Warning(_('Not allowed to create ' - 'manufacturing order with ' - 'quantity higher than 1 ' - 'for serialized product')) - else: - production_data = self.mrp_production_prepare(bom_id, routing_id) - pr = self.env['mrp.production'].create(production_data) - self.production_id = pr.id - self.current_qty = self.mrp_qty - self.current_date = self.mrp_date - self.mrp_processed = True - self.name = pr.name - - # TODO: extension to purchase requisition in other module? - @api.model - def mrp_process_pr(self): - if self.mrp_action != 'pr': - return True - seq = self.env['ir.sequence'].search( - [('code', '=', 'purchase.order.requisition')]) - seqnbr = self.env['ir.sequence'].next_by_id(seq.id) - self.env['purchase.requisition'].create({ - 'origin': 'MRP - [' + self.product_id.default_code + '] ' + - self.product_id.name, - 'exclusive': 'exclusive', - 'message_follower_ids': False, - 'date_end': False, - 'date_start': self.mrp_date, - 'company_id': 1, - 'warehouse_id': 1, - 'state': 'draft', - 'line_ids': [[0, False, - {'product_uom_id': - self.product_id.product_tmpl_id.uom_id.id, - 'product_id': self.product_id.id, - 'product_qty': self.mrp_qty, - 'name': self.product_id.name}]], - 'message_ids': False, - 'description': False, - 'name': seqnbr - }) - self.current_qty = self.mrp_qty - self.current_date = self.mrp_date - self.mrp_processed = True - self.name = seqnbr + stock_move_id = fields.Many2one( + comodel_name='stock.move', + string='Stock Move', index=True, + ) diff --git a/mrp_multi_level/models/mrp_product.py b/mrp_multi_level/models/mrp_product.py index 69ffd7d03..4ec561c06 100644 --- a/mrp_multi_level/models/mrp_product.py +++ b/mrp_multi_level/models/mrp_product.py @@ -25,7 +25,8 @@ class MrpProduct(models.Model): compute='_compute_main_supplier', store=True, ) mrp_inspection_delay = fields.Integer( - string='Inspection Delay', related='product_id.mrp_inspection_delay') + string='Inspection Delay', + related='product_id.mrp_inspection_delay') mrp_lead_time = fields.Float( string='Lead Time', related='product_id.produce_delay', @@ -35,10 +36,12 @@ class MrpProduct(models.Model): ) # TODO: minimun stock and max/min order qty assigned by area? mrp_maximum_order_qty = fields.Float( - string='Maximum Order Qty', related='product_id.mrp_maximum_order_qty', + string='Maximum Order Qty', + related='product_id.mrp_maximum_order_qty', ) mrp_minimum_order_qty = fields.Float( - string='Minimum Order Qty', related='product_id.mrp_minimum_order_qty', + string='Minimum Order Qty', + related='product_id.mrp_minimum_order_qty', ) mrp_minimum_stock = fields.Float( string='Minimum Stock', @@ -50,14 +53,18 @@ class MrpProduct(models.Model): ) mrp_nbr_days = fields.Integer( string='Nbr. Days', related='product_id.mrp_nbr_days') - mrp_qty_available = fields.Float('MRP Qty Available') - mrp_qty_multiple = fields.Float(string='Qty Multiple', - related='product_id.mrp_qty_multiple') - # TODO: this was: mrp_transit_delay = fields.Integer(mrp_move_ids) ??¿?¿¿? + mrp_qty_available = fields.Float( + string='MRP Qty Available') + mrp_qty_multiple = fields.Float( + string='Qty Multiple', + related='product_id.mrp_qty_multiple', + ) mrp_transit_delay = fields.Integer(related='product_id.mrp_transit_delay') - mrp_verified = fields.Boolean(string='MRP Verified', - related='product_id.mrp_verified') - name = fields.Char('Description') + mrp_verified = fields.Boolean( + string='MRP Verified', + related='product_id.mrp_verified', + ) + name = fields.Char(string='Description') # TODO: rename to mrp_action_count? nbr_mrp_actions = fields.Integer( string='Nbr Actions', index=True, @@ -69,11 +76,11 @@ class MrpProduct(models.Model): comodel_name='product.product', string='Product', index=True, ) - product_tmpl_id = fields.Many2one('product.template', 'Product Template', - related='product_id.product_tmpl_id') - # TODO: extension to purchase requisition in other module? - # purchase_requisition = fields.Boolean(string='Purchase Requisition', - # related='product_id.purchase_requisition') + product_tmpl_id = fields.Many2one( + comodel_name='product.template', + string='Product Template', + related='product_id.product_tmpl_id', + ) supply_method = fields.Selection( selection=[('buy', 'Buy'), ('none', 'Undefined'), @@ -90,7 +97,8 @@ class MrpProduct(models.Model): for rec in self: values = { 'warehouse_id': rec.mrp_area_id.warehouse_id, - 'company_id': self.env.user.company_id.id, # TODO: better way to get company + 'company_id': self.env.user.company_id.id, + # TODO: better way to get company } rule = group_obj._get_rule( rec.product_id, rec.mrp_area_id.location_id, values) diff --git a/mrp_multi_level/models/product.py b/mrp_multi_level/models/product.py index 21eb147b6..f0339d26c 100644 --- a/mrp_multi_level/models/product.py +++ b/mrp_multi_level/models/product.py @@ -1,6 +1,5 @@ -# © 2016 Ucamco - Wim Audenaert -# © 2016 Eficent Business and IT Consulting Services S.L. -# - Jordi Ballester Alomar +# Copyright 2016 Ucamco - Wim Audenaert +# Copyright 2016-18 Eficent Business and IT Consulting Services S.L. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from odoo import fields, models @@ -8,40 +7,44 @@ from odoo import fields, models class Product(models.Model): _inherit = 'product.product' - - llc = fields.Integer('Low Level Code', default=0) + + llc = fields.Integer(string='Low Level Code', default=0) manufacturing_order_ids = fields.One2many( comodel_name='mrp.production', inverse_name='product_id', string='Manufacturing Orders', domain=[('state', '=', 'draft')], ) - mrp_applicable = fields.Boolean('MRP Applicable') - mrp_exclude = fields.Boolean('Exclude from MRP') - mrp_inspection_delay = fields.Integer('Inspection Delay', default=0) + # TODO: applicable and exclude... redundant?? + mrp_applicable = fields.Boolean(string='MRP Applicable') + mrp_exclude = fields.Boolean(string='Exclude from MRP') + mrp_inspection_delay = fields.Integer(string='Inspection Delay') mrp_maximum_order_qty = fields.Float( string='Maximum Order Qty', default=0.0, ) mrp_minimum_order_qty = fields.Float( string='Minimum Order Qty', default=0.0, ) - mrp_minimum_stock = fields.Float('Minimum Stock') + mrp_minimum_stock = fields.Float(string='Minimum Stock') mrp_nbr_days = fields.Integer( string='Nbr. Days', default=0, help="Number of days to group demand for this product during the " "MRP run, in order to determine the quantity to order.", ) - mrp_product_ids = fields.One2many('mrp.product', - 'product_id', 'MRP Product data') - mrp_qty_multiple = fields.Float('Qty Multiple', default=1.00) - mrp_transit_delay = fields.Integer('Transit Delay', default=0) - mrp_verified = fields.Boolean('Verified for MRP', - help="Identifies that this product has " - "been verified to be valid for the " - "MRP.") - purchase_order_line_ids = fields.One2many('purchase.order.line', - 'product_id', 'Purchase Orders') - # TODO: extension to purchase requisition in other module? - # purchase_requisition_ids = fields.One2many('purchase.requisition.line', - # 'product_id', - # 'Purchase Requisitions') + mrp_product_ids = fields.One2many( + comodel_name='mrp.product', + inverse_name='product_id', + string='MRP Product data', + ) + mrp_qty_multiple = fields.Float(string='Qty Multiple', default=1.00) + mrp_transit_delay = fields.Integer(string='Transit Delay', default=0) + mrp_verified = fields.Boolean( + string='Verified for MRP', + help="Identifies that this product has been verified " + "to be valid for the MRP.", + ) + purchase_order_line_ids = fields.One2many( + comodel_name='purchase.order.line', + inverse_name='product_id', + string='Purchase Orders', + ) diff --git a/mrp_multi_level/models/stock_location.py b/mrp_multi_level/models/stock_location.py index 3a6957b7f..c9d656256 100644 --- a/mrp_multi_level/models/stock_location.py +++ b/mrp_multi_level/models/stock_location.py @@ -8,7 +8,7 @@ from odoo import fields, models class StockLocation(models.Model): _inherit = 'stock.location' - + mrp_area_id = fields.Many2one( comodel_name='mrp.area', string='MRP Area', help="Requirements for a particular MRP area are combined for the " diff --git a/mrp_multi_level/tests/test_mrp_multi_level.py b/mrp_multi_level/tests/test_mrp_multi_level.py index 7603218ce..a8b156bd9 100644 --- a/mrp_multi_level/tests/test_mrp_multi_level.py +++ b/mrp_multi_level/tests/test_mrp_multi_level.py @@ -10,7 +10,7 @@ from dateutil.rrule import WEEKLY class TestMrpMultiLevel(SavepointCase): - + @classmethod def setUpClass(cls): super(TestMrpMultiLevel, cls).setUpClass() @@ -363,4 +363,4 @@ class TestMrpMultiLevel(SavepointCase): self.assertEqual(mos.date_planned_start, datetime_5) # TODO: test procure wizard: pos, multiple... - # TODO: test multiple destination IDS:... \ No newline at end of file + # TODO: test multiple destination IDS:... diff --git a/mrp_multi_level/views/mrp_area_view.xml b/mrp_multi_level/views/mrp_area_view.xml index 9bc182e0f..8f7f5dc2a 100644 --- a/mrp_multi_level/views/mrp_area_view.xml +++ b/mrp_multi_level/views/mrp_area_view.xml @@ -1,60 +1,46 @@ - - mrp.area.tree - mrp.area - form - - - - - - - - + + mrp.area.tree + mrp.area + tree + + + + + + + + - - mrp.area.form - mrp.area - form - -
- - - - - - - - - - -
-
-
+ + mrp.area.form + mrp.area + form + +
+ + + + + + + + + + +
+
+
- - - MRP Area - mrp.area - ir.actions.act_window - form - tree,form - - - - - - form - - - - - - tree - - - + + MRP Area + mrp.area + ir.actions.act_window + form + tree,form + +
diff --git a/mrp_multi_level/views/mrp_inventory_view.xml b/mrp_multi_level/views/mrp_inventory_view.xml index 852f55c36..774434f61 100644 --- a/mrp_multi_level/views/mrp_inventory_view.xml +++ b/mrp_multi_level/views/mrp_inventory_view.xml @@ -1,54 +1,54 @@ - - mrp.inventory.form - mrp.inventory - form - -
- - - - - - - - - - - - - - - - -
-
-
+ + mrp.inventory.form + mrp.inventory + form + +
+ + + + + + + + + + + + + + + + +
+
+
- - mrp.inventory.tree - mrp.inventory - tree - - - - - - - - - - - -