#include #include #include #include #include #include #include #include #include #include #include #include // dongle() #include // Oracle Recset #include // std::map #include "../ve/velib05.h" #include "../cg/cglib03.h" #include "../fe/felib.h" #include "tf0100a.h" ///////////////////////////////////////////////////////////////////////////////////// // Globals ///////////////////////////////////////////////////////////////////////////////////// static XVT_SQLDB _db = NULL; // TFF sqlite db enum return_code { found, // Trovato foundcust, // Trovato in trasfatt foundidcust,// Trovato ma con id customizzato nextmov, // Trovato ma cambiato movimento eof, // EOF rmoviva eofcust, // EOF trasfatt after // File mov su un movimento dopo rispetto a rmoviva }; // Su DB: X o ''->Da inviare, F->Forzato, I->Inviato, N->Non inviare enum filter_fatt { toSend, // Da inviare sent, // Inviate disabled // Disabilitate }; #define MOV_CUSTOM 10000000 #define SHEET_GAP 101 #define DTE_PROVV "DTE0000001" #define DTR_PROVV "DTR0000001" #define TOLLARANZA 0.05 // Flag invio #define FLAG_INVIO "X" #define FLAG_ERRORE "E" #define FLAG_NINVIO "N" #define FLAG_FORZATO "F" #define FLAG_INVIATO "I" #define SPESOMETROBASE "ModuliSirio" #define REG_ATT 1 #define REG_PAS 2 #define CARATTERI_ACCENTATI "àèéìòù" /* Così facendo basta modificare la maschera (e le dichiarazioni di conseguenza) * per avere l'inserimento nello sheet corretto */ enum spesometroFields{ _spedita = A_SPEDITA - SHEET_GAP, _invio = A_INVIO - SHEET_GAP, _forzata = A_FORZATA - SHEET_GAP, _numero = A_NUMERO - SHEET_GAP, _datareg = A_DATAREG - SHEET_GAP, _tipocf = A_TIPOCF - SHEET_GAP, _codcf = A_CODCF - SHEET_GAP, _occas = A_OCFPI - SHEET_GAP, _ragsoc = A_RAGSOC - SHEET_GAP, _rfso = A_RFSO - SHEET_GAP, _ragsocrfso = A_RAGSOCRFSO - SHEET_GAP, _codnum = A_TIPODOC - SHEET_GAP, _numdoc = A_NUMDOC - SHEET_GAP, _datadoc = A_DATADOC - SHEET_GAP, _natura = A_NATURA - SHEET_GAP, _aliquota = A_ALIQUOTA - SHEET_GAP, _detraibile = A_DETRAIB - SHEET_GAP, _imponibile = A_IMPONIBILE - SHEET_GAP, _importoIVA = A_IMPOSTA - SHEET_GAP, // Imposta è già preso _reverse = A_REVERSE - SHEET_GAP, _autofatt = A_AUTOFATT - SHEET_GAP, _paiv = A_PAIV - SHEET_GAP, _codfis = A_COFI - SHEET_GAP, _coderr = A_CODERR - SHEET_GAP }; ///////////////////////////////////////////////////////////////////////////////////// // Utilities ///////////////////////////////////////////////////////////////////////////////////// // Da un id ritorna il tipo doc corrispondente TString getTipoDoc(int id); int getTipoDoc(TString id); // Ritorna il record custom TRectype getTrasFatt(TString reg, TString codiva); // Ritorna il cliente in un record di $clifo, con tipocf = "O" lo cerca in $occas TRectype getCli(const TString& tipocf, const TString& codcf, const TString& ocfpi); // Cerca una stringa all'interno di una SLIST (Potrebbe diventare una funzione di XVT.h) static SLIST_ELT xvt_slist_find_str(SLIST list, const char* str); // Aggiorna il file dst se più vecchio di src (Potrebbe diventare una funzione di XVT.h) bool xvt_fsys_fupdate(const char* src, const char* dst); // Controlla se l'azienda ha un RFSO bool haveRFSO(TString& codrfso); // Decodifica il tipo di documento per il trasferimento fatture const char * decodTipo(TToken_string* strarr); // Salvo un singolo record bool saveRec(TToken_string row, bool esportato = false); // Ritorno una data in formato ANSI inline TDate toDate(const char * date) { return TDate(date).string(); } // Salto se la riga non è abilitata #define IF_IS_ENABLED(strarr) if(strcmp(strarr->get(_invio), FLAG_INVIO) != 0 && strcmp(strarr->get(_invio), FLAG_FORZATO) != 0) continue; // Ritorno il carattere senza accento maiuscolo inline char noAccent(char a); ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_record ///////////////////////////////////////////////////////////////////////////////////// // Contenitore di campi di un record di database SQLite class TTrFa_record : public TObject { TString8 _table; TToken_string _key; TAssoc_array _fields; protected: void copy(const TTrFa_record& rec) { _table = rec._table; _key = rec._key; _fields = rec._fields; } const TString& var2str(const TString& fld, const TVariant& var) const; public: void reset() { _fields.destroy(); } void set(const char* fld, const TVariant& var); void set(const char* fld, long var); void set(const char* fld, const char* var); void set(const char* fld, const real& var); void set(const char* fld, const TString& var); void set(const char* fld, const TDate& var); void set(const char* fld, bool var); const TVariant& get(const char* fld) const; bool insert(); bool remove(); bool search(); bool search(const char* k1, const char* k2 = NULL, const char* k3 = NULL); virtual TObject* dup() const { return new TTrFa_record(*this); } virtual bool ok() const { return _table.not_empty(); } TTrFa_record& operator=(const TTrFa_record& rec) { copy(rec); return *this; } TTrFa_record(const TTrFa_record& rec) { copy(rec); } TTrFa_record(const char* table); }; ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_cursors ///////////////////////////////////////////////////////////////////////////////////// /* * Classe per la gestione di RMOVIVA, MOV, TFCUST */ class TTrFa_cursors : TObject { friend class TCursor; TISAM_recordset* c_rmoviva; TISAM_recordset* c_trasfatt; bool _newMov; bool _newCust; // Se trovo un record custom devo saltare tutti quelli che trovo successivamente, per fare ciò utilizzo una TToken_string TToken_string _alqCust; TRectype _next(return_code& code, TString& tipocf, TString& codcf, TString& ocfpi); // Si sposta avanti di un elemento TRectype _nextCust(return_code& code, TString& tipocf, TString& codcf, TString& ocfpi); // Si sposta avanti di un elemento tra quelli custom bool checkRecord(TISAM_recordset* rec); public: //TTrFa_cursors(); ~TTrFa_cursors(); long int getIvaItems() { return c_rmoviva->items(); } long int getIvaPos() { return c_rmoviva->cursor()->pos(); } TRectype getIva() { return c_rmoviva->cursor()->curr(); } int next(TAssoc_array& recimposte, bool& ok, TString& tipocf, TString& codcf, TString& ocfpi); // Legge tutto il prossimo movimento, in importi mette per ogni codiva la somma int updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, int cod = toSend); }; ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_mask ///////////////////////////////////////////////////////////////////////////////////// class TTrFa_mask : public TAutomask { friend class TTrFa_cursors; TMaskmode _mode; bool _sheet_dirty; bool _filter_changed; protected: virtual void next_page(int p); const char * natura(const TString& codiva) const; real get_IVA(const TString& codiva) const; TString findDetraib(TString tipodet) const; TString revCharge(TString numreg) const; TString getRFSO(TString codrfso) const; TRecnotype nuovo_progr() const; void changeInvio(TString tipocf, TString codcf, TString numdoc, TString invio) const; virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void openJava(); public: void setFilterChanged() { _filter_changed = true; } void load_sheet(); TTrFa_mask(TString msk); ~TTrFa_mask(); // Carico i tipi documento all'inizio void loadConfig(); // Salvo i tipi documento void saveConfig(); // Salvo tutti i records bool saveAll(); // Controllo tutti i records bool checkAll(); // Testo validità record bool checkRec(TPrinter* stampa, TToken_string* rec); // Controllo che siano presenti records bool checkNotEmpty(); // Controllo finale prima di inviare il tutto, se ci sono fatture // con più volte lo stesso codice aliquota disabilito il precedente void theFinalCheckDown(); // Mette il flag di invio = [flag] per la riga numero [nrow] void flagRow(int nrow, TString flag); // Salto se la riga ha un tipo invio non del filtro bool checkInvio(const TString& invio); }; // Funzione inline di stampa inline void printError(TPrinter* stampa, TString movimento, TString documento, TString msgerr); ///////////////////////////////////////////////////////////////////////////////////// // TTrFa_app ///////////////////////////////////////////////////////////////////////////////////// struct clifoDoc { long contCliFo; long countDoc; }; class TTrFa_app : public TSkeleton_application { TAnagrafica _ditta; TString16 _cofi; TFilename _dbname; TLog_report* _log; TString _logTFF; bool _append; TString myrfso; static long header; // Solitamente nei programmi di campo cerco di sfruttare le classi interne ma per mancanza di tempo sono costretto a usare l'std::vector std::map mCliDoc; private: int parse_line(const TString& line, TString& var, TString& val) const; bool create_table(TScanner& TFF, const TString& table); TString getKey(TToken_string* strarr); TString getHeader(TToken_string* strarr); TString getBody(TToken_string* strarr, bool add = true); bool tff0100(TSheet_field& sheet); // Header esportazione bool tff0200(TString key); // Anagrafica ditta bool tff0300(TString key, TRectype r_ana); // Rappresentante fiscale ditta bool tff0400(TSheet_field& sheet); // Anagrafica clifo bool tff0700(TSheet_field& sheet); // Testata documento bool tff2200(TToken_string* strarr, int nriga); // Riepilogo aliquote bool tff3100(TToken_string* strarr, TRectype r_ana); // Rappresentante fiscale clifo bool setEsportato(TSheet_field& sheet); bool emptyTables(TString key); // Cancella da tutte le tabelle i record con chiave key protected: void log(int severity, const char* msg); bool show_log(); bool syncronizeDB(); bool createDB(); bool copySSA(); public: virtual bool create(); virtual bool destroy(); virtual void main_loop(); bool send(TTrFa_mask* msk); TTrFa_app() : _log(NULL) {} };