From c8ff9764726e4858c9fb95cbb5b303ab22027728 Mon Sep 17 00:00:00 2001 From: Stefan Rijnhart Date: Mon, 12 Nov 2012 13:09:48 +0100 Subject: [PATCH] [ADD] module bank_statement_instant_voucher --- bank_statement_instant_voucher/__init__.py | 1 + bank_statement_instant_voucher/__openerp__.py | 56 ++++ bank_statement_instant_voucher/i18n/nl.po | 158 ++++++++++ .../model/__init__.py | 2 + .../model/account_bank_statement_line.py | 48 +++ .../model/account_voucher_instant.py | 273 ++++++++++++++++++ .../view/account_bank_statement_line.xml | 21 ++ .../view/account_voucher_instant.xml | 48 +++ 8 files changed, 607 insertions(+) create mode 100644 bank_statement_instant_voucher/__init__.py create mode 100644 bank_statement_instant_voucher/__openerp__.py create mode 100644 bank_statement_instant_voucher/i18n/nl.po create mode 100644 bank_statement_instant_voucher/model/__init__.py create mode 100644 bank_statement_instant_voucher/model/account_bank_statement_line.py create mode 100644 bank_statement_instant_voucher/model/account_voucher_instant.py create mode 100644 bank_statement_instant_voucher/view/account_bank_statement_line.xml create mode 100644 bank_statement_instant_voucher/view/account_voucher_instant.xml diff --git a/bank_statement_instant_voucher/__init__.py b/bank_statement_instant_voucher/__init__.py new file mode 100644 index 000000000..16e8b082f --- /dev/null +++ b/bank_statement_instant_voucher/__init__.py @@ -0,0 +1 @@ +import model diff --git a/bank_statement_instant_voucher/__openerp__.py b/bank_statement_instant_voucher/__openerp__.py new file mode 100644 index 000000000..5a811d541 --- /dev/null +++ b/bank_statement_instant_voucher/__openerp__.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2012 Therp BV (). +# +# 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 . +# +############################################################################## +{ + "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: diff --git a/bank_statement_instant_voucher/i18n/nl.po b/bank_statement_instant_voucher/i18n/nl.po new file mode 100644 index 000000000..d6cfa507e --- /dev/null +++ b/bank_statement_instant_voucher/i18n/nl.po @@ -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" + diff --git a/bank_statement_instant_voucher/model/__init__.py b/bank_statement_instant_voucher/model/__init__.py new file mode 100644 index 000000000..bb3faa358 --- /dev/null +++ b/bank_statement_instant_voucher/model/__init__.py @@ -0,0 +1,2 @@ +import account_voucher_instant +import account_bank_statement_line diff --git a/bank_statement_instant_voucher/model/account_bank_statement_line.py b/bank_statement_instant_voucher/model/account_bank_statement_line.py new file mode 100644 index 000000000..f2f655c49 --- /dev/null +++ b/bank_statement_instant_voucher/model/account_bank_statement_line.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2012 Therp BV (). +# +# 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 . +# +############################################################################## + +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 + diff --git a/bank_statement_instant_voucher/model/account_voucher_instant.py b/bank_statement_instant_voucher/model/account_voucher_instant.py new file mode 100644 index 000000000..106e73627 --- /dev/null +++ b/bank_statement_instant_voucher/model/account_voucher_instant.py @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2012 Therp BV (). +# +# 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 . +# +############################################################################## + +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'} diff --git a/bank_statement_instant_voucher/view/account_bank_statement_line.xml b/bank_statement_instant_voucher/view/account_bank_statement_line.xml new file mode 100644 index 000000000..0e467c0f0 --- /dev/null +++ b/bank_statement_instant_voucher/view/account_bank_statement_line.xml @@ -0,0 +1,21 @@ + + + + + Add instant voucher button to bank statement line on statement form + + account.bank.statement + form + + + +