Merge 2023.1 RC3 patches

svn path=/Website/trunk/; revision=59410
This commit is contained in:
Jos Groot Lipman
2023-03-02 12:24:33 +00:00
parent 805fc7f70d
commit 2743e4540a
40 changed files with 868 additions and 532 deletions

View File

@@ -8,9 +8,9 @@
*/
function API_func()
function API_func(APIname)
{
this.APIname = getQParam("API");
this.APIname = APIname || getQParam("API");
var sql = "SELECT *"
+ " FROM fac_api"
+ " WHERE fac_api_name = " + safe.quoted_sql(this.APIname);
@@ -44,7 +44,8 @@ function API_func()
oRs2.Close();
Response.End;
};
__Log("API User is: " + oRs2("prs_perslid_naam"));
__Log("API User is: " + oRs2("prs_perslid_naam").Value);
// JGL: komen we hier ooit? Gebeurt nu ooit dit: /* global */ user = new Perslid(user_key);
user_key = oRs2("prs_perslid_key").Value;
oRs2.Close();
}

View File

@@ -178,7 +178,7 @@ function model_appointments()
+ " FROM alg_gebouw g"
+ " , alg_v_onroerendgoed o"
+ " WHERE g.alg_gebouw_key = o.alg_gebouw_key"
+ " AND o.alg_onroerendgoed_keys = " jsondata._alg_keys
+ " AND o.alg_onroerendgoed_keys = " + (jsondata._alg_keys ? jsondata._alg_keys : -1)
+ " )"
+ " , (SELECT MIN(bez_actie_groep_key)"
+ " FROM bez_actie_groep"

View File

@@ -164,6 +164,89 @@ function model_prs_bedrijf_bedrijf()
abort_with_warning(L("prs_bedrijf_bedrijf_err1").format(L("prs_bedrijf_key1"), L("prs_bedrijf_key2")));
}
this.hook_pre_delete = function (params, jsondata)
{ // Bij multi wordt deze functie voor elke te verwijderen prs_bedrijf_bedrijf_key aangeroepen.
// Voordat de standaard functie REST_DELETE de bedrijf-bedrijf koppeling verwijdert,
// moeten eerst de bijbehorende bedrijfdienstlocaties records worden verwijderd.
// De bedrijfdienstlocaties waarbij het veld prs_bedrijf_voor_key ("Voor opdrachtgever/bedrijf") is gevuld
// met <20><>n van de twee bedrijven uit de bedrijf-bedrijf koppeling, moeten sowieso worden verwijderd.
var sql_bdl = "SELECT prs_bedrijfdienstlocatie_key"
+ " FROM prs_bedrijfdienstlocatie"
+ " WHERE prs_bedrijf_voor_key IN (SELECT prs_bedrijf_key1"
+ " FROM prs_bedrijf_bedrijf"
+ " WHERE prs_bedrijf_bedrijf_key = " + jsondata
+ " UNION"
+ " SELECT prs_bedrijf_key2"
+ " FROM prs_bedrijf_bedrijf"
+ " WHERE prs_bedrijf_bedrijf_key = " + jsondata + ")"
+ " AND prs_perslid_key IN (SELECT prs_perslid_key"
+ " FROM prs_contactpersoon"
+ " WHERE prs_bedrijf_key IN (SELECT prs_bedrijf_key1"
+ " FROM prs_bedrijf_bedrijf"
+ " WHERE prs_bedrijf_bedrijf_key = " + jsondata
+ " UNION"
+ " SELECT prs_bedrijf_key2"
+ " FROM prs_bedrijf_bedrijf"
+ " WHERE prs_bedrijf_bedrijf_key = " + jsondata + ")"
+ " AND prs_contactpersoon_verwijder IS NULL)";
var sql = "DELETE prs_bedrijfdienstlocatie"
+ " WHERE prs_bedrijfdienstlocatie_key IN (" + sql_bdl + ")";
Oracle.Execute(sql);
// Als dit de laatste bedrijf-bedrijf koppeling is van een bedrijf dan moeten alle bedrijfdienstlocatie records van zijn contactpersoon,
// waarbij het veld prs_bedrijf_voor_key niet is gevuld (NULL), nu ook verwijderd worden.
// Beide bedrijven ophalen.
sql = "SELECT prs_bedrijf_key1"
+ " , prs_bedrijf_key2"
+ " FROM prs_bedrijf_bedrijf"
+ " WHERE prs_bedrijf_bedrijf_key = " + jsondata;
var oRs = Oracle.Execute(sql);
var bdr_key1 = oRs("prs_bedrijf_key1").Value;
var bdr_key2 = oRs("prs_bedrijf_key2").Value;
oRs.Close();
// Voor beide bedrijven controleren of het de laatste bedrijf-bedrijf koppeling is.
var lastone = [];
sql = "SELECT COUNT(*) aantal"
+ " FROM prs_bedrijf_bedrijf bb"
+ " WHERE bb.prs_bedrijf_key1 = " + bdr_key1
+ " OR bb.prs_bedrijf_key2 = " + bdr_key1;
var oRs = Oracle.Execute(sql);
if (oRs("aantal").Value == 1)
lastone.push(bdr_key1);
oRs.Close();
sql = "SELECT COUNT(*) aantal"
+ " FROM prs_bedrijf_bedrijf bb"
+ " WHERE bb.prs_bedrijf_key1 = " + bdr_key2
+ " OR bb.prs_bedrijf_key2 = " + bdr_key2;
var oRs = Oracle.Execute(sql);
if (oRs("aantal").Value == 1)
lastone.push(bdr_key2);
oRs.Close();
// Van de bedrijven waarvan dit de laatste bedrijf-bedrijf koppeling is, alle prs_bedrijfdienstlocatie_key records verwijderen.
if (lastone.length)
{
var sql_bdl = "SELECT prs_bedrijfdienstlocatie_key"
+ " FROM prs_bedrijfdienstlocatie"
+ " WHERE prs_bedrijfdienstlocatie_key IN (SELECT prs_bedrijfdienstlocatie_key"
+ " FROM prs_bedrijfdienstlocatie"
+ " WHERE prs_bedrijf_voor_key IS NULL"
+ " AND prs_perslid_key IN (SELECT prs_perslid_key"
+ " FROM prs_contactpersoon"
+ " WHERE prs_bedrijf_key IN (" + lastone.join(",") + ")"
+ " AND prs_contactpersoon_verwijder IS NULL))";
var sql = "DELETE prs_bedrijfdienstlocatie"
+ " WHERE prs_bedrijfdienstlocatie_key IN (" + sql_bdl + ")";
Oracle.Execute(sql);
}
// Nu kan de standaard functie REST_DELETE de bedrijf-bedrijf koppeling verwijderen.
}
this.REST_GET = generic_REST_GET(this);
this.REST_POST = generic_REST_POST(this);
this.REST_PUT = generic_REST_PUT(this);

View File

@@ -138,7 +138,11 @@ function model_prs_bedrijfdienstlocatie()
"selectjustone": true
},
"defaultvalue": null,
"emptyoption": L("mgt_all")
"emptyoption": L("mgt_all"),
"listfunction": function(oRs)
{
return (oRs.Fields("forcompany.id").Value? oRs.Fields("forcompany.name").Value : L("mgt_all"));
}
},
"duration": {
"dbs": "prs_bdl_t_uitvoertijd",

View File

@@ -419,15 +419,14 @@ function model_res_ruimte()
DEZE: DEZE,
custabspath: Server.MapPath(custpath)
});
if (oldExternalID) {
if (oldExternalID) { // Opschonen moet sowieso gebeuren als die veld een andere waarde had;
// Maak nu ook de res_ruimte_syncstate en res_ruimte_syncdate in de res_ruimte_sync tabel leeg
var sql = "UPDATE res_ruimte_sync SET res_ruimte_syncstate = NULL, res_ruimte_syncdate = NULL WHERE res_ruimte_key = " + res_ruimte_key;
Oracle.Execute(sql);
// En ook de res_ruimte_externsyncdate en res_ruimte_graphhooksecret uit de res_ruimte tabel
var sql = "UPDATE res_ruimte SET res_ruimte_externsyncdate = NULL, res_ruimte_graphhooksecret = NULL WHERE res_ruimte_key = " + res_ruimte_key;
Oracle.Execute(sql);
if (hook.subscription(oldExternalID, res_ruimte_key, "D")) {
// Maak nu ook de res_ruimte_syncstate en res_ruimte_syncdate in de res_ruimte_sync tabel leeg
var sql = "UPDATE res_ruimte_sync SET res_ruimte_syncstate = NULL, res_ruimte_syncdate = NULL WHERE res_ruimte_key = " + res_ruimte_key;
Oracle.Execute(sql);
// En ook de res_ruimte_externsyncdate en res_ruimte_graphhooksecret uit de res_ruimte tabel
var sql = "UPDATE res_ruimte SET res_ruimte_externsyncdate = NULL, res_ruimte_graphhooksecret = NULL WHERE res_ruimte_key = " + res_ruimte_key;
Oracle.Execute(sql);
__DoLog("MS Graph subscription deleted for res_ruimte (" + res_ruimte_key + ") with Extern ID: " + oldExternalID, "#FF4");
} else {
__DoLog("Error: Failed to delete MS Graph subscription for res_ruimte (" + res_ruimte_key + ") with Extern ID: " + oldExternalID, "#FF0000");

View File

@@ -45,7 +45,6 @@ function withinTimeRange(_date) {
}
var canChange = true;
if (0)
if (afspraak_key == -1)
{
var rsv_ruimte_key = getQParamInt("rsv_ruimte_key"); // dan moet deze er zijn
@@ -56,30 +55,30 @@ if (afspraak_key == -1)
if (!oRs.eof)
{
afspraak_key = oRs("bez_afspraak_key").Value;
var sql_r = "SELECT rrr.res_rsv_ruimte_externnr"
+ " , rrr.res_rsv_ruimte_van"
+ " FROM res_rsv_ruimte rrr"
+ " WHERE rrr.res_rsv_ruimte_key = " + rsv_ruimte_key;
var oRs_r = Oracle.Execute(sql_r);
canChange = oRs_r("res_rsv_ruimte_externnr").Value == null || withinTimeRange(oRs_r("res_rsv_ruimte_van").Value);
oRs_r.Close();
}
else // Eerste bezoeker bij een reservering niet toestaan voor externe reserveringen
{
sql = "SELECT rr.res_ruimte_extern_id"
+ " , rrr.res_rsv_ruimte_externnr"
+ " , rrr.res_rsv_ruimte_van"
+ " FROM res_rsv_ruimte rrr"
+ " , res_ruimte_opstelling ro"
+ " , res_ruimte rr"
+ " WHERE ro.res_ruimte_opstel_key = rrr.res_ruimte_opstel_key"
+ " AND rr.res_ruimte_key = ro.res_ruimte_key"
+ " AND rrr.res_rsv_ruimte_key = " + rsv_ruimte_key;
var oRs2 = Oracle.Execute(sql);
if (!oRs2.Eof && ((oRs2("res_ruimte_extern_id").Value != null || oRs2("res_rsv_ruimte_externnr").Value != null)) && !withinTimeRange(oRs2("res_rsv_ruimte_van").Value))
canChange = false;
oRs2.Close();
// var sql_r = "SELECT rrr.res_rsv_ruimte_externnr"
// + " , rrr.res_rsv_ruimte_van"
// + " FROM res_rsv_ruimte rrr"
// + " WHERE rrr.res_rsv_ruimte_key = " + rsv_ruimte_key;
// var oRs_r = Oracle.Execute(sql_r);
// canChange = oRs_r("res_rsv_ruimte_externnr").Value == null || withinTimeRange(oRs_r("res_rsv_ruimte_van").Value);
// oRs_r.Close();
}
// else // Eerste bezoeker bij een reservering niet toestaan voor externe reserveringen
// {
// sql = "SELECT rr.res_ruimte_extern_id"
// + " , rrr.res_rsv_ruimte_externnr"
// + " , rrr.res_rsv_ruimte_van"
// + " FROM res_rsv_ruimte rrr"
// + " , res_ruimte_opstelling ro"
// + " , res_ruimte rr"
// + " WHERE ro.res_ruimte_opstel_key = rrr.res_ruimte_opstel_key"
// + " AND rr.res_ruimte_key = ro.res_ruimte_key"
// + " AND rrr.res_rsv_ruimte_key = " + rsv_ruimte_key;
// var oRs2 = Oracle.Execute(sql);
// if (!oRs2.Eof && ((oRs2("res_ruimte_extern_id").Value != null || oRs2("res_rsv_ruimte_externnr").Value != null)) && !withinTimeRange(oRs2("res_rsv_ruimte_van").Value))
// canChange = false;
// oRs2.Close();
// }
oRs.Close();
}
if (afspraak_key > 0)

View File

@@ -40,6 +40,7 @@ var import_datum_gelezen = oRs("fac_import_datum_gelezen").value;
var import_datum_verwerkt = oRs("fac_import_datum_verwerkt").value;
var import_filenaam = oRs("fac_import_filenaam").value;
var import_uitvoerder = oRs("uitvoerder").value;
oRs.Close();
// Heb ik rechten om rapportage te zien
var this_imp = imp.func_enabled_import(import_key);
@@ -112,4 +113,4 @@ user.auth_required_or_abort(this_imp.canReadAny);
</body>
</html>
<% ASPPAGE_END(); %>
<% ASPPAGE_END(); %>

View File

@@ -4744,8 +4744,10 @@ ins = {checkAutLevel:
+ " , l.alg_locatie_code"
+ " , l.alg_locatie_omschrijving"
+ " , l.alg_locatie_key"
+ " , g.alg_gebouw_naam" /* was code-naam */
+ " , g.alg_gebouw_code"
+ " , g.alg_gebouw_naam"
+ " , g.alg_gebouw_key"
+ " , t.alg_terreinsector_code"
+ " , t.alg_terreinsector_naam"
+ " , t.alg_terreinsector_key"
+ " , onrg.alg_ruimte_key"
@@ -5040,8 +5042,10 @@ ins = {checkAutLevel:
+ " , cv.alg_locatie_code"
+ " , cv.alg_locatie_omschrijving"
+ " , cv.alg_locatie_key"
+ " , cv.alg_gebouw_naam" /* was code-naam */
+ " , cv.alg_gebouw_code"
+ " , cv.alg_gebouw_naam"
+ " , cv.alg_gebouw_key"
+ " , cv.alg_terreinsector_code"
+ " , cv.alg_terreinsector_naam"
+ " , cv.alg_terreinsector_key"
+ " , cv.alg_ruimte_key"
@@ -5359,10 +5363,12 @@ ins = {checkAutLevel:
if (groupby == 3 || moredetail == 2)
{
fields.push("alg_gebouw_key");
fields.push("alg_gebouw_code");
fields.push("alg_gebouw_naam");
if (ins_score_enabled)
fields.push("alg_gebouw_mjb_score1");
fields.push("alg_terreinsector_key");
fields.push("alg_terreinsector_code");
fields.push("alg_terreinsector_naam");
}
}
@@ -5517,7 +5523,8 @@ ins = {checkAutLevel:
break;
case 3: sql += " ORDER BY alg_district_omschrijving"
+ " , alg_locatie_omschrijving" // eigenlijk S(alg_loc_string)
+ " , alg_gebouw_naam"; /* was code-naam */
+ " , alg_gebouw_code"
+ " , alg_gebouw_naam";
break;
case 4: sql += " ORDER BY ins_discipline_omschrijving";
break;
@@ -5536,7 +5543,8 @@ ins = {checkAutLevel:
case 8: sql += " ORDER BY alg_district_omschrijving"
+ " , ins_srtcontrole_omschrijving"
+ " , alg_locatie_code"
+ " , alg_gebouw_naam" /* was code-naam */
+ " , alg_gebouw_code"
+ " , alg_gebouw_naam"
+ (mjb_show_srt_with_tasks
? " , ins_discipline_omschrijving"
+ " , ins_srtgroep_omschrijving"

View File

@@ -20,7 +20,7 @@ FCLTHeader.Requires({ plugins:["suggest", "jQuery"],
var urole = getQParamSafe("urole");
// Het maakt ons hier nog niet uit of we in SLE zitten
var urole = getQParamInt("self", 0) == 1 ? "fe" : urole;
var ins_key = getQParamInt("ins_key", -1);
var copy = (getQParamInt("ins_copy", 0) == 1);
var disc_key_arr = getQParamIntArray("disc", []); // Discipline.

View File

@@ -97,6 +97,7 @@ if (!warning)
kenmerkKey: "ins_kenmerk_key",
kenmerkToonbaar: "ins_kenmerk_toonbaar",
currentKenmerkenSQL: currentKenmerkenSQL,
noFlexCleanup: true,
requestQF: Request.Form,
isNew: isNew,
flexPath: "INS/S",

View File

@@ -50,8 +50,8 @@ var transitParam = buildTransitParam(["deelsrtcont_keys", "fromfinish", "finishm
function inspectClose(params)
{
<% if (deelsrtcont_key < 0)
{ %>
if (<%=multi? 1 : 0%> == 1 || params.cancel || params.close)
{ // Scherm sluiten bij: 1) multi actie, 2) voltooien per categorie, 3) annuleren, 4) gereedmelden.
%> if (<%=multi? 1 : 0%> == 1 || <%=catclose? 1 : 0%> == 1 || params.cancel || params.close)
{
FcltMgr.closeDetail(window, params );
return true;

View File

@@ -157,9 +157,9 @@ if (catclose)
dist_key_arr: dist_key_arr,
loc_key_arr: loc_key_arr,
bld_key_arr: bld_key_arr,
disc_key_arr: disc_key,
srtgroep_key_arr: srtgroep_key,
srtdeel_key_arr: srtdeel_key,
disc_key_arr: disc_key_arr,
srtgroep_key_arr: srtgroep_key_arr,
srtdeel_key_arr: srtdeel_key_arr,
groep_str_arr: groep_str_arr,
categorie_key: categorie_key,
srtcontrole_key_arr: srtcontrole_key_arr,

View File

@@ -152,6 +152,7 @@ function ins_list (pautfunction, params)
});
<% } %>
var urole = "<%=urole%>";
var eigen = "<%=params.eigen||0%>";
function ins_deelkoppeling()
{
FcltMgr.openModalDetail("../ins/ins_deelkoppeling.asp?urole=<%=urole%>&ins_keys=<%=koppel_key%>",

View File

@@ -121,7 +121,8 @@ function insEdit(row)
if (ins_key > 0)
{
var url = 'appl/ins/ins_deel.asp?ins_key=' + ins_key
+ '&urole=' + urole;
+ '&urole=' + urole
+ '&self=' + eigen;
FcltMgr.openDetail(url, "", { reuse: true });
}
}

View File

@@ -189,6 +189,7 @@ var params = { urole : urole,
gwfitness_score1_through : gwfitness_score1_through,
priority_score2_from : priority_score2_from,
priority_score2_through : priority_score2_through,
eigen: eigen,
withflex: true
};
// Flags

View File

@@ -168,6 +168,8 @@ if (mode == "show" && res_ruimte_key > -1 && (S("msgraph_sync_level") & 2)) {
+ " AND rr.res_ruimte_extern_id IS NOT NULL"
+ " AND rrr.res_rsv_ruimte_verwijder IS NULL"
+ " AND rrr.res_rsv_ruimte_externsyncdate IS NULL"
+ " AND rrr.res_rsv_ruimte_externnr IS NULL"
+ " AND rrr.res_rsv_ruimte_externnr2 IS NULL"
+ " AND rro.res_ruimte_key = " + res_ruimte_key;
var oRs = Oracle.Execute(sql);
if (!oRs.EoF) {

View File

@@ -928,32 +928,70 @@ var transitParam = buildTransitParam(["deel", "groep", "categorie_key", "distric
return "";
}
function fnLocatie(oRs)
function fnLocatieX(oRs, naamofcode)
{
if (naamofcode == 1) // 1=naam
{
var locatietekst = oRs("alg_locatie_omschrijving").Value;
}
else // 2=code
{
var locatietekst = oRs("alg_locatie_code").Value;
}
if ((hasReadALGUSE || hasReadALGMAN) && outputmode == 0)
{
return "<span class='details' title='{2}' onclick='naarlocatie({0}, this)'>{1}</span>".format(oRs("alg_locatie_key").Value, safe.htmlattr(oRs("alg_locatie_omschrijving").Value), (fulldetails ? safe.htmlattr(L("lcl_estate_locatie_title")): L("ins_srtcontrole_m")));
return "<span class='details' title='{2}' onclick='naarlocatie({0}, this)'>{1}</span>".format(oRs("alg_locatie_key").Value, safe.htmlattr(locatietekst), (fulldetails ? safe.htmlattr(L("lcl_estate_locatie_title")): L("ins_srtcontrole_m")));
}
else
return safe.html(oRs("alg_locatie_omschrijving").Value);
return safe.html(locatietekst);
}
function fnLocatie(oRs)
{
return fnLocatieX(oRs, 1);
}
function fnLocatieCode(oRs)
{
return fnLocatieX(oRs, 2);
}
function fnGebouwTerreinX(oRs, naamofcode)
{
if (naamofcode == 1) // 1=naam
{
var gebouwtekst = oRs("alg_gebouw_naam").Value;
var terreintekst = oRs("alg_terreinsector_naam").Value;
}
else // 2=code
{
var gebouwtekst = oRs("alg_gebouw_code").Value;
var terreintekst = oRs("alg_terreinsector_code").Value;
}
if ((hasReadALGUSE || hasReadALGMAN) && outputmode == 0)
{
if (oRs("alg_gebouw_key").Value > 0)
return "<span class='details' title='{2}' onclick='naargebouw({0}, this)'>{1}</span>".format(oRs("alg_gebouw_key").Value, safe.html(gebouwtekst), (fulldetails ? safe.htmlattr(L("lcl_estate_gebouw_title")): L("ins_srtcontrole_m")));
else
return "<span class='details' title='{2}' onclick='naarterrein({0}, this)'>{1}</span>".format(oRs("alg_terreinsector_key").Value, safe.html(terreintekst), (fulldetails ? safe.htmlattr(L("lcl_estate_terreinsector_title")): L("ins_srtcontrole_m")));
}
else
{
if (oRs("alg_gebouw_key").Value > 0)
return safe.html(gebouwtekst);
else
return safe.html(terreintekst);
}
}
function fnGebouwTerreinCode(oRs)
{
return fnGebouwTerreinX(oRs, 2);
}
function fnGebouwTerrein(oRs)
{
if ((hasReadALGUSE || hasReadALGMAN) && outputmode == 0)
{
if (oRs("alg_gebouw_key").Value > 0)
return "<span class='details' title='{2}' onclick='naargebouw({0}, this)'>{1}</span>".format(oRs("alg_gebouw_key").Value, safe.html(oRs("alg_gebouw_naam").Value), (fulldetails ? safe.htmlattr(L("lcl_estate_gebouw_title")): L("ins_srtcontrole_m")));
else
return "<span class='details' title='{2}' onclick='naarterrein({0}, this)'>{1}</span>".format(oRs("alg_terreinsector_key").Value, safe.html(oRs("alg_terreinsector_naam").Value), (fulldetails ? safe.htmlattr(L("lcl_estate_terreinsector_title")): L("ins_srtcontrole_m")));
}
else
{
if (oRs("alg_gebouw_key").Value > 0)
return safe.html(oRs("alg_gebouw_naam").Value);
else
return safe.html(oRs("alg_terreinsector_naam").Value);
}
return fnGebouwTerreinX(oRs, 1);
}
function fnRuimte(oRs)
@@ -1296,11 +1334,14 @@ var transitParam = buildTransitParam(["deel", "groep", "categorie_key", "distric
if (groupby == 2 || groupby == 3 || moredetail == 2)
{
if (groupby == 2)
rst.addColumn(new Column({caption: L("lcl_estate_locatie_man_code"), content: "alg_locatie_code" }));
rst.addColumn(new Column({caption: L("lcl_estate_locatie_man_code"), content: fnLocatieCode, colName: "alg_locatie_code" }));
rst.addColumn(new Column({caption: L("lcl_location"), content: fnLocatie, colName: "fnLocatie" }));
}
if (fulldetails || groupby == 3 || moredetail == 2)
if (fulldetails || groupby == 3 || moredetail == 2)
{
rst.addColumn(new Column({caption: L("lcl_estate_gebouw_man_code"), content: fnGebouwTerreinCode, colName: "fnGebouwTerreinCode" }));
rst.addColumn(new Column({caption: L("lcl_bld_terra"), content: fnGebouwTerrein, colName: "fnGebouwTerrein" }));
}
if (!fulldetails || (fulldetails && mjb_show_srt_with_tasks) || moredetail == 1)
{
if (groupby >= 4 || moredetail == 1) rst.addColumn(new Column({caption: L("lcl_discipline"), content: "ins_discipline_omschrijving"}));

View File

@@ -449,11 +449,15 @@ function generateFlexKenmerkBlock(params)
+ (arrGroep.length? " OR k.mld_kenmerk_groep IN (" + arrGroep.join(",") + "))" : ")")
+ " AND " + sql_waarde + " IS NULL"; // Bij "Afmelden" de verplichte, niet ingevulde, afmelden kenmerken tonen.
}
if (halt)
sql1 += " AND k.mld_kenmerk_onderbreken > 0"; // Bij "Onderbreken" de onderbreken kenmerken tonen.
else if (!reado)
// Edit mode.
sql1 += " AND k.mld_kenmerk_onderbreken = 0"; // In de edit mode GEEN onderbreken kenmerken tonen.
if (changeOpdracht || newOpdracht)
{
if (halt)
sql1 += " AND k.mld_kenmerk_onderbreken > 0"; // Bij "Onderbreken" de onderbreken kenmerken tonen.
else if (!reado)
// Edit mode.
sql1 += " AND k.mld_kenmerk_onderbreken = 0"; // In de edit mode GEEN onderbreken kenmerken tonen.
}
}
else
{ // changeMelding || newMelding || advancedMelding

View File

@@ -685,11 +685,13 @@ div.dbezet .resoms {
font-size: 17px;
background-color: rgba(0,0,0,0.3) ;
font-weight: bold;
border-radius: 40px;
border-radius: 50%;
padding: 11px;
min-width: 20px;
text-align: center;
margin: auto auto;
width: 20px;
aspect-ratio: 1;
display: flex;
justify-content: center;
align-items: center;
}
/* Set de default jQuery mobile font-weight naar normal */

View File

@@ -32,6 +32,8 @@ var sql = "SELECT " + lcl.xsqla("rdis.ins_discipline_omschrijving", "rdis.ins_di
+ " , " + lcl.xsqla("a.res_activiteit_omschrijving", "a.res_activiteit_key")
+ " , rdis.ins_discipline_key"
+ " , ins_discipline_min_level"
+ " , res_activiteit_master_key"
+ " , res_activiteit_duur"
+ " FROM res_discipline rdis, res_activiteitdiscipline rad, res_activiteit a"
+ " WHERE rdis.ins_discipline_min_level IN (1, 5) "
+ " AND rdis.ins_discipline_key = rad.res_discipline_key"
@@ -49,6 +51,8 @@ if (oRs.eof)
// Zonder disciplines, maar ook met heeft deze query de disciplines gecheckt, we nemen de onze
res_disc_key_arr = [];
var activiteitnaam = oRs("res_activiteit_omschrijving").Value; // die gegevens is of een willekeurige bij de catalogus
var ischild = oRs("res_activiteit_master_key").Value;
var res_activiteit_duur = oRs("res_activiteit_duur").Value;
var ins_discipline_min_level;
var catalogusnaam = "??";
while (!oRs.eof)
@@ -87,6 +91,12 @@ var dagcapaciteit = getQParamFloat("capaciteit", 9); // aantal uren beschikbaa
var minimumbeschikbaarheid = getQParamFloat("minbes", 1.1); // minder dan zoveel uur beschikbaar beschouwen we onbeschikbaar
var onlyfree = getQParamInt("onlyfree", 1); // moeten bezette werkplekken wel (0) of niet (1) (onklikbaar) getoond worden in de lijst
if (ischild)
{
dagcapaciteit = 0; // als geen master gevonden
minimumbeschikbaarheid = res_activiteit_duur;
}
var transitParam = buildTransitParam(["zoom", "daylimit", "offset", "act_key", "res_disc", "geb_key", "floor_key", "wsp_key", "date", "onlyfree", "floorselect", "mapselect", "thema_key", "themaI_key", "bordlabel_key", "limit", "capaciteit", "minbes"]);
var qrc = getQParamInt("qrc", 0) != 0;
@@ -118,6 +128,22 @@ if (datelimit == -1)
<%
var buttons = [];
/* global */ var calc_dagcapaciteit;
function fnDataFilter(oRs)
{
var dt = resdate;
if (!dt) // dan moet hij in de query zitten
{
dt = new Date(oRs("datum").Value);
}
/* global */ calc_dagcapaciteit = rdpt.dagcapaciteitCalc(dt, dagcapaciteit, act_key, res_disc_key_arr);
if (!calc_dagcapaciteit)
{
return false;
}
return true;
}
// KIES GEBOUW INDIEN NOG NIET BEKEND
if (geb_key == -1)
{
@@ -193,7 +219,7 @@ if (datelimit == -1)
}
oRs_bld_afb.close();
}
if (icon == "fa-building") icon = '<div class="buildingavatar">' + safe.html((oRs("alg_locatie_plaats").Value).substr(0,2).toUpperCase()) + "</div>";
if (icon == "fa-building") icon = '<div class="buildingavatar">' + safe.html((oRs("alg_locatie_code").Value).substr(0,2).toUpperCase()) + "</div>";
return icon;
}
@@ -242,7 +268,7 @@ if (datelimit == -1)
oRs.close();
var gebouwcapaciteit = aantalitems * dagcapaciteit; // in uren
sql = rdpt.dagbezetting_resdelen_in_gebouw_sql(res_disc_key_arr, geb_key, -1, dateoffset, datelimit, null);
sql = rdpt.dagbezetting_resdelen_in_gebouw_sql(res_disc_key_arr, geb_key, -1, dateoffset, datelimit, null); // JGL: act_key
function fnrowClassD(oRs)
{
@@ -255,26 +281,37 @@ if (datelimit == -1)
}
else
{
bcls += rdpt.bezettings_class(oRs("gevuld").value, dagcapaciteit*aantalitems, minimumbeschikbaarheid*aantalitems);
bcls += rdpt.bezettings_class(oRs("gevuld").value, calc_dagcapaciteit*aantalitems, minimumbeschikbaarheid*aantalitems);
}
return bcls;
}
function fnBeschikbaarheid(oRs)
{
var txt = "";
if (oRs("vrijedag").value == 0 && (!alleenwerkdagen ||(alleenwerkdagen && (oRs("weekdag").value != 1 && oRs("weekdag").value != 7))))
if (ischild)
{
var beschikbaarheid = ((1 - (oRs("gevuld").Value/gebouwcapaciteit))*100).toFixed(0); // 0..100
txt = L("lcl_res_dagbeschikbaarpct")+" "+beschikbaarheid+"%";
// We veronderstellen (mogelijk onterecht) dat elk van de aantalitems even lang beschikbaar is op een dag
// Als er maar <20><>n master is per dag is dat zeker logisch
var blok_per_dag = Math.floor(calc_dagcapaciteit / res_activiteit_duur)*aantalitems;
beschikbaarheid = blok_per_dag - oRs("gevuld").Value/res_activiteit_duur;
var txt = beschikbaarheid+ "/" + blok_per_dag
}
else
{
if (oRs("vrijedag").value > 0) txt += L("mld_vrije_dagen")+" ";
if (oRs("weekdag").value == 1 || oRs("weekdag").value == 7)
var txt = "";
if (oRs("vrijedag").value == 0 && (!alleenwerkdagen ||(alleenwerkdagen && (oRs("weekdag").value != 1 && oRs("weekdag").value != 7))))
{
if (alleenwerkdagen)
txt += L("lcl_res_weekend");
var beschikbaarheid = ((1 - (oRs("gevuld").Value/gebouwcapaciteit))*100).toFixed(0); // 0..100
txt = L("lcl_res_dagbeschikbaarpct")+" "+beschikbaarheid+"%";
}
else
{
if (oRs("vrijedag").value > 0) txt += L("mld_vrije_dagen")+" ";
if (oRs("weekdag").value == 1 || oRs("weekdag").value == 7)
{
if (alleenwerkdagen)
txt += L("lcl_res_weekend");
}
}
}
return txt
@@ -301,6 +338,7 @@ if (datelimit == -1)
}
var rst = new ResultsetTable({ sql: sql
, fnDataFilter: fnDataFilter
, keyColumn: "datum"
, linkColumn: fnSubmitD
, singleLink: true
@@ -358,7 +396,7 @@ if (datelimit == -1)
var bcls= "";
var sql2 = rdpt.dagbezetting_resdelen_in_gebouw_sql(res_disc_key_arr, geb_key, oRs("alg_verdieping_key").value, dateoffset, datelimit, resdate);
oRs2 = Oracle.Execute(sql2)
bcls += rdpt.bezettings_class(oRs2("gevuld").value, dagcapaciteit*oRs("aantal").value, minimumbeschikbaarheid*oRs("aantal").value);
bcls += rdpt.bezettings_class(oRs2("gevuld").value, calc_dagcapaciteit*oRs("aantal").value, minimumbeschikbaarheid*oRs("aantal").value);
oRs2.close();
return bcls; // te duur
}
@@ -366,7 +404,7 @@ if (datelimit == -1)
function fnBeschikbaarheidF(oRs)
{
var txt = "";
var vloercapaciteit = oRs("aantal").value * dagcapaciteit; // in uren
var vloercapaciteit = oRs("aantal").value * calc_dagcapaciteit; // in uren
var sql2 = rdpt.dagbezetting_resdelen_in_gebouw_sql(res_disc_key_arr, geb_key, oRs("alg_verdieping_key").value, dateoffset, datelimit, resdate);
oRs2 = Oracle.Execute(sql2);
// Stop when invalid date is detected
@@ -381,13 +419,14 @@ if (datelimit == -1)
else
{
var beschikbaarheid = ((1 - (oRs2("gevuld").Value/vloercapaciteit))*100).toFixed(0); // 0..100
txt = L("lcl_res_dagbeschikbaarpct")+" "+beschikbaarheid+"%";
txt = L("lcl_res_dagbeschikbaarpct")+" "+calc_dagcapaciteit+"%";
}
oRs2.close();
return txt
}
var rst = new ResultsetTable({ sql: sql
, fnDataFilter: fnDataFilter
, keyColumn: "alg_verdieping_key"
, linkColumn: fnSubmitF
, singleLink: true
@@ -495,7 +534,7 @@ if (datelimit == -1)
function fnrowClassRD(oRs)
{
return rdpt.bezettings_class(oRs("bezet").value, dagcapaciteit, minimumbeschikbaarheid);
return rdpt.bezettings_class(oRs("bezet").value, calc_dagcapaciteit, minimumbeschikbaarheid);
}
function fnResDeelIcon(oRs)
{
@@ -508,7 +547,7 @@ if (datelimit == -1)
}
else if (oRs.Fields("ins_discipline_image").Value != null)
icon = oRs.Fields("ins_discipline_image").Value;
return icon;
}
@@ -518,7 +557,7 @@ if (datelimit == -1)
}
function fnSubmitRD(oRs)
{
if (oRs("bezet").value < dagcapaciteit - minimumbeschikbaarheid)
if (oRs("bezet").value < calc_dagcapaciteit - minimumbeschikbaarheid)
return "../pda/reserveringen.asp?qrc="+(qrc?1:0)+"&res_deel_key=" + oRs("res_deel_key").Value + "&res_van="+(new Date(resdate).getTime())
else
return "";
@@ -528,6 +567,7 @@ if (datelimit == -1)
sql = rdpt.res_deel_bezetting_op_dag_sql(res_disc_key_arr, geb_key, floor_key, resdate, (onlyfree ? dagcapaciteit - minimumbeschikbaarheid : null));
var rst = new ResultsetTable({ sql: sql
, fnDataFilter: fnDataFilter // zet globale calc_dagcapaciteit
, keyColumn: "res_deel_key"
, linkColumn: fnSubmitRD
, singleLink: true

View File

@@ -31,7 +31,7 @@ var JSON_Result = true;
Session("org_user_key") = user_key;
Session("org_user_key_ts") = new Date().getTime();
shared.trackaction("PRSLOG", prs_key, L("lcl_impersonated") +" "+ L("lcl_impersonate_reason") + ": " + prs_reason);
shared.trackaction("PRSLOG", prs_key, L("lcl_impersonated") + " ('" + prs_reason + "')");
doLogin(prs_key);
result = { success: "true" };

View File

@@ -1491,15 +1491,6 @@ FCLTHeader.Requires({ plugins: ["jQuery", "kenmerk"] });
res_activiteit_meteindtijd="<%=rrr.activiteit_meteindtijd? 1 : 0%>"
res_activiteit_cvab_mode="<%=rrr.ab_mode? rrr.ab_mode : 0%>"
res_activiteit_intervals="<%=rrr.activiteit_intervals%>">
<script type="text/javascript">
$(function()
{
checkVeldenVerplicht();
<% if (rrr.reservering_key < 0) { %>
autosetEindtijd();
<% } %>
});
</script>
<%
FCLTcalendar( "date_to",
@@ -1523,6 +1514,18 @@ FCLTHeader.Requires({ plugins: ["jQuery", "kenmerk"] });
required : true,
onChangeTime : '$("#time_from_date_to").css("color", "inherit"); onChangeTijd(event);'
});
%>
<script type="text/javascript">
$(function()
{
checkVeldenVerplicht();
<% if (rrr.reservering_key < 0) { %>
autosetEindtijd();
<% } %>
});
</script>
<%
// ======= FIELD 'Aantal personen/nr visitors' =======
if (rrr.srtactiviteit_metaantal)
{

View File

@@ -863,7 +863,8 @@ var flextrack = saveFlexKenmerken(rsv_ruimte_key,
/* Update een evt. Exchange event (via MS Graph) */
if (restype == "R" && extern_id != null && (S("msgraph_sync_level") & 6) // Er is een ReadWrite exchange-koppeling voor deze ruimte
&& (isNew || resdateChanged || onlineProviderChanged || omsChanged || opmChanged)) // Er moet wel iets te muteren zijn
&& (isNew || resdateChanged || onlineProviderChanged || omsChanged || opmChanged) // Er moet wel iets te muteren zijn
&& (isNew || this_res.canWriteExtern)) // Deze is false als we S("msgraph_sync_level") & 2 gebruiken en de reservering is vanuit Outlook geinitieerd
{
var DEZE = this;
var hookfile = Server.MapPath(rooturl + "/utils/exchange/res_to_graph.wsc");

View File

@@ -521,7 +521,13 @@ function res_list (pautfunction, params)
sql_floor = " AND ruimte_geg.alg_verdieping_key IN (" + floor_key_arr.join(",") + ")";
if (room_key_arr.length) {
sql_room = " AND ruimte_geg.alg_ruimte_key IN (" + room_key_arr.join(",") + ")";
sql_room = " AND ( ruimte_geg.alg_ruimte_key IN (" + room_key_arr.join(",") + ")"
+ " OR res_geg.res_ruimte_key IN"
+ " (SELECT r.res_ruimte_key"
+ " FROM res_alg_ruimte r"
+ " WHERE r.alg_ruimte_key IN (" + room_key_arr.join(",") + ")"
+ " )"
+ " )";
}
}
@@ -776,7 +782,6 @@ function res_list (pautfunction, params)
+ " , " + lcl.xsqla("rr.res_ruimte_nr", "rr.res_ruimte_key")
+ " , MIN(rar.alg_ruimte_key) alg_ruimte_key"
+ " , rro.res_ruimte_opstel_default"
+ (res_key ? "" : ", rar.res_alg_ruimte_key")
+ " FROM res_ruimte_opstelling rro, res_alg_ruimte rar, res_ruimte rr"
+ " WHERE rro.res_ruimte_key = rar.res_ruimte_key"
+ " AND rr.res_ruimte_key = rar.res_ruimte_key"
@@ -787,7 +792,6 @@ function res_list (pautfunction, params)
+ " GROUP BY rro.res_ruimte_opstel_key"
+ " , " + lcl.xsql("rr.res_ruimte_nr", "rr.res_ruimte_key")
+ " , rro.res_ruimte_opstel_default"
+ (res_key ? "" : ", rar.res_alg_ruimte_key")
+ " ) opstelalg"
+ " , prs_kostenplaats k"
+ " , prs_v_afdeling_boom boom";

View File

@@ -123,59 +123,19 @@ var contmode = getQParamInt("contmode", 0); // contouren aan 0 of
var resdate = getQParamDate("date", null); // de (in stap 2 gekozen) datum
var dagcapaciteit = getQParamFloat("dagcapaciteit", 9); // aantal uren beschikbaar per dag tbv berekening van globale vulling
function dagcapaciteitCalc(date)
// minder dan zoveel uur beschikbaar beschouwen we onbeschikbaar
var minimumbeschikbaarheid = getQParamFloat("minbes", ischild?res_activiteit_duur:1.5);
if (ischild)
{
var begintijd = new Date(0, 0, 0, 23, 59, 0);
var eindtijd = new Date(0, 0, 0, 0, 0, 0);
var btBegintijd;
var btEindtijd;
var btArr;
var index;
var bt = [];
if (act_key > 0)
{
bt = res.getBloktijdenAct(act_key, date);
}
if (!bt.length)
{
// Neem bij meerdere disciplines alleen de eerste: De bloktijden zouden hetzelfde moeten zijn. Mergen van twee disciplines is niet mogelijk.
var bt = res.getBloktijdenDisc(res_disc_key_arr[0], date);
}
if (bt.length > 0)
{
for (index = 0; index < bt.length; index++)
{
btArr = bt[index].begin.split(":");
btBegintijd = new Date(0, 0, 0, btArr[0], btArr[1], 0);
if (btBegintijd.getTime() < begintijd.getTime())
{
begintijd = btBegintijd;
}
btArr = bt[index].end.split(":");
btEindtijd = new Date(0, 0, 0, btArr[0], btArr[1], 0);
if (btEindtijd.getTime() > eindtijd.getTime())
{
eindtijd = btEindtijd;
}
}
var diff = eindtijd.getTime() - begintijd.getTime();
var uren = Math.floor(diff / 1000 / 60 / 60);
diff -= uren * 1000 * 60 * 60;
var minuten = Math.floor(diff / 1000 / 60) / 60; // make minutes decimal
return uren + minuten;
}
else
{
return dagcapaciteit;
}
dagcapaciteit = 0; // als geen master gevonden
res_activiteit_duur = 0;
}
if (resdate)
{
dagcapaciteit = dagcapaciteitCalc(resdate);
dagcapaciteit = rdpt.dagcapaciteitCalc(resdate, dagcapaciteit, act_key, res_disc_key_arr);
}
// minder dan zoveel uur beschikbaar beschouwen we onbeschikbaar
var minimumbeschikbaarheid = getQParamFloat("minbes", ischild?res_activiteit_duur:1.5);
var onlyfree = getQParamInt("onlyfree", 0); // moeten bezette werkplekken wel (0) of niet (1) (onklikbaar) getoond worden in de lijst
var thema_key = getQParamInt("thema_key", 12); // Voor ruimtekleuren (noot: niet zeker of die niet 13 als default moet zijn)
@@ -513,13 +473,25 @@ if (datelimit == -1)
var reserveerbaredag = true;
var aantalitems = oRs("delen").Value;
var calc_dagcapaciteit = dagcapaciteitCalc(new Date(oRs("datum").Value));
var calc_dagcapaciteit = rdpt.dagcapaciteitCalc(new Date(oRs("datum").Value), dagcapaciteit, act_key, res_disc_key_arr);
if (!calc_dagcapaciteit)
{
__Log("No capacity on " + toDateString(oRs("datum").Value));
oRs.MoveNext();
continue;
}
var beschikbaarheid = ((1 - (oRs("gevuld").Value/(calc_dagcapaciteit*aantalitems)))*100).toFixed(0); // 0..100
if (ischild)
{
// We veronderstellen (mogelijk onterecht) dat elk van de aantalitems even lang beschikbaar is op een dag
// Als er maar <20><>n master is per dag is dat zeker logisch
var blok_per_dag = Math.floor(calc_dagcapaciteit / res_activiteit_duur)*aantalitems;
beschikbaarheid = blok_per_dag - oRs("gevuld").Value/res_activiteit_duur;
}
else
{
var beschikbaarheid = ((1 - (oRs("gevuld").Value/(calc_dagcapaciteit*aantalitems)))*100).toFixed(0); // 0..100
}
var bcls = rdpt.bezettings_class(oRs("gevuld").value, calc_dagcapaciteit*aantalitems, minimumbeschikbaarheid*aantalitems);
if (oRs("vrijedag").value > 0)
{
@@ -545,7 +517,9 @@ if (datelimit == -1)
style='width:14%; height: 12vw;' <%=clickaction%>>
<div class="iconitem">
<div class="icondate iconimg <%=bcls%>"><%=toDateString(oRs("datum").Value, false, true) %></div>
<div class="res-iconlabel"><%=licon%><%=aantalitems+" "+safe.html(oRs("ins_discipline_omschrijving").Value).toLowerCase()%><br><%=L("lcl_mobile_resbeschikbaar")+" "+safe.html("" +" "+beschikbaarheid +"%") %></div>
<div class="res-iconlabel"><%=licon%><%=aantalitems+" "+safe.html(oRs("ins_discipline_omschrijving").Value).toLowerCase()%>
<br><%=L("lcl_mobile_resbeschikbaar")+" " +(ischild?(beschikbaarheid+ "/" + blok_per_dag):beschikbaarheid +"%") %>
</div>
</div>
</div>
<%

View File

@@ -79,6 +79,7 @@ rdpt = {
{
var lsql = " SELECT l.alg_locatie_plaats"
+ " , l.alg_locatie_code"
+ " , g.alg_gebouw_naam"
+ " , g.alg_gebouw_key"
+ " , g.alg_gebouw_image"
@@ -117,6 +118,7 @@ rdpt = {
+ " AND niveau = " + p_alglevel + ")";
}
lsql += " GROUP BY l.alg_locatie_plaats"
+ " , l.alg_locatie_code"
+ " , g.alg_gebouw_naam"
+ " , g.alg_gebouw_key"
+ " , g.alg_gebouw_image"
@@ -131,6 +133,7 @@ rdpt = {
if (p_gebouw_key == -1)
{
lsql = "SELECT alg_locatie_plaats,"
+ " alg_locatie_code,"
+ " alg_gebouw_naam,"
+ " alg_gebouw_key,"
+ " alg_gebouw_image,"
@@ -139,6 +142,7 @@ rdpt = {
+ " SUM (aantal) aantal"
+ " FROM (" + lsql + ")"
+ " GROUP BY alg_locatie_plaats,"
+ " alg_locatie_code,"
+ " alg_gebouw_naam,"
+ " alg_gebouw_key,"
+ " alg_gebouw_image,"
@@ -170,7 +174,9 @@ rdpt = {
// Dagbezetting (som van de gereserveerde uren) van iedere dag vanaf vandaag+offset t/m vandaag+limit, inclusief de lege dagen
// Als p_resdate is gegeven, dan wordt uiteindelijk alleen het record voor die dag daaruit geselecteerd.
dagbezetting_resdelen_in_gebouw_sql: function (p_res_disc_key_arr, p_geb_key, p_flr_key, p_dateoffset, p_datelimit, p_resdate)
// Als p_act_key is meegegeven en het is een child-activiteit dan worden alleen dagen meegenomen waar
// de master een reservering heeft
dagbezetting_resdelen_in_gebouw_sql: function (p_res_disc_key_arr, p_geb_key, p_flr_key, p_dateoffset, p_datelimit, p_resdate, p_act_key)
{
var lsql = "SELECT datum, SUM (gevuld) gevuld, MAX (aantal) aantal, MAX (vrijedag) vrijedag, MAX (weekdag) weekdag "
+ "FROM ("
@@ -207,13 +213,35 @@ rdpt = {
+ " FROM mld_vrije_dagen vrij"
+ " WHERE vrij.mld_vrije_dagen_datum BETWEEN TRUNC (SYSDATE +"+(p_dateoffset||0)+") AND TRUNC (SYSDATE-1+"+(p_dateoffset||0)+"+"+p_datelimit+") "
+ ")"
+ "GROUP BY datum "
+ "ORDER BY 1" ;
+ "GROUP BY datum ";
if (p_resdate)
{
lsql = "SELECT * FROM (" + lsql + ") WHERE datum = " + p_resdate.toSQL();
}
if (p_act_key > 0)
{
var sql = "SELECT res_activiteit_master_key"
+ " , res_activiteit_duur"
+ " FROM res_activiteit "
+ " WHERE res_activiteit_key = " + p_act_key;
var oRs = Oracle.Execute(sql);
var master_act_key = oRs("res_activiteit_master_key").Value;
var res_activiteit_duur = oRs("res_activiteit_duur").Value;
oRs.close();
if (master_act_key > 0)
{
lsql = "SELECT * FROM (" + lsql + ")"
+ " WHERE EXISTS (SELECT 1 FROM res_rsv_ruimte"
+ " WHERE res_rsv_ruimte_verwijder IS NULL"
+ " AND res_activiteit_key = " + master_act_key
+ " AND TRUNC(res_rsv_ruimte_van) = datum"
+ " )";
}
}
lsql = lsql + "ORDER BY 1";
return lsql;
},
@@ -493,7 +521,50 @@ rdpt = {
lres = "";
return lres;
}
},
// Bereken een specifieke(re) dagcapaciteit
// Het kan afhankelijk zijn van de bloktijden die zijn gedefinieerd.
// Dan wordt 'date' alleen gebruikt om de bloktijden naar 'date' te verschuiven
// Als act_key een subreservering is wordt zelfs gekeken of er op date een master-reservering is
dagcapaciteitCalc: function _dagcapaciteitCalc(date, dagcapaciteit, act_key, res_disc_key_arr)
{
var begintijd = new Date(0, 0, 0, 23, 59, 0);
var eindtijd = new Date(0, 0, 0, 0, 0, 0);
var btBegintijd;
var btEindtijd;
var btArr;
var index;
// Neem bij meerdere disciplines alleen de eerste: De bloktijden zouden hetzelfde moeten zijn.
// Mergen van twee disciplines is niet mogelijk.
var bt = res.getBloktijden(act_key, res_disc_key_arr[0], date);
if (bt.length > 0)
{
for (index = 0; index < bt.length; index++)
{
btArr = bt[index].begin.split(":");
btBegintijd = new Date(0, 0, 0, btArr[0], btArr[1], 0);
if (btBegintijd.getTime() < begintijd.getTime())
{
begintijd = btBegintijd;
}
btArr = bt[index].end.split(":");
btEindtijd = new Date(0, 0, 0, btArr[0], btArr[1], 0);
if (btEindtijd.getTime() > eindtijd.getTime())
{
eindtijd = btEindtijd;
}
}
var diff = eindtijd.getTime() - begintijd.getTime();
var uren = Math.floor(diff / 1000 / 60 / 60);
diff -= uren * 1000 * 60 * 60;
var minuten = Math.floor(diff / 1000 / 60) / 60; // make minutes decimal
return uren + minuten;
}
else
{
return dagcapaciteit;
}
}
}
%>

View File

@@ -161,14 +161,16 @@ oRs.Close();
// nooit gecombineerd), maar verfijnder willen we niet.
var sql = "SELECT ''"
+ " FROM res_deel"
+ " WHERE res_deel_prijs IS NOT NULL"
+ " AND res_deel_verwijder IS NULL"; // ignore vervaldatum ok
+ " WHERE (res_deel_prijs IS NOT NULL OR res_deel_prijs_vast = 0)" // prijs is mogelijk
+ " AND (res_deel_vervaldatum IS NULL OR res_deel_vervaldatum > SYSDATE)" // actueel relevant
+ " AND res_deel_verwijder IS NULL"; // niet historisch
var oRs = Oracle.Execute(sql);
var anydeelprijs = !oRs.eof;
oRs.close();
sql = "SELECT ''"
+ " FROM res_artikel"
+ " WHERE res_artikel_prijs IS NOT NULL"
+ " WHERE (res_artikel_prijs IS NOT NULL OR res_artikel_prijs_vast = 0)"
+ " AND (res_artikel_vervaldatum IS NULL OR res_artikel_vervaldatum > SYSDATE)"
+ " AND res_artikel_verwijder IS NULL";
oRs = Oracle.Execute(sql);
var anyartikelprijs = !oRs.eof;

View File

@@ -101,6 +101,7 @@ if (!groep || user.has("WEB_FACTAB"))
bijlagen("WEB_FACTAB", custpath + "/export bestanden", "CUSTEXP", true);
bijlagen("WEB_FACTAB", custpath + "/import bestanden", "CUSTIMP", true);
bijlagen("WEB_FACTAB", custpath + "/tasks bestanden", "CUSTTASKS", true);
bijlagen("WEB_FACTAB", custpath + "/exchange bestanden", "CUSTEXCH", true);
bijlagen("WEB_FACTAB", "hMailServer logbestanden", "SMTP", true);
bijlagen("WEB_FACTAB", "Shibboleth SAML logbestanden", "SHIB", true);
BLOCK_END();

View File

@@ -635,6 +635,15 @@ function flexProps(pModule, pKey, pSubpath, pNiveau, params)
result.autfunctionapiread = 'WEB_FACTAB';
result.autfunctionapiwrite = 'WEB_FACTAB';
break;
case "CUSTEXCH":
result.AttachRootPath = Server.MapPath(custpath + "/exchange");
result.AttachPath = result.AttachRootPath + "/";
result.extFilter = "log";
settings.overrule_setting("flexAllowedExt", result.extFilter); // tijdelijk log toestaan
settings.overrule_setting("flexFilesOrdering", 0);
result.autfunctionapiread = 'WEB_FACTAB';
result.autfunctionapiwrite = 'WEB_FACTAB';
break;
case "CUSTTEMP":
result.AttachRootPath = shared.tempFolder();
result.AttachPath = result.AttachRootPath + "/";

View File

@@ -64,8 +64,8 @@ i.suggestklikker {
cursor: pointer;
}
i.suggestklikker:hover{
color: red;
i.suggestklikker:hover {
color: var(--buttonhoverbackgroundcolor);
font-weight: 900;
}

View File

@@ -3968,7 +3968,7 @@ table#vis_tab .suggestBad {
position: relative;
z-index: 1;
right: 20px;
color: #7B7B7B; /* gelijk aan i.suggestklikker */
color: var(--buttonhoverbackgroundcolor);
cursor: pointer;
width: 0;
}
@@ -6083,8 +6083,11 @@ tr.rscols_combined td {
border-color: transparent!important;
}
.ui-widget-content{
border: 1px solid #eee;
.ui-widget-content {
border: 1px solid #eee;
}
.ui-dialog:not(.ui-resizable) .ui-dialog-content {
position: static;
}
li.hiddenbutton {

View File

@@ -8,7 +8,7 @@
Context: Vanuit ELK asp bestand
*/
var FCLTVersion="2023.1RC2";
var FCLTVersion="2023.1RC3";
var FCLTMinDatabaseSchema="44"; // Alleen de cijfers
var custpath = rooturl + "/cust/" + customerId; // path to customer files

View File

@@ -17,6 +17,8 @@
<script language="JScript" src="../wsf_shared.js"/>
<script language="JScript" src="../json2.js"/>
<script language="JScript" src="ms_graph.js"/>
<script language="JScript" src="exchange_graph.js"/>
<script language="JScript" src="../../appl/imp/imp_shared.js"/>
<script language="JScript">
/* global */ var custabspath = fso.GetAbsolutePathName("../");
@@ -34,25 +36,18 @@
else
{ // Autodetect ngrok started with: ngrok http sggr.facws001.sg.nl:80
var ngrokurl = null;
try
{ // Probeer of ngrrok is opgestart
var result = doHTTP('GET',
'http://127.0.0.1:4040/api/tunnels/command_line',
null,
{"Content-Type": "application/json"});
var json = JSON.parse(result.responseText);
ngrokurl = json.public_url; // https://09f8481827d5.ngrok.io
__Log("Ngrok detected: " + ngrokurl);
__Log(" tip: view traffic at http://127.0.0.1:4040");
hookurl = ngrokurl + "/trunk/";
}
catch(e)
{
__Log("Usage: CScript create_webhooks.wsf <<hookurl>>");
__Log(" hookurl: https://xxxx.facilitor.nl");
__Log("For local testing start ngrok.exe en omit hookurl");
WScript.Quit(1);
var request = {
"method": "GET",
"url": "http://127.0.0.1:4040/api/tunnels/command_line",
"headers": {"Content-Type": "application/json"},
"params": { "callback": function (request, response) {
__Log("Ngrok detected: " + response.public_url);
__Log(" tip: view traffic at http://127.0.0.1:4040");
hookurl = response.public_url + "/branch20231/"; /* TODO revert naar trunk */
}
}
}
doHTTP(request);
}
__Log("Using hookurl : " + hookurl);
@@ -63,16 +58,19 @@
var token = requestToken(config);
var sql = "BEGIN DBMS_APPLICATION_INFO.SET_MODULE ('create_webhooks.wsf', NULL); END;";
Oracle.Execute(sql);
var sql = "SELECT fac_version_cust FROM fac_version";
var oRs = Oracle.Execute(sql);
var customerId = oRs(0).Value;
// Determine customerId
sql = "SELECT fac_version_cust FROM fac_version";
oRs = Oracle.Execute(sql);
var customerId = oRs("fac_version_cust").Value;
oRs.Close();
var sql = "SELECT prs_perslid_apikey FROM prs_perslid WHERE prs_perslid_oslogin = '_MSGRAPHNOTIFICATION'";
var oRs = Oracle.Execute(sql);
var apikey = oRs(0).Value;
// Get the api-(user)key
sql = "SELECT prs_perslid_key, prs_perslid_apikey FROM prs_perslid WHERE prs_perslid_oslogin = '_MSGRAPHNOTIFICATION'";
oRs = Oracle.Execute(sql);
var apikey = oRs("prs_perslid_apikey").Value;
var user_key = oRs("prs_perslid_key").Value;
oRs.Close();
var webhookurl = hookurl + "?API={0}&APIKEY={1}&fac_id={2}".format(apiname, apikey, customerId); // fac_id is vooral voor ngrok nodig
@@ -83,18 +81,21 @@
WScript.Quit(1);
}
var sql = "SELECT res_ruimte_key,"
+ " res_ruimte_extern_id,"
+ " res_ruimte_graphhooksecret"
+ " FROM res_ruimte"
+ " WHERE res_ruimte_verwijder IS NULL"
+ " AND res_ruimte_extern_id IS NOT NULL";
var oRs = Oracle.Execute(sql);
while (!oRs.Eof)
{
createSubscription( oRs("res_ruimte_extern_id").Value,
oRs("res_ruimte_key").Value,
webhookurl);
sql = "SELECT res_ruimte_key,"
+ " res_ruimte_extern_id,"
+ " res_ruimte_graphhooksecret"
+ " FROM res_ruimte"
+ " WHERE res_ruimte_verwijder IS NULL"
+ " AND res_ruimte_extern_id IS NOT NULL";
oRs = Oracle.Execute(sql);
while (!oRs.Eof) {
// Fullsync bij het aanmaken van een nieuwe subscription zodat we volgens updates snel met een deltatoken kunnen ophalen
var zaalemail = oRs("res_ruimte_extern_id").Value;
var res_ruimte_key = oRs("res_ruimte_key").Value;
createSubscription( zaalemail,
res_ruimte_key,
webhookurl,
true); // Voorkomt onnodige validaties van de notificatie-url, want dat is hierboven al gebeurd
oRs.MoveNext();
}
oRs.Close();

View File

@@ -37,8 +37,12 @@
}
var success = true;
for (var i = 0; i < subscriptionList.length; i++) {
var xhr = doHTTP("DELETE", "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionList[i].id, null, { "Accept": "application/json", "Authorization": "Bearer " + token });
success = success && xhr !== null && xhr.status === 204;
var request = {
"method": "DELETE",
"url": "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionList[i].id,
"headers": { "Accept": "application/json", "Authorization": "Bearer " + token }
}
success = success && doHTTP(request);
}
if (success) {
WScript.Echo(subscriptionList.length + " subscription(s) deleted");

View File

@@ -21,7 +21,7 @@ var fso = new ActiveXObject("Scripting.FileSystemObject");
function csv_for_room(zaalemail, import_app_code, as_stream)
{
__Log("Connecting to Graph API")
__Log("Connecting to Graph API");
// ---
// kunnen we niets mee doExchange(config.endpointurl, "<m:GetRoomLists />", "roomlist.xml");
@@ -36,7 +36,7 @@ function csv_for_room(zaalemail, import_app_code, as_stream)
var import_app_files_pre = "sync_";
var sql = "SELECT i.fac_import_app_files "
+ " FROM fac_import_app i"
+ " WHERE i.fac_import_app_code = " + safe.quoted_sql(import_app_code);
+ " WHERE i.fac_import_app_code = " + safe.quoted_sql(String(import_app_code));
var oRs = Oracle.Execute(sql);
if (!oRs.EOF)
{
@@ -46,12 +46,12 @@ function csv_for_room(zaalemail, import_app_code, as_stream)
oRs.Close();
// Vanaf hier alleen wijzigingen ophalen
var sql = "SELECT s.res_ruimte_key sync_key, r.res_ruimte_key, s.res_ruimte_syncstate" // syncstate is deltatoken
+ " FROM res_ruimte r"
+ " , res_ruimte_sync s"
+ " WHERE r.res_ruimte_key = s.res_ruimte_key(+)"
+ " AND r.res_ruimte_verwijder IS NULL"
+ " AND res_ruimte_extern_id = '" + zaalemail + "'";
sql = "SELECT s.res_ruimte_key sync_key, r.res_ruimte_key, s.res_ruimte_syncstate" // syncstate is deltatoken
+ " FROM res_ruimte r"
+ " , res_ruimte_sync s"
+ " WHERE r.res_ruimte_key = s.res_ruimte_key(+)"
+ " AND r.res_ruimte_verwijder IS NULL"
+ " AND res_ruimte_extern_id = '" + zaalemail + "'";
oRs = Oracle.Execute(sql);
sync_key = oRs("sync_key").Value; // value null means not there
@@ -80,6 +80,9 @@ function csv_for_room(zaalemail, import_app_code, as_stream)
}
var response = getCalendarItems(zaalemail, null, deltatoken);
if (typeof DEZE != "undefined" && response) { /* TODO debug log weghalen */
__DoLog(response, "lightblue");
}
if (response && response.value)
{
var results = response.value;
@@ -89,7 +92,34 @@ function csv_for_room(zaalemail, import_app_code, as_stream)
results.push(response.value[index]);
}
}
if (!("deltatoken" in response)) {
// Het laatste antwoord bevatte geen deltatoken, dat hoort er altijd te zijn, waarschijnlijk een MS Graph fout.
return _handleMsGraphFailure(null, response);
}
deltatoken = response.deltatoken;
// deltatoken needs to be saved (asap) to retrieve changes only during a future run
var sql;
if (sync_key)
{
sql = "UPDATE res_ruimte_sync s"
+ " SET s.res_ruimte_syncstate = " + safe.quoted_sql(deltatoken, 32000) + ", s.res_ruimte_syncdate = SYSDATE"
+ " WHERE s.res_ruimte_key = " + sync_key;
}
else // Deze mag niet meer voorkomen, want we maken nu bij 'createSubscription' al een record aan voor de res_ruimte
{
sql = "INSERT INTO res_ruimte_sync (res_ruimte_key,"
+ " res_ruimte_syncstate,"
+ " res_ruimte_syncdate)"
+ " SELECT " + res_ruimte_key + ", " + safe.quoted_sql(deltatoken, 32000) + ", SYSDATE"
+ " FROM DUAL"
+ " WHERE NOT EXISTS" // Voorkom meerdere entries per ruimte bij snelle updates achter elkaar
+ " (SELECT 1"
+ " FROM res_ruimte_sync s"
+ " WHERE s.res_ruimte_key = " + res_ruimte_key + ")";
}
oRs = Oracle.Execute(sql);
var csvFileText = makeCSV(results, zaalemail);
// save the CSV file to disc here
fileStream = new ActiveXObject("ADODB.Stream");
@@ -110,36 +140,9 @@ function csv_for_room(zaalemail, import_app_code, as_stream)
}
}
// deltatoken needs to be saved to retrieve changes during a future run
var sql;
if (sync_key)
{
sql = "UPDATE res_ruimte_sync s"
+ " SET s.res_ruimte_syncstate = " + safe.quoted_sql(deltatoken, 32000) + ", s.res_ruimte_syncdate = SYSDATE"
+ " WHERE s.res_ruimte_key = " + sync_key;
}
else
{
sql = "INSERT INTO res_ruimte_sync (res_ruimte_key,"
+ " res_ruimte_syncstate,"
+ " res_ruimte_syncdate)"
+ " SELECT " + res_ruimte_key + ", " + safe.quoted_sql(deltatoken, 32000) + ", SYSDATE"
+ " FROM DUAL"
+ " WHERE NOT EXISTS" // Voorkom meerdere entries per ruimte bij snelle updates achter elkaar
+ " (SELECT 1"
+ " FROM res_ruimte_sync s"
+ " WHERE s.res_ruimte_key = " + res_ruimte_key + ")";
}
oRs = Oracle.Execute(sql);
// Als we hier komen is alles goed
return fileStream;
}
else
{
__Log("User for email address " + zaalemail + " not found");
return false;
}
}
function getMasterEvent(data, id) {
@@ -151,7 +154,9 @@ function getMasterEvent(data, id) {
break;
}
}
__Log(JSON.stringify(result));
if (typeof DEZE != "undefined") {
__Log(JSON.stringify(result));
}
return result;
}
@@ -159,11 +164,12 @@ function getReserveringByEvent(_id, _occurrence, _email)
{
var eventSql = "SELECT res_rsv_ruimte_omschrijving"
+ " , res_rsv_ruimte_dirtlevel"
+ " , res_rsv_ruimte_externnr2"
+ " FROM res_rsv_ruimte rr,"
+ " res_ruimte_opstelling ro,"
+ " res_ruimte r"
+ " WHERE rr.res_rsv_ruimte_externnr IS NOT NULL"
+ " AND rr.res_rsv_ruimte_externnr LIKE " + safe.quoted_sql(_id) + "||'|'||" + (_occurrence ? safe.quoted_sql(_occurrence) : "''") + "||'|%'"
+ " AND rr.res_rsv_ruimte_externnr LIKE " + safe.quoted_sql(_id) + " || '|' || " + (_occurrence ? safe.quoted_sql(_occurrence) : "''") + " || '|%'"
+ " AND rr.res_rsv_ruimte_verwijder IS NULL"
+ " AND ro.res_ruimte_opstel_key = rr.res_ruimte_opstel_key"
+ " AND r.res_ruimte_key = ro.res_ruimte_key"
@@ -174,6 +180,7 @@ function getReserveringByEvent(_id, _occurrence, _email)
if (!eventoRs.eof)
_returnValue = {
"description": eventoRs("res_rsv_ruimte_omschrijving").Value,
"organisatorId": eventoRs("res_rsv_ruimte_externnr2").Value || "",
"isDirty": (eventoRs("res_rsv_ruimte_dirtlevel").Value || 0 > 0)
};
eventoRs.Close();
@@ -211,6 +218,9 @@ function makeCSV(data, zaalemail)
*/
for (index = 0; index < data.length; index++)
{
if (typeof DEZE !== "undefined") { /* TODO debug log weghalen */
__DoLog(data[index], "green");
}
if ((getMSGraphSyncLevel() & 4) && "responseStatus" in data[index] && data[index].responseStatus.response == "notResponded")
{ /*
Bij S("msgraph_sync_level") & 2 is dit "organizer"
@@ -219,11 +229,20 @@ function makeCSV(data, zaalemail)
continue; // Hier doen we (nog) niets mee
}
if (getMSGraphSyncLevel() & 4) // ReadWrite
{
var fcltRsv = getReserveringByEvent(data[index].id, data[index].OccurrenceId, zaalemail);
if (fcltRsv === null) // Niet gevonden in Facilitor onder het externnr
updateExternnr(zaalemail, data[index].id); // Misschien moet het externnr nog gesync'd worden ?
var fcltRsv = getReserveringByEvent(data[index].id, data[index].OccurrenceId, zaalemail);
if (getMSGraphSyncLevel() > 2) {
if ((fcltRsv !== null && fcltRsv.organisatorId == data[index].id) || // Hij is bekend in Facilitor en de ruimte is de organisator
fcltRsv === null && data[index].isOrganizer) { // Hij is niet bekend in Fclt en de ruimte is de organisator
// Beide ondersteunen we niet
if (typeof DEZE !== "undefined") { /* TODO debug log weghalen */
__DoLog("Unsupported/ignored: notification from Outlook for an Event with the room-resource as the organizer (most likely Facilitor initiated)", "#FFFF44");
}
continue;
}
}
if (getMSGraphSyncLevel() & 4 && fcltRsv === null) { // ReadWrite
updateExternnr(zaalemail, data[index].id); // Misschien moet het externnr nog gesync'd worden ?
}
// deleted event
@@ -231,7 +250,7 @@ function makeCSV(data, zaalemail)
{ // {"@odata.type":"#microsoft.graph.event","id":"AAMkAGQ1Yz.......","@removed":{"reason":"deleted"}}
if (getMSGraphSyncLevel() & 4)
{ // Deze gaan vanzelf goed; de reservering blijft (dirty) staan in Facilitor en de ruimte declined het event in Exchange
var fcltRsv = getReserveringByEvent(data[index].id, data[index].OccurrenceId, zaalemail);
// Wordt overigens bij de nachtelijk full sync alsnog verwijderd, dan had je het maar moeten rechtzetten
if (fcltRsv && fcltRsv.isDirty)
continue;
}
@@ -257,9 +276,8 @@ function makeCSV(data, zaalemail)
if (_startDate.getTime() >= curDate.getTime())
{
{
var fcltRsv = getReserveringByEvent(data[index].id, data[index].OccurrenceId, zaalemail);
var modifier = fcltRsv == null ? "C" : "U"; // [U]pdate of [C]reate
var doImportDescription = modifier == "C" || (getMSGraphSyncLevel() & 4);
var doImportDescription = modifier == "C" || (getMSGraphSyncLevel() & 4); // Deprecated; altijd true tegenwoordig
if (data[index].type == "occurrence") // Repeating event
{
masterEvent = getMasterEvent(data, data[index].seriesMasterId) || {};
@@ -280,7 +298,7 @@ function makeCSV(data, zaalemail)
else if (inArray(data[index].type, ["singleInstance", "seriesMaster", "exception"]))
{
tds = [
doImportDescription ? masterEvent.subject : fcltRsv.description,
doImportDescription ? data[index].subject : fcltRsv.description,
_startDate.toISOString(),
_endDate.toISOString(),
data[index].organizer.emailAddress.address,
@@ -300,7 +318,7 @@ function makeCSV(data, zaalemail)
for (attendee in data[index].attendees)
{
tds = [
doImportDescription ? masterEvent.subject : fcltRsv.description,
doImportDescription ? data[index].subject : fcltRsv.description,
_startDate.toISOString(),
_endDate.toISOString(),
data[index].organizer.emailAddress.address,
@@ -320,5 +338,8 @@ function makeCSV(data, zaalemail)
}
if (trs.length)
trs = [headerRow].concat(trs);
if (typeof DEZE != "undefined") { /* TODO debug log weghalen */
__DoLog(trs.join("\r\n"), "pink");
}
return trs.join("\r\n");
}

View File

@@ -26,11 +26,15 @@
Oracle.Open('File Name=../oracle.udl'); //../Oracle.udl
token = requestToken(config);
var xhr = doHTTP("GET", "https://graph.microsoft.com/v1.0/subscriptions",
null,
{ "Accept": "application/json", "Authorization": "Bearer " + token });
if (xhr)
WScript.Echo(JSON.stringify(JSON.parse(xhr.responseText), null, 2));
var request = {
"method": "GET",
"url": "https://graph.microsoft.com/v1.0/subscriptions",
"headers": { "Accept": "application/json", "Authorization": "Bearer " + token },
"params": { "callback": function (req, xhr) {
WScript.Echo(JSON.stringify(xhr, null, 2))
}
}
}
doHTTP(request);
</script>
</job>

View File

@@ -71,8 +71,14 @@ function requestTokenCC(config)
+ '&client_secret=' + config.client_secret
+ '&client_id=' + config.client_id
+ '&scope=' + 'https://graph.microsoft.com/.default';
var xhr = doHTTP("POST", "https://login.microsoftonline.com/" + config.tenant + "/oauth2/v2.0/token", data, { "Content-Type": "application/x-www-form-urlencoded" });
return xhr !== null ? JSON.parse(xhr.responseText).access_token : null
var request = {
"method": "POST",
"url": "https://login.microsoftonline.com/" + config.tenant + "/oauth2/v2.0/token",
"body": data,
"headers": { "Content-Type": "application/x-www-form-urlencoded" }
}
var xhr = doHTTP(request);
return xhr ? xhr.access_token : null;
}
}
@@ -90,8 +96,14 @@ function requestTokenROCP(config)
+ '&username=' + config.username
+ '&password=' + config.password
+ '&scope=' + scope;
var xhr = doHTTP("POST", "https://login.microsoftonline.com/" + config.tenant + "/oauth2/v2.0/token", data, { "Content-Type": "application/x-www-form-urlencoded" });
return xhr !== null ? JSON.parse(xhr.responseText).access_token : null;
var request = {
"method": "POST",
"url": "https://login.microsoftonline.com/" + config.tenant + "/oauth2/v2.0/token",
"body": data,
"headers": { "Content-Type": "application/x-www-form-urlencoded" }
}
var xhr = doHTTP(request);
return xhr ? xhr.access_token : null;
}
// Request bearer token using a Certificate
@@ -145,30 +157,42 @@ function requestTokenCertificate(config)
+ '&scope=' + 'https://graph.microsoft.com/.default'
+ '&client_assertion=' + jwt.CreateJwtPk(jose.Emit(), claims.Emit(), privKey)
+ '&client_assertion_type=' + 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer';
var xhr = doHTTP("POST", "https://login.microsoftonline.com/" + config.tenant + "/oauth2/v2.0/token", parms, { "Content-Type": "application/x-www-form-urlencoded" }, 1); //- removed from content type
return xhr !== null ? JSON.parse(xhr.responseText).access_token : null;
var request = {
"method": "POST",
"url": "https://login.microsoftonline.com/" + config.tenant + "/oauth2/v2.0/token",
"body": parms,
"headers": { "Content-Type": "application/x-www-form-urlencoded" }
}
var xhr = doHTTP(request);
return xhr ? xhr.access_token : null;
}
/* Returns the event data */
function getCalendarEventByID(userPrincipalName, id)
{
var url = "https://graph.microsoft.com/v1.0/users/" + userPrincipalName + "/events/" + id;
var xhr = doHTTP("GET", url, null, { "Content-Type": "application/json", "Authorization": "Bearer " + token });
return xhr ? JSON.parse(xhr.responseText) : null;
var request = {
"method": "GET",
"url": "https://graph.microsoft.com/v1.0/users/" + userPrincipalName + "/events/" + id,
"headers": { "Content-Type": "application/json", "Authorization": "Bearer " + token }
}
return doHTTP(request);
}
/* Returns the event data */
function getCalendarEventByICalUId(userPrincipalName, iCalUId)
{
var url = url = "https://graph.microsoft.com/v1.0/users/" + userPrincipalName + "/events?$filter=iCalUId eq '" + iCalUId + "'"
var xhr = doHTTP("GET", url, null, { "Content-Type": "application/json", "Authorization": "Bearer " + token });
return xhr ? JSON.parse(xhr.responseText).value[0] : null;
var request = {
"method": "GET",
"url": "https://graph.microsoft.com/v1.0/users/" + userPrincipalName + "/events?$filter=iCalUId eq '" + iCalUId + "'",
"headers": { "Content-Type": "application/json", "Authorization": "Bearer " + token }
}
var xhr = doHTTP(request);
return xhr ? xhr.value[0] : null;
}
/* Returns all changed events within the configurated timeframe */
function getCalendarItems(userPrincipalName, skiptoken, deltatoken)
{
var response = null;
var parms;
if (skiptoken) { // Set parameters to read the next batch of events
parms = "$skiptoken=" + skiptoken;
@@ -185,60 +209,27 @@ function getCalendarItems(userPrincipalName, skiptoken, deltatoken)
__Log("Full syncing from " + dateFrom.toISOString() + " to " + dateTo.toISOString() + " for user " + userPrincipalName + " (" + (config.fullfuture + config.fullpast) + " days)");
}
var url = 'https://graph.microsoft.com/v1.0/users/' + userPrincipalName + '/calendarView/delta?' + parms;
var xhr = doHTTP("GET", url, null, { "Accept": "application/json", "Authorization": "Bearer " + token }, { "returnErrors": true });
if (xhr != null && xhr.status == 200) {
response = JSON.parse(xhr.responseText);
if ("@odata.deltaLink" in response) { // Dit is de deltatoken die we opslaan als syncstate; "Tot hier zijn we gesynced"
response.deltatoken = response["@odata.deltaLink"].split("$deltatoken=")[1];
} else if ("@odata.nextLink" in response) { // Er is meer; we roepen ons zelf straks nogmaals aan met dit token
response.skiptoken = response["@odata.nextLink"].split("$skiptoken=")[1];
}
} else if (xhr != null) {
response = JSON.parse(xhr.responseText);
if ("code" in response) {
if (xhr.status == 410 || response.code == "resyncRequired" || response.code == "syncStateNotFound") {
response = getCalendarItems(userPrincipalName, null, null); // delta token is gone, invalid of expired -> full sync
} else {
__DoLog("(calendarView) - MS Graph unidentified code (" + response.code + ")", "#FFFF44");
__DoLog(response, "#FFFF44");
}
} else if ("error" in response && "code" in response.error) {
__DoLog("(calendarView) - MS Graph error", "#FF0000");
__DoLog("Request: " + url, "#FF0000");
__DoLog("Response: [" + response.error.code + "] - " + response.error.message, "#FF0000");
} else {
__DoLog("(calendarView) - MS Graph unknown error", "#FF0000");
__DoLog(response, "#FF0000");
}
} else {
__DoLog("(calendarView) - Geen response van MS Graph ontvangen (Configuratie/verbindings-problemen).", "#FF0000");
var request = {
"method": "GET",
"url": "https://graph.microsoft.com/v1.0/users/" + userPrincipalName + "/calendarView/delta?" + parms,
"headers": { "Accept": "application/json", "Authorization": "Bearer " + token }
}
return response;
return doHTTP(request);
}
/* Returns all known subscriptions */
function getSubscriptions(skiptoken)
{
var response = null;
var parms = "";
var parms = "";
if (typeof skiptoken !== "undefined") { // Set parameters to read the next batch of events
parms = "?$skiptoken=" + skiptoken;
}
var xhr = doHTTP("GET", "https://graph.microsoft.com/v1.0/subscriptions" + parms, null, { "Accept": "application/json", "Authorization": "Bearer " + token }, { "returnErrors": true });
if (xhr != null && xhr.status == 200) {
response = JSON.parse(xhr.responseText);
if ("@odata.nextLink" in response) { // Er is meer; we roepen ons zelf straks nogmaals aan met dit token
response.skiptoken = response["@odata.nextLink"].split("$skiptoken=")[1];
}
} else if (xhr != null) {
__DoLog("(subscription) - MS Graph error", "#FF0000");
__DoLog(JSON.parse(xhr.responseText), "#FF0000");
} else {
__DoLog("(subscription) - Geen response van MS Graph ontvangen (Configuratie/verbindings-problemen).", "#FF0000");
var request = {
"method": "GET",
"url": "https://graph.microsoft.com/v1.0/subscriptions" + parms,
"headers": { "Accept": "application/json", "Authorization": "Bearer " + token }
}
return response;
return doHTTP(request);
}
/* Returns the notificationUrl used by MS Graph to send Facilitor notifications about changes in resources on which we are subscribed */
@@ -251,18 +242,18 @@ function getNotificationUrl(customerId)
if (config.hookurl) {
hookurl = config.hookurl;
} else { // Autodetect ngrok started with: ngrok http sggr.facws001.sg.nl:80
var result = doHTTP('GET',
'http://127.0.0.1:4040/api/tunnels/command_line',
null,
{"Content-Type": "application/json"});
if (result != null && result.status >= 200 && result.status < 300) {
var json = JSON.parse(result.responseText);
__Log("Ngrok detected: " + json.public_url);
__Log(" tip: view traffic at http://127.0.0.1:4040");
hookurl = json.public_url + "/trunk/";
} else {
__DoLog("getNotificationUrl ERROR: geen Response ontvangen", "#FF0000");
var request = {
"method": "GET",
"url": "http://127.0.0.1:4040/api/tunnels/command_line",
"headers": {"Content-Type": "application/json"},
"params": { "callback": function (request, response) {
__Log("Ngrok detected: " + response.public_url);
__Log(" tip: view traffic at http://127.0.0.1:4040");
hookurl = response.public_url + "/branch20231/"; /* TODO revert naar trunk */
}
}
}
doHTTP(request);
}
if (!hookurl) {
_AiAi("INTERNAL_ERROR attempting to subscribe without a valid hookurl");
@@ -291,31 +282,45 @@ function validNotificationUrl(url) {
var validationToken = "Validation: testing MS Graph <-> notificationUrl connection (" + new Date().toISOString() + ")";
__Log("\nPre-testing webhook url (like MS Graph will do soon): ");
__Log("get "+ url + "&validationToken=" + encodeURIComponent(validationToken));
try {
var result = doHTTP('GET',
url + "&validationToken=" + encodeURIComponent(validationToken),
null,
{"Accept": "application/json"}); // application/json maakt dat een AiAi leesbaarder terugkomt
if (!result || result.responseText != validationToken) {
__Log("FAILED");
__Log("Expected: " + validationToken);
if (result) {
__Log(" Got: " + result.responseText);
}
return false;
var request = {
"method": "GET",
"url": url + "&validationToken=" + encodeURIComponent(validationToken),
"headers": {"Accept": "application/json"},
"params": { "callback": function (request, response) {
return response.responseText == validationToken;
}
} catch(e) {
__Log("FAILED");
__Log(e.description);
return false;
}
}
return true;
return doHTTP(request);
}
function createSubscription(userPrincipalName, res_ruimte_key, notificationUrl) {
if (!validNotificationUrl(notificationUrl)) {
// Let op, deze functie doet eerst een full-sync
function createSubscription(userPrincipalName, res_ruimte_key, notificationUrl, urlValidated) {
if (!urlValidated && !validNotificationUrl(notificationUrl)) {
return false;
}
// Maak een res_ruimte_sync-record aan, of maak hem leeg zodat 'doImport' de juiste waarde in kan vullen na een full-sync
var sql = "SELECT 1 FROM res_ruimte_sync WHERE res_ruimte_key = " + res_ruimte_key;
var oRs = Oracle.Execute(sql);
var nieuw = oRs.EoF;
oRs.Close();
if (nieuw) { // Deze ruimte wordt voor het eerst gekoppeld, maak direct een res_ruimte_sync-record aan
sql = "INSERT INTO res_ruimte_sync (res_ruimte_key,"
+ " res_ruimte_syncstate,"
+ " res_ruimte_syncdate)"
+ " VALUES (" + res_ruimte_key + ", NULL, SYSDATE)";
} else { // De res_ruimte_sync-record bestaan al voor deze ruimte, hoogstwaarschijnlijk een refreshSubscription -> maak deltaToken leeg zodat de datum-range ververst wordt
sql = "UPDATE res_ruimte_sync"
+ " SET res_ruimte_syncstate = NULL"
+ " WHERE res_ruimte_key = " + res_ruimte_key;
}
Oracle.Execute(sql);
// Nu full-'sync'en, dan hebben we zsm een deltaToken waarmee we alleen mutaties kunnen ophalen
doImport(res_ruimte_key, userPrincipalName);
// En dan nu de subscription aanmaken
var oCrypto = new ActiveXObject("SLNKDWF.Crypto");
var expirationDate = new Date();
if (notificationUrl.indexOf("ngrok") != -1) {
@@ -327,12 +332,6 @@ function createSubscription(userPrincipalName, res_ruimte_key, notificationUrl)
__Log("Creating hook for " + userPrincipalName);
var clientState = oCrypto.hex_random(20);
var sql = "UPDATE res_ruimte"
+ " SET res_ruimte_graphhooksecret = " + safe.quoted_sql(clientState)
+ " , res_ruimte_externsyncdate = SYSDATE"
+ " WHERE res_ruimte_key = " + res_ruimte_key;
Oracle.Execute(sql);
var data = {
"changeType" : "updated",
"notificationUrl" : notificationUrl + "&res_ruimte=" + res_ruimte_key + "&hookcreated=" + new Date().toISOString(),
@@ -340,20 +339,27 @@ function createSubscription(userPrincipalName, res_ruimte_key, notificationUrl)
"clientState" : clientState,
"expirationDateTime": expirationDate
}
var result = doHTTP("POST",
"https://graph.microsoft.com/v1.0/subscriptions",
JSON.stringify(data),
{ "Content-Type": "application/json", "Authorization": "Bearer " + token },
{ "returnErrors": true });
if (result) {
var newSubscriptionCallback = function _newSubscriptionCallback(request, response) {
__Log("Gelukt");
__Log(JSON.stringify(JSON.parse(result.responseText), null, 2));
return result.status == 201;
} else {
__Log("result.responseText lijkt null te zijn. Kan zijn omdat er bovenstaand (in log) iets misgaat.");
__Log(JSON.stringify(response, null, 2));
// Update de data aangaande de (ver)nieuw(d)e subscription
sql = "UPDATE res_ruimte"
+ " SET res_ruimte_graphhooksecret = " + safe.quoted_sql(clientState) // Met dit secret verifieren we dat requests van MS Graph ook echt van MS Graph zijn
+ " , res_ruimte_externsyncdate = SYSDATE" // Dit is de datum waarop de subscription is aangemaakt
+ " WHERE res_ruimte_key = " + res_ruimte_key;
Oracle.Execute(sql);
return true;
}
return false;
var request = {
"method": "POST",
"url": "https://graph.microsoft.com/v1.0/subscriptions",
"body": JSON.stringify(data),
"headers": { "Content-Type": "application/json", "Authorization": "Bearer " + token },
"params": { "callback": newSubscriptionCallback }
}
return doHTTP(request);
}
function deleteSubscription(userPrincipalName) {
@@ -377,8 +383,12 @@ function deleteSubscription(userPrincipalName) {
}
var success = true;
for (var i = 0; i < subscriptionList.length; i++) {
var xhr = doHTTP("DELETE", "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionList[i], null, { "Accept": "application/json", "Authorization": "Bearer " + token }, { "returnErrors": true });
success = success && xhr !== null && xhr.status == 204;
var request = {
"method": "DELETE",
"url": "https://graph.microsoft.com/v1.0/subscriptions/" + subscriptionList[i],
"headers": { "Accept": "application/json", "Authorization": "Bearer " + token }
}
success = success && doHTTP(request);
}
return success;
}
@@ -445,7 +455,18 @@ function updateExternnr2(userPrincipalName, id, hostPrincipalName)
//////////////////////////////////
function doHTTP(method, url, body, headers, params)
{
params = params || {};
if (arguments.length === 1 && typeof arguments[0] === "object") {
request = arguments[0];
var method = request.method;
var url = request.url;
var body = request.body || null;
var headers = request.headers;
request.params = request.params || {};
var params = request.params;
} else { // Deprecated; het request is nu 1 object als argument
var params = params || {};
}
//var SXH_PROXY_SET_PROXY = 2;
var SXH_OPTION_IGNORE_SERVER_SSL_CERT_ERROR_FLAGS = 2;
var SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS = 0x3300;
@@ -474,85 +495,88 @@ function doHTTP(method, url, body, headers, params)
return null;
}
if (params.async) {
return objXMLHTTP;
}
if (objXMLHTTP.status < 200 || objXMLHTTP.status >= 300) {
if (config.loglevel > 0) {
__Log(objXMLHTTP.status);
__Log(objXMLHTTP.statusText);
__Log(objXMLHTTP.responseText);
}
if (String(objXMLHTTP.getResponseHeader("Content-Type") == 'application/json'))
{
__Log(JSON.stringify(JSON.parse(objXMLHTTP.responseText), null, 2));
}
else
{
__Log2File("response.xml", objXMLHTTP.responseText);
}
if (!params.returnErrors) {
return null;
}
}
return objXMLHTTP;
return _handleMsGraphResponse(request, objXMLHTTP);
}
function _handleMsGraphResponse(rsv_ruimte_key, httpResponse, CRUD)
/* Evalueert een MS Graph response */
function _handleMsGraphResponse(request, httpResponse)
{
var stateSuccessful;
switch (CRUD) { // Read is in dit bestand nvt
case "C": stateSuccessful = 201; break; // https://docs.microsoft.com/en-us/graph/api/calendar-post-events
case "U": stateSuccessful = 200; break; // https://docs.microsoft.com/en-us/graph/api/event-update
case "D": stateSuccessful = 204; break; // https://docs.microsoft.com/en-us/graph/api/event-delete
default: _AiAi("INTERNAL ERROR: invalid CRUD-action specified in bulkToGraph(): CRUD = " + CRUD + "");
if (request.params.async) {
for (var i = 0; i < 100 && httpResponse.readyState && httpResponse.readyState != 4; i++) { // Max 100 iteraties van 100ms = 10s
httpResponse.waitForResponse(100);
}
}
for (var i = 0; i < 100 && httpResponse.readyState && httpResponse.readyState != 4; i++) { // Max 100 iteraties van 100ms = 10s
httpResponse.waitForResponse(100);
if (!(httpResponse.status >= 200 && httpResponse.status < 300)) {
return _handleMsGraphFailure(request, httpResponse);
} else if (request.method === "DELETE") { // 204 = 'No Content' dus niks terug te geven
return true;
}
if (httpResponse && httpResponse.status == stateSuccessful) {
return _handleMsGraphSuccess(rsv_ruimte_key, httpResponse, CRUD);
} else {
return _handleMsGraphError(httpResponse, CRUD);
/* Parse het alvast, 'bulk' was onderdeel van een $batch, dat is al een geparsed object, en geen httpResponse */
if (request.bulk) {
httpResponse = httpResponse.body;
} else { /* MS Graph returned altijd JSON */
try {
httpResponse = JSON.parse(httpResponse.responseText);
} catch (e) { /* Ok, dan niet */ }
}
}
// Onderstaande functie wordt alleen aangeroepen als de response.state succesvol is
function _handleMsGraphSuccess(rsv_ruimte_key, httpResponse, CRUD) {
if (CRUD == "C") {
var msGraphResponse = httpResponse.responseText ? JSON.parse(httpResponse.responseText) : httpResponse.body;
// We hebben hier nog niet de informatie van het ruimte-resource event, die krijgen we straks via de webhook binnen.
// Vul voor nu alleen het organisator-event-id in bij res_rsv_ruimte_externnr2 zodat we deze res_rsv herkennen in de process_webhook waar we hem straks zullen aanvullen
var sql = "UPDATE res_rsv_ruimte"
+ " SET res_rsv_ruimte_externnr2 = " + DEZE.safe.quoted_sql(msGraphResponse.id)
+ " , res_rsv_ruimte_externsyncdate = SYSDATE"
+ ((getMSGraphSyncLevel() & 6) == 2 // Dan is het event alleen bij de ruimte geboekt en is dit zowel room-event-id als organisator-event-id
? " , res_rsv_ruimte_externnr = " + DEZE.safe.quoted_sql(msGraphResponse.id + "||" + new Date().getTime())
: "")
+ " WHERE res_rsv_ruimte_key = " + rsv_ruimte_key;
Oracle.Execute(sql);
if (request.method === "GET") { // Detecteer skip/delta-tokens en zet die in het response-object
if ("@odata.deltaLink" in httpResponse) { // Dit is de deltatoken die we opslaan als syncstate; "Tot hier zijn we gesynced"
httpResponse.deltatoken = httpResponse["@odata.deltaLink"].split("$deltatoken=")[1];
} else if ("@odata.nextLink" in httpResponse) { // Er is meer; we roepen ons zelf straks nogmaals aan met dit token
httpResponse.skiptoken = httpResponse["@odata.nextLink"].split("$skiptoken=")[1];
}
}
__Log("Succesvol naar Exchange gesynchroniseerd.");
return true;
if (request.params.callback) {
return request.params.callback(request, httpResponse);
}
return httpResponse;
}
// Onderstaande functie wordt alleen aangeroepen als de response niet aanwezig, of onsuccesvol is
function _handleMsGraphError(httpResponse, CRUD) {
function _handleMsGraphFailure(request, httpResponse) {
if (httpResponse && httpResponse.status) {
try {
var msGraphResponse = httpResponse.responseText ? JSON.parse(httpResponse.responseText) : httpResponse.body;
var msGraphResponse = httpResponse.responseText ? JSON.parse(httpResponse.responseText) : httpResponse.body; // Die laatste is voor batches
} catch (e) {
var msGraphResponse = httpResponse.responseText || "";
}
if ("error" in msGraphResponse && "code" in msGraphResponse.error) { // De bekende errors
if (CRUD == "D" && msGraphResponse.error.code == "ErrorItemNotFound") {
__DoLog("(DELETE) - Verwijderde reservering kon in Outlook niet gevonden worden", "#FFFF44");
// Hier gaat iets fout
if (typeof msGraphResponse == "object" && "error" in msGraphResponse && "code" in msGraphResponse.error) { // De bekende errors
switch (msGraphResponse.error.code) {
case "ErrorItemNotFound":
__Log("(DELETE) - Verwijderde reservering kon in Outlook niet gevonden worden", "#FFFF44");
break;
case "ResyncRequired":
case "SyncStateNotFound":
__Log("MS Graph [" + msGraphResponse.error.code + "] - " + msGraphResponse.error.message, "#FFFF44");
__Log("Refreshing syncstate ...");
var zaalemail = request.url.substring(
request.url.indexOf("/users/") + "/users/".length,
request.url.lastIndexOf("/calendarView/")
);
return getCalendarItems(zaalemail, null, null); // delta token is gone, invalid of expired -> full sync
case "ApplicationThrottled":
__DoLog("MS Graph [ApplicationThrottled] - " + msGraphResponse.error.message, "#FF0000");
/* UNTESTED
var retryAfterXSeconds = parseInt(httpResponse.getResponseHeader("Retry-After"), 10);
__DoLog("volgens MS Graph moeten we het over " + retryAfterXSeconds + "s weer proberen", "#FFFF44");
if (!request || retryAfterXSeconds > 100) { // Dan niet hoor
return false;
}
var oSLNKDWF = new ActiveXObject("SLNKDWF.About");
oSLNKDWF.Sleep(retryAfterXSeconds * 1000);
return doHTTP(request);
*/
default:
__DoLog("MS Graph unidentified error code [" + msGraphResponse.error.code + "] - " + msGraphResponse.error.message, "#FF0000");
__Log(msGraphResponse, "#FF0000");
return msGraphResponse;
}
} else {
__DoLog("MS Graph NIET succesvol afgehandeld, onderstaand antwoord ontvangen", "#FF0000");
@@ -564,6 +588,57 @@ function _handleMsGraphError(httpResponse, CRUD) {
return false;
}
function getImportAppKey(appCode) {
var result = "";
var sql = "SELECT i.fac_import_app_key "
+ " FROM fac_import_app i"
+ " WHERE i.fac_import_app_code = " + safe.quoted_sql(appCode);
var oRs = Oracle.Execute(sql);
if (oRs.EOF) {
__DoLog("FATAL: Import '" + appCode + "' not found");
return false;
}
result = oRs("fac_import_app_key").Value;
oRs.Close();
return result;
}
function doImport(res_ruimte_key, zaalemail, import_type) {
if (typeof import_type === "undefined") {
var import_type = "EXCHFULL";
}
var import_app_key = getImportAppKey(import_type);
var fileStream = csv_for_room(zaalemail, import_app_key, true); // as Stream
if (!fileStream || !fileStream.Size) {
__Log("No action required after receiving MS Graph import", "#FFFF44");
return true; // Klaar
}
if (typeof DEZE !== "undefined") { /* Alleen vanuit de asp, en niet bij het runnen van refreshMSGraphSubscriptions.bat */
user_key = DEZE.user_key;
customerId = DEZE.customerId;
}
var res = impReadStream(fileStream,
import_app_key,
{ fac_home: custabspath + "/exchange/",
filepathname: "SYNC_" + zaalemail,
customerId: customerId,
ref_key: res_ruimte_key,
keep_old: 300, // Parallelle import 300 seconden ondersteunen (nodig voor deze import?)
user_key: user_key,
keep_backup: false, // mits fac_import_app_folder gezet
is_stream: true
});
if (res.success) {
var processres = impProcessStream(res.import_key, { customerId: customerId });
} else {
__DoLog(res);
}
return true;
}
if (!Date.prototype.toISOString) {
Date.prototype.toISOString = function () {
function pad(n) { return n < 10 ? '0' + n : n }

View File

@@ -103,47 +103,7 @@ function process_webhook(res_ruimte_key, zaalemail, notidata)
}
oRs.Close();
}
var import_app = "EXCHANGE";
var sql = "SELECT i.fac_import_app_key "
+ " FROM fac_import_app i"
+ " WHERE i.fac_import_app_code = " + DEZE.safe.quoted_sql(import_app);
var oRs = Oracle.Execute(sql);
if (oRs.EOF)
{
__DoLog("FATAL: Import EXCHANGE not found");
return false;
}
var import_app_key = oRs("fac_import_app_key").Value;
oRs.Close();
var fileStream = csv_for_room(zaalemail, import_app, true); // as Stream
if (!fileStream || !fileStream.Size)
{
__Log("No action required after receiving MS Graph notification", "#FFFF44");
return false;
}
var res = impReadStream(fileStream,
import_app_key,
{ fac_home: custabspath + "/exchange/",
filepathname: "SYNC_" + zaalemail,
customerId: DEZE.customerId,
ref_key: res_ruimte_key,
keep_old: 300, // Parallelle import 300 seconden ondersteunen (nodig voor deze import?)
user_key: DEZE.user_key,
keep_backup: false, // mits fac_import_app_folder gezet
is_stream: true
});
if (res.success)
{
var processres = impProcessStream(res.import_key, { customerId: DEZE.customerId });
}
else
{
__DoLog(res);
}
return true;
return doImport(res_ruimte_key, zaalemail, "EXCHANGE");
}
]]>
</script>

View File

@@ -51,6 +51,8 @@
<script language="JScript" src="../wsf_shared.js"/>
<script language="JScript" src="../json2.js"/>
<script language="JScript" src="ms_graph.js"/>
<script language="JScript" src="exchange_graph.js"/>
<script language="JScript" src="../../appl/imp/imp_shared.js"/>
<script language="javascript">
<![CDATA[
@@ -133,37 +135,31 @@ function subscription(userPrincipalName, res_ruimte_key, CRUD) {
function bulkToGraph(res_ruimte_key, CRUD) { // [C]reate, [R]ead, [U]pdate & [D]elete
if (CRUD == "C") {
var MAX_BATCH = 20;
var MAX_BATCH = 20; // TODO async maken en throttling testen/afhandelen
var MAX_TIME = 90000;
function _processBatch(requests, httpResponse) {
for (var i = 0; i < 100 && httpResponse.readyState != 4; i++) { // Max 100 iteraties van 100ms = 10s
httpResponse.waitForResponse(100);
}
/* Handel een hele batch met requests af */
function _processBatch(batch, httpResponse) {
var requests = JSON.parse(batch.body).requests; // Dit kan wel veilig want we hebben dit object zojuist zelf stringified
for (var i = 0; i < httpResponse.responses.length; i++) {
var response = httpResponse.responses[i];
var request = requests[response.id - 1];
request.params = { "callback": resToGraphCallback };
if (httpResponse.readyState != 4) {
result.failed += requests.length;
return false;
}
if (httpResponse && httpResponse.status === 200) {
var msGraphResponses = JSON.parse(httpResponse.responseText);
for (var i = 0; i < msGraphResponses.responses.length; i++) {
var response = msGraphResponses.responses[i];
if (_handleMsGraphResponse(requests[response.id - 1].res_rsv_ruimte_key, response, CRUD)) {
result.done++;
} else {
result.failed++;
}
// Returned true als resToGraphCallback klaar is, of false als het niet goed is gegaan
if (_handleMsGraphResponse(request, response)) {
result.done++;
} else {
result.failed++;
}
} else {
result.failed += requests.length;
return _handleMsGraphError(httpResponse);
}
return true;
}
var sql = _getSql(CRUD)
+ " AND rrr.res_rsv_ruimte_externsyncdate IS NULL"
+ " AND rrr.res_rsv_ruimte_externnr IS NULL"
+ " AND rrr.res_rsv_ruimte_externnr2 IS NULL"
+ " AND rr.res_ruimte_key = " + res_ruimte_key;
var oRs = Oracle.Execute(sql);
var result = {
@@ -190,13 +186,16 @@ function bulkToGraph(res_ruimte_key, CRUD) { // [C]reate, [R]ead, [U]pdate & [D]
result.total++;
oRs.moveNext();
}
var batch_response = doHTTP("POST",
"https://graph.microsoft.com/v1.0/$batch",
JSON.stringify({ "requests": batch }),
{ "Content-Type": "application/json", "Authorization": "Bearer " + token },
{ "returnErrors": true, "async": true });
_processBatch(batch, batch_response);
var batch_request = {
"method": "POST",
"url": "https://graph.microsoft.com/v1.0/$batch",
"body": JSON.stringify({ "requests": batch }),
"headers": { "Content-Type": "application/json", "Authorization": "Bearer " + token },
"params": { "async": true, "callback": _processBatch }
}
if (!doHTTP(batch_request)) { // Voert de callback uit indien succesvol
result.failed += batch.length;
}
}
if (!oRs.EoF) {
@@ -229,7 +228,7 @@ function resToGraph(rsv_ruimte_key, CRUD) // [C]reate, [R]ead, [U]pdate & [D]ele
__Log("Now in res_to_graph.wsc for rsv_ruimte_key (" + CRUD + ") = " + rsv_ruimte_key);
if ((getMSGraphSyncLevel() & 6) == 0) {
__DoLog("Error: resToGraph aangeroepen zonder schrijf-intenties volgens S(msgraph_sync_level)", "#FA58E3");
__DoLog("Error: resToGraph aangeroepen zonder schrijf-intenties volgens S(msgraph_sync_level)", "#FF0000");
return false;
}
@@ -238,15 +237,10 @@ function resToGraph(rsv_ruimte_key, CRUD) // [C]reate, [R]ead, [U]pdate & [D]ele
+ " AND res_rsv_ruimte_key = " + rsv_ruimte_key;
var oRs = Oracle.Execute(sql);
if (oRs.EOF) {
__DoLog("Error: rsv_ruimte-record met rsv_ruimte_key = " + rsv_ruimte_key + " niet gevonden", "#FF0000");
__DoLog("Error: rsv_ruimte-record met rsv_ruimte_key = " + rsv_ruimte_key + " niet gevonden\n(is de reservering misschien in het verleden gemaakt?)", "#FF0000");
return false;
}
var httpResponse = _resToGraph(oRs, CRUD);
if (httpResponse === false) {
var result = false;
} else {
var result = _handleMsGraphResponse(rsv_ruimte_key, httpResponse, CRUD);
}
var result = _resToGraph(oRs, CRUD);
oRs.Close();
return result;
}
@@ -336,15 +330,21 @@ function _resToGraph(oRs, CRUD, bulk)
"name": data.location.displayName,
"address": res_ruimte_extern_id
}
},
{
"type": "required",
"emailAddress": {
"name": host_name,
"address": host_mail
}
}
];
/* In deze modus nodigen we de gastheer/vrouw toe als deelnemer */
if (getMSGraphSyncLevel() & 2) {
data.attendees.push(
{
"type": "required",
"emailAddress": {
"name": host_name,
"address": host_mail
}
}
);
}
}
var targetId = res_ruimte_extern_id;
@@ -354,7 +354,7 @@ function _resToGraph(oRs, CRUD, bulk)
if (targetId === undefined || targetId === null)
{
__DoLog("Error: Kan geen gebruiker vinden namens wie we de reservering kunnen maken", "#FA58E3");
__DoLog("Error: Kan geen gebruiker vinden namens wie we de reservering kunnen maken", "#FF0000");
return false;
}
@@ -381,14 +381,18 @@ function _resToGraph(oRs, CRUD, bulk)
return false;
}
var request = {
"method": method,
"url": url,
"body": data,
"headers": { "Content-Type": "application/json", "Authorization": "Bearer " + token }
}
if (bulk) {
return {
"method": method,
"url": url,
"headers": { "Content-Type": "application/json", "Authorization": "Bearer " + token },
"body": data
}
request.bulk = true;
return request;
} else {
request.params = { "callback": resToGraphCallback };
__Log("(" + method + ")" + " to: " + url);
if (data) {
__Log(data);
@@ -396,12 +400,23 @@ function _resToGraph(oRs, CRUD, bulk)
}
}
return doHTTP(method,
url,
data,
{ "Content-Type": "application/json", "Authorization": "Bearer " + token },
{ "returnErrors": true, "async": true }
);
return doHTTP(request);
}
/* Deze query wordt uitgevoerd als we een (succesvol) response van MS Graph ontvangen hebben */
var resToGraphCallback = function _resToGraphCallback(request, httpResponse) {
// We hebben hier nog niet de informatie van het ruimte-resource event, die krijgen we straks via de webhook binnen (indien S(msgraph_sync_level) &4)
// Vul voor nu alleen het organisator-event-id in bij res_rsv_ruimte_externnr2 zodat we deze res_rsv herkennen in de process_webhook waar we hem straks zullen aanvullen
var sql = "UPDATE res_rsv_ruimte"
+ " SET res_rsv_ruimte_externnr2 = " + DEZE.safe.quoted_sql(httpResponse.id)
+ " , res_rsv_ruimte_externsyncdate = SYSDATE"
+ ((getMSGraphSyncLevel() & 6) == 2 // Dan is het event alleen bij de ruimte geboekt en is dit zowel room-event-id als organisator-event-id
? " , res_rsv_ruimte_externnr = " + DEZE.safe.quoted_sql(httpResponse.id + "||" + new Date().getTime())
: "")
+ " WHERE res_rsv_ruimte_key = " + request.res_rsv_ruimte_key;
__DoLog(sql, "blue");
Oracle.Execute(sql);
return true;
}
]]>

View File

@@ -24,12 +24,12 @@ function toDateTimeString(jsDate)
function __Log(s, params)
{
var params = params || {}; // default logging met timestamp.
params.severity = params.severity || "I";
WScript.Echo(toDateTimeString(new Date) + ";" + params.severity + ";" + s);
var severity = params.severity || "I";
WScript.Echo(toDateTimeString(new Date) + ";" + severity + ";" + s);
}
function __DoLog(s, params)
{
__Log(s, params)
__Log(s, params);
}
function subfolderKey(pNiveau, pKey)
{