1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2011 MSF, TeMPO Consulting.
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.
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.
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/>.
20
##############################################################################
22
from osv import fields, osv
24
class msf_instance(osv.osv):
25
_name = 'msf.instance'
27
def _get_current_instance_level(self, cr, uid, ids, fields, arg, context=None):
30
res = dict.fromkeys(ids, False)
31
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
32
if user.company_id and user.company_id.instance_id:
34
res[id] = user.company_id.instance_id.level
37
def _get_top_cost_center(self, cr, uid, ids, fields, arg, context=None):
39
Search for top cost center from the given instance.
44
if isinstance(ids, (int, long)):
47
res = dict.fromkeys(ids, False)
48
# Search top cost center
49
for instance in self.read(cr, uid, ids, ['target_cost_center_ids', 'level'], context=context):
50
target_cc_ids = instance.get('target_cost_center_ids', False)
52
for target in self.pool.get('account.target.costcenter').read(cr, uid, target_cc_ids, ['is_top_cost_center', 'cost_center_id']):
53
if target.get('is_top_cost_center', False):
54
res[instance.get('id')] = target.get('cost_center_id', [False])[0]
56
elif instance.get('level', '') == 'section':
57
parent_cost_centers = self.pool.get('account.analytic.account').search(cr, uid, [('category', '=', 'OC'), ('parent_id', '=', '')], context=context)
58
if len(parent_cost_centers) > 0:
59
res[instance.get('id')] = parent_cost_centers[0]
62
def _get_po_fo_cost_center(self, cr, uid, ids, fields, arg, context=None):
65
if isinstance(ids, (int, long)):
68
res = dict.fromkeys(ids, False)
69
for instance in self.browse(cr, uid, ids, context=context):
70
if instance.target_cost_center_ids:
71
for target in instance.target_cost_center_ids:
72
if target.is_po_fo_cost_center:
73
res[instance.id] = target.cost_center_id.id
75
elif instance.level == 'section':
76
parent_cost_centers = self.pool.get('account.analytic.account').search(cr, uid, [('category', '=', 'OC'), ('parent_id', '=', '')], context=context)
77
if len(parent_cost_centers) > 0:
78
res[instance.id] = parent_cost_centers[0]
82
'level': fields.selection([('section', 'Section'),
84
('project', 'Project')], 'Level', required=True),
85
'code': fields.char('Code', size=64, required=True),
86
'mission': fields.char('Mission', size=64),
87
'instance': fields.char('Instance', size=64),
88
#'parent_id': fields.many2one('msf.instance', 'Parent', domain=[('level', '!=', 'project'), ('state', '=', 'active')]),
89
'parent_id': fields.many2one('msf.instance', 'Parent', domain=[('level', '!=', 'project') ]),
90
'child_ids': fields.one2many('msf.instance', 'parent_id', 'Children'),
91
'name': fields.char('Name', size=64, required=True),
92
'note': fields.char('Note', size=256),
93
'target_cost_center_ids': fields.one2many('account.target.costcenter', 'instance_id', 'Target Cost Centers'),
94
'state': fields.selection([('draft', 'Draft'),
96
('inactive', 'Inactive')], 'State', required=True),
97
'move_prefix': fields.char('Account move prefix', size=5, required=True),
98
'reconcile_prefix': fields.char('Reconcilation prefix', size=5, required=True),
99
'current_instance_level': fields.function(_get_current_instance_level, method=True, store=False, string="Current Instance Level", type="char", readonly="True"),
100
'top_cost_center_id': fields.function(_get_top_cost_center, method=True, store=False, string="Top cost centre for budget consolidation", type="many2one", relation="account.analytic.account", readonly="True"),
101
'po_fo_cost_center_id': fields.function(_get_po_fo_cost_center, method=True, store=False, string="Cost centre picked for PO/FO reference", type="many2one", relation="account.analytic.account", readonly="True"),
106
'current_instance_level': 'section', # UTP-941 set the default value to section, otherwise all fields in the new form are readonly
109
def button_cost_center_wizard(self, cr, uid, ids, context=None):
112
if isinstance(ids, (int, long)):
120
'name': "Add Cost Centers",
121
'type': 'ir.actions.act_window',
122
'res_model': 'wizard.add.cost.centers',
124
'view_mode': 'form,tree',
129
def create(self, cr, uid, vals, context=None):
130
# Check if lines are imported from coordo; if now, create those
131
res_id = osv.osv.create(self, cr, uid, vals, context=context)
132
if 'parent_id' in vals and 'level' in vals and vals['level'] == 'project':
133
parent_instance = self.browse(cr, uid, vals['parent_id'], context=context)
134
instance = self.browse(cr, uid, res_id, context=context)
135
if len(parent_instance.target_cost_center_ids) != len(instance.target_cost_center_ids):
136
# delete existing cost center lines
137
old_target_line_ids = [x.id for x in instance.target_cost_center_ids]
138
self.unlink(cr, uid, old_target_line_ids, context=context)
139
# copy existing lines for project
140
for line_to_copy in parent_instance.target_cost_center_ids:
141
self.pool.get('account.target.costcenter').create(cr, uid, {'instance_id': instance.id,
142
'cost_center_id': line_to_copy.cost_center_id.id,
144
'parent_id': line_to_copy.id}, context=context)
148
def _check_name_code_unicity(self, cr, uid, ids, context=None):
151
for instance in self.browse(cr, uid, ids, context=context):
152
bad_ids = self.search(cr, uid, [('&'),
153
('state', '!=', 'inactive'),
155
('name', '=ilike', instance.name),
156
('code', '=ilike', instance.code)])
157
if len(bad_ids) and len(bad_ids) > 1:
161
def onchange_parent_id(self, cr, uid, ids, parent_id, level, context=None):
165
if isinstance(ids, (int, long)):
167
if parent_id and level == 'project':
168
parent_instance = self.browse(cr, uid, parent_id, context=context)
169
for instance in self.browse(cr, uid, ids, context=context):
170
# delete existing cost center lines
171
old_target_line_ids = [x.id for x in instance.target_cost_center_ids]
172
self.unlink(cr, uid, old_target_line_ids, context=context)
173
# copy existing lines for project
174
for line_to_copy in parent_instance.target_cost_center_ids:
175
self.pool.get('account.target.costcenter').create(cr, uid, {'instance_id': instance.id,
176
'cost_center_id': line_to_copy.cost_center_id.id,
178
'parent_id': line_to_copy.id}, context=context)
181
def _check_database_unicity(self, cr, uid, ids, context=None):
184
for instance in self.browse(cr, uid, ids, context=context):
185
bad_ids = self.search(cr, uid, [('&'),
186
('state', '!=', 'inactive'),
188
('instance', '!=', False),
189
('instance', '=', instance.instance)])
190
if len(bad_ids) and len(bad_ids) > 1:
194
def _check_move_prefix_unicity(self, cr, uid, ids, context=None):
197
for instance in self.browse(cr, uid, ids, context=context):
198
bad_ids = self.search(cr, uid, [('&'),
199
('state', '!=', 'inactive'),
200
('move_prefix', '=ilike', instance.move_prefix)])
201
if len(bad_ids) and len(bad_ids) > 1:
205
def _check_reconcile_prefix_unicity(self, cr, uid, ids, context=None):
208
for instance in self.browse(cr, uid, ids, context=context):
209
bad_ids = self.search(cr, uid, [('&'),
210
('state', '!=', 'inactive'),
211
('reconcile_prefix', '=ilike', instance.reconcile_prefix)])
212
if len(bad_ids) and len(bad_ids) > 1:
217
(_check_name_code_unicity, 'You cannot have the same code or name than an active instance!', ['code', 'name']),
218
(_check_database_unicity, 'You cannot have the same database than an active instance!', ['instance']),
219
(_check_move_prefix_unicity, 'You cannot have the same move prefix than an active instance!', ['move_prefix']),
220
(_check_reconcile_prefix_unicity, 'You cannot have the same reconciliation prefix than an active instance!', ['reconcile_prefix']),
223
def name_get(self, cr, user, ids, context=None):
226
result = self.browse(cr, user, ids, context=context)
230
res += [(rs.id, txt)]
231
context['level'] = rs.level
235
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
237
Search Instance regarding their code and their name
245
ids = self.search(cr, uid, [('code', 'ilike', name)]+ args, limit=limit, context=context)
247
ids = self.search(cr, uid, [('name', 'ilike', name)]+ args, limit=limit, context=context)
248
return self.name_get(cr, uid, ids, context=context)
250
def button_deactivate(self, cr, uid, ids, context=None):
254
self.write(cr, uid, ids, {'state': 'inactive'}, context=context)
257
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
259
Override the tree view to display historical prices according to context
263
res = super(msf_instance, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
264
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
266
if user.company_id and user.company_id.instance_id:
267
current_instance_level = user.company_id.instance_id.current_instance_level
269
if current_instance_level != 'section':
270
if 'hide_new_button="PROP_INSTANCE_HIDE_BUTTON"' in res['arch']:
271
res['arch'] = res['arch'].replace('hide_duplicate_button="PROP_INSTANCE_HIDE_BUTTON"', 'hide_duplicate_button="1"')
272
res['arch'] = res['arch'].replace('hide_delete_button="PROP_INSTANCE_HIDE_BUTTON"', 'hide_delete_button="1"')
273
res['arch'] = res['arch'].replace('hide_new_button="PROP_INSTANCE_HIDE_BUTTON"', 'hide_new_button="1" noteditable="1" notselectable="0"')
275
if 'target_cost_center_ids' in res['fields']:
276
arch = res['fields']['target_cost_center_ids']['views']['tree']['arch']
277
if 'hide_delete_button="PROP_INSTANCE_HIDE_BUTTON' in arch:
278
res['fields']['target_cost_center_ids']['views']['tree']['arch'] = arch.replace('hide_delete_button="PROP_INSTANCE_HIDE_BUTTON', 'noteditable="1" hide_delete_button="1')
280
if res['type'] == 'form' and 'hide_new_button="PROP_INSTANCE_HIDE_BUTTON"' in res['arch']:
281
res['arch'] = res['arch'].replace('hide_duplicate_button="PROP_INSTANCE_HIDE_BUTTON"', '')
282
res['arch'] = res['arch'].replace('hide_delete_button="PROP_INSTANCE_HIDE_BUTTON"', '')
283
res['arch'] = res['arch'].replace('hide_new_button="PROP_INSTANCE_HIDE_BUTTON"', '')
284
if 'target_cost_center_ids' in res['fields']:
285
arch = res['fields']['target_cost_center_ids']['views']['tree']['arch']
286
if 'hide_delete_button="PROP_INSTANCE_HIDE_BUTTON' in arch:
287
res['fields']['target_cost_center_ids']['views']['tree']['arch'] = arch.replace('PROP_INSTANCE_HIDE_BUTTON', '0')
294
class res_users(osv.osv):
295
_inherit = 'res.users'
298
def get_browse_user_instance(self, cr, uid, context=None):
299
current_user = self.browse(cr, uid, uid, context=context)
300
return current_user and current_user.company_id and current_user.company_id.instance_id or False
302
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: