#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fe0100a.h" #include "../cg/cglib01.h" // Data limite da cui si cominciano a dichiarare anche gli scontrini const TDate data_limite_scontrini(1,7,2011); /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// static const TString& comune_di(const TString& codcom) { if (codcom.blank() || codcom.len() != 4) return EMPTY_STRING; TString8 key; key << " |" << codcom; TString& den = get_tmp_string(); den = cache().get(LF_COMUNI, key, COM_DENCOM); den.cut(40); den.upper(); return den; } static const TString& provincia_di(const TString& codcom) { if (codcom.blank() || codcom.len() != 4) return EMPTY_STRING; TString8 key; key << '|' << codcom; return cache().get(LF_COMUNI, key, COM_PROVCOM); } /////////////////////////////////////////////////////////// // TContratti /////////////////////////////////////////////////////////// const TRectype& contratto(char tipocf, long codcf, const char* codcont) { TString80 key; key.format("%c%6ld%s", tipocf, codcf, codcont); TRectype& c = (TRectype&)cache().get("&CON", key); if (c.empty()) { int primo_anno = c.get_int("I0"); if (primo_anno < 2010) { const TDate inizio = c.get("D0"); primo_anno = inizio.year(); if (primo_anno < 2010) primo_anno = 2010; c.put("I0", primo_anno); } real importo = c.get("R0"); if (importo <= ZERO) { importo = primo_anno > 2010 ? 3000 : 25000; c.put("R0", importo); } } return c; } bool importo_contratto(const TRectype& c, int anno, real& importo, real& imposta) { if (c.empty() || anno < 2010) return false; // Determina l'indice i [0..3] degli importi del contratto per l'anno richiesto char fld[] = "I3"; int i = 3; for (i = 3; i > 0; i--) { fld[1] = '0'+i; const int y = c.get_int(fld); if (y > 0 && y <= anno) break; } // Determina il nome del campo importo corrispondente all'indice i: 0 -> R0; 1 -> R2; 2 -> R4; 3 -> R6 fld[0] = 'R'; fld[1] = '0'+(i*2); importo = c.get_real(fld); fld[1]++; // Il campo imposta č sempre quello successivo a quello dell'importo imposta = c.get_real(fld); return importo > ZERO; } bool importo_figli_contratto(const TRectype& c, int anno, real& importo, real& imposta) { const TString& codtab = c.get("CODTAB"); const TString& prefix = codtab.left(7); const TString& suffix = codtab.mid(7); TString query; query << "USE &CON SELECT S1=\"" << suffix << '\"' << "\nFROM CODTAB=\"" << prefix << '\"' << "\nTO CODTAB=\"" << prefix << '\"'; TISAM_recordset recset(query); importo = imposta = ZERO; for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { real imp, iva; importo_figli_contratto(recset.cursor()->curr(), anno, imp, iva); importo += imp; imposta += iva; } if (importo <= ZERO) importo_contratto(c, anno, importo, imposta); return !importo.is_zero(); } real importo_totale_contratto(char tipocf, long codcf, const char* codcont, int anno, real& importo, real& imposta) { importo = imposta = ZERO; const TRectype& c = contratto(tipocf, codcf, codcont); if (!c.empty() && anno >= 2010) { const TString& padre = c.get("S1"); if (padre.full()) importo_totale_contratto(tipocf, codcf, padre, anno, importo, imposta); else importo_figli_contratto(c, anno, importo, imposta); } return importo > ZERO; } /////////////////////////////////////////////////////////// // TAnagrafica /////////////////////////////////////////////////////////// class TAnagrafica : public TObject { char _tipo; // F o G TString16 _cofi, _paiv; TString _ragsoc; TString4 _com_nasc, _com_res; TDate _data_nasc; int _allegato, _stato_estero; TAnagrafica(const TAnagrafica&) { CHECK(false, "Can't copy TAnagrafica"); } public: virtual bool ok() const { return _tipo=='F' || _tipo == 'G'; } bool fisica() const { return _tipo == 'F'; } bool giuridica() const { return _tipo == 'G'; } const TString& codice_fiscale() const { return _cofi; } const TString& partita_IVA() const { return _paiv; } const TString& ragione_sociale() const { return _ragsoc; } const TString& cognome() const { return _ragsoc.left(24); } const TString& nome() const { return _ragsoc.mid(30,20); } char sesso() const { return (_cofi[9] >= '4') ? 'F' : 'M'; } const TDate& data_nascita() const { return _data_nasc; } int stato_estero() const { return _stato_estero; } int inserimento_in_allegato() const { return _allegato; } const TString& comune_nascita() const { return comune_di(_com_nasc); } const TString& provincia_nascita() const { return provincia_di(_com_nasc); } const TString& comune_residenza() const { return comune_di(_com_res); } const TString& provincia_residenza() const { return provincia_di(_com_res); } bool init(const TRectype& rec); bool init(int num, const TString& codice) { return init(cache().get(num, codice)); } bool init(int num, long codice) { return init(cache().get(num, codice)); } bool init(int num, char tipo, long codice); bool init(char tipo, long codice, const TString& ocfpi); TAnagrafica() : _tipo('\0') {} TAnagrafica(int lognum, const TString& codice) { init(lognum, codice); } TAnagrafica(int lognum, long codice) { init(lognum, codice); } TAnagrafica(int lognum, char tipo, long codice) { init(lognum, tipo, codice); } TAnagrafica(char tipo, long codice, const TString& ocfpi) { init(tipo, codice, ocfpi); } TAnagrafica(const TRectype& rec) { init(rec); } }; bool TAnagrafica::init(const TRectype& rec) { _tipo = '\0'; _stato_estero = 0; _allegato = 0; if (rec.empty()) return false; switch (rec.num()) { case LF_OCCAS: _tipo = 'F'; _cofi = rec.get(OCC_COFI); _paiv = rec.get(OCC_PAIV); if (_cofi.blank() || _paiv.blank()) { const TString& codice = rec.get(OCC_CFPI); if (_cofi.blank() && cf_check("", codice)) _cofi = codice; if (_paiv.blank() && pi_check("", codice)) _paiv = codice; } _ragsoc = rec.get(OCC_RAGSOC); _ragsoc.upper(); _data_nasc = rec.get(OCC_DNASC); _com_nasc = rec.get(OCC_COMNASC); _com_res = rec.get(OCC_COM); _stato_estero = rec.get_int(OCC_STATO); _allegato = _paiv.blank() ? 6 : 2; break; case LF_ANAG: _tipo = rec.get_char(ANA_TIPOA); _ragsoc = rec.get(ANA_RAGSOC); _ragsoc.upper(); _cofi = rec.get(ANA_COFI); _paiv = rec.get(ANA_PAIV); // Comune di residenza fiscale o domicilio _com_res = rec.get(ANA_COMRF); if (_com_res.empty()) _com_res = rec.get(ANA_COMRES); // Dati di nascita persone fisiche if (_tipo == 'F') { const TRectype& anafis = cache().get(LF_ANAGFIS, rec.get_long(ANA_CODANAGR)); _data_nasc = anafis.get(ANF_DATANASC); _com_nasc = rec.get(ANF_COMNASC); } else _tipo = 'G'; break; case LF_NDITTE: { const bool good = init(LF_ANAG, rec.get_char(NDT_TIPOA), rec.get_long(NDT_CODANAGR)); _ragsoc = rec.get(NDT_RAGSOC); _ragsoc.upper(); return good; } break; case LF_CLIFO: _tipo = rec.get_char(CLI_TIPOAPER); if (_tipo == 'F') init(LF_ANAG, _tipo, rec.get_long(CLI_CODANAGPER)); else _tipo = 'G'; // Assegno codice fiscale e partita IVA se validi, altrimenti mantengo quelli dell'anagrafica if (rec.get(CLI_COFI).not_empty()) _cofi = rec.get(CLI_COFI); if (rec.get(CLI_PAIV).not_empty()) _paiv = rec.get(CLI_PAIV); // Prevale sempre la ragione sociale del cliente: "Il cliente ha sempre ragione". _ragsoc = rec.get(CLI_RAGSOC); _ragsoc.upper(); _stato_estero = rec.get_int(CLI_STATOCF); _allegato = rec.get_int(CLI_ALLEG); break; case LF_MOV: return init(rec.get_char(MOV_TIPO), rec.get_long(MOV_CODCF), rec.get(MOV_OCFPI)); case LF_ALLEG: return init(rec.get_char(ALL_TIPOCF), rec.get_long(ALL_CODCF), rec.get(ALL_OCFPI)); default: CHECKD(false, "Record non valido per TAnagrafica ", rec.num()); break; } return _tipo == 'F' || _tipo == 'G'; } bool TAnagrafica::init(int num, char tipo, long codice) { TString16 key; key << tipo << '|' << codice; return init(cache().get(num, key)); } bool TAnagrafica::init(char tipo, long codice, const TString& ocfpi) { bool done = false; if (ocfpi.full()) done = init(LF_OCCAS, ocfpi); if (!done) done = init(LF_CLIFO, tipo, codice); return done; } /////////////////////////////////////////////////////////// // TDati_rilevanti_trc /////////////////////////////////////////////////////////// #define AN _alfafld #define CF _alfafld #define DT _datefld #define NU _intfld #define PI _alfafld #define OBBLIG true class TDati_rilevanti_trc : public TObject { int _tipo; TAS400_recordset* _recset; protected: bool add_field(int n, int da, int a, int len, const char* descr, TFieldtypes tipo = AN, const char* def = NULL, bool required = false); public: void create_fields(int tipo, TAS400_recordset& recset); }; bool TDati_rilevanti_trc::add_field(int n, int da, int a, int len, const char* descr, TFieldtypes tipo, const char* def, bool required) { CHECKD(descr && *descr, "Campo ignoto ", n); CHECKS(n > 0 && da > 0 && a >= da && a <= 1800 && len == (a-da+1), "Campo inconsistente ", descr); TString8 name; name.format("%d.%d", _tipo, n); bool ok = _recset->create_field(name, da-1, len, tipo, required, def); CHECKS(ok, "Can't create field ", descr); return ok; } void TDati_rilevanti_trc::create_fields(int tipo, TAS400_recordset& recset) { CHECKD(tipo >= 0 && tipo <= 5 || tipo == 9, "Tipo record non valido ", tipo); _tipo = tipo; _recset = &recset; TString4 def; def << _tipo; add_field(1, 1, 1, 1, "Tipo record", NU, def, OBBLIG); if (_tipo == 0 || _tipo == 9) { add_field( 2, 2, 6, 5, "Codice identificativo fornitura", AN, "ART21", OBBLIG); add_field( 3, 7, 8, 2, "Codice numerico fornitura", NU, "47", OBBLIG); add_field( 4, 9, 9, 1, "Tipologia di invio", NU, "0", OBBLIG); add_field( 5, 10, 26,17, "Protocollo da sostituire", NU); add_field( 6, 27, 42,16, "Codice fiscale", CF, "", OBBLIG); add_field( 7, 43, 53,11, "Partita IVA", PI); add_field( 8, 54,113,60, "Denominazione", AN); add_field( 9,114,153,40, "Comune domicilio fiscale", AN); add_field(10,154,155, 2, "Provincia domicilio fiscale", AN); add_field(11,156,179,24, "Cognome", AN); add_field(12,180,199,20, "Nome", AN); add_field(13,200,200, 1, "Sesso", AN); add_field(14,201,208, 8, "Data di nascita", DT); add_field(15,209,248,40, "Comune o stato di nascita", AN); add_field(16,249,250, 2, "Provincia di nascita", AN); add_field(17,251,254, 4, "Anno di riferimento", NU); add_field(18,255,255, 1, "Comunicazione societā incorp.", AN, "0", OBBLIG); add_field(19,256,259, 4, "Progressivo invio telmatico", NU, "1"); add_field(20,260,263, 4, "Numero totale invii telematici", NU, "1"); add_field(21,264,279,16, "Codice fiscale intermediario", CF); add_field(22,280,284, 5, "Numero iscrizione C.A.F.", NU); add_field(23,285,285, 1, "Impegno alla trasmissione", NU, "1"); add_field(24,286,293, 8, "Data dell'impegno", DT); add_field(25,294,1797,1504, "Filler", AN); add_field(26,1798,1798,1,"Carattere di controllo", AN, "A", OBBLIG); add_field(27,1799,1800,2,"Caratteri di fine riga", AN, "\r\n"); } else if (_tipo == 1) { add_field( 2, 2,17,16, "Codice fiscale", CF, "", OBBLIG); add_field( 3,18,25, 8, "Data dell'operazione", DT); add_field( 4,26,26, 1, "Modalitā di pagamento", NU, "3", OBBLIG); add_field( 5,27,35, 9, "Importo dovuto", NU); add_field( 6,36,36, 1, "Natura operazione", NU, "1", OBBLIG); add_field( 7,37,37, 1, "Tipologia dell'operazione", NU, "1", OBBLIG); add_field( 8,38,46, 9, "Importo totale operazione", NU); add_field( 9,47,1797,1751, "Filler", AN); add_field(10,1798,1798,1,"Carattere di controllo", AN, "A", OBBLIG); add_field(11,1799,1800,2,"Caratteri di fine riga", AN, "\r\n"); } else if (_tipo == 2) { add_field( 2, 2,12,11, "Partita IVA", PI, "", OBBLIG); add_field( 3,13,20, 8, "Data dell'operazione", DT); add_field( 4,21,21, 1, "Modalitā di pagamento", NU, "3", OBBLIG); add_field( 5,22,30, 9, "Importo dovuto", NU); add_field( 6,31,39, 9, "Imposta", NU); add_field( 6,40,40, 1, "Natura operazione", NU, "1", OBBLIG); add_field( 7,41,41, 1, "Tipologia dell'operazione", NU, "1", OBBLIG); add_field( 8,42,50, 9, "Importo totale operazione", NU); add_field( 9,51,59, 9, "Imposta totale operazione", NU); add_field(10,60,1797,1738, "Filler", AN); add_field(11,1798,1798,1,"Carattere di controllo", AN, "A", OBBLIG); add_field(12,1799,1800,2,"Caratteri di fine riga", AN, "\r\n"); } else if (_tipo == 3) { add_field( 2, 2, 25,24, "Cognome", AN); add_field( 3, 26, 45,20, "Nome", AN); add_field( 4, 46, 53, 8, "Data di nascita", DT); add_field( 5, 54, 93,40, "Comune o stato estero di nascita", AN); add_field( 6, 94, 95, 2, "Provincia di nascita", AN); add_field( 7, 96, 98, 3, "Stato estero del domicilio", AN); add_field( 8, 99,158,60, "Ragione sociale", AN); add_field( 9,159,198,40, "Cittā estera della sede legale", AN); add_field(10,199,201, 3, "Stato estero della sede legale", AN); add_field(11,202,241,40, "Indirizzo estero della sede legale", AN); add_field(12,242,249, 8, "Data dell'operazione", DT); add_field(13,250,250, 1, "Modalitā di pagamento", NU, "3", OBBLIG); add_field(14,251,259, 9, "Importo dovuto", NU); add_field(15,260,268, 9, "Imposta", NU); add_field(16,269,269, 1, "Natura operazione", NU, "1", OBBLIG); add_field(17,270,270, 1, "Tipologia dell'operazione", NU, "1", OBBLIG); add_field(18,271,279, 9, "Importo totale operazione", NU); add_field(19,280,288, 9, "Imposta totale operazione", NU); add_field(20,289,1797,1509, "Filler", AN); add_field(21,1798,1798,1,"Carattere di controllo", AN, "A", OBBLIG); add_field(22,1799,1800,2,"Caratteri di fine riga", AN, "\r\n"); } else if (_tipo == 4) { add_field( 2, 2,12,11, "Partita IVA", PI); add_field( 3,13,20, 8, "Data dell'operazione", DT, "", OBBLIG); add_field( 4,21,30,10, "Numero della Nota di Variazione", AN, "", OBBLIG); add_field( 5,31,39, 9, "Imponibile Nota di Variazione", NU); add_field( 6,40,48, 9, "Imposta Nota di Variazione", NU); add_field( 7,49,56, 8, "Data della Fattura da rettificare", DT, "", OBBLIG); add_field( 8,57,66,10, "Numero della Fattura da rettificare", AN, "", OBBLIG); add_field( 9,67,75, 9, "Imponibile Fattura da rettificare", NU); add_field(10,76,84, 9, "Imposta Fattura da rettificare", NU); add_field(11,85,1797,1713, "Filler", AN); add_field(12,1798,1798,1,"Carattere di controllo", AN, "A", OBBLIG); add_field(13,1799,1800,2,"Caratteri di fine riga", AN, "\r\n"); } else if (_tipo == 5) { add_field( 2, 2, 25,24, "Cognome", AN); add_field( 3, 26, 45,20, "Nome", AN); add_field( 4, 46, 53, 8, "Data di nascita", DT); add_field( 5, 54, 93,40, "Comune o stato estero di nascita", AN); add_field( 6, 94, 95, 2, "Provincia di nascita", AN); add_field( 7, 96, 98, 3, "Stato estero del domicilio", AN); add_field( 8, 99,158,60, "Ragione sociale", AN); add_field( 9,159,198,40, "Cittā estera della sede legale", AN); add_field(10,199,201, 3, "Stato estero della sede legale", AN); add_field(11,202,241,40, "Indirizzo estero della sede legale", AN); add_field(12,242,249, 8, "Data dell'operazione", DT, "", OBBLIG); add_field(13,250,259,10, "Numero della Nota di Variazione", AN, "", OBBLIG); add_field(14,260,268, 9, "Imponibile Nota di Variazione", NU); add_field(15,269,277, 9, "Imposta Nota di Variazione", NU); add_field(16,278,285, 8, "Data della Fattura da rettificare", DT, "", OBBLIG); add_field(17,286,295,10, "Numero della Fattura da rettificare",AN, "", OBBLIG); add_field(18,296,304, 9, "Imponibile Fattura da rettificare", NU); add_field(19,305,313, 9, "Imposta Fattura da rettificare", NU); add_field(20,314,1797,1484, "Filler", AN); add_field(21,1798,1798,1,"Carattere di controllo", AN, "A", OBBLIG); add_field(22,1799,1800,2,"Caratteri di fine riga", AN, "\r\n"); } _recset = NULL; } /////////////////////////////////////////////////////////// // TDati_rilevanti_set /////////////////////////////////////////////////////////// class TDati_rilevanti_set : public TAS400_recordset { int _anno; protected: virtual bool set_field(const TAS400_column_info& fi, const TVariant& var); void init(); public: bool set(unsigned int n, const TVariant& v) { return TAS400_recordset::set(n-1, v); } bool set(unsigned int n, const TString& v) { return TAS400_recordset::set(n-1, TVariant(v)); } bool set(unsigned int n, char v) { TString4 str; str << v; return TAS400_recordset::set(n-1, TVariant(str)); } bool set(unsigned int n, int v) { return TAS400_recordset::set(n-1, TVariant(long(v))); } bool set(unsigned int n, const real& v) { return TAS400_recordset::set(n-1, v.integer()); } bool set(unsigned int n, const TDate& v) { return TAS400_recordset::set(n-1, TVariant(v)); } void add_control_rec(int zero_o_nove); TDati_rilevanti_set(int anno); }; bool TDati_rilevanti_set::set_field(const TAS400_column_info& fi, const TVariant& var) { // Salva le date in formato GGMMAAAA invece dello standard ANSI AAAAMMGG if (fi._type == _datefld && fi._width == 8) { const TDate d = var.as_date(); TString8 str; str.format("%02d%02d%04d", d.day(), d.month(), d.year()); row().overwrite(str, fi._pos); return true; } return TAS400_recordset::set_field(fi, var); } void TDati_rilevanti_set::add_control_rec(int zon) { CHECKD(zon == 0 || zon == 9, "Tipo record di testa o coda non valido ", zon); const TAnagrafica ditta(LF_NDITTE, prefix().get_codditta()); TString4 tipo; tipo << zon; new_rec(tipo); set(6, ditta.codice_fiscale()); set(7, ditta.partita_IVA()); if (ditta.giuridica()) { TString den; set(8, ditta.ragione_sociale()); set(9, ditta.comune_residenza()); set(10, ditta.provincia_residenza()); } else { set(11, ditta.cognome()); set(12, ditta.nome()); set(13, ditta.sesso()); set(14, ditta.data_nascita()); set(15, ditta.comune_nascita()); set(16, ditta.provincia_nascita()); } set(17, _anno); } TDati_rilevanti_set::TDati_rilevanti_set(int anno) : TAS400_recordset("AS400(1800,1)"), _anno(anno) { TDati_rilevanti_trc trc; for (int i = 0; i <= 5; i++) trc.create_fields(i, *this); trc.create_fields(9, *this); } /////////////////////////////////////////////////////////// // TDati_rilevanti_msk /////////////////////////////////////////////////////////// #define MANUAL_ROW 900000L class TDati_rilevanti_msk : public TAutomask { TMaskmode _mode; bool _sheet_dirty, _send_all; TAssoc_array _contratti; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void load_sheet(); bool save_sheet(); bool save_if_dirty(); void set_dirty(bool d = true); protected: TRecnotype last_user_progr() const; TRecnotype nuovo_progr() const; bool check_rows(bool show_error); bool send_nc(const TISAM_recordset& alleg, TDati_rilevanti_set& operaz); bool send_fatt(const TISAM_recordset& alleg, TDati_rilevanti_set& operaz); bool send_rec(const TISAM_recordset& alleg, TDati_rilevanti_set& operaz); public: TRecnotype genera_alleg(); bool elabora_alleg(); bool send_alleg(); bool azzera_alleg(bool manual, TRecnotype first) const; bool elabora_movimento(const TRectype& mov, TFast_isamfile& falleg, TRecnotype& progr, TLog_report& log); bool salva_allegato(const TRectype& mov, TFast_isamfile& falleg, TRecnotype& progr, const real& corrispettivo, const real& imposta, int natope, int tipope, TLog_report& log); bool convalida_clifo(const TRectype& mov, TLog_report& log) const; bool convalida_mov(const TRectype& mov, TLog_report& log) const; bool ignora_movimento(const TRectype& mov, const char* motivo, TLog_report& log) const; TDati_rilevanti_msk() : TAutomask("fe0100a"), _mode(MODE_QUERY) { set_dirty(false); } }; bool TDati_rilevanti_msk::ignora_movimento(const TRectype& mov, const char* motivo, TLog_report& log) const { const long numreg = mov.get_long(MOV_NUMREG); TString msg; msg.format(FR("%7ld Scartato: %s"), numreg, motivo); log.log(1, msg); return false; } bool TDati_rilevanti_msk::convalida_clifo(const TRectype& mov, TLog_report& log) const { const char tipocf = mov.get_char(MOV_TIPO); const long codcf = mov.get_long(MOV_CODCF); const TString16 ocfpi = mov.get(MOV_OCFPI); if (tipocf <= ' ' || (codcf <= 0 && ocfpi.blank())) return false; if (!_send_all) { TString4 stato; if (ocfpi.full()) { const TRectype& rec_occas = cache().get(LF_OCCAS, ocfpi); stato = rec_occas.get(OCC_STATO); } else { TString8 key; key.format("%c|%ld", tipocf, codcf); const TRectype& rec_clifo = cache().get(LF_CLIFO, key); stato = rec_clifo.get(CLI_STATOCF); // tutti i fornitori esteri vanno esclusi (importazioni) const int alleg = rec_clifo.get_int(CLI_ALLEG); if (tipocf == 'F' && alleg == 5) return ignora_movimento(mov, TR("Importazione da fornitore estero"), log); } if (stato.full()) { const TRectype& rec_sta = cache().get("%STA", stato); if (rec_sta.get_bool("B0")) return ignora_movimento(mov, TR("Soggetto residente in stato a fiscalitā agevolata"), log); if (tipocf == 'F') return ignora_movimento(mov, TR("Importazione da fornitore estero"), log); } } return true; //se arriva qui il clifo č da considerare } bool TDati_rilevanti_msk::convalida_mov(const TRectype& mov, TLog_report& log) const { // Ignora eventuale vecchio movimento IVA (ANNOIVA < 2010) const int anno = mov.get_int(MOV_ANNOIVA); if (anno < 2010) return false; if (!_send_all) { // Ignora i movimenti giā comunicati tramite modello INTRA if (!mov.get_real(MOV_CORRLIRE).is_zero() || !mov.get_real(MOV_CORRVALUTA).is_zero()) return ignora_movimento(mov, "INTRA", log); if (anno <= 2011) { const TDate datareg = mov.get_date(MOV_DATAREG); const TString& tipodoc = mov.get(MOV_TIPODOC); if (tipodoc == "SC" && datareg < data_limite_scontrini) { // Ignoro ma segnalo scontrini rilevanti prima della data limite if (anno == 2011 && mov.get_long(MOV_TOTDOC) >= 3600) { TString msg; msg << TR("Scontrino antecedente il ") << data_limite_scontrini; return ignora_movimento(mov, msg, log); } // Ignoro silenziosamente gli altri return false; } } } return convalida_clifo(mov, log); } bool TDati_rilevanti_msk::salva_allegato(const TRectype& mov, TFast_isamfile& falleg, TRecnotype& progr, const real& importo, const real& imposta, int natope, int tipope, TLog_report& log) { bool update_contract = false; const int anno = mov.get_int(MOV_ANNOIVA); falleg.zero(); TRectype& alleg = falleg.curr(); alleg.put(ALL_ANNO, anno); alleg.put(ALL_PROGR, progr); const TString80 contratto = mov.get(MOV_CONTRATTO); if (contratto.full()) { TString80 key; key.format("%c%06ld_%s_%d%d", mov.get_char(MOV_TIPO), mov.get_long(MOV_CODCF), (const char*)contratto, natope, tipope); real* first_progr = (real*)_contratti.objptr(key); if (first_progr == NULL) // Primo movimento del contratto { first_progr = new real; *first_progr = progr; _contratti.add(key, first_progr); } else { // Aggiorno il record generato col primo movimento del contratto const TRecnotype old_progr = first_progr->integer(); CHECKD(old_progr > 0 && old_progr < progr, "Numero progressivo da contratto non valido ", old_progr); alleg.put(ALL_PROGR, old_progr); if (falleg.read() != NOERR) { TString msg; msg << TR("Impossibile aggiornare record da contratto: ") << key; log.log_error(msg); return false; } update_contract = true; } } // I dati della registrazione IVA vanno aggiornati comunque alleg.put(ALL_NUMREG, mov.get(MOV_NUMREG)); alleg.put(ALL_DATAREG, mov.get(MOV_DATAREG)); int modpag = mov.get_int(MOV_MODPAG); if (modpag <= 0) modpag = contratto.full() ? 1 : 3; alleg.put(ALL_MODPAG, modpag); int err = 0; if (update_contract) { // Mi limito ad incrementare gli importi alleg.add(ALL_IMPORTO, importo); alleg.add(ALL_IMPOSTA, imposta); err = falleg.rewrite(); } else { // Registro tutti i dati del cliente e gli importi const char tipocf = mov.get_char(MOV_TIPO); const long codcf = mov.get_long(MOV_CODCF); alleg.put(ALL_TIPOCF, tipocf); alleg.put(ALL_CODCF, codcf); alleg.put(ALL_OCFPI, mov.get(MOV_OCFPI)); alleg.put(ALL_NATOPE, natope); alleg.put(ALL_TIPOPE, tipope); alleg.put(ALL_IMPORTO, importo); alleg.put(ALL_IMPOSTA, imposta); if (contratto.full()) { alleg.put(ALL_CONTRATTO, contratto); real importotot, impostatot; importo_totale_contratto(tipocf, codcf, contratto, anno, importotot, impostatot); alleg.put(ALL_IMPORTOTOT, importotot); alleg.put(ALL_IMPOSTATOT, impostatot); } err = falleg.rewrite_write(); if (err == NOERR) progr++; } if (err != NOERR) { TString msg; msg.format(FR("Errore %d di aggiornamento del file %s"), err, (const char*)falleg.name()); log.log_error(msg); } return err == NOERR; } // Struttura di comodo per memorizzare importi da sommare prima di spedire struct TCorrimp : public TObject { real _corrispettivo, _imposta; }; bool TDati_rilevanti_msk::elabora_movimento(const TRectype& mov, TFast_isamfile& falleg, TRecnotype& progr, TLog_report& log) { if (!convalida_mov(mov, log)) return false; const char tipocf = mov.get_char(MOV_TIPO); const TString4 tipodoc = mov.get(MOV_TIPODOC); const TDate datareg = mov.get_date(MOV_DATAREG); const int anno = datareg.year(); const TString& keytok = mov.get(MOV_NUMREG); TRecord_array righe_iva(keytok, LF_RMOVIVA); // Corrispettivi ed imposte raggruppate per tipologia imponibile [1..4] e tipologia movimento [1..4] TAssoc_array importi; real tot_imponibile, tot_imposta; //calcolo di imponibile ed imposta di tutte le righe iva del movimento for (int r = righe_iva.last_row(); r > 0; r = righe_iva.pred_row(r)) { const TRectype& rmi = righe_iva.row(r); const TCodiceIVA ci(rmi.get(RMI_CODIVA)); int natura_operazione = ci.allegato(tipocf); if (natura_operazione <= 0 || natura_operazione > 5) continue; // Tratto a parte gli scontrini: devono sempre essere di tipo 4 if (natura_operazione == 1 && tipodoc == "SC") natura_operazione = 4; if (!_send_all) { // Controllo per bene gli scontrini che fossero sfuggiti ai controlli precedenti if (natura_operazione == 4 && datareg < data_limite_scontrini) continue; const bool com_obbl = ci.get_bool("B6"); if (com_obbl) { // Le bollette vengono giā spedite dal Enel, per cui non si devono spedire nuovamente ignora_movimento(mov, TR("oggetto di comunicazione obbligatoria all'anagrafe tributaria"), log); continue; } // Esportazioni const bool art_8 = ci.get("S2") == "20" && ci.get("S3") == "1"; if (art_8) { ignora_movimento(mov, TR("soggetto all'articolo 8 (del dpr 26/10/1972)"), log); continue; } const TString4 cod_det = rmi.get(RMI_TIPODET); const int tip_det = cod_det == "3" ? 3 : atoi(cache().get("%DET", cod_det, "I0")); if (tip_det == 3) { ignora_movimento(mov, TR("passaggi interni"), log); continue; } } real rmi_imponibile = rmi.get_real(RMI_IMPONIBILE); real rmi_imposta = rmi.get_real(RMI_IMPOSTA); if (natura_operazione == 4 && rmi_imposta.is_zero()) // se l'imposta non č specificata ... rmi_imposta = ci.scorpora(rmi_imponibile); // ... scorporo il lordo // Determina se la riga sia di servizi o merce. bool srv = ci.get_bool("B8"); // Flag apposito sul codice IVA if (!srv) { const TBill bill(rmi); const TRectype& pcon = cache().get(LF_PCON, bill.string()); srv = pcon.get_bool(PCN_SERVIZI); // Flag apposito sul sottoconto } // Cessione o acquisto di beni (1 o 3) o servizi (2 o 4) const int tipope = (tipocf == 'C' ? 1 : 3) + (srv ? 1 : 0); const char key[3] = { natura_operazione+'0', tipope+'0', '\0' }; TCorrimp* imp = (TCorrimp*)importi.objptr(key); if (imp == NULL) { imp = new TCorrimp; importi.add(key, imp); } imp->_corrispettivo += rmi_imponibile; imp->_imposta += rmi_imposta; tot_imponibile += rmi_imponibile; tot_imposta += rmi_imposta; } bool elabora = true; if (!_send_all) { if (mov.get(MOV_CONTRATTO).full()) { // Considera comunque i contratti per ora, alla fine sistemera' situazioni non rilevanti elabora = true; } else { // Considera solo registrazioni con importo rilevante const real limite = anno == 2010 ? 25000 : 3000; elabora = tot_imponibile >= limite; } } if (elabora) { FOR_EACH_ASSOC_OBJECT(importi, obj, key, itm) { const TCorrimp& corrimp = *(const TCorrimp*)itm; salva_allegato(mov, falleg, progr, corrimp._corrispettivo, corrimp._imposta, key[0]-'0', key[1]-'0', log); } } return elabora; } bool TDati_rilevanti_msk::azzera_alleg(bool manual, TRecnotype first) const { const int anno = get_int(F_ANNO); TFast_isamfile falleg(LF_ALLEG); // Azzeramento anno/attivitā selezionati TString limit; limit << ALL_ANNO << '=' << anno << ' ' << ' ' << ALL_PROGR << '='; TRecnotype daprog = manual ? MANUAL_ROW : first; TRecnotype aprog = manual ? 0 : MANUAL_ROW; TString query; query << "USE " << LF_ALLEG; if (manual) // Elimina i record immessi manualmente ed ignorati query << "\nSELECT " << ALL_IGNORA << "!=\"\""; if (daprog > 0)query << "\nFROM " << limit << daprog; if (aprog > 0) query << "\nTO " << limit << aprog; TISAM_recordset alleg(query); const TRecnotype items = alleg.items(); TString str_pi; str_pi << TR("Compattazione dati ") << anno; TProgind pi(items, str_pi); const TRectype& rec = alleg.cursor()->curr(); for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) { if (!pi.addstatus(1)) break; falleg.curr() = rec; int err = falleg.remove(); if (err != NOERR) return cantwrite_box(falleg.name()); } return items > 0; } // Cerca l'ultimo numero di riga immesso manualmente TRecnotype TDati_rilevanti_msk::last_user_progr() const { const int anno = get_int(F_ANNO); TRecnotype progr = MANUAL_ROW; TString query; query << "USE " << LF_ALLEG << "\nFROM " << ALL_ANNO << '=' << anno << ' ' << ALL_PROGR << '=' << MANUAL_ROW << "\nTO " << ALL_ANNO << '=' << anno; TISAM_recordset alleg(query); if (alleg.move_last()) progr = alleg.get(ALL_PROGR).as_int(); return progr; } TRecnotype TDati_rilevanti_msk::nuovo_progr() const { TRecnotype progr = last_user_progr(); TSheet_field& righe = sfield(F_RIGHE); const int items = righe.items(); if (items > 0) { const int col = righe.cid2index(A_RIGA); for (int i = items-1; i >= 0; i--) { const TRecnotype sheet_progr = atol(righe.cell(i,col)); if (sheet_progr > 0) { if (sheet_progr > progr) progr = sheet_progr; break; } } } return progr+1; } TRecnotype TDati_rilevanti_msk::genera_alleg() { const int anno = get_int(F_ANNO); TString str_pi; str_pi << TR("Movimenti ") << anno; TLog_report log(str_pi); TFast_isamfile falleg(LF_ALLEG); TFast_isamfile fmov(LF_MOV); TString query; query << "USE MOV KEY 2 SELECT CODCF!=''" << "\nFROM DATAREG=01-01-" << anno << "\nTO DATAREG=31-12-" << anno; TISAM_recordset mov(query); const TRectype& mov_rec = mov.cursor()->curr(); const TRecnotype items = mov.items(); TProgind pi(items, str_pi); TRecnotype nprog = 1; _contratti.destroy(); for (bool ok = mov.move_first(); ok; ok = mov.move_next()) { if (!pi.addstatus(1)) break; elabora_movimento(mov_rec, falleg, nprog, log); } log.preview(); return nprog; } // Analizza tutti i movimenti dell'anno dell'attivitā corrente e genera i record rilevanti bool TDati_rilevanti_msk::elabora_alleg() { if (!check_fields()) // Controlla che l'anno sia valido return false; _send_all = get_bool(F_SENDALL); const TRecnotype prog = genera_alleg(); azzera_alleg(false, prog); return prog > 1; } bool TDati_rilevanti_msk::send_nc(const TISAM_recordset& alleg, TDati_rilevanti_set& operaz) { return false; // TBI } bool TDati_rilevanti_msk::send_fatt(const TISAM_recordset& alleg, TDati_rilevanti_set& operaz) { const TAnagrafica anag(alleg.cursor()->curr()); const real importo = alleg.get(ALL_IMPORTO).as_real(); const real imposta = alleg.get(ALL_IMPOSTA).as_real(); const real importo_tot = alleg.get(ALL_IMPORTOTOT).as_real(); const real imposta_tot = alleg.get(ALL_IMPOSTATOT).as_real(); const TString& paiv = anag.partita_IVA(); if (!_send_all) { bool send = false; const int anno = alleg.get(ALL_ANNO).as_int(); if (!anag.stato_estero() && paiv.blank()) { // Se l'importo dello scontrino o l'importo del contratto superano la soglia ... const real limit = 3600; send = anno > 2010 && ((importo+imposta) >= limit || (importo_tot+imposta_tot) >= limit); } else { // Se l'importo della fattura o l'importo del contratto superano la soglia ... const real limit = anno == 2010 ? 25000 : 3000; send = importo >= limit || importo_tot >= limit; } if (!send) return false; } if (anag.stato_estero() > 0) { operaz.new_rec("3"); // Operazioni con soggetti non residenti if (anag.fisica()) { operaz.set(2, anag.cognome()); operaz.set(3, anag.nome()); operaz.set(4, anag.data_nascita()); operaz.set(5, anag.comune_nascita()); operaz.set(6, anag.provincia_nascita()); operaz.set(7, anag.stato_estero()); } else { operaz.set(8, anag.ragione_sociale()); operaz.set(9, anag.comune_residenza()); operaz.set(10, anag.stato_estero()); operaz.set(11, EMPTY_STRING); // TBI? Indirizzo estero } operaz.set(12, alleg.get(ALL_DATAREG).as_date()); operaz.set(13, alleg.get(ALL_MODPAG).as_int()); operaz.set(14, importo); operaz.set(15, imposta); operaz.set(16, alleg.get(ALL_NATOPE).as_int()); operaz.set(17, alleg.get(ALL_TIPOPE).as_int()); operaz.set(18, importo_tot); operaz.set(19, imposta_tot); } else { if (paiv.blank()) { operaz.new_rec("1"); // Operazioni con soggetti residenti non titolari di partita IVA operaz.set(2, anag.codice_fiscale()); operaz.set(3, alleg.get(ALL_DATAREG).as_date()); operaz.set(4, alleg.get(ALL_MODPAG).as_int()); operaz.set(5, real(importo+imposta)); operaz.set(6, alleg.get(ALL_NATOPE).as_int()); operaz.set(7, alleg.get(ALL_TIPOPE).as_int()); operaz.set(8, real(importo_tot+imposta_tot)); } else { operaz.new_rec("2"); // Operazioni con soggetti residenti - titolari di partita IVA operaz.set(2, paiv); operaz.set(3, alleg.get(ALL_DATAREG).as_date()); operaz.set(4, alleg.get(ALL_MODPAG).as_int()); operaz.set(5, alleg.get(ALL_IMPORTO).as_real()); operaz.set(6, alleg.get(ALL_IMPOSTA).as_real()); operaz.set(7, alleg.get(ALL_NATOPE).as_int()); operaz.set(8, alleg.get(ALL_TIPOPE).as_int()); operaz.set(9, importo_tot); operaz.set(10,imposta_tot); } } return false; } bool TDati_rilevanti_msk::send_rec(const TISAM_recordset& alleg, TDati_rilevanti_set& operaz) { const bool ignora = alleg.get(ALL_IGNORA).as_bool(); if (ignora) return false; const long numrett = alleg.get(ALL_NUMRETT).as_int(); return numrett > 0 ? send_nc(alleg, operaz) : send_fatt(alleg, operaz); } // Genera file per invio telematico bool TDati_rilevanti_msk::send_alleg() { const int anno = get_int(F_ANNO); _send_all = get_bool(F_SENDALL); TFilename temp; temp.tempdir(); temp.add("datiril.txt"); TDati_rilevanti_set recset(anno); recset.add_control_rec(0); TString query; query << "USE " << LF_ALLEG << " SELECT " << ALL_IGNORA << "==\"\"" << "\nFROM " << ALL_ANNO << '=' << anno << "\nTO " << ALL_ANNO << '=' << anno; TISAM_recordset alleg(query); for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) send_rec(alleg, recset); recset.add_control_rec(9); return recset.save_as(temp); } void TDati_rilevanti_msk::set_dirty(bool d) { _sheet_dirty = d; enable(DLG_SAVEREC, d); } void TDati_rilevanti_msk::load_sheet() { const int anno = get_int(F_ANNO); TString16 limit; limit << ALL_ANNO << '=' << anno; const char tipocf = get(F_TIPOCF)[0]; const long codcf = get_long(F_CODCF); const TString& ocfpi = get(F_OCFPI); TSheet_field& s = sfield(F_RIGHE); s.destroy(); TString query; query << "USE " << LF_ALLEG; if (codcf > 0) { query << " SELECT (" << ALL_TIPOCF << "='" << tipocf << "')&&(" << ALL_CODCF << "='" << codcf << "')"; if (ocfpi.full()) query << "&&(" << ALL_OCFPI << "='" << ocfpi << "')"; } query << "\nFROM " << limit << "\nTO " << limit; TISAM_recordset alleg(query); const TRecnotype items = alleg.items(); if (items > 0) { TString pi_str; pi_str << TR("Caricamento ") << anno; TProgind pi(items, pi_str); const TRectype& curr = alleg.cursor()->curr(); int rec = 0; for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) { if (!pi.addstatus(1)) break; s.autoload_line(rec+1, curr); s.check_row(rec); rec++; } } s.force_update(); set_dirty(false); if (s.items() > 0) { _mode = MODE_MOD; disable(-1); } else { _mode = MODE_QUERY; enable(-1); } } bool TDati_rilevanti_msk::save_sheet() { if (!check_rows(false)) return false; bool done = true; const int anno = get_int(F_ANNO); TSheet_field& s = sfield(F_RIGHE); const TRecnotype items = s.items(); if (items > 0) { TFast_isamfile alleg(LF_ALLEG); TRectype& rec = alleg.curr(); TProgind pi(items, TR("Registrazione righe"), false); FOR_EACH_SHEET_ROW(s, r, row) { if (!pi.addstatus(1)) break; alleg.zero(); rec.put(ALL_ANNO, anno); s.autosave_line(r+1, rec); const int err = alleg.rewrite_write(); if (err != NOERR) { done = cantwrite_box(alleg.name()); break; } } } if (done) { // Cancella le righe manuali marcate come da NON inviare azzera_alleg(true, MANUAL_ROW); set_dirty(false); } return done; } bool TDati_rilevanti_msk::check_rows(bool show_error) { const int anno = get_int(F_ANNO); bool ok = anno >= 2010; if (!ok) { if (show_error) check_fields(); // Provoco segnalazione automatica return false; } long codcf = 0L; TString16 ocfpi; TSheet_field& s = sfield(F_RIGHE); FOR_EACH_SHEET_ROW(s, i, row) { row->get(s.cid2index(A_CODCF), codcf); row->get(s.cid2index(A_OCFPI), ocfpi); if (codcf <= 0L && ocfpi.blank()) { ok = show_error && error_box(FR("Soggetto mancante alla riga %d"), i+1); break; } } return ok; } bool TDati_rilevanti_msk::save_if_dirty() { bool done = true; if (_sheet_dirty && yesno_box(TR("Si desiderano registrare le modifiche?"))) { done = check_rows(true); if (done) done = save_sheet(); } return done; } bool TDati_rilevanti_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_OK: // Salva if (e == fe_button && jolly == 0) // Selezione su maschera principale { if (_mode == MODE_QUERY || save_if_dirty()) load_sheet(); return false; } break; case DLG_CANCEL: if (e == fe_button && _mode != MODE_QUERY && jolly == 0) { if (save_if_dirty()) { TSheet_field& s = sfield(F_RIGHE); s.destroy(); s.force_update(); _mode = MODE_QUERY; enable(-1); } return false; } break; case DLG_SAVEREC: if (e == fe_button) save_if_dirty(); break; case DLG_RECALC: if (e == fe_button && check_fields()) { if (elabora_alleg()) load_sheet(); } break; case DLG_ELABORA: if (e == fe_button && check_fields()) send_alleg(); break; case F_RIGHE: if (e == se_notify_modify) set_dirty( true); else if (e == se_query_add) { if (!check_rows(false)) return false; } else if (e == se_notify_add) { TSheet_field& s = (TSheet_field&)o; TToken_string& row = s.row(jolly); row.add(nuovo_progr(), s.cid2index(A_RIGA)); row.add(TDate(TODAY), s.cid2index(A_DATAREG)); row.add(3, s.cid2index(A_MODPAG)); row.add(1, s.cid2index(A_NATOPE)); row.add(1, s.cid2index(A_TIPOPE)); } else if (e == se_query_del) return false; break; case DLG_DELREC: if (e == fe_button) { // La cancellazione fisica non si puo' fare subito o.mask().set(A_IGNORA, "X"); return false; } break; case DLG_EXPORT: if (e == fe_button) return sfield(F_RIGHE).esporta(); break; case A_CODCF: case A_OCFPI: if (e == fe_modify || (e == fe_init && !o.empty())) { TMask& m = o.mask(); const TAnagrafica anag(m.get(A_TIPOCF)[0], m.get_long(A_CODCF), m.get(A_OCFPI)); m.set(A_RAGSOC, anag.ragione_sociale()); m.set(A_PAIV, anag.partita_IVA()); m.set(A_COFI, anag.codice_fiscale()); } break; case A_CONTRATTO: if (e == fe_modify || (e == fe_init && !o.empty())) { TMask& m = o.mask(); real importo, imposta; importo_totale_contratto(m.get(A_TIPOCF)[0], m.get_long(A_CODCF), m.get(A_CONTRATTO), get_int(F_ANNO), importo, imposta); m.set(A_IMPORTOTOT, importo); m.set(A_IMPOSTATOT, imposta); } break; default: break; } return true; } /////////////////////////////////////////////////////////// // TDati_rilevanti_app /////////////////////////////////////////////////////////// class TDati_rilevanti_app : public TSkeleton_application { protected: virtual bool create(); public: virtual void main_loop(); }; bool TDati_rilevanti_app::create() { TSheet_field::set_line_number_width(6); const TRectype alleg(LF_ALLEG); if (!alleg.exist(ALL_IMPORTO)) return error_box(TR("Il database non č stato ancora convertito per il modulo FE")); return TSkeleton_application::create(); } void TDati_rilevanti_app::main_loop() { TDati_rilevanti_msk msk; msk.run(); } /////////////////////////////////////////////////////////// // main /////////////////////////////////////////////////////////// int fe0100(int argc, char* argv[]) { TDati_rilevanti_app app; app.run(argc, argv, TR("Gestione dati rilevanti")); return 0; }