Skip to content

Commit

Permalink
Merge pull request #365 from Eficent/11.0-mrp_multi_level-planned-orders
Browse files Browse the repository at this point in the history
[11.0][REW/IMP] mrp_multi_level: add planned orders
  • Loading branch information
JordiBForgeFlow committed Jun 6, 2019
2 parents 1bfd586 + bff997c commit 906bf2d
Show file tree
Hide file tree
Showing 20 changed files with 536 additions and 362 deletions.
15 changes: 11 additions & 4 deletions mrp_multi_level/README.rst
Expand Up @@ -35,12 +35,12 @@ and explodes this down to the lowest level.
Key Features
------------

* MRP parameters at product variant level.
* MRP parameters set by product variant MRP area pairs.
* Integration with `Stock Demand Estimates <https://github.com/OCA/stock-logistics-warehouse/tree/11.0/stock_demand_estimate>`_ system.
* Cron job to calculate the MRP demand.
* Manually calculate the MRP demand.
* Confirm the calculated MRP demand and create PO's, or MO's.
* Able to see the products for which action is needed.
* Able to see the products for which action is needed throught Planned Orders.

**Table of contents**

Expand Down Expand Up @@ -81,18 +81,25 @@ To launch replenishment orders (moves, purchases, production orders...):
Changelog
=========

11.0.3.0.0 (2019-05-22)
~~~~~~~~~~~~~~~~~~~~~~~

* [REW/IMP] Rework to include Planned Orders.
(`#365 <https://github.com/OCA/manufacture/pull/365>`_).
* [IMP] Able to procure from a different location than the area's location.

11.0.2.2.0 (2019-05-02)
~~~~~~~~~~~~~~~~~~~~~~~

* [IMP] Able to run MRP only for selected areas.
(`#360 <https://github.com/OCA/manufacture/pull/360>`_):
(`#360 <https://github.com/OCA/manufacture/pull/360>`_).

11.0.2.1.0 (2019-04-02)
~~~~~~~~~~~~~~~~~~~~~~~

* [IMP] Implement *Nbr. Days* functionality to be able to group demand when
generating supply proposals.
(`#345 <https://github.com/OCA/manufacture/pull/345>`_):
(`#345 <https://github.com/OCA/manufacture/pull/345>`_).

11.0.2.0.0 (2018-11-20)
~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion mrp_multi_level/__manifest__.py
Expand Up @@ -3,7 +3,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
'name': 'MRP Multi Level',
'version': '11.0.2.2.0',
'version': '11.0.3.0.0',
'development_status': 'Beta',
'license': 'AGPL-3',
'author': 'Ucamco, '
Expand Down
1 change: 1 addition & 0 deletions mrp_multi_level/models/__init__.py
Expand Up @@ -3,5 +3,6 @@
from . import product_product
from . import product_template
from . import mrp_move
from . import mrp_planned_order
from . import mrp_inventory
from . import product_mrp_area
13 changes: 10 additions & 3 deletions mrp_multi_level/models/mrp_area.py
@@ -1,15 +1,16 @@
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
# © 2016 Eficent Business and IT Consulting Services S.L.
# © 2016-19 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
# - Lois Rilo Antelo <lois.rilo@eficent.com>
# 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 MrpArea(models.Model):
_name = 'mrp.area'

name = fields.Char('Name')
name = fields.Char(required=True)
warehouse_id = fields.Many2one(
comodel_name='stock.warehouse', string='Warehouse',
required=True,
Expand All @@ -24,3 +25,9 @@ class MrpArea(models.Model):
string='Working Hours',
related='warehouse_id.calendar_id',
)

@api.multi
def _get_locations(self):
self.ensure_one()
return self.env['stock.location'].search([
('id', 'child_of', self.location_id.id)])
34 changes: 25 additions & 9 deletions mrp_multi_level/models/mrp_inventory.py
@@ -1,6 +1,7 @@
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
# Copyright 2016-18 Eficent Business and IT Consulting Services S.L.
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
# - Lois Rilo Antelo <lois.rilo@eficent.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import api, fields, models
Expand All @@ -17,7 +18,6 @@ class MrpInventory(models.Model):
# 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: show a LT based on the procure method?

mrp_area_id = fields.Many2one(
comodel_name='mrp.area', string='MRP Area',
Expand All @@ -26,6 +26,7 @@ class MrpInventory(models.Model):
product_mrp_area_id = fields.Many2one(
comodel_name='product.mrp.area', string='Product Parameters',
index=True,
required=True,
)
product_id = fields.Many2one(
comodel_name='product.product',
Expand All @@ -41,18 +42,38 @@ class MrpInventory(models.Model):
supply_qty = fields.Float(string='Supply')
initial_on_hand_qty = fields.Float(string='Starting Inventory')
final_on_hand_qty = fields.Float(string='Forecasted Inventory')
to_procure = fields.Float(string='To procure')
to_procure = fields.Float(
string="To procure",
compute="_compute_to_procure",
store=True,
)
running_availability = fields.Float(
string="Planned Availability",
help="Theoretical inventory level if all planned orders"
"were released.",
)
order_release_date = fields.Date(
string="Order Release Date",
compute="_compute_order_release_date",
store=True,
)
planned_order_ids = fields.One2many(
comodel_name="mrp.planned.order",
inverse_name="mrp_inventory_id",
readonly=True,
)

@api.multi
def _compute_uom_id(self):
for rec in self:
rec.uom_id = rec.product_mrp_area_id.product_id.uom_id

@api.depends("planned_order_ids", "planned_order_ids.qty_released")
def _compute_to_procure(self):
for rec in self:
rec.to_procure = sum(rec.planned_order_ids.mapped('mrp_qty')) - \
sum(rec.planned_order_ids.mapped('qty_released'))

@api.multi
@api.depends('product_mrp_area_id',
'product_mrp_area_id.main_supplierinfo_id',
Expand All @@ -61,12 +82,7 @@ def _compute_uom_id(self):
def _compute_order_release_date(self):
today = date.today()
for rec in self.filtered(lambda r: r.date):
delay = 0
if rec.product_mrp_area_id.supply_method == 'buy':
delay = rec.product_mrp_area_id.main_supplierinfo_id.delay
elif rec.product_mrp_area_id.supply_method == 'manufacture':
delay = rec.product_mrp_area_id.mrp_lead_time
# TODO: 'move' supply method
delay = rec.product_mrp_area_id.mrp_lead_time
if delay and rec.mrp_area_id.calendar_id:
dt_date = fields.Datetime.from_string(rec.date)
order_release_date = rec.mrp_area_id.calendar_id.plan_days(
Expand Down
67 changes: 24 additions & 43 deletions mrp_multi_level/models/mrp_move.py
Expand Up @@ -11,69 +11,51 @@ class MrpMove(models.Model):

# TODO: too many indexes...

product_mrp_area_id = fields.Many2one(
comodel_name="product.mrp.area",
string="Product", index=True,
required=True,
)
mrp_area_id = fields.Many2one(
comodel_name='mrp.area',
related='product_mrp_area_id.mrp_area_id',
string='MRP Area',
comodel_name="mrp.area",
related="product_mrp_area_id.mrp_area_id",
string="MRP Area",
store=True,
index=True,
)
product_id = fields.Many2one(
comodel_name='product.product',
related='product_mrp_area_id.product_id',
store=True,
)

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'),
('cancel', 'Cancel'),
('none', 'None')],
string='Action',
)
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',
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_mrp_area_id.mrp_minimum_stock',
planned_order_up_ids = fields.Many2many(
comodel_name="mrp.planned.order",
relation="mrp_move_planned_order_rel",
column1="move_down_id",
column2="order_id",
string="Planned Orders UP",
)
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'),
('mv', 'Move'),
('fc', 'Forecast'), ('mrp', 'MRP')],
('fc', 'Forecast'),
('mrp', 'MRP')],
string='Origin')
mrp_processed = fields.Boolean(string='Processed')
product_mrp_area_id = fields.Many2one(
comodel_name='product.mrp.area',
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(string='Description')
parent_product_id = fields.Many2one(
comodel_name='product.product',
string='Parent Product', index=True,
)
product_id = fields.Many2one(
comodel_name='product.product',
string='Product', index=True,
comodel_name="product.product",
string="Parent Product", index=True,
)
production_id = fields.Many2one(
comodel_name='mrp.production',
Expand All @@ -87,7 +69,6 @@ class MrpMove(models.Model):
comodel_name='purchase.order',
string='Purchase Order', index=True,
)
running_availability = fields.Float(string='Running Availability')
state = fields.Selection(
selection=[('draft', 'Draft'),
('assigned', 'Assigned'),
Expand Down
63 changes: 63 additions & 0 deletions mrp_multi_level/models/mrp_planned_order.py
@@ -0,0 +1,63 @@
# Copyright 2019 Eficent Business and IT Consulting Services S.L.
# - Lois Rilo Antelo <lois.rilo@eficent.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import models, fields


class MrpPlannedOrder(models.Model):
_name = "mrp.planned.order"
_description = "Planned Order"
_order = "due_date, id"

name = fields.Char(string="Description")
product_mrp_area_id = fields.Many2one(
comodel_name="product.mrp.area",
string="Product",
index=True,
required=True,
)
mrp_area_id = fields.Many2one(
comodel_name="mrp.area",
related="product_mrp_area_id.mrp_area_id",
string="MRP Area",
store=True,
index=True,
readonly=True,
)
product_id = fields.Many2one(
comodel_name="product.product",
related="product_mrp_area_id.product_id",
store=True,
readonly=True,
)
order_release_date = fields.Date(
string="Release Date",
help="Order release date planned by MRP.",
)
due_date = fields.Date(
string="Due Date",
help="Date in which the supply must have been completed.",
)
qty_released = fields.Float()
fixed = fields.Boolean()
mrp_qty = fields.Float(string="Quantity")
mrp_move_down_ids = fields.Many2many(
comodel_name="mrp.move",
relation="mrp_move_planned_order_rel",
column1="order_id",
column2="move_down_id",
string="MRP Move DOWN",
)
mrp_action = fields.Selection(
selection=[("manufacture", "Manufacturing Order"),
("buy", "Purchase Order"),
("move", "Transfer"),
("none", "None")],
string="Action",
)
mrp_inventory_id = fields.Many2one(
string="Associated MRP Inventory",
comodel_name="mrp.inventory",
ondelete="set null",
)

0 comments on commit 906bf2d

Please sign in to comment.