#ifndef __F901001_H #define __F901001_H // #include // #include // #include #include "strings.h" #include "date.h" #include "real.h" #include "../cg/cglib.h" #include "sheet.h" #include "sqlset.h" #include "reprint.h" #include "reputils.h" #define INI_PAR_MOD "F9" #define INI_CATDOC "CATDOC" #define INI_ANNESSI "ANNCAT" #define IS_ITALIANO(statopaiv) ((statopaiv) == "IT" || !(statopaiv).full()) // Controlla eventuali apostrofi e li raddoppia const char* check_str(const TString& str); const TString & get_numdoc_exp_fp(int numreg); class TAnnesso_mov : public TObject { long _numreg; TString _filename; TString _catdocpad; TString _catdocann; TDate _loaddate; TString _user; protected: TAnnesso_mov & copy(const TAnnesso_mov & a); public : virtual TObject* TAnnesso_mov::dup() const { return new TAnnesso_mov(*this); } TAnnesso_mov & operator = (const TAnnesso_mov & a) { return copy(a);} const TString & numreg() const { return _numreg; } const TString & filename() const { return _filename; } const TString & catdocpad() const { return _catdocpad; } const TString & catdocann() const { return _catdocann; } const TDate & loaddate() const { return _loaddate; } const TString & user() const { return _user; } void ann2row(TToken_string & row); TAnnesso_mov(long numreg, const char * filename, const char * catdocpad, const char * catdocann, const TDate & loaddate, const char * user) : _numreg(numreg), _filename(filename), _catdocpad(catdocpad), _catdocann(catdocann), _loaddate(loaddate), _user(user) {} TAnnesso_mov(TToken_string & row, int start = 0); TAnnesso_mov(const TAnnesso_mov & a) { copy(a); } ~TAnnesso_mov() {} }; struct statistics { size_t total; size_t fa_skip; size_t fa_err; size_t fa_estr; size_t fa_nocatdoc; size_t fv_cart_skip; size_t fv_err; size_t fv_estr; size_t fv_nocatdoc; }; extern statistics _stats; struct drd { TString cod_soc; TString id_estr; bool flag_prov{ true }; TString descr; char tipo_doc{ 'A' }; TDate dal; TDate al; TString user; TString timestamp; TString4 stato_estr{ "01" }; TString addr_cart; }; enum result_estr { estr_ok = 1, // Estrazione e' avvenuta senza errori. estr_err_db_iva = 0, // Errore scrittura database iva. estr_stop = -1, // Non esistono movimenti estraibili in quel periodo, o periodo sovrapposto ad altra estrazione. estr_diag_err = -2, // La diagnostica ha riportato errori. estr_err_db_drd = -99 // Errore scrittura F9DRD. }; struct return_estr { result_estr result; size_t* fa_skip; size_t* fa_total; size_t* fa_err; size_t* fv_cart_skip; size_t* fv_err; size_t* fv_estr; }; enum state_fppro { correct = 1, reg_with_err = -1, // Movimento associato male con FPPRO not_fa = -10, // Non e' fattura acquisti guessed = 100, no_guessed = 0, null_state = -100, err_read_db = 999 // Errore lettura da fppro }; class TF9_config { // todo: controllare che siano sqlsafe // Config in f90100: TString _ambiente; // Codice ambiente (codsoc) TString _addr_doc; // Indirizzo documenti cartacei WebApp (Server) TString _addr_doc_loc; // Indirizzo documenti cartacei WebApp (Locale) bool _cartexp; // Config in f90300: TString _addr_cart; // Indirizzo cartella documenti cartacei TString _estensioni; // Estensioni valide per il caricamenti dei doc. cart. public: const TString& get_ambiente() const { return _ambiente; } const TString& get_addr_doc() const { return _addr_doc; } const TString& get_addr_doc_loc() const { return _addr_doc_loc; } bool get_has_cartexp() const { return _cartexp; } const TString& get_addr_cart() const { return _addr_cart; } const TString& get_estensioni() const { return _estensioni; } void set_ambiente(const TString& cod_amb); void set_addr_doc(const TString& path); void set_addr_doc_loc(const TString& path); void set_has_cartexp(bool flag); void set_addr_cart(const TString& path); void set_estensioni(const TString& ext); TF9_config(); }; extern TF9_config F9CONF; class TClasse_doc : public TObject { TString _catdoc; // Codice cat. documentale. TString _descr; // Descrizione documento. TString _class_sost; // { FTA | FTV } - classe documentale sostitutiva. TString _caus_sost; // causale per sostitutiva (TD01...). TString _causcont; // Codice causale. TString _tipocaus; // Usato come tipo documento (FA, FV, CR, ...). protected: TClasse_doc & copy(const TClasse_doc & c); public: virtual TObject* TClasse_doc::dup() const { return new TClasse_doc(*this); } TClasse_doc & operator = (const TClasse_doc & c) { return copy(c); } const TString & catdoc() const { return _catdoc; } const TString & descr() const { return _descr; } const TString & class_sost() const { return _class_sost; } const TString & caus_sost() const { return _caus_sost; } const TString & causcont() const { return _causcont; } const TString & tipocaus() const { return _tipocaus; } void ann2row(TToken_string & row); TClasse_doc(const char * catdoc, const char * descr, const char * class_sost, const char * caus_sost, const char * causcont, const char * tipocaus) : _catdoc(catdoc), _descr(descr), _class_sost(class_sost), _caus_sost(caus_sost), _causcont(causcont), _tipocaus(tipocaus) {} TClasse_doc(TToken_string & row, int start = 0); TClasse_doc(const TClasse_doc & c) { copy(c); } ~TClasse_doc() {} }; class TAnnesso : public TObject { TString _catdocpadre; TString _catdoc; // Codice cat. documentale. TString _descr; // Descrizione documento. TString _opcee; // { RV | DC } - Usato come classificazione annesso (Reverse, ann. cartaceo). bool _obblig; // Definisce se deve essere per forza presente l'annesso. TAnnesso & copy(const TAnnesso & a); public: virtual TObject* TAnnesso::dup() const { return new TAnnesso(*this); } TAnnesso & operator = (const TAnnesso & a) { return copy(a); } const TString & catdocpadre() const { return _catdocpadre; } const TString & catdoc() const { return _catdoc; } const TString & descr() const { return _descr; } const TString & opcee() const { return _opcee; } bool obblig() const { return _obblig; } void ann2row(TToken_string & row); TAnnesso(const char * catdocpadre, const char * catdoc, const char * descr, const char * opcee, bool obblig = false) : _catdocpadre(catdocpadre), _catdoc(catdoc), _descr(descr), _opcee(opcee), _obblig(obblig) {} TAnnesso(TToken_string & row, int start = 0); TAnnesso(const TAnnesso & a) { copy(a); } ~TAnnesso() {} }; class TCategorie_doc { TAssoc_array _rows; // TClasse_doc * TAssoc_array _sheets_annessi; // TArray_sheet * TArray_sheet * _sheet_catdocs; TString_array * _name_catdocs; int _mode_sheet; TClasse_doc * find_tipodocsdi(const TString& tipodocsdi, const char * tipocaus); // OK TArray_sheet * find_sheet_annessi(const TString& catdoc) { return (TArray_sheet *) _sheets_annessi.objptr(catdoc); } void load_all(); void save_ann(); void save_cat(); static const char* traduci_caus_sost(const TString& caus); static const char* traduci_class_ann(const TString& class_ann); static const char* traduci_class_sost(const TString& class_sost); protected: TAssoc_array _rows_annessi; // TAnnesso TCategorie_doc::TAnnesso * find_annesso(const TString& catdoc_padre, const char* catdoc_ann); public: TClasse_doc * find_causcont(const TString& caus); // OK TClasse_doc * find_tipodoc(const TString& tipodoc); // OK void add_annesso(const TString& catdoc_padre, const TString& catdoc_ann, const TString& descr, const TString& class_ann, bool obblig = false); void edit_annesso(const TString& catdoc_padre, const TString& catdoc_ann, const TString& descr, const TString& class_ann, bool obblig = false); void add_categoria(const TString& catdoc, const TString& descr, const TString& class_sost, const TString& caus_sost, const TString& causcont, const TString& tipocaus); bool annesso_exist(const TString& catdoc_padre, const char* catdoc_ann) { return find_annesso(catdoc_padre, catdoc_ann) != nullptr; } void del_annesso(const TString& catdoc, const char* catdoc_ann); TAnnesso * get_ann(const TString & catdoc, const TString& catann); TString_array get_array_ann(const TString& catdoc); TString_array get_array_rows(bool traduci = false); TClasse_doc* get_classe_doc(const TString& catdoc) { return (TClasse_doc *)_rows.objptr(catdoc); } TString_array * get_name_catdocs() { get_sheet_catdocs(); return _name_catdocs; } TArray_sheet * get_sheet_catdocs(); TArray_sheet * get_sheet_ann(const TString& catdoc); TClasse_doc * mov2cat(const long numreg); const TString & tipo2caus_cont(const TString & tipodoc, const char * tipocaus) { TClasse_doc * c = find_tipodocsdi(tipodoc, tipocaus); if (c != nullptr) return c->causcont(); else return EMPTY_STRING; } void reload(); static void remove_all(); static void remove_all_ann(); static void remove_all_cat(); void set_mode_sheet(const int mode) { _mode_sheet = mode; } TCategorie_doc(); }; TCategorie_doc& categorie_doc(bool reload = false); class TRecord_categorie : public TCategorie_doc { public: enum type { catdocs = 0, annessi = 1 }; private: type _table; struct recordtype { TString_array head; TToken_string record; } _categorie, _annessi; TString_array _result_set; int _next_pos{ 0 }; public: TString get(const char* field); bool next(); void put(const char* field, const char* value); bool read(bool traduci = false); TRecord_categorie(type table = catdocs); }; enum err_mov { mov_no_error, // Estratto normalmente. mov_escluso, // Movimento con flag escluso. mov_no_catdoc, // Nessuna cat. doc. riconosciuta per questo movimento, o non e' una fattura. mov_no_doc, // Il mov. di vendita non ha un documento generatore. mov_notfound_elet, // Non trovata fatt. elettronica mov vendita. mov_no_fa, // Movimento di acquisto non e' una fattura. mov_no_fv, // Movimento di vendita non e' una fattura. mov_no_cartaceo, // Movimento cartaceo che non ha bisogno di essere estratto. mov_pura_iva, // Movimento di sola IVA (integrazione Rev. Charge) mov_no_filecart, // Il documento cartaceo non ha associato un file, o questo non e' stato trovato. mov_annesso_nexist, // Un annesso obbligatorio e' mancante. mov_nocat_butok // Non è stata trovata nessuna categoria documentale per il seguente documento. Verra usato il TIPODOCSDI presente nel FPPRO }; class TMovimento_estr : public TObject // aggiungere metodi per TArray { bool _err; long _numreg; TDate _datareg; TDate _datadoc; TString _codcaus; int _meseliq; TString _numdoc; real _tot; long _codcf; TString _ragsoc; TString _reg_protiva; TString _descr; state_fppro _state; TString _descr_err; // Messaggio di errore visibile dal controllo estrazione. bool _estratto; err_mov _descr_estr; // Messaggio di informazioni visibile dal 'Apri Estr.' bool _cartaceo; TString_array _documenti_allegati; TString _cat_doc_padre; TDate _data_estr; TString _user; TFilename _nomefiledoc; TMovimento_estr & copy(const TMovimento_estr & m); public: virtual TObject* TMovimento_estr::dup() const { return new TMovimento_estr(*this); } TMovimento_estr & operator =(const TMovimento_estr& m) { return copy(m);} static const char* err_mov2name(const err_mov descr_estr); const char* get_descr_estr() const { return err_mov2name(_descr_estr); } bool err() const { return _err; } bool no_err() const { return !err(); } long numreg() const { return _numreg; } const TDate & datareg() const { return _datareg; } const TDate & datadoc() const { return _datadoc; } const TString & codcaus() const { return _codcaus; } int meseliq() const { return _meseliq; } const TString & numdoc() const { return _numdoc; } real totale() const { return _tot; } long codcf() const { return _codcf; } const TString & ragsoc() const { return _ragsoc; } const TString & protiva() const { return _reg_protiva; } const TString & descr() const { return _descr; } state_fppro state() const { return _state; } const TString & descr_err() const { return _descr_err; } bool estratto() const { return _estratto; } err_mov descr_estr() const { return _descr_estr; } TClasse_doc* catdoc(TCategorie_doc& catdoc) const { return catdoc.mov2cat(numreg()); } bool cartaceo() const { return _cartaceo || allegati(); } const TFilename & nomefiledoc() const { return _nomefiledoc; } bool allegati() const { return _documenti_allegati.items() > 0; } TString_array & documenti_allegati() { return _documenti_allegati; } const TString & cat_doc_padre() const { return _cat_doc_padre; } TDate data_estr() const { return _data_estr; } const TString& user() const { return _user; }; void set_err(const char * descr = "", err_mov descr_estr = mov_no_error); void reset_err() { set_err(); } void set_state(state_fppro state) { _state = state; } void set_descr_estr(err_mov descr_estr) { _descr_estr = descr_estr; } void set_numdoc(const char * numdoc) { _numdoc = numdoc; } void set_estratto(bool estratto) { _estratto = estratto; } void set_nomefiledoc(const char * nomefiledoc) { _nomefiledoc = nomefiledoc; } void set_cartaceo(bool cartaceo) { _cartaceo = cartaceo; } void set_cat_doc_padre(const char *cat) { _cat_doc_padre = cat; } void set_data_estr(TDate data) { _data_estr = data; } void set_user(const char *user) { _user = user; }; bool load_docs(); bool fill_doc_list(TString_array& list_docs); TMovimento_estr(TSheet_field& sf, int row); TMovimento_estr(const long numreg); TMovimento_estr (const TMovimento_estr & m) { copy(m); } TMovimento_estr(TISAM_recordset & mov, TipoIVA tipo, bool escl); ~TMovimento_estr() {} }; long find_movcoll(long numreg); // ma serve ?? class TEstrazione : public TObject { drd _head; TArray _movs; // TMovimento_estr TLog_report * _log; bool _escluso; const TString _descr; bool _has_cartacei; TFilename _spotlite_path; /** Aggiorna stato estrazione. Utilizzato ad esempio dopo la diagnostica per riportare * il nuovo stato sul db. */ bool update_drd_stato_estr(); const char* caus_sos(const TLocalisamfile& mov, TipoIVA iva); void check_annessi(TMovimento_estr& mov); // Controllo se ci sono tutti gli annessi obbligatori. // Controllo se esistono tutti gli annessi cartacei obbligatori e se ci sono annessi reverse charge li genero. bool check_annessi_oblig(TMovimento_estr& mov, TToken_string& ann_nexist); bool check_cartaceo_acq(TMovimento_estr& movimento); static bool check_documento_vendita(const TLocalisamfile& mov, bool& exist_doc); /** CHECK RIFERIMENTO FPPRO * Per le fatture di acquisto controllo se ho il riferimento nell'FPPRO. * Altrimenti cerco di capire se riesco a trovare il corrispondente del movimento * nell'FPPRO ("Guessing"). * \return \a correct se ho gia' il riferimento e corrisponde effettivamente. * \return \a reg_with_err se ho il riferimento ma la corrispondenza e' sbagliata. * \return \a guessed se non ho il riferimento ma sono riuscito a trovarlo a manina. * \return \a no_guessed se non avevo il riferimento e non sono riuscito a trovarlo. * \return \a not_fa se il movimento passato non è una fattura. */ static state_fppro check_fppro(int numreg); bool check_periodo_def() const; void copy_file_to_webapp_fld(TMovimento_estr& movimento) const; void fill_id(const TRectype& clifo, TString& statopaiv, TString& idfisc, TString& paiv, TString& codfis); TipoIVA get_tipoiva() const { return _head.tipo_doc == 'A' ? iva_acquisti : iva_vendite; } bool is_doc_xml(const TRectype& mov); bool load_docs(TMovimento_estr& movimento) { return movimento.load_docs(); } // Se il movimento e' di vendita e ha i riferimenti al documento generatore provo a stamparlo con ve, e lo inserisco tra i cartacei F9. // bool stampa_documento(const TMovimento_estr& movimento, TFilename& file); bool grab_pdf_from_spotlite(const TMovimento_estr& movimento, TFilename& file) const; public: static bool make_prosp_int_revc(int numreg, TAnnesso * TAnnesso); private: static TString& drd_attr(); TString& drd_tovalues() const; bool insert_into_drd(); /**< Scrittura testata estrazione. Tabella F9DRD. */ bool insert_into_f9movestr(); /**< Scrittura su db dell'elenco di movimenti presi. */ bool export_error_list(); /**< Esporta sheet controllo fatture sul db. */ /** Controlla ultimo id estrazione della giornata e in base al tipo di estrazione, * genera il progressivo seguente. Chiamata da \a estrai() e \a estrai_single(). * \return Nuovo id estrazione. */ TString next_estr_today(char tipo) const; static bool pura_iva(const TRectype& mov); void write_errorsql_log(const TString& query); public: void add_mov(TMovimento_estr * movimento) { _movs.add(movimento); } /** DIAGNOSTICA GESTIONALE. * Controllo lo stato delle fatture: * Per le fatt. acquisto non collegate a fppro cerca di agganciarle. * Le fatture di vendita devono essere collegate ad un documento originario. * Automaticamente aggiorna lo stato nella dell'estrazione, anche sul db (chiama /a aggiorna_stato()). * * \return D_GEST_OK (03) se non ci sono errori e l'estrazione puo' continuare. * \return D_GEST_ERR (02) se la diagnostica ha riportato degli errori. */ const char* diagnostica_mov(); /** Estrazione per pacchetti "normali" (non da esclusi). * Viene chiamata dall'handler estrai_handler: bottone estrai nella maschera estrazione. * * \return estr_ok (1) Se l'estrazione e' avvenuta senza errori. * \return estr_err_db_iva (0) Errore scrittura database iva. * \return estr_stop (-1) Non esistono movimenti estraibili in quel periodo, o periodo sovrapposto ad altra estrazione. * \return estr_diag_err (-2) La diagnostica ha riportato errori. * \return estr_err_db_drd (-99) Errore scrittura F9DRD. */ result_estr estrai(); /** Estrazione dati IVA sia per pacch. normali che per esclusi. Scrittura tabella F9IVA. * \param escluso Settare a true se si sta estraendo un movimento escluso (estrazione pacchetto singolo, see estrai_single()). * \return true Scrittura sul db senza errori. * \return false Errore scrittura db. */ bool estrazione_iva(bool escluso = false); bool exist_prov() const; /**< Controllo che esista per questo stesso periodo una estrazione provvisoria. */ /** Controllo se esiste un periodo antecedente a questa estrazione che non e' mai stato estratto definitivamente. */ bool gap_periodo() const; // Getters TString get_id_estr() const { return _head.id_estr; } TString4 get_stato_estr() const { return _head.stato_estr; } const TArray & get_movs() const { return _movs; } // Setters void set_provvisorio(bool flag_prov) { _head.flag_prov = flag_prov; } void set_dataini(const TDate& dal) { _head.dal = dal; } void set_dataend(const TDate& al) { _head.al = al; } void set_dates(); // Solo se e' escluso void set_tipodoc(char tipodoc) { _head.tipo_doc = tipodoc; } void set_ambiente(const TString& ambiente) { _head.cod_soc = ambiente; } void set_descr(const TString& descr) { _head.descr = descr; } void set_addrcart(const TString& addrcart) { _head.addr_cart = addrcart; } TEstrazione(const TString& ambiente, bool flag_prov, char tipodoc, const TString& descr, const TString& addrcart, bool escluso, TFilename& spotlite_path, TLog_report * log, const TDate* dal = nullptr, const TDate* al = nullptr, bool has_cartacei = false); ~TEstrazione() {} }; class TF9_dberr { TString _str; TString _insert; TLog_report * _log; protected: void add_str(const TString& string); void add_num(const long& num); void write_sqlerrlog(const TString& query) const; public: void add(const TString& string); void add(const TDate& date); void add(const char* string) { add(TString(string)); } void add(long num); void add() { add_str("NULL"); } bool send(); TF9_dberr(TLog_report * log); }; bool dberr_del_err(const TString& codsoc, const TString& id_estr, int numreg); char dberr_get_err(const TString& codsoc, const TString& id_estr, TArray& controllo_mov); class TIva_insert_prepared_stat { TAssoc_array _fields; // TString bool _ok{ true }; TString _query; void add_value(const char* field, const TString& value) { _fields.add(field, value); } void write(); public: void add(const char* field, const TString& str, int len = -1); void add(const char* field, const char* str, int len = -1); void add(const char* field, const TDate& date); void add(const char* field, char c); void add(const char* field, long l); void add(const char* field, const int n) { add(field, (long)n); } void add_getdate(const char* field) { _fields.add(field, "GETDATE()"); } bool get(TString& query); void reset(); }; bool doc_already_exists(const TFilename& file, long& numreg); const TString & get_full_path_file_cartaceo(const TString& filename); class TF9_doccart { public: static bool add_cart(const TFilename& file, long numreg, bool is_annesso = false, const TString& catannpadre = "", const TString& catdocann = "", bool suppress_errors = true); bool doc_already_exists(const TFilename& file, long & numreg, bool& TAnnesso); bool mov2doc(long numreg, TFilename& doc); bool mov2listann(long numreg, TMovimento_estr& movimento, TString_array & list_annessi); bool mov2listann_vect(const long numreg, TArray & list_annessi); bool load_docs(long numreg, TMovimento_estr& movimento); TF9_doccart() { } }; /////////////////////////////////////////////////////////////////////////////// // TProspetto_recset /////////////////////////////////////////////////////////////////////////////// class TProspetto_recset final : public TSQL_recordset { TString _query; TString* _numreg; TString* _today; TString* _ragsoc; TString* _address; TString* _cap; TString* _citta; TString* _provin; TString* _codfisc; TString* _partiva; TString* _ndoc; TString* _datadoc; TString* _totdoc; TString* _codforn; TString* _ragsocforn; TString* _addrforn; TString* _capforn; TString* _cittaforn; TString* _provinforn; TString* _partivaforn; TString* _regacq; TString* _protivaacq; TString* _dataregacq; real _totale; real _totimponibile; real _totimposta; static void format_string(TString& str_out, const TString& str) { str_out.cut(0) << "'" << check_str(str) << "'"; } static void format_string(TString& str_out, const char* str) { format_string(str_out, TString(str)); } static void format_string(TString& str_out, const TDate& date) { TString dt; dt << date.date2ansi(); format_string(str_out, dt); } void precarica_tabelle(); public: const TString& get_query() const { return _query; } static void get_sum_imponibile_imposta(long numreg_ven, real& s_imponibili, real& s_imposte); TProspetto_recset(long numreg_acq, long numreg_ven); ~TProspetto_recset(); }; class TF9Prospetto_integr { static constexpr const char* _name = "f9ProspIntegr"; TReport_book _book; const TFilename _f_report; TRecnotype _items; TReport _rep; static TFilename get_path_rep(); public: bool export_pdf(TFilename& tmp); const char* make_name_rep(); bool preview(); const TFilename& filename() const { return _rep.filename(); } bool operator()(long numreg_acq, long numreg_ven); TF9Prospetto_integr(); }; #endif // #ifndef __F901001_H