Ejemplo n.º 1
0
    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