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

#include <progind.h>              
#include <sheet.h>
#include <config.h>
#include <utility.h>
#include "cg4300.h"

#define CHECK_ROUND(m,x) if(m==13)x.round(ROUND_MILLELIRE) 

// -------------------- QUI comincia l'avventura --------------------------
// Datemi un punto di appoggio                           ******************
//           e mi ci appoggero'                          ******************
// ----------------------------------------------------- ******************

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

  for (int l = 0; l < _ditte->items(); l++)
  {                           
    if (_prind->iscancelled())
      break;

    if (_selected[(long)l])
    {                                     
      TToken_string& nomeditta = _ditte->row(l);
      int save_month = _month;
      
      /* -------------------------------------------------------------
       * leggi parametri ditta necessari; stabilisci se annuale, 
       * se si' metti _month a 13
       *   istanzia _freqviva, _isbenzinaro, _isannual, _isriepilogo
       * --------------------------------------------------------------
       */
      
      _nditte->zero(); 
      _nditte->curr().put("CODDITTA",nomeditta.get_long(1));
      _nditte->read(); 
      _freqviva = nomeditta.get(3);
      bool   mens  = _freqviva == "M"; 

      // determina attivita' prevalente e istanzia cazzuole
      // per vedere che Kazzo di liquidazione calcolare
      TString attprev = _nditte->curr().get("CODATTPREV");
      TLocalisamfile& atts = _nditte->lfile(LF_ATTIV);
      atts.zero();
      atts.put("CODDITTA",nomeditta.get_long(1));
      atts.put("CODATT",  attprev);
      if (atts.read() != NOERR) atts.zero();
      // istanzia benzinaro
      _isbenzinaro = atts.get_bool("ART74_4");
      
      // riaggiusta relazione
      _nditte->read();               
      
      // decidi per stocazzo di annuale      
      // ***************** Previous kasin ***************************
      // per QUALSIASI annuale il mese diventa 13
//      _isannual    = (_month == 12 && !mens && !_isbenzinaro) || 
//                     (_month == 13 && (mens || _isbenzinaro));    
//      _isriepilogo = _month == 13 && !mens;               
//      if (_isannual) _month = 13;  // che ti piaccia o no  
      // ************************************************************                                                               
                                                                     
      // strasemplificato: per l'annuale si sceglie annuale, altrimenti
      // e' la 12ma anche per le trimestrali.
      _isannual = _isriepilogo = _month == 13;
      
      TApplication::set_firm(nomeditta.get_long(1));
      _prind->addstatus(1);              
      
      /*
       * trimestrali impropriamente selezionate per mesi intermedi
       * provocano il ricalcolo dei progressivi mensili ma non la stampa    
       */
      _canprint = is_month_ok_strict(_month) || _month == 13;

      /* --------------------------------------------------------------
       * Ricalcola i mesi necessari, tutti se annuale
       * --------------------------------------------------------------
       */

      int need_refresh = FALSE;
      if (_recalc != ever)
      { 
        for (int m = 1; m < _month; m++)
          if (is_month_ok_strict(m) && (!look_lim(m) || !_lim->get_bool("B0")))
          {
             need_refresh = TRUE; 
             break;
          }

        if (need_refresh && yesno_box("Alcuni mesi precedenti non "
               "risultano ricalcolati. E' consigliabile il ricalcolo. "
               "Si desidera eseguirlo?"))
            _recalc = ever;
       }         
       
       for (int m = 1; m <= _month; m++)   // fino a 13 compreso
         if (is_month_plain(m) || _recalc == ever)
         {               
           if (_prind->iscancelled()) break;
           update_firm(m);
         }
      
      // se ci sono altri mesi dopo l'ultimo calcolato, invalida il 
      // flag 'calcolato' del primo, per causare il ricalcolo dei
      // successivi (evitando problemi per credito precedente)
      for (m = _month+1; m <= 13; m++)
        if (look_lim(m))
        { 
          _lim->put("B0","");
          _lim->rewrite();
          break; 
        } 
        
      _month = save_month;      
    }  
  }
  bool canc = _prind->iscancelled();
  if (!canc) _prind->addstatus(1);

  TApplication::set_firm(__firm);
  delete _prind;  _prind = NULL;
  
  return !canc;
}

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(liq_month(month), TRUE);
  
  if (_isfinal && _lim->get_bool("B1") && _month != 13)  
    return TRUE;
  
  TConfig cnf(CONFIG_DITTA, "cg");
  _isdiffacc = cnf.get_bool("GeLiDi");   //usato per stampa acconto in coda ai registri
  _isdifferita = _isdiffacc && _month != 13;
  _isintr      = !cnf.get_bool("InTrTr") && _freqviva != "M";
  if (_isbenzinaro)
    _gest4 = cnf.get_bool("GesT74");
  // controlla che il periodo corrente non sia l'inizio dell'attivita'
  // nel caso, differita va a FALSE                  
  _monthinatt = 1; 
  TDate inatt(_nditte->lfile().get("DINIZIOATT"));
  if (is_in_liq_period(inatt)) _isdifferita = FALSE;
  if (inatt.year() == atoi(_year)) _monthinatt = inatt.month();
  
  TConfig cnf1(CONFIG_STUDIO, "cg");
  _isricacq = cnf1.get_bool("RicAcq");

  // ricalcolo normale  
  // lim c'e' solo per i trimestri
  bool ok   = _lim->get_bool("B0");
  if (ok && !recalc) return TRUE; 
  bool calc = (_recalc == ever || (_recalc == one && is_month_ok(month,_month)));
  if (!calc && _recalc != never) calc = !ok;
  bool gheravergot = FALSE;
  bool quater      = FALSE;
  
  TToken_string atts;
  TToken_string cattivs;
                 
  // azzera rimborsi                
  zero_firm(month);
  
  // casini per stampa minchie in coda ai registri                           
  bool riepliq = FALSE; 
  bool stliq = FALSE;
  
  _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");
      quater           = _nditte->curr().get_bool("FLIVA11Q");

      // 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, _printonly ? "Stampa liquidazione (%d)...\n%s: %s\n" : 
               "Calcolo liquidazione (%d)...\n%s: %s\n",
               month,
               (const char*)_nditte_r->get("RAGSOC"),
               (const char*)desatt); 
               
      if (_prind) _prind->set_text(buf);
      
      // se ricalcola l'annuale si tiene tutte le vendite e corrispettivi di
      // tutti i lerci mesi
      if (!(_month == 13 && month > 1))
      { 
        _vend_arr.destroy();
        _corr_arr.destroy();
      } 
      
      cattivs = "";
      
      for (int tipoatt = 1; tipoatt <= (_mixed ? 2 : 1); tipoatt++)
      {
        TString cattiv(codatt); bool waspla;
        
        cattiv << tipoatt;
        if (tipoatt == 1 && (waspla = 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");
        _isvent = FALSE; 

        if (tipoatt == 1 && waspla && month == 13)
        {
          // azzera pla dove serve             
          _pla->put("R0","");
          _pla->put("R1","");
          _pla->put("R2","");
          _pla->put("R3","");
          _pla->put("R4","");
          _pla->put("R13","");
          _pla->put("R9","");
          _pla->put("R10","");
          _pla->put("R11","");
          _pla->put("R12","");
          _pla->put("R14","");
          _pla->put("S1","0");
          _pla->put("S2","0");
          _pla->put("S3","0");
          _pla->rewrite();
        }
        
                                          
        for (_reg->first(); _reg->good(); _reg->next())
        {
          if (codatt == _reg->get("S8") || quater) 
          {
            if (!riepliq) riepliq = _reg->get_bool("B6");
            if (!stliq)   stliq   = _reg->get_bool("B7");
            if (_reg->get_int("I0") == 2) 
              if (!_isvent) _isvent = _reg->get_bool("B3"); 
          }
        }
        
        if (!_isregis)
          stliq = riepliq = TRUE;
        
        if (_comp_acconto)
          stliq = riepliq = FALSE;
        
        if (calc || !recalc)
          if (!update_att(month, cattiv) && stliq)
            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 && riepliq)
          describe_att(month, cattiv, gheravergot, 
                       '0' + (_mixed ? tipoatt : 0)); 
        
        atts.add(cattiv);
        cattivs.add(cattiv);
      } // for tipoatt

      // se attivita' mista stampa riepilogo
      if (_mixed && month == _month && riepliq) 
        describe_att(month,cattivs, TRUE, 'M');
    } 
    while (_nditte->next_match(LF_ATTIV));

    // se quater stampa riepilogo
    if (quater && month == _month && riepliq) 
      describe_att(month,atts, TRUE, 'Q');
    
    // occorre poterla chiamare altre volte con mesi diversi
    _nditte->restore_status();
    
    // aggiorna le liquidazioni
    if (calc || !recalc)
      if (is_month_ok_strict(month) || month == 13) 
         write_liq(month, atts);
    
    // rimborso infraannuale
    _DescrItem* rimb_d = NULL;
    if (month == _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, stliq);
    }

    if (month == _month && stliq)
    {
      describe_firm(month);
      //describe_liq(_month, atts, _isregis ? NULL : rimb_d);
      describe_liq(_month, atts, rimb_d);
    }  

    //in caso di stampa registri e in caso sia 
    //stato calcolato l'acconto (metodo analitico)
    //deve essere stampato il prospetto di liquidazione
    //dell'acconto in coda al resto
    if (_isregis && stliq)
      if ((month == 12 && _freqviva == "M") || 
          (month == 12 && _isbenzinaro && _gest4) ||
          (_isannual && _freqviva == "T" && !_isbenzinaro) ||
          (_isannual && _isbenzinaro && !_gest4))  
        describe_liqacc();
  }
  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 && is_month_ok(month,_month));
  if (!calc && _recalc != never) calc = !ok; 

  if (calc || !recalc)
  {
    zero_att(month,codatt);            
    recalc_att(month,codatt);          
    if (!_isagricolo)
    { 
      recalc_ventilation(month, codatt); 
      recalc_corrispettivi(month, codatt);  
    }
    if (month == 13)
     recalc_annual(codatt);
  }
  return ok || calc;  
}
     
void TLiquidazione_app::zero_firm(int month)
{
  // nothing more, left for sicurezz
}    
     
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 && (_year == *_pim_anno))
    {
      _pim->put("R0","");
      _pim->put("R1","");
      _pim->put("R2","");
      _pim->put("R3","");
      _pim->put("R4","");
      _pim->put("R5","");
      _pim->put("R6","");
      _pim->put("R7","");
      _pim->put("R8","");
      _pim->put("R9","");
      _pim->put("R10","");
      _pim->put("R11","");
      _pim->put("R12","");
      _pim->put("R13","");
      _pim->put("R14","");
      _pim->put("S1","");
      _pim->put("S2","");
      _pim->rewrite();
    }
  }      
  if (look_plm(month, codatt))
  {
    // zero PLM, POM, PAM, PUM
    TString codtab(_plm->get("CODTAB"));
    _plm->zero();
    _pom->zero();   
    _pam->zero();   
    _pum->zero();
    _plm->put("CODTAB", codtab);   
    _pom->put("CODTAB", codtab);   
    _pam->put("CODTAB", codtab);   
    _pum->put("CODTAB", codtab);   
    _plm->rewrite();
    _pam->rewrite();
    _pom->rewrite();
    _pum->rewrite();
  }
  if (_isplafond && month != 13)
    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} )
  // occhecasino. Se _comp_acconto e' TRUE, i movimenti considerati
  // saranno solo quelli di dicembre per data <= 20/12; 
{ 
  real totintra         = 0.0;
  real nond19_imp       = 0.0;
  real nond19_iva       = 0.0;
  real ammort_det       = 0.0;
  real ammort_det_iva   = 0.0;
  real ammort_indet     = 0.0;
  real ammort_indet_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 esni_rimb        = 0.0;   // ci sommo tutti esenti e ni validi per rimborso
  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_1i           = 0.0;
  real agr_2i           = 0.0;
  real agr_1            = 0.0;
  real agr_2            = 0.0;
  real agr_3            = 0.0;
  real agr_4            = 0.0;
  real agr_5            = 0.0;
  real agr_6            = 0.0;
  real agr_7            = 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;
  real spgen            = 0.0;
  real spgen_iva        = 0.0;
  real assp_imp         = 0.0;
  real assp_iva         = 0.0;
  real vssp_imp         = 0.0;
  real vssp_iva         = 0.0;
  real bdog_imp         = 0.0;
  real bdog_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->get("DATAREG"));
    TString16 reg     = _mov->get("REG");
    bool isreg        = look_reg(_mov->get("REG"));
    TString16 tipodoc = _mov->get("TIPODOC");
    bool    corrisp  = _reg->get_bool("B0");  
    tiporeg tipomov  = (tiporeg)_reg->get_long("I0");

    if (_isviaggio && tipomov == vendita && !(_mov->get("DATA74TER").empty())) 
      date = _mov->get_date("DATA74TER");
      
    /*
     * check register present, rmoviva present and date OK
     */      
    const bool dok      = !is_date_ok(date, month);  
    const bool sreg     = !isreg;
    const bool rs8      = _reg->get("S8") != trueatt;
    const bool cmt      = !_cur->is_first_match(LF_RMOVIVA);
    const bool sosp_imp = _reg->get_bool("B1");
    const TRectype& rcs = _cur->curr(LF_CAUSALI);
    const bool fattrit  = rcs.get_bool("RITFATT");
    
    if (dok || sreg || rs8 || cmt) continue;
    
    /*
     * Tipo documento da eliminare (Scudler 1994)   
     * Trattasi per lo piu' di non incassati
     * Da oggi vengono sommati nei real di S2 in pim 
     * assieme alle FS per stampa registri 
     */
     bool noninc = (tipodoc == "SN" || tipodoc == "CN" || tipodoc == "RN" ||
                    tipodoc == "IN" || tipodoc == "PG");
    
    /*
     * check date: se si calcola l'acconto, solo da 1/12 a 20/12 
     */     
    int accmonth = _isdifferita ? 11 : 12; 
    
    /* 
     * Patrizia: se e' differita i mov. vanno da 1/11 a 30/11 
     * potrei allora andarmi a leggere i risultati della liq di 11
     * ma il cliente potrebbe voler calcolare l'acconto prima
     * di aver calcolato la liquidazione (perche' cosi' complicato?)
     */  
    //if (_comp_acconto && date.month() == accmonth && date.day() > 20)
    if (_comp_acconto && date.month() == accmonth)
      if (!_isdifferita && date.day() > 20)
       continue;
    
    do
    {     
      look_iva(_rmoviva->get("CODIVA"));
      
      // totali parziali registrati nei pim per motivi ignoti
      real bolld_imp = 0.0;         // imponibile bolle doganali
      real bolld_iva = 0.0;         // imposta bolle doganali
      real asimp_imp = 0.0;         // imponibile acquisti sosp. imposta
      real asimp_iva = 0.0;         // imposta acquisti sosp. imposta
      real vsimp_imp = 0.0;         // imponibile vendite sosp. imposta
      real vsimp_iva = 0.0;         // imposta vendite sosp. imposta
      real rit_imp   = 0.0;         // imponibile fatture in ritardo
      real rit_iva   = 0.0;         // imposta fatture in ritardo
      real nin_imp   = 0.0;         // imponibile non incassati
      real nin_iva   = 0.0;         // imposta non incassati
      
      TString codiva     = _iva->get("CODTAB");
      TString tipoiva    = _iva->get("S1");
      TString riga11_v   = _iva->get("S0");
      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    isrimbinfr = _iva->get_bool("B3");     // vale per calcolo rimborso se ES o NI
      bool    ivarimb    = !_iva->get_bool("B4");    // non escluso calcolo rimb. per al. media
      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");
      int     rigaimp    = _rmoviva->get_int("RIGAIMP");
      // autofatture art. 17 per non residenti, con trattamento
      // speciale in liquidazione annuale
      bool    autodafe = (tipodoc == "AF" && tipocr == 4); 
      // indica acquisti per rivendita; viene messo in B4 di PIM per
      // indicare che e' soggetto al ricalcolo IVA (se voluto) in modo
      // da evitare di dover controllare mese e anno sul PIM
      bool    was_riv = FALSE;
      /*
       * puo' capitare per motivi brutalmente prassici
       * SENSU Sergio 1995, Guido
       */
      if (tipoatt == 0) tipoatt = 1;
      
      if(tipoatt != tipatt) continue;    
      
      /*
       * Riga imponibile > 9 = ritenute; non si
       * considerano (Scudler 1994)
       */
      if(rigaimp > 9) continue;                               

      /*
       * In liq. annuale si totalizzano
       * solo le stranezze che seguono
       */
      if (month == 13)
      {         
        // si contano soltanto le vendite.
        bool okc = tipomov == vendita;  
        // purche' ...
        bool cond1 = (rcs.get_bool("AUTOFATT") && tipoiva == "NS" && tipodoc == "AF");
        // oppure ... 
        bool cond2 = (rcs.get_bool("AUTOFATT") && tipoiva == "NS" && tipodoc != "AF" &&
                       rcs.get_bool("INTRACOM") && rcs.get_bool("VALINTRA"));
        /*
         * Fatture in ritardo vengono considerate solo in dichiarazione
         * annuale, ma vanno comunque sommate per i porci registri
         */
        if (!(okc && (cond1 || cond2)) && !fattrit)
          continue;
      } 

      if (noninc)   // non incassati: non devono entrare in nessun altro calcolo
      {              
        nin_imp = imponibile;
        nin_iva = imposta;
      }
      else if (sosp_imp)    // sospensione di imposta
      {
        if (tipomov == vendita)
        {
          vsimp_imp = imponibile;
          vsimp_iva = imposta;
        }
        else
        {
          asimp_imp = imponibile;
          asimp_iva = imposta;
        }       
        assp_imp += asimp_imp;
        assp_iva += asimp_iva;
        vssp_imp += vsimp_imp;
        vssp_iva += vsimp_iva;
      }
      else if (fattrit && month != 13)
      {
        rit_imp = imponibile;
        rit_iva = imposta;
      }      
      else if (!fattrit)  // normale
      {
       
        // ***************************************** 
        // casi particolari
        // ***************************************** 

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

        // Altre cose di cui tener conto
        if (tipomov == acquisto && (tipocr == 1 || tipocr == 5)) 
          /* 
           * Acquisto beni per rivendita
           */
        {
          acq_riv     += imponibile;
          acq_riv_iva += imposta;
          was_riv      = TRUE;
        }                                 
      
        else if (tipomov == acquisto && tipocr == 2 && tipodet == 0)
          // Acquisto beni ammortizzabili detraibili
        {
          ammort_det     += imponibile;
          ammort_det_iva += imposta;
        }
        else if (tipomov == acquisto && tipocr == 2 && tipodet != 0)
          // Acquisto beni ammortizzabili indetraibili
        {
          ammort_indet     += imponibile;
          ammort_indet_iva += imposta;
        }
        else if (tipomov == acquisto && tipocr == 3) 
          // Acquisto beni ammortizzabili detr. 6%
        {
          ammort_6     += imponibile;
          ammort_6_iva += imposta;
          ult_detr     += imponibile * real(DETRAZIONE_6PERCENTO);
        }
        else if (tipomov == vendita && tipocr == 4) 
          /*
           * Vendite strum. art 17 (cess. amm.)
           * Comprende anche autofatture, anche nell'annuale
           * (Sergio 1995) 
           */
        { 
           /* NO!      
           * Invece non le deve comprendere nell'annuale 
           * (Vladimiro 1995, piu' tardi)
           */
          if (!(_month == 13 && autodafe))  
          {
            cess_amm     += imponibile;
            cess_amm_iva += imposta;   
          }
        }
        else if (tipomov == acquisto && tipocr == 8) 
          // Acquisto beni strum. acquisiti in leasing
        {
          leasing      += imponibile;
          leasing_iva  += imposta;
        }
        else if (tipomov == acquisto && tipocr == 9)
          // Spese generali
        {
          spgen        += imponibile;
          spgen_iva    += imposta;
        }
                         
        // operazioni per calcolo rimborso infraanale
        // Scudler 1995 e molti dopo di lei
        // La breve estate vissuta dal metodo del 51% rende
        // oramai superflua la tabella rimborsi, eliminata
        // senza entusiasmo ed interrogandomi sul senso della vita
        if (ivarimb)
        { 
          bool ok   = _isagricolo ? tipoagr == 2 : FALSE;
          
          if (tipomov == acquisto && !ok)
             ok = (tipocr == 0 || tipocr == 1 || tipocr == 5 || tipocr == 9);

          if (tipomov == vendita && !ok)
            ok = tipoiva != "NS" && tipocr != 4;
          
          ivarimb = ok;
        }

        // 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;
            }                          
            // se e' il caso sommare esenti per rimborso 
            if (isrimbinfr)
              esni_rimb += imponibile;
          }
          else if (tipoes_a == 14)
            esenti_b14 += imponibile;
        }
        
        // non imponibili per rimborso
        if (tipoiva == "NI" && tipomov == vendita && isrimbinfr)
           esni_rimb += imponibile;
        
        // bolle doganali
        if (tipodoc == "BD")
        {
          bolld_imp = imponibile;
          bolld_iva = imposta; 
          
          bdog_imp += bolld_imp;
          bdog_iva += bolld_iva;
        }                       
                               
        // plafond
        if (_isplafond && tipomov == acquisto && month != 13 && 
            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 + imposta;
            else                     corr_CEE += imponibile + imposta;
            break;
          case 2:
            if (tipomov == acquisto) acq_noCEE  += imponibile + imposta;
            else                     corr_noCEE += imponibile + imposta;
            break;
          case 3: corr_misCEE  += imponibile + imposta; break;
          case 4: acq_misCEE   += imponibile + imposta; break;
          case 5: acq_misnoCEE += imponibile + imposta; break;
          }
      

        if (_isagricolo) 
        {
          /*
           * rifatto sensu Scudler 1995 con invidiabile sicurezza
           * senza porsi domande e mettendo NUMERI uguali
           * al TIPO RECORD del frigorifero     
           */
          if (tipomov == vendita)
          {
            if (tipoagr == 1 || tipoagr == 3)
            {  
              agr_1  += imposta;       
              agr_1i += imponibile;
            }
            else if (tipoagr == 2)
            {
              agr_2  += imposta;
              agr_2i += imponibile;
            }
          }
          else if (tipodet == 0)
          {
            if (tipoagr == 2)
            {
              if (tipocr != 2 && tipocr != 3 && tipocr != 8)
                agr_3 += imposta;  
              else
                agr_4 += imposta;
            }
            else if (tipoagr == 3)
            {    
              if (tipocr != 2 && tipocr != 3 && tipocr != 8)
                agr_7 += imposta;  
            }
            else   // ne' 2 ne' 3
            {
              if (tipocr != 2 && tipocr != 3 && tipocr != 8)
                agr_5 += imposta;
              else
                agr_6 += imposta;
            }            
          }
        }

        if (tipodet == 1)    // acquisti indeducibili su ricavi esenti art. 10 
        {                                                       
          acq_ies     += imponibile;
          acq_ies_iva += imposta;
        }
      
        if (tipodet == 3)  // passaggi interni (solo per ventilaz)
        {  
          acq_pint     += imponibile;
          acq_pint_iva += imposta;
        }

        // acquisti non detraibili art. 19
        // possono valere per la ventilazione
        if (tipodet == 9)
        {
          nond19_imp += imponibile;
          nond19_iva += imposta;
        }
      
        // ***************************************** 
        // Fine casi particolari
        // Non che i casi normali siano tanto meglio
        // *****************************************
      }  // non sosp_imp ne' altre casistiche che escludono la liq.
      /*
       * Calcolo e aggiornamento
       * cerca o crea progressivo IVA
       */
      look_pim(month, codatt, reg, tipocr_s, codiva, tipodet, TRUE);
      
      /* 
       * se ign == TRUE non bisogna neppure PROGRESSIVARLI
       */
      bool ign = sosp_imp || (fattrit && month != 13) || noninc;

      /*
       * se liq == FALSE gli importi non contano ai fini
       * del calcolo liquidazione  
       */                                        
      bool liq = !(tipodet == 1 || tipodet == 3 || tipodet == 9 || ign);
      
      real imp = _pim->get_real("R0"); // imponibile
      real ivp = _pim->get_real("R1"); // IVA su imp.
      real lor = _pim->get_real("R2"); // lordo  

      /*
       * le maledette fatture con scontrino sono sul registro dei
       * corrispettivi, ma vanno riportate nelle vendite in stampa;
       * dunque, le sommiamo in R5 e R6 di PIM anche se continuiamo
       * a sommarle anche in R0 e R1. La stampa (describe_pim)
       * dovra' scorporarle
       */
      real ifs = _pim->get_real("R5"); // imponibile fatture con scontrino
      real vfs = _pim->get_real("R6"); // IVA fatt. con scontrino

      /*
       * le maledette autofatture non residenti art. 17
       * vedi al calcolo if (autodafe) si tengono da parte 
       * La stampa le scorpora solo IN SEDE di dichiarazione annuale
       */
      real adf = _pim->get_real("R7");                
      real adi = _pim->get_real("R8");
                      
      /* le fottute fatture in sospensione di imposta */
      real fsi = _pim->get_real("R11");
      real fsv = _pim->get_real("R12");
      
      /* le putride bolle doganali */
      real bdi = _pim->get_real("R9");
      real bdv = _pim->get_real("R10");
      
      /* i luridi falsi corrispettivi */
      real fci = _pim->get_real("R13");
      real fcv = _pim->get_real("R14");                   
      
      /* le porche fatture in ritardo */
      TToken_string fr(_pim->get("S1")); 
      real rti(fr.get(0));
      real rtv(fr.get(1));
      
      /* 
       * la stramadonna dei corrispettivi gia' scorporati 
       * Gli si aggiungono i non incassati, sperando in bene
       */
      TToken_string cs(_pim->get("S2"));
      real csi(cs.get(0));
      real csv(cs.get(1));  
      /* incrociamm'e dituozz' */
      csi += nin_imp;                
      csv += nin_iva;                
                      
      rti   += rit_imp;
      rtv   += rit_iva;
      
      if (tipomov == vendita)
      {
        fsi += vsimp_imp;
        fsv += vsimp_iva;
      }
      else
      { 
        fsi += asimp_imp;
        fsv += asimp_iva;
        bdi += bolld_imp;
        bdv += bolld_iva;
      }

      if (liq && tipomov == vendita && !corrisp) 
      // i corrispettivi sono gestiti a parte
      {
        // totale vendite
        vendite     += imponibile;
        vendite_iva += imposta;
      }
      else if (liq && tipomov == acquisto)
      {
        // totale acquisti
        acquisti     += imponibile;
        acquisti_iva += imposta;
      }
     
      // corrispettivi  
      bool true_corrisp = FALSE;             
      if (corrisp)
      {
        /*
         * ennesimo casino: non tutti i corrispettivi sono
         * corrispettivi; in effetti, alcuni corrispettivi
         * non sono corrispettivi. Ci si potrebbe domandare
         * se gli altri corrispettivi sono corrispettivi o
         * no; ebbene, gli altri corrispettivi risultano
         * fortunatamente essere corrispettivi, a meno di
         * indicazioni contrarie.
         */
        if (tipodoc == "CR" || tipodoc == "RF" || tipodoc == "SC")
        {                      
          true_corrisp = TRUE;
          _pim->put("I0",LORDO);
          // questi sono corrispettivi davvero; comportamento normale 
          if (tipoiva == "VE")   // da ventilare
          {
            lor += imponibile;
            add_vendite(month, reg, tipodet, imponibile);
          }                    
          else // non da ventilare, con imposta gia' conteggiata
          {
            real perc = _iva->get_real("R0")/CENTO;
            lor += imponibile + imposta;   
            real tot = imponibile+imposta;   
            if (liq) add_corrisp(month, reg, tot, perc, tipodet, codiva, codatt);
          }
        } 
        else if (tipodoc == "FS")
        {
          // queste sono fatture che seguono scontrino, il lordo va detratto
          // perche' si e' gia' registrato lo scontrino medesimo   
          true_corrisp = TRUE; // non e' vero ma non devono essere sommate ai falsi
                               // corrispettivi
          if (tipoiva == "VE")
          {
            real rr  = imponibile + imposta; 
            imp     += rr;
            if (liq)
              vendite += rr;
            add_vendite(month, reg, tipodet, rr); 
          } 
          if (liq)
          {
            csi += imponibile;
            csv += imposta;
          }
          imp -= imponibile;
          ivp -= imposta;
          lor -= imponibile + imposta;
          ifs += imponibile;
          vfs += imposta; 
        }
        else  // vendite normali a tutti gli effetti
        {     
          if (liq)
          {
            vendite     += imponibile;
            vendite_iva += imposta;
            csi += imponibile;
            csv += imposta;
          }
          imp += imponibile;
          ivp += imposta;
          fci += imponibile;
          fcv += imposta; 
          _pim->put("I0",NETTO);
          }
        }  // if corrisp
        else // non corrisp
        {       // imponibile e imposta separata
          imp += imponibile;
          ivp += imposta; 
          _pim->put("I0",NETTO);
        }

        if (autodafe)  // autofatture non residenti art, 17
        {                    
          /*
           * Si devono riportare a parte in annuale
           * e non comparire nel riepilogo del codice IVA 
           * corrispondente, solo se la liq. e' annuale
           * Li metto in R7/R8 di pim e li sommo anche nelle
           * vendite; la describe_pim() dovra' sommarli su tutti i 
           * pim, scorporarli dalle rispettive vendite 
           * e assegnarli al codice IVA A35 in caso di liq. annuale
           */
          adf += imponibile;
          adi += imposta;       
        }                                    
        
        if (corrisp && !true_corrisp)
        {
          fci += imponibile; 
          fcv += imposta;
        } 
      
        if (!ign) 
        {
          _pim->put("R0",imp);
          _pim->put("R1",ivp);
          _pim->put("R2",lor);   
          _pim->put("R5",ifs);   
          _pim->put("R6",vfs);   
          _pim->put("R7",adf);   
          _pim->put("R8",adi);  
          _pim->put("R9",bdi);         
          _pim->put("R10",bdv);         
          _pim->put("R13",fci);         
          _pim->put("R14",fcv);       
      } 
                           
      // questi servono per i ricalcoli altrui (classify_pim) o 
      // per trucchetti di ricalcolo successivi
      _pim->put("R11",fsi);         
      _pim->put("R12",fsv);         
      _pim->put("I1", (long)tipomov);  
      _pim->put("B3", ivarimb ?   "X" : "");  
      _pim->put("B4", (_isricacq && was_riv) ? "X" : "");  
      _pim->put("S5", tipoiva);              
                           
      // fatture in ritardo                     
      fr.add(rti.string(), 0);
      fr.add(rtv.string(), 1);
      _pim->put("S1",fr);
      
      // corrispettivi gia' scorporati; anche questi servono per
      // non cannare la stampa dei registri; contengono anche
      // tutti i non incassati (vedi definizione di bool nonimp)
      cs.add(csi.string(), 0);
      cs.add(csv.string(), 1);
      _pim->put("S2",cs);      
      _pim->rewrite();
    }
    while (_cur->next_match(LF_RMOVIVA));
  }  // fine calcolo progressivi IVA 
    
  /*  
   * calcolati tutti i movimenti e aggiornati i pim
   * se necessario risistema le imposte acquisti beni
   * per rivendita   
   */
   
  if (_isricacq)  // flag settato parametri studio
  {
    for (_pim->first(); !_pim->eof(); _pim->next())
    {
      // this is much furber than doing all of the checks
      if (_pim->get_bool("B4"))
      {
        // ricalcola l'imposta a partire dal codice IVA
        look_iva(*_pim_codiva);   
        real old_iva = _pim->get_real("R1");
        real perc    = _iva->get_real("R0");
        
        real new_iva = (_pim->get_real("R0") * perc)/CENTO; 
        new_iva.ceil(ROUND_LIRA);  // TBC check ceil
        
        if (new_iva != old_iva)
        {
           // ricalcola: acquisti_iva, acq_riv_iva   
           acquisti_iva -= old_iva;
           acquisti_iva += new_iva;
           acq_riv_iva  -= old_iva;
           acq_riv_iva  += new_iva;
           _pim->put("R1", new_iva);  
           // resetta in modo da non vederlo il mese dopo 
           _pim->put("B4", "");
           _pim->rewrite();
        }
      }
    }
  }
  
  /* 
   * calcola il lercio prorata  
   * solo se liq. periodica
   */
  real prorata; 
  if (!_prorata.is_zero() && month != 13)
  {
    prorata = acquisti_iva * (_prorata / CENTO);
    prorata.round(ROUND_MILLELIRE);  
    acquisti_iva -= prorata;
  }
  look_plm(month, codatt, TRUE);   
  
  /*
   * ACHTUNG: l'iva sulle vendite e' calcolata sommando anche i 
   * corrispettivi che sono corrispettivi, a differenza dei corrispettivi
   * che non sono corrispettivi, ma tanto quelli (come si sa) non sono
   * corrispettivi. Dunque, non si tiene conto delle imposte calcolate
   * con la ventilazione (che vanno sottratte) ne' di quelle 
   * calcolate per le agenzie di viaggio (che sembra non vadano
   * comunque sottratte nel calcolo del volume di affari)
   */

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

  if (_isviaggio)
  {  
    real deb_mens = 0.0;
    _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);       
    
    // ---- NOTA BENE ------------------------
    // l'iva vendite nei plm non comprende 
    // l'iva agenzie di viaggio, calcolata
    // in liquidazione (mensile o trimestrale)
    // ---------------------------------------
    // Mod 7/7/95: calcolo effettuato anche qui, in modo da
    // avere l'IVA dovuta per riportarla nei progressivi
    // Dato che il resto funziona non tocco nulla, ovvero
    // duplico il calcolo di write_liq, nella remota ipotesi
    // che ci siano due o piu' attivita' e siano tutte
    // agenzie di viaggio
    real perc_r   = (acq_misCEE * CENTO)/(acq_misCEE + acq_misnoCEE); perc_r.round(2);
    real ivm      = (corr_misCEE * perc_r)/CENTO; ivm.round(ROUND_LIRA);
    real tc       = (corr_CEE + ivm);
    real ta       = (acq_CEE + acq_misCEE);
    real bi       = tc - ta - credito_costo_prec(month);

    if (bi.sign() > 0)
    {
      deb_mens    = (bi /((CENTO + aliquota_agvia())/CENTO)) *
                    (aliquota_agvia()/CENTO);
      deb_mens.ceil(ROUND_LIRA);   // ceil voluto MI3074 
    } 
    _pom->put("R13", deb_mens);
  }
  else if (_isagricolo)
  {                                
    _plm->put("R5",  agr_1);
    _plm->put("R6",  agr_2);
    _plm->put("R7",  agr_3);
    _plm->put("R8",  agr_4);
    _plm->put("R9",  agr_5);
    _plm->put("R10", agr_6);
    _plm->put("R11", agr_7); 
    _pum->put("R10", agr_1i);
    _pum->put("R11", agr_2i);
    
    // Il porco agricoltore spende poco e paga meno
    vendite_iva  = agr_2;   
    acquisti_iva = agr_3;

    // nuovo calcolo IVA detraibile 
    if (!agr_7.is_zero())
    {         
      real pdetr   = (agr_2i / (agr_1i + agr_2i));  
      pdetr.round(2);
      acquisti_iva += agr_7 * pdetr;
      acquisti_iva.round(ROUND_LIRA);
    }
  }

  _plm->put("R0",  vendite_iva);
  _plm->put("R1",  acquisti_iva);
  _plm->put("R3",  ult_detr);
  // probabilmente R4 serviva per il decalage e non si usera'
  _plm->put("R12", _prorata); // per comodita' in stampa
  _plm->put("B0",  "X");       // calcolato (invalidato dalla primanota)
  _pom->put("R9",  acq_ies);
  _pom->put("R10", acq_ies_iva);  
  _pum->put("R8",  acq_pint);
  _pum->put("R9",  acq_pint_iva); 
  _pam->put("R10", spgen);
  _pam->put("R11", spgen_iva); 
  _pom->put("R0",  totintra);  
  _pom->put("R1",  nond19_imp);  
  _pom->put("R2",  nond19_iva);  
  _pom->put("R3",  ammort_det);  
  _pom->put("R4",  ammort_det_iva);  
  _pom->put("R5",  acq_riv);  
  _pom->put("R6",  acq_riv_iva);  
  _pom->put("R7",  leasing);  
  _pom->put("R8",  leasing_iva);  
  _pom->put("R11", ammort_indet);  
  _pom->put("R12", ammort_indet_iva);  
  _pum->put("R0",  cess_amm);  
  _pum->put("R1",  cess_amm_iva);  
  _pum->put("R2",  ammort_6);  
  _pum->put("R3",  ammort_6_iva);
  _pum->put("R4",  esenti_b1);
  _pum->put("R5",  esenti_b2);
  _pum->put("R6",  esenti_b3);
  _pum->put("R7",  esenti_b14); 
  _pum->put("R12", esni_rimb);
  _pam->put("R0",  acquisti);
  _pam->put("R1",  vendite);  
  _pam->put("R6",  assp_imp);
  _pam->put("R7",  assp_iva);  
  _pam->put("R8",  vssp_imp);
  _pam->put("R9",  vssp_iva);
  _pam->put("R4",  bdog_imp);
  _pam->put("R5",  bdog_iva);  
  
  _plm->rewrite();
  _pam->rewrite();
  _pum->rewrite();
  _pom->rewrite();        
}          


void TLiquidazione_app::write_liq(int month, const char* codatts)
  // Calcolo liq. mensili e  liq. annuali
{
  TToken_string atts(codatts);
  const char* tmpatt;     
  
  // evita casino se differita ma si sta ricalcolando il primo
  // mese con ricalcolo di piu' mesi
  bool wasdifferita = (_isdifferita && month <= _monthinatt && 
                 _month > _monthinatt);

  if (wasdifferita) _isdifferita = FALSE;
  
  // liq. differita: considera mese precedente (solo per i risultati)                                    
  int deltam = month;                                    
  if (_isdifferita && !is_first_month(month) && month != 13)
    month -= (_freqviva == "T" ? 3 : 1);
  deltam -= month;
                
  real risultato    = 0.0;
  real detrazioni   = 0.0;
  real versamenti   = 0.0;
  real vers_int     = 0.0;
  real rimborsi     = 0.0;
  real rettifiche   = 0.0;   
  real res_debt     = 0.0;
  real res_cred     = 0.0;
  real cred_prec    = 0.0;
  real debt_precd   = 0.0;
  real acc_dec      = 0.0;
  real iva_vend     = 0.0;
  real iva_acq      = 0.0;
  real conguaglio   = 0.0;
  
  // totali per agenzie viaggio
  real c_iCEE       = 0.0;
  real c_eCEE       = 0.0;
  real a_iCEE       = 0.0;
  real a_eCEE       = 0.0;
  real c_mCEE       = 0.0;
  real a_mCEE       = 0.0;
  real a_meCEE      = 0.0;   
  real cred_cost    = 0.0;
  real deb_mens     = 0.0;
  real perc_r       = 0.0;       
  
  // totali per annuali
  real vol_aff_1    = 0.0;
  real vol_aff_2    = 0.0;
  real vol_aff_t    = 0.0;
  real vol_aff_l    = 0.0;
  real tot_cong     = 0.0;
  
  bool differita = FALSE;
  int attc = 0; // counter attivita'
  
  while ((tmpatt = atts.get()) != NULL)
  {
    TString att(tmpatt);
    
    if (_isdifferita && is_first_month(month))
    {
      // usa i totali del mese di dicembre dell'anno
      // precedente      
      differita = TRUE;
      TString yr(_year);
      _year = format("%d", atoi(_year)-1);
      if (!look_lim(12))
      { 
        _year = yr; 
        differita = FALSE;
      }
    }
    if (differita)
    { 
      if (attc == 0)
      {
        risultato  = result_liq(12);
        deb_mens   = _lim->get_real("R3");
        detrazioni = _lim->get_real("R6");
        perc_r     = _lim->get_real("R4");
        cred_cost  = _lim->get_real("R2");  
        rettifiche = _lim->get_real("R5");
        rimborsi   = _lim->get_real("R1");   
        // leggi anche tutti gli altri totali
        acc_dec    = _lim->get_real("R11");
        res_cred   = _lim->get_real("R12");
        res_debt   = _lim->get_real("R13");
        iva_vend   = _lam->get_real("R0"); 
        iva_acq    = _lam->get_real("R1"); 
        cred_prec  = _lam->get_real("R2");
        debt_precd = _lam->get_real("R3");
        _year      = format("%d", atoi(_year)+1); 
      }
    }                             
    else // puo' essere: differita e mese > 1 o non differita e mese qualunque
    {
      for (int m = 1; m <= 13; m++)
      {                             
        // ciclo su tutti i mesi del caso (1 o 3;
        // tutti se annuale)
        if (!is_month_ok(m, month)) 
          continue;
    
        look_plm(m, att); 
        bool is_lim = look_lim(m);
        
        // gia' conteggiato: prorata
        // da conteggiare: IVA vendite ag. viaggio
        // a debito:  IVA vendite, debito precedente
        // a credito: IVA acquisti, ulteriori detrazioni 1 e 2     
        
        iva_vend  += _plm->get_real("R0");
        iva_acq   += _plm->get_real("R1");
        risultato += (_plm->get_real("R0") - _plm->get_real("R1"));
        detrazioni+= (_plm->get_real("R3") + _plm->get_real("R4"));
        res_debt  += _plm->get_real("R0");
        res_cred  += _plm->get_real("R1");
        
        // detrazioni solo non in regime agricolo
        if (!_isagricolo)
        {
          risultato -= (_plm->get_real("R3") + _plm->get_real("R4")); 
          res_cred  += (_plm->get_real("R3") + _plm->get_real("R4"));
        }
        /* se annuale, somma versamenti mesi 1-12 
         * solo una volta (non per tutte le attivita')
         */
        if (attc == 0 && month == 13)
        { 
          // l'acconto a dicembre si conteggia a parte solo
          // nei casi previsti e non in annuale (vedi sotto)     
          // smentito!
          real vs(versamenti_IVA(m , m == 12 ? "1" : "1|7"));
          real vi(versamenti_IVA(m,"5"));
          versamenti += vs;
          vers_int   += vi;
          res_cred   += vs + vi;
        }
                
        /*
         * rimborso se chiesto e previsto 
         * in annuale non si chiede e non va sommato se no lo cumula
         */
        if (attc == 0 && is_lim && m < 13)
        {
          risultato += _lim->get_real("R1"); 
          rimborsi  += _lim->get_real("R1"); 
          res_debt  += _lim->get_real("R1");
        }                               
        /*
         * rettifiche gia' col loro bravo segno
         */
        if (attc == 0 && is_lim)
        {
          // se sono per benzinaro le conta solo in annuale, 
          // se no vanno solo in periodica 
          // almeno cosi' dicevano fino ad agosto
          // poi, sara' il caldo, mi hanno detto che e' sbagliato   
          TString descrett(_lim->get("S0"));
          bool isforbenzinaro = descrett[0] == '$' ||
                                (descrett[0] == '>' && descrett[1] == '>');
                                
          if (/*(isforbenzinaro && _isannual) ||  ...alla cincia quest'idea non piaceva piu'
              (!isforbenzinaro && !_isannual)    adesso la storia e' cosi':
               in ANNUALE solo se benzinaro, altrimenti niente; diversamente tutto*/
              !(month == 13 && !isforbenzinaro) && m < 13)  
          {
            risultato  += _lim->get_real("R5"); 
            rettifiche += _lim->get_real("R5"); 
            if (_lim->get_real("R5").sign() < 0)
              res_cred += abs(_lim->get_real("R5"));
            else
              res_debt += abs(_lim->get_real("R5"));
          }
        }

        /* totalizza importi 74 ter */           
        if (_isviaggio) 
        {
          // somma totali per calcolo successivo
          c_iCEE  += _plm->get_real("R5");
          c_eCEE  += _plm->get_real("R6");
          a_iCEE  += _plm->get_real("R7");
          a_eCEE  += _plm->get_real("R8");
          c_mCEE  += _plm->get_real("R9");
          a_mCEE  += _plm->get_real("R10");
          a_meCEE += _plm->get_real("R11");   
        }        
      } // fine ciclo sul mese  
      
      // counter attivita' per evitare troppi versamenti
      attc++;                                           
    } // fine else
    
    if (!(_isdifferita && is_first_month(month+deltam)))
    {   
      if (_isviaggio)
      {
        // calcolo credito costo, debito mensile, perc. ripart.
        perc_r   = (a_mCEE * CENTO)/(a_mCEE + a_meCEE); perc_r.round(2);
        real ivm = (c_mCEE * perc_r)/CENTO; ivm.round(ROUND_LIRA);
        real tc  = (c_iCEE + ivm);
        real ta  = (a_iCEE + a_mCEE);
        real bi  = tc - ta - credito_costo_prec(month);

        if (bi.sign() < 0)
          // credito di costo 
        {
          cred_cost = abs(bi); 
          cred_cost.round(ROUND_LIRA);
        }
        else
        {
          deb_mens    = (bi /((CENTO + aliquota_agvia())/CENTO)) *
                        (aliquota_agvia()/CENTO);
          deb_mens.ceil(ROUND_LIRA);   // ceil voluto MI3074 
          risultato  += deb_mens; 
          res_debt   += deb_mens; 
          iva_vend   += deb_mens;
        }
      }      
    }    
  } // end ciclo su attivita'
  
  if (!(_isdifferita && is_first_month(month+deltam))) 
  { 
    if (month < 13) // va bene anche se differita sommando deltam (che e' 0 normalmente)
    {
      // toglie credito precedente
      cred_prec  =  credito_prec(month+deltam);
      risultato -=  cred_prec; 
      res_cred  +=  cred_prec;
      // vedi se c'era un debito precedente per debiti < 50.000
      debt_precd = debt_prec(month+deltam);
      risultato += debt_precd;
      res_debt  += debt_precd;
    }
    else 
    { 
      // per l'annuale considera solo il credito a inizio anno
      cred_prec = credito_prec(_freqviva == "M" ? 1 : 3);
      risultato -=  cred_prec; 
      res_cred  +=  cred_prec;
    }
  } 


  if (month == 13)
  {
    // totalizza volumi affari e calcola nuovo prorata
    // per tutte le attivita' 
    atts.restart();
    while ((tmpatt = atts.get()) != NULL)
    {
      TString att(tmpatt); 
      int tipoatt = att[att.len() -1] - '0';
      if (tipoatt == 1) // su PLA l'attivita' e' sempre 1
      {
        look_pla(att);     
        real vf1 = _pla->get_real("R14");
        real vf2(_pla->get("S1"));              
        real iaq = _pla->get_real("R11"); // IVA acquisti
        real ppg = _pla->get_real("R12"); // pro-rata pagato
        
        vol_aff_1 += vf1;
        vol_aff_2 += vf2; 
        vol_aff_t  = vf1 + vf2;
        vol_aff_l += _pla->get_real("R0"); // volume affari lordo
        
        real es_b1 = _pla->get_real("R1");
        real es_b2 = _pla->get_real("R2");
        real es_b3 = _pla->get_real("R3");
        real csamm = _pla->get_real("R4");
        
        // calcola nuovo prorata per ogni attivita' (miste: 1+2)
        real ris = vol_aff_t;  // gia' esclusi: NS, B3, cess. amm
        real prorata(0.0); 
        if (!ris.is_zero())
          prorata = (es_b1/ris) * CENTO;
        real conguaglio = 0.0;
        prorata.round(ROUND_LIRA);
        if (prorata != _prorata)
        {
          // calcolo conguaglio -- se positivo e' a debito
          real topay = (iaq + ppg) * (prorata / CENTO); 
          topay.round(ROUND_MILLELIRE);
          conguaglio = topay - ppg;
          conguaglio.round(ROUND_MILLELIRE);
        }
        _pla->put("R9", conguaglio);        
        _pla->put("R10",prorata); 
        tot_cong += conguaglio;
        _pla->rewrite();
        
        // scrivi nuovo prorata in tabella anno successivo
        TString yr = _year;
        _year = format("%d", atoi(_year) + 1);
        look_pla(att, TRUE);
        _pla->put("R8", prorata);
        _pla->rewrite();
        look_lia();
        _lia->put("R5", cred_cost); 
        _lia->rewrite(); 
        _year = yr;         
      } 
    }                     

    look_lia();
    _lia->put("R1", vol_aff_l);
    _lia->put("R2", vol_aff_1);
    _lia->put("R3", vol_aff_2); 
    /***08/09/1995
    _lia->put("R4", acc_dec);
    ***/
    _lia->rewrite();
  }
  
  // comprende anche il conguaglio prorata
  risultato += tot_cong;
  if (tot_cong.sign() > 0) res_debt += tot_cong;
  if (tot_cong.sign() < 0) res_cred += abs(tot_cong);
                
  look_lim(month+deltam,TRUE);       
  // azzeriamo tutto (tranne r1, r5, s1, s0, s7)
  TString codtab = _lim->get("CODTAB");

  real    r5 = _lim->get("R5");
  real    r1 = _lim->get("R1");
  TString s7 = _lim->get("S7");  
  TString s0 = _lim->get("S0");  
  TString s1 = _lim->get("S1");  
  bool wasb0 = _lim->get_bool("B0");
  bool wasb1 = _lim->get_bool("B1");

  _lim->zero();
  _lim->put("CODTAB", codtab);
  _lim->put("R1", r1);  
  _lim->put("R5", r5);  
  _lim->put("S0", s0);  
  _lim->put("S1", s1);  
  _lim->put("S7", s7);           
  _lim->put("B0", wasb0 ? "X" : "");
  _lim->put("B1", wasb1 ? "X" : "");
  
  /* 
   * versamenti effettuati: si conteggiano in R0,
   * sono > 0 solo se andavano calcolati (vedi sopra)
   */
  risultato -= versamenti + vers_int;
  /* 
   * acconto dicembre se previsto
   */
  //if ((month == 12 && _isbenzinaro)  || 
  //    (month >= 12 && _freqviva == "M"))
  if (((month+deltam) >= 12 && _freqviva == "M") || //solo freq. M puo'
      (month == 12 && _isbenzinaro && _gest4) ||    //essere differita
      (_isannual && _freqviva == "T")) 
  {
    risultato -= versamenti_IVA(12,"7");
    acc_dec    = versamenti_IVA(12,"7");        
    res_cred  += acc_dec;
  }
  
  // in annuale si arrotondera' a 1000 in stampa 
  // se no il conguaglio prorata fa casino
  risultato.round(ROUND_LIRA);
                                
  _lim->put("R0",risultato); 
  _lim->put("R2",cred_cost); 
  _lim->put("R3",deb_mens); 
  _lim->put("R4",perc_r); 
 
  if (!_isagricolo)
    _lim->put("R6",detrazioni);  
  else // per evitare sbagli nei ricalcoli esterni
    _lim->put("R6","");
    
  if (month == 13 || differita)
  {
    // scrivi totali rettifiche e rimborsi
    // nella finale oppure se copiati da
    // anno precedente
    _lim->put("R1",rimborsi);
    _lim->put("R5",rettifiche);
  }
                                 
  /*
   * Interessi dovuti solo da trimestrali in periodica,
   * Era anche non benzinari, smentito da Cinzia (MI0853);
   * Ora gestito esplicitamente nei parametri ditta, forzato 
   * FALSE per ditte mensili e liq. annuale
   * Ulteriormente smentito e rettificato
   */              
  //if (_isintr && month < 13)
  bool true_trim = (month == 3 || month == 6 || month == 9);
  if (_isintr && ( true_trim || (month == 12 && _isbenzinaro && _gest4)
      || (month == 13 && !(_isbenzinaro && _gest4)) ))
  {
    real interesse = interesse_trimestrale(_month);
    real ivi = risultato * (interesse / CENTO); 
    ivi.ceil(ROUND_LIRA);
    _lim->put("R14", ivi); 
  }
  
  //questo serve anche per la visualizzazione e per l'estrazione deleghe  
  //if (_isintr && month < 13) 
  if (_isintr && ( true_trim || (month == 12 && _isbenzinaro && _gest4)
      || (month == 13 && !(_isbenzinaro && _gest4)) ))
    _lim->put("R10",interesse_trimestrale(_month));       
  
  // totale conguaglio su tutte le attivita'
  _lim->put("R7",  tot_cong);
  _lim->put("R8",  versamenti);
  _lim->put("R9",  vers_int);
  _lam->put("R0",  iva_vend);
  _lam->put("R1",  iva_acq);
  _lam->put("R2",  cred_prec);
  _lam->put("R3",  debt_precd);
  _lim->put("R11", acc_dec);
  _lim->put("R12", res_cred);  
  _lim->put("R13", res_debt);  
    
   
  if (!_recalc_only) 
    _lim->put("B0","X");   
    
  if (_isfinal) _lim->put("B1", "X");
  
  if (wasdifferita) _isdifferita = TRUE;

  // AWFUL! se siamo in annuale, occorre arrotondare alle 1000 lire
  // TUTTI gli ADDENDI e non il risultato. Cio' e' disonesto e mostruoso;
  // siccome sa di ricorso al TAR nonche' di errore della Prassi
  // schiaffo tutto il codice nell'IF che segue, e se lo si vuole togliere
  // non si fara' che scancellare tutto il blocco
  if (month == 13)
  {
    // molto codice duplicato, ma ne val la pena (vedi sopra)
    iva_vend.round(ROUND_MILLELIRE);
    iva_acq.round(ROUND_MILLELIRE);
    detrazioni.round(ROUND_MILLELIRE);
    versamenti.round(ROUND_MILLELIRE);
    vers_int.round(ROUND_MILLELIRE);
    rimborsi.round(ROUND_MILLELIRE);
    rettifiche.round(ROUND_MILLELIRE);
    deb_mens.round(ROUND_MILLELIRE);
    cred_prec.round(ROUND_MILLELIRE);
    tot_cong.round(ROUND_MILLELIRE);
    acc_dec.round(ROUND_MILLELIRE);
    debt_precd.round(ROUND_MILLELIRE);

    res_cred  = iva_acq + versamenti + vers_int + cred_prec + acc_dec;
    res_debt  = iva_vend + rimborsi + deb_mens + debt_precd;          
    
    if (tot_cong.sign() > 0) res_debt += tot_cong;
    else res_cred -= tot_cong;

    if (rettifiche.sign() > 0) res_debt += rettifiche;
    else res_cred -= rettifiche;

    if (!_isagricolo) res_cred  += detrazioni; 

//    res_debt.round();
//    res_cred.round();
    
//    TString r1(res_debt.string());
//    TString r2(res_cred.string());
    
//    real rd(r1);
//    real rc(r2);

    risultato = res_debt - res_cred;

//    TString   r3(risultato.string());
                
    // tut ricalcule', riscrivem
    _lim->put("R0",  risultato);          
    _lim->put("R2",  cred_cost); 
    _lim->put("R3",  deb_mens); 
    _lim->put("R1",  rimborsi);
    _lim->put("R5",  rettifiche);
    _lim->put("R7",  tot_cong);
    _lim->put("R8",  versamenti);
    _lim->put("R9",  vers_int);
    _lam->put("R0",  iva_vend);
    _lam->put("R1",  iva_acq);
    _lam->put("R2",  cred_prec);
    _lam->put("R3",  debt_precd);
    _lim->put("R11", acc_dec);
    _lim->put("R12", res_cred);  
    _lim->put("R13", res_debt);       
    // ciapa
  }

  _lim->rewrite();           
  _lam->rewrite();           
}

void TLiquidazione_app::recalc_annual(const char* att)
{
  // viene chiamata 2 volte per le att.  miste; PLA e' stata
  // azzerata dove serve da update_firm se siamo all'annuale
  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 iva_acq  = 0.0;
  real ven_lrd  = 0.0;  
  real volaff1  = 0.0;
  real volaff2  = 0.0;

  int tipoatt = att[strlen(att) -1] - '0';
  TString aaa(att);
  
  look_pla(aaa);
  volaff1  = _pla->get_real("R14");
  volaff2  = (const char*)_pla->get("S1");
  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");  
  pro_pag  = _pla->get_real("R12");
  iva_acq  = _pla->get_real("R11"); 

  for (_pim->first(); !_pim->eof();  _pim->next())
  {           
    if (_year != *_pim_anno) continue;
    
    int tipocr = atoi(*_pim_tipocr);
    TString16 codiva = *_pim_codiva;
    TString16 reg    = *_pim_codreg;      
    look_iva(codiva); look_reg(reg);  
    TString16 tiva = _iva->get("S1");
    int       biva = (int)_iva->get_long("I3");
    tiporeg   treg = (tiporeg)_reg->get_long("I0");
    bool      simp = _reg->get_bool("B1");
    
    if (                                        // ESCLUSI:      
        strcmp(att,*_pim_codatt) != 0   ||
        treg != vendita                 || //   non vendite
        tipocr == 4                     || //   cessioni beni ammortizzabili
        tiva == "NS"                    || //   non soggetti
        biva == 3                       || //   bi tre
        simp)                              //   sospensione di imposta 
      continue;
   
    if (tipoatt == 1) volaff1 += _pim->get_real("R0");
    else              volaff2 += _pim->get_real("R0");
  }

  // calcola esenti, cessioni, lordo vendite, prorata pagato
  // e IVA acquisti dai plm/ptm/pum/pam/pom 
  
  for (int i = 1; i <= 13; i++)
  {
    if (!look_plm(i,aaa))
      continue;

    vendite   += _pam->get_real("R1");
    iva_acq   += _plm->get_real("R1");
    es_b1     += _pum->get_real("R4");
    es_b2     += _pum->get_real("R5");
    es_b3     += _pum->get_real("R6");
    cess_amm  += _pum->get_real("R0"); 
    pro_pag   += _plm->get_real("R2");
  }
                             
  _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("R11", iva_acq);
  _pla->put("R12", pro_pag);
  _pla->put("R14", volaff1);      
  _pla->put("S1",  volaff2.string());      
  _pla->rewrite();
}

