#include #include #include #include #include // cache() #include // TISAM_recordset #include #include #include // TExternal_app #include "cglib03.h" #include "tf0.h" #include "tf0200a.h" #define CAMPI_CON_BOOLEAN F_TOTOPATT // ComLiqPerIva: Comunicazione Liquidazioni Periodiche IVA /** Utilities **/ // Ritorna un cursore di tab.PRM const TCursor getPRM(int anno) { static TRelation rprm(LF_TAB); TRectype from(rprm.curr()); from.put("COD", "PRM");from.put("CODTAB", anno); TRectype to(rprm.curr()); to.put("COD" , "PRM");to.put("CODTAB", anno); TCursor cprm(&rprm, "", 1, &from, &to); return cprm; } // Ritorna il record richiesto di tabcom.LIM const TRectype getLIM(int anno, int mese) { TString key; key << anno; if(mese < 10) key << "0" << mese; else key << mese; return cache().get("LIM", key); } // Ritorna il record richiesto di tabcom.LIA const TRectype getLIA(int anno) { TString key; key << format("%05d", prefix().firm().codice()) << anno; // %05d Crea un numero di 5 cifre partendo dal codice e mettendoci 0 davanti return cache().get("%LIA", key); } // Ritorna il record richiesto di tabcom.LIM const TRectype getLAM(int anno, int mese) { TString key; key << anno; if(mese < 10) key << "0" << mese; else key << mese; return cache().get("LAM", key); } // Ritorna il record valido richiesto di tabcom.VER const TRectype getVER(int anno, int mese) { // Questa tabella ha come chiave l'inizio validità, creo un cursore e scorro finche non trovo l'ultimo periodo valido static TRelation rver(LF_TABCOM); static TRectype from(rver.curr()); from.put("COD", "VER"); static TRectype to(rver.curr()); to.put("COD" , "VER"); static TCursor cver(&rver, "", 1, &from, &to); // Costruisco il controllo sulla chiave TString key; key << anno; if(mese < 10) key << "0" << mese; else key << mese; TRectype rowRet(LF_TABCOM); for(cver = 0; cver.pos() < cver.items(); ++cver) { TRectype rowVer = cver.curr(); if(rowVer.get("CODTAB") < key) { rowRet = rowVer; } else break; } return rowRet; } // Scopiazzata brutalmente da cg4304.cpp, aggiunto controllo indetraibilità per le imposte, non devono essere prese in considerazione se indetraibili int calc_inc_diff(int anno, int mese, int tipoiva, real& imponibile_diff, real& imposta_diff, real& imponibile_xcas, real& imposta_xcas) { CHECKD(tipoiva == 1 || tipoiva == 2, "Bad tipo iva:", tipoiva); int flag = 0; imponibile_diff = imposta_diff = imponibile_xcas = imposta_xcas = ZERO; TString limit; limit << "ANNOLIQ=" << anno; if (mese < 13) limit << " MESELIQ=" << mese; TString query; // righe pagamento (TIPOMOV>=3) ed escluse NC! query << "USE IVADIFF KEY 2 SELECT (TIPOMOV>2)&&(TIPOIVA=" << tipoiva << ")" << "\nFROM " << limit << "\nTO " << limit; TISAM_recordset id(query); const TRectype& rec = id.cursor()->curr(); for (bool ok = id.move_first(); ok; ok = id.move_next()) { const real iva = rec.get_real(RMI_IMPOSTA); const real imp = rec.get_real(RMI_IMPONIBILE); if (!iva.is_zero() || !imp.is_zero()) { const int tipodiff = rec.get_int("TIPODIFF"); switch (tipodiff) { case 1: imponibile_diff += imp; if(!rec.get_bool("INDETR")) imposta_diff += iva; break; case 2: imponibile_xcas += imp; if(!rec.get_bool("INDETR")) imposta_xcas += iva; break; default: break; } flag |= tipodiff; } } if (tipoiva == 2 && !rec.get_bool("INDETR")) { real perc_prorata; query = "USE PLM"; query << "\nFROM CODTAB=" << anno << "\nTO CODTAB=" << anno; TISAM_recordset ip(query); const TRectype& recp = ip.cursor()->curr(); for (bool ok = ip.move_first(); ok && perc_prorata == ZERO; ok = ip.move_next()) { int m = atoi(ip.get("CODTAB").as_string().mid(10)); real p = ip.get("R12").as_real(); if (m == mese && p != ZERO) perc_prorata = p; } if (perc_prorata > ZERO) { real ind = imposta_diff * perc_prorata / CENTO; ind.round(TCurrency::get_firm_dec()); imposta_diff -= ind; ind = imposta_xcas * perc_prorata / CENTO; ind.round(TCurrency::get_firm_dec()); imposta_xcas -= ind; } } return flag; } class ComLiqPerIva_mask : public TAutomask { protected: bool mensile; TRectype trueData; virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void extractinator(); void checkOldValue(int field, real val); public: ComLiqPerIva_mask() : TAutomask("tf0200a"), trueData(LF_IVALIQ) { first_focus(F_ANNO); } void saveGen(); }; bool ComLiqPerIva_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_ANNO: if(e == fe_modify) { TString cod = get(F_CODDITTA); cod << get_int(F_ANNO); if(cache().get("%LIA", cod).empty()) { warning_box("Attenzione anno di liquidazione non presente"); set(F_ANNO, ""); break; } if(cache().get("%LIA", cod, "S7") == "M") { mensile = true; enable(F_MESE); disable(F_TRIMESTRE); } else { mensile = false; disable(F_MESE); enable(F_TRIMESTRE); } } else if(e == fe_init) { // Per trovare un valore tento per 5 anni di vedere se c'è una liquidazione aperta, così da valorizzare tutta la roba int year = TDate(TODAY).year(); for(int i = year; i >= year - 5; i--) { TString cod = get(F_CODDITTA); cod << i; if(cache().get("%LIA", cod).empty()) continue; // Trovato set(F_ANNO, i); if(cache().get("%LIA", cod, "S7") == "M") { mensile = true; enable(F_MESE); disable(F_TRIMESTRE); } else { mensile = false; disable(F_MESE); enable(F_TRIMESTRE); } break; } } break; case F_MESE: if(e == fe_modify && mensile) set(F_TRIMESTRE, (get_int(F_MESE) - 1) / 3 + 1); break; case F_TRIMESTRE: if(e == fe_modify && !mensile) set(F_MESE, get_int(F_TRIMESTRE) * 3); break; case DLG_RECALC: // Vado a prendere i dati di quel mese dalla liquidazione IVA if(e == fe_button) { // Controllo che non ci sia già if(!cache().get(LF_IVALIQ, TString(get(F_ANNO)) << "|" << get(F_MESE) << "|U").empty()) { if(!yesno_box("Sono già stati elaborati questi dati, si desidera ricalcolarli?")) break; } extractinator(); } break; case DLG_EMAIL: { if(e == fe_button) { // Richiamo il programma di invio TExternal_app invioApp("tf0 -4"); invioApp.run(); } } break; case DLG_SAVEREC: if(e != fe_init && !trueData.empty()) trueData.write_rewrite(TLocalisamfile(LF_IVALIQ)); } if(o.dlg() >= CAMPI_CON_BOOLEAN && o.dlg() <= F_IMPNOVER && e == fe_modify) // Se l'utente modifica manualmente uno dei campi calcolati da Campo flaggo il DB { checkOldValue(o.dlg(), get_real(o.dlg())); } // Controllo sull'aggiornamento di campi collegati ad altri if(e == fe_modify) { switch(o.dlg()) { // Iva Esigibile VS Iva Detratta case F_IVAES : case F_IVAESXC : case F_IVAESDIFF : case F_IVADET : case F_IVADETXC : case F_IVADETDIFF : { real ivaes = get_real(F_IVAES) + get_real(F_IVAESXC) + get_real(F_IVAESDIFF); real ivadet = get_real(F_IVADET) + get_real(F_IVADETXC) + get_real(F_IVADETDIFF); if((ivaes - ivadet) >= ZERO) { set(F_IVADOV, ivaes - ivadet); set(F_IVADOVC, ZERO); checkOldValue(F_IVADOV, ivaes - ivadet); checkOldValue(F_IVADOVC, ""); } else { set(F_IVADOV, ZERO); set(F_IVADOVC, (ivaes - ivadet) * -UNO); checkOldValue(F_IVADOV, ""); checkOldValue(F_IVADOVC, (ivaes - ivadet) * -UNO); } } // IVA da versare VS a credito case F_IVADOV : case F_DEBPREC : case F_INTLIQTRI : case F_IVADOVC : case F_CREPREC : case F_CREAPREC : case F_VEAUE : case F_CREIMP : case F_ACCDOV : { // Ricalcolo VP13 e VP14 real debito = get_real(F_IVADOV) + get_real(F_DEBPREC) + get_real(F_INTLIQTRI); real credito = get_real(F_IVADOVC) + get_real(F_CREPREC) + get_real(F_CREAPREC) + get_real(F_VEAUE) + get_real(F_CREIMP) + get_real(F_ACCDOV); if(debito - credito >= ZERO) { set(F_IVAVER, debito - credito); set(F_IVAVERC, ZERO); checkOldValue(F_IVAVER, debito - credito); checkOldValue(F_IVAVERC, ""); } else { set(F_IVAVER, ZERO); set(F_IVAVERC, credito - debito); checkOldValue(F_IVAVER, ""); checkOldValue(F_IVAVERC, credito - debito); } } break; } } return true; } // Funzione che effettivamente estrapola i dati necessari void ComLiqPerIva_mask::extractinator() // Per gli amici GTFO { /* Devo estrapolare più mesi, per farlo vado ciclo n volte (1 o 3) in base se stiamo parlando di trimestralità o meno * I dati da prelevare saranno in PRM, LIM e %LIA * In PRM e LIM troverò le informazioni suddivise per mese, mentre in %LIA ho l'anno di liquidazione */ int start = mensile ? get_int(F_MESE) : (((get_int(F_TRIMESTRE) - 1) * 3) + 1); int end = mensile ? start : start + 2; int anno = get_int(F_ANNO); // Valori da calcolare real totopatt = ZERO; real totopattxc = ZERO; real totoppas = ZERO; real totoppasxc = ZERO; real ivaes = ZERO; real ivaesxc = ZERO; real ivaesdiff = ZERO; real ivadet = ZERO; real ivadetxc = ZERO; real ivadetdiff = ZERO; real rettifiche = ZERO; real varimp = ZERO; real rimborsi = ZERO; real impnover = ZERO; real crespec = ZERO; real vereff = ZERO; real ivadov = ZERO; real ivadovc = ZERO; real debprec = ZERO; real creprec = ZERO; real creaprec = ZERO; real intliqtri = ZERO; real accdov = ZERO; real ivaver = ZERO; real ivaverc = ZERO; // Costanti static const int reg_att = 1; static const int reg_pas = 2; for(; start <= end; start++) { TDate data_da(1, start, anno); TDate data_a(31, start, anno); /**************************************************************************************************************** * TOTOPATT, TOTOPATTXC, TOTOPPAS, TOTOPPASXC, IVAES, IVAESXC, IVAESDIFF, * IVADET , IVADETXC, IVADETDIFF ****************************************************************************************************************/ // Riga LIM const TRectype rowLim = getLIM(anno, start); // Controllo che la liquidazione è stata effettuata if(rowLim.empty()) { message_box("Errore LIM"); error_box("Attenzione non è stata calcolata la liquidazione del periodo corrente"); return; } // Riga LIA const TRectype rowLia = getLIA(anno); // Calcolo il cursore di PRM //TCursor curPrm = getPRM(anno); static TRelation rprm(LF_TAB); TRectype from(rprm.curr()); from.put("COD", "PRM");from.put("CODTAB", anno); TRectype to(rprm.curr()); to.put("COD" , "PRM");to.put("CODTAB", anno); TCursor curPrm(&rprm, "", 1, &from, &to); for(curPrm = 0; curPrm.pos() < curPrm.items(); ++curPrm) { TRectype rowPrm = curPrm.curr(); // Controllo il mese TString codtab = rowPrm.get("CODTAB"); if(atoi(rowPrm.get("CODTAB").sub(13,15)) != start) continue; // Verifico su che registro mi trovo int tiporeg = rowPrm.get_int("I1"); bool detraibile = atoi(rowPrm.get("CODTAB").mid(20,1)) == 0; // Se > è indetraibile if(!detraibile) continue; // Non mi interessa if(tiporeg == reg_att) { totopatt = totopatt + rowPrm.get_real("R0"); } else if(tiporeg == reg_pas) { totoppas = totoppas + rowPrm.get_real("R0"); } } // Se ha attiva l'IVA x cassa if(gestione_IVAxCassa(data_da)) { // IVA esigibile real imponibile_diff, imposta_diff, imponibile_xcas, imposta_xcas; imponibile_diff = imposta_diff = imponibile_xcas = imposta_xcas = ZERO; // 1 = Vendite calc_inc_diff(anno, start, reg_att, imponibile_diff, imposta_diff, imponibile_xcas, imposta_xcas); totopattxc = totopattxc + imponibile_xcas; ivaesxc = ivaesxc + imposta_xcas; ivaesdiff = ivaesdiff + imposta_diff; // IVA detraibile imponibile_diff = imposta_diff = imponibile_xcas = imposta_xcas = ZERO; // 2 = Acquisti calc_inc_diff(anno, start, reg_pas, imponibile_diff, imposta_diff, imponibile_xcas, imposta_xcas); totoppasxc = totoppasxc + imponibile_xcas; ivadetxc = ivadetxc + imposta_xcas; ivadetdiff = ivadetdiff + imposta_diff; } /** Resto *****************************************************************************************************/ TRectype rowLam = getLAM(anno, start); ivaes = ivaes + rowLam.get_real("R0") + ivaesxc + ivaesdiff; ivadet = ivadet + rowLam.get_real("R1") + ivadetxc + ivadetdiff; rettifiche = rettifiche + rowLim.get_real("R5"); varimp = varimp + rowLim.get_real("R17"); rimborsi = rimborsi + rowLim.get_real("R1"); impnover = impnover + rowLim.get_real("R18"); crespec = crespec + rowLim.get_real("R19"); vereff = vereff + rowLim.get_real("R8"); debprec = debprec + rowLim.get_real("S2"); real appReal = ZERO; // Credito periodo precedente if(start != 1) // A gennaio non lo calcolo { /* Se siamo in una liquidazione trimestrale e stiamo calcolando il primo trimestre * andiamo a prendere i dati da LAM */ if(!mensile && start <= 3) { // Recupero il record di LAM del mese precedente TRectype tempLam = getLAM(anno, start - 1); // Calcolo eventuale credito real appCredito = tempLam.get_real("R0") - tempLam.get_real("R1"); // Se c'è un credito lo scrivo if(appCredito > ZERO) creprec = creprec + appCredito; } /* Se sono in una liquidazione mensile o nel primo mese di una trimestrale * es. aprile ((4 - 1) % 3) = 0, maggio ((5 - 1) % 3) = 1 */ else if(mensile || (!mensile && ((start - 1) % 3) == 0)) { TString key; key << anno << "|" << start - 1 << "|U"; real appCredito(cache().get(LF_IVALIQ, key, "IVADOVC")); if(appCredito > ZERO) creprec = creprec + appCredito; } } // Credito anno precedente /* Per calcolare il credito dell'anno precedente inizio a leggere i record precedenti su IVALIQ * fino a quando ne trovo uno >= 0. * Questi geni hanno messo la possibilità di mettere un valore <0 se voglio utilizzare del credito precedente */ if(mensile || (!mensile && ((start - 1) % 3) == 0)) { TRelation ivaLiq(LF_IVALIQ); TRectype from(ivaLiq.curr()); from.put("ANNO", anno); from.put("MESE", 1); // Fino al mese precedente TRectype to(ivaLiq.curr()); to.put("ANNO", anno); to.put("MESE", start - 1); TSorted_cursor curLiq(&ivaLiq, "MESE-", "GENERATA!=\"G\"", 1, &from, &to); bool trovato = false; for(curLiq = 0; curLiq.pos() < curLiq.items() && !trovato; ++curLiq) { TRectype rowLiq = curLiq.curr(); if(rowLiq.get_int("MESE") >= start) continue; // Perchè li prende lo stesso? creaprec = creaprec + rowLiq.get_real("CREAPREC") - rowLiq.get_real("IVADOV"); // Se è > 0 Ho trovato il primo valore messo nella dichiarazione if(rowLiq.get_real("CREAPREC") > ZERO) { trovato = true; } } if(!trovato) { creaprec = rowLia.get_real("R0"); } else if(creaprec < ZERO) { creaprec = ZERO; } } /* Se siamo in una liquidazione trimestrale la scadenza della dichiarazione IVA è il 28 febbraio * quindi so per certo che il valore calcolato in LIA.R0 è stato trasmesso */ else if(!mensile && start == 3) { creaprec = rowLia.get_real("R0"); } intliqtri = intliqtri + rowLim.get_real("R14"); accdov = accdov + rowLim.get_real("R11"); } // Controllo debprec // Calcolo prendendo dalla tabella %VER TRectype rowVer = getVER(anno, start); if(rowVer.empty() || rowVer.get_real("R5") == ZERO) { message_box("Errore VER"); error_box("Non è stata valorizzato correttamente il campo \"Periodico\" in \"Versamenti ed interessi IVA\""); return; } else { if(debprec > rowVer.get_real("R5")) // Se è maggiore di 25.82€ va azzerato debprec = ZERO; } // Imposto tutti i campi set(F_TOTOPATT, totopatt); set(F_TOTOPATTXC, totopattxc); set(F_TOTOPPAS, totoppas); set(F_TOTOPPASXC, totoppasxc); set(F_IVAES, ivaes); set(F_IVAESXC, ivaesxc); set(F_IVAESDIFF, ivaesdiff); set(F_IVADET, ivadet); set(F_IVADETXC, ivadetxc); set(F_IVADETDIFF, ivadetdiff); // Iva dovuta o a credito if(ivaes - ivadet > ZERO) { ivadov = ivaes - ivadet; set(F_IVADOV, ivadov); set(F_IVADOVC, ZERO); } else { ivadovc = ivadet - ivaes; set(F_IVADOV, ZERO); set(F_IVADOVC, ivadovc); } set(F_DEBPREC, debprec); set(F_CREPREC, creprec); set(F_CREAPREC, creaprec); //set(F_VEAUE, veaue); // Campi non calcolati, messi qua per un eventuale futuro //set(F_CREIMP, creimp); set(F_INTLIQTRI, intliqtri); set(F_ACCDOV, accdov); // Calcolo l'IVA da versare o a Credito ivaver = (ivadov + debprec + intliqtri) - (ivadovc + creprec + creaprec + get_real(F_VEAUE) + get_real(F_CREIMP) + accdov); ivaverc = (ivadovc + creprec + creaprec + get_real(F_VEAUE) + get_real(F_CREIMP) + accdov) - (ivadov + debprec + intliqtri); if(ivaver >= ZERO) { set(F_IVAVER, ivaver); set(F_IVAVERC, ZERO); } else { set(F_IVAVER, ZERO); set(F_IVAVERC, ivaverc); } set(F_RETTIFICHE, rettifiche); set(F_VARIMP, varimp); set(F_RIMBORSI, rimborsi); set(F_IMPNOVER, impnover); set(F_CRESPEC, crespec); set(F_VEREFF, vereff); // Preparo il record saveGen(); // Azzero i booleani for(int i = B_TOTOPATT; i <= B_CRESPEC; i++) { set(i, ""); } } void ComLiqPerIva_mask::saveGen() { // Assegno tutti i campi trueData.put("ANNO", get(F_ANNO)); trueData.put("MESE", get(F_MESE)); trueData.put("TRIMESTRE", get(F_TRIMESTRE)); trueData.put("GENERATA", 'G'); // Segno che è generata da campo trueData.put("TOTOPATT", get(F_TOTOPATT)); trueData.put("TOTOPATTXC", get(F_TOTOPATTXC)); trueData.put("TOTOPPAS", get(F_TOTOPPAS)); trueData.put("TOTOPPASXC", get(F_TOTOPPASXC)); trueData.put("IVAES", get(F_IVAES)); trueData.put("IVAESXC", get(F_IVAESXC)); trueData.put("IVAESDIFF", get(F_IVAESDIFF)); trueData.put("IVADET", get(F_IVADET)); trueData.put("IVADETXC", get(F_IVADETXC)); trueData.put("IVADETDIFF", get(F_IVADETDIFF)); trueData.put("IVADOV", get(F_IVADOV)); trueData.put("IVADOVC", get(F_IVADOVC)); trueData.put("DEBPREC", get(F_DEBPREC)); trueData.put("CREPREC", get(F_CREPREC)); trueData.put("CREAPREC", get(F_CREAPREC)); trueData.put("VEAUE", get(F_VEAUE)); trueData.put("CREIMP", get(F_CREIMP)); trueData.put("INTLIQTRI", get(F_INTLIQTRI)); trueData.put("ACCDOV", get(F_ACCDOV)); trueData.put("IVAVER", get(F_IVAVER)); trueData.put("IVAVERC", get(F_IVAVERC)); trueData.put("RETTIFICHE", get(F_RETTIFICHE)); trueData.put("VARIMP", get(F_VARIMP)); trueData.put("RIMBORSI", get(F_RIMBORSI)); trueData.put("CRESPEC", get(F_CRESPEC)); trueData.put("IMPNOVER", get(F_IMPNOVER)); trueData.put("VEREFF", get(F_VEREFF)); } void ComLiqPerIva_mask::checkOldValue(int field, real val) { if(trueData.empty()) { TString key; key << get(F_ANNO) << "|" << get(F_MESE) << "|G"; trueData = cache().get(LF_IVALIQ, key); } real trueVal = ZERO; // Modo più intelligente di uno stupido switch case? switch(field) { case F_TOTOPATT: trueVal = trueData.get_real("TOTOPATT"); break; case F_TOTOPATTXC: trueVal = trueData.get_real("TOTOPATTXC"); break; case F_TOTOPPAS: trueVal = trueData.get_real("TOTOPPAS"); break; case F_TOTOPPASXC: trueVal = trueData.get_real("TOTOPPASXC"); break; case F_IVAES: trueVal = trueData.get_real("IVAES"); break; case F_IVAESXC: trueVal = trueData.get_real("IVAESXC"); break; case F_IVAESDIFF: trueVal = trueData.get_real("IVAESDIFF"); break; case F_IVADET: trueVal = trueData.get_real("IVADET"); break; case F_IVADETXC: trueVal = trueData.get_real("IVADETXC"); break; case F_IVADETDIFF: trueVal = trueData.get_real("IVADETDIF"); break; case F_IVADOV: trueVal = trueData.get_real("IVADOV"); break; case F_IVADOVC: trueVal = trueData.get_real("IVADOVC"); break; case F_DEBPREC: trueVal = trueData.get_real("DEBPREC"); break; case F_CREPREC: trueVal = trueData.get_real("CREPREC"); break; case F_CREAPREC: trueVal = trueData.get_real("CREAPREC"); break; case F_VEAUE: trueVal = trueData.get_real("VEAUE"); break; case F_CREIMP: trueVal = trueData.get_real("CREIMP"); break; case F_INTLIQTRI: trueVal = trueData.get_real("INTLIQTRI"); break; case F_ACCDOV: trueVal = trueData.get_real("ACCDOV"); break; case F_IVAVER: trueVal = trueData.get_real("IVAVER"); break; case F_IVAVERC: trueVal = trueData.get_real("IVAVERC"); break; case F_RETTIFICHE: trueVal = trueData.get_real("RETTIFICHE"); break; case F_VARIMP: trueVal = trueData.get_real("VARIMP"); break; case F_RIMBORSI: trueVal = trueData.get_real("RIMBORSI"); break; case F_CRESPEC: trueVal = trueData.get_real("CRESPEC"); break; case F_IMPNOVER: trueVal = trueData.get_real("IMPNOVER"); break; case F_VEREFF: trueVal = trueData.get_real("VEREFF"); break; } set(field + 50, trueVal != val ? "X" : ""); } class ComLiqPerIva_app : public TRelation_application { private: ComLiqPerIva_mask* _mask; TRelation* _rel; protected: bool user_create(); bool user_destroy(); virtual TMask* get_mask(int mode) { return _mask; } public: virtual TRelation* get_relation() const {return (TRelation*)_rel;} }; bool ComLiqPerIva_app::user_create() { _rel = new TRelation(LF_IVALIQ); _mask = new ComLiqPerIva_mask; set_search_field(F_ANNO); return true; } bool ComLiqPerIva_app::user_destroy() { delete _mask; return true; } int tf0200(int argc, char* argv[]) { ComLiqPerIva_app app; app.run(argc, argv, TR("Trasferimento dati liquidazione IVA")); return 0; }