commerciale. git-svn-id: svn://10.65.10.50/trunk@4108 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1894 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1894 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <applicat.h>
 | 
						|
#include <utility.h>
 | 
						|
#include "pagament.h"
 | 
						|
 | 
						|
#include "cg2100.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
 | 
						|
 | 
						|
inline void swap(int& x, int& y) {int tmp = x; x = y; y = tmp; }
 | 
						|
 | 
						|
int TPagamento::_rata_ifield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return t.get_int(f);
 | 
						|
}                            
 | 
						|
 | 
						|
long TPagamento::_rata_lfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return t.get_long(f);
 | 
						|
}                            
 | 
						|
 | 
						|
real TPagamento::_rata_rfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return real(t.get(f));
 | 
						|
}                            
 | 
						|
 | 
						|
TDate TPagamento::_rata_dfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  return TDate(t.get(f));
 | 
						|
}                                 
 | 
						|
 | 
						|
const char* TPagamento::_rata_sfield(int n, int f) const
 | 
						|
{                                     
 | 
						|
  static char kak[16];
 | 
						|
  TToken_string& t = (TToken_string&)_rate[n];
 | 
						|
  const char* k = t.get(f);
 | 
						|
  if (k != NULL) 
 | 
						|
    strncpy(kak, k, 16); 
 | 
						|
  else           
 | 
						|
    kak[0] = '\0';
 | 
						|
  return kak;
 | 
						|
}                                 
 | 
						|
 | 
						|
void TPagamento::set_inizio(const TDate& d, bool rispetta_date)
 | 
						|
{                          
 | 
						|
  _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 gironi 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 (_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 = real(100) / real(nact); 
 | 
						|
  p.round(2);
 | 
						|
  
 | 
						|
  if (_inited || (!_inited && rdiff == 1))   // se e' inited rdiff e' 2 per forza
 | 
						|
  { 
 | 
						|
    real tot = _inited ? importo_da_dividere(FALSE) : real(100.0);
 | 
						|
    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, real(100.0));
 | 
						|
      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 = (100.0 * div) / tot;
 | 
						|
        
 | 
						|
        real rem(tot); 
 | 
						|
        real oem(oot);
 | 
						|
        real p(perc);
 | 
						|
        
 | 
						|
        p.round(2);
 | 
						|
        
 | 
						|
        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 or;
 | 
						|
            if (inv) or = importo_rata(first,TRUE) + oem;
 | 
						|
            set_imprata(first, r, FALSE);
 | 
						|
            if (inv) set_imprata(first, or, TRUE);
 | 
						|
 | 
						|
            if (_inited && _tpr > 0 && _tpr < 4)
 | 
						|
            {
 | 
						|
              r -= importo_da_non_dividere(FALSE);
 | 
						|
              if (inv) or -= importo_da_non_dividere(TRUE);  
 | 
						|
            }
 | 
						|
            set_percrata(first, 100 * 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 = (100.0 * div)/tot;
 | 
						|
        real rem(rest);
 | 
						|
        real oem(oest);
 | 
						|
        real p(perc);
 | 
						|
        
 | 
						|
        p.round(2);
 | 
						|
        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 or;
 | 
						|
            if (inv) or = importo_rata(first,TRUE) + oem;
 | 
						|
            set_imprata(first, r, FALSE);
 | 
						|
            if (inv) set_imprata(first, or, TRUE);
 | 
						|
            if (_inited && _tpr > 0 && _tpr < 4)
 | 
						|
              r -= importo_da_non_dividere(FALSE);  
 | 
						|
            set_percrata(first, 100 * r / tot);
 | 
						|
          }
 | 
						|
          else
 | 
						|
          {
 | 
						|
            const real r(perc_rata(first) + rem);
 | 
						|
            
 | 
						|
            set_percrata(first, r);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } 
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {   
 | 
						|
    for (i = first; sum < real(100.0); i++)
 | 
						|
    {
 | 
						|
      if ((real(100.0) - sum) < p) 
 | 
						|
        p = real(100.0) - sum;  
 | 
						|
        
 | 
						|
      sum += p;           
 | 
						|
      
 | 
						|
      // if necessary add remainder on first one
 | 
						|
      if ((real(100.0) - sum) /* still */ < p)
 | 
						|
      {      
 | 
						|
        real prc = perc_rata(first);
 | 
						|
        prc += real(100.0) - sum; 
 | 
						|
        TToken_string& rt = rata(first);
 | 
						|
        rt.add(prc.string(),1), 
 | 
						|
        sum = 100;  
 | 
						|
      }
 | 
						|
      
 | 
						|
      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++; }
 | 
						|
        
 | 
						|
//    bool last = d.is_end_month() && inizio_scadenza() == 'M';
 | 
						|
    const bool last = inizio_scadenza() == 'M' || _datadoc.is_end_month();
 | 
						|
        
 | 
						|
    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);
 | 
						|
/*        
 | 
						|
    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 r)
 | 
						|
{                                              
 | 
						|
  TToken_string& tt = (TToken_string&)_rate[i];  
 | 
						|
  tt.add(r.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)
 | 
						|
{
 | 
						|
  real hm(importo_da_dividere(v));
 | 
						|
  
 | 
						|
  if (i == 0 && _tpr > 3) return ZERO;
 | 
						|
  
 | 
						|
  real tpay(importo_rata(i,v));
 | 
						|
  if (i == 0 && _tpr > 0 && _tpr < 4)
 | 
						|
    tpay -= importo_da_non_dividere(v);
 | 
						|
  real perc = tpay * 100.0 / hm;
 | 
						|
  perc.round(2);
 | 
						|
  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 *= real(100.0);
 | 
						|
  perc.round(2);
 | 
						|
  
 | 
						|
  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(0.0);
 | 
						|
  
 | 
						|
  int first    = _tpr < 4 ? 0 : 1;        
 | 
						|
  
 | 
						|
  // check percentages & prepare slicer
 | 
						|
  for (int i = first; i < n_rate(); i++)
 | 
						|
    r += perc_rata(i); 
 | 
						|
  r -= real(100.0);
 | 
						|
  real delta(0.005);
 | 
						|
  delta = delta * real(n_rate());
 | 
						|
  r = abs(r);
 | 
						|
  if (r > delta)
 | 
						|
    res |= P_RSUM;            
 | 
						|
  
 | 
						|
  
 | 
						|
  if (_inited)
 | 
						|
  {     
 | 
						|
    real tot;                         
 | 
						|
    
 | 
						|
    for (int 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[] = { tipo+'0', toupper(ulc), '\0' };
 | 
						|
    TTable clr("%CLR");
 | 
						|
    clr.put("CODTAB", key);
 | 
						|
    
 | 
						|
    const int err = clr.read();
 | 
						|
    if (err == NOERR)    
 | 
						|
      o = clr.get("S0"); 
 | 
						|
    else if (ok != NULL) 
 | 
						|
     *ok = FALSE;
 | 
						|
  }
 | 
						|
  if (*o == '\0')
 | 
						|
  {
 | 
						|
    switch (tipo)
 | 
						|
    {          
 | 
						|
      case 0:  o = "Altro pagamento"; break;
 | 
						|
      case 1:  o = "Rimessa diretta o 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 = "Rapporti interban. diretti"; break;
 | 
						|
      case 9:  o = "Bonifici"; break;
 | 
						|
      default: o = ""; 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);      
 | 
						|
  TString oldulc = ulc_rata(last_rata);      
 | 
						|
  int oldscad    = scad_rata(last_rata);
 | 
						|
  TDate lastdate = data_rata(0);  
 | 
						|
  int first      = _tpr < 4 ? 0 : 1;
 | 
						|
  TString_array srate(_rate);   // rate come erano   
 | 
						|
  int warnscad = 0;
 | 
						|
  
 | 
						|
  if (oldscad <= 0) oldscad = _int_rate;
 | 
						|
  if (oldtype <= 0) oldtype = _def_tpr;
 | 
						|
  
 | 
						|
  bool exhausted = FALSE;
 | 
						|
  
 | 
						|
  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 ? real(100.0) : 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 ? real(100.0) : 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 ? 2 : 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());
 | 
						|
     for (int 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 ? real(100.0) : 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
 | 
						|
  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 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 ? real(100.0) : 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
 | 
						|
  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 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;
 | 
						|
   TString16  last_ulc;
 | 
						|
   int        last_scad;
 | 
						|
 | 
						|
   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)
 | 
						|
{
 | 
						|
   real other = importo_da_dividere(v);
 | 
						|
 | 
						|
   const int first = _tpr > 3 ? 1 : 0;               
 | 
						|
 | 
						|
   for (int 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 * 100.0)/other; // percentuale
 | 
						|
     zpx.round(2);
 | 
						|
     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(100.0);
 | 
						|
   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));
 | 
						|
   }                                                   
 | 
						|
   
 | 
						|
   for (int j = _rate.items() - 1; j >= first ; j--)
 | 
						|
   {   
 | 
						|
     real rvl = perc_rata(j); 
 | 
						|
     // togli pezxo 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; 
 | 
						|
  }
 | 
						|
  t->zero(); t->put("CODTAB", _code);
 | 
						|
  if (t->read() != NOERR) return FALSE;   
 | 
						|
  
 | 
						|
  _rate.destroy();
 | 
						|
  
 | 
						|
  // 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");
 | 
						|
 | 
						|
#ifdef USE_DEFAULT_INT_RATE
 | 
						|
//  if (_int_rate == 0) _int_rate = 30;
 | 
						|
#endif                               
 | 
						|
 | 
						|
  // 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;
 | 
						|
  
 | 
						|
  for (int 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()
 | 
						|
{               
 | 
						|
  // 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;                           
 | 
						|
 | 
						|
  main_app().begin_wait();
 | 
						|
  set_inizio(_datadoc);
 | 
						|
 | 
						|
  for (int v = 0; v < (in_valuta() ? 2 : 1); v++)
 | 
						|
  {  
 | 
						|
    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 = real(100.0)/real(rut); refrata.round(2);
 | 
						|
        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))/real(100.0); 
 | 
						|
    
 | 
						|
          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)/real(100.0));
 | 
						|
        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);  
 | 
						|
  }
 | 
						|
 | 
						|
  // risistema rate per scadenze fisse
 | 
						|
  adjust_fixed_scad();
 | 
						|
  main_app().end_wait();
 | 
						|
}                                     
 | 
						|
 | 
						|
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;        
 | 
						|
  _cambio = 1.0;
 | 
						|
 | 
						|
  _firstr = _secndr = ZERO;            // Azzera importi in valuta
 | 
						|
  init_total(ib, im, sp, FALSE);       // 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 bool era_valuta = _in_valuta;
 | 
						|
 | 
						|
  _in_valuta = TRUE;        
 | 
						|
  _cambio    = c;
 | 
						|
  if (_cambio.sign() <= 0)  
 | 
						|
    _cambio = real(1.0);
 | 
						|
    
 | 
						|
  // setta regolarmente totali in lire
 | 
						|
  init_total(ibl, iml, spl, FALSE);           
 | 
						|
  // ripeti tutto con la valuta
 | 
						|
  init_total(ib, im, sp, TRUE);           
 | 
						|
  
 | 
						|
  if (!era_valuta && _in_valuta)
 | 
						|
    adjust_perc_imp(TRUE, _rdiff, TRUE);
 | 
						|
}  
 | 
						|
                          
 | 
						|
void TPagamento::init_total(const real& ib, const real& im, const real& sp, bool valuta)
 | 
						|
{  
 | 
						|
  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)
 | 
						|
{                             
 | 
						|
  main_app().begin_wait();
 | 
						|
  
 | 
						|
  if (_rate.items() == 0)
 | 
						|
  {   
 | 
						|
    if (_tpr > 3) 
 | 
						|
      add_rata(ZERO, sscad <= 0 ? 0 : sscad, _def_tpr, _def_ulc);
 | 
						|
    add_rata(real(100.0), sscad <= 0 ? (_tpr < 4 ? 0 : 30) : sscad, _def_tpr, _def_ulc);  
 | 
						|
    _dirty = TRUE;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (_inited)
 | 
						|
  {
 | 
						|
    // si istanzia uno sheet di primanota
 | 
						|
    for (int 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;
 | 
						|
    for (int 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
 | 
						|
  }
 | 
						|
  
 | 
						|
  main_app().end_wait();
 | 
						|
}
 | 
						|
   
 | 
						|
void TPagamento::adjust_fixed_scad()
 | 
						|
{   
 | 
						|
  if (!_inited) return;
 | 
						|
  
 | 
						|
  for (int i = 0; i < n_rate(); i++)
 | 
						|
  { 
 | 
						|
    TDate d = data_rata(i);
 | 
						|
    
 | 
						|
    // riaggiusta se ci sono scadenze fissate
 | 
						|
    if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0)
 | 
						|
    {
 | 
						|
      for (int 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);
 | 
						|
  }
 | 
						|
}
 | 
						|
   
 | 
						|
TPagamento::TPagamento(const char* codtab, const char* data) :
 | 
						|
  _new(FALSE), _mcomm(FALSE), _imponlit(0.0), _imposlit(0.0), 
 | 
						|
  _speselit(0.0), _cambio(1.0), _in_valuta(FALSE),
 | 
						|
  _code(codtab), _dirty(FALSE), _inited(FALSE),
 | 
						|
  _def_tpr(1), _def_ulc(""), _roundval(3), _int_rate(30), _tpr(0), _rdiff(FALSE),
 | 
						|
 _was_tpr4(FALSE), _roundlit(0), _imponval(0.0), _imposval(0.0), _speseval(0.0)
 | 
						|
{               
 | 
						|
  _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;    
 | 
						|
}  
 |