// 770100.cpp - Scheda percipienti
#include <relapp.h>
#include <msksheet.h>
#include <tabutil.h>
#include <mailbox.h>
#include <defmask.h>

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

#include "770101.h"  
#include "770102.h"  
#include "770100a.h"
#include "770.h"
#include "77lib.h"

// Token_string pilota per relazione tra l'informazione e la 
// sua posizione nello sheet, ogni riga individua uno sheet diverso
const char* PILOT_SHEET[] = {
  "DATAPAG|COMPENSO|SPESA|IMPONIBILE|PERC|RITLORDA|CONTROBB|DETFAMIL|GIOLAVDIP|DETLAVDIP|TOTDET|RITENUTA|NETTO|SOMNSRIT|AMMLORDO|QUOTAPROV|IMPNETTO|COMNETTO|NUMVERS",
  "DATAPAG|COMPENSO|IMPCPA|IMPONIBILE|PERC|RITENUTA|SPESA|SOMREGCONV|NETTO|SOMNSRIT|AMMLORDO|QUOTAPROV|IMPNETTO|COMNETTO|NUMVERS",
  "DATAPAG|COMPENSO|SPESA|IMPONIBILE|PERC|RITENUTA|SOMREGCONV|ALQIMP10|CTSSNPERC|CTSSNCOMP|COD10|NETTO|SOMNSRIT|AMMLORDO|QUOTAPROV|IMPNETTO|COMNETTO|NUMVERS",
  "DATAPAG|COMPENSO|IMPONIBILE|PERC|RITENUTA|UTPAGATI|RITUTPAG|UTSPETT|RITUTSPE|NQUOTE|NETTO|SOMNSRIT|AMMLORDO|QUOTAPROV|IMPNETTO|COMNETTO|NUMVERS"};	

// Items per causale quadro C
const int NUM_ITEMS_C = 8;  
const char* ITEMS_C[] = {
	"A|indenn. e compensi erogati ai prest. lavoro dipendente.....",
	"B|somme corrisp. a titolo di borsa di studio o di assegno....",
	"C|indenn., gett. di pres. altri comp. corrisp. dallo Stato...",
	"D|indenn., percep. per cariche elettive di cui all'art. 114..",
	"E|rendite vital. e rendite a tempo determ., a tit. oneroso...",
	"F|prestaz. comunque erogate in forma di trattam. periodico...",          
	"G|ass. period. alla cui prod. concor. n� capitale n� lavoro..",          
	"H|compensi corrisp. ai lav. imp. in lavori socialm. utili...."};
	
// Items per causale quadro D
const int NUM_ITEMS_D = 13;  
const char* ITEMS_D[] = {
	"A|prestaz. di lav. auton. nell'eserc. di arti o prof. abit...",
	"B|utiliz. econom., da parte dell'autore o dell'inventore,....",
	"C|a titolo di utili deriv. da contrat. di ass. in partecip...",
	"D|a titolo di utili spett. ai soci prom. ed ai soci fondat...",
	"E|per la levata di protesti cambiari da parte dei segr. com..",
	"F|utiliz. econom., da parte di sogg. diverso dall'autore o...",          
	"G|indenn. corrisp. per la cessaz. dei rapporti di agenzia....",          
	"H|indenn. corrisp. per la cessaz. da funzioni notarili",          
	"I|indenn. di trasf. o di rimb. forfet. di spese spettanti....",          
	"L|prestaz. di lavoro autonomo non esercitate abitualmente",          
	"M|prestaz. rese dagli sportivi con contratto di lav. autonomo",                  
	"N|indenn. corrisp. per la cessaz. di attivit� sportiva prof..",
	"T|altro titolo diverso dai precedenti"};
	
// Items per causale quadro Dbis
const int NUM_ITEMS_DB = 8;  
const char* ITEMS_DB[] = {
	"A|prestaz. di lav. auton. ..... iscritti in albi senza cassa",
	"B|prestaz. rese da amministrat., sindaci e revis. di soc.....",
	"C|prestaz. rese da collab. a giornali, riviste, enciclop.....",
	"D|prestaz. rese da partecipanti a collegi e commissioni",
	"E|prestaz. di collab. coord. e contin. diversi da quelli.....",
	"F|indenn. corrisp. per la cessaz. di rapp.. ass. a tass. sep.", 
	"G|provvigioni degli incaricati per le vendite a domicilio",
	"T|altro titolo diverso dai precedenti"};
	
// Items per causale quadro D1
const int NUM_ITEMS_D1 = 5;  
const char* ITEMS_D1[] = {
	"A|Agente o rappresentante di commercio monomandatario",
	"B|Agente o rappresentate plurimandatario",
	"C|Commissionario",
	"D|Mediatore",
	"E|Procacciatore d'affari"};    
	
// Items per causale quadro E
const int NUM_ITEMS_E = 5;  
const char* ITEMS_E[] = {
	"A|redditi di capitale corrisp. a sogg. resid. non eserc......",
	"B|prov. corrisp. a stabili organiz. estere di impr. resid....",
	"C|comp. per avviamento commerc. assogg. alla rit. a tit. acc.",
	"D|contrib. degli enti pubbl. e premi corrisp. dall'Unione....", 
	"E|interessi, premi e altri frutti dei tit. obbligaz. emessi.."};		

// Items per causale quadro E1
const int NUM_ITEMS_E1 = 4;  
const char* ITEMS_E1[] = {
	"A|somme deriv. dal riscatto di contratti di assic. sulla vita",
	"B|capitali corrisp. in dipend... per i quali rit. del 12,50..",
	"C|capitali corrisp. in dipend. di contr. di assic. sulla vita",
	"D|capitali corrisp. in dipend. di contr. di capitalizzazione"};     
	
// Items per causale quadro G
const int NUM_ITEMS_G = 1;  
const char* ITEMS_G[] = {    
	" |Niente"};               

HIDDEN TString80 __tmp;                                              

TSchedaPercipienti::TSchedaPercipienti(): _rel(NULL), _flag_cg(FALSE)
{
  _from_modify = FALSE;  
  _soggnres = FALSE;
  memset(_msk, 0, sizeof(_msk));
}

void  TSchedaPercipienti::update_lasts(TMask& m)
{
  if (m.mode() == MODE_MOD)   
  {
    const long codditta = m.get_long(F_CODDITTA);
    const char tipoa = m.get(F_TIPOA)[0];
    const long codanagr = m.get_long(F_CODANAGR);
    const int  nprog = m.get_int(F_NPROG);

// Determino ultimo numero di riga usato nei PAGAMENTI
    _rpag->zero();
    _rpag->put("CODDITTA", (long) codditta);
    _rpag->put("TIPOA", tipoa);
    _rpag->put("CODANAGR", (long) codanagr);
    _rpag->put("NPROG", nprog);

    TRectype dep(_rpag->curr());    
    long nriga = 0L;
    
    for (_rpag->read(); !_rpag->eof(); _rpag->next())
    {
      if (_rpag->curr() > dep) break;
      nriga = _rpag->get_long("NRIGA");
    }                                    
    _lastpag = nriga;

// Determino ultimo numero di riga usato nei VERSAMENTI
    _rver->zero();
    _rver->put("CODDITTA", (long) codditta);
    _rver->put("TIPOA", tipoa);
    _rver->put("CODANAGR", (long) codanagr);
    _rver->put("NPROG", nprog);

    TRectype dep2(_rver->curr());    
    long nrigav = 0L;
    
    for (_rver->read(); !_rver->eof(); _rver->next())
    {
      if (_rver->curr() > dep2) break;
      nrigav = _rver->get_long("NRIGA");
    }                                    
    _lastvers = nrigav;
  }
  else
    _lastpag = _lastvers = 0L;
}

bool TSchedaPercipienti::changing_mask(int mode)
{
 if ((mode == MODE_MOD) && (_mode == MODE_INS))
	return FALSE; 
 else	              
  return _mode != mode;
}

TMask* TSchedaPercipienti::get_mask(int mode)
{
  const int m = (mode == MODE_QUERY) ? 0 : 1;
  _mode = mode;
  return load_mask(m);
}


TMask* TSchedaPercipienti::load_mask(int n)
{
  if (_msk[n] != NULL) 
    return _msk[n];

  TFilename name("770100"); name << char(n == 0 ? 'a' : 'b');
  TMask* m = new TMask(name);
                             
  switch (n)
  {                                   
  case 0:        
    m->set_handler(F_NPROG, nprog_handler);
    m->set_handler(F_CODDITTA, codditta_handler);
    m->set_handler(F_CODANAGRCOM,  codanagr_handler);
    m->set_handler(F_CODANAGRPERC,  codanagr_handler);    
    break;
  case 1: 
    {
      m->disable(DLG_FINDREC);    
      m->set_handler(F_DATADOC, check_handler);
      m->set_handler(F_CODCAUS, check_causale);
      m->set_handler(F_SPESE,   check_spese);
      m->set_handler(F_COMPENS, check_compensi); 
      m->set_handler(F_MESECOMP, check_competenza);
      
////////////////////////////////////////////////////////////////////////
// Handler versamenti
////////////////////////////////////////////////////////////////////////
      TSheet_field& vers = (TSheet_field&) m->field(F_VERSAMENTI);  
      vers.set_notify(vers_notify);
      vers.sheet_mask().set_handler(F_VERS_1015, vers1015_handler);
      vers.sheet_mask().set_handler(DLG_SELPAG, pag_select);
      vers.sheet_mask().set_handler(DLG_AZZERA, ver_azzera);
      vers.sheet_mask().set_handler(F_TIPOVERS, tipo_hndl);
      vers.sheet_mask().set_handler(F_LUOVERS,  luo_hndl);
      vers.sheet_mask().set_handler(F_ABI,  abicab_hndl);
      vers.sheet_mask().set_handler(F_CAB,  abicab_hndl);
    }
    break;
  default:
    CHECKD(0, "Che strano genere di maschera e' la ", n);
    break;  
  }
  return _msk[n] = m;
}
                               
// Ricerca e output dell'ultimo nprog del percipiente scelto
bool TSchedaPercipienti::setta_nprog(TMask& m, const bool variazione, const char* codanag)
{
  long  nprog = 0L;
  const char tipoa = m.get(F_TIPOA)[0];               
  TString16 codanagr(codanag ? codanag : m.get(F_CODANAGR));
  const long codditta = app().tipo_coll()==nessuno ? get_firm_770() : app().get_firm();

	// Scrivi nprog solo se il percipiente ESISTE sull'arkivio
  if (!app().esiste_perc(m, codanagr))
    return TRUE;
    
  // istanza e inizializza chiave file schede 
  TLocalisamfile scperc(LF_SCPERC, FALSE);    
  scperc.zero();
  scperc.put("CODDITTA", codditta);  
  scperc.put("TIPOA", tipoa);
  scperc.put("CODANAGR", codanagr);
  
  // istanza record di confronto
  TRectype rec(scperc.curr());

  // cerca ultimo progressivo usato 
  // e per tipo collegamento variazione
  // individuo eventuale scheda coincidente 
  bool trovato = FALSE;
  for (scperc.read(_isgteq); scperc.good() && scperc.curr() == rec && !trovato; scperc.next())
  {
    nprog = scperc.get_long("NPROG");   
    if (variazione)
    {                                   
    	TString16 numdoc,datadoc;
    	numdoc = scperc.get("NUMDOC");    
      numdoc.trim();                     
      datadoc = scperc.get("DATADOC");            
      trovato = ((numdoc == app()._coll._numdoc) && (datadoc == app()._coll._datadoc));
    }      
  }
  
  m.set(F_NPROG, trovato ? nprog : nprog+1);

  return variazione ? trovato : TRUE;
}

bool TSchedaPercipienti::codditta_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB && !(f.mask().is_running()) )
  {
    TString16 codditta;      
		// Se chiamata dalla contabilita' prendo ditta con get_firm    
    if (app().tipo_coll() == nessuno)
      codditta << get_firm_770();
    else
      codditta << app().get_firm();
      
    if (codditta != "0")
    {
      f.set(codditta);
      f.check();
    }
  }   
  return TRUE;
}

bool TSchedaPercipienti::codanagr_handler(TMask_field& f, KEY k)
{
  if (k == K_TAB)
  {
    TMask& m = f.mask();
    const bool variazione = app().coll_variazione();
    TString16 codanagr(f.get());
    if (codanagr.not_empty())  
    {
			if (!app().esiste_perc(f.mask(), codanagr)) 
      	return f.warning_box("Percipiente non valido");
      setta_nprog(m, variazione, codanagr);
    }  
    // faccio a mano decodifica del percipiente 
    // perch� l'automatismo non funziona
    long tmp_codanagr = atol(codanagr);
  	TString16 tmp_tipoa = f.mask().get(F_TIPOA);
  	TString80 tmp_ragsoc = app().get_ragsoc(tmp_tipoa, tmp_codanagr);
  	f.mask().set(F_RAGSOCPER, tmp_ragsoc);
    f.mask().set(F_RAGSOCCOM, tmp_ragsoc);
  }

  return TRUE;
}

bool TSchedaPercipienti::esiste_perc(TMask& m, const char* codanag)
{
  const char tipoa    = m.get(F_TIPOA)[0];               
  TString16 codanagr(codanag ? codanag : m.get(F_CODANAGR));

	// Controllo che l'anagrafica esista
  TLocalisamfile anag(LF_ANAG);
  anag.zero();
  anag.put("TIPOA",    tipoa);
  anag.put("CODANAGR", codanagr);
  const bool esiste_anagr = anag.read() == NOERR;   
  
  // memorizzo flag soggetto non residente nel dato membro usato 
  // nei controlli
  if (esiste_anagr)
  	_soggnres = anag.get_bool("SOGGNRES");    

  return esiste_anagr;
}

// Passa al modo inserimento/modifica.
bool TSchedaPercipienti::nprog_handler(TMask_field& f, KEY key)
{
  if (!f.mask().is_running()) 
    return TRUE;            

  if (key == K_CTRL+K_TAB)
  {
    f.set_dirty();
    return TRUE;
  }
    
  const int nprog = atoi(f.get());

  if (key == K_ENTER)
    if (app()._flag_cg)
    {
      app()._flag_cg = FALSE;   // avoid recursion
      if (nprog==0 || !app().esiste_perc(f.mask())) 
        return FALSE;
    }
  return TRUE;
}

bool TSchedaPercipienti::user_create()
{                          
  _per      = new TLocalisamfile(LF_PERC);
  _rel      = new TSchedaPE;
  _rver     = new TLocalisamfile(LF_RVER);
  _rpag     = new TLocalisamfile(LF_RPAG);

  _pags = new TNikArray_sheet(-1, -1, -4, -4, "Selezione Pagamenti",
         "@1|Data@11|Compenso@16|Ritenuta@16|",
         0,NULL_WIN,5);

  set_search_field(F_CODANAGRPERC);

//  simulo una chiamata da contabilit�
//  (lo lascio per eventuali prove)
//  real totdocla = 1000000;
//  real spesela = ZERO;
//	real compensola = 1000000;
//	real impostela = ZERO;
//	real ritenutela = ZERO;
//	TToken_string s(80);
//  s.add(pagamento);
//  s.add("M");
//  s.add("F");
//  s.add(30010);
//  s.add(1);
//  s.add("1");
//  s.add("01-01-1996");
//  s.add(totdocla.string());
//  s.add(spesela.string());    
//  s.add(compensola.string());    
//  s.add(impostela.string());    
//  s.add(ritenutela.string());   
//  const char* name = "770 -0";
//  TMessage mla(name, "LINK770", s);                                                      
//  mla.send();                        
    
// Collegamento da contabilita'
  TMailbox m;
  TMessage* msg = m.next_s("LINK770");

  if (msg != NULL)           
  {
    if ( !_coll.read(msg->body()) )
#ifdef DBG
      return warning_box("Errore nei parametri passati");
#endif
     ;

    const long ditta_cg = get_firm();
    if (!exist_dichiar_770(ditta_cg))
      if (yesno_box("Creo la dichiarazione per la ditta %ld", ditta_cg))
        if (!enter_dichiar_770(ditta_cg))
#ifdef DBG        
          return warning_box("Creazione dichiarazione fallita!");
#endif          
            ;

  }
    
  load_mask(0);                                   

  return TRUE;
}

bool TSchedaPercipienti::user_destroy()
{ 
  if (_msk[1] != NULL) delete _msk[1];
  if (_msk[0] != NULL) delete _msk[0];

  delete _rel;  delete _per;  delete _rver;
  delete _rpag; delete _pags;

  return TRUE;
}

//
// COMPILA_TESTATA
//
// Usata nel collegamento da cg 
//
void TSchedaPercipienti::compila_testata(TMask& m)
{
  m.set(F_DATADOC,  _coll._datadoc);
  m.set(F_NUMDOC,   _coll._numdoc);
  m.set(F_IVA,      _coll._imposte.string());  
  m.set(F_SPESE,    _coll._spese.string());
  m.set(F_COMPENS,  _coll._compenso.string());
      
  switch (tipo_coll())
  {                               
    case occasionale:
      m.set(F_COMPENS, _coll._compenso.string()); 
      m.set(F_TOTDOC,  _coll._compenso.string());   
      break;
    case fattura:
      m.set(F_TOTDOC, _coll._totdoc.string());   
      m.set(F_TOTRIT, _coll._ritenute.string());
      break;
    default:
      break;
  }
}

bool TSchedaPercipienti::coll_variazione() const
{ 
  return _coll._immissione == 'M' || tipo_coll() == pagamento || 
         tipo_coll() == pagamento_piu_perc; 
}

TString80 TSchedaPercipienti::get_ragsoc(const char* tipoa, const long codanagr)
{
  TLocalisamfile anag(LF_ANAG);
  anag.zero();
  anag.setkey(1);
  anag.put("TIPOA", tipoa);
  anag.put("CODANAGR", codanagr);
  const int rc = anag.read();
  if (rc != NOERR) 
    anag.zero();
  return anag.get("RAGSOC");
}

void TSchedaPercipienti::init_modify_mode(TMask& m)
{
  _from_modify = TRUE;
  _codanagr    = m.get_long(F_CODANAGR);
  _tipoa       = m.get(F_TIPOA);
  _ragsoc = get_ragsoc(_tipoa, _codanagr); 
	
  // inizilizza maschera
  init_mask(m);
}
  
void TSchedaPercipienti::init_insert_mode(TMask& m)
{
  init_mask(m);
}

void TSchedaPercipienti::on_config_change()
{
  TConfig conf(CONFIG_STUDIO);
  _anno_dic = (int)conf.get_long(ANNO_SEL, NULL); 
}

void TSchedaPercipienti::init_query_mode(TMask& m)
{
  m.set(F_ANNODIC, _anno_dic);

// Controllo se chiamata dalla contabilita'  
  if (tipo_coll() != nessuno)
  {                          
    const bool variazione = coll_variazione();        
    _flag_cg = TRUE;                    
    TString16 tipo("");
    tipo << _coll._tipo;
    m.set(F_TIPOA,        tipo);
    if (_coll._codanagr != 0L)
    {
      m.set(F_CODANAGR,     _coll._codanagr);
      m.set(F_CODANAGRPERC, _coll._codanagr);
      m.set(F_CODANAGRCOM,  _coll._codanagr);        
    } 
    
    switch (tipo_coll())
    {
      case fattura:
        setta_nprog(m, variazione);
        m.send_key(K_AUTO_ENTER,0); 
        return;
        break;
      case pagamento:
        if (coll_datanum())
        {
          if (setta_nprog(m, variazione))
          	m.send_key(K_AUTO_ENTER,0);
        }  
        return;
        break;     
      case occasionale:
        m.send_key(K_AUTO_ENTER, 0); 
        return;
        break;
      default:
        break;
    }
  }

  if (_from_modify)  
  {
    m.set(F_TIPOA,    _tipoa);
    m.set(F_CODANAGR, _codanagr);
    m.set(F_CODANAGRPERC, _codanagr);
    m.set(F_CODANAGRCOM, _codanagr);
    m.set(F_RAGSOCPER,   _ragsoc);
    m.set(F_RAGSOCCOM,   _ragsoc);
  }    
  else 
  {
    m.hide(-1);  // group 1 Scelta ANAGR
    m.show(-2);  // group 3 Ricerca su DATI PER
  }

  _from_modify = FALSE;

// forza il ricalcolo dell'ultimo numero disponibile
  TString16 dummy(m.get(F_NPROG));
  if (dummy.not_empty())
    setta_nprog(m);
}

void TSchedaPercipienti::init_query_insert_mode(TMask& m)
{
  m.set(F_ANNODIC, _anno_dic);

// Se vengo da modifica mantieni la selezione precedente
  if (_from_modify)
  {
    m.set(F_TIPOA,    _tipoa);
    m.set(F_CODANAGR, _codanagr);
    m.set(F_CODANAGRPERC, _codanagr);
    m.set(F_CODANAGRCOM, _codanagr);
    m.set(F_RAGSOCPER,   _ragsoc);
    m.set(F_RAGSOCCOM,   _ragsoc);
  }
  else
  {
    m.hide(-2);  // group 3 Nasconde ricerca su PERC
    m.show(-1);  // group 1 Ricerca su ANAGR
  }
}

void TSchedaPercipienti::rec2row(TToken_string& r, TRectype& rec, int row)
{
  TString16     dver, dpag, serie, numero, rite;
  TString16     comp, impo, perc,  spesa, netto;
  TString16     nrigavers, numpag, progrbanca;
  TString		SsnPerc, SsnCompl;
  
  r = ""; 
  if (rec.num() == LF_RVER) 
  {
    char v1015 = rec.get_bool("VERS1015") ? 'X' : ' ';
    dver       = rec.get("DATAVERS");
    char  tv   = rec.get_char("TIPOVERS");
    char  lv   = rec.get_char("LUOVERS");
    serie      = rec.get("SERIE");
    numero     = rec.get("NUMERO");
    rite       = rec.get("RITENUTA");      
    progrbanca = rec.get("PROGBANC");
    nrigavers    = rec.get("NRIGA");    

    if (rite.empty())       rite = " ";
    if (progrbanca.empty()) progrbanca = " ";
    if (nrigavers.empty())  nrigavers = " ";    
    if (serie.empty())      serie = " ";
    if (numero.empty())     numero = " ";
    
    r.add(v1015, 0); 
    r.add(dver,1); 
    r.add(lv == '\0' ? ' ' : lv); 
    r.add(tv == '\0' ? ' ' : tv);
    r.add(serie);     
    r.add(numero);           
    r.add(progrbanca);
    r.add(rite);
    r.add(nrigavers);
    
    if (v1015 == 'X')
      disable_vers_cells(row);
    else
      enable_vers_cells(row);
  }

  if (rec.num() == LF_RPAG)
  {
    // istanza struttura pagamento
		Pag_struct s;
		
    // compilo campi struttura
    s.datapag = rec.get_date("DATAPAG");      
    s.imponibile = rec.get_real("IMPONIBILE");
    s.perc = rec.get_real("PERC");  
    s.ritenuta = rec.get_real("RITENUTA"); 
    s.compenso = rec.get_real("COMPENSO");  
    s.netto = rec.get_real("NETTO"); 
    s.numvers = rec.get_long("NUMVERS");    
    s.spesa = rec.get_real("SPESA");
    s.ctssnperc = rec.get_real("CTSSNPERC");
    s.ctssncomp = rec.get_real("CTSSNCOMP"); 
    s.ritlorda = rec.get_real("RITLORDA");
    s.controbb = rec.get_real("CONTROBB");
    s.detfamil = rec.get_real("DETFAMIL"); 
    s.detlavdip = rec.get_real("DETLAVDIP");
    s.totdet = rec.get_real("TOTDET");
    s.giolavdip = rec.get_int("GIOLAVDIP"); 
    s.impcpa = rec.get_real("IMPCPA"); 
    s.somregconv = rec.get_real("SOMREGCONV");
    s.alqimp10 = rec.get_real("ALQIMP10"); 
    s.cod10 = rec.get("COD10");
    s.utpagati = rec.get_real("UTPAGATI");
    s.utspett = rec.get_real("UTSPETT");
    s.ritutpag = rec.get_real("RITUTPAG");
    s.ritutspe = rec.get_real("RITUTSPE"); 
    s.nquote = rec.get_real("NQUOTE"); 
    s.somnsrit = rec.get_real("SOMNSRIT");
    s.ammlordo = rec.get_real("AMMLORDO");
    s.quotaprov = rec.get_real("QUOTAPROV");
    s.impnetto = rec.get_real("IMPNETTO");
    s.comnetto = rec.get_real("COMNETTO");  
    
    // compilo riga di sheet 
    from_struct_to_sheet(s, r);
  }
}

int TSchedaPercipienti::read(TMask& m)
{
  m.autoload(*_rel);
  
  // reperische sheet attivo forzando l'abilitazione in base al quadro
  // ci� � necessario per attivare lo sheet corretto quando
  // si esce/entra dalle singole schede
  TSheet_field& pags = pag_sheet_enabled(m,TRUE);
  
  pags.destroy();
  
  for (int r = 0; r < _rel->pag_items(); r++)
    rec2row(pags.row(r), _rel->pag(r), r);

  TSheet_field& vers = (TSheet_field&)m.field(F_VERSAMENTI);
  vers.destroy();
  
  for (r = 0; r < _rel->ver_items(); r++) 
    rec2row(vers.row(r), _rel->ver(r), r);
      
  return 0;
}            

void TSchedaPercipienti::enable_vers_cells(int r, bool enable)
{
  TSheet_field& ver = vers();
  // calcolo numero di colonne utili (scartando l'ultima)    
  int num_col = ver.row(r).items() - 1;
  // abilito/disabilito celle 
  for (int i=1; i<num_col; i++)
    enable ? ver.enable_cell(r,i) : ver.disable_cell(r,i);
}

void TSchedaPercipienti::new_row(TSheet_field& ver_pag, int r, bool vers) 
{ 
  TToken_string&    riga = ver_pag.row(r);

  if (vers)
    riga.add(++_lastvers, COLONNE_SIGNIFICATIVE_SPREADSHEET_VERSAMENTI);
  else		
    riga.add(-1, num_sheet_column());  
}
          
//
//  FILL_SHEET
//  
// Determino QUI un progressivo unico per i pagamenti e i versamenti
// (NUMVERS e NUMPAG: vedi new_row())
void TSchedaPercipienti::fill_sheet(TMask& m) 
{ 
  // leggo codice quadro
	TString16 qua(m.get(F_CODQUA));        
  
  TSheet_field& pags = pag_sheet_enabled(m);
  for (int r = pags.items(); r < 16; r++)
    new_row(pags, r, FALSE);

  TSheet_field& vers = (TSheet_field&)m.field(F_VERSAMENTI);
  for (r = vers.items(); r < 16; r++) 
    new_row(vers, r, TRUE);
}

bool TSchedaPercipienti::scrivi_dati_per(TRectype& rec)
{
  TLocalisamfile dati_per(LF_PERC);
  const long codditta = rec.get_long("CODDITTA");
  char       tipoa    = rec.get_char("TIPOA");
  const long codanagr = rec.get_long("CODANAGR");
  
  dati_per.zero();
  dati_per.put("CODDITTA", codditta);    
  dati_per.put("TIPOA", tipoa);    
  dati_per.put("CODANAGR", codanagr);   
  
  const bool preesistente = (dati_per.read() == NOERR);
  
  if (!preesistente)
  {
    dati_per.zero();
    dati_per.put("CODDITTA", codditta);    
    dati_per.put("TIPOA", tipoa);    
    dati_per.put("CODANAGR", codanagr);   
  
    dati_per.write();   
  }
    
  return preesistente;
}

int  TSchedaPercipienti::rewrite(const TMask& m)
{
  mask2rel(m);
  const int err = _rel->rewrite();
  scrivi_dati_per(_rel->curr());
  return err;
}

int  TSchedaPercipienti::write(const TMask& m)
{
  mask2rel(m);
  const int err = _rel->write();
  scrivi_dati_per(_rel->curr());
  return err;
}

bool TSchedaPercipienti::check_compensi(TMask_field& f, KEY k)           
{
  if (k == K_ENTER)
  {
    const bool forzatura = f.mask().get_bool(F_FORCED);  
    real       doc_compenso(f.get());

    if (app()._tot_compenso > doc_compenso)
    {  
      f.warning_box("Il totale dei compensi non puo' superare\n"
                    "il compenso indicato nel documento");

      return forzatura;
    }
  }
  return TRUE;     
}

bool TSchedaPercipienti::check_spese(TMask_field& f, KEY k)           
{
  if (k == K_ENTER)
  {
    const bool forzatura = f.mask().get_bool(F_FORCED);  
    real       doc_spese(f.get());

    if (app()._tot_spese > doc_spese)
    {
      f.warning_box ("Il totale delle spese non puo' superare\n"
                     "la spesa indicata nel documento");
      return forzatura;
    }
  }
  return TRUE;
}        

bool TSchedaPercipienti::check_competenza(TMask_field& f, KEY k)           
{
  if (k == K_ENTER)
  {
    const bool forzatura = f.mask().get_bool(F_FORCED);  
    int anno_competenza(f.mask().get_int(F_ANNOCOMP)); 
    int mese_competenza(f.mask().get_int(F_MESECOMP)); 

    if (anno_competenza && !mese_competenza)
    {
      f.warning_box ("Indicare anche il mese di competenza");
      return forzatura;
    }     
    
    if (!anno_competenza && mese_competenza)
    {
      f.warning_box ("Indicare anche l'anno competenza");
      return forzatura;
    }
  }
  return TRUE;
}

//           
// Calcola:
//
// totale compenzi
// totale spese
// totale netti pagati
//
// - NB - 
// FUNZIONA SOLO SE PASSA PRIMA DI QUA!
// 
bool TSchedaPercipienti::check_handler(TMask_field& f, KEY k)
{  
  if (k == K_ENTER)
  {      
    TMask& m = f.mask();
    
    const bool forzatura = m.get_bool(F_FORCED);    
    int     i;
    TArray& rpag = app().pags().rows_array();

    app()._tot_compenso = ZERO;
    app()._tot_spese    = ZERO;
    app()._tot_rit      = ZERO;
    
		// Calcolo totale compensi, totale spese e totale ritenute  
    for (i = 0; i < rpag.items(); i++)
    {
      TToken_string& row = (TToken_string&)rpag[i];    
      
      if (app().my_empty_items(row, FALSE)) continue;                   
      
      real compenso = ZERO;
      real spese = ZERO;
      real ritenuta = ZERO;      
      real netto = ZERO;               

      int pos;
			if ((pos = app().token_pos("COMPENSO")) != -1)
      	compenso = row.get(pos);                 
      if ((pos = app().token_pos("SPESA")) != -1)	
      	spese = row.get(pos);                     
      if ((pos = app().token_pos("RITENUTA")) != -1)		
      	ritenuta = row.get(pos);
      
      app()._tot_compenso  += compenso;
      app()._tot_spese     += spese;
      app()._tot_rit       += ritenuta;               
    }
    
    TArray& rver        = app().vers().rows_array();
    app()._tot_vers     = ZERO;  
    
		// Calcola totale versato
    for (i = 0; i < rver.items(); i++)
    { 
      TToken_string& row = (TToken_string&)rver[i];    
      if (app().my_empty_items(row, TRUE)) continue;  
      real       versato (row.get(7));
      app()._tot_vers  += versato;
    }

    app()._tot_rit.round(0);
    app()._tot_vers.round(0);
    
    // memorizzo i totali ritenute pagate/versate
    m.set(F_RITOPE, app()._tot_rit);  
    m.set(F_RITVER, app()._tot_vers); 
    
    const real THRESOLD = 500.00;
    const real diff = app()._tot_vers - app()._tot_rit;
    
    if (app()._tot_vers != ZERO && diff > ZERO)
      if (diff > THRESOLD)
      {
        f.warning_box ("La differenza tra il totale dei versamenti " 
                       "e il totale delle ritenute non puo' superare "
                       "le %s lire", THRESOLD.string());
        return forzatura;
      }
  }
  return TRUE;
}

// Trasferisce i dati dalla maschera alla relazione
void TSchedaPercipienti::mask2rel(const TMask& m)
{
  _rel->lfile().zero();
  m.autosave(*_rel);
  
  // leggo chiave scheda
  const long codditta = m.get_long(F_CODDITTA);
  const char tipoa    = m.get(F_TIPOA)[0];
  const long codanagr = m.get_long(F_CODANAGR);
  const int  nprogr   = m.get_int(F_NPROG);  
     
  // leggo valori tabella causali per calcolo
  const real h_PercAssImp = m.get_real(F_QUOTAIMP);
	const real h_PercCassaPrev = m.get_real(F_CASSA_PREV); 
	const real h_PercRitenuta = m.get_real(F_PERRIT);     
	const bool h_FlagInps = m.get_bool(F_FLAG_INPS);
	const real h_PercInps = m.get_real(F_PERC_INPS); 
	const real h_PercAssImpInps = m.get_real(F_PERC_ASS_INPS);
	const real h_PercCommitInps = m.get_real(F_PERC_COMMIT_INPS);
      
  // istanza struttura di comodo per calcolo riga pagamenti
	Pag_struct c; 
  
  _rel->destroy_rows();                  // Destroy all records
  pag_pack();                            // Destroy all null rows

  
  // salva pagamenti
  TArray& rows = pags().rows_array();  
  for (int i = 0; i < rows.items(); i++)
  {
    TToken_string& row = (TToken_string&)rows[i];
    TRectype &r = _rel->pag(i);

    long nriga = i + 1;
    
    // compilo campi chiave
    r.zero();
    r.put("CODDITTA", codditta);
    r.put("TIPOA",    tipoa);
    r.put("CODANAGR", codanagr);
    r.put("NPROG",    nprogr);
    r.put("NRIGA",    nriga);

		// compilo struttura rigo di pagamento
		Pag_struct s;                         
		from_sheet_to_struct(row, s);
		
		// ricalcolo riga pagamento
		// (per ottenere la congruit� dei dati semplicemente 
		// registrando la scheda) 
		calcola_riga_pag(s,
									   c,	
									   FALSE,  
									   h_PercAssImp,
									   h_PercCassaPrev,
									   h_PercRitenuta,
									   h_PercInps,
									   h_PercAssImpInps,
									   h_PercCommitInps);	
		
    // compilo restanti campi
    r.put("DATAPAG", s.datapag);      
    r.put("IMPONIBILE",s.imponibile);
    r.put("PERC", s.perc);  
    r.put("RITENUTA", s.ritenuta); 
    r.put("COMPENSO", s.compenso);  
    r.put("NETTO",s.netto); 
    r.put("NUMVERS", s.numvers);    
    r.put("SPESA", s.spesa);
    r.put("CTSSNPERC", s.ctssnperc);
    r.put("CTSSNCOMP", s.ctssncomp); 
    r.put("RITLORDA", s.ritlorda);
    r.put("CONTROBB", s.controbb);
    r.put("DETFAMIL", s.detfamil); 
    r.put("DETLAVDIP", s.detlavdip);
    r.put("TOTDET", s.totdet);
    r.put("GIOLAVDIP", s.giolavdip); 
    r.put("IMPCPA", s.impcpa); 
    r.put("SOMREGCONV", s.somregconv);
    r.put("ALQIMP10", s.alqimp10); 
    r.put("COD10", s.cod10);
    r.put("UTPAGATI", s.utpagati);
    r.put("UTSPETT", s.utspett);
    r.put("RITUTPAG", s.ritutpag);
    r.put("RITUTSPE", s.ritutspe); 
    r.put("NQUOTE", s.nquote); 
    r.put("SOMNSRIT", s.somnsrit);
    r.put("AMMLORDO", s.ammlordo);
    r.put("QUOTAPROV", s.quotaprov);
    r.put("IMPNETTO", s.impnetto);
    r.put("COMNETTO", s.comnetto);
  }

  // salva versamenti
  rows = vers().rows_array();  
  for (i = 0; i < rows.items(); i++)
  {
    TToken_string& row = (TToken_string&)rows[i];
    TRectype &r = _rel->ver(i);
    
    if (my_empty_items(row, TRUE))
      continue;  // non salvare righe vuote
      
    long nriga = i+1;
    
    r.zero();
    r.put("CODDITTA", codditta);
    r.put("TIPOA", tipoa);
    r.put("CODANAGR", codanagr);
    r.put("NPROG", nprogr);
    r.put("NRIGA", nriga);   

		// LEGGO SPREADSHEET VERSAMENTI    
    const bool vers1015 = (row.get_char(0) == 'X');
    TString16 datav = row.get(1);
    const TDate dataver(datav);

    const char luogo = row.get_char(2);
    const char tipo  = row.get_char(3);
    
    TString16  serie(row.get(4));
    TString    numero(row.get(5));  
    const long ProgBanca(row.get_long(6));
    real       ritenuta  (row.get(7));
    const int  numvers (row.get_int(8));
   
    r.put("VERS1015",vers1015);  
    r.put("DATAVERS",dataver);  
    r.put("LUOVERS", luogo); 
    r.put("TIPOVERS",tipo);    
    r.put("SERIE",   serie); 
    r.put("NUMERO",  numero); 
    r.put("PROGBANC",ProgBanca);
    r.put("RITENUTA",ritenuta);
  }
}

TMask& TSchedaPercipienti::TheMask() const
{
	if (_msk[1] == NULL)
		error_box("Maschera di inserimento/modifica non ancora istanziata!");
	
	return *(_msk[1]);
}             

TSheet_field& TSchedaPercipienti::pag_sheet_enabled(TMask& m, bool force_enable) const
{
	TSheet_field* s = NULL;

	// istanza reference sheet a disposizione
	TSheet_field& s_C = (TSheet_field&)m.field(F_PAGAMENTI_C);
	TSheet_field& s_D = (TSheet_field&)m.field(F_PAGAMENTI_D);
	TSheet_field& s_DB = (TSheet_field&)m.field(F_PAGAMENTI_DB);
	TSheet_field& s_G = (TSheet_field&)m.field(F_PAGAMENTI_G);
	
	// forza la disabilitazione di tutti se richiesta
	// l'abilitazionein base al quadro
	if (force_enable) 
	{
		s_C.hide(); 
		s_D.hide();
		s_DB.hide();	
		s_G.hide(); 
	}	
		
	// valorizzo reference sheet abilitato                    
	if (s_C.shown()) 
		s = &s_C;
	if (s_D.shown())
		s = &s_D;
	if (s_DB.shown())
		s = &s_DB;   	 
	if (s_G.shown())
		s = &s_G;	
		
	// se nessuno abilitato forzo l'abilitazione in base al quadro
	// questo si rende necessario per il primo che invoca questo
	// metodo, in quanto gli sheet sono hide alla partenza 
	if (s == NULL)
	{
		// reperisco codice quadro della scheda 
		TString16 codcau(_rel->lfile().get("CODCAUS"));
		TTable cau("%ca7");
		cau.zero();
		cau.put("CODTAB", codcau);
		TString16 qua = "C";
		if (cau.read() == NOERR)
			qua = cau.get("S1");  
			
		// abilito sheet 	
    s = &(enable_pag_sheet(m, qua));   
    
    // aggancio handler
  	set_pag_handler(*s);
  }  
	
	return *s;	
}             

bool TSchedaPercipienti::activate_pag_sheet(TMask& m)
{
	// reperisco sheet attivo da cui copiare, la Token_string pilota 
	// e il numero di colonne 
	TSheet_field& prev_s = pag_sheet_enabled(m);
	TToken_string prev_pilot(pilot_sheet());    
	int prev_col = num_sheet_column() + 1;  
	
	// leggo codice quadro
	TString16 qua(m.get(F_CODQUA));
	
	// abilito sheet 	
  TSheet_field& curr_s = enable_pag_sheet(m, qua);	
		
	// reperisco la Token_string pilota dallo sheet attivo
	TToken_string curr_pilot(pilot_sheet());
	
	// copia dallo sheet disattivato a quello attivato solo se non coincidono,
	// preoccupandosi di spostare le colonne al posto giusto 
	if (prev_s.dlg() != curr_s.dlg())
	{
		curr_s.destroy();
		for (int i=0; i<prev_s.items(); i++) 
		{
			TToken_string curr_row;
			for (int j=0; j<prev_col; j++) 
			{ 
				// trovo posizione token nello sheet attivo
				TString prev_token(prev_pilot.get(j));
				int pos = token_pos((const char*)prev_token);
				// copio solo se � presente nello sheet attivo
				if (pos != -1)      
				{
					TString prev_val(prev_s.row(i).get(j));
					curr_row.add(prev_val, pos);
				}
			}    
			curr_s.row(i) = curr_row;
		}
	}

	// ricalcolo tutte le righe pagamento
	const real h_PercAssImp = m.get_real(F_QUOTAIMP);
	const real h_PercCassaPrev = m.get_real(F_CASSA_PREV); 
	const real h_PercRitenuta = m.get_real(F_PERRIT);     
	const bool h_FlagInps = m.get_bool(F_FLAG_INPS);
	const real h_PercInps = m.get_real(F_PERC_INPS); 
	const real h_PercAssImpInps = m.get_real(F_PERC_ASS_INPS);
	const real h_PercCommitInps = m.get_real(F_PERC_COMMIT_INPS);
	// istanza strutture per calcolo
	Pag_struct c;
	Pag_struct s;
	// elaboro le righe di pagamento
	for (int r = 0; r < curr_s.items(); r++)   
  {					
		TToken_string& t = curr_s.row(r);
		if (!my_empty_items(t, FALSE)) 
		{
			from_sheet_to_struct(t, s);
			calcola_riga_pag(s,
										   c,	
										   TRUE,  
										   h_PercAssImp,
										   h_PercCassaPrev,
										   h_PercRitenuta,
										   h_PercInps,
										   h_PercAssImpInps,
										   h_PercCommitInps);			
			from_struct_to_sheet(s, t);  
		}	
	}   
	
	// aggancio handler pagamenti
  set_pag_handler(curr_s);     
  
  // forzo ridisegno dello sheet a video
	curr_s.force_update();					
	
	return TRUE;	
}                                                    

int TSchedaPercipienti::num_sheet_column() const
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());
		
	// ritorno il numero di colonne ignorando l'ultima
	// che � ad uso interno	
	return columns.items()-1;	
}                                               

int TSchedaPercipienti::token_pos(const char* t) const
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());  
	
	// ritorno la posizione del token richiesto
	return columns.get_pos(t);	
}                                                     

int TSchedaPercipienti::token_dlg(const char* t) const
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());  
	
	// ritorno l'identificatore del token richiesto
	int dlg = columns.get_pos(t);
	if (dlg != -1)
		dlg += 101;
	return dlg;	
}                                                     

const char* TSchedaPercipienti::pilot_sheet() const
{
	// reperisco sheet attivo
	TSheet_field& s = pag_sheet_enabled(TheMask());
	
	// individuo la testata giusta
	char* columns;  
	int dlg = s.dlg();
	switch(dlg)
	{
		case F_PAGAMENTI_C  : columns = (char*)PILOT_SHEET[0]; break;	
	  case F_PAGAMENTI_D  : columns = (char*)PILOT_SHEET[1]; break;
		case F_PAGAMENTI_DB : columns = (char*)PILOT_SHEET[2]; break;
	  case F_PAGAMENTI_G	: columns = (char*)PILOT_SHEET[3]; break;
    default : break;
	}
		
	// ritorno la Token_string pilota
	return columns;	
}                                                  

Pag_struct& TSchedaPercipienti::from_sheet_to_struct(TToken_string& t, Pag_struct& s)
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());
	
	// azzero struttura 
	clear_struct(s);
	
	// posizione dell'informazione all'interno della Token_string
	int pos;
	
	// set data pagamento
	if ((pos = token_pos("DATAPAG")) != -1)  
	{
		TString16 datap = t.get(pos);
  	s.datapag = datap; 
  }
  
  // set imponibile
	if ((pos = token_pos("IMPONIBILE")) != -1)
  	s.imponibile = t.get(pos);
  
  // set percentuale ritenuta
	if ((pos = token_pos("PERC")) != -1)
  	s.perc = t.get(pos);	 

  // set ritenuta
	if ((pos = token_pos("RITENUTA")) != -1)
  	s.ritenuta = t.get(pos);	 

  // set compenso
	if ((pos = token_pos("COMPENSO")) != -1)
  	s.compenso = t.get(pos);	 

  // set compenso netto
	if ((pos = token_pos("NETTO")) != -1)
  	s.netto = t.get(pos);	 

  // set numero versamento collegato
	if ((pos = token_pos("NUMVERS")) != -1)
  	s.numvers = t.get_long(pos);	 

  // set spesa
	if ((pos = token_pos("SPESA")) != -1)
  	s.spesa = t.get(pos);	 

  // set contr.10% percipiente
	if ((pos = token_pos("CTSSNPERC")) != -1)
  	s.ctssnperc = t.get(pos);	 

  // set contr.10% complessivo
	if ((pos = token_pos("CTSSNCOMP")) != -1)
  	s.ctssncomp = t.get(pos);	 

  // set ritenuta lorda
	if ((pos = token_pos("RITLORDA")) != -1)
  	s.ritlorda = t.get(pos);	 

  // set contributi obbligatori
	if ((pos = token_pos("CONTROBB")) != -1)
  	s.controbb = t.get(pos);	 

  // set detrazioni famigliari
	if ((pos = token_pos("DETFAMIL")) != -1)
  	s.detfamil = t.get(pos);	 

  // set detrazioni lavoro dipendente
	if ((pos = token_pos("DETLAVDIP")) != -1)
  	s.detlavdip = t.get(pos);	 

  // set totale detrazioni
	if ((pos = token_pos("TOTDET")) != -1)
  	s.totdet = t.get(pos);	 

  // set giorni lavoro dipendente
	if ((pos = token_pos("GIOLAVDIP")) != -1)
  	s.giolavdip = t.get_int(pos);	 

  // set importo CPA
	if ((pos = token_pos("IMPCPA")) != -1)
  	s.impcpa = t.get(pos);	 

  // set somme regime convenzionale
	if ((pos = token_pos("SOMREGCONV")) != -1)
  	s.somregconv = t.get(pos);	 

  // set percentuale contributo 10%
	if ((pos = token_pos("ALQIMP10")) != -1)
  	s.alqimp10 = t.get(pos);	 

  // set codice contributo 10%
	if ((pos = token_pos("COD10")) != -1)
  	s.cod10 = t.get(pos);	 

  // set utili pagati
	if ((pos = token_pos("UTPAGATI")) != -1)
  	s.utpagati = t.get(pos);	 

  // set utili spettanti
	if ((pos = token_pos("UTSPETT")) != -1)
  	s.utspett = t.get(pos);	 

  // set ritenuta utili pagati
	if ((pos = token_pos("RITUTPAG")) != -1)
  	s.ritutpag = t.get(pos);	 

  // set ritenuta utili spettanti
	if ((pos = token_pos("RITUTSPE")) != -1)
  	s.ritutspe = t.get(pos);	 

  // set numero quote
	if ((pos = token_pos("NQUOTE")) != -1)
  	s.nquote = t.get(pos);	 

  // set somme non sogg.ritenuta
	if ((pos = token_pos("SOMNSRIT")) != -1)
  	s.somnsrit = t.get(pos);	 

  // set ammontare lordo
	if ((pos = token_pos("AMMLORDO")) != -1)
  	s.ammlordo = t.get(pos);	 

  // set quota provvigioni
	if ((pos = token_pos("QUOTAPROV")) != -1)
  	s.quotaprov = t.get(pos);	 

  // set imponibile al netto ritenute
	if ((pos = token_pos("IMPNETTO")) != -1)
  	s.impnetto = t.get(pos);	 

  // set compenso al netto ritenute
	if ((pos = token_pos("COMNETTO")) != -1)
  	s.comnetto = t.get(pos);	     
  	
  // set numero versamento collegato
	if ((pos = token_pos("NUMVERS")) != -1)
  	s.numvers = t.get_long(pos);	 	

	return s;
}    

void TSchedaPercipienti::from_struct_to_sheet(Pag_struct& s, TToken_string& t)
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());
	
	// posizione dell'informazione all'interno della Token_string
	int pos;
	
	// set data pagamento
	if ((pos = token_pos("DATAPAG")) != -1)
		t.add(s.datapag, pos);
  
  // set imponibile
	if ((pos = token_pos("IMPONIBILE")) != -1)
  	t.add(s.imponibile.string(), pos);
  
  // set percentuale ritenuta
	if ((pos = token_pos("PERC")) != -1)
  	t.add(s.perc.string(), pos);	 

  // set ritenuta
	if ((pos = token_pos("RITENUTA")) != -1)
  	t.add(s.ritenuta.string(), pos);	 

  // set compenso
	if ((pos = token_pos("COMPENSO")) != -1)
  	t.add(s.compenso.string(), pos);	 

  // set compenso netto
	if ((pos = token_pos("NETTO")) != -1)
  	t.add(s.netto.string(), pos);	 

  // set numero versamento collegato
	if ((pos = token_pos("NUMVERS")) != -1)
  	t.add(s.numvers, pos);	 

  // set spesa
	if ((pos = token_pos("SPESA")) != -1)
  	t.add(s.spesa.string(), pos);	 

  // set contr.10% percipiente
	if ((pos = token_pos("CTSSNPERC")) != -1)
  	t.add(s.ctssnperc.string(), pos);	 

  // set contr.10% complessivo
	if ((pos = token_pos("CTSSNCOMP")) != -1)
  	t.add(s.ctssncomp.string(), pos);	 

  // set ritenuta lorda
	if ((pos = token_pos("RITLORDA")) != -1)
  	t.add(s.ritlorda.string(), pos);	 

  // set contributi obbligatori
	if ((pos = token_pos("CONTROBB")) != -1)
  	t.add(s.controbb.string(), pos);	 

  // set detrazioni famigliari
	if ((pos = token_pos("DETFAMIL")) != -1)
  	t.add(s.detfamil.string(), pos);	 

  // set detrazioni lavoro dipendente
	if ((pos = token_pos("DETLAVDIP")) != -1)
  	t.add(s.detlavdip.string(), pos);	 

  // set totale detrazioni
	if ((pos = token_pos("TOTDET")) != -1)
  	t.add(s.totdet.string(), pos);	 

  // set giorni lavoro dipendente
	if ((pos = token_pos("GIOLAVDIP")) != -1)
  	t.add(s.giolavdip, pos);	 

  // set importo CPA
	if ((pos = token_pos("IMPCPA")) != -1)
  	t.add(s.impcpa.string(), pos);	 

  // set somme regime convenzionale
	if ((pos = token_pos("SOMREGCONV")) != -1)
  	t.add(s.somregconv.string(), pos);	 

  // set percentuale contributo 10%
	if ((pos = token_pos("ALQIMP10")) != -1)
  	t.add(s.alqimp10.string(), pos);	 

  // set codice contributo 10%
	if ((pos = token_pos("COD10")) != -1)
  	t.add(s.cod10, pos);	 

  // set utili pagati
	if ((pos = token_pos("UTPAGATI")) != -1)
  	t.add(s.utpagati.string(), pos);	 

  // set utili spettanti
	if ((pos = token_pos("UTSPETT")) != -1)
  	t.add(s.utspett.string(), pos);	 

  // set ritenuta utili pagati
	if ((pos = token_pos("RITUTPAG")) != -1)
  	t.add(s.ritutpag.string(), pos);	 

  // set ritenuta utili spettanti
	if ((pos = token_pos("RITUTSPE")) != -1)
  	t.add(s.ritutspe.string(), pos);	 

  // set numero quote
	if ((pos = token_pos("NQUOTE")) != -1)
  	t.add(s.nquote.string(), pos);	 

  // set somme non sogg.ritenuta
	if ((pos = token_pos("SOMNSRIT")) != -1)
  	t.add(s.somnsrit.string(), pos);	 

  // set ammontare lordo
	if ((pos = token_pos("AMMLORDO")) != -1)
  	t.add(s.ammlordo.string(), pos);	 

  // set quota provvigioni
	if ((pos = token_pos("QUOTAPROV")) != -1)
  	t.add(s.quotaprov.string(), pos);	 

  // set imponibile al netto ritenute
	if ((pos = token_pos("IMPNETTO")) != -1)
  	t.add(s.impnetto.string(), pos);	 

  // set compenso al netto ritenute
	if ((pos = token_pos("COMNETTO")) != -1)
  	t.add(s.comnetto.string(), pos);
  	
  // set numero versamento collegato	    
  if ((pos = token_pos("NUMVERS")) != -1)
  	t.add(s.numvers, pos);
} 

Pag_struct& TSchedaPercipienti::from_mask_to_struct(TMask& m, Pag_struct& s)
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());
	
	// azzero struttura 
	clear_struct(s);
	
	// identificatore del token all'interno della maschera
	int dlg;
	
	// set data pagamento
	if ((dlg = token_dlg("DATAPAG")) != -1)
  	s.datapag = m.get_date(dlg);	 

  // set imponibile
	if ((dlg = token_dlg("IMPONIBILE")) != -1)
  	s.imponibile = m.get_real(dlg);	 

  // set percentuale ritenuta
	if ((dlg = token_dlg("PERC")) != -1)
  	s.perc = m.get_real(dlg);	 

  // set ritenuta
	if ((dlg = token_dlg("RITENUTA")) != -1)
  	s.ritenuta = m.get_real(dlg);	 

  // set compenso
	if ((dlg = token_dlg("COMPENSO")) != -1)
  	s.compenso = m.get_real(dlg);	 

  // set compenso netto
	if ((dlg = token_dlg("NETTO")) != -1)
  	s.netto = m.get_real(dlg);

  // set spesa
	if ((dlg = token_dlg("SPESA")) != -1)
  	s.spesa = m.get_real(dlg);	 

  // set contr.10% percipiente
	if ((dlg = token_dlg("CTSSNPERC")) != -1)
  	s.ctssnperc = m.get_real(dlg);	 

  // set contr.10% complessivo
	if ((dlg = token_dlg("CTSSNCOMP")) != -1)
  	s.ctssncomp = m.get_real(dlg);	 

  // set ritenuta lorda
	if ((dlg = token_dlg("RITLORDA")) != -1)
  	s.ritlorda = m.get_real(dlg);	 

  // set contributi obbligatori
	if ((dlg = token_dlg("CONTROBB")) != -1)
  	s.controbb = m.get_real(dlg);	 

  // set detrazioni famigliari
	if ((dlg = token_dlg("DETFAMIL")) != -1)
  	s.detfamil = m.get_real(dlg);	 

  // set detrazioni lavoro dipendente
	if ((dlg = token_dlg("DETLAVDIP")) != -1)
  	s.detlavdip = m.get_real(dlg);	 

  // set totale detrazioni
	if ((dlg = token_dlg("TOTDET")) != -1)
  	s.totdet = m.get_real(dlg);	 

  // set giorni lavoro dipendente
	if ((dlg = token_dlg("GIOLAVDIP")) != -1)
  	s.giolavdip = m.get_int(dlg);	 

  // set importo CPA
	if ((dlg = token_dlg("IMPCPA")) != -1)
  	s.impcpa = m.get_real(dlg);	 

  // set somme regime convenzionale
	if ((dlg = token_dlg("SOMREGCONV")) != -1)
  	s.somregconv = m.get_real(dlg);	 

  // set percentuale contributo 10%
	if ((dlg = token_dlg("ALQIMP10")) != -1)
  	s.alqimp10 = m.get_real(dlg);	 

  // set codice contributo 10%
	if ((dlg = token_dlg("COD10")) != -1)
  	s.cod10 = m.get(dlg);	 

  // set utili pagati
	if ((dlg = token_dlg("UTPAGATI")) != -1)
  	s.utpagati = m.get_real(dlg);	 

  // set utili spettanti
	if ((dlg = token_dlg("UTSPETT")) != -1)
  	s.utspett = m.get_real(dlg);	 

  // set ritenuta utili pagati
	if ((dlg = token_dlg("RITUTPAG")) != -1)
  	s.ritutpag = m.get_real(dlg);	 

  // set ritenuta utili spettanti
	if ((dlg = token_dlg("RITUTSPE")) != -1)
  	s.ritutspe = m.get_real(dlg);	 

  // set numero quote
	if ((dlg = token_dlg("NQUOTE")) != -1)
  	s.nquote = m.get_real(dlg);	 
  
  // set somme non sogg.ritenuta
	if ((dlg = token_dlg("SOMNSRIT")) != -1)
  	s.somnsrit = m.get_real(dlg);	 

  // set ammontare lordo
	if ((dlg = token_dlg("AMMLORDO")) != -1)
  	s.ammlordo = m.get_real(dlg);	 

  // set quota provvigioni
	if ((dlg = token_dlg("QUOTAPROV")) != -1)
  	s.quotaprov = m.get_real(dlg);	 

  // set imponibile al netto ritenute
	if ((dlg = token_dlg("IMPNETTO")) != -1)
  	s.impnetto = m.get_real(dlg);	 

  // set compenso al netto ritenute
	if ((dlg = token_dlg("COMNETTO")) != -1)
  	s.comnetto = m.get_real(dlg);	        
  	
  // set numero versamento collegato	    
  if ((dlg = token_dlg("NUMVERS")) != -1)
  	s.numvers = m.get_long(dlg);	        	
  
	return s;
}                                                                           

void TSchedaPercipienti::from_struct_to_mask(Pag_struct& s, TMask& m)
{
	// reperisco la Token_string pilota
	TToken_string columns(pilot_sheet());
	
	// identificatore del token all'interno della maschera
	int dlg;
	
	// set data pagamento
	if ((dlg = token_dlg("DATAPAG")) != -1)
  	m.set(dlg, s.datapag);	 

  // set imponibile
	if ((dlg = token_dlg("IMPONIBILE")) != -1)
  	m.set(dlg, s.imponibile);	 

  // set percentuale ritenuta
	if ((dlg = token_dlg("PERC")) != -1)
  	m.set(dlg, s.perc);	 

  // set ritenuta
	if ((dlg = token_dlg("RITENUTA")) != -1)
  	m.set(dlg, s.ritenuta);	 

  // set compenso
	if ((dlg = token_dlg("COMPENSO")) != -1)
  	m.set(dlg, s.compenso);	 

  // set compenso netto
	if ((dlg = token_dlg("NETTO")) != -1)
  	m.set(dlg, s.netto);

  // set spesa
	if ((dlg = token_dlg("SPESA")) != -1)
  	m.set(dlg, s.spesa);	 

  // set contr.10% percipiente
	if ((dlg = token_dlg("CTSSNPERC")) != -1)
  	m.set(dlg, s.ctssnperc);	 

  // set contr.10% complessivo
	if ((dlg = token_dlg("CTSSNCOMP")) != -1)
  	m.set(dlg, s.ctssncomp);	 

  // set ritenuta lorda
	if ((dlg = token_dlg("RITLORDA")) != -1)
  	m.set(dlg, s.ritlorda);	 

  // set contributi obbligatori
	if ((dlg = token_dlg("CONTROBB")) != -1)
  	m.set(dlg, s.controbb);	 

  // set detrazioni famigliari
	if ((dlg = token_dlg("DETFAMIL")) != -1)
  	m.set(dlg, s.detfamil);	 

  // set detrazioni lavoro dipendente
	if ((dlg = token_dlg("DETLAVDIP")) != -1)
  	m.set(dlg, s.detlavdip);	 

  // set totale detrazioni
	if ((dlg = token_dlg("TOTDET")) != -1)
  	m.set(dlg, s.totdet);	 

  // set giorni lavoro dipendente
	if ((dlg = token_dlg("GIOLAVDIP")) != -1)
  	m.set(dlg, s.giolavdip);	 

  // set importo CPA
	if ((dlg = token_dlg("IMPCPA")) != -1)
  	m.set(dlg, s.impcpa);	 

  // set somme regime convenzionale
	if ((dlg = token_dlg("SOMREGCONV")) != -1)
  	m.set(dlg, s.somregconv);	 

  // set percentuale contributo 10%
	if ((dlg = token_dlg("ALQIMP10")) != -1)
  	m.set(dlg, s.alqimp10);	 

  // set codice contributo 10%
	if ((dlg = token_dlg("COD10")) != -1)
  	m.set(dlg, s.cod10);	 

  // set utili pagati
	if ((dlg = token_dlg("UTPAGATI")) != -1)
  	m.set(dlg, s.utpagati);	 

  // set utili spettanti
	if ((dlg = token_dlg("UTSPETT")) != -1)
  	m.set(dlg, s.utspett);	 

  // set ritenuta utili pagati
	if ((dlg = token_dlg("RITUTPAG")) != -1)
  	m.set(dlg, s.ritutpag);	 

  // set ritenuta utili spettanti
	if ((dlg = token_dlg("RITUTSPE")) != -1)
  	m.set(dlg, s.ritutspe);	 

  // set numero quote
	if ((dlg = token_dlg("NQUOTE")) != -1)
  	m.set(dlg, s.nquote);	 
  
  // set somme non sogg.ritenuta
	if ((dlg = token_dlg("SOMNSRIT")) != -1)
  	m.set(dlg, s.somnsrit);	 

  // set ammontare lordo
	if ((dlg = token_dlg("AMMLORDO")) != -1)
  	m.set(dlg, s.ammlordo);	 

  // set quota provvigioni
	if ((dlg = token_dlg("QUOTAPROV")) != -1)
  	m.set(dlg, s.quotaprov);	 

  // set imponibile al netto ritenute
	if ((dlg = token_dlg("IMPNETTO")) != -1)
  	m.set(dlg, s.impnetto);	 

  // set compenso al netto ritenute
	if ((dlg = token_dlg("COMNETTO")) != -1)
  	m.set(dlg, s.comnetto);               
  	
  // set numero versamento collegato	    
  if ((dlg = token_dlg("NUMVERS")) != -1)
  	m.set(dlg, s.numvers);               	
}                                                                           

Pag_struct& TSchedaPercipienti::clear_struct(Pag_struct& s)
{
	s.datapag = NULLDATE;
	s.imponibile = ZERO;
	s.perc = ZERO;
	s.ritenuta = ZERO;
	s.compenso = ZERO;
	s.netto = ZERO;
	s.numvers = -1L;
	s.spesa = ZERO;
	s.ctssnperc = ZERO;
	s.ctssncomp = ZERO;
	s.ritlorda = ZERO;
	s.controbb = ZERO;  
	s.detfamil = ZERO;
	s.detlavdip = ZERO;
	s.totdet = ZERO;
	s.giolavdip = 0;
	s.impcpa = ZERO;  
	s.somregconv = ZERO;   
	s.alqimp10 = ZERO;   
	s.cod10 = "";
	s.utpagati = ZERO;  
	s.utspett = ZERO;   
	s.ritutpag = ZERO;    
	s.ritutspe = ZERO;    
	s.nquote = ZERO;   
	s.somnsrit = ZERO;
	s.ammlordo = ZERO;  
	s.quotaprov = ZERO;   
	s.impnetto = ZERO;  
	s.comnetto = ZERO;        
  
	return s;
}    

Pag_struct& TSchedaPercipienti::calcola_riga_pag(Pag_struct& s,
																								 Pag_struct& c,
																								 bool force,
    																						 const real h_PercAssImp,
  																							 const real h_PercCassaPrev,
  																							 const real h_PercRitenuta,
  																							 const real h_PercInps,
  																							 const real h_PercAssImpInps,
  																							 const real h_PercCommitInps)
{

	// azzera struttura di valori calcolati
	clear_struct(c);
    
  // calcolo CPA
  c.impcpa = (s.compenso * h_PercCassaPrev) / (100.00 + h_PercCassaPrev);
  c.impcpa.round();
  if (s.impcpa == ZERO || force)
  	s.impcpa = c.impcpa; 
    
  // calcolo imponibile
  c.imponibile = ((s.compenso - s.impcpa) * h_PercAssImp) / 100.00;
  c.imponibile.round();
  if (s.imponibile == ZERO || force)
  	s.imponibile = c.imponibile;                                 
    	
  // percentuale ritenuta acconto
  if (s.perc == ZERO || force)
  	s.perc = h_PercRitenuta;	                                   
    	
  // calcolo ritenuta lorda
  c.ritlorda = (s.imponibile * s.perc) / 100.00;
  c.ritlorda.round();
  s.ritlorda = c.ritlorda; 
    
  // calcolo totale detrazioni
  c.totdet = s.detfamil + s.detlavdip;  
  if (abs(c.totdet) > abs(s.ritlorda))
  	c.totdet = s.ritlorda;
  s.totdet = c.totdet;        
    
  // calcolo ritenuta
  c.ritenuta = s.ritlorda - s.totdet;                            
  if (s.ritenuta == ZERO || force)
  	s.ritenuta = c.ritenuta;     
    	
  // percentuale assoggettamento Inps
  if (s.alqimp10 == ZERO || force)
  	s.alqimp10 = h_PercAssImpInps;
    	
  // calcolo contributo Inps complessivo
  c.ctssncomp = (((s.compenso * s.alqimp10) / 100.00) * h_PercInps) / 100.00;
  c.ctssncomp.round();
  if (s.ctssncomp == ZERO || force)
  	s.ctssncomp = c.ctssncomp; 
    
	// calcolo contributo Inps del percipiente
	if (h_PercCommitInps == ZERO)
		c.ctssnperc = s.ctssncomp - ((s.ctssncomp * 2) / 3); 
 	else
  	c.ctssnperc = s.ctssncomp - ((s.ctssncomp * h_PercCommitInps) / 100.00);	    		   	
  c.ctssnperc.round();
  if (s.ctssnperc == ZERO || force)
  	s.ctssnperc = c.ctssnperc; 
    	
  // calcolo utili pagati
  if (abs(s.utpagati) > abs(s.imponibile))
  	s.utpagati = s.imponibile;	                        
    	
  // calcolo ritenute utili pagati
  c.ritutpag = (s.utpagati * s.perc) / 100.00;
  c.ritutpag.round();
  if (s.ritutpag == ZERO || force)
  	s.ritutpag = c.ritutpag;    
  if (abs(s.ritutpag) > abs(s.ritenuta))
  	s.ritutpag = s.ritenuta;		
    	
  // calcolo utili spettanti
  s.utspett = s.imponibile - s.utpagati;	
    
  // calcolo ritenute utili spettanti
  s.ritutspe = s.ritenuta - s.ritutpag;	
    
  // calcolo compenso netto
  s.netto = s.compenso + s.spesa - s.ritenuta - s.ctssnperc;	    
    
  // calcolo somme non soggette a ritenuta
  s.somnsrit = s.compenso - s.imponibile + s.spesa - s.impcpa - s.somregconv; 
    
  // calcolo ammontare lordo
  s.ammlordo = s.imponibile + s.somnsrit + s.controbb + s.somregconv;
    
  // calcolo quota provvigioni
  s.quotaprov = s.somnsrit - s.spesa;
    
  // calcolo imponibile al netto delle ritenute
  s.impnetto = s.imponibile - s.ritenuta;      
    
  // calcolo compenso al netto delle ritenute
  s.comnetto = s.compenso - s.ritenuta;    
  
  return s;
}

TSheet_field& TSchedaPercipienti::enable_pag_sheet(TMask& m, TString16& quadro) const
{
  TSheet_field* s = NULL;
  
  TSheet_field& s_C = (TSheet_field&)m.field(F_PAGAMENTI_C);
	if (quadro == "C") 
	{
		s_C.show();
		s = &s_C;
	}	 
	else s_C.hide();   
	
	TSheet_field& s_D = (TSheet_field&)m.field(F_PAGAMENTI_D);
	if (quadro == "D" || quadro == "D1" || quadro == "E" || quadro == "E1")
	{
		s_D.show();
		s = &s_D;
	}	 
	else s_D.hide(); 
	
	TSheet_field& s_DB = (TSheet_field&)m.field(F_PAGAMENTI_DB);
	if (quadro == "DB")
	{
		s_DB.show();
		s = &s_DB;
	}	 
	else s_DB.hide(); 
	
	TSheet_field& s_G = (TSheet_field&)m.field(F_PAGAMENTI_G);
	if (quadro == "G")
	{
		s_G.show();
		s = &s_G;
	}	 
	else s_G.hide();    
	
	// abilito sheet di default nel caso il quadro non fosse uno dei previsti
	if (s == NULL)
	{
		s_C.show();
		s = &s_C;
	}	 	
	
	return *s;
}		         

void TSchedaPercipienti::set_pag_handler(TSheet_field& s) const
{
	// aggancio handler notify dei pagamenti
  s.set_notify(pags_notify);
                                                                       
  // aggancio handler data pagamento
  int dlg = token_dlg("DATAPAG");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);                                                                     
  // aggancio handler imponibile
  dlg = token_dlg("IMPONIBILE");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler percentuale ritenuta
  dlg = token_dlg("PERC");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);  
  // aggancio handler ritenuta
  dlg = token_dlg("RITENUTA");  
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler compensi
  dlg = token_dlg("COMPENSO");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler spesa
  dlg = token_dlg("SPESA");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler); 
  // aggancio handler contributo Inps percipiente
  dlg = token_dlg("CTSSNPERC");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler); 
  // aggancio handler contributo Inps complessivo
  dlg = token_dlg("CTSSNCOMP");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler contributi obbligatori
  dlg = token_dlg("CONTROBB");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler detrazioni familiari a carico
  dlg = token_dlg("DETFAMIL");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler contributo Inps complessivo
  dlg = token_dlg("DETLAVDIP");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler CPA
  dlg = token_dlg("IMPCPA");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler contributo Inps complessivo
  dlg = token_dlg("SOMREGCONV");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler percentuale assogg.imponibile Inps
  dlg = token_dlg("ALQIMP10");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler utili pagati
  dlg = token_dlg("UTPAGATI");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  // aggancio handler ritenute utili pagati
  dlg = token_dlg("RITUTPAG");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler); 
  // aggancio handler numero quote
  dlg = token_dlg("NQUOTE");
  if (dlg != -1) s.sheet_mask().set_handler(dlg, pag_standard_handler);
  
  // aggancio handler button azzera
  s.sheet_mask().set_handler(DLG_AZZERAPAG, pag_azzera);    
}

void TSchedaPercipienti::build_causqua_items(TMask& m, TString16& quadro) const
{	
	// reference al campo causale quadro
	TEdit_field& f_causqua = m.efield(F_CAUSQUA);
	// refernce allo sheet del campo causale quadro
	TString_array& Items = f_causqua.sheet()->rows_array();  
	// rimuovo tutti gli items
	Items.destroy();
	// genero i nuovi items
	if (quadro == "C")
		for (int i=0; i<NUM_ITEMS_C; i++)
			Items.add(ITEMS_C[i]);
	if (quadro == "D")
		for (int i=0; i<NUM_ITEMS_D; i++)
			Items.add(ITEMS_D[i]);		
	if (quadro == "DB")
		for (int i=0; i<NUM_ITEMS_DB; i++)
			Items.add(ITEMS_DB[i]);		
	if (quadro == "D1")
		for (int i=0; i<NUM_ITEMS_D1; i++)
			Items.add(ITEMS_D1[i]);		
	if (quadro == "E")
		for (int i=0; i<NUM_ITEMS_E; i++)
			Items.add(ITEMS_E[i]);
	if (quadro == "E1")
		for (int i=0; i<NUM_ITEMS_E1; i++)
			Items.add(ITEMS_E1[i]);
	if (quadro == "G")
		for (int i=0; i<NUM_ITEMS_G; i++)
			Items.add(ITEMS_G[i]);  
}		         


int SchedaPerc (int argc, char* argv[])
{
  TSchedaPercipienti a;
  a.run(argc, argv, "Scheda Percipienti");
  return 0;
}