# HG changeset patch
# User Arthur MAYER <arthur.mayer@xcg-consulting.fr>
# Date 1691052067 -7200
#      Thu Aug 03 10:41:07 2023 +0200
# Branch 16.0
# Node ID 639f810c23f63f1526b46bf5b538d2e47bdd4018
# Parent  ca3104ce09509fea04d3b4d52dbbb4e22a7bae54
Add find() method needed by other modules

diff --git a/NEWS.rst b/NEWS.rst
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -2,6 +2,11 @@
 Changelog
 =========
 
+16.0.1.2.0
+----------
+
+Add ``find(date)`` method
+
 16.0.1.1.0
 ----------
 
diff --git a/__manifest__.py b/__manifest__.py
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -22,7 +22,7 @@
     "name": "Accounting Periods",
     "license": "AGPL-3",
     "summary": "Add period accounting concept",
-    "version": "16.0.1.1.0",
+    "version": "16.0.1.2.0",
     "category": "Accounting/Accounting",
     "author": "XCG Consulting",
     "website": "https://orbeet.io/",
diff --git a/models/account_move.py b/models/account_move.py
--- a/models/account_move.py
+++ b/models/account_move.py
@@ -18,7 +18,7 @@
 #
 ##############################################################################
 
-from odoo import _, exceptions, fields, models, tools
+from odoo import fields, models
 
 
 class AccountMove(models.Model):
@@ -46,70 +46,7 @@
 
         for accdoc in self:
             acc_date = accdoc.date or today
-            company = accdoc.company_id
-            period_domain = [
-                ("company_id", "=", company.id),
-                ("date_start", "<=", acc_date),
-                ("date_effective_cutoff", ">=", acc_date),
-            ]
-
-            # Periods are ordered by date so selecting the first one is fine.
-            period = self.env["account.period"].search(
-                period_domain + [("state", "!=", "done")],
-                limit=1,
-            )
-            if not period:
-                # Create missing periods on-the-fly when running tests / DB populate.
-                if (
-                    tools.config["test_enable"]
-                    or tools.config["test_file"]
-                    or self.env.context.get("install_demo", False)
-                    or hasattr(self.env.registry, "populated_models")
-                ) and (
-                    not self.env.context.get("period_close_enable")
-                    or not self.env["account.period"].search(
-                        period_domain + [("state", "=", "done")],
-                        limit=1,
-                    )
-                ):
-                    year_start = acc_date.replace(day=1, month=1)
-                    year_end = acc_date.replace(day=31, month=12)
-                    fiscalyear = (
-                        self.env["account.fiscal.year"]
-                        .sudo()
-                        .search(
-                            [
-                                ("company_id", "=", company.id),
-                                ("date_from", "<=", year_start),
-                                ("date_to", ">=", year_end),
-                            ],
-                            limit=1,
-                        )
-                    )
-                    if not fiscalyear:
-                        fiscalyear = (
-                            self.env["account.fiscal.year"]
-                            .sudo()
-                            .create(
-                                {
-                                    "company_id": company.id,
-                                    "date_from": year_start,
-                                    "date_to": year_end,
-                                    "name": str(acc_date.year),
-                                }
-                            )
-                        )
-                        fiscalyear.create_periods()
-                    period = self.env["account.period"].search(
-                        period_domain + [("state", "!=", "done")],
-                        limit=1,
-                    )
-
-                else:
-                    raise exceptions.UserError(
-                        _("No period found around %(date)s in the company %(name)s.")
-                        % {"date": acc_date, "name": company.sudo().name}
-                    )
+            period = self.env["account.period"].find(date=acc_date)
 
             # When we are between the period end and cut-off date, force the
             # last day of the period.
diff --git a/models/account_period.py b/models/account_period.py
--- a/models/account_period.py
+++ b/models/account_period.py
@@ -17,7 +17,7 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 ##############################################################################
-from odoo import api, fields, models
+from odoo import _, api, exceptions, fields, models, tools
 
 
 class AccountPeriod(models.Model):
@@ -89,3 +89,73 @@
         res = super().unlink()
         date_range_record.unlink()
         return res
+
+    def find(self, date=None):
+        if not date:
+            date = fields.Date.context_today(self)
+
+        company = self.env.company
+        domain = [
+            ("company_id", "=", company.id),
+            ("date_start", "<=", date),
+            ("date_effective_cutoff", ">=", date),
+        ]
+        period = self.search(
+            domain + [("state", "!=", "done")],
+            limit=1,
+        )
+
+        if not period:
+            # Create missing periods on-the-fly when running tests / DB populate.
+            if (
+                tools.config["test_enable"]
+                or tools.config["test_file"]
+                or self.env.context.get("install_demo", False)
+                or hasattr(self.env.registry, "populated_models")
+            ) and (
+                not self.env.context.get("period_close_enable")
+                or not self.env["account.period"].search(
+                    domain + [("state", "=", "done")],
+                    limit=1,
+                )
+            ):
+                year_start = date.replace(day=1, month=1)
+                year_end = date.replace(day=31, month=12)
+                fiscalyear = (
+                    self.env["account.fiscal.year"]
+                    .sudo()
+                    .search(
+                        [
+                            ("company_id", "=", company.id),
+                            ("date_from", "<=", year_start),
+                            ("date_to", ">=", year_end),
+                        ],
+                        limit=1,
+                    )
+                )
+                if not fiscalyear:
+                    fiscalyear = (
+                        self.env["account.fiscal.year"]
+                        .sudo()
+                        .create(
+                            {
+                                "company_id": company.id,
+                                "date_from": year_start,
+                                "date_to": year_end,
+                                "name": str(date.year),
+                            }
+                        )
+                    )
+                    fiscalyear.create_periods()
+                period = self.env["account.period"].search(
+                    domain + [("state", "!=", "done")],
+                    limit=1,
+                )
+
+            else:
+                raise exceptions.UserError(
+                    _("No period found around %(date)s in the company %(name)s.")
+                    % {"date": date, "name": company.sudo().name}
+                )
+
+        return period
diff --git a/tests/test_account_period.py b/tests/test_account_period.py
--- a/tests/test_account_period.py
+++ b/tests/test_account_period.py
@@ -18,9 +18,11 @@
 #
 ##############################################################################
 
+import datetime
+
 from freezegun import freeze_time
 
-from odoo import exceptions, fields, models
+from odoo import exceptions, fields
 from odoo.tests import tagged
 
 from odoo.addons.account.tests.common import AccountTestInvoicingCommon
@@ -45,12 +47,14 @@
 
         cls.env = cls.env(context=dict(cls.env.context, period_close_enable=True))
 
+        cls.Period = cls.env["account.period"]
+
     def test_001_invoice_dates_with_periods(self):
         """Check invoice date corresponding to periods."""
 
         # Dates & period around today.
         year = fields.Date.from_string(self.today).year
-        period_today = self._get_period(pivot_date=self.today)
+        period_today = self.Period.find(date=self.today)
 
         # Control: Default dates & period around today.
         accdoc = self._make_invoice(company=period_today.company_id)
@@ -62,7 +66,7 @@
 
         # Force a date on the invoice; ensure period selection follows it.
         date_2017 = self.today.replace(year=2017)
-        period_2017 = self._get_period(pivot_date=date_2017)
+        period_2017 = self.Period.find(date=date_2017)
         accdoc_2017 = self._make_invoice(
             invoice_date=date_2017, company=period_2017.company_id
         )
@@ -86,7 +90,7 @@
         """Check the "Close period" dialog box."""
 
         # Find the period around today. We should have one in demo data.
-        period_today = self._get_period()
+        period_today = self.Period.find()
 
         self.assertEqual(period_today.state, "draft")
 
@@ -118,26 +122,6 @@
             }
         )
 
-    def _get_period(self, pivot_date=None) -> models.Model:
-        """Find the period around the specified date (defaults to today).
-
-        :return: The period, an Odoo "account.period" record set.
-        """
-
-        if pivot_date is None:
-            pivot_date = self.today
-
-        period = self.env["account.period"].search(
-            [
-                ("company_id", "=", self.env.company.id),
-                ("date_start", "<=", pivot_date),
-                ("date_end", ">=", pivot_date),
-                ("state", "=", "draft"),
-            ]
-        )
-        self.assertEqual(len(period), 1)
-        return period
-
     def _make_invoice(self, amount=None, invoice_date=None, post=False, company=None):
         return self.init_invoice(
             "out_invoice",
@@ -180,3 +164,18 @@
         self.assertFalse(date_ranges)
         self.assertEqual(len(periods), 0)
         self.assertEqual(len(date_ranges), 0)
+
+    def test_005_find_period(self):
+        # Today
+        date_today = datetime.date.today()
+        period_today_str = self.Period.find().name
+        period_today_date = datetime.datetime.strptime(period_today_str, "%Y/%m").date()
+        self.assertEqual(period_today_date.month, date_today.month)
+        self.assertEqual(period_today_date.year, date_today.year)
+
+        # 2017/02
+        date_2017 = datetime.date(2017, 2, 1)
+        period_2017_str = self.Period.find(date_2017).name
+        period_2017_date = datetime.datetime.strptime(period_2017_str, "%Y/%m").date()
+        self.assertEqual(period_2017_date.month, date_2017.month)
+        self.assertEqual(period_2017_date.year, date_2017.year)