20
20
##############################################################################
22
22
from osv import fields, osv
25
class financing_contract_funding_pool_line(osv.osv):
27
_name = "financing.contract.funding.pool.line"
30
'contract_id': fields.many2one('financing.contract.format', 'Contract', required=True),
31
'funding_pool_id': fields.many2one('account.analytic.account', 'Funding pool name', required=True),
32
'funded': fields.boolean('Funded'),
33
'total_project': fields.boolean('Total project'),
38
'total_project': True,
41
financing_contract_funding_pool_line()
43
24
class financing_contract_contract(osv.osv):
45
26
_name = "financing.contract.contract"
46
27
_inherits = {"financing.contract.format": "format_id"}
49
def contract_open(self, cr, uid, ids, *args):
50
self.write(cr, uid, ids, {
52
'open_date': datetime.date.today().strftime('%Y-%m-%d'),
53
'soft_closed_date': None
57
def contract_soft_closed(self, cr, uid, ids, *args):
58
self.write(cr, uid, ids, {
59
'state': 'soft_closed',
60
'soft_closed_date': datetime.date.today().strftime('%Y-%m-%d')
64
def contract_hard_closed(self, cr, uid, ids, *args):
65
self.write(cr, uid, ids, {
66
'state': 'hard_closed',
67
'hard_closed_date': datetime.date.today().strftime('%Y-%m-%d')
71
def get_contract_domain(self, cr, uid, browse_contract, reporting_type=None, context=None):
72
# we update the context with the contract reporting type and currency
73
format_line_obj = self.pool.get('financing.contract.format.line')
76
if reporting_type is None:
77
reporting_type = browse_contract.reporting_type
79
general_domain = format_line_obj._get_general_domain(cr,
81
browse_contract.format_id,
85
# parse parent lines (either value or sum of children's values)
86
for line in browse_contract.actual_line_ids:
87
if not line.parent_id:
88
account_ids += format_line_obj._get_account_ids(line, general_domain['funding_pool_account_ids'])
92
account_domain = format_line_obj._create_domain('general_account_id', account_ids)
93
date_domain = eval(general_domain['date_domain'])
94
if reporting_type == 'allocated':
95
analytic_domain = [date_domain[0],
98
eval(general_domain['funding_pool_domain'])]
100
analytic_domain = [date_domain[0],
102
eval(account_domain),
103
eval(general_domain['funding_pool_domain']),
104
eval(general_domain['cost_center_domain'])]
106
return analytic_domain
29
def _create_parent_line(self, cr, uid, contract_id, context=None):
30
# create parent reporting line (representing the contract in the tree view)
31
report_line_obj = self.pool.get('financing.contract.donor.reporting.line')
32
contract = self.browse(cr, uid, contract_id, context=context)
33
if contract.report_line:
34
# delete existing parent reporting line (representing the contract in the tree view)
35
report_line_obj.unlink(cr, uid, contract.report_line.id, context=context)
36
parent_line_id = False
38
general_information = self._get_general_information(cr, uid, contract, context=context)
39
if contract.name and contract.code and contract.reporting_type:
41
'name': contract.name,
42
'code': contract.code,
43
'date_domain': general_information['date_domain'],
44
'funding_pool_domain': general_information['funding_pool_domain'],
45
'cost_center_domain': general_information['cost_center_domain'],
46
'computation_type': 'children_sum',
48
vals['report_line'] = report_line_obj.create(cr, uid, parent_line_vals, context=context)
49
super(financing_contract_contract, self).write(cr, uid, contract_id, vals, context=context)
52
def _get_general_information(self, cr, uid, browse_contract, context=None):
53
# common part of the analytic domain
54
date_domain = "[('date', '>=', '"
55
date_domain += browse_contract.eligibility_from_date
56
date_domain += "'), ('date', '<=', '"
57
date_domain += browse_contract.eligibility_to_date
59
funding_pool_domain = "('account_id', 'in', ["
60
# list of expense accounts in the funding pools.
61
# Unicity is not important, it's just for a future comparison
62
funding_pool_account_ids = []
63
# list of cost centers in the funding pools.
64
# Unicity is important
66
if len(browse_contract.funding_pool_ids) > 0:
67
for funding_pool in browse_contract.funding_pool_ids:
68
funding_pool_domain += str(funding_pool.id)
69
funding_pool_domain += ", "
70
for account in funding_pool.account_ids:
71
funding_pool_account_ids.append(account.id)
72
if len(funding_pool.cost_center_ids) > 0:
73
for cost_center in funding_pool.cost_center_ids:
74
cost_center_ids.append(cost_center.id)
75
funding_pool_domain = funding_pool_domain[:-2]
76
funding_pool_domain += "])"
77
cost_center_domain = "('cost_center_id', 'in', ["
78
if len(cost_center_ids) > 0:
79
cost_center_set = set(cost_center_ids)
80
for cost_center_id in cost_center_set:
81
cost_center_domain += str(cost_center_id)
82
cost_center_domain += ', '
83
cost_center_domain = cost_center_domain[:-2]
84
cost_center_domain += "])"
85
return {'date_domain': date_domain,
86
'funding_pool_domain': funding_pool_domain,
87
'cost_center_domain': cost_center_domain,
88
'account_ids': funding_pool_account_ids}
90
def _create_actual_reporting_line(self, cr, uid, browse_actual_line, general_information, parent_line_id=False, context=None):
91
report_line_obj = self.pool.get('financing.contract.donor.reporting.line')
92
if general_information \
93
and 'date_domain' in general_information \
94
and 'funding_pool_domain' in general_information \
95
and 'cost_center_domain' in general_information \
96
and 'account_ids' in general_information:
98
'name': browse_actual_line.name,
99
'code': browse_actual_line.code,
100
'parent_id': parent_line_id,
101
'date_domain': general_information['date_domain'],
102
'funding_pool_domain': general_information['funding_pool_domain'],
103
'cost_center_domain': general_information['cost_center_domain'],
105
if browse_actual_line.line_type == 'view':
106
# view lines have no information, they take it from their children
107
line_vals['computation_type'] = 'children_sum'
108
elif browse_actual_line.line_type == 'normal':
109
# normal actual lines retrieve their amounts from the analytic lines
110
line_vals['computation_type'] = 'analytic_sum'
111
line_vals['allocated_budget_value'] = browse_actual_line.allocated_amount
112
line_vals['project_budget_value'] = browse_actual_line.project_amount
113
# compute domain from accounts
114
account_ids = [account.id for account in browse_actual_line.account_ids if account.id in general_information['account_ids']]
115
account_domain = "('general_account_id', 'in', ["
116
if len(account_ids) > 0:
117
for account_id in account_ids:
118
account_domain += str(account_id)
119
account_domain += ", "
120
account_domain = account_domain[:-2]
121
account_domain += "])"
122
line_vals['account_domain'] = account_domain
123
new_line_id = report_line_obj.create(cr, uid, line_vals, context=context)
124
# create children, and retrieve their list of accounts
125
for child_line in browse_actual_line.child_ids:
126
self._create_actual_reporting_line(cr, uid, child_line, general_information, new_line_id, context=context)
129
def _create_actual_lines(self, cr, uid, contract_id, context=None):
130
contract = self.browse(cr, uid, contract_id, context=context)
131
if contract.report_line:
132
# retrieve parent reporting line
133
parent_line_id = contract.report_line.id
134
# common part of the analytic domain
135
general_information = self._get_general_information(cr, uid, contract, context=context)
136
for line in contract.actual_line_ids:
137
if not line.parent_id:
138
# "top" actual lines; the other are created recursively
139
self._create_actual_reporting_line(cr, uid, line, general_information, parent_line_id, context=context)
142
def _create_nonactual_lines(self, cr, uid, contract_id, context=None):
143
contract = self.browse(cr, uid, contract_id, context=context)
144
report_line_obj = self.pool.get('financing.contract.donor.reporting.line')
145
if contract.report_line:
146
# retrieve parent reporting line
147
parent_line_id = contract.report_line.id
148
# create overhead line
149
overhead_line_vals = {}
150
if contract.overhead_type != 'amount' and contract.overhead_percentage > 0.0:
151
# create overhead line
152
overhead_line_vals = {
155
'parent_id': parent_line_id,
156
'computation_type': contract.overhead_type,
157
'overhead_percentage': contract.overhead_percentage,
159
report_line_obj.create(cr, uid, overhead_line_vals, context=context)
160
elif contract.budget_allocated_overhead > 0.0 \
161
or contract.budget_project_overhead > 0.0 \
162
or contract.allocated_overhead > 0.0 \
163
or contract.project_overhead > 0.0:
164
overhead_line_vals = {
167
'parent_id': parent_line_id,
168
'computation_type': contract.overhead_type,
169
'allocated_budget_value': contract.budget_allocated_overhead,
170
'project_budget_value': contract.budget_project_overhead,
171
'allocated_real_value': contract.allocated_overhead,
172
'project_real_value': contract.project_overhead,
174
report_line_obj.create(cr, uid, overhead_line_vals, context=context)
176
if contract.budget_allocated_lump_sum > 0.0 \
177
or contract.budget_project_lump_sum > 0.0 \
178
or contract.allocated_lump_sum > 0.0 \
179
or contract.project_lump_sum > 0.0:
180
lump_sum_line_vals = {
183
'parent_id': parent_line_id,
184
'computation_type': 'amount',
185
'allocated_budget_value': contract.budget_allocated_lump_sum,
186
'project_budget_value': contract.budget_project_lump_sum,
187
'allocated_real_value': contract.allocated_lump_sum,
188
'project_real_value': contract.project_lump_sum,
190
report_line_obj.create(cr, uid, lump_sum_line_vals, context=context)
192
if contract.budget_allocated_consumption > 0.0 \
193
or contract.budget_project_consumption > 0.0 \
194
or contract.allocated_consumption > 0.0 \
195
or contract.project_consumption > 0.0:
196
consumption_line_vals = {
197
'name': 'Consumption',
199
'parent_id': parent_line_id,
200
'computation_type': 'amount',
201
'allocated_budget_value': contract.budget_allocated_consumption,
202
'project_budget_value': contract.budget_project_consumption,
203
'allocated_real_value': contract.allocated_consumption,
204
'project_real_value': contract.project_consumption,
206
report_line_obj.create(cr, uid, consumption_line_vals, context=context)
209
# def dummy(self, cr, uid, ids, *args, **kwargs):
210
# mode = self.read(cr, uid, ids, ['reporting_type'])[0]['reporting_type']
212
# if mode == 'allocated':
213
# next_mode = 'project'
214
# elif mode == 'project':
217
# next_mode = 'allocated'
218
# self.write(cr, uid, [ids[0]], {'reporting_type': next_mode})
109
222
'name': fields.char('Financing contract name', size=64, required=True),
110
223
'code': fields.char('Financing contract code', size=16, required=True),
111
224
'donor_id': fields.many2one('financing.contract.donor', 'Donor', required=True),
225
'grant_name': fields.char('Grant name', size=64, required=True),
112
226
'donor_grant_reference': fields.char('Donor grant reference', size=64),
113
227
'hq_grant_reference': fields.char('HQ grant reference', size=64),
228
'contract_type': fields.selection([('', ''), ('ear_marked','Ear-marked'), ('global_contribution','Global Contribution')], 'Financing contract type', required=True),
229
'eligibility_from_date': fields.date('Eligibility date from', required=True),
230
'eligibility_to_date': fields.date('Eligibility date to', required=True),
114
231
'grant_amount': fields.float('Grant amount', size=64, required=True),
115
232
'reporting_currency': fields.many2one('res.currency', 'Reporting currency', required=True),
116
233
'notes': fields.text('Notes'),
234
'funding_pool_ids': fields.many2many('account.analytic.account', 'financing_contract_funding_pool', 'contract_id', 'funding_pool_id', string='Funding Pools'),
117
235
'open_date': fields.date('Open date'),
118
236
'soft_closed_date': fields.date('Soft-closed date'),
119
237
'hard_closed_date': fields.date('Hard-closed date'),
169
258
'format_name': source_format.format_name,
170
259
'reporting_type': source_format.reporting_type,
260
'overhead_type': source_format.overhead_type,
261
'overhead_percentage': source_format.overhead_percentage,
172
263
self.pool.get('financing.contract.format').copy_format_lines(cr, uid, donor.format_id.id, format_id, context=context)
173
264
return {'value': format_vals}
175
def onchange_currency_table(self, cr, uid, ids, currency_table_id, reporting_currency_id, context=None):
176
values = {'reporting_currency': False}
177
if reporting_currency_id:
178
# it can be a currency from another table
179
reporting_currency = self.pool.get('res.currency').browse(cr, uid, reporting_currency_id, context=context)
180
# Search if the currency is in the table, and active
181
if reporting_currency.reference_currency_id:
182
currency_results = self.pool.get('res.currency').search(cr, uid, [('reference_currency_id', '=', reporting_currency.reference_currency_id.id),
183
('currency_table_id', '=', currency_table_id),
184
('active', '=', True)], context=context)
186
currency_results = self.pool.get('res.currency').search(cr, uid, [('reference_currency_id', '=', reporting_currency_id),
187
('currency_table_id', '=', currency_table_id),
188
('active', '=', True)], context=context)
189
if len(currency_results) > 0:
190
# it's here, we keep the currency
191
values['reporting_currency'] = reporting_currency_id
192
# Restrain domain to selected table (or None if none selected
193
domains = {'reporting_currency': [('currency_table_id', '=', currency_table_id)]}
194
return {'value': values, 'domain': domains}
196
def create_reporting_line(self, cr, uid, browse_contract, browse_format_line, parent_report_line_id=None, context=None):
197
format_line_obj = self.pool.get('financing.contract.format.line')
198
reporting_line_obj = self.pool.get('financing.contract.donor.reporting.line')
199
analytic_domain = format_line_obj._get_analytic_domain(cr,
202
browse_contract.reporting_type,
204
vals = {'name': browse_format_line.name,
205
'code': browse_format_line.code,
206
'line_type': browse_format_line.line_type,
207
'allocated_budget': round(browse_format_line.allocated_budget),
208
'project_budget': round(browse_format_line.project_budget),
209
'allocated_real': round(browse_format_line.allocated_real),
210
'project_real': round(browse_format_line.project_real),
211
'analytic_domain': analytic_domain,
212
'parent_id': parent_report_line_id}
213
reporting_line_id = reporting_line_obj.create(cr,
218
for child_line in browse_format_line.child_ids:
219
self.create_reporting_line(cr, uid, browse_contract, child_line, reporting_line_id, context=context)
220
return reporting_line_id
222
def menu_interactive_report(self, cr, uid, ids, context=None):
266
def create(self, cr, uid, vals, context=None):
269
contract_id = super(financing_contract_contract, self).create(cr, uid, vals, context=context)
271
self._create_parent_line(cr, uid, contract_id, context=context)
272
self._create_actual_lines(cr, uid, contract_id, context=context)
273
self._create_nonactual_lines(cr, uid, contract_id, context=context)
276
def write(self, cr, uid, ids, vals, context=None):
279
if isinstance(ids, (int, long)):
281
result = super(financing_contract_contract, self).write(cr, uid, ids, vals, context=context)
282
for contract in self.browse(cr, uid, ids, context=context):
283
# delete existing parent reporting line (representing the contract in the tree view)
284
self._create_parent_line(cr, uid, contract.id, context=context)
285
self._create_actual_lines(cr, uid, contract.id, context=context)
286
self._create_nonactual_lines(cr, uid, contract.id, context=context)
289
def unlink(self, cr, uid, ids, context=None):
292
report_line_obj = self.pool.get('financing.contract.donor.reporting.line')
293
for contract in self.browse(cr, uid, ids, context=context):
294
# delete existing parent reporting line (representing the contract in the tree view)
295
report_line_obj.unlink(cr, uid, contract.report_line.id, context=context)
296
return super(financing_contract_contract, self).unlink(cr, uid, ids, context=context)
299
def menu_interactive_report(self, cr, uid, ids, context={}):
225
300
# we update the context with the contract reporting type
226
contract = self.browse(cr, uid, ids[0], context=context)
227
context.update({'reporting_currency': contract.reporting_currency.id,
228
'reporting_type': contract.reporting_type,
229
'currency_table_id': contract.currency_table_id.id,
301
contract_obj = self.browse(cr, uid, ids[0], context=context)
302
model_data_obj = self.pool.get('ir.model.data')
303
# update the context with reporting type (used for "get analytic_lines" action)
304
context.update({'reporting_type': contract_obj.reporting_type,
230
305
'active_id': ids[0],
231
306
'active_ids': ids})
232
reporting_line_obj = self.pool.get('financing.contract.donor.reporting.line')
233
# Create reporting lines
234
# Contract line first (we'll fill it later)
235
contract_line_id = reporting_line_obj.create(cr,
237
vals = {'name': contract.name,
238
'code': contract.code,
239
'line_type': 'view'},
248
# create "real" lines
249
for line in contract.actual_line_ids:
250
if not line.parent_id:
251
allocated_budget += line.allocated_budget
252
project_budget += line.project_budget
253
allocated_real += line.allocated_real
254
project_real += line.project_real
255
reporting_line_id = self.create_reporting_line(cr, uid, contract, line, contract_line_id, context=context)
257
# Refresh contract line with general infos
258
analytic_domain = self.get_contract_domain(cr, uid, contract, context=context)
259
contract_values = {'allocated_budget': allocated_budget,
260
'project_budget': project_budget,
261
'allocated_real': allocated_real,
262
'project_real': project_real,
263
'analytic_domain': analytic_domain}
264
reporting_line_obj.write(cr, uid, [contract_line_id], vals=contract_values, context=context)
266
307
# retrieve the corresponding_view
267
model_data_obj = self.pool.get('ir.model.data')
269
309
view_ids = model_data_obj.search(cr, uid,
270
310
[('module', '=', 'financing_contract'),
271
('name', '=', 'view_donor_reporting_line_tree_%s' % str(contract.reporting_type))],
311
('name', '=', 'view_donor_reporting_line_tree_%s' % str(contract_obj.reporting_type))],
272
312
offset=0, limit=1)
273
313
if len(view_ids) > 0:
274
314
view_id = model_data_obj.browse(cr, uid, view_ids[0]).res_id