Files correlati : ba3.exe cg2.exe ve0.exe ve6.exe Ricompilazione Demo : [ ] Commento : il periodo di non accettazione effetti viene applicato per i seguenti tipi di movimento tratta ricevuta bancaria cessione paghero tratta accettata (SRM) git-svn-id: svn://10.65.10.50/branches/R_10_00@21491 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1996 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1996 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include "cgpagame.h"
 | |
| 
 | |
| #include <diction.h>
 | |
| #include <msksheet.h>
 | |
| #include <recarray.h>
 | |
| #include <tabutil.h>
 | |
| 
 | |
| #include "cg2100.h"
 | |
| 
 | |
| #include <cfven.h>
 | |
| #include <mov.h>
 | |
| #include <partite.h>
 | |
| #include <scadenze.h>
 | |
| #include <pagsca.h>
 | |
| 
 | |
| // se settato, si usa per rate nuove l'intervallo rate default (letto da tab. pagamenti)
 | |
| #define USE_DEFAULT_INT_RATE  1
 | |
| #define PERC_DECIMALS 2
 | |
| 
 | |
| inline void swap(int& x, int& y) {int tmp = x; x = y; y = tmp; }
 | |
| 
 | |
| int TPagamento::_rata_ifield(int n, int f) const
 | |
| {            
 | |
|   int v = 0;
 | |
|   _rate.row(n).get(f, v);
 | |
|   return v;
 | |
| }                            
 | |
| 
 | |
| long TPagamento::_rata_lfield(int n, int f) const
 | |
| {                                     
 | |
|   long v = 0;
 | |
|   _rate.row(n).get(f, v);
 | |
|   return v;
 | |
| }                            
 | |
| 
 | |
| real TPagamento::_rata_rfield(int n, int f) const
 | |
| {                                     
 | |
|   real v;
 | |
|   _rate.row(n).get(f, v);
 | |
|   return v;
 | |
| }                            
 | |
| 
 | |
| TDate TPagamento::_rata_dfield(int n, int f) const
 | |
| {                                     
 | |
|   const TDate v = _rata_sfield(n, f);
 | |
|   return v;
 | |
| }                                 
 | |
| 
 | |
| /* Funzione sgradita al nuovo C ed anche a Guy: static bleah!
 | |
| const char* TPagamento::_rata_sfield(int n, int f) const
 | |
| {                                     
 | |
|   TToken_string& t = (TToken_string&)_rate[n];
 | |
| 	TString & s = get_tmp_string(30);
 | |
| 
 | |
| 	s = t.get(f);
 | |
|   return s;
 | |
| }                                 
 | |
| */
 | |
| 
 | |
| // Funzione digeribile dal nuovo C
 | |
| const TString& TPagamento::_rata_sfield(int n, int f) const
 | |
| {                                     
 | |
|   const TToken_string& t = _rate.row(n);
 | |
|   TString& kak = get_tmp_string();
 | |
|   t.get(f, kak);
 | |
|   return kak;
 | |
| }                                 
 | |
| 
 | |
| void TPagamento::set_inizio(const TDate& d, bool rispetta_date)
 | |
| {
 | |
|   if (_rate.items() == 0)
 | |
|     return;
 | |
|     
 | |
|   _datadoc = d;                                          
 | |
|   _inizio = d;             
 | |
|   _inited = true;
 | |
|     // aggiusta _inizio secondo INSCAD; vedi mese commerciale etc.                         
 | |
|   if (_inscad == 'M')
 | |
|     _inizio.set_end_month();
 | |
|   else
 | |
|   {
 | |
|     if (_inscad == 'F' && _mcomm && _inizio.day() == 31) 
 | |
|      _inizio.set_day(30);
 | |
|   }          
 | |
| 
 | |
|   TDate data(rispetta_date ? data_rata(0) : _inizio); // Aggiusta data iniziale con i giorni prima rata
 | |
|   if (!rispetta_date)
 | |
|     next_scad(data, scad_rata(0), _mcomm, 0);
 | |
| 
 | |
|   bool dummy;
 | |
|   recalc_rate(0, false, NULL, NULL, data.string(), NULL, NULL, _rdiff, _mcomm, dummy);    
 | |
| }
 | |
| 
 | |
| void TPagamento::set_intervallo_rate(int in)
 | |
| {
 | |
|   if (_mcomm  && (in % 30) != 0)
 | |
|   {
 | |
|     if (yesno_box("E' specificato \"mese commerciale\". Si desidera annullarlo?")) 
 | |
|      _mcomm = false;
 | |
|     else 
 | |
|       return; 
 | |
|   }
 | |
|   for (int i = 1; i < n_rate(); i++)
 | |
|   {       
 | |
|     TToken_string& ts = rata(i);
 | |
|     ts.add(in, 0);    
 | |
|   } 
 | |
|   _int_rate = in;
 | |
|   _dirty = true;                    
 | |
| }
 | |
| 
 | |
| void TPagamento::set_mese_commerciale(bool v, int& sscad)
 | |
| {
 | |
|   _dirty = false;
 | |
|   if (_mcomm == v) return;  
 | |
|   if (sscad < 0) sscad = 30;
 | |
|   
 | |
|   if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1);
 | |
|   set_intervallo_rate(sscad);
 | |
|   
 | |
|   _mcomm = v; 
 | |
| }        
 | |
| 
 | |
| void TPagamento::set_rate_differenziate(int v)
 | |
| {                           
 | |
|   _dirty = false;
 | |
|   if ((int(_rdiff) ^ v) == 2) return; 
 | |
|   
 | |
|   if (v == 2 && (100 % n_rate()) == 0)
 | |
|   {
 | |
|     int p = 100 / n_rate();
 | |
|     for (int i = _tpr < 4 ? 0 : 1; i < n_rate(); i++)
 | |
|     {
 | |
|       TToken_string& tt = rata(i);
 | |
|       tt.add(p,1);
 | |
|     }
 | |
|   }                           
 | |
|   _rdiff = (v != 2);
 | |
|   _dirty = true;
 | |
| }
 | |
| 
 | |
| void TPagamento::set_tipo_prima_rata(int v, int sscad)
 | |
| {                           
 | |
|   _dirty = false;
 | |
|   if (_tpr == v) return;      
 | |
|   
 | |
|   if (!_inited)
 | |
|   {
 | |
|     if (v < 4  && _tpr > 3)
 | |
|     {
 | |
|       for (int i = n_rate() - 1; i > 0; i--)
 | |
|       {
 | |
|         TToken_string& tt = rata(i);
 | |
|         tt.add(scad_rata(i-1),0);
 | |
|         tt.add(tipo_rata(i-1),2);
 | |
|         tt.add(ulc_rata(i-1),5);
 | |
|       }
 | |
|       _rate.destroy(0, true);
 | |
|     }
 | |
|     else if ( _tpr < 4 && v > 3)                    
 | |
|     {   
 | |
|       TToken_string* ttn = new TToken_string(32);
 | |
|       ttn->add(0,  0);
 | |
|       ttn->add(0,  1);
 | |
|       ttn->add(1,  2);
 | |
|       ttn->add("", 3);
 | |
|       ttn->add("", 4);
 | |
|       ttn->add("", 5); 
 | |
|       _rate.insert(ttn,0);
 | |
|       for (int i = 0; i < (n_rate()-1); i++)
 | |
|       {
 | |
|         TToken_string& tt = rata(i);   
 | |
|         tt.add(scad_rata(i+1),0);
 | |
|         tt.add(tipo_rata(i+1),2);
 | |
|         tt.add(ulc_rata(i+1), 5);
 | |
|       }             
 | |
|       if (n_rate() == 2 && scad_rata(1) == 0)
 | |
|       {                             
 | |
|         // l'unica rata aveva scadenza 0; ci mettiamo n.giorni default
 | |
|         TToken_string& tt = rata(1);                                  
 | |
|         tt.add(_int_rate, 0);
 | |
|       }
 | |
|      }  
 | |
|    }                           
 | |
|    else
 | |
|    {
 | |
|      if ((_tpr > 3 && (v > 0 && v < 3)) || (v > 3 && (_tpr > 0 && _tpr < 3)))
 | |
|      {
 | |
|        // swap _firstr and _secndr
 | |
|        real tmp(_firstr);
 | |
|        _firstr = _secndr;
 | |
|        _secndr = tmp;
 | |
|        tmp = _firstl;
 | |
|        _firstl = _secndl;
 | |
|        _secndl = tmp;
 | |
|      }
 | |
|    }
 | |
|   _tpr = v;    
 | |
|   _dirty = true;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TPagamento::set_numero_rate(int n, int sscad, int rdiff)
 | |
| {                         
 | |
|   if (n <= 0) return;
 | |
|   _dirty = false;
 | |
|   
 | |
|   const int nr = n_rate();
 | |
|   const int first = _tpr < 4 ? 0 : 1;
 | |
|   real sum = 0.0;
 | |
|   int i = 0;
 | |
|   bool inv = in_valuta();
 | |
|                                   
 | |
|   // diciamo che gli diciamo il numero giusto                                
 | |
|   if (first == 1 && n < 2) return;
 | |
|   
 | |
|   int nact = first == 1 ? n - 1 : n;  
 | |
|   
 | |
|   real p = CENTO / real(nact); 
 | |
|   p.round(PERC_DECIMALS);
 | |
|   
 | |
|   if (_inited || (!_inited && rdiff == 1))   // se e' inited rdiff e' 2 per forza
 | |
|   { 
 | |
|     real tot = _inited ? importo_da_dividere(false) : CENTO;
 | |
|     real oot;
 | |
|     if (inv) 
 | |
|       oot = importo_da_dividere(true);
 | |
|       
 | |
|     if (nact == 1)
 | |
|     {
 | |
|       if (_inited) 
 | |
|       {
 | |
|         set_imprata(first, tot, false); 
 | |
|         if (inv) set_imprata(first, oot, true);  
 | |
|       }
 | |
|       set_percrata(first, CENTO);
 | |
|       if (_inited && _tpr > 0 && _tpr < 4)
 | |
|       {                 
 | |
|         set_imprata(first, importo_rata(first,false) + importo_da_non_dividere(false), false);
 | |
|         if (inv)
 | |
|           set_imprata(first, importo_rata(first,true) + importo_da_non_dividere(true), true);
 | |
|       }
 | |
|       i = first + 1; // per rimozione successiva
 | |
|     }
 | |
|     else
 | |
|     {   
 | |
| 
 | |
|       if (nr == first + 1)
 | |
|       {                               
 | |
|         // suddividi equamente e riaggiusta la percentuale di conseguenza  
 | |
|         real div  = tot / real(nact);     
 | |
|         real oiv;
 | |
|         if (inv)
 | |
|           oiv = oot/real(nact);
 | |
|         if (_inited)
 | |
|         {
 | |
|           div.round(_roundlit);
 | |
|           if (inv) oiv.round(_roundval);
 | |
|         }
 | |
|         real perc = (CENTO * div) / tot;
 | |
|         
 | |
|         real rem(tot); 
 | |
|         real oem(oot);
 | |
|         real p(perc);
 | |
|         
 | |
|         p.round(PERC_DECIMALS);
 | |
|         
 | |
|         for (i = first; i < n; i++)
 | |
|         {
 | |
|           if (i > first)
 | |
|           { 
 | |
|             int scd = sscad == -1 ? scad_rata(first) : sscad;
 | |
| #ifdef USE_DEFAULT_INT_RATE
 | |
|             if (scd == 0) 
 | |
|               scd = _int_rate;
 | |
| #endif            
 | |
|             add_rata(perc, scd, tipo_rata(0), ulc_rata(0));
 | |
|           }
 | |
|           if (_inited)
 | |
|           {
 | |
|             set_imprata (i, div, false); 
 | |
|             rem -= importo_rata(i,false);
 | |
|             if (inv)
 | |
|             {
 | |
|               set_imprata (i, oiv, true); 
 | |
|               oem -= importo_rata(i,true); 
 | |
|             }
 | |
|           }   
 | |
|           else 
 | |
|             rem -= p;
 | |
|           set_percrata(i, perc);
 | |
|         }
 | |
|         if (_inited && _tpr > 0 && _tpr < 4)
 | |
|         {                 
 | |
|           set_imprata(0, importo_rata(0,false) + importo_da_non_dividere(false), false);
 | |
|           if (inv)
 | |
|             set_imprata(0, importo_rata(0,true) + importo_da_non_dividere(true), true);
 | |
|         }
 | |
|         if (rem != ZERO || oem != ZERO)
 | |
|         {
 | |
|           if (_inited)
 | |
|           {
 | |
|             real r(importo_rata(first,false) + rem); 
 | |
|             real oldr;
 | |
|             if (inv) oldr = importo_rata(first,true) + oem;
 | |
|             set_imprata(first, r, false);
 | |
|             if (inv) set_imprata(first, oldr, true);
 | |
| 
 | |
|             if (_inited && _tpr > 0 && _tpr < 4)
 | |
|             {
 | |
|               r -= importo_da_non_dividere(false);
 | |
|               if (inv) oldr -= importo_da_non_dividere(true);  
 | |
|             }
 | |
|             set_percrata(first, CENTO * r / tot);
 | |
|           }          
 | |
|           else
 | |
|           {
 | |
|             const real r(perc_rata(first) + rem);
 | |
|             
 | |
|             set_percrata(first, r);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       else if (nr > first + 1)
 | |
|       {
 | |
|         // dalla prima nota e' abilitato solo se rdiff == 2
 | |
|         // e' selezionato UGUALI: devo: lasciare la prima
 | |
|         // rata com'e' (a meno che non ce ne sia una sola) e 
 | |
|         // suddividere il resto dell'importo tra le altre
 | |
|         real rfirst = _inited ? importo_rata(0,false) : perc_rata(0);
 | |
|         real ofirst;
 | |
|         if (inv) 
 | |
|           ofirst = importo_rata(0,true);
 | |
|         if (_inited && _tpr > 0 && _tpr < 4)
 | |
|         {
 | |
|           rfirst -= importo_da_non_dividere(false);  
 | |
|           if (inv)  
 | |
|             ofirst -= importo_da_non_dividere(true);
 | |
|         }                                                       
 | |
|         real rest = tot - (_tpr >= 4 ? ZERO : rfirst);
 | |
|         real oest;
 | |
|         if (inv)
 | |
|           oest = oot - (_tpr >= 4 ? ZERO : ofirst);
 | |
|         real div = rest / real(nact - (first > 0 ? 0 : 1));
 | |
|         real oiv;
 | |
|         if (inv)
 | |
|           oiv = oest / real(nact - (first > 0 ? 0 : 1));
 | |
|         if (_inited)
 | |
|         {
 | |
|           div.round(_roundlit);
 | |
|           if (inv)
 | |
|             oiv.round(_roundval);
 | |
|         }
 | |
|         real perc = (CENTO * div)/tot;
 | |
|         real rem(rest);
 | |
|         real oem(oest);
 | |
|         real p(perc);    
 | |
|         p.round(PERC_DECIMALS);
 | |
|         for (i = 1; i < n; i++)
 | |
|         {
 | |
|           if (i >= nr)     
 | |
|           {
 | |
|             int scd = sscad == -1 ? scad_rata(first) : sscad;
 | |
| #ifdef USE_DEFAULT_INT_RATE
 | |
|             if (scd == 0) 
 | |
|               scd = _int_rate;
 | |
| #endif            
 | |
|             add_rata(perc, (sscad == -1 ? scad_rata(nr-1) : sscad),
 | |
|                      tipo_rata(nr-1), ulc_rata(nr-1));
 | |
|           }
 | |
|           if (_inited) 
 | |
|           {
 | |
|             set_imprata (i, div, false); 
 | |
|             rem -= div;
 | |
|             if (inv)
 | |
|             {
 | |
|               set_imprata (i, oiv, true); 
 | |
|               oem -= oiv; 
 | |
|             }
 | |
|           }
 | |
|           else
 | |
|             rem -= p;
 | |
|           set_percrata(i, perc);
 | |
|         }
 | |
|         if (rem != ZERO)
 | |
|         {
 | |
|           if (_inited)         
 | |
|           {
 | |
|             real r(importo_rata(first,false) + rem);
 | |
|             real oldr;
 | |
|             if (inv) oldr = importo_rata(first,true) + oem;
 | |
|             set_imprata(first, r, false);
 | |
|             if (inv) set_imprata(first, oldr, true);
 | |
|             if (_inited && _tpr > 0 && _tpr < 4)
 | |
|               r -= importo_da_non_dividere(false);  
 | |
|             set_percrata(first, CENTO * r / tot);
 | |
|           }
 | |
|           else
 | |
|           {
 | |
|             const real r(perc_rata(first) + rem);
 | |
|             set_percrata(first, r);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     } 
 | |
|   }
 | |
|   else
 | |
|   {   
 | |
|     for (i = first; sum < CENTO; i++)
 | |
|     {
 | |
|       if ((CENTO - sum) < p) 
 | |
|         p = CENTO - sum;  
 | |
|         
 | |
|       sum += p;           
 | |
|       
 | |
|       // if necessary add remainder on first one
 | |
|       if ((CENTO - sum) /* still */ < p)
 | |
|       {      
 | |
|         real prc = perc_rata(first);
 | |
|         prc += CENTO - sum; 
 | |
|         TToken_string& rt = rata(first);
 | |
|         rt.add(prc.string(),1), 
 | |
|         sum = CENTO;  
 | |
|       }
 | |
|       
 | |
|       int scd = i == 0 ? (i < nr ? scad_rata(0) : 0) :
 | |
|          (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad);
 | |
| #ifdef USE_DEFAULT_INT_RATE
 | |
|       if (i != 0 && scd == 0) 
 | |
|           scd = _int_rate;
 | |
| #endif            
 | |
|       set_rata(i, real(p), scd, (i < nr ? tipo_rata(i) : tipo_rata(nr-1)), false);
 | |
|     } 
 | |
|   }         
 | |
|   // erase remaining  
 | |
|   remove_rate_from(i);  
 | |
|   
 | |
|   if (_inited)
 | |
|   {
 | |
|     set_inizio(_datadoc, true);
 | |
|     adjust_perc(rdiff, inv);
 | |
|   }
 | |
|   
 | |
|   adjust_fixed_scad();
 | |
|   _dirty = true;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata)
 | |
| { 
 | |
|   if (mcomm && (rata > 0 || (scad % 30) == 0))
 | |
|   {
 | |
|     int nm = scad / 30;
 | |
|     int ny = nm   / 12;
 | |
|     nm %= 12;
 | |
|         
 | |
|     int newm = d.month() + nm;
 | |
|     if (newm > 12) { newm -= 12; ny++; }
 | |
|         
 | |
|         
 | |
|     int dy = d.day();
 | |
|         
 | |
|     // la palla del febbraio & c.     ???                               
 | |
|     if (rata > 1)
 | |
|     {
 | |
|       const TDate oldd(data_rata(rata-2));
 | |
|       if (oldd.day() > dy) dy = oldd.day();
 | |
|     } 
 | |
|         
 | |
|     d.set_day(1);             // il giorno 1 ce l'hanno tutti
 | |
|     d.set_month(newm);
 | |
|     d.set_year(d.year()+ny);
 | |
| 
 | |
| //    bool last = d.is_end_month() && inizio_scadenza() == 'M';
 | |
|     const bool last = inizio_scadenza() == 'M' || _datadoc.is_end_month();
 | |
| /*        
 | |
|     d.set_end_month();  
 | |
|     if (!last && dy < d.day()) 
 | |
|     d.set_day(dy);
 | |
| */
 | |
|     if (last) 
 | |
|       d.set_end_month();  
 | |
|     else 
 | |
|     { 
 | |
|       int last_day = d.last_day(d.month(),d.year());
 | |
|       if (dy > last_day) dy = last_day;
 | |
|       d.set_day(dy);
 | |
|     }
 | |
|   }        
 | |
|   else 
 | |
|   {
 | |
|     d += scad;
 | |
|   }    
 | |
| }
 | |
| 
 | |
| void TPagamento::set_default_type(int type, bool change_existing)
 | |
| {                                                                     
 | |
|   _def_tpr = type;
 | |
|   if (change_existing)
 | |
|   {
 | |
|     for (int i = 0; i < n_rate(); i++)
 | |
|     {
 | |
|       TToken_string& tt = rata(i);
 | |
|       tt.add(type, 2);
 | |
|     }               
 | |
|     _dirty = true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TPagamento::set_default_ulc(const char* ulc, bool change_existing)
 | |
| {    
 | |
|   _def_ulc = ulc;
 | |
|   if (change_existing)
 | |
|   {
 | |
|     for (int i = 0; i < n_rate(); i++)
 | |
|     {
 | |
|       TToken_string& tt = rata(i);
 | |
|       tt.add(ulc, 5);       
 | |
|     }     
 | |
|     _dirty = true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TPagamento::remove_rata(int i)
 | |
| {                         
 | |
|   // non fa nessun ricalcolo, si limita ad impacchettare se necessario
 | |
|   _rate.destroy(i, true);
 | |
|   _dirty = true;
 | |
| }             
 | |
| 
 | |
| void TPagamento::remove_rate_from(int i)
 | |
| {                         
 | |
|   // elimina dall'ultima a quella indicata (compresa)
 | |
|   for (int j = n_rate() - 1; j >= i; j--)
 | |
|     _rate.destroy(j);
 | |
|   _dirty = true;
 | |
| }             
 | |
| 
 | |
| 
 | |
| TToken_string& TPagamento::add_rata()
 | |
| {                                        
 | |
|   // rata vuota, con -1 sulla scadenza per segnalare
 | |
|   TToken_string* tt = new TToken_string("-1| | | | | | | ");
 | |
|   _rate.add(tt);             
 | |
|   _dirty = true;
 | |
|   return *tt;
 | |
| }
 | |
| 
 | |
| TToken_string& TPagamento::add_rata(real perc, int day, int type, const char* ulc)
 | |
| {
 | |
|   TToken_string* tt = new TToken_string(64);
 | |
|   
 | |
|   tt->add(day);                // scadenza
 | |
|   tt->add(perc.string());      // percentuale
 | |
|   tt->add(type);               // tipo
 | |
|   tt->add("");                 // data
 | |
|   tt->add("");                 // importo valuta
 | |
|   tt->add(ulc);                // ulc
 | |
|   tt->add("");                 // ratapagata
 | |
|   tt->add("");                 // importo lire
 | |
|   
 | |
|   _rate.add(tt);             
 | |
|   _dirty = true;
 | |
|   return *tt;
 | |
| }
 | |
| 
 | |
| TToken_string& TPagamento::set_rata (int index, real perc, int day, int type,
 | |
|             bool val, const char* ulc, const char* imp, const char* data)
 | |
| {                                   
 | |
|   TToken_string* tt = (TToken_string*)_rate.objptr(index);
 | |
|   const bool nwr = (tt == NULL);
 | |
|   if (nwr) tt = new TToken_string(64); 
 | |
|   
 | |
|   tt->add(day,0);                // scadenza
 | |
|   tt->add(perc.string(),1);      // percentuale
 | |
|   tt->add(type,2);               // tipo 
 | |
|   tt->add(data == NULL ? "" : data, 3);
 | |
|   tt->add(imp  == NULL ? "" : imp,  val ? 4 : 7);
 | |
|   tt->add(ulc  == NULL ? "" : ulc,  5);
 | |
| 
 | |
|   if (!nwr)
 | |
|   {
 | |
|     if (index > _rate.items()) 
 | |
|     {   
 | |
|       error_box("Rate non contigue");
 | |
|       delete tt;
 | |
|     }
 | |
|   } 
 | |
|   else 
 | |
|   {
 | |
|     _rate.add(tt,index);   
 | |
|     _dirty = true;
 | |
|   }
 | |
|   return *tt;
 | |
| }                                
 | |
| 
 | |
| void TPagamento::set_imprata(int i, const real& r, bool v)
 | |
| {
 | |
|   TToken_string& tt = (TToken_string&)_rate[i];  
 | |
|   tt.add(r.string(), v ? 4 : 7);
 | |
| }
 | |
| 
 | |
| void TPagamento::set_percrata(int i, real perc)
 | |
| {                                              
 | |
|   TToken_string& tt = (TToken_string&)_rate[i];  
 | |
|   perc.round(PERC_DECIMALS);
 | |
|   tt.add(perc.string(), 1);
 | |
| }     
 | |
| 
 | |
| void TPagamento::set_datarata(int i, const TDate & d)
 | |
| {                                              
 | |
|   TToken_string& tt = (TToken_string&)_rate[i];  
 | |
|   tt.add((const char *) d, 3);
 | |
| }     
 | |
| 
 | |
| real TPagamento::recalc_percrata(int i, bool v)
 | |
| {
 | |
|   if (i == 0 && _tpr > 3) 
 | |
|     return ZERO;
 | |
| 
 | |
|   const real hm = importo_da_dividere(v);
 | |
|   real tpay = importo_rata(i,v);
 | |
|   if (i == 0 && _tpr > 0 && _tpr < 4)
 | |
|     tpay -= importo_da_non_dividere(v);
 | |
|   const real perc = tpay * CENTO / hm;
 | |
|   set_percrata(i, perc);
 | |
|   
 | |
|   return perc;
 | |
| }
 | |
| 
 | |
| TToken_string& TPagamento::set_rata(int index, const real& impval, const real& implit,
 | |
|                                     const TDate& date, int type,const char* ulc, bool pagato)
 | |
| {
 | |
|   // calcola percentuali e scadenze a partire dagli importi 
 | |
|   TToken_string* tt = _rate.rowptr(index);
 | |
|   const int first    = _tpr < 4 ? 0 : 1;        
 | |
|   
 | |
|   const bool nwr = (tt == NULL);  // nuova rata
 | |
|   
 | |
|   if (nwr) tt = new TToken_string(64); 
 | |
| 
 | |
|   const TDate oldd = index > 0 ? data_rata(index -1) : _inizio;
 | |
|   const long day = date - oldd;
 | |
|   
 | |
|   const real toshare = importo_da_dividere(in_valuta());
 | |
|   
 | |
|   real hm = in_valuta() ? impval : implit;
 | |
|   if (index == first && _tpr > 0 && _tpr < 4) 
 | |
|     hm -= importo_da_non_dividere(in_valuta());
 | |
|       
 | |
|   real perc = (_tpr > 3 && index == 0) ? ZERO : hm/toshare; 
 | |
|   perc *= CENTO;
 | |
|   perc.round(PERC_DECIMALS);
 | |
|   
 | |
|   tt->cut(0);
 | |
|   tt->add(day);                // 0 - scadenza
 | |
|   tt->add(perc.string());      // 1 - percentuale
 | |
|   tt->add(type);               // 2 - tipo 
 | |
|   tt->add(date.string());      // 3 - data
 | |
|   tt->add(impval.string());    // 4 - importo
 | |
|   tt->add(ulc);                // 5 - ulc(era?)
 | |
|   tt->add(pagato ? "X" : " "); // 6 - pagata
 | |
|   tt->add(implit.string());    // 7 - Importo in lire
 | |
|   if (!nwr)
 | |
|   {
 | |
|     if (index > _rate.items()) 
 | |
|     {   
 | |
|       error_box("Rate non contigue");
 | |
|       delete tt;
 | |
|     }
 | |
|   } 
 | |
|   else 
 | |
|   {
 | |
|     _rate.add(tt, index);   
 | |
|     _dirty = true;
 | |
|   }
 | |
|   return *tt;
 | |
| }
 | |
| 
 | |
| word TPagamento::validate() const
 | |
| {
 | |
|   word res = 0x0000; 
 | |
|   int warnscad = 0;
 | |
|   real r;
 | |
|   
 | |
|   int first = _tpr < 4 ? 0 : 1;        
 | |
|   
 | |
|   // check percentages & prepare slicer
 | |
|   for (int i = first; i < n_rate(); i++)
 | |
|     r += perc_rata(i); 
 | |
|   r -= CENTO;
 | |
|   real delta(0.005);
 | |
|   delta = delta * real(n_rate());
 | |
|   r = abs(r);
 | |
|   if (r > delta)
 | |
|     res |= P_RSUM;            
 | |
|   
 | |
|   
 | |
|   if (_inited)
 | |
|   {     
 | |
|     real tot;
 | |
|     int i;                         
 | |
|     
 | |
|     for (i = 0; i < n_rate(); i++) 
 | |
|     {
 | |
|       const real tpay(tlit_rata(i));
 | |
|     
 | |
|       if (tpay.is_zero())
 | |
|         res |= P_ZEROLIT;
 | |
|       tot += tpay;
 | |
|     }
 | |
|     
 | |
|     tot.round(_roundlit);
 | |
|     // serve per fatture in valuta, onde evitare cazzi e canguri
 | |
|     real tmax = importo_da_dividere(false) + importo_da_non_dividere(false); 
 | |
|     tmax.round(_roundlit);
 | |
|      
 | |
|     if (tot != tmax) res |= P_TOTNCLIT;                          
 | |
| 
 | |
|     if (in_valuta())
 | |
|     {                     
 | |
|       tot = 0.0;
 | |
|       for (int i = 0; i < n_rate(); i++)
 | |
|       {
 | |
|         const real tpay = tval_rata(i);
 | |
|         if (tpay.is_zero())
 | |
|           res |= P_ZEROVAL;
 | |
|         tot += tpay;
 | |
|       }
 | |
|     
 | |
|       tot.round(_roundval);
 | |
|       // serve per fatture in valuta, onde evitare cazzi e canguri
 | |
|       real tmax = importo_da_dividere(true) + importo_da_non_dividere(true); 
 | |
|       tmax.round(_roundval);
 | |
|      
 | |
|       if (tot != tmax) 
 | |
|         res |= P_TOTNCVAL;                          
 | |
|     }
 | |
| 
 | |
|     // check errori date scadenze (se istanziate)
 | |
|     TDate d(data_rata(0));
 | |
|     if (d < _datadoc)  // _inizio
 | |
|       res |= P_INIZIO;   
 | |
|       
 | |
|     for (i = 1; i < n_rate(); i++)
 | |
|     {
 | |
|       if (data_rata(i) < d) 
 | |
|         { res |= P_SCAD; break; }    
 | |
|       if (data_rata(i) == d)
 | |
|         warnscad++;
 | |
|       d = data_rata(i);
 | |
|     }     
 | |
|   } 
 | |
|                  
 | |
|   if (warnscad && !yesno_box("N. %d rate cadono nello stesso giorno. Si desidera proseguire?", warnscad+1))
 | |
|     res |= P_SCAD;
 | |
|     
 | |
|   return res;
 | |
| }                                                                     
 | |
| 
 | |
| 
 | |
| void TPagamento::strerr(word err, TString& s)
 | |
| {
 | |
|   s = "Errore:\n";
 | |
|   if (err & P_RSUM)
 | |
|     s << "- le percentuali non sommano a 100\n";
 | |
|   if (err & P_IMPNC)
 | |
|     s << "- le percentuali sono inconsistenti con gli importi\n";
 | |
|   if (err & P_SCAD)
 | |
|     s << "- le scadenze non sono consecutive\n";
 | |
|   if (err & P_INIZIO)
 | |
|     s << "- la prima rata e' antecedente alla data del documento (" << _datadoc << ")\n"; // _inizio
 | |
|   if (err & P_NEG)
 | |
|     s << "- l'importo dato e' inferiore al minimo possibile\n";
 | |
|   if (err & P_TROP)
 | |
|     s << "- l'importo dato e' superiore al massimo possibile\n";
 | |
|   if (err & P_TOTNCLIT)
 | |
|   {
 | |
|     const real tot = importo_da_dividere(false) + importo_da_non_dividere(false);
 | |
|     real imp;
 | |
|     for (int i = 0; i < n_rate(); i++)
 | |
|       imp += tlit_rata(i);
 | |
|     char pic[3] =  ".0";
 | |
|     pic[1] += _roundlit;                
 | |
|     s << "- la somma degli importi in lire (" << imp.string(pic);
 | |
|     s << ") e' diversa dal\ntotale del documento in lire(" << tot.string(pic) << ")\n";
 | |
|   }  
 | |
|   if (err & P_TOTNCVAL)
 | |
|   {
 | |
|     const real tot = importo_da_dividere(true) + importo_da_non_dividere(true);
 | |
|     real imp;
 | |
|     for (int i = 0; i < n_rate(); i++)
 | |
|       imp += tval_rata(i);
 | |
|     char pic[3] =  ".0";
 | |
|     pic[1] += _roundval;                
 | |
|     s << "- la somma degli importi in valuta (" << imp.string(pic);
 | |
|     s << ") e' diversa dal\ntotale del documento in valuta(" << tot.string(pic) << ")\n";
 | |
|   }  
 | |
|   if (err & P_MCOMM)
 | |
|     s << "- scadenze incompatibili con il mese commerciale\n";
 | |
|   if (err & P_ZEROLIT)
 | |
|     s << "- almeno una rata ha importo in lire uguale a zero\n";
 | |
|   if (err & P_ZEROVAL)
 | |
|     s << "- almeno una rata ha importo in valuta uguale a zero\n";
 | |
|   if (err & P_SCWIDE)
 | |
|     s << "- le scadenze sono troppo distanti\n";
 | |
|   if (err & P_TOOMANY)
 | |
|     s << "- il calcolo genera piu' di 999 rate!\n";
 | |
| }
 | |
| 
 | |
| const char* TPagamento::desc_tpr() const
 | |
| {            
 | |
|   const char* o;
 | |
|   switch (_tpr)
 | |
|   {
 | |
|     case 0: o = "Totale su tutte le rate"; break;
 | |
|     case 1: o = "Tutte le imposte su 1a"; break;
 | |
|     case 2: o = "Tutte le spese su 1a"; break;
 | |
|     case 3: o = "Imposte + spese su 1a"; break;
 | |
|     case 4: o = "Solo imposte"; break;
 | |
|     case 5: o = "Solo spese"; break;
 | |
|     case 6: o = "Imposte + spese"; break; 
 | |
|     default: o = ""; break;
 | |
|   } 
 | |
|   return o;
 | |
| }                        
 | |
| 
 | |
| const char* TPagamento::desc_tipo(int tipo, char ulc, bool* ok) const
 | |
| {         
 | |
|   const char* o = "";                 
 | |
|   if (ok != NULL) *ok = true;
 | |
|   if (ulc > ' ')
 | |
|   {
 | |
|     const char key[3] = { tipo+'0', toupper(ulc), '\0' };
 | |
|     o = cache().get("%CLR", key).get("S0");
 | |
|   }
 | |
|   if (*o == '\0')
 | |
|   {
 | |
|     switch (tipo)
 | |
|     {          
 | |
|       case  0: o = TR("Altro pagamento"); break;
 | |
|       case  1: o = TR("Rimessa diretta o contanti"); break;
 | |
|       case  2: o = TR("Tratta"); break;
 | |
|       case  3: o = TR("Ricevuta Bancaria"); break;
 | |
|       case  4: o = TR("Cessione"); break;
 | |
|       case  5: o = TR("Paghero'"); break;
 | |
|       case  6: o = TR("Lettera di credito"); break;
 | |
|       case  7: o = TR("Tratta accettata"); break;                   
 | |
|       case  8: o = TR("Rapporti interban. diretti"); break;
 | |
|       case  9: o = TR("Bonifici"); break;
 | |
|       default: if (ok != NULL) *ok = false; break;
 | |
|     } 
 | |
|   }  
 | |
|   return o;            
 | |
| }
 | |
| 
 | |
| word TPagamento::recalc_rate(int row, bool is_perc_modified, 
 | |
|                             const char* new_value, const char* new_lire, 
 | |
|                             const char* scad, const char* typ, const char* ulc,
 | |
|                             int rdiff, bool mcomm, bool& need_recalc)
 | |
|      // ricalcola le rate sulla base di parametri modificati sulla riga row
 | |
|      // parametri: tutti i const char* possono essere NULL, il che vuol dire
 | |
|      //              che i dati corrispondenti non sono stati modificati;
 | |
|      //            se new_value non e' NULL puo' essere la percentuale (e 
 | |
|      //              allora is_perc_modified e' true) o l'importo. Non e'
 | |
|      //              possibile modificare entrambi; se succede viene data
 | |
|      //              priorita' alla percentuale.
 | |
| {                                     
 | |
|   CHECK(!(!is_perc_modified &&  (new_value != NULL || new_lire != NULL) && !_inited), 
 | |
|         "A'stronzo! E famme 'na pippa! Me dai n'importo che nun ce sta? Ma Vaffanculo!");
 | |
|   
 | |
|   if (_rate.items() == 0) return P_OK;    
 | |
|   
 | |
|   real rsum(0.0), newv(0.0), rmax(0.0); 
 | |
|   const int last_rata = _rate.items() - 1; 
 | |
|   int oldtype    = tipo_rata(last_rata);      
 | |
|   TString8 oldulc = ulc_rata(last_rata);      
 | |
|   int oldscad    = scad_rata(last_rata);
 | |
|   TDate lastdate = data_rata(0);  
 | |
|   const TString_array srate(_rate);   // rate come erano   
 | |
|   
 | |
|   if (oldscad <= 0) oldscad = _int_rate;
 | |
|   if (oldtype <= 0) oldtype = _def_tpr;
 | |
|   
 | |
|   for (int i = 0; i < srate.items(); i++)
 | |
|   {
 | |
|     if (i == row)
 | |
|     {  
 | |
|       if (typ != NULL)
 | |
|       { 
 | |
|         for (int k = 0; k < srate.items(); k++)
 | |
|         { 
 | |
|           // deve farlo per tutte dalla 1 in poi se rdiff == 2, 
 | |
|           // soltanto per row diversamente           
 | |
|           if ((rdiff == 2 && row > 0 && k > 0) || k == row)
 | |
|           {            
 | |
|             TToken_string& tt = rata(k);
 | |
|             TToken_string& ss = (TToken_string&)srate[k];
 | |
|             tt.add(typ,2);
 | |
|             ss.add(typ,2);  
 | |
|             tt.add(ulc,5);
 | |
|             ss.add(ulc,5);  
 | |
|             need_recalc = true;                        
 | |
|             // no error is possible  
 | |
|           }        
 | |
|         }  
 | |
|       } 
 | |
|     
 | |
|       if (ulc != NULL)
 | |
|       {
 | |
|         for (int k = 0; k < srate.items(); k++)
 | |
|         { 
 | |
|           // deve farlo per tutte dalla 1 in poi se rdiff == 2, 
 | |
|           // soltanto per row diversamente           
 | |
|           if ((rdiff == 2 && row > 0 && k > 0) || k == row)
 | |
|           {            
 | |
|             TToken_string& tt = rata(k);
 | |
|             TToken_string& ss = (TToken_string&)srate[k];
 | |
|             tt.add(ulc,5);
 | |
|             ss.add(ulc,5);  
 | |
|             need_recalc = true;                        
 | |
|             // no error is possible  
 | |
|           }        
 | |
|         }  
 | |
|       }
 | |
|     
 | |
|       if (scad != NULL)
 | |
|       {   
 | |
|         // if !_inited scad e' il n. giorni, se no e' la rata 
 | |
|         if (_inited)
 | |
|         {
 | |
|           TToken_string& tt = rata(row);
 | |
|           TToken_string& ss = (TToken_string&)srate[row];
 | |
|           lastdate = scad;  
 | |
|           int lastscad = oldscad;                           
 | |
|           // controlla errore sulla data scadenza
 | |
|           if (i > 0) 
 | |
|           {
 | |
|             oldscad  = lastscad = (int)(lastdate - data_rata(i-1)); 
 | |
|             if (oldscad <  0l) return P_SCAD;
 | |
|           }
 | |
|           else  
 | |
|           {
 | |
|             if (lastdate < _datadoc) 
 | |
|               return P_INIZIO; // _inizio 
 | |
|             lastscad = scad_rata(0);
 | |
|           }
 | |
|           tt.add(scad,3); tt.add(lastscad, 0); 
 | |
|           ss.add(scad,3); ss.add(lastscad, 0);     
 | |
|           // ricalcola rate successive: se si vuole modificarne solo una
 | |
|           // ci si fotte e si disabilita il ricalcolo
 | |
|           TDate ddd (lastdate);
 | |
|           for (int j = row+1; j < srate.items(); j++)
 | |
|           { 
 | |
|             TToken_string& ttt = rata(j);
 | |
|             TToken_string& sss = (TToken_string&)srate[j];
 | |
|             next_scad(ddd,scad_rata(j), mcomm,j);
 | |
|             ttt.add(ddd.string(),3);
 | |
|             sss.add(ddd.string(),3);
 | |
|             need_recalc = true;      
 | |
|           }
 | |
|         }
 | |
|         else
 | |
|         { 
 | |
|           // nulla di speciale visto che si memorizza la derivata
 | |
|           long sc = atol(scad);
 | |
|           for (int i = 0; i < row; i ++)
 | |
|             sc -= scad_rata(i);
 | |
|           if (sc < 0) return P_SCAD;  
 | |
|           if (row > 0 && sc == 0 && 
 | |
|               !yesno_box("Due o piu' rate cadranno nello stesso giorno. Si conferma l'immissione?")) 
 | |
|             return P_SCAD;
 | |
|           if (sc > 10000L) return P_SCWIDE;
 | |
|           if (_mcomm && row > 0 && (sc % 30) != 0) 
 | |
|             return P_MCOMM;
 | |
|           TToken_string& tt = rata(row);
 | |
|           TToken_string& ss = (TToken_string&)srate[row];
 | |
|           tt.add(sc,0);
 | |
|           ss.add(sc,0);
 | |
|           need_recalc = true;       
 | |
|         }       
 | |
|       }                 
 | |
|     
 | |
|       if (new_value != NULL)
 | |
|       {        
 | |
|         need_recalc = true;            
 | |
|         // questa la subappaltiamo, per evitare l'inferno
 | |
|         return  change_value(row, real(new_value), rdiff, is_perc_modified, mcomm, true);     
 | |
|       }                                         
 | |
|       
 | |
|       if (new_lire != NULL)
 | |
|       {        
 | |
|         need_recalc = true;            
 | |
|         // questa pure la subappaltiamo, sempre per evitare l'inferno
 | |
|         return  change_value(row, real(new_lire), rdiff, is_perc_modified, mcomm, false);     
 | |
|       } 
 | |
|     }
 | |
|     else  // i != row modified
 | |
|     {                                
 | |
|       if (rdiff == 2) 
 | |
|         continue;
 | |
| 
 | |
|       if (scad != NULL)
 | |
|       {
 | |
|         // check sulle scadenze solo se si sono modificate
 | |
|         lastdate = data_rata(i);
 | |
| 
 | |
|         if (_inited && i > 0) 
 | |
|         {
 | |
|           if (data_rata(i) < data_rata(i-1)) 
 | |
|             return P_SCAD;                 
 | |
|         }
 | |
|         else if (_inited && lastdate < _inizio)
 | |
|           return P_INIZIO;
 | |
|       }
 | |
|     }    
 | |
|   }
 | |
|   
 | |
|   adjust_fixed_scad();    
 | |
|   return P_OK;
 | |
| }
 | |
| 
 | |
| word TPagamento::change_value(int rata, real user_val, int rdiff, bool is_perc, 
 | |
|                               bool mcomm, bool valuta)
 | |
| {
 | |
|   word err         = 0;
 | |
| 
 | |
|   switch (rdiff)
 | |
|   {              
 | |
|     case 1:
 | |
|       err = change_value_differenziate(rata, user_val, is_perc, valuta);
 | |
|       break;
 | |
|     case 2:
 | |
|       err = change_value_uguali(rata, user_val, is_perc, valuta);
 | |
|       break;
 | |
|     case 3:
 | |
|       err = change_value_uguali_prossima(rata, user_val, is_perc, valuta);
 | |
|       break;
 | |
|     case 4:
 | |
|       err = change_value_uguali_possible(rata, user_val, is_perc, valuta);
 | |
|       break;
 | |
|   }
 | |
|                            
 | |
|   if (!err)
 | |
|   {                         
 | |
|     // riaggiusta gli altri parametri se si sono create rate nuove
 | |
|     adjust_parameters(mcomm);  
 | |
|     // risistema scadenze fisse se necessario
 | |
|     adjust_fixed_scad();        
 | |
|     // riaggiusta le percentuali o gli importi rispetto al dato modificato              
 | |
|     if (_inited) 
 | |
|     {                                         
 | |
|       // questa aggiusta anche l'eventuale importo in lire se si e' in valuta
 | |
|       // e si e' modificato l'importo in valuta
 | |
|       adjust_perc_imp(is_perc, rdiff, valuta);   
 | |
|       // se era in valuta e ho modificato le percentuali aggiustalo anche in lire
 | |
|       if (valuta && is_perc) adjust_perc_imp(is_perc, rdiff, false);  
 | |
|     }  
 | |
|     _dirty = true;
 | |
|   }
 | |
|                 
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| // Sulla prima riga, se il tipo rata e > 0 il valore (importo o percentuale)
 | |
| // puo' anche essere nullo, altrimenti deve essere positivo
 | |
| bool TPagamento::sign_ok(const real& val, int row) const
 | |
| {
 | |
|   const bool ok = val.sign() > (row == 0 && _tpr > 0 ? -1 : 0);
 | |
|   return ok;
 | |
| }    
 | |
| 
 | |
| 
 | |
| // le quattro che seguono modificano le rate (solo importi o percentuali), e 
 | |
| // lasciano in last_old l'indice dell'ultima rata rimasta dalle vecchie che
 | |
| // hanno adoperato 
 | |
|   
 | |
| word TPagamento::change_value_differenziate(int row, real user_val, bool is_perc, bool v)
 | |
| {                                                   
 | |
|   // importi totali, da non suddividere, da suddividere
 | |
|   real to_share = is_perc ? CENTO : importo_da_dividere(v);
 | |
|   real to_subtract = ZERO;
 | |
|   if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc) 
 | |
|     to_subtract = importo_da_non_dividere(v); 
 | |
|   real user_div    = user_val - to_subtract;
 | |
|   const int first        = _tpr > 3 ? 1 : 0;
 | |
|   _rdiff = true;
 | |
|   
 | |
|   if (!sign_ok(user_div, row))
 | |
|     return P_NEG;
 | |
|   
 | |
|   // togli rate gia' presenti
 | |
|   for (int i = first; i < row; i++)
 | |
|   {
 | |
|     to_share -= (is_perc ? perc_rata(i): importo_rata(i,v));
 | |
|     if (i == 0 && !is_perc && _tpr > 0 && _tpr < 4)
 | |
|       to_share += importo_da_non_dividere(v);
 | |
|   }
 | |
| 
 | |
|   real remainder   = to_share - user_div;
 | |
|   if (remainder.sign() < 0) return P_TROP;
 | |
|   
 | |
|   const int tok_ind = is_perc ? 1 : (v ? 4 : 7);
 | |
|   rata(row).add(user_val.string(), tok_ind);
 | |
|   
 | |
|   if (!remainder.is_zero()) 
 | |
|   {
 | |
|      if (n_rate() <= row + 1) add_rata();
 | |
|      rata(row+1).add(remainder.string(), tok_ind);
 | |
|   }
 | |
|   
 | |
|   // elimina rate successive
 | |
|   remove_rate_from(remainder.is_zero() ? row +1 : row+2);
 | |
|   
 | |
|   return 0;
 | |
| }  
 | |
| 
 | |
| word TPagamento::change_value_uguali(int row, real user_val, bool is_perc, bool v)
 | |
| {                                                   
 | |
|   // importi totali, da non suddividere, da suddividere
 | |
|   real to_share    = is_perc ? CENTO : importo_da_dividere(v);
 | |
|   real to_subtract = ZERO;
 | |
|   if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc) 
 | |
|     to_subtract = importo_da_non_dividere(v); 
 | |
|   real user_div    = user_val - to_subtract;
 | |
|   real remainder   = to_share - user_div;
 | |
|   const int tok_ind      = is_perc ? 1 : (v ? 4 : 7);
 | |
|   const int first        = _tpr > 3 ? 1 : 0;
 | |
|   _rdiff = false;
 | |
| 
 | |
|   if (!sign_ok(user_div, row))
 | |
|     return P_NEG;
 | |
|   
 | |
|   // la prima viene mantenuta uguale (vale solo per la 0 anche se _tpr > 4)
 | |
| 
 | |
|   // se si modifica la prima, si suddivide l'importo rimanente tra tutte le
 | |
|   // altre e si aggiunge il residuo alla prima; il n. rate viene mantenuto
 | |
|   if (row == 0)
 | |
|   {  
 | |
|      if (n_rate() == 1)
 | |
|      {
 | |
|        // se il numero rate e' 1 si aggiungono rate uguali a coprire l'importo
 | |
|        if ((to_share - user_div) < user_div) return 0;
 | |
|        real div   = to_share / user_div;  
 | |
|        real delta = to_share - (user_div * div.integer()); 
 | |
|        if (div > real(999.0)) return P_TOOMANY;
 | |
|        for (int i = 0; i < div.integer(); i++)
 | |
|        {
 | |
|          if (n_rate() <= i) add_rata(); 
 | |
|          rata(i).add(i == 0 ? user_val.string() : user_div.string(), tok_ind);
 | |
|        }      
 | |
|        
 | |
|        // add residuo
 | |
|        if (!delta.is_zero()) 
 | |
|        {     
 | |
|          real tp = is_perc ? perc_rata(first) : importo_rata(first,v);
 | |
|          tp += delta;
 | |
|          rata(first).add(tp.string(), tok_ind);
 | |
|        } 
 | |
|      }
 | |
|      else  // n. rate > 1, modificata la rata 0: _tpr e' per forza < 4
 | |
|      {             
 | |
|        real div = remainder / real(n_rate() - 1);
 | |
|        div.round(is_perc ? PERC_DECIMALS : round(v)); 
 | |
|        real delta = remainder - (div * real(n_rate() - 1));
 | |
|        
 | |
|        rata(0).add(user_val.string(), tok_ind); 
 | |
|        if (remainder.is_zero())
 | |
|        {                 
 | |
|          remove_rate_from(1);
 | |
|          return 0;
 | |
|        }       
 | |
|        
 | |
|        // ripartisci il resto
 | |
|        for (int i = 1; i < n_rate(); i++)
 | |
|          rata(i).add(div.string(), tok_ind);
 | |
| 
 | |
|        if (!delta.is_zero())
 | |
|        {
 | |
|          user_val += delta;
 | |
|          rata(0).add(user_val.string(), tok_ind);
 | |
|        }
 | |
|      }
 | |
|   }
 | |
|   // dalla seconda in poi, tutte le rate devono essere uguali a quella indicata
 | |
|   // (a meno dell'importo non suddivisibile se c'e' (to_subtract); il numero rate
 | |
|   // puo' cambiare. Si rispetta il valore della rata 0 
 | |
|   // se c'e' un residuo lo metto sulla prima calcolabile (dipende da _tpr)
 | |
|   else
 | |
|   {                                      
 | |
|      real first_imp;
 | |
|      if (_tpr < 4) 
 | |
|      {
 | |
|        first_imp = is_perc ? perc_rata(0) : importo_rata(0,v);
 | |
|        if (_tpr > 0 && !is_perc) first_imp -= importo_da_non_dividere(v);
 | |
|      }
 | |
|      real div   = (to_share - first_imp)/user_val;                    
 | |
|      if (div < real(1.0)) return P_TROP;
 | |
|      if (div > real(999.0)) return P_TOOMANY;
 | |
| 
 | |
|      real delta = (to_share - first_imp) - user_val * real(div.integer());
 | |
|      int i;
 | |
|      
 | |
|      for (i = 1; i < div.integer()+1l; i++)
 | |
|      {  
 | |
|        if (n_rate() <= i) add_rata(); 
 | |
|        rata(i).add(user_val.string(), tok_ind);
 | |
|      } 
 | |
|      
 | |
|      remove_rate_from(i);
 | |
|                                           
 | |
|      if (!delta.is_zero()) 
 | |
|      {     
 | |
|        real tp = is_perc ? perc_rata(first) : importo_rata(first,v);
 | |
|        tp += delta;
 | |
|        rata(first).add(tp.string(), tok_ind);
 | |
|      }      
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }                        
 | |
| 
 | |
| word TPagamento::change_value_uguali_prossima(int row, real user_val, bool is_perc, bool v)
 | |
| {                                                   
 | |
|   _rdiff = true;           
 | |
|   // uguali finche' possibile da row in poi; residuo su first 
 | |
|   // importi totali, da non suddividere, da suddividere
 | |
|   real to_share = is_perc ? CENTO : importo_da_dividere(v);
 | |
|   real to_subtract = ZERO;
 | |
|   if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc) 
 | |
|     to_subtract = importo_da_non_dividere(v); 
 | |
|   real user_div    = user_val - to_subtract;
 | |
|   const int tok_ind      = is_perc ? 1 : (v ? 4 : 7);
 | |
|   const int first        = _tpr > 3 ? 1 : 0;
 | |
| 
 | |
|   if (!sign_ok(user_div, row))
 | |
|     return P_NEG;
 | |
|   
 | |
|   // togli rate gia' presenti
 | |
|   int i;
 | |
|   
 | |
|   for (i = first; i < row; i++)
 | |
|   {
 | |
|     to_share -= (is_perc ? perc_rata(i): importo_rata(i,v));
 | |
|     if (i == 0 && !is_perc && _tpr > 0 && _tpr < 4)
 | |
|       to_share += importo_da_non_dividere(v);
 | |
|   }
 | |
| 
 | |
|   real div   = to_share/user_div;
 | |
|   if (div < real(1.0)) return P_TROP;
 | |
|   if (div > real(999.0)) return P_TOOMANY;
 | |
|   
 | |
|   real delta = to_share - (user_div * div.integer());
 | |
|   for (i = row; i < (row + div.integer()); i++)
 | |
|   {
 | |
|      if (n_rate() <= i) add_rata();
 | |
|      rata(i).add(user_div.string(), tok_ind);
 | |
|   }
 | |
|   remove_rate_from(i);
 | |
|   if (!delta.is_zero()) 
 | |
|   { 
 | |
|     real r = is_perc ? perc_rata(first) : importo_rata(first,v);
 | |
|     r += delta;
 | |
|     rata(first).add(r.string(), tok_ind);
 | |
|   }   
 | |
|   return 0;
 | |
| }  
 | |
| 
 | |
| word TPagamento::change_value_uguali_possible(int row, real user_val, bool is_perc, bool v)
 | |
| {                                                   
 | |
|   _rdiff = true;
 | |
|   // uguali finche' possibile da row in poi; residuo come rata a parte 
 | |
|   real to_share = is_perc ? CENTO : importo_da_dividere(v);
 | |
|   real to_subtract = ZERO;
 | |
|   if (row == 0 && _tpr > 0 && _tpr < 4 && !is_perc) 
 | |
|     to_subtract = importo_da_non_dividere(v); 
 | |
|   real user_div    = user_val - to_subtract;
 | |
|   const int tok_ind      = is_perc ? 1 : (v ? 4 : 7);
 | |
|   const int first        = _tpr > 3 ? 1 : 0;
 | |
|   
 | |
|   if (!sign_ok(user_div, row))
 | |
|     return P_NEG;
 | |
|   
 | |
|   // togli rate gia' presenti
 | |
|   int i;
 | |
|   
 | |
|   for (i = first; i < row; i++)
 | |
|   {
 | |
|     to_share -= (is_perc ? perc_rata(i): importo_rata(i,v));
 | |
|     if (i == 0 && !is_perc && _tpr > 0 && _tpr < 4)
 | |
|       to_share += importo_da_non_dividere(v);
 | |
|   }
 | |
| 
 | |
|   real div   = to_share/user_div;
 | |
|   if (div < real(1.0)) return P_TROP;
 | |
|   if (div > real(999.0)) return P_TOOMANY;
 | |
|   
 | |
|   real delta = to_share - (user_div * div.integer());
 | |
|   for (i = row; i < (row + div.integer()); i++)
 | |
|   {
 | |
|      if (n_rate() <= i) add_rata();
 | |
|      rata(i).add(user_div.string(), tok_ind);
 | |
|   }
 | |
|   if (!delta.is_zero()) 
 | |
|   {                      
 | |
|     if (n_rate() <= i) add_rata();
 | |
|     rata(i++).add(delta.string(), tok_ind);
 | |
|   }
 | |
|   remove_rate_from(i);
 | |
|   return 0;
 | |
| }  
 | |
| 
 | |
| void TPagamento::adjust_parameters(bool mcomm)
 | |
| {
 | |
|    TDate      last_date;
 | |
|    int        last_type = 0;
 | |
|    TString16  last_ulc;
 | |
|    int        last_scad = 0;
 | |
| 
 | |
|    for (int i = 0; i < n_rate(); i++)
 | |
|    {  
 | |
|      if (scad_rata(i) != -1)
 | |
|      {   
 | |
|         last_date = data_rata(i);
 | |
|         last_type = tipo_rata(i);
 | |
|         last_ulc  = ulc_rata(i);
 | |
|         last_scad = scad_rata(i);
 | |
|      }
 | |
|      else
 | |
|      {
 | |
|        TToken_string& r = rata(i);
 | |
| #ifdef USE_DEFAULT_INT_RATE
 | |
|        r.add(last_scad == 0 ? _int_rate : last_scad, 0);
 | |
| #else
 | |
|        r.add(last_scad, 0);
 | |
| #endif
 | |
|        r.add(last_type, 2);
 | |
|        r.add(last_ulc,  5);
 | |
|        if (_inited)
 | |
|        {                               
 | |
| #ifdef USE_DEFAULT_INT_RATE
 | |
|          next_scad(last_date, last_scad == 0 ? _int_rate : last_scad, mcomm, i);
 | |
| #else
 | |
|          next_scad(last_date, last_scad, mcomm, i);
 | |
| #endif
 | |
|          r.add(last_date, 3);
 | |
|        }
 | |
|     }
 | |
|    }
 | |
| }
 | |
|   
 | |
| void TPagamento::adjust_perc(int rdiff, bool v)
 | |
| {
 | |
|    const real other = importo_da_dividere(v);
 | |
|    if (other.is_zero())
 | |
|      return;
 | |
| 
 | |
|    const int first = _tpr > 3 ? 1 : 0; 
 | |
|    int j;              
 | |
| 
 | |
|    for (j = first; j < _rate.items(); j++)
 | |
|    {   
 | |
|      real rvl = importo_rata(j,v); 
 | |
|      // togli pezzo di troppo
 | |
|      if (j == first && _tpr > 0 && _tpr < 4)
 | |
|         rvl -= importo_da_non_dividere(v);                     
 | |
|      real zpx = (rvl * CENTO) / other; // percentuale
 | |
|      zpx.round(PERC_DECIMALS);
 | |
|      set_percrata(j, zpx);       
 | |
|    }  
 | |
|    if (in_valuta())
 | |
|    {
 | |
|      // riaggiusta l'importo rimanente 
 | |
|      real tot = importo_da_dividere(!v);
 | |
|      TDistrib dt(tot); dt.set_dec(round(!v));
 | |
|      for (j = first; j < _rate.items(); j++)
 | |
|      { 
 | |
|        real rvl = importo_rata(j,v); 
 | |
|        // togli pezzo di troppo
 | |
|        if (j == first && _tpr > 0 && _tpr < 4)
 | |
|           rvl -= importo_da_non_dividere(v);                     
 | |
|        dt.add(rvl/other);
 | |
|      }
 | |
|      for (j = first; j < _rate.items(); j++)
 | |
|      { 
 | |
|        real rvl = dt.get(); 
 | |
|        // aggiungi pezzo mancante
 | |
|        if (j == first && _tpr > 0 && _tpr < 4)
 | |
|           rvl += importo_da_non_dividere(!v);                     
 | |
|        set_imprata(j, rvl, !v);
 | |
|      }
 | |
|    }
 | |
| }
 | |
|                       
 | |
| void TPagamento::adjust_perc_imp(bool is_perc, int rdiff, bool v)
 | |
| {                      
 | |
|    if (!is_perc)
 | |
|    {
 | |
|      adjust_perc(rdiff, v);
 | |
|      return;
 | |
|    }
 | |
| 
 | |
|    real toshare(importo_da_dividere(v)); 
 | |
|    const real other = CENTO;
 | |
|    bool inv = in_valuta();
 | |
|    
 | |
|    TDistrib dt(toshare, round(v));                 
 | |
|    const int first = _tpr > 3 ? 1 : 0;               
 | |
|    
 | |
|    TDistrib ot(0.0, 0); // slicer per l'importo non modificato
 | |
|    if (inv) 
 | |
|    { 
 | |
|      ot.init(importo_da_dividere(!v));
 | |
|      ot.set_dec(round(v));
 | |
|    }                                                   
 | |
|    
 | |
|    int j;
 | |
|    
 | |
|    for (j = _rate.items() - 1; j >= first ; j--)
 | |
|    {   
 | |
|      real rvl = perc_rata(j); 
 | |
|      // togli pezzo di troppo
 | |
|      real zpx = rvl/other; // percentuale
 | |
|      dt.add(zpx);    
 | |
|      if (inv) ot.add(zpx);      
 | |
|    }    
 | |
|         
 | |
|    real rem(toshare);    
 | |
|    real oem(0.0);
 | |
|    if (inv) oem = importo_da_dividere(!v);
 | |
|    
 | |
|    for (j = n_rate() - 1; j >= first ; j--)
 | |
|    { 
 | |
|       real rfirst(0.0);              
 | |
|       real ofirst(0.0);  
 | |
|                   
 | |
|       TToken_string& tr = rata(j);    
 | |
|          
 | |
|       real rvl = dt.get();
 | |
|       rem -= rvl;
 | |
|       real ovl;
 | |
|       
 | |
|       if (inv)   
 | |
|       {
 | |
|         ovl = ot.get();
 | |
|         oem -=  ovl;
 | |
|       }
 | |
|           
 | |
|       if (j == first) 
 | |
|       {  
 | |
|         rfirst = rvl; 
 | |
|         if (!rem.is_zero()) rfirst += rem;
 | |
| 
 | |
|         if (inv)
 | |
|         {
 | |
|           ofirst = ovl; 
 | |
|           if (!oem.is_zero()) ofirst += oem;   
 | |
|         }
 | |
|       }
 | |
|            
 | |
|       if (j == first && _tpr > 0 && _tpr < 4)
 | |
|       {
 | |
|          rfirst += importo_da_non_dividere(v);   
 | |
|          if (inv)
 | |
|            ofirst += importo_da_non_dividere(!v);   
 | |
|       }    
 | |
|       tr.add((j == first ? rfirst.string() : rvl.string()), v ? 4 : 7);        
 | |
|       if (inv)
 | |
|         tr.add((j == first ? ofirst.string() : ovl.string()), v ? 7 : 4);        
 | |
|    } 
 | |
| }
 | |
| 
 | |
| bool TPagamento::read(TTable* t, TTable* r)
 | |
| {                                                         
 | |
|   // puo' chiamarla chiunque
 | |
|   bool istnew = false;
 | |
|   if (t == NULL) 
 | |
|   { 
 | |
|     t = new TTable("%CPG"); 
 | |
|     istnew = true; 
 | |
|   }
 | |
|   _rate.destroy();
 | |
|   t->zero(); t->put("CODTAB", _code);
 | |
|   if (t->read() != NOERR) return false;   
 | |
|   
 | |
|   
 | |
|   // set everything 
 | |
|   _rdiff    = t->get_bool("B1");
 | |
|   _mcomm    = t->get_bool("B0");
 | |
|   _tpr      = t->get_int("S3");
 | |
|   _inscad   = t->get_char("S1");
 | |
|   _code     = t->get("CODTAB");
 | |
|   _name     = t->get("S0");
 | |
|   _fixd[0]  = t->get_int("I0");
 | |
|   _fixd[1]  = t->get_int("I1");
 | |
|   _fixd[2]  = t->get_int("I2");
 | |
|   _int_rate = t->get_int("I3");
 | |
| 
 | |
|   // aggiusta _inizio secondo INSCAD; vedi mese commerciale etc.                         
 | |
|   if (_inscad == 'M')
 | |
|     _inizio.set_end_month();
 | |
|   else if (_inscad == 'F' && _mcomm && _inizio.day() == 31) 
 | |
|     _inizio.set_day(30);
 | |
|   
 | |
|   // leggi rate e scadenze          
 | |
|   bool isrnew = false;
 | |
|   if (r == NULL) 
 | |
|   { 
 | |
|     r = new TTable("%RPG"); 
 | |
|     isrnew = true; 
 | |
|   }
 | |
|  
 | |
|   TString16 s; 
 | |
|   for (int i = 0; ;i++)
 | |
|   {   
 | |
|     r->zero(); s.format("%s%3d",(const char*)_code, i);
 | |
|     r->put("CODTAB", (const char*)s);
 | |
|     if (r->read() != NOERR) 
 | |
|       break;
 | |
|     TToken_string* tt = new TToken_string(48);
 | |
|     tt->add((const char*)(r->get("I0")));  // scadenza
 | |
|     tt->add((const char*)(r->get("R0")));  // percentuale
 | |
|     tt->add((const char*)(r->get("I1")));  // tipo 
 | |
|     // data e importo         
 | |
|     TDate d = _inizio; 
 | |
|     next_scad(d,(int)(r->get_long("I0")),_mcomm,i);
 | |
|     tt->add((const char*)d);  
 | |
|     tt->add("");                         
 | |
|     tt->add(r->get("S1"));                 // ulteriore classificazione
 | |
|     _rate.add(tt);
 | |
|   }
 | |
|   
 | |
|   if (istnew) delete t;
 | |
|   if (isrnew) delete r;
 | |
|   
 | |
|   return true;          
 | |
| }
 | |
| 
 | |
| 
 | |
| int TPagamento::write(TTable& r)
 | |
| {   
 | |
|   // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una
 | |
|   // relapp, che ha scritto il file principale                                 
 | |
|   
 | |
|   TString16 s; 
 | |
|   int err = NOERR;    
 | |
|   
 | |
|   for (int i = 0; err == NOERR && i < n_rate(); i++)
 | |
|   {
 | |
|     r.zero(); s.format("%s%3d",(const char*)_code, i);
 | |
|     r.put("CODTAB", s);
 | |
|     r.put("I0", (long)scad_rata(i));
 | |
|     r.put("R0", perc_rata(i).string());
 | |
|     r.put("I1", (long)tipo_rata(i));
 | |
|     r.put("S1", ulc_rata(i));
 | |
|     err = r.write();
 | |
|   }                                      
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| int TPagamento::rewrite(TTable& r)
 | |
| {
 | |
|   TString16 s; int err = NOERR;
 | |
|   int i;
 | |
|   
 | |
|   for (i = 0; err == NOERR && i < n_rate(); i++)
 | |
|   {
 | |
|     r.zero(); s.format("%s%3d",(const char*)_code, i);
 | |
|     r.put("CODTAB", s);
 | |
|     bool was = (r.read() == NOERR);
 | |
|     r.zero(); s.format("%s%3d",(const char*)_code, i);
 | |
|     r.put("CODTAB", (const char*)s);
 | |
|     r.put("I0", (long)scad_rata(i));
 | |
|     r.put("R0", perc_rata(i).string());
 | |
|     r.put("I1", (long)tipo_rata(i));
 | |
|     r.put("S1", ulc_rata(i));
 | |
|     err = (was ? r.rewrite() : r.write());
 | |
|   }                                      
 | |
|   
 | |
|   // erase possible rate > current n. rate
 | |
|   for (;err == NOERR;i++)
 | |
|   { 
 | |
|     r.zero(); s.format("%s%3d",(const char*)_code, i);
 | |
|     r.put("CODTAB", (const char*)s);
 | |
|     if (r.read() == NOERR) err = r.remove();
 | |
|     else break;
 | |
|   }
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| int TPagamento::remove(TTable& r)
 | |
| {          
 | |
|   TString16 s; int err = NOERR;
 | |
|   for (int i = 0 ; err == NOERR; i++)
 | |
|   { 
 | |
|     r.zero(); s.format("%s%3d", (const char*)_code, i);
 | |
|     r.put("CODTAB", s);
 | |
|     if (r.read() == NOERR) 
 | |
|       err = r.remove();
 | |
|     else break;
 | |
|   }  
 | |
|   return err;
 | |
| }                               
 | |
| 
 | |
| void TPagamento::set_rate_auto()
 | |
| {               
 | |
|   TWait_cursor hourglass;
 | |
| 
 | |
|   // vedi rate esistenti e tipo prima rata 
 | |
|   // deve fare riferimento ad un tipo pagamento esistente
 | |
|   // e sensato
 | |
| 
 | |
|   if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1))  
 | |
|     return;
 | |
|   int first = _tpr > 3 ? 1 : 0;                           
 | |
| 
 | |
|   set_inizio(_datadoc);
 | |
| 
 | |
|   for (int va = 0; va < (in_valuta() ? 2 : 1); va++)
 | |
|   {  
 | |
|     const bool v = va != 0;
 | |
|     real toslice = importo_da_dividere(v); 
 | |
|     if (_tpr > 3) 
 | |
|       set_imprata(0, importo_da_non_dividere(v), v); 
 | |
|     real r1(0.0), ro(0.0); 
 | |
|     if (!_rdiff)
 | |
|     {                         
 | |
|       const int rut = _tpr > 3 ? n_rate() - 1 : n_rate();
 | |
|       if (rut > 1)  // Guy was here! Don't kill me for this
 | |
|       {
 | |
|         real refrata = CENTO/real(rut); refrata.round(PERC_DECIMALS);
 | |
|         if (perc_rata(first+1) == refrata) // tutte uguali nonostante perc arrotondate
 | |
|         {
 | |
|           ro = toslice / real(rut);
 | |
|           ro.round(round(v)); 
 | |
|           r1 = toslice - (ro * real(rut-1));
 | |
|         } 
 | |
|         else // la prima e' diversa
 | |
|         {
 | |
|           // usa la percentuale per la prima rata
 | |
|           r1 = (toslice * perc_rata(first))/CENTO; 
 | |
|     
 | |
|           const real reminder = toslice - r1;
 | |
|           if (!reminder.is_zero()) 
 | |
|           {
 | |
|             ro = reminder/real(rut-1); ro.round(round(v));
 | |
|             r1 = (toslice - (ro*real(rut-1)));
 | |
|           }
 | |
|         }
 | |
|       }  
 | |
|       else
 | |
|         r1 = toslice;  
 | |
|       r1.round(round(v));
 | |
|     }
 | |
|   
 | |
|     real rdi, rdsum;
 | |
| 
 | |
|     for (int i = first; i < n_rate(); i++)        
 | |
|       // setta le fette e le date di scadenza
 | |
|     { 
 | |
|       if (_rdiff) 
 | |
|       {  
 | |
|         rdi = toslice*(perc_rata(i)/CENTO);
 | |
|         rdi.round(round(v));
 | |
|         if (i > first) rdsum += rdi;
 | |
|       }
 | |
|       set_imprata(i, _rdiff ? rdi : (i == first ? r1 : ro), v);
 | |
|     }                
 | |
|     if (_rdiff)
 | |
|       set_imprata(first, toslice - rdsum, v);
 | |
|       
 | |
|     // se e' nei primi tre casi, si somma l'importo da non dividere alla
 | |
|     // prima rata                                        
 | |
|     if (_tpr > 0 && _tpr < 4)
 | |
|       set_imprata(0, importo_rata(0,v) + importo_da_non_dividere(v), v);  
 | |
|   }
 | |
| }                                     
 | |
| 
 | |
| const real&  TPagamento::importo_da_dividere(bool v) const     
 | |
| {
 | |
|   if (_tpr < 4) return v ? _firstr : _firstl; 
 | |
|   else return v ? _secndr : _secndl;
 | |
| }
 | |
| 
 | |
| const real& TPagamento::importo_da_non_dividere(bool v)  const
 | |
| {
 | |
|   if (_tpr < 4) return v ? _secndr : _secndl; 
 | |
|   else return v ? _firstr : _firstl;
 | |
| }
 | |
| 
 | |
| void TPagamento::set_total(const real& ib, const real& im, const real& sp)
 | |
| {
 | |
|   _in_valuta = false;        
 | |
|   _firstr = _secndr = ZERO;            // Azzera importi in valuta
 | |
|   init_total(ib, im, sp, NULL);        // setta regolarmente totali in lire
 | |
| }
 | |
|                           
 | |
| void TPagamento::set_total_valuta(const real& ib,  const real& im,  const real& sp, const real& c,
 | |
|                                   const real& ibl, const real& iml, const real& spl, const char* codval)
 | |
| { 
 | |
|   CHECKS(is_true_value(codval), "Valuta non valida ", codval);
 | |
|   const bool era_valuta = _in_valuta;
 | |
| 
 | |
|   _in_valuta = true;        
 | |
|   // setta regolarmente totali in lire
 | |
|   init_total(ibl, iml, spl, NULL);           
 | |
|   // ripeti tutto con la valuta
 | |
|   init_total(ib, im, sp, codval);           
 | |
|   
 | |
|   if (!era_valuta && _in_valuta)
 | |
|     adjust_perc_imp(true, _rdiff, true);
 | |
| }  
 | |
|                           
 | |
| void TPagamento::init_total(const real& ib, const real& im, const real& sp, const char* codval)
 | |
| { 
 | |
|   const bool valuta = (codval != NULL) && *codval && TCurrency::get_firm_val() != codval;
 | |
|   if (valuta)
 | |
|   {
 | |
|     const TCurrency cur(ZERO, codval);
 | |
|     _roundval = cur.decimals();
 | |
|   }
 | |
|   else
 | |
|     _roundlit = TCurrency::get_firm_dec();
 | |
| 
 | |
|   const int round = valuta ? _roundval : _roundlit;  
 | |
|   real& ibp = valuta ? _imponval : _imponlit;
 | |
|   real& imp = valuta ? _imposval : _imposlit;
 | |
|   real& spp = valuta ? _speseval : _speselit;
 | |
|   real& frs = valuta ? _firstr   : _firstl;
 | |
|   real& scn = valuta ? _secndr   : _secndl;
 | |
|    
 | |
|   ibp = ib; ibp.round(round);
 | |
|   imp = im; imp.round(round);
 | |
|   spp = sp; spp.round(round);
 | |
|   _inited   = true;
 | |
|   
 | |
|   // istanzia _firstr e _secndr a seconda di _tpr  
 | |
|   switch(_tpr)
 | |
|   {          
 | |
|     case 0:                                         
 | |
|       frs = ibp + imp + spp;
 | |
|       scn = 0.0;
 | |
|       break;              
 | |
|     case 1: 
 | |
|       scn = imp;
 | |
|       frs = ibp + spp;
 | |
|       break;
 | |
|     case 2: 
 | |
|       scn = spp;
 | |
|       frs = ibp + imp;
 | |
|       break;
 | |
|     case 3:
 | |
|       scn = imp + spp; 
 | |
|       frs = ibp;
 | |
|       break;
 | |
|     case 4: 
 | |
|       scn = spp + ibp;
 | |
|       frs = imp;
 | |
|       break;  
 | |
|     case 5:     
 | |
|       scn = ibp + imp;
 | |
|       frs = spp;
 | |
|       break;  
 | |
|     case 6:            
 | |
|       scn = ibp;
 | |
|       frs = imp + spp;
 | |
|       break;  
 | |
|   }
 | |
| }                            
 | |
| 
 | |
| 
 | |
| void TPagamento::set_sheet(TSheet_field& sf, int sscad)
 | |
| {                             
 | |
|   TWait_cursor hourglass;
 | |
|   
 | |
|   if (_rate.items() == 0)
 | |
|   {   
 | |
|     if (_tpr > 3) 
 | |
|       add_rata(ZERO, sscad <= 0 ? 0 : sscad, _def_tpr, _def_ulc);
 | |
|     add_rata(CENTO, sscad <= 0 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc);  
 | |
|     _dirty = true;
 | |
|   }
 | |
|   
 | |
|   if (_inited)
 | |
|   {
 | |
|     // si istanzia uno sheet di primanota
 | |
|     int i;
 | |
|     
 | |
|     for (i = 0; i < n_rate(); i++)
 | |
|     {                                        
 | |
|       TToken_string& ts = sf.row(i);
 | |
|         
 | |
|       ts.add(data_rata(i), 0);                        // 0 - Data scadenza
 | |
|       if (in_valuta())
 | |
|       {
 | |
|         ts.add(tlit_rata(i).string(), 1);             // 1 - Importo in lire
 | |
|         ts.add(tval_rata(i).string(), 2);             // 2 - Importo in valuta
 | |
|       }  
 | |
|       else                                            
 | |
|       {
 | |
|         ts.add(tlit_rata(i).string(), 1);             // 1 - Importo
 | |
|         ts.add("", 2);
 | |
|       }
 | |
|       ts.add(perc_rata(i).string(), 3);               // 3 - Percentuale
 | |
|         
 | |
|       const int tr = tipo_rata(i);
 | |
|       const char uc = ulc_rata(i)[0];
 | |
|       ts.add(tr, 4);                                  // 4 - Tipo rata
 | |
|       ts.add(uc, 5);                                  // 5 - Ulteriore classificazione
 | |
|       ts.add(desc_tipo(tr, uc), 6);                   // 6 - Descrizione tipo rata  
 | |
|     }
 | |
|       
 | |
|     for (int d = sf.items()-1; d >= i; d--)
 | |
|       sf.destroy(d, false);
 | |
|           
 | |
|     sf.enable_column(2, in_valuta());
 | |
|   }
 | |
|   else 
 | |
|   {
 | |
|     long scr = 0L;
 | |
|     int i;
 | |
|     
 | |
|     for (i = 0; i < n_rate(); i++)
 | |
|     {
 | |
|       TToken_string& s = sf.row(i);
 | |
|       scr += scad_rata(i);   
 | |
|       s = "";   
 | |
|       s.add(scr);
 | |
|       s.add(perc_rata(i).string());
 | |
|         
 | |
|       const int tr = tipo_rata(i);
 | |
|       const char uc = ulc_rata(i)[0];
 | |
|       s.add(tr);
 | |
|       s.add(uc);       
 | |
|       s.add(desc_tipo(tr, uc));
 | |
|     } 
 | |
| 
 | |
|     for (int d = sf.items()-1; d >= i; d--)
 | |
|       sf.destroy(d, false);
 | |
|   }
 | |
|   
 | |
|   const bool abilita = _tpr <= 3;
 | |
|   // disabilita campi da non toccare sulla prima rata
 | |
|   if (_inited)
 | |
|   {        
 | |
| //    sf.enable_cell(0, 1, abilita); // importo
 | |
| //    sf.enable_cell(0, 2, abilita); // in valuta
 | |
| //    sf.enable_cell(0, 3, abilita); // percentuale
 | |
|     sf.force_update();   
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     sf.enable_cell(0, 1, abilita); // percentuale
 | |
|   }
 | |
| }
 | |
|    
 | |
| void TPagamento::adjust_fixed_scad()
 | |
| {   
 | |
|   if (!_inited) return;
 | |
|   
 | |
|   const bool are_fixed = _fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0;
 | |
|   int i;
 | |
|   
 | |
|   for (i = 0; i < n_rate(); i++)
 | |
|   { 
 | |
|     TDate d = data_rata(i);
 | |
|     
 | |
|     // riaggiusta se ci sono scadenze fissate
 | |
|     if (are_fixed)
 | |
|     {
 | |
|       int i;
 | |
|       
 | |
|       for (i = 0; i < 3; i++)
 | |
|       {
 | |
|         if (_fixd[i] >= d.day())
 | |
|         { 
 | |
|           if (d.last_day(d.month(), d.year()) >= _fixd[i]) 
 | |
|             d.set_day(_fixd[i]);  
 | |
|           else 
 | |
|             d.set_end_month();
 | |
|           break;
 | |
|         } 
 | |
|       } 
 | |
|       
 | |
|       if (i == 3)
 | |
|       {
 | |
|         if (_fixd[0] > 0 && _fixd[0] < d.day())
 | |
|         {
 | |
|           d.set_day(_fixd[0]);       
 | |
|           const bool chyear = d.month() == 12;
 | |
|           d.set_month(chyear ? 1 : d.month() + 1);
 | |
|           if (chyear) d.set_year(d.year() + 1);  
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     TToken_string& tt = rata(i);
 | |
|     tt.add(d.string(), 3);
 | |
|   }
 | |
| 
 | |
|   adjust_refused_scad();
 | |
| }
 | |
| 
 | |
| void TPagamento::adjust_refused_scad()
 | |
| {
 | |
|   if (_codcf <= 0L)
 | |
|     return;
 | |
| 
 | |
|   CHECK(_tipocf == 'C' || _tipocf == 'F', "Bad tipocf in pagament");
 | |
| 
 | |
|   TString16 codice;
 | |
|   codice << _tipocf << '|' << _codcf;
 | |
|   const TRectype& clifo = cache().get(LF_CFVEN, codice);
 | |
| 
 | |
|   const TToken_string nonacceff(clifo.get(CFV_NONACCEFF), ';');
 | |
|   if (nonacceff.empty_items())
 | |
|     return;
 | |
|   const TToken_string nonscadeff(clifo.get(CFV_NONSCADEFF), ';');
 | |
| 
 | |
|   TToken_string intervallo(12, ',');
 | |
|   TToken_string dalgiorno(5, '-'), algiorno(5, '-');
 | |
|   for (int i = 0; i < n_rate(); i++)
 | |
|   { 
 | |
| 		TTipo_pag tipo = tipo_rata(i);
 | |
| 	
 | |
| 		if (tipo == _tratta ||
 | |
| 				tipo == _ric_ban ||
 | |
| 				tipo == _cessione ||
 | |
| 				tipo == _paghero ||
 | |
| 				tipo == _tratta_acc)
 | |
| 		{
 | |
| 			const TDate d = data_rata(i);
 | |
| 			int inter = 0;
 | |
| 			for (bool good = nonacceff.get(inter, intervallo); 
 | |
| 					 good; good = nonacceff.get(++inter, intervallo))
 | |
| 			{
 | |
| 				intervallo.get(0, dalgiorno);
 | |
| 				int gio = dalgiorno.get_int(0);
 | |
| 				int mes = dalgiorno.get_int(1);
 | |
| 				if (mes <= 0 || mes > 12) mes = 1;
 | |
| 				int ann = d.year();
 | |
| 				int max_gio = TDate::last_day(mes, ann);
 | |
| 				if (gio <= 0) gio = 1; else
 | |
| 				if (gio > max_gio) gio = max_gio;
 | |
| 
 | |
| 				const TDate frd(gio, mes, ann);
 | |
| 				if (d < frd)
 | |
| 					continue;
 | |
| 
 | |
| 				intervallo.get(1, algiorno);
 | |
| 				gio = algiorno.get_int(0);
 | |
| 				mes = algiorno.get_int(1);
 | |
| 				if (mes <= 0 || mes > 12) mes = 1;
 | |
| 				ann += (mes < frd.month()) ? 1 : 0;
 | |
| 				max_gio = TDate::last_day(mes, ann);
 | |
| 				if (gio <= 0 || gio > max_gio)
 | |
| 					gio = max_gio;
 | |
| 				const TDate tod(gio, mes, ann);
 | |
| 				if (d > tod)
 | |
| 					continue;
 | |
| 	      
 | |
| 				nonscadeff.get(inter, algiorno);
 | |
| 				gio = algiorno.get_int(0);
 | |
| 				mes = algiorno.get_int(1);
 | |
| 				ann += (mes < tod.month()) ? 1 : 0;
 | |
| 				if (mes <= 0 || mes > 12) mes = 1;
 | |
| 				max_gio = TDate::last_day(mes, ann);
 | |
| 				if (gio <= 0 || gio > max_gio)
 | |
| 					gio = max_gio;
 | |
| 
 | |
| 				const TDate nd(gio, mes, ann);   
 | |
| 				TToken_string& tt = rata(i);
 | |
| 				tt.add(nd.string(), 3);
 | |
| 				break; 
 | |
| 			}
 | |
| 		}
 | |
|   }
 | |
| }
 | |
|    
 | |
| TPagamento::TPagamento(const char* codtab, const char* data) :
 | |
|   _code(codtab), _imponval(0.0), _imposval(0.0), _speseval(0.0),
 | |
|   _imponlit(0.0), _imposlit(0.0), _speselit(0.0), _new(false), _mcomm(false), // _cambio(1.0),
 | |
|   _rdiff(false), _tpr(0), _dirty(false), _inited(false), _roundlit(0), _roundval(3), _int_rate(30),
 | |
|   _def_tpr(1), _def_ulc(""), _was_tpr4(false), _in_valuta(false), _tipocf('C'), _codcf(0L)
 | |
| {               
 | |
|   _fixd[0] = _fixd[1] = _fixd[2] = 0;
 | |
|   if (data != NULL && *data)     
 | |
|     _inizio = data;
 | |
|   else
 | |
|     _inizio = TDate(TODAY);
 | |
|   _datadoc = _inizio;
 | |
|     
 | |
|   if (_code.blank() || !read()) 
 | |
|     _new = true;    
 | |
| }  
 |