fints/formals.py
class ParameterChallengeClass(DataElementGroup):
    """Parameter Challenge-Klasse

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    parameters = DataElementField(type='an', max_length=999, count=9, required=False)
fints/formals.py
class BankIdentifier(DataElementGroup):
    COUNTRY_ALPHA_TO_NUMERIC = {
        # Kapitel E.4 der SEPA-Geschäftsvorfälle
        'BE': '056',
        'BG': '100',
        'DK': '208',
        'DE': '280',
        'FI': '246',
        'FR': '250',
        'GR': '300',
        'GB': '826',
        'IE': '372',
        'IS': '352',
        'IT': '380',
        'JP': '392',
        'CA': '124',
        'HR': '191',
        'LI': '438',
        'LU': '442',
        'NL': '528',
        'AT': '040',
        'PL': '616',
        'PT': '620',
        'RO': '642',
        'RU': '643',
        'SE': '752',
        'CH': '756',
        'SK': '703',
        'SI': '705',
        'ES': '724',
        'CZ': '203',
        'TR': '792',
        'HU': '348',
        'US': '840',
        'EU': '978'
    }
    COUNTRY_NUMERIC_TO_ALPHA = {v: k for k, v in COUNTRY_ALPHA_TO_NUMERIC.items()}
    COUNTRY_NUMERIC_TO_ALPHA['276'] = 'DE'  # not yet in use by banks, but defined by ISO

    country_identifier = DataElementField(type='ctr')
    bank_code = DataElementField(type='an', max_length=30)
fints/fields.py
class CodeField(CodeFieldMixin, AlphanumericField):
    type = 'code'
    _DOC_TYPE = str
fints/formals.py
class KTI1(DataElementGroup):
    """Kontoverbindung international, version 1

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle """
    iban = DataElementField(type='an', max_length=34, required=False, _d="IBAN")
    bic = DataElementField(type='an', max_length=11, required=False, _d="BIC")
    account_number = DataElementField(type='id', required=False, _d="Konto-/Depotnummer")
    subaccount_number = DataElementField(type='id', required=False, _d="Unterkontomerkmal")
    bank_identifier = DataElementGroupField(type=BankIdentifier, required=False, _d="Kreditinstitutskennung")

    @classmethod
    def from_sepa_account(cls, acc):
        return cls(
            iban=acc.iban,
            bic=acc.bic,
        )
fints/formals.py
class TANMediaClass4(RepresentableEnum):
    """TAN-Medium-Klasse, version 4

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    ALL = 'A'  #: Alle Medien
    LIST = 'L'  #: Liste
    GENERATOR = 'G'  #: TAN-Generator
    MOBILE = 'M'  #: Mobiltelefon mit mobileTAN
    SECODER = 'S'  #: Secoder
    BILATERAL = 'B'  #: Bilateral vereinbart
fints/formals.py
class ParameterTwostepTAN1(ParameterTwostepCommon):
    security_profile_bank_signature = DataElementField(type='code', length=1)
    twostep_parameters = DataElementGroupField(type=TwoStepParameters1, min_count=1, max_count=98)
fints/formals.py
class ParameterTwostepTAN4(ParameterTwostepCommon):
    twostep_parameters = DataElementGroupField(type=TwoStepParameters4, min_count=1, max_count=98)
fints/formals.py
class TANMedia5(DataElementGroup):
    """TAN-Medium-Liste, version 5

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    tan_medium_class = CodeField(enum=TANMediaClass4, _d="TAN-Medium-Klasse")
    status = CodeField(enum=TANMediumStatus, _d="Status")
    security_function = DataElementField(type='num', required=False, _d="Sicherheitsfunktion, kodiert")
    card_number = DataElementField(type='id', required=False, _d="Kartennummer")
    card_sequence = DataElementField(type='id', required=False, _d="Kartenfolgenummer")
    card_type = DataElementField(type='num', required=False, _d="Kartenart")
    account = DataElementGroupField(type=Account3, required=False, _d="Kontonummer Auftraggeber")
    valid_from = DataElementField(type='dat', required=False, _d="Gültig ab")
    valid_until = DataElementField(type='dat', required=False, _d="Gültig bis")
    tan_list_number = DataElementField(type='an', max_length=20, required=False, _d="TAN-Listennummer")
    tan_medium_name = DataElementField(type='an', max_length=32, required=False, _d="Bezeichnung des TAN-Mediums")
    mobile_number_masked = DataElementField(type='an', max_length=35, required=False, _d="Mobiltelefonnummer, verschleiert")
    mobile_number = DataElementField(type='an', max_length=35, required=False, _d="Mobiltelefonnummer")
    sms_charge_account = DataElementGroupField(type=KTI1, required=False, _d="SMS-Abbuchungskonto")
    number_free_tans = DataElementField(type='num', max_length=3, required=False, _d="Anzahl freie TANs")
    last_use = DataElementField(type='dat', required=False, _d="Letzte Benutzung")
    active_since = DataElementField(type='dat', required=False, _d="Freigeschaltet am")
fints/formals.py
class ParameterTwostepTAN6(ParameterTwostepCommon):
    twostep_parameters = DataElementGroupField(type=TwoStepParameters6, min_count=1, max_count=98)
fints/formals.py
class SystemIDStatus(RepresentableEnum):
    """Kundensystem-Status, version 2

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Formals"""
    ID_UNNECESSARY = '0'  #: Kundensystem-ID wird nicht benötigt
    ID_NECESSARY = '1'  #: Kundensystem-ID wird benötigt
fints/formals.py
class ParameterPinTan(DataElementGroup):
    min_pin_length = DataElementField(type='num', max_length=2, required=False)
    max_pin_length = DataElementField(type='num', max_length=2, required=False)
    max_tan_length = DataElementField(type='num', max_length=2, required=False)
    user_id_field_text = DataElementField(type='an', max_length=30, required=False)
    customer_id_field_text = DataElementField(type='an', max_length=30, required=False)
    transaction_tans_required = DataElementGroupField(type=TransactionTanRequired, max_count=999, required=False)
fints/formals.py
class ParameterTwostepTAN2(ParameterTwostepCommon):
    twostep_parameters = DataElementGroupField(type=TwoStepParameters2, min_count=1, max_count=98)
fints/fields.py
class DataElementField(DocTypeMixin, TypedField):
    pass
fints/formals.py
class ChallengeValidUntil(DataElementGroup):
    """Gültigkeitsdatum und -uhrzeit für Challenge

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    date = DataElementField(type='dat', _d="Datum")
    time = DataElementField(type='tim', _d="Uhrzeit")
fints/formals.py
class TANUsageOption(RepresentableEnum):
    """TAN-Einsatzoption

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    ALL_ACTIVE = '0'  #: Kunde kann alle "aktiven" Medien parallel nutzen
    EXACTLY_ONE = '1'  #: Kunde kann genau ein Medium zu einer Zeit nutzen
    MOBILE_AND_GENERATOR = '2'  #: Kunde kann ein Mobiltelefon und einen TAN-Generator parallel nutzen
fints/formals.py
class TANMediaClass3(RepresentableEnum):
    """TAN-Medium-Klasse, version 3

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    ALL = 'A'  #: Alle Medien
    LIST = 'L'  #: Liste
    GENERATOR = 'G'  #: TAN-Generator
    MOBILE = 'M'  #: Mobiltelefon mit mobileTAN
    SECODER = 'S'  #: Secoder
fints/formals.py
class Language2(RepresentableEnum):
    """Dialogsprache

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Formals"""
    DEFAULT = '0'  #: Standard
    DE = '1'  #: Deutsch, 'de', Subset Deutsch, Codeset 1 (Latin 1)
    EN = '2'  #: Englisch, 'en', Subset Englisch, Codeset 1 (Latin 1)
    FR = '3'  #: Französisch, 'fr', Subset Französisch, Codeset 1 (Latin 1)
fints/segments/base.py
class FinTS3Segment(Container, SubclassesMixin, metaclass=FinTS3SegmentMeta):
    header = DataElementGroupField(type=SegmentHeader, _d="Segmentkopf")

    @classproperty
    def TYPE(cls):
        match = TYPE_VERSION_RE.match(cls.__name__)
        if match:
            return match.group(1)

    @classproperty
    def VERSION(cls):
        match = TYPE_VERSION_RE.match(cls.__name__)
        if match:
            return int(match.group(2))

    def __init__(self, *args, **kwargs):
        if 'header' not in kwargs:
            kwargs['header'] = SegmentHeader(self.TYPE, None, self.VERSION)

        args = (kwargs.pop('header'), ) + args

        super().__init__(*args, **kwargs)

    @classmethod
    def find_subclass(cls, segment):
        h = SegmentHeader.naive_parse(segment[0])
        target_cls = None

        for possible_cls in cls._all_subclasses():
            if getattr(possible_cls, 'TYPE', None) == h.type and getattr(possible_cls, 'VERSION', None) == h.version:
                target_cls = possible_cls

        if not target_cls:
            target_cls = cls

        return target_cls
fints/formals.py
class ParameterTwostepTAN3(ParameterTwostepCommon):
    twostep_parameters = DataElementGroupField(type=TwoStepParameters3, min_count=1, max_count=98)
fints/formals.py
class ParameterTwostepTAN5(ParameterTwostepCommon):
    twostep_parameters = DataElementGroupField(type=TwoStepParameters5, min_count=1, max_count=98)
fints/segments/base.py
class ParameterSegment(FinTS3Segment):
    max_number_tasks = DataElementField(type='num', max_length=3, _d="Maximale Anzahl Aufträge")
    min_number_signatures = DataElementField(type='num', length=1, _d="Anzahl Signaturen mindestens")
    security_class = IntCodeField(SecurityClass, length=1, _d="Sicherheitsklasse")
fints/formals.py
class TANMedia4(DataElementGroup):
    """TAN-Medium-Liste, version 4

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    tan_medium_class = CodeField(enum=TANMediaClass3, _d="TAN-Medium-Klasse")
    status = CodeField(enum=TANMediumStatus, _d="Status")
    card_number = DataElementField(type='id', required=False, _d="Kartennummer")
    card_sequence = DataElementField(type='id', required=False, _d="Kartenfolgenummer")
    card_type = DataElementField(type='num', required=False, _d="Kartenart")
    account = DataElementGroupField(type=Account3, required=False, _d="Kontonummer Auftraggeber")
    valid_from = DataElementField(type='dat', required=False, _d="Gültig ab")
    valid_until = DataElementField(type='dat', required=False, _d="Gültig bis")
    tan_list_number = DataElementField(type='an', max_length=20, required=False, _d="TAN-Listennummer")
    tan_medium_name = DataElementField(type='an', max_length=32, required=False, _d="Bezeichnung des TAN-Mediums")
    mobile_number_masked = DataElementField(type='an', max_length=35, required=False, _d="Mobiltelefonnummer, verschleiert")
    mobile_number = DataElementField(type='an', max_length=35, required=False, _d="Mobiltelefonnummer")
    sms_charge_account = DataElementGroupField(type=KTI1, required=False, _d="SMS-Abbuchungskonto")
    number_free_tans = DataElementField(type='num', max_length=3, required=False, _d="Anzahl freie TANs")
    last_use = DataElementField(type='dat', required=False, _d="Letzte Benutzung")
    active_since = DataElementField(type='dat', required=False, _d="Freigeschaltet am")
fints/formals.py
class TANMediaType2(RepresentableEnum):
    """TAN-Medium-Art

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    ALL = '0'  #: Alle
    ACTIVE = '1'  #: Aktiv
    AVAILABLE = '2'  #: Verfügbar
fints/formals.py
class ResponseHHDUC(DataElementGroup):
    """Antwort HHD_UC

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    atc = DataElementField(type='an', max_length=5, _d="ATC")
    ac = DataElementField(type='bin', max_length=256, _d="Application Cryptogram AC")
    ef_id_data = DataElementField(type='bin', max_length=256, _d="EF_ID Data")
    cvr = DataElementField(type='bin', max_length=256, _d="CVR")
    version_info_chiptan = DataElementField(type='bin', max_length=256, _d="Versionsinfo der chipTAN-Applikation")
fints/fields.py
class DataElementGroupField(DocTypeMixin, ContainerField):
    pass


Question: from fints.fields import CodeField, DataElementField, DataElementGroupField
from fints.formals import (
    KTI1, BankIdentifier, ChallengeValidUntil, Language2,
    ParameterChallengeClass, ParameterPinTan, ParameterTwostepTAN1,
    ParameterTwostepTAN2, ParameterTwostepTAN3, ParameterTwostepTAN4,
    ParameterTwostepTAN5, ParameterTwostepTAN6, ResponseHHDUC,
    SystemIDStatus, TANMedia4, TANMedia5, TANMediaClass3,
    TANMediaClass4, TANMediaType2, TANUsageOption,
)
from .base import FinTS3Segment, ParameterSegment
    tan_medium_name = DataElementField(type='an', max_length=32, required=False, _d="Bezeichnung des TAN-Mediums")
    response_hhd_uc = DataElementGroupField(type=ResponseHHDUC, required=False, _d="Antwort HHD_UC")


class HITAN2(FinTS3Segment):
    """Zwei-Schritt-TAN-Einreichung Rückmeldung, version 2

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    tan_process = DataElementField(type='code', length=1, _d="TAN-Prozess")
    task_hash_value = DataElementField(type='bin', max_length=256, required=False, _d="Auftrags-Hashwert")
    task_reference = DataElementField(type='an', max_length=35, required=False, _d="Auftragsreferenz")
    challenge = DataElementField(type='an', max_length=2048, required=False, _d="Challenge")
    challenge_valid_until = DataElementGroupField(type=ChallengeValidUntil, required=False, _d="Gültigkeitsdatum und -uhrzeit für Challenge")
    tan_list_number = DataElementField(type='an', max_length=20, required=False, _d="TAN-Listennummer")
    ben = DataElementField(type='an', max_length=99, required=False, _d="BEN")


class HITAN3(FinTS3Segment):
    """Zwei-Schritt-TAN-Einreichung Rückmeldung, version 3

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    tan_process = DataElementField(type='code', length=1, _d="TAN-Prozess")
    task_hash_value = DataElementField(type='bin', max_length=256, required=False, _d="Auftrags-Hashwert")
    task_reference = DataElementField(type='an', max_length=35, required=False, _d="Auftragsreferenz")
    challenge = DataElementField(type='an', max_length=2048, required=False, _d="Challenge")
    challenge_valid_until = DataElementGroupField(type=ChallengeValidUntil, required=False, _d="Gültigkeitsdatum und -uhrzeit für Challenge")
    tan_list_number = DataElementField(type='an', max_length=20, required=False, _d="TAN-Listennummer")
    ben = DataElementField(type='an', max_length=99, required=False, _d="BEN")
    tan_medium_name = DataElementField(type='an', max_length=32, required=False, _d="Bezeichnung des TAN-Mediums")


class HITAN5(FinTS3Segment):
    """Zwei-Schritt-TAN-Einreichung Rückmeldung, version 5

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    tan_process = DataElementField(type='code', length=1, _d="TAN-Prozess")
    task_hash_value = DataElementField(type='bin', max_length=256, required=False, _d="Auftrags-Hashwert")
    task_reference = DataElementField(type='an', max_length=35, required=False, _d="Auftragsreferenz")
    challenge = DataElementField(type='an', max_length=2048, required=False, _d="Challenge")
    challenge_hhduc = DataElementField(type='bin', required=False, _d="Challenge HHD_UC")
    challenge_valid_until = DataElementGroupField(type=ChallengeValidUntil, required=False, _d="Gültigkeitsdatum und -uhrzeit für Challenge")
    tan_list_number = DataElementField(type='an', max_length=20, required=False, _d="TAN-Listennummer")
    ben = DataElementField(type='an', max_length=99, required=False, _d="BEN")
    tan_medium_name = DataElementField(type='an', max_length=32, required=False, _d="Bezeichnung des TAN-Mediums")


class HITAN6(FinTS3Segment):
    """Zwei-Schritt-TAN-Einreichung Rückmeldung, version 6

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""
    tan_process = DataElementField(type='code', length=1, _d="TAN-Prozess")
    task_hash_value = DataElementField(type='bin', max_length=256, required=False, _d="Auftrags-Hashwert")
    task_reference = DataElementField(type='an', max_length=35, required=False, _d="Auftragsreferenz")
    challenge = DataElementField(type='an', max_length=2048, required=False, _d="Challenge")
    challenge_hhduc = DataElementField(type='bin', required=False, _d="Challenge HHD_UC")
    challenge_valid_until = DataElementGroupField(type=ChallengeValidUntil, required=False, _d="Gültigkeitsdatum und -uhrzeit für Challenge")
    tan_medium_name = DataElementField(type='an', max_length=32, required=False, _d="Bezeichnung des TAN-Mediums")


class HKTAB4(FinTS3Segment):
    """TAN-Generator/Liste anzeigen Bestand, version 4

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    tan_media_type = CodeField(enum=TANMediaType2, _d="TAN-Medium-Art")
    tan_media_class = CodeField(enum=TANMediaClass3, _d="TAN-Medium-Klasse")


class HITAB4(FinTS3Segment):
    """TAN-Generator/Liste anzeigen Bestand Rückmeldung, version 4

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    tan_usage_option = CodeField(enum=TANUsageOption, _d="TAN_Einsatzoption")
    tan_media_list = DataElementGroupField(type=TANMedia4, max_count=99, required=False, _d="TAN-Medium-Liste")


class HKTAB5(FinTS3Segment):
    """TAN-Generator/Liste anzeigen Bestand, version 5

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    tan_media_type = CodeField(enum=TANMediaType2, _d="TAN-Medium-Art")
    tan_media_class = CodeField(enum=TANMediaClass4, _d="TAN-Medium-Klasse")


class HITAB5(FinTS3Segment):
    """TAN-Generator/Liste anzeigen Bestand Rückmeldung, version 5

    Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Sicherheitsverfahren PIN/TAN"""

    tan_usage_option = CodeField(enum=TANUsageOption, _d="TAN_Einsatzoption")
    tan_media_list = DataElementGroupField(type=TANMedia5, max_count=99, required=False, _d="TAN-Medium-Liste")


class HITANSBase(ParameterSegment):
    pass


class HITANS1(HITANSBase):
    parameter = DataElementGroupField(type=ParameterTwostepTAN1)


class HITANS2(HITANSBase):
    parameter = DataElementGroupField(type=ParameterTwostepTAN2)


class HITANS3(HITANSBase):
    parameter = DataElementGroupField(type=ParameterTwostepTAN3)


class HITANS4(HITANSBase):
    parameter = DataElementGroupField(type=ParameterTwostepTAN4)


class HITANS5(HITANSBase):
    parameter = DataElementGroupField(type=ParameterTwostepTAN5)


class HITANS6(HITANSBase):

Answer:     parameter = DataElementGroupField(type=ParameterTwostepTAN6)