diff --git a/compassion_denmark_payment/__manifest__.py b/compassion_denmark_payment/__manifest__.py index 3a1bd1c..4e40bb0 100644 --- a/compassion_denmark_payment/__manifest__.py +++ b/compassion_denmark_payment/__manifest__.py @@ -35,9 +35,13 @@ "version": "14.0.1.3.3", "license": "AGPL-3", "category": "Banking addons", - "depends": ["compassion_nordic_accounting"], + "depends": [ + "compassion_nordic_accounting", + "account_payment_return_import" #OCA/account-payment + ], "data": [ "data/account_payment_method.xml", + "data/payment.return.reason.csv" ], "installable": True, } diff --git a/compassion_denmark_payment/data/payment.return.reason.csv b/compassion_denmark_payment/data/payment.return.reason.csv new file mode 100644 index 0000000..fbbc929 --- /dev/null +++ b/compassion_denmark_payment/data/payment.return.reason.csv @@ -0,0 +1,4 @@ +id,code,name +automated_dk_payment_rejected,237,Beservice payment rejected +automated_dk_payment_cancelled,238,Beservice payment cancelled +automated_dk_payment_charged_back,239,Beservice payment charged back \ No newline at end of file diff --git a/compassion_denmark_payment/models/__init__.py b/compassion_denmark_payment/models/__init__.py index 8eccf8a..8c9ebd6 100644 --- a/compassion_denmark_payment/models/__init__.py +++ b/compassion_denmark_payment/models/__init__.py @@ -10,5 +10,4 @@ from ..beservice import * from . import account_payment_order -from . import account_statement_import from . import account_statement_import_beservice_parser \ No newline at end of file diff --git a/compassion_denmark_payment/models/account_payment_order.py b/compassion_denmark_payment/models/account_payment_order.py index 93f3c6c..f1895b6 100644 --- a/compassion_denmark_payment/models/account_payment_order.py +++ b/compassion_denmark_payment/models/account_payment_order.py @@ -53,8 +53,7 @@ def generate_payment_file(self): data_delivery.sections[0].add_payment(customer_number=f'{pymt_trx.partner_id.ref:15}', mandate_number=pymt_trx.payment_line_ids[0].move_line_id.move_id. line_ids.mapped('contract_id').group_id.ref, - reference=(pymt_trx.date.strftime("%b").capitalize() - + ' ' + pymt_trx.payment_line_ids[0].payment_type.capitalize())[:20], + reference=f"{self.id}_{pymt_trx.id}_{pymt_trx.ref}_"[:30], amount=pymt_trx.amount, sign_code=beservice.SignCode.COLLECTION, payment_date=pymt_trx.date, diff --git a/compassion_denmark_payment/models/account_statement_import.py b/compassion_denmark_payment/models/account_statement_import.py deleted file mode 100644 index 0b2460d..0000000 --- a/compassion_denmark_payment/models/account_statement_import.py +++ /dev/null @@ -1,32 +0,0 @@ -############################################################################## -# -# Copyright (C) 2022 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty -# @author: Robin Berguerand -# -# The licence is in the file __manifest__.py -# -############################################################################## - -import logging - -from odoo import fields, models - -_logger = logging.getLogger(__name__) - - -class AccountStatementImport(models.TransientModel): - _inherit = "account.statement.import" - - def _parse_file(self, data_file): - self.ensure_one() - try: - Parser = self.env["account.statement.import.beservice.parser"] - return Parser.parse( - data_file, self.statement_filename - ) - except Exception: - if self.env.context.get("account_statement_import_paypal_test"): - raise - _logger.warning("PayPal parser error", exc_info=True) - return super()._parse_file(data_file) diff --git a/compassion_denmark_payment/models/account_statement_import_beservice_parser.py b/compassion_denmark_payment/models/account_statement_import_beservice_parser.py index d3c8175..1fe7967 100644 --- a/compassion_denmark_payment/models/account_statement_import_beservice_parser.py +++ b/compassion_denmark_payment/models/account_statement_import_beservice_parser.py @@ -8,17 +8,12 @@ # ############################################################################## -import base64 import itertools import logging -from datetime import datetime -from decimal import Decimal from io import StringIO -from os import path from .. import beservice -from pytz import timezone, utc -from odoo import _, api, models +from odoo import _, api, models, fields _logger = logging.getLogger(__name__) @@ -33,41 +28,31 @@ class AccountBankStatementImportPayPalParser(models.TransientModel): _description = "Account Statement Import Betalingsservice Parser " @api.model - def parse(self, data_file, filename): - journal = self.env["account.journal"].browse(self.env.context.get("journal_id")) + def parse(self, data_file): + file_data = beservice.parse(StringIO(data_file.decode("iso-8859-1")).read()) + Journal = self.env["account.journal"] + journal = Journal.search([ + ("payment_mode_id.initiating_party_scheme", "=", file_data.data_supplier_number) + ], limit=1) or Journal.browse(self.env.context.get("journal_id")) currency_code = (journal.currency_id or journal.company_id.currency_id).name account_number = journal.bank_account_id.acc_number - - name = _("%s: %s") % ( - journal.code, - path.basename(filename), - ) - file_data = beservice.parse(StringIO(data_file.decode("iso-8859-1")).read()) + name = journal.code + str(fields.Datetime.now()) lines = [a for a in self._calculate_lines(file_data.sections[0]) if - a.transaction_code == beservice.TransactionCode.AUTOMATED_PAYMENT_COMPLETED] + a.transaction_code != beservice.TransactionCode.AUTOMATED_PAYMENT_COMPLETED] if not lines: return currency_code, account_number, [{"name": name, "transactions": []}] date = file_data.sections[0].section_date - transactions = list( itertools.chain.from_iterable( map(lambda line: self._convert_line_to_transactions(line), lines) ) ) - - return ( - currency_code, - account_number, - [ - { - "name": name, - "date": date, - "balance_start": float(-file_data.sections[0].get_net_amount()), - "balance_end_real": float(0), - "transactions": transactions, - } - ], - ) + return { + "name": name, + "date": date, + "account_number": account_number, + "transactions": transactions, + } @staticmethod def _calculate_lines(data): @@ -78,19 +63,16 @@ def _calculate_lines(data): @api.model def _convert_line_to_transactions(self, line: beservice.PaymentInformation): - transactions = [] - details = line.reference + pay_ord_id, pay_trx_id, pay_trx_ref, empty = line.reference.split("_") + payment = self.env["account.payment"].browse(int(pay_trx_id)) gross_amount = line.amount - # res = self.env['recurring.contract.group'].search([('ref', '=', line.mandate_number)]) - bank_account = res.partner_id.bank_ids - transaction = { + return [{ "partner_id": res.partner_id.id, "amount": str(gross_amount), "date": line.info_date, - "ref": line.mandate_number, - "payment_ref": details, - } - transactions.append(transaction) - - return transactions + "concept": line.mandate_number, + "reference": payment.move_id.name, + "reason_code": line.transaction_code.value, + "raw_import_data": line, + }] diff --git a/compassion_denmark_payment/wizards/__init__.py b/compassion_denmark_payment/wizards/__init__.py index b166293..4bb1946 100644 --- a/compassion_denmark_payment/wizards/__init__.py +++ b/compassion_denmark_payment/wizards/__init__.py @@ -10,4 +10,5 @@ # ############################################################################## -from . import load_mandate_wizard \ No newline at end of file +from . import load_mandate_wizard +from . import payment_return_import \ No newline at end of file diff --git a/compassion_denmark_payment/wizards/payment_return_import.py b/compassion_denmark_payment/wizards/payment_return_import.py new file mode 100644 index 0000000..3b167f3 --- /dev/null +++ b/compassion_denmark_payment/wizards/payment_return_import.py @@ -0,0 +1,23 @@ +# Copyright 2016 Tecnativa - Carlos Dauden +# Copyright 2016 Tecnativa - Pedro M. Baeza +# Copyright 2018 Tecnativa - Luis M. Ontalba +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from odoo import _, api, models +_logger = logging.getLogger(__name__) + + +class PaymentReturnImport(models.TransientModel): + _inherit = "payment.return.import" + + @api.model + def _parse_file(self, data_file): + try: + Parser = self.env["account.statement.import.beservice.parser"] + return Parser.with_context(journal_id=self.journal_id.id).parse( + data_file + ) + except Exception: + _logger.warning(_("The file couldn't be parsed by danish beservice parser"), exc_info=True) + return super()._parse_file(data_file) diff --git a/compassion_sweden_payment/__manifest__.py b/compassion_sweden_payment/__manifest__.py index 5ead560..b99fe93 100644 --- a/compassion_sweden_payment/__manifest__.py +++ b/compassion_sweden_payment/__manifest__.py @@ -34,9 +34,13 @@ "website": "http://www.compassion.ch", "license": "AGPL-3", "category": "Banking addons", - "depends": ["compassion_nordic_accounting"], + "depends": [ + "compassion_nordic_accounting", + "account_payment_return_import" # OCA/account-payment + ], "data": [ "data/account_payment_method.xml", + "data/payment.return.reason.csv", "data/statement_import_sheet_mapping.xml", ], "installable": True, diff --git a/compassion_sweden_payment/data/payment.return.reason.csv b/compassion_sweden_payment/data/payment.return.reason.csv new file mode 100644 index 0000000..7b15234 --- /dev/null +++ b/compassion_sweden_payment/data/payment.return.reason.csv @@ -0,0 +1,4 @@ +id,code,name +automated_se_payment_insufficient_fund,1,Autogiro payment refused for insufficient fund +automated_se_payment_no_connection,2,Autogiro payment refused for no connection +automated_se_payment_renewed_funds,9,Autogiro payment refused for renewed funds \ No newline at end of file diff --git a/compassion_sweden_payment/models/account_payment_order.py b/compassion_sweden_payment/models/account_payment_order.py index 19aea9e..3f55e20 100644 --- a/compassion_sweden_payment/models/account_payment_order.py +++ b/compassion_sweden_payment/models/account_payment_order.py @@ -25,13 +25,13 @@ def generate_payment_file(self): payment_initiation = bggiro.PaymentInitiation(date_written=self.create_date, bankgiro_number=self.company_partner_bank_id.acc_number, customer_number=self.payment_mode_id.initiating_party_identifier) - for payment_line in self.payment_line_ids: + for payment in self.payment_ids: payment_initiation.add_payment( transaction_type=bggiro.TransactionType.INCOMING_PAYMENT, - payment_date=payment_line.date, + payment_date=payment.date, period_code=bggiro.PeriodCode.ONCE, number_recurring_payments=0, - payer_number=int(payment_line.move_line_id.move_id.line_ids.mapped('contract_id').group_id.ref), - amount=int(payment_line.amount_currency), - reference=payment_line.communication[:16]) + payer_number=int(payment.move_id.line_ids.mapped('contract_id').group_id.ref), + amount=int(payment.amount), + reference=payment.id[:16]) return payment_initiation.to_ocr().encode('iso-8859-1'), "{}.txt".format(self.name) diff --git a/compassion_sweden_payment/models/account_statement_import_bggiro_parser.py b/compassion_sweden_payment/models/account_statement_import_bggiro_parser.py index bb29d29..fe8b7a5 100644 --- a/compassion_sweden_payment/models/account_statement_import_bggiro_parser.py +++ b/compassion_sweden_payment/models/account_statement_import_bggiro_parser.py @@ -12,7 +12,7 @@ from io import StringIO from os import path -from odoo import _, api, models +from odoo import _, api, models, fields from .. import bggiro _logger = logging.getLogger(__name__) @@ -28,44 +28,37 @@ class AccountBankStatementImportPayPalParser(models.TransientModel): _description = "Account Statement Import Betalingsservice Parser " @api.model - def parse(self, data_file, filename): - journal = self.env["account.journal"].browse(self.env.context.get("journal_id")) + def parse(self, data_file): + file_data = bggiro.parse(StringIO(data_file.decode("iso-8859-1")).read()) + Journal = self.env["account.journal"] + journal = Journal.search([ + ("payment_mode_id.initiating_party_identifier", "=", file_data.customer_number) + ], limit=1) or Journal.browse(self.env.context.get("journal_id")) currency_code = (journal.currency_id or journal.company_id.currency_id).name account_number = journal.bank_account_id.acc_number - - name = _("%s: %s") % ( - journal.code, - path.basename(filename), - ) - file_data = bggiro.parse(StringIO(data_file.decode("iso-8859-1")).read()) - lines = [p for p in file_data.payments if p.payment_status_code == bggiro.PaymentStatus.APPROVED] + name = journal.code + str(fields.Datetime.now()) + lines = [p for p in file_data.payments if p.payment_status_code != bggiro.PaymentStatus.APPROVED] if not lines: return currency_code, account_number, [{"name": name, "transactions": []}] date = file_data.date_written transactions = list(map(lambda line: self._convert_line_to_transactions(line), lines)) - return ( - currency_code, - account_number, - [ - { - "name": name, - "date": date, - "balance_start": float(-file_data.get_total_amount_incoming()), - "balance_end_real": float(0), - "transactions": transactions, - } - ], - ) + return { + "name": name, + "date": date, + "account_number": account_number, + "transactions": transactions, + } @api.model def _convert_line_to_transactions(self, line: bggiro.Payment): pay_opt = self.env['recurring.contract.group'].search([('ref', '=', line.payer_number)], limit=1) + payment = self.env["account.payment"].search([("ref", "=", line.reference)], limit=1) return { "partner_id": pay_opt.partner_id.id, "amount": str(line.amount), "date": line.payment_date, - # str(line.payer_bankgiro_number) We do not implement the account_number see cp-264 comment - "account_number": False, - "ref": line.payer_number, - "payment_ref": line.reference or "" + "concept": line.reference, + "reference": payment.move_id.name, + "reason_code": line.payment_status_code.value, + "raw_import_data": line } diff --git a/compassion_sweden_payment/wizards/__init__.py b/compassion_sweden_payment/wizards/__init__.py index ab6335e..b988720 100644 --- a/compassion_sweden_payment/wizards/__init__.py +++ b/compassion_sweden_payment/wizards/__init__.py @@ -9,4 +9,4 @@ # ############################################################################## from . import generate_tax_wizard -from . import account_statement_import +from . import payment_return_import diff --git a/compassion_sweden_payment/wizards/account_statement_import.py b/compassion_sweden_payment/wizards/account_statement_import.py deleted file mode 100644 index f768e48..0000000 --- a/compassion_sweden_payment/wizards/account_statement_import.py +++ /dev/null @@ -1,30 +0,0 @@ -############################################################################## -# -# Copyright (C) 2015-2022 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty -# @author: Robin Berguerand -# -# -# The licence is in the file __manifest__.py -# -############################################################################## -import logging - -from odoo import models - -_logger = logging.getLogger(__name__) - - -class AccountStatementImport(models.TransientModel): - _inherit = "account.statement.import" - - def _parse_file(self, data_file): - self.ensure_one() - try: - Parser = self.env["account.statement.import.bggiro.parser"] - return Parser.parse( - data_file, self.statement_filename - ) - except ValueError as e: - _logger.warning(f"Sweden BGgiro parser error {e}", exc_info=True) - return super()._parse_file(data_file) diff --git a/compassion_sweden_payment/wizards/payment_return_import.py b/compassion_sweden_payment/wizards/payment_return_import.py new file mode 100644 index 0000000..d53ac12 --- /dev/null +++ b/compassion_sweden_payment/wizards/payment_return_import.py @@ -0,0 +1,21 @@ +# Copyright 2023 Compassion CH Simon Gonzalez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from odoo import _, api, models +_logger = logging.getLogger(__name__) + + +class PaymentReturnImport(models.TransientModel): + _inherit = "payment.return.import" + + @api.model + def _parse_file(self, data_file): + try: + Parser = self.env["account.statement.import.bggiro.parser"] + return Parser.with_context(journal_id=self.journal_id.id).parse( + data_file + ) + except Exception: + _logger.warning(_("The file couldn't be parsed by Swedish bggiro parser"), exc_info=True) + return super()._parse_file(data_file)