#include #include #include #include #include #include #include #include #include #include #include #include #include #include "../mg/anamag.h" #include "../mg/umart.h" #include "ps0398100a.h" /////////////////////////////////////////////// // MASCHERA /////////////////////////////////////////////// class TTrasferimento_ordini_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TTrasferimento_ordini_mask(); }; TTrasferimento_ordini_mask::TTrasferimento_ordini_mask() : TAutomask("ps0398100a") { } bool TTrasferimento_ordini_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { /*switch(o.dlg()) { default: break; }*/ return true; } class TTrasferimento_ordini_recordset : public TCSV_recordset { public: TTrasferimento_ordini_recordset(const char* filename); }; ////////////////////////////////////////////// // RECORDSET ///////////////////////////////////////////// //creazione del recordset di ogni ordine TTrasferimento_ordini_recordset::TTrasferimento_ordini_recordset(const char* filename) : TCSV_recordset("CSV(\"\t\")") { load_file(filename); }; ////////////////////////////////////////////// // APPLICAZIONE ///////////////////////////////////////////// //Ridistributore di F24 per il computer class TTrasferimento_ordini : public TSkeleton_application { TTrasferimento_ordini_mask* _mask; TString4 _codmag; protected: virtual bool check_autorization() const {return false;} virtual const char * extra_modules() const {return "ve";} virtual bool create(); virtual void main_loop(); public: bool ordine_gf(TTrasferimento_ordini_recordset& recset); void elab_hd_ht(const TString& riga_txt, const int curr_nriga, TString& str); void elab_hf(const TString& riga_txt, const int curr_nriga, TConfig& curr_ini, TLog_report& log, TString& ragsoc); void elab_ho(const TString& riga_txt, const int curr_nriga, TConfig& curr_ini, TLog_report& log, TString& ho_note_generali); void elab_ra(const TString& riga_txt, const int curr_nriga, TConfig& curr_ini, TLog_report& log); bool elabora_file_txt(TTrasferimento_ordini_recordset& recset, const TFilename& ini_fname, TLog_report& log); bool sposta_file_elaborato(const TFilename& dst_file, const TFilename& curr_fname, TLog_report& log); bool elabora(); }; //metodo per scoprire se l'ordine è di GF o no bool TTrasferimento_ordini::ordine_gf(TTrasferimento_ordini_recordset& recset) { //le righe articolo o sono tutte di GF o non lo sono (nessuna situazione mista) bool is_ordine_gf = false; for (bool ok = recset.move_last(); ok; ok = recset.move_prev()) { const TString& riga_txt = recset.get(0L).as_string(); const TString& tr = riga_txt.left(2); if (tr == "RA") { TToken_string riga_ord(riga_txt.mid(5), ';'); const TString& codart = riga_ord.get(); //se il codice articolo non contiene il carattere '.' -> non è di GF -> scartato const int dot_pos = codart.find('.'); if (dot_pos >= 0) { is_ordine_gf = true; break; } } } return is_ordine_gf; } void TTrasferimento_ordini::elab_hf(const TString& riga_txt, const int curr_nriga, TConfig& curr_ini, TLog_report& log, TString& ragsoc) { switch (curr_nriga) { case 1: { ragsoc = riga_txt.mid(5); ragsoc.trim(); ragsoc.cut(50); } break; case 6: { const long codcf = atol(riga_txt.mid(14,6)); //per prima cosa controlla se è possibile risalire al cliente che ha generato l'ordine.. //..no cliente...no party! if (codcf <= 0) { TString msg; msg.format("Il cliente %s ha codice nullo!", (const char*)ragsoc); log.log(2, msg); } else { TString4 head_paragrafo; head_paragrafo << LF_DOC; curr_ini.set(DOC_TIPOCF, "C", head_paragrafo); curr_ini.set(DOC_CODCF, codcf, head_paragrafo); } } break; default: break; } } void TTrasferimento_ordini::elab_hd_ht(const TString& riga_txt, const int curr_nriga, TString& str) { if (riga_txt.full()) { switch (curr_nriga) { case 3: case 4: str << riga_txt; str.strip_double_spaces(); str << "\\n"; break; default: break; } } } void TTrasferimento_ordini::elab_ho(const TString& riga_txt, const int curr_nriga, TConfig& curr_ini, TLog_report& log, TString& ho_note_generali) { switch (curr_nriga) { case 1: //numero ordine del sito web (per ora non serve, ma poi si vedrà...) { const long num_ord_web = atol(riga_txt.mid(5)); } break; case 3: //datadoc (scritta alla cazzo) { TToken_string str_data(riga_txt.mid(5, 100).before(' '), '/'); const TDate datadoc(str_data.get_int(0), str_data.get_int(1), str_data.get_int(2)); if (!datadoc.ok()) { TString msg; msg.format(FR("Data documento non valida: %s"), (const char*)str_data); log.log(2, msg); } TString4 head_paragrafo; head_paragrafo << LF_DOC; curr_ini.set(DOC_DATADOC, datadoc, head_paragrafo); } break; case 4: //altre note ordine (da mettere in DOC_NOTE) { ho_note_generali << riga_txt.mid(5); ho_note_generali.trim(); } break; case 5: //codice condizione pagamento (anche questo x ora non serve, ma sempre si vedrà...) { const int cod_pag = atoi(riga_txt.mid(5)); } break; default: break; } //switch(curr_nriga) } void TTrasferimento_ordini::elab_ra(const TString& riga_txt, const int curr_nriga, TConfig& curr_ini, TLog_report& log) { TToken_string riga_ord(riga_txt.mid(5), ';'); const TString codart = riga_ord.get(); TString16 str_qta = riga_ord.get(); str_qta.strip(". "); str_qta.replace(',', '.'); //set_paragraph sulle righe (file 34, righedoc) TString8 row_paragrafo; row_paragrafo << LF_RIGHEDOC << ',' << curr_nriga; curr_ini.set_paragraph(row_paragrafo); curr_ini.set(RDOC_TIPORIGA, "01"); //l'articolo deve esistere per stare in codartmag e codart; //se non esiste in anagrafica -> solo in codart con segnalazione //la desc riga sarà la desc articolo const TRectype& rec_anamag = cache().get(LF_ANAMAG, codart); //se il record è vuoto l'articolo non è in anagrafica if (rec_anamag.empty()) { TString msg; msg = TR("Articolo non in anagrafica"); curr_ini.set(RDOC_DESCR, msg); msg << ": " << codart; log.log(2, msg); } else //sennò va tranquillo { // curr_ini.set(RDOC_CODARTMAG, codart); curr_ini.set(RDOC_DESCR, rec_anamag.get(ANAMAG_DESCR)); // curr_ini.set(RDOC_CHECKED, "X"); //alla qta associa la prima unità di misura TToken_string key_umart; key_umart.add(codart); key_umart.add(1); const TRectype& rec_umart = cache().get(LF_UMART, key_umart); const TString& umqta = rec_umart.get(UMART_UM); curr_ini.set(RDOC_UMQTA, umqta); } //queste le fa in ogni modo (forse rischiando) curr_ini.set(RDOC_CODART, codart); curr_ini.set(RDOC_QTA, str_qta); // TString80 str_prezzo = riga_ord.get(); //per adesso ci si mette il prezzo sull'ordine // str_prezzo.replace(',', '.'); // curr_ini.set(RDOC_PREZZO, str_prezzo); //e per ultime le eventuali note const TString nota = riga_ord.get(); if (nota.full()) { curr_ini.set(RDOC_DESCLUNGA, "X"); curr_ini.set(RDOC_DESCEST, nota); } //anzi, per ultimissimo il magazzino curr_ini.set(RDOC_CODMAG, _codmag); } bool TTrasferimento_ordini::elabora_file_txt(TTrasferimento_ordini_recordset& recset, const TFilename& ini_fname, TLog_report& log) { //variabili da riempire ad ogni giro TString4 curr_tiporiga; //tipo riga in esame (HT...RA), ovvero sezione del file int curr_nriga = 0; //n riga della sezione in esame TString ragsoc, piva; TString hd_spedizione; //questi stanno qui perchè valgono una volta per file .txt TString ht_fatturazione; TString ho_note_generali; //creazione del file .ini di transazione TConfig curr_ini(ini_fname); curr_ini.set_paragraph("Transaction"); //setto il paragrafo [Transaction] del file ini curr_ini.set("Action","INSERT"); curr_ini.set("Mode",""); //set_paragraph sulle testate (file 33, doc) TString4 head_paragrafo; head_paragrafo << LF_DOC; curr_ini.set_paragraph(head_paragrafo); TToken_string tipi_record("HF|HD|HT|HS|HO|RA"); //comincia il giro sulle righe del recordset //va al contrario perchè se le righe non hanno articoli di GF -> salta il tutto for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { //riga corrente del file di input const TString& riga_txt = recset.get(0L).as_string(); //gestione cambio riga e cambio sezione const TString& tr = riga_txt.left(2); if (tipi_record.get_pos(tr) < 0) { if (curr_tiporiga == "HO") { //righe del cazzo senza capo; in teoria possono appartenere solo al campo NOTE di HO (in teoria, ovviamente) TString riga_del_cazzo = riga_txt; riga_del_cazzo.trim(); ho_note_generali << " " << riga_del_cazzo; } continue; } if (tr != curr_tiporiga) { curr_tiporiga = tr; curr_nriga = 1; } else curr_nriga ++; //trattazione delle varie sezioni // HS (va saltata) if (curr_tiporiga == "HS") continue; // HF if (curr_tiporiga == "HF") elab_hf(riga_txt, curr_nriga, curr_ini, log, ragsoc); // HD if (curr_tiporiga == "HD") elab_hd_ht(riga_txt.mid(5, 100), curr_nriga, hd_spedizione); //(note spedizione) // HT if (curr_tiporiga == "HT") elab_hd_ht(riga_txt.mid(5, 100), curr_nriga, ht_fatturazione); //(note fatturazione) // HO if (curr_tiporiga == "HO") elab_ho(riga_txt, curr_nriga, curr_ini, log, ho_note_generali); // RA //gestione delle righe ordine if (curr_tiporiga == "RA") elab_ra(riga_txt, curr_nriga, curr_ini, log); } //for(bool ok=recset.move.frst... //scrive sul campo NOTE della testata quello che sa delle note spedizione e fatturazione TString note; note << '"'; if (hd_spedizione.full()) note << "Note Spedizione: " << hd_spedizione << "\\n"; if (ht_fatturazione.full()) note << "Note Fatturazione: " << ht_fatturazione << "\\n"; if (ho_note_generali.full()) note << "Note generali: " << ho_note_generali; note << '"'; curr_ini.set(DOC_NOTE, note, head_paragrafo); //qui ci va il lancio di ve0 con l'ini generato curr_ini.set(DOC_PROVV, "D"); curr_ini.set(DOC_CODNUM, _mask->get(F_CODNUM)); const TDate datadoc = curr_ini.get(DOC_DATADOC); curr_ini.set(DOC_ANNO, datadoc.year()); curr_ini.set(DOC_TIPODOC, _mask->get(F_TIPODOC)); curr_ini.set(DOC_STATO, 1); return true; } bool TTrasferimento_ordini::sposta_file_elaborato(const TFilename& dst_file, const TFilename& curr_fname, TLog_report& log) { bool copia_riuscita = fcopy(curr_fname, dst_file, false, true); if (copia_riuscita) { const long src_size = fsize(curr_fname); const long dst_size = fsize(dst_file); copia_riuscita = src_size == dst_size; } if (copia_riuscita) //se va tutto bene elimina il file dalla directory di origine { #ifdef DBG if (noyes_box(FR("Si desidera eliminare il file remoto '%s'"), (const char*)curr_fname)) #endif if (!remove_file(curr_fname)) { TString msg; msg.format("Impossibile eliminare il file origine '%s'", (const char*)curr_fname); log.log(1, msg); } } else { TString msg; msg.format(FR("Impossibile copiare il file '%s'!"), curr_fname.name()); log.log(2, msg); } return copia_riuscita; } bool TTrasferimento_ordini::elabora() { TFilename src_files = _mask->get(F_PATH_SRC); src_files.add("*HEADER.txt"); TString_array src_files_list; //dalla cartella origine prende tutti i files *HEADER.txt e crea una simpatica lista int n_files_txt = 0; if (src_files.full()) { TWait_cursor hourglass; n_files_txt = list_files(src_files, src_files_list); } //già che c'è prende pure gli altri dati dalla maschera che gli servono poi TFilename dst_path = _mask->get(F_PATH_DST); //cartella dove saranno creati i .ini TFilename tmp; tmp.tempdir(); tmp.add("ps0398"); const bool crea_dir = make_dir(tmp); //non riesce a crearla! deve dare errore di grave livello! if (!crea_dir) { TString msg; msg.format(FR("Impossibile creare la cartella di lavoro %s!"), tmp); return error_box(msg); } //scansione dello string_array per il trasferimento (con tanto di progind e log) TProgind pi(n_files_txt, main_app().title(), true, true); TLog_report log(main_app().title()); if (n_files_txt >= 0) { const bool pasv = ini_get_string(CONFIG_INSTALL, "Server", "ftp", "Passive")[0] != 'A'; TString msg; msg << src_files; log.log(0, msg); msg.cut(0) << n_files_txt << ' ' << TR("ordini da elaborare") << " (ftp " << (pasv ? "Passive" : "Active") << " mode)"; log.log(n_files_txt<=0 ? 1 : 0, msg); } //si accatta anche il magazzino _codmag = _mask->get(F_CODMAG); //ciclo su tutti i files .txt da esaminare for (int i = 0; i < n_files_txt; i++) { if (!pi.addstatus(1)) break; //file in formato filename (è l'ordine corrente da elaborare) const TFilename curr_fname = src_files_list.row(i); TFilename tempfile(tmp); tempfile.add(curr_fname.name()); if (!fcopy(curr_fname, tempfile, false, true)) { TString msg; msg << TR("Impossibile leggere il file ") << curr_fname; log.log(2, msg); continue; } //creazione del recordset associato al file TTrasferimento_ordini_recordset recset(tempfile); //se il file non è di GF (si vede dal codart) viene saltato! Hop! if (!ordine_gf(recset)) { TString msg; msg << TR("File Scartato: ") << curr_fname; log.log(1, msg); continue; } //avverte sul log quale file sta elaborando TString msg; msg << TR("Elaborazione file ") << curr_fname; log.log(0, msg); //per ogni ordine in formato .txt genera un file.ini che andrà poi documentizzato //file .ini TFilename ini_fname = tmp; ini_fname.add(format("ORD%05ld.ini", i)); //elaborazione del file .txt per riempireil .ini della successiva elaborazione differita bool elaborazione_ok = elabora_file_txt(recset, ini_fname, log); //elaborazione interattiva dell'ordine dal .ini if (elaborazione_ok) { TString commandline; commandline << "ve0 -0 /i" << ini_fname; TExternal_app ve(commandline); ve.run(); } //qui ci va lo spostamento del file elaborato se ve0 ha funzionato correttamente TFilename dst_file = dst_path; dst_file.add(curr_fname.name()); const bool copia_riuscita = sposta_file_elaborato(dst_file, curr_fname, log); } //for(int i... log.log(0, TR("Acquisizione ordini completata")); log.preview(); return true; } bool TTrasferimento_ordini::create() { Tdninst dninst; if (!dninst.can_I_run(true)) return error_box(TR("Programma non autorizzato!")); return TSkeleton_application::create(); } void TTrasferimento_ordini::main_loop() { _mask = new TTrasferimento_ordini_mask; if (_mask->run() != K_QUIT) elabora(); delete _mask; _mask = NULL; } int ps0398100 (int argc, char **argv) { TTrasferimento_ordini a; a.run(argc,argv, TR("Acquisizione ordini web")); return true; }