// 772400.cpp - Calcolo e Stampa versamenti ritenute
#include <printapp.h>
#include <progind.h>
#include <sort.h>
#include <tabutil.h>
#include <utility.h>

#include <anagr.h> 
#include <nditte.h>

#include "772.h"
#include "772400.h"
#include "77lib.h"

#include "scperc.h"
#include "rpag.h" 
#include "rver.h" 
#include "perc.h"


static bool filter_func (const TRelation*);

class TSt_vers : public TPrintapp
 {  
  friend bool filter_func (const TRelation *);
  
  struct righe_vers
  {
    char anno[5];
    char mese[3];
    char codtrib[5];
    char tipoa;
    char codan[6]; 
    char descr[51];
    int  nprog;
    TDate datadoc;
    char numdoc[8];
    real rite;
  };
  righe_vers*       _rig;
  TRelation*        _rel;
  TCursor*          _cur;
  TProgind*         _prog;
  TSort*            _sort;
  const char*       _buf;
  TLocalisamfile*   _nditte;
  TLocalisamfile*   _anag;
  TLocalisamfile*   _rpag; 
  TLocalisamfile*   _rver; 
  TLocalisamfile*   _scperc;
  TTable*           _ca7; 
  int               _annop, _mesep, _codtribp;
  TDate             _dataini, _datafine;
  char              _tipoap;         
  long              _codditta, _codanagp;
  real              _tot_cod, _tot_mese;
  bool              _primo;
  TString           _tmp;
                                       
protected:
  virtual bool user_create() ;
  virtual bool user_destroy();
  virtual bool set_print(int m);
  virtual bool preprocess_page (int,int);
  virtual bool preprocess_print(int,int);
  virtual print_action postprocess_page (int,int);
  virtual void postclose_print();
  
public:
  const TRectype& look_causali(int);
  const TRectype& look_schperc(long,char,long,int);
  TDate look_vers(const TSchedaP& sch, long numvers);
  void crea_sort();
  void init_sort();
  void leggi_sort();
  void setta_intestazione(); 
  const char* desc_percipiente(char,long); 
  void riempi_record(int,int,int,char,long,const char*,int,const TDate&, const char*,const real&);

  static bool codditta_hnd(TMask_field& f, KEY k); 
  
  TSt_vers() {}
  virtual ~TSt_vers() {}
};

HIDDEN inline TSt_vers& app() { return (TSt_vers&)main_app(); }

const real& round_mille_lire(real& n)
{  
  // Arrotonda alle mille lire se siamo in lire, altrimenti non arrotondare!
  const int dec = TCurrency::get_firm_dec();
  if (dec == 0) 
    n.round(-3);  // 1000 Lire
    
  return n;  
}

bool TSt_vers::codditta_hnd(TMask_field& f, KEY k)
{         
  if (k == K_TAB && !(f.mask().is_running()) )
  {
    TString16 codditta; codditta << app()._codditta;
    if (codditta != "0")        
    {
      f.set(codditta);
      f.check();
    }
  }   

  return TRUE;                                           
}

bool filter_func (const TRelation* rel)
{ 
  const TRectype& rpag = rel->curr(LF_RPAG);
  const long codditta = rpag.get_long(PAG_CODDITTA);
  if (codditta != app()._codditta)
     return FALSE;
  
  const TDate datapag = rpag.get(PAG_DATAPAG); 

  if (datapag.ok() && datapag >= app()._dataini && datapag <= app()._datafine) 
  {  
    const long numvers = rpag.get_long(PAG_NUMVERS);
    if (numvers <= 0)
      return TRUE;           
    const long codanagr = rpag.get_long(PAG_CODANAGR);
    const char tipoa    = rpag.get_char(PAG_TIPOA);
    const int  nprog    = rpag.get_int(PAG_NPROG);
    TSchedaP sch(codditta, tipoa, codanagr, nprog);
    TDate datavers = app().look_vers(sch, numvers);
    if (!datavers.ok()) 
      return TRUE;  
  }
  return FALSE;
} 

TDate TSt_vers::look_vers(const TSchedaP& scheda, long num)
{
  TLocalisamfile vers(LF_RVER); 
  vers.zero();
  vers.put(VER_CODDITTA, scheda.codditta());
  vers.put(VER_TIPOA,    scheda.tipoa());
  vers.put(VER_CODANAGR, scheda.codanagr());
  vers.put(VER_NPROG,    scheda.nprog());  
  vers.put(VER_NRIGA, num);
  vers.read();
  if (vers.bad())
    vers.zero();

  return vers.get_date(VER_DATAVERS);
}

const TRectype& TSt_vers::look_schperc (long cod, char t, long codan, int np)
{
  TLocalisamfile& schede = *_scperc; 
  schede.zero();
  schede.put(SPR_CODDITTA, cod);
  schede.put(SPR_TIPOA, t);
  schede.put(SPR_CODANAGR, codan);
  schede.put(SPR_NPROG, np);
  schede.read();
  if (schede.bad())
    schede.zero();

  return schede.curr();
}

const TRectype& TSt_vers::look_causali(int cod)
{                            
  TString16 dep;
  
  _ca7->zero();
  dep.format("%02d", cod);
  _ca7->put("CODTAB", dep);
  _ca7->read();      
  if (_ca7->bad())
     _ca7->zero();

  return _ca7->curr();
}

void TSt_vers::init_sort()
{
  _rig  = new righe_vers;
  _sort = new TSort(sizeof(righe_vers));
 
  _sort -> addsortkey((char*)&(_rig->anno) - (char*)&(_rig->anno),4);
  _sort -> addsortkey((char*)&(_rig->mese) - (char*)&(_rig->anno),2);
  _sort -> addsortkey((char*)&(_rig->codtrib) - (char*)&(_rig->anno),4);
  _sort->addsortkey ((char*)&(_rig->tipoa) - (char*)&(_rig->anno),1);
  _sort->addsortkey ((char*)&(_rig->codan) - (char*)&(_rig->anno),5);
  _sort->init();
}
                                    
void TSt_vers::crea_sort()
{
  long codan;
  char tipoa;
  int nprog, codc, mese, anno;
  real rite;
  TDate datapag, datadoc;
  TString16 numdoc;

  init_sort();
  *_cur = 0l;  //il cursore e' stato filtrato (filter_function)

  for (int i = 0; i < _cur->items(); i++, ++(*_cur))
  {
    _prog->addstatus(1);
    tipoa   = _cur->curr().get(PAG_TIPOA)[0];
    codan   = _cur->curr().get_long(PAG_CODANAGR);
    nprog   = _cur->curr().get_int(PAG_NPROG);
    datapag = _cur->curr().get(PAG_DATAPAG);
    mese    = datapag.month();
    anno    = datapag.year();
    
    const TRectype dep = look_schperc(_codditta, tipoa, codan, nprog);
    codc = dep.get_int(SPR_CODCAUS);
    datadoc = dep.get_date(SPR_DATADOC);
    numdoc = dep.get(SPR_NUMDOC); 
    
    const TRectype& cau = look_causali(codc);
    TString descr = cau.get("S0");
    int codtrib   = cau.get_int("I0");
    
//    rite = _rpag->get_real(PAG_RITENUTA);  Non va!
    rite = _cur->curr().get_real(PAG_RITENUTA);
    riempi_record(anno,mese,codtrib,tipoa,codan,descr,nprog,datadoc,numdoc,rite); 
  }
}

void TSt_vers::riempi_record(int a,int m,int ct,char t,long ca,const char* d,
                               int np,const TDate& dd,const char* nd,const real& ri)
{
  sprintf (_rig->anno, "%4d", a);
  sprintf (_rig->mese, "%2d", m);
  sprintf (_rig->codtrib, "%4d", ct);
  _rig->tipoa = t;
  sprintf(_rig->codan, "%5ld", ca);  
  _rig->rite  = ri;
  sprintf(_rig->descr, "%s", d);
  _rig->nprog = np;
  _rig->datadoc = dd;
  sprintf(_rig->numdoc, "%s", nd);

  _sort->sort((const char*)_rig);
}    

void TSt_vers::leggi_sort()
{
  reset_print();
  
  if ((_buf = _sort->retrieve()) != NULL)
  {
    struct righe_vers* rp;
    
    rp = (struct righe_vers*)_buf;
    int anno = atoi(rp->anno);
    int mese = atoi(rp->mese);
    int codtrib = atoi(rp->codtrib);
    TString80 descr(rp->descr);  //descrizione della causale
    char tipoa = rp->tipoa;           
    long codanag = atol(rp->codan); 
    int nprog = rp->nprog;
    TString16 data((rp->datadoc).string(brief, '.'));
    TString16 numdoc(rp->numdoc);
    real rite = rp->rite;
    
    TString80 dp;
    TString16 ff;
    int i = 1;
    TString dep(94);
    dep.fill('-');
    
    if ((mese != _mesep && _mesep != 0) || (anno != _annop && _annop != 0)) //e' cambiato il mese oppure l'anno
    {
      set_row(i++, "@b@87gTOTALI CODICE ESATTORIA@115g%r", &_tot_cod);
      TDate d = format("%02d/%04d", mese, anno);
      TString16 s(d.string(brief,'/'));
      real arr = round_mille_lire(_tot_mese);
      set_row(i++, "@b@87gTOTALI MESE PAGAMENTO %s@115g%r", (const char*)s, &arr);
      set_row(i++, "");
      set_row(i++, "");
      dp = desc_percipiente(tipoa,codanag);
      ff = format("%5ld/%c", codanag,tipoa); 
      set_row(i++,"@1g%2d  %4d@11g%4d@17g%-.30s@49g%s@61g%-.30s@91g%4d@98g%s@107g%s@115g%r",
              mese,anno,codtrib,(const char*)descr,(const char*)ff,
              (const char*)dp,nprog,(const char*)data,(const char*)numdoc,&rite);
      
      _tot_cod = _tot_mese = ZERO;
    }
    else if (codtrib != _codtribp && _codtribp != -1)
    {
      set_row(i++, "@b@87gTOTALI CODICE ESATTORIA@115g%r", &_tot_cod);
      set_row(i++, "");
      dp = desc_percipiente(tipoa, codanag);            
      ff = format("%5ld/%c", codanag,tipoa);
      set_row(i++,"@11g%4d@17g%-.30s@49g%s@61g%-.30s@91g%4d@98g%s@107g%s@115g%r",
              codtrib,(const char*)descr,(const char*)ff,
              (const char*)dp,nprog,(const char*)data,(const char*)numdoc,&rite);
     
      _tot_cod = ZERO;
    }
    else if ((codanag != _codanagp && _codanagp != 0) || (tipoa != _tipoap && _tipoap != ' ')) 
    {
      dp = desc_percipiente(tipoa,codanag);
      ff = format("%5ld/%c", codanag,tipoa);
      set_row(i++,"@49g%s@61g%-.30s@91g%4d@98g%s@107g%s@115g%r",
              (const char*)ff,(const char*)dp,nprog,(const char*)data,(const char*)numdoc,&rite);
    }
    else //non e' cambiato nulla
    {
     if (_primo)
     { 
       dp = desc_percipiente(tipoa,codanag);
       ff = format("%5ld/%c", codanag,tipoa);
       set_row(i++,"@1g%2d  %4d@11g%4d@17g%-.30s@49g%s@61g%-.30s@91g%4d@98g%s@107g%s@115g%r",
               mese,anno,codtrib,(const char*)descr,(const char*)ff,
              (const char*)dp,nprog,(const char*)data,(const char*)numdoc,&rite);
       
       _primo = FALSE;
     }
     else
       set_row(i++, "@91g%4d@98g%s@107g%s@115g%r", nprog,(const char*)data,(const char*)numdoc,&rite); 
    }  
    _mesep = mese;
    _annop = anno;
    _codtribp = codtrib;
    _codanagp = codanag;
    _tipoap = tipoa;
     
    _tot_cod += rite;
    _tot_mese += rite;
  }
  else
  { 
    set_row(1, "@b@87gTOTALI CODICE ESATTORIA@115g%r", &_tot_cod);
    TDate d = format("%02d/%04d", _mesep, _annop);
    TString16 s(d.string(brief,'/'));
    real arr = round_mille_lire(_tot_mese);
    set_row(2, "@b@87gTOTALI MESE PAGAMENTO %s@115g%r", (const char*)s, &arr);
  }
}

bool TSt_vers::preprocess_print(int file, int counter)
{
  _annop = _mesep = 0;
  _codanagp = 0l;   
  _codtribp = -1;
  _tipoap = ' ';
  _primo = TRUE;
  _tot_mese = _tot_cod = ZERO;
   
  return TRUE;
}

bool TSt_vers::preprocess_page(int file, int counter)
{
  leggi_sort(); 
  return TRUE;
}

print_action TSt_vers::postprocess_page(int file, int counter)
{
  if (_buf == NULL)
     return NEXT_PAGE;

  return REPEAT_PAGE;   
}

void TSt_vers::postclose_print()
{
  delete _sort;
}
                                         
bool TSt_vers::set_print(int)
{
  TMask msk ("772400a");
  KEY tasto;
  TLocalisamfile& fl = _cur->file(LF_RPAG);

  msk.set_handler (F_CODDITTA, codditta_hnd);
    
  tasto = msk.run();

  if (tasto == K_ENTER)
  {
    const int anno = msk.get_int(F_ANNO);
    const int damese = msk.get_int(F_DAMESE);
    const int amese = msk.get_int(F_AMESE);
   
    _dataini = TDate(1, damese, anno);
    _datafine = TDate(1, amese, anno);
    _datafine.set_end_month();
    
    _cur->set_filterfunction(filter_func);
    
    set_real_picture ("###.###.###.###");
    set_print_zero(); 
    set_magic_currency(true);
    
    printer().footerlen(5);
    
    setta_intestazione();
    
    _prog = new TProgind(_cur->items(), "Elaborazione in corso...", false);
    
    crea_sort();
    _sort->endsort();
    
    delete _rig;
    delete _prog;  
    
    return true;
  }
  else
    return false;
}

void TSt_vers::setta_intestazione()
{
  int soh = 1;       
  TString sep(132);
  TString ragsoc(50);
 
  TLocalisamfile nditte(LF_NDITTE); 
  nditte.zero();
  nditte.put(NDT_CODDITTA, get_firm_770());   
  if (nditte.read() == NOERR) 
    ragsoc = nditte.get(NDT_RAGSOC);
  
  reset_header();
  
  set_header (soh++, "STAMPA VERSAMENTI RITENUTE@54gDITTA@61g%-.45s@107gDATA @<  PAG. @#", (const char*) ragsoc);
  sep.fill('-');
  set_header (soh++, (const char *) sep);
  set_header (soh++, "PAGAMENTO  CODICE ESATTORIA@48gPERCIPIENTE@91gN�@101gDOCUMENTO@122gRITENUTA");
  set_header (soh++, "MESE ANNO@48gCODICE/TIPO@61gDESCRIZIONE@91gPROG.@99gDATA@108gNUMERO");
  set_header (soh, (const char *) sep);
}

const char* TSt_vers::desc_percipiente(char t, long c)
{ 
  TString80 ragsoc;
  _anag->setkey(1);
  _anag->zero();
  _anag->put(ANA_TIPOA, t);
  _anag->put(ANA_CODANAGR, c);
  if (_anag->read() == NOERR)
  {  
    ragsoc = _anag->get(ANA_RAGSOC);
    if (t == 'F')
    {
      TString80 nome = ragsoc.mid(30);
      ragsoc.cut(30);
      ragsoc.trim(); nome.trim();
      ragsoc << ' ' << nome;
    }
    _tmp = ragsoc;
  }
  else 
    _tmp.cut(0);
  return _tmp;
}

bool TSt_vers::user_create()
{
  //TToken_string exp;
  
  //exp.add("CODDITTA=CODDITTA");
  //exp.add("NUMVERS=NUMVERS");
  
  _rel = new TRelation (LF_RPAG);
  
  //_rel->add(LF_RVER, exp, 2, LF_RPAG);
  
  _cur = new TCursor(_rel,"",1);
  
  _nditte = new TLocalisamfile (LF_NDITTE);
  _anag   = new TLocalisamfile (LF_ANAG);
  _rpag   = new TLocalisamfile (LF_RPAG);
  _rver   = new TLocalisamfile (LF_RVER);
  _scperc = new TLocalisamfile (LF_SCPERC);
  _ca7    = new TTable ("%CA7");
  _rig    = new righe_vers;
  _codditta = get_firm_770();
  return TRUE;
}

bool TSt_vers::user_destroy()
{
  delete _rel;   
  delete _nditte;
  delete _anag;
  delete _rpag;
  delete _rver;
  delete _scperc;
  delete _ca7;
  
  return TRUE;
}

int m72400(int argc, char* argv[])
{
  TSt_vers a;
  a.run(argc, argv, "Calcolo e stampa versamenti ritenute");
  return 0;
}