[11.0][REW/IMP] multi_level_mrp: major overhault

This commit is contained in:
Lois Rilo
2018-06-13 20:16:40 +02:00
committed by Jordi Ballester Alomar
parent 523ca538fe
commit a3a6992ba7
8 changed files with 640 additions and 393 deletions

View File

@@ -175,7 +175,7 @@ class MrpForecastProduct(models.Model):
'forecast_product_id',
'Forecast')
name = fields.Char(compute='_function_name', string='Description')
product_id = fields.Many2one('product.product', 'Product', select=True)
product_id = fields.Many2one('product.product', 'Product', index=True)
mrp_area_id = fields.Many2one('mrp.area', 'MRP Area')
qty_forecast_m0 = fields.Float(compute='_function_forecast_m0',
string='This Month Forecast')

View File

@@ -17,6 +17,7 @@ class MrpInventory(models.Model):
# 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?
# TODO: add to_procure_date
mrp_area_id = fields.Many2one(
comodel_name='mrp.area', string='MRP Area',
@@ -24,7 +25,7 @@ class MrpInventory(models.Model):
)
mrp_product_id = fields.Many2one(
comodel_name='mrp.product', string='Product',
select=True,
index=True,
)
uom_id = fields.Many2one(
comodel_name='product.uom', string='Product UoM',

View File

@@ -1,6 +1,5 @@
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
# © 2016 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
# © 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, _
@@ -9,43 +8,66 @@ from odoo import exceptions
class MrpMove(models.Model):
_name = 'mrp.move'
_order = 'mrp_product_id, mrp_date, mrp_type desc, id'
# 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')
mrp_action = fields.Selection((('mo', 'Manufacturing Order'),
('po', 'Purchase Order'),
('pr', 'Purchase Request'),
('so', 'Sale Order'),
('push', 'Push'),
('pull', 'Pull'),
('cancel', 'Cancel'),
('none', 'None')),
'Action')
# TODO: remove purchase request and move to other module?
# 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_move_down_ids = fields.Many2many('mrp.move', 'mrp_move_rel',
'move_up_id', 'move_down_id',
'MRP Move DOWN')
mrp_move_up_ids = fields.Many2many('mrp.move', 'mrp_move_rel',
'move_down_id', 'move_up_id',
'MRP Move UP')
mrp_minimum_stock = fields.Float(string='Minimum Stock',
related='product_id.mrp_minimum_stock')
mrp_move_down_ids = fields.Many2many(
comodel_name='mrp.move',
relation='mrp_move_rel',
column1='move_up_id',
column2='move_down_id',
string='MRP Move DOWN',
)
mrp_move_up_ids = fields.Many2many(
comodel_name='mrp.move',
relation='mrp_move_rel',
column1='move_down_id',
column2='move_up_id',
string='MRP Move UP',
)
mrp_minimum_stock = fields.Float(
string='Minimum Stock',
related='product_id.mrp_minimum_stock',
)
mrp_order_number = fields.Char('Order Number')
mrp_origin = fields.Selection((('mo', 'Manufacturing Order'),
('po', 'Purchase Order'),
('pr', 'Purchase Request'),
('so', 'Sale Order'), ('mv','Move'),
('fc', 'Forecast'), ('mrp', 'MRP')),
'Origin')
# TODO: move purchase request to another module
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_type = fields.Selection((('s', 'Supply'), ('d', 'Demand')), 'Type')
mrp_type = fields.Selection(
selection=[('s', 'Supply'), ('d', 'Demand')],
string='Type',
)
name = fields.Char('Description')
parent_product_id = fields.Many2one('product.product',
'Parent Product', index=True)
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',
@@ -65,15 +87,12 @@ class MrpMove(models.Model):
('waiting', 'Waiting'),
('partially_available', 'Partially Available'),
('ready', 'Ready'),
('in_production', 'In Production'),
('picking_except', 'Picking Exception'),
('sent', 'Sent'), ('approved', 'Approved'),
('except_invoice', 'Invoice Exception')],
('sent', 'Sent'),
('to approve', 'To Approve'),
('approved', 'Approved')],
string='State',
)
stock_move_id = fields.Many2one('stock.move', 'Stock Move', index=True)
_order = 'mrp_product_id, mrp_date, mrp_type desc, id'
@api.model
def mrp_production_prepare(self, bom_id, routing_id):

View File

@@ -1,9 +1,8 @@
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
# © 2016 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
# © 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
from odoo import api, fields, models
class MrpProduct(models.Model):
@@ -12,38 +11,105 @@ class MrpProduct(models.Model):
mrp_area_id = fields.Many2one('mrp.area', 'MRP Area')
current_qty_available = fields.Float(string='Current Qty Available',
related='product_id.qty_available')
main_supplier_id = fields.Many2one('res.partner', 'Main Supplier',
select=True)
main_supplier_id = fields.Many2one(
comodel_name='res.partner', string='Main Supplier',
compute='_compute_main_supplier', store=True,
index=True,
)
mrp_inspection_delay = fields.Integer(
string='Inspection Delay', related='product_id.mrp_inspection_delay')
mrp_lead_time = fields.Float(string='Lead Time',
related='product_id.produce_delay')
mrp_llc = fields.Integer('Low Level Code', select=True)
mrp_lead_time = fields.Float(
string='Lead Time',
related='product_id.produce_delay',
)
mrp_llc = fields.Integer(
string='Low Level Code', index=True, readonly=True,
)
# 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')
mrp_minimum_stock = fields.Float(string='Minimum Stock',
related='product_id.mrp_minimum_stock')
mrp_move_ids = fields.One2many('mrp.move', 'mrp_product_id', 'MRP Moves')
string='Minimum Order Qty', related='product_id.mrp_minimum_order_qty',
)
mrp_minimum_stock = fields.Float(
string='Minimum Stock',
related='product_id.mrp_minimum_stock',
)
mrp_move_ids = fields.One2many(
comodel_name='mrp.move', inverse_name='mrp_product_id',
string='MRP Moves',
)
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_transit_delay = fields.Integer(related = 'product_id.mrp_transit_delay')
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')
nbr_mrp_actions = fields.Integer('Nbr Actions', select=True)
nbr_mrp_actions_4w = fields.Integer('Nbr Actions 4 Weeks', select=True)
product_id = fields.Many2one('product.product', 'Product', select=True)
# TODO: rename to mrp_action_count?
nbr_mrp_actions = fields.Integer(
string='Nbr Actions', index=True,
)
nbr_mrp_actions_4w = fields.Integer(
string='Nbr Actions 4 Weeks', index=True,
)
product_id = fields.Many2one(
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')
supply_method = fields.Selection((('buy', 'Buy'),
('produce', 'Produce')),
'Supply Method')
supply_method = fields.Selection(
selection=[('buy', 'Buy'),
('none', 'Undefined'),
('manufacture', 'Produce'),
('move', 'Transfer')],
string='Supply Method',
compute='_compute_supply_method', store=True,
)
@api.multi
@api.depends('mrp_area_id')
def _compute_supply_method(self):
group_obj = self.env['procurement.group']
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
}
rule = group_obj._get_rule(
rec.product_id, rec.mrp_area_id.location_id, values)
rec.supply_method = rule.action if rule else 'none'
@api.multi
@api.depends('supply_method')
def _compute_main_supplier(self):
"""Simplified and similar to procurement.rule logic."""
for rec in self.filtered(lambda r: r.supply_method == 'buy'):
suppliers = rec.product_id.seller_ids.filtered(
lambda r: (not r.product_id or r.product_id == rec.product_id))
if not suppliers:
continue
rec.main_supplier_id = suppliers[0].name
@api.multi
def _adjust_qty_to_order(self, qty_to_order):
# TODO: consider mrp_qty_multiple?
self.ensure_one()
if not self.mrp_maximum_order_qty and not self.mrp_minimum_order_qty:
return qty_to_order
if qty_to_order < self.mrp_minimum_order_qty:
return self.mrp_minimum_order_qty
if self.mrp_maximum_order_qty and qty_to_order > \
self.mrp_maximum_order_qty:
qty = self.mrp_maximum_order_qty
else:
qty = qty_to_order
return qty

View File

@@ -19,14 +19,18 @@ class Product(models.Model):
mrp_applicable = fields.Boolean('MRP Applicable')
mrp_exclude = fields.Boolean('Exclude from MRP')
mrp_inspection_delay = fields.Integer('Inspection Delay', default=0)
mrp_maximum_order_qty = fields.Float('Maximum Order Qty', default=0.00)
mrp_minimum_order_qty = fields.Float('Minimum Order Qty', default=0.00)
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_nbr_days = fields.Integer('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_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)