#include <automask.h>
#include <filetext.h>
  
#include "../ve/velib.h"
   
#include "ps0077.h"
#include "ps0077400a.h"
 
class TFilConad: public TFile_text
{
protected:
  virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str);

public:
  TFilConad(const TString& file_name, const TString& config_name);
  virtual ~TFilConad() { }
};

TFilConad::TFilConad(const TString& file_name, const TString& config_name)
          : TFile_text(file_name, config_name)
{
}

class TBolle2Conad_mask : public TAutomask
{
protected:
  bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:

  TBolle2Conad_mask();
  
  virtual ~TBolle2Conad_mask(){};
};
  
TBolle2Conad_mask::TBolle2Conad_mask() :TAutomask ("ps0077400a")
{
}  
  
bool TBolle2Conad_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{ 
  return TRUE;
}

class TBolle2Conad : public TSkeleton_application
{                     
	TCursor*				   _cur;
  TBolle2Conad_mask* _msk;
  TDate							 _dataini, _datafin;
  long 					     _codconad;
  TString80					 _codforn;
  TDocumento*				 _fattura;
  TDocumento*  			 _bolla;
  TRiga_documento*   _rigabolla;
  TFilConad*				 _trasfile;
  long							 _progressivo;
  int								 _modalita;     // 0 = elabora doc. originali (MARPESCA) 1 = elabora doc. indicati (MAINARDI)
  TAssoc_array*			 _elencobolle; // assoc array per verificare se la bolla � gia stat passata
  
protected:

  virtual const char * extra_modules() const {return "ve";}

  virtual bool create(void);
  virtual bool destroy(void);
  virtual void main_loop() ;
  
  void elabora_documenti();
  void elabora_righe_doc();
  void elabora_doc_originale(const TDocumento& documento);

public:
	const TDocumento fattura() {return *_fattura;} ;
	const TDocumento bolla() {return *_bolla;} ;
	const TRiga_documento rigabolla() {return *_rigabolla;} ;
	const long progressivo() {return _progressivo;} ;
	const TString80 fornitore() { return _codforn;} ;
	const long conad() { return _codconad;} ;
  TBolle2Conad() {} ;
  virtual ~TBolle2Conad() {} ;
};  

// restituisce un riferimento all' applicazione
inline TBolle2Conad& app() { return (TBolle2Conad&) main_app();}

// gestione dei messaggi estesi nei campi
void TFilConad::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str)
{
  const TString code(s.get(0));
  TString valore;
  if (code == "_FISSO")
  {
    // gestione dei campi fissi per i record delle riba
    // sintassi: _FISSO,!<valore>
    // dove: <valore> � la stringa fissa da emettere
    TString in(s.get());
    CHECK(in[0]=='!',"Macro _FISSO senza carattere '!'");
    in.ltrim(1);
    in.trim();
    valore = in;
  }
  else if (code == "_PROGRESSIVO")
  {
    valore.format("%05d", app().progressivo());
  }
  else if (code == "_FORNITORE")
  {
    valore = app().fornitore();
  }
  else if (code == "_CONAD")
  {
    valore.format("%015d", app().conad());
  }
  else if (code == "_FATTURA")
  {
     // gestione campi da leggere dalla fattura 
    TString in(s.get());
    if (in == "DATA")
    {
    	TDate data = app().fattura().data();
    	valore = data.string(brief, '-', full, full, amg_date);
    	valore.strip("-");
    }
    else if (in == "NUMERO")
    {
    	valore.format("%06d", app().fattura().numero());
    }
  }
  else if (code == "_BOLLA")
  {
     // gestione campi da leggere dalla bolla
    TString in(s.get());
    if (in == "DATA")
    {
    	TDate data = app().bolla().data();
    	valore = data.string(brief, '-', full, full, amg_date);
    	valore.strip("-");
    }
		else if (in == "NUMERO")
		{
			valore = str;
			const TString16 codnum = cur.curr().get("CODNUM");
			TString16 suffisso = cache().get("%NUM", codnum, "S7");
			valore.trim();
			suffisso.trim();
			valore << suffisso;
		}
  }
  else if (code == "_RIGABOLLA")
  {
  	// gestione campi da leggere dalla riga bolla corrente
 		TString in(s.get()); 	
 		if (in == "PREZZO")
 		{
 			real r = app().rigabolla().prezzo(TRUE, FALSE);
 			valore = r.string(9,3);
 			valore.strip(".");
 		}
 		else if (in == "IMPORTO")
 		{
 			real r = app().rigabolla().importo(TRUE, FALSE);
 			valore = r.string(9,3);
 			valore.strip(".");
 		}
 		else if (in == "ALIQUOTA")
 		{
 			real r = app().rigabolla().iva().percentuale();
 			valore = r.string(2,0,'0');
 		}
 		else if (in == "QUANTITA")
 		{
 			real r = app().rigabolla().quantita();
 			valore = r.string(7,2);
 			valore.strip(".");
 		}
 		else if (in == "OMAGGIO")
 		{
 			if (app().rigabolla().is_omaggio())
 				valore = "6";
 			else	         
 				valore = "1";
 		}
  }
  else NFCHECK("Macro non definita: %s", (const char *)code);
  
  str = valore;
}

bool TBolle2Conad::create()
{      
	open_files(LF_DOC, LF_RIGHEDOC, LF_CLIFO, LF_CFVEN, LF_INDSP, LF_ANAMAG, 0);
  _msk = new TBolle2Conad_mask();
  _trasfile = NULL;
	_elencobolle = new TAssoc_array();
  
  return TSkeleton_application::create();
}

bool TBolle2Conad::destroy()
{             
	delete _elencobolle;
	if (_trasfile)  
  	delete _trasfile;
  delete _msk;

  return TSkeleton_application::destroy();
}

void TBolle2Conad::main_loop()
{
	TConfig config("ps0077400conf.ini", "TRASFERIMENTO");
	TFilename tracciatoname = config.get("TRACCIATO");
	_modalita = config.get_int("MODALITA");
	_codconad = config.get_long("CONAD");
	_codforn = config.get("FORNITORE");
	TFilename filename = config.get("NOMEFILE");
	if (filename.exist())
		remove(filename);
  while (_msk->run()!=K_QUIT)
  {                     
		_elencobolle->destroy();
  	_progressivo = 0;
  	_trasfile = new TFilConad(filename, tracciatoname);
  	_trasfile->open(filename,'w');
	  _trasfile->force_record_separator(TRUE);
  	
    _dataini = _msk->get_date(F_DATAINI);
    _datafin = _msk->get_date(F_DATAFIN);
		elabora_documenti(); 		
		_trasfile->close();
		delete _trasfile;
		_trasfile = NULL;
	}	
}

void TBolle2Conad::elabora_documenti()
{
  TSheet_field& sheet = _msk->sfield(F_SHEETDOC);

  TRelation doc_rel(LF_DOC);
  doc_rel.add(LF_RIGHEDOC, "CODNUM==CODNUM|ANNO==ANNO|PROVV==PROVV|NDOC==NDOC");
  doc_rel.add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF");
  TRectype da(LF_DOC);
  TRectype a(LF_DOC);
  const long items = sheet.items();
  if (items > 0)
  {
	  bool ok = TRUE;
	  TString16 codnum;
	  TString filt_expr;
	  if (_modalita == 0) // MARPESCA, seleziono in base al codice cliente indicato in ps0077400conf.ini
	  {
			da.put("TIPOCF", "C");
			da.put("CODCF", _codconad);
			da.put("PROVV", "D");
			da.put("ANNO", _dataini.year());
			da.put("DATADOC", _dataini);

			a.put("TIPOCF", "C");
			a.put("CODCF", _codconad);
			a.put("PROVV", "D");
			a.put("ANNO", _datafin.year());
			a.put("DATADOC", _datafin);
		}
		else // MAINARDI selezione solo per data iniziale e finale
		{
		  da.put("DATADOC", _dataini);
		  da.put("PROVV", "D");
		  da.put("ANNO", _dataini.year());
	  
		  a.put("DATADOC", _datafin);
		  a.put("PROVV", "D");
		  a.put("ANNO", _datafin.year());
		}
	  filt_expr << "(";
	  FOR_EACH_SHEET_ROW(sheet, r, row)
	  {
	    codnum = row->get(0);
	    if (codnum.not_empty())
	    {
	    	filt_expr << "(CODNUM==\"";
	    	filt_expr << codnum << "\")||";
	    }
	  }
	  filt_expr.rtrim(2);  
	  filt_expr << ")";
    if (_modalita == 0)
	  _cur = new TCursor(&doc_rel,filt_expr,2,&da,&a);
	  else
	  	_cur = new TCursor(&doc_rel,filt_expr,3,&da,&a);
	  const long cur_items = _cur ->items(); // Scorre tutti i documenti che rientrano nell'intervallo selezionato
	  if (cur_items != 0) 
	  {
		  _cur->freeze();
	    TRectype& cur_rec = _cur->curr();
	    for (*_cur = 0; _cur->pos() < cur_items; ++(*_cur))
	    {
	    	if (_modalita == 0)
		    	elabora_righe_doc();
	    	else                      
	    	{
	    		TString16 codprcf = _cur->curr(LF_CFVEN).get("CODPRCF");
	    		if (codprcf.not_empty())
	    		{
						_bolla = new TDocumento(_cur->curr());
						elabora_doc_originale(*_bolla);
						delete _bolla;
					}
				}
			}
	  }                  
	  delete _cur;
	}  
}

void TBolle2Conad::elabora_righe_doc()
{                          
          
	_fattura = new TDocumento(_cur->curr());
	for (int i=1;i<=_fattura->rows();i++)
	{
		const TRiga_documento& riga = (*_fattura)[i];
		const TString16 dacodnum = riga.get("DACODNUM");		
		const int daanno = riga.get_int("DAANNO");		
		const char daprovv = riga.get("DAPROVV")[0];		
		const long dandoc = riga.get_long("DANDOC");		
		if (dacodnum.not_empty() && daanno != 0  && daprovv != ' ' && dandoc != 0)
		{
			TString codicebolla = "";
			codicebolla << daprovv;
			codicebolla << daanno;
			codicebolla << dacodnum;
			codicebolla << dandoc;
			if (!_elencobolle->is_key((const char*) codicebolla))
			{ 
				_elencobolle->add((const char*) codicebolla);
				_bolla = new TDocumento(daprovv, daanno, dacodnum, dandoc);
				elabora_doc_originale(*_bolla);
				delete _bolla;
			}
		}
	}	
	delete _fattura;
}
 
void TBolle2Conad::elabora_doc_originale(const TDocumento& documento)
{                                   
	TRelation bol_rel(LF_DOC);
  bol_rel.add(LF_RIGHEDOC, "CODNUM==CODNUM|ANNO==ANNO|PROVV==PROVV|NDOC==NDOC");
  bol_rel.add(LF_ANAMAG, "CODART==CODART", 1, LF_RIGHEDOC);
  bol_rel.add(LF_INDSP, "TIPOCF==TIPOCF|CODCF==CODCF|CODIND==CODINDSP", 1, LF_DOC);
  bol_rel.add(LF_CFVEN, "TIPOCF==TIPOCF|CODCF==CODCF",1, LF_DOC);
	TRectype da(documento.head());
  
  TCursor bol_cur(&bol_rel, "", 2, &da, &da);
  bol_cur = 0;
	_progressivo++;                   	
	// scrivo il record 01 testata bolla
  TRecord_text rec;
  rec.set_type("01");
  _trasfile->autoload(rec, bol_cur); 
  _trasfile->write(rec);
  // scrivo i record 02 righe bolla
	for (int i=1;i<=documento.rows();i++)
	{                                        
		_rigabolla = new TRiga_documento(documento[i]);
	  rec.set_type("02");
  	_trasfile->autoload(rec, bol_cur); 
  	_trasfile->write(rec);
  	delete _rigabolla;
  	bol_cur.next_match(LF_RIGHEDOC);
  }  
}
 
int ps0077400(int argc, char **argv) 
{
  TBolle2Conad a;
  a.run(argc, argv, TR("Trasferimento bolle CONAD"));
  return 0;
}