<% /*
    $Revision$
    $Id$

    File:           model_bgt_budgetmutatie.inc

    Description:    Model voor bgt_budgetmutatie

    Context:

    Notes:
*/
%>
<!-- #include file="../bgt/bgt_tools.inc" -->
<%

function model_bgt_budgetmutatie()
{
    this.records_name = "budgetmutations";
    this.record_name = "budgetmutation";
    this.table = "bgt_budgetmutatie";
    this.primary = "bgt_budgetmutatie_key";
    this.autfunction = "WEB_BGTUSE";
    this.record_title = L("bgt_budgetmutatie");
    this.records_title = L("bgt_budgetmutatie_m");


    var p_budget_key  = getQParamInt("budgetcommon", -1);
    var p_mutatie_key = getQParamInt("id", -1);
    var budgetnaam_sql = "SELECT NULL bgt_budget_key"
                       + "     , 'E '||" + safe.quoted_sql(L("bgt_budgetmutatie_extbudget")) + " bgt_budget_naam"
                       + "     , NULL fin_btwtabelwaarde_perc"
                       + " FROM DUAL"
                       + " UNION "
                       + "SELECT b.bgt_budget_key"
                       + "     , CASE WHEN b.prs_kostensoort_key IS NOT NULL"
                                 + "  THEN s.prs_kostensoort_oms"
                                 + "  ELSE CASE WHEN b.prs_kostensoortgrp_key IS NOT NULL"
                                           + "  THEN g.prs_kostensoortgrp_oms"
                                           + "  ELSE CASE WHEN b.bgt_kostenrubriek_key IS NOT NULL"
                                                     + "  THEN r.bgt_kostenrubriek_oms"
                                                     + "  ELSE " + safe.quoted_sql(L("bgt_budgetmutatie_reserve"))
                                                + "  END"
                                      + "  END"
                       + "       END bgt_budget_naam"
                       + "     , f.fin_btwtabelwaarde_perc"
                       + "  FROM bgt_budget         b"
                       + "     , bgt_kostenrubriek  r"
                       + "     , prs_kostensoortgrp g"
                       + "     , prs_kostensoort    s"
                       + "     , fin_btwtabelwaarde f"
                       + " WHERE b.bgt_kostenrubriek_key  = r.bgt_kostenrubriek_key(+)"
                       + "   AND b.prs_kostensoortgrp_key = g.prs_kostensoortgrp_key(+)"
                       + "   AND b.prs_kostensoort_key    = s.prs_kostensoort_key(+)"
                       + "   AND s.fin_btwtabelwaarde_key = f.fin_btwtabelwaarde_key(+)"
                       + ( p_budget_key > -1
                         ? "   AND b.bgt_project_key = "
                         + "(SELECT p.bgt_project_key"
                         + "   FROM bgt_budget p"
                         + "  WHERE bgt_budget_key = " + p_budget_key
                         + ")"
                         : ""
                         );

    this.fields = {
        "id": {
            "dbs": "bgt_budgetmutatie_key",
            "label": L("lcl_key"),
            "typ": "key",
            "hidden_fld": true,
            "required": true,
            "seq": "bgt_s_bgt_budgetmutatie_key"
        },
        "mutationdate": {
            "dbs": "bgt_budgetmutatie_datum",
            "label": L("bgt_budgetmutatie_datum"),
            "typ": "date",
            "required": true,
            "defaultvalue": new Date()
        },
        "name": {
            "dbs": "bgt_budgetmutatie_omschrijving",
            "label": L("bgt_budgetmutatie_oms"),
            "typ": "varchar",
            "required": true
        },
        "code": {
            "dbs": "bgt_budgetmutatie_code",
            "label": L("bgt_budgetmutatie_code"),
            "typ": "varchar",
            "LOV": budgetmutatie_code_LOV()
        },
        "sequence": {
            "dbs": "bgt_budgetmutatie_volgnr",
            "label": L("bgt_budgetmutatie_volgnr"),
            "typ": "number"
        },
        "ident": {
            "dbs": "bgt_budgetmutatie_identity",
            "sql": "COALESCE(bgt_budgetmutatie_code || TO_CHAR(bgt_budgetmutatie_volgnr), TO_CHAR(bgt_budgetmutatie_key))",
            "label": "Volgnr",
            "typ": "varchar"
        },
        "adjustedby": {
            "dbs": "prs_perslid_key",
            "label": L("bgt_budgetmutatie_door"),
            "typ": "key",
            "foreign": "PRS_PERSLID",
            "required": true,
            "defaultvalue": user_key
        },
        "budgetfrom": {
            "dbs": "bgt_budget_key_van",
            "label": L("bgt_budgetmutatie_van"),
            "typ": "key",
            "foreign": {
               "tbl": "(" + budgetnaam_sql + ")",
               "key": "bgt_budget_key",
               "desc": "bgt_budget_naam"
            },
            "emptyoption": L("bgt_budgetmutatie_extbudget")
        },
        "budgetto": {
            "dbs": "bgt_budget_key_naar",
            "label": L("bgt_budgetmutatie_naar"),
            "typ": "key",
            "foreign": {
                "tbl": "(" + budgetnaam_sql + ")",
                "key": "bgt_budget_key",
                "desc": "bgt_budget_naam"
            },
            "emptyoption": L("bgt_budgetmutatie_extbudget")
        },
        "amountfrom": {
            "dbs": "bgt_budget_bedrag_van",
            "label": L("bgt_budgetmutatie_bedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true,
            "hidden_fld": true
        },
        "vatfrom": {
            "dbs": "bgt_budget_btwbedrag_van",
            "label": L("bgt_budgetmutatie_btwbedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true,
            "hidden_fld": true
        },
        "amountfromexc": {
            "dbs": "bgt_budget_bedrag_van_exc",
            "sql": "CASE WHEN bgt_budget_key_van IS NULL THEN NULL ELSE bgt_budget_bedrag_van END",
            "label": L("bgt_budgetmutatie_bedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true
        },
        "amountfromvat": {
            "dbs": "bgt_budget_bedrag_van_btw",
            "sql": "CASE WHEN bgt_budget_key_van IS NULL THEN NULL ELSE bgt_budget_btwbedrag_van END",
            "label": L("bgt_budgetmutatie_btwbedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true
        },
        "amountfrominc": {
            "dbs": "bgt_budget_bedrag_van_incl",
            "sql": "COALESCE(bgt_budget_bedrag_van, 0) + COALESCE(bgt_budget_btwbedrag_van, 0)",
            "label": L("lcl_fin_total_sum"),
            "typ": "float",
            "readonly": true,
            "sqlshow": false,
            "iscurrency": true,
            "defaultvalue": "0"
        },
        "amountto": {
            "dbs": "bgt_budget_bedrag_naar",
            "label": L("bgt_budgetmutatie_bedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true
        },
        "vatto": {
            "dbs": "bgt_budget_btwbedrag_naar",
            "label": L("bgt_budgetmutatie_btwbedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true
        },
        "amounttoexc": {
            "dbs": "bgt_budget_bedrag_naar_exc",
            "sql": "CASE WHEN bgt_budget_key_naar IS NULL THEN NULL ELSE bgt_budget_bedrag_naar END",
            "label": L("bgt_budgetmutatie_bedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true
        },
        "amounttovat": {
            "dbs": "bgt_budget_bedrag_naar_btw",
            "sql": "CASE WHEN bgt_budget_key_naar IS NULL THEN NULL ELSE bgt_budget_btwbedrag_naar END",
            "label": L("bgt_budgetmutatie_btwbedrag"),
            "typ": "float",
            "iscurrency": true,
            "total": true
        },
        "amounttoinc": {
            "dbs": "bgt_budget_bedrag_naar_incl",
            "sql": "COALESCE(bgt_budget_bedrag_naar, 0) + COALESCE(bgt_budget_btwbedrag_naar, 0)",
            "label": L("lcl_fin_total_sum"),
            "typ": "float",
            "readonly": true,
            "sqlshow": true,
            "iscurrency": true,
            "defaultvalue": "0"
        },
        "mutbudgetexc": {
            "dbs": "bgt_budget_mutatie_exc",
            "sql": "BGT.getMutatieOpBudget("+p_budget_key+", bgt_budgetmutatie_key, 0)",
            "label": L("bgt_budgetmutatie_bedrag"),
            "typ": "float",
            "readonly": true,
            "iscurrency": true,
            "total": true
        },
        "mutbudgetvat": {
            "dbs": "bgt_budget_mutatie_btw",
            "sql": "BGT.getMutatieOpBudget("+p_budget_key+", bgt_budgetmutatie_key, 1)",
            "label": L("bgt_budgetmutatie_btwbedrag"),
            "typ": "float",
            "readonly": true,
            "iscurrency": true,
            "total": true
        },
        "budgetdiscipline": {
            "dbs": "bgt_budget.ins_discipline_key",
            "label": L("bgt_discipline_omschrijving"),
            "typ": "key",
            "foreign": bgt_budgetdiscipline_foreign(),
            "hidden_fld": true
        },
        "budgetproject": {
            "dbs": "bgt_budget.bgt_project_key",
            "label": L("bgt_project_omschrijving"),
            "typ": "key",
            "foreign": bgt_budgetproject_foreign(),
            "delayload": true,
            "hidden_fld": true
        },
        "budgetcostcategory": {
            "dbs": "bgt_budget.bgt_kostenrubriek_key",
            "label": L("bgt_kostenrubriek_oms"),
            "typ": "key",
            "foreign": bgt_budgetcostcategory_foreign(),
            "delayload": true,
            "hidden_fld": true
        }
    };

    this.edit = {
        "modal": true
    };

    this.list = {
        "columns": [
            "mutationdate",
            "sequence",
            "code",
            //"ident",
            "name",
            "budgetfrom",
            "amountfromexc",
            "amountfromvat",
            "budgetto",
            "amountto",
            "vatto",
            "amounttoexc",
            "amounttovat"
        ]
    };

    function budgetmutatie_code_LOV()
    {
        var mutatie_code = "A;A - " + L("bgt_budgetmutatie_code_a")   + ";"
                         + "W;W - " + L("bgt_budgetmutatie_code_w")   + ";"
                         + "E;E - " + L("bgt_budgetmutatie_code_e")   + ";"
                         + "M;M - " + L("bgt_budgetmutatie_code_m")   + ";"
                         + "O;O - " + L("bgt_budgetmutatie_code_o")   + ";"
                         + "R;R - " + L("bgt_budgetmutatie_code_r");
        return mutatie_code;
    }

    function getNextSequence(p_project_key)
    {
        var sql = "SELECT COALESCE(MAX(m.bgt_budgetmutatie_volgnr),0) + 1"
                + "   FROM bgt_budget b"
                + "      , bgt_budgetmutatie m"
                + "  WHERE (  b.bgt_budget_key = m.bgt_budget_key_naar"
                + "        OR b.bgt_budget_key = m.bgt_budget_key_van"
                + "        )"
                + "    AND b.bgt_project_key = " + p_project_key;
        var oRs = Oracle.Execute(sql);
        var new_sequence = oRs(0).Value;
        oRs.Close();
        return new_sequence;
    }

    this.hook_pre_edit = function (obj, fld)
    {
        var btw_data = {};
        fld.amountto.label = L("bgt_budgetmutatie_bedrag");
        if (!obj.id) // nieuwe mutatie: wanneer en door wie wordt op de achtergrond gevuld
        {
            fld.adjustedby.hidden_fld = true;
        }
        else // bestaande mutatie: alleen de omschrijving en bedrag is aan te passen
        {
            fld.adjustedby.readonly = true;

            var sql = "SELECT s.prs_kostensoort_btw"
                    + "     , f.fin_btwtabelwaarde_perc"
                    + "  FROM bgt_budgetmutatie m"
                    + "     , bgt_budget b"
                    + "     , prs_kostensoort s"
                    + "     , fin_btwtabelwaarde f"
                    + " WHERE s.fin_btwtabelwaarde_key = f.fin_btwtabelwaarde_key"
                    + "   AND b.prs_kostensoort_key = s.prs_kostensoort_key"
                    + "   AND m.bgt_budget_key_naar = b.bgt_budget_key"
                    + "   AND m.bgt_budgetmutatie_key = " + obj.id;
            var oRs = Oracle.Execute(sql);
            if (!oRs.eof)
            {
                btw_data.btw_inc = oRs("prs_kostensoort_btw").Value;
                btw_data.btw_val = oRs("fin_btwtabelwaarde_perc").Value;
            }
            oRs.Close();

            var sql = "SELECT COALESCE(bgt_budgetmutatie_volgnr,-1) bgt_budgetmutatie_volgnr"
                    + "  FROM bgt_budgetmutatie"
                    + " WHERE bgt_budgetmutatie_key = " + obj.id;
            var oRs = Oracle.Execute(sql);
            var volgnr_oud = oRs("bgt_budgetmutatie_volgnr").Value;
            oRs.Close();
            if (volgnr_oud == -1)
            {
                fld.code.readonly = true;
                fld.sequence.readonly = true;
            }
            else
            {
                fld.sequence.required = true;
            }
        }

        var budgetcommon_key       = getQParamInt("budgetcommon",        0);
        var budgetdiscipline_key   = getQParamInt("budgetdiscipline",   -1);
        var budgetproject_key      = getQParamInt("budgetproject",      -1);
        var budgetcostcategory_key = getQParamInt("budgetcostcategory", -1);

        // Nieuw volgnummer genereren.
        var seq_prj_key = budgetproject_key; // Deze wordt gebruikt vanuit Projectadministratie
        if (budgetcommon_key)
        {                                    // Deze wordt gebruikt vanuit Budgetbewaking.
            var sql = "SELECT bgt_project_key"
                    + "  FROM bgt_budget"
                    + " WHERE bgt_budget_key = " + budgetcommon_key;
            var oRs = Oracle.Execute(sql);
            if (!oRs.eof)
                seq_prj_key = oRs("bgt_project_key").Value;
            oRs.Close();
        }
        var next_sequence = getNextSequence(seq_prj_key);

        if (budgetcommon_key == -1 && budgetdiscipline_key != -1 && budgetproject_key != -1)
        { // via de selectieparams van budgetmutatie/search
%>
    <script>
            var budgetdiscipline_key = <%=budgetdiscipline_key%>;
            var budgetproject_key = <%=budgetproject_key%>;
            if (<%=budgetcostcategory_key%> != -1) var budgetcostcategory_key = <%=budgetcostcategory_key%>;
    </script>
<%
        }
%>
    <script>
        // Deze variabelen zijn nodig in bgt_budgetmutatie.js
        var budget_key = <%=p_budget_key%>;
        var mutatie_key = <%=p_mutatie_key%>;
        var nextsequence = <%=next_sequence%>;
        var btw_data = <%=JSON.stringify(btw_data)%>;
    </script>
<%
    }

    this.hook_pre_post = function (params, jsondata)
    {
        if (jsondata.budgetfrom == jsondata.budgetto)
            abort_with_warning(L("bgt_budgetmutatie_err1").format(L("bgt_budgetmutatie_van"), L("bgt_budgetmutatie_naar")));

        if ((!jsondata.amountto || jsondata.amountto == 0) && (!jsondata.vatto || jsondata.vatto == 0))
            abort_with_warning(L("bgt_budgetmutatie_err2").format(L("bgt_budgetmutatie_bedrag"), L("bgt_budgetmutatie_btwbedrag")));
        if (jsondata.amountto < 0 || jsondata.vatto < 0)
            abort_with_warning(L("bgt_budgetmutatie_err3"));
        jsondata.amountfrom = -1 * jsondata.amountto;
        jsondata.vatfrom    = -1 * jsondata.vatto;

        if (jsondata.budgetfrom == -1 || jsondata.budgetto == -1)
            jsondata.code = "E";

        // Gebruiker heeft zelf al een volgnummer ingevuld. Controleer of deze geldig is.
        if (jsondata.sequence)
        {
            var budget_key = ((jsondata.budgetfrom && jsondata.budgetfrom != -1) ? jsondata.budgetfrom : jsondata.budgetto);
            var sql = "SELECT bgt_project_key"
                    + "  FROM bgt_budget"
                    + " WHERE bgt_budget_key = " + budget_key;
            var oRs = Oracle.Execute(sql);
            var project_key = oRs("bgt_project_key").Value;
            oRs.Close();
            if (check_volgnr(project_key, jsondata.sequence))
                abort_with_warning(L("bgt_budgetmutatie_err4"));
        }
    }

    this.hook_post_post = function (params, jsondata, key)
    {
        // Alleen handmatig toegevoegde mutatie krijgen een volgnummer.
        // Deze zijn uniek binnen het subproject.
        if (!jsondata.sequence)
        {
            var sql = "UPDATE bgt_budgetmutatie"
                    + "   SET bgt_budgetmutatie_volgnr ="
                    + "       (SELECT COALESCE(MAX(m.bgt_budgetmutatie_volgnr),0) + 1"
                           + "   FROM bgt_budget b"
                           + "      , bgt_budgetmutatie m"
                           + "  WHERE (  b.bgt_budget_key = m.bgt_budget_key_naar"
                           + "        OR b.bgt_budget_key = m.bgt_budget_key_van"
                           + "        )"
                           + "    AND b.bgt_project_key = (SELECT bs.bgt_project_key"
                                                       + "   FROM bgt_budget bs"
                                                       + "      , bgt_budgetmutatie ms"
                                                       + "  WHERE bs.bgt_budget_key = COALESCE(ms.bgt_budget_key_van, ms.bgt_budget_key_naar)"
                                                       + "    AND ms.bgt_budgetmutatie_key = " + key
                                                       + ")"
                    + "       )"
                    + " WHERE bgt_budgetmutatie_key = " + key;
            Oracle.Execute(sql);

            if (jsondata.budgetfrom > -1 && jsondata.budgetto > -1)
            {
                // Haal de budget-keys voor correctie uit het mutatierecord.
                // Alleen als beide keys bestaan.
                var sql = "SELECT bgt_budget_key_van"
                        + "     , bgt_budget_key_naar"
                        + "  FROM bgt_budgetmutatie"
                        + " WHERE bgt_budgetmutatie_key = " + key;
                var oRs = Oracle.Execute(sql);
                if (!oRs.eof)
                {
                    mutatie_correctie(oRs("bgt_budget_key_van").Value);
                    mutatie_correctie(oRs("bgt_budget_key_naar").Value);
                }
                oRs.Close();
            }
        }
    }

    this.hook_pre_put = function (params, jsondata, key)
    {
        if ((!jsondata.amountto || jsondata.amountto == 0) && (!jsondata.vatto || jsondata.vatto == 0))
            abort_with_warning(L("bgt_budgetmutatie_err2").format(L("bgt_budgetmutatie_bedrag"), L("bgt_budgetmutatie_btwbedrag")));

        var sign_amountto = Math.sign(jsondata.amountto);
        var sign_vatto    = Math.sign(jsondata.vatto);
        if ( (sign_amountto == 0 ? sign_vatto : sign_amountto) != (sign_vatto == 0 ? sign_amountto : sign_vatto) )
            abort_with_warning(L("bgt_budgetmutatie_err6"));

        jsondata.amountfrom = -1 * jsondata.amountto;
        jsondata.vatfrom    = -1 * jsondata.vatto;

        // Indien het volgnummer gewijzigd is moet gecontroleerd worden of het volgnummer dan niet dubbel voor komt.
        var sql = "SELECT COALESCE(bgt_budgetmutatie_volgnr,-1) bgt_budgetmutatie_volgnr"
                + "  FROM bgt_budgetmutatie"
                + " WHERE bgt_budgetmutatie_key = " + key;
        var oRs = Oracle.Execute(sql);
        var volgnr_oud = oRs("bgt_budgetmutatie_volgnr").Value;
        oRs.Close();
        if (volgnr_oud != -1)  // Het is een handmatig toegevoegde mutatie, dus moet een volgnummer blijven houden.
        {
            if (!jsondata.sequence && (("AW").indexOf(jsondata.code) < 0))
                abort_with_warning(L("bgt_budgetmutatie_err5"));

            if (jsondata.sequence != volgnr_oud)
            {
                var sql = "SELECT bs.bgt_project_key"
                        + "   FROM bgt_budget bs"
                        + "      , bgt_budgetmutatie ms"
                        + "  WHERE bs.bgt_budget_key = COALESCE(ms.bgt_budget_key_van, ms.bgt_budget_key_naar)"
                        + "    AND ms.bgt_budgetmutatie_key = " + key;
                var oRs = Oracle.Execute(sql);
                var project_key = oRs("bgt_project_key").Value;
                oRs.Close();
                if (check_volgnr(project_key, jsondata.sequence))
                    abort_with_warning(L("bgt_budgetmutatie_err4"));
            }
        }
     }

    this.hook_post_put = function(params, jsondata, key)
    {
        // Haal de budget-keys voor correctie uit het mutatierecord.
        var sql = "SELECT m.bgt_budget_key_van"
                + "     , m.bgt_budget_key_naar"
                + "     ,  (SELECT MAX(b.bgt_budget_isreserve)"
                        + "   FROM bgt_budget b"
                        + "  WHERE b.bgt_budget_key IN (m.bgt_budget_key_van, m.bgt_budget_key_naar)"
                        + ") is_reserve"
                + "  FROM bgt_budgetmutatie m"
                + " WHERE m.bgt_budgetmutatie_key = " + key;
        var oRs = Oracle.Execute(sql);
        if (!oRs.eof)
        {
            if (oRs("bgt_budget_key_van").Value && oRs("bgt_budget_key_naar").Value && (oRs("is_reserve").Value == 0))
            {   // Alleen als beide budget-keys bestaan is het een mutatie correctie
                // Als er maar 1 budget-key is, gaat het om toevoegen of onttrekken van budget (eigenlijk een E-mutatie)
                // Laat mutaties met reserve toe.
                mutatie_correctie(oRs("bgt_budget_key_van").Value);
                mutatie_correctie(oRs("bgt_budget_key_naar").Value);
            }
        }
        oRs.Close();
    }

    function contract_waarde(p_budget_key)
    {
        var v_contract = { bedrag_exc: 0
                         , bedrag_btw: 0
                         };
        var sql = "SELECT SUM(COALESCE(o.mld_opdr_kosten, 0)) contract_exc"
                + "     , SUM(COALESCE(o.mld_opdr_kosten_btw, 0)) contract_btw"
                + "  FROM bgt_budget b"
                + "     , mld_opdr   o"
                + " WHERE b.prs_kostensoort_key = o.prs_kostensoort_key(+)"
                + "   AND b.bgt_budget_key = " + p_budget_key;
        var oRs = Oracle.Execute(sql);
        if (!oRs.eof)
        {
            v_contract.bedrag_exc = oRs("contract_exc").Value;
            v_contract.bedrag_btw = oRs("contract_btw").Value;
        }
        oRs.Close();
        return v_contract;
    }

    function budget_waarde(p_budget_key)
    {
        var v_budget = { bedrag_exc: 0
                       , bedrag_btw: 0
                       , isreserve: true
                       , reserve_key: -1
                       };
        var sql = "SELECT b.bgt_budget_isreserve"
                + "     , COALESCE(b.bgt_budget_bedrag, 0)    bgt_budget_exc"
                + "     , COALESCE(b.bgt_budget_btwbedrag, 0) bgt_budget_btw"
                + "     , r.bgt_budget_key"
                + "  FROM bgt_budget r"
                + "     , bgt_budget b"
                + " WHERE r.bgt_project_key = b.bgt_project_key"
                + "   AND r.prs_kostensoort_key IS NULL"
                + "   AND r.prs_kostensoortgrp_key IS NULL"
                + "   AND b.bgt_budget_key = " + p_budget_key;
        var oRs = Oracle.Execute(sql);
        if (!oRs.eof)
        {
            v_budget.bedrag_exc  = oRs("bgt_budget_exc").Value;
            v_budget.bedrag_btw  = oRs("bgt_budget_btw").Value;
            v_budget.isreserve   = oRs("bgt_budget_isreserve").Value == 1;
            v_budget.reserve_key = oRs("bgt_budget_key").Value;
        }
        oRs.Close();
        return v_budget;
    }

    function mutatie_waarde(p_budget_key, p_reserve)
    {
        var van_reserve = { bedrag_exc: 0
                          , bedrag_btw: 0
                          };
        switch (p_reserve)
        {
            case "A": sql_res = " AND  m.bgt_budgetmutatie_reserve = 1"; break;  // alleen automatische overboekingen
            case "M": sql_res = " AND  m.bgt_budgetmutatie_reserve = 0"; break;  // alleen mutaties
            case "T": sql_res = ""; break;                                       // totaal alle mutaties
            default: "";
        }
        var sql = "SELECT SUM(COALESCE(bedrag_exc, 0)) bedrag_exc"
                + "     , SUM(COALESCE(bedrag_btw, 0)) bedrag_btw"
                + "  FROM (SELECT SUM(COALESCE(m.bgt_budget_bedrag_van,    0)) bedrag_exc"
                       + "      , SUM(COALESCE(m.bgt_budget_btwbedrag_van, 0)) bedrag_btw"
                       + "   FROM bgt_budgetmutatie m"
                       + "  WHERE bgt_budget_key_van = " + p_budget_key
                       + sql_res
                       + " UNION"
                       + " SELECT SUM(COALESCE(m.bgt_budget_bedrag_naar,    0)) bedrag_exc"
                       + "      , SUM(COALESCE(m.bgt_budget_btwbedrag_naar, 0)) bedrag_btw"
                       + "   FROM bgt_budgetmutatie m"
                       + "  WHERE bgt_budget_key_naar = " + p_budget_key
                       + sql_res
                       + ")";
        var oRs = Oracle.Execute(sql);
        if (!oRs.eof)
        {
            van_reserve.bedrag_exc = oRs("bedrag_exc").Value;
            van_reserve.bedrag_btw = oRs("bedrag_btw").Value;
        }
        oRs.Close();
        return van_reserve;
    }

    function mutatie_correctie(p_budget_key)
    {
        function een_correctie(p_budget_key, p_budget_bedrag, p_uitreserve_bedrag, p_contract_bedrag)
        {
            // Als een deel van het budgetbedrag uit automatische overboeking bestaat kan het budgetbedrag nooit groter zijn dan het contractbedrag.
            var te_contracteren = p_budget_bedrag - p_contract_bedrag;
            var naar_reserve = ( (te_contracteren > p_uitreserve_bedrag) ? p_uitreserve_bedrag : te_contracteren);
            return naar_reserve;
        }

        var v_budget = budget_waarde(p_budget_key);
        var v_uitreserve = mutatie_waarde(p_budget_key, "A");
        var v_contracten = contract_waarde(p_budget_key);

        if (!v_budget.isreserve)
        {   // Correctie is alleen voor budgetten op kostensoort, niet het reserve.
            var v_correctie_bedrag_exc = een_correctie(p_budget_key, v_budget.bedrag_exc, v_uitreserve.bedrag_exc, v_contracten.bedrag_exc);
            var v_correctie_bedrag_btw = een_correctie(p_budget_key, v_budget.bedrag_btw, v_uitreserve.bedrag_btw, v_contracten.bedrag_btw);

            var data_correctie = { budget_res_key: v_budget.reserve_key
                                 , budget_srt_key: p_budget_key
                                 , bedrag_exc: v_correctie_bedrag_exc
                                 , bedrag_btw: v_correctie_bedrag_btw
                                 };
            insertMutatie(data_correctie, "AO");
        }
    }

    function insertMutatie(data_mutatie, mutatie_soort)
    {
        if (data_mutatie.bedrag_exc != 0 || data_mutatie.bedrag_btw != 0)
        {
            var sql = "SELECT prs_kostensoort_altcode"
                    + "  FROM prs_kostensoort"
                    + " WHERE prs_kostensoort_key = "
                        + " (SELECT MIN(prs_kostensoort_key)"
                        + "    FROM bgt_budget"
                        + "   WHERE bgt_budget_key = " + data_mutatie.budget_srt_key
                        + " )";
            var oRs = Oracle.Execute(sql);
            var v_costtype_code = oRs("prs_kostensoort_altcode").Value;
            oRs.Close();

            var mutatie_omschr = "";
            var mutatie_code = "";
            switch (mutatie_soort)
            {
                case "AO": mutatie_omschr = "AO Automatische overboeking";
                           mutatie_code = "A";
                           break;
                case "MW": mutatie_omschr = "MW Meer-, minderwerk van " + v_costtype_code;
                           mutatie_code = "W";
                           break;
            }

            var sql_m = "INSERT INTO bgt_budgetmutatie"
                      + "( bgt_budgetmutatie_datum"
                      + ", bgt_budgetmutatie_omschrijving"
                      + ", prs_perslid_key" // not null!
                      + ", bgt_budget_key_van"
                      + ", bgt_budget_bedrag_van"
                      + ", bgt_budget_btwbedrag_van"
                      + ", bgt_budget_key_naar"
                      + ", bgt_budget_bedrag_naar"
                      + ", bgt_budget_btwbedrag_naar"
                      + ", bgt_budgetmutatie_reserve"
                      + ", bgt_budgetmutatie_code"
                      + ") VALUES"
                      + "( SYSDATE"
                      + ", " + safe.quoted_sql(mutatie_omschr)
                      + ", " + user_key
                      + ", " + data_mutatie.budget_res_key
                      + ", " + data_mutatie.bedrag_exc
                      + ", " + data_mutatie.bedrag_btw
                      + ", " + data_mutatie.budget_srt_key
                      + ", " + (-1 * data_mutatie.bedrag_exc)
                      + ", " + (-1 * data_mutatie.bedrag_btw)
                      + ", 1"
                      + ", " + safe.quoted_sql(mutatie_code)
                      + ")";
            Oracle.Execute(sql_m);
        }
    }

    function check_volgnr(p_project_key, p_volgnr)
    {
        var sql = "SELECT MAX(CASE WHEN m.bgt_budgetmutatie_volgnr = " + p_volgnr
                + "                THEN 1"
                + "                ELSE 0"
                + "           END) volgnr_aanwezig"
                + "  FROM bgt_budget b"
                + "     , bgt_budgetmutatie m"
                + " WHERE (  b.bgt_budget_key = m.bgt_budget_key_naar"
                + "       OR b.bgt_budget_key = m.bgt_budget_key_van"
                + "       )"
                + "   AND b.bgt_project_key = " + p_project_key;
        var oRs = Oracle.Execute(sql);
        var volgnr_bestaat = oRs("volgnr_aanwezig").Value == 1;
        oRs.Close();
        return volgnr_bestaat;
    }


    var budget_key = getQParamInt("budgetcommon", -1);
    var mutatie_key = getQParamInt("id", -1);
    var budgetdiscipline_key = getQParamInt("budgetdiscipline", -1);
    var budgetproject_key = getQParamInt("budgetproject", -1);
    var budgetcostcategory_key = getQParamIntArray("budgetcostcategory", []);
    var code = getQParamArray("code", []);

    var gparams = {
            GET: {
                tables: ["bgt_budget"],
                wheres: ["(bgt_budget.bgt_budget_key = bgt_budgetmutatie.bgt_budget_key_van OR bgt_budget.bgt_budget_key = bgt_budgetmutatie.bgt_budget_key_naar)"]
            }
        };
    gparams.GET["filter"] = { nolimit :true };

    if (budget_key > -1)
    {
        var v_where = ( mutatie_key > -1
                      ? "bgt_budgetmutatie_key = {0}".format(mutatie_key)
                      : "(bgt_budget.bgt_budget_key = {0})".format(budget_key)
                      );
        gparams.GET.wheres.push(v_where);
    }
    else
    {
        if (budgetdiscipline_key          > -1) gparams.GET.wheres.push("bgt_budget.ins_discipline_key = " + budgetdiscipline_key);
        if (budgetproject_key             > -1) gparams.GET.wheres.push("bgt_budget.bgt_project_key = " + budgetproject_key);
        if (budgetcostcategory_key.length >  0) gparams.GET.wheres.push("bgt_budget.bgt_kostenrubriek_key IN (" + budgetcostcategory_key.join(",") + ")");
        if (code.length                   >  0) gparams.GET.wheres.push("bgt_budgetmutatie.bgt_budgetmutatie_code IN (" + safe.quoted_sql_join(code) + ")");
    }

    var autparams = user.checkAutorisation(this.autfunction);
    var canWrite = (autparams.PRSwritelevel < 9 && autparams.ALGwritelevel < 9);
    this.REST_GET = generic_REST_GET(this, gparams);
    // Alleen een mutatie kunnen toevoegen als je van een budget komt, of (in overzichtslijst mutaties) project en deelproject zijn geselecteerd.
    if (p_budget_key > -1 || (canWrite && budgetproject_key > -1))
        this.REST_POST = generic_REST_POST(this);
    if (canWrite)
    {
        this.REST_PUT = generic_REST_PUT(this);
        this.REST_DELETE = generic_REST_DELETE(this);
    }
}
%>