Files correlati : sc1.exe Ricompilazione Demo : [ ] Commento : 0001618: 002458 - pharmatex - generazione abbuoni Descrizione richiedono una generazione automatica di abbuoni sul saldaconto, con massimale di abbuono da generare. Dovrà essere generata anche la registrazione contabile. git-svn-id: svn://10.65.10.50/branches/R_10_00@21529 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1182 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1182 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
// Esercizi contabili e registri IVA
 | 
						||
 | 
						||
#include "cglib01.h"
 | 
						||
 | 
						||
#include <diction.h>
 | 
						||
#include <mask.h>
 | 
						||
#include <tabutil.h>
 | 
						||
#include <recarray.h>
 | 
						||
#include <relation.h>
 | 
						||
 | 
						||
#include <clifo.h>
 | 
						||
#include <comuni.h>
 | 
						||
#include <pconti.h>
 | 
						||
#include <rcausali.h>
 | 
						||
#include <rmoviva.h>
 | 
						||
#include <rmov.h>
 | 
						||
 | 
						||
#include "comuni.h"
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// Gestione Tabella esercizi
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TArray TEsercizi_contabili::_esercizi;
 | 
						||
long TEsercizi_contabili::_firm = 0;
 | 
						||
 | 
						||
TEsercizio::TEsercizio(const TRectype& rec)
 | 
						||
{                   
 | 
						||
  _codice   = rec.get_int("CODTAB");
 | 
						||
  _inizio   = rec.get("D0");
 | 
						||
  _fine     = rec.get("D1");
 | 
						||
  _scarico  = rec.get("D2");
 | 
						||
  _chiusura = rec.get("D3");
 | 
						||
  _chiusura_mag = rec.get("D4");
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizio::compare(const TSortable& s) const
 | 
						||
{
 | 
						||
  const TEsercizio& e = (const TEsercizio&)s;
 | 
						||
  int c = 0;
 | 
						||
  if (_inizio != e._inizio) 
 | 
						||
    c = _inizio > e._inizio ? +1 : -1;
 | 
						||
  return c;  
 | 
						||
}
 | 
						||
 | 
						||
TEsercizi_contabili::TEsercizi_contabili()
 | 
						||
{ 
 | 
						||
}
 | 
						||
 | 
						||
void TEsercizi_contabili::update()
 | 
						||
{       
 | 
						||
  _firm = prefix().get_codditta();
 | 
						||
  _esercizi.destroy();
 | 
						||
  TTable tab_esc("ESC");
 | 
						||
  for (int err = tab_esc.first(); err == NOERR; err = tab_esc.next())
 | 
						||
  {
 | 
						||
    TEsercizio* e = new TEsercizio(tab_esc.curr());
 | 
						||
    _esercizi.add(e);
 | 
						||
  }              
 | 
						||
  _esercizi.sort();
 | 
						||
} 
 | 
						||
 | 
						||
void TEsercizi_contabili::check()
 | 
						||
{
 | 
						||
  if (_firm != prefix().get_codditta())
 | 
						||
    update();
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::date2index(const TDate& d) const
 | 
						||
{
 | 
						||
  int i = -1;
 | 
						||
  if (d.ok())
 | 
						||
  {
 | 
						||
    check();    
 | 
						||
    for (i = items()-1; i >= 0; i--)
 | 
						||
    {     
 | 
						||
      const TEsercizio& e = esc(i);
 | 
						||
      if (d >= e.inizio() && d <= e.fine())
 | 
						||
        break;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return i;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::esc2index(int codice) const
 | 
						||
{
 | 
						||
  int i = -1;
 | 
						||
  if (codice > 0)
 | 
						||
  {
 | 
						||
    check();    
 | 
						||
    for (i = items()-1; i >= 0; i--)
 | 
						||
    {     
 | 
						||
      const TEsercizio& e = esc(i);
 | 
						||
      if (codice == e.codice())
 | 
						||
        break;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return i;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::date2esc(const TDate& d) const
 | 
						||
{
 | 
						||
  const int i = date2index(d);
 | 
						||
  return i >= 0 ? esc(i).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::date2prevesc(const TDate& d) const
 | 
						||
{
 | 
						||
  const int i = date2index(d);
 | 
						||
  return i > 0 ? esc(i - 1).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::date2nextesc(const TDate& d) const
 | 
						||
{
 | 
						||
  const int i = date2index(d);
 | 
						||
  return i >=0 && i < items()-1 ? esc(i+1).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::first() const
 | 
						||
{
 | 
						||
  check();
 | 
						||
  return items() ? esc(0).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::last() const
 | 
						||
{
 | 
						||
  check();
 | 
						||
  return items() ? esc(items()-1).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
// Certified 99%
 | 
						||
int TEsercizi_contabili::last_mag() const
 | 
						||
{
 | 
						||
  check();            
 | 
						||
  int i;
 | 
						||
  
 | 
						||
  for (i = items()-1; i >= 0; i--)
 | 
						||
  {
 | 
						||
    const TEsercizio& e = esc(i);
 | 
						||
    if (e.chiusura_mag().ok())
 | 
						||
      break;
 | 
						||
  }
 | 
						||
  return esc(i+1).codice();
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
int TEsercizi_contabili::pred(int codice) const
 | 
						||
{
 | 
						||
  const int i = esc2index(codice);
 | 
						||
  return i > 0 ? esc(i-1).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
int TEsercizi_contabili::next(int anno) const
 | 
						||
{
 | 
						||
  const int i = esc2index(anno);
 | 
						||
  return i < items()-1 ? esc(i+1).codice() : 0;
 | 
						||
}
 | 
						||
 | 
						||
bool TEsercizi_contabili::exist(int codice) const
 | 
						||
{
 | 
						||
  const int i = esc2index(codice);
 | 
						||
  return i >= 0;
 | 
						||
}
 | 
						||
 | 
						||
const TEsercizio& TEsercizi_contabili::esercizio(int codice) const
 | 
						||
{
 | 
						||
  int i = esc2index(codice);
 | 
						||
  if (i < 0 && codice > 0)
 | 
						||
  {
 | 
						||
    error_box(FR("Attenzione! E' necessario aprire l'esercizio %d"), codice);
 | 
						||
    const int last_index = items()-1;
 | 
						||
    if (last_index >= 0)
 | 
						||
    {
 | 
						||
      TRectype rec(LF_TAB); rec.settab("ESC");
 | 
						||
      const TEsercizio& last = esc(last_index);
 | 
						||
      const int last_code = last.codice();
 | 
						||
      for (int k = last_code+1; k <= codice; k++)
 | 
						||
      {
 | 
						||
        rec.put("CODTAB", k);
 | 
						||
        TDate ini = last.inizio(); ini.set_year(ini.year()+k-last_code);
 | 
						||
        TDate fin = last.fine();   fin.set_year(fin.year()+k-last_code);
 | 
						||
        rec.put("D0", ini);
 | 
						||
        rec.put("D1", fin);
 | 
						||
        _esercizi.add(new TEsercizio(rec));
 | 
						||
      }
 | 
						||
    }     
 | 
						||
    else
 | 
						||
    {
 | 
						||
      if (codice > 2000)
 | 
						||
      {
 | 
						||
        TRectype rec(LF_TAB); rec.settab("ESC");
 | 
						||
        rec.put("CODTAB", codice);
 | 
						||
        rec.put("D0", TDate(1,1,codice));
 | 
						||
        rec.put("D1", TDate(31,12,codice));
 | 
						||
        _esercizi.add(new TEsercizio(rec));
 | 
						||
      }
 | 
						||
    }
 | 
						||
 | 
						||
    i = esc2index(codice); // Dovrei ritrovare l'ultimo
 | 
						||
  }
 | 
						||
  return esc(i);
 | 
						||
}
 | 
						||
 | 
						||
bool TEsercizi_contabili::code2range(int codice, TDate& dal, TDate& al) const
 | 
						||
{
 | 
						||
  bool ok = exist(codice);
 | 
						||
  if (ok)
 | 
						||
  {
 | 
						||
    const TEsercizio& e = esercizio(codice);
 | 
						||
    dal = e.inizio();
 | 
						||
    al = e.fine();
 | 
						||
  }
 | 
						||
  else
 | 
						||
  {
 | 
						||
    const int primo_esercizio = first();
 | 
						||
    const int ultimo_esercizio = last();
 | 
						||
    if (codice < primo_esercizio)
 | 
						||
    {
 | 
						||
      const TEsercizio& e = esercizio(primo_esercizio);
 | 
						||
      dal = e.inizio();
 | 
						||
      al = e.fine();
 | 
						||
      dal.addyear(primo_esercizio - codice);
 | 
						||
      al.addyear(primo_esercizio - codice);
 | 
						||
      ok = true;
 | 
						||
    }
 | 
						||
    if (codice > ultimo_esercizio)
 | 
						||
    {
 | 
						||
      const TEsercizio& e = esercizio(ultimo_esercizio);
 | 
						||
      dal = e.inizio();
 | 
						||
      al = e.fine();
 | 
						||
      dal.addyear(codice - ultimo_esercizio);
 | 
						||
      al.addyear(codice - ultimo_esercizio);
 | 
						||
      ok = true;
 | 
						||
    }
 | 
						||
 | 
						||
    if (!ok)
 | 
						||
    {
 | 
						||
      if(codice > 1900)
 | 
						||
      {
 | 
						||
        dal = TDate(1, 1, codice);
 | 
						||
        al =  TDate(31, 12, codice);
 | 
						||
        ok = true;
 | 
						||
      }
 | 
						||
      else
 | 
						||
        dal = al = TDate();
 | 
						||
    }
 | 
						||
  }   
 | 
						||
  return ok;
 | 
						||
}
 | 
						||
 | 
						||
TEsercizi_contabili & esercizi()
 | 
						||
{
 | 
						||
	HIDDEN TEsercizi_contabili __esercizi;
 | 
						||
 | 
						||
	return __esercizi;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/////////////////////////////////////////////////////////
 | 
						||
//	Simpatici metodi jolly
 | 
						||
/////////////////////////////////////////////////////////
 | 
						||
 | 
						||
 | 
						||
 | 
						||
const char* iva2name(TipoIVA iva)
 | 
						||
{
 | 
						||
  const char* i;
 | 
						||
  switch(iva)
 | 
						||
  {
 | 
						||
  case nessuna_iva: 
 | 
						||
    i = TR("Nessuna IVA"); break;
 | 
						||
  case iva_acquisti: 
 | 
						||
    i = TR("IVA Acquisti"); break;
 | 
						||
  case iva_vendite: 
 | 
						||
    i = TR("IVA Vendite"); break;
 | 
						||
  case iva_generica: 
 | 
						||
    i = TR("IVA Generica"); break;
 | 
						||
  default: 
 | 
						||
    i = TR("IVA ERRATA!"); break;
 | 
						||
  }
 | 
						||
  return i;
 | 
						||
}
 | 
						||
 | 
						||
const TString& cap2comune(const TString& cap, const TString& denom)
 | 
						||
{             
 | 
						||
  if (cap.len() == 5 && denom.full())
 | 
						||
  {
 | 
						||
    TString8 cappone = cap; 
 | 
						||
    if (cappone[2] == '1')	//e' un capoluogo di provincia
 | 
						||
		  cappone.overwrite("00", 3, 2);
 | 
						||
 | 
						||
    TString80 up_denom = denom; 
 | 
						||
    up_denom.upper();
 | 
						||
 | 
						||
    TRelation relcom(LF_COMUNI);
 | 
						||
    TRectype& comrec = relcom.curr();
 | 
						||
    comrec.put(COM_CAPCOM, cappone);
 | 
						||
 | 
						||
    TString4 codone;
 | 
						||
 | 
						||
	  TCursor comuni (&relcom, "", 3, &comrec, &comrec);
 | 
						||
	  const TRecnotype items = comuni.items();
 | 
						||
	  comuni.freeze();
 | 
						||
	  double cmp = 0.69;
 | 
						||
    for (comuni = 0L; comuni.pos() < items; ++comuni)
 | 
						||
    {
 | 
						||
      TString80 denominazione = comrec.get(COM_DENCOM);
 | 
						||
      denominazione.upper();
 | 
						||
		  const double fc = xvt_str_fuzzy_compare (up_denom, denominazione);
 | 
						||
		  if (fc > cmp)
 | 
						||
		  {
 | 
						||
			  codone = comrec.get(COM_COM);
 | 
						||
			  cmp = fc;
 | 
						||
		  }
 | 
						||
    }
 | 
						||
 | 
						||
    if (codone.full())
 | 
						||
      return get_tmp_string() = codone;
 | 
						||
  }
 | 
						||
  return EMPTY_STRING;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// Registro
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TRegistro::TRegistro(const char* cod, int year) 
 | 
						||
         : _rec(LF_TAB), _att(LF_ATTIV)
 | 
						||
{
 | 
						||
  read(cod, year);
 | 
						||
}
 | 
						||
 | 
						||
bool TRegistro::read(const char* cod, int year)
 | 
						||
{               
 | 
						||
  if (year <= 0) 
 | 
						||
  {
 | 
						||
    const TDate oggi(TODAY);
 | 
						||
    year = oggi.year();
 | 
						||
  }
 | 
						||
  if (cod == NULL)
 | 
						||
    cod = "";
 | 
						||
 | 
						||
  TString8 chiave; chiave.format("%04d%s", year, cod);
 | 
						||
  _rec = cache().get("REG", chiave);
 | 
						||
  read_att();  
 | 
						||
 | 
						||
  return !_rec.empty();
 | 
						||
}           
 | 
						||
 | 
						||
bool TRegistro::reread()
 | 
						||
{
 | 
						||
  if (ok()) 
 | 
						||
  {
 | 
						||
    const TString8 n(name());
 | 
						||
    const int y = year();
 | 
						||
    return read(n, y);
 | 
						||
  }  
 | 
						||
  return FALSE;
 | 
						||
}              
 | 
						||
 | 
						||
int TRegistro::year() const 
 | 
						||
{                
 | 
						||
  const TString& anno = _rec.get("CODTAB").left(4); 
 | 
						||
  return atoi(anno);
 | 
						||
}   
 | 
						||
 | 
						||
const TString& TRegistro::name() const 
 | 
						||
{ 
 | 
						||
  return _rec.get("CODTAB").mid(4);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TRegistro& TRegistro::operator =(const TRegistro& r)
 | 
						||
{ 
 | 
						||
  _rec = r._rec; 
 | 
						||
  _att = r._att;
 | 
						||
  _prorata = r._prorata;
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
int TRegistro::tipo() const
 | 
						||
{
 | 
						||
  const int t = _rec.get_int("I0");
 | 
						||
  return t;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TRegistro::corrispettivi() const
 | 
						||
{
 | 
						||
  const bool c = _rec.get_bool("B0");
 | 
						||
  return c;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TipoIVA TRegistro::iva() const
 | 
						||
{ 
 | 
						||
  TipoIVA i = (TipoIVA)tipo();
 | 
						||
  switch (i)
 | 
						||
  {
 | 
						||
  case nessuna_iva:
 | 
						||
  case iva_vendite:
 | 
						||
  case iva_acquisti:
 | 
						||
    break;
 | 
						||
  case libro_giornale:
 | 
						||
    i = nessuna_iva;
 | 
						||
    break;
 | 
						||
  default:  
 | 
						||
    error_box(FR("Il registro '%s' non e' un registro IVA o contabile: tipo %d"), 
 | 
						||
              (const char*)name(), i);
 | 
						||
    i = nessuna_iva;
 | 
						||
    break;
 | 
						||
  }
 | 
						||
  return i;     
 | 
						||
} 
 | 
						||
 | 
						||
bool TRegistro::read_att()
 | 
						||
{ 
 | 
						||
 | 
						||
  TString16 chiave;
 | 
						||
  chiave << prefix().get_codditta() << '|' << attivita();
 | 
						||
  
 | 
						||
  _att = cache().get(LF_ATTIV, chiave);
 | 
						||
  // Ditta - Anno - Attivita' - Tipo Attivita' (fissata a 1)
 | 
						||
  chiave.format("%05ld", prefix().get_codditta());
 | 
						||
  chiave << year();             // non fare << year() << attivita()
 | 
						||
  chiave << attivita() << "1";
 | 
						||
 | 
						||
  _prorata.destroy();
 | 
						||
    
 | 
						||
  const TRectype & pla = cache().get("%PLA", chiave);
 | 
						||
  if (!pla.empty())
 | 
						||
  {
 | 
						||
    chiave.format("%d", year());
 | 
						||
    _prorata.add(chiave, pla.get_real("R8"));
 | 
						||
    _att.put("TIPOATT", pla.get("S7")); // Aggiorna tipo attivita'
 | 
						||
  }  
 | 
						||
    
 | 
						||
  return !_att.empty();
 | 
						||
}
 | 
						||
 | 
						||
bool TRegistro::agenzia_viaggi()
 | 
						||
{                             
 | 
						||
  bool av = FALSE;
 | 
						||
  if (iva() == iva_vendite) 
 | 
						||
    av = _att.get_bool("REG74TER");
 | 
						||
  return av;
 | 
						||
}
 | 
						||
 | 
						||
const TString& TRegistro::tipo_attivita()
 | 
						||
{
 | 
						||
  return _att.get("TIPOATT");
 | 
						||
}
 | 
						||
 | 
						||
real* TRegistro::read_prorata(int anno) const
 | 
						||
{
 | 
						||
  TString16 chiave;      // Ditta - Anno - Attivita' - Tipo Attivita' (fissata a 1)
 | 
						||
  chiave.format("%05ld", prefix().get_codditta());
 | 
						||
  chiave << anno << attivita() << "1";
 | 
						||
 | 
						||
  real* prorata = NULL;
 | 
						||
  const TRectype& pla = cache().get("%PLA", chiave);
 | 
						||
 | 
						||
  if (!pla.empty())
 | 
						||
    prorata = new real(pla.get("R8"));
 | 
						||
    
 | 
						||
  return prorata;
 | 
						||
}
 | 
						||
 | 
						||
real TRegistro::prorata(int annodoc)
 | 
						||
{                
 | 
						||
  const int annoiva = year();
 | 
						||
  if (annodoc <= 1900) annodoc = annoiva; // Test per anno documento non specificato
 | 
						||
  const int annopro = annoiva >= 1998 && annodoc < annoiva ? annodoc+1 : annoiva;
 | 
						||
                                     
 | 
						||
  TString16 chiave; chiave << annopro;
 | 
						||
  real* pr = (real*)_prorata.objptr(chiave);
 | 
						||
  
 | 
						||
  if (pr == NULL)
 | 
						||
  {     
 | 
						||
    pr = read_prorata(annopro);
 | 
						||
    if (pr == NULL && annopro != annoiva)
 | 
						||
      pr = read_prorata(annoiva);
 | 
						||
 | 
						||
    if (pr == NULL)
 | 
						||
      pr = new real(ZERO);
 | 
						||
 | 
						||
    _prorata.add(chiave, pr, TRUE);
 | 
						||
  }
 | 
						||
  
 | 
						||
  return *pr;
 | 
						||
}
 | 
						||
 | 
						||
void TRegistro::set_prorata(int annodoc, const real& pro)
 | 
						||
{              
 | 
						||
  const int annoiva = year();
 | 
						||
  if (annodoc <= 1900) annodoc = annoiva; // Test per anno documento non specificato
 | 
						||
  const int annopro = annoiva >= 1998 && annodoc < annoiva ? annodoc+1 : annoiva;
 | 
						||
 | 
						||
  TString16 chiave; chiave << annopro;
 | 
						||
  _prorata.add(chiave, pro, TRUE);
 | 
						||
}
 | 
						||
 | 
						||
// Certified 99%                       
 | 
						||
bool TRegistro::update(long protiva, const TDate& datareg)
 | 
						||
{ 
 | 
						||
  bool updated = TRUE;
 | 
						||
  
 | 
						||
  if (protiva > _rec.get_long("I5"))
 | 
						||
  {
 | 
						||
    _rec.put("I5", protiva);
 | 
						||
    updated = FALSE;
 | 
						||
  }  
 | 
						||
  if (datareg > _rec.get_date("D2"))
 | 
						||
  {
 | 
						||
    _rec.put("D2", datareg);
 | 
						||
    updated = FALSE;
 | 
						||
  }  
 | 
						||
  if (!updated)
 | 
						||
  { 
 | 
						||
    TTable reg("REG");
 | 
						||
    updated = reg.rewrite(_rec) == NOERR;
 | 
						||
    cache().discard(_rec);  // Forza rilettura registro in cache
 | 
						||
  }  
 | 
						||
  
 | 
						||
  return updated;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// Libro giornale
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
// Legge il libro giornale dell'anno specificato
 | 
						||
bool TLibro_giornale::read(int y)
 | 
						||
{
 | 
						||
  bool found = FALSE;                 
 | 
						||
 | 
						||
  if (y <= 0) 
 | 
						||
  {
 | 
						||
    const TDate oggi(TODAY);
 | 
						||
    y = oggi.year();
 | 
						||
  }
 | 
						||
  
 | 
						||
  TString4 anno; anno.format("%04d", y);
 | 
						||
  TTable reg("REG");
 | 
						||
  reg.put("CODTAB", anno);                    // Cerca il primo registro dell'anno
 | 
						||
  
 | 
						||
  for (int err = reg.read(_isgteq); err == NOERR; err = reg.next())
 | 
						||
  {
 | 
						||
    if (reg.get("CODTAB").compare(anno, 4) != 0) 
 | 
						||
      break;                                  // Sono arrivato all'anno dopo
 | 
						||
    
 | 
						||
    if (reg.get_int("I0") == libro_giornale)
 | 
						||
    {       
 | 
						||
      found = TRUE;
 | 
						||
      break;
 | 
						||
    }  
 | 
						||
  }
 | 
						||
  
 | 
						||
  if (!found) reg.zero();                     // Memorizza record (anche vuoto)
 | 
						||
  _rec = reg.curr();
 | 
						||
  
 | 
						||
  return found;
 | 
						||
}
 | 
						||
 | 
						||
TLibro_giornale::TLibro_giornale(int y)
 | 
						||
{
 | 
						||
  read(y);
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// Codice IVA
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TCodiceIVA::TCodiceIVA(const char* cod) : TRectype(LF_TABCOM)
 | 
						||
{
 | 
						||
  read(cod);
 | 
						||
}                 
 | 
						||
 | 
						||
bool TCodiceIVA::read(const char* cod)
 | 
						||
{   
 | 
						||
  if (cod && *cod)
 | 
						||
    *this = cache().get("%IVA", cod);
 | 
						||
  else
 | 
						||
    zero();  
 | 
						||
 | 
						||
  return !empty();
 | 
						||
}               
 | 
						||
 | 
						||
real TCodiceIVA::imposta(const real& imponibile, int ndec, const char* codval) const
 | 
						||
{
 | 
						||
  const real percent = percentuale();
 | 
						||
  real iva = imponibile * percent / CENTO; 
 | 
						||
  
 | 
						||
  switch (ndec)
 | 
						||
  {
 | 
						||
  case AUTO_DECIMALS:
 | 
						||
    ndec = TExchange(codval).decimals(FALSE);
 | 
						||
    break;
 | 
						||
  case AUTO_PRICES_DECIMALS:
 | 
						||
    ndec = TExchange(codval).decimals(TRUE);
 | 
						||
    break;
 | 
						||
  default:
 | 
						||
    break;
 | 
						||
  }     
 | 
						||
  if (ndec < 20)
 | 
						||
  {                  
 | 
						||
    if (ndec == 0)  // VECCHIE LIRE!   
 | 
						||
    {
 | 
						||
      if (imponibile > ZERO)
 | 
						||
        iva.ceil(ndec);
 | 
						||
      else  
 | 
						||
        iva.floor(ndec);
 | 
						||
    }
 | 
						||
    else
 | 
						||
      iva.round(ndec);
 | 
						||
  }
 | 
						||
  return iva;
 | 
						||
}  
 | 
						||
 | 
						||
real TCodiceIVA::scorpora(real& lordo, int ndec, const char* codval) const
 | 
						||
{
 | 
						||
  const real percent = percentuale();
 | 
						||
  real iva = (lordo * percent) / (percent + CENTO); 
 | 
						||
  real imponibile = lordo - iva;
 | 
						||
 | 
						||
  switch (ndec)
 | 
						||
  {
 | 
						||
    case AUTO_DECIMALS:
 | 
						||
      ndec = TExchange(codval).decimals(FALSE);
 | 
						||
      break;
 | 
						||
    case AUTO_PRICES_DECIMALS:
 | 
						||
      ndec = TExchange(codval).decimals(TRUE);
 | 
						||
      break;
 | 
						||
    default:
 | 
						||
      break;
 | 
						||
  }     
 | 
						||
  if (ndec < 20) // E' richiesto un arrotondamento significativo?
 | 
						||
  {                  
 | 
						||
    lordo.round(ndec);      // Arrotondo importo lordo 
 | 
						||
    if (ndec == 0)          // Probabile caso Lire: arrotondo per eccesso l'IVA
 | 
						||
    {
 | 
						||
      if (imponibile > ZERO)
 | 
						||
        iva.ceil(ndec);
 | 
						||
      else  
 | 
						||
        iva.floor(ndec);
 | 
						||
    }
 | 
						||
    else
 | 
						||
      iva.round(ndec);      // Probabile caso Euro: arrotondo matematicamente l'IVA
 | 
						||
    imponibile.round(ndec); // Arrotondo imponibile 
 | 
						||
 | 
						||
    real diff = lordo - imponibile - iva;
 | 
						||
    diff.round(ndec);       // Arrotondo la differenza (importantissimo per evitare valori del tipo 1E-18)
 | 
						||
    if (!diff.is_zero())
 | 
						||
    {
 | 
						||
      if (iva.sign() == diff.sign()) // Faccio crescere l'iva o l'imponibile ?
 | 
						||
        iva += diff;
 | 
						||
      else
 | 
						||
        imponibile += diff;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  lordo = imponibile;  // lordo <20> un reference da aggiornare con l'imponibile!
 | 
						||
  return iva;
 | 
						||
}  
 | 
						||
 | 
						||
real TCodiceIVA::lordo(const real& imponibile, int ndec, const char* codval) const
 | 
						||
{
 | 
						||
  return imponibile + imposta(imponibile, ndec, codval);
 | 
						||
}  
 | 
						||
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TBill
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TBill::~TBill() 
 | 
						||
{
 | 
						||
  if (_descrizione)
 | 
						||
    delete _descrizione;
 | 
						||
}
 | 
						||
 | 
						||
void TBill::set_description(const char* d)
 | 
						||
{
 | 
						||
  if (_descrizione || (d && *d))
 | 
						||
  {
 | 
						||
    if (_descrizione)
 | 
						||
      *_descrizione = d;
 | 
						||
    else
 | 
						||
      _descrizione = new TString(d);
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
// Certified 90%
 | 
						||
const TBill& TBill::get(TToken_string& s, int from, int mode)
 | 
						||
{
 | 
						||
  const char* first = s.get(from);
 | 
						||
  if (mode & 0x1)
 | 
						||
  {
 | 
						||
    _tipo = first ? char(toupper(*first)) : ' ';
 | 
						||
    first = s.get();
 | 
						||
  } else _tipo = ' ';
 | 
						||
 | 
						||
#ifdef DBG
 | 
						||
  if (strchr(" CF", _tipo) == NULL)
 | 
						||
  {
 | 
						||
    error_box(FR("Tipo conto errato: '%c'"), _tipo);
 | 
						||
    _tipo = ' ';
 | 
						||
  }
 | 
						||
#endif
 | 
						||
 | 
						||
  _gruppo = first ? atoi(first) : 0;
 | 
						||
  _conto = s.get_int();
 | 
						||
  _sottoconto = s.get_long();
 | 
						||
  if (mode & 0x2)
 | 
						||
    set_description(s.get());
 | 
						||
    
 | 
						||
  _tipo_cr = -1;
 | 
						||
  _sezione = ' ';
 | 
						||
  
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
const TBill& TBill::copy(const TBill& bill)
 | 
						||
{
 | 
						||
  _tipo = bill._tipo;
 | 
						||
  _gruppo = bill._gruppo;
 | 
						||
  _conto = bill._conto;
 | 
						||
  _sottoconto = bill._sottoconto;
 | 
						||
  set_description(bill.descrizione());
 | 
						||
  _tipo_cr = bill._tipo_cr;
 | 
						||
  _sospeso = bill._sospeso;
 | 
						||
  _sezione = bill._sezione;
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// Certified 100%
 | 
						||
const TBill& TBill::set(int g, int c, long s, char t, const char* d, int r)
 | 
						||
{
 | 
						||
  _tipo = (t > ' ') ? char(toupper(t)) : ' ';
 | 
						||
  _gruppo = g;
 | 
						||
  _conto = c;
 | 
						||
  _sottoconto = s;
 | 
						||
  set_description(d);
 | 
						||
  _tipo_cr = r;
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
const TBill& TBill::add_to(TToken_string& ts, int from, int mode)
 | 
						||
{
 | 
						||
  if (mode & 0x4) 
 | 
						||
  {
 | 
						||
    const int cr = tipo_cr();
 | 
						||
    if (cr > 0) ts.add(cr, from++); else ts.add(" ", from++);
 | 
						||
  }  
 | 
						||
  
 | 
						||
  if (mode & 0x1) 
 | 
						||
    ts.add(_tipo, from++);
 | 
						||
  
 | 
						||
  if (_gruppo > 0) ts.add(_gruppo, from++); else ts.add(" ", from++);
 | 
						||
  if (_conto > 0) ts.add(_conto, from++); else ts.add(" ", from++);
 | 
						||
  if (_sottoconto > 0L) ts.add(_sottoconto, from++); else ts.add(" ", from++);
 | 
						||
  
 | 
						||
  if (mode & 0x2) 
 | 
						||
    ts.add(descrizione(), from++);
 | 
						||
  
 | 
						||
  return *this;  
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
const char* TBill::field_name(int n, const TRectype& r, bool contro) const
 | 
						||
{             
 | 
						||
  CHECKD(n >= 0 && n <= 3, "Invalid bill field ", n);        
 | 
						||
 | 
						||
  const char* f = NULL;
 | 
						||
  if (contro)
 | 
						||
  {
 | 
						||
    CHECKD(r.num() == LF_RMOV || r.num() == LF_PAGSCA, "Record non valido per contropartita: ", r.num());        
 | 
						||
    switch(n)
 | 
						||
    {
 | 
						||
    case 0: f = RMV_GRUPPOC; break;
 | 
						||
    case 1: f = RMV_CONTOC; break;
 | 
						||
    case 2: f = RMV_SOTTOCONTOC; break;
 | 
						||
    default:f = RMV_TIPOCC; break;
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  else
 | 
						||
  {
 | 
						||
    switch(n)
 | 
						||
    {
 | 
						||
    case 0: f = RMV_GRUPPO; break;
 | 
						||
    case 1: f = RMV_CONTO; break;
 | 
						||
    case 2: 
 | 
						||
      if (r.num() == LF_CLIFO)
 | 
						||
        f = CLI_CODCF;
 | 
						||
      else
 | 
						||
        f = RMV_SOTTOCONTO; 
 | 
						||
      break;
 | 
						||
    default:
 | 
						||
      switch(r.num())
 | 
						||
      {
 | 
						||
      case LF_CLIFO   : f = CLI_TIPOCF; break;
 | 
						||
      case LF_RCAUSALI: f = RCA_TIPOCF; break;
 | 
						||
      default         : f = RMV_TIPOC; break;
 | 
						||
      }
 | 
						||
      break;
 | 
						||
    }
 | 
						||
  }  
 | 
						||
  return f;
 | 
						||
}
 | 
						||
 | 
						||
void TBill::put(TRectype& r, bool c) const
 | 
						||
{  
 | 
						||
  r.put(field_name(0, r, c), gruppo());
 | 
						||
  r.put(field_name(1, r, c), conto());
 | 
						||
  r.put(field_name(2, r, c), sottoconto());
 | 
						||
  r.put(field_name(3, r, c), tipo());
 | 
						||
}
 | 
						||
 | 
						||
bool TBill::get(const TRectype& r, bool c)
 | 
						||
{ 
 | 
						||
  char t = ' ';
 | 
						||
  if (r.type(field_name(3, r, c)) != _nullfld)
 | 
						||
    t = r.get_char(field_name(3, r, c));
 | 
						||
 | 
						||
  set(r.get_int(field_name(0, r, c)), 
 | 
						||
      r.get_int(field_name(1, r, c)),
 | 
						||
      r.get_long(field_name(2, r, c)), 
 | 
						||
      t);
 | 
						||
  
 | 
						||
  set_description(NULL);
 | 
						||
  _tipo_cr = -1;
 | 
						||
  _sezione = ' ';
 | 
						||
  
 | 
						||
  if (r.num() == LF_RMOVIVA)      
 | 
						||
    tipo_cr(r.get_int(RMI_TIPOCR));
 | 
						||
  
 | 
						||
  return ok();
 | 
						||
}
 | 
						||
 | 
						||
void TBill::set(TMask& m, short g, short c, short s, short t, short d) const
 | 
						||
{
 | 
						||
  m.set(g, gruppo());
 | 
						||
  m.set(c, conto());
 | 
						||
  m.set(s, sottoconto());
 | 
						||
  if (t) 
 | 
						||
  {
 | 
						||
    char typ[2] = { tipo(), '\0' };
 | 
						||
    m.set(t, typ);
 | 
						||
  }  
 | 
						||
  if (d)
 | 
						||
    m.set(d, descrizione());
 | 
						||
}
 | 
						||
 | 
						||
void TBill::get(const TMask& m, short g, short c, short s, short t, short d)
 | 
						||
{
 | 
						||
  const int gr = m.get_int(g);
 | 
						||
  const int co = m.get_int(c);
 | 
						||
  const long so = m.get_long(s);
 | 
						||
  char ti = ' ';
 | 
						||
  if (t) 
 | 
						||
    ti = m.get(t)[0];
 | 
						||
  TString80 de;
 | 
						||
  if (d)  
 | 
						||
    de = m.get(d);
 | 
						||
  set(gr, co, so, ti, de);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// Certified 100%
 | 
						||
bool TBill::ok() const
 | 
						||
{
 | 
						||
  return _gruppo != 0 && _conto != 0 && _sottoconto != 0L;
 | 
						||
}
 | 
						||
 | 
						||
// Certified 99%
 | 
						||
int TBill::compare(const TSortable& s) const
 | 
						||
{
 | 
						||
  CHECK(class_name()==s.class_name(), "Can't compare TBill with TObject");
 | 
						||
  const TBill& c = (const TBill&)s;
 | 
						||
 | 
						||
  int res = _gruppo - c._gruppo;
 | 
						||
  if (res) return res;
 | 
						||
 | 
						||
  res = _conto - c._conto;
 | 
						||
  if (res) return res;
 | 
						||
 | 
						||
  const long lres = _sottoconto - c._sottoconto;
 | 
						||
  if (lres < 0L) res = -1; else
 | 
						||
    if (lres > 0L) res = +1;
 | 
						||
 | 
						||
  return res;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// Certified 95%
 | 
						||
bool TBill::find()
 | 
						||
{   
 | 
						||
  bool ok = FALSE;
 | 
						||
 | 
						||
  if ((_tipo != 'C' && _tipo != 'F') || _sottoconto == 0L)
 | 
						||
  {                 
 | 
						||
    TRectype pcon(LF_PCON);
 | 
						||
    ok = read(pcon);
 | 
						||
    if (!ok && _sottoconto != 0L)
 | 
						||
    {
 | 
						||
      const long sotto = _sottoconto;
 | 
						||
      _sottoconto = 0L;
 | 
						||
      if (read(pcon))
 | 
						||
         _tipo = char(toupper(pcon.get_char(PCN_TMCF)));
 | 
						||
      _sottoconto = sotto; 
 | 
						||
    }
 | 
						||
  } 
 | 
						||
  
 | 
						||
  if ((_tipo == 'C' || _tipo == 'F') && _sottoconto != 0L)
 | 
						||
  {
 | 
						||
    TString16 key;
 | 
						||
    key.format("%c|%ld", _tipo, _sottoconto);
 | 
						||
		const TRectype & clifo = cache().get(LF_CLIFO, key);
 | 
						||
    ok = !clifo.empty();
 | 
						||
    if (ok)
 | 
						||
    {        
 | 
						||
      set_description(clifo.get("RAGSOC"));
 | 
						||
      if (_tipo_cr < 0) 
 | 
						||
      {
 | 
						||
        _tipo_cr = 0;
 | 
						||
        _sezione = ' ';
 | 
						||
      }  
 | 
						||
      _sospeso = clifo.get_bool("SOSPESO"); 
 | 
						||
      
 | 
						||
      const char tipoa = clifo.get_char("TIPOPERS");
 | 
						||
      if (tipoa == 'F')  // Se persona fisica allora aggiusta la ragione sociale
 | 
						||
      {
 | 
						||
        TString nome(descrizione().mid(30));
 | 
						||
        if (nome.not_empty())
 | 
						||
        {
 | 
						||
          _descrizione->cut(30);
 | 
						||
          _descrizione->trim(); nome.trim();
 | 
						||
          *_descrizione << ' ' << nome;
 | 
						||
        }  
 | 
						||
      }
 | 
						||
      if (_gruppo == 0 || _conto == 0)
 | 
						||
      {
 | 
						||
        _gruppo = clifo.get_int("GRUPPO");
 | 
						||
        _conto = clifo.get_int("CONTO");
 | 
						||
      }
 | 
						||
    }  
 | 
						||
  }
 | 
						||
  return ok;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TBill::read(TRectype &r)
 | 
						||
{
 | 
						||
  bool ok = FALSE;
 | 
						||
 | 
						||
  if (tipo() <= ' ' || sottoconto() <= 0)
 | 
						||
  {
 | 
						||
    const char* key = string();
 | 
						||
    const TRectype& pcon = cache().get(LF_PCON, key);
 | 
						||
    if (!pcon.empty())
 | 
						||
    {
 | 
						||
      r = pcon;
 | 
						||
      ok = TRUE;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  if (ok)
 | 
						||
  {
 | 
						||
    _tipo_cr = r.get_int(PCN_TIPOSPRIC);    
 | 
						||
    _sezione = r.get_char(PCN_SEZSALDI);
 | 
						||
    set_description(r.get(PCN_DESCR));
 | 
						||
    _sospeso = r.get_bool(PCN_SOSPESO); 
 | 
						||
  }  
 | 
						||
  else
 | 
						||
    r.zero();  
 | 
						||
  
 | 
						||
  return ok;
 | 
						||
}
 | 
						||
 | 
						||
int TBill::tipo_att()
 | 
						||
{
 | 
						||
  int tipo_att = 1;
 | 
						||
  if (tipo() <= ' ' && ok())               
 | 
						||
  { 
 | 
						||
    TBill bill(gruppo(), conto());
 | 
						||
    TRectype rec(LF_PCON); bill.read(rec);
 | 
						||
    const TIndbil ib = (TIndbil)rec.get_int(PCN_INDBIL);
 | 
						||
    if (ib == ib_passivita || ib == ib_ricavi)
 | 
						||
    {
 | 
						||
      read(rec);
 | 
						||
      const int ricser = rec.get_int(PCN_RICSER);  // 0 = Altre attivita  1 = Servizi
 | 
						||
      tipo_att = (ricser == 1) ? 1 : 2;
 | 
						||
    }
 | 
						||
  }                      
 | 
						||
  return tipo_att;
 | 
						||
}  
 | 
						||
 | 
						||
// Certified 99%
 | 
						||
const TString& TBill::descrizione() const
 | 
						||
{                    
 | 
						||
  TBill& myself = (TBill&)*this;
 | 
						||
  // Se il conto e' valido (c'e' almeno il gruppo) cerca la sua descrizione su file
 | 
						||
  if ((_descrizione == NULL || _descrizione->blank()) && 
 | 
						||
       (gruppo() != 0 || (tipo() > ' ' && codclifo()>0)))
 | 
						||
  {
 | 
						||
    if (!myself.find()) 
 | 
						||
      myself.set_description(TR("Sconosciuto"));
 | 
						||
  }
 | 
						||
  
 | 
						||
  return _descrizione ? *_descrizione : (const TString&) EMPTY_STRING;
 | 
						||
}
 | 
						||
 | 
						||
int TBill::tipo_cr() const
 | 
						||
{
 | 
						||
  if (_tipo_cr < 0)
 | 
						||
  {
 | 
						||
    TBill& myself = (TBill&)*this;
 | 
						||
    myself.find();
 | 
						||
  }  
 | 
						||
  return _tipo_cr;
 | 
						||
}
 | 
						||
 | 
						||
int TBill::indicatore_bilancio() const
 | 
						||
{
 | 
						||
  TString8 str; 
 | 
						||
  str.format("%d|%d", gruppo(), conto());
 | 
						||
  const int ib = atoi(cache().get(LF_PCON, str, PCN_INDBIL));
 | 
						||
  if (ib <= 0)
 | 
						||
  {
 | 
						||
    TString msg = str;
 | 
						||
    msg.replace('|', '.');
 | 
						||
    msg.insert(TR("Impossibile stabilire l'indicatore di bilancio del conto "));
 | 
						||
    NFCHECK(msg);
 | 
						||
  }
 | 
						||
  return ib;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TBill::sospeso() const 
 | 
						||
{ 
 | 
						||
  if (_tipo_cr < 0) tipo_cr();  // trick to load _sospeso
 | 
						||
  return _sospeso; 
 | 
						||
}  
 | 
						||
 | 
						||
char TBill::sezione() const 
 | 
						||
{ 
 | 
						||
  if (_sezione == ' ') tipo_cr();  // trick to load _sezione
 | 
						||
  return _sezione; 
 | 
						||
}
 | 
						||
 | 
						||
// Certified 100%
 | 
						||
const char* TBill::string(int mode) const
 | 
						||
{
 | 
						||
  TString& s = get_tmp_string();
 | 
						||
 | 
						||
  if (mode & 0x8)
 | 
						||
  {
 | 
						||
    if (_sottoconto != 0)
 | 
						||
      s.format("%03d%03d%06ld", _gruppo, _conto, _sottoconto); else
 | 
						||
    if (_conto != 0)
 | 
						||
      s.format("%03d%03d", _gruppo, _conto); else
 | 
						||
    if (_gruppo != 0)
 | 
						||
      s.format("%03d", _gruppo);
 | 
						||
    return s;
 | 
						||
  }
 | 
						||
 | 
						||
  if (mode & 0x4)
 | 
						||
  {
 | 
						||
    const int cr = tipo_cr();
 | 
						||
    if (cr > 0) s << cr << '|';
 | 
						||
    else s << " |";
 | 
						||
  }  
 | 
						||
  
 | 
						||
  if (mode & 0x1)
 | 
						||
    s << _tipo << '|';
 | 
						||
  
 | 
						||
  if (_gruppo > 0) s << _gruppo  << '|';
 | 
						||
  else s << " |";
 | 
						||
  
 | 
						||
  if (_conto > 0) s << _conto  << '|';
 | 
						||
  else s << " |";
 | 
						||
  
 | 
						||
  if (_sottoconto > 0L) s << _sottoconto;
 | 
						||
  else s << ' ';
 | 
						||
  
 | 
						||
  if (mode & 0x2) 
 | 
						||
    s << '|' << descrizione();
 | 
						||
 | 
						||
  return s;
 | 
						||
}
 | 
						||
 | 
						||
bool TBill::required_cdc() const
 | 
						||
{
 | 
						||
  TString16 key; 
 | 
						||
  for (int i = 2; i >= 0; i--)
 | 
						||
  {
 | 
						||
    key.format("%d|%d|%ld", gruppo(), i > 0 ? conto() : 0, i > 1 ? sottoconto() : 0);
 | 
						||
    const TRectype& sottoc = cache().get(LF_PCON, key);
 | 
						||
    if (sottoc.get_bool(PCN_CMSNEEDED))
 | 
						||
      return true;
 | 
						||
  }
 | 
						||
  return false;
 | 
						||
}
 | 
						||
 | 
						||
bool TBill::default_cdc(TString& cdc, TString& fas) const
 | 
						||
{     
 | 
						||
  bool ok = tipo() <= ' ' && sottoconto() > 0;
 | 
						||
  if (ok)
 | 
						||
  {                
 | 
						||
    TString16 key; 
 | 
						||
    for (int i = 2; i >= 0; i--)
 | 
						||
    {
 | 
						||
      key.format("%d|%d|%ld", gruppo(), i > 0 ? conto() : 0, i > 1 ? sottoconto() : 0);
 | 
						||
      const TRectype& pcon = cache().get(LF_PCON, key);
 | 
						||
      if (!pcon.empty())
 | 
						||
      {
 | 
						||
        cdc = pcon.get(PCN_CODCMS);
 | 
						||
        fas = pcon.get(PCN_FASCMS);
 | 
						||
        if (cdc.not_empty() || fas.not_empty())
 | 
						||
          break;
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return ok && (cdc.not_empty() || fas.not_empty());
 | 
						||
}
 | 
						||
 | 
						||
bool TBill::is_analitico() const
 | 
						||
{
 | 
						||
  TString16 key; 
 | 
						||
 | 
						||
  for (int i = 2; i >= 0; i--)
 | 
						||
  {
 | 
						||
    key.format("%d|%d|%ld", gruppo(), i > 0 ? conto() : 0, i > 1 ? sottoconto() : 0);
 | 
						||
    const TRectype& picone = cache().get(LF_PCON, key);
 | 
						||
    if (picone.get_bool(PCN_ANALITICA))
 | 
						||
      return true;
 | 
						||
  }
 | 
						||
  return false;
 | 
						||
}
 | 
						||
 | 
						||
const char * num2str(const TString & s)
 | 
						||
{
 | 
						||
	TString & str = get_tmp_string(20);
 | 
						||
 | 
						||
	str = s;
 | 
						||
	str.trim();
 | 
						||
	if (str.len() > 2)
 | 
						||
	{
 | 
						||
		str = s.left(2);
 | 
						||
		const int sub = atoi(s.mid(2, 2));
 | 
						||
		const TString4 sotsub(s.mid(4));
 | 
						||
 | 
						||
		switch (sub)
 | 
						||
		{
 | 
						||
			case 0:
 | 
						||
			case 1:
 | 
						||
				break;
 | 
						||
			case 2:
 | 
						||
				str << " bis";
 | 
						||
				break;
 | 
						||
			case 3:
 | 
						||
				str << " ter";
 | 
						||
				break;
 | 
						||
			case 4:
 | 
						||
				str << " quater";
 | 
						||
				break;
 | 
						||
			case 5:
 | 
						||
				str << " quinquies";
 | 
						||
				break;
 | 
						||
			case 6:
 | 
						||
				str << " sexies";
 | 
						||
				break;
 | 
						||
			default:
 | 
						||
				break;
 | 
						||
		}
 | 
						||
		if (sotsub.full())
 | 
						||
			str << " " << sotsub;
 | 
						||
	}
 | 
						||
	return (const char *) str;
 | 
						||
}
 | 
						||
 |