diff --git a/account_banking/account_banking_view.xml b/account_banking/account_banking_view.xml index 19ec91bb1..d4ef8684d 100644 --- a/account_banking/account_banking_view.xml +++ b/account_banking/account_banking_view.xml @@ -465,30 +465,6 @@ - - - payment.mode.form.inherit - payment.mode - - form - - - - - - - - payment.mode.tree.inherit - payment.mode - - tree - - - - - - - view.payment.mode.type.form diff --git a/account_banking_pain_base/__init__.py b/account_banking_pain_base/__init__.py new file mode 100644 index 000000000..6662843e6 --- /dev/null +++ b/account_banking_pain_base/__init__.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# 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 . import payment_line +from . import payment_mode +from . import company +from . import banking_export_pain diff --git a/account_banking_pain_base/__openerp__.py b/account_banking_pain_base/__openerp__.py new file mode 100644 index 000000000..71c52d5d0 --- /dev/null +++ b/account_banking_pain_base/__openerp__.py @@ -0,0 +1,51 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# 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': 'Account Banking PAIN Base Module', + 'summary': 'Base module for PAIN file generation', + 'version': '0.1', + 'license': 'AGPL-3', + 'author': 'Akretion, Noviat', + 'website': 'http://openerp-community-association.org/', + 'category': 'Hidden', + 'depends': ['account_banking_payment_export'], + 'external_dependencies': { + 'python': ['unidecode', 'lxml'], + }, + 'data': [ + 'payment_line_view.xml', + 'payment_mode_view.xml', + 'company_view.xml', + ], + 'description': ''' +Base module for PAIN file generation +==================================== + +This module contains fields and functions that are used by the module for SEPA Credit Transfer (account_banking_sepa_credit_transfer) and SEPA Direct Debit (account_banking_sepa_direct_debit). This module doesn't provide any functionnality by itself. + +This module is part of the banking addons: https://launchpad.net/banking-addons + +This module was started during the Akretion-Noviat code sprint of November 21st 2013 in Epiais les Louvres (France). + ''', + 'active': False, + 'installable': True, +} diff --git a/account_banking_pain_base/banking_export_pain.py b/account_banking_pain_base/banking_export_pain.py new file mode 100644 index 000000000..211b70f2b --- /dev/null +++ b/account_banking_pain_base/banking_export_pain.py @@ -0,0 +1,439 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# 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 openerp.osv import orm +from openerp.tools.translate import _ +from openerp.tools.safe_eval import safe_eval +from datetime import datetime +from lxml import etree +from openerp import tools +import logging +import base64 + +logger = logging.getLogger(__name__) + + +class banking_export_pain(orm.AbstractModel): + _name = 'banking.export.pain' + + def _validate_iban(self, cr, uid, iban, context=None): + '''if IBAN is valid, returns IBAN + if IBAN is NOT valid, raises an error message''' + partner_bank_obj = self.pool.get('res.partner.bank') + if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context): + return iban.replace(' ', '') + else: + raise orm.except_orm( + _('Error:'), _("This IBAN is not valid : %s") % iban) + + def _prepare_field( + self, cr, uid, field_name, field_value, eval_ctx, max_size=0, + gen_args=None, context=None): + '''This function is designed to be inherited !''' + from unidecode import unidecode + if gen_args is None: + gen_args = {} + assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict' + try: + value = safe_eval(field_value, eval_ctx) + # SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters + # But we are dealing with banks... + # and many banks don't want non-ASCCI characters ! + # cf section 1.4 "Character set" of the SEPA Credit Transfer + # Scheme Customer-to-bank guidelines + if gen_args.get('convert_to_ascii'): + value = unidecode(value) + unallowed_ascii_chars = [ + '"', '#', '$', '%', '&', '*', ';', '<', '>', '=', '@', + '[', ']', '^', '_', '`', '{', '}', '|', '~', '\\', '!'] + for unallowed_ascii_char in unallowed_ascii_chars: + value = value.replace(unallowed_ascii_char, '-') + except: + line = eval_ctx.get('line') + if line: + raise orm.except_orm( + _('Error:'), + _("Cannot compute the '%s' of the Payment Line with " + "reference '%s'.") + % (field_name, line.name)) + else: + raise orm.except_orm( + _('Error:'), + _("Cannot compute the '%s'.") % field_name) + if not isinstance(value, (str, unicode)): + raise orm.except_orm( + _('Field type error:'), + _("The type of the field '%s' is %s. It should be a string " + "or unicode.") + % (field_name, type(value))) + if not value: + raise orm.except_orm( + _('Error:'), + _("The '%s' is empty or 0. It should have a non-null value.") + % field_name) + if max_size and len(value) > max_size: + value = value[0:max_size] + return value + + def _prepare_export_sepa( + self, cr, uid, total_amount, transactions_count, xml_string, + gen_args, context=None): + return { + 'batch_booking': gen_args['sepa_export'].batch_booking, + 'charge_bearer': gen_args['sepa_export'].charge_bearer, + 'total_amount': total_amount, + 'nb_transactions': transactions_count, + 'file': base64.encodestring(xml_string), + 'payment_order_ids': [( + 6, 0, [x.id for x in gen_args['sepa_export'].payment_order_ids] + )], + } + + def _validate_xml(self, cr, uid, xml_string, gen_args, context=None): + xsd_etree_obj = etree.parse( + tools.file_open(gen_args['pain_xsd_file'])) + official_pain_schema = etree.XMLSchema(xsd_etree_obj) + + try: + root_to_validate = etree.fromstring(xml_string) + official_pain_schema.assertValid(root_to_validate) + except Exception, e: + logger.warning( + "The XML file is invalid against the XML Schema Definition") + logger.warning(xml_string) + logger.warning(e) + raise orm.except_orm( + _('Error:'), + _("The generated XML file is not valid against the official " + "XML Schema Definition. The generated XML file and the " + "full error have been written in the server logs. Here " + "is the error, which may give you an idea on the cause " + "of the problem : %s") + % str(e)) + return True + + def finalize_sepa_file_creation( + self, cr, uid, ids, xml_root, total_amount, transactions_count, + gen_args, context=None): + xml_string = etree.tostring( + xml_root, pretty_print=True, encoding='UTF-8', + xml_declaration=True) + logger.debug( + "Generated SEPA XML file in format %s below" + % gen_args['pain_flavor']) + logger.debug(xml_string) + self._validate_xml(cr, uid, xml_string, gen_args, context=context) + + file_id = gen_args['file_obj'].create( + cr, uid, self._prepare_export_sepa( + cr, uid, total_amount, transactions_count, + xml_string, gen_args, context=context), + context=context) + + self.write( + cr, uid, ids, { + 'file_id': file_id, + 'state': 'finish', + }, context=context) + + action = { + 'name': 'SEPA File', + 'type': 'ir.actions.act_window', + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': self._name, + 'res_id': ids[0], + 'target': 'new', + } + return action + + def generate_group_header_block( + self, cr, uid, parent_node, gen_args, context=None): + group_header_1_0 = etree.SubElement(parent_node, 'GrpHdr') + message_identification_1_1 = etree.SubElement( + group_header_1_0, 'MsgId') + message_identification_1_1.text = self._prepare_field( + cr, uid, 'Message Identification', + 'sepa_export.payment_order_ids[0].reference', + {'sepa_export': gen_args['sepa_export']}, 35, + gen_args=gen_args, context=context) + creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm') + creation_date_time_1_2.text = datetime.strftime( + datetime.today(), '%Y-%m-%dT%H:%M:%S') + if gen_args.get('pain_flavor') == 'pain.001.001.02': + # batch_booking is in "Group header" with pain.001.001.02 + # and in "Payment info" in pain.001.001.03/04 + batch_booking = etree.SubElement(group_header_1_0, 'BtchBookg') + batch_booking.text = \ + str(gen_args['sepa_export'].batch_booking).lower() + nb_of_transactions_1_6 = etree.SubElement( + group_header_1_0, 'NbOfTxs') + control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum') + # Grpg removed in pain.001.001.03 + if gen_args.get('pain_flavor') == 'pain.001.001.02': + grouping = etree.SubElement(group_header_1_0, 'Grpg') + grouping.text = 'GRPD' + self.generate_initiating_party_block( + cr, uid, group_header_1_0, gen_args, + context=context) + return group_header_1_0, nb_of_transactions_1_6, control_sum_1_7 + + def generate_start_payment_info_block( + self, cr, uid, parent_node, payment_info_ident, + priority, local_instrument, sequence_type, requested_date, + eval_ctx, gen_args, context=None): + payment_info_2_0 = etree.SubElement(parent_node, 'PmtInf') + payment_info_identification_2_1 = etree.SubElement( + payment_info_2_0, 'PmtInfId') + payment_info_identification_2_1.text = self._prepare_field( + cr, uid, 'Payment Information Identification', + payment_info_ident, eval_ctx, 35, + gen_args=gen_args, context=context) + payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd') + payment_method_2_2.text = gen_args['payment_method'] + if gen_args.get('pain_flavor') != 'pain.001.001.02': + batch_booking_2_3 = etree.SubElement(payment_info_2_0, 'BtchBookg') + batch_booking_2_3.text = \ + str(gen_args['sepa_export'].batch_booking).lower() + # The "SEPA Customer-to-bank + # Implementation guidelines" for SCT and SDD says that control sum + # and nb_of_transactions should be present + # at both "group header" level and "payment info" level + nb_of_transactions_2_4 = etree.SubElement( + payment_info_2_0, 'NbOfTxs') + control_sum_2_5 = etree.SubElement(payment_info_2_0, 'CtrlSum') + payment_type_info_2_6 = etree.SubElement( + payment_info_2_0, 'PmtTpInf') + if priority: + instruction_priority_2_7 = etree.SubElement( + payment_type_info_2_6, 'InstrPrty') + instruction_priority_2_7.text = priority + service_level_2_8 = etree.SubElement( + payment_type_info_2_6, 'SvcLvl') + service_level_code_2_9 = etree.SubElement(service_level_2_8, 'Cd') + service_level_code_2_9.text = 'SEPA' + if local_instrument: + local_instrument_2_11 = etree.SubElement( + payment_type_info_2_6, 'LclInstrm') + local_instr_code_2_12 = etree.SubElement( + local_instrument_2_11, 'Cd') + local_instr_code_2_12.text = local_instrument + if sequence_type: + sequence_type_2_14 = etree.SubElement( + payment_type_info_2_6, 'SeqTp') + sequence_type_2_14.text = sequence_type + + if gen_args['payment_method'] == 'DD': + request_date_tag = 'ReqdColltnDt' + else: + request_date_tag = 'ReqdExctnDt' + requested_date_2_17 = etree.SubElement( + payment_info_2_0, request_date_tag) + requested_date_2_17.text = requested_date + return payment_info_2_0, nb_of_transactions_2_4, control_sum_2_5 + + def generate_initiating_party_block( + self, cr, uid, parent_node, gen_args, context=None): + my_company_name = self._prepare_field( + cr, uid, 'Company Name', + 'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name', + {'sepa_export': gen_args['sepa_export']}, + gen_args.get('name_maxsize'), gen_args=gen_args, context=context) + initiating_party_1_8 = etree.SubElement(parent_node, 'InitgPty') + initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm') + initiating_party_name.text = my_company_name + initiating_party_identifier = self.pool['res.company'].\ + _get_initiating_party_identifier( + cr, uid, + gen_args['sepa_export'].payment_order_ids[0].company_id.id, + context=context) + initiating_party_issuer = gen_args['sepa_export'].\ + payment_order_ids[0].company_id.initiating_party_issuer + if initiating_party_identifier and initiating_party_issuer: + iniparty_id = etree.SubElement(initiating_party_1_8, 'Id') + iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId') + iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr') + iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id') + iniparty_org_other_id.text = initiating_party_identifier + iniparty_org_other_issuer = etree.SubElement( + iniparty_org_other, 'Issr') + iniparty_org_other_issuer.text = initiating_party_issuer + return True + + def generate_party_agent( + self, cr, uid, parent_node, party_type, party_type_label, + order, party_name, iban, bic, eval_ctx, gen_args, context=None): + '''Generate the piece of the XML file corresponding to BIC + This code is mutualized between TRF and DD''' + assert order in ('B', 'C'), "Order can be 'B' or 'C'" + try: + bic = self._prepare_field( + cr, uid, '%s BIC' % party_type_label, bic, eval_ctx, + gen_args=gen_args, context=context) + party_agent = etree.SubElement(parent_node, '%sAgt' % party_type) + party_agent_institution = etree.SubElement( + party_agent, 'FinInstnId') + party_agent_bic = etree.SubElement( + party_agent_institution, gen_args.get('bic_xml_tag')) + party_agent_bic.text = bic + except orm.except_orm: + if order == 'C': + if iban[0:2] != gen_args['initiating_party_country_code']: + raise orm.except_orm( + _('Error:'), + _("The bank account with IBAN '%s' of partner '%s' " + "must have an associated BIC because it is a " + "cross-border SEPA operation.") + % (iban, party_name)) + if order == 'B' or ( + order == 'C' and gen_args['payment_method'] == 'DD'): + party_agent = etree.SubElement( + parent_node, '%sAgt' % party_type) + party_agent_institution = etree.SubElement( + party_agent, 'FinInstnId') + party_agent_other = etree.SubElement( + party_agent_institution, 'Othr') + party_agent_other_identification = etree.SubElement( + party_agent_other, 'Id') + party_agent_other_identification.text = 'NOTPROVIDED' + # for Credit Transfers, in the 'C' block, if BIC is not provided, + # we should not put the 'Creditor Agent' block at all, + # as per the guidelines of the EPC + return True + + def generate_party_block( + self, cr, uid, parent_node, party_type, order, name, iban, bic, + eval_ctx, gen_args, context=None): + '''Generate the piece of the XML file corresponding to Name+IBAN+BIC + This code is mutualized between TRF and DD''' + assert order in ('B', 'C'), "Order can be 'B' or 'C'" + if party_type == 'Cdtr': + party_type_label = 'Creditor' + elif party_type == 'Dbtr': + party_type_label = 'Debtor' + party_name = self._prepare_field( + cr, uid, '%s Name' % party_type_label, name, eval_ctx, + gen_args.get('name_maxsize'), + gen_args=gen_args, context=context) + piban = self._prepare_field( + cr, uid, '%s IBAN' % party_type_label, iban, eval_ctx, + gen_args=gen_args, + context=context) + viban = self._validate_iban(cr, uid, piban, context=context) + # At C level, the order is : BIC, Name, IBAN + # At B level, the order is : Name, IBAN, BIC + if order == 'B': + gen_args['initiating_party_country_code'] = viban[0:2] + elif order == 'C': + self.generate_party_agent( + cr, uid, parent_node, party_type, party_type_label, + order, party_name, viban, bic, + eval_ctx, gen_args, context=context) + party = etree.SubElement(parent_node, party_type) + party_nm = etree.SubElement(party, 'Nm') + party_nm.text = party_name + party_account = etree.SubElement( + parent_node, '%sAcct' % party_type) + party_account_id = etree.SubElement(party_account, 'Id') + party_account_iban = etree.SubElement( + party_account_id, 'IBAN') + party_account_iban.text = viban + if order == 'B': + self.generate_party_agent( + cr, uid, parent_node, party_type, party_type_label, + order, party_name, viban, bic, + eval_ctx, gen_args, context=context) + return True + + def generate_remittance_info_block( + self, cr, uid, parent_node, line, gen_args, context=None): + + remittance_info_2_91 = etree.SubElement( + parent_node, 'RmtInf') + if line.state == 'normal': + remittance_info_unstructured_2_99 = etree.SubElement( + remittance_info_2_91, 'Ustrd') + remittance_info_unstructured_2_99.text = \ + self._prepare_field( + cr, uid, 'Remittance Unstructured Information', + 'line.communication', {'line': line}, 140, + gen_args=gen_args, + context=context) + else: + if not line.struct_communication_type: + raise orm.except_orm( + _('Error:'), + _("Missing 'Structured Communication Type' on payment " + "line with reference '%s'.") + % (line.name)) + remittance_info_structured_2_100 = etree.SubElement( + remittance_info_2_91, 'Strd') + creditor_ref_information_2_120 = etree.SubElement( + remittance_info_structured_2_100, 'CdtrRefInf') + if gen_args.get('pain_flavor') == 'pain.001.001.02': + creditor_ref_info_type_2_121 = etree.SubElement( + creditor_ref_information_2_120, 'CdtrRefTp') + creditor_ref_info_type_code_2_123 = etree.SubElement( + creditor_ref_info_type_2_121, 'Cd') + creditor_ref_info_type_issuer_2_125 = etree.SubElement( + creditor_ref_info_type_2_121, 'Issr') + creditor_reference_2_126 = etree.SubElement( + creditor_ref_information_2_120, 'CdtrRef') + else: + creditor_ref_info_type_2_121 = etree.SubElement( + creditor_ref_information_2_120, 'Tp') + creditor_ref_info_type_or_2_122 = etree.SubElement( + creditor_ref_info_type_2_121, 'CdOrPrtry') + creditor_ref_info_type_code_2_123 = etree.SubElement( + creditor_ref_info_type_or_2_122, 'Cd') + creditor_ref_info_type_issuer_2_125 = etree.SubElement( + creditor_ref_info_type_2_121, 'Issr') + creditor_reference_2_126 = etree.SubElement( + creditor_ref_information_2_120, 'Ref') + + creditor_ref_info_type_code_2_123.text = 'SCOR' + creditor_ref_info_type_issuer_2_125.text = \ + line.struct_communication_type + creditor_reference_2_126.text = \ + self._prepare_field( + cr, uid, 'Creditor Structured Reference', + 'line.communication', {'line': line}, 35, + gen_args=gen_args, + context=context) + return True + + def generate_creditor_scheme_identification( + self, cr, uid, parent_node, identification, identification_label, + eval_ctx, scheme_name_proprietary, gen_args, context=None): + csi_id = etree.SubElement( + parent_node, 'Id') + csi_privateid = csi_id = etree.SubElement(csi_id, 'PrvtId') + csi_other = etree.SubElement(csi_privateid, 'Othr') + csi_other_id = etree.SubElement(csi_other, 'Id') + csi_other_id.text = self._prepare_field( + cr, uid, identification_label, identification, eval_ctx, + gen_args=gen_args, context=context) + csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm') + csi_scheme_name_proprietary = etree.SubElement( + csi_scheme_name, 'Prtry') + csi_scheme_name_proprietary.text = scheme_name_proprietary + return True diff --git a/account_banking_pain_base/company.py b/account_banking_pain_base/company.py new file mode 100644 index 000000000..94864d548 --- /dev/null +++ b/account_banking_pain_base/company.py @@ -0,0 +1,82 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# Copyright (C) 2013 Noviat (http://www.noviat.com) +# @author: Alexis de Lattre +# @author: Luc de Meyer (Noviat) +# +# 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 openerp.osv import orm, fields + + +class res_company(orm.Model): + _inherit = 'res.company' + + _columns = { + 'initiating_party_issuer': fields.char( + 'Initiating Party Issuer', size=35, + help="This will be used as the 'Initiating Party Issuer' in the " + "PAIN files generated by OpenERP."), + } + + def _get_initiating_party_identifier( + self, cr, uid, company_id, context=None): + '''The code here may be different from one country to another. + If you need to add support for an additionnal country, you can + contribute your code here or inherit this function in the + localization modules for your country''' + assert isinstance(company_id, int), 'Only one company ID' + company = self.browse(cr, uid, company_id, context=context) + company_vat = company.vat + party_identifier = False + if company_vat: + country_code = company_vat[0:2].upper() + if country_code == 'BE': + party_identifier = company_vat[2:].replace(' ', '') + elif country_code == 'ES': + party_identifier = company.sepa_creditor_identifier + return party_identifier + + def _initiating_party_issuer_default(self, cr, uid, context=None): + '''If you need to add support for an additionnal country, you can + add an entry in the dict "party_issuer_per_country" here + or inherit this function in the localization modules for + your country''' + initiating_party_issuer = '' + # If your country require the 'Initiating Party Issuer', you should + # contribute the entry for your country in the dict below + party_issuer_per_country = { + 'BE': 'KBO-BCE', # KBO-BCE = the registry of companies in Belgium + } + company_id = self._company_default_get( + cr, uid, 'res.company', context=context) + if company_id: + company = self.browse(cr, uid, company_id, context=context) + country_code = company.country_id.code + initiating_party_issuer = party_issuer_per_country.get( + country_code, '') + return initiating_party_issuer + + def _initiating_party_issuer_def(self, cr, uid, context=None): + return self._initiating_party_issuer_default( + cr, uid, context=context) + + _defaults = { + 'initiating_party_issuer': _initiating_party_issuer_def, + } diff --git a/account_banking_pain_base/company_view.xml b/account_banking_pain_base/company_view.xml new file mode 100644 index 000000000..6a2dc2c85 --- /dev/null +++ b/account_banking_pain_base/company_view.xml @@ -0,0 +1,25 @@ + + + + + + + pain.group.on.res.company.form + res.company + form + + + + + + + + + + + + diff --git a/account_banking_pain_base/i18n/account_banking_pain_base.pot b/account_banking_pain_base/i18n/account_banking_pain_base.pot new file mode 100644 index 000000000..d4a7dbac5 --- /dev/null +++ b/account_banking_pain_base/i18n/account_banking_pain_base.pot @@ -0,0 +1,146 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_pain_base +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-23 21:26+0000\n" +"PO-Revision-Date: 2013-12-23 21:26+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: account_banking_pain_base +#: field:res.company,initiating_party_issuer:0 +msgid "Initiating Party Issuer" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:122 +#, python-format +msgid "The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.line,priority:0 +msgid "Priority" +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_line +msgid "Payment Line" +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_mode +msgid "Payment Mode" +msgstr "" + +#. module: account_banking_pain_base +#: help:res.company,initiating_party_issuer:0 +msgid "This will be used as the 'Initiating Party Issuer' in the PAIN files generated by OpenERP." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:351 +#, python-format +msgid "Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "Normal" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:70 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:77 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:81 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#: code:addons/account_banking_pain_base/banking_export_pain.py:69 +#: code:addons/account_banking_pain_base/banking_export_pain.py:76 +#: code:addons/account_banking_pain_base/banking_export_pain.py:86 +#: code:addons/account_banking_pain_base/banking_export_pain.py:121 +#: code:addons/account_banking_pain_base/banking_export_pain.py:350 +#, python-format +msgid "Error:" +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_res_company +msgid "Companies" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:80 +#, python-format +msgid "Field type error:" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.line,struct_communication_type:0 +msgid "Structured Communication Type" +msgstr "" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:87 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_banking_export_pain +msgid "banking.export.pain" +msgstr "" + +#. module: account_banking_pain_base +#: help:payment.mode,convert_to_ascii:0 +msgid "If active, OpenERP will convert each accented caracter to the corresponding unaccented caracter, so that only ASCII caracters are used in the generated PAIN file." +msgstr "" + +#. module: account_banking_pain_base +#: help:payment.line,priority:0 +msgid "This field will be used as the 'Instruction Priority' in the generated PAIN file." +msgstr "" + +#. module: account_banking_pain_base +#: view:res.company:0 +msgid "Payment Initiation" +msgstr "" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "High" +msgstr "" + +#. module: account_banking_pain_base +#: field:payment.mode,convert_to_ascii:0 +msgid "Convert to ASCII" +msgstr "" + diff --git a/account_banking_pain_base/i18n/fr.po b/account_banking_pain_base/i18n/fr.po new file mode 100644 index 000000000..e58b8ece0 --- /dev/null +++ b/account_banking_pain_base/i18n/fr.po @@ -0,0 +1,172 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_pain_base +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-12-23 21:26+0000\n" +"PO-Revision-Date: 2014-02-01 04:48+0000\n" +"Last-Translator: Alexis de Lattre \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-05-31 06:02+0000\n" +"X-Generator: Launchpad (build 17031)\n" + +#. module: account_banking_pain_base +#: field:res.company,initiating_party_issuer:0 +msgid "Initiating Party Issuer" +msgstr "Initiating Party Issuer" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:122 +#, python-format +msgid "" +"The generated XML file is not valid against the official XML Schema " +"Definition. The generated XML file and the full error have been written in " +"the server logs. Here is the error, which may give you an idea on the cause " +"of the problem : %s" +msgstr "" +"Le fichier XML généré n'est pas valide par rapport à la Définition du Schéma " +"XML officiel. Le fichier XML généré et le message d'erreur complet ont été " +"écrits dans les logs du serveur. Voici l'erreur, qui vous donnera peut-être " +"une idée sur la cause du problème : %s" + +#. module: account_banking_pain_base +#: field:payment.line,priority:0 +msgid "Priority" +msgstr "Priorité" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_line +msgid "Payment Line" +msgstr "Ligne de paiement" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_mode +msgid "Payment Mode" +msgstr "Mode de paiement" + +#. module: account_banking_pain_base +#: help:res.company,initiating_party_issuer:0 +msgid "" +"This will be used as the 'Initiating Party Issuer' in the PAIN files " +"generated by OpenERP." +msgstr "" +"Ce champ sera le 'Initiating Party Issuer' dans les fichiers PAIN générés " +"par OpenERP." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:351 +#, python-format +msgid "" +"Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "" +"Le 'Type de communication structuré' n'est pas renseigné sur la ligne de " +"paiement ayant la référence '%s'." + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "Normal" +msgstr "Normal" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:70 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." +msgstr "" +"Impossible de calculer le '%s' de la ligne de paiement ayant la référence " +"'%s'." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:77 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "Impossible de calculer le '%s'." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:81 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "" +"Le type du champ '%s' est %s. Il devrait être de type string ou unicode." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#: code:addons/account_banking_pain_base/banking_export_pain.py:69 +#: code:addons/account_banking_pain_base/banking_export_pain.py:76 +#: code:addons/account_banking_pain_base/banking_export_pain.py:86 +#: code:addons/account_banking_pain_base/banking_export_pain.py:121 +#: code:addons/account_banking_pain_base/banking_export_pain.py:350 +#, python-format +msgid "Error:" +msgstr "Erreur :" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_res_company +msgid "Companies" +msgstr "Sociétés" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "Cet IBAN n'est pas valide : %s" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:80 +#, python-format +msgid "Field type error:" +msgstr "Erreur dans le type de champ :" + +#. module: account_banking_pain_base +#: field:payment.line,struct_communication_type:0 +msgid "Structured Communication Type" +msgstr "Type de communication structurée" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:87 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "Le '%s' est vide ou égal à 0. Il devrait avoir une valeur non-nulle." + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_banking_export_pain +msgid "banking.export.pain" +msgstr "banking.export.pain" + +#. module: account_banking_pain_base +#: help:payment.mode,convert_to_ascii:0 +msgid "" +"If active, OpenERP will convert each accented caracter to the corresponding " +"unaccented caracter, so that only ASCII caracters are used in the generated " +"PAIN file." +msgstr "" +"Si actif, OpenERP convertira chaque caractère accentué en son équivalent non " +"accentué, de telle façon que seuls des caractères ASCII soient utilisés dans " +"le fichier PAIN généré." + +#. module: account_banking_pain_base +#: help:payment.line,priority:0 +msgid "" +"This field will be used as the 'Instruction Priority' in the generated PAIN " +"file." +msgstr "Ce champ sera le 'Instruction Priority' dans le fichier PAIN généré." + +#. module: account_banking_pain_base +#: view:res.company:0 +msgid "Payment Initiation" +msgstr "Payment Initiation" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "High" +msgstr "Élevé" + +#. module: account_banking_pain_base +#: field:payment.mode,convert_to_ascii:0 +msgid "Convert to ASCII" +msgstr "Convertir en ASCII" diff --git a/account_banking_pain_base/i18n/nl.po b/account_banking_pain_base/i18n/nl.po new file mode 100644 index 000000000..721d24f68 --- /dev/null +++ b/account_banking_pain_base/i18n/nl.po @@ -0,0 +1,172 @@ +# Dutch translation for banking-addons +# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 +# This file is distributed under the same license as the banking-addons package. +# FIRST AUTHOR , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: banking-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2013-12-23 21:26+0000\n" +"PO-Revision-Date: 2014-02-11 08:32+0000\n" +"Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" +"Language-Team: Dutch \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-05-31 06:02+0000\n" +"X-Generator: Launchpad (build 17031)\n" + +#. module: account_banking_pain_base +#: field:res.company,initiating_party_issuer:0 +msgid "Initiating Party Issuer" +msgstr "Initiating Party Issuer" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:122 +#, python-format +msgid "" +"The generated XML file is not valid against the official XML Schema " +"Definition. The generated XML file and the full error have been written in " +"the server logs. Here is the error, which may give you an idea on the cause " +"of the problem : %s" +msgstr "" +"Het gegenereerde XML bestand is niet geldig volgens de officiële XML schema " +"definities. Het gegenereerde XML bestand en de volledige fout zijn " +"weggeschreven in de server log bestanden. Hier is de fout, wat u een idee " +"kunt geven over de oorzaak van het probleem: %s\"" + +#. module: account_banking_pain_base +#: field:payment.line,priority:0 +msgid "Priority" +msgstr "Prioriteit" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_line +msgid "Payment Line" +msgstr "Betaalregel" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_payment_mode +msgid "Payment Mode" +msgstr "Betaalwijze" + +#. module: account_banking_pain_base +#: help:res.company,initiating_party_issuer:0 +msgid "" +"This will be used as the 'Initiating Party Issuer' in the PAIN files " +"generated by OpenERP." +msgstr "" +"Dit wordt gebruikt als de 'Initiating Party Issuer' in de PAIN bestanden " +"gegenereerd door OpenERP." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:351 +#, python-format +msgid "" +"Missing 'Structured Communication Type' on payment line with reference '%s'." +msgstr "" +"Ontbrekende 'Structured Communication Type' op betaalregel met referentie " +"'%s'." + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "Normal" +msgstr "Normaal" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:70 +#, python-format +msgid "Cannot compute the '%s' of the Payment Line with reference '%s'." +msgstr "Kan de '%s' niet berekenen van de betaalregel met referentie '%s'." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:77 +#, python-format +msgid "Cannot compute the '%s'." +msgstr "Kan de '%s' niet berekenen." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:81 +#, python-format +msgid "The type of the field '%s' is %s. It should be a string or unicode." +msgstr "Het type van veld '%s' is %s. Dit moet een string of unicode zijn." + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#: code:addons/account_banking_pain_base/banking_export_pain.py:69 +#: code:addons/account_banking_pain_base/banking_export_pain.py:76 +#: code:addons/account_banking_pain_base/banking_export_pain.py:86 +#: code:addons/account_banking_pain_base/banking_export_pain.py:121 +#: code:addons/account_banking_pain_base/banking_export_pain.py:350 +#, python-format +msgid "Error:" +msgstr "Fout:" + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_res_company +msgid "Companies" +msgstr "Bedrijven" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:47 +#, python-format +msgid "This IBAN is not valid : %s" +msgstr "Deze IBAN is niet geldig : %s" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:80 +#, python-format +msgid "Field type error:" +msgstr "Veld type fout:" + +#. module: account_banking_pain_base +#: field:payment.line,struct_communication_type:0 +msgid "Structured Communication Type" +msgstr "Structured Communication Type" + +#. module: account_banking_pain_base +#: code:addons/account_banking_pain_base/banking_export_pain.py:87 +#, python-format +msgid "The '%s' is empty or 0. It should have a non-null value." +msgstr "De '%s' is leeg of 0. Deze waarde zou niet nul moeten zijn." + +#. module: account_banking_pain_base +#: model:ir.model,name:account_banking_pain_base.model_banking_export_pain +msgid "banking.export.pain" +msgstr "banking.export.pain" + +#. module: account_banking_pain_base +#: help:payment.mode,convert_to_ascii:0 +msgid "" +"If active, OpenERP will convert each accented caracter to the corresponding " +"unaccented caracter, so that only ASCII caracters are used in the generated " +"PAIN file." +msgstr "" +"Indien aangevinkt, zal OpenERP elk geaccentueerde karakter omzetten in een " +"overeenkomstige ongeaccentueerde karakter, zodat alleen ASCII karakters " +"worden gebruikt in het gegenereerde PAIN bestand." + +#. module: account_banking_pain_base +#: help:payment.line,priority:0 +msgid "" +"This field will be used as the 'Instruction Priority' in the generated PAIN " +"file." +msgstr "" +"Dit veld wordt gebruikt als de 'Instruction Priority' in het gegenereerde " +"PAIN bestand." + +#. module: account_banking_pain_base +#: view:res.company:0 +msgid "Payment Initiation" +msgstr "Payment Initiation" + +#. module: account_banking_pain_base +#: selection:payment.line,priority:0 +msgid "High" +msgstr "Hoog" + +#. module: account_banking_pain_base +#: field:payment.mode,convert_to_ascii:0 +msgid "Convert to ASCII" +msgstr "Converteer naar ASCII" diff --git a/account_banking_pain_base/payment_line.py b/account_banking_pain_base/payment_line.py new file mode 100644 index 000000000..0dffbcf42 --- /dev/null +++ b/account_banking_pain_base/payment_line.py @@ -0,0 +1,52 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# 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 openerp.osv import orm, fields + + +class payment_line(orm.Model): + _inherit = 'payment.line' + + def _get_struct_communication_types(self, cr, uid, context=None): + return [('ISO', 'ISO')] + + _columns = { + 'priority': fields.selection([ + ('NORM', 'Normal'), + ('HIGH', 'High'), + ], 'Priority', + help="This field will be used as the 'Instruction Priority' in " + "the generated PAIN file."), + # Update size from 64 to 140, because PAIN allows 140 caracters + 'communication': fields.char( + 'Communication', size=140, required=True, + help="Used as the message between ordering customer and current " + "company. Depicts 'What do you want to say to the recipient " + "about this order ?'"), + 'struct_communication_type': fields.selection( + _get_struct_communication_types, 'Structured Communication Type'), + } + + _defaults = { + 'priority': 'NORM', + 'struct_communication_type': 'ISO', + } diff --git a/account_banking_pain_base/payment_line_view.xml b/account_banking_pain_base/payment_line_view.xml new file mode 100644 index 000000000..f92b1bbf5 --- /dev/null +++ b/account_banking_pain_base/payment_line_view.xml @@ -0,0 +1,41 @@ + + + + + + + pain.base.payment.line.form + payment.line + + + + + + + + + + + + + + pain.base.payment.line.inside.order.form + payment.order + + + + + + + + + + + + + + diff --git a/account_banking_pain_base/payment_mode.py b/account_banking_pain_base/payment_mode.py new file mode 100644 index 000000000..540d01b67 --- /dev/null +++ b/account_banking_pain_base/payment_mode.py @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# PAIN Base module for OpenERP +# Copyright (C) 2013 Akretion (http://www.akretion.com) +# @author: Alexis de Lattre +# +# 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 openerp.osv import orm, fields + + +class payment_mode(orm.Model): + _inherit = 'payment.mode' + + _columns = { + 'convert_to_ascii': fields.boolean( + 'Convert to ASCII', + help="If active, OpenERP will convert each accented caracter to " + "the corresponding unaccented caracter, so that only ASCII " + "caracters are used in the generated PAIN file."), + } + + _defaults = { + 'convert_to_ascii': True, + } diff --git a/account_banking_pain_base/payment_mode_view.xml b/account_banking_pain_base/payment_mode_view.xml new file mode 100644 index 000000000..2deb24999 --- /dev/null +++ b/account_banking_pain_base/payment_mode_view.xml @@ -0,0 +1,22 @@ + + + + + + + add.convert_to_ascii.in.payment.mode.form + payment.mode + + + + + + + + + + diff --git a/account_banking_payment_export/__init__.py b/account_banking_payment_export/__init__.py new file mode 100644 index 000000000..833a0ba11 --- /dev/null +++ b/account_banking_payment_export/__init__.py @@ -0,0 +1,2 @@ +from . import model + diff --git a/account_banking_payment_export/__openerp__.py b/account_banking_payment_export/__openerp__.py new file mode 100644 index 000000000..424be1620 --- /dev/null +++ b/account_banking_payment_export/__openerp__.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# (C) 2013 - 2014 ACSONE SA (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# 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': 'Account Banking - Payments Export Infrastructure', + 'version': '0.1.165', + 'license': 'AGPL-3', + 'author': 'Banking addons community', + 'website': 'https://launchpad.net/banking-addons', + 'category': 'Banking addons', + 'depends': [ + 'account_payment', + 'base_iban', # for manual_bank_tranfer + ], + 'conflicts': [ + # lp:account-payment/account_payment_extension also adds + # a type field to payment.mode, with a very similar purpose. + # We can't add a dependency on account_payment_extension here + # because account_payment_extension adds many other features + # that probably conflict with other parts of lp:banking-addons. + # Proposal to resolve: make account_payment_extension depend + # on the present account_banking_payment_export module. + 'account_payment_extension', + ], + 'data': [ + 'view/account_payment.xml', + 'view/bank_payment_manual.xml', + 'view/payment_mode.xml', + 'view/payment_mode_type.xml', + 'view/payment_order_create_view.xml', + 'data/payment_mode_type.xml', + 'security/ir.model.access.csv', + ], + 'demo': ['demo/banking_demo.xml'], + 'description': ''' + Infrastructure to export payment orders + plus some bug fixes and obvious enhancements to payment orders + that will hopefully land in offical addons one day. + + This technical module provides the base infrastructure to export + payment orders for electronic banking. It provides the following + technical features: + * a new payment.mode.type model + * payment.mode now has a mandatory type + * a better implementation of payment_mode.suitable_bank_types() based on payment.mode.type + * the "make payment" button launches a wizard depending on the payment.mode.type + * a manual payment mode type is provided as an example, with a default "do nothing" wizard + + To enable the use of payment order to collect money for customers, + it adds a payment_order_type (payment|debit) as a basis of direct debit support + (this field becomes visible when account_direct_debit is installed). + Refactoring note: this field should ideally go in account_direct_debit, + but account_banking_payment currently depends on it. + + Bug fixes and enhancement that should land in official addons: + * make the search function of the payment export wizard extensible + * fix lp:1275478: allow payment of customer refunds + * display the maturity date of the move lines when you are in + the wizard to select the lines to pay + ''', + 'installable': True, +} diff --git a/account_banking_payment_export/data/payment_mode_type.xml b/account_banking_payment_export/data/payment_mode_type.xml new file mode 100644 index 000000000..c1e4a4abd --- /dev/null +++ b/account_banking_payment_export/data/payment_mode_type.xml @@ -0,0 +1,14 @@ + + + + + + Manual Bank Transfer + BANKMAN + + + + + diff --git a/account_banking_payment_export/demo/banking_demo.xml b/account_banking_payment_export/demo/banking_demo.xml new file mode 100644 index 000000000..fd29e4c51 --- /dev/null +++ b/account_banking_payment_export/demo/banking_demo.xml @@ -0,0 +1,78 @@ + + + + + + + Fortuneo Banque + FTNOFRP1XXX + 26 avenue des Champs Elysées + 75008 + Paris + + + + + La Banque Postale + PSSTFRPPXXX + 115 rue de Sèvres + 75007 + Paris + + + + + Société Générale + SOGEFRPPXXX + 1 avenue du Roi Fabien 1er + 75008 + Paris + + + + + FR76 4242 4242 4242 4242 4242 424 + iban + + + La Banque Postale + PSSTFRPPXXX + + + + FR20 1242 1242 1242 1242 1242 124 + iban + + + Société Générale + SOGEFRPPXXX + + + + FR66 1212 1212 1212 1212 1212 121 + iban + + + Fortuneo Banque + FTNOFRP1XXX + + + + Credit Trf Banque Postale + + + + + + + + Credit Trf Société Générale + + + + + + + + + diff --git a/account_banking_payment_export/i18n/account_banking_payment_export.pot b/account_banking_payment_export/i18n/account_banking_payment_export.pot new file mode 100644 index 000000000..bb2ac6301 --- /dev/null +++ b/account_banking_payment_export/i18n/account_banking_payment_export.pot @@ -0,0 +1,145 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_payment_export +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-25 15:58+0000\n" +"PO-Revision-Date: 2013-10-25 15:58+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: account_banking_payment_export +#: help:payment.mode.type,name:0 +msgid "Payment Type" +msgstr "" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_order +msgid "Payment Order" +msgstr "" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "Please execute payment order manually, and click OK when succesfully sent." +msgstr "" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_mode +msgid "Payment Mode" +msgstr "" + +#. module: account_banking_payment_export +#: code:addons/account_banking_payment_export/model/account_payment.py:69 +#, python-format +msgid "You can only combine payment orders of the same type" +msgstr "" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_mode_type +msgid "Payment Mode Type" +msgstr "" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_account_move_line +msgid "Journal Items" +msgstr "" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_manual +msgid "Send payment order(s) manually" +msgstr "" + +#. module: account_banking_payment_export +#: field:payment.mode.type,name:0 +msgid "Name" +msgstr "" + +#. module: account_banking_payment_export +#: help:payment.mode.type,ir_model_id:0 +msgid "Select the Payment Wizard for payments of this type. Leave empty for manual processing" +msgstr "" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "Manual payment" +msgstr "" + +#. module: account_banking_payment_export +#: field:payment.manual,payment_order_ids:0 +msgid "Payment orders" +msgstr "" + +#. module: account_banking_payment_export +#: code:addons/account_banking_payment_export/model/account_payment.py:52 +#, python-format +msgid "Payment Order Export" +msgstr "" + +#. module: account_banking_payment_export +#: help:payment.mode,type:0 +msgid "Select the Payment Type for the Payment Mode." +msgstr "" + +#. module: account_banking_payment_export +#: view:payment.order:0 +msgid "launch_wizard" +msgstr "" + +#. module: account_banking_payment_export +#: help:payment.mode.type,code:0 +msgid "Specify the Code for Payment Type" +msgstr "" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_order_create +msgid "payment.order.create" +msgstr "" + +#. module: account_banking_payment_export +#: code:addons/account_banking_payment_export/model/account_payment.py:68 +#, python-format +msgid "Error" +msgstr "" + +#. module: account_banking_payment_export +#: field:payment.mode.type,ir_model_id:0 +msgid "Payment wizard" +msgstr "" + +#. module: account_banking_payment_export +#: field:payment.mode,type:0 +msgid "Payment type" +msgstr "" + +#. module: account_banking_payment_export +#: field:payment.mode.type,code:0 +msgid "Code" +msgstr "" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "OK" +msgstr "" + +#. module: account_banking_payment_export +#: view:payment.mode.type:0 +msgid "Payment mode" +msgstr "" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "Cancel" +msgstr "" + +#. module: account_banking_payment_export +#: field:payment.mode.type,suitable_bank_types:0 +msgid "Suitable bank types" +msgstr "" + diff --git a/account_banking_payment_export/i18n/nl.po b/account_banking_payment_export/i18n/nl.po new file mode 100644 index 000000000..dea08f97f --- /dev/null +++ b/account_banking_payment_export/i18n/nl.po @@ -0,0 +1,151 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * account_banking_payment_export +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-10-25 15:58+0000\n" +"PO-Revision-Date: 2013-12-03 11:49+0000\n" +"Last-Translator: Erwin van der Ploeg (BAS Solutions) \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2014-05-31 06:02+0000\n" +"X-Generator: Launchpad (build 17031)\n" + +#. module: account_banking_payment_export +#: help:payment.mode.type,name:0 +msgid "Payment Type" +msgstr "Betaalwijze" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_order +msgid "Payment Order" +msgstr "Betalingsopdracht" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "" +"Please execute payment order manually, and click OK when succesfully sent." +msgstr "" +"Voer de betaalopdracht handmatig uit en klik OK, wanneer succesvol verzonden." + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_mode +msgid "Payment Mode" +msgstr "Betaalwijze" + +#. module: account_banking_payment_export +#: code:addons/account_banking_payment_export/model/account_payment.py:69 +#, python-format +msgid "You can only combine payment orders of the same type" +msgstr "U kunt alleen betalingsopdrachten van dezelfde soort combineren" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_mode_type +msgid "Payment Mode Type" +msgstr "Betaalwijze soort" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_account_move_line +msgid "Journal Items" +msgstr "Boekingen" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_manual +msgid "Send payment order(s) manually" +msgstr "Verzend betaalopdrachten handmatig" + +#. module: account_banking_payment_export +#: field:payment.mode.type,name:0 +msgid "Name" +msgstr "Naam" + +#. module: account_banking_payment_export +#: help:payment.mode.type,ir_model_id:0 +msgid "" +"Select the Payment Wizard for payments of this type. Leave empty for manual " +"processing" +msgstr "" +"Selecteer de wizard voor het verwerken van betalingen van dit type. Laat " +"leeg voor handmatige verwerking." + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "Manual payment" +msgstr "Handmatige betaling" + +#. module: account_banking_payment_export +#: field:payment.manual,payment_order_ids:0 +msgid "Payment orders" +msgstr "Betaalopdrachten" + +#. module: account_banking_payment_export +#: code:addons/account_banking_payment_export/model/account_payment.py:52 +#, python-format +msgid "Payment Order Export" +msgstr "Betaalopdracht export" + +#. module: account_banking_payment_export +#: help:payment.mode,type:0 +msgid "Select the Payment Type for the Payment Mode." +msgstr "Selecteer het type van de betaalmodus." + +#. module: account_banking_payment_export +#: view:payment.order:0 +msgid "launch_wizard" +msgstr "launch_wizard" + +#. module: account_banking_payment_export +#: help:payment.mode.type,code:0 +msgid "Specify the Code for Payment Type" +msgstr "Geef de code op voor het betaaltype" + +#. module: account_banking_payment_export +#: model:ir.model,name:account_banking_payment_export.model_payment_order_create +msgid "payment.order.create" +msgstr "payment.order.create" + +#. module: account_banking_payment_export +#: code:addons/account_banking_payment_export/model/account_payment.py:68 +#, python-format +msgid "Error" +msgstr "Fout" + +#. module: account_banking_payment_export +#: field:payment.mode.type,ir_model_id:0 +msgid "Payment wizard" +msgstr "Betaalwizard" + +#. module: account_banking_payment_export +#: field:payment.mode,type:0 +msgid "Payment type" +msgstr "Betaaltype" + +#. module: account_banking_payment_export +#: field:payment.mode.type,code:0 +msgid "Code" +msgstr "Code" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "OK" +msgstr "OK" + +#. module: account_banking_payment_export +#: view:payment.mode.type:0 +msgid "Payment mode" +msgstr "Betaalwijze" + +#. module: account_banking_payment_export +#: view:payment.manual:0 +msgid "Cancel" +msgstr "Annuleren" + +#. module: account_banking_payment_export +#: field:payment.mode.type,suitable_bank_types:0 +msgid "Suitable bank types" +msgstr "Geschikte banktypen" diff --git a/account_banking_payment_export/model/__init__.py b/account_banking_payment_export/model/__init__.py new file mode 100644 index 000000000..74ab85c8d --- /dev/null +++ b/account_banking_payment_export/model/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +from . import account_move_line +from . import account_payment +from . import bank_payment_manual +from . import payment_mode +from . import payment_mode_type +from . import payment_order_create diff --git a/account_banking_payment_export/model/account_move_line.py b/account_banking_payment_export/model/account_move_line.py new file mode 100644 index 000000000..67c8b849d --- /dev/null +++ b/account_banking_payment_export/model/account_move_line.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2004-2014 OpenERP S.A. (http://www.openerp.com/) +# (C) 2014 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 . +# +############################################################################## + +from openerp.osv import orm, fields +from operator import itemgetter + + +# All the code below aims at fixing one small issue in _to_pay_search() +# But _to_pay_search() is the search function of the field 'amount_to_pay' +# which is a field.function and these functions are not inheritable in OpenERP. +# So we have to inherit the field 'amount_to_pay' and duplicate the related +# functions +# If the patch that I proposed in this bug report +# https://bugs.launchpad.net/openobject-addons/+bug/1275478 +# is integrated in addons/account_payment, then we will be able to remove this +# file. -- Alexis de Lattre +class account_move_line(orm.Model): + _inherit = 'account.move.line' + + def amount_to_pay(self, cr, uid, ids, name, arg=None, context=None): + """ Return the amount still to pay regarding all the payemnt orders + (excepting cancelled orders)""" + if not ids: + return {} + cr.execute("""SELECT ml.id, + CASE WHEN ml.amount_currency < 0 + THEN - ml.amount_currency + ELSE ml.credit + END - + (SELECT coalesce(sum(amount_currency),0) + FROM payment_line pl + INNER JOIN payment_order po + ON (pl.order_id = po.id) + WHERE move_line_id = ml.id + AND po.state != 'cancel') AS amount + FROM account_move_line ml + WHERE id IN %s""", (tuple(ids),)) + r = dict(cr.fetchall()) + return r + + def _to_pay_search(self, cr, uid, obj, name, args, context=None): + if not args: + return [] + line_obj = self.pool.get('account.move.line') + query = line_obj._query_get(cr, uid, context={}) + where = ' and '.join(map(lambda x: '''(SELECT + CASE WHEN l.amount_currency < 0 + THEN - l.amount_currency + ELSE l.credit + END - coalesce(sum(pl.amount_currency), 0) + FROM payment_line pl + INNER JOIN payment_order po ON (pl.order_id = po.id) + WHERE move_line_id = l.id + AND po.state != 'cancel' + ) %(operator)s %%s ''' % {'operator': x[1]}, args)) + sql_args = tuple(map(itemgetter(2), args)) + + cr.execute(('''SELECT id + FROM account_move_line l + WHERE account_id IN (select id + FROM account_account + WHERE type in %s AND active) + AND reconcile_id IS null + AND credit > 0 + AND ''' + where + ' and ' + query), + (('payable', 'receivable'),)+sql_args ) + # The patch we have compared to the original function in + # addons/account_payment is just above : + # original code : type = 'payable' + # fixed code : type in ('payable', 'receivable') + + res = cr.fetchall() + if not res: + return [('id', '=', '0')] + return [('id', 'in', map(lambda x:x[0], res))] + + _columns = { + 'amount_to_pay': fields.function(amount_to_pay, + type='float', string='Amount to pay', fnct_search=_to_pay_search), + } diff --git a/account_banking_payment_export/model/account_payment.py b/account_banking_payment_export/model/account_payment.py new file mode 100644 index 000000000..fe69c290f --- /dev/null +++ b/account_banking_payment_export/model/account_payment.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# 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 openerp.osv import orm, fields +from openerp.tools.translate import _ +from openerp import netsvc + + +class payment_order(orm.Model): + _inherit = 'payment.order' + + _columns = { + 'payment_order_type': fields.selection( + [('payment', 'Payment'), ('debit', 'Direct debit')], + 'Payment order type', required=True, + readonly=True, states={'draft': [('readonly', False)]}, + ), + 'mode_type': fields.related( + 'mode', 'type', type='many2one', relation='payment.mode.type', + string='Payment Type'), + } + + _defaults = { + 'payment_order_type': 'payment', + } + + def launch_wizard(self, cr, uid, ids, context=None): + """ + Search for a wizard to launch according to the type. + If type is manual. just confirm the order. + Previously (pre-v6) in account_payment/wizard/wizard_pay.py + """ + if context == None: + context = {} + result = {} + 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 orm.except_orm( + _('Error'), + _('You can only combine payment orders of the same type') + ) + # process manual payments + wf_service = netsvc.LocalService('workflow') + for order_id in ids: + wf_service.trg_validate(uid, 'payment.order', order_id, 'done', cr) + return result diff --git a/account_banking_payment_export/model/bank_payment_manual.py b/account_banking_payment_export/model/bank_payment_manual.py new file mode 100644 index 000000000..8cfa35d53 --- /dev/null +++ b/account_banking_payment_export/model/bank_payment_manual.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# 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 . +# +############################################################################## + +''' +This module contains a single "wizard" for confirming manual +bank transfers. +''' + +from openerp.osv import orm, fields +from openerp import netsvc + + +class payment_manual(orm.TransientModel): + _name = 'payment.manual' + _description = 'Send payment order(s) manually' + + _columns = { + 'payment_order_ids': fields.many2many('payment.order', + 'wiz_manual_payorders_rel', 'wizard_id', 'payment_order_id', + 'Payment orders', readonly=True), + } + + def create(self, cr, uid, vals, context=None): + payment_order_ids = context.get('active_ids', []) + vals.update({ + 'payment_order_ids': [[6, 0, payment_order_ids]], + }) + return super(payment_manual, self).create(cr, uid, + vals, context=context) + + def button_ok(self, cr, uid, ids, context=None): + wf_service = netsvc.LocalService('workflow') + for wiz in self.browse(cr, uid, ids, context=context): + for order_id in wiz.payment_order_ids: + wf_service.trg_validate( + uid, 'payment.order', order_id.id, 'done', cr) + return {'type': 'ir.actions.act_window_close'} diff --git a/account_banking_payment_export/model/payment_mode.py b/account_banking_payment_export/model/payment_mode.py new file mode 100644 index 000000000..cac103402 --- /dev/null +++ b/account_banking_payment_export/model/payment_mode.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# 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 openerp.osv import orm, fields + + +class payment_mode(orm.Model): + ''' Restoring the payment type from version 5, + used to select the export wizard (if any) ''' + _inherit = "payment.mode" + + def suitable_bank_types(self, cr, uid, payment_mode_id=None, context=None): + """ Reinstates functional code for suitable bank type filtering. + Current code in account_payment is disfunctional. + """ + res = [] + payment_mode = self.browse( + cr, uid, payment_mode_id, context) + if (payment_mode and payment_mode.type and + payment_mode.type.suitable_bank_types): + res = [t.code for t in payment_mode.type.suitable_bank_types] + return res + + _columns = { + 'type': fields.many2one( + 'payment.mode.type', 'Payment type', + required=True, + help='Select the Payment Type for the Payment Mode.' + ), + 'payment_order_type': fields.related( + 'type', 'payment_order_type', readonly=True, type='selection', + selection=[('payment', 'Payment'), ('debit', 'Direct debit')], + string="Payment Order Type"), + 'active': fields.boolean('Active'), + } + + _defaults = { + 'active': True, + } diff --git a/account_banking_payment_export/model/payment_mode_type.py b/account_banking_payment_export/model/payment_mode_type.py new file mode 100644 index 000000000..e65727715 --- /dev/null +++ b/account_banking_payment_export/model/payment_mode_type.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# 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 openerp.osv import orm, fields + + +class payment_mode_type(orm.Model): + _name = 'payment.mode.type' + _description = 'Payment Mode Type' + _columns = { + 'name': fields.char( + 'Name', size=64, required=True, + help='Payment Type' + ), + 'code': fields.char( + 'Code', size=64, required=True, + help='Specify the Code for Payment Type' + ), + 'suitable_bank_types': fields.many2many( + 'res.partner.bank.type', + '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_order_type': fields.selection( + [('payment', 'Payment'), ('debit', 'Direct debit')], + 'Payment order type', required=True, + ), + 'active': fields.boolean('Active'), + } + + _defaults = { + 'payment_order_type': 'payment', + 'active': True, + } + + def _auto_init(self, cr, context=None): + r = super(payment_mode_type, self)._auto_init(cr, context=context) + # migrate xmlid from manual_bank_transfer to avoid dependency on account_banking + cr.execute("""UPDATE ir_model_data SET module='account_banking_payment_export' + WHERE module='account_banking' AND + name='manual_bank_tranfer' AND + model='payment.mode.type'""") + return r diff --git a/account_banking_payment_export/model/payment_order_create.py b/account_banking_payment_export/model/payment_order_create.py new file mode 100644 index 000000000..20d8c3ac1 --- /dev/null +++ b/account_banking_payment_export/model/payment_order_create.py @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2009 EduSense BV (). +# (C) 2011 - 2013 Therp BV (). +# +# All other contributions are (C) by their respective contributors +# +# All Rights Reserved +# +# 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 openerp.osv import orm, fields +from openerp.tools.translate import _ + + +class payment_order_create(orm.TransientModel): + _inherit = 'payment.order.create' + + def extend_payment_order_domain( + self, cr, uid, payment_order, domain, context=None): + if payment_order.payment_order_type == 'payment': + domain += [ + ('account_id.type', 'in', ('payable', 'receivable')), + ('amount_to_pay', '>', 0) + ] + return True + + def search_entries(self, cr, uid, ids, context=None): + """ + This method taken from account_payment module. + We adapt the domain based on the payment_order_type + """ + line_obj = self.pool.get('account.move.line') + mod_obj = self.pool.get('ir.model.data') + if context is None: + context = {} + data = self.read(cr, uid, ids, ['duedate'], context=context)[0] + search_due_date = data['duedate'] + + ### start account_banking_payment ### + payment = self.pool.get('payment.order').browse( + cr, uid, context['active_id'], context=context) + # Search for move line to pay: + domain = [ + ('move_id.state', '=', 'posted'), + ('reconcile_id', '=', False), + ('company_id', '=', payment.mode.company_id.id), + ] + self.extend_payment_order_domain( + cr, uid, payment, domain, context=context) + ### end account_direct_debit ### + + domain = domain + [ + '|', ('date_maturity', '<=', search_due_date), + ('date_maturity', '=', False) + ] + line_ids = line_obj.search(cr, uid, domain, context=context) + context.update({'line_ids': line_ids}) + model_data_ids = mod_obj.search( + cr, uid,[ + ('model', '=', 'ir.ui.view'), + ('name', '=', 'view_create_payment_order_lines')], + context=context) + resource_id = mod_obj.read( + cr, uid, model_data_ids, fields=['res_id'], + context=context)[0]['res_id'] + return {'name': _('Entry Lines'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'payment.order.create', + 'views': [(resource_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + } + + def _prepare_payment_line(self, cr, uid, payment, line, context=None): + '''This function is designed to be inherited + The resulting dict is passed to the create method of payment.line''' + _today = fields.date.context_today(self, cr, uid, 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 + if line.date_maturity and line.date_maturity > _today + else False) + ### end account banking + elif payment.date_prefered == 'fixed': + ### account_banking + # date_to_pay = payment.date_scheduled + date_to_pay = ( + payment.date_scheduled + if payment.date_scheduled and payment.date_scheduled > _today + else False) + ### end account banking + + ### account_banking + state = 'normal' + communication = line.ref or '-' + if line.invoice: + if line.invoice.type in ('in_invoice', 'in_refund'): + if line.invoice.reference_type == 'structured': + state = 'structured' + communication = line.invoice.reference + else: + if line.invoice.reference: + communication = line.invoice.reference + elif line.invoice.supplier_invoice_number: + communication = line.invoice.supplier_invoice_number + else: + # Make sure that the communication includes the + # customer invoice number (in the case of debit order) + communication = line.invoice.number.replace('/', '') + state = 'structured' + + # support debit orders when enabled + if (payment.payment_order_type == 'debit' and + 'amount_to_receive' in line): + amount_currency = line.amount_to_receive + else: + amount_currency = line.amount_to_pay + ### end account_banking + + ### account banking + # t = None + # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context) + line2bank = self.pool['account.move.line'].line2bank( + cr, uid, [line.id], payment.mode.id, context) + ### end account banking + + res = { + 'move_line_id': line.id, + 'amount_currency': amount_currency, + '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, + 'state': state, + ### end account banking + 'date': date_to_pay, + 'currency': (line.invoice and line.invoice.currency_id.id + or line.journal_id.currency.id + or line.journal_id.company_id.currency_id.id), + } + return res + + 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. + ''' + 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 = self.pool['payment.order'].browse( + cr, uid, context['active_id'], context=context) + ## Populate the current payment with new lines: + for line in self.pool['account.move.line'].browse( + cr, uid, line_ids, context=context): + vals = self._prepare_payment_line( + cr, uid, payment, line, context=context) + self.pool['payment.line'].create(cr, uid, vals, context=context) + # Force reload of payment order view as a workaround for lp:1155525 + return {'name': _('Payment Orders'), + 'context': context, + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'payment.order', + 'res_id': context['active_id'], + 'type': 'ir.actions.act_window', + } diff --git a/account_banking_payment_export/security/ir.model.access.csv b/account_banking_payment_export/security/ir.model.access.csv new file mode 100644 index 000000000..699f2d023 --- /dev/null +++ b/account_banking_payment_export/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_payment_mode_type","payment.mode.type","model_payment_mode_type","account_payment.group_account_payment",1,1,1,1 diff --git a/account_banking_payment_export/view/account_payment.xml b/account_banking_payment_export/view/account_payment.xml new file mode 100644 index 000000000..3e9d35882 --- /dev/null +++ b/account_banking_payment_export/view/account_payment.xml @@ -0,0 +1,23 @@ + + + + + + + account.payment.order.form.banking-1 + + payment.order + + + launch_wizard + + + + + + + + + diff --git a/account_banking_payment_export/view/bank_payment_manual.xml b/account_banking_payment_export/view/bank_payment_manual.xml new file mode 100644 index 000000000..572de1d4b --- /dev/null +++ b/account_banking_payment_export/view/bank_payment_manual.xml @@ -0,0 +1,17 @@ + + + + + Form for manual payment wizard + payment.manual + +
+