    /**
     * Represents a contract
     *
     * @author MW, ELO Digital Office GmbH
     * @version 1.0
     *
     * @elowf
     * @requires sol.contract.forms.Utils
     */
    sol.define("sol.contract.forms.Contract", {

      initialize: function () {
        var me = this;
        me.utils = sol.contract.forms.Utils;

        me.utils.setLocalizedKwlField("IX_MAP_CONTRACT_MIN_TERM_UNIT", "y", { onlyIfEmpty: true });
        me.utils.setLocalizedKwlField("IX_MAP_CONTRACT_DURATION_UNIT", "y", { onlyIfEmpty: true });
        me.utils.setLocalizedKwlField("IX_MAP_NOTICE_PERIOD_UNIT", "M", { onlyIfEmpty: true });
        me.utils.setLocalizedKwlField("IX_MAP_REMINDER_PERIOD_UNIT", "w", { onlyIfEmpty: true });
        me.utils.setLocalizedKwlField("IX_MAP_EXTENSION_INTERVAL_UNIT", "y", { onlyIfEmpty: true });
        me.utils.setLocalizedKwlField("IX_MAP_TERMINATION_POINT", "d", { onlyIfEmpty: true });
      },

      /**
       * Shows or hides the fixed-term fields
       * @param {Object} source Changed input field
       */
      setDurationTypeFields: function (source) {
        var me = this;

        if (!source && !$val("IX_MAP_DURATION_TYPE")) {
          $update("IX_MAP_DURATION_TYPE", "sol.contract.form.fixedTerm");
        }

        if (!source && !$val("IX_MAP_TERMINABLE")) {
          $update("IX_MAP_TERMINABLE", "sol.contract.form.notTerminable");
        }

        if (!me.utils.isFieldChangedOrFormLoaded(source, ["IX_MAP_DURATION_TYPE", "IX_MAP_SPECIAL_TERMINATION_RIGHT"])) {
          return;
        }

        if ($val("IX_MAP_DURATION_TYPE") == "sol.contract.form.noTerm") {
          sol.common.forms.Utils.showTemplate($var("LBL_CONTRACT_DATE"));
          sol.common.forms.Utils.hideTemplate($var("LBL_CONTRACT_START"));
        } else {
          sol.common.forms.Utils.hideTemplate($var("LBL_CONTRACT_DATE"));
          sol.common.forms.Utils.showTemplate($var("LBL_CONTRACT_START"));
        }

        if ($val("IX_MAP_DURATION_TYPE") == "sol.contract.form.permanent") {
          $update("IX_MAP_CONTRACT_DURATION", "");
          $update("IX_MAP_EXTENSION_INTERVAL", "");
          $update("IX_MAP_EXTENSION_FLAG", "");
          sol.common.forms.Utils.removeBodyClass("fixedterm_active");
          sol.common.forms.Utils.removeBodyClass("fixedregular_active");
          sol.common.forms.Utils.addBodyClass("permanent_active");
        } else {
          sol.common.forms.Utils.removeBodyClass("permanent_active");
          sol.common.forms.Utils.addBodyClass("fixedterm_active");
          $update("IX_MAP_NEXT_POSSIBLE_CONTRACT_END", "");
          if ($val("IX_MAP_SPECIAL_TERMINATION_RIGHT") == "1") {
            sol.common.forms.Utils.removeBodyClass("fixedregular_active");
          } else {
            sol.common.forms.Utils.addBodyClass("fixedregular_active");
            $update("IX_MAP_NEXT_POSSIBLE_CONTRACT_END", "");
          }
        }
      },

      initPaymentDataFields: function() {
        if (sol.contract.forms.Utils.fieldExists("IX_GRP_CONTRACT_SUBJECTTOVAT") && $val("IX_GRP_CONTRACT_SUBJECTTOVAT") == "") {
          $update("IX_GRP_CONTRACT_SUBJECTTOVAT", "sol.contract.form.subjectToVat.Yes");
        }

        if (sol.contract.forms.Utils.fieldExists("IX_GRP_CONTRACT_PRETAXDEDUCTION") && $val("IX_GRP_CONTRACT_PRETAXDEDUCTION") == "") {
          $update("IX_GRP_CONTRACT_PRETAXDEDUCTION", "sol.contract.form.preTaxDeduction.Yes");
        }
      },

      togglePaymentDataFields: function (source) {
        var me = this;

        if (!sol.common.forms.Utils.checkSource(source)) {
          me.initPaymentDataFields();

          // each of these fields might be undefined, but togglePaymentDataField will still work
          me.togglePaymentDataField($var("IX_GRP_CONTRACT_SUBJECTTOVAT"));
          me.togglePaymentDataField($var("IX_GRP_CONTRACT_PRETAXDEDUCTION"))
        } else {
          me.togglePaymentDataField(source);
        }
      },

      togglePaymentDataField: function (source) {
        var me = this, checkValue, toggleField;

        if (sol.common.forms.Utils.checkSource(source)) {
          if (source.name == "IX_GRP_CONTRACT_SUBJECTTOVAT" && sol.contract.forms.Utils.fieldExists("IX_MAP_CONTRACT_EXEMPTIONSTANDARD")) {
            checkValue = "sol.contract.form.subjectToVat.No";
            toggleField = "IX_MAP_CONTRACT_EXEMPTIONSTANDARD";
          } else if (source.name == "IX_GRP_CONTRACT_PRETAXDEDUCTION" && sol.contract.forms.Utils.fieldExists("IX_MAP_CONTRACT_PROPORTIONALPERCENTAGE")) {
            checkValue = "sol.contract.form.preTaxDeduction.Quotal";
            toggleField = "IX_MAP_CONTRACT_PROPORTIONALPERCENTAGE";
          }

          if (checkValue) {
            value = $val(String(source.name));

            if (value == checkValue) {
              $show("LBL_" + toggleField);
              $show(toggleField);
            } else {
              $hide("LBL_" + toggleField);
              $hide(toggleField);
            }
          }
        }
      },

      /**
       * Calculates contract data
       * @param {Object} source Changed input field
       *
       */
      calcContract: function (source) {
        var me = this,
            tplSord, updates, contractStart;

        if (!me.utils.isFieldChangedOrFormLoaded(source, ["IX_GRP_CONTRACT_STATUS", "IX_GRP_CONTRACT_START", "IX_GRP_CONTRACT_START_NOTERM", "IX_GRP_CONTRACT_END", "IX_MAP_CONTRACT_DURATION", "IX_MAP_NOTICE_PERIOD", "IX_MAP_TERMINATION_POINT", "IX_MAP_DURATION_TYPE",
          "IX_MAP_CONTRACT_MIN_TERM", "IX_MAP_REMINDER_PERIOD", "IX_MAP_REMINDER_PERIOD", "IX_MAP_SPECIAL_TERMINATION_RIGHT", "IX_MAP_EXTENSION_FLAG", "IX_MAP_EXTENSION_INTERVAL", "IX_MAP_EXTENSION_INTERVAL_UNIT"])) {
          return;
        }

        if (source && source.name) {
          if (source.name == "IX_GRP_CONTRACT_START_NOTERM") {
            contractStart = $val("IX_GRP_CONTRACT_START_NOTERM");
            $update("IX_GRP_CONTRACT_START", contractStart);
          }
        }

        tplSord = sol.common.forms.Utils.getTemplateSord();

        updates = {
          objKeys: {},
          mapKeys: {}
        };

        sol.contract.DurationUtils.calcContract(tplSord, updates);

        sol.common.forms.Utils.updateValues(updates);

        me.utils.setDstFieldWriteableIfEmpty("IX_MAP_CONTRACT_DURATION", "IX_GRP_CONTRACT_END");
        me.utils.setDstFieldWriteableIfEmpty("IX_MAP_NOTICE_PERIOD", "IX_GRP_NEXT_POSSIBLE_TERMINATION");
        me.utils.setDstFieldWriteableIfEmpty("IX_MAP_REMINDER_PERIOD", "IX_GRP_NEXT_REMINDER_DATE");
      },

      /**
       * Calculates the payment plan fields
       * @param {Object} source Changed input field
       */
      calcPaymentPlan: function (source) {
        var me = this,
            cashFlowSum;

        if (!me.utils.isFieldChangedOrFormLoaded(source, ["IX_GRP_CONTRACT_START", "IX_GRP_CONTRACT_END", "IX_MAP_NEXT_POSSIBLE_CONTRACT_END", "IX_MAP_CONTRACT_CASHFLOW_SINGLE", "IX_MAP_CONTRACT_CASHFLOW_DATE", "IX_MAP_CONTRACT_CASHFLOW_TO", "IX_MAP_CONTRACT_CASHFLOW_RECURRING_UNIT"])) {
          return;
        }
        me.utils.forEachRow("IX_MAP_CONTRACT_CASHFLOW_DESC", function (i) {
          var singleAmount, startDateIso, endDateIso, unit,
              rowTotal = "";

          singleAmount = sol.common.forms.Utils.toDecimal("IX_MAP_CONTRACT_CASHFLOW_SINGLE" + i);
          startDateIso = sol.common.forms.Utils.getIsoDate("IX_MAP_CONTRACT_CASHFLOW_DATE" + i) || sol.common.forms.Utils.getIsoDate("IX_GRP_CONTRACT_START");
          endDateIso = sol.common.forms.Utils.getIsoDate("IX_MAP_CONTRACT_CASHFLOW_TO" + i) || sol.common.forms.Utils.getIsoDate("IX_GRP_CONTRACT_END") || sol.common.forms.Utils.getIsoDate("IX_MAP_NEXT_POSSIBLE_CONTRACT_END") || sol.common.DateUtils.nowIso();
          unit = $val("IX_MAP_CONTRACT_CASHFLOW_RECURRING_UNIT" + i);
          if (!unit) {
            me.utils.setLocalizedKwlField("IX_MAP_CONTRACT_CASHFLOW_RECURRING_UNIT" + i, "O", { onlyIfEmpty: true });
            unit = "O";
          }
          rowTotal = sol.contract.DurationUtils.calcRowTotal(startDateIso, endDateIso, singleAmount, unit);
          sol.common.forms.Utils.updateDecimal("IX_MAP_CONTRACT_CASHFLOW_AMOUNT" + i, rowTotal);
        }, me);

        cashFlowSum = sol.common.forms.Utils.sumItems("IX_MAP_CONTRACT_CASHFLOW_AMOUNT");

        sol.common.forms.Utils.updateDecimal("IX_GRP_CONTRACT_CASHFLOW_SUM", cashFlowSum, { callInputChanged: true });
      },

      /**
       * Calculates the amounts
       * @param {Object} source Changed input field
       */
      calcAmounts: function (source) {
        var me = this;
        if (!me.utils.isFieldChangedOrFormLoaded(source, ["IX_GRP_CONTRACT_CASHFLOW_SUM", "IX_MAP_CONTRACT_FX_RATE"])) {
          return;
        }
        me.utils.calcLocalCurrencyAmount("IX_GRP_CONTRACT_CASHFLOW_SUM", "IX_MAP_CONTRACT_FX_RATE", {
          currencyCodeFieldName: "IX_GRP_CONTRACT_CURRENCY_CODE",
          baseCurrencyCodeFieldName: "IX_MAP_CONTRACT_BASE_CURRENCY_CODE",
          dependentElementNames: ["LBL_CONTRACT_CASHFLOW_SUM_LOCAL_CURR","IX_GRP_CONTRACT_CASHFLOW_SUM_LOCAL_CURR","IX_MAP_CONTRACT_FX_RATE", "LBL_CONTRACT_FX_RATE", "IX_MAP_CONTRACT_BASE_CURRENCY_CODE","LBL_CONTRACT_BASE_CURRENCY_CODE"],
          baseCurrencyCode: me.config.baseCurrencyCode
        });
      },

      /**
       * Validates wether the partner name or the last name is set
       * @return {String}
       */
      validateName: function () {
        var message;
        if (!$val("IX_GRP_PARTNER_NAME") && !$val("IX_GRP_CONTACT_LASTNAME")) {
          message = $val("IX_TRANS_PARTNERNAME_OR_LASTNAME");
          return message;
        }
      }
    });