//#include #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 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& 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 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 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& 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(); _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& 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) const { 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) const { for (auto it = _rows.begin(); it != _rows.end(); ++it) { const std::shared_ptr& classe = *it; if (classe->causcont.blank() && classe->tipocaus == tipodoc) return *it; } return nullptr; } std::shared_ptr 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>>::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(); _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(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::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(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::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& 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 TCategorie_doc::get_sheet_catdocs() { if (_sheet_catdocs == nullptr) { _sheet_catdocs = make_shared(-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>(); 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 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 sheet = make_shared(-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::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::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(); } 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; }