campo-sirio/cg/cg4303.cpp
guy 5fde0436de Nuova comunicazione annuale IVA
Nuovi dari per CU

git-svn-id: svn://10.65.10.50/branches/R_10_00@23176 c028cbd2-c16b-5b4b-a496-9718f37d4682
2016-02-25 11:30:51 +00:00

671 lines
21 KiB
C++
Executable File
Raw Blame History

// -----------------------------------------------------------------
// Calcolo liquidazione
// part 4: casi particolari
// fv 2-2-94
// -----------------------------------------------------------------
#include "cg4300.h"
#include <progind.h>
#include <recarray.h>
#include <recset.h>
void TLiquidazione_app::add_plafond(int month, const char* codatt, int type,
const real& howmuch, bool intra)
{
look_ppa(month,codatt,type);
const char* field = intra ? "R1" : "R0";
_ppa_r->add(field, howmuch);
_ppa->rewrite();
}
void TLiquidazione_app::zero_plafond (int month, const char* codatt)
{
for (int jj = 1; jj <= 3; jj++) // three types of plafond
{
real r;
look_ppa(month,codatt,jj,TRUE);
if (month == 1 /*is_first_trim(month)*/) // controlla da sola nel caso di freq. mensile...
{
r = (jj == 1 ? _p8 : (jj == 2 ? _p8b : _p9));
}
else
{
const long rn = _ppa->recno();
// se non c'e' quello del mese prima c'e' poco da fare,
// si ricalcola tutto
bool is_ok = TRUE;
if (!look_ppa(month == 1 ? 1 : month -1/*previous_month(month)*/, codatt,jj))
// mazza che bella chiamata ricorsiva
{
if (_recalc != needed)
{
describe_error(TR("Progressivi plafond non ricalcolati per i mesi precedenti: possibili errori"),
codatt);
is_ok = FALSE;
}
else
{
if (!update_att(previous_month(month),codatt, FALSE))
describe_error(TR("Progressivi plafond non ricalcolati per i mesi precedenti: possibili errori"),
codatt);
look_ppa(previous_month(month),codatt,jj);
}
}
if (is_ok) // Se il record prec. esiste allora esegue i calcoli; In caso contrario diventa un errore sistematico
r = _ppa_r->get_real("R2") - _ppa_r->get_real("R0") - _ppa_r->get_real("R1");
_ppa->readat(rn);
}
_ppa_r->put("R2",r);
_ppa_r->put("R0","");
_ppa_r->put("R1","");
_ppa->rewrite();
} // for tipo esenzione plafond
}
// ricalcolo dei corrispettivi
void TLiquidazione_app::recalc_corrispettivi(int month, const char* codatt)
{
const int items = _corr_arr.items();
if (items == 0) return;
real imponibile,imposta;
// Se siamo in annuale non aggiornare i PIM/PAM/PLM dei mesi calcolati
// ricalcola (solo per il mese in corso!) operando sull'array
for (int i = 0; i < items; i++)
{
_CorrItem* ci = (_CorrItem*)&_corr_arr[i];
// memorizza per codiva
if (ci->_month != month || ci->_codatt != codatt)
continue;
lordo2netto(ci->_totale, imponibile, imposta, ci->_aliquota);
// aggiusto l'IVA vendite nei plm
look_plm(month, codatt);
real ive = _plm->get_real("R0");
ive += imposta;
_plm->put("R0",ive);
_plm->rewrite();
// .. e il volume di affari nei pam
real vaf = _pam->get_real("R1");
vaf += imponibile;
_pam->put("R1", vaf);
_pam->rewrite();
// Aggiorna il totale IVA periodica CD1_1
if (month == 13 && look_iva(ci->_codiva))
{
if (_iva->get("S10").not_empty()) // Solo CD1_1 ha senso coi corrispettivi...
{
_pum->curr().add("R14", imponibile); // CD1_1
_pum->rewrite();
}
}
}
}
// ricalcolo della malefica ventilazione
void TLiquidazione_app::recalc_ventilation(int month, const char* codatt)
{
if (!_isvent || _isagricolo || _isviaggio || _vend_arr.items() == 0) return;
TString att(codatt);
// 1) ricalcola i pim dei mesi dal primo al corrente se necessario
recalc rcl = _recalc;
_recalc = needed;
int m;
for (m = 1; m < month; m++)
update_att(m,codatt, FALSE);
_recalc = rcl;
_vent_arr.destroy();
m = month == 13 ? 13 : 1; // In annuale legge solo il PIM13
for (; m <= month; m++)
{
// aggiunge gli acquisti del mese m operando sui pim
for (_pim->first(); !_pim->eof(); _pim->next())
{
if (_year != *_pim_anno) continue;
// se e' acquisto beni per rivendita
int tipocr = atoi(*_pim_tipocr);
int mese = atoi(*_pim_mese);
int tipodet = atoi(*_pim_tipodet);
look_iva(*_pim_codiva);
// base di riparto solo se non esente, non soggetto, non imponibile
TString16 tipoiva(_iva->get("S1"));
TString16 reg = *_pim_codreg;
/*
* caso particolare SENSU Vladimiro (1995) #MI3001
* questi vengono pero' conteggiati nel totale
* acquisti per rivendita
*/
if (tipodet == 1 ||( tipocr == 5 && tipodet == 3) || tipodet == 9)
continue;
TString att(codatt);
if (tipocr == 1 && (mese == m) &&
att == (const char*)(*_pim_codatt))
{
if (tipoiva != "NS" && tipoiva != "NI" && tipoiva != "ES")
{
real lurd = _pim->get_real("R0");
lurd += _pim->get_real("R1");
real perc = _iva->get_real("R0");
TString other = _iva->get("S6");
if (!other.empty())
{
// ventila a un altro codice
look_iva(other);
perc = _iva->get_real("R0");
}
add_ventilation(perc / CENTO, lurd, *_pim_codiva, other);
}
}
}
}
// 2) calcola totale acquisti su tutte le aliquote
real totacq = 0.0;
real totven = 0.0;
const int vent_items = _vent_arr.items();
int j;
for (j = 0; j < vent_items; j++)
{
_VentItem& vv = (_VentItem&)_vent_arr[j];
totacq += vv._totale;
}
// 3) ricalcola (solo per il mese in corso!) operando sull'array
const int vend_items = _vend_arr.items();
for (int i = 0; i < vend_items; i++)
{
_VendItem* vi = (_VendItem*)&_vend_arr[i];
totven += vi->_totale;
}
/*
* Udite! Udite! Per editto di sua maesta' la ventilazione
* va calcolata in modo uguale al frigorifero (cioe' sbagliato)
* I migliori auguri per una pronta guarigione dallo stato di
* infermita' mentale che vi affligge tutti.
* Bando ai convenevoli e passiamo alla spiegazione (se siete
* rigorosamente razionali fermatevi qui e non andate oltre):
* la ventilazione, in breve, consiste in questo:
* si totalizzano gli acquisti beni per rivendita da inizio anno
* e le vendite (solo del periodo) da scorporare (corrispettivi).
* A questo punto si dovranno "scaglionare" le vendite in
* proporzione agli acquisti dello stesso codice IVA. Avremo quindi N
* importi vendite lordi, la cui somma dovra' sempre dare il totale vendite
* calcolato inizialmente. Per ogni scaglione ottenuto si procedera' poi
* allo scorporo dell'iva, in modo che il tutto risulti coerente.
*
* La nostra implementazione:
* si calcolino il totale acquisti beni per rivendita da inizio anno e
* le vendite da ventilare nel periodo.
* Si istanzia un TDistrib (vedi la classe) sul totale delle vendite da ripartire,
* quindi per ogni aliquota acquisti presente si aggiunge una percentuale di ripartizione
* (acquisti/totale acquisti) al suddetto oggetto.
* In tal modo avremo che il totale delle vendite sara' sempre
* uguale all'originale senza perdite 0 aggiunte di insignificanti lirette.
* come ultima cosa si estraggono le varie suddivisioni ottenute a da li si procede
* allo scorporo dell'iva.
*
* La loro implementazione:
* come nel nostro caso si effettua la totalizzazione degli acquisti e delle vendite
* a questo punto pero' si introduce il leggendario moltiplicatore, che serve, se non
* altro a far sbagliare i conti sugli arrotondamenti e sui totali. Tale moltiplicatore
* e' dato dal rapporto tra totale acquisti e totale vendite. Per ogni aliquota iva
* acquisti si effettua percio' la seguente operazione per ottenere il relativo
* importo vendite:
* ROUND(acquisti * moltiplicatore)
* come si puo' notare, gia' qui si introduce un errore, perche' non e' affatto detto
* che la somma di tutti gli importi vendite ottenuti dia ancora l'importo complessivo originale.
* Infine si scorpora l'iva come nel nostro caso.
*
* Ebbene si': il nostro metodo (corretto) e' stato bandito e sostituito con quello
* super-mega-maxi-iper-errato del sistema. Si lascia commentato per memoria futura
* l'implementazione corretta, anche perche' forse in futuro (possibilita' molto remota)
* cambieranno idea.
*
* Sigh!
*
{
_VendItem* vi = (_VendItem*)&_vend_arr[0];
// 3.2) calcola percentuali di ripartizione e prepara l'affettatrice
TDistrib dst(totven, ROUND_LIRA);
for (j = 0; j < vent_items; j++)
{
_VentItem* vv = (_VentItem*)&_vent_arr[j];
dst.add(vv->_totale/totacq);
}
// 3.3) affetta l'importo
real tlor = 0.0;
for (j = 0; j < vent_items; j++)
{
_VentItem* vv = (_VentItem*)&_vent_arr[j];
real imponibile = dst.get();
real div(1.0); div += vv->_aliquota;
real totale = imponibile;
real imposta = imponibile - (imponibile/div);
imposta.ceil(ROUND_LIRA);
imponibile -= imposta;
// quadratura del cerchione
real delta = totale - imponibile - imposta;
if (!delta.is_zero())
imposta += delta;
tlor += imponibile + imposta;
// quadratura generale (solo per unita', che peraltro
// dovrebbe essere l'unica possibile stronzata
if ((totven - tlor) == real(1.0))
imposta += real(1.0);
// aggiusto l'IVA vendite nei plm
look_plm(month, codatt);
real ive = _plm->get_real("R0");
ive += imposta;
_plm->put("R0",ive);
_plm->rewrite();
// .. e il volume di affari nei pam
real vaf = _pam->get_real("R1");
vaf += imponibile;
_pam->put("R1", vaf);
_pam->rewrite();
// Aggiorno i luridi pim
bool was = look_pim(month, codatt, vi->_codreg, "0", vv->_codiva, vi->_tipodet, TRUE);
imponibile += _pim->get_real("R0");
imposta += _pim->get_real("R1");
_pim->put("R0", imponibile);
_pim->put("R1", imposta);
_pim->put("S4", vv->_other);
// segnale per comodita' in stampa prospetto
_pim->put("B1","X");
// se e' nuovo, il segnale per usare l'importo nel calcolo del rimborso
// viene amorosamente messo a quanto il codice IVA prevede
if (!was)
{
look_iva(vv->_codiva);
_pim->put("I1", (long)vendita);
if (!_iva->get_bool("B4")) _pim->put("B3", "X");
}
_pim->rewrite();
}
}
*/
// Di seguito l'implementazione del sistema (errata come spiegato sopra).
real moltiplicatore = totven / totacq;
moltiplicatore.round(9);
real imponibile, imposta;
_VendItem* vi = (_VendItem*)&_vend_arr[0];
for (j = 0; j < vent_items; j++)
{
_VentItem* vv = (_VentItem*)&_vent_arr[j];
imponibile = vv->_totale * moltiplicatore; // Importo lordo vendite
round_al_centesimo(imponibile);
lordo2netto(imponibile, imposta, vv->_aliquota); // Scorpora l'iva
// aggiusto l'IVA vendite nei plm
look_plm(month, codatt);
real ive = _plm->get_real("R0");
ive += imposta;
_plm->put("R0",ive);
_plm->rewrite();
// .. e il volume di affari nei pam
real vaf = _pam->get_real("R1");
vaf += imponibile;
_pam->put("R1", vaf);
_pam->rewrite();
// Aggiorna il totale IVA periodica CD1_1
if (month == 13 && look_iva(vv->_codiva))
{
if (_iva->get("S10").not_empty()) // Solo CD1_1 ha senso coi corrispettivi
{
_pum->curr().add("R14", imponibile); // CD1_1
_pum->rewrite();
}
}
// Aggiorno i luridi pim
bool was = look_pim(month, codatt, vi->_codreg, "0", vv->_codiva, vi->_tipodet, TRUE);
imponibile += _pim->get_real("R0");
imposta += _pim->get_real("R1");
_pim->put("R0", imponibile);
_pim->put("R1", imposta);
_pim->put("S4", vv->_other);
// segnale per comodita' in stampa prospetto
_pim->put("B1","X");
// se e' nuovo, il segnale per usare l'importo nel calcolo del rimborso
// viene amorosamente messo a quanto il codice IVA prevede
if (!was)
{
look_iva(vv->_codiva);
_pim->put("I1", (long)vendita);
if (!_iva->get_bool("B4"))
_pim->put("B3", "X");
}
_pim->rewrite();
}
// memorizza totali per il prospettino di m.
look_plm(month, codatt);
// PAM e PUM
_pam->put("R2",totacq);
_pam->put("R3",totven);
_pam->rewrite();
}
// ricalcolo iva dovuta agenzie viaggio
void TLiquidazione_app::recalc_viaggio(int month, const char* codatt)
{
if (!_isviaggio)
return;
real c_CEE, c_mCEE, c_fCEE, a_CEE, a_mCEE, a_fCEE, a_mfCEE;
for (int mese = month == 13 ? 13 : 1; mese <= month; mese++)
{
if (!is_month_ok(mese,month) || !look_plm(mese, codatt))
continue;
c_CEE += _plm->get_real("R5"); // corrispettivi CEE
c_mCEE += _plm->get_real("R9"); // corrispettivi misti CEE
c_fCEE += _plm->get_real("R6"); // corrispettivi fuori CEE
a_CEE += _plm->get_real("R7"); // acquisti CEE
a_mCEE += _plm->get_real("R10"); // acquisti misti parte CEE
a_fCEE += _plm->get_real("R8"); // acquisti fuori CEE
a_mfCEE += _plm->get_real("R11"); // acquisti misti parte fuori CEE
}
if (month == 13) // Arrotondamento 13a liquidazione
{
round_imposta(c_CEE);
round_imposta(c_mCEE);
round_imposta(c_fCEE);
round_imposta(a_CEE);
round_imposta(a_mCEE);
round_imposta(a_fCEE);
round_imposta(a_mfCEE);
}
// calcolo debito mensile da aggiornare su tabella POM
real perc_r = a_mCEE.is_zero() ? ZERO : (a_mCEE * CENTO)/(a_mCEE + a_mfCEE); perc_r.round(2);
real ivm = (c_mCEE * perc_r)/CENTO;
if (month == 13)
round_imposta(ivm);
else
round_al_centesimo(ivm);
const real tc = c_CEE + ivm;
const real ta = a_CEE + a_mCEE;
const real bi = tc - ta - credito_costo_prec(month);
real deb_mens;
if (bi > ZERO)
{
const real alivia = aliquota_agvia();
deb_mens = bi * alivia / (CENTO + alivia);
if (month == 13)
round_imposta(deb_mens);
else
round_al_centesimo(deb_mens);
}
if (look_plm(month,codatt))
{
_pom->put("R13", deb_mens); // Scrive il valore corretto (mensile/trimestrale/annuale)
_pom->rewrite();
}
}
_DescrItem* TLiquidazione_app::recalc_rimborso(int month, const char* codatts,
bool stliq)
{
// calcola condizioni per il diritto al rimborso infracazzuale
// chiamata soltanto per i trimestri anche se annuale
// aggiornata a normative per anno liq. > 1994
bool rimborsami = FALSE;
_DescrItem* d = NULL;
TToken_string atts(codatts);
const char* tmpatt;
TString att;
const bool is_mens = _freqviva == "M";
// variabili per condizione 1
real es_ni = 0.0;
real vol_aff = 0.0;
int m;
if (is_mens) m = month; // per le mensili considera solo il mese attuale
else m = next_trim(month)-2; // per le trimestrali considera i mesi del trimestre
if (month == 13) m = 13; // se annuale considera solo il mese 13
// variabili per condizione 2
real vtot = 0.0;
real atot = 0.0;
real ivav = 0.0;
real ivaa = 0.0;
real alv = 0.0; // aliquota media vendite
real ala = 0.0; // aliquota media acquisti
// Condizione 1...
while ((tmpatt = atts.get()) != NULL)
{
att = tmpatt;
for (; m <= month; m++)
{
if (!look_plm(m,att)) continue;
vol_aff += _pam->get_real("R1");
es_ni += _pum->get_real("R12");
if (_isagricolo) // questo calcolo per il regime agricolo, riguarda la condizione 2
{
vtot += _pum->get_real("R11");
ivav += _plm->get_real("R6");
}
}
}
// condizione 1: prc = es_ni / vol_aff
if (stliq && !vol_aff.is_zero())
{
real prc = es_ni / vol_aff;
prc.round(2);
if (prc > MIN_PARTE_ESENTE)
{
rimborsami = TRUE;
d = new _DescrItem(RIMBORSO);
d->_f0 = TRUE;
d->_r0 = es_ni;
d->_r1 = vol_aff;
}
}
// Condizione 2...
// scorri i bellissimi progressivi mensili
// Nota: i valori ricavati vanno poi integrati con R3, dove sono memorizzati i corrispettivi da scorporare
// anche qui si accumula per codice iva e si effettua lo scorporo alla fine del ciclo.
TAssoc_array corr_ann;
TString codiva;
_CorrItem cx,*cc;
bool is_key;
const int year = atoi((const char*)_year);
for (_pim->first(); !_pim->eof(); _pim->next())
{
int ryear = atoi(*_pim_anno);
int rmese = atoi(*_pim_mese);
int tipodet = atoi(*_pim_tipodet);
codiva = *_pim_codiva;
// B3 significa che e' acq. o vendita valido per rimb. per aliquota
if (!_pim->get_bool("B3")) continue;
// Se il tipo di codice e' NS non va considerato nella sommatoria del tot. acquisti
look_iva(codiva);
const bool non_sogg = _iva->get("S1") == "NS";
if (!is_mens) // Trimestrali
{
if (year != ryear ||
(rmese < (next_trim(month)-2) || rmese > month))
continue;
} else // Mensili
if (year != ryear || month != rmese)
continue;
int tipomov = (tiporeg)_pim->get_long("I1");
const real imp = _pim->get("R0");
const real iva = _pim->get("R1");
// totali imponibili
if (tipomov == vendita)
{
if (!_isagricolo)
{ // per il regime agricolo il calcolo e' a parte: si reperiscono PUM->R11(Imponibile) e PLM->R6(Imposta)
// vedi sopra...
vtot += imp;
ivav += iva;
ivav += _pim->get_real("R29");
is_key = corr_ann.is_key(codiva);
cx._totale = 0;
_CorrItem& ca = is_key ? (_CorrItem&) corr_ann[codiva] : cx;
ca._totale += _pim->get_real("R3");
if (!is_key) // se non c'e' lo aggiunge
{
ca._aliquota = _iva->get_real("R0")/CENTO; // Se e' nuovo setta l'aliquota
corr_ann.add(codiva,ca);
}
}
}
else
if (tipodet != 9) // I progressivi con tipo detraibilita' a 9 vanno saltati (MI2209)
{
if (!non_sogg)
atot += imp;
ivaa += iva;
}
} // end of for
real impc,ivac; // Aggiunge lo scorporo dei corrispettivi alle vendite calcolate
for (cc = (_CorrItem *)corr_ann.first_item(); cc != NULL; cc = (_CorrItem *)corr_ann.succ_item())
{
lordo2netto(cc->_totale,impc,ivac,cc->_aliquota);
vtot += impc;
ivav += ivac;
}
// finalmente
alv = ivav.is_zero() ? ZERO : ivav/vtot; alv.round(4);
ala = ivaa.is_zero() ? ZERO : ivaa/atot; ala.round(4);
// vedi condizioni
rimborsami = ala > alv;
if (rimborsami && !alv.is_zero())
{
// vedi di quanto ala eccede alv; deve essere > 10%
const real ecc = (ala/alv) - UNO;
rimborsami = (ecc >= SOGLIA_MAGGIORE_ALIQUOTA_DEL_CAZZO_PER_AVER_DIRITTO_AL_RIMBORSO);
}
if (stliq && rimborsami)
{
if (d == NULL) d = new _DescrItem(RIMBORSO);
d->_f1 = true;
d->_r2 = vtot;
d->_r3 = atot;
d->_r4 = ivav;
d->_r5 = ivaa;
d->_r6 = alv * CENTO;
d->_r7 = ala * CENTO;
}
if (rimborsami && is_month_ok_strict(month))
{
look_lim(month);
_lim->put("B2", "X");
_lim->rewrite();
}
return d;
}
// Azzera tabella IVA x CASSA
void TLiquidazione_app::zero_diff(int month, const char* codatt)
{
// Azzero tutto al momento dell'azzeramento della prima attivit<69>
if (!_nditte->is_first_match(LF_ATTIV))
return;
if (month > 12 || (_freqviva == "T" && (month % 3) != 1))
return;
TFast_isamfile fid(LF_IVADIFF);
if (fid.status() != NOERR)
return;
TString query;
query << "USE IVADIFF KEY 2"; // Key 2 = ANNOLIQ+MESELIQ+...
query << "\nFROM ANNOLIQ=" << _year;
// Se calcolo gennaio (o marzo trimestrale) azzero tutto l'anno, altrimenti solo il mese selezionato
if (month > (_freqviva == "T" ? 3 : 1))
query << " MESELIQ=" << month;
query << "\nTO ANNOLIQ=" << _year; // Dal 18-06-2014 lascia stare l'anno prossimo!
TISAM_recordset id(query);
TString msg;
msg.format("Azzeramento IVADIFF %s %s attivit<69> %s", month <= 12 ? itom(month) : "13ma", (const char*)_year, codatt);
TProgress_monitor pi(id.items(), msg, false);
TLocalisamfile& file = id.cursor()->file();
for (bool ok = id.move_first(); ok; ok = id.move_next())
{
pi.add_status(1);
file.zero("ANNOLIQ");
file.zero("MESELIQ");
file.zero("IMPORTO");
file.zero("IMPONIBILE");
file.zero("IMPOSTA");
file.zero("DATAREG");
file.zero("NUMREGP");
file.zero("NUMRIGP");
file.zero("DATAREGP");
file.zero("DATAREGP");
file.zero("TIPOMOV");
file.zero("TIPOIVA");
file.zero("TIPOATT");
file.zero("TIPODIFF");
file.zero("CHIUSA");
file.rewrite();
}
}