##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
from tools import config
from tools.translate import _
+class fiscalyear_seq(osv.osv):
+ _name = "fiscalyear.seq"
+ _description = "Maintains Invoice sequences with Fiscal Year"
+ _rec_name = 'fiscalyear_id'
+ _columns = {
+ 'journal_id': fields.many2one('account.journal', 'Journal'),
+ 'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year',required=True),
+ 'sequence_id':fields.many2one('ir.sequence', 'Sequence',required=True),
+ }
+
+fiscalyear_seq()
+
class account_invoice(osv.osv):
- def _amount_all(self, cr, uid, ids, name, args, context={}):
+ def _amount_all(self, cr, uid, ids, name, args, context=None):
res = {}
for invoice in self.browse(cr,uid,ids, context=context):
res[invoice.id] = {
return res
def _get_journal(self, cr, uid, context):
+ if context is None:
+ context = {}
type_inv = context.get('type', 'out_invoice')
type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale', 'in_refund': 'purchase'}
journal_obj = self.pool.get('account.journal')
else:
return pooler.get_pool(cr.dbname).get('res.currency').search(cr, uid, [('rate','=',1.0)])[0]
- def _get_journal_analytic(self, cr, uid, type_inv, context={}):
+ def _get_journal_analytic(self, cr, uid, type_inv, context=None):
type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale', 'in_refund': 'purchase'}
tt = type2journal.get(type_inv, 'sale')
result = self.pool.get('account.analytic.journal').search(cr, uid, [('type','=',tt)], context=context)
if not result:
- raise osv.except_osv(_('No Analytic Journal !'),("You have to define an analytic journal of type '%s' !") % (tt,))
+ raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal of type '%s' !") % (tt,))
return result[0]
- def _get_type(self, cr, uid, context={}):
+ def _get_type(self, cr, uid, context=None):
+ if context is None:
+ context = {}
type = context.get('type', 'out_invoice')
return type
def _get_reference_type(self, cr, uid, context=None):
return [('none', _('Free Reference'))]
- def _amount_residual(self, cr, uid, ids, name, args, context={}):
+ def _amount_residual(self, cr, uid, ids, name, args, context=None):
res = {}
data_inv = self.browse(cr, uid, ids)
for inv in data_inv:
paid_amt = 0.0
to_pay = inv.amount_total
for lines in inv.move_lines:
- paid_amt = paid_amt + lines.credit
- res[inv.id] = to_pay - paid_amt
+ paid_amt = paid_amt - lines.credit + lines.debit
+ res[inv.id] = to_pay - abs(paid_amt)
return res
def _get_lines(self, cr, uid, ids, name, arg, context=None):
res[id]=[x for x in l if x <> line.id]
return res
- def _get_invoice_line(self, cr, uid, ids, context={}):
+ def _get_invoice_line(self, cr, uid, ids, context=None):
result = {}
for line in self.pool.get('account.invoice.line').browse(cr, uid, ids, context=context):
result[line.invoice_id.id] = True
return result.keys()
- def _get_invoice_tax(self, cr, uid, ids, context={}):
+ def _get_invoice_tax(self, cr, uid, ids, context=None):
result = {}
for tax in self.pool.get('account.invoice.tax').browse(cr, uid, ids, context=context):
result[tax.invoice_id.id] = True
return result.keys()
- def _compute_lines(self, cr, uid, ids, name, args, context={}):
+ def _compute_lines(self, cr, uid, ids, name, args, context=None):
result = {}
for invoice in self.browse(cr, uid, ids, context):
moves = self.move_line_id_payment_get(cr, uid, [invoice.id])
result[invoice.id] = lines
return result
+ def _get_invoice_from_line(self, cr, uid, ids, context={}):
+ move = {}
+ for line in self.pool.get('account.move.line').browse(cr, uid, ids):
+ if line.reconcile_partial_id:
+ for line2 in line.reconcile_partial_id.line_partial_ids:
+ move[line2.move_id.id] = True
+ if line.reconcile_id:
+ for line2 in line.reconcile_id.line_id:
+ move[line2.move_id.id] = True
+ invoice_ids = []
+ if move:
+ invoice_ids = self.pool.get('account.invoice').search(cr, uid, [('move_id','in',move.keys())], context=context)
+ return invoice_ids
+
+ def _get_invoice_from_reconcile(self, cr, uid, ids, context={}):
+ move = {}
+ for r in self.pool.get('account.move.reconcile').browse(cr, uid, ids):
+ for line in r.line_partial_ids:
+ move[line.move_id.id] = True
+ for line in r.line_id:
+ move[line.move_id.id] = True
+ invoice_ids = []
+ if move:
+ invoice_ids = self.pool.get('account.invoice').search(cr, uid, [('move_id','in',move.keys())], context=context)
+ return invoice_ids
+
_name = "account.invoice"
_description = 'Invoice'
_order = "number"
('in_refund','Supplier Refund'),
],'Type', readonly=True, select=True),
- 'number': fields.char('Invoice Number', size=32, readonly=True, help="Uniq number of the invoice, computed automatically when the invoice is created."),
+ 'number': fields.char('Invoice Number', size=32, readonly=True, help="Unique number of the invoice, computed automatically when the invoice is created."),
'reference': fields.char('Invoice Reference', size=64, help="The partner reference of this invoice."),
'reference_type': fields.selection(_get_reference_type, 'Reference Type',
required=True),
- 'comment': fields.text('Additionnal Information'),
+ 'comment': fields.text('Additional Information'),
'state': fields.selection([
('draft','Draft'),
('proforma2','Pro-forma'),
('open','Open'),
('paid','Done'),
- ('cancel','Canceled')
+ ('cancel','Cancelled')
],'State', select=True, readonly=True),
'date_invoice': fields.date('Date Invoiced', states={'open':[('readonly',True)],'close':[('readonly',True)]}),
- 'date_due': fields.date('Due Date', states={'open':[('readonly',True)],'close':[('readonly',True)]}),
-
+ 'date_due': fields.date('Due Date', states={'open':[('readonly',True)],'close':[('readonly',True)]},
+ help="If you use payment terms, the due date will be computed automatically at the generation "\
+ "of accounting entries. If you keep the payment term and the due date empty, it means direct payment."),
'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}),
'address_contact_id': fields.many2one('res.partner.address', 'Contact Address', readonly=True, states={'draft':[('readonly',False)]}),
'address_invoice_id': fields.many2one('res.partner.address', 'Invoice Address', readonly=True, required=True, states={'draft':[('readonly',False)]}),
-
- 'payment_term': fields.many2one('account.payment.term', 'Payment Term',readonly=True, states={'draft':[('readonly',False)]} ),
-
- 'period_id': fields.many2one('account.period', 'Force Period', help="Keep empty to use the period of the validation date."),
+ 'payment_term': fields.many2one('account.payment.term', 'Payment Term',readonly=True, states={'draft':[('readonly',False)]},
+ help="If you use payment terms, the due date will be computed automatically at the generation "\
+ "of accounting entries. If you keep the payment term and the due date empty, it means direct payment. "\
+ "The payment term may compute several due dates: 50% now, 50% in one month."),
+ 'period_id': fields.many2one('account.period', 'Force Period', domain=[('state','<>','done')], help="Keep empty to use the period of the validation date."),
'account_id': fields.many2one('account.account', 'Account', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="The partner account used for this invoice."),
'invoice_line': fields.one2many('account.invoice.line', 'invoice_id', 'Invoice Lines', readonly=True, states={'draft':[('readonly',False)]}),
'company_id': fields.many2one('res.company', 'Company', required=True),
'check_total': fields.float('Total', digits=(16,2), states={'open':[('readonly',True)],'close':[('readonly',True)]}),
'reconciled': fields.function(_reconciled, method=True, string='Paid/Reconciled', type='boolean',
- store=True, help="The account moves of the invoice have been reconciled with account moves of the payment(s)."),
+ store={
+ 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, None, 50),
+ 'account.move.line': (_get_invoice_from_line, None, 50),
+ 'account.move.reconcile': (_get_invoice_from_reconcile, None, 50),
+ }, help="The account moves of the invoice have been reconciled with account moves of the payment(s)."),
'partner_bank': fields.many2one('res.partner.bank', 'Bank Account',
help='The bank account to pay to or to be paid from'),
'move_lines':fields.function(_get_lines , method=True,type='many2many' , relation='account.move.line',string='Move Lines'),
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, None, 50),
'account.invoice.tax': (_get_invoice_tax, None, 50),
'account.invoice.line': (_get_invoice_line, None, 50),
+ 'account.move.line': (_get_invoice_from_line, None, 50),
+ 'account.move.reconcile': (_get_invoice_from_reconcile, None, 50),
},
help="Remaining amount due."),
'payment_ids': fields.function(_compute_lines, method=True, relation='account.move.line', type="many2many", string='Payments'),
'move_name': fields.char('Account Move', size=64),
+ 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position')
}
_defaults = {
'type': _get_type,
'reference_type': lambda *a: 'none',
}
- def unlink(self, cr, uid, ids):
+ def unlink(self, cr, uid, ids, context=None):
invoices = self.read(cr, uid, ids, ['state'])
unlink_ids = []
for t in invoices:
unlink_ids.append(t['id'])
else:
raise osv.except_osv(_('Invalid action !'), _('Cannot delete invoice(s) which are already opened or paid !'))
- osv.osv.unlink(self, cr, uid, unlink_ids)
+ osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
return True
# def get_invoice_address(self, cr, uid, ids):
partner_payment_term = False
acc_id = False
bank_id = False
+ fiscal_position = False
opt = [('uid', str(uid))]
if partner_id:
acc_id = p.property_account_receivable.id
else:
acc_id = p.property_account_payable.id
-
+ fiscal_position = p.property_account_position and p.property_account_position.id or False
partner_payment_term = p.property_payment_term and p.property_payment_term.id or False
if p.bank_ids:
bank_id = p.bank_ids[0].id
'address_invoice_id': invoice_addr_id,
'account_id': acc_id,
'payment_term': partner_payment_term,
+ 'fiscal_position': fiscal_position
}
}
ok = ok and bool(cr.fetchone()[0])
return ok
- def button_reset_taxes(self, cr, uid, ids, context={}):
+ def button_reset_taxes(self, cr, uid, ids, context=None):
ait_obj = self.pool.get('account.invoice.tax')
for id in ids:
cr.execute("DELETE FROM account_invoice_tax WHERE invoice_id=%s", (id,))
for taxe in ait_obj.compute(cr, uid, id).values():
ait_obj.create(cr, uid, taxe)
+ # Update the stored value (fields.function), so we write to trigger recompute
+ self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
+# self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
return True
- def button_compute(self, cr, uid, ids, context={}, set_total=False):
- ait_obj = self.pool.get('account.invoice.tax')
- cur_obj = self.pool.get('res.currency')
+ def button_compute(self, cr, uid, ids, context=None, set_total=False):
+ self.button_reset_taxes(cr, uid, ids, context)
for inv in self.browse(cr, uid, ids):
- company_currency = inv.company_id.currency_id.id
- compute_taxes = ait_obj.compute(cr, uid, inv.id)
- if not inv.tax_line:
- for tax in compute_taxes.values():
- ait_obj.create(cr, uid, tax)
- else:
- tax_key = []
- for tax in inv.tax_line:
- if tax.manual:
- continue
- key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id)
- tax_key.append(key)
- if not key in compute_taxes:
- ait_obj.unlink(cr, uid, [tax.id])
- continue
- compute_taxes[key]['base'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, compute_taxes[key]['base'], context={'date': inv.date_invoice})
- if abs(compute_taxes[key]['base'] - tax.base) > inv.company_id.currency_id.rounding:
- ait_obj.write(cr, uid, [tax.id], compute_taxes[key])
- for key in compute_taxes:
- if not key in tax_key:
- ait_obj.create(cr, uid, compute_taxes[key])
if set_total:
self.pool.get('account.invoice').write(cr, uid, [inv.id], {'check_total': inv.amount_total})
return True
def action_move_create(self, cr, uid, ids, *args):
ait_obj = self.pool.get('account.invoice.tax')
cur_obj = self.pool.get('res.currency')
- acc_obj = self.pool.get('account.account')
+
for inv in self.browse(cr, uid, ids):
if inv.move_id:
continue
- self.button_compute(cr, uid, ids, context={},set_total=True)
- if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0):
- raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.'))
+
if not inv.date_invoice:
self.write(cr, uid, [inv.id], {'date_invoice':time.strftime('%Y-%m-%d')})
company_currency = inv.company_id.currency_id.id
if not key in tax_key:
raise osv.except_osv(_('Warning !'), _('Taxes missing !'))
+ if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0):
+ raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.'))
+
# one move line per tax line
iml += ait_obj.move_line_get(cr, uid, inv.id)
# create one move line for the total and possibly adjust the other lines amount
total = 0
total_currency = 0
- key_line=[]
for i in iml:
- if i.has_key('account_id') and i.has_key('taxes'):
- if not (i['account_id'],i['taxes']) in key_line:
- key_line.append((i['account_id'],i['taxes']))
if inv.currency_id.id != company_currency:
i['currency_id'] = inv.currency_id.id
i['amount_currency'] = i['price']
acc_id = inv.account_id.id
name = inv['name'] or '/'
- iml_temp=[]
- move_list=[]
-
- for item in key_line:
- move_temp={}
- if acc_obj.browse(cr,uid,item[0]).merge_invoice:
- repeat=False
- for move_line in iml:
- if (move_line.has_key('account_id') and move_line['account_id']==item[0]) and (move_line.has_key('taxes') and move_line['taxes']==item[1]):
- move_list.append(move_line)
- if repeat:
- for key in move_line:
- if key in ['name','amount_currency','price_unit','price','quantity']:
- if key=='name':
- move_temp[key]=move_temp[key] + "," +move_line[key]
- else:
- move_temp[key] +=move_line[key]
- else:
- for key in move_line:
- move_temp[key]=move_line[key]
- repeat=True
- if move_temp:
- iml_temp.append(move_temp)
-
- if len(iml_temp)<len(move_list):
- for old_elem in move_list:
- iml.remove(old_elem)
- for new_elem in iml_temp:
- iml.append(new_elem)
-
totlines = False
if inv.payment_term:
totlines = self.pool.get('account.payment.term').compute(cr,
date = inv.date_invoice or time.strftime('%Y-%m-%d')
part = inv.partner_id.id
+
line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part, date, context={})) ,iml)
+ if inv.journal_id.group_invoice_lines:
+ line2 = {}
+ for x, y, l in line:
+ tmp = str(l['account_id'])
+ tmp += '-'+str('tax_code_id' in l and l['tax_code_id'] or "False")
+ tmp += '-'+str('product_id' in l and l['product_id'] or "False")
+ tmp += '-'+str('analytic_account_id' in l and l['analytic_account_id'] or "False")
+
+ if tmp in line2:
+ am = line2[tmp]['debit'] - line2[tmp]['credit'] + (l['debit'] - l['credit'])
+ line2[tmp]['debit'] = (am > 0) and am or 0.0
+ line2[tmp]['credit'] = (am < 0) and -am or 0.0
+ line2[tmp]['tax_amount'] += l['tax_amount']
+ line2[tmp]['analytic_lines'] += l['analytic_lines']
+ else:
+ line2[tmp] = l
+ line = []
+ for key, val in line2.items():
+ line.append((0,0,val))
+
journal_id = inv.journal_id.id #self._get_journal(cr, uid, {'type': inv['type']})
journal = self.pool.get('account.journal').browse(cr, uid, journal_id)
- if journal.sequence_id and not inv.move_name:
- name = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id)
- else:
- name = inv.move_name
if journal.centralisation:
raise osv.except_osv(_('UserError'),
- _('Can not create invoice move on centralized journal'))
-
- move = {'name': name, 'line_id': line, 'journal_id': journal_id}
+ _('Can not create invoice move on centralised journal'))
+ move = {'ref': inv.number, 'line_id': line, 'journal_id': journal_id, 'date': date}
period_id=inv.period_id and inv.period_id.id or False
if not period_id:
period_ids= self.pool.get('account.period').search(cr,uid,[('date_start','<=',inv.date_invoice or time.strftime('%Y-%m-%d')),('date_stop','>=',inv.date_invoice or time.strftime('%Y-%m-%d'))])
move['period_id'] = period_id
for i in line:
i[2]['period_id'] = period_id
+
move_id = self.pool.get('account.move').create(cr, uid, move)
new_move_name = self.pool.get('account.move').browse(cr, uid, move_id).name
# make the invoice point to that move
self._log_event(cr, uid, ids)
return True
- def line_get_convert(self, cr, uid, x, part, date, context={}):
+ def line_get_convert(self, cr, uid, x, part, date, context=None):
return {
- 'date':date,
'date_maturity': x.get('date_maturity', False),
'partner_id':part,
'name':x['name'][:64],
cr.execute('SELECT id, type, number, move_id, reference ' \
'FROM account_invoice ' \
'WHERE id IN ('+','.join(map(str,ids))+')')
+ obj_inv = self.browse(cr, uid, ids)[0]
for (id, invtype, number, move_id, reference) in cr.fetchall():
if not number:
- number = self.pool.get('ir.sequence').get(cr, uid,
- 'account.invoice.' + invtype)
+ if obj_inv.journal_id.invoice_sequence_id:
+ sid = obj_inv.journal_id.invoice_sequence_id.id
+ number = self.pool.get('ir.sequence').get_id(cr, uid, sid, 'id=%s', {'fiscalyear_id': obj_inv.period_id.fiscalyear_id.id})
+ else:
+ number = self.pool.get('ir.sequence').get(cr, uid,
+ 'account.invoice.' + invtype)
if invtype in ('in_invoice', 'in_refund'):
ref = reference
else:
ref = self._convert_ref(cr, uid, number)
cr.execute('UPDATE account_invoice SET number=%s ' \
'WHERE id=%s', (number, id))
+ cr.execute('UPDATE account_move SET ref=%s ' \
+ 'WHERE id=%s AND (ref is null OR ref = \'\')',
+ (ref, move_id))
cr.execute('UPDATE account_move_line SET ref=%s ' \
'WHERE move_id=%s AND (ref is null OR ref = \'\')',
(ref, move_id))
self.pool.get('res.partner.event').create(cr, uid, {'name':'Invoice: '+name, 'som':False, 'description':name+' '+str(inv['id']), 'document':name, 'partner_id':part, 'date':time.strftime('%Y-%m-%d %H:%M:%S'), 'canal_id':False, 'user_id':uid, 'partner_type':partnertype, 'probability':1.0, 'planned_revenue':pr, 'planned_cost':pc, 'type':eventtype})
return len(invs)
- def name_get(self, cr, uid, ids, context={}):
+ def name_get(self, cr, uid, ids, context=None):
if not len(ids):
return []
types = {
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
if not args:
args=[]
- if not context:
+ if context is None:
context={}
ids = []
if name:
new_ids.append(self.create(cr, uid, invoice))
return new_ids
- def pay_and_reconcile(self, cr, uid, ids, pay_amount, pay_account_id, period_id, pay_journal_id, writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context={}, name=''):
+ def pay_and_reconcile(self, cr, uid, ids, pay_amount, pay_account_id, period_id, pay_journal_id, writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context=None, name=''):
+ if context is None:
+ context = {}
#TODO check if we can use different period for payment and the writeoff line
assert len(ids)==1, "Can only pay one invoice at a time"
invoice = self.browse(cr, uid, ids[0])
src_account_id = invoice.account_id.id
- journal = self.pool.get('account.journal').browse(cr, uid, pay_journal_id)
- if journal.sequence_id:
- name = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id)
- else:
- raise osv.except_osv(_('No piece number !'), _('Can not create an automatic sequence for this piece !\n\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
# Take the seq as name for move
- if journal.sequence_id:
- seq = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id)
- else:
- raise osv.except_osv('No piece number !', 'Can not create an automatic sequence for this piece !\n\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.')
types = {'out_invoice': -1, 'in_invoice': 1, 'out_refund': 1, 'in_refund': -1}
direction = types[invoice.type]
#take the choosen date
- if context.has_key('date_p') and context['date_p']:
+ if 'date_p' in context and context['date_p']:
date=context['date_p']
else:
date=time.strftime('%Y-%m-%d')
l1 = {
- 'name': name,
'debit': direction * pay_amount>0 and direction * pay_amount,
'credit': direction * pay_amount<0 and - direction * pay_amount,
'account_id': src_account_id,
'partner_id': invoice.partner_id.id,
- 'date': date,
'ref':invoice.number,
}
l2 = {
- 'name':name,
'debit': direction * pay_amount<0 and - direction * pay_amount,
'credit': direction * pay_amount>0 and direction * pay_amount,
'account_id': pay_account_id,
'partner_id': invoice.partner_id.id,
- 'date': date,
'ref':invoice.number,
}
+ if not name:
+ name = invoice.invoice_line and invoice.invoice_line[0].name or invoice.number
+ l1['name'] = name
+ l2['name'] = name
+
lines = [(0, 0, l1), (0, 0, l2)]
- move = {'name': seq, 'line_id': lines, 'journal_id': pay_journal_id, 'period_id': period_id}
+ move = {'ref': invoice.number, 'line_id': lines, 'journal_id': pay_journal_id, 'period_id': period_id, 'date': date}
move_id = self.pool.get('account.move').create(cr, uid, move)
line_ids = []
line = self.pool.get('account.move.line')
cr.execute('select id from account_move_line where move_id in ('+str(move_id)+','+str(invoice.move_id.id)+')')
lines = line.browse(cr, uid, map(lambda x: x[0], cr.fetchall()) )
- for l in lines:
+ for l in lines+invoice.payment_ids:
if l.account_id.id==src_account_id:
line_ids.append(l.id)
total += (l.debit or 0.0) - (l.credit or 0.0)
self.pool.get('account.move.line').reconcile(cr, uid, line_ids, 'manual', writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context)
else:
self.pool.get('account.move.line').reconcile_partial(cr, uid, line_ids, 'manual', context)
+
+ # Update the stored value (fields.function), so we write to trigger recompute
+ self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context)
return True
account_invoice()
res[line.id] = round(line.price_unit * line.quantity * (1-(line.discount or 0.0)/100.0),2)
return res
- def _price_unit_default(self, cr, uid, context={}):
+ def _price_unit_default(self, cr, uid, context=None):
+ if context is None:
+ context = {}
if 'check_total' in context:
t = context['check_total']
for l in context.get('invoice_line', {}):
'price_unit': _price_unit_default,
}
- def product_id_change_unit_price_inv(self, cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context={}):
+ def product_id_change_unit_price_inv(self, cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context=None):
tax_obj = self.pool.get('account.tax')
if price_unit:
taxes = tax_obj.browse(cr, uid, tax_id)
price_unit = price_unit - tax['amount']
return {'price_unit': price_unit,'invoice_line_tax_id': tax_id}
- def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, price_unit=False, address_invoice_id=False, context={}):
+ def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, address_invoice_id=False, context=None):
+ if context is None:
+ context = {}
if not partner_id:
raise osv.except_osv(_('No Partner Defined !'),_("You must first select a partner !") )
if not product:
else:
return {'value': {'price_unit': 0.0}, 'domain':{'product_uom':[]}}
part = self.pool.get('res.partner').browse(cr, uid, partner_id)
+ fpos = fposition_id and self.pool.get('account.fiscal.position').browse(cr, uid, fposition_id) or False
+
lang=part.lang
context.update({'lang': lang})
+ result = {}
res = self.pool.get('product.product').browse(cr, uid, product, context=context)
- taxep=None
- tax_obj = self.pool.get('account.tax')
- if type in ('out_invoice', 'out_refund'):
- tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, part, res.taxes_id)
- else:
- tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, part, res.supplier_taxes_id)
- if type in ('in_invoice', 'in_refund'):
- result = self.product_id_change_unit_price_inv(cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context=context)
- else:
- result = {'price_unit': res.list_price, 'invoice_line_tax_id': tax_id}
-
- if not name:
- result['name'] = res.name
if type in ('out_invoice','out_refund'):
a = res.product_tmpl_id.property_account_income.id
if not a:
a = res.categ_id.property_account_expense_categ.id
- a = self.pool.get('account.fiscal.position').map_account(cr, uid, part, a)
+ a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, a)
if a:
result['account_id'] = a
+ taxep=None
+ tax_obj = self.pool.get('account.tax')
+ if type in ('out_invoice', 'out_refund'):
+ taxes = res.taxes_id and res.taxes_id or (a and self.pool.get('account.account').browse(cr, uid,a).tax_ids or False)
+ tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
+ else:
+ taxes = res.supplier_taxes_id and res.supplier_taxes_id or (a and self.pool.get('account.account').browse(cr, uid,a).tax_ids or False)
+ tax_id = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
+ if type in ('in_invoice', 'in_refund'):
+ to_update = self.product_id_change_unit_price_inv(cr, uid, tax_id, price_unit, qty, address_invoice_id, product, partner_id, context=context)
+ result.update(to_update)
+ else:
+ result.update({'price_unit': res.list_price, 'invoice_line_tax_id': tax_id})
+
+ if not name:
+ result['name'] = res.name
+
domain = {}
result['uos_id'] = uom or res.uom_id.id or False
if result['uos_id']:
domain = {'uos_id':[('category_id','=',res2 )]}
return {'value':result, 'domain':domain}
- def move_line_get(self, cr, uid, invoice_id, context={}):
+ def move_line_get(self, cr, uid, invoice_id, context=None):
res = []
tax_grouped = {}
tax_obj = self.pool.get('account.tax')
res[-1]['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, tax_amount, context={'date': inv.date_invoice})
return res
- def move_line_get_item(self, cr, uid, line, context={}):
+ def move_line_get_item(self, cr, uid, line, context=None):
return {
'type':'src',
'name': line.name[:64],
'taxes':line.invoice_line_tax_id,
}
#
- # Set the tax field according to the account and the partner
+ # Set the tax field according to the account and the fiscal position
#
- def onchange_account_id(self, cr, uid, ids, partner_id,account_id):
- if not (partner_id and account_id):
+ def onchange_account_id(self, cr, uid, ids, fposition_id, account_id):
+ if not account_id:
return {}
taxes = self.pool.get('account.account').browse(cr, uid, account_id).tax_ids
- part = self.pool.get('res.partner').browse(cr, uid, partner_id)
-
- res = self.pool.get('account.fiscal.position').map_tax(cr, uid, part, taxes)
+ fpos = fposition_id and self.pool.get('account.fiscal.position').browse(cr, uid, fposition_id) or False
+ res = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes)
r = {'value':{'invoice_line_tax_id': res}}
return r
account_invoice_line()