// Description:
// 	Azzeramento archivi        
//                                 
// Usage:
// 	774 -2 S (livello di studio)          
// 	774 -2 D (livello di ditta)  

// Author:
//	L.A.

#include <relapp.h>
#include <progind.h>
#include <urldefid.h> 
#include <execp.h> 
#include <prefix.h>   
#include <form.h>   
#include "774200.h"
#include "77lib.h" 
#include "resetfil.h"
#include "scandich.h"
#include "774300a.h"

// definizione campi del form 
#define HODD_ANNODIC		1 
#define FODD_TODAY			2 
#define FODD_USER				3


// derivazione della classe TArray_sheet per implementare
// la funzione membro on_key() in modo che gestisca eventuali 
// bottoni aggiunti dall'utente
class TArray_sheetDerived : public TArray_sheet  
{ 

public:
	// @cmember Gestisce la pressione del tasto (vedi <mf TWindow::on_key>)
  virtual bool on_key(KEY);
	// @cmember Costruttore
  TArray_sheetDerived(short x, short y, short dx, short dy, const char* caption, const char* head, byte buttons = 0):
  TArray_sheet(x, y, dx, dy, caption, head, buttons){};
	// @cmember Distruttore
  virtual ~TArray_sheetDerived(){};
};

class TAzzeramento_archivi : public TRelation_application
{   
  private: 
    char	_liv;
    long 	_curditta;
    int		_anno_dich;
    	
    TMask* _msk;
    TRelation* _rel;
    TConfig* _cnf_studio;  
    TRiporti* _riporti;   
    TIsamtempfile* _logschede;
    
    // elenco campi da riportare
    real _mem_ECCRIT23_BASEBIS;
    
		// elenco file da azzerare
		TResetfile* _reset_BASE;
		TResetfile* _reset_BASEBIS; 
		TResetfile* _reset_SOCTRASF;            
		TResetfile* _reset_PERC;
		TResetfile* _reset_SCPERC; 
    TResetfile* _reset_RVER; 
		TResetfile* _reset_RPAG;
		TResetfile* _reset_DIPEND;                                
		TResetfile* _reset_QUAA;
		TResetfile* _reset_QUAA1;                
		TResetfile* _reset_QUAA2;                
		TResetfile* _reset_QUAA3;                
		TResetfile* _reset_QUAB;                 
		TResetfile* _reset_QUAB1;                
		TResetfile* _reset_QUAC;                 
		TResetfile* _reset_QUAD;                 
		TResetfile* _reset_QUAD1;                
		TResetfile* _reset_QUAE;                 
		TResetfile* _reset_QUAE1;                
		TResetfile* _reset_QUAE2;                
		TResetfile* _reset_PROSPE1;              
		TResetfile* _reset_QUAF;                 
		TResetfile* _reset_RIGHEF;               
		TResetfile* _reset_QUAF1;                
		TResetfile* _reset_RIGHEF1;              
		TResetfile* _reset_QUAF2;                
		TResetfile* _reset_RIGHEF2;             
		TResetfile* _reset_QUAG;                 
		TResetfile* _reset_QUAGD;
		TResetfile* _reset_QUAG1;                
		TResetfile* _reset_QUAH;                 
		TResetfile* _reset_DETH;                 
		TResetfile* _reset_QUAL;                 
		TResetfile* _reset_QUAN;                 
		TResetfile* _reset_QUAP;                 
		TResetfile* _reset_QUAQ;                 
		TResetfile* _reset_QUAR;                 
		TResetfile* _reset_QUAS;                 
		TResetfile* _reset_QUAT;                 

    // elenco di VALIDATE_RECORD function                 
    static bool validate_record_SCPERC(const TRectype& rec);  
    static bool validate_record_SCPERC_2(const TRectype& rec); 
    static bool validate_record_RPAG(const TRectype& rec);
    static bool validate_record_RVER(const TRectype& rec);
    static bool validate_record_QUAL(const TRectype& rec);
    static bool validate_record_DETH(const TRectype& rec);
    
    // elenco di VALIDATE_FIELD function
    static bool validate_field_BASE(const TRectype& rec, const TString& fld); 
    static bool validate_field_BASEBIS(const TRectype& rec, const TString& fld); 
    
    // elenco di BEFORE_RESET function
    static void before_reset_BASEBIS(TRectype& rec);
    
    // elenco di AFTER_RESET function        
    static void after_reset_BASEBIS(TRectype& rec);
    
  	// validazione e azioni su schede percipienti
  	bool is_resetable(const TRectype& rec);
  	
    // handler di campi                                    
    static bool F_ANNODIC_hnd(TMask_field& f, KEY key);     
    static bool F_AZZSCH_hnd(TMask_field& f, KEY key);     
    static bool F_AZZQUA_hnd(TMask_field& f, KEY key);
    
  	// creazione/distruzione istanze d'azzeramento
  	void azzera_create(const bool azzsch, const bool azzqua);
  	void azzera_destroy(const bool azzsch, const bool azzqua);
  	
  	// gestione del log delle schede percipienti
  	void handle_log();                          
  	
  	// stampa del log delle schede percipienti
  	void print_log();
  	                                          
  	// azzera schede loggate selezionate
  	void azzera_schlog();
  	                                          
  	// message box di conferma azzeramento
  	bool conferma_azzera(const TMask& m, const bool azzsch, const bool azzqua);
  	
  	// elaborazioni previste
  	void elab_tutte(const bool azzsch, const bool azzqua);
  	void elab_selezionate(const bool azzsch, const bool azzqua);
  	void elab_manutenzione(const bool azzsch, const bool azzqua){}
  
  protected:
  	virtual bool user_create();
    virtual bool user_destroy();
    virtual TRelation* get_relation() const { return _rel; }
    virtual TMask* get_mask(int mode) { return _msk; }
    virtual bool changing_mask(int mode) { return FALSE; }
    virtual void init_modify_mode(TMask&); 
    virtual int rewrite(const TMask& m);
    virtual int write(const TMask& m);
    virtual bool firm_change_enabled() const; 
    virtual bool save_and_new() const;
    
  public:
    TAzzeramento_archivi(char livello) : _liv(toupper(livello)) {}
    ~TAzzeramento_archivi() {}
};

// riferimento all'istanza dell'applicazione 
TAzzeramento_archivi& app() { return (TAzzeramento_archivi&)main_app(); }

// implementazione per gestire eventuali bottoni aggiunti dall'utente 
bool TArray_sheetDerived::on_key(KEY key)
{                                         
	// verifico se premuto un bottone utente
  switch(key)
  {
  // ignorato perch� non restituisce se stesso  
  case K_CTRL+'N':
    break;

  default:             
    // verifico altri bottoni non previsti dallo sheet standard
	  if (key > K_CTRL)
	  { 
	  	for (int i = fields()-1; i >= 0; i--)
	   	{
	    	TMask_field& f = fld(i);
	     	if (f.active() && f.is_kind_of(CLASS_BUTTON_FIELD))
	     	{
	      	TButton_field& b = (TButton_field&)f;
	      	if (b.virtual_key() == key)
	      	{	
	       		stop_run(key);
	         	return TRUE;
	       	}
	     	}
	   	}
	  }
    break;
  }  
  
  // richiamo on_key base
  return TArray_sheet::on_key(key);
}

// redifinizione del metodo della TRelation_application
// per avere sempre disattivata la possibilit� di scegliere la ditta
bool TAzzeramento_archivi::firm_change_enabled() const
{
  return FALSE;
}  

// redifinizione del metodo della TRelation_application
// per attivare la modalit� save_and_new (altrimenti disattivata)
bool TAzzeramento_archivi::save_and_new() const
{ return TRUE; }

bool TAzzeramento_archivi::user_create()
{ 
  // istanza membri oggetto
  _msk						= new TMask("774300a");
  _rel 						= new TRelation(LF_STAZZ);
  _cnf_studio 		= new TConfig(CONFIG_STUDIO,"77");
  _riporti 				= new TRiporti;    
  
  // inizilizzazione anno dichiarazioni
  _anno_dich = _cnf_studio->get_int(ANNO_SEL);
  
  // inizializzazione istanza file temporaneo di log
	_logschede = NULL;
	                                         
  // inizializzazione istanze d'azzeramento
	_reset_PERC 		= NULL;
	_reset_SCPERC 	= NULL;
	_reset_RVER 		= NULL;
	_reset_RPAG 		= NULL;
	_reset_BASE 		=	NULL;
	_reset_BASEBIS 	= NULL;
	_reset_SOCTRASF = NULL;
	_reset_DIPEND 	= NULL;
	_reset_QUAA 		= NULL;
	_reset_QUAA1 		= NULL;
	_reset_QUAA2 		= NULL;
	_reset_QUAA3 		= NULL;
	_reset_QUAB 		= NULL;
	_reset_QUAB1 		= NULL;
	_reset_QUAC			= NULL;
	_reset_QUAD			= NULL;
	_reset_QUAD1		= NULL;
	_reset_QUAE			= NULL;
	_reset_QUAE1		= NULL;
	_reset_QUAE2		= NULL;
	_reset_PROSPE1	= NULL;
	_reset_QUAF			= NULL;
	_reset_RIGHEF		= NULL;
	_reset_QUAF1		= NULL;
	_reset_RIGHEF1	= NULL;
	_reset_QUAF2		= NULL;
	_reset_RIGHEF2	= NULL;
	_reset_QUAG			= NULL;
	_reset_QUAGD		= NULL;
	_reset_QUAG1		= NULL;
	_reset_QUAH			= NULL;
	_reset_DETH			= NULL;
	_reset_QUAL			= NULL;
	_reset_QUAN			= NULL;
	_reset_QUAP			= NULL;
	_reset_QUAQ			= NULL;
	_reset_QUAR			= NULL;
	_reset_QUAS			= NULL;
	_reset_QUAT			= NULL;
  
  // attivazione handler campi               
  _msk->set_handler(F_ANNODIC,F_ANNODIC_hnd);  
  _msk->set_handler(F_AZZSCH,F_AZZSCH_hnd);  
  _msk->set_handler(F_AZZQUA,F_AZZQUA_hnd);
  
  // disattivazione bottoni non utilizzabili
  _msk->disable(DLG_DELREC);  

  return TRUE;
}

bool TAzzeramento_archivi::user_destroy()
{                    
  delete _msk;
	delete _rel;
	delete _cnf_studio;     
	delete _riporti;     
	                                        
	// distruzione istanza file temporaneo di log
	if (_logschede) delete _logschede;
	                                        
	// distruzione istanze d'azzeramento
	if (_reset_PERC) 		 delete _reset_PERC; 
	if (_reset_SCPERC) 	 delete _reset_SCPERC;
	if (_reset_RVER) 		 delete _reset_RVER;
  if (_reset_RPAG)		 delete _reset_RPAG;
  if (_reset_BASE)		 delete _reset_BASE;  
	if (_reset_BASEBIS)	 delete _reset_BASEBIS; 
	if (_reset_SOCTRASF) delete _reset_SOCTRASF;
	if (_reset_DIPEND)	 delete _reset_DIPEND;
	if (_reset_QUAA)		 delete _reset_QUAA; 
	if (_reset_QUAA1)		 delete _reset_QUAA1;
	if (_reset_QUAA2)		 delete _reset_QUAA2;
	if (_reset_QUAA3)		 delete _reset_QUAA3;
	if (_reset_QUAB)		 delete _reset_QUAB; 
	if (_reset_QUAB1)		 delete _reset_QUAB1;
	if (_reset_QUAC)		 delete _reset_QUAC;
	if (_reset_QUAD)		 delete _reset_QUAD;
	if (_reset_QUAD1)		 delete _reset_QUAD1;
	if (_reset_QUAE)		 delete _reset_QUAE;
	if (_reset_QUAE1)		 delete _reset_QUAE1;
	if (_reset_QUAE2)		 delete _reset_QUAE2; 
	if (_reset_PROSPE1)	 delete _reset_PROSPE1; 
	if (_reset_QUAF)		 delete _reset_QUAF; 
	if (_reset_RIGHEF)	 delete _reset_RIGHEF;
	if (_reset_QUAF1)		 delete _reset_QUAF1; 
	if (_reset_RIGHEF1)	 delete _reset_RIGHEF1; 
	if (_reset_QUAF2)		 delete _reset_QUAF2; 
	if (_reset_RIGHEF2)	 delete _reset_RIGHEF2;
	if (_reset_QUAG)		 delete _reset_QUAG; 
	if (_reset_QUAGD)		 delete _reset_QUAGD;
	if (_reset_QUAG1)		 delete _reset_QUAG1;
	if (_reset_QUAH)		 delete _reset_QUAH;
	if (_reset_DETH)		 delete _reset_DETH;
	if (_reset_QUAL)		 delete _reset_QUAL;
	if (_reset_QUAN)		 delete _reset_QUAN;
	if (_reset_QUAP)		 delete _reset_QUAP;
	if (_reset_QUAQ)		 delete _reset_QUAQ;
	if (_reset_QUAR)		 delete _reset_QUAR;
	if (_reset_QUAS)		 delete _reset_QUAS;
	if (_reset_QUAT)		 delete _reset_QUAT;
	
  return TRUE;  
}

// creazione istanze d'azzeramento
void TAzzeramento_archivi::azzera_create(const bool azzsch, const bool azzqua)
{
  // richiesto azzeramento schede percipienti
	if (azzsch)
	{
  	_reset_PERC 		= new	TResetfile(LF_PERC);
		_reset_SCPERC 	= new	TResetfile(LF_SCPERC,TRUE); 
  	_reset_RVER 		= new TResetfile(LF_RVER,TRUE); 
		_reset_RPAG 		= new	TResetfile(LF_RPAG,TRUE);
  }
  
  // richiesto azzeramento quadri
	if (azzqua)
	{
  	_reset_BASE 		=	new TResetfile(LF_BASE);
		_reset_BASEBIS 	= new TResetfile(LF_BASEBIS); 
		_reset_SOCTRASF = new	TResetfile(LF_SOCTRASF,TRUE);
		_reset_DIPEND 	= new TResetfile(LF_DIPEND);                                
		_reset_QUAA 		= new	TResetfile(LF_QUAA,TRUE);
		_reset_QUAA1 		= new TResetfile(LF_QUAA1,TRUE);                
		_reset_QUAA2 		= new TResetfile(LF_QUAA2,TRUE);                
		_reset_QUAA3 		= new TResetfile(LF_QUAA3,TRUE);                
		_reset_QUAB 		= new	TResetfile(LF_QUAB,TRUE);                 
		_reset_QUAB1 		= new TResetfile(LF_QUAB1,TRUE);                
		_reset_QUAC			= new	TResetfile(LF_QUAC,TRUE);                 
		_reset_QUAD			= new	TResetfile(LF_QUAD,TRUE);                 
		_reset_QUAD1		= new	TResetfile(LF_QUAD1,TRUE);                
		_reset_QUAE			= new	TResetfile(LF_QUAE,TRUE);                 
		_reset_QUAE1		= new	TResetfile(LF_QUAE1,TRUE);                
		_reset_QUAE2		= new TResetfile(LF_QUAE2,TRUE);                
		_reset_PROSPE1	= new	TResetfile(LF_PROSPE1,TRUE);              
		_reset_QUAF			= new	TResetfile(LF_QUAF,TRUE);                 
		_reset_RIGHEF		= new	TResetfile(LF_RIGHEF,TRUE);               
		_reset_QUAF1		= new	TResetfile(LF_QUAF1,TRUE);                
		_reset_RIGHEF1	= new	TResetfile(LF_RIGHEF1,TRUE);              
		_reset_QUAF2		= new	TResetfile(LF_QUAF2,TRUE);                
		_reset_RIGHEF2	= new	TResetfile(LF_RIGHEF2,TRUE);             
		_reset_QUAG			= new	TResetfile(LF_QUAG,TRUE);                 
		_reset_QUAGD		= new	TResetfile(LF_QUAGD,TRUE);
		_reset_QUAG1		= new	TResetfile(LF_QUAG1,TRUE);                
		_reset_QUAH			= new	TResetfile(LF_QUAH,TRUE);                 
		_reset_DETH			= new	TResetfile(LF_DETH,TRUE);                 
		_reset_QUAL			= new	TResetfile(LF_QUAL,TRUE);                 
		_reset_QUAN			= new	TResetfile(LF_QUAN,TRUE);                 
		_reset_QUAP			= new	TResetfile(LF_QUAP,TRUE);                 
		_reset_QUAQ			= new	TResetfile(LF_QUAQ,TRUE);                 
		_reset_QUAR			= new	TResetfile(LF_QUAR,TRUE);                 
		_reset_QUAS			= new	TResetfile(LF_QUAS,TRUE);                 
		_reset_QUAT			= new	TResetfile(LF_QUAT,TRUE);
	}
}
                                          
// distruzione istanze d'azzeramento
void TAzzeramento_archivi::azzera_destroy(const bool azzsch, const bool azzqua)
{
	// richiesto azzeramento schede percipienti
	if (azzsch)
	{
		delete _reset_PERC;
	  delete _reset_SCPERC;
  	delete _reset_RVER;
		delete _reset_RPAG;  
    _reset_PERC 	= NULL;
		_reset_SCPERC = NULL;
		_reset_RVER 	= NULL;
		_reset_RPAG 	= NULL;
	}	
	                                           
	// richiesto azzeramento quadri
	if (azzqua)
	{
		delete _reset_BASE;
		delete _reset_BASEBIS;
		delete _reset_SOCTRASF;            
		delete _reset_DIPEND;
		delete _reset_QUAA;
		delete _reset_QUAA1;
		delete _reset_QUAA2;
		delete _reset_QUAA3;
		delete _reset_QUAB;
		delete _reset_QUAB1;
		delete _reset_QUAC;
		delete _reset_QUAD;
		delete _reset_QUAD1;
		delete _reset_QUAE;
		delete _reset_QUAE1;
		delete _reset_QUAE2;
		delete _reset_PROSPE1;
		delete _reset_QUAF;
		delete _reset_RIGHEF;
		delete _reset_QUAF1;
		delete _reset_RIGHEF1;
		delete _reset_QUAF2;
		delete _reset_RIGHEF2;
		delete _reset_QUAG;
		delete _reset_QUAGD;
		delete _reset_QUAG1;
		delete _reset_QUAH;
		delete _reset_DETH;
		delete _reset_QUAL;
		delete _reset_QUAN;
		delete _reset_QUAP;
		delete _reset_QUAQ;
		delete _reset_QUAR;
		delete _reset_QUAS;
		delete _reset_QUAT;  
		_reset_BASE 		=	NULL;
		_reset_BASEBIS 	= NULL;
		_reset_SOCTRASF = NULL;
		_reset_DIPEND 	= NULL;
		_reset_QUAA 		= NULL;
		_reset_QUAA1 		= NULL;
		_reset_QUAA2 		= NULL;
		_reset_QUAA3 		= NULL;
		_reset_QUAB 		= NULL;
		_reset_QUAB1 		= NULL;
		_reset_QUAC			= NULL;
		_reset_QUAD			= NULL;
		_reset_QUAD1		= NULL;
		_reset_QUAE			= NULL;
		_reset_QUAE1		= NULL;
		_reset_QUAE2		= NULL;
		_reset_PROSPE1	= NULL;
		_reset_QUAF			= NULL;
		_reset_RIGHEF		= NULL;
		_reset_QUAF1		= NULL;
		_reset_RIGHEF1	= NULL;
		_reset_QUAF2		= NULL;
		_reset_RIGHEF2	= NULL;
		_reset_QUAG			= NULL;
		_reset_QUAGD		= NULL;
		_reset_QUAG1		= NULL;
		_reset_QUAH			= NULL;
		_reset_DETH			= NULL;
		_reset_QUAL			= NULL;
		_reset_QUAN			= NULL;
		_reset_QUAP			= NULL;
		_reset_QUAQ			= NULL;
		_reset_QUAR			= NULL;
		_reset_QUAS			= NULL;
		_reset_QUAT			= NULL;
	}	
}
                                          
// gestione del log delle schede percipienti
void TAzzeramento_archivi::handle_log()
{	
	// creazione sheet 
	TString caption = "Schede percipienti insolute";
	TString head = "@1|";
	head << "Ditta@5@R|";
	head << "Tipo|";
	head << "Codice@R|";
	head << "Scheda@R|";
	head << "Data doc.@10@R|";
	head << "Num.doc.|";
	head << "Cau.|";
	head << "Totale doc.@15@R|";
	head << "Compenso@15@R|";
	head << "Spese@15@R|";
	head << "Iva@15@R";
	TArray_sheetDerived log_sheet(12, 3, 66, 20, caption, head);
	log_sheet.add_button(DLG_PRINT, "~Stampa", K_CTRL+'S');
	
	// tasto di ritorno dall'esecuzione dello sheet
	KEY retkey;
	
	// delimitatore di scope per l'apertura fittizia di LF_SCPERC (che palle!) 
	{
	// apertura file fisico originale perch� altrimenti da "erore!"
	TLocalisamfile f(LF_SCPERC);
	
	// riempimento sheet
		for (int err = _logschede->first(); err == NOERR; err = _logschede->next()) 
		{
	    TToken_string row;
	    row.add(" ");
	    row.add(_logschede->get_long("CODDITTA")); 
	    row.add(_logschede->get_char("TIPOA"));
	    row.add(_logschede->get_long("CODANAGR"));
	    row.add(_logschede->get_long("NPROG"));
	    row.add(_logschede->get_date("DATADOC"));
	    row.add(_logschede->get("NUMDOC"));
	    row.add(_logschede->get_int("CODCAUS")); 
	    row.add(_logschede->get("TOTALE"));
	    row.add(_logschede->get("COMPENSO"));
	    row.add(_logschede->get("SPESE"));
	    row.add(_logschede->get("IVA"));
	    log_sheet.add(row);
	  }
  
	  // esecuzione sheet
	  log_sheet.enable_check();
	  retkey = log_sheet.run();
	  
	  // rimozione dei record non selezionati dal file temporaneo
		if (retkey == K_ENTER && log_sheet.one_checked())
			for (int i = 0; i < log_sheet.items(); i++)
			{
				if (!log_sheet.checked(i))
				{
				  _logschede->setkey(1);
		  		_logschede->zero();
		  		_logschede->put("CODDITTA",log_sheet.row(i).get_long(1));
		  		_logschede->put("TIPOA",log_sheet.row(i).get_char(2));
		  		_logschede->put("CODANAGR",log_sheet.row(i).get_long(3)); 
		  		_logschede->put("NPROG",log_sheet.row(i).get_int(4));
				  if (_logschede->read() == NOERR)
						_logschede->remove();
				}
			}	               
	}
		
  // interpreto azione restituita
  switch (retkey)
  {
  	case K_CTRL+'S':
  		print_log(); 
  		// inizilizzazione puntatore all'istanza del file di log
			// perche' il distruttore della relazione usata in stampa 
			// ne ha effettuato implicitamente la "delete"
  		_logschede = NULL;
  	  break;
  	case K_ENTER:
  		if (log_sheet.one_checked())
  			azzera_schlog();
  		break;
  	default:
  		break;	
  }
}

// stampa del log delle schede percipienti
void TAzzeramento_archivi::print_log()
{
	// istanza form
	TForm log_form("77logazz");
  // sostituisce lfile originale con lfile di log
  log_form.relation()->replace(_logschede);
	// apertura file fisico originale perch� altrimenti da "erore!"
	TLocalisamfile f(LF_SCPERC);
	// set anno dichiarazione
	TForm_item& hodd_annodic = log_form.find_field('H',odd_page,HODD_ANNODIC);	
	hodd_annodic.set(_msk->get(F_ANNODIC));
	// set footer standard prassi
	TForm_item& fodd_today = log_form.find_field('F',odd_page,FODD_TODAY);	
	TForm_item& fodd_user  = log_form.find_field('F',odd_page,FODD_USER);	
	fodd_today.set(_msk->get(F_DATASCH)); 
	fodd_user.set(user());
	// stampa form
	log_form.print();
}                                         

// azzera le schede loggate selezionate
void TAzzeramento_archivi::azzera_schlog()
{	
	// azzeramento schede selezionate (non invertire l'ordine di chiamata!!)
	_reset_SCPERC->set_validate_record_function(validate_record_SCPERC_2);  
  _reset_RPAG->set_validate_record_function(validate_record_RPAG); 
  _reset_RVER->set_validate_record_function(validate_record_RVER); 
  _reset_SCPERC->run(); 
  _reset_RPAG->run(); 
  _reset_RVER->run();	
}

// elabora tutte le dichiarazioni
void TAzzeramento_archivi::elab_tutte(const bool azzsch, const bool azzqua)
{ 
  // creazione istanze d'azzeramento
  azzera_create(azzsch, azzqua);
  
  // richiesto azzeramento schede percipienti
  if (azzsch)
  {
    // istanza file temporaneo di log
  	if (_logschede) delete _logschede;
  	_logschede = new TIsamtempfile(LF_SCPERC,"LOGAZZ",TRUE);
  	
  	// percipienti
  	_reset_PERC->run();
  
  	// schede percipienti (non invertire l'ordine di chiamata!!)                                           
  	_reset_SCPERC->set_validate_record_function(validate_record_SCPERC);  
  	_reset_RPAG->set_validate_record_function(validate_record_RPAG); 
  	_reset_RVER->set_validate_record_function(validate_record_RVER); 
  	_reset_SCPERC->run(); 
  	_reset_RPAG->run(); 
  	_reset_RVER->run();
  }	
  
  // richiesto azzeramento quadri
  if (azzqua)
  {
  	// quadro BASE e BASEBIS
  	_reset_BASE->set_validate_field_function(validate_field_BASE); 
  	_reset_BASEBIS->set_validate_field_function(validate_field_BASEBIS); 
  	_reset_BASEBIS->set_before_reset_function(before_reset_BASEBIS); 
  	_reset_BASEBIS->set_after_reset_function(after_reset_BASEBIS);
  	_reset_BASE->run();
  	_reset_BASEBIS->run();
  
  	// societ� trasformate
  	_reset_SOCTRASF->run();   
  
  	// quadri A/A1/A2/A3/B/B1  
  	_reset_QUAA->run();
		_reset_QUAA1->run();
		_reset_QUAA2->run();
		_reset_QUAA3->run();
		_reset_QUAB->run();
		_reset_QUAB1->run(); 
	                           
  	// quadri C/D/D1/E/E1/E2 e prospetto E1  
  	_reset_QUAC->run();
		_reset_QUAD->run();
		_reset_QUAD1->run();
		_reset_QUAE->run();
		_reset_QUAE1->run();
		_reset_QUAE2->run(); 	                           
		_reset_PROSPE1->run(); 	                           
	                                         
		// quadri F/F1/F2/G/G1 e distinta G  
  	_reset_QUAF->run(); 
  	_reset_RIGHEF->run();
		_reset_QUAF1->run(); 
		_reset_RIGHEF1->run();
		_reset_QUAF2->run();
		_reset_RIGHEF2->run();
		_reset_QUAG->run();
		_reset_QUAG1->run();
		_reset_QUAGD->run();
	                                         
		// quadro H e dettaglio
		_reset_DETH->set_validate_record_function(validate_record_DETH); 
		_reset_QUAH->run();   
		_reset_DETH->run();  
	
		// quadro L
		_reset_QUAL->set_validate_record_function(validate_record_QUAL); 
		_reset_QUAL->run();  
	                                                                
		// quadri N/P/Q/R/S/T 
  	_reset_QUAN->run();
		_reset_QUAP->run();
		_reset_QUAQ->run();
		_reset_QUAR->run();
		_reset_QUAS->run();
		_reset_QUAT->run(); 
	}
  
  // handle log schede percipienti
  if (azzsch && !_logschede->empty())
  	handle_log();
  
  // distruzione istanze d'azzeramento
  azzera_destroy(azzsch, azzqua);
  
  return; 
}
 
// elabora le dichiarazioni selezionate (non implementata)
void TAzzeramento_archivi::elab_selezionate(const bool azzsch, const bool azzqua)
{
  long  codditta;
  
    TScandich scandich(_sel_dich);
    for (codditta = scandich.first();
    		 scandich.good(); codditta = scandich.next()) 
    {
      _curditta = codditta;
    }
 
  return; 
} 
                                                                    
bool TAzzeramento_archivi::validate_record_SCPERC(const TRectype& rec)
{
  // verifica se la scheda � azzerabile
  bool isresetable = app().is_resetable(rec);
  
  // scheda da non azzerare
  if (!isresetable)	
  	return FALSE;	
  	                   
	// scheda da loggare
  if (isresetable == 2)	  
  {
  	app()._logschede->write(rec);
  	return FALSE;	  	           
  }	        
  
  // elimino tutti gli altri record
  return TRUE;  
}                                                                                  
                                                                      
bool TAzzeramento_archivi::validate_record_SCPERC_2(const TRectype& rec)
{
	// inizializzo chiave file di log
  app()._logschede->setkey(1);
  app()._logschede->zero();
  app()._logschede->put("CODDITTA",rec.get_long("CODDITTA"));
  app()._logschede->put("TIPOA",rec.get_char("TIPOA"));
  app()._logschede->put("CODANAGR",rec.get_long("CODANAGR")); 
  app()._logschede->put("NPROG",rec.get_int("NPROG"));
  
  // elimino la scheda se esiste nel file di log
  if (app()._logschede->read() == NOERR)
		return TRUE;
  
  // non elimino tutti gli altri record
  return FALSE;    
}                                                                     

bool TAzzeramento_archivi::validate_record_RPAG(const TRectype& rec)
{
  // apro file e inizializzo chiave schede percipienti
  TLocalisamfile scperc(LF_SCPERC);
  scperc.setkey(1);
  scperc.zero();
  scperc.put("CODDITTA",rec.get_long("CODDITTA"));
  scperc.put("TIPOA",rec.get_char("TIPOA"));
  scperc.put("CODANAGR",rec.get_long("CODANAGR")); 
  scperc.put("NPROG",rec.get_int("NPROG"));
  
  // non elimino pagamento se esiste scheda di appartenenza
  if (scperc.read() == NOERR)
		return FALSE;
  
  // elimino tutti gli altri record
  return TRUE;  
}                                                                   

bool TAzzeramento_archivi::validate_record_RVER(const TRectype& rec)
{
  // apro file e inizializzo chiave schede percipienti
  TLocalisamfile scperc(LF_SCPERC);
  scperc.setkey(1);
  scperc.zero();
  scperc.put("CODDITTA",rec.get_long("CODDITTA"));
  scperc.put("TIPOA",rec.get_char("TIPOA"));
  scperc.put("CODANAGR",rec.get_long("CODANAGR")); 
  scperc.put("NPROG",rec.get_int("NPROG"));
  
  // non elimino pagamento se esiste scheda di appartenenza
  if (scperc.read() == NOERR)
		return FALSE;  
	
  // elimino tutti gli altri record
  return TRUE;  
}                                                                                                                                           
                                                                      
bool TAzzeramento_archivi::validate_record_DETH(const TRectype& rec)
{
  // non elimino i record con anno maggiore dell'anno dichiarazione
  if (rec.get_int("ANNO") > app()._anno_dich)
  	return FALSE;	
  	
  // elimino tutti gli altri record
  return TRUE;  
}              

bool TAzzeramento_archivi::validate_record_QUAL(const TRectype& rec)
{
  // non elimino i record con anno maggiore dell'anno dichiarazione
  if (rec.get_int("QLAP") > app()._anno_dich)
  	return FALSE;	
  	
  // elimino tutti gli altri record
  return TRUE;  
}              
                                                                    
bool TAzzeramento_archivi::validate_field_BASE(const TRectype& rec, const TString& fld)
{
  if (fld == "ANNODIC" ||
  		fld == "RAPPR" ||
  		fld == "CARRAPP" ||
  		fld == "CODCAAF" ||
  		fld == "CODPRO" ||
  		fld == "DITTACAAF") 
  	return FALSE;

  return TRUE;
}
   
bool TAzzeramento_archivi::validate_field_BASEBIS(const TRectype& rec, const TString& fld)
{
  if (fld == "L0CCONC1" || 
  		fld == "L0CCONC2" || 
  		fld == "L0CCONC3" ||
  		fld == "L0CTES1" ||  
  		fld == "L0CTES2" ||
  		fld == "L0CTES3")
		return FALSE;  		  

	return TRUE;
}   

void TAzzeramento_archivi::before_reset_BASEBIS(TRectype& rec)
{
  // memorizzo campi da riportare
  app()._mem_ECCRIT23_BASEBIS = rec.get_real("ECCRIT23");
  return;  
}                                                                   

void TAzzeramento_archivi::after_reset_BASEBIS(TRectype& rec)
{
  // campi da riportare
  rec.put("ECCRIT12",app()._mem_ECCRIT23_BASEBIS);
  return;  
}              
                                                             
// questa funzione restituisce :
// FALSE - la scheda non � azzerabile;
// TRUE  - la scheda � azzerabile;
// 2     - la scheda � da loggare;
bool TAzzeramento_archivi::is_resetable(const TRectype& rec)
{ 
  // apro file e inizializzo chiave pagamenti
  TLocalisamfile rpag(LF_RPAG);
  rpag.setkey(1);
  rpag.zero();
  rpag.put("CODDITTA",rec.get_long("CODDITTA"));
  rpag.put("TIPOA",rec.get_char("TIPOA"));
  rpag.put("CODANAGR",rec.get_long("CODANAGR")); 
  rpag.put("NPROG",rec.get_int("NPROG"));
  
  // istanzio record di confronto
  TRectype dummyrec(rpag.curr());  
  
  // istanzio date di confronto
  TDate dummydate(31,12,app()._anno_dich);    
  TDate dummydate2(01,01,app()._anno_dich);   
  
  // inizializzo boolean per almeno un pagamento
  bool nopags = TRUE;                           
  
  // inizializzo totale compenso e spese 
  real tot_compenso = ZERO;  
  real tot_spesa = ZERO; 
  
  // controllo se i pagamenti sono azzerabili
  for (int err = rpag.read(_isgteq);
  		 err == NOERR && rpag.curr() == dummyrec;
  		 err = rpag.next(), nopags = FALSE)
  {		
  	// data pagamento superiore al 31/12/AAAA
  	if (rpag.get_date("DATAPAG") > dummydate)
  		return FALSE; // scheda da non azzerare
  		                                       
		// pagamento non versato 
  	if (rpag.get_long("NUMVERS") <= 0L)
  		return 2; // scheda da loggare  		                                       
  		                                       
  	// totalizzo compenso e spese
  	tot_compenso += rpag.get_real("COMPENSO");	
  	tot_spesa += rpag.get_real("SPESA");
  }                       
  
  // se ci sono pagamenti controllo che la scheda sia totalmente pagata
  if (!nopags)
  	if (tot_compenso != rec.get_real("COMPENSO") ||
  		 tot_spesa != rec.get_real("SPESE"))
  		return 2; // scheda da loggare 
  		
  // se non ci sono pagamenti controllo la data documento
  if (nopags) 
  	// data documento minore del 01/01/AAAA
  	if (rec.get_date("DATADOC") < dummydate2)
  		return 2; // scheda da loggare				  
  	else	
  		return FALSE; // scheda da non azzerare

  return TRUE;  
}
                                                          
// implementazione funzione virtuale TRelation_application
void TAzzeramento_archivi::init_modify_mode(TMask& m)
{                  
  TDate dateazz; 
  
  // disabilito checkbox azzeramento schede
  dateazz = m.get_date(F_DATASCH);
  if (dateazz.year() != 0)
	{  
	  m.set(F_AZZSCH,TRUE);
	  m.disable(F_AZZSCH); 
	}
	                                       
  // disabilito checkbox azzeramento quadri
  dateazz = m.get_date(F_DATAQUA);  
  if (dateazz.year() != 0)
  {  
    m.set(F_AZZQUA,TRUE);
    m.disable(F_AZZQUA);  
  }
}                                                          
                                                          
// implementazione funzione virtuale TRelation_application
int TAzzeramento_archivi::write(const TMask& m)
{
  bool azzsch = m.get_bool(F_AZZSCH);
  bool azzqua = m.get_bool(F_AZZQUA);
  
  // chiede conferma azzeramento
  if (conferma_azzera(m, azzsch, azzqua))  
  {  
  	elab_tutte(azzsch, azzqua);      
  	return TRelation_application::write(m);
  }
    
  return NOERR;
}

// implementazione funzione virtuale TRelation_application
int TAzzeramento_archivi::rewrite(const TMask& m)
{
  TDate datasch = _rel->lfile().get_date("DATASCH"); 
  TDate dataqua = _rel->lfile().get_date("DATAQUA");   
  bool azzsch = m.get_bool(F_AZZSCH) && datasch.year() == 0;
  bool azzqua = m.get_bool(F_AZZQUA) && dataqua.year() == 0;
  
  // chiede conferma azzeramento
  if (conferma_azzera(m, azzsch, azzqua))  
  {  
  	elab_tutte(azzsch, azzqua);      
  	return TRelation_application::rewrite(m);
  }

  return NOERR;
}

// message box di conferma azzeramento
bool TAzzeramento_archivi::conferma_azzera(const TMask& m, const bool azzsch, const bool azzqua)
{
	if (azzsch || azzqua)
  {
  	TString testo;
  	testo << "Conferma azzeramento ";
  	if (azzsch)	
  		testo << "schede percipienti, ";
  	if (azzqua)	
  		testo << "quadri dichiarazione, ";	
  	testo << "per l'anno " << m.get(F_ANNODIC) << " ?";  
		return yesno_box(testo); 
	}
	
	return FALSE;
}

// handler del campo maschera F_ANNODIC
bool TAzzeramento_archivi::F_ANNODIC_hnd(TMask_field& f, KEY k)
{
  return TRUE;
}                            

// handler del campo maschera F_AZZSCH
bool TAzzeramento_archivi::F_AZZSCH_hnd(TMask_field& f, KEY k)
{             
  if (f.to_check(K_TAB))
  {
    TMask& m = f.mask();
    
    // compila in automatico l'utente e la data di azzeramento 
		// delle schede percipiente
    if (m.get_bool(F_AZZSCH) == TRUE)
    {
    	TDate today(TODAY);
    	m.set(F_DATASCH,today);
    	m.set(F_USERSCH,user());
    }   
    else
    {	
    	m.reset(F_DATASCH);
    	m.reset(F_USERSCH);
    }
  
  }
  return TRUE;
}                            

// handler del campo maschera F_AZZQUA
bool TAzzeramento_archivi::F_AZZQUA_hnd(TMask_field& f, KEY k)
{             
  if (f.to_check(K_TAB))
  {
    TMask& m = f.mask();
    
    // compila in automatico l'utente e la data di azzeramento 
		// delle schede percipiente
    if (m.get_bool(F_AZZQUA) == TRUE)
    {
    	TDate today(TODAY);
    	m.set(F_DATAQUA,today);
    	m.set(F_USERQUA,user());
    }  
    else
    {	
    	m.reset(F_DATAQUA);
    	m.reset(F_USERQUA);
    }
  }
  return TRUE;
}             
                                      
// funzione principale di lancio applicazione
int Azzeramento_archivi(int argc, char* argv[])
{
  TAzzeramento_archivi a(*argv[2]);
  a.run(argc, argv, "Azzeramento archivi");
  return 0;
}