<% /* $Revision$ $Id$ File: model_issues.inc Description: Melding model Parameters: Context: Notes: TODO on demand: PUT/POST/DELETE TODO test autorisatie-toepassing (MGE?) */ %> <% function fnextendedStatus (oRs, field, model) { var xstatus = mld.getextendedmldstatus(oRs("mld_melding_status").Value, oRs("mld_melding_key").Value); return xstatus; } function model_issues(mld_key, params) { params = params || {}; this.module = "MLD"; this.table = "mld_melding"; this.primary = "mld_melding_key"; this.records_name = "issues"; this.record_name = "issue"; this.fields = {"id" : { dbs: "mld_melding_key", typ: "key", filter: "exact" }, "name" : { dbs: "mld_melding_id", typ: "varchar", sql: "ins_srtdiscipline.ins_srtdiscipline_prefix||mld_melding.mld_melding_key", filter: "exact", readonly: true }, "contact" : { dbs: "prs_perslid_key", typ: "key", foreign: "prs_perslid", label: L("lcl_mld_name"), track: true, filter: "exact" }, "requestor" : { dbs: "prs_perslid_key_voor", typ: "key", foreign: "prs_perslid", label: L("lcl_mld_call_for"), track: true, filter: "exact" }, "issuedate" : { dbs: "mld_melding_datum", typ: "datetime", label: L("lcl_mld_date_time"), track: true, filter: "range" }, "enddate" : { dbs: "mld_melding_einddatum", typ: "datetime", label: L("lcl_mld_enddate"), track: true}, "issuetype" : { dbs: "mld_stdmelding_key", typ: "key", foreign: "mld_stdmelding", label: L("lcl_complain"), track: true, filter: "exact" }, "description": { dbs: "mld_melding_omschrijving", typ: "varchar", label: L("lcl_descr"), track: true, filter: "like" }, "remark" : { dbs: "mld_melding_opmerking", typ: "varchar", label: L("lcl_remark"), track: true}, "subject" : { dbs: "mld_melding_onderwerp", typ: "varchar", label: L("lcl_mld_subject"), track: true}, "status" : { dbs: "mld_melding_status", typ: "key", foreign: mld.getmldstatustext, label: L("lcl_status"), track: true, filter: mld.getStatusSql }, "flag" : { dbs: "mld_melding_flag", typ: "key", /* geen echte key, wel key-gedrag */ label: L("lcl_mld_flags"), track: true, filter: "exact" }, "account" : { dbs: "prs_kostenplaats_key", typ: "key", foreign: "prs_kostenplaats", label: L("lcl_account"), track: true, filter: "exact" }, "handler" : { dbs: "mld_melding_behandelaar_key", typ: "key", foreign: "prs_perslid", label: L("lcl_mld_behandelaar"), track: true, filter: "exact" }, "location" : { dbs: "mld_alg_locatie_key", typ: "key", foreign: "alg_locatie", label: L("lcl_location"), track: true, filter: "exact" }, "building" : { dbs: "alg_v_allonroerendgoed.alg_gebouw_key", typ: "key", foreign: "alg_gebouw", label: L("lcl_building"), track: true, filter: "exact" }, "floor" : { dbs: "alg_v_allonroerendgoed.alg_verdieping_key", typ: "key", foreign: "alg_verdieping", label: L("lcl_floor"), track: true, filter: "exact" }, "room" : { dbs: "alg_v_allonroerendgoed.alg_ruimte_key", typ: "key", foreign: "alg_ruimte", label: L("lcl_room"), track: true, filter: "exact" }, "terrain" : { dbs: "alg_v_allonroerendgoed.alg_terreinsector_key", typ: "key", foreign: "alg_terreinsector", label: L("lcl_room"), track: true, filter: "exact" }, "parent" : { dbs: "mld_melding_parentkey", typ: "key", xforeign: "mld_melding", label: L("lcl_mld_completion_in"), track: true, filter: "exact" }, "extern_id" : { dbs: "mld_melding_externnr", typ: "varchar", label: L("lcl_mld_externr"), track: true, filter: "exact" }, "kto_key" : { dbs: "mld_melding_kto_key", typ: "key", label: L("lcl_mld_linktoparent"), track: true, filter: "exact" }, "kto_type" : { dbs: "mld_melding_kto_type", typ: "varchar", label: L("lcl_mld_kto"), track: true, filter: "exact" }, "kto" : { dbs: "mld_melding_kto", typ: "number", label: L("lcl_mld_kto_invite"), track: true, filter: "exact" }, "priority" : { dbs: "mld_melding_spoed", typ: "key", label: L("lcl_mld_urg"), track: true, filter: "exact" }, "xstatus" : { dbs: "mld_melding_status", val: fnextendedStatus, typ: "key", foreign: mld.getmldstatustext, label: L("lcl_extended_status"), track: true, filter: "exact", readonly: true } }; this.list = { columns: ["id", "name", "requestor", "description"] }; this.includes = { "custom_fields": { model: new model_custom_fields(this, new model_mld_kenmerk('M', { internal: true }), { pNiveau: "M", readman: true, readuse: true }), joinfield: "flexparentkey", "enable_update": true }, "tracking": { model: new model_tracking(['melding']), joinfield: "trackingrefkey" }, "notes": { model: new model_notes("MLD"), joinfield: "parent" }, "orders": { model: new model_orders(), joinfield: "issue" }, "issueobjects": { model: model_issueobjects, joinfield: "mld_melding_key" } }; this.REST_GET = function _GET(params) { var query = api2.sqlfields(params, this ); query.wheres.push("mld_melding.fac_activiteit_key IS NULL"); // Als je een filter-id meegeeft werken we scopeloos/ heel nauwkeurig if (params.filter.id) { var sql = "SELECT 1 FROM mld_melding WHERE mld_melding_key = " + params.filter.id; var oRs = Oracle.Execute(sql); if (!oRs.eof) { // XD: zoeken op niet-bestaande key geeft anders een AiAi. var this_mld = mld.func_enabled_melding(params.filter.id); user.auth_required_or_abort(this_mld.canReadAny); } oRs.Close(); } else { var scope = params.filter.scope || "fe"; var autfunction = { fe : "WEB_MLDUSE", fo : "WEB_MLDFOF", bo : "WEB_MLDBOF", mi : "WEB_MLDBAC" } [scope]; params.authparams = user.checkAutorisation(autfunction, null, null, true); /* pessimistic */ // Hier kom je niet meer terecht als bovenstaande autorisatiecheck niet tot succes leidt. var alg3d = false; var prs3d = false; if (scope == "fe") { query.wheres.push("mld_melding.prs_perslid_key=" + user_key); } /* You can't go any further back in time than the GUI could (ongeveer)*/ /* Als er wel een start_issuedate is dan wordt deze toegevoegd in api2.sqlfilter() verderop. */ if (!params.filter.start_issuedate && S("mld_max_history") > 0) { query.wheres.push("mld_melding_datum > SYSDATE - "+ S("mld_max_history")); } if (!params.filter.status) { /* Limitation: if no status filter, then default to the active statusses (all except 1,6,5) */ // Zou zo kunnen, params.filter.status = [0,2,3,4,7];, maar eigenlijk is dit logischer query.wheres.push("mld_melding_status IN (0,2,3,4,7)"); } } /* we need the prefix for the name */ query.tables.push("mld_stdmelding"); query.wheres.push("mld_melding.mld_stdmelding_key = mld_stdmelding.mld_stdmelding_key"); query.tables.push("ins_tab_discipline"); query.wheres.push("mld_stdmelding.mld_ins_discipline_key = ins_tab_discipline.ins_discipline_key"); query.tables.push("ins_srtdiscipline"); query.wheres.push("ins_tab_discipline.ins_srtdiscipline_key = ins_srtdiscipline.ins_srtdiscipline_key"); query.tables.push("alg_v_allonroerendgoed"); query.wheres.push("mld_melding.mld_alg_onroerendgoed_keys = alg_v_allonroerendgoed.alg_onroerendgoed_keys(+)"); if (!params.filter.id) { if (params.authparams.ALGreadlevel > -1) { /* required for 3D ALG scopeing */ alg3d = true; __Log("ALGreadlevel="+params.authparams.ALGreadlevel); query.tables.push("alg_locatie"); /* opletten: outerjoin denk ik? */ query.wheres.push("mld_melding.mld_alg_onroerendgoed_keys = alg_locatie.alg_locatie_key(+)"); query.tables.push("alg_district"); query.wheres.push("alg_locatie.alg_district_key = alg_district.alg_district_key(+)"); } if (params.authparams.PRSreadlevel > -1) { /* required for 3D PRS scopeing */ prs3d = true; __Log("PRSreadlevel="+params.authparams.PRSreadlevel); query.tables.push("prs_perslid"); query.tables.push("prs_v_afdeling_boom"); query.wheres.push("mld_melding.prs_perslid_key = prs_perslid.prs_perslid_key"); query.wheres.push("prs_perslid.prs_afdeling_key = prs_v_afdeling_boom.prs_afdeling_key"); } } var wheres = api2.sqlfilter(params, this); query.wheres = query.wheres.concat(wheres); var sql = "SELECT " + query.selects.join(", ") + " FROM " + query.tables.join(", ") + " WHERE " + query.wheres.join(" AND " ); if (!params.filter.id) { // Over het resultaat moet nog de 3D rasp, altijd sql = discx3d (sql, "ins_tab_discipline.ins_discipline_key", (alg3d ? "alg_district.alg_regio_key" : null), (alg3d ? "alg_district.alg_district_key" : null), (alg3d ? "mld_melding.mld_alg_locatie_key" : null), (alg3d ? "alg_v_allonroerendgoed.alg_gebouw_key" : null), (alg3d ? "alg_v_allonroerendgoed.alg_verdieping_key" : null), (alg3d ? "alg_v_allonroerendgoed.alg_ruimte_key" : null), (prs3d ? "prs_bedrijf_key" : null), (prs3d ? "prs_afdeling_key" : null), autfunction, "", /* no additional discipline restrictions */ (alg3d && prs3d ? 2 : prs3d ? 1 : 0) ); } sql += " ORDER BY mld_melding_key"; // Order by nodig voor includes if (query.orderbys.length) sql += ", " + query.orderbys.join(", "); var json = api2.sql2json (params, sql, this ); return json; }; function _pre_analyze_fields (params, jsondata) /* analyseer inkomende jsondata voor POST */ { params.data = {}; var mld_key = jsondata.id; // // var stdm_info = mld.mld_stdmeldinginfo(jsondata.issuetype); // Startdatum: indien niet meegegeven, neem dan sysdate var startdate = (jsondata.issuedate ? jsondata.issuedate : new Date); var startwerkdag = parseFloat(S("fac_t_startofworkday")); var startwerkdag_uur = Math.floor(startwerkdag); var startwerkdag_min = (startwerkdag - Math.floor(startwerkdag)) * 60; var startdatebegin = new Date(startdate.getFullYear(), startdate.getMonth(), startdate.getDate(), startwerkdag_uur, startwerkdag_min); var sysdate = new Date(); // if (stdm_info.startdatum) { // Situatie 1: Einddatum = TRUNC(startdatum) + 8:00 uur + SLA // LET OP!!!: Als setting "mld_disc_params_startdatum" is gezet dan wordt eigenlijk verondersteld dat de SLA in dagen is en niet in uren. // Echter als de startdatum de registratiedatum (bij nieuwe melding dus sysdate) is moet wel voor de begintijd de registratietijd (registratiedatum) genomen worden tijdens het opslaan. // Anders geldt de acceptatietijd (in uren) onterecht al vanaf het begin van de dag. if (params.isNew) { // Nieuwe melding. // Startdatum is vandaag: starttijd is huidige tijd. // Startdatum is niet vandaag: starttijd is begin werkdag. var startdate_is_today = (startdate.midnight().getTime() == sysdate.midnight().getTime()); params.data.startdate = (startdate_is_today? sysdate : startdatebegin); } else { // Bestaande melding sql = "SELECT mld_melding_datum" + " FROM mld_melding" + " WHERE mld_melding_key = " + mld_key; oRs = Oracle.Execute(sql); var oldstartdate = new Date(oRs("mld_melding_datum").Value); // Alleen als datum veranderd is moet de starttijd worden aangepast. if (startdate.midnight().getTime() != oldstartdate.midnight().getTime()) { // Startdatum is aangepast. // Als de startdatum is aangepast in registratiedatum, dan wel weer de registratietijd (registratiedatum) pakken. // In alle andere gevallen begin van de werkdag pakken. sql = "SELECT fac.gettrackingdate('MLDNEW', " + mld_key + ") registratiedatum FROM DUAL" oRs_1 = Oracle.Execute(sql); var registratiedatum = new Date(oRs_1("registratiedatum").Value); oRs_1.Close(); var startdatum_is_registratiedatum = (startdate.midnight().getTime() == registratiedatum.midnight().getTime()); params.data.startdate = (startdatum_is_registratiedatum? registratiedatum : startdatebegin); } else { // else startdatum niet aanpassen. params.data.startdate = oldstartdate; } oRs.Close(); } } else { // Situatie 2: Einddatum = COALESCE(huidige waarde, sysdate) + SLA if (params.isNew) { params.data.startdate = new Date(); } else { // startdate = jsondata.issuedate; } } // jsondata.issuedate = startdate; // De einddatum is de meegegeven einddatum, maar als die niet wordt meegegeven regelt de trigger dat wel, dus DAN MOET IK HEM NIET MEEGEVEN // // Onroerendgoed_keys wordt de verfijnste van de opgegeven plaats var locatiekey = (jsondata.location ? jsondata.location : -1); var gebouwkey = (jsondata.building ? jsondata.building : -1); var verdiepingkey = (jsondata.floor ? jsondata.floor : -1); var ruimtekey = (jsondata.room ? jsondata.room : -1); var alg_onroerendgoed_keys = -1; if (stdm_info.alg_level > 2) { // die specifiekere plaats moet dan leegblijven if (ruimtekey != -1) alg_onroerendgoed_keys = ruimtekey; else if (verdiepingkey != -1) alg_onroerendgoed_keys = verdiepingkey; else if (gebouwkey != -1) alg_onroerendgoed_keys = gebouwkey; } params.data.alg_onroerendgoed_keys = alg_onroerendgoed_keys; return params; }; function _analyze_fields (dbfields, params, jsondata) /* analyseer inkomende data, common voor PUT en POST */ { }; function _validate_fields (dbfields, params, jsondata) /* valideer fields, alle constraints die niet door de database worden afgevangen */ { // als einddatum ingevuld is moet deze groter/gelijk zijn aan de begindatum }; function _validate_close (params, jsondata, the_key) /* uit: mld_close_save.asp */ { var mld_key = the_key; var this_mld = mld.func_enabled_melding(mld_key); user.auth_required_or_abort(this_mld.canClose); // Als je mag accepteren mag je ook rejecten params.data = {}; params.data.tobeclosed = false; params.data.canCloseOpdrOfMld = []; var canCloseOpdr = []; var reqStatusEmpty = []; var noOpdrCloseAtAll = false; var futureOpdr = false; // Zijn er nog kenmerken die nu wel verplicht zijn? var kvsAfwezig = mld.hasRequiredStatusEmptyMelding(mld_key, 5); // Melding status "Afgemeld(5)" if (kvsAfwezig.length) { var mldnr = mld.mld_prefix(mld_key) + mld_key; reqStatusEmpty.push(L("lcl_mld_req_status_empty").format(kvsAfwezig.join(", "), mldnr) ); } // Zijn er nog lopende opdrachten? var sql = "SELECT o.mld_opdr_key" + " FROM mld_opdr o" + " WHERE o.mld_melding_key = " + mld_key + " AND o.mld_statusopdr_key NOT IN (1, 6, 7, 9)"; var oRsOM = Oracle.Execute(sql); while (!oRsOM.eof) { // Voor elke opdracht van een melding controleren of deze afgemeld mag worden var mld_opdr_key = oRsOM("mld_opdr_key").Value; sql = "SELECT mld_opdr_einddatum" + " FROM mld_opdr o" + " WHERE o.mld_opdr_key = " + mld_opdr_key; var oRs = Oracle.Execute(sql); // Als Setting S("mld_ord_afmeld_future") niet is gezet (0): Opdrachten waarvan de einddatum in de toekomst ligt mogen niet worden afgemeld. var this_opdr = mld.func_enabled_opdracht(mld_opdr_key); if (!this_opdr.canClose || (S("mld_ord_afmeld_future") != 1 && (oRs("mld_opdr_einddatum").value > new Date()))) { // Geen autorisatie om alle opdrachten van een melding af te melden of opdrachten in de toekomst // met setting S("mld_ord_afmeld_future") niet gezet-->dan geen enkele van die melding noOpdrCloseAtAll = true; if (S("mld_ord_afmeld_future") != 1 && (oRs("mld_opdr_einddatum").value > new Date())) futureOpdr = true; // Indien opdrachten in de toekomst en setting S("mld_ord_afmeld_future") niet gezet (0) dan mag je de melding niet afmelden } oRs.Close(); params.data.canCloseOpdrOfMld.push(mld_opdr_key); oRsOM.MoveNext(); } oRsOM.Close(); if (!futureOpdr && !noOpdrCloseAtAll) { // Indien opdrachten in de toekomst en setting S("mld_ord_afmeld_future") niet gezet (0) dan mag je de melding niet afmelden // EN geen opdrachten of alle opdrachten mogen gesloten worden, dan kan de melding afgemeld worden params.data.tobeclosed = true; } else { api2.error(500, "Issue can not be closed"); } }; this.REST_PUT = function (params, jsondata, the_key) /* update issue */ { if (!jsondata.id) jsondata.id = the_key; var mld_key = jsondata.id; // Vul jsondata aan met actuele 'oude' data var old_mld = new model_issues(mld_key).data; for (var fld in old_mld) { if (!(fld in jsondata)) jsondata[fld] = old_mld[fld]; } api2.cleanup_data(this, jsondata); // Doet een generieke dereference van alle foreign's var this_mld = mld.func_enabled_melding(mld_key); user.auth_required_or_abort(this_mld.canChange); // Geen wijzigingen toestaan bij onvoldoende rechten. if (params.custom_fields_only) { var mldUpd = { trackarray: [] }; } else { params = _pre_analyze_fields(params, jsondata); // Verwijder voor PUT wat niet gewijzigd mag worden. delete jsondata.name; delete jsondata.contact; delete jsondata.requestor; delete jsondata.issuetype; delete jsondata.location; var dbfields = api2.update_fields(params, this, jsondata); // Build updater _analyze_fields(dbfields, params, jsondata); _validate_fields(dbfields, params, jsondata); var wheres = [" mld_melding_key = " + mld_key]; var mldUpd = buildTrackingUpdate("mld_melding", wheres.join(" AND " ), dbfields, { noValidateToken: true }); var err = Oracle.Execute(mldUpd.sql, true); if (err.friendlyMsg) abort_with_warning(err.friendlyMsg); } var mldtrack = api2.process_includes(params, this, jsondata, mld_key); if (mldUpd.trackarray.length) { shared.trackaction("MLDUPD", mld_key, L("lcl_mld_is_mldupdtrack").format(mld_key) + (mldUpd.trackarray.length > 0? "\n" : "") + mldUpd.trackarray.join("\n")); } if (jsondata.status > 0) mld.setmeldingstatus(mld_key, jsondata.status, ""); return { key: mld_key }; }; this.REST_POST = function (params, jsondata) /* new call */ { api2.cleanup_data(this, jsondata); // Doet een generieke dereference van alle foreign's // // Voor een nieuwe melding moet er een geldige stdmelding zijn. if (!jsondata.issuetype) api2.error(500, "Missing issuetype") var stdm = new model_issuetypes(jsondata.issuetype).data; // // Bepaal de kostenplaats, indien verplicht. var stdm_info = mld.mld_stdmeldinginfo(jsondata.issuetype); var kpkey = (jsondata.account ? jsondata.account : -1); if (stdm_info.kpnverplicht && kpkey < 0) { // Kostenplaats is verplicht, maar is niet meegegeven. Bepaal default kostenplaats. kpkey = (user.afdeling().prs_kostenplaats_key() || -1); // User kostenplaats key } if (stdm_info.kpnverplicht && kpkey < 0) { // Kon ook geen default kostenplaats vinden. api2.error(500, "Account could not be validated"); } jsondata.account = kpkey; if (!jsondata.issuedate) jsondata.issuedate = new Date(); if (!jsondata.priority) jsondata.priority = 3; // if (!jsondata.contact) jsondata.contact = user_key; // Als er geen aanvrager opgegeven is, dan de huidige gebruiker invullen. // Als de setting niet is gezet is "Melding voor" gelijk aan contactpersoon. if (S("mld_allow_for_others") == 0) { jsondata.requestor = jsondata.contact; } params.isNew = true; params = _pre_analyze_fields(params, jsondata); var this_mld = mld.func_enabled_mld(stdm_info.ins_discipline_key, "D"); user.auth_required_or_abort(this_mld.canFEwrite || this_mld.canFOwrite); // var dbfields = api2.update_fields(params, this, jsondata); // Build updater _analyze_fields(dbfields, params, jsondata); _validate_fields(dbfields, params, jsondata); dbfields["alg"] = { dbs: "mld_alg_onroerendgoed_keys", typ: "datetime", val: params.data.alg_onroerendgoed_keys == -1 ? null : params.data.alg_onroerendgoed_keys }; dbfields["origin"] = { dbs: "mld_meldbron_key", typ: "key", val: jsondata.meldbron? jsondata.meldbron : S("mld_meldbron_key") }; dbfields["module"] = { dbs: "mld_melding_module", typ: "varchar", val: "MLD" }; dbfields["issue"] = { dbs: "mld_melding_key", typ: "key", seq: "mld_s_mld_melding_key" }; var mldIns = buildInsert("mld_melding", dbfields, { noValidateToken: true }); var new_key = mldIns.sequences["mld_melding_key"]; var sql = mldIns.sql; Oracle.Execute(mldIns.sql); var mldtrack = api2.process_includes(params, this, jsondata, new_key); mld.setmeldingstatus(new_key, (stdm.xmld_directklaar? 0 : 2)); // Zorgt ook voor tracking & daarmee notificatie if (stdm_info.xis_kto_answer) // die direct afmelden mld.setmeldingstatus(new_key, 5); return { key: new_key }; }; //JGL: Even uitgeschakeld want beetje raar en in ieder geval krijgt hij geen jsondata meer this.xxxREST_DELETE = function (params, the_key) /* delete call */ { // Een melding wordt niet verwijderd maar wordt afgesloten. var scope = params.filter.scope || "fe"; var autfunction = { fe : "WEB_MLDUSE", fo : "WEB_MLDFOF", bo : "WEB_MLDBOF", mi : "WEB_MLDBAC" } [scope]; params.authparams = user.checkAutorisation(autfunction, null, null, true); /* pessimistic */ // Hier kom je niet meer terecht als bovenstaande autorisatiecheck niet tot succes leidt. this._validate_close(params, jsondata, the_key); // De melding en eventuele opdrachten mogen afgemeld worden. // Ik had nog graag een L("lcl_mld_final_remark") toe willen voegen aan de melding, maar er is geen jsondata bij DELETE. // Eventuele opdrachten afmelden. for (opdr_i in params.data.canCloseOpdrOfMld) { mld.setopdrachtstatus(canCloseOpdrOfMld[opdr_i], 6); // Technisch voltooid (TV) (Afgemeld) } // De melding zelf afmelden. mld.setmeldingstatus(the_key, 5); } this.search = { "filters": ["id"] }; if (mld_key > 0) { params.filter = params.filter || {}; params.filter.id = mld_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]; } } %>