mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
[12.0][MIG] mrp_multi_level:
* You can know integrate with different forecasting mechanisms. As a consequence integration with stock_demand_estimate is moved to a new module (mrp_multi_level_estimate). * As agreed by the authors, the module is re-licensed to LGPL-3.
This commit is contained in:
committed by
JasminSForgeFlow
parent
511f020109
commit
d750aae31b
@@ -1,6 +1,6 @@
|
||||
# Copyright 2018-19 Eficent Business and IT Consulting Services S.L.
|
||||
# (http://www.eficent.com)
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
@@ -95,6 +95,7 @@ class MrpInventoryProcure(models.TransientModel):
|
||||
|
||||
class MrpInventoryProcureItem(models.TransientModel):
|
||||
_name = 'mrp.inventory.procure.item'
|
||||
_description = "MRP Inventory procure item"
|
||||
|
||||
wiz_id = fields.Many2one(
|
||||
comodel_name='mrp.inventory.procure', string='Wizard',
|
||||
@@ -103,7 +104,7 @@ class MrpInventoryProcureItem(models.TransientModel):
|
||||
qty = fields.Float(string='Quantity')
|
||||
uom_id = fields.Many2one(
|
||||
string='Unit of Measure',
|
||||
comodel_name='product.uom',
|
||||
comodel_name='uom.uom',
|
||||
)
|
||||
date_planned = fields.Date(string='Planned Date', required=False)
|
||||
mrp_inventory_id = fields.Many2one(
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<field name="location_id" groups="stock.group_stock_multi_locations" readonly="1"/>
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="qty"/>
|
||||
<field name="uom_id" groups="product.group_uom"/>
|
||||
<field name="uom_id" groups="uom.group_uom"/>
|
||||
<field name="date_planned"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
# Copyright 2016-19 Eficent Business and IT Consulting Services S.L.
|
||||
# - Jordi Ballester Alomar <jordi.ballester@eficent.com>
|
||||
# - Lois Rilo <lois.rilo@eficent.com>
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import api, fields, models, exceptions, _
|
||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from datetime import date, datetime, timedelta
|
||||
from datetime import date, timedelta
|
||||
import logging
|
||||
from odoo.tools.float_utils import float_round
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MultiLevelMrp(models.TransientModel):
|
||||
_name = 'mrp.multi.level'
|
||||
_description = "Multi Level MRP"
|
||||
|
||||
mrp_area_ids = fields.Many2many(
|
||||
comodel_name="mrp.area",
|
||||
@@ -27,7 +26,6 @@ class MultiLevelMrp(models.TransientModel):
|
||||
def _prepare_product_mrp_area_data(self, product_mrp_area):
|
||||
qty_available = 0.0
|
||||
product_obj = self.env['product.product']
|
||||
# TODO: move mrp_qty_available computation, maybe unreserved??
|
||||
location_ids = product_mrp_area.mrp_area_id._get_locations()
|
||||
for location in location_ids:
|
||||
product_l = product_obj.with_context(
|
||||
@@ -41,35 +39,6 @@ class MultiLevelMrp(models.TransientModel):
|
||||
'mrp_llc': product_mrp_area.product_id.llc,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _prepare_mrp_move_data_from_forecast(
|
||||
self, estimate, product_mrp_area, date):
|
||||
mrp_type = 'd'
|
||||
origin = 'fc'
|
||||
daily_qty = float_round(
|
||||
estimate.daily_qty,
|
||||
precision_rounding=product_mrp_area.product_id.uom_id.rounding,
|
||||
rounding_method='HALF-UP')
|
||||
return {
|
||||
'mrp_area_id': product_mrp_area.mrp_area_id.id,
|
||||
'product_id': product_mrp_area.product_id.id,
|
||||
'product_mrp_area_id': product_mrp_area.id,
|
||||
'production_id': None,
|
||||
'purchase_order_id': None,
|
||||
'purchase_line_id': None,
|
||||
'stock_move_id': None,
|
||||
'mrp_qty': -daily_qty * product_mrp_area.group_estimate_days,
|
||||
'current_qty': -daily_qty,
|
||||
'mrp_date': date,
|
||||
'current_date': date,
|
||||
'mrp_type': mrp_type,
|
||||
'mrp_origin': origin,
|
||||
'mrp_order_number': None,
|
||||
'parent_product_id': None,
|
||||
'name': 'Forecast',
|
||||
'state': 'confirmed',
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _prepare_mrp_move_data_from_stock_move(
|
||||
self, product_mrp_area, move, direction='in'):
|
||||
@@ -91,7 +60,6 @@ class MultiLevelMrp(models.TransientModel):
|
||||
origin = 'mo'
|
||||
mo = move.production_id.id
|
||||
else:
|
||||
# TODO: move.move_dest_id -> move.move_dest_ids. DONE, review
|
||||
if move.move_dest_ids:
|
||||
# move_dest_id = move.move_dest_ids[:1]
|
||||
for move_dest_id in move.move_dest_ids:
|
||||
@@ -107,11 +75,8 @@ class MultiLevelMrp(models.TransientModel):
|
||||
if order_number is None:
|
||||
order_number = move.name
|
||||
mrp_date = date.today()
|
||||
if datetime.date(datetime.strptime(
|
||||
move.date_expected,
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)) > date.today():
|
||||
mrp_date = datetime.date(datetime.strptime(
|
||||
move.date_expected, DEFAULT_SERVER_DATETIME_FORMAT))
|
||||
if move.date_expected.date() > date.today():
|
||||
mrp_date = move.date_expected.date()
|
||||
return {
|
||||
'product_id': move.product_id.id,
|
||||
'product_mrp_area_id': product_mrp_area.id,
|
||||
@@ -192,8 +157,9 @@ class MultiLevelMrp(models.TransientModel):
|
||||
if calendar and product_mrp_area.mrp_lead_time:
|
||||
date_str = fields.Date.to_string(mrp_date)
|
||||
dt = fields.Datetime.from_string(date_str)
|
||||
# dt is at the beginning of the day (00:00)
|
||||
res = calendar.plan_days(
|
||||
-1 * product_mrp_area.mrp_lead_time - 1, dt)
|
||||
-1 * product_mrp_area.mrp_lead_time, dt)
|
||||
mrp_action_date = res.date()
|
||||
else:
|
||||
mrp_action_date = mrp_date - timedelta(
|
||||
@@ -359,35 +325,9 @@ class MultiLevelMrp(models.TransientModel):
|
||||
logger.info(log_msg)
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def _estimates_domain(self, product_mrp_area):
|
||||
locations = product_mrp_area.mrp_area_id._get_locations()
|
||||
return [
|
||||
('product_id', '=', product_mrp_area.product_id.id),
|
||||
('location_id', 'in', locations.ids),
|
||||
('date_range_id.date_end', '>=', fields.Date.today()),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def _init_mrp_move_from_forecast(self, product_mrp_area):
|
||||
if not product_mrp_area.group_estimate_days:
|
||||
return False
|
||||
today = fields.Date.today()
|
||||
domain = self._estimates_domain(product_mrp_area)
|
||||
estimates = self.env['stock.demand.estimate'].search(domain)
|
||||
for rec in estimates:
|
||||
start = rec.date_range_id.date_start
|
||||
if start < today:
|
||||
start = today
|
||||
mrp_date = fields.Date.from_string(start)
|
||||
date_end = fields.Date.from_string(rec.date_range_id.date_end)
|
||||
delta = timedelta(days=product_mrp_area.group_estimate_days)
|
||||
while mrp_date <= date_end:
|
||||
mrp_move_data = \
|
||||
self._prepare_mrp_move_data_from_forecast(
|
||||
rec, product_mrp_area, mrp_date)
|
||||
self.env['mrp.move'].create(mrp_move_data)
|
||||
mrp_date += delta
|
||||
"""This method is meant to be inherited to add a forecast mechanism."""
|
||||
return True
|
||||
|
||||
# TODO: move this methods to product_mrp_area?? to be able to
|
||||
@@ -416,7 +356,6 @@ class MultiLevelMrp(models.TransientModel):
|
||||
|
||||
@api.model
|
||||
def _init_mrp_move_from_stock_move(self, product_mrp_area):
|
||||
# TODO: Should we exclude the quantity done from the moves?
|
||||
move_obj = self.env['stock.move']
|
||||
mrp_move_obj = self.env['mrp.move']
|
||||
in_domain = self._in_stock_moves_domain(product_mrp_area)
|
||||
|
||||
Reference in New Issue
Block a user