@api.returns('account.analytic.journal', lambda r: r.id)
def _get_journal_analytic(self, inv_type):
""" Return the analytic journal corresponding to the given invoice type. """
- journal_type = TYPE2JOURNAL.get(inv_type, 'sale')
+ type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale', 'in_refund': 'purchase'}
+ journal_type = type2journal.get(inv_type, 'sale')
journal = self.env['account.analytic.journal'].search([('type', '=', journal_type)], limit=1)
if not journal:
raise except_orm(_('No Analytic Journal!'),
'move_id.line_id.currency_id',
'move_id.line_id.reconcile_partial_id.line_partial_ids.invoice.type',
)
+ # An invoice's residual amount is the sum of its unreconciled move lines and,
+ # for partially reconciled move lines, their residual amount divided by the
+ # number of times this reconciliation is used in an invoice (so we split
+ # the residual amount between all invoice)
def _compute_residual(self):
- nb_inv_in_partial_rec = max_invoice_id = 0
self.residual = 0.0
+ # Each partial reconciliation is considered only once for each invoice it appears into,
+ # and its residual amount is divided by this number of invoices
+ partial_reconciliations_done = []
for line in self.sudo().move_id.line_id:
- if line.account_id.type in ('receivable', 'payable'):
- if line.currency_id == self.currency_id:
- self.residual += line.amount_residual_currency
- else:
- # ahem, shouldn't we use line.currency_id here?
- from_currency = line.company_id.currency_id.with_context(date=line.date)
- self.residual += from_currency.compute(line.amount_residual, self.currency_id)
- # we check if the invoice is partially reconciled and if there
- # are other invoices involved in this partial reconciliation
+ if line.account_id.type not in ('receivable', 'payable'):
+ continue
+ if line.reconcile_partial_id and line.reconcile_partial_id.id in partial_reconciliations_done:
+ continue
+ # Get the correct line residual amount
+ if line.currency_id == self.currency_id:
+ line_amount = line.currency_id and line.amount_residual_currency or line.amount_residual
+ else:
+ from_currency = line.company_id.currency_id.with_context(date=line.date)
+ line_amount = from_currency.compute(line.amount_residual, self.currency_id)
+ # For partially reconciled lines, split the residual amount
+ if line.reconcile_partial_id:
+ partial_reconciliation_invoices = set()
for pline in line.reconcile_partial_id.line_partial_ids:
if pline.invoice and self.type == pline.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, pline.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 invoices to have a sum of
- # residual amounts that matches the partner balance
- new_value = self.currency_id.round(self.residual / nb_inv_in_partial_rec)
- if self.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
- self.residual = self.residual - ((nb_inv_in_partial_rec - 1) * new_value)
- else:
- self.residual = new_value
- # prevent the residual amount on the invoice to be less than 0
+ partial_reconciliation_invoices.update([pline.invoice.id])
+ line_amount = self.currency_id.round(line_amount / len(partial_reconciliation_invoices))
+ partial_reconciliations_done.append(line.reconcile_partial_id.id)
+ self.residual += line_amount
self.residual = max(self.residual, 0.0)
@api.one
if line.value == 'fixed':
total_fixed += line.value_amount
if line.value == 'procent':
- total_percent += line.value_amount
+ total_percent += (line.value_amount/100.0)
total_fixed = (total_fixed * 100) / (inv.amount_total or 1.0)
if (total_fixed + total_percent) > 100:
raise except_orm(_('Error!'), _("Cannot create the invoice.\nThe related payment term is probably misconfigured as it gives a computed amount greater than the total invoiced amount. In order to avoid rounding issues, the latest line of your payment term must be of type 'balance'."))
_inherit = 'res.partner'
invoice_ids = fields.One2many('account.invoice', 'partner_id', string='Invoices',
- readonly=True)
+ readonly=True, copy=False)
def _find_accounting_partner(self, partner):
'''