[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
committed by JasminSForgeFlow
parent e0492ab351
commit 3519eaa966
4 changed files with 71 additions and 7 deletions

View File

@@ -1,10 +1,10 @@
# © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com> # © 2016 Ucamco - Wim Audenaert <wim.audenaert@ucamco.com>
# Copyright 2016-19 ForgeFlow S.L. (https://www.forgeflow.com) # Copyright 2016-21 ForgeFlow S.L. (https://www.forgeflow.com)
# - Jordi Ballester Alomar <jordi.ballester@forgeflow.com> # - Jordi Ballester Alomar <jordi.ballester@forgeflow.com>
# - Lois Rilo Antelo <lois.rilo@forgeflow.com> # - Lois Rilo Antelo <lois.rilo@forgeflow.com>
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo import fields, models from odoo import api, fields, models
class MrpArea(models.Model): class MrpArea(models.Model):
@@ -28,6 +28,15 @@ class MrpArea(models.Model):
related="warehouse_id.calendar_id", related="warehouse_id.calendar_id",
) )
@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."""
return fields.Date.context_today(
self.with_context(tz=self.calendar_id.tz),
timestamp=dt_to_convert,
)
def _get_locations(self): def _get_locations(self):
self.ensure_one() self.ensure_one()
return self.env["stock.location"].search( return self.env["stock.location"].search(

View File

@@ -186,6 +186,19 @@ class TestMrpMultiLevelCommon(SavepointCase):
"mrp_qty_multiple": 5.0, "mrp_qty_multiple": 5.0,
} }
) )
# 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}
)
# Create pickings for Scenario 1: # Create pickings for Scenario 1:
dt_base = cls.calendar.plan_days(3 + 1, datetime.today()) dt_base = cls.calendar.plan_days(3 + 1, datetime.today())

View File

@@ -1,6 +1,8 @@
# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) # Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com)
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from datetime import date, datetime
from odoo import fields from odoo import fields
from .common import TestMrpMultiLevelCommon from .common import TestMrpMultiLevelCommon
@@ -336,3 +338,40 @@ class TestMrpMultiLevel(TestMrpMultiLevelCommon):
[("product_mrp_area_id.product_id", "=", self.av_22.id)] [("product_mrp_area_id.product_id", "=", self.av_22.id)]
) )
self.assertTrue(av_22_supply) self.assertTrue(av_22_supply)
def test_13_timezone_handling(self):
self.calendar.tz = "Australia/Sydney" # 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 = date(2090, 4, 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_14_timezone_not_set(self):
self.wh.calendar_id = False
date_move = datetime(2090, 4, 19, 20, 00)
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, date_move.date())

View File

@@ -22,8 +22,6 @@ class MultiLevelMrp(models.TransientModel):
help="If empty, all areas will be computed.", help="If empty, all areas will be computed.",
) )
# TODO: dates are not being correctly computed for supply...
@api.model @api.model
def _prepare_product_mrp_area_data(self, product_mrp_area): def _prepare_product_mrp_area_data(self, product_mrp_area):
qty_available = 0.0 qty_available = 0.0
@@ -45,6 +43,7 @@ class MultiLevelMrp(models.TransientModel):
def _prepare_mrp_move_data_from_stock_move( def _prepare_mrp_move_data_from_stock_move(
self, product_mrp_area, move, direction="in" self, product_mrp_area, move, direction="in"
): ):
area = product_mrp_area.mrp_area_id
if direction == "out": if direction == "out":
mrp_type = "d" mrp_type = "d"
product_qty = -move.product_qty product_qty = -move.product_qty
@@ -74,9 +73,13 @@ class MultiLevelMrp(models.TransientModel):
if not order_number: if not order_number:
order_number = (move.picking_id or move).name order_number = (move.picking_id or move).name
origin = "mv" origin = "mv"
mrp_date = date.today() # The date to display is based on the timezone of the warehouse.
if move.date.date() > date.today(): today_tz = area._datetime_to_date_tz()
mrp_date = move.date.date() move_date_tz = area._datetime_to_date_tz(move.date)
if move_date_tz > today_tz:
mrp_date = move_date_tz
else:
mrp_date = today_tz
return { return {
"product_id": move.product_id.id, "product_id": move.product_id.id,
"product_mrp_area_id": product_mrp_area.id, "product_mrp_area_id": product_mrp_area.id,