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

« back to all changes in this revision

Viewing changes to financing_contract/format_line.py

  • Committer: matthieu.choplin at msf
  • Date: 2012-08-30 07:48:00 UTC
  • mto: This revision was merged to the branch mainline in revision 1118.
  • Revision ID: matthieu.choplin@geneva.msf.org-20120830074800-l442bu42mt0yzutn
[uf-1374]- change the write and create by an _sql_constraint on the financing contract check dates

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from osv import fields, osv
23
23
import pooler
24
24
from analytic_distribution.destination_tools import many2many_sorted
25
 
from account_override import ACCOUNT_RESTRICTED_AREA
26
25
 
27
26
 
28
27
class financing_contract_format_line(osv.osv):
29
 
 
 
28
    
30
29
    _name = "financing.contract.format.line"
31
 
 
32
 
    def _auto_init(self, cr, context=None):
33
 
        table_name = 'financing_contract_actual_account_quadruplets'
34
 
        cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (table_name, ))
35
 
        table_exists = cr.rowcount
36
 
 
37
 
        if not table_exists:
38
 
            cr.execute('''
39
 
        CREATE TABLE financing_contract_actual_account_quadruplets (
40
 
            actual_line_id integer NOT NULL,
41
 
            account_quadruplet_id integer NOT NULL
42
 
        )'''
43
 
        )
44
 
        res = super(financing_contract_format_line, self)._auto_init(cr, context)
45
 
        if not table_exists:
46
 
            cr.execute('''
47
 
            ALTER TABLE ONLY financing_contract_actual_account_quadruplets
48
 
                ADD CONSTRAINT financing_contract_actual_account_quadruplet_actual_line_id_key UNIQUE (actual_line_id, account_quadruplet_id)
49
 
            ''')
50
 
            cr.execute('''CREATE INDEX financing_contract_actual_account_quadruplets_account_quadruple ON financing_contract_actual_account_quadruplets USING btree (account_quadruplet_id)''')
51
 
            cr.execute('''CREATE INDEX financing_contract_actual_account_quadruplets_actual_line_id_in ON financing_contract_actual_account_quadruplets USING btree (actual_line_id)''')
52
 
            cr.execute('''
53
 
            ALTER TABLE ONLY financing_contract_actual_account_quadruplets
54
 
                ADD CONSTRAINT financing_contract_actual_account_quadruple_actual_line_id_fkey FOREIGN KEY (actual_line_id) REFERENCES financing_contract_format_line(id) ON DELETE CASCADE
55
 
            ''')
 
30
    
56
31
    def _create_domain(self, header, element_list):
57
32
        domain = "('" + header + "', 'in', ["
58
33
        if len(element_list) > 0:
62
37
            domain = domain[:-2]
63
38
        domain += "])"
64
39
        return domain
65
 
 
66
 
    # get list of accounts for duplet format lines
67
 
    def _create_account_couple_domain(self, account_destination_list, general_domain):
 
40
    
 
41
    def _create_account_destination_domain(self, account_destination_list):
68
42
        if len(account_destination_list) == 0:
69
 
            return False # Just make this condition to False
 
43
            return ['&',
 
44
                    ('general_account_id', 'in', []),
 
45
                    ('destination_id', 'in', [])]
70
46
        elif len(account_destination_list) == 1:
71
 
            temp_domain = ['&',
 
47
            return ['&',
72
48
                    ('general_account_id', '=', account_destination_list[0].account_id.id),
73
49
                    ('destination_id', '=', account_destination_list[0].destination_id.id)]
74
 
 
75
 
            return temp_domain
76
 
        else:
77
 
            firstElement = self._create_account_couple_domain([account_destination_list[0]], general_domain)
78
 
            secondElement = self._create_account_couple_domain(account_destination_list[1:], general_domain)
79
 
 
80
 
            if firstElement and secondElement:
81
 
                return ['|'] + firstElement + secondElement
82
 
            elif firstElement:
83
 
                return firstElement
84
 
            return secondElement
85
 
 
86
 
    # get list of accounts for quadruplet format lines
87
 
    def _create_account_quadruplet_domain(self, account_quadruplet_list, funding_pool_ids=False):
88
 
        if len(account_quadruplet_list) == 0:
89
 
            return False
90
 
        elif len(account_quadruplet_list) == 1:
91
 
            if account_quadruplet_list[0].funding_pool_id.id in funding_pool_ids:
92
 
                quad_element = account_quadruplet_list[0]
93
 
                return ['&',
94
 
                        '&',
95
 
                        ('general_account_id', '=', quad_element.account_id.id),
96
 
                        ('destination_id', '=', quad_element.account_destination_id.id),
97
 
                        '&',
98
 
                        ('cost_center_id', '=', quad_element.cost_center_id.id),
99
 
                        ('account_id', '=', quad_element.funding_pool_id.id)]
100
 
            else:
101
 
                return False
102
 
        else:
103
 
            firstElement = self._create_account_quadruplet_domain([account_quadruplet_list[0]], funding_pool_ids)
104
 
            secondElement = self._create_account_quadruplet_domain(account_quadruplet_list[1:], funding_pool_ids)
105
 
 
106
 
            if firstElement and secondElement:
107
 
                return ['|'] + firstElement + secondElement
108
 
            elif firstElement:
109
 
                return firstElement
110
 
            return secondElement
 
50
        else:
 
51
            return ['|'] + self._create_account_destination_domain([account_destination_list[0]]) + self._create_account_destination_domain(account_destination_list[1:])
111
52
 
112
53
    def _get_number_of_childs(self, cr, uid, ids, field_name=None, arg=None, context=None):
113
54
        # Verifications
116
57
        if isinstance(ids, (int, long)):
117
58
            ids = [ids]
118
59
        # Prepare some values
119
 
                    #account_quadruplet_domain = ['&',('funding_pool_id', 'in', (36,40))]
120
60
        res = {}
121
61
        for line in self.browse(cr, uid, ids, context=context):
122
62
            res[line.id] = line.child_ids and len(line.child_ids) or 0
123
63
        return res
124
 
 
 
64
    
125
65
    def _get_parent_ids(self, cr, uid, ids, context=None):
126
66
        res = []
127
67
        for line in self.browse(cr, uid, ids, context=context):
128
68
            if line.parent_id:
129
69
                res.append(line.parent_id.id)
130
70
        return res
131
 
 
 
71
    
132
72
    def _get_total_costs(self, cr, uid, browse_overhead_line, field_name=None, context=None):
133
73
        # since this is only called from the overhead line, the domain is
134
74
        # "all children, except the overhead lines"
142
82
        for total_cost in total_costs.values():
143
83
            result += total_cost
144
84
        return result
145
 
 
146
 
    def button_delete_all_quads(self, cr, uid, ids, context=None):
147
 
        self.write(cr, uid, ids, {'account_quadruplet_ids':[(6, 0, [])]}, context=context )
148
 
        return True
149
 
 
150
 
    def button_delete_all_couples(self, cr, uid, ids, context=None):
151
 
        self.write(cr, uid, ids, {'account_destination_ids':[(6, 0, [])]}, context=context )
152
 
        return True
153
 
 
154
 
    # Get the list of accounts for both duplet and quadruplet
155
 
    def _get_accounts_couple_and_quadruplets(self, browse_line):
156
 
        account_destination_result = []
157
 
        account_quadruplet_result = []
158
 
 
 
85
    
 
86
    def _get_account_destination_ids(self, browse_line, funding_pool_account_destination_ids):
 
87
        result = []
159
88
        if browse_line.line_type != 'view':
160
 
            if browse_line.is_quadruplet:
161
 
                account_quadruplet_result = [account_quadruplet for account_quadruplet in browse_line.account_quadruplet_ids]
162
 
            else:
163
 
                account_destination_result = [account_destination for account_destination in browse_line.account_destination_ids]
 
89
            result = [account_destination for account_destination in browse_line.account_destination_ids if account_destination.id in funding_pool_account_destination_ids]
164
90
        else:
165
91
            for child_line in browse_line.child_ids:
166
 
                temp = self._get_accounts_couple_and_quadruplets(child_line)
167
 
                account_destination_result += temp['account_destination_list']
168
 
                account_quadruplet_result += temp['account_quadruplet_list']
169
 
        return {'account_destination_list': account_destination_result,
170
 
                'account_quadruplet_list': account_quadruplet_result}
171
 
 
 
92
                result += self._get_account_destination_ids(child_line, funding_pool_account_destination_ids)
 
93
        return result
 
94
    
172
95
    def _get_general_domain(self, cr, uid, browse_format, domain_type, context=None):
173
96
        # Method to get the domain (allocated or project) of a line
174
 
 
175
97
        date_domain = "[('document_date', '>=', '"
176
98
        date_domain += browse_format.eligibility_from_date
177
99
        date_domain += "'), ('document_date', '<=', '"
178
100
        date_domain += browse_format.eligibility_to_date
179
101
        date_domain += "')]"
180
 
 
181
 
        gen_domain = {}
182
 
        gen_domain['date_domain'] = date_domain
183
 
 
184
 
        cost_center_domain = self._create_domain('cost_center_id', browse_format.cost_center_ids)
185
 
        gen_domain['cost_center_domain'] = cost_center_domain
186
 
 
187
 
 
188
 
        # note: even though reporting should be from quadruplets and couples, an additional verification against funding pools
189
 
        # and cost centers is required. This is because a user could follow this sequence -
190
 
        # 1. add a funding pool to the contract
191
 
        # 2. create quads based on it
192
 
        # 3. remove the funding pool
193
 
        # 4. The quad reporting line still refers to the removed FP.
194
 
        #
195
 
 
 
102
        # list of expense accounts in the funding pools.
 
103
        # we take them all (funded and project), as for funded,
 
104
        # we are sure that no allocation will be done with
 
105
        # (funded funding pool, account in other funding pool)
 
106
        funding_pool_account_destination_ids = []
 
107
        for funding_pool_line in browse_format.funding_pool_ids:
 
108
            funding_pool = funding_pool_line.funding_pool_id
 
109
            for account_destination in funding_pool.tuple_destination_account_ids:
 
110
                funding_pool_account_destination_ids.append(account_destination.id)
196
111
        # Funding pools
197
112
        funding_pool_ids = []
198
 
        if domain_type == 'allocated':
 
113
        if domain_type == 'allocated': 
199
114
            funding_pool_ids = [funding_pool_line.funding_pool_id for funding_pool_line in browse_format.funding_pool_ids if funding_pool_line.funded]
200
115
        else:
201
116
            funding_pool_ids = [funding_pool_line.funding_pool_id for funding_pool_line in browse_format.funding_pool_ids]
202
 
 
203
 
        if funding_pool_ids:
204
 
            # remove 'FP' funding pool from the list if it exists.
205
 
            fp_ids = self.pool.get('account.analytic.account').search(cr, uid, ['&',('category','=','FUNDING'),('code','=','FP')], context=None)
206
 
            funding_pool_ids = [x for x in funding_pool_ids if x not in fp_ids]
207
 
            funding_pool_domain = self._create_domain('account_id', funding_pool_ids)
208
 
            gen_domain['funding_pool_domain'] = funding_pool_domain
209
 
 
210
 
        gen_domain['funding_pool_ids'] = [x.id for x in funding_pool_ids]
211
 
        return gen_domain
212
 
 
213
 
 
214
 
    def _get_analytic_domain(self, cr, uid, browse_line, domain_type, isFirst=True, context=None):
 
117
        funding_pool_domain = self._create_domain('account_id', funding_pool_ids)
 
118
        # Cost centers
 
119
        cost_center_domain = self._create_domain('cost_center_id', browse_format.cost_center_ids)
 
120
        return {'date_domain': date_domain,
 
121
                'funding_pool_domain': funding_pool_domain,
 
122
                'cost_center_domain': cost_center_domain,
 
123
                'funding_pool_account_destination_ids': funding_pool_account_destination_ids}
 
124
    
 
125
    def _get_analytic_domain(self, cr, uid, browse_line, domain_type, context=None):
215
126
        if browse_line.line_type in ('consumption', 'overhead'):
216
 
            # No domain for this case
217
 
            return []
 
127
            # No domain for those
 
128
            return False
218
129
        else:
219
 
            # last domain: get only non-corrected lines.
220
 
            non_corrected_domain = [('is_reallocated', '=', False),('is_reversal', '=', False)]
221
130
            format = browse_line.format_id
222
131
            if format.eligibility_from_date and format.eligibility_to_date:
223
 
                #### DUY US-385: MOVE THIS TO OUTSIDE OF THE ALL THE LOOPS
224
132
                general_domain = self._get_general_domain(cr, uid, format, domain_type, context=context)
225
 
 
226
133
                # Account + destination domain
227
 
                account_destination_quadruplet_ids = self._get_accounts_couple_and_quadruplets(browse_line)
228
 
                account_couple_domain = self._create_account_couple_domain(account_destination_quadruplet_ids['account_destination_list'], False)
229
 
                # get the criteria for accounts of quadruplet mode
230
 
                account_quadruplet_domain = self._create_account_quadruplet_domain(account_destination_quadruplet_ids['account_quadruplet_list'], general_domain['funding_pool_ids'])
231
 
 
232
 
                if not account_couple_domain and not account_quadruplet_domain:
233
 
                    return [('id', '=', '-1')]
234
 
 
235
 
                accounts_criteria = ['&', '&', ] + non_corrected_domain
236
 
                if account_couple_domain and account_quadruplet_domain:
237
 
                    accounts_criteria += ['|'] + account_couple_domain + account_quadruplet_domain
238
 
                elif account_couple_domain:
239
 
                    accounts_criteria += account_couple_domain
240
 
                elif account_quadruplet_domain:
241
 
                    accounts_criteria += account_quadruplet_domain
242
 
 
243
 
                return accounts_criteria
 
134
                account_destination_ids = self._get_account_destination_ids(browse_line, general_domain['funding_pool_account_destination_ids'])
 
135
                account_domain = self._create_account_destination_domain(account_destination_ids)
 
136
                # create the final domain
 
137
                date_domain = eval(general_domain['date_domain'])
 
138
                return [date_domain[0], date_domain[1]] + account_domain + [eval(general_domain['funding_pool_domain']), eval(general_domain['cost_center_domain'])]
244
139
            else:
245
 
                return []
246
 
 
247
 
    def _is_overhead_present(self, cr, uid, ids, context={}):
248
 
        for line in self.browse(cr, uid, ids, context=context):
249
 
            if line.line_type == 'overhead':
250
 
                return True
251
 
            elif line.line_type == 'view':
252
 
                if self._is_overhead_present(cr, uid, [x.id for x in line.child_ids], context=context):
253
 
                    return True
254
 
        return False
255
 
 
256
 
    def _get_actual_line_ids(self, cr, uid, ids, context={}):
257
 
        actual_line_ids = []
258
 
        for line in self.browse(cr, uid, ids, context=context):
259
 
            if line.line_type == 'view':
260
 
                actual_line_ids += self._get_actual_line_ids(cr, uid, [x.id for x in line.child_ids], context=context)
261
 
            elif line.line_type in ['actual', 'consumption']:
262
 
                actual_line_ids.append(line.id)
263
 
        return actual_line_ids
264
 
 
265
 
    def _get_view_amount(self, browse_line, total_costs, retrieved_lines):
266
 
        if browse_line.line_type == 'view':
267
 
            sum = 0.0
268
 
            for child_line in browse_line.child_ids:
269
 
                if child_line.id not in retrieved_lines:
270
 
                    self._get_view_amount(child_line, total_costs, retrieved_lines)
271
 
                sum += retrieved_lines[child_line.id]
272
 
            retrieved_lines[browse_line.id] = sum
273
 
        elif browse_line.line_type == 'overhead':
274
 
            if browse_line.overhead_type == 'cost_percentage':
275
 
                # percentage of all costs (sum of all 2nd-level lines, except overhead)
276
 
                retrieved_lines[browse_line.id] = round(total_costs * browse_line.overhead_percentage / 100.0)
277
 
            elif browse_line.overhead_type == 'grant_percentage':
278
 
                # percentage of all costs (sum of all 2nd-level lines, except overhead)
279
 
                retrieved_lines[browse_line.id] = round(total_costs * browse_line.overhead_percentage / (100.0 - browse_line.overhead_percentage))
280
 
 
 
140
                # Dates are not set (since we are probably in a donor).
 
141
                # Return False
 
142
                return False
281
143
 
282
144
    def _get_budget_amount(self, cr, uid, ids, field_name=None, arg=None, context=None):
283
145
        """
284
146
            Method to compute the allocated budget/amounts, depending on the information in the line
285
147
        """
286
148
        res = {}
287
 
        # 1st step: get the real list of actual lines to compute
288
 
        actual_line_ids = []
289
 
        overhead = self._is_overhead_present(cr, uid, ids, context=context)
290
 
        if overhead and len(ids) > 0:
291
 
            line_for_format = self.browse(cr, uid, ids[0], context=context)
292
 
            actual_line_ids = [line.id for line in line_for_format.format_id.actual_line_ids if line.line_type in ['actual', 'consumption']]
293
 
        else:
294
 
            actual_line_ids = self._get_actual_line_ids(cr, uid, ids, context=context)
295
 
 
296
 
        # 2nd step: retrieve values for all actual lines above
297
 
        for line in self.browse(cr, uid, actual_line_ids, context=context):
 
149
        for line in self.browse(cr, uid, ids, context=context):
298
150
            # default value
299
151
            res[line.id] = 0.0
300
152
            if line.line_type:
304
156
                        res[line.id] = line.allocated_budget_value
305
157
                    elif field_name == 'project_budget':
306
158
                        res[line.id] = line.project_budget_value
307
 
 
308
 
        # 3rd step: compute all remaining lines from the retrieved results
309
 
        total_budget_costs = 0.0
310
 
        if overhead:
311
 
            total_budget_costs = sum(res.values())
312
 
        for line in self.browse(cr, uid, [id for id in ids if id not in actual_line_ids], context=context):
313
 
            if line.id not in res:
314
 
                self._get_view_amount(line, total_budget_costs, res)
315
 
 
 
159
                elif line.line_type == 'view':
 
160
                    # Sum of all its children
 
161
                    sum_budget = 0.0
 
162
                    for child_line in line.child_ids:
 
163
                        child_values = self._get_budget_amount(cr, uid, [child_line.id], field_name, context=context)
 
164
                        sum_budget += child_values[child_line.id]
 
165
                    res[line.id] = sum_budget
 
166
                elif line.line_type == 'overhead':
 
167
                    # 2 cases
 
168
                    if line.overhead_type == 'cost_percentage':
 
169
                        # percentage of all costs (sum of all 2nd-level lines, except overhead)
 
170
                        total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
 
171
                        res[line.id] = round(total_costs * line.overhead_percentage / 100.0)
 
172
                    elif line.overhead_type == 'grant_percentage':
 
173
                        # percentage of all costs (sum of all 2nd-level lines, except overhead)
 
174
                        total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
 
175
                        res[line.id] = round(total_costs * line.overhead_percentage / (100.0 - line.overhead_percentage))
316
176
        return res
317
177
 
318
178
    def _get_actual_amount(self, cr, uid, ids, field_name=None, arg=None, context=None):
320
180
            Method to compute the allocated budget/amounts, depending on the information in the line
321
181
        """
322
182
        res = {}
323
 
        # 1st step: get the real list of actual lines to compute
324
 
        actual_line_ids = []
325
 
        overhead = self._is_overhead_present(cr, uid, ids, context=context)
326
 
        if overhead and len(ids) > 0:
327
 
            line_for_format = self.browse(cr, uid, ids[0], context=context)
328
 
            actual_line_ids = [line.id for line in line_for_format.format_id.actual_line_ids if line.line_type in ['actual', 'consumption']]
329
 
        else:
330
 
            actual_line_ids = self._get_actual_line_ids(cr, uid, ids, context=context)
331
 
 
332
 
        # 2nd step: retrieve values for all actual lines above
333
 
        for line in self.browse(cr, uid, actual_line_ids, context=context):
 
183
        for line in self.browse(cr, uid, ids, context=context):
334
184
            # default value
335
185
            res[line.id] = 0.0
336
186
            if line.line_type:
340
190
                        res[line.id] = line.allocated_real_value
341
191
                    elif field_name == 'project_real':
342
192
                        res[line.id] = line.project_real_value
 
193
                elif line.line_type == 'view':
 
194
                    # Sum of all its children
 
195
                    sum_real = 0.0
 
196
                    for child_line in line.child_ids:
 
197
                        child_values = self._get_actual_amount(cr, uid, [child_line.id], field_name, context=context)
 
198
                        sum_real += child_values[child_line.id]
 
199
                    res[line.id] = sum_real
 
200
                elif line.line_type == 'overhead':
 
201
                    # 2 cases
 
202
                    if line.overhead_type == 'cost_percentage':
 
203
                        # percentage of all costs (sum of all 2nd-level lines, except overhead)
 
204
                        total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
 
205
                        res[line.id] = round(total_costs * line.overhead_percentage / 100.0)
 
206
                    elif line.overhead_type == 'grant_percentage':
 
207
                        # percentage of all costs (sum of all 2nd-level lines, except overhead)
 
208
                        total_costs = self._get_total_costs(cr, uid, line, field_name, context=context)
 
209
                        res[line.id] = round(total_costs * line.overhead_percentage / (100.0 - line.overhead_percentage))
343
210
                elif line.line_type == 'actual':
344
211
                    # sum of analytic lines, determined by the domain
345
212
                    analytic_domain = []
346
 
                    report_type = ''
347
213
                    if field_name == 'project_real':
348
 
                        analytic_domain = self._get_analytic_domain(cr, uid, line, 'project', True, context=context)
349
 
                        report_type = 'project'
 
214
                        analytic_domain = self._get_analytic_domain(cr, uid, line, 'project', context=context)
350
215
                    elif field_name == 'allocated_real':
351
 
                        analytic_domain = self._get_analytic_domain(cr, uid, line, 'allocated', True, context=context)
352
 
                        report_type = 'allocated'
353
 
                    if analytic_domain:
354
 
                        analytic_domain = self.pool.get('financing.contract.contract').add_general_domain(cr, uid, analytic_domain, line.format_id, report_type, context)
 
216
                        analytic_domain = self._get_analytic_domain(cr, uid, line, 'allocated', context=context)
355
217
                    # selection of analytic lines
356
 
                    if 'reporting_currency' in context:  # TODO Why do we only get analytic lines if reporting_currency in context
 
218
                    if 'reporting_currency' in context:
357
219
                        analytic_line_obj = self.pool.get('account.analytic.line')
358
220
                        analytic_lines = analytic_line_obj.search(cr, uid, analytic_domain ,context=context)
359
 
                        # list of analytic journal_ids which are in the engagement journals
360
 
                        exclude_journal_ids = self.pool.get('account.analytic.journal').search(cr, uid, [('type','=','engagement')])
361
 
                        exclude_line_ids = []
362
 
                        for analytic_line in analytic_line_obj.browse(cr, uid, analytic_lines, context=None):
363
 
                            if analytic_line.journal_id.id in exclude_journal_ids:
364
 
                                exclude_line_ids.append(analytic_line.id)
365
 
                        analytic_lines = [x for x in analytic_lines if x not in exclude_line_ids]
366
221
                        real_sum = 0.0
367
222
                        currency_table = None
368
223
                        if 'currency_table_id' in context:
373
228
                            real_sum += self.pool.get('res.currency').compute(cr,
374
229
                                                                              uid,
375
230
                                                                              analytic_line.currency_id.id,
376
 
                                                                              context['reporting_currency'],
 
231
                                                                              context['reporting_currency'], 
377
232
                                                                              analytic_line.amount_currency or 0.0,
378
233
                                                                              round=False,
379
234
                                                                              context=date_context)
380
235
                        # Invert the result from the lines (positive for out, negative for in)
381
236
                        real_sum = -real_sum
382
237
                        res[line.id] = real_sum
383
 
 
384
 
        # 3rd step: compute all remaining lines from the retrieved results
385
 
        total_actual_costs = 0.0
386
 
        if overhead:
387
 
            total_actual_costs = sum(res.values())
388
 
        for line in self.browse(cr, uid, [id for id in ids if id not in actual_line_ids], context=context):
389
 
            if line.id not in res:
390
 
                self._get_view_amount(line, total_actual_costs, res)
391
 
 
392
238
        return res
393
 
 
394
 
 
 
239
    
 
240
    
395
241
    _columns = {
396
242
        'name': fields.char('Name', size=64, required=True),
397
243
        'code': fields.char('Code', size=16, required=True),
398
244
        'format_id': fields.many2one('financing.contract.format', 'Format'),
399
 
        'is_quadruplet': fields.boolean('Input CC/FP at line level?'),
400
 
        'account_destination_ids': many2many_sorted('account.destination.link', 'financing_contract_actual_account_destinations', 'actual_line_id', 'account_destination_id', string='Accounts/Destinations', domain=ACCOUNT_RESTRICTED_AREA['contract_reporting_lines']),
401
 
        'account_quadruplet_ids': many2many_sorted('financing.contract.account.quadruplet', 'financing_contract_actual_account_quadruplets', 'actual_line_id', 'account_quadruplet_id', string='Accounts/Destinations/Funding Pools/Cost Centres'),
 
245
        'account_destination_ids': many2many_sorted('account.destination.link', 'financing_contract_actual_account_destinations', 'actual_line_id', 'account_destination_id', string='Accounts/Destinations', domain=[('account_id.user_type_report_type', '=', 'expense')]),
402
246
        'parent_id': fields.many2one('financing.contract.format.line', 'Parent line'),
403
247
        'child_ids': fields.one2many('financing.contract.format.line', 'parent_id', 'Child lines'),
404
248
        'line_type': fields.selection([('view','View'),
412
256
        'allocated_real_value': fields.float('Real allocated amount (value)'),
413
257
        'project_real_value': fields.float('Real project amount (value)'),
414
258
        'overhead_percentage': fields.float('Overhead percentage'),
415
 
 
416
259
        'allocated_budget': fields.function(_get_budget_amount, method=True, store=False, string="Funded - Budget", type="float", readonly=True),
417
260
        'project_budget': fields.function(_get_budget_amount, method=True, store=False, string="Total project - Budget", type="float", readonly=True),
418
 
 
419
261
        'allocated_real': fields.function(_get_actual_amount, method=True, store=False, string="Funded - Actuals", type="float", readonly=True),
420
262
        'project_real': fields.function(_get_actual_amount, method=True, store=False, string="Total project - Actuals", type="float", readonly=True),
421
 
        'quadruplet_update': fields.text('Internal Use Only'),
422
 
        'instance_id': fields.many2one('msf.instance','Proprietary Instance'),
423
263
    }
424
 
 
 
264
    
425
265
    _defaults = {
426
 
        'is_quadruplet': False,
427
266
        'line_type': 'actual',
428
267
        'overhead_type': 'cost_percentage',
429
268
        'parent_id': lambda *a: False
430
269
    }
431
 
 
432
 
    _order = 'code asc'
433
 
 
434
 
    # UF-2311: Calculate the quadruplet value before writing or creating the format line
435
 
    def calculate_quaduplet(self, vals, context):
436
 
        if 'line_type' in vals and vals['line_type'] == 'view':
437
 
            vals['allocated_amount'] = 0.0
438
 
            vals['project_amount'] = 0.0
439
 
            vals['account_destination_ids'] = [(6, 0, [])]
440
 
            vals['account_quadruplet_ids'] = [(6, 0, [])]
441
 
        elif 'is_quadruplet' in vals: # If the vals contains quadruplet value, then check if it is true or false
442
 
            if vals.get('is_quadruplet', False):
443
 
                # delete account/destinations
444
 
                vals['account_destination_ids'] = [(6, 0, [])]
445
 
                if context.get('sync_update_execution'):
446
 
                    quads_list = []
447
 
                    if vals.get('quadruplet_update', False):
448
 
                        quadrup_str = vals['quadruplet_update']
449
 
                        quads_list = map(int, quadrup_str.split(','))
450
 
                    vals['account_quadruplet_ids'] = [(6, 0, quads_list)]
451
 
                else:
452
 
                    temp = vals['account_quadruplet_ids']
453
 
                    if temp[0]:
454
 
                        vals['quadruplet_update'] = str(temp[0][2]).strip('[]')
455
 
            else:
456
 
                vals['account_quadruplet_ids'] = [(6, 0, [])]
457
 
                vals['quadruplet_update'] = '' # delete quadruplets
458
 
 
 
270
    
459
271
    def create(self, cr, uid, vals, context=None):
460
272
        if not context:
461
273
            context = {}
462
 
 
463
 
        # calculate the quadruplet combination
464
 
        self.calculate_quaduplet(vals, context)
 
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_destination_ids'] = []
465
279
        return super(financing_contract_format_line, self).create(cr, uid, vals, context=context)
466
 
 
 
280
    
467
281
    def write(self, cr, uid, ids, vals, context=None):
468
282
        if not context:
469
283
            context = {}
470
284
        if isinstance(ids, (int, long)):
471
285
            ids = [ids]
472
 
 
473
 
        # US-180: Check if it comes from the sync update
474
 
        if context.get('sync_update_execution') and vals.get('format_id', False):
475
 
            # US-180: and if the financing contract of the contract format does not exist, then just ignore this update
476
 
            exist = self.pool.get('financing.contract.contract').search(cr, uid, [('format_id', '=', vals['format_id'])])
477
 
            if not exist: # No contract found for this format line
478
 
                return True
479
 
 
480
 
        # calculate the quadruplet combination
481
 
        self.calculate_quaduplet(vals, context)
 
286
        # if the account is set as view, remove budget and account values
 
287
        if 'line_type' in vals and vals['line_type'] == 'view':
 
288
            vals['allocated_amount'] = 0.0
 
289
            vals['project_amount'] = 0.0
 
290
            vals['account_destination_ids'] = [(6, 0, [])]
482
291
        return super(financing_contract_format_line, self).write(cr, uid, ids, vals, context=context)
483
 
 
 
292
    
484
293
    def copy_format_line(self, cr, uid, browse_source_line, destination_format_id, parent_id=None, context=None):
485
294
        if destination_format_id:
486
295
            format_line_vals = {
489
298
                'format_id': destination_format_id,
490
299
                'parent_id': parent_id,
491
300
                'line_type': browse_source_line.line_type,
492
 
                'account_quadruplet_ids': [(6, 0, [])],
493
301
            }
494
 
            account_destination_ids = [account_destination.id for account_destination in browse_source_line.account_destination_ids]
 
302
            account_destination_ids = []
 
303
            for account_destination in browse_source_line.account_destination_ids:
 
304
                account_destination_ids.append(account_destination.id)
495
305
            format_line_vals['account_destination_ids'] = [(6, 0, account_destination_ids)]
496
306
            parent_line_id = self.pool.get('financing.contract.format.line').create(cr, uid, format_line_vals, context=context)
497
307
            for child_line in browse_source_line.child_ids:
498
308
                self.copy_format_line(cr, uid, child_line, destination_format_id, parent_line_id, context=context)
499
309
        return
500
 
 
 
310
            
501
311
financing_contract_format_line()
502
312
 
503
 
 
504
313
class financing_contract_format(osv.osv):
505
 
 
 
314
    
506
315
    _name = "financing.contract.format"
507
316
    _inherit = "financing.contract.format"
508
 
 
 
317
    
509
318
    _columns = {
510
319
        'actual_line_ids': fields.one2many('financing.contract.format.line', 'format_id', 'Actual lines')
511
320
    }
512
 
 
 
321
    
513
322
    def copy_format_lines(self, cr, uid, source_id, destination_id, context=None):
514
323
        # remove all old report lines
515
324
        destination_obj = self.browse(cr, uid, destination_id, context=context)
527
336
                                                                                 parent_id=None,
528
337
                                                                                 context=context)
529
338
        return
530
 
 
 
339
        
531
340
financing_contract_format()
532
341
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: