[FIX] mrp_multi_level: Consider timezone of the warehouse to generate mrp inventory records.

This commit is contained in:
Lois Rilo
2021-04-22 15:52:32 +02:00
parent 08c3193161
commit f3a69ceeb3
4 changed files with 82 additions and 10 deletions

View File

@@ -5,6 +5,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models
from odoo.addons.base.res.res_partner import _tz_get
class MrpArea(models.Model):
@@ -30,6 +31,24 @@ class MrpArea(models.Model):
string='Working Hours',
related='warehouse_id.calendar_id',
)
tz = fields.Selection(
_tz_get, string='Timezone', required=True,
default=lambda self: self._context.get(
'tz') or self.env.user.tz or 'UTC',
help="This field is used in order to define in which timezone "
"the MRP Area will work.")
@api.model
def _datetime_to_date_tz(self, dt_to_convert=None):
"""Coverts a datetime to date considering the timezone
of MRP Area. If no datetime is provided, it returns today's
date in the timezone."""
if isinstance(dt_to_convert, str):
dt_to_convert = fields.Datetime.from_string(dt_to_convert)
return fields.Date.context_today(
self.with_context(tz=self.tz),
timestamp=dt_to_convert,
)
@api.multi
def _get_locations(self):

View File

@@ -100,6 +100,20 @@ class TestMrpMultiLevel(SavepointCase):
'product_id': cls.prod_test.id,
'mrp_area_id': cls.mrp_area.id,
})
# Another product:
cls.product_tz = cls.product_obj.create(
{
"name": "Product Timezone",
"type": "product",
"list_price": 100.0,
"route_ids": [(6, 0, [route_buy])],
"seller_ids": [(0, 0, {"name": vendor1.id, "price": 20.0})],
}
)
cls.product_mrp_area_obj.create(
{"product_id": cls.product_tz.id, "mrp_area_id": cls.cases_area.id}
)
# Parameters in secondary area with nbr_days set.
cls.product_mrp_area_obj.create({
'product_id': cls.prod_test.id,
@@ -675,3 +689,42 @@ class TestMrpMultiLevel(SavepointCase):
self.assertEqual(mrp_invs[0].to_procure, 130)
# Net needs = 18, available on-hand = 3 -> 15
self.assertEqual(mrp_invs[1].to_procure, 15)
def test_timezone_handling(self):
self.cases_area.tz = "Australia/Sydney"
# Sidney timezone -> Oct-Apr/Apr-Oct: UTC+11/UTC+10
date_move = datetime(2090, 4, 19, 20, 00) # Apr 20 6/7 am in Sidney
sidney_date = "2090-04-20"
self._create_picking_in(
self.product_tz, 10.0, date_move, location=self.cases_loc
)
self.mrp_multi_level_wiz.create(
{"mrp_area_ids": [(6, 0, self.cases_area.ids)]}
).run_mrp_multi_level()
inventory = self.mrp_inventory_obj.search(
[
("mrp_area_id", "=", self.cases_area.id),
("product_id", "=", self.product_tz.id),
]
)
self.assertEqual(len(inventory), 1)
self.assertEqual(inventory.date, sidney_date)
def test_timezone_not_set(self):
self.wh.calendar_id = False
date_move = datetime(2090, 4, 19, 20, 00)
no_tz_date = "2090-04-19"
self._create_picking_in(
self.product_tz, 10.0, date_move, location=self.cases_loc
)
self.mrp_multi_level_wiz.create(
{"mrp_area_ids": [(6, 0, self.cases_area.ids)]}
).run_mrp_multi_level()
inventory = self.mrp_inventory_obj.search(
[
("mrp_area_id", "=", self.cases_area.id),
("product_id", "=", self.product_tz.id),
]
)
self.assertEqual(len(inventory), 1)
self.assertEqual(inventory.date, no_tz_date)

View File

@@ -40,6 +40,7 @@
</group>
<group name="settings">
<field name="calendar_id"/>
<field name="tz"/>
</group>
</group>
</sheet>

View File

@@ -5,8 +5,7 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.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__)
@@ -21,8 +20,6 @@ class MultiLevelMrp(models.TransientModel):
help="If empty, all areas will be computed.",
)
# TODO: dates are not being correctly computed for supply...
@api.model
def _prepare_product_mrp_area_data(self, product_mrp_area):
qty_available = 0.0
@@ -73,6 +70,7 @@ class MultiLevelMrp(models.TransientModel):
@api.model
def _prepare_mrp_move_data_from_stock_move(
self, product_mrp_area, move, direction='in'):
area = product_mrp_area.mrp_area_id
if direction == 'out':
mrp_type = 'd'
product_qty = -move.product_qty
@@ -107,12 +105,13 @@ class MultiLevelMrp(models.TransientModel):
else:
order_number = move.name
origin = "mv"
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))
# The date to display is based on the timezone of the warehouse.
today_tz = area._datetime_to_date_tz()
move_date_tz = area._datetime_to_date_tz(move.date_expected)
if move_date_tz > today_tz:
mrp_date = move_date_tz
else:
mrp_date = today_tz
return {
'product_id': move.product_id.id,
'product_mrp_area_id': product_mrp_area.id,