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 financing_contract_format_line(osv.osv):
26
_name = "financing.contract.format.line"
28
def _create_domain(self, header, element_list):
29
domain = "('" + header + "', 'in', ["
30
if len(element_list) > 0:
31
for element in element_list:
32
domain += str(element.id)
38
def _get_number_of_childs(self, cr, uid, ids, field_name=None, arg=None, context={}):
42
if isinstance(ids, (int, long)):
46
for line in self.browse(cr, uid, ids, context=context):
47
res[line.id] = line.child_ids and len(line.child_ids) or 0
50
def _get_parent_ids(self, cr, uid, ids, context=None):
52
for line in self.browse(cr, uid, ids, context=context):
54
res.append(line.parent_id.id)
57
def _get_total_costs(self, cr, uid, browse_overhead_line, field_name=None, context=None):
58
# since this is only called from the overhead line, the domain is
59
# "all children of the parent line, except the current one"
61
total_line_ids = [line.id for line in browse_overhead_line.format_id.actual_line_ids if not line.parent_id and line.line_type != 'overhead']
63
if field_name and field_name in ('allocated_budget', 'project_budget'):
64
total_costs = self._get_budget_amount(cr, uid, total_line_ids, field_name, context=context)
66
total_costs = self._get_actual_amount(cr, uid, total_line_ids, field_name, context=context)
67
for total_cost in total_costs.values():
71
def _get_account_ids(self, browse_line, funding_pool_account_ids):
73
if browse_line.line_type != 'view':
74
result = [account for account in browse_line.account_ids if account.id in funding_pool_account_ids]
76
for child_line in browse_line.child_ids:
77
result += self._get_account_ids(child_line, funding_pool_account_ids)
80
def _get_general_domain(self, cr, uid, browse_format, domain_type, context=None):
81
# Method to get the domain (allocated or project) of a line
82
date_domain = "[('date', '>=', '"
83
date_domain += browse_format.eligibility_from_date
84
date_domain += "'), ('date', '<=', '"
85
date_domain += browse_format.eligibility_to_date
87
# list of expense accounts in the funding pools.
88
# we take them all (funded and project), as for funded,
89
# we are sure that no allocation will be done with
90
# (funded funding pool, account in other funding pool)
91
funding_pool_account_ids = []
92
for funding_pool_line in browse_format.funding_pool_ids:
93
funding_pool = funding_pool_line.funding_pool_id
94
for account in funding_pool.account_ids:
95
funding_pool_account_ids.append(account.id)
98
if domain_type == 'allocated':
99
funding_pool_ids = [funding_pool_line.funding_pool_id for funding_pool_line in browse_format.funding_pool_ids if funding_pool_line.funded]
101
funding_pool_ids = [funding_pool_line.funding_pool_id for funding_pool_line in browse_format.funding_pool_ids]
102
funding_pool_domain = self._create_domain('account_id', funding_pool_ids)
104
cost_center_domain = self._create_domain('cost_center_id', browse_format.cost_center_ids)
105
return {'date_domain': date_domain,
106
'funding_pool_domain': funding_pool_domain,
107
'cost_center_domain': cost_center_domain,
108
'funding_pool_account_ids': funding_pool_account_ids}
110
def _get_analytic_domain(self, cr, uid, browse_line, domain_type, context=None):
111
if browse_line.line_type in ('consumption', 'overhead'):
112
# No domain for those
115
format = browse_line.format_id
116
general_domain = self._get_general_domain(cr, uid, format, domain_type, context=context)
118
account_ids = self._get_account_ids(browse_line, general_domain['funding_pool_account_ids'])
119
account_domain = self._create_domain('general_account_id', account_ids)
120
# create the final domain
121
date_domain = eval(general_domain['date_domain'])
122
if domain_type == 'allocated':
123
return [date_domain[0],
125
eval(account_domain),
126
eval(general_domain['funding_pool_domain'])]
128
return [date_domain[0],
130
eval(account_domain),
131
eval(general_domain['funding_pool_domain']),
132
eval(general_domain['cost_center_domain'])]
134
def _get_budget_amount(self, cr, uid, ids, field_name=None, arg=None, context=None):
136
Method to compute the allocated budget/amounts, depending on the information in the line
139
for line in self.browse(cr, uid, ids, context=context):
143
if line.line_type in ('actual', 'consumption'):
144
# Value is set by the user, just return it
145
if field_name == 'allocated_budget':
146
res[line.id] = line.allocated_budget_value
147
elif field_name == 'project_budget':
148
res[line.id] = line.project_budget_value
149
elif line.line_type == 'view':
150
# Sum of all its children
152
for child_line in line.child_ids:
153
child_values = self._get_budget_amount(cr, uid, [child_line.id], field_name, context=context)
154
sum_budget += child_values[child_line.id]
155
res[line.id] = sum_budget
156
elif line.line_type == 'overhead':
158
if line.overhead_type == 'cost_percentage':
159
# percentage of all costs (sum of all 2nd-level lines, except overhead)
160
total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
161
res[line.id] = total_costs * line.overhead_percentage / 100.0
162
elif line.overhead_type == 'grant_percentage':
163
# percentage of all costs (sum of all 2nd-level lines, except overhead)
164
total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
165
res[line.id] = total_costs * line.overhead_percentage / (100.0 - line.overhead_percentage)
168
def _get_actual_amount(self, cr, uid, ids, field_name=None, arg=None, context=None):
170
Method to compute the allocated budget/amounts, depending on the information in the line
173
for line in self.browse(cr, uid, ids, context=context):
177
if line.line_type == 'consumption':
178
# Value is set by the user, just return it
179
if field_name == 'allocated_real':
180
res[line.id] = line.allocated_real_value
181
elif field_name == 'project_real':
182
res[line.id] = line.project_real_value
183
elif line.line_type == 'view':
184
# Sum of all its children
186
for child_line in line.child_ids:
187
child_values = self._get_actual_amount(cr, uid, [child_line.id], field_name, context=context)
188
sum_real += child_values[child_line.id]
189
res[line.id] = sum_real
190
elif line.line_type == 'overhead':
192
if line.overhead_type == 'cost_percentage':
193
# percentage of all costs (sum of all 2nd-level lines, except overhead)
194
total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
195
res[line.id] = total_costs * line.overhead_percentage / 100.0
196
elif line.overhead_type == 'grant_percentage':
197
# percentage of all costs (sum of all 2nd-level lines, except overhead)
198
total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
199
res[line.id] = total_costs * line.overhead_percentage / (100.0 - line.overhead_percentage)
200
elif line.line_type == 'actual':
201
# sum of analytic lines, determined by the domain
203
if field_name == 'project_real':
204
analytic_domain = self._get_analytic_domain(cr, uid, line, 'project', context=context)
205
elif field_name == 'allocated_real':
206
analytic_domain = self._get_analytic_domain(cr, uid, line, 'allocated', context=context)
207
# selection of analytic lines
208
if 'reporting_currency' in context:
209
analytic_line_obj = self.pool.get('account.analytic.line')
210
analytic_lines = analytic_line_obj.search(cr, uid, analytic_domain ,context=context)
212
currency_table = None
213
if 'currency_table_id' in context:
214
currency_table = context['currency_table_id']
215
for analytic_line in analytic_line_obj.browse(cr, uid, analytic_lines, context=context):
216
date_context = {'date': analytic_line.source_date or analytic_line.date,
217
'currency_table_id': currency_table}
218
real_sum += self.pool.get('res.currency').compute(cr,
220
analytic_line.currency_id.id,
221
context['reporting_currency'],
222
analytic_line.amount_currency or 0.0,
224
context=date_context)
225
real_sum = abs(real_sum)
226
res[line.id] = real_sum
230
'name': fields.char('Name', size=64, required=True),
231
'code': fields.char('Code', size=16, required=True),
232
'format_id': fields.many2one('financing.contract.format', 'Format'),
233
'account_ids': fields.many2many('account.account', 'financing_contract_actual_accounts', 'actual_line_id', 'account_id', string='Accounts'),
234
'parent_id': fields.many2one('financing.contract.format.line', 'Parent line', ondelete='cascade'),
235
'child_ids': fields.one2many('financing.contract.format.line', 'parent_id', 'Child lines'),
236
'line_type': fields.selection([('view','View'),
238
('consumption','Consumption'),
239
('overhead','Overhead')], 'Line type', required=True),
240
'overhead_type': fields.selection([('cost_percentage','Percentage of total costs'),
241
('grant_percentage','Percentage of direct costs')], 'Overhead percentage type'),
242
'allocated_budget_value': fields.float('Budget allocated amount (value)'),
243
'project_budget_value': fields.float('Budget project amount (value)'),
244
'allocated_real_value': fields.float('Real allocated amount (value)'),
245
'project_real_value': fields.float('Real project amount (value)'),
246
'overhead_percentage': fields.float('Overhead percentage'),
247
'allocated_budget': fields.function(_get_budget_amount, method=True, store=False, string="Funded amount - Budget", type="float", readonly="True"),
248
'project_budget': fields.function(_get_budget_amount, method=True, store=False, string="Total project amount - Budget", type="float", readonly="True"),
249
'allocated_real': fields.function(_get_actual_amount, method=True, store=False, string="Funded amount - Actuals", type="float", readonly="True"),
250
'project_real': fields.function(_get_actual_amount, method=True, store=False, string="Total project amount - Actuals", type="float", readonly="True"),
254
'line_type': 'actual',
255
'overhead_type': 'cost_percentage',
256
'parent_id': lambda *a: False
259
def create(self, cr, uid, vals, context=None):
262
# if the account is set as view, remove budget and account values
263
if 'line_type' in vals and vals['line_type'] == 'view':
264
vals['allocated_amount'] = 0.0
265
vals['project_amount'] = 0.0
266
vals['account_ids'] = []
267
return super(financing_contract_format_line, self).create(cr, uid, vals, context=context)
269
def write(self, cr, uid, ids, vals, context=None):
272
if isinstance(ids, (int, long)):
274
# if the account is set as view, remove budget and account values
275
if 'line_type' in vals and vals['line_type'] == 'view':
276
vals['allocated_amount'] = 0.0
277
vals['project_amount'] = 0.0
278
vals['account_ids'] = [(6, 0, [])]
279
return super(financing_contract_format_line, self).write(cr, uid, ids, vals, context=context)
281
def copy_format_line(self, cr, uid, browse_source_line, destination_format_id, parent_id=None, context=None):
282
if destination_format_id:
284
'name': browse_source_line.name,
285
'code': browse_source_line.code,
286
'format_id': destination_format_id,
287
'parent_id': parent_id,
288
'line_type': browse_source_line.line_type,
291
for account in browse_source_line.account_ids:
292
account_ids.append(account.id)
293
format_line_vals['account_ids'] = [(6, 0, account_ids)]
294
parent_line_id = self.pool.get('financing.contract.format.line').create(cr, uid, format_line_vals, context=context)
295
for child_line in browse_source_line.child_ids:
296
self.copy_format_line(cr, uid, child_line, destination_format_id, parent_line_id, context=context)
299
financing_contract_format_line()
301
class financing_contract_format(osv.osv):
303
_name = "financing.contract.format"
304
_inherit = "financing.contract.format"
307
'actual_line_ids': fields.one2many('financing.contract.format.line', 'format_id', 'Actual lines')
310
def copy_format_lines(self, cr, uid, source_id, destination_id, context=None):
311
# remove all old report lines
312
destination_obj = self.browse(cr, uid, destination_id, context=context)
313
for to_remove_line in destination_obj.actual_line_ids:
314
self.pool.get('financing.contract.format.line').unlink(cr, uid, to_remove_line.id, context=context)
315
source_obj = self.browse(cr, uid, source_id, context=context)
316
# Method to copy a format
318
for source_line in source_obj.actual_line_ids:
319
if not source_line.parent_id:
320
self.pool.get('financing.contract.format.line').copy_format_line(cr,
328
financing_contract_format()
329
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
b'\\ No newline at end of file'