<%@language = "javascript" %>
<% Server.ScriptTimeout=600; %>
<% /*
     $Revision$
     $Id$

     File:           mjb_search_list.asp
     Description:
     Parameters:

     Context:

     Note:

*/ %>
<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../Shared/resultset_table_v2.inc" -->
<!-- #include file="../alg/alg.inc" -->
<!-- #include file="../ins/ins.inc" -->
<%
FCLTHeader.Requires({plugins: ["jQuery"],
                        js  : ["jquery-ui.js", "../ins/ins_list.js", "../mjb/mjb_search_list.js"]}); // Voor slepen en acties.

var urole = getQParamSafe("urole", "");   // Indien niet meegegeven, veronderstel dan frontend gebruik
var mode = 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 ins_score_enabled = S("ins_score_enabled") == 1;
var mjb_show_srt_with_tasks = S("mjb_show_srt_with_tasks") == 1;
var scenario = getQParamInt("scenario", 1); // Scenario

// FORM parameters: de waarde indien aanwezig, anders null
// Vaak is een lege selectie ook een -1, dus dan is-ie wel aanwezig, maar hoeft niet
// als filter te worden toegepast. Dan is null dus gelijk aan -1, qua betekenis,
// Vandaar dat een default van -1 ipv null ook mag
// In eerste instantie identificeren we elk veld gewoon 1-op-1.
var outputmode = getQParamInt("outputmode", 0); //  0 = screen, 1 = print, 2 = excel etc
var print = (outputmode == 1 || outputmode == 5);
var excel = (outputmode == 2 || outputmode == 6);
var showall = getQParamInt("showall", 0) == 1;

// Er zijn zeker enkele INSUSE én CTRUSE/CTRSEN rechten nodig.
// Er zijn zeker INSUSE rechten nodig.
// mode 1: Daarnaast zijn er CTRUSE/CTRSEN rechten nodig.
// mode 3: Daarnaast zijn er CTRBOF rechten nodig.
if (mode == 1)
{
  var authparamsINSUSE = user.checkAutorisation("WEB_INSUSE");
  var authparamsCTRUSESEN = user.checkAutorisation(["WEB_CTRUSE", "WEB_CTRSEN"]);
}
else if (mode == 3)
  var authparamsCTRBOF = user.checkAutorisation("WEB_CTRBOF");
var authparamsCTRUSE = user.checkAutorisation("WEB_CTRUSE", true);
var authparamsCTRBOF = user.checkAutorisation("WEB_CTRBOF", true);
var authparamsCTRSEN = user.checkAutorisation("WEB_CTRSEN", true);
// Voor mode 3 heb je in ieder geval ook CTRBOF rechten nodig.

var hasWriteCTRSEN = authparamsCTRSEN && authparamsCTRSEN.ALGwritelevel < 9 && authparamsCTRSEN.PRSwritelevel < 9;
var hasWriteCTRUSESEN = authparamsCTRUSESEN && authparamsCTRUSESEN.ALGwritelevel < 9 && authparamsCTRUSESEN.PRSwritelevel < 9;

var hasReadCTRUSE = authparamsCTRUSE && authparamsCTRUSE.ALGreadlevel < 9 && authparamsCTRUSE.PRSreadlevel < 9;
var hasReadCTRBOF = authparamsCTRBOF && authparamsCTRBOF.ALGreadlevel < 9 && authparamsCTRBOF.PRSreadlevel < 9;
var hasReadCTRSEN = authparamsCTRSEN && authparamsCTRSEN.ALGreadlevel < 9 && authparamsCTRSEN.PRSreadlevel < 9;
// Als ik alleen CTRUSE/CTRBOF read rechten heb dan mag ik alleen de Actuele situatie (scenario = 1) zien.
// Als ik alleen CTRSEN read rechten heb dan mag ik alleen de Scenario's (scenario > 1) zien.
user.anything_todo_or_abort(((hasReadCTRUSE || hasReadCTRBOF) && scenario == 1) || (hasReadCTRSEN && scenario > 1));

// Rechten om exception (xcp) waarden van de inspectie/taak te kunnen zien en om details van het object te kunnen zien.
var authparamsINSMAN = user.checkAutorisation("WEB_INSMAN", true);
var hasReadINSMAN = authparamsINSMAN && authparamsINSMAN.ALGreadlevel < 9 && authparamsINSMAN.PRSreadlevel < 9;
var hasWriteINSMAN = authparamsINSMAN && authparamsINSMAN.ALGwritelevel < 9 && authparamsINSMAN.PRSwritelevel < 9;

// Rechten om alg (locatie) details te kunnen zien.
var authparamsALGUSE = user.checkAutorisation("WEB_ALGUSE", true);
var hasReadALGUSE = authparamsALGUSE && authparamsALGUSE.ALGreadlevel < 9 && authparamsALGUSE.PRSreadlevel < 9;

var authparamsALGMAN = user.checkAutorisation("WEB_ALGMAN", true);
var hasReadALGMAN = authparamsALGMAN && authparamsALGMAN.ALGreadlevel < 9 && authparamsALGMAN.PRSreadlevel < 9;

var authparamsMLDBOF = user.checkAutorisation("WEB_MLDBOF", true);
var hasReadMLDBOF = authparamsMLDBOF && authparamsMLDBOF.ALGreadlevel < 9 && authparamsMLDBOF.PRSreadlevel < 9;

var mjb_start_year = S("mjb_start_year");
var mjb_freeze_year = Math.max(S("mjb_freeze_year"), new Date().getFullYear());
var mjb_show_years = S("mjb_show_years");

var groupby = getQParamInt("groupby");  // kan obv filtering nog wijzigen verderop
var fulldetails = (groupby == 9); // Geen aggregate, dan kun je van alles manipuleren
var fromyear = getQParamInt("fromyear", new Date().getFullYear());
var toyear = (mode == 3)? mjb_freeze_year : getQParamInt("toyear", new Date().getFullYear());

var deel = getQParam("deel", ""); // Identieficatie
var categorie_key_arr = getQParamKeyArray("categorie", []); // Categorie
var reg_key_arr = getQParamKeyArray("regiokey", []); // Regio
var dist_key_arr = getQParamKeyArray("districtkey", []); // District
var loc_key_arr = getQParamKeyArray("locatiekey", []); // Locatie
var bld_key_arr = getQParamKeyArray("gebouwkey", []); // Gebouw
var disc_key_arr = getQParamKeyArray("disc", []);
var srtgroep_key_arr = getQParamKeyArray("srtgroep", []);
var srtdeel_key_arr = getQParamKeyArray("srtdeel", []);
var srtgebouw_key_arr = getQParamKeyArray("srtgebouw", []);
var groep_str_arr = getQParamStringArray("groep", []); // Groep (tekst).
var srtcontrole_key_arr = getQParamKeyArray("srtcontrole", []); // Taak
var frequentie_arr = getQParamKeyArray("frequentie", []); // Array met frequenties.
var kp_key_arr = getQParamKeyArray("account", []); // Kostenplaats
var verantw_key = getQParamInt("verantw", -1); // Gebouw verantwoordelijke
var beheerder_key = getQParamInt("sBeh_key", -1); // Beheerder
var incbtw = getQParamInt("incbtw", 0) == 1; // Lijst inclusief BTW weergeven.
var inflatiepct = S("mjb_inflation");
var inflatiefactor = 1 + (inflatiepct / 100);

var actsit = getQParamInt("actsit", 0) == 1; // Ook actuele situatie.
var showunfin = getQParamInt("showunfin", 0) == 1; // Alleen onvoltooide regels.
var mjbshowempty = getQParamInt("mjbshowempty", 0) == 1; // Ook lege regels.

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

// FORM status checkboxes.
var mjbMoved  = getQParamInt("mjbMoved", 0) == 1; // Verschoven.
var mjbFreezed = getQParamInt("mjbFreezed", 0) == 1; // In behandeling.
var mjbXcped = getQParamInt("mjbXcped", 0) == 1; // Aangepast.
var mjbStatus2 = getQParamInt("mjbStatus2", 0) == 1; // Geaccordeerd.
var mjbStatus3 = getQParamInt("mjbStatus3", 0) == 1; // Ter uitvoering.

// Ingrijpen om onlogische keuzes te corrigeren:
// Als de groepering grover is dan de filtering ontstaat een misleidend overzicht
// Dat kunnen we verhelpen door de gekozen groepering zelf te verfijnen tot het filterniveau
if ((groupby == 4 || groupby == 5) && srtdeel_key_arr.length > 0) groupby = 6;
if (groupby == 4 && srtgroep_key_arr.length > 0) groupby = 5;
if ((groupby == 1 || groupby == 2) && bld_key_arr.length > 0) groupby = 3;
if (groupby == 1 && loc_key_arr.length > 0) groupby = 2;

// Feature: als een groepering wordt gekozen en tevens gefilterd wordt op dat item,
// dan zou je dus altijd precies 1 record krijgen. Beter is het dan om extra detail
// te presenteren voor het gekozen item. Dit is dan detail van de andere dimensie:
// filter/groepeer op soort -> plaatsdetails erbij
// filter/groepeer op plaats -> soortonderverdeling erbij
// tevens: als je exporteert (ouputmode > 0) dan tonen we ook plaatsdetails
var moredetail_plaats = ((groupby == 1 && dist_key_arr.length > 0) ||
                         (groupby == 2 && loc_key_arr.length > 0) ||
                         (groupby == 3 && bld_key_arr.length > 0));
var moredetail_soort = ((groupby == 4 && disc_key_arr.length > 0) ||
                        (groupby == 5 && srtgroep_key_arr.length > 0) ||
                        (groupby == 6 && srtdeel_key_arr.length > 0) ||
                          outputmode > 0);
var moredetail = (moredetail_plaats ? 1 : (moredetail_soort ? 2 : 0));

var ctrdisc_key = getQParamInt("ctrdisc_key", -1); // Ctrdiscipline
if (ctrdisc_key > 0)
    lcl.set_dialect(ctrdisc_key, "INS_TAB_DISCIPLINE_KEY");

var filterParams = { deel: (deel != ""? deel : null),
                     categorie_key_arr: categorie_key_arr,
                     reg_key_arr: reg_key_arr,
                     dist_key_arr: dist_key_arr,
                     loc_key_arr: loc_key_arr,
                     bld_key_arr: bld_key_arr,
                     disc_key: disc_key_arr,
                     insgroup_key: srtgroep_key_arr,
                     objsrt_key_arr: srtdeel_key_arr,
                     srtgebouw_key_arr: srtgebouw_key_arr,
                     verantw_key: verantw_key,
                     beheerder_key: beheerder_key,
                     kp_key_arr: kp_key_arr,
                     mjbgroup: groupby,
                     mjbtoyear: toyear,
                     mjbscgroep: groep_str_arr.join(","),
                     mjbsrtcontr: srtcontrole_key_arr.join(","),
                     mjbinfl_pct: inflatiepct,
                     mjbfreq: frequentie_arr.join(","),
                     mjbincbtw: incbtw,
                     mjbscenario: scenario,
                     mjbactsit: actsit,
                     mjbshowunfin: showunfin,
                     mjbshowempty: mjbshowempty,
                     mjbMoved: mjbMoved,
                     mjbFreezed: mjbFreezed,
                     mjbXcped: mjbXcped,
                     mjbStatus2: mjbStatus2,
                     mjbStatus3: mjbStatus3,
                     mjbs1_from: fitness_score1_from,
                     mjbs1_to: fitness_score1_through,
                     mjbs1_fromneg: fitness_score1_from_neg,
                     mjbs1_toneg: fitness_score1_through_neg,
                     mjbs1_frompos: fitness_score1_from_pos,
                     mjbs1_topos: fitness_score1_through_pos,
                     mjbs2_from: priority_score2_from,
                     mjbs2_to: priority_score2_through
                   };
var transitParam = buildTransitParam(["urole", "mode", "deel", "groep", "categorie_key_arr", "districtkey", "locatiekey", "gebouwkey", "verdiepingkey", "ruimtekey",
                                      "disc", "srtgroep", "srtdeel", "verantw", "sBeh_key", "srtcontrole",
                                      "frequentie", "account", "incbtw", "toyear",
                                      "scenario", "actsit", "showunfin", "mjbshowempty", "ctrdisc_key",
                                      "fitness_score1_from", "fitness_score1_through", "fitness_score1_from_neg", "fitness_score1_through_neg",
                                      "fitness_score1_from_pos", "fitness_score1_through_pos", "priority_score2_from", "priority_score2_through",
                                      "mjbMoved", "mjbFreezed", "mjbXcped", "mjbStatus2, mjbStatus3"]);
%>
  <html>
    <head>
      <style>
        div#timetip {position:absolute;border:1px solid #666;background-color:#fff;padding:2px;z-index:999;display:none;}
      </style>
<%
      FCLTHeader.Generate({ outputmode: outputmode });

      // In het Uitvoering scherm (mode 3) scherm mag ik alle tussenliggende jaren ook zien net als in het Begroting scherm (mode 1), ook al is een jaar kolom helemaal leeg.
      // Dan weet ik wanneer en of er volgende inspectie zijn ingepland. De lege jaren hoef ik er dus niet per se uit te filteren zoals in het Realisatie scherm (mode 2) wel gebeurt.
      var jaren = [];
      for (var i = fromyear; i <= toyear; i++)
          jaren.push(i);

      if (outputmode == 0) {
%>
      <script type="text/javascript">
        var mjb_freeze_year = <%=mjb_freeze_year%>;
        var mjb_show_years = <%=mjb_show_years%>;
        var urole = "<%=urole%>";
        var scenario = <%=scenario%>;
        var fulldetails = <%=fulldetails? 1 : 0%> == 1;
        var transitParam = "<%=transitParam%>";
        var actsit = <%=actsit? 1 : 0%> == 1;
        var showunfin = <%=showunfin? 1 : 0%> ==1;
        var showempty = <%=mjbshowempty? 1 : 0%> == 1;
        var categorie_key_arr = [<%=categorie_key_arr%>];
        var reg_key_arr = [<%=reg_key_arr%>];
        var dist_key_arr = [<%=dist_key_arr%>];
        var loc_key_arr = [<%=loc_key_arr%>];
        var bld_key_arr = [<%=bld_key_arr%>];
        var disc_key_arr = [<%=disc_key_arr%>];
        var srtgroep_key_arr = [<%=srtgroep_key_arr%>];
        var srtdeel_key_arr = [<%=srtdeel_key_arr%>];
        var moredetail = <%=moredetail%>;
        var srtgebouw_key_arr = [<%=srtgebouw_key_arr%>];
        var groep_str_arr = [];
<%      for (var i = 0; i < groep_str_arr.length; i++)
        { %>
          groep_str_arr.push("<%=groep_str_arr[i]%>");
<%      } %>
        var srtcontrole_key_arr = [<%=srtcontrole_key_arr.join(",")%>];
        var frequentie_arr = [<%=frequentie_arr.join(",")%>];
        var kp_key_arr = [<%=kp_key_arr%>];
        var ctrdisc_key = <%=ctrdisc_key%>;
        var verantw_key = <%=verantw_key%>;
        var beheerder_key = <%=beheerder_key%>;
        var incbtw = <%=incbtw? 1 : 0%>;
        var toyear = <%=toyear%>;
        var showunfin = <%=showunfin? 1 : 0%>;
        var groupby = <%=groupby%>;
        var deel = "<%=safe.jsstring(deel)%>";
        var mjbMoved = <%=mjbMoved? 1 : 0%>;
        var mjbFreezed = <%=mjbFreezed? 1 : 0%>;
        var mjbXcped = <%=mjbXcped? 1 : 0%>;
        var mjbStatus2 = <%=mjbStatus2? 1 : 0%>;
        var mjbStatus3 = <%=mjbStatus3? 1 : 0%>;
        var fitness_score1_from = <%=safe.jsfloat(fitness_score1_from)%>;
        var fitness_score1_through = <%=safe.jsfloat(fitness_score1_through)%>;
        var fitness_score1_from_neg = <%=safe.jsfloat(fitness_score1_from_neg)%>;
        var fitness_score1_through_neg = <%=safe.jsfloat(fitness_score1_through_neg)%>;
        var fitness_score1_from_pos = <%=safe.jsfloat(fitness_score1_from_pos)%>;
        var fitness_score1_through_pos = <%=safe.jsfloat(fitness_score1_through_pos)%>;
        var priority_score2_from = <%=priority_score2_from%>;
        var priority_score2_through = <%=priority_score2_through%>;
        var jaren = [<%=jaren.join(",")%>];

        $(function ()
        {
          $('td.mjbjaar').droppable(
                       { drop: function(event, ui)
                               { // Als het bedrag verschoven is naar zijn eigen cel/kolom dan kunnen we direct stoppen.
                                 if ($(ui.draggable).is("tr") || $(ui.draggable).hasClass("ui-dialog")) // De legenda en de 'kolommen'-popup zijn ook draggables
                                   return false;

                                 var sourcecol = $(this).closest('tr').find('.draggable').parent().index(); // Kolomindex vanwaar is verschoven
                                 var targetcol = $(this).index(); // Kolomindex waar naar toe is verschoven

                                 $td = $(this);
                                 $td.css('border', '3px solid grey');
                                 // Zoek de TH erbij. Daarin staat het drop-jaartal
                                 var $th = $td.closest('table').find('th').eq($td.index()); // werkt omdat we geen colspan's hebben

                                 if (sourcecol == targetcol ||                              // Naar zichzelf verschoven.
                                     parseInt($th.text(), 10) < (new Date()).getFullYear()) // Naar het verleden verschuiven kan niet.
                                 {
                                   FcltCallbackRefresh({success: true});
                                   return;
                                 }

                                 var row = $td.closest('tr')[0];
                                 var insData = JSON.parse(row.getAttribute("ROWDATA"));
                                 mjb_dragdrop_1x(null,
                                                 insData.insKey,
                                                 insData.insSrtControleKey,
                                                 insData.insScenKey,
                                                 insData.insDeelSrtContrKey,
                                                 insData.insStartDatum,
                                                 insData.insHasControle,
                                                 insData.insBedragFY,
                                                 insData.insNotSucces,
                                                 insData.insRejectedInFY,
                                                 $th.text(),
                                                 insData.insDeelSrtContrPlanOpm);
                               }
                       });


          $('span.draggable').each(function ()
                   {
                     var element = $(this);
                     element.draggable(
                             {
                                scroll: false,
                                axis: "x",
                                revert: "invalid"
                             });
                   });
           $("#mjobtable").mousemove(function (event)
               {
                    $('#timetip').show();
                    $td = $(event.target).closest("td");
                    $tr = $(event.target).closest("tr");

                    if (!$td.hasClass('mjbjaar'))
                    {
                        $('#timetip').hide();
                        return;
                    }
                    // Zoek de TH erbij. Daarin staat het drop-jaartal
                    var $th = $td.closest('table').find('th').eq($td.index()); // werkt omdat we geen colspan's hebben
                    var jaar = $th.text();
                    var insDeelSrtContrPlanOpm;

                    // Als de inspectie gepland is (tr heeft class "mjbplanned") dan de oorspronkelijke datum tonen.
                    // Oorspronkelijke datum alleen tonen op het schuifbare bedrag, anders gewoon jaar van de kolom.
                    if ($tr.hasClass("mjbplanned") && $td.find("span").hasClass("draggable"))
                    { // Inspectie is gepland.
                      var data = JSON.parse($tr[0].getAttribute("ROWDATA"));

                      if (data.insCtrControleType == 1)
                        // Oorspronkelijke jaar is onbepaald.
                        jaar = L("lcl_mjb_original").format(L("lcl_ins_controle_first").toLowerCase());
                      else
                        // Oorspronkelijke jaar weergeven.
                        jaar = L("lcl_mjb_original").format(data.org_nextdate);

                      if (data.insDeelSrtContrPlanOpm)
                        insDeelSrtContrPlanOpm = data.insDeelSrtContrPlanOpm.replace(/\n/ig, "<br>");
                    }

                    if (insDeelSrtContrPlanOpm)
                    {
                      jaar += "<br>" + insDeelSrtContrPlanOpm;
                    }

                    $("#timetip").html(jaar)
                                 .css({ left: parseInt(event.pageX, 10) + 30 + "px",
                                        top: parseInt(event.pageY, 10) - 30 + "px"
                                      })
                                 .show();
               });
           $("#mjobtable").mouseout(function ()
               {
                    $('#timetip').hide();
               });
        })
      </script>
<%
      } //if (outputmode == 0)
%>
    </head>
    <body id="listbody">
<div id='timetip'></div>

<%
    // Start building the query to fetch all objects satisfying
    var algFlexParams = alg.alg_onroerendgoed_flex_params("G", 2); // In overzicht tonen: 2=MJOB Planningsconsole.
    var insFlexParams = ins.ins_deel_flex_params(2, {inspect: false}); // In overzicht tonen: 2=MJOB Planningsconsole.
    var mjbparams = { execute: mode == 3,
                      scenario: scenario,
                      fulldetails: fulldetails,
                      actsit: actsit,
                      showunfin: showunfin,
                      //showempty: mjbshowempty, // Niet meegeven. De functie "fnrowFilter" bepaald later of de lege regels getoond worden.
                      categorie_key_arr: categorie_key_arr,
                      reg_key_arr: reg_key_arr,
                      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,
                      srtgebouw_key_arr: srtgebouw_key_arr,
                      groep_str_arr: groep_str_arr,
                      srtcontrole_key_arr: srtcontrole_key_arr,
                      frequentie_arr: frequentie_arr,
                      kp_key_arr: kp_key_arr,
                      verantw_key: verantw_key,
                      beheerder_key: beheerder_key,
                      incbtw: incbtw,
                      inflatiefactor: inflatiefactor,
                      toyear: toyear,
                      groupby: groupby,
                      moredetail: moredetail,
                      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,
                      mjbStatus2: mjbStatus2,
                      mjbStatus3: mjbStatus3,
                      jaren: jaren,
                      show_scenario_oms: ((print || excel) && scenario > 1),
                      algFlexParams: algFlexParams,
                      insFlexParams: insFlexParams
                     };
    var sql = ins.getmjblist_sql(mjbparams);
    // ========== now 'sql' holds the main SQL-statement voor de mjbsearchlist.

    ///////////////////////////////////////////////////////////
    //
    //      Now let's present the results:
    //
    ///////////////////////////////////////////////////////////

    /***********************************************
     * Callback functions ResultsetTable
     **********************************************/

    function fnkeyFunction(oRs)
    {
      if (fulldetails)
        return oRs("ins_deel_key").Value; // + "-" + oRs("ins_srtcontrole_key").Value;
      else
        return oRs("keyColumn").Value;
    }

    function fnrowData(oRs)
    {
      var data = {};
      if (fulldetails)
      {
        data.insKey = oRs("ins_deel_key").Value;
        data.insSrtControleKey = oRs("ins_srtcontrole_key").Value;
        data.insDeelSrtContrKey = oRs("ins_deelsrtcontrole_key").Value? oRs("ins_deelsrtcontrole_key").Value : -1;
        data.insDeelSrtContrKeyFreezed = oRs("idsc_freezed").Value? oRs("idsc_freezed").Value : -1;
        data.insDeelSrtContrPlanOpm = safe.htmlattr(oRs("ins_deelsrtcontrole_plan_opm").Value);
        data.insXcpKey = oRs("ins_srtcontroledl_xcp_key").Value || -1;
        data.insDeelSrtContrStatus = oRs("ins_deelsrtcontrole_status").Value == null? -1 : oRs("ins_deelsrtcontrole_status").Value;
        data.org_nextdate = oRs("org_nextdate").Value; // Eerstaankomende inspectie vandaag of in de toekomst.
        data.insCtrControleType = oRs("ctr_controle_type").Value;
        data.insScenKey = oRs("ins_scenario_key").Value;
        data.insStartDatum = oRs("startdatum").Value != null? new Date(oRs("startdatum").Value).getTime() : -1;
        data.insHasControle = oRs("hascontroles").Value? oRs("hascontroles").Value : -1;
        data.insIsFreezeYear = oRs("isFreezeYear").Value;
        data.insCtrDisciplineKey = oRs("ctr_discipline_key").Value;
        data.insBedragFY = oRs("" + mjb_freeze_year).Value;
        data.insNotSucces = oRs("laatste_not_suc").Value || -1;
        data.insRejectedInFY = oRs(mjb_freeze_year + "_rejected").Value || 0;
      }
      else
      {
        data.keyColumn = oRs("keyColumn").Value;
      }
      data.freezed = oRs(mjb_freeze_year + "_freezed").Value;
      data.tobefreezed = oRs(mjb_freeze_year + "_tobefreezed").Value;

      if (!fulldetails && !mjbshowempty)
      {
        data.aantaltaken = 0;
        for (var j = 0; j < jaren.length; j++)
        {
          if (oRs(String(jaren[j]) + "_aantaltaken_withoutempty").Value > 0)
            data.aantaltaken += oRs(String(jaren[j]) + "_aantaltaken_withoutempty").Value;
        }
      }
      else
        data.aantaltaken = oRs("aantaltaken").Value;;

      return JSON.stringify(data);
    }

    function fnrowClass(oRs)
    {
      var lclass = "";

      if (!fulldetails)
        return lclass;
      var scen_key = oRs("ins_scenario_key").Value;
      lclass += (scen_key == 1 && oRs("ins_srtcontroledl_xcp_key").Value != null? " mjbxcp" : " mjbstd");
      if (scen_key > 1)
        lclass += " scenerized1";
      if (oRs("isPlanned").Value == 1)
        lclass += " mjbplanned";

      return lclass;
    }

    // true als er *ergens* een bedrag is ingevuld
    function fnrowFilter(oRs)
    {
      if (mjbshowempty)
        return true;

      for (var j = 0; j < jaren.length; j++)
      {
          if (oRs(String(jaren[j])).Value != null) // Wel regels met een bedrag van 0 i.p.v. null tonen. Die moeten wel geaccodeerd worden ook al kosten deze niets.
            return true;
      }

      return false;
    }

    function fnHasScenario(oRs)
    {
      if (oRs("scenario_aantal").Value > 0)
      {
        return "<nobr>" + (oRs("scenario_aantal").Value > 1? "*" : "") + "<span title='" + safe.htmlattr(oRs("scenario_oms").Value) + "'>" + I("fa-clone") + "</span>" + "</nobr>"
      }
      else
        return "";
    }

    function fnLocatieX(oRs, naamofcode)
    {
      if (naamofcode == 1) // 1=naam
      {
        var locatietekst  = oRs("alg_locatie_omschrijving").Value;
      }
      else // 2=code
      {
        var locatietekst  = oRs("alg_locatie_code").Value;
      }
      if ((hasReadALGUSE || hasReadALGMAN) && outputmode == 0)
      {
        return "<span class='details' title='{2}' onclick='naarlocatie({0}, this)'>{1}</span>".format(oRs("alg_locatie_key").Value, safe.htmlattr(locatietekst), (fulldetails ? safe.htmlattr(L("lcl_estate_locatie_title")): L("ins_srtcontrole_m")));
      }
      else
        return safe.html(locatietekst);
    }

    function fnLocatie(oRs)
    {
        return fnLocatieX(oRs, 1);
    }
    function fnLocatieCode(oRs)
    {
        return fnLocatieX(oRs, 2);
    }

    function fnGebouwTerreinX(oRs, naamofcode)
    {

      if (naamofcode == 1) // 1=naam
      {
        var gebouwtekst  = oRs("alg_gebouw_naam").Value;
        var terreintekst = oRs("alg_terreinsector_naam").Value;
      }
      else // 2=code
      {
        var gebouwtekst  = oRs("alg_gebouw_code").Value;
        var terreintekst = oRs("alg_terreinsector_code").Value;
      }
      if ((hasReadALGUSE || hasReadALGMAN) && outputmode == 0)
      {
        if (oRs("alg_gebouw_key").Value > 0)
          return "<span class='details' title='{2}' onclick='naargebouw({0}, this)'>{1}</span>".format(oRs("alg_gebouw_key").Value, safe.html(gebouwtekst), (fulldetails ? safe.htmlattr(L("lcl_estate_gebouw_title")): L("ins_srtcontrole_m")));
        else
          return "<span class='details' title='{2}' onclick='naarterrein({0}, this)'>{1}</span>".format(oRs("alg_terreinsector_key").Value, safe.html(terreintekst), (fulldetails ? safe.htmlattr(L("lcl_estate_terreinsector_title")): L("ins_srtcontrole_m")));
      }
      else
      {
        if (oRs("alg_gebouw_key").Value > 0)
          return safe.html(gebouwtekst);
        else
          return safe.html(terreintekst);
      }
    }

    function fnGebouwTerreinCode(oRs)
    {
      return fnGebouwTerreinX(oRs, 2);
    }

    function fnGebouwTerrein(oRs)
    {
      return fnGebouwTerreinX(oRs, 1);
    }

    function fnRuimte(oRs)
    {
      var retval = "";
      if ((oRs("alg_ruimte_nr").Value).substring(0,1) != "_")
      {
        if ((hasReadALGUSE || hasReadALGMAN) && outputmode == 0)
        {
            retval = "<span class='details' title='{2}' onclick='naarruimte({0}, this)'>{1}</span>".format(oRs("alg_ruimte_key").Value, safe.htmlattr(oRs("alg_ruimte_nr").Value), safe.htmlattr(oRs("alg_ruimte_omschrijving").Value));
        }
        else
          retval = safe.html(oRs("alg_ruimte_nr").Value);
      }
      return retval;
    }

    function fnDeel(oRs)
    { // Alleen voor groupby Element(7) en Taak(9)
      if (outputmode != 0)
        return safe.html(oRs("ins_deel_omschrijving").Value);
      if (hasReadINSMAN)
      {
        return "<span class='details' title='{2}' onclick='naardeel({0}, this)'>{1}</span>".format(oRs("keyColumn").Value, safe.html(oRs("ins_deel_omschrijving").Value), safe.htmlattr(L("lcl_mld_deel_details")));
      }
      else
        return safe.html(oRs("ins_deel_omschrijving").Value);
    }

    function fnSrtcontrole(oRs)
    {
      var hasXcp = oRs("ins_srtcontroledl_xcp_key").Value != null;
      if (outputmode == 0 && ((hasXcp && hasReadINSMAN) || (hasWriteCTRUSESEN && hasWriteINSMAN)))
      {
        var fncall = "exception({0}, {1}, '{2}', '{3}')"
                            .format(oRs("ins_deel_key").Value,
                                    oRs("ins_srtcontrole_key").Value,
                                    oRs("ins_scenario_key").Value,
                                    safe.jsstring(oRs("ins_deel_omschrijving").Value));
        return "<span class='details' onclick='{0}'>{1}</span>"
                            .format(safe.htmlattr(fncall),
                                    safe.html(oRs("ins_srtcontrole_omschrijving").Value));
      }
      else
        return safe.html(oRs("ins_srtcontrole_omschrijving").Value);
    }

    function fnCyclus(oRs)
    {
      var cyclus_omschr = oRs("ins_srtcontrole_periode").Value;
      var eenheid_index = oRs("ins_srtcontrole_eenheid").Value;
      // LOV to Array:  '0;Uurlijks;1;Dagelijks;2;Wekelijks;3;Maandelijks;4;Jaarlijks'
      var eenheid_LOV = L("ins_srtcontrole_eenheidLOV").split(";");
      var eenheid_arr = [];
      for (var i=0; i<(eenheid_LOV.length/2); i++)
      {
        eenheid_arr[eenheid_LOV[i*2]] = eenheid_LOV[i*2+1];
      }
      var eenheid = eenheid_arr[eenheid_index];
      return safe.html(cyclus_omschr + " " + eenheid);
    }

    function fnTaakgroep(oRs)
    {
      return safe.html(oRs("ins_srtcontrole_groep").Value);
    }

    function fnMelding(oRs)
    { // Alleen voor groupby Taak(9) en mode Uitvoering(3).
      if (outputmode != 0)
        return safe.html(oRs("melding").Value);
      var melding_omschr = safe.html(oRs("prefix").Value) + safe.html(oRs("melding").Value);
      if (hasReadMLDBOF)
      {
        return "<span class='details' title='{2}' onclick='naarmelding({0}, this)'>{1}</span>".format(oRs("melding").Value, melding_omschr, safe.htmlattr(L("lcl_mjb_melding_details")));
      }
      else
        return melding_omschr;
    }

    function fnXcpPrio(oRs)
    {
      var prio = oRs("ins_srtcontroledl_xcp_prio").Value;
      if (oRs("ins_srtcontroledl_xcp_prio").Value == null)
      {
        prio = "2"; // default value
      }
      return L("lcl_ins_srtcontroledl_xcp_prio_" + prio);
    }

    function fnfncolPrioClass(oRs)
    {
      var prio = oRs("ins_srtcontroledl_xcp_prio").Value;
      if (oRs("ins_srtcontroledl_xcp_prio").Value == null)
      {
        prio = "2"; // default value
      }
        return "xcp_prio_" + prio;
    }

    function fnfnBedrag(jaar) // altijd afronden
    {
      return function (oRs)
      {
          if (oRs(jaar).Value == null)
            return "";
          var v = safe.curr(Math.round(oRs(jaar).Value), true);
          return v;
      }
    }

    function fnfnBedragNumber(jaar) // Voor optellen
    {
      return function (oRs)
      {
          return Math.round(oRs(jaar).Value);
      }
    }

    var mjb_total_add_pct1 = S("mjb_total_add_pct1");
    var mjb_total_add_pct2 = S("mjb_total_add_pct2");
    var showpct1 = mjb_total_add_pct1 > 0 || mjb_total_add_pct1 < 0;
    var showpct2 = mjb_total_add_pct2 > 0 || mjb_total_add_pct2 < 0;
    function totalColumnText()
    {
      var totalcolumntext = "";
      if (showpct1 || showpct2)
      {
        totalcolumntext = "<br>"
                        + (showpct1
                          ? L("lcl_mjb_total_add_pct1") + " (" + (mjb_total_add_pct1 > 0? "+" : "") + mjb_total_add_pct1 + "%)"
                            + "<br>"
                          : "")
                        + (showpct2
                          ? (showpct1? "<br>" : "")
                            + L("lcl_mjb_total_add_pct2") + " (" + (mjb_total_add_pct2 > 0? "+" : "") + mjb_total_add_pct2 + "%) "
                            + "<br>"
                          : "")
                        + L("lcl_mjb_total");
      }
      return totalcolumntext;
    }

    function totalShow(column, rowNum)
    {
      var totaal = safe.curr(column.totalsum, true);
      var totalshow = totaal;
      if (showpct1 || showpct2)
      {
        // Opslag #1 = mjb_total_add_pct1 procent van subtotaal.
        var add_pct1 = column.totalsum * (mjb_total_add_pct1 / 100);
        // Opslag #2 = mjb_total_add_pct2 procent van (subtotaal + opslag #1).
        var add_pct2 = (column.totalsum + add_pct1) * (mjb_total_add_pct2 / 100);
        if (showpct1)
        {
          totalshow += "<br>"
                     + " <u>"
                     + (mjb_total_add_pct1 > 0? "+" : "")
                     + safe.curr(add_pct1, true)
                     + "</u>";
          if (showpct2)
            totalshow += "<br>"
                       + safe.curr(column.totalsum + add_pct1, true);
        }
        if (showpct2)
          totalshow += "<br>"
                     + "<u>"
                     + (mjb_total_add_pct2 > 0? "+" : "")
                     + safe.curr(add_pct2, true)
                     + "</u>";
        if (showpct1 || showpct2)
          totalshow += "<br>"
                     + safe.curr(column.totalsum + add_pct1 + add_pct2, true);
      }
      return totalshow;
    }

    // Voor de laatste kolom
    function fnTotal(oRs)
    {
      var s = 0;
      for (var j = 0; j < jaren.length; j++)
      {
          s = s + Math.round(oRs(String(jaren[j])).Value);
      }
      return s;
    }

    function fnTotalText(oRs)
    {
      return safe.curr(fnTotal(oRs), true);
    }

    var doneclick = {}; // Altijd alleen de eerste klikken
    function fnfnClickBedrag(jaar) // altijd afronden
    {
      return function (oRs)
      {
        if (oRs(jaar).Value == null)
            return "";
        var v = Math.round(oRs(jaar).Value);
        var org_v = Math.round(oRs(jaar + "_ORGBEDRAG").Value);
        if (v == 0) // (jaar >= vervaljaar) of (startjaar >= jaar)
        {
          var startjaar = oRs("startjaar").Value; // Startjaar heeft altijd een waarde.
          var starttype = oRs("starttype").Value;
          var ctr_controle_type = oRs("ctr_controle_type").Value;
          var planjaar = oRs("planjaar").Value;
          var vervaljaar = oRs("vervaljaar").Value;
          var afbouwtijd = oRs("afbouwtijd").Value || 0;
          var ins_srtcontrole_periode = oRs("ins_srtcontrole_periode").Value;
          // Bedrag bij startjaar tonen indien alleen bij startdate of bij aanmaakdatum in toekomst bij controle type "Controle(1)"
          // Bedrag bij startjaar + periode pas tonen als aanmaakdatum in toekomst bij controle typen "Vervanging(2)" of "Certificering(3)", tenzij het bedrag richting of naar het startjaar is verschoven.
          // Als de registratiedatum in de toekomst ligt en de startdatum eventueel ook dan geldt het volgende.
          // Voor Controle(1): Eerste inspectie tonen op MAX(startdatum, registratiedatum) van het object.
          // Voor Vervanging(2) of Certificering(3):
          // a) Als registratiedatum het verst in de toekomst ligt: Eerste inspectie tonen op 1 periode verder dan de registratiedatum.
          // b) Als de startdatum het verst in de toekomst ligt: Eerste inspectie tonen op de startdatum.
          if ((vervaljaar != null && jaar > vervaljaar - afbouwtijd) ||  // Als 2022 vervaljaar is en afbouwtijd is 2 jaar, dan 2020 nog 0 tonen.
              (startjaar > jaar) ||  // In startjaar komt een bedrag te staan.
              ((startjaar + ins_srtcontrole_periode) > jaar && starttype == "A" && ctr_controle_type != 1 && ((planjaar == null) || (planjaar != null && planjaar > jaar))))  // In startjaar + periode komt een bedrag te staan, tenzij verschoven.
          {
            return "";
          }
        }
        if (outputmode != 0)
            return safe.curr(v, true);

        if (v != org_v)
        {
          if (outputmode == 0)
            v = "<span class='mjborgbedrag' title='{1}'>{0}</span>".format(safe.curr(v, true), L('lcl_valutasign') + safe.curr(org_v, true));
          else
            v = "{0}".format(safe.curr(v, true));
        }

        var deel_key = oRs("ins_deel_key").Value;
        var srtcont_key = oRs("ins_srtcontrole_key").Value;
        if ((jaar < mjb_freeze_year && (oRs(jaar + "_completed").Value == 1 || oRs(jaar + "_rejected").Value == 1 || oRs(jaar + "_freezed").Value == 1 || oRs(jaar + "_execute").Value == 1)) ||  // inspecties voor het freeze jaar (completed, rejected, freezed, execute) niet sleepbaar, behalve ingeplande die nog niet zijn gedaan.
            // Als in het freeze jaar of daarvoor een geaccordeerde/bevroren of ter uitvoeringstaande inspectie is dan moet volgende bedrag sleepbaar zijn.
            // Er kan naast een geaccordeerde/bevroren(2) of ter uitvoering(3) staande inspectie ook nog een ingeplande(0) inspectie als laatste melding zijn (2 lopende records, vandaar (status < 5)).
            (jaar <= mjb_freeze_year && (oRs(jaar + "_freezed").Value == 1 || oRs(jaar + "_execute").Value == 1) && oRs("ins_deelsrtcontrole_status").Value < 5) ||
            (oRs(jaar + "_completed").Value == 1) || (oRs(jaar + "_rejected").Value == 1) ||
            (deel_key + ":" + srtcont_key) in doneclick)
        {
          return safe.curr(v, true);
        }

        doneclick[deel_key + ":" + srtcont_key] = 1;


        var scen_key = oRs("ins_scenario_key").Value;
        // INSUSE read rechten heb je al nodig om dit overzicht te zien.
        // Inspecties in de status gestart(2) of gereedgemeld(5) mogen niet drag en drop zijn. Planningsdatum is daarvan niet aan te passen.
        return "<span" + (hasWriteCTRUSESEN? " class='" + ((scenario == 1 || scen_key > 1 || oRs("hasscenario2").Value == 1)? "details draggable" : "") + "'" : "") + ">{0}</span>".format(safe.curr(v, true));
      }
    }

    function fncolScore1Class(oRs)
    { // Conditiescore.
      if ((groupby == 7 || groupby == 9) && ins_score_enabled && oRs("ins_deel_mjb_score1").Value != null)
        return safe.htmlattr("dcscore" + (oRs("ins_deel_mjb_score1").Value).toString().replace(".", "_"));

    }

    function fncolScore2Class(oRs)
    { // Prioriteit.
      if ((groupby == 7 || groupby == 9) && ins_score_enabled && oRs("ins_deel_mjb_score2").Value != null)
        return safe.htmlattr("dpscore" + (oRs("ins_deel_mjb_score2").Value).toString().replace(".", "_"));

    }

    function fnfncolClass(jaar)
    {
      return function (oRs)
      {
        var freezeclass = "";
        if (fulldetails)
        {
          var startjaar = oRs("startjaar").Value;
          var vervaljaar = oRs("vervaljaar").Value;
          var afbouwtijd = oRs("afbouwtijd").Value || 0;
          if ((vervaljaar != null && jaar > vervaljaar - afbouwtijd) ||  // Afzien van taken/vervanging/inspecties. Geen kosten meer.
              (startjaar > jaar))                                        // Vanaf startjaar pas bedragen mogelijk.
          {
            if (vervaljaar != null && afbouwtijd != null && jaar > vervaljaar - afbouwtijd && jaar <= vervaljaar)
              return "mjbafbouw" + freezeclass;
            else if ((vervaljaar != null && jaar > vervaljaar) || (startjaar > jaar))
              return "mjbverval";
          }
          else
          {
            var bedrag;
            if (oRs(jaar).Value == null)
              bedrag = -1;
            else
              bedrag = Math.round(oRs(jaar).Value); // Bedrag moet niet naar een string (safe.curr) geconverteerd worden. Bedrag wordt alleen in IF statement gebruikt.

            // Alleen geaccordeerde taken in of eerder dan het freeze jaar kunnen geaccordeerd/bevroren zijn.
            if (oRs(jaar + "_freezed").Value == 1 && bedrag >= 0)
              freezeclass = " mjbfreezed";
            if (oRs(jaar + "_execute").Value == 1 && bedrag >= 0)
              freezeclass = " mjbexecute";
            if (oRs(jaar + "_completed").Value == 1)
              freezeclass += " mjbcompleted";
            if (oRs(jaar + "_rejected").Value == 1)
              freezeclass += " mjbrejected";
          }
        }
        else
        { // groepering.
          if (jaar == mjb_freeze_year && oRs(jaar + "_tobefreezed").Value == 0)
          {
            var bedrag;
            if (oRs(jaar).Value == null)
              bedrag = -1;
            else
              bedrag = Math.round(oRs(jaar).Value); // Bedrag moet niet naar een string (safe.curr) geconverteerd worden. Bedrag wordt alleen in IF statement gebruikt.

            if (bedrag > 0)
              freezeclass = " mjbfreezed";
          }
        }
        return "mjbjaar" + freezeclass;
      }
    }

    function fncolCloneClass()
    {
      return function (oRs)
      {
        if (oRs("scenario_aantal").Value > 0)
        {
          return "mjbcloned"
        }
        else
          return "";
      }
    }

    function fncolFlexAlgBijlagen(oRs)
    {
      var flexval = oRs("algflex").Value;
      var alg_key = oRs("alg_gebouw_key").Value;
      var result = ( flexval
                     ? safe.html(flexval.replace(/\r/g, "\n")+ "\n")
                     : ""
                   );
      if (algFlexParams.bijlageflex)
      {
        result += alg.alg_onroerendgoed_flex_bijlagen("G", alg_key, 2);
      }
      return result;
    }

    function fncolFlexInsBijlagen(oRs)
    {
      var flexval = oRs("insflex").Value;
      var ins_key = oRs("ins_deel_key").Value;
      var result = ( flexval
                     ? safe.html(flexval.replace(/\r/g, "\n")+ "\n")
                     : ""
                   );
      if (insFlexParams.bijlageflex)
      {
        result += ins.ins_deel_flex_bijlagen(ins_key, 2, false); // In overzicht tonen: 2=MJOB Planningsconsole.
      }
      return result;
    }

    var buttons = [];
    buttons.push({ icon: "fa-columns",  title: L("lcl_scf_columns"), action: "openColumns()"});
    buttons.push({ icon: "fa-fclt-refresh", title: L("lcl_refresh"), action: "FcltMgr.reload()" });
    buttons.push({ icon: "fa-list-ul",  title: L("lcl_ins_controle_legenda"), action: 'openLegenda()' });

    var rst = new ResultsetTable({ keyColumn: fnkeyFunction,
                                   sql: sql,
                                   ID: "mjobtable",
                                   tabs_code: "mjob_list-" + groupby,  // per groepering kun je wat anders (willen)
                                   rowData: fnrowData,
                                   rowClass: fnrowClass,
                                   rowFilter: fnrowFilter,
                                   // Buttons zijn alleen aanwezig bij fulldetails. Buttons worden daar alleen multi gebruikt.
                                   // Dan hoeven we hier niet te bepalen of de buttons zichtbaar moeten zijn en kan rowActionEnabler dus weg.
                                   // Bij multi worden de buttons altijd getoond en wordt bij het doorvoeren wel bepaald of het kan.
                                   //rowActionEnabler: fnrowActionEnabler,
                                   totalColumnText: totalColumnText,
                                   totalShow: totalShow,
                                   flexModule: "INS",
                                   multiple: true,
                                   filterParams: filterParams,
                                   outputmode: outputmode,
                                   title: L("lcl_mjb_begroting") + " (" + L("lcl_mjb_budget_year").format(mjb_freeze_year)
                                        + (inflatiepct != 0 ? ", " + L("lcl_mjb_inflation").format(safe.curr(inflatiepct)): "") + ")",
                                   showAll: showall,
                                   canCSV: true,
                                   buttons: buttons
                                 });

    if (fulldetails && scenario == 1 && outputmode == 0)
      rst.addColumn(new Column({caption: "<span title='{0}'>".format(safe.htmlattr(L("lcl_mjb_scenarios"))) + I("fa-clone") + "</span>", content: fnHasScenario, colName: "fnHasScenario" }));
    else if ((print || excel) && scenario > 1)
      rst.addColumn(new Column({caption: safe.htmlattr(L("lcl_mjb_scenarios")), content: "scenario_oms"}));
    if (groupby == 1 || groupby == 2 || groupby == 3 || moredetail == 2)
      rst.addColumn(new Column({caption: L("lcl_district"), content: "alg_district_omschrijving" }));
    if (groupby == 2 || groupby == 3  || moredetail == 2)
    {
      if (groupby == 2)
        rst.addColumn(new Column({caption: L("lcl_estate_locatie_man_code"), content: fnLocatieCode, colName: "alg_locatie_code" }));
      rst.addColumn(new Column({caption: L("lcl_location"), content: fnLocatie, colName: "fnLocatie" }));
    }
    if (fulldetails || groupby == 3 || moredetail == 2)
    {
      rst.addColumn(new Column({caption: L("lcl_estate_gebouw_man_code"), content: fnGebouwTerreinCode, colName: "fnGebouwTerreinCode" }));
      rst.addColumn(new Column({caption: L("lcl_bld_terra"), content: fnGebouwTerrein, colName: "fnGebouwTerrein" }));
    }
    if (!fulldetails || (fulldetails && mjb_show_srt_with_tasks) || moredetail == 1)
    {
      if (groupby >= 4 || moredetail == 1) rst.addColumn(new Column({caption: L("lcl_discipline"), content: "ins_discipline_omschrijving"}));
      if (groupby >= 5 || moredetail == 1) rst.addColumn(new Column({caption: L("lcl_obj_group"), content: "ins_srtgroep_omschrijving"}));
      if (groupby >= 6 || moredetail == 1) rst.addColumn(new Column({caption: L("lcl_obj_sort"), content: "ins_srtdeel_omschrijving"}));
    }
    if (groupby == 2 && ins_score_enabled)
      rst.addColumn(new Column({caption: L("lcl_alg_locatie_mjb_score1"), content: "alg_locatie_mjb_score1", datatype: "number", align: "center"}));
    if (groupby == 3 && ins_score_enabled)
      rst.addColumn(new Column({caption: L("lcl_alg_gebouw_mjb_score1"), content: "alg_gebouw_mjb_score1", datatype: "number", align: "center"}));
    if (groupby == 7 || groupby == 9)
    {
      rst.addColumn(new Column({caption: L("lcl_ins_object"), content: fnDeel, colName: "fnDeel"}));
      if (S("mjb_show_ruimte") == 1)
      {
        rst.addColumn(new Column({caption: L("lcl_room"), content: fnRuimte, colName: "fnRuimte" }));
        rst.addColumn(new Column({caption: L("lcl_estate_ruimte_man_descr"), content: "alg_ruimte_omschrijving", purpose: PRINTING_ONLY})); // zit op schernm in tooltip
      }
      rst.addColumn(new Column({caption: L("lcl_ins_opmerking"), content: "ins_deel_opmerking"}));
      rst.addColumn(new Column({caption: L("lcl_amount"), content: "ins_deel_aantal", datatype: "float"}));
      rst.addColumn(new Column({caption: L("lcl_obj_unit"), content: "ins_srtdeel_eenheid"}));
      if (ins_score_enabled)
      {
        rst.addColumn(new Column({caption: L("ins_srtdeel_mjb_grensscore1"), content: "ins_srtdeel_mjb_grensscore1", datatype: "number", align: "center"}));
        rst.addColumn(new Column({caption: L("lcl_ins_deel_mjb_score1"), content: "ins_deel_mjb_score1", datatype: "number", align: "center", columnClass: fncolScore1Class}));
        rst.addColumn(new Column({caption: L("lcl_ins_deel_mjb_score2"), content: "ins_deel_mjb_score2", datatype: "number", align: "center", columnClass: fncolScore2Class}));
        if (groupby == 9)
          rst.addColumn(new Column({caption: L("lcl_ins_srtcontroledl_xcp_prio"), content: fnXcpPrio, colName: "fnXcpPrio", columnClass: fnfncolPrioClass, align: "center"}));
      }
    }
    if (fulldetails)
    {
      rst.addColumn(new Column({caption: L("lcl_ins_controle_srt"), content: fnSrtcontrole, colName: "fnSrtcontrole"}));
      rst.addColumn(new Column({caption: L("lcl_ins_controle_opm_task"), content: "ins_srtcontrole_opmerking"}));
      rst.addColumn(new Column({caption: L("lcl_ins_controle_cyclus"), content: fnCyclus, colName: "fnCyclus" }));

      // De kolom taakgroep alleen tonen als er taakgroepen zijn.
      var sqlt = "SELECT DISTINCT COALESCE(xcp.ins_srtcontroledl_xcp_groep, isc.ins_srtcontrole_groep)"
               + "  FROM ins_srtcontrole isc"
               + "     , ins_srtcontroledl_xcp xcp"
               + " WHERE isc.ins_srtcontrole_key = xcp.ins_srtcontrole_key(+)"
               + "   AND xcp.ins_scenario_key(+) = 1"
               + "   AND COALESCE(xcp.ins_srtcontroledl_xcp_groep, isc.ins_srtcontrole_groep) IS NOT NULL"
      var oRst = Oracle.Execute(sqlt);
      if (!oRst.eof)
        rst.addColumn(new Column({caption: L("lcl_ins_srtcontrole_groep"), content: fnTaakgroep, colName: "fnTaakgroep"}));
      oRst.Close();

      if (mode == 3 && mjbStatus3)
      { // Zijn er gaccordeerde en ter uitvoering staande inspecties waaraan een melding gekoppeld is?
        var sqlm = "SELECT COUNT(m.mld_melding_key) aantal"
                 + "  FROM mld_melding_object mo"
                 + "     , mld_melding m"
                 + "     , ins_deelsrtcontrole idsc"
                 + " WHERE mo.mld_melding_key = m.mld_melding_key"
                 + "   AND mo.ins_deelsrtcontrole_key = idsc.ins_deelsrtcontrole_key"
                 + "   AND mo.ins_deelsrtcontrole_key IS NOT NULL"
                 + "   AND idsc.ins_deelsrtcontrole_status IN (2, 3)";
        var oRsm = Oracle.Execute(sqlm);
        if (oRsm("aantal").Value > 0)
          rst.addColumn(new Column({caption: L("lcl_mjb_melding"), content: fnMelding, colName: "fnMelding"}));
        oRsm.Close();
      }
      rst.addColumn(new Column({caption: L("lcl_prs_kosten"), content: "kostenplaats"}));
    }
    if (fulldetails)
    {
      if (excel)
        rst.addColumn(new Column({caption: L("lcl_mjb_scen_opm"), content: "ins_srtcontrole_opmerking"}));
      rst.addColumn(new Column({caption: L("lcl_mjb_datum_org"), content: "ins_deelsrtcontrole_datum_org"}));
      rst.addColumn(new Column({caption: L("lcl_mjb_start_date"), content: "startdatum"}));
      rst.addColumn(new Column({caption: L("lcl_mjb_plan_opmerking"), content: "ins_deelsrtcontrole_plan_opm"}));
      rst.addColumn(new Column({caption: L("lcl_estate_gebouw_srtgebouw"), content: "alg_srtgebouw_omschrijving"}));
      rst.addColumn(new Column({caption: L("lcl_alg_verantw"), content: "gebouwverantwoordelijke"}));
      rst.addColumn(new Column({caption: L("ctr_discipline"), content: "taakcategorie"}));
      rst.addColumn(new Column({caption: L("lcl_mjb_call_history"), content: "meldingshistorie", datatype: "number"}));
      if (algFlexParams.anyflex)
        rst.addColumn(new Column({caption: algFlexParams.flexlabel, content: fncolFlexAlgBijlagen, colName: "fncolFlexAlgBijlagen"}));
      if (insFlexParams.anyflex)
        rst.addColumn(new Column({caption: insFlexParams.flexlabel, content: fncolFlexInsBijlagen, colName: "fncolFlexInsBijlagen"}));
    }
    for (var j = 0; j < jaren.length; j++)
    {
      if (fulldetails)
          var content = fnfnClickBedrag(String(jaren[j]));
      else
          var content = fnfnBedrag(String(jaren[j]));
      rst.addColumn(new Column({caption: String(jaren[j]),
                                colName: "IGNORE" + String(jaren[j]),  // sluit deze uit van kolommanipulaties: colName moet uniek zijn!
                                ignore: true,
                                content: content,
                                datatype: "number",
                                xmltag: "year" + String(jaren[j]),
                                columnClass: fnfncolClass(String(jaren[j])), // tdClass dan niet meer nodig.
                                fnAmount: fnfnBedragNumber(String(jaren[j])),
                                total: true
                               }));
    }
    rst.addColumn(new Column({caption: L("lcl_Total"), datatype: "number",
                              colName: "IGNORE" + L("lcl_Total"),  // sluit deze uit van kolommanipulaties: colName moet uniek zijn!
                              ignore: true,
                              content: fnTotalText,
                              tdClass: "mjbtotal",
                              fnAmount: fnTotal,
                              total: true
                             }));

    /* de mogelijke acties */
    if (mode != 3)
    {
      if (fulldetails)
      {
        rst.addAction({ action: "mjb_dragdrop",     caption: L("lcl_mjb_dragdrop"),   multi: true, multiOnce: true, onlyMulti: true });
        // De button "Terugplannen" niet bij scenario s tonen indien vinkje "Mét de actuele situatie" was aangevinkt.
        if (!(scenario > 1 && actsit))
          rst.addAction({ action: "mjb_moveYearBack", caption: L("lcl_mjb_move_back"),  multi: true, multiOnce: true, onlyMulti: true });
      }

      if (scenario == 1)
      {
        rst.addAction({ action: "insFreeze",  caption: L("lcl_mjb_freeze"), multi: true, multiOnce: true, onlyMulti: true });
        rst.addAction({ action: "insUnfreeze", caption: L("lcl_ins_unstart"), multi: true, multiOnce: true, onlyMulti: true });
        if (S("mjb_operation_external") == 1)
          rst.addAction({ action: "insFinishMJOB", caption: L("lcl_ins_finish"), multi: true, multiOnce: true, onlyMulti: true });
        if (fulldetails && S("mjb_enable_moveup") == 1)
          rst.addAction({ action: "insMoveUp",  caption: L("lcl_mjb_moveup"), multi: true, multiOnce: true, onlyMulti: true });
        if (hasWriteCTRSEN)
          rst.addAction({ action: "insAddScen", caption: L("lcl_mjb_incl_scen"), multi: true, multiOnce: true, onlyMulti: true });
      }
      else if (fulldetails && scenario > 1 && actsit && hasWriteCTRSEN)
      {
        var oRs = Oracle.Execute("SELECT ins_scenario_omschrijving FROM ins_scenario WHERE ins_scenario_key = " + scenario);
        var scen_oms = oRs("ins_scenario_omschrijving").Value;
        oRs.Close();
        rst.addAction({ action: "insAddScen", caption: L("lcl_mjb_incl_scen0").format(scen_oms), multi: true, multiOnce: true, onlyMulti: true });
      }
      // Ook "Multi wijzigen taken" voor de scenerio's.
      if (fulldetails)
        rst.addAction({ action: "insMultiEdit", caption: L("lcl_ins_multi_edit_tasks"), multi: true, multiOnce: true, onlyMulti: true });
      else if (scenario == 1)
      { // Er moeten wel actieve kosten velden aanwezig zijn anders heeft de button geen zin.
        var ins_xcp_active_cost = S("ins_xcp_active_cost");
        if (ins_xcp_active_cost > 0 && ins_xcp_active_cost < 16)
          rst.addAction({ action: "insMultiPriceChange", caption: L("lcl_mjb_change_costs"), multi: true, multiOnce: true, onlyMulti: true });
      }
    }
    else
    { // mode == 3
      rst.addAction({ action: "insExecute", caption: L("lcl_mjb_execute"), multi: true, multiOnce: true, onlyMulti: true });
      rst.addAction({ action: "insUnfreeze", caption: L("lcl_ins_unstart"), multi: true, multiOnce: true, onlyMulti: true });
      rst.addAction({ action: "insFinishMJOB", caption: L("lcl_ins_finish"), multi: true, multiOnce: true, onlyMulti: true });
    }

    var count = rst.processResultset();


    if (!excel && !print)
	  {
%>
		  <!-- LEGENDA  -->
		  <script type="text/javascript">
        function openLegenda()
        {
            var myPosition = "right top+30";
            if (elems.$originalHeaderRow && elems.$originalHeaderRow.length)
                myPosition = "right-15 top+"+(parseInt(elems.$fcltFrameHeader.css("top"))+30);
            params = { width: 500,
                       minWidth: 250,
                       minHeight: 10,
                       resizable: false,
                       position: {my: "right top", at: myPosition},
                       title: "<%=L("lcl_ins_controle_legenda")%>",
                       create: FcltMgr.fnCreateCloseButton("div#legenda")
                     };
            $('div#legenda').dialog(params).dialog('open');
            FcltMgr.resized();
        }

        $(".mjbafbouw").html("<%=I("fa-minus", {fastyle: "fas"})%>");
        $(".mjbverval").html("<%=I("fa-minus-circle", {fastyle: "fas"})%>");

		  </script>
		  <div id="legenda" style="display:none; line-height: 30px;">
		    <table id="inslegenda">
		      <tr class="mjbplanned">
		        <td title="<%= L("lcl_mjb_moved") %>"><%= L("lcl_mjb_moved") %></td>
		      </tr>
		      <tr class="mjbxcp">
		        <td title="<%= L("lcl_mjb_overruled_xcp") %>"><%= L("lcl_mjb_overruled_xcp") %></td>
		      </tr>
		      <tr class="scenerized1">
		        <td title="<%= L("lcl_mjb_scenario") %>"><%= L("lcl_mjb_scenario") %></td>
		      </tr>
		      <tr>
		        <td  class="mjbfreezed" title="<%= L("lcl_mjb_started") %>"><%= L("lcl_mjb_started") %></td>
		      </tr>
		      <tr>
		        <td  class="mjbexecute" title="<%= L("lcl_mjb_in_execution") %>"><%= L("lcl_mjb_in_execution") %></td>
		      </tr>
		      <tr>
		        <td  class="mjbcompleted" title="<%= L("lcl_mjb_completed") %>"><%= "Uitgevoerd" %></td>
		      </tr>
		      <tr>
		        <td  class="mjbrejected" title="<%= L("lcl_mjb_rejected") %>"><%= "Afgewezen" %></td>
		      </tr>
		      <tr class="mjbafbouw">
		        <td title="<%= L("lcl_mjb_phasingout") %>"></td>
		      </tr>
		      <tr class="mjbverval">
		        <td title="<%= L("lcl_mjb_becancelled") %>"></td>
		      </tr>
		      <tr class="mjbcloned">
		        <td title="<%= L("lcl_mjb_part_scenario") %>">
		          <span style="z-index:-1;"><%= L("lcl_mjb_part_scenario") %></span>
		          <span style="left:242px;"><%= I("fa-clone") %></span>
		        </td>
		      </tr>
		      <tr class="mjbcloned">
		        <td title="<%= L("lcl_mjb_part_scenario_m") %>">
		          <span style="z-index:-1;"><%= L("lcl_mjb_part_scenario_m") %></span>
		          <span style="left:242px;">*<%= I("fa-clone") %></span>
		        </td>
		      </tr>
		    </table>
		  </div>
<%
	  }
%>
    </body>
  </html>
<% ASPPAGE_END(); %>
