<%@ LANGUAGE = JavaScript %>
<%  Server.ScriptTimeout=6000; %>
<% /*
     $Revision$
     $Id$

     File:               ins_inspect_start.asp
     Description:        Starten van de inspecties.
     Parameters:
         ins_keys        Array van objecten waarvan inspecties moeten worden gestart.
         srtcont_keys    Array van soort controles die moeten worden gestart.

     Context:            Inline actie ins_list.inc of actie ins_inspect_list
                         Resultaat van een submit is een json object

*/ %>

<%
var JSON_Result = true;
%>

<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../shared/save2db.inc" -->
<!-- #include file="../Shared/kenmerk_common.inc" -->
<!-- #include file="../Shared/discxalg3d.inc" -->
<!-- #include file="../API2/api2.inc" -->
<!-- #include file="ins.inc" -->
<!-- #include file="../mld/mld.inc" -->

<%
protectRequest.validateToken();
var mode = "show"; // mode must be defined because of use in model_mld_kenmerk.inc
var ins_key_arr = getFParamKeyArray("ins_keys");
var srtcont_key_arr = getFParamKeyArray("srtcont_key_arr", []);

var multi = ins_key_arr.length > 1;
var freeze = getFParamInt("freeze", 0) == 1;
var groupby = getFParamInt("groupby", 9);
var aantaltaken = getFParamInt("aantaltaken", 0);

var inflatiepct = S("mjb_inflation");
var inflatiefactor = 1 + (inflatiepct / 100);
var mjb_start_year = S("mjb_start_year");
var mjb_freeze_year = Math.max(S("mjb_freeze_year"), new Date().getFullYear());

var ingesloten = [];
var badbody;
var oldfreeze = false;
if (freeze && groupby < 9)
{
  var screenmode = getQParamInt("mode", 1); // Schermmode 1=Begroting (aankomende jaren) (=default), 2=Realisatie (huidige en lopende jaren, 3=Uitvoering (koppelen (uitvoerend) van taken aan een melding).
  var dist_key_arr = getFParamKeyArray("dist_key_arr", []); // District array
  var loc_key_arr = getFParamKeyArray("loc_key_arr", []); // Locatie array
  var bld_key_arr = getFParamKeyArray("bld_key_arr", []); // Gebouw array

  var disc_key_arr = getFParamKeyArray("disc_key_arr", []);
  var srtgroep_key_arr = getFParamKeyArray("srtgroep_key_arr", []);
  var srtdeel_key_arr = getFParamKeyArray("srtdeel_key_arr", []);
  var moredetail = getFParamInt("moredetail", 0);
  var srtgebouw_key_arr = getFParamKeyArray("srtgebouw_key_arr", []);
  var groep_str_arr = getFParamArray("groep_str_arr", []); // Groep
  var categorie_key_arr = getFParamKeyArray("categorie_key_arr", []); // Categorie
  var srtcontrole_key_arr = getFParamKeyArray("srtcontrole_key_arr", []); // Taak
  var frequentie_arr = getFParamIntArray("frequentie_arr", []); // Array met frequenties.
  var kp_key_arr = getFParamKeyArray("kp_key_arr", []); // Kostenplaats.
  var incbtw = false; // Voor het accorderen zijn de bedragen (freeze) zonder BTW nodig. Dus ALTIJD false meegeven;
  var showunfin = getFParamInt("showunfin", 0) == 1; // Alleen onvoltooide regels.
  var deel = getFParam("deel", ""); // Identieficatie

  // FORM score velden.
  var fitness_score1_from = getFParamInt("fitness_score1_from", -1);               // Conditie score van.
  var fitness_score1_through = getFParamInt("fitness_score1_through", -1);         // Conditie score t/m.
  var fitness_score1_from_neg = getFParamInt("fitness_score1_from_neg", -1);       // Negatieve afwijking conditie score van.
  var fitness_score1_through_neg = getFParamInt("fitness_score1_through_neg", -1); // Negatieve afwijking conditie score t/m.
  var fitness_score1_from_pos = getFParamInt("fitness_score1_from_pos", -1);       // Positieve afwijking conditie score van.
  var fitness_score1_through_pos = getFParamInt("fitness_score1_through_pos", -1); // Positieve afwijking conditie score t/m.
  var priority_score2_from = getFParamInt("priority_score2_from", -1);             // Prioriteitsscore van.
  var priority_score2_through = getFParamInt("priority_score2_through", -1);       // Prioriteitsscore t/m.

  // FORM status checkboxes.
  var mjbMoved  = getFParamInt("mjbMoved", 0) == 1; // Verschoven.
  var mjbFreezed = getFParamInt("mjbFreezed", 0) == 1; // In behandeling.
  var mjbXcped = getFParamInt("mjbXcped", 0) == 1; // Aangepast.

  // Start building the query to fetch all objects satisfying
  var mjbparams = { niveau: groupby,   // Het niveau (betekenis) van de keys (district(1), locatie(2), gebouw(3), discipline(4), groep(5), objectsoort(6), object(7))
                    keys: ins_key_arr,
                    scenario: 1,
                    fulldetails: true,
                    //actsit: actsit, // actsit alleen van invloed op scenario_key > 1.
                    mode: screenmode,
                    dist_key_arr: dist_key_arr,
                    loc_key_arr: loc_key_arr,
                    bld_key_arr: bld_key_arr,
                    disc_key_arr: disc_key_arr,
                    srtgroep_key_arr: srtgroep_key_arr,
                    srtdeel_key_arr: srtdeel_key_arr,
                    moredetail: moredetail,
                    srtgebouw_key_arr: srtgebouw_key_arr,
                    groep_str_arr: groep_str_arr,
                    categorie_key_arr: categorie_key_arr,
                    srtcontrole_key_arr: srtcontrole_key_arr,
                    frequentie_arr: frequentie_arr,
                    kp_key_arr: kp_key_arr,
                    incbtw: incbtw,
                    showunfin: showunfin,
                    inflatiefactor: inflatiefactor,
                    toyear: mjb_freeze_year,
                    groupby: 9, // Ik wil alle objecten opvragen.
                    deel: deel,
                    fitness_score1_from : fitness_score1_from,
                    fitness_score1_through : fitness_score1_through,
                    fitness_score1_from_neg : fitness_score1_from_neg,
                    fitness_score1_through_neg : fitness_score1_through_neg,
                    fitness_score1_from_pos : fitness_score1_from_pos,
                    fitness_score1_through_pos : fitness_score1_through_pos,
                    priority_score2_from : priority_score2_from,
                    priority_score2_through : priority_score2_through,
                    mjbMoved: mjbMoved,
                    mjbFreezed: mjbFreezed,
                    mjbXcped: mjbXcped,
                    jaren: [mjb_freeze_year],
                    freeze: true
                  };
  var mjblist_sql = ins.getmjblist_sql(mjbparams);
  // De mjblist_sql bevat nu alle objecten (ins_deel_key) van de aangevinkte regels uit het mjb overzicht en levert voor elk object de waarden voor de insert op.

  var result = {key: "", success: true, multi: multi, start: true };

  var oRs = Oracle.Execute(mjblist_sql);
  // Hier geen "user.anything_todo_or_abort(!oRs.eof);". We geven altijd een melding terug hoeveel taken er geaccodeerd zijn.

  var freeze_sql = "BEGIN ";
  while (!oRs.eof)
  {
    var ins_key = oRs("ins_deel_key").Value;
    var srtcont_key = oRs("ins_srtcontrole_key").Value;
    var ins_srtdeel_oms = oRs("ins_srtdeel_omschrijving").Value;
    var ins_srtcont_oms = oRs("ins_srtcontrole_omschrijving").Value;
    var ins_srtcont_info = oRs("ins_srtcontrole_info").Value;
    var nextdate = oRs("nextdate").Value != null? new Date(oRs("nextdate").Value) : null;
    var inspstatus = oRs("ins_deelsrtcontrole_status").Value;
    var kosten = oRs("freeze_bedrag").Value;
    var opm_has_higherprio = oRs("opm_has_higherprio").Value;
    ingesloten.push({ ins_key: ins_key,
                      srtcont_key: srtcont_key,
                      dlsrtcont_key: -1,
                      kosten: kosten,
                      ismjob: true,
                      srtdeel_oms: ins_srtdeel_oms,
                      srtcontr_oms: ins_srtcont_oms,
                      srtcontr_info: ins_srtcont_info
                    });

    if (inspstatus == 0)
      // Er is al een ingeplande inspectie. Deze kan nu gestart worden.
      // Status staat al op Gepland(0) en zal later op In behandeling(2) worden gezet zodat de wijziging ook getrackt gaat worden.
      // De prs_perslid_key pas ik niet aan. Aan de tracking, die verderop wordt aangemaakt, kan ik wel zien wie deaccordeerd/gefreezed heeft.
      freeze_sql += "UPDATE ins_deelsrtcontrole"
                  + "   SET ins_deelsrtcontrole_freezecost = " + kosten
                  + "     , ins_deelsrtcontrole_freezedate = TRUNC(TO_DATE(TO_CHAR(SYSDATE, 'DD-MON') || '-" + mjb_freeze_year + "', 'DD-MON-YYYY'), 'YEAR')"
                  + "     , ins_deelsrtcontrole_opmerking = " + safe.quoted_sql(opm_has_higherprio)
                  + (nextdate
                    ? "   , ins_deelsrtcontrole_datum_org = " + nextdate.toSQL(true)
                    : "")
                  + " WHERE ins_deel_key = " + ins_key
                  + "   AND ins_srtcontrole_key = " + srtcont_key
                  + "   AND ins_deelsrtcontrole_status = 0"
                  + "   AND ins_scenario_key = 1"
                  + ";";
    else
    {
      ins.testInspectInsert(ins_key, srtcont_key, 1);
      freeze_sql += "INSERT INTO ins_deelsrtcontrole(ins_deel_key"
                  + "                              , ins_srtcontrole_key"
                  + "                              , ins_deelsrtcontrole_status"
                  + "                              , prs_perslid_key"
                  + "                              , ins_deelsrtcontrole_freezecost"
                  + "                              , ins_deelsrtcontrole_freezedate"
                  + "                              , ins_deelsrtcontrole_opmerking"
                  + (nextdate
                    ? "                            , ins_deelsrtcontrole_datum_org"
                    : "")
                  + "                               )"
                  + "                        VALUES (" + ins_key
                  + "                              , " + srtcont_key
                  + "                              , 2"
                  + "                              , " + user_key
                  + "                              , " + kosten
                  + "                              , TRUNC(TO_DATE(TO_CHAR(SYSDATE, 'DD-MON') || '-" + mjb_freeze_year + "', 'DD-MON-YYYY'), 'YEAR')"
                  + "                              , " + safe.quoted_sql(opm_has_higherprio)
                  + (nextdate
                    ? "                            , " + nextdate.toSQL(true)
                    : "")
                  + "                               )"
                  + ";";
    }
    oRs.MoveNext();
  }
  oRs.Close();
  freeze_sql += " END;"

  if (ingesloten.length)
  {
    Oracle.Execute(freeze_sql);
  }

  for (var i = 0; i < ingesloten.length; i++)
  {
    var sql = "SELECT MAX(idsc.ins_deelsrtcontrole_key) max_idsc_key"
            + "  FROM ins_deelsrtcontrole idsc"
            + " WHERE idsc.ins_deel_key = " + ingesloten[i].ins_key
            + "  AND idsc.ins_srtcontrole_key = " + ingesloten[i].srtcont_key
            + "  AND idsc.ins_scenario_key = 1";
    var oRs_idsc = Oracle.Execute(sql);

    ingesloten[i].dlsrtcont_key = oRs_idsc("max_idsc_key").Value;
    oRs_idsc.Close();
  }
}
else
{
  var tobestart = 0;
  var dlsrtcont_key = -1;
  // Bepaal de objecten/delen in de selectie die
  // ook echt gestart kunnen of mogen worden.
  var ctrdisc_key = -1;
  if (srtcont_key_arr.length > 0)
  {
    for (var i = 0; i < ins_key_arr.length; i++)
    {
      dlsrtcont_key = -1;
      var ins_xcp_active_cost = S("ins_xcp_active_cost");
      var costarray = [];
      if (ins_xcp_active_cost & 1) costarray.push("COALESCE(xcp.ins_srtcontrole_kosten, 0)");
      if (ins_xcp_active_cost & 2) costarray.push("COALESCE(xcp.ins_srtcontrole_kosten2, 0)");
      if (ins_xcp_active_cost & 4) costarray.push("COALESCE(xcp.ins_srtcontrole_kosten3, 0)");
      if (ins_xcp_active_cost & 8) costarray.push("COALESCE(xcp.ins_srtcontrole_materiaal, 0)");
      var sqlcost = "";
      if (costarray.length > 0)
        sqlcost = "(" + costarray.join(" + ") + ") *";

      var sql = "SELECT idsc.ins_deelsrtcontrole_key"
              + "     , idsc.ins_deelsrtcontrole_status"
              + "     , EXTRACT(YEAR FROM idsc.ins_deelsrtcontrole_freezedate) freezedate"
              + "     , xcp.ctr_discipline_key"
              + "     , xcp.ins_srtcontrole_key"
              + "     , xcp.ins_srtcontrole_level"
              + "     , COALESCE (xcp.ins_deel_aantal *"
              + "             " + sqlcost
              + "                 (COALESCE(xcp.ins_srtcontrole_percentage, 100) / 100) *"
              + "                 POWER(" + inflatiefactor + " , " + mjb_freeze_year + " - EXTRACT(YEAR FROM SYSDATE))" // Bevriezen van het kalenderjaar S("mjb_freeze_year").
              + "              ,  0) bedrag" // Geen btw in bedrag/kosten die opgeslagen moet worden.
              + "     , xcp.ctr_ismjob"
              + "     , xcp.ins_srtcontrole_omschrijving"
              + "     , xcp.ins_srtcontrole_info"
              + "     , isd.ins_srtdeel_omschrijving"
              + "  FROM ins_deelsrtcontrole idsc"
              + "     , ins_srtdeel isd"
              + "     , ins_v_defined_inspect_xcp xcp"
              + " WHERE xcp.ins_srtcontrole_key = idsc.ins_srtcontrole_key(+)" // Er kan nog voor de eerste keer geinspecteerd moeten worden.
              + "   AND xcp.ins_deel_key = idsc.ins_deel_key(+)"
              + "   AND isd.ins_srtdeel_key = xcp.ins_srtdeel_key"
              + "   AND xcp.ins_deel_key = " + ins_key_arr[i]
              + "   AND xcp.ins_srtcontrole_key = " + srtcont_key_arr[i]
              + "   AND idsc.ins_scenario_key(+) = 1"
              + "   AND xcp.ins_scenario_key = 1"
              + " ORDER BY ins_deelsrtcontrole_datum DESC";
      var oRs = Oracle.Execute(sql);
      ctrdisc_key = oRs("ctr_discipline_key").Value;
      // Waarden moeten aanwezig zijn. Mocht dat niet zo zijn dan is er iets fout.
      var ins_deelsrtcontrole_status = oRs("ins_deelsrtcontrole_status").Value != null? oRs("ins_deelsrtcontrole_status").Value : -1; // Als er nog geen inspectie is geweest is de status -1.
      var ins_deelsrtcontrole_key = oRs("ins_deelsrtcontrole_key").Value;
      var freezedate = oRs("freezedate").Value;
      var ins_srtdeel_oms = oRs("ins_srtdeel_omschrijving").Value;
      var ins_srtcont_oms = oRs("ins_srtcontrole_omschrijving").Value;
      var ins_srtcont_info = oRs("ins_srtcontrole_info").Value;
      var kosten =  oRs("bedrag").Value;
      var ismjob = oRs("ctr_ismjob").Value == 1;
      oRs.Close();

      if (ins_deelsrtcontrole_status != -1 && ins_deelsrtcontrole_status != 6)
        dlsrtcont_key = ins_deelsrtcontrole_key;
      var this_ins = ins.func_enabled_deel(ins_key_arr[i],
                                           {srtcont_key: srtcont_key_arr[i],
                                            deelsrtcont_key: dlsrtcont_key
                                           });

      // Het laatste inspectierecord moet Gepland(0) of Verwerkt(6) (ins_deelsrtcontrole_status = -1) zijn, anders kan de inspectie niet gestart worden.
      if ((!freeze && this_ins.canInspStart) || (freeze && this_ins.canInspFreeze))
      { // Alle Arrays zijn even groot.
        ingesloten.push({ ins_key: ins_key_arr[i],
                          srtcont_key: srtcont_key_arr[i],
                          dlsrtcont_key: dlsrtcont_key,
                          inspectiestatus: ins_deelsrtcontrole_status,
                          kosten: kosten,
                          ismjob: ismjob,
                          srtdeel_oms: ins_srtdeel_oms,
                          srtcontr_oms: ins_srtcont_oms,
                          srtcontr_info: ins_srtcont_info
                         });
        tobestart++;
      }
    }
  }
  lcl.set_dialect(ctrdisc_key, "CTR_DISCIPLINE_KEY");
  mld.dialectIsSet = true;
  oldfreeze = (tobestart == 0 && ins_key_arr.length == 1 && ins_deelsrtcontrole_status == 2 && freezedate < mjb_freeze_year);
  badbody = (oldfreeze? L("lcl_shared_old_freeze").format(freezedate) : null);
  // Hier geen "user.anything_todo_or_abort(tobestart > 0, badbody);". We geven altijd een melding terug hoeveel taken er terug gezet zijn.

  var result = {key: "", success: true, multi: multi, start: true };

  if (!oldfreeze)
  {
    for (var i = 0; i < ingesloten.length; i++)
    { // Zetten van de status en afhandelen van de tracking van het starten.

      if (ingesloten[i].dlsrtcont_key < 0)
      { // Er is nog geen inspectie (ins_deelsrtcontrole) record aangemaakt. Eerst maar eens de waarden van de velden bepalen.
        // Als er al een inspectie is geweest kan er een volgende inspectiedatum berekend worden.
        var nextdate = null;
        if (ingesloten[i].inspectiestatus > -1 || !ingesloten[i].ismjob) // Bij periodieke taken kunnen we tegenwoordig de eerste inspectiedatum ook berkenen.
        { // Bereken de volgende orginele inspectiedatum (nextdate).
          // Alleen Active Situatie (AS) soort controle's kunnen gestart worden dus voor scenario key moet 1 genomen worden.
          // Bij mjob kan de laatste inspectie niet succesvol zijn. Dus ins.nextcyclusdate(ins_key, srtcont_key, scen_key) kan ik hier niet gebruiken.

          // func_get_nextdate kijkt naar en houd rekening met onderstaande 4 punten.
          // Er is al een inspectie geweest als ik binnen deze if ben.
          // Nummer 4 komt daarom niet voor want dan was je in de else beland.
          // 1) De laatste inspectie is succesvol voltooid: De volgende met ins.nextcyclusdate() te berekenen.
          // 2) De laatste inspectie is NIET succesvol voltooid. De volgende is in het freeze jaar.
          // 3) De laatste inspectie is geaccordeerd/bevroren/gestart(2): De volgende is een periode verder als het freeze jaar.
          // 4) Er is geen inspectie geweest of gestart.
          nextdate = ins.func_get_nextdate(ingesloten[i].ins_key, ingesloten[i].srtcont_key, 1, {mjob: ingesloten[i].ismjob});
        }
        //else MJOB: Er zijn nog geen mjob inspecties geweest voor dit object. Dit wordt de eerste mjob inspectie.
        //           Volgende mjob inspectiedatum kun je niet berekenen en is dus onbekend (leeg)

        // Plandatum blijft leeg.
        var fields = [ { dbs: "ins_deelsrtcontrole_key",        typ: "key",      seq: "ins_s_ins_deelsrtcontrole_key" },
                       { dbs: "ins_deel_key",                   typ: "key",      val: ingesloten[i].ins_key },
                       { dbs: "ins_srtcontrole_key",            typ: "key",      val: ingesloten[i].srtcont_key },
                       { dbs: "ins_deelsrtcontrole_status",     typ: "key",      val: 2 },
                       { dbs: "prs_perslid_key",                typ: "key",      val: user_key },
                       { dbs: "ins_deelsrtcontrole_datum_org",  typ: "datetime", val: (nextdate? nextdate : null) }
                     ];
      }
      else
      {
        var fields = [];
      }

      // Als je mag bevriezen (canInspFreeze) dan zijn er kosten aanwezig in het jaar mjb_freeze_year.
      if (freeze && (ingesloten[i].kosten >= 0))
      { // Uitzoeken of de taak door een hogere prio taak wordt uitgevoerd (kosten zijn 0 in het overzicht).
        // In dat geval zijn de freeze kosten 0 en plaatsen we een opmerking.
        // Voor MJOB is de interval modus actief.
        // Neem de Active Situatie (AS) (Scenario = 1).
        var sql = "SELECT insp.ins_deelsrtcontrole_key"
                + "     , insp.ins_srtcontrole_level"
                // Bepaling in welk jaar er een inspectie is gepland.
                // 1) In het jaar dat er nog een geaccordeerde/bevroren(2) inspectie actief is.
                // 2) In het jaar van de plandatum.
                // 3) In het jaar van de startdatum.
                // 4) a) Laatste inspectie is NULL (eerste inspectie moet nog komen) en het is een Controle(1).
                //       Volgende inspectie is in het freeze jaar.
                //    b) Laatste inspectie is NULL (eerste inspectie moet nog komen) en het is een Vervanging(2) of Certificering(3).
                //       Nextdate is na het freeze jaar?
                //       Ja)  Vorige inspectie ligt na het start jaar en ligt niet in het aanmaak jaar?
                //            Ja)  Volgende inspectie is in het freeze jaar.
                //            Nee) Volgende inspectie is het jaar van de nextdate.
                //       Nee) De laatst ingeplande inspectie (nextdate) is na of in het start jaar?
                //            Ja)  Volgende inspectie is in het freeze jaar.
                //            Nee) Volgende inspectie is in het jaar "nextdatum + periode".
                //    c) Laatste inspectie is niet NULL. Er is al 1 of meerdere keren geinspecteerd.
                //       Ligt de laatst ingeplande inspectie (nextdate) na dit jaar?
                //       Ja)  Volgende inspectie is het jaar van de nextdate (in de toekomst).
                //       Nee) Volgende inspectie is in het freeze jaar.
                + "     , CASE"
                  + "     WHEN"
                  + "       EXTRACT(YEAR FROM "
                  + "         COALESCE(CASE"                   // Taak is geaccordeerd (gefreezed). Freeze jaar is het huidige (vervangings)jaar.
                  + "                  WHEN insp.ins_deelsrtcontrole_status IN (2, 3)"
                  + "                  THEN insp.ins_deelsrtcontrole_freezedate"
                  + "                  ELSE NULL"
                  + "                  END"
                  + "                , insp.plandatum"
                  + "                , CASE WHEN insp.laatste IS NULL THEN insp.ins_srtcontroledl_xcp_startdat ELSE NULL END"
                  + "                , CASE"
                  + "                  WHEN insp.laatste IS NULL AND insp.ctr_controle_type = 1"  // 1: Controle.
                  + "                  THEN TO_DATE('" + mjb_freeze_year + "', 'YYYY')"
                  + "                  WHEN insp.laatste IS NULL AND insp.ctr_controle_type != 1" // 2: Vervanging, 3: Certificering.
                  + "                  THEN"                   // Er is nog geen inspectie geweest
                  + "                    CASE"
                  + "                    WHEN EXTRACT(YEAR FROM insp.inspectie_next0) > " + mjb_freeze_year
                  + "                    THEN"                 // Nextdate is na de freeze datum.
                  + "                      CASE"
                  + "                      WHEN EXTRACT(YEAR FROM ADD_MONTHS(insp.inspectie_next0, -1 * 12 * insp.ins_srtcontrole_periode)) >= " + mjb_start_year + " AND"
                  + "                           EXTRACT(YEAR FROM ADD_MONTHS(insp.inspectie_next0, -1 * 12 * insp.ins_srtcontrole_periode)) != EXTRACT(YEAR FROM insp.ins_deel_aanmaak)"
                  + "                      THEN TO_DATE('" + mjb_freeze_year + "', 'YYYY')"     // Vorige inspectie ligt tussen start en freeze jaar (Nu ligt er ook tussen).
                  + "                      ELSE insp.inspectie_next0"
                  + "                      END"
                  + "                    ELSE"                 // Nextdate is voor of in het freeze jaar.
                  + "                      CASE"
                  + "                      WHEN EXTRACT(YEAR FROM insp.inspectie_next0) >= " + mjb_start_year
                  + "                      THEN TO_DATE('" + mjb_freeze_year + "', 'YYYY')"                           // Nextdate tussen start en freeze jaar.
                  + "                      ELSE ADD_MONTHS(insp.inspectie_next0, 12 * insp.ins_srtcontrole_periode)"  // Nextdate voor het start jaar.
                  + "                      END"
                  + "                    END"
                  + "                  ELSE"                   // Laatste IS NOT NULL. Er is al een inspectie geweest.
                  + "                    CASE"
                  + "                    WHEN EXTRACT(YEAR FROM insp.inspectie_next0) > EXTRACT(YEAR FROM SYSDATE)"
                  + "                    THEN insp.inspectie_next0"                             // Volgende inspectie is in de toekomst.
                                                                                                // Geaccordeerde laatste inspectie wordt in het begin al afgevangen.
                                                                                                // en niet hier zoals bij org_nextdate in functie getmjblist_sql.
                  + "                    ELSE TO_DATE('" + mjb_freeze_year + "', 'YYYY')"       // Laatst ingeplande inspectie is nog steeds niet uitgevoerd. Dus opnieuw in het freeze jaar tonen zodat deze daar gefreezed kan worden.
                  + "                    END"
                  + "                  END)) = " + mjb_freeze_year
                  + "     THEN 1"
                  + "     ELSE 0"
                  + "     END isFreezeYear"
                + "  FROM ("
                + "        SELECT xcp.ins_deel_key"
                + "             , xcp.ins_srtcontrole_key"
                + "             , idsc.ins_deelsrtcontrole_key"
                + "             , xcp.ctr_discipline_key"
                + "             , xcp.ins_srtcontrole_periode"
                + "             , xcp.ins_deel_aanmaak"
                + "             , xcp.ctr_controle_type"
                + "             , idsc.ins_deelsrtcontrole_status"
                + "             , idsc.ins_deelsrtcontrole_freezedate"
                + "             , idsc.ins_deelsrtcontrole_plandatum plandatum"
                + "             , ins_srtcontroledl_xcp_startdat"
                + "             , xcp.ins_srtcontrole_level"
                + "             , ins.nextcyclusdate(xcp.ins_deel_key, xcp.ins_srtcontrole_key, 1, 0) inspectie_next0"
                + "             , (SELECT MAX(idsc2.ins_deelsrtcontrole_datum)"
                + "                  FROM ins_deelsrtcontrole idsc2"
                + "                 WHERE idsc2.ins_deel_key = " + ingesloten[i].ins_key
                + "                   AND idsc2.ins_srtcontrole_key = xcp.ins_srtcontrole_key"
                + "                   AND idsc2.ins_scenario_key = 1) laatste"
                + "          FROM ins_deelsrtcontrole idsc"
                + "             , ins_v_defined_inspect_xcp xcp"
                + "         WHERE xcp.ins_srtcontrole_key = idsc.ins_srtcontrole_key(+)" // Er kan nog voor de eerste keer geinspecteerd moeten worden.
                + "           AND xcp.ins_srtcontrole_key = xcp.ins_srtcontrole_key"
                + "           AND xcp.ins_deel_key = " + ingesloten[i].ins_key
                + "           AND idsc.ins_deel_key(+) = " + ingesloten[i].ins_key
                + "           AND idsc.ins_scenario_key(+) = 1"
                + "           AND xcp.ins_scenario_key = 1"
                + "           AND xcp.ctr_ismjob = " + (ingesloten[i].ismjob? "1" : "0")
                + "           AND (idsc.ins_deelsrtcontrole_key IS NULL OR"
                  + "              idsc.ins_deelsrtcontrole_key = (SELECT MAX(idsc2.ins_deelsrtcontrole_key)"
                  + "                                                FROM ins_deelsrtcontrole idsc2"
                  + "                                               WHERE idsc2.ins_deel_key = " + ingesloten[i].ins_key
                  + "                                                 AND idsc2.ins_srtcontrole_key = xcp.ins_srtcontrole_key"
                  + "                                                 AND idsc2.ins_scenario_key = 1"
                  + "                                             ))"
                // Zichtzelf uitsluiten.
                + "           AND xcp.ins_srtcontrole_key != " + ingesloten[i].srtcont_key
                // Alleen soort controles met een lager level opleveren.
                + "           AND xcp.ins_srtcontrole_level < (SELECT isc.ins_srtcontrole_level"
                + "                                              FROM ins_srtcontrole isc"
                + "                                              WHERE isc.ins_srtcontrole_key = " + ingesloten[i].srtcont_key + ")"
                + "           AND xcp.ins_srtcontrole_periode > 0" // Alleen actieve taken.
                + "       ) insp"
                + " ORDER BY isFreezeYear DESC";
        var oRs = Oracle.Execute(sql);
        var has_higherprio = !oRs.eof && oRs("isFreezeYear").Value == 1; // Is er een hoger prio soort controle in het freeze jaar?
        oRs.Close();

        fields.push( { dbs: "ins_deelsrtcontrole_freezecost", typ: "float",    val: (has_higherprio? 0 : ingesloten[i].kosten) } );
        fields.push( { dbs: "ins_deelsrtcontrole_freezedate", typ: "datetime", val: new Date(mjb_freeze_year, 0, 1) } ); // Freezedate eerste dag van freeze year.
        // Als er een hoger prio soort controle aanwezig is in het freeze jaar, dan een opmerking toevoegen.
        if (has_higherprio)
          fields.push( { dbs: "ins_deelsrtcontrole_opmerking", typ: "varchar", val: L("lcl_mjb_performed_high") } );
      }


      if (ingesloten[i].dlsrtcont_key < 0)
      { // Inspectie (ins_deelsrtcontrole) record aanmaken.
        ins.testInspectInsert(ingesloten[i].ins_key, ingesloten[i].srtcont_key, 1);
        var insIns = buildInsert("ins_deelsrtcontrole", fields);
        ingesloten[i].dlsrtcont_key = insIns.sequences["ins_deelsrtcontrole_key"];
        var err = Oracle.Execute(insIns.sql, true);
        if (err.friendlyMsg)
        {
          result.warning = err.friendlyMsg;
          result.success = false;
        }
      }
      else
      { // Inspectie (ins_deelsrtcontrole) record aanpassen.
        var insUpd = buildTrackingUpdate("ins_deelsrtcontrole", " ins_deelsrtcontrole_key = " + ingesloten[i].dlsrtcont_key, fields);

        // Velden voor het bevriezen/accorderen opslaan.
        var err = Oracle.Execute(insUpd.sql, true);
        if (err.friendlyMsg)
          abort_with_warning(err.friendlyMsg);

        // Tracken van de freezedate en freezedate hoeft niet. Bevriezen/Accorderen gebeurt eenmalig en dan worden de freeze velden gevuld.
        // Het bevriezen/accorderen zelf wordt (hieronder) met het zetten van de status op Gestart(2) getrackt.
      }
    }
  }
}

var aantalmld = 0;
if (!oldfreeze)
{
  for (var i = 0; i < ingesloten.length; i++)
  { // Zetten van de status en afhandelen van de tracking en notificatie van het starten.
    ins.setinspectstatus(ingesloten[i].dlsrtcont_key, 2); // In behandeling(2)

    // Melding aanmaken bij bevriezen van taak als setting op internal staat.
    // De setting "mjb_default_stdmelding" is met FCLT#52905 verwijderd.
    // Controleren of er een automatische een melding moet worden aangemaakt.
    // Voor zowel periodieke taken als mjob taken kunnen er tegenwoordig automatisch taken aangemaakt worden. Dus altijd controleren.
    // Bij MJOB melding aanmaken kan ook via het MJOB-Uitvoering scherm met de actie "Uitvoeren".
    sql = "SELECT di.mld_stdmelding_key" // In de view ins_v_defined_inspect is dit de COALESCE van ins_srtcontrole.mld_stdmelding_key en ctr_disc_params.mld_stdmelding_key.
        + "     , di.prs_kostenplaats_key"
        + "  FROM ins_deelsrtcontrole idsc"
        + "     , ins_srtcontrole isc"
        + "     , ins_tab_discipline itd"
        + "     , ins_v_defined_inspect di"
        + "     , mld_stdmelding std"
        + " WHERE idsc.ins_srtcontrole_key = isc.ins_srtcontrole_key"
        + "   AND idsc.ins_scenario_key = isc.ins_scenario_key"
        + "   AND isc.ctr_discipline_key = itd.ins_discipline_key"
        + "   AND isc.ins_srtcontrole_key = di.ins_srtcontrole_key"
        + "   AND idsc.ins_deel_key = di.ins_deel_key"
        + "   AND di.mld_stdmelding_key = std.mld_stdmelding_key(+)"
        + "   AND std.mld_stdmelding_verwijder IS NULL"                                                        // Alleen actuele stdmeldingen.
        + "   AND (std.mld_stdmelding_vervaldatum IS NULL OR std.mld_stdmelding_vervaldatum > TRUNC(SYSDATE))" // Alleen actuele stdmeldingen.
        + "   AND idsc.ins_deelsrtcontrole_key = " + ingesloten[i].dlsrtcont_key;
    oRs = Oracle.Execute(sql);
    var mld_stdmelding_key = -1;
    var prs_kostenplaats_key = -1;
    if (!oRs.eof)
    {
      mld_stdmelding_key = oRs("mld_stdmelding_key").Value || -1;
      prs_kostenplaats_key = oRs("prs_kostenplaats_key").Value || -1;
    }
    oRs.Close();

    if (mld_stdmelding_key > 0)
    { // Er is een mld_stdmelding_key bekend. Nu melding aanmaken (1-op-1 relatie).
      var stdm_info = mld.mld_stdmeldinginfo(mld_stdmelding_key);

      var loc_key = -1;
      var bld_key = -1;
      var flr_key = -1;
      var room_key = -1;
      var alg_onroerendgoed_keys = -1;
      sql = "SELECT alg_locatie_key,"
          + "       alg_gebouw_key,"
          + "       alg_verdieping_key,"
          + "       alg_ruimte_key"
          + "  FROM ins_v_deelenonderdeel isd, alg_v_allonroerendgoed alg"
          + " WHERE ins_deel_key = " + ingesloten[i].ins_key
          + "   AND alg_onroerendgoed_keys = isd.ins_alg_ruimte_key"
          + "   AND isd.ins_alg_ruimte_type = 'R'"
      oRs = Oracle.Execute(sql);
      if (!oRs.Eof)
      {
          loc_key = oRs("alg_locatie_key").Value;
          bld_key = oRs("alg_gebouw_key").Value;
          flr_key = oRs("alg_verdieping_key").Value;
          room_key = oRs("alg_ruimte_key").Value;

          if (room_key > 0)
            alg_onroerendgoed_keys = room_key;
          else if (flr_key > 0)
            alg_onroerendgoed_keys = flr_key;
          else if (bld_key > 0)
            alg_onroerendgoed_keys = bld_key;
      }
      oRs.Close();

      if (prs_kostenplaats_key == -1 && bld_key > 0)
      {
        sql = "SELECT prs_kostenplaats_key"
            + "  FROM alg_gebouw"
            + " WHERE alg_gebouw_key = " + bld_key;
        oRs = Oracle.Execute(sql);
        if (!oRs.Eof)
          prs_kostenplaats_key = oRs("prs_kostenplaats_key").Value;
        oRs.Close();
      }

      var mld_subject;
      switch(S("mjb_approvedmelding_description")) {
        case 2: mld_subject = ingesloten[i].srtcontr_oms; break;
        case 3: mld_subject = ingesloten[i].srtcontr_oms + " (" + ingesloten[i].srtdeel_oms + ")"; break;
        case 1: // 1 = default
        default: mld_subject = ingesloten[i].srtdeel_oms; break;
      }

      sql = "SELECT sm.mld_stdmelding_default_disc"
          + "  FROM mld_stdmelding sm"
          + " WHERE sm.mld_stdmelding_key = " + mld_stdmelding_key;
      oRs = Oracle.Execute(sql);
      var mld_stdmelding_default_disc = oRs("mld_stdmelding_default_disc").Value || "NULL";
      oRs.Close();

      sql = "BEGIN ctr.taak_naar_ter_uitvoering(" + mld_stdmelding_key
          + "                                 , " + safe.quoted_sql(mld_subject, 200)
          + "                                 , " + safe.quoted_sql(ingesloten[i].srtcontr_info)
          + "                                 , " + prs_kostenplaats_key
          + "                                 , " + user_key
          + "                                 , " + mld_stdmelding_default_disc
          + "                                 , " + loc_key
          + "                                 , " + alg_onroerendgoed_keys
          + "                                 , " + ingesloten[i].ins_key
          + "                                 , " + ingesloten[i].dlsrtcont_key
          + "                                  );"
          + " END;"
      Oracle.Execute(sql);
      aantalmld++;

      // De taak ter uitvoering zetten en afhandelen van de tracking en notificatie van het uitvoeren.
      ins.setinspectstatus(ingesloten[i].dlsrtcont_key, 3); // Ter uitvoering(3)
    }

    result.key += (i > 0? "," : "") + ingesloten[i].dlsrtcont_key;
  }
}

if (oldfreeze)
{ // Er is nog een onafgeronde taak voor het begrotingsjaar/freezeyear.
  result.message = badbody;
}
else if (ingesloten.length < aantaltaken)
{ // Niet alle taken zijn geaccordeerd of ter uitvoering gezet.
  result.message = (ingesloten.length - aantalmld) == 1? L("lcl_mjb_freeze_mes_1").format(aantaltaken) : L("lcl_mjb_freeze_mes_n").format(ingesloten.length - aantalmld, aantaltaken);
  if (aantalmld > 0)
    result.message += "\n" + (aantalmld == 1? L("lcl_mjb_execute_mes_1") : L("lcl_mjb_execute_mes_n").format(aantalmld));
}
else
{ // Alle taken zijn geaccordeerd of ter uitvoering gezet.
  result.toaster = L("lcl_mjb_freezing_completed");
}
Response.Write(JSON.stringify(result));
%>
<% ASPPAGE_END(); %>
