diff --git a/stock_orderpoint_procurement_date/__manifest__.py b/stock_orderpoint_procurement_date/__manifest__.py index d04d733..2079e27 100644 --- a/stock_orderpoint_procurement_date/__manifest__.py +++ b/stock_orderpoint_procurement_date/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Stock Orderpoint Procurement Date", - "version": "1.0.0", + "version": "1.1.0", "author": "Numigi", "maintainer": "Numigi", "website": "https://bit.ly/numigi-com", diff --git a/stock_orderpoint_procurement_date/models/stock_orderpoint.py b/stock_orderpoint_procurement_date/models/stock_orderpoint.py index 433685c..40736d7 100644 --- a/stock_orderpoint_procurement_date/models/stock_orderpoint.py +++ b/stock_orderpoint_procurement_date/models/stock_orderpoint.py @@ -1,146 +1,28 @@ # Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import logging from datetime import datetime, time -from psycopg2 import OperationalError from pytz import timezone, UTC -from odoo import SUPERUSER_ID, registry -from odoo.addons.stock.models.stock_rule import ProcurementException -from odoo.tools import float_compare, split_every +from odoo import models -from odoo.addons.stock.models.stock_orderpoint import StockWarehouseOrderpoint +class Orderpoint(models.Model): + _inherit = "stock.warehouse.orderpoint" - -_logger = logging.getLogger(__name__) - - -class StockWarehouseOrderpoint(StockWarehouseOrderpoint): - - def _get_orderpoint_procurement_date(self, lead_days_date): - """Return the right procurement date for the orderpoint.""" + def _get_date_per_tz(self, date): + """Return the right date per company tz""" return ( timezone(self.company_id.partner_id.tz or "UTC") - .localize(datetime.combine(lead_days_date, time(12))) + .localize(datetime.combine(date, time(12))) .astimezone(UTC) .replace(tzinfo=None) ) - def _procure_orderpoint_confirm( - self, use_new_cursor=False, company_id=None, raise_user_error=True - ): - """Create procurements based on orderpoints. - :param bool use_new_cursor: if set, use a dedicated cursor and auto-commit - after processing 1000 orderpoints. - This is appropriate for batch jobs only. - """ - self = self.with_company(company_id) - orderpoints_noprefetch = self.read(["id"]) - orderpoints_noprefetch = [ - orderpoint["id"] for orderpoint in orderpoints_noprefetch - ] - for orderpoints_batch in split_every(1000, orderpoints_noprefetch): - if use_new_cursor: - cr = registry(self._cr.dbname).cursor() - self = self.with_env(self.env(cr=cr)) - try: - orderpoints_batch = self.env["stock.warehouse.orderpoint"].browse( - orderpoints_batch - ) - orderpoints_exceptions = [] - while orderpoints_batch: - procurements = [] - for orderpoint in orderpoints_batch: - origins = orderpoint.env.context.get("origins", {}).get( - orderpoint.id, False - ) - if origins: - origin = "%s - %s" % ( - orderpoint.display_name, - ",".join(origins), - ) - else: - origin = orderpoint.name - if ( - float_compare( - orderpoint.qty_to_order, - 0.0, - precision_rounding=orderpoint.product_uom.rounding, - ) == 1 - ): - date = self._get_orderpoint_procurement_date( - orderpoint.lead_days_date - ) # This is the improvement to get the right date - values = orderpoint._prepare_procurement_values(date=date) - procurements.append( - self.env["procurement.group"].Procurement( - orderpoint.product_id, - orderpoint.qty_to_order, - orderpoint.product_uom, - orderpoint.location_id, - orderpoint.name, - origin, - orderpoint.company_id, - values, - ) - ) - try: - with self.env.cr.savepoint(): - self.env["procurement.group"].with_context( - from_orderpoint=True - ).run(procurements, raise_user_error=raise_user_error) - except ProcurementException as errors: - for procurement, error_msg in errors.procurement_exceptions: - orderpoints_exceptions += [ - (procurement.values.get("orderpoint_id"), error_msg) - ] - failed_orderpoints = self.env[ - "stock.warehouse.orderpoint" - ].concat(*[o[0] for o in orderpoints_exceptions]) - if not failed_orderpoints: - _logger.error("Unable to process orderpoints") - break - orderpoints_batch -= failed_orderpoints - - except OperationalError: - if use_new_cursor: - cr.rollback() - continue - else: - raise - else: - orderpoints_batch._post_process_scheduler() - break - - # Log an activity on product template for failed orderpoints. - for orderpoint, error_msg in orderpoints_exceptions: - existing_activity = self.env["mail.activity"].search( - [ - ("res_id", "=", orderpoint.product_id.product_tmpl_id.id), - ( - "res_model_id", - "=", - self.env.ref("product.model_product_template").id, - ), - ("note", "=", error_msg), - ] - ) - if not existing_activity: - orderpoint.product_id.product_tmpl_id.activity_schedule( - "mail.mail_activity_data_warning", - note=error_msg, - user_id=orderpoint.product_id.responsible_id.id - or SUPERUSER_ID, - ) - finally: - if use_new_cursor: - try: - cr.commit() - finally: - cr.close() - - return {} - - StockWarehouseOrderpoint._procure_orderpoint_confirm = _procure_orderpoint_confirm + def _prepare_procurement_values(self, date=False, group=False): + values = super()._prepare_procurement_values(date=date, group=group) + date_planned = self._get_date_per_tz(values["date_planned"]) + date = self._get_date_per_tz(date) + values["date_planned"] = date_planned + values["date_deadline"] = date or False + return values diff --git a/stock_orderpoint_procurement_date/tests/__init__.py b/stock_orderpoint_procurement_date/tests/__init__.py deleted file mode 100644 index 614e46e..0000000 --- a/stock_orderpoint_procurement_date/tests/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from . import test_orderpoint_procurement_date diff --git a/stock_orderpoint_procurement_date/tests/test_orderpoint_procurement_date.py b/stock_orderpoint_procurement_date/tests/test_orderpoint_procurement_date.py deleted file mode 100644 index 232debe..0000000 --- a/stock_orderpoint_procurement_date/tests/test_orderpoint_procurement_date.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from datetime import datetime, time, timedelta -from pytz import timezone, UTC -from odoo.tests import TransactionCase - - -class TestStockWarehouseOrderpoint(TransactionCase): - - def setUp(self): - super(TestStockWarehouseOrderpoint, self).setUp() - # Assuming that the product and company are set up in the test database - self.orderpoint = self.env["stock.warehouse.orderpoint"].create( - { - "product_id": self.env.ref("product.product_product_1").id, - "company_id": self.env.ref("base.main_company").id, - "location_id": self.env.ref("stock.stock_location_stock").id, - "product_min_qty": 0.0, - "product_max_qty": 10.0, - "qty_multiple": 1.0, - "warehouse_id": self.env.ref("stock.warehouse0").id, - } - ) - - def test__get_orderpoint_procurement_date_with_timezone(self): - lead_days_date = datetime.now().date() + timedelta(days=5) - expected_date = ( - timezone(self.orderpoint.company_id.partner_id.tz or "UTC") - .localize(datetime.combine(lead_days_date, time(12))) - .astimezone(UTC) - .replace(tzinfo=None) - ) - procurement_date = self.orderpoint._get_orderpoint_procurement_date( - lead_days_date - ) - self.assertEqual(procurement_date, expected_date)