mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[ADD] create sql-view for lines violating rules
This commit is contained in:
committed by
Iryna Vyshnevska
parent
f71235ef40
commit
447abc40cf
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import models
|
||||
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import account_move_line
|
||||
@@ -1,2 +0,0 @@
|
||||
Prohibits items reconcilation for different partners, and items with partner and
|
||||
without it.
|
||||
4
account_reconcile_restrict_partner_mismatch/__init__.py
Executable file
4
account_reconcile_restrict_partner_mismatch/__init__.py
Executable file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
from . import report
|
||||
@@ -3,8 +3,9 @@
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
'name': 'Account Partner Reconciliation',
|
||||
'summary': 'Allows run reconciliation only for same partner',
|
||||
'name': 'Reconcile restrict partner mismatch',
|
||||
'summary': 'Restrict reconciliation on receivable '
|
||||
'and payable accounts to the same partner',
|
||||
'version': '10.0.1.0.0',
|
||||
'depends': ['account'],
|
||||
'author': 'Camptocamp, Odoo Community Association (OCA)',
|
||||
@@ -12,7 +13,8 @@
|
||||
'category': 'Finance',
|
||||
'license': 'AGPL-3',
|
||||
'data': [
|
||||
'report/account_move_lines_report.xml'
|
||||
'report/account_move_lines_report.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
3
account_reconcile_restrict_partner_mismatch/models/__init__.py
Executable file
3
account_reconcile_restrict_partner_mismatch/models/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_move_line
|
||||
@@ -12,7 +12,8 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
@api.multi
|
||||
def reconcile(self, writeoff_acc_id=False, writeoff_journal_id=False):
|
||||
if config['test_enable']:
|
||||
if (config['test_enable']
|
||||
and not self.env.context.get('test_partner_mismatch')):
|
||||
return super(AccountMoveLine, self).reconcile(
|
||||
writeoff_acc_id, writeoff_journal_id)
|
||||
|
||||
@@ -21,13 +22,10 @@ class AccountMoveLine(models.Model):
|
||||
return True
|
||||
partners = set()
|
||||
for line in self:
|
||||
if (line.account_id.internal_type in ('receivable', 'payable')):
|
||||
if line.account_id.internal_type in ('receivable', 'payable'):
|
||||
partners.add(line.partner_id.id)
|
||||
if len(partners) > 1:
|
||||
raise UserError(_('The partner has to be the same on all'
|
||||
' lines for receivable and payable accounts!'))
|
||||
if len(partners) and not all([l.partner_id for l in self]):
|
||||
raise UserError(_('You cannot match entries with and '
|
||||
'without partner!'))
|
||||
return super(AccountMoveLine, self).reconcile(
|
||||
writeoff_acc_id, writeoff_journal_id)
|
||||
@@ -0,0 +1,10 @@
|
||||
This module restricts reconciliation between journal items when:
|
||||
|
||||
- both items have different partners
|
||||
- one item is with partner and the other without it
|
||||
|
||||
This rule applies only for journal items using receivable and payable account type.
|
||||
|
||||
As at the moment of installation some journal items could have been reconciled
|
||||
using different partners, you can detect them in menu Accounting > Adviser >
|
||||
Reconciled items with partner mismatch.
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import report_reconciled_lines
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_account_move_reconciled_report_tree" model="ir.ui.view">
|
||||
<field name="name">Reconciled items with partner mismatch</field>
|
||||
<field name="model">account.reconcile.partner.mismatch.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Reconciled items with partner mismatch" create="false" delete="false" edit="false">
|
||||
<!-- links are not clickable in tree view
|
||||
only after open form view -->
|
||||
<field name="partial_reconcile_id" />
|
||||
<field name="full_reconcile_id" />
|
||||
<field name="debit_move_id" />
|
||||
<field name="debit_amount" />
|
||||
<field name="debit_partner_id" />
|
||||
<field name="credit_move_id" />
|
||||
<field name="credit_amount" />
|
||||
<field name="credit_partner_id" />
|
||||
<field name="account_type_id" />
|
||||
<field name="account_id" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_reconcile_partner_mismatch_report_view_form" model="ir.ui.view">
|
||||
<field name="name">account.reconcile.partner.mismatch.report.form</field>
|
||||
<field name="model">account.reconcile.partner.mismatch.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Reconciled items with partner mismatch" create="false" delete="false" edit="false">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="partial_reconcile_id" />
|
||||
<field name="full_reconcile_id" />
|
||||
<field name="debit_amount" />
|
||||
<field name="credit_amount" />
|
||||
<field name="debit_partner_id" />
|
||||
<field name="credit_partner_id" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="account_id" />
|
||||
<field name="account_type_id" />
|
||||
<field name="debit_move_id" />
|
||||
<field name="credit_move_id" />
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_reconcile_partner_mismatch_report" model="ir.actions.act_window">
|
||||
<field name="name">Reconciled items with partner mismatch</field>
|
||||
<field name="res_model">account.reconcile.partner.mismatch.report</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_account_reconcile_partner_mismatch_report"
|
||||
parent="account.menu_finance_entries" sequence="80"
|
||||
action="action_account_reconcile_partner_mismatch_report"
|
||||
name="Reconciled items with partner mismatch"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 Camptocamp SA
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
|
||||
from odoo import api, fields, models, tools
|
||||
|
||||
|
||||
class AccountReconcilePartnerMismatchReport(models.Model):
|
||||
_name = 'account.reconcile.partner.mismatch.report'
|
||||
_auto = False
|
||||
|
||||
partial_reconcile_id = fields.Many2one(
|
||||
'account.partial.reconcile',
|
||||
string="Partial Reconcile"
|
||||
)
|
||||
full_reconcile_id = fields.Many2one('account.full.reconcile')
|
||||
account_id = fields.Many2one(
|
||||
'account.account',
|
||||
string="Account"
|
||||
)
|
||||
account_type_id = fields.Many2one(
|
||||
'account.account.type',
|
||||
string="Account type",
|
||||
)
|
||||
debit_move_id = fields.Many2one('account.move.line', string="Debit move")
|
||||
debit_amount = fields.Float("Debit amount")
|
||||
debit_partner_id = fields.Many2one('res.partner', string="Debit partner")
|
||||
credit_move_id = fields.Many2one('account.move.line', string="Credit move")
|
||||
credit_amount = fields.Float("Credit amount")
|
||||
credit_partner_id = fields.Many2one('res.partner', string="Credit partner")
|
||||
|
||||
@api.model_cr
|
||||
def init(self):
|
||||
"""Select lines which violate defined rules"""
|
||||
tools.drop_view_if_exists(self.env.cr, self._table)
|
||||
self._cr.execute(
|
||||
"""CREATE OR REPLACE VIEW %s AS (
|
||||
SELECT pr.id id
|
||||
, pr.id partial_reconcile_id
|
||||
, pr.full_reconcile_id
|
||||
, pr.debit_move_id
|
||||
, daml.debit debit_amount
|
||||
, aat.id account_type_id
|
||||
, daml.partner_id debit_partner_id
|
||||
, daml.account_id account_id
|
||||
, pr.credit_move_id
|
||||
, caml.credit credit_amount
|
||||
, caml.partner_id credit_partner_id
|
||||
FROM account_partial_reconcile pr
|
||||
LEFT JOIN account_move_line daml
|
||||
ON daml.id = pr.debit_move_id
|
||||
LEFT JOIN account_move_line caml
|
||||
ON caml.id = pr.credit_move_id
|
||||
LEFT JOIN account_account_type aat
|
||||
ON daml.user_type_id = aat.id
|
||||
WHERE aat.type in ('receivable', 'payable')
|
||||
AND (daml.partner_id <> caml.partner_id
|
||||
OR (daml.partner_id IS NULL
|
||||
AND caml.partner_id IS NOT NULL)
|
||||
OR (caml.partner_id IS NULL
|
||||
AND daml.partner_id IS NOT NULL))
|
||||
)
|
||||
"""
|
||||
% self._table
|
||||
)
|
||||
@@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_account_reconcile_partner_mismatch_report,access_account_reconcile_partner_mismatch_report,model_account_reconcile_partner_mismatch_report,account.group_account_user,1,0,0,0
|
||||
|
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
@@ -0,0 +1 @@
|
||||
from . import test_reconciliation
|
||||
@@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 Camptocamp SA
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class TestReconciliation(AccountingTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestReconciliation, self).setUp()
|
||||
self.env = self.env(context=dict(
|
||||
self.env.context, tracking_disable=True,
|
||||
test_partner_mismatch=True)
|
||||
)
|
||||
|
||||
self.partner = self.env.ref("base.res_partner_2")
|
||||
self.partner_id = self.partner.id
|
||||
rec_type = self.env['account.account'].search([
|
||||
('user_type_id', '=',
|
||||
self.env.ref('account.data_account_type_receivable').id)
|
||||
], limit=1)
|
||||
pay_type = self.env['account.account'].search([
|
||||
('user_type_id', '=',
|
||||
self.env.ref('account.data_account_type_payable').id)
|
||||
], limit=1)
|
||||
self.account_rcv = (self.partner.property_account_receivable_id
|
||||
or rec_type)
|
||||
self.account_rsa = self.partner.property_account_payable_id or pay_type
|
||||
|
||||
self.bank_journal = self.env['account.journal']. \
|
||||
create({'name': 'Bank', 'type': 'bank', 'code': 'BNK67'})
|
||||
self.aml = self.init_moves()
|
||||
self.wizard = self.env['account.move.line.reconcile.writeoff']. \
|
||||
with_context(active_ids=[x.id for x in self.aml]).create({
|
||||
'journal_id': self.bank_journal.id,
|
||||
'writeoff_acc_id': self.account_rsa.id
|
||||
})
|
||||
|
||||
def create_move(self, name, amount):
|
||||
debit_line_vals = {
|
||||
'name': name,
|
||||
'debit': amount > 0 and amount or 0.0,
|
||||
'credit': amount < 0 and -amount or 0.0,
|
||||
'account_id': self.account_rcv.id,
|
||||
}
|
||||
credit_line_vals = debit_line_vals.copy()
|
||||
credit_line_vals['debit'] = debit_line_vals['credit']
|
||||
credit_line_vals['credit'] = debit_line_vals['debit']
|
||||
credit_line_vals['account_id'] = self.account_rsa.id
|
||||
vals = {
|
||||
'journal_id': self.bank_journal.id,
|
||||
'line_ids': [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
|
||||
}
|
||||
return self.env['account.move'].create(vals).id
|
||||
|
||||
def init_moves(self):
|
||||
move_list_vals = [
|
||||
('1', -1.83),
|
||||
('2', 728.35),
|
||||
('3', -4.46),
|
||||
('4', 0.32),
|
||||
('5', 14.72),
|
||||
('6', -737.10),
|
||||
]
|
||||
move_ids = []
|
||||
for name, amount in move_list_vals:
|
||||
move_ids.append(self.create_move(name, amount))
|
||||
aml_recs = self.env['account.move.line'].search([
|
||||
('move_id', 'in', move_ids),
|
||||
('account_id', '=', self.account_rcv.id)
|
||||
])
|
||||
return aml_recs
|
||||
|
||||
def test_reconcile_no_partner(self):
|
||||
self.wizard.trans_rec_reconcile()
|
||||
self.assertTrue(all(self.aml.mapped('reconciled')))
|
||||
|
||||
def test_reconcile_partner_mismatch(self):
|
||||
self.aml[0].partner_id = self.partner.id
|
||||
with self.assertRaises(UserError):
|
||||
self.wizard.trans_rec_reconcile()
|
||||
# all lines with same partner allowed
|
||||
self.aml.write({'partner_id': self.partner.id})
|
||||
self.wizard.trans_rec_reconcile()
|
||||
self.assertTrue(all(self.aml.mapped('reconciled')))
|
||||
|
||||
def test_reconcile_accounts_excluded(self):
|
||||
self.aml[0].partner_id = self.partner.id
|
||||
with self.assertRaises(UserError):
|
||||
self.wizard.trans_rec_reconcile()
|
||||
# reconciliation forbiden only for certain types of accounts
|
||||
account = self.env['account.account'].search([
|
||||
('user_type_id.type', '=', 'other')
|
||||
], limit=1)
|
||||
account.reconcile = True
|
||||
self.aml[0].account_id = account.id
|
||||
with self.assertRaises(UserError):
|
||||
self.wizard.trans_rec_reconcile()
|
||||
# reconciliation for different partners allowed
|
||||
# for not forbidden types
|
||||
self.aml.write({'account_id': account.id})
|
||||
self.wizard.trans_rec_reconcile()
|
||||
self.assertTrue(all(self.aml.mapped('reconciled')))
|
||||
Reference in New Issue
Block a user