From ffd5f5c19a4a5a64e35e95f9062f06c061d50f61 Mon Sep 17 00:00:00 2001 From: Simone Palacino Date: Thu, 14 May 2020 23:38:30 +0200 Subject: [PATCH] Patch level : 12.0 no-patch Files correlati : f90.exe Commento : - ESTRAZIONE: - Aggiunto flag esportazione cartacei. - Aggiunta pagina a 'Apri estrazione' per vedere i risultati dell'estrazione (se un mov e' stato saltato e perche'. - Corretta esportazione su tabella F9IVA. - Modificato riconoscimento categoria documentale (da caus cont e tipodoc). - Modificato flag ha vendite esterne in abilita controllo doc elettronici per vendite. - Modificata diagnostica vendite: sono xml solo quegli per italiani, controllo se c'e' il documento elettronico inviato solo se c'e' il flag di controllo vendite. - Aggiunte informazioni di statistica per controllo estrazione. - TABELLA CATEGORIE DOCUMENTALI: - Aggiunta colonna tipodocumento alla tabella delle cat. documentali. - Aggiunto richiamo per causali contabili e per tipi documento. - GESTIONE FILE CARTACEI: - Aggiunto pulsante configurazione (inseririmento estensioni file, cartella doc cartacei). - Modificata finestrella apri file aggiungendo campo per richiamare il movimento da associare. - Aggiunta eliminazione file: i file vengono spostati temporaneamente e eliminati automaticamente dopo un mese. - Implementato caricamento tabella elenco file caricati. - Implementato effettivo caricamento associazione con scrittura su db del file (aggiunto file). --- src/f9/f90100.cpp | 273 ++++++++++++++++++++---------- src/f9/f90100.h | 114 +++++++------ src/f9/f90100a.h | 5 +- src/f9/f90100d.h | 44 +++-- src/f9/f90100d.uml | 218 +++++++++++++++++++----- src/f9/f901tab.h | 12 +- src/f9/f90200a.h | 3 +- src/f9/f90200a.uml | 39 +++-- src/f9/f90300.cpp | 407 ++++++++++++++++++++++++++++++++++----------- src/f9/f90300a.h | 1 + src/f9/f90300a.uml | 27 ++- src/f9/f9lib01.cpp | 298 ++++++++++++++------------------- src/f9/f9lib01.h | 67 ++++++-- 13 files changed, 1010 insertions(+), 498 deletions(-) diff --git a/src/f9/f90100.cpp b/src/f9/f90100.cpp index cf6bbe5dd..e50304720 100644 --- a/src/f9/f90100.cpp +++ b/src/f9/f90100.cpp @@ -9,6 +9,7 @@ #include "f90100b.h" #include "f90100d.h" #include "sqlset.h" +#include "f90100c.h" /** \file f90100.cpp * Per aggiornare le tabelle f9 aggiungere nella cartella "sql\f9\" il file sql cosi' fatto: @@ -79,10 +80,13 @@ TMask& inclusi_mask() { _inclusi_mask = std::make_unique("f90100d.msk"); TMask& m = *_inclusi_mask; - ((TSheet_field&)m.field(S_ESCL)).set_notify(TF9_app::select_escl_notify); // Handler dello sheet per selezione singola + ((TSheet_field&)m.field(S_INCL)).set_notify(TF9_app::select_escl_notify); // Handler dello sheet per selezione singola - TMask& sheet_m = ((TSheet_field&)m.field(S_ESCL)).sheet_mask(); // Maschera dei campi dello sheet + TMask& sheet_m = ((TSheet_field&)m.field(S_INCL)).sheet_mask(); // Maschera dei campi dello sheet sheet_m.set_handler(DLG_USER, TF9_app::mov_handler); // Bottone collega movimento + + TMask& sheet_res = ((TSheet_field&)m.field(S_RES)).sheet_mask(); + sheet_res.set_handler(DLG_USER, TF9_app::mov_handler); } return *_inclusi_mask; } @@ -224,17 +228,19 @@ bool TMonitor_mask::save_conf_handler(TMask_field& f, KEY key) TString old_codsoc = a.get_ambiente(); if(config_mask.get(CF_CODSOC).empty()) warning_box("Codice Ambiente vuoto. Impossibile salvare i dati."); - a.set_ambiente (config_mask.get(CF_CODSOC)); - a.set_addr_doc (config_mask.get(CF_ADDRDOC)); - a.set_has_vendext (config_mask.get_bool(CF_VENDEXT)); - a.set_viewmov (config_mask.get_bool(CF_VIEWMOVPRE)); + a.set_ambiente (config_mask.get(CF_CODSOC)); + a.set_addr_doc (config_mask.get(CF_ADDRDOC)); + a.set_has_cartexp (config_mask.get_bool(CF_CARTEXP)); + a.set_has_checkvend (config_mask.get_bool(CF_CHECKVEND)); + a.set_viewmov (config_mask.get_bool(CF_VIEWMOVPRE)); if (a.get_ambiente().full()) - ini_set_string(CONFIG_DITTA, "F9", AMBIENTE_F9, a.get_ambiente()); + ini_set_string(CONFIG_DITTA, PAR_MOD, AMBIENTE_F9, a.get_ambiente()); if (a.get_addr_doc().full()) - ini_set_string(CONFIG_DITTA, "F9", ADDRCART_F9, a.get_addr_doc()); - ini_set_bool(CONFIG_DITTA, PAR_MOD, VENDEXT_F9, a.get_has_vendext()); - ini_set_bool(CONFIG_DITTA, PAR_MOD, VIEWMOV_F9, a.get_viewmov()); + ini_set_string(CONFIG_DITTA, PAR_MOD, ADDRCART_F9, a.get_addr_doc()); + ini_set_bool(CONFIG_DITTA, PAR_MOD, CHECKVEND_F9, a.get_has_checkvend()); + ini_set_bool(CONFIG_DITTA, PAR_MOD, CARTEXP_F9, a.get_has_cartexp()); + ini_set_bool(CONFIG_DITTA, PAR_MOD, VIEWMOV_F9, a.get_viewmov()); config_mask.close(); a.edit_wa(old_codsoc); return true; @@ -297,7 +303,7 @@ void TMonitor_mask::delete_pack(const bool all) const " IF (@flag_prov = 'P' OR @stato = '" D_GEST_ERR "') BEGIN\n" " DELETE FROM " F9_DRD " WHERE " DRD_CODSOC " = '" << codsoc << "' AND " DRD_ID_EST " = '" << id_estr << "';\n" " DELETE FROM " F9_IVA " WHERE " IVA_CODSOC " = '" << codsoc << "' AND " IVA_IDLAN " = '" << id_estr << "';\n" - " DELETE FROM " F9_MOVESTR " WHERE " MOV_CODSOC " = '" << codsoc << "' AND " MOV_IDESTR " = '" << id_estr << "';\n" + " DELETE FROM " F9_MOVESTR " WHERE " MES_CODSOC " = '" << codsoc << "' AND " MES_IDESTR " = '" << id_estr << "';\n" " END\n" " SELECT @flag_prov AS FLAG, @stato AS STATO;\n" "END"; @@ -399,12 +405,101 @@ bool TMonitor_mask::on_key(const KEY key) return TAutomask::on_key(key); } +void fill_escl(TMask& msk, const char* codsoc, const char* id, const char tipodoc) +{ + TString query; + query << "SELECT " IVA_SEZIVA ", " IVA_DATADOC ", " IVA_NUMDOC ", " IVA_NPROT "\n" + "FROM " F9_IVA "\n" + "WHERE " IVA_CODSOC " = '" << codsoc << "' AND " IVA_IDLAN " = '" << id << "'"; + // REG + DATAREG + PROTIVA + DATAINC + DATA74TER + NUMREG + TString sql; + TSQL_recordset rec(""); + fp_db().sq_set_exec(query, false); + TSheet_field& sf = msk.sfield(S_ESCL); + sf.destroy(); + + TProgress_monitor* prog = new TProgress_monitor(fp_db().sq_items(), "Caricamento dati estrazione..."); + for (bool ok = fp_db().sq_next(); ok; ok = fp_db().sq_next()) + { + if (!prog->add_status()) + break; + + sql.cut(0) << "SELECT NUMREG, DATAREG, DATADOC, CODCAUS, TIPODOC, MESELIQ, NUMDOC, TOTDOC, CODCF, REG, PROTIVA, DESCR\n" + "FROM MOV\n" + "WHERE REG = '" << fp_db().sq_get(IVA_SEZIVA) << "' AND DATADOC=" << TDate(fp_db().sq_get_date(IVA_DATADOC)).date2ansi() << + " AND PROTIVA = " << fp_db().sq_get(IVA_NPROT); + rec.set(sql); + rec.move_first(); + TToken_string& r = sf.row(-1); + r.add(" ", 0); + r.add(rec.get(0).as_string()); // Numreg + r.add(rec.get(1).as_string()); // Data reg + r.add(rec.get(2).as_string()); // Data doc + r.add(rec.get(3).as_string()); // Cod caus + r.add(rec.get(4).as_string()); // Tipo doc + r.add(rec.get(5).as_string()); // Mese liq + r.add(rec.get(6).as_string()); // Num doc + r.add(rec.get(7).as_string()); // Tot doc + r.add(rec.get(8).as_string()); // Clifo + TLocalisamfile clifo(LF_CLIFO); + clifo.put(CLI_CODCF, rec.get(7).as_string()); + clifo.put(CLI_TIPOCF, tipodoc == 'A' ? "F" : "C"); + clifo.read(); + r.add(clifo.get(CLI_RAGSOC)); // Rag soc + r.add(TString(rec.get(9).as_string()) << "/" << rec.get(10).as_string()); // Prot iva + r.add(rec.get(11).as_string()); // Descr + } + delete prog; // Distruggo l'oggetto subito, altrimenti rimane aperta la finestrella. +} + +void fill_res(TMask& msk, const char* codsoc, const char* id, const char tipodoc) +{ + TString query; + query << "SELECT * FROM " F9_MOVESTR "\n" + "WHERE " MES_CODSOC " = '" << codsoc << "' AND " MES_IDESTR " = '" << id << "'"; + + fp_db().sq_set_exec(query, false); + TSheet_field& sf = msk.sfield(S_RES); + sf.destroy(); + + TProgress_monitor* prog = new TProgress_monitor(fp_db().sq_items(), "Caricamento dati estrazione..."); + for (bool ok = fp_db().sq_next(); ok; ok = fp_db().sq_next()) + { + if (!prog->add_status()) + break; + + TLocalisamfile mov(LF_MOV); + mov.put(MOV_NUMREG, fp_db().sq_get(MES_NUMREG)); + mov.read(); + TToken_string& r = sf.row(-1); + r.add(fp_db().sq_get_int(MES_ESTR) ? "X" : " ", 0); // Estratto + r.add(mov.get (MOV_NUMREG)); // Numreg + r.add(mov.get_date(MOV_DATAREG)); // Data reg + r.add(mov.get_date(MOV_DATADOC)); // Data doc + r.add(mov.get (MOV_CODCAUS)); // Cod caus + r.add(mov.get (MOV_TIPODOC)); // Tipo doc + r.add(mov.get_int (MOV_MESELIQ)); // Mese liq + r.add(mov.get (MOV_NUMDOC)); // Num doc + r.add(mov.get_real(MOV_TOTDOC)); // Tot doc + r.add(mov.get_int (MOV_CODCF)); // Clifo + + TLocalisamfile clifo(LF_CLIFO); + clifo.put(CLI_CODCF, mov.get(MOV_CODCF)); + clifo.put(CLI_TIPOCF, mov.get(MOV_TIPO)); + clifo.read(); + + r.add(clifo.get(CLI_RAGSOC)); // Rag soc + r.add(TString(mov.get(MOV_REG)) << "/" << mov.get(MOV_PROTIVA)); // Prot iva + r.add(mov.get(MOV_DESCR)); // Descr + r.add(fp_db().sq_get(MES_ERR)); // Descrizione errore + } + delete prog; // Distruggo l'oggetto subito, altrimenti rimane aperta la finestrella. +} + void TMonitor_mask::open_mostra_estrazione() const { TMask& msk = inclusi_mask(); - //fill - TSheet_field& sf = msk.sfield(S_ESCL); - sf.destroy(); + TString id; TToken_string* _row = nullptr; FOR_EACH_SHEET_ROW(sfield(S_ELAB), nr, row) @@ -427,49 +522,22 @@ void TMonitor_mask::open_mostra_estrazione() const message_box("Selezionare un pacchetto."); return; } - msk.set(F_IIDESTR, _row->get(cid2index(F_IDESTR))); - msk.set(F_IDATA, _row->get(cid2index(F_DATAESTR))); - msk.set(F_IPROV, _row->get(cid2index(F_PROV_B))); - msk.set(F_ITIPOD, _row->get(cid2index(F_TIPODOC))); - msk.set(F_IDAL, _row->get(cid2index(F_DATADAL))); - msk.set(F_IAL, _row->get(cid2index(F_DATAAL))); + msk.set(F_IIDESTR, _row->get(cid2index(F_IDESTR))); + msk.set(F_IDATA, _row->get(cid2index(F_DATAESTR))); + msk.set(F_IPROV, _row->get(cid2index(F_PROV_B))); + msk.set(F_ITIPOD, _row->get(cid2index(F_TIPODOC))); + msk.set(F_IDAL, _row->get(cid2index(F_DATADAL))); + msk.set(F_IAL, _row->get(cid2index(F_DATAAL))); - TString query; - query << "SELECT " IVA_SEZIVA ", " IVA_DATADOC ", " IVA_NUMDOC ", " IVA_NPROT "\n" - "FROM " F9_IVA "\n" - "WHERE " IVA_IDLAN " = '" << id << "'"; + const TString& codsoc = f9_app().get_ambiente(); + const char tipodoc = _row->get(cid2index(F_TIPODOC))[0]; - // REG + DATAREG + PROTIVA + DATAINC + DATA74TER + NUMREG - TString sql; - TSQL_recordset rec(""); - fp_db().sq_set_exec(query, false); - - for (bool ok = fp_db().sq_next(); ok; ok = fp_db().sq_next()) + static TString last_fill_id = 0; + if (last_fill_id != id) { - sql.cut(0) << "SELECT NUMREG, DATAREG, DATADOC, CODCAUS, TIPODOC, MESELIQ, NUMDOC, TOTDOC, CODCF, REG, PROTIVA, DESCR\n" - "FROM MOV\n" - "WHERE REG = '" << fp_db().sq_get(IVA_SEZIVA) << "' AND DATADOC=" << TDate(fp_db().sq_get_date(IVA_DATADOC)).date2ansi() << - " AND PROTIVA = " << fp_db().sq_get(IVA_NPROT); - rec.set(sql); - rec.move_first(); - TToken_string& r = sf.row(-1); - r.add(" ", 0); - r.add(rec.get(rec.find_column(MOV_NUMREG)).as_string()); - r.add(rec.get(1).as_string()); - r.add(rec.get(2).as_string()); - r.add(rec.get(3).as_string()); - r.add(rec.get(4).as_string()); - r.add(rec.get(5).as_string()); - r.add(rec.get(6).as_string()); - r.add(rec.get(7).as_string()); - r.add(rec.get(8).as_string()); // Siamo sicuri? - TLocalisamfile clifo(LF_CLIFO); - clifo.put(CLI_CODCF, rec.get(7).as_string()); - clifo.put(CLI_TIPOCF, _row->get(cid2index(F_TIPODOC))[0] == 'A' ? "F" : "C"); - clifo.read(); - r.add(clifo.get(CLI_RAGSOC)); - r.add(TString(rec.get(8).as_string()) << "/" << rec.get(9).as_string()); - r.add(rec.get(10).as_string()); + fill_escl(msk, codsoc, id, tipodoc); + fill_res (msk, codsoc, id, tipodoc); + last_fill_id = id; } msk.run(); } @@ -487,25 +555,27 @@ void TMonitor_mask::open_win_conf() const if (m == nullptr) { - m = new TMask("Configurazione Archiviazione Sostitutiva", 1, 60, 18); + m = new TMask("Configurazione Archiviazione Sostitutiva", 1, 70, 20); m->add_button_tool(DLG_OK, "Conferma", TOOL_OK); m->add_button_tool(DLG_NULL, "", 0); m->add_button_tool(DLG_QUIT, "Esci", TOOL_QUIT); - m->add_groupbox(CF_CODGROUP, 0, "Codice Ambiente Societa' (WEBAPP):", 1, 0, 59, 3, ""); - m->add_string(CF_CODSOC, 0, "Codice ambiente", 4, 1, 10, "", 10); - m->add_groupbox(CF_ADDRGROUP, 0, "Indicare percorso documenti cartacei:", 1, 3, 59, 3, ""); - m->add_string(CF_ADDRDOC, 0, "Percorso", 2, 4, 256, "", 40); - m->add_groupbox(CF_ESTRGROUP, 0, "Opzioni estrazione", 1, 6, 59, 4, ""); - m->add_boolean(CF_VENDEXT, 0, "Disabilita controllo documenti vendita (no fatturazione vendite)", 2, 7); - m->add_boolean(CF_VIEWMOVPRE, 0, "Visualizza movimenti preparati prima di lanciare l'estrazione", 2, 8); + m->add_groupbox (CF_CODGROUP, 0, "Codice Ambiente Societa' (WEBAPP):", 1, 0, 69, 3, ""); + m->add_string (CF_CODSOC, 0, "Codice ambiente", 4, 1, 10, "", 10); + m->add_groupbox (CF_ADDRGROUP, 0, "Indicare percorso documenti cartacei:", 1, 3, 69, 3, ""); + m->add_string (CF_ADDRDOC, 0, "Percorso", 2, 4, 256, "", 40); + m->add_groupbox (CF_ESTRGROUP, 0, "Opzioni estrazione", 1, 6, 69, 5, ""); + m->add_boolean (CF_CHECKVEND, 0, "Abilita controllo movimenti di vendita: esiste il documento elettronico inviato.", 2, 7); + m->add_boolean (CF_CARTEXP, 0, "Estrai anche documenti cartacei", 2, 8); + m->add_boolean (CF_VIEWMOVPRE, 0, "Visualizza movimenti preparati prima di lanciare l'estrazione", 2, 9, "D"); m->set_handler(DLG_OK, save_conf_handler); m->set(CF_CODSOC, ini_get_string(CONFIG_DITTA, PAR_MOD, AMBIENTE_F9)); m->set(CF_ADDRDOC, ini_get_string(CONFIG_DITTA, PAR_MOD, ADDRCART_F9)); - m->set(CF_VENDEXT, ini_get_bool(CONFIG_DITTA, PAR_MOD, VENDEXT_F9)); + m->set(CF_CHECKVEND, ini_get_bool(CONFIG_DITTA, PAR_MOD, CHECKVEND_F9, true)); + m->set(CF_CARTEXP, ini_get_bool(CONFIG_DITTA, PAR_MOD, CARTEXP_F9)); m->set(CF_VIEWMOVPRE, ini_get_bool(CONFIG_DITTA, PAR_MOD, VIEWMOV_F9)); } m->run(); @@ -1059,6 +1129,10 @@ movimento_t TF9_app::escl2mov(TToken_string* row) t.descr = row->get(11); t.state = null_state; t.descr_err = ""; + + // todo: controllo attributi aggiunti. + t.estratto = true; + t.descr_estr = movimento_t::no_err; return t; } @@ -1084,6 +1158,7 @@ bool TF9_app::estrai_escl_handler(TMask_field&, KEY key) { const auto mov = escl2mov(row); a._estr_escluso->add_mov(mov); + _stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const int stato = a._estr_escluso->estrai(); if (stato == 1) { @@ -1125,7 +1200,8 @@ void TF9_app::edit_wa(TString& old_codsoc) const TString query; if (!old_codsoc.empty()) query << "DELETE FROM " F9_WA " WHERE " WA_CODSOC " = '" << old_codsoc << "';\n"; - query << "INSERT INTO " F9_WA " (" WA_CODSOC ", " WA_ADDR_DOC ") VALUES (" << _config.ambiente << ", " << _config.addr_doc << ");"; + query << "INSERT INTO " F9_WA " (" WA_CODSOC ", " WA_ADDR_DOC ") VALUES (" << + _config.ambiente << ", " << _config.addr_doc << ");"; } int TF9_app::estrai() @@ -1137,15 +1213,16 @@ 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_has_vendext() // Flag in configurazione per staltare controlli vendite + 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_checkvend(), // Flag in configurazione per aggiungere controllo f.e. in vendite + get_has_cartexp() // Flag per estrarre anche i doc. cartacei ); // Leggo i movimenti e li carico nell'estrazione. ///////////// @@ -1153,7 +1230,7 @@ int TF9_app::estrai() query << "SELECT * FROM MOV WHERE DATAREG>=" << dataini.date2ansi() << " AND DATAREG<=" << dataend.date2ansi() << ";"; TSQL_recordset mov(query); - TProgress_monitor progr(mov.items(), "Acquisizione movimenti"); + TProgress_monitor progr(mov.items(), "Acquisizione movimenti", false); TLocalisamfile clifo(LF_CLIFO); const TipoIVA tipo = tipodoc == 'A' ? iva_acquisti : iva_vendite; @@ -1163,13 +1240,15 @@ int TF9_app::estrai() if (!progr.add_status()) break; - TToken_string elab_f9(recset_get_string(mov, MOV_ELABF9), ';'); // Stringa del campo elaborazione f9 nel file mov - const bool escluso = !(elab_f9.items() == 3 && elab_f9.get(2)[0] != 'X' || elab_f9.empty()); - const TCausale caus(recset_get_string(mov, MOV_CODCAUS, 3)); - const bool stampato = recset_get_bool(mov, MOV_REGST); - const TString& numdoc = recset_get_string(mov, MOV_NUMDOC); + TToken_string elab_f9(recset_get_string(mov, MOV_ELABF9), ';'); // Stringa del campo elaborazione f9 nel file mov + const bool escluso = !(elab_f9.items() == 3 && elab_f9.get(2)[0] != 'X' || elab_f9.empty()); + const TCausale caus(recset_get_string(mov, MOV_CODCAUS, 3)); + const bool stampato = recset_get_bool(mov, MOV_REGST); + const TString& numdoc = recset_get_string(mov, MOV_NUMDOC); + const TRegistro& reg = caus.reg(); + const TipoIVA& iva = reg.iva(); // Se definitivo controllo il flag di stampato REGST - if ((flagpro || stampato) && numdoc.full() && caus.reg().iva() == tipo) + if ((flagpro || stampato) && numdoc.full() && iva == tipo) { clifo.zero(); clifo.put(CLI_TIPOCF, tipo == iva_acquisti ? "F" : "C"); @@ -1200,8 +1279,27 @@ int TF9_app::estrai() } } + _stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const result_estr result = _estrazione->estrai(); - +#ifdef DBG + TString msg; + msg << "total: " << (int)_stats.total << "\n"; + if (tipodoc == 'A') + { + msg << "Movimenti saltati: " << (int)_stats.fa_skip << "\n"; + msg << "Movimenti in errore: " << (int)_stats.fa_err << "\n"; + msg << "Movimenti estratti: " << (int)_stats.fa_estr << "\n"; + msg << "Movimenti senza cat. doc.: " << (int)_stats.fa_nocatdoc; + } + else + { + msg << "Movimenti saltati poiche' cartacei: " << (int)_stats.fv_cart_skip << "\n"; + msg << "Movimenti in errore: " << (int)_stats.fv_err << "\n"; + msg << "Movimenti estratti: " << (int)_stats.fv_estr << "\n"; + msg << "Movimenti senza cat. doc.: " << (int)_stats.fv_nocatdoc; + } + message_box(msg); +#endif // Ricalcolo sheet estrazioni _msk->fill(); @@ -1409,14 +1507,17 @@ void TF9_app::main_loop() delete _estr_msk;*/ } -TF9_app& f9_app() +TF9_app::TF9_app() + : _config({ "", "", false, false, false }), _estr_msk(nullptr), _msk(nullptr), _mov_escl("", '|'), + _tipodoc_escl('A'), _flagprov_escl('P'), _estrazione(nullptr), _estr_escluso(nullptr) { - static TF9_app* app = nullptr; - if (app == nullptr) - app = (TF9_app*)&main_app(); - return *app; + _config.ambiente = ini_get_string(CONFIG_DITTA, PAR_MOD, AMBIENTE_F9); + _config.addr_doc = ini_get_string(CONFIG_DITTA, PAR_MOD, ADDRCART_F9); } + + + int f90100(const int argc, char* argv[]) { TF9_app app; diff --git a/src/f9/f90100.h b/src/f9/f90100.h index cbb7c3331..f213d63f2 100644 --- a/src/f9/f90100.h +++ b/src/f9/f90100.h @@ -1,17 +1,18 @@ #ifndef __F90100H__ #define __F90100H__ -#define PAR_MOD "F9" -#define AMBIENTE_F9 "CODSOC" // Codice ambiente (codsoc) -#define ADDRCART_F9 "ADDDOC" // Indirizzo documenti cartacei -#define VENDEXT_F9 "VENDEXT" // Flag no vendite con campo -#define VIEWMOV_F9 "VIEWMOVPRE" // Flag visualizza moviementi prima di estrarre +#define PAR_MOD "F9" +#define AMBIENTE_F9 "CODSOC" // Codice ambiente (codsoc) +#define ADDRCART_F9 "ADDDOC" // Indirizzo documenti cartacei +#define CHECKVEND_F9 "CHECKVEND" // Flag controlli per vendite (quando hai fatt. con Campo) +#define CARTEXP_F9 "CARTEXP" // Flag esporta documenti cartacei +#define VIEWMOV_F9 "VIEWMOVPRE" // Flag visualizza moviementi prima di estrarre #include "execp.h" #include "f90100a.h" #include "f9lib01.h" #include "mov.h" -#include +#include "automask.h" #include "applicat.h" /** class TEstrai_mask @@ -32,9 +33,9 @@ public: TEstrai_mask(); }; -class TEstrai_mask; -class TMonitor_mask; -class TControllo_mask; + + + class TF9_app : public TSkeleton_application { //friend class TEstrai_mask; @@ -46,7 +47,8 @@ class TF9_app : public TSkeleton_application { TString ambiente; // Codice ambiente (codsoc) TString addr_doc; // Indirizzo documenti cartacei - bool vendext; + bool cartexp; + bool checkvend; bool viewmovpre; } _config; // todo: controllare che siano sqlsafe unique_ptr _estr_msk; @@ -62,46 +64,54 @@ class TF9_app : public TSkeleton_application unique_ptr _estrazione; TEstrazione* _estr_escluso; - TDate get_dataini() const { return _estr_msk->get_date(ES_DATAINI); } - TDate get_dataend() const { return _estr_msk->get_date(ES_DATAEND); } - char get_tipodoc() const { return _estr_msk->get(ES_TIPODOC)[0]; } - char get_tipodoc_escl() const { return _tipodoc_escl; } - TipoIVA get_tipoiva() const { return get_tipodoc() == 'A' ? iva_acquisti : iva_vendite; } - TipoIVA get_tipoiva_escl() const { return get_tipodoc_escl() == 'A' ? iva_acquisti : iva_vendite; } - TString get_descr() const { return _estr_msk->get(ES_DESCR); } - bool is_provviso() const { return _estr_msk->get(ES_FLAGPROV)[0] == 'P'; } + TDate get_dataini() const { return _estr_msk->get_date(ES_DATAINI); } + TDate get_dataend() const { return _estr_msk->get_date(ES_DATAEND); } + char get_tipodoc() const { return _estr_msk->get(ES_TIPODOC)[0]; } + char get_tipodoc_escl() const { return _tipodoc_escl; } + TipoIVA get_tipoiva() const { return get_tipodoc() == 'A' ? iva_acquisti : iva_vendite; } + TipoIVA get_tipoiva_escl() const { return get_tipodoc_escl() == 'A' ? iva_acquisti : iva_vendite; } + TString get_descr() const { return _estr_msk->get(ES_DESCR); } + bool is_provviso() const { return _estr_msk->get(ES_FLAGPROV)[0] == 'P'; } + // Dato il codice stato estrazione (es. '01') viene restituito il suo significato a parole. static const char* traduci_stato(const TString& cod); - //void fill(); - public: - const TString& get_ambiente() const { return _config.ambiente; } - const TString& get_addr_doc() const { return _config.addr_doc; } - bool get_has_vendext() const { return _config.vendext; } - bool get_viewmov() const { return _config.viewmovpre; } + const TString& get_ambiente() const { return _config.ambiente; } + const TString& get_addr_doc() const { return _config.addr_doc; } + bool get_has_cartexp() const { return _config.cartexp; } + bool get_has_checkvend() const { return _config.checkvend; } + bool get_viewmov() const { return _config.viewmovpre; } - void set_ambiente(const char* cod) { _config.ambiente.cut(0) << cod; } - void set_addr_doc(const char* add) { _config.addr_doc.cut(0) << add; } - void set_has_vendext(const bool flag) { _config.vendext = flag; } - void set_viewmov(const bool flag) { _config.viewmovpre = flag; } + void set_ambiente(const char* cod) { _config.ambiente.cut(0) << cod; } + void set_addr_doc(const char* add) { _config.addr_doc.cut(0) << add; } + void set_has_cartexp(const bool flag) { _config.cartexp = flag; } + void set_has_checkvend(const bool flag){ _config.checkvend = flag; } + void set_viewmov(const bool flag) { _config.viewmovpre = flag; } + /** Esegue la maschera di inserimento opzioni per avviare l'estrazione. */ void run_estr_msk() const { _estr_msk->run(); } - // Estrazione esclusi + // Estrazione esclusi - handlers + static bool select_escl_notify(TSheet_field& s, int row, KEY key); static bool controllo_escl_handler(TMask_field& field, KEY key); static bool year_handler(TMask_field& field, KEY key); + static bool estrai_escl_handler(TMask_field&, KEY key); + void open_esclusi(); static void fill_esclusi(); + static movimento_t escl2mov(TToken_string* row); - static bool estrai_escl_handler(TMask_field&, KEY key); + static bool mov_handler(TMask_field&, KEY key); static bool mov_handler_escl(TMask_field&, KEY key); + /** Aggiorna tabella F9WA. */ void edit_wa(TString& old_codsoc) const; - /** Caricamento di tutti i movimenti data un periodo di data registrazione. - * \return See TEstrazione::estrai(). + /** Prepara l'estrazione caricando tutti i movimenti dato un periodo (data registrazione), + * e avvia la procedura di estrazione. + * \return See \a TEstrazione::estrai(). */ int estrai(); @@ -111,28 +121,36 @@ public: void add_msg_log(const char* msg); void add_sqlerror_msg_log(const char* query); - bool segna_estratti(bool escluso = false, int numreg = 0); /**< Segna su mov che il movimento e' stato estratto */ - static void segna_in_errore(); - static bool is_autofattura(const TLocalisamfile& mov); - void main_loop() override; + /** Segna su mov che il movimento e' stato estratto. */ + bool segna_estratti(bool escluso = false, int numreg = 0); + /** Segna su DRD che l'estrazione e' in errore diag. gestionale. */ + static void segna_in_errore(); // Controllo e aggiornamento tabelle F9 - bool create_tables() const; /**< Creazione tabelle F9 */ - bool check_tabelle_f9() const; /**< Controllo esistenza delle tabelle e in caso le crea */ - bool aggiorna_tab_f9(int version) const; /**< Aggiorna modifiche alle tabelle F9 come descritto in cima al file .cpp */ - bool check_tab_version() const; /**< Controllo della versione e in caso aggiorna le tabelle */ - bool check_table() const; - TF9_app() : _config({ "", "", false, false }), _estr_msk(nullptr), _msk(nullptr), _mov_escl("", '|'), - _tipodoc_escl('A'), _flagprov_escl('P'), _estrazione(nullptr), _estr_escluso(nullptr) - { - _config.ambiente = ini_get_string(CONFIG_DITTA, PAR_MOD, AMBIENTE_F9); - _config.addr_doc = ini_get_string(CONFIG_DITTA, PAR_MOD, ADDRCART_F9); - } +private: + bool create_tables() const; // Creazione tabelle F9. + bool check_tabelle_f9() const; // Controllo esistenza delle tabelle e in caso le crea. + bool aggiorna_tab_f9(int version) const; // Aggiorna modifiche alle tabelle F9 come descritto in cima al file f90100.cpp. + bool check_tab_version() const; // Controllo della versione e in caso aggiorna le tabelle. + +public: + bool check_table() const; /**< Controllo e aggiornamento versione sql. */ + + void main_loop() override; + + TF9_app(); }; -TF9_app& f9_app(); + +inline TF9_app& f9_app() +{ + static TF9_app* app = nullptr; + if (app == nullptr) + app = (TF9_app*)&main_app(); + return *app; +} class TMonitor_mask : public TAutomask { diff --git a/src/f9/f90100a.h b/src/f9/f90100a.h index 3bd3db2ec..3811021cb 100644 --- a/src/f9/f90100a.h +++ b/src/f9/f90100a.h @@ -50,8 +50,9 @@ #define CF_ADDRGROUP 503 #define CF_ADDRDOC 504 #define CF_ESTRGROUP 505 -#define CF_VENDEXT 506 -#define CF_VIEWMOVPRE 507 +#define CF_CHECKVEND 506 +#define CF_CARTEXP 507 +#define CF_VIEWMOVPRE 508 // Campi maschera descrizione estrazione #define DES_TEXT 501 diff --git a/src/f9/f90100d.h b/src/f9/f90100d.h index 1efabbcaf..af9f30ad7 100644 --- a/src/f9/f90100d.h +++ b/src/f9/f90100d.h @@ -1,5 +1,5 @@ -#define S_ESCL 201 -#define F_ETEXT 202 +#define S_INCL 201 +#define F_ETEXT 202 #define B_ESTRAI 203 #define F_IIDESTR 204 #define F_IDATA 205 @@ -8,17 +8,35 @@ #define F_IDAL 208 #define F_IAL 209 -// Elenco movimenti esclusi -#define F_SEL 101 -#define F_NUMREG 102 -#define F_DATAREG 103 -#define F_DATADOC 104 -#define F_CODCAUS 105 -#define F_TIPOMOV 106 -#define F_MESELIQ 107 -#define F_NUMDOC 108 +#define S_RES 301 + +// Elenco movimenti inclusi +#define F_SEL 101 +#define F_NUMREG 102 +#define F_DATAREG 103 +#define F_DATADOC 104 +#define F_CODCAUS 105 +#define F_TIPOMOV 106 +#define F_MESELIQ 107 +#define F_NUMDOC 108 #define F_IMPTOTDOC 109 #define F_FORN 110 #define F_RAGSOC 111 -#define F_PROTIVA 112 -#define F_DESCR 113 +#define F_PROTIVA 112 +#define F_DESCR 113 + +// Elenco risultato movimenti (S_RES) +#define F_RSEL 101 +#define F_RNUMREG 102 +#define F_RDATAREG 103 +#define F_RDATADOC 104 +#define F_RCODCAUS 105 +#define F_RTIPOMOV 106 +#define F_RMESELIQ 107 +#define F_RNUMDOC 108 +#define F_RIMPTOTDOC 109 +#define F_RFORN 110 +#define F_RRAGSOC 111 +#define F_RPROTIVA 112 +#define F_RDESCR 113 +#define F_RDESCRERR 114 diff --git a/src/f9/f90100d.uml b/src/f9/f90100d.uml index e2b019a60..081dfde14 100644 --- a/src/f9/f90100d.uml +++ b/src/f9/f90100d.uml @@ -72,106 +72,248 @@ END TEXT F_ETEXT BEGIN - PROMPT 0 3 "@BMovimenti estratti nel pacchetto:" + PROMPT 0 3 "@BMovimenti estratti nel pacchetto:" END -SPREADSHEET S_ESCL -1 -1 +SPREADSHEET S_INCL -1 -1 BEGIN - PROMPT 0 4 "Movimenti estratti" - ITEM " " - ITEM "Numero\nReg.@8" - ITEM "Data\nReg.@8" - ITEM "Data\nDoc.@8" - ITEM "Codice\nCaus.@8" - ITEM "Tipo Doc.@5" - ITEM "Mese\nliquidazione@8" - ITEM "Numero\nDocumento@8" - ITEM "Totale\nDocumento@8" - ITEM "Cliente/\nFornitore@8" - ITEM "Ragione\nSociale@8" - ITEM "Cod. regis./\nprot.IVA@8" + PROMPT 0 4 "Movimenti estratti" + ITEM " " + ITEM "Numero\nReg.@8" + ITEM "Data\nReg.@8" + ITEM "Data\nDoc.@8" + ITEM "Codice\nCaus.@8" + ITEM "Tipo Doc.@5" + ITEM "Mese\nliquidazione@8" + ITEM "Numero\nDocumento@8" + ITEM "Totale\nDocumento@8" + ITEM "Cliente/\nFornitore@8" + ITEM "Ragione\nSociale@8" + ITEM "Cod. regis./\nprot.IVA@8" ITEM "Descrizione@8" END + +ENDPAGE + + +PAGE "Risultato estrazione" 0 0 0 0 + +SPREADSHEET S_RES -1 -1 +BEGIN + PROMPT 0 0 "Movimenti" + ITEM "Estratto" + ITEM "Numero\nReg.@8" + ITEM "Data\nReg.@8" + ITEM "Data\nDoc.@8" + ITEM "Codice\nCaus.@8" + ITEM "Tipo Doc.@5" + ITEM "Mese\nliquidazione@8" + ITEM "Numero\nDocumento@8" + ITEM "Totale\nDocumento@8" + ITEM "Cliente/\nFornitore@8" + ITEM "Ragione\nSociale@8" + ITEM "Cod. regis./\nprot.IVA@8" + ITEM "Descrizione@8" + ITEM "Descrizione Errore@30" +END + ENDPAGE ENDMASK + + PAGE "Mov Inclusi" -1 -1 78 13 BOOLEAN F_SEL BEGIN - PROMPT 1 1 "" + PROMPT 1 1 "" END NUMERIC F_NUMREG 7 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 2 "" + FLAGS "D" END DATA F_DATAREG BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 3 "" + FLAGS "D" END DATA F_DATADOC BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 4 "" + FLAGS "D" END STRING F_CODCAUS 3 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 5 "" + FLAGS "D" END STRING F_TIPOMOV 3 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 6 "" + FLAGS "D" END NUMERIC F_MESELIQ 2 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 7 "" + FLAGS "D" END STRING F_NUMDOC 50 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 8 "" + FLAGS "D" END NUMERIC F_IMPTOTDOC 15 2 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 9 "" + FLAGS "D" END NUMERIC F_FORN 6 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 10 "" + FLAGS "D" END STRING F_RAGSOC 80 BEGIN - PROMPT 1 1 "" - FLAGS "D" + PROMPT 1 11 "" + FLAGS "D" END STRING F_PROTIVA 10 BEGIN - PROMPT 1 1 "" + PROMPT 1 12 "" FLAGS "D" END STRING F_DESCR 50 BEGIN - PROMPT 1 1 "" + PROMPT 1 13 "" + FLAGS "D" +END + +ENDPAGE + +TOOLBAR "topbar" 0 0 0 2 + +BUTTON DLG_USER 2 2 +BEGIN + PROMPT 1 1 "Collega" + PICTURE TOOL_LINK +END + +BUTTON DLG_NULL 2 2 +BEGIN + PROMPT -1 0 "" + PICTURE 0 +END + +BUTTON DLG_QUIT 2 2 +BEGIN + PROMPT 3 1 "Fine" + MESSAGE EXIT,K_QUIT + PICTURE TOOL_QUIT +END + +ENPAGE +ENDMASK + + + + +PAGE "Risultato estratti" -1 -1 78 13 + +BOOLEAN F_SEL +BEGIN + PROMPT 1 1 "" + FLAGS "D" +END + +NUMERIC F_RNUMREG 7 +BEGIN + PROMPT 1 2 "" + FLAGS "D" +END + +DATA F_RDATAREG +BEGIN + PROMPT 1 3 "" + FLAGS "D" +END + +DATA F_RDATADOC +BEGIN + PROMPT 1 4 "" + FLAGS "D" +END + +STRING F_RCODCAUS 3 +BEGIN + PROMPT 1 5 "" + FLAGS "D" +END + +STRING F_RTIPOMOV 3 +BEGIN + PROMPT 1 6 "" + FLAGS "D" +END + +NUMERIC F_RMESELIQ 2 +BEGIN + PROMPT 1 7 "" + FLAGS "D" +END + +STRING F_RNUMDOC 50 +BEGIN + PROMPT 1 8 "" + FLAGS "D" +END + +NUMERIC F_RIMPTOTDOC 15 2 +BEGIN + PROMPT 1 9 "" + FLAGS "D" +END + +NUMERIC F_RFORN 6 +BEGIN + PROMPT 1 10 "" + FLAGS "D" +END + +STRING F_RRAGSOC 80 +BEGIN + PROMPT 1 11 "" + FLAGS "D" +END + +STRING F_RPROTIVA 10 +BEGIN + PROMPT 1 12 "" + FLAGS "D" +END + +STRING F_RDESCR 50 +BEGIN + PROMPT 1 13 "" + FLAGS "D" +END + +STRING F_RDESCRERR 87 +BEGIN + PROMPT 1 13 "" FLAGS "D" END diff --git a/src/f9/f901tab.h b/src/f9/f901tab.h index cacc6f5fc..414dd29c0 100644 --- a/src/f9/f901tab.h +++ b/src/f9/f901tab.h @@ -140,9 +140,9 @@ // F9MOVESTR : TABELLA MOVIMENTI ESTRATTI -#define MOV_CODSOC "IDSOC" -#define MOV_IDESTR "IDESTR" -#define MOV_NUMREG "NUMREG" -#define MOV_DATAREG "DATAREG" -#define MOV_ESTR "ESTRATTO" -#define MOV_ERR "DESCR_ERR" +#define MES_CODSOC "IDSOC" +#define MES_IDESTR "IDESTR" +#define MES_NUMREG "NUMREG" +#define MES_DATAREG "DATAREG" +#define MES_ESTR "ESTRATTO" +#define MES_ERR "DESCR_ERR" diff --git a/src/f9/f90200a.h b/src/f9/f90200a.h index 85547f151..ea03f4a68 100644 --- a/src/f9/f90200a.h +++ b/src/f9/f90200a.h @@ -9,5 +9,4 @@ #define F_CAUSSOS 105 #define F_CAUSCONT 106 #define F_TIPOCAUSCONT 107 -#define F_TIPOMOVCONT 108 -#define F_OPERCEE 109 +#define F_OPERCEE 108 diff --git a/src/f9/f90200a.uml b/src/f9/f90200a.uml index 94381619d..7fa3592ac 100644 --- a/src/f9/f90200a.uml +++ b/src/f9/f90200a.uml @@ -61,8 +61,7 @@ BEGIN ITEM "Classe Documentale\nSostitutiva@18" ITEM "Causale per\nSostitutiva (TD01...)@25" ITEM "Causale\nContabile@8" - ITEM "Tipo Causale\nContabile@8" - ITEM "Tipo Movimento\nContabile@10" + ITEM "Tipo\nDocumento@6" ITEM "Classificazione\nCategoria@14" END @@ -79,17 +78,17 @@ END STRING F_CATDOC 10 BEGIN - PROMPT 0 0 "Categoria Documento" + PROMPT 1 2 "Categoria Documento" END STRING F_DESCRDOC 30 BEGIN - PROMPT 0 0 "Descrizione Documento" + PROMPT 1 3 "Descrizione Documento" END LIST F_CLASDOCSOS 3 24 BEGIN - PROMPT 0 0 "" + PROMPT 1 4 "" FLAGS "" ITEM "FTA|FTA - Fattura Acquisti" ITEM "FTV|FTV - Fattura di Vendita" @@ -97,7 +96,7 @@ END LIST F_CAUSSOS 4 33 BEGIN - PROMPT 0 0 "" + PROMPT 1 5 "" FLAGS "" ITEM "" ITEM "TD01|TD01 Fattura" @@ -111,22 +110,32 @@ END STRING F_CAUSCONT 6 BEGIN - PROMPT 0 0 "Causale Contabile" + PROMPT 1 6 "Causale Contabile" + USE 26 + INPUT CODCAUS F_CAUSCONT + DISPLAY "Codice" CODCAUS + DISPLAY "Descrizione@50" DESCR + OUTPUT F_CAUSCONT CODCAUS + CHECKTYPE NORMAL + FLAG "U" END -STRING F_TIPOCAUSCONT 6 +STRING F_TIPOCAUSCONT 2 BEGIN - PROMPT 0 0 "Tipo Causale Contabile" -END - -STRING F_TIPOMOVCONT 6 -BEGIN - PROMPT 0 0 "Tipo Movimento Contabile" + PROMPT 1 7 "Tipo Documento" + USE %TPD + INPUT CODTAB F_TIPOCAUSCONT + DISPLAY "Tipo " CODTAB + DISPLAY "Descrizione @50" S0 + OUTPUT F_TIPOCAUSCONT CODTAB + WARNING "Tipo documento errato" + CHECKTYPE NORMAL + FLAG "U" END LIST F_OPERCEE 2 14 BEGIN - PROMPT 0 0 "Operatore CEE" + PROMPT 1 8 "Operatore CEE" ITEM "|" ITEM "BD|Bolla Doganale" ITEM "RC|Reverse Charge" diff --git a/src/f9/f90300.cpp b/src/f9/f90300.cpp index 1a9c07cbe..8fc75bba8 100644 --- a/src/f9/f90300.cpp +++ b/src/f9/f90300.cpp @@ -1,75 +1,42 @@ #include "f90.h" + +#include +#include +#include +#include + #include "applicat.h" #include "automask.h" #include "f90300a.h" #include "urldefid.h" #include "utility.h" -#include -#include +#include "f90300b.h" +#include "mov.h" +#include "isam.h" +#include "f9cart.h" -#define INI_ESTENSIONI "DOCUMENTI_EXT" - -#define F_ADDRGROUP 101 -#define F_ADDRESS 102 -#define F_DIRECTORY 103 +#define INI_ESTENSIONI "DOCUMENTI_EXT" +#define TABMOD_CARTDIR "S0" +#define F9_ADDRCART "ADDRCART" /////////////////////////////////////////////////////////////////////////////// -// TGestione_doc_cartacei_f9_msk -/////////////////////////////////////////////////////////////////////////////// -#define TAutomask TMask +// TImport_msk -class TImport_msk : public TAutomask +class TImport_msk : public TMask { friend class TGestione_doc_cartacei_f9_msk; - static bool addr_handler(TMask_field& field, KEY key); - static bool dir_handler(TMask_field& field, KEY key); - static bool ok_handler(TMask_field& field, KEY key); - -#ifndef TAutomask - bool on_field_event(TOperable_field& o, TField_event e, long jolly) override; -#endif + static bool ok_handler(TMask_field& field, KEY key) + { + field.mask().send_key(K_ENTER, DLG_OK); + return true; + } + public: - TImport_msk(); + TImport_msk() : TMask("f90300b") { } }; -bool TImport_msk::addr_handler(TMask_field& field, KEY key) -{ - if (field.dirty() && key != K_TAB) - field.set(""); - return true; -} -bool TImport_msk::dir_handler(TMask_field& field, KEY key) -{ - if(field.dirty() && key != K_TAB) - field.set(""); - return true; -} - -bool TImport_msk::ok_handler(TMask_field& field, KEY key) -{ - field.mask().send_key(K_ENTER, DLG_OK); - return true; -} - -TImport_msk::TImport_msk() : TAutomask("Apri...", 0, 78, 10) -{ - add_button_tool(DLG_OK, "Conferma", TOOL_OK); - add_button_tool(DLG_NULL, "", 0); - add_button_tool(DLG_QUIT, "Esci", TOOL_QUIT); - - add_groupbox(F_ADDRGROUP, 0, "", 1, 0, 76, 6, ""); - add_static( DLG_NULL, 0, "@BInserire percorso file.", 2, 1); - add_string( F_ADDRESS, 0, "Apri: ", 2, 2, 255, "B", 64).set_selector('F', EMPTY_STRING); - add_static( DLG_NULL, 0, "@BOppure, inserire percorso cartella per inserimento multiplo.", 2, 3); - add_string( F_DIRECTORY, 0, "Apri da:", 2, 4, 255, "B", 64).set_selector('D', EMPTY_STRING); - - TMask::set_handler(F_ADDRESS, addr_handler); - TMask::set_handler(F_DIRECTORY, dir_handler); -} - -#undef TAutomask /////////////////////////////////////////////////////////////////////////////// @@ -78,21 +45,35 @@ TImport_msk::TImport_msk() : TAutomask("Apri...", 0, 78, 10) class TGestione_doc_cartacei_f9_msk : public TAutomask { - std::unique_ptr _import_msk; - std::unique_ptr> _extensions; + struct doc_cart_t + { + TString filename; + TString loaddate; + TString numreg; + TString user; + }; + TString _addr_cart; // Indirizzo cartella doc. cartacei F9 + std::unique_ptr> _extensions; // todo: controllare che con TString funzioni l'ordinamento, quindi la find + std::unique_ptr _import_msk; + std::map _list_file; bool on_field_event(TOperable_field& o, TField_event e, long jolly) override; - void fill(); /* todo */ - static TToken_string& get_valid_extensions(); /* */ - void load_dir(const TString& dir); /* Carica i file della cartella specificata, controllandone l'estensione. */ - void load_extensions(); /* Lazy initialization for _extensions. */ - void load_file(const TFilename& file); /* Carica singolo file. */ - void open_import_win(); /* Esegue la maschera di importazione files (Lazy initilization). */ - bool verify_extension(const TFilename& file); /* Verifica che l'estensione del file sia valida. */ + static void check_deleted(); + bool check_file_exist(const TString& file) const; + void delete_file(); + bool doc_already_exists(_In_ const TFilename& file, _Out_ TString& numreg) const; + void fill(); + static TString get_addrcart(); + static TToken_string& get_valid_extensions(); + void load_extensions(); + bool load_file(const TFilename& file, const TString& numreg); + void open_config_win() const; + void open_import_win(); + bool verify_extension(const TFilename& file); public: - TGestione_doc_cartacei_f9_msk() : TAutomask("f90300a") { } + TGestione_doc_cartacei_f9_msk(); }; bool TGestione_doc_cartacei_f9_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) @@ -100,15 +81,156 @@ bool TGestione_doc_cartacei_f9_msk::on_field_event(TOperable_field& o, TField_ev if(e == se_query_add || e == se_query_del || e == se_query_modify) return false; - if (o.dlg() == B_IMPORT && e == fe_button) - open_import_win(); - + switch (o.dlg()) + { + case B_IMPORT: + if (e == fe_button) + open_import_win(); + break; + case B_DELETE: + if (e == fe_button) + delete_file(); + break; + case B_CONFIG: + if (e == fe_button) + open_config_win(); + default: break; + } return true; } +void TGestione_doc_cartacei_f9_msk::check_deleted() +{ + // Controllo che non ci siano file nella cartella eliminati da piu' di un mese, altrimenti li elimino + TString_array result; + TString s = get_addrcart(); s << "eliminati\\"; + list_files(s, result); + FOR_EACH_ARRAY_ITEM(result, nr, file) + { + const char* deletedfile = *(TString*)(file); + HANDLE h_file = CreateFile(deletedfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + FILETIME last_access_time; + SYSTEMTIME time; + bool flag = false; + if (h_file != INVALID_HANDLE_VALUE) + { + if(GetFileTime(h_file, NULL, &last_access_time, NULL)) + { + FileTimeToSystemTime(&last_access_time, &time); + TDate today = TDate(TODAY); + if(time.wMonth < (unsigned short)today.month() - 1 || + time.wMonth == (unsigned short)today.month() - 1 && time.wDay <= (unsigned short)today.day()) + { + flag = true; + CloseHandle(h_file); + DeleteFile(deletedfile); + } + } + } + if(!flag) + CloseHandle(h_file); + } +} + +bool TGestione_doc_cartacei_f9_msk::check_file_exist(const TString& file) const +{ + TFilename path(_addr_cart); + path.slash_terminate() << file; + return path.exist(); +} + +void TGestione_doc_cartacei_f9_msk::delete_file() +{ + TSheet_field& sf = sfield(S_IMPORTED); + FOR_EACH_SHEET_ROW(sf, nr, row) + { + if (row->starts_with("X")) + { + TLocalisamfile f9cart(LF_F9CART); + f9cart.setkey(2); + const char* filename = row->get(cid2index(F_FILENAME)); + const char* numreg = row->get(cid2index(104)); + f9cart.put(F9C_FILENAME, filename); + f9cart.put(F9C_NUMREG, numreg); + f9cart.read(); + TFilename filecart = get_addrcart(); filecart << filename; + TFilename deleted = get_addrcart(); deleted << "eliminati" << SLASH; + if (!deleted.exist()) + make_dir(deleted); + deleted << filename; + if (deleted.exist()) + DeleteFile(deleted); + if (!MoveFile(filecart, deleted)) + warning_box(TString("Attenzione:") << " non e' stato possibile rimuovere questo file: " << filecart); + else + f9cart.remove(); + } + } + fill(); +} + +bool TGestione_doc_cartacei_f9_msk::doc_already_exists(const TFilename& file, TString& numreg) const +{ + const auto it = _list_file.find(file); + if (it != _list_file.end()) + { + numreg = it->second.numreg; + return true; + } + numreg = ""; + return false; +} + void TGestione_doc_cartacei_f9_msk::fill() { - // todo + TLocalisamfile files(LF_F9CART); + TLocalisamfile mov(LF_MOV); + TSheet_field& sf = sfield(S_IMPORTED); + sf.hide(); + sf.destroy(); + _list_file.clear(); + std::vector file_err; + if(files.first() == NOERR) + { + do + { + const TString& namefile = files.get(F9C_FILENAME); + if(!check_file_exist(namefile)) + file_err.emplace_back(namefile); + const TString& numreg = files.get(F9C_NUMREG); + TString datamov, caus, numdoc, nprot, descrmov; + mov.zero(); + mov.put(MOV_NUMREG, numreg); + if(mov.read() == NOERR) + { + datamov = mov.get(MOV_DATAREG); + caus = mov.get(MOV_CODCAUS); + numdoc = mov.get(MOV_NUMDOCEXT); + if(numdoc.empty()) numdoc = mov.get(MOV_NUMDOC); + nprot = mov.get(MOV_PROTIVA); + descrmov = mov.get(MOV_DESCR); + } + TToken_string& r = sf.row(-1); + r.add(" ", 0); // F_SEL + r.add(namefile); // F_FILENAME + r.add(files.get(F9C_LOADDATE)); // F_DATACARIC + r.add(numreg); // F_NUMREG + r.add(datamov); // F_DATAMOV + r.add(caus); // F_CAUS + r.add(numdoc); // F_NUMDOC + r.add(nprot); // F_NPROTOCOL + r.add(descrmov); // F_DESCRMOV + + _list_file.insert({ namefile, { namefile, files.get(F9C_LOADDATE), numreg, files.get(F9C_USER) } }); + } while (files.next() == NOERR); + sf.force_update(); + } + sf.show(); +} + +TString TGestione_doc_cartacei_f9_msk::get_addrcart() +{ + return ini_get_string(CONFIG_DITTA, "F9", F9_ADDRCART); } TToken_string& TGestione_doc_cartacei_f9_msk::get_valid_extensions() @@ -123,26 +245,11 @@ TToken_string& TGestione_doc_cartacei_f9_msk::get_valid_extensions() return ext; } -void TGestione_doc_cartacei_f9_msk::load_dir(const TString& dir) -{ - TFilename path(dir); - TString_array flist; - //bool* lookup_t = new bool[flist.items()]; - path.add("*.*"); // Qualsiasi file con estensione, controllo dopo. - list_files(path, flist); - FOR_EACH_ARRAY_ROW(flist, nr, file) - { - TFilename f(*file); - if (verify_extension(f)) - load_file(f); - } -} - void TGestione_doc_cartacei_f9_msk::load_extensions() { if (_extensions == nullptr) { - _extensions = std::make_unique>(); + _extensions = std::make_unique>(); TToken_string& ext = get_valid_extensions(); for (int i = 0; i < ext.items(); ++i) { @@ -151,15 +258,114 @@ void TGestione_doc_cartacei_f9_msk::load_extensions() { if (e.starts_with(".")) e.ltrim(1); - _extensions->insert(std::string(e)); + _extensions->insert(e); } } } } -void TGestione_doc_cartacei_f9_msk::load_file(const TFilename& file) +bool TGestione_doc_cartacei_f9_msk::load_file(const TFilename& file, const TString& numreg) { - // todo + TString numreg_old; + if(doc_already_exists(file, numreg_old)) + { + error_box(TString("Attenzione:") << "esiste gia' un documento con questo nome associato al num. di registrazione " << numreg_old); + return false; + } + + TLocalisamfile f9cart(LF_F9CART); + f9cart.put(F9C_FILENAME, file.name()); + f9cart.put(F9C_LOADDATE, TDate(TODAY)); + f9cart.put(F9C_NUMREG, numreg); +#ifdef DBG + const TString n_user = user(); + if (n_user.empty()) + message_box("Attenzione nome utente vuoto!"); + f9cart.put(F9C_USER, n_user); +#else + f9cart.put(F9C_USER, user()); +#endif + TFilename fdestin = get_addrcart(); + const TString filename = file.name(); + fdestin << filename; + const bool ok = CopyFile(file, fdestin, true); + if (!ok) + { + if(fdestin.exist()) + warning_box("Errore nel copiare il file nella cartella di destinazione.\nEsiste gia' un file con questo nome."); + else + warning_box("Errore nel copiare il file nella cartella di destinazione. Ritentare."); + f9cart.zero(); + return false; + } + f9cart.write(); + f9cart.rewrite(); + return true; +} + +void TGestione_doc_cartacei_f9_msk::open_config_win() const +{ + static std::unique_ptr msk; + if(msk == nullptr) + { + msk = std::make_unique("Configurazione", 1, 78, 14); + msk->add_button_tool(DLG_OK, "Conferma", TOOL_OK); + msk->add_button_tool(DLG_NULL, "", 0); + msk->add_button_tool(DLG_QUIT, "Esci", TOOL_QUIT); + + msk->add_groupbox(DLG_NULL, 0, "", 1, 0, 76, 4, ""); + msk->add_static (DLG_NULL, 0, "@BInserire estensioni file riconosciute, separate da virgola.", 2, 1); + msk->add_string (101, 0, "Estensioni:", 2, 2, 255, "", 60); + msk->add_groupbox(DLG_NULL, 0, "@BCartella documenti cartacei", 1, 4, 76, 4); + msk->add_static (DLG_NULL, 0, "@BInserire nome cartella, all'interno della area dati della ditta", 2, 5); + msk->add_string (102, 0, "", 2, 6, 64, "", 30); + + msk->set(101, ini_get_string(CONFIG_DITTA, "F9", INI_ESTENSIONI)); + TString s = ini_get_string(CONFIG_DITTA, "F9", F9_ADDRCART); + s.rtrim(1); + s.ltrim(s.rfind('\\') + 1); + msk->set(102, s); + } + + while (true) + { + if (msk->run() != K_ENTER) + { + if (msk->get(102).empty()) + { + warning_box("Si prega di inserire il nome della cartella per i documenti cartacei."); + continue; + } + else break; + } + ini_set_string(CONFIG_DITTA, "F9", INI_ESTENSIONI, msk->get(101)); + TString dir = msk->get(102); + if (dir.empty()) + { + if(yesno_box("Nome cartella vuoto.\nCreare cartella con nome 'Cartacei_F9'?")) + msk->set(102, dir = "Cartacei_F9"); + else continue; + } + + TFilename path(prefix().get_studio()); + path.slash_terminate() << dir; + path.slash_terminate(); + if (!path.exist()) + { + if (dir == "Cartacei_F9" || yesno_box("Il percorso indicato e' inesistente.\nCreare la cartella con questo nome?")) + { + if (!make_dir(path)) + { + warning_box("Impossibile creare il percorso specificato."); + continue; + } + } + else continue; + } + ini_set_string(CONFIG_DITTA, "F9", F9_ADDRCART, path); + + break; + } } void TGestione_doc_cartacei_f9_msk::open_import_win() @@ -168,19 +374,21 @@ void TGestione_doc_cartacei_f9_msk::open_import_win() _import_msk = make_unique(); while(_import_msk->run() == K_ENTER) { - const TString& file = _import_msk->get(F_ADDRESS); - const TString& dir = _import_msk->get(F_DIRECTORY); - if(file.empty()) - load_dir(dir); - else + const TString& file = _import_msk->get(F_IMPADDRESS); + const TString& numreg = _import_msk->get(F_IMPNUMREG); + if (!file.empty()) { TFilename f(file); if (verify_extension(f)) - load_file(f); + { + if (load_file(f, numreg)) + message_box("File caricato."); + } else warning_box("Questo file e' in un formato non accettato."); } } + fill(); } bool TGestione_doc_cartacei_f9_msk::verify_extension(const TFilename& file) @@ -189,7 +397,16 @@ bool TGestione_doc_cartacei_f9_msk::verify_extension(const TFilename& file) return _extensions->find(file.ext()) != _extensions->end(); } - +TGestione_doc_cartacei_f9_msk::TGestione_doc_cartacei_f9_msk(): TAutomask("f90300a"), _addr_cart(get_addrcart()) +{ + if (_addr_cart.empty()) + { + message_box("Inserire nome cartella documenti cartacei."); + open_config_win(); + } + check_deleted(); + fill(); +} /////////////////////////////////////////////////////////////////////////////// diff --git a/src/f9/f90300a.h b/src/f9/f90300a.h index 038e81414..e9c7856fb 100644 --- a/src/f9/f90300a.h +++ b/src/f9/f90300a.h @@ -1,5 +1,6 @@ #define B_IMPORT 201 #define B_DELETE 202 +#define B_CONFIG 203 #define S_IMPORTED 301 diff --git a/src/f9/f90300a.uml b/src/f9/f90300a.uml index 3950fea19..8a6f542b7 100644 --- a/src/f9/f90300a.uml +++ b/src/f9/f90300a.uml @@ -20,6 +20,19 @@ BEGIN PICTURE 0 END +BUTTON B_CONFIG 2 2 +BEGIN + PROMPT 1 1 "Settin~gs" + PICTURE TOOL_CONFIG + FLAGS "" +END + +BUTTON DLG_NULL 2 2 +BEGIN + PROMPT -1 1 "" + PICTURE 0 +END + BUTTON DLG_INFO 2 2 BEGIN PROMPT 1 1 "Info" @@ -89,6 +102,18 @@ END NUMBER F_NUMREG 7 BEGIN PROMPT 0 3 "Numero registrazione" + USE MOV + INPUT NUMREG F_NUMREG + DISPLAY "Numero" NUMREG + DISPLAY "Data " DATAREG + DISPLAY "Causale" CODCAUS + DISPLAY "Num. Doc." NUMDOC + DISPLAY "N. esteso" NUMDOCEXT + DISPLAY "Prot. IVA" PROTIVA + DISPLAY "Descrizione" DESCR + OUTPUT F_NUMREG NUMREG + CHECKTYPE NORMAL + FLAG "U" END DATE F_DATAMOV @@ -119,4 +144,4 @@ END ENDPAGE -ENDMASK +ENDMASK \ No newline at end of file diff --git a/src/f9/f9lib01.cpp b/src/f9/f9lib01.cpp index 888616f8f..11be372cb 100644 --- a/src/f9/f9lib01.cpp +++ b/src/f9/f9lib01.cpp @@ -7,6 +7,9 @@ #include "mov.h" #include "../fp/fplib.h" + +statistics _stats = { 0 }; + // Controlla eventuali apostrofi e li raddoppia const char* check_str(const TString& str); @@ -19,15 +22,15 @@ const char* TEstrazione::categoria_doc() return ""; // todo: } -const char* TEstrazione::caus_sos(const TLocalisamfile& mov, TipoIVA acquisti) +const char* TEstrazione::caus_sos(const TLocalisamfile& mov, const TipoIVA iva) { - if (acquisti == iva_acquisti) + if (iva == iva_acquisti) { TToken_string keys(mov.get(MOV_KEYFPPRO)); fppro_db().set_keys(keys); return fppro_db().get_tipodoc(); } - if (acquisti == iva_vendite) + 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; @@ -36,6 +39,26 @@ const char* TEstrazione::caus_sos(const TLocalisamfile& mov, TipoIVA acquisti) 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); @@ -82,20 +105,14 @@ bool TEstrazione::check_periodo_def() const bool TEstrazione::is_doc_xml(const TLocalisamfile& mov) { - const char provv = mov.get(MOV_DPROVV)[0]; - const int anno = mov.get_int(MOV_DANNO); - const TString& codnum = mov.get(MOV_DCODNUM); - const int numdoc = mov.get_int(MOV_DNDOC); - - const TDocumento doc(provv, anno, codnum, numdoc); - TString hfatt(20), bfatt(50), query; - 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; - } - return false; + 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 } TString& TEstrazione::drd_attr() @@ -132,7 +149,7 @@ bool TEstrazione::insert_into_f9movestr() const bool ok = true; for(auto it = _movs.begin(); it != _movs.end(); ++it) { - query.cut(0) << "INSERT INTO " F9_MOVESTR " (" MOV_CODSOC ", IDESTR, NUMREG, DATAREG, ESTRATTO, DESCR_ERR)\nVALUES " << + 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 @@ -268,17 +285,17 @@ 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; #ifdef DBG - if (it->numreg == 96963) + if (it->numreg == 96153) bool simo = true; #endif // Se escluso passo avanti @@ -300,13 +317,14 @@ const char* TEstrazione::diagnostica_mov() break; // ERRORS - // Errore non bloccante + // 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; + 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 @@ -332,12 +350,17 @@ const char* TEstrazione::diagnostica_mov() mov_i.state = res; default: break; } - +#ifdef DBG + if (mov_i.numreg == 95954) + bool simo = true; +#endif + 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().causcont2cat(mov_i.codcaus); + 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; @@ -347,7 +370,6 @@ const char* TEstrazione::diagnostica_mov() 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) { @@ -355,113 +377,55 @@ const char* TEstrazione::diagnostica_mov() break; //TToken_string& row = *it; movimento_t& mov_i = *it; - TString numreg(mov_i.numreg); + TString numreg; numreg << mov_i.numreg; TLocalisamfile mov(LF_MOV); mov.put(MOV_NUMREG, numreg); - mov.read(); - - /* Qui la situazione e' bruttina. - * Se non hai il flag di documenti esterni, sono in grado di capire se il movimento corrisponde a un documento elettronico - * che effettivamente e' stato inviato. - * - Quindi prima di tutto se non ho il flag attivo, controllo che esista il documento "generatore". Altrimenti lo escludo. - * - Guardo se ha il flag di invio xml e controllo sui PAF, altrimento la considero come cartacea. +#ifdef DBG + if(mov.read() != NOERR) + warning_box("OOOOOOOOOHH! E DICE SIII!!"); + if (mov_i.numreg == 95677) + 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) { - bool cartacea = false; - if (!_has_vendext) + const bool cartacea = !is_doc_xml(mov); + bool exist_doc; + if(!_has_cartacei && cartacea) // Se non devo esportare i cartacei e questa e' cartacea la salto (non errore) { - if (!mov.get(MOV_DPROVV).empty() && !mov.get(MOV_DANNO).empty() && !mov.get(MOV_DCODNUM).empty() && !mov.get(MOV_DNDOC).empty()) - { - if (!is_doc_xml(mov)) - cartacea = true; - // Nel caso in cui non ha l'invio xml e non trovo la categoria vendite cartacea escludo come nella versione precedente, - // non trovo la fattura elettronica. - std::shared_ptr cd = categorie_doc().causcont2cat(mov_i.codcaus, cartacea); - mov_i.estratto = cd.get(); - mov_i.descr_estr = cd ? movimento_t::no_err : movimento_t::no_catdoc; - mov_i.catdoc = cd; - if(!cd->catdoc) - { - mov_i.err = true; - mov_i.descr_err = "Movimento collegato a un documento senza fatturazione elettronica. Escludere? O aggiungere cat. doc."; - mov_i.descr_estr = movimento_t::notfound_elet; - } - else - mov_i.err = false; - } - else - { - // Escludo - 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?"; - } + ++_stats.fv_cart_skip; + mov_i.err = false; + mov_i.estratto = false; + mov_i.descr_estr = movimento_t::no_cartaceo; + } + else if(!cartacea && _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 { - // Ricerca cat. doc. senza controllare documento originale e quindi perdendo anche la possbilita' di distinguere se - // semplicemente una vendita cartacea. - std::shared_ptr cd = categorie_doc().causcont2cat(mov_i.codcaus); + std::shared_ptr cd = categorie_doc().mov2cat(mov_i.numreg); mov_i.estratto = cd.get(); + mov_i.err = false; 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; } - ok &= !mov_i.err; } - //else Salto il mov - - - - - - - ///* Categorie documentali. Come per gli acquisti. */ - //if (!mov_i.err && mov_i.estratto) - //{ - // 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; - //} - - //if (mov_i.catdoc && !mov_i.catdoc->is_cartaceo()) - //{ - // // 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; - // } - // } - //} + ok &= !mov_i.err; } } _head.stato_estr = ok ? D_GEST_OK : D_GEST_ERR; @@ -502,8 +466,7 @@ result_estr TEstrazione::estrai() // 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.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. @@ -540,7 +503,6 @@ result_estr TEstrazione::estrai() // 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; - return res; } @@ -554,7 +516,8 @@ bool TEstrazione::estrazione_iva(bool escluso) { if (!bar.add_status()) break; - + if (!it->estratto) + continue; TLocalisamfile mov(LF_MOV); TLocalisamfile cli(LF_CLIFO); mov.put(MOV_NUMREG, it->numreg); @@ -599,11 +562,10 @@ bool TEstrazione::estrazione_iva(bool escluso) const TString& name_reg = TRegistro(TCausale(mov.get(MOV_CODCAUS)).reg()).name(); const TString classdoc = it->catdoc->class_sost; - const TString nomefile = it->catdoc->is_cartaceo() ? "nomefile.pdf" : ""; // todo: + const TString nomefile = it->is_cartaceo() ? "nomefile.pdf" : ""; // todo: // todo usare per categorie documentali caus_sos(mov, get_tipoiva()); - query << "\n)\n" << "VALUES (\n" << "'" << _head.cod_soc << "', '" << _head.id_estr << "', '" << (_head.flag_prov ? "P" : "D") << "',\n" << @@ -631,7 +593,7 @@ bool TEstrazione::estrazione_iva(bool escluso) "'" << fppro_db().get_tipoprot() << "', '" << fppro_db().get_numprot() << "', '" << fppro_db().get_annoprot() << "', '" << fppro_db().get_dataoraric() << "'"; } query << "\n)"; - const bool ok = fp_db().sq_set_exec(query); + const bool ok = fp_db().sq_set_exec(query) && fp_db().sq_commit(); if (!ok) write_errorsql_log(query); @@ -670,8 +632,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, const bool has_vendext) - : _descr(descr), _has_vendext(has_vendext) + 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; @@ -820,25 +782,25 @@ TF9_dberr::TF9_dberr() // TCategorie_doc /////////////////////////////////////////////////////////////////////////////////////////// -bool TCategorie_doc::classe_doc::is_cartaceo() const +std::shared_ptr TCategorie_doc::find_causcont(const TString& caus) { - return !opcee.empty(); + for (auto it = _rows.begin(); it != _rows.end(); ++it) + { + if ((*it)->causcont == caus) + return *it; + } + return nullptr; } -vector::iterator TCategorie_doc::find(const TString& class_sost, const TString& caus_sost, - const TString& op_cee) +std::shared_ptr TCategorie_doc::find_tipodoc(const TString& tipodoc) { - vector::iterator a = _rows.end(); - for(auto it = _rows.begin(); it != _rows.end(); ++it) + for (auto it = _rows.begin(); it != _rows.end(); ++it) { - classe_doc& cd = *it; - if(cd.class_sost == class_sost && cd.caus_sost == caus_sost && cd.opcee == op_cee) - { - a = it; - break; - } + const std::shared_ptr& classe = *it; + if (classe->causcont.empty() && classe->tipocaus == tipodoc) + return *it; } - return a; + return nullptr; } void TCategorie_doc::load_all() @@ -851,46 +813,28 @@ void TCategorie_doc::load_all() 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(cd); + _rows.emplace_back(std::make_shared(cd)); } } -std::shared_ptr TCategorie_doc::causcont2cat(const char* caus, bool force_cartacea) // todo: force_cartacea per le vendite +std::shared_ptr TCategorie_doc::mov2cat(const int numreg) { - const TCausale c(caus); - const TString& tipodoc = c.tipo_doc(); - const tipo_movimento tipomov = c.tipomov(); - const int reg_speciva = c.regime_speciale(); - const bool op_intra = c.intra(); - TString class_sost, caus_sost, op_cee; - if(tipodoc == "FA") - { - class_sost = "FTA"; - } - else if(tipodoc == "FV") - { - class_sost = "FTV"; - } - else if(tipodoc == "BD") - { - class_sost = "FTA"; - op_cee = "BD"; - } + // 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(); - if(tipomov == tm_fattura) - { - caus_sost = "TD01"; - } - else if(tipomov == tm_nota_credito) - { - caus_sost = "TD04"; - } + const TString& caus = mov.get(MOV_CODCAUS); + const TCausale c(caus); + const TString& tipodoc = c.tipo_doc(); - const vector::iterator it = find(class_sost, caus_sost, op_cee); - std::shared_ptr cd = nullptr; - if (it != _rows.end()) - cd = std::make_shared(*it); // Creo una copia e la restituisco. todo: Test it! - return cd; + // 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); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/f9/f9lib01.h b/src/f9/f9lib01.h index f11e9cd5a..58aa1a4fe 100644 --- a/src/f9/f9lib01.h +++ b/src/f9/f9lib01.h @@ -9,6 +9,20 @@ const TDate today(TODAY); +struct statistics +{ + size_t total; + size_t fa_skip; + size_t fa_err; + size_t fa_estr; + size_t fa_nocatdoc; + size_t fv_cart_skip; + size_t fv_err; + size_t fv_estr; + size_t fv_nocatdoc; +}; +extern statistics _stats; + struct drd { TString cod_soc; @@ -33,6 +47,17 @@ enum result_estr estr_err_db_drd = -99 // Errore scrittura F9DRD. }; +struct return_estr +{ + result_estr result; + size_t* fa_skip; + size_t* fa_total; + size_t* fa_err; + size_t* fv_cart_skip; + size_t* fv_err; + size_t* fv_estr; +}; + enum state_fppro { correct = 1, @@ -57,16 +82,19 @@ public: TString tipocaus; TString tipomov; TString opcee; - - bool is_cartaceo() const; }; private: - vector _rows; + std::vector> _rows; + + std::vector>::iterator find(const TString& class_sost, const TString& caus_sost, + const TString& op_cee); + std::shared_ptr find_causcont(const TString& caus); + std::shared_ptr find_tipodoc(const TString& tipodoc); - vector::iterator find(const TString& class_sost, const TString& caus_sost, const TString& op_cee); void load_all(); public: - std::shared_ptr causcont2cat(const char* caus, bool force_cartacea = false); + std::shared_ptr causcont2cat(const char* caus, bool force_cartacea); + std::shared_ptr mov2cat(int numreg); void reload() { _rows.clear(); @@ -90,12 +118,13 @@ 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_doc, // Il mov. di vendita non ha un documento generatore - notfound_elet, // Non trovata fatt. elettronica mov vendita - no_fa // Movimento di acquisto 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. + no_fa, // Movimento di acquisto non e' una fattura. + no_cartaceo // Movimento cartaceo che non ha bisogno di essere estratto. }; bool err; @@ -130,6 +159,10 @@ struct movimento_t return "Il mov. di vendita non ha un documento generatore"; case notfound_elet: return "Non trovata fatt. elettronica mov vendita"; + case no_fa: + return "Questo movimento di acquisto non e' una fattura"; + case no_cartaceo: + return "Movimento cartaceo che non ha bisogno di essere estratto"; default: return ""; } } @@ -164,6 +197,8 @@ struct movimento_t default: return ""; } } + + bool is_cartaceo() const { return false; } // todo }; class TEstrazione : public TObject @@ -173,14 +208,16 @@ class TEstrazione : public TObject ofstream* _error_sql; bool _escluso; const TString _descr; - bool _has_vendext; + bool _has_checkvend; + bool _has_cartacei; /** Aggiorna stato estrazione. Utilizzato ad esempio dopo la diagnostica per riportare * il nuovo stato sul db. */ bool update_drd_stato_estr() const; - static const char* categoria_doc(); - static const char* caus_sos(const TLocalisamfile& mov, TipoIVA acquisti); + static const char* categoria_doc(); + static const char* caus_sos(const TLocalisamfile& mov, TipoIVA iva); + static bool check_documento_vendita(const TLocalisamfile& mov, _Out_ bool& exist_doc); /** CHECK RIFERIMENTO FPPRO * Per le fatture di acquisto controllo se ho il riferimento nell'FPPRO. * Altrimenti cerco di capire se riesco a trovare il corrispondente del movimento @@ -255,7 +292,7 @@ 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 has_vendext = false); + bool escluso, const TDate* dal = nullptr, const TDate* al = nullptr, bool has_vendext = false, bool has_cartacei = false); };