[REF] account_move_name_sequence: Add number_next_actual and date range lines data based on current moves
This commit is contained in:
parent
4aeaa9ca51
commit
d1d6874aad
@ -1,5 +1,7 @@
|
||||
# Copyright 2021 Akretion France (http://www.akretion.com/)
|
||||
# Copyright 2022 Vauxoo (https://www.vauxoo.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# @author: Moisés López <moylop260@vauxoo.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
@ -8,7 +10,7 @@
|
||||
"category": "Accounting",
|
||||
"license": "AGPL-3",
|
||||
"summary": "Generate journal entry number from sequence",
|
||||
"author": "Akretion,Odoo Community Association (OCA)",
|
||||
"author": "Akretion,Vauxoo,Odoo Community Association (OCA)",
|
||||
"maintainers": ["alexis-via"],
|
||||
"website": "https://github.com/OCA/account-financial-tools",
|
||||
"depends": ["account"],
|
||||
|
@ -1,10 +1,18 @@
|
||||
# Copyright 2021 Akretion France (http://www.akretion.com/)
|
||||
# Copyright 2022 Vauxoo (https://www.vauxoo.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# @author: Moisés López <moylop260@vauxoo.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
_inherit = "account.journal"
|
||||
@ -13,16 +21,10 @@ class AccountJournal(models.Model):
|
||||
"ir.sequence",
|
||||
string="Entry Sequence",
|
||||
copy=False,
|
||||
required=True,
|
||||
check_company=True,
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
help="This sequence will be used to generate the journal entry number.",
|
||||
)
|
||||
refund_sequence = fields.Boolean(
|
||||
string="Dedicated Credit Note Sequence",
|
||||
default=True,
|
||||
help="If enabled, you will be able to setup a sequence dedicated for refunds.",
|
||||
)
|
||||
refund_sequence_id = fields.Many2one(
|
||||
"ir.sequence",
|
||||
string="Credit Note Entry Sequence",
|
||||
@ -31,6 +33,8 @@ class AccountJournal(models.Model):
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
help="This sequence will be used to generate the journal entry number for refunds.",
|
||||
)
|
||||
# Redefine the default to True as <=v13.0
|
||||
refund_sequence = fields.Boolean(default=True)
|
||||
|
||||
@api.constrains("refund_sequence_id", "sequence_id")
|
||||
def _check_journal_sequence(self):
|
||||
@ -95,3 +99,145 @@ class AccountJournal(models.Model):
|
||||
def _create_sequence(self, vals, refund=False):
|
||||
seq_vals = self._prepare_sequence(vals, refund=refund)
|
||||
return self.env["ir.sequence"].sudo().create(seq_vals)
|
||||
|
||||
def _prepare_sequence_current_moves(self, refund=False):
|
||||
"""Get sequence dict values the journal based on current moves"""
|
||||
self.ensure_one()
|
||||
move_domain = [
|
||||
("journal_id", "=", self.id),
|
||||
("name", "!=", "/"),
|
||||
]
|
||||
if self.refund_sequence:
|
||||
# Based on original Odoo behavior
|
||||
if refund:
|
||||
move_domain.append(("move_type", "in", ("out_refund", "in_refund")))
|
||||
else:
|
||||
move_domain.append(("move_type", "not in", ("out_refund", "in_refund")))
|
||||
last_move = self.env["account.move"].search(
|
||||
move_domain, limit=1, order="id DESC"
|
||||
)
|
||||
msg_err = (
|
||||
"Journal %s could not get sequence %s values based on current moves. "
|
||||
"Using default values." % (self.id, refund and "refund" or "")
|
||||
)
|
||||
if not last_move:
|
||||
_logger.warning("%s %s", msg_err, "No moves found")
|
||||
return {}
|
||||
try:
|
||||
with self.env.cr.savepoint():
|
||||
# get the current sequence values could be buggy to get
|
||||
# But even we can use the default values
|
||||
# or do manual changes instead of raising errors
|
||||
last_sequence = last_move._get_last_sequence()
|
||||
if not last_sequence:
|
||||
last_sequence = (
|
||||
last_move._get_last_sequence(relaxed=True)
|
||||
or last_move._get_starting_sequence()
|
||||
)
|
||||
|
||||
__, seq_format_values = last_move._get_sequence_format_param(
|
||||
last_sequence
|
||||
)
|
||||
prefix1 = seq_format_values["prefix1"]
|
||||
prefix = prefix1
|
||||
if seq_format_values["year_length"] == 4:
|
||||
prefix += "%(range_year)s"
|
||||
elif seq_format_values["year_length"] == 2:
|
||||
prefix += "%(range_y)s"
|
||||
else:
|
||||
# If there is not year so current values are valid
|
||||
seq_vals = {
|
||||
"padding": seq_format_values["seq_length"],
|
||||
"suffix": seq_format_values["suffix"],
|
||||
"prefix": prefix,
|
||||
"date_range_ids": [],
|
||||
"use_date_range": False,
|
||||
"number_next_actual": seq_format_values["seq"] + 1,
|
||||
}
|
||||
return seq_vals
|
||||
prefix2 = seq_format_values.get("prefix2") or ""
|
||||
prefix += prefix2
|
||||
month = seq_format_values.get("month") # It is 0 if only have year
|
||||
if month:
|
||||
prefix += "%(range_month)s"
|
||||
prefix3 = seq_format_values.get("prefix3") or ""
|
||||
where_name_value = "%s%s%s%s%s%%" % (
|
||||
prefix1,
|
||||
"_" * seq_format_values["year_length"],
|
||||
prefix2,
|
||||
"_" * bool(month) * 2,
|
||||
prefix3,
|
||||
)
|
||||
prefixes = prefix1 + prefix2
|
||||
select_year = (
|
||||
"split_part(name, '%s', %d)" % (prefix2, prefixes.count(prefix2))
|
||||
if prefix2
|
||||
else "''"
|
||||
)
|
||||
prefixes += prefix3
|
||||
select_month = (
|
||||
"split_part(name, '%s', %d)" % (prefix3, prefixes.count(prefix3))
|
||||
if prefix3
|
||||
else "''"
|
||||
)
|
||||
select_max_number = (
|
||||
"MAX(split_part(name, '%s', %d)::INTEGER) AS max_number"
|
||||
% (prefixes[-1], prefixes.count(prefixes[-1]) + 1)
|
||||
)
|
||||
query = (
|
||||
"SELECT %s, %s, %s FROM account_move "
|
||||
"WHERE name LIKE %%s AND journal_id=%%s GROUP BY 1,2"
|
||||
) % (
|
||||
select_year,
|
||||
select_month,
|
||||
select_max_number,
|
||||
)
|
||||
# It is not using user input
|
||||
# pylint: disable=sql-injection
|
||||
self.env.cr.execute(query, (where_name_value, self.id))
|
||||
res = self.env.cr.fetchall()
|
||||
prefix += prefix3
|
||||
seq_vals = {
|
||||
"padding": seq_format_values["seq_length"],
|
||||
"suffix": seq_format_values["suffix"],
|
||||
"prefix": prefix,
|
||||
"date_range_ids": [],
|
||||
"use_date_range": True,
|
||||
}
|
||||
for year, month, max_number in res:
|
||||
if not year and not month:
|
||||
seq_vals.update(
|
||||
{
|
||||
"use_date_range": False,
|
||||
"number_next_actual": max_number + 1,
|
||||
}
|
||||
)
|
||||
continue
|
||||
if len(year) == 2:
|
||||
# Year >=50 will be considered as last century 1950
|
||||
# Year <=49 will be considered as current century 2049
|
||||
if int(year) >= 50:
|
||||
year = "19" + year
|
||||
else:
|
||||
year = "20" + year
|
||||
if month:
|
||||
date_from = fields.Date.to_date("%s-%s-1" % (year, month))
|
||||
date_to = date_from + relativedelta(day=31)
|
||||
else:
|
||||
date_from = fields.Date.to_date("%s-1-1" % year)
|
||||
date_to = fields.Date.to_date("%s-12-31" % year)
|
||||
seq_vals["date_range_ids"].append(
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"date_from": date_from,
|
||||
"date_to": date_to,
|
||||
"number_next_actual": max_number + 1,
|
||||
},
|
||||
)
|
||||
)
|
||||
return seq_vals
|
||||
except Exception as e:
|
||||
_logger.warning("%s %s", msg_err, e)
|
||||
return {}
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Copyright 2021 Akretion France (http://www.akretion.com/)
|
||||
# Copyright 2022 Vauxoo (https://www.vauxoo.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# @author: Moisés López <moylop260@vauxoo.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import SUPERUSER_ID, api
|
||||
@ -10,16 +12,17 @@ def create_journal_sequences(cr, registry):
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
journals = env["account.journal"].with_context(active_test=False).search([])
|
||||
for journal in journals:
|
||||
vals = {}
|
||||
journal_vals = {
|
||||
"code": journal.code,
|
||||
"name": journal.name,
|
||||
"company_id": journal.company_id.id,
|
||||
}
|
||||
seq_vals = journal._prepare_sequence(journal_vals)
|
||||
vals["sequence_id"] = env["ir.sequence"].create(seq_vals).id
|
||||
seq_vals.update(journal._prepare_sequence_current_moves())
|
||||
vals = {"sequence_id": env["ir.sequence"].create(seq_vals).id}
|
||||
if journal.type in ("sale", "purchase") and journal.refund_sequence:
|
||||
rseq_vals = journal._prepare_sequence(journal_vals, refund=True)
|
||||
rseq_vals.update(journal._prepare_sequence_current_moves(refund=True))
|
||||
vals["refund_sequence_id"] = env["ir.sequence"].create(rseq_vals).id
|
||||
journal.write(vals)
|
||||
return
|
||||
|
@ -1 +1,2 @@
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* Moisés López <moylop260@vauxoo.com>
|
||||
|
@ -14,14 +14,15 @@
|
||||
<field
|
||||
name="sequence_id"
|
||||
required="0"
|
||||
context="{'default_name': name, 'default_company_id': company_id, 'default_implementation': 'no_gap', 'default_padding': 4, 'default_use_date_range': True, 'default_prefix': code + '/%%(range_year)s/'}"
|
||||
context="{'default_name': name, 'default_company_id': company_id, 'default_implementation': 'no_gap', 'default_padding': 4, 'default_use_date_range': True, 'default_prefix': (code or 'UNKNOWN') + '/%%(range_year)s/'}"
|
||||
/>
|
||||
</field>
|
||||
<field name="refund_sequence" position="after">
|
||||
<field
|
||||
name="refund_sequence_id"
|
||||
attrs="{'invisible': ['|', ('type', 'not in', ('sale', 'purchase')), ('refund_sequence', '=', False)]}"
|
||||
context="{'default_name': name, 'default_company_id': company_id, 'default_implementation': 'no_gap', 'default_padding': 4, 'default_use_date_range': True, 'default_prefix': 'R' + code + '/%%(range_year)s/'}"
|
||||
required="1"
|
||||
context="{'default_name': name, 'default_company_id': company_id, 'default_implementation': 'no_gap', 'default_padding': 4, 'default_use_date_range': True, 'default_prefix': 'R' + (code or 'UNKNOWN') + '/%%(range_year)s/'}"
|
||||
/>
|
||||
</field>
|
||||
</field>
|
||||
|
Loading…
Reference in New Issue
Block a user