~pedro.baeza/banking-addons/6.1-bank-statement-reconcile-trans

« back to all changes in this revision

Viewing changes to account_easy_reconcile/easy_reconcile.py

[ADD] added account_easy_reconcile from account_extra_addons

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    Copyright 2012 Camptocamp SA (Guewen Baconnier)
 
5
#    Copyright (C) 2010   Sébastien Beau
 
6
#
 
7
#    This program is free software: you can redistribute it and/or modify
 
8
#    it under the terms of the GNU Affero General Public License as
 
9
#    published by the Free Software Foundation, either version 3 of the
 
10
#    License, or (at your option) any later version.
 
11
#
 
12
#    This program is distributed in the hope that it will be useful,
 
13
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#    GNU Affero General Public License for more details.
 
16
#
 
17
#    You should have received a copy of the GNU Affero General Public License
 
18
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
#
 
20
##############################################################################
 
21
 
 
22
import time
 
23
from openerp.osv.orm import Model, AbstractModel
 
24
from openerp.osv import fields
 
25
from openerp.tools.translate import _
 
26
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
 
27
 
 
28
 
 
29
class easy_reconcile_options(AbstractModel):
 
30
    """Options of a reconciliation profile, columns
 
31
    shared by the configuration of methods and by the
 
32
    reconciliation wizards. This allows decoupling
 
33
    of the methods with the wizards and allows to
 
34
    launch the wizards alone
 
35
    """
 
36
 
 
37
    _name = 'easy.reconcile.options'
 
38
 
 
39
    def _get_rec_base_date(self, cr, uid, context=None):
 
40
        return [('end_period_last_credit', 'End of period of most recent credit'),
 
41
                ('newest', 'Most recent move line'),
 
42
                ('actual', 'Today'),
 
43
                ('end_period', 'End of period of most recent move line'),
 
44
                ('newest_credit', 'Date of most recent credit'),
 
45
                ('newest_debit', 'Date of most recent debit')]
 
46
 
 
47
    _columns = {
 
48
            'write_off': fields.float('Write off allowed'),
 
49
            'account_lost_id': fields.many2one('account.account', 'Account Lost'),
 
50
            'account_profit_id': fields.many2one('account.account', 'Account Profit'),
 
51
            'journal_id': fields.many2one('account.journal', 'Journal'),
 
52
            'date_base_on': fields.selection(_get_rec_base_date,
 
53
                required=True,
 
54
                string='Date of reconcilation'),
 
55
            'filter': fields.char('Filter', size=128),
 
56
    }
 
57
 
 
58
    _defaults = {
 
59
        'write_off': 0.,
 
60
        'date_base_on': 'end_period_last_credit',
 
61
    }
 
62
 
 
63
 
 
64
class account_easy_reconcile_method(Model):
 
65
 
 
66
    _name = 'account.easy.reconcile.method'
 
67
    _description = 'reconcile method for account_easy_reconcile'
 
68
 
 
69
    _inherit = 'easy.reconcile.options'
 
70
    _auto = True  # restore property set to False by AbstractModel
 
71
 
 
72
    _order = 'sequence'
 
73
 
 
74
    def _get_all_rec_method(self, cr, uid, context=None):
 
75
        return [
 
76
            ('easy.reconcile.simple.name', 'Simple. Amount and Name'),
 
77
            ('easy.reconcile.simple.partner', 'Simple. Amount and Partner'),
 
78
            ('easy.reconcile.simple.reference', 'Simple. Amount and Reference'),
 
79
            ]
 
80
 
 
81
    def _get_rec_method(self, cr, uid, context=None):
 
82
        return self._get_all_rec_method(cr, uid, context=None)
 
83
 
 
84
    _columns = {
 
85
            'name': fields.selection(_get_rec_method, 'Type', size=128, required=True),
 
86
            'sequence': fields.integer('Sequence', required=True,
 
87
                help="The sequence field is used to order the reconcile method"),
 
88
            'task_id': fields.many2one('account.easy.reconcile', 'Task',
 
89
                required=True, ondelete='cascade'),
 
90
    }
 
91
 
 
92
    _defaults = {
 
93
        'sequence': 1,
 
94
    }
 
95
 
 
96
    def init(self, cr):
 
97
        """ Migration stuff, name is not anymore methods names
 
98
        but models name"""
 
99
        cr.execute("""
 
100
        UPDATE account_easy_reconcile_method
 
101
        SET name = 'easy.reconcile.simple.partner'
 
102
        WHERE name = 'action_rec_auto_partner'
 
103
        """)
 
104
        cr.execute("""
 
105
        UPDATE account_easy_reconcile_method
 
106
        SET name = 'easy.reconcile.simple.name'
 
107
        WHERE name = 'action_rec_auto_name'
 
108
        """)
 
109
 
 
110
 
 
111
class account_easy_reconcile(Model):
 
112
 
 
113
    _name = 'account.easy.reconcile'
 
114
    _description = 'account easy reconcile'
 
115
 
 
116
    def _get_total_unrec(self, cr, uid, ids, name, arg, context=None):
 
117
        obj_move_line = self.pool.get('account.move.line')
 
118
        res = {}
 
119
        for task in self.browse(cr, uid, ids, context=context):
 
120
            res[task.id] = len(obj_move_line.search(
 
121
                cr, uid,
 
122
                [('account_id', '=', task.account.id),
 
123
                 ('reconcile_id', '=', False),
 
124
                 ('reconcile_partial_id', '=', False)],
 
125
                context=context))
 
126
        return res
 
127
 
 
128
    def _get_partial_rec(self, cr, uid, ids, name, arg, context=None):
 
129
        obj_move_line = self.pool.get('account.move.line')
 
130
        res = {}
 
131
        for task in self.browse(cr, uid, ids, context=context):
 
132
            res[task.id] = len(obj_move_line.search(
 
133
                cr, uid,
 
134
                [('account_id', '=', task.account.id),
 
135
                 ('reconcile_id', '=', False),
 
136
                 ('reconcile_partial_id', '!=', False)],
 
137
                context=context))
 
138
        return res
 
139
 
 
140
    _columns = {
 
141
        'name': fields.char('Name', size=64, required=True),
 
142
        'account': fields.many2one('account.account', 'Account', required=True),
 
143
        'reconcile_method': fields.one2many('account.easy.reconcile.method', 'task_id', 'Method'),
 
144
        'scheduler': fields.many2one('ir.cron', 'scheduler', readonly=True),
 
145
        'rec_log': fields.text('log', readonly=True),
 
146
        'unreconciled_count': fields.function(_get_total_unrec,
 
147
            type='integer', string='Fully Unreconciled Entries'),
 
148
        'reconciled_partial_count': fields.function(_get_partial_rec,
 
149
            type='integer', string='Partially Reconciled Entries'),
 
150
    }
 
151
 
 
152
    def copy_data(self, cr, uid, id, default=None, context=None):
 
153
        if default is None:
 
154
            default = {}
 
155
        default = dict(default, rec_log=False, scheduler=False)
 
156
        return super(account_easy_reconcile, self).copy_data(
 
157
            cr, uid, id, default=default, context=context)
 
158
 
 
159
    def _prepare_run_transient(self, cr, uid, rec_method, context=None):
 
160
        return {'account_id': rec_method.task_id.account.id,
 
161
                'write_off': rec_method.write_off,
 
162
                'account_lost_id': rec_method.account_lost_id and \
 
163
                        rec_method.account_lost_id.id,
 
164
                'account_profit_id': rec_method.account_profit_id and \
 
165
                        rec_method.account_profit_id.id,
 
166
                'journal_id': rec_method.journal_id and rec_method.journal_id.id,
 
167
                'date_base_on': rec_method.date_base_on,
 
168
                'filter': rec_method.filter}
 
169
 
 
170
    def run_reconcile(self, cr, uid, ids, context=None):
 
171
        if context is None:
 
172
            context = {}
 
173
        for rec_id in ids:
 
174
            rec = self.browse(cr, uid, rec_id, context=context)
 
175
            total_rec = 0
 
176
            total_partial_rec = 0
 
177
            details = []
 
178
            count = 0
 
179
            for method in rec.reconcile_method:
 
180
                count += 1
 
181
 
 
182
                rec_model = self.pool.get(method.name)
 
183
                auto_rec_id = rec_model.create(
 
184
                    cr, uid,
 
185
                    self._prepare_run_transient(cr, uid, method, context=context),
 
186
                    context=context)
 
187
 
 
188
                rec_ids, partial_ids = rec_model.automatic_reconcile(
 
189
                    cr, uid, auto_rec_id, context=context)
 
190
 
 
191
                details.append(_('method %d : full: %d lines, partial: %d lines') % \
 
192
                    (count, len(rec_ids), len(partial_ids)))
 
193
 
 
194
                total_rec += len(rec_ids)
 
195
                total_partial_rec += len(partial_ids)
 
196
 
 
197
            log = self.read(cr, uid, rec_id, ['rec_log'], context=context)['rec_log']
 
198
            log_lines = log and log.splitlines() or []
 
199
            log_lines[0:0] = [_("%s : %d lines have been fully reconciled" \
 
200
                " and %d lines have been partially reconciled (%s)") % \
 
201
                (time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), total_rec,
 
202
                    total_partial_rec, ' | '.join(details))]
 
203
            log = "\n".join(log_lines)
 
204
            self.write(cr, uid, rec_id, {'rec_log': log}, context=context)
 
205
        return True
 
206