campo-sirio/src/f9/f9lib.h
Simone Palacino cb5a7ffe65 Patch level : 12.0 986
Files correlati     : f90.exe
Commento            :
- Modifica creazione query per creazione prospetto integrativo: aggiunti doppi apici.
- Aggiunta possibilita' di salvare messaggio di errore in sqlite.
2020-07-29 17:45:19 +02:00

580 lines
20 KiB
C++
Raw Blame History

#ifndef __F901001_H
#define __F901001_H
#include <map>
#include <set>
#include <vector>
#include "strings.h"
#include "date.h"
#include "real.h"
#include "cglib.h"
#include "sheet.h"
#include "sqlset.h"
#include "reprint.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 TDate today(TODAY);
struct annesso_t
{
TString numreg; // TString ez-pz
TString filename;
TString catdocpad;
TString catdocann;
TDate loaddate;
TString user;
};
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 TCategorie_doc
{
public:
struct classe_doc
{
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, ...).
};
struct annesso
{
TString catdocpadre;
TString catdoc; // Codice cat. documentale.
TString descr; // Descrizione documento.
TString opcee; // { RV | DC } - Usato come classificazione annesso (Reverse, ann. cartaceo).
bool obblig{ false }; // Definisce se deve essere per forza presente l'annesso.
};
private:
std::vector<std::shared_ptr<classe_doc>> _rows;
std::vector<std::pair<TString, std::shared_ptr<TArray_sheet>>> _sheets_annessi;
std::shared_ptr<TArray_sheet> _sheet_catdocs;
std::shared_ptr<std::set<TString>> _name_catdocs;
int _mode_sheet;
std::shared_ptr<classe_doc> find_causcont(const TString& caus); // OK
std::shared_ptr<classe_doc> find_tipodoc(const TString& tipodoc); // OK
std::vector<pair<TString, std::shared_ptr<TArray_sheet>>>::iterator find_sheet_annessi(const TString& catdoc); // OK
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:
std::map<TString, annesso> _rows_annessi;
std::map<TString, annesso>::iterator find_annesso(const TString& catdoc_padre, const char* catdoc_ann);
public:
void add_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);
void del_annesso(const TString& catdoc, const char* catdoc_ann);
bool get_ann(const TString& catann, _Out_ annesso& _Annesso_out);
TString_array get_array_ann(const TString& catdoc);
TString_array get_array_rows(bool traduci = false);
std::shared_ptr<classe_doc> get_classe_doc(const TString& catdoc);
std::set<TString>& get_name_catdocs() { get_sheet_catdocs(); return *_name_catdocs; }
std::shared_ptr<TArray_sheet> get_sheet_catdocs();
std::shared_ptr<TArray_sheet> get_sheet_ann(const TString& catdoc);
std::shared_ptr<classe_doc> mov2cat(int numreg);
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();
};
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);
};
inline TCategorie_doc& categorie_doc()
{
static unique_ptr<TCategorie_doc> cd = nullptr;
if (cd == nullptr)
cd = make_unique<TCategorie_doc>();
return *cd;
}
struct movimento_t
{
enum err_mov
{
no_err, // Estratto normalmente.
escluso, // Movimento con flag escluso.
no_catdoc, // Nessuna cat. doc. riconosciuta per questo movimento, o non e' una fattura.
no_doc, // Il mov. di vendita non ha un documento generatore.
notfound_elet, // Non trovata fatt. elettronica mov vendita.
no_fa, // Movimento di acquisto non e' una fattura.
no_fv, // Movimento di vendita non e' una fattura.
no_cartaceo, // Movimento cartaceo che non ha bisogno di essere estratto.
pura_iva, // Movimento di sola IVA (integrazione Rev. Charge)
no_filecart, // Il documento cartaceo non ha associato un file, o questo non e' stato trovato.
annesso_nexist // Un annesso obbligatorio e' mancante.
};
bool err{ false };
int numreg;
TDate datareg;
TDate datadoc;
TString codcaus;
int meseliq;
TString numdoc;
real tot;
int codcf;
TString ragsoc;
TString reg_protiva;
TString descr;
state_fppro state{ null_state };
TString descr_err{}; // Messaggio di errore visibile dal controllo estrazione.
bool estratto{ true };
err_mov descr_estr{ no_err }; // Messaggio di informazioni visibile dal 'Apri Estr.'
std::shared_ptr<TCategorie_doc::classe_doc> catdoc{ nullptr };
bool cartaceo{ false };
TFilename nomefilecart{};
vector<annesso_t> annessi{};
static const char* err_mov2name(const err_mov descr_estr)
{
switch (descr_estr)
{
case no_err:
return "OK";
case escluso:
return "Il movimento e' segnato come escluso. Saltato.";
case no_catdoc:
return "Nessuna categoria documentale riconosciuta per questo movimento, o non e' una fattura.";
case no_doc:
return "Il mov. di vendita non ha un documento generatore";
case notfound_elet:
return "Non trovata fatt. elettronica mov vendita";
case no_fa:
return "Questo movimento di acquisto non e' una fattura";
case no_fv:
return "Movimento di vendita non e' una fattura.";
case no_cartaceo:
return "Movimento cartaceo che non ha bisogno di essere estratto";
case pura_iva:
return "Movimento di sola IVA. (Le integrazioni Rev. Charge sono gestite come annessi alle vendite)";
case annesso_nexist:
return "Un annesso obbligatorio e' mancante.";
default: return "";
}
}
const char* get_descr_estr() const
{
return err_mov2name(descr_estr);
}
TString get(const int i) const
{
TString a;
switch (i)
{
case 0: return err;
case 1: return a << numreg;
case 2: return (const char*)datareg;
case 3: return (const char*)datadoc;
case 4: return codcaus;
case 5: return a << meseliq;
case 6: return numdoc;
case 7:
a << tot;
if (a == "0")
a << ".0";
return a;
case 8: return a << codcf;
case 9: return ragsoc;
case 10: return reg_protiva;
case 11: return descr;
case 14: return descr_err;
default: return "";
}
}
bool is_cartaceo() const { return false; } // todo
};
class TEstrazione : public TObject
{
drd _head;
vector<movimento_t> _movs;
ofstream* _error_sql;
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;
static const char* caus_sos(const TLocalisamfile& mov, TipoIVA iva);
static void check_annessi(movimento_t& mov_i, int numreg); // 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.
static bool check_annessi_oblig(const TString& catdoc, int numreg, _Out_ TToken_string& ann_nexist);
static bool check_cartaceo_acq(const movimento_t& movimento);
static bool check_documento_vendita(const TLocalisamfile& mov, _Out_ 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 <20> una fattura.
*/
static state_fppro check_fppro(int numreg);
bool check_periodo_def() const;
void copy_file_to_webapp_fld(const movimento_t& movimento) const;
static void fill_id(TLocalisamfile& clifo, TString& statopaiv, TString& idfisc, TString& paiv, TString& codfis);
TipoIVA get_tipoiva() const { return _head.tipo_doc == 'A' ? iva_acquisti : iva_vendite; }
static bool is_doc_xml(const TLocalisamfile& mov);
static bool find_movcoll(int numreg, _Out_ TString& numreg_rev_vend);
static bool load_annessi(movimento_t& movimento);
// 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.
static bool stampa_documento(const movimento_t& movimento, TFilename& file);
bool grab_pdf_from_spotlite(const movimento_t& movimento, TFilename& file) const;
public:
static bool make_prosp_int_revc(int numreg, TCategorie_doc::annesso& annesso);
private:
static TString& drd_attr();
TString& drd_tovalues() const;
bool insert_into_drd() const; /**< Scrittura testata estrazione. Tabella F9DRD. */
bool insert_into_f9movestr() const; /**< Scrittura su db dell'elenco di movimenti presi. */
bool export_error_list() const; /**< 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 TLocalisamfile& mov);
void write_errorsql_log(const TString& query) const;
public:
void add_mov(const movimento_t& 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 vector<movimento_t>& 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, const TDate* dal = nullptr, const TDate* al = nullptr, bool has_cartacei = false);
};
class TF9_dberr
{
TString _str;
TString _insert;
ofstream* _fout;
protected:
void add_str(const TString& string);
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();
static bool del_err(const TString& codsoc, const TString& id_estr, int numreg);
static char get_errori(const TString& codsoc, const TString& id_estr, vector<TToken_string>& controllo_mov);
TF9_dberr();
};
class TIva_insert_prepared_stat
{
vector<pair<TString, TString>> _fields;
bool _ok{ true };
TString _query;
void add_value(const char* field, const TString& 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);
bool get(TString& query);
void reset();
};
class TF9_doccart
{
TLocalisamfile _tdocs;
TLocalisamfile _tannessi;
public:
static bool add_cart(const TFilename& file, const TString& numreg, bool is_annesso = false,
const TString& catannpadre = "", const TString& catdocann = "", bool suppress_errors = true);
bool doc_already_exists(const TFilename& file, _Out_ TString& numreg, _Out_ bool& annesso);
bool mov2doc(const TString& numreg, _Out_ TFilename& doc);
bool mov2listann(const TString& numreg, _Out_ TString_array& list_annessi);
bool mov2listann_vect(const TString& numreg, _Out_ vector<annesso_t>& list_annessi);
static TString get_full_path_file_cartaceo(const TString& filename)
{
return TString() << TFilename(F9CONF.get_addr_cart()).slash_terminate() << filename;
}
TF9_doccart() : _tdocs(LF_F9DOCS), _tannessi(LF_F9ANNESSI) { }
};
///////////////////////////////////////////////////////////////////////////////
// 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;
TString* _totale;
TString* _totimponibile;
TString* _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(const char* numreg_ven, real& s_imponibili, real& s_imposte);
TProspetto_recset(const char* numreg_acq, const char* 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()(const char* numreg_acq, const char* numreg_ven);
TF9Prospetto_integr();
};
#endif // #ifndef __F901001_H