~unifield-team/unifield-wm/us-671-homere

« back to all changes in this revision

Viewing changes to analytic_override/analytic_distribution.py

[UF-43] fix added noupdate to demo data

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) 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 osv
23
 
from osv import fields
24
 
from time import strftime
25
 
import decimal_precision as dp
26
 
 
27
 
class analytic_distribution1(osv.osv):
28
 
    _name = "analytic.distribution"
29
 
 
30
 
    _columns = {
31
 
        'analytic_lines': fields.one2many('account.analytic.line', 'distribution_id', 'Analytic Lines'),
32
 
        'invoice_ids': fields.one2many('account.invoice', 'analytic_distribution_id', string="Invoices"),
33
 
        'invoice_line_ids': fields.one2many('account.invoice.line', 'analytic_distribution_id', string="Invoice Lines"),
34
 
        'register_line_ids': fields.one2many('account.bank.statement.line', 'analytic_distribution_id', string="Register Lines"),
35
 
        '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, distrib_id, default=None, context=None):
41
 
        """
42
 
        Copy an analytic distribution without the one2many links
43
 
        """
44
 
        if default is None:
45
 
            default = {}
46
 
        default.update({
47
 
            'analytic_lines': False,
48
 
            'invoice_ids': False,
49
 
            'invoice_line_ids': False,
50
 
            'register_line_ids': False,
51
 
            'move_line_ids': False,
52
 
            'commitment_ids': False,
53
 
            'commitment_line_ids': False,
54
 
        })
55
 
        return super(osv.osv, self).copy(cr, uid, distrib_id, default, context=context)
56
 
 
57
 
    def update_distribution_line_amount(self, cr, uid, ids, amount=False, context=None):
58
 
        """
59
 
        Update amount on distribution lines for given distribution (ids)
60
 
        """
61
 
        # Some verifications
62
 
        if not context:
63
 
            context = {}
64
 
        if isinstance(ids, (int, long)):
65
 
            ids = [ids]
66
 
        if not amount:
67
 
            return False
68
 
        # Process distributions
69
 
        for distrib_id in ids:
70
 
            for dl_name in ['cost.center.distribution.line', 'funding.pool.distribution.line', 'free.1.distribution.line', 'free.2.distribution.line']:
71
 
                dl_obj = self.pool.get(dl_name)
72
 
                dl_ids = dl_obj.search(cr, uid, [('distribution_id', '=', distrib_id)], context=context)
73
 
                for dl in dl_obj.read(cr, uid, dl_ids, ['percentage'], context=context):
74
 
                    dl_vals = {
75
 
                        'amount': round(dl.get('percentage', False) * amount) / 100.0,
76
 
                    }
77
 
                    dl_obj.write(cr, uid, [dl.get('id')], dl_vals, context=context)
78
 
        return True
79
 
 
80
 
    def update_distribution_line_account(self, cr, uid, line_ids, account_id, context=None):
81
 
        """
82
 
        Update account on distribution line
83
 
        """
84
 
        # Some verifications
85
 
        if not context:
86
 
            context = {}
87
 
        # Return False if no line_ids
88
 
        if not account_id or not line_ids: # fix bug on UF-2205 with analytic lines that comes from INTL Engagement journal without any distribution
89
 
            return False
90
 
        if isinstance(line_ids, (int, long)):
91
 
            line_ids = [line_ids]
92
 
        # Prepare some values
93
 
        account = self.pool.get('account.analytic.account').browse(cr, uid, [account_id], context=context)[0]
94
 
        if account.category == 'OC':
95
 
            vals = {'cost_center_id': account_id}
96
 
        elif account.category == 'DEST':
97
 
            vals = {'destination_id': account_id}
98
 
        else:
99
 
            vals = {'analytic_id': account_id}
100
 
        return self.pool.get('funding.pool.distribution.line').write(cr, uid, line_ids, vals)
101
 
 
102
 
    def create_funding_pool_lines(self, cr, uid, ids, account_id=False, context=None):
103
 
        """
104
 
        Create funding pool lines regarding cost_center_lines from analytic distribution.
105
 
        If funding_pool_lines exists, then nothing appends.
106
 
        By default, add funding_pool_lines with MSF Private Fund element (written in an OpenERP demo file).
107
 
        For destination axis, get those from account_id default configuration (default_destination_id).
108
 
        """
109
 
        # Some verifications
110
 
        if not context:
111
 
            context = {}
112
 
        if isinstance(ids, (int, long)):
113
 
            ids = [ids]
114
 
        # Prepare some values
115
 
        res = {}
116
 
        # Browse distributions
117
 
        for distrib in self.browse(cr, uid, ids, context=context):
118
 
            if distrib.funding_pool_lines:
119
 
                res[distrib.id] = False
120
 
                continue
121
 
            # Browse cost center lines
122
 
            for line in distrib.cost_center_lines:
123
 
                # Search MSF Private Fund
124
 
                try:
125
 
                    pf_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution',
126
 
                    'analytic_account_msf_private_funds')[1]
127
 
                except ValueError:
128
 
                    pf_id = 0
129
 
                if pf_id:
130
 
                    vals = {
131
 
                        'analytic_id': pf_id,
132
 
                        'amount': line.amount or 0.0,
133
 
                        'percentage': line.percentage or 0.0,
134
 
                        'currency_id': line.currency_id and line.currency_id.id or False,
135
 
                        'distribution_id': distrib.id or False,
136
 
                        'cost_center_id': line.analytic_id and line.analytic_id.id or False,
137
 
                        'destination_id': line.destination_id and line.destination_id.id or False,
138
 
                    }
139
 
                    if distrib and distrib.partner_type:
140
 
                        vals.update({'partner_type': distrib.partner_type})
141
 
 
142
 
                    # Search default destination if no one given
143
 
                    if account_id and not vals.get('destination_id'):
144
 
                        account = self.pool.get('account.account').browse(cr, uid, account_id)
145
 
                        if account and account.is_analytic_addicted:
146
 
                            vals.update({'destination_id': account.default_destination_id and account.default_destination_id.id or False})
147
 
                    self.pool.get('funding.pool.distribution.line').create(cr, uid, vals, context=context)
148
 
            res[distrib.id] = True
149
 
        return res
150
 
 
151
 
    def create_analytic_lines(self, cr, uid, ids, name, date, amount, journal_id, currency_id, document_date=False, ref=False, source_date=False, general_account_id=False, \
152
 
        move_id=False, invoice_line_id=False, commitment_line_id=False, context=None):
153
 
        """
154
 
        Create analytic lines from given elements:
155
 
         - date
156
 
         - name
157
 
         - amount
158
 
         - journal_id (analytic_journal_id)
159
 
         - currency_id
160
 
         - ref (optional)
161
 
         - source_date (optional)
162
 
         - general_account_id (optional)
163
 
         - move_id (optional)
164
 
         - invoice_line_id (optional)
165
 
         - commitment_line_id (optional)
166
 
        Return all created ids, otherwise return false (or [])
167
 
        """
168
 
        # Some verifications
169
 
        if not context:
170
 
            context = {}
171
 
        if isinstance(ids, (int, long)):
172
 
            ids = [ids]
173
 
        if not name or not date or not amount or not journal_id or not currency_id:
174
 
            return False
175
 
        if not document_date:
176
 
            document_date = date
177
 
        # Prepare some values
178
 
        res = []
179
 
        vals = {
180
 
            'name': name,
181
 
            'date': source_date or date,
182
 
            'document_date': document_date,
183
 
            'ref': ref or '',
184
 
            'journal_id': journal_id,
185
 
            'general_account_id': general_account_id or False,
186
 
            'move_id': move_id or False,
187
 
            'invoice_line_id': invoice_line_id or False,
188
 
            'user_id': uid,
189
 
            'currency_id': currency_id,
190
 
            'source_date': source_date or False,
191
 
            'commitment_line_id': commitment_line_id or False,
192
 
        }
193
 
        company_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
194
 
        # Browse distribution(s)
195
 
        for distrib in self.browse(cr, uid, ids, context=context):
196
 
            vals.update({'distribution_id': distrib.id,})
197
 
            # create lines
198
 
            for distrib_lines in [distrib.funding_pool_lines, distrib.free_1_lines, distrib.free_2_lines]:
199
 
                for distrib_line in distrib_lines:
200
 
                    context.update({'date': source_date or date}) # for amount computing
201
 
                    anal_amount = (distrib_line.percentage * amount) / 100
202
 
                    vals.update({
203
 
                        'amount': -1 * self.pool.get('res.currency').compute(cr, uid, currency_id, company_currency,
204
 
                            anal_amount, round=False, context=context),
205
 
                        'amount_currency': -1 * anal_amount,
206
 
                        'account_id': distrib_line.analytic_id.id,
207
 
                        'cost_center_id': False,
208
 
                        'destination_id': False,
209
 
                        'distrib_line_id': '%s,%s'%(distrib_line._name, distrib_line.id),
210
 
                    })
211
 
                    # Update values if we come from a funding pool
212
 
                    if distrib_line._name == 'funding.pool.distribution.line':
213
 
                        vals.update({'cost_center_id': distrib_line.cost_center_id and distrib_line.cost_center_id.id or False,
214
 
                            'destination_id': distrib_line.destination_id and distrib_line.destination_id.id or False,})
215
 
                    # create analytic line
216
 
                    al_id = self.pool.get('account.analytic.line').create(cr, uid, vals, context=context)
217
 
                    res.append(al_id)
218
 
        return res
219
 
 
220
 
analytic_distribution1()
221
 
 
222
 
class distribution_line(osv.osv):
223
 
    _name = "distribution.line"
224
 
 
225
 
    _columns = {
226
 
        'name': fields.char('Name', size=64),
227
 
        "distribution_id": fields.many2one('analytic.distribution', 'Associated Analytic Distribution', ondelete='cascade', select="1"), # select is for optimisation purposes. Example: 3 seconds on 1 invoice creation+validation
228
 
        "analytic_id": fields.many2one('account.analytic.account', 'Analytical Account'),
229
 
        "amount": fields.float('Amount', digits_compute=dp.get_precision('Account')),
230
 
        "percentage": fields.float('Percentage', digits=(16,4)),
231
 
        "currency_id": fields.many2one('res.currency', 'Currency', required=True),
232
 
        "date": fields.date(string="Date"),
233
 
        "source_date": fields.date(string="Source Date", help="This date is for source_date for analytic lines"),
234
 
        'partner_type': fields.text(string='Partner Type of FO/PO', required=False, readonly=True),
235
 
    }
236
 
 
237
 
    _defaults ={
238
 
        'name': 'Distribution Line',
239
 
        'date': lambda *a: strftime('%Y-%m-%d'),
240
 
        'source_date': lambda *a: strftime('%Y-%m-%d'),
241
 
    }
242
 
 
243
 
    def _check_percentage(self, cr, uid, ids, context=None):
244
 
        """
245
 
        Do not allow 0.0 percentage value
246
 
        """
247
 
        for l in self.browse(cr, uid, ids):
248
 
            if l.percentage == 0.0:
249
 
                return False
250
 
        return True
251
 
 
252
 
    _constraints = [
253
 
        (_check_percentage, '0 is not allowed as percentage value!', ['percentage']),
254
 
    ]
255
 
 
256
 
    def create_analytic_lines(self, cr, uid, ids, move_line_id, date, document_date, source_date=False, name=False, ref='', context=None):
257
 
        '''
258
 
        Creates an analytic lines from a distribution line and an account.move.line
259
 
        '''
260
 
        if isinstance(ids, (int, long)):
261
 
            ids = [ids]
262
 
 
263
 
        ret = {}
264
 
        move_line = self.pool.get('account.move.line').browse(cr, uid, move_line_id)
265
 
        company = self.pool.get('res.users').browse(cr, uid, uid).company_id
266
 
        company_currency_id = company.currency_id.id
267
 
        instance_id = company.instance_id.id
268
 
 
269
 
        for line in self.browse(cr, uid, ids):
270
 
            amount_cur = (move_line.credit_currency - move_line.debit_currency) * line.percentage / 100
271
 
            ctx = {'date': source_date or date}
272
 
            amount = self.pool.get('res.currency').compute(cr, uid, move_line.currency_id.id, company_currency_id, amount_cur, round=False, context=ctx)
273
 
            vals = {
274
 
                'instance_id': instance_id,
275
 
                'account_id': line.analytic_id.id,
276
 
                'amount_currency': amount_cur,
277
 
                'amount': amount,
278
 
                'currency_id': move_line.currency_id.id,
279
 
                'general_account_id': move_line.account_id.id,
280
 
                'date': date,
281
 
                # UFTP-361: source_date or source date from line or from line posting date if any
282
 
                # for rev line must be the source date of the move line: posting date of reversed line
283
 
                'source_date': source_date or move_line.source_date or move_line.date,
284
 
                'document_date': document_date,
285
 
                'journal_id': move_line.journal_id and move_line.journal_id.analytic_journal_id and move_line.journal_id.analytic_journal_id.id or False,
286
 
                'move_id': move_line.id,
287
 
                'name': name or move_line.name,
288
 
                'distrib_id': line.distribution_id.id,
289
 
                'distribution_id': line.distribution_id.id,
290
 
                'distrib_line_id': '%s,%s'%(self._name, line.id),
291
 
                'ref': ref or move_line.move_id.name,
292
 
            }
293
 
            if self._name == 'funding.pool.distribution.line':
294
 
                vals.update({
295
 
                    'destination_id': line.destination_id and line.destination_id.id or False,
296
 
                    'cost_center_id': line.cost_center_id and line.cost_center_id.id or False,
297
 
                })
298
 
            ret[line.id] = self.pool.get('account.analytic.line').create(cr, uid, vals)
299
 
 
300
 
        return ret
301
 
 
302
 
distribution_line()
303
 
 
304
 
class cost_center_distribution_line(osv.osv):
305
 
    _name = "cost.center.distribution.line"
306
 
    _inherit = "distribution.line"
307
 
    _columns = {
308
 
        "destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=True),
309
 
    }
310
 
 
311
 
cost_center_distribution_line()
312
 
 
313
 
class funding_pool_distribution_line(osv.osv):
314
 
    _name = "funding.pool.distribution.line"
315
 
    _inherit = "distribution.line"
316
 
    _columns = {
317
 
        "cost_center_id": fields.many2one('account.analytic.account', 'Cost Center Account', required=True),
318
 
        "destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=True),
319
 
    }
320
 
 
321
 
funding_pool_distribution_line()
322
 
 
323
 
class free_1_distribution_line(osv.osv):
324
 
    _name = "free.1.distribution.line"
325
 
    _inherit = "distribution.line"
326
 
    _columns = {
327
 
        "destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=False),
328
 
    }
329
 
 
330
 
free_1_distribution_line()
331
 
 
332
 
class free_2_distribution_line(osv.osv):
333
 
    _name = "free.2.distribution.line"
334
 
    _inherit = "distribution.line"
335
 
    _columns = {
336
 
        "destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=False),
337
 
    }
338
 
 
339
 
free_2_distribution_line()
340
 
 
341
 
class analytic_distribution(osv.osv):
342
 
    _name = 'analytic.distribution'
343
 
    _inherit = "analytic.distribution"
344
 
 
345
 
    def _get_lines_count(self, cr, uid, ids, name=False, args=False, context=None):
346
 
        """
347
 
        Get count of each analytic distribution lines type.
348
 
        Example: with an analytic distribution with 2 cost center, 3 funding pool and 1 Free 1:
349
 
        2 CC; 3 FP; 1 F1; 0 F2;
350
 
        (Number of chars: 20 chars + 4 x some lines number)
351
 
        """
352
 
        # Some verifications
353
 
        if not context:
354
 
            context = {}
355
 
        # Prepare some values
356
 
        res = {}
357
 
        if not ids:
358
 
            return res
359
 
        if isinstance(ids, (int, long)):
360
 
            ids = [ids]
361
 
        # Browse given invoices
362
 
        for distrib in self.browse(cr, uid, ids, context=context):
363
 
            txt = ''
364
 
            txt += str(len(distrib.cost_center_lines) or '0') + ' CC; '
365
 
            txt += str(len(distrib.funding_pool_lines) or '0') + ' FP; '
366
 
            txt += str(len(distrib.free_1_lines) or '0') + ' F1; '
367
 
            txt += str(len(distrib.free_2_lines) or '0') + ' F2'
368
 
            if not txt:
369
 
                txt = ''
370
 
            res[distrib.id] = txt
371
 
        return res
372
 
 
373
 
    _columns = {
374
 
        'cost_center_lines': fields.one2many('cost.center.distribution.line', 'distribution_id', 'Cost Center Distribution'),
375
 
        'funding_pool_lines': fields.one2many('funding.pool.distribution.line', 'distribution_id', 'Funding Pool Distribution'),
376
 
        'free_1_lines': fields.one2many('free.1.distribution.line', 'distribution_id', 'Free 1 Distribution'),
377
 
        'free_2_lines': fields.one2many('free.2.distribution.line', 'distribution_id', 'Free 2 Distribution'),
378
 
        'name': fields.function(_get_lines_count, method=True, type='char', size=256, string="Name", readonly=True, store=False),
379
 
    }
380
 
 
381
 
analytic_distribution()
382
 
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: