~unifield-team/unifield-wm/us-826

« back to all changes in this revision

Viewing changes to analytic_distribution/analytic_account.py

[MOVE] funding_pool module to analytic_distribution module

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
##############################################################################
3
 
#
4
 
#    OpenERP, Open Source Management Solution
5
 
#    Copyright (C) 2011 MSF, TeMPO Consulting.
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 datetime
23
 
from dateutil.relativedelta import relativedelta
24
 
from osv import fields, osv
25
 
from tools.translate import _
26
 
from lxml import etree
27
 
 
28
 
class analytic_account(osv.osv):
29
 
    _name = "account.analytic.account"
30
 
    _inherit = "account.analytic.account"
31
 
    
32
 
    _columns = {
33
 
        'name': fields.char('Name', size=128, required=True),
34
 
        'code': fields.char('Code', size=24),
35
 
        'type': fields.selection([('view','View'), ('normal','Normal')], 'Type', help='If you select the View Type, it means you won\'t allow to create journal entries using that account.'),
36
 
        'date_start': fields.date('Active from', required=True),
37
 
        'date': fields.date('Inactive from', select=True),
38
 
        'category': fields.selection([('OC','Cost Center'),
39
 
            ('FUNDING','Funding Pool'),
40
 
            ('FREE1','Free 1'),
41
 
            ('FREE2','Free 2')], 'Category', select=1),
42
 
        'cost_center_ids': fields.many2many('account.analytic.account', 'funding_pool_associated_cost_centers', 'funding_pool_id', 'cost_center_id', string='Cost Centers'),
43
 
        'account_ids': fields.many2many('account.account', 'funding_pool_associated_accounts', 'funding_pool_id', 'account_id', string='Accounts'),
44
 
        'for_fx_gain_loss': fields.boolean(string="For FX gain/loss", help="Is this account for default FX gain/loss?"),
45
 
    }
46
 
    
47
 
    _defaults ={
48
 
        'date_start': lambda *a: (datetime.datetime.today() + relativedelta(months=-3)).strftime('%Y-%m-%d'),
49
 
        'for_fx_gain_loss': lambda *a: False,
50
 
    }
51
 
    def _check_unicity(self, cr, uid, ids, context=None):
52
 
        if not context:
53
 
            context = {}
54
 
        for account in self.browse(cr, uid, ids, context=context):
55
 
            bad_ids = self.search(cr, uid, [('category', '=', account.category),('|'),('name', '=ilike', account.name),('code', '=ilike', account.code)])
56
 
            if len(bad_ids) and len(bad_ids) > 1:
57
 
                return False
58
 
        return True
59
 
 
60
 
    def _check_gain_loss_account_unicity(self, cr, uid, ids, context=None):
61
 
        """
62
 
        Check that no more account is "for_fx_gain_loss" available.
63
 
        """
64
 
        if not context:
65
 
            context = {}
66
 
        search_ids = self.search(cr, uid, [('for_fx_gain_loss', '=', True)])
67
 
        if search_ids and len(search_ids) > 1:
68
 
            return False
69
 
        return True
70
 
 
71
 
    def _check_gain_loss_account_type(self, cr, uid, ids, context=None):
72
 
        """
73
 
        Check account type for fx_gain_loss_account: should be Normal type and Cost Center category
74
 
        """
75
 
        if not context:
76
 
            context = {}
77
 
        for account in self.browse(cr, uid, ids, context=context):
78
 
            if account.for_fx_gain_loss == True and (account.type != 'normal' or account.category != 'OC'):
79
 
                return False
80
 
        return True
81
 
 
82
 
    _constraints = [
83
 
        (_check_unicity, 'You cannot have the same code or name between analytic accounts in the same category!', ['code', 'name', 'category']),
84
 
        (_check_gain_loss_account_unicity, 'You can only have one account used for FX gain/loss!', ['for_fx_gain_loss']),
85
 
        (_check_gain_loss_account_type, 'You have to use a Normal account type and Cost Center category for FX gain/loss!', ['for_fx_gain_loss']),
86
 
    ]
87
 
 
88
 
    def copy(self, cr, uid, id, default=None, context=None, done_list=[], local=False):
89
 
        account = self.browse(cr, uid, id, context=context)
90
 
        if not default:
91
 
            default = {}
92
 
        default = default.copy()
93
 
        default['code'] = (account['code'] or '') + '(copy)'
94
 
        default['name'] = (account['name'] or '') + '(copy)'
95
 
        return super(analytic_account, self).copy(cr, uid, id, default, context=context)
96
 
    
97
 
    def set_funding_pool_parent(self, cr, uid, vals):
98
 
        if 'category' in vals and \
99
 
           'code' in vals and \
100
 
            vals['category'] == 'FUNDING' and \
101
 
            vals['code'] != 'FUNDING':
102
 
            # for all accounts except the parent one
103
 
            funding_pool_parent = self.search(cr, uid, [('category', '=', 'FUNDING'), ('parent_id', '=', False)])[0]
104
 
            vals['parent_id'] = funding_pool_parent
105
 
 
106
 
    def _check_date(self, vals):
107
 
        if 'date' in vals and vals['date'] is not False:
108
 
            if vals['date'] <= datetime.date.today().strftime('%Y-%m-%d'):
109
 
                 # validate the date (must be > today)
110
 
                 raise osv.except_osv(_('Warning !'), _('You cannot set an inactivity date lower than tomorrow!'))
111
 
            elif 'date_start' in vals and not vals['date_start'] < vals['date']:
112
 
                # validate that activation date 
113
 
                raise osv.except_osv(_('Warning !'), _('Activation date must be lower than inactivation date!'))
114
 
 
115
 
    def create(self, cr, uid, vals, context=None):
116
 
        """
117
 
        Some verifications before analytic account creation
118
 
        """
119
 
        self._check_date(vals)
120
 
        self.set_funding_pool_parent(cr, uid, vals)
121
 
        return super(analytic_account, self).create(cr, uid, vals, context=context)
122
 
    
123
 
    def write(self, cr, uid, ids, vals, context=None):
124
 
        """
125
 
        Some verifications before analytic account write
126
 
        """
127
 
        self._check_date(vals)
128
 
        self.set_funding_pool_parent(cr, uid, vals)
129
 
        return super(analytic_account, self).write(cr, uid, ids, vals, context=context)
130
 
    
131
 
    def search(self, cr, uid, args, offset=0, limit=None, order=None,
132
 
            context=None, count=False):
133
 
        if context and 'filter_inactive_accounts' in context and context['filter_inactive_accounts']:
134
 
            args.append(('date_start', '<=', datetime.date.today().strftime('%Y-%m-%d')))
135
 
            args.append('|')
136
 
            args.append(('date', '>', datetime.date.today().strftime('%Y-%m-%d')))
137
 
            args.append(('date', '=', False))
138
 
            
139
 
        if context and 'search_by_ids' in context and context['search_by_ids']:
140
 
            args2 = args[-1][2]
141
 
            del args[-1]
142
 
            ids = []
143
 
            for arg in args2:
144
 
                ids.append(arg[1])
145
 
            args.append(('id', 'in', ids))
146
 
            
147
 
        return super(analytic_account, self).search(cr, uid, args, offset, limit,
148
 
                order, context=context, count=count)
149
 
    
150
 
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
151
 
        if not context:
152
 
            context = {}
153
 
        view = super(analytic_account, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
154
 
        try:
155
 
            oc_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_project')[1]
156
 
        except ValueError:
157
 
            oc_id = 0
158
 
        if view_type=='form':
159
 
            tree = etree.fromstring(view['arch'])
160
 
            fields = tree.xpath('/form/field[@name="cost_center_ids"]')
161
 
            for field in fields:
162
 
                field.set('domain', "[('type', '!=', 'view'), ('id', 'child_of', [%s])]" % oc_id)
163
 
            view['arch'] = etree.tostring(tree)
164
 
        return view
165
 
    
166
 
    def on_change_category(self, cr, uid, id, category):
167
 
        if not category:
168
 
            return {}
169
 
        res = {'value': {}, 'domain': {}}
170
 
        parent = self.search(cr, uid, [('category', '=', category), ('parent_id', '=', False)])[0]
171
 
        res['value']['parent_id'] = parent
172
 
        res['domain']['parent_id'] = [('category', '=', category), ('type', '=', 'view')]
173
 
        return res
174
 
    
175
 
    def unlink(self, cr, uid, ids, context=None):
176
 
        """
177
 
        Delete the dummy analytic account is forbidden!
178
 
        """
179
 
        # Some verification
180
 
        if not context:
181
 
            context = {}
182
 
        if isinstance(ids, (int, long)):
183
 
            ids = [ids]
184
 
        # Prepare some values
185
 
        analytic_accounts = []
186
 
        # Search dummy CC that have xml_id: analytic_account_project_dummy
187
 
        try:
188
 
            dummy_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_project_dummy')[1]
189
 
        except ValueError:
190
 
            dummy_id = 0
191
 
        analytic_accounts.append(dummy_id)
192
 
        # Search OC CC
193
 
        try:
194
 
            oc_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_project')[1]
195
 
        except ValueError:
196
 
            oc_id = 0
197
 
        analytic_accounts.append(oc_id)
198
 
        # Search Funding Pool
199
 
        try:
200
 
            fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_funding_pool')[1]
201
 
        except ValueError:
202
 
            fp_id = 0
203
 
        analytic_accounts.append(fp_id)
204
 
        # Search Free 1
205
 
        try:
206
 
            f1_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_free_1')[1]
207
 
        except ValueError:
208
 
            f1_id = 0
209
 
        analytic_accounts.append(f1_id)
210
 
        # Search Free 2
211
 
        try:
212
 
            f2_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_free_2')[1]
213
 
        except ValueError:
214
 
            f2_id = 0
215
 
        analytic_accounts.append(f2_id)
216
 
        # Search MSF Private Fund
217
 
        try:
218
 
            msf_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
219
 
        except ValueError:
220
 
            msf_id = 0
221
 
        analytic_accounts.append(msf_id)
222
 
        # Accounts verification
223
 
        for id in ids:
224
 
            if id in analytic_accounts:
225
 
                raise osv.except_osv(_('Error'), _('You cannot delete this Analytic Account!'))
226
 
        return super(analytic_account, self).unlink(cr, uid, ids, context=context)
227
 
 
228
 
analytic_account()
229
 
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: