~alejandrosantana/account-financial-tools/7.0-account-financial_tools--add--account_account_extended_search

« back to all changes in this revision

Viewing changes to account_renumber/wizard/wizard_renumber.py

[IMP] account_renumber: General Refactoring:

- Changed types to orm.Model, orm.TransientModel and orm.AbstractModel.
- Change renumbering assistants in renumbering, show results and cancellation to version 7.
- Remove legacy code calls.
- Contributions have been written in the standard format of the community.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
##############################################################################
 
3
#
 
4
#    OpenERP - Account renumber wizard
 
5
#    Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved
 
6
#    $Id$
 
7
#
 
8
#    This program is free software: you can redistribute it and/or modify
 
9
#    it under the terms of the GNU Affero General Public License as published
 
10
#    by the Free Software Foundation, either version 3 of the License, or
 
11
#    (at your option) any later version.
 
12
#
 
13
#    This program is distributed in the hope that it will be useful,
 
14
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
#    GNU Affero General Public License for more details.
 
17
#
 
18
#    You should have received a copy of the GNU Affero General Public License
 
19
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
#
 
21
##############################################################################
 
22
 
 
23
"""
 
24
Account renumber wizard
 
25
"""
 
26
__author__ = ["Borja López Soilán (Pexego)",
 
27
                "Omar Castiñeira Saavedra (Pexego)"]
 
28
 
 
29
 
 
30
from openerp.osv import fields, orm
 
31
from openerp.tools.translate import _
 
32
from datetime import datetime
 
33
import logging
 
34
import time
 
35
 
 
36
class wizard_renumber(orm.TransientModel):
 
37
    _name = "wizard.renumber"
 
38
    _columns = {
 
39
 
 
40
        'journal_ids': fields.many2many('account.journal', 'account_journal_wzd_renumber_rel', 
 
41
                                        'wizard_id', 'journal_id', required=True, help="Journals to renumber", string="Journals"),
 
42
        'period_ids': fields.many2many('account.period', 'account_period_wzd_renumber_rel', 'wizard_id', 'period_id', required=True,
 
43
                                       help='Fiscal periods to renumber', string="Periods", ondelete='null'),
 
44
        'number_next': fields.integer('First Number', required=True, help="Journal sequences will start counting on this number"),
 
45
        'state': fields.selection([('init', 'Initial'), ('renumber', 'Renumbering')], readonly=True)
 
46
                }
 
47
 
 
48
    _defaults = {
 
49
        'number_next': 1,
 
50
        'state': 'init'
 
51
    }
 
52
 
 
53
    ###############################
 
54
    # Helper methods
 
55
    ###############################
 
56
 
 
57
    def _process(self, s, date_to_use=None):
 
58
        """
 
59
        Based on ir_sequence._process. We need to have our own method
 
60
        as ir_sequence one will always use the current date.
 
61
        We will use the given date instead.
 
62
        """
 
63
        date_to_use = date_to_use or time
 
64
        return (s or '') % {
 
65
            'year': date_to_use.strftime('%Y'),
 
66
            'month': date_to_use.strftime('%m'),
 
67
            'day': date_to_use.strftime('%d'),
 
68
            'y': date_to_use.strftime('%y'),
 
69
            'doy': date_to_use.strftime('%j'),
 
70
            'woy': date_to_use.strftime('%W'),
 
71
            'weekday': date_to_use.strftime('%w'),
 
72
            'h24': time.strftime('%H'),
 
73
            'h12': time.strftime('%I'),
 
74
            'min': time.strftime('%M'),
 
75
            'sec': time.strftime('%S'),
 
76
        }
 
77
 
 
78
    def get_id(self, cr, uid, sequence_id, test='id=%s', context=None, date_to_use=None):
 
79
        """
 
80
        Based on ir_sequence.get_id. We need to have our own method
 
81
        as ir_sequence one will always use the current date for the prefix
 
82
        and sufix processing. We will use the given date instead.
 
83
        """
 
84
        try:
 
85
            cr.execute('SELECT id, number_next, prefix, suffix, padding FROM ir_sequence WHERE ' + test + ' AND active=%s FOR UPDATE', (sequence_id, True))
 
86
            res = cr.dictfetchone()
 
87
            if res:
 
88
                cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=%s', (res['id'], True))
 
89
                if res['number_next']:
 
90
                    return self._process(res['prefix'], date_to_use=date_to_use) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix'], date_to_use=date_to_use)
 
91
                else:
 
92
                    return self._process(res['prefix'], date_to_use=date_to_use) + self._process(res['suffix'], date_to_use=date_to_use)
 
93
        finally:
 
94
            cr.commit()
 
95
        return False
 
96
 
 
97
    def get_sequence_id_for_fiscalyear_id(self, cr, uid, sequence_id, fiscalyear_id, context=None):
 
98
        """
 
99
        Based on ir_sequence.get_id from the account module.
 
100
        Allows us to get the real sequence for the given fiscal year.
 
101
        """
 
102
        cr.execute('SELECT id FROM ir_sequence WHERE id=%s AND active=%s',
 
103
                   (sequence_id, True,))
 
104
        res = cr.dictfetchone()
 
105
        if res:
 
106
            seq_facade = self.pool.get('ir.sequence')
 
107
            for line in seq_facade.browse(cr, uid, res['id'], context=context).fiscal_ids:
 
108
                if line.fiscalyear_id.id == fiscalyear_id:
 
109
                    return line.sequence_id.id
 
110
        return sequence_id
 
111
 
 
112
    ############################################################################
 
113
    # Renumber form/action
 
114
    ##########################################################################
 
115
 
 
116
    def renumber(self, cr, uid, ids, context):
 
117
        """
 
118
        Action that renumbers all the posted moves on the given
 
119
        journal and periods, and returns their ids.
 
120
        """
 
121
        logger = logging.getLogger("account_renumber")
 
122
        obj = self.browse(cr, uid, ids[0])
 
123
 
 
124
        period_ids = [x.id for x in obj.period_ids]
 
125
        journal_ids = [x.id for x in obj.journal_ids]
 
126
        number_next = obj.number_next or 1
 
127
 
 
128
        if not (period_ids and journal_ids):
 
129
            raise orm.except_orm(_('No Data Available'), _(
 
130
                'No records found for your selection!'))
 
131
 
 
132
        logger.debug("Searching for account moves to renumber.")
 
133
        move_facade = self.pool.get('account.move')
 
134
        move_ids = move_facade.search(cr, uid, [('journal_id', 'in', journal_ids), ('period_id', 'in', period_ids), ('state', '=', 'posted')], limit=0, order='date,id', context=context)
 
135
 
 
136
        if len(move_ids) == 0:
 
137
            raise orm.except_orm(_('No Data Available'), _(
 
138
                'No records found for your selection!'))
 
139
        sequences_seen = []
 
140
        logger.debug("Renumbering %d account moves." % len(move_ids))
 
141
 
 
142
        for move in move_facade.browse(cr, uid, move_ids):
 
143
            #
 
144
            # Get the sequence to use for this move.
 
145
            # Note: We will use the journal's sequence or one of its
 
146
            #       children (if it has children sequences per fiscalyear)
 
147
            #
 
148
            sequence_id = self.get_sequence_id_for_fiscalyear_id(cr, uid,
 
149
                                                                 sequence_id=move.journal_id.sequence_id.id,
 
150
                                                                 fiscalyear_id=move.period_id.fiscalyear_id.id)
 
151
            if not sequence_id in sequences_seen:
 
152
                # First time we see this sequence, reset it
 
153
                self.pool.get('ir.sequence').write(
 
154
                    cr, uid, [sequence_id], {'number_next': number_next})
 
155
                sequences_seen.append(sequence_id)
 
156
 
 
157
            #
 
158
            # Generate (using our own get_id) and write the new move number.
 
159
            #
 
160
            date_to_use = datetime.strptime(move.date, '%Y-%m-%d')
 
161
            new_name = self.get_id(cr, uid, sequence_id,
 
162
                                   context=context, date_to_use=date_to_use)
 
163
            # Note: We can't just do a
 
164
            # "move_facade.write(cr, uid, [move.id], {'name': new_name})"
 
165
            # cause it might raise a "You can't do this modification on a confirmed entry"
 
166
            # exception.
 
167
            cr.execute('UPDATE account_move SET name=%s WHERE id=%s',
 
168
                       (new_name, move.id))
 
169
 
 
170
        logger.debug("%d account moves renumbered." % len(move_ids))
 
171
 
 
172
        obj.write({'state': 'renumber'})
 
173
 
 
174
        view_wizard = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_renumber', 'view_account_renumber_form')
 
175
        view_wizard_id = view_wizard and view_wizard[1] or False,
 
176
        res = {
 
177
            'type': 'ir.actions.act_window',
 
178
            'name': _("Wizard successfully executed "),
 
179
            'res_model': 'wizard.renumber',
 
180
            'view_type': 'form',
 
181
            'view_mode': 'form',
 
182
            'res_id': obj.id,
 
183
            'view_id': view_wizard_id,
 
184
            'context': context,
 
185
            'target': 'current',
 
186
            }
 
187
 
 
188
        return res
 
189
 
 
190
    ############################################################################
 
191
    # Show results action
 
192
    ##########################################################################
 
193
    def show_results(self, cr, uid, ids, context):
 
194
        """
 
195
        Action that shows the list of (non-draft) account moves from
 
196
        the selected journals and periods, so the user can review
 
197
        the renumbered account moves.
 
198
        """
 
199
        obj = self.browse(cr, uid, ids[0])
 
200
        period_ids = [x.id for x in obj.period_ids]
 
201
        journal_ids = [x.id for x in obj.journal_ids]
 
202
 
 
203
        assert (period_ids and journal_ids)
 
204
 
 
205
        view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'view_move_tree')
 
206
        view_id = view_ref and view_ref[1] or False,
 
207
        res = {
 
208
            'type': 'ir.actions.act_window',
 
209
            'name': _("Renumbered account moves"),
 
210
            'res_model': 'account.move',
 
211
            'domain': "[('journal_id','in',%s), ('period_id','in',%s), ('state','=','posted')]" % (repr(journal_ids), repr(period_ids)),
 
212
            'view_type': 'form',
 
213
            'view_mode': 'tree',
 
214
            'view_id': view_id,
 
215
            'context': context,
 
216
            'target': 'current',
 
217
            }
 
218
        return res
 
219
 
 
220
wizard_renumber()