#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <textset.h>

#include <mov.h>
#include <rmoviva.h>

#include "../ca/calib01.h"
#include "../ca/calib02.h"
#include "../cg/cgsaldac.h"

#include "ps0713100a.h"

                                       ///////////////////////////////////
                                       ////    TESPORTA_DATIVA_MSK    ////
                                       ///////////////////////////////////

//Classe TEsporta_dativa_msk
class TEsporta_dativa_msk : public TAutomask
{

public:
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
  TEsporta_dativa_msk();
};

//ON_FIELD_EVENT: metodo che gestisce i comportamenti dei vari campi della maschera
bool TEsporta_dativa_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
	switch (o.dlg())
	{		
	case F_ADATA:
		if (e == fe_modify || e == fe_close)
    {
			//setto il campo F_NAME a un valore fisso, e cioè: "data_in_ANSI.txt"
      TDate adata = o.get();
			TString16 str_adata;  str_adata << adata.date2ansi() << ".txt";
			set(F_NAME, str_adata);
		}
		break;
	default: break;
	}
  return true;
}

//metodo costruttore
TEsporta_dativa_msk::TEsporta_dativa_msk() : TAutomask("ps0713100a"){}

                                       ///////////////////////////////////
                                       ////    TESPORTA_DATIVA_REC    ////
                                       ///////////////////////////////////

//Classe TEsporta_dativa_rec (righe movimenti iva)
class TEsporta_dativa_rec : public TCSV_recordset
{
public:
	TEsporta_dativa_rec();
};

//metodo costruttore
TEsporta_dativa_rec::TEsporta_dativa_rec() 
                    : TCSV_recordset("CSV(\"\t\")")
{
}

                                       ///////////////////////////////////
                                       ////    TESPORTA_DATIVA_APP    ////
                                       ///////////////////////////////////

//Classe TEsporta_dativa_app
class TEsporta_dativa_app : public TSkeleton_application
{
protected:
	virtual bool check_autorization() const {return false;}
  virtual const char * extra_modules() const {return "cg";}
	virtual void main_loop();

	bool test_partita(const long numreg, TDate& last_data_pag, const TDate& data) const;

public:
	void esporta_righe_iva(const TMask& msk) const;
	void set_inviva(TISAM_recordset& rmoviva, const TDate& data) const;
};

//TEST_PARTITA: metodo che cerca l'ultima data pagamento delle partite relative ad un numreg (la maggiore)
//il metodo restiruisce true se esiste almeno una partita per il numreg indicato
bool TEsporta_dativa_app::test_partita(const long numreg, TDate& last_data_pag, const TDate& data) const
{
  TPartite_array torneo;
  //aggiungo all'array tutte le partite con quel numreg
	torneo.add_numreg(numreg);
	TPartita* partita = torneo.first();
  //se esiste almeno una partita ed è chiusa
	if (partita != NULL && partita->chiusa())
	{
		//scorro tutte le partite
    for (int r = partita->last(); r > 0; r = partita->pred(r))
		{
      //instanzio una riga_partite
			const TRiga_partite& row = partita->riga(r);
			const tipo_movimento tipo = row.tipo();
      //controllo il tipo_movimento; se è del tipo tm_pagamento o tm_pagamento_insoluto
      //recupero la data del pagamento, e se questa è maggiore di quella già trovata, aggiorno
      //quest'ultima
			if (tipo == tm_pagamento || tipo == tm_pagamento_insoluto)
			{
				const TDate datadoc = row.get_date(PART_DATAPAG);
				if (datadoc > last_data_pag)
					last_data_pag = datadoc;
			}
		}
    return last_data_pag <= data ? true : false;
	}
	return false;
}

//ESPORTA_RIGHE_IVA: metodo che prepara il csv-recordset per essere esportato
void TEsporta_dativa_app::esporta_righe_iva(const TMask& m) const
{
	//instanzio il TFilename e controllo la sua esistenza
  TFilename path = m.get(F_PATH);
	path.add(m.get(F_NAME));
	if (path.exist())
  {
		TString str;
    str << "ATTENZIONE! "  << "Il file " << m.get(F_NAME) << "è già esistente.\n"
        << "Se si procede sara' azzerato il file esistente!\nContinuare?";
    if (!yesno_box(str))
			return;
  }

  //preparo le date di interesse  
  const TDate adata(m.get_date(F_ADATA));
	const TDate dadata(1, 1, adata.year() - 1);
  
  //preparo query su righe iva joinati ai mov
	TString query("USE RMOVIVA SELECT BETWEEN(23.DATAREG,#DADATA,#ADATA)&&(23.INVIVA!=\"X\")&&(23.TIPO=\"F\")\n");

	bool with_cms = m.get_int(F_JOB) == 1;
/* if (m.get_int(F_JOB) == 1)
			query << "&&(CODCMS!=\"\")\n";
		else
			query << "&&(CODCMS=\"\")\n"; */

	query << "JOIN MOV INTO NUMREG==NUMREG\n"
	      << "JOIN %IVA ALIAS 101 INTO CODTAB==CODIVA\n"
	      << "JOIN CLIFO TO MOV INTO TIPOCF==TIPO CODCF==CODCF";
	
  //instanzio il recordset
	TISAM_recordset rmoviva(query);	
	rmoviva.set_var("#DADATA", dadata);
	rmoviva.set_var("#ADATA",  adata);

	//instanzio il csv recordset
  TEsporta_dativa_rec csv;

	TProgind pi(rmoviva.items(), TR("Estrazione dati..."), true, true);	
	for (bool ok = rmoviva.move_first(); ok; ok = rmoviva.move_next())
	{
    if (!pi.addstatus(1))
      break;

		TDate last_data_pag;
    const long  numreg = rmoviva.get(RMI_NUMREG).as_int();
		bool partita_chiusa = test_partita(numreg, last_data_pag, adata);

		if (partita_chiusa)
		{
			if (with_cms)
			{
				TAnal_mov movana;

				movana.read_cgnum(numreg);
				const int rows = movana.rows();

				if (rows > 0)
				{
					for(int i = 1; i <= rows; i++)
					{
						csv.new_rec("");
						const TRectype& rmovana = movana.body()[i];
						const TString80 codcms = rmovana.get("CODCMS");        

						csv.set(0, codcms);
						csv.set(1, rmoviva.get("23.CODCF"));
						csv.set(2, rmoviva.get("20.RAGSOC"));
						char sez = rmovana.get_char("SEZIONE");
						TImporto importo(sez, rmovana.get_real("IMPORTO"));		
						importo.normalize('D');
						csv.set(3, importo.valore());		
						csv.set(6, rmoviva.get("23.DATADOC"));
						csv.set(7, rmoviva.get("23.NUMDOC"));
						csv.set(8, last_data_pag);
					}
					while (rmoviva.move_next())
					{
						const long wnumreg = rmoviva.get(RMI_NUMREG).as_int();
						if (wnumreg != numreg)
						{
							rmoviva.move_prev();
							break;
						}
					}

				}
				else
				{
					const TString & codcms = rmoviva.get("CODCMS").as_string();

					if (codcms.full())
					{
						csv.new_rec("");
						csv.set(0, codcms);
						csv.set(1, rmoviva.get("23.CODCF"));
						csv.set(2, rmoviva.get("20.RAGSOC"));			
						csv.set(3, rmoviva.get(RMI_IMPONIBILE).as_real());		
						csv.set(6, rmoviva.get("23.DATADOC"));
						csv.set(7, rmoviva.get("23.NUMDOC"));
						csv.set(8, last_data_pag);
					}
				}
			}
			else
				if (rmoviva.get("CODCMS").as_string().blank())
				{
					csv.new_rec("");
					csv.set(0, "");
					csv.set(1, rmoviva.get("23.CODCF"));
					csv.set(2, rmoviva.get("20.RAGSOC"));			
					csv.set(3, rmoviva.get(RMI_IMPONIBILE).as_real());		
					csv.set(6, rmoviva.get("23.DATADOC"));
					csv.set(7, rmoviva.get("23.NUMDOC"));
					csv.set(8, last_data_pag);
				}
		}
	} 	
	csv.save_as(path, fmt_text);

#ifdef DBG
	xvt_sys_goto_url(path, "open");
#endif

	TString msg;
	msg << TR("Si conferma l'esportazione definitiva dei movimenti IVA fino al ") << m.get(F_ADATA);
	if (yesno_box(msg))
		set_inviva(rmoviva, adata);	//mette il flag di "INVIVA" alla testata movimento
}

//SET_INVIA: metodo che mette il flag di "INVIVA" alla testata movimento
void TEsporta_dativa_app::set_inviva(TISAM_recordset& rmoviva, const TDate& data) const
{
	long last_numreg = 0L;

	TProgind pi(rmoviva.items(), TR("Impostazione flag Inviata parte IVA..."), true, true);
	TLocalisamfile mov(LF_MOV);

  //scorro il recordset che contiene le righe IVA joinate con i movimenti
	for (bool ok = rmoviva.move_first(); ok; ok = rmoviva.move_next())
	{
    if (!pi.addstatus(1))
      break;
		
    const long curr_numreg = rmoviva.get(RMI_NUMREG).as_int();
		//ad ogni cambio di numreg
    if (curr_numreg != last_numreg)
		{
			TDate last_data_pag;
			bool partita_chiusa = test_partita(curr_numreg, last_data_pag, data);
      //controllo che la partita sia chiusa
			if (partita_chiusa)
			{
				//leggo dal file LF_MOV quello che ha il numero di registrazione selezionato
        mov.put(MOV_NUMREG, curr_numreg);
				int err = mov.read();

        //se riesco a leggerlo setto il flag di invio e aggiorno il movimento
				if (err == NOERR)
				{
					mov.put(MOV_INVIVA, 'X');
					err = mov.rewrite();
				}

        //se non sono riuscito ne' a leggerlo ne' a scriverlo, lo segnalo
				if (err != NOERR)
				{
					TString str;
					str << TR("Impossibile aggiornare il movimento ") << curr_numreg;
					error_box(str);
					break;
				}
			}
			last_numreg = curr_numreg;
		}
	}
}

void TEsporta_dativa_app::main_loop()
{
  TEsporta_dativa_msk m;
  while (m.run() == K_ENTER)
		esporta_righe_iva(m);
}

int ps0713100(int argc, char* argv[])
{
  TEsporta_dativa_app app;
  app.run(argc, argv, TR("Trasferimento dati IVA"));
  return 0;
}