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

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

#include "cg4300.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(int x, int month)
     // 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_first_month(int m)
{
  return _freqviva == "M" ? 
    m == 1 : m == 3;
}

int TLiquidazione_app::previous_month(int m)
{
  if (m == 13) m = 12;
  if (_freqviva == "M")
    return m == 1 ? 1 : m - 1;
  else return m == 3 ? 3 : m - 3;
}

bool TLiquidazione_app::check_month(int m, int m2)
     // se si sta ricalcolando una liquidazione 
     // annuale di check, ritorna TRUE per tutti i 
     // mesi, altrimenti solo per quello in corso
     // di calcolo
{
  return (_isannual || _isriepilogo) ? m < 13 : m == m2; 
}

bool TLiquidazione_app::is_date_ok(TDate& d, int month)
     // TRUE se la data passata va considerata nel
     // ricalcolo dei progressivi per il mese e anno
     // selezionati
{
  if (d.month() > month || d.year() != atoi(_year))
    return FALSE;
  return _freqviva == "M" ? 
    (d.month() == month):
  ((month - d.month()) >= 0 &&  
   (month - d.month()) < 3);
}


void TLiquidazione_app::add_ventilation(real iva, real howmuch,  const char* codiva)
{
  _VentItem* vi = NULL;
  for (int 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->_totale += howmuch;
}

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

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


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

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

  _plm_r->zero();
  (*_plm_codatt) = a;
  (*_plm_mese)   = format("%d",m);
  (*_plm_anno)   = _year;

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

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

  _ptm->zero();
  (*_ptm_codatt) = a;
  (*_ptm_mese)   = format("%d",m);
  (*_ptm_anno)   = _year;

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

bool TLiquidazione_app::look_lim(int m, bool create)
{
  bool ok = FALSE;

  _lim_r->zero();
  (*_lim_mese)   = format("%d",m);
  (*_lim_anno)   = _year;

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

bool TLiquidazione_app::look_pla(const char* a, bool create)
{
  bool ok = FALSE;
  _pla_r->zero();

  // forza il tipoatt a 1
  char buf[10]; strcpy(buf,a);
  buf[strlen(buf) - 1] = '1';
  
  (*_pla_codatt) = buf;
  (*_pla_anno)   = _year;

  TString s = _pla_r->get("CODTAB");
  _pla->read();
  ok = _pla->good();
  
  if (!ok && create)
    {
      real es_b1, es_b2, es_b3, prorata;
      // alla creazione del PLA
      // si prendono i valori di prorata e plafond dall'anno scorso
      // e (TBI) si controllano incompatibilita' con la normativa
       
      _pla_r->zero();
      (*_pla_codatt) = buf;
      (*_pla_anno)   = atoi(_year) - 1;
      if (_pla->read() == NOERR)
	  {
	    es_b1 = _pla->get_real("R1");
	    es_b2 = _pla->get_real("R2");
	    es_b3 = _pla->get_real("R3");
	    es_b1 = _pla->get_real("R9");
	  }
      _pla->zero();
      _pla_r->put("CODTAB",s);
      _pla->put("R5",es_b1);
      _pla->put("R6",es_b2);
      _pla->put("R7",es_b3);
      _pla->put("R8",prorata);
      _pla->write();
    }
  return ok;
}

bool TLiquidazione_app::look_reg(const char* reg)
{
  _reg_r->zero();
  TString s(12); s << _year; s << format("%-3s",reg);
  _reg_r->put("CODTAB",(const char*)s);
  _reg->read();
  return _reg->good();
}

bool TLiquidazione_app::look_iva(const char* cod)
{
  _iva->zero();
  _iva->put("CODTAB",cod);
  _iva->read();
  return _iva->good();
}

bool TLiquidazione_app::look_ppa(int month, const char* codatt, int type, bool create)
{
  _ppa->zero();
  (*_ppa_year)   = _year;
  (*_ppa_month)  = month;
  (*_ppa_codatt) = 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)
{
  TString ditta = _nditte->curr().get("CODDITTA");
  _del->zero();
  (*_del_ditta)  = ditta;
  (*_del_anno)   = _year;
  (*_del_mese)   = month;
  (*_del_tipo)   = type;
  TString ctab   = _del->get("CODTAB");
  _del->read();

  bool ok = _del->good();

  if (!ok && create)
    {
      _del->zero();
      _del->put("CODTAB",ctab);
      _del->write();
    }
  return ok;
}

bool TLiquidazione_app::look_lia(bool create, int year)
{
  if (year == 0) year = atoi(_year);
  TString16 y; y << year;
 
  _lia->zero();
  _lia->put("CODTAB", y);
  _lia->read();
  const bool ok = _lia->good();
  if (!ok && create)
  {
    _lia->zero();
    _lia->put("CODTAB", y);
    _lia->put("S7", _freqviva);
		_lia->write();
	}
	return ok;
}


real TLiquidazione_app::credito_prec(int month)
     // ritorna l'appropriato credito precedente al mese in corso
     // lascia PLM posizionata sul mese passato
{
  real c(0.0);

  if (is_first_month(month))
  {
    look_lia();
    if (_lia->status() == NOERR)
    {
  	 	c = _lia->get_real("R0");
		if (!c.is_zero()) return c;
    }
    int yr = atoi(_year) - 1;
    _lim->zero();
    *_lim_anno = yr;
    *_lim_mese = 12;
    if (_lim->read() == NOERR)
	// considera anche il rimborso
	c = _lim->get_real("R0") - _lim->get_real("R1");
   // e le eventuali rettifiche a debito
    real rett = _lim->get_real("R5");
    if (rett.sign() > 0)
	c -= rett;
    // e l'acconto versato a dicembre
    _del->zero();
    TString ditta = _nditte->curr().get("CODDITTA");
    *_del_ditta   = ditta;
    *_del_anno    = yr;
    *_del_mese    = 12;
    *_del_tipo    = 7;
    if (_del->read() == NOERR)
	c -= _del->get_real("R0");
  }
  else
  {
     bool ok = look_lim(previous_month(month));
     if (!ok || !_lim->get_bool("B0"))
	 {
	   update_firm(previous_month(month), FALSE);
	   look_lim(previous_month(month));
	 }                         
	 // toglie il rimborso chiesto
     c = _lim->get_real("R0") + _lim->get_real("R1"); 
     real rett = _lim->get_real("R5");
     if (rett.sign() > 0)
	 c -= rett;
  }
  look_lim(month);
  
  if (c.sign() < 0) c = abs(c); else c = real(0.0);
  return c;
}

real TLiquidazione_app::credito_costo_prec(int month, const char* codatt)
// ritorna l'appropriato credito di costo precedente al mese in corso
// (travel agency only)
{
  real c = 0.0;
  if (is_first_month(month))
    {
      int yr = atoi(_year) - 1;
      _lim->zero();
      *_lim_anno = yr;
      *_lim_mese = 12;
      if (_lim->read() == NOERR) c = _lim->get_real("R2");
    }
  else
    {
      bool ok = look_lim(previous_month(month));
      if (!ok || !_lim->get_bool("B0"))
	{
	  // Super Prassi a questo punto vorrebbe una update_firm
	  update_att(previous_month(month), codatt, FALSE);
	  look_lim(previous_month(month));
	}
      // qui il rimborso non c'e'
      c = _lim->get_real("R2");
    }
  look_lim(month);
  return c;
}


real TLiquidazione_app::aliquota_agvia()
{
  TConfig cnf(CONFIG_STUDIO);
  look_iva(cnf.get("CodAgv"));
  real r = _iva->get_real("R0");
  return r;
}


real TLiquidazione_app::interesse_trimestrale(int month)
{
  month /= 3; month--;
  TConfig cnf(CONFIG_STUDIO);
  real r = cnf.get("InTr", NULL, month);
  return r;
}
