[ADD] module bank_statement_instant_voucher

This commit is contained in:
Stefan Rijnhart
2012-11-12 13:09:48 +01:00
parent df8d20c359
commit c8ff976472
8 changed files with 607 additions and 0 deletions

View File

@@ -0,0 +1 @@
import model

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2012 Therp BV (<http://therp.nl>).
#
# 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/>.
#
##############################################################################
{
"name": "Bank statement instant voucher",
"version": "1.0r028",
"author": "Therp BV",
"category": 'Base',
'complexity': "normal",
"description": """
This module adds a new button on the bank statement line that allows the
accountant to instantly create a sales or purchase voucher based on the
values of the bank statement line.
This module does not depend on account_banking, but if this module is
installed, the bank statement line will be reconciled automatically
in the confirmation step of the wizard.
If account_banking is not installed, the accountant will still have to
reconcile the associated move line with the move line from the bank
statement line manually.
If the wizard is cancelled,the created voucher will be deleted again.
Known limitations:
Currency conversion and payment difference writeoff are not yet
supported.
""",
'website': 'http://therp.nl',
'images': [],
'depends': ['account_voucher'],
'data': [
'view/account_voucher_instant.xml',
'view/account_bank_statement_line.xml',
],
"license": 'AGPL-3',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@@ -0,0 +1,158 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * bank_statement_instant_voucher
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 6.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-11-12 10:42+0000\n"
"PO-Revision-Date: 2012-11-12 10:42+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: bank_statement_instant_voucher
#: view:account.voucher.instant:0
msgid "Confirm"
msgstr "Bevestig"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:71
#, python-format
msgid "Voucher for statement line %s.%s"
msgstr "Journaalbon voor bankafschrift %s.%s"
#. module: bank_statement_instant_voucher
#: field:account.voucher.instant,state:0
msgid "State"
msgstr "Status"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:201
#, python-format
msgid "The voucher could not be posted."
msgstr "De journaalbon kon niet worden bevestigd."
#. module: bank_statement_instant_voucher
#: selection:account.voucher.instant,state:0
msgid "ready"
msgstr "ready"
#. module: bank_statement_instant_voucher
#: model:ir.model,name:bank_statement_instant_voucher.model_account_voucher_instant
msgid "Instant Voucher"
msgstr "Instant journaalbon"
#. module: bank_statement_instant_voucher
#: selection:account.voucher.instant,state:0
msgid "confirm"
msgstr "confirm"
#. module: bank_statement_instant_voucher
#: view:account.bank.statement:0
#: model:ir.actions.act_window,name:bank_statement_instant_voucher.act_instant_voucher
msgid "Create matching voucher"
msgstr "Bijpassende journaalbon aanmaken"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:137
#, python-format
msgid "Cannot determine statement line"
msgstr "Kan de bankafschriftregel niet afleiden"
#. module: bank_statement_instant_voucher
#: selection:account.voucher.instant,state:0
msgid "init"
msgstr "init"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:209
#, python-format
msgid "The voucher's move line could not be posted."
msgstr "De journaalposten van de journaalbon konden niet geboekt worden"
#. module: bank_statement_instant_voucher
#: model:ir.model,name:bank_statement_instant_voucher.model_account_bank_statement_line
msgid "Bank Statement Line"
msgstr "Bankafschriftregel"
#. module: bank_statement_instant_voucher
#: view:account.voucher.instant:0
msgid "Create voucher"
msgstr "Journaalbon aanmaken"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:214
#, python-format
msgid "The amount on the bank statement line needs to be the same as on the voucher. Write-off is not yet supported."
msgstr "Het bedrag op het bankafschrift dient gelijk te zijn aan het bedrag op de journaalbon. Afschrijven is nog niet ondersteund."
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:59
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:136
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:190
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:200
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:208
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:213
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:224
#, python-format
msgid "Error"
msgstr "Fout"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:60
#, python-format
msgid "No %s journal defined"
msgstr "Geen %s-dagboek ingesteld"
#. module: bank_statement_instant_voucher
#: constraint:account.bank.statement.line:0
msgid "The amount of the voucher must be the same amount as the one on the statement line"
msgstr "Het bedrag op de bon moet hetzelfde bedrag zijn dat vermeld staat op de afschriftregel"
#. module: bank_statement_instant_voucher
#: field:account.voucher.instant,balance:0
msgid "Balance"
msgstr "Balans"
#. module: bank_statement_instant_voucher
#: field:account.voucher.instant,statement_line_id:0
msgid "Bank statement line"
msgstr "Bankafschriftregel"
#. module: bank_statement_instant_voucher
#: field:account.voucher.instant,ref:0
msgid "Reference"
msgstr "Referentie"
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:191
#, python-format
msgid "Currency on the bank statement line needs to be the same as on the voucher. Currency conversion is not yet supported."
msgstr "De valuta van de bankafschriftregel dient gelijk te zijn aan die op de journaalbon. Omrekenen tussen valuta is nog niet ondersteund."
#. module: bank_statement_instant_voucher
#: code:addons/bank_statement_instant_voucher/model/account_voucher_instant.py:225
#, python-format
msgid "Cannot match a confirmed statement line"
msgstr "Kan een bevestigde bankafschriftregel niet afletteren"
#. module: bank_statement_instant_voucher
#: field:account.voucher.instant,voucher_id:0
msgid "Voucher"
msgstr "Journaalbon"
#. module: bank_statement_instant_voucher
#: view:account.voucher.instant:0
msgid "Cancel"
msgstr "Annuleer"
#. module: bank_statement_instant_voucher
#: field:account.voucher.instant,partner_id:0
msgid "Partner"
msgstr "Relatie"

View File

@@ -0,0 +1,2 @@
import account_voucher_instant
import account_bank_statement_line

View File

@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2012 Therp BV (<http://therp.nl>).
#
# 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 osv import osv, fields
class account_bank_statement_line(osv.osv):
_inherit = 'account.bank.statement.line'
def create_instant_voucher(self, cr, uid, ids, context=None):
res = False
if ids:
if isinstance(ids, (int, float)):
ids = [ids]
if context is None:
context = {}
local_context = context.copy()
context['active_id'] = ids[0]
wizard_obj = self.pool.get('account.voucher.instant')
res = {
'name': wizard_obj._description,
'view_type': 'form',
'view_mode': 'form',
'res_model': wizard_obj._name,
'domain': [],
'context': context,
'type': 'ir.actions.act_window',
'target': 'new',
'res_id': False,
'nodestroy': False,
}
return res

View File

@@ -0,0 +1,273 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright (C) 2012 Therp BV (<http://therp.nl>).
#
# 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 osv import osv, fields
from tools.translate import _
import decimal_precision as dp
class instant_voucher(osv.osv_memory):
_name = 'account.voucher.instant'
_description = 'Instant Voucher'
def cancel(self, cr, uid, ids, context=None):
"""
Delete the voucher and close window
"""
instant = self.browse(cr, uid, ids[0], context=context)
if instant.voucher_id:
self.pool.get('account.voucher').cancel_voucher(
cr, uid, [instant.voucher_id.id], context=context)
self.pool.get('account.voucher').unlink(
cr, uid, [instant.voucher_id.id], context=context)
return {'type': 'ir.actions.act_window_close'}
def create_voucher(self, cr, uid, ids, context=None):
"""
Create a fully fledged voucher counterpart for the
statement line. User only needs to process taxes and may
adapt cost/income account.
"""
voucher_pool = self.pool.get('account.voucher')
period_pool = self.pool.get('account.period')
instant = self.browse(cr, uid, ids[0], context=context)
line = instant.statement_line_id
voucher_type = line.amount < 0 and 'purchase' or 'sale'
journal_ids = self.pool.get('account.journal').search(
cr, uid, [('company_id', '=', line.company_id.id),
('type', '=', voucher_type)])
if not journal_ids:
osv.exept_osv(
_('Error'),
_('No %s journal defined') % voucher_type)
journal = self.pool.get('account.journal').browse(
cr, uid, journal_ids[0], context=context)
if journal.type in ('sale', 'sale_refund'):
line_account_id = (journal.default_credit_account_id and
journal.default_credit_account_id.id or False)
elif journal.type in ('purchase', 'expense', 'purchase_refund'):
line_account_id = (journal.default_debit_account_id and
journal.default_debit_account_id.id or False)
vals = {
'name': _('Voucher for statement line %s.%s') % (line.statement_id.name, line.name),
'reference': line.ref or False,
'company_id': line.company_id.id,
'partner_id': instant.partner_id.id,
'date': line.date or res.get('line.date', False),
'account_id': line.account_id.id,
'type': voucher_type,
'line_ids': [(0, 0, {'amount': abs(line.amount),
'account_id': line_account_id,
'type': line.amount < 0 and 'dr' or 'cr',
'name': line.ref or False,
})],
'amount': line.amount and abs(line.amount) or res.get('amount', False),
'journal_id': journal_ids[0],
}
if vals['date']:
period_ids = period_pool.find(cr, uid, vals['date'], context=context)
if period_ids:
vals['period_id'] = period_ids[0]
voucher_id = voucher_pool.create(
cr, uid, vals, context=context)
self.write(
cr, uid, ids[0],
{'voucher_id': voucher_id,
'state': 'ready',
}, context=context)
return {
'name': self._description,
'view_type': 'form',
'view_mode': 'form',
'res_model': self._name,
'domain': [],
'context': context,
'type': 'ir.actions.act_window',
'target': 'new',
'res_id': ids[0],
'nodestroy': False,
}
def dummy(self, cr, uid, ids, context=None):
return {
'name': self._description,
'view_type': 'form',
'view_mode': 'form',
'res_model': self._name,
'domain': [],
'context': context,
'type': 'ir.actions.act_window',
'target': 'new',
'res_id': ids[0],
'nodestroy': False,
}
def default_get(self, cr, uid, fields_list, context=None):
"""
Gather sane default values from the originating statement line
"""
res = super(instant_voucher, self).default_get(
cr, uid, fields_list, context=context)
if 'statement_line_id' in fields_list:
res['statement_line_id'] = (
context.get('active_id') or
context.get('active_ids') and context.get('active_ids')[0])
if not res['statement_line_id']:
raise osv.except_osv(
_('Error'),
_('Cannot determine statement line'))
line = self.pool.get('account.bank.statement.line').browse(
cr, uid, res['statement_line_id'], context=context)
if 'balance' in fields_list:
res['balance'] = line.amount
if 'ref' in fields_list:
res['ref'] = line.ref
if 'partner_id' in fields_list:
if line.partner_id:
res['partner_id'] = line.partner_id.id
return res
def _get_balance(self, cr, uid, ids, field_name, args, context=None):
"""
Compute the expected residual
TODO: currency conversion
"""
res = {}
for instant in self.browse(cr, uid, ids, context=context):
if instant.voucher_id and instant.voucher_id.state == 'posted':
amount = instant.statement_line_id.amount
counteramount = 0.0
for line in instant.voucher_id.move_ids:
if line.account_id.id == instant.statement_line_id.account_id.id:
counteramount = line.debit - line.credit
for line in instant.voucher_id.move_ids:
if line.account_id.id == instant.statement_line_id.account_id.id:
counteramount = line.debit - line.credit
else:
amount = abs(instant.statement_line_id.amount)
counteramount = abs(instant.voucher_id and instant.voucher_id.amount or 0.0)
res[instant.id] = amount - counteramount
return res
def confirm(self, cr, uid, ids, context=None):
"""
Post the voucher if necessary
Post the voucher's move lines if necessary
Sanity checks on currency and residual = 0.0
If Banking Addons are installed, perform matching and reconciliation.
If not, the user is left to manual reconciliation of OpenERP.
"""
statement_line_obj = self.pool.get('account.bank.statement.line')
voucher_obj = self.pool.get('account.voucher')
move_obj = self.pool.get('account.move')
instant = self.browse(cr, uid, ids[0], context=context)
voucher_currency = (instant.voucher_id.currency_id and
instant.voucher_id.currency_id or
instant.voucher_id.company_id.currency_id)
if (instant.statement_line_id.statement_id.currency.id !=
voucher_currency.id):
raise osv.except_osv(
_("Error"),
_("Currency on the bank statement line needs to be the "
"same as on the voucher. Currency conversion is not yet "
"supported."))
if instant.voucher_id.state != 'posted':
voucher_obj.proforma_voucher(
cr, uid, [instant.voucher_id.id], context=context)
instant.refresh()
if instant.voucher_id.state != 'posted':
raise osv.except_osv(
_("Error"),
_("The voucher could not be posted."))
if instant.voucher_id.move_id.state != 'posted':
move_obj.post(
cr, uid, [instant.voucher_id.move_id.id], context=context)
instant.refresh()
if instant.voucher_id.move_id.state != 'posted':
raise osv.except_osv(
_("Error"),
_("The voucher's move line could not be posted."))
if not self.pool.get('res.currency').is_zero(
cr, uid, voucher_currency, instant.balance):
raise osv.except_osv(
_("Error"),
_("The amount on the bank statement line needs to be the "
"same as on the voucher. Write-off is not yet "
"supported."))
# Banking addons integration:
# Gather the info needed to match the bank statement line
# and trigger its posting and reconciliation.
if ('import_transaction_id' in statement_line_obj._columns
and instant.statement_line_id.import_transaction_id):
if instant.statement_line_id.state == 'confirmed':
raise osv.except_osv(
_("Error"),
_("Cannot match a confirmed statement line"))
for line in instant.voucher_id.move_ids:
if line.account_id.id == instant.statement_line_id.account_id.id:
self.pool.get('banking.import.transaction').write(
cr, uid, instant.statement_line_id.import_transaction_id.id,
{
'move_line_id': line.id,
'move_line_ids': [(6, 0, [line.id])],
'match_type': 'move',
'invoice_id': False,
'invoice_ids': [(6, 0, [])],
}, context=context)
statement_line_obj.confirm(
cr, uid, [instant.statement_line_id.id], context=context)
break
return {'type': 'ir.actions.act_window_close'}
_columns = {
'balance': fields.function(
_get_balance,
type='float',
digits_compute=dp.get_precision('Account'),
string="Balance",),
'partner_id': fields.many2one(
'res.partner',
'Partner',
required=True),
'statement_line_id': fields.many2one(
'account.bank.statement.line',
'Bank statement line',
readonly=True),
'ref': fields.related(
'statement_line_id', 'ref',
type="char", size="48",
readonly=True,
string="Reference"),
'voucher_id': fields.many2one(
'account.voucher',
'Voucher',
readonly=True),
'state': fields.selection(
[('init', 'init'),
('ready', 'ready'),
('confirm', 'confirm')],
'State'),
}
_defaults = {'state': 'init'}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_banking_bank_statement_form" model="ir.ui.view">
<field name="name">Add instant voucher button to bank statement line on statement form</field>
<field name="inherit_id" ref="account.view_bank_statement_form" />
<field name="model">account.bank.statement</field>
<field name="type">form</field>
<field name="priority" eval="30"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page/field[@name='line_ids']/tree/field[@name='voucher_id']"
position="before">
<button name="create_instant_voucher" states="draft"
string="Create matching voucher"
icon="terp-gtk-jump-to-ltr"
type="object"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="instant_voucher_form" model="ir.ui.view">
<field name="name">Instant voucher form view</field>
<field name="model">account.voucher.instant</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form>
<field name="state" invisible="1" readonly="1"/>
<field name="statement_line_id"/>
<field name="ref"/>
<newline/>
<field name="partner_id"/>
<field name="balance"/>
<newline/>
<field name="voucher_id"
context="{'statement_line_id': statement_line_id,
'form_view_ref': 'account_voucher.view_voucher_form'}"
/>
<newline/>
<newline/>
<button icon="gtk-cancel"
string="Cancel"
name="cancel"
type="object"/>
<button icon="gtk-ok" string="Confirm"
states="ready"
name="confirm"
type="object"
/>
<button icon="gtk-ok" string="Create voucher"
states="init"
name="create_voucher"
type="object"
/>
</form>
</field>
</record>
<act_window name="Create matching voucher"
res_model="account.voucher.instant"
src_model="account.bank.statement.line"
view_mode="form"
target="new"
key2="client_action_multi"
id="act_instant_voucher"/>
</data>
</openerp>