<% /*
     $Revision$
     $Id$

    File:               res_list.inc
    Description:        Show an overview of reservations in list-form,
                        which meets with the given requirements
    Parameters:
        urole           user role (fe, fo, bo, mi)
        outputmode      behave in an output mode, print to 0 = screen, 1 = printer, 2 = excel, etc.
        showall         show all orders which meets with the given requirements
        datefrom        search for reservations at the selected date-month-year
        dateto          search for reservations at the selected date-month-year
        res_key         search for reservation with the given reservation key
        reg_key         search for contracts with the given regio key
        dist_key        search for contracts with the given district key
        loc_key         search for reservations for the selected location
        bld_key         search for reservations for the selected building
        floor_key       search for reservations for the selected floor
        room_key        search for reservations for the selected room
        act_key         search for reservations witch the selected activity
        srtact          search for reservations witch the selected srt activity
        searchtext      search for reservations with the searchtext in description or remark
        kp              search for reservations with the given account text in account description
        requestor_key   search for reservations for selected requestor
        host_key        search for reservations for selected host
        dep_key         search for reservations for the selected department
        room_key_arr    search for reservations with the selected room categories/types
        obj_key_arr     search for reservations with the selected objects categories/types
        art_key_arr     search for reservations with the selected articles categories/types
        article_arr     search for reservations with the selected articles
        artgroup        search for reservations with the selected article group
        resstatus       search for reservations with the selected reservation FO status
        roomcat         search for room reservations
        objcat          search for object reservations
        artcat          search for article reservations
        res_actual      search for actual reservations
        res_deleted     search for res_deleted reservations
        res_open        search for reservations which are open
        res_closed      search for reservations which are closed
        res_approved    search for reservations which are approved
        res_notapproved search for reservations which are not approved
        res_tobeapproved search for reservations which heave to be approved
        res_noshowonly  show noshow's only
        sortout         sort out the reservations by
        groupres        groupres the reservations by
    Context:            Search action from res_fefo_search.asp or res_bomi_search form
    Note:
    TODO:
    de afhankelijkheden van urole moeten er uit! Deze functie levert een lijst op die voldoet aan de criteria
    en gegeven de user en de autorisatie. Punt!

*/
%>

<!-- #include file="../Shared/discx3d.inc" -->
<!-- #include file="../Shared/json2.js" -->
<!-- #include file="../Shared/resultset_table_v2.inc" -->
<!-- #include file="../Shared/rater.inc" -->
<!-- #include file="./res.inc" -->
<!-- #include file="../Shared/getkenmerksql.inc" -->

<%
FCLTHeader.Requires({ plugins:["jQuery"],
                      js: ["../res/res_list.js"]
                    });

function res_list (pautfunction, params)
{ // VALIDATE AND PREPARE
  // Als een parameter niet gedefinieerd of null is, dan doet-ie niks
  // anders wordt die verondersteld een zinvolle waarde te hebben
  // NB: -1 is vaak geen zinvolle waarde; null had het dan moeten zijn!

  // Valid and supported parameters are:
  // params.urole           : the usuals two-letter lowercase string
  // params.outputmode      : print to 0 = screen, 1 = printer, 2 = excel, etc.
  // params.showall         : boolean (true | false)
  // params.datefrom        : date
  // params.dateto          : date
  // params.res_key         : key
  // params.reg_key         : key
  // params.dist_key        : key
  // params.loc_key         : key
  // params.bld_key         : key
  // params.floor_key       : key
  // params.room_key        : key
  // params.act_key         : key
  // params.suppress_cont   : boolean (true | false)
  // params.searchtxt       : wildcard string
  // params.dep_key         : key
  // params.kp              : wildcard string
  // params.requestor_key   : key
  // params.host_key        : key
  // params.dep_key         : key
  // params.room_key_arr    : Array met keys
  // params.obj_key_arr     : Array met keys
  // params.art_key_arr     : Array met keys
  // params.article_arr     : Array met keys
  // params.artgroup        : string met keys
  // params.resstatus       : key
  // params.roomcat         : boolean (true | false)
  // params.objcat          : boolean (true | false)
  // params.artcat          : boolean (true | false)
  // params.res_actual      : boolean (true | false)
  // params.res_deleted     : boolean (true | false)
  // params.res_open        : boolean (true | false)
  // params.res_closed      : boolean (true | false)
  // params.res_closed      : boolean (true | false)
  // params.res_approved    : boolean (true | false)
  // params.res_notapproved : boolean (true | false)
  // params.sortout         : key
  // params.groupres        : key

  // De functie checkAutorisation(autfunction) geeft een Response.End indien er geen autorisatie voor autfunction wordt gevonden
  var authparams = user.checkAutorisation(pautfunction);
  var authparamsRESNOS = user.checkAutorisation("WEB_RESNOS", true);

  var urole = params.urole;
  var fronto = (urole == "fo");
  var backo = (urole == "bo");
  var minfo = (urole == "mi"); // NOT APPLICABLE?
  var frontend = (urole == "fe" || (!fronto & !backo & !minfo));

  // Voor resulttable de globalen zetten; zou nog anders moeten.
  var outputmode = params.outputmode; // print to 0 = screen, 1 = printer, 2 = excel, etc.
  var print = (outputmode == 1 || outputmode == 5);
  var excel = (outputmode == 2 || outputmode == 6);
  var formString = params.formString;
  var showall = params.showall;

  var datefrom = params.datefrom;
  var dateto = params.dateto;
  var res_key = params.res_key;
  var reg_key = params.reg_key;
  var dist_key = params.dist_key;
  var loc_key = params.loc_key;
  var bld_key = params.bld_key;
  var floor_key = params.floor_key;
  var room_key = params.room_key;
  var act_key = params.act_key;
  var suppress_cont = params.suppress_cont;
  var srtact = params.srtact;
  var searchtext = params.searchtext;
  var dep_key = params.dep_key;
  var kp = params.kp;
  var requestor_key = params.requestor_key;
  var host_key = params.host_key;
  var room_key_arr = params.room_key_arr || [];
  var obj_key_arr = params.obj_key_arr || [];
  var art_key_arr = params.art_key_arr || [];
  var article_arr = params.article_arr || [];
  var artgroup = params.artgroup;
  var resstatus = params.resstatus;
  var roomcat = params.roomcat || res_key > 0;
  var objcat = params.objcat || res_key > 0;
  var artcat = params.artcat || res_key > 0;
  var res_actual = params.res_actual;
  var res_deleted = params.res_deleted;
  var res_open = params.res_open;
  var res_closed = params.res_closed;
  var res_approved = params.res_approved;
  var res_notapproved = params.res_notapproved;
  var res_tobeapproved = params.res_tobeapproved;
  var sortout = params.sortout;
  var groupres = params.groupres;
  var flags = params.flags||[];

  // Als er wel artikelen zijn geselecteerd maar geen verbruiksartikel catalogus, dan de catalogussen erbij zoeken zodat we daar ook op kunnen filteren.
  // Anders komen ook nog alle ruimte en object reserveringen in de lijst.
  var article_disc_arr = new Array();
  article_disc_arr = article_disc_arr.concat(art_key_arr);
  if (art_key_arr.length == 0 && article_arr.length > 0)
  {
    var sql = "SELECT ra.res_discipline_key"
            + "  FROM res_artikel ra"
            + " WHERE ra.res_artikel_key IN (" + article_arr.join(",") + ")";
    oRs = Oracle.Execute(sql);
    while (!oRs.eof)
    {
      article_disc_arr.push(oRs("res_discipline_key").Value);
      oRs.MoveNext();
    }
  }

  // Berekenen is duur en niet altijd nodig
  var withprices = (groupres == 4
                 || groupres == 5
                 || groupres == 6
                 || groupres == 7
                 || groupres == 8
                 || groupres == 9
                 || groupres == 10
                 || groupres == 11
                 || groupres == 12
                 || groupres == 13
                 || groupres == 14);
%>

  <html>
    <head>
<%
      FCLTHeader.Generate({ outputmode: outputmode });
%>
      <script type="text/javascript">
        var urole = "<%=urole%>";
        var groupres = "<%=groupres%>";
        var user_naam = "<%=safe.jsstring(user.naam())%>";
        var todayString = "<%=toDateString(new Date())%>";
        // For BO/MI functions
        var res_closed = (<%=res_closed? 1 : 0%> == 1)
      </script>

    </head>
    <body id="listbody">

<%

  // Functie fncolFlags kan in alle overzichten worden gebruikt.
  function fncolFlags(oRs)
  {
    var reskey = oRs("rsv_ruimte_key").Value; // rsv_ruimte_key
    var flagkey = oRs("res_rsv_ruimte_flag").Value || 0;
    var ttl = L("lcl_res_flag" + flagkey);
    var displ = flagkey||"";

    if (print)
    {
        if (flagkey != 0) displ = safe.html(ttl);  // else blijft-ie gewoon leeg
    }
    else if (excel)  // dan gewoon maar de code, handig groeperen
    {
        displ = flagkey||"";
    }
    else  // maak er dan nog leuke plaatjes van
    {
        if (flagkey == 0)
            var flagimg = "<i id='resflagimg"+reskey+"' flagkey='0' class='fa fa-circle-o resflag"+flagkey+"'>";
        else
            var flagimg = "<i id='resflagimg"+reskey+"' flagkey='"+flagkey+"' class='fa fa-circle resflag"+flagkey+"'>";
        // Met hidden flagkey voor sortering. 999 zorgt dat bij 1 keer sorteren de gevlagde direct bovenaan staan
        displ = "<div " + ((urole == "bo" || urole == "fo") ? "onclick='toggleFlag(event, "+ reskey +");'":"")
              + " title='"+safe.htmlattr(ttl)+"'>"
              + flagimg
              + "<span style='display:none'>"+(flagkey||999)+"</span></div>";
    }
    return displ;
  }

  function fncolOordeel(oRs)
  {
    var result = null;
    var displ_val = oRs("oordeel").Value;
    var displ_txt = oRs("oordeel_opm").Value;
    if (displ_val && displ_val != 0)
    {
      if (excel || print)
        result = "<span id='oordeel' title='" + safe.htmlattr(displ_txt)+"'>" + displ_val + "</span>";
      else
        result = rating.stars(displ_val, {rating: {id: "oordeel", note: displ_txt}});
    }
    return result;
  }

  function fncolOordeelAvg(oRs)
  {
    var result = null;
    var displ_val = oRs("oordeel").Value;
    if (displ_val && displ_val != 0)
    {
      if (excel || print)
        result = "<span id='oordeel'>" + safe.displayfloat(displ_val, 1) + "</span>";
      else
        result = rater(displ_val, {readonly: true});
    }
    return result;
  }

        /***** Build sql *****/
        // WITH-aliassen eerst
        thePerslid = " thePerslid AS"
                   + " (SELECT prs_perslid_key"
                   + ", prs_perslid_telefoonnr"
                   + ", prs_afdeling_key"
                   + ", " + S("prs_pers_string")  + " naam FROM prs_perslid p)"

        theResrsv =  " theResrsv AS"
                   + " (SELECT *"
                   + "    FROM res_rsv_ruimte WHERE 1=1";

      if (res_key)
          theResrsv += " AND res_reservering_key = " + res_key
      else
      {   // If there is no res_key then determine sql_date
          // If from and to are given both are used
          // If only one of from and to are give, this is used as a (1) day, not an half open interval
          // 20-10-2009 9:46:28/PF
          datefrom = datefrom || dateto;
          dateto = dateto || datefrom;
          if (datefrom && dateto)
          {
            var ora_date1 = datefrom.beginToSQL();
            var ora_date2 = dateto.endToSQL();
            // Er staan indexen op TRUNC(res_rsv_ruimte_van,'DD') en TRUNC(res_rsv_ruimte_tot,'DD')
            // waardoor onderstaande met de redundante 'TRUNC's een stuk sneller is
            // Hmm, bij nader inzien lijken de indexen niet veel verschil te maken. Haal echter
            // hieronder een (redundante) vergelijking weg en het wordt langzamer
            theResrsv += " AND res_rsv_ruimte_van < " +  ora_date2
                       + "  AND res_rsv_ruimte_tot > " + ora_date1
                       + "  AND TRUNC(res_rsv_ruimte_van, 'DD') <= " + dateto.toSQL()
                       + "  AND TRUNC(res_rsv_ruimte_tot, 'DD') >= " + datefrom.toSQL()
                       + (suppress_cont
                         ? " AND (TRUNC(res_rsv_ruimte_van, 'DD') >= " + datefrom.toSQL() + " OR TRUNC(res_rsv_ruimte_tot, 'DD') <= " + dateto.toSQL() + ")"
                         : "");
          }
          if (resstatus)
              theResrsv += " AND res_status_fo_key = " + resstatus;

          // Aanvrager
          if (requestor_key)
              theResrsv += " AND res_rsv_ruimte_contact_key = " + requestor_key;

          if (searchtext) // search text in description and remark
              theResrsv += " AND (UPPER(res_rsv_ruimte_omschrijving) LIKE "+safe.quoted_sql_wild("%" + searchtext + "%")
                        + " OR UPPER(res_rsv_ruimte_opmerking) LIKE "+safe.quoted_sql_wild("%" + searchtext + "%") + ")";

          if (host_key)
              theResrsv += " AND res_rsv_ruimte_host_key = " + host_key;

          // Flags
          if (params.flags && params.flags.length > 0 && params.flags.length < S("res_reservering_flags"))
          {
              theResrsv += " AND res_rsv_ruimte_flag IN (" + params.flags.join(",") + ")";
          }
      }

      if (frontend) //  Altijd de FE-autorisatie erop
      {
          var prsKeys = user.collegakeylist();

          theResrsv += " AND (res_rsv_ruimte_contact_key IN (" + prsKeys + ")"
                     + "  OR res_rsv_ruimte_host_key IN (" + prsKeys + "))";
      }

      theResrsv += ")";

      if (frontend || fronto)
      { // Make ResultsetTable for FE or FO
        // RES_RSV_ROOM
        sqlR  = "SELECT rm.res_reservering_key"
              + ",      r.res_reservering_ispool"
              + ",      rm.res_rsv_ruimte_key"
              + ",      rm.res_rsv_ruimte_omschrijving descr"
              + ",      rm.res_status_bo_key"
              + ",      rm.res_status_fo_key"
              + ",      rm.res_rsv_ruimte_flag"
              + ",      rm.res_rsv_ruimte_prijs"
              + ",      rm.res_rsv_ruimte_dirtlevel dirtlevel"
              + ",      rm.res_rsv_ruimte_afgerond"
              + "," + lcl.xsql('rr.res_ruimte_nr', 'rr.res_ruimte_key') + " waar"
              + ",      res_rsv_ruimte_van datumvan"
              + ",      res_rsv_ruimte_tot datumtot"
              + ",      pcontact.naam contact"
              + ",      pHost.naam gastheer"
              + ",      res_rsv_ruimte_contact_key"
              + ",      res_rsv_ruimte_host_key"
              + ",      'R' AS restype"
              + ",      rm.res_rsv_ruimte_bezoekers bezoekers"
              + ",      rm.res_rsv_ruimte_verwijder" // Als verwijderd dan wordt hij readonly
              + ",      (SELECT prs_afdeling_key FROM prs_perslid WHERE prs_perslid_key = rm.res_rsv_ruimte_host_key) prs_afdeling_key"
              + ",      rm.res_rsv_ruimte_opmerking remark"
              + ",      rm.res_rsv_ruimte_volgnr"
              + ",      sa.res_srtactiviteit_prefix"
              + ",      rr.res_ruimte_vervaldatum"
              + ",      ract.res_activiteit_meteindtijd"
              + "  FROM theResrsv rm"
              + ",      res_reservering r"
              + ",      res_ruimte_opstelling ro"
              + ",      res_ruimte rr"
              + ",      alg_v_ruimte_gegevens_all rg"
              + ",      alg_district di"
              + ",      res_v_aanwezigalg_ruimte rar"
              + ",      theperslid pcontact"
              + ",      thePerslid pHost"
              + ",      res_activiteit ract"
              + ",      res_srtactiviteit sa"
              + ",      prs_v_afdeling_boom boom"
              + " WHERE rm.res_reservering_key = r.res_reservering_key"
              + "   AND rm.res_ruimte_opstel_key = ro.res_ruimte_opstel_key"
              + "   AND rg.alg_district_key = di.alg_district_key"
              + "   AND ro.res_ruimte_key = rr.res_ruimte_key"
              + "   AND rr.res_ruimte_key = rar.res_ruimte_key"
              + "   AND rar.alg_ruimte_key = rg.alg_ruimte_key"
              + "   AND rm.res_activiteit_key = ract.res_activiteit_key"
              + "   AND ract.res_srtactiviteit_key = sa.res_srtactiviteit_key"
              + "   AND rar.alg_ruimte_key = (SELECT MIN (rar2.alg_ruimte_key)"
                +   " FROM res_v_aanwezigalg_ruimte rar2"
                +   " WHERE rar2.res_ruimte_key = rr.res_ruimte_key)"
              + "   AND rm.res_rsv_ruimte_contact_key = pcontact.prs_perslid_key"
              + "   AND pHost.prs_perslid_key = rm.res_rsv_ruimte_host_key"
              + "   AND pcontact.prs_afdeling_key = boom.prs_afdeling_key";

        if (!res_key)
        {
          if (!res_actual && !res_deleted) // Ongeldige actuele reserveringen
            sqlR += " AND rm.res_rsv_ruimte_dirtlevel > 0"
                  + " AND rm.res_rsv_ruimte_verwijder IS NULL";
          else if (!res_deleted)
            sqlR += " AND rm.res_rsv_ruimte_verwijder IS NULL";
          else if (!res_actual)
            sqlR += " AND rm.res_rsv_ruimte_verwijder IS NOT NULL";
        }

        // Activiteit
        if (act_key)
          sqlR += " AND ract.res_activiteit_key = " + act_key;
        else if (srtact)
          sqlR += " AND ract.res_srtactiviteit_key = " + srtact;

        if (room_key_arr.length != 0)
            sqlR += " AND rr.res_discipline_key IN (" + room_key_arr.join(",") + ")";

        // fronto en frontend hebben dezelfde levels.
        var sql_onrgoed = "";
        if (room_key)
        {
          sql_onrgoed = " AND rg.ALG_RUIMTE_KEY = " + room_key;
        }
        else
        {
          if (floor_key) {
            sql_onrgoed = " AND rg.alg_verdieping_key = " + floor_key;
          }
          else
          {
            if (bld_key) {
              sql_onrgoed = " AND rg.alg_gebouw_key = " + bld_key;
            }
            else if (loc_key)
            {
              sql_onrgoed = " AND rg.alg_locatie_key = " + loc_key;
            }
            else if (dist_key)
            {
              sql_onrgoed = " AND di.alg_district_key = " + dist_key;
            }
            else if (reg_key)
            {
              sql_onrgoed = " AND di.alg_regio_key = " + reg_key;
            }
          }
        }

        if (fronto) // er moet 3D op
        {
          if (!res_key && sql_onrgoed != "" )
            sqlR += sql_onrgoed;

          // apply 3D authorization to the locations (both ALG and PRS)
          sqlR = discx3d (sqlR,
                          "rr.res_discipline_key",
                          "di.alg_regio_key",
                          "rg.alg_district_key",
                          "rg.alg_locatie_key",
                          "rg.alg_gebouw_key",
                          "rg.alg_verdieping_key",
                          "rg.alg_ruimte_key",
                          "boom.prs_bedrijf_key",
                          "boom.prs_afdeling_key",
                          pautfunction,
                          (!res_key && (room_key_arr.length != 0) ? room_key_arr.join(",") : ""),
                          2,null,3);
        }
        else
      	{
      	  sqlR += sql_onrgoed;
      	}

        sqlDeelCount = "SELECT rvard.res_rsv_ruimte_key"
                     + ", COUNT(rvard.res_rsv_ruimte_key) aantal"
                     + ", resd.res_discipline_key"
                     + ", MAX(rvard.res_rsv_deel_dirtlevel) res_rsv_deel_dirtlevel"
                     + (res_deleted || res_key
                       ? " FROM res_rsv_deel rvard"
                       : " FROM res_v_aanwezigrsv_deel rvard")
                         + ", res_deel resd"
                     + " WHERE rvard.res_deel_key = resd.res_deel_key"
                     + (S("vis_parking_key") != -1 ? " AND resd.res_discipline_key != " + S("vis_parking_key") : "")
                     + " GROUP BY rvard.res_rsv_ruimte_key"
                     + ", rvard.res_rsv_deel_van"
                     + ", resd.res_discipline_key";

        // RES_RSV_DEEL in alg_ruimte
        sqlDe = "SELECT DISTINCT rvarr.res_reservering_key"
              + ",      0 res_reservering_ispool"
              + ",      rvarr.res_rsv_ruimte_key"
              + ",      res_rsv_ruimte_omschrijving descr"
              + ",      rvarr.res_status_bo_key"
              + ",      rvarr.res_status_fo_key"
              + ",      rvarr.res_rsv_ruimte_flag"
              + ",      rvarr.res_rsv_ruimte_prijs"
              + ",      rd.res_rsv_deel_dirtlevel dirtlevel"
              + ",      rvarr.res_rsv_ruimte_afgerond"
              + ",      alg_ruimte_aanduiding waar"
              + ",      res_rsv_ruimte_van datumvan"
              + ",      res_rsv_ruimte_tot datumtot"
              + ",      pcontact.naam contact"
              + ",      pHost.naam gastheer"
              + ",      res_rsv_ruimte_contact_key"
              + ",      res_rsv_ruimte_host_key"
              + ",      'CV' AS restype"
              + ",      res_rsv_ruimte_bezoekers bezoekers"
              + ",      res_rsv_ruimte_verwijder res_rsv_ruimte_verwijder"
              + ",      pHost.prs_afdeling_key"
              + ",      res_rsv_ruimte_opmerking remark"
              + ",      res_rsv_ruimte_volgnr"
              + ",      sa.res_srtactiviteit_prefix"
              + ",      null"
              + ",      ract.res_activiteit_meteindtijd"
              + "  FROM (" + sqlDeelCount + ") rd"
              + ",      alg_v_ruimte_gegevens_all rg"
              + ",      theResrsv rvarr"
              + ",      res_reservering r"
              + ",      thePerslid pcontact"
              + ",      thePerslid pHost"
              + ",      alg_district di"
              + ",      res_activiteit ract"
              + ",      res_srtactiviteit sa"
              + ",      prs_v_afdeling_boom boom"
              + " WHERE rd.res_rsv_ruimte_key = rvarr.res_rsv_ruimte_key"
              + "   AND rvarr.alg_ruimte_key = rg.alg_ruimte_key" // Automatically filters RES_DEEL's on ALG_RUIMTE
              + "   AND rg.alg_district_key = di.alg_district_key"
              + "   AND rvarr.res_rsv_ruimte_contact_key = pcontact.prs_perslid_key"
              + "   AND pHost.prs_perslid_key = rvarr.res_rsv_ruimte_host_key"
              + "   AND r.res_reservering_key = rvarr.res_reservering_key"
              + "   AND rvarr.res_activiteit_key = ract.res_activiteit_key"
              + "   AND ract.res_srtactiviteit_key = sa.res_srtactiviteit_key"
              + "   AND pcontact.prs_afdeling_key = boom.prs_afdeling_key";

        if (!res_key)
        {
          if (!res_actual && !res_deleted) // Ongeldige actuele reserveringen
            sqlDe += " AND rd.res_rsv_deel_dirtlevel > 0"
                   + " AND rvarr.res_rsv_ruimte_verwijder IS NULL";
          else if (res_actual && !res_deleted)
            sqlDe += " AND rvarr.res_rsv_ruimte_verwijder IS NULL";
          else if (!res_actual && res_deleted)
            sqlDe += " AND rvarr.res_rsv_ruimte_verwijder IS NOT NULL";
        }

        // Activiteit
        if (act_key)
          sqlDe += " AND ract.res_activiteit_key = " + act_key;
        else if (srtact)
          sqlDe += " AND ract.res_srtactiviteit_key = " + srtact;

        if (fronto) {
          if (!res_key && sql_onrgoed != "")
             sqlDe += sql_onrgoed;

          // apply 3D authorization to the locations (both ALG and PRS)
          sqlDe = discx3d (sqlDe,
                           "rd.res_discipline_key",
                           "di.alg_regio_key",
                           "rg.alg_district_key",
                           "rg.alg_locatie_key",
                           "rg.alg_gebouw_key",
                           "rg.alg_verdieping_key",
                           "rg.alg_ruimte_key",
                           "boom.prs_bedrijf_key",
                           "boom.prs_afdeling_key",
                           pautfunction,
                           (!res_key && (room_key_arr.length != 0) ? room_key_arr.join(",") : ""),
                           2,null,1);
        }
        else
        { // FrontEnd is al gefilterd
            if (loc_key)
                sqlDe += " AND rg.alg_locatie_key = " + loc_key
            else if (dist_key)
            {
                sqlDe += " AND rg.alg_district_key = " + dist_key;
            }
            else if (reg_key)
            {
                sqlDe += " AND di.alg_regio_key = " + reg_key;
            }
        }

        sqlArtCount = "SELECT rvara.res_rsv_ruimte_key"
                    + ", MIN(rvara.res_rsv_artikel_levering) res_rsv_artikel_levering"
                    + ", COUNT(res_rsv_ruimte_key) aantal"
                    + ", resa.res_discipline_key"
                    + ", MAX(rvara.res_rsv_artikel_dirtlevel) res_rsv_artikel_dirtlevel"
                    + (res_deleted || res_key
                      ? " FROM res_rsv_artikel rvara"
                      : " FROM res_v_aanwezigrsv_artikel rvara")
                        + ", res_artikel resa"
                    + " WHERE rvara.res_artikel_key = resa.res_artikel_key"
                    + " GROUP BY rvara.res_rsv_ruimte_key"
                    + ", resa.res_discipline_key";

        // RES_RSV_ARTIKEL in alg_ruimte
        sqlA = "SELECT DISTINCT rvarr.res_reservering_key"
             + ",      0 res_reservering_ispool"
             + ",      rvarr.res_rsv_ruimte_key"
             + ",      res_rsv_ruimte_omschrijving descr"
             + ",      rvarr.res_status_bo_key"
             + ",      rvarr.res_status_fo_key"
             + ",      rvarr.res_rsv_ruimte_flag"
             + ",      rvarr.res_rsv_ruimte_prijs"
             + ",      ra.res_rsv_artikel_dirtlevel dirtlevel"
             + ",      rvarr.res_rsv_ruimte_afgerond"
             + ",      alg_ruimte_aanduiding waar"
             + ",      ra.res_rsv_artikel_levering datumvan"
             + ",      res_rsv_ruimte_tot datumtot" //afruimtijd
             + ",      pcontact.naam contact"
             + ",      pHost.naam gastheer"
             + ",      res_rsv_ruimte_contact_key"
             + ",      res_rsv_ruimte_host_key"
             + ",      'CV' AS restype"
             + ",      res_rsv_ruimte_bezoekers bezoekers"
             + ",      res_rsv_ruimte_verwijder"
             + ",      pHost.prs_afdeling_key"
             + ",      res_rsv_ruimte_opmerking remark"
             + ",      res_rsv_ruimte_volgnr"
             + ",      sa.res_srtactiviteit_prefix"
             + ",      null"
             + ",      ract.res_activiteit_meteindtijd"
             + "  FROM (" + sqlArtCount + ") ra"
             + ",      theResrsv rvarr"
             + ",      alg_v_ruimte_gegevens_all rg"
             + ",      thePerslid pcontact"
             + ",      alg_district di"
             + ",      thePerslid pHost"
             + ",      res_reservering r"
             + ",      res_activiteit ract"
             + ",      res_srtactiviteit sa"
             + ",      prs_v_afdeling_boom boom"
             + " WHERE rvarr.alg_ruimte_key = rg.alg_ruimte_key" // Automatically filters RES_ARTIKEL on ALG_RUIMTE
             + "   AND rg.alg_district_key = di.alg_district_key"
             + "   AND rvarr.res_rsv_ruimte_contact_key = pcontact.prs_perslid_key"
             + "   AND rvarr.res_rsv_ruimte_host_key = pHost.prs_perslid_key"
             + "   AND r.res_reservering_key = rvarr.res_reservering_key"
             + "   AND ra.res_rsv_ruimte_key = rvarr.res_rsv_ruimte_key"
             + "   AND rvarr.res_activiteit_key = ract.res_activiteit_key"
             + "   AND ract.res_srtactiviteit_key = sa.res_srtactiviteit_key"
             + "   AND pcontact.prs_afdeling_key = boom.prs_afdeling_key";

        if (!res_key)
        {
            if (!res_actual && !res_deleted) // Ongeldige actuele reserveringen
              sqlA += " AND ra.res_rsv_artikel_dirtlevel > 0"
                    + " AND res_rsv_ruimte_verwijder IS NULL";
            else if (res_actual && !res_deleted)
              sqlA += " AND res_rsv_ruimte_verwijder IS NULL";
            else if (!res_actual && res_deleted)
              sqlA += " AND res_rsv_ruimte_verwijder IS NOT NULL";
        }

        if (act_key)
          sqlA += " AND ract.res_activiteit_key = " + act_key;
        else if (srtact)
          sqlA += " AND ract.res_srtactiviteit_key = " + srtact;

        sql_select = " rec2.res_reservering_key"
                   + ", rec2.res_reservering_ispool"
                   + ", rec2.descr"
                   + ", rec2.res_status_bo_key"
                   + ", rec2.res_status_fo_key"
                   + ", rec2.res_rsv_ruimte_flag"
                   + ", rec2.res_rsv_ruimte_prijs"
                   + ", rec2.dirtlevel"
                   + ", rec2.res_rsv_ruimte_afgerond"
                   + ", rec2.approval"
                   + ", rec2.waar"
                   + ", MIN(rec2.datumvan) datumvan"
                   + ", MAX(rec2.datumtot) datumtot"
                   + ", rec2.contact"
                   + ", rec2.gastheer"
                   + ", rec2.res_rsv_ruimte_contact_key"
                   + ", rec2.res_rsv_ruimte_host_key"
                   + ", rec2.restype"
                   + ", rec2.bezoekers"
                   + ", rec2.res_rsv_ruimte_verwijder"
                   + ", rec2.prs_afdeling_key"
                   + ", rec2.remark"
                   + ", rec2.res_rsv_ruimte_volgnr"
                   + ", rec2.res_rsv_ruimte_key rsv_ruimte_key"
                   + ", (SELECT COUNT('1')"
                     + " FROM res_rsv_deel rrd, res_deel resd"
                     + " WHERE rrd.res_rsv_ruimte_key = rec2.res_rsv_ruimte_key"
                     + "   AND rrd.res_deel_key = resd.res_deel_key"
                     + (S("vis_parking_key") != -1 ? " AND resd.res_discipline_key != " + S("vis_parking_key") : "")
                     + ") + "
                     + " (SELECT COUNT('2')"
                     + " FROM res_rsv_artikel"
                     + " WHERE res_rsv_ruimte_key = rec2.res_rsv_ruimte_key) nrObjects"
                   + ", rec2.res_srtactiviteit_prefix"
                   + ", rec2.verval"
                   + ", rec2.res_activiteit_meteindtijd";

        sql_groupby = " rec2.res_reservering_key"
                    + ", rec2.res_reservering_ispool"
                    + ", rec2.descr"
                    + ", rec2.res_status_bo_key"
                    + ", rec2.res_status_fo_key"
                    + ", rec2.res_rsv_ruimte_flag"
                    + ", rec2.res_rsv_ruimte_prijs"
                    + ", rec2.dirtlevel"
                    + ", rec2.waar"
                    + ", rec2.contact"
                    + ", rec2.gastheer"
                    + ", rec2.res_rsv_ruimte_contact_key"
                    + ", rec2.res_rsv_ruimte_host_key"
                    + ", rec2.restype"
                    + ", rec2.bezoekers"
                    + ", rec2.res_rsv_ruimte_verwijder"
                    + ", rec2.prs_afdeling_key"
                    + ", rec2.remark"
                    + ", rec2.res_rsv_ruimte_volgnr"
                    + ", rec2.res_rsv_ruimte_key"
                    + ", rec2.res_srtactiviteit_prefix"
                    + ", rec2.verval"
                    + ", rec2.res_rsv_ruimte_afgerond"
                    + ", rec2.approval"
                    + ", rec2.res_activiteit_meteindtijd";

        if (fronto)
        {
          if (!res_key && sql_onrgoed != "")
            sqlA += sql_onrgoed;

          // apply 3D authorization to the locations (both ALG and PRS)
          sqlA = discx3d (sqlA,
                         "ra.res_discipline_key",
                         "di.alg_regio_key",
                         "rg.alg_district_key",
                         "rg.alg_locatie_key",
                         "rg.alg_gebouw_key",
                         "rg.alg_verdieping_key",
                         "rg.alg_ruimte_key",
                         "boom.prs_bedrijf_key",
                         "boom.prs_afdeling_key",
                         pautfunction,
                         (!res_key && (room_key_arr.length != 0) ? room_key_arr.join(",") : ""),
                         2,null,2);
        }
        else  // frontend
        { // FrontEnd is al gefilterd
            if (loc_key)
                sqlA += " AND rg.alg_locatie_key = " + loc_key
            else if (dist_key)
            {
                sqlA += " AND rg.alg_district_key = " + dist_key;
            }
            else if (reg_key)
            {
                sqlA += " AND di.alg_regio_key = " + reg_key;
            }
        }

        var approve_sql = [];
        if (res_approved)
        {
            approve_sql.push("rec2.res_rsv_ruimte_afgerond = 1");
        }
        if (res_tobeapproved)
        {
            switch (S("res_approval"))
            {
                case 0: // geen approval
                        break;
                case 1: // goedkeuren na reserveringdatum
                        approve_sql.push("rec2.res_rsv_ruimte_afgerond = 0"
                                        +" AND (rec2.datumtot < TRUNC(SYSDATE, 'DD'))");
                        break;
                case 2: // goedkeuren na afmelden
                        approve_sql.push("rec2.res_rsv_ruimte_afgerond = 0"
                                        +" AND (  (rec2.res_rsv_ruimte_prijs IS NOT NULL AND rec2.res_status_bo_key = 5)"
                                        +    " OR (rec2.res_rsv_ruimte_prijs IS     NULL AND rec2.res_status_bo_key IS NULL))");
                        break;
            }
        }

        var sqlinside = "WITH " + thePerslid + "," + theResrsv + " " + sqlR + " UNION ALL " + sqlDe + " UNION ALL " + sqlA;
        // Indien verschillende dirtlevels bij dirty reservering, neem dan het maximum om dubbele regels te voorkomen
        // Geld hier alleen voor fronto en frontend
        var sql_rec2 = " SELECT res_reservering_key"
                     + ", res_reservering_ispool"
                     + ", res_rsv_ruimte_key"
                     + ", descr"
                     + ", res_status_bo_key"
                     + ", res_status_fo_key"
                     + ", res_rsv_ruimte_flag"
                     + ", res_rsv_ruimte_prijs"
                     + ", MAX(dirtlevel) dirtlevel"
                     + ", res_rsv_ruimte_afgerond"
                     + ", waar"
                     + ", datumvan"
                     + ", datumtot"
                     + ", contact"
                     + ", gastheer"
                     + ", res_rsv_ruimte_contact_key"
                     + ", res_rsv_ruimte_host_key"
                     + ", restype"
                     + ", bezoekers"
                     + ", res_rsv_ruimte_verwijder"
                     + ", prs_afdeling_key"
                     + ", remark"
                     + ", res_rsv_ruimte_volgnr"
                     + ", res_srtactiviteit_prefix"
                     + ", CASE"
                       + " WHEN (res_ruimte_vervaldatum IS NULL OR res_ruimte_vervaldatum > datumtot)"
                       + " THEN 1"
                       + " ELSE 0"
                       + " END verval"
                     + ", CASE"
                       + " WHEN res_rsv_ruimte_afgerond = 0";

                    switch (S("res_approval"))
                    {
                      case 0: // niets aan toevoegen
                              break;
                      case 1: sql_rec2 += " AND (datumtot < TRUNC(SYSDATE, 'DD'))";
                              break;
                      case 2: sql_rec2 += " AND (  (res_rsv_ruimte_prijs IS NOT NULL AND res_status_bo_key = 5)"
                                        + "     OR (res_rsv_ruimte_prijs IS     NULL AND res_status_bo_key IS NULL)"
                                        + "     )";
                              break;
                    };

            sql_rec2 +=  " THEN 1"
                       + " ELSE 0"
                       + " END approval"
                     + ", res_activiteit_meteindtijd"
                     + " FROM (" + sqlinside + ")"
                     + " GROUP BY res_reservering_key"
                     + ", res_reservering_ispool"
                     + ", res_rsv_ruimte_key"
                     + ", descr"
                     + ", res_status_bo_key"
                     + ", res_status_fo_key"
                     + ", res_rsv_ruimte_flag"
                     + ", res_rsv_ruimte_prijs"
                     + ", waar"
                     + ", datumvan"
                     + ", datumtot"
                     + ", contact"
                     + ", gastheer"
                     + ", res_rsv_ruimte_contact_key"
                     + ", res_rsv_ruimte_host_key"
                     + ", restype"
                     + ", bezoekers"
                     + ", res_rsv_ruimte_verwijder"
                     + ", prs_afdeling_key"
                     + ", remark"
                     + ", res_rsv_ruimte_volgnr"
                     + ", res_srtactiviteit_prefix"
                     + ", res_ruimte_vervaldatum"
                     + ", res_rsv_ruimte_afgerond"
                     + ", res_activiteit_meteindtijd";

        // Voeg laatste tracking datum toe
        sqltrack = ", (SELECT MAX(t.fac_tracking_datum)"
                 + "     FROM fac_tracking t"
                 + "        , fac_srtnotificatie sn"
                 + "    WHERE t.fac_srtnotificatie_key = sn.fac_srtnotificatie_key"
                 + "      AND t.fac_tracking_refkey = rec2.res_rsv_ruimte_key" // res_rsv_ruimte_key uit "sql_select"
                 + "      AND sn.fac_srtnotificatie_xmlnode = 'reservering') recentdatum";

        sql = "SELECT " + sql_select + sqltrack
            + " FROM (" + sql_rec2 + ") rec2"
            + " WHERE 1=1 "
            + (!res_key && approve_sql.length > 0 ? " AND (" + approve_sql.join(" OR ") + ")" : "")

        if (dep_key)
        {
          sqln = "SELECT db.niveau"
               + " FROM prs_v_afdeling_boom db"
               + " WHERE db.prs_afdeling_key = " + dep_key;
          oRsn = Oracle.Execute(sqln);
          var niveau = oRsn(0).Value;

          sql += " AND prs_afdeling_key IN"
               + " (SELECT d.prs_afdeling_key afd_key"
               + " FROM prs_v_afdeling d"
               + ", prs_v_afdeling_boom db"
               + " WHERE d.prs_afdeling_verwijder IS NULL"
               + " AND d.prs_afdeling_key = db.prs_afdeling_key"
               + " AND db.prs_afdeling_key" + niveau + " = " + dep_key + ")";
        }

        sql += " GROUP BY " + sql_groupby
             + " ORDER BY " + (datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime()? " datumvan" : " TO_CHAR(datumvan, 'HH24:MI:SS')") + " desc, waar, datumvan desc";

        /***** End build sql *****/

        function isMeerdaags(oRs)
        {
          var datefrom = new Date(oRs("datumvan").value);
          var dateto   = new Date(oRs("datumtot").value);
          return (dateto.midnight().getTime() != datefrom.midnight().getTime());
        }

        function fncolDatum(oRs)
        {
          if (isMeerdaags(oRs))
            return L("lcl_res_multidays");
          else
            return toDateString(new Date(oRs("datumvan").value), excel); // excel-->noDay
        }

        function fncolDatumSort(oRs)
        {
          if (isMeerdaags(oRs))
            return toDateString(new Date(oRs("datumvan").value), excel); // excel-->noDay
          else
            return null
        }

        function fncolVan(oRs)
        {
          var datefrom = new Date(oRs("datumvan").value);
          var dt = toTimeString(datefrom);
          if (isMeerdaags(oRs))
              dt += "<br>" + toDateString(datefrom, excel); // excel-->noDay
          return dt;
        }

        function fncolTot(oRs)
        {
          var met_eindtijd = oRs("res_activiteit_meteindtijd").Value == 1;
          var dateto = new Date(oRs("datumtot").value);
          var dt = toTimeString(dateto);
          if (met_eindtijd)
          {
            if (isMeerdaags(oRs))
              dt += "<br>" + toDateString(dateto, excel); // excel-->noDay
          }
          else
            dt = "";
          return dt;
        }

        /*****************************************************
         * Callback functies ResultsetTable for FE and FO only
         ****************************************************/

        var recent = new Date();
        recent.setMinutes(recent.getMinutes() - S("res_reservering_recent"));
        function fnrowClassF(oRs)   // tr-class
        {
          var rowclass = "";
          if (oRs("res_rsv_ruimte_verwijder").Value != null)
          {  // verwijderd
            rowclass = "deleted";
          }

          if (oRs("verval").Value == 0 || oRs("dirtlevel").Value != 0)
          {  // dirty!
            rowclass += " res_fatal";
          }

          var res_recent = new Date(oRs("recentdatum").Value);
          if (res_recent > recent)
          {
            rowclass += " updated";
          }
          return rowclass;
        }

        function fnrowDataF(oRs)
        {
          var resKey = oRs("res_reservering_key").value; // Reservering key
          var resVolgnr = oRs("res_rsv_ruimte_volgnr").value; // Reservering volgnummer
          var resRsvRuimteKey = oRs("rsv_ruimte_key").value; // rsv_ruimte_key

          var data = {resKey: resKey, resVolgnr: resVolgnr, resRsvRuimteKey: resRsvRuimteKey};

          return JSON.stringify(data);
        }

        function fncolStatus(oRs) {
            return res.getfostatustext(oRs("res_status_fo_key").value);
        }

        function fnHasVZ(oRs)
        {
            if (oRs("nrObjects").value > 0)
                return oRs("nrObjects").value + " " + L("lcl_res_reserved_objects");
            else
                return null;
        }

        function fncolResNr(oRs)
        {
          var content = (oRs("res_srtactiviteit_prefix").value? oRs("res_srtactiviteit_prefix").value : "") + String(oRs("res_reservering_key").value)
          if (oRs("res_reservering_ispool").Value == 1)
            content = L("lcl_respool_prefix") + content;
          else
            content = content + "/" + oRs("res_rsv_ruimte_volgnr").value;
          return content;
        }

        function fnrowVisitorsF(oRs)
        {
          return (oRs("bezoekers").value != 0? oRs("bezoekers").value : "");
        }

        function fncolHostRequestor(oRs)
        {
          var requestor = oRs("contact").value
          if (S("res_allow_for_others") && !excel && oRs("gastheer").value == requestor)
            	requestor = "";
          return safe.html(requestor);
        }

        /*********************************************************
         * End callback functies ResultsetTable for FE and FO only
         ********************************************************/

         var rst = new ResultsetTable({keyColumn: "rsv_ruimte_key",
                                      ID: "restable",
                                      rowClass: fnrowClassF,
                                      rowData: fnrowDataF,
                                      sql: sql,
                                      filterParams: params,
                                      outputmode: outputmode,
                                      title: L("lcl_reservation_title"),
                                      inlineDetails: "inlineVoorzieningUrl",
                                      hasInlineDetails: fnHasVZ,
                                      showAll: showall
                                     });

        // Kolommen
        if (!frontend && S("res_reservering_flags") > 0)
          rst.addColumn(new Column({caption: "o", content: fncolFlags, align: "center"}));
        rst.addColumn(new Column({caption: L("lcl_resnr"), content: fncolResNr }));
        rst.addColumn(new Column({caption: L("lcl_room_n"), content: "waar", hasActions: true}));
        // Compacter op scherm als datefrom==dateto
        if (res_key || outputmode != 0 || outputmode == 0 && datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime())
        {
            rst.addColumn(new Column({caption: L("lcl_date"), content: fncolDatum, customSort: fncolDatumSort, datatype: "date", nowrap: true}));
        }
        rst.addColumn(new Column({caption: L("lcl_from"), content: fncolVan, datatype: "time", nowrap: true}));
        rst.addColumn(new Column({caption: L("lcl_to"), content: fncolTot, datatype: "time"}));
        rst.addColumn(new Column({caption: L("lcl_room_status"), content: fncolStatus}));
        rst.addColumn(new Column({caption: L("lcl_res_pers_n"), content: fnrowVisitorsF, datatype: "number"}));
        if (S("res_allow_for_others"))
        {
          rst.addColumn(new Column({caption: L("lcl_host"), content: "gastheer"}));
        }
        rst.addColumn(new Column({caption: L("lcl_res_requestor"), content: fncolHostRequestor, combine: (S("res_allow_for_others")?true:false)}));
        rst.addColumn(new Column({caption: L("lcl_descr"), content: "descr"}));
        if (S("res_approval") > 0)
          rst.addColumn(new Column({caption: L("lcl_res_approval"), content: fncolResApproved}));

        // Acties
        rst.addAction({ action: "resEdit", caption: L("lcl_edit"), isDefault: true});

        var count = rst.processResultset();
      }  // frontend || fronto
      else
      { // Make ResultsetTable for bo or mi

        /***** Build sql *****/
        //var res_key = 0;
        var sql_loc = "";
        var sql_bld = "";
        var sql_floor = "";
        var sql_room = "";
        var sql_act = "";
        var sql_dept = "";
        var sql_account = "";
        var sql_name = "";
        var sql_room_key = "";
        var sql_obj_key = "";
        var sql_art_key = "";
        var sql_article = "";
        var status_sql = "";

        if (!res_key)
        {
          if (dep_key)
          {
            sql_org = "SELECT ab.niveau"
                    + " FROM prs_v_afdeling_boom ab"
                    + " WHERE ab.prs_afdeling_key = " + dep_key;
            oRs_org = Oracle.Execute(sql_org);

            sql_dept  += " AND phost.prs_afdeling_key IN (SELECT ab.prs_afdeling_key"
                       + " FROM prs_v_afdeling_boom ab"
                       + " WHERE ab.prs_afdeling_key" + (!oRs_org.eof?oRs_org(0).value:"") + " = " + dep_key + ")";
          }

          if (kp)
            sql_dept = " AND k.prs_kostenplaats_upper LIKE " + safe.quoted_sql_wild(kp);

          if (reg_key)
            sql_reg = " AND di.alg_regio_key = " + reg_key;
          else
            // Only looking at authorisation of the room is sufficient
            sql_reg = "";

          if (dist_key)
            sql_dist = " AND ruimte_geg.alg_district_key = " + dist_key;
          else
            // Only looking at authorisation of the room is sufficient
            sql_dist = "";

          if (loc_key)
            sql_loc = " AND ruimte_geg.alg_locatie_key = " + loc_key;
          else
            // Only looking at authorisation of the room is sufficient
            sql_loc = "";

          if (bld_key)
            sql_bld = " AND ruimte_geg.alg_gebouw_key = " + bld_key;
          else
            // Only looking at authorisation of the room is sufficient
            sql_bld = "";

          if (floor_key)
            sql_floor = " AND ruimte_geg.alg_verdieping_key = " + floor_key;
          else
            // Only looking at authorisation of the room is sufficient
            sql_floor = "";

          if (room_key)
            sql_room = " AND ruimte_geg.alg_ruimte_key = " + room_key;

          // Activiteit
          if (act_key)
            sql_act = " AND ract.res_activiteit_key = " + act_key;
          else if (srtact)
            sql_act = " AND ract.res_srtactiviteit_key = " + srtact;

          // Flags
          if (params.flags && params.flags.length > 0 && params.flags.length < S("res_reservering_flags"))
          {
            sql_flag = " AND rrr.res_rsv_ruimte_flag IN (" + params.flags.join(",") + ")";
          }

          if (room_key_arr.length != 0)
            sql_room_key = " AND res_discipline_key IN (" + room_key_arr.join(",") + ")";

          if (obj_key_arr.length != 0)
            sql_obj_key = " AND rd.res_discipline_key IN (" + obj_key_arr.join(",") + ")";

          if (art_key_arr.length != 0)
            sql_art_key = " AND ra.res_discipline_key IN (" + art_key_arr.join(",") + ")";

          if (article_arr.length != 0)
            sql_article = " AND rra.res_artikel_key IN (" + article_arr.join(",") + ")";

          if (res_open)
          {
            if (!res_closed)
              status_sql += " AND res_geg.res_status_bo_key < " + S("res_bo_status_key");
          }
          else
            status_sql += " AND res_geg.res_status_bo_key >= " + S("res_bo_status_key");

          var approve_sql = [];
          if (res_approved)
          {
            approve_sql.push("rrr.res_rsv_ruimte_afgerond = 1");
          }
          if (res_notapproved)
          {
            approve_sql.push("rrr.res_rsv_ruimte_afgerond = 0");
          }
        }

        // Artikel groep. Ook uitvoeren als resnum is meegegeven
        var sql_art_group = "";
        if (artgroup)
          sql_art_group = " AND UPPER(ra.res_artikel_groep) IN (" + safe.quoted_sql_join(artgroup, true) + ")";

        var sql = "";
        // New res structure
        // Volgens mij willen we 1 regel per reservering hier; wat doen we dan met de mogelijk varierende kolommen?
        var sql_select = "SELECT rrr.res_reservering_key"
                       + "     , ruimte_geg.alg_locatie_key"
                       + "     , l.alg_locatie_code locatie"
                       + "     , ruimte_geg.alg_gebouw_key"
                       + "     , ruimte_geg.alg_verdieping_key"
                       + "     , ruimte_geg.alg_ruimte_key"
                       + "     , COALESCE(opstelalg.res_ruimte_nr, ruimte_geg.alg_ruimte_aanduiding) res_ruimte_nr" //res_ruimte_nr is al vertaald
                       + "     , " + ( minfo
                                     ? "COALESCE(opstelalg.res_ruimte_nr, ruimte_geg.alg_ruimte_omschrijving)"
                                     : "ruimte_geg.alg_ruimte_aanduiding"
                                     ) + " alg_ruimte_aanduiding"
                       + "     , res_geg.res_voorziening"
                       + "     , opstelalg.res_ruimte_opstel_default"
                       + "     , NULL"
                       + "     , res_geg.res_reservering_van datumvan"
                       + "     , res_geg.res_reservering_tot datumtot"
                       + "     , pcontact.naam aanvrager"
                       + "     , res_geg.res_ins_discipline_key"
                       + "     , res_rsv_ruimte_omschrijving omschrijving"
                       + "     , res_rsv_ruimte_opmerking opmerking"
                       + "     , res_geg.res_rsv_ruimte_key rsv_ruimte_key"
                       + "     , res_geg.res_item_key"
                       + ((groupres == 1) // Bij groupering op deelreservering is het afmelden afhankelijk van de laagste bo status
                         ? "   , (SELECT MIN(res_status_bo_key)"
                           + "      FROM (SELECT rrr.res_rsv_ruimte_key"
                             + "               , rrr.res_status_bo_key"
                             + "            FROM res_v_aanwezigrsv_ruimte rrr"
                             + "          UNION ALL"
                             + "          SELECT rrd.res_rsv_ruimte_key"
                             + "               , rrd.res_status_bo_key"
                             + "            FROM res_v_aanwezigrsv_deel rrd"
                             + "          UNION ALL"
                             + "          SELECT rra.res_rsv_ruimte_key"
                             + "               , rra.res_status_bo_key"
                             + "            FROM res_v_aanwezigrsv_artikel rra) bostatus"
                           + "             WHERE bostatus.res_rsv_ruimte_key = res_geg.res_rsv_ruimte_key)"
                         : "   , res_geg.res_status_bo_key")
                         + "     res_status_bo_key"
                       + "     , res_rsv_ruimte_flag"
                       + "     , res_geg.res_type categorie"
                       + "     , rrr.res_rsv_ruimte_bezoekers bezoekers"
                       + "     , phost.naam gastheer"
                       + "     , pcontact.prs_perslid_telefoonnr"
                       + "     , COALESCE((SELECT k.prs_kostenplaats_nr "
                         + "                 FROM prs_kostenplaats k"
                         + "                WHERE rrr.prs_kostenplaats_key = k.prs_kostenplaats_key), '') kostenplaats"
                       + "     , res_geg.aantal aantal"
                       + "     , res_geg.rsv_ruimte_aantal"                                     // 29 Hogere nummers worden alleen op naam gebruikt, zoals het hoort :-)
                       + "     , res_geg.prijs verwerkt_prijs"
                       + "     , l.alg_district_key"
                       + "     , rrr.res_activiteit_key"
                       + "     , " + lcl.xsqla('ract.res_activiteit_omschrijving', 'ract.res_activiteit_key')
                       + "     , ract.res_activiteit_meteindtijd"
                       + "     , ract.res_activiteit_upper"  // for sorting
                       + "     , res_geg.stuks_prijs stuks_prijs"
                       + "     , res_geg.btwtarief btwtarief"
                       + "     , phost.prs_afdeling_key"
                       + "     , (SELECT " + S("prs_dep_string")
                       + "         FROM prs_v_afdeling d"
                       + "         WHERE phost.prs_afdeling_key = d.prs_afdeling_key ) organisatie"
                       + "     , artikelnummer"
                       + "     , CASE WHEN COALESCE (res_rsv_ruimte_bezoekers_shown, res_rsv_ruimte_bezoekers) < res_rsv_ruimte_bezoekers"
                       + "            THEN 1"
                       + "            ELSE rrr.res_rsv_ruimte_noshow "
                       + "       END noshow"
                       + "     , artikel_groep"
                       + "     , res_geg.rcv_type rcv_type"
                       + "     , res_geg.res_type res_type"
                       + "     , res_geg.keycolumn keycolumn"
                       + "     , (SELECT COUNT('1')"
                         + "        FROM res_rsv_deel rrd, res_deel resd"
                         + "       WHERE rrd.res_rsv_ruimte_key = res_geg.res_rsv_ruimte_key"
                         + "         AND rrd.res_deel_key = resd.res_deel_key"
                         + (S("vis_parking_key") != -1
                           ? "       AND resd.res_discipline_key != " + S("vis_parking_key")
                           : "")
                         + "     ) + "
                         + "     (SELECT COUNT('2')"
                         + "        FROM res_rsv_artikel"
                         + "       WHERE res_rsv_ruimte_key = res_geg.res_rsv_ruimte_key) nrObjects"
                       + ((groupres == 7) || (groupres == 8)
                         ? "   , res_artikel_key artikel_key"
                         : "")
                       + ((groupres == 9 || groupres == 14)
                         ? "   , rrr.prs_kostenplaats_key kostenplaats_key"
                         : "")
                       + ((groupres == 12)
                         ? "   , (SELECT ks.prs_kostensoort_oms"
                           + "      FROM prs_kostensoort ks, ins_tab_discipline d"
                           + "     WHERE d.ins_discipline_key = res_ins_discipline_key"
                           + "       AND d.prs_kostensoort_key = ks.prs_kostensoort_key) prs_kostensoort_oms "
                           + " , (SELECT d.prs_kostensoort_key"
                           + "      FROM ins_tab_discipline d"
                           + "     WHERE d.ins_discipline_key = res_ins_discipline_key) prs_kostensoort_key"
                         : "")
                       + ((groupres == 13)
                         ? "   , (SELECT " + lcl.xsql('ksg.prs_kostensoortgrp_oms','ksg.prs_kostensoortgrp_key')
                           + "      FROM prs_kostensoortgrp ksg"
                           + "         , prs_kostensoort ks"
                           + "         , ins_tab_discipline d"
                           + "     WHERE ksg.prs_kostensoortgrp_key = ks.prs_kostensoortgrp_key"
                           + "       AND d.ins_discipline_key = res_ins_discipline_key"
                           + "       AND d.prs_kostensoort_key = ks.prs_kostensoort_key) prs_kostensoortgrp_oms"
                           + " , (SELECT ks.prs_kostensoortgrp_key"
                           + "      FROM prs_kostensoort ks"
                           + "         , ins_tab_discipline d"
                           + "     WHERE d.ins_discipline_key = res_ins_discipline_key"
                           + "       AND d.prs_kostensoort_key = ks.prs_kostensoort_key) prs_kostensoortgrp_key"
                         : "")
                       + "     , rrr.res_rsv_ruimte_volgnr"
                       + "     , rrr.res_rsv_ruimte_key"
                       + "     , rrr.res_rsv_ruimte_ordernr"
                       + "     , res_geg.res_ruimte_key"
                       + "     , sa.res_srtactiviteit_prefix"
                       + "     , COALESCE(rrr.res_rsv_ruimte_bezoekers_shown, -1) bezoekers_shown"
                       + "     , res_geg.ingang"
                       + "     , res_geg.verval"
                       + "     , res_geg.ins_discipline_key"
                       + "     , res_geg.ins_srtdeel_uitleenbaar"
                       + "     , res_geg.ins_alg_ruimte_key_org"
                       + "     , res_geg.res_rsv_ruimte_satisfaction"
                       + "     , res_geg.res_rsv_ruimte_satisfaction_op"
                       + "     , rrr.res_rsv_ruimte_afgerond";

        var sql_from = "    FROM res_rsv_ruimte rrr"
                     + "       , res_activiteit ract"
                     + "       , res_srtactiviteit sa"
                     + "       , thePerslid phost"
                     + "       , thePerslid pcontact"
                     + "       , alg_v_ruimte_gegevens_all ruimte_geg"  // DB12
                     + "       , (SELECT res_ruimte_opstel_key"
                       + "             , " +lcl.xsqla('rr.res_ruimte_nr','rr.res_ruimte_key')
                       + "             , MIN (alg_ruimte_key) alg_ruimte_key"
                       + "             , res_ruimte_opstel_default"
                       + "          FROM res_ruimte_opstelling rro, res_alg_ruimte rar, res_ruimte rr "
                       + "         WHERE rro.res_ruimte_key = rar.res_ruimte_key"
                       + "           AND rr.res_ruimte_key = rar.res_ruimte_key "
                       + "           AND rar.res_alg_ruimte_verwijder is null "
                       + "        GROUP BY res_ruimte_opstel_key"
                       + "               , " + lcl.xsql('rr.res_ruimte_nr','rr.res_ruimte_key')
                       + "               , res_ruimte_opstel_default ) opstelalg"
                     + "       , alg_locatie l"
                     + "       , alg_district di"
                     + "       , prs_kostenplaats k"
                     + "       , prs_v_afdeling_boom boom"

        var sql_where = "  WHERE res_geg.res_rsv_ruimte_key = rrr.res_rsv_ruimte_key"
                      + "    AND rrr.res_rsv_ruimte_verwijder IS NULL"
                      + "    AND rrr.res_activiteit_key = ract.res_activiteit_key"
                      + "    AND ract.res_srtactiviteit_key = sa.res_srtactiviteit_key"
                      + "    AND res_rsv_ruimte_host_key = phost.prs_perslid_key"
                      + "    AND res_rsv_ruimte_contact_key = pcontact.prs_perslid_key"
                      + "    AND rrr.res_ruimte_opstel_key = opstelalg.res_ruimte_opstel_key(+)"
                      + "    AND rrr.prs_kostenplaats_key = k.prs_kostenplaats_key(+)"
                      + "    AND ruimte_geg.alg_ruimte_key = coalesce(rrr.alg_ruimte_key, opstelalg.alg_ruimte_key)"
                      + "    AND l.alg_locatie_key = ruimte_geg.alg_locatie_key"
                      + "    AND l.alg_district_key = di.alg_district_key"
                      + "    AND pcontact.prs_afdeling_key = boom.prs_afdeling_key"
                      + (!res_key
                        ? sql_act
                          + sql_name
                          + status_sql
                          + (approve_sql.length > 0 ? " AND (" + approve_sql.join(" OR ") + ")" : "")
                          + sql_reg + sql_dist + sql_loc + sql_bld + sql_floor + sql_room + sql_dept + sql_account
                        : "");
        if (params.res_noshowonly)
        {
          sql_where += " AND (rrr.res_rsv_ruimte_noshow = 1";
          sql_where += "      OR COALESCE(res_rsv_ruimte_bezoekers_shown, res_rsv_ruimte_bezoekers) < res_rsv_ruimte_bezoekers)";
        }
        if (!groupres || groupres == 1)
          sql_where += getKenmerkSql("RES", "rrr.res_rsv_ruimte_key", true);

        var sql_from_art_part = "SELECT 'C' AS res_type"
                              + "     , 'CV' AS rcv_type"
                              + "     , rra.res_rsv_ruimte_key"
                              + "     , (SELECT rro.res_ruimte_key"
                                + "        FROM res_ruimte_opstelling rro"
                                + "       WHERE rrr.res_ruimte_opstel_key = rro.res_ruimte_opstel_key) AS res_ruimte_key"
                              + "     , res_rsv_artikel_key AS res_item_key"
                              + (groupres == 1
                                ? "   , rrr.res_rsv_ruimte_van AS res_reservering_van"
                                : "   , rra.res_rsv_artikel_levering AS res_reservering_van")
                              + "     , res_rsv_ruimte_tot AS res_reservering_tot"
                              + "     , rra.res_rsv_artikel_aantal AS aantal"
                              + "     , LTRIM(" + lcl.xsql('ra.res_artikel_omschrijving','ra.res_artikel_key') +") || CASE WHEN " + lcl.xsql('ra.res_artikel_eenheid','ra.res_artikel_key') +" IS NULL THEN '' ELSE ' ('|| " + lcl.xsql('ra.res_artikel_eenheid','ra.res_artikel_key') + " || ')' END AS res_voorziening"
                              + "     , NULL"
                              + "     , ra.res_discipline_key AS res_ins_discipline_key"
                              + "     , rra.res_status_bo_key"
                              + "     , ra.res_artikel_key AS res_artikel_key"
                              + "     , "+ (withprices ? "res.getartikelprijs(rra.res_rsv_artikel_key)" : "NULL") + " AS prijs"
                              + "     , ra.res_artikel_prijs AS stuks_prijs"
                              + "     , ra.res_artikel_btw AS btwtarief"
                              + "     , to_number(null) AS rsv_ruimte_aantal"
                              + "     , ra.res_artikel_nr AS artikelnummer"
                              + "     , ra.res_artikel_groep AS artikel_groep"
                              + "     , rra.res_rsv_artikel_key keycolumn"
                              + "     , CASE"
                                + "     WHEN (ra.res_artikel_ingangsdatum IS NULL OR ra.res_artikel_ingangsdatum <= rrr.res_rsv_ruimte_van)"
                                + "     THEN 1"
                                + "     ELSE 0"
                                + "     END ingang"
                              + "     , CASE"
                                + "     WHEN (ra.res_artikel_vervaldatum IS NULL OR ra.res_artikel_vervaldatum > rrr.res_rsv_ruimte_tot)"
                                + "     THEN 1"
                                + "     ELSE 0"
                                + "     END verval"
                              + "     , NULL ins_discipline_key"
                              + "     , 0 ins_srtdeel_uitleenbaar"
                              + "     , NULL ins_alg_ruimte_key_org"
                              + "     ,  rrr.res_rsv_ruimte_satisfaction"
                              + "     ,  rrr.res_rsv_ruimte_satisfaction_op"
                              + "  FROM res_v_aanwezigrsv_artikel rra"
                              + "     , theResrsv rrr"
                              + "     , res_artikel ra"
                              + " WHERE rra.res_rsv_ruimte_key = rrr.res_rsv_ruimte_key"
                              + "   AND rra.res_rsv_artikel_dirtlevel = 0"   // Geen dirty ruimtes voor de BO! TODO: voor mi wel? En hoe dan?
                              + "   AND rra.res_artikel_key = ra.res_artikel_key"
                              + (groupres == 1 && roomcat
                                ? " AND rrr.alg_ruimte_key IS NOT NULL"
                                : "")
                              + sql_art_key
                              + sql_article
                              + sql_art_group;

        var sql_from_obj_part = "SELECT 'V' as res_type"
                              + "     , 'CV' AS rcv_type"
                              + "     , rrd.res_rsv_ruimte_key"
                              + "     , (SELECT rro.res_ruimte_key"
                              + "          FROM res_ruimte_opstelling rro"
                              + "         WHERE rrr.res_ruimte_opstel_key = rro.res_ruimte_opstel_key) AS res_ruimte_key"
                              + "     , rrd.res_rsv_deel_key AS res_item_key"
                              + (groupres == 1
                                ? "   , rrr.res_rsv_ruimte_van AS res_reservering_van"
                                : "   , rrd.res_rsv_deel_van AS res_reservering_van")
                              + (groupres == 1
                                ? "   , rrr.res_rsv_ruimte_tot AS res_reservering_tot"
                                : "   , rrd.res_rsv_deel_tot AS res_reservering_tot")
                              + "     , to_number(null) AS aantal"
                              + "     , " + lcl.xsql('rd.res_deel_omschrijving','rd.res_deel_key')
                               + "      || CASE WHEN " + lcl.xsql('rd.res_deel_eenheid','rd.res_deel_key') +" IS NULL THEN '' ELSE ' ('|| " + lcl.xsql('rd.res_deel_eenheid','rd.res_deel_key') +" || ')' END AS res_voorziening"
                              + "     , NULL"
                              + "     , rd.res_discipline_key AS res_ins_discipline_key"
                              + "     , rrd.res_status_bo_key"
                              + "     , TO_NUMBER(null) AS res_artikel_key"
                              + "     , " + (withprices ? "res.getdeelprijs(rrd.res_rsv_deel_key)" : "NULL") + " AS prijs"
                              + "     , rd.res_deel_prijs AS stuks_prijs"
                              + "     , to_number(null) AS btwtarief"
                              + "     , to_number(null) AS rsv_ruimte_aantal"
                              + "     , null AS artikelnummer"
                              + "     , '' AS artikel_groep"
                              + "     , rrd.res_rsv_deel_key keycolumn"
                              + "     , 1 ingang"
                              + "     , CASE"
                                + "     WHEN (rd.res_deel_vervaldatum IS NULL OR rd.res_deel_vervaldatum > rrr.res_rsv_ruimte_tot)"
                                + "     THEN 1"
                                + "     ELSE 0"
                                + "     END verval"
                              + "     , id.ins_discipline_key"
                              + "     , isd.ins_srtdeel_uitleenbaar"
                              + "     , id.ins_alg_ruimte_key_org"
                              + "     , rrr.res_rsv_ruimte_satisfaction"
                              + "     , rrr.res_rsv_ruimte_satisfaction_op"
                              + "  FROM res_v_aanwezigrsv_deel rrd"
                              + "     , theResrsv rrr"
                              + "     , res_deel rd"
                              + "     , ins_deel id"
                              + "     , ins_srtdeel isd"
                              + " WHERE rrd.res_rsv_ruimte_key = rrr.res_rsv_ruimte_key "
                              + "   AND rrd.res_deel_key = rd.res_deel_key "
                              + (S("vis_parking_key") != -1
                                ? " AND rd.res_discipline_key != " + S("vis_parking_key")
                                : "")
                              + "   AND rrd.res_rsv_deel_dirtlevel = 0"   // Geen dirty ruimtes voor de BO! TODO: voor mi wel? En hoe dan?
                              + "   AND rd.res_ins_deel_key = id.ins_deel_key"
                              + "   AND id.ins_srtdeel_key = isd.ins_srtdeel_key"
                              + (groupres == 1 && roomcat
                                ? " AND rrr.alg_ruimte_key IS NOT NULL"
                                : "")
                              + sql_obj_key;

        var sql_from_room_part = "SELECT 'R' AS res_type"
                               + "     , 'R' AS rcv_type"
                               + "     , rrr.res_rsv_ruimte_key"
                               + "     , rro.res_ruimte_key"
                               + "     , rrr.res_rsv_ruimte_key AS res_item_key"
                               + "     , rrr.res_rsv_ruimte_van AS res_reservering_van"
                               + "     , rrr.res_rsv_ruimte_tot AS res_reservering_tot"
                               + "     , TO_NUMBER(null) AS aantal"
                               + "     , " + lcl.xsql('ro.res_opstelling_omschrijving','ro.res_opstelling_key') + " AS res_voorziening"
                               + "     , rro.res_ruimte_opstel_default AS res_ruimte_opstel_default"
                               + "     , rr.res_discipline_key AS res_ins_discipline_key"
                               + "     , rrr.res_status_bo_key"
                               + "     , to_number(null) AS res_artikel_key"
                               + "     , "+ (withprices ? "res.getruimteprijs(rrr.res_rsv_ruimte_key) - COALESCE(rrr.res_rsv_ruimte_korting, 0)" : "NULL") + " AS prijs"
                               + "     , to_number(null) AS stuks_prijs"
                               + "     , to_number(null) AS btwtarief"
                               + "     , 1 AS rsv_ruimte_aantal"
                               + "     , null AS artikelnummer"
                               + "     , '' AS artikel_groep"
                               + "     , rrr.res_rsv_ruimte_key keycolumn"
                               + "     , 1 ingang"
                               + "     , CASE"
                                 + "     WHEN (rr.res_ruimte_vervaldatum IS NULL OR rr.res_ruimte_vervaldatum > rrr.res_rsv_ruimte_tot)"
                                 + "     THEN 1"
                                 + "     ELSE 0"
                                 + "     END verval"
                               + "     , NULL ins_discipline_key"
                               + "     , 0 ins_srtdeel_uitleenbaar"
                               + "     , NULL ins_alg_ruimte_key_org"
                               + "     ,  rrr.res_rsv_ruimte_satisfaction"
                               + "     ,  rrr.res_rsv_ruimte_satisfaction_op"
                               + "  FROM theResrsv rrr"
                               + "     , res_ruimte_opstelling rro"
                               + "     , res_ruimte rr"
                               + "     , res_opstelling ro"
                               + " WHERE rrr.res_ruimte_opstel_key = rro.res_ruimte_opstel_key"
                               + "   AND rro.res_ruimte_key = rr.res_ruimte_key"
                               + "   AND rrr.res_rsv_ruimte_dirtlevel = 0"   // Geen dirty ruimtes voor de BO! TODO: voor mi wel? En hoe dan?
                               + "   AND rro.res_opstelling_key = ro.res_opstelling_key "
                               + sql_room_key;

        //===================================================

        sql_from_art_part = sql_select
                          + sql_from
                          + " , (" + sql_from_art_part + ") res_geg"
                          + sql_where;

        // apply 3D authorization to the locations and to the organisations (both ALG and PRS)
        sql_from_art_part = discx3d (sql_from_art_part,
                                     "res_geg.res_ins_discipline_key",
                                     "di.alg_regio_key",
                                     "l.alg_district_key",
                                     "ruimte_geg.alg_locatie_key",
                                     "ruimte_geg.alg_gebouw_key",
                                     "ruimte_geg.alg_verdieping_key",
                                     "ruimte_geg.alg_ruimte_key",
                                     "boom.prs_bedrijf_key",
                                     "boom.prs_afdeling_key",
                                     pautfunction,
                                     (!res_key && article_disc_arr && (article_disc_arr.length > 0) ? article_disc_arr.join(",") : ""),
                                     2);

        sql_from_obj_part = sql_select
                          + sql_from
                          + " , (" + sql_from_obj_part + ") res_geg"
                          + sql_where;

        sql_from_obj_part = discx3d (sql_from_obj_part,
                                     "res_geg.res_ins_discipline_key",
                                     "di.alg_regio_key",
                                     "l.alg_district_key",
                                     "ruimte_geg.alg_locatie_key",
                                     "ruimte_geg.alg_gebouw_key",
                                     "ruimte_geg.alg_verdieping_key",
                                     "ruimte_geg.alg_ruimte_key",
                                     "boom.prs_bedrijf_key",
                                     "boom.prs_afdeling_key",
                                     pautfunction,
                                     (!res_key && obj_key_arr && (obj_key_arr.length > 0) ? obj_key_arr.join(",") : ""),
                                     2);

        sql_from_room_part = sql_select
                           + sql_from
                           + " , (" + sql_from_room_part + ") res_geg"
                           + sql_where;

        sql_from_room_part = discx3d (sql_from_room_part,
                                      "res_geg.res_ins_discipline_key",
                                      "di.alg_regio_key",
                                      "l.alg_district_key",
                                      "ruimte_geg.alg_locatie_key",
                                      "ruimte_geg.alg_gebouw_key",
                                      "ruimte_geg.alg_verdieping_key",
                                      "ruimte_geg.alg_ruimte_key",
                                      "boom.prs_bedrijf_key",
                                      "boom.prs_afdeling_key",
                                      pautfunction,
                                      (!res_key && room_key_arr && (room_key_arr.length > 0) ? room_key_arr.join(",") : ""),
                                      2);

        var sql_from_total = "";
        if (res_key || roomcat)
        {
          sql_from_total += sql_from_room_part;
          if (res_key || objcat || artcat)
            sql_from_total += " UNION ALL "
        }

        if (res_key || objcat)
        {
          sql_from_total += sql_from_obj_part;
          if (res_key || artcat)
            sql_from_total += " UNION ALL "
        }

        if (res_key || artcat)
          sql_from_total += sql_from_art_part;

        sql = "WITH " + thePerslid + "," + theResrsv + sql_from_total;

        var sql_order = "";
        if (groupres == 1)
        { // Alleen backoffice reserveringen, group by deelreservering (rsv_ruimte_key and rcv_type DESC)
          if (sortout == 1) // locatie, tijd
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " locatie, " + (datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime()? " datumvan" : " TO_CHAR(datumvan, 'HH24:MI:SS')") + ", rsv_ruimte_key, rcv_type DESC, res_reservering_key, categorie DESC";
          else if (sortout == 2) // plaats
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " locatie, rsv_ruimte_key, rcv_type DESC, datumvan";
          else if (sortout == 3) // reservering
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " res_reservering_key, rsv_ruimte_key, rcv_type DESC, datumvan";
          else if (sortout == 4) // gastheer
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " gastheer, rsv_ruimte_key, rcv_type DESC, datumvan";
          else if (sortout == 5) // tijd
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + (datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime()? " datumvan" : " TO_CHAR(datumvan, 'HH24:MI:SS')") + ", rsv_ruimte_key, rcv_type DESC, locatie, categorie DESC, bezoekers DESC";
          else
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " res_reservering_key DESC, rsv_ruimte_key, rcv_type DESC, locatie, categorie DESC, datumvan, res_ruimte_nr, bezoekers DESC";
        }
        else
        {
          if (sortout == 1) // locatie, tijd
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " locatie, " + (datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime()? " datumvan" : " TO_CHAR(datumvan, 'HH24:MI:SS')") + ", res_ruimte_nr, rcv_type DESC, res_reservering_key, categorie DESC";
          else if (sortout == 2) // plaats
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " locatie, res_ruimte_nr, datumvan, res_reservering_key, categorie DESC";
          else if (sortout == 3) // reservering
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " res_reservering_key, datumvan, res_ruimte_nr, categorie DESC";
          else if (sortout == 4) // gastheer
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + " gastheer, datumvan, res_ruimte_nr, res_reservering_key, categorie DESC";
          else if (sortout == 5) // tijd
            sql_order = " ORDER BY" + (excel? " res_activiteit_upper," : "")
                      + (datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime()? " datumvan" : " TO_CHAR(datumvan, 'HH24:MI:SS')") + ", locatie, res_ruimte_nr, res_reservering_key, categorie DESC";
        }

        // Voor groeperingen het resultaat nu eerst filteren zodat je maar 1 regel per deelreservering overhoud.
        if (groupres == 1)
        {
          // Voor groepering nog verder filteren
          sql = " SELECT DISTINCT res_reservering_key"
              + ", locatie"
              + ", alg_gebouw_key"
              + ", alg_verdieping_key"
              + ", alg_ruimte_key"
              + ","+lcl.xsqla('res_ruimte_nr', 'res_ruimte_key')    // PF: weet zo niet of deze niet hierboven al vertaald is?!
              + ", alg_ruimte_aanduiding"
              + ", CASE categorie"
                + " WHEN 'V' THEN " + safe.quoted_sql(L("lcl_reserved_object"))
                + " WHEN 'C' THEN " + safe.quoted_sql(L("lcl_reserved_object"))
                + " ELSE res_voorziening"
                + " END res_voorziening"
              + ", datumvan"
              + ", datumtot"
              + ", aanvrager"
              + ", omschrijving"
              + ", opmerking"
              + ", rsv_ruimte_key"
              + ", NULL res_item_key"
              + ", res_status_bo_key"
              + ", res_rsv_ruimte_flag"
              + ", CASE categorie"
                + " WHEN 'V' THEN 'CV'"
                + " WHEN 'C' THEN 'CV'"
                + " ELSE 'R'"
                + " END categorie"
              + ", bezoekers"
              + ", gastheer"
              + ", prs_perslid_telefoonnr"
              + ", kostenplaats"
              + ", rsv_ruimte_aantal"
              + ", verwerkt_prijs"
              + ", rcv_type"
              + ", res_type"
              + ", rsv_ruimte_key keycolumn"
              + ", nrobjects"
              + ", res_rsv_ruimte_volgnr"
              + ", res_rsv_ruimte_ordernr"
              + ", res_ruimte_key"
              + ", res_activiteit_key"
              + ", res_activiteit_upper"
              + ", res_srtactiviteit_prefix"
              + ", bezoekers_shown"
              + ", ingang"
              + ", verval"
              + ", ins_discipline_key"
              + ", ins_srtdeel_uitleenbaar"
              + ", ins_alg_ruimte_key_org"
              + ", res_ruimte_opstel_default"
              + ", resgroup.res_activiteit_omschrijving"
              + ", resgroup.res_activiteit_meteindtijd"
              + ", res_rsv_ruimte_afgerond"
              + " FROM ("
              + sql
              + ") resgroup"
        }

        var res_keyColumn = ""
        var res_columns = new Array();

        // Deprecated: overal waar verderop 'new columnData' wordt gebruikt kan ook/beter de
        //             'new Column' gebruikt worden. Dan heb je namelijk alle properties tot
        //             je beschikking. Voor het gemak even backwards compatible.
        function columnData(caption, content, datatype, total, decimals)
        {
            return new Column({caption: caption, content: content, datatype: datatype, total: total, decimals: decimals});
        }

        select_oordeel = ", SUM(res.res_rsv_ruimte_satisfaction) sum_satisfaction"
                       + ", COUNT(res.res_rsv_ruimte_satisfaction) cnt_satisfaction"
                       + ", AVG(res.res_rsv_ruimte_satisfaction) oordeel"
                       + ", MAX(res_rsv_ruimte_satisfaction_op) oordeel_opm";

        if (groupres == 6)
        { // locatie
          res_keyColumn = "alg_locatie_key";
          res_columns[res_columns.length] = new columnData(L("lcl_location"), "locatie")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = "SELECT l.alg_locatie_key " + res_keyColumn
              + ", l.alg_locatie_omschrijving locatie"
              + ", COUNT(distinct res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + ", alg_locatie l "
              + " WHERE res.alg_locatie_key = l.alg_locatie_key"
              + " GROUP BY l.alg_locatie_key"
              + ", l.alg_locatie_omschrijving";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 10)
        { // gebouw
          res_keyColumn = "alg_gebouw_key";
          res_columns[res_columns.length] = new columnData(L("lcl_building"), "gebouw")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = " SELECT g.alg_gebouw_key " + res_keyColumn
              + ", l.alg_locatie_code || '-' || g.alg_gebouw_naam gebouw"
              + ", COUNT(distinct res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + ", alg_locatie l"
              + ", alg_gebouw g"
              + " WHERE res.alg_gebouw_key = g.alg_gebouw_key"
              + " AND g.alg_locatie_key = l.alg_locatie_key"
              + " GROUP BY g.alg_gebouw_key"
              + ", l.alg_locatie_code || '-' || g.alg_gebouw_naam";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 11)
        { // activiteit
          res_keyColumn = "res_activiteit_key";
          res_columns[res_columns.length] = new columnData(L("lcl_activity"), "activiteit")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = " SELECT a.res_activiteit_key " + res_keyColumn
              + ", " + lcl.xsql('a.res_activiteit_omschrijving', 'a.res_activiteit_key') + " activiteit"
              + ", COUNT(distinct res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + ", res_activiteit a"
              + " WHERE res.res_activiteit_key = a.res_activiteit_key"
              + " GROUP BY a.res_activiteit_key"
              + ", " + lcl.xsql('a.res_activiteit_omschrijving', 'a.res_activiteit_key');
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 12)
        { // kostensoort
          res_keyColumn = "prs_kostensoort_key";
          res_columns[res_columns.length] = new columnData(L("lcl_charge_type"), "kostensoort")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = " SELECT COALESCE(res.prs_kostensoort_key, 0) " + res_keyColumn
              + ", res.prs_kostensoort_oms kostensoort"
              + ", COUNT(distinct res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + " GROUP BY res.prs_kostensoort_key"
              + ", res.prs_kostensoort_oms";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 13)
        { // kostensoortgrp
          res_keyColumn = "prs_kostensoortgrp_key";
          res_columns[res_columns.length] = new columnData(L("lcl_charge_type_group"), "kostensoortgrp")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = " SELECT COALESCE(res.prs_kostensoortgrp_key, 0) " + res_keyColumn
              + ", " + lcl.xsql('res.prs_kostensoortgrp_oms','res.prs_kostensoortgrp_key') + " kostensoortgrp"
              + ", COUNT(distinct res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + " GROUP BY res.prs_kostensoortgrp_key"
              + ", res.prs_kostensoortgrp_oms";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 7)
        { // artikelen
          res_keyColumn = "artikel_key";
          res_columns[res_columns.length] = new columnData(L("lcl_res_art_desc"), "artikelomschrijving")
          res_columns[res_columns.length] = new columnData(L("lcl_res_item_price"), "artikelprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_btw_percentage"), "artikelbtw", "float", false)
          res_columns[res_columns.length] = new columnData(L("lcl_res_art_nr"), "artikelaantal", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          sql = " SELECT res.artikel_key " + res_keyColumn
              + ", res.res_voorziening artikelomschrijving"
              + ", res.stuks_prijs artikelprijs"
              + ", res.btwtarief artikelbtw"
              + ", SUM(res.aantal) artikelaantal"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + " FROM (" + sql + ") res"
              + " WHERE categorie = 'C'"
              + " GROUP BY artikel_key"
              + ", res_voorziening"
              + ", stuks_prijs"
              + ", btwtarief";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 8)
        { // artikelnummer
          res_keyColumn = "artikel_key";
          res_columns[res_columns.length] = new columnData(L("lcl_res_art_number"), "artikel")
          res_columns[res_columns.length] = new columnData(L("lcl_res_art_nr"), "artikelaantal", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          sql = " SELECT res.artikel_key " + res_keyColumn
              + ", res.artikelnummer || ' - ' ||"
                + " (SELECT MIN(" + lcl.xsql('res_artikel_omschrijving','res_artikel_key') + ")"
                + " FROM res_v_aanwezigartikel"
                + " WHERE res_artikel_nr = res.artikelnummer)"
                + " || ' ' ||"
                + " CASE (SELECT COUNT(" + lcl.xsql('res_artikel_omschrijving','res_artikel_key') +") FROM res_v_aanwezigartikel WHERE res_artikel_nr = res.artikelnummer)"
                + " WHEN 1"
                + " THEN ''"
                + " ELSE '...'"
                + " END artikel"
              + ", SUM(res.aantal) artikelaantal"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + " FROM (" + sql + ") res"
              + " WHERE categorie = 'C'"
              + " GROUP BY artikel_key"
              + ", artikelnummer";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 9 || groupres == 14)
        { // kostenplaats
          if (groupres == 9)
          {
            res_keyColumn = "kostenplaats_key";
          }
          else
          {
            res_keyColumn = "prs_afdeling_key";
            res_columns[res_columns.length] = new columnData(L("lcl_department"), "organisatie")
          }
          res_columns[res_columns.length] = new columnData(L("lcl_res_account"), "kostenplaats")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = " SELECT COALESCE(res.kostenplaats_key, 0) kostenplaats_key"
              + ", res.kostenplaats"
              + ", res.prs_afdeling_key"
              + ", res.organisatie"
              + ", COUNT(DISTINCT res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + " GROUP BY kostenplaats_key"
              + ", kostenplaats"
              + ", prs_afdeling_key"
              + ", organisatie";
          sql_order = " ORDER BY organisatie, kostenplaats";
        }
        else if (groupres == 5)
        { // district
          res_keyColumn = "alg_district_key";
          res_columns[res_columns.length] = new columnData(L("lcl_district"), "district")
          res_columns[res_columns.length] = new columnData(L("lcl_res_res_nr"), "aantalres", "number", true)
          res_columns[res_columns.length] = new columnData(L("lcl_total"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new columnData(L("lcl_res_oordeel"), fncolOordeelAvg, "float", true, 1)
          sql = "SELECT d.alg_district_key " + res_keyColumn
              + ", d.alg_district_omschrijving district"
              + ", COUNT(distinct res.res_rsv_ruimte_key) aantalres"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + select_oordeel
              + " FROM (" + sql + ") res"
              + ", alg_district d"
              + " WHERE res.alg_district_key = d.alg_district_key"
              + " GROUP BY d.alg_district_key"
              + ", d.alg_district_omschrijving";
          sql_order = " ORDER BY 2";
        }
        else if (groupres == 4)
        { // De default als groepering als niets gekozen
          // minfo reserveringen
          res_keyColumn = "res_reservering_key";
          if (S("res_reservering_flags") > 0)
            res_columns[res_columns.length] = new Column({caption: "o", content: fncolFlags, align: "center"})
          res_columns[res_columns.length] = new columnData(L("lcl_resnr"), "res_reservering_key")
          res_columns[res_columns.length] = new columnData(L("lcl_location"), "locatie")
          res_columns[res_columns.length] = new columnData(L("lcl_room_n"), "ruimte_aanduiding")
          res_columns[res_columns.length] = new Column( {caption: L("lcl_date"), content: fncolDatum, customSort: fncolDatumSort, datatype: "date", nowrap: true});
          res_columns[res_columns.length] = new columnData(L("lcl_res_starttime"), fncolVan, "time")
          res_columns[res_columns.length] = new columnData(L("lcl_res_endtime"), fncolTot, "time")
          res_columns[res_columns.length] = new columnData(L("lcl_prs_organisatie"), "organisatie")
          if (S("res_allow_for_others"))
            res_columns[res_columns.length] = new columnData(L("lcl_host"), "gastheer")
          res_columns[res_columns.length] = new columnData(L("lcl_res_account"), "kostenplaats")
          res_columns[res_columns.length] = new columnData(L("lcl_descr"), "omschrijving")
          res_columns.push (new Column({caption: L("lcl_config_instance"), content: fnrowConfiguration, keepKeyRepeat: true}));
          res_columns[res_columns.length] = new columnData(L("lcl_remark"), "opmerking")
          res_columns.push (new Column({caption: L("lcl_res_pers_n"), content: fnrowVisitorsF, datatype: "number", total: true}));
          res_columns[res_columns.length] = new columnData(L("lcl_res_no_show"), "noshow")
          res_columns[res_columns.length] = new columnData(L("lcl_res_rsv_kosten"), "totaalprijs", "currency", true)
          res_columns[res_columns.length] = new Column( {caption: L("lcl_res_oordeel"), content: fncolOordeel, total: true})
          if (excel || print)
            res_columns[res_columns.length] = new Column( {caption: L("lcl_fac_like_remark"), content: "oordeel_opm"})

          sql = "SELECT res_srtactiviteit_prefix || res.res_reservering_key || '/' || res.res_rsv_ruimte_volgnr " + res_keyColumn
              + ", res.res_reservering_key rkey"
              + ", res.res_rsv_ruimte_volgnr volgnr"
              + ", res.locatie locatie"
              + ", res.alg_ruimte_aanduiding ruimte_aanduiding"
              + ", MIN(res.datumvan) datumvan"
              + ", MAX(res.datumtot) datumtot"
              + ", res.organisatie organisatie"
              + (S("res_allow_for_others") ? ", res.gastheer gastheer" : "")
              + ", res.kostenplaats kostenplaats"
              + ", res.omschrijving omschrijving"
              + ", res.opmerking opmerking"
              + ", res.res_rsv_ruimte_satisfaction oordeel"
              + ", res.res_rsv_ruimte_satisfaction_op oordeel_opm"
              + ", res.res_rsv_ruimte_flag"
              + ", bezoekers"
              + ", res.verval"
              + ", res.res_ruimte_opstel_default"
              + ", res.aantal"
              + ", res.res_voorziening"
              + ", MAX(res.noshow) noshow"
              + ", SUM(res.verwerkt_prijs) totaalprijs"
              + ", MAX(res.rsv_ruimte_key) rsv_ruimte_key"
              + ", MAX(res.alg_ruimte_key) alg_ruimte_key"
              + ", MAX(res.categorie) categorie"
              + ", MAX(res.res_item_key) res_item_key"
              + ", MAX(res.res_ruimte_key) res_ruimte_key"
              + ", res.res_activiteit_meteindtijd"
              + " FROM (" + sql + ") res"
              + " GROUP BY res_srtactiviteit_prefix || res_reservering_key || '/' || res.res_rsv_ruimte_volgnr"
              + ", res.res_reservering_key"
              + ", res.res_reservering_key || '/' || res.res_rsv_ruimte_volgnr"
              + ", res_rsv_ruimte_volgnr"
              + ", locatie"
              + ", alg_ruimte_aanduiding"
              + ", datumvan"
              + ", organisatie"
              + (S("res_allow_for_others") ? ", gastheer" : "")
              + ", kostenplaats"
              + ", omschrijving"
              + ", opmerking"
              + ", res.res_rsv_ruimte_satisfaction"
              + ", res.res_rsv_ruimte_satisfaction_op"
              + ", noshow"
              + ", res_ruimte_key"
              + ", res_rsv_ruimte_flag"
              + ", bezoekers"
              + ", verval"
              + ", res_ruimte_opstel_default"
              + ", aantal"
              + ", res_voorziening"
              + ", res_activiteit_meteindtijd";
          sql_order = " ORDER BY rkey || '/' || volgnr";
        }
        // Extra wrapper omdat ADO anders komt met 'Operation not allowed when object is closed'
        // Blijkbaar snapt die de WITH constructie vooraan niet zo
        if ((groupres > 1) && (groupres != 4))
        {
          sql = "SELECT * FROM (" + sql + ") " + sql_order;
        }
        else
        {
          sqltrack = (minfo
                     ? ", TO_DATE('01-01-1970', 'DD-MM-YYYY')"
                     : ", (SELECT MAX(t.fac_tracking_datum)"
                       + "     FROM fac_tracking t"
                       + "        , fac_srtnotificatie sn"
                       + "    WHERE t.fac_srtnotificatie_key = sn.fac_srtnotificatie_key"
                       + "      AND t.fac_tracking_refkey = rsv_ruimte_key" // rsv_ruimte_key voor groupres=4 en <=1
                       + "      AND sn.fac_srtnotificatie_xmlnode = 'reservering')")
                   + " recentdatum";
          sql = "SELECT us.*"
              + sqltrack
              + " FROM (" + sql + ") us " + sql_order;
        }

        /***** End build sql *****/

        var count = 0;
        var descr = "";
        var remark = "";
        var total = new Array;

        if (groupres > 1)
        { // minfo with grouping
          /*****************************************************************
           * Callback functies ResultsetTable for only MI with grouping
           ****************************************************************/
          var recent = new Date();
          recent.setMinutes(recent.getMinutes() - S("res_reservering_recent"));
          function fnrowClassM(oRs)   // tr-class
          {
            var class1 = "";
            if (groupres == 4)
            {
              var cnt_recent = new Date(oRs("recentdatum").value);
              if (cnt_recent > recent)
              {
                class1 += " updated ";
              }
            }
            return class1;
          }
          function fnrowDataM(oRs)
          {
            var data = { resKey : oRs(res_keyColumn).value }; // Reservering key
            if (res_keyColumn == "res_reservering_key")
            {
                data.resVolgnr = oRs("volgnr").value; // Reservering volgnummer
                data.resRsvRuimteKey = oRs("rsv_ruimte_key").value; // rsv_ruimte_key
            }

            return JSON.stringify(data);
          }

          function fncolDistrict(oRs)
          {
            var content = oRs("locatie");
            return content;
          }

          var tot_aantal_art = 0;
          var tot_aantal_res = 0;
          var tot_artikelprijs = 0;
          var tot_totaalprijs = 0;
          var sum_satisfaction = 0;
          var cnt_satisfaction = 0;
          var aantal_oordeel = 0;
          function fntotalCalc(oRs)
          {
            if (groupres == 4 && (oRs("oordeel").Value))
            { // Totaal oordeel is alle cijfers opgeteld gedeeld door het aantal beoordelingen.
                sum_satisfaction += oRs("oordeel").Value;
                aantal_oordeel++;
            }
            if (groupres != 4 && groupres != 7 && groupres != 8)
            {
              tot_aantal_res += parseInt(oRs("aantalres").Value, 10);

              // Totaal oordeel is alle cijfers opgeteld gedeeld door het aantal beoordelingen.
              sum_satisfaction += oRs("sum_satisfaction").Value;
              cnt_satisfaction += oRs("cnt_satisfaction").Value;
            }
            if (groupres == 7 || groupres == 8)
            {
              tot_aantal_art += parseInt(oRs("artikelaantal").Value, 10);
              if (groupres == 7)
              {
                tot_artikelprijs += parseFloat((oRs("artikelprijs").Value? oRs("artikelprijs").Value : 0), 10);
              }
            }
              tot_totaalprijs += oRs("totaalprijs").Value;
          }

          function fntotalShow(column, nrlines)
          {
            function doOordeel(cnt_satisfaction, sum_satisfaction)
            {
              var result = cnt_satisfaction > 0? sum_satisfaction/cnt_satisfaction : 0;
              if (excel || print)
                result = (result!=0? safe.displayfloat(sum_satisfaction/cnt_satisfaction, 1) : "");
              else
                result = rater(result, {readonly: true});
              return result;
            }

            var result = "";
            switch (column.caption)
            {
              case L("lcl_res_art_nr")    : result = tot_aantal_art; break;
              case L("lcl_res_res_nr")    : result = tot_aantal_res; break;
              case L("lcl_res_oordeel")   : if (groupres == 4)
                                              result = aantal_oordeel > 0? doOordeel(aantal_oordeel, sum_satisfaction) : "";
                                            else
                                              result = cnt_satisfaction > 0? doOordeel(cnt_satisfaction, sum_satisfaction) : "";
                                            break;
              case L("lcl_res_item_price"): result = safe.curr(tot_artikelprijs); break;
              case L("lcl_res_rsv_kosten"):
              case L("lcl_total")         : result = safe.curr(tot_totaalprijs); break;
            }
            return result;
          }

          /*********************************************************************
           * End callback functies ResultsetTable for only MI with grouping
           ********************************************************************/

          var rst = new ResultsetTable({keyColumn: res_keyColumn,
                                        ID: "restable",
                                        rowClass: fnrowClassM,
                                        rowData: fnrowDataM,
                                        sql: sql,
                                        filterParams: params,
                                        outputmode: outputmode,
                                        title: L("lcl_reservation_title"),
                                        showAll: showall,
                                        totalCalc: fntotalCalc,
                                        totalShow: fntotalShow
                                       })

          // Kolommen
          for (var i = 0; i < res_columns.length; i++)
          {
            rst.addColumn(res_columns[i]);
          }

          // Acties
          if (groupres == 4) {
            rst.addAction({action: "resEdit", caption: L("lcl_edit"), isDefault: true});
          }

          var count = rst.processResultset();

        }
        else
        { // (BO: grouping and no grouping)
          /***********************************************************************
           * Callback functies ResultsetTable for only BO grouping and no grouping
           **********************************************************************/
          var recent = new Date();
          recent.setMinutes(recent.getMinutes() - S("res_reservering_recent"));
          function fnrowClassB(oRs)   // tr-class
          {
            // resR of resC of resV
            var class1 = "res" + oRs("res_type").value + (oRs("ingang").value == 0 || oRs("verval").value == 0? " res_fatal " : "");

            var cnt_recent = new Date(oRs("recentdatum").value);
            if (cnt_recent > recent)
            {
              class1 += " updated ";
            }
            return class1;
          }

          function fnrowData(oRs)
          {
            var resKey = oRs("res_reservering_key").value; // Reservering key
            var resVolgnr = oRs("res_rsv_ruimte_volgnr").value; // Reservering volgnummer
            var resRsvRuimteKey = oRs("rsv_ruimte_key").value; // rsv_ruimte_key
            var resPartkey = oRs("res_item_key").value; // rsv_ruimte_key, rsv_deel_key of rsv_artikel_key
            var resPartType = oRs("categorie").value; // reserveringstype ('C', 'V', 'R')

            var resVanDatumMidnight = new Date(oRs("datumvan").value).midnight(); // rsv_ruimte_van datum om middernacht
            var now = new Date();
            var resFuture = (resVanDatumMidnight > now? 1 : 0)

            var data = {resKey: resKey, resVolgnr: resVolgnr, resRsvRuimteKey: resRsvRuimteKey,
                        resPartkey: resPartkey, resPartType: resPartType, resFuture: resFuture,
                        res_rsv_deel_key: resPartkey};

            return JSON.stringify(data);
          }

          function fnrowActionEnabler(oRs)
          {
            var data = { eEdit   : true, // Altijd aanwezig
                         eClose  : false,
                         eNoShow : false,
                         eLendOut: false,
                         eReceive: false,
                         eAdapt: false
                       }

            var besStatusBO = oRs("res_status_bo_key").value;
            if (oRs("res_status_bo_key").value < S("res_bo_status_key"))
            {
                data.eClose = true;
                // Voor noshow-optie wordt ivm performance globaal gekeken of het mag. De feitelijke
                // actie controleert definitief en verfijnder
                data.eNoShow = true;
            }
            if (oRs("ins_srtdeel_uitleenbaar").Value == 1)
            {
              // TODO: We negeren de 3D scope vooralsnog. Veel te ingewikkeld met org-velden en dergelijke
              //       Eerst maar even parktijkgeluiden afwachten
              //       user.checkAutorisation cache't per discipline dus dat is te overzien.
              // LET OP: Hier dus de ins_discipline_key, niet de res_ins_discipline_key
              var authparams = user.checkAutorisation("WEB_INSFOF", true, oRs("ins_discipline_key").Value);
              if (authparams && authparams.PRSwritelevel < 9)
              {
                  data.eLendOut = oRs("ins_alg_ruimte_key_org").value == null;
                  data.eReceive = !data.eLendOut;
                  data.eAdapt = data.eReceive;
              }
            }
            return data;
          }

          function fncolCompleteRes(oRs)
          {
            var content = "<div id='afm" + oRs("keycolumn").value + "'></div>";
            if (oRs("res_status_bo_key").Value >= 5)
            {
                if (!excel)
                    content = "<img src='../Pictures/res_ok.gif'><div style='display:none'>"+oRs("res_status_bo_key").Value+"</div>";
                else
                    content = L("lcl_Yes");
            }
            return content;
          }

          function fnrowResNr(oRs)
          {
            return (oRs("res_srtactiviteit_prefix").value? oRs("res_srtactiviteit_prefix").value : "") + String(oRs("res_reservering_key").value) + "/" + oRs("res_rsv_ruimte_volgnr").value;
          }

          function fnrowVisitors(oRs)
          {
            var bezoekers_shown = oRs("bezoekers_shown").value;
            return (oRs("bezoekers").value && oRs("bezoekers").value != 0? (bezoekers_shown >= 0? bezoekers_shown + "/" : "") + oRs("bezoekers").value : "");
          }

          function fnrowOpstelling(oRs)
          {
            return ((oRs('categorie').value == 'R')? safe.html(oRs("res_voorziening").value) : "");
          }

          function fnrowObject(oRs)
          {
            return ((oRs('categorie').value != 'R')? safe.html(oRs("res_voorziening").value) : "");
          }

          function fnrowConfiguration(oRs)
          {
            var isDefault = true;
            if (oRs("categorie").value == 'R')
            {
              isDefault = (oRs('res_ruimte_opstel_default').value == '1');
            }
            if (groupres == 1)
            {
              if (oRs("categorie").value == 'R')
              {
                // TODO: ik wil hier een span class toevoegen om afwijking van de
                // defaultopstelling te markeren. Ik vind het echter nu nogal ondoorzichtig
                // waar die kolomwaarde vandaan zou moeten komen.
                //c_inst = (oRs('res_ruimte_opstel_default').value != "1" ? "*" : "")
                c_inst = oRs("res_voorziening").value;
              }
              else
              {
                c_inst = L("lcl_reserved_object");
              }
            }
            else
            {
              if (oRs("aantal").value == null)
              {
                 c_inst = oRs("res_voorziening").value;
              }
              else
              {
                 c_inst = oRs("aantal").value + " * " + oRs("res_voorziening").value;
              }
            }
            if (!isDefault)
            {
              return "<span class='afwijkopstel'>" + safe.html(c_inst) + "</span>";
            }
            else
            {
              return safe.html(c_inst);
            }
          }

          function fncolResApproved(oRs)
          {
            var approved_txt = "";
            if (oRs("res_rsv_ruimte_afgerond").Value == 1)
            {
              approved_txt = L("lcl_res_resappr");
            }
            else
            {
              if (frontend)
              {
                if (oRs("approval").Value == 1)
                  approved_txt = L("lcl_res_tobeapproved");
                //else 'nog niet goed te keuren'
              }
              else
                approved_txt = L("lcl_res_notapproved");
            }
            return approved_txt;
          }

          /***************************************************************************
           * End callback functies ResultsetTable for only BO grouping and no grouping
           **************************************************************************/

          var rst = new ResultsetTable({keyColumn: "keycolumn",
                                        ID: "restable",
                                        rowClass: fnrowClassB,
                                        rowData: fnrowData,
                                        rowActionEnabler: fnrowActionEnabler,
                                        sql: sql,
                                        flexModule: "RES",
                                        flexId: "rsv_ruimte_key", // keycolumn is soms res_rsv_deel_key
                                        flexGroupId: "res_activiteit_key",
                                        filterParams: params,
                                        outputmode: outputmode,
                                        title: L("lcl_reservation_title"),
                                        inlineDetails: ((backo || minfo) && groupres == 1)?"inlineVoorzieningUrl":null,
                                        hasInlineDetails: ((backo || minfo) && groupres == 1)?fnHasVZ:null,
                                        showAll: showall,
                                        suppressKeyRepeat: print?"rsv_ruimte_key":null // suppress fields when no key-change
                                       });
          // Kolommen
          // AAFM#14872/PF: Deze locatiekolom is wat dubbelop. We spreken af dat we die
          //                eerst maar eens niet meer tonen. Als er gefundeerde klachten komen is
          //                deze snel genoeg combined terug te halen
//          rst.addColumn(new Column({caption: L("lcl_location"), content: "locatie"}));
          rst.addColumn(new Column({caption: (excel?L("lcl_res_resafm"):'<img id="checkall" src="../Pictures/res_ok.gif">'), content: fncolCompleteRes}));
          if (S("res_reservering_flags") > 0)
            rst.addColumn(new Column({caption: "o", content: fncolFlags, align: "center"}));
          rst.addColumn(new Column({caption: L("lcl_room_n"), content: "res_ruimte_nr", combine: false, hasActions: true}));
          // Compacter op scherm als datefrom==dateto
          if (res_key || outputmode != 0 || (outputmode == 0 && datefrom && dateto && datefrom.midnight().getTime() != dateto.midnight().getTime()))
          { // Compact als begin==eind
            rst.addColumn(new Column({caption: L("lcl_date"), content: fncolDatum, customSort: fncolDatumSort, datatype: "date", nowrap: true}));
          }
          rst.addColumn(new Column({caption: L("lcl_res_starttime"), content: fncolVan, datatype: "time", keepKeyRepeat: true}));
          rst.addColumn(new Column({caption: L("lcl_res_endtime"), content: fncolTot, datatype: "time"}));

          rst.addColumn(new Column({caption: L("lcl_resnr"), content: fnrowResNr}));
          rst.addColumn(new Column({caption: L("lcl_res_pers_n"), content: fnrowVisitors}));
          if (excel)
          { // Aparte kolommen voor aantal/config en aantal/voorzieningen
            rst.addColumn(new Column({caption: L("lcl_res_opstelling"), content: fnrowOpstelling}));
            if (groupres != 1)
                rst.addColumn(new Column({caption: L("lcl_res_aantalvoorziening"), content: "aantal"}));
            rst.addColumn(new Column({caption: L("lcl_reserved_object"), content: fnrowObject}));
          }
          else
            rst.addColumn(new Column({caption: L("lcl_config_instance"), content: fnrowConfiguration, keepKeyRepeat: true}));
          if (S("res_allow_for_others") && S("res_bo_show_host") == 1)
            rst.addColumn(new Column({caption: L("lcl_host"), content: "gastheer"}));
          rst.addColumn(new Column({caption: L("lcl_res_requestor"), content: "aanvrager"}));
          if (S("res_bo_show_telnr") == 1)
            rst.addColumn(new Column({caption: L("lcl_res_requestor_phone"), content: "prs_perslid_telefoonnr"}));
          if (S("res_bo_show_kpn") == 1)
          {
            rst.addColumn(new Column({caption: L("lcl_res_account"), content: "kostenplaats"}));
          }
          if (S('show_ordernr') == 3 && outputmode != 0)
            rst.addColumn(new Column({caption: L("lcl_mld_inf_Ordernr"), content: "res_rsv_ruimte_ordernr" }));
          rst.addColumn(new Column({caption: L("lcl_descr"), content: "omschrijving"}));
          if (!S("res_hide_remark"))
            rst.addColumn(new Column({caption: L("lcl_remark"), content: "opmerking"}));

          if (outputmode != 0)
            rst.addColumn(new Column({caption: L("lcl_activity"), content: "res_activiteit_omschrijving"}));
          if (S("res_approval") > 0)
            rst.addColumn(new Column({caption: L("lcl_res_approval"), content: fncolResApproved}));

          // Acties
          rst.addAction({action: "resEdit", caption: L("lcl_edit"), isDefault: true});
          if (authparams.PRSwritelevel < 9 && authparams.ALGwritelevel < 9) // grove controle
            rst.addAction({action: "resClose", caption: L("lcl_close"), enabler: "eClose", multi: true, multiOnce: true});
          if (    S("res_noshow_detailed") == 1
               && authparamsRESNOS
               && authparamsRESNOS.PRSwritelevel < 9
               && authparamsRESNOS.ALGwritelevel < 9)
          {
            rst.addAction({action: "resNoShow", caption: L("lcl_res_no_show"), enabler: "eNoShow"});
          }

          rst.addAction({ action: "insCheckOut", caption: L("lcl_obj_lend_out"), enabler: "eLendOut"});
          rst.addAction({ action: "insCheckIn", caption: L("lcl_obj_receive"), enabler: "eReceive"});
          // te druk rst.addAction({ action: "insAdapt", caption: L("lcl_ins_adapt"), enabler: "eAdapt"});

          var count = rst.processResultset();
        }
      } // else bo || mi
%>
    </body>
  </html>
<%
}
%>
