#include #include #include #include #include "cg2101.h" #include "cg2103.h" /////////////////////////////////////////////////////////// // Movimento di prima nota /////////////////////////////////////////////////////////// TMovimentoPN::TMovimentoPN() : TRelation(LF_MOV), _cg(LF_RMOV, RMV_NUMRIG), _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); } 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) { _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.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'); TString16 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) { int err = re ? TRelation::rewrite(force) : TRelation::write(force); if (err != NOERR) return err; const TRectype& m = curr(); const long numreg = m.get_long(MOV_NUMREG); _cg.renum_key(MOV_NUMREG, numreg); err = _cg.write(re); if (err != NOERR) return err; const int annoiva = m.get_int(MOV_ANNOIVA); const TString reg(m.get(MOV_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(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); } _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.not_empty()) { 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); } controlla_liquidazione(dataliq, registro, TRUE); if (re && dataliq.month() != _olddataliq.month()) controlla_liquidazione(_olddataliq, 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 TString 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 /////////////////////////////////////////////////////////// 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; int r; for (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_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; } } }