907 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			907 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include "pagament.h"
 | 
						|
#include <utility.h>
 | 
						|
 | 
						|
int Pagamento::_rata_ifield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return t.get_int(f);
 | 
						|
}                            
 | 
						|
 | 
						|
real Pagamento::_rata_rfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return real(t.get(f));
 | 
						|
}                            
 | 
						|
 | 
						|
TDate Pagamento::_rata_dfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return TDate(t.get(f));
 | 
						|
}                                 
 | 
						|
 | 
						|
const char* Pagamento::_rata_sfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  static char kak[6];
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  strcpy(kak,t.get(f)); 
 | 
						|
  return kak;
 | 
						|
}                                 
 | 
						|
 | 
						|
 | 
						|
void Pagamento::set_intervallo_rate(int in)
 | 
						|
{
 | 
						|
	_dirty = TRUE;
 | 
						|
	if (_mcomm  && (in % 30) != 0)
 | 
						|
		_mcomm = FALSE;
 | 
						|
	for (int i = 0; i < n_rate(); i++)
 | 
						|
	{       
 | 
						|
		TToken_string& ts = rata(i);
 | 
						|
		ts.add(i == 0 ? "0" : format("%d",in), 0);		
 | 
						|
	}
 | 
						|
}
 | 
						|
    
 | 
						|
void Pagamento::set_mese_commerciale(bool v, int& sscad)
 | 
						|
{
 | 
						|
	_dirty = FALSE;
 | 
						|
	if (_mcomm == v) return;  
 | 
						|
	if (sscad == -1) sscad = 30;
 | 
						|
	
 | 
						|
	if ((sscad % 30) != 0) sscad = 30 * ((sscad/30)+1);
 | 
						|
	set_intervallo_rate(sscad);
 | 
						|
	
 | 
						|
	_mcomm = v;	
 | 
						|
}        
 | 
						|
 | 
						|
void Pagamento::set_rate_differenziate(int v)
 | 
						|
{                           
 | 
						|
	_dirty = FALSE;
 | 
						|
	if (!_rdiff && v == 2) return; 
 | 
						|
	
 | 
						|
	if (v == 2 && (100 % n_rate()) == 0)
 | 
						|
	{
 | 
						|
		int p = 100 / n_rate();
 | 
						|
		for (int i = _tpr == 0 ? 0 : 1; i < n_rate(); i++)
 | 
						|
		{
 | 
						|
			TToken_string& tt = rata(i);
 | 
						|
			tt.add(p,1);
 | 
						|
		}
 | 
						|
		_rdiff = !(v == 2);
 | 
						|
		_dirty = TRUE;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Pagamento::set_tipo_prima_rata(int v, int sscad)
 | 
						|
{                           
 | 
						|
	_dirty = FALSE;
 | 
						|
	if (_tpr == v) return;
 | 
						|
    
 | 
						|
    if (v == 0 && _tpr > 0)
 | 
						|
    {
 | 
						|
    	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.add(NULL,0);
 | 
						|
    	_rate.pack();	
 | 
						|
    }
 | 
						|
    else if ( _tpr == 0 && v > 0)                    
 | 
						|
    {   
 | 
						|
       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);
 | 
						|
       	  }
 | 
						|
       }
 | 
						|
    }
 | 
						|
	_tpr = v;    
 | 
						|
	_dirty = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void Pagamento::set_numero_rate(int n, int sscad)
 | 
						|
{                         
 | 
						|
	_dirty = FALSE;
 | 
						|
	if (n == 0 || n == n_rate()) return; 
 | 
						|
	
 | 
						|
	int p =   100 / n;
 | 
						|
	int nr = n_rate();
 | 
						|
	int first = _tpr == 0 ? 0 : 1;
 | 
						|
	               
 | 
						|
	for (int i = first, sum = 0; sum < 100; i++)
 | 
						|
	{
 | 
						|
		if ((100 - sum) < p) p = 100 - sum;
 | 
						|
		sum += p; 
 | 
						|
		
 | 
						|
		set_rata(i, real(p), 
 | 
						|
					i == 0 ? 0 :
 | 
						|
					(sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad),
 | 
						|
					(i < nr ? tipo_rata(i) : tipo_rata(nr-1)));
 | 
						|
	}
 | 
						|
	
 | 
						|
	_dirty = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
                           
 | 
						|
void Pagamento::next_scad(TDate& d, int scad, bool mcomm, int rata)
 | 
						|
{
 | 
						|
	if (mcomm)
 | 
						|
	{
 | 
						|
	    int nm   = scad / 30;
 | 
						|
		int ny   = nm   / 12;
 | 
						|
		nm  %= 12;
 | 
						|
        
 | 
						|
        int newm = d.month() + nm;
 | 
						|
        if (newm > 12) { newm -= 12; ny++; }
 | 
						|
		
 | 
						|
		bool last = d.is_end_month() && inizio_scadenza() == 'M';
 | 
						|
                
 | 
						|
        int dy = d.day();
 | 
						|
                                             
 | 
						|
        // la palla del febbraio & c.                                    
 | 
						|
        if (rata > 1)
 | 
						|
        {
 | 
						|
        	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);
 | 
						|
		
 | 
						|
		d.set_end_month();  
 | 
						|
		if (!last && dy < d.day()) d.set_day(dy);
 | 
						|
	}
 | 
						|
	else d += scad;
 | 
						|
}
 | 
						|
                            
 | 
						|
                            
 | 
						|
void Pagamento::remove_rata(int i)
 | 
						|
{                         
 | 
						|
	// non fa nessun ricalcolo, si limita ad impacchettare se 
 | 
						|
	// necessario
 | 
						|
	_rate.add(NULL,i);
 | 
						|
	_rate.pack();
 | 
						|
	_dirty = TRUE;
 | 
						|
}             
 | 
						|
             
 | 
						|
TToken_string& Pagamento::add_rata(real perc, int day, int type)
 | 
						|
{
 | 
						|
  TToken_string* tt = new TToken_string(16);
 | 
						|
  tt->add(day);                // scadenza
 | 
						|
  tt->add(perc.string());      // percentuale
 | 
						|
  tt->add(type);               // tipo
 | 
						|
  
 | 
						|
  _rate.add(tt);             
 | 
						|
  _dirty = TRUE;
 | 
						|
  return *tt;
 | 
						|
}
 | 
						|
 | 
						|
TToken_string& Pagamento::set_rata (int index, real perc, int day, int type,
 | 
						|
									const char* ulc, const char* imp, 
 | 
						|
									const char* data)
 | 
						|
{                                   
 | 
						|
  bool nwr = FALSE;
 | 
						|
  TToken_string* tt = (TToken_string*)_rate.objptr(index);
 | 
						|
  if (nwr = (tt == NULL)) tt = new TToken_string(16); 
 | 
						|
  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,4);
 | 
						|
  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 Pagamento::set_imprata(int i, real r)
 | 
						|
{
 | 
						|
  TToken_string& tt = (TToken_string&)_rate[i];  
 | 
						|
  TDate d = _inizio; 
 | 
						|
 | 
						|
  for (int n = 0; n <= i; n++)
 | 
						|
    next_scad(d, scad_rata(n), _mcomm, n); 
 | 
						|
 | 
						|
  tt.add((const char*)d, 3);
 | 
						|
  tt.add(r.string(), 4);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
word Pagamento::validate() const
 | 
						|
{
 | 
						|
  word res = 0x0000; 
 | 
						|
  real r(0.0);
 | 
						|
                    
 | 
						|
  int first    = _tpr == 0 ? 0 : 1;        
 | 
						|
  real toshare(_tpr == 0 ? _firstr : _secndr);    
 | 
						|
  TDistrib ds(toshare,0);          
 | 
						|
                    
 | 
						|
  // check percentages & prepare slicer
 | 
						|
  for (int i = first; i < n_rate(); i++)
 | 
						|
    {                
 | 
						|
    	real p(perc_rata(i));
 | 
						|
    	ds.add(p);
 | 
						|
    	r += p; 
 | 
						|
    }
 | 
						|
             
 | 
						|
  if (r != real(100.0))
 | 
						|
  	res |= P_RSUM;            
 | 
						|
  
 | 
						|
 | 
						|
  if (_inited)
 | 
						|
  {
 | 
						|
 	  ds.init(toshare);
 | 
						|
	  // check importi rate consistenti con la percentuale
 | 
						|
	  for (int i = first; i < n_rate(); i++)
 | 
						|
	  {                 
 | 
						|
	  	real r1(tpay_rata(i));  
 | 
						|
	  	real r2(ds.get());
 | 
						|
	  	if (r1 != r2) 
 | 
						|
	  		{ res |= P_IMPNC; break; }		
 | 
						|
	  }     
 | 
						|
 | 
						|
	  // check errori date scadenze (se istanziate)
 | 
						|
      TDate d(data_rata(0));
 | 
						|
      if (d < _inizio) 
 | 
						|
      	res |= P_INIZIO;
 | 
						|
      for (i = 1; i < n_rate(); i++)
 | 
						|
	  {
 | 
						|
	    if (data_rata(i) <= d) 
 | 
						|
	    	{ res |= P_SCAD; break; }
 | 
						|
	    d = data_rata(i);
 | 
						|
	  }     
 | 
						|
  }
 | 
						|
  return res;
 | 
						|
}                                                                     
 | 
						|
 | 
						|
 | 
						|
void Pagamento::strerr(word err, TString& s)
 | 
						|
{
 | 
						|
  s = "Errore:";
 | 
						|
  if (err & P_RSUM)
 | 
						|
    s << "\n   Le percentuali non sommano a 100";
 | 
						|
  if (err & P_IMPNC)
 | 
						|
    s << "\n   Le percentuali sono inconsistenti con gli importi";
 | 
						|
  if (err & P_SCAD)
 | 
						|
    s << "\n   Le scadenze non sono consecutive";
 | 
						|
  if (err & P_INIZIO)
 | 
						|
    s << "\n   La prima rata e' antecedente alla data movimento";
 | 
						|
}
 | 
						|
                        
 | 
						|
const char* Pagamento::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 = "Spese + merce su 1a"; break;
 | 
						|
		case 5: o = "Merce + imposte su 1a"; break;
 | 
						|
		case 6: o = "Tutta la merce su 1a"; break;
 | 
						|
	} 
 | 
						|
	return o;
 | 
						|
}                        
 | 
						|
 | 
						|
const char* Pagamento::desc_tipo(int i) const
 | 
						|
{         
 | 
						|
	const char* o;
 | 
						|
    switch (i)
 | 
						|
    {   
 | 
						|
      case 1: o = "Rimessa diretta / contanti"; break;
 | 
						|
      case 2: o = "Tratta"; break;
 | 
						|
      case 3: o = "Ricevuta bancaria"; break;
 | 
						|
      case 4: o = "Cessione"; break;
 | 
						|
      case 5: o = "Paghero'"; break;
 | 
						|
      case 6: o = "Lettera di credito"; break;
 | 
						|
      case 7: o = "Tratta accettata"; break;                   
 | 
						|
      case 8: o = "Altro pagamento"; break;
 | 
						|
    } 
 | 
						|
    return o;            
 | 
						|
}
 | 
						|
                        
 | 
						|
word Pagamento::recalc_rate(int row, bool is_perc_modified, 
 | 
						|
                            const char* new_value, const char* scad, 
 | 
						|
                            const char* typ, 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 && !_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); 
 | 
						|
  int oldtype    = tipo_rata(0);
 | 
						|
  int oldscad    = scad_rata(0);
 | 
						|
  TDate lastdate = data_rata(0);  
 | 
						|
  int first      = _tpr == 0 ? 0 : 1;
 | 
						|
  TArray srate(_rate);   // rate come erano   
 | 
						|
 | 
						|
                       
 | 
						|
  if (srate.items() > 1)
 | 
						|
  {
 | 
						|
  	// calcola defaults per tipo pagamento e scadenza
 | 
						|
  	// nel caso di rate nuove
 | 
						|
	oldscad = scad_rata(1);
 | 
						|
  }       
 | 
						|
 | 
						|
  if (oldscad == 0) oldscad = 30;
 | 
						|
  if (oldtype == 0) oldtype = 1;
 | 
						|
    
 | 
						|
  if (new_value != NULL)
 | 
						|
  {     
 | 
						|
    newv = new_value;                       
 | 
						|
    rmax = is_perc_modified? real(100.0) : (_tpr == 0 ? _firstr : _secndr);
 | 
						|
    if (newv > rmax) return P_RSUM;
 | 
						|
  }                                                   
 | 
						|
  
 | 
						|
  bool exhausted = FALSE;
 | 
						|
  
 | 
						|
  for (int i = first; i < srate.items(); i++)
 | 
						|
  {
 | 
						|
	if (i == row)
 | 
						|
	{  
 | 
						|
		if (typ != NULL)
 | 
						|
		{	
 | 
						|
			TToken_string& tt = rata(row);
 | 
						|
			TToken_string& ss = (TToken_string&)srate[row];
 | 
						|
			tt.add(typ,2);
 | 
						|
			ss.add(typ,2);			                     
 | 
						|
			// 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;                             
 | 
						|
				// controlla errore sulla data scadenza
 | 
						|
				if (i > 0) 
 | 
						|
				{
 | 
						|
					oldscad  =  (int)(lastdate - data_rata(i-1)); 
 | 
						|
					if (oldscad <= 0l) return P_SCAD;
 | 
						|
				}
 | 
						|
				else if (lastdate < _inizio) return P_INIZIO;
 | 
						|
				tt.add(scad,3);
 | 
						|
				ss.add(scad,3);      
 | 
						|
				// 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& tt = rata(j);
 | 
						|
					TToken_string& ss = (TToken_string&)srate[j];
 | 
						|
					next_scad(ddd,scad_rata(j),mcomm,j);
 | 
						|
					tt.add(ddd.string(),3);
 | 
						|
					ss.add(ddd.string(),3);
 | 
						|
					need_recalc = TRUE;      
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{ 
 | 
						|
				// nulla di speciale visto che si memorizza la derivata
 | 
						|
				int sc = atoi(scad);
 | 
						|
				if (sc <= 0) return P_SCAD;
 | 
						|
				if (_mcomm && (sc % 30) != 0) _mcomm = FALSE;
 | 
						|
				TToken_string& tt = rata(row);
 | 
						|
				TToken_string& ss = (TToken_string&)srate[row];
 | 
						|
				tt.add(0,sc);
 | 
						|
				ss.add(1,sc);				
 | 
						|
			}       
 | 
						|
		}                 
 | 
						|
		
 | 
						|
		// here's the bell
 | 
						|
		if (new_value != NULL)
 | 
						|
		{                       
 | 
						|
			if (newv == ZERO || (rsum+newv) > rmax) 
 | 
						|
				return P_RSUM; 
 | 
						|
			// did not sforate
 | 
						|
			rsum += newv;         
 | 
						|
			TToken_string& rt = rata(row);
 | 
						|
			// setta nuovo valore e ricalcola cio' che ne consegue
 | 
						|
			if (is_perc_modified) rt.add(new_value,1);
 | 
						|
			else rt.add(new_value,4);
 | 
						|
			// riaggiusta le rate rimanenti
 | 
						|
			real remainder(0.0); remainder = rmax - rsum;
 | 
						|
			if (!(exhausted = (remainder == real(0.0))))
 | 
						|
			{                                            
 | 
						|
				// controlla se rdiff e' compatibile con
 | 
						|
				// i dati e se e' il caso riaggiusta
 | 
						|
				if (rdiff == 3 && !((remainder % newv.integer()) == ZERO))
 | 
						|
					rdiff = 2;
 | 
						|
				if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) 
 | 
						|
					rdiff = 1;                   
 | 
						|
				_rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4);
 | 
						|
 | 
						|
				// procedi			
 | 
						|
				if (rdiff == 1) 
 | 
						|
				{
 | 
						|
					// cancella tutte le rate successive, aggiungi un'unica rata 
 | 
						|
					// con il resto dell'importo                                
 | 
						|
					if (row < (srate.items()-1))
 | 
						|
					{
 | 
						|
						TToken_string& trt = rata(row+1);
 | 
						|
						trt.add(remainder.string(), is_perc_modified ? 1 : 4);     
 | 
						|
						for(int j = row+2; j < srate.items(); j++)
 | 
						|
							_rate.add(NULL,j);
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						// l'importante e' esagerare
 | 
						|
						for(int j = row+1; j < srate.items(); j++)
 | 
						|
							_rate.add(NULL,j); 
 | 
						|
							
 | 
						|
						TToken_string& trt = add_rata(is_perc_modified? remainder : real(0.0), 
 | 
						|
													 oldscad, oldtype);
 | 
						|
						if (!is_perc_modified) trt.add(remainder.string(),4);
 | 
						|
						if (_inited)
 | 
						|
						{ 
 | 
						|
							TDate dd = data_rata(row); 
 | 
						|
							next_scad(dd,oldscad,mcomm,row);
 | 
						|
							trt.add(dd.string(),3); 
 | 
						|
						}
 | 
						|
					} 
 | 
						|
				}
 | 
						|
				else  // rate non differenziate (dall'inizio o da row)
 | 
						|
				{
 | 
						|
					// ripartisci l'importo nel numero necessario di rate per
 | 
						|
					// mantenere costante il valore 
 | 
						|
					real sum(0.0);
 | 
						|
					if (_inited) lastdate = data_rata(rdiff == 2 ? first : row);
 | 
						|
						
 | 
						|
					TDate dd(lastdate);
 | 
						|
					int type = oldtype;
 | 
						|
					int nscd = oldscad;                        
 | 
						|
					
 | 
						|
					int  frs = (rdiff == 3 || rdiff == 4) ? row+1     : first;
 | 
						|
					real mx  = (rdiff == 3 || rdiff == 4) ? remainder : rmax;
 | 
						|
					
 | 
						|
					// cancelliamo tutto, va'
 | 
						|
					for (int j = frs; j < srate.items(); j++)
 | 
						|
						_rate.add(NULL,j);
 | 
						|
					
 | 
						|
					if (rdiff != 4)	
 | 
						|
					  for (j = frs; sum < mx; j++)
 | 
						|
					  {	
 | 
						|
						// se c'e' la vecchia rata si tengono i parametri
 | 
						|
						// altrimenti si calcolano 
 | 
						|
						if (j < srate.items())
 | 
						|
						{   
 | 
						|
							TToken_string& trt = (TToken_string&)srate[j];
 | 
						|
							if (_inited) dd   = trt.get(3);
 | 
						|
							type = atoi(trt.get(2));
 | 
						|
							nscd = j == 0 ? 0 : atoi(trt.get(0));	
 | 
						|
							if (type == 0) type = 1;
 | 
						|
							if (j > 0 && nscd == 0) nscd = oldscad;
 | 
						|
							if (_inited && dd == lastdate && j > 0) 
 | 
						|
								next_scad(dd,nscd,mcomm,j);
 | 
						|
						}
 | 
						|
						else if (_inited) 
 | 
						|
						{
 | 
						|
							if (dd <= botime) dd = lastdate;
 | 
						|
							next_scad(dd,nscd,mcomm,j); 
 | 
						|
						} 
 | 
						|
						          
 | 
						|
						TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO,
 | 
						|
													  nscd, type); 
 | 
						|
						if (_inited)
 | 
						|
							ttr.add(dd.string(), 3);
 | 
						|
                        if (!is_perc_modified)
 | 
						|
                        	ttr.add(newv.string(),4);
 | 
						|
						sum += newv;
 | 
						|
					  }			
 | 
						|
					else  // rdiff == 4; uguali finche' possibile
 | 
						|
    				{
 | 
						|
				   	  	bool basta = FALSE;       
 | 
						|
					    for (j = frs; ; j++)
 | 
						|
				   	    {	
 | 
						|
				   	      // ultima rata puo' differire dalle precedenti     
 | 
						|
				   	  	  if (mx - sum <= newv) 
 | 
						|
				   	  	  {
 | 
						|
				   	    	 newv = mx - sum;
 | 
						|
				   	    	 basta = TRUE;
 | 
						|
				   	      }
 | 
						|
				  		  // se c'e' la vecchia rata si tengono i parametri
 | 
						|
			  			  // altrimenti si calcolano 
 | 
						|
		  				  if (j < srate.items())
 | 
						|
						  {   
 | 
						|
							  TToken_string& trt = (TToken_string&)srate[j];
 | 
						|
						  	  if (_inited) dd   = trt.get(3);
 | 
						|
							  type = atoi(trt.get(2));
 | 
						|
							  nscd = j == 0 ? 0 : atoi(trt.get(0));	
 | 
						|
							  if (type == 0) type = 1;
 | 
						|
							  if (j > 0 && nscd == 0) nscd = oldscad;
 | 
						|
							  if (_inited && dd == lastdate && j > 0)
 | 
						|
							  	 next_scad(dd,nscd,mcomm,j);
 | 
						|
						  }
 | 
						|
						  else if (_inited) next_scad(dd,nscd,mcomm,j);  
 | 
						|
						         
 | 
						|
						  TToken_string& ttr = set_rata(j, is_perc_modified ? newv : ZERO,
 | 
						|
												 nscd, type); 
 | 
						|
						  if (_inited)
 | 
						|
							  ttr.add(dd.string(), 3);
 | 
						|
                          if (!is_perc_modified)
 | 
						|
                        	  ttr.add(newv.string(),4);
 | 
						|
						  if (basta) break; 
 | 
						|
						  sum += newv;
 | 
						|
					    }					
 | 
						|
		            }
 | 
						|
				}          
 | 
						|
			
 | 
						|
			}
 | 
						|
			else  // exhausted
 | 
						|
			{
 | 
						|
				for(int j = row+1; j < srate.items(); j++)
 | 
						|
					_rate.add(NULL,j);				
 | 
						|
			}             
 | 
						|
			
 | 
						|
			
 | 
						|
			if (_inited)
 | 
						|
			{
 | 
						|
			    // ricalcola il valore secondario (non modificato)
 | 
						|
				real toshare(100.0); 
 | 
						|
				if (is_perc_modified) 
 | 
						|
					toshare = (_tpr == 0 ? _firstr : _secndr);  
 | 
						|
				TDistrib dt(toshare,0);                 
 | 
						|
			
 | 
						|
				for (int j = first; j < _rate.items(); j++)
 | 
						|
				{   
 | 
						|
					real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); 
 | 
						|
					real zpx = rvl/rmax; // percentuale
 | 
						|
					dt.add(zpx);				
 | 
						|
				}    
 | 
						|
				for (j = first; j < _rate.items(); j++)
 | 
						|
				{	              
 | 
						|
					TToken_string& tr = rata(j);
 | 
						|
					real rvl = dt.get();
 | 
						|
					tr.add(rvl.string(), is_perc_modified ? 4 : 1);				
 | 
						|
				}    
 | 
						|
			}
 | 
						|
			            
 | 
						|
			need_recalc = TRUE;            
 | 
						|
			return	P_OK;			
 | 
						|
		} // new_value != NULL
 | 
						|
			   	
 | 
						|
		   
 | 
						|
	}
 | 
						|
	else  // i != row modified
 | 
						|
	{           
 | 
						|
		if (i > 0 && !((perc_rata(i-1) == perc_rata(i))))
 | 
						|
		{
 | 
						|
			if (rdiff == 2) rdiff = 1;
 | 
						|
			_rdiff = FALSE;
 | 
						|
		}
 | 
						|
		rsum    += is_perc_modified ? perc_rata(i) : tpay_rata(i);  
 | 
						|
		
 | 
						|
		lastdate = data_rata(i);
 | 
						|
		oldtype  = tipo_rata(i);
 | 
						|
	 	oldscad  = scad_rata(i); 
 | 
						|
		if (_inited && i > 0) 
 | 
						|
		{
 | 
						|
			if (data_rata(i) <= data_rata(i-1)) 
 | 
						|
				return P_SCAD;
 | 
						|
		}
 | 
						|
		else if (lastdate < _inizio) 
 | 
						|
			return P_INIZIO;
 | 
						|
	}    
 | 
						|
  }
 | 
						|
  
 | 
						|
  return P_OK;
 | 
						|
}
 | 
						|
                             
 | 
						|
                             
 | 
						|
bool Pagamento::read(TTable* t, TTable* r)
 | 
						|
{                                                         
 | 
						|
  // puo' chiamarla chiunque
 | 
						|
  bool istnew = FALSE;
 | 
						|
  if (t == NULL) 
 | 
						|
  { 
 | 
						|
  	t = new TTable("%CPG"); 
 | 
						|
  	istnew = TRUE; 
 | 
						|
  }
 | 
						|
  t->zero(); t->put("CODTAB",_code);
 | 
						|
  t->read(); if (t->eof()) return FALSE;
 | 
						|
  
 | 
						|
  // set everything 
 | 
						|
  _rdiff  = t->get_bool("B1");
 | 
						|
  _mcomm  = t->get_bool("B0");
 | 
						|
  _tpr    = *((const char*)(t->get("S3")));
 | 
						|
  _inscad = *((const char*)(t->get("S1")));
 | 
						|
  _code   = t->get("CODTAB");
 | 
						|
  _name   = t->get("S0");
 | 
						|
  
 | 
						|
  // TBI aggiusta _inizio secondo INSCAD; vedi mese commerciale etc.                         
 | 
						|
  if (_inscad == 'M')
 | 
						|
  {
 | 
						|
    if (_mcomm) _inizio.set_month(_inizio.month() == 2 ? 28 : 30);
 | 
						|
    else        _inizio.set_end_month();
 | 
						|
  }
 | 
						|
  else if (_inscad == 'F' && _mcomm && _inizio.month() == 31) 
 | 
						|
    _inizio.set_month(30);
 | 
						|
  
 | 
						|
  // leggi rate e scadenze          
 | 
						|
  bool isrnew = FALSE;
 | 
						|
  if (r == NULL) 
 | 
						|
  { 
 | 
						|
  	r = new TTable("%RPG"); 
 | 
						|
  	isrnew = TRUE; 
 | 
						|
  }
 | 
						|
  TString s(16); 
 | 
						|
  
 | 
						|
  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(16);
 | 
						|
    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"));
 | 
						|
    _slicer.add(real(r->get("R0")));
 | 
						|
    _rate.add(tt);
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (istnew) delete t;
 | 
						|
  if (isrnew) delete r;
 | 
						|
  
 | 
						|
  return TRUE;          
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool Pagamento::write(TTable& r)
 | 
						|
{   
 | 
						|
  // Scrive soltanto le righe di pagamento; si assume sia stata chiamata da una
 | 
						|
  // relapp, che ha scritto il file principale                                 
 | 
						|
  
 | 
						|
  TString s(16); bool ok = TRUE;
 | 
						|
  for (int i = 0; i < n_rate(); i++)
 | 
						|
  {
 | 
						|
    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));
 | 
						|
    ok &= (r.write() == NOERR);
 | 
						|
  }                                      
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
                               
 | 
						|
bool Pagamento::rewrite(TTable& r)
 | 
						|
{
 | 
						|
  TString s(16); bool ok = TRUE;
 | 
						|
  for (int i = 0; i < n_rate(); i++)
 | 
						|
  {
 | 
						|
    r.zero(); s.format("%s%3d",(const char*)_code, i);
 | 
						|
    r.put("CODTAB", (const char*)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));
 | 
						|
    ok &= ((was ? r.rewrite : r.write()) == NOERR);
 | 
						|
  }                                      
 | 
						|
  // erase possible rates > current n. rates
 | 
						|
  for (;;i++)
 | 
						|
  { 
 | 
						|
     r.zero(); s.format("%s%3d",(const char*)_code, i);
 | 
						|
     r.put("CODTAB", (const char*)s);
 | 
						|
     if (r.read() == NOERR) r.remove();
 | 
						|
     else break;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
void Pagamento::remove(TTable& r)
 | 
						|
{          
 | 
						|
  TString s(16);
 | 
						|
  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) r.remove();
 | 
						|
     else break;
 | 
						|
  }
 | 
						|
}                               
 | 
						|
 | 
						|
void Pagamento::set_rate_auto()
 | 
						|
{
 | 
						|
  // vedi rate esistenti e tipo prima rata 
 | 
						|
  // deve fare riferimento ad un tipo pagamento esistente
 | 
						|
  // e sensato
 | 
						|
  int first = 0;                           
 | 
						|
  
 | 
						|
  real toslice = _firstr;
 | 
						|
  
 | 
						|
  if (n_rate() == 0 || !_inited || (_tpr > 0 && n_rate() == 1))  return;
 | 
						|
  if (_tpr > 1)           // ripartisci _firstr su tutte le rate
 | 
						|
  {
 | 
						|
    first = 1; 
 | 
						|
    toslice = _secndr;
 | 
						|
  }
 | 
						|
 | 
						|
  _slicer.init(toslice);
 | 
						|
  
 | 
						|
  if (_tpr > 0)
 | 
						|
    // prima rata obbligatoria
 | 
						|
    set_imprata(0, _firstr); 
 | 
						|
  
 | 
						|
  for (int i = first; i < n_rate(); i++)        
 | 
						|
    // setta le fette e le date di scadenza
 | 
						|
    set_imprata(i, _slicer.get());
 | 
						|
}                                     
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void Pagamento::set_total(real& imponibile, real& imposta, real& spese)
 | 
						|
{
 | 
						|
  _imponibile = imponibile;
 | 
						|
  _imposta    = imposta;
 | 
						|
  _spese      = spese;
 | 
						|
  _inited     = TRUE;
 | 
						|
 | 
						|
  // istanzia _firstr e _secndr a seconda di _tpr  
 | 
						|
  switch(_tpr)
 | 
						|
  {          
 | 
						|
  case 0:                                         
 | 
						|
    _firstr = _imponibile + _imposta + _spese;
 | 
						|
    _secndr = 0.0;
 | 
						|
    break;              
 | 
						|
  case 1: 
 | 
						|
    _firstr = _imposta;
 | 
						|
    _secndr = _imponibile + _spese;
 | 
						|
    break;
 | 
						|
  case 2: 
 | 
						|
    _firstr = _spese;
 | 
						|
    _secndr = _imposta + _imponibile;
 | 
						|
    break;
 | 
						|
  case 3:
 | 
						|
    _firstr = _imposta + _spese; 
 | 
						|
    _secndr = _imponibile;
 | 
						|
    break;
 | 
						|
  case 4: 
 | 
						|
    _firstr = _spese + _imponibile;
 | 
						|
    _secndr = _imposta;
 | 
						|
    break;  
 | 
						|
  case 5:     
 | 
						|
    _firstr = _imponibile + _imposta;
 | 
						|
    _secndr = _spese;
 | 
						|
    break;  
 | 
						|
  case 6:            
 | 
						|
    _firstr = _imponibile;
 | 
						|
    _secndr = _imposta + _spese;
 | 
						|
    break;  
 | 
						|
  }
 | 
						|
 | 
						|
  for (int i = 0; i < _rate.items(); i++)
 | 
						|
  {
 | 
						|
    TToken_string& t = (TToken_string&)_rate[i]; 
 | 
						|
    real rr(t.get(1));
 | 
						|
    _slicer.add(rr);
 | 
						|
  }                   
 | 
						|
}                            
 | 
						|
 | 
						|
 | 
						|
void Pagamento::set_sheet(TSheet_field& sf, int sscad)
 | 
						|
{
 | 
						|
  sf.reset();
 | 
						|
  if (_inited && _rate.items() > 0)
 | 
						|
  {  
 | 
						|
  	// si istanzia uno sheet di primanota
 | 
						|
  	for (int i = 0; i < n_rate(); i++)
 | 
						|
  	{
 | 
						|
   	  TToken_string* ts = new TToken_string(36);
 | 
						|
   	  // istanzia, o stronzo
 | 
						|
      ts->add((const char*)data_rata(i));
 | 
						|
      ts->add(perc_rata(i).string());
 | 
						|
      ts->add(tpay_rata(i).string());
 | 
						|
      ts->add(tipo_rata(i));
 | 
						|
	  ts->add(desc_tipo(tipo_rata(i)));
 | 
						|
      sf.row(-1) = (*ts);
 | 
						|
     }
 | 
						|
   }
 | 
						|
   else if (_rate.items() > 0)  // not inited: set edit sheet
 | 
						|
   {
 | 
						|
   	 for (int i = 0, scr = 0; i < n_rate(); i++)
 | 
						|
   	 {
 | 
						|
   	 	TToken_string* s = new TToken_string(32);
 | 
						|
   	 	scr += scad_rata(i);   	 	
 | 
						|
   	 	s->add(format("%d",scr));
 | 
						|
   	 	s->add(perc_rata(i).string());
 | 
						|
   	 	s->add(format("%d",tipo_rata(i)));
 | 
						|
   	 	s->add(desc_tipo(tipo_rata(i)));
 | 
						|
   	 	s->add(ulc_rata(i));   	 	
 | 
						|
   	 	sf.row(-1) = *s; 	 	
 | 
						|
   	 }
 | 
						|
   }
 | 
						|
   else  // new: set with 1 or 2 rates according to tpr
 | 
						|
   {        
 | 
						|
   	 if (_tpr > 0) 
 | 
						|
   	 	set_rata(0, ZERO, sscad == -1 ? 0 : sscad, 1);
 | 
						|
   	 set_rata(_tpr == 0 ? 0 : 1, real(100.0), sscad == -1 ? (_tpr == 0 ? 0 :30) 
 | 
						|
   	 										  : sscad, 1); 
 | 
						|
   	 _dirty = TRUE;
 | 
						|
   	 
 | 
						|
   	 for (int i = 0, scr = 0; i < n_rate(); i++)
 | 
						|
   	 {
 | 
						|
   	 	TToken_string* s = new TToken_string(32);
 | 
						|
   	 	scr += scad_rata(i);
 | 
						|
   	 	s->add(format("%d",scr));
 | 
						|
   	 	s->add(perc_rata(i).string());
 | 
						|
   	 	s->add(format("%d",tipo_rata(i)));
 | 
						|
   	 	s->add(desc_tipo(tipo_rata(i)));
 | 
						|
   	 	s->add(ulc_rata(i));  
 | 
						|
   	 	sf.row(-1) = *s; 	 	
 | 
						|
   	 }   	 
 | 
						|
   }            
 | 
						|
   if (_tpr > 0)
 | 
						|
   {     
 | 
						|
   	  // disabilita campi da non toccare sulla prima rata
 | 
						|
   	  if (_inited)
 | 
						|
   	  {        
 | 
						|
   	  	sf.disable_cell(0,1); // percentuale
 | 
						|
   	  	sf.disable_cell(0,2); // importo
 | 
						|
   	  }
 | 
						|
   	  else
 | 
						|
   	  {
 | 
						|
   	  	sf.disable_cell(0,1); // percentuale
 | 
						|
   	  }
 | 
						|
   }
 | 
						|
   sf.force_update();   
 | 
						|
}
 | 
						|
 | 
						|
Pagamento::Pagamento(const char* codtab, const char* data) : 
 | 
						|
_slicer(0.0,0), _new(FALSE), _imponibile(0.0), _imposta(0.0), 
 | 
						|
_spese(0.0), _code(codtab), _dirty(FALSE), _inited(FALSE)
 | 
						|
{               
 | 
						|
  if (data != NULL)     
 | 
						|
  	_inizio = data;
 | 
						|
  if (_code.empty() || !read()) 
 | 
						|
    _new = TRUE; 
 | 
						|
  if (_new && data != NULL) error_box("Modalita' pagamento inesistente");
 | 
						|
}
 |