#include #include #include #include #include "cg2101.h" #include "cg2103.h" /////////////////////////////////////////////////////////// // Movimento di prima nota /////////////////////////////////////////////////////////// TMovimentoPN::TMovimentoPN() : TRelation(LF_MOV), _cg(LF_RMOV, "NUMRIG"), _iva(LF_RMOVIVA, "NUMRIG") { add(LF_RMOV, "NUMREG=NUMREG"); add(LF_RMOVIVA, "NUMREG=NUMREG"); } void TMovimentoPN::destroy_rows(long num) { _cg.destroy_rows(); _cg.renum_key("NUMREG", num); _iva.destroy_rows(); _iva.renum_key("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); } 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); /* 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) { _olddate = file().get("DATAREG"); // Memorizza data operazione per aggiornare i saldi 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("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.zero("B1"); // progressivi ricalcolati 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; TString16 attivita(registro.attivita()); attivita.right_just(5, '0'); chiave << data.year() << attivita << a << format("%02d", data.month()); 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) { int err = re ? TRelation::rewrite(force) : TRelation::write(force); if (err != NOERR) return err; const TRectype& m = curr(); const long numreg = m.get_long("NUMREG"); if (!re) _cg.renum_key("NUMREG", numreg); err = _cg.write(re); if (err != NOERR) return err; const int annoiva = m.get_int("ANNOIVA"); const TString reg(m.get("REG")); TRegistro registro(reg, annoiva); const bool att_mista = reg.empty() ? FALSE : registro.attivita_mista(); for (int i = 0 ; i < iva_items(); i++) { TRectype& r = iva(i); int tipoatt = 1; if (att_mista) { const char tipo = r.get_char("TIPOC"); if (tipo <= ' ') { TBill c(r.get_int("GRUPPO"), r.get_int("CONTO"), r.get_long("SOTTOCONTO")); tipoatt = c.tipo_att(); } } r.put("TIPOATT", tipoatt); } if (!re) _iva.renum_key("NUMREG", numreg); err = _iva.write(re); if (err != NOERR) return err; // Aggiorna data registrazione e protocollo IVA sul registro const TDate datareg(m.get("DATAREG")); if (reg.not_empty()) { const long protiva = m.get_long("PROTIVA"); const long uprotiva = m.get_long("UPROTIVA"); const long max = protiva > uprotiva ? protiva : uprotiva; registro.update(max, datareg); } // Aggiorna flags di ricalcolo liquidazione controlla_liquidazione(datareg, registro, TRUE); if (re && datareg != _olddate) controlla_liquidazione(_olddate, registro, TRUE); 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 TDate datareg(m.get("DATAREG")); const int annoiva = m.get_int("ANNOIVA"); const TString reg(m.get("REG")); TRegistro registro(reg, annoiva); controlla_liquidazione(datareg, registro, TRUE); } return err; } /////////////////////////////////////////////////////////// // Aggiustamento movimenti rovinati o convertiti male /////////////////////////////////////////////////////////// class TConti_array : private TAssoc_array { public: // TObject virtual bool ok() const { return items() != 0; } public: bool add(const TBill& conto, const real& importo); real importo(const TBill& conto); bool remove(const TBill& conto); bool add_iva(bool det, const real& importo); real importo_iva(bool det); bool remove_iva(bool det); TConti_array() {} virtual ~TConti_array() {} }; bool TConti_array::add(const TBill& conto, const real& importo) { const char* key = conto.string(); real* imp = (real*)objptr(key); if (imp == NULL) TAssoc_array::add(key, importo); else *imp += importo; return imp != NULL; } 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) { const char* const key = det ? "D" : "N"; real* imp = (real*)objptr(key); if (imp == NULL) TAssoc_array::add(key, importo); else *imp += importo; return imp != NULL; } 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); } bool TMovimentoPN::detraibile(const TRectype& row, const TCausale& cau) const { if (cau.iva() == iva_vendite) // Vendite sempre detraibili return TRUE; const int tipo_det = row.get_int(RMI_TIPODET); // Leggi tipo detraibilita if (tipo_det != 0) return FALSE; const int annodoc = curr().get_date(MOV_DATADOC).year(); const bool prorata100 = cau.reg().prorata100(annodoc); return !prorata100; // Se prorata = 100% e' indetraibile } // 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 TCausale causale(mov.get(MOV_CODCAUS), annoiva); TConti_array conti; for (int r = 0; r < _iva.rows(); r++) { const TRectype& row = iva(r); const TBill bill(row); real imponibile(row.get(RMI_IMPONIBILE)); real imposta(row.get(RMI_IMPOSTA)); const bool det = detraibile(row, causale); if (imposta.is_zero() && causale.corrispettivi()) { const TCodiceIVA iva(row.get(RMI_CODIVA)); imposta = iva.scorpora(imponibile); } conti.add(bill, imponibile); conti.add_iva(det, imposta); } 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_RITENUTE_FISCALI, 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_RITENUTE_SOCIALI, 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; } } }