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):
return [('none', _('Free Reference'))]
def _amount_residual(self, cr, uid, ids, name, args, context=None):
+ """Function of the field residua. It computes the residual amount (balance) for each invoice"""
+ if context is None:
+ context = {}
+ ctx = context.copy()
result = {}
+ currency_obj = self.pool.get('res.currency')
for invoice in self.browse(cr, uid, ids, context=context):
+ nb_inv_in_partial_rec = max_invoice_id = 0
result[invoice.id] = 0.0
if invoice.move_id:
- for m in invoice.move_id.line_id:
- if m.account_id.type in ('receivable','payable'):
- result[invoice.id] += m.amount_residual_currency
+ for aml in invoice.move_id.line_id:
+ if aml.account_id.type in ('receivable','payable'):
+ if aml.currency_id and aml.currency_id.id == invoice.currency_id.id:
+ result[invoice.id] += aml.amount_residual_currency
+ else:
+ ctx['date'] = aml.date
+ result[invoice.id] += currency_obj.compute(cr, uid, aml.company_id.currency_id.id, invoice.currency_id.id, aml.amount_residual, context=ctx)
+
+ if aml.reconcile_partial_id.line_partial_ids:
+ #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 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)
+ if nb_inv_in_partial_rec:
+ #if there are several invoices in a partial reconciliation, we split the residual by the number
+ #of invoice to have a sum of residual amounts that matches the partner balance
+ new_value = currency_obj.round(cr, uid, invoice.currency_id, result[invoice.id] / nb_inv_in_partial_rec)
+ if invoice.id == max_invoice_id:
+ #if it's the last the invoice of the bunch of invoices partially reconciled together, we make a
+ #balance to avoid rounding errors
+ result[invoice.id] = result[invoice.id] - ((nb_inv_in_partial_rec - 1) * new_value)
+ else:
+ result[invoice.id] = new_value
+
#prevent the residual amount on the invoice to be less than 0
result[invoice.id] = max(result[invoice.id], 0.0)
return result
'type': {
},
'state': {
- 'account.mt_invoice_paid': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'paid' and obj['type'] in ('out_invoice', 'out_refund'),
- 'account.mt_invoice_validated': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'open' and obj['type'] in ('out_invoice', 'out_refund'),
+ 'account.mt_invoice_paid': lambda self, cr, uid, obj, ctx=None: obj.state == 'paid' and obj.type in ('out_invoice', 'out_refund'),
+ 'account.mt_invoice_validated': lambda self, cr, uid, obj, ctx=None: obj.state == 'open' and obj.type in ('out_invoice', 'out_refund'),
},
}
_columns = {
def onchange_payment_term_date_invoice(self, cr, uid, ids, payment_term_id, date_invoice):
res = {}
+ if isinstance(ids, (int, long)):
+ ids = [ids]
if not date_invoice:
date_invoice = time.strftime('%Y-%m-%d')
if not payment_term_id:
- return {'value':{'date_due': date_invoice}} #To make sure the invoice has a due date when no payment term
+ 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]
return {'value': {}}
def onchange_company_id(self, cr, uid, ids, company_id, part_id, type, invoice_line, currency_id, context=None):
+ #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')
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, [])
self.create_workflow(cr, uid, ids)
return True
+ # ----------------------------------------
+ # Mail related methods
+ # ----------------------------------------
+
+ def _get_formview_action(self, cr, uid, id, context=None):
+ """ Update form view id of action to open the invoice """
+ action = super(account_invoice, self)._get_formview_action(cr, uid, id, context=context)
+ obj = self.browse(cr, uid, id, context=context)
+ if obj.type == 'in_invoice':
+ model, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'invoice_supplier_form')
+ action.update({
+ 'views': [(view_id, 'form')],
+ })
+ else:
+ model, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account', 'invoice_form')
+ action.update({
+ 'views': [(view_id, 'form')],
+ })
+ return action
+
# Workflow stuff
#################
inv = self.browse(cr, uid, id)
cur_obj = self.pool.get('res.currency')
- company_currency = inv.company_id.currency_id.id
+ company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id.id
if inv.type in ('out_invoice', 'in_refund'):
sign = 1
else:
return move_lines
def check_tax_lines(self, cr, uid, inv, compute_taxes, ait_obj):
+ company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id
if not inv.tax_line:
for tax in compute_taxes.values():
ait_obj.create(cr, uid, tax)
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) > inv.company_id.currency_id.rounding:
+ if abs(base - tax.base) > company_currency.rounding:
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:
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)
- company_currency = inv.company_id.currency_id.id
+ 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
iml = self._get_analytic_lines(cr, uid, inv.id, context=ctx)
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 (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,
'line_id': line,
'journal_id': journal_id,
'date': date,
- 'narration':inv.comment
+ 'narration': inv.comment,
+ 'company_id': inv.company_id.id,
}
period_id = inv.period_id and inv.period_id.id or False
ctx.update(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:
_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):
result = {}
res = self.pool.get('product.product').browse(cr, uid, product, context=context)
+ result['name'] = res.partner_ref
if type in ('out_invoice','out_refund'):
a = res.property_account_income.id
if not a:
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, context=context).tax_ids or False)
+ if res.description_sale:
+ result['name'] += '\n'+res.description_sale
else:
taxes = res.supplier_taxes_id and res.supplier_taxes_id or (a and self.pool.get('account.account').browse(cr, uid, a, context=context).tax_ids or False)
+ if res.description_purchase:
+ result['name'] += '\n'+res.description_purchase
+
tax_id = fpos_obj.map_tax(cr, uid, fpos, taxes)
if type in ('in_invoice', 'in_refund'):
result.update( {'price_unit': price_unit or res.standard_price,'invoice_line_tax_id': tax_id} )
else:
result.update({'price_unit': res.list_price, 'invoice_line_tax_id': tax_id})
- result['name'] = res.partner_ref
result['uos_id'] = uom_id or res.uom_id.id
- if res.description:
- result['name'] += '\n'+res.description
domain = {'uos_id':[('category_id','=',res.uom_id.category_id.id)]}
if context is None:
context = {}
inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context)
- company_currency = inv.company_id.currency_id.id
-
+ 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:
cur_obj = self.pool.get('res.currency')
inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context)
cur = inv.currency_id
- company_currency = inv.company_id.currency_id.id
-
+ company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id.id
for line in inv.invoice_line:
for tax in tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, (line.price_unit* (1-(line.discount or 0.0)/100.0)), line.quantity, line.product_id, inv.partner_id)['taxes']:
val={}