<%
 /*
    $Revision$
    $Id$

    File:               bes.inc
    Description:        bas-module functies

    Context:
    Note:

*/ %>
<%
    bes =
    {
        setbestellingstatus:
           function (bes_key, bes_bestellingstatus_key)
           {
               var sql = "BEGIN bes.setbestellingstatus(" + bes_key + ", " + bes_bestellingstatus_key + ", " + user_key + "); END;"
               Oracle.Execute(sql);
               // Deze zet de status en doet dan bijpassende tracking en notificatie
               // zou leuk zijn om true of false op te leveren naar gelang de status echt anders is geworden
           },
        setbestelopdrstatus:
           function (bes_key, bes_bestelopdrstatus_key)
           {
               var sql = "BEGIN bes.setbestelopdrstatus(" + bes_key + ", " + bes_bestelopdrstatus_key + ", " + user_key + "); END;"
               Oracle.Execute(sql);
               // Deze zet de status en doet dan bijpassende tracking en notificatie
               // zou leuk zijn om true of false op te leveren naar gelang de status echt anders is geworden
           },
        updatebestellingstatus:
           function (bes_key)
           {
               var sql = "BEGIN bes.updatebestellingstatus(" + bes_key + ", " + user_key + "); END;"
               Oracle.Execute(sql);
               // Deze zet de controleert de status van de bestelling op basis van de status van de regels
               // en doet dan ook bijpassende tracking en notificatie
           },
        updatebestelopdrstatus:
           function (besopdr_key)
           {
               var sql = "BEGIN bes.updatebestelopdrstatus(" + besopdr_key + ", " + user_key + "); END;"
               Oracle.Execute(sql);
               // Deze zet de controleert de status van de bestelopdracht op basis van de status van de regels
               // en doet dan ook bijpassende tracking en notificatie
           },

        matchObjectSql:
           function (pins_srtdeel_key, pbestelling_item_key, params)
           { // Matcht bestelde artikelen op objecten die dezelfde kenmerken (srtkenmerk_omschrijving) hebben.
               var sql = "SELECT DISTINCT ins.ins_deel_key"
                       + "     , ins_alg_ruimte_key"
                       + "     , ins_alg_ruimte_type"
                       + "     , bes.bes_waarde"
                       + "     , ins.ins_waarde"
                       + "  FROM (SELECT sd.ins_srtdeel_key"
                       + "             , sk.bes_srtkenmerk_omschrijving"
                       + "             , kbi.bes_kenmerkbesteli_waarde bes_waarde"
                       + "          FROM bes_bestelling_item bi"
                       + "             , bes_srtdeel sd"
                       + "             , bes_srtkenmerk sk"
                       + "             , bes_kenmerk k"
                       + "             , bes_kenmerkbesteli kbi"
                       + "         WHERE bi.bes_bestelling_item_key = kbi.bes_bestelling_item_key(+)"
                       + "           AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                       + "           AND kbi.bes_kenmerk_key = k.bes_kenmerk_key(+)"
                       + "           AND k.bes_srtkenmerk_key = sk.bes_srtkenmerk_key(+)"
                       + "           AND bi.bes_bestelling_item_key IN (" + pbestelling_item_key + ")"
                       + "           AND kbi.bes_kenmerkbesteli_verwijder(+) IS NULL"
                       + "           AND k.bes_kenmerk_verwijder(+) IS NULL"
                       + "           AND k.bes_kenmerk_type(+) = 'I'"
                       + "           AND sk.bes_srtkenmerk_verwijder(+) IS NULL) bes"
                       + "     , (SELECT DISTINCT d.ins_deel_key"
                       + "             , s.ins_srtdeel_key"
                       + "             , d.ins_alg_ruimte_key"
                       + "             , d.ins_alg_ruimte_type"
                       + "             , t.ins_srtkenmerk_omschrijving ins_srtkenmerk_omschrijving"
                       + "             , (SELECT v.ins_kenmerkdeel_waarde"
                       + "                  FROM ins_kenmerkdeel v"
                       + "                 WHERE (v.ins_deel_key = d.ins_deel_key"
                       + "                    AND k.ins_kenmerk_bewerkniveau = 'D'"
                       + "                     OR v.ins_deel_key IN (" + pins_srtdeel_key + ")"
                       + "                    AND k.ins_kenmerk_bewerkniveau = 'S')"
                       + "                   AND v.ins_kenmerk_key = k.ins_kenmerk_key"
                       + "                   AND ins_kenmerkdeel_verwijder IS NULL) ins_waarde"
                       + "          FROM ins_deel d"
                       + "             , ins_srtkenmerk t"
                       + "             , ins_kenmerk k"
                       + "             , ins_srtdeel s"
                       + "             , ins_srtgroep g"
                       + "         WHERE s.ins_srtdeel_key = d.ins_srtdeel_key"
                       + "           AND k.ins_srtkenmerk_key = t.ins_srtkenmerk_key"
                       + "           AND g.ins_srtgroep_key = s.ins_srtgroep_key"
                       + "           AND k.ins_kenmerk_verwijder IS NULL"
                       + "           AND t.ins_srtkenmerk_verwijder IS NULL"
                       + "           AND s.ins_srtdeel_key IN (" + pins_srtdeel_key + ")"
                       + "           AND ((k.ins_srtinstallatie_key = s.ins_srtdeel_key"
                       + "             AND k.ins_kenmerk_niveau = 'S')"
                       + "             OR (k.ins_srtinstallatie_key = s.ins_srtgroep_key"
                       + "             AND k.ins_kenmerk_niveau = 'G')"
                       + "             OR (k.ins_srtinstallatie_key = g.ins_discipline_key"
                       + "             AND k.ins_kenmerk_niveau = 'D'))"
                       + (params.retour
                         ? "           AND d.ins_alg_ruimte_key_org IS NOT NULL AND d.ins_alg_ruimte_type_org IS NOT NULL" // Alleen objecten die in gebruik zijn.
                           + " AND d.bes_bestelopdr_key = " + params.bestelopdr_key
                         : "           AND d.ins_alg_ruimte_key_org IS NULL AND d.ins_alg_ruimte_type_org IS NULL")        // Alleen vrije objecten.
                       + "       ) ins"
                       + " WHERE bes.ins_srtdeel_key = ins.ins_srtdeel_key"
                       + "   AND bes.bes_srtkenmerk_omschrijving = ins.ins_srtkenmerk_omschrijving"
                       + " ORDER BY ins_deel_key"
             return sql;
           },


        getMatchObjectsSql:
           function (pins_srtdeel_key, pbestelling_item_key, params)
           { // Matcht bestelde artikelen op objecten.
             // Geeft een query terug met alle objecten die behoren onder de objectsoort die is gekoppeld aan het bestelde artikel.
             // Als er bij het bestelde artikel kenmerkwaarden zijn ingevuld van kenmerken die gelijk zijn aan kenmerken van het object (dezelfde srtkenmerk_omschrijving)
             // dan moeten deze waarden ook overeenkomen.

             // Zijn er ingevulde artikel kenmerken die overeen moeten komen met gelijke kenmerken bij het object? Waarden zijn nog niet van belang.
             var sql_match = "SELECT COUNT(DISTINCT ins_deel_key) aantal"
                           + "  FROM (" + bes.matchObjectSql(pins_srtdeel_key, pbestelling_item_key, params) + ")";
             var oRs_match = Oracle.Execute(sql_match);
             var domatch = oRs_match("aantal").Value > 0;
             oRs_match.Close()

             if (domatch)
             {
               var sql_freeobj = "SELECT "
                               + (params.getcount
                                 ? "     COUNT(DISTINCT ins_deel_key) aantal"
                                 : "     DISTINCT ins_deel_key"
                                   + " , ins_alg_ruimte_key"
                                   + " , ins_alg_ruimte_type")
                               + "  FROM (" + bes.matchObjectSql(pins_srtdeel_key, pbestelling_item_key, params) + ")"
                               + " WHERE bes_waarde = ins_waarde";
             }
             else
             { // Alle objecten van de objectsoort die gekoppeld is aan het bestelde artikel zijn ok.
               var sql_freeobj = "SELECT "
                               + (params.getcount
                                 ? "     COUNT(DISTINCT d.ins_deel_key) aantal"
                                 : "     DISTINCT d.ins_deel_key"
                                   + " , d.ins_alg_ruimte_key"
                                   + " , d.ins_alg_ruimte_type")
                               + "  FROM ins_deel d"
                               + "     , ins_srtdeel s"
                               + " WHERE s.ins_srtdeel_key = d.ins_srtdeel_key"
                               + "   AND s.ins_srtdeel_key IN (" + pins_srtdeel_key + ")"
                               + (params.retour
                                 ? " AND d.ins_alg_ruimte_key_org IS NOT NULL AND d.ins_alg_ruimte_type_org IS NOT NULL" // Alleen objecten die in gebruik zijn.
                                   + " AND d.bes_bestelopdr_key = " + params.bestelopdr_key
                                 : " AND d.ins_alg_ruimte_key_org IS NULL AND d.ins_alg_ruimte_type_org IS NULL");       // Alleen vrije objecten.
             }

             return sql_freeobj;
           },

        createattachdisconnectObjects:
           function (popdr_key, pbestelopdr_item_key, paantalontv)
           { // Aanmaken (Create), koppelen (Attach) of loskoppelen (Disconnect) van objecten aan of van de bestelopdracht (per bestelopdrachtregel).
             if (isNaN(paantalontv) || paantalontv == 0) return;

             // Eerst instelling gegevens ophalen.
             sql = "SELECT bi.bes_bestelling_item_key"
                 + "     , bdp.bes_disc_params_ins_mode"
                 + "     , s.ins_srtdeel_key"
                 + "     , bes.prs_perslid_key_voor"
                 + "     , BITAND(sd.ins_srtdeel_binding, 8) afd_binding"
                 + "     , BITAND(sd.ins_srtdeel_binding, 16) prs_binding"
                 + "     , CASE"
                 + "       WHEN bes.bes_bestelling_retourvan_key IS NOT NULL"
                 + "       THEN 1"
                 + "       ELSE 0"
                 + "       END isRetour"
                 + "     , bes.bes_bestelling_retourvan_key"
                 + "  FROM bes_bestelopdr b"
                 + "     , bes_bestelopdr_item boi"
                 + "     , bes_bestelling_item bi"
                 + "     , bes_bestelling bes"
                 + "     , bes_srtdeel s"
                 + "     , bes_srtgroep g"
                 + "     , bes_v_aanwezigdiscipline d"
                 + "     , bes_disc_params bdp"
                 + "     , ins_srtdeel sd"
                 + " WHERE b.bes_bestelopdr_key = boi.bes_bestelopdr_key"
                 + "   AND boi.bes_bestelopdr_item_key = bi.bes_bestelopdr_item_key"
                 + "   AND bi.bes_srtdeel_key = s.bes_srtdeel_key"
                 + "   AND bi.bes_bestelling_key = bes.bes_bestelling_key"
                 + "   AND s.bes_srtgroep_key = g.bes_srtgroep_key"
                 + "   AND g.ins_discipline_key = d.ins_discipline_key"
                 + "   AND d.ins_discipline_key = bdp.bes_ins_discipline_key"
                 + "   AND s.ins_srtdeel_key = sd.ins_srtdeel_key(+)"
                 + "   AND b.bes_bestelopdr_key = " + popdr_key
                 + "   AND boi.bes_bestelopdr_item_key = " + pbestelopdr_item_key;
             var oRsb = Oracle.Execute(sql);

             // Alle artikelen/bestelregels hebben dezelfde discipline en dus dezelfde ins_mode (bes_disc_params_ins_mode).
             var ins_mode = oRsb("bes_disc_params_ins_mode").Value;
             // Als de ins_mode "Niet van toepassing(0)" is, dan zijn we direct klaar.
             if (ins_mode == 0)
             {
                oRsb.Close();  // Ja, voor return de cursor sluiten!
                return;
             }

             var bestelling_item_key = oRsb("bes_bestelling_item_key").Value;
             var ins_mode = oRsb("bes_disc_params_ins_mode").Value;
             var ins_srtdeel_key = oRsb("ins_srtdeel_key").Value || -1;
             var prs_perslid_key_voor = oRsb("prs_perslid_key_voor").Value;
             var afd_binding = oRsb("afd_binding").Value == 8;
             var prs_binding = oRsb("prs_binding").Value == 16;
             var isRetour = oRsb("isRetour").Value == 1;
             var bes_bestelling_retourvan_key = oRsb("bes_bestelling_retourvan_key").Value;
             oRsb.Close();

             if (!isRetour && ins_mode > 0 && ins_srtdeel_key < 0)
               abort_with_warning(L("lcl_bes_notlinkedto_obj_type"));

             var freeobj_params = {retour: isRetour};
             if (isRetour)
             {
               sql_r = "SELECT boi.bes_bestelopdr_key"
                     + "  FROM bes_bestelling_item bi"
                     + "     , bes_bestelopdr_item boi"
                     + " WHERE bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key"
                     + "   AND bi.bes_bestelling_key = " + bes_bestelling_retourvan_key;
               oRs_r = Oracle.Execute(sql_r);
               freeobj_params.bestelopdr_key = oRs_r("bes_bestelopdr_key").Value;
               oRs_r.Close();
             }

             // De scope is vooralsnog alleen de functionaliteit waarbij de objecten al bestaan in FACILITOR (ins_deel records) (DJIN#41674).
             //if (ins_mode == 1 && paantalontv > 0)
             //{ // Aanmaken objecten.
             //  // TODO: Objecten vanuit bestellingen kunnen aanmaken voordat deze objecten worden gekoppeld.
             //}

             // Koppelen van objecten.
             var sql_freeobj = bes.getMatchObjectsSql(ins_srtdeel_key, bestelling_item_key, freeobj_params);
             sql = "SELECT ins_deel_key"
                 + "     , ins_alg_ruimte_key"
                 + "     , ins_alg_ruimte_type"
                 + "  FROM (" + sql_freeobj + ")"
                 + " WHERE ROWNUM <= (" + Math.abs(paantalontv) + ")"
                 + " ORDER BY ins_deel_key"
                 + (isRetour
                   ? " DESC"
                   : "");
             var oRsi = Oracle.Execute(sql);
             while (!oRsi.eof)
             {
               ins_deel_key = oRsi("ins_deel_key").Value;

               if (paantalontv > 0)
               {
                 // Object koppelen.
                 sql = "UPDATE ins_deel"
                     + "   SET ins_alg_ruimte_key_org = " + oRsi("ins_alg_ruimte_key").Value
                     + "     , ins_alg_ruimte_type_org = '" + oRsi("ins_alg_ruimte_type").Value + "'"
                     + "     , ins_alg_ruimte_key = " + (prs_binding? prs_perslid_key_voor : new Perslid(prs_perslid_key_voor).prs_afdeling_key())
                     + "     , ins_alg_ruimte_type = " + (prs_binding? "'P'" : "'A'")
                     + "     , bes_bestelopdr_key = " + popdr_key
                     + " WHERE ins_deel_key = " + ins_deel_key;
               }
               else
               {
                 // Object loskoppelen.
                 sql = "UPDATE ins_deel"
                     + "   SET ins_alg_ruimte_key_org = NULL"
                     + "     , ins_alg_ruimte_type_org = NULL"
                     + "     , ins_alg_ruimte_key = ins_alg_ruimte_key_org"
                     + "     , ins_alg_ruimte_type = ins_alg_ruimte_type_org"
                     + "     , bes_bestelopdr_key = NULL"
                     + " WHERE ins_deel_key = " + ins_deel_key;
               }
               Oracle.Execute(sql);
               oRsi.MoveNext();
             }
             oRsi.Close();
           },
        autoapprovefactuur:
           function (opdr_key)
           { // Zijn er bijbehorende facturen die al zijn ingevoerd met de status "Ingevoerd(2)" die nog geapproved moeten worden?
             sql = "SELECT f.fin_factuur_key"
                 + "  FROM fin_factuur f"
                 + " WHERE f.bes_bestelopdr_key = " + opdr_key
                 + "   AND f.fin_factuur_statuses_key = 2"
                 + "   AND f.fin_factuur_verwijder IS NULL" // Verwijderde facturen niet auto approven (VGLD#60654).
                 + " ORDER BY f.fin_factuur_key";
             var oRs = Oracle.Execute(sql);
             while (!oRs.eof)
             { // Autofiatteer de facturen als dat zo ingesteld is.
               // Functie kijkt zelf of autofiatteren aanstaat.
               sql = "BEGIN fin.autoapprovefactuur(" + oRs("fin_factuur_key").Value + "); END;";
               Oracle.Execute(sql);
               oRs.MoveNext();
             }
             oRs.Close();
           },
        getbesbestellingstatustext:
           function(p)
           {
              var statustekst = "??";
              switch (p) { // grofweg op volgorde timeline
                  case 2: { statustekst = L("lcl_bes_new"); break; }
                  case 3: { statustekst = L("lcl_bes_gefiatteerd"); break; }  // Door kostenplaats (en/of -groep) verantwoordelijke
                  case 4: { statustekst = L("lcl_bes_geaccepteerd"); break; } // Door backoffice (afdeling inkoop)
                  case 5: { statustekst = L("lcl_bes_besteld"); break; }      // Opdrachten zijn aangemaakt
                  case 1: { statustekst = L("lcl_bes_afgewezen"); break; }
                  case 6: { statustekst = L("lcl_bes_geleverd"); break; }
                  case 7: { statustekst = L("lcl_bes_verwerkt"); break; }
                  case 8: { statustekst = L("lcl_bes_is_bescan"); break; }
                  case 9: { statustekst = L("lcl_bes_ontvangen"); break; }
              }
              if (__Logging > 0)
                statustekst += " ("+String(p)+")";
              return statustekst;
           },
        getbesopdrstatustext:
           function(p)
           {
              var statustekst = "??";
              switch (p) { // grofweg op volgorde timeline
                  case 2: { statustekst = L("lcl_bes_ord_new"); break; }           // JGL: niet gebruikt trouwens
                  case 3: { statustekst = L("lcl_bes_ord_inbehandeling"); break; } // JGL: Moet nog verstuurd worden
                  case 5: { statustekst = L("lcl_bes_ord_onbevestigd"); break; }   // JGL: wel verstuurd maar nog 'Ter acceptatie bij de leverancier'
                  case 4: { statustekst = L("lcl_bes_ord_inbestelling"); break; }  // JGL: Leverancier heeft hem bevestigd
                  case 1: { statustekst = L("lcl_bes_ord_afgewezen"); break; }     // Afgewezen door leverancier
                  case 6: { statustekst = L("lcl_bes_ord_geleverd"); break; }
                  case 7: { statustekst = L("lcl_bes_ord_verwerkt"); break; }
                  case 8: { statustekst = L("lcl_bes_ord_geannuleerd"); break; }
              }
              if (__Logging > 0)
                statustekst += " ("+String(p)+")";
              return statustekst;
           },

        trackbestellingaccepteren:
           function (opdr_key, ptxt)
           {
                shared.trackaction('BESACP', opdr_key, ptxt);
           },

        // Alle (BES) informatie van een disciplnie
        disc_info: function _disc_info(disc_key, autfunction)
        {
            var sql = "SELECT " + lcl.xsqla('ins_discipline_omschrijving', 'bd.ins_discipline_key')
                    + "     , bes_disc_params_fiatflow"
                    + "     , bes_disc_params_retour"
                    + "     , bes_disc_params_retour_url"
                    + "     , bes_disc_params_levopm_url"
                    + "     , bes_disc_params_leverdagen"
                    + "     , bes_disc_params_expire_tijd"
                    + "     , bes_disc_params_punchouturl"
                    + "     , bes_disc_params_punch_bedr_key"
                    + "     , bes_disc_params_logo_url"
                    + "     , bes_disc_params_autoacceptrfo"
                    + "     , bes_disc_params_auto_order"
                    + "     , bes_disc_params_min_bedrag"
                    + "     , bes_disc_params_bestellimiet"
                    + "     , bes_disc_params_bestellimiet2"
                    + "     , bes_disc_params_bestellimiet3"
                    + "     , bes_disc_params_bestellimiet4"
                    + "     , bes_disc_params_bestellimiet5"
                    + "     , ins_discipline_kpnverplicht"
                    + "     , bes_disc_params_pgb"
                    + "     , bes_disc_params_herfiat"
                    + "     , bes_disc_params_herfiatpct"
                    + "     , bes_disc_params_herfiatmarge"
                    + "     , (SELECT COUNT(sd.bes_srtdeel_key)"
                    + "          FROM bes_v_aanwezigsrtgroep sg"
                    + "             , bes_v_aanwezigsrtdeel sd"
                    + "         WHERE bd.ins_discipline_key = sg.ins_discipline_key"
                    + "           AND sg.bes_srtgroep_key = sd.bes_srtgroep_key"
                    + "           AND sd.bes_staffeltabel_key IS NOT NULL) staffelgroepitems"
                    + "     , bes_disc_params_maxartikel"
                    + "     , bes_disc_params_kpautorisatie"
                    + "     , bes_disc_params_for_others"
                    + "     , bes_disc_params_fe_confirm"
                    + "     , bes_disc_params_bestelmode"
                    + "     , bes_disc_params_fotomode"
                    + "     , bes_disc_params_hide_cost_fe"
                    + "  FROM bes_discipline bd, bes_disc_params bdp"
                    + " WHERE bd.ins_discipline_key = " + disc_key
                    + "   AND bdp.bes_ins_discipline_key = bd.ins_discipline_key";

            var oRs = Oracle.Execute(sql);
            var result = { disc_key                       : disc_key,
                           discipline_omschrijving        : oRs("ins_discipline_omschrijving").Value,
                           discipline_kpnverplicht        : oRs("ins_discipline_kpnverplicht").Value || 0,
                           disc_params_fiatflow           : oRs("bes_disc_params_fiatflow").Value,
                           disc_params_retour             : oRs("bes_disc_params_retour").Value == '1',
                           disc_params_retour_url         : oRs("bes_disc_params_retour_url").Value,
                           disc_params_levopm_url         : oRs("bes_disc_params_levopm_url").Value,
                           disc_params_leverdagen         : oRs("bes_disc_params_leverdagen").Value || 0,
                           disc_params_expire_tijd        : oRs("bes_disc_params_expire_tijd").Value,
                           disc_params_punchouturl        : oRs("bes_disc_params_punchouturl").Value,
                           disc_params_punch_bedr_key     : oRs("bes_disc_params_punch_bedr_key").Value,
                           disc_params_logo_url           : oRs("bes_disc_params_logo_url").Value,
                           disc_params_autoacceptrfo      : oRs("bes_disc_params_autoacceptrfo").Value,
                           disc_params_auto_order         : oRs("bes_disc_params_auto_order").Value,
                           disc_params_min_bedrag         : oRs("bes_disc_params_min_bedrag").Value,
                           disc_params_bestellimiet       : oRs("bes_disc_params_bestellimiet").Value || 0,
                           disc_params_bestellimiet2      : oRs("bes_disc_params_bestellimiet2").Value || 0,
                           disc_params_bestellimiet3      : oRs("bes_disc_params_bestellimiet3").Value || 0,
                           disc_params_bestellimiet4      : oRs("bes_disc_params_bestellimiet4").Value || 0,
                           disc_params_bestellimiet5      : oRs("bes_disc_params_bestellimiet5").Value || 0,
                           disc_params_pgb                : oRs("bes_disc_params_pgb").Value,
                           disc_params_herfiat            : oRs("bes_disc_params_herfiat").Value || 0,
                           disc_params_herfiatpct         : oRs("bes_disc_params_herfiatpct").Value,
                           disc_params_herfiatmarge       : oRs("bes_disc_params_herfiatmarge").Value,
                           staffelgroepitems              : oRs("staffelgroepitems").Value,
                           maxartikel                     : oRs("bes_disc_params_maxartikel").Value? oRs("bes_disc_params_maxartikel").Value : -1,
                           kpautorisatie                  : oRs("bes_disc_params_kpautorisatie").Value == 1,
                           disc_params_for_others         : oRs("bes_disc_params_for_others").Value == 1,
                           disc_params_fe_confirm         : oRs("bes_disc_params_fe_confirm").Value == 1,
                           disc_params_hide_cost_fe       : oRs("bes_disc_params_hide_cost_fe").Value == 1,
                           bestelmode                     : oRs("bes_disc_params_bestelmode").Value, // 0=ouderwets artikelselector, 1=vrij artikelen, 2=bestellijst
                           fotomode                       : oRs("bes_disc_params_fotomode").Value, // 0=ouderwets bij kiezen, 1=ook in bestellijst
                           isFreeArticle                  : oRs("bes_disc_params_bestelmode").Value == 1,
                           can_concept                    : oRs("bes_disc_params_herfiat").Value > 0 // 5.1.2 functionaliteit
                         }
            oRs.Close();
            if (autfunction)
                result.authparams = user.checkAutorisation(autfunction, true, disc_key);
            return result;
        },

        generateBesInfoBlock: function (bes_bestelling, bes_disc_info, show_leverancier, mode) //edit_leverancier)
        {
          if (bes_bestelling.bes_key == -1)
          {
            BLOCK_START("besInfo" ,L("lcl_mld_new_bestelling"), {icon: "fa-question-square"});
            if (bes_disc_info.disc_params_punchouturl)  // geen opmerking als via punchout
            {
              ROTEXTAREATR("fldtxt", L("lcl_bes_bestelling_lev_opm"), bes_bestelling.lev_opm, {suppressEmpty: true} );
            } else {
              RWTEXTAREATR("lev_opm", "fldtxt", L("lcl_bes_bestelling_lev_opm"), bes_bestelling.lev_opm, { trclass: "lev_opm", html: "rows='3'", maxlength: 320 } );
            }
          }
          else
          {
            BLOCK_START("besInfo" , L("lcl_bes_key") + " " + S("bes_bestelling_prefix") + bes_bestelling.bes_key + (bes_bestelling.parent_key? "*" : ""), {icon: "fa-question-square"});
              if (bes_bestelling.satisfaction)
                  AFIELDTR("fld", L("lcl_res_beoordeling"), "", "", {rating: {score: bes_bestelling.satisfaction, note: bes_bestelling.satisfaction_op} });

              ROFIELDTR("fld", L("lcl_bes_discipline"), bes_disc_info.discipline_omschrijving);
              if (bes_bestelling.prs_bedrijf_key > 0 && show_leverancier)
              {
                    FCLTbedrijfselector("lev_key_ro", // supplier
                                       "sg_lev",
                                      { companyKey: bes_bestelling.prs_bedrijf_key,
                                        label: L("lcl_bes_Supplier"),
                                        filtercode: "",
                                        readonly: true,
                                        moreinfo: true
                                      });
              }

              // Zijn wij een incidentele bestelling via een melding?
              if (bes_bestelling.mld_key != null)
              {
                  var params = { infoPointer: { Url: "appl/mld/mld_melding.asp?urole=" + urole + "&mld_key=" + bes_bestelling.mld_key,
                                                Title: L("lcl_complain") + " " + bes_bestelling.mld_key
                                              }
                               }
                  ROFIELDTR("fld", L("lcl_bes_onbe_call"), bes_bestelling.mld_prefix+bes_bestelling.mld_key, params);
              }

              ROFIELDTR ("fld", L("lcl_date_time"), toDateTimeString(bes_bestelling.rfoDate));
              ROFIELDTR (bes_bestelling.rfoStatus==1 ? 'fld rejected' : 'fld', L("lcl_bes_RFO_status"), bes_bestelling.rfoStatusText);
              ROTEXTAREATR("fldtxt", bes_bestelling.rfoStatus == 1? L("lcl_bes_reject_remark") : L("lcl_bes_remark"), bes_bestelling.rfoOpmerking, {id: "opmerk", html: "rows='8'", suppressEmpty: true});

              var fiat_key = bes_bestelling.bes_bestelling_fiat_user;
              var hasToFiat = ((bes_disc_info.disc_params_fiatflow == 0 && bes_bestelling.rfoStatus == 2) ||
                               (bes_disc_info.disc_params_fiatflow == 1 && bes_bestelling.rfoStatus == 4));
              if (hasToFiat) // (nog) ter fiattering
              {
                // Binnenkort eens uitwerken: deze zijn gelijk (onderscheid zou al eerder gemaakt moeten zijn
                // door de fiat_key uit te sluiten van nieuwe fiatteurs). Komt met 5.1.0 nader
                fiat_key = bes_bestelling.fiatteur_key; // Die moet fiatteren
              }
              if (fiat_key)
              {
                    FCLTpersoonselector(
                        "Fiatteur",
                        "sgFiatteur",
                      { perslidKey: fiat_key,
                        label: (hasToFiat? L("lcl_bes_toapprove"):L("lcl_bes_approver")),
                        readonly: true,
                        moreinfo: !frontend
                      });
              }

              var l_orders = [];
              var l_orders_key = [];
              sql_boi = "(SELECT bo.bes_bestelopdr_id, " +
                        "        bes_bestelopdr_status, " +
                        "        bes_bestelopdr_item_key, " +
                        "        bo.bes_bestelopdr_key " +
                        "   FROM BES_BESTELOPDR_ITEM boi, " +
                        "        BES_BESTELOPDR bo " +
                        "  WHERE bo.BES_BESTELOPDR_key = boi.BES_BESTELOPDR_key " +
                        "  GROUP BY bo.bes_bestelopdr_id, bes_bestelopdr_status, bes_bestelopdr_item_key, bo.bes_bestelopdr_key)";
              // Door welke bestelopdracht(en) wordt deze aanvraag afgehandeld?
              sql = "SELECT DISTINCT boi.bes_bestelopdr_id"
                  + "     , boi.bes_bestelopdr_status"
                  + "     , boi.bes_bestelopdr_key"
                  + "  FROM bes_bestelling_item bi"
                  + "     , " + sql_boi + " boi"
                  + " WHERE bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key"
                  + "   AND bi.bes_bestelling_key =" + bes_bestelling.bes_key
                  + " ORDER BY 1";
              oRs = Oracle.Execute(sql);
              while(!oRs.eof)
              {
                var txt = S("bes_bestelopdr_prefix") + oRs("bes_bestelopdr_id").Value;
                if (oRs("bes_bestelopdr_status").Value == 1) // afgewezen
                    txt += " (" + bes.getbesopdrstatustext(oRs("bes_bestelopdr_status").Value) + ")";
                if (bes_bestelling.parent_key)
                    txt += "*"; // wij zijn een change dus de opdracht ook
                l_orders.push(txt);
                l_orders_key.push(oRs("bes_bestelopdr_key").Value);
                oRs.MoveNext();
              }
              oRs.Close();

              // Bestelling opdrachten. Dat kunnen er in de praktijd meerdere zijn.
              if (l_orders_key.length > 0)
              {
%>              <tr>
                  <td class="label"><label><%=L("lcl_bes_orders")%></label></td>
                  <td> <%
                    for (var i = 0; i < l_orders_key.length; i++)
                    {
                      var params = { infoPointer: { Url: "appl/bes/bes_opdr.asp?urole=" + urole + "&ordernr=" + l_orders_key[i] },
                                                    //xTitle: L("lcl_bes_bestelling") + " " + bes_bestelling.rfoRetourVan,
                                     suppressEmpty: true };
                      ROFIELD ("fld", null, l_orders[i],  params);
                      if (i < (l_orders_key.length - 1))
                      {
%>                      <br><%
                      }
                    }
%>                </td> <%
%>              </tr> <%
              }

              // Origineel weergeven indien aanwezig
              if (bes_bestelling.parent_key)
              {
                params = { infoPointer: { Url: "appl/bes/bes_bestelling.asp?urole=" + urole + "&bes_key=" + bes_bestelling.parent_key,
                           Title: L("lcl_bes_bestelling") + " " + S("bes_bestelling_prefix") + bes_bestelling.parent_key,
                           suppressEmpty: true }}
                ROFIELDTR ("fld", L("lcl_bes_origineel"), S("bes_bestelling_prefix") + bes_bestelling.parent_key,  params);
              }
              // Huidige wijziging weergeven indien aanwezig
              if (bes_bestelling.change_key)
              {
                params = { infoPointer: { Url: "appl/bes/bes_bestelling.asp?urole=" + urole + "&bes_key=" + bes_bestelling.change_key,
                           Title: L("lcl_bes_bestelling") + " " + S("bes_bestelling_prefix") + bes_bestelling.change_key,
                           suppressEmpty: true }}
                ROFIELDTR ("fld", L("lcl_bes_change"), S("bes_bestelling_prefix") + bes_bestelling.change_key +"*",  params);
              }

              // Waar worden we door geretourneerd?
              l_retours = [];
              l_retourk = [];
              sql = "SELECT bes_bestelling_key"
                  + "  FROM bes_bestelling"
                  + " WHERE bes_bestelling_retourvan_key = " + bes_bestelling.bes_key
                  + " ORDER BY bes_bestelling_key";
              oRs = Oracle.Execute(sql);
              while(!oRs.eof) {
                l_retours.push(S("bes_bestelling_prefix") + oRs("bes_bestelling_key").Value);
                l_retourk.push(oRs("bes_bestelling_key").Value);
                oRs.MoveNext();
              }
              oRs.Close();

              if (l_retours.length) {
                  var params = {};
                  if (l_retourk.length == 1)
                  {
                    params = { infoPointer: { Url: "appl/bes/bes_bestelling.asp?urole=" + urole + "&bes_key=" + l_retourk[0],
                                              Title: L("lcl_bes_bestelling") + " " + l_retours[0]
                                            }
                             }
                  }
                  ROFIELDTR ("fld rejected", L("lcl_bes_retour_nr"), l_retours.join(","), params);
              }

              // Waar zijn we een retour van?
              if (bes_bestelling.rfoRetourVan != null)
              {
                var params = { infoPointer: { Url: "appl/bes/bes_bestelling.asp?urole=" + urole + "&bes_key=" + bes_bestelling.rfoRetourVan,
                                              Title: L("lcl_bes_bestelling") + " " + bes_bestelling.rfoRetourVan
                                            }
                             }
                ROFIELDTR ("rejected", L("lcl_bes_retour_of"), S("bes_bestelling_prefix") + bes_bestelling.rfoRetourVan, params);
              }

              // MGE: l_orders_key is in de praktijk nu nog altijd 1 key
              if (l_orders_key.length >0) {
                  sql = "SELECT c.cnt_contract_key"
                      + "  FROM cnt_contract c"
                      + " WHERE c.bes_bestelopdr_key IN (" + l_orders_key.join(",") + ")";
                  oRs = Oracle.Execute(sql);
                  if (!oRs.eof)
                  {
                    var params = { infoPointer: { Url: "appl/cnt/cnt_contract.asp?urole=" + urole + "&cnt_key=" + oRs("cnt_contract_key").Value,
                                   Title: L("lcl_contract") + " " + S("bes_bestelling_prefix") + bes_bestelling.bes_key,
                                   suppressEmpty: true }}
                    ROFIELDTR ("fld", L("lcl_contract"), S("bes_bestelling_prefix") + bes_bestelling.bes_key,  params);
                  }
                  oRs.Close();
              }

              if (mode == "RW")
                RWTEXTAREATR("lev_opm", "fldtxt", L("lcl_bes_bestelling_lev_opm"), bes_bestelling.lev_opm, { trclass: "lev_opm", html: "rows='3'", maxlength: 320 });
              else
                ROTEXTAREATR("fldtxt", L("lcl_bes_bestelling_lev_opm"), bes_bestelling.lev_opm, {suppressEmpty: true} );
            }
            BLOCK_END();
        },

        bestelling_info: function _bestelling_info(bes_key)
        {
            var srtdeel_arr = [];
            var amount_arr = [];
            var sql = "SELECT bi.bes_srtdeel_key"
                    + "     , bi.bes_bestelling_item_aantal"
                    + "  FROM bes_bestelling_item bi"
                    + " WHERE bi.bes_bestelling_key = " + bes_key;
            var oRs = Oracle.Execute(sql);

            if (oRs.Eof)
                shared.record_not_found("BES: Record not found");

            while(!oRs.eof)
            {
              srtdeel_arr.push(oRs("bes_srtdeel_key").Value);
              amount_arr.push(oRs("bes_bestelling_item_aantal").Value);
              oRs.MoveNext();
            }
            oRs.Close();

            var staffel_info = bes.staffel_info(srtdeel_arr, amount_arr);

            // Get info of existing BES_BESTELLING
            var sql = "SELECT b.bes_bestelling_status"
                    + "     , b.bes_bestelling_datum"
                    + "     , b.prs_perslid_key"
                    + "     , p.prs_perslid_telefoonnr"
                    + "     , b.prs_perslid_key_voor"
                    + "     , p.prs_afdeling_key"
                    + "     , b.prs_kostenplaats_key"
                    + "     , (SELECT " + S("prs_kpn_string")
                    + "          FROM prs_kostenplaats k"
                    + "         WHERE k.prs_kostenplaats_key = b.prs_kostenplaats_key) prs_kostenplaats_omschr"
                    + "     , b.bes_bestelling_plaats"
                    + "     , b.bes_bestelling_status"
                    + "     , b.bes_bestelling_ordernr"
                    + "     , m.mld_adres_naam"
                    + "     , m.mld_adres_key"
                    + "     , b.bes_bestelling_leverdatum"
                    + "     , b.bes_bestelling_retourvan_key"
                    + "     , prs.getfiatteur (b.prs_kostenplaats_key"
                    + "                      , -1"
                    + "                      , " + staffel_info.totaalbedrag
                    + "                      , sg.ins_discipline_key"
                    + "                      , COALESCE(b.bes_bestelling_fiatbedrag, 0)" // Bij een kpg fiatteur moeten we de volgende hebben en niet de laatste, daarom (fiatbedrag >= 0) meegeven.
                    + "                        ) fiatteur_kp_key" // De kostenplaats verantwoordelijke/fiatteur/budgethouder.
                    + "     , kg.prs_perslid_key fiatteur_kpg_key"
                    + "     , kg.prs_kostenplaatsgrp_fiat2_key"
                    + "     , kg.prs_kostenplaatsgrp_fiat3_key"
                    + "     , kg.prs_kostenplaatsgrp_fin_limit1"
                    + "     , kg.prs_kostenplaatsgrp_fin_limit2"
                    + "     , b.bes_bestelling_fiat_user"
                    + "     , b.bes_bestelling_fiatbedrag"
                    + "     , b.bes_bestelling_korting"
                    + "     , b.bes_bestelling_levkosten"
                    + "     , b.mld_melding_key"
                    + "     , b.bes_bestelling_opmerking"
                    + "     , b.bes_bestelling_lev_opm"
                    + "     , b.fac_activiteit_key"
                    + "     , b.bes_bestelling_parentkey"
                    + "     , b.bes_bestelling_satisfaction"
                    + "     , b.bes_bestelling_satisfaction_op"
                    + "     , (SELECT b1.bes_bestelling_key"
                    + "          FROM bes_bestelling b1"
                    + "         WHERE b1.bes_bestelling_parentkey = b.bes_bestelling_key) change_key"
                    + "     , b.bes_bestelling_approved"
                    + "  FROM bes_bestelling b"
                    + "     , prs_perslid p"
                    + "     , mld_adres m"
                    + "     , bes_bestelling_item bi"
                    + "     , bes_srtdeel sd"
                    + "     , bes_srtgroep sg"
                    + "     , prs_kostenplaats k"
                    + "     , prs_kostenplaatsgrp kg"
                    + " WHERE b.bes_bestelling_key = " + bes_key
                    + "   AND p.prs_perslid_key = b.prs_perslid_key"
                    + "   AND m.mld_adres_key(+) = b.mld_adres_key_lev"
                    + "   AND b.bes_bestelling_key = bi.bes_bestelling_key"
                    + "   AND bi.bes_bestelling_item_key = (SELECT MAX(bi2.bes_bestelling_item_key)"
                    + "                                       FROM bes_bestelling_item bi2"
                    + "                                      WHERE bi2.bes_bestelling_key = " + bes_key + ")"
                    + "   AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                    + "   AND sd.bes_srtgroep_key = sg.bes_srtgroep_key"
                    + "   AND b.prs_kostenplaats_key = k.prs_kostenplaats_key(+)" // kostenplaats van de opdracht kan leeg zijn
                    + "   AND k.prs_kostenplaatsgrp_key = kg.prs_kostenplaatsgrp_key(+)";

            var oRs = Oracle.Execute(sql);
            if (oRs.Eof)
                shared.record_not_found("BES: Record not found");

            var bes_bestelling =
            {
                bes_key             : bes_key,
                //rfoStatusText       : oRs("status").Value,
                rfoStatusText       : ((oRs("bes_bestelling_status").Value == 6 && (oRs("bes_bestelling_retourvan_key").Value && oRs("bes_bestelling_retourvan_key").Value > 0))
                                      ? L("lcl_bes_collected")
                                      : bes.getbesbestellingstatustext(oRs("bes_bestelling_status").Value)),
                rfoDate             : new Date(oRs("bes_bestelling_datum").Value),
                kostenplaats_key    : oRs("prs_kostenplaats_key").Value||-1,
                kostenplaats_omschr : oRs("prs_kostenplaats_omschr").Value||"",
                perslid_key         : oRs("prs_perslid_key").Value, // Persoon die de bestelling aanmaakt
                prs_telefoonnr      : oRs("prs_perslid_telefoonnr").Value, // Tel. van de persoon die de bestelling aanmaakt
                afdeling_key        : oRs("prs_afdeling_key").Value, // Afdeling van de persoon die de bestelling aanmaakt
                perslid_key_voor    : oRs("prs_perslid_key_voor").Value, // Aanvrager/invoerder/contactpersoon
                rfoStatus           : oRs("bes_bestelling_status").Value,
                orderNr             : oRs("bes_bestelling_ordernr").Value,
                afleverruimte       : oRs("bes_bestelling_plaats").Value,
                rfoDeliverydate     : new Date(oRs("bes_bestelling_leverdatum").Value),
                rfoRetourVan        : oRs("bes_bestelling_retourvan_key").Value,
                fiatteur_kp_key     : oRs("fiatteur_kp_key").Value || -1,
                fiatteur_kpg_key    : oRs("fiatteur_kpg_key").Value || -1,
                fiatteur2_kpg_key   : oRs("prs_kostenplaatsgrp_fiat2_key").Value || -1,
                fiatteur3_kpg_key   : oRs("prs_kostenplaatsgrp_fiat3_key").Value || -1,
                kpg_fin_limit1      : oRs("prs_kostenplaatsgrp_fin_limit1").Value || S("mld_opdr_kpg_fin_limit1"),
                kpg_fin_limit2      : oRs("prs_kostenplaatsgrp_fin_limit2").Value || S("mld_opdr_kpg_fin_limit2"),
                bes_bestelling_fiat_user : oRs("bes_bestelling_fiat_user").Value, // Degene als laatste heeft gefiatteerd.
                fiatbedrag          : oRs("bes_bestelling_fiatbedrag").Value || 0,
                rfoBesKosten        : oRs("bes_bestelling_korting").Value,
                rfoLevKosten        : oRs("bes_bestelling_levkosten").Value,
                rfoOpmerking        : oRs("bes_bestelling_opmerking").Value,
                lev_opm             : oRs("bes_bestelling_lev_opm").Value,
                mld_adres_naam      : oRs("mld_adres_naam").Value,
                mld_adres_key       : oRs("mld_adres_key").Value,
                fac_activiteit_key  : oRs("fac_activiteit_key").Value? oRs("fac_activiteit_key").Value : -1,
                mld_key             : oRs("mld_melding_key").Value,
                parent_key          : oRs("bes_bestelling_parentkey").Value,
                satisfaction        : oRs("bes_bestelling_satisfaction").Value,
                satisfaction_op     : oRs("bes_bestelling_satisfaction_op").Value,
                change_key          : oRs("change_key").Value,
                approved            : oRs("bes_bestelling_approved").Value? oRs("bes_bestelling_approved").Value : -1
            }
            oRs.close();

            // Kan ik zelf fiatteren?: true:  totaalbedrag <= can_selfapprove
            //                         false  totaalbedrag > can_selfapprove
            // deze mag/hoeft niet meer te fiatteren
            var exclude_fiatter =
                    bes_bestelling.bes_bestelling_fiat_user || (staffel_info.totaalbedrag <= S("can_selfapprove")? -1 : bes_bestelling.perslid_key);

            var totaalbedrag = "(SELECT SUM(i1.bes_bestelling_item_aantal * COALESCE(i1.bes_bestelling_item_prijs, 0))"
                             + "   FROM bes_bestelling_item i1"
                             + "  WHERE i1.bes_bestelling_key = b.bes_bestelling_key)";

            // Deze mag/hoeft niet meer te fiatteren
            var exclude_fiatter = " COALESCE(b.bes_bestelling_fiat_user, "
                                + " CASE"
                                + " WHEN " + totaalbedrag + " <= " + S("can_selfapprove")
                                + " THEN -1"
                                + " ELSE b.prs_perslid_key"
                                + " END)";

            // Nu de info die indirect uit de bestelaanvraag regels afgeleid moet worden
            // Merk op dat het datamodel bestellingen uit meerdere catalogi ondersteund maar
            // de interface niet. Daarom kan hieronder de MAX(bsg.ins_discipline_key) om één record te krijgen
            var sql = "SELECT MAX(bsg.ins_discipline_key) ins_discipline_key"
                    + "     , prs.nextfiatteur(" + bes_key + ", 'BES', " + exclude_fiatter + ") fiatteur_key"
                    + "     , SUM(bi.bes_bestelling_item_aantal * bi.bes_bestelling_item_prijs) totaal"
                    + "     , SUM(bi.bes_bestelling_item_aantalontv) aantalontv"
                    + "     , MAX(bsg.bes_srtgroep_key) bes_srtgroep_key" // Wordt gebruikt tbv. singlegroep en dan is er maar eentje
                    + "     , MAX(bes_disc_params_singlegroep) singlegroep"
                    + "     , MAX ((SELECT ks.prs_kostensoort_btw"
                      + "             FROM prs_kostensoort ks"
                      + "            WHERE ks.prs_kostensoort_key = COALESCE(bsg.prs_kostensoort_key, bd.prs_kostensoort_key))) inclbtw"
                    + "     , MAX(COALESCE(bes_srtdeel_wijzigdagen, 9999)) bes_srtdeel_wijzigdagen"
                    + "     , MAX(COALESCE(bes_srtdeel_annuleerdagen, 9999)) bes_srtdeel_annuleerdagen"
                    + "     , MAX(bdp.bes_disc_params_contract) bes_disc_params_contract"
                    + "     , MAX(bdp.bes_disc_params_deliver_fe) bes_disc_params_deliver_fe"
                    + "     , MIN(bsd.prs_bedrijf_key) prs_bedrijf_key"
                    + "     , COUNT(DISTINCT prs_bedrijf_key) aantal_bedrijf"
                    + "  FROM bes_bestelling b"
                    + "     , bes_bestelling_item bi"
                    + "     , bes_srtdeel bsd"
                    + "     , bes_srtgroep bsg"
                    + "     , bes_discipline bd"
                    + "     , bes_disc_params bdp"
                    + " WHERE bi.bes_srtdeel_key = bsd.bes_srtdeel_key"
                    + "   AND bsd.bes_srtgroep_key = bsg.bes_srtgroep_key"
                    + "   AND bsg.ins_discipline_key = bd.ins_discipline_key"
                    + "   AND bsg.ins_discipline_key = bdp.bes_ins_discipline_key"
                    + "   AND bi.bes_bestelling_key = b.bes_bestelling_key"
                    + "   AND b.bes_bestelling_key = " + bes_bestelling.bes_key
                    + " GROUP BY b.bes_bestelling_fiat_user"
                    + "        , b.bes_bestelling_key"
                    + "        , b.prs_perslid_key"
            oRs = Oracle.Execute(sql);

            if (oRs("ins_discipline_key").Value == null)
                shared.internal_error("BES: no item lines.");

            bes_bestelling.dis_key      = oRs("ins_discipline_key").Value;
            bes_bestelling.fiatteur_key = oRs("fiatteur_key").Value; // De volgende fiatteur. Degene die het moet doen.
            bes_bestelling.srtgroep     = oRs("bes_srtgroep_key").Value;
            bes_bestelling.singlegroep  = oRs("singlegroep").Value == 1;
            bes_bestelling.inclBTW      = oRs("inclBTW").Value || 0;
            bes_bestelling.totaal       = oRs("totaal").Value || 0;
            bes_bestelling.aantalontv   = oRs("aantalontv").Value || 0;
            if (oRs("aantal_bedrijf").Value == 1) // Anders te ingewikkeld
                bes_bestelling.prs_bedrijf_key   = oRs("prs_bedrijf_key").Value;
            bes_bestelling.isAbonnement = oRs("bes_disc_params_contract").Value == 1; // Bij abonnement bestellingen mag er maar 1 bestelregel zijn en is er dus 1 srtgroep.
            bes_bestelling.deliver_fe = oRs("bes_disc_params_deliver_fe").Value == 1;
            // Let op: Als bes_srtdeel_wijzigdagen niet gezet dan wordt bes_bestelling.wijzig_tot
            // ook niet gezet en hebben we oude <5.1.1 gedrag (meestal niet te wijzigen)
            if (oRs("bes_srtdeel_wijzigdagen").Value != 9999)
            {
                bes_bestelling.wijzig_tot = new Date(bes_bestelling.rfoDeliverydate);
                bes_bestelling.wijzig_tot.setDate(bes_bestelling.wijzig_tot.getDate() - oRs("bes_srtdeel_wijzigdagen").Value);
                __Log("Wijzigen tot " + bes_bestelling.wijzig_tot);
            }
            if (oRs("bes_srtdeel_annuleerdagen").Value != 9999)
            {
                bes_bestelling.annuleer_tot = new Date(bes_bestelling.rfoDeliverydate);
                bes_bestelling.annuleer_tot.setDate(bes_bestelling.annuleer_tot.getDate() - oRs("bes_srtdeel_annuleerdagen").Value);
                __Log("Annuleren tot " + bes_bestelling.annuleer_tot);
            }
            oRs.close();

            // Nu de info die indirect uit de bestelopdracht regels afgeleid moet worden
            var sql = "SELECT MAX(bo.bes_bestelopdr_status) bes_bestelopdr_status"
                    + "     , MAX(boi.bes_bestelopdr_item_key) isordered"
                    + "     , MAX(boi.bes_bestelopdr_key) bes_bestelopdr_key"
                    + "      FROM bes_bestelopdr bo"
                    + ",          bes_bestelopdr_item boi"
                    + ",          bes_bestelling_item bi"
                    + "     WHERE bo.bes_bestelopdr_key = boi.bes_bestelopdr_key"
                    + "       AND boi.bes_bestelopdr_item_key = bi.bes_bestelopdr_item_key"
                    + "       AND bi.bes_bestelling_key = " + bes_bestelling.bes_key;
            oRs = Oracle.Execute(sql);
            bes_bestelling.rfoBestelOpdrKey = oRs("bes_bestelopdr_key").Value;
            bes_bestelling.rfoBestelOpdrStatus = oRs("bes_bestelopdr_status").Value||0,
            bes_bestelling.isordered = oRs("isordered").Value||0,
            oRs.close();

            if (bes_bestelling.mld_key)
               bes_bestelling.mld_prefix = shared.mld_prefix(bes_bestelling.mld_key);

            return bes_bestelling;
        },

        bestelopdracht_info: function (opdr_key)
        {
          var bes_key_str = [];
          // Welke bestelaanvragen worden door deze bestelopdracht afgehandeld?
          sql = "SELECT DISTINCT bes_bestelling_key"
              + "  FROM bes_bestelling_item bi"
              + "     , bes_bestelopdr_item boi"
              + " WHERE boi.bes_bestelopdr_item_key = bi.bes_bestelopdr_item_key"
              + "   AND boi.bes_bestelopdr_key = " + opdr_key;
          oRs = Oracle.Execute(sql);
          while (!oRs.eof)
          {
            bes_key_str.push(oRs("bes_bestelling_key").Value);
            oRs.MoveNext();
          }
          oRs.Close();

          // Get info of existing BES_BESTELOPDR
          sql = "SELECT bd.prs_bedrijf_key"
              + "     , bd.prs_bedrijf_naam"
              + "     , " + lcl.xsqla('d.ins_discipline_omschrijving', 'd.ins_discipline_key')
              + "     , " + lcl.xsqla('s.bes_srtdeel_omschrijving', 's.bes_srtdeel_key')
              + "     , " + lcl.xsqla('s.bes_srtdeel_eenheid', 's.bes_srtdeel_key')
              + "     , COALESCE(bes_bestelopdr_item_inkprijs, boi.bes_bestelopdr_item_prijs) item_prijs"
              + "     , boi.bes_bestelopdr_item_aantal"
              + "     , boi.bes_bestelopdr_item_aantalontv"
              + "     , COALESCE(bes_bestelopdr_item_inkprijs, boi.bes_bestelopdr_item_prijs) * boi.bes_bestelopdr_item_aantal prijs"
              + "     , boi.bes_bestelopdr_item_omschrijv"
              + "     , boi.bes_bestelopdr_item_opmerking"
              + "     , boi.bes_bestelopdr_item_key"
              + "     , COALESCE(b.mld_adres_key_lev,-1) mld_adres_key_lev"
              + "     , COALESCE(b.mld_adres_key_fac,-1) mld_adres_key_fac"
              + "     , b.bes_bestelopdr_id"
              + "     , b.bes_bestelopdr_opmerking"
              + "     , b.bes_bestelopdr_key"
              + "     , b.prs_perslid_key"
              + "     , (SELECT bst.bes_bestelling_retourvan_key "
              + "          FROM bes_bestelling bst "
              + "         WHERE bst.bes_bestelling_key = bi.bes_bestelling_key) bes_bestelling_retourvan_key"
              + "     , " + S("prs_pers_string") + " naam"
              + "     , bi.bes_bestelling_item_key"
              + "     , p.prs_perslid_upper"
              + "     , b.bes_bestelopdr_delivery_opmerk"
              + "     , b.bes_bestelopdr_korting"
              + "     , b.bes_bestelopdr_levkosten"
              + "     , b.bes_bestelopdr_flag"
              + "     , bes_bestelopdr_status"
              + "     , (SELECT ks.prs_kostensoort_btw"
              + "          FROM prs_kostensoort ks"
              + "         WHERE ks.prs_kostensoort_key = COALESCE(g.prs_kostensoort_key, d.prs_kostensoort_key)) inclbtw"
              + "     , s.bes_srtdeel_nr"
              + "     , s.bes_srtdeel_notitie"
              + "     , d.ins_discipline_key"
              + "  FROM bes_v_aanwezigdiscipline d"
              + "     , bes_srtgroep g"
              + "     , bes_disc_params bdp"
              + "     , bes_srtdeel s"
              + "     , prs_bedrijf bd"
              + "     , bes_bestelopdr b"
              + "     , bes_bestelling_item bi"
              + "     , bes_bestelopdr_item boi"
              + "     , prs_perslid p"
              + " WHERE d.ins_discipline_key = g.ins_discipline_key"
              + "   AND d.ins_discipline_key = bdp.bes_ins_discipline_key"
              + "   AND g.bes_srtgroep_key = s.bes_srtgroep_key"
              + "   AND s.bes_srtdeel_key = bi.bes_srtdeel_key"
              + "   AND boi.bes_bestelopdr_key = b.bes_bestelopdr_key"
              + "   AND boi.bes_bestelopdr_item_key = bi.bes_bestelopdr_item_key"
              + "   AND b.prs_bedrijf_key = bd.prs_bedrijf_key"
              + "   AND b.prs_perslid_key = p.prs_perslid_key"
              + "   AND b.bes_bestelopdr_key = " + opdr_key
              + " ORDER BY 2, 3, 4";

          var oRs = Oracle.Execute(sql);
          if (oRs.Eof)
              shared.record_not_found("BES: Record not found");

          var bes_bestelopdr =
          {
            opdr_key              : opdr_key,
            bestelopdr_id         : oRs("bes_bestelopdr_id").Value,
            bes_key_str           : bes_key_str,
            prs_bedrijf_key       : oRs("prs_bedrijf_key").Value,
            prs_bedrijf_naam      : oRs("prs_bedrijf_naam").Value,
            mld_adres_key_lev     : oRs("mld_adres_key_lev").Value,
            mld_adres_key_fac     : oRs("mld_adres_key_fac").Value,
            opmerking             : oRs("bes_bestelopdr_opmerking").Value,
            delivery_opmerk       : oRs("bes_bestelopdr_delivery_opmerk").Value,
            inclBTW               : oRs("inclBTW").Value,
            status                : oRs("bes_bestelopdr_status").Value,
            statustxt             : bes.getbesopdrstatustext(oRs("bes_bestelopdr_status").Value),
            prs_perslid_naam      : oRs("naam").Value, // Aangemaakt door
            perslid_key           : oRs("prs_perslid_key").Value,
            dis_key               : oRs("ins_discipline_key").Value,
            korting               : parseFloat((oRs("bes_bestelopdr_korting").Value? oRs("bes_bestelopdr_korting").Value : 0).toFixed(2)),
            levkosten             : parseFloat((oRs("bes_bestelopdr_levkosten").Value? oRs("bes_bestelopdr_levkosten").Value : 0).toFixed(2)),
            flag                  : oRs("bes_bestelopdr_flag").Value
          }
          if(oRs("bes_bestelopdr_status").Value == 6 && oRs("bes_bestelling_retourvan_key").Value > 0)
              bes_bestelopdr.statustxt = L("lcl_bes_collected");

          var totaal = 0;
          bes_bestelopdr.artikel_arr = new Array();
          while (!oRs.eof)
          { // Nu de artikelregels
            var catalogus_omschr = oRs("ins_discipline_omschrijving").Value;
            var omschr = oRs("bes_srtdeel_omschrijving").Value
                       + " (" + S("currency_pref") + safe.curr(oRs("item_prijs").Value)
                       + S("currency_suff") + "/" + (oRs("bes_srtdeel_eenheid").Value || "") + ")"
            var opmerk = oRs("bes_bestelopdr_item_opmerking").Value;
            var aantal = oRs("bes_bestelopdr_item_aantal").Value;
            var aantalontv = oRs("bes_bestelopdr_item_aantalontv").Value || 0;
            var prijs = parseFloat((oRs("prijs").Value? oRs("prijs").Value : 0).toFixed(2));
            var item_key = oRs("bes_bestelopdr_item_key").Value;
            var item_prijs = parseFloat((oRs("item_prijs").Value? oRs("item_prijs").Value : 0).toFixed(2));
            var artikelnr = oRs("bes_srtdeel_nr").Value;
            var bes_item_key = oRs("bes_bestelling_item_key").Value;
            var bes_mag_loc = oRs("bes_srtdeel_notitie").Value;
            var item_flex = [];

            var sql_flex = "SELECT COALESCE (" + lcl.xsql("k.bes_kenmerk_omschrijving", "k.bes_kenmerk_key")
                         + "              ,  " + lcl.xsql("sk.bes_srtkenmerk_omschrijving", "sk.bes_srtkenmerk_key") + ") kenmerk_omschrijving"
                         + ",      sk.bes_srtkenmerk_key"
                         + ",      sk.bes_srtkenmerk_kenmerktype kenmerk_kenmerktype"
                         + ",      ki.bes_kenmerkbesteli_waarde  waarde"
                         + ",      sk.bes_srtkenmerk_systeem     kenmerk_systeem"
                         + ",      k.bes_kenmerk_toonbaar        kenmerk_readonly"
                         + ",      k.bes_kenmerk_uniek           kenmerk_uniek"
                         + ",      r.fac_kenmerkdomein_key"
                         + ",      r.fac_kenmerkdomein_objectnaam"
                         + ",      r.fac_kenmerkdomein_kolomnaam"
                         + ",      r.fac_kenmerkdomein_kolomtxt"
                         + "  FROM bes_kenmerk k "
                         + "     , bes_srtkenmerk sk"
                         + "     , bes_kenmerkbesteli ki"
                         + "     , fac_kenmerkdomein r"
                         + " WHERE k.bes_kenmerk_key = ki.bes_kenmerk_key"
                         + "   AND k.bes_srtkenmerk_key = sk.bes_srtkenmerk_key"
                         + "   AND sk.fac_kenmerkdomein_key  = r.fac_kenmerkdomein_key(+)"
                         + "   AND sk.bes_srtkenmerk_verwijder IS NULL"
                         + "   AND k.bes_kenmerk_verwijder IS NULL"
                         + "   AND k.bes_kenmerk_type = 'I'"
                         + "   AND ki.bes_bestelling_item_key = " + bes_item_key;
            var oRs_flex = Oracle.Execute(sql_flex);
            while (!oRs_flex.eof)
            {
               var flex_omschr = oRs_flex("kenmerk_omschrijving").Value;
               var flex_waarde = oRs_flex("waarde").value;
               var ktype = oRs_flex("kenmerk_kenmerktype").Value;
               if (ktype == "R" || ktype == "S")
               {
                  var sql_val = "SELECT " + oRs_flex("fac_kenmerkdomein_kolomnaam").value
                              + "      ," + oRs_flex("fac_kenmerkdomein_kolomtxt").value + " waarde"
                              + "  FROM " + oRs_flex("fac_kenmerkdomein_objectnaam").value
                              + " WHERE " + oRs_flex("fac_kenmerkdomein_kolomnaam").value + " = " + safe.quoted_sql(flex_waarde);
                  var oRs_val = Oracle.Execute(sql_val);
                  var flex_waarde = oRs_val("waarde").Value;
                  oRs_val.Close();
               }
               item_flex.push({ktype: ktype, knaam: flex_omschr, kwaarde: flex_waarde});
               oRs_flex.MoveNext();
            }
            oRs_flex.Close();

            bes_bestelopdr.artikel_arr.push({ catalogus_omschr: catalogus_omschr,
                                              omschr:           omschr,
                                              aantal:           aantal,
                                              aantalontv:       aantalontv,
                                              prijs:            prijs,
                                              opmerk:           opmerk,
                                              item_key:         item_key,
                                              item_prijs:       item_prijs,
                                              artikelnr:        artikelnr,
                                              bes_item_key:     bes_item_key,
                                              bes_mag_loc:      bes_mag_loc,
                                              flex:             item_flex
                                            });
            totaal += prijs;
            oRs.MoveNext();
          }
          bes_bestelopdr.totaal = totaal;
          oRs.close();

          return bes_bestelopdr;
        },

        func_enabled_bestelling: // Wat mag ik zoal op deze specifieke bestelling?
            function _func_enabled_bestelling(bes_bestelling, params) // bes_bestelling is een bestelling_info hash
            {
              params = params || {};
              var isVerantwoordelijke = user.isCollega(bes_bestelling.fiatteur_key);
              isVerantwoordelijke |= user.isCollega(bes_bestelling.bes_bestelling_fiat_user);

              var bresult = user.func_enabled2("BES",
                                               { ins_discipline_key: bes_bestelling.dis_key,
                                                 alg_key: null,
                                                 prs_key: bes_bestelling.perslid_key,
                                                 checkOptimistic: false, // pessimist
                                                 isOptional: isVerantwoordelijke,  // isVerantwoordelijke dan optional
                                                 knownread: params.knownread
                                               }
                                              );
              bresult.isVerantwoordelijke = isVerantwoordelijke;

              bresult.canReadAny = bresult.canRead("WEB_BESBOF") ||
                                   bresult.canRead("WEB_BESBAC") ||
                                   bresult.canRead("WEB_BESFOF") ||
                                   bresult.canRead("WEB_BESUSE") ||
                                   isVerantwoordelijke;

              // (als alleen) Frontend-rechten-->we controleren nog strenger
              bresult.canReadFEOnly = false;
              if (    bresult.canReadAny
                  && !bresult.canRead("WEB_BESBOF")
                  && !bresult.canRead("WEB_BESBAC")
                  && !bresult.canRead("WEB_BESFOF")
                  && !isVerantwoordelijke
                  )
              {   // frontend controles
                  bresult.canReadFEOnly = true;
                  if (   bes_bestelling.perslid_key_voor != user_key
                      && !user.isCollega(bes_bestelling.perslid_key))
                  {
                      bresult.canReadAny = false; // Legaal bijv. via google-zoekveldje
                  }
              }

              bresult.canReadFOF = bresult.canRead("WEB_BESFOF");
              bresult.canReadBOF = bresult.canRead("WEB_BESBOF");

              var eigenBestelling = user.isCollega(bes_bestelling.perslid_key);
              // Als ik nog voor voor_wijzig // voor_annuleer zit mag de fe vaak nog wel wijzigen/ annuleren
              var voor_annuleer = bes_bestelling.annuleer_tot && bes_bestelling.annuleer_tot > (new Date);
              var voor_wijzig = bes_bestelling.wijzig_tot && bes_bestelling.wijzig_tot > (new Date);

              // Op button niveau
              bresult.canChange   = false; // Wijzig knop tonen
              bresult.canAccept   = false; // BO Accepteren
              bresult.canReject   = false; // BO Afwijzen
              bresult.canSubmit   = false; // Echt bestellen (vaak automatisch), maakt opdracht aan
              bresult.canApprove  = false; // Fiatteren financieel
              bresult.canDelete   = false; // Algemeen verwijderen
              bresult.canFactuur  = false; // Facturen bekijken
              bresult.canConfirm  = false; // FE Bevestigen ontvangst.
              bresult.canDeliver  = false; // Levering
              // TODO: Hoe is retour functie-autorisatie afhankelijk? canWrite("WEB_BESUSE") || canWrite("WEB_BESFOF")?
              var bes_disc_info = bes.disc_info(bes_bestelling.dis_key); // alle discipline informatie
              var _canRetour = (bes_disc_info.disc_params_retour == 1 && bes_bestelling.rfoRetourVan == null) &&
                                (bresult.canWrite("WEB_BESUSE") || bresult.canWrite("WEB_BESFOF"));
              var fiatflow_std = bes_disc_info.disc_params_fiatflow == 0;
              bresult.canRetourURL  = false;  // (Deels) retour via site leverancier
              bresult.canRetourBES  = false;  // (Deels) retour via negatieve levering

              var isPunchout = !bresult.isFreeArticle && bes_disc_info.disc_params_punchouturl;
              bresult.canMainChange = false; // 'Bovenste stuk', voormalig lower_part
              bresult.canItemsChange = false; // Mag ik toevoegen en aantallen verhogen

              var eigenBestelling = user.isCollega(bes_bestelling.perslid_key_voor);
              var fe_confirm = bes_disc_info.disc_params_fe_confirm;
              var isRetour = bes_bestelling.rfoRetourVan != null;
              var canConfirm = !isRetour && fe_confirm && eigenBestelling;

              bresult.isChange = bes_bestelling.parent_key > 0;
              bresult.hasChange = bes_bestelling.change_key > 0;
              if (!bresult.hasChange) // Als de bestelaanvraag een change heeft mag je er niets meer mee.
              {
                // Sinds 5.1.2 is canDelete duaal: 'vroeg' wordt de bestelaanvraag echt verwijderd
                //                                 'laat' wordt er een annuleringsopdrachtaanvraag naar de leverancier gestuurd
                // Verder: FO mag eigenlijk heel lang wijzigen als bes_bestelling.wijzig_tot maar is gezet:
                //         het is aan de leverancier om al dan niet te weigeren
                var t_cost = bes_bestelling.totaal - bes_bestelling.rfoBesKosten + bes_bestelling.rfoLevKosten;
                var bes_approved = bes_bestelling.approved;
                var bestellimiet = bes_disc_info.disc_params_bestellimiet;
                var bestellimiet2 = bes_disc_info.disc_params_bestellimiet2;
                var bestellimiet3 = bes_disc_info.disc_params_bestellimiet3;
                var bestellimiet4 = bes_disc_info.disc_params_bestellimiet4;
                var bestellimiet5 = bes_disc_info.disc_params_bestellimiet5;
                var canAccept      = bresult.canWrite("WEB_BESBOF") &&                                  // Heb ik de rechten om goed te keuren op dit niveau 1?
                                     ((S("bes_approval_all") == 0 && t_cost >= bestellimiet) ||         // Zijn de kosten hoger als de limiet
                                      (S("bes_approval_all") == 1 && t_cost <= bestellimiet2)) &&       // Zijn de kosten onder mijn limiet om volledig goed te keuren
                                     bes_approved <= bestellimiet;                                      // Welke goedkeur? 1, 2, 3, 4 of 5?
                var canAccept2     = bresult.canWrite("WEB_BESGO2") &&
                                     // Setting bes_approval_all is
                                     // 0: Het approved bedrag is eigen bestellimiet of vorige goedkeur niveau rechten heb ik al (dan direct niveau hoger)
                                     // 1: Het approved bedrag is kleiner of gelijk aan eigen bestellimiet
                                     ((S("bes_approval_all") == 0 && t_cost >= bestellimiet2 && (bes_approved == bestellimiet2 || bresult.canAccept)) ||
                                      (S("bes_approval_all") == 1 && t_cost <= bestellimiet3 && bes_approved <= bestellimiet2));
                var canAccept3     = bresult.canWrite("WEB_BESGO3") &&
                                     ((S("bes_approval_all") == 0 && t_cost >= bestellimiet3 && (bes_approved == bestellimiet3 || bresult.canAccept2)) ||
                                      (S("bes_approval_all") == 1 && t_cost <= bestellimiet4 && bes_approved <= bestellimiet3));
                var canAccept4     = bresult.canWrite("WEB_BESGO4") &&
                                     ((S("bes_approval_all") == 0 && t_cost >= bestellimiet4 && (bes_approved == bestellimiet4 || bresult.canAccept3)) ||
                                      (S("bes_approval_all") == 1 && t_cost <= bestellimiet5 && bes_approved <= bestellimiet4));
                var canAccept5     = bresult.canWrite("WEB_BESGO5") &&
                                     ((S("bes_approval_all") == 0 && t_cost >= bestellimiet5 && (bes_approved >= bestellimiet5 || bresult.canAccept4)) ||
                                      (S("bes_approval_all") == 1 && t_cost > bestellimiet5 && bes_approved <= bestellimiet5)) &&
                                     t_cost > bes_approved;
                var canApprove     = (bes_bestelling.bes_bestelling_fiat_user != user_key) && isVerantwoordelijke;
                switch (bes_bestelling.rfoStatus) // (*aanvraag* status)
                {
                    case 1: // Afgewezen/verworpen. Je kunt hem effectie wijzigen en weer opnieuw aanbieden
                            bresult.canDelete     = bresult.canWrite("WEB_BESFOF") ||
                                                    bresult.canWrite("WEB_BESBOF");
                            bresult.canMainChange = eigenBestelling || bresult.canWrite("WEB_BESFOF") || bresult.canWrite("WEB_BESBOF");
                            bresult.canItemsChange = bresult.canMainChange && !isPunchout;
                            break;
                    case 2: // Nieuw, ter fiattering
                            if (fiatflow_std)
                              bresult.canApprove   = canApprove;
                            else
                            {
                              bresult.canAccept    = canAccept;
                              bresult.canAccept2   = canAccept2;
                              bresult.canAccept3   = canAccept3;
                              bresult.canAccept4   = canAccept4;
                              bresult.canAccept5   = canAccept5;
                              bresult.canReject    = bresult.canAccept ||
                                                     bresult.canAccept2 ||
                                                     bresult.canAccept3 ||
                                                     bresult.canAccept4 ||
                                                     bresult.canAccept5;
                            }
                            bresult.canDelete      = bresult.canWrite("WEB_BESBOF") ||
                                                     (bresult.canWrite("WEB_BESFOF") && bes_bestelling.annuleer_tot) ||
                                                     (eigenBestelling && voor_annuleer);
                            bresult.canMainChange  = bresult.canApprove  || //  fiatteur mag ook aanpassen
                                                     bresult.canWrite("WEB_BESBOF") ||
                                                     (bresult.canWrite("WEB_BESFOF") && bes_bestelling.wijzig_tot) ||
                                                     (eigenBestelling && voor_wijzig);
                            bresult.canItemsChange = bresult.canMainChange && !isPunchout;
                            break;
                    case 3: // Gefiatteerd
                            if (fiatflow_std)
                            {
                              bresult.canAccept    = canAccept;
                              bresult.canAccept2   = canAccept2;
                              bresult.canAccept3   = canAccept3;
                              bresult.canAccept4   = canAccept4;
                              bresult.canAccept5   = canAccept5;
                              bresult.canReject    = bresult.canAccept ||
                                                     bresult.canAccept2 ||
                                                     bresult.canAccept3 ||
                                                     bresult.canAccept4 ||
                                                     bresult.canAccept5;
                            }
                            bresult.canDelete      = bresult.canWrite("WEB_BESBOF") ||
                                                     (bresult.canWrite("WEB_BESFOF") && bes_bestelling.annuleer_tot) ||
                                                     (eigenBestelling && voor_annuleer);
                            bresult.canSubmit      = !fiatflow_std && bresult.canWrite("WEB_BESBOF") && !bes_bestelling.isordered;
                            bresult.canRetourURL   = !fiatflow_std && _canRetour && (bes_disc_info.disc_params_retour_url != null); // Zichtbaar indien bestelling naar de leverancier verzonden is.
                            bresult.canMainChange  = (bresult.canWrite("WEB_BESBOF") ||
                                                      (bresult.canWrite("WEB_BESFOF") && bes_bestelling.wijzig_tot) ||
                                                      (eigenBestelling && voor_wijzig))
                                                     && !bresult.isChange; // Change bestelaanvraag kan alleen gewijzigd worden als status = 2
                            bresult.canItemsChange = bresult.canMainChange && !isPunchout;
                            break;
                    case 4: // Geaccepteerd door BO
                            if (!fiatflow_std)
                              bresult.canApprove   = canApprove;
                            bresult.canDelete      = bresult.canWrite("WEB_BESBOF") ||
                                                     (bresult.canWrite("WEB_BESFOF") && bes_bestelling.annuleer_tot) ||
                                                     (eigenBestelling && voor_annuleer);
                            bresult.canSubmit      = fiatflow_std && bresult.canWrite("WEB_BESBOF") && !bes_bestelling.isordered;
                            bresult.canRetourURL   = fiatflow_std && _canRetour && (bes_disc_info.disc_params_retour_url != null); // Zichtbaar indien bestelling naar de leverancier verzonden is.
                            bresult.canMainChange  = (bresult.canWrite("WEB_BESBOF") ||
                                                      (bresult.canWrite("WEB_BESFOF") && bes_bestelling.wijzig_tot) ||
                                                      (eigenBestelling && voor_wijzig)) &&
                                                     !bresult.isChange; // Change bestelaanvraag kan alleen gewijzigd worden als status = 2
                            bresult.canItemsChange = bresult.canMainChange && !isPunchout;
                            break;
                    case 5: // Besteld (lees: opdracht is aangemaakt/ligt bij leverancier)
                            if (bes_bestelling.aantalontv == 0)// Als er artikelen ontvangen zijn houdt het op
                            {
                                bresult.canDelete  = bresult.canWrite("WEB_BESBOF") ||
                                                     (bresult.canWrite("WEB_BESFOF") && bes_bestelling.annuleer_tot) ||
                                                     (eigenBestelling && voor_annuleer);
                                bresult.canDelete &= bes_disc_info.can_concept;
                            }
                            bresult.canRetourURL   = _canRetour && (bes_disc_info.disc_params_retour_url != null);
                            // Als iemand wijzigt zal het een change-opdracht worden!
                            bresult.canMainChange  = (bresult.canWrite("WEB_BESBOF") ||
                                                      (bresult.canWrite("WEB_BESFOF") && bes_bestelling.annuleer_tot) ||
                                                      (eigenBestelling && voor_wijzig)) &&
                                                     !bresult.isChange && // Change bestelaanvraag kan niet meer gewijzigd worden
                                                     bes_disc_info.can_concept;

                            bresult.canItemsChange = bresult.canMainChange && !isPunchout;
                            bresult.canDeliver = (bes_bestelling.rfoBestelOpdrStatus == 4) && eigenBestelling && bes_bestelling.deliver_fe && bresult.canWrite("WEB_BESUSE");
                            break;
                    case 6: // Geleverd (TV)
                            bresult.canMainChange  = bresult.canWrite("WEB_BESFOF")||user.checkAutorisation("WEB_ORDFIN", true); // Bijvoorbeeld kostenplaats te wijzigen
                            bresult.canRetourURL   = _canRetour && (bes_disc_info.disc_params_retour_url != null);
                            bresult.canRetourBES   = _canRetour && !bresult.canRetourURL;
                            bresult.canConfirm     = canConfirm
                            break;
                    case 7: // Verwerkt (AV)
                            break;
                    case 8: // Geannuleerd, sinds 5.1.2 (was: mixed?)
                            break;
                }
                bresult.canChange = bresult.canItemsChange || bresult.canMainChange; // Dan komt de knop
              }

              return bresult;
            },

        func_enabled_bestelopdracht: // Wat mag ik zoal op deze specifieke bestel opdracht?
            function _func_enabled_bestelopdracht(opdr_key) // bes_bestelopdr is een bestelopdr_info hash
            {
              var sql = "SELECT DISTINCT bo.prs_perslid_key bes_opdr_prs_key"
                      + "     , g.ins_discipline_key"
                      + "     , bo.bes_bestelopdr_status"
                      + "     , ma.alg_locatie_key"
                      + "     , bdp.bes_disc_params_fe_confirm"
                      + "     , bdp.bes_disc_params_deliver_fe"
                      + "     , b.prs_perslid_key_voor"
                      + "  FROM bes_bestelopdr bo"
                      + "     , bes_bestelopdr_item boi"
                      + "     , bes_bestelling_item bi"
                      + "     , bes_bestelling b"
                      + "     , bes_srtdeel s"
                      + "     , bes_srtgroep g"
                      + "     , bes_disc_params bdp"
                      + "     , mld_adres ma"
                      + " WHERE bo.bes_bestelopdr_key = boi.bes_bestelopdr_key"
                      + "   AND boi.bes_bestelopdr_item_key = bi.bes_bestelopdr_item_key"
                      + "   AND bi.bes_bestelling_key = b.bes_bestelling_key"
                      + "   AND bi.bes_srtdeel_key = s.bes_srtdeel_key"
                      + "   AND s.bes_srtgroep_key = g.bes_srtgroep_key"
                      + "   AND bo.mld_adres_key_lev = ma.mld_adres_key(+)"
                      + "   AND bdp.bes_ins_discipline_key = g.ins_discipline_key"
                      + "   AND bo.bes_bestelopdr_key = " + opdr_key;

              var oRs = Oracle.Execute(sql);
              var bes_opdr_prs_key = oRs("bes_opdr_prs_key").Value; // De aanmaker van de bestelopdracht.
              var dis_key = oRs("ins_discipline_key").Value;
              var alg_locatie_key = oRs("alg_locatie_key").Value;
              var bestelopdr_status = oRs("bes_bestelopdr_status").Value;
              var disc_params_fe_confirm = oRs("bes_disc_params_fe_confirm").Value;
              var disc_params_fe_deliver = oRs("bes_disc_params_deliver_fe").Value;
              var bestelling_perslid_key_voor = oRs("prs_perslid_key_voor").Value;
              var eigenBestelling = user.isCollega(bestelling_perslid_key_voor);
              oRs.Close();

              var bresult = user.func_enabled2("BES",
                                               { ins_discipline_key: dis_key,
                                                 loc_key: alg_locatie_key,
                                                 prs_key: bes_opdr_prs_key,
                                                 checkOptimistic: false, // pessimist
                                                 isOptional: false
                                               }
                                              );


              bresult.canReadAny = bresult.canRead("WEB_BESBOF") || bresult.canRead("WEB_BESBOR") || bresult.canRead("WEB_BESBAC"); // Bestel opdracht alleen zichtbaar voor backoffice
              bresult.canReadBOF = bresult.canRead("WEB_BESBOF");
              bresult.canReadBOR = bresult.canRead("WEB_BESBOR");
              bresult.canWriteFlags = bresult.canWrite("WEB_BESBOF") || bresult.canWrite("WEB_BESFOF"); // Kan ik flags aanpassen

              // Op button niveau
              bresult.canChange  = false; // Wijzigen
              bresult.canAccept  = false; // Accepteren
              bresult.canReject  = false; // Afwijzen
              bresult.canSend    = false; // Markeer als verzonden
              bresult.canDeliver = false; // Levering

              switch (bestelopdr_status) // Opdracht status
              {
                case 1: // Afgewezen.
                        bresult.canChange  = bresult.canWrite("WEB_BESBOF");
                        break;
                case 2: // Nieuw, niet gebruikt
                        break;
                case 3: // In Behandeling.
                        bresult.canChange  = bresult.canWrite("WEB_BESBOF");
                        bresult.canSend    = bresult.canWrite("WEB_BESBOF");
                        break;
                case 4: // In Bestelling (Bevestigd)
                        bresult.canChange  = bresult.canWrite("WEB_BESBOF");
                        bresult.canDeliver = bresult.canWrite("WEB_BESBOR") // Afvinken goederenontvangst met WEB_BESBOR rechten
                                         || (bresult.canWrite("WEB_BESUSE") && eigenBestelling && disc_params_fe_deliver) ;
                        break;
                case 5: // Ter Bevestiging (Verzonden)
                        bresult.canAccept  = bresult.canWrite("WEB_BESBOF");
                        bresult.canReject  = bresult.canWrite("WEB_BESBOF");
                        break;
                case 6: // Geleverd
                        break;
                case 7: // Verwerkt
                        break;
                case 8: // Geannuleerd
                        break;
              }

              return bresult;
            },

        func_enabled_bestelitem: // Wat mag ik zoal op deze specifieke bestel item?
            function _func_enabled_bestelitem(bes_key, item_key)
            {
                var bresult = {};
                // Controleeer wel de rechten voor een bestaande besteling.
                if (bes_key > -1)
                {
                    var voor_prs_key = user_key;
                    var sql = "SELECT prs_perslid_key_voor"
                            + "  FROM bes_bestelling"
                            + " WHERE bes_bestelling_key = " + bes_key;
                    var oRs = Oracle.Execute(sql);
                    voor_prs_key = oRs("prs_perslid_key_voor").Value;
                    oRs.Close();

                    var sql = "SELECT g.ins_discipline_key"
                            + "  FROM bes_srtdeel d"
                            + "     , bes_srtgroep g"
                            + " WHERE d.bes_srtgroep_key = g.bes_srtgroep_key"
                            + "   AND d.bes_srtdeel_key = " + item_key;
                    var oRs = Oracle.Execute(sql);
                    var disc_key = oRs("ins_discipline_key").Value;
                    oRs.Close();

                    bresult = user.func_enabled2( "BES"
                                                , { ins_discipline_key: disc_key
                                                  , prs_key: voor_prs_key
                                                  , checkOptimistic: false // pessimist
                                                  , isOptional: true
                                                  }
                                                );
                    bresult.canChangeLine = bresult.canWrite("WEB_BESBOF");
                }
                else
                {
                    // Als je bezig bent met een nieuse bestelling dan heb je voldoende rechten.
                    bresult = { canChangeLine: true }
                }
                return bresult;
            },

        staffel_info: function _staffel_info(srtdeel_keys, itemaantal_arr)
        {
            var lsgnaamstring = [];
            var lsgkeystring = [];
            var lsgkortingstring = [];
            var lsgaantalstring = [];
            var lsgeenheidstring = [];
            var litemprijsstring = [];
            var first = true;
            var prs_bedrijf_key;
            var liakorting = 0;
            var subbedrag = 0;
            var subkorting = 0;
            var subtotaal = 0;
            var totaalbedrag = 0;
            var bes_kosten;
            var bes_limiet;

            function StaffelGroep(naam, aantal, eenheid, korting, groep, bestelbedrag)
            {
              this.naam = naam;
              this.aantal = aantal;
              this.eenheid = eenheid;
              this.korting = korting;
              this.groep = groep;
              this.bestelbedrag = bestelbedrag;
            }

            var ItemArray = new Array();
            var staffelGroepArray = new Array();

            // Je hebt eerst totaal aantallen per staffelgroep nodig om korting van een (groeps) artikel te kunnen berekenen.
            for (var i = 0; i < srtdeel_keys.length; i++)
            {
              if (itemaantal_arr[i] == 0) // Bij een bestel_lijst zijn er heel veel met aantal 0
              {
                ItemArray.push({ item_key    : srtdeel_keys[i],
                                 aantal      : itemaantal_arr[i],
                                 prijs       : null,
                                 eenheid     : null,
                                 staffelgroep: null
                                });
                // Maar ik wil wel het bedrijf weten.
                var sql_b = "SELECT sd.prs_bedrijf_key"
                          + "  FROM bes_srtdeel sd"
                          + " WHERE sd.bes_srtdeel_key = " + srtdeel_keys[i];
                var oRs_b = Oracle.Execute(sql_b);
                if (!oRs_b.eof)
                  prs_bedrijf_key = oRs_b("prs_bedrijf_key").Value;
                oRs_b.Close();

                continue;
              }


              sql = "SELECT sd.bes_staffeltabel_key staffelgroep"
                  + ",      bst.bes_staffeltabel_naam staffelgroepnaam"
                  + ",      COALESCE(bes.getsrtdeelprijs(sd.bes_srtdeel_key, NULL) , 0) prijs"
                  + ",      bst.bes_staffeltabel_groep groep"
                  + "," + lcl.xsql('sd.bes_srtdeel_eenheid','sd.bes_srtdeel_key') +" eenheid"
                  + ",      sd.prs_bedrijf_key"
                  + "  FROM bes_srtdeel sd"
                  + ",      bes_staffeltabel bst"
                  + " WHERE sd.bes_staffeltabel_key = bst.bes_staffeltabel_key(+)"
                  + "   AND sd.bes_srtdeel_key = " + srtdeel_keys[i];
              var oRs = Oracle.Execute(sql);
              if (!oRs.eof)
              {
                // Oplaan bedrijf waar alle artikelen worden besteld. Moet voor elke artikel hetzelfde zijn.
                prs_bedrijf_key = oRs("prs_bedrijf_key").Value;
                if (!prs_bedrijf_key)
                    __DoLog("Artikel wordt niet door een bedrijf geleverd.", "#FFFF00")

                // Opslaan van staffelgroep van een item
                ItemArray.push({ item_key    : srtdeel_keys[i],
                                 aantal      : itemaantal_arr[i],
                                 prijs       : oRs("prijs").Value,
                                 eenheid     : oRs("eenheid").Value,
                                 staffelgroep: oRs("staffelgroep").Value
                                });
                // Opslaan van totaalaantallen van een staffelgroep
                if (oRs("staffelgroep").Value)
                {
                  if (staffelGroepArray[oRs("staffelgroep").Value])
                  {
                    staffelGroepArray[oRs("staffelgroep").Value].aantal += itemaantal_arr[i];
                    staffelGroepArray[oRs("staffelgroep").Value].bestelbedrag += (oRs("prijs").Value *  itemaantal_arr[i]);
                  }
                  else
                  {
                    staffelGroepArray[oRs("staffelgroep").Value] =
                            new StaffelGroep(oRs("staffelgroepnaam").Value,
                                              itemaantal_arr[i],
                                              oRs("eenheid").Value,
                                              0,
                                              oRs("groep").Value,
                                              (oRs("prijs").Value *  itemaantal_arr[i], 10))
                  }
                }
              }
              oRs.Close();
            }

            // Nu kunnen we totale kortingen per staffelgroep uitrekenen
            // Daarnaast itemprijsstring opbouwen. Nodig bij het opslaan van de juiste betaalde prijs van een artikel (bes_edit_bestelling_save)
            for (var j in ItemArray)
            {
              if (ItemArray[j] != null && ItemArray[j].item_key && ItemArray[j].staffelgroep != null) // Item moet staffelgroep hebben
              {
                sql = "SELECT BES.calcartikelkortingsprijs(" + ItemArray[j].item_key + ", " + (staffelGroepArray[ItemArray[j].staffelgroep].groep == 1? staffelGroepArray[ItemArray[j].staffelgroep].aantal : ItemArray[j].aantal) + ") kortingsprijs"
                    + " FROM DUAL";
                var oRs = Oracle.Execute(sql);

                if (!oRs.eof)
                {
                  staffelGroepArray[ItemArray[j].staffelgroep].korting += ItemArray[j].aantal * (ItemArray[j].prijs - parseFloat(oRs("kortingsprijs").Value, 10));
                  litemprijsstring.push(oRs("kortingsprijs").Value);
                  first = false;
                }
                oRs.Close();
              }
              else // geen staffelkortingen voor dit artikel. Wel in de itemprijsstring opnemen
              {
                litemprijsstring.push(ItemArray[j].prijs);
                first = false;
              }
              subbedrag += ItemArray[j].aantal * ItemArray[j].prijs;
            }

            // Groepeer staffelgegevens in een string die verzonden kan worden
            first = true;
            for (var sg in staffelGroepArray)
            {
              if (staffelGroepArray[sg] != null && staffelGroepArray[sg].aantal)
              {
                if (staffelGroepArray[sg].groep == 0)
                { // Individuele artikelkorting
                  liakorting +=  parseFloat(staffelGroepArray[sg].korting);
                  subkorting += staffelGroepArray[sg].korting;
                }
                else
                { // Groepskorting
                  lsgnaamstring.push(staffelGroepArray[sg].naam);
                  lsgkeystring.push(sg);
                  lsgkortingstring.push(staffelGroepArray[sg].korting);
                  lsgaantalstring.push(staffelGroepArray[sg].aantal);
                  lsgeenheidstring.push(staffelGroepArray[sg].eenheid);
                  subkorting += staffelGroepArray[sg].korting;
                  first = false;
                }
              }
            }

            // Bereken subtotaal: Bestelbedrag - artikel en groepskoringen
            subtotaal = subbedrag - subkorting;


            // Extra (transport) kosten en onderlimiet bepalen
            sql = "SELECT CASE"
                + " WHEN (prs_bedrijf_bes_limiet - " + subtotaal + ") <= 0" // Subtotaal: Bestelbedrag - alle kortingen
                + " THEN 0"
                + " ELSE COALESCE(prs_bedrijf_bes_kosten, 0)"
                + " END bes_kosten"
                + ", COALESCE(prs_bedrijf_bes_limiet, 0) bes_limiet"
                + " FROM prs_bedrijf"
                + " WHERE prs_bedrijf_key = " + prs_bedrijf_key;
            oRs = Oracle.Execute(sql);
            if (!oRs.eof)
            {
              // Extra (transport) kosten
              bes_kosten = oRs("bes_kosten").Value;
              bes_limiet = oRs("bes_limiet").Value;
            }
            oRs.Close();

            // Totaalbedrag
            totaalbedrag = subtotaal + bes_kosten;

             var result = { sgnaamstring         : lsgnaamstring,
                            sgkeystring          : lsgkeystring,
                            sgkortingstring      : lsgkortingstring,
                            sgaantalstring       : lsgaantalstring,
                            sgeenheidstring      : lsgeenheidstring,
                            itemprijsstring      : litemprijsstring,
                            bes_kosten           : bes_kosten,
                            bes_limiet           : bes_limiet,
                            prs_bedrijf_key      : prs_bedrijf_key,
                            iakorting            : liakorting,
                            totaalbedrag         : totaalbedrag
                         };

            return result;
        },

      // Geeft het PGB overschrijdingsbedrag van de PGB-limiet terug
      get_pgb_exceed_amount: function(bestelbedrag, prs_key, dis_key, bes_key)
      {
        var amount = bestelbedrag; // Indien geen pgblimiet dan gehele bestel bedrag

        // Opvragen PGB limiet
        var pgblimiet = budget.get_pgblimiet(prs_key, dis_key);

        if (pgblimiet != null)
        { // Verschil PGB limiet met het besteed budget van persoon en desbetreffende discipline voor dit jaar inclusief bestelbedrag
          amount = (budget.besteed_budget_pgb(prs_key, dis_key, {bes_key: bes_key}) + bestelbedrag - pgblimiet);
        }
        return amount;
      },

      // Geeft het AGB overschrijdingsbedrag van de AGB-limiet terug
      get_agb_exceed_amount: function(bestelbedrag, kp_key, dis_key, bes_key)
      {
        var amount = bestelbedrag; // Indien geen agblimiet dan gehele bestel bedrag

        // Opvragen AGB limiet
        var agblimiet = budget.get_agblimiet(kp_key, dis_key);

        if (agblimiet != null)
        { // Verschil AGB limiet met het besteed budget van persoon en desbetreffende discipline voor dit jaar inclusief bestelbedrag
          amount = (budget.besteed_budget_agb(kp_key, {bes_key: bes_key}) + bestelbedrag - agblimiet);
        }
        return amount;
      },

      // Persoonlijk Gebonden Budget (PGB) en/of Afdeling Gebonden Budget (AGB) controle
      // bes_disc_info.disc_params_pgb: 0 = Geen van beiden
      //                                1 = Alleen pgb
      //                                2 = Alleen agb
      //                                3 = Beiden, pgb en agb

      // Geeft true als het bestelde bedrag boven de PGB-limiet van prs_key uit komt
      // en dus (eventueel) goedkeuring vereist zal zijn.
      exceeds_pgb: function(bestelbedrag, prs_key, dis_key)
      {
        if (bes_disc_info.disc_params_pgb == 1 || bes_disc_info.disc_params_pgb == 3)
          return budget.exceeds_profiel(bestelbedrag + budget.besteed_budget_pgb(prs_key, dis_key), prs_key, dis_key);
        else // Geen pgb. Dan kan je ook niet boven de pgb zitten
          return false;
      },

      // Geeft true als het bestelde bedrag boven de AGB-limiet van prs_key uit komt
      // en dus (eventueel) goedkeuring vereist zal zijn.
      // Negeer evt bestaand bestelbedrag van bes_key (indien > -1)
      exceeds_agb: function(bestelbedrag, kp_key, dis_key, bes_key)
      {
        if (bes_disc_info.disc_params_pgb == 2 || bes_disc_info.disc_params_pgb == 3)
          return budget.exceeds_limietagb(bestelbedrag + budget.besteed_budget_agb(kp_key, {bes_key: bes_key}), kp_key, dis_key);
        else // Geen agb. Dan kan je ook niet boven de agb zitten
          return false;
      },

      // Moet bij wijzigen van de bestelaanvraag, de bestelaanvraag hergefiatterd worden door de budgethouder of backoffice?
      herfiatteren: function(bes_bestelling, bes_disc_info, nieuwtotaal)
      { // Bepalen wanneer gefiatteerd moet worden:
        // Mutaties als al besteld?: 0=Niet toestaan
        //                           1=Toestaan, herfiatteren zie criteria
        //                           2=Toestaan, herfiatteren als nieuwe (altijd)
        //                           3=Toestaan, herfiatteren niet nodig (nooit)
        if (bes_disc_info.disc_params_herfiat == 0)
          // 5.1.1 gedrag: Altijd als nieuw.
          // Als er nog niets besteld (status 2, 3, 4) is dan altijd herfiatteren, als er al besteld is kan er niet eens gewijzigd worden (geen potloodje).
          return true;
        if (bes_disc_info.disc_params_herfiat == 2)
          return true;
        if (bes_disc_info.disc_params_herfiat == 3)
          return false
        // Alleen als bedrag verhoogd
        if (bes_disc_info.disc_params_herfiatpct > 0) // Herfiattering noodzakelijk indien >%
          return ((nieuwtotaal - bes_bestelling.totaal) / bes_bestelling.totaal)*100 > bes_disc_info.disc_params_herfiatpct;
        else if (bes_disc_info.disc_params_herfiatmarge > 0) // Herfiattering noodzakelijk indien >€
          return (nieuwtotaal - bes_bestelling.totaal) > bes_disc_info.disc_params_herfiatmarge;
        else
          return true;
      },

      checkFiat: function(bes_key, params)
      { // Controleer of de bestelling gefiatteerd moet worden.
        var prs_key = params.prs_key;
        var prs_key_voor = params.prs_key_voor;
        var dis_key = params.dis_key;
        var kp_key = params.kp_key;
        var totaalbedrag = params.totaalbedrag;

        var bes_bestelling = params.bes_bestelling;
        var bes_disc_info = params.bes_disc_info;
        var pgb = bes_disc_info.disc_params_pgb;
        var autoacceptrfo = bes_disc_info.disc_params_autoacceptrfo;

        var isFE = params.isFE;
        var oldStatus = params.oldStatus;
        var act_mode = params.act_mode;
        // Persoonlijk Gebonden Budget (PGB) en/of Afdeling Gebonden Budget (AGB) controle
        // bes_disc_info.disc_params_pgb: 0 = Geen van beiden
        //                                1 = Alleen pgb
        //                                2 = Alleen agb
        //                                3 = Beiden, pgb en agb
        if (pgb > 0)
        { // Persoonlijk Gebonden Budget (PGB) en Afdeling Gebonden Budget (AGB) controle
          // Fiatteringsproces moet gevolgd worden op de naam van
          // S("prs_dep_default_kpn_voor") == 0: de contactpersoon prs_key
          // S("prs_dep_default_kpn_voor") == 1: de "voor wie" (bestelling voor) prs_key_voor
          // Als bes_disc_params_for_others niet is gezet zijn prs_key en prs_key_voor identiek
          var exceeds_pgb = bes.exceeds_pgb(totaalbedrag, (S("prs_dep_default_kpn_voor") == 0? prs_key : prs_key_voor), dis_key)
          var exceeds_agb = bes.exceeds_agb(totaalbedrag, kp_key, dis_key, bes_key)
          if (exceeds_pgb || exceeds_agb)
          {
            if (S("bes_pgb_fiattering") == 1 && !(isFE && S("bes_pgb_fe_fiat") == 1))
              // Algemene fiatterings proces noodzakelijk naast PGB fiatering
              return true;
            else
            { // Fiatteringsproces moet gevolgd worden op de naam van.
              // S("prs_dep_default_kpn_voor") == 0: de contactpersoon prs_key.
              // S("prs_dep_default_kpn_voor") == 1: de "voor wie" (bestelling voor) prs_key_voor.
              // Als bes_disc_params_for_others niet is gezet zijn prs_key en prs_key_voor identiek.
              var strState = (exceeds_pgb
                             ? L("lcl_bes_exceeds_pgb") + safe.curr(bes.get_pgb_exceed_amount(totaalbedrag, (S("prs_dep_default_kpn_voor") == 0? prs_key : prs_key_voor), dis_key, bes_key))
                             : "")
                           + (exceeds_pgb && exceeds_agb
                             ? "\n" // Nieuwe regel.
                             : "")
                           + (exceeds_agb
                             ? L("lcl_bes_exceeds_agb") + safe.curr(bes.get_agb_exceed_amount(totaalbedrag, kp_key, dis_key, bes_key))
                             : "")
                           + "\n" + L("lcl_bes_adjust_order");
              abort_with_warning(strState);
            }
          }
          else if (isFE && S("bes_pgb_fe_fiat") == 1)
          { // Onder PGB/AGB en bestelling van FE en moet zeker langs budgethouder
            return true;
          }
        }
        else
        { // Standaard fiatteringscontrole.
          // Fiatteringsproces moet gevolgd worden op de naam van
          // S("prs_dep_default_kpn_voor") == 0: de contactpersoon prs_key
          // S("prs_dep_default_kpn_voor") == 1: de "voor wie" (bestelling voor) prs_key_voor
          // Als bes_disc_params_for_others niet is gezet zijn prs_key en prs_key_voor identiek.
          // Als orgineel nog gefiatteerd moet worden door budgethouder (status is 2) dan zeker eerst fiatteren.
          // Kan prs_key (aanmaker) zelf fiatteren?: true:  totaalbedrag <= can_selfapprove
          //                                         false  totaalbedrag > can_selfapprove => prs_key als exclude key meegeven.
          if ((!act_mode
              && !autoacceptrfo
              && budget.exceeds_profiel(totaalbedrag, (S("prs_dep_default_kpn_voor") == 0? prs_key : prs_key_voor), dis_key)
              && (bes_key == -1 || oldStatus == 2 || bes.herfiatteren(bes_bestelling, bes_disc_info, totaalbedrag)))
              || totaalbedrag > S("can_selfapprove"))
            // niet automatisch fiat(!)teren en profiel wordt overschreden.
            return true;
        }
        return false;

      },

      // Levert de 'Is ter fiattering aangeboden bij approver' op.
      sendNeedApprovalNotification: function(bes_key, approver)
      {
        if (approver == null)
            return false;

        // These notifications are now sent on behalf of the system, what might be the local FM organisation
        var sql = "SELECT l.alg_locatie_email"  // null as a string
                + " FROM mld_adres ma, alg_locatie l, bes_bestelling b"
                + " WHERE b.mld_adres_key_lev = ma.mld_adres_key"
                + " AND ma.alg_locatie_key = l.alg_locatie_key"
                + " AND b.bes_bestelling_key = " + bes_key;
        var oRs = Oracle.Execute(sql);
        if (!oRs.eof) {
            var lsender = oRs(0).Value;
        } else {
            var lsender = null;
        }
        oRs.Close();
        // notify approver and requestor by message & mail as configured in fac_srtnotificatie with BESAPx
        shared.trackaction("BESAP2", bes_key);

        Oracle.Execute("BEGIN fac.putnotificationsrtprio(NULL, " + approver + ", 'BESAP1', " + bes_key + ", NULL, NULL, NULL, NULL, NULL, 2, " + (lsender ? safe.quoted_sql(lsender) : "NULL") + "); END;");

        sql = "SELECT prs_perslid_naam_full FROM prs_v_perslid_fullnames WHERE prs_perslid_key = " + approver;
        oRs = Oracle.Execute(sql);
        var regApprove_txt = "";
        if (!oRs.eof)
          regApprove_txt = L("lcl_bes_RFO_regApprov") + oRs("prs_perslid_naam_full").Value;
        else
          regApprove_txt = L("lcl_bes_RFO_regApprov");
        oRs.Close();
        return regApprove_txt
      },

      makeOrders: function (puserkey, pbestelling_key)
      {
        var sql = "BEGIN bes.makeorders("+ puserkey + ", " + pbestelling_key + "); END;";
        Oracle.Execute(sql);
        // Note: BES.MAKEORDERS notificeert zelf de leveranciers.
      },

      changeOrders: function (puserkey, pbestelling_key)
      {
        var sql = "BEGIN bes.changeorders("+ puserkey + ", " + pbestelling_key + "); END;";
        Oracle.Execute(sql);
      },

      bestelopdracht: function (bes_bestelling)
      {
        var l_orders_txt = [];
        var l_orders_key = [];
        sql_boi = "(SELECT bo.bes_bestelopdr_id, " +
                  "        bes_bestelopdr_status, " +
                  "        bes_bestelopdr_item_key, " +
                  "        bo.bes_bestelopdr_key " +
                  "   FROM BES_BESTELOPDR_ITEM boi, " +
                  "        BES_BESTELOPDR bo " +
                  "  WHERE bo.BES_BESTELOPDR_key = boi.BES_BESTELOPDR_key " +
                  "  GROUP BY bo.bes_bestelopdr_id, bes_bestelopdr_status, bes_bestelopdr_item_key, bo.bes_bestelopdr_key)";
        // Door welke bestelopdracht(en) wordt deze aanvraag afgehandeld?
        sql = "SELECT DISTINCT boi.bes_bestelopdr_id"
            + "     , boi.bes_bestelopdr_status"
            + "     , boi.bes_bestelopdr_key"
            + "  FROM bes_bestelling_item bi"
            + "     , " + sql_boi + " boi"
            + " WHERE bi.bes_bestelopdr_item_key = boi.bes_bestelopdr_item_key"
            + "   AND bi.bes_bestelling_key =" + bes_bestelling.bes_key
            + " ORDER BY 1";
            oRs = Oracle.Execute(sql);
        while(!oRs.eof)
        {
          var txt = S("bes_bestelopdr_prefix") + oRs("bes_bestelopdr_id").Value;
          if (oRs("bes_bestelopdr_status").Value == 1) // afgewezen
              txt += " (" + bes.getbesopdrstatustext(oRs("bes_bestelopdr_status").Value) + ")";
          if (bes_bestelling.parent_key)
              txt += "*"; // wij zijn een change dus de opdracht ook
          l_orders_txt.push(txt);
          l_orders_key.push(oRs("bes_bestelopdr_key").Value);
          oRs.MoveNext();
        }
        oRs.Close();
        result = { key : l_orders_key
                 , txt : l_orders_txt
                 };
        return result;
      },

      verwijderBestelling: function (bes_key, bestelopdr_key)
      {
        var message;
        var sql = "DELETE bes_bestelling WHERE bes_bestelling_key = " + bes_key;
        var err = Oracle.Execute(sql, true);
        if (err.friendlyMsg)
          message = err.friendlyMsg;

        // check of bestelaanvraag is verwijderd
        if (message == "")
        { // DELETE is niet echt trackbaar
          success = true;
          // bestelaanvraag is verwijderd. Verwijder nu ook de rest
          // JGL: Is dat niet allemaal automatisch meegecascadeerd?
          // Verwijder bestelaanvraag items
          sql = "DELETE bes_bestelling_item WHERE bes_bestelling_key = " + bes_key;
          Oracle.Execute(sql);

          // Indien een bestelopdracht aanwezig is dan bestelopdracht + bestelopdracht items verwijderen.
          if (bestelopdr_key > 0)
          {
            // Verwijder bestelopdracht items
            sql = "DELETE bes_bestelopdr_item WHERE bes_bestelopdr_key = " + bestelopdr_key;
            Oracle.Execute(sql);

            // Verwijder bestelopdracht
            sql = "DELETE bes_bestelopdr WHERE bes_bestelopdr_key = " + bestelopdr_key
            Oracle.Execute(sql);
          }
          message = L("lcl_bes_deleted_1") + S("bes_bestelling_prefix") + bes_key + L("lcl_bes_deleted_2");
        }
        return message;
      },
      // returns bes_srtdeel_key
      upsert_deel: function _upsert_deel(dis_key, params)
      {
          if (!("srtdeel_btw" in params))
            params.srtdeel_btw = 21.0; // Wordt vaak in custfunctions.wsc/hook bes_punch_receive gecorrigeerd
          if (!("srtgroep_omschrijving" in params) && params.srtgroep_key > 0)
          { // upsert_srtdeel werkt alleen op basis van omschrijving, helaas (nog) niet op srtgroep_key
            var sql = "SELECT bes_srtgroep_omschrijving"
                    + "  FROM bes_srtgroep"
                    + " WHERE bes_srtgroep_key = " + params.srtgroep_key;
            var oRs = Oracle.Execute(sql);
            params.srtgroep_omschrijving = oRs("bes_srtgroep_omschrijving").Value;;
            oRs.Close()
          }
          var sql = "BEGIN bes.upsert_srtdeel "
                  + "     ( " + dis_key
                  + "     , " + safe.quoted_sql(params.srtgroep_omschrijving, 60)        // bes_srtgroep_omschrijving
                  + "     , " + safe.quoted_sql(params.srtdeel_omschrijving, 100)        // bes_srtdeel_omschrijving
                  + "     , " + params.srtdeel_prijs
                  + "     , " + params.srtdeel_btw
                  + "     , " + safe.quoted_sql(params.srtdeel_eenheid, 30)       // bes_srtdeel_eenheid
                  + "     , " + safe.quoted_sql(params.srtdeel_nr, 32) // bes_srtdeel_nr
                  + "     , " + (params.bedrijf_key || -1)
                  + "     , NULL "                                       // vervaldatum
                  + "     , ''"
                  + "     , 1 "
                  + "     , " + safe.quoted_sql(params.srtdeel_opmerking, 2000)  // PF: hier stond opmerking ipv srtdeel_opmerking, heeft het dus nooit gedaan??
                  + "     , " + safe.quoted_sql(params.srtdeel_details_loc, 255)
                  + "     , new_bes_srtdeel_key => ?"
                  + "); END;";
          var oparams = [ { typ: adInteger, dir: adParamOutput } ]; // moet op volgorde van de '?'
          Oracle.ExecuteParam(sql, oparams);
          var bes_srtdeel_key = oparams[0].val;

          return bes_srtdeel_key;
      },
      voorraad_srtdeel: function _voorraad_srtdeel(pautfunction, params)
      {
          // Valid and supported parameters are:
          // params.catalogus_type: key
          // params.catalogus_key : key
          // params.besgroep_key  :
          // params.item_key      :
          // params.searchtekst   :
          // params.tebestellen   :
          var authparams = user.checkAutorisation(pautfunction);

          var sql_srtdeel = "SELECT sd2.bes_srtdeel_nr"
                          + "     , sd2.bes_srtdeel_voorraadfactor  intern_voorraadfactor"
                          + "     , sg2.ins_discipline_key"
                          + "     , sd2.bes_srtdeel_notitie intern_notitie"
                          + "     , "+ lcl.xsqla("sd2.bes_srtdeel_omschrijving","sd2.bes_srtdeel_key")
                          + "  FROM bes_srtdeel sd2"
                          + "     , bes_srtgroep sg2"
                          + " WHERE sd2.bes_srtgroep_key = sg2.bes_srtgroep_key"
                          + "   AND sd2.bes_srtdeel_verwijder IS NULL"
                          + "   AND (  sd2.bes_srtdeel_vervaldatum IS NULL"
                          + "       OR sd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE)"
                          + "       )";

          var sql_srtdeel2 = "  FROM bes_srtdeel isd2"
                           + "     , bes_srtgroep isg2"
                           + "     , bes_discipline bd2"
                           + " WHERE isd2.bes_srtgroep_key = isg2.bes_srtgroep_key"
                           + "   AND bd2.ins_discipline_key = isg2.ins_discipline_key"
                           + "   AND isd2.bes_srtdeel_nr LIKE sd.bes_srtdeel_nr"
                           + "   AND isd2.bes_srtdeel_verwijder IS NULL"
                           + "   AND (  isd2.bes_srtdeel_vervaldatum IS NULL"
                           + "       OR isd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE)"
                           + "       )"
                           + "   AND bd2.ins_discipline_key = dp.bes_ins_discipline_key_inkoop";


          // Bestelde artikelen intern (gekoppeld via bes_disc_params.bes_ins_discipline_key_inkoop)
          var sql_from_intern = "SELECT sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , (SELECT isd2.bes_srtdeel_key" + sql_srtdeel2 + ") bes_srtdeel_key_inkoop"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , dp.bes_ins_discipline_key_inkoop inkoop_disc"
                              + "     , (SELECT "+ lcl.xsql('bd2.ins_discipline_omschrijving','bd2.ins_discipline_key')
                                + "        FROM bes_discipline bd2"
                                + "       WHERE bd2.ins_discipline_key = dp.bes_ins_discipline_key_inkoop) disc_oms"
                              + "     , (SELECT isd2.bes_srtdeel_voorraadmax" + sql_srtdeel2 + ") voorraadmax" // Voorraadmax van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_voorraadmin" + sql_srtdeel2 + ") voorraadmin" // Voorraadmin van gekoppelde discipline
                              + "     , SUM (bo.bes_bestelopdr_item_aantal) aantal_intern"
                              + "     , TO_NUMBER (NULL) aantal_intern_besteld"
                              + "     , TO_NUMBER (NULL) aantal_intern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_open_order"
                              + "     , TO_NUMBER (NULL) aantal_extern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_extern_besteld"
                              + "     , (SELECT isd2.bes_srtdeel_maxbestel" + sql_srtdeel2 + ") maxbestel"         // maxbestel van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_minimum" + sql_srtdeel2 + ") bestelmin"           // Bestelminimum van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_maximum" + sql_srtdeel2 + ") bestelmax"           // Bestelmaximum van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_veelvoud" + sql_srtdeel2 + ") bestelveelvoud"     // Bestelveelvoud van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_eenheid" + sql_srtdeel2 + ") bes_srtdeel_eenheid" // Eenheid van gekoppelde discipline
                              + "     , sd.bes_srtdeel_eenheid bes_srtdeel_eenheid_intern"
                              + "  FROM bes_discipline bd"
                              + "     , bes_v_aanwezigsrtgroep g"
                              + "     , bes_v_aanwezigsrtdeel sd"
                              + "     , bes_bestelling b"
                              + "     , bes_bestelling_item bi"
                              + "     , bes_bestelopdr_item bo"
                              + "     , bes_disc_params dp"
                              + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                              + "   AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                              + "   AND b.bes_bestelling_key = bi.bes_bestelling_key"
                              + "   AND bi.bes_bestelopdr_item_key = bo.bes_bestelopdr_item_key"
                              + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                              + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                              + "   AND sd.bes_srtdeel_verwijder IS NULL"
                              + (params.catalogus_type
                                ? " AND dp.bes_disc_params_bestelmode = " + params.catalogus_type
                                : "")
                              + (params.catalogus_key
                                ? " AND dp.bes_ins_discipline_key_inkoop = " + params.catalogus_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.besgroep_key
                                ? " AND (sd.bes_srtdeel_nr IN (SELECT sd3.bes_srtdeel_nr"  // Inkoop en interne artikelen zijn op bes_srtdeel_nr gekoppeld.
                                  + "                            FROM bes_v_aanwezigsrtdeel sd3"
                                  + "                           WHERE (sd3.bes_srtdeel_vervaldatum IS NULL OR sd3.bes_srtdeel_vervaldatum > SYSDATE)"
                                  + "                            AND sd3.bes_srtgroep_key = " + params.besgroep_key + ")"
                                  + "    OR"
                                  + "    (SELECT isd2.bes_srtdeel_key"                     // Het kan zijn dat er (nog) geen inkoop variant is.
                                  + "       FROM bes_srtdeel isd2"
                                  + "          , bes_srtgroep isg2"
                                  + "          , bes_discipline bd2"
                                  + "      WHERE isd2.bes_srtgroep_key = isg2.bes_srtgroep_key"
                                  + "        AND bd2.ins_discipline_key = isg2.ins_discipline_key"
                                  + "        AND isd2.bes_srtdeel_nr LIKE sd.bes_srtdeel_nr"
                                  + "        AND isd2.bes_srtdeel_verwijder IS NULL"
                                  + "        AND (isd2.bes_srtdeel_vervaldatum IS NULL OR isd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE))"
                                  + "        AND bd2.ins_discipline_key = dp.bes_ins_discipline_key_inkoop) IS NULL"
                                  + "   )"
                                : "")
                              + (params.item_key
                                ? " AND sd.bes_srtdeel_key IN (SELECT sd2.bes_srtdeel_key"
                                  + "                            FROM bes_v_aanwezigsrtdeel sd2"
                                  + "                               ,  bes_v_aanwezigsrtgroep sg2"
                                  + "                           WHERE sd2.bes_srtgroep_key = sg2.bes_srtgroep_key"
                                  + "                             AND (sd2.bes_srtdeel_vervaldatum IS NULL OR sd2.bes_srtdeel_vervaldatum > SYSDATE)"
                                  + "                             AND sd2.bes_srtdeel_nr LIKE (SELECT sd3.bes_srtdeel_nr"
                                  + "                                                            FROM bes_v_aanwezigsrtdeel sd3"
                                  + "                                                           WHERE (sd3.bes_srtdeel_vervaldatum IS NULL OR sd3.bes_srtdeel_vervaldatum > SYSDATE)"
                                  + "                                                           AND sd3.bes_srtdeel_key = " + params.item_key + "))"
                                : "")
                              + " GROUP BY sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , dp.bes_ins_discipline_key_inkoop"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key")
                              + "     , bes_srtdeel_voorraadmax"
                              + "     , bes_srtdeel_voorraadmin"
                              + "     , sd.bes_srtdeel_maxbestel"
                              + "     , sd.bes_srtdeel_minimum"
                              + "     , sd.bes_srtdeel_maximum"
                              + "     , sd.bes_srtdeel_veelvoud"
                              + "     , sd.bes_srtdeel_eenheid"
                              + " UNION ALL "
                              + "SELECT sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , (SELECT isd2.bes_srtdeel_key" + sql_srtdeel2 + ") bes_srtdeel_key_inkoop"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , dp.bes_ins_discipline_key_inkoop inkoop_disc"
                              + "     , (SELECT "+ lcl.xsql('bd2.ins_discipline_omschrijving','bd2.ins_discipline_key')
                                + "        FROM bes_discipline bd2"
                                + "       WHERE bd2.ins_discipline_key = dp.bes_ins_discipline_key_inkoop) disc_oms"
                              + "     , (SELECT isd2.bes_srtdeel_voorraadmax" + sql_srtdeel2 + ") voorraadmax" // Voorraadmax van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_voorraadmin" + sql_srtdeel2 + ") voorraadmin" // Voorraadmin van gekoppelde discipline
                              + "     , TO_NUMBER (NULL) aantal_intern"
                              + "     , SUM (bo.bes_bestelopdr_item_aantal) aantal_intern_besteld"
                              + "     , SUM (bo.bes_bestelopdr_item_aantalontv) aantal_intern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_open_order"
                              + "     , TO_NUMBER (NULL) aantal_extern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_extern_besteld"
                              + "     , (SELECT isd2.bes_srtdeel_maxbestel" + sql_srtdeel2 + ") maxbestel"         // maxbestel van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_minimum" + sql_srtdeel2 + ") bestelmin"           // Bestelminimum van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_maximum" + sql_srtdeel2 + ") bestelmax"           // Bestelmaximum van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_veelvoud" + sql_srtdeel2 + ") bestelveelvoud"     // Bestelveelvoud van gekoppelde discipline
                              + "     , (SELECT isd2.bes_srtdeel_eenheid" + sql_srtdeel2 + ") bes_srtdeel_eenheid" // Eenheid van gekoppelde discipline
                              + "     , sd.bes_srtdeel_eenheid bes_srtdeel_eenheid_intern"
                              + "  FROM bes_discipline bd"
                              + "     , bes_v_aanwezigsrtgroep g"
                              + "     , bes_v_aanwezigsrtdeel sd"
                              + "     , bes_bestelling b"
                              + "     , bes_bestelling_item bi"
                              + "     , bes_bestelopdr_item bo"
                              + "     , bes_disc_params dp"
                              + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                              + "   AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                              + "   AND b.bes_bestelling_status = 5"
                              + "   AND b.bes_bestelling_key = bi.bes_bestelling_key"
                              + "   AND bi.bes_bestelopdr_item_key = bo.bes_bestelopdr_item_key"
                              + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                              + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                              + "   AND sd.bes_srtdeel_verwijder IS NULL"
                              + (params.catalogus_type
                                ? " AND dp.bes_disc_params_bestelmode = " + params.catalogus_type
                                : "")
                              + (params.catalogus_key
                                ? " AND dp.bes_ins_discipline_key_inkoop = " + params.catalogus_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.besgroep_key
                                ? " AND (sd.bes_srtdeel_nr IN (SELECT sd3.bes_srtdeel_nr"  // Inkoop en interne artikelen zijn op bes_srtdeel_nr gekoppeld.
                                  + "                            FROM bes_v_aanwezigsrtdeel sd3"
                                  + "                           WHERE (sd3.bes_srtdeel_vervaldatum IS NULL OR sd3.bes_srtdeel_vervaldatum > SYSDATE)"
                                  + "                            AND sd3.bes_srtgroep_key = " + params.besgroep_key + ")"
                                  + "    OR"
                                  + "    (SELECT isd2.bes_srtdeel_key"                     // Het kan zijn dat er (nog) geen inkoop variant is.
                                  + "       FROM bes_srtdeel isd2"
                                  + "          , bes_srtgroep isg2"
                                  + "          , bes_discipline bd2"
                                  + "      WHERE isd2.bes_srtgroep_key = isg2.bes_srtgroep_key"
                                  + "        AND bd2.ins_discipline_key = isg2.ins_discipline_key"
                                  + "        AND isd2.bes_srtdeel_nr LIKE sd.bes_srtdeel_nr"
                                  + "        AND isd2.bes_srtdeel_verwijder IS NULL"
                                  + "        AND (isd2.bes_srtdeel_vervaldatum IS NULL OR isd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE))"
                                  + "        AND bd2.ins_discipline_key = dp.bes_ins_discipline_key_inkoop) IS NULL"
                                  + "   )"
                                : "")
                              + (params.item_key
                                ? " AND sd.bes_srtdeel_key IN (SELECT sd2.bes_srtdeel_key"
                                  + "                            FROM bes_v_aanwezigsrtdeel sd2"
                                  + "                               ,  bes_v_aanwezigsrtgroep sg2"
                                  + "                           WHERE sd2.bes_srtgroep_key = sg2.bes_srtgroep_key"
                                  + "                             AND (sd2.bes_srtdeel_vervaldatum IS NULL OR sd2.bes_srtdeel_vervaldatum > SYSDATE)"
                                  + "                             AND sd2.bes_srtdeel_nr LIKE (SELECT sd3.bes_srtdeel_nr"
                                  + "                                                            FROM bes_v_aanwezigsrtdeel sd3"
                                  + "                                                           WHERE (sd3.bes_srtdeel_vervaldatum IS NULL OR sd3.bes_srtdeel_vervaldatum > SYSDATE)"
                                  + "                                                           AND sd3.bes_srtdeel_key = " + params.item_key + "))"
                                : "")
                              + " GROUP BY sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , dp.bes_ins_discipline_key_inkoop"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key")
                              + "     , bes_srtdeel_voorraadmax"
                              + "     , bes_srtdeel_voorraadmin"
                              + "     , sd.bes_srtdeel_maxbestel"
                              + "     , sd.bes_srtdeel_minimum"
                              + "     , sd.bes_srtdeel_maximum"
                              + "     , sd.bes_srtdeel_veelvoud"
                              + "     , sd.bes_srtdeel_eenheid";

          // Bestelde artikelen bij de leverancier (extern)
          // Besteld (status = 5) en Geleverd (status = 6,7)
          var sql_from_extern = "SELECT sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , NULL bes_srtdeel_key_inkoop"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , bd.ins_discipline_key inkoop_disc"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key") +" disc_oms"
                              + "     , bes_srtdeel_voorraadmax voorraadmax"
                              + "     , bes_srtdeel_voorraadmin voorraadmin"
                              + "     , TO_NUMBER (NULL) aantal_intern"
                              + "     , TO_NUMBER (NULL) aantal_intern_besteld"
                              + "     , TO_NUMBER (NULL) aantal_intern_geleverd"
                              + "     , SUM (bi.bes_bestelling_item_aantal) - SUM (COALESCE(bi.bes_bestelling_item_aantalontv, 0)) aantal_open_order"
                              + "     , TO_NUMBER (NULL) aantal_extern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_extern_besteld"
                              + "     , sd.bes_srtdeel_maxbestel maxbestel"
                              + "     , sd.bes_srtdeel_minimum bestelmin"
                              + "     , sd.bes_srtdeel_maximum bestelmax"
                              + "     , sd.bes_srtdeel_veelvoud bestelveelvoud"
                              + "     , sd.bes_srtdeel_eenheid"
                              // Het artikel moet gekoppeld zijn aan een externe leverancier die gekoppeld is aan de interne leverancier (bes_ins_discipline_key_inkoop).
                              // Er kunnen meerdere disciplines gekoppeld zijn aan de inkoopcatalogus.
                              // We gaan er van uit dat de eenheid van de gekoppelde artikelen hetzelfde zijn zodat we de MIN kunnen nemen.
                              + "     , (SELECT MIN(isd2.bes_srtdeel_eenheid)"
                                + "        FROM bes_srtdeel isd2"
                                + "           , bes_srtgroep isg2"
                                + "           , bes_disc_params dp2"
                                + "       WHERE isd2.bes_srtgroep_key = isg2.bes_srtgroep_key"
                                + "         AND dp2.bes_ins_discipline_key = isg2.ins_discipline_key"
                                + "         AND isd2.bes_srtdeel_nr LIKE sd.bes_srtdeel_nr"
                                + "         AND isd2.bes_srtdeel_verwijder IS NULL"
                                + "         AND (isd2.bes_srtdeel_vervaldatum IS NULL OR isd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE))"
                                + "         AND dp.bes_ins_discipline_key = dp2.bes_ins_discipline_key_inkoop) bes_srtdeel_eenheid_intern" // Eenheid van gekoppelde discipline
                              + "  FROM bes_discipline bd"
                              + "     , bes_v_aanwezigsrtgroep g"
                              + "     , bes_v_aanwezigsrtdeel sd"
                              + "     , bes_bestelling b"
                              + "     , bes_bestelling_item bi"
                              + "     , bes_bestelopdr_item bo"
                              + "     , bes_disc_params dp"
                              + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                              + "   AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                              + "   AND b.bes_bestelling_key = bi.bes_bestelling_key"
                              + "   AND bi.bes_bestelopdr_item_key = bo.bes_bestelopdr_item_key"
                              + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                              + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                              + "   AND sd.bes_srtdeel_verwijder IS NULL"
                              + "   AND b.bes_bestelling_status IN (2, 3, 4, 5)"
                              + "   AND dp.bes_ins_discipline_key_inkoop IS NULL"
                              // Het moet een gekoppelde discipline zijn
                              + "   AND dp.bes_ins_discipline_key IN"
                                    + " (SELECT dp1.bes_ins_discipline_key_inkoop"
                                    + "    FROM bes_disc_params dp1"
                                    + "   WHERE dp1.bes_ins_discipline_key_inkoop IS NOT NULL)"
                              // Het artikel moet gekoppeld zijn aan een externe leverancier die gekoppeld is aan de interne leverancier (bes_ins_discipline_key_inkoop).
                              + " AND EXISTS (SELECT bd1.ins_discipline_key"
                              + "                  , g1.bes_srtgroep_key"
                              + "                  , sd1.bes_srtdeel_key"
                              + "                  , sd1.bes_srtdeel_nr"
                              + "                  , dp1.bes_ins_discipline_key_inkoop"
                              + "               FROM bes_discipline bd1"
                              + "                  , bes_v_aanwezigsrtgroep g1"
                              + "                  , bes_v_aanwezigsrtdeel sd1"
                              + "                  , bes_disc_params dp1"
                              + "              WHERE sd1.bes_srtgroep_key = g1.bes_srtgroep_key"
                              + "                AND g1.ins_discipline_key = bd1.ins_discipline_key"
                              + "                AND bd1.ins_discipline_key = dp1.bes_ins_discipline_key"
                              + "                AND sd1.bes_srtdeel_nr = sd.bes_srtdeel_nr"                     // Dezelfde omschrijving.
                              + "                AND dp1.bes_ins_discipline_key_inkoop = bd.ins_discipline_key)" // Gekoppeld aan inkoopcatalogus.
                              + (params.catalogus_type
                                ? " AND dp.bes_disc_params_bestelmode = " + params.catalogus_type
                                : "")
                              + (params.catalogus_key
                                ? " AND bd.ins_discipline_key = " + params.catalogus_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.besgroep_key
                                ? " AND g.bes_srtgroep_key = " + params.besgroep_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.item_key
                                ? " AND sd.bes_srtdeel_key = " + params.item_key
                                : "")
                              + " GROUP BY sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , bd.ins_discipline_key"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key")
                              + "     , bes_srtdeel_voorraadmax"
                              + "     , bes_srtdeel_voorraadmin"
                              + "     , sd.bes_srtdeel_maxbestel"
                              + "     , sd.bes_srtdeel_minimum"
                              + "     , sd.bes_srtdeel_maximum"
                              + "     , sd.bes_srtdeel_veelvoud"
                              + "     , sd.bes_srtdeel_eenheid"
                              + " UNION ALL "
                              + "SELECT sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , NULL bes_srtdeel_key_inkoop"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , bd.ins_discipline_key inkoop_disc"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key") +" disc_oms"
                              + "     , bes_srtdeel_voorraadmax voorraadmax"
                              + "     , bes_srtdeel_voorraadmin voorraadmin"
                              + "     , TO_NUMBER (NULL) aantal_intern"
                              + "     , TO_NUMBER (NULL) aantal_intern_besteld"
                              + "     , TO_NUMBER (NULL) aantal_intern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_open_order"
                              + "     , SUM (COALESCE(bi.bes_bestelling_item_aantalontv, 0)) aantal_extern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_extern_besteld"
                              + "     , sd.bes_srtdeel_maxbestel maxbestel"
                              + "     , sd.bes_srtdeel_minimum bestelmin"
                              + "     , sd.bes_srtdeel_maximum bestelmax"
                              + "     , sd.bes_srtdeel_veelvoud bestelveelvoud"
                              + "     , sd.bes_srtdeel_eenheid"
                              // Het artikel moet gekoppeld zijn aan een externe leverancier die gekoppeld is aan de interne leverancier (bes_ins_discipline_key_inkoop).
                              // Er kunnen meerdere disciplines gekoppeld zijn aan de inkoopcatalogus.
                              // We gaan er van uit dat de eenheid van de gekoppelde artikelen hetzelfde zijn zodat we de MIN kunnen nemen.
                              + "     , (SELECT MIN(isd2.bes_srtdeel_eenheid)"
                                + "        FROM bes_srtdeel isd2"
                                + "           , bes_srtgroep isg2"
                                + "           , bes_disc_params dp2"
                                + "       WHERE isd2.bes_srtgroep_key = isg2.bes_srtgroep_key"
                                + "         AND dp2.bes_ins_discipline_key = isg2.ins_discipline_key"
                                + "         AND isd2.bes_srtdeel_nr LIKE sd.bes_srtdeel_nr"
                                + "         AND isd2.bes_srtdeel_verwijder IS NULL"
                                + "         AND (isd2.bes_srtdeel_vervaldatum IS NULL OR isd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE))"
                                + "         AND dp.bes_ins_discipline_key = dp2.bes_ins_discipline_key_inkoop) bes_srtdeel_eenheid_intern" // Eenheid van gekoppelde discipline
                              + "  FROM bes_discipline bd"
                              + "     , bes_v_aanwezigsrtgroep g"
                              + "     , bes_v_aanwezigsrtdeel sd"
                              + "     , bes_bestelling b"
                              + "     , bes_bestelling_item bi"
                              + "     , bes_bestelopdr_item bo"
                              + "     , bes_disc_params dp"
                              + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                              + "   AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                              + "   AND b.bes_bestelling_key = bi.bes_bestelling_key"
                              + "   AND bi.bes_bestelopdr_item_key = bo.bes_bestelopdr_item_key"
                              + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                              + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                              + "   AND sd.bes_srtdeel_verwijder IS NULL"
                              // Bestellingstatus 5:      Alleen de bestelopdr items waarbij de ontvangen datum is gezet zijn gedeeltelijk of in zijn geheel geleverd.
                              // Bestellingstatus 6 en 7: Bestelopdr is in zijn geheel geleverd.
                              + "   AND (b.bes_bestelling_status IN (6, 7)"
                              + "        OR (bo.bes_bestelopdr_item_ontvangen IS NOT NULL"
                              + "            AND b.bes_bestelling_status IN (5)))"
                              + "   AND dp.bes_ins_discipline_key_inkoop IS NULL"
                              // Het moet een gekoppelde discipline zijn
                              + "   AND dp.bes_ins_discipline_key IN"
                                + "     (SELECT dp1.bes_ins_discipline_key_inkoop"
                                + "        FROM bes_disc_params dp1"
                                + "       WHERE dp1.bes_ins_discipline_key_inkoop IS NOT NULL)"
                              // Het artikel moet gekoppeld zijn aan een externe leverancier die gekoppeld is aan de interne leverancier (bes_ins_discipline_key_inkoop).
                              + " AND EXISTS (SELECT bd1.ins_discipline_key"
                              + "                  , g1.bes_srtgroep_key"
                              + "                  , sd1.bes_srtdeel_key"
                              + "                  , sd1.bes_srtdeel_nr"
                              + "                  , dp1.bes_ins_discipline_key_inkoop"
                              + "               FROM bes_discipline bd1"
                              + "                  , bes_v_aanwezigsrtgroep g1"
                              + "                  , bes_v_aanwezigsrtdeel sd1"
                              + "                  , bes_disc_params dp1"
                              + "              WHERE sd1.bes_srtgroep_key = g1.bes_srtgroep_key"
                              + "                AND g1.ins_discipline_key = bd1.ins_discipline_key"
                              + "                AND bd1.ins_discipline_key = dp1.bes_ins_discipline_key"
                              + "                AND sd1.bes_srtdeel_nr = sd.bes_srtdeel_nr"                     // Dezelfde omschrijving.
                              + "                AND dp1.bes_ins_discipline_key_inkoop = bd.ins_discipline_key)" // Gekoppeld aan inkoopcatalogus.
                              + (params.catalogus_type
                                ? " AND dp.bes_disc_params_bestelmode = " + params.catalogus_type
                                : "")
                              + (params.catalogus_key
                                ? " AND bd.ins_discipline_key = " + params.catalogus_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.besgroep_key
                                ? " AND g.bes_srtgroep_key = " + params.besgroep_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.item_key
                                ? " AND sd.bes_srtdeel_key = " + params.item_key
                                : "")
                              + " GROUP BY sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , bd.ins_discipline_key"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key")
                              + "     , bes_srtdeel_voorraadmax"
                              + "     , bes_srtdeel_voorraadmin"
                              + "     , sd.bes_srtdeel_maxbestel"
                              + "     , sd.bes_srtdeel_minimum"
                              + "     , sd.bes_srtdeel_maximum"
                              + "     , sd.bes_srtdeel_veelvoud"
                              + "     , sd.bes_srtdeel_eenheid"
                              + " UNION ALL "
                              + "SELECT sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , NULL bes_srtdeel_key_inkoop"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , bd.ins_discipline_key inkoop_disc"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key") +" disc_oms"
                              + "     , bes_srtdeel_voorraadmax voorraadmax"
                              + "     , bes_srtdeel_voorraadmin voorraadmin"
                              + "     , TO_NUMBER (NULL) aantal_intern"
                              + "     , TO_NUMBER (NULL) aantal_intern_besteld"
                              + "     , TO_NUMBER (NULL) aantal_intern_geleverd"
                              + "     , TO_NUMBER (NULL) aantal_open_order"
                              + "     , TO_NUMBER (NULL) aantal_extern_geleverd"
                              + "     , SUM (COALESCE(bi.bes_bestelling_item_aantal, 0)) aantal_extern_besteld"
                              + "     , sd.bes_srtdeel_maxbestel maxbestel"
                              + "     , sd.bes_srtdeel_minimum bestelmin"
                              + "     , sd.bes_srtdeel_maximum bestelmax"
                              + "     , sd.bes_srtdeel_veelvoud bestelveelvoud"
                              + "     , sd.bes_srtdeel_eenheid"
                              // Het artikel moet gekoppeld zijn aan een externe leverancier die gekoppeld is aan de interne leverancier (bes_ins_discipline_key_inkoop).
                              // Er kunnen meerdere disciplines gekoppeld zijn aan de inkoopcatalogus.
                              // We gaan er van uit dat de eenheid van de gekoppelde artikelen hetzelfde zijn zodat we de MIN kunnen nemen.
                              + "     , (SELECT MIN(isd2.bes_srtdeel_eenheid)"
                                + "        FROM bes_srtdeel isd2"
                                + "           , bes_srtgroep isg2"
                                + "           , bes_disc_params dp2"
                                + "       WHERE isd2.bes_srtgroep_key = isg2.bes_srtgroep_key"
                                + "         AND dp2.bes_ins_discipline_key = isg2.ins_discipline_key"
                                + "         AND isd2.bes_srtdeel_nr LIKE sd.bes_srtdeel_nr"
                                + "         AND isd2.bes_srtdeel_verwijder IS NULL"
                                + "         AND (isd2.bes_srtdeel_vervaldatum IS NULL OR isd2.bes_srtdeel_vervaldatum > TRUNC(SYSDATE))"
                                + "         AND dp.bes_ins_discipline_key = dp2.bes_ins_discipline_key_inkoop) bes_srtdeel_eenheid_intern" // Eenheid van gekoppelde discipline
                              + "  FROM bes_discipline bd"
                              + "     , bes_v_aanwezigsrtgroep g"
                              + "     , bes_v_aanwezigsrtdeel sd"
                              + "     , bes_bestelling b"
                              + "     , bes_bestelling_item bi"
                              + "     , bes_bestelopdr_item bo"
                              + "     , bes_disc_params dp"
                              + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                              + "   AND bi.bes_srtdeel_key = sd.bes_srtdeel_key"
                              + "   AND b.bes_bestelling_key = bi.bes_bestelling_key"
                              + "   AND bi.bes_bestelopdr_item_key = bo.bes_bestelopdr_item_key"
                              + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                              + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                              + "   AND sd.bes_srtdeel_verwijder IS NULL"
                              // Bestellingstatus 5:      Alleen de bestelopdr items waarbij de ontvangen datum niet is gezet zijn in bestelling bij de leverancier.
                              + "   AND bo.bes_bestelopdr_item_ontvangen IS NULL"
                              + "   AND b.bes_bestelling_status IN (5)"
                              + "   AND dp.bes_ins_discipline_key_inkoop IS NULL"
                              // Het moet een gekoppelde discipline zijn
                              + "   AND dp.bes_ins_discipline_key IN"
                                + "     (SELECT dp1.bes_ins_discipline_key_inkoop"
                                + "        FROM bes_disc_params dp1"
                                + "       WHERE dp1.bes_ins_discipline_key_inkoop IS NOT NULL)"
                              // Het artikel moet gekoppeld zijn aan een externe leverancier die gekoppeld is aan de interne leverancier (bes_ins_discipline_key_inkoop).
                              + " AND EXISTS (SELECT bd1.ins_discipline_key"
                              + "                  , g1.bes_srtgroep_key"
                              + "                  , sd1.bes_srtdeel_key"
                              + "                  , sd1.bes_srtdeel_nr"
                              + "                  , dp1.bes_ins_discipline_key_inkoop"
                              + "               FROM bes_discipline bd1"
                              + "                  , bes_v_aanwezigsrtgroep g1"
                              + "                  , bes_v_aanwezigsrtdeel sd1"
                              + "                  , bes_disc_params dp1"
                              + "              WHERE sd1.bes_srtgroep_key = g1.bes_srtgroep_key"
                              + "                AND g1.ins_discipline_key = bd1.ins_discipline_key"
                              + "                AND bd1.ins_discipline_key = dp1.bes_ins_discipline_key"
                              + "                AND sd1.bes_srtdeel_nr = sd.bes_srtdeel_nr"                     // Dezelfde omschrijving.
                              + "                AND dp1.bes_ins_discipline_key_inkoop = bd.ins_discipline_key)" // Gekoppeld aan inkoopcatalogus.
                              + (params.catalogus_type
                                ? " AND dp.bes_disc_params_bestelmode = " + params.catalogus_type
                                : "")
                              + (params.catalogus_key
                                ? " AND bd.ins_discipline_key = " + params.catalogus_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.besgroep_key
                                ? " AND g.bes_srtgroep_key = " + params.besgroep_key
                                  + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                                : "")
                              + (params.item_key
                                ? " AND sd.bes_srtdeel_key = " + params.item_key
                                : "")
                              + " GROUP BY sd.bes_srtdeel_nr"
                              + "     , sd.bes_srtdeel_key"
                              + "     , dp.bes_ins_discipline_key"
                              + "     , bd.ins_discipline_key"
                              + "     , "+ lcl.xsql("bd.ins_discipline_omschrijving","bd.ins_discipline_key")
                              + "     , bes_srtdeel_voorraadmax"
                              + "     , bes_srtdeel_voorraadmin"
                              + "     , sd.bes_srtdeel_maxbestel"
                              + "     , sd.bes_srtdeel_minimum"
                              + "     , sd.bes_srtdeel_maximum"
                              + "     , sd.bes_srtdeel_veelvoud"
                              + "     , sd.bes_srtdeel_eenheid";

          var sql_from = sql_from_intern
                       + " UNION ALL "
                       + sql_from_extern;

          var sql_from_all = "SELECT COALESCE (bo.bes_srtdeel_key_inkoop, bo.bes_srtdeel_key) bes_srtdeel_key"
                           + "     , bo.bes_srtdeel_nr"
                           + "     , bo.bes_ins_discipline_key"
                           + "     , bo.inkoop_disc"
                           + "     , bo.disc_oms"
                           + "     , bo.voorraadmax"
                           + "     , bo.voorraadmin"
                           + "     , SUM (bo.aantal_intern)          aantal_intern_uit"
                           + "     , SUM (bo.aantal_intern_besteld)  aantal_intern_bes"
                           + "     , SUM (bo.aantal_intern_geleverd) aantal_intern_gel"
                           + "     , SUM (bo.aantal_extern_geleverd) aantal_geleverd"
                           + "     , SUM (bo.aantal_extern_besteld)  aantal_besteld"
                           + "     , SUM (bo.aantal_open_order)      aantal_open_order"
                           + "     , bo.maxbestel"
                           + "     , bo.bestelmin"
                           + "     , bo.bestelmax"
                           + "     , bo.bestelveelvoud"
                           + "     , bo.bes_srtdeel_eenheid"
                           + "     , bo.bes_srtdeel_eenheid_intern"
                           + "  FROM (" + sql_from + ") bo"
                           + " GROUP BY bo.bes_srtdeel_key"
                           + "        , bo.bes_srtdeel_key_inkoop"
                           + "        , bo.bes_srtdeel_nr"
                           + "        , bo.bes_ins_discipline_key"
                           + "        , bo.inkoop_disc"
                           + "        , bo.disc_oms"
                           + "        , bo.voorraadmax"
                           + "        , bo.voorraadmin"
                           + "        , bo.maxbestel"
                           + "        , bo.bestelmin"
                           + "        , bo.bestelmax"
                           + "        , bo.bestelveelvoud"
                           + "        , bo.bes_srtdeel_eenheid"
                           + "        , bo.bes_srtdeel_eenheid_intern";

          var sql_prijs = "SELECT sp.bes_srtdeel_key"
                        + "     , sp.bes_srtdeel_prijs_prijs"
                        + "     , sp.bes_srtdeel_prijs_inkprijs"
                        + "  FROM bes_srtdeel_prijs sp"
                        + " WHERE sp.bes_srtdeel_prijs_vervaldatum IS NULL"

          var sql_val = "SELECT a.bes_srtdeel_key"
                      + "     , a.bes_srtdeel_nr"
                      + "     , a.inkoop_disc"
                      + "     , a.disc_oms"
                      + "     , a.voorraadmax"
                      + "     , a.voorraadmin"
                      + "     , a.maxbestel"
                      + "     , a.bestelmin"
                      + "     , a.bestelmax"
                      + "     , a.bestelveelvoud"
                      + "     , SUM(a.aantal_intern_uit) aantal_intern_uit"
                      + "     , SUM(CEIL (a.aantal_intern_uit / b.intern_voorraadfactor))  aantal_extern_uit"
                      + "     , SUM(a.aantal_geleverd) aantal_geleverd"
                      + "     , SUM(a.aantal_intern_bes) - SUM(a.aantal_intern_gel)  aantal_uitmaarnoginmagazijn"
                      + "     , SUM(a.aantal_besteld)    aantal_inbestellingbijlever"
                      + "     , SUM(a.aantal_open_order) aantal_open_order"
                      + "     , b.intern_voorraadfactor"
                      + "     , COALESCE(SUM(a.aantal_geleverd), 0) - COALESCE(SUM(CEIL (a.aantal_intern_uit / b.intern_voorraadfactor)), 0) voorraad"
                      + "     , COALESCE(SUM (a.aantal_geleverd * b.intern_voorraadfactor), 0) -  COALESCE(SUM (a.aantal_intern_uit), 0) voorraad_intern"
                      + "     , b.intern_notitie"
                      + "     , b.bes_srtdeel_omschrijving"
                      + "     , a.bes_srtdeel_eenheid eenheid_extern"
                      + "     , a.bes_srtdeel_eenheid_intern eenheid_intern"
                      + "     , c.bes_srtdeel_prijs_prijs prijs_intern"
                      + "  FROM (" + sql_from_all + ") a"
                      + "     , (" + sql_srtdeel  + ") b"
                      + "     , (" + sql_prijs    + ") c"
                      + " WHERE a.bes_srtdeel_nr = b.bes_srtdeel_nr"
                      + "   AND a.inkoop_disc = b.ins_discipline_key"
                      + "   AND a.bes_srtdeel_key = c.bes_srtdeel_key(+)"
                      + "   AND a.inkoop_disc IN"
                      + "         (SELECT ins_discipline_key"
                      + "            FROM fac_v_webgebruiker g"
                      + "               , fac_functie f"
                      + "            WHERE g.prs_perslid_key = " + user_key
                      + "            AND f.fac_functie_key = g.fac_functie_key "
                      + "            AND f.fac_functie_code = " + safe.quoted_sql(pautfunction) + ")"
                      + (params.catalogus_key
                        ? " AND a.inkoop_disc = " + params.catalogus_key
                        : "")
                      + (params.searchtekst
                        ? " AND (  UPPER(a.bes_srtdeel_nr) LIKE " + safe.quoted_sql_wild("%" + params.searchtekst + "%")
                          + "   OR UPPER(b.bes_srtdeel_omschrijving) LIKE " + safe.quoted_sql_wild("%" + params.searchtekst + "%") + ")"
                        : "")
                      + " GROUP BY a.bes_srtdeel_key"
                      + "        , a.bes_srtdeel_nr"
                      + "        , a.inkoop_disc"
                      + "        , a.disc_oms"
                      + "        , a.voorraadmax"
                      + "        , a.voorraadmin"
                      + "        , a.maxbestel"
                      + "        , a.bestelmin"
                      + "        , a.bestelmax"
                      + "        , a.bestelveelvoud"
                      + "        , b.intern_voorraadfactor"
                      + "        , b.intern_notitie"
                      + "        , b.bes_srtdeel_omschrijving"
                      + "        , a.bes_srtdeel_eenheid"
                      + "        , a.bes_srtdeel_eenheid_intern"
                      + "        , c.bes_srtdeel_prijs_prijs";

          var sql = "SELECT bes_srtdeel_key"
                  + "     , bes_srtdeel_nr"
                  + "     , bes_srtdeel_omschrijving"
                  + "     , intern_notitie bes_srtdeel_notitie"
                  + "     , intern_voorraadfactor"
                  + "     , inkoop_disc"
                  + "     , disc_oms"
                  + "     , voorraadmax"
                  + "     , voorraadmin"
                  + "     , maxbestel"
                  + "     , bestelmin"
                  + "     , bestelmax"
                  + "     , bestelveelvoud"
                  + "     , aantal_intern_uit"
                  + "     , aantal_extern_uit"
                  + "     , aantal_geleverd"
                  + "     , aantal_uitmaarnoginmagazijn"
                  + "     , aantal_inbestellingbijlever"
                  + "     , aantal_open_order"
                  + "     , CASE"
                  + "         WHEN (  COALESCE(aantal_open_order, 0)"
                  + "               + COALESCE (aantal_geleverd, 0)"
                  + "               - COALESCE (aantal_extern_uit, 0) < voorraadmin)"
                  + "          THEN"
                  + "               voorraadmax"
                  + "             - COALESCE (aantal_open_order, 0)"
                  + "             - COALESCE (aantal_geleverd, 0)"
                  + "             + COALESCE (aantal_extern_uit, 0)"
                  + "          ELSE"
                  + "             NULL"
                  + "       END tebestellen"
                  + "     , voorraad"
                  + "     , voorraad_intern"
                  + "     , (SELECT COUNT(*)"
                  + "          FROM bes_kenmerk bk"
                  + "             , bes_srtkenmerk sk"
                  + "             , bes_srtdeel sd"
                  + "             , bes_srtgroep sg"
                  + "         WHERE sd.bes_srtgroep_key = sg.bes_srtgroep_key"
                  + "           AND (bk.bes_srtinstallatie_key = sg.ins_discipline_key AND bk.bes_kenmerk_niveau LIKE 'D'"
                  + "                OR bk.bes_srtinstallatie_key = sg.bes_srtgroep_key AND bk.bes_kenmerk_niveau LIKE 'G'"
                  + "                OR bk.bes_srtinstallatie_key = sd.bes_srtdeel_key AND bk.bes_kenmerk_niveau LIKE 'S')"
                  + "           AND bk.bes_kenmerk_type = 'I'"
                  + "           AND bk.bes_srtkenmerk_key = sk.bes_srtkenmerk_key"
                  + "           AND bk.bes_kenmerk_verwijder IS NULL"
                  + "           AND sk.bes_srtkenmerk_verwijder IS NULL"
                  + "           AND sd.bes_srtdeel_key = l.bes_srtdeel_key) aantalkenmerken"
                  + "     , l.eenheid_extern"
                  + "     , l.eenheid_intern"
                  + "     , l.prijs_intern"
                  + "  FROM (" + sql_val + ") l";

          if (params.tebestellen)
            sql = "SELECT *"
                + " FROM (" + sql + ")"
                + " WHERE tebestellen IS NOT NULL"

          sql += " ORDER BY bes_srtdeel_nr";

          return sql;
      },

      current_srtdeel: function _current_srtdeel(pautfunction, params)
      { // Query voor de artikelen lijst van het catalogus type "Actuele lijst(3)".

        // Valid and supported parameters are:
        // params.catalogus_key : key
        // params.besgroep_key  :
        // params.item_key      :
        // params.searchtekst   :
        var authparams = user.checkAutorisation(pautfunction);

                // Artikelen met lopende bestellingen.
        var sql = "SELECT sd.bes_srtdeel_key"
                + "     , sd.bes_srtdeel_volgnr"
                + "     , sd.bes_srtdeel_nr"
                + "     , sd.bes_srtdeel_omschrijving"
                + "     , g.bes_srtgroep_omschrijving"
                + "     , sd.bes_srtdeel_notitie"
                + "     , dp.bes_ins_discipline_key"
                + "     , bd.ins_discipline_omschrijving"
                + "     , sd.bes_srtdeel_voorraadmax voorraadmax"
                + "     , sd.bes_srtdeel_voorraadmin voorraadmin"
                + "     , sd.bes_srtdeel_maxbestel maxbestel"
                + "     , sd.bes_srtdeel_minimum bestelmin"
                + "     , sd.bes_srtdeel_maximum bestelmax"
                + "     , sd.bes_srtdeel_veelvoud bestelveelvoud"
                + "     , sd.bes_srtdeel_eenheid eenheid"
                + "     , sd.bes_srtdeel_vervaldatum"
                + "     , (SELECT COUNT(*)"
                  + "        FROM bes_kenmerk bk"
                  + "           , bes_srtkenmerk sk"
                  + "           , bes_srtdeel sd2"
                  + "           , bes_srtgroep sg"
                  + "       WHERE sd2.bes_srtgroep_key = sg.bes_srtgroep_key"
                  + "         AND (bk.bes_srtinstallatie_key = sg.ins_discipline_key AND bk.bes_kenmerk_niveau LIKE 'D'"
                  + "              OR bk.bes_srtinstallatie_key = sg.bes_srtgroep_key AND bk.bes_kenmerk_niveau LIKE 'G'"
                  + "              OR bk.bes_srtinstallatie_key = sd2.bes_srtdeel_key AND bk.bes_kenmerk_niveau LIKE 'S')"
                  + "         AND bk.bes_kenmerk_type = 'I'"
                  + "         AND bk.bes_srtkenmerk_key = sk.bes_srtkenmerk_key"
                  + "         AND bk.bes_kenmerk_verwijder IS NULL"
                  + "         AND sk.bes_srtkenmerk_verwijder IS NULL"
                  + "         AND sd2.bes_srtdeel_key = sd.bes_srtdeel_key) aantalkenmerken"
                  + "   , SUM (bi.bes_bestelling_item_aantal) - SUM (COALESCE(bi.bes_bestelling_item_aantalontv, 0)) inbestelling"
                  + "   , COALESCE(bes.getsrtdeelprijs(sd.bes_srtdeel_key, null) , 0) prijs"
                  + "   , NVL2(sd.bes_srtdeel_image, p.prs_bedrijf_image_loc || sd.bes_srtdeel_image, NULL) foto"
                + "  FROM bes_discipline bd"
                + "     , bes_v_aanwezigsrtgroep g"
                + "     , bes_v_aanwezigsrtdeel sd"
                + "     , bes_disc_params dp"
                + "     , bes_bestelling b"
                + "     , bes_bestelling_item bi"
                + "     , prs_bedrijf p"
                + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                + "   AND dp.bes_disc_params_bestelmode = 3"
                + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                + "   AND sd.bes_srtdeel_key = bi.bes_srtdeel_key"
                + "   AND bi.bes_bestelling_key = b.bes_bestelling_key"
                + "   AND sd.prs_bedrijf_key = p.prs_bedrijf_key"
                + "   AND b.bes_bestelling_status IN (2, 3, 4, 5)" // Artikelen met lopende bestellingen.
                + "   AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                + (params.catalogus_key
                  ? " AND dp.bes_ins_discipline_key = " + params.catalogus_key
                  : "")
                + (params.besgroep_key
                  ? " AND g.bes_srtgroep_key = " + params.besgroep_key
                    + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                  : "")
                + (params.item_key
                  ? " AND sd.bes_srtdeel_key = " + params.item_key
                  : "")
                + (params.searchtekst
                  ? " AND (  UPPER(sd.bes_srtdeel_nr) LIKE " + safe.quoted_sql_wild("%" + params.searchtekst + "%")
                    + "   OR UPPER(sd.bes_srtdeel_omschrijving) LIKE " + safe.quoted_sql_wild("%" + params.searchtekst + "%") + ")"
                  : "")
                + " GROUP BY sd.bes_srtdeel_volgnr"
                + "        , sd.bes_srtdeel_nr"
                + "        , sd.bes_srtdeel_key"
                + "        , sd.bes_srtdeel_omschrijving"
                + "        , g.bes_srtgroep_omschrijving"
                + "        , sd.bes_srtdeel_notitie"
                + "        , dp.bes_ins_discipline_key"
                + "        , bd.ins_discipline_omschrijving"
                + "        , sd.bes_srtdeel_voorraadmax"
                + "        , sd.bes_srtdeel_voorraadmin"
                + "        , sd.bes_srtdeel_maxbestel"
                + "        , sd.bes_srtdeel_minimum"
                + "        , sd.bes_srtdeel_maximum"
                + "        , sd.bes_srtdeel_veelvoud"
                + "        , sd.bes_srtdeel_eenheid"
                + "        , sd.bes_srtdeel_vervaldatum"
                + "        , sd.bes_srtdeel_image"
                + "        , p.prs_bedrijf_image_loc"
                + " UNION "
                // Artikelen zonder lopende bestellingen.
                + "SELECT sd.bes_srtdeel_key"
                + "     , sd.bes_srtdeel_volgnr"
                + "     , sd.bes_srtdeel_nr"
                + "     , sd.bes_srtdeel_omschrijving"
                + "     , g.bes_srtgroep_omschrijving"
                + "     , sd.bes_srtdeel_notitie"
                + "     , dp.bes_ins_discipline_key"
                + "     , bd.ins_discipline_omschrijving"
                + "     , sd.bes_srtdeel_voorraadmax voorraadmax"
                + "     , sd.bes_srtdeel_voorraadmin voorraadmin"
                + "     , sd.bes_srtdeel_maxbestel maxbestel"
                + "     , sd.bes_srtdeel_minimum bestelmin"
                + "     , sd.bes_srtdeel_maximum bestelmax"
                + "     , sd.bes_srtdeel_veelvoud bestelveelvoud"
                + "     , sd.bes_srtdeel_eenheid eenheid"
                + "     , sd.bes_srtdeel_vervaldatum"
                + "     , (SELECT COUNT(*)"
                  + "        FROM bes_kenmerk bk"
                  + "           , bes_srtkenmerk sk"
                  + "           , bes_srtdeel sd2"
                  + "           , bes_srtgroep sg"
                  + "       WHERE sd2.bes_srtgroep_key = sg.bes_srtgroep_key"
                  + "         AND (bk.bes_srtinstallatie_key = sg.ins_discipline_key AND bk.bes_kenmerk_niveau LIKE 'D'"
                  + "              OR bk.bes_srtinstallatie_key = sg.bes_srtgroep_key AND bk.bes_kenmerk_niveau LIKE 'G'"
                  + "              OR bk.bes_srtinstallatie_key = sd2.bes_srtdeel_key AND bk.bes_kenmerk_niveau LIKE 'S')"
                  + "         AND bk.bes_kenmerk_type = 'I'"
                  + "         AND bk.bes_srtkenmerk_key = sk.bes_srtkenmerk_key"
                  + "         AND bk.bes_kenmerk_verwijder IS NULL"
                  + "         AND sk.bes_srtkenmerk_verwijder IS NULL"
                  + "         AND sd2.bes_srtdeel_key = sd.bes_srtdeel_key) aantalkenmerken"
                  + "   , 0 inbestelling"
                  + "   , COALESCE(bes.getsrtdeelprijs(sd.bes_srtdeel_key, null) , 0) prijs"
                  + "   , NVL2(sd.bes_srtdeel_image, p.prs_bedrijf_image_loc || sd.bes_srtdeel_image, NULL) foto"
                + "  FROM bes_discipline bd"
                + "     , bes_v_aanwezigsrtgroep g"
                + "     , bes_v_aanwezigsrtdeel sd"
                + "     , bes_disc_params dp"
                + "     , prs_bedrijf p"
                + " WHERE sd.bes_srtgroep_key = g.bes_srtgroep_key"
                + "   AND dp.bes_disc_params_bestelmode = 3"
                + "   AND g.ins_discipline_key = bd.ins_discipline_key"
                + "   AND bd.ins_discipline_key = dp.bes_ins_discipline_key"
                + "   AND sd.prs_bedrijf_key = p.prs_bedrijf_key"
                + "   AND sd.bes_srtdeel_key NOT IN (SELECT bi.bes_srtdeel_key"
                + "                                   FROM bes_bestelling b"
                + "                                      , bes_bestelling_item bi"
                + "                                  WHERE bi.bes_bestelling_key = b.bes_bestelling_key"
                + "                                    AND b.bes_bestelling_status IN (2, 3, 4, 5))" // Artikelen zonder lopende bestellingen.
                + "   AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                + (params.catalogus_key
                  ? " AND dp.bes_ins_discipline_key = " + params.catalogus_key
                  : "")
                + (params.besgroep_key
                  ? " AND g.bes_srtgroep_key = " + params.besgroep_key
                    + " AND (sd.bes_srtdeel_vervaldatum IS NULL OR sd.bes_srtdeel_vervaldatum > SYSDATE)"
                  : "")
                + (params.item_key
                  ? " AND sd.bes_srtdeel_key = " + params.item_key
                  : "")
                + (params.searchtekst
                  ? " AND (  UPPER(sd.bes_srtdeel_nr) LIKE " + safe.quoted_sql_wild("%" + params.searchtekst + "%")
                    + "   OR UPPER(sd.bes_srtdeel_omschrijving) LIKE " + safe.quoted_sql_wild("%" + params.searchtekst + "%") + ")"
                  : "")
                + " GROUP BY sd.bes_srtdeel_volgnr"
                + "        , sd.bes_srtdeel_nr"
                + "        , sd.bes_srtdeel_key"
                + "        , sd.bes_srtdeel_omschrijving"
                + "        , g.bes_srtgroep_omschrijving"
                + "        , sd.bes_srtdeel_notitie"
                + "        , dp.bes_ins_discipline_key"
                + "        , bd.ins_discipline_omschrijving"
                + "        , sd.bes_srtdeel_voorraadmax"
                + "        , sd.bes_srtdeel_voorraadmin"
                + "        , sd.bes_srtdeel_maxbestel"
                + "        , sd.bes_srtdeel_minimum"
                + "        , sd.bes_srtdeel_maximum"
                + "        , sd.bes_srtdeel_veelvoud"
                + "        , sd.bes_srtdeel_eenheid"
                + "        , sd.bes_srtdeel_vervaldatum"
                + "        , sd.bes_srtdeel_image"
                + "        , p.prs_bedrijf_image_loc";

        sql = "SELECT *"
            + "  FROM (" + sql + ") x"
            + " ORDER BY X.bes_srtdeel_volgnr"
            + "        , x.bes_srtdeel_nr";
        return sql;
      }
    }
%>
