<% /*
    $Revision$
    $Id$

    File:           model_notes.inc

    Description:    notes model.
    Parameters:
    Context:

    Notes:          table en fields worden dynamisch per module bepaald
                    Merk op dat dit een beetje een vreemde eend in de bijt is.
                    Notities vallen echt onder andere objecten en en dan is een
                    include het meest voor de hand liggend. Desalniettemin mag (/moet)
                    je ze ook *rechtstreeks* toevoegen via /api2/notes
                    Ook: in model_issues.inc doen we extra filtering op mld_melding_note_flag
*/

/*
alle notes in 1 view
CREATE OR REPLACE VIEW fac_v_notes
( module, key, parent_key, writer_key, aanmaak, omschrijving)
AS
SELECT 'MLD'
     , mld_melding_note_key
     , mld_melding_key
     , prs_perslid_key
     , mld_melding_note_aanmaak
     , mld_melding_note_omschrijving
     , mld_melding_note.fac_note_group_key
  FROM mld_melding_note
UNION
SELECT 'ORD'
     , mld_opdr_note_key
     , mld_opdr_key
     , prs_perslid_key
     , mld_opdr_note_aanmaak
     , mld_opdr_note_omschrijving
     , mld_opdt_note.fac_note_group_key
  FROM mld_opdr_note
UNION
SELECT 'FIN'
     , fin_factuur_note_key
     , fin_factuur_key
     , prs_perslid_key
     , fin_factuur_note_aanmaak
     , fin_factuur_note_omschrijving
  FROM fin_factuur_note
UNION
SELECT 'CNT'
     , cnt_contract_note_key
     , cnt_contract_key
     , prs_perslid_key
     , cnt_contract_note_aanmaak
     , cnt_contract_note_omschrijving
  FROM cnt_contract_note
UNION
SELECT 'PRJ'
     , prj_scenario_note_key
     , prj_scenario_key
     , prs_perslid_key
     , prj_scenario_note_aanmaak
     , prj_scenario_note_omschrijving
  FROM prj_scenario_note
*/

%>
<!-- #include file="../mld/mld.inc" -->
<!-- #include file="../mld/mld_edit_note.inc" -->
<!-- #include file="../mld/opdr_edit_note.inc" -->
<%

function model_notes(module)
{
    this.module =       module;
    // this.table =        "fac_v_notes";
    this.records_name = "notes";
    this.record_name =  "note";

    var tabel = {}; // De tabel met notes die aangepast moet worden.
    switch (module)
    {
        case "MLD":
        {   tabel.naam   = "mld_melding_note";
            tabel.id     = "mld_melding_note_key";
            tabel.seq    = "mld_s_mld_melding_note_key";
            tabel.parent = "mld_melding";
            break;
        }
        case "ORD":
        {   tabel.naam   = "mld_opdr_note";
            tabel.id     = "mld_opdr_note_key";
            tabel.seq    = "mld_s_mld_opdr_note_key";
            tabel.parent = "mld_opdr";
            break;
        }
        case "FIN":
        {   tabel.naam   = "fin_factuur_note";
            tabel.id     = "fin_dactuur_note_key";
            tabel.seq    = "fin_s_fin_factuur_note_key";
            tabel.parent = "fin_factuur";
            break;
        }
        case "CNT":
        {   tabel.naam   = "cnt_contract_note";
            tabel.id     = "cnt_contract_note_key";
            tabel.seq    = "cnt_s_cnt_contract_note_key";
            tabel.parent = "cnt_contract";
            break;
        }
        case "PRJ":
        {   tabel.naam   = "prj_scenario_note";
            tabel.id     = "prj_scenario_note_key";
            tabel.seq    = "prj_s_prj_scenario_note_key";
            tabel.parent = "prj_scenario";
            break;
        }
        default:
            api2.error(500, "Missing module parameter");
    }
    this.table = tabel.naam;
    this.primary = tabel.parent + "_note_key";
    var sqlbijlagen = "(SELECT COUNT(*) aantal"
                    + "   FROM fac_bijlagen"
                    + "  WHERE fac_bijlagen_module = " + safe.quoted_sql((module === "OPDR" ? "ORD" : module) + "N")
                    + "    AND fac_bijlagen_refkey = " + tabel.naam + "." + tabel.id + ")";

    this.fields =
            { "id"            : { dbs: tabel.id,                     typ: "key",     seq:     tabel.seq },
              "author"        : { dbs: "prs_perslid_key",            typ: "key",     foreign: "prs_perslid" },
              "description"   : { dbs: tabel.naam + "_omschrijving", typ: "varchar",                         filter: "like"  },
              "created"       : { dbs: tabel.naam + "_aanmaak",      typ: "datetime", "readonly": true},
              "parent"        : { dbs: tabel.parent + "_key",        typ: "key" },
              "nnattachments" : { dbs: "dummy",                      typ: "number", sql: sqlbijlagen }
        };

    var notes_id = getQParamInt("notes_id", -1); // Om een specifieke notitie op te vragen
    if (notes_id > 0)
    {
        this.tablesql = "(SELECT * FROM {0} WHERE {1} = {2}) {0}".format(tabel.naam, tabel.id, parseInt(notes_id))
    }
    switch (module)
    {
        case "MLD":
        {
            this.fields["flag"] = { dbs: tabel.parent + "_note_flag", typ: "number" }; // database default is 0, onzichtbaarFE
            this.fields["group"] = { dbs: "fac_note_group_key", typ: "key", foreign: "fac_note_group"};
            break;
        }
        case "ORD":
        {
            this.fields["flag"] = { dbs: tabel.parent + "_note_flag", typ: "number" }; // database default is 4, zichtbaarUITV
            this.fields["group"] = { dbs: "fac_note_group_key", typ: "key", foreign: "fac_note_group"};
            break;
        }
    }
    this.list = {
            "columns": [
              "id",
              "author",
              "description",
              "createdate"
            ]
          };

    // Deze functie wordt na de GET aangeroepen. De bijlagen zijn zo afwijkend
    // dat ik dat niet fatsoenlijk in 'fields' verwerkt kreeg
    this.post_get = function (params, record)
        {
            record.attachments = [];
            if (!record.nnattachments) // voorkom sql-statement per notitie
            {
                delete record["nnattachments"];
                return;
            }
            delete record["nnattachments"];
            
            var fileparams = { getFiles: true, getFileEncoded: params.filter.fileencoding, /* api2name: "notes", */ cacheablehmac: true };
            var props = flexProps((module === "OPDR" ? "ORD" : module) + "N", record.id, undefined, undefined, fileparams);
            for (var f in props.files)
            {
                var file = props.files[f];
                var attachment = { name: file.name,
                                   date: file.date,
                                   size: file.size };
                if (file.deepurl) attachment.content_url = file.deepurl;
                if (file.token)   attachment.token = file.token;
                if (file.key)     attachment.id = file.key;
                if (file.digest)  attachment.digest = file.digest;
                switch (params.filter.fileencoding) // De enige twee encodings die we ondersteunen
                {
                    case "base64":
                        attachment.content_base64 = file.data;
                        break;
                    case "hex":
                        attachment.content_hex = file.data;
                        break;
                }
                record.attachments.push(attachment);
            };
        }

    function _check_authorization (params, method)
        {
            params.message = "";

            switch (params.filter.module)
            {
                case "MLD":
                {
                    var autfunction = ( params.filter.scope == "fe"
                                      ? "WEB_MLDUSE"
                                      : ( params.filter.scope == "fo"
                                        ? "WEB_MLDFOF"
                                        : "WEB_MLDBOF"
                                        )
                                      );
                    params.authparams = user.checkAutorisation(autfunction, null, null, true); // pessimistisch

                    switch (method)
                    {
                        case "GET":
                            if (params.filter.parent_key)
                            {
                                var mld_key = params.filter.parent_key;
                                var this_mld = mld.func_enabled_melding(mld_key, params);
                                user.auth_required_or_abort(this_mld.canReadNotes);
                            }
                            break;
                        case "DELETE":
                            // Notes mogen niet worden verwijderd.
                            // en verder met de autorisatie van PUT...
                        case "PUT":
                            var mld_key = params.filter.parent;
                            var this_mld = mld.func_enabled_melding(mld_key, params);
                            user.auth_required_or_abort(this_mld.canWriteNotes);
                            params.isNew = false;
                            break;
                        case "POST":
                            var mld_key = params.filter.parent_key;
                            var this_mld = mld.func_enabled_melding(mld_key, params);
                            user.auth_required_or_abort(this_mld.canWriteNotes);
                            params.isNew = true;
                            break;
                    }
                    params.func_enabled = this_mld || {};
                    break;
                }
                case "ORD":
                {
                    var opdr_key = params.filter.parent_key;
                    var this_opdr = mld.func_enabled_opdracht(opdr_key);

                    switch (method)
                    {
                        case "PUT":
                            user.auth_required_or_abort(this_opdr.canEditOpdrNote);
                            params.isNew = false;
                            break;
                        case "POST":
                            user.auth_required_or_abort(this_opdr.canEditOpdrNote);
                            params.isNew = true;
                            break;
                    }
                    params.func_enabled = this_opdr || {};
                    break;
                }
                default:
                {
                    // Voor alle andere modules (nog) niets toestaan.
                    user.auth_required_or_abort(false);
                }
            }
        }

    this._validate_fields = function (params, jsondata) { /* valideer fields, alle constraints die niet door de database worden afgevangen */
        switch (params.filter.module) {
            case "MLD": {
                if (!params.filter.scope) {
                    params.filter.scope = "fe"; // default scope
                }
                break;
            }
            case "ORD": {
                if (S("mld_opdr_actiecode") == 0 || // Dan doen deze niet mee
                    jsondata.action_to_backoffice && jsondata.action_to_executor) { /* Deze zijn exclusief, als je ze allebei zet, dan weet je vast niet wat je doet, dus doe dan niets */
                    delete jsondata.action_to_backoffice;
                    delete jsondata.action_to_executor;
                }
                if (params.func_enabled.myRole === 4) { // Ik ben uitvoerder
                    jsondata.flag = (jsondata.flag || 0) | 4; // *Altijd* ZichtbaarUITV
                    delete jsondata.notify_executor;
                    delete jsondata.action_to_executor;
                    if (jsondata.flag && jsondata.flag & 32 || jsondata.action_to_requestor) {
                        jsondata.flag = jsondata.flag | 37;
                        jsondata.notify_requestor = true;
                        jsondata.action_to_requestor = true;
                    } else {
                        delete jsondata.action_to_requestor;
                    }
                } else if (params.func_enabled.myRole === 2) { // Ik ben BO
                    jsondata.flag = ("flag" in jsondata) ? jsondata.flag : 4; // *Default* ZichtbaarUITV
                    delete jsondata.notify_backoffice;
                    if (jsondata.action_to_executor) {
                        jsondata.flag = (jsondata.flag || 0) | 4; // *Altijd* ZichtbaarUITV
                        jsondata.notify_executor = true;
                    }
                }
            }
        }
    };

    // Geen standaard REST_GET, dat doe je maar via het hoofdmodel/include
    this.templateREST_GET = function _GET(params)
        {
            var query = api2.sqlfields(params, this );
            var wheres = api2.sqlfilter(params, this);
            query.wheres = query.wheres.concat(wheres);

            var sql = "SELECT " + query.selects.join(", ")
                    + "  FROM " + query.tables.join(", ");
            if (query.wheres.length)
                sql += " WHERE " + query.wheres.join(" AND " );

            var json = api2.sql2json (params, sql, this );

            return json;
        };

    // deprecated omdat hij volgens mij toch niet werkt / geen _check_authorization heeft
    this.deprecatedREST_PUT = function (params, jsondata, the_key) /* update note */
        {
            this.REST_GET = this.templateREST_GET; // om het resultaat te kunnen opleveren
            // Een note kan alleen worden aangepast door de persoon die hem geschreven heeft.
            // Alleen van de meest recente note bij een (melding/opdracht/...) kan de omschrijving worden aangepast.
            //
            var dbfields = api2.update_fields(params, this, jsondata); // Build updater

            var wheres = [ this.fields.id.dbs + " = " + the_key];
            wheres.push("prs_perslid = " + user_key);

            var xxxUpd = buildTrackingUpdate(this.table, wheres.join(" AND " ), dbfields, { noValidateToken: true });

            Oracle.Execute(xxxUpd.sql);

            return { key: the_key };
        };

    this.REST_POST = function (params, jsondata) /* new note */
        {
            this.REST_GET = this.templateREST_GET; // om het resultaat te kunnen opleveren
            params.filter.parent_key = parseInt(jsondata.parent, 10);
            if (!(params.filter.parent_key > 0))
                abort_with_warning(L("lcl_invalid_key"));

            _check_authorization(params, "POST");

            if (!jsondata.author) // Dit werkt niet echt hoor, overal wordt user(_key) gebruikt, bij shared.trackaction, de bepaling van myRole, etc ..
                jsondata.author = user_key;

            this._validate_fields(params, jsondata);

            var dbfields = api2.update_fields(params, this, jsondata); // Build updater
            dbfields["id"] = { dbs: tabel.id, typ: "key", seq: tabel.seq };

            var xxxIns = buildInsert(this.table, dbfields, { noValidateToken: true });
            params.note_key = xxxIns.sequences[tabel.id];

            Oracle.Execute(xxxIns.sql);

            if (module == "ORD") { // Momenteel alleen hier nog ondersteund
                _set_actiecode(params, jsondata);
                _track_and_notify(params, jsondata);
            }

            return { key: params.note_key };
        }

     // REST_DELETE = function (params, the_key) /* delete note doen we niet */
}
%>
