From 4f5f83485f823199e502d377eca9110d0145380f Mon Sep 17 00:00:00 2001
From: villa <villa@c028cbd2-c16b-5b4b-a496-9718f37d4682>
Date: Mon, 11 Sep 1995 10:53:00 +0000
Subject: [PATCH] Pagament and corrections and recalcuation of scadenzs
 reorganized but not over yet

git-svn-id: svn://10.65.10.50/trunk@1804 c028cbd2-c16b-5b4b-a496-9718f37d4682
---
 cg/cg2100.cpp   |   1 +
 cg/cg2102.h     |   1 +
 cg/cg2104.cpp   |  31 ++++-
 cg/cg21sld.h    |   1 +
 cg/cg21sld.uml  |  28 +++--
 cg/pagament.cpp | 328 +++++++++++++++++++++++++++++++++++++++---------
 cg/pagament.h   |   5 +-
 7 files changed, 319 insertions(+), 76 deletions(-)

diff --git a/cg/cg2100.cpp b/cg/cg2100.cpp
index 41a888646..d40982544 100755
--- a/cg/cg2100.cpp
+++ b/cg/cg2100.cpp
@@ -96,6 +96,7 @@ TMask* TPrimanota_application::load_mask(int n)
       TSheet_field& ps = (TSheet_field&)m->field(FS_RATESHEET);
       ps.set_notify(pag_notify);                        
       m->set_handler(FS_RESET, reset_handler);
+      m->set_handler(FS_NRATE, nrate_handler);
     }   
     _iva_showed = FALSE;
   case 1:
diff --git a/cg/cg2102.h b/cg/cg2102.h
index a67371b0c..9c2e898c3 100755
--- a/cg/cg2102.h
+++ b/cg/cg2102.h
@@ -113,6 +113,7 @@ class TPrimanota_application : public TRelation_application
   static bool cg_conto_handler(TMask_field& f, KEY key);
   static bool codpag_handler(TMask_field& f, KEY key);
   static bool reset_handler(TMask_field& f, KEY key);
+  static bool nrate_handler(TMask_field& f, KEY key);
 
   static bool iva_notify(TSheet_field& s, int r, KEY key);
   static bool iva_handler(TMask_field& f, KEY key);
diff --git a/cg/cg2104.cpp b/cg/cg2104.cpp
index bfed6e199..a3d92ef6a 100755
--- a/cg/cg2104.cpp
+++ b/cg/cg2104.cpp
@@ -4,6 +4,7 @@
 // --------------------------------------------------------------------------
 
 #include <sheet.h>
+#include <utility.h>
 #include "pagament.h"
 #include "saldacon.h"
 
@@ -98,6 +99,7 @@ bool TPrimanota_application::pag_notify(TSheet_field&, int r, KEY k)
                                rdiff, mcomm, need_recalc);
       // see if rdiff changed                          
       msk->set(FS_RDIFFER, pag.rate_differenziate() ? "1" : "2");
+      msk->set(FS_NRATE, format("%d", pag.n_rate()));
     }
     if (!recalc)
     {                              
@@ -147,7 +149,7 @@ bool TPrimanota_application::codpag_handler(TMask_field& f, KEY key)
   
   if (key == K_TAB && f.focusdirty() && m.is_running() && app().is_saldaconto())
   {
-    const TString16 dt(m.get(F_DATAREG));
+    const TString16 dt(m.get(F_DATADOC));
     app().set_pagamento(f.get(), dt);     
     app().set_scadenze(m);
   }
@@ -166,6 +168,24 @@ bool TPrimanota_application::reset_handler(TMask_field& f, KEY key)
   return TRUE;
 }
 
+bool TPrimanota_application::nrate_handler(TMask_field& f, KEY key)
+{                                 
+  TMask& m = f.mask();
+  TSheet_field& ps = (TSheet_field&)m.field(FS_RATESHEET);
+  
+  if (key == K_TAB && m.is_running() && app().is_saldaconto())
+  {
+    if (app().pagamento() != NULL) 
+    {
+      app().pagamento()->set_numero_rate(atoi(f.get()), /*TBI*/-1);
+     if (app().pagamento()->dirty())
+        app().pagamento()->set_sheet(ps);    
+    }
+    else f.set("");
+  }
+  return TRUE;
+}
+
 
 bool TPrimanota_application::numrif_handler(TMask_field& f, KEY key)
 {
@@ -223,7 +243,7 @@ bool TPrimanota_application::numrif_handler(TMask_field& f, KEY key)
              else  
              {
                f.mask().enable_page(2);
-               app().set_pagamento(codpag, f.mask().get(F_DATAREG));     
+               app().set_pagamento(codpag, f.mask().get(F_DATADOC));     
                app().set_scadenze(f.mask());
              }
            }
@@ -323,7 +343,8 @@ void TPrimanota_application::set_scadenze(TMask& m)
   m.set(FS_TIPOPR,  pag.desc_tpr());
   m.set(FS_MCOMM,   pag.mese_commerciale() ? "X" : "");
   m.set(FS_RECALC,  "X", TRUE);
-
+  
+  
   pag.set_total(imponibile, imposta, spese);                              
   pag.set_rate_auto();          
   bool new_part = TRUE; 
@@ -332,7 +353,8 @@ void TPrimanota_application::set_scadenze(TMask& m)
 
   // prepara lo sheet
   pag.set_sheet(ps);
-  _pag_rows = ps.rows_array();
+  _pag_rows = ps.rows_array();            
+  m.set(FS_NRATE, pag.n_rate());
 
   // se la prima rata e' fissa non si tocca
   if (pag.tipo_prima_rata() > 3)
@@ -529,6 +551,7 @@ void TPrimanota_application::write_scadenze(const TMask& m)
   int  numrig     = 1;     // TBC
   
   int row = part.prima_fattura(nreg);
+  // TBC controllo aggiunta su partita se ridefinita a culo
   TRiga_partite& partita = row == -1 ? part.nuova_riga() : part.riga(row);
   
   TPagamento& pag = *pagamento();                      
diff --git a/cg/cg21sld.h b/cg/cg21sld.h
index 84bbc1389..b885c52f2 100755
--- a/cg/cg21sld.h
+++ b/cg/cg21sld.h
@@ -9,3 +9,4 @@
 #define FS_TIPOPR     509    
 #define FS_MCOMM      510  
 #define FS_RESET      511
+#define FS_NRATE      512
diff --git a/cg/cg21sld.uml b/cg/cg21sld.uml
index 957513fec..f98b0e672 100755
--- a/cg/cg21sld.uml
+++ b/cg/cg21sld.uml
@@ -30,34 +30,40 @@ END
 RADIOBUTTON FS_RDIFFER 31
 BEGIN
 	PROMPT 1 4 "Opzioni ricalcolo rate" 
-	ITEM "1|Differenziate"
-	ITEM "2|Uguali"
-	ITEM "3|Uguali dall'ultima modificata" 
-	ITEM "4|Uguali finche' possibile"
+	ITEM "1|Differenziate"                 MESSAGE DISABLE,FS_NRATE
+	ITEM "2|Uguali (obbligate dalla 2a)"   MESSAGE ENABLE,FS_NRATE
+	ITEM "3|Uguali dall'ultima modificata" MESSAGE DISABLE,FS_NRATE
+	ITEM "4|Uguali finche' possibile"      MESSAGE DISABLE,FS_NRATE
 END
-
+           
+NUMBER FS_NRATE 3 0
+BEGIN
+	PROMPT 36 8 "Numero di rate  "
+END          
+           
 BOOLEAN FS_RECALC
 BEGIN
-	PROMPT 53 5 "Ricalcolo automatico"       
-	MESSAGE TRUE  ENABLE,FS_RDIFFER|ENABLE,FS_MCOMM
-	MESSAGE FALSE DISABLE,FS_RDIFFER|DISABLE,FS_MCOMM
+	PROMPT 58 7 "Ricalcolo automatico"       
+	MESSAGE TRUE  ENABLE,FS_RDIFFER|ENABLE,FS_MCOMM|K_SPACE,FS_RDIFFER
+	MESSAGE FALSE DISABLE,FS_RDIFFER|DISABLE,FS_MCOMM|DISABLE,FS_NRATE 
+	HELP "Attiva/disattiva il ricalcolo automatico delle scadenze"
 END          
 
 BOOLEAN FS_MCOMM
 BEGIN
-	PROMPT 53 6 "Mese commerciale"       
+	PROMPT 36 7 "Mese commerciale"       
 END          
 
 
 STRING FS_NAMEPAG 27
 BEGIN 
-	PROMPT 36 7 "Pagamento       "
+	PROMPT 36 5 "Pagamento       "
 	FLAGS "D"
 END
 
 STRING FS_TIPOPR 27
 BEGIN 
-	PROMPT 36 8 "Tipo prima rata "
+	PROMPT 36 6 "Tipo prima rata "
 	FLAGS "D"
 END
 
diff --git a/cg/pagament.cpp b/cg/pagament.cpp
index a78d03c04..16fa7f629 100755
--- a/cg/pagament.cpp
+++ b/cg/pagament.cpp
@@ -1,4 +1,5 @@
 #include <utility.h>
+#include <relapp.h>
 
 #include "pagament.h"
 
@@ -126,7 +127,7 @@ void TPagamento::set_tipo_prima_rata(int v, int sscad)
   _dirty = TRUE;
 }
 
-void TPagamento::set_numero_rate(int n, int sscad)
+void TPagamento::set_numero_rate(int n, int sscad, int rdiff)
 {                         
   _dirty = FALSE;
   if (n == 0 || n == n_rate()) return; 
@@ -136,8 +137,66 @@ void TPagamento::set_numero_rate(int n, int sscad)
   int nr = n_rate();
   int first = _tpr < 4 ? 0 : 1;
   real sum = 0.0;
+  int i = 0;
+
+  if (_inited || (!_inited && rdiff == 1))   // se e' inited rdiff e' 2 per forza
+  { 
+    real tot = _inited ? (_tpr < 4 ? _firstr  : _secndr) : real(100.0);
+    if (n == 1)
+    {
+      if (_inited) set_imprata(first, tot); 
+      set_percrata(first, real(100.0));
+      if (_inited && _tpr > 0 && _tpr < 4)                 
+        set_imprata(first, tpay_rata(first) + _secndr);
+      i = first + 1; // per rimozione successiva
+    }
+    else
+    {   
+
+      if (nr == first + 1)
+      {               
+        // suddividi equamente e riaggiusta la percentuale di conseguenza  
+        real div  = tot / real(n);
+        real perc = real(100.0)*(div/tot);  
+        for (i = first; i < n; i++)
+        {
+          if (i > 0) 
+            add_rata(perc, (sscad == -1 ? scad_rata(0) : sscad), tipo_rata(0));
+          if (_inited) set_imprata (i, div); 
+          set_percrata(i, perc);
+        }
+        if (_inited && _tpr > 0 && _tpr < 4)                 
+          set_imprata(0, tpay_rata(0) + _secndr);
+      }
+      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 ? tpay_rata(first) : perc_rata(first);
+        if (_inited && _tpr > 0 && _tpr < 4) rfirst -= _secndr;  
+        
+        real rest = tot - rfirst;
+        const real div = rest / real(n - 1);
+        real perc = real(100.0)*(div/tot);
+
+        for (i = first+1; i < n; i++)
+        {
+          if (i >= nr) 
+            add_rata(perc, (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad),
+                     tipo_rata(nr-1));
+          if (_inited) set_imprata (i, div); 
+          set_percrata(i, perc);
+        }
+      }
+    } 
+  }
   
-  for (int i = first; sum < real(100.0); i++)
+  else
+  {
+  
+    for (i = first; sum < real(100.0); i++)
     {
       if ((real(100.0) - sum) < p) 
         p = real(100.0) - sum;  
@@ -158,7 +217,8 @@ void TPagamento::set_numero_rate(int n, int sscad)
 	       i == 0 ? (i < nr ? scad_rata(0) : 0):
 	       (sscad == -1 ? (i < nr ? scad_rata(i) : scad_rata(nr-1)) : sscad),
 	       (i < nr ? tipo_rata(i) : tipo_rata(nr-1)));
-    }          
+     } 
+  }         
   // erase remaining  
   for (; i < nr; i++) 
   	_rate.add(NULL,i);
@@ -186,8 +246,8 @@ void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata)
       // la palla del febbraio & c.                                    
       if (rata > 1)
         {
-	  TDate oldd(data_rata(rata-2));
-	  if (oldd.day() > dy) dy = oldd.day();
+	      TDate oldd(data_rata(rata-2));
+	      if (oldd.day() > dy) dy = oldd.day();
         }	
       
       d.set_day(1);  // il giorno 1 ce l'hanno tutti
@@ -196,14 +256,14 @@ void TPagamento::next_scad(TDate& d, int scad, bool mcomm, int rata)
       
       d.set_end_month();  
       if (!last && dy < d.day()) 
-	d.set_day(dy);
+  	  d.set_day(dy);
     }
     else 
     {
-	d += scad;
+	  d += scad;
     }    
     
-    // riaggiusta la minchia se ci sono scadenze fissate
+    // riaggiusta se ci sono scadenze fissate
     if (_fixd[0] != 0 || _fixd[1] != 0 || _fixd[2] != 0)
     {
       for (int i = 0; i < 3; i++)
@@ -323,6 +383,14 @@ void TPagamento::set_imprata(int i, real r)
   tt.add((const char*)d, 3);
   tt.add(r.string(), 4);
 }
+
+void TPagamento::set_percrata(int i, real r)
+{
+  TToken_string& tt = (TToken_string&)_rate[i];  
+  TDate d = _inizio; 
+  tt.add(r.string(), 1);
+}
+
                                         
 TToken_string& TPagamento::set_rata(int index, const real& howmuch, 
 	const TDate& date, int type,const char* ulc, bool pagato)
@@ -374,13 +442,13 @@ word TPagamento::validate() const
   
   int first    = _tpr < 4 ? 0 : 1;        
   real toshare(_tpr < 4 ? _firstr : _secndr);    
-  TDistrib ds(toshare,0);          
+//  TDistrib ds(toshare,0);          
   
   // check percentages & prepare slicer
   for (int i = first; i < n_rate(); i++)
     {                
       real p(perc_rata(i));
-      ds.add(p);
+//      ds.add(p);
       r += p; 
     }
   
@@ -390,15 +458,17 @@ word TPagamento::validate() const
   
   if (_inited)
     {
-      ds.init(toshare);
+//   RIMOSSO in quanto con rate uguali non si usa la percentuale,
+//   per evitare merdaglia
+//      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; }		
-	}     
+//      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));
@@ -426,6 +496,10 @@ void TPagamento::strerr(word err, TString& s)
     s << "\n   Le scadenze non sono consecutive";
   if (err & P_INIZIO)
     s << "\n   La prima rata e' antecedente alla data movimento";
+  if (err & P_NEG)
+    s << "\n   L'importo dato e' inferiore al minimo possibile";
+  if (err & P_TROP)
+    s << "\n   L'importo dato e' superiore al massimo possibile";
 }
 
 const char* TPagamento::desc_tpr() const
@@ -457,7 +531,7 @@ const char* TPagamento::desc_tipo(int i) const
 	  case 5:  o = "Paghero'"; break;
 	  case 6:  o = "Lettera di credito"; break;
 	  case 7:  o = "Tratta accettata"; break;                   
-      case 8:  o = "Rapporti interbancari diretti"; break;
+      case 8:  o = "Rapporti interban. diretti"; break;
       case 9:  o = "Bonifici"; break;
 	  case 10: o = "Altro pagamento"; break;
 	} 
@@ -488,7 +562,6 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
   int first      = _tpr < 4 ? 0 : 1;
   TArray srate(_rate);   // rate come erano   
   
-  
   if (srate.items() > 1)
     {
   	// calcola defaults per tipo pagamento e scadenza
@@ -502,7 +575,7 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
   if (new_value != NULL)
     {     
       newv = new_value;                       
-      rmax = is_perc_modified? (real) 100.0 : (_tpr < 4 ? _firstr : _secndr);
+      rmax = is_perc_modified? real(100.0) : (_tpr < 4 ? _firstr : _secndr);
       if (newv > rmax) return P_RSUM;
     }                                                   
   
@@ -514,11 +587,20 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 	{  
 	  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
+          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);	
+	          need_recalc = TRUE;		                     
+	          // no error is possible  
+	        }        
+          }
 	    }
 	  
 	  if (scad != NULL)
@@ -591,7 +673,15 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 // *** 10/8/95: se uguali e non e' multiplo intero lo teniamo cosi' e poi
 // *** aggiungiamo alla prima rata utile
 //		  if (rdiff == 2 && !((rmax % newv.integer()) == ZERO)) 
-//		    rdiff = 1;                   
+//		    rdiff = 1;                        
+// *** 5/9/85: UGUALI (2) significa la seguente menata: se c'e' una sola rata
+// *** uguale al totale importo, come prima; diversamente, la prima rata
+// *** va mantenuta uguale comunque sia, e occorre ridefinire le restanti in
+// *** modo che siano uguali. In questo caso deve far fede il NUMERO di RATE
+// *** indicato, che in prima nota non c'e' e va quindi inserito (porcoddio).
+
+          // si registrano rate UGUALI soltanto se specificato UGUALI
+          // il che non e' sorprendente, ma coi tempi che corrono... 
 		  _rdiff = (rdiff == 1 || rdiff == 3 || rdiff == 4);
 		  
 		  // procedi			
@@ -600,14 +690,14 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 		      // 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);
-			}
+			  {
+			    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); 
@@ -621,7 +711,7 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 			      next_scad(dd,oldscad,mcomm,row);
 			      trt.add(dd.string(),3); 
 			    }
-			} 
+			  } 
 		    }
 		  else  // rate non differenziate (dall'inizio o da row)
 		    {
@@ -639,12 +729,96 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 		      
 		      // cancelliamo tutto, va'
 		      for (int j = frs; j < srate.items(); j++)
-			_rate.add(NULL,j);
-		      
-		      if (rdiff != 4)	
+                _rate.add(NULL,j);
+		     
+		     if (rdiff == 2 && srate.items() > 1)
+		     {
+		       // HERE
+		       
+		       int n = srate.items(); // questo rimane per forza costante
+               real tot   = is_perc_modified ? real(100.0) : (_tpr < 4 ? _firstr  : _secndr);
+		       real delta = is_perc_modified ? ZERO : 
+		                    ((_tpr > 0 && _tpr) < 4 ?  _secndr : ZERO);
+		       real nimp(new_value);
+
+		       // se ho modificato la prima, divido il resto nelle successive
+		       // lasciando costante il numero rate
+		       if (row == first)
+		       {                                    
+		         if (!delta.is_zero()) nimp -= delta;
+		         // inferiore al minimo 
+		         if (nimp.sign() < 0) { _rate = srate; return P_NEG; }
+		         real remainder = tot - nimp;  
+		         real div = remainder / real(n - 1);                  
+                 div.round(is_perc_modified ? 3 : _round);
+                 nimp = tot - (div * real(n-1));
+
+                 for (int k = first; k < n; k++)
+                 {
+				   TToken_string& trt = (TToken_string&)srate[k];
+				   if (_inited) dd   = trt.get(3);
+				   type = atoi(trt.get(2));
+				   nscd = k == 0 ? 0 : atoi(trt.get(0));	
+			 	   if (type == 0) type = 1;
+				   if (k > 0 && nscd == 0) nscd = oldscad;
+				   if (_inited && dd == lastdate && k > 0) 
+				     next_scad(dd,nscd,mcomm,k);
+                   
+			       set_rata(k, is_perc_modified ? (k == first ? nimp : div) : ZERO,
+					  		nscd, type);
+                   if (!is_perc_modified)
+                     set_imprata (k, k == first ? (nimp + delta) : div);
+                 }
+		       }
+		       else
+		       { 
+		       // se ho modificato la seconda o oltre, faccio tutte uguali dalla
+		       // seconda in poi; la prima resta com'e' se possibile, mentre se 
+		       // c'e' un resto glielo sommo.
+		       // Dunque: prendo la prima, calcolo il resto, divido per quella nuova,
+		       // se resto lo sommo alla prima, e faccio quante rate servono 
+		         
+				 TToken_string& trt = (TToken_string&)srate[first];
+		         real rfirst(is_perc_modified ? trt.get(1) :  trt.get(4));   
+		         if (!delta.is_zero()) rfirst -= delta;
+		         real rest      = tot - rfirst;
+		         real div       = rest / nimp;
+		         if (div < real(1.0)) { _rate = srate; return P_TROP; } 
+
+		         int nr = (int)div.integer() + (_tpr > 4 ? 2 : 1);
+		         real reminder = rest - (nimp * real(nr -1));
+		         rfirst += reminder;
+                 for (int k = first; k < nr; k++)
+                 {                    
+                   nscd = oldscad;
+                   type = _def_tpr;        
+                   TString16 ulc(_def_ulc);
+                   
+                   if (srate.items() > k)
+                   {
+				     TToken_string& trt = (TToken_string&)srate[k];
+				     if (_inited) dd   = trt.get(3);
+				     type = atoi(trt.get(2));
+				     nscd = atoi(trt.get(0));	 
+				     ulc  = trt.get(5);
+				   }
+				   
+			 	   if (type == 0) type = 1;
+
+				   if (_inited && dd == lastdate && k > 0) 
+				     next_scad(dd,nscd,mcomm,k);
+                   
+			       set_rata(k, is_perc_modified ? (k == first ? rfirst : nimp) : ZERO,
+					  		nscd, type, ulc);
+                   if (!is_perc_modified)
+                     set_imprata (k, k == first ? (rfirst + delta) : nimp);
+                 }
+		       }
+		     } 
+		    
+		    else if (rdiff != 4)	
 			for (j = frs; sum < mx; j++)
 			  {	
-			    // TBI: qui mod se rdiff == 2
 			    // se c'e' la vecchia rata si tengono i parametri
 			    // altrimenti si calcolano 
 			    if (j < srate.items())
@@ -746,23 +920,45 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 		  for (int j = first; j < _rate.items(); j++)
 		    {   
 		      real rvl = is_perc_modified ? perc_rata(j) : tpay_rata(j); 
+		      // togli pezxo di troppo
+		      if (!is_perc_modified && j == first && _tpr > 0 && _tpr < 4)
+		        rvl -= _secndr;		        		      
 		      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);				
+		    {	
+		      real rfirst(0.0);              
+		      TToken_string& tr = rata(j);    
+		     
+		      real rvl = dt.get(); 
+		      
+		      if (j == first) 
+		      {  
+		        rfirst = rvl; 
+		        if (rdiff == 2)
+		        {
+		          real reminder  = toshare - rfirst;
+		          real rdiv = reminder / real(_rate.items() - (1+first));  
+		          rdiv.round( is_perc_modified ? _round : 3);
+		          rfirst   += reminder - (rdiv * real(_rate.items() - (1+first)));
+                  rvl       = rdiv;
+                }
+		      }
+		       
+		      if (is_perc_modified &&  j == first && _tpr > 0 && _tpr < 4)
+		        rfirst += _secndr;   
+		        
+		      tr.add((j == first ? rfirst.string() : rvl.string()), is_perc_modified ? 4 : 1);				
 		    }  
 		    
 		  // se e' il caso aggiungi l'importo fisso sulla prima rata
-		  if (_inited && _tpr > 0 && _tpr < 4)
-		  {
-		      TToken_string& tr = rata(0);   
-		      real tot = tpay_rata(0) + _firstr;
-		      tr.add(tot.string(), 4);
-		  } 
+//		  if (_inited && _tpr > 0 && _tpr < 4)
+//		  {
+//		      TToken_string& tr = rata(0);   
+//		      real tot = tpay_rata(0) + _secndr;
+//		      tr.add(tot.string(), 4);
+//		  } 
 		    
 		}
 	      
@@ -771,7 +967,8 @@ word TPagamento::recalc_rate(int row, bool is_perc_modified,
 	    } // new_value != NULL
 	}
 	else  // i != row modified
-	  {           
+	  {                                
+	    if (rdiff == 2) continue;
         if (i > 0 && !((perc_rata(i-1) == perc_rata(i))))
 	    {
 	      if (rdiff == 2) rdiff = 1;
@@ -873,7 +1070,8 @@ 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                                 
   
-  TString s(16); int err = NOERR;
+  TString s(16); int err = NOERR;    
+  
   for (int i = 0; err == NOERR && i < n_rate(); i++)
     {
       r.zero(); s.format("%s%3d",(const char*)_code, i);
@@ -890,6 +1088,7 @@ int TPagamento::write(TTable& r)
 int TPagamento::rewrite(TTable& r)
 {
   TString s(16); int err = NOERR;
+  
   for (int i = 0; err == NOERR && i < n_rate(); i++)
     {
       r.zero(); s.format("%s%3d",(const char*)_code, i);
@@ -937,6 +1136,7 @@ void TPagamento::set_rate_auto()
   real toslice = _firstr;
   
   if (n_rate() == 0 || !_inited || (_tpr > 3 && n_rate() == 1))  return;
+
   if (_tpr > 3)           // ripartisci _firstr su tutte le rate
     {
       first = 1; 
@@ -954,8 +1154,16 @@ void TPagamento::set_rate_auto()
   if (!_rdiff)
   {              
     int rut = _tpr > 3 ? n_rate() - 1 : n_rate();
-    ro = toslice/real(rut); ro.trunc(_round);
-    r1 = ro + (toslice - (ro*real(rut)));
+    
+    // usa la percentuale per la prima rata
+    r1 = (toslice * perc_rata(first))/real(100.0); 
+    r1.round(_round);
+    real reminder = toslice - r1;
+    if (!reminder.is_zero()) 
+    {
+      ro = reminder/real(rut-1); ro.trunc(_round);
+      r1 = (toslice - (ro*real(rut-1)));
+    }
   }
   
   for (int i = first; i < n_rate(); i++)        
@@ -965,7 +1173,7 @@ void TPagamento::set_rate_auto()
   // se e' nei primi tre casi, si somma l'importo da non dividere alla
   // prima rata                                        
   if (_tpr > 0 && _tpr < 4)
-    set_imprata(0, tpay_rata(0) + _firstr);  
+    set_imprata(0, tpay_rata(0) + _secndr);  
 }                                     
 
 
@@ -985,16 +1193,16 @@ void TPagamento::set_total(const real& imponibile, const real& imposta, const re
       _secndr = 0.0;
       break;              
     case 1: 
-      _firstr = _imposta;
-      _secndr = _imponibile + _spese;
+      _secndr = _imposta;
+      _firstr = _imponibile + _spese;
       break;
     case 2: 
-      _firstr = _spese;
-      _secndr = _imposta + _imponibile;
+      _secndr = _spese;
+      _firstr = _imposta + _imponibile;
       break;
     case 3:
-      _firstr = _imposta + _spese; 
-      _secndr = _imponibile;
+      _secndr = _imposta + _spese; 
+      _firstr = _imponibile;
       break;
     case 4: 
       _firstr = _spese + _imponibile;
diff --git a/cg/pagament.h b/cg/pagament.h
index 77cb6a1a3..bb8f7aa6e 100755
--- a/cg/pagament.h
+++ b/cg/pagament.h
@@ -19,6 +19,8 @@ const word P_RSUM   = 0x0001;     // percentages do not sum up to 100
 const word P_IMPNC  = 0x0002;     // inconsistenza percentuali / importi
 const word P_SCAD   = 0x0004;     // scadenze non consecutive 
 const word P_INIZIO = 0x0008;     // data 1a rata < data inizio pagamenti
+const word P_NEG    = 0x0010;     // importo specificato < minimo possibile
+const word P_TROP   = 0x0020;     // importo specificato > massimo possibile
 
 class TPagamento : public TObject
 {   
@@ -93,7 +95,8 @@ public:
   void   set_mese_commerciale(bool v, int& sscad);          
   void   set_rate_differenziate(int v);
   void   set_tipo_prima_rata(int v, int sscad = -1);
-  void   set_numero_rate(int n, int sscad = -1);
+  void   set_percrata(int n, real r);
+  void   set_numero_rate(int n, int sscad = -1, int rdiff = 1);
   
   void   set_inizio_scadenza(char v)    { _inscad = v; }           
   void   set_code(const char* c)        { _code = c;   }