858 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			858 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include "saldacon.h"
 | |
| 
 | |
| #include <mov.h>
 | |
| #include <partite.h>
 | |
| #include <scadenze.h>
 | |
| #include <pagsca.h>
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TTree_rectype
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TTree_rectype::TTree_rectype(const TRectype& testa, const TRectype& riga, const char* num)
 | |
| : TRectype(testa), _recarr(riga, num)
 | |
| {
 | |
| }
 | |
| 
 | |
| TTree_rectype::TTree_rectype(int testa, int riga, const char* num)
 | |
| : TRectype(testa), _recarr(riga, num)
 | |
| {
 | |
| }
 | |
| 
 | |
| TTree_rectype::TTree_rectype(const TTree_rectype& t)
 | |
| : TRectype(t), _recarr(t._recarr)
 | |
| {
 | |
| }
 | |
| 
 | |
| 
 | |
| TObject* TTree_rectype::dup() const
 | |
| {
 | |
|   TTree_rectype* r = new TTree_rectype(*this);
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| void TTree_rectype::copy_key_to_row(TRectype& row) const
 | |
| {   
 | |
|   const int numkey = 0;      // Memento! Gli indici delle chiavi partono da zero!  
 | |
|   RecDes* recd = rec_des();  // Descrizione del record della testata
 | |
|   
 | |
|   row.zero();                              
 | |
|   const KeyDes& kd = recd->Ky[numkey];
 | |
|   for (int i = recd->Ky[numkey].NkFields-1; i >= 0; i--)
 | |
|   {                        
 | |
|     const int nf = kd.FieldSeq[i] % MaxFields;
 | |
|     const RecFieldDes& rf = recd->Fd[nf];  
 | |
|     const char* name = rf.Name;
 | |
|     const TString& val = get(name);
 | |
|     row.put(name, val);
 | |
|   }
 | |
| }  
 | |
| 
 | |
| int TTree_rectype::fill_array()
 | |
| {
 | |
|   TRectype* row = (TRectype*)_recarr.key().dup();
 | |
|   copy_key_to_row(*row);
 | |
|   const int err = _recarr.read(row);
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| 
 | |
| int TTree_rectype::read(TBaseisamfile& f, word op)
 | |
| {
 | |
|   int err = TRectype::read(f, op);
 | |
|   if (err == NOERR)
 | |
|     fill_array();
 | |
|   else 
 | |
|     _recarr.destroy_rows();
 | |
|   return err; 
 | |
| }
 | |
| 
 | |
| int TTree_rectype::next(TBaseisamfile& f)
 | |
| {
 | |
|   int err = TRectype::next(f);
 | |
|   if (err == NOERR)
 | |
|     fill_array();
 | |
|   else 
 | |
|     _recarr.destroy_rows();
 | |
|   return err; 
 | |
| }
 | |
| 
 | |
| int TTree_rectype::write(TBaseisamfile& f) const
 | |
| {
 | |
|   int err = TRectype::write(f);
 | |
|   if (err == NOERR)
 | |
|     err = _recarr.write();
 | |
|   return err; 
 | |
| }
 | |
| 
 | |
| int TTree_rectype::rewrite(TBaseisamfile& f) const
 | |
| {
 | |
|   int err = TRectype::rewrite(f);
 | |
|   if (err == NOERR)
 | |
|     err = _recarr.rewrite();
 | |
|   return err; 
 | |
| }
 | |
| 
 | |
| int TTree_rectype::remove(TBaseisamfile& f)
 | |
| {
 | |
|   int err = TRectype::remove(f);
 | |
|   if (err == NOERR)
 | |
|     err = _recarr.remove();
 | |
|   return err; 
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRiga_scadenze
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TRiga_scadenze::TRiga_scadenze(TRiga_partite* r)
 | |
| : TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP"), _riga(r)
 | |
| {
 | |
|   CHECK(_riga, "Riga nulla");
 | |
| }  
 | |
| 
 | |
| TRiga_scadenze::TRiga_scadenze(const TRiga_scadenze& s)
 | |
| : TTree_rectype(s), _riga(s._riga)
 | |
| 
 | |
| {
 | |
|   CHECK(_riga, "Riga nulla");
 | |
| } 
 | |
| 
 | |
| TPartita& TRiga_scadenze::partita() const
 | |
| {
 | |
|   return riga().partita();
 | |
| }
 | |
| 
 | |
| // Controlla se la fattura della rata e' in valuta
 | |
| bool TRiga_scadenze::in_valuta() const
 | |
| {
 | |
|   return riga().get(PART_CODVAL).not_empty();
 | |
| }
 | |
| 
 | |
| // Controlla se la rata e' stata completamente pagata
 | |
| int TRiga_scadenze::pagata() const
 | |
| {                                                  
 | |
|   for (int p = last(); p > 0; p = pred(p))
 | |
|   {
 | |
|     const TRectype& pag = row(p);
 | |
|     if (pag.get_char("ACCSAL") == 'S')
 | |
|       break;
 | |
|   }  
 | |
|   return p;
 | |
| }
 | |
| 
 | |
| // Calcola il totale dei pagamenti (eventualmente in valuta)
 | |
| TImporto TRiga_scadenze::importo_pagato(bool val) const
 | |
| {            
 | |
|   const char* imp_field = val && in_valuta() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
 | |
|   const TPartita& game = partita();
 | |
|   TImporto totale;
 | |
|   for (int p = last(); p > 0; p = pred(p))
 | |
|   {
 | |
|     const TRectype& pag = row(p);                         // Riga pagamento
 | |
|     const TRiga_partite& sum = game.riga(p);              // Riga partite
 | |
|     const TImporto imp(sum.sezione(), pag.get_real(imp_field));
 | |
|     totale += imp;
 | |
|   }  
 | |
|   
 | |
|   return totale;
 | |
| }
 | |
| 
 | |
| // Calcola l'importo da pagare (eventualmente in valuta)
 | |
| TImporto TRiga_scadenze::importo_da_pagare(bool val) const
 | |
| {            
 | |
|   const char* imp_field = val && in_valuta() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
 | |
|   const TRiga_partite& r = riga();              // Riga fattura
 | |
|   const TImporto totale(r.sezione(), get_real(imp_field));
 | |
|   return totale;
 | |
| }
 | |
| 
 | |
| // Calcola l'abbuono della rata e ritorna il suo tipo:
 | |
| // 'A' abbuono attivo; 'P' abbuono passivo
 | |
| // La sezione dell'abbuono calcolato e' quella della riga contabile in cui finira'
 | |
| char TRiga_scadenze::calcola_abbuono(TImporto& abbuono, bool val) const
 | |
| {
 | |
|   bool ap = ' ';
 | |
|   if (pagata())
 | |
|   {
 | |
|     abbuono = importo_da_pagare(TRUE);
 | |
|     abbuono += importo_pagato(TRUE);
 | |
| 
 | |
|     const int sign = abbuono.valore().sign();
 | |
|     if (sign != 0)
 | |
|     {
 | |
|       if (sign > 0)
 | |
|         ap = abbuono.sezione() == 'D' ? 'P' : 'A';
 | |
|       else  
 | |
|         ap = abbuono.sezione() == 'D' ? 'A' : 'P';
 | |
|     }    
 | |
|     
 | |
|     if (val && in_valuta())
 | |
|     {
 | |
|       abbuono.valore() *= riga().get_real(PART_CAMBIO);
 | |
|       abbuono.valore().round();
 | |
|     }
 | |
|   }
 | |
|   else 
 | |
|     abbuono.valore() = ZERO;
 | |
|   
 | |
|   return ap;
 | |
| }
 | |
| 
 | |
| // Calcola la differenza cambi con la sezione da mettere nella riga contabile corrispondente
 | |
| TImporto TRiga_scadenze::calcola_differenza_cambio(bool update)
 | |
| { 
 | |
|   TImporto diffcam;      
 | |
| 
 | |
|   if (in_valuta())
 | |
|   {
 | |
|     const int riga_saldo = pagata();
 | |
|     if (riga_saldo > 0)
 | |
|     {
 | |
|       TRectype& pag = row(riga_saldo);
 | |
|       const TRiga_partite& sum = partita().riga(riga_saldo);              
 | |
|       const char sez = sum.sezione();
 | |
|       
 | |
|       if (update)
 | |
|       {
 | |
|         diffcam = importo_da_pagare(FALSE);
 | |
|         diffcam += importo_pagato(FALSE);
 | |
|         
 | |
|         real a = pag.get_real(PAGSCA_ABBUONI);
 | |
|         if (in_valuta())
 | |
|         {
 | |
|           a *= riga().get_real(PART_CAMBIO);
 | |
|           a.round();
 | |
|         }                                  
 | |
|         
 | |
|         const TImporto abb_lit(sez, a);
 | |
|         diffcam += abb_lit;
 | |
|         diffcam.normalize(sez);
 | |
|         pag.put(PAGSCA_DIFFCAM, diffcam.valore());
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         diffcam.set(sez, pag.get_real(PAGSCA_DIFFCAM));
 | |
|       }  
 | |
|     } 
 | |
|     else
 | |
|       if (update)
 | |
|       {
 | |
|         for (int p = last(); p > 0; p = pred(p))    
 | |
|         {
 | |
|           TRectype& pag = row(p);
 | |
|           pag.zero(PAGSCA_DIFFCAM);
 | |
|         }  
 | |
|       }
 | |
|   }    
 | |
|   
 | |
|   return diffcam;
 | |
| }
 | |
| 
 | |
| real TRiga_scadenze::residuo(bool val) const
 | |
| {                         
 | |
|   TImporto residuo(importo_da_pagare(val));
 | |
|   residuo += importo_pagato(val);            // Somma con sezione opposta 
 | |
|   return residuo.valore();
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRiga_scadenze::modifica_pagamento(const TRectype& new_pag,
 | |
|                                         char& old_ap, TImporto& old_abb, TImporto& old_diffcam,  
 | |
|                                         char& new_ap, TImporto& new_abb, TImporto& new_diffcam)
 | |
| {       
 | |
|   const int nrigp = new_pag.get_int(PAGSCA_NRIGP);
 | |
|   const TRectype old_pag(row(nrigp));
 | |
|   TRiga_partite& sum = partita().riga(nrigp);
 | |
|   
 | |
|   TImporto old_abbuono;
 | |
|   old_ap = calcola_abbuono(old_abbuono, TRUE);           // Vecchio abbuono in valuta
 | |
|   old_abb = old_abbuono;                                 // Vecchio abbuono in lire
 | |
|   if (in_valuta())
 | |
|   {
 | |
|     old_abb.valore() *= riga().get_real(PART_CAMBIO);
 | |
|     old_abb.valore().round();
 | |
|   }
 | |
|   
 | |
|   old_diffcam = calcola_differenza_cambio(FALSE);
 | |
| 
 | |
|   const char* imp_field = in_valuta() ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
 | |
|   const real importo(new_pag.get(imp_field));
 | |
|   const bool empty = importo.is_zero();
 | |
|   if (empty)
 | |
|     rows_array().destroy_row(nrigp);
 | |
|   else    
 | |
|     row(nrigp) = new_pag;
 | |
|   
 | |
|   TImporto new_abbuono;
 | |
|   new_ap = calcola_abbuono(new_abbuono, TRUE); // Calcolo abbuono in valuta
 | |
| 
 | |
|   new_abb = new_abbuono;                       // Calcola nuovo abbuono in lire
 | |
|   if (in_valuta())
 | |
|   {
 | |
|     new_abb.valore() *= riga().get_real(PART_CAMBIO);
 | |
|     new_abb.valore().round();
 | |
|   }  
 | |
|   
 | |
|   // Scambia sezione per registrazione contabile
 | |
|   old_abbuono.swap_section();          
 | |
|   new_abbuono.swap_section();          
 | |
|   new_abbuono.normalize(sum.sezione());
 | |
|   if (new_ap != ' ')
 | |
|   {         
 | |
|     CHECK(nrigp == pagata(), "Aggiornamento abbuoni inconsistente");
 | |
|     TRectype& pag = row(nrigp);
 | |
|     pag.put(PAGSCA_ABBUONI, new_abbuono.valore());
 | |
|   } 
 | |
|   sum.update(old_abbuono, new_abbuono, PART_SEZABB, PART_ABBUONI);
 | |
|   
 | |
|   new_diffcam = calcola_differenza_cambio(TRUE);
 | |
|   // Memorizza differenza cambi invertita, mettendo new_diffcam prima di old_diffcam!
 | |
|   sum.update(new_diffcam, old_diffcam, PART_SEZDIFCAM, PART_DIFFCAM);
 | |
|   
 | |
|   sum.update(old_pag, new_pag, PART_IMPORTO);
 | |
|   sum.update(old_pag, new_pag, PART_IMPORTOVAL);
 | |
|   sum.update(old_pag, new_pag, PART_RITENUTE);
 | |
|   
 | |
|   partita().chiusa(TRUE);             // Aggiorna flag di chiusura
 | |
|   
 | |
|   return empty;
 | |
| }
 | |
| 
 | |
| bool TPartita::modifica_pagamento(const TRectype& new_pag)
 | |
| {
 | |
|   char old_ap, new_ap;
 | |
|   TImporto old_abbuono, new_abbuono, old_diffcam, new_diffcam;
 | |
|   return modifica_pagamento(new_pag, 
 | |
|                             old_ap, old_abbuono, old_diffcam, 
 | |
|                             new_ap, new_abbuono, new_diffcam);
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRiga_partite
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TRiga_partite::TRiga_partite(TPartita* game)
 | |
| : TTree_rectype(LF_PARTITE, LF_SCADENZE, SCAD_NRATA), _partita(game)
 | |
| {
 | |
|   CHECK(_partita, "Partita nulla");
 | |
| }  
 | |
| 
 | |
| TRiga_partite::TRiga_partite(const TRiga_partite& r)
 | |
| : TTree_rectype(r), _partita(r._partita)
 | |
| {
 | |
|   CHECK(_partita, "Partita nulla");
 | |
| }  
 | |
| 
 | |
| TRiga_scadenze& TRiga_partite::new_row(int r)
 | |
| {                       
 | |
|   if (r <= 0) r = last()+1;
 | |
|   
 | |
|   if (_recarr.rows() == 0)
 | |
|   {
 | |
|     TRiga_scadenze* scad = new TRiga_scadenze(this);
 | |
|     copy_key_to_row(*scad);
 | |
|     _recarr.set_key(scad);                          // Altrimenti le righe sarebbero dei TRectype!
 | |
|   }
 | |
|   
 | |
|   return (TRiga_scadenze&)_recarr.row(r, TRUE); 
 | |
| }
 | |
| 
 | |
| int TRiga_partite::read(TBaseisamfile& f, word op)
 | |
| {                  
 | |
|   int err = TRectype::read(f, op);
 | |
|   if (err == NOERR && get_int(PART_TIPOMOV) == 1)
 | |
|   {
 | |
|     TRiga_scadenze* s = new TRiga_scadenze(this);             
 | |
|     copy_key_to_row(*s);
 | |
|     err = _recarr.read(s);                // Deve esistere almento una scadenza
 | |
|   }  
 | |
|   else 
 | |
|     _recarr.destroy_rows();
 | |
|   return err; 
 | |
| }
 | |
| 
 | |
| int TRiga_partite::ultimo_pagamento(int r) const
 | |
| {
 | |
|   const TRiga_scadenze& s = rata(r);
 | |
|   return s.last();
 | |
| }
 | |
| 
 | |
| bool TRiga_partite::update(const TRectype& vec, const TRectype& nuo, const char* field)
 | |
| {
 | |
|   real totale(get(field));
 | |
|   totale -= vec.get_real(field);
 | |
|   totale += nuo.get_real(field);
 | |
|   put(field, totale);
 | |
|   return totale.is_zero();
 | |
| }
 | |
| 
 | |
| bool TRiga_partite::update(const TImporto& vec, const TImporto& nuo, 
 | |
|                            const char* sez, const char* val)
 | |
| {  
 | |
|   bool zero = FALSE;                  
 | |
|   TImporto growth(nuo); growth -= vec;     // Variazione al totale
 | |
| 
 | |
|   if (!growth.is_zero())
 | |
|   {
 | |
|     TImporto totale(get_char(sez), get_real(val));
 | |
|     totale += growth;                      // incrementa il totale
 | |
|     totale.normalize();
 | |
|     put(sez, totale.sezione());            // Aggiorna il totale sul record
 | |
|     put(val, totale.valore());
 | |
|     zero = totale.is_zero();
 | |
|   }
 | |
|   else
 | |
|     zero = get_real(val).is_zero();
 | |
|   
 | |
|   return zero;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TPartita
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TPartita::TPartita(const TBill& clifo, int anno, const char* num) 
 | |
| : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP")
 | |
| { 
 | |
|   read(clifo, anno, num); 
 | |
| }
 | |
| 
 | |
| TPartita::TPartita() 
 | |
| : _part(LF_PARTITE, PART_NRIGA), _unassigned(LF_PAGSCA, "NRIGP")
 | |
| {}
 | |
| 
 | |
| // Costruisce le righe della partita
 | |
| bool TPartita::read(const TBill& clifo, int anno, const char* num)
 | |
| {
 | |
|   TRiga_partite* partita = new TRiga_partite(this);  // Record campione della partita
 | |
|   partita->put(PART_TIPOCF, clifo.tipo());           // Tipo clifo
 | |
|   if (clifo.tipo() <= ' ')
 | |
|   {
 | |
|     partita->put(PART_GRUPPO, clifo.gruppo());       // Scrivi gruppo e conto solamente
 | |
|     partita->put(PART_CONTO, clifo.conto());         // nei conti normali (no clifo)
 | |
|   }
 | |
|   partita->put(PART_SOTTOCONTO, clifo.sottoconto()); // Sottoconto o codice clifo
 | |
|   partita->put(PART_ANNO, anno);                     // Anno partita
 | |
|   partita->put(PART_NUMPART, num);                   // Numero partita
 | |
|   _part.read(partita);
 | |
| 
 | |
|   TRectype unas(LF_PAGSCA);                          // Record campione pagamenti non assegnati
 | |
|   unas.zero();
 | |
|   unas.put(PART_TIPOCF, partita->get(PART_TIPOCF));  // Copia chiave partite
 | |
|   unas.put(PART_GRUPPO, partita->get(PART_GRUPPO));
 | |
|   unas.put(PART_CONTO, partita->get(PART_CONTO));
 | |
|   unas.put(PART_SOTTOCONTO, partita->get(PART_SOTTOCONTO));
 | |
|   unas.put(PART_ANNO, partita->get(PART_ANNO));
 | |
|   unas.put(PART_NUMPART, partita->get(PART_NUMPART));
 | |
|   unas.put(PART_NRIGA, (int)UNASSIGNED);                           
 | |
|   unas.put(SCAD_NRATA, (int)UNASSIGNED);
 | |
|   _unassigned.read(unas);
 | |
|   
 | |
|   return ok();
 | |
| }
 | |
| 
 | |
| bool TPartita::reread()
 | |
| {       
 | |
|   TBill zio;
 | |
|   conto(zio);
 | |
|   const int year = anno();
 | |
|   const TString16 num = numero();
 | |
|   return read(zio, year, num);
 | |
| }
 | |
| 
 | |
| bool TPartita::write(bool re)
 | |
| {                   
 | |
|   const bool ok = _part.write(re);
 | |
|   return ok;
 | |
| } 
 | |
| 
 | |
| bool TPartita::remove()
 | |
| {
 | |
|   _part.destroy_rows();
 | |
|   return rewrite();
 | |
| } 
 | |
| 
 | |
| 
 | |
| // Crea un  nuova riga partite e gli copia la chiave principale e il conto cliente/fornitore
 | |
| TRiga_partite& TPartita::nuova_riga() 
 | |
| {                                                                   
 | |
|   TRiga_partite& nuova = (TRiga_partite&)_part.row(last()+1, TRUE); 
 | |
|   const TRiga_partite& prima = riga(first());
 | |
|   nuova.put(PART_GRUPPOCL, prima.get(PART_GRUPPOCL));
 | |
|   nuova.put(PART_CONTOCL, prima.get(PART_CONTOCL));
 | |
|   return nuova;
 | |
| }
 | |
| 
 | |
| TRiga_scadenze& TPartita::rata(int nriga, int nrata) const
 | |
| {
 | |
|   if (nriga < 1) nriga = prima_fattura();
 | |
|   const TRiga_partite& r = riga(nriga);
 | |
|   return r.rata(nrata);
 | |
| }
 | |
| 
 | |
| TImporto TPartita::importo_speso(long nreg, int numrig, bool extra) const
 | |
| {           
 | |
|   TImporto imp;
 | |
|   
 | |
|   for (int r = last(); r > 0; r = pred(r))
 | |
|   {
 | |
|     const TRiga_partite& part = riga(r);
 | |
|     const long reg = part.get_long(PART_NREG);
 | |
|     if (reg == nreg)
 | |
|     {
 | |
|       const int num = part.get_int(PART_NUMRIG);
 | |
|       if (num == numrig) 
 | |
|       {                                  
 | |
|         const char sez = part.get_char(PART_SEZ);             // Deve essere valida per forza!
 | |
|         imp += TImporto(sez, part.get_real(PART_IMPORTO));
 | |
|         
 | |
|         if (extra)
 | |
|         {
 | |
|           TImporto abbuoni(part.get_char(PART_SEZABB), part.get_real(PART_ABBUONI));
 | |
|           if (part.in_valuta())            // Se e' in valuta
 | |
|           {
 | |
|             abbuoni.valore() *= part.get_real(PART_CAMBIO);
 | |
|             abbuoni.valore().round();
 | |
|           }  
 | |
|           imp += abbuoni;
 | |
|           imp += TImporto(part.get_char(PART_SEZDIFCAM), part.get_real(PART_DIFFCAM));
 | |
|         }    
 | |
|       }  
 | |
|     }    
 | |
|   }
 | |
|   
 | |
|   return imp;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TPartita::update_reg_num(long nreg, const TRectype& mov)
 | |
| {
 | |
|   for (int r = last(); r > 0; r = pred(r))
 | |
|   {
 | |
|     TRectype& pag = _part.row(r, FALSE);
 | |
|     
 | |
|     const long reg = pag.get_long(PART_NREG);
 | |
|     if (reg == nreg)
 | |
|     {
 | |
|       pag.put(PART_NREG, mov.get(MOV_NUMREG));
 | |
|       pag.put(PART_DATAREG, mov.get(MOV_DATAREG));
 | |
|       pag.put(PART_NUMDOC, mov.get(MOV_NUMDOC));
 | |
|       pag.put(PART_DATADOC, mov.get(MOV_DATADOC));
 | |
|     }    
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Calcola la riga di movimento relativa a una riga partita
 | |
| int TPartita::rig2mov(int rp) const
 | |
| {
 | |
|   const TRiga_partite& r = riga(rp);
 | |
|   return r.get_int(PART_NUMRIG);
 | |
| }
 | |
| 
 | |
| // Calcola la riga di partita relativa a una riga movimento
 | |
| int TPartita::mov2rig(long numreg, int rm) const
 | |
| { 
 | |
|   for (int r = last(); r > 0; r = pred(r))
 | |
|   {
 | |
|     const TRiga_partite& row = riga(r);
 | |
|     if (row.get_long(PART_NREG) == numreg)
 | |
|     {
 | |
|       if (rm <= 0 || row.get_int(PART_NUMRIG) == rm)
 | |
|         return r;
 | |
|     }  
 | |
|   }
 | |
|   return -1;
 | |
| } 
 | |
| 
 | |
| // Trova la prima riga della partita contenente una fattura
 | |
| int TPartita::prima_fattura(long nreg) const
 | |
| {  
 | |
|   const int lastrow = last();
 | |
|   for (int r = first(); r <= lastrow; r = succ(r))
 | |
|   {
 | |
|     const TRiga_partite& row = riga(r);
 | |
|     const int tipomov = row.get_int(PART_TIPOMOV);
 | |
|     if (tipomov == 1 || tipomov == 2)
 | |
|       if (nreg == -1 || nreg == row.get_long(PART_NREG))
 | |
|         return r;
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| // Trova la prima riga della partita contenente una fattura
 | |
| int TPartita::primo_pagamento(long nreg) const
 | |
| {  
 | |
|   const int lastrow = last();
 | |
|   for (int r = first(); r <= lastrow; r = succ(r))
 | |
|   {
 | |
|     const TRiga_partite& row = riga(r);
 | |
|     const int tipomov = row.get_int(PART_TIPOMOV);
 | |
|     if (tipomov == 3)   // TBI controllare per insoluti (tipomov == 6)
 | |
|       if (nreg == -1 || nreg == row.get_long(PART_NREG))
 | |
|         return r;
 | |
|   }
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| void TPartita::calcola_saldo(TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp) const
 | |
| {   
 | |
|   doc = pag = imp = TImporto('D', ZERO);
 | |
| 
 | |
|   for (int r = last(); r > 0; r = pred(r))
 | |
|   {
 | |
|     const TRiga_partite& row = riga(r);
 | |
|     TImporto i(row.get_char(PART_SEZ), row.get_real(PART_IMPORTO));
 | |
|     switch (row.get_int(PART_TIPOMOV))
 | |
|     {
 | |
|     case 1:
 | |
|     case 2:
 | |
|       doc += i;              // documenti
 | |
|       break;
 | |
|     case 3: 
 | |
|       pag += i;              // pagamenti
 | |
|       break;
 | |
|     default:
 | |
|       imp += i;              // altri importi
 | |
|       break;
 | |
|     }    
 | |
|     
 | |
|     TImporto abbuoni(row.get_char(PART_SEZABB), row.get_real(PART_ABBUONI));
 | |
|     if (row.get(PART_CODVAL).not_empty())
 | |
|     {
 | |
|       abbuoni.valore() *= row.get_real(PART_CAMBIO);
 | |
|       abbuoni.valore().round();
 | |
|     }
 | |
|     imp += abbuoni;
 | |
|     
 | |
|     imp += TImporto(row.get_char(PART_SEZDIFCAM), row.get_real(PART_DIFFCAM));
 | |
|   }
 | |
| 
 | |
|   saldo = doc;
 | |
|   saldo += pag;
 | |
|   saldo += imp;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TPartita::utilizzata(int nrigp) const
 | |
| {           
 | |
|   for (int p = last(); p > 0; p = pred(p))
 | |
|   {
 | |
|     const TRiga_partite& fatt = riga(p);
 | |
|     const int tipomov = fatt.get_int(PART_TIPOMOV);
 | |
|     if (tipomov == 1)
 | |
|     {
 | |
|       for (int r = fatt.rate(); r > 0; r--)
 | |
|       {
 | |
|         const TRiga_scadenze& scad = fatt.rata(r);
 | |
|         if (scad.rows_array().exist(nrigp))
 | |
|           return TRUE;
 | |
|       }
 | |
|     }    
 | |
|   }           
 | |
|   return _unassigned.exist(nrigp);
 | |
| } 
 | |
| 
 | |
| 
 | |
| bool TPartita::remove_unassigned(long nreg)
 | |
| {              
 | |
|   bool found = FALSE;
 | |
| 
 | |
|   for (int u = _unassigned.last_row(); u > 0; u = _unassigned.pred_row(u))
 | |
|   {
 | |
|     const TRectype& pag = _unassigned.row(u);
 | |
|     const int nrigp = pag.get_int(PAGSCA_NRIGP);
 | |
|     TRiga_partite& sum = riga(nrigp);
 | |
|     if (sum.get_long(PART_NREG) == nreg)
 | |
|     {         
 | |
|       TRectype zero(pag); zero.zero();
 | |
|       sum.update(pag, zero, PART_IMPORTO);
 | |
|       sum.update(pag, zero, PART_IMPORTOVAL);
 | |
|       sum.update(pag, zero, PART_RITENUTE);
 | |
|       _unassigned.destroy_row(u);
 | |
|       found = TRUE;
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   return found;
 | |
| }
 | |
| 
 | |
| bool TPartita::modifica_pagamento(const TRectype& new_pag,
 | |
|                                   char& old_ap, TImporto& old_abb, TImporto& old_diffcam,  
 | |
|                                   char& new_ap, TImporto& new_abb, TImporto& new_diffcam)
 | |
| {                    
 | |
|   const int nriga = new_pag.get_int(PAGSCA_NRIGA);
 | |
|   const TRiga_partite& fattura = riga(nriga);
 | |
|   
 | |
|   const int nrata = new_pag.get_int(PAGSCA_NRATA);
 | |
|   TRiga_scadenze& scaden = fattura.rata(nrata);
 | |
| 
 | |
|   const int nrigp = new_pag.get_int(PAGSCA_NRIGP);
 | |
|   const TRectype& old_pag = scaden.row(nrigp);
 | |
| 
 | |
|   const bool empty = scaden.modifica_pagamento(new_pag,
 | |
|                                                old_ap, old_abb, old_diffcam,  
 | |
|                                                new_ap, new_abb, new_diffcam);
 | |
|   
 | |
|   if (empty && !utilizzata(nrigp))
 | |
|     _part.destroy_row(nrigp);
 | |
|   
 | |
|   return empty;    
 | |
| } 
 | |
| 
 | |
| bool TPartita::chiusa(bool update)
 | |
| {
 | |
|   const TRiga_partite& row = riga(first());
 | |
|   bool chiusa = row.get_bool(PART_CHIUSA);
 | |
|   
 | |
|   if (update)
 | |
|   {
 | |
|     bool forse_chiusa = TRUE;
 | |
|     for (int p = last(); p > 0 && forse_chiusa; p = pred(p))
 | |
|     {
 | |
|       const TRiga_partite& part = riga(first());
 | |
|       if (part.get_int(PART_TIPOMOV) == 1)
 | |
|       {
 | |
|         for (int r = part.last(); r > 0; r--)
 | |
|         {
 | |
|           const TRiga_scadenze& scad = part.rata(r);
 | |
|           if (!scad.pagata())
 | |
|           {
 | |
|             forse_chiusa = FALSE;
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }  
 | |
|     
 | |
|     if (chiusa != forse_chiusa)
 | |
|     {
 | |
|       chiusa = forse_chiusa;
 | |
|       for (p = last(); p > 0; p = pred(p))
 | |
|       {
 | |
|         TRiga_partite& part = riga(first());
 | |
|         part.put(PART_CHIUSA, chiusa);
 | |
|       }
 | |
|     }
 | |
|   }  
 | |
| 
 | |
|   return chiusa;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TPartite_array
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| // Certified 99%              
 | |
| const TString& TPartite_array::key(const TBill& clifo, int anno, const char* num)
 | |
| {                  
 | |
|   if (clifo.tipo() > ' ')
 | |
|     _key.format("%c%3d%3d%6ld%4d%s", clifo.tipo(), 0, 0, clifo.sottoconto(), anno, num);
 | |
|   else
 | |
|     _key.format("%c%3d%3d%6ld%4d%s", 
 | |
|                 clifo.tipo(), clifo.gruppo(), clifo.conto(), clifo.sottoconto(), anno, num);
 | |
|   return _key;
 | |
| }
 | |
| 
 | |
| // Certified 99%              
 | |
| TPartita* TPartite_array::find(const TBill& clifo, int anno, const char* num, bool create)
 | |
| {
 | |
|   const TString& k = key(clifo, anno, num);
 | |
|   TPartita* p = (TPartita*)objptr(k);
 | |
|   if (p == NULL && create)
 | |
|   {
 | |
|     p = new TPartita(clifo, anno, num);
 | |
|     if (p->ok()) 
 | |
|       add(k, p);
 | |
|     else 
 | |
|     {
 | |
|       delete p;
 | |
|       p = NULL;
 | |
|     }
 | |
|   }
 | |
|   return p;
 | |
| }
 | |
| 
 | |
| TPartita* TPartite_array::find(const TRectype& r, bool create)
 | |
| {                           
 | |
|   TBill zio; zio.get(r);
 | |
|   const int anno = r.get_int(PART_ANNO);
 | |
|   const char* num = r.get_str(PART_NUMPART);
 | |
|   return find(zio, anno, num, create);
 | |
| }
 | |
| 
 | |
| TPartita& TPartite_array::partita(const TBill& clifo, int anno, const char* num)
 | |
| {                           
 | |
|   TPartita* game = find(clifo, anno, num, TRUE);
 | |
|   CHECKS(game, "Partita errata ", num);
 | |
|   return *game;
 | |
| }
 | |
| 
 | |
| TPartita& TPartite_array::partita(const TRectype& r)
 | |
| {                           
 | |
|   TPartita* game = find(r, TRUE);
 | |
|   CHECK(game, "Partita errata");
 | |
|   return *game;
 | |
| }
 | |
| 
 | |
| bool TPartite_array::write(bool re)
 | |
| {       
 | |
|   int err = NOERR;
 | |
|   
 | |
|   TPartita* game;
 | |
|   restart();
 | |
|   while ((game = (TPartita*)get()) != NULL)
 | |
|   {
 | |
|     err = game->write(re);
 | |
|     if (err != NOERR)    // L'errore viene gia' segnalato dalla partita
 | |
|       break;
 | |
|   }  
 | |
|   
 | |
|   return err == NOERR;
 | |
| }
 | |
| 
 | |
| // Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg
 | |
| int TPartite_array::add_reg_num(long nreg, int numrig)
 | |
| {
 | |
|   TRelation rel(LF_PARTITE);
 | |
|   TRectype& part = rel.lfile().curr(); 
 | |
|   
 | |
|   // Costruzione filtro del cursore
 | |
|   part.zero();
 | |
|   part.put(PART_NREG, nreg);
 | |
|   if (numrig > 0)
 | |
|     part.put(PART_NUMRIG, numrig);
 | |
|   
 | |
|   const TRectype filter(part);    
 | |
| 
 | |
|   TCursor cur(&rel, "", 2, &filter, &filter);
 | |
|   
 | |
|   for (cur = 0; cur.ok(); ++cur)
 | |
|   {
 | |
|     TPartita& p = partita(part); // Aggiungi partita se non esiste gia'
 | |
|     p.remove_unassigned(nreg);   // Togli righe non assegnate
 | |
|   }  
 | |
|   
 | |
|   return (int)cur.items();
 | |
| }
 | |
| 
 | |
| TImporto TPartite_array::importo_speso(long nreg, int numrig, bool extra)
 | |
| {
 | |
|   TImporto imp;
 | |
|   add_reg_num(nreg, numrig);
 | |
|   for (TPartita* game = first(); game; game = next())
 | |
|     imp += game->importo_speso(nreg, numrig, extra);
 | |
|   return imp;
 | |
| }
 | |
| 
 | |
| void TPartite_array::update_reg_num(long nreg, const TRectype& mov)
 | |
| {
 | |
|   add_reg_num(nreg, 0);      
 | |
|   for (TPartita* game = first(); game; game = next())
 | |
|     game->update_reg_num(nreg, mov);
 | |
| }
 | |
| 
 |