//Creazione versamenti per acconti
#include <applicat.h>
#include <mask.h>
#include <tabutil.h> 
#include <relation.h>
#include <sheet.h>
#include <urldefid.h>
#include <prefix.h>
#include <printer.h>
#include <progind.h>
#include <utility.h>
#include <config.h>
#include "cg4800a.h"
#include "cg4800b.h"

#define ACCONTO_SENZA_CREDITO real(200000)
#define ROUND_MILLELIRE (-3)

class VersAcc_app : public TApplication
{
  TRelation*    _nditte;
  TArray_sheet* _ditte;
  TArray        _nomiditte, _desc;
  TBit_array    _selected;
  
  TTable*    _lim;  
  TTable*    _lia;  
  TTable*    _del;
  TTable*    _ban; 
  TTable*    _ucc; 
  
  TProgind*  _prind;
  
  int   _year; 
  real  _acconto, _credito, _diff, _impver;                   
  bool  _calcall, _da_stampare, _print;
  TDate _dataver;
  TString16 _abi, _cab, _con;
  TString16 _abips, _cabps; //dai parametri di studio
  
protected:               
  virtual bool create(); 
  virtual bool destroy();
  virtual bool menu(MENU_TAG);
  virtual void print();
  
  // handlers             
  static bool ch_year_handler(TMask_field& f, KEY key);

public:                                                  

  static VersAcc_app& app() { return (VersAcc_app&)main_app(); }
  void build_ditte_sheet();
  void build_nomiditte();

  void lettura_delega();
  void lettura_anagrafica(bool*);
  void crea_riga_stampa(bool);
  void aggiorna_delega();
  void crea_delega();
  void vers_acc();
  
  bool look_lia();
  bool video_conferma(); 
  bool check_acc(); 
  
  VersAcc_app() : _ditte(NULL), _selected(10000), _nomiditte(100), _desc(100) {}
};

bool VersAcc_app::look_lia()
{
  TTable lia ("%LIA");
  
  TString16 y; y.format("%05ld%04d", _nditte->lfile().get_long("CODDITTA"), _year);
  
  lia.zero();
  lia.put("CODTAB", y);
  lia.read();
  const bool ok = lia.good(); 
  if (ok)
  { 
    _acconto = lia.get_real("R4");
    _credito = lia.get_real("R6");
  }
  else
  {
    _acconto = ZERO;
    _credito = ZERO;
  }  
  return ok;
}

bool VersAcc_app::create()
{ 
  TApplication::create(); 

  _nditte = new TRelation(LF_NDITTE);
  _nditte->add(LF_ANAG, "TIPOA=TIPOA|CODANAGR=CODANAGR");
  _nditte->add(LF_COMUNI, "COM=COMRF(COMRES)", 1, LF_ANAG);
  
  _ditte  = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                             "@1|Cod.@5R|Ragione Sociale@50|Vers.");  
  
  _del = new TTable("%DEL");
  _lia = new TTable("%LIA");
  _ban = new TTable("%BAN");
  _ucc = new TTable("%UCC"); 
  _lim = new TTable("LIM");
  
  TConfig c (CONFIG_STUDIO, "cg");
  _abips = c.get("CodABI");
  _cabps = c.get("CodCAB");
  
  TDate oggi(TODAY);
  _year = oggi.year();
  
  begin_wait();
  build_nomiditte();
  build_ditte_sheet();
  end_wait();
  
  dispatch_e_menu(BAR_ITEM(1));
  
  return TRUE; 
}

bool VersAcc_app::destroy()
{                                  
  delete _lim;   
  delete _lia;
  delete _del;
  delete _ban;
  delete _ucc;
  delete _ditte;
  delete _nditte;
  
  return TApplication::destroy();
}

bool VersAcc_app::ch_year_handler(TMask_field& f, KEY key)
{                                                    
  if (key == K_TAB && f.focusdirty())
  {                         
    app().begin_wait();
    app()._year = atoi(f.get());
    app().build_nomiditte();
    app().build_ditte_sheet();  
    app().end_wait();
  }
  return TRUE;
} 


void VersAcc_app::build_ditte_sheet()
{
  // build sheet
  _ditte->destroy();
  for (int i = 0; i < _nomiditte.items(); i++)
  {
    TToken_string* d = new TToken_string(64);
    *d = (TToken_string&)_nomiditte[i];
    const char vers = d->get_char(2);
    d->insert(" |", 0);
    bool selectable = vers == '?';
    const long pos = _ditte->add(d);     
    if (selectable)  _ditte->disable(pos);
  }     
}

void VersAcc_app::build_nomiditte()
{                 
  _nomiditte.destroy();
  // ricostruire _nomiditte e rifare build_ditte_sheet
  TLocalisamfile& dt = _nditte->lfile();
  TString fr(2);
  TTable lia("%LIA");

  for (dt.first(); !dt.eof(); dt.next())
  {     
    // check no archivi
    fr = "??";
    bool good = prefix().exist(dt.get_long("CODDITTA"));                        
    
    if (good) 
    {   
      // check no parametri liquidazione                                               
      lia.put("CODTAB", format("%05ld%d",dt.get_long("CODDITTA"),_year));
      if (lia.read() != NOERR) good = FALSE; 
      else fr = lia.get("S7");
    }
    else continue;

    TToken_string* d = new TToken_string(64);
    
    // add record 
    d->add(dt.get_long("CODDITTA"));
    d->add(dt.get("RAGSOC"));
    d->add(fr);
    
    _nomiditte.add(d);  
  }
}

bool VersAcc_app::menu(MENU_TAG)
{
  if (check_acc()) 
  { 
    if (_calcall || _selected.ones() > 0l)
    {
      vers_acc();
      if (_print)
      {
       enable_menu_item(M_FILE_PRINT);
       print();
      }   
    }
    else warning_box("Nessuna ditta selezionata!");
  }
  return FALSE;
}                

bool VersAcc_app::check_acc()
{               
  KEY k;
  
  TMask m("cg4800a");
  
  m.set_handler(FLD_CGB_YEAR, ch_year_handler);   
  
  long j;
  _calcall = FALSE;

  for (;;)
  {
    if (k == K_ESC || k == K_ENTER)
      break;

    k = m.run();
    
    switch (k)
    {
     case DLG_SELECT:
       _ditte->run();
       for (j = 0l; j < _ditte->items(); j++)
          if (_ditte->checked(j)) _selected.set(j);
       break;

     case BUT_CGB_ALL:
       _ditte->check(-1);
       for (j = 0l; j < _ditte->items(); j++)
          if (_ditte->checked(j) && !_ditte->disabled(j)) 
            _selected.set(j);
       _calcall = TRUE;
       k = K_ENTER;
       break;
    }
  }

  if (k == K_ENTER) _year = m.get_int(FLD_CGB_YEAR);

  return k == K_ENTER;
}

void VersAcc_app::vers_acc()
{
  char buf[256]; bool tipo;
  
  _desc.destroy();
  _da_stampare = _print = FALSE;

  _prind = new TProgind(_calcall ? 0l : _selected.ones(),
                        "         Creazione versam. acconti \n"
                        "        preparazione archivi       \n"
                        "                                   \n",
                        TRUE,TRUE,30);

  for (int l = 0; l < _ditte->items(); l++)
  {
    if (_prind->iscancelled())
      break;

    if (!(_calcall || _selected[l]) || _ditte->disabled(l)) 
      continue;
    
    _abi = _abips;
    _cab = _cabps;
    _da_stampare = FALSE;  //relativo a ciascuna ditta
    
    TApplication::set_firm(_ditte->row(l).get_long(1));

    _nditte->curr().zero();
    _nditte->curr().put("CODDITTA",_ditte->row(l).get(1));
    _nditte->read();                                                          
   
    if (!look_lia()) continue;    
    
    sprintf (buf,"Creazione vers. acconti:\nditta %s\n ",
             (const char*)_nditte->lfile().get("RAGSOC"));
    _prind->set_text(buf);
    
    lettura_anagrafica(&tipo);
    
    lettura_delega();
    
    if (_da_stampare)
    { 
      crea_riga_stampa(tipo);
      _print = TRUE;   //relativo alla stampa finale 
    }
     
    _prind->addstatus(1);
  }
  delete _prind;
}  

void VersAcc_app::print()
{
  printer().open();
  
  TPrintrow row;
  
  row.put("Gestione iva", 0);
  row.put("Data @>", 106);
  row.put("Pag.@#", 124);
  printer().setheaderline(0,row);
  
  row.reset(); 
  TString256 t("@bCREAZIONE VERSAMENTI PER ACCONTI DICEMBRE");
  t <<' '<<_year;
  row.put(t,34); 
  printer().setheaderline(1,row);
  
  t = "";
  t.fill('-',132);
  row.reset();
  row.put(t,0);
  printer().setheaderline(2,row);
  printer().setheaderline(4,row);  
  
  row.reset();
  row.put("Ditta",0);
  row.put("Denominazione",7);
  row.put("Importo",46);
  row.put("Banca",55);
  row.put("Dipendenza",62);
  row.put("Concessione",74);
  printer().setheaderline(3,row);
  
  for (int i = 0; i < _desc.items(); i++)
  {
    TToken_string& tt = (TToken_string&)_desc[i]; 
    
    TParagraph_string rs (tt.get(1),30);
    
    row.reset();
    row.put(tt.get(0),0);  
    const real imp(real::ita2eng(tt.get(2)));
    row.put(imp.string("###.###.###.###"),38);
    if (tt.get_int(7) == 0)
    {        
      row.put(tt.get(3),55);
      row.put(tt.get(4),63);
    }
    else row.put(tt.get(5),77);
    
    const TString80 descr(tt.get(6));
    row.put(descr.left(45),86);    
    const char* r;
    while ((r = rs.get()) != NULL)
    {
      row.put(r,7);
      printer().print(row);
      row.reset(); 
    }
  }                 
  printer().close();
}

void VersAcc_app::lettura_delega()
{
  TString16 cod;
  TString16 y (format("%05ld", _nditte->lfile().get_long("CODDITTA")));
  
  _diff = _acconto - _credito;  
  _diff.round(ROUND_MILLELIRE);
  
  cod << y << _year << 12 << 7;
  
  _del->zero();
  _del->put("CODTAB", cod);
  
  if (_del->read() == NOERR)
  {
    if (_diff < ACCONTO_SENZA_CREDITO)  //l'importo non e' dovuto
    {
      //cancello la delega
      _del->remove();
      return;
    }
    
    // se sono qui e' perche' l'importo e' dovuto (_diff >= ACCONTO_SENZA_CREDITO)
    bool stampata = _del->get_bool("B0");
    
    _impver = _del->get_real("R0");
    _dataver = _del->get_date("D0");
    
    if (stampata)
    {       
      _abi = _del->get("S7");
      _cab = _del->get("S8");
      _con = _del->get("S9"); 
      if (_diff != _impver)
        video_conferma(); 
      return;  
    }
    else 
    {
      aggiorna_delega();
      _da_stampare = TRUE;  
    }
  }
  else //non esiste la delega
  {
    if (_diff >= ACCONTO_SENZA_CREDITO)
    //creo record delega
    {
      crea_delega(); 
      _da_stampare = TRUE;
    }
  }
  return;  
}

void VersAcc_app::crea_delega()
{
  TString16 y (format("%05ld", _nditte->lfile().get_long("CODDITTA")));
  TString16 cod;
  
  cod << y << _year << 12 << 7;
  
  _del->zero();
  _del->put("CODTAB", cod);
  _del->put("S7", _abi);
  _del->put("S8", _cab);
  _del->put("S9", _con);
  _del->put("R0", _diff);
  
  _del->write();  
}

void VersAcc_app::aggiorna_delega()
{ 
  _del->put("S7", _abi);
  _del->put("S8", _cab);
  _del->put("S9", _con);
  _del->put("R0", _diff);
  
  _del->rewrite();
}                 

void VersAcc_app::lettura_anagrafica(bool* tipo)
{
  TLocalisamfile& anag = _nditte->lfile(LF_ANAG);
  TLocalisamfile& com  = _nditte->lfile(LF_COMUNI); // Comune residenza fiscale
    
  const bool cf = anag.get_bool("TITCF");    
  const int isdel = anag.get_int("TIPOSTDEL");
  
  if (cf && (isdel == 1 || isdel == 2))
  {
    *tipo = TRUE;
    const int con = com.get_int("UFFCONC"); 
    _abi = "";
    _cab = "";
    _con = format("%03d",con);
  }  
  else
  {
    *tipo = FALSE;
    _con = "";
    //const long codabi = anag.get_long("CODABI");
    //const long codcab = anag.get_long("CODCAB");
    const long codabi = _nditte->lfile().get_long("ABIBAN");
    const long codcab = _nditte->lfile().get_long("CABBAN");
    //if (codabi != 0 || codcab != 0)
    if (codabi != 0 && codcab != 0)
    {
      _abi = format("%05ld", codabi);
      _cab = format("%05ld", codcab);
    }
  }
}  
   
bool VersAcc_app::video_conferma()
{                                               
  TMask m("cg4800b");  

  m.field(F_CODDITTA).set(_nditte->lfile().get("CODDITTA"));
  m.field(F_RAGSOC).set(_nditte->lfile().get("RAGSOC"));
  m.field(F_DATAVER).set(_dataver);
  m.field(F_ABI).set(_abi);
  m.field(F_CAB).set(_cab);
  m.field(F_CON).set(_con);       
  m.field(F_IMPVER).set(_impver.string());
  m.field(F_NEWIMP).set(_diff.string());    

  for (bool stop = FALSE; !stop;)
  {
    KEY k = m.run();        
    
    switch(k)
    {
     case K_SAVE: 
       {
         KEY k = yesnocancel_box("Delega gia' stampata. Si desidera ugualmente confermare l'aggiornamento?");
         if (k ==  K_YES)
         {
           _da_stampare = TRUE;
           _del->put("R0",_diff);
           _del->put("B0", "");
           _del->rewrite();
         }
         if (k == K_YES || k == K_NO) 
           stop = TRUE;
       }    
       break;  
     case K_ESC:
     //case K_QUIT:     
       stop = TRUE;
       break;
    }
  }
  return TRUE;
}    

void VersAcc_app::crea_riga_stampa(bool tipost)
{
  TToken_string* tt = new TToken_string(150);    
  TString80 desc; 
  
  if (tipost) //prendo la descrizione dell'ufficio concessione
  {
    if (_con.not_empty())
    {
     TTable ucc("%UCC");
     ucc.zero();
     ucc.put("CODTAB", _con);
     if (ucc.read() == NOERR)
       desc = ucc.get("S0");
    }   
  }
  else       //prendo la descrizione della banca
  {
    if (_abi.not_empty())
    {
     TTable ban("%BAN");
     TString16 cod;
     cod = _abi; if (!_cab.empty()) cod << _cab; 
     ban.zero();
     ban.put("CODTAB", cod);
     if (ban.read() == NOERR)
       desc = ban.get("S0");
    }
  }                        
  
  tt->add(_nditte->lfile().get("CODDITTA"));
  tt->add(_nditte->lfile().get("RAGSOC"));
  tt->add(_diff.string());
  tt->add(_abi);
  tt->add(_cab);
  tt->add(_con);
  tt->add(desc);
  tt->add(tipost);
  
  if (tt != NULL) _desc.add(tt);  
}

int cg4800(int argc, char* argv[])
{
  VersAcc_app app;
  app.run(argc, argv, "Creazione versam. acconti dicembre");
  return 0;
}
