Skip to content
Snippets Groups Projects
account_period.py 4.78 KiB
Newer Older
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
##############################################################################
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
#    Accounting periods, for Odoo
#    Copyright (C) 2018, 2021 XCG Consulting <https://odoo.consulting/>
#
#    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/>.
#
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
##############################################################################
import datetime
from typing import Optional
from odoo import _, api, exceptions, fields, models


class AccountPeriod(models.Model):
    """Account period defined an accounting period.

    This module aims to recreate the same behaviour as the account.period model from
    previous versions of Odoo.
    _name = "account.period"
    _description = "Accounting period"
    _order = "date_start"
    code = fields.Char(
        string="Code",
        help="Unique code of this period.",
        index=True,
        required=True,
    )

    company_id = fields.Many2one(
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        related="fiscalyear_id.company_id",
        comodel_name="res.company",
        string="Company",
        help="The company the fiscal year is in.",
        readonly=True,
        store=True,
        index=True,
    date_cutoff = fields.Date(
        string="Cut-off date",
        help=(
            "Optional cut-off date which helps force transaction dates and "
            "this period for a few days after the end of this period."
    @api.depends("date_cutoff", "date_stop")
    def _get_date_effective_cutoff(self):
        for period in self:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
            period.date_effective_cutoff = period.date_cutoff or period.date_stop

    date_effective_cutoff = fields.Date(
        compute=_get_date_effective_cutoff,
        string="Effective cut-off date",
        help="The cut-off date when defined; the ending date otherwise.",
        readonly=True,
        store=True,
    )

    date_start = fields.Date(
        string="Start", help="When this period starts.", required=True
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    date_stop = fields.Date(string="End", help="When this period ends.", required=True)
    fiscalyear_id = fields.Many2one(
        comodel_name="account.fiscalyear",
        string="Fiscal year",
        help="The fiscal year this period is in.",
        ondelete="cascade",
        required=True,
    )

    name = fields.Char(
        string="Name", help="Displayed name of this period.", required=True
    state = fields.Selection(
        selection=[("draft", "Open"), ("done", "Closed")],
        string="State",
        default="draft",
        readonly=True,
        required=True,

    _sql_constraints = [
        (
            "unique_code_per_company",
            "UNIQUE(code, company_id)",
            "The code must be unique.",
        )
    def find(self, date: Optional[datetime.date] = None, create: bool = False):
        if not date:
            date = fields.Date.context_today(self)
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
        company_id = self.env.context.get("company_id") or self.env.company.id
        result = self.search(
            [
                ("date_start", "<=", date),
                ("date_stop", ">=", date),
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
                ("company_id", "=", company_id),
            ]
        )
            if create:
                self.env["account.fiscalyear"].find(date, True)
                return self.find(date, False)

            action = self.env.ref(
                "account_period.redirect_warning_account_period_action"
            )
            msg = (
                _(
                    "There is no period defined for this date: %s.\n"
                    "Please go to Configuration/Periods."
                )
            )

            raise exceptions.RedirectWarning(
                msg, action, _("Go to the configuration panel")

    @api.model
    def name_search(self, name="", args=None, operator="ilike", limit=100):
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        """Override to add company filter."""
        args = list(args or [])
Houzefa Abbasbhay's avatar
Houzefa Abbasbhay committed
        args.append(("company_id", "=", self.env.company.id))
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        return super().name_search(name=name, args=args, operator=operator, limit=limit)

    def reopen_period(self):
        """Called by a button to re-open a closed period."""

        self.ensure_one()

        self.state = "draft"