// -------------------------------------------------------------
// calcolo liquidazioni
// part 3: utilities
// fv 2-2-94
// --------------------------------------------------------------

#include <config.h>
#include <currency.h>
#include <recarray.h> 
#include <utility.h>

#include "cglib03.h"
#include "cg4300.h"

#include <attiv.h>
#include <nditte.h>

bool TLiquidazione_app::is_trim(int x)
  // TRUE se il mese passato e' un trimestre
{ return x == 3 || x == 6 || x == 9 || x == 12; }

bool TLiquidazione_app::is_month_ok_strict(int x, int month) const
  // TRUE se il mese passato e' compatibile con il regime
  // di liquidazione e (opz) non e' maggiore di quello scelto
{ 
  if (month == -1) month = x;
  return _freqviva == "M" ? ( x > 0 && x <= month) : ( x <= month && is_trim(x));
} 

bool TLiquidazione_app::is_month_plain(int x) const
  // la piu' semplice: vero se mese == _month o se fa parte del
  // trimestre indicato da month
{                             
  bool ok = x == _month;
  if (!ok && _freqviva == "T")
  {
    // aggiusta al trimestre il mese da calcolare 
    int mto = _month;
    mto += 2 - ((mto-1) % 3);   
    ok = x > (mto - 3) && x <= mto;
  }    
  return ok;
}               

bool TLiquidazione_app::is_month_ok(int x, int mtocalc) const
  // TRUE se il mese passato e' compatibile con il mese da calcolare
  // rispetto al regime di liquidazione scelto
{ 
  bool ret = x == mtocalc;
  if (!ret && _freqviva == "T" && mtocalc != 13)
  {  
    // aggiusta al trimestre il mese da calcolare
    mtocalc += 2 - ((mtocalc-1) % 3);   
    ret = x > (mtocalc - 3) && x <= mtocalc; 
  }
  else if (!ret && mtocalc == 13)
  {               
    // per l'annuale ritorna TRUE per tutti i mesi da liquidare
    ret =  x <= 13;
  }      
  return ret;
} 

int TLiquidazione_app::liq_month(int x)
  // ritorna il mese da liquidare (= LIM presente)
  //  che corrisponde al mese passato
{         
  if (x == 13 || _freqviva == "M") 
    return x;
  else 
    return next_trim(x);
}

int TLiquidazione_app::next_trim(int x)  
{                              
  if (x == 13) 
    x = 12;
  return x + (2 - ((x-1) % 3));
}

bool TLiquidazione_app::is_in_liq_period(const TDate& d)
{  
  bool ok = FALSE;
  const int y = atoi(_year);
  if (_freqviva == "M") 
  {
    ok = d.month() == _month && d.year() == y;
  }
  else 
  {   
    const int m = liq_month(_month);
    ok = d.month() > m - 3 && d.month() <= m && d.year() == y;
  }                                          
  return ok;
}

bool TLiquidazione_app::is_first_month(int m)
{
  return _freqviva == "M" ?  m == 1 : m == 3;
}

int TLiquidazione_app::previous_month(int m) const
{
  // vale per LIM (mese o trimestre precedente)
  if (_freqviva == "M")
    return m == 1 ? 1 : m - 1;
  else 
    //return m == 3 ? 3 : m - 3;  // Cambiato il 10/11/2014
    return m <= 6 ? 3 : m >= 10 ? 9 : 6;
}

bool TLiquidazione_app::is_date_ok(const TDate& d, int month, int liqmonth, int year) const
  // TRUE se la data passata va considerata nel
  // ricalcolo dei progressivi mensili per il mese e anno
  // selezionati. Vedi cg4301.cpp per maggiori informazioni
  // sul nuovo filtro di selezione movimenti.
{
  CHECKD(year > 2000, "Invalid year ", year);
  const int regmonth = d.month();
  const int regyear  = d.year();

  // if (regyear() != year) return false;
  if (year < 1998 || _recalc_regis) // Vecchia selezione o calcolo progressivi per stampa registri bollati
  {
    if (regyear != year || regmonth > month)
			return false;
	
    if (month == 13)                                    
      return true; // was regmonth <= month;
    else   
    {
      if (_freqviva == "M")        // Guy!!!
        return regmonth == month;
      else  
        return regmonth >= month-2 && regmonth <= month;
    }
  }
  else   // Nuova selezione dal 1998 in poi
  {
    if (month <= 12)
      return (regyear == year) && ((regmonth == month && liqmonth == 0) || (liqmonth == month));
    else // Annuale, month == 13
      return (regyear == year && liqmonth != 12) || (regyear == year + 1 && liqmonth == 12);
  }
  return false;
}


void TLiquidazione_app::add_ventilation(real iva, real howmuch,  
                                        const char* codiva, const char* other)
{
  _VentItem* vi = NULL;
  int i;
  for (i = 0; i < _vent_arr.items(); i++)
  {
    vi = (_VentItem*)&_vent_arr[i];
    if (vi->_codiva == codiva)
      break;
  }
  if (i == _vent_arr.items())
  {
    _vent_arr.add(vi = new _VentItem);
    vi->_aliquota    = iva;
    vi->_codiva      = codiva;
    vi->_other       = other;
  }
  vi->_totale += howmuch;
}

void TLiquidazione_app::add_vendite(int month, const char* codreg, 
                                    int tipodet, const real& r)
{
  _VendItem* vi = NULL;
  int i;
  for (i = 0; i < _vend_arr.items(); i++)
  {
    vi = (_VendItem*)&_vend_arr[i];
    if (vi->_codreg == codreg && vi->_month == month && vi->_tipodet == tipodet)
      break;
  }
  if (i == _vend_arr.items())
  {
    _vend_arr.add(vi = new _VendItem);
    vi->_codreg      = codreg;
    vi->_month       = month;
    vi->_tipodet     = tipodet;
  }
  vi->_totale += r;
}

void TLiquidazione_app::add_corrisp(int month, const char* codreg, const real& r,
                                    const real& p, int tipodet, const char* codiva,
                                    const char* codatt)
{
  _CorrItem* ci = NULL;
  const int nitems = _corr_arr.items();
  int i;
  for (i = 0; i < nitems; i++)
  {
    ci = (_CorrItem*)&_corr_arr[i];
    if (ci->_codreg == codreg && ci->_month == month &&
        ci->_codiva == codiva && ci->_tipodet == tipodet &&
        ci->_codatt == codatt)
      break;
  }
  if (i == nitems)
  {
    _corr_arr.add(ci = new _CorrItem);
    ci->_codreg      = codreg;
    ci->_month       = month;
    ci->_codiva      = codiva;
    ci->_codatt      = codatt;
    ci->_tipodet     = tipodet;
    ci->_aliquota    = p;
  }
  ci->_totale += r;
}

void TLiquidazione_app::lordo2netto(const real& totale, real& imponibile, real& imposta, const real& aliquota)
{ 
  const int dec = TCurrency::get_firm_dec();
  if (dec == 0)  // Lire
  {
    imposta = (abs(totale) * aliquota)/(aliquota + 1.00);
    imposta.ceil();
    if (totale.sign()  < 0) imposta = -imposta;
    imponibile = totale - imposta;
    // Qui si entra nel regno del mistero: delta e' SEMPRE zero 
    const real delta = totale - imponibile - imposta; 
    if (!delta.is_zero())
      imposta += delta;
  }
  else  // Euro
  {
    imposta = (totale * aliquota)/(aliquota + 1.00);
    imposta.round(dec);
    imponibile = totale - imposta;
  }
}

void TLiquidazione_app::lordo2netto(real& imponibile, real& imposta, const real& aliquota)
{ 
  const real totale = imponibile;
  lordo2netto(totale, imponibile, imposta, aliquota);
}

// Funzione per trovare i PIM: Progressivi liquidazione Iva Mensili. 
bool TLiquidazione_app::look_pim(int month, const char* codatt, const char* codreg, 
                                 const char* tipocr, const char* codiva, int tipodet,  
                                 bool create)
  // ritorna il PIM corrispondente alla chiave passata; se 
  // create = TRUE lo crea se non lo trova. Ritorna se c'era
{
  _pim_r->zero();
  (*_pim_anno)    = _year;
  (*_pim_mese)    = format("%02d", month);
  (*_pim_codreg)  = codreg;
  (*_pim_codiva)  = codiva;
  (*_pim_codatt)  = codatt;
  (*_pim_tipocr)  = tipocr;
  (*_pim_tipodet) = tipodet;
  
  const TString80 s = _pim_r->get("CODTAB"); 
  const bool ok = _pim->read() == NOERR;
  if (!ok && create)
  {
    _pim_r->zero();
    _pim_r->put("CODTAB",s);
    _pim->write();
  }
  return ok;
}

// Le tabelle seguenti (PIS, PRM, PRP) sono vengono introdotte solo dal 1998 in poi.
// Pertanto il loro utilizzo e' significativo in tale periodo.
// Funzione per trovare i PIS: Progressivi liquidazione Iva mensili di cui periodo Successivo
bool TLiquidazione_app::look_pis(int month, const char* codatt, const char* codreg, 
                                 const char* tipocr, const char* codiva, int tipodet,  
                                 bool create)
{  
  _pis_r->zero();
  (*_pis_anno)    = _year;
  (*_pis_mese)    = format("%02d", month);
  (*_pis_codreg)  = codreg;
  (*_pis_codiva)  = codiva;
  (*_pis_codatt)  = codatt;
  (*_pis_tipocr)  = tipocr;
  (*_pis_tipodet) = tipodet;
  const TString80 s = _pis_r->get("CODTAB"); 
  bool ok = _pis->read() == NOERR; 
  
  if (!ok && create)
  {
    _pis_r->zero();
    _pis_r->put("CODTAB",s);
    _pis->write();
  }
  return ok;
}

// Funzione per trovare i PRM: Progressivi Registri iva Mensili. 
bool TLiquidazione_app::look_prm(int month, const char* codatt, const char* codreg, 
                                 const char* tipocr, const char* codiva, int tipodet,  
                                 bool create)
{
  _prm_r->zero();
  (*_prm_anno)    = _year;
  (*_prm_mese)    = format("%02d", month);
  (*_prm_codreg)  = codreg;
  (*_prm_codiva)  = codiva;
  (*_prm_codatt)  = codatt;
  (*_prm_tipocr)  = tipocr;
  (*_prm_tipodet) = tipodet;
  
  const TString80 s = _prm_r->get("CODTAB"); 
  bool ok = _prm->read() == NOERR;
  
  if (!ok && create)
  {
    _prm_r->zero();
    _prm_r->put("CODTAB",s);
    _prm->write();
  }
  return ok;
}

// Funzione per trovare i PRP: Progressivi Registri iva mensili di cui da periodo Precedente 
bool TLiquidazione_app::look_prp(int month, const char* codatt, const char* codreg, 
                                 const char* tipocr, const char* codiva, int tipodet,  
                                 bool create)
{
  bool ok = false;

  _prp_r->zero();
  (*_prp_anno)    = _year;
  (*_prp_mese)    = format("%02d", month);
  (*_prp_codreg)  = codreg;
  (*_prp_codiva)  = codiva;
  (*_prp_codatt)  = codatt;
  (*_prp_tipocr)  = tipocr;
  (*_prp_tipodet) = tipodet;
  
  const TString80 s = _prp_r->get("CODTAB"); 
  ok = _prp->read() == NOERR;
  if (!ok && create)
  {
    _prp_r->zero();
    _prp_r->put("CODTAB",s);
    ok  = _prp->write() == NOERR;
  }
  return ok;
}

bool TLiquidazione_app::look_plm(int m, const char* att, bool create)
{
  _plm_r->zero();
  (*_plm_codatt) = format("%6s", att);
  (*_plm_mese)   = format("%02d",m);
  (*_plm_anno)   = _year;

  const TString16 s = _plm_r->get("CODTAB");
  const bool ok = _plm->read() == NOERR;
  
  if (!ok && create)
  {
    _plm_r->zero();
    _plm_r->put("CODTAB",s);
    _plm->write();
  }  
  // crea/posiziona tabelle gemelle PAM, PUM, POM
  look_pam(m, att, !ok);
  look_pum(m, att, !ok);    
  look_pom(m, att, !ok);    
  
  return ok;
}

bool TLiquidazione_app::look_pia(int m, const char* a, const char* cod1, const char* cod2, bool create)
{
  bool ok = FALSE;

  (*_pia_codatt) = format("%6s", a);
  (*_pia_mese)   = format("%02d",m);
  (*_pia_anno)   = _year;
  (*_pia_codord) = cod1;
  (*_pia_codcom) = cod2;

  TString s = _pia_r->get("CODTAB");
  _pia->read();
  ok = _pia->good();
  
  if (!ok && create)
  {
    _pia_r->zero();
    _pia_r->put("CODTAB",s);
    _pia->write();
  }  
  return ok;
}

bool TLiquidazione_app::look_pum(int m, const char* a, bool create)
{
  bool ok = FALSE;

  _pum->zero();
  (*_pum_codatt) = format("%6s", a);
  (*_pum_mese)   = format("%02d",m);
  (*_pum_anno)   = _year;

  TString s = _pum->get("CODTAB");
  _pum->read();
  ok = _pum->good();
  
  if (!ok && create)
  {
    _pum->zero();
    _pum->put("CODTAB",s);
    _pum->write();
  }
  return ok;
}

bool TLiquidazione_app::look_pem(TTable & pem, int codreg)
{
  TString8 key;

	key.format("%04d%02d", atoi((const char *) _year), codreg);
  pem.put("CODTAB", key);
  bool ok = pem.read() == NOERR;
  if (!ok)
  {
    pem.zero();
	  pem.put("CODTAB", key);
    ok = pem.write() == NOERR;
  }
  return ok;
}

bool TLiquidazione_app::look_pom(int m, const char* a, bool create)
{
  _pom->zero();
  (*_pom_codatt) = format("%6s", a);
  (*_pom_mese)   = format("%02d",m);
  (*_pom_anno)   = _year;

  const TString16 s = _pom->get("CODTAB");
  bool ok = _pom->read() == NOERR;
  
  if (!ok && create)
  {
    _pom->zero();
    _pom->put("CODTAB",s);
    ok = _pom->write() == NOERR;
  }
  return ok;
}

bool TLiquidazione_app::look_pam(int m, const char* a, bool create)
{
  _pam->zero();
  (*_pam_codatt) = format("%6s", a);
  (*_pam_mese)   = format("%02d",m);
  (*_pam_anno)   = _year;

  const TString16 s = _pam->get("CODTAB");
  
  const bool ok = _pam->read() == NOERR;
  
  if (!ok && create)
  {
    _pam->zero();
    _pam->put("CODTAB",s);
    _pam->write();
  }
  return ok;
}

bool TLiquidazione_app::look_lim(int m, bool create)
{
  _lim_r->zero();
  (*_lim_mese)   = format("%02d",m);
  (*_lim_anno)   = _year;

  const TString8 s = _lim_r->get("CODTAB");
  const bool ok = _lim->read() == NOERR;

  if (!ok && create)
  {
    _lim_r->zero();
    _lim_r->put("CODTAB",s);
    _lim->write(); 
  }

  // crea o posiziona la tabella gemella LAM
  look_lam(m, !ok);   
  
  return ok;
}

bool TLiquidazione_app::look_lam(int m, bool create)
{
  _lam_r->zero();
  (*_lam_mese)   = format("%02d",m);
  (*_lam_anno)   = _year;

  const TString8 s = _lam_r->get("CODTAB");
  const bool ok = _lam->read() == NOERR;
  if (!ok && create)
  {
    _lam_r->zero();
    _lam_r->put("CODTAB",s);
    _lam->write();
  }
  return ok;
}

int TLiquidazione_app::count_activities() const
{
  TRelation rel(LF_ATTIV);
  TRectype& rec = rel.curr();
  rec.put(ATT_CODDITTA, get_firm());
  TCursor cur(&rel, "", 1, &rec, &rec);
  return cur.items();
}

bool TLiquidazione_app::look_pla(const char* a, bool create)
{
  // forza il tipoatt a 1
  TString16 buf(a);
  buf.ltrim();
  buf.rtrim(1);
  buf << "1";
  //while (buf.len() < 6)  buf.insert("0");
  buf.right_just(6, '0');
  
  _pla_r->zero();
  (*_pla_ditta)  = format("%05ld", get_firm());
  (*_pla_anno)   = _year;
  (*_pla_codatt) = buf;

  const TString16 s = _pla_r->get("CODTAB");
  bool ok = _pla->read() == NOERR;
  if (!ok && create)
  {
    _pla->zero();
    _pla_r->put("CODTAB",s);
    _pla->write();
  }
  return ok;
}

bool TLiquidazione_app::look_reg(const char* reg)
{
  TString16 s; s << _year; s << format("%-3s",reg);
  bool rt = TRUE;
  const bool is_key = _reg_arr.is_key(s);
  if (is_key)
    _reg->curr() = (TRectype&) _reg_arr[s];
  else
  {
    _reg_r->zero();
    _reg_r->put("CODTAB",s);
    if (_reg->read() == NOERR)
      _reg_arr.add(s,_reg->curr());
    else 
      rt = FALSE;
  }
  return rt;
}

bool TLiquidazione_app::look_iva(const char* cod)
{
  bool rt = true;

  TString4 s = cod; s.trim();
  const bool is_key = _codiva_arr.is_key(s);
  
  if (is_key)
    _iva->curr() = (const TRectype&)_codiva_arr[s];
  else
  {
    _iva->zero();
    _iva->put("CODTAB", s);
    rt = _iva->read() == NOERR;
    if (rt)
      _codiva_arr.add(s, _iva->curr());
  }
 
  return rt;
}

bool TLiquidazione_app::look_ppa(int month, const char* codatt, int type, bool create)
{
  _ppa->zero();
  (*_ppa_year)   = _year;
  (*_ppa_month)  = format("%02d",month);
  (*_ppa_codatt) = format("%6s", codatt);
  (*_ppa_kind)   = type;
  TString ctab   = _ppa_r->get("CODTAB");
  _ppa->read();

  bool ok = _ppa->good();
  
  if (!ok && create)
  {
    _ppa_r->zero();
    _ppa_r->put("CODTAB",ctab);
    _ppa->write();
  }
  return ok;
}


bool TLiquidazione_app::look_del(int month, int type, bool create)
{ 
  // se chiamata con il flag di creazione, aggiorna le info su
  // codici tributo, concessione, conto fiscale anche se la
  // delega esiste gia'
  
  // Molto pericoloso chiamare con create = TRUE:
  // se e' gia' stata fatta l'estrazione versamenti 
  // e l'utente cambia titcf e isdel sull'anagrafica
  // sono c... suoi!!! (Maurizio)
  // deve rifarsi la delega con l'ESTRAZIONE VERSAMENTI 
  // io l'ho lasciato per rispetto del lavoro altrui 
  
  const long ditta = _nditte->curr().get_long("CODDITTA");
  _del->zero();
  (*_del_ditta)  = format("%05ld", ditta);
  (*_del_anno)   = _year;
  (*_del_mese)   = format("%02d", month);
  (*_del_tipo)   = format("%1d",  type);     
  
  const TString16 ctab = _del->get("CODTAB");
  bool ok = _del->read() == NOERR;

  if (!ok && create)
  {
    _del->zero();
    _del->put("CODTAB",ctab);  
  }
  
  if (create) 
  {
    // vedi se titolare conto fiscale
    bool titcf = FALSE;
    bool isdel = FALSE;
    int uffiva;
		TString16 key;

		key.format("%s|%s", (const char *)_nditte->lfile().get("TIPOA"), (const char *) _nditte->lfile().get("CODANAGR"));
	  
		const TRectype & anag = cache().get(LF_ANAG, key);
    if (!anag.empty())
    {
      titcf = anag.get_bool("TITCF");
      isdel = anag.get_long("TIPOSTDEL") == 0l;    
      uffiva = anag.get_int("UFFIVA");      
    }

    TString16 con;
    TString uva;
    if (titcf)
      look_conc(con, uva); // Legge la concessione se titolare conto fiscale

    if (!titcf || isdel)
    {
      // non titolare conto fiscale oppure paga con delega:
      // cerca banca
      // codici ABI e CAB da anagrafica ditte
      TString16 abi, cab;
      abi = _nditte->lfile().get("ABIBAN");
      cab = _nditte->lfile().get("CABBAN");    
      if (abi.empty()) 
      {
        TConfig c (CONFIG_STUDIO, "cg");
        abi = c.get("CodABI");
        cab = c.get("CodCAB");
      } 
      _del->put("S7", abi);
      _del->put("S8", cab);
      if (titcf && isdel) // Se e' titolare CF e stampa la delega, va riportata anche la conc
      {
        _del->put("S9", con);
        _del->put("S2", uva);
      }
      else
        _del->put("S9", "");
    }
    else
    {
      // non usa delega bensi' bollettino o distinta:
      // cerca concessione comune
      // infila ufficio concessione in S9
      // e descrizione comune in S2
      _del->put("S9", con);
      _del->put("S2", uva);
      _del->put("S7", "");
      _del->put("S8", "");
    }
  } //fine create   
    
  // le descrizioni sulla delega non vengono 
  // memorizzate dai vari programmi di gestione
  // e estrazione ma solo qui.
  if (ok)
  {
    int uffiva;
		TString16 key;

		key.format("%s|%s", (const char *)_nditte->lfile().get("TIPOA"), (const char *) _nditte->lfile().get("CODANAGR"));
	  
		const TRectype & anag = cache().get(LF_ANAG, key);
    if (!anag.empty())
      uffiva = anag.get_int("UFFIVA");      

    TString16 abi = _del->get("S7");
    TString16 cab = _del->get("S8");  
    TString16 con = _del->get("S9");

    // descrizione banca
    if (abi.not_empty())
    {
     TString codban = format("%05ld", atol(abi));
     if (!cab.empty()) codban << format("%05ld", atol(cab)); 
     const TRectype & ban = cache().get("%BAN", codban);
     if (!ban.empty())
     {                          
       TString desban(ban.get("S0"));
       _del->put("S1", desban);
     }
     //che rottura: ogni giorno alla prassi cambiano idea!!!
     TString16 coduff = format("%03d", uffiva);
     const TRectype & uiv = cache().get("%UIV", coduff);
     if (!uiv.empty())
     {                          
       TString desiva(uiv.get("S0"));
       _del->put("S2", desiva);
     }
    }
    // Descrizione cod. concessione
    if (con.not_empty())
    {
      TString uva;
      if (look_conc(con, uva))
        _del->put("S2", uva);
    }
  }
  // scrive codice tributo
  int ctri = 6000;
  if (month == 13 && type == 7) 
    ctri = 6035;           // acconto IVA annuale (trimestrali?)
  else if (month == 13 && type == 1)
    ctri = 6099;           // IVA annuale
   else if (month < 13 && type == 7)
      ctri = 6013;           // acconto mensile
    else if (month < 13 && type == 1)  // regular
      ctri = _freqviva == "M" ? 6000 + month : 6030 + (month/3); 
    
  _del->put("S6", format("%d",ctri));

  if (!ok) _del->write();
  else _del->rewrite();    

  return ok;
}

bool TLiquidazione_app::look_lia(long ditta, bool create, int year)
{
  if (year <= 0) year = atoi(_year);      
  if (ditta <= 0l) ditta = get_firm();

  TString16 y; y.format("%05ld%04d", ditta, year);
  _lia->put("CODTAB", y);
  const bool ok = _lia->read() == NOERR;
  if (!ok)
  {
    _lia->zero();
    _lia->put("CODTAB", y);
    _lia->put("S7", _freqviva);
    if (create)
      _lia->write();
  }
  return ok;
}

real TLiquidazione_app::result_liq(int month)
  // risultato esatto della liquidazione del mese month, <0 a credito
  // > 0 a debito; comprende TUTTI, anche il conguaglio prorata in annuale
{  
  real r;                               
  // ulteriori detrazioni, acconti, versamenti,
  // rettifiche, conguagli sono gia' compresi in R0
  if (look_lim(month))
    r = _lim->get_real("R0");
  return r;
}                                           
  
real TLiquidazione_app::iva_da_riportare(int month)
{ 
  real idr;
  const int anno = atoi(_year); 
  if (month > 12)
  { 
    if (_ver->read(anno, 12) == NOERR)
      idr = _ver->get(I_ANNUALE);
  }
  else
  {
    if (_ver->read(anno, month) == NOERR)
      idr = _ver->get(I_PERIODICO);
  }
  return idr;
}

real TLiquidazione_app::debt_prec(int month)
{
  real r;
  if (!is_first_month(month))
  {
    if (look_lim(previous_month(month)))
    {
      r = result_liq(previous_month(month));
      if (!(r > ZERO && r < iva_da_riportare(month)))
        r = ZERO;
    }
  } 
  return r;
}


real TLiquidazione_app::credito_prec(int month)
  // ritorna l'appropriato credito precedente al mese in corso
{
  real c = ZERO;
  if (!(_freqviva =="M" || is_trim(month)))  // Aggiunto il 10/11/2014
    return c; 
  
  const bool lia_ok = look_lia();
  const bool credito_visibile = _lia->get("S9") != "NV";

  if (is_first_month(month))
  {
    // credito inizio anno
    if (lia_ok) 
    {                                             
      // Dal 2000 se S9="NV" il credito precedente non esiste piu'
      if (credito_visibile)
        c = _lia->get_real("R0");
    }
    // e' positivo o 0
  }
  else
  {
    c = result_liq(previous_month(month)); 
    if (c < ZERO) 
      c = -c; 
    else 
      c = ZERO;
    
    // Dal 2000 se S9="NV" il credito trasferito non esiste piu'
    if (credito_visibile)
    {
      // Nel caso di trimestrali considera dal trimestre corrispondente a 
      // quello impostato+1. Ad es. se m == 1 considera dal I trim. (m=3)
      // se m == 2 idem (m=3). Se m == 3 considera dal II trim. (m=6).
      const int crm = _lia->get_int("I0") + 1;
      if (lia_ok && crm > 1) // Vale dal mese successivo a quello impostato
      {
        // Toglie il Credito Trasferito 
        if (month == liq_month(crm))
          c -= _lia->get_real("R15");
      }
    }
  }

  return c;
}

real TLiquidazione_app::credito_costo_prec(int month)
  // ritorna l'appropriato credito di costo precedente al mese in corso
  // (travel agency only)
{
  real c = ZERO;
  if (is_first_month(month) || month == 13)
  {
    // credito inizio anno
    if (look_lia()) 
      c = _lia->get_real("R5");
  }
  else
  {
    if (look_lim(previous_month(month)))
      // qui il rimborso non c'e'
      c = _lim->get_real("R2");
  }
  look_lim(month);
  return c;
}


real TLiquidazione_app::versamenti_IVA(int month, const char* types, bool intr)
{ 
  real ret(0.0); TToken_string typ(types);

  for (int i = 0; i < typ.items(); i++)
  {                      
    int tp = typ.get_int(i);
    if (look_del(month,tp))         
    {
      real importo_dovuto_non_arrotondato(_del->get_real("R2"));
      real interessi(_del->get_real("R1"));
      real importo_dovuto_arrotondato(_del->get_real("R0"));
      real work(importo_dovuto_non_arrotondato);
      
      round_imposta(work);
      if (_month == 13 && _freqviva == "T" &&  importo_dovuto_arrotondato == work)
        ret += importo_dovuto_non_arrotondato; // Questo e' l'importo lordo non arrotondato!!
      else
        ret += importo_dovuto_arrotondato;
      //gli interessi vengono memorizzati solo se si 
      //devono pagare (=> nessun controllo su intra)
      if (!(_is_visliq && _freqviva == "T" && _month != 13)) // toglie gli interessi se non siamo in visualiz. o la ditta non e' TRIM o siamo in annuale
        ret -= interessi;    // al netto degli interessi
      // In caso di 13a liq e per trimestrali... devo fare la somma 
      // degli importi netti dovuti, ecco perche' leggo R2,
      // perche togliendo poi gli interessi ottengo il dovuto netto!
      // Questa casistica vale pero' solo se in R2 c'e' qualcosa(!=0) ed 
      // e' relativo all'importo presente in R0. Ovvero:
      // nel caso si estraggano i versamenti trimestrali, i campi R2
      // vengono correttamente compilati. Se poi si modificano a mano i 
      // valori di R0 (tramite gestione versamenti, visualizzazione o 
      // calcolo acconti) tale importo non e' piu' consistente, ecco quindi
      // il controllo effettuato tra R0 e ROUND(R2). In realta' sarebbe piu'
      // oppurtuno che in gestione versamenti, visualizzazione liquidazione e
      // calcolo acconti, vi sia la possibilita' di modificare anche R2.
      // Tutto cio' e' relativo all'errore MI3386.
    }
  }
  return ret;
}

// Arrotonda intelligentemente alle 1000 Lire, al centesimo di Euro o all'unit� di Euro
void TLiquidazione_app::round_imposta(real& d) const
{
  TIva_round ir;
  ir.round(d);
}

void TLiquidazione_app::round_al_centesimo(real& d) const
{ d.round(2); }


// Ritorna il parametro della liquidazione differita per la ditta corrente, cosi come 
// e' scritto sui parametri liquidazione (LIA)
// Se si passa 0 (default) vede prende la ditta correntemente in corso di calcolo
// Analogamente per l'anno
bool TLiquidazione_app::is_acconto_differito(long firm, int year)
{
  bool diff = false;
  const long d = (firm <= 0) ? _nditte->curr().get_long(NDT_CODDITTA) : firm;
  const int  y = (year <= 0) ? atoi(_year) : year;
  if (look_lia(d, y > 0, y))   // 26/03/2012 aggiunto   ,y)
    diff = _lia->get_bool("B1");

  return diff;
}

real TLiquidazione_app::aliquota_agvia()
{
  real r;
  const TString& codagv = ini_get_string(CONFIG_STUDIO, "cg", "CodAgv");
  if (codagv.full() && look_iva(codagv)) // Controlla se � vuoto! CM600475
    r = _iva->get_real("R0");
  return r;
}


real TLiquidazione_app::interesse_trimestrale(int month)
{
  month--; month /= 3;
  real r(_ver->get(month)); // month varia da 0 a 4, proprio come da P_1_TRIMESTRE... in poi
  return r;
}

bool TLiquidazione_app::look_conc(TString& uffcon, TString& uffiva)
{                       
  // piazza nelle TString passate: l'ufficio concessioni
  // l'ufficio IVA. Quest'ultimo e' preso dall'anagrafica se
  // c'e', dal comune (primo non vuoto) se non
  
  // Assume _nditte correctly positioned
  const TString4 ana(_nditte->lfile().get("TIPOA"));
  const TString8 codana(_nditte->lfile().get("CODANAGR"));
  // look anagrafica
	TString16 key;
	key.format("%s|%s", (const char *) ana, (const char *) codana);
	  
	const TRectype & anag = cache().get(LF_ANAG, key);
  if (anag.empty()) return false;
  
  // becca comune residenza fiscale
  TString4 com(anag.get("COMRF")); 
  // se non c'e', residenza
  if (com.empty())
    com = anag.get("COMRES");
  
  if (com.empty()) 
    return false;
  
  // becca comune
	key.format("|%s", (const char *) com);
	  
	const TRectype  comuni = cache().get(LF_COMUNI, key);

  if (comuni.empty()) return FALSE;
  
  const int uffa = comuni.get_int("UFFCONC");
  if (uffcon.empty())
    uffcon = format("%03d",uffa);
  if (uffcon.not_empty())
  {
    const TRectype & ucc = cache().get("%UCC", uffcon);
    if (!ucc.empty())
      uffiva = ucc.get("S0");
  }   
  
  return true;
}

real TLiquidazione_app::credito_utilizzato(int month, bool iva, bool f24) const
{
  real credito;

  TTable lim("LIM");
  TString16 cod;
  for (int m = 1; m <= month; m++)
  {       
    cod.format("%s%02d", (const char*)_year, m);
    lim.put("CODTAB", cod);
    if (lim.read() == NOERR)
    {
      if (iva && m < month)
        credito += lim.get_real("R15"); // Credito utilizzato IVA
      if (f24 && m < 13)
        credito += lim.get_real("R16"); // Credito utilizzato F24
    }
  }
  
  return credito;
}