// -----------------------------------------------------------------
// Calcolo liquidazione
// part 4: casi particolari
// fv 2-2-94
// -----------------------------------------------------------------

#include "cg4300.h"

void CG4300_App::add_plafond(int month, const char* codatt, int type,
			     real& howmuch, bool intra)
{
  look_ppa(month,codatt,type);

  real r0 = _ppa_r->get("R0");
  real r1 = _ppa_r->get("R1");
  real r2 = _ppa_r->get("R2");

  if (intra) r1 += howmuch; else r0 += howmuch;

  if (r2 < (r0+r1))
    describe_error("Acquisti in eccesso rispetto al plafond disponibile",
		   codatt);

  r2 -= (r0+r1);
	if (r2.sign() < 0) r2 = 0.0;

  _ppa_r->put("R0",r0);
  _ppa_r->put("R1",r1);
  _ppa_r->put("R2",r2);
  
  _ppa->rewrite();
}    

void CG4300_App::zero_plafond (int month, const char* codatt)
{
  for (int jj = 1; jj <= 3; jj++) // three types of plafond
    {
      real r;
      look_ppa(month,codatt,jj,TRUE);
      if (is_first_month(month))
	{
	  r = (jj == 1 ? _p8 : (jj == 2 ? _p8b : _p9)); 
	}
      else 
	{
	  long rn = _ppa->recno();
	  
	  // se non c'e' quello del mese prima c'e' poco da fare,
	  // si ricalcola tutto
	  if (!look_ppa(previous_month(month),codatt,jj))
	    // mazza che bella chiamata ricorsiva
	    {
	      if (!update_att(previous_month(month),codatt, FALSE))
		describe_error("Progressivi plafond non ricalcolati per "
			       "i mesi precedenti: possibili errori",
			       codatt);
	      look_ppa(previous_month(month),codatt,jj);
	    }
	  r = _ppa_r->get_real("R2");
	  _ppa->readat(rn);
	}
      _ppa_r->put("R2",r);
      _ppa_r->put("R0","");
      _ppa_r->put("R1","");
      _ppa->rewrite();
    } // for tipo esenzione plafond      
}  

void CG4300_App::describe_plafond(int month, const char* codatt)
{
  if (month == 13) month = 12;
  // prepara la descrizione del riepilogo da stampare e lo accoda
  real t1, t2, t3;
  _DescrItem* d = new _DescrItem(PLAFOND);

  for (int jj = 1; jj <= 3; jj++) // three types of plafond
    {
      t1 = 0.0; t2 = 0.0; t3 = 0.0;
      for (int m = 1; m <= month; m++) 
	{
	  if (look_ppa(m,codatt,jj))
	    {
	      t1 = _ppa->get_real("R0");
	      t2 = _ppa->get_real("R1");
	      t3 = _ppa->get_real("R2");
	    }
	}
      switch (jj)
	{
	case 1: d->_r0 = t1; d->_r1 = t2; d->_r2 = t3; break;
	case 2: d->_r3 = t1; d->_r4 = t2; d->_r5 = t3; break;
	case 3: d->_r6 = t1; d->_r7 = t2; d->_r8 = t3; break;
	}  
    } // for tipo esenzione plafond 
  
  _descr_arr.add(d);
}


// ricalcolo della malefica ventilazione
void CG4300_App::recalc_ventilation(int month, const char* codatt)
{
  if (_vend_arr.items() == 0) return;

  TString att(codatt);
  look_pla(att);
  _pla->put("B0","X");
  _pla->rewrite();
  _isvent = TRUE;

  // 1) ricalcola i pim dei mesi dal primo al corrente se necessario
  for (int m = 1; m < month; m++)
    if (is_month_ok(m)) update_att(m,codatt, FALSE);

  _vent_arr.destroy();
  
  for (m = 1; m <= month; m++)
    {
      if (is_month_ok(m))
	{
	  // aggiunge gli acquisti del mese m operando sui pim
	  for (_pim->first(); !_pim->eof(); _pim->next())
	    {
	      // se e' acquisto beni per rivendita
	      int tipocr = atoi(*_pim_tipocr);
	      int mese   = atoi(*_pim_mese);
	      TString att(codatt); 
	      if (tipocr == 1 && mese == m && 
		  att == (const char*)(*_pim_codatt))
		
		{
		  look_iva(*_pim_codiva);

		  // soltanto normali ed esenti IVA sono base di riparto
		  if (_iva->get("S1").empty() ||
		      _iva->get("S1") == "ES")
		    {
		      real lurd = _pim->get_real("R0");
		      lurd     += _pim->get_real("R1");
		      real perc = _iva->get_real("R0");
		      TString other = _iva->get("S6");
		      if (!other.empty())
			{
			  // ventila a un altro codice
			  look_iva(other);
			  perc = _iva->get_real("R0");
			}
		      add_ventilation(perc/100.0, lurd, *_pim_codiva);
		    }
		}
	    }
	}
    }
  
  // 2) calcola totale acquisti su tutte le aliquote
  real totacq = 0.0;
  real totven = 0.0;
  
  for (int j = 0; j < _vent_arr.items(); j++)
    {
      _VentItem* vv = (_VentItem*)&_vent_arr[j];
      totacq += vv->_totale;
    }
  
  // 3) ricalcola (solo per il mese in corso!) operando sull'array 
  for (int i = 0; i < _vend_arr.items(); i++)
    {
      _VendItem* vi = (_VendItem*)&_vend_arr[i];
      if (vi->_month != month)
	continue;
     
      // questo serve solo per il prospettino di m.
      totven += vi->_totale;

      // 3.2) calcola percentuali di ripartizione e prepara l'affettatrice
      TDistrib dst(vi->_totale,ROUND_LIRA);
      for (j = 0; j < _vent_arr.items(); j++)
	{
	  _VentItem* vv = (_VentItem*)&_vent_arr[j];
	  dst.add(vv->_totale/totacq);
	}
      
      // 3.3) affetta l'importo
      for (j = 0; j < _vent_arr.items(); j++)
	{
	  _VentItem* vv = (_VentItem*)&_vent_arr[j];
	  real imponibile = dst.get();
	  real imposta    = imponibile*vv->_aliquota;
	  imposta.round(ROUND_LIRA);

	  // aggiusto l'IVA vendite nei plm
	  look_plm(month, codatt);
	  real ive = _plm->get_real("R0");
	  ive     += imposta;
	  _plm->put("R0",ive);
	  _plm->rewrite();

	  // Aggiorno i luridi pim
	  look_pim(month, codatt, vi->_codreg, "0", vv->_codiva, TRUE);
	  
	  imponibile += _pim->get_real("R0");
	  imposta    += _pim->get_real("R1");
	  _pim->put("R0", imponibile);
	  _pim->put("R1", imposta);
	  // segnale per comodita'
	  _pim->put("B1","X");
	  _pim->rewrite();
       }
    }   
  // memorizza totali per il prospettino di m.
  look_ptm(month, codatt);
  _ptm->put("S4",totacq.string());
  _ptm->put("S5",totven.string());
  _ptm->rewrite();
}