campo-sirio/src/f9/f9lib01.cpp
Alessandro Bonazzi a898b955ca Patch level : 12.0 1066
Files correlati     : ce3.exe ce3900.msk rimosso ce3900b.rep
Commento        :

corretta la ricerca della causale quando è impostato il tipo documento SDI.

Interno :

Controllare un pò di contabilizzazioni
2021-07-01 08:54:25 +02:00

1769 lines
55 KiB
C++

//#include <Windows.h>
#include "f9lib.h"
#include "../f1/f1lib.h"
#include "f901tab.h"
#include "progind.h"
#include "clifo.h"
#include "../cg/cglib.h"
#include "mov.h"
#include "../fp/fplib.h"
#include "annessif9.h"
#include "dongle.h"
#include "execp.h"
#define MODE_SHEETS 0xC
statistics _stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
///////////////////////////////////////////////////////////////////////////////
// TEstrazione
///////////////////////////////////////////////////////////////////////////////
const char* TEstrazione::caus_sos(const TLocalisamfile& mov, const TipoIVA iva)
{
if (iva == iva_acquisti)
{
TToken_string keys(mov.get(MOV_KEYFPPRO));
fppro_db().set_keys(keys);
return fppro_db().get_tipodoc();
}
if (iva == iva_vendite)
{
const TDocumento doc(mov.get(MOV_DPROVV)[0], mov.get_int(MOV_DANNO), mov.get(MOV_DCODNUM), mov.get_int(MOV_DNDOC));
static TString tipo_doc_sdi;
return tipo_doc_sdi = doc.tipo().tipo_doc_sdi();
}
return "";
}
void TEstrazione::check_annessi(movimento_t& mov_i, const int numreg)
{
TToken_string ann_nexist;
if (!check_annessi_oblig(mov_i.catdoc->catdoc, numreg, ann_nexist))
{
TString msg_annessi_mancanti("Annessi obligatori mancanti: ");
for (int i = 0; i < ann_nexist.items(); ++i)
msg_annessi_mancanti << ann_nexist.get() << " ";
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = msg_annessi_mancanti;
mov_i.descr_estr = movimento_t::annesso_nexist;
}
else
{
load_annessi(mov_i);
}
}
bool TEstrazione::check_annessi_oblig(const TString& catdoc, const int numreg, _Out_ TToken_string& ann_nexist)
{
ann_nexist.destroy(-1);
const TString_array lista_cat_annessi = categorie_doc().get_array_ann(catdoc); // Lista cat annessi
TF9_doccart file_cart;
std::vector<annesso_t> list_file_ann; // Lista file annessi
file_cart.mov2listann_vect(TString() << numreg, list_file_ann);
bool ok_ann = true;
FOR_EACH_ARRAY_ITEM(lista_cat_annessi, nr, ann)
{
TCategorie_doc::annesso annesso;
const bool ok_cat = categorie_doc().get_ann(catdoc,*(TToken_string*)ann, annesso);
// Ignoro il flag obbligatorio per il prospetto di reverse charge
if (ok_cat && annesso.obblig && annesso.opcee != "RC")
{
// Controllo che esista l'annesso per questo mov.
bool exist = false;
for (auto f_ann = list_file_ann.begin(); f_ann != list_file_ann.end(); ++f_ann)
{
if (f_ann->catdocann == *(TToken_string*)ann)
{
exist = true;
break;
}
}
ok_ann &= exist;
if (!exist)
ann_nexist.add(*(TToken_string*)ann);
}
else if(ok_cat && annesso.opcee == "RC")
{
// Generazione prospetto integrativo.
const bool ok = make_prosp_int_revc(numreg, annesso);
if (!ok)
ann_nexist.add(TString() << "Prospetto integrativo (" << annesso.catdoc << ")");
ok_ann &= ok;
}
}
return ok_ann;
}
bool TEstrazione::check_cartaceo_acq(const movimento_t& movimento)
{
TF9_doccart filecart;
TFilename file;
TString reg; reg << movimento.numreg;
return filecart.mov2doc(reg, file) && file.exist();
}
bool TEstrazione::check_documento_vendita(const TLocalisamfile& mov, _Out_ bool& exist_doc)
{
if (!mov.get(MOV_DPROVV).empty() && !mov.get(MOV_DANNO).empty() && !mov.get(MOV_DCODNUM).empty() && !mov.get(MOV_DNDOC).empty())
{
TString hfatt(20), bfatt(50), query;
const TDocumento doc(mov.get(MOV_DPROVV)[0], mov.get_int(MOV_DANNO), mov.get(MOV_DCODNUM), mov.get_int(MOV_DNDOC));
exist_doc = true;
if (chiave_paf(doc, hfatt, bfatt))
{
query << "SELECT * FROM PAF0100F WHERE P1_KEYHEADERFATT = '" << hfatt << "' AND P1_KEYBODYFATT = '" << bfatt << "';";
fp_db().sq_set_exec(query);
return fp_db().sq_items() > 0;
}
}
else
exist_doc = false;
return false;
}
state_fppro TEstrazione::check_fppro(int numreg)
{
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
if (mov.read() == NOERR && check_causale(mov.get(MOV_CODCAUS)))
{
// Controllo se ho i riferimenti all'FPPRO e verifico che sia tutto ok
const TString& keys_fppro = mov.get(MOV_KEYFPPRO);
if (keys_fppro.full())
{
TToken_string keys(keys_fppro, ';');
if (fppro_db().check_reg(keys, numreg))
return correct;
TString err(fppro_db().get_last_error());
if (!err.empty())
{
error_box(err.cut(0) << "Errore durante il controllo del movimento n. " << numreg << "\n" << err);
return err_read_db;
}
return reg_with_err;
}
else // Se non ho i riferimenti faccio guessing
{
if (fppro_db().guess_the_doc(mov))
return guessed;
return no_guessed;
}
}
return not_fa;
}
bool TEstrazione::check_periodo_def() const
{
TString query;
// Controllo se ci sono estrazioni (definitive) che si sovrappongono di periodo (con lo stesso tipo) e che non siano in stato di errore
// Nel caso di stato di errore e' invece possibile la ri-estrazione
query << "SELECT *\nFROM " F9_DRD "\n"
"WHERE " DRD_CODSOC " = '" << _head.cod_soc << "' AND " DRD_DATAA " >= '" << _head.dal.date2ansi() << "' AND " DRD_DATADA " <= '" <<
_head.al.date2ansi() << "' AND " DRD_FLAG_PD " = 'D' AND\n " DRD_STATO " <> '" D_GEST_ERR "' AND " DRD_STATO " <> '" D_WA_ERR "' AND "
DRD_STATO " <> '" D_ERR_SOS "' AND " DRD_TIPODOC " = '" << _head.tipo_doc << "';";
fp_db().sq_set_exec(query);
return fp_db().sq_items() == 0;
}
void TEstrazione::copy_file_to_webapp_fld(const movimento_t& movimento) const
{
// f9pwa + ambiente + idlancio(ID drd) + categoria_documento(drt) + nome_documento
TFilename base(F9CONF.get_addr_doc_loc());
base.add(_head.cod_soc).add(_head.id_estr).slash_terminate();
TToken_string categorie;
TToken_string files;
if(movimento.cartaceo && movimento.catdoc != nullptr)
{
categorie.add(movimento.catdoc->catdoc, 0);
files.add(movimento.nomefilecart, 0);
}
if(!movimento.annessi.empty())
{
for (auto it = movimento.annessi.begin(); it != movimento.annessi.end(); ++it)
{
categorie.add(it->catdocann);
files.add(TF9_doccart::get_full_path_file_cartaceo(it->filename));
}
}
#ifdef DBG
CHECK(files.items() == categorie.items(), "copy_file_to_webapp_fld: Numero di file diverso dal numero di categorie");
#endif
for(int i = 0; i < files.items(); ++i)
{
TFilename file = files.get(i);
TFilename dest(base);
dest.add(categorie.get(i)).add(file.name());
make_dir(dest.path());
const bool f = fcopy(file, dest);
if (!f)
error_box("Errore nel copiare il file nella cartella di destinazione: %s", (const char*)dest);
}
}
void TEstrazione::fill_id(TLocalisamfile& clifo, TString& statopaiv, TString& idfisc, TString& paiv, TString& codfis)
{
idfisc.cut(0);
statopaiv = clifo.get(CLI_STATOPAIV);
paiv = clifo.get(CLI_PAIV);
codfis = clifo.get(CLI_COFI);
if (IS_ITALIANO(statopaiv))
{
// Se ho un codice fiscale che inizia per 8 o 9 e' come un privato e devo considerarlo solo come codice fiscale senza partita IVA.
if (paiv.full())
{
if (paiv.len() == 11 && (paiv[0] == '8' || paiv[0] == '9'))
{
codfis = paiv;
paiv.cut(0);
}
}
else if (codfis.full() && codfis.len() == 11 && (codfis[0] == '8' || codfis[0] == '9'))
paiv.cut(0);
}
if (paiv == "0")
paiv.cut(0);
if (IS_ITALIANO(statopaiv))
{
idfisc << "IT";
if (paiv.full()) // Se non ho la partita IVA e' privato quindi non metto niente solo cod. ISO
{
const int len = paiv.len();
for (int i = 0; i < 11 - len; ++i) // Siccome e' numerico mi trancia via le prime cifre 0.
paiv.add_front("0");
idfisc << paiv;
}
}
else // Esteri
{
idfisc << statopaiv;
if (codfis.full())
idfisc << codfis;
else
idfisc << paiv;
}
}
bool TEstrazione::is_doc_xml(const TLocalisamfile& mov)
{
const TString& tipocf = mov.get(MOV_TIPO);
const TString& codcf = mov.get(MOV_CODCF);
TLocalisamfile clifo(LF_CLIFO);
clifo.put(CLI_TIPOCF, tipocf);
clifo.put(CLI_CODCF, codcf);
clifo.read();
const TString& statopaiv = clifo.get(CLI_STATOPAIV);
return (IS_ITALIANO(statopaiv)) && clifo.get(CLI_COMCF) != "B513"; // Campione d'Italia
}
bool TEstrazione::find_movcoll(const int numreg, _Out_ TString& numreg_rev_vend)
{
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
mov.read();
const TCausale& cau = cached_causale(mov.get(MOV_CODCAUS), mov.get_int(MOV_ANNOES));
const TString4 cau_reg = cau.causale_reg_iva();
const TString numdoc = mov.get(MOV_NUMDOC);
TString query("USE ");
query << LF_MOV << " KEY 1 SELECT " << MOV_CODCAUS << "==\"" << cau_reg << "\"\nFROM " << MOV_NUMREG << "==" << numreg;
TISAM_recordset mov_rs(query);
long movcoll = 0L;
for (bool ok = mov_rs.move_first(); ok; ok = mov_rs.move_next())
{
TRectype& curr = (TRectype&)mov_rs.cursor()->curr();
const long movcoll_found = curr.get_long(MOV_MOVCOLL);
if (curr.get(MOV_NUMDOC) == numdoc && (movcoll_found == 0L || movcoll_found == numreg))
{
movcoll = mov_rs.get(MOV_NUMREG).as_int();
curr.put(MOV_MOVCOLL, numreg);
break;
}
}
numreg_rev_vend.cut(0) << movcoll;
return numreg_rev_vend.full();
}
bool TEstrazione::load_annessi(movimento_t& movimento)
{
TF9_doccart doccart;
TString numreg; numreg << movimento.numreg;
return doccart.mov2listann_vect(numreg, movimento.annessi);
}
bool TEstrazione::stampa_documento(const movimento_t& movimento, TFilename& file)
{
bool ok = false;
// 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.
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, movimento.numreg);
if (mov.read() == NOERR &&
!mov.get(MOV_DPROVV).empty() && !mov.get(MOV_DANNO).empty() && !mov.get(MOV_DCODNUM).empty() && !mov.get(MOV_DNDOC).empty())
{
const TDocumento doc(mov.get(MOV_DPROVV)[0], mov.get_int(MOV_DANNO), mov.get(MOV_DCODNUM), mov.get_int(MOV_DNDOC));
if(doc.ok() && dongle().active(RSAUT))
{
// ve1 -2 {CODNUM} {ANNO} {PROVV} {NDOC}(-{ANDOC}) {TIPO_ELABORAZIONE} {TIPO_STAMPA} {NUM_COPIE} {ARCHIVIAZIONE}
static TString commandline;
commandline.cut(0) << "ve1 -2 " << doc.get(DOC_CODNUM) << ' ' << doc.get(DOC_ANNO)
<< ' ' << doc.get(DOC_PROVV) << ' ' << doc.get(DOC_NDOC) << " X P 1 D"; // X: stampa su disco, P: provvisorio, 1: 1 copia, D: disabilita archiviazione
TExternal_app interattivo(commandline);
if (interattivo.run() == NOERR)
{
TFilename pdf; pdf.tempdir();
pdf << SLASH << doc.get(DOC_ANNO) << '_' << doc.get(DOC_CODNUM) << '_' << doc.get(DOC_NDOC) << ".pdf";
if (pdf.exist())
{
file.cut(0) << pdf;
TString numreg; numreg << movimento.numreg;
// Controllo anche se false perche' potrebbe esistere gia'.
if(!TF9_doccart::add_cart(file, numreg))
{
TF9_doccart filecart;
TFilename fdoc;
ok = filecart.mov2doc(numreg, fdoc) && fdoc.name() == file.name();
}
else
ok = true;
}
}
}
}
return ok;
}
bool TEstrazione::grab_pdf_from_spotlite(const movimento_t& movimento, TFilename& file) const
{
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, movimento.numreg);
if (mov.read() == NOERR &&
!mov.get(MOV_DPROVV).empty() && !mov.get(MOV_DANNO).empty() && !mov.get(MOV_DCODNUM).empty() && !mov.get(MOV_DNDOC).empty())
{
const TDocumento doc(mov.get(MOV_DPROVV)[0], mov.get_int(MOV_DANNO), mov.get(MOV_DCODNUM), mov.get_int(MOV_DNDOC));
if (doc.ok())
{
char buffer[34];
TString f_pdf; f_pdf << "ve1300_" << mov.get(MOV_DCODNUM) << "_";
sprintf_s(buffer, 34, "%010d", mov.get_long(MOV_DNDOC));
f_pdf << buffer << "_";
sprintf_s(buffer, 34, "%07d", doc.clifor().codice());
f_pdf << buffer << ".pdf";
TFilename doccart(_spotlite_path);
doccart.add(mov.get(MOV_DANNO));
doccart.add(prefix().name());
doccart.add(f_pdf);
if (doccart.exist())
{
file.cut(0);
file = doccart;
return true;
}
}
}
return false;
}
bool TEstrazione::make_prosp_int_revc(const int numreg, TCategorie_doc::annesso& annesso)
{
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
mov.read();
TString rev_vend = mov.get(MOV_MOVCOLL);
if((rev_vend.full() || find_movcoll(numreg, rev_vend)) && rev_vend != "0")
{
TF9Prospetto_integr prosp;
TString acq; acq << numreg;
if (prosp(acq, rev_vend))
{
// [ NUMREG][ CAT.ANN.].pdf
// [0000000][AAAAAAAAAA].pdf
TFilename tmp_file; tmp_file.tempdir();
TString name; name << format("%07d%10s", numreg, (const char*)annesso.catdoc);
name.replace(' ', '_');
tmp_file.add(name);
tmp_file.ext("pdf");
if(prosp.export_pdf(tmp_file))
{
// Sposto il file nella cartella dei documenti cartacei.
const TFilename newfile(TF9_doccart::get_full_path_file_cartaceo(tmp_file.name()));
// if (newfile.exist())
// DeleteFile(newfile);
fcopy(tmp_file, newfile);
// Controllo che non esista gia' altrimenti elimino il record
TF9_doccart doccart;
bool a;
TString numreg_old;
if (doccart.doc_already_exists(newfile, numreg_old, a))
{
TLocalisamfile lf_ann(LF_F9ANNESSI);
lf_ann.setkey(2);
lf_ann.put(F9A_FILENAME, newfile.name());
lf_ann.read();
lf_ann.remove();
lf_ann.zero();
}
// Registro il file come annesso RC
TLocalisamfile lf_ann(LF_F9ANNESSI);
lf_ann.put(F9A_NUMREG, numreg);
lf_ann.put(F9A_FILENAME, newfile.name());
lf_ann.put(F9A_CATDOCPAD, annesso.catdocpadre);
lf_ann.put(F9A_CATDOCANN, annesso.catdoc);
lf_ann.put(F9A_LOADDATE, TDate(TODAY));
lf_ann.put(F9A_USER, user());
bool ok = lf_ann.write() == NOERR;
ok &= lf_ann.rewrite() == NOERR;
if (!ok)
ok = yesno_box("Impossibile creare il prospetto integrativo per la registrazione n. %s.\nContinuare con l'estrazione?", (const char*)TString(numreg));
return ok;
}
}
}
return false;
}
TString& TEstrazione::drd_attr()
{
static TString attr;
attr.cut(0) << DRD_CODSOC ", " DRD_ID_EST ", " DRD_FLAG_PD ", " DRD_DESC
", " DRD_TIPODOC ", " DRD_DATADA ", " DRD_DATAA ", " DRD_UTENTE ", " DRD_TIME ", "
DRD_STATO ", " DRD_PERC;
return attr;
}
TString& TEstrazione::drd_tovalues() const
{
static TString str;
return str.cut(0) << "'" << _head.cod_soc << "', '" << _head.id_estr << "', '" << (_head.flag_prov ? "P" : "D") << "', '" << _head.descr <<
"', '" << _head.tipo_doc << "', '" << _head.dal.date2ansi() << "', '" << _head.al.date2ansi() << "', '" << _head.user << "', CURRENT_TIMESTAMP, '" <<
_head.stato_estr << "', '" << _head.addr_cart << "'";
}
bool TEstrazione::insert_into_drd() const
{
TString query;
query << "INSERT INTO " F9_DRD " ( " << drd_attr() << " ) \nVALUES ( " << drd_tovalues() << " );";
bool ok = fp_db().sq_set_exec(query);
ok = ok && fp_db().sq_commit();
if (!ok)
write_errorsql_log(query);
return ok;
}
bool TEstrazione::insert_into_f9movestr() const
{
TString query;
bool ok = true;
TProgress_monitor prog(_movs.size(), "Salvataggio informazioni estrazione", false);
for(auto it = _movs.begin(); it != _movs.end(); ++it)
{
if(!prog.add_status())
break;
query.cut(0) << "INSERT INTO " F9_MOVESTR " (" MES_CODSOC ", IDESTR, NUMREG, DATAREG, ESTRATTO, DESCR_ERR)\nVALUES " <<
" ('" << _head.cod_soc << "', '" << _head.id_estr << "', '" << it->numreg << "', '" << it->datareg.date2ansi() << "', " <<
(it->estratto ? "1" : "0") << ", '" << check_str(it->get_descr_estr()) << "')";
ok &= fp_db().sq_set_exec(query) && fp_db().sq_commit();
if (!ok)
{
write_errorsql_log(query);
break;
}
}
return ok;
}
bool TEstrazione::export_error_list() const
{
TF9_dberr dberr;
const vector<movimento_t>& movs = _movs;
bool ok = true;
int count = 0;
TProgress_monitor pg(movs.size(), "Scrittura movimenti in errore");
for (auto it = movs.begin(); it != movs.end(); ++it)
{
if (!pg.add_status())
break;
if (it->err)
{
dberr.add(_head.cod_soc);
dberr.add(_head.id_estr);
for (int i = 1; i < 15; i++)
{
TString string(it->get(i));
if (i == 2 || i == 3) // Sono obbligato a far cosi' per aggiungere le date
dberr.add(TDate(it->get(i)));
else if (string.full())
{
string.replace("'", "''");
dberr.add(string);
}
else
dberr.add(); // Se vuoto metto NULL
}
if (!(ok &= dberr.send()))
break;
++count;
}
}
return ok;
}
TString TEstrazione::next_estr_today(char tipo) const
{
char estr[] = { 0,0,0,0,0,0,0,0,0 };
TString query;
query << "SELECT TOP 1 SUBSTRING(" DRD_ID_EST ", 11, 8) AS IDESTR\n"
"FROM " F9_DRD "\n"
"WHERE " DRD_CODSOC " = '" << _head.cod_soc << "' AND\n"
DRD_ID_EST " LIKE '" << today.date2ansi() << "%'\n"
"ORDER BY IDESTR DESC";
fp_db().sq_set_exec(query);
const int last_estr = fp_db().sq_items() > 0 ? real(fp_db().sq_get("IDESTR")).integer() : -1;
if (last_estr < -1 || last_estr == 99999999)
{
ofstream fout; fout.open("f9err_nextestr.txt");
if (fout.is_open())
{
fout << "Errore progressivo nuova estrazione!\n" << today << "\nn:" << last_estr << "\n" << query << "\n";
fout.close();
}
TString msg;
fatal_box(msg << "database error: progressivo nuova estrazione. Ultima estrazione: " << last_estr);
}
sprintf_s(estr, 9, "%08d", last_estr + 1);
return TString(estr);
}
bool TEstrazione::pura_iva(const TLocalisamfile& mov)
{
if (TCausale(mov.get(MOV_CODCAUS), mov.get_date(MOV_DATAREG).year()).soloiva())
return true;
TMovimento_contabile* rel = new TMovimento_contabile();
rel->put(MOV_NUMREG, mov.get(MOV_NUMREG));
return rel->cg_rows() == 0;
}
void TEstrazione::write_errorsql_log(const TString& query) const
{
TString msg;
msg << query << "\n" <<
fp_db().sq_get_string_error() << "\n" <<
fp_db().sq_get_text_error();
if (_error_sql->is_open())
*_error_sql << msg << "\n\n";
#ifdef DBG
else
warning_box("Impossibile aprire il file f9_TEstrazione_error_sql.txt\nper scrivere errori scrittura db.");
#endif
}
TCategorie_doc& TEstrazione::categorie_doc(const bool reload)
{
static TCategorie_doc* _doc_cats = nullptr;
if (_doc_cats == nullptr)
_doc_cats = new TCategorie_doc();
else if (reload)
_doc_cats->reload();
return *_doc_cats;
}
// Public methods /////////////////////////////////////////////////////////////////////////////////////////////
void TEstrazione::add_mov(const movimento_t& movimento)
{
_movs.insert(_movs.end(), movimento);
}
bool TEstrazione::update_drd_stato_estr() const
{
bool ok;
do
{
TString query;
query << "UPDATE " F9_DRD "\n" \
"SET " DRD_STATO " = '" << _head.stato_estr << "'\n"
"WHERE " DRD_CODSOC " = '" << _head.cod_soc << "'"
" AND " DRD_ID_EST " = '" << _head.id_estr << "'"
" AND " DRD_FLAG_PD " = '" << (_head.flag_prov ? "P" : "D") << "'";
ok = fp_db().sq_set_exec(query);
ok = ok && fp_db().sq_commit();
if (!ok)
write_errorsql_log(query);
} while (!ok && yesno_box("Impossibile aggiornare stato dell'estrazione.\nRiprovare?"));
return ok;
}
const char* TEstrazione::diagnostica_mov()
{
categorie_doc(true);
bool ok = true;
const TipoIVA tipo = get_tipoiva();
_stats.total = _movs.size();
if (tipo == iva_acquisti)
{
// Controlli per le fatture di acquisto
TProgress_monitor bar(_movs.size(), "Controllo stato movimenti di acquisto");
for (auto it = _movs.begin(); it != _movs.end(); ++it)
{
if (!bar.add_status())
break;
movimento_t& mov_i = *it;
// Se gia' escluso passo avanti
if (!mov_i.estratto && mov_i.descr_estr == movimento_t::escluso)
continue;
if (!mov_i.err && mov_i.estratto)
{
const int numreg = mov_i.numreg;
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
mov.read();
mov_i.cartaceo = !is_doc_xml(mov);
const state_fppro res = check_fppro(numreg);
switch (res)
{
// OK
case guessed:
ok &= fppro_db().associa_mov(numreg);
case correct:
ok &= true;
mov_i.err = false;
mov_i.numdoc = fppro_db().get_numdoc();
break;
// ERRORS
// Errore non bloccante (skip)
case not_fa:
ok &= true;
mov_i.err = false;
mov_i.estratto = false;
mov_i.descr_estr = movimento_t::no_fa;
++_stats.fa_skip;
break;
// ERRORI BLOCCANTI
case reg_with_err:
ok &= false;
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = "Errore controllo movimento: associazione movimento con fattura elettronica passiva sbagliato.";
break;
case err_read_db:
ok &= false;
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = "Errore controllo movimento: errore lettura db.";
break;
case no_guessed:
// Controllo se esiste il cartaceo es. forfettari => la considero cartacea.
// Ma poi devo comunque avere il flag per l'esportazione dei cartacei
if(check_cartaceo_acq(mov_i))
{
ok &= true;
mov_i.err = false;
mov_i.cartaceo = true;
mov_i.estratto = true;
mov_i.descr_err = "";
mov_i.state = correct;
}
else
{
ok &= false;
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = "Non associato a fattura elettr. abbinamento automatico non riuscito. Abbinare manualmente, o escludere";
}
default: break;
}
if(mov_i.state == null_state)
mov_i.state = res;
if (mov_i.err) ++_stats.fa_err;
/* Per quelli che hanno passato il primo controllo errori controllo che debba essere estratto
* secondo le categorie documentali. */
if (mov_i.estratto)
{
if (!mov_i.err)
{
// Cerco la categoria documentale
std::shared_ptr<TCategorie_doc::classe_doc> cd = categorie_doc().mov2cat(mov_i.numreg);
mov_i.estratto = cd.get();
mov_i.descr_estr = cd ? movimento_t::no_err : movimento_t::no_catdoc;
mov_i.catdoc = cd;
if (mov_i.catdoc)
check_annessi(mov_i, numreg);
}
// Se cartaceo preparo il file.
if (F9CONF.get_has_cartexp()) // Se e' abilitata l'esportazione dei cartacei, altrimenti skip...
{
if (mov_i.cartaceo)
{
TF9_doccart filecart;
TFilename file;
TString reg; reg << it->numreg;
if (filecart.mov2doc(reg, file) && file.exist())
mov_i.nomefilecart << file;
else
{
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = "Non e' stato possibile reperire il file del documento cartaceo per questo movimento.";
mov_i.descr_estr = movimento_t::no_filecart;
}
}
else
{
ok &= true;
mov_i.err = false;
mov_i.estratto = false;
mov_i.descr_estr = movimento_t::no_cartaceo; // Cartaceo che non ha bisogno di essere estratto.
++_stats.fa_skip;
}
}
copy_file_to_webapp_fld(mov_i);
}
}
ok &= !mov_i.err;
}
}
else if (tipo == iva_vendite)
{
// Controlli per le fatture di vendita
TProgress_monitor bar(_movs.size(), "Controllo stato movimenti di vendita");
for (auto it = _movs.begin(); it != _movs.end(); ++it)
{
if (!bar.add_status())
break;
//TToken_string& row = *it;
movimento_t& mov_i = *it;
// Se escluso passo avanti
if (!mov_i.estratto && mov_i.descr_estr == movimento_t::escluso)
continue;
TString numreg; numreg << mov_i.numreg;
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
mov.read();
/* Controlli per vendite cambiati:
* Elettroniche solo quelle agli italiani, tutti gli altri sono cartacei
*/
if (!mov_i.err && mov_i.estratto)
{
mov_i.cartaceo = !is_doc_xml(mov);
unsigned short skip = 0;
if (!_has_cartacei && mov_i.cartaceo) skip |= 0x1;
else if (pura_iva(mov)) skip |= 0x2;
else if (mov_i.datadoc.empty() || mov_i.numdoc.empty()) skip |= 0x4;
if(skip)
{
++_stats.fv_cart_skip;
mov_i.err = false;
mov_i.estratto = false;
switch(skip)
{
case 0x1: mov_i.descr_estr = movimento_t::no_cartaceo; break;
case 0x2: mov_i.descr_estr = movimento_t::pura_iva; break;
case 0x4: mov_i.descr_estr = movimento_t::no_fv;
default: break;
}
}
/*else if(!mov_i.cartaceo && _has_checkvend && !check_documento_vendita(mov, exist_doc))
{
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = !exist_doc ?
"Il movimento non ha un documento generatore. (Escludere? o Rimuovere flag controllo vendite)"
: "Non e' stato trovato il documento elettronico nel database delle F.E. (Escludere? o Rimuovere flag controllo vendite)";
mov_i.descr_estr = !exist_doc ? movimento_t::no_doc : movimento_t::notfound_elet;
}*/
else
{
std::shared_ptr<TCategorie_doc::classe_doc> cd = categorie_doc().mov2cat(mov_i.numreg);
mov_i.err = false;
mov_i.estratto = cd.get();
mov_i.descr_estr = cd ? movimento_t::no_err : movimento_t::no_catdoc;
mov_i.catdoc = cd;
if (mov_i.catdoc)
check_annessi(mov_i, mov_i.numreg);
if (!mov_i.catdoc)
++_stats.fv_nocatdoc;
if (mov_i.err)
++_stats.fv_err;
else if (mov_i.estratto)
++_stats.fv_estr;
}
if (mov_i.estratto)
{
if (mov_i.cartaceo)
{
TF9_doccart filecart;
TFilename file;
TString reg; reg << it->numreg;
if (filecart.mov2doc(reg, file) && file.exist() || grab_pdf_from_spotlite(mov_i, file) && file.exist())
{
mov_i.nomefilecart << file;
}
else
{
mov_i.err = true;
mov_i.estratto = false;
mov_i.descr_err = "Non e' stato possibile reperire il file del documento cartaceo per questo movimento.";
mov_i.descr_estr = movimento_t::no_filecart;
}
}
copy_file_to_webapp_fld(mov_i);
}
}
ok &= !mov_i.err;
}
}
_head.stato_estr = ok ? D_GEST_OK : D_GEST_ERR;
return _head.stato_estr;
}
result_estr TEstrazione::estrai()
{
// Se non c'e' nessun movimento non sto nemmeno a scrivere il record di estrazione.
// Se estrazione definitiva controllo che il periodo non si sovrapponga alle altre estrazioni def.
// Do' errore ed esco subito.
if (_movs.empty())
{
warning_box("Non esistono movimenti estraibili per il periodo selezionato.");
return estr_stop;
}
if (!_escluso && !_head.flag_prov)
{
if (!check_periodo_def())
{
error_box("Attenzione e' stato inserito un periodo che si sovrappone\nad un'estrazione definitiva gia' esistente. Impossibile procedere.");
return estr_stop;
}
if (gap_periodo())
{
if (!noyes_box("Attenzione, e' stato saltato un periodo rispetto all'ultimo\n"
"estratto e quello selezionato, il quale rimarrebbe vuoto.\nContinuare comunque?"))
return estr_stop;
}
// Avviso nel caso in cui si stia facendo un'estrazione definitiva di un periodo di cui non si e' mai fatta
// una prova provvisoria.
if(!exist_prov())
{
if (!noyes_box("Attenzione, non e' mai stata fatta alcuna\nestrazione provvisoria per questo periodo.\nContinuare comunque?"))
return estr_stop;
}
}
// Non so come usare questi 18 caratteri...
// Uso dati anche se gia' noti in altri campi (I know..) + un numero incrementale.
_head.id_estr.cut(0) << today.date2ansi() << (_head.flag_prov ? "P" : "D") << (!_escluso ? "N" : "X") << next_estr_today(_head.tipo_doc);
_head.user = user();
// Eseguo controllo sui movimenti e segno in testata lo stato
_head.stato_estr = IN_DIAGN; // "01" che verra' quasi subito rimpiazzato dal risultato della diagnostica.
if (_escluso)
set_dates(); // Se escluso imposto data inizio e fine uguali
// Scrivo record estrazione (in stato '01': in diagnostica).
const bool ok = insert_into_drd();
if (!ok)
{
TString msg;
msg << "Errore database: impossibile scrivere nuova estrazione.\n"
<< fp_db().sq_get_text_error(false);
error_box(msg);
return estr_err_db_drd;
}
// Faccio partire la diagnostica e mi salvo il nuovo stato.
diagnostica_mov();
insert_into_f9movestr();
if (_head.stato_estr == D_GEST_ERR)
{
warning_box("Attenzione l'estrazione ha prodotto degli errori.\n"
"Controllare e correggere eventuali problemi\ndal Controllo Estrazione.");
// Se in errore, esporto lista errori sul db
if (!export_error_list())
warning_box("Errore scrittura db. Controllare log errori.");
update_drd_stato_estr();
return estr_diag_err; // Errore diagnostica gestionale
}
// Se va tutto ben fino a qui, posso andare a scrivere nella
// tabella IVA i movimenti. F9IVA
const result_estr res = estrazione_iva() ? estr_ok : estr_err_db_iva;
if (res == estr_err_db_iva)
_head.stato_estr = D_GEST_ERR;
update_drd_stato_estr();
return res;
}
bool TEstrazione::estrazione_iva(bool escluso)
{
TString statopaiv, idfisc, paiv, codfis;
bool stato = true;
TProgress_monitor bar(_movs.size(), "Estrazione dati IVA");
for (auto it = _movs.begin(); it != _movs.end() && stato; ++it)
{
if (!bar.add_status())
break;
if (!it->estratto)
continue;
TLocalisamfile mov(LF_MOV);
TLocalisamfile cli(LF_CLIFO);
mov.put(MOV_NUMREG, it->numreg);
mov.read();
cli.put(CLI_TIPOCF, mov.get(MOV_TIPO));
cli.put(CLI_CODCF, mov.get(MOV_CODCF));
cli.read();
const char tipodoc = _head.tipo_doc;
const TString& name_registro = TRegistro(TCausale(mov.get(MOV_CODCAUS), mov.get_date(MOV_DATAREG).year()).reg()).name();
fill_id(cli, statopaiv, idfisc, paiv, codfis);
TDate datadoc = mov.get_date(MOV_DATADOC);
TDate datareg = mov.get_date(MOV_DATAREG);
TIva_insert_prepared_stat iva_query;
iva_query.add(IVA_CODSOC, _head.cod_soc, 10);
iva_query.add(IVA_IDLAN, _head.id_estr, 18);
iva_query.add(IVA_FLAG_PD, _head.flag_prov ? 'P' : 'D');
iva_query.add(IVA_ANNOES, mov.get_int(MOV_ANNOES));
iva_query.add(IVA_GIVA, tipodoc);
iva_query.add(IVA_TIPOG, name_registro, 10);
iva_query.add(IVA_DOCXML, it->cartaceo ? 'N' : 'S');
iva_query.add(IVA_TIPOCF, mov.get_char(MOV_TIPO));
iva_query.add(IVA_CODCF, mov.get_long(MOV_CODCF));
iva_query.add(IVA_RAGSOC, cli.get(CLI_RAGSOC), 60);
iva_query.add(IVA_IDFISC, idfisc, 30);
iva_query.add(IVA_PIVA, paiv, 28);
iva_query.add(IVA_CODFIS, codfis, 16);
iva_query.add(IVA_CATDOC, it->catdoc->catdoc, 10);
iva_query.add(IVA_CAUSSOS, it->catdoc->caus_sost, 6);
iva_query.add(IVA_NUMDOC, it->numdoc, 20);
iva_query.add(IVA_DATADOC, datadoc);
iva_query.add(IVA_SEZIVA, mov.get(MOV_REG), 10);
iva_query.add(IVA_TIPOREG, "", 6);
iva_query.add(IVA_NPROT, mov.get(MOV_PROTIVA), 20);
iva_query.add(IVA_DATPROT, datareg);
/*if(is_autofattura(mov))
{
iva_query.add(IVA_FORNOR, "");
iva_query.add(IVA_REGOR, "");
iva_query.add(IVA_NUMOR, N ORI);
iva_query.add(IVA_DATAOR, TDate(20010101));
}*/
iva_query.add(IVA_CLASDOC, it->catdoc->class_sost, 10);
iva_query.add(IVA_NOMFD, it->nomefilecart.name(), 100);
// Load annessi...
if(!it->annessi.empty())
{
vector<annesso_t>& ann = it->annessi;
size_t i = 0;
const size_t size = ann.size();
iva_query.add(IVA_CLASAN1, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF1, ann[i++].filename, 100);
// HOW DID MY LIFE COME TO THIS?...
if (size > i)
{
iva_query.add(IVA_CLASAN2, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF2, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN3, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF3, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN4, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF4, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN5, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF5, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN4, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF4, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN6, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF6, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN7, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF7, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN8, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF8, ann[i++].filename, 100);
}
if (size > i)
{
iva_query.add(IVA_CLASAN9, ann[i].catdocann, 10);
iva_query.add(IVA_NOMF9, ann[i++].filename, 100);
}
}
iva_query.add(IVA_USERELA, user(), 10);
iva_query.add_getdate(IVA_TIMEELA);
if (_head.tipo_doc == 'A' && !it->cartaceo)
{
TToken_string keys(mov.get(MOV_KEYFPPRO), ';');
fppro_db().set_keys(keys);
iva_query.add(IVA_TIPPROT, fppro_db().get_tipoprot(), 2);
iva_query.add(IVA_ANNPROT, TVariant(fppro_db().get_annoprot()).as_int());
iva_query.add(IVA_NUMPROT, fppro_db().get_numprot(), 10); // Non controllo che sia in realta' un numero...
iva_query.add(IVA_TIMERIC, TDate(fppro_db().get_dataoraric()));
}
TString sql;
bool ok = iva_query.get(sql);
if (ok)
ok = fp_db().sq_set_exec(sql);
if (ok)
ok = fp_db().sq_commit();
if (!ok)
write_errorsql_log(sql);
stato &= ok;
}
return stato;
}
bool TEstrazione::exist_prov() const
{
TString query; query << "SELECT * FROM " F9_DRD "\n" <<
"WHERE " DRD_CODSOC " = '" << _head.cod_soc << "' AND " DRD_DATADA " = '" << _head.dal.date2ansi() << "'"
" AND " DRD_DATAA " = '" << _head.al.date2ansi() << "' AND " DRD_FLAG_PD " = 'P' AND " DRD_TIPODOC " = '" << _head.tipo_doc << "'";
const bool ok = fp_db().sq_set_exec(query);
return ok && fp_db().sq_items() > 0;
}
bool TEstrazione::gap_periodo() const
{
TString query; query << "SELECT " DRD_ID_EST " AS ID, " DRD_DATAA " AS DATA_A\n"
"FROM " F9_DRD "\n"
"WHERE " DRD_CODSOC " = '" << _head.cod_soc << "' AND " DRD_ID_EST " LIKE '%N%' AND " // '%N%' = Pacchetto normale
DRD_FLAG_PD " = 'D' AND " DRD_TIPODOC " = '" << _head.tipo_doc << "'\n"
"ORDER BY " DRD_DATAA " DESC";
const bool ok = fp_db().sq_set_exec(query);
return ok && fp_db().sq_items() > 0 && _head.dal - fp_db().sq_get_date("DATA_A") > 1;
}
void TEstrazione::set_dates()
{
if (_escluso)
{
set_dataini(_movs[0].datareg);
set_dataend(_movs[0].datareg);
}
}
TEstrazione::TEstrazione(const TString& ambiente, const bool flag_prov, const char tipodoc, const TString& descr,
const TString& addrcart, const bool escluso, TFilename& spotlite_path, const TDate* const dal, const TDate* const al, const bool has_cartacei)
: _descr(descr), _has_cartacei(has_cartacei), _spotlite_path(spotlite_path)
{
_head.cod_soc = ambiente;
_head.flag_prov = flag_prov;
_head.descr = descr;
_head.tipo_doc = tipodoc;
if (!escluso && dal != nullptr && al != nullptr)
{
_head.dal = *dal;
_head.al = *al;
}
_head.addr_cart = addrcart;
_escluso = escluso;
_error_sql = make_unique<ofstream>();
_error_sql->open("f9_TEstrazione_error_sql.txt");
// Svuoto log.
FILE* f = fopen("TF9Prospetto_integr_error.txt", "w");
fwrite("\n", sizeof(char), 1, f);
fclose(f);
}
//////////////////////////////////////////////////////
// TF9_dberr
//////////////////////////////////////////////////////
void TF9_dberr::add_str(const TString& string)
{
_insert.rtrim(1);
if (_insert[_insert.len() - 1] != '(')
_insert << ", ";
_insert << string << ")";
}
void TF9_dberr::write_sqlerrlog(const TString& query) const
{
if (_fout->is_open())
{
TString msg;
msg << query << "\n" <<
fp_db().sq_get_string_error() << "\n" <<
fp_db().sq_get_text_error();
*_fout << msg << "\n";
}
}
void TF9_dberr::add(const TString& string)
{
TString str;
add_str(str << "'" << string << "'");
}
void TF9_dberr::add(const TDate& date)
{
if (date.ok())
add(date.date2ansi());
else
add("00010101");
}
void TF9_dberr::add(const long num)
{
TString app;
app << num;
add(app);
}
bool TF9_dberr::send()
{
const bool ok = fp_db().sq_set_exec(_insert) && fp_db().sq_commit();
if(!ok)
write_sqlerrlog(_insert);
_insert.cut(0) << "INSERT INTO " F9_ERR " ("
ERR_CODSOC ", "
ERR_IDESTR ", "
ERR_NUMREG ", "
ERR_DATAREG ", "
ERR_DATADOC ", "
ERR_CODCAUS ", "
ERR_MESELIQ ", "
ERR_NUMDOC ", "
ERR_IMPTDOC ", "
ERR_FORN ", "
ERR_RAGSOC ", "
ERR_PROTIVA ", "
ERR_DESCR ", "
ERR_ESCLUDI ", "
ERR_ESCLUSO ", "
ERR_DESCERR ") VALUES ()";
return ok;
}
bool TF9_dberr::del_err(const TString& codsoc, const TString& id_estr, const int numreg)
{
TString query;
query << "DELETE FROM " F9_ERR
"\nWHERE " ERR_CODSOC " = '" << codsoc << "'"
"\nAND " ERR_IDESTR " = '" << id_estr << "' AND " ERR_NUMREG " = '" << numreg << "';";
return fp_db().sq_set_exec(query) && fp_db().sq_commit();
}
char TF9_dberr::get_errori(const TString& codsoc, const TString& id_estr, vector<TToken_string>& controllo_mov)
{
TString query;
query << "SELECT * FROM " F9_ERR
"\nWHERE " ERR_CODSOC " = '" << codsoc << "' AND "
ERR_IDESTR " = '" << id_estr << "';";
fp_db().sq_set_exec(query, false);
for (bool ok = fp_db().sq_next(); ok; ok = fp_db().sq_next())
{
TToken_string row("", '|');
row.add("X");
for (int i = 1; i < 15; i++)
{
if (fp_db().sq_get_type_field(i) == _datefld)
row.add(fp_db().sq_get_date(fp_db().sq_get_name_field(i)));
else
row.add(fp_db().sq_get(i));
}
controllo_mov.insert(controllo_mov.end(), row);
}
query.cut(0) << "SELECT " DRD_TIPODOC " FROM " F9_DRD "\n" <<
"WHERE " DRD_CODSOC " = '" << codsoc << "' AND " DRD_ID_EST " = '" << id_estr << "'";
fp_db().sq_set_exec(query);
return fp_db().sq_get((unsigned)0)[0];
}
TF9_dberr::TF9_dberr()
{
_insert.cut(0) << "INSERT INTO " F9_ERR " ("
ERR_CODSOC ", "
ERR_IDESTR ", "
ERR_NUMREG ", "
ERR_DATAREG ", "
ERR_DATADOC ", "
ERR_CODCAUS ", "
ERR_MESELIQ ", "
ERR_NUMDOC ", "
ERR_IMPTDOC ", "
ERR_FORN ", "
ERR_RAGSOC ", "
ERR_PROTIVA ", "
ERR_DESCR ", "
ERR_ESCLUDI ", "
ERR_ESCLUSO ", "
ERR_DESCERR ") VALUES ()";
_fout = new ofstream;
_fout->open("f9_dberr.txt");
}
///////////////////////////////////////////////////////////////////////////////////////////
// TCategorie_doc
///////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<TCategorie_doc::classe_doc> TCategorie_doc::find_causcont(const TString& caus) const
{
for (auto it = _rows.begin(); it != _rows.end(); ++it)
{
if ((*it)->causcont == caus)
return *it;
}
return nullptr;
}
std::shared_ptr<TCategorie_doc::classe_doc> TCategorie_doc::find_tipodoc(const TString& tipodoc) const
{
for (auto it = _rows.begin(); it != _rows.end(); ++it)
{
const std::shared_ptr<classe_doc>& classe = *it;
if (classe->causcont.blank() && classe->tipocaus == tipodoc)
return *it;
}
return nullptr;
}
std::shared_ptr<TCategorie_doc::classe_doc> TCategorie_doc::find_tipodocsdi(const TString& tipodocsdi, const char * tipocaus) const
{
for (auto it = _rows.begin(); it != _rows.end(); ++it)
{
if (((*it)->caus_sost == tipodocsdi) && ((*it)->tipocaus == tipocaus))
return *it;
}
return nullptr;
}
std::vector<pair<TString, std::shared_ptr<TArray_sheet>>>::iterator TCategorie_doc::find_sheet_annessi(const TString& catdoc)
{
for(auto it = _sheets_annessi.begin(); it != _sheets_annessi.end(); ++it)
{
if (it->first == catdoc)
return it;
}
return _sheets_annessi.end();
}
std::shared_ptr<TCategorie_doc::classe_doc> TCategorie_doc::get_classe_doc(const TString& catdoc)
{
for(auto it = _rows.begin(); it != _rows.end(); ++it)
{
if ((*it)->catdoc == catdoc)
return *it;
}
return nullptr;
}
void TCategorie_doc::load_all()
{
_rows.clear();
_rows_annessi.clear();
int idx = 0;
while (true)
{
const TString& appo = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_CATDOC, "", idx++);
if (appo == "STOP" || appo.blank()) /* STOP: Riga terminatrice */
break;
TToken_string row(appo);
classe_doc cd = { row.get(1), row.get(), row.get(), row.get(), row.get(), row.get() };
_rows.emplace_back(std::make_shared<classe_doc>(cd));
}
idx = 0;
while (true)
{
const TString& appo = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, "", idx++);
if (appo == "STOP" || appo.blank()) /* STOP: Riga terminatrice */
break;
TToken_string row(appo);
annesso ann{ row.get(0), row.get(), row.get(), row.get(), row.get_bool() };
TToken_string key = row.get(0);
key.add(row.get(1));
_rows_annessi.insert({ key, ann }); //da sistemare
}
}
void TCategorie_doc::save_ann()
{
remove_all_ann();
int idx = 0;
for (auto it = _rows_annessi.begin(); it != _rows_annessi.end(); ++it)
{
TToken_string row;
if(!it->second.catdocpadre.blank())
row.add(it->second.catdocpadre, 0);
if (!it->second.catdoc.blank())
row.add(it->second.catdoc, 1);
if (!it->second.descr.blank())
row.add(it->second.descr, 2);
if (!it->second.opcee.blank())
row.add(it->second.opcee, 3);
row.add(it->second.obblig ? "X" : "", 4);
ini_set_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, row, idx++);
}
ini_set_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, "STOP", idx); // Riga terminatrice
reload();
}
void TCategorie_doc::save_cat()
{
remove_all_cat();
int idx = 0;
for (auto it = _rows.begin(); it != _rows.end(); ++it)
{
classe_doc& cd = **it;
TToken_string row;
if (!cd.catdoc.blank())
row.add(cd.catdoc, 1);
if (!cd.descr.blank())
row.add(cd.descr, 2);
if (!cd.class_sost.blank())
row.add(cd.class_sost, 3);
if (!cd.caus_sost.blank())
row.add(cd.caus_sost, 4);
if (!cd.causcont.blank())
row.add(cd.causcont, 5);
if (!cd.tipocaus.blank())
row.add(cd.tipocaus, 6);
ini_set_string(CONFIG_DITTA, INI_PAR_MOD, INI_CATDOC, row, idx++);
}
ini_set_string(CONFIG_DITTA, INI_PAR_MOD, INI_CATDOC, "STOP", idx); // Riga terminatrice
reload();
}
const char* TCategorie_doc::traduci_caus_sost(const TString& caus)
{
if (caus == "TD01") return "TD01 Fattura";
if (caus == "TD02") return "TD02 Acconto/Anticipo su fattura";
if (caus == "TD03") return "TD03 Acconto/Anticipo su parcella";
if (caus == "TD04") return "TD04 Nota di credito";
if (caus == "TD05") return "TD05 Nota di debito";
if (caus == "TD06") return "TD06 Parcella";
if (caus == "TD16") return "TD16 Integraz. fatt. rev.ch. interno";
if (caus == "TD17") return "TD17 Integ./autof. acq. servizi estero";
if (caus == "TD18") return "TD18 Integ. acq. beni intracomunitari";
if (caus == "TD19") return "TD19 Integ./autof. acq. beni ex art. 17";
if (caus == "TD20") return "TD20 Autofattura";
if (caus == "TD21") return "TD21 Autofattura per splafonamento";
if (caus == "TD22") return "TD22 Estrazione beni da Deposito IVA";
if (caus == "TD23") return "TD23 Estr. beni Deposito IVA vers. IVA";
if (caus == "TD24") return "TD24 Fatt. differita art.21 c.4 lett. a";
if (caus == "TD25") return "TD25 Fatt. differita art. 21 c.4 per.3 b";
if (caus == "TD26") return "TD26 Cess. beni ammort./passaggi interni";
if (caus == "TD27") return "TD27 Fatt. autoconsumo/cessioni gratuite";
return "";
}
const char* TCategorie_doc::traduci_class_ann(const TString& class_ann)
{
if (class_ann == "RC") return "Reverse Charge";
if (class_ann == "DC") return "ANN. cartaceo";
return "";
}
const char* TCategorie_doc::traduci_class_sost(const TString& class_sost)
{
if (class_sost == "FTA") return "FTA - Fattura Acquisti";
if (class_sost == "FTV") return "FTV - Fattura di Vendita";
return "";
}
std::map<TString, TCategorie_doc::annesso>::iterator TCategorie_doc::find_annesso(const TString& catdoc_padre, const char* catdoc_ann)
{
TToken_string key = catdoc_padre;
key.add(catdoc_ann);
auto it = _rows_annessi.find(key);
if (it != _rows_annessi.end())
return it;
return _rows_annessi.end();
}
void TCategorie_doc::add_annesso(const TString& catdoc_padre, const TString& catdoc_ann, const TString& descr,
const TString& class_ann, const bool obblig)
{
if(!(catdoc_padre && *catdoc_padre && catdoc_ann && *catdoc_ann && class_ann && *class_ann))
fatal_box("add_annesso failed: some parameters are NULL or keys are empty");
annesso ann{ catdoc_padre, catdoc_ann, descr, class_ann, obblig };
TToken_string key = catdoc_padre;
key.add(catdoc_ann);
_rows_annessi.insert({ key, ann });
save_ann();
}
void TCategorie_doc::edit_annesso(const TString& catdoc_padre, const TString& catdoc_ann, const TString& descr,
const TString& class_ann, const bool obblig)
{
if (!(catdoc_padre && *catdoc_padre && catdoc_ann && *catdoc_ann && class_ann && *class_ann))
fatal_box("add_annesso failed: some parameters are NULL or keys are empty");
annesso ann{ catdoc_padre, catdoc_ann, descr, class_ann, obblig };
if (find_annesso(catdoc_padre,catdoc_ann) != _rows_annessi.end())
del_annesso(catdoc_padre,catdoc_ann);
TToken_string key = catdoc_padre;
key.add(catdoc_ann);
_rows_annessi.insert({ key, ann });
save_ann();
}
void TCategorie_doc::add_categoria(const TString& catdoc, const TString& descr, const TString& class_sost, const TString& caus_sost,
const TString& causcont, const TString& tipocaus)
{
if(!(catdoc && *catdoc && class_sost && *class_sost && caus_sost && *caus_sost))
fatal_box("add_categoria failed: some parameters are NULL or keys are empty");
classe_doc cd = { catdoc, descr, class_sost, caus_sost, causcont, tipocaus };
_rows.emplace_back(std::make_shared<classe_doc>(cd));
save_cat();
}
void TCategorie_doc::del_annesso(const TString& catdoc, const char* catdoc_ann)
{
const auto ann = find_annesso(catdoc, catdoc_ann);
if(ann != _rows_annessi.end())
{
_rows_annessi.erase(ann);
save_ann();
}
}
bool TCategorie_doc::get_ann(const TString & catdoc ,const TString& catann, _Out_ annesso& _Annesso_out)
{
TToken_string key = catdoc;
key.add(catann);
const map<TString, annesso>::iterator it = _rows_annessi.find(key);
if (it != _rows_annessi.end() )
{
if (it->first == catdoc)
{
_Annesso_out = it->second;
return true;
}
}
return false;
}
TString_array TCategorie_doc::get_array_ann(const TString& catdoc)
{
TString_array sa(0);
for(auto it = _rows_annessi.begin(); it != _rows_annessi.end(); ++it)
{
if (it->second.catdocpadre == catdoc)
{
TToken_string row(it->second.catdoc);
sa.add(row);
}
}
return sa;
}
TString_array TCategorie_doc::get_array_rows(const bool traduci)
{
TString_array sa(_rows.size());
for(auto it = _rows.begin(); it != _rows.end(); ++it)
{
const shared_ptr<classe_doc>& row = *it;
TToken_string ts;
ts.add(row->catdoc);
ts.add(row->descr);
ts.add(!traduci ? row->class_sost : traduci_class_sost(row->class_sost));
ts.add(!traduci ? row->caus_sost : traduci_caus_sost(row->caus_sost));
ts.add(row->causcont);
ts.add(row->tipocaus);
sa.add(ts);
}
return sa;
}
std::shared_ptr<TArray_sheet> TCategorie_doc::get_sheet_catdocs()
{
if (_sheet_catdocs == nullptr)
{
_sheet_catdocs = make_shared<TArray_sheet>(-1, -1, 125, 20, "Categorie Documentali",
"Categoria\nDocumento(Codice)@15|Descrizione\nDocumento@26|"
"Classe Documentale\nSostitutiva@13|Causale per\nSostitutiva (TD01...)@13|"
"Causale\nContabile@8|Tipo\nDocumento@8",
MODE_SHEETS);
if (!_name_catdocs)
_name_catdocs = make_shared<set<TString>>();
else
_name_catdocs->clear();
//_sheet_catdocs->add_button(DLG_CANCEL, "Annulla", K_ESC, TOOL_CANCEL, TOOL_CANCEL);
const TString_array ar = get_array_rows();
FOR_EACH_ARRAY_ITEM(ar, nr, row)
{
_sheet_catdocs->add(*(TToken_string*)row);
_name_catdocs->insert(((TToken_string*)row)->get(0));
}
}
return _sheet_catdocs;
}
std::shared_ptr<TArray_sheet> TCategorie_doc::get_sheet_ann(const TString& catdoc)
{
auto it = find_sheet_annessi(catdoc);
if (it != _sheets_annessi.end())
_sheets_annessi.erase(it);
it = find_sheet_annessi(catdoc);
if (it == _sheets_annessi.end())
{
TString title; title << "Annessi della Categoria " << catdoc;
shared_ptr<TArray_sheet> sheet = make_shared<TArray_sheet>(-1, -1, 78, 13, title,
"Categoria\nAnnesso(Codice)@15|Descrizione\nDocumento@26|"
"Classificazione\nAnnesso@14|Obbligatorio@8",
_mode_sheet);
const auto inserted = _sheets_annessi.insert(_sheets_annessi.end(), { catdoc, sheet });
const TString_array & aann = get_array_ann(catdoc);
FOR_EACH_ARRAY_ITEM(aann, nr, r)
{
TToken_string& row = *(TToken_string*)r;
std::map<TString, annesso>::iterator it_ann = find_annesso(catdoc, row.get(0));
if(it_ann != _rows_annessi.end())
{
const annesso& ann = it_ann->second;
TToken_string t;
t.add(ann.catdoc);
t.add(ann.descr);
t.add(ann.opcee);
t.add(ann.obblig ? "X" : "");
sheet->add(t);
}
}
it = inserted; // Per restituirlo anche vuoto.
}
return it->second;
}
std::shared_ptr<TCategorie_doc::classe_doc> TCategorie_doc::mov2cat(const int numreg)
{
// Leggo la causale e cerco la corrispondente nelle categorie documentali, se c'e'.
// Guardo le colonne causale cont., tipodoc, class. cat. (opcee)
TLocalisamfile mov(LF_MOV);
mov.put(MOV_NUMREG, numreg);
mov.read();
const TString& caus = mov.get(MOV_CODCAUS);
const TCausale c(caus, mov.get_date(MOV_DATAREG).year());
const TString& tipodoc = c.tipo_doc();
// Cerco se ho un record che abbia specificata quella caus. contabile
std::shared_ptr<classe_doc> cat = find_causcont(caus);
if (cat != nullptr)
return cat;
// Altrimenti cerco per tipo documento
return find_tipodoc(tipodoc);
}
void TCategorie_doc::reload()
{
load_all();
}
void TCategorie_doc::remove_all()
{
remove_all_ann();
remove_all_cat();
}
void TCategorie_doc::remove_all_ann()
{
int idx = 0;
TString iget = "start";
while (iget != "STOP" && !iget.blank())
{
iget = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, "", idx);
ini_remove(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, idx++);
}
}
void TCategorie_doc::remove_all_cat()
{
int idx = 0;
TString iget = "start";
while (iget != "STOP" && !iget.blank())
{
iget = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_CATDOC, "", idx);
ini_remove(CONFIG_DITTA, INI_PAR_MOD, INI_CATDOC, idx++);
}
}
TCategorie_doc::TCategorie_doc() : _mode_sheet(MODE_SHEETS)
{
load_all();
}
///////////////////////////////////////////////////////////////////////////////
// TRecord_categorie
///////////////////////////////////////////////////////////////////////////////
TString TRecord_categorie::get(const char* field)
{
recordtype& rec = _table == 0 ? _categorie : _annessi;
const int i = rec.head.find(field);
if (i != -1)
return rec.record.get(i);
return "";
}
bool TRecord_categorie::next()
{
recordtype& rec = _table == 0 ? _categorie : _annessi;
TToken_string* p = (TToken_string*)_result_set.objptr(_next_pos++);
rec.record = p ? *p : "";
return p;
}
void TRecord_categorie::put(const char* field, const char* value)
{
recordtype& rec = _table == 0 ? _categorie : _annessi;
const int i = rec.head.find(field);
if (i != -1)
rec.record.add(value, i);
}
bool TRecord_categorie::read(bool traduci)
{
_next_pos = 0;
_result_set.destroy();
if (_table == 0)
{
const TString_array sa = get_array_rows(traduci);
FOR_EACH_ARRAY_ITEM(sa, nr, str)
{
TString s = (*(TToken_string*)str).get(0);
if (s == _categorie.record.get(0))
_result_set.add(*(TToken_string*)str);
}
return next();
}
else
{
const TString catdoc = _annessi.record.get(0);
const TString name = _annessi.record.get(1);
const TString_array sa = get_array_ann(catdoc);
FOR_EACH_ARRAY_ITEM(sa, nr, str)
{
TString n = (*(TToken_string*)str).get(0);
if (name.blank() || n == name) // Se name vuoto perche' sto cercando solo per catdoc
{
auto it = find_annesso(catdoc, n);
if (it != _rows_annessi.end())
{
TToken_string t;
t.add(it->second.catdocpadre);
t.add(it->second.catdoc);
t.add(it->second.descr);
t.add(it->second.opcee);
t.add(it->second.obblig);
_result_set.add(t);
}
}
}
return next();
}
}
TRecord_categorie::TRecord_categorie(type table): _table(table)
{
_categorie.head.add("NAME");
_categorie.head.add("DESCR");
_categorie.head.add("CLASSDOCSOS");
_categorie.head.add("CAUSSOS");
_categorie.head.add("CAUSCONT");
_categorie.head.add("TIPODOC");
_annessi.head.add("CATDOC");
_annessi.head.add("NAME");
_annessi.head.add("DESCR");
_annessi.head.add("TIPOANN");
_annessi.head.add("OBBLIG");
}
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
const char* check_str(const TString& str)
{
static TString n_str; n_str.cut(0) << str;
n_str.replace("'", "''");
n_str.replace(" ", " ");
return (const char*)n_str;
}