<% /* $Revision$ $Id$ File: kenmerk_common.inc Description: Context: Used by /XX/kenmerk.inc Note: Writes flex-props html edit/view code to Response object Usage: listKenmerk must be called once with an SQL-statement that fetches all kenmerk-information The structure of tha SQL should match the predefined structure (column names) TODO: HTML5-achtige zaken toevoegen - required is ook een attribute met functionaliteit. Tot dusverre zetten we alleen reuired_class moeten we behalve adt attr toevoegen ook iets met toggle en zo? FlexFiles.inc functie bepaalNiveau is altijd nodig dus FlexFiles.inc erbij */ %> <% // "jquery-ui.js" en "date.js" zijn alleen nodig als er een datumkenmerk is. // meestal is die er toch al wel in het hoofdscherm dus voor het gemak doen // we het hier ook maar voor overige schermen. if (!this.JSON_Result) FCLTHeader.Requires({plugins:["jQuery", "kenmerk"], js: ["jquery-ui.js", "date.js"]}) var requiredGroupUsed = new Array(); // Array zorgt voor eenmalige initiele aanroep van checkRequiredGroup(groep) per groep function parseDocumentPath(kenmerk_val) { // kenmerk_val is een padnaam naar een document // Als het document begint met dan halen we // dat er af voordat het de database in gaat. // We maken van back-slashes (alleen) dan altijd forward slashes // Bij presenteren plakken we er mettertijd S("image_path_virtual") voor // de check S("image_path_local") != "\\" is nog historisch om problemen te voorkomen var localpath = S("image_path_local").replace(/\//g,"\\"); var newval = String(kenmerk_val).replace(/\//g,"\\"); __Log("newval: " + newval); if (S("image_path_local") != "\\" && newval.indexOf(localpath) == 0) return newval.substring(localpath.length); else if (S("image_path_local_regexp") && newval.match(S("image_path_local_regexp"))) { __Log("regexp match!"); return newval.substring(RegExp.lastIndex); } else return kenmerk_val; // Origineel ongewijzigd } function kenmerk_write(s) { Response.Write(s); } // Tel/ zoek de bijlagen in een folder // Resultaat: array met bijlage namen function BijlagenList(pModule, pNiveau, pKey, pKenmerk_key, otherKenmerk_path) { if (otherKenmerk_path) var vAttachPath = S("flexFilesPath") + "/" + otherKenmerk_path + "/"; else { if (pKey > 0) // anders valt er niets te tellen var vAttachPath = flexProps(pModule, pKey, String(pKenmerk_key), pNiveau).AttachPath + "/"; } var lijst = []; var fso = Server.CreateObject("Scripting.FileSystemObject") if (vAttachPath) __Log("Tellen in folder: " + vAttachPath); if (vAttachPath && fso.FolderExists(vAttachPath)) { var fso, f, f1, fc, s; fso = new ActiveXObject("Scripting.FileSystemObject"); f = fso.GetFolder(vAttachPath); fc = new Enumerator(f.files); for (; !fc.atEnd(); fc.moveNext()) { lijst.push(fc.item().Name); } } return lijst; } function BijlagenButton(pModule, pNiveau, pKey, tmpfolder, pKenmerk_key, pReadonly, pRequired, kdim, pregexp, otherKenmerk_path, identify, label, params) { // Lever code op voor een BijlagenButton type M (map) // Let op: F (file) gebeurt verderop in de code // Module is 'R' voor ruimte, 'M' voor melding enz // key is de object key // Parameter otherKenmerk_path is null of bevat het pad van het kenmerk waarvan we // in een veel later stadium (SaveFlexKenmerken) de folder kopieren (order onder melding) // of moven (wijzigen type stdmelding of type opdracht) // Als die is meegegeven en er zitten bestanden in de folder dan wordt de knop // vooralsnog read-only /* Bestanden zijn nu te vinden in ...cust/X/flexfiles/[module]/[key]/[kenmerk_key] */ var lijst = BijlagenList(pModule, pNiveau, pKey, pKenmerk_key, otherKenmerk_path); if (pReadonly) { // Indien readonly en lijst.length = 0 dan hoeft het kenmerk (net als bij andere kenmerken) helemaal niet getoond te worden. var filehtmlarr = []; for (var file in lijst) { if (kdim == 'xxx') var href = protectQS.create(OpenFlexFile(pModule, pNiveau, pKey, pKenmerk_key, lijst[file], { mime_type: "image/png", contentdp: "inline" })); else var href = protectQS.create(OpenFlexFile(pModule, pNiveau, pKey, pKenmerk_key, lijst[file])); //var html = "" + safe.html(lijst[file]) + ""; var html = '' + safe.html(lijst[file]) + ''; filehtmlarr.push(html); } var res = filehtmlarr.join("
");; } else { if (otherKenmerk_path && lijst.length > 0) var res = L("lcl_flex_autocopy"); else // pf: op 1 regel tbv mijn syntaxhiliting { var res ="" +" " +" " +"" +"" +"" +"" +"" +"" +"" +"" +""; return ret_str; } function getDatatypeValue(table, column, checkval) { var tsql = "SELECT data_type" + ", data_length" + ", data_precision" + ", data_scale" + " FROM user_tab_columns" + " WHERE table_name = " + safe.quoted_sql_upper(table) + " AND column_name = " + safe.quoted_sql_upper(column); var oRs_t = Oracle.Execute(tsql); if (oRs_t("data_type").value == "NUMBER") { if (!oRs_t("data_scale").value || oRs_t("data_scale").value > 0) suggestval = parseFloat(checkval) || 0; else suggestval = parseInt(checkval) || 0; } else if (oRs_t("data_type").value == "VARCHAR2") { suggestval = safe.quoted_sql(checkval); } else { suggestval = safe.quoted_sql(checkval); } oRs_t.close(); return suggestval; } // ================================================================================================ // listKenmerk // Genereer code voor flexkenmerken // // Genereer code voor flexkenmerken. Vrij kale code // lbl1:flex1lbl2:flex2 en dat dan herhaald // (Alleen!) voor bewerkbare velden voegen we ook name's toe die met het formulier gesubmit worden // params: sql: moet een query met de goede :-) velden bevatten // sinds kort worden deze By Name gebruikt ipv By volgorde // module, key: alleen gebruikt voor flexkenmerk 'F' (file) 'E' (encrypted file) en 'M' (map) // props { fnIsInvisible: optioneel function (volgnr, type) - true betekent onzichtbaar // fnIsReadonly: optioneel function (volgnr) - true betekent readonly // parentKey: optioneel om flexkenmerken onder op te slaan // kenmerk_module: optioneel bij ALG: "L", "G", "R" etc. // multiMode // hideVervallen: om alleen nu nog geldige waarden te tonen // defaults { bsn: "12345678", plaats: "Enschede", postcode:"1234AB" } altijd lowercase namen // prs_key (of obsolete reqId) - key om bij defaultwaarde in ##PRS_PERSLID_KEY## te substitueren // fnpre en fnpost: functies die voor en na genereren worden aangroepen *mits er kenmerken zijn* // wfbuilder: toon ook flex-colname :f123 (voor workflow expression builder) // } // ================================================================================================ function listKenmerk(sql, module, key, props) { var flexcolumns = props.flexcolumns; var kenmerk_search = props.kenmerk_search; var kenmerk_colspan = props.kenmerk_colspan; var kenmerk_extraTD = props.kenmerk_extraTD; var multiMode = props.multiMode; // TODO: support this! var hideVervallen = props.hideVervallen; var prs_key = props.prs_key || props.reqId; // Oude obsolete reqId nog even ondersteunen var cont_key = props.cont_key; var nameprefix = props.nameprefix || "k"; var extraserie = props.extraserie || false; var niveau = props.niveau || ""; var srtdeel_key = props.srtdeelKey; var requiredbyfield = props.requiredbyfield; var serie = props.serie || 0; var parent_list = props.parent_list; // Maak voor deze keys ook bijlagen knop var formobile = props.mobile; var notr = props.notr; // Geen tr's toevoegen. var nolabel = props.nolabel; // Geen labels toevoegen. var flexstart = props.flexstart || 1; // De kenmerken vanaf de flexstart-ste element tonen {flexstart >= 1 indien meegegeven). var flexend = props.flexend || -1; // De kenmerken tot het flexend-ste element tonen {flexend >= 1 indien meegegeven}. var hasfilter = props.hasfilter || false; // De kenmerken kunnen op naam gefilterd worden. var tmpfolder = props.tmpfolder || ""; var predone = false; var colCount = 0; // Even/oneven zodat we weten of we links of rechts zitten var forceNewLine = false; // Bij labels en grote text velden var val_seperator = ''; var val_label = ''; var idCounter = 1; // We maken alleen name/id-s voor de velden die ook echt bewerkt kunnen worden var clabelCounter = 0; // Het aantal collapsable labels var anyDate = false; var anyTextarea = false; var kenmerkidref = new Array(); // Bijhouden welk kenmerk welke id referentie mee heeft gekregen var dpYearRanges = []; // te gebruiker jaren voor datepicker vastleggen. var allCollapsable = false; // true bij eerste 'l'-label var inMobileBlock = false; // true van begin mobile-collapse-content tot eind mobile-collapse-content var kenmerk_2col = (flexcolumns >= 2); // 2 kolommnen voor flexkenmerken als aantal kolommen ingevuld 2 of meer is. if (module == "INS" && niveau == "S") { // Sleutelmodule werkt met srtdeel_key if (srtdeel_key > 0) key = srtdeel_key; } // Zitten er expressie kenmerken tussen? var flexExprIncluded = false; var oRs = Oracle.Execute(sql); while (!oRs.eof) { var kdefault = oRs("kenmerk_default").Value; if (kdefault && kdefault.match('##EXPR##') != null) { flexExprIncluded = true; break; } oRs.MoveNext(); } oRs.Close(); // Opnieuw dezelfde query is niet supperefficient maar een MoveFirst is problematisch (FSN#39008) var oRs = Oracle.Execute(sql); // ============================================================================================ // Doorloop alle flexkenmerken if (key < 0 && tmpfolder == "") tmpfolder = shared.random(32); // voor als nog geen key en wel bijlagen var prssql = false; for (i = 1; !oRs.eof; i++) { var val = null; val_seperator = ':'; var def_val = oRs("kenmerk_default").Value; var isExpression = false; if (!kenmerk_search && !multiMode) { // In multiMode no filling of default values val = oRs("kenmerk_waarde").value; if (def_val && def_val.match('##EXPR##') != null) isExpression = true; // For a new value, this default is used. It could be a primitive value (string, number or key) or // it is suggested to support (later) // a more sophisticated value, using ##asp-variable## and/or SQL:SELECT in the string. if (val != null) { //__Log("val:"+val); if (val == def_val && val.match('##SQL##') != null) { //__Log("val match"); prssql = true; val = val.substr(val.indexOf('##SQL##') + 7); var sql2 = val.replace("##PRS_PERSLID_KEY##", prs_key).replace("##PRS_CONTACTPERSOON_KEY##", cont_key); oRsPerslid = Oracle.Execute(sql2); if (!oRsPerslid.eof) val = oRsPerslid(0).value; else val = ''; oRsPerslid.Close(); } else if (def_val && val == def_val && def_val.match('##EXPR##') != null) { val = ""; } } } // Meegegeven default verwerken (UWVA Pacta o.a.) if (props.defaults && oRs("kenmerk_omschrijving").value) { var xx = props.defaults[oRs("kenmerk_omschrijving").value.toLowerCase()]; if (typeof xx != "undefined") { val = xx; if (oRs("kenmerk_kenmerktype").value == "C" || oRs("kenmerk_kenmerktype").value == "N" || oRs("kenmerk_kenmerktype").value == "B") val = val.substr(0, oRs("kenmerk_lengte").value); // Kap de waarde op de maximale lengte af } } // De weer te geven waarde is nu bepaald var kkey = oRs("kenmerk_key").value; val_label = Server.HTMLEncode(oRs("kenmerk_omschrijving").value? oRs("kenmerk_omschrijving").value : ""); // Omschrijving kan leeg gelaten zijn var ktype = oRs("kenmerk_kenmerktype").value; var klen = oRs("kenmerk_lengte").value; if (!klen) klen = 4000; var kdec = oRs("kenmerk_dec").value; var kmin = oRs("kenmerk_nmin").value; var kmax = oRs("kenmerk_nmax").value; var kvolgnr = "" + oRs("kenmerk_volgnr").value; var kdim = oRs("kenmerk_dimensie").value; // beperkt bij uploads de extensie var hint = oRs("kenmerk_hint").value; var kregexp = oRs("kenmerk_regexp").value; var kdomein_key = oRs("kenmerkdomein_key").value; // if (hint == null) hint = ""; // PF vindt van niet if (def_val == null) def_val = " "; var required = oRs("kenmerk_verplicht").value; if ((props.sqldefaultnotrequired && def_val && def_val.match('##SQL##')) || props.ignorerequired) required = false; var reqgroup = oRs("kenmerk_groep").value; var otherPath = oRs("otherpath").value; // otherKenmerkPath, alleen voor meldingen en facturen (tbv kopieren) // // forceReadonly kan gezet zijn: dan is het veld *altijd* readonly en kan alleen // ingevuld raken doordat een extern proces (importjob?) dat doet of het wordt // gevuld door de default waarde. var forceReadonly = oRs("kenmerk_toonbaar").value == 1; // Velden die de gebruiker niet mag zien zijn we héél snel klaar mee // Ook velden waar je niet op kunt zoeken slaan we direct over in zoekmode // En labels met een readonly-kenmerk tonen we niet als readonly, om invulinstructies in showmode weg te laten if ((!kenmerk_search && props.fnIsInvisible && props.fnIsInvisible(kvolgnr, ktype, oRs)) || (kenmerk_search && (ktype == 'L' || ktype == 'l' || ktype == 'Q' || ktype == 'M' || ktype == 'F' || ktype == 'E') || kvolgnr < 0) || (!kenmerk_search && (ktype == 'L' || ktype == 'l') && forceReadonly && props.fnIsReadonly && props.fnIsReadonly(kvolgnr, oRs)) ) { oRs.MoveNext(); continue; // Onzichtbaar } //kenmerk_write( ""); //kenmerk_write( ""); var readonlyfield = forceReadonly; // startwaarde if (!readonlyfield && !kenmerk_search && props.fnIsReadonly) // Zoeken is natuurlijk nooit readonly readonlyfield = props.fnIsReadonly(kvolgnr, oRs) if (readonlyfield || kenmerk_search) required = false; var required_class = ""; var required_group = ""; if (required) { required_class = " required"; // Indien required afhankelijk is van een gewoon veld dan requiredgroup gebruiken met groep >= 10 if (requiredbyfield && required == 1) { required = 10; } if (required > 1) { if (required == 2) required_group = reqgroup + "S" + parseInt(serie, 10); else required_group = required + "S" + parseInt(serie, 10); required_class += required_group; if (!requiredGroupUsed[required_group]) // Array requiredGroupUsed[] zorgt voor eenmalige initiele aanroep van checkRequiredGroup(groep) per groep { requiredGroupUsed[required_group] = true; %> <% } } } // Als een parent kenmerk niet toonbaar is (vinkje "Niet te wijzigen" is gezet) en een lege waarde heeft, // dan moet het parent kenmerk toch getoond worden i.v.m. de afhankelijkheid. // en het child kenmerk is toonbaar (vinkje "Niet te wijzigen" is niet gezet) // Afhankelijke child-parent kenmerken kunnen niet beide "niet toonbaar" zijn. // Dan heeft de afhankelijkheid ook geen zin. Dus daarop ga ik niet controleren. Dat is een configuratie fout. // Alleen controle of parent niet toonbaar is bij een toonbare child. var isParent = false; if (kdomein_key) { sqlP = "SELECT ut2.fac_usrtab_parentkey" + " FROM fac_kenmerkdomein kd1" + " , fac_usrtab ut1" + " , fac_usrtab ut2" + " WHERE kd1.fac_usrtab_key = ut1.fac_usrtab_key" + " AND ut1.fac_usrtab_key = ut2.fac_usrtab_parentkey" // Kenmerk 1 is een parent van een ander kenmerk 2. + " AND kd1.fac_kenmerkdomein_key = " + kdomein_key; var oRs2 = Oracle.Execute(sqlP); if (!oRs2.eof) { isParent = true; // Er is minstens 1 child kenmerk. // In zoekscherm hoeft de parent dan ook niet readonly te zijn. Je mag er mee zoeken if (kenmerk_search) readonlyfield = false; } oRs2.close(); } // In het geval van readonly laten we velden zonder waarde helemaal niet zien, // met uitzondering van Labels. // Parent kenmerken laten we altijd zien. // PF vraagt zich af: heeft dit ook gevolg voor print en excel? // En: voor type M is het altijd nu nog leeg, en die komen dus readonly nooit! // Voorlopig laat ik die dan altijd maar zien (TODO: evt niet als er 0 bestanden zijn) if (readonlyfield && !isParent && ktype != 'L' && ktype != 'l' && ktype != 'M' && (!val || val=="") && (!kenmerk_search && (ktype == 'C' || ktype == 'N' || ktype == 'B' || ktype == 'D' || ktype == 'R' || ktype == 'S')) ) // Als geavanceerd dan maakt het niet uit of het readonly is. Dan moet je het kenmerk gewoon tonen. { oRs.MoveNext(); continue; } // Als geavanceerd dan maakt het niet uit of het readonly is. Dan moet je het kenmerk gewoon tonen. if (kenmerk_search && readonlyfield && (ktype == 'C' || ktype == 'N' || ktype == 'B' || ktype == 'D' || ktype == 'R' || ktype == 'S')) readonlyfield = false; colCount++; // Nu pas ophogen. // De kenmerken vanaf de flexstart-ste element tonen. // De kenmerken tot het flexend-ste element tonen. if (flexstart > colCount || (flexend >= 0 && flexend < colCount)) { oRs.MoveNext(); idCounter++; continue; } if( ktype == 'L' || ktype == 'l' ) { forceNewLine = true; colCount = 2; // Forceer 'even' } else forceNewLine = false; if (kenmerk_search || val && val!="") allCollapsable = false; // Eerst de simpele datatypes ('C', 'D' en 'N'). De complexere overrulen kv mogelijk later nog wel. // De classes-conventie is: // fldflex+[ktype] voor edit/show en fldSflex+[ktype] voor searchmode // waarbij type niet perse hoeft als er geen onderscheid is. // Extra is er nog C50 ipv C voor lange C kenmerken // Ook class number/float (of currency) toevoegen var kv = ""; // Het in te voegen veld in HTML, zonder label var onchangeExp = ""; // Een flexkenmerk wordt altijd weergegeven volgens het volgende format: // : // Eventueel met 2 kolommen in een rij. // Er zijn 2 uitzonderingen: // - een lange tekst wordt een textarea // - een R wordt een select // We doen eerst die uitzonderingen // KENMERKTYPE C (Karakter) ================================================================= if (ktype == 'C') { if (flexExprIncluded && !isExpression) onchangeExp = ";if (fvalid) calculateFlexExpressions(this" + ", \"" + module + "\"" + ", " + key + ", \"" + (props.kenmerk_module || "") + "\"" + ", \"" + nameprefix + "\"" + ", \"" + extraserie + "\"" + ");"; if (klen > 50 && !kenmerk_search) { // Groot text veld wordt automatisch textarea if (readonlyfield) { if (formobile) { kv = ""; } else { kv = "
" + safe.html(val) + "
"; } } else { anyTextarea = true; // straks autogrow code kv = ""; } } else { // klein input veld if (readonlyfield) { if (formobile) { kv = ""; } else { kv = "" + safe.htmlattr(val) + ""; } } else { kv = ""; } } } // C // Bijhouden welk kenmerk welke id referentie mee heeft gekregen function idref(idname, waarde) { this.idname = idname; this.waarde = waarde; } // Bijhouden van kenmerken. Later kan blijken dat ze parent kenmerken zijn. // Kenmerkkey alleen is niet uniek bij meerdere bezoekers of factuurregels. // Daarom nameprefix meenemen want die is per bezoeker of factuurregel wel uniek. kenmerkidref[nameprefix + kkey] = new idref(nameprefix + idCounter, val); var parentkenmerkid = ""; var parentkenmerk_key = -1; var parentkenmerkwaarde; if (!readonlyfield && (ktype == 'S' || ktype == 'R')) { // Aannames die tot nu toe zijn gemaakt: // 1) Een kenmerk kan alleen afhankelijk zijn van een kenmerk van hetzelfde type. // M.a.w. een suggest box kan nu nog alleen afhankelijk zijn van een andere suggestbox (idem geldt voor listbox). // Als een suggestbox namelijk dezelfde kenmerkdomein gebruikt als een listbox en ze worden beide gelijktijdig gebruikt geeft dat anders problemen. // 2) Afhankelijke suggestboxen met hetzelfde kenmerkdomein mogen niet voorkomen. Anders kun je niet de juiste afhankelijke suggestbox bepalen. // Idem geldt dit voor listboxen. // 3) Als een kenmerk afhankelijk is van een ander kenmerk dan moet de afhankelijke kenmerk een hoger volgnummer hebben (later worden getoond) // dan het kenmerk waarvan het afhankelijk is. // 4) Afhankelijkheid van kenmerken werkt alleen voor eigen tabellen (fac_usrtab, fac_usrdata) // Is er een afhankelijkheid met een ander kenmerk (met een lager volgnummer)? var sqlDep = "SELECT tfin.kenmerk_key" + " FROM fac_usrtab ut1" + " , fac_usrtab ut2" + " , fac_kenmerkdomein kd1" + " , fac_kenmerkdomein kd2" + " , (" + sql + ") tfin" + " WHERE kd1.fac_kenmerkdomein_key = " + kdomein_key + " AND kd1.fac_usrtab_key = ut1.fac_usrtab_key" + " AND ut1.fac_usrtab_parentkey = ut2.fac_usrtab_key" + " AND ut2.fac_usrtab_key = kd2.fac_usrtab_key" + " AND kd2.fac_kenmerkdomein_key = tfin.kenmerkdomein_key" + " AND tfin.kenmerk_kenmerktype = " + safe.quoted_sql(ktype) var oRs2 = Oracle.Execute(sqlDep); if (!oRs2.eof) { // Er is een afhankelijkheid met een ander kenmerk parentkenmerk_key = oRs2("kenmerk_key").value; parentkenmerkid = kenmerkidref[nameprefix + parentkenmerk_key].idname; parentkenmerkwaarde = kenmerkidref[nameprefix + parentkenmerk_key].waarde; } oRs2.close(); } // KENMERKTYPE R/S (Referentie/Suggest) ===================================================== if (ktype == 'R' || (readonlyfield && ktype == 'S')) // Referentie naar andere tabel (listboxje) { var wheres = []; var dsql = "SELECT fac_kenmerkdomein_objectnaam" + ", fac_kenmerkdomein_kolomnaam" + ", fac_kenmerkdomein_kolomtxt" + ", fac_kenmerkdomein_xmlnode" + ", fac_kenmerkdomein_verval" + ", fac_usrtab_key" + " FROM fac_kenmerkdomein" + " WHERE fac_kenmerkdomein_key = " + kdomein_key; var oRs_d = Oracle.Execute(dsql); var xmlnode = oRs_d("fac_kenmerkdomein_xmlnode").value; var vervalkolom = oRs_d("fac_kenmerkdomein_verval").value; if (!readonlyfield && parentkenmerkid != "") { if (parentkenmerkwaarde != null) wheres.push("fac_usrdata_parentkey = " + parentkenmerkwaarde); else // Parent heeft geen waarde geselecteerd. wheres.push("fac_usrdata_parentkey IS NOT NULL"); } if (val !== null && String(oRs_d("fac_kenmerkdomein_kolomnaam").value).match(/\_key$/i)) { var vv = parseInt(val, 10); if (isNaN(vv)) { // Kan gebeuren als van een text-kenmerk *achteraf* een referentiekenmerk wordt gemaakt // Ook: als je bij een referentie kenmerk een foutieve default-waarde (textueel) invult __DoLog("Ongeldige referentie waarde {0} voor kolom {1}.{2}".format(val, oRs_d("fac_kenmerkdomein_objectnaam").value, oRs_d("fac_kenmerkdomein_kolomnaam").value), "#ff0000"); val = "-1"; } else val = String(vv); } if (oRs_d("fac_kenmerkdomein_objectnaam").value == "FAC_USRDATA" && oRs_d("fac_usrtab_key").value) { // Deze kunnen we standaard localisen! var fsql = "SELECT fac_usrdata_key, " + lcl.xsql('fac_usrdata_omschr', 'fac_usrdata_key') + " || CASE WHEN fac_usrdata_vervaldatum < SYSDATE THEN " + safe.quoted_sql(L("lcl_inactive_data_suffix")) + " END" + " fac_usrdata_omschr" + ", fac_usrdata_vervaldatum" + " FROM fac_usrdata "; wheres.push("fac_usrtab_key=" + oRs_d("fac_usrtab_key").value); if (!readonlyfield) wheres.push("fac_usrdata_verwijder IS NULL"); // bij readonly tonen we ook verwijderde oude waarden if (hideVervallen) wheres.push("(fac_usrdata_vervaldatum IS NULL OR fac_usrdata_vervaldatum > SYSDATE)"); } else { var fsql = "SELECT " + oRs_d("fac_kenmerkdomein_kolomnaam").value + "," + oRs_d("fac_kenmerkdomein_kolomtxt").value + (vervalkolom ? " || CASE WHEN " + vervalkolom + " < SYSDATE THEN " + safe.quoted_sql(L("lcl_inactive_data_suffix")) + " END" : "" ) + " fac_kenmerkdomein_omschr" + "," + (vervalkolom ? vervalkolom : "NULL" ) + " x" + " FROM " + oRs_d("fac_kenmerkdomein_objectnaam").value; if ((!readonlyfield || hideVervallen) && vervalkolom) wheres.push("("+vervalkolom+" IS NULL OR "+vervalkolom+" > SYSDATE)"); } if (readonlyfield) wheres.push(oRs_d("fac_kenmerkdomein_kolomnaam").value + " = " + safe.quoted_sql(val)); if (wheres.length) fsql += " WHERE " + wheres.join(" AND "); fsql += (oRs_d("fac_kenmerkdomein_objectnaam").value == "FAC_USRDATA") ? " ORDER BY fac_usrdata_volgnr, 2" : " ORDER BY 2, 1"; oRs_d.close(); var oRs2 = Oracle.Execute(fsql); var c0 = ""; var c1 = ""; var inactiveval = false; if (!oRs2.eof) { c0 = oRs2(0); // for performance this is better, it seems (-JGL). c1 = oRs2(1); inactiveval = (oRs2(2).value != null && oRs2(2).value maxLen) maxLen = String(c1.value).length; appender = ''; builder[builder.length] = appender; } oRs2.MoveNext(); } if (kvv == '') kvv += builder.join(' '); if (kvv == '') kvv = ' '; // Zodat readonly/print in ieder geval het label getoond wordt. oRs2.close(); if (!readonlyfield) { // is dus impliciet ook type R if (flexExprIncluded && !isExpression) onchangeExp = "calculateFlexExpressions(this" + ", \"" + module + "\"" + ", " + key + ", \"" + (props.kenmerk_module || "") + "\"" + ", \"" + nameprefix + "\"" + ", \"" + extraserie + "\"" + ");"; kv = ""; if (required) // wrapper voor rode streepje, IE-only. Wat vind je Jos (ik vind het te lelijk in chrome/safari) kv = "" + kv + ""; } else { var showdetail = (formobile ? "" : (xmlnode? ' details' : '') ); var clickdetail = (formobile ? "" : (xmlnode? ' onClick="xmlNodeDetails(' + val + ', \'' + xmlnode + '\')"' : '') ); if (ktype == "R") kv = ''; else kv = ''; } if (!readonlyfield && parentkenmerkid != "") { %> <% } } // KENMERKTYPE F/E (File) =================================================================== var MasF = false; // M behandelen als F? if ((ktype == 'F' || ktype == 'E' || ktype == 'M') && formobile) { var lijst = BijlagenList(module, niveau, key, kkey, otherPath); // die hebben we dan nodig } if (ktype == 'M' && formobile && !lijst.length) MasF = true; // Een M zonder files doen we als F zodat je tenminste één betand kunt toevoegen if (ktype == 'F' || ktype == 'E' || MasF) // single File of Encrypted { if (formobile && lijst.length) readonlyfield = true; // Bedoeling is: toon de filenaam in een inputfield. // In showmode/readonly kun je er op klikken als-ie bestaat, in editmode // moet je de change button gebruiken om te wijzigen en is niet klikbaar. // De echte waarde bewaren we in een hidden veld. Die wordt dan ook gesubmit var fld = nameprefix + idCounter + "val"; // Er is redundantie: de bestandsnaam zit in de database en staat in de folder // door bijvoorbeeld niet op Ok te drukken na vervanging van het bestand // kan er inconstistentie ontstaan. Lastig tegen te gaan dus maar detecteren en melden. var missing = false; if (val && ktype != 'M') { var fso = new ActiveXObject("Scripting.FileSystemObject"); if (otherPath) var vAttachPath = S("flexFilesPath") + "/" + otherPath; else { // JGL: Zou dit niet moeten/ kunnen via bijvoorbeeld iets als flexProps(module, key, String(kkey), niveau).AttachPath + "/"; var vAttachPath = S("flexFilesPath") + "/" + module + "/" + subfolderKey(bepaalNiveau(module, niveau), key) + "/" + kkey; } missing = !fso.FileExists(vAttachPath + "/" + val); if (missing) __Log(vAttachPath + "/" + val + " is missing"); } // Mobile heeft een compleet eigen BijlagenForm.asp if (kdim == 'xxx') var url = "../shared/BijlagenSignature.asp" else if (formobile) var url = "../pda/BijlagenForm.asp" else var url = "../shared/BijlagenForm.asp" url += "?module=" + module + "&key=" + key + (niveau != ""? "&niveau=" + niveau : "") + "&kenmerk_key=" + kkey + "&mobile=" + (formobile ? 1 : 0) + (props.kenmerk_module? "&kenmerk_module=" + props.kenmerk_module : ""); // nooit if (pReadonly) url += "&reado=1"; // nooit url += "&multi=1"; if (kdim) url += "&extFilter=" + escape(kdim); if (kregexp) url += "&pregexp=" + escape(kregexp); // P800x600 voor foto van 800x600 if (ktype == "E") url += "&encrypt=1"; if (key < 0) url += "&tmpfolder=" + tmpfolder; var saveUrl = ""; if (props.parentKey > 0 && ktype != 'M') { // Voor de zekerheid slaan we wijziging van de bestandsnaam direct op. // op het filesysteem is het namelijk ook al 'gecommit' var saveUrl="../shared/AjaxSaveFlex.asp"; if (module=="MLD" && niveau == "O") saveUrl += "?module=OPDR"; else if (module=="FIN" && niveau == "R") saveUrl += "?module=FINR"; else saveUrl += "?module="+module; saveUrl += "&parentKey="+props.parentKey; saveUrl += "&kenmerkKey=" + kkey; if (props.kenmerk_module) saveUrl += "&kenmerk_module="+props.kenmerk_module; }; var func = "onBijlagen"; if (formobile) func = "onBijlagenMobile"; var blg = func + "('" + safe.jsstring(protectQS.create(url)) + "'" + ",'" + (saveUrl?safe.jsstring(protectQS.create(saveUrl)):"") + "'" + ", false" + ", $('#" + fld + "')[0]" + ")"; if (!readonlyfield || val) { kv = " 1 ? " onChange='checkRequiredGroup(\"" + required_group + "\")'" : "") //+ " placeholder='"+val_label+"'" + " value='" + safe.htmlattr(val) + "' " + (!val?" style=display:none":""); // + ">"; //komt later var kvClick=""; if (otherPath) // Even niet klikbaar kvClick = " title='" + L("lcl_flex_autocopy") +"' "; else if (readonlyfield && val && !missing) // rechtstreeks openen { if (kdim == 'xxx') var fnclick = "parent.window.open('" + protectQS.create(OpenFlexFile(module, niveau, key, kkey, val, { mime_type: "image/png", contentdp: "inline" })) + "')"; else var fnclick = "parent.window.open('" + protectQS.create(OpenFlexFile(module, niveau, key, kkey, val)) + "')"; kvClick = " onclick='" + safe.htmlattr(fnclick) + "'"; } else if (readonlyfield && val && missing) // Waarschuwen kvClick = " title='" + safe.htmlattr(L("lcl_flex_filenotfoundRO")) + "'"; else { kvClick = " onClick='" + safe.htmlattr(blg) + "'"; // klik altijd naar bijlagenform if (missing) { kvClick += " title='" + safe.htmlattr(L("lcl_flex_filenotfound")) + "'"; } else kvClick += " title='" + L("lcl_change") + "'"; } // Om te saven doet de gebruiker maar rightclick/Saveas kv += kvClick + ">"; // hier tag afsluiten } if (!readonlyfield && !otherPath) // Altijd aanwezig { kv += ""; } if (kdim == 'xxx') { if (!missing && val) kv += ""; else kv += ""; } } // KENMERKTYPE M (Map) ====================================================================== // Mobiel hebben we hem al bij 'F' gedaan if (ktype == 'M' && !MasF) // Map met bestanden is altijd heel simpel { var requiredfield = (required ? required_class : ""); var identify = " id='" + nameprefix + idCounter + "val' name='" + nameprefix + idCounter + "val'"; var res = BijlagenButton(module, niveau, key, tmpfolder, kkey, readonlyfield || formobile, // Mobile altijd readonly requiredfield, kdim, kregexp, otherPath, identify, L("lcl_appendixes_teller"), props) kv = res.html; if (res.count > 0) allCollapsable = false; if (parent_list) { for (pp in parent_list) { // JGL: parent_list is alleen bij workflowmeldingen in *show*mode. // Meeste parameters hieronder zullen dan ook don't care zijn var res = BijlagenButton(parent_list[pp].module, niveau, parent_list[pp].key, tmpfolder, kkey, readonlyfield, requiredfield, kdim, kregexp, otherPath, identify, parent_list[pp].label, props) if (res.count > 0) { allCollapsable = false; kv = res.html + "
" + kv; // parent komt ervoor } } } } var makeCheckbox = false; if ((ktype == 'N' || ktype == 'B') && klen == 1 && kmin == 0 && kmax == 1 && (kdec == 0 || !kdec)) { makeCheckbox = true; if (formobile) // Daar staat de tekst achter het vinkje val_seperator = ''; } // =========================================================================== // De uitzonderingen hebben we nu gehad, alle overige types beginnen hetzelfde // =========================================================================== // JGL: Wat zijn de overige types nog van CNDRSXFEMLlQB ? // Volgens mij NDXLlQB waarbij L en l nog overruled worden. if (kv == "" && ktype != "M" && ktype != "F" && ktype != "E" && !makeCheckbox) { // Ook lege folders met bestanden en een enkele bestandsnaam krijgen we via de query mee. Maar deze niet tonen. // Ooit meer HTML-types toepassen (number, float) if (flexExprIncluded && (ktype == "N" || ktype == "D" || ktype == "S") && !isExpression) onchangeExp = ";if (fvalid) calculateFlexExpressions(this" + ", \"" + module + "\"" + ", " + key + ", \"" + (props.kenmerk_module || "") + "\"" + ", \"" + nameprefix + "\"" + ", \"" + extraserie + "\"" + ");"; kv = ""; } else { kv = "" + (val == 1? L("lcl_check_1") : L("lcl_check_0")) + ""; } } else kv = "" + ""; } else kv += " class='" + (kenmerk_search ? "fldSflexN " : "fldflexN ") + (required ? required_class : "") + (kdec > 0 ? " float " : " number ") + (isExpression? " expression " : "") + "'" + (required ? " required='required' " : "") + (isExpression ? " readonly " : "") //+ " placeholder='"+val_label+"'" + " value='" + (kdec > 0 && val? safe.displayfloat(parseFloat(val), kdec) : safe.html(val)) + "'" + " maxlength='" + ((kmin >= 0? 0 : 1) + (kdec > 0? 1 : 0) + klen) + "'" + ">"; } // KENMERKTYPE D (Date) ================================================================= if (ktype == 'D') { kv += " class='" + (kenmerk_search ? "fldSflexD " : "fldflexD ") + (required ? required_class : "") + (isExpression? " expression " : "") + "'" + (required ? " required='required' " : "") + (isExpression? " readonly " : "") + " value='" + safe.htmlattr(val) + "'" + ">"; if (!readonlyfield && !isExpression) kv += ""; // Als er voor een datumveld geen kmin en kmax is ingevuld dan is de yearRange default -10 tot +10 jaar vanaf geselecteerd jaar. // Is een van beiden ingevuld dan wordt de andere op 10 jaar vanaf geselecteerde jaar gezet (deze verschuift met selectie). // Een opgegeven waarde is het aantal jaren voor of na het huidige jaar (waarde < 1000), of een jaartal (waarde > 1000). if (kmin || kmax) { range_val = (kmin ? ((Math.abs(kmin)<1000) ? "c"+(kmin>0?"+"+kmin:kmin) : Math.abs(kmin)) : "c-10") + ":" + (kmax ? ((Math.abs(kmax)<1000) ? "c"+(kmax>0?"+"+kmax:kmax) : Math.abs(kmax)) : "c+10"); field_id = nameprefix + idCounter + "val"; dpYearRanges.push({id: field_id, range: range_val}); } anyDate |= !readonlyfield; } // KENMERKTYPE X (Bestandsnaam/url) ========================================================= if (ktype == 'X') { if (S("flex_X_is_URL")==0) var viewpath = S("image_path_virtual") + val; else var viewpath = val; if (readonlyfield) // Je mag er wel op klikken if (val) kv = ''; else kv = ""; else if (val) // Tekstveld met 'view' button er achter plakken kv += " class='fldflexX" + (required ? required_class : "") + "'" + " value='" + safe.htmlattr(val) + "'" + (required ? " required='required' " : "") + ">"; else if (!kenmerk_search) // !val // Browse button for new er achter plakken kv = " 1 ? " onChange='checkRequiredGroup(\"" + required_group + "\")'" : "") + " type='" + (S("flex_X_is_URL") == 0 ? 'file' : 'text') + "' " + ((S("flex_X_is_URL")==0) && kregexp ? " regexp='" + kregexp + "' " : "") + "name='" + nameprefix + idCounter + "val' " + "value='" + safe.htmlattr(val) + "'" + ">"; else kv += ">"; } // KENMERKTYPE S (Suggest) ================================================================== // readonlyfield is bij "R" al meegenomen if (ktype == 'S' && !readonlyfield) // Referentie naar andere tabel (suggest box) { // Huidige waarde opzoeken var dsql = "SELECT fac_kenmerkdomein_objectnaam " + ", fac_kenmerkdomein_kolomnaam " + ", fac_kenmerkdomein_kolomtxt " + ", fac_usrtab_key " + "FROM fac_kenmerkdomein " + "WHERE fac_kenmerkdomein_key = " + kdomein_key; var oRs_d = Oracle.Execute(dsql); var suggestval = getDatatypeValue(oRs_d("fac_kenmerkdomein_objectnaam").value, oRs_d("fac_kenmerkdomein_kolomnaam").value, val); if (oRs_d("fac_kenmerkdomein_objectnaam").value == "FAC_USRDATA" && oRs_d("fac_usrtab_key").value) { var fsql = "SELECT fac_usrdata_key, " + lcl.xsql('fac_usrdata_omschr', 'fac_usrdata_key') + " || CASE WHEN fac_usrdata_vervaldatum < SYSDATE THEN " + safe.quoted_sql(L("lcl_inactive_data_suffix")) + " END" + " fac_usrdata_omschr" + ", fac_usrdata_vervaldatum" + " FROM fac_usrdata " + " WHERE " + oRs_d("fac_kenmerkdomein_kolomnaam").value + " = " + suggestval; fsql += " AND fac_usrtab_key = " + oRs_d("fac_usrtab_key").value + " AND fac_usrdata_verwijder IS NULL" } else { var fsql = "SELECT " + oRs_d("fac_kenmerkdomein_kolomnaam").value + "," + oRs_d("fac_kenmerkdomein_kolomtxt").value + ", NULL x" + " FROM " + oRs_d("fac_kenmerkdomein_objectnaam").value + " WHERE " + oRs_d("fac_kenmerkdomein_kolomnaam").value + " = " + suggestval; } oRs_d.close(); var oRs2 = Oracle.Execute(fsql); var currval = ""; //var inactiveval = false; if (!oRs2.eof) { currval = oRs2(1).value; //inactiveval = (oRs2(2).value != null); // zie opmerking hieronder } oRs2.close(); %> <% kv = " 1 ? " sgonChange='onChangeSKenmerk" + nameprefix + idCounter + "'" : "") + ">" + "" + ""; } // KENMERKTYPE L (Label) ==================================================================== if (ktype == 'L' || ktype == 'l') { // Label line allCollapsable = (ktype == 'l'); // opnieuw beginnen met zoeken inMobileBlock = (formobile && ktype == 'l'); // op dit moment zitten we in een mobile-collapse-content-block val_label = oRs("kenmerk_omschrijving").Value; // was: 1 clabelCounter++; val_seperator = ''; kv = def_val; // suggestie voor UWVA#20007: if required then collapsable } // ========================================================================================== // Alles bepaald, nu positioneren enzo // ========================================================================================== if (!predone && props.fnpre && (kv || (ktype == 'L' || ktype == 'l'))) { predone = true; props.fnpre(); } // KENMERKTYPE Q (spacer) =================================================================== // Alleen echt nuttig bij 2-koloms layout if (ktype == 'Q') { // PF: deze implementatie lijkt me discutabel; is forceNewLine niet beter? if (((colCount&1) || !kenmerk_2col) && !formobile && !notr) kenmerk_write(''); else if (!((colCount&1) && kenmerk_2col) && !formobile && !notr) kenmerk_write(''); oRs.MoveNext(); continue; // Teller is wel opgehoogd: volgende komt vanzelf op nieuwe regel } if (kv != '') { // Schrijf eventueel een tabelregel begin if (((colCount&1) || forceNewLine || !kenmerk_2col) && !formobile && !notr) kenmerk_write(''); // Nu altijd zichtbaar in popup dmodal scherm // Schrijf een tabelcell met het label if (makeCheckbox && formobile) // Zie commentaar iets verderop props.label_colspan = 2; if (props.wfbuilder) // Workflow Expression Builder kenmerk_write(":flex{0}".format(kkey)); if (!formobile && !nolabel) kenmerk_write(''); if (!nolabel) kenmerk_write((formobile && ktype == 'l'? '

' : '') + ''+(formobile && ktype == 'l' ? '

' : '')); // labelwaardes (vaak invulinstructie) in apart te stylen span if (formobile && (ktype == 'L' || ktype == 'l') && kv) { kv = '' + kv + ''; } // Bij mobile willen we de checkbox en zijn label in dezelfde ene TD hebben met colspan=2. // jQuery voegt ze namelijk samen tot een enkel interface element en dat past niet altijd // in de ene TD anders if ((!makeCheckbox || !formobile) && !formobile) { if (!nolabel) kenmerk_write(''); kenmerk_write(''); kenmerk_write(Operand(idCounter)); } else { if ( ktype == 'L' || ktype == 'l' ) if (typeof kenmerk_extraTD != "undefined" && kenmerk_extraTD) kenmerk_write(' colspan=4>'); // MLD_OPDR heeft TD-tje extra else kenmerk_write(' colspan=3>'); else kenmerk_write(">"); } if (nolabel) kenmerk_write(''); } // Schrijf vervolgens nu het echte veld kenmerk_write(kv); if (typeof kenmerk_extraTD != "undefined" && kenmerk_extraTD && !formobile) kenmerk_write('') // Extra leeg celletje voor layout MLD_OPDR if (val && forceReadonly && ktype != "M" && ktype != 'L' && ktype != 'l') { // hidden veld met de *echt* waardes zodat ze wel worden opgeslagen kenmerk_write("") } if ((kenmerk_search || !readonlyfield || (val && forceReadonly)) && ktype != "M" && ktype != 'L' && ktype != 'l') { // Alleen dan hidden name-velden er bij %> <% if (isExpression) { %> <% } %> <% } idCounter++; // Nu ophogen if (!formobile) { kenmerk_write(''); if (!((colCount&1) && kenmerk_2col) && !notr) kenmerk_write(''); } } oRs.MoveNext(); // Collapse code er achteraan als de *volgende* een ander label is if ((inMobileBlock || (!formobile && allCollapsable)) && (oRs.Eof || oRs("kenmerk_kenmerktype").value.toUpperCase() == 'L')) // einde huidige label { if (formobile) { kenmerk_write('
'); inMobileBlock = false; if (!allCollapsable) // the current collapseBlock should be expanded kenmerk_write(''); } else kenmerk_write(''); allCollapsable = false; } } oRs.close(); if (inMobileBlock || (!formobile && allCollapsable)) // allerlaatste ook nog { if (formobile) { kenmerk_write(''); if (!allCollapsable) // the current collapseBlock should be expanded kenmerk_write(''); } else kenmerk_write(''); } var counterName = (extraserie? nameprefix + "_all" : "k_all"); if (!formobile) { if (!notr) kenmerk_write(''); kenmerk_write(''); } if (key < 0) kenmerk_write(""); kenmerk_write(''); kenmerk_write(''); if (!formobile) { kenmerk_write(''); if (!notr) kenmerk_write(''); } if (predone && props.fnpost) props.fnpost(); // Eventuele scripts moeten buiten de if (anyTextarea && !kenmerk_search) { %><% } // Bij kenmerk_search doen de load_kenmerk's geen FCLTHeader.Generate en dus hebben // we date.js niet gegarandeerd. .fldSflexD werd echter hieronder toch al niet // meegenomen dus komen we er mee weg gewoon hier geen kalenders te doen if (anyDate && !kenmerk_search) { // FCLTHeader.Requires is hier te laat %><% } if (hasfilter) { %> <% } if (props.getTmpfolder) return tmpfolder; } // Ondersteunende filehandlingfuncties ============================================================ // Hernoem folders onder basepath // Flexsql levert twee velden op: oude key en nieuwe key function RenameFlexFolders(basepath, flexsql) { var basepath = S("flexFilesPath") + "/" + basepath + "/"; var oRs = Oracle.Execute(flexsql); while (!oRs.Eof) { var vAttachPath = basepath + oRs(0).value; var vAttachPath2 = basepath + oRs(1).value; MoveFlexfiles(vAttachPath, vAttachPath2); oRs.MoveNext(); } } // Kopieer folders van oldbasepath naar newbasepath // Flexsql levert twee velden op: oude key en nieuwe key function CopyFlexFolders(oldbasepath, newbasepath, flexsql) { var fso = Server.CreateObject("Scripting.FileSystemObject") var oldbasepath = S("flexFilesPath") + "\\" + oldbasepath + "\\"; var newbasepath = S("flexFilesPath") + "\\" + newbasepath + "\\"; var oRs = Oracle.Execute(flexsql); while (!oRs.Eof) { vAttachPath = oldbasepath + oRs(0).value; vAttachPath2 = newbasepath + oRs(1).value; __Log("Kopie " + vAttachPath + " Naar " + vAttachPath2); try { if (fso.FolderExists(vAttachPath)) { __Log("xAbout to copy " + vAttachPath + "\\*.* to " + vAttachPath2 + "\\"); CreateFullPath(vAttachPath2); fso.CopyFile(vAttachPath+"\\*.*", vAttachPath2, false); // Don't overwrite } } catch(ee) { __SafeDoLog("Copying files from " + vAttachPath + "
to " + vAttachPath2 + " failed:
" + ee.description, "#FFFF00"); } oRs.MoveNext(); } fso = null; } // ================================================================================================ // Save de kenmerken die we met listKenmerk hebben aangemaakt // Verondersteld POST formulier (we doen een Request.Form) // kenmerkTable : "mld_kenmerkopdr" // kenmerkParentKey: "mld_opdr_key" // kenmerkWaarde : "mld_kenmerkopdr_waarde" // kenmerkKey : "mld_kenmerk_key" // currentKenmerkenSQL : Voor maken array met kenmerk_keys die voor dit object al in de database waren // als tracking dan moet ook tweede parameter de oude waarde opleveren // RequestQ : true voor QueryString, false voor Form // moduleName : optional "ALG_ONRGOED_NIVEAU" // moduleVal : optional "R" // isNew : optional, true als het object nieuw is // flexPath : die gebruiken we dan om tijdelijke folder te hernoemen bijv. "ALG/R" // tracking : optional, dan tracken we als !isNew // - allKenmerkenSQL is dan ook verplicht met kenmerk_omschrijving en // srtkenmerk_key (zie melding_save) // - module is dan ook verplicht // In listKenmerk hebben we al gezorgd dat er alleen waarden gesubmit worden van velden die we // ook echt mochten wijzigen. kkn en kvn zullen er dan ook altijd beide zijn // ================================================================================================ // Let op: de voorkeur is het gebruik van saveFlexKenmerken(parentKey, params) // voor backward compatibilitiet mag je het nog uitschrijven. // bez_edit_bezoekers_save, cnt_contract_save en mld_opdr_save gebruiken al de nieuwe methode function saveFlexKenmerken(parentKey, kenmerkTable /* eigenlijk: Params */, // deprecated: */ kenmerkParentKey, kenmerkWaarde, kenmerkKey, currentKenmerkenSQL, RequestQ, moduleName, moduleVal, isNew, flexPath, multiMode) // TODO: support multiMode! { if (typeof kenmerkTable == "object") { var kenmerkParams = kenmerkTable; } else // oldstyle { var kenmerkParams = { kenmerkTable: kenmerkTable, kenmerkParentKey : kenmerkParentKey, kenmerkWaarde: kenmerkWaarde, kenmerkKey: kenmerkKey, currentKenmerkenSQL: currentKenmerkenSQL, requestQF: RequestQ?Request.QueryString:Request.Form, moduleName: moduleName, moduleVal: moduleVal, isNew: isNew, flexPath: flexPath, multiMode: multiMode } } var flexdata = kenmerkParams.flexdata; if (!flexdata) { // Maak alsnog het flexdata object: backwards compatible! var params = {}; if (kenmerkParams.extraserie) params.extraserie = kenmerkParams.extraserie; if (kenmerkParams.nameprefix) params.nameprefix = kenmerkParams.nameprefix; flexdata = flexkenmerken2jsondata(params); } return _saveFlexKenmerken(parentKey, kenmerkParams, flexdata); } function _saveFlexKenmerken(parentKey, params, flexdata) // TODO: support multiMode! { var kenmerk_keys = new Array(); // kenmerk table is used to check whether a kenmerk already exists or not. if (params.currentKenmerkenSQL) // JGL: Is volgens mij altijd wel aanwezig { // FSN#18613/ PNBR#22893 Foute kenmerken opruimen // Kunnen met name onstaan als iemand bijvoorbeeld de stdmelding wijzigt van een melding, // srtactiviteit van een reservering etc. // params.currentKenmerkenSQL bevat alle geldige kenmerkwaarden (ongeacht autorisatie) if (!params.noFlexCleanup) { var sqldelete = "DELETE FROM " + params.kenmerkTable + " WHERE " + params.kenmerkParentKey + " = " + parentKey + " AND " + params.kenmerkKey + " NOT IN (SELECT " + params.kenmerkKey + " FROM (" + params.currentKenmerkenSQL + "))"; if (params.moduleName) // voorzichtig sqldelete += " AND " + params.moduleName + " = " + safe.quoted_sql(params.moduleVal); Oracle.Execute(sqldelete); } // Nu oude kenmerken verzamelen in kenmerk_keys var oRs = Oracle.Execute(params.currentKenmerkenSQL); while (!oRs.eof) { kenmerk_keys[oRs(params.kenmerkKey).value] = oRs(params.kenmerkWaarde).value; // kenmerkwaarde moet oldval bevatten oRs.MoveNext(); } oRs.Close(); } if (params.isNew && !params.noAttachments) { var ktmpfolder = getFParam("ktmpfolder" + (params.tmpfolderNum? params.tmpfolderNum : 0), ""); if (ktmpfolder) { var tmp_folder = "__NEW__" + user_key + "_" + safe.filename(ktmpfolder); vAttachPath = S("flexFilesPath") + "/" + params.flexPath + tmp_folder; var flexPathArray = params.flexPath.split("/"); // MLD/M => MLD (0) en M (1) vAttachPath2 = S("flexFilesPath") + "/" + flexPathArray[0] + "/" + subfolderKey(bepaalNiveau(params.moduleName, flexPathArray[1]), parentKey); // Niet van toepassing: we doen altijd een hele folder hieronder. // MoveFlexfiles(vAttachPath, vAttachPath2) var fso = Server.CreateObject("Scripting.FileSystemObject") if (fso.FolderExists(vAttachPath)) { __Log("Hernoem " + vAttachPath + " naar " + vAttachPath2); CreateFullPath(vAttachPath2); // het 1000-tal was er misschien nog niet. try { fso.MoveFolder(vAttachPath + "/*.*", vAttachPath2); fso.DeleteFolder(vAttachPath); } catch (ee) { __DoLog("MoveFolder " + vAttachPath + " naar " + vAttachPath2 + " nog mislukt: " + ee.description); } } fso = null; } } var trackarray = []; // eventuele tracking var hasExpression = false; for (kenmerkkey in flexdata) { var flex = flexdata[kenmerkkey]; var vold = kenmerk_keys[flex.id]? kenmerk_keys[flex.id] : ""; hasExpression = hasExpression || flex.expr == 1; var vnew = flex.value || ""; // tracking? if (!params.isNew && params.tracking) { if (vold != vnew) { var oRsk = Oracle.Execute(params.allKenmerkenSQL + flex.id); var label = oRsk("kenmerk_omschrijving").Value; var kdomein_key = oRsk("fac_kenmerkdomein_key").Value; oRsk.Close(); if (flex.type == "S" || flex.type == "R") { if (vold != "") { var oRsd = Oracle.Execute("SELECT fac.getdomeinwaarde(" + kdomein_key + ", " + safe.quoted_sql(vold) + ") domeinwaarde FROM DUAL"); vold = oRsd("domeinwaarde").Value; oRsd.Close(); } if (vnew != "") { var oRsd = Oracle.Execute("SELECT fac.getdomeinwaarde(" + kdomein_key + ", " + safe.quoted_sql(vnew) + ") domeinwaarde FROM DUAL"); vnew = oRsd("domeinwaarde").Value; oRsd.Close(); } } trackarray.push(label + ": " + buildTrackText("varchar", vold, vnew, {nodiff: (flex.type != "C"? true : null)})); } } // Bepaal of het hier gaat om een flexkemerk verbruiksmeter. Dan moet historie behouden blijven var verbruiksmeter = false; if (params.kenmerkKey == "ins_kenmerk_key") { // Het gaat om een INS flexkenemerk. // Controleren of het hier om een verbruiksmeter gaat. var sql2 = "SELECT ins_kenmerk_meetwaarde" + " FROM ins_kenmerk" + " WHERE ins_kenmerk_key = " + flex.id; oRs = Oracle.Execute(sql2); verbruiksmeter = oRs("ins_kenmerk_meetwaarde").value == 1; oRs.Close(); } // A real kenmerk value exists if (flex.type == "X" && S("flex_X_is_URL") == 0) flex.value = parseDocumentPath(flex.value); if (( flex.value == "" || flex.value == "undefined")) { if (kenmerk_keys[flex.id] && !params.multiMode) { if (verbruiksmeter) { // Zet de sysdate zodat de historie behouden blijft sql = "UPDATE ins_kenmerkdeel" + " SET ins_kenmerkdeel_verwijder = " + "SYSDATE" + " WHERE ins_deel_key = " + parentKey + " AND ins_kenmerk_key = " + flex.id + " AND ins_kenmerkdeel_verwijder IS NULL"; Oracle.Execute(sql); } else { // Delete; // Zelf zetten we niet de verwijderdatum maar als een ander proces dat // heeft gedaan (BONS#21991) dan blijven wij wel van die records af. sql = "DELETE FROM " + params.kenmerkTable + " WHERE " + params.kenmerkParentKey + " = " + parentKey + " AND " + params.kenmerkKey + " = " + flex.id + " AND " + params.kenmerkTable + "_VERWIJDER IS NULL"; Oracle.Execute(sql); } } continue; } if (flex.id in kenmerk_keys) // Kenmerk komt in de kenmerkTable voor. Desnoods met waarde null (wat eigenlijk niet zou mogen). { // update // Alleen een update als de waarde veranderd is if (vold != vnew) { // Alleen een update/insert als de waarde veranderd of toegevoegd is if (verbruiksmeter) { // Bij de verbruiksmeters moet de historie behouden blijven // Bij verbruiksmeter gaat het over ins kenmerken sql = "UPDATE ins_kenmerkdeel" + " SET ins_kenmerkdeel_verwijder = " + "SYSDATE" + " WHERE ins_deel_key = " + parentKey + " AND ins_kenmerk_key = " + flex.id + " AND ins_kenmerkdeel_verwijder IS NULL"; Oracle.Execute(sql); sql = "INSERT INTO ins_kenmerkdeel " + " (ins_kenmerkdeel_waarde, ins_deel_key, ins_kenmerk_key)" + " VALUES " + " (" + safe.quoted_sql(flex.value) + ", " + parentKey + ", " + flex.id + ")"; Oracle.Execute(sql); } else { // Gewone flexkenmerken // Zelf zetten we niet de verwijderdatum maar als een ander proces dat // heeft gedaan (BONS#21991) dan blijven wij wel van die records af. sql = "UPDATE " + params.kenmerkTable + " SET " + params.kenmerkWaarde + " = " + safe.quoted_sql(flex.value) + " WHERE " + params.kenmerkParentKey + " = " + parentKey + " AND " + params.kenmerkKey + " = " + flex.id + " AND " + params.kenmerkTable + "_VERWIJDER IS NULL"; Oracle.Execute(sql); } } } else { // Insert if (( flex.value != "" && flex.value != "undefined")) { sql = "INSERT INTO " + params.kenmerkTable + "(" + params.kenmerkParentKey + "," + params.kenmerkKey + "," + params.kenmerkWaarde + (params.moduleName? "," + params.moduleName : "") + ")" + " VALUES " + "(" + parentKey + "," + flex.id + "," + safe.quoted_sql(flex.value) + (params.moduleName? "," + safe.quoted_sql(params.moduleVal): "") + ")"; Oracle.Execute(sql); } } } if (hasExpression) { if (params.module == "MLD") { if (params.flexPath == "MLD/O") module = "OPD" else module = "MLD" } else module = params.module; // Tabel fac_kenmwaarden vullen, expressies berekenen en tabel fac_kenmwaarden weer leeg maken. // Vorige waarden verwijderen. removekenmerkwaarden(module, parentKey); savekenmerkwaarden(module, parentKey, params.moduleVal, flexdata); evaluateflexexpressions(module, parentKey, true); //removekenmerkwaarden(module, parentKey); } return trackarray; } function savekenmerkwaarden(module, refkey, kenmerkniveau, flexdata) { for (kenmerkkey in flexdata) { var sql = "INSERT INTO fac_kenmwaarden" + " (fac_kenmwaarden_module" + " , fac_kenmwaarden_refkey" + (kenmerkniveau ? " , fac_kenmwaarden_niveau" : "") + " , fac_kenmwaarden_kenmerk_key" + " , fac_kenmwaarden_waarde" + " , fac_kenmwaarden_kenmerktype" + " , fac_kenmwaarden_isexpr" + " , prs_perslid_key" + " )" + " VALUES (" + safe.quoted_sql(module) + " , " + refkey + (kenmerkniveau ? " , " + safe.quoted_sql(kenmerkniveau) : "") + " , " + flexdata[kenmerkkey].id + " , " + safe.quoted_sql(flexdata[kenmerkkey].value) + " , " + safe.quoted_sql(flexdata[kenmerkkey].type) + " , " + flexdata[kenmerkkey].expr + " , " + user_key + " )"; Oracle.Execute(sql); } } function evaluateflexexpressions(module, refkey, savetodb) { // Berekening van de expressie kenmerken. var sql = "BEGIN flx.evaluateflexexpressions(" + safe.quoted_sql(module) + ", " + refkey + ", " + user_key + ", " + (savetodb? 1 : 0) + "); END;"; var err = Oracle.Execute(sql, true); if (err.friendlyMsg) { var message = "kenmerk_common.inc (evaluateflexexpressions): Error writing flex expression\n" + err.friendlyMsg; __DoLog(message); abort_with_warning(err.friendlyMsg); } } function removekenmerkwaarden(module, refkey) { var sql = "DELETE FROM fac_kenmwaarden" + " WHERE fac_kenmwaarden_module = " + safe.quoted_sql(module) + " AND fac_kenmwaarden_refkey = " + refkey + " AND prs_perslid_key = " + user_key; Oracle.Execute(sql); } function flexkenmerken2jsondata(params) { // Lees de Form parameters van flexkenmerken en zet ze in een json-object. var jsondata = []; var namePrefix = params.nameprefix || "k"; var counterName = (params.extraserie? namePrefix + "_all" : "k_all"); if (Request.Form(counterName).count > 0) var kall = Request.Form(counterName)(1); // bij bezoekers komt counterName (k_all) meerdere keren voor maar wel altijd identiek else { // JGL: komt normaal nooit voor, alleen als edit-scherm flexkenmerken niet goed heeft kunnen laden, bijv. AKZA#21569 // Normaal laten we zoiets gewoon gebeuren maar // Error: File /facilitor5iwork/appl/shared/kenmerk_common.inc Line 1246 Index out of range. An array index is out of range. // in de eventvwr(!) wil ik echt niet hebben var kall = 0; } for (var kenmerk=1; kenmerk<=kall; kenmerk++) { var flex = namePrefix + kenmerk; var kkn = Request.Form(flex + "key").Count; var ktn = Request.Form(flex + "t").Count; if( kkn && ktn ) { var kk = getFParamInt(flex + "key"); // kenmerk key var kt = getFParam(flex + "t", ""); // Type letter var kv = getFParam(flex + "val", ""); // kenmerk waarde var ke = Request.Form(flex + "e").Count; // Flexkenmerk is een expressie. // ATTENTIE: Als het een numeriek/decimaal veld is, kan het zijn dat er een komma in voorkomt die eigenlijk een punt moet zijn. // Als het een numeriek/decimaal veld is, kan het ook een checkbox zijn if (kt == "N") { kv = kv.replace(",", "."); // We slaan altijd op met punten if (kv.substr(0, 2) == "0.") // leading zero er af. Doet de database trigger ook en nu if (kv.length == 2 || kv.substr(3) == " ") kv = "0"; else kv = kv.substr(1); // krijgen we geen ongewenste tracking. // Kijken of het een checkbox is var isCheckbox = getFParamInt("has_" + flex + "val", 0) == 1; if (isCheckbox) { var isChecked = Request.Form(flex + "val").Count; kv = (isChecked ? "1" : ""); // Een niet aangevinkte checkbox hoeft niet opgeslagen te worden als de waarde "0". } } // Suggest kenmerken moeten ook gedelete worden als ze leeg zijn. Dus voor delete actie leeg maken. // Ook nodig voor correctere tracking if ((kt == "S" || kt == "R") && kv == "-1") kv = ""; // anders zouden we '-1' opslaan jsondata[kk] = { id: kk, //name: "", type: kt, value: kv, expr: (ke? 1 : 0), kfieldid: flex }; } } return jsondata; } %>