// ------------------------------------------------------------
// Calcolo liquidazioni
// Part 2: calcolo 
// fv 21-1-94
// ------------------------------------------------------------

#include <progind.h>
#include "cg4300.h"

// -------------------- QUI comincia l'avventura --------------------------

bool TLiquidazione_app::recalc_all() 
{
  long l;
  
  _prind = new TProgind(_selected.ones()*2,
                        "       Calcolo liquidazione...     \n"
                        "       Preparazione archivi      ",
                        TRUE,TRUE,45);

  for (l = 0l, _nditte->first(); !_nditte->eof(); l++, _nditte->next())
  {
    if (_prind->iscancelled()) 
      break;

    if (_selected[l])
    {
      TApplication::set_firm(_nditte->curr().get_long("CODDITTA"));
      _prind->addstatus(1);              
      
      // trimestrali impropriamente selezionate per mesi intermedi
      _freqviva    = look_lia() ? _lia->get("S7") : _nditte->curr().get("FREQVIVA");
      if (!is_month_ok(_month)) continue;

      int need_refresh = FALSE;
      if (_recalc != ever)
      { 
        for (int m = 1; m < _month; m++)
        {  
          if (!is_month_ok(m)) continue;
          if (!look_lim(m))    need_refresh = TRUE;
          else if (!(_lim->get_bool("B0"))) need_refresh = TRUE;
        }
        if (need_refresh)
          if (yesno_box("Alcuni mesi precedenti non risultano ricalcolati. E' "
                        "consigliabile il ricalcolo. Si desidera eseguirlo?"))
            _recalc = ever;
      }         
      
      if (_recalc == ever)
      {
        for (int m = 1; m < _month; m++)
          if (is_month_ok(m))
            update_firm(m);
      }
      update_firm(_month);    
      
      // se ci sono altri mesi dopo quello calcolato, invalida il 
      // flag 'calcolato' del primo, per causare il ricalcolo dei
      // successivi (evitando problemi per credito precedente)
      for (int m = _month+1; m <= 13; m++)
        if (is_month_ok(m) && look_lim(m))
        { 
          _lim->put("B0","");
          break; 
        }       
    }
  }
  if (!_prind->iscancelled()) _prind->addstatus(1);
  TApplication::set_firm(__firm);
  delete _prind;  _prind = NULL;

  return TRUE;
}

bool TLiquidazione_app::update_firm(int month, bool recalc)
{
  // Se recalc e' TRUE considera la necessita' di ricalcolare e le
  // opzioni utente. Se FALSE se ne impipa dell'utente e ricalcola 
  // se necessario (serve nelle chiamate ricorsive)
  // Ritorna FALSE soltanto se il ricalcolo era necessario e non e'
  // stato effettuato per scelta dello stronzo commercialista.
  
  look_lim(month, TRUE);

  // gia' ricalcolata definitivamente? 
  bool ok   = _lim->get_bool("B1");
  if (ok && !_comp_acconto) return TRUE;
  
  // azzera ulteriori detrazioni
  _lim->put("R6","");
  _lim->rewrite(); 

  // ricalcolo normale
  ok   = _lim->get_bool("B0");
  if (ok && !recalc) return TRUE; 
  bool calc = (_recalc == ever || (_recalc == one && month == _month));
  if (!calc && _recalc != never) calc = !ok;
  bool gheravergot = FALSE;
  
  TToken_string atts;
  TToken_string cattivs;
  
  _nditte->save_status();  
  if (_nditte->is_first_match(LF_ATTIV))
  {
    char buf[256];
    do
    {
      TString16 codatt = _nditte->curr(LF_ATTIV).get("CODATT");
      TString80 desatt = _nditte->curr(LF_ATTIV).get("DESCR");
      
      // attivita' mista: ce ne sono in realta' due
      // viene calcolato nel ciclo su tipoatt (che viene ripetuto solo
      // se diventa TRUE);
      _mixed     = FALSE;
      
      sprintf (buf,"Calcolo liquidazioni (%d)...\n%s: %s",
               month,
               (const char*)_nditte_r->get("RAGSOC"),
               (const char*)desatt);
      if (_prind) _prind->set_text(buf);
      _vend_arr.destroy();
      _corr_arr.destroy();
      
      cattivs = "";
      
      for (int tipoatt = 1; tipoatt <= (_mixed ? 2 : 1); tipoatt++)
      {
        TString cattiv(codatt);
        
        cattiv << tipoatt;
        if (tipoatt == 1 && look_pla(cattiv, FALSE))
        {
          _p8          = _pla->get_real("R5");
          _p8b         = _pla->get_real("R6");
          _p9          = _pla->get_real("R7");
          _prorata     = _pla->get_real("R8");
          _isplafond   = !(_p8.is_zero() && _p8b.is_zero() && 
                           _p9.is_zero());
          _isservizio  = _pla->get("S7") == "S";
          _mixed       = _pla->get("S7") == "M" || _pla->get("S7") == "E";
        }
        else
          _isservizio  = _nditte->curr(LF_ATTIV).get("TIPOATT") == "S";
        _isviaggio   = _nditte->curr(LF_ATTIV).get_bool("REG74TER");
        _isagricolo  = _nditte->curr(LF_ATTIV).get_bool("REGAGR");
        _isbenzinaro = _nditte->curr(LF_ATTIV).get_bool("ART74/4");
        //        _freqviva    = look_lia() ? _lia->get("S7") : _nditte->curr().get("FREQVIVA");
        bool   mens  = _freqviva == "M"; 
        _isannual    = (_month == 12 && !mens && !_isbenzinaro) || 
          (_month == 13 && (mens || _isbenzinaro));
        _isriepilogo = _month == 13;
        
        _isvent = FALSE;
        
        for (_reg->first(); !_isvent && _reg->good(); _reg->next())
        {
          if (codatt == _reg->get("S8") && _reg->get_int("I0") == 2)
            _isvent = _reg->get_bool("B3");
        }


        if ((month != 13 || _isannual) && (calc || !recalc))
          if (!update_att(month, cattiv))
            describe_error("Attivita' non ricalcolate: possibili errori",
                           codatt);        
        
        // vediamo se c'e' qualcosa da raccontare
        gheravergot = _isannual || _isriepilogo;
        if (!gheravergot) 
        {
          look_plm(month,cattiv);
          gheravergot = !_plm->get_real("R0").is_zero() ||
            !_plm->get_real("R1").is_zero();
        }                            

        if (month == _month && gheravergot) 
          describe_att(month,cattiv);
        atts.add(cattiv);
        cattivs.add(cattiv);
      } // for tipoatt

      // se attivita' mista stampa riepilogo (solo se 
      // la seconda attivita'aveva movimenti)

      if (_mixed && month == _month && gheravergot)
        describe_att(month,cattivs);
    } 
    while (_nditte->next_match(LF_ATTIV));
    
    // occorre poterla chiamare altre volte con mesi diversi
    _nditte->restore_status();
    
    // aggiorna le liquidazioni mensili
    if ((_month != 13 || _isannual) && (calc || !recalc))
      write_liq (month, atts);
    
    // rimborso infraannuale
    _DescrItem* rimb_d = NULL;
    if (month == _month && is_trim(month))
    {
      // unica nel suo genere, recalc_rimborso ritorna
      // un bel descritem (NULL se non si rimborsa un cas)
      // da passare a describe_liq
      rimb_d = recalc_rimborso(month,atts);
    }

    if (month == _month)
    {
      describe_firm(month);
      describe_liq(_month, atts, rimb_d);
    }
  }
  return ok || calc;
}

bool TLiquidazione_app::update_att(int month, const char* codatt, bool recalc)
  // viene passato un codice attivita' con codatt+tipoatt
  // vedi update_firm per il burdel dei calc e recalc

  // occhecasino. Se _comp_acconto e' TRUE, i movimenti considerati
  // saranno solo quelli di dicembre per data <= 20/12; 
  // il ricalcolo e' FORZATO da _recalc messo a one
{ 
  look_plm(month, codatt, TRUE);
  bool ok   = _plm->get_bool("B0");
  if (ok && !recalc) return TRUE; 
  bool calc = _recalc == ever || (_recalc == one && month == _month) ;

  if (!calc && _recalc != never) calc = !ok;
  if (_isannual && month == 13) month = 12;

  if (calc || !recalc)
  {
    zero_att(month,codatt);            
    recalc_att(month,codatt);          
    recalc_ventilation(month, codatt); 
    recalc_corrispettivi(month, codatt);
    if (month == 12) recalc_annual(codatt);
  }
  return ok || calc;
}

void TLiquidazione_app::zero_att(int month, const char* codatt)
{
  for (_pim->first(); !_pim->eof(); _pim->next())
  {
    int       m = atoi(*_pim_mese);
    TString att = (const char*)*_pim_codatt;
    if (m == month && att == codatt)
    {
      _pim->put("R0","");
      _pim->put("R1","");
      _pim->put("R2","");
      _pim->rewrite();
    }
  }
  if (_isplafond)
    zero_plafond(month,codatt);
}

void TLiquidazione_app::recalc_att(int month, const char* codatt)
  // il codatt passato e' codice att + tipo att ( IN {1|2} )
{ 
  real totintra     = 0.0;
  real nond19_imp   = 0.0;
  real nond19_iva   = 0.0;
  real ammort       = 0.0;
  real ammort_iva   = 0.0;
  real ammort_6     = 0.0;
  real ammort_6_iva = 0.0;
  real acq_riv      = 0.0;
  real acq_riv_iva  = 0.0;
  real leasing      = 0.0;
  real leasing_iva  = 0.0;
  real cess_amm     = 0.0;
  real cess_amm_iva = 0.0;
  real acquisti     = 0.0;
  real acquisti_iva = 0.0;
  real vendite      = 0.0;
  real vendite_iva  = 0.0;
  real esenti_b1    = 0.0;
  real esenti_b2    = 0.0;
  real esenti_b3    = 0.0;
  real esenti_b14   = 0.0;
  real corr_CEE     = 0.0;
  real corr_noCEE   = 0.0;
  real acq_CEE      = 0.0;
  real acq_noCEE    = 0.0;
  real corr_misCEE  = 0.0;
  real acq_misCEE   = 0.0;
  real acq_misnoCEE = 0.0;
  real agr_ven      = 0.0;
  real agr_acq      = 0.0;
  real agr_conf     = 0.0;
  real agr_acc      = 0.0;
  real cred_cost    = 0.0;
  real for_rimb     = 0.0;
  real acq_ies      = 0.0;
  real acq_ies_iva  = 0.0;                                    
  real ult_detr     = 0.0;
  real acq_pint     = 0.0;
  real acq_pint_iva = 0.0;
  
  *_cur      = 0;
  long items = _cur->items();
  TString      trueatt(codatt); 
  int tipatt = atoi(trueatt.sub(5));
  trueatt    = trueatt.left(5);

  for (; _cur->pos() < items; ++(*_cur))
  {      
    TDate date(_mov_r->get("DATAREG"));
    TString16 reg     = _mov_r->get("REG");
    bool isreg        = look_reg(_mov_r->get("REG"));
    TString16 tipodoc = _mov_r->get("TIPODOC");
    /*
     * check register present, rmoviva present and date OK
     */      
    const bool dok = !is_date_ok(date, month);  
    const bool sreg = !isreg;
    const bool rs8  = _reg_r->get("S8") != trueatt;
    const bool cmt  = !_cur->is_first_match(LF_RMOVIVA);
    
    if (dok || sreg || rs8 || cmt) continue;

    /*
     * check date se si calcola l'acconto
     */
    if (_month == 12 && _comp_acconto)
      if (date.month() != 12 && date.day() > 20)
        continue;
    
    bool    corrisp  = _reg_r->get_bool("B0");  
    tiporeg tipomov  = (tiporeg)_reg_r->get_long("I0");
    
    do
    {     
      look_iva(_rmoviva->get("CODIVA"));

      // TBI settare _isrimborso

      TString codiva     = _iva->get("CODTAB");
      TString tipoiva    = _iva->get("S1");
      int     tipoes_v   = (int)_iva->get_long("I3");
      int     tipoes_a   = (int)_iva->get_long("I4");
      int     tipoagr    = atoi(_iva->get("S4"));
      int     tipoag     = atoi(_iva->get("S5"));
      int     tipopla    = atoi(_iva->get("S3"));
      int     tipodet    = atoi(_rmoviva->get("TIPODET"));
      bool    ivarimb    = _iva->get_bool("B3");
      TString tipocr_s   = _rmoviva->get("TIPOCR");       
      int     tipocr     = atoi(tipocr_s);        
      real    imponibile = _rmoviva->get_real("IMPONIBILE");
      real    imposta    = _rmoviva->get_real("IMPOSTA");
      bool    intra      = _rmoviva->get_bool("INTRA");
      int     tipoatt    = _rmoviva->get_int("TIPOATT");
      
      if (  tipoatt != tipatt ) continue;                                   
      
      // ***************************************** 
      // casi particolari
      // ***************************************** 

      // imposta acquisti intracomunitari
      if (tipomov == acquisto && intra) 
        totintra += imposta;

      // acquisti non detraibili art. 19
      if (tipodet == 9)
      {
        nond19_imp += imponibile;
        nond19_iva += imposta;
        continue;
      }

      // Altre cose di cui tener conto
      if (tipomov == acquisto && (tipocr == 1 || tipocr == 5)) 
        // Acquisto beni per rivendita
      {
        acq_riv     += imponibile;
        acq_riv_iva += imposta;
      }
      else if (tipomov == acquisto && tipocr == 2)
        // Acquisto beni ammortizzabili
      {
        ammort     += imponibile;
        ammort_iva += imposta;
      }
      else if (tipomov == acquisto && tipocr == 3) 
        // Acquisto beni ammortizzabili detr. 6%
      {
        ammort_6     += imponibile;
        ammort_6_iva += imposta;
        ult_detr     += imposta * real(DETRAZIONE_6PERCENTO);
      }
      else if (tipomov == vendita && tipocr == 4) 
        // Vendite strum. art 17 (cess. amm.???)
      {
        cess_amm     += imponibile;
        cess_amm_iva += imposta;
      }
      else if (tipomov == acquisto && tipocr == 8) 
        // Acquisto beni strum. in leasing
      {
        leasing      += imponibile;
        leasing_iva  += imposta;
      }
      
      // operazioni per calcolo rimborso infracazzuale
      if ((tipoiva == "ES" || tipoiva == "NI") && ivarimb)
      {
        for_rimb += imponibile;
      }
      
      // operazioni esenti
      if (tipoiva == "ES")
      {
        if (tipomov == vendita)
        {
          switch(tipoes_v)
          {
          case 1: 
            esenti_b1 += imponibile; 
            break;
          case 2: 
            esenti_b2 += imponibile; 
            break;
          case 3: 
            esenti_b3 += imponibile; 
            break;
          }
        }
        else if (tipoes_a == 14)
          esenti_b14 += imponibile;
      }
      
      // plafond
      if (_isplafond && tipomov == acquisto && 
          tipoiva == "NI" && tipopla != 0)
      { 
        add_plafond(month, codatt, tipopla, imponibile, tipodoc == "BD");
      }
      // agenzie viaggio (CHECK imponibili etc.)
      if (_isviaggio)
        switch (tipoag)
        {
        case 1: 
          if (tipomov == acquisto) acq_CEE  += imponibile;
          else                     corr_CEE += imponibile;
          break;
        case 2:
          if (tipomov == acquisto) acq_noCEE  += imponibile;
          else                     corr_noCEE += imponibile;
          break;
        case 3: corr_misCEE  += imponibile; break;
        case 4: acq_misCEE   += imponibile; break;
        case 5: acq_misnoCEE += imponibile; break;
        }
      
      if (_isagricolo)
        switch(tipoagr)
        {
        case 1: 
          if (tipomov == acquisto) agr_acq  += imposta; 
          else agr_ven  += imposta; 
          break;
        case 2: if (tipomov == vendita) agr_conf += imposta; break;
        case 3: if (tipomov == vendita) agr_acc  += imposta; break;  
        }

      if (tipodet == 1)    // acquisti indeducibili su ricavi esenti art. 10 
      {                                                       
        acq_ies     += imponibile;
        acq_ies_iva += imposta;
        continue;                       // non entrano in liquidazione
      }
      
      if (tipodet == 3)  // passaggi interni (solo ventilaz)
      {  
        acq_pint     += imponibile;
        acq_pint_iva += imposta;
        continue;                       // precauzionale (in genere sono esenti IVA)
      }
      
      // ***************************************** 
      // Fine casi particolari
      // Non che i casi normali siano tanto meglio
      // *****************************************

      /*
       * Calcolo e aggiornamento
       * cerca o crea progressivo IVA
       */

      look_pim(month, codatt, reg, tipocr_s, codiva, TRUE);

      real imp = _pim_r->get_real("R0"); // imponibile
      real ivp = _pim_r->get_real("R1"); // IVA su imp.
      real lor = _pim_r->get_real("R2"); // lordo


      if (tipomov == vendita && !corrisp)  // i corrispettivi sono gestiti a parte
      {
        // totale vendite
        vendite     += imponibile;
        vendite_iva += imposta;
      }
      else if (tipomov == acquisto)
      {
        // totale acquisti
        acquisti     += imponibile;
        acquisti_iva += imposta;
      }
      
      // corrispettivi               
      if (corrisp)
      {
        // l'ultimo casino
        if (tipodoc == "CR" || tipodoc == "RF" || tipodoc == "SC")
        {
          // questi sono corrispettivi davvero; comportamento normale 
          if (tipoiva == "VE")   // da ventilare
          {
            lor += imponibile;
            _pim_r->put("I0",LORDO);
            add_vendite(month, reg, imponibile);
          }                    
          else // non da ventilare, con imposta gia' conteggiata
          {
            real perc = _iva->get_real("R0") / CENTO;
            lor += imponibile + imposta;
            _pim_r->put("I0",LORDO);
            add_corrisp(month, reg, imponibile, perc, codiva);
          }
        }
      else if (tipodoc == "FS")
      {
        // queste sono fatture che seguono scontrino, il lordo va detratto
        // perche' si e' gia' registrato lo scontrino medesimo
        if (tipoiva == "VE")
        {
          real rr  = imponibile + imposta; 
          vendite += rr;
          imp     += rr;
          add_vendite(month, reg, rr); 
        }
        else
        {
          vendite     += imponibile;
          vendite_iva += imposta;
          imp         += imponibile;
          ivp         += imposta;
        }
        lor           -= imponibile + imposta; 
      }
        else  // vendite normali a tutti gli effetti
        {     
          vendite     += imponibile;
          vendite_iva += imposta;
          imp         += imponibile;
          ivp         += imposta;
          _pim_r->put("I0",NETTO);
        }
      }  // if corrisp
      else // non corrisp
      { 
        // imponibile e imposta separata
        imp += imponibile;
        ivp += imposta;
        _pim_r->put("I0",NETTO);
      }
      
      _pim_r->put("R0",imp);
      _pim_r->put("R1",ivp);
      _pim_r->put("R2",lor);
      _pim->rewrite();
    }
    while (_cur->next_match(LF_RMOVIVA));
  }  
  
  // calcolati tutti i movimenti e aggiornati i pim
  // salviamo i totali antes que seja tarde
  
  // calcola il lercio prorata
  real prorata; 
  if (!_prorata.is_zero())
  {
    prorata = acquisti_iva * (_prorata / CENTO);
    prorata.round(ROUND_LIRA);
  }
  look_plm(month, codatt, TRUE);

  // ACHTUNG: l'iva sulle vendite e' calcolata sommando anche i 
  // corrispettivi; non tiene conto quindi delle imposte calcolate
  // con la ventilazione (che vanno sottratte) ne' di quelle 
  // calcolate per le agenzie di viaggio (che sembra non vadano
  // sottratte per il calcolo del volume di affari)

  _plm->put("R2", prorata);

  if (_isviaggio)
  {
    _plm->put("R5", corr_CEE);
    _plm->put("R6", corr_noCEE);
    _plm->put("R7", acq_CEE);
    _plm->put("R8", acq_noCEE);
    _plm->put("R9", corr_misCEE);
    _plm->put("R10",acq_misCEE);
    _plm->put("R11",acq_misnoCEE);
    // calcola base da base e credito di costo
    // indi abilmente trova il codiva e calcola l'iva del caso
    real rip       = acq_misCEE / (acq_misCEE + acq_misnoCEE);
    real corr_imp  = corr_misCEE * rip; corr_imp.round(ROUND_LIRA);
    corr_imp      += corr_CEE;
    real cost_detr = acq_misCEE  * acq_CEE;
    real base_imp  = corr_imp - (cost_detr 
                                 + credito_costo_prec(month, codatt));

    real debito = 0.0;

    if (base_imp.sign() < 0)
    {
      // credito di costo
      cred_cost = abs(base_imp);
      // vendite_iva e' corretto cosi' visto che i corrispettivi
      // sono registrati al lordo e l'imposta e' 0
    }
    else
    {
      debito       = base_imp * aliquota_agvia();
      vendite_iva += debito; 
      vendite_iva.round(ROUND_LIRA);
    }

    // tutte ste minchie le mettiamo in lim anche se sarebbe
    // assai piu' migliore metterle in plm
    look_lim(month,TRUE);
    _lim->put("R2", cred_cost);
    _lim->put("R3", debito);
    _lim->put("R4", rip);
    _lim->rewrite();
  }
  else if (_isagricolo)
  {
    _plm->put("R5", agr_ven);
    _plm->put("R6", agr_conf);
    _plm->put("R7", agr_acc);
    _plm->put("R8", agr_acq);
    // Il porco agricoltore spende poco e paga meno
    acquisti_iva -= (agr_acq + leasing_iva + ammort_iva + ammort_6_iva);
    vendite_iva  -= (agr_ven + agr_conf + agr_acc);
  }
  _plm->put("R0", vendite_iva);
  _plm->put("R1", acquisti_iva);
  _plm->put("R3", ult_detr);
  _plm->put("R12", _prorata); // per comodita' in stampa
  _plm->put("B0", "X");       // calcolato (invalidato dalla primanota)
  _plm->put("S1",  for_rimb.string());
  _plm->put("S2",  acq_ies.string());
  _plm->put("S3",  acq_ies_iva.string());
  _plm->put("S4",  acq_pint.string());
  _plm->put("S5",  acq_pint_iva.string());
  _plm->rewrite();

  // salva gli altri totali para no ponernos locos despues
  look_ptm(month,  codatt, TRUE);
  _ptm->put("R0",  totintra);  
  _ptm->put("R1",  nond19_imp);  
  _ptm->put("R2",  nond19_iva);  
  _ptm->put("R3",  ammort);  
  _ptm->put("R4",  ammort_iva);  
  _ptm->put("R5",  ammort_6);  
  _ptm->put("R6",  acq_riv);  
  _ptm->put("R7",  acq_riv_iva);  
  _ptm->put("R8",  leasing);  
  _ptm->put("R9",  leasing_iva);  
  _ptm->put("R10", cess_amm);  
  _ptm->put("R11", cess_amm_iva);  
  _ptm->put("R12", ammort_6_iva);
  _ptm->put("R13", esenti_b1);
  _ptm->put("R14", esenti_b2);
  _ptm->put("S0",  esenti_b3.string());
  _ptm->put("S1",  esenti_b14.string());
  _ptm->put("S2",  acquisti.string());
  _ptm->put("S3",  vendite.string());  
  _ptm->rewrite();
  
  // somma le ulteriori detrazioni
  look_lim(month, TRUE);
  real dt = _lim->get_real("R6");
  dt += ult_detr;
  _lim->put("R6", dt);
  _lim->rewrite();
}

void TLiquidazione_app::write_liq(int month, const char* codatts)
  // Calcolo liq. mensili e progr. liq. annuali
{
  TToken_string atts(codatts);
  const char* tmpatt;
  
  real risultato    = 0.0;
  real vol_aff      = 0.0;
  real debito_prec  = 0.0;
  
  while ((tmpatt = atts.get()) != NULL)
  {
    TString att(tmpatt);
  {
    look_plm(month, att);  look_ptm(month,att);
    // a debito:  IVA vendite, debito precedente, Prorata
    // a credito: IVA acquisti, ulteriori detrazioni 1 e 2
    risultato += (_plm->get_real("R0") - _plm->get_real("R1") +
                  _plm->get_real("R2") - _plm->get_real("R3") -
                  _plm->get_real("R4"));
    
    if (month == 12)
    {
      look_pla(att);
      vol_aff   += _pla->get_real("R0");
      // a credito anche il conguaglio prorata
      risultato -= _pla->get_real("R10");
    }
  }
  }
  // toglie credito precedente decrementato di ev. rimborsi chiesti
  // e acconto versato e rettifiche a debito
  risultato -= credito_prec(month);

  // vedi se c'era un debito precedente
  if (!is_first_month(month))
  {
    if (look_lim(previous_month(month)))
    {
      real r = _lim->get_real("R0");
      if (_lim->get_real("R5").sign() > 0)
        r += _plm->get_real("R5");
      // non considera il rimborso in quanto se e' a debito
      // non c'e' rimborso, e se e' rettificato pure
      if (r.sign() > 0 && r < IVA_DA_RIPORTARE)
        debito_prec += r;
    }
  }
  risultato += debito_prec;

  look_lim(month,TRUE);
  
  // scorpora ulteriori detrazioni                               
  real dt = _lim->get_real("R6");
  risultato -= dt;
  
  _lim->put("R0",risultato);
  _lim->put("B0","X");

  if (_isfinal) _lim->put("B1","X");
  _lim->rewrite();  

  if (month == 12)
  {
    if (!look_lia(TRUE))
      _lia->put("S7", (const char *) _freqviva);
    _lia->put("R1", vol_aff);
    _lia->rewrite();
  }
}


void TLiquidazione_app::recalc_annual(const char* att)
{
  // calcolo volume d'affari e altro
  real es_b1    = 0.0;
  real es_b2    = 0.0;
  real es_b3    = 0.0;
  real cess_amm = 0.0;
  real vendite  = 0.0;
  real pro_pag  = 0.0;
  real acq_iva  = 0.0; // per conguaglio prorata
  real acq      = 0.0;
  real ivlac    = 0.0;
  real ivven    = 0.0;
  real ven_lrd  = 0.0;

  int tipoatt = att[strlen(att) -1] - '0';
  TString aaa(att);
  
  if (tipoatt == 2)
  {
    // istanzia ai valori precedenti, calcolati per l'attivita' 1
    look_pla(aaa);
    vendite  = _pla->get_real("R0");
    es_b1    = _pla->get_real("R1");
    es_b2    = _pla->get_real("R2");
    es_b3    = _pla->get_real("R3");
    cess_amm = _pla->get_real("R4");  
    ivven    = _pla->get_real("R11");
    ivlac    = _pla->get_real("R12");
    ven_lrd  = _pla->get_real("R13");
    acq      = _pla->get_real("R14");
  } 
  
  for (int i = 1; i <= 12; i++)
  {
    if (is_month_ok(i))
    {
      // ricalcola se necessario
      if (i != 12 && !update_att(i,aaa,FALSE))
        describe_error("Attivita' non ricalcolata: "
                       "possibili errori",att);
      look_ptm(i,aaa); look_plm(i,aaa);
      real vend(_ptm->get("S3"));
      ven_lrd   += vend;  // lordo vendite
      // non entra l'IVA per calcolo volume affari
      vendite   += (vend - _plm->get_real("R0"));
      real eb3(_ptm->get("S0"));
      es_b1     += _ptm->get_real("R13");
      es_b2     += _ptm->get_real("R14");
      es_b3     += eb3;
      acq_iva   += _plm->get_real("R1");
      cess_amm  += _ptm->get_real("R10"); 
      pro_pag   += _plm->get_real("R2");
      real aax(_ptm->get("S2"));
      acq       += aax -   // rilevanti per aliquota media
        _ptm->get_real("R3") - // toglie ammortizz. etc
          _ptm->get_real("R5") - // non detraibili non ci sono
            _ptm->get_real("R8");
      ivlac     += _plm->get_real("R1") - // idem per IVE
        _ptm->get_real("R4") -
          _ptm->get_real("R9") -
            _ptm->get_real("R12");
      ivven     += _plm->get_real("R0");
    }
  }
  // calcolo prorata
  real prorata = (es_b1/(vendite - cess_amm - es_b3)) * CENTO;
  real conguaglio = 0.0;
  prorata.round(ROUND_LIRA);
  if (prorata != _prorata)
  {
    // calcolo conguaglio -- se positivo e' a debito
    real topay = acq_iva * (prorata / CENTO);
    conguaglio = topay - pro_pag;
  }
  
  // vediamo se la porca aliquota media acquisti e' superiore alla
  // porca aliquota media vendite

  look_pla(aaa);
  _pla->put("R0",  vendite);
  _pla->put("R1",  es_b1);
  _pla->put("R2",  es_b2);
  _pla->put("R3",  es_b3);
  _pla->put("R4",  cess_amm);  
  _pla->put("R9",  prorata);
  _pla->put("R10", conguaglio);
  _pla->put("R11", ivven);
  _pla->put("R12", ivlac);
  _pla->put("R13", ven_lrd);
  _pla->put("R14", acq);
  _pla->rewrite();
}

_DescrItem* TLiquidazione_app::recalc_rimborso(int month, const char* codatts)
{
  bool rimborsami = FALSE;
  _DescrItem* d = NULL;
  TToken_string atts(codatts);
  const char* tmpatt; 
  TString att;

  real iva_v, iva_a, imp_a, es_ni, vol_aff;

  while ((tmpatt = atts.get()) != NULL)
  {
    att = tmpatt;
    look_plm(month,att); look_ptm(month,att);
    
    real tvol(_ptm->get("S3"));
    vol_aff   += tvol;
    real esni(_plm->get("S1"));
    es_ni     += esni;
    iva_a     += _plm->get_real("R1");
    iva_v     += _plm->get_real("R0");
    real aax(_ptm->get("S2"));
    imp_a     += aax -   // rilevanti per aliquota media
      _ptm->get_real("R3") - // toglie ammortizz. etc
        _ptm->get_real("R5") - // non detraibili non ci sono
          _ptm->get_real("R8");

    if (_freqviva == "M") // sommiamo i due mesi precedenti
    {
      for (int m = month - 2; m < month; m++)
      { 
        bool ok = look_plm(m,att); 
        if (!ok)
          if (!update_att(m, att))
            describe_error("Attivita' non ricalcolate: possibili errori",
                           att);
        
        look_ptm(m,att);
        
        real tvol(_ptm->get("S3"));
        vol_aff   += tvol;
        real esni(_plm->get("S1"));
        es_ni     += esni;
        iva_a     += _plm->get_real("R1");
        iva_v     += _plm->get_real("R0");
        real aax(_ptm->get("S2"));
        imp_a     += aax -   // rilevanti per aliquota media
          _ptm->get_real("R3") - // toglie ammortizz. etc
            _ptm->get_real("R5") - // non detraibili non ci sono
              _ptm->get_real("R8");
      }
    }
  }

  // condizione 1
  if (!vol_aff.is_zero() && (es_ni/vol_aff) > MIN_PARTE_ESENTE)
  {
    rimborsami = TRUE;
    d = new _DescrItem(RIMBORSO);
    d->_f0 = TRUE;
    d->_r0 = es_ni;
    d->_r1 = vol_aff;
  }

  real alv = vol_aff.is_zero() ? real(0.0) : (iva_v / vol_aff);
  real ala = imp_a.is_zero()   ? real(0.0) : (iva_a / imp_a);
  
  // condizione 2
  if (ala > alv)
  {
    rimborsami = TRUE;
    if (d == NULL) d = new _DescrItem(RIMBORSO);
    d->_f1 = TRUE;
    d->_r2 = vol_aff; 
    d->_r3 = imp_a; 
    d->_r4 = iva_v; 
    d->_r5 = iva_a; 
    d->_r6 = alv * CENTO; 
    d->_r7 = ala * CENTO; 
  }

  return d;
}
