<% /*
    $Revision$
    $Id$

    File:           model_invoicelines.inc

    Description:    Factuurregel model.
    Parameters:
    Context:

    Notes:          TODO: autorisaties voor scope=fo|bo
                    TODO on demand: PUT/POST/DELETE
*/

%>
<!-- #include file="../Shared/discxalg3d.inc"-->
<!-- #include file="../fin/fin.inc" -->
<%

model_invoicelines =
{
    module: "FIN",
    table: "fin_factuurregel",
    primary: "fin_factuurregel_key",
    records_name: "invoicelines",
    record_name: "invoiceline",
    fields: { "id"       : { dbs: "fin_factuurregel_key",          typ: "key",                                                                              filter: "exact" },
              "name"     : { dbs: "fin_factuurregel_omschrijving", typ: "varchar",                                track: true, label: L("lcl_descr"),                    filter: "like"  },
              "line"     : { dbs: "fin_factuurregel_nr",           typ: "number"                                                                                            },
              "total"    : { dbs: "fin_factuurregel_totaal",       typ: "float",   "iscurrency": true,            track: true, label: L("lcl_fin_total_sum_exBTW")                       },
              "vat"      : { dbs: "fin_factuurregel_btw",          typ: "float",   "iscurrency": true,            track: true, label: L("lcl_fin_total_sum_inBTW")                       },
              "reference": { dbs: "fin_factuurregel_referentie",   typ: "varchar",                                track: true, label: L("lcl_fin_referencecode"),        filter: "like"  },
              "vatvalue" : { dbs: "fin_btwtabelwaarde_key",        typ: "key",     foreign: "fin_btwtabelwaarde", track: true, label: L("lcl_fin_btwtarief"),            filter: "exact" },
              "costtype" : { dbs: "prs_kostensoort_key",           typ: "key",     foreign: "prs_kostensoort",    track: true, label: L("lcl_shared_charge_type"),       filter: "exact" },
              "fin_factuur_key": { dbs: "fin_factuur_key",         typ: "key",     filter: "exact" }
            },

    _pre_analyze_fields: function (params, jsondata) /* analyseer inkomende jsondata, common voor PUT en POST */
    {
        delete jsondata.line; // factuurregelnummer niet door de gebruiker laten zetten.
    },

    _analyze_fields: function (dbfields, params, jsondata) /* analyseer inkomende data, common voor PUT en POST */
    {
    },

    _validate_fields: function (dbfields, params, jsondata) /* valideer dbfields, alle constraints die niet door de database worden afgevangen */
    {
      //__Log(jsondata);
      //var factuurregel_key = parseInt(jsondata.id);
    },

    _synchronize_totals_sql: function (factuur_key)
    {
        // Redundante info bijwerken. Door dat hier te doen hebben we redelijk consistentie-garantie.
        var sql = " UPDATE fin_factuur ff"
                + "    SET fin_factuur_totaal = (SELECT SUM(fin_factuurregel_totaal)"
                                             + "   FROM fin_factuurregel fr"
                                             + "  WHERE fr.fin_factuur_key = ff.fin_factuur_key)"
                + "      , fin_factuur_totaal_btw = (SELECT SUM(fin_factuurregel_btw)"
                                                  + "  FROM fin_factuurregel fr"
                                                  + " WHERE fr.fin_factuur_key = ff.fin_factuur_key)"
                + "  WHERE fin_factuur_key = " + factuur_key;
        return sql;
    },

    _renumber_invoicelines_sql: function (factuur_key)
    {
        // Regels hernummeren zodat ze weer opeenvolgend zijn.
        var sql = "UPDATE fin_factuurregel"
                + "   SET fin_factuurregel_nr = ROWNUM"
                + " WHERE fin_factuur_key = " + factuur_key;
        return sql;
    },


    REST_GET: function _GET(params)
    {
        var scope = params.filter.scope || "fe";
        var autfunction = { fe : "WEB_FINUSE", fo : "WEB_FINFOF", bo : "WEB_FINBOF" } [scope];
        params.authparams = user.checkAutorisation(autfunction, null, null, true); // pessimistisch

        var query = api2.sqlfields(params, model_invoicelines );
        var parentexists = ["f.fin_factuur_verwijder IS NULL"];

        if (scope == "fe")
        {
            parentexists.push("f.prs_perslid_key_user=" + user_key);
        }
        else
        {
            // TODO: disc3d conditie voor de geldendende autfunction toevoegen
        }

        if (parentexists.length)
        {
            var sqlparent = " EXISTS (SELECT 1"
                                  + "   FROM fin_factuur f"
                                  + "  WHERE f.fin_factuur_key = fin_factuurregel.fin_factuur_key"
                                  + "    AND " + parentexists.join(" AND ") + ")";
            query.wheres.push(sqlparent);
        }

        var wheres = api2.sqlfilter(params, model_invoicelines);
        query.wheres = query.wheres.concat(wheres);

        var sql = "SELECT " + query.selects.join(", ")
                + "  FROM " + query.tables.join(", ")
                + " WHERE " + query.wheres.join(" AND " )
                + " ORDER BY fin_factuurregel_nr";
        var json = api2.sql2json (params, sql, model_invoicelines );

        return json;
    },

    REST_PUT: function (params, jsondata, the_key) /* update invoiceline */
    {
        var finregel_key = the_key;
        model_invoicelines._pre_analyze_fields(params, jsondata);
        var dbfields = api2.update_fields(params, model_invoicelines, jsondata); // Build updater
        model_invoicelines._analyze_fields(dbfields, params, jsondata);
        model_invoicelines._validate_fields(dbfields, params, jsondata);
        //
        var sql = "SELECT fin_factuur_key"
                + "  FROM fin_factuurregel"
                + " WHERE fin_factuurregel_key = " + finregel_key;
        var oRs = Oracle.Execute(sql);
        var fin_factuur_key = oRs("fin_factuur_key").value;
        oRs.Close();

        var this_fin = fin.func_enabled_factuur(fin_factuur_key);
        user.auth_required_or_abort(this_fin.canChange);  // Geen wijzigingen toestaan bij onvoldoende rechten.

        var wheres = [" fin_factuurregel_key = " + finregel_key];
        var finUpd = buildTrackingUpdate("fin_factuurregel", wheres.join(" AND " ), dbfields, { noValidateToken: true });

        var sql = "BEGIN "
                + finUpd.sql + ";"
                + model_invoicelines._synchronize_totals_sql(fin_factuur_key) + ";"
                + "END;";
        var err = Oracle.Execute(sql, true);
        if (err.friendlyMsg)
            abort_with_warning(err.friendlyMsg);

        return { key: finregel_key };
    },

    REST_POST: function (params, jsondata, parent_key) /* new invoiceline */
    {
        var trackarray  = [];
        var factuur_key = parent_key;
        var this_fin    = fin.func_enabled_factuur(factuur_key); // Wat heb ik zoal aan rechten op deze specifieke factuur
        user.auth_required_or_abort(this_fin.canChange); // Geen nieuwe factuurregels bij een verwerkte factuur en onvoldoende rechten.

        model_invoicelines._pre_analyze_fields(params, jsondata);
        var dbfields = api2.update_fields(params, model_invoicelines, jsondata); // Build updater
        model_invoicelines._analyze_fields(dbfields, params, jsondata);
        model_invoicelines._validate_fields(dbfields, params, jsondata);

        // Zet volgnummer van de nieuwe factuurregel.
        var sql = "SELECT MAX(fin_factuurregel_nr) volgnr"
                + "  FROM fin_factuurregel"
                + " WHERE fin_factuur_key = " + factuur_key;
        var oRs = Oracle.Execute(sql);
        var volgnr = oRs("volgnr").value + 1;
        oRs.Close();

        dbfields["invoice"] = { dbs: "fin_factuur_key",      typ: "key",    val: factuur_key };
        dbfields["id"] = { dbs: "fin_factuurregel_key", typ: "key",    seq: "fin_s_fin_factuurregel_key" };
        dbfields["line"] = { dbs: "fin_factuurregel_nr",  typ: "number", val: volgnr };

        var finIns = buildInsert("fin_factuurregel", dbfields, { noValidateToken: true });
        var factuurregel_key = finIns.sequences["fin_factuurregel_key"];

        var sql = "BEGIN "
                + finIns.sql + ";"
                + model_invoicelines._synchronize_totals_sql(factuur_key) + ";"
                + "END;";
        var err = Oracle.Execute(sql, true);
        if (err.friendlyMsg)
            abort_with_warning(err.friendlyMsg);

        // Tracking toevoegen.
        trackarray.push(L("lcl_fin_invoicerow_add") + ": " + safe.quoted_sql(jsondata.name) + "/" + jsondata.total);
        shared.trackaction("FINNEW", factuur_key, trackarray.join("\n"));
        //
        return { key: factuurregel_key };
    },

    REST_DELETE: function (params, the_key) /* delete invoiceline */
    {
        var trackarray  = [];
        var factuurregel_key = the_key;

        var sql = "SELECT fin_factuur_key"
                + "     , fin_factuurregel_omschrijving"
                + "     , fin_factuurregel_totaal"
                + "  FROM fin_factuurregel"
                + " WHERE fin_factuurregel_key = " + factuurregel_key;
        var oRs = Oracle.Execute(sql);
        var factuur_key = oRs("fin_factuur_key").value;
        var desc = oRs("fin_factuurregel_omschrijving").value;
        var total = oRs("fin_factuurregel_totaal").value;
        oRs.Close();

        var this_fin = fin.func_enabled_factuur(factuur_key);
        user.auth_required_or_abort(this_fin.canDelete);

        // Alleen bij voldoende rechten op de factuur kan een factuurregel worden verwijderd.
        fin.deleteFactuurregel(factuurregel_key);

        var sql = "BEGIN "
                + model_invoicelines._synchronize_totals_sql(factuur_key) + ";"
                + model_invoicelines._renumber_invoicelines_sql(factuur_key) + ";"
                + "END;"
        var err = Oracle.Execute(sql, true);
        if (err.friendlyMsg)
            abort_with_warning(err.friendlyMsg);
        else
        {
            trackarray.push(L("lcl_fin_regel_del") + ": " + safe.quoted_sql(desc) + "/" + total);
            //shared.trackaction("FINDEL", factuur_key, trackarray.join("\n")); // srtnotificatie FINDEL bestaat (nog) niet
        }
    }
}
%>
