mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[MIG] account_mass_reconcile: Migration to 15.0
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
{
|
||||
"name": "Account Mass Reconcile",
|
||||
"version": "14.0.1.1.1",
|
||||
"version": "15.0.1.0.0",
|
||||
"depends": ["account"],
|
||||
"author": "Akretion,Camptocamp,Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/account-reconcile",
|
||||
|
||||
@@ -6,7 +6,6 @@ from odoo import models
|
||||
|
||||
|
||||
class MassReconcileAdvancedRef(models.TransientModel):
|
||||
|
||||
_name = "mass.reconcile.advanced.ref"
|
||||
_inherit = "mass.reconcile.advanced"
|
||||
_description = "Mass Reconcile Advanced Ref"
|
||||
@@ -44,7 +43,7 @@ class MassReconcileAdvancedRef(models.TransientModel):
|
||||
to consider them as "opposite"
|
||||
|
||||
The matchers will be evaluated in the same order as declared
|
||||
vs the the opposite matchers, so you can gain performance by
|
||||
vs the opposite matchers, so you can gain performance by
|
||||
declaring first the partners with the less computation.
|
||||
|
||||
All matchers should match with their opposite to be considered
|
||||
@@ -54,9 +53,9 @@ class MassReconcileAdvancedRef(models.TransientModel):
|
||||
|
||||
:return: tuple of tuples (key, value) where the keys are
|
||||
the matchers keys
|
||||
(must be the same than `_opposite_matchers` returns,
|
||||
(They must be the same that `_opposite_matchers` returns,
|
||||
and their values to match in the opposite lines.
|
||||
A matching key can have multiples values.
|
||||
A matching key can have multiples values.)
|
||||
"""
|
||||
return (
|
||||
("partner_id", move_line["partner_id"]),
|
||||
@@ -97,7 +96,7 @@ class MassReconcileAdvancedRef(models.TransientModel):
|
||||
yield ('ref', (move_line['ref'], move_line['name'])
|
||||
|
||||
An OR is used between the values for the same key.
|
||||
An AND is used between the differents keys.
|
||||
An AND is used between the different keys.
|
||||
|
||||
:param dict move_line: values of the move_line
|
||||
:yield: matchers as tuple ('matcher key', value(s))
|
||||
@@ -151,7 +150,7 @@ class MassReconcileAdvancedName(models.TransientModel):
|
||||
to consider them as "opposite"
|
||||
|
||||
The matchers will be evaluated in the same order as declared
|
||||
vs the the opposite matchers, so you can gain performance by
|
||||
vs the opposite matchers, so you can gain performance by
|
||||
declaring first the partners with the less computation.
|
||||
|
||||
All matchers should match with their opposite to be considered
|
||||
@@ -161,9 +160,9 @@ class MassReconcileAdvancedName(models.TransientModel):
|
||||
|
||||
:return: tuple of tuples (key, value) where the keys are
|
||||
the matchers keys
|
||||
(must be the same than `_opposite_matchers` returns,
|
||||
(They must be the same that `_opposite_matchers` returns,
|
||||
and their values to match in the opposite lines.
|
||||
A matching key can have multiples values.
|
||||
A matching key can have multiples values.)
|
||||
"""
|
||||
return (
|
||||
("partner_id", move_line["partner_id"]),
|
||||
@@ -204,7 +203,7 @@ class MassReconcileAdvancedName(models.TransientModel):
|
||||
yield ('ref', (move_line['ref'], move_line['name'])
|
||||
|
||||
An OR is used between the values for the same key.
|
||||
An AND is used between the differents keys.
|
||||
An AND is used between the different keys.
|
||||
|
||||
:param dict move_line: values of the move_line
|
||||
:yield: matchers as tuple ('matcher key', value(s))
|
||||
|
||||
@@ -72,9 +72,9 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
|
||||
:return: tuple of tuples (key, value) where the keys are
|
||||
the matchers keys
|
||||
(must be the same than `_opposite_matchers` returns,
|
||||
(They must be the same that `_opposite_matchers` returns,
|
||||
and their values to match in the opposite lines.
|
||||
A matching key can have multiples values.
|
||||
A matching key can have multiples values.)
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -112,7 +112,7 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
yield ('ref', (move_line['ref'], move_line['name'])
|
||||
|
||||
An OR is used between the values for the same key.
|
||||
An AND is used between the differents keys.
|
||||
An AND is used between the different keys.
|
||||
|
||||
:param dict move_line: values of the move_line
|
||||
:yield: matchers as tuple ('matcher key', value(s))
|
||||
@@ -137,7 +137,7 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
|
||||
@classmethod
|
||||
def _compare_matcher_values(cls, key, values, opposite_values):
|
||||
"""Compare every values from a matcher vs an opposite matcher
|
||||
"""Compare every `values` from a matcher vs an opposite matcher
|
||||
and return True if it matches
|
||||
"""
|
||||
for value, ovalue in product(values, opposite_values):
|
||||
@@ -155,9 +155,9 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
mkey, mvalue = matcher
|
||||
omkey, omvalue = opposite_matcher
|
||||
assert mkey == omkey, _(
|
||||
"A matcher %s is compared with a matcher %s, the _matchers and "
|
||||
"A matcher %(mkey)s is compared with a matcher %(omkey)s, the _matchers and "
|
||||
"_opposite_matchers are probably wrong"
|
||||
) % (mkey, omkey)
|
||||
) % {"mkey": mkey, "omkey": omkey}
|
||||
if not isinstance(mvalue, (list, tuple)):
|
||||
mvalue = (mvalue,)
|
||||
if not isinstance(omvalue, (list, tuple)):
|
||||
@@ -175,10 +175,10 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
for matcher in matchers:
|
||||
try:
|
||||
opp_matcher = next(opp_matchers)
|
||||
except StopIteration:
|
||||
except StopIteration as e:
|
||||
# if you fall here, you probably missed to put a `yield`
|
||||
# in `_opposite_matchers()`
|
||||
raise ValueError("Missing _opposite_matcher: %s" % matcher[0])
|
||||
raise ValueError("Missing _opposite_matcher: %s" % matcher[0]) from e
|
||||
|
||||
if not self._compare_matchers(matcher, opp_matcher):
|
||||
# if any of the matcher fails, the opposite line
|
||||
@@ -238,9 +238,9 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
def _rec_group_by_chunk(self, reconcile_groups, lines_by_id, chunk_size):
|
||||
"""Commit after each chunk
|
||||
|
||||
:param dict reconcile_grous: all groups to reconcile, will be splitted
|
||||
:param list reconcile_groups: all groups to reconcile, will be split
|
||||
by chunk
|
||||
:param list lines_by_id: list of dict of move lines values,
|
||||
:param dict lines_by_id: dict of move lines values,
|
||||
the move lines we want to search for
|
||||
:return: list of reconciled lines
|
||||
"""
|
||||
@@ -251,23 +251,19 @@ class MassReconcileAdvanced(models.AbstractModel):
|
||||
# Copy and commit current transient model before creating a new cursor
|
||||
# This is required to avoid CacheMiss when using data from `self`
|
||||
# which is created during current transaction.
|
||||
with api.Environment.manage():
|
||||
with registry(self.env.cr.dbname).cursor() as new_cr:
|
||||
new_env = api.Environment(new_cr, self.env.uid, self.env.context)
|
||||
self_env = self.with_env(new_env)
|
||||
rec = self_env.create(self.copy_data())
|
||||
with registry(self.env.cr.dbname).cursor() as new_cr:
|
||||
new_env = api.Environment(new_cr, self.env.uid, self.env.context)
|
||||
self_env = self.with_env(new_env)
|
||||
rec = self_env.create(self.copy_data())
|
||||
for i in range(0, len(reconcile_groups), chunk_size):
|
||||
chunk = reconcile_groups[i : i + chunk_size]
|
||||
_logger.debug("Reconcile group chunk %s", chunk)
|
||||
try:
|
||||
with api.Environment.manage():
|
||||
with registry(self.env.cr.dbname).cursor() as new_cr:
|
||||
new_env = api.Environment(
|
||||
new_cr, self.env.uid, self.env.context
|
||||
)
|
||||
# Re-use the commited transient we just commited
|
||||
self_env = self.with_env(new_env).browse(rec.id)
|
||||
reconciled_ids += self_env._rec_group(chunk, lines_by_id)
|
||||
with registry(self.env.cr.dbname).cursor() as new_cr:
|
||||
new_env = api.Environment(new_cr, self.env.uid, self.env.context)
|
||||
# Re-use the committed transient we just committed
|
||||
self_env = self.with_env(new_env).browse(rec.id)
|
||||
reconciled_ids += self_env._rec_group(chunk, lines_by_id)
|
||||
except Exception as e:
|
||||
msg = "Reconciliation failed for group chunk %s with error:\n%s"
|
||||
_logger.exception(msg, chunk, e)
|
||||
|
||||
@@ -77,7 +77,7 @@ class MassReconcileBase(models.AbstractModel):
|
||||
# it would be great to use dict for params
|
||||
# but as we use _where_calc in _get_filter
|
||||
# which returns a list, we have to
|
||||
# accomodate with that
|
||||
# accommodate with that
|
||||
params = [self.account_id.id]
|
||||
if self.partner_ids:
|
||||
where += " AND account_move_line.partner_id IN %s"
|
||||
|
||||
@@ -64,7 +64,6 @@ class AccountMassReconcileMethod(models.Model):
|
||||
|
||||
name = fields.Selection("_selection_name", string="Type", required=True)
|
||||
sequence = fields.Integer(
|
||||
string="Sequence",
|
||||
default=1,
|
||||
required=True,
|
||||
help="The sequence field is used to order the reconcile method",
|
||||
@@ -110,8 +109,8 @@ class AccountMassReconcile(models.Model):
|
||||
)
|
||||
rec.last_history = last_history_rs or False
|
||||
|
||||
name = fields.Char(string="Name", required=True)
|
||||
account = fields.Many2one("account.account", string="Account", required=True)
|
||||
name = fields.Char(required=True)
|
||||
account = fields.Many2one("account.account", required=True)
|
||||
reconcile_method = fields.One2many(
|
||||
"account.mass.reconcile.method", "task_id", string="Method"
|
||||
)
|
||||
@@ -134,9 +133,9 @@ class AccountMassReconcile(models.Model):
|
||||
return {
|
||||
"account_id": rec_method.task_id.account.id,
|
||||
"write_off": rec_method.write_off,
|
||||
"account_lost_id": (rec_method.account_lost_id.id),
|
||||
"account_profit_id": (rec_method.account_profit_id.id),
|
||||
"journal_id": (rec_method.journal_id.id),
|
||||
"account_lost_id": rec_method.account_lost_id.id,
|
||||
"account_profit_id": rec_method.account_profit_id.id,
|
||||
"journal_id": rec_method.journal_id.id,
|
||||
"date_base_on": rec_method.date_base_on,
|
||||
"_filter": rec_method._filter,
|
||||
}
|
||||
@@ -175,13 +174,13 @@ class AccountMassReconcile(models.Model):
|
||||
" FOR UPDATE NOWAIT",
|
||||
(rec.id,),
|
||||
)
|
||||
except psycopg2.OperationalError:
|
||||
except psycopg2.OperationalError as e:
|
||||
raise exceptions.UserError(
|
||||
_(
|
||||
"A mass reconcile is already ongoing for this account, "
|
||||
"please try again later."
|
||||
)
|
||||
)
|
||||
) from e
|
||||
ctx = self.env.context.copy()
|
||||
ctx["commit_every"] = rec.account.company_id.reconciliation_commit_every
|
||||
if ctx["commit_every"]:
|
||||
@@ -245,7 +244,6 @@ class AccountMassReconcile(models.Model):
|
||||
"name": name,
|
||||
"view_mode": "tree,form",
|
||||
"view_id": False,
|
||||
"view_type": "form",
|
||||
"res_model": "account.move.line",
|
||||
"type": "ir.actions.act_window",
|
||||
"nodestroy": True,
|
||||
@@ -280,7 +278,7 @@ class AccountMassReconcile(models.Model):
|
||||
"""Launch the reconcile with the oldest run
|
||||
This function is mostly here to be used with cron task
|
||||
|
||||
:param run_all: if set it will ingore lookup and launch
|
||||
:param run_all: if set it will ignore lookup and launch
|
||||
all reconciliation
|
||||
:returns: True in case of success or raises an exception
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ class MassReconcileHistory(models.Model):
|
||||
"name": name,
|
||||
"view_mode": "tree,form",
|
||||
"view_id": False,
|
||||
"view_type": "form",
|
||||
"res_model": "account.move.line",
|
||||
"type": "ir.actions.act_window",
|
||||
"nodestroy": True,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestOnChange(common.SavepointCase):
|
||||
class TestOnChange(common.TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestOnChange, cls).setUpClass()
|
||||
|
||||
@@ -130,7 +130,7 @@ class TestScenarioReconcile(TestAccountReconciliationCommon):
|
||||
"reconcile_method": [(0, 0, {"name": "mass.reconcile.simple.partner"})],
|
||||
}
|
||||
)
|
||||
# call the automatic reconcilation method
|
||||
# call the automatic reconciliation method
|
||||
mass_rec.run_reconcile()
|
||||
self.assertEqual("paid", invoice.payment_state)
|
||||
|
||||
@@ -228,7 +228,7 @@ class TestScenarioReconcile(TestAccountReconciliationCommon):
|
||||
],
|
||||
}
|
||||
)
|
||||
# call the automatic reconcilation method
|
||||
# call the automatic reconciliation method
|
||||
mass_rec.run_reconcile()
|
||||
self.assertEqual("not_paid", invoice.payment_state)
|
||||
mass_rec.reconcile_method.write_off = 0.11
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</page>
|
||||
<page name="history" string="History">
|
||||
<field name="history_ids" nolabel="1">
|
||||
<tree string="Automatic Mass Reconcile History">
|
||||
<tree>
|
||||
<field name="date" />
|
||||
<button
|
||||
icon="fa-share"
|
||||
@@ -116,7 +116,7 @@ The lines should have the same partner, and the credit entry ref. is matched wit
|
||||
<field name="priority">20</field>
|
||||
<field name="model">account.mass.reconcile</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Automatic Mass Reconcile">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
<field name="account" />
|
||||
<field name="company_id" groups="base.group_multi_company" />
|
||||
@@ -161,7 +161,7 @@ The lines should have the same partner, and the credit entry ref. is matched wit
|
||||
<field name="priority">20</field>
|
||||
<field name="model">account.mass.reconcile.method</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="top" string="Automatic Mass Reconcile Method">
|
||||
<tree editable="top">
|
||||
<field name="sequence" widget="handle" />
|
||||
<field name="name" />
|
||||
<field name="write_off" />
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<field name="name">mass.reconcile.history.tree</field>
|
||||
<field name="model">mass.reconcile.history</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Automatic Mass Reconcile History">
|
||||
<tree>
|
||||
<field name="mass_reconcile_id" />
|
||||
<field name="date" />
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user