mirror of
https://github.com/OCA/account-reconcile.git
synced 2025-01-20 12:27:39 +02:00
[ADD] add module 'account_easy_reconcile' : v8 migration
This commit is contained in:
63
account_easy_reconcile/README.rst
Normal file
63
account_easy_reconcile/README.rst
Normal file
@@ -0,0 +1,63 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:alt: License: AGPL-3
|
||||
|
||||
Easy Reconcile
|
||||
==============
|
||||
|
||||
This is a shared work between Akretion and Camptocamp
|
||||
in order to provide:
|
||||
- reconciliation facilities for big volume of transactions
|
||||
- setup different profiles of reconciliation by account
|
||||
- each profile can use many methods of reconciliation
|
||||
- this module is also a base to create others
|
||||
reconciliation methods which can plug in the profiles
|
||||
- a profile a reconciliation can be run manually
|
||||
or by a cron
|
||||
- monitoring of reconciliation runs with an history
|
||||
which keep track of the reconciled Journal items
|
||||
|
||||
2 simple reconciliation methods are integrated
|
||||
in this module, the simple reconciliations works
|
||||
on 2 lines (1 debit / 1 credit) and do not allow
|
||||
partial reconcilation, they also match on 1 key,
|
||||
partner or Journal item name.
|
||||
|
||||
You may be interested to install also the
|
||||
``account_advanced_reconciliation`` module.
|
||||
This latter add more complex reconciliations,
|
||||
allows multiple lines and partial.
|
||||
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/{project_repo}/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**>`_.
|
||||
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Damien Crier <damien.crier@camptocamp.com>
|
||||
* Frédéric Clémenti <frederic.clementi@camptocamp.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
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.
|
||||
|
||||
27
account_easy_reconcile/__init__.py
Executable file
27
account_easy_reconcile/__init__.py
Executable file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012 Camptocamp SA (Guewen Baconnier)
|
||||
# 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
|
||||
# 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 . import easy_reconcile
|
||||
from . import base_reconciliation
|
||||
from . import simple_reconciliation
|
||||
from . import easy_reconcile_history
|
||||
from . import res_config
|
||||
68
account_easy_reconcile/__openerp__.py
Executable file
68
account_easy_reconcile/__openerp__.py
Executable file
@@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012 Camptocamp SA (Guewen Baconnier)
|
||||
# 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
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
"name": "Easy Reconcile",
|
||||
"version": "1.3.1",
|
||||
"depends": ["account"],
|
||||
"author": "Akretion,Camptocamp,Odoo Community Association (OCA)",
|
||||
"description": """
|
||||
Easy Reconcile
|
||||
==============
|
||||
|
||||
This is a shared work between Akretion and Camptocamp
|
||||
in order to provide:
|
||||
- reconciliation facilities for big volume of transactions
|
||||
- setup different profiles of reconciliation by account
|
||||
- each profile can use many methods of reconciliation
|
||||
- this module is also a base to create others
|
||||
reconciliation methods which can plug in the profiles
|
||||
- a profile a reconciliation can be run manually
|
||||
or by a cron
|
||||
- monitoring of reconciliation runs with an history
|
||||
which keep track of the reconciled Journal items
|
||||
|
||||
2 simple reconciliation methods are integrated
|
||||
in this module, the simple reconciliations works
|
||||
on 2 lines (1 debit / 1 credit) and do not allow
|
||||
partial reconcilation, they also match on 1 key,
|
||||
partner or Journal item name.
|
||||
|
||||
You may be interested to install also the
|
||||
``account_advanced_reconciliation`` module.
|
||||
This latter add more complex reconciliations,
|
||||
allows multiple lines and partial.
|
||||
|
||||
""",
|
||||
"website": "http://www.akretion.com/",
|
||||
"category": "Finance",
|
||||
"data": ["easy_reconcile.xml",
|
||||
"easy_reconcile_history_view.xml",
|
||||
"security/ir_rule.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"res_config_view.xml",
|
||||
],
|
||||
'license': 'AGPL-3',
|
||||
"auto_install": False,
|
||||
'installable': True,
|
||||
|
||||
}
|
||||
237
account_easy_reconcile/base_reconciliation.py
Normal file
237
account_easy_reconcile/base_reconciliation.py
Normal file
@@ -0,0 +1,237 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier)
|
||||
# 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
|
||||
# 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 import models, api, fields
|
||||
from operator import itemgetter, attrgetter
|
||||
|
||||
|
||||
class EasyReconcileBase(models.AbstractModel):
|
||||
|
||||
"""Abstract Model for reconciliation methods"""
|
||||
|
||||
_name = 'easy.reconcile.base'
|
||||
|
||||
_inherit = 'easy.reconcile.options'
|
||||
|
||||
account_id = fields.Many2one(
|
||||
'account.account',
|
||||
string='Account',
|
||||
required=True
|
||||
)
|
||||
partner_ids = fields.Many2many(
|
||||
comodel_name='res.partner',
|
||||
string='Restrict on partners',
|
||||
)
|
||||
# other fields are inherited from easy.reconcile.options
|
||||
|
||||
@api.multi
|
||||
def automatic_reconcile(self):
|
||||
""" Reconciliation method called from the view.
|
||||
|
||||
:return: list of reconciled ids, list of partially reconciled items
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self._action_rec()
|
||||
|
||||
@api.multi
|
||||
def _action_rec(self):
|
||||
""" Must be inherited to implement the reconciliation
|
||||
|
||||
:return: list of reconciled ids
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _base_columns(self):
|
||||
""" Mandatory columns for move lines queries
|
||||
An extra column aliased as ``key`` should be defined
|
||||
in each query."""
|
||||
aml_cols = (
|
||||
'id',
|
||||
'debit',
|
||||
'credit',
|
||||
'date',
|
||||
'period_id',
|
||||
'ref',
|
||||
'name',
|
||||
'partner_id',
|
||||
'account_id',
|
||||
'reconcile_partial_id',
|
||||
'move_id')
|
||||
return ["account_move_line.%s" % col for col in aml_cols]
|
||||
|
||||
def _select(self, *args, **kwargs):
|
||||
return "SELECT %s" % ', '.join(self._base_columns())
|
||||
|
||||
def _from(self, *args, **kwargs):
|
||||
return ("FROM account_move_line "
|
||||
"LEFT OUTER JOIN account_move_reconcile ON "
|
||||
"(account_move_line.reconcile_partial_id "
|
||||
"= account_move_reconcile.id)"
|
||||
)
|
||||
|
||||
def _where(self, *args, **kwargs):
|
||||
where = ("WHERE account_move_line.account_id = %s "
|
||||
"AND COALESCE(account_move_reconcile.type,'') <> 'manual' "
|
||||
"AND account_move_line.reconcile_id IS NULL ")
|
||||
# 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
|
||||
params = [self.account_id.id]
|
||||
if self.partner_ids:
|
||||
where += " AND account_move_line.partner_id IN %s"
|
||||
params.append(tuple([l.id for l in self.partner_ids]))
|
||||
return where, params
|
||||
|
||||
def _get_filter(self):
|
||||
ml_obj = self.pool.get('account.move.line')
|
||||
where = ''
|
||||
params = []
|
||||
if self.filter:
|
||||
dummy, where, params = ml_obj._where_calc(
|
||||
eval(self.filter)).get_sql()
|
||||
if where:
|
||||
where = " AND %s" % where
|
||||
return where, params
|
||||
|
||||
@api.multi
|
||||
def _below_writeoff_limit(self, lines, writeoff_limit):
|
||||
self.ensure_one()
|
||||
precision = self.pool.get('decimal.precision').precision_get('Account')
|
||||
keys = ('debit', 'credit')
|
||||
sums = reduce(
|
||||
lambda line, memo:
|
||||
dict((key, value + memo[key])
|
||||
for key, value
|
||||
in line.iteritems()
|
||||
if key in keys), lines)
|
||||
debit, credit = sums['debit'], sums['credit']
|
||||
writeoff_amount = round(debit - credit, precision)
|
||||
return bool(writeoff_limit >= abs(writeoff_amount)), debit, credit
|
||||
|
||||
@api.multi
|
||||
def _get_rec_date(self, lines, based_on='end_period_last_credit'):
|
||||
self.ensure_one()
|
||||
|
||||
def last_period(mlines):
|
||||
period_ids = [ml['period_id'] for ml in mlines]
|
||||
return max(period_ids, key=attrgetter('date_stop'))
|
||||
|
||||
def last_date(mlines):
|
||||
return max(mlines, key=itemgetter('date'))
|
||||
|
||||
def credit(mlines):
|
||||
return [l for l in mlines if l['credit'] > 0]
|
||||
|
||||
def debit(mlines):
|
||||
return [l for l in mlines if l['debit'] > 0]
|
||||
|
||||
if based_on == 'end_period_last_credit':
|
||||
return last_period(credit(lines)).date_stop
|
||||
if based_on == 'end_period':
|
||||
return last_period(lines).date_stop
|
||||
elif based_on == 'newest':
|
||||
return last_date(lines)['date']
|
||||
elif based_on == 'newest_credit':
|
||||
return last_date(credit(lines))['date']
|
||||
elif based_on == 'newest_debit':
|
||||
return last_date(debit(lines))['date']
|
||||
# reconcilation date will be today
|
||||
# when date is None
|
||||
return None
|
||||
|
||||
@api.multi
|
||||
def _reconcile_lines(self, lines, allow_partial=False):
|
||||
""" Try to reconcile given lines
|
||||
|
||||
:param list lines: list of dict of move lines, they must at least
|
||||
contain values for : id, debit, credit
|
||||
:param boolean allow_partial: if True, partial reconciliation will be
|
||||
created, otherwise only Full
|
||||
reconciliation will be created
|
||||
:return: tuple of boolean values, first item is wether the items
|
||||
have been reconciled or not,
|
||||
the second is wether the reconciliation is full (True)
|
||||
or partial (False)
|
||||
"""
|
||||
self.ensure_one()
|
||||
ml_obj = self.env['account.move.line']
|
||||
writeoff = self.write_off
|
||||
line_ids = [l['id'] for l in lines]
|
||||
below_writeoff, sum_debit, sum_credit = self._below_writeoff_limit(
|
||||
lines, writeoff
|
||||
)
|
||||
date = self._get_rec_date(lines, self.date_base_on)
|
||||
rec_ctx = dict(self.env.context or {}, date_p=date)
|
||||
if below_writeoff:
|
||||
if sum_credit > sum_debit:
|
||||
writeoff_account_id = self.account_profit_id.id
|
||||
else:
|
||||
writeoff_account_id = self.account_lost_id.id
|
||||
period_id = self.env['account.period'].find(dt=date)[0]
|
||||
if self.analytic_account_id:
|
||||
rec_ctx['analytic_id'] = self.analytic_account_id.id
|
||||
ml_obj.with_context(rec_ctx).reconcile(
|
||||
line_ids,
|
||||
type='auto',
|
||||
writeoff_acc_id=writeoff_account_id,
|
||||
writeoff_period_id=period_id,
|
||||
writeoff_journal_id=self.journal_id.id
|
||||
)
|
||||
return True, True
|
||||
elif allow_partial:
|
||||
# Check if the group of move lines was already partially
|
||||
# reconciled and if all the lines were the same, in such
|
||||
# case, just skip the group and consider it as partially
|
||||
# reconciled (no change).
|
||||
if lines:
|
||||
existing_partial_id = lines[0]['reconcile_partial_id']
|
||||
if existing_partial_id:
|
||||
partial_line_ids = set(ml_obj.search(
|
||||
[('reconcile_partial_id', '=', existing_partial_id)],
|
||||
))
|
||||
if set(line_ids) == partial_line_ids:
|
||||
return True, False
|
||||
|
||||
# We need to give a writeoff_acc_id
|
||||
# in case we have a multi currency lines
|
||||
# to reconcile.
|
||||
# If amount in currency is equal between
|
||||
# lines to reconcile
|
||||
# it will do a full reconcile instead of a partial reconcile
|
||||
# and make a write-off for exchange
|
||||
if sum_credit > sum_debit:
|
||||
writeoff_account_id = self.income_exchange_account_id.id
|
||||
else:
|
||||
writeoff_account_id = self.expense_exchange_account_id.id
|
||||
period_id = self.env['account.period'].find(dt=date)[0]
|
||||
if self.analytic_account_id:
|
||||
rec_ctx['analytic_id'] = self.analytic_account_id.id
|
||||
ml_obj.with_context(rec_ctx).reconcile_partial(
|
||||
line_ids,
|
||||
type='manual',
|
||||
writeoff_acc_id=writeoff_account_id,
|
||||
writeoff_period_id=period_id,
|
||||
writeoff_journal_id=self.journal_id.id,
|
||||
)
|
||||
return True, False
|
||||
return False, False
|
||||
424
account_easy_reconcile/easy_reconcile.py
Normal file
424
account_easy_reconcile/easy_reconcile.py
Normal file
@@ -0,0 +1,424 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier)
|
||||
# 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
|
||||
# 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 datetime import datetime
|
||||
from openerp import models, api, fields, _
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.exceptions import except_orm
|
||||
from openerp import sql_db
|
||||
|
||||
# from openerp import pooler
|
||||
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EasyReconcileOptions(models.AbstractModel):
|
||||
"""Options of a reconciliation profile
|
||||
|
||||
Columns shared by the configuration of methods
|
||||
and by the reconciliation wizards.
|
||||
This allows decoupling of the methods and the
|
||||
wizards and allows to launch the wizards alone
|
||||
"""
|
||||
|
||||
_name = 'easy.reconcile.options'
|
||||
|
||||
@api.model
|
||||
def _get_rec_base_date(self):
|
||||
return [
|
||||
('end_period_last_credit', 'End of period of most recent credit'),
|
||||
('newest', 'Most recent move line'),
|
||||
('actual', 'Today'),
|
||||
('end_period', 'End of period of most recent move line'),
|
||||
('newest_credit', 'Date of most recent credit'),
|
||||
('newest_debit', 'Date of most recent debit')
|
||||
]
|
||||
|
||||
write_off = fields.Float('Write off allowed', default=0.)
|
||||
account_lost_id = fields.Many2one('account.account',
|
||||
string="Account Lost")
|
||||
account_profit_id = fields.Many2one('account.account',
|
||||
string="Account Profit")
|
||||
journal_id = fields.Many2one('account.journal',
|
||||
string="Journal")
|
||||
date_base_on = fields.Selection('_get_rec_base_date',
|
||||
required=True,
|
||||
string='Date of reconciliation',
|
||||
default='end_period_last_credit')
|
||||
filter = fields.Char(string='Filter', size=128)
|
||||
analytic_account_id = fields.Many2one('account.analytic.account',
|
||||
string='Analytic_account',
|
||||
help="Analytic account"
|
||||
"for the write-off")
|
||||
income_exchange_account_id = fields.Many2one('account.account',
|
||||
string='Gain Exchange'
|
||||
'Rate Account')
|
||||
expense_exchange_account_id = fields.Many2one('account.account',
|
||||
string='Loss Exchange'
|
||||
'Rate Account')
|
||||
|
||||
|
||||
class AccountEasyReconcileMethod(models.Model):
|
||||
_name = 'account.easy.reconcile.method'
|
||||
_description = 'reconcile method for account_easy_reconcile'
|
||||
_inherit = 'easy.reconcile.options'
|
||||
_order = 'sequence'
|
||||
|
||||
@api.model
|
||||
def _get_all_rec_method(self):
|
||||
return [
|
||||
('easy.reconcile.simple.name', 'Simple. Amount and Name'),
|
||||
('easy.reconcile.simple.partner', 'Simple. Amount and Partner'),
|
||||
('easy.reconcile.simple.reference',
|
||||
'Simple. Amount and Reference'),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def _get_rec_method(self):
|
||||
return self._get_all_rec_method()
|
||||
|
||||
name = fields.Selection('_get_rec_method', string='Type', required=True)
|
||||
sequence = fields.Integer(string='Sequence',
|
||||
default=1,
|
||||
required=True,
|
||||
help="The sequence field is used to order "
|
||||
"the reconcile method"
|
||||
)
|
||||
task_id = fields.Many2one('account.easy.reconcile',
|
||||
string='Task',
|
||||
required=True,
|
||||
ondelete='cascade'
|
||||
)
|
||||
company_id = fields.Many2one('res.company',
|
||||
string='Company',
|
||||
related="task_id.company_id",
|
||||
store=True,
|
||||
readonly=True
|
||||
)
|
||||
|
||||
# def init(self, cr):
|
||||
# """ Migration stuff
|
||||
#
|
||||
# Name is not anymore methods names but the name
|
||||
# of the model which does the reconciliation
|
||||
# """
|
||||
# cr.execute("""
|
||||
# UPDATE account_easy_reconcile_method
|
||||
# SET name = 'easy.reconcile.simple.partner'
|
||||
# WHERE name = 'action_rec_auto_partner'
|
||||
# """)
|
||||
# cr.execute("""
|
||||
# UPDATE account_easy_reconcile_method
|
||||
# SET name = 'easy.reconcile.simple.name'
|
||||
# WHERE name = 'action_rec_auto_name'
|
||||
# """)
|
||||
|
||||
|
||||
class AccountEasyReconcile(models.Model):
|
||||
|
||||
_name = 'account.easy.reconcile'
|
||||
_inherit = ['mail.thread']
|
||||
_description = 'account easy reconcile'
|
||||
|
||||
@api.one
|
||||
@api.depends('account')
|
||||
def _get_total_unrec(self):
|
||||
obj_move_line = self.env['account.move.line']
|
||||
self.unreconciled_count = len(obj_move_line.search(
|
||||
[('account_id', '=', self.account.id),
|
||||
('reconcile_id', '=', False),
|
||||
('reconcile_partial_id', '=', False)],
|
||||
))
|
||||
|
||||
@api.one
|
||||
@api.depends('account')
|
||||
def _get_partial_rec(self):
|
||||
obj_move_line = self.env['account.move.line']
|
||||
self.reconciled_partial_count = len(obj_move_line.search(
|
||||
[('account_id', '=', self.account.id),
|
||||
('reconcile_id', '=', False),
|
||||
('reconcile_partial_id', '!=', False)],
|
||||
))
|
||||
|
||||
@api.one
|
||||
@api.depends('history_ids')
|
||||
def _last_history(self):
|
||||
# do a search() for retrieving the latest history line,
|
||||
# as a read() will badly split the list of ids with 'date desc'
|
||||
# and return the wrong result.
|
||||
history_obj = self.env['easy.reconcile.history']
|
||||
last_history_rs = history_obj.search(
|
||||
[('easy_reconcile_id', '=', self.id)],
|
||||
limit=1, order='date desc'
|
||||
)
|
||||
self.last_history = last_history_rs[0] if last_history_rs else False
|
||||
|
||||
name = fields.Char(string='Name', size=32, required=True)
|
||||
account = fields.Many2one('account.account',
|
||||
string='Account',
|
||||
required=True,
|
||||
)
|
||||
reconcile_method = fields.One2many('account.easy.reconcile.method',
|
||||
'task_id',
|
||||
string='Method'
|
||||
)
|
||||
unreconciled_count = fields.Integer(string='Unreconciled Items',
|
||||
compute='_get_total_unrec'
|
||||
)
|
||||
reconciled_partial_count = fields.Integer(
|
||||
string='Partially Reconciled Items',
|
||||
compute='_get_partial_rec'
|
||||
)
|
||||
history_ids = fields.One2many('easy.reconcile.history',
|
||||
'easy_reconcile_id',
|
||||
string='History',
|
||||
readonly=True
|
||||
)
|
||||
last_history = fields.Many2one('easy.reconcile.history',
|
||||
string='readonly=True',
|
||||
compute='_last_history',
|
||||
readonly=True
|
||||
)
|
||||
company_id = fields.Many2one('res.company', string='Company')
|
||||
|
||||
@api.model
|
||||
def _prepare_run_transient(self, rec_method):
|
||||
return {'account_id': rec_method.task_id.account.id,
|
||||
'write_off': rec_method.write_off,
|
||||
'account_lost_id': (rec_method.account_lost_id and
|
||||
rec_method.account_lost_id.id),
|
||||
'account_profit_id': (rec_method.account_profit_id and
|
||||
rec_method.account_profit_id.id),
|
||||
'analytic_account_id': (rec_method.analytic_account_id and
|
||||
rec_method.analytic_account_id.id),
|
||||
'income_exchange_account_id':
|
||||
(rec_method.income_exchange_account_id and
|
||||
rec_method.income_exchange_account_id.id),
|
||||
'expense_exchange_account_id':
|
||||
(rec_method.income_exchange_account_id and
|
||||
rec_method.income_exchange_account_id.id),
|
||||
'journal_id': (rec_method.journal_id and
|
||||
rec_method.journal_id.id),
|
||||
'date_base_on': rec_method.date_base_on,
|
||||
'filter': rec_method.filter}
|
||||
|
||||
@api.multi
|
||||
def run_reconcile(self):
|
||||
def find_reconcile_ids(fieldname, move_line_ids):
|
||||
if not move_line_ids:
|
||||
return []
|
||||
sql = ("SELECT DISTINCT " + fieldname +
|
||||
" FROM account_move_line "
|
||||
" WHERE id in %s "
|
||||
" AND " + fieldname + " IS NOT NULL")
|
||||
self.env.cr.execute(sql, (tuple(move_line_ids),))
|
||||
res = self.env.cr.fetchall()
|
||||
return [row[0] for row in res]
|
||||
|
||||
# we use a new cursor to be able to commit the reconciliation
|
||||
# often. We have to create it here and not later to avoid problems
|
||||
# where the new cursor sees the lines as reconciles but the old one
|
||||
# does not.
|
||||
|
||||
for rec in self:
|
||||
ctx = self.env.context.copy()
|
||||
ctx['commit_every'] = (
|
||||
rec.account.company_id.reconciliation_commit_every
|
||||
)
|
||||
if ctx['commit_every']:
|
||||
new_cr = sql_db.db_connect(self.env.cr.dbname).cursor()
|
||||
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 = []
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
# self.env.cr.close()
|
||||
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def _no_history(self, rec):
|
||||
""" Raise an `orm.except_orm` error, supposed to
|
||||
be called when there is no history on the reconciliation
|
||||
task.
|
||||
"""
|
||||
raise except_orm(
|
||||
_('Error'),
|
||||
_('There is no history of reconciled '
|
||||
'items on the task: %s.') % rec.name)
|
||||
|
||||
@api.model
|
||||
def _open_move_line_list(self, move_line_ids, name):
|
||||
return {
|
||||
'name': name,
|
||||
'view_mode': 'tree,form',
|
||||
'view_id': False,
|
||||
'view_type': 'form',
|
||||
'res_model': 'account.move.line',
|
||||
'type': 'ir.actions.act_window',
|
||||
'nodestroy': True,
|
||||
'target': 'current',
|
||||
'domain': unicode([('id', 'in', move_line_ids)]),
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def open_unreconcile(self):
|
||||
""" Open the view of move line with the unreconciled move lines"""
|
||||
self.ensure_one()
|
||||
obj_move_line = self.env['account.move.line']
|
||||
line_ids = obj_move_line.search(
|
||||
[('account_id', '=', self.account.id),
|
||||
('reconcile_id', '=', False),
|
||||
('reconcile_partial_id', '=', False)])
|
||||
name = _('Unreconciled items')
|
||||
return self._open_move_line_list(line_ids and line_ids.ids or [], name)
|
||||
|
||||
@api.multi
|
||||
def open_partial_reconcile(self):
|
||||
""" Open the view of move line with the unreconciled move lines"""
|
||||
self.ensure_one()
|
||||
obj_move_line = self.env['account.move.line']
|
||||
line_ids = obj_move_line.search(
|
||||
[('account_id', '=', self.account.id),
|
||||
('reconcile_id', '=', False),
|
||||
('reconcile_partial_id', '!=', False)])
|
||||
name = _('Partial reconciled items')
|
||||
return self._open_move_line_list(line_ids and line_ids.ids or [], name)
|
||||
|
||||
@api.model
|
||||
def last_history_reconcile(self, rec_id):
|
||||
""" Get the last history record for this reconciliation profile
|
||||
and return the action which opens move lines reconciled
|
||||
"""
|
||||
if isinstance(rec_id, (tuple, list)):
|
||||
assert len(rec_id) == 1, \
|
||||
"Only 1 id expected"
|
||||
rec_id = rec_id[0]
|
||||
rec = self.browse(rec_id)
|
||||
if not rec.last_history:
|
||||
self._no_history(rec)
|
||||
return rec.last_history.open_reconcile()
|
||||
|
||||
@api.model
|
||||
def last_history_partial(self, rec_id):
|
||||
""" Get the last history record for this reconciliation profile
|
||||
and return the action which opens move lines reconciled
|
||||
"""
|
||||
if isinstance(rec_id, (tuple, list)):
|
||||
assert len(rec_id) == 1, \
|
||||
"Only 1 id expected"
|
||||
rec_id = rec_id[0]
|
||||
rec = self.browse(rec_id)
|
||||
if not rec.last_history:
|
||||
self._no_history(rec)
|
||||
return rec.last_history.open_partial()
|
||||
|
||||
@api.model
|
||||
def run_scheduler(self, run_all=None):
|
||||
""" 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
|
||||
all reconciliation
|
||||
:returns: True in case of success or raises an exception
|
||||
|
||||
"""
|
||||
def _get_date(reconcile):
|
||||
if reconcile.last_history.date:
|
||||
return datetime.strptime(reconcile.last_history.date,
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
else:
|
||||
return datetime.min
|
||||
|
||||
reconciles = self.search([])
|
||||
assert reconciles.ids, "No easy reconcile available"
|
||||
if run_all:
|
||||
reconciles.run_reconcile()
|
||||
return True
|
||||
reconciles.sorted(key=_get_date)
|
||||
older = reconciles[0]
|
||||
older.run_reconcile()
|
||||
return True
|
||||
190
account_easy_reconcile/easy_reconcile.xml
Normal file
190
account_easy_reconcile/easy_reconcile.xml
Normal file
@@ -0,0 +1,190 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- account.easy.reconcile view -->
|
||||
<record id="account_easy_reconcile_form" model="ir.ui.view">
|
||||
<field name="name">account.easy.reconcile.form</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="model">account.easy.reconcile</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Automatic Easy Reconcile" version="7.0">
|
||||
<header>
|
||||
<button name="run_reconcile" class="oe_highlight"
|
||||
string="Start Auto Reconciliation" type="object"/>
|
||||
<button icon="STOCK_JUMP_TO" name="last_history_reconcile"
|
||||
string="Display items reconciled on the last run"
|
||||
type="object"/>
|
||||
<button icon="STOCK_JUMP_TO" name="last_history_partial"
|
||||
string="Display items partially reconciled on the last run"
|
||||
type="object"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<separator colspan="4" string="Profile Information" />
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" select="1"/>
|
||||
<field name="account"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group>
|
||||
<group>
|
||||
<field name="unreconciled_count"/>
|
||||
<button icon="STOCK_JUMP_TO" name="open_unreconcile"
|
||||
string="Go to unreconciled items" type="object"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="reconciled_partial_count"/>
|
||||
<button icon="STOCK_JUMP_TO" name="open_partial_reconcile"
|
||||
string="Go to partial reconciled items" type="object"/>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page name="methods" string="Configuration">
|
||||
<field name="reconcile_method" colspan = "4" nolabel="1"/>
|
||||
</page>
|
||||
<page name="history" string="History">
|
||||
<field name="history_ids" nolabel="1">
|
||||
<tree string="Automatic Easy Reconcile History">
|
||||
<field name="date"/>
|
||||
<button icon="STOCK_JUMP_TO" name="open_reconcile"
|
||||
string="Go to reconciled items" type="object"/>
|
||||
<button icon="STOCK_JUMP_TO" name="open_partial"
|
||||
string="Go to partially reconciled items" type="object"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page name="information" string="Information">
|
||||
<separator colspan="4" string="Simple. Amount and Name"/>
|
||||
<label string="Match one debit line vs one credit line. Do not allow partial reconciliation.
|
||||
The lines should have the same amount (with the write-off) and the same name to be reconciled." colspan="4"/>
|
||||
|
||||
<separator colspan="4" string="Simple. Amount and Partner"/>
|
||||
<label string="Match one debit line vs one credit line. Do not allow partial reconciliation.
|
||||
The lines should have the same amount (with the write-off) and the same partner to be reconciled." colspan="4"/>
|
||||
|
||||
<separator colspan="4" string="Simple. Amount and Reference"/>
|
||||
<label string="Match one debit line vs one credit line. Do not allow partial reconciliation.
|
||||
The lines should have the same amount (with the write-off) and the same reference to be reconciled." colspan="4"/>
|
||||
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_easy_reconcile_tree" model="ir.ui.view">
|
||||
<field name="name">account.easy.reconcile.tree</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="model">account.easy.reconcile</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Automatic Easy Reconcile">
|
||||
<field name="name"/>
|
||||
<field name="account"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="unreconciled_count"/>
|
||||
<field name="reconciled_partial_count"/>
|
||||
<button icon="gtk-ok" name="run_reconcile" colspan="4"
|
||||
string="Start Auto Reconcilation" type="object"/>
|
||||
<button icon="STOCK_JUMP_TO" name="last_history_reconcile" colspan="2"
|
||||
string="Display items reconciled on the last run" type="object"/>
|
||||
<button icon="STOCK_JUMP_TO" name="last_history_partial" colspan="2"
|
||||
string="Display items partially reconciled on the last run"
|
||||
type="object"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_easy_reconcile" model="ir.actions.act_window">
|
||||
<field name="name">Easy Automatic Reconcile</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.easy.reconcile</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a reconciliation profile.
|
||||
</p><p>
|
||||
A reconciliation profile specifies, for one account, how
|
||||
the entries should be reconciled.
|
||||
You can select one or many reconciliation methods which will
|
||||
be run sequentially to match the entries between them.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- account.easy.reconcile.method view -->
|
||||
|
||||
<record id="account_easy_reconcile_method_form" model="ir.ui.view">
|
||||
<field name="name">account.easy.reconcile.method.form</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="model">account.easy.reconcile.method</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Automatic Easy Reconcile Method">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="write_off"/>
|
||||
<field name="account_lost_id" attrs="{'required':[('write_off','>',0)]}"/>
|
||||
<field name="account_profit_id" attrs="{'required':[('write_off','>',0)]}"/>
|
||||
<field name="income_exchange_account_id" groups="base.group_multi_currency"/>
|
||||
<field name="expense_exchange_account_id" groups="base.group_multi_currency"/>
|
||||
<field name="journal_id" attrs="{'required':[('write_off','>',0)]}"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="date_base_on"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_easy_reconcile_method_tree" model="ir.ui.view">
|
||||
<field name="name">account.easy.reconcile.method.tree</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="model">account.easy.reconcile.method</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="top" string="Automatic Easy Reconcile Method">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="write_off"/>
|
||||
<field name="account_lost_id" attrs="{'required':[('write_off','>',0)]}"/>
|
||||
<field name="account_profit_id" attrs="{'required':[('write_off','>',0)]}"/>
|
||||
<field name="income_exchange_account_id" groups="base.group_multi_currency"/>
|
||||
<field name="expense_exchange_account_id" groups="base.group_multi_currency"/>
|
||||
<field name="journal_id" attrs="{'required':[('write_off','>',0)]}"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="date_base_on"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- menu item -->
|
||||
|
||||
<menuitem action="action_account_easy_reconcile"
|
||||
id="menu_easy_reconcile"
|
||||
parent="account.periodical_processing_reconciliation"/>
|
||||
|
||||
</data>
|
||||
|
||||
<data noupdate="1">
|
||||
|
||||
<record forcecreate="True" id="ir_cron_run_reconciliations" model="ir.cron">
|
||||
<field name="name">Do Automatic Reconciliations</field>
|
||||
<field eval="False" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">3</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
<field eval="'account.easy.reconcile'" name="model"/>
|
||||
<field eval="'run_scheduler'" name="function"/>
|
||||
<field eval="'()'" name="args"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
</openerp>
|
||||
143
account_easy_reconcile/easy_reconcile_history.py
Normal file
143
account_easy_reconcile/easy_reconcile_history.py
Normal file
@@ -0,0 +1,143 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Guewen Baconnier
|
||||
# Copyright 2012 Camptocamp SA
|
||||
# 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
|
||||
# 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 import models, api, fields, _
|
||||
|
||||
|
||||
class EasyReconcileHistory(models.Model):
|
||||
""" Store an history of the runs per profile
|
||||
Each history stores the list of reconciliations done"""
|
||||
|
||||
_name = 'easy.reconcile.history'
|
||||
_rec_name = 'easy_reconcile_id'
|
||||
_order = 'date DESC'
|
||||
|
||||
@api.one
|
||||
@api.depends('reconcile_ids', 'reconcile_partial_ids')
|
||||
def _reconcile_line_ids(self):
|
||||
move_line_ids = []
|
||||
for reconcile in self.reconcile_ids:
|
||||
move_line_ids += [line.id
|
||||
for line
|
||||
in reconcile.line_id]
|
||||
self.reconcile_line_ids = move_line_ids
|
||||
move_line_ids = []
|
||||
for reconcile in self.reconcile_partial_ids:
|
||||
move_line_ids += [line.id
|
||||
for line
|
||||
in reconcile.line_partial_ids]
|
||||
self.partial_line_ids = move_line_ids
|
||||
|
||||
easy_reconcile_id = fields.Many2one(
|
||||
'account.easy.reconcile',
|
||||
string='Reconcile Profile',
|
||||
readonly=True
|
||||
)
|
||||
date = fields.Datetime(string='Run date', readonly=True, required=True)
|
||||
reconcile_ids = fields.Many2many(
|
||||
comodel_name='account.move.reconcile',
|
||||
relation='account_move_reconcile_history_rel',
|
||||
string='Partial Reconciliations',
|
||||
readonly=True
|
||||
)
|
||||
reconcile_partial_ids = fields.Many2many(
|
||||
comodel_name='account.move.reconcile',
|
||||
relation='account_move_reconcile_history_partial_rel',
|
||||
string='Partial Reconciliations',
|
||||
readonly=True
|
||||
)
|
||||
reconcile_line_ids = fields.Many2many(
|
||||
comodel_name='account.move.line',
|
||||
relation='account_move_line_history_rel',
|
||||
string='Reconciled Items',
|
||||
readonly=True,
|
||||
multi='lines',
|
||||
_compute='_reconcile_line_ids'
|
||||
)
|
||||
partial_line_ids = fields.Many2many(
|
||||
comodel_name='account.move.line',
|
||||
relation='account_move_line_history_rel',
|
||||
string='Partially Reconciled Items',
|
||||
readonly=True,
|
||||
multi='lines',
|
||||
_compute='_reconcile_line_ids'
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
store=True,
|
||||
readonly=True,
|
||||
related='easy_reconcile_id.company_id'
|
||||
)
|
||||
|
||||
def _open_move_lines(self, rec_type='full'):
|
||||
""" For an history record, open the view of move line with
|
||||
the reconciled or partially reconciled move lines
|
||||
|
||||
:param history_id: id of the history
|
||||
:param rec_type: 'full' or 'partial'
|
||||
:return: action to open the move lines
|
||||
"""
|
||||
assert rec_type in ('full', 'partial'), \
|
||||
"rec_type must be 'full' or 'partial'"
|
||||
history = self
|
||||
if rec_type == 'full':
|
||||
field = 'reconcile_line_ids'
|
||||
name = _('Reconciliations')
|
||||
else:
|
||||
field = 'partial_line_ids'
|
||||
name = _('Partial Reconciliations')
|
||||
move_line_ids = [line.id for line in getattr(history, field)]
|
||||
return {
|
||||
'name': name,
|
||||
'view_mode': 'tree,form',
|
||||
'view_id': False,
|
||||
'view_type': 'form',
|
||||
'res_model': 'account.move.line',
|
||||
'type': 'ir.actions.act_window',
|
||||
'nodestroy': True,
|
||||
'target': 'current',
|
||||
'domain': unicode([('id', 'in', move_line_ids)]),
|
||||
}
|
||||
|
||||
def open_reconcile(self):
|
||||
""" For an history record, open the view of move line
|
||||
with the reconciled move lines
|
||||
|
||||
:param history_ids: id of the record as int or long
|
||||
Accept a list with 1 id too to be
|
||||
used from the client.
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self._open_move_lines(rec_type='full')
|
||||
|
||||
@api.model
|
||||
def open_partial(self):
|
||||
""" For an history record, open the view of move line
|
||||
with the partially reconciled move lines
|
||||
|
||||
:param history_ids: id of the record as int or long
|
||||
Accept a list with 1 id too to be
|
||||
used from the client.
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self._open_move_lines(rec_type='partial')
|
||||
98
account_easy_reconcile/easy_reconcile_history_view.xml
Normal file
98
account_easy_reconcile/easy_reconcile_history_view.xml
Normal file
@@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="view_easy_reconcile_history_search" model="ir.ui.view">
|
||||
<field name="name">easy.reconcile.history.search</field>
|
||||
<field name="model">easy.reconcile.history</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Automatic Easy Reconcile History">
|
||||
<filter icon="terp-go-today" string="Today"
|
||||
domain="[('date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), ('date','>=', time.strftime('%%Y-%%m-%%d 00:00:00'))]"
|
||||
help="Todays' Reconcilations" />
|
||||
<filter icon="terp-go-week" string="7 Days"
|
||||
help="Reconciliations of last 7 days"
|
||||
domain="[('date','<', time.strftime('%%Y-%%m-%%d 23:59:59')),('date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d 00:00:00'))]"
|
||||
/>
|
||||
|
||||
<separator orientation="vertical"/>
|
||||
<field name="easy_reconcile_id"/>
|
||||
<field name="date"/>
|
||||
|
||||
<newline/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Reconciliation Profile"
|
||||
icon="terp-stock_effects-object-colorize"
|
||||
domain="[]" context="{'group_by': 'easy_reconcile_id'}"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]"
|
||||
context="{'group_by': 'date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="easy_reconcile_history_form" model="ir.ui.view">
|
||||
<field name="name">easy.reconcile.history.form</field>
|
||||
<field name="model">easy.reconcile.history</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Automatic Easy Reconcile History" version="7.0">
|
||||
<header>
|
||||
<button name="open_reconcile"
|
||||
string="Go to reconciled items"
|
||||
icon="STOCK_JUMP_TO" type="object"/>
|
||||
<button name="open_partial"
|
||||
string="Go to partially reconciled items"
|
||||
icon="STOCK_JUMP_TO" type="object"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="easy_reconcile_id"/>
|
||||
<field name="date"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group col="2">
|
||||
<separator colspan="2" string="Reconciliations"/>
|
||||
<field name="reconcile_ids" nolabel="1"/>
|
||||
</group>
|
||||
<group col="2">
|
||||
<separator colspan="2" string="Partial Reconciliations"/>
|
||||
<field name="reconcile_partial_ids" nolabel="1"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="easy_reconcile_history_tree" model="ir.ui.view">
|
||||
<field name="name">easy.reconcile.history.tree</field>
|
||||
<field name="model">easy.reconcile.history</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Automatic Easy Reconcile History">
|
||||
<field name="easy_reconcile_id"/>
|
||||
<field name="date"/>
|
||||
<button icon="STOCK_JUMP_TO" name="open_reconcile"
|
||||
string="Go to reconciled items" type="object"/>
|
||||
<button icon="STOCK_JUMP_TO" name="open_partial"
|
||||
string="Go to partially reconciled items" type="object"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_easy_reconcile_history" model="ir.actions.act_window">
|
||||
<field name="name">Easy Automatic Reconcile History</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">easy.reconcile.history</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<act_window
|
||||
context="{'search_default_easy_reconcile_id': [active_id], 'default_easy_reconcile_id': active_id}"
|
||||
id="act_easy_reconcile_to_history"
|
||||
name="History Details"
|
||||
groups=""
|
||||
res_model="easy.reconcile.history"
|
||||
src_model="account.easy.reconcile"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
567
account_easy_reconcile/i18n/account_easy_reconcile.pot
Normal file
567
account_easy_reconcile/i18n/account_easy_reconcile.pot
Normal file
@@ -0,0 +1,567 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_easy_reconcile
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-06-12 14:08+0000\n"
|
||||
"PO-Revision-Date: 2015-06-12 14:08+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "7 Days"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.actions.act_window,help:account_easy_reconcile.action_account_easy_reconcile
|
||||
msgid "<p class=\"oe_view_nocontent_create\">\n"
|
||||
" Click to add a reconciliation profile.\n"
|
||||
" </p><p>\n"
|
||||
" A reconciliation profile specifies, for one account, how\n"
|
||||
" the entries should be reconciled.\n"
|
||||
" You can select one or many reconciliation methods which will\n"
|
||||
" be run sequentially to match the entries between them.\n"
|
||||
" </p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,account:0
|
||||
#: field:easy.reconcile.base,account_id:0
|
||||
#: field:easy.reconcile.simple,account_id:0
|
||||
#: field:easy.reconcile.simple.name,account_id:0
|
||||
#: field:easy.reconcile.simple.partner,account_id:0
|
||||
#: field:easy.reconcile.simple.reference,account_id:0
|
||||
msgid "Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,account_lost_id:0
|
||||
#: field:easy.reconcile.base,account_lost_id:0
|
||||
#: field:easy.reconcile.options,account_lost_id:0
|
||||
#: field:easy.reconcile.simple,account_lost_id:0
|
||||
#: field:easy.reconcile.simple.name,account_lost_id:0
|
||||
#: field:easy.reconcile.simple.partner,account_lost_id:0
|
||||
#: field:easy.reconcile.simple.reference,account_lost_id:0
|
||||
msgid "Account Lost"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,account_profit_id:0
|
||||
#: field:easy.reconcile.base,account_profit_id:0
|
||||
#: field:easy.reconcile.options,account_profit_id:0
|
||||
#: field:easy.reconcile.simple,account_profit_id:0
|
||||
#: field:easy.reconcile.simple.name,account_profit_id:0
|
||||
#: field:easy.reconcile.simple.partner,account_profit_id:0
|
||||
#: field:easy.reconcile.simple.reference,account_profit_id:0
|
||||
msgid "Account Profit"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:account.easy.reconcile.method,analytic_account_id:0
|
||||
#: help:easy.reconcile.base,analytic_account_id:0
|
||||
#: help:easy.reconcile.options,analytic_account_id:0
|
||||
#: help:easy.reconcile.simple,analytic_account_id:0
|
||||
#: help:easy.reconcile.simple.name,analytic_account_id:0
|
||||
#: help:easy.reconcile.simple.partner,analytic_account_id:0
|
||||
#: help:easy.reconcile.simple.reference,analytic_account_id:0
|
||||
msgid "Analytic accountfor the write-off"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,analytic_account_id:0
|
||||
#: field:easy.reconcile.base,analytic_account_id:0
|
||||
#: field:easy.reconcile.options,analytic_account_id:0
|
||||
#: field:easy.reconcile.simple,analytic_account_id:0
|
||||
#: field:easy.reconcile.simple.name,analytic_account_id:0
|
||||
#: field:easy.reconcile.simple.partner,analytic_account_id:0
|
||||
#: field:easy.reconcile.simple.reference,analytic_account_id:0
|
||||
msgid "Analytic_account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_tree
|
||||
msgid "Automatic Easy Reconcile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_form
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_tree
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Automatic Easy Reconcile History"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile.method:account_easy_reconcile.account_easy_reconcile_method_form
|
||||
#: view:account.easy.reconcile.method:account_easy_reconcile.account_easy_reconcile_method_tree
|
||||
msgid "Automatic Easy Reconcile Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.model,name:account_easy_reconcile.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,company_id:0
|
||||
#: field:account.easy.reconcile.method,company_id:0
|
||||
#: field:easy.reconcile.history,company_id:0
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Configuration"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,create_uid:0
|
||||
#: field:account.easy.reconcile.method,create_uid:0
|
||||
#: field:easy.reconcile.history,create_uid:0
|
||||
#: field:easy.reconcile.simple.name,create_uid:0
|
||||
#: field:easy.reconcile.simple.partner,create_uid:0
|
||||
#: field:easy.reconcile.simple.reference,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,create_date:0
|
||||
#: field:account.easy.reconcile.method,create_date:0
|
||||
#: field:easy.reconcile.history,create_date:0
|
||||
#: field:easy.reconcile.simple.name,create_date:0
|
||||
#: field:easy.reconcile.simple.partner,create_date:0
|
||||
#: field:easy.reconcile.simple.reference,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,date_base_on:0
|
||||
#: field:easy.reconcile.base,date_base_on:0
|
||||
#: field:easy.reconcile.options,date_base_on:0
|
||||
#: field:easy.reconcile.simple,date_base_on:0
|
||||
#: field:easy.reconcile.simple.name,date_base_on:0
|
||||
#: field:easy.reconcile.simple.partner,date_base_on:0
|
||||
#: field:easy.reconcile.simple.reference,date_base_on:0
|
||||
msgid "Date of reconciliation"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:account.easy.reconcile,message_last_post:0
|
||||
msgid "Date of the last message posted on the record."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_tree
|
||||
msgid "Display items partially reconciled on the last run"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_tree
|
||||
msgid "Display items reconciled on the last run"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.actions.act_window,name:account_easy_reconcile.action_account_easy_reconcile
|
||||
#: model:ir.ui.menu,name:account_easy_reconcile.menu_easy_reconcile
|
||||
msgid "Easy Automatic Reconcile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.actions.act_window,name:account_easy_reconcile.action_easy_reconcile_history
|
||||
msgid "Easy Automatic Reconcile History"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: code:addons/account_easy_reconcile/easy_reconcile.py:329
|
||||
#, python-format
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,filter:0
|
||||
#: field:easy.reconcile.base,filter:0
|
||||
#: field:easy.reconcile.options,filter:0
|
||||
#: field:easy.reconcile.simple,filter:0
|
||||
#: field:easy.reconcile.simple.name,filter:0
|
||||
#: field:easy.reconcile.simple.partner,filter:0
|
||||
#: field:easy.reconcile.simple.reference,filter:0
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,message_follower_ids:0
|
||||
msgid "Followers"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,income_exchange_account_id:0
|
||||
#: field:easy.reconcile.base,income_exchange_account_id:0
|
||||
#: field:easy.reconcile.options,income_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple,income_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple.name,income_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple.partner,income_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple.reference,income_exchange_account_id:0
|
||||
msgid "Gain ExchangeRate Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Go to partial reconciled items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_form
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_tree
|
||||
msgid "Go to partially reconciled items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_form
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_tree
|
||||
msgid "Go to reconciled items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Go to unreconciled items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Group By..."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
#: field:account.easy.reconcile,history_ids:0
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.actions.act_window,name:account_easy_reconcile.act_easy_reconcile_to_history
|
||||
msgid "History Details"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:account.easy.reconcile,message_summary:0
|
||||
msgid "Holds the Chatter summary (number of messages, ...). This summary is directly in html format in order to be inserted in kanban views."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:res.company,reconciliation_commit_every:0
|
||||
msgid "How often to commit when performing automaticreconciliation."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,id:0
|
||||
#: field:account.easy.reconcile.method,id:0
|
||||
#: field:easy.reconcile.base,id:0
|
||||
#: field:easy.reconcile.history,id:0
|
||||
#: field:easy.reconcile.options,id:0
|
||||
#: field:easy.reconcile.simple,id:0
|
||||
#: field:easy.reconcile.simple.name,id:0
|
||||
#: field:easy.reconcile.simple.partner,id:0
|
||||
#: field:easy.reconcile.simple.reference,id:0
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:account.easy.reconcile,message_unread:0
|
||||
msgid "If checked new messages require your attention."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Information"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,message_is_follower:0
|
||||
msgid "Is a Follower"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,journal_id:0
|
||||
#: field:easy.reconcile.base,journal_id:0
|
||||
#: field:easy.reconcile.options,journal_id:0
|
||||
#: field:easy.reconcile.simple,journal_id:0
|
||||
#: field:easy.reconcile.simple.name,journal_id:0
|
||||
#: field:easy.reconcile.simple.partner,journal_id:0
|
||||
#: field:easy.reconcile.simple.reference,journal_id:0
|
||||
msgid "Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,message_last_post:0
|
||||
msgid "Last Message Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,write_uid:0
|
||||
#: field:account.easy.reconcile.method,write_uid:0
|
||||
#: field:easy.reconcile.history,write_uid:0
|
||||
#: field:easy.reconcile.simple.name,write_uid:0
|
||||
#: field:easy.reconcile.simple.partner,write_uid:0
|
||||
#: field:easy.reconcile.simple.reference,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,write_date:0
|
||||
#: field:account.easy.reconcile.method,write_date:0
|
||||
#: field:easy.reconcile.history,write_date:0
|
||||
#: field:easy.reconcile.simple.name,write_date:0
|
||||
#: field:easy.reconcile.simple.partner,write_date:0
|
||||
#: field:easy.reconcile.simple.reference,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:res.company,reconciliation_commit_every:0
|
||||
msgid "Leave zero to commit only at the end of the process."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,expense_exchange_account_id:0
|
||||
#: field:easy.reconcile.base,expense_exchange_account_id:0
|
||||
#: field:easy.reconcile.options,expense_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple,expense_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple.name,expense_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple.partner,expense_exchange_account_id:0
|
||||
#: field:easy.reconcile.simple.reference,expense_exchange_account_id:0
|
||||
msgid "Loss ExchangeRate Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Match one debit line vs one credit line. Do not allow partial reconciliation. The lines should have the same amount (with the write-off) and the same name to be reconciled."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Match one debit line vs one credit line. Do not allow partial reconciliation. The lines should have the same amount (with the write-off) and the same partner to be reconciled."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Match one debit line vs one credit line. Do not allow partial reconciliation. The lines should have the same amount (with the write-off) and the same reference to be reconciled."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,message_ids:0
|
||||
msgid "Messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:account.easy.reconcile,message_ids:0
|
||||
msgid "Messages and communication history"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,reconcile_method:0
|
||||
msgid "Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,name:0
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.config.settings:account_easy_reconcile.view_account_config
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: code:addons/account_easy_reconcile/easy_reconcile_history.py:108
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_form
|
||||
#: field:easy.reconcile.history,reconcile_ids:0
|
||||
#: field:easy.reconcile.history,reconcile_partial_ids:0
|
||||
#, python-format
|
||||
msgid "Partial Reconciliations"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: code:addons/account_easy_reconcile/easy_reconcile.py:368
|
||||
#, python-format
|
||||
msgid "Partial reconciled items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:easy.reconcile.history,partial_line_ids:0
|
||||
msgid "Partially Reconciled Items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Profile Information"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:easy.reconcile.history,easy_reconcile_id:0
|
||||
msgid "Reconcile Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:easy.reconcile.history,reconcile_line_ids:0
|
||||
msgid "Reconciled Items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.config.settings:account_easy_reconcile.view_account_config
|
||||
msgid "Reconciliation"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Reconciliation Profile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: code:addons/account_easy_reconcile/easy_reconcile_history.py:105
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.easy_reconcile_history_form
|
||||
#, python-format
|
||||
msgid "Reconciliations"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Reconciliations of last 7 days"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:easy.reconcile.base,partner_ids:0
|
||||
#: field:easy.reconcile.simple,partner_ids:0
|
||||
#: field:easy.reconcile.simple.name,partner_ids:0
|
||||
#: field:easy.reconcile.simple.partner,partner_ids:0
|
||||
#: field:easy.reconcile.simple.reference,partner_ids:0
|
||||
msgid "Restrict on partners"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:easy.reconcile.history,date:0
|
||||
msgid "Run date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Simple. Amount and Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Simple. Amount and Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Simple. Amount and Reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_tree
|
||||
msgid "Start Auto Reconcilation"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.easy.reconcile:account_easy_reconcile.account_easy_reconcile_form
|
||||
msgid "Start Auto Reconciliation"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,message_summary:0
|
||||
msgid "Summary"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,task_id:0
|
||||
msgid "Task"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: help:account.easy.reconcile.method,sequence:0
|
||||
msgid "The sequence field is used to order the reconcile method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: code:addons/account_easy_reconcile/easy_reconcile.py:330
|
||||
#, python-format
|
||||
msgid "There is no history of reconciled items on the task: %s."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Today"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:easy.reconcile.history:account_easy_reconcile.view_easy_reconcile_history_search
|
||||
msgid "Todays' Reconcilations"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,name:0
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile,message_unread:0
|
||||
msgid "Unread Messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: code:addons/account_easy_reconcile/easy_reconcile.py:356
|
||||
#, python-format
|
||||
msgid "Unreconciled items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: field:account.easy.reconcile.method,write_off:0
|
||||
#: field:easy.reconcile.base,write_off:0
|
||||
#: field:easy.reconcile.options,write_off:0
|
||||
#: field:easy.reconcile.simple,write_off:0
|
||||
#: field:easy.reconcile.simple.name,write_off:0
|
||||
#: field:easy.reconcile.simple.partner,write_off:0
|
||||
#: field:easy.reconcile.simple.reference,write_off:0
|
||||
msgid "Write off allowed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.model,name:account_easy_reconcile.model_account_easy_reconcile
|
||||
msgid "account easy reconcile"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: view:account.config.settings:account_easy_reconcile.view_account_config
|
||||
msgid "eInvoicing & Payments"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_easy_reconcile
|
||||
#: model:ir.model,name:account_easy_reconcile.model_account_easy_reconcile_method
|
||||
msgid "reconcile method for account_easy_reconcile"
|
||||
msgstr ""
|
||||
|
||||
58
account_easy_reconcile/res_config.py
Normal file
58
account_easy_reconcile/res_config.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Leonardo Pistone
|
||||
# Copyright 2014 Camptocamp SA
|
||||
# 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
|
||||
# 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 import models, api, fields
|
||||
|
||||
|
||||
class AccountConfigSettings(models.TransientModel):
|
||||
_inherit = 'account.config.settings'
|
||||
|
||||
reconciliation_commit_every = fields.Integer(
|
||||
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."""
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def onchange_company_id(self, company_id):
|
||||
|
||||
result = super(AccountConfigSettings, self).onchange_company_id(
|
||||
company_id
|
||||
)
|
||||
|
||||
if company_id:
|
||||
company = self.env['res.company'].browse(company_id)
|
||||
result['value']['reconciliation_commit_every'] = (
|
||||
company.reconciliation_commit_every
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
class Company(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
reconciliation_commit_every = fields.Integer(
|
||||
string="How often to commit when performing automatic"
|
||||
"reconciliation.",
|
||||
help="""Leave zero to commit only at the end of the process."""
|
||||
)
|
||||
24
account_easy_reconcile/res_config_view.xml
Normal file
24
account_easy_reconcile/res_config_view.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_account_config" model="ir.ui.view">
|
||||
<field name="name">account settings</field>
|
||||
<field name="model">account.config.settings</field>
|
||||
<field name="inherit_id" ref="account.view_account_config_settings"/>
|
||||
<field name="arch" type="xml">
|
||||
<separator string="eInvoicing & Payments" position="before">
|
||||
<separator string="Reconciliation"/>
|
||||
<group>
|
||||
<label for="id" string="Options"/>
|
||||
<div name="reconciliation_config">
|
||||
<div>
|
||||
<label for="reconciliation_commit_every"/>
|
||||
<field name="reconciliation_commit_every" class="oe_inline"/>
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
</separator>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
9
account_easy_reconcile/security/ir.model.access.csv
Normal file
9
account_easy_reconcile/security/ir.model.access.csv
Normal file
@@ -0,0 +1,9 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_easy_reconcile_options_acc_user,easy.reconcile.options,model_easy_reconcile_options,account.group_account_user,1,0,0,0
|
||||
access_account_easy_reconcile_method_acc_user,account.easy.reconcile.method,model_account_easy_reconcile_method,account.group_account_user,1,0,0,0
|
||||
access_account_easy_reconcile_acc_user,account.easy.reconcile,model_account_easy_reconcile,account.group_account_user,1,1,0,0
|
||||
access_easy_reconcile_options_acc_mgr,easy.reconcile.options,model_easy_reconcile_options,account.group_account_user,1,0,0,0
|
||||
access_account_easy_reconcile_method_acc_mgr,account.easy.reconcile.method,model_account_easy_reconcile_method,account.group_account_user,1,1,1,1
|
||||
access_account_easy_reconcile_acc_mgr,account.easy.reconcile,model_account_easy_reconcile,account.group_account_user,1,1,1,1
|
||||
access_easy_reconcile_history_acc_user,easy.reconcile.history,model_easy_reconcile_history,account.group_account_user,1,1,1,0
|
||||
access_easy_reconcile_history_acc_mgr,easy.reconcile.history,model_easy_reconcile_history,account.group_account_manager,1,1,1,1
|
||||
|
25
account_easy_reconcile/security/ir_rule.xml
Normal file
25
account_easy_reconcile/security/ir_rule.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record id="easy_reconcile_rule" model="ir.rule">
|
||||
<field name="name">Easy reconcile multi-company</field>
|
||||
<field name="model_id" ref="model_account_easy_reconcile"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="easy_reconcile_history_rule" model="ir.rule">
|
||||
<field name="name">Easy reconcile history multi-company</field>
|
||||
<field name="model_id" ref="model_easy_reconcile_history"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="easy_reconcile_method_rule" model="ir.rule">
|
||||
<field name="name">Easy reconcile method multi-company</field>
|
||||
<field name="model_id" ref="model_account_easy_reconcile_method"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
114
account_easy_reconcile/simple_reconciliation.py
Normal file
114
account_easy_reconcile/simple_reconciliation.py
Normal file
@@ -0,0 +1,114 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright 2012-2013 Camptocamp SA (Guewen Baconnier)
|
||||
# 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
|
||||
# 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.osv.orm import AbstractModel, TransientModel
|
||||
from openerp import models, api
|
||||
|
||||
|
||||
class EasyReconcileSimple(models.AbstractModel):
|
||||
_name = 'easy.reconcile.simple'
|
||||
_inherit = 'easy.reconcile.base'
|
||||
|
||||
# has to be subclassed
|
||||
# field name used as key for matching the move lines
|
||||
_key_field = None
|
||||
|
||||
@api.model
|
||||
def rec_auto_lines_simple(self, lines):
|
||||
if self._key_field is None:
|
||||
raise ValueError("_key_field has to be defined")
|
||||
count = 0
|
||||
res = []
|
||||
while (count < len(lines)):
|
||||
for i in xrange(count + 1, len(lines)):
|
||||
if lines[count][self._key_field] != lines[i][self._key_field]:
|
||||
break
|
||||
check = False
|
||||
if lines[count]['credit'] > 0 and lines[i]['debit'] > 0:
|
||||
credit_line = lines[count]
|
||||
debit_line = lines[i]
|
||||
check = True
|
||||
elif lines[i]['credit'] > 0 and lines[count]['debit'] > 0:
|
||||
credit_line = lines[i]
|
||||
debit_line = lines[count]
|
||||
check = True
|
||||
if not check:
|
||||
continue
|
||||
reconciled, dummy = self._reconcile_lines(
|
||||
self,
|
||||
[credit_line, debit_line],
|
||||
allow_partial=False
|
||||
)
|
||||
if reconciled:
|
||||
res += [credit_line['id'], debit_line['id']]
|
||||
del lines[i]
|
||||
break
|
||||
count += 1
|
||||
return res, [] # empty list for partial, only full rec in "simple" rec
|
||||
|
||||
def _simple_order(self, *args, **kwargs):
|
||||
return "ORDER BY account_move_line.%s" % self._key_field
|
||||
|
||||
def _action_rec(self):
|
||||
"""Match only 2 move lines, do not allow partial reconcile"""
|
||||
select = self._select(self)
|
||||
select += ", account_move_line.%s " % self._key_field
|
||||
where, params = self._where()
|
||||
where += " AND account_move_line.%s IS NOT NULL " % self._key_field
|
||||
|
||||
where2, params2 = self._get_filter()
|
||||
query = ' '.join((
|
||||
select,
|
||||
self._from(),
|
||||
where, where2,
|
||||
self._simple_order()))
|
||||
|
||||
self.env.cr.execute(query, params + params2)
|
||||
lines = self.env.cr.dictfetchall()
|
||||
return self.rec_auto_lines_simple(lines)
|
||||
|
||||
|
||||
class EasyReconcileSimpleName(models.TransientModel):
|
||||
_name = 'easy.reconcile.simple.name'
|
||||
_inherit = 'easy.reconcile.simple'
|
||||
|
||||
# has to be subclassed
|
||||
# field name used as key for matching the move lines
|
||||
_key_field = 'name'
|
||||
|
||||
|
||||
class EasyReconcileSimplePartner(models.TransientModel):
|
||||
_name = 'easy.reconcile.simple.partner'
|
||||
_inherit = 'easy.reconcile.simple'
|
||||
|
||||
# has to be subclassed
|
||||
# field name used as key for matching the move lines
|
||||
_key_field = 'partner_id'
|
||||
|
||||
|
||||
class EasyReconcileSimpleReference(models.TransientModel):
|
||||
_name = 'easy.reconcile.simple.reference'
|
||||
_inherit = 'easy.reconcile.simple'
|
||||
|
||||
# has to be subclassed
|
||||
# field name used as key for matching the move lines
|
||||
_key_field = 'ref'
|
||||
Reference in New Issue
Block a user