diff --git a/stock_warehouse_calendar/README.rst b/stock_warehouse_calendar/README.rst new file mode 100644 index 000000000..ba0dbb58f --- /dev/null +++ b/stock_warehouse_calendar/README.rst @@ -0,0 +1,116 @@ +======================== +Stock Warehouse Calendar +======================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github + :target: https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_warehouse_calendar + :alt: OCA/stock-logistics-warehouse +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_warehouse_calendar + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/153/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds a Calendar to the Warehouse. This calendar can then used as +the basis of the proper computation of start/end dates based on lead times in +this and other modules. + +In this module, the calendar considered in the computation of start date of +stock moves and pickings created from procurements, where the lead time +is used. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +* Go to *Settings* and activate the developer mode. + +* Go to *Settings > Technical > Resource > Working Time* and define your + resource calendar. + +* Go to *Inventory > Configuration > Warehouse Management > Warehouses* + and assign the Resource Calendar. + +* Go to *Inventory > Configuration > Settings* and in *Warehouse* mark + 'Multi-Step Routes option'. + +* Go to *Inventory > Configuration > Warehouse Management > Routes* and + set up the proper delays in the stock rules where 'action' + is 'Move From Another Location'. + +Usage +===== + +When a picking is created out of a procurement evaluation (from an +orderpoint, MTO,...) the calendar is considered in the computation of the +expected date of the picking and moves. For example, if it takes 1 day to +execute a stock transfer from another warehouse and it is Monday, the picking +to resupply will be created with expected start date on the previous Friday, +if the warehouse operates under a Mo-Fri working calendar. + +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 smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ForgeFlow + +Contributors +~~~~~~~~~~~~ + +* Jordi Ballester +* Lois Rilo + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-JordiBForgeFlow| image:: https://github.com/JordiBForgeFlow.png?size=40px + :target: https://github.com/JordiBForgeFlow + :alt: JordiBForgeFlow + +Current `maintainer `__: + +|maintainer-JordiBForgeFlow| + +This module is part of the `OCA/stock-logistics-warehouse `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/stock_warehouse_calendar/__init__.py b/stock_warehouse_calendar/__init__.py new file mode 100644 index 000000000..133f68732 --- /dev/null +++ b/stock_warehouse_calendar/__init__.py @@ -0,0 +1,2 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from . import models diff --git a/stock_warehouse_calendar/__manifest__.py b/stock_warehouse_calendar/__manifest__.py new file mode 100644 index 000000000..aa5fe1855 --- /dev/null +++ b/stock_warehouse_calendar/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Stock Warehouse Calendar", + "summary": "Adds a calendar to the Warehouse", + "version": "13.0.1.0.0", + "license": "LGPL-3", + "website": "https://github.com/stock-logistics-warehouse", + "author": "ForgeFlow, " "Odoo Community Association (OCA)", + "category": "Warehouse Management", + "depends": ["stock", "resource"], + "data": ["views/stock_warehouse_views.xml"], + "installable": True, + "development_status": "Beta", + "maintainers": ["JordiBForgeFlow"], +} diff --git a/stock_warehouse_calendar/i18n/stock_warehouse_calendar.pot b/stock_warehouse_calendar/i18n/stock_warehouse_calendar.pot new file mode 100644 index 000000000..5f3f13eed --- /dev/null +++ b/stock_warehouse_calendar/i18n/stock_warehouse_calendar.pot @@ -0,0 +1,30 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_warehouse_calendar +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_warehouse_calendar +#: model:ir.model,name:stock_warehouse_calendar.model_stock_rule +msgid "Stock Rule" +msgstr "" + +#. module: stock_warehouse_calendar +#: model:ir.model,name:stock_warehouse_calendar.model_stock_warehouse +msgid "Warehouse" +msgstr "" + +#. module: stock_warehouse_calendar +#: model:ir.model.fields,field_description:stock_warehouse_calendar.field_stock_warehouse__calendar_id +msgid "Working Hours" +msgstr "" + diff --git a/stock_warehouse_calendar/i18n/zh_CN.po b/stock_warehouse_calendar/i18n/zh_CN.po new file mode 100644 index 000000000..12e8fb8d7 --- /dev/null +++ b/stock_warehouse_calendar/i18n/zh_CN.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_warehouse_calendar +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-10-16 15:58+0000\n" +"Last-Translator: 黎伟杰 <674416404@qq.com>\n" +"Language-Team: none\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.8\n" + +#. module: stock_warehouse_calendar +#: model:ir.model,name:stock_warehouse_calendar.model_stock_rule +msgid "Stock Rule" +msgstr "库存规则" + +#. module: stock_warehouse_calendar +#: model:ir.model,name:stock_warehouse_calendar.model_stock_warehouse +msgid "Warehouse" +msgstr "仓库" + +#. module: stock_warehouse_calendar +#: model:ir.model.fields,field_description:stock_warehouse_calendar.field_stock_warehouse__calendar_id +msgid "Working Hours" +msgstr "工作时间" diff --git a/stock_warehouse_calendar/models/__init__.py b/stock_warehouse_calendar/models/__init__.py new file mode 100644 index 000000000..200eddbf2 --- /dev/null +++ b/stock_warehouse_calendar/models/__init__.py @@ -0,0 +1,3 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). +from . import stock_warehouse +from . import stock_rule diff --git a/stock_warehouse_calendar/models/stock_rule.py b/stock_warehouse_calendar/models/stock_rule.py new file mode 100644 index 000000000..baf30d037 --- /dev/null +++ b/stock_warehouse_calendar/models/stock_rule.py @@ -0,0 +1,41 @@ +# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import datetime + +from odoo import models + + +class StockRule(models.Model): + _inherit = "stock.rule" + + def _get_stock_move_values( + self, + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ): + res = super(StockRule, self)._get_stock_move_values( + product_id, + product_qty, + product_uom, + location_id, + name, + origin, + company_id, + values, + ) + warehouse = self.propagate_warehouse_id or self.warehouse_id + if warehouse.calendar_id and self.delay: + date_expected = warehouse.wh_plan_days( + values["date_planned"], -1 * self.delay + ) + if date_expected > datetime.now(): + res["date"] = date_expected + res["date_expected"] = date_expected + return res diff --git a/stock_warehouse_calendar/models/stock_warehouse.py b/stock_warehouse_calendar/models/stock_warehouse.py new file mode 100644 index 000000000..26318c2f6 --- /dev/null +++ b/stock_warehouse_calendar/models/stock_warehouse.py @@ -0,0 +1,41 @@ +# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from datetime import datetime, timedelta + +from odoo import fields, models + + +class StockWarehouse(models.Model): + _inherit = "stock.warehouse" + + calendar_id = fields.Many2one( + comodel_name="resource.calendar", string="Working Hours" + ) + + def wh_plan_days(self, date_from, delta): + """Helper method to schedule warehouse operations based on its + working days (if set). + + :param datetime date_from: reference date. + :param integer delta: offset to apply. + :return: datetime: resulting date. + """ + self.ensure_one() + if not isinstance(date_from, datetime): + date_from = fields.Datetime.to_datetime(date_from) + if delta == 0: + return date_from + + if self.calendar_id: + if delta < 0: + # We force the date planned to be at the beginning of the day. + # So no work intervals are found in the reference date. + dt_planned = date_from.replace(hour=0) + else: + # We force the date planned at the end of the day. + dt_planned = date_from.replace(hour=23) + date_result = self.calendar_id.plan_days(delta, dt_planned) + else: + date_result = date_from + timedelta(days=delta) + return date_result diff --git a/stock_warehouse_calendar/readme/CONFIGURE.rst b/stock_warehouse_calendar/readme/CONFIGURE.rst new file mode 100644 index 000000000..2c97aad45 --- /dev/null +++ b/stock_warehouse_calendar/readme/CONFIGURE.rst @@ -0,0 +1,14 @@ +* Go to *Settings* and activate the developer mode. + +* Go to *Settings > Technical > Resource > Working Time* and define your + resource calendar. + +* Go to *Inventory > Configuration > Warehouse Management > Warehouses* + and assign the Resource Calendar. + +* Go to *Inventory > Configuration > Settings* and in *Warehouse* mark + 'Multi-Step Routes option'. + +* Go to *Inventory > Configuration > Warehouse Management > Routes* and + set up the proper delays in the stock rules where 'action' + is 'Move From Another Location'. diff --git a/stock_warehouse_calendar/readme/CONTRIBUTORS.rst b/stock_warehouse_calendar/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..8cc067b15 --- /dev/null +++ b/stock_warehouse_calendar/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Jordi Ballester +* Lois Rilo diff --git a/stock_warehouse_calendar/readme/DESCRIPTION.rst b/stock_warehouse_calendar/readme/DESCRIPTION.rst new file mode 100644 index 000000000..ac46ffca3 --- /dev/null +++ b/stock_warehouse_calendar/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +This module adds a Calendar to the Warehouse. This calendar can then used as +the basis of the proper computation of start/end dates based on lead times in +this and other modules. + +In this module, the calendar considered in the computation of start date of +stock moves and pickings created from procurements, where the lead time +is used. diff --git a/stock_warehouse_calendar/readme/USAGE.rst b/stock_warehouse_calendar/readme/USAGE.rst new file mode 100644 index 000000000..f71e1f60c --- /dev/null +++ b/stock_warehouse_calendar/readme/USAGE.rst @@ -0,0 +1,6 @@ +When a picking is created out of a procurement evaluation (from an +orderpoint, MTO,...) the calendar is considered in the computation of the +expected date of the picking and moves. For example, if it takes 1 day to +execute a stock transfer from another warehouse and it is Monday, the picking +to resupply will be created with expected start date on the previous Friday, +if the warehouse operates under a Mo-Fri working calendar. diff --git a/stock_warehouse_calendar/static/description/icon.png b/stock_warehouse_calendar/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/stock_warehouse_calendar/static/description/icon.png differ diff --git a/stock_warehouse_calendar/static/description/index.html b/stock_warehouse_calendar/static/description/index.html new file mode 100644 index 000000000..da42a079a --- /dev/null +++ b/stock_warehouse_calendar/static/description/index.html @@ -0,0 +1,453 @@ + + + + + + +Stock Warehouse Calendar + + + +
+

Stock Warehouse Calendar

+ + +

Beta License: LGPL-3 OCA/stock-logistics-warehouse Translate me on Weblate Try me on Runbot

+

This module adds a Calendar to the Warehouse. This calendar can then used as +the basis of the proper computation of start/end dates based on lead times in +this and other modules.

+

In this module, the calendar considered in the computation of start date of +stock moves and pickings created from procurements, where the lead time +is used.

+

Table of contents

+ +
+

Configuration

+
    +
  • Go to Settings and activate the developer mode.
  • +
  • Go to Settings > Technical > Resource > Working Time and define your +resource calendar.
  • +
  • Go to Inventory > Configuration > Warehouse Management > Warehouses +and assign the Resource Calendar.
  • +
  • Go to Inventory > Configuration > Settings and in Warehouse mark +‘Multi-Step Routes option’.
  • +
  • Go to Inventory > Configuration > Warehouse Management > Routes and +set up the proper delays in the stock rules where ‘action’ +is ‘Move From Another Location’.
  • +
+
+
+

Usage

+

When a picking is created out of a procurement evaluation (from an +orderpoint, MTO,…) the calendar is considered in the computation of the +expected date of the picking and moves. For example, if it takes 1 day to +execute a stock transfer from another warehouse and it is Monday, the picking +to resupply will be created with expected start date on the previous Friday, +if the warehouse operates under a Mo-Fri working calendar.

+
+
+

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 smashing it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ForgeFlow
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

JordiBForgeFlow

+

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

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/stock_warehouse_calendar/tests/__init__.py b/stock_warehouse_calendar/tests/__init__.py new file mode 100644 index 000000000..a9c56aa8e --- /dev/null +++ b/stock_warehouse_calendar/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_warehouse_calendar diff --git a/stock_warehouse_calendar/tests/test_stock_warehouse_calendar.py b/stock_warehouse_calendar/tests/test_stock_warehouse_calendar.py new file mode 100644 index 000000000..15d8983e5 --- /dev/null +++ b/stock_warehouse_calendar/tests/test_stock_warehouse_calendar.py @@ -0,0 +1,120 @@ +# Copyright 2018-19 ForgeFlow S.L. (https://www.forgeflow.com) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import fields +from odoo.tests.common import TransactionCase + + +class TestStockWarehouseCalendar(TransactionCase): + def setUp(self): + super(TestStockWarehouseCalendar, self).setUp() + self.wh_obj = self.env["stock.warehouse"] + self.move_obj = self.env["stock.move"] + self.pg_obj = self.env["procurement.group"] + + self.company = self.env.ref("base.main_company") + self.warehouse = self.env.ref("stock.warehouse0") + self.customer_loc = self.env.ref("stock.stock_location_customers") + self.company_partner = self.env.ref("base.main_partner") + self.calendar = self.env.ref("resource.resource_calendar_std") + self.warehouse.calendar_id = self.calendar + self.warehouse_2 = self.wh_obj.create( + {"code": "WH-T", "name": "Warehouse Test", "calendar_id": self.calendar.id} + ) + self.warehouse_3 = self.wh_obj.create( + {"code": "WH-no-calendar", "name": "Warehouse Test 2"} + ) + + self.product = self.env["product.product"].create( + {"name": "test product", "default_code": "PRD", "type": "product"} + ) + + route_vals = {"name": "WH2 -> WH"} + self.transfer_route = self.env["stock.location.route"].create(route_vals) + rule_vals = { + "location_id": self.warehouse.lot_stock_id.id, + "location_src_id": self.warehouse_2.lot_stock_id.id, + "action": "pull_push", + "warehouse_id": self.warehouse.id, + "propagate_warehouse_id": self.warehouse_2.id, + "picking_type_id": self.env.ref("stock.picking_type_internal").id, + "name": "WH2->WH", + "route_id": self.transfer_route.id, + "delay": 1, + } + self.transfer_rule = self.env["stock.rule"].create(rule_vals) + self.product.route_ids = [(6, 0, self.transfer_route.ids)] + + def test_01_procurement_with_calendar(self): + values = { + "date_planned": "2097-01-07 09:00:00", # Monday + "warehouse_id": self.warehouse, + "company_id": self.company, + "rule_id": self.transfer_rule, + } + self.pg_obj.run( + [ + self.pg_obj.Procurement( + self.product, + 100, + self.product.uom_id, + self.warehouse.lot_stock_id, + "Test", + "Test", + self.warehouse.company_id, + values, + ) + ] + ) + move = self.env["stock.move"].search( + [("product_id", "=", self.product.id)], limit=1 + ) + date_expected = fields.Date.to_date(move.date_expected) + # Friday 4th Jan 2017 + friday = fields.Date.to_date("2097-01-04 09:00:00") + + self.assertEquals(date_expected, friday) + + def test_02_procurement_with_calendar_early(self): + """Test procuring at the beginning of the day, with no work intervals + before.""" + values = { + "date_planned": "2097-01-07 01:00:00", # Monday + "warehouse_id": self.warehouse, + "company_id": self.company, + "rule_id": self.transfer_rule, + } + self.pg_obj.run( + [ + self.pg_obj.Procurement( + self.product, + 100, + self.product.uom_id, + self.warehouse.lot_stock_id, + "Test", + "Test", + self.warehouse.company_id, + values, + ) + ] + ) + move = self.env["stock.move"].search( + [("product_id", "=", self.product.id)], limit=1 + ) + date_expected = fields.Date.to_date(move.date_expected) + # Friday 4th Jan 2017 + friday = fields.Date.to_date("2097-01-04 09:00:00") + + self.assertEquals(date_expected, friday) + + def test_03_wh_plan_days_future(self): + """Test plan days helper in warehouse.""" + reference = "2097-01-09 12:00:00" # Wednesday + # With calendar + result = self.warehouse_2.wh_plan_days(reference, 3).date() + next_monday = fields.Date.to_date("2097-01-14") + self.assertEquals(result, next_monday) + # Without calendar + result = self.warehouse_3.wh_plan_days(reference, 3).date() + saturday = fields.Date.to_date("2097-01-12") + self.assertEquals(result, saturday) diff --git a/stock_warehouse_calendar/views/stock_warehouse_views.xml b/stock_warehouse_calendar/views/stock_warehouse_views.xml new file mode 100644 index 000000000..7f07fa9e0 --- /dev/null +++ b/stock_warehouse_calendar/views/stock_warehouse_views.xml @@ -0,0 +1,16 @@ + + + + + + stock.warehouse + stock.warehouse + + + + + + + +