diff --git a/src/f9/f90100.cpp b/src/f9/f90100.cpp index 7ebd4c47e..d0dbe418f 100644 --- a/src/f9/f90100.cpp +++ b/src/f9/f90100.cpp @@ -153,7 +153,7 @@ bool TEstrai_mask::estrai_handler(TMask_field& f, KEY key) { warning_box("L'estrazione non e' stata completata. Controllare il log degli errori."); if (stato == 0) // Errore scrittura F9IVA, non segno in errore in testata... - a.segna_in_errore(); // ... se l'errore e' dovuto alla scrittura sul db + TF9_app::segna_in_errore(); // ... se l'errore e' dovuto alla scrittura sul db } a.print_log(); msk.field(ES_DESCR).set(""); @@ -1116,14 +1116,15 @@ int TF9_app::estrai() // Vero e proprio oggetto estrazione _estrazione = make_unique( - get_ambiente(), // Codice ambiente - flagpro, // Flag prov. - tipodoc, // Tipo doc. - get_descr(), // Descrizione estrazione - get_addr_doc(), // Cartella documenti - false, // Estrazione di un escluso - &dataini, // Data estr. mov dal - &dataend // Data estr. mov al + get_ambiente(), // Codice ambiente + flagpro, // Flag prov. + tipodoc, // Tipo doc. + get_descr(), // Descrizione estrazione + get_addr_doc(), // Cartella documenti + false, // Estrazione di un escluso + &dataini, // Data estr. mov dal + &dataend, // Data estr. mov al + get_has_vendext() // Flag in configurazione per staltare controlli vendite ); // Leggo i movimenti e li carico nell'estrazione. ///////////// diff --git a/src/f9/f9lib01.cpp b/src/f9/f9lib01.cpp index a021bb81f..33117a2d1 100644 --- a/src/f9/f9lib01.cpp +++ b/src/f9/f9lib01.cpp @@ -127,21 +127,23 @@ bool TEstrazione::insert_into_drd() const bool TEstrazione::insert_into_f9movestr() const { TString query; - query << "INSERT INTO " F9_MOVESTR " (IDESTR, NUMREG, DATAREG, ESTRATTO, DESCR_ERR)\nVALUES "; + bool ok = true; for(auto it = _movs.begin(); it != _movs.end(); ++it) { - query << " ('" << _head.id_estr << "', '" << it->numreg << "', '" << it->datareg.date2ansi() << "', " << - (it->estratto ? "1" : "0") << ", '" << check_str(it->get_descr_estr()) << "'),\n"; + query.cut(0) << "INSERT INTO " F9_MOVESTR " (IDESTR, NUMREG, DATAREG, ESTRATTO, DESCR_ERR)\nVALUES " << + " ('" << _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; + } } - query.rtrim(2); - bool ok = fp_db().sq_set_exec(query); - ok = ok && fp_db().sq_commit(); - if (!ok) - write_errorsql_log(query); return ok; } @@ -151,8 +153,12 @@ bool TEstrazione::export_error_list() const 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 @@ -347,24 +353,55 @@ const char* TEstrazione::diagnostica_mov() if (!bar.add_status()) break; //TToken_string& row = *it; - movimento_t& row = *it; - TString numreg(row.numreg); + movimento_t& mov_i = *it; + TString numreg(mov_i.numreg); TLocalisamfile mov(LF_MOV); mov.put(MOV_NUMREG, numreg); mov.read(); - // Controllo che abbia il riferimento al documento originale generatore del movimento - // todo: modificare controllo in base al flag in configurazione - if (mov.get(MOV_DPROVV).empty() || mov.get(MOV_DANNO).empty() || mov.get(MOV_DCODNUM).empty() || mov.get(MOV_DNDOC).empty()) + + /* Categorie documentali. Come per gli acquisti. */ + if (!mov_i.err && mov_i.estratto) { - row.err = true; - row.descr_err = "Movimento non collegato a un documento originale. Impossibile estrarre. Escludere?"; - ok &= false; + std::shared_ptr cd = categorie_doc().causcont2cat(mov_i.codcaus); + mov_i.estratto = cd.get(); + mov_i.descr_estr = cd ? movimento_t::no_err : movimento_t::no_catdoc; + mov_i.catdoc = cd; } - else if (!is_doc_xml(mov)) // Quindi controllo che sia un documento xml, se no lo metto in errore e te lo escludi a mano, se e' da escludere + if (mov_i.catdoc && !mov_i.catdoc->is_cartaceo()) { - row.err = true; - row.descr_err = "Movimento collegato a un documento senza fatturazione elettronica. Escludere?"; - ok &= false; + // Che controlli devo fare per essere sicuro di tirare fuori mov di vendita che siano corretti (sicuramente da estrarre)? + // Dovrei essere sicuro che sia un documento che abbia bisogno della fatturazione e che sia stato spedito. + // Nel caso in cui la fatturazione/invio/contabilita' venga fatta in Campo/WebApp posso capire se e' una fattura elettronica, + // nel caso in cui le fatture vengono fatte da un altro gestionale e importate nella webapp dopo, non ho modo di capire dal mov + // se deriva da un vero documento di fatturazione elettronica. + // E se il movimento fosse per qualche motivo esente dalla fatturazione elettronica? Nel caso in cui venga fatto in campo avrei + // il documento generatore e, o da questo vedo che il numeratore non ha il flag di fattura xml (salto), + // o non lo trovo sui paf (devi escludere), ma nell'altro caso non so dir nulla, ma a questo punto io lo estrarrei normalmente, e + // poi la WebApp mi darebbe errore, ma io non sono in grado di escludere la fattura al prossimo tentativo. + // Possibili soluzioni: + // - Fare in modo di escludere anche movimenti che apparentemente sono passati per buoni; + // - In corso di estrazione mostrare la lista dei movimenti che sarebbero estratti e casellare quelli da escludere. + + // Controllo che abbia il riferimento al documento originale generatore del movimento solo se non ha flag di vendite esterne + if (!_has_vendext) + { + if (mov.get(MOV_DPROVV).empty() || mov.get(MOV_DANNO).empty() || mov.get(MOV_DCODNUM).empty() || mov.get(MOV_DNDOC).empty()) + { + mov_i.err = true; + mov_i.estratto = false; + mov_i.descr_estr = movimento_t::no_doc; + mov_i.descr_err = "Movimento non collegato a un documento originale. Impossibile estrarre. Escludere?"; + ok &= mov_i.estratto; + } + else if (!is_doc_xml(mov)) // Quindi controllo che sia un documento xml, se no lo metto in errore e te lo escludi a mano, se e' da escludere + { + mov_i.err = true; + mov_i.descr_err = "Movimento collegato a un documento senza fatturazione elettronica. Escludere?"; + mov_i.estratto = false; + mov_i.descr_estr = movimento_t::notfound_elet; + ok &= mov_i.estratto; + } + } } } } @@ -382,10 +419,26 @@ result_estr TEstrazione::estrai() warning_box("Non esistono movimenti estraibili per il periodo selezionato."); return estr_stop; } - if (!_escluso && !_head.flag_prov && !check_periodo_def()) + if (!_escluso && !_head.flag_prov) { - error_box("Attenzione e' stato inserito un periodo che si sovrappone\nad un'estrazione definitiva gia' esistente. Impossibile procedere."); - return estr_stop; + 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... @@ -518,6 +571,24 @@ bool TEstrazione::estrazione_iva(bool escluso) return stato; } +bool TEstrazione::exist_prov() const +{ + TString query; query << "SELECT * FROM " F9_DRD "\n" << + "WHERE " 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 F9RIDES AS ID, F9RUESA AS DATA_A FROM " F9_DRD "\n" + "WHERE " DRD_ID_EST " LIKE '%N%' AND " DRD_FLAG_PD " = 'D' AND " DRD_TIPODOC " = '" << _head.tipo_doc << "'\n" + "ORDER BY F9RUESA 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) @@ -528,7 +599,8 @@ void TEstrazione::set_dates() } 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) : _descr(descr) + const TString& addrcart, const bool escluso, const TDate* const dal, const TDate* const al, const bool has_vendext) + : _descr(descr), _has_vendext(has_vendext) { _head.cod_soc = ambiente; _head.flag_prov = flag_prov; @@ -642,6 +714,11 @@ TF9_dberr::TF9_dberr() // TCategorie_doc /////////////////////////////////////////////////////////////////////////////////////////// +bool TCategorie_doc::classe_doc::is_cartaceo() const +{ + return !opcee.empty(); +} + vector::iterator TCategorie_doc::find(const TString& class_sost, const TString& caus_sost, const TString& op_cee) { diff --git a/src/f9/f9lib01.h b/src/f9/f9lib01.h index 3d0d716cc..25266bee5 100644 --- a/src/f9/f9lib01.h +++ b/src/f9/f9lib01.h @@ -57,6 +57,8 @@ public: TString tipocaus; TString tipomov; TString opcee; + + bool is_cartaceo() const; }; private: vector _rows; @@ -88,9 +90,11 @@ struct movimento_t { enum err_mov { - no_err, // Estratto normalmente - escluso, // Movimento con flag escluso - no_catdoc // Nessuna cat. doc. riconosciuta per questo movimento, o non e' una fattura + no_err, // Estratto normalmente + escluso, // Movimento con flag escluso + no_catdoc, // Nessuna cat. doc. riconosciuta per questo movimento, o non e' una fattura + no_doc, // Il mov. di vendita non ha un documento generatore + notfound_elet // Non trovata fatt. elettronica mov vendita }; bool err; @@ -121,6 +125,10 @@ struct movimento_t return "Il movimemnto e' segnato come escluso. Saltato."; case no_catdoc: return "Nessuna categoria documentale riconosciuta per questo movimento, o non e' una fattura."; + case no_doc: + return "Il mov. di vendita non ha un documento generatore"; + case notfound_elet: + return "Non trovata fatt. elettronica mov vendita"; default: return ""; } } @@ -161,9 +169,10 @@ class TEstrazione : public TObject { drd _head; vector _movs; - ofstream* _error_sql; + ofstream* _error_sql; bool _escluso; const TString _descr; + bool _has_vendext; /** Aggiorna stato estrazione. Utilizzato ad esempio dopo la diagnostica per riportare * il nuovo stato sul db. @@ -225,6 +234,9 @@ public: * \return true Scrittura sul db senza errori. * \return false Errore scrittura db. */ bool estrazione_iva(bool escluso = false); + bool exist_prov() const; /**< Controllo che esista per questo stesso periodo una estrazione provvisoria. */ + /** Controllo se esiste un periodo antecedente a questa estrazione che non e' mai stato estratto definitivamente. */ + bool gap_periodo() const; // Getters TString get_id_estr() const { return _head.id_estr; } @@ -242,12 +254,10 @@ public: void set_addrcart(const TString& addrcart) { _head.addr_cart = addrcart; } TEstrazione(const TString& ambiente, bool flag_prov, char tipodoc, const TString& descr, const TString& addrcart, - bool escluso, const TDate* dal = nullptr, const TDate* al = nullptr); + bool escluso, const TDate* dal = nullptr, const TDate* al = nullptr, bool has_vendext = false); }; - - class TF9_dberr { TString _str;