mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
[MIG] account_move_name_sequence: Migration to 17.0
This commit is contained in:
committed by
Marcos Oitaben
parent
e8b3d2ed97
commit
d95f747d39
@@ -7,7 +7,7 @@
|
||||
|
||||
{
|
||||
"name": "Account Move Number Sequence",
|
||||
"version": "16.0.1.1.6",
|
||||
"version": "17.0.1.0.0",
|
||||
"category": "Accounting",
|
||||
"license": "AGPL-3",
|
||||
"summary": "Generate journal entry number from sequence",
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
# @author: Francisco Luna <fluna@vauxoo.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import SUPERUSER_ID, api
|
||||
|
||||
|
||||
def post_init_hook(cr, registry):
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
def post_init_hook(env):
|
||||
create_journal_sequences(env)
|
||||
|
||||
|
||||
|
||||
@@ -86,10 +86,11 @@ class AccountJournal(models.Model):
|
||||
@api.model
|
||||
def _prepare_sequence(self, vals, refund=False):
|
||||
code = vals.get("code") and vals["code"].upper() or ""
|
||||
prefix = "%s%s/%%(range_year)s/" % (refund and "R" or "", code)
|
||||
prefix = "{}{}/%(range_year)s/".format(refund and "R" or "", code)
|
||||
seq_vals = {
|
||||
"name": "%s%s"
|
||||
% (vals.get("name", _("Sequence")), refund and " " + _("Refund") or ""),
|
||||
"name": "{}{}".format(
|
||||
vals.get("name", _("Sequence")), refund and " " + _("Refund") or ""
|
||||
),
|
||||
"company_id": vals.get("company_id") or self.env.company.id,
|
||||
"implementation": "no_gap",
|
||||
"prefix": prefix,
|
||||
@@ -124,8 +125,8 @@ class AccountJournal(models.Model):
|
||||
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 "")
|
||||
"Journal {} could not get sequence {} values based on current moves. "
|
||||
"Using default values.".format(self.id, refund and "refund" or "")
|
||||
)
|
||||
if not last_move:
|
||||
_logger.warning("%s %s", msg_err, "No moves found")
|
||||
@@ -168,7 +169,7 @@ class AccountJournal(models.Model):
|
||||
if month:
|
||||
prefix += "%(range_month)s"
|
||||
prefix3 = seq_format_values.get("prefix3") or ""
|
||||
where_name_value = "%s%s%s%s%s%%" % (
|
||||
where_name_value = "{}{}{}{}{}%".format(
|
||||
prefix1,
|
||||
"_" * seq_format_values["year_length"],
|
||||
prefix2,
|
||||
@@ -177,31 +178,27 @@ class AccountJournal(models.Model):
|
||||
)
|
||||
prefixes = prefix1 + prefix2
|
||||
select_year = (
|
||||
"split_part(name, '%s', %d)" % (prefix2, prefixes.count(prefix2))
|
||||
f"split_part(name, '{prefix2}', {prefixes.count(prefix2)})"
|
||||
if prefix2
|
||||
else "''"
|
||||
)
|
||||
prefixes += prefix3
|
||||
select_month = (
|
||||
"split_part(name, '%s', %d)" % (prefix3, prefixes.count(prefix3))
|
||||
f"split_part(name, '{prefix3}', {prefixes.count(prefix3)})"
|
||||
if prefix3
|
||||
else "''"
|
||||
)
|
||||
select_max_number = (
|
||||
"MAX(split_part(name, '%s', %d)::INTEGER) AS max_number"
|
||||
% (
|
||||
"MAX(split_part(name, '{}', {})::INTEGER) AS max_number".format(
|
||||
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,
|
||||
)
|
||||
"SELECT {}, {}, {} FROM account_move "
|
||||
"WHERE name LIKE %s AND journal_id=%s GROUP BY 1,2"
|
||||
).format(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))
|
||||
@@ -231,11 +228,11 @@ class AccountJournal(models.Model):
|
||||
else:
|
||||
year = "20" + year
|
||||
if month:
|
||||
date_from = fields.Date.to_date("%s-%s-1" % (year, month))
|
||||
date_from = fields.Date.to_date(f"{year}-{month}-1")
|
||||
date_to = fields.Date.end_of(date_from, "month")
|
||||
else:
|
||||
date_from = fields.Date.to_date("%s-1-1" % year)
|
||||
date_to = fields.Date.to_date("%s-12-31" % year)
|
||||
date_from = fields.Date.to_date(f"{year}-1-1")
|
||||
date_to = fields.Date.to_date(f"{year}-12-31")
|
||||
seq_vals["date_range_ids"].append(
|
||||
(
|
||||
0,
|
||||
|
||||
@@ -75,5 +75,5 @@ class AccountMove(models.Model):
|
||||
self.flush_model(["name", "journal_id", "move_type", "state"])
|
||||
return super()._fetch_duplicate_supplier_reference(only_posted=only_posted)
|
||||
|
||||
def _get_last_sequence(self, relaxed=False, with_prefix=None, lock=True):
|
||||
return super()._get_last_sequence(relaxed, None, lock)
|
||||
def _get_last_sequence(self, relaxed=False, with_prefix=None):
|
||||
return super()._get_last_sequence(relaxed, None)
|
||||
|
||||
@@ -11,7 +11,7 @@ class IrSequence(models.Model):
|
||||
# https://github.com/odoo/odoo/pull/91019
|
||||
date_obj = fields.Date.from_string(date)
|
||||
sequence_range = self.env["ir.sequence.date_range"]
|
||||
prefix_suffix = "%s %s" % (self.prefix, self.suffix)
|
||||
prefix_suffix = f"{self.prefix} {self.suffix}"
|
||||
if "%(range_day)s" in prefix_suffix:
|
||||
date_from = date_obj
|
||||
date_to = date_obj
|
||||
|
||||
@@ -72,7 +72,7 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
self.assertEqual(move.name, "/")
|
||||
move.action_post()
|
||||
seq = self.misc_journal.sequence_id
|
||||
move_name = "%s%s" % (seq.prefix, "1".zfill(seq.padding))
|
||||
move_name = "{}{}".format(seq.prefix, "1".zfill(seq.padding))
|
||||
move_name = move_name.replace("%(range_year)s", str(self.date.year))
|
||||
self.assertEqual(move.name, move_name)
|
||||
self.assertTrue(seq.date_range_ids)
|
||||
@@ -170,22 +170,6 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
self.assertEqual(in_invoice.name, "/")
|
||||
in_invoice.action_post()
|
||||
|
||||
move_reversal = (
|
||||
self.env["account.move.reversal"]
|
||||
.with_context(active_model="account.move", active_ids=in_invoice.ids)
|
||||
.create(
|
||||
{
|
||||
"journal_id": in_invoice.journal_id.id,
|
||||
"reason": "no reason",
|
||||
"refund_method": "cancel",
|
||||
}
|
||||
)
|
||||
)
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reversed_move = self.env["account.move"].browse(reversal["res_id"])
|
||||
self.assertTrue(reversed_move)
|
||||
self.assertEqual(reversed_move.state, "posted")
|
||||
|
||||
in_invoice = in_invoice.copy(
|
||||
{
|
||||
"invoice_date": self.date,
|
||||
@@ -193,18 +177,14 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
)
|
||||
in_invoice.action_post()
|
||||
|
||||
move_reversal = (
|
||||
self.env["account.move.reversal"]
|
||||
.with_context(active_model="account.move", active_ids=in_invoice.ids)
|
||||
.create(
|
||||
{
|
||||
"journal_id": in_invoice.journal_id.id,
|
||||
"reason": "no reason",
|
||||
"refund_method": "modify",
|
||||
}
|
||||
)
|
||||
move_reversal = self.env["account.move.reversal"].create(
|
||||
{
|
||||
"move_ids": in_invoice.ids,
|
||||
"journal_id": in_invoice.journal_id.id,
|
||||
"reason": "no reason",
|
||||
}
|
||||
)
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reversal = move_reversal.modify_moves()
|
||||
draft_invoice = self.env["account.move"].browse(reversal["res_id"])
|
||||
self.assertTrue(draft_invoice)
|
||||
self.assertEqual(draft_invoice.state, "draft")
|
||||
@@ -217,18 +197,14 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
)
|
||||
in_invoice.action_post()
|
||||
|
||||
move_reversal = (
|
||||
self.env["account.move.reversal"]
|
||||
.with_context(active_model="account.move", active_ids=in_invoice.ids)
|
||||
.create(
|
||||
{
|
||||
"journal_id": in_invoice.journal_id.id,
|
||||
"reason": "no reason",
|
||||
"refund_method": "refund",
|
||||
}
|
||||
)
|
||||
move_reversal = self.env["account.move.reversal"].create(
|
||||
{
|
||||
"move_ids": in_invoice.ids,
|
||||
"journal_id": in_invoice.journal_id.id,
|
||||
"reason": "no reason",
|
||||
}
|
||||
)
|
||||
reversal = move_reversal.reverse_moves()
|
||||
reversal = move_reversal.refund_moves()
|
||||
draft_reversed_move = self.env["account.move"].browse(reversal["res_id"])
|
||||
self.assertTrue(draft_reversed_move)
|
||||
self.assertEqual(draft_reversed_move.state, "draft")
|
||||
@@ -257,7 +233,7 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
self.assertEqual(in_refund_invoice.name, "/")
|
||||
in_refund_invoice.action_post()
|
||||
seq = self.purchase_journal.refund_sequence_id
|
||||
move_name = "%s%s" % (seq.prefix, "1".zfill(seq.padding))
|
||||
move_name = "{}{}".format(seq.prefix, "1".zfill(seq.padding))
|
||||
move_name = move_name.replace("%(range_year)s", str(self.date.year))
|
||||
self.assertEqual(in_refund_invoice.name, move_name)
|
||||
in_refund_invoice.button_draft()
|
||||
@@ -277,7 +253,7 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
)
|
||||
self.assertEqual(invoice.name, "/")
|
||||
invoice.action_post()
|
||||
error_msg = "You cannot delete an item linked to a posted entry."
|
||||
error_msg = "You can't delete a posted journal item. Don’t play games with your accounting records; reset the journal entry to draft before deleting it."
|
||||
with self.assertRaisesRegex(UserError, error_msg):
|
||||
invoice.unlink()
|
||||
invoice.button_draft()
|
||||
@@ -309,7 +285,7 @@ class TestAccountMoveNameSequence(TransactionCase):
|
||||
)
|
||||
self.assertEqual(in_refund_invoice.name, "/")
|
||||
in_refund_invoice.action_post()
|
||||
error_msg = "You cannot delete an item linked to a posted entry."
|
||||
error_msg = "You can't delete a posted journal item. Don’t play games with your accounting records; reset the journal entry to draft before deleting it."
|
||||
with self.assertRaisesRegex(UserError, error_msg):
|
||||
in_refund_invoice.unlink()
|
||||
in_refund_invoice.button_draft()
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<field name="refund_sequence" position="after">
|
||||
<field
|
||||
name="refund_sequence_id"
|
||||
attrs="{'invisible': ['|', ('type', 'not in', ('sale', 'purchase')), ('refund_sequence', '=', False)],
|
||||
'required': [('type', 'in', ('sale', 'purchase')), ('refund_sequence', '=', True)]}"
|
||||
invisible="type not in ('sale', 'purchase') or not refund_sequence"
|
||||
required="type in ('sale', 'purchase') and refund_sequence"
|
||||
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>
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
expr="//div[hasclass('oe_title')]//field[@name='name']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute name="attrs">{'invisible': [('name', '=', '/')]}</attribute>
|
||||
<attribute name="invisible">name == '/'</attribute>
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//div[hasclass('oe_title')]//h1//span" position="attributes">
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'invisible': ['|', ('state', '!=', 'draft'), ('name', '!=', '/')]}</attribute>
|
||||
<attribute name="invisible">state != 'draft' or name != '/'</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user