<%@ LANGUAGE = JavaScript %>
<% /*
     $Revision$
     $Id$

    File:               mld_edit_melding_save.asp
    Description:        Sla de wijzigingen van mld_edit_melding op
    Parameters:         submit van mld/mld_edit_melding.asp en pda/melding.asp
    Note:               Eventueel maken we uiteindelijk een print-scherm aan!
                        Als backo opslaat dan wordt impliciet de status op 4 (geaccepteerd) gezet
                        Uiteindelijk willen we deze general purpose hebben, waarbij bv zo weinig mogelijk
                        velden verplicht zijn en zeker niet onnodig meegegeven hoeven te worden; vandaar
                        de introductie van de savewhen parameter in de save2db
*/
var JSON_Result = true;

var mld_key = getFParamInt("mld_key", -1);
var LOCKED_USER_OK = { "xmlnode": "melding", "key": mld_key };
%>

<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../shared/save2db.inc" -->
<!-- #include file="../Shared/kenmerk_common.inc" -->
<!-- #include file="mld.inc" -->
<!-- #include file="mld_edit_note.inc" -->

<%
var copy = (getFParamInt("mld_copy", 0) == 1);
var cont = (getFParamInt("mld_continue", 0) == 1);
var isTemplate = (getFParamInt("template", 0) == 1);
var child_arr_cont = [];
var mld_info;
var multi = false;
if (copy || cont)
  var mld_copy_key = getFParamInt("mld_copy_key");
if (cont)
{
  var mld_key_arr = getFParamIntArray("child_arr", []);
  if (mld_key_arr.length == 0)
    mld_key_arr.push(mld_copy_key)
  else
    multi = mld_key_arr.length > 1;

  var tobecontinued = 0;
  // Heb ik de juiste rechten op de child meldingen.
  for (var i = 0; i < mld_key_arr.length; i++)
  {
    this_mld = mld.func_enabled_melding(mld_key_arr[i]); // Wat heb ik zoal aan rechten op deze specifieke melding
    mld_info = mld.mld_melding_info(mld_key_arr[i]);
    lcl.set_dialect(mld_info.srtdisc_key, "MLD_SRTDISCIPLINE_KEY");
    if (this_mld.canContinue && !mld_info.parent_key) // Geen child melding
    {
      child_arr_cont.push(mld_key_arr[i]);
      tobecontinued++;
    }
  }
  // De laatst gebruikte set_dialect uit de for-lus geldt nu voor de onderstaande code.
  user.anything_todo_or_abort(tobecontinued > 0); // We klagen niet over enkele wel en enkele niet
}

function validMldReferenceKey(mldkey, refkey)
{
    // Is de opgegeven referentie een geldige melding?
    var result = false;
    if (refkey && refkey > 0)
    {
      var sql_r = "SELECT m.mld_melding_key"
                + "  FROM mld_melding m"
                + "     , mld_stdmelding sm"
                + "  WHERE m.mld_melding_key = " + refkey
                + "    AND m.mld_stdmelding_key = sm.mld_stdmelding_key"
                + "    AND sm.mld_ins_discipline_key IN"
                  + " (SELECT ins_discipline_key"
                  + "    FROM fac_v_webgebruiker g"
                  + "       , fac_functie f"
                  + "   WHERE g.prs_perslid_key = " + user_key
                  + "     AND f.fac_functie_key = g.fac_functie_key"
                  + "     AND f.fac_functie_code IN ('WEB_MLDFOF', 'WEB_MLDBOF')"
                  + "     AND g.fac_gebruiker_alg_level_read < 9)"
                + (mldkey==-1
                  ? ""
                  : "     AND m.mld_melding_key != " + mldkey  // niet naar jezelf refereren
                  )
                + "   AND TRUNC(m.mld_melding_einddatum, 'DD') >= SYSDATE - " + S("mld_reference_days");
      var oRs_r = Oracle.Execute(sql_r);
      if (!oRs_r.eof)
        result = true;
      oRs_r.Close();
    }
    else
      result = true; // Geen referentie is altijd geldig.

    return result;
}

function validCtrReferenceKey(refkey)
{
    // Is de opgegeven referentie een geldige periodieke taak?
    var result = false;
    if (refkey && refkey > 0)
    {
      var sql_r = "SELECT idsc.ins_deelsrtcontrole_key"
                + "  FROM ins_deelsrtcontrole idsc"
                + " WHERE idsc.ins_deelsrtcontrole_key = " + refkey;
      var oRs_r = Oracle.Execute(sql_r);
      if (!oRs_r.eof)
        result = true;
      oRs_r.Close();
    }
    else
      result = true; // Geen referentie is altijd geldig.

    return result;
}


// AUTORISATIEPARAMETERS
var urole = getFParamSafe("urole");
var fronto = urole == "fo";
var backo  = urole == "bo";
var frontend = (!fronto && !backo);

var parent_key = getFParamInt("parent_key", -1);
var isNew = (mld_key <= 0); // dan gaan we S("mld_melding_autoprint") beschouwen

var locatiekey = getFParamInt("locatiekey", -1);

var mld_ins_discipline_key = getFParamInt("mld_ins_discipline", -1);
var sBehandel_key          = getFParamInt("sBehandel", -2);
var sBehandel2_key         = getFParamInt("sBehandel2", -2);
var mldgroup_key           = getFParamInt("mldgroup_key", -1);
if (mldgroup_key == 0)
  mldgroup_key = -1;

var prio = getFParamInt("prio", mld_key>0?-1:3); // Default 3 voor nieuwe. Bij readonly bestaande meldingen de prio niet aanpassen.

// Bepaal de nieuwe waarde voor de checkbox afgerond.
var newvalafgerond = hasFParam("afgerond") ? 1: 0;

// Als we geen locatiekey hebben maar wel een afleveradres, kunnen we mogelijk ook een locatiekey bepalen
var del_address = getFParamInt("del_address", -1);
if (locatiekey == -1 && hasFParam("del_address") && del_address != -1)
{
  oRs = Oracle.Execute("SELECT alg_locatie_key FROM mld_adres WHERE mld_adres_key = " + del_address);
  if (!oRs.eof && oRs("alg_locatie_key").Value)
  {
    locatiekey = oRs("alg_locatie_key").Value;
  }
  oRs.Close();
}

// Objects...
var obj_arr = getFParamIntArray("r_objs", []);
var one_object = (obj_arr.length == 1); // Is er 1 object geselecteerd?

var forcesave = (getFParamInt("forcesave", 0) == 1);
var stdm_key = getFParamInt("stdm");
var stdm_info = mld.mld_stdmeldinginfo(stdm_key);

var meldbron_key = getFParamInt("meldbronkey", S("mld_meldbron_key"));
var meldbron = getFParamInt("meldbron", -1);
meldbron_key = (meldbron > 0 ? meldbron : meldbron_key); // Als door FO/BO de meldbron is ingevuld heeft deze prioriteit boven de default.
// If a deelsrtcont_key is given, this new melding will reference to a ins_deelsrtcontrole_key via table mld_melding_object.
var deelsrtcont_key = getFParamInt("deelsrtcont_key", null);


// Onroerendgoed_keys wordt de verfijnste van de opgegeven plaats
var gebouwkey     = getFParamInt("gebouwkey", -1);
var verdiepingkey = getFParamInt("verdiepingkey", -1);
var ruimtekey     = getFParamInt("ruimtekey", -1);
var bttype        = getFParam("bttype", "B"); // Type van gebouw/terrein ("B", "T"). Bepaald of bld_key een gebouw of terreinsector key bevat.

var alg_onroerendgoed_keys = -1;

// Wis de onroerendgoed keys die op basis van alglevel niet van belang zijn.
if (stdm_info.ins_srtdiscipline_alglevel < 3) gebouwkey = -1
if (stdm_info.ins_srtdiscipline_alglevel < 4) verdiepingkey = -1
if (stdm_info.ins_srtdiscipline_alglevel < 5) ruimtekey = -1;

if (stdm_info.ins_srtdiscipline_alglevel > 2)
{
  // die specifiekere plaats moet dan leegblijven
  if (ruimtekey != -1)
    alg_onroerendgoed_keys = ruimtekey;
  else if (verdiepingkey != -1)
    alg_onroerendgoed_keys = verdiepingkey;
  else if (gebouwkey != -1)
    alg_onroerendgoed_keys = gebouwkey;
}

var savemode = true;
if (!isTemplate && !forcesave && (fronto || frontend) && isNew)
{
  // mld_stdmelding_doublecheck: 00 (0) Geen controle uitvoeren
  //                             01 (1) Controle dubbel bij invoer nieuwe melding (door FE, FO (of BO))
  //                             10 (2) Controle dubbel bij accepteren melding (door BO)
  //                             11 (3) Controle zowel bij invoer als bij accepteren
  if (stdm_info.doublecheck == 1 || stdm_info.doublecheck == 3)
  {
    // In facmgt moet altijd een verplicht niveau gekozen worden. stdm_info.alg_onrgoed_niveau heeft dus een waarde (R, V, G, L).
    var where_alg = "AND m.mld_alg_onroerendgoed_keys = org.alg_onroerendgoed_keys(+)";
    if (!stdm_info.ins_srtdiscipline_alg)
      where_alg = "";
    else if (stdm_info.alg_onrgoed_niveau == "R")
      where_alg += " AND org.alg_ruimte_key = " + ruimtekey;
    else if (stdm_info.alg_onrgoed_niveau == "V")
      where_alg += " AND org.alg_verdieping_key = " + verdiepingkey;
    else if (stdm_info.alg_onrgoed_niveau == "G")
      where_alg += " AND org.alg_gebouw_key = " + gebouwkey;
    else if (stdm_info.alg_onrgoed_niveau == "L")
      where_alg = "AND m.mld_alg_locatie_key = " + locatiekey;

    // Als er exact 1 object is geselecteerd beschouwen
    // we alleen meldingen op dat object

    sql = "SELECT DISTINCT m.mld_melding_key"
        + "  FROM mld_melding m"
        + (where_alg?
          "     , alg_v_allonroerendgoed org": "")
        + (one_object?
          "     , mld_melding_object mo" : "")
        + " WHERE m.mld_melding_status IN (0, 2, 4, 7)"
        + (one_object
          ? "   AND m.mld_melding_key = mo.mld_melding_key"
            + " AND mo.ins_deel_key = " + obj_arr
          : "")
        + "   AND m.mld_melding_parentkey IS NULL" // Geen child meldingen tonen
        + "   AND m.mld_stdmelding_key = " + stdm_key
        + where_alg;
    oRs = Oracle.Execute(sql);
    if (!oRs.eof)
    { // Er is mogelijk een dubbele melding aanwezig
      savemode = false;
    }
    oRs.Close();
  }
}

if (savemode)
{ // Verder met opslaan van de gegevens
  var sql = "SELECT ms.mld_ins_discipline_key"
          + "     , mld_stdmelding_vereisdienst"
          + "     , mld_stdmelding_autoorder"
          + "     , ms.prs_dienst_key"
          + "     , ms.mld_stdmelding_prseigen"
          + "     , ms.mld_typeopdr_key"
          + "     , " + lcl.xsqla('pd.prs_dienst_omschrijving', 'pd.prs_dienst_key')
          + "     , COALESCE(ms.mld_stdmelding_directklaar, dp.mld_disc_params_directklaar, 0) mld_directklaar"
          + "  FROM mld_stdmelding ms"
          + "     , prs_dienst pd"
          + "     , mld_disc_params dp"
          + " WHERE mld_stdmelding_key = " + stdm_key
          + "   AND pd.prs_dienst_key(+) = ms.prs_dienst_key"
          + "   AND ms.mld_ins_discipline_key = dp.mld_ins_discipline_key";
  var oRs = Oracle.Execute(sql);
  var discipline_key = oRs("mld_ins_discipline_key").Value;
  var vereisdienst = oRs("mld_stdmelding_vereisdienst").Value == 1;
  var eigenprs = oRs("mld_stdmelding_prseigen").Value == 1;
  var prs_dienst_key = oRs("prs_dienst_key").Value;
  var prs_dienst_desc = oRs("prs_dienst_omschrijving").Value; // 'Schoonmaken'
  // Als de melding een child melding is en aan de parent gekoppeld moet worden dan niet automatisch een opdracht aanmaken.
  var autoorder = oRs("mld_stdmelding_autoorder").Value == 1 && parent_key < 0;
  var mld_typeopdr_key = oRs("mld_typeopdr_key").Value;
  var directNaarFO = oRs("mld_directklaar").Value == 2;
  oRs.Close();

  var old_ref_key     = -1;
  var old_mld_status  = -1;
  if (mld_key > 0)
  {
    var sql_m = "SELECT m.mld_melding_kto_key"
              + "     , m.mld_melding_spoed"
              + "     , m.mld_melding_status"
              + "     , m.mld_ins_discipline_key"
              + "     , m.mld_stdmelding_key"
              + "     , std.mld_ins_discipline_key"
              + "  FROM mld_melding m"
              + "     , mld_stdmelding std"
              + " WHERE m.mld_stdmelding_key = std.mld_stdmelding_key"
              + "   AND m.mld_melding_key = " + mld_key;
    var oRs_m       = Oracle.Execute(sql_m);
    old_ref_key     = oRs_m("mld_melding_kto_key").Value;
    old_mld_status  = oRs_m("mld_melding_status").Value;
    var old_prio    = oRs_m("mld_melding_spoed").Value;
    var old_disc    = oRs_m("mld_ins_discipline_key").Value;
    var old_stdm    = oRs_m("mld_stdmelding_key").Value;

    oRs_m.Close();

    var new_stdm  = getFParamInt("stdm", old_stdm);
  }

  var person_key = getFParamInt("person", -1);
  if (cont)
  {
    if (mld_ins_discipline_key == -1)
    { // Er is geen behandelteam geselecteerd, probeer alsnog een default behandelteam.
      mld_ins_discipline_key = ((stdm_info.srtgroep & 2 || stdm_info.srtgroep & 4) && stdm_info.default_ins_disc_key
                               ? stdm_info.default_ins_disc_key
                               : -1);
    }
    // mld_info = mld.mld_melding_info(mld_copy_key);
    var melder_key = person_key != -1 ? person_key : (multi ? user_key : mld_info.melder_key);
    var melder_info = new Perslid(melder_key); // Je maakt de melding voor jezelf of ander aan (prs_perslid_key_voor is user_key).
    person_key = (melder_info.isSystemUser() ? user_key : melder_key);
    var prs_key_voor = person_key;
    user.auth_required_or_abort(person_key != -1); // Serverside check op deze verplichting
  }
  else
  {
    // Als S(mld_allow_for_others) niet is gezet is "Melding voor" gelijk aan contactpersoon. Invoerveld "Melding voor" was dan ook niet aanwezig.
    // Kolommen prs_perslid_key en prs_perslid_key_voor zijn dan identiek.
    if (S("mld_allow_for_others") == 1 || S("mld_allow_for_others") == 2)
      var prs_key_voor = getFParamInt("personFor", -1);
    else
      var prs_key_voor = getFParamInt("person", -1);
  }

  if (multi)
    var prs_bedrijf_key = mld.dienst_controle(stdm_key, user.alg_locatie_key(), user.alg_gebouw_key(), user.alg_ruimte_key(), obj_arr, user_key);
  else
  {
    // Als we geen locatiekey hadden dan is hierboven al via afleveradres naar locatiekey gezocht.
    // Indien de gebouwkey een terrein is, gaan we kijken naar de locatie. Terrein heeft geen diensten. De ruimtekey is dan al null.
    var prs_bedrijf_key = mld.dienst_controle(stdm_key, locatiekey, (bttype == "B"? gebouwkey : null), ruimtekey, obj_arr, prs_key_voor);
  }

  lcl.set_dialect(stdm_info.ins_srtdiscipline_key, "MLD_SRTDISCIPLINE_KEY");

  var kpkey = getFParamInt("account", -1);
  if (stdm_info.kpnverplicht && kpkey < 0)
  { // Kostenplaats is verplicht, maar is niet meegegeven. Bepaal default kostenplaats.
    kpkey = (user.prs_kostenplaats_key() || -1); // User kostenplaats key
    if (kpkey < 0)
      // We kunnen geen default kostenplaats bepalen. We kunnen de melding niet aanmaken.
      // Alert geven en terug.
      shared.simpel_page("Melding niet automatisch aangemaakt omdat kostenplaats niet bepaald kon worden");  //lcl?
  }

  if (stdm_info.kanverwijzen)
  {
    function mld_foreign (pval, oldjsvals) // bij oldval krijgen we oldjsvals tot nu toe mee
    {
      if (!pval)
        return "";
      return mld.referentielabel("M", pval);
    }
  }

  // tamper check
  if (S("fac_tamper_check") > 0 && !user.has(["WEB_MLDFOF", "WEB_MLDBOF"]))
  {
    __Log("Tamper checking frontend");
    if (person_key > 0)
        user.auth_required_or_abort(user.isCollega(person_key));

    var personH_key = getFParamInt("personH", user_key);
    if (prs_key_voor > 0 && prs_key_voor != user_key) // geen onnodig dure controle
    {
        var bresult = user.func_enabled2("MLD", {  // We nemen geen disciplines mee, dat is onbegonnen werk
                                                   // alg_key: alg_onroerendgoed_keys,
                                                   prs_key: prs_key_voor
                                                }
                                        )
        user.auth_required_or_abort(bresult.canWrite("WEB_MLDUSE"));
    }
  }

  // Deze velden altijd opslaan
  var fields = [ { dbs: "mld_melding_omschrijving",        typ: "clob",     frm: "melding_omschrijving", track: L("lcl_mld_inf_Omschrijving"), len: S("mld_melding_oms_maxlen") },
                 { dbs: "mld_kosten_klant",                typ: "check",    frm: "kostenklant"           /* notrack: */ },
                 { dbs: "mld_melding_ordernr",             typ: "varchar",  frm: "ordernr",              track: L("lcl_mld_inf_Ordernr")},
                 { dbs: "prs_perslid_key",                 typ: "key",      val: person_key,             track: L("lcl_mld_name"),             foreign: "prs_perslid" },
                 { dbs: "prs_perslid_key_voor",            typ: "key",      val: prs_key_voor,
                                                                            savewhen: "personFor",       track: L("lcl_mld_call_for"),         foreign: "prs_perslid" },
                 { dbs: "prs_kostenplaats_key",            typ: "key",      val: kpkey,                  track: L("lcl_mld_inf_Kostenplaats"), foreign: "prs_kostenplaats" },
                 { dbs: "mld_melding_opmerking",           typ: "varchar",  frm: "remark",               track: L("lcl_mld_inf_Opmerking"),    len: 4000 },
                 { dbs: "mld_stdmelding_key",              typ: "key",      frm: "stdm",                 track: L("lcl_complain"),             buildTrackText: buildStdmTrackText },
                 { dbs: "mld_alg_onroerendgoed_keys",      typ: "key",      val: alg_onroerendgoed_keys,
                                                                            savewhen: "locatiekey",      track: true /* afzonderlijke tracking, wel oldjsval */ },
                 { dbs: "mld_alg_locatie_key",             typ: "key",      val: locatiekey,
                                                                            savewhen: "locatiekey",      track: true /* afzonderlijke tracking, wel oldjsval */ },
                 { dbs: "mld_adres_key",                   typ: "key",      frm: "del_address",          track: L("lcl_delivery_address"),     foreign: "mld_v_afleveradres" },
                 { dbs: "mld_melding_behandelaar_key",     typ: "key",      frm: "sBehandel",            track: true /* afzonderlijke tracking, wel oldjsval */ },
                 { dbs: "mld_melding_behandelaar2_key",    typ: "key",      frm: "sBehandel2",           track: true /* afzonderlijke tracking, wel oldjsval */ },
                 { dbs: "mld_melding_externnr",            typ: "varchar",  frm: "externnr",             track: L("lcl_mld_externr") },
                 { dbs: "mld_melding_publiek",             typ: "check0",   frm: "publiek"               /*track: L("lcl_mld_publiek")*/ },
                 { dbs: "mld_melding_indult",              typ: "check0",   frm: "indult",               track: L("lcl_mld_indult") },
                 { dbs: "mld_melding_afgerond",            typ: "check0",   frm: "afgerond",             track: L("lcl_mld_afgerond") },
                 { dbs: "mld_melding_mldgroup_key",        typ: "key",      val: mldgroup_key,           track: L("lcl_mldgroup_key"),         foreign: mld_foreign },
                 { dbs: "mld_melding_tag_key",             typ: "key",      frm: "tag_key",              track: L("mld_melding_tag_naam"),     foreign: "mld_tag" },
                 { dbs: "mld_melding_dwgx",                typ: "float",    frm: "caddwgx",              track: L("lcl_mld_dwgx") }, // Als idadd "1" was geweest was frm: "caddwgx1"
                 { dbs: "mld_melding_dwgy",                typ: "float",    frm: "caddwgy",              track: L("lcl_mld_dwgy") }  // Als idadd "1" was geweest was frm: "caddwgy1"
               ];

  var subject = getFParam("melding_onderwerp", "");
  if (!subject && isNew && stdm_info.subject == 3 && S("ai_enabled") & 1) { // AI generate the subject
    var omschrijving = shared.stripbbcodes(getFParam("melding_omschrijving", ""));
    var result = shared.promptAI(omschrijving, { "instructions": L("lcl_mld_ai_subject_instructions").format(stdm_info.mld_stdmelding_omschrijving) });
    if (result.success) {
      subject = result.content;
      fields.push({ dbs: "mld_melding_onderwerp_ai", typ: "varchar", val: subject, len: 200 });
    } else {
      if (result.warning) {
        __DoLog(result.warning, "#FF0000");
      }
    }
  }
  fields.push({ dbs: "mld_melding_onderwerp", typ: "varchar", val: subject, track: L("lcl_mld_subject"), len: 200 });

  if (cont || hasFParam("mld_ins_discipline"))
    fields.push({ dbs: "mld_ins_discipline_key",          typ: "key",      val: mld_ins_discipline_key, track: true /* afzonderlijke tracking, wel oldjsval */,     foreign: "mld_discipline" });

  if (hasFParam("canholdthirdparty"))
  {
      fields.push({ dbs: "mld_melding_naam_ext",       typ: "varchar",      frm: "naam_ext",         track: L("lcl_mld_naam_ext") });
      fields.push({ dbs: "mld_melding_email_ext",      typ: "varchar",      frm: "email_ext",        track: L("lcl_mld_email_ext") });
      fields.push({ dbs: "mld_melding_tel_ext",        typ: "varchar",      frm: "tel_ext",          track: L("lcl_mld_tel_ext") });
  }
  // Checken of een geldige respijt aanwezig was.
  // De eenheid van respijt wordt gelijk genomen aan de eenheid van de stdmelding en is dus altijd readonly.
  // Als respijt niet aanwezig was dan ook eenheid niet opslaan (val wordt altijd opgeslagen, maar frm niet).
  // We ondersteunen ook negatieve respijt maar op eigen risico: (Facilitor) SLA berekeningen over meerdere dagen kunnen onverwachte resultaten geven.
  var respijtpresent = hasFParam("respijt") && (getFParamFloat("respijt") > 0 || (S("mld_negatief_respijt") == 1 && getFParamFloat("respijt") != 0));
  if (respijtpresent)
    fields.push({ dbs: "mld_melding_t_respijt.tijdsduur",
                  obj: "MLD_T_UITVOERTIJD",               typ: "float",   frm: "respijt",    track: L("lcl_mld_respijt") },
                { dbs: "mld_melding_t_respijt.eenheid",
                  obj: "MLD_T_UITVOERTIJD",               typ: "varchar", val: stdm_info.prioriteiten[(prio > 0? prio : old_prio)].eenheid, track: L("lcl_mld_respijt_eenheid") });
  else // Leegmaken
    fields.push({ dbs: "mld_melding_t_respijt.tijdsduur",
                  obj: "MLD_T_UITVOERTIJD",               typ: "float",   val: null,         track: L("lcl_mld_respijt") },
                { dbs: "mld_melding_t_respijt.eenheid",
                  obj: "MLD_T_UITVOERTIJD",               typ: "varchar", val: null,         track: L("lcl_mld_respijt_eenheid") });

  if (S("mld_use_department") == 1)
  {
    var sgDept = getFParamInt("sgDept", -1);
    if (sgDept == -1)
        sgDept = user.prs_afdeling_key();
    fields.push({ dbs: "prs_afdeling_key",                typ: "key",     val: sgDept,       track: L("lcl_mld_afdeling"),  foreign: "prs_afdeling" });
  }

  if (S("mld_melding_flags") > 0)
    fields.push({ dbs: "mld_melding_flag",            typ: "number",   frm: "mldflag" /* notrack */ });

  var rsv_ruimte_key = getFParamInt("rsv_ruimte_key", -1);
  var cnt_key = getFParamInt("cnt_key", -1);
  if (rsv_ruimte_key > 0)
    fields.push({ dbs: "res_rsv_ruimte_key",          typ: "key",      frm: "rsv_ruimte_key", track: L("lcl_mld_with_res"), foreign: "res_rsv_ruimte" }); // Alleen bij aanmaken wordt deze eventueel gezet.

  // De startdatum ophalen die opgeslagen moet worden.
  var params_startdate = { disc_with_startdatum: stdm_info.startdatum };
  var startdate_info = mld.getstartdatesave(mld_key, params_startdate);
  var startdate = startdate_info.startdate;
  fields.push(startdate_info.startfield);

  if (stdm_info.show_actiedatum && hasFParam("actiondate"))
  { // Actiedatum was invulbaar en is meegegeven.
    fields.push({ dbs: "mld_melding_actiedatum", typ: "datetime", frm: "actiondate", track: L("lcl_mld_actiondate") });
  }

  // enddate_std wordt m.b.v. trigger en database functie mld.geteinddatum(startdate, stdm_key, prio, geb_key) berekend.
  // mld_melding_acceptdatum_std wordt ook in de trigger bepaald

  // De einddatum is de meegegeven einddatum (zoals mogelijk bepaald en aangepast), maar als die niet wordt meegegeven is het
  // gewoon enddate_std en dat regelt de trigger wel, dus DAN MOET IK HEM NIET MEEGEVEN
  // De tijd van de einddatum wordt nu altijd opgeslagen onafhankelijk of de tijd getoond wordt.
  if (hasFParam("enddate"))
  { // Was de einddatum hidden?
    var einddatumHidden = stdm_info.planbaar == 2 || (stdm_info.planbaar == 0 && stdm_info.planbaarfe == 0 && frontend && mld_key < 0);
    if (einddatumHidden)
    { // Omdat de einddatum niet zichtbaar is willen we wel een zuivere SLA en niet een kortere SLA omdat de invoer lange heeft geduurd.
      var ins_deel_key = -1;
      if (obj_arr.length)
      {
        var sql = "SELECT MAX(d.ins_deel_key) ins_deel_key "
                + "  FROM ins_deel d"
                + " WHERE d.ins_deel_key IN (" + obj_arr.join(",") + ")"
                + "   AND (CASE"
                + "            WHEN d.ins_deel_t_uitvoertijd.eenheid = 'U' THEN d.ins_deel_t_uitvoertijd.tijdsduur / 24"
                + "            ELSE d.ins_deel_t_uitvoertijd.tijdsduur"
                + "        END) = "
                + "       (SELECT MIN("
                + "                   CASE"
                + "                       WHEN d1.ins_deel_t_uitvoertijd.eenheid = 'U' THEN d1.ins_deel_t_uitvoertijd.tijdsduur / 24"
                + "                       ELSE d1.ins_deel_t_uitvoertijd.tijdsduur"
                + "                   END)"
                + "          FROM ins_deel d1"
                + "         WHERE d1.ins_deel_key IN (" + obj_arr.join(",") + "))";
        var oRs = Oracle.Execute(sql);
        ins_deel_key = oRs("ins_deel_key").Value || -1;
        oRs.Close();
      }
      // Bereken de einddatum vanaf het moment van opslaan (nu) volgens de geldende SLA's.
      var enddate = mld.geteinddatum(startdate, stdm_key, prio, gebouwkey, ruimtekey, ins_deel_key);
    }
    else
    {
      // Als gevolg van het verschil in tijdstip tussen meldingscherm openen en melding opslaan
      // de einddatum corrigeren als deze voor de startdatum is komen te liggen.
      var enddate = getFParamDate("enddate", new Date);
      if (enddate < startdate)
        enddate = startdate;
    }
    fields.push({ dbs: "mld_melding_einddatum", typ: "datetime", val: enddate, track: stdm_info.planbaar == 2? false: L("lcl_mld_enddate") });
  }

  //quicknote
  var note = getFParam("note", "");
  if(note){
    var notestamp       = getFParamDate("notestamp", new Date());
    var note_key        = getQParamInt("note_key", -1);
    var has_zichtbaarFE = getFParam("has_zichtbaarFE", 0 ) == 1;
    var zichtbaarFE     = getFParam("zichtbaarFE", "off" ) == "on";
    var has_notifyBO    = getFParam("has_notifyBO", 0 ) == 1;
    var fac_note_group_key = getFParamInt("fac_note_group_key", null );
    if (fac_note_group_key == -1)
    {
      fac_note_group_key = null;
    }

    var result = mld_note_save( mld_key,
                            note,
                            { note_key:        note_key,
                              fac_note_group_key: fac_note_group_key,
                              ismailnote:      0
                            });
  }

  var fac_activiteit_key = getFParamInt("fac_activiteit_key", -1);
  var is_planned_mld = fac_activiteit_key > -1;
  if (!isNew)
  { // Update an existing mld_melding record
    // Hardness controle schrijfrechten
    var this_mld = mld.func_enabled_melding(mld_key); // Wat heb ik zoal aan rechten op deze specifieke melding
    user.auth_required_or_abort(this_mld.canChange || this_mld.canChangeKenmerkBlok);

    if (stdm_info.kanverwijzen)
    {
        var ref_key = getFParamInt("ref_key", -1);
        // Referentie naar een periodiek taak veranderd niet.
        if (this_mld.meldbron_key != 10 && !stdm_info.is_kto_antwoord && stdm_info.kanverwijzen == 128 && ref_key != old_ref_key)
        {
            if (!validMldReferenceKey(mld_key, ref_key))
                abort_with_warning(L("lcl_mld_invalid_reference"));
        }

        function ref_foreign (pval, oldjsvals) // bij oldval krijgen we oldjsvals tot nu toe mee
        {
            if (!pval)
                return "";
            var ref_type = oldjsvals?oldjsvals.mld_melding_kto_type:getFParam("ref_type");
            return mld.referentielabel(ref_type, pval);
        }

        fields.push({ dbs: "mld_melding_kto_type",    typ: "varchar",  frm: "ref_type", track: true /* afzonderlijke tracking, wel oldjsval */ });
        fields.push({ dbs: "mld_melding_kto_key",     typ: "key",      frm: "ref_key",  track: L("lcl_reference"), foreign: ref_foreign });
    }
    fields.push({ dbs: "mld_melding_kto",           typ: "check",    frm: "ktoself",              track: L("lcl_mld_kto_invite") });

    // Controleer soms of er geen lopende opdrachten zijn die buiten de (gewijzigde) meldingsperiode vallen
    if (S("mld_enforce_orderdates") == 1)
    { // Einddatum: indien niet meegegeven, neem dan sysdate.
      var enddate = getFParamDate("enddate", new Date);

      sql = "SELECT COUNT (*) aantal FROM mld_opdr"
          + " WHERE mld_statusopdr_key IN (3, 4, 5, 8)"
          + (stdm_info.startdatum == 1
            ? " AND (TRUNC(mld_opdr_datumbegin) < " + startdate.beginToSQL()
              + "    OR (mld_opdr_einddatum IS NOT NULL AND TRUNC(mld_opdr_einddatum) >" + enddate.beginToSQL() + "))"
            : " AND (mld_opdr_einddatum IS NOT NULL AND TRUNC(mld_opdr_einddatum) > " + enddate.beginToSQL() + ")")
          + " AND mld_melding_key = " + mld_key;
      oRs = Oracle.Execute(sql);
      if (oRs("aantal").Value > 0)
          abort_with_warning(L("lcl_mld_meldingbuitenopdracht"));
      oRs.Close();
    }

    fields.push({ dbs: "mld_melding_spoed",    typ: "key",      frm: "prio",      track: L("lcl_mld_urg"), foreign: mld.getpriotext });
    fields.push({ dbs: "mld_melding_impact",   typ: "key",      frm: "impact",    track: L("lcl_mld_impact"), foreign: mld.getimpacttext });
    fields.push({ dbs: "mld_melding_urgentie", typ: "key",      frm: "urgentie",  track: L("lcl_mld_urgentie"), foreign: mld.geturgentietext });

    /* mldUpd heeft na afloop handige oldjsvals */
    var mldUpd = buildTrackingUpdate("mld_melding", " mld_melding_key = " + mld_key, fields);

    /* SUBMIT THE CHANGED DATA */
    var err = Oracle.Execute(mldUpd, true); // No .sql to support bind-variables

    if (err.friendlyMsg)
      abort_with_warning(err.friendlyMsg);

    // Als er child meldingen zijn, dan volgen het behandelteam en de behandelaar2 van de child die van de parent.
    // Eerst nagaan of beide velden zijn gewijzigd.
    var parentparams = {saveBehandelteam: false,
                        saveBehandelaar2: false,
                        behandelteam_key: mld_ins_discipline_key,
                        behandelaar2_key: sBehandel2_key
                       };

    /* SET STATUS AND SUBMIT ADDITIONAL TRACKING */
    // Geplande acties moeten niet genotificeerd worden en kunnen niet gekoppeld zijn/worden.

    // Eventuele wijziging van primaire behandelaar
    if (sBehandel_key != -2 && (mldUpd.oldjsvals["mld_melding_behandelaar_key"] || -1) != (sBehandel_key || -1))
    { // Anders is-ie niet meegegeven of niet veranderd
      mld.trackbehandelaar(mld_key, sBehandel_key, is_planned_mld);
    }

    // Eventuele wijziging van behandelteam
    if ((mldUpd.oldjsvals["mld_ins_discipline_key"] || -1) != mld_ins_discipline_key && !is_planned_mld)
    { // Anders is-ie niet meegegeven of niet veranderd
      // PF: ik vermoed toch van wel hoor: LOGC#84925 mld.notifybehandelteam(mld_key, mld_ins_discipline_key); // Notificatie parent. // Tracking wordt in de MLDUPD gedaan dus hier geen mld.trackAndNotifyBehandelteam.
      mld.trackAndNotifyBehandelteam(mld_key, mld_ins_discipline_key);
      // Het behandelteam van eventuele child meldingen moeten aangepast worden.
      parentparams.saveBehandelteam = true; // Het behandelteam van de parent is aangepast.
    }

    // Eventuele wijziging van (secundaire) behandelteam-behandelaar
    // Behandelaars2 van de child meldingen moeten die van de parent volgen.
    if (sBehandel2_key != -2 && (mldUpd.oldjsvals["mld_melding_behandelaar2_key"] || -1) != (sBehandel2_key || -1))
    { // Anders is-ie niet meegegeven of niet veranderd
      mld.trackbehandelaar2(mld_key, sBehandel2_key, is_planned_mld); // Tracking parent.
      // De behandelaars2 van eventuele child meldingen moeten aangepast worden.
      parentparams.saveBehandelaar2 = true; // De behandelaar2 van de parent is aangepast.
    }

    // Nu de childmeldingen als het behandelteam en/of de behandelaar2 zijn gewijzigd.
    if (parentparams.saveBehandelteam || parentparams.saveBehandelaar2)
    {
      // Array child_arr_cont is alleen gevuld bij het opslaan van een vervolgmelding. Dan hier maar een nieuwe array vullen/bepalen.
      var child_arr = mld.getchildmeldingen(mld_key);
      mld.updatechildren(child_arr, parentparams);
    }

    if (S("mld_rejected_is_open") && old_mld_status == 1) {
      // Aanpassen van een afgewezen melding werpt die weer opnieuw de molen in.
      mld.setmeldingstatus(mld_key, 2);
    }

    // Send notification for calls that have priority changed to 1 or 2
    if (old_prio != prio && (prio == 1 || prio == 2) && !is_planned_mld)
        mld.notifyprio(mld_key, prio);

    // tracking plaats is ingewikkelder (twee keys maar slechts één track gewenst), die doen we handmatig
    // alg_onroerendgoed_keys en locatiekey bevatten reeds de nieuwe waardes
    if (stdm_info.ins_srtdiscipline_alg && stdm_info.alg_onrgoed_niveau != "H" && this_mld.canPlaatsChange && hasFParam("locatiekey")) // dan kan de plaats gewijzigd zijn
    {
      if (alg_onroerendgoed_keys > 0)
        newsql = "SELECT alg_plaatsaanduiding FROM alg_v_plaatsaanduiding_all WHERE alg_onroerendgoed_keys = " + alg_onroerendgoed_keys;
      else if (locatiekey > 0)
        newsql = "SELECT alg_locatie_code FROM alg_locatie WHERE alg_locatie_key = " + locatiekey;
      else
        newsql = "SELECT '' FROM DUAL";
      var og_key = mldUpd.oldjsvals["mld_alg_onroerendgoed_keys"];
      var loc_key = mldUpd.oldjsvals["mld_alg_locatie_key"];
      if (og_key>0)
        oldsql = "SELECT alg_plaatsaanduiding FROM alg_v_plaatsaanduiding_all WHERE alg_onroerendgoed_keys = " + og_key;
      else if (loc_key > 0)
        oldsql = "SELECT alg_locatie_code FROM alg_locatie WHERE alg_locatie_key = " + loc_key;
      else
        oldsql = "SELECT '' FROM DUAL";
      var oRs_old = Oracle.Execute(oldsql);
      var oldtxt = oRs_old(0).Value;
      oRs_old.Close();
      var oRs_new = Oracle.Execute(newsql);
      var newtxt = oRs_new(0).Value;
      oRs_new.Close();
      if (oldtxt != newtxt)
        mldUpd.trackarray.push(L("lcl_plaatsgegevens") + ": " + buildTrackText("varchar", oldtxt, newtxt, { nodiff: true }));
    }

    // tracking doen we gelijk met de flexkenmerken

    mld.keepFlexDocuments(mld_key, mldUpd.oldjsvals["mld_stdmelding_key"], stdm_key);
  }
  else
  { // A new mld_melding record

    // We hebben de melding en dus de discipline. Autorisatie controle kan al redelijk scherp
    var this_mld = mld.func_enabled_mld(stdm_info.ins_discipline_key, "D");
    user.auth_required_or_abort(this_mld.canFEwrite || this_mld.canFOwrite);

    if (stdm_info.is_kto_antwoord || stdm_info.kanverwijzen == 0)
    {
        var ref_key = getFParamInt("kto_key", null);
        var ref_type = getFParam("kto_type", null);
    }
    else
    {
        var ref_key = getFParamInt("ref_key", -1);  // explicit reference
        var ref_type = getFParam("ref_type", null);
    }

    if (deelsrtcont_key > 0)
    {
      if (!validCtrReferenceKey(deelsrtcont_key))
        abort_with_warning(L("lcl_mld_invalid_ctr_ref"));
    }
    else if (!stdm_info.is_kto_antwoord && stdm_info.kanverwijzen == 128 && !validMldReferenceKey(-1, ref_key) )
    {
      abort_with_warning(L("lcl_mld_invalid_reference"));
    }

    fields = fields.concat(
                    [ { dbs: "mld_melding_key",         typ: "key",      seq: "mld_s_mld_melding_key" },
                      { dbs: "mld_meldbron_key",        typ: "key",      val: meldbron_key },
                      { dbs: "mld_melding_start_key",   typ: "key",      frm: "start_key" },
                      { dbs: "mld_melding_module",      typ: "varchar",  val: "MLD" },
                      { dbs: "mld_melding_spoed",       typ: "key",      val: (prio > 0? prio : 3) }, // default (frontend) 3
                      { dbs: "mld_melding_impact",      typ: "key",      frm: "impact" },
                      { dbs: "mld_melding_urgentie",    typ: "key",      frm: "urgentie" },
                      { dbs: "mld_melding_kto_type",    typ: "varchar",  val: ref_type },
                      { dbs: "mld_melding_kto_key",     typ: "key",      val: ref_key },
                      { dbs: "mld_melding_kto",         typ: "number",   val: (stdm_info.stdmelding_kto & 1)? 1 : 0 }
                    ]);
    if (!(copy && isTemplate))
    {
      fields.push({ dbs: "fac_activiteit_key",      typ: "key",      frm: "fac_activiteit_key" });
    }

    var mldIns = buildInsert("mld_melding", fields);
    var mld_key = mldIns.sequences["mld_melding_key"];

    // Hier maken we de nieuwe melding echt aan
    var err = Oracle.Execute(mldIns, true);
    if (err.friendlyMsg)
      abort_with_warning(err.friendlyMsg);

    // De trigger mld_t_mld_melding_B_IU vult de mld_melding_conceptstatus met de stdmelding setting mld_stdmelding_conceptstatus.
    // Hier kunnen we dus (pas) de conceptstatus weten en ophalen.
    var oRs = Oracle.Execute("SELECT mld_melding_conceptstatus FROM mld_melding WHERE mld_melding_key={0}".format(mld_key));
    var conceptstatus = oRs("mld_melding_conceptstatus").Value;
    oRs.Close();

    // Als er ingestemd moet worden, dan instemmen volgens setting "mld_instemmer_self" (Wat doen als ik zelf zou moeten instemmen. {0(=default)=niks, >0=volgens codering conceptstatus}).
    // LET OP: Onderstaande controle zou ook in de trigger mld_t_mld_melding_B_IU plaats kunnen vinden maar dit moet in 2024.1 (branch) dus geen database wijzigingen.
    if (conceptstatus > 0 && S("mld_instemmer_self") > 0)
    { // Er moet ingestemd worden en de melder mag dat niet zelf.
      var instemmer = mld.getinstemmer_key(mld_key);
      var isInstemmer = (user.isCollega(instemmer)); // Ik kijk hier niet of user WEB_MLDMSU rechten heeft.
      if (isInstemmer && user_key == person_key)
      { // Instemmer is de melder van de melding. De instemmer moet nu bepaald worden volgens codering conceptstatus van de setting mld_instemmer_self.
        // Zet de nieuwe conceptstatus want de melder mag niet instemmen.
        Oracle.Execute("UPDATE mld_melding SET mld_melding_conceptstatus = " + S("mld_instemmer_self") + " WHERE mld_melding_key = " + mld_key);
      }
    }

    if (parent_key > 0)
    {
        mld.link_child_to_parent(mld_key, parent_key);
    }
    else
    {
        // Zetten van de status op ingevoerd en afhandelen van de tracking.
        mld.setmeldingstatus(mld_key, (directNaarFO? 0 : 2)); // Zorgt ook voor tracking & daarmee notificatie

        // CND-gebrekmeldingen kunnen automatisch geaccepteerd moeten worden
        if (S("cnd_gebreken_srtdisc_key") > -1 && S("cnd_autoaccept") == 1 &&  stdm_info.ins_srtdiscipline_key == S("cnd_gebreken_srtdisc_key")) {
            mld.setmeldingstatus(mld_key, 4);
        }

        if (mld_ins_discipline_key > 0 && !is_planned_mld) // Een default toewijzing ook gewoon tracken en notificeren
        {
            mld.trackAndNotifyBehandelteam(mld_key, mld_ins_discipline_key, true);
        }
        if (sBehandel2_key > 0)
        {
            mld.trackbehandelaar2(mld_key, sBehandel2_key, is_planned_mld);
        }
    }

    if (stdm_info.is_kto_antwoord) // die direct afmelden
      mld.setmeldingstatus(mld_key, 5);

    if (multi)
    { // Tracking children na het zetten van de status van de nieuwe parent melding (mld_melding_parentkey) pas aanroepen.
      // Als er een XML document (bon) wordt aangemaakt moet de status van de parent melding gezet zijn,
      // anders levert de functie xml.make_xml2() een lege XML op en daardoor een foutmelding (zie ook FSN#46388).
      for (var i = 0; i < child_arr_cont.length; i++)
      {
        var fields = [ { dbs: "mld_melding_parentkey", typ: "number", val: mld_key, track: L("lcl_mld_completion_in") } ];
        var mldUpd = buildTrackingUpdate("mld_melding", " mld_melding_key = " + child_arr_cont[i], fields);
        Oracle.Execute(mldUpd.sql);
        if (mldUpd.trackarray.length)
            mld.trackmeldingupdate(child_arr_cont[i], L("lcl_mld_is_mldupd") + "\n" + mldUpd.trackarray.join("\n"));
      }
    }
  }

  if (getFParamInt("has_r_objs", 0) == 1) // voorkom dat we wissen vanuit mobile-save die helemaal geen listbox heeft
  { // Objecten verwijderen of toevoegen.
    var objtrack = mld.saveobjects(mld_key, obj_arr, deelsrtcont_key); // Als een melding bij een taak wordt geregistreerd dan heeft deelsrtcont_key een waarde.
    // Tracken van de objectwijzigingen.
    if (!isNew && objtrack != "")
      mldUpd.trackarray.push(objtrack);
  }

  // Eventuele (gewijzigde) objecten zijn nu ook opgeslagen.
  // Nu kan de definitieve mld_melding.mld_melding_einddatum_std en mld_melding.mld_melding_t_uitvoertijd bepaald en gezet worden.
  mld.finishmeldingiu(mld_key);

  // Sql met de huidige kenmerken rekening houdend met de juiste vakgroep en melding.
  // Ander kenmerken worden door de functie saveFlexKenmerken verwijderd (FSN#18613)
  currentKenmerkenSQL = "SELECT vk.mld_kenmerk_key"
                      + "     , mld_kenmerkmelding_waarde"
                      + "     , vk.mld_kenmerk_toonbaar"
                      + "     , vk.fac_functie_key"
                      + "  FROM mld_kenmerkmelding km"
                      + "     , mld_kenmerk vk"
                      + "     , mld_melding m"
                      + "     , mld_stdmelding s"
                      + "     , mld_discipline d"
                      + " WHERE km.mld_kenmerk_key = vk.mld_kenmerk_key"
                      + "   AND km.mld_kenmerkmelding_verwijder IS NULL"
                      + "   AND km.mld_melding_key = m.mld_melding_key"
                      + "   AND m.mld_melding_key = " + mld_key
                      + "   AND s.mld_stdmelding_key = m.mld_stdmelding_key"
                      + "   AND s.mld_ins_discipline_key = d.ins_discipline_key"
                      + "   AND ((vk.mld_stdmelding_key IS NULL AND vk.mld_kenmerk_niveau = 'A')"
                      + "     OR (vk.mld_stdmelding_key = s.mld_stdmelding_key     AND vk.mld_kenmerk_niveau = 'S')"
                      + "     OR (vk.mld_stdmelding_key = s.mld_ins_discipline_key AND vk.mld_kenmerk_niveau = 'D')"
                      + "     OR (vk.mld_stdmelding_key = d.ins_srtdiscipline_key  AND vk.mld_kenmerk_niveau = 'T'))";

  allKenmerkenSQL     = "SELECT COALESCE (" + lcl.xsql("k.mld_kenmerk_omschrijving", "k.mld_kenmerk_key")
                      + "              ,  " + lcl.xsql("t.mld_srtkenmerk_omschrijving", "t.mld_srtkenmerk_key") + ") kenmerk_omschrijving"
                      + "     , t.mld_srtkenmerk_kenmerktype kenmerk_kenmerktype"
                      + "     , t.mld_srtkenmerk_systeem     kenmerk_systeem"
                      + "     , k.mld_kenmerk_toonbaar       kenmerk_readonly"
                      + "     , k.mld_kenmerk_uniek          kenmerk_uniek"
                      + "     , fac_kenmerkdomein_key"
                      + "  FROM mld_kenmerk k"
                      + "     , mld_srtkenmerk t"
                      + " WHERE k.mld_srtkenmerk_key = t.mld_srtkenmerk_key"
                      + "   AND k.mld_kenmerk_key = "; /* wordt in saveFlexkenmerken uitgebreid */

  var flextrack = [];
  if (isNew || this_mld.canFlexChange || this_mld.canChangeKenmerkBlok) // anders veel te riskant (FSN#38017)
  {
      var kenmerkParams = { kenmerkTable: "mld_kenmerkmelding",
                            kenmerkParentKey : "mld_melding_key",
                            kenmerkWaarde: "mld_kenmerkmelding_waarde",
                            kenmerkKey: "mld_kenmerk_key",
                            kenmerkToonbaar: "mld_kenmerk_toonbaar",
                            currentKenmerkenSQL: currentKenmerkenSQL,
                            allKenmerkenSQL: allKenmerkenSQL,
                            requestQF: Request.Form,
                            isNew: isNew,
                            flexPath: "MLD/M",
                            tracking: true,
                            module: "MLD"
                          };
      if (hasFParam("nameprefix"))
      {
        kenmerkParams.nameprefix = getFParamSafe("nameprefix", "");
        kenmerkParams.extraserie = true;
      }
      var flextrack = saveFlexKenmerken(mld_key, kenmerkParams);
      if (copy || cont)
      {
        var sql = "SELECT mld_stdmelding_key FROM mld_melding WHERE mld_melding_key = " + mld_copy_key;
        var oRs = Oracle.Execute(sql);
        var old_stdmelding_key = oRs("mld_stdmelding_key").Value;
        oRs.Close();
        var flexsql = "SELECT k_old.mld_kenmerk_key k_old"
                    + "     , k_new.mld_kenmerk_key k_new"
                    + "  FROM mld_kenmerk     k_new"
                    + "     , mld_kenmerk     k_old"
                    + "     , mld_srtkenmerk  sk_new"
                    + "     , mld_srtkenmerk  sk_old"
                    + " WHERE k_new.mld_srtkenmerk_key = k_old.mld_srtkenmerk_key"
                    + "   AND k_new.mld_srtkenmerk_key = sk_new.mld_srtkenmerk_key"
                    + "   AND k_old.mld_srtkenmerk_key = sk_old.mld_srtkenmerk_key"
                    + "   AND sk_old.mld_srtkenmerk_key = sk_new.mld_srtkenmerk_key"
                    + "   AND COALESCE (k_new.mld_kenmerk_omschrijving, sk_new.mld_srtkenmerk_omschrijving) ="
                    + "       COALESCE (k_old.mld_kenmerk_omschrijving, sk_old.mld_srtkenmerk_omschrijving)"
                    + "   AND sk_new.mld_srtkenmerk_kenmerktype = sk_old.mld_srtkenmerk_kenmerktype"
                    + "   AND sk_new.mld_srtkenmerk_kenmerktype IN ('F', 'E', 'M')"
                    + "   AND k_old.mld_kenmerk_groep = k_new.mld_kenmerk_groep"
                    + "   AND (   (    k_new.mld_stdmelding_key IS NULL"
                    + "            AND k_new.mld_kenmerk_niveau = 'A')"
                    + "        OR (    k_new.mld_stdmelding_key = " + stdm_key
                    + "            AND k_new.mld_kenmerk_niveau = 'S')"
                    + "        OR (    k_new.mld_stdmelding_key = (SELECT s.mld_ins_discipline_key"
                    + "                                           FROM mld_stdmelding s"
                    + "                                          WHERE s.mld_stdmelding_key = " + stdm_key + ")"
                    + "            AND k_new.mld_kenmerk_niveau = 'D')"
                    + "        OR (    k_new.mld_stdmelding_key = (SELECT d.ins_srtdiscipline_key"
                    + "                                           FROM mld_stdmelding s, mld_discipline d"
                    + "                                          WHERE s.mld_ins_discipline_key = d.ins_discipline_key"
                    + "                                            AND s.mld_stdmelding_key = " + stdm_key + ")"
                    + "            AND k_new.mld_kenmerk_niveau = 'T'))"
                    + "   AND (   (    k_old.mld_stdmelding_key IS NULL"
                    + "            AND k_old.mld_kenmerk_niveau = 'A')"
                    + "        OR (    k_old.mld_stdmelding_key = " + old_stdmelding_key
                    + "            AND k_old.mld_kenmerk_niveau = 'S')"
                    + "        OR (    k_old.mld_stdmelding_key = (SELECT s.mld_ins_discipline_key"
                    + "                                           FROM mld_stdmelding s"
                    + "                                          WHERE s.mld_stdmelding_key = " + old_stdmelding_key + ")"
                    + "            AND k_old.mld_kenmerk_niveau = 'D')"
                    + "        OR (    k_old.mld_stdmelding_key = (SELECT d.ins_srtdiscipline_key"
                    + "                                           FROM mld_stdmelding s, mld_discipline d"
                    + "                                          WHERE s.mld_ins_discipline_key = d.ins_discipline_key"
                    + "                                            AND s.mld_stdmelding_key = " + old_stdmelding_key + ")"
                    + "            AND k_old.mld_kenmerk_niveau = 'T'))"
                    + "   AND k_old.mld_kenmerk_verwijder IS NULL"
                    + "   AND sk_old.mld_srtkenmerk_verwijder IS NULL"
                    + "   AND k_new.mld_kenmerk_verwijder IS NULL"
                    + "   AND sk_new.mld_srtkenmerk_verwijder IS NULL"
                    + "   AND BITAND(k_old.mld_kenmerk_wissen, 1) = 0";;
        CopyFlexFolders("MLD", "M", mld_copy_key, "M", mld_key, flexsql);
      }
  }

  // DIT KAN WELLICHT BINNEN DE CONDITIE VAN has_r_objs (dus minder vaak)?
  // Na het koppelen van de objecten aan de melding, en het opslaan van de kenmerken de conditiescore berekening uitvoeren.
  mld.process_mjb_score_effects(mld_key);

  var doneParams = { mld_key : mld_key, autoprint: false, warning: "", success: true, noShowToaster: L("lcl_mld_is_mldupd") };
  if (autoorder && (isNew || (old_mld_status == 2 && old_stdm != new_stdm)) && conceptstatus == 0)
      doneParams.autoorder = 1;

  var sjabl_opdr_key = -1;
  if (!isNew)
  {
    if (mldUpd.trackarray.length || flextrack.length)
    { // NB: de eerste regel wordt ook als notificatie (ipv automatisch fac_srtnotificatie_oms[MLDUPD]) gebruikt,
      // Vandaar hier bij uitzondering ook het meldingsnummer en stdmelding_omschrijving vermelden
      // Is quickfix voor AANS#20804

      var formattedID = stdm_info.ins_srtdiscipline_prefix+mld_key + " ("+ stdm_info.discipline_omschrijving + "/"+ stdm_info.stdmelding_omschrijving +")";
      mld.trackmeldingupdate(mld_key, L("lcl_mld_is_mldupdtrack").format(formattedID) + "\n" + mldUpd.trackarray.concat(flextrack).join("\n"));
    }

    // Voeg extra tracking toe als melding afgerond is.
    if (newvalafgerond == 1 && !mldUpd.oldjsvals["mld_melding_afgerond"])
      mld.trackmeldingafronden(mld_key, L("lcl_mld_is_mldafrtrack").format(formattedID));

    var new_disc  = getFParamInt("disc", old_disc);
    if (old_mld_status == 2 && old_disc != new_disc && S("mld_forward_if_active") == 0)
    { // Status blijft "Ingevoerd(2)". Zetten van de status genereert geen tracking en notificaties. Daarom daar zelf voor zorgen.
      mld.trackmeldingforward(mld_key); // Zorgt voor "MLDFWD" tracking en daarme "MLD2BO" notificaties via mld.notifybackoffice.
    }
  }
  else if (parent_key < 0)  // isNew, Doe wat speciale dingen voor nieuwe opdrachten (sjabloon of autoorder)
  {
    // deze is zich zelf bewust van het eventueel conceptmelding zijn en doet dan nog niks
    mld.nextworkflowstep(mld_key, -1, true);  // -1 = initial (the originating call)

    if (isTemplate)
    { // Voeg bij het kopieren van een sjabloonmelding ook alle opdrachten die bij de melding horen toe.
      var sql_o = "SELECT mo.mld_opdr_key"
                + "  FROM mld_melding mm"
                + "     , mld_opdr mo"
                + "     , fac_activiteit fa"
                + " WHERE mm.mld_melding_key = mo.mld_melding_key(+)"
                + "   AND mm.fac_activiteit_key = fa.fac_activiteit_key"
                + "   AND fa.fac_activiteit_xmlnode = 'melding'"
                + "   AND fa.fac_activiteit_eenheid = 5"
                + "   AND fa.fac_activiteit_key = " + fac_activiteit_key;
    }
    else
    { // Als er een activiteit is gevonden met een sjabloon opdracht (sjabl_opdr_key > 0)
      // dan moet er een nieuwe opdracht onder water aangemaakt worden met het sjabloon als voorbeeld
      var sql_o = "SELECT mo.mld_opdr_key"
                + "  FROM mld_disc_params dp, fac_activiteit fa, mld_opdr mo"
                + " WHERE dp.fac_activiteit_key = fa.fac_activiteit_key"
                + "   AND fa.fac_activiteit_xmlnode = 'opdracht'"
                + "   AND mo.fac_activiteit_key = fa.fac_activiteit_key"
                + "   AND dp.mld_ins_discipline_key = " + discipline_key;
    }
    var v_zetStatus = true;
    var oRs_o = Oracle.Execute(sql_o);
    while (!oRs_o.EOF)
    {
      sjabl_opdr_key = oRs_o("mld_opdr_key").Value;
      if ((sjabl_opdr_key > 0) || (isTemplate && sjabl_opdr_key === null))
      { // Eerst de melding op gaccepteerd zetten dan opdracht aanmaken
        /* FSN#15158/PF 13-2-2009 15:00:24*/
        // Zetten van de status op geaccepteerd en afhandelen van de tracking.
        // NB: Voor een sjabloonmelding zonder opdracht geldt sjabl_opdr_key=null. Dan wel de status van de melding wijzigen.
        //     Voor gewone opdrachten alleen als de melding ook opdrachten heeft.
        if (v_zetStatus) {
          mld.setmeldingstatus(mld_key, 4);
          v_zetStatus = false; // De meldingstatus hoeft maar 1 keeer gezet te worden.
        }
      }

      if (sjabl_opdr_key > 0)
      { 
        var sql_s = "SELECT mld_s_mld_opdr_key.nextval FROM DUAL";
        var oRs_s = Oracle.Execute(sql_s);
        var new_opdr = oRs_s(0).Value;
        oRs_s.Close();

        var sql_i = "INSERT INTO mld_opdr ("
                  + "mld_opdr_key"
                  + ", mld_opdr_module"
                  + ", mld_melding_key"
                  + ", mld_uitvoerende_keys"
                  + ", mld_typeopdr_key"
                  + ", mld_statusopdr_key"
                  + ", mld_standaardopdr_key"
                  + ", mld_opdr_omschrijving"
                  + ", mld_opdr_datumbegin"
                  + ", mld_opdr_einddatum"
                  + ", mld_opdr_werkzaamheden"
                  + ", mld_opdr_uren"
                  + ", mld_opdr_materiaal"
                  + ", mld_opdr_kosten"
                  + ", mld_opdr_contactpersoon"
                  + ", mld_opdr_geprint"
                  + ", mld_opdr_bedrijfopdr_volgnr"
                  + ", mld_opdr_uurloon"
                  + ", prs_perslid_key"
                  + ", prs_contactpersoon_key"
                  + ", cnt_contract_key"
                  + ", cnt_contract_dienst_key"
                  + ", prs_kostenplaats_key"
                  + ", mld_opdr_opmerking_fiat"
                  + ", mld_opdr_ordernr"
                  + ", mld_opdr_teverzenden"
                  + ", mld_opdr_opmerking)"
                  + " SELECT"
                  + " " + new_opdr
                  + ", mld_opdr_module"
                  + ", " + mld_key
                  + ", mld_uitvoerende_keys"
                  + ", mld_typeopdr_key"
                  + ", mld_statusopdr_key"
                  +   ", mld_standaardopdr_key"
                  + ", mld_opdr_omschrijving"
                  + ", mld_opdr_datumbegin"
                  + ", mld_opdr_einddatum"
                  + ", mld_opdr_werkzaamheden"
                  + ", mld_opdr_uren"
                  + ", mld_opdr_materiaal"
                  + ", mld_opdr_kosten"
                  + ", mld_opdr_contactpersoon"
                  + ", mld_opdr_geprint"
                  + ", mld_opdr_bedrijfopdr_volgnr"
                  + ", mld_opdr_uurloon"
                  + ", prs_perslid_key"
                  + ", prs_contactpersoon_key"
                  + ", cnt_contract_key"
                  + ", cnt_contract_dienst_key"
                  + ", prs_kostenplaats_key"
                  + ", mld_opdr_opmerking_fiat"
                  + ", mld_opdr_ordernr"
                  + ", mld_opdr_teverzenden"
                  + ", mld_opdr_opmerking"
                  + " FROM mld_opdr o"
                  + " WHERE o.mld_opdr_key = " + sjabl_opdr_key;

        Oracle.Execute(sql_i);

        // Kopiëren flexkenmerken
        // De regels in de tabel mld_kenmerkopdr kopiëren
        var sql_k = "INSERT INTO mld_kenmerkopdr ("
                  + " mld_opdr_key"
                  + ", mld_kenmerk_key"
                  + ", mld_kenmerkopdr_waarde)"
                  + " SELECT " + new_opdr
                  + ", mld_kenmerk_key"
                  + ", mld_kenmerkopdr_waarde"
                  + " FROM mld_kenmerkopdr"
                  + " WHERE mld_opdr_key = " + sjabl_opdr_key;
        Oracle.Execute(sql_k);

        // Copy de flex folders: CopyFlexFolders(oldbasepath, newbasepath, flexsql)
        // typeopdr and mld_kenmerk_key is for both orders, old (sjabloon) and new, the same

        var flexsql = "SELECT k_old.mld_kenmerk_key k_old"
                    + "     , k_old.mld_kenmerk_key k_new"
                    + "  FROM mld_srtkenmerk t"
                    + "     , mld_kenmerk k_old"
                    + "     , mld_opdr o_old"
                    + " WHERE o_old.mld_opdr_key = " + sjabl_opdr_key
                    + "   AND t.mld_srtkenmerk_kenmerktype IN ('F', 'E', 'M')"
                    + "   AND (k_old.mld_typeopdr_key = o_old.mld_typeopdr_key OR k_old.mld_typeopdr_key IS NULL)"
                    + "   AND k_old.mld_kenmerk_niveau IN ('P', 'O')"
                    + "   AND k_old.mld_kenmerk_verwijder IS NULL"
                    + "   AND k_old.mld_srtkenmerk_key = t.mld_srtkenmerk_key"
                    + "   AND t.mld_srtkenmerk_verwijder IS NULL"
                    + "   AND BITAND(k_old.mld_kenmerk_wissen, 1) = 0";
        CopyFlexFolders("MLD", "O", sjabl_opdr_key, "O", new_opdr, flexsql);
      }
      oRs_o.MoveNext();
    }
    oRs_o.Close();
  }

  if (!frontend && (S("mld_melding_autoprint") == 2 || (isNew && sjabl_opdr_key < 0 && S("mld_melding_autoprint") == 1)))
  { // S("mld_melding_autoprint"): 2-altijd, 1-aleen als er geen orders zijn.
    doneParams.autoprint = true;
  }
  // Klantspecifieke check functie (hookfunction) voor de invoer
  var pResult = new HookResult();
  if (!custfunc.mld_postsave(mld_key, pResult))
  {
    abort_with_warning(pResult.errmsg);
  }
}
else
{ // Eerst extra signaleringsvraag stellen daarna pas gegevens opslaan
  var doneParams = { doublecheck: true,
                     success: false,
                     urole: urole,
                     stdm_key: stdm_key,
                     ruimtekey: ruimtekey,
                     verdiepingkey: verdiepingkey,
                     gebouwkey: gebouwkey,
                     locatiekey: locatiekey,
                     obj_arr: obj_arr }
}

mld.unlock(mld_key);

Response.Write(JSON.stringify(doneParams));
%>
<% ASPPAGE_END(); %>
