def parse_file(filename): log.info("parse file {}".format(filename)) tree = ET.parse(filename) root = tree.getroot() payments = [] ns = {'pf': 'urn:iso:std:iso:20022:tech:xsd:camt.053.001.04'} def find_or_empty(transaction, name): e = transaction.find(".//pf:{}".format(name), ns) return e.text if e is not None else "" for transaction in root.findall(".//pf:Ntry", ns): # check if transaction id is valid transaction exists already -> skip transaction_id = find_or_empty(transaction, 'AcctSvcrRef') only_zero_regex = re.compile(r"^0*$") if only_zero_regex.match(transaction_id): log.warning("A transaction of file {} has an invalid transaction ID: {}".format(filename, transaction_id)) continue log.info("processing transaction {}".format(transaction_id)) payments_count = Payment.objects.filter(transaction_id=transaction_id).count() if payments_count > 0: log.warning( "transaction {} in file {} already exists in database".format(transaction_id, filename)) continue payment = Payment() # for IBAN transactions payment.bic = find_or_empty(transaction, 'BICFI') payment.iban = find_or_empty(transaction, 'DbtrAcct') # unique reference number by postfinance payment.transaction_id = transaction_id payment.amount = float(find_or_empty(transaction, 'Amt') or 0.0) payment.currency_code = transaction.find('.//pf:Amt', ns).get('Ccy') # Credit or Debit credit_debit = find_or_empty(transaction, 'CdtDbtInd') if credit_debit == 'CRDT': payment.credit_debit = Payment.CreditDebit.CREDIT elif credit_debit == 'DBIT': payment.credit_debit = Payment.CreditDebit.DEBIT else: payment.credit_debit = Payment.CreditDebit.UNKNOWN # remittance user string payment.remittance_user_string = find_or_empty(transaction, 'AddtlNtryInf') user_data = ISO2022Parser.parse_user_string(payment.remittance_user_string) if user_data is not None: payment.name = user_data['name'] payment.address = "{}, {} {}".format(user_data['street'], user_data['plz'], user_data['city']) payment.remittance_user_string = user_data['note'] payment.state = Payment.State.NEW # postal_address = debitor.find(".//pf:PstlAdr",ns) # if postal_address: # addresses = debitor.findall(".//pf:AdrLine", ns) # payment.address = ", ".join([adr.text for adr in addresses]) payment.date = datetime.today() # TODO not exactly elegant payment.filename = os.path.split(filename)[-1] payments.append(payment) log.info('Detected payment: {}'.format(payment)) return payments