From 076473f46e70968fe498850a2ec1819267299dba Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:37:43 +0000
Subject: [PATCH 1/3] Initial plan
From 5d0d2d963149635735ac13fe60c19b7023a40fd3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:43:21 +0000
Subject: [PATCH 2/3] Add RemittanceInformationFull field to capture all Ustrd
elements - fixes #6
Co-authored-by: ODAncona <71207824+ODAncona@users.noreply.github.com>
---
pycamt/parser.py | 5 ++
tests/test_parser.py | 164 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+)
diff --git a/pycamt/parser.py b/pycamt/parser.py
index 2d1b4e3..094ca8e 100644
--- a/pycamt/parser.py
+++ b/pycamt/parser.py
@@ -306,6 +306,11 @@ def _extract_transaction_details(self, tx_detail):
if tx_detail.find(".//RmtInf//Ustrd", self.namespaces) is not None
else None
),
+ "RemittanceInformationFull": (
+ " ".join(rinfo.text.strip() for rinfo in tx_detail.findall(".//RmtInf//Ustrd", self.namespaces) if rinfo.text)
+ if tx_detail.findall(".//RmtInf//Ustrd", self.namespaces)
+ else None
+ ),
}
structured_remittance_elem = tx_detail.find(".//RmtInf//Strd", self.namespaces)
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 6b4e7ad..af424fc 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -88,3 +88,167 @@ def test_get_statement_info(self, parser):
"ClosingBalanceDate": None
}]
assert parser.get_statement_info() == expected
+
+ def test_multiple_remittance_information(self):
+ """Test that multiple Ustrd elements in RemittanceInformation are captured"""
+ xml_data = """
+
+
+
+ ABC123
+ 2020-06-23T18:56:25.64Z
+
+
+
+
+ GB33BUKB20201555555555
+
+
+
+ 69.06
+ CRDT
+
+ 2020-07-07
+
+
+ 2020-07-07
+
+ 123
+
+
+
+ ENDTOENDID123
+
+
+ Ref.. 1234567890123456
+ Betrag EUR 69,06
+ /ADRS CH/Basel,1234
+ A12345/ Best 00123456
+ 7185) Peter Pan
+ Urspr. EUR 69,06
+ ADRS Re xxxxx,4 CH/Basel
+ Land,1234/
+ ERST RAIFCH12345
+
+
+
+
+
+
+
+ """
+ parser = Camt053Parser(xml_data)
+ transactions = parser.get_transactions()
+
+ assert len(transactions) == 1
+ transaction = transactions[0]
+
+ # Current behavior: only first Ustrd element
+ assert transaction["RemittanceInformation"] == "Ref.. 1234567890123456"
+
+ # New behavior: all Ustrd elements joined
+ expected_full = (
+ "Ref.. 1234567890123456 Betrag EUR 69,06 "
+ "/ADRS CH/Basel,1234 A12345/ Best 00123456 7185) Peter Pan "
+ "Urspr. EUR 69,06 ADRS Re xxxxx,4 CH/Basel "
+ "Land,1234/ ERST RAIFCH12345"
+ )
+ assert "RemittanceInformationFull" in transaction
+ assert transaction["RemittanceInformationFull"] == expected_full
+
+ def test_single_remittance_information_backward_compatibility(self):
+ """Test that single Ustrd element works for both fields"""
+ xml_data = """
+
+
+
+ ABC123
+ 2020-06-23T18:56:25.64Z
+
+
+
+
+ GB33BUKB20201555555555
+
+
+
+ 500.00
+ CRDT
+
+ 2020-06-23
+
+
+ 2020-06-23
+
+ 123
+
+
+
+ ENDTOENDID123
+
+
+ Single remittance info
+
+
+
+
+
+
+
+ """
+ parser = Camt053Parser(xml_data)
+ transactions = parser.get_transactions()
+
+ assert len(transactions) == 1
+ transaction = transactions[0]
+
+ # Both fields should have the same value for single Ustrd
+ assert transaction["RemittanceInformation"] == "Single remittance info"
+ assert transaction["RemittanceInformationFull"] == "Single remittance info"
+
+ def test_no_remittance_information(self):
+ """Test that transactions without RemittanceInformation still work"""
+ xml_data = """
+
+
+
+ ABC123
+ 2020-06-23T18:56:25.64Z
+
+
+
+
+ GB33BUKB20201555555555
+
+
+
+ 500.00
+ CRDT
+
+ 2020-06-23
+
+
+ 2020-06-23
+
+ 123
+
+
+
+ ENDTOENDID123
+
+
+
+
+
+
+
+ """
+ parser = Camt053Parser(xml_data)
+ transactions = parser.get_transactions()
+
+ assert len(transactions) == 1
+ transaction = transactions[0]
+
+ # Both fields should be None when no remittance info exists
+ assert "RemittanceInformation" not in transaction # Filtered out by return statement
+ assert "RemittanceInformationFull" not in transaction # Filtered out by return statement
From 8073b2e04a0c764f3ded940d7399231a6e6f749f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 18 Sep 2025 10:44:43 +0000
Subject: [PATCH 3/3] Update documentation for new RemittanceInformationFull
field
Co-authored-by: ODAncona <71207824+ODAncona@users.noreply.github.com>
---
docs/index.md | 6 ++++++
pycamt/parser.py | 3 +++
2 files changed, 9 insertions(+)
diff --git a/docs/index.md b/docs/index.md
index 46e007e..63b3038 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -61,6 +61,12 @@ for transaction in transactions:
print(transaction)
```
+**Note**: Each transaction includes remittance information in two fields:
+- `RemittanceInformation`: Contains only the first unstructured remittance line
+- `RemittanceInformationFull`: Contains all unstructured remittance lines joined with spaces
+
+This is particularly useful for international transactions that may contain multiple lines of remittance information.
+
### Extracting Statement Information
To get basic statement information like IBAN and opening/closing balance:
diff --git a/pycamt/parser.py b/pycamt/parser.py
index 094ca8e..1475397 100644
--- a/pycamt/parser.py
+++ b/pycamt/parser.py
@@ -258,6 +258,9 @@ def _extract_transaction_details(self, tx_detail):
-------
dict
Detailed information extracted from the transaction detail element.
+ Includes RemittanceInformation (first Ustrd) and RemittanceInformationFull
+ (all Ustrd elements joined with spaces) for backward compatibility and
+ comprehensive remittance data capture.
"""
data = {