~jgrandguillaume-c2c/account-financial-tools/account-constraints-adding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Pexego Sistemas Informáticos. All Rights Reserved
#    $Id$
#
#    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/>.
#
##############################################################################
"""
Set Partner in Moves Wizard
"""
__author__ = "Borja López Soilán (Pexego)"

import re
from osv import fields, osv
from tools.translate import _


class set_partner_in_moves(osv.osv_memory):
    """
    Set Partner in Moves Wizard

    Searchs for account move lines of that use the payable/receivable account
    of a single partner, and have no partner reference in the line,
    and sets the partner reference (partner_id).
    This may fix cases where the receivable/payable amounts displayed in the
    partner form does not match the balance of the receivable/payable accounts.
    """
    _name = "account_admin_tools.set_partner_in_moves"
    _description = "Set Partner in Moves Wizard"

    _columns = {
        'state': fields.selection([('new', 'New'), ('ready', 'Ready'), ('done', 'Done')], 'Status', readonly=True),
        'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True),
        'period_ids': fields.many2many('account.period', 'set_partner_in_moves_period_rel', 'wizard_id', 'period_id', "Periods"),
        'move_line_ids': fields.many2many('account.move.line', 'set_partner_in_move_move_line_rel', 'wizard_id', 'line_id', 'Move Lines'),
    }

    _defaults = {
        'company_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context).company_id.id,
        'move_line_ids': lambda self, cr, uid, context: context and context.get('move_line_ids', None),
        'period_ids': lambda self, cr, uid, context: context and context.get('period_ids', None),
        'state': lambda self, cr, uid, context: context and context.get('state', 'new'),
    }

    def _next_view(self, cr, uid, ids, view_name, args=None, context=None):
        """
        Return the next wizard view
        """
        if context is None:
            context = {}
        if args is None:
            args = {}
        ctx = context.copy()
        ctx.update(args)

        model_data_ids = self.pool.get('ir.model.data').search(cr, uid, [
            ('model', '=', 'ir.ui.view'),
            ('module', '=', 'account_admin_tools'),
            ('name', '=', view_name)
        ])
        resource_id = self.pool.get('ir.model.data').read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
        return {
            'name': _("Set Partner Reference in Moves"),
            'type': 'ir.actions.act_window',
            'res_model': 'account_admin_tools.set_partner_in_moves',
            'view_type': 'form',
            'view_mode': 'form',
            'views': [(resource_id, 'form')],
            'domain': "[('id', 'in', %s)]" % ids,
            'context': ctx,
            'target': 'new',
        }

    def _get_accounts_map(self, cr, uid, context=None):
        """
        Find the receivable/payable accounts that are associated with
        a single partner and return a (account.id, partner.id) map
        """
        partner_ids = self.pool.get(
            'res.partner').search(cr, uid, [], context=context)
        accounts_map = {}
        for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
            #
            # Add the receivable account to the map
            #
            if accounts_map.get(partner.property_account_receivable.id, None) is None:
                accounts_map[
                    partner.property_account_receivable.id] = partner.id
            else:
                # Two partners with the same receivable account: ignore
                # this account!
                accounts_map[partner.property_account_receivable.id] = 0
            #
            # Add the payable account to the map
            #
            if accounts_map.get(partner.property_account_payable.id, None) is None:
                accounts_map[partner.property_account_payable.id] = partner.id
            else:
                # Two partners with the same receivable account: ignore
                # this account!
                accounts_map[partner.property_account_payable.id] = 0
        return accounts_map

    def action_skip_new(self, cr, uid, ids, context=None):
        """
        Action that just skips the to the ready state
        """
        return self._next_view(cr, uid, ids, 'view_set_partner_in_moves_ready_form', {'state': 'ready'}, context)

    def action_find_moves_missing_partner(self, cr, uid, ids, context=None):
        """
        Action that searchs for account move lines of payable/receivable
        accounts (of just one partner) that don't have the partner reference.
        """
        wiz = self.browse(cr, uid, ids[0], context)

        # FIXME: The next block of code is a workaround to the lp:586252 bug of the 6.0 client.
        #        (https://bugs.launchpad.net/openobject-client/+bug/586252)
        if wiz.period_ids:
            period_ids = [period.id for period in wiz.period_ids]
        else:
            period_ids = context and context.get('period_ids')

        move_line_ids = []
        accounts_map = self._get_accounts_map(cr, uid, context=context)

        #
        # Find the account move lines, of each of the accounts in the map
        # that don't have a partner set.
        #
        query = """
                SELECT id FROM account_move_line
                WHERE account_id=%s
                      AND partner_id IS NULL
                """
        if period_ids:
            query += """      AND period_id IN %s"""

        for account_id in accounts_map.keys():
            if accounts_map[account_id] != 0:
                if period_ids:
                    cr.execute(query, (account_id, tuple(period_ids)))
                else:
                    cr.execute(query, (account_id,))
                new_move_line_ids = filter(
                    None, map(lambda x: x[0], cr.fetchall()))
                if new_move_line_ids:
                    move_line_ids.extend(new_move_line_ids)

        #
        # Return the next view: Show 'ready' view
        #
        args = {
            'move_line_ids': move_line_ids,
            'state': 'ready',
        }
        return self._next_view(cr, uid, ids, 'view_set_partner_in_moves_ready_form', args, context)

    def action_set_partner_in_moves(self, cr, uid, ids, context=None):
        """
        Action that sets for each partner payable/receivable account,
        that is used only on one partner, the parner reference on its move
        lines.
        """
        wiz = self.browse(cr, uid, ids[0], context)

        # FIXME: The next block of code is a workaround to the lp:586252 bug of the 6.0 client.
        #        (https://bugs.launchpad.net/openobject-client/+bug/586252)
        if wiz.move_line_ids:
            move_line_ids = [line.id for line in wiz.move_line_ids]
        else:
            move_line_ids = context and context.get('move_line_ids')

        accounts_map = self._get_accounts_map(cr, uid, context=context)

        #
        # Update the account move lines, of each of the accounts in the map
        # that don't have a partner set, with the associated partner.
        #
        query = """
                UPDATE account_move_line
                SET partner_id=%s
                WHERE id=%s
                      AND partner_id IS NULL
                """
        for line in self.pool.get('account.move.line').browse(cr, uid, move_line_ids, context=context):
            if accounts_map[line.account_id.id] != 0:
                cr.execute(query, (accounts_map[line.account_id.id], line.id))

        #
        # Return the next view: Show 'done' view
        #
        args = {
            'move_line_ids': move_line_ids,
            'state': 'done',
        }
        return self._next_view(cr, uid, ids, 'view_set_partner_in_moves_done_form', args, context)


set_partner_in_moves()