#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fe0100a.h" #include "felib.h" #include "../cg/cglib01.h" const char* const INVALID_NUMDOC = "???????"; long MANUAL_ROW = 900000L; /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// enum TExclusion_mode { em_normale, em_importo_limite, em_no_allegato, em_fiscalita_agevolata, em_estero, em_intra, em_art8, em_data_limite, em_passaggi_interni, em_inviato, em_altro }; static const char* mode2string(TExclusion_mode motivo) { const char* msg = ""; switch (motivo) { case em_importo_limite : msg = TR("Importo non rilevante"); break; case em_no_allegato : msg = TR("Soggetto da non inserire in allegato"); break; case em_fiscalita_agevolata: msg = TR("Soggetto residente in stato a fiscalitā agevolata"); break; case em_estero : msg = TR("Soggetto residente all'estero"); break; case em_intra : msg = TR("Movimento intra"); break; case em_data_limite : msg = TR("Data fuori dal limite della comunicazione"); break; case em_art8 : msg = TR("Soggetto all'articolo 8 (del dpr 26-10-1972)"); break; case em_passaggi_interni : msg = TR("Passaggi interni"); break; case em_inviato : msg = TR("Inviato in definitivo"); break; default : msg = TR("Altri motivi"); break; } return msg; } /////////////////////////////////////////////////////////// // TSpesometro_msk /////////////////////////////////////////////////////////// class TSpesometro_msk : public TAutomask { TMaskmode _mode; bool _sheet_dirty; TExclusion_mode _why; TLog_report* _log; TString16 _partita_IVA, _codice_fiscale; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void alleg_sort(TSheet_field& s) const; void load_sheet(); bool save_sheet(); bool save_if_dirty(); void set_dirty(bool d = true); bool send_fatt(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const; bool send_nota_variazione(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const; bool send_estero(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const; void build_outname(TFilename& n) const; int get_date_range(TDate& dal, TDate& al) const; protected: TRecnotype last_user_progr() const; TRecnotype nuovo_progr() const; bool check_rows(bool show_error); void enable_buttons(); void save_anagr(const TAnagrafica& anag, TSpesometro_set& operaz) const; bool send_rec(const TRectype& alleg, TSpesometro_set& operaz); TExclusion_mode segnala_movimento(const TRectype& mov, TExclusion_mode motivo); //bool fattura_associata(long numreg_var, TDate& datafatt, TString& numdoc) const; bool azzera_alleg(TAssoc_array& manuali) const; public: TRecnotype genera_alleg(); bool elabora_alleg(); bool send_alleg(); bool recall_alleg() const; TExclusion_mode elabora_movimento(const TRectype& mov, TBaseisamfile& falleg); bool salva_allegato(const TRectype& mov, TBaseisamfile& falleg, TRecnotype& progr, const real& corrispettivo, const real& imposta, int tipope); TExclusion_mode validate_clifo(const TRectype& mov); TExclusion_mode validate_mov(const TRectype& mov); TSpesometro_msk(); ~TSpesometro_msk() { save_profile(); } }; TSpesometro_msk::TSpesometro_msk() : TAutomask("fe0100a"), _mode(MODE_QUERY), _log(NULL) { load_profile(); set_dirty(false); const long codditta = prefix().get_codditta(); const TAnagrafica ditta(LF_NDITTE, codditta); _partita_IVA = ditta.partita_IVA(); if (_partita_IVA.blank()) _codice_fiscale = ditta.codice_fiscale(); else { if (_partita_IVA[0] == '8' || _partita_IVA[0] == '9') { _codice_fiscale = _partita_IVA; _partita_IVA.cut(0); } } } TExclusion_mode TSpesometro_msk::segnala_movimento(const TRectype& mov, TExclusion_mode motivo) { if (_why == em_normale) // Aggiorna motivo esclusione se normale { _why = motivo; bool segnala = true; if (_why != em_fiscalita_agevolata && get(F_TIPO) == "BL") // Segnalo solo black list segnala = false; if (segnala) { const long numreg = mov.get_long(MOV_NUMREG); const char tipocf = mov.get_char(MOV_TIPO); const long codcf = mov.get_long(MOV_CODCF); const TAnagrafica a(tipocf, codcf, mov.get(MOV_OCFPI)); TString msg; msg.format(FR("Mov. %7ld %s %s: "), numreg, tipocf=='F' ? TR("For.") : TR("Cli."), (const char*)a.ragione_sociale()); msg << mode2string(motivo); if (a.estero() && a.stato_estero_UNICO().blank()) msg << " (Codice UNICO non specificato)"; msg.strip_double_spaces(); _log->log(1, msg); } } return motivo; } TExclusion_mode TSpesometro_msk::validate_clifo(const TRectype& mov) { 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 segnala_movimento(mov, em_no_allegato); TString8 key; key.format("%c|%ld", tipocf, codcf); const TRectype& rec_clifo = cache().get(LF_CLIFO, key); const int alleg = rec_clifo.get_int(CLI_ALLEG); if (alleg == 4) { const long codalleg = rec_clifo.get_long(CLI_CODALLEG); key; key.format("%c|%ld", tipocf, codalleg); const TRectype& rec_alleg = cache().get(LF_CLIFO, key); if (!rec_alleg.empty()) { ((TRectype&)mov).put(MOV_CODCF, codalleg); return validate_clifo(mov); } } TString4 stato; if (ocfpi.full()) { const TRectype& rec_occas = cache().get(LF_OCCAS, ocfpi); stato = rec_occas.get(OCC_STATO); } else { if (alleg == 1) return segnala_movimento(mov, em_no_allegato); if (alleg == 5) return segnala_movimento(mov, em_intra); stato = rec_clifo.get(CLI_STATOCF); if (stato.blank() && alleg == 9) // Flag extra CEE incoerente return segnala_movimento(mov, em_estero); } if (stato.full()) { // I clienti privati vanno inclusi anche se residenti in stati esteri in black list if (ocfpi.blank() && alleg != 6) { const TRectype& rec_sta = cache().get("%STA", stato); if (rec_sta.get_bool("B0") || rec_sta.get_bool("B1")) // Black list o San Marino return segnala_movimento(mov, em_fiscalita_agevolata); } return segnala_movimento(mov, em_estero); } return em_normale; // se arriva qui il clifo č da considerare } TExclusion_mode TSpesometro_msk::validate_mov(const TRectype& mov) { // Ignora eventuale vecchio movimento IVA (ANNOIVA < 2012) const int anno = mov.get_int(MOV_ANNOIVA); if (anno < 2012) return segnala_movimento(mov, em_data_limite); // Trova i movimenti INTRA if (!mov.get_real(MOV_CORRLIRE).is_zero() || !mov.get_real(MOV_CORRVALUTA).is_zero()) return segnala_movimento(mov, em_intra); const TString& keytok = mov.get(MOV_NUMREG); const char tipocf = mov.get_char(MOV_TIPO); TRecord_array righe_iva(keytok, LF_RMOVIVA); 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)); const int natura_operazione = ci.allegato(tipocf); if (natura_operazione <= 0 || natura_operazione > 5) continue; tot_imponibile += rmi.get_real(RMI_IMPONIBILE); tot_imposta += rmi.get_real(RMI_IMPOSTA); } if (tot_imponibile.is_zero() && tot_imposta.is_zero()) { TExclusion_mode em = validate_clifo(mov); if (em == em_normale) em = segnala_movimento(mov, em_importo_limite); return em; } return validate_clifo(mov); } TExclusion_mode TSpesometro_msk::elabora_movimento(const TRectype& mov, TBaseisamfile& falleg) { TExclusion_mode em = validate_mov(mov); const char tipocf = mov.get_char(MOV_TIPO); const long codcf = mov.get_long(MOV_CODCF); const TString4 tipodoc = mov.get(MOV_TIPODOC); const TDate datareg = mov.get_date(MOV_DATAREG); const int anno = get_int(F_ANNO); TString4 tipope = "FE"; // Default = Fattura emessa if (em == em_fiscalita_agevolata) { tipope = "BL"; } else if (em == em_estero) { if (tipocf == 'C') tipope = "FN"; } else { const bool is_nota = fe_is_nota_variazione(mov); if (tipocf == 'F') { tipope = is_nota ? "NR" : "FR"; } else { tipope = is_nota ? "NE" : "FE"; } } const TString& keytok = mov.get(MOV_NUMREG); TRecord_array righe_iva(keytok, LF_RMOVIVA); int tipo_iva = 1; // Normale real tot_imponibile, tot_imposta; real ser_imponibile, mer_imponibile; //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; // Scarta codici IVA non rilevanti if (natura_operazione > tipo_iva) tipo_iva = natura_operazione; // Esportazioni const bool art_8 = ci.get("S2") == "20" && ci.get("S3") == "1"; if (art_8) segnala_movimento(mov, em_art8); 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) segnala_movimento(mov, em_passaggi_interni); 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 sullo scontrino ... rmi_imposta = ci.scorpora(rmi_imponibile); // ... scorporo il lordo tot_imponibile += rmi_imponibile; tot_imposta += rmi_imposta; if (tipope == "SE") { const TBill zio(rmi); const TRectype& rec = cache().get(LF_PCON, zio.string()); if (rec.get_int(PCN_RICSER) == 1) // 0=Altro; 1=Servizi; 2=Merce ser_imponibile += rmi_imponibile; else mer_imponibile += rmi_imponibile; } } const long numreg = mov.get_long(MOV_NUMREG); // Registro tutti i dati del cliente e gli importi falleg.zero(); switch (em) { case em_normale: { TString8 key; key << tipocf << '|' << codcf; const TRectype& clifo = cache().get(LF_CLIFO, key); if (clifo.get_char(CLI_ALLEG) == 'C') // Carta carburanti falleg.put(ALL_CARBURAN, true); else { if (tipocf == 'C') { bool af = false; if (_partita_IVA.full()) af = _partita_IVA == clifo.get(CLI_PAIV); else af = _codice_fiscale == clifo.get(CLI_COFI) && clifo.get(CLI_PAIV).blank(); // Agriturismo if (af) { falleg.put(ALL_AUTOFATT, af); if (tot_imponibile.is_zero() && !tot_imposta.is_zero()) tot_imponibile = tot_imposta.sign(); } } if (mov.get_int(MOV_UPROTIVA) > 0) falleg.put(ALL_RIEPILOG, true); } } break; case em_fiscalita_agevolata: if (abs(tot_imponibile) <= 500) falleg.put(ALL_IGNORA, em = em_importo_limite); // Ignora importo <= 500 Euro break; // Non ignorare! case em_estero: if (tot_imponibile.is_zero()) falleg.put(ALL_IGNORA, em = em_importo_limite); // Ignora importo nullo else { if (tipocf == 'F') // Considera solo fatture servizi { if (ser_imponibile > mer_imponibile) falleg.put(ALL_SERVIZI, true); else falleg.put(ALL_IGNORA, em); // Ignora importazioni di merce } } break; case em_intra: if (tipocf == 'C' && !tot_imposta.is_zero()) { tipope = "FN"; em = em_estero; break; } default: falleg.put(ALL_IGNORA, em); // Ignora break; } if (mov.get_date(MOV_INVIOFE).ok()) { falleg.put(ALL_IGNORA, em_inviato); segnala_movimento(mov, em_inviato); } if (em == em_normale || em_intra) { if (tipocf == 'F') { const TRectype& caus = cache().get(LF_CAUSALI, mov.get(MOV_CODCAUS)); const int reg_spec = caus.get_int(CAU_REGSPIVA); if (reg_spec == 13 || reg_spec == 50 || reg_spec == 51) // reverse charge falleg.put(ALL_REVERSE, true); } } if (tipope == "SE") { const TAnagrafica anag(mov); bool good = anag.comune_residenza().full(); if (good) { if (anag.fisica()) good = anag.cognome().full() && anag.data_nascita().ok(); else good = anag.ragione_sociale().full(); } if (!good) { falleg.put(ALL_AUTOFATT, true); if (tot_imponibile.is_zero() && !tot_imposta.is_zero()) tot_imponibile = tot_imposta.sign(); } } falleg.put(ALL_ANNO, anno); falleg.put(ALL_PROGR, numreg); falleg.put(ALL_TIPOPE, tipope); falleg.put(ALL_TIPOCF, tipocf); falleg.put(ALL_CODCF, codcf); falleg.put(ALL_OCFPI, mov.get(MOV_OCFPI)); falleg.put(ALL_DATAREG, mov.get(MOV_DATAREG)); falleg.put(ALL_NUMDOC, mov.get(MOV_NUMDOC)); falleg.put(ALL_DATADOC, mov.get(MOV_DATADOC)); falleg.put(ALL_NOLEGGIO,mov.get(MOV_NOLEGGIO)); falleg.put(ALL_TIPOIVA, tipo_iva); falleg.put(ALL_IMPORTO, tot_imponibile); falleg.put(ALL_IMPOSTA, tot_imposta); const int err = falleg.rewrite_write(); if (err != NOERR) { TString msg; msg.format(FR("Errore %d di aggiornamento del record %d/%ld sul file %s"), err, anno, numreg, (const char*)falleg.name()); _log->log(2, msg); } return _why; } bool TSpesometro_msk::azzera_alleg(TAssoc_array& manuali) const { TDate dataini, datafin; const int anno = get_date_range(dataini, datafin); if (!delete_box(FR("Si desiderano eliminare le righe dal %s al %s"), dataini.stringa(), datafin.stringa())) return false; TFast_isamfile fast_alleg(LF_ALLEG); TFast_isamfile fast_mov(LF_MOV); TString query; query << "USE " << LF_ALLEG << "\nSELECT BETWEEN(DATAREG," << dataini.date2ansi() << ',' << datafin.date2ansi() << ')' << "\nJOIN MOV INTO NUMREG==PROGR" << "\nFROM ANNO=" << anno << "\nTO ANNO=" << anno << " PROGR=" << MANUAL_ROW; TISAM_recordset alleg(query); TLocalisamfile& falleg = alleg.cursor()->file(); TRectype& arec = falleg.curr(); TLocalisamfile& fmov = alleg.cursor()->file(LF_MOV); TRectype& mrec = fmov.curr(); TString msg; msg << TR("Azzeramento ") << falleg.description() << ' ' << anno; TProgind pi(alleg.items(), msg, false); manuali.destroy(); for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) { pi.addstatus(1); const long progr = arec.get_long(ALL_PROGR); const long numreg = mrec.get_long(MOV_NUMREG); const TDate datareg = mrec.get_long(MOV_DATAREG); const int annoiva = mrec.get_long(MOV_ANNOIVA); bool kill = numreg != progr || annoiva < anno; if (!kill) { const bool forzata = arec.get_bool(ALL_FORZATURA); if (forzata) manuali.add(arec.get(ALL_PROGR)); else kill = annoiva == anno; } if (kill) falleg.remove(); // Riga generata dalla vecchia versione } return !manuali.empty(); } // Cerca l'ultimo numero di riga immesso manualmente TRecnotype TSpesometro_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 TSpesometro_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 > progr) progr = sheet_progr; } } return progr+1; } static int sort_alleg(const TSortable& s1, const TSortable& s2, void* jolly) { const TRectype& a1 = (const TRectype&)s1; const TRectype& a2 = (const TRectype&)s2; const TDate d1 = a1.get(ALL_DATAREG); const TDate d2 = a2.get(ALL_DATAREG); int cmp = d1 - d2; return cmp; } TRecnotype TSpesometro_msk::genera_alleg() { const int anno = get_int(F_ANNO); TString str_pi; str_pi << TR("Movimenti"); str_pi << ' ' << anno; _log = new TLog_report(str_pi); TAssoc_array manuali; azzera_alleg(manuali); TRecnotype nprog = 1; if (anno >= 2012) // Dummy test for bracing TFast_isamfiles { TFast_isamfile falleg(LF_ALLEG); TFast_isamfile fmov(LF_MOV); const TDate dal(1,1,anno); const TDate al(31,12,anno); TString query; query << "USE MOV KEY 3 SELECT (BETWEEN(DATAREG," << dal.date2ansi() << ',' << al.date2ansi() << "))&&(REG!=\"\")" << "\nFROM TIPO=C\nTO TIPO=F"; TISAM_recordset mov(query); TRectype& mov_rec = mov.cursor()->curr(); const TRecnotype items = mov.items(); TProgind pi(items, str_pi); for (bool ok = mov.move_first(); ok; ok = mov.move_next()) { if (!pi.addstatus(1)) break; _why = em_normale; const TDate datafe = mov_rec.get(MOV_INVIOFE); if (datafe.ok()) // Non elaborare i movimenti giā inviati in definitivo! { segnala_movimento(mov_rec, em_inviato); continue; } const TString& key = mov_rec.get(MOV_NUMREG); if (manuali.is_key(key)) { manuali.remove(key); continue; } elabora_movimento(mov_rec, falleg); } } _log->preview(); delete _log; _log = NULL; return nprog; } // Analizza tutti i movimenti dell'anno dell'attivitā corrente e genera i record rilevanti bool TSpesometro_msk::elabora_alleg() { if (!check_fields()) // Controlla che l'anno sia valido return false; const TRecnotype prog = genera_alleg(); return prog > 1; } bool TSpesometro_msk::send_nota_variazione(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const { const real imp = alleg.get_real(ALL_IMPORTO); operaz.set(11, imp > ZERO ? "ND" : "NC"); return true; } bool TSpesometro_msk::send_fatt(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const { return true; } bool TSpesometro_msk::send_estero(const TRectype& alleg, const TAnagrafica& anag, TSpesometro_set& operaz) const { const char tipocf = alleg.get_char(ALL_TIPOCF); const bool is_nota = fe_is_nota_variazione(alleg); if (is_nota) // Le istruzioni dicono di ignorarla, ma Sirio non ha ancora deciso send_nota_variazione(alleg, anag, operaz); // Imposta solamente il campo 11 a ND o NC const char cayman = anag.is_black_list(); const bool servizi = tipocf == 'F' && alleg.get_bool(ALL_SERVIZI); if (servizi && alleg.get_bool(ALL_AUTOFATT)) { // Trasforma la fattura da non residente ad autofattura operaz.set(0, "FR"); // Azzera campi anagrafici e sostituiscili con quelli del dichiarante const long codditta = prefix().get_codditta(); const TAnagrafica ditta(LF_NDITTE, codditta); for (int f = 14; f <= 26; f++) operaz.set(f, ""); save_anagr(ditta, operaz); return true; } // I flag 27,28,29 sono obbligatori e mutuamente esclusivi if (cayman > ' ') // Residente in paese a fiscalitā agevolata (o San Marino) { const char str[2] = { cayman, '\0' }; // Convert char to string operaz.set(27, str); } else { if (servizi) operaz.set(29, true); // Acquisto servizi all'estero else operaz.set(28, true); // Residente all'estero } const char* sez = "BL30"; if (cayman > ' ') { if (is_nota) sez = "BL50"; else { if (alleg.get_int(ALL_TIPOIVA) == 4) // Non esposta sez = "BL41"; } } operaz.set(30, sez); // Tipologia imponibile BL return true; } void TSpesometro_msk::save_anagr(const TAnagrafica& anag, TSpesometro_set& operaz) const { // Partita IVA e Codice fiscale sono alternativi const TString& piva = anag.partita_IVA(); if (piva.full()) { if (piva[0] >= '8' && piva.len() == 11 && anag.italiano()) // Ente pubblico! operaz.set(2, piva); // In realtā trattasi di codice fiscale speciale! else operaz.set(1, piva); } else operaz.set( 2, anag.codice_fiscale()); if (anag.fisica()) { operaz.set(14, anag.cognome()); operaz.set(15, anag.nome()); operaz.set(16, anag.data_nascita()); operaz.set(17, anag.comune_nascita()); operaz.set(18, anag.provincia_nascita()); operaz.set(19, anag.stato_estero_UNICO()); operaz.set(20, anag.comune_residenza()); operaz.set(21, anag.indirizzo_residenza()); } else { operaz.set(22, anag.ragione_sociale()); operaz.set(23, anag.comune_residenza()); operaz.set(24, anag.stato_estero_UNICO()); operaz.set(25, anag.indirizzo_residenza()); operaz.set(26, piva); } } bool TSpesometro_msk::send_rec(const TRectype& alleg, TSpesometro_set& operaz) { bool done = false; const real importo = abs(alleg.get_real(ALL_IMPORTO)); const real imposta = abs(alleg.get_real(ALL_IMPOSTA)); if (importo.is_zero() && imposta.is_zero()) return false; // should never happen const TAnagrafica anag(alleg); if (!anag.ok()) return false; // should never happen const char tipocf = alleg.get_char(ALL_TIPOCF); const TString4 tipo = alleg.get(ALL_TIPOPE); operaz.new_rec(tipo); operaz.set(31, alleg.get_int(ALL_ATTAGG)); // Provoca nascita dei 34 campi vuoti precedenti operaz.set(32, alleg.get_int(ALL_PASAGG)); operaz.set(33, alleg.get_bool(ALL_RIEPILOG)); operaz.set(34, alleg.get_bool(ALL_CARBURAN)); operaz.set( 3, alleg.get_int(ALL_TIPOIVA) == 4); // IVA non esposta in fattura operaz.set( 4, alleg.get(ALL_NOLEGGIO)); // Noleggio operaz.set( 5, alleg.get_bool(ALL_AUTOFATT)); // Autofattura operaz.set( 6, alleg.get_bool(ALL_REVERSE)); // Reverse charge operaz.set( 7, alleg.get(ALL_DATADOC)); operaz.set( 8, alleg.get(ALL_DATAREG)); operaz.set( 9, alleg.get(ALL_NUMDOC)); operaz.set(10, tipocf == 'F' ? "A" : "C"); // Acquisto o Cessione operaz.set(12, importo); operaz.set(13, imposta); save_anagr(anag, operaz); if (anag.estero()) done = send_estero(alleg, anag, operaz); else { if (fe_is_nota_variazione(alleg)) done = send_nota_variazione(alleg, anag, operaz); else done = send_fatt(alleg, anag, operaz); } return done; } bool TSpesometro_msk::recall_alleg() const { TDate dal, al; const int anno = get_date_range(dal, al); if (!delete_box(FR("Si desidera annullare l'invio definitivo dal %s al %s?"), dal.stringa(), al.stringa())) return false; TFast_isamfile mov(LF_MOV); TString query; query << "USE MOV KEY 2"; query << "\nFROM DATAREG=" << dal; query << "\nTO DATAREG=" << al; TISAM_recordset recset(query); TLocalisamfile& file = recset.cursor()->file(); TString msg; msg << TR("Aggiornamento movimenti di prima nota dal ") << dal.stringa() << TR(" al ") << al.stringa(); TProgind pi(recset.items(), msg); for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { if (!pi.addstatus(1)) break; if (file.get_date(MOV_INVIOFE).ok()) { file.zero(MOV_INVIOFE); file.rewrite(); } } return true; } void TSpesometro_msk::build_outname(TFilename& n) const { TDate dal, al; const int anno = get_date_range(dal,al); n = get(F_OUTFOLDER); if (n.blank()) n.tempdir(); TString80 f; if (get(F_TIPO) == "BL") { const int dm = dal.month(), am = al.month(); if (dm == am) { TString16 m = itom(dal.month()); m.cut(3); f.format("BlackList%05ld%s%04d", prefix().get_codditta(), (const char*)m, anno); } else if (am-dm == 2) { TString16 m; m << TR("Trim") << itor(am/3); f.format("BlackList%05ld%s%04d", prefix().get_codditta(), (const char*)m, anno); } else f.format("BlackList%05ld%04d", prefix().get_codditta(), anno); } else f.format("Spesometro%05ld%04d", prefix().get_codditta(), anno); n.add(f); n.ext("csv"); } // Genera file per invio telematico bool TSpesometro_msk::send_alleg() { const TString& tipo = get(F_TIPO); TDate dal, al; const int anno = get_date_range(dal, al); TString query; query << "USE ALLEG KEY 2\nSELECT "; if (tipo == "BL") { query << "(BETWEEN(DATAREG," << dal.date2ansi() << ',' << al.date2ansi() << "))&&" << "(TIPOPE==\"BL\")"; } else query << "(TIPOPE!=\"BL\")"; query << "\nFROM " << ALL_ANNO << '=' << anno << "\nTO " << ALL_ANNO << '=' << anno; TISAM_recordset alleg(query); const TRectype& rec = alleg.cursor()->curr(); const TRecnotype tot_alleg = alleg.items(); bool done = tot_alleg > 0; if (done) { TSpesometro_set recset; recset.add_header(*this); TFilename temp; build_outname(temp); _log = new TLog_report(temp); TProgind pi(tot_alleg, temp); for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) { if (!pi.addstatus(1)) break; const int ignora = alleg.get(ALL_IGNORA).as_int(); // Non mi fido di "", " " e "0" per questo campo if (ignora == 0) send_rec(rec, recset); } recset.add_footer(*this); done = recset.save_as(temp); if (_log->recordset()->items()) _log->preview(); delete _log; _log = NULL; } const char* const jar = "spesometro.jar"; if (xvt_fsys_file_exists(jar)) xvt_sys_goto_url(jar, "run"); // open doesn't work right now if (done && get_bool(F_DEFINITIVO) && yesno_box(TR("Si conferma l'invio definitivo della comunicazione?"))) { TFast_isamfile mov(LF_MOV); TProgind pi(tot_alleg, TR("Aggiornamento movimenti di prima nota"), false); for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) { if (!pi.addstatus(1)) break; const int ignora = rec.get_int(ALL_IGNORA); if (ignora) continue; const long numreg = rec.get_long(ALL_PROGR); if (numreg > 0 && numreg < MANUAL_ROW) { mov.put(MOV_NUMREG, numreg); int err = mov.read(_isequal, _lock); if (err == NOERR) { if (!mov.get_date(MOV_INVIOFE).ok()) { mov.put(MOV_INVIOFE, al); err = mov.rewrite(); } else mov.reread(_unlock); } if (err != NOERR) { error_box(FR("Impossibile aggiornare il movimento %ld: errore %d"), numreg, err); break; } } if (numreg > 0) { TLocalisamfile& fall = alleg.cursor()->file(); fall.put(ALL_IGNORA, em_inviato); fall.rewrite(); } } } return done; } void TSpesometro_msk::set_dirty(bool d) { _sheet_dirty = d; enable(DLG_SAVEREC, d); } void TSpesometro_msk::alleg_sort(TSheet_field& s) const { s.sort(); } void TSpesometro_msk::load_sheet() { TWait_cursor hourglass; 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.hide(); // Nascondo lo sheet per guadagnare un 20% di velocitā di caricamento s.destroy(); _mode = MODE_QUERY; const TString& tipope = get(F_TIPO); TDate dal, al; const int anno = get_date_range(dal, al); TString limit; limit << ALL_ANNO << '=' << anno; if (codcf > 0) limit << ' ' << ALL_TIPOCF << '=' << tipocf << ' ' << ALL_CODCF << '=' << codcf; TString sel; if (ocfpi.full()) sel << "&&(" << ALL_OCFPI << "='" << ocfpi << "')"; if (tipope != "**") // Tutto { if (tipope == "XX") { sel << "&&(STR(IGNORA>0))"; } else if (tipope == "IN") { sel << "&&(STR(IGNORA==9))"; } else { if (tipope == "BL") sel << "&&(TIPOPE=\"BL\")"; // Black List else sel << "&&(TIPOPE!=\"BL\")"; // Spesometro sel << "&&(STR(IGNORA==0))"; } } if (dal.month() != 1 || al.month() != 12) sel << "&&(BETWEEN(DATAREG," << dal.date2ansi() << ',' << al.date2ansi() << "))"; TString query; query << "USE " << LF_ALLEG << " KEY 2"; if (sel.full()) { sel.ltrim(2); query << " SELECT " << sel; } if (limit.full()) query << "\nFROM " << limit << "\nTO " << limit; TISAM_recordset alleg(query); const TRecnotype items = alleg.items(); if (items > 0) { TString pi_str; pi_str << TR("Caricamento ") << items << TR(" movimenti "); if (dal.month() != 1 || al.month() != 12) { if (dal.month() == al.month()) pi_str << itom(dal.month()) << ' '; else pi_str << itom(dal.month()) << '/' << itom(al.month()) << ' '; } pi_str << anno; TProgind pi(items, pi_str); TRectype& curr = alleg.cursor()->curr(); int rec = 0; for (bool ok = alleg.move_first(); ok; ok = alleg.move_next()) { if (!pi.addstatus(1)) break; if (anno <= 2012) { const int t = curr.get_int(ALL_TIPOPE); switch (t) { case 1: curr.put(ALL_TIPOPE, "FE"); break; case 2: curr.put(ALL_TIPOPE, "FR"); break; default: break; } } s.autoload_line(++rec, curr); } } //alleg_sort(s); s.force_update(); s.show(); set_dirty(false); if (s.items() > 0) { _mode = MODE_MOD; disable(-1); } else { _mode = MODE_QUERY; enable(-1); } enable_buttons(); } bool TSpesometro_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) { set_dirty(false); } return done; } bool TSpesometro_msk::check_rows(bool show_error) { const int anno = get_int(F_ANNO); bool ok = anno >= 2012; 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 TSpesometro_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; } int TSpesometro_msk::get_date_range(TDate& dal, TDate& al) const { const TDate oggi(TODAY); int anno = get_int(F_ANNO); if (anno < 2012) anno = oggi.year(); dal = TDate( 1, 1, anno); al = TDate(31, 12, anno); if (get(F_TIPO) == "BL") { const TString& m = get(F_PERIODO); if (m[0] == 'T') { const int t = m[1]-'1'; dal = TDate( 1, 3*t+1, anno); al = TDate(28, 3*t+3, anno); } else { const int mese = atoi(m); if (mese > 0) dal = al = TDate(1, mese, anno); } al.set_end_month(); } return anno; } void TSpesometro_msk::enable_buttons() { TSheet_field& s = sfield(F_RIGHE); TDate dal, al; const int anno = get_date_range(dal, al); const bool good_year = anno >= 2012; const bool def = get_bool(F_DEFINITIVO); const bool full_rows = good_year && !s.empty(); bool one_sent = false; // Ho spedito almeno un movimento in definitivo if (good_year) { TString query; query << "USE MOV KEY 2 SELECT INVIOFE!=\"\""; query << "\nFROM DATAREG=" << dal; query << "\nTO DATAREG=" << al; TISAM_recordset recset(query); one_sent = recset.move_first(); } enable(DLG_CANCEL, full_rows); enable(DLG_SAVEREC,full_rows && _sheet_dirty); enable(DLG_EXPORT, full_rows); enable(DLG_RECALC, !full_rows && good_year && !one_sent); enable(DLG_ELABORA, good_year && !(one_sent && def)); enable(DLG_DELREC, one_sent); enable(F_DEFINITIVO, !def); if (def) reset(F_DEFINITIVO); TFilename temp; build_outname(temp); enable(DLG_PREVIEW, temp.exist()); } bool TSpesometro_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 && jolly == 0) { if (_mode != MODE_QUERY && save_if_dirty()) { TSheet_field& s = sfield(F_RIGHE); s.destroy(); s.force_update(); _mode = MODE_QUERY; enable(-1); enable_buttons(); } return false; } break; case DLG_SAVEREC: if (e == fe_button) save_if_dirty(); break; case DLG_EXPORT: if (e == fe_button) return sfield(F_RIGHE).esporta(); 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()) { const TString& tipo = get(F_TIPO); if (tipo != "FE" && tipo != "BL") return error_box("Non č possibile inviare i record che verrebbero scartati"); TDate dal, al; get_date_range(dal, al); if (tipo == "BL" && (al-dal) > 93) return error_box("E' necessario specificare il mese o il trimestre per la Black List"); send_alleg(); enable_buttons(); // Disabilita bottone se definitivo } break; case DLG_DELREC: if (e == fe_button && o.active()) { if (jolly == 0) // Toolbar principale { recall_alleg(); enable_buttons(); // Disabilita bottone return false; } else // Maschera di riga { const long progr = o.mask().get_long(A_RIGA); if (progr >= MANUAL_ROW) { TLocalisamfile alleg(LF_ALLEG); alleg.put(ALL_ANNO, get(F_ANNO)); alleg.put(ALL_PROGR, progr); const int err = alleg.remove(); if (err != NOERR) return error_box(FR("Errore di cancellazione: %d"), err); } else return error_box(TR("Riga non cancellabile")); } } break; case DLG_PREVIEW: if (e == fe_button) { TFilename temp; build_outname(temp); if (temp.exist()) { TSpesometro_rep rep(temp); rep.preview(); } } break; case F_ANNO: if (e == fe_init || e == fe_modify) { int anno = atoi(o.get()); if (anno < 2013) { anno = TDate(TODAY).year()-1; o.set(anno); } enable_buttons(); } break; case F_OUTFOLDER: if (e == fe_init && o.empty()) { TFilename tmp; tmp.tempdir(); o.set(tmp); } break; case F_RIGHE: if (e == fe_init) load_sheet(); else if (e == se_query_modify) { TSheet_field& s = (TSheet_field&)o; TToken_string& row = s.row(jolly); const TRecnotype progr = row.get_long(0); s.sheet_mask().enable(DLG_DELREC, progr >= MANUAL_ROW); s.sheet_mask().enable(DLG_USER, progr < MANUAL_ROW); } else if (e == se_notify_modify) { set_dirty(true); enable_buttons(); } 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)); } else if (e == se_query_del) { TSheet_field& s = (TSheet_field&)o; TToken_string& row = s.row(jolly); const TRecnotype progr = row.get_long(0); return progr >= MANUAL_ROW; } 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 DLG_USER: if (e == fe_button || e == fe_init) { const long numreg = o.mask().get_long(A_RIGA); const bool enab = (numreg > 0) && (numreg < MANUAL_ROW); if (e == fe_button && enab) { o.disable(); // Tecnica anti doppio click! TRectype mov(LF_MOV); mov.put(MOV_NUMREG, numreg); mov.edit(); o.enable(); } else o.enable(enab); } break; default: break; } if (e == fe_modify && jolly == 1 && _mode == MODE_MOD) { const short id = o.dlg(); if (id >= A_RIGA && id < A_COFI && id != A_FORZATA) { o.mask().set(A_FORZATA, true); set_dirty(); } } return true; } /////////////////////////////////////////////////////////// // TSpesometro_app /////////////////////////////////////////////////////////// class TSpesometro_app : public TSkeleton_application { protected: virtual bool create(); public: virtual void main_loop(); }; bool TSpesometro_app::create() { if (!has_module(F3AUT)) { TString html; html << "" << "
Attenzione: Il modulo FE deve essere attivato in congiunzione a F3.
\n" << "

Al fine di poter attivare l'utilizzo della Comunicazione Polivalente 2013 " << "La preghiamo di contattare Sirio informatica e sistemi al seguente riferimento:


" << "" << ""; return warning_box(html); } // Controllo preventivo dell'avvenuta conversione del tracciato record TRectype alleg(LF_ALLEG); if (alleg.type(ALL_CARBURAN) == _nullfld) return error_box(TR("Database non convertito per la Comunicazione Polivalente")); TLocalisamfile mov(LF_MOV); if (mov.last() == NOERR) { const long numreg = mov.get_long(MOV_NUMREG); while (numreg > MANUAL_ROW) MANUAL_ROW *= 10; } // Teoricamente č possibile visualizzare tutti i movimenti di un anno, per cui allargo il numero riga TSheet_field::set_line_number_width(7); return TSkeleton_application::create(); } void TSpesometro_app::main_loop() { TSpesometro_msk msk; msk.run(); } /////////////////////////////////////////////////////////// // main /////////////////////////////////////////////////////////// int fe0100(int argc, char* argv[]) { TSpesometro_app app; app.run(argc, argv, TR("Comunicazione Polivalente")); return 0; }