801 lines
38 KiB
PHP
801 lines
38 KiB
PHP
<% /*
|
|
$Revision$
|
|
$Id$
|
|
|
|
File: save2db.inc
|
|
Description: functions to save records to database
|
|
Context: Form u2 action from reserv_Change.asp form
|
|
Note:
|
|
*/
|
|
%>
|
|
<!-- #include file="../Shared/adovbs.inc"-->
|
|
<%
|
|
|
|
/* TODO: Kunnen/willen we dit generiek herschrijven naar bind-variabelen?
|
|
(of recordset operatie: handig voor tracking oude waarden)
|
|
fields is een array van bij te werken velden
|
|
telkens een tuple met:
|
|
dbs: veldnaam in database
|
|
typ: key, altijd integer number. Als -1 of "" dan wordt NULL opgeslagen
|
|
date, Tijd wordt er af gestript
|
|
datetime, Inclusief tijd
|
|
float, Accepteert punten en komma's
|
|
number,
|
|
varchar Quotes worden escaped
|
|
memo Quotes worden escaped
|
|
check "on" wordt 1, "" wordt "null". Let op: moet aangemaakt zijn met iface.inc/CHECKBOX
|
|
check0 "on" wordt 1, "" wordt 0. Let op: moet aangemaakt zijn met iface.inc/CHECKBOX
|
|
time millisecs sinds middernacht
|
|
sql voorgedefinieerd, wordt ongewijzigd gebruikt
|
|
len: varchar wordt hier op afgekapt
|
|
-- een van de volgende view (verplicht) --
|
|
frm: Request.Form veld. Als niet meegesubmit dan ook niet opgeslagen!
|
|
seq: naam van een sequence
|
|
qrs: (nog niet ondersteund!) vergelijk frm maar dan voor QueryString
|
|
val: kant en klare waarde, zelf berekend
|
|
track: "een tekst" waaronder wijzigingen getrackt moeten worden
|
|
of: true waardoor wel oldjsval wordt bepaald maar niet getrackt (mld_behandelaar_key)
|
|
foreign: bij tracking nodig als typ=="key", een waarde uit onderstaande foreignKeyTable
|
|
of: een functie, voorals we zelf de waarde naar een (andere) tekst willen vertalen
|
|
params: vooralsnog geen
|
|
result: een sqlstatement met alvast het woord WHERE er achter (opdat het het niet vergeten)
|
|
|
|
*/
|
|
|
|
// Zorg dat tbl ook eventueel verwijderde records bevat. Anders kan
|
|
// de tracking de oude waarde niet naar tekst omzetten
|
|
var __foreignKeyTable; // Indirect om te voorkomen dat bij API's te vroeg lcl.xsql wordt uitgevoerd
|
|
function foreignKeyTable(field)
|
|
{
|
|
if (!__foreignKeyTable)
|
|
{
|
|
__foreignKeyTable
|
|
= {
|
|
"ALG_DISTRICT" : { tbl: "alg_district", key: "alg_district_key", desc: "alg_district_omschrijving" },
|
|
"ALG_GEBOUW" : { tbl: "alg_gebouw", key: "alg_gebouw_key", desc: "alg_gebouw_code", name: "alg_gebouw_naam" },
|
|
"ALG_LOCATIE" : { tbl: "alg_locatie", key: "alg_locatie_key", desc: "alg_locatie_code", name: "alg_locatie_omschrijving" },
|
|
"ALG_REGIO" : { tbl: "alg_regio", key: "alg_regio_key", desc: "alg_regio_omschrijving" },
|
|
"ALG_RUIMTE" : { tbl: "alg_ruimte", key: "alg_ruimte_key", desc: "alg_ruimte_nr" },
|
|
"ALG_SRTGEBOUW" : { tbl: "alg_srtgebouw", key: "alg_srtgebouw_key", desc: lcl.xsql("alg_srtgebouw_omschrijving", "alg_srtgebouw_key") },
|
|
"ALG_SRTRUIMTE" : { tbl: "alg_srtruimte", key: "alg_srtruimte_key", desc: lcl.xsql("alg_srtruimte_omschrijving", "alg_srtruimte_key") },
|
|
"ALG_SRTTERREINSECTOR" : { tbl: "alg_srtterreinsector", key: "alg_srtterreinsector_key", desc: lcl.xsql("alg_srtterreinsec_omschrijving", "alg_srtterreinsector_key") },
|
|
"ALG_TERREINSECTOR" : { tbl: "alg_terreinsector", key: "alg_terreinsector_key", desc: "alg_terreinsector_code", name: "alg_terreinsector_naam"},
|
|
"ALG_V_PLAATSAANDUIDING" : { tbl: "alg_v_plaatsaanduiding", key: "alg_onroerendgoed_keys", desc: "alg_plaatsaanduiding" },
|
|
"ALG_VERDIEPING" : { tbl: "alg_verdieping", key: "alg_verdieping_key", desc: "alg_verdieping_code", name: "alg_verdieping_code" },
|
|
"BES_BESTELOPDR" : { tbl: "bes_bestelopdr", key: "bes_bestelopdr_key", desc: "bes_bestelopdr_id" },
|
|
"BES_SRTPROD" : { tbl: "bes_srtprod", key: "bes_srtprod_key", desc: "bes_srtprod_omschrijving" },
|
|
"BEZ_ACTIE" : { tbl: "bez_actie", key: "bez_actie_key", desc: lcl.xsql("bez_actie_omschrijving", "bez_actie_key") },
|
|
"BEZ_AFSPRAAK" : { tbl: "bez_afspraak", key: "bez_afspraak_key", desc: "'Appointment ' || TO_CHAR(bez_afspraak_datum, 'YYYY-MM-DD HH24:MI')" },
|
|
"BEZ_ACTIE_GROEP" : { tbl: "bez_actie_groep", key: "bez_actie_groep_key", desc: "bez_actie_groep_omschrijving" },
|
|
"CNT_CONTRACT" : { tbl: "cnt_contract", key: "cnt_contract_key", desc: "cnt_contract_nummer_intern" },
|
|
"CNT_CONTRACT_PLAATS" : { tbl: "cnt_contract_plaats", key: "cnt_contract_plaats_key", alias: "plaats",
|
|
desc: "(SELECT cp.cnt_plaats_omschrijving"
|
|
+ " FROM cnt_v_aanwezigcontract_plaats ap, cnt_v_contract_plaats cp "
|
|
+ " WHERE ap.cnt_contract_plaats_key = plaats.cnt_contract_plaats_key"
|
|
+ " AND cp.cnt_plaats_key = ap.cnt_alg_plaats_key"
|
|
+ " AND cp.cnt_plaats_code = ap.cnt_alg_plaats_code) cnt_plaats_omschrijving" },
|
|
"CNT_DISCIPLINE" : { tbl: "cnt_discipline", key: "ins_discipline_key", desc: "ins_discipline_omschrijving" },
|
|
"CNT_TERMIJN" : { tbl: "cnt_termijn", key: "cnt_termijn_key", desc: lcl.xsql("cnt_termijn_omschrijving", "cnt_termijn_key" )},
|
|
"CTR_DISCIPLINE" : { tbl: "ctr_discipline", key: "ins_discipline_key", desc: "ins_discipline_omschrijving" },
|
|
"FAC_FUNCTIE" : { tbl: "fac_functie", key: "fac_functie_key", desc: "lcl.l(fac_functie_omschrijving, 1) || ' (' || fac_functie_code || ')'" },
|
|
"FAC_GROEP" : { tbl: "fac_groep", key: "fac_groep_key", desc: "fac_groep_omschrijving" },
|
|
"FAC_NOTE_GROUP" : { tbl: "fac_note_group", key: "fac_note_group_key", desc: "fac_note_group_omschrijving"},
|
|
"FAC_PROFIEL" : { tbl: "fac_profiel", key: "fac_profiel_key", desc: "fac_profiel_omschrijving" },
|
|
"FAC_SRTNOTIFICATIE" : { tbl: "fac_srtnotificatie", key: "fac_srtnotificatie_key", desc: "fac_srtnotificatie_code" },
|
|
"FAQ_DISCIPLINE" : { tbl: "ins_tab_discipline", key: "ins_discipline_key", desc: "ins_discipline_omschrijving" },
|
|
"FIN_BTWTABEL" : { tbl: "fin_btwtabel", key: "fin_btwtabel_key", desc: "fin_btwtabel_omschrijving" },
|
|
"FIN_BTWTABELWAARDE" : { tbl: "fin_btwtabelwaarde", key: "fin_btwtabelwaarde_key", desc: lcl.xsql("fin_btwtabelwaarde_oms", "fin_btwtabelwaarde_key") },
|
|
"INS_CONTROLEMODE" : { tbl: "ins_controlemode", key: "ins_controlemode_key", desc: "ins_controlemode_oms" },
|
|
"INS_DEEL" : { tbl: "ins_deel", key: "ins_deel_key", desc: "ins_deel_omschrijving" },
|
|
"INS_DISCIPLINE" : { tbl: "ins_discipline", key: "ins_discipline_key", desc: "ins_discipline_omschrijving"},
|
|
"INS_SRTDEEL" : { tbl: "ins_srtdeel", key: "ins_srtdeel_key", desc: "ins_srtdeel_omschrijving" },
|
|
"INS_SRTDISCIPLINE" : { tbl: "ins_srtdiscipline", key: "ins_srtdiscipline_key", desc: "ins_srtdiscipline_omschrijving"},
|
|
"INS_SRTGROEP" : { tbl: "ins_srtgroep", key: "ins_srtgroep_key", desc: "ins_srtgroep_omschrijving" },
|
|
"MLD_ADRES" : { tbl: "mld_adres", key: "mld_adres_key", desc: "mld_adres_naam" },
|
|
"MLD_DIENSTNIVEAU" : { tbl: "mld_dienstniveau", key: "mld_dienstniveau_key", desc: lcl.xsql("mld_dienstniveau_omschr", "mld_dienstniveau_key") },
|
|
// Altijd met de prefix ervoor
|
|
"MLD_DISCIPLINE" : { tbl: "mld_discipline",
|
|
key: "ins_discipline_key",
|
|
desc: "ins_discipline_omschrijving",
|
|
alias: "sdiscipline",
|
|
name: "(SELECT (NVL2(ins_srtdiscipline_prefix,ins_srtdiscipline_prefix||'-','')) || ins_discipline_omschrijving"
|
|
+ " FROM ins_srtdiscipline isd"
|
|
+ " WHERE isd.ins_srtdiscipline_key = sdiscipline.ins_srtdiscipline_key) ins_discipline_omschrijving" },
|
|
/* de prefix komt zo niet mee met de desc van opdracht: */
|
|
"MLD_OPDR" : { tbl: "mld_opdr", key: "mld_opdr_key", desc: "COALESCE(mld_opdr_id, mld_melding_key||'/'||mld_opdr_bedrijfopdr_volgnr)", alias: "o" },
|
|
"MLD_STDMELDING" : { tbl: "mld_stdmelding", key: "mld_stdmelding_key", desc: lcl.xsql("mld_stdmelding_omschrijving", "mld_stdmelding_key") },
|
|
"MLD_TYPEOPDR" : { tbl: "mld_typeopdr", key: "mld_typeopdr_key", desc: lcl.xsql("mld_typeopdr_omschrijving", "mld_typeopdr_key") },
|
|
"MLD_UITVOERENDE" : { tbl: "mld_v_uitvoerende", key: "mld_uitvoerende_key", desc: "naam" },
|
|
"MLD_V_AFLEVERADRES" : { tbl: "mld_adres", key: "mld_adres_key", desc: "mld_adres_naam" },
|
|
"MLD_V_FACTUURADRES" : { tbl: "mld_adres", key: "mld_adres_key", desc: "mld_adres_naam" },
|
|
"PRS_AFDELING" : { tbl: "prs_v_afdeling", key: "prs_afdeling_key", desc: S("prs_dep_string"), alias: "d"},
|
|
"PRS_BEDRIJF" : { tbl: "prs_bedrijf", key: "prs_bedrijf_key", desc: "prs_bedrijf_naam" },
|
|
"PRS_CONTACTPERSOON" : { tbl: "prs_contactpersoon", key: "prs_contactpersoon_key", desc: S("prs_contactpers_string"), alias: "cp"},
|
|
"PRS_DIENST" : { tbl: "prs_dienst", key: "prs_dienst_key", desc: lcl.xsql('prs_dienst_omschrijving', 'prs_dienst_key') },
|
|
"PRS_KOSTENPLAATS" : { tbl: "prs_kostenplaats", key: "prs_kostenplaats_key", desc: S("prs_kpn_string"), alias: "k"},
|
|
"PRS_KOSTENPLAATSGRP" : { tbl: "prs_kostenplaatsgrp", key: "prs_kostenplaatsgrp_key", desc: "prs_kostenplaatsgrp_oms"},
|
|
"PRS_KOSTENSOORT" : { tbl: "prs_kostensoort", key: "prs_kostensoort_key", desc: "prs_kostensoort_oms"},
|
|
"PRS_KOSTENSOORTGRP" : { tbl: "prs_kostensoortgrp", key: "prs_kostensoortgrp_key", desc: "prs_kostensoortgrp_oms"},
|
|
"PRS_PERSLID" : { tbl: "prs_v_perslid_fullnames_all", key: "prs_perslid_key", desc: "prs_perslid_naam_full"},
|
|
"PRS_SRTPERSLID" : { tbl: "prs_srtperslid", key: "prs_srtperslid_key", desc: "prs_srtperslid_omschrijving"},
|
|
"PRS_RELATIETYPE" : { tbl: "prs_relatietype", key: "prs_relatietype_key", desc: "prs_relatietype_omschrijving" },
|
|
"PRS_WERKPLEK" : { tbl: "prs_werkplek", key: "prs_werkplek_key", desc: "prs_werkplek_omschrijving" },
|
|
"RES_ACTIVITEIT" : { tbl: "res_activiteit", key: "res_activiteit_key", desc: lcl.xsql("res_activiteit_omschrijving", "res_activiteit_key") },
|
|
"RES_ARTIKEL" : { tbl: "res_artikel", key: "res_artikel_key", desc: "res_artikel_omschrijving" },
|
|
"RES_DEEL" : { tbl: "res_deel", key: "res_deel_key", desc: "res_deel_omschrijving" },
|
|
"RES_DISCIPLINE" : { tbl: "res_discipline", key: "ins_discipline_key", desc: "ins_discipline_omschrijving" },
|
|
"RES_OPSTELLING" : { tbl: "res_opstelling", key: "res_opstelling_key", desc: lcl.xsql("res_opstelling_omschrijving", "res_opstelling_key") },
|
|
"RES_RUIMTE" : { tbl: "res_ruimte", key: "res_ruimte_key", desc: lcl.xsql("res_ruimte_nr", "res_ruimte_key") },
|
|
"RES_RSV_RUIMTE" : { tbl: "res_rsv_ruimte", key: "res_rsv_ruimte_key", desc: "res_reservering_key || '/' || res_rsv_ruimte_volgnr" },
|
|
"RES_SRTACTIVITEIT" : { tbl: "res_srtactiviteit", key: "res_srtactiviteit_key", desc: "res_srtactiviteit_omschrijving" }
|
|
};
|
|
}
|
|
return __foreignKeyTable[field.toUpperCase()];
|
|
}
|
|
|
|
function buildUpdate(tabel, fields, params)
|
|
{
|
|
return buildTrackingUpdate(tabel, null, fields, params).sql;
|
|
}
|
|
|
|
function shorttxt(txt, len)
|
|
{
|
|
len = len || S("max_tracking_length");
|
|
if (txt.length < len)
|
|
return txt;
|
|
else
|
|
return txt.substr(0, len-4) + "...";
|
|
}
|
|
|
|
function getForeignText(key, foreign)
|
|
{
|
|
var sql = "SELECT " + foreign.desc
|
|
+ " FROM " + foreign.tbl + " " + (foreign.alias||"");
|
|
if (foreign.where)
|
|
sql += " WHERE " + foreign.where + " AND ";
|
|
else
|
|
sql += " WHERE ";
|
|
sql += foreign.key + " = " + key;
|
|
var oRs = Oracle.Execute(sql);
|
|
if (oRs.EOF)
|
|
{
|
|
__DoLog("Foreign record not found?", "#FF0000");
|
|
__DoLog(sql);
|
|
var oldtxt = "<????>"; // Beter dan een AiAi
|
|
}
|
|
else
|
|
{
|
|
var oldtxt = oRs(0).Value;
|
|
oRs.MoveNext();
|
|
if (!oRs.EOF)
|
|
{
|
|
__DoLog(sql);
|
|
__DoLog("Multiple foreign records with key {0} found in {1}\nFirst is {2}, second is {3}?".format(key, foreign.tbl, oldtxt, oRs(0).Value), "#FF0000");
|
|
}
|
|
}
|
|
oRs.Close();
|
|
|
|
return oldtxt;
|
|
}
|
|
|
|
// tracktxt.push(buildTrackText(tupel.field.typ, oldjsval, tupel.jsval, oRs(tupel.field.dbs).DefinedSize));
|
|
// bouw een mooie tekst die de van-naar wijziging beschrijft
|
|
// params: nodiff: geen L("lcl_trackappend") of L("lcl_trackpercent")
|
|
// foreign: info over de te toeken foreign key
|
|
function buildTrackText(typ, oldjsval, newjsval, params)
|
|
{
|
|
params = params || {};
|
|
var oldtxt = oldjsval;
|
|
var newtxt = newjsval;
|
|
|
|
if (typeof params.foreign == "function")
|
|
{
|
|
oldtxt = params.foreign(oldjsval, params.oldjsvals);
|
|
newtxt = params.foreign(newjsval);
|
|
}
|
|
else
|
|
{
|
|
switch (typ)
|
|
{
|
|
case "datetime":
|
|
{
|
|
var oldtxt = toDateTimeString(oldjsval);
|
|
var newtxt = toDateTimeString(newjsval);
|
|
break;
|
|
}
|
|
case "date":
|
|
{
|
|
var oldtxt = toDateString(oldjsval);
|
|
var newtxt = toDateString(newjsval);
|
|
break;
|
|
}
|
|
case "time":
|
|
{
|
|
var oldtxt = toTimeString(oldjsval);
|
|
var newtxt = toTimeString(newjsval);
|
|
break;
|
|
}
|
|
case "key": // hash foreign moet ook gedefinieerd zijn
|
|
{
|
|
var foreign = params.foreign;
|
|
if (!foreign)
|
|
abort_with_warning("INTERNAL ERROR:\nForeign key for tracking " + oldjsval + " to "+newjsval+" is not defined");
|
|
|
|
if (typeof foreign == 'string')
|
|
foreign = foreignKeyTable(params.foreign);
|
|
|
|
if (!foreign)
|
|
abort_with_warning("INTERNAL ERROR:\nForeign key for tracking " + params.foreign.toUpperCase()+" is not defined in foreignKeyTable");
|
|
|
|
if (oldjsval)
|
|
oldtxt = getForeignText(oldjsval, foreign)
|
|
if (newjsval)
|
|
newtxt = getForeignText(newjsval, foreign)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (oldjsval === null || oldjsval === "") oldtxt = L("lcl_trackfromempty");
|
|
if (newjsval === null || newjsval === "") newtxt = L("lcl_tracktoempty");
|
|
// oke, en hoe gaan we het verschil presenteren?
|
|
var tracktxt = null;
|
|
switch (typ)
|
|
{
|
|
case "memo":
|
|
case "varchar":
|
|
{
|
|
if (oldjsval == null || oldjsval == "") // leeg naar iets
|
|
var txt = oldtxt + L("lcl_trackto") + shorttxt(newjsval);
|
|
else if (newjsval == null || newjsval == "") // iets naar leeg
|
|
var txt = shorttxt(oldjsval) + L("lcl_trackto") + newtxt;
|
|
else if (params.nodiff || (oldjsval.length < S("max_tracking_length") && newjsval.length < S("max_tracking_length"))) // korte tekst: gewoon oud-->nieuw
|
|
var txt = shorttxt(oldtxt) + L("lcl_trackto") + shorttxt(newtxt)
|
|
else if (newjsval.indexOf(oldjsval) == 0) // lange tekst aangevuld
|
|
var txt = L("lcl_trackappend") + shorttxt(newjsval.substr(oldjsval.length));
|
|
else // lange tekst gewijzigd: percentage verschil noemen
|
|
{
|
|
// Helemaal naar Oracle om dit te berekenen is niet echt efficient natuurlijk
|
|
// maar voor met name lange strings fors sneller dan een js-functie
|
|
var sqldiff = "SELECT UTL_MATCH.EDIT_DISTANCE_SIMILARITY("+safe.quoted_sql(String(oldjsval))
|
|
+","+safe.quoted_sql(String(newjsval))+") FROM DUAL";
|
|
try
|
|
{
|
|
var oRs = Oracle.Execute(sqldiff);
|
|
var diff = 100 - oRs(0).Value;
|
|
oRs.Close();
|
|
}
|
|
catch(e)
|
|
{ // 10.2.0.4? Crasht sporadisch bij extreem lange teksten UWVA#19894
|
|
__DoLog("Bad UTL_MATCH.EDIT_DISTANCE_SIMILARITY call #19894");
|
|
var diff = "??"; // beter dan niet kunnen opslaan
|
|
}
|
|
var txt = String(diff) + L("lcl_trackpercent");
|
|
}
|
|
tracktxt = txt;
|
|
break;
|
|
}
|
|
default:
|
|
tracktxt = oldtxt + L("lcl_trackto") + newtxt;
|
|
}
|
|
return tracktxt;
|
|
}
|
|
|
|
// Die is wat specifiekers omdat een andere stdm dezelfde tekst kan hebben
|
|
// maar dan onder een andere vakgroep of vakgroeptype
|
|
// Een vakgroep(type)wissel wil je eventueel ook tracken
|
|
function buildStdmTrackText(typ, oldjsval, newjsval, params)
|
|
{
|
|
var old_disc_key = Oracle.Get("mld_ins_discipline_key", "mld_stdmelding", oldjsval);
|
|
var new_disc_key = Oracle.Get("mld_ins_discipline_key", "mld_stdmelding", newjsval);
|
|
var old_srtdisc_key = Oracle.Get("ins_srtdiscipline_key", "mld_discipline", "ins_discipline_key", old_disc_key);
|
|
var new_srtdisc_key = Oracle.Get("ins_srtdiscipline_key", "mld_discipline", "ins_discipline_key", new_disc_key);
|
|
|
|
var oldsrtdisctxt = getForeignText(old_srtdisc_key, foreignKeyTable("ins_srtdiscipline"));
|
|
var newsrtdisctxt = getForeignText(new_srtdisc_key, foreignKeyTable("ins_srtdiscipline"));
|
|
var olddisctxt = getForeignText(old_disc_key, foreignKeyTable("mld_discipline"));
|
|
var newdisctxt = getForeignText(new_disc_key, foreignKeyTable("mld_discipline"));
|
|
var oldstdmtxt = getForeignText(oldjsval, foreignKeyTable("mld_stdmelding"));
|
|
var newstdmtxt = getForeignText(newjsval, foreignKeyTable("mld_stdmelding"));
|
|
|
|
var returntextArr = [];
|
|
|
|
if (oldsrtdisctxt == newsrtdisctxt)
|
|
oldsrtdisctxt = newsrtdisctxt = "";
|
|
if (olddisctxt == newdisctxt)
|
|
olddisctxt = newdisctxt = "";
|
|
if (oldstdmtxt == newstdmtxt)
|
|
oldstdmtxt = newstdmtxt = "";
|
|
|
|
if (newsrtdisctxt)
|
|
returntextArr.push (L("lcl_vakgroup_type") + ": " + oldsrtdisctxt + L("lcl_trackto") + newsrtdisctxt);
|
|
if (newdisctxt)
|
|
returntextArr.push (L("lcl_vakgroup") + ": " + olddisctxt + L("lcl_trackto") + newdisctxt);
|
|
if (newstdmtxt)
|
|
returntextArr.push (L("lcl_complain") + ": " + oldstdmtxt + L("lcl_trackto") + newstdmtxt);
|
|
|
|
return returntextArr.join("\n");
|
|
}
|
|
|
|
|
|
var known_adotypes =
|
|
{
|
|
key: ['NUMBER'],
|
|
date: ['DATE'],
|
|
datetime: ['DATE'],
|
|
number: ['NUMBER'],
|
|
float: ['NUMBER'],
|
|
memo: ['VARCHAR2'],
|
|
icon: ['VARCHAR2'],
|
|
file: ['VARCHAR2'],
|
|
color: ['VARCHAR2'],
|
|
symbol: ['VARCHAR2'],
|
|
varchar: ['VARCHAR2'],
|
|
check: ['NUMBER'],
|
|
check0: ['NUMBER'],
|
|
time: ['DATE'],
|
|
sql: []
|
|
};
|
|
|
|
// automatische debugging tool als logging aan staat
|
|
// controleert of field-lijst klopt met echte veldtypes
|
|
function checkFieldTypes(tabel, fields)
|
|
{
|
|
var i, j;
|
|
var oRs = Oracle.RealConnection.Execute("SELECT column_name || CASE"
|
|
+ " WHEN attr_name IS NOT NULL"
|
|
+ " THEN '.' || attr_name"
|
|
+ " ELSE ''"
|
|
+ " END column_name"
|
|
+ " , COALESCE(attr_type_name, data_type) data_type"
|
|
+ " , data_scale"
|
|
+ " , attr_name"
|
|
+ " FROM user_tab_columns utc"
|
|
+ " , user_type_attrs uta"
|
|
+ " WHERE table_name = " + safe.quoted_sql(tabel.toUpperCase())
|
|
+ " AND utc.data_type = uta.type_name(+)");
|
|
if (oRs.eof) // dan kunnen we niets
|
|
{
|
|
oRs.Close();
|
|
return;
|
|
}
|
|
|
|
for (i=0; i < fields.length; i++)
|
|
{
|
|
var field = fields[i];
|
|
var val = field.val;
|
|
var dbs = field.dbs;
|
|
var dbfield = null;
|
|
while (!oRs.eof)
|
|
{
|
|
if (oRs("column_name").value == dbs.toUpperCase())
|
|
{
|
|
dbfield = { name: oRs("column_name").value,
|
|
Type: oRs("data_type").value,
|
|
NumericScale: oRs("data_scale").value
|
|
};
|
|
}
|
|
//else
|
|
//__Log(oRs.Fields(j).Name.toUpperCase() + " is het niet?");
|
|
oRs.MoveNext();
|
|
}
|
|
if (!dbfield)
|
|
{
|
|
__Log(tabel + "." + dbs + " niet gevonden in recordset?");
|
|
continue;
|
|
}
|
|
|
|
var ok_types = known_adotypes[field.typ];
|
|
var found = false;
|
|
for (j in ok_types)
|
|
{
|
|
if (ok_types[j] == dbfield.Type)
|
|
found = true;
|
|
}
|
|
if (!found && field.typ != "sql")
|
|
{
|
|
__SafeLog("<span style='background-color: #00FFFF;'>" + dbs + " is opgegeven als type '" + field.typ + "' maar is: " + dbfield.Type + "</span>");
|
|
}
|
|
else
|
|
{
|
|
if (field.typ == "number" && dbfield.NumericScale > 0)
|
|
{
|
|
__SafeLog("<span style='background-color: #00FFFF;'>"
|
|
+ dbs + " is gedefinieerd als 'number' maar heeft " + dbfield.NumericScale
|
|
+ " decimalen dus 'float' ligt meer voor de hand</span>");
|
|
}
|
|
}
|
|
oRs.MoveFirst(); // voor de volgende
|
|
}
|
|
oRs.Close();
|
|
}
|
|
|
|
// where is bijvoorbeeld 'MLD_MELDING_KEY=1234'
|
|
// params bevat eventueel
|
|
// dialect_key: 134
|
|
function buildTrackingUpdate(tabel, where, xfields, params)
|
|
{
|
|
params = params || {};
|
|
|
|
if (!params.noValidateToken) // Uit API's
|
|
protectRequest.validateToken(); // Alle _edit_ schermen horen IFACE.FORM_END aan het einde te hebben
|
|
|
|
if (xfields instanceof Array)
|
|
var fields = xfields;
|
|
else // Uit API2
|
|
{
|
|
var fields = [];
|
|
for (var fld in xfields)
|
|
fields.push(xfields[fld]);
|
|
}
|
|
if (!fields.length)
|
|
{
|
|
__Log("Nothing to update in buildTrackingUpdate?");
|
|
return { sql: "BEGIN NULL; END;", trackarray: [], oldjsvals: [] }
|
|
}
|
|
|
|
if (__Logging & 1)
|
|
{
|
|
checkFieldTypes(tabel, fields)
|
|
}
|
|
var result = _buildFields(fields, params, tabel, where);
|
|
var tupels = result.tupels;
|
|
// we hebben nooit sequences bij updates?
|
|
var updates = [];
|
|
var i;
|
|
var trackfields = [];
|
|
for (i=0; i < tupels.length; i++)
|
|
{
|
|
var tupel = tupels[i];
|
|
if (tupel.field.dbs)
|
|
{
|
|
updates.push("xx." + tupel.field.dbs + " = " + tupel.sql);
|
|
}
|
|
if (where && tupel.field.track)
|
|
trackfields.push(tupel.field.dbs);
|
|
}
|
|
var trackarray = [];
|
|
var oldjsvals = [];
|
|
if (updates.length && trackfields.length)
|
|
{
|
|
var sqlt = "SELECT xx." + trackfields.join(", xx.")
|
|
+ " FROM " + tabel + " xx"
|
|
+ " WHERE " + where;
|
|
var oRs = Oracle.Execute(sqlt);
|
|
for (i in tupels)
|
|
{
|
|
var tupel = tupels[i];
|
|
if (tupel.field.track)
|
|
{
|
|
switch (tupel.field.typ)
|
|
{
|
|
case "datetime":
|
|
case "date":
|
|
case "time":
|
|
// Waarde kan ook null zijn en moet dat dan ook blijven.
|
|
var oldjsval = (oRs(tupel.field.dbs).Value!=null? new Date(oRs(tupel.field.dbs).Value) : null);
|
|
break;
|
|
case "sql":
|
|
ERROR_CANNOT_TRACK_TYP_SQL;
|
|
default:
|
|
var oldjsval = oRs(tupel.field.dbs).Value;
|
|
}
|
|
var different = false;
|
|
switch (tupel.field.typ)
|
|
{
|
|
case "datetime":
|
|
case "date":
|
|
case "time":
|
|
// Beide waarden kunnen null zijn.
|
|
var different = (oldjsval !=null || tupel.jsval != null)
|
|
&& ((oldjsval == null && tupel.jsval != null)
|
|
|| (oldjsval != null && tupel.jsval == null)
|
|
|| (oldjsval.getTime() != tupel.jsval.getTime()))
|
|
|
|
break
|
|
case "memo":
|
|
case "varchar":
|
|
var different = (oldjsval||"") != (tupel.jsval||"");// bij Oracle tekst is null gelijk aan ""
|
|
break
|
|
default:
|
|
var different = oldjsval != tupel.jsval;
|
|
}
|
|
// Waarden converteren naar gebruikersvriendelijke teksten
|
|
if (typeof tupel.field.track == "string" && different)
|
|
{
|
|
var lbl = tupel.field.track;
|
|
// if (params.dialect_key)
|
|
// lbl = lcl.x(tupel.field.track, params.dialect_key);
|
|
if (tupel.field.buildTrackText)
|
|
var tracktxt = tupel.field.buildTrackText(tupel.field.typ, oldjsval, tupel.jsval, { foreign: tupel.field.foreign, oldjsvals: oldjsvals } );
|
|
else
|
|
var tracktxt = lbl + ": " + buildTrackText(tupel.field.typ, oldjsval, tupel.jsval, { foreign: tupel.field.foreign, oldjsvals: oldjsvals } );
|
|
trackarray.push( (params.includeName ? params.includeName + "; " : "") + tracktxt);
|
|
}
|
|
oldjsvals[tupel.field.dbs] = oldjsval;
|
|
}
|
|
}
|
|
oRs.Close();
|
|
}
|
|
|
|
if (!updates.length) // bijvoorbeeld als alle fields verwijzen naar een Form-parameter die niet is meegestuurd
|
|
{
|
|
__Log("Effectively nothing to update in buildTrackingUpdate?");
|
|
return { sql: "BEGIN NULL; END;", trackarray: [], oldjsvals: [] }
|
|
}
|
|
|
|
var sql = "UPDATE " + tabel + " xx"
|
|
+ " SET " + updates.join(", ")
|
|
+ " WHERE " + (where||"");
|
|
|
|
return { sql: sql, trackarray: trackarray, oldjsvals: oldjsvals };
|
|
}
|
|
|
|
function buildInsert(tabel, xfields, params)
|
|
{
|
|
params = params || {};
|
|
|
|
if (!params.noValidateToken) // Uit API's
|
|
protectRequest.validateToken(); // Alle _edit_ schermen horen IFACE.FORM_END aan het einde te hebben
|
|
|
|
if (xfields instanceof Array)
|
|
var fields = xfields;
|
|
else // Uit API2
|
|
{
|
|
var fields = [];
|
|
for (var fld in xfields)
|
|
fields.push(xfields[fld]);
|
|
}
|
|
|
|
var result = _buildFields(fields, params);
|
|
var tupels = result.tupels;
|
|
var first = true;
|
|
var cols = "",vals="";
|
|
var i;
|
|
var obj = [];
|
|
|
|
for (i=0; i < tupels.length; i++)
|
|
{
|
|
if (tupels[i].field.obj)
|
|
{ // Object typen hier verzamelen en later toevoegen aan cols en vals.
|
|
var objfield = tupels[i].field.dbs.split(".") // objfield = kolom_object.object_field
|
|
var obj_identifier = tupels[i].field.obj + "." + objfield[0]; // obj_identifier = object_type.object_field
|
|
if (!obj[obj_identifier])
|
|
obj[obj_identifier] = [];
|
|
obj[obj_identifier].push(objfield[1] + "=>" + tupels[i].sql);
|
|
}
|
|
else
|
|
{
|
|
if (tupels[i].field.dbs)
|
|
{
|
|
if (!first) { cols += ", "; vals += ", " };
|
|
first = false;
|
|
cols += tupels[i].field.dbs;
|
|
vals += tupels[i].sql;
|
|
}
|
|
}
|
|
}
|
|
|
|
// De verzamelde object type nog toevoegen aan cols en vals: OBJECT_TYPE(field1 => val1, field2 => val2).
|
|
for (var obj_i in obj)
|
|
{
|
|
if (cols != "") { cols += ", "; vals += ", " };
|
|
var obj_identifier = obj_i.split(".");
|
|
cols += obj_identifier[1];
|
|
vals += obj_identifier[0] + "(" + obj[obj_i] + ")";
|
|
}
|
|
|
|
var sql = "INSERT INTO "+tabel+"("+cols+") VALUES ("+vals+")";
|
|
return { sql: sql, sequences: result.sequences};
|
|
}
|
|
// Return new_price OR price +/- percentage
|
|
function calculatePrice(price, new_price)
|
|
{
|
|
if (new_price.match('%'))
|
|
{
|
|
return (price + price * parseFloat(new_price) / 100).toFixed(2);
|
|
}
|
|
else
|
|
{
|
|
if (new_price.match(/^-{2}|\+{2}/)) //match ++ or -- at beginning
|
|
{
|
|
return price + parseFloat(new_price.replace("++", "+").replace("--", "-"));
|
|
}
|
|
else
|
|
{
|
|
return new_price == "" ? new_price : parseFloat(new_price);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Bouw het field-array om naar { tupels: tupels, sequences: sequences }
|
|
// met tupels { dbs: veldnaam, jsval: js-value, sql: sql-value }
|
|
// en sequences[veldnaam] = seq-value
|
|
// alleen velden die in de Form-collection voorkwamen worden
|
|
// gebruikt
|
|
// params wordt nog niet gebruikt.
|
|
function _buildFields(fields, params, tabel, where)
|
|
{
|
|
params = params || {};
|
|
var tupels = [];
|
|
var sequences = [];
|
|
var i;
|
|
for (i=0; i < fields.length; i++)
|
|
{
|
|
var field = fields[i];
|
|
var val = field.val;
|
|
if (typeof field.savewhen != "boolean")
|
|
{
|
|
if (typeof field.savewhen == "string")
|
|
field.savewhen = Request.Form(field.savewhen).count > 0;
|
|
else if (field.frm)
|
|
{
|
|
if (field.typ=="check" || field.typ=="check0") // Zie iface.inc/CHECKBOX: we hebben een hidden field has_xxxx toegevoegd
|
|
field.savewhen = Request.Form("has_" + field.frm).count==1;
|
|
else
|
|
field.savewhen = Request.Form(field.frm).count > 0;
|
|
}
|
|
else
|
|
field.savewhen = true;
|
|
}
|
|
|
|
if (!field.savewhen)
|
|
continue; // helemaal niet opnemen
|
|
|
|
if (field.frm)
|
|
{
|
|
if (field.typ=="check" || field.typ=="check0")
|
|
{
|
|
var val = (Request.Form(field.frm).count==1);
|
|
}
|
|
else
|
|
{
|
|
var val = Request.Form(field.frm)(1);
|
|
}
|
|
}
|
|
if (field.seq)
|
|
{
|
|
var sql="select "+field.seq+".nextval from dual";
|
|
var oRs = Oracle.Execute( sql );
|
|
var seq_key = oRs(0).value;
|
|
oRs.Close();
|
|
sequences[field.dbs] = seq_key;
|
|
var val = seq_key;
|
|
}
|
|
|
|
var tupel = { field: field }; // 'teruggeven'
|
|
switch (field.typ)
|
|
{
|
|
case "sql":
|
|
{
|
|
tupel.sql = val;
|
|
break;
|
|
}
|
|
case "memo":
|
|
case "icon":
|
|
case "file":
|
|
case "color":
|
|
case "symbol":
|
|
case "varchar":
|
|
{
|
|
if (val == "" || val === null)
|
|
tupel.sql = " NULL"
|
|
else
|
|
{
|
|
var val2 = String(val);
|
|
val2 = val2.replace(/^\s+/,""); // trim spaties aan begin
|
|
val2 = val2.replace(/\s+$/,""); // trim spaties aan einde
|
|
tupel.jsval = val2;
|
|
tupel.sql = safe.quoted_sql(val2, field.len);
|
|
}
|
|
break;
|
|
}
|
|
case "key":
|
|
{ // Pas op: *zeer* sporadisch komt een key==0 voor!
|
|
if (val === "" || val === null || parseInt(val, 10)==-1)
|
|
tupel.sql = " NULL"
|
|
else
|
|
{
|
|
tupel.sql = parseInt(val, 10);
|
|
if (isNaN(tupel.sql))
|
|
abort_with_warning("Unexpected error: " + field.dbs + " is not a key but " + val);
|
|
}
|
|
break;
|
|
}
|
|
case "bool":
|
|
{
|
|
if (val == "" || val === null || val == "0")
|
|
tupel.sql = " NULL"
|
|
else
|
|
tupel.sql = " 1"
|
|
break;
|
|
}
|
|
case "number":
|
|
{
|
|
if (val === "" || val === null)
|
|
tupel.sql = " NULL"
|
|
else
|
|
{ tupel.sql = parseInt(val, 10);
|
|
if (isNaN(tupel.sql))
|
|
abort_with_warning("Unexpected error: " + field.dbs + " is not a number but " + val);
|
|
}
|
|
break;
|
|
}
|
|
case "float":
|
|
{
|
|
if (val === "" || val === null)
|
|
tupel.sql = " NULL"
|
|
else if (field.relativeValuesAllowed) // calculate (relative) price
|
|
{
|
|
var oldval_oRs = Oracle.Execute("SELECT " + field.dbs + " FROM " + tabel + " WHERE " + (where||""));
|
|
if (oldval_oRs.EOF)
|
|
{
|
|
tupel.sql = calculatePrice(0, val);
|
|
}
|
|
else
|
|
{
|
|
tupel.sql = calculatePrice(oldval_oRs(field.dbs).Value, val);
|
|
}
|
|
oldval_oRs.Close();
|
|
}
|
|
else
|
|
{
|
|
if (typeof val == "string")
|
|
val = val.replace(/,/g,".");
|
|
tupel.sql = parseFloat(val);
|
|
if (isNaN(tupel.sql))
|
|
abort_with_warning("Unexpected error: " + field.dbs + " is not a float but " + val);
|
|
}
|
|
break;
|
|
}
|
|
case "check":
|
|
case "check0":
|
|
{
|
|
if (val) // ((val && !field.inverse) || (!val && field.inverse))
|
|
tupel.sql = " 1"
|
|
else
|
|
tupel.sql = (field.typ == "check"? " NULL" : 0)
|
|
break;
|
|
}
|
|
case "date":
|
|
case "datetime":
|
|
{
|
|
if (val == "" || val === null)
|
|
tupel.sql = " NULL"
|
|
else
|
|
{
|
|
tupel.jsval = (val instanceof Date)?val:new Date(parseInt(val, 10));
|
|
tupel.sql = tupel.jsval.toSQL(field.typ=="datetime");
|
|
}
|
|
break;
|
|
}
|
|
case "time": // Laat datum-deel ongemoeid!!
|
|
{
|
|
if (val == "" || val === null)
|
|
tupel.sql = " TRUNC("+field.dbs+")";
|
|
else
|
|
{
|
|
tupel.jsval = (val instanceof Date)?val:new Date(parseInt(val, 10));
|
|
var tm = tupel.jsval.getHours()*60+tupel.jsval.getMinutes();
|
|
tupel.sql = " TRUNC("+field.dbs+") + " + tm + "/24/60";
|
|
}
|
|
break;
|
|
}
|
|
case "processingtime":
|
|
{
|
|
tupel.sql = " MLD_T_UITVOERTIJD(tijdsduur => {0}, eenheid => {1})".format(val.duration, safe.quoted_sql(val.unit));
|
|
break;
|
|
}
|
|
default: ERROR_UNSUPPORTED_FIELDTYP;
|
|
}
|
|
if (typeof tupel.jsval == "undefined")
|
|
{
|
|
if (tupel.sql == " NULL")
|
|
tupel.jsval = null;
|
|
else
|
|
tupel.jsval = tupel.sql; // default;
|
|
}
|
|
tupels.push(tupel);
|
|
}
|
|
return { tupels: tupels, sequences: sequences };
|
|
}
|
|
%> |