Files
Facilitor/APPL/CARE/custfunctions.wsc
Jos Groot Lipman 07a16dddcc Merge 2023.1 Gold D patches
svn path=/Website/trunk/; revision=60700
2023-06-08 13:34:13 +00:00

491 lines
22 KiB
XML

<?xml version="1.0"?>
<component>
<?component error="true" debug="true"?>
<registration
description="custfunctions"
progid="custfunction.wsc"
version="1.00"
classid="{C068EBA0-5AA9-438C-AD4F-8F909E5787C6}"
>
</registration>
<public>
<!-- properties -->
<property name="Oracle">
<put/>
</property>
<property name="__Log">
<put/>
</property>
<property name="__DoLog">
<put/>
</property>
<property name="safe">
<put/>
</property>
<!-- methods -->
<method name="mld_urenpostsave">
<PARAMETER name="prskey_array"/>
<PARAMETER name="datumarray"/>
<PARAMETER name="pResult"/>
</method>
<method name="mld_urenkostenpostsave">
<PARAMETER name="p_mld_opdruren_kosten_key"/>
<PARAMETER name="p_mld_opdruren_key"/>
<PARAMETER name="p_kosten_key"/>
<PARAMETER name="p_kosten"/>
<PARAMETER name="p_actie"/>
<PARAMETER name="pResult"/>
</method>
<method name="fclt_calc_dist_from_google">
<PARAMETER name="p_prs_perslid_key"/>
<PARAMETER name="p_mld_opdr_uren_datum"/>
<PARAMETER name="p_actie"/>
</method>
</public>
<script language="javascript">
<![CDATA[
/* properties */
function put_Oracle(newValue) {Oracle = newValue};
function put___Log(newValue) {__Log = newValue};
function put___DoLog(newValue) {__DoLog = newValue};
function put_safe(newValue) {safe = newValue};
/* methods */
/*
$Revision$
$Id$
File: CARE custfunction.wsc
*/
/* Dit zijn de enige drie functies die je mag gebruiken */
var Oracle;
var __Log;
var __DoLog;
var safe;
care_km_cache_days = 56; // we kunnen niet bij S() dus maar hard
function padout(number) { return (number < 10) ? "0" + number : number; }
Date.prototype.toSQL = function toSQL(withTime)
{
var str = padout(this.getDate()) + "-" + padout(this.getMonth() + 1) + "-" + padout(this.getFullYear())
if (withTime)
{
str += " " + padout(this.getHours()) + ":" + padout(this.getMinutes());
return "to_date(" + safe.quoted_sql(str) + ", 'DD-MM-YYYY HH24:MI')";
}
else
return "to_date(" + safe.quoted_sql(str) + ", 'DD-MM-YYYY')";
}
// CARE: doorloop de week van deze persoon en bepaal de dagtotaalkilometers
// om op te slaan in mld_opdruren_dagkosten
//mld_urenpostsave = function (prskey_array, datumarray, pResult) {
mld_urenpostsave = function (p_prs_key, p_datum, p_opdr_key, p_impropdr_key, p_actie, presult){
__Log('HOOKFUNCTION: mld_urenpostsave');
__Log('HOOKFUNCTION parameter p_prs_key='+p_prs_key);
__Log('HOOKFUNCTION parameter p_datum='+p_datum);
__Log('HOOKFUNCTION parameter p_opdr_key='+p_opdr_key);
__Log('HOOKFUNCTION parameter p_impropdr_key='+p_impropdr_key);
__Log('HOOKFUNCTION parameter p_actie='+p_actie);
if (p_actie == "DD"){
//Alleen bij verwijderen van uren waarbij kosten zaten, gaan we Google opnieuw raadplegen
l_result = fclt_calc_dist_from_google (p_prs_key, p_datum, "D");
}
return true;
}
//mld_urenpost2save = function (p_prskey, p_datumfrom, presult) {
// Log('NEW HOOKFUNCTION: mld_urenpostsave');
// Log('HOOKFUNCTION parameter p_prskey='+p_prskey);
// Log('HOOKFUNCTION parameter p_datumfrom='+p_datumfrom);
// return true;
//}
mld_urenkostenpostsave = function (p_mld_opdruren_kosten_key, p_mld_opdruren_key, p_kosten_key, p_kosten, p_actie, pResult){
__Log('HOOKFUNCTION: mld_urenKOSTENpostsave');
__Log('HOOKFUNCTION parameter p_mld_opdruren_kosten_key='+p_mld_opdruren_kosten_key);
__Log('HOOKFUNCTION parameter p_mld_opdruren_key='+p_mld_opdruren_kosten_key);
__Log('HOOKFUNCTION parameter p_kosten_key='+p_kosten_key);
__Log('HOOKFUNCTION parameter p_kosten='+p_kosten);
__Log('HOOKFUNCTION parameter p_actie='+p_actie);
var sql;
var oRs;
if (p_kosten_key == 1 || p_kosten_key == 2 || p_kosten_key == 3) // auto/bromfiets/fiets
{
sql=" select prs_perslid_key, mld_opdr_uren_datum" +
" from mld_opdr_uren" +
" where mld_opdr_uren_key = " + p_mld_opdruren_key;
oRs = Oracle.Execute(sql);
var l_prs_perslid_key = oRs("prs_perslid_key").Value;
var l_mld_opdr_uren_datum = new Date(oRs("mld_opdr_uren_datum").Value);
oRs.Close();
l_result = fclt_calc_dist_from_google (l_prs_perslid_key, l_mld_opdr_uren_datum, p_actie);
}
else {
// Andere kosten dan kilometers / fiets / bromfiets: doen we niets mee.
}
return true;
}
// Actie p_actie = I, U of D (insert/update/delete), andere codes werken niet (doen niets)
// p_prs_perslid_key is de key van de verzorger (route van verzorger)
// p_mld_opdr_uren_datum is de datum behorende bij de route (dag van de route)
fclt_calc_dist_from_google = function (p_prs_perslid_key, p_mld_opdr_uren_datum, p_actie)
{
p_mld_opdr_uren_datum = new Date(p_mld_opdr_uren_datum); // is binnen wsc anders een object?
// URL voor het berekenen van de dag-route
var oRs = Oracle.Execute("SELECT COALESCE(fac_setting_pvalue, fac_setting_default) fac_setting_value FROM fac_setting WHERE fac_setting_name = 'fg_maps_distance_apikey'");
var v_GoogleAPI_URL = "https://maps.googleapis.com/maps/api/directions/xml?key="+ oRs("fac_setting_value").Value;
oRs.Close();
// URL tbv het tonen van de dag-route
var v_url_google_maps = "https://maps.google.nl/maps";
var sql;
var oRs;
if (p_actie == "U") {
// Een update van kilometer is niet interessant om de kilometers opnieuw te berekenen, dus hier doen we dan niets!!
// NOOP
__Log("NOOP");
}
else{
if (p_actie == "I" || p_actie == "D") {
// Er zijn kilometers op de dag bijgeschreven (insert) of verwijderd (delete), dus de route opnieuw berekenen...
// Daartoe eerst de clienten verzamelen die VERZORGER op de DATUM met auto heeft bezocht.
//var sql="select verzorger, datum, adres, huisnr, woonplaats, prs_client_naam, prs_client_voorletters, client_adres, client_huisnr, client_woonplaats from care_v_km_weekbrief" +
// " where prs_perslid_key = "+ p_prs_perslid_key +
// " and datum =" + p_mld_opdr_uren_datum.toSQL() +
// " order by client_woonplaats";
// care_v_km_weekbrief bevat alleen auto-kilometers. Daarom view hieronder uitgeschreven
var sql = "SELECT v.prs_perslid_key,"
+ " v.prs_verzorger_naam || ',' || v.prs_verzorger_voorletters || ' ' || v.prs_verzorger_tussenvoegsel verzorger,"
+ " v.verzorger_adres adres,"
+ " v.verzorger_huisnr huisnr,"
+ " v.verzorger_postcode,"
+ " v.verzorger_woonplaats woonplaats,"
+ " uur.datum_gewerkt datum,"
+ " c.prs_client_naam,"
+ " c.prs_client_tussenvoegsel,"
+ " c.prs_client_voorletters,"
+ " c.client_adres,"
+ " c.client_huisnr,"
+ " c.client_postcode,"
+ " c.client_woonplaats"
+ " FROM care_v_totaal_uren_all uur, care_v_verzorger v, mld_opdruren_kosten ouk, mld_kosten k, mld_opdr o, mld_melding m, care_v_client c"
+ " WHERE uur.prs_perslid_key = v.prs_perslid_key"
+ " AND uur.mld_opdr_uren_key = ouk.mld_opdr_uren_key"
+ " AND ouk.mld_kosten_key = k.mld_kosten_key"
+ " AND k.mld_kosten_verwijder IS NULL"
// niet alleen auto's + " AND k.mld_kosten_code = 'A'"
+ " AND opdracht_type = 'P'"
+ " AND uur.opdracht_key=o.mld_opdr_key"
+ " AND o.mld_melding_key = m.mld_melding_key"
+ " AND m.prs_perslid_key = c.prs_client_key"
+ " AND v.prs_perslid_key = " + p_prs_perslid_key
+ " AND uur.datum_gewerkt= " + p_mld_opdr_uren_datum.toSQL()
+ " ORDER BY client_woonplaats";
oRs = Oracle.Execute(sql);
if (!oRs.Eof)
{
// Er is minimaal 1 client waar verzorger naar toe gaat op de dag, dus het record mld_opdruren_dagkosten inserten (nog niet aanwezig) of updaten (indien aanwezig)
// Laten we eerst Google Maps maar eens vragen naar het aantal kilometers...
__Log("Berekening op:" + oRs("datum").Value + " voor: " + oRs("verzorger").Value);
var l_huis=oRs("adres").Value + " " + oRs("huisnr").Value + ", " + oRs("verzorger_postcode").Value + " " + oRs("woonplaats").Value;
var v_url_google_huis1 = "?saddr=" + l_huis;
var v_url_google_huis2 = "+to:" + l_huis;
var v_url_google_route = "";
__Log ("Huis van verzorger: "+ l_huis);
var p_adresARR = new Array();
while (!oRs.eof)
{ var l_client_huis = oRs("client_adres").Value + " " + oRs("client_huisnr").Value + ", " + oRs("client_postcode").Value + " " + oRs("client_woonplaats").Value;
__Log ("Huis van client: " + l_client_huis);
if (p_adresARR.length == 0){
// Eerste keer: daddr-argument in de URL!!
v_url_google_route += "&daddr=" + encodeURIComponent(l_client_huis);
}
else{
// Volgende keren: :to in het daddr-argument (van de URL)!!!
v_url_google_route += "+to:" + encodeURIComponent(l_client_huis);
}
p_adresARR[p_adresARR.length]= l_client_huis;
oRs.MoveNext();
}
var v_db_url_google = v_url_google_maps + v_url_google_huis1 + v_url_google_route + v_url_google_huis2 + "&hl=nl";
// We proberen eerst de afstand uit de "cache" van maximaal 4 weken geleden te halen, zodat we niet van Google gebruik hoeven te maken.
__Log ("CACHING - Aantal dagen in het verleden: care_km_cache_days: " + care_km_cache_days);
var cached_OracleDistance = Get_Cached_OracleDistance(v_db_url_google, care_km_cache_days);
var l_afst = cached_OracleDistance.dagkosten;
var l_afstinter = cached_OracleDistance.inter_afstand;
// BONS#78434: 0 km gecached maar wel meerdere clienten is verdacht ==> opnieuw berekenen
if (l_afst == -1 || l_afstinter == -1 || (l_afstinter == 0 && p_adresARR.length > 1))
{
// Er is geen cache km in DB gevonden, laat Google maar eens rekenen...
// Return-codes van Get_OPTIMIZED_GoogleDistance:
// -2: Communicatiefout/connectieprobleem Google-server/internet
// -1: Een van de adressen (verzorger of client) is onbekend/kan niet door Google gevonden worden
// 0: Afstand = 0 km
// > 0: Aantal meters dat volgens Google gereden kan worden (optimaal).
l_afst = Get_OPTIMIZED_GoogleDistance(v_GoogleAPI_URL, l_huis, l_huis, p_adresARR, "");
__Log ("Google-afstand:" + l_afst + " meter");
l_afstinter = 0;
if (p_adresARR.length > 1)
{
l_afstinter = Get_interclient_GoogleDistance(v_GoogleAPI_URL, l_huis, l_huis, p_adresARR, "");
__Log ("Google-afstand interclient:" + l_afstinter + " meter");
}
}
else if (p_adresARR.length < 2)
{
l_afstinter = 0; // is in het verleden wel eens foutief gecached
}
var l_route = l_huis + " - " + v_url_google_route + " - " + l_huis;
l_route= l_route.replace('+to:' , ' - ');
l_route= l_route.replace('&daddr=' , ' - ');
sql=" select mld_opdruren_dagkosten_key" +
" from mld_opdruren_dagkosten" +
" where prs_perslid_key = "+ p_prs_perslid_key +
" and mld_opdruren_dagkosten_datum =" + p_mld_opdr_uren_datum.toSQL();
var oRs2 = Oracle.Execute(sql);
if (!oRs2.Eof)
{
// Registratie van dagtotaal bestaat al, dus een update...
// Hier een kilometer-berekening vanuit Google...
// Indien l_afst >= 0, dan een geldige afstandsberekening, dan is een van de adressen (verzorger/clienten) niet in orde, althans Google kan ze niet vinden
// agv b.v. spelfout in straatnaam is dan zeer waarschijnlijk.
// De kilometers worden op -1 (negatief getal) gezet (ongeldig cq. onbepaald).
// Via een rapport met filter hierop kan er door ADMIN van de CARE-klant een correcie op adresgegevens worden gedaan....
sql = " UPDATE mld_opdruren_dagkosten"
+ " SET mld_opdruren_dagkosten_totaal = " + l_afst
+ " , mld_opdruren_dagkosten_opm = " + safe.quoted_sql(v_db_url_google + "#" + l_afstinter)
+ " , mld_opdruren_dagkosten_aantal = " + p_adresARR.length
+ " WHERE mld_opdruren_dagkosten_key = " + oRs2("mld_opdruren_dagkosten_key").Value;
}
else
{
// Registratie van dagtotaal bestaat nog niet, dus een insert..
sql = "INSERT INTO mld_opdruren_dagkosten"
+ "( prs_perslid_key"
+ ", mld_opdruren_dagkosten_datum"
+ ", mld_opdruren_dagkosten_aantal"
+ ", mld_opdruren_dagkosten_totaal"
+ ", mld_opdruren_dagkosten_opm"
+ ")"
+ " VALUES "
+ "( " + p_prs_perslid_key
+ ", " + p_mld_opdr_uren_datum.toSQL()
+ ", " + p_adresARR.length
+ ", " + l_afst
+ ", " + safe.quoted_sql(v_db_url_google + "#" + l_afstinter)
+ ")";
}
oRs2.Close();
}
else
{
// Er zijn geen clienten meer die verzorger op die dag met de auto bezocht heeft...
// Dat betekent een simpele DELETE van het record mld_opdruren_dagkosten
// Als het goed is, moet de p_actie gelijk aan "D" zijn (er is een delete gedaan van de laatste kilometers op die dag
// hetzij direct de kilometers wissen of indirect, via een delete van de uren van die dag (die dan bijbehorende kilometers had).
sql = " DELETE FROM mld_opdruren_dagkosten"
+ " WHERE prs_perslid_key = " + p_prs_perslid_key
+ " AND mld_opdruren_dagkosten_datum = " + p_mld_opdr_uren_datum.toSQL();
}
oRs.Close();
// Hier volgt een INSERT, UPDATE of DELETE van mld_opdruren_dagkosten...
Oracle.Execute(sql);
}
}
return true;
}
// Parameters:
// p_db_url_google: exacte Google-URL voor een dagroute, indien deze tussen nu en p_aant_dagen geleden gevonden, dan levert deze functie het daarbij bijbehorende aantal kilometers op.
// p_aant_dagen: integer >=0, indien 0, dan geen limiet, en anders zoeken tot zoveel dagen terug
// JGL Ik zou verwachten dat elke p_aant_dagen de kilometers opnieuw worden berekend
// maar het is zo dat als binnen p_aant_dagen de cache wordt gebruikt de waarde nog
// p_aant_dagen dagen langer gebruikt wordt. Een regelmatige route wordt effectief *nooit*
// opnieuw berekend. Maar ach....
function Get_Cached_OracleDistance(p_db_url_google, p_aant_dagen)
{
var l_result = { dagkosten: -1 // Initieel -1, d.w.z. geen afstand in cache gevonden...
, inter_afstand: -1 // Deze route is nog niet bekend.
};
var wildurl = p_db_url_google.replace(/_/g, '\'_'); // Escape de underscore
wildurl = p_db_url_google.replace(/\%/g, '\\%'); // Escape de procent
var sql = "SELECT mld_opdruren_dagkosten_totaal"
+ " , mld_opdruren_dagkosten_datum"
+ " , mld_opdruren_dagkosten_opm"
+ " , prs_perslid_key"
+ " FROM mld_opdruren_dagkosten"
+ " WHERE mld_opdruren_dagkosten_opm LIKE " + safe.quoted_sql(wildurl + "#%") + " ESCAPE '\\'"
+ " AND mld_opdruren_dagkosten_totaal is not null"
+ " AND mld_opdruren_dagkosten_totaal >= 0"
+ (p_aant_dagen > 0 ? " AND TRUNC(mld_opdruren_dagkosten_datum) >= TRUNC(SYSDATE - " + p_aant_dagen + ")" : "")
+ " ORDER BY mld_opdruren_dagkosten_datum DESC";
var oRs = Oracle.Execute(sql);
if (!oRs.Eof)
{
// Er bestaat minimaal 1 gecach-te kilometer aantal
// Pak dan de laatste berekende/ingevulde stand...
l_result.dagkosten = oRs("mld_opdruren_dagkosten_totaal").Value;
var opm = oRs("mld_opdruren_dagkosten_opm").Value;
var afst = opm.substr(opm.indexOf("#")+1);
if (!isNaN(afst))
l_result.inter_afstand = afst;
__Log("----");
__Log("Kilometers uit cache");
__Log("Perslid_key:" + oRs("prs_perslid_key").Value);
__Log("Datum:" + oRs("mld_opdruren_dagkosten_datum").Value);
__Log("Afstand (meters):" + oRs("mld_opdruren_dagkosten_totaal").Value);
__Log("Afstand inter-client (meters):" + l_result.inter_afstand);
}
oRs.Close();
return (l_result);
}
// Parameters:
// p_locatie1 is start-node
// p_locatie2 is eind-node
// p_AdresArr zijn tussennodes
// p_output_xmlfile is logbestand xml, iniden "" dan geen logging, anders result-xml vanuit Google loggen
// Return-codes:
// -2: Communicatiefout/connectieprobleem Google-server/internet
// -1: Een van de adressen (verzorger of client) is onbekend/kan niet door Google gevonden worden
// 0: Afstand = 0 km
// > 0: Aantal meters dat volgens Google gereden kan worden (optimaal).
function Get_OPTIMIZED_GoogleDistance(p_GoogleAPI_URL, p_locatie1, p_locatie2, p_AdresArr, p_output_xmlfile){
if (p_AdresArr.length == 0){
l_result = 0}
else{
l_result = GetGoogleDistance(p_GoogleAPI_URL, p_locatie1, p_locatie2, p_AdresArr, 1, p_output_xmlfile);
}
return (l_result);
}
// Get_interclient_GoogleDistance: als minstens twee klanten dan de afstand van die route
// (zonder aanrijd/ terugrijd km van/naar huis)
// Return-codes:
// -2: Communicatiefout/connectieprobleem Google-server/internet
// -1: Een van de adressen (verzorger of client) is onbekend/kan niet door Google gevonden worden
// 0: Afstand = 0 km
// > 0: Aantal meters dat volgens Google gereden kan worden (optimaal).
function Get_interclient_GoogleDistance(p_GoogleAPI_URL, p_locatie1, p_locatie2, p_AdresArr, p_output_xmlfile)
{
if (p_AdresArr.length < 2)
{
l_result = 0
}
else
{
var eerste = p_AdresArr.shift();
var laatste = p_AdresArr.pop();
// Als er precies twee clienten waren is p_AdresArr nu leeg maar dat maakt niet uit
l_result = GetGoogleDistance(p_GoogleAPI_URL, eerste, laatste, p_AdresArr, 1, p_output_xmlfile);
}
return (l_result);
}
// Haal de XML van URL p_GoogleAPI_URL met p_locatie1 (=huis) en p_locatie2 (=huis), en een array van tussennodes (clienten)
// en sla op in bestand p_output_xmlfile (indien != "", als p_output_xmlfile =="" dan geen logging)
// Parameter optimize = 1 gaat Google vertellen om van de nodes de meest optimale route qua minst aantal km te berekenen).
function GetGoogleDistance(p_GoogleAPI_URL, p_locatie1, p_locatie2, p_AdresArr, p_optimize, p_output_xmlfile)
{
__Log({ from: p_locatie1, to: p_locatie2, waypoints: p_AdresArr });
var objXMLHTTP = new ActiveXObject("MSXML2.ServerXMLHTTP.6.0");
l_waypoints = p_AdresArr.join("|");
if (p_optimize == 1){
l_waypoints = "optimize:true|" + l_waypoints;
}
__Log(l_waypoints);
var l_GoogleAPI_URL = p_GoogleAPI_URL
+ '&origin=' + encodeURIComponent(p_locatie1)
+ '&destination=' + encodeURIComponent(p_locatie2)
+ '&waypoints=' + encodeURIComponent(l_waypoints)
objXMLHTTP.open("GET", l_GoogleAPI_URL, false);
objXMLHTTP.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
objXMLHTTP.send();
__Log("HTTP-status: " + objXMLHTTP.status);
if (objXMLHTTP.status==200)
{ // Geldigheid XML wordt gecontroleerd door GEN_IMPORT
__Log("Gelukt, status = " + objXMLHTTP.status);
if (p_output_xmlfile != ""){
oStream = new ActiveXObject("ADODB.Stream");
oStream.Open();
oStream.Type = 1; // adTypeBinary
oStream.Write(objXMLHTTP.responseBody); // responseText geeft encoding problemen!
oStream.SaveToFile (p_output_xmlfile, 2); // adSaveCreateOverWrite
oStream.Close();
}
var xmlnode;
var l_result = 0;
xmlResp = objXMLHTTP.responseXML;
statusnode = "DirectionsResponse/status";
l_status = xmlResp.selectSingleNode(statusnode);
if (l_status.text == "OK"){
for (var i=0; i<= p_AdresArr.length;i++){
xmlnode = "DirectionsResponse/route/leg[" + (i + 1) + "]/distance/value";
l_dist = xmlResp.selectSingleNode(xmlnode);
l_result = l_result + parseInt(l_dist.text);
}
}
else {
__DoLog("Maps aanroep faalde met " + l_status.text, "#FF00FF");
__DoLog(l_GoogleAPI_URL);
__DoLog(xmlResp.xml);
__DoLog({ from: p_locatie1, to: p_locatie2, waypoints: p_AdresArr });
l_result = -1;
}
return (l_result);
}
else
{
__Log("Mislukt, status = " + objXMLHTTP.status);
__Log(objXMLHTTP.statusText);
return(-2);
}
}
]]>
</script>
</component>