1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# ShineERP, Enterprise Management Solution
5
# Copyright (C) 2007-2012 ShineERP Co.,ltd (<http://www.erp.mn>). All Rights Reserved
7
# Address : Suhkbaatar District, National ITPark, ShineERP LLC
9
# Phone : 976 + 11-318043
11
##############################################################################
13
from osv import fields, osv
14
from tools.translate import _
15
from lxml import etree
16
import decimal_precision as dp
19
class purchase_import_expenses_option(osv.osv_memory):
20
_name = 'purchase.import.expenses.option'
21
_description = "Purchase Add Expenses Option"
24
'option': fields.selection([('exists','Import from existing invoice'),('create','Create and import new expense')],
25
'Option', required=True)
32
def next(self, cr, uid, ids, context={}):
33
data = self.read(cr, uid, ids[0], context=context)
34
if data['option'] == 'create':
36
'name': _('Add Expenses'),
39
'res_model': 'purchase.import.expenses',
40
'type': 'ir.actions.act_window',
46
'name': _('Add Expenses'),
49
'res_model': 'purchase.import.expenses.from.invoice',
50
'type': 'ir.actions.act_window',
55
purchase_import_expenses_option()
57
class purchase_import_expenses(osv.osv_memory):
58
_name = "purchase.import.expenses"
59
_description = "Purchase Add Expenses"
64
('price','Unit Price'),
65
('subtotal','SubTotal')
69
'name': fields.char('Description', size=256),
70
'product_id': fields.many2one('product.product', 'Expense', domain=[('type','=','service')],
71
help="Select a service product to include extra costs for this purchase order."),
72
'purchase_lines': fields.many2many('purchase.order.line', 'purchase_lines_import_rel', 'wiz_id', 'line_id', 'To be included lines'),
73
'portion_method': fields.selection(PORTION_SELECTION, 'Portion Method', required=True),
74
'taxes_id': fields.many2many('account.tax', 'purchase_order_import_taxe', 'line_id', 'tax_id', 'Taxes'),
75
'amount': fields.float('Expense Amount', digits_compute=dp.get_precision('Purchase Price'), required=True),
76
'currency_id': fields.many2one('res.currency', 'Currency'),
77
'account_analytic_id':fields.many2one('account.analytic.account', 'Analytic Account'),
78
'expense_partner_id': fields.many2one('res.partner', 'Associated Partner', help="This expense will be invoiced from selected partner."),
79
'not_included': fields.boolean('This expense is VAT'),
80
'date_planned': fields.date('Scheduled Date'),
81
'notes': fields.text('Note')
84
def product_id_change(self, cr, uid, ids, product, context={}):
86
return {'value': {'taxes_id': []}}
87
prod = self.pool.get('product.product').browse(cr, uid, product)
89
taxes_id = map(lambda x: x.id, prod.supplier_taxes_id)
90
if context.get('active_id', False) and len(taxes_id) > 0 :
91
order = self.pool.get('purchase.order').browse(cr, uid, context['active_id'])
92
taxes = self.pool.get('account.tax').browse(cr, uid, taxes_id)
93
if order.fiscal_position :
94
taxes_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, order.fiscal_position, taxes)
96
prod_name = self.pool.get('product.product').name_get(cr, uid, [prod.id])[0][1]
104
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
105
res = super(purchase_import_expenses, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
108
if context.get('active_model', 'ir.ui.menu') == self._name:
109
doc = etree.XML(res['arch'])
110
nodes = doc.xpath("//field[@name='purchase_lines']")
112
node.set('domain', "[('order_id','=',%s),('is_extra_expense','=',False)]" % context['active_id'])
113
res['arch'] = etree.tostring(doc)
114
order = self.pool.get('purchase.order').browse(cr, uid, context['active_id'], context=context)
115
selection = [(order.company_id.currency_id.id, order.company_id.currency_id.name)]
116
if order.pricelist_id.currency_id.id <> order.company_id.currency_id.id:
117
selection.append( (order.pricelist_id.currency_id.id, order.pricelist_id.currency_id.name) )
118
res['fields']['currency_id']['selection'] = selection
122
def _get_currency(self, cr, uid, context={}):
123
if context.get('active_id', False) :
124
order = self.pool.get('purchase.order').browse(cr, uid, context['active_id'])
125
return order.company_id.currency_id.id
126
raise osv.except_osv('BUG!', u'active_id context-оор орж ирэхгүй байна.')
128
def _get_date_planned(self, cr, uid, context={}):
129
if context.get('active_id', False) :
130
order = self.pool.get('purchase.order').browse(cr, uid, context['active_id'])
131
return order.date_order or time.strftime('%Y-%m-%d')
134
'portion_method': 'subtotal',
135
'currency_id': _get_currency,
136
'not_included': False,
137
'date_planned': _get_date_planned
140
def make_portion(self, cr, uid, method, lines, amount, context={}):
143
if method == 'price' :
145
total += line.price_unit
148
coff = amount / total
150
portion_dict[line.id] = (line.price_unit * coff) / line.product_qty
151
elif method == 'subtotal' :
153
total += line.price_unit * line.product_qty
156
coff = amount / total
158
portion_dict[line.id] = line.price_unit * coff
159
elif method == 'volume' :
161
total += (line.product_id.volume or 1) * line.product_qty
164
coff = amount / total
166
portion_dict[line.id] = (line.product_id.volume or 1) * coff
167
elif method == 'weight' :
169
total += (line.product_id.weight_net or 1) * line.product_qty
172
coff = amount / total
174
portion_dict[line.id] = (line.product_id.weight_net or 1) * coff
180
def make_expenses(self, cr, uid, ids, context={}):
181
purchase_obj = self.pool.get('purchase.order')
182
purchase_line_obj = self.pool.get('purchase.order.line')
183
purchase_line_exp_obj = self.pool.get('purchase.order.line.expenses')
184
currency_obj = self.pool.get('res.currency')
186
order = purchase_obj.browse(cr, uid, context['active_id'])
187
form = self.browse(cr, uid, ids[0])
189
selected_lines = form.purchase_lines
190
if not selected_lines :
191
selected_lines = [line for line in order.order_line if not line.is_extra_expense]
192
portion_dict = self.make_portion(cr, uid, form.portion_method, selected_lines, form.amount, context=context)
195
for line in order.order_line:
196
line_state = line.state
199
new_line_id = purchase_line_obj.create(cr, uid, {'order_id' : order.id,
201
'product_id': form.product_id.id,
202
'product_uom': form.product_id.uom_id.id,
204
'account_analytic_id':form.account_analytic_id.id,
205
'price_unit': form.amount,
206
'base_price': form.amount,
207
'taxes_id': [(6, 0, map(lambda x: x.id, form.taxes_id))],
208
'date_planned': form.date_planned,
209
'is_extra_expense': True,
210
'portion_method': form.portion_method,
211
'expense_partner_id': form.expense_partner_id.id,
212
'not_included': form.not_included,
213
'expense_currency_id': form.currency_id.id,
217
purchase_obj.write(cr, uid, order.id, {'partner_id':1}, context=context)
218
for line in selected_lines :
219
purchase_line_exp_obj.create(cr, uid, {
220
'base_line' : new_line_id,
221
'target_line': line.id,
222
'amount': portion_dict[line.id]
225
return {'type': 'ir.actions.act_window_close'}
227
purchase_import_expenses()
229
class purchase_import_expenses_from_invoice(osv.osv_memory):
230
_inherit = 'purchase.import.expenses'
231
_name = 'purchase.import.expenses.from.invoice'
234
'invoice_id': fields.many2one('account.invoice', 'Invoice', required=True),
235
'company_id': fields.many2one('res.company', 'Company', required=True)
238
def _get_company(self, cr, uid, context={}):
239
if context.get('active_id', False) :
240
order = self.pool.get('purchase.order').browse(cr, uid, context['active_id'])
241
return order.company_id.id
244
'company_id': _get_company
247
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
248
res = super(purchase_import_expenses_from_invoice, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
251
if context and context['active_model'] <> 'ir.ui.menu':
252
doc = etree.XML(res['arch'])
253
nodes = doc.xpath("//field[@name='purchase_lines']")
255
node.set('domain', "[('order_id','=',%s),('is_extra_expense','=',False)]" % context['active_id'])
256
res['arch'] = etree.tostring(doc)
258
order = self.pool.get('purchase.order').browse(cr, uid, context['active_id'], context=context)
259
selection = [(order.company_id.currency_id.id, order.company_id.currency_id.name)]
260
if order.pricelist_id.currency_id.id <> order.company_id.currency_id.id:
261
selection.append( (order.pricelist_id.currency_id.id, order.pricelist_id.currency_id.name) )
262
res['fields']['currency_id']['selection'] = selection
266
def invoice_id_change(self, cr, uid, ids, invoice, company, context={}):
268
return {'value': {'amount':0,'currency_id':False}}
269
currency_obj = self.pool.get('res.currency')
270
invoice = self.pool.get('account.invoice').browse(cr, uid, invoice, context=context)
271
name = (len(invoice.invoice_line) > 0 and invoice.invoice_line[0].name) or False
272
currency_id = invoice.currency_id.id
273
company = self.pool.get('res.company').browse(cr, uid, company, context=context)
274
if company.currency_id.id <> currency_id:
275
invoice.amount_total = currency_obj.compute(cr, uid, currency_id,
276
company.currency_id.id, invoice.amount_total, context={'date':invoice.date_invoice})
277
currency_id = company.currency_id.id
278
self.pool.get('account.invoice').write(cr, uid, [invoice.id], {'is_extra_expense':True})
280
'amount': invoice.amount_total,
281
'currency_id': currency_id,
282
'date_planned': invoice.date_invoice,
284
'expense_partner_id': False,
288
def make_expenses(self, cr, uid, ids, context={}):
289
purchase_obj = self.pool.get('purchase.order')
290
purchase_line_obj = self.pool.get('purchase.order.line')
291
purchase_line_exp_obj = self.pool.get('purchase.order.line.expenses')
292
currency_obj = self.pool.get('res.currency')
294
order = purchase_obj.browse(cr, uid, context['active_id'])
295
form = self.browse(cr, uid, ids[0])
297
selected_lines = form.purchase_lines
298
if not selected_lines :
299
selected_lines = [line for line in order.order_line if not line.is_extra_expense]
301
for inv in order.invoice_ids:
302
if inv.id == form.invoice_id.id :
303
raise osv.except_osv(_('Warning!'), _('This invioce already related in this purchase order!'))
304
amount = form.invoice_id.amount_total
305
if order.company_id.currency_id.id <> form.invoice_id.currency_id.id:
306
amount = currency_obj.compute(cr, uid, form.invoice_id.currency_id.id,
307
order.company_id.currency_id.id, amount, context={'date':form.invoice_id.date_invoice})
308
date_planned = form.invoice_id.date_invoice
309
currency_id = order.company_id.currency_id.id
312
for l in form.invoice_id.invoice_line:
314
product_id = l.product_id.id
316
partner_id = form.invoice_id.partner_id.id
318
portion_dict = self.make_portion(cr, uid, form.portion_method, selected_lines, amount, context=context)
323
uom = self.pool.get('product.product').read(cr, uid, product_id, ['uom_id'])['uom_id'][0]
325
'order_id' : order.id,
327
'product_id': product_id,
330
'price_unit': amount,
331
'base_price': amount,
332
'date_planned': date_planned,
333
'is_extra_expense': True,
334
'portion_method': form.portion_method,
335
'expense_partner_id': partner_id,
336
'not_included': form.not_included,
337
'expense_currency_id': currency_id
340
expense_val['invoice_lines'] = [(6,0,map(lambda x:x.id, form.invoice_id.invoice_line))]
341
expense_val['invoiced'] = True
342
purchase_obj.write(cr, uid, order.id, {'invoice_ids': [(4, form.invoice_id.id)]}, context=context)
345
for line in order.order_line:
346
line_state = line.state
348
expense_val['state'] = line_state
349
new_line_id = purchase_line_obj.create(cr, uid, expense_val, context=context)
351
for line in selected_lines :
352
purchase_line_exp_obj.create(cr, uid, {
353
'base_line' : new_line_id,
354
'target_line': line.id,
355
'amount': portion_dict[line.id]
358
return {'type': 'ir.actions.act_window_close'}
360
def create(self, cr, uid, vals, context=None):
362
if 'amount' not in vals:
363
invoice = self.pool.get('account.invoice').browse(cr, uid, vals['invoice_id'], context=context)
364
vals.update({'amount': invoice.amount_total})
365
return super(purchase_import_expenses_from_invoice, self).create(cr, uid, vals, context=context)
368
purchase_import_expenses_from_invoice()
370
class purchase_remove_expenses(osv.TransientModel):
371
_name = 'purchase.remove.expenses'
372
_description = 'Remove Expenses'
375
'extra_expense_ids': fields.many2many('purchase.order.line','wizard_extra_expense_rel', 'wizard_id','expense_id', 'Extra Expense'),
378
def default_get(self, cr, uid, fields, context=None):
382
res = super(purchase_remove_expenses, self).default_get(cr, uid, fields, context=context)
383
if context.get('active_model',False) == 'purchase.order':
384
record_id = context and context.get('active_id', False) or False
385
purchase_obj = self.pool.get('purchase.order')
386
order = purchase_obj.browse(cr, uid, record_id, context=context)
388
for line in order.order_line:
389
if not line.is_extra_expense or line.invoiced:
391
extra_ids.append(line.id)
393
res['extra_expense_ids'] = extra_ids
396
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
397
context=None, toolbar=False, submenu=False):
398
res = super(purchase_remove_expenses, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
401
if context.get('active_model',False):
402
active_model = context.get('active_model')
403
if active_model != 'purchase.order':
406
record_id = context and context.get('active_id', False)
407
purchase_obj = self.pool.get('purchase.order')
408
order = purchase_obj.browse(cr, uid, record_id, context=context)
411
for line in order.order_line:
412
if line.is_extra_expense:
413
extra_ids.append(line.id)
415
domain = "[('id','in',("+','.join(map(str,extra_ids))+"))]"
417
domain = "[('id','in',False)]"
418
doc = etree.XML(res['arch'])
419
nodes = doc.xpath("//field[@name='extra_expense_ids']")
421
node.set('domain', domain)
422
res['arch'] = etree.tostring(doc)
425
def remove_expenses(self, cr, uid, ids, context=None):
428
if context.get('active_id',False):
429
record_id = context and context.get('active_id', False)
430
purchase_obj = self.pool.get('purchase.order')
431
purchase_line_obj = self.pool.get('purchase.order.line')
432
order = purchase_obj.browse(cr, uid, record_id, context=context)
433
st = self.browse(cr, uid, ids[0], context=context)
436
for ex in st.extra_expense_ids:
438
todo_remove = purchase_line_obj.search(cr, uid, [('order_id','=',order.id),('is_extra_expense','=',True),('id','<>',ex_ids)])
440
purchase_line_obj.unlink(cr, uid, todo_remove, context=context)
442
return {'type': 'ir.actions.act_window_close'}
444
purchase_remove_expenses()