<%@ language = "JavaScript" %>
<% /*
    $Revision$
    $Id$

    File:               res_edit_objcat_save.asp
    Description:        Opslaan van de gegevens uit res_edit_objcat.asp
                        Note that because of many checks and constraints in the input-form
                        availability is almost guaranteed.
    Parameters:
        rsv_ruimte_key required
                        .... alle andere gePOSTte res_edit_objcat form u2 fields

    Context:            Opsla script voor res_edit_objcat.asp maar ook $.post van anderen
    Note:
*/
var JSON_Result = true;
%>

<!-- #include file="../Shared/common.inc" -->
<!-- #include file="../Shared/save2db.inc" -->
<!-- #include file="../Shared/json2.js" -->
<!-- #include file="res.inc"-->

<%
protectRequest.validateToken();
FCLTHeader.Requires({plugins: ["jQuery"], js:[] })

var urole = getQParamSafe("urole");
var rsv_ruimte_key = getQParamInt("rsv_ruimte_key");
var verynew = getQParamInt("verynew",0);

var this_res = res.func_enabled(rsv_ruimte_key); // Wat heb ik zoal aan rechten op deze specifieke reservering
user.auth_required_or_abort(this_res.canChangeCV); // dat is toch wel het minste

res.res_set_dialect(rsv_ruimte_key);

// Zo snel mogelijk relevante basisinformatie opzoeken
sql = "SELECT res_reservering_key, "
    + "       res_rsv_ruimte_van, res_rsv_ruimte_tot,"
    + "       prs_kostenplaats_key,"
    + "       alg_ruimte_key,"
    + "       res_rsv_ruimte_volgnr"
    + "  FROM res_rsv_ruimte"
    + " WHERE res_rsv_ruimte_key = " + rsv_ruimte_key;
oRs = Oracle.Execute(sql);
var res_key = oRs("res_reservering_key").value;
var res_van = new Date(oRs("res_rsv_ruimte_van").value);
var res_tot = new Date(oRs("res_rsv_ruimte_tot").value);
var res_volgnr = oRs("res_rsv_ruimte_volgnr").Value;
if (oRs("alg_ruimte_key").value != null)
  restype = "CV";
else
  restype = "R";

var warning = null;
// Hier wordt de expire getest van de *bestaande* objcat
// Setting "res_cat_with_expired_room": Can catering be edited when room is expired {false | true}.
if ((!S("res_cat_with_expired_room") && res_van < this_res.earliest_expire_change) || (res_van < this_res.earliest_expire_changeCV))
{
  if (this_res.canChangeFEOnly)
      abort_with_warning(L("lcl_res_lastmin")); // te laat
  //later pas..., we weten niet eens of ze iets opengeklapt hebben
  //else
  //    if (urole != "bo")
  //        warning = L("lcl_res_obj_lastminute");
}

var _disc_expires = []; // expire tijd per discipline
function is_expired(disc_key, jsDate)
{
  if (disc_key > 0)
  {
    if (!_disc_expires[disc_key])
      _disc_expires[disc_key] = res.discipline_expire(disc_key);
    return (jsDate < _disc_expires[disc_key]);
  }
}

// artikelen die gesubmit zijn
function resObj(res_deel, res_rsv_deel, van_h, van_m, tot_h, tot_m, i_cnt, i_price)
{
  this.res_deel = res_deel;
  this.res_rsv_deel = res_rsv_deel; // is hier de res_rsv_artikel_key
  this.van_h = van_h;
  this.van_m = van_m;
  this.tot_h = tot_h;
  this.tot_m = tot_m;
  this.cnt = 0;
  if (i_cnt)
    this.cnt = i_cnt;
  this.price = 0;
  if (i_price)
    this.price = i_price;
}

// consumable objects

// artikelen in de database
function artinf(key, rsv_key, pricefixed, disc, quantity, lev_h, lev_m, price, bo_status)
{
    this.key = key;
    this.rsv_key = rsv_key;
    this.pricefixed = pricefixed;
    this.disc = disc;
    this.quantity = quantity;
    this.lev_h = lev_h;
    this.lev_m = lev_m;
    this.price = price;
    this.bo_status = bo_status;
}

var backo = this_res.canWrite("WEB_RESBOF");
var fronto = this_res.canWrite("WEB_RESFOF");

var year = res_van.getFullYear();
var month = res_van.getMonth()+1;
var day = res_van.getDate();

succes = true; // igv twijfel

// reservable objects
var aDel = new Array();
var aUpd = new Array();
var aIns = new Array();

var a_arIns = new Array();

var cur_res_art = null;
var cur_rsv_art = null;
var cur_lev_h = "";
var cur_lev_m = "";
var cur_cnt = 0;
var cur_price = 0;

var pos, lpos, npos, upos;
var sstring = "", pstring;

var must_warn = false; // must I warn about last-minute?

//=================================================
// DEEL EEN: PARSEN VAN HET FORMULIER
//
//
// Request.Form is iets als inpb_c_216_2470136=0,inpbh1_c_216_2470136=14,inpbm1_c_216_2470136=30,inpb_c_217_2470138=0,inpbh1_c_217_2470138=14,inpbm1_c_217_2470138=30,......
// waarbij 216 de res_artikel_key is en 2470136 de res_rsv_artikel_key
// in het geval van catering
for (i = 1; i <= Request.Form.Count; i++)
{
  var fname = Request.Form.key(i);
  var fval = getFParam(fname, "");
  pos = lpos = npos = upos = 0;
  if (fval && fval.length)
  {
    sstring = fname.substring(0,7)
    switch (sstring)
    {
      case "inpbp_c":
      { // JGL: Parsing catering RES_ARTIKEL_KEY price
        // Will only occur for backoffice
        if (cur_res_art)
        {
          if (fname.indexOf("inpbp_c_") >= 0)
          {
            if (fval == "" || isNaN(parseFloat(fval.replace(/,/g, "."))))
            {
              cur_res_art = null;
              cur_rsv_art = null;
              cur_lev_h = "";
              cur_lev_m = "";
              cur_price = 0;
              break;
            }
            cur_price = parseFloat(fval.replace(/,/g, "."));
          }
        }
        break;
      }

      //=================================================
      case "inpbh1_":
      { // JGL: Parsing catering hour
        if (cur_res_art)
        {
          if (fname.indexOf("inpbh1_c_") >= 0)
          { // Het is een catering veld
            if (fval == "" || isNaN(parseInt(fval,10)))
            {
              cur_res_art = null;
              cur_rsv_art = null;
              cur_lev_h = "";
              cur_lev_m = "";
              cur_price = 0;
              break;
            }
            cur_lev_h = parseInt(fval,10);
          }
        }
        break;
      }

      //=================================================
      case "inpbm1_":
      { // JGL: Parsing catering minutes
        if (cur_res_art)
        { // Zal alleen gezet zijn als het aantal ongelijk 0 was
          if (fname.indexOf("inpbm1_c_") >= 0)
          { // Het is een catering veld
            if (fval == "" || isNaN(parseInt(fval,10)))
            {
              cur_res_art = null;
              cur_rsv_art = null;
              cur_lev_h = "";
              cur_lev_m = "";
              cur_price = 0;
              break;
            }
            cur_lev_m = parseInt(fval,10); // De minuten
          }
          if (a_arIns.length && a_arIns[a_arIns.length-1].res_rsv_deel == cur_rsv_art && a_arIns[a_arIns.length-1].res_deel == cur_res_art)
          { // CAPG#161
            __DoLog("Internal error: Attempting to add " + cur_res_art + " twice", "#FF0000");
            __DoLog("Request.Form: " + String(Request.Form));
          }
          else
            a_arIns[a_arIns.length] = new resObj(cur_res_art, cur_rsv_art, cur_lev_h, cur_lev_m, null, null, cur_cnt, cur_price);
        }
        break;
      }

      case "inpb_c_":
      { // JGL: Parsing catering aantal en bepaal catering RES_ARTIKEL_KEY key
        if (cur_res_art)
        {
          cur_res_art = null;
          cur_rsv_art = null;
          cur_lev_h = "";
          cur_lev_m = "";
          cur_price = 0;
        }

        cur_cnt = parseInt(fval, 10); // Onthouden totdat we het uur en de minuten ook hebben
        if (isNaN(cur_cnt) || cur_cnt == 0)
        { // is count corrupted or undefined
          i += (backo? 4 : 2); // skip hours and minutes (and for backo also price and total price)
          continue;
        }
        res_rsv_art = fname.substring(7);
        cur_res_art = res_rsv_art.substring(0,res_rsv_art.indexOf("_")); // Bepaal catering RES_ARTIKEL_KEY key
        cur_rsv_art = res_rsv_art.substring(res_rsv_art.indexOf("_")+1); // Bepaal catering RES_RSV_ARTIKEL_KEY key
        break;
      }
    }
  }
}

var trackarray = [];
//=================================================
// DEEL TWEE: DE OBJECTEN BIJWERKEN
// Onze checkboxen hebben een hidden veld 'has_xxx' waaraan je kunt zien dat het object gereservereerd was
// in het voorheen.
var durationHours = (res_tot - res_van) / 1000/60/60;

for (i = 1; i <= Request.Form.Count; i++)
{
  deel_key = -1;
  var name = Request.Form.key(i);
  if (name.match(/has_[0-9].*/)) // bestaand object
  {
    var deel_key = parseInt(name.substring(4));
    var present = Request.Form("chk_" + deel_key).Count > 0;
    if (!present)
    {
      sql = "DELETE from res_rsv_deel"
          + " WHERE res_rsv_ruimte_key=" + rsv_ruimte_key
          + "   AND res_deel_key = " + deel_key;
      Oracle.Execute(sql);
      __Log("removed " + name + " : " + deel_key);
      //+ "  res.set_delen_clean(" + aDel[i].res_deel + "," + res_van.toSQL() + "); " // Anderen 'clean' geworden vandaag?
      // Tracking toevoegen.
      var deletetrack = res.trackobject(deel_key, "delete");
      trackarray.push(deletetrack);
    }
    else
    {
      // Als we update van de tijdstipjes gaan ondersteunen komt dat hier.
      //+ "  res.set_deel_dirty (" + aUpd[i].res_rsv_deel + "); " // Zelf dirty geworden?
      //+ "  res.set_delen_clean(" + aUpd[i].res_deel + "," + res_van.toSQL() + "); " // Anderen 'clean' geworden vandaag?
    }
  }
  else // misschien nieuw object
  {
    if (name.match(/chk_[0-9].*/))
    {
      var deel_key = parseInt(name.substring(4));
      var old = Request.Form("has_" + deel_key).Count > 0;
      if (!old)
      {
        // Hoe lang mag ik dit deel reserveren?
        var sql = "SELECT p.res_disc_params_maxduur"
                + "     , " + lcl.xsqla("c.ins_discipline_omschrijving", "c.ins_discipline_key")
                + "  FROM res_deel d"
                + "     , res_disc_params p"
                + "     , res_discipline c"
                + " WHERE d.res_discipline_key = p.res_ins_discipline_key"
                + "   AND d.res_discipline_key = c.ins_discipline_key"
                + "   AND d.res_deel_key = " + deel_key;
        var oRs = Oracle.Execute(sql);
        var maxHours = (oRs.Eof ? 0 : oRs("res_disc_params_maxduur").Value);
        if ((maxHours > 0) && (maxHours < durationHours))
        {
           abort_with_warning( oRs("ins_discipline_omschrijving").Value + ": " + L("lcl_res_bad_maxperiod").format(maxHours));
        }
        oRs.Close();

        sql = "INSERT into res_rsv_deel"
            + " (res_rsv_ruimte_key"
            + ", res_deel_key"
            + ", res_rsv_deel_van"
            + ", res_rsv_deel_tot"
            + ", res_rsv_deel_aantal)"
            + " VALUES(" + rsv_ruimte_key
            + "," + deel_key
            + "," + res_van.toSQL(true) // Vooralsnog geen eigen tijdstippen
            + "," + res_tot.toSQL(true)
            + ", 1)";
        // Nu de echte update.
        Oracle.Execute(sql);
        __Log("added " + name + " : " +deel_key);
        // Tracking toevoegen.
        var inserttrack = res.trackobject(deel_key, "insert");
        trackarray.push(inserttrack);
      }
    }
  }

  if (deel_key > 0 && !must_warn)
  {
    // Expire check
    sql = "SELECT res_discipline_key"
        + "  FROM res_deel rd"
        + " WHERE rd.res_deel_key = " + deel_key;
    oRs = Oracle.Execute(sql)
    must_warn = must_warn || is_expired(oRs("res_discipline_key").value, res_van);
  }
}

// Check of er delen dirty zijn (geworden)
var check_fail_sql = "";
if (S("res_fe_allow_dirty") != 1 && this_res.canChangeFEOnly)
{
  check_fail_sql = " if res.dirty_level_all(" + rsv_ruimte_key + ") <> 0 then"
                 + "    raise_application_error (-20000, 'res_m960 "+L("lcl_res_fe_no_dirty")+"');"
                 + " end if;"
}
var sql = "BEGIN"
        + " res.set_delen_dirty (" + rsv_ruimte_key + "); "
        +   check_fail_sql
        + "END;";
var err = Oracle.Execute(sql, true);
if (err.friendlyMsg)
    abort_with_warning(err.friendlyMsg);

// consumable objects

// Haal eerst de (volgens de database) reeds eerder gereserveerde objecten op
// en bewaar die in array r_a_key
// use initial (old) year, month and day when date was changed
sql = " SELECT r_disc.ins_discipline_key,"
    + "        r_art.res_artikel_key,"
    + "        r_r_art.res_rsv_artikel_key,"
    + "        r_r_art.res_rsv_artikel_aantal,"
    + "        TO_CHAR(r_r_art.res_rsv_artikel_levering,'HH24') hh,"
    + "        TO_CHAR(r_r_art.res_rsv_artikel_levering,'MI') mi,"
    + "        r_art.res_artikel_prijs_vast vast, "
    + "        COALESCE(r_r_art.res_rsv_artikel_prijs/r_r_art.res_rsv_artikel_aantal, r_art.res_artikel_prijs, 0) prijs,"
    + "        r_r_art.res_status_BO_key"
    + " FROM res_v_aanwezigdiscipline r_disc,"
    + "      res_v_aanwezigartikel r_art,"
    + "      res_v_aanwezigrsv_artikel r_r_art,"
    + "      res_v_aanwezigrsv_ruimte r_r_Rmt"
    + " WHERE r_r_art.res_rsv_ruimte_key = r_r_Rmt.res_rsv_ruimte_key"
    + "   and r_r_art.res_rsv_ruimte_key = " + rsv_ruimte_key
    + "   AND r_r_art.res_artikel_key = r_art.res_artikel_key            "
    + "   AND r_art.res_discipline_key = r_disc.ins_discipline_key"
    + " ORDER BY ins_discipline_volgnr, " + lcl.xsql('ins_discipline_omschrijving', 'r_disc.ins_discipline_key') + ", res_artikel_nr";


oRs = Oracle.Execute(sql);
var r_a_key = new Array();
while ( !oRs.eof )
{
  r_a_key[r_a_key.length] = new artinf(oRs("res_artikel_key").value, oRs("res_rsv_artikel_key").value, oRs("vast").value, oRs("ins_discipline_key").value,
                                       oRs("res_rsv_artikel_aantal").value,
                                       oRs("hh").value, oRs("mi").value, oRs("prijs").value, oRs("res_status_BO_key").value);
  oRs.MoveNext();
}
oRs.Close();

var cnt;

reserved = 0;
// delete and update are based on the list of previously reserved objects
for (i = 0; i < r_a_key.length; i++)
{
  art_rsv_key = r_a_key[i].key + "_" + r_a_key[i].rsv_key;
  if (Request.Form("inpb_c_" + art_rsv_key).Count)
  { // De categorie was opgeklapt-->Hij was zichtbaar
    cnt = parseInt(Request.Form("inpb_c_" + art_rsv_key), 10);
    if (!isNaN(cnt) && cnt == 0)
    { // delete maar gewoon echt
      sql = "DELETE FROM res_rsv_artikel"
          + " WHERE res_rsv_ruimte_key=" + rsv_ruimte_key
          + "   AND res_artikel_key = " + r_a_key[i].key
          + "   AND res_rsv_artikel_key = " + r_a_key[i].rsv_key;
      Oracle.Execute(sql);
      // Tracking toevoegen.
      var deletetrack = res.trackartikel(r_a_key[i].key, "delete");
      trackarray.push(deletetrack);
      continue;
    }
    cur_price = Request.Form("inpbp_c_" + art_rsv_key);
    cur_price = (cur_price == "" ? "0.00" : cur_price);
    cur_price = parseFloat(String(cur_price).replace(/,/g,"."));
    if (!isNaN(cnt) && (!backo || !isNaN(cur_price)))
    { // update, negatieve aantallen en negatieve prijs mogelijk
      cur_lev_h = parseInt(Request.Form("inpbh1_c_" + art_rsv_key), 10);
      cur_lev_m = parseInt(Request.Form("inpbm1_c_" + art_rsv_key), 10);
      if (isNaN(cur_lev_m) || isNaN(cur_lev_h))
      { // we do nothing when datetime is corrupted,
        continue; // should report about this error?
      }
      // Never cyclic updates
      var jsDate = new Date(year, month-1, day, cur_lev_h, cur_lev_m)
      must_warn = must_warn || is_expired(r_a_key[i].disc, jsDate);
      var bIsAfgemeld = (r_a_key[i].bo_status == 5 || r_a_key[i].bo_status == 6);
      var oudeAantal = r_a_key[i].quantity;
      var oudeLevH = r_a_key[i].lev_h;
      var oudeLevM = r_a_key[i].lev_m;
      var oudePrijs = r_a_key[i].price;
      var oudeDatum = new Date(year, month-1, day, oudeLevH, oudeLevM)
      // FO kan alleen aantal en tijd aanpassen
      sql = "BEGIN "
          + "UPDATE res_rsv_artikel"
          + " SET res_rsv_artikel_aantal = " + cnt
      // res_rsv_artikel_prijs moet bijgewerkt worden als
      // 1) bij wijzigbare vrije-prijs reserveringen. Alleen de BO kan dat.
      // 2) bij afgemelde reserveringen
      if (backo && r_a_key[i].pricefixed == 0)
      { // De backoffice had het bedrag in beeld dus kunnen we hier direct vermenigvuldigen.
        sql += ",res_rsv_artikel_prijs = " + parseFloat((cnt * cur_price).toFixed(2))
      }
      else if (oudeAantal != cnt)
      { // frontoffice en frontend hebben mogelijk het aantal aangepast. De prijs konden ze niet bij
        // mogelijk is res_rsv_artikel_prijs nog niet ingevuld, dat gaat hier wel goed (NULL==>NULL)
        sql += " ,res_rsv_artikel_prijs = res_rsv_artikel_prijs / " + oudeAantal + " * " + cnt;
      }
      sql +=", res_rsv_artikel_levering = " + jsDate.toSQL(true)
          + " WHERE res_rsv_ruimte_key = " + rsv_ruimte_key
          + " AND res_artikel_key = " + r_a_key[i].key
          + " AND res_rsv_artikel_key = " + r_a_key[i].rsv_key + ";"
          + "  res.set_artikel_dirty (" + r_a_key[i].rsv_key + "); " // Zelf dirty/clean geworden?
          + " END;";
      Oracle.Execute(sql);
      if (oudeAantal != cnt || oudePrijs != cur_price || oudeDatum.getTime() != jsDate.getTime())
      {
        var updatetrack = res.trackartikel(r_a_key[i].key,
                                           "update",
                                           { old_number: oudeAantal,
                                             new_number: cnt,
                                             old_price: oudePrijs,
                                             new_price: cur_price,
                                             old_date: oudeDatum,
                                             new_date: jsDate
                                           });
        trackarray.push(updatetrack);
      }

      reserved++;
      continue;
    }
  }
}

// insert is based on the scanned list of currently reserved objects
for (i = 0; i < a_arIns.length; i++)
{
  for ( j =0; j < r_a_key.length; j++ ) { // r_a_key bevat records die al in de database zitten
    if( r_a_key[j].rsv_key == a_arIns[i].res_rsv_deel ) {
      break; // Deze was al eerder gereserveerd en hebben we als het goed is al bijgewerkt
    }
  }
  if (j == r_a_key.length)
  { // object was not reserved yet
    var jsDate = new Date(year,month-1,day,a_arIns[i].van_h, a_arIns[i].van_m)

    sql = "SELECT ra.res_artikel_prijs_vast"
        + "     , res_discipline_key"
        + "  FROM res_artikel ra"
        + " WHERE ra.res_artikel_key = " + a_arIns[i].res_deel;
    oRs = Oracle.Execute(sql);
    var prijs_vast = oRs("res_artikel_prijs_vast").value == 1;
    var disc_key = oRs("res_discipline_key").value;

    if (!must_warn)
      must_warn = must_warn || is_expired(disc_key, jsDate);

    // Niets aan de hand, toevoegen
    sql = "INSERT INTO res_rsv_artikel"
        + " (res_artikel_key"
        + ", res_rsv_artikel_aantal"
        + ", res_rsv_ruimte_key"
        + ", res_rsv_artikel_prijs"
        + ", res_rsv_artikel_levering)"
        + " VALUES (" + a_arIns[i].res_deel
        + "," + a_arIns[i].cnt
        + "," + rsv_ruimte_key

    // Backo had mogelijk flexprijs in beeld. Sla die dan op
    // Prijs alleen aan te passen als geen vaste prijs (flexprijs)
    if (backo && !isNaN(a_arIns[i].price) && !prijs_vast) // De prijs was in beeld en wijzigbaar
    {
      sql += "," + parseFloat((a_arIns[i].cnt * a_arIns[i].price).toFixed(2))
    }
    else // Fronto: of geen prijs in beeld (vaste prijs artikel)
    {
      sql += ", NULL";
    }
    sql += "," + jsDate.toSQL(true) + ")";
    Oracle.Execute(sql);
    // Tracking toevoegen.
    var inserttrack = res.trackartikel(a_arIns[i].res_deel, "insert");
    trackarray.push(inserttrack);

    reserved++;
  }
}

if (must_warn && urole != "bo")
{
  warning = L("lcl_res_obj_lastminute");
}

// ========================================
// Is er wel iets echts overgebleven bij CV
// ========================================
sql = "SELECT 1"
    + "  FROM res_rsv_deel"
    + " WHERE res_rsv_ruimte_key = " + rsv_ruimte_key
    + "   AND res_rsv_deel_verwijder IS NULL"
    + " UNION"
    + " SELECT 2"
    + "   FROM res_rsv_artikel"
    + "  WHERE res_rsv_ruimte_key = " + rsv_ruimte_key
    + "    AND res_rsv_artikel_verwijder IS NULL";
oRs = Oracle.Execute(sql);
var hasAnyCV = !oRs.Eof;

if (restype == "R")
{
  if (trackarray.length > 0)
    res.trackreserveringupdate(rsv_ruimte_key, trackarray.length? L("lcl_res_is_resupdtrack").format(res_key + "/" + res_volgnr) + "\n" + trackarray.join("\n") : null);
}
else
{ // CV
  sql = "UPDATE res_rsv_ruimte"
      + "   SET res_rsv_ruimte_dirtlevel = " + (hasAnyCV? 0 : res.dirtlevel.ruimte.nocatering)
      + " WHERE res_rsv_ruimte_key = " + rsv_ruimte_key;
  Oracle.Execute(sql);
  if(hasAnyCV)
  {
    if (verynew == 1 && !this_res.min_bo) // misbruik this_res.min_bo: er was niets
      shared.trackaction("RESNEW", rsv_ruimte_key);
    else
      res.trackreserveringupdate(rsv_ruimte_key, trackarray.length? L("lcl_res_is_resupdtrack").format(res_key + "/" + res_volgnr) + "\n" + trackarray.join("\n") : null);
  }
}

doneParams = { hasAnyCV: hasAnyCV,
               warning: warning,
               success: true
             };
Response.Write(JSON.stringify(doneParams));
Response.End;
%>
