// ------------------------------------------------------------
// Calcolo liquidazioni
// Part 1: interfaccia
// fv 21-1-94
// ------------------------------------------------------------

#include <defmask.h>                  
#include <progind.h>
#include <sheet.h>
#include <prefix.h>

#include "cg4300.h"
#include "cg4300a.h"

#include <mov.h>
#include <mailbox.h>

real TLiquidazione_app::CENTO(100.0);

inline TLiquidazione_app& app()
{ return (TLiquidazione_app&)main_app(); }

TLiquidazione_app::TLiquidazione_app() 
: _ditte(NULL), _selected(10000), _year(4), _nomiditte(100)
{ 
  _isprint = TRUE; _recalc = needed;
  _isplafond = FALSE; _isfinal = FALSE; 
  _isvent = _isagricolo = _isbenzinaro = _isviaggio = FALSE; 
  _row = 1;  _what = all; _comp_acconto = FALSE; 
  _isriepilogo = FALSE; _calcall = FALSE;
}

bool TLiquidazione_app::user_create()
{                 
  // vediamo se c'e' il messaggio per calcolare in batch
  TMailbox m;
  TProgind* pnd = NULL;
  TMessage* msg = m.next_s("RCL");
  TToken_string subj(36);
  bool is_interactive = msg == NULL;
  bool recalc_only = FALSE; 
  bool is_header = TRUE;
  TDate   printdate;            
  TString filename;         
  long    ditta;
  
  _prind = NULL;

  if (msg != NULL) subj = msg->body();  
  
  if (is_interactive) 
    pnd = new TProgind (3,"Preparazione archivi\nPrego attendere", 
                        FALSE, TRUE, 30); 

  _nditte = new TRelation(LF_NDITTE);
  _nditte->add(LF_ATTIV,"CODDITTA=CODDITTA");
  _nditte_r   = &(_nditte->curr());
  _att_r      = &(_nditte->curr(LF_ATTIV));

  _ditte  = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                             "@1|Cod.@5|Ragione Sociale@50|Vers.");
  _n_ditte = 0l;    
  
  // prevediamo la data che usera'; se calcola la liq. di un altro anno
  // si fottera' la frequenza versamenti                      
  
  if (is_interactive)
  {
    TDate oggi(TODAY);                    
    _year.format("%d",oggi.year());
  }
  else // parse messaggio
  {
    _year       = subj.get(0);
    _month      = subj.get_int(1);
    ditta       = subj.get_long(2);
    recalc_only = *(subj.get(3)) == 'C';
    printdate   = subj.get(4);
    filename    = subj.get(5);
    is_header   = subj.items() == 6;
    
  }

  if(pnd) pnd->addstatus(1);
  
  _rel = new TRelation(LF_MOV);
  _rel->add(LF_RMOVIVA,"NUMREG=NUMREG");

  _cur = new TCursor(_rel, "", 2);

  _pim        = new TTable("PIM");
  _ppa        = new TTable("PPA"); 
  _plm        = new TTable("PLM"); 
  _ptm        = new TTable("PTM"); 
  _lim        = new TTable("LIM");
  _pla        = new TTable("PLA");  
  _reg        = new TTable("REG"); 
  _iva        = new TTable("%IVA");
  _del        = new TTable("%DEL");
  _lia        = new TTable("LIA");
  
  _mov        = &_cur->file(LF_MOV); 
  _rmoviva    = &_cur->file(LF_RMOVIVA); 

  _pim_r      = &(_pim->curr());
  _plm_r      = &(_plm->curr());
  _ptm_r      = &(_ptm->curr());
  _lim_r      = &(_lim->curr());
  _iva_r      = &(_iva->curr());
  _del_r      = &(_del->curr());
  _pla_r      = &(_pla->curr());
  _ppa_r      = &(_ppa->curr());
  _reg_r      = &(_reg->curr());
  _rmoviva_r  = &(_cur->curr(LF_RMOVIVA));
  _mov_r      = &(_mov->curr());

  // ACHTUNG: tutti i _codatt (codici attivita') sono
  // in realta' composti dal codice attivita' piu' il
  // tipo attivita' (1 o 2)

  _pim_anno   = new TRecfield(*_pim_r,"CODTAB",0,3);
  _pim_codatt = new TRecfield(*_pim_r,"CODTAB",4,9);
  _pim_codreg = new TRecfield(*_pim_r,"CODTAB",10,12);  
  _pim_mese   = new TRecfield(*_pim_r,"CODTAB",13,14);
  _pim_tipocr = new TRecfield(*_pim_r,"CODTAB",15,15);
  _pim_codiva = new TRecfield(*_pim_r,"CODTAB",16,19);  
  _ppa_year   = new TRecfield(*_ppa_r,"CODTAB",0,3);
  _ppa_codatt = new TRecfield(*_ppa_r,"CODTAB",4,9);
  _ppa_month  = new TRecfield(*_ppa_r,"CODTAB",10,11);
  _ppa_kind   = new TRecfield(*_ppa_r,"CODTAB",12,12); 
  _plm_anno   = new TRecfield(*_plm_r,"CODTAB",0,3);
  _plm_codatt = new TRecfield(*_plm_r,"CODTAB",4,9);
  _plm_mese   = new TRecfield(*_plm_r,"CODTAB",10,11);
  _ptm_anno   = new TRecfield(*_ptm_r,"CODTAB",0,3);
  _ptm_codatt = new TRecfield(*_ptm_r,"CODTAB",4,9);
  _ptm_mese   = new TRecfield(*_ptm_r,"CODTAB",10,11);
  _lim_anno   = new TRecfield(*_lim_r,"CODTAB",0,3);
  _lim_mese   = new TRecfield(*_lim_r,"CODTAB",4,6);
  _pla_anno   = new TRecfield(*_pla_r,"CODTAB",0,3);
  _pla_codatt = new TRecfield(*_pla_r,"CODTAB",4,9);
  _del_ditta  = new TRecfield(*_del_r,"CODTAB",0,4);
  _del_anno   = new TRecfield(*_del_r,"CODTAB",5,8);
  _del_mese   = new TRecfield(*_del_r,"CODTAB",9,10);
  _del_tipo   = new TRecfield(*_del_r,"CODTAB",11,11);

  __firm = TApplication::get_firm();

  if (pnd) pnd->addstatus(1);
  
  if (is_interactive)
  {
    for (_nditte->first(); !_nditte->eof(); _nditte->next())
    {            
      if (!prefhndl->exist(_nditte_r->get_long("CODDITTA")))
        continue;                                             
      
      TApplication::set_firm(_nditte_r->get_long("CODDITTA"));   
      _n_ditte++;
      
      TToken_string* d = new TToken_string(64);
      
      // add record 
      d->add(_nditte_r->get("CODDITTA"));
      d->add(_nditte_r->get("RAGSOC"));
      d->add(look_lia() ? _lia->get("S7") : _nditte_r->get("FREQVIVA"));
      _nomiditte.add(d); 
    }
  }

  if (pnd) pnd->addstatus(1);

  TApplication::set_firm(__firm);
  set_real_picture(REAL_PICTURE);  
  
  if (!is_interactive)
  {            
    TTemp_window w(TASK_WIN);
    w.iconize();
    if (recalc_only) _isprint = FALSE;
    else printer().set_export_file(filename, is_header);
    // calcola liquidazione 
    printer().setdate(printdate);
    _recalc  = one;
    TApplication::set_firm(ditta);

    _nditte->zero(); _nditte_r->put("CODDITTA", ditta); _nditte->read();
    _freqviva = (look_lia() ? _lia->get("S7") : _nditte_r->get("FREQVIVA"));

    TRectype& mov = _cur->curr();
    TRectype  from(_cur->curr()); from.zero();
    TRectype  to(from);
    TDate f(1, 1, atoi(_year));
    TDate t(1, _month, atoi(_year));
    t.set_end_month();
    from.put(MOV_DATAREG, f);
    to.put(MOV_DATAREG, t);
    _cur->setregion(from, to);

    if (is_month_ok(_month)) update_firm(_month);
    if (_isprint) print();
    TApplication::set_firm(__firm);
  }                    
  else delete pnd; 
  
  return is_interactive;
}

bool TLiquidazione_app::user_destroy()
{
  delete _ditte;

  delete _pim_anno;
  delete _pim_codreg;
  delete _pim_mese;
  delete _pim_tipocr;
  delete _pim_codiva;
  delete _ppa_year;
  delete _ppa_codatt;
  delete _ppa_month;
  delete _ppa_kind;
  delete _plm_anno;
  delete _plm_codatt;
  delete _plm_mese;
  delete _ptm_anno;
  delete _ptm_codatt;
  delete _ptm_mese;
  delete _lim_anno;
  delete _lim_mese;
  delete _pla_anno;
  delete _pla_codatt;
  delete _pim_codatt;
  delete _del_ditta;
  delete _del_anno;
  delete _del_mese;
  delete _del_tipo;

  delete _pim;
  delete _ppa;
  delete _plm;
  delete _ptm;
  delete _lim;
  delete _pla;
  delete _del;

  delete _nditte;
  delete _rel;
  delete _cur;   
  
  return TRUE;
}

bool TLiquidazione_app::set_print(int n)
{
  _descr_arr.destroy();

  switch(n)
  {
  case 1: // liquidazione
    _isprint = TRUE;
    while (set_liquidazione()) 
    {
      if (_selected.ones() > 0l)
      {
        TRectype& mov = _cur->curr();
        TRectype  from(_cur->curr()); from.zero();
        TRectype  to(from);
        TDate f(1, 1, atoi(_year));
        TDate t(1, _month, atoi(_year));
        t.set_end_month();
        from.put(MOV_DATAREG, f);
        to.put(MOV_DATAREG, t);
        _cur->setregion(from, to);
        recalc_all();
        return _isprint;
      }
      else warning_box("Nessuna ditta selezionata!");
    }
    break;
  case 2: // estrazione deleghe
    _isprint = FALSE;
    while (set_deleghe()) 
    { 
      if (_calcall || _selected.ones() > 0l)
      {
        TRectype & mov = _cur->curr();
        TRectype from(_cur->curr()); from.zero();
        TRectype to(from);
        TDate f(1, _recalc == one ? _month : 1, atoi(_year));
        TDate t(1, _month, atoi(_year));
        t.set_end_month();
        from.put(MOV_DATAREG, f);
        to.put(MOV_DATAREG, t);
        _cur->setregion(from, to);  
        extract_deleghe(); 
        return FALSE;
      } 
      else warning_box("Nessuna ditta selezionata!");
    }
    break;
  case 3: // calcolo acconto
    _isprint = TRUE;
    while (set_acconto()) 
    { 
      if (_calcall || _selected.ones() > 0l)
      {
        TRectype & mov = _cur->curr();
        TRectype from(_cur->curr()); from.zero();
        TRectype to(from); 
        TDate f(1, _recalc == one ? _month : 1, atoi(_year));
        TDate t(1, _month, atoi(_year));
        t.set_end_month();
        from.put(MOV_DATAREG, f);
        to.put(MOV_DATAREG, t);
        _cur->setregion(from, to); 
        recalc_acconti(); 
        return _isprint; 
      } 
      else warning_box("Nessuna ditta selezionata!");
    }
    break;
  }
  return FALSE;
}

long TLiquidazione_app::select_firm_range(long from, long to, wht freq)
{
  if (to == 0) to = 99999L;
  
  for (int i = 0; i < _nomiditte.items(); i++)
  {
    TToken_string& d = (TToken_string&)_nomiditte[i];
    const char vers = d.get_char(2);
    if ((freq == mnt && vers == 'T') || (freq == quarter && vers == 'M'))
      continue;
    const long cod = d.get_long(0);
    if (cod >= from && cod <= to)
      _selected.set(i);
  } 
  
  return _selected.ones();
}


bool TLiquidazione_app::to_ditta_handler(TMask_field& f, KEY key)
{
  if (key == K_TAB && f.focusdirty() || key == K_ENTER)
  {
    TMask& m = f.mask();
    const long from = m.get_long(CG43_FLD_DFR);
    const long to = m.get_long(CG43_FLD_DTO);
    const wht freq = (wht)m.get_int(CG43_RDB_VERS);
    if (from > 0 || to > 0) 
    {
      const long sel = app().select_firm_range(from, to, freq);  
      m.set(CG43_FLD_SELECTED, sel);
      //      m.reset(CG43_FLD_DFR);
      //      m.reset(CG43_FLD_DTO);
    }  
  }
  return TRUE;
}


bool TLiquidazione_app::set_liquidazione()
{
  TMask m("cg4300a.msk");
  m.set_handler(CG43_FLD_DTO, to_ditta_handler);

  m.field(CG43_FLD_SELECTED).set("0");
  _selected.reset();
  
  KEY k;
  // stampa abilitata per default
  m.set(CG43_CHK_STAMPA,"X");
  
  do  
  {
    k = m.run();
    
    if (k == K_ESC) break;

    
    _what    = (wht)m.get_int(CG43_RDB_VERS);
    _month   = m.get_int(CG43_LST_MESE);
    
    if (_what == all)
    {
      if (_month != 3  && _month != 6 && _month != 9 && 
          _month != 12 && _month != 13)
        _what = mnt;
    }
    else if (_what == quarter)
      _month = m.get_int(CG43_LST_TRIM);
    
    _year    = m.get(CG43_FLD_ANNO);
    _date    = m.get(CG43_FLD_DATA);
    _isprint = m.get_bool(CG43_CHK_STAMPA);
    _recalc  = (recalc)m.get_long(CG43_LST_CALC);
    _isfinal = m.get_bool(CG43_CHK_FINAL);

    if (_isprint) printer().setdate(_date);
    
    // ------------------------------------------------
    m.first_focus(k);
    
    int i;
    

    switch(k)
    { 
    case DLG_SELECT:
      // build sheet
      _ditte->destroy();
      for (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);
        
        if ((_what == mnt && vers == 'T') || (_what == quarter && vers == 'M'))
          continue;
        
        d->insert(" |", 0);
        const long pos = _ditte->add(d);
        if (_selected[i]) _ditte->check(pos);
      }
      
      // seleziona e aggiungi alle gia' selezionate 
      if (_ditte->run() == K_ENTER)
      {
        for (long j = 0l; j < _ditte->items(); j++)
        {  
          const long cod = _ditte->row(j).get_long(1);
          for (int d = 0; d < _nomiditte.items(); d++)
          {
            const long firm = ((TToken_string&)_nomiditte[d]).get_long(0);
            if (firm == cod)
            {
              _selected.set(d, _ditte->checked(j));
              break;
            }  
          }
#ifdef DBG          
          if (d >= _nomiditte.items())
            yesnofatal_box("Non ritrovo piu' la ditta %ld", cod);
#endif     
        }
      }
      m.set(CG43_FLD_SELECTED, _selected.ones());
      break;
    case CG43_BUT_ANN:
      _selected.reset();
      m.reset(CG43_FLD_SELECTED);
      break;
    }
  }  
  while (k != K_ENTER && k != K_ESC);      



  return k == K_ENTER;
}

int cg4300(int argc, char* argv[])
{
  TLiquidazione_app main_app;
  main_app.run(argc, argv, "Liquidazione IVA");
  return TRUE;
}




