campo-sirio/cg/cg4303.cpp
angelo cafd3fcd50 Correzione in liquidazione IVA relativa allo scorporo corretto
(sia in annuale che nel periodo).


git-svn-id: svn://10.65.10.50/trunk@4139 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-02-19 08:53:29 +00:00

765 lines
22 KiB
C++
Executable File

// -----------------------------------------------------------------
// Calcolo liquidazione
// part 4: casi particolari
// fv 2-2-94
// -----------------------------------------------------------------
#include "cg4300.h"
class Annual_item : public TObject
{
real _imposta;
real _imponibile;
TString _codiva;
TString _other;
public:
virtual TObject* dup() const { return new Annual_item(*this); }
real& imposta() { return _imposta;}
real& imponibile() { return _imponibile;}
TString& codiva() { return _codiva;}
TString& other() { return _other;}
Annual_item() { _imposta = 0.0; _imponibile = 0.0; _codiva = ""; _other = ""; }
virtual ~Annual_item() {}
};
void TLiquidazione_app::add_plafond(int month, const char* codatt, int type,
real& howmuch, bool intra)
{
look_ppa(month,codatt,type);
TString att(codatt);
real r0 = _ppa_r->get_real("R0");
real r1 = _ppa_r->get_real("R1");
real r2 = _ppa_r->get_real("R2");
if (intra) r1 += howmuch;
else r0 += howmuch;
//06/12/1995
/*
if (r2 < (r0+r1))
describe_error("Acquisti in eccesso rispetto al plafond disponibile",
att.cut(5));
*/
//fine
_ppa_r->put("R0",r0);
_ppa_r->put("R1",r1);
_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 (is_first_month(month))
{
r = (jj == 1 ? _p8 : (jj == 2 ? _p8b : _p9));
}
else
{
long rn = _ppa->recno();
// se non c'e' quello del mese prima c'e' poco da fare,
// si ricalcola tutto
if (!look_ppa(previous_month(month),codatt,jj))
// mazza che bella chiamata ricorsiva
{
if (_recalc != needed)
{
describe_error("Progressivi plafond non ricalcolati per "
"i mesi precedenti: possibili errori",
codatt);
}
else
{
if (!update_att(previous_month(month),codatt, FALSE))
describe_error("Progressivi plafond non ricalcolati per "
"i mesi precedenti: possibili errori",
codatt);
look_ppa(previous_month(month),codatt,jj);
}
}
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;
// Nota: i commenti marcati con x13 indicano modifiche da rimuovere non appena implementato
// correttamente il mese 13
// x13
TString key;
bool is_key;
TAssoc_array corr_ann; // Contiene corrispettivi annuali (temporaneo, da correggere
// non appena implementato correttamente il mese 13)
_CorrItem cx;
// Se siamo in annuale non aggiornare i PIM/PAM/PLM dei mesi calcolati
if (_month == 13 && month < 13) return;
// fine x13
// 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
// x13
if ((month != 13 && ci->_month != month) || ci->_codatt != codatt) continue;
key = ci->_codiva;
is_key = corr_ann.is_key(key);
cx._totale = 0;
_CorrItem& ca = is_key ? (_CorrItem&) corr_ann[key] : cx;
ca._totale += ci->_totale;
if (!is_key) // se non c'e' lo aggiunge
{
ca._aliquota = ci->_aliquota;
/*
ca._codreg = ci->_codreg;
ca._tipodet = ci->_tipodet;
*/
corr_ann.add(key,ca);
}
/*
continue;
// fine x13
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();
// Aggiorno i luridi pim
look_pim(month, codatt, ci->_codreg, "", ci->_codiva, ci->_tipodet, TRUE);
imponibile += _pim->get_real("R0");
imposta += _pim->get_real("R1");
_pim->put("R0", imponibile);
_pim->put("R1", imposta);
_pim->rewrite();
*/
}
// Dopo aver calcolato la somma dei corrispettivi annualmente, li scorpora
// x13
// if (month == 13)
//{
real imp,iva,imp1,iva1;
_CorrItem* cc;
// Per le prossime scritture(PAM e PLM) uso impropriamente il mese 12, lo so e' terribile...
// ma non appena possibile il mese 13 sara' disponibile tutto sara' piu' bello.
//const int m = month == 13 ? 12 : month;
for (cc = (_CorrItem *)corr_ann.first_item(); cc != NULL; cc = (_CorrItem *)corr_ann.succ_item())
{
lordo2netto(cc->_totale, imp, iva, cc->_aliquota);
imponibile += imp;
imposta += iva;
/*
look_pim(m, codatt, cc->_codreg, "", corr_ann.get_hashobj()->key(), cc->_tipodet, TRUE);
imp1 = _pim->get_real("R0");
iva1 = _pim->get_real("R1");
imp1 += imp;
iva1 += iva;
_pim->put("R0",imp1);
_pim->put("R1",iva1);
_pim->rewrite();
*/
//}
}
look_plm(month, codatt); // Aggiorna l'iva vendite in PLM...
real ive = _plm->get_real("R0");
ive += imposta;
_plm->put("R0",ive);
// ed il volume d'affari in PAM
real vaf = _pam->get_real("R1");
vaf += imponibile;
_pam->put("R1",vaf);
_plm->rewrite();
_pam->rewrite();
// fine x13
}
// 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);
TArray annual_vent;
Annual_item a_item;
// 1) ricalcola i pim dei mesi dal primo al corrente se necessario
recalc rcl = _recalc;
_recalc = needed;
for (int m = 1; m < month; m++)
update_att(m,codatt, FALSE);
_recalc = rcl;
_vent_arr.destroy();
for (m = 1; 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 (tipocr == 5 && tipodet == 3)
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;
for (int j = 0; j < _vent_arr.items(); j++)
{
_VentItem& vv = (_VentItem&)_vent_arr[j];
totacq += vv._totale;
}
const bool is_annual = _month == 13 && month == 13;
for (j = 0; is_annual && j < _vend_arr.items(); j++)
{
_VendItem& vi = (_VendItem&)_vend_arr[j];
totven += vi._totale;
}
// 3) ricalcola (solo per il mese in corso!) operando sull'array
for (int i = 0; i < _vend_arr.items(); i++)
{
_VendItem* vi = (_VendItem*)&_vend_arr[i];
if (vi->_month != month && !is_annual)
continue;
// questo serve solo per il prospettino di m.
if (!is_annual)
totven += vi->_totale;
// 3.2) calcola percentuali di ripartizione e prepara l'affettatrice
TDistrib dst(!is_annual ? vi->_totale : totven,ROUND_LIRA);
for (j = 0; j < _vent_arr.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_arr.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);
if (is_annual)
{
// memorizza i dati della ventilazione annuale in un TArray
a_item.imposta() = imposta;
a_item.imponibile() = imponibile;
a_item.codiva() = vv->_codiva;
a_item.other() = vv->_other;
annual_vent.add(a_item);
continue;
} else if (_month != 13)
{
// 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();
}
}
if (is_annual)
{
// Cazzeggia e riscrive i PIM/PAM/PLM (veid sopra) ripartendo equamente gli importi annuali
// tra i vari mesi, tipodet e codici IVA.
const int slices = _vend_arr.items();
const int a_items = annual_vent.items();
real perc(1.0),imp_fetta, iva_fetta, tot_imp, tot_iva, delta;
perc /= slices;
for (i = 0; i < a_items; i++)
{
Annual_item& item = (Annual_item&) annual_vent[i];
TDistrib imp_s(item.imponibile(),ROUND_LIRA);
TDistrib iva_s(item.imposta(),ROUND_LIRA);
tot_imp = 0.0; tot_iva = 0.0;
for (j = 0; j < slices; j++)
{
imp_s.add(perc); iva_s.add(perc);
}
for (j = 0; j < slices; j++)
{
_VendItem * vi = (_VendItem*) &_vend_arr[j];
imp_fetta = imp_s.get();
iva_fetta = iva_s.get();
tot_imp += imp_fetta; tot_iva += iva_fetta; // Serve per eventuali perdite di lirette...
if (j == (slices - 1))
{
delta = item.imponibile() - tot_imp;
if (!delta.is_zero()) imp_fetta += delta; // Aggiusta l'ultima fetta(IVA e IMPONIBILE)
delta = item.imposta() - tot_iva; // per eventali perdite di lire nella ripartizione
if (!delta.is_zero()) iva_fetta += delta;
}
// aggiusto l'IVA vendite nei plm
look_plm(vi->_month, codatt);
real ive = _plm->get_real("R0");
ive += iva_fetta;
_plm->put("R0",ive);
_plm->rewrite();
// .. e il volume di affari nei pam
real vaf = _pam->get_real("R1");
vaf += imp_fetta;
_pam->put("R1", vaf);
_pam->rewrite();
// Aggiorno i luridi pim
bool was = look_pim(vi->_month, codatt, vi->_codreg, "0", item.codiva(), vi->_tipodet, TRUE);
imp_fetta += _pim->get_real("R0");
iva_fetta += _pim->get_real("R1");
_pim->put("R0", imp_fetta);
_pim->put("R1", iva_fetta);
_pim->put("S4", item.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(item.codiva());
_pim->put("I1", (long)vendita);
if (!_iva->get_bool("B4")) _pim->put("B3", "X");
}
_pim->rewrite();
}
}
totven = 0.0; // Questa va azzerato, poiche' quando ancora non era prevista
break; // la ventilazione annuale , registrava totven come 0.0
}
}
// memorizza totali per il prospettino di m.
look_plm(month, codatt);
// PAM e PUM
_pam->put("R2",totacq);
_pam->put("R3",totven);
_pam->rewrite();
}
// questa servIVA per il rimborso secondo le
// nuove cazzonorme, mai entrate in vigore ma
// devotamente programmate
//class rObj : public TObject
//{
//public:
// real _imp;
// real _iva;
// real _perc;
//
// rObj() {}
// virtual ~rObj() {}
//};
_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 = 1; // se annuale considera tutti i mesi
// 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
real prc = es_ni/vol_aff; prc.round(2);
if (stliq && !vol_aff.is_zero() && prc > MIN_PARTE_ESENTE)
{
rimborsami = TRUE;
d = new _DescrItem(RIMBORSO);
d->_f0 = TRUE;
d->_r0 = es_ni;
d->_r1 = vol_aff;
}
// ---------------------- condizione 2
// u' casinu pazzescu d'u nuiu guvernu
/***********************************************************************
Sembra che sia stato annullato subito dopo che ho finito di scrivere
queste 150 righe di casino
***********************************************************************
// due array dove ficcare i totali per
// codiva in ordine di imponibile
TArray varr, aarr;
// scorri i bellissimi progressivi mensili rimborso
for (_rmb->first(); !_rmb->eof(); _rmb->next())
{
int year = atoi((const char*)_year);
int ryear = atoi((const char*)(*_rmb_anno));
int rmese = atoi((const char*)(*_rmb_mese));
if (year != ryear || (rmese < (month - 2) || rmese > month))
continue;
real imp = _rmb->get("R0");
real iva = _rmb->get("R1");
real per = _rmb->get("R2");
rObj* rb = new rObj;
rb->_imp = imp;
rb->_iva = iva;
rb->_perc = per;
TArray& arr = (tiporeg)atoi((const char*)(*_rmb_tiporeg)) == vendita ? varr : aarr;
for (int i = 0; i < arr.items(); i++)
{
rObj& robj = (rObj&)arr[i];
if (robj._imp < imp)
break;
}
arr.insert(rb, i);
// totali imponibili
if ((tiporeg)atoi((const char*)(*_rmb_tiporeg)) == vendita)
vtot += imp;
else
atot += imp;
}
// se ci sono due o piu' imponibili uguali devo
// sostituire l'imposta con la media delle aliquote
// ciclo uguale sui due array
for (int w = 0; w < 2; w++)
{
TArray& arr = w == 0 ? varr : aarr;
for (int i = 0; i < arr.items(); i++)
{
rObj& robj = (rObj&)arr[i];
real impref = robj._imp;
real perc = robj._perc;
for (int j = i+1; j < arr.items(); j++)
{
rObj& rbj = (rObj&)arr[j];
if (rbj._imp != impref)
break;
perc += rbj._perc;
}
// riaggiustesbimo
if (j > i+1)
{
// funzionerebbe comunque ma risparmiamo una
// divisione per 1
real ndiv(j-i);
perc /= ndiv;
for (; i < j; i++)
{
rObj& rbj = (rObj&)arr[i];
rbj._iva = rbj._imp * (perc/CENTO);
rbj._iva.round(ROUND_LIRA);
}
i --;
}
}
}
// 51 per cento
vtot *= PERC_IMP_RIMBORSABILE;
atot *= PERC_IMP_RIMBORSABILE;
for (w = 0; w < 2; w++)
{
TArray& arr = w == 0 ? varr : aarr;
real timp = w == 0 ? vtot : atot;
real tiva = 0.0;
for (int i = 0; i < arr.items(); i++)
{
rObj& robj = (rObj&)arr[i];
if (timp >= robj._imp)
{
tiva += robj._iva;
timp -= robj._imp;
}
else
{
real perc = timp/robj._imp;
if (!perc.is_zero())
{
real ttiv = robj._iva * perc;
ttiv.round(ROUND_LIRA);
tiva += ttiv;
}
break;
}
}
if (w == 0) ivav = tiva;
else ivaa = tiva;
}
**************************************************************************/
// 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 ||
(month != 13 && (rmese < (next_trim(month)-2) || rmese > month)))
continue;
} else // Mensili
if (year != ryear || (month != rmese && month != 13))
continue;
int tipomov = (tiporeg)_pim->get_long("I1");
real imp = _pim->get("R0");
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;
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/vtot; alv.round(4);
ala = ivaa/atot; ala.round(4);
// vedi condizioni
rimborsami = ala > alv;
if (rimborsami)
{
// vedi di quanto ala eccede alv; deve essere > 10%
real ecc = ((ala/alv) - real(1.0));
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;
}