#include #include #include #include #include #include #include #include #include #include #include "cgsaldac.h" #include "cglib03.h" #include "cg1300m.h" #include #include #include #include #include #define AGR_PCON1 201 #define AGR_PCON2 202 enum tiporeg { vendita = 1, acquisto = 2 }; /////////////////////////////////////////////////////////// // TCheck_ivadiff_mask /////////////////////////////////////////////////////////// class TCheck_ivadiff_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TCheck_ivadiff_mask() : TAutomask("cg1300m") { } }; // Carica lo sheet in base alle impostazioni correnti (F_CLIFO, F_COFI) bool TCheck_ivadiff_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODDITTA: break; case F_ANNO: break; default: break; } return true; } /////////////////////////////////////////////////////////// // TCheck_ivadiff /////////////////////////////////////////////////////////// static bool partita_chiusa_al(const TPartita& p, const TDate& d) { bool c = p.chiusa(); if (c) { const TImporto imp = p.calcola_saldo_al(true, d, d, d); c = imp.is_zero(); } return c; } class TCheck_ivadiff : public TSkeleton_application { protected: bool ivadiff_chiusa(const TRectype& mov, const TDate& fine) const; void check_year(long firm, int year); bool is_date_ok(const TDate& d, int liqmonth, int year) const; public: virtual void main_loop(); }; bool TCheck_ivadiff::ivadiff_chiusa(const TRectype& mov, const TDate& fine) const { bool chiusa = false; const long numreg = mov.get_long(MOV_NUMREG); TLocalisamfile id(LF_IVADIFF); TRectype& rid = id.curr(); rid.put(MOV_NUMREG, numreg); int err = id.read(_isgteq); if (err == NOERR && rid.get_long(MOV_NUMREG) == numreg) { bool some_pag = false; // Ci sono pagamenti? TImporto tot; for (; err == NOERR && rid.get_long(MOV_NUMREG) == numreg; err = id.next()) { const TDate data = rid.get("DATAREGP"); if (data > fine) continue; if (data == fine && rid.get_long("NUMREGP") == numreg) continue; // Ignora pagamento automatico dopo un anno const real imp = rid.get(RMI_IMPOSTA); if (!imp.is_zero()) { const char sez = rid.get_char("SEZIONE"); tot += TImporto(sez, imp); if (!some_pag && rid.get_int(MOV_TIPOMOV) > 1) some_pag = true; } } chiusa = some_pag && tot.valore() < 0.01; } return chiusa; } bool TCheck_ivadiff::is_date_ok(const TDate& d, int liqmonth, int year) const // true se la data passata va considerata nel // ricalcolo dei progressivi mensili per il mese e anno // selezionati. Vedi cg4301.cpp per maggiori informazioni // sul nuovo filtro di selezione movimenti. { const int regyear = d.year(); return (regyear == year && liqmonth != 12) || (regyear == year + 1 && liqmonth == 12); } void TCheck_ivadiff::check_year(long firm, int year) { if (!(has_module(SCAUT, CHK_DONGLE) && ini_get_bool(CONFIG_DITTA, "cg", "GesSal"))) { warning_box("Per l'iva differita o per cassa è necessario il saldaconto"); return; } const long old_firm = prefix().get_codditta(); prefix().set_codditta(firm); TString16 key; key.format("%05ld%04d", firm, year); TRectype & lia = (TRectype &) cache().get("%LIA", key); const TString4 freqviva = lia.get("S7"); TRelation rel(LF_MOV); rel.add(LF_RMOVIVA,"NUMREG=NUMREG"); rel.add(LF_PCON,"GRUPPO=GRUPPO|CONTO=CONTO",1,LF_RMOVIVA,AGR_PCON1); rel.add(LF_PCON,"GRUPPO=GRUPPO|CONTO=CONTO|SOTTOCONTO=SOTTOCONTO",1,LF_RMOVIVA,AGR_PCON2); rel.add(LF_CAUSALI,"CODCAUS=CODCAUS"); TCursor cur(&rel, "", 4); TLocalisamfile & mov = cur.relation()->lfile(); TLocalisamfile & rmoviva = cur.relation()->lfile(LF_RMOVIVA); TRectype from(cur.curr()); from.zero(); TRectype to(from); TString8 fromreg("~"), toreg("0"); TRelation regrel("REG"); TCursor reg(®rel); TString4 codreg; long items = reg.items(); const TDate fromdate(1, 1, year); const TDate todate(31, 12, year); TString filter; for (reg = 0L; reg.pos() < items; ++reg) { codreg = reg.curr().get("CODTAB").mid(4); if (codreg < fromreg) fromreg = codreg; if (codreg > toreg) toreg = codreg; } from.put(MOV_REG, fromreg); to.put(MOV_REG, toreg); filter.format("BETWEEN(DATAREG,%ld,%ld)&&NUM(LIQDIFF==\"X\")", fromdate.date2ansi(), todate.date2ansi()); cur.freeze(false); cur.setregion(from, to); cur.setfilter(filter); items = cur.items(); cur.freeze(); TString pimsg; pimsg << TR("Ricalcolo IVA differita ditta ") << firm << TR(" anno ") << year; TProgress_monitor pi(items, pimsg, false); for (cur = 0L; cur.pos() < items; ++cur) { if (!pi.set_status(cur.pos())) break; const TString4 codreg = mov.get("REG"); TString16 s; s << year; s << format("%-3s", (const char *) codreg); const TRectype & reg = cache().get("REG", s); TDate date = mov.get(MOV_DATAREG); const int liqmonth = mov.get_int(MOV_MESELIQ); const TString4 tipodoc = mov.get(MOV_TIPODOC); const bool corrisp = reg.get_bool("B0"); tipo_movimento tm = (tipo_movimento)mov.get_int(MOV_TIPOMOV); const tiporeg tipomov = (tiporeg) reg.get_int("I0"); // 1=Vendite; 2=Acquisti // Inizio gestione IVA differita bool dok = is_date_ok(date, liqmonth, year); TPartite_array arrpart; // Partite interessate TPointer_array pagscatt; // Righe di pagsca interessate if (tm == tm_fattura) { const bool iva_diff = is_IVA_diff(mov.curr()); const bool id_chiusa = ivadiff_chiusa(mov.curr(), TDate(31,12,year-1)); if (!dok && id_chiusa) continue; // Salta vecchi movimenti differiti già chiusi // Sezione preferita per fatture decisa in base a vendita->'A' o acquisto->'D' const char sezfat = tipomov == vendita ? 'D' : 'A'; const char sezpag = (sezfat=='D') ? 'A' : 'D'; const long numreg = mov.get_long(MOV_NUMREG); real tot_incassato, tot_da_incassare; bool game_found = false; arrpart.add_numreg(numreg); const TPartita* p = arrpart.first(); const int row = p ? p->mov2rig(numreg, 0) : 0; game_found = row > 0; if (game_found && !id_chiusa) { const TRiga_partite& rp = p->riga(row); TDate orizzonte = todate; // caso tradizionale TImporto pg_per, nc_per; rp.calcola_pagato_periodo(fromdate+1L, orizzonte, pg_per, nc_per, &pagscatt); if (pagscatt.items() >= 2) { // Fondo tra loro le righe generate dallo stesso pagamento for (int p = pagscatt.last(); p > 0; p--) { const TRectype& p0 = (const TRectype&)pagscatt[p]; const TRectype& p1 = (const TRectype&)pagscatt[p-1]; if (p0.get_int(PAGSCA_NRIGP) == p1.get_int(PAGSCA_NRIGP)) { const real imp = p0.get_real(PAGSCA_IMPORTO); ((TRectype&)p1).add(PAGSCA_IMPORTO, imp); pagscatt.destroy(p, true); } } } if (iva_diff) { TPointer_array pagscaold; TImporto pg_tot, nc_tot; rp.calcola_pagato_periodo(TDate(0L), orizzonte, pg_tot, nc_tot, &pagscaold); // Controllo se ci siam persi delle note di credito negli anni scorsi if (!nc_tot.is_zero() && pagscaold.items() > pagscatt.items()) { FOR_EACH_ARRAY_ITEM(pagscaold, i, obj) { const TRectype& pagsca = *(const TRectype*)obj; const int anno = pagsca.get_int(PAGSCA_ANNO); const int nrigp = pagsca.get_int(PAGSCA_NRIGP); // Appartiene all'anno scorso? if (anno < year && nrigp < 999) // 9999 on pagsca -> 999 on ivadiff { const TPartita& p = arrpart.partita(pagsca); const TRiga_partite& rp = p.riga(nrigp); // E' veramente una nota di credito? if (rp.tipo() == tm_nota_credito) { bool found = false; FOR_EACH_ARRAY_ITEM(pagscatt, j, ps) { if (ps == obj) { found = true; break; } } if (!found) { TLocalisamfile id(LF_IVADIFF); id.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG)); id.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG)); id.put("NUMPRO", nrigp); if (id.read(_isequal) != NOERR || id.get_int("ANNOLIQ") == 0) pagscatt.add(obj); } } } } } TImporto incasso = pg_tot; TImporto saldo = rp.importo(false); incasso += nc_tot; saldo += incasso; saldo.normalize(sezfat); incasso.normalize(sezpag); if (saldo.valore() > ZERO) tot_da_incassare = saldo.valore(); if (incasso.valore() > ZERO) tot_incassato = incasso.valore(); } } } do { const int rmi_tipoatt = max(rmoviva.get_int(RMI_TIPOATT), 1); // Poteva capitare tipoatt == 0 const TString4 codiva = rmoviva.get(RMI_CODIVA); TCodiceIVA civa(codiva); if (!civa.ok()) { error_box(FR("Codice IVA \"%s\" non riconosciuto alla riga %d del movimento %ld."), (const char*)codiva, rmoviva.get_int(RMI_NUMRIG), rmoviva.get_long(RMI_NUMREG)); continue; } const real imponibile_orig = rmoviva.get_real(RMI_IMPONIBILE); const real imposta_orig = rmoviva.get_real(RMI_IMPOSTA); const real lordo_orig = imponibile_orig + imposta_orig; if (tm == tm_fattura) { const char sezfat = tipomov == vendita ? 'D' : 'A'; const TDate datareg = mov.get(MOV_DATAREG); TLocalisamfile id(LF_IVADIFF); id.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG)); id.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG)); id.put("NUMPRO", 0); if (id.read(_isequal) != NOERR) { id.zero(); id.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG)); id.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG)); id.put("NUMPRO", 0); id.put(PART_TIPOMOV, tm); id.put("TIPOATT", rmi_tipoatt); id.put("ANNOLIQ", datareg.year()); int mesereg = datareg.month(); if (freqviva == "T") { const int resto = mesereg % 3; if (resto > 0) mesereg += 3-resto; } id.put("MESELIQ", mesereg); id.put("TIPOIVA", tipomov == 2 ? 2 : 1); id.put("TIPODIFF", 1); id.put(MOV_DATAREG, mov.get(MOV_DATADOC)); id.put(RMI_CODIVA, codiva); id.put("SEZIONE", sezfat); id.put("IMPORTO", imponibile_orig+imposta_orig); id.put(RMI_IMPONIBILE, imponibile_orig); id.put(RMI_IMPOSTA, imposta_orig); const int ew = id.write(); if (ew != NOERR) cantwrite_box(id.description()); } } if (!pagscatt.empty()) { const char sezpag = tipomov == vendita ? 'A' : 'D'; real totfat = mov.get(MOV_TOTDOC); real tot = totfat; TLocalisamfile id(LF_IVADIFF); TRectype& idcurr = id.curr(); FOR_EACH_ARRAY_ITEM(pagscatt, r, obj) { const TRectype& pagsca = *(TRectype*)obj; const int nrigp = pagsca.get_int(PAGSCA_NRIGP); id.zero(); idcurr.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG)); idcurr.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG)); CHECKD(nrigp > 0, "Invalid NRIGP ", nrigp); idcurr.put("NUMPRO", min(nrigp, 999)); if (id.read(_isequal, _lock) != NOERR) { id.zero(); idcurr.put(RMI_NUMREG, rmoviva.get(RMI_NUMREG)); idcurr.put(RMI_NUMRIG, rmoviva.get(RMI_NUMRIG)); idcurr.put("NUMPRO", min(nrigp, 999)); idcurr.put(MOV_DATAREG, mov.get(MOV_DATADOC)); idcurr.put("TIPOATT", rmi_tipoatt); idcurr.put("TIPOIVA", tipomov == 2 ? 2 : 1); idcurr.put("TIPODIFF", 1); idcurr.put(RMI_CODIVA, codiva); TImporto pagtmp; bool ultimo = false; tipo_movimento tipomov_pag = tm_pagamento; if (nrigp > 0) { const TPartita& p = arrpart.partita(pagsca); const TRiga_partite& rp = p.riga(nrigp); tipomov_pag = rp.tipo(); idcurr.put(PART_TIPOMOV, tipomov_pag); idcurr.put("NUMREGP", rp.get(PART_NREG)); idcurr.put("NUMRIGP", rp.get(PART_NUMRIG)); TDate d = rp.get(PART_DATAPAG); if (!d.ok()) d = rp.get(PART_DATADOC); if (!d.ok()) d = rp.get(PART_DATAREG); idcurr.put("DATAREGP", d); idcurr.put("ANNOLIQ", d.year()); pagtmp = p.importo_pagsca(pagsca); pagtmp.normalize(sezpag); ultimo = (r == pagscatt.last()) && partita_chiusa_al(p, todate); } int meseliq = id.get_date("DATAREGP").month(); if (freqviva == "T") { const int resto = meseliq % 3; if (resto > 0) meseliq += 3-resto; } idcurr.put("MESELIQ", meseliq); idcurr.put("SEZIONE", pagtmp.sezione()); real val_imp = pagtmp.valore() * lordo_orig / tot; real val_iva = civa.scorpora(val_imp, TCurrency::get_firm_dec()); idcurr.put("IMPORTO", val_imp + val_iva); idcurr.put(RMI_IMPONIBILE, val_imp); idcurr.put(RMI_IMPOSTA, val_iva); if (id.write() != NOERR) cantwrite_box(id.description()); } } } } while (cur.next_match(LF_RMOVIVA)); } prefix().set_codditta(firm); } void TCheck_ivadiff::main_loop() { TCheck_ivadiff_mask m; while (m.run() == K_ENTER) check_year(m.get_long(F_CODDITTA), m.get_int(F_ANNO)); } void controlla_ivadiff(int argc, char* argv[]) { TCheck_ivadiff cp; cp.run(argc, argv, TR("Ricalcolo IVA differita")); }