#include "f9lib01.h" #include "f1lib.h" #include "f901tab.h" #include "progind.h" #include "clifo.h" #include "cg2103.h" #include "mov.h" #include "../fp/fplib.h" #define MODE_SHEETS 0xC statistics _stats = { 0 }; // Controlla eventuali apostrofi e li raddoppia const char* check_str(const TString& str); //////////////////////////////////////////////////////// // TEstrazione //////////////////////////////////////////////////////// const char* TEstrazione::categoria_doc() { return ""; // todo: } 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 ""; } 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 { // todo: } 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 (paiv == "0") paiv.cut(0); if (statopaiv == "IT" || statopaiv.empty()) { 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(); return (clifo.get(CLI_STATOPAIV).empty() || clifo.get(CLI_STATOPAIV) == "IT") && clifo.get(CLI_COMCF) != "B513"; // Campione d'Italia } bool TEstrazione::load_annessi(movimento_t& movimento) { TF9_doccart doccart; TString numreg; numreg << movimento.numreg; return doccart.mov2listann_vect(numreg, movimento.annessi); } 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()) << "')"; #ifdef DBG if (TString(check_str(it->get_descr_estr())).empty()) bool simo = true; #endif 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& 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) { #ifdef DBG if (count == 25) bool simo = true; if (it->numreg == 187680) bool simo = true; #endif 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 " DRD_ID_EST " AS IDESTR\n" "FROM " F9_DRD "\n" "WHERE " DRD_CODSOC " = '" << _head.cod_soc << "' AND\n" DRD_ID_EST " LIKE '" << today.date2ansi() << "%'\n" << "ORDER BY " DRD_ID_EST " DESC"; fp_db().sq_set_exec(query); const int last_estr = fp_db().sq_items() > 0 ? real(fp_db().sq_get("IDESTR").ltrim(10)).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) { return TCausale(mov.get(MOV_CODCAUS), mov.get_date(MOV_DATAREG).year()).soloiva(); } 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 } // 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() { 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 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); #ifdef DBG if (mov.read() != NOERR) warning_box("OOOOOOOOOHH! E DICE SIII!!"); #endif 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.state = res; 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; mov_i.state = res; ++_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."; mov_i.state = res; 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."; mov_i.state = res; break; case no_guessed: 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"; mov_i.state = res; default: break; } 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.err && mov_i.estratto) { std::shared_ptr 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.estratto) { 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; copy_file_to_webapp_fld(mov_i); } 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; } } bool loaded = load_annessi(mov_i); #ifdef DBG if (loaded) bool simo = true; #endif } } 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); #ifdef DBG if(mov.read() != NOERR) warning_box("OOOOOOOOOHH! E DICE SIII!!"); if (it->numreg == 96956) bool simo = true; // Rev charge if (it->numreg == 95752) bool simo = true; // Cartaceo if (it->numreg == 95740) // Annessi bool simo = true; #endif /* 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); bool exist_doc; 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 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) ++_stats.fv_nocatdoc; if (mov_i.err) ++_stats.fv_err; else if (mov_i.estratto) ++_stats.fv_estr; } if (mov_i.estratto && mov_i.cartaceo) { TF9_doccart filecart; TFilename file; TString reg; reg << it->numreg; if (filecart.mov2doc(reg, file) && file.exist()) { mov_i.nomefilecart << file; copy_file_to_webapp_fld(mov_i); } 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; } } bool loaded = load_annessi(mov_i); #ifdef DBG if (loaded) bool simo = true; #endif } 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). 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(); ok &= insert_into_f9movestr(); ok &= update_drd_stato_estr(); 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."); 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 numdoc, 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; #ifdef DBG if (it->numreg == 95752) // Cartaceo bool simo = true; if (it->numreg == 95747) // idfisc errato Arredamenti Riva bool simo = true; if (it->numreg == 95740) // Annessi bool simo = true; #endif 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 TString& tipodoc = _head.tipo_doc; const TString& name_reg = TRegistro(TCausale(mov.get(MOV_CODCAUS), mov.get_date(MOV_DATAREG).year()).reg()).name(); fill_id(cli, statopaiv, idfisc, paiv, codfis); numdoc.cut(0) << (mov.get(MOV_NUMDOCEXT).full() ? mov.get(MOV_NUMDOCEXT) : mov.get(MOV_NUMDOC)); TString datadoc; datadoc << mov.get_date(MOV_DATADOC).date2ansi(); TString datareg; datareg << mov.get_date(MOV_DATAREG).date2ansi(); TIva_insert_prepared_stat iva_query; iva_query.add(IVA_CODSOC, _head.cod_soc); iva_query.add(IVA_IDLAN, _head.id_estr); iva_query.add(IVA_FLAG_PD, _head.flag_prov ? "P" : "D"); iva_query.add(IVA_ANNOES, mov.get(MOV_ANNOES)); iva_query.add(IVA_GIVA, tipodoc); iva_query.add(IVA_TIPOG, name_reg); iva_query.add(IVA_DOCXML, it->cartaceo ? "N" : "S"); iva_query.add(IVA_TIPOCF, mov.get(MOV_TIPO)); iva_query.add(IVA_CODCF, mov.get(MOV_CODCF)); iva_query.add(IVA_RAGSOC, check_str(cli.get(CLI_RAGSOC))); iva_query.add(IVA_IDFISC, idfisc); iva_query.add(IVA_PIVA, paiv); iva_query.add(IVA_CODFIS, codfis); iva_query.add(IVA_CATDOC, it->catdoc->catdoc); iva_query.add(IVA_CAUSSOS, it->catdoc->caus_sost); iva_query.add(IVA_NUMDOC, numdoc); iva_query.add(IVA_DATADOC, datadoc); iva_query.add(IVA_SEZIVA, mov.get(MOV_REG)); iva_query.add(IVA_TIPOREG, ""); iva_query.add(IVA_NPROT, mov.get(MOV_PROTIVA)); 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, 20010101); }*/ iva_query.add(IVA_CLASDOC, it->catdoc->class_sost); iva_query.add(IVA_NOMFD, it->nomefilecart.name()); // Load annessi... if(!it->annessi.empty()) { vector& ann = it->annessi; TCategorie_doc cd; auto classost = [&](const int i) { const std::shared_ptr as = cd.get_classe_doc(ann[i].catdocann); if (as != nullptr) return as->class_sost; return TString(""); }; size_t i = 0; size_t size = ann.size(); iva_query.add(IVA_CLASAN1, classost(i)); iva_query.add(IVA_NOMF1, ann[i++].filename); // HOW DID MY LIFE COME TO THIS?.... if (size > i) { iva_query.add(IVA_CLASAN2, classost(i)); iva_query.add(IVA_NOMF2, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN3, classost(i)); iva_query.add(IVA_NOMF3, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN4, classost(i)); iva_query.add(IVA_NOMF4, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN5, classost(i)); iva_query.add(IVA_NOMF5, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN4, classost(i)); iva_query.add(IVA_NOMF4, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN6, classost(i)); iva_query.add(IVA_NOMF6, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN7, classost(i)); iva_query.add(IVA_NOMF7, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN8, classost(i)); iva_query.add(IVA_NOMF8, ann[i++].filename); } if (size > i) { iva_query.add(IVA_CLASAN9, classost(i)); iva_query.add(IVA_NOMF9, ann[i++].filename); } } iva_query.add(IVA_USERELA, user()); iva_query.add_getdate(IVA_TIMEELA); if (_head.tipo_doc == 'A') { TToken_string keys(mov.get(MOV_KEYFPPRO), ';'); fppro_db().set_keys(keys); iva_query.add(IVA_TIPPROT, fppro_db().get_tipoprot()); iva_query.add(IVA_NUMPROT, fppro_db().get_numprot()); iva_query.add(IVA_ANNPROT, fppro_db().get_annoprot()); iva_query.add(IVA_TIMERIC, fppro_db().get_dataoraric()); } const bool ok = fp_db().sq_set_exec(iva_query.get()) && fp_db().sq_commit(); if (!ok) write_errorsql_log(iva_query.get()); 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, const TDate* const dal, const TDate* const al, const bool has_checkvend, const bool has_cartacei) : _descr(descr), _has_checkvend(has_checkvend), _has_cartacei(has_cartacei) { _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 = new ofstream; _error_sql->open("f9_TEstrazione_error_sql.txt"); } ////////////////////////////////////////////////////// // 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; } void TF9_dberr::del_err(const TString& codsoc, const TString& id_estr, int numreg) { TString query; query << "DELETE FROM " F9_ERR "\nWHERE " ERR_CODSOC " = '" << codsoc << "'" "\nAND " ERR_IDESTR " = '" << id_estr << "' AND " ERR_NUMREG " = '" << numreg << "';"; fp_db().sq_set_exec(query); } char TF9_dberr::get_errori(const TString& codsoc, const TString& id_estr, vector& 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::find_causcont(const TString& caus) { for (auto it = _rows.begin(); it != _rows.end(); ++it) { if ((*it)->causcont == caus) return *it; } return nullptr; } std::shared_ptr TCategorie_doc::find_tipodoc(const TString& tipodoc) { for (auto it = _rows.begin(); it != _rows.end(); ++it) { const std::shared_ptr& classe = *it; if (classe->causcont.empty() && classe->tipocaus == tipodoc) return *it; } return nullptr; } std::vector>::iterator TCategorie_doc::find_annesso(const TString& catdoc, const char* catdoc_ann) { for (auto it = _annessi.begin(); it != _annessi.end(); ++it) { if (it->first == catdoc && it->second == catdoc_ann) return it; } return _annessi.end(); } std::vector>>::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::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(); _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.empty()) /* STOP: Riga terminatrice */ break; TToken_string row(appo); classe_doc cd = { row.get(1), row.get(), row.get(), row.get(), row.get(), row.get(), row.get(), row.get() }; _rows.emplace_back(std::make_shared(cd)); } idx = 0; while (true) { const TString& appo = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, "", idx++); if (appo == "STOP" || appo.empty()) /* STOP: Riga terminatrice */ break; TToken_string row(appo); _annessi.emplace_back(pair({ row.get(0), row.get(1) })); } } 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 == "TD20") return "TD20 Autofattura"; return ""; } const char* TCategorie_doc::traduci_class_ann(const TString& class_ann) { if (class_ann == "RC") return "Reverse Charge"; if (class_ann == "DC") return "Doc. 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 ""; } void TCategorie_doc::add_annesso(const TString& catdoc, const char* catdoc_ann) { _annessi.insert(_annessi.end(), pair({ catdoc, catdoc_ann })); int idx = 0; TString iget = "start"; while (iget != "STOP" && !iget.empty()) { iget = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, "", idx); ini_remove(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, idx++); } idx = 0; for(auto it = _annessi.begin(); it != _annessi.end(); ++it) { TToken_string row; row.add(it->first, 0); row.add(it->second); 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::del_annesso(const TString& catdoc, const char* catdoc_ann) { const auto annesso = find_annesso(catdoc, catdoc_ann); if(annesso != _annessi.end()) { _annessi.erase(annesso); int idx = 0; TString iget = "start"; while (iget != "STOP" && !iget.empty()) { iget = ini_get_string(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, "", idx); ini_remove(CONFIG_DITTA, INI_PAR_MOD, INI_ANNESSI, idx++); } idx = 0; for (auto it = _annessi.begin(); it != _annessi.end(); ++it) { TToken_string row; row.add(it->first, 0); row.add(it->second); 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(); } } TString_array TCategorie_doc::get_array_ann(const TString& catdoc) { TString_array sa(0); for(auto it = _annessi.begin(); it != _annessi.end(); ++it) { if (it->first == catdoc) { TToken_string row(it->second); sa.add(row); } } return sa; } TString_array TCategorie_doc::get_array_rows(bool traduci) { TString_array sa(_rows.size()); for(auto it = _rows.begin(); it != _rows.end(); ++it) { const shared_ptr& 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); ts.add(!traduci ? row->tipomov : traduci_class_ann(row->tipomov)); sa.add(ts); } return sa; } std::shared_ptr TCategorie_doc::get_sheet_catdocs() { if (_sheet_catdocs == nullptr) { _sheet_catdocs = make_shared(-1, -1, 78, 13, "cat.docs", "Categoria\nDocumento(Codice)@15|Descrizione\nDocumento@26|" "Classe Documentale\nSostitutiva@25|Causale per\nSostitutiva (TD01...)@34|" "Causale\nContabile@8|Tipo\nDocumento@6|Classificazione\nAnnesso@15", MODE_SHEETS); if (!_name_catdocs) _name_catdocs = make_shared>(); else _name_catdocs->clear(); //_sheet_catdocs->add_button(DLG_CANCEL, "Annulla", K_ESC, TOOL_CANCEL, TOOL_CANCEL); const TString_array ar = get_array_rows(true); 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 TCategorie_doc::get_sheet_ann(const TString& catdoc) { auto it = find_sheet_annessi(catdoc); if (it == _sheets_annessi.end()) { const auto inserted = _sheets_annessi.insert(_sheets_annessi.end(), { catdoc, make_shared(-1, -1, 78, 13, "Annessi", "Categoria\nAnnesso(Codice)@15|Descrizione\nDocumento@26|" "Classe Documentale\nSostitutiva@25|Classificazione\nAnnesso@14", MODE_SHEETS) }); const TString_array aann = get_array_ann(catdoc); if (!aann.empty()) { TArray_sheet* as = inserted->second.get(); TRecord_categorie rec; FOR_EACH_ARRAY_ITEM(aann, nr, row) { rec.put("NAME", ((TToken_string*)row)->get(0)); rec.read(true); TToken_string t; t.add(((TToken_string*)row)->get(0)); t.add(rec.get("DESCR")); t.add(rec.get("CLASSDOCSOS")); t.add(rec.get("CLASSANN")); as->add(t); } } it = inserted; } return it->second; } std::shared_ptr 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 cat = find_causcont(caus); if (cat != nullptr) return cat; // Altrimenti cerco per tipo documento return find_tipodoc(tipodoc); } void TCategorie_doc::reload() { 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.empty() || n == name) { TToken_string t; t.add(catdoc); t.add(n); _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"); _categorie.head.add("CLASSANN"); _annessi.head.add("CATDOC"); _annessi.head.add("NAME"); } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// 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; }