From 82285e236f52928cd217eb9e7f848e78c54e4613 Mon Sep 17 00:00:00 2001 From: Srujan N Date: Mon, 22 Sep 2025 20:46:44 +0000 Subject: [PATCH] fix: handle MT940 statement numbers longer than 5 digits The MT940 standard expects statement numbers to be maximum 5 digits, but some banks provide longer statement numbers that cause parsing errors. Problem: - MT940 files with statement numbers > 5 digits fail to parse - Error: "Unable to parse StatementNumber object from '167619/1'" - This breaks bank statement import functionality Solution: - Add preprocess_mt940_content() function to truncate long statement numbers - Preserve sequence numbers (e.g., '/1') when present - Apply preprocessing before mt940.parse() to ensure compatibility The fix truncates statement numbers to the last 5 digits while maintaining the MT940 format structure, allowing successful parsing of previously failing bank statements. --- .../bank_statement_import.py | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py index 2d5422f0d16..bb61eb094c0 100644 --- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py +++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py @@ -112,6 +112,32 @@ class BankStatementImport(DataImport): @frappe.whitelist() +def preprocess_mt940_content(content): + """Preprocess MT940 content to fix statement number format issues. + + The MT940 standard expects statement numbers to be maximum 5 digits, + but some banks provide longer statement numbers that cause parsing errors. + This function truncates statement numbers longer than 5 digits to the last 5 digits. + """ + # Pattern to match :28C: field with statement number and optional sequence + pattern = r'(:28C:)(\d{6,})(/\d+)?' + + def replace_statement_number(match): + prefix = match.group(1) # ':28C:' + statement_num = match.group(2) # The statement number + sequence_part = match.group(3) or '' # The sequence part like '/1' + + # If statement number is longer than 5 digits, truncate to last 5 digits + if len(statement_num) > 5: + statement_num = statement_num[-5:] + + return prefix + statement_num + sequence_part + + # Apply the replacement + processed_content = re.sub(pattern, replace_statement_number, content) + return processed_content + + def convert_mt940_to_csv(data_import, mt940_file_path): doc = frappe.get_doc("Bank Statement Import", data_import) @@ -124,7 +150,9 @@ def convert_mt940_to_csv(data_import, mt940_file_path): frappe.throw(_("MT940 file detected. Please enable 'Import MT940 Format' to proceed.")) try: - transactions = mt940.parse(content) + # Preprocess MT940 content to fix statement number format issues + processed_content = preprocess_mt940_content(content) + transactions = mt940.parse(processed_content) except Exception as e: frappe.throw(_("Failed to parse MT940 format. Error: {0}").format(str(e)))