mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
[REF] account_check_deposit : Port to new API
* Move description from __openerp__.py to README.rst * Move files in sub-directories * FIX access rights issue when user was not accounting manager
This commit is contained in:
committed by
ps-tubtim
parent
700a81aacb
commit
29834f8fdd
69
account_check_deposit/README.rst
Normal file
69
account_check_deposit/README.rst
Normal file
@@ -0,0 +1,69 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
=============
|
||||
Check Deposit
|
||||
=============
|
||||
|
||||
This module allows you to easily manage check deposits : you can select all
|
||||
the checks you received and create a global deposit for the
|
||||
selected checks. This module supports multi-currency ; each deposit has a currency
|
||||
and all the checks of the deposit must have the same currency
|
||||
(so, if you have checks in EUR and checks in USD, you must create 2 deposits :
|
||||
one in EUR and one in USD).
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
A journal named *Check Received* is automatically created. It will be available as a payment method in Odoo. On this journal, you must configure the *Default Debit Account* and *Defaut Credit Account* ; this is the account via which the amounts of checks will transit between the reception of a check from a customer and the validation of the check deposit in Odoo.
|
||||
|
||||
On the company form view, you should configure the *Account for Check Deposits* ; this is the account via which the amounts of checks will transit between the validation of the check deposit in Odoo and the credit on the bank account.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
When you receive a check that pays a customer invoice, you can go to that invoice and click on the button *Register Payment* and select the *Check Received* journal as *Payment Method*.
|
||||
|
||||
When you want to deposit checks to the bank, go to the menu *Accounting > Bank and Cash > Check Deposit*, create a new check deposit and set the journal *Checks Received* and select the bank account on which you want to credit the checks. Then click on *Add an item* to select the checks you want to deposit at the bank. Eventually, validate the deposit and print the report (you probably want to customize this report).
|
||||
|
||||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
|
||||
:alt: Try me on Runbot
|
||||
:target: https://runbot.odoo-community.org/runbot/92/8.0
|
||||
|
||||
For further information, please visit:
|
||||
|
||||
* https://www.odoo.com/forum/help-1
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-financial-tools/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
|
||||
`here <https://github.com/OCA/account-financial-tools/issues/new?body=module:%20account_check_deposit%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Benoît GUILLOT <benoit.guillot@akretion.com>
|
||||
* Chafique DELLI <chafique.delli@akretion.com>
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: http://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: http://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
To contribute to this module, please visit http://odoo-community.org.
|
||||
@@ -1,22 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# account_check_deposit for Odoo/OpenERP
|
||||
# Copyright (C) 2012-2015 Akretion (http://www.akretion.com/)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
from . import account_deposit
|
||||
from . import models
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# account_check_deposit for Odoo/OpenERP
|
||||
# account_check_deposit for Odoo
|
||||
# Copyright (C) 2012-2015 Akretion (http://www.akretion.com/)
|
||||
# @author: Benoît GUILLOT <benoit.guillot@akretion.com>
|
||||
# @author: Chafique DELLI <chafique.delli@akretion.com>
|
||||
@@ -28,18 +28,6 @@
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Manage deposit of checks to the bank',
|
||||
'description': """
|
||||
Account Check Deposit
|
||||
=====================
|
||||
This module allows you to easily manage check deposits : you can select all
|
||||
the checks you received as payments and create a global deposit for the
|
||||
selected checks.
|
||||
|
||||
A journal for received checks is automatically created.
|
||||
You must configure on this journal the default debit account and the default
|
||||
credit account. You must also configure on the company the account for
|
||||
check deposits.
|
||||
""",
|
||||
'author': "Akretion,Odoo Community Association (OCA)",
|
||||
'website': 'http://www.akretion.com/',
|
||||
'depends': [
|
||||
@@ -47,14 +35,14 @@ check deposits.
|
||||
'report_webkit',
|
||||
],
|
||||
'data': [
|
||||
'account_deposit_view.xml',
|
||||
'account_move_line_view.xml',
|
||||
'account_deposit_sequence.xml',
|
||||
'company_view.xml',
|
||||
'views/account_deposit_view.xml',
|
||||
'views/account_move_line_view.xml',
|
||||
'data/account_deposit_sequence.xml',
|
||||
'views/company_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/check_deposit_security.xml',
|
||||
'account_data.xml',
|
||||
'report.xml',
|
||||
'data/account_data.xml',
|
||||
'report/report.xml',
|
||||
'report/report_checkdeposit.xml',
|
||||
],
|
||||
'installable': True,
|
||||
|
||||
@@ -1,340 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# account_check_deposit for Odoo/OpenERP
|
||||
# Copyright (C) 2012-2015 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>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
from openerp.osv import fields, orm
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class account_check_deposit(orm.Model):
|
||||
_name = "account.check.deposit"
|
||||
_description = "Account Check Deposit"
|
||||
_order = 'deposit_date desc'
|
||||
|
||||
def _compute_check_deposit(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
for deposit in self.browse(cr, uid, ids, context=context):
|
||||
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_id:
|
||||
if line.debit > 0 and line.reconcile_id:
|
||||
reconcile = True
|
||||
res[deposit.id] = {
|
||||
'total_amount': total,
|
||||
'is_reconcile': reconcile,
|
||||
'currency_none_same_company_id': currency_none_same_company_id,
|
||||
'check_count': count,
|
||||
}
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'name': fields.char(
|
||||
'Name', size=64, readonly=True),
|
||||
'check_payment_ids': fields.one2many(
|
||||
'account.move.line', 'check_deposit_id', 'Check Payments',
|
||||
states={'done': [('readonly', '=', True)]}),
|
||||
'deposit_date': fields.date(
|
||||
'Deposit Date', required=True,
|
||||
states={'done': [('readonly', '=', True)]}),
|
||||
'journal_id': fields.many2one(
|
||||
'account.journal', 'Journal', domain=[('type', '=', 'bank')],
|
||||
required=True, states={'done': [('readonly', '=', True)]}),
|
||||
'journal_default_account_id': fields.related(
|
||||
'journal_id', 'default_debit_account_id', type='many2one',
|
||||
relation='account.account',
|
||||
string='Default Debit Account of the Journal'),
|
||||
'currency_id': fields.many2one(
|
||||
'res.currency', 'Currency', required=True,
|
||||
states={'done': [('readonly', '=', True)]}),
|
||||
'currency_none_same_company_id': fields.function(
|
||||
_compute_check_deposit, type='many2one',
|
||||
relation='res.currency', multi='deposit',
|
||||
string='Currency (False if same as company)'),
|
||||
'state': fields.selection([
|
||||
('draft', 'Draft'),
|
||||
('done', 'Done'),
|
||||
], 'Status', readonly=True),
|
||||
'move_id': fields.many2one(
|
||||
'account.move', 'Journal Entry', readonly=True),
|
||||
'partner_bank_id': fields.many2one(
|
||||
'res.partner.bank', 'Bank Account', required=True,
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
states={'done': [('readonly', '=', True)]}),
|
||||
'line_ids': fields.related(
|
||||
'move_id', 'line_id', relation='account.move.line',
|
||||
type='one2many', string='Lines', readonly=True),
|
||||
'company_id': fields.many2one(
|
||||
'res.company', 'Company', required=True,
|
||||
change_default=True,
|
||||
states={'done': [('readonly', '=', True)]}),
|
||||
'total_amount': fields.function(
|
||||
_compute_check_deposit, multi='deposit',
|
||||
string="Total Amount", readonly=True,
|
||||
type="float", digits_compute=dp.get_precision('Account')),
|
||||
'check_count': fields.function(
|
||||
_compute_check_deposit, multi='deposit', readonly=True,
|
||||
string="Number of Checks", type="integer"),
|
||||
'is_reconcile': fields.function(
|
||||
_compute_check_deposit, multi='deposit', readonly=True,
|
||||
string="Reconcile", type="boolean"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'name': '/',
|
||||
'deposit_date': fields.date.context_today,
|
||||
'state': 'draft',
|
||||
'company_id': lambda self, cr, uid, c: self.pool['res.company'].
|
||||
_company_default_get(cr, uid, 'account.check.deposit', context=c),
|
||||
}
|
||||
|
||||
def _check_deposit(self, cr, uid, ids):
|
||||
for deposit in self.browse(cr, uid, ids):
|
||||
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 orm.except_orm(
|
||||
_('Error:'),
|
||||
_("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 orm.except_orm(
|
||||
_('Error:'),
|
||||
_("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))
|
||||
return True
|
||||
|
||||
_constraints = [(
|
||||
_check_deposit,
|
||||
"All the checks of the deposit must be in the currency of the deposit",
|
||||
['currency_id', 'check_payment_ids', 'company_id']
|
||||
)]
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
for deposit in self.browse(cr, uid, ids, context=context):
|
||||
if deposit.state == 'done':
|
||||
raise orm.except_orm(
|
||||
_('Error!'),
|
||||
_("The deposit '%s' is in valid state, so you must "
|
||||
"cancel it before deleting it.")
|
||||
% deposit.name)
|
||||
return super(account_check_deposit, self).unlink(
|
||||
cr, uid, ids, context=context)
|
||||
|
||||
def backtodraft(self, cr, uid, ids, context=None):
|
||||
for deposit in self.browse(cr, uid, ids, context=context):
|
||||
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.reconcile_id:
|
||||
line.reconcile_id.unlink()
|
||||
deposit.move_id.unlink()
|
||||
deposit.write({'state': 'draft'})
|
||||
return True
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if vals.get('name', '/') == '/':
|
||||
vals['name'] = self.pool['ir.sequence'].\
|
||||
next_by_code(cr, uid, 'account.check.deposit')
|
||||
return super(account_check_deposit, self).\
|
||||
create(cr, uid, vals, context=context)
|
||||
|
||||
def _prepare_account_move_vals(self, cr, uid, deposit, context=None):
|
||||
date = deposit.deposit_date
|
||||
period_obj = self.pool['account.period']
|
||||
period_ids = period_obj.find(cr, uid, dt=date, context=context)
|
||||
# period_ids will always have a value, cf the code of find()
|
||||
move_vals = {
|
||||
'journal_id': deposit.journal_id.id,
|
||||
'date': date,
|
||||
'period_id': period_ids[0],
|
||||
'name': _('Check Deposit %s') % deposit.name,
|
||||
'ref': deposit.name,
|
||||
}
|
||||
return move_vals
|
||||
|
||||
def _prepare_move_line_vals(
|
||||
self, cr, uid, line, context=None):
|
||||
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,
|
||||
}
|
||||
|
||||
def _prepare_counterpart_move_lines_vals(
|
||||
self, cr, uid, deposit, total_debit, total_amount_currency,
|
||||
context=None):
|
||||
return {
|
||||
'name': _('Check Deposit %s') % deposit.name,
|
||||
'debit': total_debit,
|
||||
'credit': 0.0,
|
||||
'account_id': deposit.company_id.check_deposit_account_id.id,
|
||||
'partner_id': False,
|
||||
'currency_id': deposit.currency_none_same_company_id.id or False,
|
||||
'amount_currency': total_amount_currency,
|
||||
}
|
||||
|
||||
def validate_deposit(self, cr, uid, ids, context=None):
|
||||
am_obj = self.pool['account.move']
|
||||
aml_obj = self.pool['account.move.line']
|
||||
if context is None:
|
||||
context = {}
|
||||
for deposit in self.browse(cr, uid, ids, context=context):
|
||||
move_vals = self._prepare_account_move_vals(
|
||||
cr, uid, deposit, context=context)
|
||||
context['journal_id'] = move_vals['journal_id']
|
||||
context['period_id'] = move_vals['period_id']
|
||||
move_id = am_obj.create(cr, uid, move_vals, context=context)
|
||||
total_debit = 0.0
|
||||
total_amount_currency = 0.0
|
||||
to_reconcile_line_ids = []
|
||||
for line in deposit.check_payment_ids:
|
||||
total_debit += line.debit
|
||||
total_amount_currency += line.amount_currency
|
||||
line_vals = self._prepare_move_line_vals(
|
||||
cr, uid, line, context=context)
|
||||
line_vals['move_id'] = move_id
|
||||
move_line_id = aml_obj.create(
|
||||
cr, uid, line_vals, context=context)
|
||||
to_reconcile_line_ids.append([line.id, move_line_id])
|
||||
|
||||
# Create counter-part
|
||||
if not deposit.company_id.check_deposit_account_id:
|
||||
raise orm.except_orm(
|
||||
_('Configuration Error:'),
|
||||
_("Missing Account for Check Deposits on the "
|
||||
"company '%s'.") % deposit.company_id.name)
|
||||
|
||||
counter_vals = self._prepare_counterpart_move_lines_vals(
|
||||
cr, uid, deposit, total_debit, total_amount_currency,
|
||||
context=context)
|
||||
counter_vals['move_id'] = move_id
|
||||
aml_obj.create(cr, uid, counter_vals, context=context)
|
||||
|
||||
am_obj.post(cr, uid, [move_id], context=context)
|
||||
deposit.write({'state': 'done', 'move_id': move_id})
|
||||
# We have to reconcile after post()
|
||||
for reconcile_line_ids in to_reconcile_line_ids:
|
||||
aml_obj.reconcile(
|
||||
cr, uid, reconcile_line_ids, context=context)
|
||||
return True
|
||||
|
||||
def onchange_company_id(
|
||||
self, cr, uid, ids, company_id, currency_id, context=None):
|
||||
vals = {}
|
||||
if company_id:
|
||||
company = self.pool['res.company'].browse(
|
||||
cr, uid, company_id, context=context)
|
||||
if currency_id:
|
||||
if company.currency_id.id == currency_id:
|
||||
vals['currency_none_same_company_id'] = False
|
||||
else:
|
||||
vals['currency_none_same_company_id'] = currency_id
|
||||
partner_bank_ids = self.pool['res.partner.bank'].search(
|
||||
cr, uid, [('company_id', '=', company_id)], context=context)
|
||||
if len(partner_bank_ids) == 1:
|
||||
vals['partner_bank_id'] = partner_bank_ids[0]
|
||||
else:
|
||||
vals['currency_none_same_company_id'] = False
|
||||
vals['partner_bank_id'] = False
|
||||
return {'value': vals}
|
||||
|
||||
def onchange_journal_id(self, cr, uid, ids, journal_id, context=None):
|
||||
vals = {}
|
||||
if journal_id:
|
||||
journal = self.pool['account.journal'].browse(
|
||||
cr, uid, journal_id, context=context)
|
||||
vals['journal_default_account_id'] = \
|
||||
journal.default_debit_account_id.id
|
||||
if journal.currency:
|
||||
vals['currency_id'] = journal.currency.id
|
||||
else:
|
||||
vals['currency_id'] = journal.company_id.currency_id.id
|
||||
else:
|
||||
vals['journal_default_account_id'] = False
|
||||
return {'value': vals}
|
||||
|
||||
def onchange_currency_id(
|
||||
self, cr, uid, ids, currency_id, company_id, context=None):
|
||||
vals = {}
|
||||
if currency_id and company_id:
|
||||
company = self.pool['res.company'].browse(
|
||||
cr, uid, company_id, context=context)
|
||||
if company.currency_id.id == currency_id:
|
||||
vals['currency_none_same_company_id'] = False
|
||||
else:
|
||||
vals['currency_none_same_company_id'] = currency_id
|
||||
else:
|
||||
vals['currency_none_same_company_id'] = False
|
||||
return {'value': vals}
|
||||
|
||||
|
||||
class account_move_line(orm.Model):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
_columns = {
|
||||
'check_deposit_id': fields.many2one(
|
||||
'account.check.deposit',
|
||||
'Check Deposit'),
|
||||
}
|
||||
|
||||
|
||||
class res_company(orm.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
_columns = {
|
||||
'check_deposit_account_id': fields.many2one(
|
||||
'account.account', 'Account for Check Deposits',
|
||||
domain=[
|
||||
('type', '<>', 'view'),
|
||||
('type', '<>', 'closed'),
|
||||
('reconcile', '=', True)]),
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
account_check_deposit for Odoo/OpenERP
|
||||
Copyright (C) 2014-2015 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
@@ -9,21 +8,12 @@
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
|
||||
<record id="check_received_journal_seq" model="ir.sequence">
|
||||
<field name="name">Journal Check Received</field>
|
||||
<field name="prefix">CHK/</field>
|
||||
<field name="padding">6</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
|
||||
<!-- The user will have to configure manually the default_credit_account_id
|
||||
and default_debit_account_id, we can't do that for him -->
|
||||
<record id="check_received_journal" model="account.journal">
|
||||
<field name="name">Check Received</field>
|
||||
<field name="code">CHK</field>
|
||||
<field name="type">bank</field>
|
||||
<field name="sequence_id" ref="check_received_journal_seq"/>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
</record>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
account_check_deposit for Odoo/OpenERP
|
||||
account_check_deposit for Odoo
|
||||
Copyright (C) 2012-2015 Akretion (http://www.akretion.com/)
|
||||
@author: Benoît GUILLOT <benoit.guillot@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
3
account_check_deposit/models/__init__.py
Normal file
3
account_check_deposit/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_deposit
|
||||
281
account_check_deposit/models/account_deposit.py
Normal file
281
account_check_deposit/models/account_deposit.py
Normal file
@@ -0,0 +1,281 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# account_check_deposit for Odoo
|
||||
# Copyright (C) 2012-2015 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>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
from openerp import models, fields, api, _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.exceptions import ValidationError
|
||||
from openerp.exceptions import Warning as 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_id.reconcile_id')
|
||||
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_id:
|
||||
if line.debit > 0 and line.reconcile_id:
|
||||
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')],
|
||||
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)
|
||||
partner_bank_id = fields.Many2one(
|
||||
'res.partner.bank', string='Bank Account', required=True,
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
states={'done': [('readonly', '=', True)]})
|
||||
line_ids = fields.One2many(
|
||||
'account.move.line', related='move_id.line_id',
|
||||
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.reconcile_id:
|
||||
line.reconcile_id.unlink()
|
||||
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):
|
||||
date = deposit.deposit_date
|
||||
period_obj = self.env['account.period']
|
||||
period_ids = period_obj.find(dt=date)
|
||||
# period_ids will always have a value, cf the code of find()
|
||||
move_vals = {
|
||||
'journal_id': deposit.journal_id.id,
|
||||
'date': date,
|
||||
'period_id': period_ids[0].id,
|
||||
'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):
|
||||
return {
|
||||
'name': _('Check Deposit %s') % deposit.name,
|
||||
'debit': total_debit,
|
||||
'credit': 0.0,
|
||||
'account_id': deposit.company_id.check_deposit_account_id.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']
|
||||
aml_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 = aml_obj.create(line_vals)
|
||||
to_reconcile_lines.append(line + move_line)
|
||||
|
||||
# Create counter-part
|
||||
if not deposit.company_id.check_deposit_account_id:
|
||||
raise UserError(
|
||||
_("Missing Account for Check Deposits on the "
|
||||
"company '%s'.") % deposit.company_id.name)
|
||||
|
||||
counter_vals = self._prepare_counterpart_move_lines_vals(
|
||||
deposit, total_debit, total_amount_currency)
|
||||
counter_vals['move_id'] = move.id
|
||||
aml_obj.create(counter_vals)
|
||||
|
||||
move.post()
|
||||
deposit.write({'state': 'done', 'move_id': move.id})
|
||||
# We have to reconcile after post()
|
||||
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:
|
||||
partner_banks = self.env['res.partner.bank'].search(
|
||||
[('company_id', '=', self.company_id.id)])
|
||||
if len(partner_banks) == 1:
|
||||
self.partner_bank_id = partner_banks[0]
|
||||
else:
|
||||
self.partner_bank_id = False
|
||||
|
||||
@api.onchange('journal_id')
|
||||
def onchange_journal_id(self):
|
||||
if self.journal_id:
|
||||
if self.journal_id.currency:
|
||||
self.currency_id = self.journal_id.currency
|
||||
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)
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
check_deposit_account_id = fields.Many2one(
|
||||
'account.account', string='Account for Check Deposits', copy=False,
|
||||
domain=[
|
||||
('type', '<>', 'view'),
|
||||
('type', '<>', 'closed'),
|
||||
('reconcile', '=', True)])
|
||||
@@ -34,18 +34,15 @@
|
||||
<group name="left">
|
||||
<field name="deposit_date" />
|
||||
<field name="journal_id"
|
||||
widget="selection"
|
||||
on_change="onchange_journal_id(journal_id, context)"/>
|
||||
widget="selection"/>
|
||||
<field name="journal_default_account_id"
|
||||
invisible="1"/>
|
||||
<field name="currency_id"
|
||||
groups="base.group_multi_currency"
|
||||
on_change="onchange_currency_id(currency_id, company_id, context)"/>
|
||||
groups="base.group_multi_currency"/>
|
||||
<field name="partner_bank_id"/>
|
||||
</group>
|
||||
<group name="right">
|
||||
<field name="company_id"
|
||||
on_change="onchange_company_id(company_id, currency_id, context)"
|
||||
groups="base.group_multi_company"/>
|
||||
<field name="currency_none_same_company_id"
|
||||
invisible="1"/>
|
||||
Reference in New Issue
Block a user