Newer
Older
##############################################################################
#
# Accounting periods, for Odoo
# Copyright © 2018, 2022, 2023 XCG Consulting <https://xcg-consulting.fr/>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import _, exceptions, fields, models, tools
class AccountMove(models.Model):
"""Add a period & dates onto accounting documents."""
comodel_name="account.period",
string="Period",
help="The period this accounting document is in.",
states={"posted": [("readonly", True), ("required", True)]},
def action_post(self):
"""Override accounting document validation to fill period."""
self.fill_period()
return super().action_post()
def fill_period(self):
"""Find an open period around move date, set it onto that move."""
today = fields.Date.today()
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.
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")],
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),
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}
)
# When we are between the period end and cut-off date, force the
# last day of the period.
in_cutoff = False
if accdoc.journal_id.type == "sale":
in_cutoff = acc_date > period_end
acc_date = period_end if in_cutoff else acc_date
# The data to update the accounting document with.
accdoc_values = {
"period_id": period.id,
}
# Ready! Update the accounting document.
accdoc.write(accdoc_values)