<% /* $Revision$ $Id$ File: model_report_columns.inc Description: rapport model voor de kolommen van rapporten. Parameters: Context: Notes: */ // model_reportcolumns is uitsluitend beschikbaar onder model_reports(x) die de autorisatie dan ook doet // TODO: neen, security lek FSN#33869 function model_reportcolumns(usrrap_key, params) { var rap_key = getQParamInt("fac_usrrap_key", -1); // JGL: Lelijk params = params || {}; this.records_name = "columns"; this.record_name = "column"; this.table = "fac_usrrap_cols"; this.primary = "fac_usrrap_cols_key"; this.records_title = L("lcl_rap_columns"); this.record_title = L("lcl_rap_column"); this.autfunction = "WEB_UDRMAN", this.edit = { modal: true }; this.fields = { "id": { dbs: "fac_usrrap_cols_key", typ: "key", label: L("lcl_key"), filter: "exact", seq: "fac_s_fac_usrrap_cols_key" }, "name": { dbs: "fac_usrrap_cols_column_name", typ: "varchar", label: L("lcl_rap_column"), required: true, insertonly: true }, "datatype": { dbs: "fac_usrrap_cols_datatype", typ: "varchar", label: L("lcl_rap_datatype"), required: true, LOV: L("lcl_rap_datatypeLOV") // "varchar;Tekst;date;Datum;datetime;Datumtijd;float;Float;currency;Bedrag;number;Getal" }, "sequence": { dbs: "fac_usrrap_cols_volgnr", typ: "number", label: L("lcl_rap_sequence"), required: true }, "caption": { dbs: "fac_usrrap_cols_caption", typ: "varchar", label: L("lcl_rap_caption"), required: true, translate: true }, "filter": { dbs: "fac_usrrap_cols_filter", typ: "varchar", label: L("lcl_rap_filter"), LOV: L("lcl_rap_filterLOV"), // "A;Automatisch" multiedit: true }, "filterdefault": { dbs: "fac_usrrap_cols_filterdefault", typ: "varchar", label: L("lcl_rap_filterdefault") }, "visible": { dbs: "fac_usrrap_cols_visible", typ: "varchar", label: L("lcl_rap_visible"), required: true, LOV: L("lcl_rap_visibleLOV"), // "V;Visible;I;Invisible;H;hidden" emptyoption: null, multiedit: true }, "group": { dbs: "fac_usrrap_cols_group", typ: "varchar", label: L("lcl_rap_groupby"), required: true, LOV: L("lcl_rap_groupbyLOV"), emptyoption: null }, "fac_usrrap_key": { dbs: "fac_usrrap_key", typ: "key", hidden_fld: true }, "expression": { dbs: "fac_usrrap_cols_expression", typ: "memo", label: L("lcl_rap_expression"), required: true, readonly: true } }; this.fnrowClass = function _fnrowClass(oRs) { return "report_" + oRs.Fields("visible").Value.id; } this.list = { columns: [ "sequence", "name", "caption", "datatype", "visible", "filter", "group" ], rowClass: this.fnrowClass }; this.hook_pre_edit = function (obj, fld) { this.fields.filter.LOV = api2.filterLOV(L("lcl_rap_filterLOV"), "A,E,R"); // De meesten mogen L(ike) niet if ((obj.datatype && !obj.expression) || !user.has("WEB_FACTAB")) { switch (obj.datatype.id) { case "date": case "datetime": this.fields.group.LOV = api2.filterLOV(L("lcl_rap_groupbyLOV"), "G,D,W,M,Q,Y,H"); this.fields.datatype.LOV = api2.filterLOV(L("lcl_rap_datatypeLOV"), "date,datetime,time"); break; case "time": this.fields.group.LOV = api2.filterLOV(L("lcl_rap_groupbyLOV"), "G,H"); this.fields.datatype.LOV = api2.filterLOV(L("lcl_rap_datatypeLOV"), "date,datetime,time"); break; case "varchar": this.fields.group.LOV = api2.filterLOV(L("lcl_rap_groupbyLOV"), "G"); this.fields.datatype.readonly = true; this.fields.filter.LOV = L("lcl_rap_filterLOV"); // die mag alle filters break; case "html": this.fields.group.LOV = api2.filterLOV(L("lcl_rap_groupbyLOV"), "G"); this.fields.datatype.readonly = true; this.fields.filter.LOV = L("lcl_rap_filterLOV"); break; case "float": case "number": case "currency": this.fields.group.LOV = api2.filterLOV(L("lcl_rap_groupbyLOV"), "G,S,C,A"); this.fields.datatype.LOV = api2.filterLOV(L("lcl_rap_datatypeLOV"), "float,currency,number"); break; default: this.fields.group.LOV = api2.filterLOV(L("lcl_rap_groupbyLOV"), "G"); } } if (user.has("WEB_FACTAB") && (obj.expression || !obj.id)) { this.fields.expression.readonly = false; this.fields.name.insertonly = false; // Een zelf toegevoegd veld mag ook verwijderd worden. if (obj.expression) { this.REST_DELETE = generic_REST_DELETE(this); } } }; this.hook_pre_post = function (params, obj) { if (obj.id == -1) this.fields.expression.readonly = false; }; this.hook_pre_delete = function (params, columns_key) { var sql = "SELECT 1" + " FROM fac_usrrap_cols" + " WHERE fac_usrrap_cols_expression IS NOT NULL" + " AND fac_usrrap_cols_key = " + columns_key; var oRs = Oracle.Execute(sql, true); if (oRs.eof) abort_with_warning(L("lcl_cnt_Del_Fails_Auth")); oRs.Close(); user.checkAutorisation("WEB_FACTAB"); this.REST_DELETE = generic_REST_DELETE(this); }; // Maakt de default fac_usrrap_cols records aan aan de hand van de view of werk ze bij this._view2columns = function (usrrap_key, lastrefresh, oldcols) { var sql = "SELECT fac_usrrap_view_name" + " , fac_usrrap_functie" + " FROM fac_usrrap" + " WHERE fac_usrrap_key = " + usrrap_key; var oRs = Oracle.Execute(sql); var view_name = oRs("fac_usrrap_view_name").Value; var is_view_name = (oRs("fac_usrrap_functie").Value & 2) == 0; // niet de procedures oRs.Close(); if (!is_view_name) return; // Rapport kan ook zijn XXXX.RAP_YYYYY? // PF: jawel, maar dan is het een procedure waarvan je de structuur niet zo op kunt vragen?! // Vandaar de regel hiervoor, die zorgt dat we hier al weg zijn. Ik denk dat de shortname dan verder // niet meer voorkomt eigenlijk. var view_name_short = view_name.toUpperCase(); var i = view_name_short.indexOf('.'); if (i != -1) view_name_short = view_name_short.substring(i+1); var hasFACFAC = user.checkAutorisation("WEB_FACFAC", true); // Die mag ook tabellen doen var sql = "SELECT object_name, object_type, last_ddl_time, status" + " FROM user_objects" + " WHERE " + (hasFACFAC ? "object_type IN ('VIEW', 'TABLE')" : " object_type = 'VIEW'") + " AND object_name = UPPER(" + safe.quoted_sql(view_name_short) + ")"; var oRs = Oracle.Execute(sql); if (oRs.Eof) abort_with_warning("Unable to determine columns for report view '{0}'!".format(view_name_short)); if (oRs("status").Value != 'VALID') // Gebeurt nog wel eens na een dump-refresh { if (oRs("object_type").Value == 'VIEW') { __DoLog("Auto compile invalid {0}".format(view_name_short)); Oracle.Execute("ALTER VIEW {0} COMPILE".format(view_name_short)); oRs.Close(); var oRs = Oracle.Execute(sql); // Tweede poging } } if (oRs("status").Value != 'VALID') abort_with_warning("Report view '{0}' is INVALID!".format(view_name_short)); var view_ddl_time = new Date(oRs("last_ddl_time").Value); oRs.Close(); var mustRefresh = (oldcols.length == 0 || !lastrefresh || view_ddl_time > lastrefresh); if (!mustRefresh) return; var sequence = 10; var sql = "SELECT INITCAP(column_name) column_name" + " , data_type" + " , data_length" + " , data_precision" + " , data_scale" + " FROM user_tab_columns" + " WHERE table_name = UPPER(" + safe.quoted_sql(view_name_short) + ")" + " ORDER BY column_id"; var oRs = Oracle.Execute(sql); var newcols = []; while (!oRs.eof) { var colname = oRs.Fields("column_name").Value.toLowerCase(); var colpar = { caption: oRs.Fields("column_name").Value, // Met de initcap name: colname, datatype: "varchar", group: 'G', sequence: sequence, visible: 'V', filter: null }; sequence += 10; var ucolname = colname.toUpperCase(); var special_cols = ucolname.match(/^(HIDE_F_|FCLT_X_|FCLT_3D_|FCLT_KEY|FCLT_F_|HTML_|FCLT_D_|FCLT_C_)/); if (special_cols) colpar.caption = colpar.caption.substring(special_cols[0].length); colpar.caption = colpar.caption.replace(/\_/g, " "); // underscores er uit if (ucolname.match(/^(HIDE_F_|FCLT_3D_|FCLT_KEY)/)) colpar.visible = 'H'; // Hidden if (ucolname.match(/^(FCLT_X_)/)) colpar.visible = 'I'; // Invisible, je mag hem wel aanzetten if (view_name_short.match(/_V_UDR/)) colpar.visible = 'H'; // Hidden, die hebben te veel kolommen if (ucolname.match(/^(FCLT_F_|FCLT_X_)/)) colpar.filter = 'A'; if (ucolname.match(/^(FCLT_D_)/)) colpar.filter = 'R'; // Altijd range var ora_type = oRs("data_type").Value; var ora_length = oRs("data_length").Value; var ora_precision = oRs("data_precision").Value; var ora_scale = oRs("data_scale").Value; if (ucolname.match("^FCLT_C_")) // Currency { colpar.datatype = 'currency'; } else if (ucolname.match("^HTML_")) { colpar.datatype = 'html'; } else if (ora_type == 'NUMBER') { colpar.datatype = 'number'; if (ora_scale > 0) { colpar.datatype = 'float'; } } else if (ora_type == "DATE") // { colpar.datatype = 'date'; } newcols.push(colpar); oRs.MoveNext(); } oRs.Close(); // Vervallen kolommen if (lastrefresh) // Nieuwe (geimporteerde) report heeft geen vervallen kolommen, maar nieuwe kolommen moeten wel toegevoegd worden. { for (var o = 0; o < oldcols.length; o++) { var found = false; for (var n = 0; !found && n < newcols.length; n++) { if (newcols[n].name == oldcols[o].name) found = true; } if (!found) { __Log("Dropping column {0}".format(oldcols[o].name)); // We kennen geen REST_DELETE var sql = "DELETE fac_usrrap_cols" + " WHERE fac_usrrap_cols_expression IS NULL" + " AND fac_usrrap_cols_key = " + oldcols[o].id; Oracle.Execute(sql); } } } // Nieuwe en gewijzigde kolommen for (var n = 0; n < newcols.length; n++) { var found = false; for (var o = 0; !found && o < oldcols.length; o++) { if (newcols[n].name == oldcols[o].name) { found = true; if (newcols[n].datatype == oldcols[o].datatype.id) continue; // wisseling binnen float,currency,number is niet erg if (inArray(newcols[n].datatype, "float,currency,number".split(",")) && inArray(oldcols[o].datatype.id, "float,currency,number".split(","))) continue; // wisseling binnen date,datetime,time is ook niet erg if (inArray(newcols[n].datatype, "date,datetime,time".split(",")) && inArray(oldcols[o].datatype.id, "date,datetime,time".split(","))) continue; // datatype aanpassen __Log("Updating datatype column {0} to {1}".format(oldcols[o].name, newcols[n].datatype)); this._REST_PUT({}, { datatype: newcols[n].datatype }, oldcols[o].id) } } if (!found) { __Log("Adding column {0}".format(newcols[n].name)); var params = { internal: true }; this._REST_POST(params, newcols[n], usrrap_key); // internal _REST_POST is er altijd } } // update lastrefresh. reports.REST_PUT is mij te kritisch op rechten var sql = "UPDATE fac_usrrap" + " SET fac_usrrap_col_refresh = SYSDATE" + " WHERE fac_usrrap_key = " + usrrap_key; Oracle.Execute(sql); } this.REST_GET = function _GET(params) { // De modal detail popup gebruikt dit echter nog wel. var query = api2.sqlfields(params, this ); 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 " ) + " ORDER BY fac_usrrap_cols_volgnr"; var json = api2.sql2json (params, sql, this ); if (!json.length) { INTERNAL_ERROR_MISSING_COLUMNS; } return json; } this.REST_PUT = function (params, jsondata, the_key) /* update columns */ { var valid_char = /^[_0-9a-zA-Z]+$/; // Alleen deze tekens zijn geldig! if (!valid_char.test(jsondata.name)) abort_with_warning(L("lcl_rap_column_invalid")); if (user.has("WEB_FACTAB") && (jsondata.expression || !jsondata.id)) { this.fields.expression.readonly = false; this.fields.name.insertonly = false; } var dbfields = api2.update_fields(params, this, jsondata); // Build updater var sql = buildUpdate("fac_usrrap_cols", dbfields, { noValidateToken: true }) + " fac_usrrap_cols_key = " + the_key; var err = Oracle.Execute(sql, true); if (err.friendlyMsg) abort_with_warning(err.friendlyMsg); return { key: the_key }; } this._REST_PUT = this.REST_PUT; // Interne is er altijd // Only internally used by report_clone and _view2columns this._REST_POST = function (params, jsondata, parent_key) /* insert columns */ { params.isNew = true; if (user.has("WEB_FACTAB") && !jsondata.id) this.fields.expression.readonly = false; var valid_char = /^[_0-9a-zA-Z]+$/; if (!valid_char.test(jsondata.name)) abort_with_warning(L("lcl_rap_column_invalid")); var dbfields = api2.update_fields(params, this, jsondata); // Build updater dbfields["id"] = this.fields["id"]; if (parent_key && !jsondata.fac_usrrap_key) dbfields["xxx"] = { dbs: "fac_usrrap_key", typ: "key", val: parent_key }; var rapIns = buildInsert("fac_usrrap_cols", dbfields, { noValidateToken: true }); var col_key = rapIns.sequences["fac_usrrap_col_key"]; var err = Oracle.Execute(rapIns.sql, true); if (err.friendlyMsg) abort_with_warning(err.friendlyMsg); return { key: col_key, warning: "" }; } if (rap_key > 0) { // var rap_data = model_reportsx(rap_key); te veel recursie var sql = "SELECT fac_usrrap_functie" + " FROM fac_usrrap" + " WHERE fac_usrrap_key = " + rap_key; var oRs = Oracle.Execute(sql); var functie = oRs("fac_usrrap_functie").Value || 0; oRs.Close(); if (functie & 32) // template this.REST_PUT = false; } if (params.internal || user.has("WEB_FACTAB")) { this.REST_POST = this._REST_POST; // Voor de clone-report } } %>