Skip to content
Snippets Groups Projects
account_move.py 5.1 KiB
Newer Older
##############################################################################
#
#    Accounting periods, for Odoo
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
#    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/>.
#
##############################################################################
arthur.mayer's avatar
arthur.mayer committed
from odoo import _, exceptions, fields, models, tools

class AccountMove(models.Model):
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    """Add a period & dates onto accounting documents."""
    _inherit = "account.move"

    period_id = fields.Many2one(
        comodel_name="account.period",
        string="Period",
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
        ondelete="restrict",
        help="The period this accounting document is in.",
        states={"posted": [("readonly", True), ("required", True)]},
arthur.mayer's avatar
arthur.mayer committed
    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()

        for accdoc in self:
arthur.mayer's avatar
arthur.mayer committed
            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")],
                # Create missing periods on-the-fly when running tests / DB populate.
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
                    tools.config["test_enable"]
                    or tools.config["test_file"]
                    or self.env.context.get("install_demo", False)
                    or hasattr(self.env.registry, "populated_models")
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
                ) and (
                    not self.env.context.get("period_close_enable")
                    or not self.env["account.period"].search(
                        period_domain + [("state", "=", "done")],
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
                        limit=1,
arthur.mayer's avatar
arthur.mayer committed
                ):
                    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,
                        )
                    )
arthur.mayer's avatar
arthur.mayer committed
                    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),
arthur.mayer's avatar
arthur.mayer committed
                                }
                            )
                        )
                        fiscalyear.create_periods()
                    period = self.env["account.period"].search(
                        period_domain + [("state", "!=", "done")],
                        limit=1,
                    )
arthur.mayer's avatar
arthur.mayer committed

                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.
            if accdoc.journal_id.type == "sale":
arthur.mayer's avatar
arthur.mayer committed
                period_end = period.date_end
                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)