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

« back to all changes in this revision

Viewing changes to analytic_distribution/analytic_distribution.py

  • Committer: Olivier DOSSMANN
  • Date: 2014-03-31 09:31:46 UTC
  • mto: This revision was merged to the branch mainline in revision 2086.
  • Revision ID: od@tempo-consulting.fr-20140331093146-tgvxnly1kc1hbv1s
UF-2171 [ADD] Analytic distribution reset button for recurring models

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
import netsvc
 
24
from tools.translate import _
 
25
 
 
26
class analytic_distribution(osv.osv):
 
27
    _name = 'analytic.distribution'
 
28
    _inherit = 'analytic.distribution'
 
29
 
 
30
    def _get_distribution_state(self, cr, uid, distrib_id, parent_id, account_id, context=None):
 
31
        """
 
32
        Return distribution state
 
33
        """
 
34
        if context is None:
 
35
            context = {}
 
36
        # Have an analytic distribution on another account than analytic-a-holic account make no sense. So their analytic distribution is valid
 
37
        logger = netsvc.Logger()
 
38
        if account_id:
 
39
            account =  self.pool.get('account.account').read(cr, uid, account_id, ['is_analytic_addicted'])
 
40
            if account and not account.get('is_analytic_addicted', False):
 
41
                return 'valid'
 
42
        if not distrib_id:
 
43
            if parent_id:
 
44
                return self._get_distribution_state(cr, uid, parent_id, False, account_id, context)
 
45
            logger.notifyChannel("analytic distribution", netsvc.LOG_WARNING, _("%s: NONE!") % (distrib_id or ''))
 
46
            return 'none'
 
47
        distrib = self.browse(cr, uid, distrib_id)
 
48
        # Search MSF Private Fund element, because it's valid with all accounts
 
49
        try:
 
50
            fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution',
 
51
            'analytic_account_msf_private_funds')[1]
 
52
        except ValueError:
 
53
            fp_id = 0
 
54
        account = self.pool.get('account.account').read(cr, uid, account_id, ['destination_ids'])
 
55
        # Check Cost Center lines with destination/account link
 
56
        for cc_line in distrib.cost_center_lines:
 
57
            if cc_line.destination_id.id not in account.get('destination_ids', []):
 
58
                logger.notifyChannel("analytic distribution", netsvc.LOG_WARNING, _("%s: Error, destination not compatible with G/L account in CC lines") % (distrib_id or ''))
 
59
                return 'invalid'
 
60
        # Check Funding pool lines regarding:
 
61
        # - destination / account
 
62
        # - If analytic account is MSF Private funds
 
63
        # - Cost center and funding pool compatibility
 
64
        for fp_line in distrib.funding_pool_lines:
 
65
            if fp_line.destination_id.id not in account.get('destination_ids', []):
 
66
                logger.notifyChannel("analytic distribution", netsvc.LOG_WARNING, _("%s: Error, destination not compatible with G/L account for FP lines") % (distrib_id or ''))
 
67
                return 'invalid'
 
68
            # If fp_line is MSF Private Fund, all is ok
 
69
            if fp_line.analytic_id.id == fp_id:
 
70
                continue
 
71
            if (account_id, fp_line.destination_id.id) not in [x.account_id and x.destination_id and (x.account_id.id, x.destination_id.id) for x in fp_line.analytic_id.tuple_destination_account_ids]:
 
72
                logger.notifyChannel("analytic distribution", netsvc.LOG_WARNING, _("%s: Error, account/destination tuple not compatible with given FP analytic account") % (distrib_id or ''))
 
73
                return 'invalid'
 
74
            if fp_line.cost_center_id.id not in [x.id for x in fp_line.analytic_id.cost_center_ids]:
 
75
                logger.notifyChannel("analytic distribution", netsvc.LOG_WARNING, _("%s: Error, CC is not compatible with given FP analytic account") % (distrib_id or ''))
 
76
                return 'invalid'
 
77
        return 'valid'
 
78
 
 
79
    def analytic_state_from_info(self, cr, uid, account_id, destination_id, cost_center_id, analytic_id, context=None):
 
80
        """
 
81
        Give analytic state from the given information.
 
82
        Return result and some info if needed.
 
83
        """
 
84
        # Checks
 
85
        if context is None:
 
86
            context = {}
 
87
        # Prepare some values
 
88
        res = 'valid'
 
89
        info = ''
 
90
        ana_obj = self.pool.get('account.analytic.account')
 
91
        account = self.pool.get('account.account').browse(cr, uid, account_id, context=context)
 
92
        fp = ana_obj.browse(cr, uid, analytic_id, context=context)
 
93
        try:
 
94
            fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
 
95
        except ValueError:
 
96
            fp_id = 0
 
97
        is_private_fund = False
 
98
        if analytic_id == fp_id:
 
99
            is_private_fund = True
 
100
        # DISTRIBUTION VERIFICATION
 
101
        # Check account user_type
 
102
        if account.user_type_code != 'expense':
 
103
            return res, _('Not an expense account')
 
104
        # Check that destination is compatible with account
 
105
        if destination_id not in [x.id for x in account.destination_ids]:
 
106
            return 'invalid', _('Destination not compatible with account')
 
107
        if not is_private_fund:
 
108
            # Check that cost center is compatible with FP (except if FP is MSF Private Fund)
 
109
            if cost_center_id not in [x.id for x in fp.cost_center_ids]:
 
110
                return 'invalid', _('Cost Center not compatible with FP')
 
111
            # Check that tuple account/destination is compatible with FP (except if FP is MSF Private Fund):
 
112
            if (account_id, destination_id) not in [x.account_id and x.destination_id and (x.account_id.id, x.destination_id.id) for x in fp.tuple_destination_account_ids]:
 
113
                return 'invalid', _('account/destination tuple not compatible with given FP analytic account')
 
114
        return res, info
 
115
 
 
116
analytic_distribution()
 
117
 
 
118
class distribution_line(osv.osv):
 
119
    _name = "distribution.line"
 
120
    _inherit = "distribution.line"
 
121
 
 
122
    def create_analytic_lines(self, cr, uid, ids, move_line_id, date, document_date, source_date=False, name=False, context=None):
 
123
        '''
 
124
        Creates an analytic lines from a distribution line and an account.move.line
 
125
        '''
 
126
        if isinstance(ids, (int, long)):
 
127
            ids = [ids]
 
128
 
 
129
        ret = {}
 
130
        move_line = self.pool.get('account.move.line').browse(cr, uid, move_line_id)
 
131
        company_currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
 
132
 
 
133
        for line in self.browse(cr, uid, ids):
 
134
            amount_cur = (move_line.credit_currency - move_line.debit_currency) * line.percentage / 100
 
135
            ctx = {'date': source_date or date}
 
136
            amount = self.pool.get('res.currency').compute(cr, uid, move_line.currency_id.id, company_currency_id, amount_cur, round=False, context=ctx)
 
137
            vals = {
 
138
                'account_id': line.analytic_id.id,
 
139
                'amount_currency': amount_cur,
 
140
                'amount': amount,
 
141
                'currency_id': move_line.currency_id.id,
 
142
                'general_account_id': move_line.account_id.id,
 
143
                'date': date,
 
144
                'source_date': source_date,
 
145
                'document_date': document_date,
 
146
                '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,
 
147
                'move_id': move_line.id,
 
148
                'name': name or move_line.name,
 
149
                'distrib_id': line.distribution_id.id,
 
150
                'distrib_line_id': '%s,%s'%(self._name, line.id),
 
151
            }
 
152
            if self._name == 'funding.pool.distribution.line':
 
153
                vals.update({
 
154
                    'destination_id': line.destination_id and line.destination_id.id or False,
 
155
                    'cost_center_id': line.cost_center_id and line.cost_center_id.id or False,
 
156
                })
 
157
            ret[line.id] = self.pool.get('account.analytic.line').create(cr, uid, vals)
 
158
 
 
159
        return ret
 
160
 
 
161
distribution_line()
 
162
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: