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

« back to all changes in this revision

Viewing changes to financing_contract/format_line.py

  • Committer: Quentin THEURET
  • Date: 2011-05-13 08:02:05 UTC
  • mto: This revision was merged to the branch mainline in revision 128.
  • Revision ID: qt@tempo-consulting.fr-20110513080205-zcebzsn2ahccvd4n
UF-205 [ADD] Added procurement_report 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
 
from osv import fields, osv
23
 
 
24
 
class financing_contract_format_line(osv.osv):
25
 
    
26
 
    _name = "financing.contract.format.line"
27
 
    
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)
33
 
                domain += ', '
34
 
            domain = domain[:-2]
35
 
        domain += "])"
36
 
        return domain
37
 
 
38
 
    def _get_number_of_childs(self, cr, uid, ids, field_name=None, arg=None, context={}):
39
 
        # Verifications
40
 
        if not context:
41
 
            context = {}
42
 
        if isinstance(ids, (int, long)):
43
 
            ids = [ids]
44
 
        # Prepare some values
45
 
        res = {}
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
48
 
        return res
49
 
    
50
 
    def _get_parent_ids(self, cr, uid, ids, context=None):
51
 
        res = []
52
 
        for line in self.browse(cr, uid, ids, context=context):
53
 
            if line.parent_id:
54
 
                res.append(line.parent_id.id)
55
 
        return res
56
 
    
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"
60
 
        result = 0.0
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']
62
 
        total_costs = {}
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)
65
 
        else:
66
 
            total_costs = self._get_actual_amount(cr, uid, total_line_ids, field_name, context=context)
67
 
        for total_cost in total_costs.values():
68
 
            result += total_cost
69
 
        return result
70
 
    
71
 
    def _get_account_ids(self, browse_line, funding_pool_account_ids):
72
 
        result = []
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]
75
 
        else:
76
 
            for child_line in browse_line.child_ids:
77
 
                result += self._get_account_ids(child_line, funding_pool_account_ids)
78
 
        return result
79
 
    
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
86
 
        date_domain += "')]"
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)
96
 
        # Funding pools
97
 
        funding_pool_ids = []
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]
100
 
        else:
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)
103
 
        # Cost centers
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}
109
 
    
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
113
 
            return False
114
 
        else:
115
 
            format = browse_line.format_id
116
 
            general_domain = self._get_general_domain(cr, uid, format, domain_type, context=context)
117
 
            # General accounts
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],
124
 
                        date_domain[1],
125
 
                        eval(account_domain),
126
 
                        eval(general_domain['funding_pool_domain'])]
127
 
            else: 
128
 
                return [date_domain[0],
129
 
                        date_domain[1],
130
 
                        eval(account_domain),
131
 
                        eval(general_domain['funding_pool_domain']),
132
 
                        eval(general_domain['cost_center_domain'])]
133
 
 
134
 
    def _get_budget_amount(self, cr, uid, ids, field_name=None, arg=None, context=None):
135
 
        """
136
 
            Method to compute the allocated budget/amounts, depending on the information in the line
137
 
        """
138
 
        res = {}
139
 
        for line in self.browse(cr, uid, ids, context=context):
140
 
            # default value
141
 
            res[line.id] = 0.0
142
 
            if line.line_type:
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
151
 
                    sum_budget = 0.0
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':
157
 
                    # 2 cases
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)
166
 
        return res
167
 
 
168
 
    def _get_actual_amount(self, cr, uid, ids, field_name=None, arg=None, context=None):
169
 
        """
170
 
            Method to compute the allocated budget/amounts, depending on the information in the line
171
 
        """
172
 
        res = {}
173
 
        for line in self.browse(cr, uid, ids, context=context):
174
 
            # default value
175
 
            res[line.id] = 0.0
176
 
            if line.line_type:
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
185
 
                    sum_real = 0.0
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':
191
 
                    # 2 cases
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
202
 
                    analytic_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)
211
 
                        real_sum = 0.0
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,
219
 
                                                                              uid,
220
 
                                                                              analytic_line.currency_id.id,
221
 
                                                                              context['reporting_currency'], 
222
 
                                                                              analytic_line.amount_currency or 0.0,
223
 
                                                                              round=False,
224
 
                                                                              context=date_context)
225
 
                        real_sum = abs(real_sum)
226
 
                        res[line.id] = real_sum
227
 
        return res
228
 
    
229
 
    _columns = {
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'),
237
 
                                       ('actual','Actual'),
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"),
251
 
    }
252
 
    
253
 
    _defaults = {
254
 
        'line_type': 'actual',
255
 
        'overhead_type': 'cost_percentage',
256
 
        'parent_id': lambda *a: False
257
 
    }
258
 
    
259
 
    def create(self, cr, uid, vals, context=None):
260
 
        if not context:
261
 
            context={}
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)
268
 
    
269
 
    def write(self, cr, uid, ids, vals, context=None):
270
 
        if not context:
271
 
            context={}
272
 
        if isinstance(ids, (int, long)):
273
 
            ids = [ids]
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)
280
 
    
281
 
    def copy_format_line(self, cr, uid, browse_source_line, destination_format_id, parent_id=None, context=None):
282
 
        if destination_format_id:
283
 
            format_line_vals = {
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,
289
 
            }
290
 
            account_ids = []
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)
297
 
        return
298
 
            
299
 
financing_contract_format_line()
300
 
 
301
 
class financing_contract_format(osv.osv):
302
 
    
303
 
    _name = "financing.contract.format"
304
 
    _inherit = "financing.contract.format"
305
 
    
306
 
    _columns = {
307
 
        'actual_line_ids': fields.one2many('financing.contract.format.line', 'format_id', 'Actual lines')
308
 
    }
309
 
    
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
317
 
        # copy format lines
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,
321
 
                                                                                 uid,
322
 
                                                                                 source_line,
323
 
                                                                                 destination_id,
324
 
                                                                                 parent_id=None,
325
 
                                                                                 context=context)
326
 
        return
327
 
        
328
 
financing_contract_format()
329
 
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
 
b'\\ No newline at end of file'