From 7754caf8eb7517b05ec36862d6cefdbe4cbebe1c Mon Sep 17 00:00:00 2001 From: SilvioC2C Date: Thu, 18 Apr 2024 12:53:06 +0200 Subject: [PATCH] fixup! address PR reviews, add migration script, tests overhaul --- .../README.rst | 8 +- .../__manifest__.py | 5 +- .../migrations/14.0.1.1.0/post-mig.py | 25 + .../migrations/14.0.1.1.0/pre-mig.py | 25 + .../models/res_company.py | 6 - .../models/res_config_settings.py | 4 - .../models/stock_warehouse.py | 9 - .../models/stock_warehouse_orderpoint.py | 63 +-- .../static/description/index.html | 8 +- .../tests/common.py | 53 +- .../tests/test_calendar_orderpoint.py | 455 +++++++++++++++--- .../views/res_config_settings.xml | 14 +- .../views/stock_warehouse.xml | 8 +- 13 files changed, 543 insertions(+), 140 deletions(-) create mode 100644 stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/post-mig.py create mode 100644 stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/pre-mig.py diff --git a/stock_warehouse_calendar_orderpoint/README.rst b/stock_warehouse_calendar_orderpoint/README.rst index 6b4411ddcd83..7b4caf8a01a5 100644 --- a/stock_warehouse_calendar_orderpoint/README.rst +++ b/stock_warehouse_calendar_orderpoint/README.rst @@ -7,7 +7,7 @@ Stock Warehouse Calendar (reordering rules) !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:37eef2072a4e67946542d61be1ad33d6f944a858e6c39d0e8c257435edb9941d + !! source digest: sha256:98565ba67ef39c3d2057bca2b8fd948f4989c37e962ea67d54ab940af6e3495c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png @@ -17,7 +17,7 @@ Stock Warehouse Calendar (reordering rules) :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-camptocamp%2Fstock--logistics--warehouse-lightgray.png?logo=github - :target: https://github.com/camptocamp/stock-logistics-warehouse/tree/14.0-add-stock_warehouse_calendar_purchase/stock_warehouse_calendar_orderpoint + :target: https://github.com/camptocamp/stock-logistics-warehouse/tree/14.0-add-stock_warehouse_calendar_orderpoint/stock_warehouse_calendar_orderpoint :alt: camptocamp/stock-logistics-warehouse |badge1| |badge2| |badge3| @@ -64,7 +64,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -92,6 +92,6 @@ Current maintainer: |maintainer-sebalix| -This module is part of the `camptocamp/stock-logistics-warehouse `_ project on GitHub. +This module is part of the `camptocamp/stock-logistics-warehouse `_ project on GitHub. You are welcome to contribute. diff --git a/stock_warehouse_calendar_orderpoint/__manifest__.py b/stock_warehouse_calendar_orderpoint/__manifest__.py index c7ca7e6e5459..e80062e04e62 100644 --- a/stock_warehouse_calendar_orderpoint/__manifest__.py +++ b/stock_warehouse_calendar_orderpoint/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock Warehouse Calendar (reordering rules)", "summary": "Adds a calendar to the Warehouse for reordering rules", - "version": "14.0.1.0.0", + "version": "14.0.1.1.0", "license": "LGPL-3", "website": "https://github.com/OCA/stock-logistics-warehouse", "author": "Camptocamp, " "Odoo Community Association (OCA)", @@ -14,9 +14,6 @@ "views/stock_warehouse.xml", "views/stock_warehouse_orderpoint.xml", ], - "demo": [ - "demo/resource_calendar.xml", - ], "installable": True, "development_status": "Production/Stable", "maintainers": ["sebalix"], diff --git a/stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/post-mig.py b/stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/post-mig.py new file mode 100644 index 000000000000..18bc0c11f016 --- /dev/null +++ b/stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/post-mig.py @@ -0,0 +1,25 @@ +# Copyright 2024 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl) + +from odoo.tools.sql import column_exists + + +def migrate(cr, version): + if not version: + return + if column_exists(cr, "stock_warehouse", "orderpoint_on_workday_tmp"): + # Fill ``orderpoint_on_workday_policy`` with a default value where needed, then + # drop the temporary column + cr.execute( + """ + UPDATE stock_warehouse + SET orderpoint_on_workday_policy = 'skip_to_first_workday' + WHERE orderpoint_on_workday_tmp + """ + ) + cr.execute( + """ + ALTER TABLE stock_warehouse + DROP COLUMN orderpoint_on_workday_tmp + """ + ) diff --git a/stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/pre-mig.py b/stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/pre-mig.py new file mode 100644 index 000000000000..1efbe4f29209 --- /dev/null +++ b/stock_warehouse_calendar_orderpoint/migrations/14.0.1.1.0/pre-mig.py @@ -0,0 +1,25 @@ +# Copyright 2024 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl) + +from odoo.tools.sql import column_exists + + +def migrate(cr, version): + if not version: + return + if column_exists(cr, "stock_warehouse", "orderpoint_on_workday"): + # Store ``orderpoint_on_workday`` in a temporary column to be used in the post-mig + # script to set default values for ``orderpoint_on_workday_policy`` + cr.execute( + """ + ALTER TABLE stock_warehouse + ADD COLUMN IF NOT EXISTS orderpoint_on_workday_tmp BOOLEAN DEFAULT false + """ + ) + cr.execute( + """ + UPDATE stock_warehouse + SET orderpoint_on_workday_tmp = true + WHERE orderpoint_on_workday + """ + ) diff --git a/stock_warehouse_calendar_orderpoint/models/res_company.py b/stock_warehouse_calendar_orderpoint/models/res_company.py index afed9524796e..80a9f4040eda 100644 --- a/stock_warehouse_calendar_orderpoint/models/res_company.py +++ b/stock_warehouse_calendar_orderpoint/models/res_company.py @@ -14,12 +14,6 @@ class ResCompany(models.Model): "This value will be used as default value for new warehouses linked to this" " company", ) - orderpoint_on_workday = fields.Boolean( - string="Schedule the lead date on workday only", - help="Postpone the lead date to the first available workday\n" - "This value will be used as default value for new warehouses linked to this" - " company", - ) orderpoint_on_workday_policy = fields.Selection( [ ("skip_to_first_workday", "Skip to first workday"), diff --git a/stock_warehouse_calendar_orderpoint/models/res_config_settings.py b/stock_warehouse_calendar_orderpoint/models/res_config_settings.py index 6a6fc716e4ec..7a3e39957b6e 100644 --- a/stock_warehouse_calendar_orderpoint/models/res_config_settings.py +++ b/stock_warehouse_calendar_orderpoint/models/res_config_settings.py @@ -11,10 +11,6 @@ class ResConfigSettings(models.TransientModel): related="company_id.orderpoint_calendar_id", readonly=False, ) - orderpoint_on_workday = fields.Boolean( - related="company_id.orderpoint_on_workday", - readonly=False, - ) orderpoint_on_workday_policy = fields.Selection( related="company_id.orderpoint_on_workday_policy", readonly=False, diff --git a/stock_warehouse_calendar_orderpoint/models/stock_warehouse.py b/stock_warehouse_calendar_orderpoint/models/stock_warehouse.py index 23e9f03b2e32..c956b76a3216 100644 --- a/stock_warehouse_calendar_orderpoint/models/stock_warehouse.py +++ b/stock_warehouse_calendar_orderpoint/models/stock_warehouse.py @@ -13,12 +13,6 @@ class StockWarehouse(models.Model): default=lambda o: o._default_orderpoint_calendar_id(), help="Calendar used to compute the lead date of reordering rules", ) - orderpoint_on_workday = fields.Boolean( - string="Reordering on Workday", - default=lambda o: o._default_orderpoint_on_workday(), - help="Postpone the lead date to the first available workday based on the" - " Working Hours calendar", - ) orderpoint_on_workday_policy = fields.Selection( [ ("skip_to_first_workday", "Skip to first workday"), @@ -40,8 +34,5 @@ class StockWarehouse(models.Model): def _default_orderpoint_calendar_id(self): return self.env.company.orderpoint_calendar_id - def _default_orderpoint_on_workday(self): - return self.env.company.orderpoint_on_workday - def _default_orderpoint_on_workday_policy(self): return self.env.company.orderpoint_on_workday_policy diff --git a/stock_warehouse_calendar_orderpoint/models/stock_warehouse_orderpoint.py b/stock_warehouse_calendar_orderpoint/models/stock_warehouse_orderpoint.py index 9d85a8fc8523..92f3c6dc3ae7 100644 --- a/stock_warehouse_calendar_orderpoint/models/stock_warehouse_orderpoint.py +++ b/stock_warehouse_calendar_orderpoint/models/stock_warehouse_orderpoint.py @@ -14,47 +14,54 @@ class StockWarehouseOrderpoint(models.Model): "rule_ids", "product_id.seller_ids", "product_id.seller_ids.delay", + "warehouse_id.calendar_id", "warehouse_id.orderpoint_calendar_id", "warehouse_id.orderpoint_on_workday_policy", ) def _compute_lead_days(self): super()._compute_lead_days() - # Override to use the orderpoint calendar to compute the 'lead_days_date' + # Override to use the WH/OP calendars to compute ``lead_days_date`` for orderpoint in self.with_context(bypass_delay_description=True): wh = orderpoint.warehouse_id if not orderpoint.product_id or not orderpoint.location_id: orderpoint.lead_days_date = False continue - # Get the next planned date to execute this orderpoint - start_date = orderpoint._get_next_reordering_date() + # Get the reordering date from the OP calendar + reordering_date = orderpoint._get_next_reordering_date() # Get the lead days for this orderpoint lead_days = orderpoint._get_lead_days() - # Get calendar, workday policy from warehouse + # Get the WH calendar calendar = wh.calendar_id - policy = wh.orderpoint_on_workday and wh.orderpoint_on_workday_policy - if calendar and policy == "skip_to_first_workday": - # Consume all the lead days, then move up to the first workday - # according to the calendar - lead_days_date = calendar.plan_hours( - 0, start_date + relativedelta(days=lead_days), compute_leaves=True - ) - elif calendar and policy == "skip_all_non_workdays": - # Postpone to the next available workday if needed, consuming lead days - # only on workdays - lead_days_date = calendar.plan_hours(0, start_date, compute_leaves=True) - if lead_days_date.date() != start_date.date(): - # We've consumed a lead day if the lead date is not the start date - lead_days -= 1 - while lead_days > 0: - # Always get the next working day according to the calendar, and - # decrease the lead days at each iteration - lead_days_date = calendar.plan_hours( - 0, lead_days_date + relativedelta(days=1), compute_leaves=True + if calendar and lead_days: + if wh.orderpoint_on_workday_policy == "skip_all_non_workdays": + # Get the first workday for the WH calendar after consuming the + # ``lead_days`` as workdays (for the WH calendar itself) starting + # from the day after the reordering date itself + lead_days_date = calendar.plan_days( + lead_days, + reordering_date + relativedelta(days=1), + compute_leaves=True, + ) + else: + # Get the first workday for the WH calendar after consuming the + # ``lead_days`` as solar days + # (This is the behavior for policy ``skip_to_first_workday``, but + # also a fallback in case the policy is not defined) + lead_days_date = calendar.plan_days( + 1, + reordering_date + relativedelta(days=lead_days), + compute_leaves=True, ) - lead_days -= 1 + elif calendar: + # Get the first workday for the WH calendar + lead_days_date = calendar.plan_days( + 1, reordering_date, compute_leaves=True + ) + elif lead_days: + # No WH calendar defined => consume ``lead_days`` as solar days + lead_days_date = reordering_date + relativedelta(days=lead_days) else: - # Simply postpone according to delays - lead_days_date = start_date + relativedelta(days=lead_days) + lead_days_date = reordering_date orderpoint.lead_days_date = lead_days_date def _get_lead_days(self): @@ -66,13 +73,13 @@ def _get_next_reordering_date(self): self.ensure_one() now = fields.Datetime.now() calendar = self.warehouse_id.orderpoint_calendar_id - # TODO: should we take into account days off or the reordering calendar with + # TODO: should we take into account days off of the reordering calendar with # 'compute_leaves=True' here? return calendar and calendar.plan_hours(0, now) or now @api.depends("rule_ids", "product_id.seller_ids", "product_id.seller_ids.delay") def _compute_json_popover(self): - # Overridden to sent the OP ID to 'stock.rule._get_lead_days()' + # Overridden to send the OP ID to 'stock.rule._get_lead_days()' # method through the context, so we can display the reordering date # on the popover forecast widget for orderpoint in self: diff --git a/stock_warehouse_calendar_orderpoint/static/description/index.html b/stock_warehouse_calendar_orderpoint/static/description/index.html index c1e7f764ac58..bff665bbcb05 100644 --- a/stock_warehouse_calendar_orderpoint/static/description/index.html +++ b/stock_warehouse_calendar_orderpoint/static/description/index.html @@ -366,9 +366,9 @@

Stock Warehouse Calendar (reordering rules)

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:37eef2072a4e67946542d61be1ad33d6f944a858e6c39d0e8c257435edb9941d +!! source digest: sha256:98565ba67ef39c3d2057bca2b8fd948f4989c37e962ea67d54ab940af6e3495c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Production/Stable License: LGPL-3 camptocamp/stock-logistics-warehouse

+

Production/Stable License: LGPL-3 camptocamp/stock-logistics-warehouse

This module adds an Reordering Calendar to the Warehouse. This calendar can then used by reordering rules to compute the forecasted date when goods will be received.

@@ -415,7 +415,7 @@

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -436,7 +436,7 @@

Contributors

Maintainers

Current maintainer:

sebalix

-

This module is part of the camptocamp/stock-logistics-warehouse project on GitHub.

+

This module is part of the camptocamp/stock-logistics-warehouse project on GitHub.

You are welcome to contribute.

diff --git a/stock_warehouse_calendar_orderpoint/tests/common.py b/stock_warehouse_calendar_orderpoint/tests/common.py index c0f5696ad2e3..d1979f26e539 100644 --- a/stock_warehouse_calendar_orderpoint/tests/common.py +++ b/stock_warehouse_calendar_orderpoint/tests/common.py @@ -11,14 +11,46 @@ def setUpClass(cls): cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) cls.product = cls.env.ref("product.product_delivery_02").copy() cls.wh = cls.env.ref("stock.warehouse0") - cls.wh.write( + days_names = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] + cls.working_hours_calendar = cls.env["resource.calendar"].create( { - "calendar_id": cls.env.ref("resource.resource_calendar_std").id, - "orderpoint_calendar_id": cls.env.ref( - "stock_warehouse_calendar_orderpoint.resource_calendar_orderpoint_demo" - ).id, - "orderpoint_on_workday": True, - "orderpoint_on_workday_policy": "skip_to_first_workday", + "name": "Working Hours (Mon-Fri, 8-12 + 13-17)", + "tz": "UTC", + "attendance_ids": [ + ( + 0, + 0, + { + "name": days_names[day], + "dayofweek": str(day), + "hour_from": hour, + "hour_to": hour + 4, + "day_period": "morning" if hour < 12 else "afternoon", + }, + ) + for day in (0, 1, 2, 3, 4) + for hour in (8, 13) + ], + } + ) + cls.reordering_calendar = cls.env["resource.calendar"].create( + { + "name": "Reordering Hours (Wed 8-12 + 13-17, Sat 13-17)", + "tz": "UTC", + "attendance_ids": [ + ( + 0, + 0, + { + "name": days_names[day], + "dayofweek": str(day), + "hour_from": hour, + "hour_to": hour + 4, + "day_period": "morning" if hour < 12 else "afternoon", + }, + ) + for day, hour in ((2, 8), (2, 13), (5, 13)) + ], } ) cls.orderpoint = cls.env["stock.warehouse.orderpoint"].create( @@ -31,4 +63,9 @@ def setUpClass(cls): "product_uom": cls.env.ref("uom.product_uom_unit"), } ) - cls.orderpoint.rule_ids.write({"action": "pull", "delay": 2}) + # We want only 1 reordering rule of type "pull" to avoid inconsistent behaviors + cls.reordering_rule = cls.orderpoint.rule_ids[0] + cls.reordering_rule.action = "pull" + other_rules = cls.orderpoint.rule_ids - cls.reordering_rule + if other_rules: + other_rules.unlink() diff --git a/stock_warehouse_calendar_orderpoint/tests/test_calendar_orderpoint.py b/stock_warehouse_calendar_orderpoint/tests/test_calendar_orderpoint.py index 4dbbfb3af238..c5bbf44b5a24 100644 --- a/stock_warehouse_calendar_orderpoint/tests/test_calendar_orderpoint.py +++ b/stock_warehouse_calendar_orderpoint/tests/test_calendar_orderpoint.py @@ -7,57 +7,404 @@ class TestCalendarOrderpoint(CommonCalendarOrderpoint): - """Lead date of orderpoints are computed from Wednesday.""" - - def setUp(self): - super().setUp() - # Reset cached value as it could have been computed during initialization - self.op_model = self.env["stock.warehouse.orderpoint"] - self.op_model.invalidate_cache(["lead_days_date"]) - - @freeze_time("2022-05-30 12:00") # Monday - def test_calendar_orderpoint_monday(self): - # Monday -> Wednesday + 2 days rule delay => Friday - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-03") - - @freeze_time("2022-06-01 12:00") # Wednesday during working hours - def test_calendar_orderpoint_wednesday_during_working_hours(self): - self.op_model.invalidate_cache(["lead_days_date"]) # Recompute field - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-03") - - @freeze_time("2022-06-01 20:00") # Wednesday after working hours - def test_calendar_orderpoint_wednesday_outside_working_hours(self): - self.op_model.invalidate_cache(["lead_days_date"]) # Recompute field - self.assertEqual( - str(self.orderpoint.lead_days_date), - "2022-06-06", # Postponed to the next working day - ) - - @freeze_time("2022-06-01 23:30") - def test_calendar_orderpoint_wednesday_outside_of_all_calendars(self): - # Wednesday outside working hours - # + outside of reordering timeslots (00:00 -> 23:00) - self.op_model.invalidate_cache(["lead_days_date"]) # Recompute field - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-10") - - @freeze_time("2022-06-02 11:00") # Thursday - def test_calendar_orderpoint_thursday(self): - self.op_model.invalidate_cache(["lead_days_date"]) - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-10") - - @freeze_time("2022-06-09 10:00") # Next Thursday - def test_calendar_orderpoint_next_thursday(self): - self.op_model.invalidate_cache(["lead_days_date"]) - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-17") - - @freeze_time("2022-06-01 12:00") # Wednesday during working hours - def test_calendar_orderpoint_policy(self): - self.orderpoint.rule_ids.delay = 4 - # 4 days are counted from Wednesday to Sunday => end on Monday - self.wh.orderpoint_on_workday_policy = "skip_to_first_workday" - self.op_model.invalidate_cache(["lead_days_date"]) - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-06") - # 4 days are counted from Wednesday, skipping the weekend => end on Tuesday - self.wh.orderpoint_on_workday_policy = "skip_all_non_workdays" - self.op_model.invalidate_cache(["lead_days_date"]) - self.assertEqual(str(self.orderpoint.lead_days_date), "2022-06-07") + """Tests orderpoints' forecast date computations + + The OP calendar defines reordering slots as Wed 8-12 + 13-17, Sat 13-17. + The WH calendar defines workdays as Mon-Fri 8-12 + 13-17. + + Each test is determined by the date it's executed on, and whether the OP calendar + is set or not. Tests are executed on: + - Monday (non-reordering day for OP calendar, workday for WH calendar) + - Wednesday (reordering day for OP calendar, workday for WH calendar) + - Saturday (reordering day for OP calendar, non-workday for WH calendar) + - Sunday (non-reordering day for OP calendar, non-workday for WH calendar) + On Wednesday and Saturday, tests are executed before, during, after and between + reordering slots. + + In each test, the forecast date is tested 5 times: + - 1: WH calendar set, lead days ≠ 0, policy = "skip_to_first_workday" + - 2: WH calendar set, lead days ≠ 0, policy = "skip_all_non_workdays" + - 3: WH calendar not set, lead days ≠ 0 + - 4: WH calendar set, lead days = 0 + - 5: WH calendar not set, lead days ≠ 0 + """ + + def _test_with_values(self, op_calendar, wh_calendar, policy, delay, expected_dt): + self.wh.orderpoint_calendar_id = op_calendar + self.wh.calendar_id = wh_calendar + self.wh.orderpoint_on_workday_policy = policy + self.reordering_rule.delay = delay + self.env["stock.warehouse.orderpoint"].invalidate_cache(["lead_days_date"]) + self.assertEqual(str(self.orderpoint.lead_days_date), expected_dt) + + @freeze_time("2024-04-01 10:00") + def test_00_monday_with_orderpoint_calendar_set(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-03 08:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-07") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-03", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-03") + + @freeze_time("2024-04-01 12:00") + def test_01_monday_with_orderpoint_calendar_unset(self): + self.wh.orderpoint_calendar_id = False + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-01 12:00:00" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_to_first_workday", 6, "2024-04-08" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_all_non_workdays", 6, "2024-04-09" + ) + self._test_with_values(False, False, False, 6, "2024-04-07") + self._test_with_values( + False, self.working_hours_calendar, False, 0, "2024-04-01" + ) + self._test_with_values(False, False, False, 0, "2024-04-01") + + @freeze_time("2024-04-03 06:00") + def test_02_wednesday_with_orderpoint_calendar_set_before_first_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-03 08:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-07") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-03", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-03") + + @freeze_time("2024-04-03 10:00") + def test_03_wednesday_with_orderpoint_calendar_set_during_first_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-03 10:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-07") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-03", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-03") + + @freeze_time("2024-04-03 12:30") + def test_04_wednesday_with_orderpoint_calendar_set_between_slots(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-03 13:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-07") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-03", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-03") + + @freeze_time("2024-04-03 15:00") + def test_05_wednesday_with_orderpoint_calendar_set_during_second_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-03 15:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-07") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-03", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-03") + + @freeze_time("2024-04-03 19:00") + def test_06_wednesday_with_orderpoint_calendar_set_after_second_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-06 13:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 7, + "2024-04-15", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 7, + "2024-04-16", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-10") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-08", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-06") + + @freeze_time("2024-04-03 12:00") + def test_07_wednesday_with_orderpoint_calendar_unset(self): + self.wh.orderpoint_calendar_id = False + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-03 12:00:00" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_to_first_workday", 4, "2024-04-08" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_all_non_workdays", 4, "2024-04-09" + ) + self._test_with_values(False, False, False, 4, "2024-04-07") + self._test_with_values( + False, self.working_hours_calendar, False, 0, "2024-04-03" + ) + self._test_with_values(False, False, False, 0, "2024-04-03") + + @freeze_time("2024-04-06 12:00") + def test_08_saturday_with_orderpoint_calendar_set_before_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-06 13:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 2, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 2, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 7, "2024-04-13") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-08", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-06") + + @freeze_time("2024-04-06 15:00") + def test_09_saturday_with_orderpoint_calendar_set_during_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-06 15:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 2, + "2024-04-08", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 2, + "2024-04-09", + ) + self._test_with_values(self.reordering_calendar, False, False, 7, "2024-04-13") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-08", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-06") + + @freeze_time("2024-04-06 18:00") + def test_10_saturday_with_orderpoint_calendar_set_after_slot(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-10 08:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-15", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-16", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-14") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-10", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-10") + + @freeze_time("2024-04-06 12:00") + def test_11_saturday_with_orderpoint_calendar_unset(self): + self.wh.orderpoint_calendar_id = False + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-06 12:00:00" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_to_first_workday", 7, "2024-04-15" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_all_non_workdays", 7, "2024-04-16" + ) + self._test_with_values(False, False, False, 4, "2024-04-10") + self._test_with_values( + False, self.working_hours_calendar, False, 0, "2024-04-08" + ) + self._test_with_values(False, False, False, 0, "2024-04-06") + + @freeze_time("2024-04-07 12:00") + def test_12_sunday_with_orderpoint_calendar_set(self): + self.wh.orderpoint_calendar_id = self.reordering_calendar + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-10 08:00:00" + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_to_first_workday", + 4, + "2024-04-15", + ) + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + "skip_all_non_workdays", + 4, + "2024-04-16", + ) + self._test_with_values(self.reordering_calendar, False, False, 4, "2024-04-14") + self._test_with_values( + self.reordering_calendar, + self.working_hours_calendar, + False, + 0, + "2024-04-10", + ) + self._test_with_values(self.reordering_calendar, False, False, 0, "2024-04-10") + + @freeze_time("2024-04-07 12:00") + def test_13_sunday_with_orderpoint_calendar_unset(self): + self.wh.orderpoint_calendar_id = False + self.assertEqual( + str(self.orderpoint._get_next_reordering_date()), "2024-04-07 12:00:00" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_to_first_workday", 7, "2024-04-15" + ) + self._test_with_values( + False, self.working_hours_calendar, "skip_all_non_workdays", 7, "2024-04-16" + ) + self._test_with_values(False, False, False, 7, "2024-04-14") + self._test_with_values( + False, self.working_hours_calendar, False, 0, "2024-04-08" + ) + self._test_with_values(False, False, False, 0, "2024-04-07") diff --git a/stock_warehouse_calendar_orderpoint/views/res_config_settings.xml b/stock_warehouse_calendar_orderpoint/views/res_config_settings.xml index 1f84db65e986..c42ae6a5e71b 100644 --- a/stock_warehouse_calendar_orderpoint/views/res_config_settings.xml +++ b/stock_warehouse_calendar_orderpoint/views/res_config_settings.xml @@ -30,24 +30,12 @@
- -
-
-
-
diff --git a/stock_warehouse_calendar_orderpoint/views/stock_warehouse.xml b/stock_warehouse_calendar_orderpoint/views/stock_warehouse.xml index 7ab7127dd2e9..7591426c5e4a 100644 --- a/stock_warehouse_calendar_orderpoint/views/stock_warehouse.xml +++ b/stock_warehouse_calendar_orderpoint/views/stock_warehouse.xml @@ -9,19 +9,15 @@ - {'required': [('orderpoint_on_workday', '=', True)]} + >{'required': [('orderpoint_on_workday_policy', '!=', False)]}