odoo-addon-stock-release-channel 16.0.3.0.0__py3-none-any.whl → 16.0.3.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ Stock Release Channels
7
7
  !! This file is generated by oca-gen-addon-readme !!
8
8
  !! changes will be overwritten. !!
9
9
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10
- !! source digest: sha256:d3e4a6ca33a07a0967c75174dc29fa2dc7cc413f659bcd0686dd3238396bd3a8
10
+ !! source digest: sha256:2fad401dca0aa4a4f4b0e8ddcc83fd0010d54cdfe53ed66d8fc01049bdb6d273
11
11
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12
12
 
13
13
  .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -5,7 +5,7 @@
5
5
  {
6
6
  "name": "Stock Release Channels",
7
7
  "summary": "Manage workload in WMS with release channels",
8
- "version": "16.0.3.0.0",
8
+ "version": "16.0.3.1.0",
9
9
  "development_status": "Beta",
10
10
  "license": "AGPL-3",
11
11
  "author": "Camptocamp, BCIM, ACSONE SA/NV, Odoo Community Association (OCA)",
@@ -8,7 +8,7 @@ from collections import defaultdict
8
8
  from copy import deepcopy
9
9
  from operator import itemgetter
10
10
 
11
- from pytz import timezone
11
+ import pytz
12
12
 
13
13
  from odoo import _, api, exceptions, fields, models
14
14
  from odoo.osv.expression import NEGATIVE_TERM_OPERATORS
@@ -617,7 +617,7 @@ class StockReleaseChannel(models.Model):
617
617
  "time": safe_time,
618
618
  "datetime": safe_datetime,
619
619
  "dateutil": safe_dateutil,
620
- "timezone": timezone,
620
+ "timezone": pytz.timezone,
621
621
  # orm
622
622
  "env": self.env,
623
623
  # record
@@ -900,3 +900,82 @@ class StockReleaseChannel(models.Model):
900
900
  """Return the new date to set on move chain"""
901
901
  self.ensure_one()
902
902
  return False
903
+
904
+ def _localize(self, dt, tz=None):
905
+ """Localize a datetime
906
+
907
+ Use the given tz or use the tz of the warehouse
908
+ """
909
+ wh_tz = pytz.timezone(tz or self.warehouse_id.partner_id.tz or "UTC")
910
+ dt_tz = dt.astimezone(pytz.utc).astimezone(wh_tz)
911
+ return dt_tz
912
+
913
+ @api.model
914
+ def _naive(self, dt_tz, reset_time=False):
915
+ """Convert a datetime as naive datetime
916
+
917
+ Allow to reset time
918
+ """
919
+ if reset_time:
920
+ dt_tz = dt_tz.replace(hour=0, minute=0, second=0, microsecond=0)
921
+ dt = dt_tz.astimezone(pytz.utc).replace(tzinfo=None)
922
+ return dt
923
+
924
+ @property
925
+ def _delivery_date_steps(self):
926
+ """Returns the steps to compute the delivery date."""
927
+ return ["preparation", "delivery", "customer"]
928
+
929
+ @property
930
+ def _delivery_date_generators(self):
931
+ """Returns generators to compute delivery date.
932
+
933
+ Meant to be extended by modules to register a generator.
934
+ Returns a dict where:
935
+ - the key must be part of _delivery_date_steps.
936
+ - the value is a list of generators
937
+ """
938
+ return defaultdict(list)
939
+
940
+ def _get_earliest_delivery_date(self, partner, order_dt):
941
+ """Compute the earliest delivery date for this channel
942
+
943
+ Go through each steps. All generators of a step must agree on a date.
944
+ Initialize them with the provided start date for the first step and
945
+ then with the agreed date from the previous step. If a generator
946
+ provides a later date, send that date to the other generators to
947
+ request agreement or a new later date.
948
+ This algorithm performs a quick convergence to a date.
949
+ """
950
+ self.ensure_one()
951
+ best_dt = order_dt
952
+ for step in self._delivery_date_steps:
953
+ funcs = self._delivery_date_generators.get(step)
954
+ if not funcs:
955
+ continue
956
+ generators = []
957
+ best_generators = []
958
+ start_dt = best_dt
959
+ for func in funcs:
960
+ # initialize generators with the start date
961
+ gen = func(start_dt, partner)
962
+ generators.append(gen)
963
+ new_dt = next(gen)
964
+ if new_dt > best_dt:
965
+ best_dt = new_dt
966
+ best_generators = [gen]
967
+ elif new_dt == best_dt:
968
+ best_generators.append(gen)
969
+ # loop until all generators return the same last date
970
+ while len(generators) != len(best_generators):
971
+ for gen in generators:
972
+ if gen in best_generators:
973
+ continue
974
+ best_dt = gen.send(previous_dt := best_dt)
975
+ if best_dt != previous_dt:
976
+ best_generators = [gen]
977
+ else:
978
+ best_generators.append(gen)
979
+ for gen in generators:
980
+ gen.close()
981
+ return best_dt
@@ -367,7 +367,7 @@ ul.auto-toc {
367
367
  !! This file is generated by oca-gen-addon-readme !!
368
368
  !! changes will be overwritten. !!
369
369
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
370
- !! source digest: sha256:d3e4a6ca33a07a0967c75174dc29fa2dc7cc413f659bcd0686dd3238396bd3a8
370
+ !! source digest: sha256:2fad401dca0aa4a4f4b0e8ddcc83fd0010d54cdfe53ed66d8fc01049bdb6d273
371
371
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
372
372
  <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/wms/tree/16.0/stock_release_channel"><img alt="OCA/wms" src="https://img.shields.io/badge/github-OCA%2Fwms-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/wms-16-0/wms-16-0-stock_release_channel"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/wms&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
373
373
  <p>Release channels are:</p>
@@ -6,4 +6,5 @@ from . import (
6
6
  test_release_channel,
7
7
  test_release_channel_lifecycle,
8
8
  test_release_channel_partner,
9
+ test_release_channel_delivery_date,
9
10
  )
@@ -1,10 +1,14 @@
1
1
  # Copyright 2020 Camptocamp (https://www.camptocamp.com)
2
+ # Copyright 2025 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
2
3
  # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
3
4
 
4
5
  import logging
5
6
 
7
+ from odoo_test_helper import FakeModelLoader
8
+
6
9
  from odoo import _, fields
7
10
  from odoo.tests import common
11
+ from odoo.tests.common import TransactionCase
8
12
 
9
13
  from odoo.addons.stock_available_to_promise_release.tests.common import (
10
14
  PromiseReleaseCommonCase,
@@ -225,3 +229,22 @@ class ChannelReleaseCase(PromiseReleaseCommonCase):
225
229
  }
226
230
  },
227
231
  )
232
+
233
+
234
+ class StockReleaseChannelDeliveryDateCommon(TransactionCase):
235
+ @classmethod
236
+ def setUpClass(cls):
237
+ super().setUpClass()
238
+ cls.loader = FakeModelLoader(cls.env, cls.__module__)
239
+ cls.loader.backup_registry()
240
+ from .models.generator_test import StockReleaseChannel
241
+
242
+ cls.loader.update_registry((StockReleaseChannel,))
243
+
244
+ cls.partner = cls.env.ref("base.main_partner")
245
+ cls.channel = cls.env.ref("stock_release_channel.stock_release_channel_default")
246
+
247
+ @classmethod
248
+ def tearDownClass(cls):
249
+ cls.loader.restore_registry()
250
+ return super().tearDownClass()
@@ -0,0 +1 @@
1
+ from . import generator_test
@@ -0,0 +1,35 @@
1
+ # Copyright 2025 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
3
+
4
+ from datetime import timedelta
5
+
6
+ from odoo import models
7
+
8
+
9
+ class StockReleaseChannel(models.Model):
10
+ _inherit = "stock.release.channel"
11
+
12
+ @property
13
+ def _delivery_date_generators(self):
14
+ d = {}
15
+ d["preparation"] = [
16
+ self._next_delivery_date_one_day,
17
+ self._next_delivery_date_two_days,
18
+ ]
19
+ return d
20
+
21
+ def _next_delivery_date_one_day(self, delivery_date, partner=None):
22
+ """Get the next valid delivery date respecting transport lead time.
23
+ The delivery date must be postponed at least by the shipment lead time.
24
+ """
25
+ later = delivery_date + timedelta(days=1)
26
+ while True:
27
+ delivery_date = yield max(delivery_date, later)
28
+
29
+ def _next_delivery_date_two_days(self, delivery_date, partner=None):
30
+ """Get the next valid delivery date respecting transport lead time.
31
+ The delivery date must be postponed at least by the shipment lead time.
32
+ """
33
+ later = delivery_date + timedelta(days=2)
34
+ while True:
35
+ delivery_date = yield max(delivery_date, later)
@@ -0,0 +1,30 @@
1
+ # Copyright 2025 Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
3
+
4
+ from freezegun import freeze_time
5
+
6
+ from odoo import fields
7
+
8
+ from .common import ReleaseChannelCase, StockReleaseChannelDeliveryDateCommon
9
+
10
+ to_datetime = fields.Datetime.to_datetime
11
+
12
+
13
+ class TestReleaseChannelDeliveryDateFake(StockReleaseChannelDeliveryDateCommon):
14
+ @freeze_time("2025-01-02 10:00:00")
15
+ def test_delivery_date(self):
16
+ """Test generator on channel object"""
17
+ now = fields.Datetime.now()
18
+ dt = self.channel._get_earliest_delivery_date(self.partner, now)
19
+ self.assertEqual(dt, to_datetime("2025-01-04 10:00:00"))
20
+
21
+
22
+ class TestReleaseChannelDeliveryDate(ReleaseChannelCase):
23
+ def test_compute_delivery_date(self):
24
+ """Test delivery date computes with registered generators
25
+
26
+ This test will run with other modules loaded.
27
+ """
28
+ now = fields.Datetime.now()
29
+ partner = self.env.ref("base.main_partner")
30
+ self.default_channel._get_earliest_delivery_date(partner, now)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: odoo-addon-stock_release_channel
3
- Version: 16.0.3.0.0
3
+ Version: 16.0.3.1.0
4
4
  Summary: Manage workload in WMS with release channels
5
5
  Home-page: https://github.com/OCA/wms
6
6
  Author: Camptocamp, BCIM, ACSONE SA/NV, Odoo Community Association (OCA)
@@ -25,7 +25,7 @@ Stock Release Channels
25
25
  !! This file is generated by oca-gen-addon-readme !!
26
26
  !! changes will be overwritten. !!
27
27
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28
- !! source digest: sha256:d3e4a6ca33a07a0967c75174dc29fa2dc7cc413f659bcd0686dd3238396bd3a8
28
+ !! source digest: sha256:2fad401dca0aa4a4f4b0e8ddcc83fd0010d54cdfe53ed66d8fc01049bdb6d273
29
29
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
30
30
 
31
31
  .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
@@ -1,6 +1,6 @@
1
- odoo/addons/stock_release_channel/README.rst,sha256=HlGy6Yw_4Wi3IcfcXeimZimA2V0ccTHUbHahDfwJP7w,6403
1
+ odoo/addons/stock_release_channel/README.rst,sha256=m3qO46sD4n0uV42WJly9y_y50yPYXt_q3u0s0j37dR4,6403
2
2
  odoo/addons/stock_release_channel/__init__.py,sha256=X9EJGOE2GtZbS0G82PtSXmWSZ_R8jEM0rlJTDliQjp4,21
3
- odoo/addons/stock_release_channel/__manifest__.py,sha256=eQzfUaGnisUlOgvWPrcJ2-tb8l4cXGMW4vQkyQb2NL8,1295
3
+ odoo/addons/stock_release_channel/__manifest__.py,sha256=MsdMgUZ_jN6eZrYjTzIgnu6ghncOqR4n75jUJ9rdB_E,1295
4
4
  odoo/addons/stock_release_channel/data/ir_cron_data.xml,sha256=Fs0se4lPKelUpNvJnfEde32718SRlKCt0hEqQWQ-tQg,639
5
5
  odoo/addons/stock_release_channel/data/queue_job_data.xml,sha256=MyCGOSZNti3sgtwtco1_EBCM246w2JG8F478tczgbtA,592
6
6
  odoo/addons/stock_release_channel/demo/stock_release_channel.xml,sha256=vV4B7aykN0VNn0xxubIHikwVi0RPMhZDWcYn5BH68ck,334
@@ -15,7 +15,7 @@ odoo/addons/stock_release_channel/models/res_config_settings.py,sha256=-oh2L7FWf
15
15
  odoo/addons/stock_release_channel/models/res_partner.py,sha256=5KcUkm-aelZwBigSybqRHDTjUC3JWHH7Nc0jpiNSe1o,878
16
16
  odoo/addons/stock_release_channel/models/stock_move.py,sha256=iaPhHbzM12YtUjexaCU6MMTQcPPntJ0FJS_BX8NKRHE,1592
17
17
  odoo/addons/stock_release_channel/models/stock_picking.py,sha256=uSffxZEGJ1x1ULZ2FhaOnjXe4b3udC6WXFjpZXOMHHw,6756
18
- odoo/addons/stock_release_channel/models/stock_release_channel.py,sha256=5P2JMajuZFy5sx5uWHyBR6XibOypj-mrEvAgiRetIyw,34545
18
+ odoo/addons/stock_release_channel/models/stock_release_channel.py,sha256=gBZcLABNaCCK0UmLJ00OlReTK-HP3XwtDvvdpQ4_f7s,37520
19
19
  odoo/addons/stock_release_channel/readme/CONFIGURE.rst,sha256=foUMWWFytuVRVkV1V4uA4FvsW2I5izyrcR1CzZ6mQTI,93
20
20
  odoo/addons/stock_release_channel/readme/CONTRIBUTORS.rst,sha256=q95yj-6flBF2N4IB-vbF_p06ClGmIrCySl2bfz9ExPA,414
21
21
  odoo/addons/stock_release_channel/readme/CREDITS.rst,sha256=-JppA6kiiAVqptoc7ytAB6vOqf_0W5uJrZLh70XGE3w,50
@@ -23,23 +23,26 @@ odoo/addons/stock_release_channel/readme/DESCRIPTION.rst,sha256=LJj2UQ3g5NteOFkf
23
23
  odoo/addons/stock_release_channel/readme/USAGE.rst,sha256=uKImsGjEDoJdmYBbgXcDLcBQ8eh4wZzPE8kGfAQvyDA,1588
24
24
  odoo/addons/stock_release_channel/security/stock_release_channel.xml,sha256=U0WfLbMKR4mnNdI4mfN8e7UTxLnyd17eVNhsBy-dMSc,1471
25
25
  odoo/addons/stock_release_channel/static/description/icon.png,sha256=6xBPJauaFOF0KDHfHgQopSc28kKvxMaeoQFQWZtfZDo,9455
26
- odoo/addons/stock_release_channel/static/description/index.html,sha256=vC61d1UiRCNyy21qI9coG-RPGXVn-a3Pj07XMvSCuNc,17424
26
+ odoo/addons/stock_release_channel/static/description/index.html,sha256=PtptmFs4GRo09FIaoYcGZp-zAlWjDnd85qT5fR0i3yg,17424
27
27
  odoo/addons/stock_release_channel/static/src/js/progressbar_fractional_widget.js,sha256=sZBSmKdZSR1GFeu04iOH72h7FX5CqujgfTRmFYhh5z0,3184
28
28
  odoo/addons/stock_release_channel/static/src/scss/stock_release_channel.scss,sha256=DK0Azc8Gk3FlxeKzjZpLhRZzCQmgXdfLNmfz1CbNN0g,975
29
- odoo/addons/stock_release_channel/tests/__init__.py,sha256=kjERz9Kti9xbMmP0MgbNnnSDUdMRzZqH78VLjFn3xfk,226
30
- odoo/addons/stock_release_channel/tests/common.py,sha256=hcuHhfMv99mdp_M6tlU99nRPq9obi3gnoilgHeY1FMw,7815
29
+ odoo/addons/stock_release_channel/tests/__init__.py,sha256=GKpdQIuWCHiN-e1yatgmy07kzgmlrXm8M66uTWfUjIk,266
30
+ odoo/addons/stock_release_channel/tests/common.py,sha256=iSjs2pWNYlu-ARg4m2T4C5HU4A-wIq4BQ7hqDgyUkc8,8593
31
31
  odoo/addons/stock_release_channel/tests/test_assign_job.py,sha256=E8k9L8VPSE9Pk_xK8U9qlqYUttrYJ0iGub8MolU06fk,2847
32
32
  odoo/addons/stock_release_channel/tests/test_channel_action.py,sha256=dtaYBCAOyNGyGWpDWDAAxVUgSWXNqR-AznKAq3iOLAI,5466
33
33
  odoo/addons/stock_release_channel/tests/test_channel_computed_fields.py,sha256=TbVkrpn5Sq6nt-QRQEi2OisjkwUuvwPJ75a0V77FsM0,4725
34
34
  odoo/addons/stock_release_channel/tests/test_channel_release_batch.py,sha256=nvLf6TqcnhaA78gSpmK7Pb9unqxTm0RnY4f1QcqFlkY,2247
35
35
  odoo/addons/stock_release_channel/tests/test_release_channel.py,sha256=cY1c1DpOTb_zIF19_kZVIVZH9GZjaSa2TJeckFtDKDk,5507
36
+ odoo/addons/stock_release_channel/tests/test_release_channel_delivery_date.py,sha256=IhuXLZfNlNfvTlyp0gRXIBC9Tzj8L_ZpyuZzCGYQnCI,1079
36
37
  odoo/addons/stock_release_channel/tests/test_release_channel_lifecycle.py,sha256=hCtjqWMgLorYhdnzB8lp3ksmC3qTBrrVVtEMuifrVvE,4455
37
38
  odoo/addons/stock_release_channel/tests/test_release_channel_partner.py,sha256=jMdMJRZ1UR6z6diA-DxRmHm-AN01J0YFEa1d9KqctPk,3471
39
+ odoo/addons/stock_release_channel/tests/models/__init__.py,sha256=O2PABMBnRskr9BvR4dVDAJBQQUSH8B1Y5sVZAvWOYlQ,29
40
+ odoo/addons/stock_release_channel/tests/models/generator_test.py,sha256=ovDRsU1aPKED_17RCAUcFYvsvbUu-4A3HqM5dmwgkVU,1227
38
41
  odoo/addons/stock_release_channel/views/res_config_settings.xml,sha256=-7hoXY3H-4sNSsSgW4Z2Un2K4Y_HB07yBhnpZspECj0,1701
39
42
  odoo/addons/stock_release_channel/views/res_partner.xml,sha256=_eJwfkaXRVNSVcg62MyTg7EJjA4fxQdCujMkDylio0Q,995
40
43
  odoo/addons/stock_release_channel/views/stock_picking_views.xml,sha256=mtspBuMsNlkKoSUw3-SR16PVxIaSj7JTQ1JfvAGwG5c,2824
41
44
  odoo/addons/stock_release_channel/views/stock_release_channel_views.xml,sha256=XmTz3w6VpJ0Rxhp9HGwTPB6Y4bb5maE2hPVT-9JBZ9Y,48468
42
- odoo_addon_stock_release_channel-16.0.3.0.0.dist-info/METADATA,sha256=P07Ys9CXW8-QRfWXyG7pl577y_MrRxKpqiqdh7cDOh0,7130
43
- odoo_addon_stock_release_channel-16.0.3.0.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
44
- odoo_addon_stock_release_channel-16.0.3.0.0.dist-info/top_level.txt,sha256=qBj40grFkGOfDZ2WDSw3y1RnDlgG0u8rP8pvGNdbz4w,5
45
- odoo_addon_stock_release_channel-16.0.3.0.0.dist-info/RECORD,,
45
+ odoo_addon_stock_release_channel-16.0.3.1.0.dist-info/METADATA,sha256=Fz0BWLZFc8ziORqhMwIsrAK-pvAiJE9lCrMkfXjDd7M,7130
46
+ odoo_addon_stock_release_channel-16.0.3.1.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
47
+ odoo_addon_stock_release_channel-16.0.3.1.0.dist-info/top_level.txt,sha256=qBj40grFkGOfDZ2WDSw3y1RnDlgG0u8rP8pvGNdbz4w,5
48
+ odoo_addon_stock_release_channel-16.0.3.1.0.dist-info/RECORD,,