mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[IMP] account_easy_reconcile: add YAML tests
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
==============
|
||||
Easy Reconcile
|
||||
==============
|
||||
|
||||
@@ -27,11 +29,21 @@ You may be interested to install also the
|
||||
This latter add more complex reconciliations,
|
||||
allows multiple lines and partial.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Go to 'Invoicing/Periodic Processing/Reconciliation/Easy Automatic Reconcile' to start a
|
||||
new easy reconcile.
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/98/8.0
|
||||
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/{project_repo}/issues>`_.
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/bank-statement-reconcile/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
|
||||
`here <https://github.com/OCA/bank-statement-reconcile/issues/new?body=module:%20account_easy_reconcile%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
@@ -73,4 +85,3 @@ mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit http://odoo-community.org.
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012 Camptocamp SA (Guewen Baconnier)
|
||||
# Copyright 2012, 2015 Camptocamp SA (Guewen Baconnier, Damien Crier)
|
||||
# Copyright (C) 2010 Sébastien Beau
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012 Camptocamp SA (Guewen Baconnier)
|
||||
# Copyright 2012, 2015 Camptocamp SA (Guewen Baconnier, Damien Crier)
|
||||
# Copyright (C) 2010 Sébastien Beau
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -22,7 +21,7 @@
|
||||
|
||||
{
|
||||
"name": "Easy Reconcile",
|
||||
"version": "1.3.1",
|
||||
"version": "8.0.1.3.1",
|
||||
"depends": ["account"],
|
||||
"author": "Akretion,Camptocamp,Odoo Community Association (OCA)",
|
||||
"website": "http://www.akretion.com/",
|
||||
@@ -33,6 +32,8 @@
|
||||
"security/ir.model.access.csv",
|
||||
"res_config_view.xml",
|
||||
],
|
||||
"test": ['test/easy_reconcile.yml',
|
||||
],
|
||||
'license': 'AGPL-3',
|
||||
"auto_install": False,
|
||||
'installable': True,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier)
|
||||
# Copyright 2012-2013, 2015 Camptocamp SA (Guewen Baconnier, Damien Crier)
|
||||
# Copyright (C) 2010 Sébastien Beau
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -21,6 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
from openerp import models, api, fields
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from operator import itemgetter, attrgetter
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ class EasyReconcileBase(models.AbstractModel):
|
||||
params = []
|
||||
if self.filter:
|
||||
dummy, where, params = ml_obj._where_calc(
|
||||
eval(self.filter)).get_sql()
|
||||
safe_eval(self.filter)).get_sql()
|
||||
if where:
|
||||
where = " AND %s" % where
|
||||
return where, params
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier)
|
||||
# Copyright 2012-2013, 2015 Camptocamp SA (Guewen Baconnier, Damien Crier)
|
||||
# Copyright (C) 2010 Sébastien Beau
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -25,8 +24,6 @@ from openerp import models, api, fields, _
|
||||
from openerp.exceptions import Warning
|
||||
from openerp import sql_db
|
||||
|
||||
# from openerp import pooler
|
||||
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -177,7 +174,7 @@ class AccountEasyReconcile(models.Model):
|
||||
readonly=True
|
||||
)
|
||||
last_history = fields.Many2one('easy.reconcile.history',
|
||||
string='readonly=True',
|
||||
string='Last history', readonly=True,
|
||||
compute='_last_history',
|
||||
)
|
||||
company_id = fields.Many2one('res.company', string='Company')
|
||||
@@ -225,75 +222,69 @@ class AccountEasyReconcile(models.Model):
|
||||
else:
|
||||
new_cr = self.env.cr
|
||||
|
||||
uid, context = self.env.uid, self.env.context
|
||||
with api.Environment.manage():
|
||||
self.env = api.Environment(new_cr, uid, context)
|
||||
try:
|
||||
all_ml_rec_ids = []
|
||||
all_ml_partial_ids = []
|
||||
|
||||
try:
|
||||
all_ml_rec_ids = []
|
||||
all_ml_partial_ids = []
|
||||
for method in rec.reconcile_method:
|
||||
rec_model = self.env[method.name]
|
||||
auto_rec_id = rec_model.create(
|
||||
self._prepare_run_transient(method)
|
||||
)
|
||||
|
||||
for method in rec.reconcile_method:
|
||||
rec_model = self.env[method.name]
|
||||
auto_rec_id = rec_model.create(
|
||||
self._prepare_run_transient(method)
|
||||
)
|
||||
ml_rec_ids, ml_partial_ids = (
|
||||
auto_rec_id.automatic_reconcile()
|
||||
)
|
||||
|
||||
ml_rec_ids, ml_partial_ids = (
|
||||
auto_rec_id.automatic_reconcile()
|
||||
)
|
||||
all_ml_rec_ids += ml_rec_ids
|
||||
all_ml_partial_ids += ml_partial_ids
|
||||
|
||||
all_ml_rec_ids += ml_rec_ids
|
||||
all_ml_partial_ids += ml_partial_ids
|
||||
|
||||
reconcile_ids = find_reconcile_ids(
|
||||
'reconcile_id',
|
||||
all_ml_rec_ids
|
||||
)
|
||||
partial_ids = find_reconcile_ids(
|
||||
'reconcile_partial_id',
|
||||
all_ml_partial_ids
|
||||
)
|
||||
|
||||
self.env['easy.reconcile.history'].create(
|
||||
{
|
||||
'easy_reconcile_id': rec.id,
|
||||
'date': fields.datetime.now(),
|
||||
'reconcile_ids': [
|
||||
(4, rid) for rid in reconcile_ids
|
||||
],
|
||||
'reconcile_partial_ids': [
|
||||
(4, rid) for rid in partial_ids
|
||||
],
|
||||
})
|
||||
except Exception as e:
|
||||
# In case of error, we log it in the mail thread, log the
|
||||
# stack trace and create an empty history line; otherwise,
|
||||
# the cron will just loop on this reconcile task.
|
||||
_logger.exception(
|
||||
"The reconcile task %s had an exception: %s",
|
||||
rec.name, e.message
|
||||
)
|
||||
message = "There was an error during reconciliation : %s" \
|
||||
% e.message
|
||||
rec.message_post(body=message)
|
||||
self.env['easy.reconcile.history'].create(
|
||||
{
|
||||
'easy_reconcile_id': rec.id,
|
||||
'date': fields.Datetime.now(),
|
||||
'reconcile_ids': [],
|
||||
'reconcile_partial_ids': [],
|
||||
}
|
||||
)
|
||||
finally:
|
||||
if ctx['commit_every']:
|
||||
new_cr.commit()
|
||||
new_cr.close()
|
||||
reconcile_ids = find_reconcile_ids(
|
||||
'reconcile_id',
|
||||
all_ml_rec_ids
|
||||
)
|
||||
partial_ids = find_reconcile_ids(
|
||||
'reconcile_partial_id',
|
||||
all_ml_partial_ids
|
||||
)
|
||||
self.env['easy.reconcile.history'].create(
|
||||
{
|
||||
'easy_reconcile_id': rec.id,
|
||||
'date': fields.Datetime.now(),
|
||||
'reconcile_ids': [
|
||||
(4, rid) for rid in reconcile_ids
|
||||
],
|
||||
'reconcile_partial_ids': [
|
||||
(4, rid) for rid in partial_ids
|
||||
],
|
||||
})
|
||||
except Exception as e:
|
||||
# In case of error, we log it in the mail thread, log the
|
||||
# stack trace and create an empty history line; otherwise,
|
||||
# the cron will just loop on this reconcile task.
|
||||
_logger.exception(
|
||||
"The reconcile task %s had an exception: %s",
|
||||
rec.name, e.message
|
||||
)
|
||||
message = _("There was an error during reconciliation : %s") \
|
||||
% e.message
|
||||
rec.message_post(body=message)
|
||||
self.env['easy.reconcile.history'].create(
|
||||
{
|
||||
'easy_reconcile_id': rec.id,
|
||||
'date': fields.Datetime.now(),
|
||||
'reconcile_ids': [],
|
||||
'reconcile_partial_ids': [],
|
||||
}
|
||||
)
|
||||
finally:
|
||||
if ctx['commit_every']:
|
||||
new_cr.commit()
|
||||
new_cr.close()
|
||||
|
||||
return True
|
||||
|
||||
# @api.model
|
||||
# def _no_history(self, rec):
|
||||
@api.multi
|
||||
def _no_history(self):
|
||||
""" Raise an `orm.except_orm` error, supposed to
|
||||
be called when there is no history on the reconciliation
|
||||
@@ -332,7 +323,8 @@ class AccountEasyReconcile(models.Model):
|
||||
|
||||
@api.multi
|
||||
def open_partial_reconcile(self):
|
||||
""" Open the view of move line with the unreconciled move lines"""
|
||||
""" Open the view of move line with the partially
|
||||
reconciled move lines"""
|
||||
self.ensure_one()
|
||||
obj_move_line = self.env['account.move.line']
|
||||
lines = obj_move_line.search(
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
# Author: Guewen Baconnier, Damien Crier
|
||||
# Copyright 2012, 2015 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -33,7 +32,7 @@ class EasyReconcileHistory(models.Model):
|
||||
|
||||
@api.one
|
||||
@api.depends('reconcile_ids', 'reconcile_partial_ids')
|
||||
def _reconcile_line_ids(self):
|
||||
def _get_reconcile_line_ids(self):
|
||||
move_line_ids = []
|
||||
for reconcile in self.reconcile_ids:
|
||||
move_lines = reconcile.mapped('line_id')
|
||||
@@ -68,13 +67,13 @@ class EasyReconcileHistory(models.Model):
|
||||
comodel_name='account.move.line',
|
||||
relation='account_move_line_history_rel',
|
||||
string='Reconciled Items',
|
||||
_compute='_reconcile_line_ids'
|
||||
compute='_get_reconcile_line_ids'
|
||||
)
|
||||
partial_line_ids = fields.Many2many(
|
||||
comodel_name='account.move.line',
|
||||
relation='account_move_line_history_partial_rel',
|
||||
string='Partially Reconciled Items',
|
||||
_compute='_reconcile_line_ids'
|
||||
compute='_get_reconcile_line_ids'
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
@@ -97,16 +96,11 @@ class EasyReconcileHistory(models.Model):
|
||||
"rec_type must be 'full' or 'partial'"
|
||||
move_line_ids = []
|
||||
if rec_type == 'full':
|
||||
move_line_ids = []
|
||||
for reconcile in self.reconcile_ids:
|
||||
move_lines = reconcile.mapped('line_id')
|
||||
move_line_ids.extend(move_lines.ids)
|
||||
move_line_ids = self.mapped('reconcile_ids.line_id').ids
|
||||
name = _('Reconciliations')
|
||||
else:
|
||||
move_line_ids = []
|
||||
for reconcile in self.reconcile_partial_ids:
|
||||
move_lines = reconcile.mapped('line_partial_ids')
|
||||
move_line_ids.extend(move_lines.ids)
|
||||
move_line_ids = self.mapped(
|
||||
'reconcile_partial_ids.line_partial_ids').ids
|
||||
name = _('Partial Reconciliations')
|
||||
return {
|
||||
'name': name,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Leonardo Pistone
|
||||
# Copyright 2014 Camptocamp SA
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
# Author: Leonardo Pistone, Damien Crier
|
||||
# Copyright 2014, 2015 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -30,7 +29,7 @@ class AccountConfigSettings(models.TransientModel):
|
||||
related="company_id.reconciliation_commit_every",
|
||||
string="How often to commit when performing automatic "
|
||||
"reconciliation.",
|
||||
help="""Leave zero to commit only at the end of the process."""
|
||||
help="Leave zero to commit only at the end of the process."
|
||||
)
|
||||
|
||||
@api.multi
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier)
|
||||
# Copyright 2012-2013, 2015 Camptocamp SA (Guewen Baconnier, Damien Crier)
|
||||
# Copyright (C) 2010 Sébastien Beau
|
||||
# Copyright 2015 Camptocamp SA (Damien Crier)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
@@ -32,7 +31,7 @@ class EasyReconcileSimple(models.AbstractModel):
|
||||
# field name used as key for matching the move lines
|
||||
_key_field = None
|
||||
|
||||
@api.model
|
||||
@api.multi
|
||||
def rec_auto_lines_simple(self, lines):
|
||||
if self._key_field is None:
|
||||
raise ValueError("_key_field has to be defined")
|
||||
@@ -70,7 +69,7 @@ class EasyReconcileSimple(models.AbstractModel):
|
||||
|
||||
def _action_rec(self):
|
||||
"""Match only 2 move lines, do not allow partial reconcile"""
|
||||
select = self._select(self)
|
||||
select = self._select()
|
||||
select += ", account_move_line.%s " % self._key_field
|
||||
where, params = self._where()
|
||||
where += " AND account_move_line.%s IS NOT NULL " % self._key_field
|
||||
|
||||
116
account_easy_reconcile/test/easy_reconcile.yml
Normal file
116
account_easy_reconcile/test/easy_reconcile.yml
Normal file
@@ -0,0 +1,116 @@
|
||||
-
|
||||
In order to test Confirm Draft Invoice wizard I create an invoice and confirm it with this wizard
|
||||
-
|
||||
!record {model: account.invoice, id: account_invoice_state2}:
|
||||
account_id: account.a_recv
|
||||
company_id: base.main_company
|
||||
currency_id: base.EUR
|
||||
invoice_line:
|
||||
- account_id: account.a_sale
|
||||
name: '[PCSC234] PC Assemble SC234'
|
||||
price_unit: 1000.0
|
||||
quantity: 1.0
|
||||
product_id: product.product_product_3
|
||||
uos_id: product.product_uom_unit
|
||||
journal_id: account.bank_journal
|
||||
partner_id: base.res_partner_12
|
||||
reference_type: none
|
||||
-
|
||||
I called the "Confirm Draft Invoices" wizard
|
||||
-
|
||||
!record {model: account.invoice.confirm, id: account_invoice_confirm_0}:
|
||||
{}
|
||||
-
|
||||
I clicked on Confirm Invoices Button
|
||||
-
|
||||
!python {model: account.invoice.confirm}: |
|
||||
self.invoice_confirm(cr, uid, [ref("account_invoice_confirm_0")], {"lang": 'en_US',
|
||||
"tz": False, "active_model": "account.invoice", "active_ids": [ref("account_invoice_state2")],
|
||||
"type": "out_invoice", "active_id": ref("account_invoice_state2"), })
|
||||
-
|
||||
I check that customer invoice state is "Open"
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_state2}:
|
||||
- state == 'open'
|
||||
|
||||
|
||||
-
|
||||
In order to test Bank Statement feature of account I create a bank statement line and confirm it and check it's move created
|
||||
-
|
||||
I select the period and journal for the bank statement
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
import time
|
||||
journal = self._default_journal_id(cr, uid, {'lang': u'en_US', 'tz': False, 'active_model': 'ir.ui.menu',
|
||||
'journal_type': 'bank', 'period_id': time.strftime('%m'), 'active_ids': [ref('account.menu_bank_statement_tree')], 'active_id': ref('account.menu_bank_statement_tree')})
|
||||
assert journal, 'Journal has not been selected'
|
||||
-
|
||||
I create a bank statement with Opening and Closing balance 0.
|
||||
-
|
||||
!record {model: account.bank.statement, id: account_bank_statement_0}:
|
||||
balance_end_real: 0.0
|
||||
balance_start: 0.0
|
||||
date: !eval time.strftime('%Y-%m-%d')
|
||||
journal_id: account.bank_journal
|
||||
-
|
||||
I create bank statement line
|
||||
-
|
||||
!python {model: account.bank.statement.line}: |
|
||||
vals = {
|
||||
'amount': 1000.0,
|
||||
'partner_id': ref('base.res_partner_12'),
|
||||
'statement_id': ref('account_bank_statement_0'),
|
||||
'name': 'EXT001'
|
||||
}
|
||||
|
||||
line_id = self.create(cr, uid, vals)
|
||||
assert line_id, "Account bank statement line has not been created"
|
||||
|
||||
-
|
||||
We process the reconciliation of the invoice line
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
line_id = None
|
||||
invoice = self.pool.get('account.invoice').browse(cr, uid, ref("account_invoice_state2"))
|
||||
for l in invoice.move_id.line_id:
|
||||
if l.account_id.id == ref('account.a_recv'):
|
||||
line_id = l
|
||||
break
|
||||
statement = self.browse(cr, uid, ref("account_bank_statement_0"))
|
||||
for statement_line in statement.line_ids:
|
||||
self.pool.get('account.bank.statement.line').process_reconciliation(
|
||||
cr, uid, statement_line.id,
|
||||
[
|
||||
{
|
||||
'counterpart_move_line_id': line_id.id,
|
||||
'credit': 1000.0,
|
||||
'debit': 0.0,
|
||||
'name': line_id.name
|
||||
}
|
||||
]
|
||||
)
|
||||
-
|
||||
We unreconcile previous reconciliation so we can create an easy reconcile record to reconcile invoice
|
||||
-
|
||||
!python {model: account.move.line}: |
|
||||
lines_to_unreconcile = self.search(cr, uid, [('reconcile_ref', '!=', False), ('statement_id', '=', ref("account_bank_statement_0"))])
|
||||
self._remove_move_reconcile(cr, uid, lines_to_unreconcile)
|
||||
|
||||
-
|
||||
We create the easy reconcile record
|
||||
-
|
||||
!record {model: account.easy.reconcile, id: account_easy_reconcile_0}:
|
||||
name: 'easy reconcile 1'
|
||||
account: account.a_recv
|
||||
reconcile_method:
|
||||
- name: 'easy.reconcile.simple.partner'
|
||||
-
|
||||
We call the automatic reconcilation method
|
||||
-
|
||||
!python {model: account.easy.reconcile}: |
|
||||
self.run_reconcile(cr, uid, [ref('account_easy_reconcile_0')])
|
||||
-
|
||||
I check that customer invoice state is "Paid"
|
||||
-
|
||||
!assert {model: account.invoice, id: account_invoice_state2}:
|
||||
- state == 'paid'
|
||||
@@ -22,3 +22,4 @@
|
||||
from . import test_onchange_company
|
||||
from . import test_reconcile_history
|
||||
from . import test_reconcile
|
||||
from . import test_scenario_reconcile
|
||||
|
||||
298
account_easy_reconcile/tests/test_scenario_reconcile.py
Normal file
298
account_easy_reconcile/tests/test_scenario_reconcile.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Damien Crier
|
||||
# Copyright 2015 Camptocamp SA
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tests import common
|
||||
import time
|
||||
|
||||
|
||||
class testScenarioReconcile(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(testScenarioReconcile, self).setUp()
|
||||
self.rec_history_obj = self.registry('easy.reconcile.history')
|
||||
self.easy_rec_obj = self.registry('account.easy.reconcile')
|
||||
self.invoice_obj = self.registry('account.invoice')
|
||||
self.bk_stmt_obj = self.registry('account.bank.statement')
|
||||
self.bk_stmt_line_obj = self.registry('account.bank.statement.line')
|
||||
self.acc_move_line_obj = self.registry('account.move.line')
|
||||
self.easy_rec_method_obj = (
|
||||
self.registry('account.easy.reconcile.method')
|
||||
)
|
||||
self.account_fx_income_id = self.ref("account.income_fx_income")
|
||||
self.account_fx_expense_id = self.ref("account.income_fx_expense")
|
||||
self.acs_model = self.registry('account.config.settings')
|
||||
|
||||
acs_ids = self.acs_model.search(
|
||||
self.cr, self.uid,
|
||||
[('company_id', '=', self.ref("base.main_company"))]
|
||||
)
|
||||
|
||||
values = {'group_multi_currency': True,
|
||||
'income_currency_exchange_account_id':
|
||||
self.account_fx_income_id,
|
||||
'expense_currency_exchange_account_id':
|
||||
self.account_fx_expense_id}
|
||||
|
||||
if acs_ids:
|
||||
self.acs_model.write(self.cr, self.uid, acs_ids, values)
|
||||
else:
|
||||
default_vals = self.acs_model.default_get(self.cr, self.uid, [])
|
||||
default_vals.update(values)
|
||||
default_vals['date_stop'] = time.strftime('%Y-12-31')
|
||||
default_vals['date_start'] = time.strftime('%Y-%m-%d')
|
||||
default_vals['period'] = 'month'
|
||||
self.acs_model.create(self.cr, self.uid, default_vals)
|
||||
|
||||
def test_scenario_reconcile(self):
|
||||
# create invoice
|
||||
inv_id = self.invoice_obj.create(
|
||||
self.cr,
|
||||
self.uid,
|
||||
{
|
||||
'type': 'out_invoice',
|
||||
'account_id': self.ref('account.a_recv'),
|
||||
'company_id': self.ref('base.main_company'),
|
||||
'currency_id': self.ref('base.EUR'),
|
||||
'journal_id': self.ref('account.sales_journal'),
|
||||
'partner_id': self.ref('base.res_partner_12'),
|
||||
'invoice_line': [
|
||||
(0, 0, {
|
||||
'name': '[PCSC234] PC Assemble SC234',
|
||||
'price_unit': 1000.0,
|
||||
'quantity': 1.0,
|
||||
'product_id': self.ref('product.product_product_3'),
|
||||
'uos_id': self.ref('product.product_uom_unit'),
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
# validate invoice
|
||||
self.invoice_obj.signal_workflow(
|
||||
self.cr,
|
||||
self.uid,
|
||||
[inv_id],
|
||||
'invoice_open'
|
||||
)
|
||||
invoice_record = self.invoice_obj.browse(self.cr, self.uid, [inv_id])
|
||||
self.assertEqual('open', invoice_record.state)
|
||||
|
||||
# create bank_statement
|
||||
bk_stmt_id = self.bk_stmt_obj.create(
|
||||
self.cr,
|
||||
self.uid,
|
||||
{
|
||||
'balance_end_real': 0.0,
|
||||
'balance_start': 0.0,
|
||||
'date': time.strftime('%Y-%m-%d'),
|
||||
'journal_id': self.ref('account.bank_journal'),
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'amount': 1000.0,
|
||||
'partner_id': self.ref('base.res_partner_12'),
|
||||
'name': invoice_record.number,
|
||||
'ref': invoice_record.number,
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# reconcile
|
||||
line_id = None
|
||||
for l in invoice_record.move_id.line_id:
|
||||
if l.account_id.id == self.ref('account.a_recv'):
|
||||
line_id = l
|
||||
break
|
||||
|
||||
statement = self.bk_stmt_obj.browse(self.cr, self.uid, bk_stmt_id)
|
||||
for statement_line in statement.line_ids:
|
||||
self.bk_stmt_line_obj.process_reconciliation(
|
||||
self.cr, self.uid, statement_line.id,
|
||||
[
|
||||
{
|
||||
'counterpart_move_line_id': line_id.id,
|
||||
'credit': 1000.0,
|
||||
'debit': 0.0,
|
||||
'name': invoice_record.number,
|
||||
}
|
||||
]
|
||||
)
|
||||
# unreconcile journal item created by previous reconciliation
|
||||
lines_to_unreconcile = self.acc_move_line_obj.search(
|
||||
self.cr,
|
||||
self.uid,
|
||||
[('reconcile_ref', '!=', False),
|
||||
('statement_id', '=', bk_stmt_id)]
|
||||
)
|
||||
self.acc_move_line_obj._remove_move_reconcile(
|
||||
self.cr,
|
||||
self.uid,
|
||||
lines_to_unreconcile
|
||||
)
|
||||
|
||||
# create the easy reconcile record
|
||||
easy_rec_id = self.easy_rec_obj.create(
|
||||
self.cr,
|
||||
self.uid,
|
||||
{
|
||||
'name': 'easy_reconcile_1',
|
||||
'account': self.ref('account.a_recv'),
|
||||
'reconcile_method': [
|
||||
(0, 0, {
|
||||
'name': 'easy.reconcile.simple.partner',
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
# call the automatic reconcilation method
|
||||
self.easy_rec_obj.run_reconcile(
|
||||
self.cr,
|
||||
self.uid,
|
||||
[easy_rec_id]
|
||||
)
|
||||
self.assertEqual(
|
||||
'paid',
|
||||
self.invoice_obj.browse(self.cr, self.uid, inv_id).state
|
||||
)
|
||||
|
||||
def test_scenario_reconcile_currency(self):
|
||||
# create currency rate
|
||||
self.registry('res.currency.rate').create(self.cr, self.uid, {
|
||||
'name': time.strftime('%Y-%m-%d') + ' 00:00:00',
|
||||
'currency_id': self.ref('base.USD'),
|
||||
'rate': 1.5,
|
||||
})
|
||||
# create invoice
|
||||
inv_id = self.invoice_obj.create(
|
||||
self.cr,
|
||||
self.uid,
|
||||
{
|
||||
'type': 'out_invoice',
|
||||
'account_id': self.ref('account.a_recv'),
|
||||
'company_id': self.ref('base.main_company'),
|
||||
'currency_id': self.ref('base.USD'),
|
||||
'journal_id': self.ref('account.bank_journal_usd'),
|
||||
'partner_id': self.ref('base.res_partner_12'),
|
||||
'invoice_line': [
|
||||
(0, 0, {
|
||||
'name': '[PCSC234] PC Assemble SC234',
|
||||
'price_unit': 1000.0,
|
||||
'quantity': 1.0,
|
||||
'product_id': self.ref('product.product_product_3'),
|
||||
'uos_id': self.ref('product.product_uom_unit'),
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
# validate invoice
|
||||
self.invoice_obj.signal_workflow(
|
||||
self.cr,
|
||||
self.uid,
|
||||
[inv_id],
|
||||
'invoice_open'
|
||||
)
|
||||
invoice_record = self.invoice_obj.browse(self.cr, self.uid, [inv_id])
|
||||
self.assertEqual('open', invoice_record.state)
|
||||
|
||||
# create bank_statement
|
||||
bk_stmt_id = self.bk_stmt_obj.create(
|
||||
self.cr,
|
||||
self.uid,
|
||||
{
|
||||
'balance_end_real': 0.0,
|
||||
'balance_start': 0.0,
|
||||
'date': time.strftime('%Y-%m-%d'),
|
||||
'journal_id': self.ref('account.bank_journal_usd'),
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'amount': 1000.0,
|
||||
'amount_currency': 1500.0,
|
||||
'currency_id': self.ref('base.USD'),
|
||||
'partner_id': self.ref('base.res_partner_12'),
|
||||
'name': invoice_record.number,
|
||||
'ref': invoice_record.number,
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
# reconcile
|
||||
line_id = None
|
||||
for l in invoice_record.move_id.line_id:
|
||||
if l.account_id.id == self.ref('account.a_recv'):
|
||||
line_id = l
|
||||
break
|
||||
|
||||
statement = self.bk_stmt_obj.browse(self.cr, self.uid, bk_stmt_id)
|
||||
for statement_line in statement.line_ids:
|
||||
self.bk_stmt_line_obj.process_reconciliation(
|
||||
self.cr, self.uid, statement_line.id,
|
||||
[
|
||||
{
|
||||
'counterpart_move_line_id': line_id.id,
|
||||
'credit': 1000.0,
|
||||
'debit': 0.0,
|
||||
'name': invoice_record.number,
|
||||
}
|
||||
]
|
||||
)
|
||||
# unreconcile journal item created by previous reconciliation
|
||||
lines_to_unreconcile = self.acc_move_line_obj.search(
|
||||
self.cr,
|
||||
self.uid,
|
||||
[('reconcile_ref', '!=', False),
|
||||
('statement_id', '=', bk_stmt_id)]
|
||||
)
|
||||
self.acc_move_line_obj._remove_move_reconcile(
|
||||
self.cr,
|
||||
self.uid,
|
||||
lines_to_unreconcile
|
||||
)
|
||||
|
||||
# create the easy reconcile record
|
||||
easy_rec_id = self.easy_rec_obj.create(
|
||||
self.cr,
|
||||
self.uid,
|
||||
{
|
||||
'name': 'easy_reconcile_1',
|
||||
'account': self.ref('account.a_recv'),
|
||||
'reconcile_method': [
|
||||
(0, 0, {
|
||||
'name': 'easy.reconcile.simple.partner',
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
# call the automatic reconcilation method
|
||||
self.easy_rec_obj.run_reconcile(
|
||||
self.cr,
|
||||
self.uid,
|
||||
[easy_rec_id]
|
||||
)
|
||||
self.assertEqual(
|
||||
'paid',
|
||||
self.invoice_obj.browse(self.cr, self.uid, inv_id).state
|
||||
)
|
||||
Reference in New Issue
Block a user