changeset d09b18cbf5be in modules/account_payment_sepa:6.4
details: 
https://hg.tryton.org/modules/account_payment_sepa?cmd=changeset&node=d09b18cbf5be
description:
        Handle multiple transactions in CAMT054 Ntry tags

        issue11672
        review413471003
        (grafted from fc8e9d9cb870d9353ff374120688b8e9779b90c0)
diffstat:

 sepa_handler.py |  84 +++++++++++++++++++++++++++++---------------------------
 1 files changed, 44 insertions(+), 40 deletions(-)

diffs (122 lines):

diff -r 629907cf742d -r d09b18cbf5be sepa_handler.py
--- a/sepa_handler.py   Fri Jul 01 23:54:36 2022 +0200
+++ b/sepa_handler.py   Mon Oct 03 00:13:39 2022 +0200
@@ -35,48 +35,59 @@
             element.clear()
 
     def handle_entry(self, element):
-        payments = self.get_payments(element)
-        if self.is_returned(element):
-            for payment in payments:
-                self.set_return_information(payment, element)
-            self.Payment.save(payments)
-            self.Payment.fail(payments)
-        else:
-            date_value = self.date_value(element)
+        tag = etree.QName(element)
+        failed, succeeded = [], []
+        date_value = self.date_value(element)
+
+        for transaction in element.findall('.//{%s}TxDtls' % tag.namespace):
+            payments = self.get_payments(transaction)
+            if self.is_returned(transaction):
+                for payment in payments:
+                    self.set_return_information(payment, transaction)
+                failed.extend(payments)
+            else:
+                succeeded.extend(payments)
+
+        if failed:
+            self.Payment.save(failed)
+            self.Payment.fail(failed)
+        if succeeded:
             with Transaction().set_context(date_value=date_value):
-                self.Payment.succeed(payments)
+                self.Payment.succeed(succeeded)
 
     def get_payment_kind(self, element):
-        tag = etree.QName(element)
-        return self._kinds[
-            element.find('./{%s}CdtDbtInd' % tag.namespace).text]
+        camt_ns = etree.QName(element).namespace
+        for path in [
+                './camt:CdtDbtInd',
+                './ancestor::camt:NtryDtls/camt:Btch/camt:CdtDbtInd',
+                './ancestor::camt:Ntry/camt:CdtDbtInd',
+                ]:
+            cdtdbtind = element.xpath(path, namespaces={'camt': camt_ns})
+            if cdtdbtind:
+                return self._kinds[cdtdbtind[0].text]
     _kinds = {
         'CRDT': 'payable',
         'DBIT': 'receivable',
         }
 
-    def get_payments(self, element):
-        tag = etree.QName(element)
-        details = element.find('./{%s}NtryDtls' % tag.namespace)
-        if details is None:
-            # Version 1 doesn't have NtryDtls but directly TxDtls
-            details = element.find('./{%s}TxDtls' % tag.namespace)
-        if details is None:
-            return []
-        instr_id = details.find('.//{%s}InstrId' % tag.namespace)
+    def get_payments(self, transaction):
+        tag = etree.QName(transaction)
+        instr_id = transaction.find(
+            './/{%s}InstrId' % tag.namespace)
+        end_to_end_id = transaction.find(
+            './/{%s}EndToEndId' % tag.namespace)
+        payment_kind = self.get_payment_kind(transaction)
         if instr_id is not None:
-            payments = self.Payment.search([
+            return self.Payment.search([
                     ('sepa_instruction_id', '=', instr_id.text),
-                    ('kind', '=', self.get_payment_kind(element)),
+                    ('kind', '=', payment_kind),
                     ])
-            return payments
-        end_to_end_id = details.find('.//{%s}EndToEndId' % tag.namespace)
-        if end_to_end_id is not None:
-            payments = self.Payment.search([
+        elif end_to_end_id is not None:
+            return self.Payment.search([
                     ('sepa_end_to_end_id', '=', end_to_end_id.text),
-                    ('kind', '=', self.get_payment_kind(element)),
+                    ('kind', '=', payment_kind),
                     ])
-            return payments
+        return []
 
     def date_value(self, element):
         tag = etree.QName(element)
@@ -92,25 +103,18 @@
 
     def is_returned(self, element):
         tag = etree.QName(element)
-        details = element.find('./{%s}NtryDtls' % tag.namespace)
-        if details is None:
-            return
-        return_reason = details.find('.//{%s}RtrInf' % tag.namespace)
-        if return_reason is None:
-            return False
-        return True
+        return_reason = element.find('.//{%s}RtrInf' % tag.namespace)
+        return return_reason is not None
 
     def set_return_information(self, payment, element):
         tag = etree.QName(element)
 
         reason_code = element.find(
-            './{%(ns)s}NtryDtls//{%(ns)s}RtrInf/{%(ns)s}Rsn/{%(ns)s}Cd'
-            % {'ns': tag.namespace})
+            './/{%(ns)s}RtrInf/{%(ns)s}Rsn/{%(ns)s}Cd' % {'ns': tag.namespace})
         if reason_code is not None:
             payment.sepa_return_reason_code = reason_code.text
 
         reason_information = element.find(
-            './{%(ns)s}NtryDtls//{%(ns)s}RtrInf/{%(ns)s}AddtlInf'
-            % {'ns': tag.namespace})
+            './/{%(ns)s}RtrInf/{%(ns)s}AddtlInf' % {'ns': tag.namespace})
         if reason_information is not None:
             payment.sepa_return_reason_information = reason_information.text

Reply via email to