#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "at1.h"
// nomi campi maschera
#include "at1200a.h"
          
// nomi dei campi
#include "soggetti.h"
#include "donaz.h"
#include "benem.h"
#include "sezioni.h" 
#include "atopera.h" 
#include "atropera.h" 
#define ALIAS_GAZ 300
class TAttribuzioneBenemerenze : public TPrintapp
{
	TMask*						_msk;
	TRelation*   			_rel;
	TLocalisamfile*		_donaz;
	TLocalisamfile* 	_benem;
	TLocalisamfile* 	_atopera;
	TLocalisamfile* 	_atropera;
	TLocalisamfile* 	_sezioni;
	TRecord_array*		_sdonazioni;
	TRecord_array* 		_sbenemerenze;
	TCursor*					_cur;
  TAssoc_array			_catdon;
  TAssoc_array			_tabben;
  TString16 				_gruppoazie, _oldben;
  int								_bonus;
	TDate							_dataela, _datapre;
	bool							_attgruppi,_anchegruppi, _prevista, _nuovicriteri;
	bool							_definitiva;
  TParagraph_string _cognome_nome;
  int								_numdon;
  int 							_contatore;
  int 							_progope;
  
protected:
	virtual bool user_create();
	virtual bool user_destroy();
	virtual bool set_print(int m);
	virtual void set_page(int file, int cnt);
	virtual bool preprocess_page(int file, int counter);
  virtual void postclose_print();
	
public:
  void crea_intestazione();
  void header_ben(const TString16 tipoben);
	TAttribuzioneBenemerenze() : _cognome_nome("",25) {}
};
HIDDEN inline TAttribuzioneBenemerenze& app() { return (TAttribuzioneBenemerenze&) main_app(); }
void TAttribuzioneBenemerenze::postclose_print()
{ 
	TLocalisamfile atropera(LF_ATROPERA);
	atropera.setkey(1);
	atropera.zero();
	atropera.put(ROP_PROGOPE, _progope);
	TRectype r(atropera.curr());
	for (atropera.read(); !atropera.eof(); atropera.next())
	{
		if (atropera.curr() != r) break;
		atropera.remove();
	}	
	if (!_definitiva)
	{
		TLocalisamfile atopera(LF_ATOPERA);
		atopera.setkey(1);
		atopera.zero();
		atopera.put(OPE_PROGOPE, _progope);
		if (atopera.read() == NOERR)
			atopera.remove();
	}
}
bool TAttribuzioneBenemerenze::preprocess_page(int file, int counter)
{ 
	if (file==LF_ATROPERA)
	{
		TRectype& recsog = current_cursor()->curr(LF_SOGGETTI);
		TString80 nome = recsog.get(SOG_COGNOME);
		nome << " ";
		nome << recsog.get(SOG_NOME);
		_cognome_nome = nome;
		if (_prevista)
		{     
			int numdon = recsog.get_int(SOG_TOTDON);
			if (_prevista)
			{
				// aggiungo le donazioni che puo' fare da oggi alla data elaborazione
				const TDate oggi(TODAY);
				const long giorni = _dataela - oggi;
				int intervallo = 0;
				if (giorni > 0)
				{                   
					const int intsi = recsog.get_int(SOG_INTSI);
					const int intaf = recsog.get_int(SOG_INTAF);							
					if (intsi == 0)
						intervallo = intaf;
					else              
					{
						if (intaf == 0)
							intervallo = intsi;
						else
							intervallo = min(intsi, intaf);
					}		
					if (intervallo > 0)
						numdon = numdon + int(giorni / intervallo);
				}
			} 
			_numdon = numdon;
		}
		// salto pagina se cambio benemerenza
		const TString16 tipoben = current_cursor()->curr().get(ROP_S0);
		if (tipoben!=_oldben)
		{
			if (_oldben != "**")
				printer().formfeed();
			_oldben = tipoben;
			header_ben(tipoben);
		}
		if (_definitiva)
		{
			const long codice = recsog.get_long(SOG_CODICE);
			TRectype* key = new TRectype(LF_BENEM);
			key->put(BEN_CODICE, codice);
			int err = _sbenemerenze->read(key);
			int r = _sbenemerenze->rows();
			TRectype& rec = _sbenemerenze->row(r+1,TRUE);
				
			TString16 codsez = recsog.get(SOG_CODSEZ);
			TString16 codsot = recsog.get(SOG_CODSOT);
			TString16 gruppoazie = recsog.get(SOG_GRUPPOAZIE);
				
			rec.put(BEN_TIPOBEN, tipoben);
			rec.put(BEN_DATAMAT, recsog.get(SOG_DATAULTDON));
			rec.put(BEN_BONUS, 	 recsog.get(SOG_TOTDON)); 
			rec.put(BEN_DATABEN, _dataela);
			rec.put(BEN_DATACON, _datapre);
			if (_attgruppi)
				rec.put(BEN_GRUPPOAZIE, gruppoazie);
			else					
			{
				rec.put(BEN_CODSEZ, codsez);
				rec.put(BEN_CODSOT, codsot);
			}	
			err = _sbenemerenze->rewrite();
		}		
	}		
  return TRUE;
}
void TAttribuzioneBenemerenze::set_page(int file, int cnt)
{                                      
	if (file == LF_SOGGETTI)
	{
		set_row(1,"@0g#a", &_cognome_nome);
		set_row(1,"@26g@S", FLD(LF_SOGGETTI,SOG_CATDON));
		set_row(1,"@29g@S", FLD(LF_SOGGETTI,SOG_TESSAVIS));
		set_row(1,"@39g@pn", FLD(LF_SOGGETTI,SOG_TOTDON,"###"));
		set_row(1,"@48g@ld", FLD(LF_SOGGETTI,SOG_DATAISC));
		if (_prevista)
			set_row(1,"@59g#3d", &_numdon);
	}				
	else
		set_row(1,"");	
}
void TAttribuzioneBenemerenze::header_ben(const TString16 tipoben)
{
	TString intestazione(132);
	intestazione = "Benemerenza ";
	intestazione << tipoben;
  intestazione << " ";
	intestazione << cache().get("BNZ", tipoben).get("S0");
	intestazione.center_just();
	set_header(1,"@0g%s", (const char*) intestazione);
	return;
}
bool TAttribuzioneBenemerenze::set_print(int)
{
  KEY tasto;
  tasto = _msk->run();
	if (tasto == K_ENTER)
	{  	 
		const TDate datarif = TDate("16/05/2004");
		_oldben = "**"; 
		_contatore = 0;                 
		_prevista = (_msk->get(F_SITUAZIONE)[0] == 'P');
		_dataela = _msk->get(F_DATAELA);
		_datapre = _msk->get(F_DATAPRE);
		_attgruppi = _msk->get_bool(F_ATTGRUPPI);
		_gruppoazie = _msk->get(F_GRUPPOAZIE);
		_anchegruppi = _msk->get_bool(F_ANCHEGRUPPI);
		_definitiva = _msk->get_bool(F_DEFINITIVA);
		_nuovicriteri = _msk->get_bool(F_NUOVICRITERI);
    _catdon.destroy();    
	  const TString16 catpri = _msk->get(F_CAT1);
	  const TString16 catsec = _msk->get(F_CAT2);
	  const TString16 catter = _msk->get(F_CAT3);
	  const TString16 catqua = _msk->get(F_CAT4);
	  const TString16 catqui = _msk->get(F_CAT5);
	  const TString16 catses = _msk->get(F_CAT6);
	  if (catpri.not_empty())
	  	_catdon.add((const char*) catpri);
	  if (catsec.not_empty())
	  	_catdon.add((const char*) catsec);
	  if (catter.not_empty())
	  	_catdon.add((const char*) catter);
	  if (catqua.not_empty())
	  	_catdon.add((const char*) catqua);
	  if (catqui.not_empty())
	  	_catdon.add((const char*) catqui);
	  if (catses.not_empty())
	  	_catdon.add((const char*) catses);
		_tabben.destroy();
		TTable ben("BNZ");
	  for(ben.first(); !ben.eof(); ben.next())
	  {             
	  	TString16 codben = ben.get("CODTAB");
	  	int numdonben = ben.get_int("I0");
			int m_numdon = ben.get_int("I1");
			int m_anni = ben.get_int("I2");
			bool solodim = ben.get_bool("B0");
			TToken_string* condizioni = new TToken_string();;
			condizioni->add(numdonben);
			condizioni->add(m_numdon);
			condizioni->add(m_anni);
			condizioni->add(solodim);
	  	_tabben.add((const char*)codben, (TObject*) condizioni);
	  }
  	TString80 filtro;
  	if (_attgruppi)
  	{
	  	if (_gruppoazie.not_empty())
		  	filtro.format("(90->GRUPPOAZIE == \"%s\")",(const char*)_gruppoazie);
			else		  	
		  	filtro.format("(90->GRUPPOAZIE != \"\")");
		}		  	
		else
			if (!_anchegruppi)
				filtro.format("(90->GRUPPOAZIE == \"\")");			
		if (filtro.not_empty())
			filtro << " && ";
		filtro << "(90->BENEM == \"X\")";							
		// filtro per sezioni
	 	const TString16 sezini = _msk->get(F_SEZINI);
	 	const TString16 sotini = _msk->get(F_SOTINI);
	  TRectype da(LF_SOGGETTI);
		if (sezini.not_empty())  
			da.put(SOG_CODSEZ, sezini);
	  if (sotini.not_empty())
			da.put(SOG_CODSOT, sotini);
		_cur = new TCursor(_rel, "", 3, &da, &da);  
		_cur->setfilter(filtro, TRUE);
		
		TLocalisamfile atopera(LF_ATOPERA);
		atopera.last();
		_progope = atopera.get_int(OPE_PROGOPE);
		_progope++;
		atopera.zero();
		atopera.put(OPE_PROGOPE, _progope);
		atopera.put(OPE_CODSEZ,sezini);
		atopera.put(OPE_CODSOT,sotini);
		atopera.put(OPE_GRUPPOAZIE,_gruppoazie);
		atopera.put(OPE_DATA1,_dataela);
		atopera.put(OPE_DATA2,_datapre);
		atopera.put(OPE_FLAG1,_anchegruppi);
		atopera.put(OPE_FLAG2,_attgruppi);
		atopera.put(OPE_UTENTE,user());
		atopera.put(OPE_TIPOOPE,'B');
		atopera.write();
		TLocalisamfile atropera(LF_ATROPERA);
		TRectype& sog = _cur->curr();
		long last = _cur->items();
		_benem->setkey(3);
		TProgind prg (last, "Elaborazione in corso... Prego attendere", FALSE, TRUE, 30);
  	for ( *_cur=0; _cur->pos() < last; ++(*_cur) )
  	{
    	prg.addstatus(1);   
			// controllare la categoria    	
			bool filtrato = TRUE;
			
			long codice = sog.get_long(SOG_CODICE);
			if (_catdon.items() != 0)
			{
				const TString16 cat = sog.get(SOG_CATDON);
				filtrato = _catdon.is_key((const char*) cat);
			}
			if (filtrato)
			{
				const char sesso = sog.get(SOG_SESSO)[0];
				const TDate datanasc = sog.get_date(SOG_DATANASC);
				const TDate dataisc = sog.get_date(SOG_DATAISC);
				TRectype* key = new TRectype(LF_DONAZ);
				key->put(DON_CODICE, codice);
				int err = _sdonazioni->read(key);
				if (err == NOERR)
				{             
					int precsi = sog.get_int(SOG_DONPRECSI);
					int precaf = sog.get_int(SOG_DONPRECAF);
					int numdon = precsi + precaf;
					int donxanno = 0;
					int anno = 0;
					for (int r=1; r<=_sdonazioni->rows(); r++)
					{
						const TRectype& riga = _sdonazioni->row(r);
						const TDate datadon = riga.get_date(DON_DATADON);
						const TString16 tipodon = riga.get(DON_TIPODON);
						if (datadon<=_dataela)
						{
							if (_nuovicriteri && datadon>datarif) // 16/05/2004
							{
								if (anno != datadon.year())
								{
									if (donxanno > 4)
										donxanno = 4;
									numdon += donxanno;
									donxanno = 0;
									anno = datadon.year();
								}
								donxanno++;
								int eta = datadon.year() - datanasc.year();
								if (datadon.month() < datanasc.month())
									eta--;
								else 
									if (datadon.month() == datanasc.month())
										if (datadon.day() < datanasc.day())
											eta--;
								if ((tipodon == "SI" || tipodon=="SN") && (sesso == '2') && (eta < 50))
									donxanno++;
							}
							else
								numdon++;
						}
					}
					if (_nuovicriteri)
					{
						if (donxanno > 4)
							donxanno = 4;
						numdon += donxanno;
					}
					if (_prevista)
					{
						// aggiungo le donazioni che puo' fare da oggi alla data elaborazione
						const TDate oggi(TODAY);
						const long giorni = _dataela - oggi;
						int intervallo = 0;
						if (giorni > 0)
						{                   
							const int intsi = sog.get_int(SOG_INTSI);
							const int intaf = sog.get_int(SOG_INTAF);							
							if (intsi == 0)
								intervallo = intaf;
							else              
							{
								if (intaf == 0)
									intervallo = intsi;
								else
									intervallo = min(intsi, intaf);
							}		
							if (intervallo > 0)
								numdon = numdon + int(giorni / intervallo);
						}
					}
					TString16 ultben = "**";       
					TRectype* key = new TRectype(LF_BENEM);
					key->put(BEN_CODICE, codice);
					int err = _sbenemerenze->read(key);
					if (err == NOERR)    
					{
						for (int r=1; r<=_sbenemerenze->rows(); r++)
						{
							const TRectype& riga = _sbenemerenze->row(r);
							ultben = riga.get(BEN_TIPOBEN);
							if (ultben.empty())
								ultben = "**";
						}							
					}
					int bonusctrl = 0;
					int m_bonusctrl = 0;
					if (ultben != "**")                                  
					{ 
						TToken_string& condizioni = (TToken_string&) _tabben.find((const char*) ultben); 
						TString str = condizioni.get();
						bonusctrl = atoi(str);
						str = condizioni.get();
						m_bonusctrl = atoi(str);
					}						
					_tabben.restart();
					TToken_string* c;
				  for (c = (TToken_string*) _tabben.first_item(); c != NULL; c = (TToken_string*) _tabben.succ_item())
				  {
 			  		const char* tipoben = _tabben.get_hashobj()->key();
				  	TString str = c->get(0);
						int bonus = atoi(str);
						str = c->get();
						int m_bonus = atoi(str);
						str = c->get();
						int m_anni = atoi(str);
						str = c->get();
						const int sd = atoi(str);
						bool solodim = sd > 0;
				  	if (bonus > bonusctrl)
				  	{
							bool attribuisci = false;
					  	if (numdon >= bonus) 
								attribuisci = true;
							if (_nuovicriteri && !attribuisci && (m_bonus > 0 || m_anni > 0))  // se uso nuovi criteri e non ne ha diritto col vecchio sistema quardo se ne ha diritto con i nuovi criteri
							{
								const int anniisc = (_dataela - dataisc)/360;
								attribuisci = (numdon >= m_bonus) && (anniisc >= m_anni);
							}
							if (attribuisci && solodim)
							{
								const TString16 cat = sog.get(SOG_CATDON);
								attribuisci = cache().get("CTD", cat).get_bool("B0");
							}
							if (attribuisci)
							{
					  		// controllo che non abbia ricevuto la benemerenza
					  		_benem->zero();
					  		_benem->put(BEN_CODICE, codice);
					  		_benem->put(BEN_TIPOBEN, tipoben);
					  		_benem->read();
					  		if (_benem->bad())
					  		{
					  			atropera.zero();
					  			atropera.put(ROP_PROGOPE, _progope);
									atropera.put(ROP_CODICE, codice);				  			
									atropera.put(ROP_S0, tipoben);
									atropera.write();
					  		}
					  	}       
						}					  	
					}				  	
				}
			}									
    }
    reset_files(); 
		TRelation* relope = new TRelation(LF_ATROPERA);
 	  relope->add(LF_SOGGETTI, "CODICE==CODICE");
		TString80 chiave = "131->S0|UPPER(90->COGNOME)|UPPER(90->NOME)";
		TString80 filtroope = format("131->PROGOPE==%d", _progope);
	  int curope = add_cursor(new TSorted_cursor(relope, (const char*) chiave, "", 1));
		current_cursor()->setfilter((const char*) filtroope, TRUE);
		add_file(LF_ATROPERA);
		add_file(LF_SOGGETTI,LF_ATROPERA);
		reset_print();		
    crea_intestazione();
    return TRUE;
  }
  else
    return FALSE;
}
void TAttribuzioneBenemerenze::crea_intestazione()
{
	reset_header();
	TString sep(132);
  sep = "ATTRIBUZIONE BENEMERENZE ";
	if (_nuovicriteri)
		sep << "CON NUOVI CRITERI ";
  if (_prevista)
  	sep << " PREVISTE ";
  if (_definitiva)
  	sep << "DEFINITIVA";
  else
  	sep << "PROVVISORIA";
  sep << " ALLA DATA ";
	sep << _dataela.string();;
	sep.center_just();
 	set_header(2, "@0g%s", (const char*) sep);
  sep = "";
  sep << "Pag. @#";
  set_header(2, "@120g%s", (const char*) sep);  
  	
  sep = "";
  sep.fill('-');
  set_header(3, (const char *) sep);
  if (_prevista)
  {
 		set_header(4,"@0gCognome e nome@26gC.@29gTessera@39gTot.don.@48gData isc.@59gDon.pre.");
 		set_header(5,"@0-------------------------@26g--@29g--------@39g--------@48g----------@59g--------");
 	}	
  else
  {
 		set_header(4,"@0gCognome e nome@26gC.@29gTessera@39gTot.don.@48gData isc.");
 		set_header(5,"@0-------------------------@26g--@29g--------@39g--------@48g----------");
 	}	
}
bool TAttribuzioneBenemerenze::user_create()
{                             
	_msk = new TMask("at1200a");
	_rel = new TRelation(LF_SOGGETTI);
	_rel->add(LF_SEZIONI,"CODSEZ==CODSEZ|CODSOT==CODSOT");
	_rel->add("GAZ", "CODTAB==GRUPPOAZIE",1,0,ALIAS_GAZ);
	_donaz = new TLocalisamfile(LF_DONAZ);
	_benem = new TLocalisamfile(LF_BENEM);
	_sdonazioni = new TRecord_array(LF_DONAZ,DON_PROGDON);
	_sbenemerenze = new TRecord_array(LF_BENEM, BEN_PROGBEN);
	_atopera = new TLocalisamfile(LF_ATOPERA);
	_atropera = new TLocalisamfile(LF_ATROPERA);
	_sezioni = new TLocalisamfile(LF_SEZIONI);
	return TRUE;
}	
bool TAttribuzioneBenemerenze::user_destroy()	
{
	delete _sezioni;
	delete _atropera;
	delete _atopera;
	delete _sbenemerenze;
	delete _sdonazioni;
	delete _benem;
	delete _donaz;
	delete _rel;
	delete _msk;
	return TRUE;
}
int at1200(int argc, char* argv[])
{
	TAttribuzioneBenemerenze a;
	a.run(argc, argv, "Attribuzione complessiva");
	return 0;
}