#include "velib05.h" #include #include #include #include "../cg/cglib03.h" #include ///////////////////////////////////////////////////////////// //TDocumentoEsteso ///////////////////////////////////////////////////////////// void TDocumentoEsteso::compile_summary() { const int ndec = decimals(); _sum_filter = 0; _summary_array.destroy(); _summary_table = tabella_iva(); _summary_table.restart(); for (TRiepilogo_iva * ri = (TRiepilogo_iva *) _summary_table.get(); ri != NULL; ri = (TRiepilogo_iva *) _summary_table.get()) { const real imponibile = ri->imponibile(); real imposta = ri->imposta(); if (ndec == 0) { if (imposta < ZERO) imposta.floor(); else imposta.ceil(); } else imposta.round(ndec); ri->imp() = imponibile; ri->imp_spese() = ZERO; ri->iva() = imposta; ri->iva_spese() = ZERO; } // Inizializza l'array di ordine if (_order_array.items() == 0) { TToken_string s; for (int i = 0; i < 32; i++) // ?? _order_array.add(s); } } static int riep_sort(const TSortable& o1, const TSortable& o2, void*) { const TRiepilogo_iva& r1 = (const TRiepilogo_iva&)o1; const TRiepilogo_iva& r2 = (const TRiepilogo_iva&)o2; const real delta = r1.imposta() - r2.imposta(); return delta.sign(); } void TDocumentoEsteso::summary_filter(byte selector) { if (_sum_filter == -1) compile_summary(); // Crea la tabella se deve ancora farlo // se ha selezionato una riga in precedenza deve finire di stamparla // ovvero non seleziona il filtro fino a quando non ha ricevuto una summary_set_next() if (_sum_selected) return; // // Procedimento: // Memorizza in un TString_array tante TToken_string quanti sono i filtri possibili // (al massimo 31 [1+2+4+8+16]). Ogni TToken_string contiene i codici IVA // delle righe di TRiepilogo_iva che soddisfano la condizione di filtro _sum_selected = true; _sum_filter = selector; CHECKD(_sum_filter > 0 && _sum_filter <= 32, "Bad selector ", _sum_filter); TToken_string& codici = _order_array.row(_sum_filter-1); if (codici.blank()) // Se non c'e' nemmeno un codice IVA allora deve effettuare il filtro { // ovvero mette in <> tutti i codici IVA che soddisfano tale filtro // sara' poi la summary_set_next() a selezionare sequenzialmente il giusto codice a seconda del filtro corrente // Scorre sequenzialmente la tabella _summary_table e compone la TToken_string con i codici IVA /* const int items = summary_items(); TRiepilogo_iva* curr = (TRiepilogo_iva *) _summary_table.first_item(); for (int i = 0; i < items && curr != NULL; i++) { if (curr->tipo() & _sum_filter) // se fa parte del filtro selezionato schiaffa il codice nella TToken_string codici.add(curr->cod_iva().codice()); curr = (TRiepilogo_iva*) _summary_table.succ_item(); } */ // Ordina i riepiloghi in ordine descrescente di imposta (Da marzo 2016) TPointer_array ri; FOR_EACH_ASSOC_OBJECT(_summary_table, obj, key, itm) { TRiepilogo_iva* curr = (TRiepilogo_iva*)itm; if (curr->tipo() & _sum_filter) // se fa parte del filtro selezionato schiaffa il codice nella lista ri.add(curr); } ri.sort(riep_sort, NULL); FOR_EACH_ARRAY_ITEM(ri, r, obj) { const TRiepilogo_iva* curr = (const TRiepilogo_iva*)obj; codici.add(curr->cod_iva().codice()); } // Fine ordinamento codici.restart(); summary_set_next(); // setta l'elemento corrente } } void TDocumentoEsteso::summary_reset(bool force) { if (force) { _sum_filter = -1; _sum_selected = false; } FOR_EACH_ARRAY_ROW(_order_array, i, row) row->cut(0); } void TDocumentoEsteso::summary_set_next() { _sum_selected = false; TToken_string& codici = _order_array.row(_sum_filter-1); const TString4 codiva(codici.get()); // Reperisce il prossimo codice nella lista. (son gia' ordinati per codice) if (codiva.full() && _summary_table.is_key(codiva)) { // Estrae da _summary_table i dati relativio al codice corrispondente. const TRiepilogo_iva& riep= (const TRiepilogo_iva&) _summary_table[codiva]; _sum_current = riep; } else { const TRiepilogo_iva i; _sum_current = i; // se non esiste il codice azzera l'elemento corrente (non stampera' nulla) } } const char * TDocumentoEsteso::summary_get(const TString& w) { if (w == "COD") // Ritorna il codice IVA return _sum_current.cod_iva().codice(); else if (w == "IMP") // Ritorna l'imponibile return _sum_current.imp().string(); else if (w == "IVA") // Ritorna l'imposta return _sum_current.iva().string(); else if (w == "ALI") // Ritorna l'aliquota % return _sum_current.cod_iva().percentuale().string(); else if (w == "DES") // Ritorna la descrizione ( se il codice e' regime normale la descr. e' vuota) { if (_sum_current.cod_iva().tipo().not_empty()) return _sum_current.cod_iva().descrizione(); } return ""; } void TDocumentoEsteso::scadenze_recalc() { _scadenze_array.destroy(); _scadenze_current = -1; TRectype& hh = head(); TPagamento& pag = pagamento(); real totspese = spese(); real totimposte = imposta(TRUE); real pagato = hh.get_real(DOC_IMPPAGATO); const bool saldo = hh.get_bool(DOC_ACCSALDO); real totimponibili = totale_doc() - ritenute() - totimposte - totspese; const bool is_in_valuta = in_valuta(); if (is_split_payment()) totimposte = ZERO; if (saldo || pagato > totale_doc()) { totimponibili = ZERO; totimposte = ZERO; totspese = ZERO; } else { TGeneric_distrib d(pagato, decimals()); d.add(totimponibili); d.add(totimposte); d.add(totspese); totimponibili -= d.get(); totimposte -= d.get(); totspese -= d.get(); } if (is_in_valuta) { const real change(cambio()); TCurrency_documento val1(totimponibili, *this); val1.change_to_firm_val(); TCurrency_documento val2(totimposte, *this); val2.change_to_firm_val(); TCurrency_documento val3(totspese, *this); val3.change_to_firm_val(); TString4 codval = valuta(); pag.set_total_valuta(totimponibili, totimposte, totspese, change, val1.get_num(), val2.get_num() ,val3.get_num(), codval); } else pag.set_total(totimponibili, totimposte, totspese); pag.set_rate_auto(); const int numrate = pag.n_rate( ); real rata; for (int i = 0; i< numrate; i++) { rata = pag.importo_rata(i, is_in_valuta); TToken_string t; t.add(pag.data_rata(i)); t.add(rata.string()); _scadenze_array.add(t); } if (_scadenze_array.items() > 0) _scadenze_current++; } const char* TDocumentoEsteso::scadenze_get(const TString& w) { // TString ret; // Pena di morte const char* ret = ""; if (_scadenze_current == -1) // calcola le scadenze e le mette in _scadenze_array scadenze_recalc(); if (_scadenze_current > -1 && _scadenze_current < _scadenze_array.items()) { if (w == "DATA") ret = _scadenze_array.row(_scadenze_current).get(0); // ritorna la data di scadenza if (w == "IMPORTO") ret = _scadenze_array.row(_scadenze_current).get(1); // ritorna l'importo in scadenza } return ret; } void TDocumentoEsteso::scadenze_set_next() { if (_scadenze_current >= 0 && _scadenze_current < _scadenze_array.items() ) _scadenze_current++; } void TDocumentoEsteso::scadenze_reset() { if (_scadenze_current > 0) _scadenze_current = 0; } real TDocumentoEsteso::tot_imponibili(byte selector) { if (!summary_compiled()) compile_summary(); real number = 0.0; const int items = summary_items(); TRiepilogo_iva* curr = (TRiepilogo_iva *) _summary_table.first_item(); for (int i = 0; i < items && curr != NULL; i++) { if (curr->tipo() & selector) // se fa parte del filtro selezionato schiaffa il codice nella TToken_string number += curr->imp(); curr = (TRiepilogo_iva *) _summary_table.succ_item(); } return number; } int TDocumentoEsteso::readat(TBaseisamfile& file, TRecnotype nrec, word lockop) { int err = TDocumento::readat(file, nrec, lockop); dirty_tabella_iva(); summary_reset(true); scadenze_reset(); return err; } TDocumentoEsteso::TDocumentoEsteso(const TRectype& rec) : TDocumento(rec), _sum_filter(-1), _sum_selected(FALSE), _scadenze_current(-1), _conai(NULL), _tic(NULL), _split(NULL) { // Inizializza i parametri di default _parm.qta_lit = 3; _parm.qta_val = 3; } TDocumentoEsteso::TDocumentoEsteso(const TRectype& rec, dec_parm & parm) : TDocumento(rec), _sum_filter(-1), _sum_selected(FALSE), _scadenze_current(-1), _conai(NULL), _tic(NULL), _split(NULL) { _parm = parm; } TDocumentoEsteso::TDocumentoEsteso() : TDocumento(), _sum_filter(-1), _sum_selected(FALSE), _scadenze_current(-1), _conai(NULL), _tic(NULL), _split(NULL) { } TDocumentoEsteso::~TDocumentoEsteso() { if (_conai) delete _conai; if (_tic) delete _tic; if (_split) delete _split; } void TDocumentoEsteso::set_riga_conai() { if (_conai != NULL) { delete _conai; _conai = NULL; } if (physical_rows() > 0) { const bool has_conai = (tipo().add_conai() && clifor().vendite().get_bool(CFV_CONAIASS)); if (has_conai) { _conai = new TRiga_documento(this, "05"); TString conai = ini_get_string(CONFIG_DITTA, "ve", "DESCCONAIASS"); if (conai.blank()) // se la variabile e' vuota ma scritta sull ini non stampa nulla conai = TR("Contributo CONAI assolto"); _conai->put(RDOC_DESCR, conai); } } } void TDocumentoEsteso::set_riga_tic() { if (_tic != NULL) { delete _tic; _tic = NULL; } if (get_int(DOC_ANNO) >= 2013 && is_fattura()) { FOR_EACH_PHYSICAL_RDOC(*this, r, rdoc) if (!rdoc->is_descrizione()) { const TString& cod = rdoc->get(RDOC_CODIVA); if (cod.full() && !rdoc->imponibile().is_zero()) { const TCodiceIVA iva(cod); TString4 tic; tic.format("%04d", iva.get_int("I1")); if (tic != "0000") { _tic = new TRiga_documento(this, "05"); _tic->put(RDOC_DESCR, cache().get("%TIC", tic, "S0")); break; } } } } } bool TDocumentoEsteso::is_split_payment() const { const long numregcg = get_long(DOC_NUMREG); if (numregcg > 0) { const TRectype& mov = cache().get(LF_MOV, numregcg); if (!mov.empty()) return ::is_split_payment(mov); } bool yes = get_int(DOC_ANNO) >= 2015 && clifor().get_bool(CLI_SPLITPAY) && (is_fattura() || is_nota_credito()) && !imposta().is_zero() && ritenute().is_zero(); if (yes) { const TRectype& causale = cache().get(LF_CAUSALI, tipo().causale()); const int rsi = causale.get_int(CAU_REGSPIVA); yes = rsi != 13 && rsi != 50 && rsi != 51; // No reverse charge } return yes; } void TDocumentoEsteso::set_riga_split() { if (_split != NULL) { delete _split; _split = NULL; } if (is_split_payment()) { _split = new TRiga_documento(this, "05"); TString split = esc(ini_get_string(CONFIG_DITTA, "ve", "DESCSPLIT", TR("SCISSIONE DEI PAGAMENTI Art.17-ter D.P.R. 633/72"))); if (split[0] > ' ') split.insert("\n"); _split->set_descr(split); } } int TDocumentoEsteso::rows() const { int n = TDocumento::rows(); if (_conai) n++; if (_tic) n++; if (_split) n++; return n; } TRiga_documento& TDocumentoEsteso::row(int index) { const int n = TDocumento::rows(); if (index > n) { TRiga_documento* extra[4] = { NULL }; int ne = 0; if (_conai) extra[ne++] = _conai; if (_tic ) extra[ne++] = _tic; if (_split) extra[ne++] = _split; return *extra[index-n-1]; } return TDocumento::row(index); }