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

     File:           mjb_search_list_curr.asp
     Description:    Overview of the execution and progression of the approved MJOB tasks
                     Shows all active and frozen budgets until they are closed.
     Parameters:

     Context:

     Note:           Vlotte kopie van mjb_search_list. Hier kan tzt nog wel wat opgeruimd worden

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

// 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 CTRBOF rechten nodig.
// Scenario gaat alleen over de toekomst en daar heb je hier niet mee te maken. Dus je hebt hier ook niet met CTRSEN rechten te maken.
var authparamsINSUSE = user.checkAutorisation("WEB_INSUSE");
var authparamsCTRBOF = user.checkAutorisation("WEB_CTRBOF");
var hasWriteCTRBOF = authparamsCTRBOF.ALGwritelevel < 9 && authparamsCTRBOF.PRSwritelevel < 9;

var authparamsCTRUSE = user.checkAutorisation("WEB_CTRUSE", true);
var hasWriteCTRUSE = authparamsCTRUSE.ALGwritelevel < 9 && authparamsCTRUSE.PRSwritelevel < 9;

// 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;

// Rechten om de realisatie te bekijken
var authparamsMLD = user.checkAutorisation("WEB_MLDBOF", true);
var hasReadMLD = authparamsMLD && authparamsMLD.ALGreadlevel < 9 && authparamsMLD.PRSreadlevel < 9;

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

var groupby = getQParamInt("groupby");
var fulldetails = (groupby == 9); // Geen aggregate, dan kun je van alles manipuleren
var fromyear = getQParamInt("fromyear", new Date().getFullYear());

var deel = getQParam("deel", ""); // Identieficatie
var categorie_key_arr = getQParamKeyArray("categorie", []); // Categorie
//var reg_key = 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 incbtw = getQParamInt("incbtw", 0) == 1; // Lijst inclusief BTW weergeven.
var showunfin = getQParamInt("showunfin", 0) == 1; // Alleen onvoltooide regels tonen.

var scenario = getQParamInt("scenario", 1); // Scenario
var actsit = getQParamInt("actsit", 0) == 1; // Ook actuele situatie.

// 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.

// 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
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));
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,
                     dist_key_arr: dist_key_arr,
                     loc_key_arr: loc_key_arr,
                     bld_key_arr: bld_key_arr,
                     disc_key_arr: disc_key_arr,
                     insgroup_key: srtgroep_key_arr,
                     objsrt_key_arr: srtdeel_key_arr,
                     srtgebouw_key_arr: srtgebouw_key_arr,
                     groep_str_arr: groep_str_arr,
                     mjbgroup: groupby,
                     mjbsrtcontr: srtcontrole_key_arr.join(","),
                     mjbfreq: frequentie_arr.join(","),
                     mjbincbtw: incbtw,
                     mjbshowunfin: showunfin
                   };
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"]);
%>
  <html>
    <head>
<%
      FCLTHeader.Generate({ outputmode: outputmode });

      if (outputmode == 0) {
%>
      <script type="text/javascript">
        var fulldetails = <%=fulldetails? 1 : 0%> == 1;

        function naarlocatie(loc_key, deze)
        {
           if (fulldetails)
             var url = "appl/alg/alg_locatie.asp?key=" + loc_key;
           else
             var url = "appl/mjb/mjb_search.asp?autosearch=1&groupby=9<%=transitParam%>&locatie_key=" + loc_key;
           FcltMgr.openDetail(url, $(deze).text());
        }

        function naargebouw(bld_key, deze)
        {
           if (fulldetails)
             var url = "appl/alg/alg_gebouw.asp?key=" + bld_key;
           else
             var url = "appl/mjb/mjb_search.asp?autosearch=1&groupby=9<%=transitParam%>&gebouw_key=" + bld_key;
           FcltMgr.openDetail(url, $(deze).text());
        }

        function naardeel(ins_key, deze)
        {
           var url = "appl/ins/ins_deel.asp?ins_key=" + ins_key + "&urole=bo";
           FcltMgr.openDetail(url, $(deze).text());
        }

        function naarmelding(mld_key, deze)
        {
            var url = "appl/mld/mld_melding.asp?mld_key=" + mld_key;
            FcltMgr.openDetail(url, $(deze).text());
        }

        function exception(ins_key, srtcont_key, scen_key, ttl)
        {
           var url = "../ins/ins_xcp.asp?ins_key=" + ins_key + "&srtcont_key=" + srtcont_key + "&scen_key=" + scen_key + "&urole=bo";
           FcltMgr.openModalDetail(url, { titel: L("lcl_ins_change_xcp") + " " + ttl, callback: <%=bld_key_arr.length? "FcltMgr.reload ": "null"%> });
        }
      </script>
<%
      } //if (outputmode == 0)
%>
    </head>
    <body id="listbody">

<%
    // SQL van soort controles die nog een bevroren nog lopende taak hebben in het freeze jaar en eventuele jaren ervoor.

    var sql_from = "  FROM ins_deelsrtcontrole dsc"
                 + "     , ins_v_defined_inspect_xcp xcp"
                 + "     , ins_deel dl" // Als het object verwijderd is, moeten de opdrachtbedragen wel meegerekend worden.
                 + "     , ins_srtdeel isd"
                 + "     , ins_srtgroep isg"
                 + "     , ins_discipline dd"
                 + "     , alg_district d"
                 + "     , alg_locatie l"
                 + "     , alg_gebouw g"
                 + "     , alg_verdieping v"
                 + "     , alg_ruimte r"
                 + "     , mld_melding_object mo"
                 + "     , (  SELECT mo1.mld_melding_key"
                 + "               , COUNT(mo1.ins_deelsrtcontrole_key) aantal_taken"
                 + "            FROM mld_melding_object mo1"
                 + "           WHERE mo1.ins_deelsrtcontrole_key IS NOT NULL"
                 + "        GROUP BY mo1.mld_melding_key) moc";

    var sql_where = " WHERE dsc.ins_deel_key = xcp.ins_deel_key"
                  + "   AND dsc.ins_srtcontrole_key = xcp.ins_srtcontrole_key"
                  + "   AND dsc.ins_scenario_key = xcp.ins_scenario_key"
                  + "   AND xcp.ins_deel_key = dl.ins_deel_key"
                  + "   AND dl.ins_srtdeel_key = isd.ins_srtdeel_key"
                  + "   AND isd.ins_srtgroep_key = isg.ins_srtgroep_key"
                  + "   AND isg.ins_discipline_key = dd.ins_discipline_key"
                  + "   AND dl.ins_alg_ruimte_key = r.alg_ruimte_key"
                  + "   AND r.alg_verdieping_key = v.alg_verdieping_key"
                  + "   AND v.alg_gebouw_key = g.alg_gebouw_key"
                  + "   AND g.alg_locatie_key = l.alg_locatie_key"
                  + "   AND d.alg_district_key = l.alg_district_key"
                  + "   AND mo.ins_deelsrtcontrole_key(+) = dsc.ins_deelsrtcontrole_key"
                  + "   AND mo.ins_deel_key(+) = dl.ins_deel_key"
                  + "   AND mo.mld_melding_key = moc.mld_melding_key(+)"
                  + "   AND dl.ins_deel_verwijder IS NULL"
                  //+ "   AND xcp.ins_srtcontrole_periode > 0" // Als de period van de taak ondertussen op 0 is gezet, moeten de opdrachtbedragen wel meegerekend worden.
                  + "   AND xcp.ins_scenario_key = 1"
                  + "   AND xcp.ctr_ismjob = 1"
                  // Je moet read CTRBOF rechten hebben op de CTR disciplines om de taken te kunnen zien.
                  + "   AND xcp.ctr_discipline_key IN (SELECT w.ins_discipline_key"
                  + "                                    FROM fac_v_webgebruiker w"
                  + "                                       , fac_functie f"
                  + "                                   WHERE w.fac_functie_key = f.fac_functie_key "
                  + "                                     AND f.fac_functie_code = 'WEB_CTRBOF'"
                  + "                                     AND w.fac_gebruiker_prs_level_read < 9"
                  + "                                     AND w.fac_gebruiker_alg_level_read < 9"
                  + "                                     AND w.prs_perslid_key = " + user_key
                  + "                                     AND w.ins_discipline_key = xcp.ctr_discipline_key)"
                  // Vroeg filteren is *heel* goed voor performance
                  + (dist_key_arr.length
                    ? " AND xcp.ins_alg_locatie_key IN (SELECT alg_locatie_key FROM alg_locatie WHERE alg_district_key IN (" + dist_key_arr.join(",") + "))"
                    : "")
                  + (loc_key_arr.length
                    ? " AND xcp.ins_alg_locatie_key IN (" + loc_key_arr.join(",") + ")"
                    : "")
                  + (bld_key_arr.length // elders in dit bestand wordt scherper gefilterd, deze is voor de performance
                    ? " AND xcp.ins_alg_locatie_key IN (SELECT alg_locatie_key FROM alg_gebouw WHERE alg_gebouw_key IN (" + bld_key_arr.join(",") + ")"
                      + "                               UNION"
                      + "                               SELECT alg_locatie_key FROM alg_terreinsector WHERE alg_terreinsector_key IN (" + bld_key_arr.join(",") + "))"
                    : "")
                  + (disc_key_arr.length
                    ? " AND xcp.ins_discipline_key IN (" + disc_key_arr.join(",") + ")"
                    : "")
                  + (srtgroep_key_arr.length
                    ? " AND xcp.ins_srtgroep_key IN (" + srtgroep_key_arr.join(",") + ")"
                    : "")
                  + (srtdeel_key_arr.length
                    ? " AND xcp.ins_srtdeel_key IN (" + srtdeel_key_arr.join(",") + ")"
                    : "")
                  + (srtgebouw_key_arr.length // elders in dit bestand wordt scherper gefilterd, deze is voor de performance
                    ? " AND xcp.ins_alg_locatie_key IN (SELECT alg_locatie_key FROM alg_gebouw WHERE alg_srtgebouw_key IN (" + srtgebouw_key_arr.join(",") + "))"
                    : "")
                  + (groep_str_arr.length
                    ? " AND UPPER(ins_srtcontrole_groep) IN (" + safe.quoted_sql_join(groep_str_arr, true) + ")"
                    : "")
                  + (srtcontrole_key_arr.length
                    ? " AND xcp.ins_srtcontrole_key IN (" + srtcontrole_key_arr.join(",") + ")"
                    : "")
                  + (frequentie_arr.length
                    ? " AND xcp.ins_srtcontrole_periode IN (" + frequentie_arr.join(",") + ")"
                    : "")
                  + (kp_key_arr.length
                    ? " AND xcp.prs_kostenplaats_key IN (" + kp_key_arr.join(",") + ")"
                    : "")
                  + (categorie_key_arr.length
                    ? " AND xcp.ctr_discipline_key IN (" + categorie_key_arr.join(",") + ")"
                    : "")
                  + (deel
                    ? " AND dl.ins_deel_upper LIKE " + safe.quoted_sql_wild("%" + deel + "%")
                    : "")
                  + (bld_key_arr.length
                    ? " AND g.alg_gebouw_key IN (" + bld_key_arr.join(",") + ")"
                    : "")
                  + (srtgebouw_key_arr.length
                    ? " AND g.alg_srtgebouw_key IN (" + srtgebouw_key_arr.join(",") + ")"
                    : "")
                  + (showunfin
                    ? " AND dsc.ins_deelsrtcontrole_status != 6"
                    : "")
                  + "   AND dsc.ins_deelsrtcontrole_status >= 2";

    var sql_years = "SELECT DISTINCT EXTRACT(YEAR FROM dsc.ins_deelsrtcontrole_freezedate) freezedate"
                  + sql_from
                  + sql_where
                  + "   AND dsc.ins_deelsrtcontrole_key = (SELECT MAX(id2.ins_deelsrtcontrole_key)"
                  + "                                        FROM ins_deelsrtcontrole id2"
                  + "                                       WHERE id2.ins_deel_key = dsc.ins_deel_key"
                  + "                                         AND id2.ins_srtcontrole_key = dsc.ins_srtcontrole_key"
                  + "                                         AND id2.ins_scenario_key = 1)";

    var sql_list_years = "SELECT /*+ OPT_PARAM('optimizer_features_enable','12.1.0.1') */"
                       + "       LISTAGG(freezedate, ',') WITHIN GROUP (ORDER BY freezedate) listfdjaar"
                       + "  FROM (" + sql_years + ")"
                       + " WHERE freezedate >= " + fromyear;
    var oRs = Oracle.Execute(sql_list_years);
    var listfdjaar = oRs("listfdjaar").Value || -1;
    oRs.Close();
    if (listfdjaar == -1)
      var jaren = [];
    else
      var jaren = listfdjaar.split(",");

    var keyColomn = "";
    switch (groupby)
    {
      case 1:  keyColumn = "d.alg_district_key";
               break;
      case 2:  keyColumn = "g.alg_locatie_key";
               break;
      case 3:  keyColumn = "g.alg_gebouw_key";
               break;
      case 4:  keyColumn = "dl.ins_discipline_key";
               break;
      case 5:  keyColumn = "isg.ins_srtgroep_key";
               break;
      case 6:  keyColumn = "isd.ins_srtdeel_key";
               break;
      case 7:  keyColumn = "dl.ins_deel_key";
               break;
      case 8:  keyColumn = "mo.mld_melding_key";
               break;
      case 9:  keyColumn = "dl.ins_deel_key";
               break;
    }

    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(" + ") + ") *";

    // vermenigvuldigingsfactor om zo nodig incl BTW te krijgen
    var btw = (incbtw
              ? " (1 + COALESCE((SELECT fbtw.fin_btwtabelwaarde_perc"
                + "                FROM fin_btwtabelwaarde fbtw"
                + "               WHERE fbtw.fin_btwtabelwaarde_key = xcp.fin_btwtabelwaarde_key) / 100"
                + "           , 0)) "
              : "1")

    // om het wat leesbaar te houden een functietje
    function SumTaskOrdersSQL(fase)
    {
        // fase: 1 klare opdrachten, 0: lopende opdrachten
        // Geraamd:    Uitgegeven(5), Technisch voltooid(6) en Geaccepteerd(8)
        // Definitief: Verwerkt(7) en Kosten voltooid(9)
        // TODO: uitwerken hoe dat precies met BTW zit; als de Kostensoort van de melding/opdracht Incl BTW is,
        //       dan is het bedrag van mld_opdr_kosten in principe al met BTW en zou mld_opdr_kosten_btw (nieuw)
        //       het btw-deel daarvan voorstellen. Dan hoef je dat er dus niet meer bij op te tellen. Nu kijken we
        //       hier nog helemaal niet naar de kostensoort, en de precieze werken is tbd. Te zijner tijd.
        // opdrachten waarvan de kosten niet meedoen (bv offerteaanvragen) niet meenemen.
        // opdrachten die nog niet goedgekeurd of gefiatteerd zijn doen ook nog niet mee.
        var osql = "SELECT CASE"
                 + "       WHEN moc.aantal_taken IS NULL"
                 + "       THEN 0"
                 + (fase == 3
                   ? "     ELSE (SUM(f.fin_factuur_totaal)" + (incbtw? " + SUM(f.fin_factuur_totaal_btw)" : "") + ") / moc.aantal_taken"
                   : "     ELSE (SUM(mld_opdr_kosten)" + (incbtw? " + SUM(mld_opdr_kosten_btw)" : "") + ") / moc.aantal_taken")
                 + "       END"
                 + " FROM mld_opdr o"
                 + "    , mld_typeopdr mto"
                 + (fase == 3
                   ? "  , fin_factuur f"
                   : "")
                 + " WHERE o.mld_melding_key = mo.mld_melding_key"
                 + "   AND o.mld_typeopdr_key = mto.mld_typeopdr_key"
                 + "   AND mto.mld_typeopdr_kosten = 1"
                 + (fase == 3
                   ? " AND o.mld_opdr_key = f.mld_opdr_key"
                   : " AND o.mld_statusopdr_key NOT IN (1, 2, 3, 4, 10)"
                     + " AND o.mld_statusopdr_key IN "+ (fase == 1 ? "(7,9)" : "(5,6,8)"))
                 + "   AND mo.ins_deelsrtcontrole_key = dsc.ins_deelsrtcontrole_key"
                 + " GROUP BY moc.aantal_taken";
        return "(" + osql + ")";
    }

    var sql_cost = "SELECT (SELECT sd.ins_srtdiscipline_prefix"
                 + "          FROM ins_srtdiscipline sd"
                 + "             , mld_discipline md"
                 + "             , mld_stdmelding std"
                 + "             , mld_melding m"
                 + "         WHERE m.mld_melding_key = mo.mld_melding_key"
                 + "           AND std.mld_stdmelding_key = m.mld_stdmelding_key"
                 + "           AND md.ins_discipline_key = std.mld_ins_discipline_key"
                 + "           AND sd.ins_srtdiscipline_key = md.ins_srtdiscipline_key) melding_prefix"
                 + "     , mo.mld_melding_key melding"
                 + "     , (SELECT m.mld_melding_onderwerp"
                 + "          FROM mld_melding m"
                 + "         WHERE mld_melding_key = mo.mld_melding_key) onderwerp"
                 + "     , d.alg_district_key"
                 + "     , d.alg_district_omschrijving"
                 + "     , l.alg_locatie_omschrijving"
                 + "     , l.alg_locatie_key"
                 + "     , g.alg_gebouw_code"
                 + "     , g.alg_gebouw_naam"
                 + "     , g.alg_gebouw_key"
                 + "     , dl.ins_deel_omschrijving"
                 + "     , xcp.ins_deel_aantal"
                 + "     , xcp.ins_srtdeel_eenheid"
                 + "     , dl.ins_deel_opmerking"
                 + "     , dd.ins_discipline_omschrijving"
                 + "     , isg.ins_srtgroep_omschrijving"
                 + "     , isd.ins_srtdeel_omschrijving"
                 + "     , xcp.ins_srtcontrole_omschrijving"
                 + "     , xcp.ins_srtcontrole_opmerking"
                 + "     , " + keyColumn + " keyColumn"
                 + "     , dsc.ins_deel_key"
                 + "     , dsc.ins_srtcontrole_key"
                 + "     , dsc.ins_scenario_key"
                 + "     , dsc.ins_deelsrtcontrole_freezedate"
                 + "     , dsc.ins_deelsrtcontrole_datum"
                 + "     , dsc.ins_deelsrtcontrole_status"
                 + "     , dsc.ins_deelsrtcontrole_key"
                 + "     , EXTRACT( YEAR FROM LEAST(COALESCE(g.alg_gebouw_vervaldatum"
                 + "                                       , dl.ins_deel_vervaldatum"
                 + "                                       , COALESCE(xcp.ins_srtcontroledl_xcp_eind, xcp.ins_srtcontrole_eind))"
                 + "                              , COALESCE(COALESCE(xcp.ins_srtcontroledl_xcp_eind, xcp.ins_srtcontrole_eind)"
                 + "                                       , g.alg_gebouw_vervaldatum"
                 + "                                       , dl.ins_deel_vervaldatum)"
                 + "                              , COALESCE(dl.ins_deel_vervaldatum"
                 + "                                       , COALESCE(xcp.ins_srtcontroledl_xcp_eind, xcp.ins_srtcontrole_eind)"
                 + "                                       , g.alg_gebouw_vervaldatum))) vervaljaar"
                 + "     , xcp.ins_srtcontrole_afbouwtijd afbouwtijd"
                 + "     , (SELECT LISTAGG(isc1.ins_scenario_omschrijving, ', ')"
                 + "               WITHIN GROUP (ORDER BY isc1.ins_scenario_omschrijving)"
                 + "          FROM ins_srtcontroledl_xcp xcp1"
                 + "             , ins_scenario isc1"
                 + "         WHERE xcp1.ins_scenario_key = isc1.ins_scenario_key"
                 + "           AND xcp1.ins_srtcontrole_key = xcp.ins_srtcontrole_key"
                 + "           AND xcp1.ins_deel_key = xcp.ins_deel_key) scenario_oms"
                 + "     , ins_srtcontroledl_xcp_key"
                 + "     , COALESCE(dsc.ins_deelsrtcontrole_datum, dsc.ins_deelsrtcontrole_freezedate) freezedatum"
                 + "     , EXTRACT(YEAR FROM COALESCE(ins_deelsrtcontrole_datum, ins_deelsrtcontrole_freezedate)) freezejaar"
                 + "     , EXTRACT(YEAR FROM COALESCE(ins_deelsrtcontrole_datum, ins_deelsrtcontrole_freezedate)) freezedatejaar"
                 + "     , " + btw + " * dsc.ins_deelsrtcontrole_freezecost ins_deelsrtcontrole_freezecost"
                 + "     , " + btw + " * dsc.ins_deelsrtcontrole_freezecost begrootbedrag"  // hetzelfde, maar dan buiten de pivot
                 + "     , " + SumTaskOrdersSQL(1) + "besteedbedrag"
                 + "     , " + SumTaskOrdersSQL(0) + "geraamdbedrag"
                 + "     , " + SumTaskOrdersSQL(3) + "factuurbedrag"
                 + sql_from
                 + sql_where
                 + "   AND EXTRACT(YEAR FROM ins_deelsrtcontrole_freezedate) IN (" + listfdjaar + ")";


    if (!fulldetails)
    {
      var fields = [];
      if (groupby == 8)
      {
        fields.push("melding_prefix");
        fields.push("melding");
        fields.push("onderwerp");
      }
      if (groupby == 1 || groupby == 2 || groupby == 3 || groupby == 8 || moredetail)
      {
        fields.push("alg_district_omschrijving");
        if (groupby == 2 || groupby == 3 || groupby == 8 || moredetail)
        {
          fields.push("alg_locatie_key");
          fields.push("alg_locatie_omschrijving");
          if (groupby == 3 || groupby == 8 || moredetail)
          {
            fields.push("alg_gebouw_key");
            fields.push("alg_gebouw_naam");  // en code?
          }
        }
      }
      if (groupby >= 4 && groupby <= 7 || moredetail)
        fields.push("ins_discipline_omschrijving");
      if (groupby >= 5 && groupby <= 7 || moredetail)
        fields.push("ins_srtgroep_omschrijving");
      if (groupby == 6 || groupby == 7 || moredetail)
        fields.push("ins_srtdeel_omschrijving");
      if (groupby == 7) // bij omschrijving hoort ook aantal met eenheid.
      {
        fields.push("ins_deel_aantal");
        fields.push("ins_srtdeel_eenheid");
        fields.push("ins_deel_omschrijving");
      }

      var sql_cost = "SELECT " + fields.join(", ")
                   + "     , keyColumn"
                   + (keyColumn == "dl.ins_deel_key"
                     ? "   , ins_deel_opmerking"
                     : "")
                   + "     , SUM(ins_deelsrtcontrole_freezecost) ins_deelsrtcontrole_freezecost"
                   + (S("mjb_operation_external") == 0
                     ? "   , SUM(besteedbedrag) besteedbedrag"
                       + " , SUM(geraamdbedrag) geraamdbedrag"
                       + " , SUM(begrootbedrag) begrootbedrag"
                       + " , SUM(factuurbedrag) factuurbedrag"
                     : "")
                   + "     , freezedatejaar"
                   + "  FROM (" + sql_cost + ")"
                   + " GROUP BY " + fields.join(", ")
                   + "         , keyColumn"
                   + (keyColumn == "dl.ins_deel_key"
                     ? "     , ins_deel_opmerking"
                     : "")
                   + "        , freezedatejaar";
    }
    else
    {
      // Regels worden samengenomen als de realisatie kolommen niet worden getoond (S("mjb_operation_external") == 1).
      var sql_cost = "SELECT alg_gebouw_naam"
                   + "     , alg_gebouw_key"
                   + "     , ins_deel_omschrijving"
                   + "     , ins_deel_aantal"
                   + "     , ins_srtdeel_eenheid"
                   + "     , ins_deel_opmerking"
                   + "     , ins_srtcontrole_omschrijving"
                   + "     , ins_srtcontrole_opmerking"
                   + "     , keyColumn"
                   + "     , ins_deel_key"
                   + "     , ins_srtcontrole_key"
                   + "     , ins_scenario_key"
                   + "     , ins_srtcontroledl_xcp_key"
                   + "     , freezedatejaar"
                   + "     , ins_deelsrtcontrole_freezecost"
                   + "     , melding_prefix"
                   + "     , melding"
                   + (S("mjb_operation_external") == 0 // Realisatie binnen de administratie van Facilitor. Realisatie kolommen tonen.
                     ? "   , begrootbedrag"
                       + " , besteedbedrag"
                       + " , geraamdbedrag"
                       + " , factuurbedrag"
                     : "")
                   + "     , ins_deelsrtcontrole_key"
                   + "  FROM (" + sql_cost + ")";
    }

    var sql = "SELECT *"
            + "  FROM (" + sql_cost + ") c"
            + " PIVOT (SUM(ins_deelsrtcontrole_freezecost)"
            + (fulldetails
              ? "   , MAX(ins_deelsrtcontrole_key) ins_deelsrtcontrole_key"
              : "")
            + "        FOR freezedatejaar IN (" + listfdjaar + "))";

    if (showunfin)
    {
      for (var j = 0; j < jaren.length; j++)
      {
        if (j == 0)
          sql += " WHERE \"" + jaren[j] + "\" IS NOT NULL";
        else
          sql += "    OR \"" + jaren[j] + "\" IS NOT NULL";
      }
    }

    sql += " ORDER BY " + (groupby == 8? "keyColumn" : "1");

    for (var i = 2; i < groupby; i++)
    {
      sql += "," + String(i)
    }


    // Functions of 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.insScenKey = oRs("ins_scenario_key").Value;
      }

      return JSON.stringify(data);
    }

    function fnrowClass(oRs)
    {
        if (S("mjb_operation_external") == 0)
        {
          // Ooit nog eens: een gradient oid van groen naar rood evenredig met de procentuele uitnutting
          var busy = oRs("besteedbedrag").Value + oRs("geraamdbedrag").Value != 0;
          var saldo = oRs("begrootbedrag").Value - oRs("besteedbedrag").Value - oRs("geraamdbedrag").Value;
          var lclass = "";
          if (saldo < 0)
              lclass = "mjbexpired";
          else
              lclass = (busy ? "mjbbusy" : "mjbwaiting");
        }
        else
          lclass = "mjbwaiting";
        return lclass;
    }


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

    function fnGebouw(oRs)  // geen terreinen kennelijk
    {
      if (hasReadALGUSE || hasReadALGMAN)
      {
        return "<span class='details' title='{2}' onclick='naargebouw({0}, this)'>{1}</span>".format(oRs("alg_gebouw_key").Value, safe.html(oRs("alg_gebouw_naam").Value), (fulldetails ? safe.htmlattr(L("lcl_estate_gebouw_title")): L("ins_srtcontrole_m")));
      }
      else
        return safe.html(oRs("alg_gebouw_naam").Value);  // kan me de code hierbij nog wel voorstellen, ging het hier niet om? todo nagaan
    }

    function fnDeel(oRs)
    { // Alleen voor groupby Element(7) en Taak(9)
      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), (oRs("ins_deel_opmerking").Value == null ? safe.htmlattr(L("lcl_mld_deel_details")) : safe.htmlattr(oRs("ins_deel_opmerking").Value)));
      }
      else
        return "<span title='{2}'>{1}</span>".format(oRs("keyColumn").Value, safe.htmlattr(oRs("ins_deel_omschrijving").Value), safe.htmlattr(oRs("ins_deel_opmerking").Value));
    }

    function fnStatus(oRs)
    {
      return ins.getinspectstatustext(oRs("ins_deelsrtcontrole_status").Value);
    }

    function fnSrtcontrole(oRs)
    {
      var hasXcp = oRs("ins_srtcontroledl_xcp_key").Value != null;
      if ((hasXcp && hasReadINSMAN) || (hasWriteCTRUSE && 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>" // TODO, maar we willen zeker niet kunnen overrulen, wel zien. ins_xcp moet dat frozen zijn herkennen
        return "<span>{1}</span>"  // dus deze dan maar voorlopig even
                            .format(safe.htmlattr(fncall),
                                    safe.html(oRs("ins_srtcontrole_omschrijving").Value));
      }
      else
        return safe.html(oRs("ins_srtcontrole_omschrijving").Value);
    }

    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(col) // Voor optellen
    {
      return function (oRs)
      {
          return Math.round(oRs(col).Value);
      }
    }

    function totalShow(column, rowNum)
    {
      return safe.curr(column.totalsum, true);
    }

    function fnClickMelding(oRs)
    {
        var melding = oRs("melding").Value || "";
        var melding_prefix = oRs("melding_prefix").Value || "";
        var v = melding_prefix + melding;

        if (authparamsMLD && S("mjb_operation_external") == 0)  // dan kun je klikken naar de melding
        {
          var fncall = "naarmelding({0})".format(melding);
          return "<span class='details' onclick='{0}'>{1}</span>".format(safe.htmlattr(fncall), v);
        }
        else
          return v;
    }

    function fnfncolClass(jaar)
    {
      return function (oRs)
      {
        return "";
      }
    }

    function fnBegrootBedrag(oRs)
    {
      return safe.curr(Math.round(oRs("begrootbedrag").Value), true);
    }
    function fnBesteedBedrag(oRs)
    {
      return safe.curr(Math.round(oRs("besteedbedrag").Value), true);
    }
    function fnGeraamdBedrag(oRs)
    {
      return safe.curr(Math.round(oRs("geraamdbedrag").Value), true);
    }
    function fnResteertBedrag(oRs)
    {
      return safe.curr(Math.round(oRs("begrootbedrag").Value-oRs("besteedbedrag").Value-oRs("geraamdbedrag").Value), true);
    }
    function fnFactuurBedrag(oRs)
    {
      return safe.curr(Math.round(oRs("factuurbedrag").Value), true);
    }
    function fnResteertBedragAmount(oRs)
    {
      return Math.round(oRs("begrootbedrag").Value-oRs("besteedbedrag").Value-oRs("geraamdbedrag").Value);
    }

    var buttons = [];
    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: "mjobctable",
                                   rowData: fnrowData,
                                   rowClass: fnrowClass,
                                   totalShow: totalShow,
                                   flexModule: "INS",
                                   multiple: true,
                                   filterParams: filterParams,
                                   outputmode: outputmode,
                                   title: (S("mjb_operation_external") == 0) ? L("lcl_mjb_begroting_cur") : L("lcl_mjb_begroting_curx"),
                                   showAll: showall,
                                   buttons: buttons
                                 });

    if (groupby == 8)
    {
      rst.addColumn(new Column({caption: L("lcl_mjb_melding"), content: fnClickMelding}));
      rst.addColumn(new Column({caption: L("lcl_mld_subject"), content: "onderwerp"}));
    }
    if (groupby == 1 || groupby == 2 || groupby == 3 || groupby == 8 || moredetail == 2)
      rst.addColumn(new Column({caption: L("lcl_district"), content: "alg_district_omschrijving"/*, purpose: (dist_key > -1 ? PRINTING_ONLY : PRINT_AND_VIEW)*/}));
    if (groupby == 2 || groupby == 3 || groupby == 8 || moredetail == 2)
      rst.addColumn(new Column({caption: L("lcl_location"), content: fnLocatie }));
    if (fulldetails || groupby == 3 || groupby == 8 || moredetail == 2)
      rst.addColumn(new Column({caption: L("lcl_building"), content: fnGebouw }));
    if (groupby < 8 || 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 == 7 || groupby == 9)
    {
      rst.addColumn(new Column({caption: L("lcl_ins_object"), content: fnDeel}));
      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 (fulldetails)
    {
      rst.addColumn(new Column({caption: L("lcl_ins_controle_srt"), content: fnSrtcontrole, tooltip: "ins_srtcontrole_opmerking"}));
      // PF: deze status wordt pas zinvol wanneer er meerdere statussen kunnen zijn hier
      //     dus wanneer er een statusfilter oid komt waarmee je ook nog naar de historie kunt, ooit.
      //rst.addColumn(new Column({caption: L("lcl_ins_status"), content: fnStatus}));
      rst.addColumn(new Column({caption: L("lcl_mjb_melding"), content: fnClickMelding}));
    }
    for (var j = 0; j < jaren.length; j++)
    {
      var content = fnfnBedrag(String(jaren[j]));

      // Het bevroren budget per jaar
      rst.addColumn(new Column({caption: String(L("lcl_mjb_begroot") + " " + jaren[j]),
                                datatype: "number",
                                content: content,
                                columnClass: fnfncolClass(String(jaren[j])),
                                total: true,
                                fnAmount: fnfnBedragNumber(String(jaren[j]))
                               }));
    }

    if (S("mjb_operation_external") == 0) {
        // De som van de bijbehorende afgeronde opdrachten
        rst.addColumn(new Column({caption: L("lcl_mjb_gerealiseerd"),
                                  datatype: "number",
                                  content: fnBesteedBedrag,
                                  total: true,
                                  fnAmount: fnfnBedragNumber("besteedbedrag")
                                 }));
        // De som van de bijbehorende lopende opdrachten
        rst.addColumn(new Column({caption: L("lcl_mjb_geraamd"),
                                  datatype: "number",
                                  content: fnGeraamdBedrag,
                                  total: true,
                                  fnAmount: fnfnBedragNumber("geraamdbedrag")
                                 }));
        // Het saldo budget-besteed-geraamd
        rst.addColumn(new Column({caption: L("lcl_mjb_resteert"),
                                  datatype: "number",
                                  content: fnResteertBedrag,
                                  total: true,
                                  fnAmount: fnResteertBedragAmount
                                 }));
        // De som van de bijbehorende facturen
        rst.addColumn(new Column({caption: L("lcl_mjb_gefactureerd"),
                                  datatype: "number",
                                  content: fnFactuurBedrag,
                                  total: true,
                                  fnAmount: fnfnBedragNumber("factuurbedrag")
                                 }));
    }
    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: 250,
                         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();
          }
        </script>
        <div id="legenda" style="display:none; line-height: 30px;">
          <table id="inslegenda">
            <tr class="mjbbusy">
              <td title="<%= L("lcl_mjb_busy") %>"><%= L("lcl_mjb_busy") %></td>
            </tr>
            <tr class="mjbwaiting">
              <td title="<%= L("lcl_mjb_waiting") %>"><%= L("lcl_mjb_waiting") %></td>
            </tr>
            <tr class="mjbexpired">
              <td title="<%= L("lcl_mjb_expired") %>"><%= L("lcl_mjb_expired") %></td>
            </tr>
          </table>
        </div>
<%
    }
%>
    </body>
  </html>
<% ASPPAGE_END(); %>
