odoo/addons/account/wizard/account_reconcile.py

145 lines
7.4 KiB
Python

from odoo import models, fields, api, _
from odoo.tools.float_utils import float_round
from odoo.exceptions import UserError
class AccountMoveLineReconcile(models.TransientModel):
"""
Account move line reconcile wizard, it checks for the write off the reconcile entry or directly reconcile.
"""
_name = 'account.move.line.reconcile'
_description = 'Account move line reconcile'
trans_nbr = fields.Integer(string='# of Transaction', readonly=True)
credit = fields.Float(string='Credit amount', readonly=True, digits=0)
debit = fields.Float(string='Debit amount', readonly=True, digits=0)
writeoff = fields.Float(string='Write-Off amount', readonly=True, digits=0)
company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.user.company_id)
@api.model
def default_get(self, fields):
res = super(AccountMoveLineReconcile, self).default_get(fields)
data = self.trans_rec_get()
if 'trans_nbr' in fields:
res.update({'trans_nbr': data['trans_nbr']})
if 'credit' in fields:
res.update({'credit': data['credit']})
if 'debit' in fields:
res.update({'debit': data['debit']})
if 'writeoff' in fields:
res.update({'writeoff': data['writeoff']})
return res
@api.multi
def trans_rec_get(self):
context = self._context or {}
credit = debit = 0
lines = self.env['account.move.line'].browse(context.get('active_ids', []))
for line in lines:
if not line.full_reconcile_id:
credit += line.credit
debit += line.debit
precision = self.env.user.company_id.currency_id.decimal_places
writeoff = float_round(debit - credit, precision_digits=precision)
credit = float_round(credit, precision_digits=precision)
debit = float_round(debit, precision_digits=precision)
return {'trans_nbr': len(lines), 'credit': credit, 'debit': debit, 'writeoff': writeoff}
@api.multi
def trans_rec_addendum_writeoff(self):
return self.env['account.move.line.reconcile.writeoff'].trans_rec_addendum()
@api.multi
def trans_rec_reconcile_partial_reconcile(self):
return self.env['account.move.line.reconcile.writeoff'].trans_rec_reconcile_partial()
@api.multi
def trans_rec_reconcile_full(self):
move_lines = self.env['account.move.line'].browse(self._context.get('active_ids', []))
currency = False
for aml in move_lines:
if not currency and aml.currency_id.id:
currency = aml.currency_id.id
elif aml.currency_id:
if aml.currency_id.id == currency:
continue
raise UserError(_('Operation not allowed. You can only reconcile entries that share the same secondary currency or that don\'t have one. Edit your journal items or make another selection before proceeding any further.'))
#Don't consider entrires that are already reconciled
move_lines_filtered = move_lines.filtered(lambda aml: not aml.reconciled)
#Because we are making a full reconcilition in batch, we need to consider use cases as defined in the test test_manual_reconcile_wizard_opw678153
#So we force the reconciliation in company currency only at first
move_lines_filtered.with_context(skip_full_reconcile_check='amount_currency_excluded', manual_full_reconcile_currency=currency).reconcile()
#then in second pass the amounts in secondary currency, only if some lines are still not fully reconciled
move_lines_filtered = move_lines.filtered(lambda aml: not aml.reconciled)
if move_lines_filtered:
move_lines_filtered.with_context(skip_full_reconcile_check='amount_currency_only', manual_full_reconcile_currency=currency).reconcile()
move_lines.compute_full_after_batch_reconcile()
return {'type': 'ir.actions.act_window_close'}
class AccountMoveLineReconcileWriteoff(models.TransientModel):
"""
It opens the write off wizard form, in that user can define the journal, account, analytic account for reconcile
"""
_name = 'account.move.line.reconcile.writeoff'
_description = 'Account move line reconcile (writeoff)'
journal_id = fields.Many2one('account.journal', string='Write-Off Journal', required=True)
writeoff_acc_id = fields.Many2one('account.account', string='Write-Off account', required=True, domain=[('deprecated', '=', False)])
date_p = fields.Date(string='Date', default=fields.Date.context_today)
comment = fields.Char(required=True, default='Write-off')
analytic_id = fields.Many2one('account.analytic.account', string='Analytic Account')
@api.multi
def trans_rec_addendum(self):
view = self.env.ref('account.account_move_line_reconcile_writeoff')
return {
'name': _('Reconcile Writeoff'),
'context': self._context,
'view_type': 'form',
'view_mode': 'form',
'res_model': 'account.move.line.reconcile.writeoff',
'views': [(view.id, 'form')],
'type': 'ir.actions.act_window',
'target': 'new',
}
@api.multi
def trans_rec_reconcile_partial(self):
context = self._context or {}
self.env['account.move.line'].browse(context.get('active_ids', [])).reconcile()
return {'type': 'ir.actions.act_window_close'}
@api.multi
def trans_rec_reconcile(self):
context = dict(self._context or {})
context['date_p'] = self.date_p
context['comment'] = self.comment
if self.analytic_id:
context['analytic_id'] = self.analytic_id.id
move_lines = self.env['account.move.line'].browse(self._context.get('active_ids', []))
currency = False
for aml in move_lines:
if not currency and aml.currency_id.id:
currency = aml.currency_id.id
elif aml.currency_id:
if aml.currency_id.id == currency:
continue
raise UserError(_('Operation not allowed. You can only reconcile entries that share the same secondary currency or that don\'t have one. Edit your journal items or make another selection before proceeding any further.'))
#Don't consider entrires that are already reconciled
move_lines_filtered = move_lines.filtered(lambda aml: not aml.reconciled)
#Because we are making a full reconcilition in batch, we need to consider use cases as defined in the test test_manual_reconcile_wizard_opw678153
#So we force the reconciliation in company currency only at first,
context['skip_full_reconcile_check'] = 'amount_currency_excluded'
context['manual_full_reconcile_currency'] = currency
writeoff = move_lines_filtered.with_context(context).reconcile(self.writeoff_acc_id, self.journal_id)
#then in second pass the amounts in secondary currency, only if some lines are still not fully reconciled
move_lines_filtered = move_lines.filtered(lambda aml: not aml.reconciled)
if move_lines_filtered:
move_lines_filtered.with_context(skip_full_reconcile_check='amount_currency_only', manual_full_reconcile_currency=currency).reconcile()
if not isinstance(writeoff, bool):
move_lines += writeoff
move_lines.compute_full_after_batch_reconcile()
return {'type': 'ir.actions.act_window_close'}