// ----------------------------------------------------------------- // Calcolo liquidazione // part 4: casi particolari // fv 2-2-94 // ----------------------------------------------------------------- #include "cg4300.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... { real cd1_1 = _pum->get_real("R14"); cd1_1 += imponibile; _pum->put("R14", 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 { real cd1_1 = _pum->get_real("R14"); cd1_1 += imponibile; _pum->put("R14", 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 tuttp al momento dell'azzeramento della prima attivitą if (_nditte->is_first_match(LF_ATTIV)) { if (month > 12 || (_freqviva == "T" && (month % 3) != 1)) return; TString query; query << "USE IVADIFF KEY 2"; query << "\nFROM ANNOLIQ=" << _year; if (month > (_freqviva == "T" ? 3 : 1)) query << " MESELIQ=" << month; TISAM_recordset id(query); TLocalisamfile& file = id.cursor()->file(); for (bool ok = id.move_first(); ok; ok = id.move_next()) { 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(); } } }