//Ab Version 4.20.25.01
'use strict';

ko.extenders.uppercase = function(target, option) {    
    target.subscribe(function(newValue) {	
       target(newValue.charAt(0).toUpperCase() + newValue.slice(1));        
    });
    return target;
};


function TeilnehmerPflicht(pName) {
  var self = this;
  self.name = ko.observable(pName);
  self.vorname = ko.observable();
  self.email = ko.observable();
  self.tel = ko.observable();
  self.tel2 = ko.observable();
  self.istkind = ko.observable(false);
  self.gebdat = ko.observable();
  self.gebjahr = ko.observable();
  self.geschlecht = ko.observable();
  self.erm_grund = ko.observable();
  self.nurplz = ko.observable();
  self.nurort = ko.observable();
  self.ort = ko.observable();
  self.nurstrasse = ko.observable();
  self.nurhausnr = ko.observable();
  self.strasse = ko.observable();
  self.zahlmethode = ko.observable();
  self.zahlart = ko.observable();
  self.arykennzeichenJS = ko.observableArray();
  self.aryattachmentsJS = ko.observableArray();
  self.uploadAttachments = ko.observableArray();
  self.spendenbetrag = ko.observable();
  self.bemerkung = ko.observable();
  self.gebdatNichtPflicht = ko.observable(false);
  self.newsl_erlaubt = ko.observable();
  self.newsl_interessensgebiete = ko.observableArray();
  self.defaults_gesetzt = ko.observableArray();  
  self.istanonym = ko.observable(false);
  self.sozposition = ko.observable();
  self.sozarbeitgeber = ko.observable();
  self.istDienstlich = ko.observable(true);//Termin 72482
  //Patch für VHS Braunschweig vom 12.07.2019 zu H 462657
  self.iban = ko.observable();
  self.kommprio = ko.observable();
  self.nation = ko.observable();

  self.datei1 = ko.observable();
  self.datei1name = ko.observable();
  self.datei2 = ko.observable();
  self.datei2name = ko.observable();
  self.datei3 = ko.observable();
  self.datei3name = ko.observable();
  self.datei4 = ko.observable();
  self.datei4name = ko.observable();
  self.datei5 = ko.observable();
  self.datei5name = ko.observable();
  
  self.uploadduplikat = ko.observable(false);
  self.uploademptyfile = ko.observable(false);
  
  self.dateiPruefen = function(element) {
    //var elements = jQuery('input[class*="tedit_datei"]'); //Würde leider zu viel selektieren.
    var elements = jQuery('.tedit_datei1class, .tedit_datei2class, .tedit_datei3class, .tedit_datei4class, .tedit_datei5class').not(element);
    if( elements.length <= 0 ) {
        return;
    }
    
    if(element.files[0] !== undefined && element.files[0].size !== undefined && element.files[0].size > 0) {
      self.uploademptyfile(false);
    }
    else {
	  if( element.files[0] !== undefined && element.files[0].name !== undefined ) {
		  self.uploademptyfile(element.files[0].name);
	  }
	  else {
		self.uploademptyfile(true);
	  }
    }
    var aktDateiname = element.value.replace(/.*[\/\\]/, '');
    var dateinamen = [];
    for( var i=0; i<elements.length; i++ ) {
        dateinamen.push(elements[i].value.replace(/.*[\/\\]/, ''));
    }
    
    if( (dateinamen.length > 0 && aktDateiname != '' && dateinamen.indexOf(aktDateiname) > -1)
     || (self.aryattachmentsJS().length > 0 && self.aryattachmentsJS().indexOf(aktDateiname) > -1 ) ) {
        clearFileInput(element);
        self.uploadduplikat(true);
        //alert("Das Hochladen mehrerer Dateien gleichen Namens ist nicht erlaubt."); //Könnte man auch so ausgeben.
    }
    else {
        self.uploadduplikat(false);
    }
  };
}

//https://stackoverflow.com/questions/1703228/how-can-i-clear-an-html-file-input-with-javascript/
function clearFileInput(ctrl) {
  try {
    ctrl.value = null;
  } catch(ex) { }
  if (ctrl.value) {
    ctrl.parentNode.replaceChild(ctrl.cloneNode(true), ctrl);
  }
}

//datestr = Geburtsdatum des Teilnehmers als Observable, atdate = '' wenn aktuelles Datum gewünscht oder Kursbeginndatum (als String) wenn Alter zu Kursbeginn ermittelt werden soll
function calculateDatesForAge(gebdat, atdate) {
  if (typeof (gebdat) == 'undefined' || gebdat == undefined) {
    return 0;
  }

  if (typeof (gebdat) == 'function') {
    gebdat = gebdat(); //weil es ein Observable ist
  }

  //Tag, Monat und Jahr aus dem Geburtsdatum des Teilnehmers extrahieren
  var dateary = gebdat.split(".");
  var gebdatYear = parseInt(dateary[2]);
  var gebdatMonth = parseInt(dateary[1]);
  var gebdatDay = parseInt(dateary[0]);

  //übergebenes Geburtsdatum fehlerhaft
  if (gebdatYear == '' || gebdatMonth == '' || gebdatDay == '') {
    return 0;
  }

  var toYear = 1;
  var toMonth = 1;
  var toDay = 1;
  var futureDate = undefined;
  //Das Datum, an dem das Alter des Teilnehmers gefragt ist
  if (typeof (atdate) != 'undefined') { //als Datumsobjekt
    var splittedDate = atdate.split(".");
    toDay = splittedDate[0];
    toMonth = splittedDate[1] - 1;
    toYear = splittedDate[2];
    futureDate = new Date(toYear, toMonth, toDay, '0', '0', '00');
  }

  if (futureDate != undefined && typeof (futureDate) != 'undefined' && futureDate instanceof Date) { //Tag, Monat und Jahr des Datums, an dem das Alter des Teilnehmers gefragt ist
    toYear = futureDate.getFullYear();
    toMonth = futureDate.getMonth() + 1;
    toDay = futureDate.getDate();
  } else { //Das Alter des Teilnehmers am heutigen Tag ist gefragt
    var currentDate = new Date();
    toYear = currentDate.getFullYear();
    toMonth = currentDate.getMonth() + 1;
    toDay = currentDate.getDate();
  }
  return {'toYear': toYear, 'toMonth': toMonth, 'toDay': toDay,
          'gebdatYear': gebdatYear, 'gebdatMonth': gebdatMonth, 'gebdatDay': gebdatDay};
}

function calculateAgeInYears(gebdat, atdate) {
  var dates = calculateDatesForAge(gebdat, atdate);
  //Alter berechnen
  var age = dates.toYear - dates.gebdatYear;
  if (dates.toMonth > dates.gebdatMonth) {
    return age;
  } else {
    if (dates.toDay >= dates.gebdatDay && dates.toMonth == dates.gebdatMonth) { //Wenn ich im gleichen Monat geboren bin, dann bin ich schon alt genug, wenn der Kurs später als mein Tag startet
      return age;
    } else { //Wenn ich in einem späteren Monat geboren bin
      age--;
      return age;
    }
  }
}

function calculateAgeInMonths(gebdat, atdate) {
  var dates = calculateDatesForAge(gebdat, atdate);
  //Alter berechnen
  var age = (dates.toYear - dates.gebdatYear)*12;
  if (dates.toMonth > dates.gebdatMonth) {
    age = age+(dates.toMonth-dates.gebdatMonth);
  } else {
    age = age-(dates.gebdatMonth-dates.toMonth);
    if (dates.toDay < dates.gebdatDay) {
      age--;
    }
  }
  return age;
}

//0, wenn Alter des Teilnehmers im gewünschten Bereich liegt oder der Kurs kein spezielles Alter verlangt.
//-1, wenn Teilnehmer zu jung ist
//1, wenn Teilnehmer zu alt ist
//null, falls kein Geburtsdatum oder kein Kursdatum angegeben ist
//Beachtet dabei, ob das Alter in Jahren oder in Monaten benutzt werden muss.
function checkAge(gebdate, atdate, kurs, allowPastAtDate = false) {
    if( gebdate == "undefined" || gebdate == '' || atdate == '' ) {
        return null;
    }

    if( (atdate == '') || (kurs.altervon == 0 && kurs.alterbis == 0 && kurs.monataltvon == 0 && kurs.monataltbis == 0) ) {
        return 0;
    }

    if(allowPastAtDate) {
      let today = new Date();
      if(KuferWEB.Utils.parseDateFormatDDMMYYYY(atdate) < today) {
        atdate = KuferWEB.Utils.formatDateDDMMYYYY(today);
      }
    }

    if( kurs.altervon == 0 && kurs.alterbis == 0 ) {
        var age = calculateAgeInMonths(gebdate, atdate);
        if( age < kurs.monataltvon ) return -1;
        else if( age > kurs.monataltbis ) return 1;
        else return 0;
    }
    else {
        var age = calculateAgeInYears(gebdate, atdate);
        if( age < kurs.altervon ) return -1;
        else if( age > kurs.alterbis ) return 1;
        else return 0;
    }
}

function Kurs(pKnr, pBeginn, pGebuehr, pSettings) {
  var self = this;
  self.knr = pKnr;
  self.gebuehrGeparsed = pGebuehr;
  self.beginn_dat = pBeginn;

  self.weitereTeilnehmer = ko.observableArray();
  if (typeof (pSettings) === 'undefined' || pSettings.zahlerInitialInKursen) {
    self.hauptTnAuch = ko.observable(1);
  } else {
    self.hauptTnAuch = ko.observable(0);
  }
  self.beleghistorie1 = ko.observable(); //Für FBS Bonn standardmäßig auf 0,00 setzen!
  self.beleghistorie2 = ko.observable();
  self.beleghistorie3 = ko.observable();
  self.beleghistorie4 = ko.observable();
  self.beleghistorie5 = ko.observable();
  self.beleghistorie6 = ko.observable();
  self.beleghistorie7 = ko.observable();
  self.beleghistorie8 = ko.observable();
  self.beleghistorie9 = ko.observable();
  self.beleghistorie10 = ko.observable();
  self.beleghistorie11 = ko.observable();
  self.beleghistorie12 = ko.observable();
  self.beleghistorie13 = ko.observable();
  self.beleghistorie14 = ko.observable();
  self.beleghistorie15 = ko.observable();
  self.beleghistorie16 = ko.observable();
  self.zahlplan = ko.observable(); //Vom Teilnehmer konkret ausgewählter Zahlplan
  self.zahlplaene = ko.observableArray(); //Alle Zahlpläne, die beim Kurs in KuferSQL hinterlegt wurden
  self.eintritt = ko.observable();
  self.austritt = ko.observable();
  self.info2doz = ko.observable();
  //s.a. kursObservableVars
  self.nuronline = ko.observable();
  self.defaults_gesetzt = ko.observableArray();

  self.setzeKursFeld = function (key, value) {
    self[key](value);
    return true;
  };

  self.setOnlineZahlplan = function (checked) {
    if(checked) {
      ko.utils.arrayForEach(self.zahlplaene(), function (zp) {
        if (zp.zusatz === 'O') {
          self.zahlplan(zp.wert);
        }
      });
    } else {
      self.zahlplan(-1);
    }
  };

  self.setzeKursFeldDefault = function (key, value) {
    if( self.defaults_gesetzt().indexOf(key) == -1 ) {
      self.setzeKursFeld(key, value);
      self.defaults_gesetzt().push(key);
    }
    return true;
  };

  self.addWeiteren = function (pTeilnehmer) {
    self.weitereTeilnehmer.push(pTeilnehmer);
  };
  self.removeWeiteren = function (pTn) {
    var curr = jQuery('div.eingabeWeiterer');
    curr.detach();
    jQuery('#kw-hafen_eingabeWeiterer').append(curr);

    //letzter TN wird entfernt => HauptTn muss teilnehmen, self.isNurAnonyme() wuerde zwar auch anschlagen, aber
    //da ist es zu spaet, weil die AJAX-Neuberechnung der Gebuehr schon bei self.weitereTeilnehmer.remove(pTn); getriggert wird
    if (self.weitereTeilnehmer().length === 1) {
      self.hauptTnAuch(true);
    }

    self.weitereTeilnehmer.remove(pTn);
    //Für Köln Elternschule:
    // Beim Löschen des letzten weiteren Teilnehmers soll auch der Haken für die Kinderbetreuung entfernt werden.
    if (pSettings.einrichtung == 'koelnelternschule') {
      if (self.weitereTeilnehmer().length < 1) {
        self.beleghistorie2(false);
      } // /Elternschule
    }
    //Wenn der Hauptteilnehmer rausgestrichen wurde, aber jetzt der letzte nicht anonyme Teilnehmer gelöscht wird,
    //so muss der Hauptteilnehmer wieder teilnehmen, da wir von irgendjemandem Daten brauchen, weil KuferSQL sonst
    //nicht mit der Anmeldung umgehen kann.
    if( self.isNurAnonyme() ) {
      self.hauptTnAuch(true);
    }
  };

  self.addWeiterenAnonym = function() {
    var weiterer;
      weiterer = new TeilnehmerPflicht();
      weiterer.istanonym(true);
      self.addWeiteren(weiterer);
  };

  //Sind alle weiteren Teilnehmer dieses Kurses anonyme Teilnehmer?
  self.isNurAnonyme = function() {
    for (var i = 0; i < self.weitereTeilnehmer().length; i++) {
      if( !self.weitereTeilnehmer()[i].istanonym() ) {
        return false;
      }
    }
    return true;
  };


  self.hasKennzeichen = function (zuPruefendesKennzeichen) {
    if (self.kennzeichen == undefined) {
      return false;
    }
    for (var j = 0; j < self.kennzeichen.length; j++) {
      if (self.kennzeichen[j] == zuPruefendesKennzeichen) {
        return true;
      }
    }
    return false;
  };
  
  self.getZahlplanGebuehr = function(zahlplanid) {
	  zahlplanid = zahlplanid();
	  if( zahlplanid == -1 ) {
		  return self.gebuehr;
	  }
	  for (var j = 0; j < self.zahlplaene().length; j++) {
      if( self.zahlplaene()[j].wert == zahlplanid ) {
        return parseInt(self.zahlplaene()[j].gebuehrengesamt, 10).toFixed(2).replace('.',',');
      }
	  }
    return self.gebuehr;
  };

  self.isNurFuerKinder = function () { //Beim Kurs in KuferSQL wurde nur genau Eltern-Kind-Anmeldung angehakt.
    var nurKinderFlag = (self.webflags & 63);
    return (nurKinderFlag == 4); //Ist es nur ein Kinderkurs? Ja, wenn es 4 ist.
  };

  //Für FBS Bonn
  //Gibt zurück, wie viel die Schwellengebühr multipliziert mit der Anzahl der Teilnehmer beträgt.
  //Der Funktion muss die Nummer der Schwellengebühr übergeben werden, d.h. ob es sich um self.geb_schw1 (1 übergeben) oder self.geb_schw2 (2 übergeben) handelt.
  self.schwelleAnzahlTeilnehmerProdukt = function (schwellengebNr) {
    var schwellengeb = (schwellengebNr == 1) ? self.geb_schw1 : (schwellengebNr == 2) ? self.geb_schw2 : 0;
    schwellengeb = schwellengeb.replace(',', '.');
    var anzHauptTn = (self.hauptTnAuch() > 0) ? 1 : 0;
    var weitereTeilnehmerLength = self.weitereTeilnehmer().length;
    if (weitereTeilnehmerLength > 0 && self.weitereTeilnehmer()[0].istkind()) {
      weitereTeilnehmerLength = weitereTeilnehmerLength - 1; //Das erste Kind soll kostenlos sein. Weitere Kinder kosten die volle Gebuehr.
    }
    var rueckgabe = schwellengeb * (weitereTeilnehmerLength + anzHauptTn);
    return rueckgabe;
  };

  self.showSchwelleAnzahlTeilnehmerProdukt = function (schwellengebNr) {
    var rueckgabe = self.schwelleAnzahlTeilnehmerProdukt(schwellengebNr);
    rueckgabe = rueckgabe.toFixed(2).toString();
    rueckgabe = rueckgabe.replace('.', ',');
    return rueckgabe;
  };
};


function KwAnmeldeViewModel() {//So ähnlich wie ein Konstruktor einer Klasse. Hier wird alles initialisiert.
  var self = this;
  self.hauptTn = ko.observable(new TeilnehmerPflicht());  
  self.kurse = ko.observableArray();
  self.einstellungen = ko.observable("");
  self.gebuehrenSummeAjax = ko.observable("0,00");
  self.gebuehrenSummeAjaxImmerErmaessigt = ko.observable("0,00");
  self.gebuehrenSummeAjaxNichtErmaessigt = ko.observable("0,00");
  self.gebuehrenSummeAjaxNetto = ko.observable("0,00");
  self.gebuehrenSummeAjaxNettoImmerErmaessigt = ko.observable("0,00");
  self.gebuehrenSummeAjaxNettoNichtErmaessigt = ko.observable("0,00");
  self.gebuehrenSummeAjaxRabatt = ko.observable("0,00");
  self.gebuehrenSummeAjaxNettoRabatt = ko.observable("0,00");
  self.refreshing = ko.observable(false);

  self.sichtSettings = {weiterePflicht: "name, vorname, email", mitarbeiterPflicht: "name, vorname, email", kinderPflicht: "vorname", zahlerInitialInKursen: 1, einrichtung: "", useGebSumAjaxBrutto: 1};
  if (typeof (kw_anmSettings) !== 'undefined') {
    self.sichtSettings = jQuery.extend(self.sichtSettings, kw_anmSettings);
  }
  self.weiterePflichtfelder = self.sichtSettings.weiterePflicht.replace(/\s/g, '').split(",");
  self.mitarbeiterPflichtfelder = self.sichtSettings.mitarbeiterPflicht.replace(/\s/g, '').split(",");
  self.kinderPflichtfelderUnveraendert = self.sichtSettings.kinderPflicht.replace(/\s/g, '').split(",");
  self.kinderPflichtfelder = self.kinderPflichtfelderUnveraendert.slice();
  self.capitalizeHauptTnfelder = self.sichtSettings.capitalizeHaupt?self.sichtSettings.capitalizeHaupt.replace(/\s/g, '').split(","):[];
  self.capitalizeWeitereTnfelder = self.sichtSettings.capitalizeWeitere?self.sichtSettings.capitalizeWeitere.replace(/\s/g, '').split(","):[false];
  
  //DemoDaten
  /*self.kurse.push(new Kurs("161-3207", "02.10.2016", 10.00));
   self.kurse.push(new Kurs("152-3104", "15.07.2016", 25.00));
   var tn = new TeilnehmerPflicht();
   tn.name('aaname');
   tn.vorname('aavorname');
   self.kurse()[0].addWeiteren(tn);
   tn = new TeilnehmerPflicht();
   tn.name('bbname');
   tn.vorname('bbvorname');
   self.kurse()[0].addWeiteren(tn);
   tn = new TeilnehmerPflicht();
   tn.name('ccname');
   tn.vorname('ccvorname');
   self.kurse()[1].addWeiteren(tn);
   */

  self.setzeHauptTnFeld = function (key, value) {
    self.hauptTn()[key](value);
    return true;
  };

  self.removeHauptTnAttachment = function(attachment) {
      self.hauptTn().aryattachmentsJS.remove(attachment); //Mit destroy() funktionierte es leider nicht, trotz Parameter includeDestroyed: false zeigte es zerstörte Items weiter an.
  }

  self.setzeHauptTnFeldDefault = function (key, value) {
    if( self.hauptTn().defaults_gesetzt.indexOf(key) == -1 ) {
      self.setzeHauptTnFeld(key, value);
      self.hauptTn().defaults_gesetzt.push(key);
    }
    return true;
  };

  self.removeHauptTn = function (pKurs) {
    pKurs.hauptTnAuch(0);
    self.refreshGebuehrenSummenAjax();
  };

  self.setHauptTn = function (pKurs) {
    pKurs.hauptTnAuch(1);
    self.refreshGebuehrenSummenAjax();
  };

  self.firmaBehandlung = function () {
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      kurs.hauptTnAuch(0);
    }
    return true;
  };

  self.menschBehandlung = function () {
    var einstellungen = self.einstellungen;
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      kurs.hauptTnAuch(1);
      //Wenn Nichtfirmenanmeldungen keine weiteren Teilnehmer zulassen, so werden diese entfernt.
      if( !((kurs.webflags & 4) == 4) && !((kurs.webflags & 16) == 16) && !((kurs.webflags & 32) == 32) ) {
	    if (!einstellungen().nurnormaleanmeldearten && einstellungen().nurerlaubteanmeldearten) {
			kurs.weitereTeilnehmer([]);
		}
      }
    }
    return true;
  };

  self.disableAddWeiteren = function (kurs) { //Button weiterer Teilnehmer ausgrauen? true = Ja, ausgrauen! 
    var einstellungen = self.einstellungen;
    if (einstellungen().paypalisexpressco) {
      return true;
    }
    if (einstellungen().iskufersql5 && self.istKinderkurs(kurs)) {
      return false;
    }
    if (einstellungen().nurnormaleanmeldearten) {
      return true;
    }
    if (!einstellungen().nurerlaubteanmeldearten) {
      return false;
    }
    /*if( kurs.webflags == 4 && kurs.weitereTeilnehmer().length > 0) { //speziell für Friedrichshafen
     return true;
     }*/

    //Paaranmeldungen dürfen nicht mehr als 2 Teilnehmer haben. Das wird erst einmal für Kurse gemacht, die NUR die Paaranmeldung freigegeben haben und sonst nichts - z.B. Tanzkurse.
    //Streicht man den Zahler aus dem Kurs, kann man zwei weitere Teilnehmer hinzufügen, bevor das Hinzufügen verboten wird.
    //beim ersten weiteren TN zu untersuchen.
    //Außerdem sollte es, wenn man den Zahler aus dem Kurs streicht, später möglich sein, dass man dann zwei weitere Teilnehmer hinzufügt.
    if ((kurs.webflags == 32) && (typeof (kurs) != 'undefined' && typeof (kurs.weitereTeilnehmer()) != 'undefined' && kurs.weitereTeilnehmer().length > 0)) {
      return true;
    }

    //Wenn Nichtfirmenanmeldungen keine weiteren Teilnehmer zulassen, so wird der Button für das Hinzufügen weiterer Teilnehmer deaktiviert.
    if( (self.hauptTn().geschlecht() != "F") && !((kurs.webflags & 4) == 4) && !((kurs.webflags & 16) == 16) && !((kurs.webflags & 32) == 32) ) {
	  var einstellungen = self.einstellungen;
	  if (!einstellungen().nurnormaleanmeldearten && einstellungen().nurerlaubteanmeldearten) {
		return true;
	  }
    }

    var vergleichAlleFlags = (kurs.webflags & 63);
    return (vergleichAlleFlags <= 2); //Für Kurse, bei denen nur normale Anmeldung (webflag 2 oder 0) oder keine Anmeldung (webflag 1) erlaubt sind, muss der weitere-Teilnehmer-Button deaktiviert werden.
  };

  self.canAddWeiterenWk = function() {
    let result = false;
    ko.utils.arrayForEach(self.kurse(), function (kurs) {
      if (!self.disableAddWeiteren(kurs)) {
        result = true;//Kurs gefunden, bei dem es geht
      }
    });
    return result;
  }

  self.isKursMitKennzeichenXimWK = function (zuPruefendesKennzeichen) {
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if (kurs.hasKennzeichen(zuPruefendesKennzeichen)) {
        return true;
      }
    }
    return false;
  };


  self.isKursOhneKennzeichenimWK = function (zuPruefendeKennzeichen) {
    var keinsgefunden = false;
    if( self.kurse().length > 0 ) {
      ko.utils.arrayForEach(self.kurse(), function (kurs) {

        //Hat der Kurs eines der Kennzeichen, das als Array an diese Funktion übergeben wurde?
        var kennzGefunden = false;
        if (typeof (zuPruefendeKennzeichen) != 'undefined' && zuPruefendeKennzeichen != '') {
          for (var i = 0; i < zuPruefendeKennzeichen.length; i++) {
            if (kurs.hasKennzeichen(zuPruefendeKennzeichen[i])) {
              kennzGefunden = true;
            }
          }
          if( !kennzGefunden ) {
            keinsgefunden = true;
          }
        }
      });
      return keinsgefunden;
    }
    return false;
  };

  self.isKursMitAnmeldeartEKimWK = function () {
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if (kurs.webflags == 4) {
        return true;
      }
    }
    return false;
  };

  self.isKursOhneAnmeldeartEKimWK = function () {
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if (kurs.webflags != 4) {
        return true;
      }
    }
    return false;
  };

  self.isKursOhneAnmeldeartNormalimWK = function () {
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if (kurs.webflags != 2) {
        return true;
      }
    }
    return false;
  };

  self.isHauptTnFirma = function ()
  {
    if (self.hauptTn().geschlecht == undefined) {
      return false;
    }
    if (self.hauptTn().geschlecht() == "F") {
      self.hauptTn().vorname("");
      self.hauptTn().gebdat("");
	  self.hauptTn().gebjahr("");
      return true;
    }
    return false;
  };

  self.DatenFromHauptTnToWeiterer = function () {
    self.geradeEditierterWeitererTn().name(self.hauptTn().name());
    self.geradeEditierterWeitererTn().nurstrasse(self.hauptTn().nurstrasse());
    self.geradeEditierterWeitererTn().nurhausnr(self.hauptTn().nurhausnr());
    self.geradeEditierterWeitererTn().nurort(self.hauptTn().nurort());
    self.geradeEditierterWeitererTn().nurplz(self.hauptTn().nurplz());
    return false;
  };

  self.CheckifHauptLikeWeiterer = function () {

    if ((self.hauptTn().name() == self.geradeEditierterWeitererTn().name())
            && (self.hauptTn().vorname() == self.geradeEditierterWeitererTn().vorname())
            && ((self.hauptTn().gebdat() == self.geradeEditierterWeitererTn().gebdat()) || (self.hauptTn().gebjahr() == self.geradeEditierterWeitererTn().gebjahr()))) {
      return true;
    }
    return false;
  };
  /*self.isHauptTnAusgefuelltOeffneWeiteren = function()
   {
   return true;
   if( self.hauptTn().name != undefined && self.hauptTn().name() != '') {
   if( self.hauptTn().vorname != undefined && self.hauptTn().vorname() != '') {
   if( self.kurse != undefined && self.kurse().length > 0 && self.kurse()[0].weitereTeilnehmer != undefined && self.kurse()[0].weitereTeilnehmer().length < 1 ) {
   self.addWeiteren(self.kurse()[0]);
   return true;
   }
   }
   }
   return false;
   }*/

  self.nurKinderKurs = function () { //Beim Kurs in KuferSQL wurde nur genau Eltern-Kind-Anmeldung angehakt.
    var einstellungen = self.einstellungen;
    if (einstellungen().nurnormaleanmeldearten || !einstellungen().nurerlaubteanmeldearten) { //Die Einstellungen im Webadmin übersteuern die Hinterlegung in KuferSQL.
      return false;
    }
    var kurs = self.geradeEditierterKurs();
    var nurKinderFlag = (kurs.webflags & 63);

    return (nurKinderFlag == 4); //Ist es nur ein Kinderkurs? Ja, wenn es 4 ist.
  };

  self.auchKinderKurs = function () { //Z.B. sind in KuferSQL Mehrfach- und Eltern-Kind-Anmeldung ausgewählt. Dann darf man zu dem Kurs AUCH Kinder anmelden, wenn man möchte.
    if (self.geradeEditierterKurs() == false) {
      return false;
    }
    var einstellungen = self.einstellungen;
    if (einstellungen().nurnormaleanmeldearten) {
      return false;
    }

    if (!einstellungen().nurerlaubteanmeldearten) {
      return true;
    }
    var kurs = self.geradeEditierterKurs();
    if (((kurs.webflags & 4) > 0)) {
      return true;
    }

    return false;
  };


//Wenn beim ersten weiteren TN die Kindercheckbox angehakt ist, dann soll das auch für den zweiten und alle weiteren Teilnehmer gelten. Dort ist dann die Checkbox ausgegraut. 
//Man kann immer nur beim ersten Teilnehmer entscheiden, ob es (und damit alle weiteren Teilnehmer des Kurses) ein Kind ist oder nicht.
  self.checkKind = function (checked) {
    var einstellungen = self.einstellungen;
    
    if (einstellungen().iskufersql5 && self.istKinderkurs(self.geradeEditierterKurs())) {
      self.geradeEditierterWeitererTn().istkind(true);
      return true;
    }
      
    //Wenn nur normale Anmeldungen zulässig sind, sollte er hier gar nicht vorbei kommen, zur Sicherheit wird die Kinder-Checkbox trotzdem nicht angehakt
    if (einstellungen().nurnormaleanmeldearten) {
      return false;
    }

    if (self.geradeEditierterKurs() == false) {
      return false;
    }

    //Wenn sowieso nur Eltern-Kind-Anmeldung (Webflag 4) (und normale Anmeldungen (Webflag 6)) zulässig sind, dann auch den ersten weiteren TN direkt anhaken
    if ((self.geradeEditierterKurs().webflags == 4 || self.geradeEditierterKurs().webflags == 6) && (einstellungen().nurerlaubteanmeldearten)) {
      self.geradeEditierterWeitererTn().istkind(true);
      return true;
    }
    
    // Erster weiterer TN wird bearbeitet, es gibt noch keine weiteren
    var ersterWeiterer = self.geradeEditierterKurs().weitereTeilnehmer()[0];
    if (!ersterWeiterer) {
      self.geradeEditierterWeitererTn().istkind(checked);
      return checked;
    }

    // Weiterer-TN-Formular wird gerade geöffnet: Gespeicherten Wert zurückgeben und nicht ändern.
    if (!self.wirdGeradeEinWeitererEditiert()) {
      return self.geradeEditierterWeitererTn().istkind();
    }

    // Erster weiterer TN wird bearbeitet
    if (self.geradeEditierterWeitererTn() == ersterWeiterer) {
      for (var i = 0; i < self.geradeEditierterKurs().weitereTeilnehmer().length; i++) {
        self.geradeEditierterKurs().weitereTeilnehmer()[i].istkind(checked);
      }
      if (checked) { //Wenn Haken gesetzt wird, dann muss der Hauptteilnehmer am Kurs teilnehmen
        self.geradeEditierterKurs().hauptTnAuch(1);
      }
      return checked;
    }

    // 2. oder höherer TN wird bearbeitet
    var rueckgabe = ersterWeiterer.istkind();
    self.geradeEditierterWeitererTn().istkind(rueckgabe);
    return rueckgabe;
  };

  //In KuferSQL 5.0 auf Seite 1 Typ Kinderkurs ausgewählt?
  self.istKinderkurs = function (kurs) {
    if (self.einstellungen().iskufersql5 && kurs.typ == 'K') {
      return true;
    }
    return false;
  };

  self.istErsterKind = function (kurs) {
    if (typeof (kurs.weitereTeilnehmer) != 'undefined' && kurs.weitereTeilnehmer().length > 0 && kurs.weitereTeilnehmer()[0].istkind()) {
      return true;
    }
    return false;
  };

  self.disableKind = function () {
    if (self.geradeEditierterKurs() == false) {
      return false;
    }

    var weitereTn = self.geradeEditierterKurs().weitereTeilnehmer();
    var einstellungen = self.einstellungen;
    if(einstellungen().iskufersql5 && self.istKinderkurs(self.geradeEditierterKurs())) {
        return true;
    }
    if (einstellungen().nurnormaleanmeldearten) {
      return true;
    }
    
    if (!einstellungen().allowKinderAnmeldung) {
      return true;
    }
    //Wenn nur Eltern-Kind-Anmeldung oder nur Eltern-Kind+Normal, dann ist der weitere TN immer ein Kind
    if ((self.geradeEditierterKurs().webflags == 4 || self.geradeEditierterKurs().webflags == 6) && (einstellungen().nurerlaubteanmeldearten)) {
      return true; //Man darf also nicht entscheiden, ob es ein Kind ist, sondern es muss definitiv ein Kind sein.
    }
    if (weitereTn.length == 0) {
      return false;
    }
    return (self.geradeEditierterWeitererTn() != weitereTn[0]);
  };

  self.kinderErlaubt = function () {
    var einstellungen = self.einstellungen;
    if(einstellungen().iskufersql5 && self.istKinderkurs(self.geradeEditierterKurs())) {
        return true;
    }
    if (einstellungen().nurnormaleanmeldearten) {
      return false;
    }
    if (!einstellungen().allowKinderAnmeldung) {
      return false;
    }
    if (!einstellungen().nurerlaubteanmeldearten) {
      return true;
    }
    return ((self.geradeEditierterKurs().webflags & 4) > 0);
  };

  //speziell für Friedrichshafen VHS
  self.veranstaltungsArtDreiImWK = function (kurse) {
    //Ja, den 0. Kurs zu prüfen reicht, weil bei Friedrichshafen ein Mischen der Veranstaltungsart 3 mit anderen nicht möglich ist.
    if (typeof (kurse) != 'undefined' && typeof (kurse) == 'function' && kurse().length > 0 && (kurse()[0].kart_key == '03' || kurse()[0].kart_key == '3')) {
      return true;
    } else {
      return false;
    }
  }

  //eingesetzt bei Freiburg VHS
  self.nurDeutscheIban = function () {
    if (typeof (self.hauptTn().iban) == "function") {
      var val = self.hauptTn().iban();
      return val != "" && val.match(/^DE/);
    }
    return true;
  };

  self.checkFormatEintritt = function() {
       if( typeof(self.hauptTn().eintritt) != "function"
              || self.hauptTn().eintritt().search(/^\d\d\.\d\d\.\d\d\d\d$/i) != 0) {
          return false;
       }
       return true;
  }
  
  self.checkFormatAustritt = function() {
       if( typeof(self.hauptTn().austritt) != "function"
              || self.hauptTn().austritt().search(/^\d\d\.\d\d\.\d\d\d\d$/i) != 0) {
          return false;
       }
       return true;
  }

  //Achtung: Diese Funktion geht davon aus, dass nur genau ein Kurs im WK liegt, speziell für Heidelberg DAI
  self.checkEintrittAustritt = function() {
      if( !self.checkFormatEintritt()
              || !self.checkFormatAustritt() ) {
        return false;
      }
      if( typeof(self.kurse()[0]) == "undefined" || self.kurse().length != 1 ) {
          return false;
      }
      if( parseDateGerman(self.hauptTn().eintritt()) < parseDateGerman(self.kurse()[0].beginn_dat)
              || parseDateGerman(self.hauptTn().eintritt()) > parseDateGerman(self.kurse()[0].ende_dat) ) {
          return false;
      }
      if( parseDateGerman(self.hauptTn().austritt()) < parseDateGerman(self.kurse()[0].beginn_dat)
              || parseDateGerman(self.hauptTn().austritt()) > parseDateGerman(self.kurse()[0].ende_dat) ) {
          return false;
      }
      return true;
  }

  self.checkKurseAbsendbar = function() { //Müssen weitere Teilnehmer angegeben werden? Sind diese bei allen Kursen angegeben, bei denen dies nötig ist?
    if (self.isHauptTnFirma()) {
      //Zur Sicherheit noch mal triggern, damit folgender Fall nicht auftreten kann:
      //Ein Kurs mit weiterem Teilnehmer bereits im Warenkorb und Geschlecht Firma wurde in Anminfo gespeichert (durch Klick auf "Weiter")
      //Weiterer Kurs wird in Warenkorb gelegt
      //In der Anmeldung ist der HauptTN mit Geschlecht Firma nicht aus dem Kurs gestrichen und der Weiter-Button nicht ausgegraut.
      self.firmaBehandlung();
    }
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if( self.checkZuWenigeTeilnehmer(kurs) || self.checkZuVieleTeilnehmer(kurs) ) {
        return false;
      }
    }
    return self.isEPayHauptTnAuch(); //Das E-Payment ist nur okay, wenn der Zahler an allen Kursen teilnimmt.
  };
  
  self.checkZuWenigeTeilnehmer = function(kurs) {
    if ((typeof (self.hauptTn().geschlecht) == "function")) {
        //Wenn der Hauptteilnehmer nicht teilnimmt
        if ((!kurs.hauptTnAuch() || kurs.hauptTnAuch() == 0) && (kurs.weitereTeilnehmer().length < 1)) {
            return true;
        }

        var einstellungen = self.einstellungen;
        if( self.istKinderkurs(kurs) && (kurs.weitereTeilnehmer().length < 1) ) {
            return true;
        }
        
        //Alles außer Paaranmeldung
        if (einstellungen().nurerlaubteanmeldearten) {
            if (((kurs.webflags & 2) !== 2) && (kurs.webflags != 0) && (kurs.weitereTeilnehmer().length < 1)) {
              return true;
            }
        }

        //Paaranmeldung
        if( kurs.webflags == 32 ) {
            if( typeof(kurs.weitereTeilnehmer()) != 'undefined' &&
                ((kurs.hauptTnAuch() && kurs.weitereTeilnehmer().length < 1) || (!kurs.hauptTnAuch() && kurs.weitereTeilnehmer().length < 2))
            ) {
                return true;
            }
        }
    }
    return false;
  };

  self.checkZuVieleTeilnehmer = function(kurs) {
    if ((typeof (self.hauptTn().geschlecht) == "function")) {
        if( kurs.webflags == 32 ) {
            if( typeof(kurs.weitereTeilnehmer()) != 'undefined' &&
                    ((kurs.hauptTnAuch() > 0 && kurs.weitereTeilnehmer().length > 1) || (!kurs.hauptTnAuch() && kurs.weitereTeilnehmer().length > 2)) ) {
                return true;
            }
        }
    }
    return false;
  };

  self.isEPayHauptTnAuch = function () { //Kann z.B. auch in Sicht 504 benutzt werden, um eine Hinweismeldung anzuzeigen.
    if (typeof (self.hauptTn().zahlart) != "undefined" && self.hauptTn().zahlart() == 'epay') {
      if (self.hauptTn().geschlecht != "undefined" && self.hauptTn().geschlecht() == 'F') {
        return true;
      }
      for (var i = 0; i < self.kurse().length; i++) {
        var kurs = self.kurse()[i];
        if ((!kurs.hauptTnAuch() || kurs.hauptTnAuch() == 0)) {
          return false;
        }
      }
    }
    return true;
  };

  //Für Bonn FBS
  //Schaut, ob die vom Nutzer gewählte Wunschgebühr zwischen der minimal und maximal zulässigen Gebühr liegt.
  //Dient zum Deaktivieren des Weiter-Buttons.
  self.checkKurseAbsendbarBeleghistorie1ZwischenSchwellengebuehren = function () {
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if (kurs.geb_schw1 === "0,00" && kurs.geb_schw2 === "0,00") {
        kurs.beleghistorie1("0,00");
      }
      if (typeof (kurs.beleghistorie1) == 'undefined' || typeof (kurs.beleghistorie1()) == 'undefined' || kurs.beleghistorie1() == '') {
        return false;
      } else {
        var schwellenAnzahlTeilnehmerProdukt1 = kurs.schwelleAnzahlTeilnehmerProdukt(1);
        var schwellenAnzahlTeilnehmerProdukt2 = kurs.schwelleAnzahlTeilnehmerProdukt(2);

        if (kurs.beleghistorie1().replace(/,/g, '.') < schwellenAnzahlTeilnehmerProdukt1
                || kurs.beleghistorie1().replace(/,/g, '.') > schwellenAnzahlTeilnehmerProdukt2) {
          return false;
        }
      }
    }
    return true;
  }

  self.checkKurseAbsendbarAlterHauptTn = function () {
    var einstellungen = self.einstellungen;
    var alterHauptTnGueltigkeit = null;
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      alterHauptTnGueltigkeit = checkAge(self.hauptTn().gebdat(),kurs.beginn_dat, kurs);
      if (alterHauptTnGueltigkeit == null) {
        return true; //Geburtsdatum wurde noch nicht ausgefüllt. Dann kommt man sowieso nicht auf die Kontrollseite, wenn das Geburtsdatum ein Pflichtfeld ist
      }
      if (kurs.empfohlenesalterpflicht && (!(einstellungen.nurerlaubteanmeldearten && kurs.webflags == 4) || einstellungen.nurnormaleanmeldearten)) {
        if (kurs.hauptTnAuch() == 1 && alterHauptTnGueltigkeit != 0) {
          return false; //Es gibt also mindestens einen Kurs, für den der Weiter-Button ausgegraut werden muss!
        }
      }
    }
    return true; //keinen Kurs gefunden, der den Weiter-Button verbieten würde
  };

  self.submitInfo = function (element) { //Wenn man die Maus über den Weiter-Button hält, dann erscheint eine Erklärung, warum er ausgegraut ist.
    if (!self.checkKurseAbsendbar()) {
      element.title = "Es sind nicht bei allen Kursen Teilnehmer angegeben.";
    } else if (self.weitererTnWirdEditiert()) {
      element.title = "Es wird noch ein weiterer Teilnehmer bearbeitet.";
    } else {
      element.title = "Weiter im Anmeldevorgang";
    }
  };

  self.removeKurs = function (pKurs) { //Mülltonnen sind sowieso nicht mehr in der Sicht, also ist diese Funktion egal.
    if (self.kurse().length > 1) {
      self.kurse.remove(pKurs);
    } else
    {
      alert("Um den letzten Kurs zu entfernen, verlassen Sie die Anmeldung und tun Sie dies im Warenkorb.");
    }
  };

  self.geradeEditierterKursHasKennzeichen = function (pKennzeichen) {
    var kurs = self.geradeEditierterKurs();
    if (kurs.kennzeichen == undefined) {
      return false;
    }
    for (var j = 0; j < kurs.kennzeichen.length; j++) {
      if (kurs.kennzeichen[j] == pKennzeichen) {
        return true;
      }
    }
    return false;
  };

  //"Hilfsvariablen" zum Einfügen/Editieren eines weiteren Tns
  self.geradeEditierterWeitererTn = ko.observable(new TeilnehmerPflicht());
  self.wirdGeradeEinWeitererEditiert = ko.observable(false);
  self.geradeEditierterKurs = ko.observable(false);
  self.geradeWirdEinNeuerTeilnehmerEditiert = false;

  self.addWeiteren = function (pKurs) {
    var newTn = new TeilnehmerPflicht();
    if (typeof (kwOnBeforeAddWeiteren) === "function") {
      kwOnBeforeAddWeiteren(pKurs, newTn, self);
    }
    self.editWeiteren(pKurs, newTn);
    self.geradeWirdEinNeuerTeilnehmerEditiert = true;
  };

  // Für Köln Elternschule:
  // Bei Klick auf die Kinderbetreuung-Checkbox soll sich die Eingabe des weiteren Teilnehmers öffnen
  // Wird die Checkbox deaktiviert, sollen allen weiteren Teilnehmer gelöscht werden, da dann
  // keine Kinderbetreuung gewünscht ist und damit auch keine Kinder angegeben werden dürfen.
  self.addWeiterenClick = function (element, pKurs) {
    if (element.checked == true) {
      self.addWeiteren(pKurs);
    } else {
      self.abortWeiteren();
      if (pKurs.weitereTeilnehmer) {
        var laenge = pKurs.weitereTeilnehmer().length;
        for (var j = laenge - 1; j >= 0; j--) {
          var tn = pKurs.weitereTeilnehmer()[j];
          pKurs.weitereTeilnehmer.remove(tn);
        }
      }
    }
    return true;
  };
  // /Elternschule

  //einmal direkt (click: $root.editWeiteren.bind($data, $parent)//Reihenfolge STIMMT, whyever) und einmal über addWeiteren aufgerufen 
  self.editWeiteren = function (pKurs, pTeilnehmer) {
	
	//Extender an Felder anhängen, die automatisch großgeschrieben werden sollen
	for (var field in pTeilnehmer) {
		if (pTeilnehmer.hasOwnProperty(field)) {
			if (self.capitalizeWeitereTnfelder.indexOf(field) > -1){
				pTeilnehmer[field] = pTeilnehmer[field].extend({ uppercase: true });
			}
		}
    }
	
    self.geradeEditierterWeitererTn(pTeilnehmer);
    self.geradeEditierterKurs(pKurs);//muss vor self.wirdGeradeEinWeitererEditiert(true); stehen!! da in weitererTnZumAktuellenKursWirdEditiert auf den Kurs zugegriffen wird!
    self.wirdGeradeEinWeitererEditiert(true);
    //EditierDialog an der richtigen Stelle einhängen
    var curr = jQuery('div.eingabeWeiterer');
    curr.detach();
    if (pKurs.weitereTeilnehmer().indexOf(pTeilnehmer) == -1) {
      jQuery(".kw-kurs-tnadd" + self.geradeEditierterKurs().knr.replace(/[\.\s]/g, '_')).append(curr);
    } else {
      jQuery(".wtn" + self.geradeEditierterKurs().knr.replace(/[\.\s]/g, '_') + '_' + pKurs.weitereTeilnehmer().indexOf(pTeilnehmer)).append(curr);
    }
  };

  self.weitererTnWirdEditiert = function () {
    return self.wirdGeradeEinWeitererEditiert();
  };
  self.weitererTnZumAktuellenKursWirdEditiert = function (pKurs) {
    return self.wirdGeradeEinWeitererEditiert() && self.geradeEditierterKurs() !== false && self.geradeEditierterKurs().knr.replace(/[\.\s]/g, '_') === pKurs.knr.replace(/[\.\s]/g, '_');
  };

  self.isWeitererUngueltig = function () {
    var pflichtfelder = '';
    self.kinderPflichtfelder = self.kinderPflichtfelderUnveraendert.slice();
    //Kinder als weitere Teilnehmer können andere Pflichtfelder als Erwachsene haben
    if (self.geradeEditierterWeitererTn().istkind()) { //weiterer Teilnehmer ist ein Kind
      pflichtfelder = self.kinderPflichtfelder;
      if (self.geradeEditierterWeitererTn().gebdatNichtPflicht()) {
        var positionGebdat = pflichtfelder.indexOf("gebdat");
        if (positionGebdat != -1) {
          pflichtfelder.splice(positionGebdat, 1);
        }
      }
    } else if (self.isHauptTnFirma()) {
      pflichtfelder = self.mitarbeiterPflichtfelder;
    } else { //weiterer Teilnehmer ist ein Erwachsener
      pflichtfelder = self.weiterePflichtfelder;
    }
    for (var i = 0; i < pflichtfelder.length; i++) {
      var varname = pflichtfelder[i];
      if (typeof (self.geradeEditierterWeitererTn()[varname]) == 'function') {
        if (typeof (self.geradeEditierterWeitererTn()[varname]()) === 'undefined' || self.geradeEditierterWeitererTn()[varname]().trim() === '') {
          self.handleRequiredMessageForWeiterenTn(varname);
          return true;
        }
      } else {
        if (typeof (self.geradeEditierterWeitererTn()[varname]) === 'undefined' || self.geradeEditierterWeitererTn()[varname].trim() === '') {
          self.handleRequiredMessageForWeiterenTn(varname);
          return true;
        }
      }
    }
    return false; //beim weiteren Teilnehmer wurden also alle Pflichtfelder ausgefüllt
  };
  
  self.handleRequiredMessageForWeiterenTn = function(varname) {
    if (self.einstellungen().anmFormWithRequired && typeof $('input[data-bind*="geradeEditierterWeitererTn().'+'name'+'"]')[0].reportValidity !== 'undefined') {
      var $input = $('input[data-bind*="geradeEditierterWeitererTn().'+varname+'"]');
      if ($input.length > 0) {
        $input.attr('required', true);
        $input[0].reportValidity();
      }
    }
  };

  self.isGebdatFalschesFormat = function () {
    return (
            typeof (self.geradeEditierterWeitererTn().gebdat()) !== "undefined"
            && self.geradeEditierterWeitererTn().gebdat() != ''
            && !(/(0[1-9]|[12][0-9]|3[01])\.(0[1-9]|1[012])\.(19|20)\d\d/.test(self.geradeEditierterWeitererTn().gebdat()))
            );
  };

  self.isEmailFalschesFormat = function () {
    return (
            typeof (self.geradeEditierterWeitererTn().email()) !== "undefined"
            && self.geradeEditierterWeitererTn().email() != ''
            && !(/.*@.*\..*/.test(self.geradeEditierterWeitererTn().email()))
            );
  };
  
  self.isPostleitzahlFalschesFormat = function () {
    const magicPlzKategorie = self.einstellungen().plzValidierung;
    let anzahlStellen = '';
    switch (magicPlzKategorie) {
      case '1':
        anzahlStellen = '5';
        break;
      case '2':
        anzahlStellen = '4,5';
        break;
      case '3':
        anzahlStellen = '4';
        break;
      default:
        return false;//vgl. Funktionsname
    }
    const pattern = new RegExp("^([0-9]{" + anzahlStellen + "})$");
    return (
            typeof (self.geradeEditierterWeitererTn().nurplz()) !== "undefined"
            && self.geradeEditierterWeitererTn().nurplz() != ''
            && !(pattern.test(self.geradeEditierterWeitererTn().nurplz()))
            );
  };

  self.submitWeiteren = function () { //Hinweismeldung ausgeben, warum man den weiteren Teilnehmer nicht hinzufügen darf.	

    if (self.isWeitererUngueltig()) {
      if (!self.einstellungen().anmFormWithRequired || typeof $('input[data-bind*="geradeEditierterWeitererTn().'+'name'+'"]')[0].reportValidity === 'undefined') {//wird sonst über die validationMessage(required) gemacht
        alert('Bitte tragen Sie erst Werte in die Pflichtfelder ein.');
      }
      return false;
    } else if (self.isGebdatFalschesFormat()) {
      alert('Das Geburtsdatum muss das Format TT.MM.YYYY haben.');
      return false;
    } else if (self.isEmailFalschesFormat()) {
      alert('Es handelt sich nicht um eine korrekte E-Mailadresse.');
      return false;
    } else if (self.isPostleitzahlFalschesFormat()) {
      alert('Die Postleitzahl hat ein falsches Format.');
      return false;
    } else if (self.CheckifHauptLikeWeiterer()) {
      alert('Dieser Teilnehmer ist bereits als Zahlungspflichtiger eingetragen. Bitte geben Sie einen anderen Teilnehmer an.');
      return false;
    }
    else if (!self.checkSubmitWeiteren()) {
      var gueltigkeitGebdat = checkAge(self.geradeEditierterWeitererTn().gebdat(), self.geradeEditierterKurs().beginn_dat, self.geradeEditierterKurs());
      if (gueltigkeitGebdat == null) {
        alert('Es handelt sich nicht um ein korrektes Geburtsdatum.');
      }
      else {
        if( gueltigkeitGebdat != 0 ) {
            if( self.geradeEditierterKurs().altervon == 0 && self.geradeEditierterKurs().alterbis == 0 ) {
                alert('Das Alter des Teilnehmers muss zu Kursbeginn zwischen ' + self.geradeEditierterKurs().monataltvon + ' und ' + self.geradeEditierterKurs().monataltbis + ' Monaten liegen.');
            }
            else {
                alert('Das Alter des Teilnehmers muss zu Kursbeginn zwischen ' + self.geradeEditierterKurs().altervon + ' und ' + self.geradeEditierterKurs().alterbis + ' Jahren liegen.');
            }
        }
      }
      return false;
    }
    self.geradeEditierterWeitererTn().istanonym(false); //Trägt man Name usw. ein, handelt es sich folglich nicht mehr um einen anonymen Teilnehmer.
    
    if (self.geradeWirdEinNeuerTeilnehmerEditiert) {
      self.geradeEditierterKurs().addWeiteren(self.geradeEditierterWeitererTn());
    }
    self.geradeEditierterWeitererTn(new TeilnehmerPflicht());
    self.refreshGebuehrenSummenAjax();
    self.wirdGeradeEinWeitererEditiert(false);
    self.geradeEditierterKurs(false);
    self.geradeWirdEinNeuerTeilnehmerEditiert = false;
    //immer beim Schließen des "Weiteren" Dialogs: ggf. required entfernen
    jQuery('div.eingabeWeiterer input[required]').removeAttr('required');
  };

  self.isWeitererGebdatPflicht = function () {
    return (self.weiterePflichtfelder.indexOf('gebdat') > -1);
  };
  
  self.isWeitererGebjahrPflicht = function() {
	return (self.weiterePflichtfelder.indexOf('gebjahr') > -1);
  };
  
  self.isMitarbeiterGebdatPflicht = function () {
    return (self.mitarbeiterPflichtfelder.indexOf('gebdat') > -1);
  };
  
  self.isMitarbeiterGebjahrPflicht = function () {
    return (self.mitarbeiterPflichtfelder.indexOf('gebjahr') > -1);
  };

  self.isKindGebdatPflicht = function () {
    return (self.kinderPflichtfelder.indexOf('gebdat') > -1);
  };
  
  self.isKindGebjahrPflicht = function() {
    return (self.kinderPflichtfelder.indexOf('gebjahr') > -1);
  };
  
  self.getGebdat = function(teilnehmer) {
    var gebdat = '';
    if( teilnehmer.gebdat() != undefined && teilnehmer.gebdat() != "" ) {
	  gebdat = teilnehmer.gebdat();		 
    }
    else if( teilnehmer.gebjahr() != undefined && teilnehmer.gebjahr() != "" ) {
	  gebdat = '01.01.'+teilnehmer.gebjahr();		  
    }
    else {
	  gebdat = '';
    }
    return gebdat;
  };

  self.checkSubmitWeiteren = function () { //Überprüfen, ob man den weiteren Teilnehmer hinzufügen darf.
    var kurs = self.geradeEditierterKurs();
    var einstellungen = self.einstellungen;
    var weiterer = self.geradeEditierterWeitererTn();
    /*//spezieller Block für Ottobrunn, nicht allgemein übernehmen!
     if( kurs.webflags == 4 && !einstellungen().nurnormaleanmeldearten && einstellungen().nurerlaubteanmeldearten && self.isKindGebdatPflicht() ) {
     //weiterer Teilnehmer ist zu jung
     if( kurs.altervon > calculateAgeInYears(weiterer.gebdat(), kurs.beginn_dat) ) {
     return false;
     }
     //weiterer Teilnehmer ist zu alt
     if( kurs.alterbis > 0 && kurs.alterbis < calculateAgeInYears(weiterer.gebdat(),kurs.beginn_dat) ) {
     return false;
     }
     return true;
     }*/ //Ende spezieller Block für Ottobrunn
    var gebdat = self.getGebdat(weiterer);
    if ((gebdat == undefined || gebdat == "") && ((weiterer.istkind() && !self.isKindGebdatPflicht() && !self.isKindGebjahrPflicht())
            || (!weiterer.istkind() && !self.isWeitererGebdatPflicht() && !self.isWeitererGebjahrPflicht())
            || (self.isHauptTnFirma() && !self.isMitarbeiterGebdatPflicht()  && !self.isMitarbeiterGebjahrPflicht()))) {
      return true;
    }

    if( gebdat == undefined || gebdat == "" ) {
      return false;
    }

    if (weiterer.istkind() || einstellungen().anmErwachsenerTnGeburtsdatumKursEntsprechen) {
      //weiterer Teilnehmer ist zu jung
      if( checkAge(weiterer.gebdat(), kurs.beginn_dat, kurs) != 0 ) {
        return false;
      }
    }
    return true;
  };

  self.abortWeiteren = function () {
    // Für Köln Elternschule:
    // Wird das Hinzufügen von Teilnehmern abgebrochen und es gibt keine Teilnehmer mehr, so muss der Haken für die Kinderbetreuung entfernt werden.
    if (self.sichtSettings.einrichtung == 'koelnelternschule' && ((typeof self.geradeEditierterKurs().weitereTeilnehmer == 'undefined') || (typeof self.geradeEditierterKurs().weitereTeilnehmer == 'function') && (self.geradeEditierterKurs().weitereTeilnehmer().length < 1))) {
      self.geradeEditierterKurs().beleghistorie2(false);
    } // /Elternschule
    self.geradeEditierterWeitererTn(new TeilnehmerPflicht());
    self.wirdGeradeEinWeitererEditiert(false);
    self.geradeEditierterKurs(false);
    self.geradeWirdEinNeuerTeilnehmerEditiert = false;
    
    jQuery('div.eingabeWeiterer input[required]').removeAttr('required');
  };

  //Wie viel Prozent der Kursgebühr darf ermäßigt werden? Dabei wird beachtet, was der Teilnehmer ausgewählt hat.
  self.ermaessigungsProzente = function () {
    var einstellungen = self.einstellungen;
    var prozente = 0;
    if (typeof (self.hauptTn()) != 'undefined' && typeof (self.hauptTn().erm_grund) != 'undefined' && typeof (einstellungen().ermaessigungen) != 'undefined' && typeof (einstellungen().ermaessigungen[self.hauptTn().erm_grund()]) != 'undefined' && typeof (einstellungen().ermaessigungen[self.hauptTn().erm_grund()].prozente) != 'undefined') {
      prozente = einstellungen().ermaessigungen[self.hauptTn().erm_grund()].prozente;
    }
    return prozente;
  };

  self.gebuehrenSummeFuerKurs = function (kurs, zuErmKennzAry) {
      var einstellungen = self.einstellungen;
      var total = 0;
      var value = parseFloat(kurs.gebuehrProPersonOhneErm().replace(',', '.'));

      //Hat der Kurs eines der Kennzeichen, das als Array an diese Funktion übergeben wurde?
      var kennzGefunden = false;
      if (typeof (zuErmKennzAry) != 'undefined' && zuErmKennzAry != '') {
        for (i = 0; i < zuErmKennzAry.length; i++) {
          if (kurs.hasKennzeichen(zuErmKennzAry[i])) {
            kennzGefunden = true;
          }
        }
      }

      var prozente = 0;
      //Entweder hat der Kurs eines der zu ermäßigenden Kennzeichen oder es wurden gar keine zu ermäßigenden Kennzeichen übergeben
      //und somit wird die Ermäßigung ganz normal auf alle Kurse angerechnet
      //Die Ermäßigung ändert sich nur live auf der Eingabeseite, wenn auch die Einstellung "Dynamische Anzeige der Ermäßigung" im Webadmin aktiviert wurde.
      if ((kennzGefunden || typeof (zuErmKennzAry) == 'undefined' || zuErmKennzAry == '') && einstellungen().ermaessigungberuecksichtigen) {
        prozente = self.ermaessigungsProzente();
      }
      if (!isNaN(value)) {
        //Kinder anders berechnen als erwachsene weitere Teilnehmer
        if (kurs.weitereTeilnehmer().length > 0 && kurs.weitereTeilnehmer()[0].istkind()) {
          //Wenn der Hauptteilnehmer bzw. das Elternteil auch mit zum Kinderkurs geht, dann gilt zumindest für ihn auch die Ermäßigung
          if (kurs.hauptTnAuch() > 0) {
            total += (value - (value * prozente) / 100)
          }
          //Jetzt noch addieren, wie viel für die Kinder bezahlt werden muss
          var geb_kind = kurs.geb_kind;
          var geb_zuskind = kurs.geb_zuskind;
          if (geb_kind == undefined) {
            geb_kind = 0;
          }
          total += parseFloat(geb_kind) + parseFloat(geb_zuskind) * (kurs.weitereTeilnehmer().length - 1); //Die Länge ist größer als 0, wird vom if oben sichergestellt. Erstes Kind kostet ja u.U. einen anderen Preis als weitere Kinder.
        } else {
          // Keine Eltern-Kind-Anmeldung, also Ermäßigung für alle Teilnehmer verwenden (in Zukunft dann evtl. noch Splitanmeldung beachten)
          var anzTn = kurs.weitereTeilnehmer().length;
          if (kurs.hauptTnAuch() > 0) {
            anzTn++;
          }
          total += (value - (value * prozente) / 100) * anzTn;
        }
      }
      return total;
  };

  //zuErmKennzAry dient dazu, bei Kursen mit diesen Kennzeichen eine Ermäßigung zu berücksichtigen. Wird nichts übergeben, so gilt die Ermäßigung für alle Kurse.
  self.gebuehrenSumme = function (zuErmKennzAry) {
    var einstellungen = self.einstellungen;
    var total = 0;
    //Alle Kurse durchlaufen und den korrekten Preis zur Gesamtsumme addieren
    ko.utils.arrayForEach(self.kurse(), function (kurs) {
      total += self.gebuehrenSummeFuerKurs(kurs, zuErmKennzAry);
    });
    if( typeof(self) != 'undefined' && typeof(self.hauptTn()) != 'undefined' 
            && typeof(self.hauptTn().spendenbetrag) != 'undefined'  
            && typeof(self.hauptTn().spendenbetrag()) != 'undefined'
            && typeof(self.hauptTn().spendencheck()) != 'undefined'
            && self.hauptTn().spendencheck()
            && einstellungen().ermaessigungberuecksichtigen ) {
      total += parseFloat(self.hauptTn().spendenbetrag().replace(',', '.'));
    }
    return total.toFixed(2);
  };
  //interessantes Schnippsel
  /*var x = ko.utils.arrayFirst(self.kurse(), function(item) {
   return ko.utils.stringStartsWith(item.knr.toLowerCase(), pKurs.knr);
   });*/

  //Für Bonn FBS
  //Äquivalent zur Gesamtsumme der Kursgebühren, nur dass eben die Wunschgebühr aus den beleghistorie1-Feldern aller Kurse summiert wird und nicht die eigentliche Kursgebühr.
  self.beleghistorie1Summe = function () {
    var gesamt = 0;
    for (var i = 0; i < self.kurse().length; i++) {
      var kurs = self.kurse()[i];
      if (typeof (kurs.beleghistorie1) == 'undefined' || typeof (kurs.beleghistorie1()) == 'undefined' || kurs.beleghistorie1() == '') {
        return gesamt;
      } else {
        gesamt = gesamt + parseFloat(kurs.beleghistorie1().replace(/,/g, '.'));
      }
    }
    return gesamt.toFixed(2).toString().replace('.', ',');
  };

  self.tnToObservable = function (pTnStruktur, pTn, pEinstellungen) {
    var result = new TeilnehmerPflicht(pTn.name);
    //Observables erzeugen
    for (var field in pTnStruktur) {
      if (pTnStruktur.hasOwnProperty(field) &&
              (typeof (pTnStruktur[field]) != 'object' || typeof (pTnStruktur[field].length) == 'undefined')) {//kein Array
        result[field] = ko.observable();
      }
    }
    for (var field in pTn) {
      if (pTn.hasOwnProperty(field) &&
              (typeof (pTn[field]) != 'object' || typeof (pTn[field].length) == 'undefined') && field != 'ibanxxx') {
				  //kein Array
				if (self.capitalizeHauptTnfelder.indexOf(field) > -1){
					result[field] = ko.observable(pTn[field]).extend({ uppercase: true });
				} else {
					result[field] = ko.observable(pTn[field]);
				}
		
      }
      //alert (field + ': ' + typeof(kurs[field]) + ' : ' + typeof(kurs[field].length));
    }
	
    result['ibanxxx'] = ko.computed(function () {
      if (typeof result.iban() !== 'undefined') {
        var ibanLength = result.iban().length;
        if (ibanLength > 3) {
          var xs = '';
          for (var i = 3; i < ibanLength; i++) {
            xs += "x";
          }
          return xs + result.iban().substring(ibanLength - 3);
        } else {
          return result.iban();
        }
      } else {
        return '';
      }
    }, this);
    
    return result;
  };

  //kann mit dem Binding optionsAfterRender: $root.setOptionHTML verwendet werden, um z.B. bei Zahlplänen Umlaute korrekt anzuzeigen (sind dort HTML encodet)
  self.setOptionHTML = function(option, objektMitTitel) {
    ko.applyBindingsToNode(option, {
        html: objektMitTitel.titel
    })
  }

  self.fromJson = function (pJson) { //Erzeugt aus dem von PHP erhaltenen JSON-Objekt mehrere KnockoutJS-Objekte, die dann in anmeldung.js und in den Sichten benutzt werden können.
    var data = ko.utils.parseJson(pJson);
    var tnStruktur = data.strukturTn;//leere TeilnehmerPflicht Struktur, um die Observables korrekt erzeugen zu können
    //self.tnStruktur = tnStruktur;
    //hier Ausnahmen für Felder einfügen, die von KnockoutJS dynamisch geändert werden können sollen!
    var kursObservableVars = ['hauptTnAuch', 'zahlplan', 'beleghistorie1', 'beleghistorie2', 'beleghistorie3', 'beleghistorie4', 'beleghistorie5', 'beleghistorie6', 'beleghistorie7', 'beleghistorie8', 'beleghistorie9', 'beleghistorie10', 'beleghistorie11', 'beleghistorie12', 'beleghistorie13', 'beleghistorie14', 'beleghistorie15', 'beleghistorie16', 'info2doz', 'nuronline'];
    var messages = data.messages;
    if (data.hauptTn) {
      if (typeof (data.einstellungen) != 'undefined' && data.einstellungen.spendenbetrag != '' && data.hauptTn.spendenbetrag == '') {
        data.hauptTn.spendenbetrag = data.einstellungen.spendenbetrag;
        if (self.sichtSettings.spendenbetragInitialAktiv) {
          data.hauptTn.spendencheck = true;
        }
      }
      var hauptTnObservable = self.tnToObservable(tnStruktur, data.hauptTn, data.einstellungen);
      hauptTnObservable.arykennzeichenJS = ko.observableArray(data.hauptTn.arykennzeichenJS);
      hauptTnObservable.aryattachmentsJS = ko.observableArray(data.hauptTn.aryattachmentsJS);
      hauptTnObservable.uploadAttachments = ko.observableArray(data.hauptTn.uploadAttachments);
      hauptTnObservable.defaults_gesetzt = ko.observableArray(data.hauptTn.defaults_gesetzt);
      hauptTnObservable.newsl_interessensgebiete = ko.observableArray(data.hauptTn.newsl_interessensgebiete);
      self.hauptTn(hauptTnObservable);
    }
    self.hauptTn().erm_grund.subscribe(function(newValue) {
      self.refreshGebuehrenSummenAjax();
    });
    self.hauptTn().spendenbetrag.subscribe(function(newValue) {
      self.refreshGebuehrenSummenAjax();
    });
    self.hauptTn().spendencheck.subscribe(function(newValue) {
      self.refreshGebuehrenSummenAjax();
    });
    self.hauptTn().geschlecht.subscribe(function(newValue) {
      if(newValue == 'F') {
        // Wenn die Ermäßigung bei M/W auswählbar ist, aber nicht bei der Firma kann ohne diese Zeile bei z.B. "M" 
        // eine Ermäßigung ausgewählt werden welche nach dem umschalten zum Geschlecht "F" trotzdem erhalten bleibt.
        self.hauptTn().erm_grund(-1);
        self.firmaBehandlung();
      } else {
        self.menschBehandlung();
      }

      self.refreshGebuehrenSummenAjax();
    });
    for (var i = 0; i < data.kurse.length; i++) {
      var kurs = data.kurse[i];
      var gebuehrGeparsed = parseFloat(kurs.gebuehr.replace(',', '.'));
      var kursOut = new Kurs(kurs.id, kurs.beginn_dat, gebuehrGeparsed, self.sichtSettings);
      for (var field in kurs) {
        kursOut['defaults_gesetzt'] = ko.observableArray(kurs.defaults_gesetzt);
        if (kurs.hasOwnProperty(field) &&
                (typeof (kurs[field]) != 'object' || typeof (kurs[field].length) == 'undefined')) {//kein Array
          kursOut[field] = kurs[field];
        }
        if (field == "kennzeichen") {
          kursOut[field] = kurs[field];
        }
        if (field == "zahlplaene") {
          if (kurs[field].length > 0) {
            var nameStandardZahlplan = 'Normal';
            if (kurs.gebuehr_name != "") {
              nameStandardZahlplan = kurs.gebuehr_name;
            }
            var zahlplaeneAry = ko.observableArray([{titel: nameStandardZahlplan, wert: '-1'}]);
            for (var j = 0; j < kurs[field].length; j++) {
              var kursgebuehren = ko.observableArray();
              for (var k = 0; k < kurs[field][j].kursgebuehren.length; k++) {
                kursgebuehren.push(kurs[field][j].kursgebuehren[0]);
              }
              zahlplaeneAry.push({
                titel: kurs[field][j].beschreibung,
                wert: kurs[field][j].id,
                zusatz: kurs[field][j].zusatz,
                kursgebuehren: kursgebuehren,
                gebuehrengesamt: kurs[field][j].gebuehrengesamt,
                gebuehrengesamtermbar: kurs[field][j].gebuehrengesamtermbar
              });
            }
            kursOut["zahlplaene"] = zahlplaeneAry;
          }
        }
        //Felder auch nach dem ersten Absenden wieder zu Observables machen
        if (kursObservableVars.indexOf(field) > -1) {
          kursOut[field] = ko.observable(kurs[field]);
        }
      }

      //ja, das steht absichtlich hier, im Kurs hat es nicht funktioniert
      kursOut['gebuehrProPersonOhneErm'] = ko.computed(function () {
        var curZahlplan = null;
        if (this.zahlplan() !== "-1" && typeof (this.zahlplaene) === "function") {
          for (var i = 0; i < this.zahlplaene().length; i++) {
            if (this.zahlplan() === this.zahlplaene()[i].wert) {
              curZahlplan = this.zahlplaene()[i];
            }
          }
        }

        var value = NaN;
        if (curZahlplan !== null && self.einstellungen().zahlplanberuecksichtigen) {
          value = parseFloat(curZahlplan.gebuehrengesamt).toFixed(2).toString().replace('.', ',');
        } else {
          value = this.gebuehr;
        }
        return value;
      }, kursOut);//somit wird kursOut als this an die function übergeben

      //weitere Teilnehmer
      if (kurs.weitereTeilnehmer) {
        for (var j = 0; j < kurs.weitereTeilnehmer.length; j++) {
          var tn = kurs.weitereTeilnehmer[j];
          kursOut.addWeiteren(self.tnToObservable(tnStruktur, tn));
        }
      }
      kursOut.weitereTeilnehmer.subscribe(function(newValue) {
        self.refreshGebuehrenSummenAjax();
      });
      kursOut.zahlplan.subscribe(function(newValue) {
        self.refreshGebuehrenSummenAjax();
      });
      self.kurse.push(kursOut);
    }
    self.einstellungen(data.einstellungen);
  };

  self.refreshGebuehrenSummenAjax = function() {
    if(self.sichtSettings.useGebSumAjaxBrutto === 1) {
      self.refreshGebuehrenSummeAjaxBrutto();
    }
    self.refreshing(false);
    if(self.sichtSettings.useGebSumAjaxNetto === 1) {
      self.refreshGebuehrenSummeAjaxNetto();
    }
  };

  self.refreshGebuehrenSummeAjaxBrutto = function() {
    let setGebuehrenSummenBrutto = function(pData) {
      self.gebuehrenSummeAjax(parseFloat(pData.sum).toFixed(2).replace(".", ","));
      self.gebuehrenSummeAjaxNichtErmaessigt(parseFloat(pData.sumNichtErmaessigt).toFixed(2).replace(".", ","));
      self.gebuehrenSummeAjaxRabatt(parseFloat(pData.sumNichtErmaessigt - pData.sum).toFixed(2).replace(".", ","));
      self.gebuehrenSummeAjaxImmerErmaessigt(parseFloat(pData.sumImmerErmaessigt).toFixed(2).replace(".", ","));
    };
    self.refreshGebuehrenSummeAjax(setGebuehrenSummenBrutto, 1);
  };

  self.refreshGebuehrenSummeAjaxNetto = function() {
    let setGebuehrenSummenNetto = function(pData) {
      self.gebuehrenSummeAjaxNetto(parseFloat(pData.sum).toFixed(2).replace(".", ","));
      self.gebuehrenSummeAjaxNettoNichtErmaessigt(parseFloat(pData.sumNichtErmaessigt).toFixed(2).replace(".", ","));
      self.gebuehrenSummeAjaxNettoRabatt(parseFloat(pData.sumNichtErmaessigt - pData.sum).toFixed(2).replace(".", ","));
      self.gebuehrenSummeAjaxNettoImmerErmaessigt(parseFloat(pData.sumImmerErmaessigt).toFixed(2).replace(".", ","));
    };
    self.refreshGebuehrenSummeAjax(setGebuehrenSummenNetto, 0);
  };
  
  self.refreshGebuehrenSummeAjax = function(sucessCallback, brutto) {
    if (self.refreshing()) {
      return;
    }
    if (typeof window.kw === "undefined") {
      window.kw = {};
    }
    if (kw && kw.wbBasePath) {
      var payloaddata = self.ajaxGenerateGebuehrenPayload(brutto);
      
      //var tn = {zp: -1, erm_grund:-1};
      //var payloaddata = {data:[{knr: "0815", tns: [tn], kinderanzahl: 0}, {knr: "0816", tn: [tn], kinderanzahl: 5}]};
      self.refreshing(true);
      jQuery.ajax({
        type: "POST",
        url: kw.wbBasePath + 'index.php?ajaxAction=getGebuehrensumme',
        data: payloaddata,
        success: function( pData ){
          sucessCallback(pData);
          self.refreshing(false);
        },
        error: function(jqXHR, textStatus, errorThrown) {
          console.log("AJAX Error: " + textStatus + ": " + errorThrown);
          self.refreshing(false);
        }
      });
    }
  };
  
  self.ajaxGenerateGebuehrenPayload = function(brutto) {
    var ermgrund = self.hauptTn().erm_grund();
    var ermGrundFuerWeitere = -1;
    if (self.einstellungen().isGebuehrFuerWeitereTnErmaessigbar) {
      ermGrundFuerWeitere = ermgrund;
    }

    var payloaddata = {data:[]};
    for (var i = 0; i < self.kurse().length; i++) {
      var haupttn = {zp: -1, erm_grund: ermgrund};
      var kurs = {
        knr: "",
        tns: [],
        kinderanzahl: 0,
        isFirmenanmeldung: self.hauptTn().geschlecht() === 'F' ? 1 : 0,
        isRabattierbar: 1,
        brutto: brutto
      };
      kurs.spendenbetrag = i == 0 && self.hauptTn().spendencheck() ? self.hauptTn().spendenbetrag() : null;
      var vmKurs = self.kurse()[i];

      var zahlplan = -1;
      if (vmKurs.zahlplan() > 0 && self.einstellungen().zahlplanberuecksichtigen) {
        zahlplan = vmKurs.zahlplan();
      }
      
      haupttn.zp = zahlplan;
      kurs.knr = vmKurs.knr;
      kurs.hauptTnAuch = vmKurs.hauptTnAuch();
      if (vmKurs.hauptTnAuch() == 1) {
        kurs.tns.push(haupttn);
      }
      for (var j = 0; j < vmKurs.weitereTeilnehmer().length; j++) {
        var currentTn = vmKurs.weitereTeilnehmer()[j];
        //das funktioniert, weil istkind mittlerweile über alle weiteren TN konsistent gehalten wird
        if (currentTn.istkind()) {
          kurs.kinderanzahl++;
        }
        else {
          var tn = {zp: zahlplan, erm_grund: ermGrundFuerWeitere};
          kurs.tns.push(tn);
        }
      }
      payloaddata.data.push(kurs);
    }
    return payloaddata;
  };
  /*
   var anminfo = 
   {
   "hauptTn": {},
   "kurse": [
   {
   "knr": "161-3207",
   "gebuehr": 10,
   "beginn_dat": "02.10.2016",
   "weitereTeilnehmer": [
   {
   "name": "aa1name",
   "vorname": "aavorname"
   },
   */
}//KwAnmeldeViewModel


//var dataFromServer = ko.utils.parseJson(anminfoString);


jQuery(function ($) {
  if (typeof (anminfoString) !== 'undefined') {
    var myViewModel = new KwAnmeldeViewModel();
    // 'refreshing' wird auf true gesetzt bis myViewModel.refreshGebuehrenSummeAjax() aufgerufen wird, da
    // ein früherer Aufruf dazu führen kann, dass z.B. die hinterlegte Ermäßigung nicht berücksichtigt wird. Der Grund:
    // Beim ersten Aufruf wurde z.B. die Ermäßigung noch nicht geladen und folgende Aufrufe finden aufgrund von 
    // refreshing == true nicht mehr statt.
    myViewModel.refreshing(true);
    ko.bindingHandlers.confirmClick = {//Für Fenster, in denen gefragt wird "Wollen Sie wirklich abbrechen? Ja/Nein".
      init: function (element, valueAccessor, allBindings, viewModel) {
        var value = valueAccessor();
        var message = ko.unwrap(value.message);
        var click = value.click;
        ko.applyBindingsToNode(element, {click: function () {
            if (confirm(message))
              return click.apply(this, Array.prototype.slice.apply(arguments));
          }}, viewModel);
      }
    };
    
    if (typeof (kwOnBeforeBinding) === "function") {
      kwOnBeforeBinding(myViewModel);
    }
    ko.applyBindings(myViewModel);
    var datastring = base64.decode(anminfoString);
    myViewModel.fromJson(datastring);

    // Deprecated:
    // Wird nurnoch verwendet für Kunden bei denen dies in individuellen Anpassungen verwendet wurde.
    // 
    // Use:
    // KuferWEB.OnAnmeldungInit.push(<function>)
    if (typeof (kwAnmOnInit) === "function") {
      kwAnmOnInit(myViewModel);
    }

    if (typeof (KuferWEB.OnAnmeldungInit) !== "undefined" && Array.isArray(KuferWEB.OnAnmeldungInit)) {
      KuferWEB.OnAnmeldungInit.forEach(function(func) {
        func(myViewModel);
      });
    }
    myViewModel.refreshing(false);
    myViewModel.refreshGebuehrenSummenAjax();
  }
  // Umschalten zwischen Überweisung/Lastschrift
  // Verstecken beim Seitenaufruf
  if (jQuery('#bedit_zahlartlastid').is(':checked')) {
    jQuery("#bankdaten").fadeIn();
    jQuery("#payment").hide();
  }
  else {
    jQuery("#bankdaten input[type=text]").each(function(index, item) {
      kw_prepareRequiredFieldForHiding($(item));
    });
  }
  if (jQuery('#bedit_zahlartueberid').is(':checked')) {
    jQuery("#bankdaten").hide();
    jQuery(".hasDataCheck").hide();
    jQuery("#payment").hide();
  }
  if (jQuery('#bedit_zahlartonlineid').is(':checked')) {
    jQuery("#bankdaten").hide();
    jQuery(".hasDataCheck").hide();
    jQuery("#payment").fadeIn();
  }
  if (jQuery('#tedit_keinebankverbindungid').is(':checked')) {
    //jQuery(".hasData").hide();
    jQuery("#bankdaten").hide();
  }

  //Wenn auf Überweisung geklickt wird, dann Lastschrift-Felder leeren und verstecken
  jQuery("[name='bedit_zahlart']").change(function () {
    if (this.value === "L") {
      //kw_prepareRequiredFieldForUnHiding(jQuery("#tedit_ibanid"));
      //kw_prepareRequiredFieldForUnHiding(jQuery("#tedit_bicid"));
      //kw_prepareRequiredFieldForUnHiding(jQuery("#tedit_bankbezid"));
      jQuery("#bankdaten input[type=text]").each(function(index, item) {
        kw_prepareRequiredFieldForUnHiding($(item));
      });
      jQuery(".hasDataCheck").fadeIn();
      jQuery("#tedit_zahlmethode_bankeinzug").click().trigger('click');
      jQuery("#payment").hide();

      if (jQuery('#tedit_keinebankverbindungid').is(':checked')) {
        jQuery("#bankdaten").hide();
      } else {
        jQuery("#bankdaten").fadeIn();
      }
    } else {//Wenn e-Payment ausgewählt wird, werden die e-Payment-Felder eingeblendet und die Bankdaten-Felder ausgeblendet
      
      jQuery("#bankdaten input[type=text]").each(function(index, item) {
        kw_prepareRequiredFieldForHiding($(item));
      });
      if (this.value === "epay") {
        jQuery(".hasDataCheck").hide();
        jQuery("#bankdaten").hide();
        jQuery("#payment").fadeIn();
      } else {//Bankdaten ausblenden, wenn Überweisung ausgewählt wird
        jQuery("#tedit_zahlmethode_bankeinzug").click().trigger('click');
        divFelderLeeren(jQuery(".hasDataCheck"));
        divFelderLeeren(jQuery("#bankdaten").not(".loginon")); // wenn nicht eingeloggt, felder leeren
        jQuery(".hasDataCheck").hide();
        jQuery("#bankdaten").hide();
        jQuery("#payment").hide();
      }
    }
  });

  //Wenn Haken "keinebankverbindung" gesetzt wird, dann Bankdaten ausblenden.
  //Wird der Haken entfernt, dann Bankdaten wieder einblenden.
  jQuery('#tedit_keinebankverbindungid').change(function () {
    if (this.checked) {
      divFelderLeeren(jQuery("#bankdaten"));
      jQuery("#bankdaten").hide();
    } else {
      jQuery("#bankdaten").fadeIn();
    }
  });
  /*beim Klick auf e-payment Button, wird die Zahlart auf epay umgestellt*/

  // Graut den "kostenpflichtig Anmelden" Button nach dem ersten Klick aus
  jQuery('.anmeldeformular_but').submit(function () {
    var form = document.querySelector('.anmeldeformular_but');
    form.querySelector('input[type="submit"]').setAttribute('disabled', 'disabled');
  });

  jQuery("[name='zahlmethode']").change(function () {
    if (this.value != "bankeinzug") {
      jQuery("#bedit_zahlartonlineid").click().trigger('click');
      divFelderLeeren(jQuery("#bankdaten").not(".loginon"));
    }
  });

  /*Giropay Bic*/
  if (jQuery('#tedit_zahlmethode_epay_girocheckout_giropay').is(':checked')) {
    jQuery('#giropaybic').show();
  } else {
    jQuery('#giropaybic').hide();
  }
  jQuery("[name='zahlmethode']").change(function () {
    if (this.value == "epay_girocheckout_giropay") {
      jQuery('#giropaybic').fadeIn();
    } else {
      jQuery('#giropaybic').hide();
    }
  });
});

function parseDateGerman(input) {
  var format = 'dd.mm.yyyy'; // default format
  var parts = input.match(/(\d+)/g), 
      i = 0, fmt = {};
  // extract date-part indexes from the format
  format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });

  return new Date(parts[fmt['yyyy']], parts[fmt['mm']]-1, parts[fmt['dd']]);
}

//Leert alle Felder, die sich innerhalb des targetDivs befinden.
//Wie divFelderLeerenBeiAnderung, nur dass diese Funktion innerhalb einer anderen Funktion aufgerufen werden kann, die verwaltet,
//wann etwas geändert werden soll und wann nicht.
//Im Zweifelsfalle lieber divFelderLeerenBeiAenderung() benutzen!
function divFelderLeeren($targetDiv) {
  //Für alle vom div eingeschlossenen textareas und input-Felder außer Checkboxen:
  $targetDiv.find('input:not([type=checkbox]), textarea').each(function () {
    jQuery(this).val(''); //Inhalt des Feldes leeren
    jQuery(this).trigger('change'); //per change aktualisieren, damit auch KnockoutJS die observables aktualisiert
  });

  //Für alle vom div eingeschlossenen Checkbox-Felder:
  $targetDiv.find('input[type=checkbox]').each(function () {
    //KnockoutJS scheint auf "click" zu prüfen und nicht auf change. Wir setzen es auf checked und "klicken" dann,
    //sodass die Checkbox nicht mehr angehakt ist.
    jQuery(this).prop('checked', true).trigger('click');
  });

}

//Alle Input-Felder, Textareas und Checkboxen leeren, die vom targetDiv eingeschlossen sind,
//wenn sich change ändert.
//Beispiel zur Benutzung: divFelderLeerenBeiAenderung(jQuery("[name='bedit_zahlart']"), jQuery('#bankdaten')); in einen JavaScript-Bereich auf der Seite einbauen
//--> Wenn auf eine andere Zahlart geklickt wird, dann alle Input-Felder und Textareas innerhalb des Divs mit der Klasse "bankdaten" leeren
function divFelderLeerenBeiAenderung($change, $targetDiv) {
  $change.change(function () {
    divFelderLeeren($targetDiv); //Wenn change angeklickt wird, dann rufe die Funktion zum leeren der Felder auf
  });
}

function kw_prepareRequiredFieldForHiding($field) {
  if ($field.length > 0 && $field.is('[required]')) {
    $field.removeAttr("required");
    $field.attr("data-kw-is-required", "1");
  }
}

function kw_prepareRequiredFieldForUnHiding($field) {
  if ($field.length > 0 && $field.attr("data-kw-is-required")==="1") {
    $field.removeAttr("data-kw-is-required");
    $field.attr("required", "required");
  }
}
