campo-sirio/src/f9/f9lib.h
Simone Men 281d673611 Merge branch 'R12.00.1136.F9' into 'R12.00.1136'
Merge Archiviazione

See merge request sirio/CAMPO/campo!5
2022-11-24 14:46:49 +00:00

643 lines
24 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 "../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 <20> 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 <20> 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