1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) MSF, TeMPO Consulting.
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.
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.
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/>.
20
##############################################################################
24
from tools.translate import _
26
class analytic_distribution(osv.osv):
27
_name = 'analytic.distribution'
28
_inherit = 'analytic.distribution'
30
def _get_distribution_state(self, cr, uid, distrib_id, parent_id, account_id, context=None):
32
Return distribution state
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()
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):
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 ''))
47
distrib = self.browse(cr, uid, distrib_id)
48
# Search MSF Private Fund element, because it's valid with all accounts
50
fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution',
51
'analytic_account_msf_private_funds')[1]
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 ''))
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 ''))
68
# If fp_line is MSF Private Fund, all is ok
69
if fp_line.analytic_id.id == fp_id:
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 ''))
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 ''))
79
def analytic_state_from_info(self, cr, uid, account_id, destination_id, cost_center_id, analytic_id, context=None):
81
Give analytic state from the given information.
82
Return result and some info if needed.
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)
94
fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
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')
116
analytic_distribution()
118
class distribution_line(osv.osv):
119
_name = "distribution.line"
120
_inherit = "distribution.line"
122
def create_analytic_lines(self, cr, uid, ids, move_line_id, date, document_date, source_date=False, name=False, context=None):
124
Creates an analytic lines from a distribution line and an account.move.line
126
if isinstance(ids, (int, long)):
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
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)
138
'account_id': line.analytic_id.id,
139
'amount_currency': amount_cur,
141
'currency_id': move_line.currency_id.id,
142
'general_account_id': move_line.account_id.id,
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),
152
if self._name == 'funding.pool.distribution.line':
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,
157
ret[line.id] = self.pool.get('account.analytic.line').create(cr, uid, vals)
162
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: