<% /*
    $Revision$
    $Id$

    File:           model_invoices.inc

    Description:    Factuur model.
    Parameters:
    Context:

    Notes:          TODO: definitieve naamgeving verifieren
                    TODO: autorisaties voor scope=fo|bo

                    We had a discussion. The references (order, contract, purchaseorder) are now present by their foreign nodes.
                    We ourselves want the creditor of the invoice in the result, it is logically a property of an invoice
                    which we technically do not store with the invoice. Formally the creditor should be obtained by a subsequent
                    call to the corresponing API. Alternatively we could add those 3 optional nodes with an include option
                    which is merely designed for 1:n relations, not n:1 like this one.
                    We do not want to slide down from our purest REST forms (yet) so we made the compromise of these 2 readonly fields.
                    Let's see how it holds.
*/
%>
<!-- #include file="../Shared/discxalg3d.inc"-->
<!-- #include file="../fin/fin.inc" -->
<!-- #include file="./model_invoicelines.inc"-->
<!-- #include file="./model_custom_fields.inc"-->
<!-- #include file="./model_tracking.inc"-->
<%
function model_invoices(fin_key, params)
{
    params = params || {};
    this.module = "FIN";
    this.table = "fin_factuur";
    this.primary = "fin_factuur_key";
    this.records_name = "invoices";
    this.record_name = "invoice";

              // Het interne factuurnr is de id, het externe nummer is name
    this.fields =
            {"id"              : { dbs: "fin_factuur_key",          typ: "key",                                                                             filter: "exact" },
             "invoicedate"     : { dbs: "fin_factuur_datum",        typ: "datetime",                               track: true, label: L("lcl_fin_findate"),             filter: "range" },
/*readonly*/ "creditor"        : { dbs: "prs_bedrijf_key",          typ: "key",     foreign: "prs_bedrijf",        track: true, label: L("lcl_ord_company_uit"),         filter: "exact",
                                   sql: "COALESCE(mld_opdr.mld_uitvoerende_keys, bes_bestelopdr.prs_bedrijf_key, cnt_contract.cnt_prs_bedrijf_key)" },
/*readonly*/ "referencetype"   : { dbs: "dummy",                    typ: "varchar",                                                                         filter: "exact",
                                   sql: "DECODE(fin_factuur.mld_opdr_key, NULL, DECODE(fin_factuur.bes_bestelopdr_key, NULL, DECODE(fin_factuur.cnt_contract_key, NULL, '?', 'C'), 'B'), 'O')" },
             "name"            : { dbs: "fin_factuur_nr",           typ: "varchar",                                track: true, label: L("lcl_fin_invoice_nr_extern"),   filter: "exact" },
             "order"           : { dbs: "mld_opdr_key",             typ: "key",     foreign: "mld_opdr",                                                    filter: "exact"},
             "contract"        : { dbs: "cnt_contract_key",         typ: "key",     foreign: "cnt_contract",                                                filter: "exact"},
             "purchaseorder"   : { dbs: "bes_bestelopdr_key",       typ: "key",     foreign: "bes_bestelopdr",                                              filter: "exact"},
             "total"           : { dbs: "fin_factuur_totaal",       typ: "float",   "iscurrency": true,            track: true, label: L("lcl_fin_totaal_bedrag"),       filter: "range" },
             "vat"             : { dbs: "fin_factuur_totaal_btw",   typ: "float",   "iscurrency": true,            track: true, label: L("lcl_fin_totaal_bedrag_btw"),   filter: "range" },
             "finstatus"       : { dbs: "fin_factuur_statuses_key", typ: "key",     foreign: fin.getfinstatustext, track: true, label: L("lcl_fin_fin_status"),          filter: "exact" },
             "accountingperiod": { dbs: "fin_factuur_boekmaand",    typ: "varchar",                                track: true, label: L("lcl_fin_divide_period"),       filter: "exact" },
             "debiteur_nr"     : { dbs: "fin_factuur_debiteur_nr",  typ: "varchar",                                track: true, label: L("lcl_fin_debtor_nr"),           filter: "like" },
             "costtype"        : { dbs: "prs_kostensoort_key",      typ: "key",     foreign: "prs_kostensoort",    track: true, label: L("lcl_shared_charge_type"),      filter: "exact" },
             "contact"         : { dbs: "prs_perslid_key_user",     typ: "key",     foreign: "prs_perslid",        track: true, label: L("lcl_mld_name"),                filter: "exact" },
             "goedkeur"        : { dbs: "prs_perslid_key_goedkeur", typ: "key",     foreign: "prs_perslid",        track: true, label: L("lcl_fin_goedkeurder"),         filter: "exact" },
             "remark"          : { dbs: "fin_factuur_opmerking",    typ: "varchar",                                track: true, label: L("lcl_fin_remark"),              filter: "like" }
            };
    this.includes =
              {"invoicelines": { model: model_invoicelines,
                                 joinfield: "fin_factuur_key",
                                 enable_update: true
                               },
                "custom_fields" : { model: new model_custom_fields(this, "FIN", { readman: true, readuse: true }),
                                    joinfield: "flexparentkey"
                                  },
                "tracking": {
                                  model: new model_tracking(['contract']),
                                  joinfield: "fac_tracking_refkey"
                            }
              };

    function _pre_analyze_fields (params, jsondata) /* analyseer inkomende jsondata, common voor PUT en POST */
    {
        // De factuurbedragen worden berekend uit de factuurregels. Eventuele waarden die hier gezet zijn negeren.
        jsondata.total = 0;
        jsondata.vat = 0;

        // Status van 3 (foute import) moet bij saven op 2 worden gezet.
        var fin_status_key = jsondata.status;
        if (fin_status_key == 3) fin_status_key = 2;

        // Status 6 (Akkoord) moet bij saven op 2 (Ingevoerd) worden gezet. Factuur dient indien nodig weer gefiatteerd te worden.
        if (fin_status_key == 6) fin_status_key = 2;

        jsondata.status = fin_status_key;
    };

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

    function _validate_fields (dbfields, params, jsondata) /* valideer fields, alle constraints die niet door de database worden afgevangen */
    {
    };

    this.REST_GET = function _GET(params)
    {
        var this_fin = fin.func_enabled_factuur(params.filter.id || -1);
        user.auth_required_or_abort(this_fin.canReadAny);

        var query = api2.sqlfields(params, this );
        query.wheres.push("fin_factuur_verwijder IS NULL");

        if (/* self */ 0)
        {
            query.wheres.push("prs_perslid_key_user=" + user_key);
        }
        else
        {
            // TODO: disc3d conditie voor de geldendende autfunction toevoegen
        }

        query.tables.push("mld_opdr");
        query.wheres.push("fin_factuur.mld_opdr_key = mld_opdr.mld_opdr_key(+)");
        query.tables.push("bes_bestelopdr");
        query.wheres.push("fin_factuur.bes_bestelopdr_key = bes_bestelopdr.bes_bestelopdr_key(+)");
        query.tables.push("cnt_contract");
        query.wheres.push("fin_factuur.cnt_contract_key = cnt_contract.cnt_contract_key(+)");

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

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

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

        return json;
    };

    this.REST_PUT = function (params, jsondata, the_key) /* update invoice */
    {
        var fin_key = the_key;
        var this_fin = fin.func_enabled_factuur(fin_key);
        user.auth_required_or_abort(this_fin.canChange);  // Geen wijzigingen toestaan bij onvoldoende rechten.
        //
        _pre_analyze_fields(params, jsondata);
        var dbfields = api2.update_fields(params, this, jsondata); // Build updater
        _analyze_fields(dbfields, params, jsondata);
        _validate_fields(dbfields, params, jsondata);
        //
        var wheres = [" fin_factuur_key = " + fin_key];
        var finUpd = buildTrackingUpdate("fin_factuur", wheres.join(" AND " ), dbfields, { noValidateToken: true });
        var err = Oracle.Execute(finUpd.sql, true);
        if (err.friendlyMsg)
            abort_with_warning(err.friendlyMsg);

        var fintrack = api2.process_includes(params, this, jsondata, the_key);

        // update nog tracken
        if (fin_key > 0)
        {
            shared.trackaction("FINUPD",
                               fin_key,
                               L("lcl_fin_is_finupdtrack").format(fin_key) + (finUpd.trackarray.length > 0? "\n" : "") + finUpd.trackarray.join("\n"));
        };

        return { key: fin_key };
    };

    this.REST_POST = function (params, jsondata) /* new invoice */
    {
        var this_fin = fin.func_enabled_factuur(-1);
        user.auth_required_or_abort(this_fin.canChange);  // Geen wijzigingen toestaan bij onvoldoende rechten.

        params.isNew = true; // negeer eventuele bestaande keys

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

        dbfields["id"] = { dbs: "fin_factuur_key",         typ: "key",   seq: "fin_s_fin_factuur_key" };
        var finIns = buildInsert("fin_factuur", dbfields, { noValidateToken: true} );
        var factuur_key = finIns.sequences["fin_factuur_key"];

        var sql = finIns.sql;

        var err = Oracle.Execute(sql, true);
        if (err.friendlyMsg)
            abort_with_warning(err.friendlyMsg);

        var fintrack = api2.process_includes(params, this, jsondata, factuur_key);

        shared.trackaction("FINNEW", factuur_key);

        return { key: factuur_key };
    };

    this.REST_DELETE = function (params, the_key) /* delete invoice */
    {
        var factuur_key = the_key;

        var this_fin = fin.func_enabled_factuur(factuur_key);
        user.auth_required_or_abort(this_fin.canDelete);
        if (this_fin.canDelete) // Dubbel op: bij canDelete=false komt hij hier niet meer.
        {
            // Verwijderdatum van de factuur zetten en niet fysiek verwijderen
            var sql = "UPDATE fin_factuur"
                    + "   SET fin_factuur_verwijder = SYSDATE"
                    + " WHERE fin_factuur_verwijder IS NULL"
                    + "   AND fin_factuur_key = " + factuur_key;
            oRs = Oracle.Execute(sql);
        }
    }

    if (fin_key > 0)
    {
        params.filter = params.filter || {};
        params.filter.id = fin_key;
        if (! ("include" in params) )
            params.include = { include: ["custom_fields"]};

        var xxx_array = this.REST_GET(params);
        if (!xxx_array.length)
            shared.record_not_found();
       this.data = xxx_array[0];
    }
}
%>