2264 lines
54 KiB
C++
Executable File
2264 lines
54 KiB
C++
Executable File
// Esercizi contabili e registri IVA
|
||
|
||
#include "cglib.h"
|
||
|
||
#include <config.h>
|
||
#include <diction.h>
|
||
#include <mask.h>
|
||
#include <recset.h>
|
||
#include <relation.h>
|
||
#include <tabutil.h>
|
||
|
||
#include <clifo.h>
|
||
#include <comuni.h>
|
||
#include <mov.h>
|
||
#include <pconti.h>
|
||
#include <causali.h>
|
||
#include <rcausali.h>
|
||
#include <rmoviva.h>
|
||
#include <rmov.h>
|
||
|
||
#include <comuni.h>
|
||
#include "cgsaldac.h"
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Causale
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TCausale::TCausale(const char* cod, int year)
|
||
: TArray(12), _rec(LF_CAUSALI),
|
||
_iva(iva_errata), _corrisp(false),
|
||
_sezione_clifo(' '), _provvisorio(' '),
|
||
_sezione_ritsoc(' '), _sezione_ritfis(' '), _sezione_revcharge(' '),
|
||
_regolarizzazione(false)
|
||
|
||
|
||
{
|
||
if (cod && *cod)
|
||
read(cod, year);
|
||
if (soloiva())
|
||
{
|
||
TCursor c(new TRelation(LF_CAUSALI));
|
||
int items = c.items();
|
||
|
||
for (c = 0L; c.pos() < items && !_regolarizzazione; ++c)
|
||
_regolarizzazione = c.curr().get(CAU_CODCAUREG) == codice();
|
||
}
|
||
}
|
||
|
||
bool TCausale::reread()
|
||
{
|
||
const TString4 cod = codice();
|
||
|
||
if (cod.full())
|
||
{
|
||
const int year = _reg.year();
|
||
|
||
if (year > 0)
|
||
return read(cod, year);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// Legge le righe della causale attualmente selezionata sulla maschera
|
||
bool TCausale::read(const char* cod, int year)
|
||
{
|
||
_rec.zero(); // Delete header
|
||
destroy(); // Delete all rows
|
||
_iva = iva_errata; // Delete misc info
|
||
_sezione_clifo = _sezione_ritsoc = _provvisorio = ' ';
|
||
_corrisp = false;
|
||
|
||
if (cod && *cod > ' ')
|
||
{
|
||
_rec = cache().get(LF_CAUSALI, cod);
|
||
if (_rec.empty())
|
||
return false;
|
||
|
||
_provvisorio = _rec.get_char(CAU_PROVV);
|
||
TLocalisamfile rcaus(LF_RCAUSALI);
|
||
rcaus.put(CAU_CODCAUS, cod);
|
||
rcaus.put(CAU_NRIGA, 0);
|
||
|
||
int err;
|
||
for (err = rcaus.read(_isgteq); // Find first line
|
||
err == NOERR && rcaus.get(CAU_CODCAUS) == cod;
|
||
err = rcaus.next()) // Read next line
|
||
{
|
||
const int riga = rcaus.get_int(CAU_NRIGA);
|
||
add(rcaus.curr(), riga);
|
||
}
|
||
|
||
const TString4 codreg(_rec.get(CAU_REG));
|
||
const bool ok = _reg.read(codreg, year); // Read register
|
||
if (!ok && codreg.not_empty())
|
||
return error_box(FR("Non esiste il registro '%s' del %d"),
|
||
(const char*)codreg, year);
|
||
calcIVA();
|
||
}
|
||
else
|
||
{
|
||
_iva = nessuna_iva; // Clear IVA data
|
||
_corrisp = false;
|
||
_reg.read("", year);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
TBill& TCausale::bill(int num, TBill& conto) const
|
||
{
|
||
const TRectype* rec = row(num);
|
||
|
||
if (rec != nullptr)
|
||
conto.set(rec->get_int(RCA_GRUPPO), rec->get_int(RCA_CONTO),
|
||
rec->get_long(RCA_SOTTOCONTO), rec->get_char(RCA_TIPOCF));
|
||
return conto;
|
||
}
|
||
|
||
const char* TCausale::cod_desc_agg(int num) const
|
||
{
|
||
const TRectype* rec = row(num);
|
||
if (rec)
|
||
return rec->get(RCA_CODDESC);
|
||
return ""; // ho problemi con ? :
|
||
}
|
||
|
||
const char* TCausale::desc_agg(int num) const
|
||
{
|
||
const char* cod = cod_desc_agg(num);
|
||
if (cod && *cod)
|
||
return cache().get("%DPN", cod, "S0");
|
||
return ""; // ho problemi con ? :
|
||
}
|
||
|
||
const char* TCausale::descrizione() const
|
||
{
|
||
return _rec.get(CAU_DESCR);
|
||
}
|
||
|
||
const char* TCausale::codice() const
|
||
{
|
||
return _rec.get(CAU_CODCAUS);
|
||
}
|
||
|
||
bool TCausale::data_doc() const
|
||
{
|
||
return _rec.get_bool(CAU_DATADOC);
|
||
}
|
||
|
||
bool TCausale::num_doc() const
|
||
{
|
||
return _rec.get_bool(CAU_NUMDOC);
|
||
}
|
||
|
||
bool TCausale::apertura() const
|
||
{
|
||
return _rec.get_char(CAU_MOVAP) == 'A';
|
||
}
|
||
|
||
bool TCausale::chiusura() const
|
||
{
|
||
return _rec.get_char(CAU_MOVAP) == 'C';
|
||
}
|
||
|
||
bool TCausale::sezionale() const
|
||
{
|
||
return _rec.get_bool(CAU_MOVSEZ);
|
||
}
|
||
|
||
bool TCausale::valuta() const
|
||
{
|
||
return _rec.get_bool(CAU_MOVVAL);
|
||
}
|
||
|
||
bool TCausale::intra() const
|
||
{
|
||
return _rec.get_bool(CAU_INTRACOM);
|
||
}
|
||
|
||
bool TCausale::valintra() const
|
||
{
|
||
return _rec.get_bool(CAU_VALINTRA);
|
||
}
|
||
|
||
bool TCausale::soloiva() const
|
||
{
|
||
return _rec.get_bool(CAU_SOLOIVA);
|
||
}
|
||
|
||
int TCausale::regime_speciale() const
|
||
{
|
||
return _rec.get_int(CAU_REGSPIVA);
|
||
}
|
||
|
||
bool TCausale::regolarizzazione() const
|
||
{
|
||
return _regolarizzazione;
|
||
}
|
||
|
||
bool TCausale::ril_fat_em_ric() const
|
||
{
|
||
return _rec.get_bool(CAU_RILFTEMRI);
|
||
}
|
||
|
||
bool TCausale::datareg_prec() const
|
||
{
|
||
return _rec.get_bool(CAU_DATAREGPR);
|
||
}
|
||
|
||
bool TCausale::reverse_charge() const
|
||
{
|
||
const int rsi = regime_speciale();
|
||
return (rsi >= 13 && rsi <= 18) || rsi == 50 || rsi == 51; // Reverse charge!
|
||
}
|
||
|
||
bool TCausale::reverse_charge_pubb() const
|
||
{
|
||
const int rsi = regime_speciale();
|
||
return (rsi >= 13 && rsi <= 19) || rsi == 50 || rsi == 51; // Reverse charge!
|
||
}
|
||
|
||
bool TCausale::esclusione_allegati() const
|
||
{
|
||
return _rec.get_bool(CAU_ALLEG);
|
||
}
|
||
|
||
const TString& TCausale::causale_collegata() const
|
||
{
|
||
return _rec.get(CAU_CODCAUSIM);
|
||
}
|
||
|
||
const TString& TCausale::causale_reg_iva() const
|
||
{
|
||
return _rec.get(CAU_CODCAUREG);
|
||
}
|
||
|
||
const TString& TCausale::tipo_doc() const
|
||
{
|
||
return _rec.get(CAU_TIPODOC);
|
||
}
|
||
|
||
tipo_movimento TCausale::tipomov() const
|
||
{
|
||
return tipo_movimento(_rec.get_int(CAU_TIPOMOV));
|
||
}
|
||
|
||
const TString& TCausale::tipodoc() const
|
||
{
|
||
return _rec.get(CAU_TIPODOC);
|
||
}
|
||
|
||
bool TCausale::saldaconto(const TDate& datareg) const
|
||
{
|
||
bool yes = tipomov() > 0;
|
||
if (yes && datareg.ok())
|
||
{
|
||
static TDate _data_sal = ini_get_string(CONFIG_DITTA, "cg", "DatSal");
|
||
yes = datareg >= _data_sal;
|
||
}
|
||
return yes;
|
||
}
|
||
|
||
int TCausale::link_m770() const
|
||
{
|
||
return _rec.get_int(CAU_M770);
|
||
}
|
||
|
||
char TCausale::link_cespiti() const
|
||
{
|
||
return _rec.get_char(CAU_COLLCESP);
|
||
}
|
||
|
||
bool TCausale::link_analitica() const
|
||
{
|
||
return _rec.get_bool(CAU_MOVIND);
|
||
}
|
||
|
||
bool TCausale::link_industriale() const
|
||
{
|
||
return _rec.exist(CAU_MOVCGIND) && _rec.get_bool(CAU_MOVCGIND);
|
||
}
|
||
|
||
bool TCausale::ok() const
|
||
{
|
||
return iva() != iva_errata;
|
||
}
|
||
|
||
char TCausale::sezione(int riga, bool low_level) const
|
||
{
|
||
const TRectype* rec = row(riga);
|
||
char sez = rec ? toupper(rec->get_char(RCA_SEZIONE)) : ' ';
|
||
if (sez <= ' ' && !low_level) // Guess section on tipocf
|
||
{
|
||
const TRectype* uno = row(1);
|
||
char tipocf = uno ? toupper(uno->get_char(RCA_TIPOCF)) : ' ';
|
||
if (tipocf <= ' ')
|
||
tipocf = (iva() == iva_vendite) ? 'C' : 'F'; // Guess tipocf on IVA
|
||
sez = (tipocf == 'C') ? 'D' : 'A';
|
||
}
|
||
return sez;
|
||
}
|
||
|
||
char TCausale::sezione_clifo() const
|
||
{
|
||
if (_sezione_clifo <= ' ')
|
||
(char&)_sezione_clifo = sezione(1);
|
||
return _sezione_clifo;
|
||
}
|
||
|
||
char TCausale::sezione_ritsoc() const
|
||
{
|
||
if (_sezione_ritsoc <= ' ')
|
||
{
|
||
const tipo_movimento tm = tipomov();
|
||
(char&)_sezione_ritsoc = sezione(tm <= tm_nota_credito ? RIGA_RITENUTE_SOCIALI : RIGA_PAG_RITSOC, true);
|
||
if (_sezione_ritsoc < 'A')
|
||
(char&)_sezione_ritsoc = (tm <= tm_nota_credito ? sezione_clifo() : (sezione_clifo() == 'D' ? 'A' : 'D'));
|
||
}
|
||
return _sezione_ritsoc;
|
||
}
|
||
|
||
char TCausale::sezione_ritfis() const
|
||
{
|
||
if (_sezione_ritfis == ' ')
|
||
{
|
||
const tipo_movimento tm = tipomov();
|
||
(char&)_sezione_ritfis = sezione(tm <= tm_nota_credito ? RIGA_RITENUTE_FISCALI : RIGA_PAG_RITFIS, true); // Fatture o Pagamenti
|
||
if (_sezione_ritfis < 'A')
|
||
(char&)_sezione_ritfis = (tm <= tm_nota_credito ? sezione_clifo() : (sezione_clifo() == 'D' ? 'A' : 'D'));
|
||
}
|
||
return _sezione_ritfis;
|
||
}
|
||
|
||
char TCausale::sezione_revcharge() const
|
||
{
|
||
if (_sezione_revcharge <= ' ')
|
||
{
|
||
(char&)_sezione_revcharge = sezione(RIGA_REVERSE_CHARGE);
|
||
if (_sezione_revcharge < 'A')
|
||
(char&)_sezione_revcharge = sezione_clifo();
|
||
}
|
||
return _sezione_revcharge;
|
||
}
|
||
|
||
bool TCausale::fattura_in_ritardo() const
|
||
{
|
||
return _rec.get_bool(CAU_RITFATT);
|
||
}
|
||
|
||
|
||
void TCausale::calcIVA()
|
||
{
|
||
TipoIVA i = nessuna_iva; // Tipo IVA di default
|
||
bool c = false; // Corrispettivi di default
|
||
|
||
const TString& td = tipo_doc();
|
||
if (td.full())
|
||
{
|
||
const TRectype& tpd = cache().get("%TPD", td);
|
||
if (!tpd.empty())
|
||
{
|
||
i = (TipoIVA)tpd.get_int("I0"); // IVA acquisti, vendite, generica
|
||
const TipoIVA ri = _reg.iva();
|
||
if (i == iva_generica)
|
||
i = ri;
|
||
if (i != ri)
|
||
{
|
||
error_box(FR("Tipo documento '%s' incompatibile con tipo registro"), (const char*)td);
|
||
i = iva_errata;
|
||
}
|
||
c = tpd.get_bool("B0"); // B0 flag corrispettivi
|
||
}
|
||
else
|
||
error_box(FR("Tipo documento sconosciuto: '%s'"), (const char*)td);
|
||
}
|
||
_iva = i;
|
||
_corrisp = c;
|
||
}
|
||
|
||
const TString& TCausale::compatible(const TCausale& c) const
|
||
{
|
||
const char* err = nullptr;
|
||
|
||
if (sezionale() != c.sezionale())
|
||
err = TR("il segnale di sezionale");
|
||
if (intra() != c.intra())
|
||
err = TR("la gestione dei movimenti intra");
|
||
if (valuta() != c.valuta())
|
||
err = TR("la gestione valuta");
|
||
if (valintra() != c.valintra())
|
||
err = TR("la gestione valuta intracomunitaria");
|
||
if (corrispettivi() != c.corrispettivi())
|
||
err = TR("la gestione dei corrispettivi");
|
||
if (iva() != c.iva())
|
||
err = TR("il tipo di IVA");
|
||
if (tipomov() != c.tipomov())
|
||
err = TR("il tipo di movimento");
|
||
|
||
if (err != nullptr)
|
||
{
|
||
TString& msg = get_tmp_string();
|
||
|
||
msg.format(FR("Causale incompatibile per %s"), err);
|
||
return msg;
|
||
}
|
||
|
||
return EMPTY_STRING;
|
||
}
|
||
|
||
bool TCausale::IVA2bill(const TCodiceIVA& iva, TBill& c) const
|
||
{
|
||
const TString& tipo = iva.tipo();
|
||
|
||
if (tipo.not_empty())
|
||
{
|
||
if (tipo == "ES") bill(5, c); else
|
||
if (tipo == "NI") bill(6, c); else
|
||
if (tipo == "NS") bill(7, c);
|
||
}
|
||
|
||
if (!c.ok())
|
||
bill(2, c);
|
||
|
||
const int spric = c.tipo_cr();
|
||
if (spric == 2 || spric == 3)
|
||
{
|
||
const TString& td = tipo_doc();
|
||
if (td == "FV" || td == "NC")
|
||
c.tipo_cr(4);
|
||
}
|
||
|
||
return c.ok();
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TCache_causali
|
||
///////////////////////////////////////////////////////////
|
||
class TCache_causale : public TCache
|
||
{
|
||
protected:
|
||
virtual TObject* key2obj(const char* key);
|
||
|
||
public:
|
||
const TCausale & caus(const char* key, const int anno = 0);
|
||
|
||
TCache_causale() : TCache() { }
|
||
virtual ~TCache_causale() { }
|
||
};
|
||
|
||
TObject* TCache_causale::key2obj(const char* key)
|
||
{
|
||
TToken_string k(key);
|
||
TString4 cod;
|
||
k.get(0, cod);
|
||
cod.trim();
|
||
int year; k.get(1, year);
|
||
return new TCausale(cod, year);
|
||
}
|
||
|
||
const TCausale & TCache_causale::caus(const char* key, const int anno)
|
||
{
|
||
TToken_string k(key);
|
||
k.add(anno);
|
||
return (const TCausale &)*objptr(k);
|
||
}
|
||
|
||
const TCausale & cached_causale(const char * codcaus, int year)
|
||
{
|
||
HIDDEN TCache_causale __cache_causale;
|
||
|
||
return __cache_causale.caus(codcaus, year);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// 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;
|
||
}
|
||
|
||
const TDate& TEsercizio::chiusura() const
|
||
{
|
||
if (!_chiusura.ok() && fine() < TDate(TODAY))
|
||
{
|
||
TAssoc_array chiusure; // Lista delle causali di chiusura (solitamente una!)
|
||
TISAM_recordset caus("USE CAUS SELECT MOVAP='C'");
|
||
for (bool ok = caus.move_first(); ok; ok = caus.move_next())
|
||
{
|
||
const TString& codcaus = caus.get(CAU_CODCAUS).as_string();
|
||
chiusure.add(codcaus, codcaus);
|
||
}
|
||
|
||
const TDate presto = fine(); // Prima data utile per chiusura esercizio
|
||
TDate tardi = presto; tardi.addyear(); // Ultima data utile per chiusura esercizio
|
||
|
||
TString query;
|
||
query = "USE MOV KEY 2";
|
||
if (chiusure.items() == 1)
|
||
{
|
||
const TString& codcaus = *(TString*)chiusure.first_item();
|
||
query << " SELECT CODCAUS='" << codcaus << '\'';
|
||
}
|
||
query << "\nFROM DATAREG=#PRESTO\nTO DATAREG=#TARDI";
|
||
TISAM_recordset mov(query);
|
||
mov.set_var("#PRESTO", presto);
|
||
mov.set_var("#TARDI", tardi);
|
||
for (bool ok = mov.move_first(); ok; ok = mov.move_next())
|
||
{
|
||
const TString& codcaus = mov.get(MOV_CODCAUS).as_string();
|
||
if (chiusure.is_key(codcaus))
|
||
{
|
||
const TDate datacomp = mov.get(MOV_DATACOMP).as_date();
|
||
if (datacomp <= presto)
|
||
{
|
||
((TDate&)_chiusura) = datacomp; // Forzatura
|
||
TTable esc("ESC");
|
||
esc.put("CODTAB", codice());
|
||
if (esc.read(_isequal, _lock) == NOERR)
|
||
{
|
||
esc.put("D3", datacomp);
|
||
esc.rewrite();
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return _chiusura;
|
||
}
|
||
|
||
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)
|
||
{
|
||
TString80 up_denom = denom;
|
||
up_denom.upper();
|
||
TString4 codone;
|
||
|
||
if (cap.len() == 5 && up_denom.full())
|
||
{
|
||
TString8 cappone = cap;
|
||
if (cappone[2] == '1') //e' un capoluogo di provincia
|
||
cappone.overwrite("00", 3, 2);
|
||
|
||
TRelation relcom(LF_COMUNI);
|
||
TRectype& comrec = relcom.curr();
|
||
comrec.put(COM_CAPCOM, cappone);
|
||
|
||
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.blank() && denom.full())
|
||
{
|
||
TLocalisamfile comuni(LF_COMUNI);
|
||
comuni.setkey(2);
|
||
comuni.put(COM_DENCOM, denom);
|
||
if (comuni.read() == NOERR)
|
||
codone = comuni.get(COM_COM);
|
||
else
|
||
{
|
||
double cmp = 0.9;
|
||
comuni.zero();
|
||
const TString4 pref = up_denom.left(4);
|
||
comuni.put(COM_DENCOM, pref);
|
||
for (int err = comuni.read(_isgteq); err == NOERR; err = comuni.next())
|
||
{
|
||
TString80 denominazione = comuni.get(COM_DENCOM);
|
||
denominazione.upper();
|
||
if (!denominazione.starts_with(pref))
|
||
break;
|
||
const double fc = xvt_str_fuzzy_compare(up_denom, denominazione);
|
||
if (fc > cmp)
|
||
{
|
||
cmp = fc;
|
||
codone = comuni.get(COM_COM);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return codone.full() ? (get_tmp_string() = codone) : EMPTY_STRING;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Registro
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TRegistro::TRegistro(const char* cod, int year)
|
||
: _rec(LF_TAB), _att(LF_ATTIV)
|
||
{ read(cod, year); }
|
||
|
||
TRegistro::TRegistro(const TRegistro & reg)
|
||
: _rec(LF_TAB), _att(LF_ATTIV)
|
||
{
|
||
const int year = atoi(reg._rec.get("CODTAB").sleft(4));
|
||
const TString8 cod = reg._rec.get("CODTAB").smid(4);
|
||
|
||
read(cod, year);
|
||
}
|
||
|
||
bool TRegistro::read(const char* cod, int year)
|
||
{
|
||
if (year <= 0)
|
||
{
|
||
const TDate oggi(TODAY);
|
||
year = oggi.year();
|
||
}
|
||
if (cod == nullptr)
|
||
cod = "";
|
||
|
||
TString8 chiave; chiave.format("%04d%s", year, cod);
|
||
_rec = cache().get("REG", chiave);
|
||
read_att();
|
||
|
||
return !_rec.empty();
|
||
}
|
||
|
||
bool TRegistro::force_read(const char* cod, int year)
|
||
{
|
||
TString8 chiave; chiave.format("%04d%s", year, cod);
|
||
|
||
cache().discard("REG", chiave);
|
||
return read(cod, year);
|
||
}
|
||
|
||
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 - Attivit<69> - Tipo Attivit<69> (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 attivit<69>
|
||
}
|
||
|
||
return !_att.empty();
|
||
}
|
||
|
||
bool TRegistro::agenzia_viaggi() const
|
||
{
|
||
return _att.get_bool("REG74TER") && (iva() == iva_vendite);
|
||
}
|
||
|
||
const TString& TRegistro::tipo_attivita() const
|
||
{
|
||
return _att.get("TIPOATT");
|
||
}
|
||
|
||
real* TRegistro::read_prorata(int anno) const
|
||
{
|
||
TString16 chiave; // Ditta - Anno - Attivit<69> - Tipo Attivit<69> (fissata a 1)
|
||
chiave.format("%05ld", prefix().get_codditta());
|
||
chiave << anno << attivita() << "1";
|
||
|
||
real* prorata = nullptr;
|
||
|
||
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 == nullptr)
|
||
{
|
||
pr = read_prorata(annopro);
|
||
if (pr == nullptr && annopro != annoiva)
|
||
pr = read_prorata(annoiva);
|
||
|
||
if (pr == nullptr)
|
||
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 <= 2000) annodoc = annoiva; // Test per anno documento non specificato
|
||
const int annopro = annodoc < annoiva ? annodoc+1 : annoiva;
|
||
TString4 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("REG", _rec.get("CODTAB")); // 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)
|
||
{
|
||
TEsercizi_contabili esc;
|
||
const int lastes = esc.last();
|
||
if (lastes > 0)
|
||
y = esc[lastes].inizio().year();
|
||
else
|
||
y = TDate(TODAY).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);
|
||
}
|
||
|
||
int TCodiceIVA::tipo_indetraibilita() const
|
||
{
|
||
int tipo = 0;
|
||
const TString& codind = indetraibilita(); // Codice indetraibilit<69> alfanumerico (ex. 1, 3, 9)
|
||
if (codind.full())
|
||
{
|
||
const TRectype& det = cache().get("%DET", codind);
|
||
if (det.empty())
|
||
tipo = atoi(codind);
|
||
else
|
||
tipo = det.get_int("I0");
|
||
}
|
||
return tipo; // Tipo indetraibilit<69>: 1,3,9
|
||
}
|
||
|
||
bool TCodiceIVA::read(const char* cod)
|
||
{
|
||
if (cod && *cod)
|
||
*this = cache().get("%IVA", cod);
|
||
else
|
||
zero();
|
||
|
||
return !empty();
|
||
}
|
||
|
||
void TCodiceIVA::round(real& n, int ndec, const char* codval) const
|
||
{
|
||
switch (ndec)
|
||
{
|
||
case AUTO_DECIMALS : ndec = (codval && *codval) ? TExchange(codval).decimals(false) : 2; break;
|
||
case AUTO_PRICES_DECIMALS: ndec = TExchange(codval).decimals(true); break;
|
||
default : break;
|
||
}
|
||
if (ndec < 10)
|
||
n.round(ndec);
|
||
}
|
||
|
||
real TCodiceIVA::imposta(const real& imponibile, int ndec, const char* codval) const
|
||
{
|
||
real iva = imponibile * percentuale() / CENTO;
|
||
round(iva, ndec, codval);
|
||
return iva;
|
||
}
|
||
|
||
real TCodiceIVA::scorpora(real& lordo, int ndec, const char* codval) const
|
||
{
|
||
round(lordo, ndec, codval); // Arrotondo importo lordo
|
||
real imponibile = lordo * CENTO / (CENTO + percentuale());
|
||
round(imponibile, ndec, codval); // Arrotondo importo netto
|
||
const real iva = lordo - imponibile;
|
||
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); }
|
||
|
||
/* bool TCodiceIVA::reverse_charge() const
|
||
{
|
||
const int rsi = regime_speciale();
|
||
return rsi == 13 || rsi == 50 || rsi == 51; // Reverse charge!
|
||
}
|
||
|
||
bool TCodiceIVA::reverse_charge_pubb() const
|
||
{
|
||
const int rsi = regime_speciale();
|
||
return rsi == 13 || rsi == 19 || rsi == 50 || rsi == 51; // Reverse charge! con aggiunta dienti pubblici
|
||
} */
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// 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 = ' ';
|
||
|
||
if (strchr(" CF", _tipo) == nullptr)
|
||
{
|
||
#ifdef DBG
|
||
error_box(FR("Tipo conto errato: '%c'"), _tipo);
|
||
#endif
|
||
_tipo = ' ';
|
||
}
|
||
|
||
_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);
|
||
|
||
if (contro)
|
||
{
|
||
CHECKD(r.num() == LF_RMOV || r.num() == LF_PAGSCA, "Record non valido per contropartita: ", r.num());
|
||
switch(n)
|
||
{
|
||
case 0: return RMV_GRUPPOC; break;
|
||
case 1: return RMV_CONTOC; break;
|
||
case 2: return RMV_SOTTOCONTOC; break;
|
||
default:return RMV_TIPOCC; break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
switch(n)
|
||
{
|
||
case 0: return RMV_GRUPPO; break;
|
||
case 1: return RMV_CONTO; break;
|
||
case 2:
|
||
if (r.num() == LF_CLIFO)
|
||
return CLI_CODCF;
|
||
else
|
||
return RMV_SOTTOCONTO;
|
||
break;
|
||
default:
|
||
switch(r.num())
|
||
{
|
||
case LF_CLIFO : return CLI_TIPOCF; break;
|
||
case LF_RCAUSALI: return RCA_TIPOCF; break;
|
||
default : return RMV_TIPOC; break;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
|
||
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(nullptr);
|
||
_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
|
||
{
|
||
if (g > 0)
|
||
m.set(g, gruppo());
|
||
if (c > 0)
|
||
m.set(c, conto());
|
||
if (s > 0)
|
||
m.set(s, sottoconto());
|
||
if (t > 0)
|
||
{
|
||
char typ[2] = { tipo(), '\0' };
|
||
m.set(t, typ);
|
||
}
|
||
if (d > 0)
|
||
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 = s > 0 ? m.get_long(s) : 0L;
|
||
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(CLI_RAGSOC));
|
||
if (_tipo_cr < 0)
|
||
{
|
||
_tipo_cr = 0;
|
||
_sezione = ' ';
|
||
}
|
||
_sospeso = clifo.get_bool(CLI_SOSPESO);
|
||
|
||
const char tipoa = clifo.get_char(CLI_TIPOPERS);
|
||
if (tipoa == 'F') // Se persona fisica allora aggiusta la ragione sociale
|
||
{
|
||
TString nome(descrizione().mid(30));
|
||
if (nome.full())
|
||
{
|
||
_descrizione->cut(30);
|
||
_descrizione->trim(); nome.trim();
|
||
*_descrizione << ' ' << nome;
|
||
}
|
||
}
|
||
if (_gruppo == 0 || _conto == 0)
|
||
{
|
||
_gruppo = clifo.get_int(CLI_GRUPPO);
|
||
_conto = clifo.get_int(CLI_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 == nullptr || _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));
|
||
switch (sub)
|
||
{
|
||
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;
|
||
}
|
||
const TString& sotsub = s.mid(4);
|
||
if (sotsub.full())
|
||
str << ' ' << sotsub;
|
||
}
|
||
return (const char*)str;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Movimento di prima nota
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TMovimentoPN::TMovimentoPN()
|
||
: TRelation(LF_MOV), _cg(LF_RMOV, RMV_NUMRIG), _iva(LF_RMOVIVA, RMI_NUMRIG), _old_iva(LF_RMOVIVA, RMI_NUMRIG)
|
||
{
|
||
add(LF_RMOV, "NUMREG=NUMREG");
|
||
add(LF_RMOVIVA, "NUMREG=NUMREG");
|
||
}
|
||
|
||
void TMovimentoPN::destroy_rows(long num)
|
||
{
|
||
_cg.destroy_rows();
|
||
_cg.renum_key(RMV_NUMREG, num);
|
||
_iva.destroy_rows();
|
||
_iva.renum_key(RMI_NUMREG, num);
|
||
}
|
||
|
||
|
||
TRectype& TMovimentoPN::cg(int i)
|
||
{
|
||
return _cg.row(i >= 0 ? i + 1 : -1, true);
|
||
}
|
||
|
||
TRectype& TMovimentoPN::iva(int i)
|
||
{
|
||
return _iva.row(i >= 0 ? i + 1 : -1, true);
|
||
}
|
||
|
||
void TMovimentoPN::destroy_cg_row(int i)
|
||
{
|
||
if (i < 0)
|
||
_cg.destroy_rows();
|
||
else
|
||
_cg.destroy_row(i + 1, true);
|
||
}
|
||
|
||
void TMovimentoPN::destroy_iva_row(int i)
|
||
{
|
||
if (i < 0)
|
||
_iva.destroy_rows();
|
||
else
|
||
_iva.destroy_row(i + 1, true);
|
||
}
|
||
|
||
void TMovimentoPN::update_rev_charge()
|
||
{
|
||
const int year = lfile().get_int(MOV_ANNOIVA);
|
||
const TString & codcaus = lfile().get(MOV_CODCAUS);
|
||
const TCausale & caus = cached_causale(codcaus, year);
|
||
const TipoIVA t = caus.iva();
|
||
|
||
if (t == iva_acquisti)
|
||
{
|
||
const bool rev_charge = caus.reverse_charge_pubb();
|
||
|
||
if (rev_charge)
|
||
{
|
||
int rows = _iva.rows();
|
||
real imp_revcharge;
|
||
bool has_revcharge = false;
|
||
|
||
for (int i = _iva.first_row(); !has_revcharge && i <= rows; i = _iva.succ_row(i))
|
||
{
|
||
has_revcharge |= _iva[i].get_bool(RMI_REVCHARGE);
|
||
imp_revcharge += _iva[i].get_real(RMI_IMPOSTA);
|
||
}
|
||
if (!has_revcharge)
|
||
{
|
||
TRectype & h = head();
|
||
|
||
if (h.get_real(MOV_REVCHARGE) <= ZERO)
|
||
{
|
||
h.put(MOV_REVCHARGE, imp_revcharge);
|
||
h.sub(MOV_RITFIS, imp_revcharge);
|
||
if (h.get_real(MOV_RITFIS) < ZERO)
|
||
h.zero(MOV_RITFIS);
|
||
}
|
||
for (int i = _iva.first_row(); i <= rows; i = _iva.succ_row(i))
|
||
_iva[i].put(RMI_REVCHARGE, true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
int TMovimentoPN::read_mov_rows()
|
||
{
|
||
const TRectype& mov = curr();
|
||
const long numreg = mov.get_long(MOV_NUMREG);
|
||
|
||
TRectype* cgfilter = new TRectype(LF_RMOV);
|
||
cgfilter->put(RMV_NUMREG, numreg);
|
||
_cg.read(cgfilter);
|
||
|
||
TRectype* ivafilter = new TRectype(LF_RMOVIVA);
|
||
ivafilter->put(RMI_NUMREG, numreg);
|
||
_iva.read(ivafilter);
|
||
update_rev_charge();
|
||
_old_iva = _iva;
|
||
/*
|
||
if (_cg.rows() > 0 && _iva.rows() > 0 && cg(0).get_char(RMV_ROWTYPE) != 'T')
|
||
adjust_row_types();
|
||
*/
|
||
return _cg.rows();
|
||
}
|
||
|
||
|
||
int TMovimentoPN::read(TIsamop op, TReclock lockop)
|
||
{
|
||
const int err = TRelation::read(op, lockop);
|
||
if (err == NOERR)
|
||
{
|
||
_olddataliq = file().get(MOV_DATAREG); // Memorizza data liquidazione
|
||
const int meseliq = file().get_int(MOV_MESELIQ);
|
||
if (meseliq > 0 && meseliq != _olddataliq.month())
|
||
{
|
||
_olddataliq.set_day(1); // Evita problemi coi mesi corti!
|
||
_olddataliq.set_month(meseliq);
|
||
}
|
||
read_mov_rows(); // Riempie i due record array
|
||
}
|
||
return err;
|
||
}
|
||
|
||
char TMovimentoPN::frequenza_versamenti(int year) const
|
||
{
|
||
static int last_year = 0;
|
||
static long last_firm = 0;
|
||
static char last_freq = ' ';
|
||
|
||
const long firm = prefix().get_codditta();
|
||
|
||
if (firm != last_firm || year != last_year)
|
||
{
|
||
TString16 key; key.format("%05ld%d", firm, year);
|
||
TTable lia("%LIA");
|
||
lia.put("CODTAB", key);
|
||
if (lia.read() != NOERR)
|
||
{
|
||
TLocalisamfile nditte(LF_NDITTE);
|
||
nditte.put("CODDITTA", firm);
|
||
nditte.read();
|
||
last_freq = nditte.get_char("FREQVIVA");
|
||
}
|
||
else
|
||
last_freq = lia.get_char("S7");
|
||
|
||
if (last_freq != 'M' && last_freq != 'T')
|
||
{
|
||
error_box(FR("La frequenza versamenti IVA per la ditta %ld\n"
|
||
"non e' valida: la si considera mensile."), firm);
|
||
last_freq = 'M';
|
||
}
|
||
|
||
last_firm = firm;
|
||
last_year = year;
|
||
}
|
||
|
||
return last_freq;
|
||
}
|
||
|
||
int TMovimentoPN::date2liq(const TDate& data) const
|
||
{
|
||
const int anno = data.year();
|
||
int mese = data.month();
|
||
if (frequenza_versamenti(anno) == 'T')
|
||
mese += 2 - ((mese - 1) % 3);
|
||
return mese;
|
||
}
|
||
|
||
|
||
bool TMovimentoPN::controlla_liquidazione(const TDate& data, TRegistro& registro, bool reset) const
|
||
{
|
||
bool calcolata = false;
|
||
|
||
const int anno = data.year();
|
||
const int mese = date2liq(data);
|
||
|
||
// Chiave di LIM: Anno (1-4), Mese (5-6)
|
||
TString16 key; key.format("%04d%02d", anno, mese);
|
||
TTable lim("LIM");
|
||
lim.setkey(1);
|
||
lim.put("CODTAB", key);
|
||
if (lim.read() == NOERR)
|
||
{
|
||
calcolata = data.month() <= registro.mese_stampa_ultima_liq(); // Controlla se progressivi ricalcolati (registri)
|
||
|
||
if (reset)
|
||
{
|
||
// Resetta i flag di calcolato sulla liquidazione IVA del mese di registrazione
|
||
lim.zero("B0"); // calcolato
|
||
lim.rewrite();
|
||
}
|
||
}
|
||
|
||
if (reset)
|
||
{
|
||
const bool att_mista = registro.name().empty() ? FALSE : registro.attivita_mista();
|
||
const int att = att_mista ? 2 : 1;
|
||
|
||
// Chiave di PLM: Anno (1-4), Cod. Att. (5-9), Tipo att. (10-10), Mese (11-12)
|
||
TTable plm("PLM");
|
||
for (int a = 1; a <= att; a++)
|
||
{
|
||
TString16 chiave;
|
||
TString8 attivita(registro.attivita()); attivita.right_just(5, '0');
|
||
TString4 mese; mese.format("%02d", data.month());
|
||
chiave << data.year() << attivita << a << mese;
|
||
plm.put("CODTAB", chiave);
|
||
if (plm.read() == NOERR)
|
||
{
|
||
const bool calcolato = plm.get_bool("B0");
|
||
if (calcolato)
|
||
{
|
||
plm.zero("B0");
|
||
plm.rewrite();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return calcolata;
|
||
}
|
||
|
||
|
||
int TMovimentoPN::registra(bool re, bool force)
|
||
{
|
||
const TRectype& m = curr();
|
||
long numreg = m.get_long(MOV_NUMREG);
|
||
|
||
if (numreg <= 0)
|
||
{
|
||
if (!re) // Tento di numerare automaticamente in caso di write
|
||
{
|
||
TLocalisamfile mov(LF_MOV); // Non sposto il file principale della relazione!
|
||
numreg = 1;
|
||
if (mov.last() == NOERR)
|
||
numreg += mov.get_long(MOV_NUMREG);
|
||
curr().put(MOV_NUMREG, numreg);
|
||
}
|
||
else
|
||
return _isnocurkey;
|
||
}
|
||
|
||
int err = re ? TRelation::rewrite(force) : TRelation::write(force);
|
||
if (err != NOERR)
|
||
return err;
|
||
|
||
_cg.renum_key(MOV_NUMREG, numreg);
|
||
err = _cg.write(re);
|
||
if (err != NOERR)
|
||
return err;
|
||
|
||
const int annoiva = m.get_int(MOV_ANNOIVA);
|
||
const TString4 reg(m.get(MOV_REG));
|
||
TRegistro registro(reg, annoiva);
|
||
const bool att_mista = reg.empty() ? false : registro.attivita_mista();
|
||
|
||
update_rev_charge();
|
||
for (int i = 0; i < iva_items(); i++)
|
||
{
|
||
TRectype& r = iva(i);
|
||
int tipoatt = 1;
|
||
if (att_mista)
|
||
{
|
||
const char tipo = r.get_char(RMI_TIPOC);
|
||
if (tipo <= ' ')
|
||
{
|
||
TBill c(r.get_int(RMI_GRUPPO), r.get_int(RMI_CONTO), r.get_long(RMI_SOTTOCONTO));
|
||
tipoatt = c.tipo_att();
|
||
}
|
||
}
|
||
r.put(RMI_TIPOATT, tipoatt);
|
||
|
||
const TString & indetr = r.get(RMI_TIPODET);
|
||
if (indetr.full())
|
||
{
|
||
const TRectype& det = cache().get("%DET", indetr);
|
||
if (!det.empty() && !det.get_bool("FPC"))
|
||
{
|
||
TTable tab("%DET");
|
||
tab.curr() = det;
|
||
tab.curr().put("FPC", "X");
|
||
tab.rewrite();
|
||
}
|
||
}
|
||
}
|
||
|
||
_iva.renum_key(MOV_NUMREG, numreg);
|
||
err = _iva.write(re);
|
||
if (err != NOERR)
|
||
return err;
|
||
|
||
// Aggiorna data registrazione e protocollo IVA sul registro
|
||
const TDate datareg(m.get(MOV_DATAREG));
|
||
if (reg.full())
|
||
{
|
||
const long protiva = m.get_long(MOV_PROTIVA);
|
||
const long uprotiva = m.get_long(MOV_UPROTIVA);
|
||
const long max = protiva > uprotiva ? protiva : uprotiva;
|
||
registro.update(max, datareg);
|
||
}
|
||
|
||
// Aggiorna flags di ricalcolo liquidazione
|
||
|
||
TDate dataliq(datareg);
|
||
const int mese_liq = m.get_int(MOV_MESELIQ);
|
||
if (mese_liq > 0 && mese_liq != dataliq.month())
|
||
{
|
||
dataliq.set_day(1); // Evita problemi coi mesi corti!
|
||
dataliq.set_month(mese_liq);
|
||
}
|
||
|
||
bool reset = !re;
|
||
if (reg.full())
|
||
{
|
||
reset = (dataliq.month() != _olddataliq.month() || _old_iva != _iva);
|
||
if (dataliq.month() != _olddataliq.month())
|
||
controlla_liquidazione(_olddataliq, registro, true);
|
||
}
|
||
else
|
||
{
|
||
const TCausale causale(m.get(MOV_CODCAUS), annoiva);
|
||
|
||
if (causale.saldaconto(datareg) && causale.tipomov() != tm_fattura)
|
||
{
|
||
TPartite_array partarray;
|
||
|
||
partarray.add_numreg(numreg);
|
||
|
||
const int npart = partarray.items();
|
||
|
||
for (TPartita * part = partarray.first(); !reset && part != nullptr; part = partarray.next())
|
||
{
|
||
const int nrpart = part->last();
|
||
|
||
for (int r = part->prima_fattura(); !reset && r >= 0 && r <= nrpart; r = part->succ(r))
|
||
{
|
||
TRiga_partite & rp = part->riga(r);
|
||
|
||
if (rp.is_fattura())
|
||
{
|
||
const TRectype & mov = cache().get(LF_MOV, rp.get(PART_NREG));
|
||
|
||
reset = mov.get_bool(MOV_LIQDIFF) || mov.get_bool(MOV_IVAXCASSA);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (reset)
|
||
controlla_liquidazione(dataliq, registro, reset);
|
||
return err;
|
||
}
|
||
|
||
|
||
int TMovimentoPN::write(bool force)
|
||
{
|
||
return registra(FALSE, force);
|
||
}
|
||
|
||
int TMovimentoPN::rewrite(bool force)
|
||
{
|
||
return registra(true, force);
|
||
}
|
||
|
||
int TMovimentoPN::remove()
|
||
{
|
||
int err = _cg.remove();
|
||
|
||
if (err == NOERR)
|
||
err = _iva.remove();
|
||
|
||
if (err == NOERR)
|
||
err = TRelation::remove();
|
||
|
||
if (err == NOERR)
|
||
{
|
||
const TRectype& m = curr();
|
||
const TString4 reg(m.get(MOV_REG));
|
||
const int annoiva = m.get_int(MOV_ANNOIVA);
|
||
TRegistro registro(reg, annoiva);
|
||
controlla_liquidazione(_olddataliq, registro, true);
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Aggiustamento movimenti rovinati o convertiti male
|
||
///////////////////////////////////////////////////////////
|
||
|
||
bool TConti_array::add(const TBill& conto, const real& importo)
|
||
{
|
||
const char* key = conto.string();
|
||
real* imp = (real*)objptr(key);
|
||
|
||
if (imp == nullptr)
|
||
TAssoc_array::add(key, importo);
|
||
else
|
||
*imp += importo;
|
||
return imp != nullptr;
|
||
}
|
||
|
||
real TConti_array::importo(const TBill& conto)
|
||
{
|
||
const char* key = conto.string();
|
||
const real* imp = (real*)objptr(key);
|
||
return imp ? *imp : ZERO;
|
||
}
|
||
|
||
bool TConti_array::remove(const TBill& conto)
|
||
{
|
||
const char* key = conto.string();
|
||
return TAssoc_array::remove(key);
|
||
}
|
||
|
||
bool TConti_array::add_iva(bool det, const real& importo)
|
||
{
|
||
real* imp = nullptr;
|
||
|
||
if (!importo.is_zero())
|
||
{
|
||
const char* const key = det ? "D" : "N";
|
||
|
||
imp = (real*)objptr(key);
|
||
if (imp == nullptr)
|
||
TAssoc_array::add(key, importo);
|
||
else
|
||
*imp += importo;
|
||
}
|
||
return imp != nullptr;
|
||
}
|
||
|
||
real TConti_array::importo_iva(bool det)
|
||
{
|
||
const char* const key = det ? "D" : "N";
|
||
const real* imp = (real*)objptr(key);
|
||
return imp ? *imp : ZERO;
|
||
}
|
||
|
||
bool TConti_array::remove_iva(bool det)
|
||
{
|
||
const char* const key = det ? "D" : "N";
|
||
return TAssoc_array::remove(key);
|
||
}
|
||
|
||
real TMovimentoPN::indetraibile_al(const TString& codind, const TCausale& caus, int annodoc) const
|
||
{
|
||
int tipodet = 0;
|
||
return ::indetraibile_al(codind, caus, annodoc, tipodet);
|
||
}
|
||
|
||
int TMovimentoPN::analizza_riga_IVA(const real& imptot, const real& ivatot, const TCausale& caus,
|
||
int annodoc, const TString& codiva, const TString& codind,
|
||
real& imp_det, real& iva_det, real& imp_ind, real& iva_ind) const
|
||
{
|
||
const real perc_ind = indetraibile_al(codind, caus, annodoc);
|
||
const bool corrispettivo = caus.corrispettivi();
|
||
TBill billind; caus.bill(RIGA_IVA_NON_DETRAIBILE, billind);
|
||
const bool iva_ind_al_costo = !billind.ok();
|
||
return analizza_IVA(imptot, ivatot, perc_ind, corrispettivo, iva_ind_al_costo,
|
||
codiva, imp_det, iva_det, imp_ind, iva_ind);
|
||
}
|
||
|
||
// Aggiusta i row types se sono andati persi o non sono stati convertiti
|
||
void TMovimentoPN::adjust_rowtypes()
|
||
{
|
||
const TRectype& mov = curr();
|
||
const char tipo = mov.get_char(MOV_TIPO);
|
||
const long codice = mov.get_long(MOV_CODCF);
|
||
const int annoiva = mov.get_int(MOV_ANNOIVA);
|
||
const int annodoc = mov.get_date(MOV_DATADOC).year();
|
||
const TCausale causale(mov.get(MOV_CODCAUS), annoiva);
|
||
|
||
TConti_array conti;
|
||
int r;
|
||
|
||
for (r = 0; r < _iva.rows(); r++)
|
||
{
|
||
const TRectype& row = iva(r);
|
||
const TBill bill(row);
|
||
const real imponibile(row.get(RMI_IMPONIBILE));
|
||
const real imposta(row.get(RMI_IMPOSTA));
|
||
const TString4 codiva = row.get(RMI_CODIVA);
|
||
const TString4 codind = row.get(RMI_TIPODET);
|
||
real imp_det, iva_det, imp_ind, iva_ind;
|
||
analizza_riga_IVA(imponibile, imposta, causale, annodoc, codiva, codind,
|
||
imp_det, iva_det, imp_ind, iva_ind);
|
||
|
||
conti.add(bill, imp_det + imp_ind);
|
||
conti.add_iva(false, iva_ind);
|
||
conti.add_iva(true, iva_det);
|
||
}
|
||
|
||
bool totale = FALSE;
|
||
bool ritfis = mov.get_real(MOV_RITFIS).is_zero();
|
||
bool ritsoc = mov.get_real(MOV_RITSOC).is_zero();
|
||
bool ivadet = conti.importo_iva(true).is_zero();
|
||
bool ivanon = conti.importo_iva(FALSE).is_zero();
|
||
|
||
for (r = 0; r < _cg.rows(); r++)
|
||
{
|
||
TRectype& row = cg(r);
|
||
const char rt = row.get_char(RMV_ROWTYPE);
|
||
switch (rt)
|
||
{
|
||
case 'F': ritfis = true; break;
|
||
case 'S': ritsoc = true; break;
|
||
case 'T': totale = true; break;
|
||
default: break;
|
||
}
|
||
if (rt > ' ') continue;
|
||
|
||
if (!totale && row.get_char(RMV_TIPOC) == tipo && row.get_long(RMV_SOTTOCONTO) == codice)
|
||
{
|
||
row.put(RMV_ROWTYPE, 'T');
|
||
totale = true;
|
||
continue;
|
||
}
|
||
|
||
const real importo(row.get(RMV_IMPORTO));
|
||
const TBill bill(row);
|
||
|
||
if (!ritfis && importo == mov.get_real(MOV_RITFIS))
|
||
{
|
||
TBill conto_rit; causale.bill(RIGA_PAG_RITFIS, conto_rit);
|
||
if (!conto_rit.ok() || conto_rit == bill)
|
||
{
|
||
row.put(RMV_ROWTYPE, 'F');
|
||
ritfis = true;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (!ritsoc && importo == mov.get_real(MOV_RITSOC))
|
||
{
|
||
TBill conto_rit; causale.bill(RIGA_PAG_RITSOC, conto_rit);
|
||
if (!conto_rit.ok() || conto_rit == bill)
|
||
{
|
||
row.put(RMV_ROWTYPE, 'S');
|
||
ritsoc = true;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (!conti.ok())
|
||
continue; // Ho esaurito i conti IVA
|
||
|
||
if (importo == conti.importo(bill))
|
||
{
|
||
row.put(RMV_ROWTYPE, 'I');
|
||
conti.remove(bill);
|
||
continue;
|
||
}
|
||
|
||
if (!ivadet && importo == conti.importo_iva(true))
|
||
{
|
||
row.put(RMV_ROWTYPE, 'D');
|
||
conti.remove_iva(true);
|
||
continue;
|
||
}
|
||
|
||
if (!ivanon && importo == conti.importo_iva(FALSE))
|
||
{
|
||
row.put(RMV_ROWTYPE, 'N');
|
||
conti.remove_iva(FALSE);
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
|
||
TMovimentoPN& TMovimentoPN::get_sum_imponibile_imposta(real& s_imponibili, real& s_imposte)
|
||
{
|
||
TRecord_array& iva = iva_rows();
|
||
s_imponibili = ZERO;
|
||
s_imposte = ZERO;
|
||
for (int i = iva.first_row(); i <= iva.rows(); ++i)
|
||
{
|
||
TRectype& r = iva[i];
|
||
s_imponibili += r.get_real("IMPONIBILE");
|
||
s_imposte += r.get_real("IMPOSTA");
|
||
}
|
||
return *this;
|
||
}
|