All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kapott.hbci.GV.GVKUmsAllCamt Maven / Gradle / Ivy

Go to download

HBCI4j - Home Banking Computer Interface for Java - Clone from https://github.com/hbci4j/hbci4java

There is a newer version: 3.5.46
Show newest version
/**********************************************************************
 *
 * Copyright (c) by Olaf Willuhn
 * All rights reserved
 * LGPL
 *
 **********************************************************************/

package org.kapott.hbci.GV;

import lombok.extern.slf4j.Slf4j;
import org.kapott.hbci.GV.parsers.ISEPAParser;
import org.kapott.hbci.GV.parsers.SEPAParserFactory;
import org.kapott.hbci.GV_Result.GVRKUms;
import org.kapott.hbci.GV_Result.GVRKUms.BTag;
import org.kapott.hbci.comm.CommPinTan;
import org.kapott.hbci.exceptions.HBCI_Exception;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.passport.HBCIPassportInternal;
import org.kapott.hbci.sepa.SepaVersion;
import org.kapott.hbci.sepa.SepaVersion.Type;
import org.kapott.hbci.status.HBCIMsgStatus;

import java.io.ByteArrayInputStream;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Implementierung des Geschaeftsvorfalls zum Abruf von Umsaetzen mit Angabe des Zeitraums im CAMT-Format (HKCAZ).
 */
@Slf4j
public class GVKUmsAllCamt extends AbstractSEPAGV {

    private boolean rawResponse;

    public GVKUmsAllCamt(HBCIPassportInternal passport, String name) {
        super(passport, name, new GVRKUms(passport));
    }

    public GVKUmsAllCamt(HBCIPassportInternal passport, boolean rawResponse) {
        this(passport, getLowlevelName());

        this.rawResponse = rawResponse;

        addConstraint("my.bic", "KTV.bic", null);
        addConstraint("my.iban", "KTV.iban", null);

        if (this.canNationalAcc(passport)) {
            addConstraint("my.country", "KTV.KIK.country", "DE");
            addConstraint("my.blz", "KTV.KIK.blz", null);
            addConstraint("my.number", "KTV.number", null);
            addConstraint("my.subnumber", "KTV.subnumber", "");
        }

        // Das DE erlaubt zwar, dass wir alle CAMT-Versionen mitschicken,
        // die wir unterstuetzen. Einige Banken (u.a. die Sparkassen) kommen
        // damit aber nicht klar. Deswegen schicken wir immer genau eine Version
        // mit. Und zwar genau die hoechste, die die Bank in den GV-spezifischen BPD
        // mitgeteilt hat
        addConstraint("suppformat", "formats.suppformat", this.getPainVersion().getURN());
        addConstraint("dummy", "allaccounts", "N");

        addConstraint("startdate", "startdate", this.getStartdate());
        addConstraint("enddate", "enddate", "");
        addConstraint("maxentries", "maxentries", "");
        addConstraint("offset", "offset", "");
    }

    /**
     * @return der Lowlevelname.
     */
    public static String getLowlevelName() {
        return "KUmsZeitCamt";
    }

    @Override
    protected SepaVersion getDefaultPainVersion() {
        return SepaVersion.CAMT_052_001_01;
    }

    @Override
    protected Type getPainType() {
        return Type.CAMT_052;
    }

    /**
     * Liefert das fruehest moegliche Startdatum fuer den Abruf der Umsaetze.
     * Im Gegensatz zur alten MT940-Version ist es jetzt bei CAMT offensichtlich
     * so, dass man (zumindest bei einigen Banken) nicht mehr pauschal das Start-Datum
     * weglassen kann und die Bank dann alles an Daten liefert. Zumindest bei der
     * Sparkasse kam dann die Fehlermeldung "9010:Abfrage uebersteigt gueltigen Zeitraum".
     * Also muessen wir - falls kein Startdatum angegeben ist (daher als Default-Wert)
     * selbst anhand der BPD herausfinden, was das Limit ist und dieses als Default-Wert
     * verwenden.
     *
     * @return das fruehest moegliche Startdatum fuer den Abruf der Umsaetze.
     */
    private String getStartdate() {
        Map bpd = this.getJobRestrictions();
        String days = bpd.get("timerange");

        String date = "";
        if (days != null && days.length() > 0 && days.matches("[0-9]{1,4}")) {
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DATE, -Integer.parseInt(days));
            date = HBCIUtils.date2StringISO(cal.getTime());
        }
        log.info("earliest start date according to BPD: " + (date != null && date.length() > 0 ? date : ""));
        return date;
    }

    @Override
    protected void extractResults(HBCIMsgStatus msgstatus, String header, int idx) {
        HashMap data = msgstatus.getData();
        GVRKUms result = (GVRKUms) jobResult;
        final String format = data.get(header + ".format");

        for (int i = 0; ; i++) {
            final String booked = data.get(header + ".booked." + HBCIUtils.withCounter("message", i));
            if (booked == null)
                break;

            result.camtBooked.add(booked);

            if (!rawResponse) {
                parseCamtBooked(result, format, booked);
            }
        }

        final String notbooked = data.get(header + ".notbooked");
        if (notbooked != null) {
            parseCamtNotBooked(result, format, notbooked);
        }
    }

    private void parseCamtBooked(GVRKUms result, String format, String camt) {
        try {
            // Im Prinzip wuerde es reichen, die verwendete CAMT-Version einmalig anhand
            // des uebergebenen camt-Deskriptors in "format" zu ermitteln. Aber es gibt
            // tatsaechlich Banken, die in der HBCI-Nachricht eine andere Version angeben,
            // als sie tatsaechlich senden. Siehe https://www.willuhn.de/bugzilla/show_bug.cgi?id=1806
            // Das betraf PAIN-Messages. Ich weiss nicht, ob das bei CAMT auch vorkommt.
            // Ich gehe aber auf Nummer sicher.
            final SepaVersion version = SepaVersion.choose(format, camt);
            ISEPAParser> parser = SEPAParserFactory.get(version);

            log.debug("  parsing camt data: " + camt);
            parser.parse(new ByteArrayInputStream(camt.getBytes(CommPinTan.ENCODING)), result.getDataPerDay());
            log.debug("  parsed camt data, entries: " + result.getFlatData().size());
        } catch (Exception e) {
            log.error("  unable to parse camt data: " + e.getMessage());
            throw new HBCI_Exception("Error parsing CAMT document", e);
        }
    }

    private void parseCamtNotBooked(GVRKUms result, String format, String notbooked) {
        try {
            final SepaVersion version = SepaVersion.choose(format, notbooked);
            ISEPAParser> parser = SEPAParserFactory.get(version);

            log.debug("  parsing unbooked camt data: " + notbooked);
            result.camtNotBooked = notbooked;
            parser.parse(new ByteArrayInputStream(notbooked.getBytes(CommPinTan.ENCODING)),
                result.getDataPerDayUnbooked());
            log.debug("  parsed unbooked camt data, entries: " + result.getFlatDataUnbooked().size());
        } catch (Exception e) {
            log.error("  unable to parse unbooked camt data: " + e.getMessage());
            throw new HBCI_Exception("Error parsing CAMT document", e);
        }
    }

    @Override
    public void verifyConstraints() {
        super.verifyConstraints();
        checkAccountCRC("my");
    }

    @Override
    public String getPainJobName() {
        return getLowlevelName();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy