24
24
from tools.misc import flatten
25
25
from time import strftime
27
class analytic_distribution1(osv.osv):
27
class analytic_distribution(osv.osv):
28
28
_name = "analytic.distribution"
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"),
40
def copy(self, cr, uid, id, default=None, context=None):
41
'name': lambda *a: 'Distribution',
42
'global_distribution': lambda *a: False,
45
def copy(self, cr, uid, id, defaults={}, context={}):
42
47
Copy an analytic distribution without the one2many links
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,
55
return super(osv.osv, self).copy(cr, uid, id, default, context=context)
57
def _get_distribution_state(self, cr, uid, id, parent_id, account_id, context=None):
59
Return distribution state
63
# Have an analytic distribution on another account than expense account make no sense. So their analaytic distribution is valid
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':
70
return self._get_distribution_state(cr, uid, parent_id, False, account_id, context)
72
distri = self.browse(cr, uid, id)
73
# Search MSF Private Fund element, because it's valid with all accounts
75
fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution',
76
'analytic_account_msf_private_funds')[1]
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:
83
if account_id not in [x.id for x in fp_line.analytic_id.account_ids]:
85
if fp_line.cost_center_id.id not in [x.id for x in fp_line.analytic_id.cost_center_ids]:
89
analytic_distribution1()
56
return super(osv.osv, self).copy(cr, uid, id, defaults, context=context)
58
analytic_distribution()
91
60
class distribution_line(osv.osv):
92
61
_name = "distribution.line"
140
109
class analytic_distribution(osv.osv):
141
110
_inherit = "analytic.distribution"
143
def _get_lines_count(self, cr, uid, ids, name, args, context=None):
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)
153
if isinstance(ids, (int, long)):
155
# Prepare some values
157
# Browse given invoices
158
for distrib in self.browse(cr, uid, ids, context=context):
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'
166
res[distrib.id] = txt
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),
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)
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)
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,
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,
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,
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,
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)
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={}):
179
194
Update amount on distribution lines for given distribution (ids)
197
212
dl_obj.write(cr, uid, [dl.id], dl_vals, context=context)
200
def update_distribution_line_account(self, cr, uid, ids, old_account_id, account_id, context=None):
202
Update account on distribution line
207
if isinstance(ids, (int, long)):
209
if not old_account_id or not account_id:
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)
231
def create_funding_pool_lines(self, cr, uid, ids, context=None):
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).
240
if isinstance(ids, (int, long)):
242
# Prepare some values
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
249
# Browse cost center lines
250
for line in distrib.cost_center_lines:
251
# Search MSF Private Fund
253
pf_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution',
254
'analytic_account_msf_private_funds')[1]
257
# pf_id = self.pool.get('account.analytic.account').search(cr, uid, [('code', '=', 'PF'), ('category', '=', 'FUNDING')], context=context, limit=1)
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,
267
new_pf_line_id = self.pool.get('funding.pool.distribution.line').create(cr, uid, vals, context=context)
268
res[distrib.id] = True
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):
274
Create analytic lines from given elements:
278
- journal_id (analytic_journal_id)
281
- source_date (optional)
282
- general_account_id (optional)
284
- invoice_line_id (optional)
285
- commitment_line_id (optional)
286
Return all created ids, otherwise return false (or [])
291
if isinstance(ids, (int, long)):
293
if not name or not date or not amount or not journal_id or not currency_id:
295
# Prepare some values
299
'date': source_date or date,
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,
306
'currency_id': currency_id,
307
'source_date': source_date or False,
308
'commitment_line_id': commitment_line_id or False,
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,})
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
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,
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)
333
215
analytic_distribution()
334
216
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: