#include #include #include #include #include #include #include #include #include "..\cg\cglib01.h" #include "..\mg\umart.h" #include "..\mg\anamag.h" #include "..\ve\condv.h" #include "..\ve\rcondv.h" #include "dl0.h" #include "dl0800a.h" #include "dlutils.h" //////////////////////////////////////////////////////// // Classe TCat2dl_file customizzata dalla TFile_text // //////////////////////////////////////////////////////// class TCat2dl_file: public TFile_text { TArray _lista_offerte; TAssoc_array _lista_codici_iva; TString _listingr,_listven,_offingr,_offven,_codiva; TLocalisamfile _condv, _rcondv, _umart; protected: virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str); void calcola_offerta(const TDate& dataini, const TDate& datafine, TString& codoff); void add_table_entry(const char * table, const char * entry); TCodiceIVA& codice_iva(const TString& codice); //viene usata dalla scorpora qui sotto real scorpora(const real& lordo, const TRecord_text& rec); public: // virtual int autosave(TRelation& rel, const TRecord_text& rec); virtual bool pre_writerel(TRelation& rel,const TRecord_text& rec); void write_supporto(const TRecord_text& rec); void write_listini(const TRecord_text& rec); void write_offerte(const TRecord_text& rec); void set_config(const char * listingr,const char * listven, const char * offingr, const char * offven, const char * codiva); TCat2dl_file(const TString& file_name, const TString& config_name); virtual ~TCat2dl_file() { } }; TCat2dl_file::TCat2dl_file(const TString& file_name, const TString& config_name) : TFile_text(file_name, config_name), _condv(LF_CONDV), _rcondv(LF_RCONDV), _umart(LF_UMART) { } void TCat2dl_file::set_config(const char * listingr,const char * listven, const char * offingr, const char * offven, const char * codiva) { _listingr = listingr; _listven = listven; _offingr = offingr; _offven = offven; _codiva = codiva; } bool TCat2dl_file::pre_writerel(TRelation& rel,const TRecord_text& rec) { TRectype& curr = rel.curr(); if (curr.get("CODIVA").blank()) curr.put("CODIVA", _codiva); //se un campo data che finirebbe in un campo user di anamag.dbf e' pieno di 0, lo svuota for (int i = 5; i <= 8; i++) { TString8 user; user.format("USER%d", i); const TString& val = curr.get(user); if (real::is_null(val)) curr.zero(user); } // 1) sistema i tipi di supporto e genere write_supporto(rec); // 2) legge e scrive i dati dei listini: se il listino non esiste lo crea write_listini(rec); // 3) legge e scrive i dati delle offerte: se l'offerta non esiste la crea write_offerte(rec); return TRUE; } void TCat2dl_file::add_table_entry(const char * table, const char * entry) { if (entry && *entry > ' ') { const TRectype& rec = cache().get(table, entry); if (rec.empty()) { TTable tab(table); tab.put("CODTAB", entry); tab.put("S0", entry); tab.write(); } } } //scrive il supporto dell'articolo nel campo UM del file umart (unita' di misura) void TCat2dl_file::write_supporto(const TRecord_text& rec) { const TString& um = rec.get(7); if (!um.blank()) //il casino lo fa solo se ha un codice supporto non nullo { TString80 codart = rec.get(2); //Sistemiamo 'sto cavolo di supporto! codart.trim(); _umart.zero(); //prende il file delle unita' di misura... _umart.put(UMART_CODART, codart); _umart.put(UMART_UM, um); _umart.setkey(2); //..con chiave 2... const int err = _umart.read(); //..e lo legge if (err != NOERR) //Se non trova l'unita' di misura tra quelle gia' presenti... { _umart.setkey(1); _umart.put(UMART_CODART, codart); _umart.put(UMART_NRIGA, 999); _umart.read(_isgreat); const int uerr = _umart.prev(); int nriga = 1; if (uerr == NOERR && _umart.get(UMART_CODART) == codart) nriga = _umart.get_int(UMART_NRIGA) + 1; _umart.zero(); //..la aggiunge come ultima unita' di misura. _umart.put(UMART_CODART, codart); _umart.put(UMART_NRIGA, nriga); _umart.put(UMART_UM, um); _umart.put(UMART_FC, 1); } real prz = rec.get(11); //legge il prezzo listino ingrosso e lo mette nel campo prezzo di UMART prz/=100; _umart.put(UMART_PREZZO, prz); if (err == NOERR) _umart.rewrite(); else _umart.write(); add_table_entry("%UMS", um); } const TString& genere = rec.get(8); //Adesso tocca al genere! Va aggiornata la tabella di ditta GMC if (!genere.blank()) { add_table_entry("GMC", genere); } } //metodo x accelerare la lettura: se il codice iva esiste gia' evita di rileggere la percentuale dalla tabella TCodiceIVA& TCat2dl_file::codice_iva(const TString& codice) { TCodiceIVA* ci = (TCodiceIVA*)_lista_codici_iva.objptr(codice); //cerca nell'assoc_array dei codici iva se l'ha gia'letto if (ci == NULL) { ci = new TCodiceIVA(codice); _lista_codici_iva.add(codice, ci); } return *ci; } //metodo per lo scorporo iva real TCat2dl_file::scorpora(const real& lordo, const TRecord_text& rec) { TString8 codice = rec.get(19); if (codice.blank()) codice = _codiva; const TCodiceIVA& pippo = codice_iva(codice); //utilizza la codice_iva real valore = lordo; pippo.scorpora(valore); return valore; } //scrive i valori dei listini (prezzi e date) void TCat2dl_file::write_listini(const TRecord_text& rec) { real prz_ingr = rec.get(11); //legge il prezzo listino ingrosso prz_ingr /=100; if (prz_ingr != ZERO) //tutto il casino lo fa solo se il prezzo non e' nullo { //cache del listino ingrosso TToken_string condv_key; condv_key.add("L"); condv_key.add(""); condv_key.add(""); condv_key.add(""); condv_key.add(_listingr); const TRectype& listino_ingrosso = cache().get(LF_CONDV, condv_key); //creazione di un nuovo listino ingrosso se non esiste if (listino_ingrosso.empty()) //se il listino indicato nell'ini non esiste.. { _condv.zero(); //..se lo crea! _condv.put(CONDV_TIPO, 'L'); //listino _condv.put(CONDV_COD, _listingr); //ingrosso _condv.put(CONDV_DESCR, "LISTINO INGROSSO"); _condv.put(CONDV_SEQRIC, "A---"); //combinazione di AGR (vedi file che fai prima!) _condv.put(CONDV_GESTUM, "X"); //abilita gestione unita' di misura _condv.write(); } _rcondv.zero(); _rcondv.put(RCONDV_TIPO, 'L'); _rcondv.put(RCONDV_COD, _listingr); _rcondv.put(RCONDV_TIPORIGA, 'A'); //uguale anche x le righe listino (come sopra) _rcondv.put(RCONDV_CODRIGA, rec.get(2)); _rcondv.put(RCONDV_UM, rec.get(7)); _rcondv.put(RCONDV_PREZZO, prz_ingr); int err = _rcondv.write(); if (err != NOERR) _rcondv.rewrite(); } real prz_vend = rec.get(15); //legge il prezzo listino vendite e fa lo stesso procedimento del caso precedente prz_vend /=100; if (prz_vend != ZERO) { //cache del listino vendita TToken_string condv_key; condv_key.add("L"); condv_key.add(""); condv_key.add(""); condv_key.add(""); condv_key.add(_listven); const TRectype& listino_vendita = cache().get(LF_CONDV, condv_key); if (listino_vendita.empty()) { _condv.zero(); _condv.put(CONDV_TIPO, 'L'); _condv.put(CONDV_COD, _listven); _condv.put(CONDV_DESCR, "LISTINO VENDITA"); _condv.put(CONDV_SEQRIC, "A---"); _condv.put(CONDV_GESTUM, "X"); _condv.write(); } _rcondv.zero(); _rcondv.put(RCONDV_TIPO, 'L'); _rcondv.put(RCONDV_COD, _listven); _rcondv.put(RCONDV_TIPORIGA, 'A'); _rcondv.put(RCONDV_CODRIGA, rec.get(2)); _rcondv.put(RCONDV_UM, rec.get(7)); _rcondv.put(RCONDV_PREZZO, scorpora(prz_vend, rec)); int err = _rcondv.write(); if (err != NOERR) _rcondv.rewrite(); } } //metodo per determinare le campagne di offerta cui appartengono gli articoli importati void TCat2dl_file::calcola_offerta(const TDate& dataini, const TDate& datafine, TString& codoff) { if (_lista_offerte.items() == 0) { for (int err = _condv.first(); err != NOERR; err = _condv.next()) { if (_condv.get_char(CONDV_TIPO) == 'O') _lista_offerte.add(_condv.curr()); } } int last_off = 0; for (int i = _lista_offerte.last(); i>=0; i--) { const TRectype& condv = (const TRectype&) _lista_offerte[i]; const TString4 cod = condv.get(CONDV_COD); if (cod[0] == codoff[0]) { if (last_off == 0) last_off = atoi(cod.mid(1)); if (dataini >= condv.get_date(CONDV_VALIN) && datafine <= condv.get_date(CONDV_VALFIN)) { codoff = cod; break; } } } if (i < 0 ) { const char pref = codoff[0]; codoff.format("%c%02d", pref, last_off + 1); _condv.zero(); _condv.put(CONDV_TIPO, 'O'); _condv.put(CONDV_COD, codoff); TString descr = "CAMPAGNA "; descr << codoff << " (dal " << dataini << " al " << datafine << ")"; _condv.put(CONDV_DESCR, descr); _condv.put(CONDV_GESTUM, "X"); _condv.put(CONDV_VALIN, dataini); _condv.put(CONDV_VALFIN, datafine); _condv.write(); _lista_offerte.add(_condv.curr()); } } //scrive i valori delle offerte (prezzi e date) void TCat2dl_file::write_offerte(const TRecord_text& rec) { real prz_ingr = rec.get(14); //legge il prezzo offerta ingrosso prz_ingr /=100; if (prz_ingr != ZERO) //tutto il casino lo fa solo se il prezzo non e' nullo { const TDate dataini = rec.get(12); const TDate datafine = rec.get(13); calcola_offerta(dataini, datafine, _offingr); _rcondv.zero(); _rcondv.put(RCONDV_TIPO, 'O'); //adesso che sa che l'offerta esiste andiamo in rcondv _rcondv.put(RCONDV_COD, _offingr); _rcondv.put(RCONDV_TIPORIGA, 'A'); _rcondv.put(RCONDV_CODRIGA, rec.get(2)); _rcondv.put(RCONDV_UM, rec.get(7)); _rcondv.put(RCONDV_PREZZO, prz_ingr); int err = _rcondv.write(); if (err != NOERR) _rcondv.rewrite(); } real prz_vend = rec.get(18); //legge il prezzo offerta ingrosso prz_vend /=100; if (prz_vend != ZERO) //tutto il casino lo fa solo se il prezzo non e' nullo { const TDate dataini = rec.get(16); const TDate datafine = rec.get(17); calcola_offerta(dataini, datafine, _offven); _rcondv.zero(); //adesso che sa che l'offerta esiste andiamo in rcondv _rcondv.put(RCONDV_TIPO, 'O'); _rcondv.put(RCONDV_COD, _offven); _rcondv.put(RCONDV_TIPORIGA, 'A'); _rcondv.put(RCONDV_CODRIGA, rec.get(2)); _rcondv.put(RCONDV_UM, rec.get(7)); _rcondv.put(RCONDV_PREZZO, scorpora(prz_vend, rec)); int err = _rcondv.write(); if (err != NOERR) _rcondv.rewrite(); } } ///////////////////////////////////////////////////// // Classe TCat2dl: applicazione principale // ///////////////////////////////////////////////////// class TCat2dl: public TSkeleton_application { TMask* _msk; TCat2dl_file* _trasfile; TString _dlfilename, _dlsitepath, _listingr, _listvend, _offeingr, _offevend; TString8 _user, _password, _codiva; protected: virtual bool create(void); virtual void main_loop(); virtual bool destroy(void); void transfer(void); static bool annulla_handler(TMask_field& f, KEY k); public: const TMask& msk() const { return *_msk; } TCat2dl() {} virtual ~TCat2dl() {} }; // restituisce un riferimento all' applicazione inline TCat2dl& app() { return (TCat2dl&) main_app();} // creazione dell'applicazione bool TCat2dl::create() { open_files(LF_ANAMAG, LF_UMART, LF_CONDV, LF_RCONDV, LF_TAB, LF_TABCOM, 0); TConfig config("cat2dl.ini","PARAMS"); _dlfilename = config.get("DLFILENAME"); _dlsitepath = config.get("DLSITEPATH"); _listingr = config.get("LISTINGR"); _listvend = config.get("LISTVEND"); _offeingr = config.get("OFFEINGR"); _offevend = config.get("OFFEVEND"); _user = config.get("USER"); _password = config.get("PASSWORD"); _codiva = config.get("CODIVASTD"); _msk = new TMask("dl0800a"); _msk->set(F_FILENAME,_dlfilename); _msk->set(F_INTERNET,_dlsitepath); _msk->set(F_USER, _user); _msk->set(F_PASSWORD, _password); _msk->set(F_CODIVA, _codiva); _trasfile = NULL; return TSkeleton_application::create(); } // distruzione dell'applicazione bool TCat2dl::destroy() { delete _msk; return TSkeleton_application::destroy(); } // carica la maschera void TCat2dl::main_loop() { // Preimposta gli eventuali valori specificati sulla riga di comando //error_box("Attenzione: manca la configurazione del trasferimento!"); KEY key = K_ENTER; while (key != K_QUIT) { key = _msk->run(); if (key == K_ENTER) { _dlfilename = _msk->get(F_FILENAME); _dlsitepath = _msk->get(F_INTERNET); _user = _msk->get(F_USER); _password = _msk->get(F_PASSWORD); _codiva = _msk->get(F_CODIVA); { TConfig config("Cat2dl.ini", "PARAMS"); config.set("DLFILENAME", _dlfilename); config.set("DLSITEPATH", _dlsitepath); config.set("USER", _user); config.set("PASSWORD", _password); config.set("CODIVASTD", _codiva); } transfer(); } } } // trasferimento dati da file su archivi void TCat2dl::transfer() { const TFilename catdlini = "cat2dl.ini"; //selezione del tipo di omportazione const bool web = _msk->get_bool(F_SELECT); TFilename fileimport; if (web) //via web { TString site; // sito dl TFilename remote; // file remoto TString16 auth; // user+password cifrati split_url(_msk->get(F_INTERNET), site, remote); fileimport.temp("DL"); //file temporaneo locale su cui vengono trasferiti i dati cifratura_laziale(_user, _password, auth); if (!http_get(site, remote, fileimport, auth)) { error_box("Impossibile aggiornare i dati dall'indirizzo web specificato"); return; } } else fileimport = _msk->get(F_FILENAME); _trasfile = new TCat2dl_file(fileimport, catdlini); //file da importare in locale const unsigned long dimension = fsize(fileimport); _trasfile->set_config(_listingr,_listvend,_offeingr,_offevend,_codiva); //parametri dell'.ini _trasfile->open(fileimport,'r'); TProgind pi(dimension,"Acquisizione in corso..."); TRelation rel(LF_ANAMAG); TRectype& record = rel.curr(); //record corrente della relazione TString str; // Stringa jolly di lavoro TRecord_text curr; unsigned long processed_rec = 0L; const clock_t start_time = clock(); clock_t rt = 0, wt = 0; while (TRUE) { const clock_t read_time = clock(); if (_trasfile->read(curr) != NOERR) break; const clock_t write_time = clock(); processed_rec ++; if (processed_rec%100 == 0) { unsigned long time = (clock()-start_time); unsigned long rs = processed_rec*1000/time; rt /= 100; wt /= 100; str.format("%lu rec; %lu sec; %lu rec/sec;\nmean read %lu; mean write %lu", processed_rec, time/1000, rs, rt, wt); rt = wt = 0; pi.set_text(str); pi.setstatus(_trasfile->read_file()->tellg()); } if (pi.iscancelled()) //se clicchi annulla si ferma davvero break; _trasfile->autosave(rel, curr); //esegue l'effettivo passaggio dati basandosi sulla formattazione del file .ini rt += write_time - read_time; wt += clock() - write_time; } const clock_t t = clock() - start_time; if (t > 0) { ofstream pippo("dl.log"); pippo << "records = " << processed_rec << endl; pippo << "time = " << t/1000 << endl; pippo << "speed = " << (processed_rec*1000/t) << endl; } _trasfile->close(); message_box("Operazione terminata"); } // handler per gestire la conferma dell'annullamento dei dati inseriti // nella maschera bool TCat2dl::annulla_handler(TMask_field& f, KEY k) { TMask &m = f.mask(); if (k == K_SPACE) { if (yesno_box("Vuoi veramente annullare i dati inseriti")) m.reset(); } return TRUE; } // gestione dei messaggi estesi nei campi void TCat2dl_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str) { const TString16 code = s.get(0); if (code == "_UPPERCASE") { str.upper(); } else NFCHECK("Macro non definita: %s", (const char *)code); } int dl0800(int argc, char* argv[]) { TCat2dl a ; a.run(argc, argv, "Importazione catalogo"); return 0; }