import openerp.addons.decimal_precision as dp
import openerp.exceptions
-from openerp import netsvc
+from openerp import netsvc, SUPERUSER_ID
from openerp import pooler
from openerp.osv import fields, osv, orm
+from openerp.tools import float_compare
from openerp.tools.translate import _
class account_invoice(osv.osv):
company_id = context.get('company_id', user.company_id.id)
type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale_refund', 'in_refund': 'purchase_refund'}
journal_obj = self.pool.get('account.journal')
- res = journal_obj.search(cr, uid, [('type', '=', type2journal.get(type_inv, 'sale')),
- ('company_id', '=', company_id)],
- limit=1)
+ domain = [('company_id', '=', company_id)]
+ if isinstance(type_inv, list):
+ domain.append(('type', 'in', [type2journal.get(type) for type in type_inv if type2journal.get(type)]))
+ else:
+ domain.append(('type', '=', type2journal.get(type_inv, 'sale')))
+ res = journal_obj.search(cr, uid, domain, limit=1)
return res and res[0] or False
def _get_currency(self, cr, uid, context=None):
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 must define an analytic journal of type '%s'!") % (tt,))
+ raise osv.except_osv(_('No Analytic Journal!'),_("You must define an analytic journal of type '%s'!") % (tt,))
return result[0]
def _get_type(self, cr, uid, context=None):
ctx = context.copy()
result = {}
currency_obj = self.pool.get('res.currency')
- for invoice in self.browse(cr, uid, ids, context=context):
+ for invoice in self.browse(cr, SUPERUSER_ID, ids, context=context):
nb_inv_in_partial_rec = max_invoice_id = 0
result[invoice.id] = 0.0
if invoice.move_id:
#we check if the invoice is partially reconciled and if there are other invoices
#involved in this partial reconciliation (and we sum these invoices)
for line in aml.reconcile_partial_id.line_partial_ids:
- if line.invoice:
+ if line.invoice and invoice.type == line.invoice.type:
nb_inv_in_partial_rec += 1
#store the max invoice id as for this invoice we will make a balance instead of a simple division
max_invoice_id = max(max_invoice_id, line.invoice.id)
lines = []
if invoice.move_id:
for m in invoice.move_id.line_id:
+ if m.account_id != invoice.account_id:
+ continue
temp_lines = []
if m.reconcile_id:
temp_lines = map(lambda x: x.id, m.reconcile_id.line_id)
},
multi='all'),
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}, track_visibility='always'),
- 'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
+ 'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]},
+ domain="[('type', 'in', {'out_invoice': ['sale'], 'out_refund': ['sale_refund'], 'in_refund': ['purchase_refund'], 'in_invoice': ['purchase']}.get(type, [])), ('company_id', '=', company_id)]"),
'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
'check_total': fields.float('Verification Total', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
'reconciled': fields.function(_reconciled, string='Paid/Reconciled', type='boolean',
'account.move.reconcile': (_get_invoice_from_reconcile, None, 50),
},
help="Remaining amount due."),
- 'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'),
+ 'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments', groups='base.group_user'),
'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, track_visibility='onchange', states={'draft':[('readonly',False)]}),
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]})
if context.get('active_model', '') in ['res.partner'] and context.get('active_ids', False) and context['active_ids']:
partner = self.pool.get(context['active_model']).read(cr, uid, context['active_ids'], ['supplier','customer'])[0]
if not view_type:
- view_id = self.pool.get('ir.ui.view').search(cr, uid, [('name', '=', 'account.invoice.tree')])
+ try:
+ view_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'account', 'invoice_tree')[1]
+ except ValueError:
+ view_id = self.pool.get('ir.ui.view').search(cr, uid, [('name', '=', 'account.invoice.tree')], limit=1)
view_type = 'tree'
if view_type == 'form':
if partner['supplier'] and not partner['customer']:
- view_id = self.pool.get('ir.ui.view').search(cr,uid,[('name', '=', 'account.invoice.supplier.form')])
+ try:
+ view_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'account', 'invoice_supplier_form')[1]
+ except ValueError:
+ view_id = self.pool.get('ir.ui.view').search(cr,uid,[('name', '=', 'account.invoice.supplier.form')], limit=1)
elif partner['customer'] and not partner['supplier']:
- view_id = self.pool.get('ir.ui.view').search(cr,uid,[('name', '=', 'account.invoice.form')])
+ try:
+ view_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'account', 'invoice_form')[1]
+ except ValueError:
+ view_id = self.pool.get('ir.ui.view').search(cr,uid,[('name', '=', 'account.invoice.form')], limit=1)
if view_id and isinstance(view_id, (list, tuple)):
view_id = view_id[0]
res = super(account_invoice,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
def onchange_payment_term_date_invoice(self, cr, uid, ids, payment_term_id, date_invoice):
res = {}
- if isinstance(ids, int):
+ if isinstance(ids, (int, long)):
ids = [ids]
if not date_invoice:
- date_invoice = time.strftime('%Y-%m-%d')
- for invoice_record in self.browse(cr, uid, ids):
- if not payment_term_id:
- if invoice_record.date_due:
- return {'value':{'date_due': invoice_record.date_due}} #To make sure the invoice due date should contain due date which is entered by user when there is no payment term defined
- else:
- return {'value':{'date_due': date_invoice}} #To make sure that the invoice due date contain current date when there is no payment term and no due date defined
- else:
- if not invoice_record.date_due:
- return {'value':{'date_due': invoice_record.date_due}} #To make sure the invoice due date should contain due date which is entered by user when there is no payment term defined
- else:
- pterm_list = self.pool.get('account.payment.term').compute(cr, uid, payment_term_id, value=1, date_ref=date_invoice)
- if pterm_list:
- pterm_list = [line[0] for line in pterm_list]
- pterm_list.sort()
- res = {'value':{'date_due': pterm_list[-1]}}
- else:
- raise osv.except_osv(_('Insufficient Data!'), _('The payment term of supplier does not have a payment term line.'))
+ date_invoice = fields.date.context_today(self, cr, uid)
+ if not payment_term_id:
+ inv = self.browse(cr, uid, ids[0])
+ #To make sure the invoice due date should contain due date which is entered by user when there is no payment term defined
+ return {'value':{'date_due': inv.date_due and inv.date_due or date_invoice}}
+ pterm_list = self.pool.get('account.payment.term').compute(cr, uid, payment_term_id, value=1, date_ref=date_invoice)
+ if pterm_list:
+ pterm_list = [line[0] for line in pterm_list]
+ pterm_list.sort()
+ res = {'value':{'date_due': pterm_list[-1]}}
+ else:
+ raise osv.except_osv(_('Insufficient Data!'), _('The payment term of supplier does not have a payment term line.'))
return res
def onchange_invoice_line(self, cr, uid, ids, lines):
return {'value': {}}
def onchange_company_id(self, cr, uid, ids, company_id, part_id, type, invoice_line, currency_id):
+ #TODO: add the missing context parameter when forward-porting in trunk so we can remove
+ # this hack!
+ context = self.pool['res.users'].context_get(cr, uid)
+
val = {}
dom = {}
obj_journal = self.pool.get('account.journal')
obj_l = account_obj.browse(cr, uid, inv_line[2]['account_id'])
if obj_l.company_id.id != company_id:
raise osv.except_osv(_('Configuration Error!'),
- _('Invoice line account\'s company and invoice\'s compnay does not match.'))
+ _('Invoice line account\'s company and invoice\'s company does not match.'))
else:
continue
if company_id and type:
- if type in ('out_invoice'):
- journal_type = 'sale'
- elif type in ('out_refund'):
- journal_type = 'sale_refund'
- elif type in ('in_refund'):
- journal_type = 'purchase_refund'
- else:
- journal_type = 'purchase'
+ journal_mapping = {
+ 'out_invoice': 'sale',
+ 'out_refund': 'sale_refund',
+ 'in_refund': 'purchase_refund',
+ 'in_invoice': 'purchase',
+ }
+ journal_type = journal_mapping[type]
journal_ids = obj_journal.search(cr, uid, [('company_id','=',company_id), ('type', '=', journal_type)])
if journal_ids:
val['journal_id'] = journal_ids[0]
if r[1] == 'journal_id' and r[2] in journal_ids:
val['journal_id'] = r[2]
if not val.get('journal_id', False):
- raise osv.except_osv(_('Configuration Error!'), (_('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % (journal_type)))
+ journal_type_map = dict(obj_journal._columns['type'].selection)
+ journal_type_label = self.pool['ir.translation']._get_source(cr, uid, None, ('code','selection'),
+ context.get('lang'),
+ journal_type_map.get(journal_type))
+ raise osv.except_osv(_('Configuration Error!'),
+ _('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % ('"%s"' % journal_type_label))
dom = {'journal_id': [('id', 'in', journal_ids)]}
else:
journal_ids = obj_journal.search(cr, uid, [])
else:
ref = self._convert_ref(cr, uid, inv.number)
if not inv.journal_id.analytic_journal_id:
- raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
+ raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
il['analytic_lines'] = [(0,0, {
'name': il['name'],
'date': inv['date_invoice'],
if not key in compute_taxes:
raise osv.except_osv(_('Warning!'), _('Global taxes defined, but they are not in invoice lines !'))
base = compute_taxes[key]['base']
- if abs(base - tax.base) > company_currency.rounding:
+ precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
+ if float_compare(abs(base - tax.base), company_currency.rounding, precision_digits=precision) == 1:
raise osv.except_osv(_('Warning!'), _('Tax base different!\nClick on compute to update the tax base.'))
for key in compute_taxes:
if not key in tax_key:
cur_obj = self.pool.get('res.currency')
for i in invoice_move_lines:
if inv.currency_id.id != company_currency:
- context.update({'date': inv.date_invoice or time.strftime('%Y-%m-%d')})
+ context.update({'date': inv.date_invoice or fields.date.context_today(self, cr, uid, context=context)})
i['currency_id'] = inv.currency_id.id
i['amount_currency'] = i['price']
i['price'] = cur_obj.compute(cr, uid, inv.currency_id.id,
if not inv.journal_id.sequence_id:
raise osv.except_osv(_('Error!'), _('Please define sequence on the journal related to this invoice.'))
if not inv.invoice_line:
- raise osv.except_osv(_('No Invoice Lines !'), _('Please create some invoice lines.'))
+ raise osv.except_osv(_('No Invoice Lines!'), _('Please create some invoice lines.'))
if inv.move_id:
continue
ctx = context.copy()
ctx.update({'lang': inv.partner_id.lang})
if not inv.date_invoice:
- self.write(cr, uid, [inv.id], {'date_invoice': fields.date.context_today(self,cr,uid,context=context)}, context=ctx)
+ self.write(cr, uid, [inv.id], {'date_invoice': fields.date.context_today(self, cr, uid, context=context)}, context=ctx)
+ inv.refresh()
company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id.id
# create the analytical lines
# one move line per invoice line
self.check_tax_lines(cr, uid, inv, compute_taxes, ait_obj)
# I disabled the check_total feature
- group_check_total_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'group_supplier_inv_check_total')[1]
- group_check_total = self.pool.get('res.groups').browse(cr, uid, group_check_total_id, context=context)
- if group_check_total and uid in [x.id for x in group_check_total.users]:
+ if self.pool['res.users'].has_group(cr, uid, 'account.group_supplier_inv_check_total'):
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 encoded total does not match the computed total.'))
+ raise osv.except_osv(_('Bad Total!'), _('Please verify the price of the invoice!\nThe encoded total does not match the computed total.'))
if inv.payment_term:
total_fixed = total_percent = 0
total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml, context=ctx)
acc_id = inv.account_id.id
- name = inv['name'] or '/'
+ name = inv['name'] or inv['supplier_invoice_number'] or '/'
totlines = False
if inv.payment_term:
totlines = payment_term_obj.compute(cr,
'ref': ref
})
- date = inv.date_invoice or time.strftime('%Y-%m-%d')
-
part = self.pool.get("res.partner")._find_accounting_partner(inv.partner_id)
- line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part.id, date, context=ctx)),iml)
+ line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part.id, inv.date_invoice, context=ctx)),iml)
line = self.group_lines(cr, uid, iml, line, inv)
'ref': inv.reference and inv.reference or inv.name,
'line_id': line,
'journal_id': journal_id,
- 'date': date,
+ 'date': inv.date_invoice,
'narration': inv.comment,
'company_id': inv.company_id.id,
}
if not ids:
return []
types = {
- 'out_invoice': 'Invoice ',
- 'in_invoice': 'Sup. Invoice ',
- 'out_refund': 'Refund ',
- 'in_refund': 'Supplier Refund ',
+ 'out_invoice': _('Invoice'),
+ 'in_invoice': _('Supplier Invoice'),
+ 'out_refund': _('Refund'),
+ 'in_refund': _('Supplier Refund'),
}
- return [(r['id'], (r['number']) or types[r['type']] + (r['name'] or '')) for r in self.read(cr, uid, ids, ['type', 'number', 'name'], context, load='_classic_write')]
+ return [(r['id'], '%s %s' % (r['number'] or types[r['type']], r['name'] or '')) for r in self.read(cr, uid, ids, ['type', 'number', 'name'], context, load='_classic_write')]
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
if not args:
refund_journal_ids = obj_journal.search(cr, uid, [('type','=','sale_refund')], context=context)
if not date:
- date = time.strftime('%Y-%m-%d')
+ date = fields.date.context_today(self, cr, uid, context=context)
invoice_data.update({
'type': type_dict[invoice['type']],
'date_invoice': date,
_name = "account.invoice.line"
_description = "Invoice Line"
+ _order = "invoice_id,sequence,id"
_columns = {
'name': fields.text('Description', required=True),
'origin': fields.char('Source Document', size=256, help="Reference of the document that produced this invoice."),
'discount': 0.0,
'price_unit': _price_unit_default,
'account_id': _default_account_id,
+ 'sequence': 10,
}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
context = dict(context)
context.update({'company_id': company_id, 'force_company': company_id})
if not partner_id:
- raise osv.except_osv(_('No Partner Defined !'),_("You must first select a partner !") )
+ raise osv.except_osv(_('No Partner Defined!'),_("You must first select a partner!") )
if not product:
if type in ('in_invoice', 'in_refund'):
return {'value': {}, 'domain':{'product_uom':[]}}
company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id.id
for line in inv.invoice_line:
mres = self.move_line_get_item(cr, uid, line, context)
- if not mres:
- continue
+ mres['invl_id'] = line.id
res.append(mres)
tax_code_found= False
for tax in tax_obj.compute_all(cr, uid, line.invoice_line_tax_id,
if company_id:
company_currency = company_obj.read(cr, uid, [company_id], ['currency_id'])[0]['currency_id'][0]
if currency_id and company_currency:
- base = cur_obj.compute(cr, uid, currency_id, company_currency, base*factor, context={'date': date_invoice or time.strftime('%Y-%m-%d')}, round=False)
+ base = cur_obj.compute(cr, uid, currency_id, company_currency, base*factor, context={'date': date_invoice or fields.date.context_today(self, cr, uid)}, round=False)
return {'value': {'base_amount':base}}
def amount_change(self, cr, uid, ids, amount, currency_id=False, company_id=False, date_invoice=False):
if company_id:
company_currency = company_obj.read(cr, uid, [company_id], ['currency_id'])[0]['currency_id'][0]
if currency_id and company_currency:
- amount = cur_obj.compute(cr, uid, currency_id, company_currency, amount*factor, context={'date': date_invoice or time.strftime('%Y-%m-%d')}, round=False)
+ amount = cur_obj.compute(cr, uid, currency_id, company_currency, amount*factor, context={'date': date_invoice or fields.date.context_today(self, cr, uid)}, round=False)
return {'value': {'tax_amount': amount}}
_order = 'sequence'
if inv.type in ('out_invoice','in_invoice'):
val['base_code_id'] = tax['base_code_id']
val['tax_code_id'] = tax['tax_code_id']
- val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['base_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
- val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['tax_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
+ val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['base_sign'], context={'date': inv.date_invoice or fields.date.context_today(self, cr, uid, context=context)}, round=False)
+ val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['tax_sign'], context={'date': inv.date_invoice or fields.date.context_today(self, cr, uid, context=context)}, round=False)
val['account_id'] = tax['account_collected_id'] or line.account_id.id
val['account_analytic_id'] = tax['account_analytic_collected_id']
else:
val['base_code_id'] = tax['ref_base_code_id']
val['tax_code_id'] = tax['ref_tax_code_id']
- val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['ref_base_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
- val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['ref_tax_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
+ val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['ref_base_sign'], context={'date': inv.date_invoice or fields.date.context_today(self, cr, uid, context=context)}, round=False)
+ val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['ref_tax_sign'], context={'date': inv.date_invoice or fields.date.context_today(self, cr, uid, context=context)}, round=False)
val['account_id'] = tax['account_paid_id'] or line.account_id.id
val['account_analytic_id'] = tax['account_analytic_paid_id']