Patch level : 12.0

Files correlati     :
Commento            :

Uniti tuuti gli header di cglib in cglib.h
Aggiunto l'oggetto TMovimento_contabile con le funzioni per calcolare l'imponibile e l'imposta
This commit is contained in:
Alessandro Bonazzi 2020-06-21 21:50:02 +02:00
parent d5580efcdf
commit e131c0c61b
2 changed files with 1832 additions and 0 deletions

1298
src/cg/cglib.h Normal file

File diff suppressed because it is too large Load Diff

534
src/cg/cglib06.cpp Normal file
View File

@ -0,0 +1,534 @@
#include "cglib.h"
#include "cg2101.h"
#include "cgsaldac.h"
char frequenza_versamenti(const int year, long firm)
{
char freq = ' ';
TString16 key; key.format("%05ld%d", firm, year);
const TRectype & lia = cache().get("%LIA", key);
if (firm <= 0L)
firm = prefix().get_codditta();
freq = lia.get_char("S7");
if (freq != 'M' && freq != 'T')
{
const TRectype & firm_rec = cache().get(LF_NDITTE, firm);
freq = firm_rec.get_char("FREQVIVA");
}
if (freq != 'M' && freq != 'T')
freq = 'M';
return freq;
}
int date2liq(const TDate& data, long firm)
{
const int anno = data.year();
int mese = data.month();
if (frequenza_versamenti(anno, firm) == 'T')
mese += 2 - ((mese - 1) % 3);
return mese;
}
bool controlla_liquidazione(const TDate & data, const TRegistro & registro, bool reset)
{
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.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 && plm.get_bool("B0"))
{
plm.zero("B0");
plm.rewrite();
}
}
}
return calcolata;
}
///////////////////////////////////////////////////////////
// Movimento di prima nota
///////////////////////////////////////////////////////////
TMovimento_contabile::TMovimento_contabile()
: TMultiple_rectype(LF_MOV), _old_iva(LF_RMOVIVA, RMI_NUMRIG)
{
add_file(LF_RMOV, RMV_NUMRIG);
add_file(LF_RMOVIVA, RMV_NUMRIG);
}
int TMovimento_contabile::readat(TBaseisamfile& f, TRecnotype nrec, word lockop)
{
const int err = TMultiple_rectype::readat(f, nrec, lockop);
if (err == NOERR)
{
_olddataliq = get_date(MOV_DATAREG); // Memorizza data liquidazione
const int meseliq = get_int(MOV_MESELIQ);
if (meseliq > 0 && meseliq != _olddataliq.month())
{
_olddataliq.set_day(1); // Evita problemi coi mesi corti!
_olddataliq.set_month(meseliq);
}
_old_iva = iva();
update_rev_charge();
}
return err;
}
int TMovimento_contabile::read(TBaseisamfile & f, word op, word lockop)
{
const int err = TMultiple_rectype::read(f, op, lockop);
if (err == NOERR)
{
_olddataliq = get_date(MOV_DATAREG); // Memorizza data liquidazione
const int meseliq = get_int(MOV_MESELIQ);
if (meseliq > 0 && meseliq != _olddataliq.month())
{
_olddataliq.set_day(1); // Evita problemi coi mesi corti!
_olddataliq.set_month(meseliq);
}
_old_iva = iva();
update_rev_charge();
}
return err;
}
int TMovimento_contabile::write_rewrite(TBaseisamfile& f, bool re) const
{
long numreg = get_long(MOV_NUMREG); // ??
TMovimento_contabile & this_mov = (TMovimento_contabile &)*this;
if (numreg <= 0)
{
if (!re) // Tento di numerare automaticamente in caso di write
{
TLocalisamfile mov(LF_MOV); // Non sposto il file principale della relazione! if (mov.last() == NOERR)
const long numreg = mov.get_long(MOV_NUMREG) + 1;
this_mov.put(MOV_NUMREG, numreg);
this_mov.cg().renum_key(RMV_NUMREG, numreg);
this_mov.iva().renum_key(RMI_NUMREG, numreg);
}
else
return _isnocurkey;
}
((TMovimento_contabile *)this)->find_movcoll();
int err = TMultiple_rectype::write_rewrite(f, re);
if (err == NOERR)
{
const int annoiva = get_int(MOV_ANNOIVA);
const TString4 reg(get(MOV_REG));
TRegistro registro(reg, annoiva);
const bool att_mista = reg.empty() ? false : registro.attivita_mista();
int last_iva = iva().last_row();
for (int i = iva().first_row(); i <= last_iva; i = iva().succ_row(i))
{
TRectype & r = this_mov.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();
}
}
}
// Aggiorna data registrazione e protocollo IVA sul registro
const TDate datareg(get(MOV_DATAREG));
if (reg.full())
{
const long protiva = get_long(MOV_PROTIVA);
const long uprotiva = 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 = 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 = cached_causale(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;
}
void TMovimento_contabile::find_movcoll()
{
if (get_long(MOV_MOVCOLL) == 0L)
{
const TCausale& cau = cached_causale(get(MOV_CODCAUS), get_int(MOV_ANNOES));
const TString4 cau_reg = cau.causale_reg_iva();
TToken_string key(get(MOV_TIPO)); key.add(get_long(MOV_CODCF));
const long codcli = cache().get(LF_CLIFO, key).get_long(CLI_CODCFASS);
const long numreg = get_long(MOV_NUMREG);
TString query("USE "); query << LF_MOV << " KEY 1 SELECT " << MOV_CODCAUS << "==\"" << cau_reg << "\"\nFROM " << MOV_NUMREG << "==" << numreg;
TISAM_recordset mov(query);
long movcoll = 0L;
for (bool ok = mov.move_first(); ok && movcoll == 0L; ok = mov.move_next())
{
TRectype& curr = (TRectype&)mov.cursor()->curr();
const long movcoll_found = curr.get_long(MOV_MOVCOLL);
if ((curr.get_long(MOV_CODCF) == codcli) && ((movcoll_found == 0L) || (movcoll_found == numreg)))
{
movcoll = mov.get(MOV_NUMREG).as_int();
curr.put(MOV_MOVCOLL, numreg);
curr.rewrite(TLocalisamfile(LF_MOV));
break;
}
}
put(MOV_MOVCOLL, movcoll);
}
}
void TMovimento_contabile::update_rev_charge()
{
const int year = get_int(MOV_ANNOIVA);
const TString & codcaus = 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)
{
real imp_revcharge;
bool has_revcharge = false;
int last_iva = iva().last_row();
for (int i = iva().first_row(); !has_revcharge && i <= last_iva; i = iva().succ_row(i))
{
has_revcharge |= iva(i, false).get_bool(RMI_REVCHARGE);
imp_revcharge += iva(i, false).get_real(RMI_IMPOSTA);
}
if (!has_revcharge)
{
if (get_real(MOV_REVCHARGE) <= ZERO)
{
put(MOV_REVCHARGE, imp_revcharge);
sub(MOV_RITFIS, imp_revcharge);
if (get_real(MOV_RITFIS) < ZERO)
TRectype::zero(MOV_RITFIS);
}
for (int i = iva().first_row(); i <= last_iva; i = iva().succ_row(i))
iva(i, false).put(RMI_REVCHARGE, true);
}
}
}
}
int TMovimento_contabile::remove()
{
const int err = TMultiple_rectype::remove();
if (err == NOERR)
{
const TString4 reg(get(MOV_REG));
const int annoiva = get_int(MOV_ANNOIVA);
TRegistro registro(reg, annoiva);
controlla_liquidazione(_olddataliq, registro, true);
}
return err;
}
real TMovimento_contabile::imponibile(const char * codiva) const
{
real imponibile;
const TString8 cod(codiva);
int last_iva = iva().last_row();
for (int i = iva().first_row(); i <= last_iva; i = iva().succ_row(i))
if (cod.blank() || cod == iva(i, false).get(RMI_CODIVA))
imponibile += iva(i, false).get_real(RMI_IMPONIBILE);
return imponibile;
}
real TMovimento_contabile::imposta(const char * codiva) const
{
real imposta;
const TString8 cod(codiva);
int last_iva = iva().last_row();
for (int i = iva().first_row(); i <= last_iva; i = iva().succ_row(i))
if (cod.blank() || cod == iva(i, false).get(RMI_CODIVA))
imposta += iva(i, false).get_real(RMI_IMPOSTA);
return imposta;
}
///////////////////////////////////////////////////////////
// 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);
}
// Aggiusta i row types se sono andati persi o non sono stati convertiti
void TMovimento_contabile::adjust_rowtypes()
{
const char tipo = get_char(MOV_TIPO);
const long codice = get_long(MOV_CODCF);
const int annoiva = get_int(MOV_ANNOIVA);
const int annodoc = get_date(MOV_DATADOC).year();
const TCausale causale(get(MOV_CODCAUS), annoiva);
TBill billind; causale.bill(RIGA_IVA_NON_DETRAIBILE, billind);
const bool corrispettivo = causale.corrispettivi();
const bool iva_ind_al_costo = !billind.ok();
TConti_array conti;
const int last_iva = iva().last_row();
for (int i = iva().first_row(); i < last_iva; i = iva().succ_row(i))
{
const TRectype& row = iva(i);
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);
int tipodet = 0;
const real perc_ind = indetraibile_al(codind, causale, annodoc, tipodet);
real imp_det, iva_det, imp_ind, iva_ind;
analizza_IVA(imponibile, imposta, perc_ind, corrispettivo, iva_ind_al_costo,
codiva, imp_det, iva_det, imp_ind, iva_ind);
conti.add(bill, imponibile);
conti.add_iva(false, iva_ind);
conti.add_iva(true, iva_det);
}
const int last_cg = cg().last_row();
bool totale = false;
bool ritfis = get_real(MOV_RITFIS) == ZERO;
bool ritsoc = get_real(MOV_RITSOC) == ZERO;
bool ivadet = conti.importo_iva(true) == ZERO;
bool ivanon = conti.importo_iva(false) == ZERO;
TBill conto_rit_fis;
TBill conto_rit_soc;
causale.bill(RIGA_PAG_RITFIS, conto_rit_fis);
causale.bill(RIGA_PAG_RITSOC, conto_rit_soc);
for (int c = cg().first_row(); c < last_cg; c = cg().succ_row(c))
{
TRectype& row = cg(c);
const char rt = row.get_char(RMV_ROWTYPE);
switch(rt)
{
case cgrowtype_ritfis: ritfis = true; break;
case cgrowtype_ritsoc: ritsoc = true; break;
case cgrowtype_totale: totale = true; break;
default : break;
}
if (rt == ' ')
{
if (!totale && row.get_char(RMV_TIPOC) == tipo && row.get_long(RMV_SOTTOCONTO) == codice)
{
row.put(RMV_ROWTYPE, cgrowtype_totale);
totale = true;
continue;
}
const real importo(row.get(RMV_IMPORTO));
const TBill bill(row);
if (!ritfis && importo == get_real(MOV_RITFIS))
{
if (!conto_rit_fis.ok() || conto_rit_fis == bill)
{
row.put(RMV_ROWTYPE, cgrowtype_ritfis);
ritfis = true;
continue;
}
}
if (!ritsoc && importo == get_real(MOV_RITSOC))
{
if (!conto_rit_soc.ok() || conto_rit_soc == bill)
{
row.put(RMV_ROWTYPE, cgrowtype_ritsoc);
ritsoc = true;
continue;
}
}
if (conti.ok())
{
if (importo == conti.importo(bill))
{
row.put(RMV_ROWTYPE, cgrowtype_imponibile);
conti.remove(bill);
}
else
if (!ivadet && importo == conti.importo_iva(true))
{
row.put(RMV_ROWTYPE, cgrowtype_IVAdet);
conti.remove_iva(true);
}
else
if (!ivanon && importo == conti.importo_iva(false))
{
row.put(RMV_ROWTYPE, cgrowtype_IVAnondet);
conti.remove_iva(FALSE);
}
}
}
}
}