2021-04-05 16:27:30 +02:00
|
|
|
# Copyright 2015-2019 ACSONE SA/NV (<http://acsone.eu>)
|
|
|
|
# Copyright 2021 CorporateHub (https://corporatehub.eu)
|
|
|
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
|
|
|
|
|
|
|
from odoo import _, models
|
|
|
|
from odoo.exceptions import UserError
|
|
|
|
from odoo.osv import expression
|
|
|
|
from odoo.tools.misc import format_date
|
|
|
|
|
|
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
|
|
_inherit = "account.move"
|
|
|
|
|
|
|
|
def _get_conflicting_invoices_domain(self):
|
|
|
|
self.ensure_one()
|
|
|
|
domain = [
|
|
|
|
("journal_id", "=", self.journal_id.id),
|
2021-04-06 20:41:36 +02:00
|
|
|
("move_type", "!=", "entry"),
|
2021-04-05 16:27:30 +02:00
|
|
|
]
|
2021-04-06 20:41:36 +02:00
|
|
|
if self.journal_id.refund_sequence:
|
|
|
|
domain.append(("move_type", "=", self.move_type))
|
2021-04-05 16:27:30 +02:00
|
|
|
return domain
|
|
|
|
|
|
|
|
def _get_older_conflicting_invoices_domain(self):
|
|
|
|
self.ensure_one()
|
|
|
|
return expression.AND(
|
|
|
|
[
|
|
|
|
self._get_conflicting_invoices_domain(),
|
|
|
|
[
|
|
|
|
("state", "=", "draft"),
|
|
|
|
("invoice_date", "!=", False),
|
|
|
|
("invoice_date", "<", self.invoice_date),
|
|
|
|
],
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
def _raise_older_conflicting_invoices(self):
|
|
|
|
self.ensure_one()
|
|
|
|
raise UserError(
|
|
|
|
_(
|
|
|
|
"Chronology conflict: A conflicting draft invoice dated before "
|
|
|
|
"{date_invoice} exists, please validate it first."
|
|
|
|
).format(date_invoice=format_date(self.env, self.invoice_date))
|
|
|
|
)
|
|
|
|
|
|
|
|
def _get_newer_conflicting_invoices_domain(self):
|
|
|
|
self.ensure_one()
|
|
|
|
return expression.AND(
|
|
|
|
[
|
|
|
|
self._get_conflicting_invoices_domain(),
|
|
|
|
[("state", "=", "posted"), ("invoice_date", ">", self.invoice_date)],
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
def _raise_newer_conflicting_invoices(self):
|
|
|
|
self.ensure_one()
|
|
|
|
raise UserError(
|
|
|
|
_(
|
|
|
|
"Chronology conflict: A conflicting validated invoice dated after "
|
|
|
|
"{date_invoice} exists."
|
|
|
|
).format(date_invoice=format_date(self.env, self.invoice_date))
|
|
|
|
)
|
|
|
|
|
2021-04-08 07:41:03 +02:00
|
|
|
def _get_sequence_order_conflicting_invoices_domain(self):
|
|
|
|
self.ensure_one()
|
|
|
|
|
|
|
|
if not self.name or self.name == "/":
|
|
|
|
return expression.FALSE_DOMAIN
|
|
|
|
|
|
|
|
last_sequence = self._get_last_sequence()
|
|
|
|
if not last_sequence or self.name > last_sequence:
|
|
|
|
return expression.FALSE_DOMAIN
|
|
|
|
|
|
|
|
return expression.AND(
|
|
|
|
[
|
|
|
|
[("name", "=", last_sequence)],
|
|
|
|
self._get_conflicting_invoices_domain(),
|
|
|
|
[("state", "=", "posted"), ("invoice_date", "<", self.invoice_date)],
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
def _raise_sequence_ordering_conflict(self):
|
|
|
|
self.ensure_one()
|
|
|
|
raise UserError(
|
|
|
|
_(
|
|
|
|
"Chronology conflict: An invoice with a higher number {highest_name}"
|
|
|
|
" dated before {date_invoice} exists."
|
|
|
|
).format(
|
|
|
|
highest_name=self._get_last_sequence(),
|
|
|
|
date_invoice=format_date(self.env, self.invoice_date),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2023-06-15 14:45:29 +02:00
|
|
|
def _conflicting_inv_after_sequence_before_inv_date_domain(self):
|
|
|
|
return expression.AND(
|
|
|
|
[
|
|
|
|
(
|
|
|
|
("name", ">", self.name),
|
|
|
|
("invoice_date", "<", self.invoice_date),
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
def _conflicting_inv_before_sequence_after_inv_date_domain(self):
|
|
|
|
return expression.AND(
|
|
|
|
[
|
|
|
|
(
|
|
|
|
("name", "<", self.name),
|
|
|
|
("invoice_date", ">", self.invoice_date),
|
|
|
|
)
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
def _get_sequence_order_conflicting_previously_validated(self):
|
|
|
|
self.ensure_one()
|
|
|
|
return expression.AND(
|
|
|
|
[
|
|
|
|
self._get_conflicting_invoices_domain(),
|
|
|
|
expression.OR(
|
|
|
|
[
|
|
|
|
self._conflicting_inv_after_sequence_before_inv_date_domain(),
|
|
|
|
self._conflicting_inv_before_sequence_after_inv_date_domain(),
|
|
|
|
]
|
|
|
|
),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
def _raise_sequence_order_conflicting_previously_validated(self):
|
|
|
|
self.ensure_one()
|
|
|
|
before_inv = self.search(
|
|
|
|
self._conflicting_inv_after_sequence_before_inv_date_domain(), limit=1
|
|
|
|
)
|
|
|
|
after_inv = self.search(
|
|
|
|
self._conflicting_inv_before_sequence_after_inv_date_domain(), limit=1
|
|
|
|
)
|
|
|
|
if after_inv:
|
|
|
|
time = "before"
|
|
|
|
else:
|
|
|
|
time = "after"
|
|
|
|
raise UserError(
|
|
|
|
_(
|
|
|
|
"Chronology conflict: Invoice {name} cannot be {time} "
|
|
|
|
"invoice {inv_name}."
|
|
|
|
).format(
|
|
|
|
name=self.name,
|
|
|
|
time=time,
|
|
|
|
inv_name=after_inv.name if after_inv else before_inv.name,
|
|
|
|
date_invoice=format_date(self.env, self.invoice_date),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2021-04-05 16:27:30 +02:00
|
|
|
def write(self, vals):
|
|
|
|
if vals.get("state") != "posted":
|
|
|
|
return super().write(vals)
|
2022-02-17 10:26:39 +01:00
|
|
|
previously_validated = self.filtered(lambda m: m.name and m.name != "/")
|
2021-04-05 16:27:30 +02:00
|
|
|
newly_posted = self.filtered(lambda move: move.state != "posted")
|
|
|
|
res = super().write(vals)
|
|
|
|
for move in newly_posted & self.filtered("journal_id.check_chronology"):
|
2021-04-08 07:41:03 +02:00
|
|
|
if self.search(
|
|
|
|
move._get_sequence_order_conflicting_invoices_domain(), limit=1
|
|
|
|
):
|
|
|
|
move._raise_sequence_ordering_conflict()
|
2021-04-05 16:27:30 +02:00
|
|
|
if self.search(move._get_older_conflicting_invoices_domain(), limit=1):
|
|
|
|
move._raise_older_conflicting_invoices()
|
2022-02-17 10:26:39 +01:00
|
|
|
if move in previously_validated:
|
2023-06-15 14:45:29 +02:00
|
|
|
if self.search(
|
|
|
|
move._get_sequence_order_conflicting_previously_validated(), limit=1
|
|
|
|
):
|
|
|
|
move._raise_sequence_order_conflicting_previously_validated()
|
2022-02-17 10:26:39 +01:00
|
|
|
continue
|
2021-04-05 16:27:30 +02:00
|
|
|
if self.search(move._get_newer_conflicting_invoices_domain(), limit=1):
|
|
|
|
move._raise_newer_conflicting_invoices()
|
|
|
|
|
|
|
|
return res
|