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

« back to all changes in this revision

Viewing changes to analytic_distribution/analytic_distribution.py

[MOVE] funding_pool module to analytic_distribution module

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
from tools.misc import flatten
25
25
from time import strftime
26
26
 
27
 
class analytic_distribution1(osv.osv):
 
27
class analytic_distribution(osv.osv):
28
28
    _name = "analytic.distribution"
29
29
 
30
30
    _columns = {
 
31
        'name': fields.char('Name', size=12),
 
32
        'global_distribution': fields.boolean('Is this distribution copied from the global distribution'),
31
33
        'analytic_lines': fields.one2many('account.analytic.line', 'distribution_id', 'Analytic Lines'),
32
34
        'invoice_ids': fields.one2many('account.invoice', 'analytic_distribution_id', string="Invoices"),
33
35
        'invoice_line_ids': fields.one2many('account.invoice.line', 'analytic_distribution_id', string="Invoice Lines"),
34
36
        'register_line_ids': fields.one2many('account.bank.statement.line', 'analytic_distribution_id', string="Register Lines"),
35
37
        'move_line_ids': fields.one2many('account.move.line', 'analytic_distribution_id', string="Move Lines"),
36
 
        'commitment_ids': fields.one2many('account.commitment', 'analytic_distribution_id', string="Commitments voucher"),
37
 
        'commitment_line_ids': fields.one2many('account.commitment.line', 'analytic_distribution_id', string="Commitment voucher lines"),
38
 
    }
39
 
 
40
 
    def copy(self, cr, uid, id, default=None, context=None):
 
38
    }
 
39
 
 
40
    _defaults ={
 
41
        'name': lambda *a: 'Distribution',
 
42
        'global_distribution': lambda *a: False,
 
43
    }
 
44
 
 
45
    def copy(self, cr, uid, id, defaults={}, context={}):
41
46
        """
42
47
        Copy an analytic distribution without the one2many links
43
48
        """
44
 
        if default is None:
45
 
            default = {}
46
 
        default.update({
 
49
        defaults.update({
47
50
            'analytic_lines': False,
48
51
            'invoice_ids': False,
49
52
            'invoice_line_ids': False,
50
53
            'register_line_ids': False,
51
54
            'move_line_ids': False,
52
 
            'commitment_ids': False,
53
 
            'commitment_line_ids': False,
54
55
        })
55
 
        return super(osv.osv, self).copy(cr, uid, id, default, context=context)
56
 
 
57
 
    def _get_distribution_state(self, cr, uid, id, parent_id, account_id, context=None):
58
 
        """
59
 
        Return distribution state
60
 
        """
61
 
        if context is None:
62
 
            context = {}
63
 
        # Have an analytic distribution on another account than expense account make no sense. So their analaytic distribution is valid
64
 
        if account_id:
65
 
            account =  self.pool.get('account.account').browse(cr, uid, account_id)
66
 
            if account and account.user_type and account.user_type.code != 'expense':
67
 
                return 'valid'
68
 
        if not id:
69
 
            if parent_id:
70
 
                return self._get_distribution_state(cr, uid, parent_id, False, account_id, context)
71
 
            return 'none'
72
 
        distri = self.browse(cr, uid, id)
73
 
        # Search MSF Private Fund element, because it's valid with all accounts
74
 
        try:
75
 
            fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 
76
 
            'analytic_account_msf_private_funds')[1]
77
 
        except ValueError:
78
 
            fp_id = 0
79
 
        for fp_line in distri.funding_pool_lines:
80
 
            # If fp_line is MSF Private Fund, all is ok
81
 
            if fp_line.analytic_id.id == fp_id:
82
 
                continue
83
 
            if account_id not in [x.id for x in fp_line.analytic_id.account_ids]:
84
 
                return 'invalid'
85
 
            if fp_line.cost_center_id.id not in [x.id for x in fp_line.analytic_id.cost_center_ids]:
86
 
                return 'invalid'
87
 
        return 'valid'
88
 
 
89
 
analytic_distribution1()
 
56
        return super(osv.osv, self).copy(cr, uid, id, defaults, context=context)
 
57
 
 
58
analytic_distribution()
90
59
 
91
60
class distribution_line(osv.osv):
92
61
    _name = "distribution.line"
95
64
        'name': fields.char('Name', size=64),
96
65
        "distribution_id": fields.many2one('analytic.distribution', 'Associated Analytic Distribution', ondelete='cascade'),
97
66
        "analytic_id": fields.many2one('account.analytic.account', 'Analytical Account'),
98
 
        "amount": fields.float('Amount', digits_compute=dp.get_precision('Account')),
99
 
        "percentage": fields.float('Percentage', digits=(16,4)),
 
67
        "amount": fields.float('Amount'),
 
68
        "percentage": fields.float('Percentage'),
100
69
        "currency_id": fields.many2one('res.currency', 'Currency', required=True),
101
70
        "date": fields.date(string="Date"),
102
71
        "source_date": fields.date(string="Source Date", help="This date is for source_date for analytic lines"),
140
109
class analytic_distribution(osv.osv):
141
110
    _inherit = "analytic.distribution"
142
111
 
143
 
    def _get_lines_count(self, cr, uid, ids, name, args, context=None):
144
 
        """
145
 
        Get count of each analytic distribution lines type.
146
 
        Example: with an analytic distribution with 2 cost center, 3 funding pool and 1 Free 1:
147
 
        2 CC; 3 FP; 1 F1; 0 F2; 
148
 
        (Number of chars: 20 chars + 4 x some lines number)
149
 
        """
150
 
        # Some verifications
151
 
        if not context:
152
 
            context = {}
153
 
        if isinstance(ids, (int, long)):
154
 
            ids = [ids]
155
 
        # Prepare some values
156
 
        res = {}
157
 
        # Browse given invoices
158
 
        for distrib in self.browse(cr, uid, ids, context=context):
159
 
            txt = ''
160
 
            txt += str(len(distrib.cost_center_lines) or '0') + ' CC; '
161
 
            txt += str(len(distrib.funding_pool_lines) or '0') + ' FP; '
162
 
            txt += str(len(distrib.free_1_lines) or '0') + ' F1; '
163
 
            txt += str(len(distrib.free_2_lines) or '0') + ' F2'
164
 
            if not txt:
165
 
                txt = ''
166
 
            res[distrib.id] = txt
167
 
        return res
168
 
 
169
112
    _columns = {
170
113
        'cost_center_lines': fields.one2many('cost.center.distribution.line', 'distribution_id', 'Cost Center Distribution'),
171
114
        'funding_pool_lines': fields.one2many('funding.pool.distribution.line', 'distribution_id', 'Funding Pool Distribution'),
172
115
        'free_1_lines': fields.one2many('free.1.distribution.line', 'distribution_id', 'Free 1 Distribution'),
173
116
        'free_2_lines': fields.one2many('free.2.distribution.line', 'distribution_id', 'Free 2 Distribution'),
174
 
        'name': fields.function(_get_lines_count, method=True, type='char', size=256, string="Name", readonly=True, store=False),
175
117
    }
 
118
    
 
119
    def copy_from_global_distribution(self, cr, uid, source_id, destination_id, destination_amount, destination_currency, context={}):
 
120
        cc_distrib_line_obj = self.pool.get('cost.center.distribution.line')
 
121
        fp_distrib_line_obj = self.pool.get('funding.pool.distribution.line')
 
122
        f1_distrib_line_obj = self.pool.get('free.1.distribution.line')
 
123
        f2_distrib_line_obj = self.pool.get('free.2.distribution.line')
 
124
        source_obj = self.browse(cr, uid, source_id, context=context)
 
125
        destination_obj = self.browse(cr, uid, destination_id, context=context)
 
126
        # clean up
 
127
        for cost_center_line in destination_obj.cost_center_lines:
 
128
            cc_distrib_line_obj.unlink(cr, uid, cost_center_line.id)
 
129
        for funding_pool_line in destination_obj.funding_pool_lines:
 
130
            fp_distrib_line_obj.unlink(cr, uid, funding_pool_line.id)
 
131
        for free_1_line in destination_obj.free_1_lines:
 
132
            f1_distrib_line_obj.unlink(cr, uid, free_1_line.id)
 
133
        for free_2_line in destination_obj.free_2_lines:
 
134
            f2_distrib_line_obj.unlink(cr, uid, free_2_line.id)
 
135
        # add values
 
136
        vals = {}
 
137
        vals['name'] = source_obj.name
 
138
        vals['global_distribution'] = True
 
139
        for source_cost_center_line in source_obj.cost_center_lines:
 
140
            distrib_line_vals = {
 
141
                'name': source_cost_center_line.name,
 
142
                'analytic_id': source_cost_center_line.analytic_id.id,
 
143
                'percentage': source_cost_center_line.percentage,
 
144
                'amount': round(source_cost_center_line.percentage * destination_amount) / 100.0,
 
145
                'distribution_id': destination_id,
 
146
                'currency_id': destination_currency,
 
147
                'date': source_cost_center_line.date or False,
 
148
                'source_date': source_cost_center_line.source_date or False,
 
149
            }
 
150
            cc_distrib_line_obj.create(cr, uid, distrib_line_vals, context=context)
 
151
        for source_funding_pool_line in source_obj.funding_pool_lines:
 
152
            distrib_line_vals = {
 
153
                'name': source_funding_pool_line.name,
 
154
                'analytic_id': source_funding_pool_line.analytic_id.id,
 
155
                'cost_center_id': source_funding_pool_line.cost_center_id.id,
 
156
                'percentage': source_funding_pool_line.percentage,
 
157
                'amount': round(source_funding_pool_line.percentage * destination_amount) / 100.0,
 
158
                'distribution_id': destination_id,
 
159
                'currency_id': destination_currency,
 
160
                'date': source_funding_pool_line.date or False,
 
161
                'source_date': source_funding_pool_line.source_date or False,
 
162
            }
 
163
            fp_distrib_line_obj.create(cr, uid, distrib_line_vals, context=context)
 
164
        for source_free_1_line in source_obj.free_1_lines:
 
165
            distrib_line_vals = {
 
166
                'name': source_free_1_line.name,
 
167
                'analytic_id': source_free_1_line.analytic_id.id,
 
168
                'percentage': source_free_1_line.percentage,
 
169
                'amount': round(source_free_1_line.percentage * destination_amount) / 100.0,
 
170
                'distribution_id': destination_id,
 
171
                'currency_id': destination_currency,
 
172
                'date': source_free_1_line.date or False,
 
173
                'source_date': source_free_1_line.source_date or False,
 
174
            }
 
175
            f1_distrib_line_obj.create(cr, uid, distrib_line_vals, context=context)
 
176
        for source_free_2_line in source_obj.free_2_lines:
 
177
            distrib_line_vals = {
 
178
                'name': source_free_2_line.name,
 
179
                'analytic_id': source_free_2_line.analytic_id.id,
 
180
                'percentage': source_free_2_line.percentage,
 
181
                'amount': round(source_free_2_line.percentage * destination_amount) / 100.0,
 
182
                'distribution_id': destination_id,
 
183
                'currency_id': destination_currency,
 
184
                'date': source_free_2_line.date or False,
 
185
                'source_date': source_free_2_line.source_date or False,
 
186
            }
 
187
            f2_distrib_line_obj.create(cr, uid, distrib_line_vals, context=context)
 
188
        if destination_obj.invoice_line_ids:
 
189
            self.pool.get('account.invoice.line').create_engagement_lines(cr, uid, [x.id for x in destination_obj.invoice_line_ids])
 
190
        return super(analytic_distribution, self).write(cr, uid, [destination_id], vals, context=context)
176
191
 
177
 
    def update_distribution_line_amount(self, cr, uid, ids, amount=False, context=None):
 
192
    def update_distribution_line_amount(self, cr, uid, ids, amount=False, context={}):
178
193
        """
179
194
        Update amount on distribution lines for given distribution (ids)
180
195
        """
197
212
                    dl_obj.write(cr, uid, [dl.id], dl_vals, context=context)
198
213
        return True
199
214
 
200
 
    def update_distribution_line_account(self, cr, uid, ids, old_account_id, account_id, context=None):
201
 
        """
202
 
        Update account on distribution line
203
 
        """
204
 
        # Some verifications
205
 
        if not context:
206
 
            context = {}
207
 
        if isinstance(ids, (int, long)):
208
 
            ids = [ids]
209
 
        if not old_account_id or not account_id:
210
 
            return False
211
 
        # Prepare some values
212
 
        account = self.pool.get('account.analytic.account').browse(cr, uid, [account_id], context=context)[0]
213
 
        # Browse distribution
214
 
        for distrib_id in ids:
215
 
            for dl_name in ['cost.center.distribution.line', 'funding.pool.distribution.line', 'free.1.distribution.line', 'free.2.distribution.line']:
216
 
                dl_obj = self.pool.get(dl_name)
217
 
                dl_ids = dl_obj.search(cr, uid, [('distribution_id', '=', distrib_id), ('analytic_id', '=', old_account_id)], context=context)
218
 
                for dl in dl_obj.browse(cr, uid, dl_ids, context=context):
219
 
                    if account.category == 'OC':
220
 
                        # Search funding pool line to update them
221
 
                        fp_line_ids = self.pool.get('funding.pool.distribution.line').search(cr, uid, [('distribution_id', "=", distrib_id), 
222
 
                            ('cost_center_id', '=', old_account_id)])
223
 
                        if isinstance(fp_line_ids, (int, long)):
224
 
                            fp_line_ids = [fp_line_ids]
225
 
                        # Update funding pool line(s)
226
 
                        self.pool.get('funding.pool.distribution.line').write(cr, uid, fp_line_ids, {'cost_center_id': account_id}, context=context)
227
 
                    # Update distribution line
228
 
                    dl_obj.write(cr, uid, [dl.id], {'analytic_id': account_id,}, context=context)
229
 
        return True
230
 
 
231
 
    def create_funding_pool_lines(self, cr, uid, ids, context=None):
232
 
        """
233
 
        Create funding pool lines regarding cost_center_lines from analytic distribution.
234
 
        If funding_pool_lines exists, then nothing appends.
235
 
        By default, add funding_pool_lines with MSF Private Fund element (written in an OpenERP demo file).
236
 
        """
237
 
        # Some verifications
238
 
        if not context:
239
 
            context = {}
240
 
        if isinstance(ids, (int, long)):
241
 
            ids = [ids]
242
 
        # Prepare some values
243
 
        res = {}
244
 
        # Browse distributions
245
 
        for distrib in self.browse(cr, uid, ids, context=context):
246
 
            if distrib.funding_pool_lines:
247
 
                res[distrib.id] = False
248
 
                continue
249
 
            # Browse cost center lines
250
 
            for line in distrib.cost_center_lines:
251
 
                # Search MSF Private Fund
252
 
                try:
253
 
                    pf_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 
254
 
                    'analytic_account_msf_private_funds')[1]
255
 
                except ValueError:
256
 
                    pf_id = 0
257
 
#                pf_id = self.pool.get('account.analytic.account').search(cr, uid, [('code', '=', 'PF'), ('category', '=', 'FUNDING')], context=context, limit=1)
258
 
                if pf_id:
259
 
                    vals = {
260
 
                        'analytic_id': pf_id,
261
 
                        'amount': line.amount or 0.0,
262
 
                        'percentage': line.percentage or 0.0,
263
 
                        'currency_id': line.currency_id and line.currency_id.id or False,
264
 
                        'distribution_id': distrib.id or False,
265
 
                        'cost_center_id': line.analytic_id and line.analytic_id.id or False,
266
 
                    }
267
 
                    new_pf_line_id = self.pool.get('funding.pool.distribution.line').create(cr, uid, vals, context=context)
268
 
            res[distrib.id] = True
269
 
        return res
270
 
 
271
 
    def create_analytic_lines(self, cr, uid, ids, name, date, amount, journal_id, currency_id, ref=False, source_date=False, general_account_id=False, \
272
 
        move_id=False, invoice_line_id=False, commitment_line_id=False, context=None):
273
 
        """
274
 
        Create analytic lines from given elements:
275
 
         - date
276
 
         - name
277
 
         - amount
278
 
         - journal_id (analytic_journal_id)
279
 
         - currency_id
280
 
         - ref (optional)
281
 
         - source_date (optional)
282
 
         - general_account_id (optional)
283
 
         - move_id (optional)
284
 
         - invoice_line_id (optional)
285
 
         - commitment_line_id (optional)
286
 
        Return all created ids, otherwise return false (or [])
287
 
        """
288
 
        # Some verifications
289
 
        if not context:
290
 
            context = {}
291
 
        if isinstance(ids, (int, long)):
292
 
            ids = [ids]
293
 
        if not name or not date or not amount or not journal_id or not currency_id:
294
 
            return False
295
 
        # Prepare some values
296
 
        res = []
297
 
        vals = {
298
 
            'name': name,
299
 
            'date': source_date or date,
300
 
            'ref': ref or '',
301
 
            'journal_id': journal_id,
302
 
            'general_account_id': general_account_id or False,
303
 
            'move_id': move_id or False,
304
 
            'invoice_line_id': invoice_line_id or False,
305
 
            'user_id': uid,
306
 
            'currency_id': currency_id,
307
 
            'source_date': source_date or False,
308
 
            'commitment_line_id': commitment_line_id or False,
309
 
        }
310
 
        company_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
311
 
        # Browse distribution(s)
312
 
        for distrib in self.browse(cr, uid, ids, context=context):
313
 
            vals.update({'distribution_id': distrib.id,})
314
 
            # create lines
315
 
            for distrib_lines in [distrib.cost_center_lines, distrib.funding_pool_lines, distrib.free_1_lines, distrib.free_2_lines]:
316
 
                for distrib_line in distrib_lines:
317
 
                    context.update({'date': source_date or date}) # for amount computing
318
 
                    anal_amount = (distrib_line.percentage * amount) / 100
319
 
                    vals.update({
320
 
                        'amount': -1 * self.pool.get('res.currency').compute(cr, uid, currency_id, company_currency, 
321
 
                            anal_amount, round=False, context=context),
322
 
                        'amount_currency': -1 * anal_amount,
323
 
                        'account_id': distrib_line.analytic_id.id,
324
 
                    })
325
 
                    # Update values if we come from a funding pool
326
 
                    if distrib_line._name == 'funding.pool.distribution.line':
327
 
                        vals.update({'cost_center_id': distrib_line.cost_center_id and distrib_line.cost_center_id.id or False,})
328
 
                    # create analytic line
329
 
                    al_id = self.pool.get('account.analytic.line').create(cr, uid, vals, context=context)
330
 
                    res.append(al_id)
331
 
        return res
332
 
 
333
215
analytic_distribution()
334
216
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: