Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
4
account_fiscal_year/models/__init__.py
Executable file
4
account_fiscal_year/models/__init__.py
Executable file
@@ -0,0 +1,4 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import account_fiscal_year
|
||||
from . import res_company
|
||||
123
account_fiscal_year/models/account_fiscal_year.py
Executable file
123
account_fiscal_year/models/account_fiscal_year.py
Executable file
@@ -0,0 +1,123 @@
|
||||
# Copyright 2020 Simone Rubino - Agile Business Group
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class AccountFiscalYear(models.Model):
|
||||
_name = "account.fiscal.year"
|
||||
_description = "Fiscal Year"
|
||||
|
||||
name = fields.Char(
|
||||
required=True,
|
||||
)
|
||||
date_from = fields.Date(
|
||||
string="Start Date",
|
||||
required=True,
|
||||
help="Start Date, included in the fiscal year.",
|
||||
)
|
||||
date_to = fields.Date(
|
||||
string="End Date",
|
||||
required=True,
|
||||
help="Ending Date, included in the fiscal year.",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
string="Company",
|
||||
required=True,
|
||||
default=lambda self: self.env.company,
|
||||
)
|
||||
|
||||
@api.constrains("date_from", "date_to", "company_id")
|
||||
def _check_dates(self):
|
||||
"""Check intersection with existing fiscal years."""
|
||||
for fy in self:
|
||||
# Starting date must be prior to the ending date
|
||||
date_from = fy.date_from
|
||||
date_to = fy.date_to
|
||||
if date_to < date_from:
|
||||
raise ValidationError(
|
||||
_("The ending date must not be prior to the starting date.")
|
||||
)
|
||||
|
||||
domain = fy._get_overlapping_domain()
|
||||
overlapping_fy = self.search(domain, limit=1)
|
||||
if overlapping_fy:
|
||||
raise ValidationError(
|
||||
_(
|
||||
"This fiscal year '{fy}' "
|
||||
"overlaps with '{overlapping_fy}'.\n"
|
||||
"Please correct the start and/or end dates "
|
||||
"of your fiscal years."
|
||||
).format(
|
||||
fy=fy.display_name,
|
||||
overlapping_fy=overlapping_fy.display_name,
|
||||
)
|
||||
)
|
||||
|
||||
def _get_overlapping_domain(self):
|
||||
"""Get domain for finding fiscal years overlapping with self.
|
||||
|
||||
The domain will search only among fiscal years of this company.
|
||||
"""
|
||||
self.ensure_one()
|
||||
# Compare with other fiscal years defined for this company
|
||||
company_domain = [
|
||||
("id", "!=", self.id),
|
||||
("company_id", "=", self.company_id.id),
|
||||
]
|
||||
|
||||
date_from = self.date_from
|
||||
date_to = self.date_to
|
||||
# Search fiscal years intersecting with current fiscal year.
|
||||
# This fiscal year's `from` is contained in another fiscal year
|
||||
# other.from <= fy.from <= other.to
|
||||
intersection_domain_from = [
|
||||
"&",
|
||||
("date_from", "<=", date_from),
|
||||
("date_to", ">=", date_from),
|
||||
]
|
||||
# This fiscal year's `to` is contained in another fiscal year
|
||||
# other.from <= fy.to <= other.to
|
||||
intersection_domain_to = [
|
||||
"&",
|
||||
("date_from", "<=", date_to),
|
||||
("date_to", ">=", date_to),
|
||||
]
|
||||
# This fiscal year completely contains another fiscal year
|
||||
# fy.from <= other.from (or other.to) <= fy.to
|
||||
intersection_domain_contain = [
|
||||
"&",
|
||||
("date_from", ">=", date_from),
|
||||
("date_from", "<=", date_to),
|
||||
]
|
||||
intersection_domain = expression.OR(
|
||||
[
|
||||
intersection_domain_from,
|
||||
intersection_domain_to,
|
||||
intersection_domain_contain,
|
||||
]
|
||||
)
|
||||
|
||||
return expression.AND(
|
||||
[
|
||||
company_domain,
|
||||
intersection_domain,
|
||||
]
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _get_fiscal_year(self, company, date_from, date_to):
|
||||
"""Return a fiscal year for the given company
|
||||
that contains the two dates. (or False if no fiscal years)
|
||||
matches the selection"""
|
||||
return self.search(
|
||||
[
|
||||
("company_id", "=", company.id),
|
||||
("date_from", "<=", date_from),
|
||||
("date_to", ">=", date_to),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
84
account_fiscal_year/models/res_company.py
Executable file
84
account_fiscal_year/models/res_company.py
Executable file
@@ -0,0 +1,84 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import fields, models
|
||||
from odoo.tools import date_utils
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
fiscal_year_date_from = fields.Date(
|
||||
string="Start Date of the Fiscal Year",
|
||||
compute="_compute_fiscal_year_dates",
|
||||
compute_sudo=True,
|
||||
)
|
||||
|
||||
fiscal_year_date_to = fields.Date(
|
||||
string="End Date of the Fiscal Year",
|
||||
compute="_compute_fiscal_year_dates",
|
||||
compute_sudo=True,
|
||||
)
|
||||
|
||||
def _compute_fiscal_year_dates(self):
|
||||
today = fields.Date.today()
|
||||
for company in self:
|
||||
res = company.compute_fiscalyear_dates(today)
|
||||
company.fiscal_year_date_from = res["date_from"]
|
||||
company.fiscal_year_date_to = res["date_to"]
|
||||
|
||||
def compute_fiscalyear_dates(self, current_date):
|
||||
"""Computes the start and end dates of the fiscal year
|
||||
where the given 'date' belongs to.
|
||||
|
||||
:param current_date: A datetime.date/datetime.datetime object.
|
||||
:return: A dictionary containing:
|
||||
* date_from
|
||||
* date_to
|
||||
* [Optionally] record: The fiscal year record.
|
||||
"""
|
||||
self.ensure_one()
|
||||
|
||||
AccountFiscalYear = self.env["account.fiscal.year"]
|
||||
|
||||
# Search a fiscal year record containing the date.
|
||||
fiscalyear = AccountFiscalYear._get_fiscal_year(
|
||||
self, current_date, current_date
|
||||
)
|
||||
|
||||
if fiscalyear:
|
||||
return {
|
||||
"date_from": fiscalyear.date_from,
|
||||
"date_to": fiscalyear.date_to,
|
||||
"record": fiscalyear,
|
||||
}
|
||||
|
||||
date_from, date_to = date_utils.get_fiscal_year(
|
||||
current_date,
|
||||
day=self.fiscalyear_last_day,
|
||||
month=int(self.fiscalyear_last_month),
|
||||
)
|
||||
|
||||
# Search for fiscal year records reducing
|
||||
# the delta between the date_from/date_to.
|
||||
# This case could happen if there is a gap
|
||||
# between two fiscal year records.
|
||||
# E.g. two fiscal year records:
|
||||
# 2017-01-01 -> 2017-02-01 and 2017-03-01 -> 2017-12-31.
|
||||
# =>
|
||||
# The period 2017-02-02 - 2017-02-30 is not covered by a fiscal year record.
|
||||
|
||||
fiscalyear_from = AccountFiscalYear._get_fiscal_year(self, date_from, date_from)
|
||||
|
||||
if fiscalyear_from:
|
||||
date_from = fiscalyear_from.date_to + timedelta(days=1)
|
||||
|
||||
fiscalyear_to = AccountFiscalYear._get_fiscal_year(self, date_to, date_to)
|
||||
|
||||
if fiscalyear_to:
|
||||
date_to = fiscalyear_to.date_from - timedelta(days=1)
|
||||
|
||||
return {
|
||||
"date_from": date_from,
|
||||
"date_to": date_to,
|
||||
}
|
||||
Reference in New Issue
Block a user