// 77lib01.cpp
#include <applicat.h> 
#include <config.h>      
#include <mask.h>        
#include <isam.h>        
#include <anagr.h>
#include <tabutil.h>
#include <comuni.h>
#include "scperc.h"
#include "perc.h"        
#include "rver.h"        
#include "rpag.h"
#include "quadrol.h"
#include "dipend.h" // per is_erede
#include "77lib.h"

HIDDEN real 		__dep;
HIDDEN TString80 	__tmp;
HIDDEN const char* 	_build_key(TVersamento& vers);
HIDDEN long	_codditta_770 = 0L; // La ditta corrente 770

#define	QUALIF_EREDE	"11"

//////////////////////////////////////////////////////////////////////////////
// Utility varie
//////////////////////////////////////////////////////////////////////////////                     
bool ricerca(const TMask& m)
{                             
  return (m.mode() == MODE_QUERY) || (m.mode() == MODE_QUERYINS);
}

bool modifica(const TMask& m)
{
  return m.mode() == MODE_MOD;
}

bool inserimento(const TMask& m)
{
  return m.mode() == MODE_INS;
}

bool esiste_perc(char tipoa, const long codanagr)
{
// Controllo che l'anagrafica esista
  TLocalisamfile anag(LF_ANAG);
  anag.zero();
  anag.put("TIPOA",    tipoa);
  anag.put("CODANAGR", (long)codanagr);
  const bool esiste_anagr = anag.read() == NOERR;      
  return esiste_anagr;
  /*
  bool ok=FALSE;
  TLocalisamfile fp(LF_PERC);
  fp.zero();
  fp.put("CODDITTA", (long)codditta);
  fp.put("TIPOA",    tipoa);
  fp.put("CODANAGR", (long) codanag);
  ok = fp.read();
  return ok;*/
}

// Ritorna il codice fiscale del titolare di codditta
const char* cod_fis(const long codditta)
{
  TLocalisamfile ditte(LF_NDITTE);
  ditte.zero();
  ditte.put("CODDITTA", (long)codditta);
  int err = ditte.read();
  if (err) return NULL;
  const char tipoa = ditte.get("TIPOA")[0];
  const long codanagr = ditte.get_long("CODANAGR");
  TLocalisamfile anagr(LF_ANAG);
  anagr.zero();
  anagr.put(ANA_TIPOA, tipoa);
  anagr.put(ANA_CODANAGR,(long)codanagr);
  err = anagr.read();
  if (err) return NULL;
  __tmp = anagr.get(ANA_COFI);
  return __tmp;
}

const char* get_desc_cau(const char* codcau)
{
  TTable ca7("%ca7");
  __tmp = "";
  ca7.zero();
  ca7.put("CODTAB", codcau);
  const int rc = ca7.read();
  if (rc == NOERR)
    __tmp = ca7.get("S0");
  return __tmp;
}


//                                
// Round_770 
//
// Round adattata per 770 - 1.12.95
// Arrotonda cosi':
//   se importo >= 500   importo -> 1000
//   se importo <  500   importo -> 0
// L'unica differenza con round(-3) e' il comportamento
// alle 500 lire.
//
real& round_770(const real& importo)
{
  __dep = ZERO;
  __dep = importo / 1000.00;
  __dep = __dep + 0.499;
  __dep.trunc();
  __dep *= 1000.00;
  return __dep;
}

int conta_tipiper(const long codit, TString& quadro, int* NumFisiche, int* NumNoFisiche)
{
  int file;
  int ctrf=0, ctr_nof=0;

  if (quadro == "C")
    file = LF_QUAC;  

  if (quadro == "D")
    file = LF_QUAD;  

  if (quadro == "D1")
    file = LF_QUAD1;  
    
  if (quadro == "E")
    file = LF_QUAE;  

  if (quadro == "E1")
    file = LF_QUAE1;  

  if (quadro == "G")
    file = LF_QUAGD;
        
  TLocalisamfile fl(file);
  fl.zero();
  fl.put("CODDITTA", (long) codit);
  TRectype dep(fl.curr());
  for (fl.read(); !fl.eof(); fl.next())
  {
    if (fl.curr() > dep)
      break;
    const char tipoa = fl.get("TIPOA")[0];
    if (tipoa == 'F')
      ctrf++;
    else
      ctr_nof++;
  }
  *NumFisiche   = ctrf;
  *NumNoFisiche = ctr_nof;
  return 0;
}

//////////////////////////////////////////////////////////////////////////////
// Gestione ditta 770
//////////////////////////////////////////////////////////////////////////////                     
// Ritorna l'anno di dichiarazione sui parametri di studio
int anno_770()
{
  TConfig conf(CONFIG_STUDIO);
  const int anno = (int)conf.get_long(ANNO_SEL, NULL, -1, TDate(TODAY).year());
  return anno;
}

long get_firm_770()
{ 
  if (!_codditta_770) 
  {
    const char* section = "77";
    TConfig cnf(CONFIG_USER, section);
    _codditta_770 = cnf.get_long(DITTA_770, section);
  }
  
  return _codditta_770;
}

void set_firm_770(const long codditta)
{
  if (_codditta_770 == 0 || codditta != _codditta_770)
  {
    const char* section = "77";
    TConfig cnf(CONFIG_USER, section);
    cnf.set(DITTA_770, codditta);
  }
  _codditta_770 = codditta;
}

// Cerca di stabilire se il titolare della ditta e' PF o PG
char tipo_persona(long codditta)
{
  TLocalisamfile nditte(LF_NDITTE);

  nditte.zero();
  nditte.put("CODDITTA", (long)codditta);

  if (nditte.read() == NOERR)  
    return nditte.get_char("TIPOA");
  else
    return NULL;
}

// Stabilisce se coddip esiste
bool esiste_dipendente(const long codditta, const long coddip)
{
  TLocalisamfile dip (LF_DIPEND);
  dip.zero();
  dip.put(DIP_CODDITTA, codditta);
  dip.put(DIP_CODIP,    coddip);
  return dip.read() == NOERR;
}

// Stabilisce se coddip e' un dipendente non erede e non deceduto
bool is_dipendente(const long codditta, const long coddip)
{
  return !(is_erede(codditta,coddip) || is_deceduto(codditta,coddip));
}

// Stabilisce se il dipendente e' un erede
// SE QUALIFICA=11 17.7.96
bool is_erede(const long codditta, const long coddip)
{
  TLocalisamfile dip (LF_DIPEND);
  TString sQualif;
  dip.setkey(1);
  dip.zero();
  dip.put(DIP_CODDITTA, (long)codditta);
  dip.put(DIP_CODIP,    (long)coddip);
  if (dip.read() == NOERR)
    sQualif = dip.get(DIP_QUALIFICA);
  sQualif.trim();
  return sQualif == QUALIF_EREDE;
}

// Stabilisce se il dipendente e' un deceduto
// Se un qualunque codice erede e' stato compilato => e' un deceduto
bool is_deceduto(const long codditta, const long coddip)
{
  TLocalisamfile dip (LF_DIPEND);
  dip.zero();
  dip.put(DIP_CODDITTA, codditta);
  dip.put(DIP_CODIP,    coddip);
  bool ok = dip.read() == NOERR;
  if (!ok) return FALSE;
  for (int i=0; i < 10; i++)
  {
    TString campo("CODEREDE"); 
    campo << i;
    TString16 dep;
    dep = dip.get(campo);
    if (dep.not_empty())
      return TRUE;
  }
  return FALSE;
}

const int MAX_EREDI = 10;

bool scrivi_erede(const long codditta, const long deceduto, const long coddip)
{
  bool esiste=FALSE, trovato=FALSE;
  TLocalisamfile dip (LF_DIPEND);

  dip.zero();
  dip.put(DIP_CODDITTA, (long)codditta);
  dip.put(DIP_CODIP,    (long)deceduto);
  esiste = dip.read(_isequal, _lock) == NOERR;
  
  if (!esiste) return FALSE;
  
  for (int i=0; i<MAX_EREDI; i++)
  {
    TString NomeCampo("CODEREDE");
    NomeCampo << i;
    TString ValCampo(dip.get(NomeCampo));
    ValCampo.trim();          
    TString sCodErede; sCodErede << coddip;

// Se c'e' gia' non lo riscrive    
    if (sCodErede == ValCampo)  
    {
      trovato = TRUE;
      break;
    }
    
    if (ValCampo.empty() || ValCampo == "0")
    {
      trovato = TRUE;
      dip.put(NomeCampo, sCodErede);
      dip.rewrite();     
      break;
    }
  }
  if (!trovato) dip.reread(_unlock);  
  return trovato;
}

bool riscrivi_erede(const long codditta, const long deceduto, const long erede, const long value)
{
  bool esiste=FALSE, trovato=FALSE;
  TLocalisamfile dip (LF_DIPEND);

  dip.zero();
  dip.put(DIP_CODDITTA, (long)codditta);
  dip.put(DIP_CODIP,    (long)deceduto);
  esiste = dip.read(_isequal, _lock) == NOERR;
  
  if (!esiste) return FALSE;
  
  for (int i=0; i<MAX_EREDI; i++)
  {
    TString NomeCampo("CODEREDE");
    NomeCampo << i;
    TString ValCampo(dip.get(NomeCampo));
    ValCampo.trim();          
    TString sCodErede; sCodErede << erede;

// Se c'e' gia' non lo riscrive    
    if (sCodErede == ValCampo)  
    {
      trovato = TRUE;                  
      dip.put(NomeCampo,(long)value);      
      dip.rewrite();     
      break;
    }
  }
  if (!trovato) dip.reread(_unlock);
//  return trovato; // Cosi' fallirebbe anche nel caso di un codice gia'
// cancellato (per es. azzero il codice e faccio registra due volte la seconda
// fallirebbe).
  return TRUE;  
}

bool esiste_pag_in_periodo(TSchedaP& sch, const TDate& data_da, const TDate& data_a)
{
  return esiste_pag_in_anno(sch, 0, data_da, data_a);
}

// Determina se esiste un pagamento con annopag = anno passato come par.
bool esiste_pag_in_anno(TSchedaP& sch, const int annodic, const TDate& data_da, const TDate& data_a)
{
  TLocalisamfile* rpag = new TLocalisamfile(LF_RPAG);
  const bool filtra_anno = annodic != 0;
  const bool filtra_periodo = !filtra_anno;
  
  rpag->zero();
  rpag->put(PAG_CODDITTA, sch.codditta());
  rpag->put(PAG_TIPOA,    sch.tipoa());   
  rpag->put(PAG_CODANAGR, sch.codanagr());
  rpag->put(PAG_NPROG,    sch.nprog());    
  TRectype mst(rpag->curr()); 
  for (rpag->read(_isgteq); !rpag->eof(); rpag->next())
  {
    if (rpag->curr() > mst) break;
    const TDate datapag = rpag->get_date(PAG_DATAPAG);
    const int   annopag = datapag.year();
    if (filtra_anno)
    {
      const int   annopag = datapag.year();    
      if (annopag == annodic)
        return TRUE;
    }

    if (filtra_periodo)
    {
      if (datapag <= data_a && datapag >= data_da)
        return TRUE;
    }
  } 
  return FALSE;
}

// in:  tipo e codice anagrafico di cui si vuole l'indirizzo
// out: località|indirizzo|num.civico|cap|provincia 
TToken_string get_anag_address(char tip_anag, long cod_anag)
{
  TToken_string address;
  TString cod_comune_df;   
  TString cod_comune_re; 
  TString cod_comune;
  TString indirizzo; 
  TString numerociv;
  TString cap;    
  TString localita;
  TString provincia;      
  TLocalisamfile anag(LF_ANAG); 
  TLocalisamfile comuni(LF_COMUNI);
           
  // lettura anagrafica persone 
  anag.setkey(1);
  anag.zero();
  anag.put(ANA_TIPOA, tip_anag);
  anag.put(ANA_CODANAGR, cod_anag);
  
  // decodifica indirizzo
  if (anag.read() == NOERR)
  {  
		cod_comune_df = anag.get(ANA_COMRF);
		cod_comune_re = anag.get(ANA_COMRES);
		 
		// indicato domicilio fiscale
    if (cod_comune_df != "")
    {
      indirizzo = anag.get(ANA_INDRF);
      numerociv = anag.get(ANA_CIVRF);
      cap       = anag.get(ANA_CAPRF);
      cod_comune= cod_comune_df;
    }                    
    
    // indicato residenza
    else
    {
      indirizzo = anag.get(ANA_INDRES);
      numerociv = anag.get(ANA_CIVRES);
      cap       = anag.get(ANA_CAPRES);
      cod_comune= cod_comune_re;
    }
    
    // lettura anagrafica comuni 
		comuni.setkey(1);
  	comuni.zero();
  	comuni.put(COM_COM,cod_comune); 
  
  	// decodifica località e provincia
  	if (comuni.read() == NOERR)
  	{
    	localita = comuni.get(COM_DENCOM);
    	provincia= comuni.get(COM_PROVCOM);
  	}
  	
  	// preparazione token_string
  	address=localita;
  	address.add(indirizzo);
  	address.add(numerociv);
  	address.add(cap);
  	address.add(provincia);
  }                            
  
  return address;
}
//////////////////////////////////////////////////////////////////////////////
// Dichiarazioni
//////////////////////////////////////////////////////////////////////////////                     
//
// Controlla se esiste il record sul base. Se (dichiarante) => controlla se c'e' 
// il record del quadro I "globale" di codditta (che deve essere quindi 
// un dichiarante)
//
bool exist_dichiar_770(long codditta, bool dichiarante)
{
  int   status;   
  TLocalisamfile    base(LF_BASE);

  base.zero();            
  base.setkey(1);
  if (dichiarante) 
    base.put("TIPOQUA", COD_QUA_I_DIC);
  base.put("CODDITTA", (long)codditta);
  status = base.read();
  return status == NOERR;
}

//
// Idem come sopra. Se (sogg_dich) s'intende che voglio creare il quadro I
// "globale" per un sogg. dichiarante
//
bool enter_dichiar_770(long codditta, int anno_dic, bool sogg_dich)
{
  int   rc1, rc1wr, rc1rw, rc2, rc2wr, rc2rw; 
  TLocalisamfile    base(LF_BASE);
  TLocalisamfile    basebis(LF_BASEBIS);  
  
  rc1wr = NOERR;
  rc1rw = NOERR;
  rc2wr = NOERR;
  rc2rw = NOERR;   
  
  base.zero();
  base.put("CODDITTA", (long)codditta);
  base.put("ANNODIC",  (long)anno_dic);          
  if (sogg_dich) 
    base.put("TIPOQUA", COD_QUA_I_DIC);
  TRectype dep1(base.curr());
  
  rc1 = base.read();    
  if (rc1 == NOERR)
    rc1rw = base.rewrite();
  else 
  {
    base.curr() = dep1;
    rc1wr = base.write();
  }

#ifdef DBG  
  if (rc1wr != NOERR) 
    warning_box("write su base fallita codice %d", rc1wr);
  if (rc1rw != NOERR) 
    warning_box("rewrite su base fallita codice %d", rc1rw);
#endif

// Devo scrivere anche su BASEBIS !                                 
  basebis.zero();
  basebis.put("CODDITTA", (long)codditta);
  if (sogg_dich) 
    basebis.put("TIPOQUA", COD_QUA_I_DIC);
  TRectype dep2(basebis.curr());
  rc2 = basebis.read();    
  if (rc2 == NOERR)
    rc2rw = basebis.rewrite(); 
  else
  {
    basebis.curr() = dep2;
    rc2wr = basebis.write();
  }

#ifdef DBG  
  if (rc2wr != NOERR) 
    warning_box("write su basebis fallita codice %d", rc2wr);
  if (rc2rw != NOERR) 
    warning_box("rewrite su basebis fallita codice %d", rc2rw);
#endif

//  return (rc1 == NOERR && rc2 == NOERR);
  return TRUE;
}

// 20.12.95 flag di quadro compilato legato all'anno dich.
bool esiste_record_L(const long codditta, const int annodic)
{
  TLocalisamfile qual(LF_QUAL);
  bool found = FALSE;
  qual.zero();
  qual.put(QUL_CODDITTA, (long)codditta);
  for (qual.read(); !qual.eof(); qual.next())
  {
    const long cod  = qual.get_long(QUL_CODDITTA);
    if (cod != codditta) break;
    const int  adic = qual.get_int(QUL_QLAP);
    found = adic == annodic;
    if (found) break;  
  }
  return found;
}

long sogg_estinto(const long codditta)
{           
  TLocalisamfile base(LF_BASE);
  long	coddic = 0L;
  
  base.zero();
  base.setkey(1);
  base.put("TIPOQUA", "");
  base.put("CODDITTA", (long)codditta);
  const int rc = base.read();
  if (rc != NOERR)
    base.zero();
  coddic = base.get_long("CODDIC");
  return coddic;
}

bool sogg_dic(const long codditta)
{           
  TLocalisamfile base(LF_BASE);

  base.zero();
  base.setkey(2); 
  base.put("CODDIC", codditta);
  const int rc = base.read();  
  if (rc == _iseof) base.zero();
  const long codic = base.get_long("CODDIC");
  return codic == codditta;
}

////////////////////////////////////////////////////////////////////////////
// Array sheet 'modificato'
////////////////////////////////////////////////////////////////////////////
TToken_string& TNikArray_sheet::row(int i)
{
  return (TToken_string&)_interno[i];
}

long TNikArray_sheet::add(TToken_string& s)
{
  _interno.add(s);
  TToken_string vis(40);
  for (int i = 0; i < _visible_items; i++)
  {
    const char* tmp = s.get(i);
    vis.add(tmp);
  }  

  return TArray_sheet::add(vis);
}

bool TNikArray_sheet::destroy(int i)
{
  _interno.destroy();
  return TArray_sheet::destroy(i);
}

////////////////////////////////////////////////////////////////////////////
// Collegamento CG - 770
////////////////////////////////////////////////////////////////////////////
TLink770::TLink770()
{
  _tipo_coll  = nessuno;
  _immissione = _tipo = NULL;
  _codanagr   = _numreg = 0L;
  _totdoc = _spese = _compenso = _imposte = _ritenute = ZERO;
}

bool TLink770::read(const char* msg)
{
  TToken_string mesg(msg);
  
  _tipo_coll  = (TTipo_coll)mesg.get_int(0);
  _immissione = mesg.get_char(1);
  _tipo       = mesg.get_char(2);
  _codanagr   = mesg.get_long(3);
  _numreg     = mesg.get_long(4);
  _numdoc     = mesg.get(5);   
  _datadoc    = mesg.get(6);
  _totdoc     = real(mesg.get(7));
  _spese      = real(mesg.get(8));
  _compenso   = real(mesg.get(9));
  _imposte    = real(mesg.get(10));
  _ritenute   = real(mesg.get(11));

  if (_tipo_coll == fattura)
    if ( (_tipo != 'F' && _tipo != 'G') || _codanagr <= 0L )
      return FALSE;
 
  return TRUE;      
}

TPercipiente::TPercipiente(const TRectype& rec)
{
  _codditta = rec.get_long(PRC_CODDITTA);  
  _tipoa    = rec.get(PRC_TIPOA)[0];
  _codanagr = rec.get_long(PRC_CODANAGR);
}

// Determina se per il percipiente esiste almeno una scheda
bool TPercipiente::esiste_scheda()
{
  TLocalisamfile sch(LF_SCPERC);
  sch.zero();
  sch.put(SCH_CODDITTA, _codditta);
  sch.put(SCH_TIPOA, _tipoa);
  sch.put(SCH_CODANAGR, _codanagr);
  TRectype dep(sch.curr());
  sch.read();
  return sch.curr() == dep;
}

bool TPercipiente::elimina_schede()
{
  TLocalisamfile sch(LF_SCPERC);
  sch.zero();
  sch.put(SCH_CODDITTA, codditta());
  sch.put(SCH_TIPOA,    tipoa());
  sch.put(SCH_CODANAGR, codanagr());
  TRectype dep(sch.curr());
  for (sch.read(); !sch.eof(); sch.next())
  {
    if (sch.curr() > dep)
      break;
    TSchedaP scheda(sch.curr());
    scheda.remove();
  }
  return TRUE;
}

int TSchedaP::anno_doc() const
{
  int	anno_doc;
  anno_doc = _data_doc.year();
  return anno_doc;  
}

real TSchedaP::compenso_doc() const
{ 
  return _compenso_doc;
}

real TSchedaP::spese_doc() const
{
  return _spese_doc;
}


int TSchedaP::remove()
{
  int err1=0, err2=0;
  
  TLocalisamfile sch(LF_SCPERC);
  sch.put(SCH_CODDITTA, codditta());
  sch.put(SCH_TIPOA,    tipoa());
  sch.put(SCH_CODANAGR, codanagr());
  sch.put(SCH_NPROG,    nprog());
  err1 = sch.read(_isequal, _testandlock);
  bool esiste = err1 == NOERR;
  if (!esiste) 
  {
    sch.reread(_unlock);
    return SCHEDA_NON_ESISTENTE;
  }

// Elimino i pagamenti
  TLocalisamfile rpag(LF_RPAG);
  rpag.put(PAG_CODDITTA, codditta());
  rpag.put(PAG_TIPOA,    tipoa());
  rpag.put(PAG_CODANAGR, codanagr());
  rpag.put(PAG_NPROG,    nprog());
  TRectype pagrec(rpag.curr()); 
  for (rpag.read(_isgteq); !rpag.eof(); rpag.next())
  {
    if (rpag.curr() > pagrec) 
      break;
    rpag.reread(_testandlock);
    err1 = rpag.remove();
    if (err1 != NOERR)   
    {
      warning_box("Elimina righe pag. errore: %d", err1);
      rpag.reread(_unlock);
      break;
    }
    rpag.reread(_unlock);
  }                   

// E poi i versamenti  
  TLocalisamfile rver(LF_RVER);  
  rver.put(VER_CODDITTA, codditta());
  rver.put(VER_TIPOA,    tipoa());
  rver.put(VER_CODANAGR, codanagr());
  rver.put(VER_NPROG,    nprog());
  TRectype verrec(rver.curr()); 
  for (rver.read(_isgteq); !rver.eof(); rver.next())
  {
    if (rver.curr() > verrec) 
      break;
    rver.reread(_testandlock);
    err2 = rver.remove();
    if (err2 != NOERR)   
    {
      warning_box("Elimina righe ver. errore: %d", err2);
      rver.reread(_unlock);
      break;
    }
    rver.reread(_unlock);
  }                   

// Alla fine se tutto e' andato bene rimuovo la testata della scheda
  if (err1 == NOERR && err2 == NOERR) err1 = sch.remove();    
  return err1 + err2;  // (NOERR e' 0)
}

bool TSchedaP::read()
{
  bool ok = FALSE;
  TLocalisamfile sch(LF_SCPERC);
  sch.put(SCH_CODDITTA, codditta());
  sch.put(SCH_TIPOA,    tipoa());
  sch.put(SCH_CODANAGR, codanagr());
  sch.put(SCH_NPROG,    nprog());
  const int rc = sch.read();
  ok = rc == NOERR;
  if (ok)          
  {
    _compenso_doc = sch.get_real(SCH_COMPENSO);
    _spese_doc    = sch.get_real(SCH_SPESE);
    _data_doc     = sch.get_date(SCH_DATADOC);
  }
  return ok;
}

TSchedaP::~TSchedaP()
{
}

TSchedaP::TSchedaP (const long codditta, const char tipoa, const long codanagr, const int nprog) 
  : _codditta(codditta), _tipoa(tipoa), _codanagr(codanagr), _nprog(nprog) 
{
  _compenso_doc = _spese_doc = ZERO;
}  

TSchedaP::TSchedaP(TRectype& rec)
{
  _codditta = rec.get_long("CODDITTA");  
  _tipoa    = rec.get("TIPOA")[0];
  _codanagr = rec.get_long("CODANAGR");
  _nprog    = rec.get_int("NPROG");
}

TVersamento::TVersamento(TRectype& rec)
{
  _codditta = rec.get_long(VER_CODDITTA);  
  _tipoa    = rec.get(VER_TIPOA)[0];
  _codanagr = rec.get_long(VER_CODANAGR);
  _nprog    = rec.get_int(VER_NPROG);
  _nriga    = rec.get_int(VER_NRIGA);
}

void TVersamento::set(TToken_string& row)
{
  _codditta = atol(row.get(0));
  _tipoa    = row.get()[0];
  _codanagr = atol(row.get());
  _nprog    = atoi(row.get());
  _nriga    = atoi(row.get());
  _importo_versato = real(row.get());
}

void TVersamento::set(const long codditta, const char tipoa, const long codanagr, 
                      const int nprog, const int nriga, const real& impvers)
{ 
  _codditta=codditta; 
  _tipoa=tipoa; 
  _codanagr=codanagr; 
  _nprog=nprog; 
  _nriga = nriga;  
  _importo_versato = impvers;
}                            


TVersamento_stampa::TVersamento_stampa(const long codditta, const char tipoa, const long codanagr, const int nprog, const int nriga, const real& impvers) :
      TVersamento(codditta, tipoa, codanagr, nprog, nriga, impvers) 
{ 
  _gia_letti_pag = FALSE;
  _num_last_pag  = 0;
}  


void TVersamento_stampa::set(const long codditta, const char tipoa, const long codanagr, 
                         const int nprog, const int nriga, const real& impvers)
{ 
// se sto cambiando versamento resetto il flag "pagamenti gia' letti"
  if ((_nriga && nriga != _nriga) || (_nprog && nprog != _nprog) ||
      (_tipoa != '\0' && tipoa != _tipoa) || (_codditta != 0 && _codditta != codditta) ||
      (_codanagr != 0 && _codanagr != codanagr) )
  {
     _gia_letti_pag 	= FALSE;
     _importo_versato	= ZERO;                    
     _importo_versato_residuo = ZERO;
  }
          
  _codditta = codditta; 
  _tipoa    = tipoa; 
  _codanagr = codanagr; 
  _nprog    = nprog; 
  _nriga    = nriga;  
  _importo_versato = impvers;
}                            

int TVersamento_stampa::num_pags(TLocalisamfile* pag) 
{ 
  if (!_gia_letti_pag)
    _num_pags = read_pags(pag);
  return _num_pags;
}

int TVersamento_stampa::read_pags(TLocalisamfile* frpag)
{
  TLocalisamfile* tmp  = frpag ? NULL : new TLocalisamfile(LF_RPAG);
  TLocalisamfile& rpag = frpag ? *frpag : *tmp; 
  int ctr = 0;
  TRecnotype recno = frpag ? frpag->recno() : 0L;
    
  rpag.zero();
  rpag.put(PAG_CODDITTA, (long)_codditta);
  rpag.put(PAG_TIPOA,    _tipoa);   
  rpag.put(PAG_CODANAGR, (long)_codanagr);
  rpag.put(PAG_NPROG,    _nprog);    
  TRectype mst(rpag.curr()); 
  for (rpag.read(_isgteq); !rpag.eof(); rpag.next())
  {
    if (rpag.curr() > mst) break;
    const int numvers = rpag.get_int(PAG_NUMVERS);
    if (numvers != _nriga) continue;              
    const int nriga = rpag.get_int(PAG_NRIGA);
    _num_last_pag = nriga;
    ctr++;
  } 
  _gia_letti_pag = TRUE;
  if (frpag) frpag->readat(recno);  // ripristina la posizione prec.
  return ctr;  
}

HIDDEN TVersamento __vers;

// stampa solo la quota di versamento corrispondente al pagamento
real TVersamento_stampa::vers_stampa(TLocalisamfile* rpag, const int nriga_pag, 
                                 const real& impvers, const real& ritenpag)
{
  real	vers_stampa  = ZERO;
  real	vers_residuo = ZERO;
  const int numpags  = num_pags(rpag); 

// se l'importo versato e' minore della ritenuta oppure c'e' solo un
// pagamento collegato stampo l'intera somma versata, altrimenti solo
// quella che copre la ritenuta                  
  const bool ultimo_pagamento = numpags == 1 || last_pag(nriga_pag);
  vers_stampa  = ultimo_pagamento || (impvers < ritenpag) ? impvers : ritenpag;
  _importo_versato_residuo = impvers - vers_stampa;
  return vers_stampa;
}

HIDDEN const char* _build_key(TVersamento& vers)
{
  __tmp.format("%5ld%c%5ld%d%d", vers.codditta(),vers.tipoa(),vers.codanagr(),vers.nprog(),vers.nriga());
  return __tmp;
}

void TVersamento_stampa::add(TVersamento& vers)
{
  TString80 key;
  real dep(vers.importo_versato());
  TString vvv(dep.string());
  key = _build_key(vers);
  _vers.add(key, vvv, TRUE);
}

bool TVersamento_stampa::find(TVersamento& vers)
{
  TString80 key; 
  bool truovato = FALSE;
  
  key = _build_key(vers);  
  truovato = _vers.is_key(key);
  
  if (truovato)
  {
    TString& vvv = (TString&)_vers.find(key);
    real dep(vvv);
    _importo_versato_residuo = dep;  
  }
  return truovato;
}

