// Esercizi contabili e registri IVA #include "cglib.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cgsaldac.h" /////////////////////////////////////////////////////////// // Causale /////////////////////////////////////////////////////////// TCausale::TCausale(const char* cod, int year) : TArray(12), _rec(LF_CAUSALI), _iva(iva_errata), _corrisp(false), _sezione_clifo(' '), _provvisorio(' '), _sezione_ritsoc(' '), _sezione_ritfis(' '), _sezione_revcharge(' '), _regolarizzazione(false) { if (cod && *cod) read(cod, year); if (soloiva()) { TCursor c(new TRelation(LF_CAUSALI)); int items = c.items(); for (c = 0L; c.pos() < items && !_regolarizzazione; ++c) _regolarizzazione = c.curr().get(CAU_CODCAUREG) == codice(); } } bool TCausale::reread() { const TString4 cod = codice(); if (cod.full()) { const int year = _reg.year(); if (year > 0) return read(cod, year); } return false; } // Legge le righe della causale attualmente selezionata sulla maschera bool TCausale::read(const char* cod, int year) { _rec.zero(); // Delete header destroy(); // Delete all rows _iva = iva_errata; // Delete misc info _sezione_clifo = _sezione_ritsoc = _provvisorio = ' '; _corrisp = false; if (cod && *cod > ' ') { _rec = cache().get(LF_CAUSALI, cod); if (_rec.empty()) return false; _provvisorio = _rec.get_char(CAU_PROVV); TLocalisamfile rcaus(LF_RCAUSALI); rcaus.put(CAU_CODCAUS, cod); rcaus.put(CAU_NRIGA, 0); int err; for (err = rcaus.read(_isgteq); // Find first line err == NOERR && rcaus.get(CAU_CODCAUS) == cod; err = rcaus.next()) // Read next line { const int riga = rcaus.get_int(CAU_NRIGA); add(rcaus.curr(), riga); } const TString4 codreg(_rec.get(CAU_REG)); const bool ok = _reg.read(codreg, year); // Read register if (!ok && codreg.not_empty()) return error_box(FR("Non esiste il registro '%s' del %d"), (const char*)codreg, year); calcIVA(); } else { _iva = nessuna_iva; // Clear IVA data _corrisp = false; _reg.read("", year); } return true; } TBill& TCausale::bill(int num, TBill& conto) const { const TRectype* rec = row(num); if (rec != nullptr) conto.set(rec->get_int(RCA_GRUPPO), rec->get_int(RCA_CONTO), rec->get_long(RCA_SOTTOCONTO), rec->get_char(RCA_TIPOCF)); return conto; } const char* TCausale::cod_desc_agg(int num) const { const TRectype* rec = row(num); if (rec) return rec->get(RCA_CODDESC); return ""; // ho problemi con ? : } const char* TCausale::desc_agg(int num) const { const char* cod = cod_desc_agg(num); if (cod && *cod) return cache().get("%DPN", cod, "S0"); return ""; // ho problemi con ? : } const char* TCausale::descrizione() const { return _rec.get(CAU_DESCR); } const char* TCausale::codice() const { return _rec.get(CAU_CODCAUS); } bool TCausale::data_doc() const { return _rec.get_bool(CAU_DATADOC); } bool TCausale::num_doc() const { return _rec.get_bool(CAU_NUMDOC); } bool TCausale::apertura() const { return _rec.get_char(CAU_MOVAP) == 'A'; } bool TCausale::chiusura() const { return _rec.get_char(CAU_MOVAP) == 'C'; } bool TCausale::sezionale() const { return _rec.get_bool(CAU_MOVSEZ); } bool TCausale::valuta() const { return _rec.get_bool(CAU_MOVVAL); } bool TCausale::intra() const { return _rec.get_bool(CAU_INTRACOM); } bool TCausale::valintra() const { return _rec.get_bool(CAU_VALINTRA); } bool TCausale::soloiva() const { return _rec.get_bool(CAU_SOLOIVA); } int TCausale::regime_speciale() const { return _rec.get_int(CAU_REGSPIVA); } bool TCausale::regolarizzazione() const { return _regolarizzazione; } bool TCausale::ril_fat_em_ric() const { return _rec.get_bool(CAU_RILFTEMRI); } bool TCausale::datareg_prec() const { return _rec.get_bool(CAU_DATAREGPR); } bool TCausale::reverse_charge() const { const int rsi = regime_speciale(); return (rsi >= 13 && rsi <= 18) || rsi == 50 || rsi == 51; // Reverse charge! } bool TCausale::reverse_charge_pubb() const { const int rsi = regime_speciale(); return (rsi >= 13 && rsi <= 19) || rsi == 50 || rsi == 51; // Reverse charge! } bool TCausale::esclusione_allegati() const { return _rec.get_bool(CAU_ALLEG); } const TString& TCausale::causale_collegata() const { return _rec.get(CAU_CODCAUSIM); } const TString& TCausale::causale_reg_iva() const { return _rec.get(CAU_CODCAUREG); } const TString& TCausale::tipo_doc() const { return _rec.get(CAU_TIPODOC); } tipo_movimento TCausale::tipomov() const { return tipo_movimento(_rec.get_int(CAU_TIPOMOV)); } const TString& TCausale::tipodoc() const { return _rec.get(CAU_TIPODOC); } bool TCausale::saldaconto(const TDate& datareg) const { bool yes = tipomov() > 0; if (yes && datareg.ok()) { static TDate _data_sal = ini_get_string(CONFIG_DITTA, "cg", "DatSal"); yes = datareg >= _data_sal; } return yes; } int TCausale::link_m770() const { return _rec.get_int(CAU_M770); } char TCausale::link_cespiti() const { return _rec.get_char(CAU_COLLCESP); } bool TCausale::link_analitica() const { return _rec.get_bool(CAU_MOVIND); } bool TCausale::link_industriale() const { return _rec.exist(CAU_MOVCGIND) && _rec.get_bool(CAU_MOVCGIND); } bool TCausale::ok() const { return iva() != iva_errata; } char TCausale::sezione(int riga, bool low_level) const { const TRectype* rec = row(riga); char sez = rec ? toupper(rec->get_char(RCA_SEZIONE)) : ' '; if (sez <= ' ' && !low_level) // Guess section on tipocf { const TRectype* uno = row(1); char tipocf = uno ? toupper(uno->get_char(RCA_TIPOCF)) : ' '; if (tipocf <= ' ') tipocf = (iva() == iva_vendite) ? 'C' : 'F'; // Guess tipocf on IVA sez = (tipocf == 'C') ? 'D' : 'A'; } return sez; } char TCausale::sezione_clifo() const { if (_sezione_clifo <= ' ') (char&)_sezione_clifo = sezione(1); return _sezione_clifo; } char TCausale::sezione_ritsoc() const { if (_sezione_ritsoc <= ' ') { const tipo_movimento tm = tipomov(); (char&)_sezione_ritsoc = sezione(tm <= tm_nota_credito ? RIGA_RITENUTE_SOCIALI : RIGA_PAG_RITSOC, true); if (_sezione_ritsoc < 'A') (char&)_sezione_ritsoc = (tm <= tm_nota_credito ? sezione_clifo() : (sezione_clifo() == 'D' ? 'A' : 'D')); } return _sezione_ritsoc; } char TCausale::sezione_ritfis() const { if (_sezione_ritfis == ' ') { const tipo_movimento tm = tipomov(); (char&)_sezione_ritfis = sezione(tm <= tm_nota_credito ? RIGA_RITENUTE_FISCALI : RIGA_PAG_RITFIS, true); // Fatture o Pagamenti if (_sezione_ritfis < 'A') (char&)_sezione_ritfis = (tm <= tm_nota_credito ? sezione_clifo() : (sezione_clifo() == 'D' ? 'A' : 'D')); } return _sezione_ritfis; } char TCausale::sezione_revcharge() const { if (_sezione_revcharge <= ' ') { (char&)_sezione_revcharge = sezione(RIGA_REVERSE_CHARGE); if (_sezione_revcharge < 'A') (char&)_sezione_revcharge = sezione_clifo(); } return _sezione_revcharge; } bool TCausale::fattura_in_ritardo() const { return _rec.get_bool(CAU_RITFATT); } void TCausale::calcIVA() { TipoIVA i = nessuna_iva; // Tipo IVA di default bool c = false; // Corrispettivi di default const TString& td = tipo_doc(); if (td.full()) { const TRectype& tpd = cache().get("%TPD", td); if (!tpd.empty()) { i = (TipoIVA)tpd.get_int("I0"); // IVA acquisti, vendite, generica const TipoIVA ri = _reg.iva(); if (i == iva_generica) i = ri; if (i != ri) { error_box(FR("Tipo documento '%s' incompatibile con tipo registro"), (const char*)td); i = iva_errata; } c = tpd.get_bool("B0"); // B0 flag corrispettivi } else error_box(FR("Tipo documento sconosciuto: '%s'"), (const char*)td); } _iva = i; _corrisp = c; } const TString& TCausale::compatible(const TCausale& c) const { const char* err = nullptr; if (sezionale() != c.sezionale()) err = TR("il segnale di sezionale"); if (intra() != c.intra()) err = TR("la gestione dei movimenti intra"); if (valuta() != c.valuta()) err = TR("la gestione valuta"); if (valintra() != c.valintra()) err = TR("la gestione valuta intracomunitaria"); if (corrispettivi() != c.corrispettivi()) err = TR("la gestione dei corrispettivi"); if (iva() != c.iva()) err = TR("il tipo di IVA"); if (tipomov() != c.tipomov()) err = TR("il tipo di movimento"); if (err != nullptr) { TString& msg = get_tmp_string(); msg.format(FR("Causale incompatibile per %s"), err); return msg; } return EMPTY_STRING; } bool TCausale::IVA2bill(const TCodiceIVA& iva, TBill& c) const { const TString& tipo = iva.tipo(); if (tipo.not_empty()) { if (tipo == "ES") bill(5, c); else if (tipo == "NI") bill(6, c); else if (tipo == "NS") bill(7, c); } if (!c.ok()) bill(2, c); const int spric = c.tipo_cr(); if (spric == 2 || spric == 3) { const TString& td = tipo_doc(); if (td == "FV" || td == "NC") c.tipo_cr(4); } return c.ok(); } /////////////////////////////////////////////////////////// // TCache_causali /////////////////////////////////////////////////////////// class TCache_causale : public TCache { protected: virtual TObject* key2obj(const char* key); public: const TCausale & caus(const char* key, const int anno = 0); TCache_causale() : TCache() { } virtual ~TCache_causale() { } }; TObject* TCache_causale::key2obj(const char* key) { TToken_string k(key); TString4 cod; k.get(0, cod); cod.trim(); int year; k.get(1, year); return new TCausale(cod, year); } const TCausale & TCache_causale::caus(const char* key, const int anno) { TToken_string k(key); k.add(anno); return (const TCausale &)*objptr(k); } const TCausale & cached_causale(const char * codcaus, int year) { HIDDEN TCache_causale __cache_causale; return __cache_causale.caus(codcaus, year); } /////////////////////////////////////////////////////////// // Gestione Tabella esercizi /////////////////////////////////////////////////////////// TArray TEsercizi_contabili::_esercizi; long TEsercizi_contabili::_firm = 0; TEsercizio::TEsercizio(const TRectype& rec) { _codice = rec.get_int("CODTAB"); _inizio = rec.get("D0"); _fine = rec.get("D1"); _scarico = rec.get("D2"); _chiusura = rec.get("D3"); _chiusura_mag = rec.get("D4"); } int TEsercizio::compare(const TSortable& s) const { const TEsercizio& e = (const TEsercizio&)s; int c = 0; if (_inizio != e._inizio) c = _inizio > e._inizio ? +1 : -1; return c; } const TDate& TEsercizio::chiusura() const { if (!_chiusura.ok() && fine() < TDate(TODAY)) { TAssoc_array chiusure; // Lista delle causali di chiusura (solitamente una!) TISAM_recordset caus("USE CAUS SELECT MOVAP='C'"); for (bool ok = caus.move_first(); ok; ok = caus.move_next()) { const TString& codcaus = caus.get(CAU_CODCAUS).as_string(); chiusure.add(codcaus, codcaus); } const TDate presto = fine(); // Prima data utile per chiusura esercizio TDate tardi = presto; tardi.addyear(); // Ultima data utile per chiusura esercizio TString query; query = "USE MOV KEY 2"; if (chiusure.items() == 1) { const TString& codcaus = *(TString*)chiusure.first_item(); query << " SELECT CODCAUS='" << codcaus << '\''; } query << "\nFROM DATAREG=#PRESTO\nTO DATAREG=#TARDI"; TISAM_recordset mov(query); mov.set_var("#PRESTO", presto); mov.set_var("#TARDI", tardi); for (bool ok = mov.move_first(); ok; ok = mov.move_next()) { const TString& codcaus = mov.get(MOV_CODCAUS).as_string(); if (chiusure.is_key(codcaus)) { const TDate datacomp = mov.get(MOV_DATACOMP).as_date(); if (datacomp <= presto) { ((TDate&)_chiusura) = datacomp; // Forzatura TTable esc("ESC"); esc.put("CODTAB", codice()); if (esc.read(_isequal, _lock) == NOERR) { esc.put("D3", datacomp); esc.rewrite(); } } break; } } } return _chiusura; } TEsercizi_contabili::TEsercizi_contabili() { } void TEsercizi_contabili::update() { _firm = prefix().get_codditta(); _esercizi.destroy(); TTable tab_esc("ESC"); for (int err = tab_esc.first(); err == NOERR; err = tab_esc.next()) { TEsercizio* e = new TEsercizio(tab_esc.curr()); _esercizi.add(e); } _esercizi.sort(); } void TEsercizi_contabili::check() { if (_firm != prefix().get_codditta()) update(); } int TEsercizi_contabili::date2index(const TDate& d) const { int i = -1; if (d.ok()) { check(); for (i = items()-1; i >= 0; i--) { const TEsercizio& e = esc(i); if (d >= e.inizio() && d <= e.fine()) break; } } return i; } int TEsercizi_contabili::esc2index(int codice) const { int i = -1; if (codice > 0) { check(); for (i = items()-1; i >= 0; i--) { const TEsercizio& e = esc(i); if (codice == e.codice()) break; } } return i; } int TEsercizi_contabili::date2esc(const TDate& d) const { const int i = date2index(d); return i >= 0 ? esc(i).codice() : 0; } int TEsercizi_contabili::date2prevesc(const TDate& d) const { const int i = date2index(d); return i > 0 ? esc(i - 1).codice() : 0; } int TEsercizi_contabili::date2nextesc(const TDate& d) const { const int i = date2index(d); return i >= 0 && i < items()-1 ? esc(i+1).codice() : 0; } int TEsercizi_contabili::first() const { check(); return items() ? esc(0).codice() : 0; } int TEsercizi_contabili::last() const { check(); return items() ? esc(items()-1).codice() : 0; } // Certified 99% int TEsercizi_contabili::last_mag() const { check(); int i; for (i = items()-1; i >= 0; i--) { const TEsercizio& e = esc(i); if (e.chiusura_mag().ok()) break; } return esc(i+1).codice(); } int TEsercizi_contabili::pred(int codice) const { const int i = esc2index(codice); return i > 0 ? esc(i-1).codice() : 0; } int TEsercizi_contabili::next(int anno) const { const int i = esc2index(anno); return i < items()-1 ? esc(i+1).codice() : 0; } bool TEsercizi_contabili::exist(int codice) const { const int i = esc2index(codice); return i >= 0; } const TEsercizio& TEsercizi_contabili::esercizio(int codice) const { int i = esc2index(codice); if (i < 0 && codice > 0) { error_box(FR("Attenzione! E' necessario aprire l'esercizio %d"), codice); const int last_index = items()-1; if (last_index >= 0) { TRectype rec(LF_TAB); rec.settab("ESC"); const TEsercizio& last = esc(last_index); const int last_code = last.codice(); for (int k = last_code+1; k <= codice; k++) { rec.put("CODTAB", k); TDate ini = last.inizio(); ini.set_year(ini.year()+k-last_code); TDate fin = last.fine(); fin.set_year(fin.year()+k-last_code); rec.put("D0", ini); rec.put("D1", fin); _esercizi.add(new TEsercizio(rec)); } } else { if (codice > 2000) { TRectype rec(LF_TAB); rec.settab("ESC"); rec.put("CODTAB", codice); rec.put("D0", TDate(1,1,codice)); rec.put("D1", TDate(31,12,codice)); _esercizi.add(new TEsercizio(rec)); } } i = esc2index(codice); // Dovrei ritrovare l'ultimo } return esc(i); } bool TEsercizi_contabili::code2range(int codice, TDate& dal, TDate& al) const { bool ok = exist(codice); if (ok) { const TEsercizio& e = esercizio(codice); dal = e.inizio(); al = e.fine(); } else { const int primo_esercizio = first(); const int ultimo_esercizio = last(); if (codice < primo_esercizio) { const TEsercizio& e = esercizio(primo_esercizio); dal = e.inizio(); al = e.fine(); dal.addyear(primo_esercizio - codice); al.addyear(primo_esercizio - codice); ok = true; } if (codice > ultimo_esercizio) { const TEsercizio& e = esercizio(ultimo_esercizio); dal = e.inizio(); al = e.fine(); dal.addyear(codice - ultimo_esercizio); al.addyear(codice - ultimo_esercizio); ok = true; } if (!ok) { if (codice > 1900) { dal = TDate(1, 1, codice); al = TDate(31, 12, codice); ok = true; } else dal = al = TDate(); } } return ok; } TEsercizi_contabili& esercizi() { HIDDEN TEsercizi_contabili __esercizi; return __esercizi; } ///////////////////////////////////////////////////////// // Simpatici metodi jolly ///////////////////////////////////////////////////////// const char* iva2name(TipoIVA iva) { const char* i; switch(iva) { case nessuna_iva: i = TR("Nessuna IVA"); break; case iva_acquisti: i = TR("IVA Acquisti"); break; case iva_vendite: i = TR("IVA Vendite"); break; case iva_generica: i = TR("IVA Generica"); break; default: i = TR("IVA ERRATA!"); break; } return i; } const TString& cap2comune(const TString& cap, const TString& denom) { TString80 up_denom = denom; up_denom.upper(); TString4 codone; if (cap.len() == 5 && up_denom.full()) { TString8 cappone = cap; if (cappone[2] == '1') //e' un capoluogo di provincia cappone.overwrite("00", 3, 2); TRelation relcom(LF_COMUNI); TRectype& comrec = relcom.curr(); comrec.put(COM_CAPCOM, cappone); TCursor comuni (&relcom, "", 3, &comrec, &comrec); const TRecnotype items = comuni.items(); comuni.freeze(); double cmp = 0.69; for (comuni = 0L; comuni.pos() < items; ++comuni) { TString80 denominazione = comrec.get(COM_DENCOM); denominazione.upper(); const double fc = xvt_str_fuzzy_compare (up_denom, denominazione); if (fc > cmp) { codone = comrec.get(COM_COM); cmp = fc; } } } if (codone.blank() && denom.full()) { TLocalisamfile comuni(LF_COMUNI); comuni.setkey(2); comuni.put(COM_DENCOM, denom); if (comuni.read() == NOERR) codone = comuni.get(COM_COM); else { double cmp = 0.9; comuni.zero(); const TString4 pref = up_denom.left(4); comuni.put(COM_DENCOM, pref); for (int err = comuni.read(_isgteq); err == NOERR; err = comuni.next()) { TString80 denominazione = comuni.get(COM_DENCOM); denominazione.upper(); if (!denominazione.starts_with(pref)) break; const double fc = xvt_str_fuzzy_compare(up_denom, denominazione); if (fc > cmp) { cmp = fc; codone = comuni.get(COM_COM); } } } } return codone.full() ? (get_tmp_string() = codone) : EMPTY_STRING; } /////////////////////////////////////////////////////////// // Registro /////////////////////////////////////////////////////////// TRegistro::TRegistro(const char* cod, int year) : _rec(LF_TAB), _att(LF_ATTIV) { read(cod, year); } TRegistro::TRegistro(const TRegistro & reg) : _rec(LF_TAB), _att(LF_ATTIV) { const int year = atoi(reg._rec.get("CODTAB").sleft(4)); const TString8 cod = reg._rec.get("CODTAB").smid(4); read(cod, year); } bool TRegistro::read(const char* cod, int year) { if (year <= 0) { const TDate oggi(TODAY); year = oggi.year(); } if (cod == nullptr) cod = ""; TString8 chiave; chiave.format("%04d%s", year, cod); _rec = cache().get("REG", chiave); read_att(); return !_rec.empty(); } bool TRegistro::force_read(const char* cod, int year) { TString8 chiave; chiave.format("%04d%s", year, cod); cache().discard("REG", chiave); return read(cod, year); } bool TRegistro::reread() { if (ok()) { const TString8 n(name()); const int y = year(); return read(n, y); } return false; } int TRegistro::year() const { const TString& anno = _rec.get("CODTAB").left(4); return atoi(anno); } const TString& TRegistro::name() const { return _rec.get("CODTAB").mid(4); } TRegistro& TRegistro::operator =(const TRegistro& r) { _rec = r._rec; _att = r._att; _prorata = r._prorata; return *this; } int TRegistro::tipo() const { const int t = _rec.get_int("I0"); return t; } bool TRegistro::corrispettivi() const { const bool c = _rec.get_bool("B0"); return c; } TipoIVA TRegistro::iva() const { TipoIVA i = (TipoIVA)tipo(); switch (i) { case nessuna_iva: case iva_vendite: case iva_acquisti: break; case libro_giornale: i = nessuna_iva; break; default: error_box(FR("Il registro '%s' non e' un registro IVA o contabile: tipo %d"), (const char*)name(), i); i = nessuna_iva; break; } return i; } bool TRegistro::read_att() { TString16 chiave; chiave << prefix().get_codditta() << '|' << attivita(); _att = cache().get(LF_ATTIV, chiave); // Ditta - Anno - Attivitā - Tipo Attivitā (fissata a 1) chiave.format("%05ld", prefix().get_codditta()); chiave << year(); // non fare << year() << attivita() chiave << attivita() << "1"; _prorata.destroy(); const TRectype& pla = cache().get("%PLA", chiave); if (!pla.empty()) { chiave.format("%d", year()); _prorata.add(chiave, pla.get_real("R8")); _att.put("TIPOATT", pla.get("S7")); // Aggiorna tipo attivitā } return !_att.empty(); } bool TRegistro::agenzia_viaggi() const { return _att.get_bool("REG74TER") && (iva() == iva_vendite); } const TString& TRegistro::tipo_attivita() const { return _att.get("TIPOATT"); } real* TRegistro::read_prorata(int anno) const { TString16 chiave; // Ditta - Anno - Attivitā - Tipo Attivitā (fissata a 1) chiave.format("%05ld", prefix().get_codditta()); chiave << anno << attivita() << "1"; real* prorata = nullptr; const TRectype& pla = cache().get("%PLA", chiave); if (!pla.empty()) prorata = new real(pla.get("R8")); return prorata; } real TRegistro::prorata(int annodoc) { const int annoiva = year(); if (annodoc <= 1900) annodoc = annoiva; // Test per anno documento non specificato const int annopro = annoiva >= 1998 && annodoc < annoiva ? annodoc+1 : annoiva; TString16 chiave; chiave << annopro; real* pr = (real*)_prorata.objptr(chiave); if (pr == nullptr) { pr = read_prorata(annopro); if (pr == nullptr && annopro != annoiva) pr = read_prorata(annoiva); if (pr == nullptr) pr = new real(ZERO); _prorata.add(chiave, pr, true); } return *pr; } void TRegistro::set_prorata(int annodoc, const real& pro) { const int annoiva = year(); if (annodoc <= 2000) annodoc = annoiva; // Test per anno documento non specificato const int annopro = annodoc < annoiva ? annodoc+1 : annoiva; TString4 chiave; chiave << annopro; _prorata.add(chiave, pro, true); } // Certified 99% bool TRegistro::update(long protiva, const TDate& datareg) { bool updated = true; if (protiva > _rec.get_long("I5")) { _rec.put("I5", protiva); updated = false; } if (datareg > _rec.get_date("D2")) { _rec.put("D2", datareg); updated = false; } if (!updated) { TTable reg("REG"); updated = reg.rewrite(_rec) == NOERR; cache().discard("REG", _rec.get("CODTAB")); // Forza rilettura registro in cache } return updated; } /////////////////////////////////////////////////////////// // Libro giornale /////////////////////////////////////////////////////////// // Legge il libro giornale dell'anno specificato bool TLibro_giornale::read(int y) { bool found = false; if (y <= 0) { TEsercizi_contabili esc; const int lastes = esc.last(); if (lastes > 0) y = esc[lastes].inizio().year(); else y = TDate(TODAY).year(); } TString4 anno; anno.format("%04d", y); TTable reg("REG"); reg.put("CODTAB", anno); // Cerca il primo registro dell'anno for (int err = reg.read(_isgteq); err == NOERR; err = reg.next()) { if (reg.get("CODTAB").compare(anno, 4) != 0) break; // Sono arrivato all'anno dopo if (reg.get_int("I0") == libro_giornale) { found = true; break; } } if (!found) reg.zero(); // Memorizza record (anche vuoto) _rec = reg.curr(); return found; } TLibro_giornale::TLibro_giornale(int y) { read(y); } /////////////////////////////////////////////////////////// // Codice IVA /////////////////////////////////////////////////////////// TCodiceIVA::TCodiceIVA(const char* cod) : TRectype(LF_TABCOM) { read(cod); } int TCodiceIVA::tipo_indetraibilita() const { int tipo = 0; const TString& codind = indetraibilita(); // Codice indetraibilitā alfanumerico (ex. 1, 3, 9) if (codind.full()) { const TRectype& det = cache().get("%DET", codind); if (det.empty()) tipo = atoi(codind); else tipo = det.get_int("I0"); } return tipo; // Tipo indetraibilitā: 1,3,9 } bool TCodiceIVA::read(const char* cod) { if (cod && *cod) *this = cache().get("%IVA", cod); else zero(); return !empty(); } void TCodiceIVA::round(real& n, int ndec, const char* codval) const { switch (ndec) { case AUTO_DECIMALS : ndec = (codval && *codval) ? TExchange(codval).decimals(false) : 2; break; case AUTO_PRICES_DECIMALS: ndec = TExchange(codval).decimals(true); break; default : break; } if (ndec < 10) n.round(ndec); } real TCodiceIVA::imposta(const real& imponibile, int ndec, const char* codval) const { real iva = imponibile * percentuale() / CENTO; round(iva, ndec, codval); return iva; } real TCodiceIVA::scorpora(real& lordo, int ndec, const char* codval) const { round(lordo, ndec, codval); // Arrotondo importo lordo real imponibile = lordo * CENTO / (CENTO + percentuale()); round(imponibile, ndec, codval); // Arrotondo importo netto const real iva = lordo - imponibile; lordo = imponibile; // lordo č un reference da aggiornare con l'imponibile! return iva; } real TCodiceIVA::lordo(const real& imponibile, int ndec, const char* codval) const { return imponibile + imposta(imponibile, ndec, codval); } /* bool TCodiceIVA::reverse_charge() const { const int rsi = regime_speciale(); return rsi == 13 || rsi == 50 || rsi == 51; // Reverse charge! } bool TCodiceIVA::reverse_charge_pubb() const { const int rsi = regime_speciale(); return rsi == 13 || rsi == 19 || rsi == 50 || rsi == 51; // Reverse charge! con aggiunta dienti pubblici } */ /////////////////////////////////////////////////////////// // TBill /////////////////////////////////////////////////////////// TBill::~TBill() { if (_descrizione) delete _descrizione; } void TBill::set_description(const char* d) { if (_descrizione || (d && *d)) { if (_descrizione) *_descrizione = d; else _descrizione = new TString(d); } } // Certified 90% const TBill& TBill::get(TToken_string& s, int from, int mode) { const char* first = s.get(from); if (mode & 0x1) { _tipo = first ? char(toupper(*first)) : ' '; first = s.get(); } else _tipo = ' '; if (strchr(" CF", _tipo) == nullptr) { #ifdef DBG error_box(FR("Tipo conto errato: '%c'"), _tipo); #endif _tipo = ' '; } _gruppo = first ? atoi(first) : 0; _conto = s.get_int(); _sottoconto = s.get_long(); if (mode & 0x2) set_description(s.get()); _tipo_cr = -1; _sezione = ' '; return *this; } const TBill& TBill::copy(const TBill& bill) { _tipo = bill._tipo; _gruppo = bill._gruppo; _conto = bill._conto; _sottoconto = bill._sottoconto; set_description(bill.descrizione()); _tipo_cr = bill._tipo_cr; _sospeso = bill._sospeso; _sezione = bill._sezione; return *this; } // Certified 100% const TBill& TBill::set(int g, int c, long s, char t, const char* d, int r) { _tipo = (t > ' ') ? char(toupper(t)) : ' '; _gruppo = g; _conto = c; _sottoconto = s; set_description(d); _tipo_cr = r; return *this; } const TBill& TBill::add_to(TToken_string& ts, int from, int mode) { if (mode & 0x4) { const int cr = tipo_cr(); if (cr > 0) ts.add(cr, from++); else ts.add(" ", from++); } if (mode & 0x1) ts.add(_tipo, from++); if (_gruppo > 0) ts.add(_gruppo, from++); else ts.add(" ", from++); if (_conto > 0) ts.add(_conto, from++); else ts.add(" ", from++); if (_sottoconto > 0L) ts.add(_sottoconto, from++); else ts.add(" ", from++); if (mode & 0x2) ts.add(descrizione(), from++); return *this; } const char* TBill::field_name(int n, const TRectype& r, bool contro) const { CHECKD(n >= 0 && n <= 3, "Invalid bill field ", n); if (contro) { CHECKD(r.num() == LF_RMOV || r.num() == LF_PAGSCA, "Record non valido per contropartita: ", r.num()); switch(n) { case 0: return RMV_GRUPPOC; break; case 1: return RMV_CONTOC; break; case 2: return RMV_SOTTOCONTOC; break; default:return RMV_TIPOCC; break; } } else { switch(n) { case 0: return RMV_GRUPPO; break; case 1: return RMV_CONTO; break; case 2: if (r.num() == LF_CLIFO) return CLI_CODCF; else return RMV_SOTTOCONTO; break; default: switch(r.num()) { case LF_CLIFO : return CLI_TIPOCF; break; case LF_RCAUSALI: return RCA_TIPOCF; break; default : return RMV_TIPOC; break; } break; } } return ""; } void TBill::put(TRectype& r, bool c) const { r.put(field_name(0, r, c), gruppo()); r.put(field_name(1, r, c), conto()); r.put(field_name(2, r, c), sottoconto()); r.put(field_name(3, r, c), tipo()); } bool TBill::get(const TRectype& r, bool c) { char t = ' '; if (r.type(field_name(3, r, c)) != _nullfld) t = r.get_char(field_name(3, r, c)); set(r.get_int(field_name(0, r, c)), r.get_int(field_name(1, r, c)), r.get_long(field_name(2, r, c)), t); set_description(nullptr); _tipo_cr = -1; _sezione = ' '; if (r.num() == LF_RMOVIVA) tipo_cr(r.get_int(RMI_TIPOCR)); return ok(); } void TBill::set(TMask& m, short g, short c, short s, short t, short d) const { if (g > 0) m.set(g, gruppo()); if (c > 0) m.set(c, conto()); if (s > 0) m.set(s, sottoconto()); if (t > 0) { char typ[2] = { tipo(), '\0' }; m.set(t, typ); } if (d > 0) m.set(d, descrizione()); } void TBill::get(const TMask& m, short g, short c, short s, short t, short d) { const int gr = m.get_int(g); const int co = m.get_int(c); const long so = s > 0 ? m.get_long(s) : 0L; char ti = ' '; if (t) ti = m.get(t)[0]; TString80 de; if (d) de = m.get(d); set(gr, co, so, ti, de); } // Certified 100% bool TBill::ok() const { return _gruppo != 0 && _conto != 0 && _sottoconto != 0L; } // Certified 99% int TBill::compare(const TSortable& s) const { CHECK(class_name()==s.class_name(), "Can't compare TBill with TObject"); const TBill& c = (const TBill&)s; int res = _gruppo - c._gruppo; if (res) return res; res = _conto - c._conto; if (res) return res; const long lres = _sottoconto - c._sottoconto; if (lres < 0L) res = -1; else if (lres > 0L) res = +1; return res; } // Certified 95% bool TBill::find() { bool ok = false; if ((_tipo != 'C' && _tipo != 'F') || _sottoconto == 0L) { TRectype pcon(LF_PCON); ok = read(pcon); if (!ok && _sottoconto != 0L) { const long sotto = _sottoconto; _sottoconto = 0L; if (read(pcon)) _tipo = char(toupper(pcon.get_char(PCN_TMCF))); _sottoconto = sotto; } } if ((_tipo == 'C' || _tipo == 'F') && _sottoconto != 0L) { TString16 key; key.format("%c|%ld", _tipo, _sottoconto); const TRectype& clifo = cache().get(LF_CLIFO, key); ok = !clifo.empty(); if (ok) { set_description(clifo.get(CLI_RAGSOC)); if (_tipo_cr < 0) { _tipo_cr = 0; _sezione = ' '; } _sospeso = clifo.get_bool(CLI_SOSPESO); const char tipoa = clifo.get_char(CLI_TIPOPERS); if (tipoa == 'F') // Se persona fisica allora aggiusta la ragione sociale { TString nome(descrizione().mid(30)); if (nome.full()) { _descrizione->cut(30); _descrizione->trim(); nome.trim(); *_descrizione << ' ' << nome; } } if (_gruppo == 0 || _conto == 0) { _gruppo = clifo.get_int(CLI_GRUPPO); _conto = clifo.get_int(CLI_CONTO); } } } return ok; } bool TBill::read(TRectype &r) { bool ok = false; if (tipo() <= ' ' || sottoconto() <= 0) { const char* key = string(); const TRectype& pcon = cache().get(LF_PCON, key); if (!pcon.empty()) { r = pcon; ok = true; } } if (ok) { _tipo_cr = r.get_int(PCN_TIPOSPRIC); _sezione = r.get_char(PCN_SEZSALDI); set_description(r.get(PCN_DESCR)); _sospeso = r.get_bool(PCN_SOSPESO); } else r.zero(); return ok; } int TBill::tipo_att() { int tipo_att = 1; if (tipo() <= ' ' && ok()) { TBill bill(gruppo(), conto()); TRectype rec(LF_PCON); bill.read(rec); const TIndbil ib = (TIndbil)rec.get_int(PCN_INDBIL); if (ib == ib_passivita || ib == ib_ricavi) { read(rec); const int ricser = rec.get_int(PCN_RICSER); // 0 = Altre attivita 1 = Servizi tipo_att = (ricser == 1) ? 1 : 2; } } return tipo_att; } // Certified 99% const TString& TBill::descrizione() const { TBill& myself = (TBill&)*this; // Se il conto e' valido (c'e' almeno il gruppo) cerca la sua descrizione su file if ((_descrizione == nullptr || _descrizione->blank()) && (gruppo() != 0 || (tipo() > ' ' && codclifo()>0))) { if (!myself.find()) myself.set_description(TR("Sconosciuto")); } return _descrizione ? *_descrizione : (const TString&) EMPTY_STRING; } int TBill::tipo_cr() const { if (_tipo_cr < 0) { TBill& myself = (TBill&)*this; myself.find(); } return _tipo_cr; } int TBill::indicatore_bilancio() const { TString8 str; str.format("%d|%d", gruppo(), conto()); const int ib = atoi(cache().get(LF_PCON, str, PCN_INDBIL)); if (ib <= 0) { TString msg = str; msg.replace('|', '.'); msg.insert(TR("Impossibile stabilire l'indicatore di bilancio del conto ")); NFCHECK(msg); } return ib; } bool TBill::sospeso() const { if (_tipo_cr < 0) tipo_cr(); // trick to load _sospeso return _sospeso; } char TBill::sezione() const { if (_sezione == ' ') tipo_cr(); // trick to load _sezione return _sezione; } // Certified 100% const char* TBill::string(int mode) const { TString& s = get_tmp_string(); if (mode & 0x8) { if (_sottoconto != 0) s.format("%03d%03d%06ld", _gruppo, _conto, _sottoconto); else if (_conto != 0) s.format("%03d%03d", _gruppo, _conto); else if (_gruppo != 0) s.format("%03d", _gruppo); return s; } if (mode & 0x4) { const int cr = tipo_cr(); if (cr > 0) s << cr << '|'; else s << " |"; } if (mode & 0x1) s << _tipo << '|'; if (_gruppo > 0) s << _gruppo << '|'; else s << " |"; if (_conto > 0) s << _conto << '|'; else s << " |"; if (_sottoconto > 0L) s << _sottoconto; else s << ' '; if (mode & 0x2) s << '|' << descrizione(); return s; } bool TBill::required_cdc() const { TString16 key; for (int i = 2; i >= 0; i--) { key.format("%d|%d|%ld", gruppo(), i > 0 ? conto() : 0, i > 1 ? sottoconto() : 0); const TRectype& sottoc = cache().get(LF_PCON, key); if (sottoc.get_bool(PCN_CMSNEEDED)) return true; } return false; } bool TBill::default_cdc(TString& cdc, TString& fas) const { bool ok = tipo() <= ' ' && sottoconto() > 0; if (ok) { TString16 key; for (int i = 2; i >= 0; i--) { key.format("%d|%d|%ld", gruppo(), i > 0 ? conto() : 0, i > 1 ? sottoconto() : 0); const TRectype& pcon = cache().get(LF_PCON, key); if (!pcon.empty()) { cdc = pcon.get(PCN_CODCMS); fas = pcon.get(PCN_FASCMS); if (cdc.not_empty() || fas.not_empty()) break; } } } return ok && (cdc.not_empty() || fas.not_empty()); } bool TBill::is_analitico() const { TString16 key; for (int i = 2; i >= 0; i--) { key.format("%d|%d|%ld", gruppo(), i > 0 ? conto() : 0, i > 1 ? sottoconto() : 0); const TRectype& picone = cache().get(LF_PCON, key); if (picone.get_bool(PCN_ANALITICA)) return true; } return false; } const char* num2str(const TString& s) { TString& str = get_tmp_string(20); str = s; str.trim(); if (str.len() > 2) { str = s.left(2); const int sub = atoi(s.mid(2, 2)); switch (sub) { case 2: str << " bis"; break; case 3: str << " ter";break; case 4: str << " quater"; break; case 5: str << " quinquies"; break; case 6: str << " sexies"; break; default: break; } const TString& sotsub = s.mid(4); if (sotsub.full()) str << ' ' << sotsub; } return (const char*)str; } /////////////////////////////////////////////////////////// // Movimento di prima nota /////////////////////////////////////////////////////////// TMovimentoPN::TMovimentoPN() : TRelation(LF_MOV), _cg(LF_RMOV, RMV_NUMRIG), _iva(LF_RMOVIVA, RMI_NUMRIG), _old_iva(LF_RMOVIVA, RMI_NUMRIG) { add(LF_RMOV, "NUMREG=NUMREG"); add(LF_RMOVIVA, "NUMREG=NUMREG"); } void TMovimentoPN::destroy_rows(long num) { _cg.destroy_rows(); _cg.renum_key(RMV_NUMREG, num); _iva.destroy_rows(); _iva.renum_key(RMI_NUMREG, num); } TRectype& TMovimentoPN::cg(int i) { return _cg.row(i >= 0 ? i + 1 : -1, true); } TRectype& TMovimentoPN::iva(int i) { return _iva.row(i >= 0 ? i + 1 : -1, true); } void TMovimentoPN::destroy_cg_row(int i) { if (i < 0) _cg.destroy_rows(); else _cg.destroy_row(i + 1, true); } void TMovimentoPN::destroy_iva_row(int i) { if (i < 0) _iva.destroy_rows(); else _iva.destroy_row(i + 1, true); } void TMovimentoPN::update_rev_charge() { const int year = lfile().get_int(MOV_ANNOIVA); const TString & codcaus = lfile().get(MOV_CODCAUS); const TCausale & caus = cached_causale(codcaus, year); const TipoIVA t = caus.iva(); if (t == iva_acquisti) { const bool rev_charge = caus.reverse_charge_pubb(); if (rev_charge) { int rows = _iva.rows(); real imp_revcharge; bool has_revcharge = false; for (int i = _iva.first_row(); !has_revcharge && i <= rows; i = _iva.succ_row(i)) { has_revcharge |= _iva[i].get_bool(RMI_REVCHARGE); imp_revcharge += _iva[i].get_real(RMI_IMPOSTA); } if (!has_revcharge) { TRectype & h = head(); if (h.get_real(MOV_REVCHARGE) <= ZERO) { h.put(MOV_REVCHARGE, imp_revcharge); h.sub(MOV_RITFIS, imp_revcharge); if (h.get_real(MOV_RITFIS) < ZERO) h.zero(MOV_RITFIS); } for (int i = _iva.first_row(); i <= rows; i = _iva.succ_row(i)) _iva[i].put(RMI_REVCHARGE, true); } } } } int TMovimentoPN::read_mov_rows() { const TRectype& mov = curr(); const long numreg = mov.get_long(MOV_NUMREG); TRectype* cgfilter = new TRectype(LF_RMOV); cgfilter->put(RMV_NUMREG, numreg); _cg.read(cgfilter); TRectype* ivafilter = new TRectype(LF_RMOVIVA); ivafilter->put(RMI_NUMREG, numreg); _iva.read(ivafilter); update_rev_charge(); _old_iva = _iva; /* if (_cg.rows() > 0 && _iva.rows() > 0 && cg(0).get_char(RMV_ROWTYPE) != 'T') adjust_row_types(); */ return _cg.rows(); } int TMovimentoPN::read(TIsamop op, TReclock lockop) { const int err = TRelation::read(op, lockop); if (err == NOERR) { _olddataliq = file().get(MOV_DATAREG); // Memorizza data liquidazione const int meseliq = file().get_int(MOV_MESELIQ); if (meseliq > 0 && meseliq != _olddataliq.month()) { _olddataliq.set_day(1); // Evita problemi coi mesi corti! _olddataliq.set_month(meseliq); } read_mov_rows(); // Riempie i due record array } return err; } char TMovimentoPN::frequenza_versamenti(int year) const { static int last_year = 0; static long last_firm = 0; static char last_freq = ' '; const long firm = prefix().get_codditta(); if (firm != last_firm || year != last_year) { TString16 key; key.format("%05ld%d", firm, year); TTable lia("%LIA"); lia.put("CODTAB", key); if (lia.read() != NOERR) { TLocalisamfile nditte(LF_NDITTE); nditte.put("CODDITTA", firm); nditte.read(); last_freq = nditte.get_char("FREQVIVA"); } else last_freq = lia.get_char("S7"); if (last_freq != 'M' && last_freq != 'T') { error_box(FR("La frequenza versamenti IVA per la ditta %ld\n" "non e' valida: la si considera mensile."), firm); last_freq = 'M'; } last_firm = firm; last_year = year; } return last_freq; } int TMovimentoPN::date2liq(const TDate& data) const { const int anno = data.year(); int mese = data.month(); if (frequenza_versamenti(anno) == 'T') mese += 2 - ((mese - 1) % 3); return mese; } bool TMovimentoPN::controlla_liquidazione(const TDate& data, TRegistro& registro, bool reset) const { bool calcolata = false; const int anno = data.year(); const int mese = date2liq(data); // Chiave di LIM: Anno (1-4), Mese (5-6) TString16 key; key.format("%04d%02d", anno, mese); TTable lim("LIM"); lim.setkey(1); lim.put("CODTAB", key); if (lim.read() == NOERR) { calcolata = data.month() <= registro.mese_stampa_ultima_liq(); // Controlla se progressivi ricalcolati (registri) if (reset) { // Resetta i flag di calcolato sulla liquidazione IVA del mese di registrazione lim.zero("B0"); // calcolato lim.rewrite(); } } if (reset) { const bool att_mista = registro.name().empty() ? FALSE : registro.attivita_mista(); const int att = att_mista ? 2 : 1; // Chiave di PLM: Anno (1-4), Cod. Att. (5-9), Tipo att. (10-10), Mese (11-12) TTable plm("PLM"); for (int a = 1; a <= att; a++) { TString16 chiave; TString8 attivita(registro.attivita()); attivita.right_just(5, '0'); TString4 mese; mese.format("%02d", data.month()); chiave << data.year() << attivita << a << mese; plm.put("CODTAB", chiave); if (plm.read() == NOERR) { const bool calcolato = plm.get_bool("B0"); if (calcolato) { plm.zero("B0"); plm.rewrite(); } } } } return calcolata; } int TMovimentoPN::registra(bool re, bool force) { const TRectype& m = curr(); long numreg = m.get_long(MOV_NUMREG); if (numreg <= 0) { if (!re) // Tento di numerare automaticamente in caso di write { TLocalisamfile mov(LF_MOV); // Non sposto il file principale della relazione! numreg = 1; if (mov.last() == NOERR) numreg += mov.get_long(MOV_NUMREG); curr().put(MOV_NUMREG, numreg); } else return _isnocurkey; } int err = re ? TRelation::rewrite(force) : TRelation::write(force); if (err != NOERR) return err; _cg.renum_key(MOV_NUMREG, numreg); err = _cg.write(re); if (err != NOERR) return err; const int annoiva = m.get_int(MOV_ANNOIVA); const TString4 reg(m.get(MOV_REG)); TRegistro registro(reg, annoiva); const bool att_mista = reg.empty() ? false : registro.attivita_mista(); update_rev_charge(); for (int i = 0; i < iva_items(); i++) { TRectype& r = iva(i); int tipoatt = 1; if (att_mista) { const char tipo = r.get_char(RMI_TIPOC); if (tipo <= ' ') { TBill c(r.get_int(RMI_GRUPPO), r.get_int(RMI_CONTO), r.get_long(RMI_SOTTOCONTO)); tipoatt = c.tipo_att(); } } r.put(RMI_TIPOATT, tipoatt); const TString & indetr = r.get(RMI_TIPODET); if (indetr.full()) { const TRectype& det = cache().get("%DET", indetr); if (!det.empty() && !det.get_bool("FPC")) { TTable tab("%DET"); tab.curr() = det; tab.curr().put("FPC", "X"); tab.rewrite(); } } } _iva.renum_key(MOV_NUMREG, numreg); err = _iva.write(re); if (err != NOERR) return err; // Aggiorna data registrazione e protocollo IVA sul registro const TDate datareg(m.get(MOV_DATAREG)); if (reg.full()) { const long protiva = m.get_long(MOV_PROTIVA); const long uprotiva = m.get_long(MOV_UPROTIVA); const long max = protiva > uprotiva ? protiva : uprotiva; registro.update(max, datareg); } // Aggiorna flags di ricalcolo liquidazione TDate dataliq(datareg); const int mese_liq = m.get_int(MOV_MESELIQ); if (mese_liq > 0 && mese_liq != dataliq.month()) { dataliq.set_day(1); // Evita problemi coi mesi corti! dataliq.set_month(mese_liq); } bool reset = !re; if (reg.full()) { reset = (dataliq.month() != _olddataliq.month() || _old_iva != _iva); if (dataliq.month() != _olddataliq.month()) controlla_liquidazione(_olddataliq, registro, true); } else { const TCausale causale(m.get(MOV_CODCAUS), annoiva); if (causale.saldaconto(datareg) && causale.tipomov() != tm_fattura) { TPartite_array partarray; partarray.add_numreg(numreg); const int npart = partarray.items(); for (TPartita * part = partarray.first(); !reset && part != nullptr; part = partarray.next()) { const int nrpart = part->last(); for (int r = part->prima_fattura(); !reset && r >= 0 && r <= nrpart; r = part->succ(r)) { TRiga_partite & rp = part->riga(r); if (rp.is_fattura()) { const TRectype & mov = cache().get(LF_MOV, rp.get(PART_NREG)); reset = mov.get_bool(MOV_LIQDIFF) || mov.get_bool(MOV_IVAXCASSA); } } } } } if (reset) controlla_liquidazione(dataliq, registro, reset); return err; } int TMovimentoPN::write(bool force) { return registra(FALSE, force); } int TMovimentoPN::rewrite(bool force) { return registra(true, force); } int TMovimentoPN::remove() { int err = _cg.remove(); if (err == NOERR) err = _iva.remove(); if (err == NOERR) err = TRelation::remove(); if (err == NOERR) { const TRectype& m = curr(); const TString4 reg(m.get(MOV_REG)); const int annoiva = m.get_int(MOV_ANNOIVA); TRegistro registro(reg, annoiva); controlla_liquidazione(_olddataliq, registro, true); } return err; } /////////////////////////////////////////////////////////// // Aggiustamento movimenti rovinati o convertiti male /////////////////////////////////////////////////////////// bool TConti_array::add(const TBill& conto, const real& importo) { const char* key = conto.string(); real* imp = (real*)objptr(key); if (imp == nullptr) TAssoc_array::add(key, importo); else *imp += importo; return imp != nullptr; } real TConti_array::importo(const TBill& conto) { const char* key = conto.string(); const real* imp = (real*)objptr(key); return imp ? *imp : ZERO; } bool TConti_array::remove(const TBill& conto) { const char* key = conto.string(); return TAssoc_array::remove(key); } bool TConti_array::add_iva(bool det, const real& importo) { real* imp = nullptr; if (!importo.is_zero()) { const char* const key = det ? "D" : "N"; imp = (real*)objptr(key); if (imp == nullptr) TAssoc_array::add(key, importo); else *imp += importo; } return imp != nullptr; } real TConti_array::importo_iva(bool det) { const char* const key = det ? "D" : "N"; const real* imp = (real*)objptr(key); return imp ? *imp : ZERO; } bool TConti_array::remove_iva(bool det) { const char* const key = det ? "D" : "N"; return TAssoc_array::remove(key); } real TMovimentoPN::indetraibile_al(const TString& codind, const TCausale& caus, int annodoc) const { int tipodet = 0; return ::indetraibile_al(codind, caus, annodoc, tipodet); } int TMovimentoPN::analizza_riga_IVA(const real& imptot, const real& ivatot, const TCausale& caus, int annodoc, const TString& codiva, const TString& codind, real& imp_det, real& iva_det, real& imp_ind, real& iva_ind) const { const real perc_ind = indetraibile_al(codind, caus, annodoc); const bool corrispettivo = caus.corrispettivi(); TBill billind; caus.bill(RIGA_IVA_NON_DETRAIBILE, billind); const bool iva_ind_al_costo = !billind.ok(); return analizza_IVA(imptot, ivatot, perc_ind, corrispettivo, iva_ind_al_costo, codiva, imp_det, iva_det, imp_ind, iva_ind); } // Aggiusta i row types se sono andati persi o non sono stati convertiti void TMovimentoPN::adjust_rowtypes() { const TRectype& mov = curr(); const char tipo = mov.get_char(MOV_TIPO); const long codice = mov.get_long(MOV_CODCF); const int annoiva = mov.get_int(MOV_ANNOIVA); const int annodoc = mov.get_date(MOV_DATADOC).year(); const TCausale causale(mov.get(MOV_CODCAUS), annoiva); TConti_array conti; int r; for (r = 0; r < _iva.rows(); r++) { const TRectype& row = iva(r); const TBill bill(row); const real imponibile(row.get(RMI_IMPONIBILE)); const real imposta(row.get(RMI_IMPOSTA)); const TString4 codiva = row.get(RMI_CODIVA); const TString4 codind = row.get(RMI_TIPODET); real imp_det, iva_det, imp_ind, iva_ind; analizza_riga_IVA(imponibile, imposta, causale, annodoc, codiva, codind, imp_det, iva_det, imp_ind, iva_ind); conti.add(bill, imp_det + imp_ind); conti.add_iva(false, iva_ind); conti.add_iva(true, iva_det); } bool totale = FALSE; bool ritfis = mov.get_real(MOV_RITFIS).is_zero(); bool ritsoc = mov.get_real(MOV_RITSOC).is_zero(); bool ivadet = conti.importo_iva(true).is_zero(); bool ivanon = conti.importo_iva(FALSE).is_zero(); for (r = 0; r < _cg.rows(); r++) { TRectype& row = cg(r); const char rt = row.get_char(RMV_ROWTYPE); switch (rt) { case 'F': ritfis = true; break; case 'S': ritsoc = true; break; case 'T': totale = true; break; default: break; } if (rt > ' ') continue; if (!totale && row.get_char(RMV_TIPOC) == tipo && row.get_long(RMV_SOTTOCONTO) == codice) { row.put(RMV_ROWTYPE, 'T'); totale = true; continue; } const real importo(row.get(RMV_IMPORTO)); const TBill bill(row); if (!ritfis && importo == mov.get_real(MOV_RITFIS)) { TBill conto_rit; causale.bill(RIGA_PAG_RITFIS, conto_rit); if (!conto_rit.ok() || conto_rit == bill) { row.put(RMV_ROWTYPE, 'F'); ritfis = true; continue; } } if (!ritsoc && importo == mov.get_real(MOV_RITSOC)) { TBill conto_rit; causale.bill(RIGA_PAG_RITSOC, conto_rit); if (!conto_rit.ok() || conto_rit == bill) { row.put(RMV_ROWTYPE, 'S'); ritsoc = true; continue; } } if (!conti.ok()) continue; // Ho esaurito i conti IVA if (importo == conti.importo(bill)) { row.put(RMV_ROWTYPE, 'I'); conti.remove(bill); continue; } if (!ivadet && importo == conti.importo_iva(true)) { row.put(RMV_ROWTYPE, 'D'); conti.remove_iva(true); continue; } if (!ivanon && importo == conti.importo_iva(FALSE)) { row.put(RMV_ROWTYPE, 'N'); conti.remove_iva(FALSE); continue; } } } TMovimentoPN& TMovimentoPN::get_sum_imponibile_imposta(real& s_imponibili, real& s_imposte) { TRecord_array& iva = iva_rows(); s_imponibili = ZERO; s_imposte = ZERO; for (int i = iva.first_row(); i <= iva.rows(); ++i) { TRectype& r = iva[i]; s_imponibili += r.get_real("IMPONIBILE"); s_imposte += r.get_real("IMPOSTA"); } return *this; }