// cglib01.cpp
// calcolo dei saldi

#include <applicat.h>
#include <date.h>
#include <real.h>
#include <lffiles.h>
#include <isam.h>
#include <tabutil.h>
#include <utility.h>
#include <config.h>
#include <rmov.h>
#include <mov.h>
#include <saldi.h> 
#include <pconti.h> 
#include <clifo.h> 

#include "cglib.h"

HIDDEN TString256 tmp;

// aep e' l'esercizio precedente
TSaldi_list::TSaldi_list(int gr, int co, int aec, int aep)
{
  TLocalisamfile    cf(LF_SALDI, FALSE);
  bool              force;
  TString16         key;
  
  destroy();
  cf.zero();
  
  if (aep)             
    cf.setkey(2);
  else
  {
    cf.setkey(1);
    cf.put(SLD_ANNOES,aec);    
  }
  
  cf.put(SLD_GRUPPO,gr);
  cf.put(SLD_CONTO,co);
  //  TRectype rec(cf.curr());

  for (cf.read(_isgteq);!cf.eof();cf.next())
  {
    //    if (cf.curr() > rec) break;
    const int ae = cf.get_int(SLD_ANNOES);
    const int  g = cf.get_int(SLD_GRUPPO);
    const int  c = cf.get_int(SLD_CONTO);        
    const long s = cf.get_long(SLD_SOTTOCONTO);
    
    if (g != gr || c != co) break;
    
    if (aep)
    {
      if (ae != aec && ae != aep) continue;
    }
    
    TRectype r(cf.curr());   
    key.format("%3d%3d%6ld", g, c, s);
    
    // Se avevo chiesto anche l'es. prec. puo' darsi che l'abbia gia' trovato
    if (aep)
      force = FALSE;
    else
      force = TRUE;

    add((const char*) key, r, force);      
  }
}

TRectype* TSaldi_list::saldi() const 
{ 
  TObject* o = ((TAssoc_array*)this)->get();
  if (o == NULL)
    return (TRectype*)NULL;
  else
    return (TRectype*)o; 
}

TSaldo::TSaldo()
{
  _saldo_iniziale  = ZERO;
  _prg_dare        = ZERO;
  _prg_avere       = ZERO;  
  _saldo           = ZERO;
  _annoes          = 0;
  _indbil          = 0;
  _saldo_ep        = new TRectype(LF_SALDI);
  _movimentato     = _significativo   = FALSE;
  _rec_presente_ec = _rec_presente_ep = FALSE;
}

TSaldo::~TSaldo() 
{
  delete _saldo_ep;
}

//  
// Cerca l'esercizio precedente di EseCorr
// Se EseCorr e' gia' il primo ritorna 0
// senno' ritorna, astutamente, EseCorr - 1
//
const int TSaldo::EsePre(const int EseCorr)
{
  TTable ese("ESC");
  TString16 first;
  TString   codtab;

  ese.first();  
  first = ese.get("CODTAB");
  
  codtab << EseCorr; 
  codtab.format("%04d");
  
  if (codtab == first)  
    return 0;
  
  return EseCorr - 1;
}

real TSaldo::saldofin_esprec(int annoes, int g, int c, long s) 
{
  real saldo,pdare,pavere,pdaresca,paveresca;
  char flag;
  const int annoesprec = EsePre(annoes);
  
  if (annoesprec == 0) return ZERO;  // non ci sono esercizi prima del primo
  
  TRectype   app = ricerca_progr_prec(annoesprec, g, c, s);
  
  flag         = app.get(SLD_FLAGSALINI)[0];
  saldo        = app.get_real(SLD_SALDO);
  pdare        = app.get_real(SLD_PDARE);
  pavere       = app.get_real(SLD_PAVERE); 
  pdaresca     = app.get_real(SLD_PDARESCA);
  paveresca    = app.get_real(SLD_PAVERESCA);

  _significativo = (saldo != ZERO || pdare != ZERO || pavere != ZERO
                    || pdaresca != ZERO || paveresca != ZERO);

  if (flag == 'D')
    return pdare-pavere+saldo+pdaresca-paveresca;
  else 
    return pdare-pavere-saldo+pdaresca-paveresca;   
} 

real TSaldo::calcola_saldo_iniziale(int g,int c,long s,int indbil)
{
  real saldoini, pdaresca, paveresca, pdare, pavere;
  char flag;
  TLocalisamfile saldi(LF_SALDI, FALSE);

  _significativo = TRUE; 
  
  saldi.zero();
  saldi.put(SLD_GRUPPO,g);
  saldi.put(SLD_CONTO,c);
  saldi.put(SLD_SOTTOCONTO,s);
  saldi.put(SLD_ANNOES,_annoes);
  
  if (saldi.read() == NOERR)
    _rec_presente_ec = TRUE;
  else
  {
    saldi.zero();
    _rec_presente_ec = FALSE;
  }

  flag      = saldi.get_char(SLD_FLAGSALINI);
  saldoini  = saldi.get_real(SLD_SALDO);
  //pdare     = saldi.get_real(SLD_PDARE);
  //pavere    = saldi.get_real(SLD_PAVERE);  
  pdaresca  = saldi.get_real(SLD_PDARESCA);
  paveresca = saldi.get_real(SLD_PAVERESCA); 
  
  _significativo = (saldoini != ZERO || pdaresca != ZERO || paveresca != ZERO);
  
  if (saldoini != ZERO)
    if (flag == 'A') saldoini = -saldoini; 
  
  if (saldoini == ZERO) 
    if ( indbil == 1 || indbil == 2 || indbil == 5 )
    {
      saldoini = saldofin_esprec(_annoes, g, c, s);
      flag     = 'D';  // Il segno DEVE essere quello del saldo precedente
    }
  
  _saldo_iniziale = saldoini;

#ifdef DBG
  TString sldi(saldoini.string());
#endif
  
  if (flag == 'D')
    return pdaresca-paveresca+saldoini; 
  else 
    return pdaresca-paveresca-saldoini;
}

const char* TSaldo::causale_chiusura_es()
{
  TConfig conf(CONFIG_DITTA);
  tmp = conf.get("CoCaCh");

  return tmp;
}

const char* TSaldo::causale_apertura_es()
{
  TConfig conf(CONFIG_DITTA);
  tmp = conf.get("CoCaAp");

  return tmp;
}

void TSaldo::leggi_mov(long nr)
{
  TLocalisamfile mov(LF_MOV, FALSE);

  mov.zero();
  mov.put (MOV_NUMREG,nr);

  if (mov.read() == NOERR)
  {
    _codcaus  = mov.get     (MOV_CODCAUS);
    _datareg  = mov.get_date(MOV_DATAREG);
    _provv    = mov.get     (MOV_PROVVIS);
    _datacomp = mov.get_date(MOV_DATACOMP);
  }  
}

/********************************************
  bool Saldo::calcola_data_limite(int annoes, int g, int c, long s, const TDate& data_inf, const TDate& data_sup, int indbil, bool controllo_competenza, const TDate& inizio_es, const TDate& fine_es, const TDate& fine_es_prec,bool stp_prov)
  {
  TString sezione, gcs_corr, gcs_prec="", provv = "";
  real    importo, dep = ZERO;
  int     gruppo, conto, annoe;
  long    sottoconto, num_reg;
  TLocalisamfile rmov(LF_RMOV, FALSE);
  
  TDate data_rmv;
  bool esito = FALSE;

  rmov.setkey(2);
  rmov.zero();
  rmov.put(RMV_GRUPPO,g);
  if (c != 0)
  rmov.put(RMV_CONTO,c);
  if (s != 0)
  rmov.put(RMV_SOTTOCONTO,s);
  TRectype rec(rmov.curr());

  rmov.read(_isgteq);     
  for ( ; !rmov.eof(); rmov.next())
  {
  if (rmov.curr() != rec) break;
  
  annoe      = rmov.get_int(RMV_ANNOES);
  gruppo     = rmov.get_int(RMV_GRUPPO);
  conto      = rmov.get_int(RMV_CONTO);
  sottoconto = rmov.get_long(RMV_SOTTOCONTO);
  data_rmv   = rmov.get_date(RMV_DATAREG);
  num_reg    = rmov.get_long(RMV_NUMREG);

  //se la causale del movimento e' uguale a quella di chiusura, il movimento non va considerato
  //if (causale_mov(num_reg,inizio_es,data_sup,provv)) 
  //   break; 

  if ((!stp_prov) && (provv.trim().not_empty())) //se non e' richiesta stampa
  continue;                                    //mov. provvisori li scarto
  
  gcs_corr   = format ("%3d%3d%6ld", gruppo, conto, sottoconto);  

  if (gcs_corr != gcs_prec)  
  {
  gcs_prec = gcs_corr;
  //dep += calcola_saldo_iniziale(annoe,gruppo,conto,sottoconto,indbil);
  }

  //controllo sulle date   
  if (annoe != annoes)
  if (annoe != annoes-1)
  continue;
  
  if (controllo_competenza)    
  if ( (annoe == annoes -1) && (data_sup != fine_es) )
  continue;
  else
  if ( (data_rmv <= fine_es) && (data_rmv <= fine_es_prec) ||
  (data_rmv > fine_es) )
  continue;     

  if ( (data_rmv < data_inf) || (data_rmv > data_sup) )
  continue;

  sezione    = rmov.get(RMV_SEZIONE);
  importo    = rmov.get_real(RMV_IMPORTO);

  if (importo.is_zero())
  continue;
  
  esito = TRUE;    
  
  if (sezione == "D")  dep += importo;
  else dep -= importo;

  }
  _saldo = dep;
  return esito;  
  }
  ***************************************************/

bool TSaldo::data_limite_bilancio(int bilancio, int g, int c, long s, const TDate& data_inf, 
                                  const TDate& data_sup, int indbil, bool stp_prov)
{
  TString16 gcs_corr, gcs_prec;
  int       gruppo, conto, annoe;
  long      sottoconto, num_reg;
  real      importo;  
  TDate     data_mov;   
  char      sezione;
  
  TLocalisamfile rmov(LF_RMOV, FALSE);
  
  _saldo_iniziale  = ZERO;
  _saldo           = ZERO;
  _movimentato     = FALSE;
  _rec_presente_ep = FALSE;
  _rec_presente_ec = FALSE;
  
  gcs_prec        = "";
  
  rmov.setkey(2);
  rmov.zero();
  rmov.put(RMV_GRUPPO,g);
  rmov.put(RMV_CONTO,c);
  rmov.put(RMV_SOTTOCONTO,s);
  TRectype rec(rmov.curr());

  for (rmov.read(_isgteq); !rmov.eof(); rmov.next())
  {
    if (rmov.curr() != rec) break;
    
    annoe      = rmov.get_int(RMV_ANNOES);
    gruppo     = rmov.get_int(RMV_GRUPPO);
    conto      = rmov.get_int(RMV_CONTO);
    sottoconto = rmov.get_long(RMV_SOTTOCONTO);
    num_reg    = rmov.get_long(RMV_NUMREG);
    sezione    = rmov.get_char(RMV_SEZIONE);
    importo    = rmov.get_real(RMV_IMPORTO);

    // Leggo la testata
    leggi_mov(num_reg);    

    if (bilancio == DataLimite)
      data_mov = _datacomp;
    else
    {
      if (_annoes == 0)
        data_mov = _datareg;
      else              
        data_mov = _datacomp;
    } 
    if (data_mov < data_inf || data_mov > data_sup)
      continue;                         
    
    // "Se la causale del movimento e' uguale a quella di chiusura, 
    //  o di apertura il movimento non va considerato"
      if (_codcaus.not_empty())
        if (_codcaus == causale_chiusura_es() || 
            _codcaus == causale_apertura_es()) 
          continue;

    //se non e' richiesta stampa mov. provvisori li scarto
    if (!stp_prov && _provv.trim().not_empty()) 
      continue;                                

    // "I mov. di puro riferimento (= con importo = 0) vanno scartati"
    if (importo == ZERO) continue;
    
    gcs_corr = format ("%3d%3d%6ld", gruppo, conto, sottoconto);  

    if (gcs_corr != gcs_prec)  
    {
      gcs_prec = gcs_corr;
      _saldo   = calcola_saldo_iniziale(gruppo,conto,sottoconto,indbil);
    }
    
#ifdef DBG
    TString dep1(_saldo.string());
#endif

    _movimentato = TRUE;

    if (sezione == 'D')  
      _saldo += importo;
    else 
      _saldo -= importo;

  }
#ifdef DBG
  TString dep2(_saldo.string());
#endif  

  // Se non movimentato vado a vedere il saldo  
  if (!_movimentato) 
    _saldo = calcola_saldo_iniziale(g,c,s,indbil);  
  
  return _movimentato;  
}

/**************************************************************
  bool Saldo::calcola_ultima_immissione(int annoes, int annoesprec, int g, int c,
  long s, int indbil)
  {
  //Si considerano i saldi e non piu' i movimenti
  char sezione; 
  int  gruppo, conto, annoe;
  long sottoconto;
  TLocalisamfile saldi(LF_SALDI, FALSE);
  bool esito = TRUE;     
  
  _saldo_iniziale = ZERO;
  _prg_dare       = ZERO;
  _prg_avere      = ZERO;
  _saldo      = ZERO;

  saldi.zero();
  
  if (annoes != 0) saldi.put(SLD_ANNOES,annoes);
  if (g != 0)      saldi.put(SLD_GRUPPO,g);
  if (c != 0)      saldi.put(SLD_CONTO,c);
  if (s != 0)      saldi.put(SLD_SOTTOCONTO,s);
  
  if (saldi.read() == NOERR)
  {
  annoe           = saldi.get_int(SLD_ANNOES);
  gruppo          = saldi.get_int(SLD_GRUPPO);
  conto           = saldi.get_int(SLD_CONTO);
  sottoconto      = saldi.get_long(SLD_SOTTOCONTO);
  _saldo_iniziale = saldi.get_real(SLD_SALDO);
  _prg_dare       = saldi.get_real(SLD_PDARE);
  _prg_avere      = saldi.get_real(SLD_PAVERE);
  sezione         = saldi.get_char(SLD_FLAGSALINI);

  if (sezione == 'A') _saldo_iniziale = -_saldo_iniziale;
  
  if (annoesprec == 0) //all'ultima immissione es.in corso
  {
  if (indbil == 1 || indbil == 2 || indbil == 5)      
  if (_saldo_iniziale == ZERO)
  _saldo_iniziale += saldofin_esprec(annoes,gruppo,conto,sottoconto);   
  
  // i tre valori precedenti vengono utilizzati per la stampa bilancio 
  // di verifica      
  _saldo = _saldo_iniziale + _prg_dare - _prg_avere;
  }
  else //all'ultima immissione es.precedente
  {  
  const int annoesprec = EsePre(annoes);
  
  if (annoesprec != 0) 
  {
  TRectype app = ricerca_progr_prec(annoe-1, gruppo, conto, sottoconto);
  annoe        = app.get_int (SLD_ANNOES);
  _prg_dare    = app.get_real(SLD_PDARE);
  _prg_avere   = app.get_real(SLD_PAVERE);
  }
  _saldo = _prg_dare - _prg_avere;  
  }
  }
  return esito;
  }  
  *****************************************************/

bool TSaldo::ultima_immissione_verifica(int annoes,int g,int c,long s,int indbil)
{
  //Si considerano i saldi e non piu' i movimenti
  char sezione; 
  int  gruppo, conto, annoe;
  long sottoconto;
  bool esito = FALSE;
  TLocalisamfile saldi(LF_SALDI, FALSE);
  
  _saldo_iniziale = ZERO;
  _prg_dare       = ZERO;
  _prg_avere      = ZERO;
  _prg_daresca    = ZERO;
  _prg_averesca   = ZERO;
  _saldo          = ZERO;

  saldi.zero();
  
  saldi.put(SLD_ANNOES,annoes);
  saldi.put(SLD_GRUPPO,g);
  saldi.put(SLD_CONTO,c);
  saldi.put(SLD_SOTTOCONTO,s);
  
  if (saldi.read() == NOERR)
  {
    annoe           = saldi.get_int(SLD_ANNOES);
    gruppo          = saldi.get_int(SLD_GRUPPO);
    conto           = saldi.get_int(SLD_CONTO);
    sottoconto      = saldi.get_long(SLD_SOTTOCONTO);
    _saldo_iniziale = saldi.get_real(SLD_SALDO);
    _prg_dare       = saldi.get_real(SLD_PDARE);
    _prg_avere      = saldi.get_real(SLD_PAVERE);
    sezione         = saldi.get_char(SLD_FLAGSALINI);
    
    if (_prg_dare == ZERO && _prg_avere == ZERO) 
      return esito;
    
    if (sezione == 'A') _saldo_iniziale = -_saldo_iniziale;
    
    if (indbil == 1 || indbil == 2 || indbil == 5)      
      if (_saldo_iniziale == ZERO)
        _saldo_iniziale += saldofin_esprec(annoes,gruppo,conto,sottoconto);   

    esito = TRUE;
    _saldo = _saldo_iniziale + _prg_dare - _prg_avere + _prg_daresca - _prg_averesca;
  }

  return esito;
}  

bool TSaldo::ultima_immissione_bilancio(int annoes,int g,int c,long s,int indbil)
{
  //Si considerano i saldi e non piu' i movimenti
  char sezione; 
  int  gruppo, conto, annoe;
  long sottoconto;
  bool esito = FALSE;
  TLocalisamfile saldi(LF_SALDI, FALSE);
  
  _saldo_iniziale = ZERO;
  _prg_dare       = ZERO;
  _prg_avere      = ZERO;
  _prg_daresca    = ZERO;
  _prg_averesca   = ZERO; 
  _saldo          = ZERO;
  _rec_presente_ec = FALSE;
  _rec_presente_ep = FALSE;
  
  saldi.zero();
  
  saldi.put(SLD_ANNOES,annoes);
  saldi.put(SLD_GRUPPO,g);
  saldi.put(SLD_CONTO,c);
  saldi.put(SLD_SOTTOCONTO,s);
  
  if (saldi.read() == NOERR)
  {
    annoe           = saldi.get_int(SLD_ANNOES);
    gruppo          = saldi.get_int(SLD_GRUPPO);
    conto           = saldi.get_int(SLD_CONTO);
    sottoconto      = saldi.get_long(SLD_SOTTOCONTO);
    _saldo_iniziale = saldi.get_real(SLD_SALDO);
    _prg_dare       = saldi.get_real(SLD_PDARE);
    _prg_avere      = saldi.get_real(SLD_PAVERE);
    _prg_daresca    = saldi.get_real(SLD_PDARESCA);
    _prg_averesca   = saldi.get_real(SLD_PAVERESCA);
    sezione         = saldi.get_char(SLD_FLAGSALINI);
    
    esito = (_saldo_iniziale != ZERO || _prg_dare != ZERO || _prg_avere != ZERO
             || _prg_daresca != ZERO || _prg_averesca != ZERO);
    
    if (sezione == 'A') _saldo_iniziale = -_saldo_iniziale;
    
    _rec_presente_ec = esito;
  }
  
  if (indbil == 1 || indbil == 2 || indbil == 5)      
    if (_saldo_iniziale == ZERO)
      _saldo_iniziale += saldofin_esprec(annoes,g,c,s);

  _saldo = _saldo_iniziale + _prg_dare - _prg_avere + _prg_daresca - _prg_averesca;  
  
  return esito;
} 

TRectype& TSaldo::ricerca_progr_prec (int annoesprec, int g, int c, long s)
{
  TLocalisamfile saldi(LF_SALDI, FALSE);
  //  TRectype rec(LF_SALDI);
  const int oldkey = saldi.getkey();       

  saldi.setkey(1);  
  saldi.zero();

  saldi.put(SLD_ANNOES,annoesprec);
  saldi.put(SLD_GRUPPO,g);
  saldi.put(SLD_CONTO,c);
  saldi.put(SLD_SOTTOCONTO,s);

  if (saldi.read() == NOERR) 
    _rec_presente_ep = TRUE;
  else
  {
    saldi.zero();
    _rec_presente_ep = FALSE;
  }

  *_saldo_ep = saldi.curr();
  saldi.setkey(oldkey);
  
  return *_saldo_ep;
}

//calcolo dei progressivi attuali  
bool TSaldo::prg_attuali(int annoes,TConto& conto,real& prgdare,real& prgavere)
{
  real saldoini  = ZERO;
  real pdare     = ZERO;
  real pavere    = ZERO;
  real pdaresca  = ZERO;
  real paveresca = ZERO;
  char flagsalini;
  int g  = conto.gruppo();
  int c  = conto.conto();
  long s = conto.sottoconto();
  TLocalisamfile saldi(LF_SALDI, FALSE);
  
  saldi.zero();
  saldi.put(SLD_GRUPPO,g);
  saldi.put(SLD_CONTO,c);
  saldi.put(SLD_SOTTOCONTO,s);
  saldi.put(SLD_ANNOES,annoes);
  
  if (saldi.read() == NOERR)
  {
    flagsalini = saldi.get_char(SLD_FLAGSALINI);
    saldoini   = saldi.get_real(SLD_SALDO);
    pdare      = saldi.get_real(SLD_PDARE);
    pavere     = saldi.get_real(SLD_PAVERE);
    pdaresca   = saldi.get_real(SLD_PDARESCA);
    paveresca  = saldi.get_real(SLD_PAVERESCA);
    
    if (flagsalini == 'D')
    {
      prgdare  = saldoini + pdare + pdaresca;
      prgavere = pavere + paveresca; 
    }
    else
    {
      prgdare  = pdare + pdaresca;
      prgavere = saldoini + pavere + paveresca;  
    }
  }
  return TRUE;
}

bool TSaldo::prg_mov_eliminati(int annoes,TConto& conto,real& prgdare,real& prgavere)
{
  real saldoini  = ZERO;
  real pdaresca  = ZERO;
  real paveresca = ZERO;
  char flagsalini;
  int g  = conto.gruppo();
  int c  = conto.conto();
  long s = conto.sottoconto();
  TLocalisamfile saldi(LF_SALDI, FALSE);
  
  saldi.zero();
  saldi.put(SLD_GRUPPO,g);
  saldi.put(SLD_CONTO,c);
  saldi.put(SLD_SOTTOCONTO,s);
  saldi.put(SLD_ANNOES,annoes);
  
  if (saldi.read() == NOERR)
  {
    flagsalini = saldi.get(SLD_FLAGSALINI)[0];
    saldoini   = saldi.get_real(SLD_SALDO);
    pdaresca   = saldi.get_real(SLD_PDARESCA);
    paveresca  = saldi.get_real(SLD_PAVERESCA);
    if (flagsalini == 'D')
    {
      prgdare  = saldoini + pdaresca;
      prgavere = paveresca; 
    }
    else
    {
      prgdare  = pdaresca;
      prgavere = saldoini + paveresca;  
    }
  }
  return TRUE;
}

/************************************
  TLocalisamfile * get_descr_cf (TLocalisamfile * pconti,
  TLocalisamfile * clifo, int g, int c, long s)
  {
  pconti->zero();
  pconti->put (PCN_GRUPPO, g);
  pconti->put (PCN_CONTO , c);
  pconti->put (PCN_SOTTOCONTO, s);

  pconti->read();

  if (pconti->good())
  return pconti;

  TString tipocf = pconti->get(PCN_TMCF);
  long    codcf  = s;

  clifo->zero();
  clifo->put(CLI_CODCF, codcf);
  clifo->put(CLI_TIPOCF, tipocf);

  clifo->read();

  if (clifo->good())
  return clifo;

  return NULL;
  }
  **********************************************/




