Patch level : 12.0 no-patch

Files correlati     : f90.exe
Commento            :
- F9 ARCHIVIAZIONE SOSTITUTIVA:
- Corretta multivalues insert in f9movestr: se troppi valori TString non poteva contenerli tutti. Separate in singole insert.
- Aggiunta barra progresso per salvataggio movimenti estratti.
- Modificato controllo per movimenti di vendita: guardo flag in configurazione (fatturazione esterna), controllo la cat.doc., e distinzione attraverso cat. doc. se si tratta di un doc. cartaceo.
- Aggiunti controllo di aiuto all'utente: avvisa se viene lasciato un gap di tempo vuoto tra un'estrazione e l'altra, e avvisa se si sta facendo un'estrazione definitiva senza aver mai fatto una provvisora dello stesso tipo e periodo.
This commit is contained in:
Simone Palacino 2020-04-15 18:01:09 +02:00
parent 496bf39046
commit 89590b09fc
3 changed files with 128 additions and 40 deletions

View File

@ -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<TEstrazione>(
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. /////////////

View File

@ -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<movimento_t>& movs = _movs;
bool ok = true;
int count = 0;
TProgress_monitor pg(movs.size(), "Scrittura movimenti in errore");
for (auto it = movs.begin(); it != movs.end(); ++it)
{
if (!pg.add_status())
break;
if (it->err)
{
#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<TCategorie_doc::classe_doc> 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<TCategorie_doc::classe_doc>::iterator TCategorie_doc::find(const TString& class_sost, const TString& caus_sost,
const TString& op_cee)
{

View File

@ -57,6 +57,8 @@ public:
TString tipocaus;
TString tipomov;
TString opcee;
bool is_cartaceo() const;
};
private:
vector<classe_doc> _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<movimento_t> _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;