diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py
index 975c88cdf16..4eb59c79090 100644
--- a/addons/account/models/account_journal_dashboard.py
+++ b/addons/account/models/account_journal_dashboard.py
@@ -510,7 +510,7 @@ class account_journal(models.Model):
[action] = self.env[model].browse(action_id).read()
action['context'] = ctx
if ctx.get('use_domain', False):
- action['domain'] = ['|', ('journal_id', '=', self.id), ('journal_id', '=', False)]
+ action['domain'] = isinstance(ctx['use_domain'], list) and ctx['use_domain'] or ['|', ('journal_id', '=', self.id), ('journal_id', '=', False)]
action['name'] += ' for journal ' + self.name
return action
diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py
index 83a65f028f0..fcb7f4b08ad 100644
--- a/addons/account/models/account_reconcile_model.py
+++ b/addons/account/models/account_reconcile_model.py
@@ -3,11 +3,83 @@
from odoo import api, fields, models, _
from odoo.tools import float_compare, float_is_zero
from odoo.exceptions import UserError
-
import re
from math import copysign
+class AccountReconcileModelLine(models.Model):
+ _name = 'account.reconcile.model.line'
+ _description = 'Rules for the reconciliation model'
+ _order = 'sequence, id'
+
+ model_id = fields.Many2one('account.reconcile.model', readonly=True)
+ match_total_amount = fields.Boolean(related='model_id.match_total_amount')
+ match_total_amount_param = fields.Float(related='model_id.match_total_amount_param')
+ rule_type = fields.Selection(related='model_id.rule_type')
+ company_id = fields.Many2one(related='model_id.company_id')
+ sequence = fields.Integer(required=True, default=10)
+ account_id = fields.Many2one('account.account', string='Account', ondelete='cascade', domain=[('deprecated', '=', False)], required=True)
+ journal_id = fields.Many2one('account.journal', string='Journal', ondelete='cascade', help="This field is ignored in a bank statement reconciliation.")
+ label = fields.Char(string='Journal Item Label')
+ amount_type = fields.Selection([
+ ('fixed', 'Fixed'),
+ ('percentage', 'Percentage of balance'),
+ ('regex', 'From label'),
+ ], required=True, default='percentage')
+ show_force_tax_included = fields.Boolean(compute='_compute_show_force_tax_included', help='Technical field used to show the force tax included button')
+ force_tax_included = fields.Boolean(string='Tax Included in Price', help='Force the tax to be managed as a price included tax.')
+ amount = fields.Float(string="Float Amount", compute='_compute_float_amount', store=True, help="Technical shortcut to parse the amount to a float")
+ amount_string = fields.Char(string="Amount", default='100', required=True, help="""Value for the amount of the writeoff line
+ * Percentage: Percentage of the balance, between 0 and 100.
+ * Fixed: The fixed value of the writeoff. The amount will count as a debit if it is negative, as a credit if it is positive.
+ * From Label: There is no need for regex delimiter, only the regex is needed. For instance if you want to extract the amount from\nR:9672938 10/07 AX 9415126318 T:5L:NA BRT: 3358,07 C:\nYou could enter\nBRT: ([\d,]+)""")
+ tax_ids = fields.Many2many('account.tax', string='Taxes', ondelete='restrict')
+ analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account', ondelete='set null')
+ analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags',
+ relation='account_reconcile_model_analytic_tag_rel')
+
+ @api.onchange('tax_ids')
+ def _onchange_tax_ids(self):
+ # Multiple taxes with force_tax_included results in wrong computation, so we
+ # only allow to set the force_tax_included field if we have one tax selected
+ if len(self.tax_ids) != 1:
+ self.force_tax_included = False
+
+ @api.depends('tax_ids')
+ def _compute_show_force_tax_included(self):
+ for record in self:
+ record.show_force_tax_included = False if len(record.tax_ids) != 1 else True
+
+ @api.onchange('amount_type')
+ def _onchange_amount_type(self):
+ self.amount_string = ''
+ if self.amount_type == 'percentage':
+ self.amount_string = '100'
+ elif self.amount_type == 'regex':
+ self.amount_string = '([\d,]+)'
+
+ @api.depends('amount_string')
+ def _compute_float_amount(self):
+ for record in self:
+ try:
+ record.amount = float(record.amount_string)
+ except ValueError:
+ record.amount = 0
+
+ @api.constrains('amount_string')
+ def _validate_amount(self):
+ for record in self:
+ if record.amount_type == 'fixed' and record.amount == 0:
+ raise UserError(_('The amount is not a number'))
+ if record.amount_type == 'percentage' and not 0 < record.amount <= 100:
+ raise UserError(_('The amount is not a percentage'))
+ if record.amount_type == 'regex':
+ try:
+ re.compile(record.amount_string)
+ except re.error:
+ raise UserError(_('The regex is not valid'))
+
+
class AccountReconcileModel(models.Model):
_name = 'account.reconcile.model'
_description = 'Preset to create journal entries during a invoices and payments matching'
@@ -88,47 +160,10 @@ class AccountReconcileModel(models.Model):
match_partner_category_ids = fields.Many2many('res.partner.category', string='Restrict Partner Categories to',
help='The reconciliation model will only be applied to the selected customer/vendor categories.')
- # ===== Write-Off =====
- # First part fields.
- account_id = fields.Many2one('account.account', string='Account', ondelete='cascade', domain=[('deprecated', '=', False)])
- journal_id = fields.Many2one('account.journal', string='Journal', ondelete='cascade', help="This field is ignored in a bank statement reconciliation.")
- label = fields.Char(string='Journal Item Label')
- amount_type = fields.Selection([
- ('fixed', 'Fixed'),
- ('percentage', 'Percentage of balance'),
- ('regex', 'From label'),
- ], required=True, default='percentage')
- show_force_tax_included = fields.Boolean(compute='_compute_show_force_tax_included', help='Technical field used to show the force tax included button')
- force_tax_included = fields.Boolean(string='Tax Included in Price',
- help='Force the tax to be managed as a price included tax.')
- amount = fields.Float(string='Write-off Amount', digits=0, required=True, default=100.0, help="Fixed amount will count as a debit if it is negative, as a credit if it is positive.")
- amount_from_label_regex = fields.Char(string="Amount from Label (regex)", default=r"([\d\.,]+)", help="There is no need for regex delimiter, only the regex is needed. For instance if you want to extract the amount from\nR:9672938 10/07 AX 9415126318 T:5L:NA BRT: 3358,07 C:\nYou could enter\nBRT: ([\d,]+)")
+ line_ids = fields.One2many('account.reconcile.model.line', 'model_id')
+
decimal_separator = fields.Char(default=lambda self: self.env['res.lang']._lang_get(self.env.user.lang).decimal_point, help="Every character that is nor a digit nor this separator will be removed from the matching string")
- tax_ids = fields.Many2many('account.tax', string='Taxes', ondelete='restrict')
- analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account', ondelete='set null')
- analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Analytic Tags',
- relation='account_reconcile_model_analytic_tag_rel')
-
- # Second part fields.
- has_second_line = fields.Boolean(string='Add a second line', default=False)
- second_account_id = fields.Many2one('account.account', string='Second Account', ondelete='cascade', domain=[('deprecated', '=', False)])
- second_journal_id = fields.Many2one('account.journal', string='Second Journal', ondelete='cascade', help="This field is ignored in a bank statement reconciliation.")
- second_label = fields.Char(string='Second Journal Item Label')
- second_amount_type = fields.Selection([
- ('fixed', 'Fixed'),
- ('percentage', 'Percentage of balance'),
- ('regex', 'From label'),
- ], string="Second Amount type",required=True, default='percentage')
- show_second_force_tax_included = fields.Boolean(compute='_compute_show_second_force_tax_included', help='Technical field used to show the force tax included button')
- force_second_tax_included = fields.Boolean(string='Second Tax Included in Price',
- help='Force the second tax to be managed as a price included tax.')
- second_amount = fields.Float(string='Second Write-off Amount', digits=0, required=True, default=100.0, help="Fixed amount will count as a debit if it is negative, as a credit if it is positive.")
- second_amount_from_label_regex = fields.Char(string="Second Amount from Label (regex)", default=r"([\d\.,]+)")
- second_tax_ids = fields.Many2many('account.tax', relation='account_reconcile_model_account_tax_bis_rel', string='Second Taxes', ondelete='restrict')
- second_analytic_account_id = fields.Many2one('account.analytic.account', string='Second Analytic Account', ondelete='set null')
- second_analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Second Analytic Tags',
- relation='account_reconcile_model_second_analytic_tag_rel')
-
+ show_decimal_separator = fields.Boolean(compute='_compute_show_decimal_separator', help="Technical field to decide if we should show the decimal separator for the regex matching field.")
number_entries = fields.Integer(string='Number of entries related to this model', compute='_compute_number_entries')
def action_reconcile_stat(self):
@@ -152,29 +187,10 @@ class AccountReconcileModel(models.Model):
for model in self:
model.number_entries = mapped_data.get(model.id, 0)
- @api.onchange('tax_ids')
- def _onchange_tax_ids(self):
- # Multiple taxes with force_tax_included results in wrong computation, so we
- # only allow to set the force_tax_included field if we have one tax selected
- if len(self.tax_ids) != 1:
- self.force_tax_included = False
-
- @api.depends('tax_ids')
- def _compute_show_force_tax_included(self):
+ @api.depends('line_ids.amount_type')
+ def _compute_show_decimal_separator(self):
for record in self:
- record.show_force_tax_included = False if len(record.tax_ids) != 1 else True
-
- @api.onchange('second_tax_ids')
- def _onchange_second_tax_ids(self):
- # Multiple taxes with force_tax_included results in wrong computation, so we
- # only allow to set the force_tax_included field if we have one tax selected
- if len(self.second_tax_ids) != 1:
- self.force_second_tax_included = False
-
- @api.depends('second_tax_ids')
- def _compute_show_second_force_tax_included(self):
- for record in self:
- record.show_second_force_tax_included = False if len(record.second_tax_ids) != 1 else True
+ record.show_decimal_separator = any(l.amount_type == 'regex' for l in record.line_ids)
@api.onchange('match_total_amount_param')
def _onchange_match_total_amount_param(self):
@@ -185,13 +201,13 @@ class AccountReconcileModel(models.Model):
# RECONCILIATION PROCESS
####################################################
- @api.model
def _get_taxes_move_lines_dict(self, tax, base_line_dict):
''' Get move.lines dict (to be passed to the create()) corresponding to a tax.
:param tax: An account.tax record.
:param base_line_dict: A dict representing the move.line containing the base amount.
:return: A list of dict representing move.lines to be created corresponding to the tax.
'''
+ self.ensure_one()
balance = base_line_dict['debit'] - base_line_dict['credit']
currency = base_line_dict.get('currency_id') and self.env['res.currency'].browse(base_line_dict['currency_id'])
@@ -212,7 +228,8 @@ class AccountReconcileModel(models.Model):
'tax_exigible': tax_res['tax_exigibility'],
'tax_repartition_line_id': tax_res['tax_repartition_line_id'],
'tax_ids': tax_res['tax_ids'],
- 'tag_ids': tax_res['tag_ids']
+ 'tag_ids': tax_res['tag_ids'],
+ 'reconcile_model_id': self.id,
})
# Handle price included taxes.
@@ -221,7 +238,7 @@ class AccountReconcileModel(models.Model):
base_line_dict['tag_ids'] = [(6, 0, res['base_tags'])]
return new_aml_dicts
- def _get_write_off_move_lines_dict(self, st_line, move_lines=None):
+ def _get_write_off_move_lines_dict(self, st_line, move_lines=None, residual_balance=None):
''' Get move.lines dict (to be passed to the create()) corresponding to the reconciliation model's write-off lines.
:param st_line: An account.bank.statement.line record.
:param move_lines: An account.move.line recordset.
@@ -238,76 +255,43 @@ class AccountReconcileModel(models.Model):
balance = total_residual - line_residual
- if not self.account_id or float_is_zero(balance, precision_rounding=line_currency.rounding):
- return []
-
- if self.amount_type == 'percentage':
- line_balance = balance * (self.amount / 100.0)
- elif self.amount_type == "regex":
- match = re.search(self.amount_from_label_regex, st_line.name)
- if match:
- line_balance = copysign(float(re.sub(r'\D' + self.decimal_separator, '', match.group(1)).replace(self.decimal_separator, '.')) * (1 if balance > 0.0 else -1), balance)
- else:
- line_balance = 0
- else:
- line_balance = self.amount * (1 if balance > 0.0 else -1)
-
new_aml_dicts = []
+ if residual_balance is None:
+ residual_balance = balance
+ for line in self.line_ids:
+ if not line.account_id or float_is_zero(residual_balance, precision_rounding=line_currency.rounding):
+ continue
- # First write-off line.
- writeoff_line = {
- 'name': self.label or st_line.name,
- 'account_id': self.account_id.id,
- 'analytic_account_id': self.analytic_account_id.id,
- 'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
- 'debit': line_balance > 0 and line_balance or 0,
- 'credit': line_balance < 0 and -line_balance or 0,
- 'reconcile_model_id': self.id,
- }
- new_aml_dicts.append(writeoff_line)
-
- if self.tax_ids:
- writeoff_line['tax_ids'] = [(6, None, self.tax_ids.ids)]
- tax = self.tax_ids
- # Multiple taxes with force_tax_included results in wrong computation, so we
- # only allow to set the force_tax_included field if we have one tax selected
- if self.force_tax_included:
- tax = tax[0].with_context(force_price_include=True)
- new_aml_dicts += self._get_taxes_move_lines_dict(tax, writeoff_line)
-
- # Second write-off line.
- if self.has_second_line and self.second_account_id:
- remaining_balance = balance - sum(aml['debit'] - aml['credit'] for aml in new_aml_dicts)
- if self.second_amount_type == 'percentage':
- line_balance = remaining_balance * (self.second_amount / 100.0)
- elif self.second_amount_type == "regex":
- match = re.search(self.second_amount_from_label_regex, st_line.name)
+ if line.amount_type == 'percentage':
+ line_balance = residual_balance * (line.amount / 100.0)
+ elif line.amount_type == "regex":
+ match = re.search(line.amount_string, st_line.name)
if match:
- line_balance = copysign(float(re.sub(r'\D' + self.decimal_separator, '', match.group(1)).replace(self.decimal_separator, '.')), remaining_balance)
+ line_balance = copysign(float(re.sub(r'\D' + self.decimal_separator, '', match.group(1)).replace(self.decimal_separator, '.')) * (1 if balance > 0.0 else -1), balance)
else:
line_balance = 0
else:
- line_balance = self.second_amount * (1 if remaining_balance > 0.0 else -1)
-
- second_writeoff_line = {
- 'name': self.second_label or st_line.name,
- 'account_id': self.second_account_id.id,
- 'analytic_account_id': self.second_analytic_account_id.id,
- 'analytic_tag_ids': [(6, 0, self.second_analytic_tag_ids.ids)],
+ line_balance = line.amount * (1 if residual_balance > 0.0 else -1)
+ writeoff_line = {
+ 'name': line.label or st_line.name,
+ 'account_id': line.account_id.id,
+ 'analytic_account_id': line.analytic_account_id.id,
+ 'analytic_tag_ids': [(6, 0, line.analytic_tag_ids.ids)],
'debit': line_balance > 0 and line_balance or 0,
'credit': line_balance < 0 and -line_balance or 0,
'reconcile_model_id': self.id,
}
- new_aml_dicts.append(second_writeoff_line)
+ new_aml_dicts.append(writeoff_line)
- if self.second_tax_ids:
- second_writeoff_line['tax_ids'] = [(6, None, self.second_tax_ids.ids)]
- tax = self.second_tax_ids
+ residual_balance -= line_balance
+ if line.tax_ids:
+ writeoff_line['tax_ids'] = [(6, None, line.tax_ids.ids)]
+ tax = line.tax_ids
# Multiple taxes with force_tax_included results in wrong computation, so we
# only allow to set the force_tax_included field if we have one tax selected
- if self.force_second_tax_included:
+ if line.force_tax_included:
tax = tax[0].with_context(force_price_include=True)
- new_aml_dicts += self._get_taxes_move_lines_dict(tax, second_writeoff_line)
+ new_aml_dicts += self._get_taxes_move_lines_dict(tax, writeoff_line)
return new_aml_dicts
diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py
index 6a5220f50ed..6dd67e8fce5 100644
--- a/addons/account/models/chart_template.py
+++ b/addons/account/models/chart_template.py
@@ -698,44 +698,42 @@ class AccountChartTemplate(models.Model):
""" This method generates a dictionary of all the values for the account.reconcile.model that will be created.
"""
self.ensure_one()
+ account_reconcile_model_lines = self.env['account.reconcile.model.line.template'].search([
+ ('model_id', '=', account_reconcile_model.id)
+ ])
return {
- 'name': account_reconcile_model.name,
- 'sequence': account_reconcile_model.sequence,
- 'has_second_line': account_reconcile_model.has_second_line,
- 'company_id': company.id,
- 'account_id': acc_template_ref[account_reconcile_model.account_id.id],
- 'label': account_reconcile_model.label,
- 'to_check': account_reconcile_model.to_check,
- 'amount_type': account_reconcile_model.amount_type,
- 'force_tax_included': account_reconcile_model.force_tax_included,
- 'amount': account_reconcile_model.amount,
- 'tax_ids': [[4, tax_template_ref[tax.id], 0] for tax in account_reconcile_model.tax_ids],
- 'second_account_id': account_reconcile_model.second_account_id and acc_template_ref[account_reconcile_model.second_account_id.id] or False,
- 'second_label': account_reconcile_model.second_label,
- 'second_amount_type': account_reconcile_model.second_amount_type,
- 'force_second_tax_included': account_reconcile_model.force_second_tax_included,
- 'second_amount': account_reconcile_model.second_amount,
- 'rule_type': account_reconcile_model.rule_type,
- 'auto_reconcile': account_reconcile_model.auto_reconcile,
- 'match_journal_ids': [(6, None, account_reconcile_model.match_journal_ids.ids)],
- 'match_nature': account_reconcile_model.match_nature,
- 'match_amount': account_reconcile_model.match_amount,
- 'match_amount_min': account_reconcile_model.match_amount_min,
- 'match_amount_max': account_reconcile_model.match_amount_max,
- 'match_label': account_reconcile_model.match_label,
- 'match_label_param': account_reconcile_model.match_label_param,
- 'match_note': account_reconcile_model.match_note,
- 'match_note_param': account_reconcile_model.match_note_param,
- 'match_transaction_type': account_reconcile_model.match_transaction_type,
- 'match_transaction_type_param': account_reconcile_model.match_transaction_type_param,
- 'match_same_currency': account_reconcile_model.match_same_currency,
- 'match_total_amount': account_reconcile_model.match_total_amount,
- 'match_total_amount_param': account_reconcile_model.match_total_amount_param,
- 'match_partner': account_reconcile_model.match_partner,
- 'match_partner_ids': [(6, None, account_reconcile_model.match_partner_ids.ids)],
- 'match_partner_category_ids': [(6, None, account_reconcile_model.match_partner_category_ids.ids)],
- 'second_tax_ids': [[4, tax_template_ref[tax.id], 0] for tax in account_reconcile_model.second_tax_ids],
- }
+ 'name': account_reconcile_model.name,
+ 'sequence': account_reconcile_model.sequence,
+ 'company_id': company.id,
+ 'rule_type': account_reconcile_model.rule_type,
+ 'auto_reconcile': account_reconcile_model.auto_reconcile,
+ 'to_check': account_reconcile_model.to_check,
+ 'match_journal_ids': [(6, None, account_reconcile_model.match_journal_ids.ids)],
+ 'match_nature': account_reconcile_model.match_nature,
+ 'match_amount': account_reconcile_model.match_amount,
+ 'match_amount_min': account_reconcile_model.match_amount_min,
+ 'match_amount_max': account_reconcile_model.match_amount_max,
+ 'match_label': account_reconcile_model.match_label,
+ 'match_label_param': account_reconcile_model.match_label_param,
+ 'match_note': account_reconcile_model.match_note,
+ 'match_note_param': account_reconcile_model.match_note_param,
+ 'match_transaction_type': account_reconcile_model.match_transaction_type,
+ 'match_transaction_type_param': account_reconcile_model.match_transaction_type_param,
+ 'match_same_currency': account_reconcile_model.match_same_currency,
+ 'match_total_amount': account_reconcile_model.match_total_amount,
+ 'match_total_amount_param': account_reconcile_model.match_total_amount_param,
+ 'match_partner': account_reconcile_model.match_partner,
+ 'match_partner_ids': [(6, None, account_reconcile_model.match_partner_ids.ids)],
+ 'match_partner_category_ids': [(6, None, account_reconcile_model.match_partner_category_ids.ids)],
+ 'line_ids': [(0, 0, {
+ 'account_id': acc_template_ref[line.account_id.id],
+ 'label': line.label,
+ 'amount_type': line.amount_type,
+ 'force_tax_included': line.force_tax_included,
+ 'amount_string': line.amount_string,
+ 'tax_ids': [[4, tax_template_ref[tax.id], 0] for tax in line.tax_ids],
+ }) for line in account_reconcile_model_lines],
+ }
def generate_account_reconcile_model(self, tax_template_ref, acc_template_ref, company):
""" This method creates account reconcile models
@@ -1175,31 +1173,23 @@ class AccountReconcileModelTemplate(models.Model):
match_partner_category_ids = fields.Many2many('res.partner.category', string='Restrict Partner Categories to',
help='The reconciliation model will only be applied to the selected customer/vendor categories.')
- # First part fields.
+ line_ids = fields.One2many('account.reconcile.model.line.template', 'model_id')
+ decimal_separator = fields.Char(help="Every character that is nor a digit nor this separator will be removed from the matching string")
+
+
+class AccountReconcileModelLineTemplate(models.Model):
+ _name = "account.reconcile.model.line.template"
+ _description = 'Reconcile Model Line Template'
+
+ model_id = fields.Many2one('account.reconcile.model.template')
+ sequence = fields.Integer(required=True, default=10)
account_id = fields.Many2one('account.account.template', string='Account', ondelete='cascade', domain=[('deprecated', '=', False)])
label = fields.Char(string='Journal Item Label')
amount_type = fields.Selection([
('fixed', 'Fixed'),
('percentage', 'Percentage of balance'),
('regex', 'From label'),
- ], required=True, default='percentage')
- amount = fields.Float(string='Write-off Amount', digits=0, required=True, default=100.0, help="Fixed amount will count as a debit if it is negative, as a credit if it is positive.")
- amount_from_label_regex = fields.Char(string="Amount from Label (regex)", default=r"([\d\.,]+)")
- decimal_separator = fields.Char(help="Every character that is nor a digit nor this separator will be removed from the matching string")
- force_tax_included = fields.Boolean(string='Tax Included in Price',
- help='Force the tax to be managed as a price included tax.')
- # Second part fields.
- has_second_line = fields.Boolean(string='Add a second line', default=False)
+ ], required=True, default='percentage')
+ amount_string = fields.Char(string="Amount")
+ force_tax_included = fields.Boolean(string='Tax Included in Price', help='Force the tax to be managed as a price included tax.')
tax_ids = fields.Many2many('account.tax.template', string='Taxes', ondelete='restrict')
- second_account_id = fields.Many2one('account.account.template', string='Second Account', ondelete='cascade', domain=[('deprecated', '=', False)])
- second_label = fields.Char(string='Second Journal Item Label')
- second_amount_type = fields.Selection([
- ('fixed', 'Fixed'),
- ('percentage', 'Percentage of amount'),
- ('regex', 'From label'),
- ], string="Second Amount type",required=True, default='percentage')
- second_amount = fields.Float(string='Second Write-off Amount', digits=0, required=True, default=100.0, help="Fixed amount will count as a debit if it is negative, as a credit if it is positive.")
- second_amount_from_label_regex = fields.Char(string="Second Amount from Label (regex)", default=r"([\d\.,]+)")
- force_second_tax_included = fields.Boolean(string='Second Tax Included in Price',
- help='Force the second tax to be managed as a price included tax.')
- second_tax_ids = fields.Many2many('account.tax.template', relation='account_reconcile_model_tmpl_account_tax_bis_rel', string='Second Taxes', ondelete='restrict')
diff --git a/addons/account/security/account_security.xml b/addons/account/security/account_security.xml
index c665789497f..7b67561fc6d 100644
--- a/addons/account/security/account_security.xml
+++ b/addons/account/security/account_security.xml
@@ -180,6 +180,13 @@
['|',('company_id','=',False),('company_id', 'in', company_ids)]
+
+ Account reconcile model_line template company rule
+
+
+ ['|',('company_id','=',False),('company_id', 'in', company_ids)]
+
+
Account payment company rule
diff --git a/addons/account/security/ir.model.access.csv b/addons/account/security/ir.model.access.csv
index 5e43dbc88a0..58ecc502f4f 100644
--- a/addons/account/security/ir.model.access.csv
+++ b/addons/account/security/ir.model.access.csv
@@ -64,7 +64,9 @@ access_account_account_tax,account.account.tag,model_account_account_tag,account
access_account_account_tax_user,account.account.tag,model_account_account_tag,account.group_account_invoice,1,0,0,0
access_account_reconcile_model_billing,account.reconcile.model.billing,model_account_reconcile_model,account.group_account_invoice,1,0,1,0
access_account_reconcile_model,account.reconcile.model,model_account_reconcile_model,account.group_account_user,1,1,1,1
-access_account_reconcile_model_template,account.reconcile.model.template,model_account_reconcile_model_template,account.group_account_invoice,1,1,1,1
+access_account_reconcile_model_template,account.reconcile.model.template,model_account_reconcile_model_template,account.group_account_manager,1,1,1,1
+access_account_reconcile_model_line,account.reconcile.model.line,model_account_reconcile_model_line,account.group_account_user,1,1,1,1
+access_account_reconcile_model_line_template,account.reconcile.model.line.template,model_account_reconcile_model_line_template,account.group_account_manager,1,1,1,1
access_account_partial_reconcile_group_invoice,account.partial.reconcile.group.invoice,model_account_partial_reconcile,account.group_account_invoice,1,1,1,1
access_account_partial_reconcile,account.partial.reconcile,model_account_partial_reconcile,account.group_account_user,1,1,1,1
access_account_full_reconcile_group_invoice,account.full.reconcile.group.invoice,model_account_full_reconcile,account.group_account_invoice,1,1,1,1
diff --git a/addons/account/tests/test_reconciliation_matching_rules.py b/addons/account/tests/test_reconciliation_matching_rules.py
index 7ef983ae4d1..07f56b2ae7c 100644
--- a/addons/account/tests/test_reconciliation_matching_rules.py
+++ b/addons/account/tests/test_reconciliation_matching_rules.py
@@ -45,7 +45,7 @@ class TestReconciliationMatchingRules(AccountTestCommon):
})
cls.rule_1 = cls.rule_0.copy()
- cls.rule_1.account_id = current_assets_account
+ cls.rule_1.write({'line_ids': [(0, 0, {'account_id': current_assets_account.id})]})
cls.rule_1.match_partner = True
cls.rule_1.match_partner_ids |= cls.partner_1 + cls.partner_2
cls.rule_2 = cls.env['account.reconcile.model'].create({
@@ -53,7 +53,7 @@ class TestReconciliationMatchingRules(AccountTestCommon):
'rule_type': 'writeoff_suggestion',
'match_partner': True,
'match_partner_ids': [],
- 'account_id': current_assets_account.id,
+ 'line_ids': [(0, 0, {'account_id': current_assets_account.id})],
})
invoice_number = cls.invoice_line_1.move_id.name
@@ -67,14 +67,14 @@ class TestReconciliationMatchingRules(AccountTestCommon):
'statement_id': cls.bank_st.id,
'name': 'invoice %s-%s' % (invoice_number.split('/')[1], invoice_number.split('/')[2]),
'partner_id': cls.partner_1.id,
- 'amount': 100,
+ 'amount': '100',
'sequence': 1,
})
cls.bank_line_2 = cls.env['account.bank.statement.line'].create({
'statement_id': cls.bank_st.id,
'name': 'xxxxx',
'partner_id': cls.partner_1.id,
- 'amount': 600,
+ 'amount': '600',
'sequence': 2,
})
@@ -86,14 +86,14 @@ class TestReconciliationMatchingRules(AccountTestCommon):
'statement_id': cls.cash_st.id,
'name': 'yyyyy',
'partner_id': cls.partner_2.id,
- 'amount': -1000,
+ 'amount': '-1000',
'sequence': 1,
})
cls.tax21 = cls.env['account.tax'].create({
'name': '21%',
'type_tax_use': 'purchase',
- 'amount': 21,
+ 'amount': '21',
})
@classmethod
@@ -338,9 +338,11 @@ class TestReconciliationMatchingRules(AccountTestCommon):
self.rule_1.write({
'auto_reconcile': True,
- 'force_tax_included': True,
- 'tax_ids': [(6, 0, self.tax21.ids)],
'rule_type': 'writeoff_suggestion',
+ 'line_ids': [(1, self.rule_1.line_ids.id, {
+ 'force_tax_included': True,
+ 'tax_ids': [(6, 0, self.tax21.ids)],
+ })]
})
self.bank_line_2.unlink()
diff --git a/addons/account/tests/test_templates_consistency.py b/addons/account/tests/test_templates_consistency.py
index f91599cd552..40a89d8a124 100644
--- a/addons/account/tests/test_templates_consistency.py
+++ b/addons/account/tests/test_templates_consistency.py
@@ -61,7 +61,10 @@ class AccountingTestTemplConsistency(TransactionCase):
'''Test fields consistency for ('account.reconcile.model', 'account.reconcile.model.template')
'''
self.check_fields_consistency('account.reconcile.model.template', 'account.reconcile.model', exceptions=['chart_template_id'])
- self.check_fields_consistency('account.reconcile.model', 'account.reconcile.model.template', exceptions=['company_id', 'journal_id', 'analytic_account_id', 'second_journal_id', 'second_analytic_account_id', 'analytic_tag_ids', 'second_analytic_tag_ids'])
+ self.check_fields_consistency('account.reconcile.model', 'account.reconcile.model.template', exceptions=['company_id'])
+ # lines
+ self.check_fields_consistency('account.reconcile.model.line.template', 'account.reconcile.model.line', exceptions=['chart_template_id'])
+ self.check_fields_consistency('account.reconcile.model.line', 'account.reconcile.model.line.template', exceptions=['company_id', 'journal_id', 'analytic_account_id', 'analytic_tag_ids', 'amount'])
def test_account_group_fields(self):
'''Test fields consistency for ('account.group', 'account.group.template')
diff --git a/addons/account/views/account_journal_dashboard_view.xml b/addons/account/views/account_journal_dashboard_view.xml
index 8b5623ceebf..7fc2b3d27af 100644
--- a/addons/account/views/account_journal_dashboard_view.xml
+++ b/addons/account/views/account_journal_dashboard_view.xml
@@ -103,7 +103,7 @@
Reconciliation
diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml
index 8b041624cb2..0968754104d 100644
--- a/addons/account/views/account_view.xml
+++ b/addons/account/views/account_view.xml
@@ -802,6 +802,7 @@ action = model.setting_init_bank_account_action()
+
@@ -882,72 +883,68 @@ action = model.setting_init_bank_account_action()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- %
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- %
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ account.reconcile.model.line.form
+ account.reconcile.model.line
+
+
+
+
account.reconcile.model.tree
account.reconcile.model
@@ -955,9 +952,8 @@ action = model.setting_init_bank_account_action()
-
-
-
+
+
@@ -966,9 +962,9 @@ action = model.setting_init_bank_account_action()
account.reconcile.model
-
-
-
+
+
+
diff --git a/addons/l10n_be/data/account_reconcile_model_template.xml b/addons/l10n_be/data/account_reconcile_model_template.xml
index d2417090926..2d1ecee80d3 100644
--- a/addons/l10n_be/data/account_reconcile_model_template.xml
+++ b/addons/l10n_be/data/account_reconcile_model_template.xml
@@ -3,44 +3,59 @@
Escompte
+
+
+
percentage
- 100
+ 100
Escompte accordé
Frais bancaires HTVA
+
+
+
percentage
- 100
+ 100
Frais bancaires HTVA
Frais bancaires TVA21
+
+
+
percentage
- 100
+ 100
Frais bancaires TVA21
-
Virements internes
- percentage
- 100
- Virements internes
+
+
+
+ percentage
+ 100
+ Virements internes
+
-
Compte Attente
- percentage
- 100
-
+
+
+
+ percentage
+ 100
+
+
diff --git a/addons/l10n_de_skr03/data/account_reconcile_model_template.xml b/addons/l10n_de_skr03/data/account_reconcile_model_template.xml
index 779b5d3a776..e25ce0c1a75 100644
--- a/addons/l10n_de_skr03/data/account_reconcile_model_template.xml
+++ b/addons/l10n_de_skr03/data/account_reconcile_model_template.xml
@@ -3,57 +3,75 @@
Skonto-EK-7%
+
+
+
+
percentage
- 100
+ 100
Skonto-EK-7%
-
Skonto-EK-19%
+
+
+
+
percentage
- 100
+ 100
Skonto-EK-19%
-
Skonto-VK-7%
+
+
+
+
percentage
- 100
+ 100
Skonto-VK-7%
-
Skonto-VK-19%
+
+
+
+
percentage
- 100
+ 100
Skonto-VK-19%
-
Forderungsverlust-7%
+
+
+
+
percentage
- 100
+ 100
Forderungsverlust-7%
-
Forderungsverlust-19%
+
+
+
+
percentage
- 100
+ 100
Forderungsverlust-19%
-
-
\ No newline at end of file
+
diff --git a/addons/l10n_de_skr04/data/account_reconcile_model_template.xml b/addons/l10n_de_skr04/data/account_reconcile_model_template.xml
index 09025543fad..3f672eb180a 100644
--- a/addons/l10n_de_skr04/data/account_reconcile_model_template.xml
+++ b/addons/l10n_de_skr04/data/account_reconcile_model_template.xml
@@ -3,57 +3,75 @@
Skonto-EK-7%
+
+
+
+
percentage
- 100
+ 100
Skonto-EK-7%
-
Skonto-EK-19%
+
+
+
+
percentage
- 100
+ 100
Skonto-EK-19%
-
Skonto-VK-7%
+
+
+
+
percentage
- 100
+ 100
Skonto-VK-7%
-
Skonto-VK-19%
+
+
+
+
percentage
- 100
+ 100
Skonto-VK-19%
-
Forderungsverlust-7%
+
+
+
+
percentage
- 100
+ 100
Forderungsverlust-7%
-
Forderungsverlust-19%
+
+
+
+
percentage
- 100
+ 100
Forderungsverlust-19%
-
-
\ No newline at end of file
+
diff --git a/addons/l10n_fr/data/account_reconcile_model_template.xml b/addons/l10n_fr/data/account_reconcile_model_template.xml
index d098a0c1c2d..edee1e908eb 100644
--- a/addons/l10n_fr/data/account_reconcile_model_template.xml
+++ b/addons/l10n_fr/data/account_reconcile_model_template.xml
@@ -6,8 +6,11 @@
Frais bancaires
+
+
+
percentage
- 100
+ 100
diff --git a/addons/l10n_generic_coa/demo/account_reconcile_model.xml b/addons/l10n_generic_coa/demo/account_reconcile_model.xml
index 3be9c3a1bde..5934fdd0ebc 100644
--- a/addons/l10n_generic_coa/demo/account_reconcile_model.xml
+++ b/addons/l10n_generic_coa/demo/account_reconcile_model.xml
@@ -6,20 +6,29 @@
writeoff_suggestion
contains
BRT
+ ,
+
+
+
+
+ 1
Due amount
regex
- BRT: ([\d,]+)
- ,
-
- Bank Fees
- BRT: ([\d,]+)
+
+
+
+
+ 2
+ Bank Fees
+
- percentage
- 100
+ percentage
+ 100
diff --git a/addons/l10n_lu/data/account_reconcile_model_template_data.xml b/addons/l10n_lu/data/account_reconcile_model_template_data.xml
index c0762c77139..2aa33c598b4 100644
--- a/addons/l10n_lu/data/account_reconcile_model_template_data.xml
+++ b/addons/l10n_lu/data/account_reconcile_model_template_data.xml
@@ -3,19 +3,25 @@
Bank Fees
+ writeoff_button
+
+
+
percentage
- 100
+ 100
Bank Fees
- writeoff_button
Cash Discount
-
- percentage
- 100
- Cash Discount
writeoff_button
+
+
+
+ percentage
+ 100
+ Cash Discount
+
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index ed0bcc3e8c8..61ecb3af1da 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -2756,6 +2756,13 @@ var FieldSelection = AbstractField.extend({
var required = this.attrs.modifiersValue && this.attrs.modifiersValue.required;
for (var i = 0 ; i < this.values.length ; i++) {
var disabled = required && this.values[i][0] === false;
+ console.log(this.values);
+ console.log(i);
+ console.log(this.values[i])
+ // console.log(this.values[i][0])
+ if (this.values[i] == undefined) {
+ debugger
+ }
this.$el.append($('', {
value: JSON.stringify(this.values[i][0]),