Files correlati : Ricompilazione Demo : [ ] Commento :prima implementazione ripartizioni costo/ricavo a saldi (da provare del tutto!) git-svn-id: svn://10.65.10.50/trunk@19232 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			336 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			336 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | |
| #include <automask.h>
 | |
| #include <defmask.h>
 | |
| #include <recarray.h>
 | |
| #include <relation.h>
 | |
| 
 | |
| #include "../cg/cglib01.h"
 | |
| #include "calib01.h"
 | |
| #include "calib02.h"
 | |
| 
 | |
| #include "ca2.h"
 | |
| #include "ca2200a.h"
 | |
| 
 | |
| #include "movana.h"
 | |
| #include "rmovana.h"
 | |
| #include "rip.h"
 | |
| #include "rrip.h"
 | |
| 
 | |
| //--------------------------------------------------------------------
 | |
| //  MASCHERA
 | |
| //--------------------------------------------------------------------
 | |
| class TRib_movanal_msk : public TAnal_report_mask
 | |
| {
 | |
| protected:
 | |
|   virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | |
| 
 | |
| public:
 | |
|   TRib_movanal_msk();
 | |
| };
 | |
| 
 | |
| 
 | |
| bool TRib_movanal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | |
| {
 | |
|   switch (o.dlg())
 | |
|   {
 | |
| 	case F_DATAINI:
 | |
| 	case F_DATAFIN:
 | |
| 		if (e == fe_close)
 | |
| 		{
 | |
| 			const int anno = get_int(F_ANNO);
 | |
| 
 | |
| 			TEsercizi_contabili esc;	//..le date devono essere incluse nell'esercizio selezionato!
 | |
| 			const TDate data(o.get());
 | |
| 			if (!data.empty() && esc.date2esc(data) != anno)
 | |
| 				return error_box(TR("La data deve appartenere all'anno selezionato"));
 | |
| 		}
 | |
| 		break;
 | |
| 
 | |
|   default: 
 | |
|     break;
 | |
|   }
 | |
|   return TAnal_report_mask::on_field_event(o, e, jolly);
 | |
| }
 | |
| 
 | |
| TRib_movanal_msk::TRib_movanal_msk() : TAnal_report_mask("ca2200a")
 | |
| {
 | |
| }
 | |
| 
 | |
| //--------------------------------------------------------------------
 | |
| //  APPLICAZIONE
 | |
| //--------------------------------------------------------------------
 | |
| class TRib_movanal_app : public TSkeleton_application
 | |
| {
 | |
|   TCache_ripartizioni _cache_rip;
 | |
|   bool _definitivo;
 | |
| 
 | |
| protected:
 | |
|   virtual void main_loop();
 | |
| 
 | |
|   bool elabora_righe(TAnal_mov& anal_mov, const TRecord_array& input_rows, TRecord_array& output_rows);
 | |
|   bool ripartizione(const TAnal_ripartizioni_batch& rrip, const TRectype& rec, TRecord_array& output_rows);
 | |
|   bool pareggio(TAnal_mov& anal_mov, const TAnal_ripartizioni_batch& rrip, const TRectype& rec, TRecord_array& output_rows);
 | |
| 
 | |
| public:
 | |
|   bool elabora_movimento(TAnal_mov& anal_mov, const bool esplodi);
 | |
| 	TRib_movanal_app(){}
 | |
| };
 | |
| 
 | |
| 
 | |
| bool TRib_movanal_app::pareggio(TAnal_mov& anal_mov, const TAnal_ripartizioni_batch& rrip, const TRectype& rec, 
 | |
|                                 TRecord_array& output_rows)
 | |
| {
 | |
|   bool ho_pareggiato = false;
 | |
| 
 | |
|   TImporto totdoc(anal_mov.get_char(MOVANA_SEZIONE), anal_mov.get_real(MOVANA_TOTDOC));
 | |
| 
 | |
|   const TImporto imp_riga(rec.get_char(RMOVANA_SEZIONE), rec.get_real(RMOVANA_IMPORTO));
 | |
| 
 | |
|   totdoc -= imp_riga;
 | |
|   totdoc.normalize();
 | |
|   anal_mov.put(MOVANA_TOTDOC, totdoc.valore());
 | |
|   anal_mov.put(MOVANA_SEZIONE, totdoc.sezione());
 | |
| 
 | |
|   //aggiunge la riga originale alle righe di output (e' un pareggio)
 | |
|   const int original_nriga = output_rows.rows() + 1;
 | |
|   TRectype* newrec = new TRectype(rec);
 | |
|   newrec->put(RMOVANA_NUMRIG, original_nriga);
 | |
|   output_rows.add_row(newrec);
 | |
| 
 | |
|   //swappa la sezione e la manda al ripartitore in modo da generare righe con la sezione rovesciata rispetto a quella..
 | |
|   //..originale ed ottenere cosi' il pareggio
 | |
|   TRectype swaprec(rec);
 | |
|   swaprec.put(RMOVANA_SEZIONE, imp_riga.sezione() == 'D' ? 'A' : 'D');
 | |
|   ho_pareggiato = ripartizione(rrip, swaprec, output_rows);
 | |
| 
 | |
|   //elimina il codcontoori da tutte le righe aggiunte per il pareggio
 | |
|   for (int i = output_rows.rows(); i > original_nriga; i--)
 | |
|     output_rows.row(i, false).zero(RMOVANA_CODCONTORI);
 | |
| 
 | |
|   return ho_pareggiato;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRib_movanal_app::ripartizione(const TAnal_ripartizioni_batch& rrip, const TRectype& rec, TRecord_array& output_rows)
 | |
| {
 | |
|   bool ho_ripartito = false;
 | |
|   // Importo totale da distribuire arrotondato ai decimali della valuta di conto
 | |
|   TGeneric_distrib distrib(rec.get_real(RMOVANA_IMPORTO), TCurrency::get_firm_dec());
 | |
| 
 | |
|   // Calcolo tutte le percentuali da ripartire
 | |
|   int i;
 | |
|   const int righe_ripartizione = rrip.rows();
 | |
|   for (i = 1; i <= rrip.rows(); i++)
 | |
|   {
 | |
|     const real importanza_riga = rrip[i].get_real(RRIP_RIPARTO);
 | |
|     distrib.add(importanza_riga);
 | |
|   }
 | |
| 
 | |
|   for (i = 1; i <= righe_ripartizione; i++)
 | |
|   {
 | |
|     const real imp = distrib.get(); // Legge la quota da distribuire
 | |
| 
 | |
| 	  if (imp != ZERO)
 | |
| 	  {
 | |
| 		  TRectype* newrec = new TRectype(rec);
 | |
| 		  newrec->put(RMOVANA_NUMRIG, output_rows.rows() + 1);
 | |
| 		  newrec->put(RMOVANA_IMPORTO, imp);  //e la mette nella nuova riga
 | |
| 		  //poi copia i valori dei campi cdc,cms,fsc,in quelli di tipo ori (nello stesso record)
 | |
| 		  ca_copia_campo(rec, RMOVANA_CODCCOSTO, *newrec, RMOVANA_CODCCORI);
 | |
| 		  ca_copia_campo(rec, RMOVANA_CODCMS,    *newrec, RMOVANA_CODCMSORI);
 | |
| 		  ca_copia_campo(rec, RMOVANA_CODFASE,   *newrec, RMOVANA_CODFASEORI);
 | |
| 		  ca_copia_campo(rec, RMOVANA_CODCONTO,  *newrec, RMOVANA_CODCONTORI);
 | |
| 		  //e mette nei campi std i valori che trova nelle righe ripartizione
 | |
| 		  ca_copia_campo(rrip[i], RRIP_CODCOSTO, *newrec, RMOVANA_CODCCOSTO);
 | |
| 		  ca_copia_campo(rrip[i], RRIP_CODCMS,   *newrec, RMOVANA_CODCMS);
 | |
| 		  ca_copia_campo(rrip[i], RRIP_CODFASE,  *newrec, RMOVANA_CODFASE);
 | |
| 		  ca_copia_campo(rrip[i], RRIP_CODCONTO, *newrec, RMOVANA_CODCONTO);
 | |
| 
 | |
| 		  output_rows.add_row(newrec);
 | |
|       ho_ripartito = true;
 | |
| 	  } //if(imp!=ZERO)...
 | |
|   } //for(i=1;i<=righe_ripartizione...
 | |
| 
 | |
|   return ho_ripartito;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRib_movanal_app::elabora_righe(TAnal_mov& anal_mov, const TRecord_array& input_rows, TRecord_array& output_rows)
 | |
| {
 | |
|   bool ho_cambiato_qualchecosa = false;
 | |
| 
 | |
|   const int annoes = anal_mov.get_int(MOVANA_ANNOES);
 | |
|   const char tipomov = anal_mov.get_char(MOVANA_TIPOMOV);
 | |
| 
 | |
|   for (int r = 1; r <= input_rows.rows(); r++)
 | |
|   {
 | |
|     const TRectype& rec = input_rows.row(r);
 | |
|     TAnal_bill zio(rec);
 | |
|     const int rmovana_indbil = zio.indicatore_bilancio();
 | |
| 
 | |
|     //ripartizione batch: passa il conto perche' per prima cosa provera' una ripartizione di tipo 'P' con chiave 3; se non..
 | |
|     //..ci riuscira', provera' da solo (metodi della TCache_ripartizioni) le ripartizioni di tipo 'B' con chiave 4.
 | |
|     const TAnal_ripartizioni_batch& rrip = _cache_rip.righe(zio, annoes, rmovana_indbil, tipomov);
 | |
|     const char tiporip = rrip.tiporip();
 | |
| 
 | |
|     //ci sono righe di ripartizione
 | |
|     const int righe_ripartizione = rrip.rows();
 | |
|     bool ripartisci = righe_ripartizione > 0;
 | |
| 
 | |
|     //se ci sono righe di ripartizione/pareggio si va a ripartire!
 | |
|     if (ripartisci)  
 | |
|     {
 | |
|       switch (tiporip)
 | |
|       {
 | |
|       //procedura di ripartizione batch 'B' originale; se tiporip=='P' invece ci vuole il pareggio del movana
 | |
|       case 'B':
 | |
|         ho_cambiato_qualchecosa = ripartizione(rrip, rec, output_rows);
 | |
|         break;
 | |
|       case 'P':
 | |
|         ho_cambiato_qualchecosa = pareggio(anal_mov, rrip, rec, output_rows);
 | |
|         break;
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     else  //if(ripartisci...   nessuna riga di ripartizione->aggiungo la riga input all'output
 | |
|     {
 | |
|       TRectype* newrec = new TRectype(rec);
 | |
|       newrec->put(RMOVANA_NUMRIG, output_rows.rows() + 1);
 | |
|       output_rows.add_row(newrec);
 | |
|     }
 | |
|   } //for(int r=1; r<=input_rows.rows()...
 | |
|   return ho_cambiato_qualchecosa;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRib_movanal_app::elabora_movimento(TAnal_mov& anal_mov, const bool esplodi)
 | |
| {
 | |
|   TRecord_array& input_rows = anal_mov.body();  //record_array con le righe del mov_anal (INPUT)
 | |
|   bool do_rewrite = false;
 | |
| 
 | |
| //Per prima cosa prende le righe del movimento su RMOVANA e le ricompatta..
 | |
|   TRecord_array compact_rows = input_rows; //record array con le righe compattate da creare con la..
 | |
|   compact_rows.destroy_rows();             //..implode_rows(); intanto le azzera per sicurezza
 | |
| 
 | |
|   if (esplodi)
 | |
|   {
 | |
|     //Imploditore
 | |
|     ca_implode_rows(input_rows, compact_rows);
 | |
|     //..poi lo riesplode in tutte le righe che possono nascere secondo le regole delle ripartizioni!
 | |
|     TRecord_array output_rows = input_rows; //crea il record_array di output come copia dell'INPUT..
 | |
|     output_rows.destroy_rows();             //..e poi lo pulisce
 | |
| 
 | |
|     //Esploditore
 | |
|     if (elabora_righe(anal_mov, compact_rows, output_rows))
 | |
|     {
 | |
|       input_rows = output_rows; //rimette i record elaborati negli originali
 | |
|       do_rewrite = true;
 | |
|     }
 | |
|     
 | |
|     if (_definitivo)  //se l'elaborazione e' definitiva...
 | |
|     {
 | |
|       anal_mov.put(MOVANA_BLOCCATO, 'X'); //..mette bloccato = X nella testata del movimento
 | |
|       do_rewrite = true;
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     //Imploditore
 | |
|     do_rewrite = ca_implode_rows(input_rows, compact_rows);
 | |
|     if (do_rewrite)
 | |
|     {
 | |
|       input_rows = compact_rows; // rimette i record compattati negli originali
 | |
|       anal_mov.update_totdoc();   //aggiorna il totale movana (necessarip per ripartizioni a pareggio, di sicurezza per le altre)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return do_rewrite; //se ha elaborato delle righe e/o e' una elaborazione definitiva, riscrive la..
 | |
| }
 | |
| 
 | |
| static bool ripartisci_callback(const TRelation& rel, void* pJolly)
 | |
| {
 | |
|   TRib_movanal_app& app = *(TRib_movanal_app*)pJolly;
 | |
|   const long numreg = rel.curr().get_long(MOVANA_NUMREG);
 | |
|   TAnal_mov anal_mov(numreg);
 | |
|   //se va tutto bene riscrive l'intero movimento analitico con conseguente ricalcolo saldi
 | |
|   if (app.elabora_movimento(anal_mov, true))
 | |
|     anal_mov.rewrite(rel.lfile());
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| static bool compatta_callback(const TRelation& rel, void* pJolly)
 | |
| {
 | |
|   TRib_movanal_app& app = *(TRib_movanal_app*)pJolly;
 | |
|   const long numreg = rel.curr().get_long(MOVANA_NUMREG);
 | |
|   TAnal_mov anal_mov(numreg);
 | |
|   //se va tutto bene riscrive l'intero movimento analitico con conseguente ricalcolo saldi
 | |
|   if (app.elabora_movimento(anal_mov, false))
 | |
|     anal_mov.rewrite(rel.lfile());
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void TRib_movanal_app::main_loop()
 | |
| {
 | |
|   TRib_movanal_msk mask;
 | |
|   while (mask.run() == K_ENTER)
 | |
|   { 
 | |
|     //deve scandire il file MOVANA con chiave 2 (per data e numero di registrazione)
 | |
|     TRelation rel_movana(LF_MOVANA);
 | |
|     TRectype darec(LF_MOVANA), arec(LF_MOVANA);
 | |
|     const TDate & dal = mask.get_date(F_DATAINI);
 | |
|     darec.put(MOVANA_DATACOMP, dal);
 | |
| 		const TDate & al = mask.get_date(F_DATAFIN);
 | |
|     arec.put(MOVANA_DATACOMP, al);
 | |
| 		_cache_rip.set_esercizio(mask.get_int(F_ANNO));
 | |
| 
 | |
| 		const TString & tipo = mask.get(F_CLASSEMOV);
 | |
| 		TString filter;
 | |
| 
 | |
| 		if (tipo.blank())
 | |
| 			filter = "BLOCCATO!=\"X\"";
 | |
| 		else
 | |
| 			if (tipo == "N")
 | |
| 				filter = "(BLOCCATO!=\"X\")&&(TIPOMOV==\"\")";
 | |
| 			else
 | |
| 				filter = "(BLOCCATO!=\"X\")&&(TIPOMOV!=\"\")";
 | |
|     TCursor cur_movana(&rel_movana, filter, 2, &darec, &arec);
 | |
|     const long items = cur_movana.items();
 | |
|     if (items > 0)
 | |
|     {
 | |
|       bool run = yesno_box(FR("Si desidera elaborare %ld movimenti?"), items);
 | |
|       //e' una compattazione?
 | |
|       const bool compattazione = mask.get_bool(F_COMPATTA);
 | |
|       //se e' un ripartizione potrebbe essere definitiva!
 | |
|       if (!compattazione)
 | |
|       {
 | |
|         // avvisa l'utente scapestrato che se fa una ripartizione definitiva
 | |
|         // blocchera' i movimenti che processa e non potra' piu' tornare indietro
 | |
|         _definitivo = mask.get_bool(F_DEFINITIVO);
 | |
|         if (run && _definitivo)
 | |
|           run = yesno_box(TR("E' stata selezionata l'elaborazione definitiva\nSi desidera proseguire?"));
 | |
|       }
 | |
| 
 | |
|       //Presa la decisione si parte! Tenetevi forte...
 | |
|       if (run)
 | |
|       {
 | |
|         if (compattazione)
 | |
|           cur_movana.scan(compatta_callback, this, TR("Compattamento movimenti..."));
 | |
|         else
 | |
|           cur_movana.scan(ripartisci_callback, this, TR("Ripartizione movimenti..."));
 | |
|       } //if(run)...
 | |
|     }
 | |
|     else
 | |
|       message_box(TR("Non ci sono movimenti da elaborare nel periodo selezionato"));
 | |
|   } 
 | |
| }
 | |
| 
 | |
| int ca2200(int argc, char* argv[])
 | |
| {
 | |
|   TRib_movanal_app app;
 | |
|   app.run(argc, argv, TR("Ripartizione movimenti di analitica"));
 | |
|   return 0;
 | |
| }
 |