// Apertura nuovo esercizio
#include "cg4501.h"
#include "cg4500a.h"

class TAp_eser : public TApplication
{
  TTable* _esc, * _reg;
  int     _anno, _newanno;
  TDate   _dataini, _datafin, _datainp, _datafip;

protected:

  bool check_esercizio(TString& cod, TDate s1, TDate f1);
  static bool mask_dataini   (TMask_field&, KEY);
  static bool mask_newanno   (TMask_field&, KEY);

public:
  virtual bool create();
  virtual bool destroy();
  virtual bool menu(MENU_TAG m);

  bool  set();
  bool  apertura_es();
  
  TAp_eser() {}
};

//TDate InizioEsercizio(int anno)
//{
//  TTable TabEs ("ESC");
//  TString codtab;
//  TDate inizio_es;
//
//  TabEs.zero();
//  codtab.format ("%04d", anno);
//  TabEs.put ("CODTAB", codtab);
//  TabEs.read();
//  if (TabEs.good())
//    inizio_es= TabEs.get_date ("D0");
//
//  return inizio_es;
//}

//TDate FineEsercizio(int anno)
//{
//  TTable TabEs ("ESC");
//  TString codtab;
//  TDate fine_es;
//
//  TabEs.zero();
//  codtab.format ("%04d", anno);
//  TabEs.put ("CODTAB", codtab);
//  TabEs.read();
//  if (TabEs.good())
//    fine_es= TabEs.get_date ("D1");
//
//  return fine_es;
//}

bool TAp_eser::mask_newanno (TMask_field& f, KEY k)
{ 
  TTable TabEs("ESC");
  TString codtab; 

  if ( (k == K_ENTER) && f.to_check(k) )
  {
    int newanno = f.mask().get_int(F_NUOVOANNO);
    int anno    = f.mask().get_int(F_ANNO);
    TabEs.zero();
    codtab.format ("%04d", newanno);
    TabEs.put ("CODTAB", codtab);
    TabEs.read();
    if ( TabEs.good() )
    {
      f.warning_box ("Il codice inserito e' gia' presente nella tabella degli esercizi!");
      return FALSE;
    }
  }
  return TRUE;
}

bool TAp_eser::mask_dataini (TMask_field& f, KEY k)
{
  if ( (k == K_ENTER) && f.to_check(k) )
  {
    TDate data(f.mask().get(F_DATAINI));
    TDate fine(f.mask().get(F_DATAFINC)); 
    if ( data <= fine )
    {
      f.warning_box ("La data di inizio del nuovo esercizio deve essere superiore alla data di fine esercizio precedente");
      return FALSE;
    }
  }
  return TRUE;
}

bool TAp_eser::create()
{
  _esc    = new TTable("ESC");
  _reg    = new TTable("REG");

  enable_menu_item(M_FILE_NEW, FALSE);

  dispatch_e_menu (BAR_ITEM(1));
  
  return TRUE;
}

bool TAp_eser::destroy()
{
  delete _esc;
  delete _reg;
  
  return TRUE;
}

bool TAp_eser::menu(MENU_TAG m)
{
  TTable TabEs ("ESC");
  TMask msk ("cg4500a");
  
  if (TabEs.last() != NOERR)
    return error_box("Non e' ancora stato aperto alcun esercizio!");
  TabEs.first();  
  TRecnotype rn = TabEs.recno();
  int anno      = TabEs.get_int ("CODTAB");
  TDate inizio  = TabEs.get_date("D0"); //data inizio es. in corso  
  TDate fine    = TabEs.get_date("D1"); //data fine es. in corso

  // determina esercizio con data fine piu' alta 
  for ( ; !TabEs.eof(); TabEs.next())
    if (TabEs.get_date("D1") > fine)
    {
      rn   = TabEs.recno();
      fine = TabEs.get_date("D1");
    }
  
  TabEs.readat(rn);
  // rilegge dati
  anno   = TabEs.get_int ("CODTAB");
  inizio = TabEs.get_date("D0"); //data inizio es. in corso  
  fine   = TabEs.get_date("D1"); //data fine es. in corso
  
  msk.set(F_ANNO, anno);
  msk.set(F_DATAINIC, inizio.string());
  msk.set(F_DATAFINC, fine.string());
//  msk.set(F_NUOVOANNO, anno+1);
  
  msk.set_handler (F_NUOVOANNO, mask_newanno);
  msk.set_handler (F_DATAINI,   mask_dataini);
  
  if (msk.run() == K_ENTER)
  {
    _anno    = msk.get_int(F_ANNO);
    _datainp = msk.get(F_DATAINIC);
    _datafip = msk.get(F_DATAFINC);      
    _newanno = msk.get_int(F_NUOVOANNO);   //nuovo anno esercizio
    _dataini = msk.get(F_DATAINI);
    _datafin = msk.get(F_DATAFIN);
    
    apertura_es();
  }
  return FALSE;
}

bool TAp_eser::apertura_es()
{
  TTable   TabReg ("REG");
  TTable   TabEs  ("ESC"); 
  TString  anno   (4);
  TString  annonew(4);
  TDate    data;
  bool ok = FALSE; 

  //viene aggiornata la tabella dei registri. Se esisteva gia' un record relativo al nuovo esercizio, viene cancellato.
  //In ogni caso ne viene creato uno nuovo relativo al nuovo esercizio.
  TabReg.zero();
  annonew = format ("%04d", _datafin.year());
  TabReg.put ("CODTAB", annonew);
  
  TRectype r (TabReg.curr());
  
  TabReg.read(_isgteq);
  
  for (; !TabReg.eof(); TabReg.next())
  {
    if (TabReg.curr() != r) break;
    
    int tiporeg = TabReg.get_int("I0");
    if (tiporeg == 5)
      TabReg.remove();
  }

  TabReg.zero();
  TRectype nuovo (TabReg.curr());
  anno = format ("%04d", _datafip.year());
  TabReg.put ("CODTAB", anno);
  
  TRectype rec (TabReg.curr());
  
  TabReg.read(_isgteq);
  
  for (; !TabReg.eof(); TabReg.next())
  { 
    if (TabReg.curr() != rec) break;
    
    int tiporeg = TabReg.get_int("I0");
    TString cod_reg = TabReg.get("CODTAB");
    cod_reg = cod_reg.mid(4,3);
    if (tiporeg == 5)
    {
      ok = TRUE;
      nuovo  = TabReg.curr();
      TString16 cod;  
      annonew = format ("%04d", _datafin.year());      
      cod << annonew << cod_reg;
      nuovo.put("CODTAB", cod);
      nuovo.put("D0", data);
      nuovo.put("D2", data);
      nuovo.put("D3", data);
      nuovo.put("I6", 0L);
      nuovo.put("R1", real(0.0));
      nuovo.put("R2", real(0.0));
      
      TabReg.write(nuovo);
    }   
  }
  // se tutto ok viene aggiornata la tabella degli esercizi  
  annonew.format("%04d", _newanno);
  if (check_esercizio(annonew, _dataini, _datafin))
  {
    TabEs.zero();
    annonew = format ("%04d", _newanno);
    TabEs.put ("CODTAB", annonew);
    TabEs.put ("D0", _dataini);
    TabEs.put ("D1", _datafin);
    TabEs.write();  
    message_box("Apertura nuovo esercizio completata");
  }
  return TRUE;
}

bool TAp_eser::check_esercizio(TString& cod, TDate s1, TDate f1)
{                                                                                            
  // -----------------------------------------------------------------------------------------
  // chiamata prima di registrare. Controlla:
  // - se non ci sono altri esercizi, ok;
  // - se ce ne sono altri:
  //    1) controllo non sovrapposizione date   
  //    2) se ci sono es. con date inferiori, datainizio -1 deve essere = data fine altro es;
  //    3) se ci sono es. con date superiori, datafine +1 deve essere = data inizio altro
  // ---------------------------------------------------------------------------------------- 
  
  byte err = 0x00;  bool ret = TRUE;
  TTable esc("ESC");
  
  bool basta1 = FALSE, basta2 = FALSE;
  
  for (esc.first(); !esc.eof(); esc.next())
  {
    if (esc.get("CODTAB") == cod) 
      continue;                      
                                                          
    TDate s2 = esc.get_date("D0");
    TDate f2 = esc.get_date("D1");
    TDate s1d = s1; --s1d;
    TDate s2d = s2; --s2d;
             
    // check sovrapposizione
    if (s1 <= f2 && s2 <= f1)         
      err |= 0x01;
    else 
    {
      if (!basta1 && f1 < s2 && f1 != s2d)
        err |= 0x02;
      if (f1 < s2 && f1 == s2d)
      {
        err &= ~0x02;
        basta1 = TRUE;
      }
      if (!basta2 && s1 > f2 && f2 != s1d)
        err |= 0x04;
      if (s1 > f2 && f2 == s1d)
      {
        err &= ~0x04;
        basta2 = TRUE;
      }
    }
  }             
  
  if (err) 
  {         
    ret = FALSE;
    TString errstr(120); 
    errstr << "Date esercizio errate: \n";
    // build error string  
    if (err & 0x01)
      errstr << "\n - l'esercizio si sovrappone ad altro gia' esistente";
    if (err & 0x02)
      errstr << "\n - l'esercizio non e' contiguo ad esercizi successivi";
    if (err & 0x04)
      errstr << "\n - l'esercizio non e' contiguo ad esercizi precedenti"; 

    if (!(err & 0x01))      
    {                         
      errstr << "\nSi desidera registrare ugualmente?";
      ret = yesno_box(errstr);  
    }
    else error_box(errstr); 
  }
  return ret;
}



int cg4500 (int argc, char* argv[])
{
  switch (*argv[2])
  {
  case 'C':
  {
    TAp_eser a;
    a.run(argc, argv, "Apertura nuovo esercizio");
  }
  break;
 case 'I':
{
  TAp_iva a;      
  a.run(argc, argv, "Apertura nuovo esercizio IVA");
}
break;
default:
break;
}
return TRUE;
}