From d5580efcdf731312aa56b820e8520d908a219574 Mon Sep 17 00:00:00 2001 From: Simone Palacino Date: Fri, 19 Jun 2020 12:30:10 +0200 Subject: [PATCH] Patch level : 12.0 no-patch Files correlati : ps6362100.exe ps6362100a.msk Commento : - Implementata importazione xml: lettura xml e caricamento dati secondo il tracciato di flexform e scrittura nuovo documento (ORC). - Aggiunti campi alla maschera per importazione da cartella degli xml ordini. --- build/ps.sln | 13 +-- build/ps6362.vcxproj | 9 +- src/ps/flexform_xml.cpp | 177 +++++++++++++++++++++++++++++-- src/ps/flexform_xml.h | 131 ++++++++++++++++++++--- src/ps/ps6362100.cpp | 125 ++++++++++++++++++---- src/ps/ps6362100a.h | 15 +-- src/ps/ps6362100a.uml | 40 ++++--- src/ps/xml_element.cpp | 230 ++++++++++++++++++++++++++++++++++++++++ src/ps/xml_element.h | 78 ++++++++++++-- 9 files changed, 729 insertions(+), 89 deletions(-) diff --git a/build/ps.sln b/build/ps.sln index db96cee4c..cfbae5247 100644 --- a/build/ps.sln +++ b/build/ps.sln @@ -54,11 +54,12 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ps6215", "ps6215.vcxproj", "{42AC85CF-2D74-4ADB-8CC4-87CE816B1508}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ps6362", "ps6362.vcxproj", "{F3AA5A90-8D73-4C9E-B417-2EA5747884D6}" + ProjectSection(ProjectDependencies) = postProject + {A1CE9743-A597-4F92-B55A-345A366C9E55} = {A1CE9743-A597-4F92-B55A-345A366C9E55} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ps0650", "ps0650.vcxproj", "{E7485070-16E1-4735-AD9D-B450C19B71C6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest_ps6362", "UnitTest_ps6362\UnitTest_ps6362.vcxproj", "{93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -229,14 +230,6 @@ Global {E7485070-16E1-4735-AD9D-B450C19B71C6}.Release|Win32.ActiveCfg = Release|Win32 {E7485070-16E1-4735-AD9D-B450C19B71C6}.Release|Win32.Build.0 = Release|Win32 {E7485070-16E1-4735-AD9D-B450C19B71C6}.Release|x64.ActiveCfg = Release|Win32 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Debug|Win32.Build.0 = Debug|Win32 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Debug|x64.ActiveCfg = Debug|x64 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Debug|x64.Build.0 = Debug|x64 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Release|Win32.ActiveCfg = Release|Win32 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Release|Win32.Build.0 = Release|Win32 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Release|x64.ActiveCfg = Release|x64 - {93B206B8-88AD-40AD-9E11-0F40CA3ACA5A}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/build/ps6362.vcxproj b/build/ps6362.vcxproj index e785d7503..756491eb4 100644 --- a/build/ps6362.vcxproj +++ b/build/ps6362.vcxproj @@ -59,7 +59,7 @@ MaxSpeed OnlyExplicitInline - ..\src\xvtdb\;..\src\cg;..\src\include;..\src\xvaga;%(AdditionalIncludeDirectories) + ..\src\xvtdb\;..\src\cg;..\src\include;..\src\xvaga;..\src\ve;%(AdditionalIncludeDirectories) NDEBUG;WIN32;_WINDOWS;%(PreprocessorDefinitions) true MultiThreaded @@ -109,7 +109,7 @@ Disabled - ..\src\xvtdb\;..\src\cg;..\src\include;..\src\xvaga;%(AdditionalIncludeDirectories) + ..\src\xvtdb\;..\src\cg;..\src\include;..\src\xvaga;..\src\ve;%(AdditionalIncludeDirectories) _DEBUG;WIN32;__LONGDOUBLE__;_WINDOWS;%(PreprocessorDefinitions) false MultiThreadedDebug @@ -119,8 +119,8 @@ .\..\debug/ Level3 true - ProgramDatabase true + EditAndContinue _DEBUG;%(PreprocessorDefinitions) @@ -152,6 +152,9 @@ {2d38a763-3d74-4338-9362-b891784ec90e} + + {a1ce9743-a597-4f92-b55a-345a366c9e55} + diff --git a/src/ps/flexform_xml.cpp b/src/ps/flexform_xml.cpp index 8dd870cb6..20097fbc5 100644 --- a/src/ps/flexform_xml.cpp +++ b/src/ps/flexform_xml.cpp @@ -1,7 +1,27 @@ #include "flexform_xml.h" + +#include + #include "config.h" #include "date.h" +#include "progind.h" +#include "velib.h" +#define CHECK_CONDXML_OR_RETURNFALSE(cond, msg) { \ + TString str; \ + if (!(cond)) { \ + str << "Errore nella lettura dell'xml: " << (msg); \ + warning_box(str); \ + return false; } } + +#define CHECK_NAMETAG_OR_RETURNFALSE(xml_element, name_tag) { \ + TString name; name << (name_tag); \ + TString msg; msg << "mi aspettavo di trovare il tag: " << name; \ + CHECK_CONDXML_OR_RETURNFALSE((xml_element)->get_name() == name, msg); } + //if ((xml_element)->get_name() != name) { \ + // msg.cut(0) << "Errore nella lettura dell'xml:" << name; \ + // warning_box(msg); \ + // return false; } } /////////////////////////////////////////////////////////// // ELEMENTI DDT @@ -114,12 +134,13 @@ TOrdini_riga_xml::~TOrdini_riga_xml() // Flexform xml export /////////////////////////////////////////////////////////// -TFlexform_xml::TFlexform_xml(const char* xml_name) : _file_name(xml_name), _fout(nullptr) +TFlexform_xml::TFlexform_xml(const char* xml_name, bool to_export) : _file_name(xml_name), _fout(nullptr), _export(to_export) { - // - _esa_import.set_attributes(TConfig(CONFIG_DITTA, "Main").get("RAGSOC"), TDate(TODAY), generate_GUID(), "1"); _esa_import.set_root(); - _fout = new ofstream(xml_name); + if (_export) + _fout = new ofstream(xml_name); + else + _fin = new ifstream(xml_name); } @@ -168,11 +189,29 @@ int TFlexform_xml_ddt::set_testata(const char* data_doc, const char* num_doc, co return i; } +TFlexform_xml_ddt::TFlexform_xml_ddt(const char* xml_name) : TFlexform_xml(xml_name) +{ + // + _esa_import.set_attributes(TConfig(CONFIG_DITTA, "Main").get("RAGSOC"), TDate(TODAY), generate_GUID(), "1"); +} + /////////////////////////////////////////////////////////// // Flexform Ordini export /////////////////////////////////////////////////////////// +void TFlexform_xml_ordini::add_doc() +{ + /* const shared_ptr doc = make_shared("DOC_UNICO", ""); + const shared_ptr test = make_shared(); + _docs_unico.insert(_docs_unico.end(), doc); + _docs_unico.back()->set_parent(_esa_import); + + _testate.insert(_testate.end(), test); + _testate.back()->set_parent(*_docs_unico.back()); + return _docs_unico.size();*/ +} + bool TFlexform_xml_ordini::print() { ofstream& out = *_fout; @@ -182,10 +221,130 @@ bool TFlexform_xml_ordini::print() return ok; } -TFlexform_xml_ordini::TFlexform_xml_ordini(const char* xml_name) : TFlexform_xml(xml_name), _ordine_impegno("ORDINE_IMPEGNO", "") +//bool TFlexform_xml_ordini::parse_ordine_xml(unique_ptr& ford, const long len) +//{ +// TXML_parser parser(ford.get(), len); +// TString name; +// vector> attributi; +// parser.get_xml_info(name, attributi); +// _info_xml = std::make_unique(name, TString(""), true); +// TXML_tag tag = parser.get_xml_tag(); +// // +// bool ok = true; +// TString source, creation_date, instance_guid, file_version, tipo_operazione; +// ok &= tag.get_attribute(source, "Source") +// && tag.get_attribute(creation_date, "CreationDate") +// && tag.get_attribute(instance_guid, "InstanceGuid") +// && tag.get_attribute(file_version, "FileVersion"); +// if (!ok) +// return false; +// _esa_import.set_attributes(source, TDate(creation_date), instance_guid, file_version); +// tag = parser.get_xml_tag(); +// tag.get_name(name); +// ok = tag.get_attribute(tipo_operazione, "TipoOperazione"); +// _ordine_impegno = std::make_unique((const char*)name, ""); +// _ordine_impegno->add_attribute("TipoOperazione", tipo_operazione); +// _ordine_impegno->set_parent(_esa_import); +// _testata.set_parent(*_ordine_impegno); +// tag = parser.get_xml_tag(); +// tag.get_name(name); +// if(name != "OR_ORDINIT") +// { +// warning_box("Errore durante la lettura del tag \"OR_ORDINIT\"."); +// return false; +// } +// tag = parser.get_xml_tag(); +// if (name != "datarow") +// { +// warning_box("Errore durante la lettura del tag \"datarow\" della testata dell'ordine."); +// return false; +// } +// //parser.get_until_tag_close("datarow"); +// return true; +//} + +bool TFlexform_xml_ordini::convert() const { - _ordine_impegno.add_attribute("TipoOperazione", "Insert"); - _ordine_impegno.set_parent(_esa_import); - _testata.set_parent(_ordine_impegno); - _fout = new ofstream(_file_name); + const std::vector>& imported = _importer._imported; + TProgress_monitor bar(imported.size(), "Conversione XML ..."); + for(auto it = imported.begin(); it != imported.end(); ++it) + { + if (!bar.add_status()) + break; + } + return false; } + +bool TFlexform_xml_ordini::create_doc() +{ + const shared_ptr esa_import = _importer._imported[1]; + CHECK_NAMETAG_OR_RETURNFALSE(esa_import, "ESA_IMPORT"); + + TXML_element* ordine_impegno = esa_import->get_childs()[0]; + CHECK_NAMETAG_OR_RETURNFALSE(ordine_impegno, "ORDINE_IMPEGNO"); + + const auto it = ordine_impegno->find_attribute("TipoOperazione"); + CHECK_CONDXML_OR_RETURNFALSE(it != ordine_impegno->get_attributes().end() && it->second == "Insert", + "il 'Tipo Operazione' deve essere 'Insert'."); + + TXML_element* or_ordinit = ordine_impegno->get_childs()[0]; + CHECK_NAMETAG_OR_RETURNFALSE(or_ordinit, "OR_ORDINIT"); + + TXML_element* datarow = or_ordinit->get_childs()[0]; + CHECK_NAMETAG_OR_RETURNFALSE(datarow, "datarow"); + + const TDate dat_doc_esterno = (const char*)datarow->get_val_child("dat_doc_esterno"); + const TString& des_num_esterno = datarow->get_val_child("des_num_esterno"); + const TDate dat_evasione = (const char*)datarow->get_val_child("dat_evasione"); + + TDocumento doc('D', dat_doc_esterno.year(), _codnum, -1); + doc.put(DOC_TIPODOC, _codnum); + doc.put(DOC_STATO, "2"); + doc.put(DOC_DATADOC, dat_doc_esterno); + doc.put(DOC_TIPOCF, "C"); + doc.put(DOC_CODCF, _codcli_flex); + doc.put(DOC_DATACONS, dat_evasione); + + vector childs_ordinit = or_ordinit->get_childs(); + CHECK_CONDXML_OR_RETURNFALSE(!childs_ordinit.empty(), "non e' presente alcun ordine."); + + for (auto child : childs_ordinit) + { + const TXML_element& row = *child; + const TXML_element& datarow_r = *row.get_childs()[0]; + + const TString& ind_tiporiga = datarow_r.get_val_child("ind_tiporiga"); + const TString& cod_art = datarow_r.get_val_child("cod_art"); + const TString& des_articolo_riga = datarow_r.get_val_child("des_articolo_riga"); + const TString& qta_merce = datarow_r.get_val_child("qta_merce"); + const TString& dat_evas_riga = datarow_r.get_val_child("dat_evas_riga"); + const TString& des_campo_libero6 = datarow_r.get_val_child("des_campo_libero6"); + + TRiga_documento& d_row = doc.new_row(ind_tiporiga == "D" ? "05" : "01"); + if (ind_tiporiga != "D") + d_row.put(RDOC_CODART, cod_art); // todo: codice articolo da mandarlo a cercare nell'altro campo + d_row.put(RDOC_DESCR, des_articolo_riga); + d_row.put(RDOC_QTA, qta_merce); + d_row.put("DATA_EVASIONE_RIGA", dat_evas_riga); // RG1 -> DATA_EVASIONE_RIGA + d_row.put("CODFLEX", des_campo_libero6); // RG1 -> CODFLEX + } + + bool ok = doc.write() == NOERR; + ok = ok && doc.rewrite() == NOERR; + return ok; +} + +bool TFlexform_xml_ordini::parse_and_import_ordine_xml(unique_ptr& ford, long len) +{ + _importer.parse(ford, len); + + // Convertion to my Flexformstructure + //bool ok = convert(); + + // Creation of ORC in DOC + bool ok = create_doc(); + return ok; +} + +TFlexform_xml_ordini::TFlexform_xml_ordini(const char* xml_name, const char* codnum, int codcli_flex) : TFlexform_xml(xml_name, false), _codnum(codnum), _codcli_flex(codcli_flex) +{ } diff --git a/src/ps/flexform_xml.h b/src/ps/flexform_xml.h index 7bd0a8939..4986abc4c 100644 --- a/src/ps/flexform_xml.h +++ b/src/ps/flexform_xml.h @@ -1,11 +1,10 @@ -#ifndef __MAJORXML_H__ -#define __MAJORXML_H__ +#ifndef __MAJORXML_H +#define __MAJORXML_H #include #include #include "strings.h" -#include "stdtypes.h" #include "xml_element.h" #include "date.h" @@ -145,15 +144,17 @@ class TFlexform_xml protected: TString _file_name; ofstream* _fout; + ifstream* _fin; TEsa_import_xml _esa_import; + bool _export; - void set_indentation(const bool use_tab, const short n_spaces) { _esa_import.set_indentation(use_tab, n_spaces); } - virtual bool print() pure; + void set_indentation(const bool use_tab, const short n_spaces) { _esa_import.set_indentation(use_tab, n_spaces); } + virtual bool print() pure; public: bool ok() const { return _fout != nullptr && _fout->is_open(); } - TFlexform_xml(const char* xml_name = ""); + TFlexform_xml(const char* xml_name = "", bool to_export = true); virtual ~TFlexform_xml() { delete _fout; } }; @@ -183,24 +184,128 @@ public: */ int set_testata(const char* data_doc, const char* num_doc, int which_doc = -1); - TFlexform_xml_ddt(const char* xml_name = "") : TFlexform_xml(xml_name) { } + TFlexform_xml_ddt(const char* xml_name = ""); ~TFlexform_xml_ddt() = default; }; /** - * \brief Esportatore XML Ordini Flexform. + * \brief Classe dell'ordine xml importato */ class TFlexform_xml_ordini final : public TFlexform_xml { - TXML_element _ordine_impegno; // Unico ordine, figlio di _esa_import - TOrdini_testata_xml _testata; // _testata contiene i dati di testata, piu' tutte gli ordini riga come figli, figlio di _ordine_impegno + unique_ptr _info_xml; + unique_ptr _ordine_impegno; // Unico ordine, figlio di _esa_import + TOrdini_testata_xml _testata; // _testata contiene i dati di testata, piu' tutte gli ordini riga come figli, figlio di _ordine_impegno + TXML_importer _importer; + TString _codnum; + int _codcli_flex; public: - void add_row(TOrdini_riga_xml* riga) { riga->set_parent(_testata); } + void add_doc(); + void add_row(const shared_ptr& riga) { riga->set_parent(_testata); } bool print() override; void set_testata(const char* data_doc, const char* num_doc, const char* str) { _testata.set_testata(data_doc, num_doc, str); } + bool parse_and_import_ordine_xml(unique_ptr& ford, long len); + bool convert() const; + bool create_doc(); - TFlexform_xml_ordini(const char* xml_name = ""); + TFlexform_xml_ordini(const char* xml_name = "", const char* codnum = "", int codcli_flex = 12); }; -#endif // __MAJORXML_H__ + + + +///////////////////////////////////////////////////////// +// Utils +///////////////////////////////////////////////////////// + +//class TXML_parser +//{ +// long _last_pos; +// const long _len; +// const char* _xml; +//public: +// bool get_xml_info(TString& name, vector>& attributi) +// { +// bool end = false; +// bool ok = true; +// TToken_string line("", ' '); +// if (_xml[_last_pos++] == '<' && _xml[_last_pos++] == '?') +// { +// for (int i = _last_pos; !end && i < _len; ++i) +// { +// bool text = false; +// TString tag; +// if (_xml[i] == '\"') +// text = !text; +// else if (!text && _xml[i] == '?' && i + 1 < _len && _xml[i + 1] == '>') +// { +// end = true; +// continue; +// } +// else if (!text && _xml[i] == '?' && !(i + 1 < _len && _xml[i + 1] == '>')) +// { +// warning_box("tag info XML non chiuso correttamente!"); +// ok = false; +// break; +// } +// line << _xml[i]; +// } +// name = line.get(0); +// TToken_string tok("", '='); +// for (int i = 1; line.get(-1, tok) && i < line.items(); ++i) +// { +// if (tok.items() != 2) +// { +// warning_box("Errore durante la lettura degli attributi delle info XML."); +// ok = false; +// break; +// } +// attributi.push_back({ tok.get(0), tok.get(1) }); +// } +// return ok; +// } +// else +// { +// error_box("XML mal formattato: mi aspettavo la riga di info xml."); +// return false; +// } +// } +// +// void get_single_tag(TString& str) const +// { +// str.cut(0); +// bool end = false; +// bool open = false; +// for (int i = _last_pos; !end && i < _len; ++i) +// { +// if (!open) +// { +// if (_xml[i] != '<') +// continue; +// open = true; +// } +// +// bool text = false; +// TString tag; +// if (_xml[i] == '\"') +// text = !text; +// else if (!text && _xml[i] == '>') +// end = true; +// str << _xml[i]; +// } +// } +// +// TXML_tag get_xml_tag() const +// { +// TXML_tag xml_tag; +// TString tag; +// get_single_tag(tag); +// xml_tag.import_tag(tag); +// return xml_tag; +// } +// +// TXML_parser(const char* xml, const long len) : _last_pos(0), _len(len), _xml(xml) { } +//}; + +#endif // __MAJORXML_H diff --git a/src/ps/ps6362100.cpp b/src/ps/ps6362100.cpp index be797b07c..44ed28b97 100644 --- a/src/ps/ps6362100.cpp +++ b/src/ps/ps6362100.cpp @@ -3,14 +3,19 @@ #include "ps6362.h" #include "ps6362100a.h" -#include "applicat.h" -#include "automask.h" +#include "applicat.h" // TSkeleton_application +#include "automask.h" // TAutomask +#include "config.h" +#include "lffiles.h" +#include "clifo.h" +#include "isam.h" #include "tabutil.h" // TTable #include "sqlset.h" // TSQL_recordset +#include "utility.h" // list_files #include "progind.h" // TProgress_monitor #include "flexform_xml.h" -#include "clifo.h" + /////////////////////////////////////////////////////////// @@ -21,30 +26,50 @@ class TMajor_export_mask final : public TAutomask { protected: bool on_field_event(TOperable_field& o, TField_event e, long jolly) override; - void load_all(); + void load_all(); public: - void save_all() const; - TMajor_export_mask(); + void save_all() const; + TMajor_export_mask(); ~TMajor_export_mask() { save_all(); } }; bool TMajor_export_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { + switch(o.dlg()) + { + case F_TIPODOC: + if(e == fe_modify || e == fe_init) + { + const TString& c = get(F_TIPODOC); + const bool en = c == "D"; + field(F_FLDDEST).enable(en); + field(F_SUBFLD).enable(en); + field(F_FLDSOURCE).enable(!en); + field(F_ANNO_ELAB).enable(en); + field(F_NUMDDT).enable(en); + field(F_NUMORD).enable(!en); + field(F_NUMDDT_DA).enable(en); + field(F_NUMDDT_A).enable(en); + } + break; + default: break; + } return true; } TMajor_export_mask::TMajor_export_mask() : TAutomask("ps6362100a") { - load_all(); + load_all(); } void TMajor_export_mask::save_all() const { - ini_set_string(CONFIG_DITTA, "ps6362", "flddest", get(F_FLDDEST)); - ini_set_bool (CONFIG_DITTA, "ps6362", "fldroot_b", get_bool(F_SUBFLD)); + ini_set_string(CONFIG_DITTA, "ps6362", "flddest", get(F_FLDDEST)); + ini_set_bool (CONFIG_DITTA, "ps6362", "fldroot_b", get_bool(F_SUBFLD)); + ini_set_string(CONFIG_DITTA, "ps6362", "fldsource", get(F_FLDSOURCE)); ini_set_string(CONFIG_DITTA, "ps6362", "fldyear", get(F_ANNO_ELAB)); + ini_set_string(CONFIG_DITTA, "ps6362", "tipodoc", get(F_TIPODOC)); ini_set_string(CONFIG_DITTA, "ps6362", "numddt", get(F_NUMDDT)); - ini_set_string(CONFIG_DITTA, "ps6362", "numord", get(F_NUMORD)); ini_set_string(CONFIG_DITTA, "ps6362", "codcf", get(F_CODCF)); ini_set_string(CONFIG_DITTA, "ps6362", "num_da", get(F_NUMDDT_DA)); ini_set_string(CONFIG_DITTA, "ps6362", "num_a", get(F_NUMDDT_A)); @@ -82,11 +107,20 @@ void TMajor_export_mask::load_all() cod_flexform = "12"; } - set(F_FLDDEST, dir); - set(F_SUBFLD, ini_get_bool (CONFIG_DITTA, "ps6362", "fldroot_b", true)); - set(F_ANNO_ELAB, ini_get_string(CONFIG_DITTA, "ps6362", "fldyear", y)); + TString dir2 = ini_get_string(CONFIG_DITTA, "ps6362", "fldsource", ""); + if(dir2.empty()) + { + dir2 << dir; + dir2 << "\\upload"; + } + + set(F_FLDDEST, dir); + set(F_FLDSOURCE, dir2); + set(F_SUBFLD, ini_get_bool (CONFIG_DITTA, "ps6362", "fldroot_b", true)); + set(F_ANNO_ELAB, ini_get_string(CONFIG_DITTA, "ps6362", "fldyear", y)); set(F_NUMDDT, ini_get_string(CONFIG_DITTA, "ps6362", "numddt", "")); set(F_NUMORD, ini_get_string(CONFIG_DITTA, "ps6362", "numord", "")); + set(F_TIPODOC, ini_get_string(CONFIG_DITTA, "ps6362", "tipodoc", "D")); set(F_CODCF, cod_flexform); set(F_NUMDDT_DA, ini_get_string(CONFIG_DITTA, "ps6362", "num_da", "")); set(F_NUMDDT_A, ini_get_string(CONFIG_DITTA, "ps6362", "num_a", "")); @@ -125,16 +159,17 @@ class TMajor_export_app : public TSkeleton_application static TFilename check_name_file(const TString& dir, bool sub_fld, int from, int to, bool ddt = true); static TString get_riferimento_flexform(const TSQL_recordset& righe_doc); static bool export_ddt(TMask& msk); - static bool export_ordini() { return false; } + static bool import_ordini(TMask& msk); void main_loop() override; public: - TMajor_export_app() = default; + TMajor_export_app() = default; }; bool TMajor_export_app::create() { - return TSkeleton_application::create(); + open_files(LF_DOC, LF_RIGHEDOC); + return TSkeleton_application::create(); } TFilename TMajor_export_app::check_name_file(const TString& dir, const bool sub_fld, const int from, const int to, bool ddt) @@ -229,7 +264,7 @@ bool TMajor_export_app::export_ddt(TMask& msk) { shared_ptr riga = xml_ddts.new_row(); - const TString& cod_art = righe_doc.get(0).as_string(); + const TString& cod_art = righe_doc.get(0).as_string(); // todo: usa il cod.art. di flexform non quello di campo (vedi terza colonna nell'anteprima) TString descr = righe_doc.get(1).as_string(); const TString& qta = righe_doc.get(2).as_string(); const TString& desccampolibero6 = get_riferimento_flexform(righe_doc); // get(3) RG1 @@ -246,28 +281,72 @@ bool TMajor_export_app::export_ddt(TMask& msk) return ok; } +bool TMajor_export_app::import_ordini(TMask& msk) +{ + bool ok = false; + const TString& dir_in = msk.get(F_FLDSOURCE); + const TString& cod_cli = msk.get(F_CODCF); + const TString& tiponumord = msk.get(F_NUMORD); + + TFilename path(dir_in); + TString_array flist; + path.add("*.xml"); + list_files(path, flist); + bool* lookup_t = new bool[flist.items()]; + for (int i = 0; i < flist.items(); ++i) + lookup_t[i] = false; + FOR_EACH_ARRAY_ROW(flist, nr, ford_name) + { + TFilename ford_filename(ford_name->operator const char*()); + FILE* fin; + if (!fopen_s(&fin, ford_filename, "rb") && fin) // Read-Binary mode + { + lookup_t[nr] = true; + std::fseek(fin, 0, SEEK_END); + const long len = std::ftell(fin); + std::unique_ptr ford = std::make_unique(len + 1); + std::fseek(fin, 0, 0); + fread_s(ford.get(), len + 1, 1, len, fin); + ford[len] = '\0'; + fclose(fin); + + TFlexform_xml_ordini order((const char*)ford_filename, msk.get(F_NUMORD), msk.get_int(F_CODCF)); + ok = order.parse_and_import_ordine_xml(ford, len); + } + else + { + TString msg; msg << "Impossibile aprire il file " << ford_filename << "\nProcedura terminata."; + warning_box(msg); + return false; + } + } + return ok; +} + void TMajor_export_app::main_loop() { - TMajor_export_mask msk; - while (msk.run() == K_ENTER) - { + TMajor_export_mask msk; + while (msk.run() == K_ENTER) + { bool ok = true; - TString msg; msg << "Esportazione "; + TString msg; if (msk.get(F_TIPODOC) == "D") { + msg << "Esportazione "; ok &= export_ddt(msk); msg << "DDT"; } else { - ok &= export_ordini(); + msg << "Importazione "; + ok &= import_ordini(msk); msg << "ordini"; } if (ok) message_box(msg << " eseguita correttamente."); else warning_box(msg << " non completata."); - } + } } int ps6362100(const int argc, char* argv[]) diff --git a/src/ps/ps6362100a.h b/src/ps/ps6362100a.h index 907975e45..667848dd9 100644 --- a/src/ps/ps6362100a.h +++ b/src/ps/ps6362100a.h @@ -1,9 +1,10 @@ #define F_FLDDEST 101 #define F_SUBFLD 102 -#define F_TIPODOC 103 -#define F_NUMORD 104 -#define F_NUMDDT 105 -#define F_ANNO_ELAB 106 -#define F_CODCF 107 -#define F_NUMDDT_DA 108 -#define F_NUMDDT_A 109 \ No newline at end of file +#define F_FLDSOURCE 103 +#define F_TIPODOC 104 +#define F_NUMORD 105 +#define F_NUMDDT 106 +#define F_ANNO_ELAB 107 +#define F_CODCF 108 +#define F_NUMDDT_DA 109 +#define F_NUMDDT_A 110 \ No newline at end of file diff --git a/src/ps/ps6362100a.uml b/src/ps/ps6362100a.uml index 6a2c35010..e8758bd0c 100644 --- a/src/ps/ps6362100a.uml +++ b/src/ps/ps6362100a.uml @@ -3,8 +3,8 @@ TOOLBAR "topbar" 0 0 0 2 BUTTON DLG_OK 2 2 BEGIN - PROMPT 1 1 "~Conferma" - PICTURE TOOL_OK + PROMPT 1 1 "~Elabora" + PICTURE TOOL_ELABORA END #include @@ -12,7 +12,7 @@ ENDPAGE PAGE "Configurazione Esportazione Major-Flexform" 0 2 0 0 -GROUPBOX DLG_NULL 78 4 +GROUPBOX DLG_NULL 78 5 BEGIN PROMPT 1 0 "@bPercorso salvataggio file" END @@ -31,27 +31,35 @@ BEGIN FLAGS "" END +STRING F_FLDSOURCE 250 50 +BEGIN + PROMPT 2 3 "Cartella caricamento " + DSELECT + FLAGS "" + CHECKTYPE REQUIRED +END + GROUPBOX DLG_NULL 66 12 BEGIN - PROMPT 5 4 "@bEstremi dei documenti da elaborare:" + PROMPT 5 5 "@bEstremi dei documenti da elaborare:" END RADIOBUTTON F_TIPODOC 64 BEGIN - PROMPT 6 5 "@bSelezionare tipo documento da esportare/importare" + PROMPT 6 6 "@bSelezionare tipo documento da esportare/importare" ITEM "D|DDT" ITEM "O|Ordini" - FLAG "ZD" + FLAG "Z" END GROUPBOX DLG_NULL 25 4 BEGIN - PROMPT 6 8 "@bSelezionare cod. numerazione" + PROMPT 6 9 "@bSelezionare cod. numerazione" END STRING F_NUMDDT 4 BEGIN - PROMPT 7 9 "DDT " + PROMPT 7 10 "DDT " FLAG "UZ" USE %NUM INPUT CODTAB F_NUMDDT @@ -63,7 +71,7 @@ END STRING F_NUMORD 4 BEGIN - PROMPT 7 10 "ORDINI" + PROMPT 7 11 "ORDINI" FLAG "UZD" USE %NUM INPUT CODTAB F_NUMORD @@ -75,12 +83,12 @@ END STRING F_ANNO_ELAB 4 BEGIN - PROMPT 32 8 "Anno elaborazione" + PROMPT 32 9 "Anno elaborazione" END NUMBER F_CODCF 6 BEGIN - PROMPT 32 9 "cod. cliente " + PROMPT 32 10 "cod. cliente " USE LF_CLIFO INPUT TIPOCF "C" INPUT CODCF F_CODCF @@ -90,14 +98,13 @@ BEGIN FLAGS "" END -STRING F_NUMDDT_DA 7 +NUMBER F_NUMDDT_DA 7 BEGIN - PROMPT 32 10 "da num. doc. " + PROMPT 32 11 "da num. doc. " USE LF_DOC JOIN %TIP ALIAS 104 INTO CODTAB=TIPODOC JOIN LF_CLIFO INTO TIPOCF=TIPOCF CODCF=CODCF INPUT PROVV "D" - INPUT TIPOCF "C" SELECT INPUT ANNO F_ANNO_ELAB SELECT INPUT CODNUM F_NUMDDT SELECT INPUT NDOC F_NUMDDT_DA @@ -108,12 +115,11 @@ BEGIN ADD RUN ve0 -0 END -STRING F_NUMDDT_A 7 +NUMBER F_NUMDDT_A 7 BEGIN - PROMPT 57 10 "a " + PROMPT 57 11 "a " COPY USE F_NUMDDT_DA INPUT PROVV "D" - INPUT TIPOCF "C" SELECT INPUT ANNO F_ANNO_ELAB SELECT INPUT CODNUM F_NUMDDT SELECT INPUT NDOC F_NUMDDT_A diff --git a/src/ps/xml_element.cpp b/src/ps/xml_element.cpp index 6ef92f829..6f75d3375 100644 --- a/src/ps/xml_element.cpp +++ b/src/ps/xml_element.cpp @@ -1,7 +1,12 @@ #include #include +#include + #include "xml_element.h" +#include "strings.h" +#include "progind.h" + #define XML_ESCAPE_CHAR '&' @@ -87,6 +92,231 @@ void TXML_element::set_value(const TString& _Val) _value = _Val; } +const TString& TXML_element::get_val_child(const char* name_child) const +{ + static TString appo = ""; + const auto it = find_child(_childs, name_child); + if (it != _childs.end()) + return (*it)->get_val(); + return appo; +} + +const wchar_t* TXML_element::get_wval_child(const char* name_child) const +{ + static wchar_t* appo = L""; + const auto it = find_child(_childs, name_child); + if (it != _childs.end()) + return (*it)->get_wval(); + return appo; +} + +vector>::const_iterator TXML_element::find_attribute(const char* str) +{ + vector>::const_iterator a = _attributes.end(); + for (auto it = _attributes.begin(); it != _attributes.end(); ++it) + if (it->first == str) + a = it; + return a; +} + +vector::const_iterator TXML_element::find_child(const vector& childs, const char* str) +{ + vector::const_iterator a = childs.end(); + for (auto it = childs.begin(); it != childs.end(); ++it) if ((*it)->get_name() == str) a = it; + return a; +} + + + + +/////////////////////////////////////////////////////////// +// TXML_importer +/////////////////////////////////////////////////////////// + +bool TXML_importer::parse(std::unique_ptr& ford, long len) +{ + char* xml = ford.get(); + std::stack s_tags; + std::stack s_elems; + bool tag_open = false; + bool text_open = false; + TString token; + TString value_pending; + TProgress_monitor bar(len, "Parsing XML Flexform Ordini"); + for (int i = 0; i < len; ++i) + { + if (!bar.add_status()) + break; + if (!text_open && !tag_open && xml[i] == '<') + { + tag_open = true; + if (!token.empty()) + { + if (s_tags.empty()) + { + TString msg; msg << "Trovato testo fuori dai tag ma senza alcun tag? " << token; + warning_box(msg); + return false; + } + // Se al giro dopo becco lo stesso tag ma di chiusura vuol dire che questo e' un valore e lo aggiungo + value_pending.cut(0) << token; + } + token.cut(0) << xml[i]; + } + else if (xml[i] == '"') + { + text_open = !text_open; + token << xml[i]; + } + else if (!text_open && tag_open && xml[i] == '>') + { + tag_open = false; + token << xml[i]; + TXML_tag tag; + tag.import_tag(token); + if (tag._opener) + { + _imported.push_back(make_shared((const char*)tag._name, "", tag._info)); + if (s_tags.empty()) + _imported.back()->set_root(); + else + _imported.back()->set_parent(*s_elems.top()); + // Aggiungo gli attributi, se ce ne sono + for (auto& attribute : tag._attributes) + _imported.back()->add_attribute(attribute.first, attribute.second); + // Aggiungo allo stack solo se non si tratta di tag singoli () o del tag info xml () + // Poiche' questi non determinano nessuna apertura + if (!tag._closed && !tag._info) + { + s_tags.push(tag); + s_elems.push(_imported.back().get()); + } + } + else + { + TXML_tag t = s_tags.top(); + if (t._name != tag._name) + { + TString msg; msg << "Chiuso tag sbagliato. Mi aspettavo: " << tag._name << " trovato: " << t._name; + warning_box(msg); + return false; + } + + if (!value_pending.trim().empty()) + { + TXML_element* last = s_elems.top(); + last->set_value(value_pending); + value_pending.cut(0); + } + s_tags.pop(); + s_elems.pop(); + } + token.cut(0); + } + else if (!tag_open && !s_tags.empty() || tag_open) // Se sto fetchando roba dentro il tag o i valori dei tag + token << xml[i]; + } + if (!s_tags.empty()) + return false; + return true; +} + + + + +//////////////////////////////////////////////////////////////////////////////// +// TXML_tag +//////////////////////////////////////////////////////////////////////////////// + +vector>::const_iterator TXML_tag::find_attribute( + const vector>& attributes, const char* str) +{ + vector>::const_iterator a = attributes.end(); + for (auto it = attributes.begin(); it != attributes.end(); ++it) + if (it->first == str) + a = it; + return a; +} + +bool TXML_tag::get_attribute(TString& out, const char* str) +{ + const auto p = find_attribute(_attributes, str); + if (p == _attributes.end()) + { + TString msg; + msg << "Impossibile trovare l'attributo " << str << " nel tag " << _name; + warning_box(msg); + out = ""; + return false; + } + out = p->second; + return true; +} + +bool TXML_tag::import_tag(const TString& tag) +{ + bool ok = true; + if (tag[0] == '<' && tag[tag.len() - 1] == '>') + { + _opener = tag[1] != '/'; + _info = tag[1] == '?'; + _closed = tag[tag.len() - 2] == '/'; + TString tok(tag.sub(1 + (_info || !_opener ? 1 : 0), tag.len() - 1 - (_info || _closed ? 1 : 0))); + if (tok.empty()) + { + warning_box("Error reading tag."); + ok = false; + } + int i = tok.find(' '); + _name = tok.sub(0, i); + bool end = i == -1; + for (++i; !end;) + { + TString tok_; + bool end_2 = false; + bool text = false; + for (; !end_2 && i < tok.len(); ++i) + { + if (tok[i] == '\"') + text = !text; + else if (!text && tok[i] == ' ') + { + end_2 = true; + continue; + } + tok_ << tok[i]; + } + if (i == tok.len()) + end = true; + TToken_string att(tok_, '='); + if (att.items() == 2) + { + TString key, val; + key = att.get(0); + key.trim(); + val = att.get(1); + val = *att.get(1) == '\"' ? val.sub(1, val.len() - 1) : att.get(1); + val.trim(); + _attributes.insert(_attributes.end(), {key, val}); + } + else + { + TString msg; + msg << "Error parsing attributes of tag " << _name; + warning_box(msg); + ok = false; + } + } + return ok; + } + return false; +} + + + + +/////////////////////////////////////////////////////////// + const char* generate_GUID() { static TString _guid; diff --git a/src/ps/xml_element.h b/src/ps/xml_element.h index 6035d6014..fa48cc3ed 100644 --- a/src/ps/xml_element.h +++ b/src/ps/xml_element.h @@ -1,11 +1,14 @@ -#ifndef __XMLELEMENT_H__ -#define __XMLELEMENT_H__ +#ifndef __XMLELEMENT_H +#define __XMLELEMENT_H #include + #include "strings.h" #define XML_ROOT_TAG nullptr +const char* generate_GUID(); + /** * \brief Elemento base xml. */ @@ -37,14 +40,75 @@ public: void set_value(const TString& _Val); bool is_root() const { return _parent == nullptr; } - TXML_element& operator<<(const char* _Val) { _value = _Val; return *this; } + const TString& get_name() const { return _name; } + const TXML_element& get_parent() const { return *_parent; } + const vector& get_childs() const { return _childs; } + const vector>& get_attributes() const { return _attributes; } + const TString& get_val() const { return _value; } + const wchar_t* get_wval() const { return _wvalue; } + const TString& get_val_child(const char* name_child) const; - explicit TXML_element(const char* name, const char* value = "", bool info_file = false) : _indent("\t"), _info_xml(info_file), _name(name), _parent(nullptr), _value(value), _wvalue(nullptr) { } + const wchar_t* get_wval_child(const char* name_child) const; + + /*static vector>::const_iterator find_attribute(const vector>& attributes, const char* str) + { + vector>::const_iterator a = attributes.end(); + for (auto it = attributes.begin(); it != attributes.end(); ++it) + if (it->first == str) + a = it; + return a; + }*/ + vector>::const_iterator find_attribute(const char* str); + + TXML_element& operator<<(const char* _Val) { _value = _Val; return *this; } + vector::const_iterator find_child(const char* str) const { return find_child(_childs, str); } + static vector::const_iterator find_child(const vector& childs, const char* str); + + explicit TXML_element(const char* name, const char* value = "", bool info_file = false) : _indent("\t"), _info_xml(info_file), _name(name), _parent(nullptr), _value(value), _wvalue(nullptr) { } explicit TXML_element(const char* name, const wchar_t* value = L"", bool info_file = false) : _indent("\t"), _info_xml(info_file), _name(name), _parent(nullptr), _value(""), _wvalue(value) { } - explicit TXML_element(const TString& name, const TString& value = "", bool info_file = false) : _indent("\t"), _info_xml(info_file), _name(name), _parent(nullptr), _value(value), _wvalue(nullptr) { } + explicit TXML_element(const TString& name, const TString& value = "", bool info_file = false) : _indent("\t"), _info_xml(info_file), _name(name), _parent(nullptr), _value(value), _wvalue(nullptr) { } explicit TXML_element(const char* name, bool info_file) : TXML_element(name, "", info_file) { } }; -const char* generate_GUID(); -#endif // __XMLELEMENT_H__ \ No newline at end of file + + +class TXML_importer +{ +public: + std::vector> _imported; + bool parse(std::unique_ptr& ford, long len); +}; + + +/** + * \brief Classe di supporto con info singolo tag. + */ +class TXML_tag +{ +public: + TString _name; + bool _opener; + bool _closed; + vector> _attributes; // Vector perche' ho bisogno di mantenere l'ordine + TString _val; // Tutto cio' che c'e' all'interno del tag. + bool _info = false; + + void add_attribute(const char* key, const char* val) { _attributes.insert(_attributes.end(), { key, val }); } + void set_name(const char* name) { _name = name; } + void set_opener(bool tag_di_apertura) { _opener = tag_di_apertura; } + void set_single_tag(bool closed) { _closed = closed; } + void get_name(TString& name) const { name = _name; } + + static vector>::const_iterator find_attribute(const vector>& attributes, + const char* str); + bool get_attribute(_Out_ TString& out, const char* str); + bool import_tag(const TString& tag); + + TXML_tag() : _opener(false), _closed(false) { } + TXML_tag(const char* name, bool tag_di_apertura = false, bool single = false) : _name(name), _opener(tag_di_apertura), _closed(single) { } + TXML_tag(const char* name, vector>& attributes, bool tag_di_apertura = false, bool single = false) + : _name(name), _opener(tag_di_apertura), _closed(single), _attributes(attributes) { } +}; + +#endif // __XMLELEMENT_H \ No newline at end of file