2495 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2495 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <config.h>
 | 
						||
#include <currency.h>
 | 
						||
#include <mask.h>
 | 
						||
#include <relation.h>
 | 
						||
 | 
						||
#include "cgsaldac.h"
 | 
						||
#include "cg2103.h"
 | 
						||
 | 
						||
#include <doc.h>
 | 
						||
#include <mov.h>
 | 
						||
#include <rmov.h>
 | 
						||
#include <rcausali.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::renum_key(const char* field, const char* val)
 | 
						||
{                   
 | 
						||
  TRectype::renum_key(field, val);
 | 
						||
  _recarr.renum_key(field, val);
 | 
						||
}
 | 
						||
 | 
						||
void TTree_rectype::copy_key_to_row(TRectype& row) const
 | 
						||
{   
 | 
						||
  const RecDes& recd = rec_des();  // Descrizione del record della testata
 | 
						||
  row.zero();                              
 | 
						||
  const KeyDes& kd = recd.Ky[0];   // Memento! Gli indici delle chiavi partono da zero!  
 | 
						||
  for (int i = kd.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.renum_key(name, val);
 | 
						||
  }
 | 
						||
}  
 | 
						||
 | 
						||
TRectype& TTree_rectype::new_row(int r) 
 | 
						||
{ 
 | 
						||
  if (r <= 0) 
 | 
						||
    r = last()+1;                     
 | 
						||
  CHECKD(!exist(r), "Ue' pirla! Esiste gia' la riga ", r);
 | 
						||
  TRectype& row = rows_array().row(r, true); 
 | 
						||
  return row;
 | 
						||
}
 | 
						||
 | 
						||
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, word lockop)
 | 
						||
{
 | 
						||
  int err = TRectype::read(f, op, lockop);
 | 
						||
  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) const
 | 
						||
{
 | 
						||
  int err = TRectype::remove(f);
 | 
						||
  if (err == NOERR)
 | 
						||
    err = _recarr.remove();
 | 
						||
  return err; 
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// Valuta
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TValuta::TValuta(const char* cod, const TDate& dat, const real& cam)
 | 
						||
: _cod(cod), _dat(dat), _cam(cam)
 | 
						||
{
 | 
						||
  adjust();
 | 
						||
}
 | 
						||
 | 
						||
TValuta::TValuta() : _cod(""), _dat(TODAY), _cam(ZERO)
 | 
						||
{
 | 
						||
  adjust();
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::adjust()
 | 
						||
{ 
 | 
						||
  const TCurrency this_cur(ZERO, _cod, _cam);
 | 
						||
  if (this_cur.is_firm_value())
 | 
						||
  {
 | 
						||
    _cod.cut(0);
 | 
						||
    _cam = ZERO;
 | 
						||
  } 
 | 
						||
  else
 | 
						||
  { 
 | 
						||
    if (_cam < ZERO) 
 | 
						||
      _cam = ZERO; 
 | 
						||
    _cod = this_cur.get_value();
 | 
						||
  }    
 | 
						||
}
 | 
						||
 | 
						||
int TValuta::compare(const TSortable& s) const
 | 
						||
{
 | 
						||
  const TValuta& v = (const TValuta&)s;
 | 
						||
  return _cod.compare(v._cod, -1, true); // qui verificare
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::get(const TRectype& rec)
 | 
						||
{
 | 
						||
  _cod = rec.get("CODVAL");
 | 
						||
  _dat = rec.get("DATACAM");
 | 
						||
  _cam = rec.get_real("CAMBIO");
 | 
						||
  adjust();
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::put(TRectype& rec) const
 | 
						||
{
 | 
						||
  if (in_valuta())            
 | 
						||
  {  
 | 
						||
    rec.put("CODVAL",  _cod);
 | 
						||
    rec.put("DATACAM", _dat);
 | 
						||
    rec.put("CAMBIO",  _cam);
 | 
						||
  }
 | 
						||
  else
 | 
						||
  {
 | 
						||
    rec.zero("CODVAL");
 | 
						||
    rec.zero("DATACAM");
 | 
						||
    rec.zero("CAMBIO");
 | 
						||
  }  
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::set(TMask& m, short v, short d, short c) const
 | 
						||
{
 | 
						||
  if (in_valuta())            
 | 
						||
  {
 | 
						||
    m.set(v, _cod);
 | 
						||
    m.set(d, _dat.string());
 | 
						||
    m.set(c, _cam.string());
 | 
						||
  }  
 | 
						||
  else
 | 
						||
  {
 | 
						||
    m.reset(v);
 | 
						||
    m.reset(d);
 | 
						||
    m.reset(c);
 | 
						||
  }  
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::get(const TMask& m, short v, short d, short c)
 | 
						||
{
 | 
						||
  _cod = m.get(v);
 | 
						||
  _dat = m.get(d);
 | 
						||
  _cam = m.get_real(c);
 | 
						||
  adjust();
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::set(const TValuta& v)
 | 
						||
{
 | 
						||
  _cod = v._cod;
 | 
						||
  _dat = v._dat;
 | 
						||
  _cam = v._cam; 
 | 
						||
}
 | 
						||
 | 
						||
real TValuta::eur2val(const real& lit) const
 | 
						||
{
 | 
						||
  TCurrency cur(lit);
 | 
						||
  cur.change_value(_cod, _cam);
 | 
						||
  return cur.get_num();
 | 
						||
}
 | 
						||
 | 
						||
real TValuta::val2eur(const real& val) const
 | 
						||
{   
 | 
						||
  TCurrency cur(val, _cod, _cam);
 | 
						||
  cur.change_to_firm_val();
 | 
						||
  return cur.get_num();
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::val2eur(real& val) const
 | 
						||
{   
 | 
						||
  TCurrency cur(val, _cod, _cam);
 | 
						||
  cur.change_to_firm_val();
 | 
						||
  val = cur.get_num();
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::eur2val(real& lit) const
 | 
						||
{   
 | 
						||
  TCurrency cur(lit);
 | 
						||
  cur.change_value(_cod, _cam);
 | 
						||
  lit = cur.get_num();
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::val2eur(TImporto& imp) const
 | 
						||
{           
 | 
						||
  val2eur(imp.valore());
 | 
						||
}
 | 
						||
 | 
						||
void TValuta::eur2val(TImporto& imp) const
 | 
						||
{           
 | 
						||
  eur2val(imp.valore());
 | 
						||
}
 | 
						||
 | 
						||
int TValuta::decimals() const
 | 
						||
{
 | 
						||
  const TExchange ex(_cod, _cam);
 | 
						||
  return ex.decimals();
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TRiga_scadenze
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TRiga_scadenze::TRiga_scadenze(TRiga_partite* r)
 | 
						||
: TTree_rectype(LF_SCADENZE, LF_PAGSCA, "NRIGP"), _riga(r)
 | 
						||
{
 | 
						||
  CHECK(_riga, "Riga nulla");
 | 
						||
  r->copy_key_to_row(*this);
 | 
						||
}  
 | 
						||
 | 
						||
TRiga_scadenze::TRiga_scadenze(const TRiga_scadenze& s)
 | 
						||
: TTree_rectype(s), _riga(s._riga)
 | 
						||
{} 
 | 
						||
 | 
						||
TRiga_scadenze::~TRiga_scadenze()
 | 
						||
{
 | 
						||
} 
 | 
						||
 | 
						||
TObject* TRiga_scadenze::dup() const
 | 
						||
{
 | 
						||
  TRiga_scadenze* r = new TRiga_scadenze(*this);
 | 
						||
  return r;
 | 
						||
}
 | 
						||
 | 
						||
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().in_valuta();
 | 
						||
}
 | 
						||
 | 
						||
// Controlla se la fattura della rata e' in valuta
 | 
						||
const TString& TRiga_scadenze::codice_valuta() const
 | 
						||
{
 | 
						||
  return riga().codice_valuta();
 | 
						||
}
 | 
						||
 | 
						||
// Controlla se la rata e' stata completamente pagata
 | 
						||
bool TRiga_scadenze::chiusa(bool update) const
 | 
						||
{                                      
 | 
						||
  bool chiusa = false;
 | 
						||
  if (update)
 | 
						||
  {          
 | 
						||
    TImporto imp(importo(true));
 | 
						||
    imp += importo_pagato(true);
 | 
						||
    chiusa = imp.is_zero();
 | 
						||
    ((TRectype*)this)->put(SCAD_PAGATA, chiusa ? "X" : "");
 | 
						||
  }
 | 
						||
  else
 | 
						||
    chiusa = get_bool(SCAD_PAGATA);
 | 
						||
  
 | 
						||
  return chiusa;  
 | 
						||
}
 | 
						||
 | 
						||
TImporto TPartita::importo_pagsca(const TRectype& pag, bool val, int mode) const 
 | 
						||
{
 | 
						||
  CHECK(pag.num() == LF_PAGSCA, "Solo PAGSCA prego");
 | 
						||
  TImporto totale;
 | 
						||
  const int nrigp = pag.get_int(PAGSCA_NRIGP);
 | 
						||
  if (!esiste(nrigp))
 | 
						||
    return totale;
 | 
						||
 | 
						||
  const TRiga_partite& sum = riga(nrigp);
 | 
						||
 | 
						||
  // Inizio aggiunte di Bonazzi del 16/02/2012
 | 
						||
  if (mode & 0x10)               // solo le note di credito
 | 
						||
  {
 | 
						||
    const tipo_movimento tm = sum.tipo();
 | 
						||
    if (tm != tm_nota_credito)
 | 
						||
      return totale;  // = ZERO
 | 
						||
  }
 | 
						||
  // Fine aggiunte di Bonazzi del 16/02/2012
 | 
						||
 | 
						||
  const bool in_val = sum.in_valuta();   
 | 
						||
  const char* imp_field = (val && in_val) ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
 | 
						||
 | 
						||
  const char sez = sum.sezione();    
 | 
						||
	if (mode & 0x1)              
 | 
						||
  {
 | 
						||
		totale += TImporto(sez, pag.get_real(imp_field));
 | 
						||
  }
 | 
						||
      
 | 
						||
  if (!in_val && (mode & 0x8))      // Le ritenute non esistono nei pagamenti in valuta
 | 
						||
	{
 | 
						||
		totale += TImporto(sez, pag.get_real(PAGSCA_RITENUTE));
 | 
						||
		totale += TImporto(sum.sezione_ritsoc(), pag.get_real(PAGSCA_RITSOC));
 | 
						||
	}
 | 
						||
	    
 | 
						||
	if (mode & 0x2)                   // Voglio anche gli abbuoni
 | 
						||
	{
 | 
						||
		real abb = pag.get_real(PAGSCA_ABBUONI);
 | 
						||
		if (!abb.is_zero())
 | 
						||
		{
 | 
						||
			if (in_val && !val)             // Gli abbuoni sono sempre in valuta e quindi
 | 
						||
			{                               // devono essere convertiti opportunamente
 | 
						||
				const TExchange cmb(sum);
 | 
						||
				TCurrency cur(abb, cmb);
 | 
						||
				cur.change_to_firm_val();
 | 
						||
				abb = cur.get_num();
 | 
						||
			}
 | 
						||
  		totale += TImporto(sez, abb);
 | 
						||
  	}  
 | 
						||
	}
 | 
						||
	    
 | 
						||
	if (in_val && !val && (mode & 0x4))   // Voglio anche le differenze cambio
 | 
						||
	{                                     // Esse esistono solo nei pagamenti in valuta
 | 
						||
		const TImporto diffcam(sez, pag.get_real(PAGSCA_DIFFCAM));
 | 
						||
		totale += diffcam;
 | 
						||
	}
 | 
						||
 | 
						||
  return totale;
 | 
						||
}
 | 
						||
 | 
						||
// Calcola il totale dei pagamenti alla data (eventualmente in valuta)
 | 
						||
TImporto TRiga_scadenze::importo_pagato_al(bool val, const TDate& al, int mode) const
 | 
						||
{                                
 | 
						||
  CHECKD(mode > 0x0 && mode <= 0xFF, "Bad importo_pagato mode ", mode);
 | 
						||
  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 TDate datapag = sum.get_date(PART_DATAPAG);
 | 
						||
		if (datapag <= al)
 | 
						||
      totale += game.importo_pagsca(pag, val, mode);
 | 
						||
  }  
 | 
						||
  
 | 
						||
  return totale.normalize();
 | 
						||
}
 | 
						||
 | 
						||
// Calcola il totale dei pagamenti (eventualmente in valuta)
 | 
						||
TImporto TRiga_scadenze::importo_pagato(bool val, int mode) const
 | 
						||
{                                
 | 
						||
  CHECKD(mode > 0x0 && mode <= 0xFF, "Bad importo_pagato mode ", mode);
 | 
						||
  const TPartita& game = partita();
 | 
						||
  const bool in_val = in_valuta();   
 | 
						||
  const char* imp_field = (val && in_val) ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
 | 
						||
  
 | 
						||
  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 char sez = sum.sezione();
 | 
						||
    
 | 
						||
    if (mode & 0x1)              
 | 
						||
      totale += TImporto(sez, pag.get_real(imp_field));
 | 
						||
    if (!in_val && (mode & 0x8))      // Le ritenute non esistono nei pagamenti in valuta
 | 
						||
    {
 | 
						||
      totale += TImporto(sez, pag.get_real(PAGSCA_RITENUTE));
 | 
						||
      totale += TImporto(sum.sezione_ritsoc(), pag.get_real(PAGSCA_RITSOC));
 | 
						||
    }
 | 
						||
    
 | 
						||
    if (mode & 0x2)                   // Voglio anche gli abbuoni
 | 
						||
    {
 | 
						||
      real abb = pag.get_real(PAGSCA_ABBUONI);
 | 
						||
      if (!abb.is_zero())
 | 
						||
      {
 | 
						||
        if (in_val && !val)             // Gli abbuoni sono sempre in valuta e quindi
 | 
						||
        {                               // devono essere convertiti opportunamente
 | 
						||
          const TExchange cmb(sum);
 | 
						||
          TCurrency cur(abb, cmb);
 | 
						||
          cur.change_to_firm_val();
 | 
						||
          abb = cur.get_num();
 | 
						||
        }
 | 
						||
        totale += TImporto(sez, abb);
 | 
						||
      }  
 | 
						||
    }
 | 
						||
    
 | 
						||
    if (in_val && !val && (mode & 0x4))   // Voglio anche le differenze cambio
 | 
						||
    {                                     // Esse esistono solo nei pagamenti in valuta
 | 
						||
      const TImporto diffcam(sez, pag.get_real(PAGSCA_DIFFCAM));
 | 
						||
      totale += diffcam;
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  
 | 
						||
  return totale.normalize();
 | 
						||
}
 | 
						||
 | 
						||
// Calcola l'importo da pagare (eventualmente in valuta)
 | 
						||
TImporto TRiga_scadenze::importo(bool val) const
 | 
						||
{                                       
 | 
						||
  const TRiga_partite& fatt = riga();              // Riga fattura
 | 
						||
  const char* const imp = val && in_valuta() ? SCAD_IMPORTOVAL : SCAD_IMPORTO;
 | 
						||
  const TImporto i(fatt.sezione(), get_real(imp));  
 | 
						||
  return i;
 | 
						||
}
 | 
						||
 | 
						||
// Calcola l'abbuono in valuta della rata e ritorna il suo tipo:
 | 
						||
// 'A' abbuono attivo; 'P' abbuono passivo
 | 
						||
char TRiga_scadenze::calcola_abbuono(int p, TImporto& abbuono, bool update)
 | 
						||
{
 | 
						||
  char ap = ' ';
 | 
						||
  TRectype& pag = row(p);
 | 
						||
 | 
						||
  const char sez = partita().riga(p).sezione();
 | 
						||
  
 | 
						||
  if (update)
 | 
						||
  {
 | 
						||
    if (pag.get_char(PAGSCA_ACCSAL) == 'S')
 | 
						||
    {                                
 | 
						||
      abbuono = importo(true);
 | 
						||
      pag.zero(PAGSCA_ABBUONI);
 | 
						||
      abbuono += importo_pagato(true, 0x0B);  // Somma di importi, abbuoni e ritenute
 | 
						||
      abbuono.swap_section();
 | 
						||
 | 
						||
      const int sign = abbuono.valore().sign();
 | 
						||
      if (sign != 0)
 | 
						||
      {
 | 
						||
        if (sign > 0)
 | 
						||
          ap = abbuono.sezione() == 'D' ? 'A' : 'P';
 | 
						||
        else  
 | 
						||
          ap = abbuono.sezione() == 'D' ? 'P' : 'A';
 | 
						||
      }                       
 | 
						||
    }
 | 
						||
    else 
 | 
						||
      abbuono.valore() = ZERO;
 | 
						||
    
 | 
						||
    if (ap > ' ')  
 | 
						||
    {                         
 | 
						||
      abbuono.normalize(sez);
 | 
						||
      pag.put(PAGSCA_ABBUONI, abbuono.valore());
 | 
						||
      pag.put(PAGSCA_PASSATT, ap);
 | 
						||
    }  
 | 
						||
    else
 | 
						||
    {
 | 
						||
      pag.zero(PAGSCA_ABBUONI);
 | 
						||
      pag.zero(PAGSCA_PASSATT);
 | 
						||
    }  
 | 
						||
  }
 | 
						||
  else
 | 
						||
  {
 | 
						||
    abbuono.set(sez, pag.get_real(PAGSCA_ABBUONI));
 | 
						||
    ap = pag.get_char(PAGSCA_PASSATT);
 | 
						||
    if (ap < ' ') ap = ' ';
 | 
						||
  }
 | 
						||
  
 | 
						||
  return ap;
 | 
						||
}
 | 
						||
 | 
						||
// Calcola la differenza cambi con la sezione da mettere nella riga contabile corrispondente
 | 
						||
TImporto TRiga_scadenze::calcola_differenza_cambio(int p, bool update)
 | 
						||
{ 
 | 
						||
  TImporto diffcam;      
 | 
						||
 | 
						||
  TRectype& pag = row(p);
 | 
						||
  const bool a_saldo = pag.get_char(PAGSCA_ACCSAL) == 'S';
 | 
						||
  if (in_valuta() && (a_saldo || partita().rileva_sempre_differenze_cambi()))
 | 
						||
  {
 | 
						||
    const char sez = partita().riga(p).sezione();   
 | 
						||
    if (update)
 | 
						||
    {
 | 
						||
      const int dec = TCurrency::get_firm_dec();
 | 
						||
      // Normalmente le differenze cambio si rilevano solo a saldo ... 
 | 
						||
      if (a_saldo)
 | 
						||
      {
 | 
						||
        diffcam = importo(false);         // Importo della scadenza in in euro
 | 
						||
        pag.zero(PAGSCA_DIFFCAM);         // Azzera temporaneamente la DIFFCAM del pagamento corrente
 | 
						||
        diffcam += importo_pagato(false); // Conta anche gli abbuoni e le altre diffcam
 | 
						||
        diffcam.swap_section();
 | 
						||
      }
 | 
						||
      else // ... ma non alla Pharmatex
 | 
						||
      {
 | 
						||
        const TImporto e = importo(false); // Importo della scadenza in euro
 | 
						||
        const TImporto v = importo(true);  // Importo della scadenza in valuta
 | 
						||
        const real pg = pag.get_real(PAGSCA_IMPORTO);
 | 
						||
        real rt = e.valore() * pag.get_real(PAGSCA_IMPORTOVAL) / v.valore(); 
 | 
						||
        rt.round(dec);
 | 
						||
        diffcam.set(e.sezione(), rt-pg);
 | 
						||
      }
 | 
						||
     
 | 
						||
      diffcam.normalize(sez);
 | 
						||
      pag.put(PAGSCA_DIFFCAM, diffcam.valore());
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {                                            
 | 
						||
      diffcam.set(sez, pag.get_real(PAGSCA_DIFFCAM));
 | 
						||
    }  
 | 
						||
  } 
 | 
						||
  else
 | 
						||
  {
 | 
						||
    if (update)
 | 
						||
      pag.zero(PAGSCA_DIFFCAM);
 | 
						||
  }
 | 
						||
 | 
						||
  return diffcam;
 | 
						||
}
 | 
						||
 | 
						||
TImporto TRiga_scadenze::residuo(bool val, int mode) const
 | 
						||
{                         
 | 
						||
  TImporto residuo(importo(val));
 | 
						||
  residuo += importo_pagato(val, mode);            // Somma con sezione opposta 
 | 
						||
  residuo.normalize();
 | 
						||
  return residuo;
 | 
						||
}
 | 
						||
 | 
						||
TImporto TRiga_scadenze::esposto_al(bool valuta, const TDate & al, const TDate & data_scad, const TDate & data_rischio, bool & sbf) const
 | 
						||
{        
 | 
						||
  TImporto esposto;
 | 
						||
  const bool rischio = data_scad != data_rischio; 
 | 
						||
	TDate data(get(SCAD_DATASCAD));
 | 
						||
	const int lasts = last();
 | 
						||
 
 | 
						||
  sbf = false;
 | 
						||
	for (int p = first(); p <= lasts; p = succ(p)) 
 | 
						||
	{            
 | 
						||
		const TRiga_partite & pag = riga().partita().riga(p);
 | 
						||
		TDate datapag = pag.get_date(PART_DATAPAG);
 | 
						||
		
 | 
						||
		if (data.ok() && datapag > data)
 | 
						||
			datapag = data;
 | 
						||
		if (datapag <= al)
 | 
						||
		{
 | 
						||
			const tipo_pagamento tp = pag.tipo_pag();
 | 
						||
 | 
						||
			if (tp >= tp_tratta && tp <= tp_rid)
 | 
						||
			{
 | 
						||
				const char sez = pag.sezione();
 | 
						||
				const TImporto imp(sez, pag.get_real(valuta ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO));
 | 
						||
				
 | 
						||
				if (rischio && datapag > data_rischio && datapag <= data_scad)
 | 
						||
				{
 | 
						||
					esposto += imp; 
 | 
						||
					sbf = true;
 | 
						||
				}
 | 
						||
				else
 | 
						||
					if (datapag > data_scad)
 | 
						||
						esposto += imp;
 | 
						||
			}
 | 
						||
		}
 | 
						||
	} 
 | 
						||
 | 
						||
  return esposto;    
 | 
						||
} 
 | 
						||
 | 
						||
TImporto TRiga_scadenze::esposto(bool valuta, const TDate& data_scad, const TDate& data_rischio, bool& sbf) const
 | 
						||
{        
 | 
						||
  TImporto esposto;
 | 
						||
  const bool rischio = data_scad != data_rischio; 
 | 
						||
	TDate data(get(SCAD_DATASCAD));
 | 
						||
	const int lasts = last();
 | 
						||
 
 | 
						||
  sbf = false;
 | 
						||
	for (int p = first(); p <= lasts; p = succ(p)) 
 | 
						||
	{            
 | 
						||
		const TRiga_partite & pag = riga().partita().riga(p);
 | 
						||
		const tipo_pagamento tp = pag.tipo_pag();
 | 
						||
 | 
						||
		if (tp >= tp_tratta && tp <= tp_rid)
 | 
						||
		{
 | 
						||
		  const char sez = pag.sezione();
 | 
						||
			const TImporto imp(sez, pag.get_real(valuta ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO));
 | 
						||
			TDate datapag(pag.get(PART_DATAPAG));
 | 
						||
			
 | 
						||
			if (data.ok() && datapag > data)
 | 
						||
				datapag = data; // controllo
 | 
						||
			if (rischio && datapag > data_rischio && datapag <= data_scad)
 | 
						||
			{
 | 
						||
				esposto += imp; 
 | 
						||
				sbf = true;
 | 
						||
			}
 | 
						||
			else
 | 
						||
				if (datapag > data_scad)
 | 
						||
					esposto += imp;
 | 
						||
		}
 | 
						||
	} 
 | 
						||
 | 
						||
  return esposto;    
 | 
						||
} 
 | 
						||
 | 
						||
bool TRiga_scadenze::modifica_pagamento(const TRectype& new_pag, const TValuta& valuta,
 | 
						||
                                        char& old_ap, TImporto& old_abb, TImporto& old_diffcam,  
 | 
						||
                                        char& new_ap, TImporto& new_abb, TImporto& new_diffcam,
 | 
						||
                                        bool update)
 | 
						||
{       
 | 
						||
  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(nrigp, old_abbuono, false);   // Vecchio abbuono in valuta
 | 
						||
  old_abb = old_abbuono;                                 // Vecchio abbuono in lire
 | 
						||
  if (in_valuta())
 | 
						||
  {
 | 
						||
    const TString4 codval = sum.codice_valuta();
 | 
						||
    TCurrency cur(old_abb.valore(), codval, sum.get_real(PART_CAMBIO));
 | 
						||
    cur.change_to_firm_val();
 | 
						||
    old_abb.valore() = cur.get_num();
 | 
						||
  }
 | 
						||
  
 | 
						||
  old_diffcam = calcola_differenza_cambio(nrigp, false);
 | 
						||
  
 | 
						||
  if (in_valuta() && !valuta.in_euro())
 | 
						||
    valuta.put(sum);
 | 
						||
  
 | 
						||
  row(nrigp) = new_pag;
 | 
						||
  
 | 
						||
  TImporto new_abbuono;
 | 
						||
  new_ap = calcola_abbuono(nrigp, new_abbuono, update); // Calcolo abbuono in valuta
 | 
						||
  
 | 
						||
  new_abb = new_abbuono;                                // Calcola nuovo abbuono in euro
 | 
						||
  if (in_valuta() && !new_abb.is_zero())
 | 
						||
  {
 | 
						||
    const TString4 codval = sum.codice_valuta();
 | 
						||
    TCurrency cur(new_abb.valore(), codval, sum.get_real(PART_CAMBIO));
 | 
						||
    cur.change_to_firm_val();
 | 
						||
    new_abb.valore() = cur.get_num();
 | 
						||
  }  
 | 
						||
 | 
						||
  new_diffcam = calcola_differenza_cambio(nrigp, update);
 | 
						||
  
 | 
						||
  sum.update(old_abbuono, new_abbuono, PART_SEZABB, PART_ABBUONI);
 | 
						||
  sum.update(old_diffcam, new_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);
 | 
						||
  sum.update(old_pag, new_pag, PART_RITSOC);
 | 
						||
  
 | 
						||
  const bool empty = new_pag.get_char(PAGSCA_ACCSAL) != 'S' && 
 | 
						||
                     new_pag.get_real(PAGSCA_IMPORTO).is_zero() &&
 | 
						||
                     new_pag.get_real(PAGSCA_RITENUTE).is_zero() &&
 | 
						||
                     new_pag.get_real(PAGSCA_RITSOC).is_zero();
 | 
						||
  if (empty)
 | 
						||
    rows_array().destroy_row(nrigp);
 | 
						||
  
 | 
						||
  // Aggiorna flags di chiusura          
 | 
						||
  chiusa(true);          
 | 
						||
  partita().chiusa(true);             
 | 
						||
  
 | 
						||
  return empty;
 | 
						||
}
 | 
						||
 | 
						||
bool TRiga_scadenze::esistono_abbuoni_diffcam() const
 | 
						||
{           
 | 
						||
/* Prima dellla Pharmatex le differenze cambi potevano aversi solo con pagamenti a saldo
 | 
						||
  bool ad = false;
 | 
						||
  for (int p = last(); p > 0 && !ad; p = pred(p))
 | 
						||
  {
 | 
						||
    const TRectype& pag = row(p);
 | 
						||
    if (pag.get_char(PAGSCA_ACCSAL) == 'S')
 | 
						||
    {
 | 
						||
      if (!pag.get_real(PAGSCA_ABBUONI).is_zero() || 
 | 
						||
          !pag.get_real(PAGSCA_DIFFCAM).is_zero())
 | 
						||
      {
 | 
						||
        ad = true;
 | 
						||
        break;
 | 
						||
      }  
 | 
						||
    }  
 | 
						||
  }    
 | 
						||
  return ad;
 | 
						||
*/
 | 
						||
  for (int p = last(); p > 0; p = pred(p))
 | 
						||
  {
 | 
						||
    const TRectype& pag = row(p);
 | 
						||
    if (!pag.get_real(PAGSCA_ABBUONI).is_zero() || !pag.get_real(PAGSCA_DIFFCAM).is_zero())
 | 
						||
      return true;
 | 
						||
  }    
 | 
						||
  return false;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TRiga_scadenze::elimina_pagamento(int p)
 | 
						||
{
 | 
						||
  TRectype old_pag(row(p));
 | 
						||
  old_pag.put(PAGSCA_ACCSAL, "A");
 | 
						||
  old_pag.zero(PAGSCA_IMPORTO);
 | 
						||
  old_pag.zero(PAGSCA_IMPORTOVAL);
 | 
						||
  old_pag.zero(PAGSCA_RITENUTE);
 | 
						||
  old_pag.zero(PAGSCA_RITSOC);
 | 
						||
  TValuta val;
 | 
						||
  return partita().modifica_pagamento(old_pag, val, true);
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TRiga_partite
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TRiga_partite::TRiga_partite(TPartita* game)
 | 
						||
: TTree_rectype(LF_PARTITE, LF_SCADENZE, SCAD_NRATA), _partita(game)
 | 
						||
{
 | 
						||
  CHECK(_partita, "Partita nulla");
 | 
						||
  TRiga_scadenze* scad = new TRiga_scadenze(this);
 | 
						||
  copy_key_to_row(*this);
 | 
						||
  rows_array().set_key(scad);               // Altrimenti le righe sarebbero dei TRectype!
 | 
						||
}  
 | 
						||
 | 
						||
TRiga_partite::TRiga_partite(const TRiga_partite& r)
 | 
						||
: TTree_rectype(r), _partita(r._partita)
 | 
						||
{
 | 
						||
  update_rigaptr();
 | 
						||
}  
 | 
						||
 | 
						||
TRiga_partite::~TRiga_partite()
 | 
						||
{}
 | 
						||
 | 
						||
void TRiga_partite::update_rigaptr()
 | 
						||
{
 | 
						||
  for (int i = rate(); i >= 0; i--)
 | 
						||
  {
 | 
						||
    TRiga_scadenze& scad = i == 0 ? (TRiga_scadenze&)rows_array().key() : rata(i);
 | 
						||
    scad._riga = this;
 | 
						||
  }  
 | 
						||
}
 | 
						||
 | 
						||
TRiga_scadenze& TRiga_partite::new_row(int r)
 | 
						||
{               
 | 
						||
  TRiga_scadenze& scad = (TRiga_scadenze&)TTree_rectype::new_row(r); 
 | 
						||
  scad._riga = this;
 | 
						||
  return scad;
 | 
						||
}   
 | 
						||
 | 
						||
// Elimina la rata r ed i suoi pagamenti, se r < 1 allora elimina tutte le rate
 | 
						||
// Certified 99%
 | 
						||
void TRiga_partite::elimina_rata(int r)
 | 
						||
{
 | 
						||
  const int from = r <= 0 ? 1 : r;
 | 
						||
  const int to   = r <= 0 ? rate() : r;
 | 
						||
  for (r = to; r >= from; r--)           // E' necessario andare all'indietro perche'
 | 
						||
  {                                      // il metodo rate() funzioni sempre correttamente
 | 
						||
    TRiga_scadenze& scad = rata(r);
 | 
						||
    for (int p = scad.last(); p > 0; p = scad.pred(p))
 | 
						||
      scad.elimina_pagamento(p);         // Elimina pagamento
 | 
						||
    rows_array().destroy_row(r);         // Elimina rata
 | 
						||
  }           
 | 
						||
}
 | 
						||
 | 
						||
// Ritorna il numero dell'ultima rata pagata o 0 se non ce ne sono
 | 
						||
// Certified 100%
 | 
						||
int TRiga_partite::ultima_ratapagata() const
 | 
						||
{
 | 
						||
	int r;
 | 
						||
	
 | 
						||
  for (r = rate(); r > 0; r--)
 | 
						||
    if (rata(r).chiusa()) break;
 | 
						||
  return r;
 | 
						||
}
 | 
						||
 | 
						||
// Ritorna il tipo movimento di una riga di partita
 | 
						||
// Certified 100%
 | 
						||
tipo_movimento TRiga_partite::tipo() const 
 | 
						||
{ 
 | 
						||
  tipo_movimento tm = (tipo_movimento)(get_int(PART_TIPOMOV)); 
 | 
						||
 | 
						||
  if (tm == tm_nessuno)
 | 
						||
  {
 | 
						||
    // Tento salvataggioin extremis
 | 
						||
    const int nriga = get_int(PART_NRIGA);
 | 
						||
    if (nriga == 1 && get_date(PART_DATADOC).ok())
 | 
						||
      tm = tm_fattura; else
 | 
						||
    if (nriga > 1 && get_date(PART_DATAPAG).ok())
 | 
						||
      tm = tm_pagamento; 
 | 
						||
#ifdef DBG  
 | 
						||
    if (tm == tm_nessuno && nriga != TPartita::UNASSIGNED)
 | 
						||
      yesnofatal_box("Riga partite con un tipo losco.");
 | 
						||
#endif  
 | 
						||
  }
 | 
						||
 
 | 
						||
  return tm;
 | 
						||
}
 | 
						||
 | 
						||
tipo_pagamento TRiga_partite::tipo_pag() const 
 | 
						||
{
 | 
						||
  const tipo_pagamento tp = (tipo_pagamento)get_int(PART_TIPOPAG);
 | 
						||
  return tp;
 | 
						||
}
 | 
						||
 | 
						||
// Calcola il segno delle ritenute sociali in base alla causale
 | 
						||
char TRiga_partite::sezione_ritsoc() const
 | 
						||
{
 | 
						||
  TString16 key; key << get(PART_CODCAUS) << '|' << RIGA_PAG_RITSOC;  // Riga ritenute sociali
 | 
						||
  const char sez_cau = cache().get(LF_RCAUSALI, key, RCA_SEZIONE)[0];
 | 
						||
  const char sez_rit = sez_cau > ' ' ? (sez_cau == 'D' ? 'A' : 'D') : sezione();
 | 
						||
  return sez_rit;
 | 
						||
}
 | 
						||
 | 
						||
// Legge le rate relative ad una riga di fattura
 | 
						||
// Certified 99%
 | 
						||
int TRiga_partite::read(TBaseisamfile& f, word op, word lock)
 | 
						||
{                  
 | 
						||
  int err = TRectype::read(f, op, lock);
 | 
						||
  if (err == NOERR && is_fattura())
 | 
						||
  {
 | 
						||
    TRiga_scadenze* s = new TRiga_scadenze(this);             
 | 
						||
    err = rows_array().read(s);                // Deve esistere almento una scadenza
 | 
						||
    update_rigaptr();
 | 
						||
  }  
 | 
						||
  else 
 | 
						||
    rows_array().destroy_rows();
 | 
						||
  return err; 
 | 
						||
}
 | 
						||
 | 
						||
// Registra una riga e le sue eventuali rate
 | 
						||
// Certified 100%
 | 
						||
int TRiga_partite::write(TBaseisamfile& f) const
 | 
						||
{ 
 | 
						||
  const int err = is_fattura() ? TTree_rectype::write(f) : TRectype::write(f);
 | 
						||
  return err;
 | 
						||
}
 | 
						||
 | 
						||
// Aggiorna una riga e le sue eventuali rate
 | 
						||
// Certified 100%
 | 
						||
int TRiga_partite::rewrite(TBaseisamfile& f) const
 | 
						||
{
 | 
						||
  int err = NOERR;
 | 
						||
  if (is_fattura())
 | 
						||
    err = TTree_rectype::rewrite(f);
 | 
						||
  else
 | 
						||
  {
 | 
						||
    err = TRectype::rewrite(f);
 | 
						||
    if (err == NOERR && rows_array().rows() > 0) // Elimina rate se riga trasformata da fattura a nota di credito
 | 
						||
      rows_array().remove();
 | 
						||
  }
 | 
						||
  return err;
 | 
						||
}
 | 
						||
 | 
						||
// Elimina una riga e le sue eventuali rate
 | 
						||
// Certified 100%
 | 
						||
int TRiga_partite::remove(TBaseisamfile& f) const
 | 
						||
{
 | 
						||
  const int err = is_fattura() ?  TTree_rectype::remove(f) : TRectype::remove(f);
 | 
						||
  return err;
 | 
						||
}
 | 
						||
 | 
						||
// Ritorna l'indice dell'ultimo pagamento della rata r o 0 se non ce ne sono
 | 
						||
// Certified 100%
 | 
						||
int TRiga_partite::ultimo_pagamento(int r) const
 | 
						||
{           
 | 
						||
  const TRiga_scadenze& s = rata(r);
 | 
						||
  return s.last();
 | 
						||
}
 | 
						||
 | 
						||
// Aggiorna il campo field contenente un totale sottraendo il corrispondente valore di
 | 
						||
// un record prima (vec) e dopo la sua modifica (nuo)
 | 
						||
// Certified 100%
 | 
						||
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;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// Cerca una rata con abbuoni o differenze cambio
 | 
						||
// Certified 99%
 | 
						||
int TRiga_partite::ultima_rata_con_abbuoni_diffcam() const
 | 
						||
{  
 | 
						||
	int s = 0;    
 | 
						||
  for (s = rate(); s > 0; s--)
 | 
						||
  {
 | 
						||
    const TRiga_scadenze& scad = rata(s);
 | 
						||
    if (scad.esistono_abbuoni_diffcam())
 | 
						||
      break;
 | 
						||
  }           
 | 
						||
  return s;
 | 
						||
}
 | 
						||
 | 
						||
// Determina il codice valuta
 | 
						||
const TString& TRiga_partite::codice_valuta() const 
 | 
						||
{
 | 
						||
  return get(PART_CODVAL);
 | 
						||
}
 | 
						||
 | 
						||
// Determina se una riga e' in valuta in base al codice valuta
 | 
						||
bool TRiga_partite::in_valuta() const 
 | 
						||
{
 | 
						||
  return !is_firm_value(codice_valuta());
 | 
						||
}
 | 
						||
 | 
						||
// Calcola l'importo in lire o in valuta su di una riga di partita
 | 
						||
// E' possibile considerare o meno IMPORTO, ABBUONI e DIFFCAM
 | 
						||
TImporto TRiga_partite::importo(bool valuta, int mode) const
 | 
						||
{      
 | 
						||
  CHECKD(mode > 0x0 && mode <= 0xF, "Bad importo mode ", mode);
 | 
						||
  const bool in_euro = !in_valuta();    // Partita in Euro
 | 
						||
  if (valuta && in_euro)
 | 
						||
    valuta = false;
 | 
						||
            
 | 
						||
  TImporto i;          
 | 
						||
  if (mode & 0x1)          
 | 
						||
  {
 | 
						||
    const char* const field = valuta ? PART_IMPORTOVAL : PART_IMPORTO;
 | 
						||
    i.set(sezione(), get_real(field));
 | 
						||
  }
 | 
						||
 | 
						||
  if (!is_fattura() && (mode & 0xE))   // Ci sono abbuoni, differenze cambio o ritenute?
 | 
						||
  { 
 | 
						||
    if (valuta)                        // Desidero gli abbuoni in valuta
 | 
						||
    {
 | 
						||
      if (mode & 0x2)
 | 
						||
      {
 | 
						||
        const TImporto abbuoni(get_char(PART_SEZABB), get_real(PART_ABBUONI));
 | 
						||
        i += abbuoni;
 | 
						||
      }                                
 | 
						||
      // In valuta ignoro completamente le differenze cambio
 | 
						||
    }
 | 
						||
    else                               // Desidero gli abbuoni in lire
 | 
						||
    {
 | 
						||
      if (in_euro && (mode & 0x8))     // Ritenute Fiscali e/o sociali
 | 
						||
      {
 | 
						||
        // Ritenute Fiscali
 | 
						||
        i.valore() += get_real(PART_RITENUTE);
 | 
						||
        // Ritenute Sociali
 | 
						||
        if (sezione() == sezione_ritsoc())
 | 
						||
          i.valore() += get_real(PART_RITSOC);
 | 
						||
        else
 | 
						||
          i.valore() -= get_real(PART_RITSOC);
 | 
						||
      }
 | 
						||
      
 | 
						||
      if (mode & 0x2)
 | 
						||
      {
 | 
						||
        TImporto abbuoni(get_char(PART_SEZABB), get_real(PART_ABBUONI));
 | 
						||
        if (!in_euro)  // Converto in lire gli abbuoni che sono memorizzati in valuta 
 | 
						||
        {
 | 
						||
          const real cambio(get(PART_CAMBIO));
 | 
						||
          TCurrency cur(abbuoni.valore(), codice_valuta(), cambio);
 | 
						||
          cur.change_to_firm_val();
 | 
						||
          abbuoni.valore() = cur.get_num();
 | 
						||
        }  
 | 
						||
        i += abbuoni;
 | 
						||
      }
 | 
						||
      
 | 
						||
      if (!in_euro && (mode & 0x4))  // Se ci sono e desidero le differenze cambio
 | 
						||
      {
 | 
						||
        const TImporto diffcam(get_char(PART_SEZDIFCAM), get_real(PART_DIFFCAM));
 | 
						||
        i += diffcam;
 | 
						||
        i.valore().round(TCurrency::get_firm_dec());
 | 
						||
      }  
 | 
						||
    }  
 | 
						||
  }
 | 
						||
 | 
						||
  return i;
 | 
						||
}
 | 
						||
 | 
						||
// Calcola l'esposto e l'esposto SBF 
 | 
						||
TImporto TRiga_partite::esposto(bool valuta, const TDate& data_scad, const TDate& data_rischio, bool & sbf) const
 | 
						||
{        
 | 
						||
  TImporto esposto;
 | 
						||
  
 | 
						||
  sbf = false;
 | 
						||
  const int nrigp = get_int(PART_NRIGA);
 | 
						||
  const char sez = sezione();
 | 
						||
  const int  last = _partita->last();     
 | 
						||
  const TDate datapag(get_date(PART_DATAPAG));
 | 
						||
  const bool rischio = data_scad != data_rischio; 
 | 
						||
  bool found_pag = false;
 | 
						||
  
 | 
						||
  for (int row = last; row > 0; row = _partita->pred(row))      
 | 
						||
  {     
 | 
						||
    const TRiga_partite & riga = _partita->riga(row);
 | 
						||
    if (riga.is_fattura())
 | 
						||
    {                             
 | 
						||
      const int lastr = riga.rate();
 | 
						||
      for (int rata = lastr; rata > 0; rata--)
 | 
						||
      {
 | 
						||
        const TRiga_scadenze& scad = riga.rata(rata);
 | 
						||
        if (scad.exist(nrigp))
 | 
						||
        {                                     
 | 
						||
          const TRectype & pag = scad.row(nrigp);
 | 
						||
          const TImporto imp(sez, pag.get_real(valuta ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO));
 | 
						||
          TDate data(scad.get(SCAD_DATASCAD));
 | 
						||
          const int lasts = scad.last();
 | 
						||
          
 | 
						||
          found_pag  = true;
 | 
						||
          for (int p = scad.first(); p <= lasts; p = scad.succ(p)) 
 | 
						||
          {            
 | 
						||
            if (p != nrigp)
 | 
						||
            {             
 | 
						||
              const TRiga_partite & prow = partita().riga(p);
 | 
						||
              const tipo_pagamento tp = prow.tipo_pag();
 | 
						||
 | 
						||
							if (tp >= tp_tratta && tp <= tp_rid)
 | 
						||
              {
 | 
						||
                const TDate dataprow(prow.get(PART_DATAPAG));
 | 
						||
                if (dataprow < datapag)
 | 
						||
                {
 | 
						||
                  data = datapag;
 | 
						||
                  break;
 | 
						||
                }  
 | 
						||
              }
 | 
						||
            }
 | 
						||
          } 
 | 
						||
          if (rischio && data > data_rischio && data <= data_scad)
 | 
						||
          {
 | 
						||
            esposto += imp; 
 | 
						||
            sbf = true;
 | 
						||
          }
 | 
						||
          else
 | 
						||
            if (data > data_scad)
 | 
						||
              esposto += imp;
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }       
 | 
						||
  if (!found_pag)
 | 
						||
  {        
 | 
						||
    const TImporto imp(importo(valuta, 0x1));
 | 
						||
    if (rischio && datapag > data_rischio && datapag <= data_scad)
 | 
						||
    {
 | 
						||
      esposto += imp; 
 | 
						||
      sbf = true;
 | 
						||
    }
 | 
						||
    else
 | 
						||
      if (datapag > data_scad)
 | 
						||
        esposto += imp;
 | 
						||
  }
 | 
						||
  return esposto;    
 | 
						||
} 
 | 
						||
 
 | 
						||
/*
 | 
						||
TImporto TRiga_partite::calcola_pagato_al(bool valuta,const TDate& al, const TDate & data_scaduto, const TDate& data_rischio, int mode) const
 | 
						||
{
 | 
						||
  TImporto pagato;
 | 
						||
    
 | 
						||
  if (is_fattura())
 | 
						||
  {
 | 
						||
		const int nrigp = get_int(PART_NRIGA);
 | 
						||
		const char sez = sezione();
 | 
						||
		const bool rischio = data_scaduto != data_rischio; 
 | 
						||
		const int lastr = rate();
 | 
						||
		for (int r = lastr; r > 0; r--)
 | 
						||
		{
 | 
						||
			const TRiga_scadenze& scad = rata(r);
 | 
						||
			const TImporto pag = scad.importo_pagato_al(valuta, al, mode);
 | 
						||
			pagato += pag;
 | 
						||
			if (rischio && !pag.is_zero())
 | 
						||
			{
 | 
						||
				bool sbf = false;
 | 
						||
				pagato -= scad.esposto_al(valuta, al, data_scaduto, data_rischio, sbf);
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
  }  
 | 
						||
  return pagato;
 | 
						||
}
 | 
						||
*/
 | 
						||
 | 
						||
TImporto TRiga_partite::importo_pagsca(const TRectype& pag, bool val, int mode) const
 | 
						||
{ return partita().importo_pagsca(pag, val, mode); }
 | 
						||
 | 
						||
int TRiga_partite::calcola_pagato_periodo(const TDate& dal, const TDate& al, TImporto& pg, TImporto& nc, TPointer_array* pagsca) const
 | 
						||
{
 | 
						||
  int flag = 0;
 | 
						||
  if (!is_fattura())
 | 
						||
    return flag;
 | 
						||
 | 
						||
  TPointer_array pags;
 | 
						||
 | 
						||
  const int lastr = rate();
 | 
						||
  for (int r = lastr; r > 0; r--)
 | 
						||
  {	
 | 
						||
		const TRiga_scadenze& scad = rata(r);
 | 
						||
    for (int p = scad.last(); p > 0; p = scad.pred(p))
 | 
						||
    {
 | 
						||
      const TRectype& pag = scad.row(p);                    // Riga pagamento
 | 
						||
      const TRiga_partite& sum = partita().riga(p);         // Riga partite
 | 
						||
		  TDate datapag = sum.get_date(PART_DATAPAG);
 | 
						||
      if (!datapag.ok())
 | 
						||
        datapag = sum.get_date(PART_DATADOC);
 | 
						||
      if (!datapag.ok())
 | 
						||
        datapag = sum.get_date(PART_DATAREG);
 | 
						||
		  if ((!dal.ok() || datapag >= dal) && (!al.ok() || datapag <= al))
 | 
						||
        pags.add((TRectype*)&pag);
 | 
						||
    }  
 | 
						||
  }
 | 
						||
 | 
						||
  // Cerco di gestire anche i non assegnati sulla unica fattura di una partita 
 | 
						||
  const TRecord_array& unas = partita().unassigned();
 | 
						||
  if (unas.rows() > 0)
 | 
						||
  {
 | 
						||
    int fatture = 0;
 | 
						||
    for (int r = partita().last(); r > 0 && fatture < 2; r = partita().pred(r))
 | 
						||
    {
 | 
						||
      if (partita().riga(r).tipo() == tm_fattura)
 | 
						||
        fatture++;
 | 
						||
    }
 | 
						||
    if (fatture == 1)
 | 
						||
    {
 | 
						||
      for(int r = unas.last_row(); r > 0; r = unas.pred_row(r))
 | 
						||
      {
 | 
						||
        const TRectype& pag = unas.row(r);
 | 
						||
        const TRiga_partite& sum = partita().riga(r);
 | 
						||
  		  TDate datapag = sum.get_date(PART_DATAPAG);
 | 
						||
        if (!datapag.ok())
 | 
						||
          datapag = sum.get_date(PART_DATADOC);
 | 
						||
        if (!datapag.ok())
 | 
						||
          datapag = sum.get_date(PART_DATAREG);
 | 
						||
	  	  if ((!dal.ok() || datapag >= dal) && (!al.ok() || datapag <= al))
 | 
						||
          pags.add((TRectype*)&pag);
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  // Ordino i pagamenti per DATAPAG/NRATA/NRIGP
 | 
						||
  for (int i = 0; i < pags.items(); i++)
 | 
						||
  {
 | 
						||
    for (int j = i+1; j < pags.items(); j++)
 | 
						||
    {
 | 
						||
      const TRectype& pi = *(TRectype*)pags.objptr(i);
 | 
						||
      const TRectype& pj = *(TRectype*)pags.objptr(j);
 | 
						||
      const int ni = pi.get_int(PAGSCA_NRIGP);
 | 
						||
      const int nj = pj.get_int(PAGSCA_NRIGP);
 | 
						||
      const TRiga_partite& si = partita().riga(ni);
 | 
						||
      const TRiga_partite& sj = partita().riga(nj);
 | 
						||
      const TDate di = si.get(PART_DATAPAG);
 | 
						||
      const TDate dj = sj.get(PART_DATAPAG);
 | 
						||
      long cmp = di - dj;
 | 
						||
      if (cmp == 0)
 | 
						||
      {
 | 
						||
        const int ri = pi.get_int(PAGSCA_NRATA);
 | 
						||
        const int rj = pj.get_int(PAGSCA_NRATA);
 | 
						||
        cmp = ri - rj;
 | 
						||
        if (cmp == 0)
 | 
						||
          cmp = ni - nj;
 | 
						||
      }
 | 
						||
      if (cmp > 0)
 | 
						||
        pags.swap(i, j);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  FOR_EACH_ARRAY_ITEM(pags, p, obj)
 | 
						||
  {
 | 
						||
    const TRectype& pag = *(TRectype*)obj;
 | 
						||
    const TRiga_partite& sum = partita().riga(pag.get_int(PAGSCA_NRIGP));
 | 
						||
    const tipo_movimento tm = sum.tipo();
 | 
						||
    const TImporto imp = importo_pagsca(pag);
 | 
						||
    if (tm == tm_nota_credito)
 | 
						||
    {
 | 
						||
      nc += imp;
 | 
						||
      flag |= 2;
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      pg += imp;
 | 
						||
      flag |= 1;
 | 
						||
    }
 | 
						||
    if (pagsca != NULL)
 | 
						||
      pagsca->add(obj);
 | 
						||
  }
 | 
						||
  
 | 
						||
  return flag;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TRiga_partite_array
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
// Filtra le righe saldo per non creare array di 9999 elementi nulli!
 | 
						||
int TRiga_partite_array::add_row(TRectype* row)
 | 
						||
{
 | 
						||
  if (row == NULL)
 | 
						||
    return -1;
 | 
						||
  if (row->get_int(PART_NRIGA) >= TPartita::UNASSIGNED)
 | 
						||
  {
 | 
						||
    delete row;
 | 
						||
    return -1;
 | 
						||
  }
 | 
						||
  return TRecord_array::add_row(row);
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TPartita
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
char TPartita::_cli_align = ' ';
 | 
						||
char TPartita::_for_align = ' ';
 | 
						||
bool TPartita::_diffcam_always = false;
 | 
						||
 | 
						||
TPartita::TPartita(const TBill& clifo, int anno, const char* num) 
 | 
						||
        : _unassigned(LF_PAGSCA, PAGSCA_NRIGP), _align(' ')
 | 
						||
{ read(clifo, anno, num); }                    
 | 
						||
 | 
						||
TPartita::TPartita(const TRectype& r)
 | 
						||
        : _unassigned(LF_PAGSCA, PAGSCA_NRIGP), _align(' ')
 | 
						||
{
 | 
						||
  TBill clifo; clifo.get(r);
 | 
						||
  if (clifo.gruppo() == 0 && r.num() == LF_PARTITE)
 | 
						||
    clifo.set(r.get_int(PART_GRUPPOCL), r.get_int(PART_CONTOCL), clifo.sottoconto(), clifo.tipo());
 | 
						||
  const int anno = r.get_int(PART_ANNO);
 | 
						||
  const TString8 num(r.get(PART_NUMPART));
 | 
						||
  read(clifo, anno, num); 
 | 
						||
}
 | 
						||
 | 
						||
TPartita::~TPartita()
 | 
						||
{ }
 | 
						||
 | 
						||
const char* TPartita::build_key(TString& key) const
 | 
						||
{
 | 
						||
  if (_conto.tipo() > ' ')
 | 
						||
    key.format("%c%3d%3d%6ld%4d%*s", _conto.tipo(), 0, 0, _conto.sottoconto(), 
 | 
						||
               _anno, NUMLEN, (const char*)_num);
 | 
						||
  else
 | 
						||
    key.format("%c%3d%3d%6ld%4d%*s", 
 | 
						||
               _conto.tipo(), _conto.gruppo(), _conto.conto(), _conto.sottoconto(), 
 | 
						||
               _anno, NUMLEN, (const char*)_num);
 | 
						||
  return key;               
 | 
						||
}
 | 
						||
 | 
						||
int TPartita::compare(const TSortable& s) const
 | 
						||
{
 | 
						||
  TString80 key; build_key(key);
 | 
						||
  const TPartita& p = (const TPartita&)s;             
 | 
						||
  TString80 par; p.build_key(par);
 | 
						||
  return strcmp(key, par);
 | 
						||
}
 | 
						||
 | 
						||
void TPartita::carica_allineamento()
 | 
						||
{
 | 
						||
  TConfig cd(CONFIG_DITTA, "cg");
 | 
						||
  _cli_align = cd.get_bool("NrCliDx") ? 'R' : 'L';
 | 
						||
  _for_align = cd.get_bool("NrForDx") ? 'R' : 'L';
 | 
						||
 | 
						||
  // Nel nuovo saldaconto si possono rilevare le differenze cambi su pagamenti non a saldo
 | 
						||
  _diffcam_always = cd.get_bool("EasySal") && cd.get_bool("DiffCamAlways") && xvt_vobj_get_attr(NULL_WIN, ATTR_APPL_VERSION_YEAR) > 2091;
 | 
						||
}
 | 
						||
 | 
						||
char TPartita::allineamento_richiesto(char tipocf)
 | 
						||
{
 | 
						||
  // Controlla se e' gia' stato caricato l'allineamento
 | 
						||
  if (_cli_align <= ' ' || _for_align <= ' ')
 | 
						||
    carica_allineamento();
 | 
						||
  
 | 
						||
  char all;
 | 
						||
  switch (tipocf)
 | 
						||
  {          
 | 
						||
    case 'C': all = _cli_align; break;
 | 
						||
    case 'F': all = _for_align; break;
 | 
						||
    default : all = (_cli_align == _for_align) ? _cli_align : 'L'; break;
 | 
						||
  }
 | 
						||
  return all;
 | 
						||
}
 | 
						||
 | 
						||
bool TPartita::rileva_sempre_differenze_cambi()
 | 
						||
{
 | 
						||
  if (_cli_align <= ' ' || _for_align <= ' ') // Carica il flag insieme agli allineamnti
 | 
						||
     carica_allineamento();
 | 
						||
  return _diffcam_always;
 | 
						||
}
 | 
						||
 | 
						||
// Ritorna l'allineamento corrente del numero partita
 | 
						||
// L = Sinistra, R = Destra, ' ' = indeterminato
 | 
						||
char TPartita::allineamento_corrente() const
 | 
						||
{
 | 
						||
  const TString& n = numero();
 | 
						||
  
 | 
						||
  char all = n[0] == ' ' ? 'R' : 'L';
 | 
						||
  if (all == 'L' && n.len() == NUMLEN && n[NUMLEN-1] != ' ')
 | 
						||
    all = ' ';
 | 
						||
  return all;  
 | 
						||
}
 | 
						||
 | 
						||
void TPartita::allinea(char all)
 | 
						||
{                       
 | 
						||
  if (all <= ' ')
 | 
						||
    all = allineamento_richiesto(conto().tipo());
 | 
						||
 | 
						||
  if (all == 'R')
 | 
						||
    _num.right_just(NUMLEN);
 | 
						||
  else
 | 
						||
    _num.trim();
 | 
						||
       
 | 
						||
  if (ok())
 | 
						||
  {  
 | 
						||
    _part.renum_key(PART_NUMPART, _num);
 | 
						||
    _unassigned.renum_key(PAGSCA_NUMPART, _num);
 | 
						||
  }  
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TPartita::is_on_file() const
 | 
						||
{
 | 
						||
  TLocalisamfile partite(LF_PARTITE);   
 | 
						||
  TRectype& part = partite.curr();
 | 
						||
  part.zero();
 | 
						||
  part.put(PART_TIPOCF, _conto.tipo());
 | 
						||
  if (_conto.tipo() <= ' ')
 | 
						||
  { 
 | 
						||
    part.put(PART_GRUPPO, _conto.gruppo());
 | 
						||
    part.put(PART_CONTO,  _conto.conto());
 | 
						||
  }
 | 
						||
  part.put(PART_SOTTOCONTO, _conto.sottoconto());
 | 
						||
  part.put(PART_ANNO, _anno);
 | 
						||
  part.put(PART_NUMPART, _num);
 | 
						||
  
 | 
						||
  const TRectype filter(part);              
 | 
						||
    
 | 
						||
  // Cerca la partita usando l'allineamento richiesto dall'utente
 | 
						||
  const bool found = partite.read(_isgteq) == NOERR && part.compare_key(filter, 1, 1) == 0;
 | 
						||
  return found;
 | 
						||
}
 | 
						||
 | 
						||
// Costruisce le righe della partita
 | 
						||
bool TPartita::read(const TBill& clifo, int year, const char* num)
 | 
						||
{
 | 
						||
  _conto = clifo;
 | 
						||
  _anno  = year;
 | 
						||
  _num   = num;
 | 
						||
  
 | 
						||
  if (allineamento_corrente() > ' ')
 | 
						||
  {   
 | 
						||
    // Cerca la partita usando l'allineamento richiesto dall'utente
 | 
						||
    if (!is_on_file())
 | 
						||
    {                     
 | 
						||
      // Se non la trova inverte l'allineamento
 | 
						||
      if (allineamento_corrente() == 'R')
 | 
						||
        _num.trim();
 | 
						||
      else  
 | 
						||
        _num.right_just(NUMLEN);
 | 
						||
      
 | 
						||
      // Riprova a cercarla col nuovo allineamento
 | 
						||
      if (!is_on_file())
 | 
						||
        allinea();                                // Non esite: e' una nuova partita!
 | 
						||
    }
 | 
						||
  }
 | 
						||
  else
 | 
						||
    _num.trim();
 | 
						||
  _align = allineamento_corrente();
 | 
						||
  
 | 
						||
  TRiga_partite* partita = new TRiga_partite(this);        // Record campione della partita
 | 
						||
  TString16 str;
 | 
						||
  str << clifo.tipo();
 | 
						||
  partita->renum_key(PART_TIPOCF, str);                    // Tipo clifo
 | 
						||
  if (clifo.tipo() <= ' ')
 | 
						||
  {                                                        
 | 
						||
    str.cut(0); str << clifo.gruppo();
 | 
						||
    partita->renum_key(PART_GRUPPO, str);                  // Scrivi gruppo e conto solamente
 | 
						||
    str.cut(0); str << clifo.conto();                      // nei conti normali (no clifo)
 | 
						||
    partita->renum_key(PART_CONTO, str);                   
 | 
						||
  }                                   
 | 
						||
  str.cut(0); str << clifo.sottoconto();
 | 
						||
  partita->renum_key(PART_SOTTOCONTO, str);                // Sottoconto o codice clifo
 | 
						||
  str.cut(0); str << _anno;
 | 
						||
  partita->renum_key(PART_ANNO, str);                      // Anno partita
 | 
						||
  partita->renum_key(PART_NUMPART, _num);                  // Numero partita
 | 
						||
  _part.read(partita);
 | 
						||
  
 | 
						||
  if (_part.exist(UNASSIGNED))
 | 
						||
    _part.destroy_row(UNASSIGNED);                         // Elimina riga saldo;
 | 
						||
 | 
						||
  TRectype* unas = new TRectype(LF_PAGSCA);                // Record pagamenti non assegnati
 | 
						||
  partita->copy_key_to_row(*unas);
 | 
						||
  unas->put(PART_NRIGA, (int)UNASSIGNED);                           
 | 
						||
  unas->put(SCAD_NRATA, (int)UNASSIGNED);
 | 
						||
  _unassigned.read(unas);
 | 
						||
  if (_unassigned.rows() > 0 &&_part.rows() <= 0)          // non assegnati orfani!
 | 
						||
    _unassigned.destroy_rows();
 | 
						||
  
 | 
						||
  return ok();
 | 
						||
}
 | 
						||
 | 
						||
bool TPartita::reread()
 | 
						||
{       
 | 
						||
  return read(conto(), anno(), numero());
 | 
						||
} 
 | 
						||
 | 
						||
int TPartita::write_saldo(bool re, TRectype* rec) const
 | 
						||
{
 | 
						||
  TImporto saldo, doc, pag, imp;
 | 
						||
  calcola_saldo(saldo, doc, pag, imp);
 | 
						||
  
 | 
						||
  TLocalisamfile part(LF_PARTITE);
 | 
						||
  TRectype& sld = part.curr();
 | 
						||
 | 
						||
  sld = _part.key();                             // Copia conto, anno e numero partita
 | 
						||
  sld.put(PART_NRIGA,     (int)UNASSIGNED);      // Assegna magic line number
 | 
						||
  sld.put(PART_SEZ,       saldo.sezione());      // Sezione saldo
 | 
						||
  sld.put(PART_IMPORTO,   saldo.valore());       // Saldo
 | 
						||
  sld.put(PART_SEZABB,    doc.sezione());        // Sezione documenti
 | 
						||
  sld.put(PART_ABBUONI,   doc.valore());         // Documenti
 | 
						||
  sld.put(PART_SEZDIFCAM, pag.sezione());        // Sezione pagamenti
 | 
						||
  sld.put(PART_DIFFCAM,   pag.valore());         // Pagamenti
 | 
						||
  sld.put(PART_REG,       imp.sezione());        // Sezione altri importi
 | 
						||
  sld.put(PART_IMPOSTA,   imp.valore());         // Altri importi
 | 
						||
  
 | 
						||
  int r = prima_fattura();                       // Cerca la prima fattura ...
 | 
						||
  if (r <= 0) r = first();                       // ... o la prima riga valida
 | 
						||
  const TRiga_partite& row = riga(r);
 | 
						||
 | 
						||
  sld.put(PART_NUMDOC, row.get(PART_NUMDOC));    // Copia estremi documento
 | 
						||
  sld.put(PART_DATADOC, row.get(PART_DATADOC));
 | 
						||
  sld.put(PART_DESCR, row.get(PART_DESCR));
 | 
						||
  
 | 
						||
  const TValuta valuta(row);                     // Copia la valuta
 | 
						||
  valuta.put(sld);
 | 
						||
  
 | 
						||
  // sld.put(PART_CHIUSA, row.get(PART_CHIUSA));    // Copia il flag di chiusura
 | 
						||
  sld.put(PART_CHIUSA, chiusa(true));
 | 
						||
  
 | 
						||
  if (rec != NULL)
 | 
						||
    *rec = sld;
 | 
						||
  
 | 
						||
  // Scrittura del record di saldo
 | 
						||
  int err = re ? part.rewrite() : part.write();
 | 
						||
  if (err != NOERR)
 | 
						||
    err = re ? part.write() : part.rewrite();
 | 
						||
  
 | 
						||
  return err;  
 | 
						||
}
 | 
						||
 | 
						||
int TPartita::read_saldo(TRectype& riga,
 | 
						||
                         TImporto& saldo, TImporto& doc, TImporto& pag, TImporto& imp)
 | 
						||
{         
 | 
						||
  int err = NOERR;
 | 
						||
  
 | 
						||
  if (riga.get_int(PART_NRIGA) != UNASSIGNED)
 | 
						||
  {
 | 
						||
    TLocalisamfile part(LF_PARTITE);
 | 
						||
    TRectype& sld = part.curr();
 | 
						||
    sld = riga;
 | 
						||
    sld.put(PART_NRIGA, (int)UNASSIGNED);
 | 
						||
    
 | 
						||
    err = part.read();
 | 
						||
    if (err != NOERR)
 | 
						||
    {
 | 
						||
      const TPartita p(riga);
 | 
						||
      err = p.write_saldo(false, &sld);
 | 
						||
    }
 | 
						||
    
 | 
						||
    if (err == NOERR)
 | 
						||
      riga = sld;
 | 
						||
    else
 | 
						||
      riga.zero();  
 | 
						||
  }
 | 
						||
  
 | 
						||
  if (err == NOERR)
 | 
						||
  {
 | 
						||
    saldo.set(riga.get_char(PART_SEZ), riga.get_real(PART_IMPORTO));
 | 
						||
    doc.set(riga.get_char(PART_SEZABB), riga.get_real(PART_ABBUONI));
 | 
						||
    pag.set(riga.get_char(PART_SEZDIFCAM), riga.get_real(PART_DIFFCAM));
 | 
						||
    imp.set(riga.get_char(PART_REG), riga.get_real(PART_IMPOSTA));
 | 
						||
  }
 | 
						||
    
 | 
						||
  return err;  
 | 
						||
}
 | 
						||
 | 
						||
bool TPartita::write(bool re) const
 | 
						||
{                   
 | 
						||
  if (ok())
 | 
						||
  {              
 | 
						||
    chiusa(true);       // Aggiorna flag di chiusura (non si sa mai)
 | 
						||
                             
 | 
						||
    if (conto().tipo() > ' ' && conto().gruppo() > 0)
 | 
						||
    {                         
 | 
						||
      // Aggiunge conti cliente/fornitore mancanti
 | 
						||
      for (int r = last(); r > 0; r = pred(r))
 | 
						||
      {
 | 
						||
        TRiga_partite& row = riga(r);
 | 
						||
        if (row.get(PART_GRUPPOCL).empty())
 | 
						||
        {
 | 
						||
          row.put(PART_GRUPPOCL, conto().gruppo());
 | 
						||
          row.put(PART_CONTOCL, conto().conto());
 | 
						||
        }
 | 
						||
      }                           
 | 
						||
    }
 | 
						||
    
 | 
						||
    const char cur_align = allineamento_corrente();
 | 
						||
    const char req_align = allineamento_richiesto(conto().tipo());
 | 
						||
    if (cur_align > ' ' && cur_align != req_align)
 | 
						||
    {
 | 
						||
      // Riallinea tutti i numeri partita nelle righe. rate e pagamenti
 | 
						||
      ((TPartita*)this)->allinea(req_align);
 | 
						||
    }  
 | 
						||
  }
 | 
						||
  
 | 
						||
  int err = _part.write(re);
 | 
						||
  if (err == NOERR)
 | 
						||
    err = _unassigned.write(re);
 | 
						||
 | 
						||
  if (err == NOERR)
 | 
						||
  {          
 | 
						||
    // Se esiste almeno una riga scrive la riga riepilogativa della partita
 | 
						||
    if (ok()) write_saldo(re); 
 | 
						||
     
 | 
						||
    // Se l'allineamento e' cambiato cancello la vecchia partita
 | 
						||
    if (allineamento_corrente() != allineamento_iniziale())
 | 
						||
    {                   
 | 
						||
      // Costruisce il vecchio numero partita
 | 
						||
      TString16 num = numero();
 | 
						||
      if (allineamento_iniziale() == 'R')
 | 
						||
        num.right_just(NUMLEN);
 | 
						||
      else  
 | 
						||
        num.trim();
 | 
						||
      
 | 
						||
      // Cancella vecchia partita
 | 
						||
			TLocalisamfile part(LF_PARTITE);
 | 
						||
 | 
						||
 | 
						||
			part.put(PART_TIPOCF, conto().tipo());
 | 
						||
		  if (conto().tipo() <= ' ')
 | 
						||
			{                                                        
 | 
						||
		    part.put(PART_GRUPPO, conto().gruppo());
 | 
						||
				part.put(PART_CONTO, conto().conto());                   
 | 
						||
  		  part.put(PART_SOTTOCONTO, conto().sottoconto());
 | 
						||
		  }   
 | 
						||
      else
 | 
						||
        part.put(PART_SOTTOCONTO, conto().codclifo());                   
 | 
						||
 | 
						||
			part.put(PART_ANNO, anno());
 | 
						||
			part.put(PART_NUMPART, num);
 | 
						||
			
 | 
						||
			const TRectype comp(part.curr());
 | 
						||
 | 
						||
			if (part.read(_isgteq) == NOERR && part.curr().compare_key(comp, 1 ,1) == 0)
 | 
						||
			{
 | 
						||
				TPartita canc(conto(), anno(), num);
 | 
						||
				canc.remove();
 | 
						||
			}
 | 
						||
    }
 | 
						||
  }
 | 
						||
    
 | 
						||
  return err == NOERR;
 | 
						||
} 
 | 
						||
 | 
						||
// Cancella tutta una partita
 | 
						||
bool TPartita::remove() const
 | 
						||
{ 
 | 
						||
  const int err = _part.remove();  
 | 
						||
  if (err == NOERR)
 | 
						||
    _unassigned.remove();
 | 
						||
  return err == NOERR;
 | 
						||
} 
 | 
						||
 | 
						||
 | 
						||
// Crea una nuova riga partite
 | 
						||
TRiga_partite& TPartita::new_row(int r) 
 | 
						||
{                        
 | 
						||
  if (r <= 0)                   
 | 
						||
    for (r = 1; esiste(r); r++);
 | 
						||
  CHECKD(!esiste(r), "Ue' pirla!, esiste gia' la riga ", r);
 | 
						||
  TRiga_partite& nuova = (TRiga_partite&)_part.row(r, true); 
 | 
						||
  nuova.put(PART_GRUPPOCL, conto().gruppo());
 | 
						||
  nuova.put(PART_CONTOCL, conto().conto());
 | 
						||
  return nuova;
 | 
						||
}
 | 
						||
 | 
						||
TRiga_partite& TPartita::riga(int r) const 
 | 
						||
{  
 | 
						||
  if (r > 0 && !_part.exist(r))
 | 
						||
  {            
 | 
						||
    yesnofatal_box("La partita %d %s del conto %c %d %d %ld (%s) <20> incoerente: manca la riga %d",
 | 
						||
                    anno(), (const char*)numero(), 
 | 
						||
                    _conto.tipo(), _conto.gruppo(), _conto.conto(), _conto.sottoconto(), 
 | 
						||
                    (const char*)_conto.descrizione(), r);
 | 
						||
                    
 | 
						||
    // Ricreiamo una riga fasulla tanto per non bloccare il programma                    
 | 
						||
    TRiga_partite& newrow = ((TPartita*)this)->new_row(r);
 | 
						||
    for (int p = last(); p > 0; p = pred(p))
 | 
						||
    {
 | 
						||
      const TRiga_partite& par = riga(p);
 | 
						||
      for (int rr = par.rate(); rr > 0; rr--)
 | 
						||
      {
 | 
						||
        TRiga_scadenze& rat = par.rata(rr);
 | 
						||
        if (rat.exist(r))  // Ho trovato un pagamento assegnato alla nuova riga!
 | 
						||
        {
 | 
						||
          newrow.put(PART_TIPOMOV, (int)tm_pagamento);                // Imposta il tipo movimento
 | 
						||
          newrow.put(PART_SEZ, par.sezione() == 'D' ? 'A' : 'D');     // Imposta sezione al contrario della fattura 
 | 
						||
          TValuta val(par); val.put(newrow);                          // Copia valuta da fattura
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return (TRiga_partite&)_part.row(r); 
 | 
						||
} 
 | 
						||
 | 
						||
TRiga_scadenze& TPartita::rata(int nriga, int nrata) const
 | 
						||
{
 | 
						||
  const TRiga_partite& r = riga(nriga);
 | 
						||
  return r.rata(nrata);
 | 
						||
}
 | 
						||
 | 
						||
bool TPartita::rata_chiusa(int nriga, int nrata) const
 | 
						||
{        
 | 
						||
  bool pag = false;
 | 
						||
  if (nriga > 0 && nriga < UNASSIGNED && nrata > 0 && nrata < UNASSIGNED)
 | 
						||
  {
 | 
						||
    const TRiga_scadenze& r = rata(nriga, nrata);
 | 
						||
    pag = r.chiusa();
 | 
						||
  }
 | 
						||
  return pag;
 | 
						||
}
 | 
						||
 | 
						||
bool TPartita::esistono_abbuoni_diffcam(long nreg) const
 | 
						||
{
 | 
						||
  int nrata = 0;
 | 
						||
  const int nriga = prima_fattura(nreg);
 | 
						||
  if (nriga > 0)
 | 
						||
    nrata = riga(nriga).ultima_rata_con_abbuoni_diffcam();
 | 
						||
  return nrata > 0;
 | 
						||
}
 | 
						||
 | 
						||
const TString& TPartita::codice_valuta() const
 | 
						||
{                        
 | 
						||
  const int ultima = last();
 | 
						||
  return ultima > 0 ? riga(ultima).codice_valuta() : (const TString&)EMPTY_STRING;
 | 
						||
}
 | 
						||
 | 
						||
bool TPartita::in_valuta() const
 | 
						||
{                        
 | 
						||
  const int ultima = last();
 | 
						||
  return ultima > 0 ? riga(ultima).in_valuta() : false;
 | 
						||
}
 | 
						||
 | 
						||
TRectype& TPartita::pagamento(int nriga, int nrata, int nrigp)
 | 
						||
{
 | 
						||
  if (nriga == UNASSIGNED || nrata == UNASSIGNED)
 | 
						||
    return _unassigned.row(nrigp, true);
 | 
						||
  TRiga_scadenze& r = rata(nriga, nrata);
 | 
						||
  return r.row(nrigp);
 | 
						||
}
 | 
						||
 | 
						||
// Controlla l'esistenza di una riga, rata, pagamento.  
 | 
						||
// Gli ultimi parametri possono essere nulli per poter testare una singola riga o rata
 | 
						||
bool TPartita::esiste(int nriga, int nrata, int nrigp) const
 | 
						||
{
 | 
						||
  if (nriga == UNASSIGNED)              // Cerca solo pagamento non assegnato
 | 
						||
    return _unassigned.exist(nrigp);
 | 
						||
  
 | 
						||
  const bool esiste_riga = _part.exist(nriga);
 | 
						||
  if (!esiste_riga || nrata <= 0)       // Riga non esistente o rata nulla
 | 
						||
    return esiste_riga;
 | 
						||
 | 
						||
  const TRiga_partite& r = riga(nriga);
 | 
						||
  const bool esiste_rata = r.exist(nrata);
 | 
						||
  if (!esiste_rata || nrigp <= 0)       // Rata inesistente o pagamento nullo
 | 
						||
    return esiste_rata;
 | 
						||
  
 | 
						||
  const TRiga_scadenze& scad = r.rata(nrata);
 | 
						||
  return scad.exist(nrigp);             // Cerca pagamento vero e proprio
 | 
						||
}             
 | 
						||
 | 
						||
bool TPartita::elimina_pagamento(int nriga, int nrata, int nrigp)
 | 
						||
{
 | 
						||
  const bool ok = esiste(nriga, nrata, nrigp);
 | 
						||
  if (ok)
 | 
						||
  {
 | 
						||
    if (nriga == UNASSIGNED)
 | 
						||
    {
 | 
						||
      TRectype old_pag(_unassigned.row(nrigp));
 | 
						||
      old_pag.put(PAGSCA_ACCSAL, "A");
 | 
						||
      old_pag.zero(PAGSCA_IMPORTO);
 | 
						||
      old_pag.zero(PAGSCA_IMPORTOVAL);
 | 
						||
      old_pag.zero(PAGSCA_RITENUTE);
 | 
						||
      old_pag.zero(PAGSCA_RITSOC);
 | 
						||
      const TValuta val;
 | 
						||
      modifica_pagamento(old_pag, val, true);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      TRiga_scadenze& scad = rata(nriga, nrata);
 | 
						||
      scad.elimina_pagamento(nrigp);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
// Ritorna l'importo in lire speso su di una riga contabile
 | 
						||
TImporto TPartita::importo_speso(long nreg, int numrig, bool valuta, int mode) const
 | 
						||
{           
 | 
						||
  TImporto imp;
 | 
						||
  for (int r = last(); r > 0; r = pred(r))
 | 
						||
  {
 | 
						||
    const TRiga_partite& row = riga(r);
 | 
						||
    if (nreg == row.get_long(PART_NREG) && numrig == row.get_int(PART_NUMRIG))
 | 
						||
      imp += row.importo(valuta, mode);
 | 
						||
  }
 | 
						||
  if (!valuta || !in_valuta())
 | 
						||
    imp.valore().round(TCurrency::get_firm_dec());
 | 
						||
  
 | 
						||
  return imp;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void TPartita::update_reg(long nreg, const TRectype& mov, TPartite_array& pa)
 | 
						||
{                         
 | 
						||
  for (int r = last(); r > 0; r = pred(r))
 | 
						||
  {
 | 
						||
    TRiga_partite& rig = riga(r);
 | 
						||
    if (rig.get_long(PART_NREG) == nreg)
 | 
						||
    {
 | 
						||
      rig.put(PART_NREG,    mov.get(MOV_NUMREG));
 | 
						||
      rig.put(PART_DATAREG, mov.get(MOV_DATAREG));
 | 
						||
      rig.put(PART_DATADOC, mov.get(MOV_DATADOC));
 | 
						||
      rig.put(PART_NUMDOC,  mov.get(MOV_NUMDOC));
 | 
						||
      rig.put(PART_REG,     mov.get(MOV_REG));
 | 
						||
      rig.put(PART_PROTIVA, mov.get(MOV_PROTIVA));
 | 
						||
      rig.put(PART_CODCAUS, mov.get(MOV_CODCAUS));
 | 
						||
      
 | 
						||
      if (rig.tipo() == tm_fattura)
 | 
						||
      {
 | 
						||
        rig.put(PART_IMPTOTDOC, mov.get(MOV_TOTDOC));
 | 
						||
        if (rig.in_valuta())
 | 
						||
          rig.put(PART_IMPTOTVAL, mov.get(MOV_TOTDOCVAL));
 | 
						||
        else  
 | 
						||
          rig.zero(PART_IMPTOTVAL);  
 | 
						||
      }
 | 
						||
      else
 | 
						||
      {
 | 
						||
        int numrig = rig.get_int(PART_NUMRIG);
 | 
						||
        if (numrig <= 0)
 | 
						||
        {
 | 
						||
          NFCHECK("Bad NUMRIG: %d", numrig);
 | 
						||
          rig.put(PART_NUMRIG, numrig = 1);
 | 
						||
        }
 | 
						||
                     
 | 
						||
        const TImporto imptotdoc = pa.importo_speso(nreg, numrig, false, 0x9);
 | 
						||
        rig.put(PART_IMPTOTDOC, imptotdoc.valore());
 | 
						||
        if (rig.in_valuta())
 | 
						||
        {
 | 
						||
          const TImporto imptotval = pa.importo_speso(nreg, numrig, true, 0x1);
 | 
						||
          rig.put(PART_IMPTOTVAL, imptotval.valore());
 | 
						||
        }
 | 
						||
        else  
 | 
						||
          rig.zero(PART_IMPTOTVAL);
 | 
						||
      }    
 | 
						||
    }  
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
// 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 (numreg == row.get_long(PART_NREG))
 | 
						||
    {
 | 
						||
      if (rm <= 0 || rm == row.get_int(PART_NUMRIG))
 | 
						||
        return r;
 | 
						||
    }  
 | 
						||
  }
 | 
						||
  return 0;
 | 
						||
} 
 | 
						||
 | 
						||
// Trova la prima riga della partita corrispondente alla registrazione nreg
 | 
						||
int TPartita::prima_riga(long nreg, tipo_movimento tipo) const
 | 
						||
{  
 | 
						||
  const int lastrow = last();
 | 
						||
  for (int r = first(); r <= lastrow; r = succ(r))
 | 
						||
  {
 | 
						||
    const TRiga_partite& row = riga(r);
 | 
						||
    if (tipo == tm_nessuno || tipo == row.tipo())
 | 
						||
      if (nreg <= 0 || nreg == row.get_long(PART_NREG))
 | 
						||
        return r;
 | 
						||
  }
 | 
						||
  return -1;
 | 
						||
}
 | 
						||
 | 
						||
// Trova la prima riga della partita contenente una fattura
 | 
						||
int TPartita::prima_fattura(long nreg) const
 | 
						||
{ return prima_riga(nreg, tm_fattura); }
 | 
						||
 | 
						||
// Trova la prima riga della partita contenente una pagamento
 | 
						||
int TPartita::primo_pagamento(long nreg) const
 | 
						||
{ return prima_riga(nreg, tm_pagamento); }
 | 
						||
 | 
						||
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);
 | 
						||
    const TImporto i(row.importo(false, 0x9));
 | 
						||
 | 
						||
    const tipo_movimento tipo = row.tipo();
 | 
						||
    switch (tipo)
 | 
						||
    {
 | 
						||
    case tm_fattura     :                  // fatture 
 | 
						||
    case tm_nota_credito: doc += i; break; // note di credito
 | 
						||
    case tm_pagamento   : pag += i; break; // pagamenti
 | 
						||
    default             : imp += i; break;// altri importi
 | 
						||
    }    
 | 
						||
    
 | 
						||
    if (tipo >= tm_pagamento)
 | 
						||
    {
 | 
						||
      const TImporto abbuoni(row.importo(false, 0x2));
 | 
						||
      imp += abbuoni;
 | 
						||
      
 | 
						||
      const TImporto diffcam(row.importo(false, 0x4));
 | 
						||
      imp += diffcam;
 | 
						||
    }  
 | 
						||
  }
 | 
						||
 | 
						||
  saldo = doc;
 | 
						||
  saldo += pag;
 | 
						||
  saldo += imp;
 | 
						||
  
 | 
						||
  saldo.normalize();
 | 
						||
  doc.normalize();
 | 
						||
  pag.normalize();
 | 
						||
  imp.normalize();    
 | 
						||
}
 | 
						||
 | 
						||
TImporto TPartita::calcola_saldo(bool valuta) const
 | 
						||
{
 | 
						||
  TImporto saldo;
 | 
						||
  for (int r = last(); r > 0; r = pred(r))
 | 
						||
  {
 | 
						||
    const TRiga_partite& row = riga(r);
 | 
						||
    saldo += row.importo(valuta);
 | 
						||
  }  
 | 
						||
  saldo.normalize(); // Aggiunto il 26/10/2010 nella 11.0 ed il 13/1/2012 nella 10.0
 | 
						||
  return saldo;
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
Funzione completamente inutile e certamente NON utilizzata nei moduli cg, sc e ve 
 | 
						||
 | 
						||
TImporto TPartita::calcola_pagato_al(bool valuta,const TDate& al, const TDate & data_scaduto, const TDate& data_rischio) const
 | 
						||
{
 | 
						||
  TImporto pagato;
 | 
						||
  
 | 
						||
  for (int r = last(); r > 0; r = pred(r))
 | 
						||
  {
 | 
						||
    const TRiga_partite& row = riga(r);
 | 
						||
    const TDate data(row.get(PART_DATAREG));  
 | 
						||
    if (data <= al)
 | 
						||
    {
 | 
						||
      pagato += row.importo(valuta);
 | 
						||
			if (!row.is_fattura())
 | 
						||
      {
 | 
						||
        const tipo_pagamento tipopag = row.tipo_pag();
 | 
						||
				if (tipopag >= tp_tratta && tipopag <= tp_rid)
 | 
						||
        {
 | 
						||
					bool sbf = false;
 | 
						||
					pagato -= row.esposto(valuta, data_scaduto, data_rischio, sbf);
 | 
						||
        }
 | 
						||
      }    
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  return pagato;
 | 
						||
}
 | 
						||
*/
 | 
						||
 | 
						||
TImporto TPartita::calcola_saldo_al(bool valuta,const TDate& al, const TDate & data_scaduto, const TDate& data_rischio) const
 | 
						||
{
 | 
						||
  TImporto saldo;
 | 
						||
  
 | 
						||
  for (int r = last(); r > 0; r = pred(r))
 | 
						||
  {
 | 
						||
    const TRiga_partite& row = riga(r);
 | 
						||
    const TDate data(row.get(PART_DATAREG));
 | 
						||
    
 | 
						||
    if (data <= al)
 | 
						||
    {
 | 
						||
      saldo += row.importo(valuta);
 | 
						||
      if (!row.is_fattura())
 | 
						||
      {
 | 
						||
        const tipo_pagamento tipopag = row.tipo_pag();
 | 
						||
 | 
						||
				if (tipopag >= tp_tratta && tipopag <= tp_rid)
 | 
						||
        {
 | 
						||
          bool sbf = false;
 | 
						||
          saldo -= row.esposto(valuta, data_scaduto, data_rischio, sbf);
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  return saldo;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
real TPartita::calcola_scaduto_al(bool valuta, const TDate& al) const
 | 
						||
{
 | 
						||
  const int ultima = last();
 | 
						||
  if (ultima > 0)
 | 
						||
  {
 | 
						||
    TImporto scaduto;
 | 
						||
    const TBill & c = conto();
 | 
						||
    char sezione = ' ';                       
 | 
						||
    
 | 
						||
    if (c.tipo() == 'C') 
 | 
						||
      sezione = 'D';
 | 
						||
    else
 | 
						||
      if (c.tipo() == 'F') 
 | 
						||
        sezione = 'A';  
 | 
						||
      else     
 | 
						||
      {        
 | 
						||
        const TRiga_partite& row = riga(ultima);    
 | 
						||
        const tipo_movimento t = row.tipo();
 | 
						||
        if (t == tm_fattura || t == tm_insoluto)
 | 
						||
          sezione = row.sezione();
 | 
						||
        else
 | 
						||
          sezione = row.sezione() == 'D' ? 'A' : 'D';  
 | 
						||
      }
 | 
						||
  
 | 
						||
    for (int r = ultima; r > 0; r = pred(r))
 | 
						||
    {
 | 
						||
      const TRiga_partite& row = riga(r);    
 | 
						||
      if (row.is_fattura())
 | 
						||
      {
 | 
						||
        for (int s = row.rate(); s > 0 ;s--)
 | 
						||
        {
 | 
						||
          const TRiga_scadenze& rata = row.rata(s);
 | 
						||
          const TDate data = rata.get(SCAD_DATASCAD);
 | 
						||
          if (data <= al)
 | 
						||
          {
 | 
						||
            scaduto += rata.importo(valuta);
 | 
						||
            scaduto += rata.importo_pagato(valuta);
 | 
						||
          }
 | 
						||
        }  
 | 
						||
      }
 | 
						||
    }  
 | 
						||
    scaduto.normalize(sezione);
 | 
						||
    if (scaduto.valore() > 0)
 | 
						||
      scaduto += importo_pagato_unassigned(valuta);
 | 
						||
    scaduto.normalize(sezione);
 | 
						||
    if (scaduto.valore() > 0)
 | 
						||
      return scaduto.valore();
 | 
						||
  }  
 | 
						||
  return ZERO;
 | 
						||
}
 | 
						||
 | 
						||
// Calcola il totale dei pagamenti non assegnati (eventualmente in valuta)
 | 
						||
TImporto TPartita::importo_pagato_unassigned(bool val, int mode) const
 | 
						||
{                                
 | 
						||
  CHECKD(mode > 0x0 && mode <= 0xF, "Bad importo_pagato mode ", mode);
 | 
						||
  const bool in_val = in_valuta();   
 | 
						||
  const char* imp_field = (val && in_val) ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO;
 | 
						||
  
 | 
						||
  TImporto totale; 
 | 
						||
  const int last_row = _unassigned.last_row();
 | 
						||
  for (int p = _unassigned.first_row(); p <= last_row; p = _unassigned.succ_row(p))
 | 
						||
  {
 | 
						||
    const TRectype& pag = _unassigned.row(p);                         // Riga pagamento
 | 
						||
    const TRiga_partite& sum = riga(pag.get_int(PAGSCA_NRIGP));       // Riga partite
 | 
						||
    const char sez = sum.sezione();
 | 
						||
    
 | 
						||
    if (mode & 0x1)              
 | 
						||
      totale += TImporto(sez, pag.get_real(imp_field));
 | 
						||
    if (!in_val && (mode & 0x8))     // Le ritenute non esistono nei pagamenti in valuta
 | 
						||
    {
 | 
						||
      totale += TImporto(sez, pag.get_real(PAGSCA_RITENUTE));
 | 
						||
      totale += TImporto(sum.sezione_ritsoc(), pag.get_real(PAGSCA_RITSOC));
 | 
						||
    }
 | 
						||
    
 | 
						||
    if (mode & 0x2)                   // Voglio anche gli abbuoni
 | 
						||
    {
 | 
						||
      real abb(pag.get_real(PAGSCA_ABBUONI));
 | 
						||
      if (in_val && !val)             // Gli abbuoni sono sempre in valuta e quindi
 | 
						||
      {                               // devono essere convertiti opportunamente
 | 
						||
        const TExchange cmb(sum);
 | 
						||
        TCurrency cur(abb, cmb);
 | 
						||
        cur.change_to_firm_val();
 | 
						||
        abb = cur.get_num();
 | 
						||
      }
 | 
						||
      totale += TImporto(sez, abb);
 | 
						||
    }
 | 
						||
    
 | 
						||
    if (in_val && !val && (mode & 0x4))   // Voglio anche le differenze cambio
 | 
						||
    {                                     // Esse esistono solo nei pagamenti in valuta
 | 
						||
      const TImporto diffcam(sez, pag.get_real(PAGSCA_DIFFCAM));
 | 
						||
      totale += diffcam;
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  
 | 
						||
  return totale.normalize();
 | 
						||
}
 | 
						||
 | 
						||
// Controlla se esistono pagamenti riferiti alla riga nrigp
 | 
						||
bool TPartita::utilizzata(int nrigp) const
 | 
						||
{           
 | 
						||
  for (int p = last(); p > 0; p = pred(p))
 | 
						||
  {
 | 
						||
    const TRiga_partite& fatt = riga(p);
 | 
						||
    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::modifica_pagamento(const TRectype& new_pag, const TValuta& valuta, 
 | 
						||
                                  char& old_ap, TImporto& old_abb, TImporto& old_diffcam,  
 | 
						||
                                  char& new_ap, TImporto& new_abb, TImporto& new_diffcam,
 | 
						||
                                  bool update)
 | 
						||
{                    
 | 
						||
  const int nriga = new_pag.get_int(PAGSCA_NRIGA);
 | 
						||
  const int nrata = new_pag.get_int(PAGSCA_NRATA);
 | 
						||
  const int nrigp = new_pag.get_int(PAGSCA_NRIGP);
 | 
						||
 | 
						||
  bool empty = false;
 | 
						||
  
 | 
						||
  if (nriga != UNASSIGNED)    
 | 
						||
  {                       
 | 
						||
    TRiga_scadenze& scaden = rata(nriga, nrata);
 | 
						||
    empty = scaden.modifica_pagamento(new_pag, valuta,
 | 
						||
                                      old_ap, old_abb, old_diffcam,  
 | 
						||
                                      new_ap, new_abb, new_diffcam, update);
 | 
						||
  }                            
 | 
						||
  else
 | 
						||
  {                                    
 | 
						||
    const TRectype& old_pag = pagamento(nriga, nrata, nrigp);
 | 
						||
    
 | 
						||
    TRiga_partite& sum = riga(nrigp);
 | 
						||
    empty = sum.update(old_pag, new_pag, PART_IMPORTO);
 | 
						||
    sum.update(old_pag, new_pag, PART_IMPORTOVAL);
 | 
						||
    sum.update(old_pag, new_pag, PART_RITENUTE);
 | 
						||
    sum.update(old_pag, new_pag, PART_RITSOC);
 | 
						||
    
 | 
						||
    if (new_pag.get_real(PAGSCA_IMPORTO).is_zero())        
 | 
						||
      _unassigned.destroy_row(nrigp);
 | 
						||
    else    
 | 
						||
      _unassigned.row(nrigp, false) = new_pag;
 | 
						||
    
 | 
						||
    // Non ci possono essere abbuoni o differenze cambio di sorta!
 | 
						||
    old_ap = new_ap = ' ';       
 | 
						||
    old_abb = new_abb = old_diffcam = new_diffcam = TImporto('D', ZERO);
 | 
						||
  }
 | 
						||
  
 | 
						||
  if (empty && !utilizzata(nrigp))
 | 
						||
    rimuovi_riga(nrigp);
 | 
						||
 | 
						||
  return empty;    
 | 
						||
} 
 | 
						||
 | 
						||
 | 
						||
bool TPartita::modifica_pagamento(const TRectype& new_pag, const TValuta& valuta, bool update)
 | 
						||
{
 | 
						||
  char old_ap, new_ap;
 | 
						||
  TImporto old_abbuono, new_abbuono, old_diffcam, new_diffcam;
 | 
						||
  return modifica_pagamento(new_pag, valuta,
 | 
						||
                            old_ap, old_abbuono, old_diffcam, 
 | 
						||
                            new_ap, new_abbuono, new_diffcam, update);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TPartita::chiusa(bool update) const
 | 
						||
{ 
 | 
						||
  bool chiusa = true;          
 | 
						||
  const int ultima = last();
 | 
						||
  if (update)
 | 
						||
  {
 | 
						||
    const TImporto saldo = calcola_saldo(true);  // Saldo in valuta
 | 
						||
    chiusa = saldo.is_zero();
 | 
						||
    for (int p = ultima; p > 0; p = pred(p))
 | 
						||
    {
 | 
						||
      TRiga_partite& part = riga(p);
 | 
						||
      part.put(PART_CHIUSA, chiusa);
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  else
 | 
						||
  {
 | 
						||
    if (ultima > 0)
 | 
						||
    {
 | 
						||
      const TRiga_partite& row = riga(ultima);
 | 
						||
      chiusa = row.get_bool(PART_CHIUSA);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  return chiusa;
 | 
						||
}
 | 
						||
 | 
						||
void TPartita::rimuovi_riga(int r) 
 | 
						||
{                
 | 
						||
  TRiga_partite& row = riga(r);
 | 
						||
  if (row.rate() > 0)
 | 
						||
    row.elimina_rata(-1);
 | 
						||
  else
 | 
						||
    CHECKD(!utilizzata(r), "Can't remove still referenced row ", r);
 | 
						||
  _part.destroy_row(r); 
 | 
						||
  chiusa(true);
 | 
						||
}
 | 
						||
 | 
						||
static void somma(const TRectype& vec, TRectype& nuo, const char* field)
 | 
						||
{
 | 
						||
  real totale(vec.get(field));
 | 
						||
  totale += nuo.get_real(field);
 | 
						||
  nuo.put(field, totale);
 | 
						||
}
 | 
						||
 | 
						||
void TPartita::sposta_riga(int from_row, TPartita& part, int to_row)
 | 
						||
{
 | 
						||
  const TRiga_partite& row = riga(from_row);
 | 
						||
  TRiga_partite& nrw = part.riga(to_row);
 | 
						||
  
 | 
						||
  const int address_size = last()+1;
 | 
						||
  int* address = new int[address_size];
 | 
						||
  memset(address, 0, address_size*sizeof(int));
 | 
						||
 | 
						||
  TToken_string knames(64); // Elenco dei campi della chiave 1 dei pagamenti
 | 
						||
  knames.add(PART_TIPOCF);
 | 
						||
  knames.add(PART_GRUPPO);
 | 
						||
  knames.add(PART_CONTO);
 | 
						||
  knames.add(PART_SOTTOCONTO);
 | 
						||
  knames.add(PART_ANNO);
 | 
						||
  knames.add(PART_NUMPART);
 | 
						||
  knames.add(PART_NRIGA);
 | 
						||
  knames.add(SCAD_NRATA);
 | 
						||
  knames.add(PAGSCA_NRIGP);
 | 
						||
  
 | 
						||
  for (int i = 1; i <= row.rate(); i++)
 | 
						||
  {                         
 | 
						||
    TRiga_scadenze& scd = row.rata(i);
 | 
						||
    for (int j = scd.last(); j > 0; j = scd.pred(j))
 | 
						||
    { 
 | 
						||
      const TRectype& pag = scd.row(j);
 | 
						||
      
 | 
						||
      CHECK(j < address_size, "Bad nrigp address");
 | 
						||
      if (address[j] == 0)
 | 
						||
      {                                       
 | 
						||
        const TRiga_partite& vecchia = riga(j);
 | 
						||
        TRiga_partite& nuova = part.new_row(part.esiste(j) ? 0 : j);
 | 
						||
        
 | 
						||
        for (int n = vecchia.items()-1; n >= 0; n--) // Copia tutti i campi non chiave
 | 
						||
        {
 | 
						||
          const char* f = vecchia.fieldname(n);
 | 
						||
          if (knames.get_pos(f) < 0)
 | 
						||
            nuova.put(f, vecchia.get(f));
 | 
						||
        }
 | 
						||
        nuova.zero(PART_IMPORTO);
 | 
						||
        nuova.zero(PART_IMPORTOVAL);
 | 
						||
        nuova.zero(PART_ABBUONI);
 | 
						||
        nuova.zero(PART_DIFFCAM);
 | 
						||
        nuova.zero(PART_RITENUTE);
 | 
						||
        nuova.zero(PART_RITSOC);
 | 
						||
        address[j] = nuova.get_int(PART_NRIGA);
 | 
						||
      }        
 | 
						||
      
 | 
						||
      int new_row = to_row;                         // Nuova riga fattura
 | 
						||
      int new_sca = i;                              // Nuovo numero rata (uguale a prima)
 | 
						||
      const int nrigp = address[j];                 // Nuova riga somma (e pagamento)
 | 
						||
 | 
						||
      if (!part.esiste(new_row, new_sca))           // Se la nuova partita non ha la rata
 | 
						||
        new_row = new_sca = UNASSIGNED;             // allora sposta sui non asseganti
 | 
						||
 | 
						||
      TRectype npg(LF_PAGSCA);                      // Nuovo record di pagamento
 | 
						||
      
 | 
						||
      if (part.esiste(new_row, new_sca, nrigp))     // Se il pagamento esiste di gia'
 | 
						||
      {  
 | 
						||
        npg = part.pagamento(new_row, new_sca, nrigp);
 | 
						||
        somma(pag, npg, PART_IMPORTO);
 | 
						||
        somma(pag, npg, PART_IMPORTOVAL); 
 | 
						||
        somma(pag, npg, PART_RITENUTE);
 | 
						||
        somma(pag, npg, PART_RITSOC);
 | 
						||
      }
 | 
						||
      else
 | 
						||
      {
 | 
						||
        if (new_sca == UNASSIGNED)
 | 
						||
          npg = part.unassigned().row(nrigp, true);
 | 
						||
        else
 | 
						||
          npg = nrw.rata(new_sca).new_row(nrigp);
 | 
						||
        for (int n = pag.items()-1; n >= 0; n--)    // Copia tutti i campi non chiave
 | 
						||
        {
 | 
						||
          const char* f = pag.fieldname(n);
 | 
						||
          if (knames.get_pos(f) < 0)
 | 
						||
            npg.put(f, pag.get(f));
 | 
						||
        }
 | 
						||
      }                               
 | 
						||
 | 
						||
      const TValuta val;
 | 
						||
      part.modifica_pagamento(npg, val, false);
 | 
						||
      scd.elimina_pagamento(j);
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  
 | 
						||
  delete address;
 | 
						||
  rimuovi_riga(from_row);        
 | 
						||
}
 | 
						||
 | 
						||
// Sposta i pagamenti della riga r, dalla rata s compresa in poi, sui non assegnati
 | 
						||
void TPartita::scollega_pagamenti(int r, int s)
 | 
						||
{                          
 | 
						||
  CHECKD(s > 0, "Impossibile scollegare la rata ", s);
 | 
						||
  const TRiga_partite& row = riga(r);
 | 
						||
  for (int i = row.rate(); i >= s; i--)
 | 
						||
  {                         
 | 
						||
    TRiga_scadenze& sc = row.rata(i);
 | 
						||
    for (int j = sc.last(); j > 0; j = sc.pred(j))
 | 
						||
    { 
 | 
						||
      TRectype& pag = sc.row(j);                              
 | 
						||
      CHECK(pag.get_real(PAGSCA_ABBUONI).is_zero(), "Can't detach payment with ABBUONI");
 | 
						||
      CHECK(pag.get_real(PAGSCA_DIFFCAM).is_zero(), "Can't detach payment with DIFFCAM");
 | 
						||
      pag.put(PAGSCA_NRIGA, (int)TPartita::UNASSIGNED);
 | 
						||
      pag.put(PAGSCA_NRATA, (int)TPartita::UNASSIGNED);  
 | 
						||
      pag.put(PAGSCA_ACCSAL, 'A');
 | 
						||
      if (_unassigned.exist(j))
 | 
						||
      { 
 | 
						||
        TRectype& unas = _unassigned.row(j, false);
 | 
						||
        somma(pag, unas, PAGSCA_IMPORTO);
 | 
						||
        somma(pag, unas, PAGSCA_IMPORTOVAL);
 | 
						||
      }
 | 
						||
      else
 | 
						||
        _unassigned.add_row(pag);
 | 
						||
      sc.rows_array().destroy_row(j);
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
// Trova la riga di causale corrispondente ad un tipo di pagamento
 | 
						||
int TPartita::tipopag2causale(int tipo) const
 | 
						||
{ 
 | 
						||
  int caus = 2;
 | 
						||
  switch (tipo)
 | 
						||
  {       
 | 
						||
  case 2:              // Tratta
 | 
						||
    caus = 3; break;   
 | 
						||
  case 3:              // Ricevuta bancaria
 | 
						||
    caus = 4; break;   
 | 
						||
  case 4:              // Cessione
 | 
						||
    caus = 5; break;   
 | 
						||
  case 5:              // Paghero'
 | 
						||
    caus = 6; break;   
 | 
						||
  case 6:              // Fattura di credito
 | 
						||
    caus = 7; break;   
 | 
						||
  case 7:              // Tratta accettata
 | 
						||
    caus = 8; break;   
 | 
						||
  case 1:              // Rimessa
 | 
						||
  case 8:              // Rapporti interbancari diretti
 | 
						||
  case 9:              // Bonifico
 | 
						||
  default:
 | 
						||
    caus = 2; break;  
 | 
						||
  }                      
 | 
						||
  return caus;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// 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.codclifo(), 
 | 
						||
                                      anno, TPartita::NUMLEN, num);
 | 
						||
  else
 | 
						||
    _key.format("%c%3d%3d%6ld%4d%*s", 
 | 
						||
                ' ', clifo.gruppo(), clifo.conto(), clifo.sottoconto(), 
 | 
						||
                anno, TPartita::NUMLEN, 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);
 | 
						||
    add(k, p);
 | 
						||
  }
 | 
						||
  return p;
 | 
						||
}
 | 
						||
 | 
						||
TPartita* TPartite_array::find(const TRectype& r, bool create)
 | 
						||
{                           
 | 
						||
  TBill zio; zio.get(r);
 | 
						||
  if (zio.gruppo() == 0 && r.num() == LF_PARTITE)
 | 
						||
  {
 | 
						||
    zio.set(r.get_int(PART_GRUPPOCL), r.get_int(PART_CONTOCL), 
 | 
						||
            zio.codclifo(), zio.tipo());
 | 
						||
  }
 | 
						||
  const int anno = r.get_int(PART_ANNO);
 | 
						||
  const TString8 num = r.get(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);
 | 
						||
  CHECK(game, "Partita errata");
 | 
						||
  return *game;
 | 
						||
}
 | 
						||
 | 
						||
TPartita& TPartite_array::partita(const TRectype& r)
 | 
						||
{                           
 | 
						||
  TPartita* game = find(r, true);
 | 
						||
  CHECK(game, "Partita errata");
 | 
						||
  return *game;
 | 
						||
}
 | 
						||
 | 
						||
bool TPartite_array::insert(TPartita* p)
 | 
						||
{
 | 
						||
  const TString& k = key(p->conto(), p->anno(), p->numero());
 | 
						||
  TPartita* old = (TPartita*)objptr(k);
 | 
						||
  if (old != NULL) remove(k);
 | 
						||
  add(k, p);
 | 
						||
  return old != NULL;
 | 
						||
}
 | 
						||
 | 
						||
bool TPartite_array::destroy(const TBill& clifo, int anno, const char* num)
 | 
						||
{
 | 
						||
  const TString& k = key(clifo, anno, num);
 | 
						||
  return remove(k);
 | 
						||
}
 | 
						||
 | 
						||
bool TPartite_array::destroy(TPartita& game)
 | 
						||
{
 | 
						||
  const TString& k = key(game.conto(), game.anno(), game.numero());
 | 
						||
  return remove(k);
 | 
						||
}
 | 
						||
 | 
						||
bool TPartite_array::write(bool re)
 | 
						||
{       
 | 
						||
  bool ok = true;
 | 
						||
  
 | 
						||
  TPartita* game;
 | 
						||
  restart();
 | 
						||
  while ((game = (TPartita*)get()) != NULL)
 | 
						||
  {
 | 
						||
    ok = game->write(re);
 | 
						||
    if (!ok)    // L'errore viene gia' segnalato dalla partita
 | 
						||
      break;
 | 
						||
  }  
 | 
						||
  
 | 
						||
  return ok;
 | 
						||
}
 | 
						||
 | 
						||
void TPartite_array::destroy() 
 | 
						||
{ 
 | 
						||
  TAssoc_array::destroy(); 
 | 
						||
  _numreg = 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// Aggiunge all'array tutte le partite che si riferiscono alla registrazione nreg
 | 
						||
int TPartite_array::add_numreg(long nreg)
 | 
						||
{                                       
 | 
						||
  if (nreg != _numreg)
 | 
						||
  {
 | 
						||
    TRelation rel(LF_PARTITE);
 | 
						||
    
 | 
						||
    TRectype& part = rel.curr(); 
 | 
						||
    part.zero(); 
 | 
						||
    part.put(PART_NREG, nreg);
 | 
						||
    
 | 
						||
    // Uso un cursore per evitare conflitti di lettura con l'oggetto partita
 | 
						||
    TCursor cur(&rel, "", 2, &part, &part);  
 | 
						||
    cur.freeze();
 | 
						||
    for (cur = 0; cur.ok(); ++cur)
 | 
						||
      partita(part);                // Aggiungi partita se non esiste gia'
 | 
						||
 | 
						||
    _numreg = nreg;
 | 
						||
  }
 | 
						||
  
 | 
						||
  return items();
 | 
						||
}
 | 
						||
 | 
						||
int TPartite_array::add_rec(const TRectype& rec)
 | 
						||
{
 | 
						||
  long numreg = 0;
 | 
						||
  switch (rec.num())
 | 
						||
  {
 | 
						||
  case LF_MOV:
 | 
						||
  case LF_RMOV:
 | 
						||
  case LF_RMOVIVA: numreg = rec.get_long(MOV_NUMREG); break;
 | 
						||
  case LF_PARTITE: numreg = rec.get_long(PART_NREG); break;
 | 
						||
  case LF_DOC:     numreg = rec.get_long(DOC_NUMREG); break;
 | 
						||
  default: break;
 | 
						||
  }
 | 
						||
  return numreg > 0 ? add_numreg(numreg) : 0L;
 | 
						||
}
 | 
						||
 | 
						||
bool TPartite_array::utilizzata(long numreg, int numrig)
 | 
						||
{
 | 
						||
  bool ok = false;
 | 
						||
  for (TPartita* game = first(); game; game = next())
 | 
						||
  {
 | 
						||
    ok = game->mov2rig(numreg, numrig) > 0;
 | 
						||
    if (ok) break;
 | 
						||
  }  
 | 
						||
  return ok;
 | 
						||
}
 | 
						||
 | 
						||
TImporto TPartite_array::importo_speso(long nreg, int numrig, bool valuta, int mode)
 | 
						||
{
 | 
						||
  TImporto imp;
 | 
						||
//  add_numreg(nreg);   // Gia' fatto nella read del movimento nreg
 | 
						||
  for (TPartita* game = first(); game; game = next())
 | 
						||
    imp += game->importo_speso(nreg, numrig, valuta, mode);
 | 
						||
  imp.normalize();
 | 
						||
  if (!valuta)
 | 
						||
    imp.valore().round(TCurrency::get_firm_dec());
 | 
						||
  return imp;
 | 
						||
}
 | 
						||
 | 
						||
void TPartite_array::update_reg(const TRectype& mov, long old_nreg)
 | 
						||
{
 | 
						||
  if (old_nreg <= 0 && old_nreg != NUMREG_PROVVISORIO)
 | 
						||
    old_nreg = mov.get_long(MOV_NUMREG);
 | 
						||
//  add_numreg(nreg);   // Non farlo mai piu', carica movimenti registrati contemporaneamente!
 | 
						||
  
 | 
						||
  const int tot = items();
 | 
						||
  if (tot > 0)
 | 
						||
  {
 | 
						||
    TPartita** giochi = new TPartita*[tot];
 | 
						||
    
 | 
						||
    int i = 0;
 | 
						||
    for (TPartita* game = first(); game; game = next())
 | 
						||
      giochi[i++] = game;
 | 
						||
    while (--i >= 0)
 | 
						||
      giochi[i]->update_reg(old_nreg, mov, *this);
 | 
						||
      
 | 
						||
    delete [] giochi;  
 | 
						||
  }    
 | 
						||
}
 | 
						||
 | 
						||
TRiga_partite* TPartite_array::mov2rig(long numreg, int numrig)
 | 
						||
{
 | 
						||
  for (TPartita* game = first(); game; game = next())
 | 
						||
  {
 | 
						||
    const int r = game->mov2rig(numreg, numrig);
 | 
						||
    if (r > 0)
 | 
						||
      return &game->riga(r);
 | 
						||
  }            
 | 
						||
  return NULL;
 | 
						||
}        
 |