// ******************************************
// * $Id$
// *
// *   sendNotification()
// * Onderstaande functies worden alleen vanuit sendNotificatie aangeroepen:
// *   notificationMail()
// *   notificationSMS()
// *   notificationAPP()
// *   notificationSYS()
// *
// * Verstuur de notificaties voor putorders.
// *
// * Uses: scr="../wsf_shared.js"
// *       scr="./puo_settings.js"
// *       scr="./puo_shared.js
// *       scr="./puo_xmltools.js"
// *       scr="./puo_sendmail.js"
// *       src="./puo_sendsms.js"
// *       src="./puo_sendfile.js"
// *
// ******************************************
// Als ref_key meegeven dan alleen notificaties met die referentie (en module zoals afgeleid uit pcode) zonder delay
function sendNotification(ref_key, pcode, params)
{
    params = params || {};
    var puo_const = { STATUS_PORTAL: 1 // Niet via Putorders
                    , STATUS_EMAIL: 2
                    , STATUS_SMS:  4
                    , STATUS_POPUP: 8 // Niet via Putorders
                    , STATUS_SUMMARY_XSL: 16 // SMS/Email subject via XSL?
                    , STATUS_APPPUSH: 32 // Via Google Firebase
                    };

    var oAbout = new ActiveXObject("SLNKDWF.About");

    // De scheduled putorders
    Log2File(2, "** START sendNotification (" + toDateTimeString(new Date()) + ")");

    var sql = "SELECT COUNT(*) aantal,"
            + "       MIN(fac_notificatie_notbefore) eerste,"
            + "       MAX(fac_notificatie_notbefore) laatste"
            + "  FROM fac_notificatie"
            + " WHERE fac_notificatie_queue = 'DEFAULT'" // putorders doet alleen de DEFAULT queue
            + "   AND fac_notificatie_notbefore > SYSDATE"
            + "   AND (   BITAND (fac_notificatie_status, " + (puo_const.STATUS_EMAIL | puo_const.STATUS_SMS| puo_const.STATUS_APPPUSH) + ") > 0"
            + "        OR fac_notificatie_systeemadres IS NOT NULL"
            + "        OR prs_bedrijfadres_key IS NOT NULL)"

    var tmStart = oAbout.usTimer;
    var oRs = Oracle.Execute(sql);
    var tm = Math.round((oAbout.usTimer - tmStart) / 1000);
    if (tm > 500)
    {
        Log2File(1, "Skipping test took {0} ms".format(tm));
    }
    var aantalfuture = oRs("aantal").Value;
    var firstdatum = new Date(oRs("eerste").Value);
    var lastdatum = new Date(oRs("laatste").Value);

    if (aantalfuture)
    {
        Log2File(1, "{0} Skipping {1} delayed notifications for between {2} and {3}".format(toDateTimeString(new Date()), aantalfuture, toDateTimeString(firstdatum), toDateTimeString(lastdatum)));
        if (forceOrders)
            Log2File(1, "*But* parameter FORCE is given so sending anyway");
    }
    oRs.Close();

    var sqlmain
            = "SELECT prs_perslid_key_receiver"
            + "     , fac_notificatie_receiver_email"
            + "     , fac_notificatie_receiver_phone"
            + "     , fac_notificatie_oms"
            + "     , fac_notificatie_status"
            + "     , fac_notificatie_refkey"
            + "     , fac_notificatie_key"
            + "     , fac_srtnotificatie_xmlnode"
            + "     , fac_srtnotificatie_code"
            + "     , fac_notificatie_naam"
            + "     , fac_notificatie_notbefore"
            + "     , fac_srtnotificatie_srtkm_key"
            + "     , BITAND(fac_srtnotificatie_noticollegas, 1) noti_collegas"
            + "     , NVL(fac_notificatie_extrakey, -1) fac_notificatie_extrakey"
            + "     , fac_notificatie_sender_email"
            + "     , COALESCE(fac_notificatie_lang, 'NL') fac_notificatie_lang"
            + "     , fac_notificatie_systeemadres"
            + "     , fac_notificatie_attachments"
            + "     , prs_bedrijfadres_key"
            + "     , fac_notificatie_datum"
            + "     , fac_notificatie_failcount"
            + "     , prs_perslid_key_sender"
            + "     , fac_notificatie_geturl"
            + "     , fac_notificatie_getbody"
            + "     , prs_perslid_inactief"
            + "     , fac_notificatie_realuser" // voor eventuele overrules
            + "  FROM fac_notificatie f"
            + "     , fac_srtnotificatie fs"
            + "     , prs_perslid p"
            + " WHERE fac_notificatie_queue = 'DEFAULT'" // putorders doet alleen de DEFAULT queue
            + "   AND (   BITAND (f.fac_notificatie_status, " + (puo_const.STATUS_EMAIL | puo_const.STATUS_SMS| puo_const.STATUS_APPPUSH) + ") > 0"
            + "        OR f.fac_notificatie_systeemadres IS NOT NULL"
            + "        OR f.prs_bedrijfadres_key IS NOT NULL)"
            + "  AND NOT EXISTS (SELECT 1" // nooit een notificatie sturen als een oudere van dezelfde opdracht nog (steeds) faalt. Alleen voor bedrijfadressen
            + "                   FROM fac_notificatie oudere, fac_srtnotificatie ouderefs"
            + "                  WHERE oudere.fac_notificatie_key < f.fac_notificatie_key" // ouder
            + "                    AND oudere.prs_bedrijfadres_key = f.prs_bedrijfadres_key" // naar hetzelfde adres
            + "                    AND ouderefs.fac_srtnotificatie_key = oudere.fac_srtnotificatie_key"
            + "                    AND ouderefs.fac_srtnotificatie_xmlnode = fs.fac_srtnotificatie_xmlnode" // over dezelfde opdracht
            + "                    AND oudere.fac_notificatie_refkey = f.fac_notificatie_refkey)" //over dezelfde opdracht
            + "   AND f.prs_perslid_key_receiver = p.prs_perslid_key(+)"
            + "   AND f.fac_srtnotificatie_key = fs.fac_srtnotificatie_key(+)";

    var what_sql = [];
    if ((S("puo_flags") & 1) == 1) // Degene met email/sms/app
    {
        what_sql.push("BITAND (f.fac_notificatie_status, " + (puo_const.STATUS_EMAIL | puo_const.STATUS_SMS| puo_const.STATUS_APPPUSH) + ") > 0");
    }
    else
    {
        Log2File(1, "====== Skipping actual notification sending because of puo_flags&1==0");
    }

    if ((S("puo_flags") & 2) == 2)
    {
        what_sql.push("(f.fac_notificatie_systeemadres IS NOT NULL OR f.prs_bedrijfadres_key IS NOT NULL)");
    }
    else
    {
        Log2File(1, "====== Skipping actual order sending because of puo_flags&2==0");
    }

    if (!what_sql.length)
    {
        Log2File(1, "====== Nothing to do because of puo_flags, exiting");
        return;
    }
    sqlmain += " AND ({0})".format(what_sql.join(" OR "));

    var sql_puo = sqlmain
            + (!forceOrders? "   AND fac_notificatie_notbefore <= SYSDATE":"")
            + " ORDER BY CASE WHEN fac_notificatie_failcount = 0 THEN 0 ELSE 1 END," // falers altijd lagere prio
            + "          fac_notificatie_prioriteit NULLS LAST" // laag nummer is hoge prio
            + "        , fac_notificatie_datum"
            + "        , fac_notificatie_key";


    Log2File(3, sql_puo);

    var notiMAILed = 0;
    var notiSMSed  = 0;
    var notiAPPed  = 0;
    var notiSYSed  = 0;
    var notiPRSed  = 0;

    // Strikt genomen moet dit binnen de loop omdat er tijdens de loop
    // ongewenste notificaties kunnen zijn bijgekomen. Dat gaat me te ver
    {
        var sql = "BEGIN fac.fac_pre_putorders(); END;";
        Log2File(3, sql);
        try
        {   // we weten niet of pre_putorders bij de klant is gedefinieerd maar kunnen het wel timen
            var tmStart = oAbout.usTimer;
            Oracle.Execute(sql);
            var tm = Math.round((oAbout.usTimer - tmStart) / 1000);
            if (tm > 500)
            {
                Log2File(1, "pre_putorders took {0} ms".format(tm));
            }
        }
        catch(e)
        {
            Log2File(0, "fac.fac_pre_putorders failed: ({0})".format(e.description), "E");
            // Wel doorgaan opdat een putsystemnotificatie over dat falen eventueel wel verstuurd wordt
        }
    }

    var delayed = null;
    var lastrealuser = "";
    var lastnotificatie_key = -1;
    while (true)
    {
        var oRs = Oracle.Execute(sql_puo); // iedere keer opnieuw openen. Er kan een hogere prio notificatie tussengekomen zijn
        if (oRs.EOF) // niets (meer) te doen
        {
            oRs.Close();

            if (!delayed) // is er een notificatie die we nog niet direct mogen versturen (bijvoorbeeld een faler die we over twee uur opnieuw proberen)?
            {
                var sql2 = "SELECT MIN(fac_notificatie_notbefore) eerstvolgende"
                         + "  FROM ({0})".format(sqlmain);
                var oRs = Oracle.Execute(sql2);
                Log2File(3, sql2);
                if (oRs("eerstvolgende").Value != null)
                {
                    delayed = new Date(oRs("eerstvolgende").Value);
                }
                oRs.Close();
            }
            if (S("tsk_master_schema")) // Stoppen. De master start ons wel als het handig/ nodig is
            {
                if (S("puo_schedule_putorders") > 0)
                {
                    Log2File(1, "Putorders will be forced in {0} minute(s)".format(S("puo_schedule_putorders")));

                    var dtschedule = new Date();
                    dtschedule.setMinutes(dtschedule.getMinutes() + S("puo_schedule_putorders"));
                    if (!delayed || delayed > dtschedule)
                    {
                        delayed = dtschedule;
                    }
                }
                if (delayed)
                {
                    var sql2 = "BEGIN tsk.starttask(p_taskcode => 'PUTORDERS', p_nextrun => {0}); END;".format(delayed.toSQL(true, true));
                    Log2File(3, sql2);
                    Oracle.Execute(sql2);
                }
                // Taak was al wel verwijderd
            }
            break; // uit de loop
        }

        if (lastnotificatie_key == oRs("fac_notificatie_key").value)
        {
            // 1 minuut uitstellen om bij zeer ernstig falen verderop te voorkomen dat we in een heel strakke loop komen
            if (typeof WScript != 'undefined')
            {
                WScript.Echo("Strange, no progress for notification {0}. Napping for 60 seconds".format(lastnotificatie_key));
            }
            var oAbout = new ActiveXObject("SLNKDWF.About");
            oAbout.Sleep(60*1000);
            Log2File(0, "Strange, no progress for notification {0}. I took a nap for 60 seconds".format(lastnotificatie_key));
        }
        lastnotificatie_key = oRs("fac_notificatie_key").value;

        delayed = null;

        Log2File(2, "\n\n" + Fill(100, "="));
        Log2File(1, "\n== Notificatie " + oRs("fac_notificatie_key").value + "; "
                  + oRs("fac_srtnotificatie_code").value + " " + oRs("fac_notificatie_refkey").value + "; "
                  + (oRs("fac_notificatie_naam").Value && oRs("fac_notificatie_naam").Value != String(oRs("fac_notificatie_refkey").value) ? oRs("fac_notificatie_naam").Value + " ": "")
                  + (oRs("fac_srtnotificatie_srtkm_key").value?"attach_srtkenmerkkey " + oRs("fac_srtnotificatie_srtkm_key").value + " ": "")
                  + "(" + toDateTimeString(new Date()) + ")"
                  + (params.userident ? " user: " + params.userident : "")
                 );

        // Was ik een beetje op tijd volgens planning?
        if (oRs("fac_notificatie_failcount").Value == 0)
        {
            var notbefore = new Date(oRs("fac_notificatie_notbefore"));
            var late = Math.round((new Date().getTime() - notbefore.getTime()) / 1000);
            if (late > 5)
            {
                Log2File(1, "Notbefore was {0}, we are {1} seconds late".format(toDateTimeString(notbefore), late));
            }
        }
        var realuser = oRs("fac_notificatie_realuser").Value;
        if (realuser && realuser != lastrealuser)
        {
            Log2File(1, "Switching to custenv.wsc overrules by " + realuser);
            if (realuser.indexOf("@") > -1 && typeof WScript != 'undefined') // AAREON\JOSGL@/trunk
            {
                rooturl = realuser.split("@")[1]; // '/trunk'
                if (rooturl && !WScript.ScriptFullName.toLowerCase().replace(/\\/g, "/").match(rooturl.toLowerCase() + "/"))
                {
                    Log2File(1, "Putorders is running in {0}, notification origin is {1}.\nThis may not be what you expected".format(WScript.ScriptFullName, rooturl));
                }
                realuser = realuser.split("@")[0];
            }
            var domain = realuser.split("\\")[0];
            var username = realuser.split("\\")[1];
            tryOverrules(domain, username);
            lastrealuser = realuser;
        }
        if (oRs("prs_perslid_inactief").Value != null)
        {
            var upd_p = "UPDATE fac_notificatie"
                      + "   SET fac_notificatie_status = 0"
                      + " WHERE fac_notificatie_key = " + oRs("fac_notificatie_key").Value;
            Log2File(3, upd_p);
            Oracle.Execute(upd_p);
            Log2File(2, "Inactive receiver: " + oRs("fac_notificatie_receiver_email").Value);
        }
        else
        {
            var XMLnode = oRs("fac_srtnotificatie_xmlnode").value || "";
            var NotificationXSL = getXslName(XMLnode);

            notiMAILed += notificationMail(oRs, NotificationXSL, puo_const);
            notiSMSed  += notificationSMS (oRs, NotificationXSL, puo_const);
            notiAPPed  += notificationAPP (oRs, NotificationXSL, puo_const);

            notiSYSed  += notificationSYS (oRs, puo_const);
            if (oRs("prs_bedrijfadres_key").Value > 0)
            {
                var nn_success = notificationPRS (oRs, puo_const);
                if (nn_success)
                {
                    notiPRSed  += nn_success;
                }
            }
        }

        // Onszelf alvast opruimen, bitje STATUS_POPUP kan nog over zijn
        var sql2 = "DELETE fac_notificatie"
                 + " WHERE fac_notificatie_status IN (0, 16)" // STATUS_SUMMARY_XSL 16 is niet interessant
                 + "   AND fac_notificatie_systeemadres IS NULL"
                 + "   AND prs_bedrijfadres_key IS NULL"
                 + "   AND fac_notificatie_key = " + oRs("fac_notificatie_key").value;
        Log2File(3, sql2);
        Oracle.Execute(sql2);

        Log2File(2, Fill(100, "=") + "\n\n");

        oRs.Close();
    }

    if (ref_key > 0 && pcode)
    {
        // Zal altijd '1' zijn als we hier komen
    }
    else
    {
        if (notiMAILed > 0) Log2File(1, " " + notiMAILed + " email messages sent (using smtp server {0}:{1})".format(S("puo_smtpserver"), S("puo_smtpserverport")));
        if (notiSMSed > 0)  Log2File(1, " " + notiSMSed  + " SMS messages sent");
        if (notiAPPed > 0)  Log2File(1, " " + notiAPPed  + " APP notifications sent");
        if (notiSYSed > 0)  Log2File(1, " " + notiSYSed  + " systemadres messages sent");
        if (notiPRSed > 0)  Log2File(1, " " + notiPRSed  + " prs_bedrijfadres messages sent");
    }
}

var v_aanduiding = "";
function notificationMail(rec, p_notificationXSL, params)
{
    // ======================== 2=mail ========================
    Log2File(2, "\n*> notificationMail");
    var noti_mailed = 0;
    try
    {
        var receiver_email       = rec("fac_notificatie_receiver_email").value || "";
        var sender_email         = rec("fac_notificatie_sender_email").value || "";
        var attach_refkey        = rec("fac_notificatie_refkey").value;
        var attach_srtkenmerkkey = rec("fac_srtnotificatie_srtkm_key").value;
        var srtcode              = rec("fac_srtnotificatie_code").value || "";
        var xmlnode              = rec("fac_srtnotificatie_xmlnode").value || "";

        var geturl               = rec("fac_notificatie_geturl").Value;
        var getbody              = rec("fac_notificatie_getbody").Value;
        var prs_perslid_key_receiver = rec("prs_perslid_key_receiver").Value;
        var noti_collegas        = rec("noti_collegas").Value;

v_aanduiding = "notificationMail 1";
        if (rec("fac_notificatie_status").value & params.STATUS_EMAIL)  // bitwise AND
        {
            var cc_arr = [];
            if (noti_collegas && prs_perslid_key_receiver)
            {
                var sql_noti = "SELECT p.prs_perslid_email"
                             + "  FROM prs_perslid p"
                             + "     , (SELECT c.prs_perslid_key_alt  prs_vervanger"
                                   + "       , c.prs_perslid_key      prs_ontvanger"
                                   + "    FROM prs_collega c"
                                   + "  UNION"
                                   + "  SELECT c.prs_perslid_key	  prs_vervanger"
                                   + "       , r.prs_perslid_key      prs_ontvanger"
                                   + "    FROM fac_gebruikersgroep r"
                                   + "       , fac_gebruikersgroep c"
                                   + "       , fac_groep g"
                                   + "   WHERE r.fac_groep_key	= c.fac_groep_key"
                                   + "     AND r.fac_groep_key = g.fac_groep_key"
                                   + "     AND g.fac_groep_collega = 1"
                                   + " ) k"
                             + " WHERE k.prs_vervanger = p.prs_perslid_key"
                             + "   AND k.prs_ontvanger = " + prs_perslid_key_receiver;

                var oRs_noti = Oracle.Execute(sql_noti);
                while (!oRs_noti.eof)
                {
                    var noti_cc = oRs_noti("prs_perslid_email").Value||"";
                    if (noti_cc != "")
                    {
                        cc_arr.push(noti_cc);
                    }
                    oRs_noti.MoveNext();
                }
                oRs_noti.Close();
            }
v_aanduiding = "notificationMail 2";
            var mail_params = { attachFileName: ""
                              , attachments: []
                              , cc: cc_arr.join(";")
                              };
            if (geturl) // Fetch data from url to mail
            {
v_aanduiding = "notificationMail 3";
                if (!S("puo_fclt_web_url"))
                {
                    throw { description: "XXXX found in XML but puo_fclt_web_url not set." };
                }
                //var geturl = "appl/fac/fac_report.asp?showall=1&outputmode=1&usrrap_key=8&viewname=fac_v_rap_auditusage&mode=list&columns=naam%2Cfclt_f_login%2Cfclt_f_groep%2Caantal_rechten&groupby=%2C%2C%2C&scf_pivot=0&fclt_f_login=&fclt_f_groep="
                //var geturl = "api2/reports.csv?usrrap_key=1081"; // 1081 is slapende meldingen
                var fac_web_url = S("puo_fclt_web_url") + geturl + "&fac_id=" + customerId;
                Log2File(1, "Fetching " + fac_web_url);
                var url = fac_web_url //+ "&APIKEY=" + S("puo_fclt_web_apikey");

                Log2File(1, "using context of prs_perslid_key " + prs_perslid_key_receiver);
                var jwt = getBearerToken(prs_perslid_key_receiver, "_INTERNAL", 30);

                var http_request = doHTTP(url, { method: getbody?"POST":"GET",
                                                 data: getbody,
                                                 headers: { "accept": "application/html", // html is voorkeur maar we kunnen meer aan
                                                            "Authorization" : "Bearer " + jwt
                                                          }
                                               });
                var strResult = http_request.responseText;
                var contentType = /*global*/ lastContentType || "";
                Log2File(1, "Got " + contentType);
                var ext = "txt";
                var isHTML = contentType.match(/text\/html/);
                if (isHTML)
                {
                    ext = "html"
                    var strResult = strResult.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "<!-- stripped script -->");
                    var strResult = strResult.replace(/<link rel=.*>/gi, "<!-- stripped css -->");
                }
                else if (contentType.match(/text\/csv/))
                {
                    ext = "csv";
                }
                else if (contentType.match(/application\/json/))
                {
                    ext = "json";
                    try
                    {
                        var jresult = JSON.parse(strResult);
                    }
                    catch (e)
                    {
                        throw { description: "Weird: could not parse JSON: {0}".format(strResult)};
                    }
                    if ("tmpxlsx" in jresult)
                    {
                        var tmpxlsx = custabspath + "/../../temp/" + customerId + "/" + jresult.tmpxlsx;
                        mail_params.include_cust_file = tmpxlsx;
                        mail_params.tempdelete = jresult.deletefile;
                        ext = "xlsx";
                    }
                }
                mail_params.attachFileName = "Facilitor_{0}.{1}".format(toDateTimeString(new Date()), ext);
                sendMail( sender_email
                        , receiver_email
                        , rec("fac_notificatie_oms").Value // body
                        , isHTML?"":rec("fac_notificatie_oms").Value // body
                        , mail_params.include_cust_file?"":strResult // bodyhtml
                        , mail_params
                        );
                // TODO: eventueel tmpxlsx opruimen
            }
            else if (!rec("fac_srtnotificatie_xmlnode").value)
            {
v_aanduiding = "notificationMail 4";
                Log2File(2, "Text-only notificatie");
                var subject = rec("fac_notificatie_oms").Value;
                var body = subject;
                var htmlbody = "";
                if (subject.indexOf("<br>") > 0)
                {
                    var body = "";
                    var htmlbody = subject.substr(subject.indexOf('<br>') + 4); // de rest
                    var subject = subject.split('<br>', 1)[0]; // alleen tot 1e <br> in de subject
                }
                sendMail( sender_email
                        , receiver_email
                        , subject
                        , body
                        , htmlbody
                        , mail_params
                        );
            }
            else
            {
v_aanduiding = "notificationMail 5";
                mail_params.fcltid =  rec("fac_srtnotificatie_xmlnode").value + ":" + rec("fac_notificatie_refkey").value; // komt in message header X-FCLT-fcltid
                if (rec("fac_notificatie_extrakey").value > 0)
                    mail_params.fcltid +=  ":" + rec("fac_notificatie_extrakey").value;

                // Errors in de generatie van de XML worden afgevangen in fetchXMLContent
                // De functie levert dan een lege string, de notificatie wordt dan als verzonden
                // afgehandeld
                var xml_content = fetchXMLContent( rec("fac_srtnotificatie_xmlnode").value
                                                 , rec("fac_notificatie_refkey").value
                                                 , rec("fac_notificatie_extrakey").value
                                                 , ""
                                                 , rec("fac_notificatie_lang").value
                                                 , {
                                                      srtnotificatie: rec("fac_srtnotificatie_code").value,
                                                      notificatie_key: rec("fac_notificatie_key").Value }
                                                 );

v_aanduiding = "notificationMail 5a";
                if (xml_content)
                {
                    if (attach_srtkenmerkkey > 0 && xmlnode == "melding") // alleen voor MLDAFM en MLDAFR
                    {
                       var sqlkenmerk = "SELECT vk.mld_kenmerk_key"
                                      + "  FROM mld_kenmerk vk"
                                      + "     , mld_melding m"
                                      + "     , mld_stdmelding s"
                                      + "     , mld_discipline d"
                                      + " WHERE m.mld_melding_key = " + attach_refkey
                                      + "   AND vk.mld_srtkenmerk_key = " + attach_srtkenmerkkey
                                      + "   AND s.mld_stdmelding_key = m.mld_stdmelding_key"
                                      + "   AND s.mld_ins_discipline_key = d.ins_discipline_key"
                                      + "   AND ((vk.mld_stdmelding_key = s.mld_stdmelding_key     AND vk.mld_kenmerk_niveau = 'S')"
                                      + "     OR (vk.mld_stdmelding_key = s.mld_ins_discipline_key AND vk.mld_kenmerk_niveau = 'D')"
                                      + "     OR (vk.mld_stdmelding_key = d.ins_srtdiscipline_key  AND vk.mld_kenmerk_niveau = 'T'))";
                        Log2File(3, sqlkenmerk);
                        var oRs = Oracle.Execute(sqlkenmerk);
                        if (!oRs.Eof)
                        {
                            mail_params.module = "MLD";
                            mail_params.refkey = attach_refkey;
                            mail_params.kenmerk_key = [];
                            while (!oRs.Eof)
                            {
                                mail_params.kenmerk_key.push(oRs("mld_kenmerk_key").Value);
                                oRs.MoveNext();
                            }
                        }
                        oRs.Close();
                    }

                    var SubjectText = "";
                    var SubjectTextXSL = "";
                    //
                    Log2File(2, "XSL file used=" + p_notificationXSL);
                    SubjectText = rec("fac_notificatie_oms").value;
v_aanduiding = "notificationMail 5aa";

                    strResult = XML2HTML( xml_content
                                        , p_notificationXSL
                                        , rec("fac_srtnotificatie_code").value
                                        , "email"
                                        );

                    var icsResult = ""; // default geen ics
                    if (strResult.indexOf("<!--ADDICS-->") > -1) // <xsl:comment>ADDICS</xsl:comment>
                    {
                        icsResult = XML2HTML( xml_content
                                            , p_notificationXSL
                                            , rec("fac_srtnotificatie_code").value
                                            , "ics"
                                            );
                    }

                    if (rec("fac_notificatie_status").value & params.STATUS_SUMMARY_XSL)
                    {
v_aanduiding = "notificationMail 5b";
                        // Via XSL
                        SubjectTextXSL = XML2HTML( xml_content
                                                 , p_notificationXSL
                                                 , rec("fac_srtnotificatie_code").value
                                                 , "summary"
                                                 );
                        Log2File(2, "SubjectText na vertaling" + SubjectTextXSL);
                        if (SubjectTextXSL)
                        {
                            SubjectText = SubjectTextXSL;
                        }
                    }
                    //
                    mail_params.notimode = "email";
                    mail_params.srtnotificatie = rec("fac_srtnotificatie_code").value;

                    if (S("puo_notificationinmailbody"))
                    {
                        Log2File(2, "Mailnotificatie in de body");
                        // In de body
                        var attachment_str = rec("fac_notificatie_attachments").value || "";
                        if (attachment_str)
                        {
                            attach_arr = attachment_str.split("|");
                            var isBijlageKey = !isNaN(parseInt(attach_arr[0]));
                            if (attach_arr.length && isBijlageKey)
                            {   // attachments worden doorgegeven met een bijlagen_key
                                for (i=0; i<attach_arr.length; i++)
                                {   // array van objecten met bijlagen_key
                                    mail_params.attachments.push( { bijlagen_key: parseInt(attach_arr[i]) });
                                }
                            }
                            else if (attach_arr.length)
                            {   // array met slechts 1 element die path-string bevat
                                mail_params.attachments_path = attach_arr;
                            }
                        }
                        mail_params.attachics = icsResult;
v_aanduiding = "notificationMail 5c";
                        sendMail( sender_email
                                , receiver_email
                                , SubjectText
                                , ""
                                , strResult
                                , mail_params
                                );
                    }
                    else
                    {
                        var startPos = strResult.indexOf("qrc=") + 4;
                        var imgstart = strResult.lastIndexOf("<img", startPos); // moet wel binnen een <img> vallen
                        var imgend   = strResult.indexOf(">", imgstart);
                        var quote = strResult.substr(startPos, 1);
                        var eindPos =  strResult.indexOf(quote, startPos + 2);
                        if (startPos > 4 && eindPos > startPos && imgstart > 0 && imgend > startPos)
                        {
                            var qrc = strResult.substring(startPos + 1, eindPos);
                            qrc = qrc.replace(/\&amp;/g, "&"); // Het was nog HTML/XML-encoded
                            var xc = new ActiveXObject("SLNKDWF.QRCode");
                            xc.Text = qrc;
                            __Log("Creating QRC: " + qrc);
                            var oXML = new ActiveXObject("Msxml2.DOMDocument.6.0");
                            var oNode = oXML.createElement("encodeddata");
                            oNode.dataType = "bin.base64"; // Zeer snelle oplossing
                            oNode.nodeTypedValue = xc.GetAsPNG();
                            var b64 = oNode.text;

                            var newbody = strResult.substr(0, startPos - 4) + "src=\"data:image/png;base64," + b64 + "\"" + strResult.substr(eindPos + 1);
                            strResult = newbody;
                        }

                        Log2File(2, "Mailnotificatie als attachment");
                        mail_params.attachFileName = "Facilitor.html";
v_aanduiding = "notificationMail 6";
                        sendMail( sender_email
                                , receiver_email
                                , SubjectText
                                , "Zie HTML attachment"
                                , strResult
                                , mail_params
                                );
                    }
v_aanduiding = "notificationMail 7";
                    // trackaction of sent mail
                    var sqlSrtNotificatie = "SELECT fac_srtnotificatie_code"
                                          + "  FROM fac_srtnotificatie"
                                          + " WHERE fac_srtnotificatie_code LIKE '%TRK'"
                                          + "   AND fac_srtnotificatie_code <> 'MESTRK'"
                                          + "   AND fac_srtnotificatie_xmlnode IN (SELECT sn.fac_srtnotificatie_xmlnode FROM fac_srtnotificatie sn"
                                                                               + " WHERE sn.fac_srtnotificatie_code='" + srtcode + "')";
                    var oRs = Oracle.Execute(sqlSrtNotificatie);
                    if (!oRs.Eof)
                    {
                      // Ook eventuele bijlagen loggen.
                      var bijlagen_naam = [];
                      if (mail_params.attachments.length)
                      {
                        var bijlagen_keys = [];
                        for (var i=0; i<mail_params.attachments.length; i++)
                        {
                          bijlagen_keys.push(mail_params.attachments[i].bijlagen_key);
                        }
                        var sql_b = "SELECT fac_bijlagen_filename FROM fac_bijlagen where fac_bijlagen_key IN (" + bijlagen_keys.join(",") + ")";
                        var oRs_b = Oracle.Execute(sql_b);
                        while (!oRs_b.eof)
                        {
                          bijlagen_naam.push(oRs_b("fac_bijlagen_filename").Value);
                          oRs_b.MoveNext();
                        }
                        oRs_b.Close();
                      }
                      if (mail_params.attachments_path)
                      {
                        bijlagen_naam.push(mail_params.attachments_path);
                      }

                      var paction = "#" + oRs("fac_srtnotificatie_code").Value;
                      // Let op: sender_email kan overruled zijn in sendMail!
                      var txt = S("puo_lcl_tracknoti").format(srtcode, receiver_email, SubjectText, sender_email);
                      txt = txt + (bijlagen_naam.length ? "\nAttachment(s): " + bijlagen_naam.join("; ") : "");
                      var sql = "BEGIN fac.trackaction({0}, {1}, NULL, NULL, {2}); END;".format(safe.quoted_sql(paction), refkeyOrExtrakey(rec), safe.quoted_sql(txt));
                      Oracle.Execute(sql);
                    }
                    oRs.Close();
                    Log2File(2, "Mail sent");
                }
            }
            noti_mailed++;
        }
    }
    catch(e)
    {
        Log2File(0, "v_aanduiding: " + v_aanduiding);
        var severity = "E";
        if (String(e.description).indexOf("The parameter is incorrect") > -1)
        {
            severity = "I";
            Log2File(0, "'The parameter is incorrect' detected. Lowering severity to 'I' to prevent putsystemnotification e-mail explosion (UWVA#89050)");
        }
        Log2File(0, toDateTimeString(new Date()) + " Error in SendNotification/MAIL (using smtp server {0}:{1})\n{2}".format(S("puo_smtpserver"), S("puo_smtpserverport"), e.description), severity);
        // Wel doorvallen naar wissen bitjes: we blijven notificaties niet tot in den treure proberen
    }
    finally
    {
        // == DONE MAIL ==
        if (clearNotifications)
        {
            // Let op: bitwise AND en NOT controle.
            var controle = (255 & ~params.STATUS_EMAIL & ~params.STATUS_SUMMARY_XSL);
            var sql = "UPDATE fac_notificatie"
                    + "   SET fac_notificatie_status = BITAND (fac_notificatie_status, " + controle + ")"
                    + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value;
            Log2File(3, sql);
            Oracle.Execute(sql);
        }
        else
            Log2File(1, "Parameter KEEP given, *not* clearing email notification " + rec("fac_notificatie_key").value);
    }
    return noti_mailed;
}


function notificationSMS(rec, p_notificationXSL, params)
{
    // ======================== 4=SMS ========================
    Log2File(2, "\n*> notificationSMS");
    var noti_smsed = 0;
    try
    {
        if (rec("fac_notificatie_status").value & params.STATUS_SMS)  // bitwise AND
        {
            var fac_notificatie_receiver_phone = rec("fac_notificatie_receiver_phone").value;

            var SMSText = rec("fac_notificatie_oms").value;
            var SMSTextXSL = "";

            if ((rec("fac_notificatie_status").value & params.STATUS_SUMMARY_XSL) && (rec("fac_srtnotificatie_xmlnode").value))
            {
                // Errors in de generatie van de XML worden afgevangen in fetchXMLContent
                // De functie levert dan een lege string, de notificatie wordt dan als verzonden
                // afgehandeld
                var xml_content = fetchXMLContent( rec("fac_srtnotificatie_xmlnode").value
                                                 , rec("fac_notificatie_refkey").value
                                                 , rec("fac_notificatie_extrakey").value
                                                 , ""
                                                 , rec("fac_notificatie_lang").value
                                                 , { srtnotificatie: rec("fac_srtnotificatie_code").value,
                                                     notificatie_key: rec("fac_notificatie_key").Value
                                                  }
                                                 );

                if (xml_content)
                {
                    Log2File(2, "XSL file used=" + p_notificationXSL)
                    SMSTextXSL = XML2HTML( xml_content
                                         , p_notificationXSL
                                         , rec("fac_srtnotificatie_code").value
                                         , "summary"
                                         );
                    Log2File(2, "SMSText na vertaling" + SMSTextXSL);
                    if (SMSTextXSL)
                    {
                        SMSText = SMSTextXSL;
                    }
                }
            }

            var smsResult = sendSMS( fac_notificatie_receiver_phone
                                   , SMSText
                                   );
            if (smsResult)
            {
                Log2File(2, "SMS sent");
                noti_smsed++;
            }
        }
    }
    catch(e)
    {
        Log2File(0, toDateTimeString(new Date()) + " Error in SendNotification/SMS: " + e.description, "E");
        // Wel doorvallen naar wissen bitjes: we blijven notificaties niet tot in den treure proberen
    }
    finally
    {
        // == DONE SMS ==
        if (clearNotifications)
        {
            // Let op: bitwise AND en NOT controle.
            var controle = (255 & ~params.STATUS_SMS & ~params.STATUS_SUMMARY_XSL);
            sql = "UPDATE fac_notificatie"
                + "   SET fac_notificatie_status = BITAND (fac_notificatie_status, " + controle + ")"
                + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value;
            Log2File(3, sql);
            Oracle.Execute(sql);
        }
        else
            Log2File(1, "Parameter KEEP given, *not* clearing SMS notification " + rec("fac_notificatie_key").value);
    }

    return noti_smsed;
}

function notificationAPP(rec, p_notificationXSL, params)
{
    // ======================== 4=APP ========================
    Log2File(2, "\n*> notificationAPP");
    var noti_apped = 0;
    try
    {
        if (rec("fac_notificatie_status").value & params.STATUS_APPPUSH)  // bitwise AND
        {
            var prs_perslid_key_receiver = rec("prs_perslid_key_receiver").value;

            var APPText = rec("fac_notificatie_oms").value;
            var APPTextXSL = "";
            var APPurl = "";

            if (rec("fac_srtnotificatie_xmlnode").value)
                APPurl = "?u=" + rec("fac_srtnotificatie_xmlnode").value + "&k=" + rec("fac_notificatie_refkey").value;

            if ((rec("fac_notificatie_status").value & params.STATUS_SUMMARY_XSL) && (rec("fac_srtnotificatie_xmlnode").value))
            {

                // Errors in de generatie van de XML worden afgevangen in fetchXMLContent
                // De functie levert dan een lege string, de notificatie wordt dan als verzonden
                // afgehandeld
                var xml_content = fetchXMLContent( rec("fac_srtnotificatie_xmlnode").value
                                                 , rec("fac_notificatie_refkey").value
                                                 , rec("fac_notificatie_extrakey").value
                                                 , ""
                                                 , rec("fac_notificatie_lang").value
                                                 , { srtnotificatie: rec("fac_srtnotificatie_code").value }
                                                 );

                if (xml_content)
                {
                    Log2File(2, "XSL file used=" + p_notificationXSL)
                    APPTextXSL = XML2HTML( xml_content
                                         , p_notificationXSL
                                         , rec("fac_srtnotificatie_code").value
                                         , "summary"
                                         );
                    Log2File(2, "APPText na vertaling" + APPTextXSL);
                    if (APPTextXSL)
                    {
                        APPText = APPTextXSL;
                    }
                }
            }

            var appResult = sendAPP( prs_perslid_key_receiver
                                   , APPText
                                   , APPurl
                                   , { // geef wat handige informatie door (zo lang we nog geen stylesheet achtige oplossing hebben
                                        "receiverkey" : prs_perslid_key_receiver,
                                        "xmlnode"     : rec("fac_srtnotificatie_xmlnode").value,
                                        "code"        : rec("fac_srtnotificatie_code").value,
                                        "refkey"      : rec("fac_notificatie_refkey").value,
                                        "extrakey"    : rec("fac_notificatie_extrakey").value,
                                        "lang"        : rec("fac_notificatie_lang").value
                                     }
                                   );
            if (appResult)
            {
                Log2File(2, "APP sent");
                noti_apped++;
            }
        }
    }
    catch(e)
    {
        Log2File(0, toDateTimeString(new Date()) + " Error in SendNotification/APP: " + e.description, "E");
        // Wel doorvallen naar wissen bitjes: we blijven notificaties niet tot in den treure proberen
    }
    finally
    {
        // == DONE APP ==
        if (clearNotifications)
        {
            // Let op: bitwise AND en NOT controle.
            var controle = (255 & ~params.STATUS_APPPUSH & ~params.STATUS_SUMMARY_XSL);
            sql = "UPDATE fac_notificatie"
                + "   SET fac_notificatie_status = BITAND (fac_notificatie_status, " + controle + ")"
                + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value;
            Log2File(3, sql);
            Oracle.Execute(sql);
        }
        else
            Log2File(1, "Parameter KEEP given, *not* clearing app notification " + rec("fac_notificatie_key").value);
    }

    return noti_apped;
}

/*
    Dit zijn *notificaties* die als *opdracht* verstuurd worden
    Voornamelijk voor system2system koppelingen
    Bijvoorbeeld AANS -> CSUN koppeling
 */
// Deprecated 2021.1, use notificationPRS
function notificationSYS(rec, params)
{
    // ======================== Systeemadres ========================
    // Het systeemadres wordt niet aangemerkt als bitje in de status kolom
    Log2File(2, "\n*> notificationSYS");
    var SendOrderResult = { resultcode: 1 };
    var noti_sysed = 0;

    var systeemadres = rec("fac_notificatie_systeemadres").value;
    if (!systeemadres)
        return noti_sysed;

    try
    {
        var xmlnode      = rec("fac_srtnotificatie_xmlnode").value || "";
        var refkey       = rec("fac_notificatie_refkey").value;
        var extrakey     = rec("fac_notificatie_extrakey").value;
        var taal         = rec("fac_notificatie_lang").value;
        var code         = rec("fac_srtnotificatie_code").value || "";
        var sender_email = rec("fac_notificatie_sender_email").value || "";

        var connect = new ConnectorCls();
        // Met FSN#34131 hoop ik echte prs_bedrijfadres informatie te krijgen
        // Tot die tijd ook even zo: je mag achteraan het systeemadres
        // een ##1 zetten voor andere encoding
        var encoding = 0; // text/xml
        if (systeemadres.indexOf('##') > -1)
        {
            encoding = systeemadres.split('##')[1];
            systeemadres = systeemadres.split('##')[0];
        }
        var bedrijfadres = { url: systeemadres,
                             error_handling: 0,
                             extension: "xml",
                             ordermode: 0,
                             certificateName: "",
                             AttachFile: "",
                             username: "",
                             password: "",
                             encoding: encoding };

        puo_hook.initialize(bedrijfadres);
        connect.connect(bedrijfadres); // vult eventueel bedrijfadres.username/password

        if (xmlnode)
        {
            // Errors in de generatie van de XML worden afgevangen in fetchXMLContent
            // De functie levert dan een lege string, de notificatie wordt dan als verzonden
            // afgehandeld
            var SendOrderResult = -1;
            var xml_content = fetchXMLContent( xmlnode
                                             , refkey
                                             , extrakey
                                             , ""
                                             , taal
                                             , { srtnotificatie: rec("fac_srtnotificatie_code").value }
                                             );
            if (xml_content)
            {
                var Bijlagen = {};
                var ordernr = "Onbekend";
                var System2SystemXSL = S("puo_system2systemxsl");

                Log2File(3, "In Notifications sender=" + sender_email);
                Log2File(4, "xsl="                     + S("puo_system2systemxsl"));
                Log2File(4, "xsl2="        + System2SystemXSL);
                Log2File(4, "ordernr="     + ordernr);
                Log2File(4, "key="         + refkey);
                Log2File(4, "order_mode="  + bedrijfadres.ordermode);
                Log2File(4, "Code="        + code);
                Log2File(4, "XMLnode="     + xmlnode);

                var SendOrderResult = SendOrder ( connect
                                                 , xml_content
                                                 , bedrijfadres
                                                 , System2SystemXSL
                                                 , ordernr
                                                 , refkey
                                                 , sender_email
                                                 , xmlnode
                                                 , code
                                                 , Bijlagen
                                                 );
            }

            if (SendOrderResult.resultcode != 0)
            {
                Log2File(0, "Notification to systeemadres failed. Errorcode:" + SendOrderResult.resultcode);
            }
            else
            {
                Log2File(2, "Notification to systeemadres sent");
                noti_sysed++;
            }
        }
    }
    catch(e)
    {
        Log2File(0, toDateTimeString(new Date()) + " Error in SendNotification/Systemaddress: " + e.description, "E");
        // Wel doorvallen naar wissen bitjes: we blijven notificaties niet tot in den treure proberen
    }
    finally
    {
        // == DONE Systeemadres ==
        if (SendOrderResult.resultcode == 0)
        {
            if (clearNotifications)
            {
                sql = "UPDATE fac_notificatie"
                    + "   SET fac_notificatie_systeemadres = NULL "
                    + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value
                Log2File(3, sql);
                Oracle.Execute(sql);
            }
            else
                Log2File(1, "Parameter KEEP given, *not* clearing system notification " + rec("fac_notificatie_key").value);
        }
        else
        {
            var failcount = rec("fac_notificatie_failcount") + 1;
            // Interval tussen pogingen steeds 10 minuten langer, max 120 minuten
            var backofminutes = Math.min(S("puo_faildelaymax"), failcount * S("puo_faildelayincrement"));
            var nextdate = new Date();
            nextdate.setMinutes(nextdate.getMinutes() + backofminutes);
            var sql = "UPDATE fac_notificatie"
                    + "   SET fac_notificatie_failcount = " + failcount
                    + "     , fac_notificatie_faildatum = SYSDATE"
                    + "     , fac_notificatie_failmessage = " + safe.quoted_sql(SendOrderResult.errtext)
                    + "     , fac_notificatie_notbefore = " + nextdate.toSQL(true, true)
                    + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value;
            Log2File(3, sql);
            Oracle.Execute(sql);

            Log2File(1, "Failed {0} time(s) since {1}, delaying until {2}".format(failcount,
                                                                                toDateTimeString(new Date(rec("fac_notificatie_datum").Value)),
                                                                                toDateTimeString(nextdate)));
            // Let op dat er latere notificaties over dezelfde xmlnode kunnen zijn of kunnen komen
            // Als je wilt dat ze nooit out-of-order worden verwerkt moet de custom-queue
            // processor zelf zo slim zijn om ook te stoppen met deze opdracht zodra hij
            // *een* notbefore in de toekomst tegenkomt.
            // Als de aanroeper nog een cursor op fac_v_notifyqueue open heeft staan ziet
            // die cursor bovenstaande wijziging nog niet!
            // ==> Zo geavanceerd doen we het bij deze notificaties niet.
        }
    }

    return noti_sysed;
}

function refkeyOrExtrakey(rec)
{
  return rec("fac_srtnotificatie_xmlnode").value == "reservering" ? rec("fac_notificatie_extrakey").value : rec("fac_notificatie_refkey").value;
}

function trk_action(srtcode, refkey, txt)
{
    var sqlSrtNotificatie = "SELECT fac_srtnotificatie_code"
                          + "  FROM fac_srtnotificatie"
                          + " WHERE fac_srtnotificatie_code LIKE '%TRK'"
                          + "   AND fac_srtnotificatie_code <> 'MESTRK'"
                          + "   AND fac_srtnotificatie_xmlnode IN (SELECT sn.fac_srtnotificatie_xmlnode FROM fac_srtnotificatie sn"
                                                                + " WHERE sn.fac_srtnotificatie_code=" + safe.quoted_sql(srtcode) + ")";
    var oRs = Oracle.Execute(sqlSrtNotificatie);
    if (!oRs.Eof)
    {
        var paction = "#" + oRs("fac_srtnotificatie_code").Value;
        var sql = "BEGIN fac.trackaction({0}, {1}, NULL, NULL, {2}); END;".format(safe.quoted_sql(paction), refkey, safe.quoted_sql(txt));
        Oracle.Execute(sql);
    }
    oRs.Close();
}

// Notification to a fac_notificatie.prs_bedrijfadres
function notificationPRS(rec, params)
{
    // ======================== prs_bedrijfadres ========================
    // Het bedrijfadres wordt niet aangemerkt als bitje in de status kolom
    Log2File(2, "\n*> notification PRS_BEDRIJFADRES");
    var noti_prsed = 0;

    if (!rec("prs_bedrijfadres_key").Value)
        return noti_prsed;

    var bedrijfadres_key  = rec("prs_bedrijfadres_key").value;
    var sql = "SELECT b.prs_bedrijf_naam"
            + "  FROM prs_bedrijf b, prs_bedrijfadres ba"
            + " WHERE ba.prs_bedrijfadres_key = " + bedrijfadres_key
            + "   AND ba.prs_bedrijf_key = b.prs_bedrijf_key";
    var oRs = Oracle.Execute(sql);
    var bedrijfnaam = oRs("prs_bedrijf_naam").Value; // Handig voor logging
    oRs.Close();
    Log2File(0, "Notification to company: {0} (adres_key {1})".format(bedrijfnaam, bedrijfadres_key));

    var keeploglevel = S("puo_loglevel");
    try
    {
        var props = {
                        ordernr: rec("fac_notificatie_naam").Value || (rec("fac_srtnotificatie_code").Value + "_" + rec("fac_notificatie_refkey").value), // voor eventuele filename
                        extrakey: rec("fac_notificatie_extrakey").Value,
                        subject: rec("fac_notificatie_oms").Value,
                        srtcode: rec("fac_srtnotificatie_code").Value,
                        sender: rec("fac_notificatie_sender_email").Value,
                        aanmaak: rec("fac_notificatie_datum").Value,
                        taal: rec("fac_notificatie_lang").Value,
                        notificatie_key: rec("fac_notificatie_key").Value
                    };
        if (props.srtcode == 'ORDNEW' ||
            props.srtcode == 'ORDSND' ||
            props.srtcode == 'ORDUPD' || // zorg dat als teverzenden=2 wordt gezet dat mld_opdr_verzonden wel bijgewerkt raakt
            props.srtcode == 'BES2NE' ||
            props.srtcode == 'CNTNEW' ||
            props.srtcode == 'RESSND')
        {
            props.marksent = marksent;
        }

        var SendOrderResult = send2address(
                      rec("prs_bedrijfadres_key").Value,
                      rec("fac_srtnotificatie_xmlnode").Value,
                      rec("fac_notificatie_refkey").Value,
                      props
                    )
        var failcount = rec("fac_notificatie_failcount");
        if (SendOrderResult.resultcode != 0 && SendOrderResult.resultcode != 2) // 0 = ok, 2 = onbekend (e-mail)
        {
            failcount ++;
            Log2File(0, "Notification {0} to prs_bedrijfadres failed. Errorcode: {1}".format(rec("fac_srtnotificatie_code").Value||"", SendOrderResult.resultcode));

            // Interval tussen pogingen steeds 10 minuten langer, max 120 minuten
            var backofminutes = Math.min(S("puo_faildelaymax"), failcount * S("puo_faildelayincrement"));
            var nextdate = new Date();
            nextdate.setMinutes(nextdate.getMinutes() + backofminutes);
            var sql = "UPDATE fac_notificatie"
                    + "   SET fac_notificatie_failcount = " + failcount
                    + "     , fac_notificatie_faildatum = SYSDATE"
                    + "     , fac_notificatie_failmessage = " + safe.quoted_sql(SendOrderResult.errtext)
                    + "     , fac_notificatie_notbefore = " + nextdate.toSQL(true, true)
                    + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value
            Log2File(3, sql);
            Oracle.Execute(sql);

            var firstdatum = new Date(rec("fac_notificatie_datum").Value);
            var lastdate = new Date(firstdatum);
            lastdate.setHours(lastdate.getHours() + S("puo_faillimit"));
            if (nextdate > lastdate)
            {
                var msg = "Failed {0} time(s) since {1} now. Giving up after {2} hours.".format(failcount, toDateTimeString(firstdatum), S("puo_faillimit"));
                Log2File(1, msg);

                sql = "UPDATE fac_notificatie"
                    + "   SET prs_bedrijfadres_key = NULL "
                    + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value
                Log2File(3, sql);
                Oracle.Execute(sql);

                // dan moeten we er nog een nette lcl van maken maar putorders kent geen LCL's
                //trk_action(props.srtcode, refkeyOrExtrakey(rec), msg);
            }
            else
            {
                Log2File(1, "Failed {0} time(s) since {1}, delaying until {2}".format(failcount,
                                                                                    toDateTimeString(new Date(rec("fac_notificatie_datum").Value)),
                                                                                    toDateTimeString(nextdate)));
            }
        }
        else
        {
            Log2File(2, "Notification to prs_bedrijfadres sent");
            if (!props.marksent) // dan xxxTRK proberen
            {
                var txt = S("puo_lcl_tracknoti_sys").format(props.srtcode, bedrijfnaam);
                if (failcount > 0)
                    txt += S("puo_lcl_tracknoti_sys_fail").format(failcount);
                trk_action(props.srtcode, refkeyOrExtrakey(rec), txt);
            }
            noti_prsed++;
        }
    }
    catch(e)
    {
        Log2File(0, toDateTimeString(new Date()) + " Error in notificationPRS: " + e.description, "E");
        // Wel doorvallen naar wissen bitjes: we blijven notificaties niet tot in den treure proberen
    }
    finally
    {
        // == DONE prs_bedrijfadres ==
        if (SendOrderResult && (SendOrderResult.resultcode == 0 || SendOrderResult.resultcode == 2))
        {
            if (clearNotifications)
            {
                sql = "UPDATE fac_notificatie"
                    + "   SET prs_bedrijfadres_key = NULL "
                    + " WHERE fac_notificatie_key = " + rec("fac_notificatie_key").value
                Log2File(3, sql);
                Oracle.Execute(sql);
            }
            else
                Log2File(1, "Parameter KEEP given, *not* clearing bedrijfadres notification " + rec("fac_notificatie_key").value);
        }
    }
    if (S("puo_loglevel") != keeploglevel)
        settings.overrule_setting("puo_loglevel", keeploglevel); // was mogelijk overruled door send2address

    return noti_prsed;
}

function getXslName(pNode)
{
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    var resxslsheet = S("puo_notificationxsl").toLowerCase() || "";

    if (pNode)
    {
        if (fso.FileExists(custabspath + "/xsl/" + pNode + ".xsl"))
            resxslsheet = "xsl/" + pNode + ".xsl";
    }

    if (resxslsheet == "" || !fso.FileExists(custabspath + "/" + resxslsheet))
        resxslsheet = "xsl/" + customerId.toLowerCase() + ".xsl";

    if (!fso.FileExists(custabspath + "/" + resxslsheet))
        resxslsheet = "../../appl/shared/default.xsl";

    return resxslsheet;
}
