<% /*
     $Revision$
     $Id$
*/

cnt = { setcontractstatus:
           function (cnt_key, cnt_status_key)
           {
             // Deze zet de status en doet dan bijpassende tracking en notificatie
             var sql = "BEGIN cnt.setcontractstatus(" + cnt_key + ", " + cnt_status_key + ", " + user_key + "); END;"
             Oracle.Execute(sql);
             // zou leuk zijn om true of false op te leveren naar gelang de status echt anders is geworden
           },

        trackcontractgoedkeuren:
           function (cnt_key, ptxt)
           {
               shared.trackaction("CNTFIT", cnt_key, ptxt);
           },

       trackcontractupdate:
           // Let op: dit moet wellicht niet altijd (aangeroepen na save)
           function (cnt_key, ptxt)
           {
               shared.trackaction("CNTUPD", cnt_key, ptxt);
           },

        trackcontractverwijderen:
           function (cnt_key, ptxt)
           {
               shared.trackaction("CNTDEL", cnt_key, ptxt);
           },

        getCntLocationsSql:
           function (locNullable)
           {
             // Alleen personen met rechten op de gebouwen of locaties van de contracten mogen goedkeuren.
             // Daarvoor hebben we de gebouwen en locatie van de contracten nodig.
             // LET OP: - type 4 (algemeen / generiek) zit er niet in.
             return " SELECT cp.cnt_contract_key"
                  + "      , 'L' cnt_alg_plaats_code"
                  + "      , cp.cnt_alg_plaats_key"
                  + "      , g.alg_locatie_key"
                  + "      , g.alg_gebouw_key"
                  + "      , NULL alg_verdieping_key"
                  + "      , NULL alg_ruimte_key"
                  + "   FROM cnt_contract_plaats cp"
                  + "      , alg_gebouw g"
                  + "  WHERE cp.cnt_alg_plaats_code = 'L'"
                  + "    AND cp.cnt_alg_plaats_key = g.alg_locatie_key"
                  + " UNION ALL"
                  + " SELECT cp.cnt_contract_key"
                  + "      , 'G'"
                  + "      , cp.cnt_alg_plaats_key onrgoed_key"
                  + "      , g.alg_locatie_key"
                  + "      , g.alg_gebouw_key"
                  + "      , NULL"
                  + "      , NULL"
                  + "   FROM cnt_contract_plaats cp"
                  + "      , alg_gebouw g"
                  + "  WHERE cp.cnt_alg_plaats_code = 'G'"
                  + "    AND cp.cnt_alg_plaats_key = g.alg_gebouw_key"
                  + " UNION ALL"
                  + " SELECT cp.cnt_contract_key"
                  + "      , 'V'"
                  + "      , cp.cnt_alg_plaats_key onrgoed_key"
                  + "      , g.alg_locatie_key"
                  + "      , g.alg_gebouw_key"
                  + "      , v.alg_verdieping_key"
                  + "      , NULL"
                  + "   FROM cnt_contract_plaats cp"
                  + "      , alg_gebouw g"
                  + "      , alg_verdieping v"
                  + "  WHERE cp.cnt_alg_plaats_code = 'V'"
                  + "    AND cp.cnt_alg_plaats_key = v.alg_verdieping_key"
                  + "    AND v.alg_gebouw_key = g.alg_gebouw_key"
                  + " UNION ALL"
                  + " SELECT cp.cnt_contract_key"
                  + "      , 'R'"
                  + "      , cp.cnt_alg_plaats_key onrgoed_key"
                  + "      , g.alg_locatie_key"
                  + "      , g.alg_gebouw_key"
                  + "      , v.alg_verdieping_key"
                  + "      , r.alg_ruimte_key"
                  + "   FROM cnt_contract_plaats cp"
                  + "      , alg_gebouw g"
                  + "      , alg_verdieping v"
                  + "      , alg_ruimte r"
                  + "  WHERE cp.cnt_alg_plaats_code = 'R'"
                  + "    AND cp.cnt_alg_plaats_key = r.alg_ruimte_key"
                  + "    AND r.alg_verdieping_key = v.alg_verdieping_key"
                  + "    AND v.alg_gebouw_key = g.alg_gebouw_key"
                  + " UNION ALL"
                  + " SELECT cp.cnt_contract_key"
                  + "      , 'T'"
                  + "      , cp.cnt_alg_plaats_key onrgoed_key"
                  + "      , t.alg_locatie_key"
                  + "      , cp.cnt_alg_plaats_key" // alias alg_gebouw_key
                  + "      , NULL"
                  + "      , NULL"
                  + "   FROM cnt_contract_plaats cp"
                  + "      , alg_terreinsector t"
                  + "  WHERE cp.cnt_alg_plaats_code = 'T'"
                  + "    AND cp.cnt_alg_plaats_key = t.alg_terreinsector_key"
                  + " UNION ALL"
                  + " SELECT co.cnt_contract_key"
                  + "      , ''"
                  + "      , NULL"
                  + "      , d.ins_alg_locatie_key"
                  + "      , g.alg_gebouw_key"
                  + "      , NULL"
                  + "      , NULL"
                  + "   FROM cnt_contract_object co"
                  + "      , ins_deel d"
                  + "      , alg_gebouw g"
                  + "  WHERE co.cnt_ins_deel_key = d.ins_deel_key"
                  + "    AND d.ins_alg_locatie_key = g.alg_locatie_key" + (locNullable ? "(+)" : "")
                  + (locNullable // Mag de locatie_key leeg zijn?
                    ? ""
                    : "    AND d.ins_alg_locatie_key IS NOT NULL");
           },

        getCntApprovers:
           function (cnt_key)
           { //  Ontvanger(s) = eerste, tweede, derde, vierde of vijfde fiatteur(s). Deze hebben WEB_CNTGO1, WEB_CNTGO2, WEB_CNTGO3, WEB_CNTGO4 en/of WEB_CNTGO5 rechten.
             var approver_arr = [];
             // Tot welk bedrag is er al goedgekeurd.
             var sql = "SELECT cnt_contract_approved"
                     + "     , cnt_contract_kosten"
                     + "  FROM cnt_contract c"
                     + " WHERE cnt_contract_key = " + cnt_key;
             var oRs = Oracle.Execute(sql);
             var kosten = oRs("cnt_contract_kosten").Value? oRs("cnt_contract_kosten").Value : 0;
             var approved = oRs("cnt_contract_approved").Value? oRs("cnt_contract_approved").Value : -1;
             oRs.Close();

             var functie_code;
             if (kosten <= S("cnt_contract_limit1")) // Dit eerst testen i.v.m. Ter goedkeuring. Verder moet sowieso goedgekeurd worden.
               return []; // Het bedrag is lager als de eerste limiet. Het contract hoeft niet goed gekeurd te worden, dus een lege fiatteurs array teruggeven.
             else if ((S("cnt_approval_all") == 0 && approved <= S("cnt_contract_limit1")) || (S("cnt_approval_all") == 1 && kosten <= S("cnt_contract_limit2")))
               functie_code = "WEB_CNTGO1";
             else if ((S("cnt_approval_all") == 0 && approved <= S("cnt_contract_limit2")) || (S("cnt_approval_all") == 1 && kosten <= S("cnt_contract_limit3")))
               functie_code = "WEB_CNTGO2";
             else if ((S("cnt_approval_all") == 0 && approved <= S("cnt_contract_limit3")) || (S("cnt_approval_all") == 1 && kosten <= S("cnt_contract_limit4")))
               functie_code = "WEB_CNTGO3";
             else if ((S("cnt_approval_all") == 0 && approved <= S("cnt_contract_limit4")) || (S("cnt_approval_all") == 1 && kosten <= S("cnt_contract_limit5")))
               functie_code = "WEB_CNTGO4";
             else if ((S("cnt_approval_all") == 0 && approved <= S("cnt_contract_limit5")) || (S("cnt_approval_all") == 1 && kosten > S("cnt_contract_limit5")))
               functie_code = "WEB_CNTGO5";
             else return []; // Het goedgekeurde bedrag zit al boven de vijfde limiet. Geen approval meer nodig.

             // Alleen personen met rechten op de locaties van de contracten mogen goedkeuren.
             // Daarvoor hebben we de locatie van de contracten nodig.
             var sql_cntloc = cnt.getCntLocationsSql();

             // Bepaal de fiatteurs.
             // De functiekey apart bepalen is 15x sneller
             sql = "SELECT fac_functie_key FROM fac_functie WHERE fac_functie_code = " + safe.quoted_sql(functie_code);
             oRs = Oracle.Execute(sql);
             var functie_key = oRs("fac_functie_key").Value;
             oRs.Close();

             // De ALGwritelevel (niveau) van de te bepalen goedkeurders weet ik niet.
             // Dat moet dus in de query zelf opgevraagd worden.
             var AlGwritelevel_GOE = "SELECT COALESCE (MIN (fac_gebruiker_alg_level_write), 9) awrite"
                                   + "  FROM fac_v_webgebruiker w"
                                   + " WHERE w.prs_perslid_key = g.prs_perslid_key"
                                   + "   AND w.fac_functie_key IN (" + functie_key + ")";

             sql = "SELECT DISTINCT g.prs_perslid_key"
                 + "  FROM fac_v_webgebruiker g"
                 + "     , cnt_contract c"
                 + "     , (" + sql_cntloc + ") cntloc"
                 + " WHERE g.fac_functie_key = " + functie_key
                 + "   AND g.ins_discipline_key = c.ins_discipline_key"
                 + "   AND c.cnt_contract_key = " + cnt_key
                 + "   AND c.cnt_contract_key = cntloc.cnt_contract_key(+)"
                 // Als AlGwritelevel_GOE > -1 is dan moet de contract locatie(s) binnen de locatie scope van de goedkeurders zitten.
                 + "   AND (cntloc.cnt_alg_plaats_code = 'L'"
                 + "        AND cntloc.alg_locatie_key IN (SELECT alg_locatie_key FROM fac_v_my_locations"
                 + "                                        WHERE prs_perslid_key = g.prs_perslid_key"
                 + "                                          AND niveau = (" + AlGwritelevel_GOE + "))"
                 // Als AlGwritelevel_GOE > -1 is dan moet het contract gebouw binnen de gebouw scope van de goedkeurders zitten.
                 + "        OR cntloc.alg_gebouw_key IN (SELECT alg_gebouw_key FROM fac_v_my_buildings"
                 + "                                      WHERE prs_perslid_key = g.prs_perslid_key"
                 + "                                        AND niveau = (" + AlGwritelevel_GOE + "))"
                 // Op contracten zonder locatie(s) heeft iedereen rechten.
                 + "        OR cntloc.alg_locatie_key IS NULL"
                 // Heeft een goedkeurder alle CNTGOX rechten dan hoef je niet naar locatie(s) te kijken.
                 + "        OR (" + AlGwritelevel_GOE + ") = -1)";
             oRs = Oracle.Execute(sql);
             while(!oRs.eof)
             {
               approver_arr.push(oRs("prs_perslid_key").Value); // Fiatteur.
               oRs.MoveNext();
             }
             oRs.Close();
             return approver_arr;
           },

        getcntstatustext:
           function (p)
           {
             var statustekst = "??";
             var s = parseInt(p, 10);
             switch (s) {
                 case 0: { statustekst = (S("cnt_contract_approval") == 1? L("lcl_cnt_active_approval") : L("lcl_cnt_active")); break; }
                 case 1: { statustekst = L("lcl_cnt_inactive"); break; }
                 case 2: { statustekst = L("lcl_cnt_new"); break; }
                 case 3: { statustekst = L("lcl_cnt_forapproval"); break; }
             }
             if (__Logging > 0)
               statustekst += " (" + String(p) + ")";
             return statustekst;
           },

        // return the right sql-condition for the given phases
        getfaseconditionsql:
           function (p)
           {
              var fasesql = "";
              var refDateSQL = p.refdate ? (p.refdate).toSQL(false) : "TRUNC(SYSDATE)";

              var addOr = " AND (";
              if (p.cntffutu)
              {
                fasesql = " AND ("+refDateSQL+" < c.cnt_contract_looptijd_van";
                addOr = " OR ";
              }
              if (p.cntfact)
              {
                fasesql += addOr + " ("+refDateSQL+" BETWEEN c.cnt_contract_looptijd_van"
                       + " AND cnt.cnt_getRappeldatum(c.cnt_contract_key))";
                addOr = " OR ";
              }
              if (p.cntfrap)
              {
                fasesql += addOr + " ("+refDateSQL
                       + " BETWEEN cnt.cnt_getRappeldatum(c.cnt_contract_key)"
                       + " AND cnt.cnt_getOpzegdatum(c.cnt_contract_key))";
                addOr = " OR ";
              }
              if (p.cntfopz)
              {
                fasesql += addOr + " ("+refDateSQL
                       + " BETWEEN cnt.cnt_getOpzegdatum(c.cnt_contract_key)"
                       +  " AND c.cnt_contract_looptijd_tot)";
                addOr = " OR ";
              }
              if (p.cntfverl)
              {
                fasesql += addOr + " "+refDateSQL+" > c.cnt_contract_looptijd_tot";
                addOr = " OR ";
              }
              if (addOr == " OR ")
              {
                fasesql += ")";
              }
              return fasesql;
           },

        getfromwherelist_sql:
           function(pautfunction, params)
           {
             var cntsrt_key_arr = params.cntsrt_key_arr;
             var cntnum = params.cntnum;
             var cntVersion = params.cntVersion;
             var dienst_key = params.dienst_key;
             var uitvoerder_key = params.uitvoerder_key;
             var cnt_persoon_key = params.cnt_persoon_key;
             var eigenaar_key = params.eigenaar_key;
             var manager_key = params.manager_key;
             var beheerder_key = params.beheerder_key;
             var reg_key_arr = params.reg_key_arr   || [];
             var dist_key_arr = params.dist_key_arr || [];
             var loc_key_arr = params.loc_key_arr   || [];
             var bld_key_arr = params.bld_key_arr   || [];
             var flr_key_arr = params.flr_key_arr   || [];
             var room_key_arr = params.room_key_arr || [];
             var objectsrt_key = params.objectsrt_key;
             var mantel_key = params.mantel_key;
             var descript = params.descript;
             var ins_key = params.ins_key;
             var kpgrp_key = params.kpgrp_key;
             var kp_key = params.kp_key;
             var ksgrp_key = params.ksgrp_key;
             var ks_key = params.ks_key;
             // Statussen.
             var cntAct = params.cntAct;
             var cntInact = params.cntInact;
             var cntNew = params.cntNew;
             var cntTgoe = params.cntTgoe;
             // Fases binnen status Acief
             var cntFFutu = params.cntFFutu;
             var cntFAct = params.cntFAct;
             var cntFRap = params.cntFRap;
             var cntFOpz = params.cntFOpz;
             var cntFVerl = params.cntFVerl;

             var cntOldVers = params.cntOldVers;
             var refDate = params.refDate;
             var grp_sel = params.grp_sel;
             var mobile = params.mobile == 1;
             var tiny = params.tiny;
             var cntNotclosed = params.cntNotclosed;

             if (cntNotclosed)
             {  // Alle niet gesloten contracten zien: dus deze vinkjes zetten.
                // Ook nieuwe en ter goedkeuring.
                cntAct   = true;
                // cntInact = false;
                cntFFutu = true;
                cntFAct  = true;
                cntFRap  = true;
                cntFOpz  = true;
                cntFVerl = true;
                cntNew   = true;
                cntTgoe  = true;
             }

             var outputmode = params.outputmode; // print to 0 = screen, 1 = printer, 2 = excel, etc.
             var print = (outputmode == 1 || outputmode == 5);
             var excel = (outputmode == 2 || outputmode == 6);

             // Voeg laatste tracking datum toe
             sqltrack = ", (SELECT MAX(t.fac_tracking_datum)"
                      + "     FROM fac_tracking t"
                      + "        , fac_srtnotificatie sn"
                      + "    WHERE t.fac_srtnotificatie_key = sn.fac_srtnotificatie_key"
                      + "      AND t.fac_tracking_refkey = c.cnt_contract_key" // contract key uit "sql"
                      + "      AND sn.fac_srtnotificatie_xmlnode = 'contract') recentdatum";

             //PCHD#88955: de prs_v_afdeling maakt de query soms enorm traag
             //            voorkom dat door indien mogelijk prs_v_afdeling_fullnames te gebruiken, die is veel lichter
             var simpledepstring = inArray(S("prs_dep_string"), "d.prs_afdeling_naam1,d.prs_afdeling_naam2,d.prs_afdeling_naam3,d.prs_afdeling_naam4,d.prs_afdeling_naam5,d.prs_afdeling_naam6".split(","))
             if (simpledepstring)
             {
                sql =  "WITH  slowafd as (select * from prs_v_afdeling_fullnames) "
             }
             else
             {
                sql =  "WITH  slowafd as (select * from prs_v_afdeling) "
             }
             sql +="SELECT c.cnt_contract_nummer"
                 + "     , c.cnt_contract_versie"
                 + "     , c.cnt_contract_omschrijving"
                 + "     , c.cnt_contract_opmerking"
                 + "     , c.cnt_contract_document"
                 + "     , COALESCE(b.prs_bedrijf_naam, af" + S("prs_dep_string") + ", " + S("prs_pers_string") + ") uitvoerder" // af + S("prs_dep_string") heeft parameter afd.
                 + "     , " + S("prs_dep_string") + " eigenaar"
                 + "     , c.cnt_contract_looptijd_van begindatum"
                 + "     , c.cnt_contract_looptijd_tot einddatum"
                 + "     , cnt.cnt_getOpzegdatum(c.cnt_contract_key) cnt_opzegdatum"
                 + "     , cnt.cnt_getRappeldatum(c.cnt_contract_key) cnt_rappeldatum"
                 + "     , cnt.cnt_contract_status("
                   + "       c.cnt_contract_looptijd_van"
                   + "     , cnt.cnt_getRappeldatum(c.cnt_contract_key)"
                   + "     , cnt.cnt_getOpzegdatum(c.cnt_contract_key)"
                   + "     , c.cnt_contract_looptijd_tot) fase_actief"
                 + "     , c.cnt_contract_status"
                 + "     , c.cnt_contract_key cnt_contract_key"
                 + "     , COALESCE(c.ins_discipline_key, -1) disc_key"
                 + "     , c.prs_afdeling_key_eig eigenaar_key"
                 + "     , c.cnt_contract_nummer_intern"
                 + "     , dp.cnt_srtcontract_type"
                 + "     , cloc.alg_locatie_oms"
                 + "     , cloc.alg_locatie_omschrijving"
                 + "     , alg_district_omschrijving"
                 + "     , cloc.alg_locatie_code"
                 + "     , cloc.alg_gebouw_code"
                 + "     , cloc.alg_verdieping_code"
                 + "     , cloc.alg_ruimte_nr"
                 + "     , cloc.alg_locatie_count"
                 + "     , cloc.alg_gebouw_count"
                 + "     , cloc.alg_verdieping_count"
                 + "     , cloc.alg_ruimte_count"
                 + "     , c.ins_discipline_key"
                 + "     , " + lcl.xsqla('cd.ins_discipline_omschrijving', 'cd.ins_discipline_key')
                 + "     , c.cnt_contract_kosten"
                 + "     , di.prs_dienst_omschrijving"
                 + "     , (SELECT prs_kostenplaatsgrp_oms"
                         + "  FROM prs_kostenplaatsgrp"
                         + " WHERE prs_kostenplaatsgrp_key = kp.prs_kostenplaatsgrp_key) kostenplaatsgrp"
                 + "     , (SELECT " + S("prs_kpn_string")
                         + "  FROM prs_kostenplaats k"
                         + " WHERE k.prs_kostenplaats_key = c.prs_kostenplaats_key) kostenplaats"
                 + "     , (SELECT prs_perslid_naam_full"
                   + "        FROM prs_v_perslid_fullnames_all pf"
                   + "       WHERE pf.prs_perslid_key = c.prs_perslid_key_beh) perslid_naam_beh"
                 + "     , (SELECT prs_perslid_naam_full"
                   + "        FROM prs_v_perslid_fullnames_all pf"
                   + "       WHERE pf.prs_perslid_key = c.prs_perslid_key_eig) manager"
                 + "     , CASE WHEN c.cnt_contract_verlenging = -1 THEN " + safe.qL("lcl_unknown")
                 + "            WHEN c.cnt_contract_verlenging = 0 OR c.cnt_contract_verlenging = 2 THEN " + safe.qL("lcl_No")
                 + "            WHEN c.cnt_contract_verlenging = 1 OR c.cnt_contract_verlenging = 3 THEN " + safe.qL("lcl_Yes")
                 + "            WHEN c.cnt_contract_verlenging = 5 THEN " + safe.qL("lcl_cnt_prolongation_auto")
                 + "       END verlenging"
                 + "     , (SELECT cnt_termijn_omschrijving"
                   + "        FROM cnt_termijn"
                   + "       WHERE cnt_termijn_key = c.cnt_contract_termijntermijn) factuur_termijn"
                 + "     , (SELECT cnt_termijn_omschrijving"
                   + "        FROM cnt_termijn"
                   + "       WHERE cnt_termijn_key = c.cnt_contract_opzegtermijn) opzeg_termijn"
                 + "     , (SELECT cnt_termijn_omschrijving"
                   + "        FROM cnt_termijn"
                   + "       WHERE cnt_termijn_key = c.cnt_contract_rappeltermijn) rappel_termijn"
                 + "     , (SELECT cnt_termijn_omschrijving"
                   + "        FROM cnt_termijn"
                   + "       WHERE cnt_termijn_key = c.cnt_contract_verleng_termijn) verleng_termijn"
                 + "     , c.cnt_contract_termijnkosten"
                 + "     , c.cnt_contract_korting"
                 + "     , c.cnt_contract_uurloon"
                 + "     , (SELECT cnt_contract_nummer_intern"
                   + "          || CASE WHEN cnt_contract_versie IS NOT NULL"
                   + "                  THEN '.' || cnt_contract_versie"
                   + "             END"
                   + "          || ' - ' || cnt_contract_omschrijving"
                   + "        FROM cnt_contract"
                   + "       WHERE cnt_contract_key = c.cnt_contract_mantel_key) mantel"
                 + "     , (SELECT prs_contactpersoon_naam"
                   + "          || CASE WHEN prs_contactpersoon_voornaam IS NOT NULL"
                   + "                  THEN ' (' || prs_contactpersoon_voornaam || ')'"
                   + "             END"
                   + "        FROM prs_contactpersoon"
                   + "       WHERE prs_contactpersoon_key = c.prs_contactpersoon_key) contactpersoon"
                 + "     , (SELECT prs_perslid_naam_full"
                   + "        FROM prs_v_perslid_fullnames"
                   + "       WHERE prs_perslid_key = c.cnt_prs_perslid_key) persoon"
                 + sqltrack
                 + "  FROM prs_v_aanwezigbedrijf b"
                 + "     , cnt_v_aanwezigcontract c"
                 + "     , prs_dienst di"
                 + "     , prs_kostenplaats kp"
                 + (ksgrp_key
                   ? "   , prs_kostensoort ks"
                   : "")
                 + "     , slowafd d"
                 + "     , slowafd afd"
                 + "     , prs_perslid p"
                 + "     , cnt_disc_params dp"
                 + "     , cnt_discipline cd";

             // Om drie redenen hebben we de locatie_key nodig in de hoofd query
             //   - Voor als de gebruiker filtert op locatie (optioneel)
             //   - Voor als de gebruiker beperkte autorisatie heeft (optioneel)
             //   - Om de locatieomschrijving in de lijst te kunnen tonen (niet bij maninfo)
             // Voor die eerste twee is sql_cnt_loc_keyA die bij contracten met meerdere locaties alles bevat
             //  Voor de tweede is sql_cnt_loc_key die groeppeert en telt per locatie
             // LET OP: - type 4 (algemeen / generiek) zit er niet in
             var sql_cnt_loc_keyA = cnt.getCntLocationsSql(true);
             var sql_cnt_loc_key = " WITH alg_onrgoed AS"
                                 + "    ( SELECT o.alg_type  alg_level"
                                 + "           , o.alg_onroerendgoed_keys  alg_key"
                                 + "           , o.alg_onroerendgoed_code  alg_code"
                                 + "           , o.alg_onroerendgoed_omschrijving  alg_omschrijving"
                                 + "           , o.alg_plaatsaanduiding"
                                 + "           , d.alg_district_key"
                                 + "           , d.alg_district_omschrijving"
                                 + "           , l.alg_locatie_key"
                                 + "           , l.alg_locatie_code"
                                 + "           , l.alg_locatie_omschrijving"
                                 + "           , o.alg_terreinsector_key"
                                 + "           , o.alg_terreinsector_code"
                                 + "           , o.alg_terreinsector_naam"
                                 + "           , o.alg_gebouw_key"
                                 + "           , o.alg_gebouw_code"
                                 + "           , o.alg_gebouw_naam"
                                 + "           , o.alg_verdieping_key"
                                 + "           , o.alg_verdieping_code"
                                 + "           , o.alg_verdieping_omschrijving"
                                 + "           , o.alg_ruimte_key"
                                 + "           , o.alg_ruimte_nr"
                                 + "           , o.alg_ruimte_omschrijving"
                                 + "        FROM alg_district d"
                                 + "           , alg_locatie l"
                                 + "           , alg_v_onroerendgoed_gegevens o"
                                 + "       WHERE l.alg_district_key = d.alg_district_key(+)"
                                 + "         AND l.alg_locatie_key = o.alg_locatie_key"
                                 + "      UNION"
                                 + "      SELECT 'L'                         alg_level"
                                 + "           , l.alg_locatie_key           alg_key"
                                 + "           , l.alg_locatie_code          alg_code"
                                 + "           , l.alg_locatie_omschrijving  alg_omschrijving"
                                 + "           , l.alg_locatie_code          alg_plaatsaanduiding"
                                 + "           , d.alg_district_key"
                                 + "           , d.alg_district_omschrijving"
                                 + "           , l.alg_locatie_key"
                                 + "           , l.alg_locatie_code"
                                 + "           , l.alg_locatie_omschrijving"
                                 + "           , NULL alg_terreinsector_key"
                                 + "           , NULL alg_terreinsector_code"
                                 + "           , NULL alg_terreinsector_naam"
                                 + "           , NULL alg_gebouw_key"
                                 + "           , NULL alg_gebouw_code"
                                 + "           , NULL alg_gebouw_naam"
                                 + "           , NULL alg_verdieping_key"
                                 + "           , NULL alg_verdieping_code"
                                 + "           , NULL alg_verdieping_omschrijving"
                                 + "           , NULL alg_ruimte_key"
                                 + "           , NULL alg_ruimte_nr"
                                 + "           , NULL alg_ruimte_omschrijving"
                                 + "        FROM alg_locatie l"
                                 + "           , alg_district d"
                                 + "       WHERE l.alg_district_key = d.alg_district_key(+)"
                                 + "    )"
                                 + ""
                                 + "SELECT MIN(ll.alg_locatie_omschrijving || ' (' || ll.alg_locatie_code || ')') alg_locatie_oms"
                                 + "     , MIN(ll.alg_district_omschrijving) alg_district_omschrijving"
                                 + "     , MIN(ll.alg_locatie_omschrijving) alg_locatie_omschrijving"
                                 + "     , MIN(ll.alg_locatie_code) alg_locatie_code"
                                 + "     , MIN(ll.alg_gebouw_code) alg_gebouw_code"
                                 + "     , MIN(ll.alg_verdieping_code) alg_verdieping_code"
                                 + "     , MIN(ll.alg_ruimte_nr) alg_ruimte_nr"
                                 + "     , MIN(ll.alg_district_key) alg_district_key"
                                 + "     , cnt_contract_key"
                                 + "     , MIN(ll.alg_locatie_key) alg_locatie_key"
                                 + "     , COUNT(DISTINCT ll.alg_locatie_code) alg_locatie_count"
                                 + "     , COUNT(DISTINCT ll.alg_gebouw_code) alg_gebouw_count"
                                 + "     , COUNT(DISTINCT ll.alg_verdieping_code) alg_verdieping_count"
                                 + "     , COUNT(DISTINCT ll.alg_ruimte_nr) alg_ruimte_count"
                                 + "  FROM alg_onrgoed ll"
                                 + "     , (" + sql_cnt_loc_keyA + ") scloc"
                                 + "  WHERE ll.alg_level = scloc.cnt_alg_plaats_code"
                                 + "    AND ll.alg_key = scloc.cnt_alg_plaats_key"
                                 + " GROUP BY scloc.cnt_contract_key";

             sql += ", (" + sql_cnt_loc_key + ") cloc";

             sql += " WHERE c.cnt_prs_bedrijf_key = b.prs_bedrijf_key(+)"
                  + " AND c.cnt_prs_afdeling_key = afd.prs_afdeling_key(+)"
                  + " AND c.cnt_prs_perslid_key = p.prs_perslid_key(+)"
                  + " AND c.prs_dienst_key = di.prs_dienst_key(+)"
                  + " AND c.prs_kostenplaats_key = kp.prs_kostenplaats_key(+)"
                  + " AND d.prs_afdeling_key = c.prs_afdeling_key_eig"
                  + " AND c.ins_discipline_key = dp.cnt_ins_discipline_key"
                  + " AND c.ins_discipline_key = cd.ins_discipline_key"
                  + " AND cloc.cnt_contract_key(+) = c.cnt_contract_key";

             if (cntsrt_key_arr && cntsrt_key_arr.length)
               sql += " AND c.ins_discipline_key IN (" + cntsrt_key_arr.join(",") + ")";

             sql += getKenmerkSql("CNT", "c.cnt_contract_key", true);

             // Dienst.
             if (dienst_key)
             {
               sql += " AND (c.prs_dienst_key = " + dienst_key
                   +  "      OR (c.prs_dienst_key IS NULL "
                   +  "          AND EXISTS (SELECT '' FROM prs_bedrijfdienstlocatie dl "
                   +  "                       WHERE dl.prs_bedrijf_key = b.prs_bedrijf_key AND dl.prs_dienst_key = " + dienst_key + ")))";
             }

             // Uitvoerder.
             if (uitvoerder_key)
               sql += " AND b.prs_bedrijf_key = " + uitvoerder_key;

             // Persoon (Contractpartij).
             if (cnt_persoon_key)
               sql += " AND c.cnt_prs_perslid_key = " + cnt_persoon_key;

             // Mantel.
             if (mantel_key)
               sql += " AND c.cnt_contract_mantel_key = " + mantel_key;

             // Afdeling (Eigenaar).
             if (eigenaar_key)
               sql += " AND c.prs_afdeling_key_eig = " + eigenaar_key;

             // Verantwoordelijk manager.
             if (manager_key)
               sql += " AND c.prs_perslid_key_eig = " + manager_key;

             // Beheerder.
             if (beheerder_key)
               sql += " AND c.prs_perslid_key_beh = " + beheerder_key;

             // Regio, District, Locatie en gebouw. En terrein, verdieping ruimte.
             // Die laatste 2 komen er nu bij, het was zinnig om onderstaand stukje iets te structureren
             // De intentie is dat als je filtert op een niveau je ook de contracten daaronder meeneemt, dus de locatiecontracten
             // zijn ook de contracten op de gebouwen enz binnen de locatie enz.
             // Soms geeft men meer parameters mee, daarom werken we van onder naar boven.
             if (room_key_arr.length) {
                sql += " AND c.cnt_contract_key IN"
                     + " (SELECT cnt_contract_key FROM cnt_v_aanwezigcontract_plaats"
                     + " WHERE (cnt_alg_plaats_code = 'R' AND cnt_alg_plaats_key IN (" + room_key_arr.join(",") + ")))";
                // TODO de contracten op objecten in deze ruimte
             }
             else if (flr_key_arr.length) {
                sql += " AND c.cnt_contract_key IN"
                     + " (SELECT cnt_contract_key FROM cnt_v_aanwezigcontract_plaats"
                     + "   WHERE (cnt_alg_plaats_code = 'V' AND cnt_alg_plaats_key IN (" + flr_key_arr.join(",") + "))"
                     + "      OR (cnt_alg_plaats_code = 'R' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_ruimte_key FROM alg_v_aanwezigruimte WHERE alg_verdieping_key IN (" + flr_key_arr.join(",") + "))))";
                // TODO de contracten op objecten op deze verdieping
             }
             else if (bld_key_arr.length) {
                sql += " AND c.cnt_contract_key IN"
                     + " (SELECT cnt_contract_key FROM cnt_v_aanwezigcontract_plaats"
                     + "   WHERE (cnt_alg_plaats_code = 'G' AND cnt_alg_plaats_key IN (" + bld_key_arr.join(",") + "))"
                     + "      OR (cnt_alg_plaats_code = 'T' AND cnt_alg_plaats_key IN (" + bld_key_arr.join(",") + "))"
                     + "      OR (cnt_alg_plaats_code = 'V' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_verdieping_key FROM alg_v_aanwezigverdieping WHERE alg_gebouw_key IN (" + bld_key_arr.join(",") + ")))"
                     + "      OR (cnt_alg_plaats_code = 'R' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_ruimte_key FROM alg_v_aanwezigruimte r, alg_verdieping v"
                     +           " WHERE r.alg_verdieping_key=v.alg_verdieping_key AND v.alg_gebouw_key IN (" + bld_key_arr.join(",") + "))))";
                // TODO de contracten op objecten in dit gebouw
             }
             else if (reg_key_arr.length || dist_key_arr.length || loc_key_arr.length) {
                // Merk op dat we hier niet kunnen verwijzen naar cloc binnen sql omdat die MIN(alg_locatie_key) en MIN(alg_gebouw_key) bevat.
                // We hebben geen contracten op regio of districtsniveau, het begint vanaf locatie
                if (loc_key_arr.length)
                    sql_loc = loc_key_arr.join(",");
                else if (dist_key_arr.length)
                    sql_loc = "SELECT alg_locatie_key"
                            + "  FROM alg_locatie"
                            + " WHERE alg_district_key IN (" + dist_key_arr.join(",") + ")";
                else if (reg_key_arr.length)
                    sql_loc = "SELECT alg_locatie_key"
                            + "  FROM alg_locatie l, alg_district d"
                            + " WHERE l.alg_district_key = d.alg_district_key AND d.alg_regio_key IN (" + reg_key_arr.join(",") + ")";

                sql += " AND c.cnt_contract_key IN"
                     + " (SELECT cnt_contract_key FROM cnt_v_aanwezigcontract_plaats"
                     + "   WHERE (cnt_alg_plaats_code = 'L' AND cnt_alg_plaats_key IN (" + sql_loc + "))"
                     // en dan nu dus nog de lagere, de OR van alle gebouwen binnen de locatie(s)
                     + "      OR (cnt_alg_plaats_code = 'G' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_gebouw_key FROM alg_v_aanweziggebouw WHERE alg_locatie_key IN (" + sql_loc + ")))"
                     + "      OR (cnt_alg_plaats_code = 'T' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_terreinsector_key FROM alg_v_aanwezigterreinsector WHERE alg_locatie_key IN (" + sql_loc + ")))"
                     + "      OR (cnt_alg_plaats_code = 'V' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_verdieping_key FROM alg_v_aanwezigverdieping"
                     +          " WHERE alg_gebouw_key IN (SELECT alg_gebouw_key FROM alg_v_aanweziggebouw WHERE alg_locatie_key IN (" + sql_loc + "))))"
                     + "      OR (cnt_alg_plaats_code = 'R' AND cnt_alg_plaats_key IN "
                     +          "(SELECT alg_ruimte_key FROM alg_v_aanwezigruimte r, alg_verdieping v"
                     +           " WHERE r.alg_verdieping_key=v.alg_verdieping_key"
                     +             " AND v.alg_gebouw_key IN (SELECT alg_gebouw_key FROM alg_v_aanweziggebouw WHERE alg_locatie_key IN (" + sql_loc + "))))";

                 // De contracten op objecten op deze locatie(s)
                 sql += " UNION SELECT cnt_contract_key FROM cnt_v_aanwezigcontract_object co, ins_v_aanwezigdeel ad"
                      + " WHERE cnt_ins_deel_key = ad.ins_deel_key AND ad.ins_alg_locatie_key IN (" + sql_loc + "))";
            }


             // Objectsoort.
             if (objectsrt_key)
             {
               sql += " AND c.cnt_contract_key IN "
                    + " (SELECT cnt_contract_key FROM cnt_v_aanwezigcontract_object"
                    + " WHERE cnt_ins_srtdeel_key = " + objectsrt_key +")";
             // we assume that srtdeel is defined if deel is defined. It is.
             //     + " OR cnt_ins_deel_key IN "
             //     + "(SELECT ins_deel_key FROM ins_v_aanwezigdeel WHERE ins_srtdeel_key = " + objectsrt_key + "))";
             }
             if (ins_key)
             {
               sql += " AND c.cnt_contract_key IN "
                    + " (SELECT DISTINCT cnt_contract_key"
                    + "    FROM (SELECT   cnt_contract_key"
                    + "            FROM cnt_contract_object"
                    + "           WHERE cnt_ins_deel_key =" + ins_key + ""
                    + "          UNION"
                    + "          SELECT co.cnt_contract_key"
                    + "            FROM cnt_v_aanwezigcontract_object co"
                    + "               , ins_deel d"
                    + "               , cnt_v_aanwezigcontract_plaats ccp"
                    + "               , alg_v_allonroerendgoed aao"
                    + "           WHERE cnt_ins_deel_key IS NULL"
                    + "             AND co.cnt_ins_srtdeel_key = d.ins_srtdeel_key"
                    + "             AND d.ins_deel_key =" + ins_key + ""
                    + "             AND ccp.cnt_contract_key = co.cnt_contract_key"
                    + "             AND COALESCE (d.ins_alg_ruimte_type_org,"
                    + "                           ins_alg_ruimte_type) = 'R'"
                    + "             AND COALESCE (d.ins_alg_ruimte_key_org,"
                    + "                           ins_alg_ruimte_key) = aao.alg_ruimte_key"
                    + "             AND ( (ccp.cnt_alg_plaats_code = 'L'"
                    + "                    AND ccp.cnt_alg_plaats_key = aao.alg_locatie_key)"
                    + "                  OR (ccp.cnt_alg_plaats_code = 'G'"
                    + "                      AND ccp.cnt_alg_plaats_key = aao.alg_gebouw_key))"
                    + "          UNION"
                    + "          SELECT co.cnt_contract_key"
                    + "            FROM cnt_v_aanwezigcontract_object co"
                    + "               , ins_deel d"
                    + "           WHERE cnt_ins_deel_key IS NULL"
                    + "             AND co.cnt_ins_srtdeel_key = d.ins_srtdeel_key"
                    + "             AND d.ins_deel_key =" + ins_key + ""
                    + "             AND (co.cnt_contract_key NOT IN"
                    + "                       (SELECT cnt_contract_key"
                    + "                          FROM cnt_v_aanwezigcontract_plaats)"
                    + "                  OR COALESCE (d.ins_alg_ruimte_type_org,"
                    + "                               ins_alg_ruimte_type) != 'R')))";
              }

             if (kpgrp_key)
             {
               sql += " AND kp.prs_kostenplaatsgrp_key = " + kpgrp_key;
             }
             if (kp_key)
             {
               sql += " AND c.prs_kostenplaats_key = " + kp_key;
             }

             if (ksgrp_key)
             {
                sql += " AND c.prs_kostensoort_key = ks.prs_kostensoort_key"
                     + " AND ks.prs_kostensoortgrp_key = " + ksgrp_key;
             }

             if (ks_key)
             {
                // Ook die van het contractsoort beschouwen, het gaat om de geldende ks, niet per se de geregistreerde
                // deze is niks sneller: sql += " AND (c.prs_kostensoort_key = " + ks_key + " OR (cd.prs_kostensoort_key = " + ks_key + " AND c.prs_kostensoort_key IS NULL))";
                sql += " AND COALESCE(c.prs_kostensoort_key, cd.prs_kostensoort_key) = " + ks_key;
             }

             // Beschrijving
             if (descript)
             {
               sql += " AND UPPER(c.cnt_contract_omschrijving) LIKE " + safe.quoted_sql_wild("%"+descript+"%");
             }

             // we don't use status field because we don't have mechanism to change its value
             // in case of mld_melding status was changed as the result of user's actions
             // here it gets changed as the result of current date changing

             // Contract number
             if (cntnum)
             {
                 var cntNumber = cntnum;
                 var cntVerion = "";
                 var arr = cntnum.split(".");
                 if (arr.length == 2)
                 {
                   cntNumber = arr[0];
                   cntVersion = arr[1];
                   sql += " AND ((UPPER(c.cnt_contract_nummer_intern) LIKE " + safe.quoted_sql_wild(cntNumber)
                        + "       AND UPPER(c.cnt_contract_versie) LIKE " + safe.quoted_sql_wild(cntVersion) + ")"
                        + "      OR UPPER(c.cnt_contract_nummer) LIKE " + safe.quoted_sql_wild(cntnum) + ")";
                 }
                 else if (arr.length == 1)
                 {
                   cntNumber = arr[0];
                   sql += " AND ((UPPER(c.cnt_contract_nummer_intern) like " + safe.quoted_sql_wild(cntNumber)
                        + "       AND c.cnt_contract_key = (SELECT MAX (c1.cnt_contract_key)"
                        + "                                   FROM cnt_contract c1"
                        + "                                  WHERE c1.cnt_contract_nummer_intern = c.cnt_contract_nummer_intern" // upper lijkt me zonder userinput niet nodig, en scheelt indexgebruik
                        + "                                    AND c1.cnt_contract_verwijder IS NULL))"
                        + "      OR UPPER(c.cnt_contract_nummer) LIKE " + safe.quoted_sql_wild(cntnum)
                        + ")"
                 }
                 else
                 {
                   sql += " AND (UPPER(c.cnt_contract_nummer) LIKE " + safe.quoted_sql_wild(cntnum)
                        + "      OR UPPER(c.cnt_contract_nummer_intern) LIKE " + safe.quoted_sql_wild(cntnum) + ")";
                 }
             }
             else
             {
               // Ik beschouw standaard alleen de hoogste versie en kijk daarvan naar status en zo
               // dus niet dat als ik op een status filter, de laatste versie daar niet aan voldoet
               // maar de eerdere versie wel dat ik dan die eerdere versie toon. Semantisch wenselijkst imho
               if (!cntOldVers) {
                 sql += " AND (   c.cnt_contract_looptijd_tot >= TRUNC(SYSDATE)"
                      + "      OR c.cnt_contract_key = (SELECT MAX (c1.cnt_contract_key)"
                      + "                                 FROM cnt_contract c1"
                      + "                                WHERE c1.cnt_contract_nummer_intern = c.cnt_contract_nummer_intern"
                      + "                                  AND c1.cnt_contract_verwijder IS NULL))";
               }
               var statussen = "";
               var komma = ", ";
               var actief = false;
               var sqlactief = "";
               if (cntAct)
               {
                 //statussen = "0", en dan ook naar de fases binnen de status Actief kijken.
                 sqlactief += " (c.cnt_contract_status = 0"
                            + cnt.getfaseconditionsql({cntffutu: cntFFutu, cntfact: cntFAct, cntfrap: cntFRap, cntfopz: cntFOpz, cntfverl: cntFVerl, refdate: refDate})
                            + ")";
               }
               if (cntInact)
                 statussen += "1";
               if (cntNew)
                 statussen += (statussen != ""? komma : "") + "2";
               if (cntTgoe)
                 statussen += (statussen != ""? komma : "") + "3";
               var sqlINT = statussen == ""? "" :  " (c.cnt_contract_status IN (" + statussen + "))";

               if (sqlactief != "" && sqlINT != "")
                 sql += " AND (" + sqlactief + " OR" + sqlINT + ")";
               else if (sqlactief != "" || sqlINT != "")
                 sql += " AND" + sqlactief + sqlINT; // Één van beide is een lege string.
               else
                 sql += " AND 1 = 0";
             }

             // scope
             // sql bevat al wel een alg_locatie_key maar er zit een group-by (en een MIN) in
             // wat te streng is voor scope
             // Daarom teruggrijpen op sql_cnt_loc_keyA die nog geen group-by op contract heeft gedaan
             sql_scope = " SELECT cnt_contract_key"
                       + "   FROM (SELECT cc.cnt_contract_key"
                         + "            , ins_discipline_key"
                         + "            , di.alg_regio_key"
                         + "            , ll.alg_district_key"
                         + "            , clk.alg_locatie_key"
                         + "            , clk.alg_gebouw_key"
                         + "         FROM (" + sql_cnt_loc_keyA + ") clk"
                         + "            , cnt_contract cc"
                         + "            , alg_locatie ll"
                         + "            , alg_district di"
                         + "        WHERE cc.cnt_contract_key = clk.cnt_contract_key"
                         + "          AND ll.alg_locatie_key(+) = clk.alg_locatie_key" // persoons/afdelingsgebonden objecten hebben geen ins_alg_locatie_key vandaar (+)
                         + "          AND ll.alg_district_key = di.alg_district_key(+)" // persoons/afdelingsgebonden objecten hebben geen ins_alg_locatie_key vandaar (+)
                         + "      ) sc"
                       + "      , prs_v_afdeling_boom boom"
                       + "  WHERE boom.prs_afdeling_key = c.prs_afdeling_key_eig";

             // Autorisatie voor ALG (cnt_contract_plaats) en PRS (cnt_contract.prs_afdeling_key_eig)
             sql_scope = discx3d (sql_scope,
                                  "sc.ins_discipline_key",
                                  "sc.alg_regio_key",
                                  "sc.alg_district_key",
                                  "sc.alg_locatie_key",
                                  "sc.alg_gebouw_key",
                                  "", // verdieping not supported
                                  "", // ruimte not supported
                                  "boom.prs_bedrijf_key",
                                  "boom.prs_afdeling_key",
                                  pautfunction,
                                  (!cntnum && cntsrt_key_arr? cntsrt_key_arr : []),
                                  2);

             // Scopeloos contract of nog geen scope toegekend. Alleen disc en eigenaar controleren
             sql_scopeloos = "SELECT cnt_contract_key"
                           + "  FROM cnt_contract c"
                           + "     , prs_v_afdeling_boom boom"
                           + " WHERE NOT EXISTS (SELECT cnt_contract_key"
                             + "                   FROM cnt_contract_plaats cp"
                             + "                  WHERE cp.cnt_contract_key = c.cnt_contract_key)"
                           + "   AND NOT EXISTS (SELECT cnt_contract_key"
                             + "                   FROM cnt_contract_object co"
                             + "                  WHERE co.cnt_contract_key = c.cnt_contract_key"
                           + "   AND co.cnt_ins_deel_key IS NOT NULL)"  // alleen de contracten met objecten uitsluiten. Niet de contracten met contractsoorten uitsluiten.
                           + "   AND boom.prs_afdeling_key = c.prs_afdeling_key_eig";

             // Autorisatie voor PRS (cnt_contract.prs_afdeling_key_eig)
             sql_scopeloos = discx3d (sql_scopeloos,
                                      "c.ins_discipline_key",
                                      "", // regio not supported
                                      "", // district not supported
                                      "", // locatie not supported
                                      "", // gebouw not supported
                                      "", // verdieping not supported
                                      "", // ruimte not supported
                                      "boom.prs_bedrijf_key",
                                      "boom.prs_afdeling_key",
                                      pautfunction,
                                      (cntsrt_key_arr? cntsrt_key_arr : []),
                                      1);

             // En de contracten waarvan ik eigenaar of beheerder ben, ook al zouden die verder buiten de scope vallen
             sql_mine = "SELECT cnt_contract_key FROM cnt_contract WHERE c.prs_perslid_key_beh = " + user_key + " OR c.prs_perslid_key_eig = " + user_key;

             sql = sql + " AND c.cnt_contract_key IN (" + sql_scope + " UNION ALL " + sql_scopeloos + " UNION ALL " + sql_mine + ")"
                 + (grp_sel == "" || grp_sel == null
                   ? ""
                   : " AND ins_discipline_omschrijving = " + safe.quoted_sql(grp_sel));

             // Op datum (c.cnt_contract_looptijd_tot) sorteren: UWVA#13274 en daarbinnen op c.cnt_contract_nummer en c.cnt_contract_nummer_intern: UWVA#14609
             // Als tiny (framed) dan ook sorteren op status en fase
             sql += " ORDER BY" + (excel || mobile? " UPPER("+ lcl.xsql('cd.ins_discipline_omschrijving','cd.ins_discipline_key') +")," : "")
                  + (mobile
                    ? "       uitvoerder"
                      + "   , cnt_contract_omschrijving"
                    :  (tiny
                       ? "  c.cnt_contract_status"
                        + "  , decode(cnt.cnt_contract_status (c.cnt_contract_looptijd_van, cnt.cnt_getRappeldatum (c.cnt_contract_key), cnt.cnt_getOpzegdatum (c.cnt_contract_key), c.cnt_contract_looptijd_tot), 4, 2, 1)"
                        + "  , c.cnt_contract_looptijd_tot"
                       :  "  c.cnt_contract_looptijd_tot")
                    + "  , c.cnt_contract_nummer")
                  + "      , c.cnt_contract_nummer_intern"
                  + "      , c.cnt_contract_key";  // om het deterministisch te maken bij versies, nodig voor mobile

             return sql;
           },

        findSenderForNotifications: function (cnt_key)
        {
          var sql = "SELECT MAX (cd.ins_discipline_email) email"
                  + "  FROM cnt_contract c"
                  + "     , cnt_discipline cd"
                  + " WHERE c.ins_discipline_key = cd.ins_discipline_key"
                  + "   AND c.cnt_contract_key = " + cnt_key;
          var oRs = Oracle.Execute(sql);
          var lsender = oRs("email").Value;
          oRs.Close();
          if (lsender == null)
          {
            sql = "SELECT MAX(email) email"
                + "  FROM (SELECT l.alg_locatie_email email"
                + "          FROM cnt_contract_plaats"
                + "             , alg_locatie l"
                + "         WHERE cnt_alg_plaats_key = l.alg_locatie_key"
                + "           AND cnt_alg_plaats_code = 'L'"
                + "           AND cnt_contract_plaats_verwijder IS NULL"
                + "           AND cnt_contract_key = " + cnt_key
                + "        UNION"
                + "        SELECT l.alg_locatie_email email"
                + "          FROM cnt_contract_plaats"
                + "             , alg_locatie l"
                + "             , alg_gebouw g"
                + "         WHERE cnt_alg_plaats_code = 'G'"
                + "           AND cnt_alg_plaats_key = g.alg_gebouw_key"
                + "           AND g.alg_locatie_key = l.alg_locatie_key"
                + "           AND cnt_contract_plaats_verwijder IS NULL"
                + "           AND cnt_contract_key = " + cnt_key
                + "        UNION"
                + "        SELECT l.alg_locatie_email email"
                + "          FROM cnt_contract_plaats"
                + "             , alg_locatie l"
                + "             , alg_terreinsector t"
                + "         WHERE cnt_alg_plaats_code = 'T'"
                + "           AND cnt_alg_plaats_key = t.alg_terreinsector_key"
                + "           AND t.alg_locatie_key = l.alg_locatie_key"
                + "           AND cnt_contract_plaats_verwijder IS NULL"
                + "           AND cnt_contract_key = " + cnt_key + ")";
            oRs = Oracle.Execute(sql);
            lsender = oRs("email").Value;
            oRs.Close();
          }
          return lsender;
        },


        //// Levert de "Contract ##KEY## (##LEV##/##OMSCH##) is goedgekeurd" en
        //// "Uw goedkeuring wordt verzocht voor contract ##KEY## (##LEV##/##OMSCH##)" op.
        sendNeedApprovalNotifications: function (cnt_key, approver_arr)
        {
          if (approver_arr == null || approver_arr.length == 0)
              return false;

          // These notifications are now sent on behalf of the system, what might be the local FM organisation
          var lsender = cnt.findSenderForNotifications(cnt_key);

          // notify approver by message & mail as configured in fac_srtnotificatie with CNTAPP
          // putnotificationsrtprio doet geen vertaling van ##LEV##/##OMSCH## (notify_tracking zou dat wel doen) dus doen we het hier zelf maar.
          var omssql = "SELECT fac_srtnotificatie_oms"
                     + "  FROM fac_srtnotificatie"
                     + " WHERE fac_srtnotificatie_code = 'CNTAPP'";
          var oRs = Oracle.Execute(omssql);
          var oms = L(oRs("fac_srtnotificatie_oms").Value, { autolcl: true });
          oRs.Close();

          for (var i = 0; i < approver_arr.length; i++)
          { // Alle fiatteurs een notificatie sturen.
            Oracle.Execute("BEGIN fac.putnotificationsrtprio(NULL, "
                            + approver_arr[i]
                            + ", 'CNTAPP', "
                            + cnt_key
                            + ", cnt.sprintf(" + safe.quoted_sql(oms) + ", " + cnt_key + "), "
                            + "  NULL, NULL, NULL, NULL, 2, "
                            + (lsender? safe.quoted_sql(lsender) : "NULL") + "); END;");
          }

          var sql = "SELECT COUNT(prs_perslid_naam_full) aantal_fiatteurs FROM prs_v_perslid_fullnames_all WHERE prs_perslid_key IN (" + approver_arr.join(",") + ")";
          var oRs = Oracle.Execute(sql);
          var aantal_fiatteurs = oRs("aantal_fiatteurs").Value;
          oRs.Close();
          return L("lcl_cnt_regapprove").format(aantal_fiatteurs);
        },

        cnt_get_afdeling:
          function _cnt_get_afdeling(afd_key) {
            sql = "SELECT " + S("prs_dep_string") + " afdeling"
                + " FROM prs_v_afdeling d"
                + " WHERE d.prs_afdeling_key = " + afd_key;
            var oRs = Oracle.Execute(sql);

            var afdeling = oRs("afdeling").Value;
            oRs.Close();

            var result = { afd_key: afd_key,
                           afdeling: afdeling };

            return result;
          },

        cnt_contract_info: // deze functie mettertijd uitbreiden
           function (cnt_key)
           {
              var sql = "SELECT cnt.cnt_contract_status(cc.cnt_contract_looptijd_van"
                        + "                           , cnt.cnt_getRappeldatum(cc.cnt_contract_key)"
                        + "                           , cnt.cnt_getOpzegdatum(cc.cnt_contract_key)"
                        + "                           , cc.cnt_contract_looptijd_tot) fase_actief"
                        + "     , cc.cnt_contract_status"
                        + "     , cc.cnt_contract_versie"
                        + "     , cc.cnt_contract_kosten"
                        + "     , cc.cnt_contract_termijnkosten"
                        + "     , cc.cnt_contract_termijntermijn"
                        + "     , (SELECT " + lcl.xsqla('cnt_termijn_omschrijving', 'cnt_termijn_key')
                          + "        FROM cnt_termijn"
                          + "       WHERE cnt_termijn_key = cc.cnt_contract_termijntermijn) termijntermijn_oms"
                        + "     , cnt.termijnjaarfactor(cc.cnt_contract_termijntermijn) termijnjaarfactor"
                        + "     , cc.cnt_contract_approved"
                        + "     , COALESCE(cc.cnt_contract_verlenging, -1) cnt_contract_verlenging"
                        + "     , cc.cnt_contract_nummer"
                        + "     , cc.cnt_contract_nummer_intern"
                        + "     , cc.cnt_contract_omschrijving"
                        + "     , cc.cnt_contract_opmerking"
                        + "     , cc.cnt_contract_document"
                        + "     , cc.cnt_contract_korting"
                        + "     , cc.cnt_contract_uurloon"
                        + "     , cc.cnt_contract_looptijd_van"
                        + "     , cc.cnt_contract_looptijd_tot"
                        + "     , cc.cnt_contract_inactiveren"
                        + "     , cc.prs_contactpersoon_key"
                        + "     , cc.cnt_contract_verwijder"
                        + "     , cc.cnt_contract_locked_user_key"
                        + "     , cc.cnt_contract_locked_date"
                        + "     , cc.bes_bestelopdr_key"
                        + "     , cc.cnt_contract_opzegtermijn"
                        + "     , (SELECT " + lcl.xsqla('cnt_termijn_omschrijving', 'cnt_termijn_key')
                          + "        FROM cnt_termijn"
                          + "       WHERE cnt_termijn_key = cc.cnt_contract_opzegtermijn) opzegtermijn_oms"
                        + "     , cnt.cnt_getOpzegdatum(cc.cnt_contract_key) opzegdatum"
                        + "     , cc.cnt_contract_rappeltermijn"
                        + "     , (SELECT " + lcl.xsqla('cnt_termijn_omschrijving', 'cnt_termijn_key')
                          + "        FROM cnt_termijn"
                          + "       WHERE cnt_termijn_key = cc.cnt_contract_rappeltermijn) rappeltermijn_oms"
                        + "     , cnt.cnt_getRappeldatum(cc.cnt_contract_key) rappeldatum"
                        + "     , cc.cnt_contract_verleng_termijn"
                        + "     , (SELECT " + lcl.xsqla('cnt_termijn_omschrijving', 'cnt_termijn_key')
                          + "        FROM cnt_termijn "
                          + "       WHERE cnt_termijn_key = cc.cnt_contract_verleng_termijn) verlengtermijn_oms"
                        + "     , cc.cnt_prs_bedrijf_key"
                        + "     , (SELECT prs_bedrijf_naam"
                          + "        FROM prs_bedrijf"
                          + "       WHERE prs_bedrijf_key = cc.cnt_prs_bedrijf_key) bedrijf_naam"
                        + "     , cc.cnt_prs_perslid_key"
                        + "     , (SELECT prs_perslid_naam_full"
                          + "        FROM prs_v_perslid_fullnames_all pf"
                          + "       WHERE pf.prs_perslid_key = cc.cnt_prs_perslid_key) perslid_naam"
                        + "     , cc.prs_dienst_key"
                        + "     , (SELECT " + lcl.xsqla('prs_dienst_omschrijving', 'prs_dienst_key')
                          + "        FROM prs_dienst"
                          + "       WHERE prs_dienst_key = cc.prs_dienst_key) dienst_omschrijving"
                        + "     , cc.cnt_prs_afdeling_key"
                        + "     , (SELECT " + S("prs_dep_string")
                          + "        FROM prs_v_afdeling d"
                          + "       WHERE d.prs_afdeling_key = cc.cnt_prs_afdeling_key) afdeling_naam"
                        + "     , cc.prs_afdeling_key_eig"
                        + "     , (SELECT " + S("prs_dep_string")
                          +"         FROM prs_v_afdeling d"
                          + "       WHERE d.prs_afdeling_key = cc.prs_afdeling_key_eig) afdeling_naam_eig"
                        + "     , cc.prs_perslid_key_beh"
                        + "     , (SELECT prs_perslid_naam_full"
                          + "        FROM prs_v_perslid_fullnames_all pf"
                          + "       WHERE pf.prs_perslid_key = cc.prs_perslid_key_beh) perslid_naam_beh"
                        + "     , cc.prs_perslid_key_eig"
                        + "     , (SELECT prs_perslid_naam_full"
                          + "        FROM prs_v_perslid_fullnames_all pf"
                          + "       WHERE pf.prs_perslid_key = cc.prs_perslid_key_eig) perslid_naam_eig"
                        + "     , cc.ins_discipline_key"
                        + "     ," + lcl.xsqla('cs.ins_discipline_omschrijving','cs.ins_discipline_key')
                        + "     , cc.prs_kostenplaats_key"
                        + "     , (SELECT " + S("prs_kpn_string")
                          + "        FROM prs_kostenplaats k "
                          + "       WHERE k.prs_kostenplaats_key = cc.prs_kostenplaats_key) kostenplaats_naam"
                        + "     , cc.prs_kostensoort_key"
                        + "     , (SELECT prs_kostensoort_oms || '-' || " + lcl.xsqla('prs_kostensoort_opmerking', 'prs_kostensoort_key')
                          + "        FROM prs_kostensoort"
                          + "       WHERE prs_kostensoort_key = COALESCE(cc.prs_kostensoort_key, cs.prs_kostensoort_key)) kostensoort_naam"
                        + "     , (SELECT prs_kostensoort_btw"
                          + "        FROM prs_kostensoort"
                          + "       WHERE prs_kostensoort_key = COALESCE(cc.prs_kostensoort_key, cs.prs_kostensoort_key)) prs_kostensoort_btw"
                        + "     , dp.cnt_srtcontract_type"
                        + "     , dp.cnt_disc_params_factuurschema"
                        + "     , dp.cnt_disc_params_fin"
                        + "     , dp.cnt_disc_params_binding"
                        + "     , dp.cnt_disc_params_leverancier"
                        + "     , dp.cnt_disc_params_uitvoerende"
                        + "     , dp.cnt_disc_params_huurder"
                        + "     , dp.cnt_disc_params_opties"
                        + "     , dp.cnt_disc_params_ksverplicht"
                        + "     , cc.cnt_contract_mantel_key"
                        + "     , mc.cnt_contract_nummer_intern mantelcontractnummer"
                        + "     , mc.cnt_contract_omschrijving mantelomschrijving"
                        + "     , mc.cnt_contract_versie mantelversie"
                        + "     , (SELECT COUNT(*) FROM cnt_contract_plaats ccp WHERE ccp.cnt_contract_key = cc.cnt_contract_key) nnScope"
                        + "     , bdp.bes_disc_params_contract"
                        + "     , (SELECT COUNT(fin_factuur_key)"
                          + "        FROM fin_factuur"
                          + "       WHERE cnt_contract_key = " + cnt_key
                          + "         AND fin_factuur_verwijder is null"
                          + "         AND fin_factuur_statuses_key NOT IN (1, 7)) openfinref"  // Aantal openstaande facturen met een referentie naar dit contract. 1=Afgewezen, 7=Verwerkt.
                        + "  FROM cnt_contract cc"
                        + "     , cnt_discipline cs"
                        + "     , cnt_disc_params dp"
                        + "     , cnt_contract mc"
                        + "     , bes_disc_params bdp"
                        + " WHERE cc.ins_discipline_key = cs.ins_discipline_key"
                        + "   AND cc.ins_discipline_key = dp.cnt_ins_discipline_key"
                        + "   AND cc.cnt_contract_mantel_key = mc.cnt_contract_key (+)"
                        + "   AND cc.ins_discipline_key = bdp.bes_disc_params_cnt_disckey(+)"
                        + "   AND cc.cnt_contract_key = " + cnt_key;
              var oRs = Oracle.Execute(sql);
              if (oRs.eof)
              {
                  shared.record_not_found(L("lcl_contract") + " " + cnt_key);
              }

              var result = { fase_actief: oRs("fase_actief").Value,
                             contract_status: oRs("cnt_contract_status").Value,
                             contract_status_str: cnt.getcntstatustext(oRs("cnt_contract_status").Value),
                             versie: oRs("cnt_contract_versie").Value,
                             kosten: oRs("cnt_contract_kosten").Value,
                             termijnkosten: oRs("cnt_contract_termijnkosten").Value,
                             termijntermijn: oRs("cnt_contract_termijntermijn").Value,
                             termijntermijn_oms: oRs("termijntermijn_oms").Value,
                             termijnjaarfactor: oRs("termijnjaarfactor").Value,
                             approved: oRs("cnt_contract_approved").Value? oRs("cnt_contract_approved").Value : 0,
                             verlenging: oRs("cnt_contract_verlenging").Value,
                             nummer: oRs("cnt_contract_nummer").Value,
                             nummer_intern: oRs("cnt_contract_nummer_intern").Value,
                             omschrijving: oRs("cnt_contract_omschrijving").Value,
                             opmerking: oRs("cnt_contract_opmerking").Value,
                             document: oRs("cnt_contract_document").Value,
                             korting: oRs("cnt_contract_korting").Value,
                             uurloon: oRs("cnt_contract_uurloon").Value,
                             looptijd_van: new Date(oRs("cnt_contract_looptijd_van").Value),
                             looptijd_tot: new Date(oRs("cnt_contract_looptijd_tot").Value),
                             inactiveren: oRs("cnt_contract_inactiveren").Value == 1,
                             contactpersoon_key: oRs("prs_contactpersoon_key").Value,
                             verwijderdatum: oRs("cnt_contract_verwijder").Value,
                             locked_user_key: oRs("cnt_contract_locked_user_key").value,
                             locked_date: new Date(oRs("cnt_contract_locked_date").value),
                             bestelopdr_key: oRs("bes_bestelopdr_key").Value,
                             opzegtermijn: oRs("cnt_contract_opzegtermijn").Value,
                             opzegtermijn_oms: oRs("opzegtermijn_oms").Value,
                             opzegdatum: new Date(oRs("opzegdatum").Value),
                             rappeltermijn: oRs("cnt_contract_rappeltermijn").Value,
                             rappeltermijn_oms: oRs("rappeltermijn_oms").Value,
                             rappeldatum: new Date(oRs("rappeldatum").Value),
                             verlengtermijn: oRs("cnt_contract_verleng_termijn").Value,
                             verlengtermijn_oms: oRs("verlengtermijn_oms").Value,
                             bedrijf_key: oRs("cnt_prs_bedrijf_key").Value,
                             bedrijf_naam: oRs("bedrijf_naam").Value,
                             perslid_key: oRs("cnt_prs_perslid_key").Value,
                             perslid_naam: oRs("perslid_naam").Value,
                             prs_dienst_key: oRs("prs_dienst_key").Value,
                             dienst_omschrijving: oRs("dienst_omschrijving").Value,
                             afdeling_key: oRs("cnt_prs_afdeling_key").Value,
                             afdeling_naam: oRs("afdeling_naam").Value,
                             afdeling_key_eig:  oRs("prs_afdeling_key_eig").Value,
                             afdeling_naam_eig: oRs("afdeling_naam_eig").Value,
                             perslid_key_beh: oRs("prs_perslid_key_beh").Value,
                             perslid_naam_beh: oRs("perslid_naam_beh").Value,
                             perslid_key_eig: oRs("prs_perslid_key_eig").Value,
                             perslid_naam_eig: oRs("perslid_naam_eig").Value,
                             discipline_key: oRs("ins_discipline_key").Value,
                             discipline_omschrijving: oRs("ins_discipline_omschrijving").Value,
                             prs_kostenplaats_key: oRs("prs_kostenplaats_key").Value,
                             kostenplaats_naam: oRs("kostenplaats_naam").Value,
                             prs_kostensoort_key: oRs("prs_kostensoort_key").Value,
                             kostensoort_btw: oRs("prs_kostensoort_btw").Value == 1,
                             kostensoort_naam: oRs("kostensoort_naam").Value,
                             srtcontract_type: oRs("cnt_srtcontract_type").Value,
                             hasfactuurschema: oRs("cnt_disc_params_factuurschema").Value == 1,
                             toon_fin_info: oRs("cnt_disc_params_fin").Value == 1,
                             discipline_binding: oRs("cnt_disc_params_binding").Value,
                             discipline_leverancier: oRs("cnt_disc_params_leverancier").Value,
                             discipline_uitvoerende: oRs("cnt_disc_params_uitvoerende").Value,
                             discipline_huurder: oRs("cnt_disc_params_huurder").Value,
                             discipline_ksverplicht: oRs("cnt_disc_params_ksverplicht").Value == 1,
                             mantel_key: oRs("cnt_contract_mantel_key").Value,
                             mantelcontractnummer: oRs("mantelcontractnummer").Value,
                             mantelversie: oRs("mantelversie").Value,
                             mantelomschrijving: oRs("mantelomschrijving").Value,
                             nnScope: oRs("nnScope").Value,
                             isAbonnement: oRs("bes_disc_params_contract").Value == 1,
                             magAutomatischVerlengen: oRs("cnt_disc_params_opties").Value == 1,
                             openfinref: oRs("openfinref").Value > 0
                           };
              oRs.Close()

              if (result.locked_user_key)
              {
                var expire = new Date;
                expire.setMinutes(expire.getMinutes() - S("mld_locked_expire"));
                if (result.locked_date < expire)
                { // In de database laten we het lock gewoon staan ter analyse achteraf welke locks niet worden vrijgegeven.
                  result.locked_user_key = null;
                  result.locked_date = null;
                }
              }

              return result;
           },

        func_enabled_contract: // Wat mag ik zoal op dit specifiek contract?
          function _func_enabled_contract(pcnt_contract_key, cnt_info) // cnt_info mag je optioneel alvast meegeven
          {
            if (!cnt_info)
              cnt_info = cnt.cnt_contract_info(pcnt_contract_key); // Haal gegevens van het contract op.

            // Alleen personen met rechten op de locaties van de contracten mogen goedkeuren.
            // Daarvoor hebben we de locatie van de contracten nodig.
            var sql_cntloc = cnt.getCntLocationsSql();
            var sql_loc = "SELECT alg_locatie_key"
                        + "  FROM (" + sql_cntloc + ") cntloc"
                        + " WHERE cntloc.cnt_contract_key = " + pcnt_contract_key;
            var oRs_loc = Oracle.Execute(sql_loc);
            var loc_arr = [];
            while (!oRs_loc.eof)
            {
              var ors_loc_key = oRs_loc("alg_locatie_key").Value;
              if (ors_loc_key) // Geen lege waarden toevoegen!
                loc_arr.push(ors_loc_key);
              oRs_loc.MoveNext();
            }
            oRs_loc.Close();

            var afd_key = cnt_info.afdeling_key_eig; // te controleren
            if (user == cnt_info.perslid_key_eig || user == cnt_info.perslid_key_beh)
                afd_key = null; // dan niet moeilijk doen over de afdeling

            // Als een contract geen locaties heeft dan heb je alle rechten op dat contract.
            var cresult = user.func_enabled2("CNT",
                                                { ins_discipline_key: cnt_info.discipline_key,
                                                  loc_key: loc_arr,
                                                  afd_key: afd_key,
                                                  checkOptimistic: false, // checkOptimistic
                                                  isOptional: true
                                                });
            var actief = cnt_info.contract_status == 0;
            var inactief = cnt_info.contract_status == 1;
            var hasOpenFacturen = cnt_info.openfinref;  // Zijn er openstaande facturen met een referentie naar dit contract.
            var nieuw = cnt_info.contract_status == 2;
            var terGoedkeuring = cnt_info.contract_status == 3;
            var isVerlengbaar = (new Date(cnt_info.opzegdatum) > new Date() && (cnt_info.verlenging < 0 || (cnt_info.verlenging & 2) != 2)); // bit 2 hoog = niet verlengbaar
            cresult.cnt_info = cnt_info; // teruggeven
            cresult.mijncontract = cnt_info.perslid_key_beh == user_key || cnt_info.perslid_key_eig == user_key;

            cresult.canMANread = cresult.canRead("WEB_CNTMAN");
            cresult.canMANwrite = cresult.canWrite("WEB_CNTMAN");
            cresult.canUSEread = cresult.canRead("WEB_CNTUSE") || cresult.mijncontract;
            cresult.canUSEwrite = cresult.canWrite("WEB_CNTUSE");
            cresult.canReadAny = cresult.canUSEread || cresult.canMANread;

            cresult.canGoedkeur1 = cresult.canWrite("WEB_CNTGO1") &&                                                   // Heb ik de rechten om goed te keuren op dit niveau 1?
                                   terGoedkeuring &&                                                                   // Moet het contract gekeurd worden (juiste status)
                                   ((S("cnt_approval_all") == 0 && cnt_info.kosten >= S("cnt_contract_limit1")) ||     // Zijn de kosten hoger als de limiet
                                    (S("cnt_approval_all") == 1 && cnt_info.kosten <= S("cnt_contract_limit2"))) &&    // Zijn de kosten onder mijn limiet om volledig goed te keuren
                                   cnt_info.approved <= S("cnt_contract_limit1");                                      // Welke goedkeur? 1, 2 of 3?
            cresult.canGoedkeur2 = cresult.canWrite("WEB_CNTGO2") &&
                                   terGoedkeuring &&
                                   // Setting cnt_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("cnt_approval_all") == 0 && cnt_info.kosten >= S("cnt_contract_limit2") && (cnt_info.approved == S("cnt_contract_limit2") || cresult.canGoedkeur1)) ||
                                    (S("cnt_approval_all") == 1 && cnt_info.kosten <= S("cnt_contract_limit3") && cnt_info.approved <= S("cnt_contract_limit2")));
            cresult.canGoedkeur3 = cresult.canWrite("WEB_CNTGO3") &&
                                   terGoedkeuring &&
                                   ((S("cnt_approval_all") == 0 && cnt_info.kosten >= S("cnt_contract_limit3") && (cnt_info.approved == S("cnt_contract_limit3") || cresult.canGoedkeur2)) ||
                                    (S("cnt_approval_all") == 1 && cnt_info.kosten <= S("cnt_contract_limit4") && cnt_info.approved <= S("cnt_contract_limit3")));
            cresult.canGoedkeur4 = cresult.canWrite("WEB_CNTGO4") &&
                                   terGoedkeuring &&
                                   ((S("cnt_approval_all") == 0 && cnt_info.kosten >= S("cnt_contract_limit4") && (cnt_info.approved == S("cnt_contract_limit4") || cresult.canGoedkeur3)) ||
                                    (S("cnt_approval_all") == 1 && cnt_info.kosten <= S("cnt_contract_limit5") && cnt_info.approved <= S("cnt_contract_limit4")));
            cresult.canGoedkeur5 = cresult.canWrite("WEB_CNTGO5") &&
                                   terGoedkeuring &&
                                   ((S("cnt_approval_all") == 0 && cnt_info.kosten >= S("cnt_contract_limit5") && (cnt_info.approved == S("cnt_contract_limit5") || cresult.canGoedkeur4)) ||
                                    (S("cnt_approval_all") == 1 && cnt_info.kosten > S("cnt_contract_limit5") && cnt_info.approved <= S("cnt_contract_limit5"))) &&
                                   cnt_info.kosten > cnt_info.approved;
            cresult.forApproval = nieuw && cresult.canUSEwrite;
            cresult.canReject = cresult.canGoedkeur1 || cresult.canGoedkeur2 || cresult.canGoedkeur3 || cresult.canGoedkeur4 || cresult.canGoedkeur5;

            // Ik mag in principe alleen de allernieuwste versie splitten of bewerken
            var csql = "SELECT cnt.getnieuwsteversiekey(" + pcnt_contract_key + ") newkey FROM DUAL";
            var coRs = Oracle.Execute(csql);
            var newestkey = coRs("newkey").Value;
            coRs.Close();
            // Met CNTMAN rechten kan men alleen de laatste versie van een contract wijzigen, en ook oudere versies indien cnt_inactivate_mode & 2 (volgens AAIT#80476)
            // Met CNTMSU rechten kan men alle versies van een contract wijzigen ook oudere versies (volgens AAEN#20694).
            // Met CNTMSU rechten kan je een contract inactiveren (sluiten)
            // Met CNTMSU (Super user) mag je dus net iets meer als met CNTMAN rechten.
            // Als het approve mechanisme actief is (S("cnt_contract_approval") == 1) dan kan ik ook met CNTUSE rechten wijzigen. Daarna volgt altijd nog het goedkeuren.
            // PAS OP!!!: CNTMSU is disciplineloos dus niet in cresult! Daardoor zijn cresult.canWrite("WEB_CNTMSU") en cresult.canRead("WEB_CNTMSU") altijd false.
            // Van een abonnement contract kan nooit een nieuwe versie worden gemaakt.

            // Met welke rechten mogen welke acties uitgevoerd worden?
            // Voor status 2 en 3 is het approval mechanisme actief en geldt AUTOMATISCH cnt_contract_approval = 1.
            // Voor de helderheid mag je met CNTMAN rechten niets in de status Nieuw(2) en Ter goedkeuring(3).
            // Cijfers 0 t/m 3 zijn statussen, Nieuwste = Alleen bij de nieuwste versie, approval = Setting cnt_contract_approval.
            //                        CNTUSE                                        CNTMAN                                                   CNTMSU
            // Splitsen:              (0, 3) + approval = 1 + nieuwste              (0, 1) + (nieuwste of cnt_inactivate_mode & 2)           ---
            // Wijzigen alg geg:      (2, 3) + nieuwste                             (0, 1) + (nieuwste of cnt_inactivate_mode & 2)           !(cnt_inactivate_mode & 1) of CNTMAN + (cnt_inactivate_mode & 1)
            //          flex:         (0, 2, 3) + approval = 1 + >=100 + nieuwste   (0, 1) + (nieuwste of cnt_inactivate_mode & 2) + <=100   ---
            // Wijzigen abo:          ((0 + beheerder), 2, 3) + verlengbaar         0 + verlengbaar                                          ---
            // Delete fase 0:         2, 3                                          (0, 1)                                                   !(cnt_inactivate_mode & 1)
            //        fase 1 t/m 4:   2, 3                                          ---                                                     ---
            // Inactivate/Sluiten     CNTMSU + 0 + !(cnt_inactivate_mode & 1)       CNTMSU + 0 + cnt_inactivate_mode & 1                     Zie kolomen CNTUSE en CNTMAN

            var haveCNTMSUrights = user.checkAutorisation("WEB_CNTMSU", true) != null; // Pas op: disciplineloos dus niet in cresult!
            var nieuwste = pcnt_contract_key == newestkey;
            cresult.canChangeFlex =    (   (actief || inactief) && cresult.canMANwrite && (nieuwste || (S("cnt_inactivate_mode") & 2))
                                        || !inactief && S("cnt_contract_approval") == 1 && cresult.canUSEwrite && nieuwste)
                                    || (S("cntuse_can_edit_datum") && cresult.canUSEwrite);
            cresult.canSplit =    cresult.canChangeFlex
                               && !cnt_info.isAbonnement
                               && !nieuw;
            var canChangeAbonnement =    cnt_info.isAbonnement
                                      && isVerlengbaar
                                      && (   (actief && cresult.canMANwrite)
                                          || (cresult.mijncontract && actief)
                                          || ((nieuw || terGoedkeuring) && cresult.canUSEwrite));
            cresult.canChange =    (cresult.canChangeFlex && !cnt_info.isAbonnement)
                                || (haveCNTMSUrights && (    (S("cnt_inactivate_mode") & 1) == 0
                                                         || ((S("cnt_inactivate_mode") & 1) == 1 && cresult.canMANwrite)))
                                || canChangeAbonnement;

            cresult.canCopy = cresult.canUSEwrite && cresult.canMANwrite;

            cresult.canChangeAlg = cresult.canChange &&
                                   !(actief && cresult.canUSEwrite && !cresult.canMANwrite && !haveCNTMSUrights); // Alleen nog status Actief(0) uitsluiten bij ALLEEN CNTUSE rechten (zie overzicht hierboven).
            cresult.canChangeKosten =    (   cresult.canMANwrite
                                          || ((nieuw || terGoedkeuring) && cresult.canUSEwrite))
                                      && !cnt_info.isAbonnement;
            if (S("cnt_scopeverdeling") == 1 && cnt_info.nnScope > 0)
                cresult.canChangeKosten = false; // Invullen doe je bij de scope verdeling
            // Inactiveren contract met WEB_CNTMAN/WEB_CNTUSE read rechten and WEB_CNTMSU rechten ((cnt_inactivate_mode & 1) == 0) of met extra WEB_CNTMAN write rechten (cnt_inactivate_mode & 1)
            canInactivateAuth =    (cresult.canUSEread || cresult.canMANread)
                                && haveCNTMSUrights
                                && (    (S("cnt_inactivate_mode") & 1) == 0
                                    || ((S("cnt_inactivate_mode") & 1) == 1 && cresult.canMANwrite));
            cresult.canInactivate = canInactivateAuth && actief && !hasOpenFacturen;                    // Contract handmatig kunnen laten sluiten.

            var today = new Date();
            var looptijd_tot = new Date(cnt_info.looptijd_tot);
            looptijd_tot.setHours(23,59,55,999);                                                        // Contract loopt tot het eind van de dag.
            cresult.canInactivateAuto = (canInactivateAuth && looptijd_tot > today) || hasOpenFacturen; // Contract automatisch kunnen laten sluiten.

            // Ik kan verlengen als het een abonnement contract betreft, als ik de contract beheerder (cnt_info.perslid_key_beh) ben en als ik WEB_CNTUSE of WEB_CNTMAN schrijf rechten heb.
            // MGE: als ik contractbeheerder ben heb ik toch automatisch WEB_CNTUSE rechten?
            cresult.canVerlengen = canChangeAbonnement;
            cresult.canReadNotes = (cresult.canUSEread || cresult.canMANread);
            cresult.canWriteNotes = cresult.canReadNotes;

            cresult.canDelete = ((nieuw || terGoedkeuring) && cresult.canUSEwrite);
            cresult.canChangeSrt = haveCNTMSUrights;
            if (cnt_info.fase_actief == 0)  // Nu - Ingangsdatum (voor Ingangsdatum)
              cresult.canDelete = cresult.canDelete ||
                                  ((actief || inactief) && cresult.canMANwrite) ||
                                  (haveCNTMSUrights && (S("cnt_inactivate_mode") & 1) == 0);

            var sql = "SELECT count(*)"
                    + "  FROM fin_factuur"
                    + " WHERE fin_factuur_verwijder IS NULL"
                    + "   AND cnt_contract_key = " + pcnt_contract_key;
            var oRs = Oracle.Execute(sql);
            cresult.hasFactuur = (oRs(0).value > 0);
            oRs.Close();
            cresult.canDelete = cresult.canDelete && !cresult.hasFactuur; // Contracten met facturen mogen nooit verwijderd worden.

            var sql = "SELECT COUNT(*)"
                    + "  FROM cnt_verlengschema"
                    + " WHERE cnt_contract_key = " + pcnt_contract_key;
            var oRs = Oracle.Execute(sql);
            cresult.hasVerlengschema = (oRs(0).Value != 0);
            oRs.Close();

            return cresult;
          },

        func_enabled_cnt: // Wat mag ik zoal voor deze specifieke discipline?
          function _func_enabled_cnt(pdiscipline_keys)
          {
            var cresult = user.func_enabled2("CNT",
                                             { ins_discipline_key: pdiscipline_keys, // Kan multi string zijn "1,2,3,4"
                                               alg_key: -1, // Er is nog geen contract key bekend en dus ook geen loc_key/alg_key. Anders was cnt.func_enabled_contract(cnt_key) wel aangeroepen.
                                               prs_key: user_key, // key_eig, // TODO: Vind de juiste perslid. Je hebt prs_afdeling_key_eig
                                               checkOptimistic: false, // checkOptimistic
                                               isOptional: true
                                             });

            cresult.canMANread = cresult.canRead("WEB_CNTMAN");
            cresult.canMANwrite = cresult.canWrite("WEB_CNTMAN");
            cresult.canUSEread = cresult.canRead("WEB_CNTUSE") || cresult.mijncontract;
            cresult.canUSEwrite = cresult.canWrite("WEB_CNTUSE");
            cresult.canReadAny = cresult.canUSEread || cresult.canMANread;

            return cresult;
          },

          lock: function (cnt_key)
          {
            var sql = "UPDATE cnt_contract"
                    + "   SET cnt_contract_locked_user_key = " + user_key
                    + "     , cnt_contract_locked_date = SYSDATE"
                    + " WHERE cnt_contract_key = " + cnt_key;
            Oracle.Execute(sql);
          },

          unlock: function (cnt_key)
          {
            var sql = "UPDATE cnt_contract"
                    + "   SET cnt_contract_locked_user_key = NULL"
                    + "     , cnt_contract_locked_date = SYSDATE"
                    + " WHERE cnt_contract_key = " + cnt_key
                    + "   AND cnt_contract_locked_user_key = " + user_key; // Alleen als we zelf het lock hadden
            Oracle.Execute(sql);
          },

        getLocationSql:
          function(select_loc_keys, alias)
          { // De select_loc_keys parameter is een SELECT string: SELECT alg_locatie_key FROM alg_locatie xx WHERE UPPER (xx.alg_locatie_omschrijving) LIKE '%XXXXXXXXXX%'.
            sql = " cnt_contract.cnt_contract_key IN (SELECT cnt_contract_key"
                + "                                     FROM cnt_v_aanwezigcontract_plaats"
                + "                                    WHERE (cnt_alg_plaats_code = 'L'"
                + "                                           AND cnt_alg_plaats_key IN (" + select_loc_keys + "))"
                + "                                       OR ((cnt_alg_plaats_code = 'G'"
                + "                                            AND cnt_alg_plaats_key IN (SELECT alg_gebouw_key"
                + "                                                                         FROM alg_v_aanweziggebouw"
                + "                                                                        WHERE alg_locatie_key IN (" + select_loc_keys + ")))"
                + "                                        OR (cnt_alg_plaats_code = 'T'"
                + "                                            AND cnt_alg_plaats_key IN (SELECT alg_terreinsector_key"
                + "                                                                         FROM alg_v_aanwezigterreinsector"
                + "                                                                        WHERE alg_locatie_key IN (" + select_loc_keys + "))))"
                + "                                   UNION"
                + "                                   SELECT cnt_contract_key"
                + "                                     FROM cnt_v_aanwezigcontract_object co"
                + "                                        , ins_v_aanwezigdeel ad"
                + "                                    WHERE cnt_ins_deel_key = ad.ins_deel_key"
                + "                                      AND ad.ins_alg_locatie_key IN (" + select_loc_keys + "))";

            return sql;
          }

      }

%>
