// 772300.cpp - Lista movimenti percipienti
//
// 16. 1.96  Stampa solo le schede che hanno almeno un pagamento con data
//           compresa negli estremi richiesti
//
#include <printapp.h>
#include <tabutil.h>

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

#include <comuni.h>
#include <nditte.h>
#include <anagr.h>
#include <anafis.h>
#include "perc.h"

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

HIDDEN TString256   __tmp;
HIDDEN bool filter_func (const TRelation *);

class TStampa_mov : public TPrintapp
{  
  char        _liv;       // Se stampa a livello di studio
  int         _anno_dic;  // Anno dichiarazione nei paramentri utente o studio
  int       _row;   // Riga corrente di stampa  
  TString16     _section;
  TConfig*      _cnf;
  TVersamento_stampa  _stvers;
  TRelation*        _rel;
  TCursor*          _cur;   
  TLocalisamfile*   _nditte;
  TLocalisamfile*   _anag;
  TLocalisamfile*   _rpag;
  TLocalisamfile*   _rver;
  TArray            _pagver;
  TPercipiente    _curr_perc, _prec_perc;                                     
  TString       _ragsocER, _ragsocPE, _datadoc, _numdoc, _datastampa;         
  int           _anno, _codcaus, _codtrib, _ind, _nprog;
  long          _codditta, _codanagER, _codanagPE, _cod_da,_cod_a;
  char          _tipoa,_tipoa_da,_tipoa_a;
  real          _tot_imponpag, _tot_ritenpag, _tot_impvers, _iva, _totdoc, _tot_totdoc, _tot_iva;
  real          _g_tot_imp, _g_tot_ver, _g_tot_rit, _g_tot_totdoc, _g_tot_iva;
  TDate         _datada, _dataa;

protected:
  friend bool   filter_func (const TRelation *);
  virtual void      on_config_change();
  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);
  bool            init_print();
  void          set_total_perc();
  void          set_global_total();
  void          add(TVersamento& vers);
  bool          find(TVersamento& vers);
public:
  void dati_erogante();
//  void intesta_fissa();  
  void stampa_dati_erog_perc();
  void ragione_sociale();
  int  ricerca_causale();
  void setta_righe_documento();
  void setta_righe_pagamenti(const TString& datapag, const real& imponpag, const real& percent, 
                             const real& ritenpag, int i);
  void setta_righe_versamenti(char,char,const TString&,const TString&,const TString&,const real&,int); 
  static bool codditta_hnd(TMask_field& f, KEY k);
// D = stampa ditta, S = stampa a livello di studio 
  TStampa_mov(char livello='D') : _liv(toupper(livello)) {}
  virtual ~TStampa_mov() {}
};

HIDDEN TStampa_mov& app() { return (TStampa_mov&) main_app(); }

bool filter_func (const TRelation * rel)
{ 
  const int anno_corr = app()._anno;
  const TRectype& sch_curr = rel->curr();
  TSchedaP  scheda(sch_curr);
  return esiste_pag_in_anno(scheda, anno_corr);
}                                        
                  
bool TStampa_mov::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;                                           
}

void TStampa_mov::on_config_change()
{ 
  TConfig conf(_liv == 'S' ? CONFIG_USER : CONFIG_STUDIO);
  _anno_dic = (int)conf.get_long(ANNO_SEL, _section); 
}

HIDDEN int compare_rows(const TObject** o1, const TObject** o2)
{
  TToken_string* r1 = (TToken_string*)*o1;
  TToken_string* r2 = (TToken_string*)*o2;

  long np1 = atol(r1->get(0));
  long nv1 = atol(r1->get(1));
  long np2 = atol(r2->get(0));
  long nv2 = atol(r2->get(1));
  
  if (nv1 == nv2 && np1 == np2)
    return 0;
    
  if (nv1 > nv2)
    return 1;
    
  if (nv1 < nv2)
    return -1;
    
  if (nv1 == nv2)
    if (np1 > np2)
      return 1;
    else
      return -1;
      
  return 0;
}
                                         
int TStampa_mov::ricerca_causale()
{                           
  TTable ca7 ("%CA7");   
  TString16 dep;
  int cod = 0;
  
  ca7.zero();
  dep.format("%02d", _codcaus);
  ca7.put("CODTAB", dep);      
  if (ca7.read() == NOERR)
    cod    = ca7.get_int("I0"); 
  
  return cod;
}
                                         
bool TStampa_mov::preprocess_print(int file, int counter)
{
  if (file == LF_SCPERC)
  {
    _tot_imponpag = ZERO;
    _tot_ritenpag = ZERO;
    _tot_impvers  = ZERO;
    _tot_totdoc   = ZERO;
    _tot_iva      = ZERO;
  }                   
  return TRUE;
}

void TStampa_mov::ragione_sociale()
{
  _ragsocPE = "";
  _anag->setkey(1);
  _anag->zero();
  _anag->put(ANA_TIPOA,    _tipoa);
  _anag->put(ANA_CODANAGR, _codanagPE);
  if (_anag->read() == NOERR)
  {  
    _ragsocPE = _anag->get(ANA_RAGSOC);
    _ragsocPE.trim();    
    if (_tipoa == 'F')
    {
      TString80 nome = _ragsocPE.mid(30);
      _ragsocPE.cut(30);
      _ragsocPE.trim(); nome.trim();
      _ragsocPE << ' ' << nome;
    }
  }                   
  set_row (_row, "%c %5ld %-50s", _tipoa, _codanagPE, (const char*) _ragsocPE);
}
                         
void TStampa_mov::setta_righe_documento()
{ 
  set_row (_row, "%-4d",      _nprog);    /* Prima era 2 */
  if (_codcaus != 0)
    set_row (_row, "@5g%02d", _codcaus);
  if (_codtrib != 0)
    set_row (_row, "@8g%4d",  _codtrib);

  set_row (_row, "@13g%10s",  (const char*) _datadoc);  
  set_row (_row, "@24g%-7s",  (const char*) _numdoc);
  set_row (_row, "@30g%r",    &_totdoc);
  set_row (_row, "@44g%r",    &_iva);
}
      
void TStampa_mov::setta_righe_pagamenti(const TString& datapag, const real& imponpag, const real& percent, 
                                        const real& ritenpag, int i)
{
  set_row (i, "@58g%10s", (const char*) datapag);
  set_row (i, "@69g%r",   &imponpag);
  set_row (i, "@83g%3ld", percent.integer());  
  set_row (i, "@87g%r",   &ritenpag);
} 
                        
void TStampa_mov::setta_righe_versamenti(char luovers, char tipovers, const TString& dataver,
                                          const TString& serie, const TString& numero, const real& impvers, int j)
{
  if (impvers != ZERO)
  {
    set_row (j, "@106g%c",    luovers);    
    set_row (j, "@109g%c",   tipovers);
    set_row (j, "@111g%10s", (const char*) dataver);
    set_row (j, "@124g%s",   (const char*) serie);
    set_row (j, "@130g%s",   (const char*) numero);
    set_row (j, "@143g%r",   &impvers);
  }
}

void TStampa_mov::set_total_perc()
{
  set_row (_row, "@8gTOTALE PERCIPIENTE");
  set_row (_row, "@30g%r", &_tot_totdoc);
  set_row (_row, "@44g%r", &_tot_iva);
  set_row (_row, "@69g%r", &_tot_imponpag);
  set_row (_row, "@87g%r",  &_tot_ritenpag);
  set_row (_row, "@116g%r", &_tot_impvers);
  set_row (_row+1, "");

  _g_tot_imp += _tot_imponpag;
  _g_tot_rit += _tot_ritenpag;
  _g_tot_ver += _tot_impvers;
  _g_tot_totdoc += _tot_totdoc;
  _g_tot_iva += _tot_iva;
        
  _tot_imponpag = _tot_ritenpag = _tot_impvers = _tot_totdoc = _tot_iva = ZERO;
}

void TStampa_mov::set_global_total()
{
  _row++;
  _row++;
  set_row (_row, "@8gTOTALE GENERALE");
  set_row (_row, "@30g%r", &_g_tot_totdoc);
  set_row (_row, "@44g%r", &_g_tot_iva);
  set_row (_row, "@69g%r", &_g_tot_imp);
  set_row (_row, "@87g%r",  &_g_tot_rit);
  set_row (_row, "@116g%r", &_g_tot_ver);
  set_row (_row+1, "");
}

void TStampa_mov::add(TVersamento& vers)
{
  _stvers.add(vers);
}

bool TStampa_mov::find(TVersamento& vers)
{
  return _stvers.find(vers);
}

bool TStampa_mov::preprocess_page(int file, int counter)
{      
  TString datapag, dataver, serie, numero;        
  TDate   datadoc,datav;
  real    imponpag, ritenpag, impvers, iva, totdoc, percent, dep, dep2;  
  char    luovers,tipovers;
  int     i,j, numvers;
  
  i = j = _row = 1;
        
  if (counter)
    return TRUE;
    
  if (file == LF_SCPERC)
  { 
    reset_print();
    const TRectype& sch_curr = current_cursor()->curr(LF_SCPERC);      
    _tipoa     = sch_curr.get_char(SPR_TIPOA);
    _codanagPE = sch_curr.get_long(SPR_CODANAGR);
    _nprog     = sch_curr.get_int(SPR_NPROG); 
    _codcaus   = sch_curr.get_int (SPR_CODCAUS);  
    _codtrib   = ricerca_causale();
    datadoc    = sch_curr.get_date(SPR_DATADOC);
    _datadoc   = datadoc.string();
    _numdoc    = sch_curr.get(SPR_NUMDOC);

    _iva       = sch_curr.get_real(SPR_IVA);
    _totdoc    = sch_curr.get_real(SPR_TOTALE);

    bool stampa_scheda = false;
    if (_datada > botime || _dataa < eotime)
    {
      const TSchedaP scheda(sch_curr);
      stampa_scheda = esiste_pag_in_periodo(scheda, _datada, _dataa);
    }
    else
    {
      const int anno_doc = datadoc.year();
      stampa_scheda = anno_doc == _anno_dic; 
    }
    if (!stampa_scheda)
      return true;
      
    _curr_perc.set(_tipoa, _codanagPE);
    if (_curr_perc != _prec_perc)
    {
      if (_prec_perc.not_empty()) 
      {
        set_total_perc();
        _row = 3;
      }
      _prec_perc = _curr_perc;
      ragione_sociale();
      _row++;
    }
    
    _tot_totdoc += _totdoc;
    _tot_iva += _iva;

    //scrive i valori relativi al documento
    setta_righe_documento();

    i = j = _row;              
    TVersamento_stampa ve;
    int nriga = 0;
    TRectype recpag(_rpag->curr());
    recpag.zero();
    recpag.put(SPR_CODDITTA,   _codditta);
    recpag.put(SPR_TIPOA,      _tipoa);
    recpag.put(SPR_CODANAGR,   _codanagPE);
    recpag.put(SPR_NPROG,      _nprog);
    _rpag->setkey(1);
    _rpag->zero();
    _rpag->curr() = recpag;

    for (_rpag->read(_isgteq); _rpag->good(); _rpag->next())
    {
      if (_rpag->curr() > recpag) break;
      TDate datap(_rpag->get_date(PAG_DATAPAG));
      if (datap < _datada || datap > _dataa) continue;
        
      datapag   = datap.string();
      imponpag  = _rpag->get_real(PAG_IMPONIBILE);
      percent   = _rpag->get_real(PAG_PERC);      
      ritenpag  = _rpag->get_real(PAG_RITENUTA);
      numvers   = _rpag->get_int(PAG_NUMVERS);   
      nriga     = _rpag->get_int(PAG_NRIGA);
      _tot_imponpag += imponpag;
      _tot_ritenpag += ritenpag;

      setta_righe_pagamenti(datapag, imponpag, percent, ritenpag, i++);      

      if (numvers < 0) continue;  

// Stampa estremi versamento
      real vers_stampa = ZERO;
      TLocalisamfile rver (LF_RVER);
      rver.zero();
      rver.put(VER_CODDITTA, _codditta);
      rver.put(VER_TIPOA,    _tipoa);
      rver.put(VER_CODANAGR, _codanagPE);
      rver.put(VER_NPROG,    _nprog);
      rver.put(VER_NRIGA,    numvers);

      if (rver.read() == NOERR) 
      {
        luovers  = rver.get(VER_LUOVERS)[0];
        tipovers = rver.get(VER_TIPOVERS)[0];
        datav    = rver.get_date(VER_DATAVERS);
        dataver  = datav.string();
        serie    = rver.get(VER_SERIE);      
        numero   = rver.get(VER_NUMERO);
        impvers  = rver.get_real(VER_IMPVERS); 
        ve.set(_codditta,_tipoa,_codanagPE,_nprog, numvers, impvers);
                           
        const bool gia_visto = find(ve);
          
        if (gia_visto)
          impvers = ve.importo_versato_residuo();
        else
        {
          _tot_impvers += impvers;          
          add(ve);
        }

// NB - in vers_stampa() viene fatta anche la add
        vers_stampa = ve.vers_stampa(_rpag, numvers, impvers, ritenpag);                    
//        if (vers_stampa != ZERO)
        setta_righe_versamenti(luovers,tipovers,dataver,serie,numero,vers_stampa,j++);
      }  
    } 
  }  
  return TRUE;
}

print_action TStampa_mov::postprocess_page(int file, int counter)
{                                                                      
  if (counter)
  {
    //printer().formfeed();
    reset_print();     // per evitare che stampi di nuovo il totale prec.  
    return NEXT_PAGE;
  }

  if (file == LF_SCPERC)
  {                                                  
    if (_cur->pos() >= _cur->items()-1)  // Se son sull'ultimo
    {
      reset_print();
      _row = 1;
      set_total_perc();
      _row++;

      set_global_total();

      return REPEAT_PAGE;
    }
  }
  return NEXT_PAGE;
}

bool TStampa_mov::set_print(int)
{
  long  codditta_prec;
  int   i = 0;

  if (_liv == 'S')
  {
    codditta_prec = get_firm_770();
    while ((_codditta = _cnf->get_long(DITTE_SEL, _section, i++)) != 0L) 
    {
      set_firm_770(_codditta);
   
// init_print ritorna TRUE solo se K_ENTER      
      if (init_print())
        print();
      else break;
    }  
    set_firm_770(codditta_prec);
// Non richiamare di nuovo print()!    
    return false;
  }
  else
    return init_print();
}

bool TStampa_mov::init_print()
{
  TMask msk ("772300a");
  msk.set_handler (F_CODDITTA, codditta_hnd);
  printer().footerlen(3);                    
  
  printer().set_char_size(8);
  set_real_picture("#.###.###.###");
  set_magic_currency(true);
  
  _g_tot_imp = _g_tot_rit = _g_tot_ver = ZERO;
        
  KEY tasto = msk.run();
  if (tasto == K_ENTER)
  {
    _tipoa_da = msk.get     (F_TIPODA)[0];
    _cod_da   = msk.get_long(F_CODDA);
    _tipoa_a  = msk.get     (F_TIPOA)[0];
    _cod_a    = msk.get_long(F_CODA);   
      
    TDate datada (msk.get(F_DATADA));
    TDate dataa  (msk.get(F_DATAA)); 
    
    TString data1 = datada.string();
    TString data2 = dataa.string();
    
    _datada = data1 == "" ? botime : datada;
    _dataa  = data2 == "" ? eotime : dataa;
     
    TDate data(msk.get(F_DATASTAMPA));
    _datastampa = data.string();
    
    reset_files();         //resetta l'albero di stampa
    add_file(LF_SCPERC);
 
    TRectype da(LF_SCPERC), a(LF_SCPERC); 
		TString filter;

    da.put(SPR_CODDITTA, _codditta);        
    da.put(SPR_TIPOA,    _tipoa_da);
    da.put(SPR_CODANAGR, _cod_da);
    if (_datada > botime)
      filter << "(" << SPR_ANNOC << ">=" << _datada.year() << ")&&(" << SPR_MESEC << ">=" << _datada.month() <<")";

    a.put(SPR_CODDITTA,  _codditta);        
    a.put(SPR_TIPOA,     _tipoa_a);
    a.put(SPR_CODANAGR,  _cod_a);
    if (_dataa < eotime)
		{
			if (filter.full())
				filter << "&&";
      filter << "(" << SPR_ANNOC << "<=" << _dataa.year() << ")&&(" << SPR_MESEC << "<=" << _dataa.month() <<")";
		}

    if (filter.full())
    {
      filter.insert("(");
      filter << ")||(" << SPR_ANNOC << "==0)";
    }

    current_cursor()->setregion(da, a);
    current_cursor()->setfilter(filter);
                        
    // viene ordinato per numero pagamento e numero versamento 
    dati_erogante();
    stampa_dati_erog_perc();     
  }
  
  return tasto == K_ENTER;
}

void TStampa_mov::dati_erogante()
{ 
  char    tipoa;
  bool  ditta_ok = FALSE;
         
  _ragsocER  = "";
  _codanagER = 0L;
                 
  _nditte->setkey(1);
  _nditte->curr().zero();
  _nditte->curr().put(NDT_CODDITTA, _codditta);
  ditta_ok = _nditte->read() == NOERR;
  if (ditta_ok)
  {
    tipoa      = _nditte->get_char(NDT_TIPOA);
    _codanagER = _nditte->get_long(NDT_CODANAGR);
  }

  if (ditta_ok)
  { 
    _anag->setkey(1);
    _anag->zero();
    _anag->put(ANA_TIPOA,    tipoa);
    _anag->put(ANA_CODANAGR, _codanagER);
    if (_anag->read() == NOERR)
    {  
      _ragsocER = _anag->get(ANA_RAGSOC);
      if (tipoa == 'F')
      {
        TString80 nome = _ragsocER.mid(30);
        _ragsocER.cut(30);
        _ragsocER.trim(); nome.trim();
        _ragsocER << ' ' << nome;
      }
    }
  }
}

void TStampa_mov::stampa_dati_erog_perc()
{ 
  TString sep;
  TString app(198);
  reset_header();

// 7.12.95 Numero di pagina qui!
  set_header (1, "ELENCO MOVIMENTI PER PERCIPIENTE @121gPag. @#"); 
  set_header (3, "SOGGETTO EROGANTE"); 
  set_header (3, "@19g%5d", _codditta);  // 20.11.95 codditta e NON codanag
  set_header (3, "@25g%s",  (const char*) _ragsocER);
  set_header (3, "@80gData@85g%10s", (const char*) _datastampa);
  sep << "@#";
  sep.right_just(125); 
  set_header(3,(const char*) sep);
  app.fill('_');
  set_header (5, (const char*) app);
  set_header (6, "Num.@5gCod.@13gDOCUMENTO@58gPAGAMENTO@105gVERSAMENTO@124gSerie@130gNumero");
  set_header (7, "Reg.@5gCaus.@13gData@24gNumero@35gTot.Doc.@53gIVA@58gData@72gImponibili@84g%%Rt@92gRitenute@105gLV@108gTV@111gData@124gABI@130gCAB@143gImporto versato");
  set_header (8, (const char*) app);
}
         

bool TStampa_mov::user_create()
{
  // Parametri configurazione
  _section = name(); 
  _section.cut(2); 
  _cnf = new TConfig(CONFIG_USER, _section);
  _rel = new TRelation (LF_SCPERC);
  _cur = new TCursor(_rel,"",2); 
  add_cursor(_cur);
  
  _nditte = new TLocalisamfile (LF_NDITTE);
  _anag   = new TLocalisamfile (LF_ANAG);
  _rpag   = new TLocalisamfile (LF_RPAG);
  _rver   = new TLocalisamfile (LF_RVER);
  _codditta = get_firm_770();

  return true;
}

bool TStampa_mov::user_destroy()
{
  delete _rel;   
  delete _nditte;
  delete _anag;
  delete _rpag;
  delete _rver;
  delete _cnf;
  return true;
}

int m72300(int argc, char* argv[])
{
  TStampa_mov a(*argv[2]);
  a.run(argc, argv, TR("Stampa movimenti per percipienti"));
  return 0;
}