#include <applicat.h>
#include <automask.h>
#include <execp.h>
#include <filetext.h>
#include <progind.h>
#include <printer.h>
#include <sort.h>
#include <utility.h>

#include "dt0.h"
#include "dt0400a.h"

#include "clifo.h"
#include "comuni.h"
#include "doc.h"
#include "rdoc.h"

#include "..\cg\cglib01.h"
#include "..\ve\velib.h"

// TAutomask

class TDT2Doc_mask : public TAutomask
{
protected:
  bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
  TDT2Doc_mask();
  virtual ~TDT2Doc_mask(){};
};
  
TDT2Doc_mask::TDT2Doc_mask() :TAutomask ("dt0400a")
{
}  

bool TDT2Doc_mask::on_field_event(TOperable_field& f, TField_event e, long jolly)
{ 
  return TRUE;
}

// TFile_text

class TDT2Doc_file: public TFile_text
{ 
protected:
  virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str);

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

void TDT2Doc_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str)
{
  const TString code(s.get(0));
  TString valore = str;
  if (code == "_UPPERCASE")
  {
    valore.upper(); 
  }
  else NFCHECK("Macro non definita: %s", (const char *)code);
  str = valore;
} 

HIDDEN bool browse_file_handler(TMask_field& f, KEY k)
{
  if (k == K_F9)
  {  
    FILE_SPEC fs; memset(&fs, 0, sizeof(FILE_SPEC));
    strcpy(fs.type, "");
    strcpy(fs.name, f.get());
    xvt_fsys_get_default_dir(&fs.dir);
    xvt_fsys_save_dir();
    if (xvt_dm_post_file_open(&fs, TR("Selezione file")) == FL_OK)
    {       
      TFilename n;
      xvt_fsys_convert_dir_to_str(&fs.dir, n.get_buffer(n.size()), n.size());
      n.add(fs.name);
      f.set(n);
    }
    xvt_fsys_restore_dir();
    f.set_focus();
  }
  
  return TRUE;
}


// TSkeleton_application

class TDT2Doc : public TSkeleton_application
{
	TDT2Doc_mask*		_msk;
	TDT2Doc_file*		_trasfile;
	TLocalisamfile* _clifor;
	
  TRelation*      _rel;
  TCursor*        _cur;
  TProgind*       _prog;  
	TAssoc_array*		_array_clifor;
	TAssoc_array*		_confditte;
	TAssoc_array*		_confdoc;
	TAssoc_array*		_totalilordi;
	TAssoc_array*		_castelletto;
	TAssoc_array*		_primariga;
	TString80				_cms, _condpag, _codnum, _negozio, _speseacc1, _speseacc2, _scontofin;
	bool						_contnetto;

public:           
  bool print_header(const TFilename& percorso);

  void print_line(const TString& rigastampa = "");
  void print_footer();
	virtual bool create();
  virtual bool destroy();
  virtual void main_loop();
	bool import_clifor(const TFilename& percorso, const char tipocf);
	bool import_documenti(const TFilename& percorso, const bool doc_attivi);
	bool elabora_documenti(const bool doc_attivi);
	const long get_nextcodcf(const char tipocf);
	bool load_conf_ditte();
	bool load_conf_doc();
	char check_negozio(const TFilename& percorso);
	bool error_msg(const TString& msg, const TString16& causale, const int numdoc, const TString& codice);
	void rename_file(const TFilename& percorso);
	int get_numdoc(const TString& numdocrif, const TDate datadoc, const TString& _codnum, const TString& tipodoc, const long codcf);
	int add_riga_doc(TDocumento* doc, TConfig& config);

  TDT2Doc() {}
};

TDT2Doc& app() { return (TDT2Doc&) main_app(); }

bool TDT2Doc::print_header(const TFilename& percorso)

{
	if (printer().open())
	{
		TDate oggi(TODAY);
		TPrintrow row;
		TString256 rigastampa;
		rigastampa = "IMPORTAZIONE FILE ";
		rigastampa << percorso;
		rigastampa.center_just(80);
		row.put(rigastampa);
  	row.put("@>", 1);
  	row.put("Pag. @#", 65);
  	printer().setheaderline(2, row);
		rigastampa = "";
		rigastampa.fill('-',80);
		row.reset();
		row.put(rigastampa);
		printer().setheaderline(3, row);
		return TRUE;
	}
	else
		return error_box(TR("Errore in apertura stampante."));	
}		

void TDT2Doc::print_line(const TString& rigastampa)
{                        
	TPrintrow row;
	row.reset();
	if (rigastampa.not_empty())
	{                    
		row.put((const char*) rigastampa);
		printer().print(row);			
	}
}

void TDT2Doc::print_footer()
{                     
	printer().formfeed();
	printer().close();
}

char TDT2Doc::check_negozio(const TFilename& percorso)
{
	char tipocf = 'E';
  TConfig config_studio(CONFIG_STUDIO, "dt");
	TString80 nomefile(percorso.name());
	TString80 estensione(percorso.ext());
	const int fine = nomefile.find(estensione);
	if (fine > 0)
		nomefile = nomefile.sub(0,fine-1);
	if (_confditte->is_key(nomefile))
	{
		TToken_string& config = (TToken_string&) _confditte->find(nomefile);
		TString16 dittastr(config.get());
		_cms = config.get();
		_codnum = config.get();
		tipocf = config.get_char();
		if (_codnum.empty())
		{
			error_box(TR("Attenzione: manca la numerazione corrispondente al negozio. Completare la tabella prima di effettuare il trasferimento"));
			tipocf = 'E';
		}
		else
		{
			const long ditta = atol(dittastr);
			if (prefix().exist(ditta))    
			{
				_negozio = nomefile.sub(2);
				load_conf_doc();
				if (!set_firm(ditta))
					tipocf = 'E';
			}
			else
			{
				error_box(TR("Attenzione: non esiste la ditta %ld; trasferimento annullato"), ditta);
				tipocf = 'E';
			}
		}
	}
	else
	{
		error_box(TR("Attenzione: manca la corrispondenza negozio - ditta; trasferimento annullato"));
		tipocf = 'E';
	}
	return tipocf;
}

bool TDT2Doc::load_conf_ditte()
{
  TConfig config_studio(TConfig(CONFIG_STUDIO, "dt"));
	TToken_string workstring;
  _confditte->destroy();
  for (int k = 0; config_studio.exist("ConfDitte", k); k++)
  {
    workstring = config_studio.get("ConfDitte", NULL, k);
		TString16 negozio(workstring.get(0));
		negozio << workstring.get(1);
		const TString16 ditta(workstring.get(2));
		const TString80 cms(workstring.get(3));
		const TString16 codnum(workstring.get(4));
		const char attpass(workstring.get_char());
		TToken_string config;
		config.add(ditta);
		config.add(cms);
		config.add(codnum);
		config.add(attpass);
		_confditte->add(negozio, config);
  }
	return TRUE;
}

bool TDT2Doc::load_conf_doc()
{
  TConfig config_studio = TConfig(CONFIG_STUDIO, "dt");
	TToken_string workstring;
  _confdoc->destroy();
  for (int k = 0; config_studio.exist("ConfDoc", k); k++)
  {
    workstring = config_studio.get("ConfDoc", NULL, k);
		TToken_string chiavedt;
		TString80 negozio = workstring.get(0);
		negozio.trim();
		if (negozio == _negozio)
		{
			chiavedt.add(workstring.get(1));
			chiavedt.add(workstring.get(2));
			TToken_string chiavecampo;
			chiavecampo.add(workstring.get(3));
			chiavecampo.add(workstring.get(4));
			_confdoc->add(chiavedt, chiavecampo);
		}
  }
	_condpag = config_studio.get("CondPag");
	_contnetto = config_studio.get_bool("ContNettoSconto");
	_speseacc1 = config_studio.get("SpeseAcc1");
	_speseacc2 = config_studio.get("SpeseAcc2");
	_scontofin = config_studio.get("ScontoFin");
	return TRUE;
}
                                 
bool TDT2Doc::create()
{
  open_files(LF_CLIFO, 0);
  _msk = new TDT2Doc_mask();
	_msk->set_handler(F_PERCORSO, browse_file_handler);
	_cms = " ";
	_condpag = " ";
	_clifor = new TLocalisamfile(LF_CLIFO);       
	// array delle corrispondenze tra codici clienti
	_array_clifor = new TAssoc_array();
	// array della configurazione negozi/ditte
	_confditte = new TAssoc_array();
	load_conf_ditte();
	// array delle corrispondenze documenti
	_confdoc = new TAssoc_array();
	// verra' caricato quando si e' deciso il negozio
	//load_conf_doc();
	// riepilogo iva per redistribuzione sconto per aliquote
	_totalilordi = new TAssoc_array();
	// castelletto iva per controllo imponibili
	_castelletto = new TAssoc_array();
	// primariga di ogni aliquota
	_primariga = new TAssoc_array();
  return TSkeleton_application::create ();

}


bool TDT2Doc::destroy()
{
	delete _primariga;
	delete _castelletto;
	delete _totalilordi;
	delete _confdoc;
	delete _confditte;
	delete _array_clifor;
	delete _clifor;

	delete _msk;
  return TApplication::destroy();
}

void TDT2Doc::main_loop()
{  
	TString80 percorso;
	KEY	tasto;
	TConfig configfile("dt0400.ini");
  _msk->set(F_PERCORSO,	configfile.get("PERCORSO", "OPZIONI"));
  tasto = _msk->run();
  if (tasto == K_ENTER)
  {
		TFilename percorso(_msk->get(F_PERCORSO));
		const char tipocf = check_negozio(percorso);
		if (tipocf != 'E')

		{
			if (print_header(percorso))
			{
				const bool doc_attivi = tipocf == 'A';
				_trasfile = new TDT2Doc_file(percorso, (doc_attivi ? true, "dt0400a.ini" : "dt0400b.ini"));
				import_clifor(percorso, (doc_attivi ? true, 'C' : 'F'));               
				int error = import_documenti(percorso, doc_attivi);
				configfile.set("PERCORSO", percorso, "OPZIONI");
				delete _trasfile;
				if (!error)
				{
					rename_file(percorso);
					message_box(TR("Importazione documenti completata"));
				}
				else
					message_box(TR("Errori nell'importazione"));
				print_footer();
			}

		}
  }   
}

const long TDT2Doc::get_nextcodcf(const char tipocfchiesto)
{
	TLocalisamfile& clifo = *_clifor;
  long  codcf = 1L ;
	if (tipocfchiesto == 'C')
	{
		if (!clifo.empty())
		{
			clifo.zero() ;
			clifo.setkey(1) ;
			clifo.put(CLI_TIPOCF, 'F');
			clifo.read(_isgteq) ;
			if (clifo.good())
				clifo.prev() ;
			clifo.setstatus(NOERR);
		}
		else clifo.last();
		if (clifo.good())
		{
			const TFixed_string tipocf(clifo.get(CLI_TIPOCF)); 
			if ( tipocf == "C")
			{
				codcf = clifo.get_long(CLI_CODCF);
				if (codcf == 999999)
					clifo.prev();
				codcf = clifo.get_long(CLI_CODCF)+1;
			}
		}               
	}
	else
	{
		clifo.last();
		if (clifo.good())
		{ 
			const TFixed_string tipocf(clifo.get(CLI_TIPOCF)); 
			if ( tipocf == "C")
				codcf = 1;
			else
				codcf = clifo.get_long(CLI_CODCF)+1;
		}               		
	}
	return codcf;
}

bool TDT2Doc::error_msg(const TString& msg, const TString16& causale, const int numdoc, const TString& codice)
{
	TString messaggio;
	TString16 desdoc;
	TToken_string str(causale);
	TString16 tipodoc = str.get(1);
	if (tipodoc == "A")
		desdoc = "Fatt. acc.";
	else if (tipodoc == "B")
		desdoc = "Bolla";
	else if (tipodoc == "D")
		desdoc = "Fatt. diff.";
	messaggio.format("Doc. %s %s, n. %d non trasferito: %s %s", (const char*) causale, (const char*) desdoc, numdoc, (const char*) msg, (const char*) codice);
	print_line(messaggio);
	return TRUE;
}

bool TDT2Doc::import_documenti(const TFilename& percorso, const bool doc_attivi)

{
	// eliminazione files delle elaborazioni precedenti
  TString_array transactions;
	TFilename dtfiles; dtfiles.tempdir();
	dtfiles.add("ditet*.ini");
  list_files(dtfiles, transactions);
  FOR_EACH_ARRAY_ROW(transactions, row, name)
    remove_file(*name);
	TFilename tempname;
	if (doc_attivi)
	  _trasfile->open(percorso, 'r');
	else
	{
		// riordina i record del file di input documenti passivi per ndoc+tiporec
		tempname.temp("", "txt");
		const size_t recordsize = 256;
		char * buf = new char[recordsize];
		ifstream infile(percorso);
		ofstream outfile(tempname);
		TSort s(recordsize);
		s.addsortkey(8, 3);
		s.addsortkey(11, 10);
		s.addsortkey(6, 2);
		s.init();
		while (infile.getline(buf, recordsize) != NULL)
			s.sort(buf);
		s.endsort();
		delete buf;
		const char * outbuf;
		while ((outbuf = s.retrieve()) != NULL)
			outfile << outbuf << endl;
		_trasfile->open(tempname, 'r');
	}
	bool error = elabora_documenti(doc_attivi);
  _trasfile->close();
	if (tempname.exist())
		remove_file(tempname);
	TString80 applicat;
	applicat.format("ve0.exe -1 -i%s", (const char*) dtfiles);
  TExternal_app gestdoc(applicat);
  gestdoc.run();
	return error;
}

int TDT2Doc::get_numdoc(const TString& numdocrif, const TDate datadoc, const TString& _codnum, const TString& tipodoc, const long codcf)
{
	int numdoc = 0;
  TRelation rel(LF_DOC);
  TRectype& curr = rel.curr();
  curr.put(DOC_TIPOCF, "F");
  curr.put(DOC_CODCF, codcf);
  curr.put(DOC_PROVV, "D");
  curr.put(DOC_ANNO, datadoc.year());
  curr.put(DOC_DATADOC, datadoc);
  curr.put(DOC_CODNUM, _codnum);
  TCursor cur(&rel, "", 2, &curr, &curr); 
  const long items = cur.items();
  for (cur = 0; cur.pos() < items; ++cur)
	{
		TString80 ndr = cur.curr().get(DOC_NUMDOCRIF);
		ndr.trim();
		if (ndr == numdocrif)
			numdoc = cur.curr().get_int(DOC_NDOC);
	}
	return numdoc;
}

int TDT2Doc::add_riga_doc(TDocumento* doc, TConfig& config)
{
	TRiga_documento& riga = doc->new_row(config.get(RDOC_TIPORIGA));
	riga.put(RDOC_QTA, config.get(RDOC_QTA));
	riga.put(RDOC_UMQTA,config.get(RDOC_UMQTA));
	riga.put(RDOC_CODIVA, config.get(RDOC_CODIVA));
	riga.put(RDOC_PREZZO, config.get(RDOC_PREZZO));
	return 0;
}

void TDT2Doc::rename_file(const TFilename& percorso)
{
	TFilename newfile;
	const TDate data(TODAY);
	TString str = data.string(full,'-',full,full,amg_date);
	str.strip("-");
	TFilename renamedfiles(percorso);
	renamedfiles << str;
	newfile = renamedfiles;
	renamedfiles << "*.*";
  TString_array listfiles;
  list_files(renamedfiles, listfiles);
	int suffisso = 0;
  FOR_EACH_ARRAY_ROW(listfiles, row, name)
	{
		TString80 namef(*name);
		namef.trim();
		suffisso = atoi(namef.right(1));
	}
	suffisso++;
	newfile << suffisso;
	if (fcopy(percorso, newfile))
		remove_file(percorso);
	TString messaggio;
	messaggio << "Il file " << percorso << " e' stato copiato in " << newfile;
	print_line(messaggio);
}

bool TDT2Doc::elabora_documenti(const bool doc_attivi)
{
	const long dimension = fsize(_trasfile->name());

  TProgind pi(dimension,"Importazione in corso...");
  TConfig* docum=NULL;
	TString256 stampa;
	real* tl;
	int err = NOERR;
	int ntransac=0;
	int nriga=0;
	bool error = FALSE;
	real sconto(ZERO);
	real importodoc(ZERO);
	real percsconto(ZERO);
	int numdoc;
	TString16 causale;
	TDocumento* doc=NULL;

  TRecord_text curr;
  while (_trasfile->read(curr) == NOERR && !pi.iscancelled() && err == NOERR) 
  {
    pi.setstatus(_trasfile->read_file()->tellg());
		if ((curr.type() == "01") || (curr.type()=="06"))// testata documento oppure ho finito i doc. e sono ai clienti
		{
			// verifico il castelletto
			if (!error)
			{
				if (sconto != ZERO && !_contnetto)
				{
					const int ndec = TCurrency::get_firm_dec(false);
					TGeneric_distrib d(sconto, ndec);
					for (tl = (real*) _totalilordi->first_item(); tl != NULL; tl = (real*) _totalilordi->succ_item())
						d.add(*tl);
					real totsconti(ZERO);
					for (tl = (real*) _totalilordi->first_item(); tl != NULL; tl = (real*) _totalilordi->succ_item())
					{
						sconto = d.get();
						const TString& codiva = _totalilordi->get_hashobj()->key();
						TCodiceIVA codiceIVA(codiva);
						codiceIVA.scorpora(sconto, ndec);
						real& imp_calcolato = *tl;
						if (_castelletto->is_key(codiva))
						{
							real& imp_castelletto = (real&) _castelletto->find(codiva);
							codiceIVA.scorpora(imp_calcolato, ndec);
							real diff = imp_calcolato-sconto-imp_castelletto;
							if (sconto != ZERO) 
							{
								if (doc_attivi)
									sconto += diff;
								nriga++;
								docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
								docum->set(RDOC_CHECKED, "X");
								docum->set(RDOC_TIPORIGA, "07");
								docum->set(RDOC_DESCR, "Sconto");
								docum->set(RDOC_PREZZO, sconto.string());
								docum->set(RDOC_CODIVA, codiva);
								docum->set(RDOC_CODCMS, _cms);
								add_riga_doc(doc, *docum);
								totsconti+=sconto;
								if (!doc_attivi)
								{
									nriga++;
									docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
									docum->set(RDOC_CHECKED, "X");
									docum->set(RDOC_TIPORIGA, "01");
									docum->set(RDOC_CODART, codiva);
									docum->set(RDOC_DESCR, "Pareggio sconto");
									docum->set(RDOC_QTA, "1");
									docum->set(RDOC_PREZZO, sconto.string());
									docum->set(RDOC_CODIVA, codiva);
									docum->set(RDOC_CODCMS, _cms);
									add_riga_doc(doc, *docum);
								}
							}
						}
						else
							error = error_msg("incongruenza nel castelletto - iva assente ", causale, numdoc, codiva);
					}
				}
				else
				{
					for (tl = (real*) _totalilordi->first_item(); tl != NULL; tl = (real*) _totalilordi->succ_item())
					{
						const TString& codiva = _totalilordi->get_hashobj()->key();
						TCodiceIVA codiceIVA(codiva);
						real& imp_calcolato = *tl;
						if (_castelletto->is_key(codiva))
						{
							real& imp_castelletto = (real&) _castelletto->find(codiva);
							codiceIVA.scorpora(imp_calcolato, TCurrency::get_firm_dec(true));
							real diff = imp_castelletto-imp_calcolato;
							diff.round(2);
							if (diff != ZERO)
							{
								nriga++;
								docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
								docum->set(RDOC_CHECKED, "X");
								docum->set(RDOC_TIPORIGA, "01");
								docum->set(RDOC_DESCR, "Rettifica");
								docum->set(RDOC_PREZZO, diff.string());
								docum->set(RDOC_QTA, "1");
								docum->set(RDOC_CODIVA, codiva);
								TString& codart = (TString&) _primariga->find(codiva);
								docum->set(RDOC_CODART, codart);
								docum->set(RDOC_CODCMS, _cms);
								add_riga_doc(doc, *docum);
							}
						}
						else
							error = error_msg("incongruenza nel castelletto - iva assente ", causale, numdoc, codiva);
					}
				}
				if ((!doc_attivi) && (doc!=NULL))
				{
					// verifico tabella iva
					TAssoc_array& tabella_iva = doc->tabella_iva();
					TRiepilogo_iva* riepilogo_iva;
					// Scorre tutti gli elementi della tabella IVA del documento (elementi per codice iva)
					for (riepilogo_iva = (TRiepilogo_iva*) tabella_iva.first_item(); riepilogo_iva != NULL; riepilogo_iva = (TRiepilogo_iva*) tabella_iva.succ_item())
					{
						const TString& codiva_riep = riepilogo_iva->cod_iva().codice();
						real& imp_castelletto = (real&) _castelletto->find( codiva_riep);
						real imponibile = riepilogo_iva->imponibile();
						real diff = imp_castelletto-imponibile;
						diff.round(2);
						if (diff != ZERO)
						{
							nriga++;
							docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
							docum->set(RDOC_CHECKED, "X");
							docum->set(RDOC_TIPORIGA, "01");
							docum->set(RDOC_DESCR, "Rettifica");
							docum->set(RDOC_PREZZO, diff.string());
							docum->set(RDOC_QTA, "1");
							docum->set(RDOC_CODIVA, codiva_riep);
							TString& codart = (TString&) _primariga->find(codiva_riep);
							docum->set(RDOC_CODART, codart);
							docum->set(RDOC_CODCMS, _cms);
							add_riga_doc(doc, *docum);
						}
					}
				}

			}
			// chiudo il file precedente
			_totalilordi->destroy();
			_castelletto->destroy();
			_primariga->destroy();
			if (docum != NULL)
			{
				delete docum;
				docum = NULL;
			}
			if (error) // cancello il file perch'e la transazione non e' andata bene
			{
				TFilename dtfile; dtfile.tempdir();
				dtfile.add(format("ditet%03d.ini",ntransac));
				if (dtfile.exist())
					remove_file(dtfile);
			}
			error = FALSE;
			if (curr.type() == "01")
			{
				ntransac++;      
				TFilename dtfile; dtfile.tempdir();
				dtfile.add(format("ditet%03d.ini",ntransac));
				docum = new TConfig(dtfile);
				sconto = ZERO;
				if (doc_attivi)
					numdoc = atoi(curr.get(3));
				else	
					numdoc = 0;
				const TDate datadoc = (TDate) curr.get(4);
				causale = curr.get(10);
				causale << "|";
				causale << curr.get(2);
				causale.trim();
				// cerca sul file di configurazione la corrispondenza causale|tipodoc -> tipodocCAMPO|stato
				if (_confdoc->is_key(causale))
				{
					TToken_string str = (TToken_string&) _confdoc->find(causale);
					const TString16 tipodoc = str.get();	
					if (tipodoc.not_empty())
					{
						TString16 codcfdt;
						codcfdt = curr.get(5);
						if (_array_clifor->is_key(codcfdt))
						{
							TString& codcf = (TString&) _array_clifor->find(codcfdt);
							nriga=0;
							docum->set_paragraph("Transaction");
							docum->set("Action","INSERT");
							docum->set("Mode","AUTO");
							docum->set_paragraph(format("%d",LF_DOC));
							docum->set(DOC_ANNO, datadoc.year());
							docum->set(DOC_PROVV, "D");
							docum->set(DOC_CODNUM, _codnum);
							docum->set(DOC_TIPODOC, tipodoc);
							if (!doc_attivi)
							{
								TString80 numdocrif = curr.get(3);
								numdocrif.strip("/");
								numdocrif.strip("\\");
								numdocrif.strip("-");
								numdocrif.strip("_");
								numdocrif.trim();
								numdoc = get_numdoc(numdocrif, datadoc, _codnum, tipodoc, atol(codcf));
								docum->set(DOC_NUMDOCRIF, numdocrif);
								docum->set(DOC_DATADOCRIF, datadoc);
							}
							if (numdoc != 0)
								docum->set(DOC_NDOC, numdoc);
							docum->set(DOC_DATADOC, datadoc);
							docum->set(DOC_TIPOCF, (doc_attivi ? "C": "F"));
							docum->set(DOC_CODCF, codcf);
							TString16 codpag = curr.get(6);
							codpag.trim();
							const TString16 codpagdt = cache().get("%DTP", codpag, "S4");
							if (codpagdt.blank())
								docum->set(DOC_CODPAG, _condpag);
							else
								docum->set(DOC_CODPAG, codpagdt);
							// istanzio TDocumento per fare le verifiche sul castelletto
							if (doc != NULL)
								delete doc;
							doc = new TDocumento('D', datadoc.year(), _codnum, 0);
						  doc->set_tipo(tipodoc);
						}
						else
							error = error_msg("cliente non identificato", causale, numdoc, "");
					}
					else
						error = error_msg("manca la corrispondenza sul tipo documento", causale, numdoc, "");
				}
				else
					error = error_msg("manca la corrispondenza sul tipo documento", causale, numdoc, "");
			}
		}		
		else if (curr.type() == "02") // castelletto iva
		{
			TString16 tabiva = curr.get(5);
			tabiva.trim();
			tabiva.rpad(4);
			TString str = curr.get(6);
			str.trim();
			tabiva << str;
			tabiva.rpad(7);
			str = curr.get(7);
			str.trim();
			tabiva << str;
			const TString16 codiva = cache().get("%DTI", tabiva, "S4");
			if (codiva.not_empty())
			{
				real importo = (real) curr.get(9);
				importo=importo/100;
				real* oggetto = new real(importo);                                
				_castelletto->add(codiva,(TObject*)oggetto);

				// creo le righe di doc. perche' nei doc.passivi non ci sono
				if (!doc_attivi)
				{
					real imposta = (real) curr.get(10);
					imposta=imposta/100;	
					nriga++;
					docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
					docum->set(RDOC_CHECKED, "X");
					docum->set(RDOC_TIPORIGA, "01");
					docum->set(RDOC_CODART, codiva);
					docum->set(RDOC_CODCMS, _cms);
					if (!_primariga->is_key(codiva))
					{	
						TString* ca = new TString(codiva);
						_primariga->add(codiva,(TObject*)ca);
					}		
					docum->set(RDOC_DESCR, "Riga documento ");
					real qta = 1;
					TString str = qta.string();
					docum->set(RDOC_QTA, str);
					docum->set(RDOC_UMQTA, "N.");
					TCodiceIVA codiceIVA((const char*) codiva);
					docum->set(RDOC_CODIVA, codiva);
					real impostacalc = codiceIVA.imposta(importo);
					str = importo.string();
					docum->set(RDOC_PREZZO, str);
					add_riga_doc(doc, *docum);
					if (imposta != impostacalc) //inserisco riga di rettifica IVA
					{
						nriga++;
						docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
						docum->set(RDOC_CHECKED, "X");
						docum->set(RDOC_TIPORIGA, "15");
						docum->set(RDOC_CODART, codiva);
						docum->set(RDOC_CODCMS, _cms);
						if (!_primariga->is_key(codiva))
						{	
							TString* ca = new TString(codiva);
							_primariga->add(codiva,(TObject*)ca);
						}		
						docum->set(RDOC_DESCR, "Rettifica IVA ");
						real qta = 1;
						TString str = qta.string();
						docum->set(RDOC_QTA, str);
						docum->set(RDOC_UMQTA, "N.");
						TCodiceIVA codiceIVA((const char*) codiva);
						docum->set(RDOC_CODIVA, codiva);
						real diff = imposta - impostacalc;
						str = diff.string();
						docum->set(RDOC_PREZZO, str);
						add_riga_doc(doc, *docum);
					}
					real importoriga = importo+impostacalc;
					if (_totalilordi->is_key(codiva))
					{
						real& importor = (real&)_totalilordi->find(codiva);			
						importor+=importoriga;
					}
					else
					{
						real* oggetto = new real(importoriga);                                
						_totalilordi->add(codiva,(TObject*)oggetto);
					}
				}
			}
			else
				error = error_msg("manca la corrispondenza iva" ,causale, numdoc, tabiva);
		}
		else if (curr.type() == "03") // piede documento (serve per leggere lo sconto)
		{
			importodoc = (real) curr.get(5);
			importodoc = importodoc/100;
			sconto = (real) curr.get(6);
			sconto = sconto/100;
			importodoc = importodoc + sconto;
			percsconto = sconto/importodoc;

			if (!doc_attivi)
			{
				TString str;
				// sconto finanziario
				real scontofin = (real) curr.get(9);
				real importoriga = scontofin/100;
				if (importoriga != ZERO)
				{
					const TString16 codiva = cache().get("SPP", _scontofin, "S3");
					nriga++;
					docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
					docum->set(RDOC_CHECKED, "X");
					docum->set(RDOC_TIPORIGA, "02");
					docum->set(RDOC_CODART, _scontofin);
					docum->set(RDOC_CODCMS, _cms);
					docum->set(RDOC_DESCR, "Sconto finanziario");
					real qta = 1;
					str = qta.string();
					docum->set(RDOC_QTA, str);
					docum->set(RDOC_UMQTA, "N.");
					TCodiceIVA codiceIVA((const char*) codiva);
					docum->set(RDOC_CODIVA, codiva);
					real imposta = codiceIVA.imposta(importoriga);
					str = importoriga.string();
					docum->set(RDOC_PREZZO, str);
					add_riga_doc(doc, *docum);
				}
				// spese accessorie 1
				char segno = curr.get(10)[0];
				importoriga = (real) curr.get(11);
				importoriga = importoriga/100;
				if (segno == '-')
					importoriga = -importoriga;
				if (importoriga != ZERO)
				{
					TString16 tabiva = curr.get(12);
					tabiva.trim();
					tabiva.rpad(4);
					str = curr.get(13);
					str.trim();
					tabiva << str;
					tabiva.rpad(7);
					str = curr.get(14);
					str.trim();
					tabiva << str;
					const TString16 codiva = cache().get("%DTI", tabiva, "S4");
					nriga++;
					docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
					docum->set(RDOC_CHECKED, "X");
					docum->set(RDOC_TIPORIGA, "02");
					docum->set(RDOC_CODART, _speseacc1);
					docum->set(RDOC_CODCMS, _cms);
					if (!_primariga->is_key(codiva))
					{	
						TString* ca = new TString(_speseacc1);
						_primariga->add(codiva,(TObject*)ca);
					}		
					docum->set(RDOC_DESCR, "Spese accessorie 1");
					real qta = 1;
					str = qta.string();
					docum->set(RDOC_QTA, str);
					docum->set(RDOC_UMQTA, "N.");
					TCodiceIVA codiceIVA((const char*) codiva);
					docum->set(RDOC_CODIVA, codiva);
					real imposta = codiceIVA.imposta(importoriga);
					str = importoriga.string();
					docum->set(RDOC_PREZZO, str);
					add_riga_doc(doc, *docum);
					if (_contnetto)
					{
						real importo = importoriga+imposta;
						if (_totalilordi->is_key(codiva))
						{
							real& importoi = (real&)_totalilordi->find(codiva);			
							importoi+=importo;					}
						else
						{
							real* oggetto = new real(importo);                                
							_totalilordi->add(codiva,(TObject*)oggetto);
						}
					}
					else //aggiungo la rettifica per far quadrare il castelletto
					{
						nriga++;
						docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
						docum->set(RDOC_CHECKED, "X");
						docum->set(RDOC_TIPORIGA, "01");
						docum->set(RDOC_DESCR, "Rettifica spese acc. 1");
						importoriga = -importoriga;
						str = importoriga.string();
						docum->set(RDOC_PREZZO, str);
						docum->set(RDOC_QTA, "1");
						docum->set(RDOC_CODIVA, codiva);
						TString& codart = (TString&) _primariga->find(codiva);
						docum->set(RDOC_CODCMS, _cms);
						add_riga_doc(doc, *docum);
					}
				}
				// spese accessorie 2
				segno = curr.get(15)[0];
				importoriga = (real) curr.get(16);
				importoriga = importoriga/100;
				if (segno =='-')
					importoriga = -importoriga;
				if (importoriga != ZERO)
				{
					TString16 tabiva = curr.get(17);
					tabiva.trim();
					tabiva.rpad(4);
					TString str = curr.get(18);
					str.trim();
					tabiva << str;
					tabiva.rpad(7);
					str = curr.get(19);
					str.trim();
					tabiva << str;
					const TString16 codiva = cache().get("%DTI", tabiva, "S4");
					nriga++;
					docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
					docum->set(RDOC_CHECKED, "X");
					docum->set(RDOC_TIPORIGA, "02");
					docum->set(RDOC_CODART, _speseacc2);
					docum->set(RDOC_CODCMS, _cms);
					if (!_primariga->is_key(codiva))
					{	
						TString* ca = new TString(_speseacc2);
						_primariga->add(codiva,(TObject*)ca);
					}		
					docum->set(RDOC_DESCR, "Spese accessorie 2");
					real qta = 1;
					str = qta.string();
					docum->set(RDOC_QTA, str);
					docum->set(RDOC_UMQTA, "N.");
					TCodiceIVA codiceIVA((const char*) codiva);
					docum->set(RDOC_CODIVA, codiva);
					real imposta = codiceIVA.imposta(importoriga);
					str = importoriga.string();
					docum->set(RDOC_PREZZO, str);
					add_riga_doc(doc, *docum);
					if (_contnetto)
					{
						real importo = importoriga+imposta;
						if (_totalilordi->is_key(codiva))
						{
							real& importoi = (real&)_totalilordi->find(codiva);			
							importoi+=importo;					}
						else
						{
							real* oggetto = new real(importo);                                
							_totalilordi->add(codiva,(TObject*)oggetto);
						}
					}
					else // aggiungo la rettifica per far quadrare il castelletto
					{
						nriga++;
						docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
						docum->set(RDOC_CHECKED, "X");
						docum->set(RDOC_TIPORIGA, "01");
						docum->set(RDOC_DESCR, "Rettifica spese acc. 2");
						importoriga = -importoriga;
						str = importoriga.string();
						docum->set(RDOC_PREZZO, str);
						docum->set(RDOC_QTA, "1");
						docum->set(RDOC_CODIVA, codiva);
						TString& codart = (TString&) _primariga->find(codiva);
						docum->set(RDOC_CODCMS, _cms);
						add_riga_doc(doc, *docum);
					}
				}
			}
		}
		else if ((!error) && (curr.type() == "04" || curr.type() == "05")) // righe documento
		{
			TString16 tabiva = curr.get(11);
			tabiva.trim();
			tabiva.rpad(4);
			TString str = curr.get(12);
			str.trim();
			tabiva << str;
			tabiva.rpad(7);
			str = curr.get(19);
			str.trim();
			tabiva << str;
			const TString16 codiva = cache().get("%DTI", tabiva, "S4");
			if (codiva.not_empty())
			{
				nriga++;
				docum->set_paragraph(format("%d,%d",LF_RIGHEDOC, nriga));
				TString80 codart = curr.get(6);
				codart.trim();
				docum->set(RDOC_CHECKED, "X");
				docum->set(RDOC_TIPORIGA, "01");
				docum->set(RDOC_CODART, codart);
				docum->set(RDOC_CODCMS, _cms);
				if (!_primariga->is_key(codiva))
				{	
					TString* ca = new TString(codart);
					_primariga->add(codiva,(TObject*)ca);
				}		
				const TRectype& recanamag = cache().get(LF_ANAMAG, codart);
				if (!recanamag.empty())
					docum->set(RDOC_CODARTMAG,codart);
				docum->set(RDOC_DESCR, curr.get(7));
				real qta = (real) curr.get(8);
				qta = qta/1000;
				TString str = qta.string();
				docum->set(RDOC_QTA, str);
				docum->set(RDOC_UMQTA, curr.get(9));
				real prezzo = (real) curr.get(10);
				prezzo = prezzo/100;
				TCodiceIVA codiceIVA((const char*) codiva);
				docum->set(RDOC_CODIVA, codiva);
				real importoriga = prezzo*qta;
				codiceIVA.scorpora(importoriga, TCurrency::get_firm_dec(true));
				importoriga.round(TCurrency::get_firm_dec());
				prezzo = importoriga/qta;
				prezzo.round(TCurrency::get_firm_dec(true));
				str = prezzo.string();
				docum->set(RDOC_PREZZO, str);
				add_riga_doc(doc, *docum);
				importoriga=prezzo*qta;
				importoriga = codiceIVA.lordo(importoriga, TCurrency::get_firm_dec(true));
				if (_totalilordi->is_key(codiva))
				{
					real& importo = (real&)_totalilordi->find(codiva);			
					importo+=importoriga;
				}
				else
				{
					real* oggetto = new real(importoriga);                                
					_totalilordi->add(codiva,(TObject*)oggetto);
				}
			}
			else
				error = error_msg("manca la corrispondenza iva" ,causale, numdoc, tabiva);
		}
	}
	// chiudo l'ultimo file
	if (docum != NULL)
		delete docum;
	if (doc != NULL)
		delete doc;

	if (error) // cancello il file perch'e la transazione non e' andata bene
	{
		TFilename dtfile; dtfile.tempdir();
		dtfile.add(format("ditet%03d.ini",ntransac));
		if (dtfile.exist())
			remove_file(dtfile);

	}
	return error;

}

bool TDT2Doc::import_clifor(const TFilename& percorso, const char tipocf)

{
// cache per i comuni
	TRecord_cache cache_comuni(LF_COMUNI, 2);
  _trasfile->open('r');
	const long dimension = fsize(percorso);
  TProgind pi(dimension,"Importazione in corso...");
  TRelation rel(LF_CLIFO);
  TRectype& reccli = rel.curr();
	TLocalisamfile& clifo = rel.lfile();
	_array_clifor->destroy();
	TString256 stampa;

	int err = NOERR;
  TRecord_text curr;
  while (_trasfile->read(curr) == NOERR && !pi.iscancelled() && err == NOERR) 
  {
    pi.setstatus(_trasfile->read_file()->tellg());
		if (curr.type() == "06")
		{
			TString16 paiv = curr.get(11);  
			TString80 cofi = curr.get(12);  
			TString16 statopaiv = "  ";
			TString80 ragsoc = curr.get(4);
			ragsoc << curr.get(5);	
			if (!cofi.blank())
			{
				rel.lfile().setkey(4);
				reccli.zero();
				reccli.put(CLI_TIPOCF, tipocf);
				reccli.put(CLI_COFI, cofi);
				if (reccli.read(rel.lfile())!=NOERR)
				{
					reccli.zero();
					const long codcf = get_nextcodcf(tipocf);
					reccli.put(CLI_TIPOCF, tipocf);
					reccli.put(CLI_CODCF, codcf);
					reccli.put(CLI_RAGSOC, ragsoc);
					err = reccli.write(rel.lfile());
					if (err != NOERR)
						message_box(TR("Errore in scrittura clienti/fornitori %d"), err);
				}
			}  
			else if (!paiv.blank())
			{
				rel.lfile().setkey(5);
				reccli.zero();
				reccli.put(CLI_TIPOCF, tipocf);
				reccli.put(CLI_STATOPAIV, statopaiv);
				reccli.put(CLI_PAIV, paiv);
				if (reccli.read(rel.lfile())!=NOERR)
				{
					reccli.zero();
					const long codcf = get_nextcodcf(tipocf);
					reccli.put(CLI_TIPOCF, tipocf);
					reccli.put(CLI_CODCF, codcf);
					reccli.put(CLI_RAGSOC, ragsoc);
					err = reccli.write(rel.lfile());
					if (err != NOERR)
						message_box(TR("Errore in scrittura clienti/fornitori %d"), err);
				}
			}
			_trasfile->autosave(rel, curr);
			TString80 str;
			// comune
			TString80 dencom = curr.get(9);
			dencom.trim();
			dencom.upper();
			TRectype reccom = cache_comuni.get(dencom);
			str = reccom.get(COM_DENCOM);
			str.trim();
			if (str == dencom)
				reccli.put(CLI_COMCF, reccom.get(COM_COM));
			else
			{
				reccli.put(CLI_COMCF, " ");
				reccli.put(CLI_LOCCF, dencom);
				stampa = "Cliente ";
				stampa << reccli.get(CLI_CODCF);
				stampa << " - comune " << dencom << " non trovato";
				print_line(stampa);
			}
			rel.rewrite();
			// aggiungo il cliente all'array per ritrovarlo sui documenti
			const TString16 codcf = rel.curr().get(CLI_CODCF);
			const TString16 codcfdt = curr.get(3);
			if (!_array_clifor->is_key(codcfdt))
				_array_clifor->add(codcfdt, codcf);
		}
	}
  _trasfile->close();
	return TRUE;
}

int dt0400(int argc, char* argv[])
{
  TDT2Doc main_app;
  main_app.run(argc, argv, TR("Importazione documenti"));
  return TRUE;
}