Files
Facilitor/APPL/API2/model_reservations.inc
Peter Koerhuis 1e8959c89c Spelen met Outlook add-in
svn path=/Website/branches/v2016.2/; revision=31427
2016-11-10 15:32:52 +00:00

417 lines
22 KiB
C++

<% /*
$Revision$
$Id$
File: model_reservations.inc
Description: Reservering model.
Parameters:
Context:
Notes: In het technisch datamodel heeft een reservering een koppeling naar een
res_ruimte_opstel record (een geldige ruimte<->opstelling combinatie)
In de API splitsen we dat in de meer natuurlijk aanvoelende res_ruimte_key
en res_ruimte_opstel_key
We ondersteunen nog niet het aanmaken van een tweede deelreservering
onder een reservering.
*/
%>
<!-- #include file="../Shared/discx3d.inc"-->
<!-- #include file="../res/res.inc" -->
<!-- #include file="./model_reservationequipment.inc"-->
<!-- #include file="./model_reservationconsumables.inc"-->
<!-- #include file="./model_custom_fields.inc"-->
<!-- #include file="./model_tracking.inc"-->
<%
var sqlro = "SELECT rg.res_ruimte_nr || CASE WHEN res_ruimte_opstel_default = 1 THEN '' ELSE ' (' || ro.res_opstelling_omschrijving || ')' END CASE"
+ " FROM res_ruimte_opstelling rro"
+ " , res_opstelling ro"
+ " , res_v_alg_ruimte_gegevens rg"
+ " WHERE rro.res_opstelling_key = ro.res_opstelling_key"
+ " AND rro.res_ruimte_key = rg.res_ruimte_key"
+ " AND rro.res_ruimte_opstel_key = res_rsv_ruimte.res_ruimte_opstel_key";
function fndirtwarn(level)
{
if (level & res.dirtlevel.ruimte.notavailable)
return L("lcl_res_dirtyroom");
return null;
}
function model_reservations(rsv_key, params)
{
this.module = "RES";
this.table = "res_rsv_ruimte";
this.primary = "res_rsv_ruimte_key";
this.records_name = "reservations";
this.record_name = "reservation";
this.fields =
{"id" : { dbs: "res_rsv_ruimte_key", typ: "key", filter: "exact", label: L("lcl_reservation") },
"name" : { dbs: "res_reservering_id", sql: "res_reservering_key||'/'||res_rsv_ruimte_volgnr", typ: "varchar", label: L("lcl_reservation")},
"from" : { dbs: "res_rsv_ruimte_van", typ: "datetime", filter: "range", label: L("lcl_res_starttime"), track: true}, // TODO: Andere lcl voor catering
"to" : { dbs: "res_rsv_ruimte_tot", typ: "datetime", filter: "range", label: L("lcl_res_endtime"), track: true},
"description" : { dbs: "res_rsv_ruimte_omschrijving", typ: "varchar", label: L("lcl_descr"), track: true },
"activity" : { dbs: "res_activiteit_key", typ: "key", filter: "exact", foreign: "res_activiteit", label: L("lcl_activity"), track: true },
"remark" : { dbs: "res_rsv_ruimte_opmerking", typ: "varchar", label: L("lcl_remark"), track: true},
"host" : { dbs: "res_rsv_ruimte_host_key", typ: "key", foreign: "prs_perslid", label: L("lcl_host"), track: true},
"contact" : { dbs: "res_rsv_ruimte_contact_key", typ: "key", foreign: "prs_perslid", label: L("lcl_name"), track: true},
"visitorscount" : { dbs: "res_rsv_ruimte_bezoekers", typ: "number", label: L("lcl_visitors"), track: true },
"status" : { dbs: "res_status_fo_key", typ: "key", foreign: res.getfostatustext },
"flag" : { dbs: "res_rsv_ruimte_flag", typ: "number", LOV: ""},
"resroom" : { dbs: "res_ruimte_opstelling.res_ruimte_key", typ: "key", filter: "exact", label: L("lcl_room"), foreign: "res_ruimte" },
"configuration" : { dbs: "res_ruimte_opstelling.res_opstelling_key", typ: "key", foreign: "res_opstelling" },
"approved" : { dbs: "res_rsv_ruimte_afgerond", typ: "number", label: L("lcl_res_resappr"), track: true },
"warning" : { dbs: "res_rsv_ruimte_dirtlevel", typ: "number", foreign: fndirtwarn, readonly: true },
"reservation" : { dbs: "res_reservering_key", typ: "key", label: L("lcl_reservation") },
"extern_id" : { dbs: "res_rsv_ruimte_externnr", typ: "varchar", label: L("extern_nr") }
};
// Mogelijke waarden voor res_rsv_ruimte_flag is afhankelijk van het aantal toegestane flags.
if (S("res_reservering_flags") > 0)
{
flag_array = [];
for (i=0; i<S("res_reservering_flags"); i++)
{
flag_array.push(i)
flag_array.push(L("lcl_res_flag"+i));
}
this.fields.flag.LOV = flag_array.join(";");
}
this.list = { columns: ["id", "name", "from", "to"] };
this.includes =
{"reservationequipment": { model: model_reservationequipment,
joinfield: "reservation",
enable_update: true
},
"reservationconsumables": { model: model_reservationconsumables,
joinfield: "reservation"
},
"tracking": {
model: new model_tracking(['reservering', 'xreservering']),
joinfield: "fac_tracking_refkey"
},
"custom_fields" : { model: new model_custom_fields(this, "RES", { readman: true, readuse: true }),
joinfield: "flexparentkey"
}
};
this.impersonate_auth = "WEB_RESFOF";
this.REST_GET = function _GET(params)
{
var scope = params.filter.scope || "fe";
var autfunction = { fe : "WEB_RESUSE", fo : "WEB_RESFOF", bo : "WEB_RESBOF", mi : "WEB_RESBAC" } [scope];
params.authparams = user.checkAutorisation(autfunction, null, null, true); // pessimistisch
// TODO: Add authorization
var query = api2.sqlfields(params, this );
if (scope == "fe")
{
query.wheres.push(user_key + " IN (res_rsv_ruimte_host_key, res_rsv_ruimte_contact_key)"); // Altijd fe vooralnog
if (!params.filter.id)
query.wheres.push("res_rsv_ruimte_van BETWEEN SYSDATE - " + S("facilitiespast_res") + " AND SYSDATE + " + S("facilitiesfuture_res"));
}
else
{
if (!params.filter.start_from && !params.filter.end_from && !params.filter.start_to && !params.filter.end_to)
query.wheres.push("res_rsv_ruimte_van >= TRUNC(SYSDATE)"); // reserveringen van vandaag en komende dagen!
}
query.tables.push("res_ruimte_opstelling");
query.tables.push("res_ruimte rr");
query.tables.push("res_alg_ruimte ra");
query.tables.push("alg_v_ruimte_gegevens_all rg");
query.tables.push("alg_district di");
query.tables.push("prs_perslid p");
query.tables.push("prs_v_afdeling_boom boom");
query.wheres.push("res_rsv_ruimte.res_ruimte_opstel_key = res_ruimte_opstelling.res_ruimte_opstel_key(+)");
query.wheres.push("rr.res_ruimte_key(+) = ra.res_ruimte_key");
query.wheres.push("ra.res_ruimte_key(+) = res_ruimte_opstelling.res_ruimte_key");
query.wheres.push("rg.alg_ruimte_key = COALESCE(res_rsv_ruimte.alg_ruimte_key, ra.alg_ruimte_key)");
query.wheres.push("rg.alg_district_key = di.alg_district_key");
query.wheres.push("res_rsv_ruimte.res_rsv_ruimte_contact_key = p.prs_perslid_key");
query.wheres.push("boom.prs_afdeling_key = p.prs_afdeling_key");
var wheres = api2.sqlfilter(params, this);
query.wheres = query.wheres.concat(wheres);
query.wheres.push("res_rsv_ruimte_verwijder IS NULL");
var sql = "SELECT " + query.selects.join(", ")
+ " FROM " + query.tables.join(", ")
+ " WHERE " + query.wheres.join(" AND " );
// Over het resultaat moet nog de 3D rasp, altijd
sql = discx3d (sql,
"rr.res_discipline_key",
"di.alg_regio_key",
"rg.alg_district_key",
"rg.alg_locatie_key",
"rg.alg_gebouw_key",
"rg.alg_verdieping_key",
"rg.alg_ruimte_key",
"boom.prs_bedrijf_key",
"boom.prs_afdeling_key",
autfunction,
"",
2,null,3
);
sql += " ORDER BY res_rsv_ruimte.res_rsv_ruimte_key"; // Order by nodig voor includes
if (query.orderbys.length)
sql += ", " + query.orderbys.join(", ");
var json = api2.sql2json (params, sql, this );
return json;
};
function _analyze_fields(dbfields, params, jsondata) /* analyseer inkomende data, common voor PUT en POST */
/* res_ruimte+config wordt bijvoorbeeld omgezet in res_ruimte_opstel_key */
{
if ("resroom" in jsondata)
{
var res_ruimte_key = parseInt(jsondata.resroom);
var res_opstel_key = -1;
if ("configuration" in jsondata) // Pas op: opstelling 'Standaard' heeft soms key 0
res_opstel_key = parseInt(jsondata.configuration);
// De default komt bovenaan
var sql = "SELECT rro.res_ruimte_opstel_key"
+ " , COALESCE (rro.res_ruimte_opstel_default, 0)"
+ " , rr.res_discipline_key"
+ " FROM res_ruimte_opstelling rro"
+ " , res_opstelling ro"
+ " , res_ruimte rr"
+ " WHERE rro.res_opstelling_key = ro.res_opstelling_key"
+ " AND rr.res_ruimte_key = " + res_ruimte_key
+ " AND rro.res_ruimte_key = " + res_ruimte_key
+ (res_opstel_key>=0 ? " AND ro.res_opstelling_key = " + res_opstel_key: "")
+ " ORDER BY COALESCE (rro.res_ruimte_opstel_default, 0)"
+ " , res_opstelling_volgnr";
var oRs = Oracle.Execute(sql);
var res_disc_key = oRs("res_discipline_key").value;
var soort = 0; // reserveerbare ruimtes
dbfields["configuration"] = { dbs: "res_ruimte_opstel_key", typ: "key", val: oRs("res_ruimte_opstel_key").Value };
dbfields["room"] = { dbs: "alg_ruimte_key", typ: "key", val: -1 };
dbfields["bostatus"] = { dbs: "res_status_bo_key", typ: "key", val: 2 }; // 'ingevoerd'. Altijd bij ruimte reserveringen
oRs.Close();
}
else // moet er een alg_ruimte zijn
{
// TODO
api2.error(500, "Missing room in input");
// var res_disc_key = ...
// var soort = 1; // algemene ruimtes
}
if ("activity" in jsondata)
{
// TODO: mag hij? Of controleren we dat in _validate_fields
}
else
{
if (params.isNew)
{
// Er is nog niet het concept 'default activiteit' dus pak gewoon de laagste
sql = " SELECT MIN (ra.res_activiteit_key) res_activiteit_key "
+ " FROM res_activiteitdiscipline ad, "
+ " res_activiteit ra,"
+ " res_srtactiviteit rs"
+ " WHERE ad.res_discipline_key = " + res_disc_key
+ " AND ra.res_activiteit_key = ad.res_activiteit_key"
+ " AND rs.res_srtactiviteit_key = ra.res_srtactiviteit_key"
+ " AND res_srtactiviteit_soort = " + soort;
oRs = Oracle.Execute(sql);
//jsondata.activity = oRs("res_activiteit_key").Value;
dbfields["activity"] = { dbs: "res_activiteit_key", typ: "key", val: oRs("res_activiteit_key").Value };
oRs.Close()
}
}
}
function _validate_fields (dbfields, params, jsondata) /* valideer dbfields, alle constraints die niet door de database worden afgevangen */
{
};
this.REST_PUT = function (params, jsondata, the_key) /* update reservation */
{
var rsv_ruimte_key = the_key;
var dbfields = api2.update_fields(params, this, jsondata); // Build updater
_analyze_fields(dbfields, params, jsondata);
_validate_fields(dbfields, params, jsondata);
// bezUpd heeft na afloop eventueel oldjsvals
var wheres = [" res_rsv_ruimte_key = " + rsv_ruimte_key];
wheres.push(user_key + " IN (res_rsv_ruimte_host_key, res_rsv_ruimte_contact_key)"); // Altijd fe vooralnog
// ons eigen tijdstip/zaal is mogelijk gewijzigd waardoor andere *dirty* reserveringen
// clean wordt. Even onze oude datum onthouden zodat we niet *alles* hoeven te controleren
// Ook even noshow onthouden
oRs = Oracle.Execute("SELECT res_reservering_key"
+ " , res_rsv_ruimte_van"
+ " , res_rsv_ruimte_tot"
+ " , res_rsv_ruimte_noshow"
+ " , res_rsv_ruimte_volgnr"
+ " FROM res_rsv_ruimte"
+ " WHERE res_rsv_ruimte_key = " + rsv_ruimte_key);
var reservering_key = oRs("res_reservering_key").Value;
var oldvan = new Date(oRs("res_rsv_ruimte_van").Value);
var oldtot = new Date(oRs("res_rsv_ruimte_tot").Value);
var oldnoshow = oRs("res_rsv_ruimte_noshow").Value == 1;
var volgnr = oRs("res_rsv_ruimte_volgnr").Value;
var resUpd = buildTrackingUpdate("res_rsv_ruimte", wheres.join(" AND " ), dbfields, { noValidateToken: true });
var check_fail_sql = " if res.dirty_level_all(" + rsv_ruimte_key + ") <> 0 then"
+ " raise_application_error (-20000, 'res_m999 " + L("lcl_res_fe_no_dirty") + "');"
+ " end if;"
var sql = "BEGIN "
+ resUpd.sql + ";"
+ " res.set_ruimte_dirty (" + rsv_ruimte_key + "); " // Zelf dirty geworden?
+ " res.set_ruimtes_clean (" + oldvan.toSQL() + "); " // Anderen 'clean' geworden
+ " res.follow_artikel (" + rsv_ruimte_key + ", " + oldvan.toSQL(true) + ", " + oldtot.toSQL(true) + "); " // catering mee verplaatsen
+ " res.follow_deel (" + rsv_ruimte_key + ", " + oldvan.toSQL(true) + ", " + oldtot.toSQL(true) + "); " // objecten mee verplaatsen
+ " res.follow_afspraak (" + rsv_ruimte_key + ", " + S("res_copy_to_bez") + "); " // bezoekers mee verplaatsen
+ check_fail_sql
+ "END;";
var err = Oracle.Execute(sql, true);
if (err.friendlyMsg)
abort_with_warning(err.friendlyMsg);
var restrack = api2.process_includes(params, this, jsondata, the_key);
// TODO: Tracking
// TODO: Bezoekers
// TODO: Flex
var flextrack = [];
//var result = saveBezoekers(afspr_key, -1, { urole: urole, loctimechanged: changed });
//if (result.beztrack && result.beztrack.length > 0)
//bezUpd.trackarray.push(result.beztrack.join("\n"));
res.trackreserveringupdate(rsv_ruimte_key, resUpd.trackarray.length || flextrack.length? L("lcl_res_is_resupdtrack").format(reservering_key + "/" + volgnr) + "\n" + resUpd.trackarray.concat(flextrack).join("\n") : null);
return { key: rsv_ruimte_key };
};
this.REST_POST = function (params, jsondata) /* new reservation */
{
params.isNew = true;
var dbfields = api2.update_fields(params, this, jsondata); // Build updater
_analyze_fields(dbfields, params, jsondata);
_validate_fields(dbfields, params, jsondata);
// Eerst een nieuw res_reservering record aanmaken
var resfields = { "id": { dbs: "res_reservering_key", typ: "key", seq: "res_s_res_reservering_key" },
"create": { dbs: "res_reservering_aanmaak", typ: "datetime", val: new Date() }
};
var resIns = buildInsert("res_reservering", resfields, { noValidateToken: true });
var reservering_key = resIns.sequences["res_reservering_key"];
var volgnr = 1;
Oracle.Execute(resIns.sql);
// Nu aan de slag met een res_rsv_ruimte record
dbfields["id"] = { dbs: "res_rsv_ruimte_key", typ: "key", seq: "res_s_res_rsv_ruimte_key" };
dbfields["reskey"] = { dbs: "res_reservering_key", typ: "key", val: reservering_key };
dbfields["sequence"] = { dbs: "res_rsv_ruimte_volgnr", typ: "number", val: volgnr };
dbfields["host"] = { dbs: "res_rsv_ruimte_host_key", typ: "key", val: user_key };
dbfields["contact"] = { dbs: "res_rsv_ruimte_contact_key", typ: "key", val: user_key };
if (!jsondata.status)
dbfields["status"] = { dbs: "res_status_fo_key", typ: "key", val: S("res_default_fe_status_key") };
var resIns = buildInsert("res_rsv_ruimte", dbfields, { noValidateToken: true });
var rsv_ruimte_key = resIns.sequences["res_rsv_ruimte_key"];
var check_fail_sql = " if res.dirty_level_all(" + rsv_ruimte_key + ") <> 0 then"
+ " raise_application_error (-20000, 'res_m999 " + L("lcl_res_fe_no_dirty") + "');"
+ " end if;"
var sql = "BEGIN "
+ resIns.sql + ";"
//+ deel_sql
+ " res.set_ruimte_dirty (" + rsv_ruimte_key + "); " // Zelf dirty geworden?
// set_ruimtes_clean hoeft niet: wij zijn nieuw en kunnen daarmee nooit een ander clean maken
+ check_fail_sql
+ "END;";
var err = Oracle.Execute(sql, true);
if (err.friendlyMsg)
abort_with_warning(err.friendlyMsg);
var restrack = api2.process_includes(params, this, jsondata, rsv_ruimte_key);
shared.trackaction("RESNEW", rsv_ruimte_key);
return { key: rsv_ruimte_key };
};
this.REST_DELETE = function (params, the_key) /* delete reservation */
{
// Sterk afgekeken van res_delete_save.asp. Die moet op termijn deze functie gaan
// gebruiken maar dan moet de auth_required_or_abort mogelijk weer iets 'zachter'
var cost_recharge = false; // TODO?
var rsv_ruimte_key = the_key;
var this_res = res.func_enabled(rsv_ruimte_key); // Wat mag ik op deze deelreservering
user.auth_required_or_abort(this_res.canDelete);
DeleteResAfspraak(rsv_ruimte_key);
// update ruimte
// equipment en articles are deleted automatically if the RES_RSV_RUIMTE is deleted
// Deze velden altijd opslaan
var dbfields = [ { dbs: "res_rsv_ruimte_opmerking", typ: "varchar", frm: "opmerk" },
{ dbs: "res_status_fo_key", typ: "key", val: (cost_recharge? 4 : 1) }, // status 1=optie, 4=vervallen
{ dbs: "res_rsv_ruimte_verwijder", typ: "sql", val: "SYSDATE" }
];
var sql = buildUpdate("res_rsv_ruimte", dbfields)
+ " res_rsv_ruimte_key = " + rsv_ruimte_key;
// ons eigen tijdstip/zaal is mogelijk gewijzigd waardoor andere *dirty* reserveringen
// clean wordt. Even onze oude datum onthouden zodat we niet *alles* hoeven te controleren
var oRs = Oracle.Execute("select res_rsv_ruimte_van,"
+ " res_rsv_ruimte_tot"
+ " from res_rsv_ruimte"
+ " where res_rsv_ruimte_key = " + rsv_ruimte_key);
var oldvan = new Date(oRs("res_rsv_ruimte_van").value);
var oldtot = new Date(oRs("res_rsv_ruimte_tot").value);
oRs.Close();
// Nu de echte update.
// Daarbij ook diverse controles/ updates uitvoeren op 'andere zaken'
sql = "BEGIN "
+ sql + ";"
+ " res.set_ruimte_dirty (" + rsv_ruimte_key + "); " // Zelf dirty geworden?
+ " res.set_ruimtes_clean (" + oldvan.toSQL() + "); " // Anderen 'clean' geworden
+ " res.follow_artikel (" + rsv_ruimte_key + ", " + oldvan.toSQL(true) + ", " + oldtot.toSQL(true) + "); " // catering mee verplaatsen
+ " res.follow_deel (" + rsv_ruimte_key + ", " + oldvan.toSQL(true) + ", " + oldtot.toSQL(true) + "); " // objecten mee verplaatsen
+ "END;";
Oracle.Execute( sql );
shared.trackaction("RESDEL", rsv_ruimte_key);
// En tenslotte eventueel de reservering zelf nog
sql = "UPDATE res_reservering "
+ " SET res_reservering_verwijder=SYSDATE"
+ " WHERE res_reservering_key="+this_res.res_reservering_key
+ " AND NOT EXISTS (SELECT *"
+ " FROM res_v_aanwezigrsv_ruimte"
+ " WHERE res_reservering_key=" + this_res.res_reservering_key + ")"
Oracle.Execute( sql );
}
if (rsv_key > 0)
{
params.filter = params.filter || {};
params.filter.id = rsv_key;
if (! ("include" in params) )
params.include = { include: ["custom_fields"]};
var xxx_array = this.REST_GET(params);
if (!xxx_array.length)
shared.record_not_found();
this.data = xxx_array[0];
}
}
%>