//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 me = this;
  me.id = ko.observable();
  me.name = ko.observable(pName);
  me.vorname = ko.observable();
  me.email = ko.observable();
  me.tel = ko.observable();
  me.tel2 = ko.observable();
  me.istkind = ko.observable(false);
  me.gebdat = ko.observable();
  me.gebjahr = ko.observable();
  me.geschlecht = ko.observable();
  me.erm_grund = ko.observable();
  me.nurplz = ko.observable();
  me.nurort = ko.observable();
  me.ort = ko.observable();
  me.nurstrasse = ko.observable();
  me.nurhausnr = ko.observable();
  me.strasse = ko.observable();
  me.zahlmethode = ko.observable();
  me.zahlart = ko.observable();
  me.arykennzeichenJS = ko.observableArray();
  me.arybranchenJS = ko.observableArray();
  me.aryattachmentsJS = ko.observableArray();
  me.uploadAttachments = ko.observableArray();
  me.spendenbetrag = ko.observable();
  me.bemerkung = ko.observable();
  me.gebdatNichtPflicht = ko.observable(false);
  me.newsl_erlaubt = ko.observable();
  me.newsl_interessensgebiete = ko.observableArray();
  me.defaults_gesetzt = ko.observableArray();
  me.istanonym = ko.observable(false);
  me.ausbildung = ko.observable();
  me.beruf = ko.observable();
  me.sozposition = ko.observable();
  me.sozarbeitgeber = ko.observable();
  me.istDienstlich = ko.observable(true);//Termin 72482
  //Patch für VHS Braunschweig vom 12.07.2019 zu H 462657
  me.iban = ko.observable();
  me.kommprio = ko.observable();
  me.nation = ko.observable();

  me.datei1 = ko.observable();
  me.datei1name = ko.observable();
  me.datei2 = ko.observable();
  me.datei2name = ko.observable();
  me.datei3 = ko.observable();
  me.datei3name = ko.observable();
  me.datei4 = ko.observable();
  me.datei4name = ko.observable();
  me.datei5 = ko.observable();
  me.datei5name = ko.observable();
  me.mitarbeiter = ko.observableArray();
  me.gutschein_code = ko.observable("");
  me.gutschein_nr = ko.observable("");
  me.gutschein_betrag = ko.observable("0,00");

  me.uploadduplikat = ko.observable(false);
  me.uploademptyfile = ko.observable(false);
  
  me.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) {
      me.uploademptyfile(false);
    }
    else {
	  if( element.files[0] !== undefined && element.files[0].name !== undefined ) {
		  me.uploademptyfile(element.files[0].name);
	  }
	  else {
		me.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)
     || (me.aryattachmentsJS().length > 0 && me.aryattachmentsJS().indexOf(aktDateiname) > -1 ) ) {
        clearFileInput(element);
        me.uploadduplikat(true);
        //alert("Das Hochladen mehrerer Dateien gleichen Namens ist nicht erlaubt."); //Könnte man auch so ausgeben.
    }
    else {
        me.uploadduplikat(false);
    }
  };

  if (typeof (KuferWEB.OnTeilnehmerPflichtCreate) !== "undefined" && Array.isArray(KuferWEB.OnTeilnehmerPflichtCreate)) {
    KuferWEB.OnTeilnehmerPflichtCreate.forEach(function(func) {
      func(self);
    });
  }
}

//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 == '') {
        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 me = this;
  me.knr = pKnr;
  me.gebuehrGeparsed = pGebuehr;
  me.beginn_dat = pBeginn;

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

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

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

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

  me.addWeiteren = function (pTeilnehmer) {
    me.weitereTeilnehmer.push(pTeilnehmer);
  };

  me.addWeiterenMitarbeiter = function(pTeilnehmer) {
    me.weitereTeilnehmer.push(pTeilnehmer);
  };

  me.removeWeiteren = function (pTn) {
    var curr = jQuery('div.eingabeWeiterer');
    curr.detach();
    jQuery('#kw-hafen_eingabeWeiterer').append(curr);

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

    if(typeof me.weitereTeilnehmer.remove(pTn)[0] == 'undefined'){
      me.weitereTeilnehmer.remove(function (item) { return item.id() === pTn.id(); })
    }
    //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 (me.weitereTeilnehmer().length < 1) {
        me.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( me.isNurAnonyme() ) {
      me.hauptTnAuch(1);
    }
  };

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

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


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

  me.isNurFuerKinder = function () { //Beim Kurs in KuferSQL wurde nur genau Eltern-Kind-Anmeldung angehakt.
    var nurKinderFlag = (me.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 me.geb_schw1 (1 übergeben) oder me.geb_schw2 (2 übergeben) handelt.
  me.schwelleAnzahlTeilnehmerProdukt = function (schwellengebNr) {
    var schwellengeb = (schwellengebNr == 1) ? me.geb_schw1 : (schwellengebNr == 2) ? me.geb_schw2 : 0;
    schwellengeb = schwellengeb.replace(',', '.');
    var anzHauptTn = (me.hauptTnAuch() > 0) ? 1 : 0;
    var weitereTeilnehmerLength = me.weitereTeilnehmer().length;
    if (weitereTeilnehmerLength > 0 && me.weitereTeilnehmer()[0].istkind()) {
      weitereTeilnehmerLength = weitereTeilnehmerLength - 1; //Das erste Kind soll kostenlos sein. Weitere Kinder kosten die volle Gebuehr.
    }
    return schwellengeb * (weitereTeilnehmerLength + anzHauptTn);
  };

  me.showSchwelleAnzahlTeilnehmerProdukt = function (schwellengebNr) {
    var rueckgabe = me.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 me = this;
  me.hauptTn = ko.observable(new TeilnehmerPflicht());
  me.kurse = ko.observableArray();
  me.einstellungen = ko.observable("");
  me.gebuehrenSummeAjax = ko.observable("0,00");
  me.gebuehrenSummeAjaxImmerErmaessigt = ko.observable("0,00");
  me.gebuehrenSummeAjaxNichtErmaessigt = ko.observable("0,00");
  me.gebuehrenSummeAjaxNetto = ko.observable("0,00");
  me.gebuehrenSummeAjaxNettoImmerErmaessigt = ko.observable("0,00");
  me.gebuehrenSummeAjaxNettoNichtErmaessigt = ko.observable("0,00");
  me.gebuehrenSummeAjaxRabatt = ko.observable("0,00");
  me.gebuehrenSummeAjaxNettoRabatt = ko.observable("0,00");
  me.refreshing = ko.observable(false);
  me.gutscheinCheckboxActive = ko.observable(false);
  me.gutscheinBetragGeben = ko.observable(true);

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

  me.setzeHauptTnFeld = function (key, value) {
    // muss geprüft werden, da sonst ein JavaScript-Fehler auftritt, weil beim ersten Aufruf eventuell das Feld noch nicht observable ist
    if(ko.isObservable(self.hauptTn()[key])){
      self.hauptTn()[key](value);
    }
    return true;
  };

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

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

  me.removeHauptTn = function (pKurs) {
    pKurs.hauptTnAuch(0);
    me.refreshGebuehrenSummenAjax();
    me.gebuehrenSummeAjaxRefreshFuerAlleKurse(me.kurse());
  };

  me.setHauptTn = function (pKurs) {
    pKurs.hauptTnAuch(1);
    me.refreshGebuehrenSummenAjax();
    me.gebuehrenSummeAjaxRefreshFuerAlleKurse(me.kurse());
  };

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

  me.menschBehandlung = function () {
    var einstellungen = me.einstellungen;
    for (var i = 0; i < me.kurse().length; i++) {
      var kurs = me.kurse()[i];
      kurs.hauptTnAuch(me.sichtSettings.hauptTnAuchNachMenschBehandlung);
      //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;
  };

  me.disableAddWeiteren = function (kurs) { //Button weiterer Teilnehmer ausgrauen? true = Ja, ausgrauen!
    var einstellungen = me.einstellungen;
    if (einstellungen().paypalisexpressco) {
      return true;
    }
    if (einstellungen().iskufersql5 && me.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( (me.hauptTn().geschlecht() != "F") && !((kurs.webflags & 4) == 4) && !((kurs.webflags & 16) == 16) && !((kurs.webflags & 32) == 32) ) {
	  var einstellungen = me.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.
  };

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

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


  me.isKursOhneKennzeichenimWK = function (zuPruefendeKennzeichen) {
    var keinsgefunden = false;
    if( me.kurse().length > 0 ) {
      ko.utils.arrayForEach(me.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;
  };

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

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

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

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

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

  me.CheckifHauptLikeWeiterer = function () {

    if ((me.hauptTn().name() == me.geradeEditierterWeitererTn().name())
            && (me.hauptTn().vorname() == me.geradeEditierterWeitererTn().vorname())
            && ((me.hauptTn().gebdat() == me.geradeEditierterWeitererTn().gebdat()) || (me.hauptTn().gebjahr() == me.geradeEditierterWeitererTn().gebjahr()))) {
      return true;
    }
    return false;
  };

  me.CheckifWeitererInMitarbeiterliste = function (pTeilnehmer) {
    if((me.geradeEditierterKurs() != false) &&(me.geradeEditierterKurs().weitereTeilnehmer() != false)) {
      if (me.geradeEditierterKurs().weitereTeilnehmer().some((element) => element.id() == pTeilnehmer.id())) {
        return true;
      }
    }
    return false;
  };
  /*me.isHauptTnAusgefuelltOeffneWeiteren = function()
   {
   return true;
   if( me.hauptTn().name != undefined && me.hauptTn().name() != '') {
   if( me.hauptTn().vorname != undefined && me.hauptTn().vorname() != '') {
   if( me.kurse != undefined && me.kurse().length > 0 && me.kurse()[0].weitereTeilnehmer != undefined && me.kurse()[0].weitereTeilnehmer().length < 1 ) {
   me.addWeiteren(me.kurse()[0]);
   return true;
   }
   }
   }
   return false;
   }*/

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

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

  me.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 (me.geradeEditierterKurs() == false) {
      return false;
    }
    var einstellungen = me.einstellungen;
    if (einstellungen().nurnormaleanmeldearten) {
      return false;
    }

    if (!einstellungen().nurerlaubteanmeldearten) {
      return true;
    }
    var kurs = me.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.
  me.checkKind = function (checked) {
    var einstellungen = me.einstellungen;
    
    if (einstellungen().iskufersql5 && me.istKinderkurs(me.geradeEditierterKurs())) {
      me.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 (me.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 ((me.geradeEditierterKurs().webflags == 4 || me.geradeEditierterKurs().webflags == 6) && (einstellungen().nurerlaubteanmeldearten)) {
      me.geradeEditierterWeitererTn().istkind(true);
      return true;
    }
    
    // Erster weiterer TN wird bearbeitet, es gibt noch keine weiteren
    var ersterWeiterer = me.geradeEditierterKurs().weitereTeilnehmer()[0];
    if (!ersterWeiterer) {
      me.geradeEditierterWeitererTn().istkind(checked);
      return checked;
    }

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

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

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

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

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

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

    var weitereTn = me.geradeEditierterKurs().weitereTeilnehmer();
    var einstellungen = me.einstellungen;
    if(einstellungen().iskufersql5 && me.istKinderkurs(me.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 ((me.geradeEditierterKurs().webflags == 4 || me.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 (me.geradeEditierterWeitererTn() != weitereTn[0]);
  };

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

  //speziell für Friedrichshafen VHS
  me.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
  me.nurDeutscheIban = function () {
    if (typeof (me.hauptTn().iban) == "function") {
      var val = me.hauptTn().iban();
      return val != "" && val.match(/^DE/);
    }
    return true;
  };

  me.checkFormatEintritt = function() {
       if( typeof(me.hauptTn().eintritt) != "function"
              || me.hauptTn().eintritt().search(/^\d\d\.\d\d\.\d\d\d\d$/i) != 0) {
          return false;
       }
       return true;
  }
  
  me.checkFormatAustritt = function() {
       if( typeof(me.hauptTn().austritt) != "function"
              || me.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
  me.checkEintrittAustritt = function() {
      if( !me.checkFormatEintritt()
              || !me.checkFormatAustritt() ) {
        return false;
      }
      if( typeof(me.kurse()[0]) == "undefined" || me.kurse().length != 1 ) {
          return false;
      }
      if( parseDateGerman(me.hauptTn().eintritt()) < parseDateGerman(me.kurse()[0].beginn_dat)
              || parseDateGerman(me.hauptTn().eintritt()) > parseDateGerman(me.kurse()[0].ende_dat) ) {
          return false;
      }
      if( parseDateGerman(me.hauptTn().austritt()) < parseDateGerman(me.kurse()[0].beginn_dat)
              || parseDateGerman(me.hauptTn().austritt()) > parseDateGerman(me.kurse()[0].ende_dat) ) {
          return false;
      }
      return true;
  }

  me.checkKurseAbsendbar = function() { //Müssen weitere Teilnehmer angegeben werden? Sind diese bei allen Kursen angegeben, bei denen dies nötig ist?
    if (me.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.
      me.firmaBehandlung();
    }
    for (var i = 0; i < me.kurse().length; i++) {
      var kurs = me.kurse()[i];
      if( me.checkZuWenigeTeilnehmer(kurs) || me.checkZuVieleTeilnehmer(kurs) ) {
        return false;
      }
    }
    return me.isEPayHauptTnAuch(); //Das E-Payment ist nur okay, wenn der Zahler an allen Kursen teilnimmt.
  };
  
  me.checkZuWenigeTeilnehmer = function(kurs) {
    if ((typeof (me.hauptTn().geschlecht) == "function")) {
        //Wenn der Hauptteilnehmer nicht teilnimmt
        if ((!kurs.hauptTnAuch() || kurs.hauptTnAuch() == 0) && (kurs.weitereTeilnehmer().length < 1)) {
            return true;
        }

        var einstellungen = me.einstellungen;
        if( me.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;
  };

  me.checkZuVieleTeilnehmer = function(kurs) {
    if ((typeof (me.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;
  };

  me.isEPayHauptTnAuch = function () { //Kann z.B. auch in Sicht 504 benutzt werden, um eine Hinweismeldung anzuzeigen.
    if (typeof (me.hauptTn().zahlart) != "undefined" && me.hauptTn().zahlart() == 'epay') {
      if (me.hauptTn().geschlecht != "undefined" && me.hauptTn().geschlecht() == 'F') {
        return true;
      }
      for (var i = 0; i < me.kurse().length; i++) {
        var kurs = me.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.
  me.checkKurseAbsendbarBeleghistorie1ZwischenSchwellengebuehren = function () {
    for (var i = 0; i < me.kurse().length; i++) {
      var kurs = me.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;
  }

  me.checkKurseAbsendbarAlterHauptTn = function () {
    var einstellungen = me.einstellungen;
    var alterHauptTnGueltigkeit = null;
    for (var i = 0; i < me.kurse().length; i++) {
      var kurs = me.kurse()[i];
      alterHauptTnGueltigkeit = checkAge(me.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
  };

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

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

  me.processOnGebuehrensummeEqualsZero = function (newGebuehrensumme) {
    if (newGebuehrensumme === '0,00') {
      jQuery(".hideOnGebuehrensummeEqualsZero").hide();
      jQuery("#bedit_zahlartueberid").click();
      jQuery("#tedit_zahlmethode_bankeinzug").click();
    } else {
      jQuery(".hideOnGebuehrensummeEqualsZero").fadeIn();
    }
  }

  me.gebuehrenSummeAjax.subscribe(function(newValue) {
    me.processOnGebuehrensummeEqualsZero(newValue);
  });

  me.getGutscheinPayload = function () {
    var gutschein_code = me.hauptTn().gutschein_code();
    var gutschein_nr = me.hauptTn().gutschein_nr();
    return {code: gutschein_code, nr: gutschein_nr}
  }

  me.gutscheinGueltigNachricht = function (data) {
    console.log('Der Gutschein ist gültig und wird automatisch beim Absenden der Anmeldung angewendet. ' +
        'Sie haben derzeit ein Guthaben von ' + data.BetragOffen + ' €.');
  }

  me.gutscheinNichtGueltigNachricht = function () {
    console.log('Der Gutschein ist nicht gültig. Bitte erneut versuchen.');
  }

  me.gutscheinSuccessCallback = function (data) {
    if (data.Gueltig === "True") {
      if (typeof (me.gutscheinGueltigNachricht) === "function") {
        me.gutscheinGueltigNachricht(data);
      }
      me.hauptTn().gutschein_betrag(data.BetragOffen.toLocaleString());
   
      me.refreshGebuehrenSummenAjax();
    }
    else if (data.Gueltig === "False"){
      if (typeof (me.gutscheinNichtGueltigNachricht) === "function") {
        me.gutscheinNichtGueltigNachricht();
      }
    }
  }

  me.getGutscheinGueltigkeitUndDetails = function () {
    if (typeof window.kw === "undefined") {
      window.kw = {};
    }
    jQuery.ajax({
      type: "POST",
      url: kw.wbBasePath + 'index.php?ajaxAction=getGutscheinGueltigkeitUndDetails',
      dataType: 'json',
      data: me.getGutscheinPayload(),
      success: function (pData) {
        me.gutscheinSuccessCallback(pData);
      },
      error: function (jqXHR, textStatus, errorThrown) {
        if (typeof (me.gutscheinNichtGueltigNachricht) === "function") {
          me.gutscheinNichtGueltigNachricht();
        }
        me.hauptTn().gutschein_betrag(null);
      }
    })
  }

  me.closeGutscheinAnwenden = function (resetCb = true) {
    me.hauptTn().gutschein_nr("");
    me.hauptTn().gutschein_code("");
    if (resetCb) {
      me.gutscheinCheckboxActive(false);
    }
    me.hauptTn().gutschein_betrag('');//Absicht: null wird bei der Nachricht geprüft
    me.refreshGebuehrenSummenAjax();
  }

  me.geradeEditierterKursHasKennzeichen = function (pKennzeichen) {
    var kurs = me.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
  me.geradeEditierterWeitererTn = ko.observable(new TeilnehmerPflicht());
  me.wirdGeradeEinWeitererEditiert = ko.observable(false);
  me.wirdGeradeEinWeitererMitarbeiterEditiert = ko.observable(false);
  me.geradeEditierterKurs = ko.observable(false);
  me.geradeWirdEinNeuerTeilnehmerEditiert = false;

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

  me.addWeiterenMitarbeiter = function (pKurs) {
    var newTn = new TeilnehmerPflicht();
    if (typeof (kwOnBeforeAddWeiteren) === "function") {
      kwOnBeforeAddWeiteren(pKurs, newTn, me);
    }
    me.editWeiterenMitarbeiter(pKurs, newTn);
    me.wirdGeradeEinWeitererMitarbeiterEditiert(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.
  me.addWeiterenClick = function (element, pKurs) {
    if (element.checked == true) {
      me.addWeiteren(pKurs);
    } else {
      me.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 
  me.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 (me.capitalizeWeitereTnfelder.indexOf(field) > -1){
				pTeilnehmer[field] = pTeilnehmer[field].extend({ uppercase: true });
			}
		}
    }
	
    me.geradeEditierterWeitererTn(pTeilnehmer);
    me.geradeEditierterKurs(pKurs);//muss vor me.wirdGeradeEinWeitererEditiert(true); stehen!! da in weitererTnZumAktuellenKursWirdEditiert auf den Kurs zugegriffen wird!
    me.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" + me.geradeEditierterKurs().knr.replace(/[\.\s]/g, '_')).append(curr);
    } else {
      jQuery(".wtn" + me.geradeEditierterKurs().knr.replace(/[\.\s]/g, '_') + '_' + pKurs.weitereTeilnehmer().indexOf(pTeilnehmer)).append(curr);
    }
  };

  me.editWeiterenMitarbeiter = function (pKurs, pTeilnehmer) {
    for (var field in pTeilnehmer) {
      if (pTeilnehmer.hasOwnProperty(field)) {
        if (me.capitalizeWeitereTnfelder.indexOf(field) > -1){
          pTeilnehmer[field] = pTeilnehmer[field].extend({ uppercase: true });
        }
      }
    }

    me.geradeEditierterWeitererTn(pTeilnehmer);
    me.geradeEditierterKurs(pKurs);
    me.wirdGeradeEinWeitererMitarbeiterEditiert(true);

  };

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

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

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

  me.isEmailFalschesFormat = function () {
    return (
            typeof (me.geradeEditierterWeitererTn().email()) !== "undefined"
            && me.geradeEditierterWeitererTn().email() != ''
            && !(/.*@.*\..*/.test(me.geradeEditierterWeitererTn().email()))
            );
  };
  
  me.isPostleitzahlFalschesFormat = function () {
    const magicPlzKategorie = me.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 (me.geradeEditierterWeitererTn().nurplz()) !== "undefined"
            && me.geradeEditierterWeitererTn().nurplz() != ''
            && !(pattern.test(me.geradeEditierterWeitererTn().nurplz()))
            );
  };

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

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


  me.submitWeiterenMitarbeiter = function (pTeilnehmer) {
    var weiterer = new TeilnehmerPflicht();
    weiterer.id = pTeilnehmer.id;
    weiterer.name = pTeilnehmer.name;
    weiterer.vorname = pTeilnehmer.vorname;
    weiterer.geschlecht = pTeilnehmer.geschlecht;
    weiterer.tel = pTeilnehmer.tel;
    weiterer.email = pTeilnehmer.email;
    weiterer.gebdat = pTeilnehmer.gebdat;
    weiterer.nurort = pTeilnehmer.nurort;
    weiterer.nurplz = pTeilnehmer.nurplz;
    weiterer.nurstrasse = pTeilnehmer.nurstrasse;
    weiterer.nurhausnr = pTeilnehmer.nurhausnr;
    me.geradeEditierterWeitererTn(weiterer);

    if (me.wirdGeradeEinWeitererMitarbeiterEditiert()) {
      me.geradeEditierterKurs().addWeiteren(me.geradeEditierterWeitererTn());
    }

    me.geradeEditierterWeitererTn(new TeilnehmerPflicht());
    me.refreshGebuehrenSummenAjax();
    me.refreshGebuehrenSummenAjax(me.geradeEditierterKurs());
  };

  me.schliessenMitarbeiterFenster = function () {
    me.wirdGeradeEinWeitererMitarbeiterEditiert(false);
    me.geradeEditierterKurs(false);
  };

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

  me.isKindGebdatPflicht = function () {
    return (me.kinderPflichtfelder.indexOf('gebdat') > -1);
  };
  
  me.isKindGebjahrPflicht = function() {
    return (me.kinderPflichtfelder.indexOf('gebjahr') > -1);
  };
  
  me.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;
  };

  me.checkSubmitWeiteren = function () { //Überprüfen, ob man den weiteren Teilnehmer hinzufügen darf.
    var kurs = me.geradeEditierterKurs();
    var einstellungen = me.einstellungen;
    var weiterer = me.geradeEditierterWeitererTn();
    /*//spezieller Block für Ottobrunn, nicht allgemein übernehmen!
     if( kurs.webflags == 4 && !einstellungen().nurnormaleanmeldearten && einstellungen().nurerlaubteanmeldearten && me.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 = me.getGebdat(weiterer);
    if ((gebdat == undefined || gebdat == "") && ((weiterer.istkind() && !me.isKindGebdatPflicht() && !me.isKindGebjahrPflicht())
            || (!weiterer.istkind() && !me.isWeitererGebdatPflicht() && !me.isWeitererGebjahrPflicht())
            || (me.isHauptTnFirma() && !me.isMitarbeiterGebdatPflicht()  && !me.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;
  };

  me.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 (me.sichtSettings.einrichtung == 'koelnelternschule' && ((typeof me.geradeEditierterKurs().weitereTeilnehmer == 'undefined') || (typeof me.geradeEditierterKurs().weitereTeilnehmer == 'function') && (me.geradeEditierterKurs().weitereTeilnehmer().length < 1))) {
      me.geradeEditierterKurs().beleghistorie2(false);
    } // /Elternschule
    me.geradeEditierterWeitererTn(new TeilnehmerPflicht());
    me.wirdGeradeEinWeitererEditiert(false);
    me.geradeEditierterKurs(false);
    me.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.
  me.ermaessigungsProzente = function () {
    var einstellungen = me.einstellungen;
    var prozente = 0;
    if (typeof (me.hauptTn()) != 'undefined' && typeof (me.hauptTn().erm_grund) != 'undefined' && typeof (einstellungen().ermaessigungen) != 'undefined' && typeof (einstellungen().ermaessigungen[me.hauptTn().erm_grund()]) != 'undefined' && typeof (einstellungen().ermaessigungen[me.hauptTn().erm_grund()].prozente) != 'undefined') {
      prozente = einstellungen().ermaessigungen[me.hauptTn().erm_grund()].prozente;
    }
    return prozente;
  };

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

      //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 = me.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.
  /**
   * @param zuErmKennzAry
   * @return {string}
   */
  me.gebuehrenSumme = function (zuErmKennzAry) {
    var einstellungen = me.einstellungen;
    var total = 0;
    //Alle Kurse durchlaufen und den korrekten Preis zur Gesamtsumme addieren
    ko.utils.arrayForEach(me.kurse(), function (kurs) {
      total += me.gebuehrenSummeFuerKurs(kurs, zuErmKennzAry);
    });
    if( typeof(me) != 'undefined' && typeof(me.hauptTn()) != 'undefined'
            && typeof(me.hauptTn().spendenbetrag) != 'undefined'
            && typeof(me.hauptTn().spendenbetrag()) != 'undefined'
            && typeof(me.hauptTn().spendencheck()) != 'undefined'
            && me.hauptTn().spendencheck()
            && einstellungen().ermaessigungberuecksichtigen ) {
      total += parseFloat(me.hauptTn().spendenbetrag());
    }

    if (typeof total === 'string') {
      return total;
    } else {
      return '' + total;
    }
  };
  //interessantes Schnippsel
  /*var x = ko.utils.arrayFirst(me.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.
  me.beleghistorie1Summe = function () {
    var gesamt = 0;
    for (var i = 0; i < me.kurse().length; i++) {
      var kurs = me.kurse()[i];
      if (typeof (kurs.beleghistorie1) == 'undefined' || typeof (kurs.beleghistorie1()) == 'undefined' || kurs.beleghistorie1() == '') {
        return gesamt;
      } else {
        gesamt = gesamt + parseFloat(kurs.beleghistorie1());
      }
    }
    return kw_formatAmount(gesamt);
  };

  me.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 (me.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;
  };

  me.refreshMitarbeiter4FirmaAjax = function(){
    let successCallback = function(data) {
      ko.utils.arrayForEach(data, function (element) {
        var weiterer = new TeilnehmerPflicht();
        weiterer.id(element.id);
        weiterer.name(element.name);
        weiterer.vorname(element.vorname);
        weiterer.geschlecht(element.geschlecht);
        weiterer.tel(element.tel.wert);
        weiterer.email(element.email.wert);
        weiterer.gebdat(element.gebdat);
        weiterer.nurort(element.nurort);
        weiterer.nurplz(element.nurplz);
        weiterer.nurstrasse(element.nurstrasse);
        weiterer.nurhausnr(element.nurhausnr);
        weiterer.strasse(element.strasse);
        weiterer.ort(element.ort);
        me.hauptTn().mitarbeiter.push(weiterer);
      });

    }
    me.getMitarbeiter4FirmaAjax(successCallback, me.hauptTn());
  }

  me.getMitarbeiter4FirmaAjax = function(successcallback, pFirma) {
    if (me.refreshing()) {
      return;
    }
    if (typeof window.kw === "undefined") {
      window.kw = {};
    }
    if (kw && kw.wbBasePath) {
      me.refreshing(false);
      jQuery.ajax({
        type: "POST",
        url: kw.wbBasePath + 'index.php?ajaxAction=getMitarbeiter4Firma',
        success: function( pData ){
          successcallback(pData);
          me.refreshing(false);
        },
        error: function(jqXHR, textStatus, errorThrown) {
          console.log("AJAX Error: " + textStatus + ": " + errorThrown);
          me.refreshing(false);
        }
      });
    }
  };

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

  me.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);
    me.hauptTn().gutschein_betrag(data.gutscheinBetrag);
    var tnStruktur = data.strukturTn;//leere TeilnehmerPflicht Struktur, um die Observables korrekt erzeugen zu können
    //me.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', 'gebuehrenSummeAjaxPerKurs'];
    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 (me.sichtSettings.spendenbetragInitialAktiv) {
          data.hauptTn.spendencheck = true;
        }
      }
      var hauptTnObservable = me.tnToObservable(tnStruktur, data.hauptTn, data.einstellungen);
      hauptTnObservable.arykennzeichenJS = ko.observableArray(data.hauptTn.arykennzeichenJS);
      hauptTnObservable.arybranchenJS = ko.observableArray(data.hauptTn.arybranchenJS);
      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);
      hauptTnObservable.mitarbeiter = ko.observableArray(data.hauptTn.mitarbeiter);
      me.hauptTn(hauptTnObservable);
      me.gutscheinCheckboxActive(me.hauptTn().gutschein_nr() != "" && me.hauptTn().gutschein_code() !="");
    }
    me.hauptTn().erm_grund.subscribe(function(newValue) {
      me.refreshGebuehrenSummenAjax();
      me.gebuehrenSummeAjaxRefreshFuerAlleKurse(me.kurse());
    });
    me.hauptTn().spendenbetrag.subscribe(function(newValue) {
      me.refreshGebuehrenSummenAjax();
    });
    me.hauptTn().spendencheck.subscribe(function(newValue) {
      me.refreshGebuehrenSummenAjax();
    });

    me.gutscheinCheckboxActive.subscribe(function(updated) {
      if (!updated) {
        me.closeGutscheinAnwenden(false);
      }
    });

    me.hauptTn().pers_nr.subscribe(function(newValue) {
      me.refreshGebuehrenSummenAjax();
      me.gebuehrenSummeAjaxRefreshFuerAlleKurse(me.kurse());
    });
    me.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.
        me.hauptTn().erm_grund(-1);
        me.firmaBehandlung();
      } else {
        me.menschBehandlung();
      }

      me.refreshGebuehrenSummenAjax();
      me.gebuehrenSummeAjaxRefreshFuerAlleKurse(me.kurse());
    });
    for (var i = 0; i < data.kurse.length; i++) {
      var kurs = data.kurse[i];
      var gebuehrGeparsed = kw_formatAmount(kurs.gebuehr);
      var kursOut = new Kurs(kurs.id, kurs.beginn_dat, gebuehrGeparsed, me.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 && me.einstellungen().zahlplanberuecksichtigen) {
          value = kw_formatAmount(curZahlplan.gebuehrengesamt);
        } else {
          value = kw_formatAmount(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(me.tnToObservable(tnStruktur, tn));
        }
      }
      kursOut.weitereTeilnehmer.subscribe(function(newValue) {
        me.refreshGebuehrenSummenAjax();
        for(var i=0 ;i < me.kurse().length; i++){
          me.refreshGebuehrenSummenAjax(me.kurse()[i]);
        }
      });
      kursOut.zahlplan.subscribe(function(newValue) {
        me.refreshGebuehrenSummenAjax();
        for(var j=0 ;j < me.kurse().length; j++){
          me.refreshGebuehrenSummenAjax(me.kurse()[j]);
        }
      });
      me.kurse.push(kursOut);
    }
    me.einstellungen(data.einstellungen);

    me.gebuehrenSummeAjaxRefreshFuerAlleKurse = function (pKurse){
      if (me.sichtSettings.useGebuehrPerKurs===0 && pKurse) {
        return;
      }
      for(var i=0;i < pKurse.length; i++){
        me.refreshGebuehrenSummenAjax(pKurse[i]);
      }
    };

  };

  me.refreshGebuehrenSummenAjax = function(pKurs) {
    if(me.sichtSettings.useGebSumAjaxBrutto === 1) {
      if(!pKurs){
        me.gutscheinBetragGeben(true);
      }
      else{
        me.gutscheinBetragGeben(false);
      }
      me.refreshGebuehrenSummeAjaxBrutto(pKurs);
      me.refreshing(false);
    }
    if(me.sichtSettings.useGebSumAjaxNetto === 1) {
	  me.gutscheinBetragGeben(false);
      me.refreshing(false);//damit der noch laufenden Brutto-Call den Netto-Call nicht verhindert
      me.refreshGebuehrenSummeAjaxNetto(pKurs);
    }
  };

  me.refreshGebuehrenSummeAjaxBrutto = function(pKurs) {
    let setGebuehrenSummenBrutto = function(pData) {
      if(!pKurs){
        me.gebuehrenSummeAjax(kw_formatAmount(pData.sum));
        me.gebuehrenSummeAjaxNichtErmaessigt(kw_formatAmount(pData.sumNichtErmaessigt));
        me.gebuehrenSummeAjaxRabatt(kw_formatAmount(pData.sumNichtErmaessigt - pData.sum));
        me.gebuehrenSummeAjaxImmerErmaessigt(kw_formatAmount(pData.sumImmerErmaessigt));
      }
      else{
        pKurs.gebuehrenSummeAjaxPerKurs(kw_formatAmount(pData.sum));
      }

    };
    me.refreshGebuehrenSummeAjax(setGebuehrenSummenBrutto, 1, pKurs);
  };

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

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

      var zahlplan = -1;
      if (vmKurs.zahlplan() > 0 && me.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);
    }
      var finalPayload = {
        ...payloaddata,
        ...gutscheinAnzuwendenPayloadData
      };
    if(!brutto){
      return payloaddata;
    }
    else{
        if(me.gutscheinBetragGeben()){
          return finalPayload;
        }
        else{
          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.refreshMitarbeiter4FirmaAjax();
    myViewModel.refreshGebuehrenSummenAjax();
    myViewModel.gebuehrenSummeAjaxRefreshFuerAlleKurse(myViewModel.kurse());
  }
  // 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('form').on('change', "[name='bedit_zahlart']", 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('form').on('change', "#tedit_keinebankverbindungid", 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('form').on('change', "[name='zahlmethode']", 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('form').on('change', "[name='zahlmethode']", 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");
  }
}

/**
 * Formatierung von KuferWEB Zahlen Strings in ein einheitliches Ausgabeformat
 * @param am
 * @returns {string|*}
 */
function kw_formatAmount(am) {
  return parseFloat(am).toFixed(2).replace(".", ",");
}