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
##############################################################################
23
from osv import fields
24
from time import strftime
25
import decimal_precision as dp
27
class analytic_distribution1(osv.osv):
28
_name = "analytic.distribution"
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"),
40
def copy(self, cr, uid, distrib_id, default=None, context=None):
42
Copy an analytic distribution without the one2many links
47
'analytic_lines': 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,
55
return super(osv.osv, self).copy(cr, uid, distrib_id, default, context=context)
57
def update_distribution_line_amount(self, cr, uid, ids, amount=False, context=None):
59
Update amount on distribution lines for given distribution (ids)
64
if isinstance(ids, (int, long)):
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):
75
'amount': round(dl.get('percentage', False) * amount) / 100.0,
77
dl_obj.write(cr, uid, [dl.get('id')], dl_vals, context=context)
80
def update_distribution_line_account(self, cr, uid, line_ids, account_id, context=None):
82
Update account on distribution line
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
90
if isinstance(line_ids, (int, long)):
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}
97
vals = {'analytic_id': account_id}
98
return self.pool.get('funding.pool.distribution.line').write(cr, uid, line_ids, vals)
100
def create_funding_pool_lines(self, cr, uid, ids, account_id=False, context=None):
102
Create funding pool lines regarding cost_center_lines from analytic distribution.
103
If funding_pool_lines exists, then nothing appends.
104
By default, add funding_pool_lines with MSF Private Fund element (written in an OpenERP demo file).
105
For destination axis, get those from account_id default configuration (default_destination_id).
110
if isinstance(ids, (int, long)):
112
# Prepare some values
114
# Browse distributions
115
for distrib in self.browse(cr, uid, ids, context=context):
116
if distrib.funding_pool_lines:
117
res[distrib.id] = False
119
# Browse cost center lines
120
for line in distrib.cost_center_lines:
121
# Search MSF Private Fund
123
pf_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution',
124
'analytic_account_msf_private_funds')[1]
129
'analytic_id': pf_id,
130
'amount': line.amount or 0.0,
131
'percentage': line.percentage or 0.0,
132
'currency_id': line.currency_id and line.currency_id.id or False,
133
'distribution_id': distrib.id or False,
134
'cost_center_id': line.analytic_id and line.analytic_id.id or False,
135
'destination_id': line.destination_id and line.destination_id.id or False,
137
if distrib and distrib.partner_type:
138
vals.update({'partner_type': distrib.partner_type})
140
# Search default destination if no one given
141
if account_id and not vals.get('destination_id'):
142
account = self.pool.get('account.account').browse(cr, uid, account_id)
143
if account and account.is_analytic_addicted:
144
vals.update({'destination_id': account.default_destination_id and account.default_destination_id.id or False})
145
self.pool.get('funding.pool.distribution.line').create(cr, uid, vals, context=context)
146
res[distrib.id] = True
149
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, \
150
move_id=False, invoice_line_id=False, commitment_line_id=False, context=None):
152
Create analytic lines from given elements:
156
- journal_id (analytic_journal_id)
159
- source_date (optional)
160
- general_account_id (optional)
162
- invoice_line_id (optional)
163
- commitment_line_id (optional)
164
Return all created ids, otherwise return false (or [])
169
if isinstance(ids, (int, long)):
171
if not name or not date or not amount or not journal_id or not currency_id:
173
if not document_date:
175
# Prepare some values
179
'date': source_date or date,
180
'document_date': document_date,
182
'journal_id': journal_id,
183
'general_account_id': general_account_id or False,
184
'move_id': move_id or False,
185
'invoice_line_id': invoice_line_id or False,
187
'currency_id': currency_id,
188
'source_date': source_date or False,
189
'commitment_line_id': commitment_line_id or False,
191
company_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
192
# Browse distribution(s)
193
for distrib in self.browse(cr, uid, ids, context=context):
194
vals.update({'distribution_id': distrib.id,})
196
for distrib_lines in [distrib.funding_pool_lines, distrib.free_1_lines, distrib.free_2_lines]:
197
for distrib_line in distrib_lines:
198
context.update({'date': source_date or date}) # for amount computing
199
anal_amount = (distrib_line.percentage * amount) / 100
201
'amount': -1 * self.pool.get('res.currency').compute(cr, uid, currency_id, company_currency,
202
anal_amount, round=False, context=context),
203
'amount_currency': -1 * anal_amount,
204
'account_id': distrib_line.analytic_id.id,
205
'cost_center_id': False,
206
'destination_id': False,
207
'distrib_line_id': '%s,%s'%(distrib_line._name, distrib_line.id),
209
# Update values if we come from a funding pool
210
if distrib_line._name == 'funding.pool.distribution.line':
211
vals.update({'cost_center_id': distrib_line.cost_center_id and distrib_line.cost_center_id.id or False,
212
'destination_id': distrib_line.destination_id and distrib_line.destination_id.id or False,})
213
# create analytic line
214
al_id = self.pool.get('account.analytic.line').create(cr, uid, vals, context=context)
218
analytic_distribution1()
220
class distribution_line(osv.osv):
221
_name = "distribution.line"
224
'name': fields.char('Name', size=64),
225
"distribution_id": fields.many2one('analytic.distribution', 'Associated Analytic Distribution', ondelete='cascade'),
226
"analytic_id": fields.many2one('account.analytic.account', 'Analytical Account'),
227
"amount": fields.float('Amount', digits_compute=dp.get_precision('Account')),
228
"percentage": fields.float('Percentage', digits=(16,4)),
229
"currency_id": fields.many2one('res.currency', 'Currency', required=True),
230
"date": fields.date(string="Date"),
231
"source_date": fields.date(string="Source Date", help="This date is for source_date for analytic lines"),
232
'partner_type': fields.text(string='Partner Type of FO/PO', required=False, readonly=True),
236
'name': 'Distribution Line',
237
'date': lambda *a: strftime('%Y-%m-%d'),
238
'source_date': lambda *a: strftime('%Y-%m-%d'),
241
def _check_percentage(self, cr, uid, ids, context=None):
243
Do not allow 0.0 percentage value
245
for l in self.browse(cr, uid, ids):
246
if l.percentage == 0.0:
251
(_check_percentage, '0 is not allowed as percentage value!', ['percentage']),
256
class cost_center_distribution_line(osv.osv):
257
_name = "cost.center.distribution.line"
258
_inherit = "distribution.line"
260
"destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=True),
263
cost_center_distribution_line()
265
class funding_pool_distribution_line(osv.osv):
266
_name = "funding.pool.distribution.line"
267
_inherit = "distribution.line"
269
"cost_center_id": fields.many2one('account.analytic.account', 'Cost Center Account', required=True),
270
"destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=True),
273
funding_pool_distribution_line()
275
class free_1_distribution_line(osv.osv):
276
_name = "free.1.distribution.line"
277
_inherit = "distribution.line"
279
"destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=False),
282
free_1_distribution_line()
284
class free_2_distribution_line(osv.osv):
285
_name = "free.2.distribution.line"
286
_inherit = "distribution.line"
288
"destination_id": fields.many2one('account.analytic.account', 'Destination', domain="[('type', '!=', 'view'), ('category', '=', 'DEST')]", required=False),
291
free_2_distribution_line()
293
class analytic_distribution(osv.osv):
294
_name = 'analytic.distribution'
295
_inherit = "analytic.distribution"
297
def _get_lines_count(self, cr, uid, ids, name=False, args=False, context=None):
299
Get count of each analytic distribution lines type.
300
Example: with an analytic distribution with 2 cost center, 3 funding pool and 1 Free 1:
301
2 CC; 3 FP; 1 F1; 0 F2;
302
(Number of chars: 20 chars + 4 x some lines number)
307
# Prepare some values
311
if isinstance(ids, (int, long)):
313
# Browse given invoices
314
for distrib in self.browse(cr, uid, ids, context=context):
316
txt += str(len(distrib.cost_center_lines) or '0') + ' CC; '
317
txt += str(len(distrib.funding_pool_lines) or '0') + ' FP; '
318
txt += str(len(distrib.free_1_lines) or '0') + ' F1; '
319
txt += str(len(distrib.free_2_lines) or '0') + ' F2'
322
res[distrib.id] = txt
326
'cost_center_lines': fields.one2many('cost.center.distribution.line', 'distribution_id', 'Cost Center Distribution'),
327
'funding_pool_lines': fields.one2many('funding.pool.distribution.line', 'distribution_id', 'Funding Pool Distribution'),
328
'free_1_lines': fields.one2many('free.1.distribution.line', 'distribution_id', 'Free 1 Distribution'),
329
'free_2_lines': fields.one2many('free.2.distribution.line', 'distribution_id', 'Free 2 Distribution'),
330
'name': fields.function(_get_lines_count, method=True, type='char', size=256, string="Name", readonly=True, store=False),
333
analytic_distribution()
334
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
b'\\ No newline at end of file'