271 lines
11 KiB
Python
271 lines
11 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# © 2012-2016 Akretion (http://www.akretion.com/)
|
||
|
# @author: Benoît GUILLOT <benoit.guillot@akretion.com>
|
||
|
# @author: Chafique DELLI <chafique.delli@akretion.com>
|
||
|
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||
|
# @author: Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
|
||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||
|
|
||
|
from odoo import models, fields, api, _
|
||
|
import odoo.addons.decimal_precision as dp
|
||
|
from odoo.exceptions import ValidationError, UserError
|
||
|
|
||
|
|
||
|
class AccountCheckDeposit(models.Model):
|
||
|
_name = "account.check.deposit"
|
||
|
_description = "Account Check Deposit"
|
||
|
_order = 'deposit_date desc'
|
||
|
|
||
|
@api.multi
|
||
|
@api.depends(
|
||
|
'company_id', 'currency_id', 'check_payment_ids.debit',
|
||
|
'check_payment_ids.amount_currency',
|
||
|
'move_id.line_ids.reconciled')
|
||
|
def _compute_check_deposit(self):
|
||
|
for deposit in self:
|
||
|
total = 0.0
|
||
|
count = 0
|
||
|
reconcile = False
|
||
|
currency_none_same_company_id = False
|
||
|
if deposit.company_id.currency_id != deposit.currency_id:
|
||
|
currency_none_same_company_id = deposit.currency_id.id
|
||
|
for line in deposit.check_payment_ids:
|
||
|
count += 1
|
||
|
if currency_none_same_company_id:
|
||
|
total += line.amount_currency
|
||
|
else:
|
||
|
total += line.debit
|
||
|
if deposit.move_id:
|
||
|
for line in deposit.move_id.line_ids:
|
||
|
if line.debit > 0 and line.reconciled:
|
||
|
reconcile = True
|
||
|
deposit.total_amount = total
|
||
|
deposit.is_reconcile = reconcile
|
||
|
deposit.currency_none_same_company_id =\
|
||
|
currency_none_same_company_id
|
||
|
deposit.check_count = count
|
||
|
|
||
|
name = fields.Char(string='Name', size=64, readonly=True, default='/')
|
||
|
check_payment_ids = fields.One2many(
|
||
|
'account.move.line', 'check_deposit_id', string='Check Payments',
|
||
|
states={'done': [('readonly', '=', True)]})
|
||
|
deposit_date = fields.Date(
|
||
|
string='Deposit Date', required=True,
|
||
|
states={'done': [('readonly', '=', True)]},
|
||
|
default=fields.Date.context_today)
|
||
|
journal_id = fields.Many2one(
|
||
|
'account.journal', string='Journal',
|
||
|
domain=[('type', '=', 'bank'), ('bank_account_id', '=', False)],
|
||
|
required=True, states={'done': [('readonly', '=', True)]})
|
||
|
journal_default_account_id = fields.Many2one(
|
||
|
'account.account', related='journal_id.default_debit_account_id',
|
||
|
string='Default Debit Account of the Journal', readonly=True)
|
||
|
currency_id = fields.Many2one(
|
||
|
'res.currency', string='Currency', required=True,
|
||
|
states={'done': [('readonly', '=', True)]})
|
||
|
currency_none_same_company_id = fields.Many2one(
|
||
|
'res.currency', compute='_compute_check_deposit',
|
||
|
string='Currency (False if same as company)')
|
||
|
state = fields.Selection(
|
||
|
[
|
||
|
('draft', 'Draft'),
|
||
|
('done', 'Done'),
|
||
|
], string='Status', default='draft', readonly=True)
|
||
|
move_id = fields.Many2one(
|
||
|
'account.move', string='Journal Entry', readonly=True)
|
||
|
bank_journal_id = fields.Many2one(
|
||
|
'account.journal', string='Bank Account', required=True,
|
||
|
domain="[('company_id', '=', company_id), ('type', '=', 'bank'), "
|
||
|
"('bank_account_id', '!=', False)]",
|
||
|
states={'done': [('readonly', '=', True)]})
|
||
|
line_ids = fields.One2many(
|
||
|
'account.move.line', related='move_id.line_ids',
|
||
|
string='Lines', readonly=True)
|
||
|
company_id = fields.Many2one(
|
||
|
'res.company', string='Company', required=True,
|
||
|
states={'done': [('readonly', '=', True)]},
|
||
|
default=lambda self: self.env['res.company']._company_default_get(
|
||
|
'account.check.deposit'))
|
||
|
total_amount = fields.Float(
|
||
|
compute='_compute_check_deposit',
|
||
|
string="Total Amount", readonly=True,
|
||
|
digits=dp.get_precision('Account'))
|
||
|
check_count = fields.Integer(
|
||
|
compute='_compute_check_deposit', readonly=True,
|
||
|
string="Number of Checks")
|
||
|
is_reconcile = fields.Boolean(
|
||
|
compute='_compute_check_deposit', readonly=True,
|
||
|
string="Reconcile")
|
||
|
|
||
|
@api.multi
|
||
|
@api.constrains('currency_id', 'check_payment_ids', 'company_id')
|
||
|
def _check_deposit(self):
|
||
|
for deposit in self:
|
||
|
deposit_currency = deposit.currency_id
|
||
|
if deposit_currency == deposit.company_id.currency_id:
|
||
|
for line in deposit.check_payment_ids:
|
||
|
if line.currency_id:
|
||
|
raise ValidationError(
|
||
|
_("The check with amount %s and reference '%s' "
|
||
|
"is in currency %s but the deposit is in "
|
||
|
"currency %s.") % (
|
||
|
line.debit, line.ref or '',
|
||
|
line.currency_id.name,
|
||
|
deposit_currency.name))
|
||
|
else:
|
||
|
for line in deposit.check_payment_ids:
|
||
|
if line.currency_id != deposit_currency:
|
||
|
raise ValidationError(
|
||
|
_("The check with amount %s and reference '%s' "
|
||
|
"is in currency %s but the deposit is in "
|
||
|
"currency %s.") % (
|
||
|
line.debit, line.ref or '',
|
||
|
line.currency_id.name,
|
||
|
deposit_currency.name))
|
||
|
|
||
|
@api.multi
|
||
|
def unlink(self):
|
||
|
for deposit in self:
|
||
|
if deposit.state == 'done':
|
||
|
raise UserError(
|
||
|
_("The deposit '%s' is in valid state, so you must "
|
||
|
"cancel it before deleting it.")
|
||
|
% deposit.name)
|
||
|
return super(AccountCheckDeposit, self).unlink()
|
||
|
|
||
|
@api.multi
|
||
|
def backtodraft(self):
|
||
|
for deposit in self:
|
||
|
if deposit.move_id:
|
||
|
# It will raise here if journal_id.update_posted = False
|
||
|
deposit.move_id.button_cancel()
|
||
|
for line in deposit.check_payment_ids:
|
||
|
if line.reconciled:
|
||
|
line.remove_move_reconcile()
|
||
|
deposit.move_id.unlink()
|
||
|
deposit.write({'state': 'draft'})
|
||
|
return True
|
||
|
|
||
|
@api.model
|
||
|
def create(self, vals):
|
||
|
if vals.get('name', '/') == '/':
|
||
|
vals['name'] = self.env['ir.sequence'].\
|
||
|
next_by_code('account.check.deposit')
|
||
|
return super(AccountCheckDeposit, self).create(vals)
|
||
|
|
||
|
@api.model
|
||
|
def _prepare_account_move_vals(self, deposit):
|
||
|
if (
|
||
|
deposit.company_id.check_deposit_offsetting_account ==
|
||
|
'bank_account'):
|
||
|
journal_id = deposit.bank_journal_id.id
|
||
|
else:
|
||
|
journal_id = deposit.journal_id.id
|
||
|
move_vals = {
|
||
|
'journal_id': journal_id,
|
||
|
'date': deposit.deposit_date,
|
||
|
'name': _('Check Deposit %s') % deposit.name,
|
||
|
'ref': deposit.name,
|
||
|
}
|
||
|
return move_vals
|
||
|
|
||
|
@api.model
|
||
|
def _prepare_move_line_vals(self, line):
|
||
|
assert (line.debit > 0), 'Debit must have a value'
|
||
|
return {
|
||
|
'name': _('Check Deposit - Ref. Check %s') % line.ref,
|
||
|
'credit': line.debit,
|
||
|
'debit': 0.0,
|
||
|
'account_id': line.account_id.id,
|
||
|
'partner_id': line.partner_id.id,
|
||
|
'currency_id': line.currency_id.id or False,
|
||
|
'amount_currency': line.amount_currency * -1,
|
||
|
}
|
||
|
|
||
|
@api.model
|
||
|
def _prepare_counterpart_move_lines_vals(
|
||
|
self, deposit, total_debit, total_amount_currency):
|
||
|
company = deposit.company_id
|
||
|
if not company.check_deposit_offsetting_account:
|
||
|
raise UserError(_(
|
||
|
"You must configure the 'Check Deposit Offsetting Account' "
|
||
|
"on the Accounting Settings page"))
|
||
|
if company.check_deposit_offsetting_account == 'bank_account':
|
||
|
if not deposit.bank_journal_id.default_debit_account_id:
|
||
|
raise UserError(_(
|
||
|
"Missing 'Default Debit Account' on bank journal '%s'")
|
||
|
% deposit.bank_journal_id.name)
|
||
|
account_id = deposit.bank_journal_id.default_debit_account_id.id
|
||
|
elif company.check_deposit_offsetting_account == 'transfer_account':
|
||
|
if not company.check_deposit_transfer_account_id:
|
||
|
raise UserError(_(
|
||
|
"Missing 'Account for Check Deposits' on the "
|
||
|
"company '%s'.") % company.name)
|
||
|
account_id = company.check_deposit_transfer_account_id.id
|
||
|
return {
|
||
|
'name': _('Check Deposit %s') % deposit.name,
|
||
|
'debit': total_debit,
|
||
|
'credit': 0.0,
|
||
|
'account_id': account_id,
|
||
|
'partner_id': False,
|
||
|
'currency_id': deposit.currency_none_same_company_id.id or False,
|
||
|
'amount_currency': total_amount_currency,
|
||
|
}
|
||
|
|
||
|
@api.multi
|
||
|
def validate_deposit(self):
|
||
|
am_obj = self.env['account.move']
|
||
|
move_line_obj = self.env['account.move.line']
|
||
|
for deposit in self:
|
||
|
move_vals = self._prepare_account_move_vals(deposit)
|
||
|
move = am_obj.create(move_vals)
|
||
|
total_debit = 0.0
|
||
|
total_amount_currency = 0.0
|
||
|
to_reconcile_lines = []
|
||
|
for line in deposit.check_payment_ids:
|
||
|
total_debit += line.debit
|
||
|
total_amount_currency += line.amount_currency
|
||
|
line_vals = self._prepare_move_line_vals(line)
|
||
|
line_vals['move_id'] = move.id
|
||
|
move_line = move_line_obj.with_context(
|
||
|
check_move_validity=False).create(line_vals)
|
||
|
to_reconcile_lines.append(line + move_line)
|
||
|
|
||
|
# Create counter-part
|
||
|
counter_vals = self._prepare_counterpart_move_lines_vals(
|
||
|
deposit, total_debit, total_amount_currency)
|
||
|
counter_vals['move_id'] = move.id
|
||
|
move_line_obj.create(counter_vals)
|
||
|
|
||
|
deposit.write({'state': 'done', 'move_id': move.id})
|
||
|
for reconcile_lines in to_reconcile_lines:
|
||
|
reconcile_lines.reconcile()
|
||
|
return True
|
||
|
|
||
|
@api.onchange('company_id')
|
||
|
def onchange_company_id(self):
|
||
|
if self.company_id:
|
||
|
bank_journals = self.env['account.journal'].search([
|
||
|
('company_id', '=', self.company_id.id),
|
||
|
('type', '=', 'bank'),
|
||
|
('bank_account_id', '!=', False)])
|
||
|
if len(bank_journals) == 1:
|
||
|
self.bank_journal_id = bank_journals[0]
|
||
|
else:
|
||
|
self.bank_journal_id = False
|
||
|
|
||
|
@api.onchange('journal_id')
|
||
|
def onchange_journal_id(self):
|
||
|
if self.journal_id:
|
||
|
if self.journal_id.currency_id:
|
||
|
self.currency_id = self.journal_id.currency_id
|
||
|
else:
|
||
|
self.currency_id = self.journal_id.company_id.currency_id
|
||
|
|
||
|
|
||
|
class AccountMoveLine(models.Model):
|
||
|
_inherit = "account.move.line"
|
||
|
|
||
|
check_deposit_id = fields.Many2one(
|
||
|
'account.check.deposit', string='Check Deposit', copy=False)
|