campo-sirio/src/fp/fp0300.cpp

584 lines
15 KiB
C++
Raw Normal View History

#include <applicat.h>
#include <automask.h>
#include <config.h>
#include "fplib.h"
#include <progind.h>
#include <cfven.h>
#include <doc.h>
#include "../ve/velib05.h"
#include "../cg/cglib03.h"
#include "../fe/felib.h"
#include "fp0.h"
#include "fp0300a.h"
/////////////////////////////////////////////////////////////////////////////////////
// Globals
/////////////////////////////////////////////////////////////////////////////////////
#define LEN_HFATT 20
#define LEN_BFATT 50
/////////////////////////////////////////////////////////////////////////////////////
// TPa_mask
/////////////////////////////////////////////////////////////////////////////////////
class TPA_mask : public TAutomask
{
protected:
enum {_codnum, _tipodoc, _dastato, _astato, _tiposdi};
void set_filter_changed();
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
void next_page(int p);
bool check_not_empty();
bool check_full_fields() const;
bool check_doc_filter(const TDocumentoEsteso& td) const;
void set_err_paf();
void fill();
void init();
bool is_fattura(const TRectype& doc) const;
void load_all_fields();
bool _filter_changed;
public:
TPA_mask() : TAutomask("fp0300a"), _filter_changed(true)
{
disable(DLG_OK);
load_all_fields();
}
void save_all_fields() const;
};
bool TPA_mask::is_fattura(const TRectype& doc) const
{
const TTipo_documento& td = cached_tipodoc(doc.get(DOC_TIPODOC));
if (!td.is_fattura()) // Tengo per buone solo le fatture e le note di credito
return false;
const TCodice_numerazione& cn = cached_numerazione(doc.get(DOC_CODNUM));
return cn.tipo() == 2 && !cn.get_bool("B10"); // Controlla se fattura provvisioria esclusa da P.A.
}
void TPA_mask::save_all_fields() const
{
ini_set_string(CONFIG_DITTA, "fp", "dataini", get(F_DATAINI));
ini_set_string(CONFIG_DITTA, "fp", "dataend", get(F_DATAEND));
// Salvo lo sheet
TFP_selected_docs selected_docs;
selected_docs.save_sheet(sfield(F_DOCUMENTI_TIPO));
// Salvo le impostazioni
fp_settings().set_esp_pri_empty(get_bool(F_SETDEFCOD));
fp_settings().set_esp_est(get_bool(F_SETCODEST));
fp_settings().set_esp_est_cod(get(F_VALCODEST));
}
void TPA_mask::load_all_fields()
{
set(F_DATAINI, ini_get_string(CONFIG_DITTA, "fp", "dataini"));
set(F_DATAEND, ini_get_string(CONFIG_DITTA, "fp", "dataend"));
const TToken_string s_accepted_docs(ini_get_string(CONFIG_DITTA, "fp", "accepted_docs"), ';');
//
auto& sheet = sfield(F_DOCUMENTI_TIPO);
sheet.hide();
TFP_selected_docs selected_docs;
if (selected_docs.has_selected_docs())
{
// Super nuova gestione super avanzata!
selected_docs.fill_sheet(sheet);
}
else if(s_accepted_docs.full())
{
// Nuova gestione avanzata!
FOR_EACH_STR_TOKEN(s_accepted_docs, tok)
{
TToken_string& row = sheet.row(-1);
row.add(tok);
row.add(TTipo_documento(TToken_string(tok).get(1)).tipo_doc_sdi());
}
}
else
{
// Vecchia gestione ):
const TString& codnum = ini_get_string(CONFIG_DITTA, "fp", "codnum");
TToken_string tipidocs(ini_get_string(CONFIG_DITTA, "fp", "tipodocs"));
FOR_EACH_STR_TOKEN(tipidocs, tok)
{
TToken_string& row = sheet.row(-1);
row.add(codnum);
row.add(tok);
// Considero 1 e 9 come stati default?
row.add(1);
row.add(9);
row.add(TTipo_documento(tok).tipo_doc_sdi());
}
}
sheet.force_update();
sheet.show();
set(F_SETDEFCOD, fp_settings().get_esp_pri_empty());
set(F_SETCODEST, fp_settings().get_esp_est());
set(F_VALCODEST, fp_settings().get_esp_est_cod());
}
TString& add_filter(const TString& field, const TString& from, const TString& to)
{
TString& query = get_tmp_string();
const TString qf = field.find('.') < 0 ? field : field.sub(field.find('.') + 1);
if (from.full() && to.full())
{
query << "&&(BETWEEN(" << field << ", #DA" << qf << ", #A" << qf << "))";
}
else if (from.full())
{
query << "&&(" << field << ">=#DA" << qf << ")";
}
else if (to.full())
{
query << "&&(" << field << "<=#A" << qf << ")";
}
return query;
}
void TPA_mask::fill()
{
// Salvo subito su file le impostazioni di esportazione, in fplib accedo ai file
save_all_fields();
TSheet_field& docs = sfield(F_DOCS);
TString_array& sht = docs.rows_array();
docs.hide();
sht.destroy();
const TDate dal = get(F_DATAINI);
const TDate al = get(F_DATAEND);
TString filter_selected = get(F_FATTSEL);
#ifdef DBG
enable(DLG_OK);
enable(DLG_SAVEREC);
#else
enable(DLG_OK, filter_selected != "X");
enable(DLG_SAVEREC, fp_settings().is_f8() && filter_selected == "X");
#endif
// Record di controllo per eventuali elaborazioni precedenti
TString hfatt(LEN_HFATT), bfatt(LEN_BFATT);
TPaf_record paf0100f("PAF0100F");
TString query;
query << "USE 33 KEY 3 \n" <<
"SELECT 33.TIPOCF==\"C\" \n" <<
"JOIN 20 INTO TIPOCF==TIPOCF CODCF==CODCF \n" <<
"JOIN 17 TO 33 INTO TIPOCF==TIPOCF CODCF==CODCF \n" <<
"JOIN %TIP TO 33 ALIAS 400 INTO CODTAB==TIPODOC \n" <<
"FROM DATADOC=#DADATADOC \n" <<
"TO DATADOC=#ADATADOC";
TISAM_recordset rec(query);
rec.set_var("#DADATADOC", dal);
rec.set_var("#ADATADOC", al);
TProgress_monitor pi(rec.items(), nullptr);
bool first, show, ask = !((show = (first = true)));
int fat_no_cod = 0;
// Disabilito la colonna del codice ufficio
docs.enable_column(docs.cid2index(S_UFFICIO), false);
for (bool okc = rec.move_first(); okc; okc = rec.move_next())
{
if (!pi.add_status())
break;
const TRectype& doc = rec.cursor()->curr();
const TTipo_documento& td = cached_tipodoc(doc.get(DOC_TIPODOC));
// Controllo che la numerazione sia tra quelle giuste
// Controllo che il tipo documento sia OK
if(!check_doc_filter(doc))
continue;
bool sent = false;
if (chiave_paf(doc, hfatt, bfatt))
{
if (paf0100f.search(nullptr, hfatt, bfatt) && paf0100f.sq_get("P1_GESTIONE") != " " && paf0100f.sq_get("P1_ERRINT") != "*")
{
if (paf0100f.sq_get("P1_GESTIONE") != filter_selected)
continue;
sent = true;
}
else if (filter_selected.not_empty())
continue;
}
TToken_string& row = docs.row(-1);
row = sent ? " " : "X";
row.add(rec.get(DOC_ANNO).as_int(), 1);
row.add(rec.get(DOC_CODNUM).as_string());
row.add(rec.get(DOC_TIPODOC).as_string());
if (!rec.get(DOC_TIPODOCSDI).is_empty())
row.add(rec.get(DOC_TIPODOCSDI).as_string());
else
row.add(td.tipo_doc_sdi());
row.add(rec.get(DOC_NDOC).as_int());
row.add(rec.get(DOC_DATADOC).as_date());
row.add(rec.get(CFV_CODCF).as_int());
row.add(rec.get("20." CLI_RAGSOC).as_string());
TString rif = get_dest_sdi(rec.get(CFV_TIPOCF).as_string()[0], rec.get(CFV_CODCF).as_int());
// Se <20> ancora vuoto potrebbe essere estero
if(rif.empty())
{
// Segno la riga errata
if (first)
{
first = false;
// Abilito la colonna del codice ufficio per segnalare l'errore
docs.enable_column(docs.cid2index(S_UFFICIO));
}
docs.set_back_and_fore_color(COLOR_RED, COLOR_WHITE, rec.current_row(), docs.cid2index(S_UFFICIO));
fat_no_cod++;
}
;
row.add(rif);
row.add(rec.get("17." CFV_PARIFAMM).as_string());
row.add(rec.get("20." CLI_COFI).as_string());
bool split = rec.get("20." CLI_SPLITPAY).as_bool();
if (split)
{
const long numreg = rec.get(DOC_NUMREG).as_int();
if (numreg > 0)
{
const TRectype& mov = cache().get(LF_MOV, numreg);
split = is_split_payment(mov);
}
}
row.add(split ? "X" : " ");
const bool attach = !rec.get("COLL_GOLEM").is_empty();
row.add(attach ? "X" : " ");
row.add(!td.invio_xml() ? "X" : "");
}
docs.force_update();
docs.show();
if (fat_no_cod > 0)
warning_box("Sono state trovate una o pi<70> fatture senza codice destinatario n<> pec");
}
void TPA_mask::set_filter_changed()
{
_filter_changed = true;
}
bool TPA_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case DLG_RECALC:
if (e == fe_button)
next_page(1);
break;
case F_DATAINI:
if (e == fe_init)
o.set(ini_get_string(CONFIG_DITTA, "fp", "LastXML", "01-01-2018"));
else if (e == fe_close)
ini_set_string(CONFIG_DITTA, "fp", "LastXML", o.get());
break;
case F_DATAEND:
if (e == fe_init)
o.set(TDate(TODAY));
case F_DOCS:
if (e == se_query_add || e == se_query_del)
return false;
break;
case DLG_USER:
if (e == fe_button && jolly > 0)
{
TSheet_field& docs = sfield(F_DOCS);
TToken_string& row = docs.row(docs.selected());
TRectype doc(LF_DOC);
doc.put(DOC_PROVV, 'D');
doc.put(DOC_ANNO, row.get(1));
doc.put(DOC_CODNUM, row.get(2));
doc.put(DOC_TIPODOC, row.get(3));
doc.put(DOC_NDOC, row.get(5));
if (doc.edit())
fill();
}
break;
case DLG_ALL:
{
if (e == fe_button)
{
TSheet_field& docs = sfield(F_DOCS);
TString_array& sht = docs.rows_array();
const int items = sht.items();
if (items > 0)
{
const TString4 select = *(sht.row(0).get(0)) == 'X' ? "" : "X";
for (int i = 0; i < items; i++)
sht.row(i).add(select, 0);
docs.force_update();
}
}
}
break;
case DLG_SAVEREC:
{
if (e == fe_button)
set_err_paf();
}
break;
default: break;
}
if((e == fe_modify || e >= se_enter) && jolly == 0)
{
if (o.dlg() >= START_MASK && o.dlg() <= END_MASK)
{
set_filter_changed();
}
}
return true;
}
void TPA_mask::next_page(int p)
{
bool ok = true;
if (_filter_changed && p != 1000)
{
if ((ok = _filter_changed = check_full_fields()))
{
TSheet_field& sf = sfield(F_DOCS);
fill();
_filter_changed = false;
}
}
if(ok)
TAutomask::next_page(p);
}
bool TPA_mask::check_not_empty()
{
TSheet_field& sheet = sfield(F_DOCS);
TString msg;
if (sheet.empty())
msg = "La tabella dei movimenti <20> vuota, vuoi caricarla con i filtri selezionati?";
else if (_filter_changed)
msg = "I filtri sono stati cambiati, vuoi ricaricare la tabella con i nuovi filtri selezionati?";
if (msg.full() && yesno_box(msg))
{
next_page(1);
}
return sheet.full();
}
bool TPA_mask::check_full_fields() const
{
// Controllo ogni campo che sia valorizzato
FOR_EACH_MASK_FIELD(*this, i, f)
{
if (!f->on_key(K_ENTER))
return false;
}
return true;
}
bool TPA_mask::check_doc_filter(const TDocumentoEsteso& d) const
{
const TString codnum = d.get(DOC_CODNUM);
const TString tipodoc = d.get(DOC_TIPODOC);
const char stato = d.stato();
const TTipo_documento& td = cached_tipodoc(d.get(DOC_TIPODOC));
// Mi precarico la tabella dei documenti scelti
FOR_EACH_SHEET_ROW(sfield(F_DOCUMENTI_TIPO), nr, row)
{
if (codnum.compare(row->get(_codnum)) == 0 && // Codice numerazione
tipodoc.compare(row->get(_tipodoc)) == 0 && // Tipo documento
td.reg_fisc().full() && // Regime fiscale
row->get_char(_dastato) <= stato && // Da stato
row->get_char(_astato) >= stato) // A stato
return true;
}
return false;
}
void TPA_mask::set_err_paf()
{
// Vado a riportare sui paf l'errore
TSheet_field& sfld = sfield(F_DOCS);
TString_array& sht = sfld.rows_array();
TLocalisamfile fdoc(LF_DOC);
if (!sht.empty())
{
TProgress_monitor pi(sht.items(), "Cambio stato fatture");
FOR_EACH_ARRAY_ROW(sht, r, riga)
{
if (!pi.add_status())
break;
if (riga->starts_with("X"))
{
const int anno = riga->get_int(sfield(F_DOCS).cid2index(S_ANNO));
const long ndoc = riga->get_long(sfield(F_DOCS).cid2index(S_NDOC));
const TFixed_string codnum(riga->get(sfield(F_DOCS).cid2index(S_CODNUM))); // lascio sapientemente per ultima la get di una stringa
const TDoc_key key(anno, codnum, ndoc);
// Ricontrollo che la fattura sia presente in Campo prima di cambiare stato
fdoc.zero();
fdoc.put(DOC_PROVV, key.provv());
fdoc.put(DOC_ANNO, key.anno());
fdoc.put(DOC_CODNUM, key.codnum());
fdoc.put(DOC_NDOC, key.ndoc());
TString hfatt, bfatt;
TPaf_record paf0100f("PAF0100F");
if (fdoc.read() == NOERR && chiave_paf(fdoc.curr(), hfatt, bfatt) && paf0100f.search(nullptr, hfatt, bfatt))
{
TString query = "UPDATE PAF0100F SET P1_GESTIONE = 'E' WHERE P1_KEYHEADERFATT = '"; query << hfatt << "' AND P1_KEYBODYFATT = '" << bfatt << "';";
if(!fp_db().sq_set_exec(query))
{
TString err = "Impossibile salvare la fattura "; err << anno << " " << codnum << " " << ndoc << "\nVerr<EFBFBD> saltata.";
error_box(err);
}
}
else
{
TString err = "Impossibile trovare la fattura "; err << anno << " " << codnum << " " << ndoc << "\nVerr<EFBFBD> saltata.";
error_box(err);
}
}
}
fp_db().sq_commit();
}
// Mi sposto nella prima pagina, setto il flag di dirty sul filtro e mi risposto
// Lo faccio perch<63> eliminando la riga direttamente e chiamando la force_update() si crea un bug che cliccando sulla prima riga viene mostrata quella che c'era prima della eliminazione
TAutomask::next_page(0);
set_focus_field(F_DATAINI);
_filter_changed = true;
next_page(1);
}
/////////////////////////////////////////////////////////////////////////////////////
// TDoc2Paf
/////////////////////////////////////////////////////////////////////////////////////
class TDoc2Paf : public TSkeleton_application
{
public:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
TDoc2Paf() {}
};
void TDoc2Paf::main_loop()
{
int ndocs = 0;
TPA_mask mask;
TLocalisamfile doc(LF_DOC);
static const int col_cod_sdi = mask.sfield(F_DOCS).cid2index(S_CODSDI);
while (mask.run() == K_ENTER)
{
TString_array& sht = mask.sfield(F_DOCS).rows_array();
TDoc_fp elab;
//elab.set_cache_insert(true);
if (!sht.empty())
{
TProgress_monitor pi(sht.items(), "Esportazione Fatture");
ndocs = 0;
FOR_EACH_ARRAY_ROW(sht, r, riga)
{
if (!pi.add_status(1))
break;
if (riga->starts_with("X"))
{
const int anno = riga->get_int(mask.sfield(F_DOCS).cid2index(S_ANNO));
const long ndoc = riga->get_long(mask.sfield(F_DOCS).cid2index(S_NDOC));
const TFixed_string codnum(riga->get(mask.sfield(F_DOCS).cid2index(S_CODNUM))); // lascio sapientemente per ultima la get di una stringa
const TDoc_key key(anno, codnum, ndoc);
// Verifico che il codice sdi nello sheet sia lo stesso sulla testata del documento in caso contrario lo aggiorno
TRectype rec_doc = elab.key_to_doc(key);
if(rec_doc.read(doc) == NOERR)
{
if(rec_doc.get(DOC_TIPODOCSDI).compare(riga->get(col_cod_sdi)) != 0)
{
rec_doc.put(DOC_TIPODOCSDI, riga->get(col_cod_sdi));
rec_doc.rewrite(doc);
}
if (elab.doc_to_paf(key))
ndocs++;
else
{
if (!yesno_box("L'ultima fattura non <20> stata esportata, continuare?"))
break;
}
}
}
}
}
if (ndocs > 0)
{
if (elab.commit() <= 0)
error_box("Errore durante il salvataggio");
elab.show_log();
}
}
}
bool TDoc2Paf::create()
{
open_files(LF_TAB, LF_TABCOM, LF_TABMOD, LF_ANAG,
LF_CLIFO, LF_CFVEN, LF_CFBAN, LF_NDITTE,
LF_DOC, LF_RIGHEDOC, 0);
TRectype cfven(LF_CFVEN);
if (cfven.length(CFV_PADESTIN) != 7) // Nuova lunghezza per privati
return error_box(TR("Database non convertito per fatturazione F.P."));
return check_tables() && TSkeleton_application::create();
}
bool TDoc2Paf::destroy()
{
fp_db().sq_disconnect();
return TSkeleton_application::destroy();
}
int fp0300(int argc, char* argv[])
{
TDoc2Paf d2p;
d2p.run(argc, argv, TR("Fatturazione F.P."));
return 0;
}