diff --git a/account_banking/__terp__.py b/account_banking/__terp__.py index d365bef1e..b00d161a2 100644 --- a/account_banking/__terp__.py +++ b/account_banking/__terp__.py @@ -35,8 +35,6 @@ 'update_xml': [ 'security/ir.model.access.csv', 'data/account_banking_data.xml', - 'account_banking_import_wizard.xml', - 'account_banking_payment_wizard.xml', 'wizard/bank_import_view.xml', 'account_banking_view.xml', 'account_banking_workflow.xml', diff --git a/account_banking/account_banking.py b/account_banking/account_banking.py index 96a5bf3b8..00435bc2b 100644 --- a/account_banking/account_banking.py +++ b/account_banking/account_banking.py @@ -203,58 +203,16 @@ class payment_mode_type(osv.osv): 'bank_type_payment_type_rel', 'pay_type_id','bank_type_id', 'Suitable bank types', required=True), + 'ir_model_id': fields.many2one( + 'ir.model', 'Payment wizard', + help=('Select the Payment Wizard for payments of this type. ' + 'Leave empty for manual processing'), + domain=[('osv_memory', '=', True)], + ), } payment_mode_type() -class payment_order_create(osv.osv_memory): - _inherit = "payment.order.create" - - def create_payment(self, cr, uid, ids, context=None): - """ This method is equal to the one in - account_payment/wizard/account_payment_order.py - except for a fix in passing the payment mode to line2bank() - """ - order_obj = self.pool.get('payment.order') - line_obj = self.pool.get('account.move.line') - payment_obj = self.pool.get('payment.line') - if context is None: - context = {} - data = self.read(cr, uid, ids, [], context=context)[0] - line_ids = data['entries'] - if not line_ids: - return {'type': 'ir.actions.act_window_close'} - - payment = order_obj.browse(cr, uid, context['active_id'], context=context) - ### account banking - # t = None - # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context) - line2bank = line_obj.line2bank(cr, uid, line_ids, payment.mode.id, context) - ### end account banking - - ## Finally populate the current payment with new lines: - for line in line_obj.browse(cr, uid, line_ids, context=context): - if payment.date_prefered == "now": - #no payment date => immediate payment - date_to_pay = False - elif payment.date_prefered == 'due': - date_to_pay = line.date_maturity - elif payment.date_prefered == 'fixed': - date_to_pay = payment.date_scheduled - payment_obj.create(cr, uid,{ - 'move_line_id': line.id, - 'amount_currency': line.amount_to_pay, - 'bank_id': line2bank.get(line.id), - 'order_id': payment.id, - 'partner_id': line.partner_id and line.partner_id.id or False, - 'communication': line.ref or '/', - 'date': date_to_pay, - 'currency': line.invoice and line.invoice.currency_id.id or False, - }, context=context) - return {'type': 'ir.actions.act_window_close'} - -payment_order_create() - class payment_mode(osv.osv): ''' Restoring the payment type from version 5, used to select the export wizard (if any) ''' @@ -794,41 +752,7 @@ class payment_order(osv.osv): ''' _inherit = 'payment.order' - def _get_id_proxy(self, cr, uid, ids, name, args, context=None): - return dict([(id, id) for id in ids]) - _columns = { - # - # 'id_proxy' is simply a reference to the resource's id - # for the following reason: - # - # The GTK client 6.0 lacks necessary support for old style wizards. - # It does not pass the resource's id if the wizard is called from - # a button on a form. - # - # As a workaround, we pass the payment order id in the context - # Evaluating 'id' in the context in the webclient on a form - # in readonly mode dies with an error "Invalid Syntax", because 'id' - # evaluates to "" and the resource's field - # values are not passed to eval in readonly mode at all. - # See /addons/openerp/static/javascript/form.js line 308 - # - # Evaluating any other variable in the webclient on a form in - # readonly mode fails silently. That is actually ok, because the - # webclient still supports passing the resource id when an old style - # wizard is called. - # - # Therefore, if we want to pass the id in the context safely we have to - # pass it under a different name. - # - # TODO: migrate old style wizards to osv_memory - # - 'id_proxy': fields.function( - _get_id_proxy, method=True, string='Copy ID', type='integer', - # Would have used store={}, but the system does not seem to - # generate triggers on the field 'id'. - store=False, - ), 'date_scheduled': fields.date( 'Scheduled date if fixed', states={ @@ -904,25 +828,39 @@ class payment_order(osv.osv): If type is manual. just confirm the order. Previously (pre-v6) in account_payment/wizard/wizard_pay.py """ + if context == None: + context={} result = {} - obj_model = self.pool.get('ir.model.data') - order = self.browse(cr, uid, ids[0], context) - t = order.mode and order.mode.type.code or 'manual' - res_id = False - if t != 'manual': - gw = self.get_wizard(t) - if gw: - module, wizard = gw - wiz_id = obj_model._get_id(cr, uid, module, wizard) - if wiz_id: - res_id = obj_model.read( - cr, uid, [wiz_id], ['res_id'])[0]['res_id'] - if res_id: - result = self.pool.get('ir.actions.wizard').read( - cr, uid, [res_id])[0] + orders = self.browse(cr, uid, ids, context) + order = orders[0] + # check if a wizard is defined for the first order + if order.mode.type and order.mode.type.ir_model_id: + context['active_ids'] = ids + wizard_model = order.mode.type.ir_model_id.model + wizard_obj = self.pool.get(wizard_model) + wizard_id = wizard_obj.create(cr, uid, {}, context) + result = { + 'name': wizard_obj._description or 'Payment Order Export', + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': wizard_model, + 'domain': [], + 'context': context, + 'type': 'ir.actions.act_window', + 'target': 'new', + 'res_id': wizard_id, + 'nodestroy': True, + } else: + # should all be manual orders without type or wizard model + for order in orders[1:]: + if order.mode.type and order.mode.type.ir_model_id: + raise osv.except_osv( + _('Error'), + _('You can only combine payment orders of the same type') + ) + # process manual payments self.action_sent(cr, uid, ids, context) - result['nodestroy'] = True return result def _write_payment_lines(self, cursor, uid, ids, **kwargs): diff --git a/account_banking/account_banking_import_wizard.xml b/account_banking/account_banking_import_wizard.xml deleted file mode 100644 index 8cbe24646..000000000 --- a/account_banking/account_banking_import_wizard.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/account_banking/account_banking_payment_wizard.xml b/account_banking/account_banking_payment_wizard.xml deleted file mode 100644 index eebfe0efb..000000000 --- a/account_banking/account_banking_payment_wizard.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/account_banking/account_banking_view.xml b/account_banking/account_banking_view.xml index f1799940c..a0c02b3d0 100644 --- a/account_banking/account_banking_view.xml +++ b/account_banking/account_banking_view.xml @@ -143,6 +143,15 @@ action="wizard_account_banking_import_file" sequence="15"/> + + + + + @@ -403,6 +423,7 @@ + diff --git a/account_banking/data/account_banking_data.xml b/account_banking/data/account_banking_data.xml index e17221a52..8906d6c34 100644 --- a/account_banking/data/account_banking_data.xml +++ b/account_banking/data/account_banking_data.xml @@ -17,11 +17,18 @@ Ratio: one can have bank accounts in foreign banks. Foreign addresses not automatically involve international banking. --> - + country_id + + + Manual Bank Transfer + BANKMAN + + diff --git a/account_banking/security/ir.model.access.csv b/account_banking/security/ir.model.access.csv index 72950a99d..be3af98bf 100644 --- a/account_banking/security/ir.model.access.csv +++ b/account_banking/security/ir.model.access.csv @@ -1,3 +1,5 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" "access_account_banking_settings","account.banking.account.settings","model_account_banking_account_settings","account.group_account_manager",1,1,1,1 +"access_account_banking_settings_user","account.banking.account.settings user","model_account_banking_account_settings","account.group_account_user",1,0,0,0 "access_account_banking_import","account.bankimport","model_account_banking_imported_file","account.group_account_user",1,1,1,1 +"access_payment_mode_type","payment.mode.type","model_payment_mode_type","account_payment.group_account_payment",1,1,1,1 diff --git a/account_banking/wizard/__init__.py b/account_banking/wizard/__init__.py index dbc740235..50822faee 100644 --- a/account_banking/wizard/__init__.py +++ b/account_banking/wizard/__init__.py @@ -20,6 +20,6 @@ ############################################################################## import bank_import import bank_payment_manual -import wizard_payment_order +import account_payment_order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_banking/wizard/account_payment_order.py b/account_banking/wizard/account_payment_order.py new file mode 100644 index 000000000..b7f3d976d --- /dev/null +++ b/account_banking/wizard/account_payment_order.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +import datetime +from osv import osv +from account_banking.struct import struct +from account_banking.parsers import convert + +today = datetime.date.today + +def str2date(str): + dt = convert.str2date(str, '%Y-%m-%d') + return datetime.date(dt.year, dt.month, dt.day) + +class payment_order_create(osv.osv_memory): + _inherit = 'payment.order.create' + + def create_payment(self, cr, uid, ids, context=None): + ''' + This method is a slightly modified version of the existing method on this + model in account_payment. + - pass the payment mode to line2bank() + - allow invoices to create influence on the payment process: not only 'Free' + references are allowed, but others as well + - check date_to_pay is not in the past. + ''' + + order_obj = self.pool.get('payment.order') + line_obj = self.pool.get('account.move.line') + payment_obj = self.pool.get('payment.line') + if context is None: + context = {} + data = self.read(cr, uid, ids, [], context=context)[0] + line_ids = data['entries'] + if not line_ids: + return {'type': 'ir.actions.act_window_close'} + + payment = order_obj.browse(cr, uid, context['active_id'], context=context) + ### account banking + # t = None + # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context) + line2bank = line_obj.line2bank(cr, uid, line_ids, payment.mode.id, context) + _today = today() + ### end account banking + + ## Finally populate the current payment with new lines: + for line in line_obj.browse(cr, uid, line_ids, context=context): + if payment.date_prefered == "now": + #no payment date => immediate payment + date_to_pay = False + elif payment.date_prefered == 'due': + ### account_banking + # date_to_pay = line.date_maturity + date_to_pay = line.date_maturity and \ + str2date(line.date_maturity) > _today\ + and line.date_maturity or False + ### end account banking + elif payment.date_prefered == 'fixed': + ### account_banking + # date_to_pay = payment.date_planned + date_to_pay = payment.date_planned and \ + str2date(payment.date_planned) > _today\ + and payment.date_planned or False + ### end account banking + + ### account_banking + state = communication2 = False + communication = line.ref or '/' + if line.invoice: + if line.invoice.reference_type == 'structured': + state = 'structured' + communication = line.invoice.reference + else: + state = 'normal' + communication2 = line.invoice.reference + ### end account_banking + + payment_obj.create(cr, uid,{ + 'move_line_id': line.id, + 'amount_currency': line.amount_to_pay, + 'bank_id': line2bank.get(line.id), + 'order_id': payment.id, + 'partner_id': line.partner_id and line.partner_id.id or False, + ### account banking + # 'communication': line.ref or '/' + 'communication': communication, + 'communication2': communication2, + 'state': state, + ### end account banking + 'date': date_to_pay, + 'currency': line.invoice and line.invoice.currency_id.id or False, + }, context=context) + return {'type': 'ir.actions.act_window_close'} + +payment_order_create() diff --git a/account_banking/wizard/bank_import.py b/account_banking/wizard/bank_import.py index 5339cfa2d..f667ce2c4 100644 --- a/account_banking/wizard/bank_import.py +++ b/account_banking/wizard/bank_import.py @@ -974,6 +974,7 @@ class banking_import(osv.osv_memory): 'State', readonly=True), 'import_id': fields.many2one( 'account.banking.imported.file', 'Import File'), + # osv_memory does not seem to support one2many 'statement_ids': fields.many2many( 'account.bank.statement', 'rel_wiz_statements', 'wizard_id', 'statement_id', 'Imported Bank Statements'), diff --git a/account_banking/wizard/wizard_payment_order.py b/account_banking/wizard/wizard_payment_order.py deleted file mode 100644 index ff2361c24..000000000 --- a/account_banking/wizard/wizard_payment_order.py +++ /dev/null @@ -1,212 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) EduSense BV (). -# All Rights Reserved. -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## -import datetime -import wizard -import pooler -from tools.misc import UpdateableStr -from tools.translate import _ -from account_banking.struct import struct -from account_banking.parsers import convert - -__doc__ = ''' -This module is a slightly modified version of the identical named payment -order wizard in account_payment. The rationale for this bulk copy is the -inability to inherit wizards in OpenERP versions prior to version 6. -The modifications in this wizard allows invoices to create influence on the -payment process: not only 'Free' references are allowed, but others as well. - -In order to allow further projects based on account_banking to inherit from -this wizard, the complete wizard is made object oriented, as is should have -been from the start. -''' - -today = datetime.date.today - -def str2date(str): - dt = convert.str2date(str, '%Y-%m-%d') - return datetime.date(dt.year, dt.month, dt.day) - -class wizard_payment_order(wizard.interface): - ''' - Create a payment object with lines corresponding to the account move line - to pay according to the date and the mode provided by the user. - Hypothesis: - - Small number of non-reconcilied move line , payment mode and bank account type, - - Big number of partner and bank account. - - If a type is given, unsuitable account move lines are ignored. - ''' - - FORM = UpdateableStr() - FIELDS = { - 'entries': { - 'string':'Entries', - 'type':'many2many', - 'relation': 'account.move.line', - }, - } - field_duedate = { - 'duedate': { - 'string': 'Due Date', - 'type': 'date', - 'required': True, - 'default': lambda *a: convert.date2str(today()), - }, - } - arch_duedate=''' -
- - ''' - - - def search_entries(self, cursor, uid, data, context): - ''' - Search for invoices that can be paid - ''' - search_due_date = data['form']['duedate'] - - pool = pooler.get_pool(cursor.dbname) - order_obj = pool.get('payment.order') - move_line_obj = pool.get('account.move.line') - - payment = order_obj.browse(cursor, uid, data['id'], context=context) - if payment.mode: - ctx = '''context="{'journal_id': %d}"''' % payment.mode.journal.id - else: - ctx = '' - - # Search account.move.line to pay: - domain = [ - ('reconcile_id', '=', False), - ('account_id.type', '=', 'payable'), - ('amount_to_pay', '>', 0), - '|', ('date_maturity','<=',search_due_date), - ('date_maturity','=',False) - ] - line_ids = move_line_obj.search(cursor, uid, domain, context=context) - self.FORM.string = ''' -
- - ''' % (','.join([str(x) for x in line_ids]), ctx) - return {} - - def get_communication(self, line): - ''' - Method to fill the communication and communication2 lines of a payment - line. Returns (state, comm1, comm2). - ''' - if line.invoice.reference_type == 'structured': - return ('structured', line.invoice.reference, '') - return ('normal', '', line.invoice.reference) - - def create_payment(self, cursor, uid, data, context): - ''' - Create payment lines from the data of previously created payable - invoices - ''' - ids = data['form']['entries'][0][2] - if not ids: - return {} - - pool = pooler.get_pool(cursor.dbname) - order_obj = pool.get('payment.order') - move_line_obj = pool.get('account.move.line') - payment_line_obj = pool.get('payment.line') - - payment = order_obj.browse(cursor, uid, data['id'], context=context) - ptype = payment.mode and payment.mode.type.id or None - line2bank = move_line_obj.line2bank(cursor, uid, ids, ptype, context) - _today = today() - retval = struct() - - # Populate the current payment with new lines - for line in move_line_obj.browse(cursor, uid, ids, context=context): - if payment.date_prefered == 'now': - # no payment date means immediate payment - date_to_pay = False - elif payment.date_prefered == 'due': - date_to_pay = line.date_maturity and \ - str2date(line.date_maturity) > _today\ - and line.date_maturity or False - elif payment.date_prefered == 'fixed': - date_to_pay = payment.date_planned and \ - str2date(payment.date_planned) > _today\ - and payment.date_planned or False - values = struct( - move_line_id = line.id, - amount_currency = line.amount_to_pay, - bank_id = line2bank.get(line.id), - order_id = payment.id, - partner_id = line.partner_id and line.partner_id.id or False, - date = date_to_pay, - currency = False, - ) - if line.invoice: - values.state, values.communication, values.communication2 = \ - self.get_communication(line) - values.currency = line.invoice.currency_id.id, - payment_line_obj.create(cursor, uid, values, context=context) - - return {} - - states = { - 'init': { - 'actions': [], - 'result': { - 'type': 'form', - 'arch': arch_duedate, - 'fields': field_duedate, - 'state': [ - ('end','_Cancel'), - ('search','_Search', '', True) - ] - }, - }, - 'search': { - 'actions': [search_entries], - 'result': { - 'type': 'form', - 'arch': FORM, - 'fields': FIELDS, - 'state': [ - ('end','_Cancel'), - ('create','_Add to payment order', '', True) - ] - }, - }, - 'create': { - 'actions': [], - 'result': { - 'type': 'action', - 'action': create_payment, - 'state': 'end' - } - }, - } - -wizard_payment_order('account_payment.populate_payment') - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_banking_nl_clieop/__terp__.py b/account_banking_nl_clieop/__terp__.py index 99e40664c..3df46766d 100644 --- a/account_banking_nl_clieop/__terp__.py +++ b/account_banking_nl_clieop/__terp__.py @@ -33,10 +33,10 @@ 'depends': ['account_banking'], 'init_xml': [], 'update_xml': [ - #'security/ir.model.access.csv', 'account_banking_nl_clieop.xml', - 'account_banking_export_wizard.xml', + 'wizard/export_clieop_view.xml', 'data/banking_export_clieop.xml', + 'security/ir.model.access.csv', ], 'demo_xml': [], 'description': ''' diff --git a/account_banking_nl_clieop/account_banking_export_wizard.xml b/account_banking_nl_clieop/account_banking_export_wizard.xml deleted file mode 100644 index ff8c5e05c..000000000 --- a/account_banking_nl_clieop/account_banking_export_wizard.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - diff --git a/account_banking_nl_clieop/account_banking_nl_clieop.py b/account_banking_nl_clieop/account_banking_nl_clieop.py index 1f1c1146a..eae9a88e1 100644 --- a/account_banking_nl_clieop/account_banking_nl_clieop.py +++ b/account_banking_nl_clieop/account_banking_nl_clieop.py @@ -22,25 +22,19 @@ from osv import osv, fields from datetime import date from tools.translate import _ -class payment_order(osv.osv): - ''' - Attach export_clieop wizard to payment order and allow traceability - ''' - _inherit = 'payment.order' - def get_wizard(self, type): - if type in ['CLIEOPPAY', 'CLIEOPINC', 'CLIEOPSAL']: - return self._module, 'wizard_account_banking_export_clieop' - return super(payment_order, self).get_wizard(type) -payment_order() - class clieop_export(osv.osv): '''ClieOp3 Export''' _name = 'banking.export.clieop' _description = __doc__ + _rec_name = 'identification' _columns = { - 'payment_order_ids': - fields.text('Payment Orders'), + 'payment_order_ids': fields.many2many( + 'payment.order', + 'account_payment_order_clieop_rel', + 'banking_export_clieop_id', 'account_order_id', + 'Payment Orders', + readonly=True), 'testcode': fields.selection([('T', _('Yes')), ('P', _('No'))], 'Test Run', readonly=True), diff --git a/account_banking_nl_clieop/account_banking_nl_clieop.xml b/account_banking_nl_clieop/account_banking_nl_clieop.xml index aa1858a3c..0c0a01fe5 100644 --- a/account_banking_nl_clieop/account_banking_nl_clieop.xml +++ b/account_banking_nl_clieop/account_banking_nl_clieop.xml @@ -14,19 +14,33 @@ form
- - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -59,5 +73,14 @@ sequence="12" /> + + + diff --git a/account_banking_nl_clieop/data/banking_export_clieop.xml b/account_banking_nl_clieop/data/banking_export_clieop.xml index a0cf11990..b0286ecdd 100644 --- a/account_banking_nl_clieop/data/banking_export_clieop.xml +++ b/account_banking_nl_clieop/data/banking_export_clieop.xml @@ -6,6 +6,8 @@ CLIEOPINC + @@ -13,6 +15,8 @@ CLIEOPPAY + @@ -20,6 +24,8 @@ CLIEOPSAL + diff --git a/account_banking_nl_clieop/security/ir.model.access.csv b/account_banking_nl_clieop/security/ir.model.access.csv new file mode 100644 index 000000000..b29d20aa8 --- /dev/null +++ b/account_banking_nl_clieop/security/ir.model.access.csv @@ -0,0 +1,2 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_banking_export_clieop","banking.export.clieop","model_banking_export_clieop","account_payment.group_account_payment",1,1,1,1 diff --git a/account_banking_nl_clieop/wizard/clieop.py b/account_banking_nl_clieop/wizard/clieop.py index a7afd262f..16305451d 100644 --- a/account_banking_nl_clieop/wizard/clieop.py +++ b/account_banking_nl_clieop/wizard/clieop.py @@ -76,7 +76,7 @@ class HeaderRecord(record.Record): #{{{ def __init__(self, id='1', seqno=1, duplicate=False): super(HeaderRecord, self).__init__() - self.sender_id = id + self.sender_id = id or '' self.file_id = '%02d%02d' % (self.creation_date.day, seqno) self.duplicatecode = duplicate and '2' or '1' #}}} @@ -362,7 +362,7 @@ class Batch(object): self.header.variantcode = batch_id and 'C' or 'B' self.header.transactiongroup = transactiongroup self.header.batch_tracer = batch_tracer - self.header.batch_id = batch_id + self.header.batch_id = batch_id or '' self.header.accountno_sender = rekeningnr self.sender.name_sender = sender self.sender.preferred_execution_date = execution_date diff --git a/account_banking_nl_clieop/wizard/export_clieop.py b/account_banking_nl_clieop/wizard/export_clieop.py index f6b509558..75c9fb4ca 100644 --- a/account_banking_nl_clieop/wizard/export_clieop.py +++ b/account_banking_nl_clieop/wizard/export_clieop.py @@ -19,12 +19,11 @@ # ############################################################################## -import wizard -import pooler import base64 from datetime import datetime, date, timedelta -from account_banking import sepa +from osv import osv, fields from tools.translate import _ +from account_banking import sepa import clieop def strpdate(arg, format='%Y-%m-%d'): @@ -35,151 +34,131 @@ def strfdate(arg, format='%Y-%m-%d'): '''shortcut''' return arg.strftime(format) -class wizard_banking_export_clieop(wizard.interface): - form = ''' -
- - - - - - - - -''' - - fields = { - 'reference' : { - 'string': 'Reference', - 'type': 'char', - 'size': 5, - 'required': False, - 'help': ('The bank will use this reference in feedback communication ' - 'to refer to this run. Only five characters are available.' - ) - }, - 'batchtype': { - 'string': 'Type', - 'type': 'selection', - 'selection': [ +class banking_export_clieop_wizard(osv.osv_memory): + _name = 'banking.export.clieop.wizard' + _description = 'Client Opdrachten Export' + _columns = { + 'state': fields.selection( + [ + ('create', 'Create'), + ('finish', 'Finish') + ], + 'State', + readonly=True, + ), + 'reference': fields.char( + 'Reference', size=5, + help=('The bank will use this reference in feedback communication ' + 'to refer to this run. Only five characters are available.' + ), + ), + 'batchtype': fields.selection( + [ ('CLIEOPPAY', 'Payments'), ('CLIEOPSAL', 'Salary Payments'), ('CLIEOPINC', 'Direct Debits'), - ], - 'readonly': True, - }, - 'execution_date': { - 'string': 'Execution Date', - 'type': 'date', - 'required': False, - 'help': ('This is the date the file should be processed by the bank. ' - 'Don\'t choose a date beyond the nearest date in your ' - 'payments. The latest allowed date is 30 days from now.\n' - 'Please keep in mind that banks only execute on working days ' - 'and typically use a delay of two days between execution date ' - 'and effective transfer date.' - ), - }, - 'test': { - 'string': 'Test Run', - 'type': 'boolean', - 'required': True, - 'default': True, - 'help': ('Select this if you want your bank to run a test process ' - 'rather then execute your orders for real.' - ) - }, - 'fixed_message': { - 'string': 'Fixed Message', - 'type': 'char', - 'size': 32, - 'required': False, - 'default': '', - 'help': ('A fixed message to apply to all transactions in addition to ' - 'the individual messages.' - ), - }, - } - - file_form = ''' -
- - - - - - - - - - -''' - - file_fields = { - 'testcode': { - 'string': 'Test Run', - 'type': 'selection', - 'selection': [('T', _('Yes')), ('P', _('No'))], - 'required': False, - 'readonly': True, - }, - 'prefered_date': { - 'string': 'Prefered Processing Date', - 'type': 'date', - 'required': False, - 'readonly': True, - }, - 'no_transactions': { - 'string': 'Number of Transactions', - 'type': 'int', - 'required': False, - 'readonly': True, - }, - 'check_no_accounts': { - 'string': 'Check Number Accounts', - 'type': 'char', - 'size': 5, - 'required': False, - 'readonly': True, - }, - 'total_amount': { - 'string': 'Total Amount', - 'type': 'float', - 'required': False, - 'readonly': True, - }, - 'identification': { - 'string': 'Identification', - 'type': 'char', - 'size': 6, - 'required': False, - 'readonly': True, - }, - 'filetype': { - 'string': 'File Type', - 'type': 'selection', - 'selection': [ + ], 'Type', readonly=True, + ), + 'execution_date': fields.date( + 'Execution Date', + help=('This is the date the file should be processed by the bank. ' + 'Don\'t choose a date beyond the nearest date in your ' + 'payments. The latest allowed date is 30 days from now.\n' + 'Please keep in mind that banks only execute on working days ' + 'and typically use a delay of two days between execution date ' + 'and effective transfer date.' + ), + ), + 'test': fields.boolean( + 'Test Run', + help=('Select this if you want your bank to run a test process ' + 'rather then execute your orders for real.' + ), + ), + 'fixed_message': fields.char( + 'Fixed Message', size=32, + help=('A fixed message to apply to all transactions in addition to ' + 'the individual messages.' + ), + ), + # file fields + 'file_id': fields.many2one( + 'banking.export.clieop', + 'ClieOp File', + readonly=True + ), + # fields.related does not seem to support + # fields of type selection + 'testcode': fields.selection( + [('T', _('Yes')), ('P', _('No'))], + 'Test Run', readonly=True, + ), + 'filetype': fields.selection( + [ ('CREDBET', 'Payment Batch'), ('SALARIS', 'Salary Payment Batch'), ('INCASSO', 'Direct Debit Batch'), - ], - 'required': False, - 'readonly': True, - }, - 'file': { - 'string': 'ClieOp File', - 'type': 'binary', - 'required': False, - 'readonly': True, - }, - 'log': { - 'string': 'Log', - 'type': 'text', - 'readonly': True, - }, - } + ], + 'File Type', + readonly=True, + ), + 'prefered_date': fields.related( + 'file_id', 'prefered_date', + type='date', + string='Prefered Processing Date', + readonly=True, + ), + 'no_transactions': fields.related( + 'file_id', 'no_transactions', + type ='integer', + string='Number of Transactions', + readonly=True, + ), + 'check_no_accounts': fields.related( + 'file_id', 'check_no_accounts', + type='char', size=5, + string='Check Number Accounts', + readonly=True, + ), + 'total_amount': fields.related( + 'file_id', 'total_amount', + type='float', + string='Total Amount', + readonly=True, + ), + 'identification': fields.related( + 'file_id', 'identification', + type='char', size=6, + string='Identification', + readonly=True, + ), + 'file': fields.related( + 'file_id', 'file', type='binary', + readonly=True, + string='File', + ), + 'payment_order_ids': fields.many2many( + 'payment.order', 'rel_wiz_payorders', 'wizard_id', + 'payment_order_id', 'Payment Orders', + readonly=True, + ), + } + + _defaults = { + 'test': True, + } - def _check_orders(self, cursor, uid, data, context): + def create(self, cursor, uid, vals, context=None): + ''' + Retrieve a sane set of default values based on the payment orders + from the context. + ''' + if 'batchtype' not in vals: + self.check_orders(cursor, uid, vals, context) + return super(banking_export_clieop_wizard, self).create( + cursor, uid, vals, context) + + def check_orders(self, cursor, uid, vals, context): ''' Check payment type for all orders. @@ -191,19 +170,14 @@ class wizard_banking_export_clieop(wizard.interface): Also mind that rates for batches are way higher than those for transactions. It pays to limit the number of batches. ''' - form = data['form'] today = date.today() - pool = pooler.get_pool(cursor.dbname) - payment_order_obj = pool.get('payment.order') - - # Can get id from context. Seems necessary due to lack of support for - # old style wizards in the GTK client - if 'ids' not in data and context.get('payment_order_id', False): - data['ids'] = [context['payment_order_id']] + payment_order_obj = self.pool.get('payment.order') + # Payment order ids are provided in the context + payment_order_ids = context.get('active_ids', []) runs = {} # Only orders of same type can be combined - payment_orders = payment_order_obj.browse(cursor, uid, data['ids']) + payment_orders = payment_order_obj.browse(cursor, uid, payment_order_ids) for payment_order in payment_orders: payment_type = payment_order.mode.type.code @@ -231,34 +205,33 @@ class wizard_banking_export_clieop(wizard.interface): else: execution_date = today if execution_date and execution_date >= max_date: - raise wizard.except_wizard( + raise osv.except_osv( _('Error'), _('You can\'t create ClieOp orders more than 30 days in advance.') ) - # Sanity check: can't process in the past - form['execution_date'] = strfdate(max(execution_date, today)) - if len(runs) != 1: - raise wizard.except_wizard( + raise osv.except_osv( _('Error'), _('You can only combine payment orders of the same type') ) - form['batchtype'] = type = runs.keys()[0] - form['reference'] = runs[type][0].reference[-5:] - return form + type = runs.keys()[0] + vals.update({ + 'execution_date': strfdate(max(execution_date, today)), + 'batchtype': type, + 'reference': runs[type][0].reference[-5:], + 'payment_order_ids': [[6, 0, payment_order_ids]], + 'state': 'create', + }) - def _create_clieop(self, cursor, uid, data, context): + def create_clieop(self, cursor, uid, ids, context): ''' Wizard to actually create the ClieOp3 file ''' - pool = pooler.get_pool(cursor.dbname) - payment_order_obj = pool.get('payment.order') - form = data['form'] - + payment_order_obj = self.pool.get('payment.order') + clieop_export = self.browse(cursor, uid, ids, context)[0] clieopfile = None - payment_orders = payment_order_obj.browse(cursor, uid, data['ids']) - for payment_order in payment_orders: + for payment_order in clieop_export.payment_order_ids: if not clieopfile: # Just once: create clieop file our_account_owner = payment_order.mode.bank_id.owner_name \ @@ -269,19 +242,19 @@ class wizard_banking_export_clieop(wizard.interface): payment_order.mode.bank_id.iban ).localized_BBAN if not our_account_nr: - raise wizard.except_wizard( + raise osv.except_osv( _('Error'), _('Your bank account has to have a valid account number') ) clieopfile = {'CLIEOPPAY': clieop.PaymentsFile, 'CLIEOPINC': clieop.DirectDebitFile, 'CLIEOPSAL': clieop.SalaryPaymentsFile, - }[form['batchtype']]( - identification = form['reference'], - execution_date = form['execution_date'], + }[clieop_export['batchtype']]( + identification = clieop_export['reference'], + execution_date = clieop_export['execution_date'], name_sender = our_account_owner, accountno_sender = our_account_nr, - test = form['test'] + test = clieop_export['test'] ) # ClieOp3 files can contain multiple batches, but we put all @@ -290,21 +263,21 @@ class wizard_banking_export_clieop(wizard.interface): # cheaper to combine than it is to split. As we split out all # reported errors afterwards, there is no additional gain in # using multiple batches. - if form['fixed_message']: - messages = [form['fixed_message']] + if clieop_export['fixed_message']: + messages = [clieop_export['fixed_message']] else: messages = [] # The first payment order processed sets the reference of the # batch. batch = clieopfile.batch( messages = messages, - batch_id = payment_order.reference + batch_id = clieop_export['reference'] ) for line in payment_order.line_ids: # Check on missing partner of bank account (this can happen!) if not line.bank_id or not line.bank_id.partner_id: - raise wizard.except_wizard( + raise osv.except_osv( _('Error'), _('There is insufficient information.\r\n' 'Both destination address and account ' @@ -323,13 +296,13 @@ class wizard_banking_export_clieop(wizard.interface): # Is this an IBAN account? if iban.valid: if iban.countrycode != 'NL': - raise wizard.except_wizard( + raise osv.except_osv( _('Error'), _('You cannot send international bank transfers ' 'through ClieOp3!') ) other_account_nr = iban.localized_BBAN - if form['batchtype'] == 'CLIEOPINC': + if clieop_export['batchtype'] == 'CLIEOPINC': kwargs['accountno_beneficiary'] = our_account_nr kwargs['accountno_payer'] = other_account_nr else: @@ -339,87 +312,63 @@ class wizard_banking_export_clieop(wizard.interface): # Generate the specifics of this clieopfile order = clieopfile.order - values = dict( - filetype = order.name_transactioncode, - identification = order.identification, - prefered_date = strfdate(order.preferred_execution_date), - total_amount = int(order.total_amount) / 100.0, - check_no_accounts = order.total_accountnos, - no_transactions = order.nr_posts, - testcode = order.testcode, - file = base64.encodestring(clieopfile.rawdata), - ) - form.update(values) - values['daynumber'] = int(clieopfile.header.file_id[2:]) - values['payment_order_ids'] = ','.join(map(str, data['ids'])) - data['file_id'] = pool.get('banking.export.clieop').create(cursor, uid, values) - data['clieop'] = clieopfile - form['log'] = '' - return form + file_id = self.pool.get('banking.export.clieop').create( + cursor, uid, dict( + filetype = order.name_transactioncode, + identification = order.identification, + prefered_date = strfdate(order.preferred_execution_date), + total_amount = int(order.total_amount) / 100.0, + check_no_accounts = order.total_accountnos, + no_transactions = order.nr_posts, + testcode = order.testcode, + file = base64.encodestring(clieopfile.rawdata), + daynumber = int(clieopfile.header.file_id[2:]), + payment_order_ids = [ + [6, 0, [x.id for x in clieop_export['payment_order_ids']]] + ], + ), context) + self.write(cursor, uid, [ids[0]], dict( + filetype = order.name_transactioncode, + testcode = order.testcode, + file_id = file_id, + state = 'finish', + ), context) + return { + 'name': _('Client Opdrachten Export'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': self._name, + 'domain': [], + 'context': dict(context, active_ids=ids), + 'type': 'ir.actions.act_window', + 'target': 'new', + 'res_id': ids[0] or False, + } - def _cancel_clieop(self, cursor, uid, data, context): + def cancel_clieop(self, cursor, uid, ids, context): ''' Cancel the ClieOp: just drop the file ''' - pool = pooler.get_pool(cursor.dbname) - pool.get('banking.export.clieop').unlink(cursor, uid, data['file_id']) - return {'state': 'end'} + clieop_export = self.read(cursor, uid, ids, ['file_id'], context)[0] + self.pool.get('banking.export.clieop').unlink(cursor, uid, clieop_export['file_id']) + return {'type': 'ir.actions.act_window_close'} - def _save_clieop(self, cursor, uid, data, context): + def save_clieop(self, cursor, uid, ids, context): ''' Save the ClieOp: mark all payments in the file as 'sent', if not a test ''' - if 'test' not in data['form'] or not data['form']['test']: - pool = pooler.get_pool(cursor.dbname) - clieop_obj = pool.get('banking.export.clieop') - payment_order_obj = pool.get('payment.order') + clieop_export = self.browse( + cursor, uid, ids, context)[0] + if not clieop_export['test']: + clieop_obj = self.pool.get('banking.export.clieop') + payment_order_obj = self.pool.get('payment.order') clieop_file = clieop_obj.write( - cursor, uid, data['file_id'], {'state':'sent'} + cursor, uid, clieop_export['file_id'].id, {'state':'sent'} ) - payment_order_obj.action_sent(cursor, uid, data['ids']) - return {'state': 'end'} + payment_order_obj.action_sent( + cursor, uid, [x.id for x in clieop_export['payment_order_ids']]) + return {'type': 'ir.actions.act_window_close'} - states = { - 'init': { - 'actions': [_check_orders], - 'result': { - 'type': 'form', - 'arch': form, - 'fields' : fields, - 'state': [ - ('end', 'Cancel', 'gtk-cancel'), - ('create', 'Create', 'gtk-ok'), - ] - } - }, - 'create': { - 'actions': [_create_clieop], - 'result': { - 'type': 'form', - 'arch': file_form, - 'fields': file_fields, - 'state': [ - ('cancel', 'Cancel', 'gtk-cancel'), - ('save', 'Finish', 'gtk-ok'), - ] - }, - }, - 'cancel': { - 'actions': [_cancel_clieop], - 'result': { - 'type': 'state', - 'state': 'end' - } - }, - 'save': { - 'actions': [_save_clieop], - 'result': { - 'type': 'state', - 'state': 'end' - }, - } - } - -wizard_banking_export_clieop('account_banking_nl_clieop.banking_export_clieop') +banking_export_clieop_wizard() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_banking_nl_clieop/wizard/export_clieop_view.xml b/account_banking_nl_clieop/wizard/export_clieop_view.xml new file mode 100644 index 000000000..454560eb1 --- /dev/null +++ b/account_banking_nl_clieop/wizard/export_clieop_view.xml @@ -0,0 +1,58 @@ + + + + + banking.export.clieop.wizard.view + banking.export.clieop.wizard + form + +
+ + + + + + + + + + + +