<%@ language = "JavaScript" %>
<% /*
     $Revision$
     $Id$

     File:              api_mld_soap.asp
     Description:       API voor mld-soap berichten
                        Interpreteert melding-bericht zodanig dat een melding  wordt
                        aangemaakt.

     Parameters:        Een xml
     Status:
     Context:
     Notes:
*/
    DOCTYPE_Disable = 1;
    THIS_FILE = "appl/api/api_mldsoap.asp";
%>
<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../Shared/kenmerk_common.inc" -->
<!-- #include file="../Shared/xml_converter.inc" -->
<!-- #include file="../Shared/save2db.inc" -->
<!-- #include file="../api/api.inc" -->
<!-- #include file="../mld/mld.inc" -->
<%
// We sturen het antwoord in UTF-8.
Session.Codepage = 65001;
Response.Charset = 'utf-8';

var API = new API_func();
var tsql = "-";        // Voor tijdelijke statement(s)
var sql = "-";         // De uiteindelijke insert/update-sql
var resultcode = -1;   /* Zolang deze -1 is, is het nog goed. Uiteindelijk eindigt het met 0 (als goed). */
var resulttekst = "";

var xmlReq = styledRequestXML(API);

var xmlResp = new ActiveXObject("MSXML2.DOMDocument.6.0");
xmlResp.appendChild(xmlResp.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\""))

// The response.
var FCLTElement = xmlResp.createElement("facilitor");
// The response header.
var now = new Date();
var nowtxt = now.getFullYear()+'-'+padout(now.getMonth()+1) +'-'+padout(now.getDate()) +' '
                       +padout(now.getHours()) +':'+padout(now.getMinutes())+':'+padout(now.getSeconds());
var elmHeader = xmlResp.createElement("header");
var headerinfo = {
//                  file: String(Request.ServerVariables("SCRIPT_NAME")).toLowerCase(),
                  datum: nowtxt,
                  naam: user.naam(),
                  custId: customerId,
                  language: user.lang()
                 }
for (param in headerinfo)
{
    var FCLTdata = xmlResp.createElement(param);
    FCLTdata.appendChild(xmlResp.createTextNode(headerinfo[param]));
    elmHeader.appendChild(FCLTdata);
}
FCLTElement.appendChild(elmHeader);

// Hier zou het echte werk moeten gebeuren nav. xmlReq
// en FCLTElement moeten we uitbreiden met antwoorden.
var detected ="?";
//xmlReq.setProperty("SelectionLanguage", "XPath");   // Weet niet of noodzakelijk

// Dit is de meldingenloop (mochten er ooit nog anderen gaan volgen).
var meldingen = xmlReq.getElementsByTagName("melding");
for (i = 0; i < meldingen.length; i++)
{
  resultcode = -1;
  resulttekst = "";
  // Lees per node de (optionele) tags en waarden.
  var fields = []; // Bij te werken velden.
  var ext_id        = meldingen[i].getAttribute("key");
  var meldaction    = meldingen[i].getAttribute("type").toLowerCase();
  var melddatum     = XMLval(meldingen[i], "datum");
  var einddatum     = XMLval(meldingen[i], "einddatum");
  //var melderemail   = XMLval(meldingen[i], "melder");                   // Unsupported yet
  var stdmld_key    = parseInt(XMLval(meldingen[i], "stdmelding"), 10); // Numeriek
  var stdmld_sla    = -1;   // Normale uitvoertijd (prio door melder nog unsupported)
  //var meldprio      = XMLval(meldingen[i], "prioriteit");               // Unsupported yet
  //var meldobj_id    = XMLval(meldingen[i], "object");                   // Unsupported yet
  var voor_email    = XMLval(meldingen[i], "voor_email"); // NEW
  var voor_login    = XMLval(meldingen[i], "voor_login"); // NEW
  var meldloc       = XMLval(meldingen[i], "locatiecode");
  var meldgeb       = XMLval(meldingen[i], "gebouwcode");
  var meldver       = XMLval(meldingen[i], "verdiepingcode");
  var meldrnr       = XMLval(meldingen[i], "ruimtecode");
  var locatie_key   = -1;   // Bepaald op basis van meldloc
  var plaats_key    = -1;   // Bepaald op basis van meldgeb/meldver/meldrnr
  var meld_kpn      = XMLval(meldingen[i], "kostenplaats");
  var meld_afd      = XMLval(meldingen[i], "afdeling");
  var meld_oms      = XMLval(meldingen[i], "omschrijving");
  var meld_opm      = XMLval(meldingen[i], "opmerking");
  var meld_onderwerp= XMLval(meldingen[i], "onderwerp");

  //var mldkenmerken  = (meldingen[i].getElementsByTagName("kenmerk"))[0].childNodes[0].nodeValue; // Unsupported yet
  var mldkenmerken  = meldingen[i].getElementsByTagName("kenmerk");
  var mld_key       = -1;   // Bepaald na insert

  user.checkAutorisation("WEB_MLDUSE"); // Dit is nog ongeacht de melding

  if (meldaction == "unknown")
  {
     // Kijk of er een melding bestaat met dit externe nummer.
     // Ben je bang dat het nummer vaker voorkomt dan kun je deze prefixen in de xsl
     tsql = "SELECT MIN(mld_melding_key) mld_melding_key, COUNT(*) aantal"
            + "  FROM mld_melding"
            + " WHERE mld_melding_externnr ="+ safe.quoted_sql(ext_id);
     var oRs = Oracle.Execute(tsql);
     if (oRs("aantal").Value == 1)
     {
        mld_key = oRs("mld_melding_key").Value;
        meldaction = "update";
     }
     else
     {
        meldaction = "insert";
     }
  }
  else if (meldaction == "update")
  {
     // Kijk of er een melding bestaat met dit externe nummer.
     // Ben je bang dat het nummer vaker voorkomt dan kun je deze prefixen in de xsl
     tsql = "SELECT MIN(mld_melding_key) mld_melding_key, COUNT(*) aantal"
            + "  FROM mld_melding"
            + " WHERE mld_melding_externnr ="+ safe.quoted_sql(ext_id);
     var oRs = Oracle.Execute(tsql);
     if (oRs("aantal").Value == 1)
     {
        mld_key = oRs("mld_melding_key").Value;
     }
  }

  if (ext_id == null)
  {
    resultcode = 1;
    resulttekst = "Undefined external ID (key)";
  }
  else if (meldaction != "insert" && meldaction != "update")
  {
    resultcode = 2;
    resulttekst = "Undefined operation (type)";
  }
  else
  {
    // voor zowel insert als update:

    var voor_key = -1;
    var perslid_key = -1;
    if (voor_login != null)
    {
      // Zoek de voorkey op aan de hand van het emailadres
      tsql = "SELECT prs_perslid_key "
           + "  FROM prs_v_aanwezigperslid "
           + " WHERE prs_perslid_oslogin = UPPER(" + safe.quoted_sql(voor_login) + ")";
      var oRs = Oracle.Execute(tsql);
      if (!oRs.eof)
      {
         voor_key = oRs("prs_perslid_key").Value;
      }
    }
    if (voor_email != null && voor_key == -1)
    {
      // Zoek de voorkey op aan de hand van het emailadres
      tsql = "SELECT prs_perslid_key "
           + "  FROM prs_v_aanwezigperslid "
           + " WHERE UPPER(prs_perslid_email) = UPPER(" + safe.quoted_sql(voor_email) + ")";
      var oRs = Oracle.Execute(tsql);
      if (!oRs.eof)
      {
         voor_key = oRs("prs_perslid_key").Value;
      }
    }
    if (voor_key == -1)
    {
      voor_key = user_key;
      perslid_key = user_key;
    }
    else
    {
       if (S("mld_allow_for_others") == 1)
       {
          perslid_key = user_key;
       }
       else
       {
          perslid_key = voor_key;
       }
    }
    // einde gezamelijke data (insert && update)
    if (meldaction == "update")
    {
      if (mld_key == -1)
      {
          resultcode = 4;
          resulttekst = "Undefined melding_key";
      }
      else
      {
        if (einddatum != null)
        {
          var mld_datum;
          tsql = "SELECT mld_melding_datum"
               + "     , mld_stdmelding_key"
               + "  FROM mld_melding"
               + " WHERE mld_melding_key = " + mld_key;
          oRs = Oracle.Execute(tsql);
          if (!oRs.EOF)
          {
            mld_datum = oRs("mld_melding_datum").Value;
            stdmld_key = oRs("mld_stdmelding_key").Value; // overwrite de xml-node
          }
          oRs.Close();

          try
          {
            var meldeinddate = XMLtoJsDate(einddatum);
            if (meldeinddate > mld_datum)
            {
              fields.push({ dbs: "mld_melding_einddatum", typ: "datetime", val: meldeinddate, track: L("lcl_mld_enddate") });
            }
            else
            {
              // Ontvangen XML-einddatum voor begindatum, dan later volgens SLA zetten!
              __DoLog("Ontvangen XML-einddatum voor begindatum: "+ einddatum, "#00FF00");
            }
          }
          catch (e)
          {
            // Verkeerde datum-formaat, dan later volgens SLA zetten!
            __DoLog("Formaat ontvangen XML-einddatum incorrect: "+ einddatum, "#00FF00");
          }
        }

        if (meld_kpn && meld_kpn != "")
        {
          var kpn_key = getKpn(meld_kpn);
          if (kpn_key != -1)
            fields.push({ dbs: "prs_kostenplaats_key", typ: "key", val: kpn_key, track: L("lcl_mld_inf_Kostenplaats"), foreign: "prs_kostenplaats"});
        }

        if (meld_afd && meld_afd != "")
        {
          var afd_key = getAfd(meld_afd);
          if (afd_key != -1)
            fields.push({ dbs: "prs_afdeling_key", typ: "key", val: afd_key, track: L("lcl_mld_afdeling"), foreign: "prs_afdeling"});
        }

        if (meld_opm)
          fields.push({ dbs: "mld_melding_opmerking",     typ: "varchar",   val: meld_opm,       track: L("lcl_mld_inf_Opmerking"),     len: 4000 });

        if (meld_onderwerp)
          fields.push({ dbs: "mld_melding_onderwerp",     typ: "varchar",   val: meld_onderwerp, track: L("lcl_mld_inf_Onderwerp"),     len: 200 });

        if (meld_oms)
          fields.push({ dbs: "mld_melding_omschrijving",  typ: "varchar",   val: meld_oms,       track: L("lcl_mld_inf_Omschrijving"),  len: 4000 });

        if (fields.length>0)
        {
            var mldUpd = buildTrackingUpdate("mld_melding", "mld_melding_key = " + mld_key, fields, { noValidateToken: true });
            Oracle.Execute(mldUpd.sql);
            mld.trackmeldingupdate(mld_key, L("lcl_mld_is_updatedbysoap").format(mld_key) + "\n" + mldUpd.trackarray.join("\n"));
        }

        // De kenmerken.
        upsertKenmerk(mldkenmerken, stdmld_key, mld_key);
      }
      resultcode = 0; // Ik heb gedaan wat ik moest en mocht doen voor deze melding.
    } // einde update
    else if (meldaction == "insert")
    {
      if (!validStdmld(stdmld_key))
      {
        resultcode = 3;
        resulttekst = "Undefined stdmelding";
      }
      else
      { // vanaf hier heb ik een geldige stdmld_key

        var stdm_info = mld.mld_stdmeldinginfo(stdmld_key);

        var stdmld_sla_tijdsduur = stdm_info.prioriteiten[3].uitvoertijd;
        var stdmld_sla_eenheid = stdm_info.prioriteiten[3].eenheid;
        var stdmld_niveau = stdm_info.alg_onrgoed_niveau; // required niveau
        var alglevel_ok = !stdm_info.ins_srtdiscipline_alg || !stdmld_niveau; // Zonder niveau altijd goed

        fields.push({ dbs: "mld_stdmelding_key", typ: "key", val: stdmld_key });
        fields.push({ dbs: "mld_melding_t_uitvoertijd.tijdsduur", typ: "number",  val: stdmld_sla_tijdsduur, obj: "MLD_T_UITVOERTIJD" });
        fields.push({ dbs: "mld_melding_t_uitvoertijd.eenheid",   typ: "varchar", val: stdmld_sla_eenheid,   obj: "MLD_T_UITVOERTIJD" });
        if (melddatum != null)
        {
          try
          {
            var meldaanmaakdate = XMLtoJsDate(melddatum);
            fields.push({ dbs: "mld_melding_datum", typ: "datetime", val: meldaanmaakdate });
          }
          catch (e)
          { // Verkeerde datum-formaat, volgens spec. dan now gebruiken!
            __DoLog("Formaat ontvangen XML-datum incorrect: "+ melddatum, "#00FF00");
            meldaanmaakdate = now;
            fields.push({ dbs: "mld_melding_datum", typ: "datetime", val: meldaanmaakdate });
          }
        }
        else
        {
          fields.push({ dbs: "mld_melding_datum", typ: "datetime", val: now });
        }
        // De einddatum is de meegegeven einddatum, maar als die niet wordt meegegeven is het
        // gewoon enddate_std en dat regelt de trigger wel, dus DAN MOET IK HEM NIET MEEGEVEN
        if (einddatum != null)
        {
          try
          {
            var meldeinddate = XMLtoJsDate(einddatum);
            if (meldeinddate > meldaanmaakdate)
            {
              fields.push({ dbs: "mld_melding_einddatum", typ: "datetime", val: meldeinddate });
            }
            else
            {
              // Ontvangen XML-einddatum voor begindatum, dan later volgens SLA zetten!
              __DoLog("Ontvangen XML-einddatum voor begindatum: "+ einddatum, "#00FF00");
            }
          }
          catch (e)
          {
            // Verkeerde datum-formaat, dan later volgens SLA zetten!
            __DoLog("Formaat ontvangen XML-einddatum incorrect: "+ einddatum, "#00FF00");
          }
        }

        tsql = "SELECT alg_locatie_key  "
             + "  FROM alg_v_aanweziglocatie"
             + " WHERE alg_locatie_code="+ safe.quoted_sql(meldloc);
        var oRs_L = Oracle.Execute(tsql);
        if (!oRs_L.eof)
        {
          alglevel_ok = alglevel_ok || stdmld_niveau == "L";
          locatie_key = oRs_L("alg_locatie_key").Value;
          fields.push({ dbs: "mld_alg_locatie_key", typ: "key", val: locatie_key });

          tsql = "SELECT alg_gebouw_key  "
               + "  FROM alg_v_aanweziggebouw"
               + " WHERE alg_locatie_key ="+ locatie_key
               + "   AND alg_gebouw_code="+ safe.quoted_sql(meldgeb);
          var oRs_G = Oracle.Execute(tsql);
          if (!oRs_G.eof)
          {
            alglevel_ok = alglevel_ok || stdmld_niveau == "G";
            plaats_key = oRs_G("alg_gebouw_key").Value;

            tsql = "SELECT alg_verdieping_key  "
                 + "  FROM alg_v_aanwezigverdieping"
                 + " WHERE alg_gebouw_key ="+ plaats_key
                 + "   AND alg_verdieping_code="+ safe.quoted_sql(meldver);
            var oRs_V = Oracle.Execute(tsql);
            if (!oRs_V.eof)
            {
              alglevel_ok = alglevel_ok || stdmld_niveau == "V";
              plaats_key = oRs_V("alg_verdieping_key").Value;

              tsql = "SELECT alg_ruimte_key  "
                   + "  FROM alg_v_aanwezigruimte"
                   + " WHERE alg_verdieping_key ="+ plaats_key
                   + "   AND alg_ruimte_nr="+ safe.quoted_sql(meldrnr);
              var oRs_R = Oracle.Execute(tsql);
              if (!oRs_R.eof) {
                  alglevel_ok = alglevel_ok || stdmld_niveau == "R";
                  plaats_key = oRs_R("alg_ruimte_key").Value;
              }
              oRs_R.Close();
            }
            oRs_V.Close();
          }
          oRs_G.Close();

          if (plaats_key != -1)
          {
            fields.push({ dbs: "mld_alg_onroerendgoed_keys", typ: "key", val: plaats_key });
          }
        }
        oRs_L.Close();

        if (!alglevel_ok)
        {
          resultcode = 5;
          resulttekst = "Location not found";
          __DoLog(resulttekst, "#00FF00");
        }

        if (resultcode == -1)
        { // nog steeds geen fouten
          var sql = "SELECT isd.ins_srtdiscipline_kostenklant"
                  + "     , id.ins_discipline_kpnverplicht"
                  + "  FROM mld_stdmelding msm"
                  + "     , ins_tab_discipline id"
                  + "     , ins_srtdiscipline isd"
                  + " WHERE msm.mld_ins_discipline_key = id.ins_discipline_key"
                  + "   AND id.ins_srtdiscipline_key = isd.ins_srtdiscipline_key"
                  + "   AND msm.mld_stdmelding_key = " + stdmld_key;
          var oRs = Oracle.Execute(sql);
          // Er is altijd een srtdiscipline gekoppeld aan de melding.
          var ins_srtdisc_kk = oRs("ins_srtdiscipline_kostenklant").Value;
          var kpnverplicht = oRs("ins_discipline_kpnverplicht").Value > 0;
          oRs.Close();

          // Met "WEB_MLDUSE" autorisatie check maak ik deze melding aan. Dan kijk ik hier ook naar de FE setting "FE Defaultwaarde kosten klant aan".
          var ins_srtdiscipline_kk = (ins_srtdisc_kk & 1) == 1;

          var kpn_key = user.prs_kostenplaats_key() || -1;
          if ((kpn_key == -1) || (meld_kpn && meld_kpn != ""))
          {
            var tempKpn = getKpn(meld_kpn);
            kpn_key = (tempKpn != -1 ? tempKpn : stdm_info.kp_key);
          }

          if (kpnverplicht && kpn_key < 0)
          {
            resultcode = 6;
            resulttekst = "Cost centre not found while mandatory";
          }
        }

        if (resultcode == -1)
        {
           var afd_key = -1;
           if (meld_afd && meld_afd != "")
           {
             afd_key = getAfd(meld_afd);
           }
        }

        if (resultcode == -1)
        { // nog steeds geen fouten
          // We weten wat te inserten, nu nog uitvoeren; rechten voldoende afgedekt via MLDUSE-check hierboven?
          fields = fields.concat(
                          [ { dbs: "mld_melding_key",            typ: "key",     seq: "mld_s_mld_melding_key" },
                            { dbs: "mld_melding_module",         typ: "varchar", val: "MLD" },
                            { dbs: "mld_meldbron_key",           typ: "key",     val: 6 }, // system
                            { dbs: "mld_melding_omschrijving",   typ: "varchar", val: meld_oms, len: 4000 },
                            { dbs: "mld_melding_onderwerp",      typ: "varchar", val: meld_onderwerp, len: 200 },
                            { dbs: "prs_kostenplaats_key",       typ: "key",     val: kpn_key },
                            { dbs: "prs_afdeling_key",           typ: "key",     val: afd_key },
                            { dbs: "mld_kosten_klant",           typ: "number",  val: kpn_key > 0 && ins_srtdiscipline_kk? 1 : null },
                            { dbs: "prs_perslid_key",            typ: "key",     val: perslid_key },
                            { dbs: "prs_perslid_key_voor",       typ: "key",     val: voor_key },
                            { dbs: "mld_melding_spoed",          typ: "key",     val: 3 }, // default (frontend) = 3
                            { dbs: "mld_melding_externnr",       typ: "varchar", val: ext_id, len: 1000 }
                          ]);

          var mldIns = buildInsert("mld_melding", fields, { noValidateToken: true });
          mld_key = mldIns.sequences["mld_melding_key"];

          sql = mldIns.sql;
          oRs = Oracle.Execute(sql);

          // Zetten van de status op ingevoerd en afhandelen van de tracking.
          mld.setmeldingstatus(mld_key, 2); // Zorgt ook voor tracking & daarmee notificatie.

          // Eventuele (gewijzigde) objecten zijn nu ook opgeslagen. Nu kan de definitieve mld_melding.mld_melding_einddatum_std bepaald en gezet worden.
          //mld.updatestdeinddatum(mld_key); // Unsupported yet. So update of mld_melding_einddatum_std not needed yet.

          // De kenmerken.
          upsertKenmerk(mldkenmerken, stdmld_key, mld_key);

          resultcode = 0; // Ik heb gedaan wat ik moest en mocht doen voor deze melding.

          // Handle workflow actions for new call:
          // Let wel: alleen initiele stap ondersteund, niet latere vervolgstappen bij statuswijzigingen!
          mld.nextworkflowstep(mld_key, -1);  // -1 = initial (the originating call)

          // Klantspecifieke check functie (hookfunction) voor de invoer
          var pResult = new HookResult();
          if (!custfunc.mld_postsave(mld_key, pResult))
          {
             __DoLog(pResult.errmsg, "#00FF00");
          }
          // De hookfunctie kan de stdmelding aanpassen.
          if (pResult.stdmld_key)
          {
             // check de paden van de flexfiles als de stdmeldingkey aangepast is
             mld.keepFlexDocuments(mld_key, stdmld_key, pResult.stdmld_key);
          }
        }
      } // end geldige stdmld_key
    } // end insert
  } // end geldige ext_id

  if (resultcode > 0)
    __DoLog("api_mldsoap fail.\nResultcode: {0}\nReturntekst: {1}".format(resultcode, resulttekst), "#00FF00");

  var binfo = {returncode: resultcode,
               returntekst: resulttekst,
               // executed:sql,   // debug
               datum: nowtxt,
               meldingnr: mld_key
              }

  var FCLTBody = xmlResp.createElement("melding");   // type=response
  FCLTBody.setAttribute('key', ext_id); // Let op: key van de aanroeper!
  FCLTBody.setAttribute('type', 'response');
  for (param in binfo)
  {
    var FCLTdata = xmlResp.createElement(param);
    FCLTdata.appendChild(xmlResp.createTextNode(binfo[param]));
    FCLTBody.appendChild(FCLTdata);
  }

  FCLTElement.appendChild(FCLTBody);
} // end for
// Alle melding-nodes zijn behandeld.


function validStdmld(stdmld_key)
{
  var tsql = "SELECT COUNT(*) aantal"
           + "  FROM mld_stdmelding sm"
           + " WHERE sm.mld_stdmelding_key = " + (stdmld_key || -1)
           + "   AND sm.mld_stdmelding_verwijder IS NULL";
  var oRs = Oracle.Execute(tsql);
  var geldig = (oRs("aantal").Value == 1);
  oRs.Close();
  return geldig;
}

function getKpn(meld_kpn)
{
  var kpn_key = -1;
  if (!meld_kpn)
  {
    var temp_sql = "SELECT ''"
                 + "  FROM prs_perslidkostenplaats pkp"
                 + " WHERE pkp.prs_perslidkostenplaats_boeken = 1"
                 + "   AND (pkp.prs_kostenplaats_key = kp.prs_kostenplaats_key"
                 + "         OR pkp.prs_kostenplaats_key IS NULL)"       // Mandated for all
                 + "   AND pkp.prs_perslid_key = " + perslid_key;

    temp_sql = "SELECT kp.prs_kostenplaats_key"
             + "  FROM prs_kostenplaats kp"
             + " WHERE kp.prs_kostenplaats_verwijder IS NULL"
             + "   AND (kp.prs_kostenplaats_begin IS NULL"
             + "         OR kp.prs_kostenplaats_begin < SYSDATE)"
             + "   AND (kp.prs_kostenplaats_eind IS NULL"
             + "         OR kp.prs_kostenplaats_eind > SYSDATE)"
             + "   AND EXISTS ("
             + temp_sql
             + "   )"
             + "   AND kp.prs_kostenplaats_upper = " + safe.quoted_sql_upper(meld_kpn); // Unique

    var oRs = Oracle.Execute(temp_sql);
    if (!oRs.eof)
    {
      kpn_key = oRs("prs_kostenplaats_key").Value;
    }
    oRs.Close();
  }

  return kpn_key;
}

function getAfd(meld_afd)
{
  if (!meld_afd)
    return -1;

  var temp_sql = "SELECT prs_afdeling_key"
               + "  FROM prs_afdeling a"
               + " WHERE a.prs_afdeling_verwijder IS NULL"
               + "   AND a.prs_afdeling_upper = " + safe.quoted_sql_upper(meld_afd);

  var oRs = Oracle.Execute(temp_sql);
  if (!oRs.EoF)
    return oRs("prs_afdeling_key").Value;
  oRs.Close();
  return -1;
}

function upsertKenmerk(kenmerken, stdmld_key, mld_key)
{
  for (j=0; j < kenmerken.length; j++)
  {
    var kenmerk_attr_key = parseInt(kenmerken[j].getAttribute("key"), 10);
    var kenmerk_attr_code = kenmerken[j].getAttribute("code");
    var kenmerk_naam = kenmerken[j].getAttribute("naam");
    // default srtkenmerk on name
    var srtkenmerk_key_code_omschr = "   AND sk.mld_srtkenmerk_upper = " + safe.quoted_sql_upper(kenmerk_naam);
    if (kenmerk_attr_key > 0)
      srtkenmerk_key_code_omschr = "   AND sk.mld_srtkenmerk_key = " + kenmerk_attr_key;
    else if (kenmerk_attr_code)
      srtkenmerk_key_code_omschr = "   AND  UPPER(sk.mld_srtkenmerk_code) = " + safe.quoted_sql_upper(kenmerk_attr_code);
    if (kenmerken[j].childNodes.length > 0)
      var kenmerk_waarde = kenmerken[j].childNodes[0].nodeValue;
    else
      var kenmerk_waarde = "";

    // Zoek het kenmerk op naam terug
    ksql = "SELECT k.mld_kenmerk_key, sk.mld_srtkenmerk_kenmerktype, sk.mld_srtkenmerk_lengte, sk.fac_kenmerkdomein_key  "
         + "  FROM mld_kenmerk k"
         + "     , mld_srtkenmerk sk"
         + "     , mld_stdmelding s"
         + "     , mld_discipline d"
         + " WHERE s.mld_ins_discipline_key = d.ins_discipline_key"
         + "   AND k.mld_srtkenmerk_key = sk.mld_srtkenmerk_key "
         + "   AND k.mld_kenmerk_verwijder IS NULL "
         + srtkenmerk_key_code_omschr
         + "   AND s.mld_ins_discipline_key = d.ins_discipline_key"
         + "   AND s.mld_stdmelding_key = " + stdmld_key
         + "   AND ((k.mld_stdmelding_key IS NULL                    AND k.mld_kenmerk_niveau = 'A')"
         + "     OR (k.mld_stdmelding_key = s.mld_stdmelding_key     AND k.mld_kenmerk_niveau = 'S')"
         + "     OR (k.mld_stdmelding_key = s.mld_ins_discipline_key AND k.mld_kenmerk_niveau = 'D')"
         + "     OR (k.mld_stdmelding_key = d.ins_srtdiscipline_key  AND k.mld_kenmerk_niveau = 'T'))";

    var oRs = Oracle.Execute(ksql);

    if (!oRs.eof)
    {
      var kenmerk_key = oRs("mld_kenmerk_key").Value;
      var kenmerk_type = oRs("mld_srtkenmerk_kenmerktype").Value;
      var kenmerkdomein_key = oRs("fac_kenmerkdomein_key").Value;
      // var kenmerk_lengte = oRs("mld_srtkenmerk_lengte").Value; // unsupported yet?

      var temp_sql = "SELECT km.mld_kenmerkmelding_key "
                   + "  FROM mld_kenmerkmelding km "
                   + " WHERE km.mld_melding_key =  " + mld_key
                   + "   AND km.mld_kenmerk_key = " + kenmerk_key;
      var oRs = Oracle.Execute(temp_sql);

      switch (kenmerk_type)
      {
        case 'R':
        case 'S':
        {
          // read reference fields
          if (kenmerk_waarde != "") {
            var kenmerk_ref = kenmerken[j].getAttribute("ref");
            if (kenmerk_ref) {
              kenmerk_waarde = getKenmerkKeyByRef(kenmerkdomein_key, kenmerk_ref, kenmerk_waarde);
            }
          }
        }
        case 'C':
        case 'X':
        case 'N':
        case 'V':
        {
          // we ondersteunen alleen nog maar karakter velden.
          if (!oRs.eof)
          {
            var kenmerkmelding_key = oRs("mld_kenmerkmelding_key").Value;
            if (kenmerk_waarde == "") {
              // delete characteristic when empty
              ksql = "DELETE FROM mld_kenmerkmelding WHERE mld_kenmerkmelding_key = " + kenmerkmelding_key;
            } else {
              ksql = "UPDATE mld_kenmerkmelding"
                   + "   SET mld_kenmerkmelding_waarde = " + safe.quoted_sql(kenmerk_waarde)
                   + " WHERE mld_kenmerkmelding_key = " + kenmerkmelding_key;
            }
            Oracle.Execute(ksql);
          }
          else
          {
            if (kenmerk_waarde != "") {
              // write a new characteristic with a value only
              ksql = "INSERT INTO mld_kenmerkmelding (mld_kenmerk_key, mld_melding_key, mld_kenmerkmelding_waarde) "
                   + "VALUES (" + kenmerk_key + ", " + mld_key + ", " + safe.quoted_sql(kenmerk_waarde) + ")";
              Oracle.Execute(ksql);
            }
          }
          break;
        }
        case "M": // Folder met bijlagen
        {
          //Response.Write(kenmerk_naam);
          var bijlagen = kenmerken[j].getElementsByTagName("bijlage");
          var bi;
          for (bi = 0; bi < bijlagen.length; bi++)
          {
            var Attachment = XMLval(bijlagen[bi], "attachment");
            var Name = XMLval(bijlagen[bi], "name");
            var Size = XMLval(bijlagen[bi], "size");
            var Encoding = XMLval(bijlagen[bi], "encoding", true);
            //Response.Write("Name: " + Name + " size: " + Size);
            if (Attachment && Name && Size)
            {
              var SafeName = safe.filename(Name);
              var params = flexProps("MLD", mld_key, String(kenmerk_key), "M");
              if (!params.isAllowedName(SafeName))
              {
                __DoLog("Unsafe SOAP file '{0}' ignored.".format(SafeName), "#FFFF00");
              }
              else
              {
                __Log("Start saving: " + params.AttachPath + SafeName);
                CreateFullPath(params.AttachPath);
                if (Encoding == 'base64')
                {
                   encodedString2File(params.AttachPath + SafeName, Attachment, "bin.base64");
                }
                else
                {
                   encodedString2File(params.AttachPath + SafeName, Attachment, "bin.hex");
                }

                var oCrypto = new ActiveXObject("SLNKDWF.Crypto");
                var sql = "BEGIN "
                        + "  flx.setflexbijlage"
                                + "(" + safe.quoted_sql("MLD")    // MLD | RES | ....
                                + ", " + kenmerk_key
                                + ", " + mld_key
                                + ", " + safe.quoted_sql(params.AttachSubPath)
                                + ", " + "NULL" // diskfilename
                                + ", " + safe.quoted_sql(SafeName)
                                + ", " + fso.GetFile(params.AttachPath + SafeName).Size
                                + ", " + "SYSDATE"
                                + ", " + safe.quoted_sql(oCrypto.hex_sha1_file(params.AttachPath + SafeName))
                                + ");"
                        + " END;";
                Oracle.Execute(sql);

                __Log("Done saving: " + params.AttachPath + SafeName);
              }
            }
          }
        }
      }
      oRs.Close();
    }
  }
}

xmlResp.appendChild(FCLTElement);

if (API.apidata.errorhandling == 1 && user.errorhandling() == 1)
{
  if (resultcode > 0) // -1 en 0 zijn 'goed'
  {
    Response.Status = '400 Bad Request';
  }
}

Response.ContentType = "text/xml";
if (API.apidata.stylesheet)
{
  // Niet super efficient dat we eerst naar tekstuele xml gaan maar ach...
  STR2Stream(xmlResp.xml, API.apidata.stylesheet, Response, {});
}
else
{
  Response.Write(xmlResp.xml)
}
%>
<% ASPPAGE_END(); %>
