Files correlati : Ricompilazione Demo : [ ] Commento : git-svn-id: svn://10.65.10.50/branches/R_10_00@20884 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			459 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			459 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | ||
| #include <automask.h>
 | ||
| #include <progind.h>
 | ||
| #include <reputils.h>
 | ||
| #include <relation.h>
 | ||
| #include <textset.h>
 | ||
| #include <utility.h>
 | ||
| 
 | ||
| #include "../ca/calib01.h"
 | ||
| #include "../ca/movana.h"
 | ||
| #include "../ca/rmovana.h"
 | ||
| #include "../cg/cglib01.h"
 | ||
| 
 | ||
| #include "ps1001.h"
 | ||
| #include "ps1001100a.h"
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TAutomask
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| class TImporta_movana_mask : public TAutomask
 | ||
| {
 | ||
| protected:
 | ||
|   virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | ||
| 
 | ||
| public:
 | ||
|   TImporta_movana_mask();
 | ||
| };
 | ||
|   
 | ||
| TImporta_movana_mask::TImporta_movana_mask() :TAutomask ("ps1001100a")
 | ||
| {
 | ||
| }  
 | ||
| 
 | ||
| bool TImporta_movana_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | ||
| { 
 | ||
| 	switch (o.dlg())
 | ||
| 	{
 | ||
| 		//giochetto per avere la lista dei files validi nella directory di trasferimento!
 | ||
| 		case F_NAME:
 | ||
| 			if (e == fe_button)
 | ||
| 			{
 | ||
| 				TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32");
 | ||
| 				TFilename path = get(F_PATH);
 | ||
| 				path.add("*.csv");	//files delle testate
 | ||
| 				list_files(path, as.rows_array());
 | ||
| 				TFilename name;
 | ||
| 				FOR_EACH_ARRAY_ROW(as.rows_array(), i, row)
 | ||
| 				{
 | ||
| 					name = *row;
 | ||
| 					*row = name.name();
 | ||
| 				}
 | ||
| 				if (as.run() == K_ENTER)
 | ||
| 				{
 | ||
| 					o.set(as.row(as.selected()));
 | ||
| 				}
 | ||
| 			}
 | ||
| 			break;
 | ||
| //controlli sui campi della testata documento
 | ||
|     case F_DATAREG:
 | ||
|       if ((e == fe_modify || e == fe_close) && !query_mode())
 | ||
|       {
 | ||
|         const TDate datareg = o.get();
 | ||
|         const TEsercizi_contabili ec;
 | ||
|         if (ec.date2esc(datareg) <= 0)
 | ||
|           return error_box(((TEdit_field&)o).get_warning());
 | ||
|         if (e == fe_close && field(F_DATACOMP).empty())
 | ||
|           set(F_DATACOMP, datareg);
 | ||
|       }
 | ||
|       break;
 | ||
|     case F_DATACOMP:
 | ||
|       if ((e == fe_modify || e == fe_close) && !query_mode())
 | ||
|       {
 | ||
|         const TDate datareg = get(F_DATAREG);
 | ||
|         TDate datacomp = o.get();
 | ||
|         if (!datacomp.ok())
 | ||
|           datacomp = datareg;
 | ||
| 
 | ||
|         const bool preventivo = get(F_TIPO).full();
 | ||
|         //i movimenti normali devono avere data competenza nel presente o passato!!
 | ||
|         if (!preventivo && datacomp > datareg)
 | ||
|           return error_box(TR("La data di competenza non puo' superare la data di registrazione"));
 | ||
| 
 | ||
|         const TEsercizi_contabili ec;
 | ||
|         int ae = ec.date2esc(datacomp);
 | ||
| 
 | ||
|         //movimenti preventivi in esercizi futuri
 | ||
|         if (ae <= 0 && preventivo && datacomp > datareg)
 | ||
|           ae = ec.date2esc(datareg) + datacomp.year() - datareg.year();
 | ||
| 
 | ||
|         if (ae > 0)
 | ||
|           set(F_ANNOES, ae, 0x1);
 | ||
|         else
 | ||
|           return error_box(((TEdit_field&)o).get_warning());
 | ||
| 
 | ||
|         const int ar = ec.date2esc(datareg);
 | ||
|         const int ap = ec.pred(ar);
 | ||
|         
 | ||
|         //preventivi un anno indietro, nel presente o nel futuro
 | ||
|         if (preventivo)
 | ||
|         {
 | ||
|           if (ae < ap)
 | ||
|             return error_box(FR("La data di competenza non pu<70> precedere l'esercizio %d"), ap);
 | ||
|         }
 | ||
|         else  //normali solo un anno indietro o nel presente
 | ||
|         {
 | ||
|           if (ae != ar && ae != ap)
 | ||
|             return error_box(FR("La data di competenza deve appartenere all'esercizio in corso o al precedente"));
 | ||
|         }
 | ||
| 
 | ||
|       }
 | ||
|       break;
 | ||
|     case F_DATAFCOMP:
 | ||
|       if (e == fe_modify || e == fe_close)
 | ||
|       {
 | ||
|         const TDate datacomp = get(F_DATACOMP);
 | ||
|         const TDate datafcomp = o.get();
 | ||
|         if (datafcomp.ok())
 | ||
|         {
 | ||
|           if (datafcomp < datacomp)
 | ||
|             return error_box(((TEdit_field&)o).get_warning());
 | ||
|         }
 | ||
|         else
 | ||
|           o.set(datacomp.string()); //se la data fine competenza viene lasciata vuota -> e' uguale alla datacomp
 | ||
|       }
 | ||
|       
 | ||
|       break;
 | ||
| 		default:
 | ||
| 			break;
 | ||
| 	}
 | ||
|   return true;
 | ||
| }
 | ||
|  
 | ||
| /////////////////////////////////////////////////////////////
 | ||
| //	Recordset specifici per i dati da trasferire
 | ||
| /////////////////////////////////////////////////////////////
 | ||
| class TImporta_movana_recordset : public TCSV_recordset
 | ||
| {
 | ||
|   char _sep_field;
 | ||
| 
 | ||
|   protected:
 | ||
|     virtual TRecnotype new_rec(const char* buf = NULL);    
 | ||
|   
 | ||
|   public:
 | ||
|     TImporta_movana_recordset(const char * fileName, char sep);
 | ||
| };
 | ||
| 
 | ||
| TRecnotype TImporta_movana_recordset::new_rec(const char* buf)
 | ||
| {
 | ||
|   TToken_string str(256,'\t'); //nuovo record tab separator
 | ||
| 
 | ||
|   if(buf && *buf)
 | ||
|   {
 | ||
|     bool apici = false;
 | ||
| 
 | ||
|     for (const char* c = buf; *c ; c++)
 | ||
|     {
 | ||
|       if (*c == '"')
 | ||
|       {
 | ||
|         apici = !apici;
 | ||
|       }
 | ||
|       else
 | ||
|       {
 | ||
|         if (*c == _sep_field)  //tipo di separatore dei campi che si trova nel record di origine
 | ||
|         {
 | ||
|           if (!apici)
 | ||
|             str << str.separator();
 | ||
|           else
 | ||
|             str << *c;
 | ||
|         }
 | ||
|         else
 | ||
|           str << *c;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   const TRecnotype n = TText_recordset::new_rec(str);
 | ||
| 
 | ||
|   if (n >= 0)
 | ||
|     row(n).separator(str.separator());
 | ||
|   
 | ||
|   return n;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TImporta_movana_recordset::TImporta_movana_recordset(const char * filename, char sep_field)
 | ||
|                         : TCSV_recordset("CSV(;)"), _sep_field(sep_field)  //separatore campi
 | ||
| {
 | ||
|   load_file(filename);
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////
 | ||
| // TSkeleton_application
 | ||
| ///////////////////////////////////////
 | ||
| class TImporta_movana : public TSkeleton_application
 | ||
| {
 | ||
| 	virtual bool check_autorization() const { return false; }
 | ||
|   virtual const char * extra_modules() const { return "ca"; }
 | ||
| 
 | ||
| 	TImporta_movana_mask* _msk;
 | ||
| 
 | ||
| protected:
 | ||
| 
 | ||
| public:           
 | ||
|   virtual bool create();
 | ||
|   virtual bool destroy();
 | ||
|   virtual void main_loop();
 | ||
| 	bool transfer(const TFilename& file);
 | ||
|  
 | ||
|   TImporta_movana() {};
 | ||
| };
 | ||
| 
 | ||
| bool TImporta_movana::transfer(const TFilename& file)
 | ||
| {
 | ||
|   //roba dalla maschera
 | ||
|   //parametri di importazione
 | ||
|   const char sep_field = _msk->get(F_SEP_FIELD)[0]; //separatore dei campi
 | ||
|   const char sep_dec = _msk->get(F_SEP_DEC)[0]; //separatore decimali
 | ||
|   //parametri del movana
 | ||
|   const long numreg = _msk->get_long(F_NUMREGCA);
 | ||
|   const int annoes = _msk->get_int(F_ANNOES);
 | ||
|   const TDate datareg = _msk->get_date(F_DATAREG);
 | ||
|   const TDate datacomp = _msk->get_date(F_DATACOMP);
 | ||
|   const TDate datafcomp = _msk->get_date(F_DATAFCOMP);
 | ||
|   const bool autofcomp = _msk->get_bool(F_AUTOFCOMP);
 | ||
|   const TString descrizione = _msk->get(F_DESCR);
 | ||
|   const char tipomov = _msk->get(F_TIPO)[0];
 | ||
|   const TString4 codcaus = _msk->get(F_CODCAUS);
 | ||
|   const real ori_totimp = _msk->get_real(F_TOTMOV);
 | ||
|   const char ori_totsez = _msk->get(F_TOTMOV_SEZ)[0];
 | ||
| 
 | ||
| 
 | ||
|   //crea il recordset sul file di input utilizzando il separatore
 | ||
|   TImporta_movana_recordset s(file, sep_field);
 | ||
|   const long recset_items = s.items();
 | ||
| 
 | ||
|   //un po' di roba iniziale
 | ||
|   TProgind pi(s.items(),"Importazione movimento in corso ...",true,true);
 | ||
|   TLog_report log("ERRORI DI TRASFERIMENTO");
 | ||
|   int curr_line = 0;
 | ||
| 
 | ||
|   //testata
 | ||
|   //-------
 | ||
|   //movimento analitico che sar<61> generato
 | ||
|   TAnal_mov movana;
 | ||
|   //il movana esisteva gi<67> o <20> nuovo?
 | ||
|   const int err = movana.read(numreg);
 | ||
|   //se esisteva gi<67> deve accoppare tutte le righe visto che le sostituir<69>
 | ||
|   if (err == NOERR)
 | ||
|     movana.destroy_rows(LF_RMOVANA);
 | ||
|   else
 | ||
|     movana.put(MOVANA_NUMREG, numreg);
 | ||
| 
 | ||
|   movana.put(MOVANA_DATAREG, datareg);
 | ||
|   movana.put(MOVANA_DATACOMP, datacomp);
 | ||
|   movana.put(MOVANA_DATAFCOMP, datafcomp);
 | ||
|   movana.put(MOVANA_ANNOES, annoes);
 | ||
|   movana.put(MOVANA_DESCR, descrizione);
 | ||
|   movana.put(MOVANA_TIPOMOV, tipomov);
 | ||
|   movana.put(MOVANA_CODCAUS, codcaus);
 | ||
|   movana.put(MOVANA_AUTOFCOMP, autofcomp);
 | ||
| 
 | ||
|   TImporto totale;
 | ||
|   //giro su tutti i record del recordset per importarli; ogni record <20> una riga
 | ||
|   //TRACCIATO RECORD all'ultima moda (21/09/2010): codcms/cdc/importo/sezione/gr/co/sott/fase (valido per crpa e dinamica)
 | ||
|   //righe analitiche
 | ||
|   //----------------
 | ||
|   for (bool ok = s.move_first(); ok; ok = s.move_next())
 | ||
|   {
 | ||
|     if (!pi.addstatus(1)) 
 | ||
|       break;
 | ||
|     curr_line ++;
 | ||
| 
 | ||
|     //prende i dati dal record di input del file csv
 | ||
|     //----------------------------------------------
 | ||
|     //CODCMS ci deve essere e va maiuscolizzato; se non c'<27> va segnalato sul log..
 | ||
|     //..ed impedir<69> la write del movana
 | ||
|     TString80 codcms = s.get(0).as_string();
 | ||
|     if (codcms.blank())
 | ||
|     {
 | ||
|       //controllo necessario e decisivo per evitare l'errore dovuto all'ultimo 'a capo' che pretendeva una riga ulteriore
 | ||
|       if (curr_line < recset_items)
 | ||
|       {
 | ||
|         TString msg;
 | ||
|         msg.format("Manca la commessa nella riga %ld", curr_line);
 | ||
|         log.log(2, msg);
 | ||
|       }
 | ||
|       continue;
 | ||
|     }
 | ||
|     codcms.upper();
 | ||
|     //altra modifica all'ultima moda: se c'<27> un '_' in realt<6C> vorrebbe un '/' (21/09/2010)
 | ||
|     codcms.replace('_', '/');
 | ||
| 
 | ||
|     //CDC ci deve essere e va maiuscolizzato; se non c'<27> va segnalato sul log..
 | ||
|     //..ed impedir<69> la write del movana
 | ||
|     TString80 cdc = s.get(1).as_string();
 | ||
|     if (cdc.blank())
 | ||
|     {
 | ||
|       TString msg;
 | ||
|       msg.format("Manca la sede nella riga %ld", curr_line);
 | ||
|       log.log(2, msg);
 | ||
|       continue;
 | ||
|     }
 | ||
|     cdc.upper();
 | ||
| 
 | ||
|     //IMPORTO (inizialmente come stringa x poter fare le replace); se nullo va segnalato..
 | ||
|     //..ma niente bloccaggio della write
 | ||
|     TString80 str_importo = s.get(2).as_string();
 | ||
|     if (sep_dec == ',')
 | ||
|     {
 | ||
|       str_importo.strip(".");  //togle il separatore delle migliaia
 | ||
|       str_importo.replace(',','.'); //sostituisce il separatore decimale
 | ||
|     }
 | ||
|     else
 | ||
|       str_importo.strip(",");
 | ||
| 
 | ||
|     const real importo = str_importo;
 | ||
|     /*if (importo == ZERO)
 | ||
|     {
 | ||
|       TString msg;
 | ||
|       msg.format("Importo nullo nella riga %ld", curr_line);
 | ||
|       log.log(0, msg);
 | ||
|     }*/
 | ||
| 
 | ||
|     //SEZIONE
 | ||
|     TString8 str_sezione = s.get(3).as_string();
 | ||
|     if (str_sezione.blank())
 | ||
|     {
 | ||
|       TString msg;
 | ||
|       msg.format("Manca la sezione nella riga %ld", curr_line);
 | ||
|       log.log(2, msg);
 | ||
|       continue;
 | ||
|     }
 | ||
|     str_sezione.upper();
 | ||
|     const char sezione = str_sezione[0];
 | ||
| 
 | ||
|     //CONTO
 | ||
|     const int gr = s.get(4).as_int();
 | ||
|     const int co = s.get(5).as_int();
 | ||
|     const long so = s.get(6).as_int();
 | ||
|     TString80 conto;
 | ||
|     conto.format("%03d%03d%06ld", gr, co, so);
 | ||
|     if (conto.blank())
 | ||
|     {
 | ||
|       TString msg;
 | ||
|       msg.format("Manca il conto nella riga %ld", curr_line);
 | ||
|       log.log(2, msg);
 | ||
|       continue;
 | ||
|     }
 | ||
| 
 | ||
|     //FASE ci pu<70> essere e va maiuscolizzata;
 | ||
|     TString80 fase = s.get(7).as_string();
 | ||
|     /*if (fase.blank())
 | ||
|     {
 | ||
|       TString msg;
 | ||
|       msg.format("Manca la fase nella riga %ld", curr_line);
 | ||
|       log.log(2, msg);
 | ||
|       continue;
 | ||
|     }*/
 | ||
|     fase.upper();
 | ||
| 
 | ||
|     //riempie la riga analitica
 | ||
|     //-------------------------
 | ||
|     //nuova riga del movana (sfrutta il fatto che <20> un multiple rectype)
 | ||
|     TRectype& rmovana = movana.new_row();
 | ||
| 
 | ||
|     rmovana.put(RMOVANA_DESCR, "Riga importata");
 | ||
|     rmovana.put(RMOVANA_CODCONTO, conto);
 | ||
|     rmovana.put(RMOVANA_CODCMS, codcms);
 | ||
|     rmovana.put(RMOVANA_CODCCOSTO, cdc);
 | ||
|     rmovana.put(RMOVANA_CODFASE, fase);
 | ||
|     rmovana.put(RMOVANA_SEZIONE, sezione);
 | ||
|     rmovana.put(RMOVANA_IMPORTO, importo);
 | ||
|     //aggiorna anche il totale documento..
 | ||
|     TImporto importo_riga(sezione, importo);
 | ||
|     totale += importo_riga;
 | ||
|   }
 | ||
| 
 | ||
|   //completa la testata
 | ||
|   //-------------------
 | ||
|   totale.normalize();
 | ||
|   const char totsez = totale.sezione();
 | ||
|   const real totimp = totale.valore();
 | ||
| 
 | ||
|   //controllo sul totmov in caso di riscrittura
 | ||
|   if (ori_totimp != totimp || (ori_totimp == ZERO && ori_totsez != totsez))
 | ||
|   {
 | ||
|     TString str_totimp;
 | ||
|     str_totimp << totimp;
 | ||
|     TString str_ori_totimp;
 | ||
|     str_ori_totimp << ori_totimp;
 | ||
|     TString msg;
 | ||
|     msg.format("Il totale movimento originale e' %s %c, quello importato e' %s %c.\n"
 | ||
|                "Registrare il movimento con il totale delle righe importate?", 
 | ||
|                (const char*)str_totimp, totsez, (const char*)str_ori_totimp, ori_totsez);
 | ||
|     if (!yesno_box(msg))
 | ||
|       log.log(2, "Totale movimento originale NON coincidente con quello importato !");
 | ||
|   }
 | ||
|   movana.put(MOVANA_SEZIONE, totale.sezione());
 | ||
|   movana.put(MOVANA_TOTDOC, totale.valore());
 | ||
| 
 | ||
|   //solo se non ci sono errori procede alla registrazione del movimento
 | ||
| 	const int items = log.recordset()->items();
 | ||
|   if (items > 0)
 | ||
|     log.preview();
 | ||
|   else
 | ||
|   {
 | ||
|     TLocalisamfile fmovana(LF_MOVANA);
 | ||
|     int err = movana.rewrite_write(fmovana);
 | ||
|     if (err != NOERR)
 | ||
|       error_box("Impossibile registrare il movimento analitico !");
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| bool TImporta_movana::create()
 | ||
| {
 | ||
|   _msk = new TImporta_movana_mask();
 | ||
|   return TSkeleton_application::create();
 | ||
| }
 | ||
| 
 | ||
| bool TImporta_movana::destroy()
 | ||
| {
 | ||
| 	delete _msk;
 | ||
|   return TApplication::destroy();
 | ||
| }
 | ||
| 
 | ||
| void TImporta_movana::main_loop()
 | ||
| {
 | ||
|   KEY	tasto;
 | ||
| 	tasto = _msk->run();
 | ||
|   TConfig& cfg = ca_config();
 | ||
|   const bool use_pdcc =  cfg.get_bool("UsePdcc");
 | ||
|   if (use_pdcc)
 | ||
|   {
 | ||
|     if (tasto == K_ENTER)
 | ||
|     {
 | ||
|       //genero il nome del file da caricare
 | ||
|       TFilename name = _msk->get(F_PATH);
 | ||
|       name.add(_msk->get(F_NAME));
 | ||
| 		  if (transfer(name))
 | ||
| 		  {
 | ||
|         message_box(TR("Elaborazione completata"));
 | ||
| 		  }
 | ||
|     }
 | ||
|   }
 | ||
|   else
 | ||
|     error_box("Il programma richiede che sia impostato l'uso del piano dei conti contabile in analitica!");
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TImporta_movana& app() { return (TImporta_movana&) main_app(); }
 | ||
| 
 | ||
| 
 | ||
| int ps1001100 (int argc, char* argv[])
 | ||
| {
 | ||
|   TImporta_movana main_app;
 | ||
|   main_app.run(argc, argv, TR("Importazione movimento analitico da CSV"));
 | ||
|   return true;
 | ||
| } |