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

    File:               opdr_edit_uren.asp
    Description:        Muteerscherm voor uren bij opdrachten
    Parameters:
                        opdr_uren_key
    Context:
    Note:               Submit naar opdr_edit_uren_save.asp
*/ %>

<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../Shared/iface.inc" -->
<!-- #include file="mld.inc" -->

<%
FCLTHeader.Requires({ plugins:["jQuery"],
                      js: ["jquery-ui.js"]
                    })

/***** Get webform parameters *****/

var urole = getQParamSafe("urole", "fe");
var opdr_key = getQParamInt("opdr_key", -1);
var mld_key = getQParamInt("mld_key", -1);
var datefrom = getQParamDate("datefrom"); // Moet een maandag zijn
var prs_key = getQParamInt("prs_key", user_key);
var withCollegas = getQParamInt("collegas", 0) == 1; // Toon ook de opdrachten van collega's
var withImprod = getQParamInt("improd", 0) == 1; // Toon ook de improductief 'opdrachten'
var withOnkosten = getQParamArray("onkosten", [""]).join(","); // Toon onkosten velden voor deze regels
var recentPastDaysInt = getQParamInt("recentpastdays", 30);  // hoeveel dagen terug kijken voor favorieten

var userinfo = new Perslid(prs_key);

var autfunction = {fe: "WEB_UURUSE", fo: "WEB_UURFOF", bo: "WEB_UURBOF"}[urole];
/***** End get webform parameters *****/

var authparams = user.checkAutorisation(autfunction);
var canWrite = authparams.PRSwritelevel < 9;

var dateto = new Date(datefrom);
dateto.setDate(dateto.getDate() + 6);
var nieuwe_maand = (datefrom.getDate() > dateto.getDate()) && S("mld_opdr_hours_approve_monthly");

// Handig
var oneDay = 24 * 60 * 60 * 1000;
var oneWeek = 7 * oneDay;
var oneYear = 365 * oneDay;

if (urole != "fe" && canWrite)
{   // (heel flexibel) controleren of wij (user_key) WEB_UURFOF schrijfrechten hebben
    // op minstens één discipline waar prs_key WEB_MLDORD rechten op heeft
    // Dan staan we toe dat je alle regels mag wijzigen.
    // We ondersteunen gewoon niet dat je enkele regels mag bewerken of goedkeuren etc.

    // Alle mogelijke uitvoerenden (mensen die MLDORD rechten hebben)
    // waarbij ikzelf MLD_UURxxx leesrechten heb op dezelfde discipline
    var uitvSQL = "SELECT DISTINCT f.prs_perslid_key"
                + "  FROM fac_v_webgebruiker f,"      // persoon met urenbriefje
                + "       fac_functie ff,"
                + "       fac_v_webgebruiker fzelf"  // ikzelf
                + " WHERE f.fac_functie_key = ff.fac_functie_key"
                + "   AND ff.fac_functie_code = 'WEB_MLDORD'"
                + "   AND f.fac_gebruiker_prs_level_read < 9"
                + "   AND f.fac_gebruiker_alg_level_read < 9"
                + "   AND fzelf.fac_functie_key = " + authparams.autfunctionkey
                + "   AND fzelf.fac_gebruiker_prs_level_write < 9" // in opdr_ures_list.inc staat hier _read!
                + "   AND fzelf.fac_gebruiker_alg_level_write < 9"
                + "   AND fzelf.prs_perslid_key = " + user_key;

    uitvSQL += "  AND f.prs_perslid_key = " + prs_key;
    uitvSQL += "  AND f.ins_discipline_key = fzelf.ins_discipline_key"; // UURFOF en UURBOF hebben nauwkeurig minlevel
    var uitvRs = Oracle.Execute(uitvSQL);
    canWrite = !uitvRs.eof;
    uitvRs.Close();
}

var sql = "SELECT COUNT(*) aantal"
        + "  FROM mld_kosten"
        + " WHERE mld_kosten_verwijder IS NULL";
var oRs = Oracle.Execute(sql);
var heeftOnkosten = (oRs("aantal").Value > 0);
oRs.Close();

%>

<html>
  <head>
    <% FCLTHeader.Generate(); %>
<%  if (!withCollegas) { // initieel handlerkolom uit
%>
    <style>
      .colhandler { display:none; }
    </style>
<%  } %>
    <script type="text/javascript">
        var anyChange = false; // Voorkom te veel refreshes
<%      function getWeekString(datum) {
          var sql = "SELECT TO_CHAR({0}, 'IYYY-IW') weeknr FROM DUAL".format(datum.toSQL());
          var oRs = Oracle.Execute(sql);
          var txt = oRs("weeknr").Value;
          oRs.Close()
          return txt;
        }
%>      FcltMgr.setTitle(L("lcl_mld_ord_weeklijst") + "<%=getWeekString(datefrom)%>");

        $(function() {
          $("div.divrstable table thead").addClass("float-alone"); // force float without fcltheader
<%        var onkostRegelIds = getQParamArray("onkosten", []);
          if (onkostRegelIds.length) { %>
            let onkostenInput = $("tr#<%=onkostRegelIds[onkostRegelIds.length-1]%>").next("tr.mldopdrurenkosten").find(":input:not([disabled])")?.get(0);
            onkostenInput?.offsetHeight; // Trigger a reflow, flushing the CSS changes
            onkostenInput?.focus();
<%        } %>
        });

        function showCollegaOpdrachten()
        {
            window.location.href = "<%=Request.ServerVariables("SCRIPT_NAME") + "?collegas=1" + transitQS()%>"
        }
        function showImproductief()
        {
            window.location.href = "<%=Request.ServerVariables("SCRIPT_NAME") + "?improd=1" + transitQS()%>"
        }
        function showOnkosten(idcode)
        {
            window.location.href = "<%=Request.ServerVariables("SCRIPT_NAME") + "?x=1" + transitQS()%>&onkosten=" + idcode;
        }

        // Onchange urenveldje
        function updateDag(veld, millisec, remark)
        {
        	var setting_mld_opdr_minuren = (<%=(S("mld_opdr_minuren")? 1 : 0)%> == 1);
          if (!sanitizeHours(veld, setting_mld_opdr_minuren))
            return false;
          anyChange = true;
          var tr = $(veld).closest("table").closest("tr")[0]; // <table><tr> <td>opdrachtnr</td> <td>omschrijving</td> <td><table><tr><td> <input><i> </i></td></tr></table> <td>...</td> ... <td>Restant</td></tr></table>
          var uPlanned = hourToDecimal($("input#fldmldurenplan"  ,tr)[0].value) || 0;
          var uBefore  = hourToDecimal($("input#fldmldurenbooked",tr)[0].value) || 0;
          var uOpdrUren = parseInt($("input#fldopdruren", tr)[0].value) || 0;
          var som = 0;
          var rest = 0;
          $("input", tr).each(function()
          {
            if (this.id == "fldmldurentotal") // som-veld
            {
              this.value = decimalToHour(som)||0;
              rest = uPlanned - uBefore - som;
              $("input#fldmldurenrest", tr)[0].value = decimalToHour(rest) || 0;
              return false; // stop de loop
            }
            else
              som += hourToDecimal(this.value);
          });

          validateField(veld, uOpdrUren != 4 || rest >= 0, L("lcl_mlduren_max_exceeded"));

          if (uOpdrUren == 4 && rest < 0)
          {   // Bij overschrijding van maximaal geregistreerde uren (mld_mld_typeopdr_uren == 4) dit melden en wijziging niet opslaan.
            return false;
          }

          var mld_opdr_key = -1;
          var mld_impropdr_key = -1;
          if (tr.id.substr(0, 1) == "O")
            mld_opdr_key = parseInt(tr.id.substr(1));
          else
            mld_impropdr_key = parseInt(tr.id.substr(1));

          var uren = hourToDecimal(veld.value);

          // Veld is het inputveld. Vind het bijbehorende <i></i> jquery object.
          var commentBaloon = $("span:has(> i)", $(veld).closest("tr")); // <table><tr><td> <input><i> </i></td></tr></table>
          if (uren == 0)
          {
            commentBaloon.html("<%=I("fa-comment fa-lg", { fastyle: "fal"})%>");
            commentBaloon.css("visibility", "hidden"); // Uren zijn verwijderd.
          }
          else
          {
            if (!commentBaloon.length) // tekstballon bestaat nog niet: aanmaken
            {
                var new_comment = "<span class='details' title='' style='visibility: visible;'"
                                + " onclick='edit_remark(this, " + veld.attributes["datum"].value + ", true)'"
                                + ">"
                                + I("fa-comment fa-lg", {fastyle: "fal"});
                commentBaloon.prevObject.append(new_comment);
            }
            else
            {
                commentBaloon.css("visibility", "visible"); // Uren zijn toegevoegd of aangepast.
            }
          }

          // Kleur/stijl aanpassen bij afwijkingen
          if ($("#fldmldurentotal", tr).val() == $("#fldmldurenplan", tr).val())
              $("#fldmldurentotal", tr).removeClass("afwijk");
          else
            $("#fldmldurentotal", tr).addClass("afwijk");

          var data = { prs_key: <%=prs_key%>,
                       mld_opdr_key: mld_opdr_key,
                       mld_impropdr_key: mld_impropdr_key,
                       datum: millisec,
                       uren: uren
                     };
          if (remark != null)
            data.remark = (remark || "")

          <% protectRequest.dataToken("data"); %>
          $.post("opdr_edit_uren_save.asp?urole=<%=urole%>",
                 data,
                 FcltCallbackAndThen(
                 function (data)
                 {
                   if (data.refresh)
                     window.location.reload(); // bijvoorbeeld als kosten vervallen
                 }),
                 "json");
        }

        // Onchange kostenveldje
        function updateKosten(veld, millisec)
        {
          anyChange = true;
          var tr = $(veld).closest("tr")[0]
          if (veld.type=="checkbox")
            var kosten = veld.checked? 1 : 0;
          else
          {
            if (0&&!sanitizeInteger(veld))
            {
              veld.focus();
              veld.select();
              return false;
            }
            var kosten = parseInt(veld.value, 10);
          }
          var kosten_key = parseInt(tr.getAttribute("kosten_key"), 10);

          var data = { mld_opdruren_key: veld.getAttribute("ukey"),
                       kosten_key: kosten_key,
                       kosten: kosten
                     };
          <% protectRequest.dataToken("data"); %>
          $.post("opdr_edit_urenkosten_save.asp?urole=<%=urole%>",
                 data,
                 FcltCallback,
                 "json");
        }

        // klaar met urenbriefje voor deze week
        function weekDone(goedkeuren)
        {
            var params = {};
            var alleen_afgelopen_maand = (goedkeuren && <%=(nieuwe_maand?1:0)%>==1);
            if (alleen_afgelopen_maand)
            {   // We voegen nog een checkbox toe in de confirm.
                params = { ishtmlsafe: true};
                var mytext = "<%=L("lcl_mlduren_approve")%> ?<br>"
                           + "<input type='checkbox' id='laatstemaand' name='laatstemaand' checked  >"
                           + "<%=L('lcl_mld_opdr_hours_approve_monthly')%>"
            }
            else
            {
                var mytext = (goedkeuren ? "<%=L("lcl_mlduren_approve")%>" : "<%=L("lcl_mlduren_close")%>") + "?";
            }

            FcltMgr.confirm( mytext
                           , params
                           , function(e)
                             {
                                var data = { prs_key: <%=prs_key%>
                                           , datum: <%=datefrom.getTime()%>
                                           , done: (goedkeuren? "3" : "2")
                                           };
                                if (alleen_afgelopen_maand)
                                {   // Is de checkbox in de confirm aangevinkt.
                                    data.permaand = ($("#laatstemaand", $(e)).is(":checked") ? 1 : 0);
                                }
                                <% protectRequest.dataToken("data"); %>
                                $.post( "opdr_edit_uren_save.asp?urole=<%=urole%>"
                                      , data
                                      , FcltCallbackAndThen(function(data)
                                            {
                                                FcltMgr.closeDetail(window, { refresh: true });
                                            })
                                      , "json");
                             });
        }

        function moveWeek(weeks) {
<%        var transitParam = buildTransitParam(["urole", "opdr_key", "mld_key", "prs_key", "collegas", "improd", "recentpastdays"]); %>
          window.location.href = "?datefrom=" + (<%=datefrom.getTime()%> + weeks * <%=oneWeek%>) + "<%=transitParam%>";
        }

        function editRemarkCallback(data, img, millisec)
        {
          if (data.success)
          { // Bijhouden of het inputveldje nu een opmerking heeft.
            $(img).find("i").removeClass("fal fas")
                            .addClass((data.remark == "" ? "fal" : "fas"));
            var ititle = data.remark == ""? "" : (data.remark.length > 50?data.remark.substr(0, 50) + "..." : data.remark);
            $(img).attr("title", ititle);

            // Vind het inputveld jquery object.
            var inputfield = $("input", $(img).closest("tr"))[0]; // <table><tr><td> <input><i> </i></td></tr></table>
            updateDag(inputfield, millisec, data.remark)
          }
          else
          {
            FcltMgr.alert(data.remark);
            window.location.reload(); // Pagina laat oude data zien. Pagina opnieuw laden.
          }
        }

        function edit_remark(img, millisec, remark_editable)
        {
          var inputveld = $("input", $(img).closest("tr"))[0]; // <table><tr><td> <input><i> </i></td></tr></table>
          var tr = $(inputveld).closest("table").closest("tr")[0]; // <table><tr> <td>opdrachtnr</td> <td>omschrijving</td> <td><table><tr><td> <input><i> </i> </td></tr></table> <td>...</td> ... <td>Restant</td></tr></table>

          var mld_opdr_key = -1;
          var mld_impropdr_key = -1;
          if (tr.id.substr(0,1) == "O")
              mld_opdr_key = parseInt(tr.id.substr(1));
          else
              mld_impropdr_key = parseInt(tr.id.substr(1));


          var url = "../mld/opdr_uren_remark.asp?prs_key=<%=prs_key%>"
                  + "&datum=" + millisec
                  + "&mld_opdr_key=" + mld_opdr_key
                  + "&mld_impropdr_key=" + mld_impropdr_key
                  + "&rem_edit=" + (remark_editable?0:1);
          FcltMgr.openModalDetail(url,
                                  L("lcl_remark"),
                                  { callback: function(data, text)
                                              {
                                                editRemarkCallback(data, img, millisec)
                                              }
                                  });
        }

        var timerID = null;
        function delayed(delay, fn)
        {
            if (window.timerID)
                clearTimeout(window.timerID);
            window.timerID = setTimeout(fn, delay);
        }
        function doFilter(deze)
        {
            var deze = $("#autofilter");
            var valThis = deze.val().toLowerCase();
            $('table.fcltblocktab>tbody>tr.mldimpropdruren,tr.colhandler,tr.mldopdruren').each(function(){
                var text = $(this).text().toLowerCase();
                var moretext = ($(this).find("span.rsTruncmore").attr('resttxt')||"").toLowerCase();
                $(this).toggle(text.indexOf(valThis) > -1 || moretext.indexOf(valThis) > -1);
            });
            if (typeof updateTableHeaders === "function")
                updateTableHeaders();
        }

        $(function () {
                        if ($('table.fcltblocktab>tbody>tr').length > 12)
                        {
                            $("#iframerextratitle").before("<input id='autofilter' type='text' placeholder='" + safe.htmlattr(L("lcl_autofilter")) + "'>");
                            $("#autofilter")
                                .click(function (e) {e.stopPropagation()})
                                .keyup(function(e){
                                    if (e.which == 27) {
                                        $("#autofilter").val("");
                                    }
                                    delayed(200, doFilter);
                                });
                        }
                      });
    </script>
  </head>

  <body class="nopin" id="opdruren">
<%
    // -------------------------------------
    // Alle al eerder ingevulde uren ophalen
    // -------------------------------------
    var sql = "SELECT ou.mld_opdr_uren_key"
            + "     , ou.mld_opdr_key"
            + "     , ou.mld_impropdr_key"
            + "     , ou.mld_opdr_uren_datum"
            + "     , ou.mld_opdr_uren_besteed"
            + "     , ou.mld_opdr_uren_status"
            + "     , ou.mld_opdr_uren_opmerking"
            + "     , count(ok.mld_opdruren_kosten_key) hasonkosten"
            + "  FROM mld_opdr_uren ou, mld_opdruren_kosten ok"
            + (mld_key > 0? ", mld_opdr o" : "")
            + " WHERE ou.mld_opdr_uren_datum BETWEEN "+datefrom.toSQL() + " AND " + datefrom.endToSQL() + " + 6"
            + "   AND ou.prs_perslid_key = " + prs_key
            + "   AND ou.mld_opdr_uren_key = ok.mld_opdr_uren_key(+)"
            + (mld_key > 0? " AND ou.mld_opdr_key = o.mld_opdr_key AND o.mld_melding_key = " + mld_key : "")
            + (opdr_key > 0? " AND ou.mld_opdr_key = " + opdr_key : "")
            + " GROUP BY ou.mld_opdr_uren_key"
            + "     , ou.mld_opdr_key"
            + "     , ou.mld_impropdr_key"
            + "     , ou.mld_opdr_uren_datum"
            + "     , ou.mld_opdr_uren_besteed"
            + "     , ou.mld_opdr_uren_status"
            + "     , ou.mld_opdr_uren_opmerking";
    var oRs = Oracle.Execute(sql);
    existingUren = [];
    var opdrkeys = [];
    var anyKlaar = false;
    while (!oRs.Eof)
    {
      anyKlaar = anyKlaar || (oRs("mld_opdr_uren_status").Value>1)
      var ou_opdr_key = oRs("mld_opdr_key").Value;
      var impropdr_key = oRs("mld_impropdr_key").Value;
      var arrKey = ou_opdr_key? ("O" + ou_opdr_key ): ("I" + impropdr_key);
      if (!existingUren[arrKey])
      {
        if (ou_opdr_key>0)
          opdrkeys.push(ou_opdr_key);
        else
          withImprod = true; // zeker tonen
        existingUren[arrKey] = [];
        existingUren[arrKey].hasonkosten = false;
      }
      existingUren[arrKey].hasonkosten = existingUren[arrKey].hasonkosten || oRs("hasonkosten").Value>0;
      existingUren[arrKey] [ new Date(oRs("mld_opdr_uren_datum").Value).getTime() ]
          = { key: oRs("mld_opdr_uren_key").Value,
              besteed: oRs("mld_opdr_uren_besteed").Value,
              status: oRs("mld_opdr_uren_status").Value,
              opmerking: oRs("mld_opdr_uren_opmerking").Value == null? "" : oRs("mld_opdr_uren_opmerking").Value
            };
      oRs.MoveNext;
    }
    oRs.Close()

    var buttons = [];
    if (canWrite && urole=="bo")
      buttons.push({title: L("lcl_mlduren_approve"), icon: "fa-flag-checkered", action:"weekDone(true)"});
    else if (canWrite && !anyKlaar)
      buttons.push({title: L("lcl_mlduren_close"), icon: "fa-flag", action:"weekDone(false)"});
    if (datefrom.getTime() - oneWeek > new Date().getTime() - oneYear) { // Niet verder dan 1 jaar terug
      buttons.push({ icon: "fa-arrow-left", title: L("lcl_previous_week"), action: "moveWeek(-1)" });
    }
    if (datefrom.getTime() + oneWeek < new Date().getTime()) { // Niet in de toekomst
      buttons.push({ icon: "fa-arrow-right", title: L("lcl_next_week"), action: "moveWeek(1)" });
    }
    // Kan geen kwaad en alleen al handig met testen
    buttons.push({ icon: "fa-fclt-refresh", title: L("lcl_refresh"), action: "FcltMgr.reload()" });

    IFRAMER_HEADER(urole == "fe"? L("lcl_menu_mld_uren_fe") : (urole == "fo"? L("lcl_menu_mld_uren_fo") : L("lcl_menu_mld_uren_bo")) + " " + userinfo.naam(), buttons);
%>
      <form name="u2" method="post">
<%
        // mld_opdr_uren_keys bevat een array met { key: opdr_uren_key } van een enkele opdrachtregel
        // full: toon ook de regels waar (nog) geen kosten op geboekt zijn
        function emitOnkosten(mld_opdr_uren_keys, reado, full)
        {
          // Eerst de eerder gemaakte onkosten er bij halen
          var has_kosten_key = []; // kostenkeys waar op geboekt is.
          for (ii in mld_opdr_uren_keys)
          {
            mld_opdr_uren_keys[ii].onkosten = []; // per kosten_key
            var sql = "SELECT mld_kosten_key, mld_opdruren_kosten_besteed"
                    + "  FROM mld_opdruren_kosten"
                    + " WHERE mld_opdr_uren_key = " + mld_opdr_uren_keys[ii].key;
            var oRs = Oracle.Execute(sql);
            while (!oRs.Eof)
            {
              has_kosten_key[oRs("mld_kosten_key").Value] = true;
              mld_opdr_uren_keys[ii].onkosten[oRs("mld_kosten_key").Value] = oRs("mld_opdruren_kosten_besteed").Value;
              oRs.MoveNext;
            }
            oRs.Close();
          }
          // -------------------------------------
          // De echte onkosten regels
          // -------------------------------------
          var sql = "SELECT mld_kosten_key"
                  + "     , "+lcl.xsqla('mld_kosten_omschrijving', 'mld_kosten_key')
                  + "     , "+lcl.xsqla('mld_kosten_eenheid', 'mld_kosten_key')
                  + "     , mld_kosten_type"
                  + "     , TRUNC(mld_kosten_verwijder) mld_kosten_verwijder"
                  + "     , TO_NUMBER(TO_CHAR(mld_kosten_verwijder, 'IW')) week_verwijder"
                  + "     , TO_NUMBER(TO_CHAR(SYSDATE, 'IW')) week_kosten"
                  + "  FROM mld_kosten"
          var oRsk = Oracle.Execute(sql);
          while (!oRsk.Eof)
          {
            var datum_verwijder = oRsk("mld_kosten_verwijder").Value;
            var week_verwijder = oRsk("week_verwijder").Value;
            var week_kosten = oRsk("week_kosten").Value;
            var geldigKostencodeWeek = (datum_verwijder == null ? true : (week_kosten < week_verwijder));
            if (!has_kosten_key[oRsk("mld_kosten_key").Value] && (!full || !geldigKostencodeWeek) )
            {
              oRsk.MoveNext;
              continue;
            }

            %><tr class="mldopdrurenkosten" kosten_key="<%=oRsk("mld_kosten_key").Value%>"><%
            %><td class="colhandler"></td>
            <td></td>
<% if (S("mld_uren_omschrijving") == 3)
   { %>
            <td></td>
<% }
            %><td><%= oRsk("mld_kosten_omschrijving").Value%> (<%=oRsk("mld_kosten_eenheid").Value%>)</td><%
            for (var dag2 = 0; dag2 < 7; dag2++)
            {
              var datum = new Date(datefrom);
              datum.setDate(datefrom.getDate()+dag2);
              datum.setHours(0,0,0,0);
              var dezeCell = mld_opdr_uren_keys[dag2];
              var geldigKostencodeDag = (datum_verwijder == null ? true : (datum < (new Date(datum_verwijder))));
              %><td><%
              if (dezeCell && geldigKostencodeDag) // er zijn uren op deze dag
              {
                var dezeDag = 1;
                switch (oRsk("mld_kosten_type").Value) {
                  case 1: // checkbox
                      %><input type="checkbox"
                               <%= dezeCell.onkosten&&dezeCell.onkosten[oRsk("mld_kosten_key").Value]? "CHECKED " : "" %>
                               <% if (reado) { %>
                               disabled="1"
                               <% } else { %>
                               ukey=<%=dezeCell.key%>
                               onChange="return updateKosten(this, <%=datum.getTime()%>)"
                               <% } %>
                            >
                       <%
                      break;
                  case 2: // inputbox
                      %><input type="text" class="fld fld_tiny fldmldkosten"
                               value="<%= dezeCell.onkosten? dezeCell.onkosten[oRsk("mld_kosten_key").Value] : "" %>"
                               <% if (reado) { %>
                               disabled="1"
                               <% } else { %>
                               ukey=<%=dezeCell.key%>
                               onFocus="this.select()"
                               onChange="return updateKosten(this, <%=datum.getTime()%>)"
                               <% } %>
                            >
                       <%
                       break;
                }
              }
              %></td><%
            }
            %><td colspan="<%=(urole == "bo"? 5 : 4)%>"></td><%
            %></tr><%
            oRsk.MoveNext;
          }
          oRsk.Close();
        };

        // Alle mld_opdr-achten waar ik op mag boeken
        var sql = "SELECT mld_opdr_key"
                + ",      -1 mld_impropdr_key"
                + ",      mo.mld_melding_key"
                + ",      cnt_contract_key"
                + ",      '' mld_impropdr_code"
                + ",      mo.mld_opdr_uren"
                + ",      mo.mld_opdr_bedrijfopdr_volgnr"
                + ",      1 canonkosten"
                + ",      mo.mld_opdr_einddatum"
                + ",      mo.mld_opdr_omschrijving"
                + ",      mo.mld_uitvoerende_keys"
                + ",      COALESCE(pf.prs_perslid_naam_full, pf2.prs_perslid_naam_full, pb.prs_bedrijf_naam) naam"
                + ",      pf3.prs_perslid_naam_full meldernaam"
                + ",  " + S("prs_dep_string") + " melderafdeling"
                + ",      mo.mld_opdr_datumbegin"
                + ", "+lcl.xsqla('mto.mld_typeopdr_omschrijving', 'mto.mld_typeopdr_key')
                + ",      mto.mld_typeopdr_uren"
                + ",      (SELECT MAX(2) FROM mld_opdr_uren"  // recent eerder gebruikte opdrachten eerst
                +         " WHERE mld_opdr_key = mo.mld_opdr_key"
                +         "   AND prs_perslid_key = " + prs_key
                +         "   AND ROWNUM = 1 "  // soort van exists
                +         "   AND mld_opdr_uren_datum BETWEEN "+ datefrom.endToSQL() +"-"+recentPastDaysInt+" AND "+ datefrom.endToSQL() +"+6) veelgebruikt"
                + "  FROM mld_opdr mo"
                + ",      mld_typeopdr mto"
                + ",      prs_v_perslid_fullnames_all pf"
                + ",      prs_v_perslid_fullnames_all pf2"
                + ",      prs_v_perslid_fullnames_all pf3"
                + ",      prs_perslid p3"
                + ",      prs_v_afdeling d"
                + ",      prs_bedrijf pb"
                + ",      mld_v_uitvoerende u"
                + ",      mld_melding m"
                + " WHERE mo.mld_typeopdr_key = mto.mld_typeopdr_key"
                + "   AND mo.mld_uitvoerende_keys = pf.prs_perslid_key(+)" // Intern bedrijf (BI).
                + "   AND mo.prs_perslid_key= pf2.prs_perslid_key(+)"      // Intern persoon (PI) [Nieuw].
                + "   AND mo.mld_uitvoerende_keys = pb.prs_bedrijf_key(+)" // Extern bedrijf (BE).
                + "   AND mo.mld_uitvoerende_keys = u.mld_uitvoerende_key"
                + "   AND m.prs_perslid_key= pf3.prs_perslid_key(+)"      // Melder
                + "   AND pf3.prs_perslid_key= p3.prs_perslid_key(+)"
                + "   AND p3.prs_afdeling_key = d.prs_afdeling_key(+)"    // Melder (afdeling)
                + "   AND mo.mld_melding_key = m.mld_melding_key"
                + (mld_key > 0? " AND mo.mld_melding_key = " + mld_key : "")
                + (opdr_key > 0? " AND mo.mld_opdr_key = " + opdr_key : "")
                + "   AND mto.mld_typeopdr_uren IN (3, 4, 5)"; // totaal te besteden uren / maximaal aantal uren / uren per week.

        filter = "        mo.mld_opdr_datumbegin <= " + (datefrom.endToSQL() + " + 6")
               + "    AND mo.mld_statusopdr_key IN (4, 5, 6, 8, 9)" // minstens gefiatteerd
               + "    AND COALESCE(fac.gettrackingdate('ORDAFM', mld_opdr_key), "+datefrom.toSQL() + ") >= " + datefrom.toSQL() // hij was *toen* nog niet afgemeld
               + "    AND (mld_opdr_einddatum IS NULL OR TRUNC(mld_opdr_einddatum) >= " + datefrom.toSQL() + ")";

        if (withCollegas)
        { // alle opdrachten van meldingen van vakgroepen waar prs_key als uitvoerende gezet had kunnen worden
             // TODO: Ook ALG_scope van MLDORD meenemen?
            filter += " AND EXISTS ("
                    +  "   SELECT mm.mld_melding_key"
                    +  "     FROM mld_melding mm, mld_stdmelding sm, fac_v_webgebruiker fw, fac_functie ff"
                    +  "    WHERE fw.fac_functie_key = ff.fac_functie_key"
                    +  "      AND ff.fac_functie_code = 'WEB_MLDORD'"
                    +  "      AND mm.mld_stdmelding_key = sm.mld_stdmelding_key"
                    +  "      AND sm.mld_ins_discipline_key = fw.ins_discipline_key"
                    +  "      AND fw.prs_perslid_key = " + prs_key
                    //AND mm.mld_melding_status < 7? Nee, opdracht is leidend
                    +  "      AND mm.mld_melding_key = mo.mld_melding_key)";
        }
        else
        {
            filter += " AND ((u.intern = 1 AND u.type = 'B' AND mo.prs_perslid_key = " + prs_key + ")" // Ben ik de behandelaar als de uitvoerder een Intern Bedrijf (BI) is.
                    + "   OR (mo.mld_uitvoerende_keys = " + prs_key + "))";                            // Ben ik de uitvoerder (Intern Bedrijf (BI), Extern Bedrijf (BE) of Intern Persoon (PI)).
        }
        if (opdrkeys.length)
            filter = "(("+filter+") OR mld_opdr_key IN (" + opdrkeys.join(",") + "))"; //Waar ik in de periode al op geboekt heb?

        sql += " AND (" + filter + ")";

        if (withImprod)
        {
          sql += " UNION ALL "
               + "SELECT -1 mld_opdr_key"
               + ",      mld_impropdr_key"
               + ",      -1 mld_melding_key"
               + ",      -1 cnt_contract_key"
               + ",      mld_impropdr_code"
               + ",      0 mld_opdr_uren"
               + ",      -1 mld_opdr_bedrijfopdr_volgnr"
               + ",      mld_impropdr_onkosten canonkosten"
               + ",      null mld_opdr_einddatum"
               + ", " + lcl.xsqla('mld_impropdr_omschrijving', 'mld_impropdr_key')
               + ", " +  prs_key + " mld_uitvoerende_keys"
               + ",      '' naam"
               + ",      '' meldernaam"
               + ",      '' melderafdeling"
               + ",      null mld_opdr_datumbegin"
               + ",      '' mld_typeopdr_omschrijving"
               + ",      0 mld_typeopdr_uren"
               + ",      0 veelgebruikt"  // onderaan
               + "  FROM mld_impropdr mo,"
               + "       prs_v_perslid_fullnames_all pf"
               + " WHERE pf.prs_perslid_key = " + prs_key
               + "   AND (  (mo.mld_impropdr_verwijder is null) "
               + "       OR (mo.mld_impropdr_verwijder >= " + datefrom.toSQL() + ")"
               + "       )";
        }

        // NULLS LAST zodat improductief etc. zeker achteraan komt
        // was: sql = "SELECT * FROM ("+sql+") ORDER BY veelgebruikt DESC NULLS LAST, naam, mld_melding_key, cnt_contract_key, mld_opdr_bedrijfopdr_volgnr, mld_opdr_omschrijving NULLS LAST"
        // Sorteren op meldingkey is chronologisch op aanmaak. Als je nadenkt zal dat niet vaak wenselijk zijn.
        // Dus eerst recent gebruikte, dan alfabetisch op naam en opdrachtomschrijving
        // In mode 3 is de naam er nu extra bij. Als in 2024 CARE weg is, kunnen we dit herzien, dit is om zo weinig mogelijk impact te hebben
        if (S("mld_uren_omschrijving") == 3)
          sql = "SELECT * FROM ("+sql+") ORDER BY veelgebruikt DESC NULLS LAST, naam, meldernaam, mld_opdr_omschrijving NULLS LAST, mld_melding_key, cnt_contract_key, mld_opdr_bedrijfopdr_volgnr"
        else
          sql = "SELECT * FROM ("+sql+") ORDER BY veelgebruikt DESC NULLS LAST, naam, mld_opdr_omschrijving NULLS LAST, mld_melding_key, cnt_contract_key, mld_opdr_bedrijfopdr_volgnr"
        var oRs = Oracle.Execute(sql);
        var noRecords = oRs.Eof;

        // - Als matchttype de oude "3" is moet er geen kolom "Restant" bijkomen:
        // Voor ATCH moet er niets veranderen (of juist wel zo laten: anders kom je in de problemen
        // als er verschillende opdrachttypes door elkaar staan?)
        // Je weet pas achteraf welke mld_mld_typeopdr_uren er gebruikt zijn.
%>      <table class="fcltblocktab"><thead><tr><th><%=L("lcl_mld_opdr_number")%></th>
                <th class="colhandler"><%=L("lcl_handler")%></th>
<% if (S("mld_uren_omschrijving") == 3)
   { %>
                <th><%=L("lcl_caller")%></th>
<% } %>
                <th><%=L("lcl_descr")%></th>
            <%
                for (var dag=0; dag<7; dag++)
                {
                  var datum = new Date(datefrom);
                  datum.setDate(datefrom.getDate()+dag);
                  datum.setHours(0,0,0,0);
                  %><th><%= datum.getDate() + "<br>" + calendar_names.daysMin[(dag + 1) % 7]%></th><%
                }
                if (heeftOnkosten)
                {
            %>
                <th title="<%=L("lcl_mlduren_onkosten")%>"><%=I("fa-plus-square")%></th>
            <%  }
            %>
                <th><%=L("lcl_total")%></th>
                <th><%=L("lcl_mlduren_planned")%></th>
                <th><%=L("lcl_mlduren_rest")%></th>
            <% if (urole == "bo") { %>
                <th><%=L("lcl_status")%></th>
            <% } %>
             </tr>
        </thead>
<%
        var anyNotSelf = false; // Dan gaan we op het laatst de handlercolom aanzetten
        while (!oRs.Eof)
        {
          var txt = "";
          var ttl = "";
          var oms = "";
          //
          // Bepalen van de gewenste identificatie om uren te kunnen schrijven
          // txt = eerste kolom: opdrachtnummer|contractnummer|improductiefcode
          //      (tweede kolom: naam van de opdrachtnemer)
          // oms = derde kolom:  bepaald door S("mld_uren_omschrijving")
          //       1=melder (care)
          //       2=vakgroep/stdmelding
          //       3=opdrachtomschrijving
          //       4=opdrachttype/aanvrager
          // ttl = tooltip op de omschrijving: de opdrachtomschrijving
          // ttl1= tooltip op het opdrachtnummer: de opdrachtperiode (van-tot)
          //
          if (oRs("mld_melding_key").value > 0)
          {
            txt = oRs("mld_melding_key").value+"/"+oRs("mld_opdr_bedrijfopdr_volgnr").value;
            ttl = oRs("mld_opdr_omschrijving").Value;

            if (S("mld_uren_omschrijving") == 1 || S("mld_uren_omschrijving") == 4)
            {
              if (S("mld_uren_omschrijving") == 1)
                oms = oRs("meldernaam").Value;
              else  // 4
                oms = oRs("mld_typeopdr_omschrijving").Value + " - " + oRs("meldernaam").Value;
            }
            if (S("mld_uren_omschrijving") == 3 && oRs("mld_opdr_omschrijving").Value) // opdrachtomschrijving
            {
              oms = (oRs("mld_opdr_omschrijving").Value).substring(0, 50) + ((oRs("mld_opdr_omschrijving").Value).length>50?"...":"");
            }
            // ik moet sowieso de prefix hebben, en voor 2 die omschrijvingen
            var tsql = "SELECT sd.ins_srtdiscipline_prefix"
                      + "     , " + lcl.xsqla('d.ins_discipline_omschrijving', 'd.ins_discipline_key')
                      + "     , " + lcl.xsqla('std.mld_stdmelding_omschrijving', 'std.mld_stdmelding_key')
                      + "  FROM ins_srtdiscipline sd"
                      + "     , ins_tab_discipline d"
                      + "     , mld_stdmelding std"
                      + "     , mld_melding m"
                      + " WHERE d.ins_srtdiscipline_key = sd.ins_srtdiscipline_key(+)"
                      + "   AND std.mld_ins_discipline_key = d.ins_discipline_key"
                      + "   AND m.mld_stdmelding_key = std.mld_stdmelding_key"
                      + "   AND m.mld_melding_key = " + oRs("mld_melding_key").value;
            var toRs = Oracle.Execute(tsql);
            var prefix = toRs("ins_srtdiscipline_prefix").Value || "";
            //txt = prefix + txt + (oRs("veelgebruikt").Value > 0 ? "&nbsp;"+I("fa-clock-rotate-left") : "");
            txt = (oRs("veelgebruikt").Value > 0 ? I("fa-clock-rotate-left")+"&nbsp;" : "")+prefix + txt;
            if (S("mld_uren_omschrijving") == 2 || !ttl) // vakgroep/stdmelding
            {
              oms = (toRs("ins_discipline_omschrijving").Value + "/" + toRs("mld_stdmelding_omschrijving").Value).substring(0, 50)
                  + ((toRs("ins_discipline_omschrijving").Value + "/" + toRs("mld_stdmelding_omschrijving").Value).length>50 ? "..." : "");
              ttl = toRs("ins_discipline_omschrijving").Value + "/" + toRs("mld_stdmelding_omschrijving").Value + "\n" + ttl;
            }
            toRs.Close();
          }
          else if (oRs("cnt_contract_key").value > 0)
          {
            txt = "C" + oRs("cnt_contract_key").value + "/" + oRs("mld_opdr_bedrijfopdr_volgnr").value;
            oms = oRs("mld_opdr_omschrijving").Value;
          }
          else // waarschijnlijk improductief
          {
            txt = oRs("mld_impropdr_code").Value;
            oms = oRs("mld_opdr_omschrijving").Value;
          }
          var cls="";
          if (oRs("mld_uitvoerende_keys").Value != user_key)
          {
            cls = "notperfect";
            anyNotSelf |= (oRs("mld_uitvoerende_keys").Value != user_key);
          }
          var ttl1 = L("lcl_from") + ": " + toDateString(oRs("mld_opdr_datumbegin").Value)
                              + " - " + toDateString(oRs("mld_opdr_einddatum").Value);

          var totalBooked = 0;
          if (oRs("mld_opdr_key").Value > 0)
          {
            var exUren = existingUren["O"+oRs("mld_opdr_key").Value] || [];
            var idcode = "O" + oRs("mld_opdr_key").Value;
            cls += " mldopdruren";
            //
            // Totaal bestede uren voor deze week(3) en maximaal geregistreerde uren(4) op deze opdracht
            // Alleen als mld_typeopdr_uren = 3 of 4.
            if (oRs("mld_typeopdr_uren").Value == 3 || oRs("mld_typeopdr_uren").Value == 4)
            {
              var bsql = "SELECT nvl(sum(mld_opdr_uren_besteed),0) tbooked"
                       + "  FROM mld_opdr_uren"
                       + " WHERE (  (mld_opdr_uren_datum < " + datefrom.toSQL() + ")"
                       + "       OR (mld_opdr_uren_datum > " + (datefrom.endToSQL() + " + 6") + "))"
                       + " AND mld_opdr_key = " + oRs("mld_opdr_key").Value
              var tbRs = Oracle.Execute(bsql);
              totalBooked = tbRs("tbooked").value;
              tbRs.close();
            }
          }
          else
          {
            var exUren = existingUren["I" + oRs("mld_impropdr_key").Value] || [];
            var idcode = "I" + oRs("mld_impropdr_key").Value;
            cls += " mldimpropdruren";
          }
          %><tr id="<%=idcode%>" class="<%=cls%>">
                <td title="<%=safe.htmlattr(ttl1)%>"><%= txt %></td>
                <td class="colhandler"><%= safe.html(oRs("naam").Value) %></td>
<% if (S("mld_uren_omschrijving") == 3)
   { %>
                <td title="<%=safe.htmlattr(oRs("melderafdeling").Value)%>"><%= safe.html(oRs("meldernaam").Value) %></td>
<% } %>
                <td title="<%=safe.htmlattr(ttl)%>"><%= safe.html(oms) %></td>
          <%
          minStatus = 9;
          var totaal = 0;
          var mld_opdr_uren_keys = []; // die met onkosten
          // Uren bevriezen indien
          // 1) geen schrijfrechten (hele week)
          // 2) geen BO en 1 dag van de week heeft status > 1 (hele week)
          // 3) status = 4 (dag)
          var reado = (!canWrite || (anyKlaar && urole != "bo")); // deze regel
          for (var dag = 0; dag < 7; dag++)
          {
            var datum = new Date(datefrom);
            datum.setDate(datefrom.getDate()+dag);
            datum.setHours(0,0,0,0);
            var dezeCell = exUren[datum.getTime()] || {};
            if (dezeCell.key && (exUren.hasonkosten || withOnkosten.indexOf(idcode) != -1))
                mld_opdr_uren_keys[dag] = { key: dezeCell.key, onkosten: [] };
            minStatus = Math.min(minStatus, dezeCell.status || 9);
            var dezeDag = dezeCell.besteed || 0;
            totaal += dezeDag;
            // Zorgen dat het type van dezeCell.opmerking altijd een String is (desnoods een lege string).
            dezeCell.opmerking = dezeCell.opmerking? dezeCell.opmerking : "";
            %><td>
               <table><tr><td>
<%               // Als het urenveldje readonly en leeg is dan hoeft er geen inputveld getoond te worden.
                 if ((!reado && dezeCell.status != 4) || dezeDag != 0)
                 { %>
                   <input type="text" class="fld fld_tiny fldmlduren <% if ((reado || dezeCell.status == 4) && dezeCell.opmerking != "") { %> fldmldhasopm <% } %>"
                          value="<%= decimalToHour(dezeDag) %>"
                          <% if (reado || dezeCell.status == 4) { %>
                          readonly="1"
                          <% } else { %>
                          onFocus="this.select()"
                          onChange="return updateDag(this, <%=datum.getTime()%>)"
                          <% } %>
                          <% if ((reado || dezeCell.status == 4) && dezeCell.opmerking != "") { %>
                          title="<%=safe.htmlattr(dezeCell.opmerking)%>"
                          <% } %>
                          <% if (!reado) { %>
                          datum="<%=datum.getTime()%>"
                          <% } %>
                   >
<%               } %>
                 </td>
                 <td>
                 <%
                 var remark_editable = (dezeCell.status == 0 || dezeCell.status == 1 || dezeCell.status == 2);
                 var remark_show = ((dezeCell.status == 3 || dezeCell.status == 4) && dezeCell.opmerking != "");
                 if (remark_editable || remark_show) { %>
                 <span class="details"
                        title="<%=safe.htmlattr(dezeCell.opmerking == ""? "" : (String(dezeCell.opmerking).length > 50? dezeCell.opmerking.substr(0, 50) + "..." : dezeCell.opmerking))%>"
                        style="visibility: <%=dezeDag == 0? "hidden" : "visible"%>; vertical-align: middle;"
                        <%=((dezeCell.status != 4) ? " onclick='edit_remark(this, " + datum.getTime() + "," + remark_editable + ")'" : "")%>
                        >
                    <%=I("fa-comment fa-lg", { fastyle: (dezeCell.opmerking == "" ? "fal" : "fas") } )%>
                 </span>
                 <% } %>
               </td></tr></table>
             </td><%
          }
          // som van de uren
          var restant = oRs("mld_opdr_uren").value - totalBooked - totaal;

          cls="";
          if (oRs("mld_typeopdr_uren").Value == 3 || oRs("mld_typeopdr_uren").Value == 4)
          {
            if (restant.toFixed(2) != (0).toFixed(2))
              cls="afwijk";
          }
          else
          {
            if (totaal.toFixed(2) != (oRs("mld_opdr_uren").value || 0).toFixed(2))
              cls="afwijk";
          }

          if (heeftOnkosten)
          { // onkosten toggle
            if (!reado && oRs("canonkosten").Value)
            {
              %><td title="<%=L("lcl_mlduren_onkosten")%>" onclick="showOnkosten('<%=idcode%>')"><%=I("fa-plus-square")%></td><%
            }
            else
            { %><td></td><%
            }
          }
          %>
            <td><input type="text" id="fldmldurentotal" class="fldmldurentotal <%=cls%>" tabindex="-1" readonly="1" value="<%= decimalToHour(totaal) || 0 %>"></td>
            <td><input type="text" id="fldmldurenplan" tabindex="-1" readonly="1" style="width: 4em;" value="<%= decimalToHour(oRs("mld_opdr_uren").value) || 0 %>"></td>
            <td><input type="text" id="fldmldurenrest"  tabindex="-1" readonly="1" style="width: 4em;" value="<%= decimalToHour(restant) || 0 %>">
                <input type="hidden" id="fldmldurenbooked" value="<%= decimalToHour(totalBooked) || 0 %>">
                <input type="hidden" id="fldopdruren" value="<%=parseInt(oRs("mld_typeopdr_uren").value)%>">
            </td>
          <%
               if (urole == "bo")
               {
                 var stattext = [ L("lcl_mld_uren_status_1"), L("lcl_mld_uren_status_2"), L("lcl_mld_uren_status_3"), L("lcl_mld_uren_status_4")][minStatus-1];
                 %>
                 <td><%= stattext %></td>
            <% } %>
            </tr>
            <%
            // -------------------------------------
            // Onkosten regels alleen als er kosten zijn
            // -------------------------------------
            if (mld_opdr_uren_keys.length)
            {
              emitOnkosten(mld_opdr_uren_keys, reado, withOnkosten.indexOf(idcode) != -1);
            }
            oRs.MoveNext;
        }
        oRs.Close();
        if (S("mld_uren_more") && canWrite && (urole == "bo" || !anyKlaar) && !withCollegas)
        {
          if (noRecords) // showCollegaOpdrachten when there are no records for the selected order
          {
            %><script> $(function() { showCollegaOpdrachten(); }); </script><%
          }
          else
          {
            %><tr><td colspan="10"><div class="weekbrieflimited" onclick="showCollegaOpdrachten()">
               <a><%=L("lcl_mlduren_more")%></a>
              </div></td></tr>
            <%
          }
        }

        if (canWrite && (urole == "bo" || !anyKlaar) && !withImprod)
        {
          %><tr><td colspan="10"><div class="weekbrieflimited" onclick="showImproductief(this)">
             <a><%=L("lcl_mlduren_impr_more")%></a>
            </div></td></tr>
          <%
        } %>

        </table>

<%      if (anyNotSelf)
        { %>
          <script type="text/javascript">
            $(function () {$(".colhandler").show()});
          </script>
<%      }
        IFACE.FORM_END();
%>
    </form>
  </body>
</html>
<% ASPPAGE_END(); %>
