#include #include #include #include #include #include #include "../cg/cglib01.h" #include "../mg/mglib.h" #include "ve6.h" #include "ve6500.h" //cosí includo i codici dei campi della maschera ve6500.uml #include #include #include "../mg/anamag.h" #include "velib.h" ////////// Dichiarazione delle classi ///////////////////// /////////////////////////////////////////////////////////// // TDoc_recordset /////////////////////////////////////////////////////////// class TDoc_recordset : public TISAM_recordset { TDocumento * _doc; TRecnotype _mypos; public: virtual TRecnotype items() const { return _doc->physical_rows();} virtual TRecnotype current_row() const { return _mypos; } virtual bool move_to(TRecnotype pos); virtual const TVariant& get(int logic, const char* field) const; TDocumento& doc() { return *_doc; } TRiga_documento& riga_doc(int r = 0) const; TDoc_recordset(const TDocumento& doc, const TString & query); virtual ~TDoc_recordset(); }; TRiga_documento& TDoc_recordset::riga_doc(int n) const { if (n <= 0) n = _mypos+1; else if (n > items()) // Non dovrebbe succedere mai { n = _doc->new_row().get_int(RDOC_NRIGA); (*_doc)[n].put(RDOC_TIPORIGA, "05"); // Crea ua riga descrizione fittizia } return (*_doc)[n]; } bool TDoc_recordset::move_to(TRecnotype pos) { const bool ok = pos >= 0 && pos < items(); if (ok) { if (pos != _mypos) { TRelation& rel = *relation(); _mypos = pos; rel.curr(LF_RIGHEDOC) = riga_doc(); // Copia riga corrente nella relazione rel.update(1); // Aggiorna solo i file della relazione dipendenti da LF_RIGHEDOC } } return ok; } const TVariant& TDoc_recordset::get(int logic, const char* field) const { if (logic == 0 || logic == LF_DOC) { const TFieldref ref(field, LF_DOC); return get_tmp_var() = ref.read(*_doc); } else if (logic == LF_RIGHEDOC) { const TFieldref ref(field, LF_RIGHEDOC); return get_tmp_var() = ref.read(riga_doc()); } return TISAM_recordset::get_field(logic, field); } TDoc_recordset::TDoc_recordset(const TDocumento& doc, const TString & query) : TISAM_recordset(query), _doc(NULL) { _doc = new TDocumento(doc); } TDoc_recordset::~TDoc_recordset() { if (_doc != NULL) delete _doc; } class TPenna_mask : public TAutomask { private: bool _gestmag; bool _gestdep; bool _gestmultimag; TString4 _codmagc; protected: virtual bool on_field_event(TOperable_field& f, TField_event e, long jolly); virtual void on_firm_change(); public: void set_magc(const TString& magc) { set(F_MAGC, _codmagc = magc); } TPenna_mask(); virtual ~TPenna_mask(){} }; bool TPenna_mask::on_field_event(TOperable_field& f, TField_event e, long jolly) //definizione di on_field_event { //é la funzione che gestisce gli switch (f.dlg()) //eventi, tipo pressione dei tasti { case F_FILE: if(e==fe_button) //se e (che é l'evento) = pressione del bottone 'cerca' (fe button) { DIRECTORY dir; FILE_SPEC fs; TFilename fname=f.get(); //se il nome del file non esiste -> gli assegna automaticamente il nome if(fname == "") //articoli.dat fname = "articoli"; xvt_fsys_get_dir(&dir); //funzioni di xvt (grafica); utilizzate per creare la finestra di ricerca del xvt_fsys_get_dir(&fs.dir); //file di tipo .dat (é una finestra tipo gestione risorse Windows) strcpy(fs.type, "dat"); strcpy(fs.name, fname); strcpy(fs.creator, "ELD"); const bool good = xvt_dm_post_file_open(&fs, "Selezionare il file ...") == FL_OK; xvt_fsys_set_dir(&dir); if (good) { xvt_fsys_convert_dir_to_str(&fs.dir, fname.get_buffer(), fname.size()); //converte il nome della directory in una fname.add(fs.name); //stringa aggiungendo il path del file f.set(fname); //mostra il campo sul video (la funzione set) } } if(e==fe_init && f.get().empty()) f.set("articoli.dat"); if(e==fe_close) //se e = alla pressione del bottone 'chiudi' (fe_close) controlla che il campo sia stato { //riempito correttamente nella maschera TFilename n=f.get(); return n.exist(); } break; case F_TIPORIGA: if(e==fe_init && f.get().empty()) f.set("01"); break; case F_TIPO: //scelta del tipo di registrazione if(e==fe_init || e==fe_modify) { if (!_gestdep) hide(F_DEP); } break; case F_MAGC: if (e == fe_init && f.empty() && _codmagc.full()) { f.set(_codmagc); f.check(STARTING_CHECK); } break; default: break; } return TRUE; } void TPenna_mask::on_firm_change() //funzione per settare i campi maschera in base alla ditta scelta { TAutomask::on_firm_change(); TConfig ini(CONFIG_DITTA,"mg"); //apre il file di configurazione della ditta (modulo mg required) _gestmag=ini.get_bool("GESMAG"); //setta la var bool in base all'interrogazione con get_bool (ovvero: se //GESMAG esiste->true, altrimenti false _gestdep=_gestmag && ini.get_bool("GESDEPOSITI"); //fa la stessa cosa con la GESDEPOSITI (l'and ci vuole perché la gestio _gestmultimag=_gestmag && ini.get_bool("GESMULTIMAG"); //depositi non puó esistere senza il magazzino; uguale per la //GESMULTIMAG } TPenna_mask::TPenna_mask():TAutomask("ve6500") //contructor di TPenna_mask;public di TAutomask chiama la maschera ve6500 { on_firm_change(); //chiama la funzione on_firm_change, che aggiorna in tutti i campi della //maschera che fanno rif. ad una ditta, con il rif. alla ditta attuale } class TCheck_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& f, TField_event e, long jolly); public: TCheck_mask() : TAutomask("ve6500b") {} //contructor di TPenna_mask;public di TAutomask chiama la maschera ve6500 virtual ~TCheck_mask(){} }; bool TCheck_mask::on_field_event(TOperable_field& f, TField_event e, long jolly) //definizione di on_field_event { //é la funzione che gestisce gli switch (f.dlg()) //eventi, tipo pressione dei tasti { case F_FILE: if(e==fe_button) //se e (che é l'evento) = pressione del bottone 'cerca' (fe button) { DIRECTORY dir; FILE_SPEC fs; TFilename fname=f.get(); //se il nome del file non esiste -> gli assegna automaticamente il nome if(fname == "") //articoli.dat fname = "articoli"; xvt_fsys_get_dir(&dir); //funzioni di xvt (grafica); utilizzate per creare la finestra di ricerca del xvt_fsys_get_dir(&fs.dir); //file di tipo .dat (é una finestra tipo gestione risorse Windows) strcpy(fs.type, "dat"); strcpy(fs.name, fname); strcpy(fs.creator, "ELD"); const bool good = xvt_dm_post_file_open(&fs, "Selezionare il file ...") == FL_OK; xvt_fsys_set_dir(&dir); if (good) { xvt_fsys_convert_dir_to_str(&fs.dir, fname.get_buffer(), fname.size()); //converte il nome della directory in una fname.add(fs.name); //stringa aggiungendo il path del file f.set(fname); //mostra il campo sul video (la funzione set) } } if(e==fe_init && f.get().empty()) f.set("articoli.dat"); if(e==fe_close) //se e = alla pressione del bottone 'chiudi' (fe_close) controlla che il campo sia stato { //riempito correttamente nella maschera TFilename n=f.get(); return n.exist(); } break; default: break; } return TRUE; } class TPenna_app : public TSkeleton_application { private: TFilename _ini_name; int _first_row; TString4 _codmagc; protected: virtual void main_loop(); void load_doc(); void check_doc(); public: bool load_ini(bool check); }; /////////// Definizione delle funzioni membro //////////// bool TPenna_app::load_ini(bool check) //definizione della member function load_ini, della classe TPenna_app { const int args = argc(); //argc é un intero che specifica quanti parametri vengono passati al const int narg = check ? 3 : 2; //programma dalla linea di comando if (args <= narg) return FALSE; //argv é un array di null-terminated strings const TFixed_string arg = argv(narg); if ((arg[0] != '-' && arg[0] != '/') || (arg[1] != 'i' && arg[1] != 'I')) return FALSE; _ini_name = arg.mid(2); if (_ini_name.blank() && args > 3) _ini_name = argv(3); if (!_ini_name.exist()) //controlla che il file su cui deve scrivere ci sia; se non c'é dá return FALSE; //una segnalazione di errore TConfig ini(_ini_name, "Main"); //istanza di TConfig, chiamata ini TString_array paragrafi; //array di stringhe int numpar = ini.list_paragraphs(paragrafi); //legge la lista dei paragrafi, li conta e mette il numero in numpar; lo //fa la funzione num_paragraphs if(numpar<2) return FALSE; TToken_string para(paragrafi.row(numpar-1),','); //istanzia (con il nome di para) la classe TToken_string, utilizzando il suo //primo constructor (ne ha 3); setta come separatore di caratteri la , al //posto del | di default; row é un metodo della classe TString_array che //ritorna la stringa alla posizione specificata dal parametro _first_row = para.get_int(1)+1; //assegna a _first_row il numero (trasformato da una stringa con get_int) //dell'ultima riga usata+1, cioé la prima riga libera: é il punto in cui //cominciare a scrivere _codmagc = ini.get("CODMAGC", "33"); // Cerca un eventuale magazzino collegato da proporre return TRUE; } void TPenna_app::check_doc() //definizione della member function main_loop, della classe TPenna_app { TCheck_mask m; //istanza di TPenna_mask con il nome m (perche'ho chiamato una maschera) if(m.run()==K_ENTER) { TConfig ini(_ini_name, "Transaction"); //apre il file su cui scrivere //chiamo il nome del file F_FILE che abbiamo scelto con la maschera; get //legge una stringa TRecord_cache c(LF_CODCORR, 2); const TFilename nomefile = m.get(F_FILE); //assegno alla variabile nomefile la stringa letta con m.get(F_FILE); //nomefile é una variabile di tipo TFilename TString16 para; //codice del paragrafo corrente TFile_text articoli(nomefile,"opticpen.ini"); //crea un oggetto articoli di tipo TFile_text TRecord_text articolocor; //crea un record vuoto con nome articolocor TTracciato_record & rec = *(articoli.t_rec("")); const int nfields = rec.tracciati_campo().items(); TString codice; //crea una stringa per contenere il codice para.format("%d", LF_DOC); const int anno = ini.get_int(DOC_ANNO, para); const TString4 codnum(ini.get(DOC_CODNUM)); const char provv = ini.get_char(DOC_PROVV); const long ndoc = ini.get_long(DOC_NDOC); int fcod = -1; int fmag = -1; int fqta = -1; TDocumento d(provv, anno, codnum, ndoc); for (int f = 0; f < nfields; f++) { const TTracciato_campo & c = rec.get(f); const TString name = c.name(); if (name == RDOC_CODART) fcod = f; else if (name == RDOC_CODMAG) fmag = f; else if (name == RDOC_QTA) fqta = f; } if (fcod < 0) { error_box("Manca il campo codice nel file del terminale"); return; } if (fqta < 0) { error_box("Manca il campo quantità nel file del terminale"); return; } articoli.open(); //applico il metodo open che apre il file in lettura (contenuta in TFile_text) for(int i=_first_row;articoli.ok_r();i++) //ok_r é una funzione che indica la fine del file { if(articoli.read(articolocor)==NOERR) { bool found = false; TString codice = articolocor.get(fcod); TString codicecorr; const real qta(articolocor.get(fqta)); TString16 mag; codice.trim(); const TRectype & codcorr = c.get(codice); if (!codcorr.empty()) codicecorr = codcorr.get("CODART"); if (fmag >= 0) mag = articolocor.get(fmag); for (int r =1; !found && r <= d.physical_rows() ; r++) { TRiga_documento & row = d[r]; const TString & rowcod = row.get(RDOC_CODART); if ((codice == rowcod) ||(codicecorr == rowcod)) { if (mag.blank() || mag == row.get(RDOC_CODMAG)) { const real q = qta + row.get_real(RDOC_QTAGG1); row.put(RDOC_QTAGG1, q); found = true; } } } if (!found) { TRiga_documento & row = d.new_row("01"); row.put(RDOC_CODART, codice); row.put(RDOC_CODARTMAG, codice); row.put(RDOC_CODMAG, mag); row.put(RDOC_DESCR, cache().get(LF_ANAMAG, codice, ANAMAG_DESCR)); row.put(RDOC_QTAGG1, qta); } } } articoli.close(); const int rows = d.physical_rows(); bool doc_different = false; for (int r = rows; !doc_different && r > 0; r--) { TRiga_documento & row = d[r]; const real qta1 = row.get_real(RDOC_QTAGG1); doc_different = row.get_real(RDOC_QTA) != qta1; } TReport rep; TReport_book book; ini.set("Result", "SUCCESS", "Transaction"); //comunica al chiamante il successo della transazione if (doc_different) { if (rep.load("ve6500a")) { const TString query(rep.recordset()->query_text()); rep.set_recordset(new TDoc_recordset(d, query)); book.add(rep); if (book.pages() > 0) book.print_or_preview(); for (int r = rows; r > 0; r--) { TRiga_documento & row = d[r]; const real qta1 = row.get_real(RDOC_QTAGG1); if (qta1 == ZERO) d.destroy_row(r, true); else { if (row.get_real(RDOC_QTA) != qta1) row.put(RDOC_QTA, qta1); row.zero(RDOC_QTAGG1); } } if (yesno_box("Si desidera aggiornare il documento\ncon la lettura da terminale")) { const int rows = d.rows(); const int items = TRectype(LF_RIGHEDOC).items(); for (int r = 1; r <= rows; r++) { const TRiga_documento & row = d[r]; para.format("%d,%d", LF_RIGHEDOC, r); // scrive i due numeri (%d) separati dalla , con format (che formatta // la stringa para con il formato specificato tra " ") ini.set_paragraph(para); // sposta il cursore sulla nuova para (nuovo valore) for (int f = 0; f < items; f++) { const char * name = row.fieldname(f); const TString & val = row.get(name); ini.set(name, val); // scrive il codice sul file ini } } } else ini.set("Result", "ERROR", "Transaction"); //comunica al chiamante l'insuccesso della transazione } else error_box("Non posso leggere il report ve6500.rep"); } xvt_fsys_removefile(nomefile); } } void TPenna_app::load_doc() //definizione della member function main_loop, della classe TPenna_app { TPenna_mask m; //istanza di TPenna_mask con il nome m (perche'ho chiamato una maschera) m.set_magc(_codmagc); // Propone l'eventuale magazzino collegatp if(m.run()==K_ENTER) { TConfig ini(_ini_name, "Transaction"); //apre il file su cui scrivere //chiamo il nome del file F_FILE che abbiamo scelto con la maschera; get //legge una stringa ini.set("Result", "SUCCESS"); //comunica al chiamante il successo della transazione const TFilename nomefile = m.get(F_FILE); //assegno alla variabile nomefile la stringa letta con m.get(F_FILE); //nomefile é una variabile di tipo TFilename const TString4 tiporiga = m.get(F_TIPORIGA); const int tipo = m.get_int(F_TIPO); //var int che indica la modalitá di archiviazione (0=quantitá, 1=dif. giac.) TString16 para; //codice del paragrafo corrente TFile_text articoli(nomefile,"opticpen.ini"); //crea un oggetto articoli di tipo TFile_text TRecord_text articolocor; //crea un record vuoto con nome articolocor TTracciato_record & rec = *(articoli.t_rec("")); const int nfields = rec.tracciati_campo().items(); TString codice; //crea una stringa per contenere il codice para.format("%d", LF_DOC); TDate datadoc(ini.get(DOC_DATADOC, para)); //dal paragrafo testata documento prende il valore della data del //documento TString16 annoes; annoes.format("%04d", esercizi().date2esc(datadoc)); //crea un intero lungo 4 riempito di 0 all'inizio TString8 codmag = m.get(F_MAG); // setta codmag in base al valore della maschera codmag.left_just(3) << m.get(F_DEP); // attacca a codmag il F_DEP, codice deposito dalla maschera TString8 codmagc = m.get(F_MAGC); // setta codmagc in base al valore della maschera codmagc.left_just(3) << m.get(F_DEPC); // attacca a codmagc il F_DEPC, codice deposito collegato dalla maschera TString val; articoli.open(); //applico il metodo open che apre il file in lettura (contenuta in TFile_text) for(int i=_first_row;articoli.ok_r();i++) //ok_r é una funzione che indica la fine del file { if(articoli.read(articolocor)==NOERR) { para.format("%d,%d", LF_RIGHEDOC,i); // scrive i due numeri (%d) separati dalla , con format (che formatta // la stringa para con il formato specificato tra " ") ini.set_paragraph(para); // sposta il cursore sulla nuova para (nuovo valore) ini.set(RDOC_TIPORIGA,tiporiga); ini.set(RDOC_CODARTMAG, NULL_CODART); // scrive il codice per forzare il check ini.set(RDOC_CODMAG, codmag); // magazzino di default ini.set(RDOC_CODMAGC, codmagc); // magazzino collegato for (int f = 0; f < nfields; f++) { const TTracciato_campo & c = rec.get(f); const TString& name = c.name(); if (name.not_empty()) { val = articolocor.get(f); val.trim(); if (name == RDOC_CODART) codice = val; else if (name == RDOC_QTA && tipo==1) { TArticolo_giacenza & art = cached_article_balances(codice); real quantita(val); const real giacenza=art.disponibilita(annoes,codmag,"",TRUE); quantita = giacenza - quantita; val = quantita.string(); } ini.set(name, val); // scrive il codice sul file ini } } } else break; } articoli.close(); xvt_fsys_removefile(nomefile); } } void TPenna_app::main_loop() //definizione della member function main_loop, della classe TPenna_app { if (!has_module(POAUT, CHK_DONGLE)) { error_box("Modulo penna ottica non attivato"); return; } TString sw(argv(2)); sw.upper(); const bool chk_doc = sw == "-V"; open_files(LF_TAB,LF_TABCOM,LF_DOC,LF_RIGHEDOC,LF_ANAMAG,LF_MAG,LF_UMART,0); if(! load_ini(chk_doc)) { error_box("Impossibile aprire il file '%s'",(const char*)_ini_name); //mostra un messaggio di errore se non riesce ad aprire //il file richiesto; nota la conversione dei tipi che //é da eseguire quando devo passare una TString ad un %s return; } if (chk_doc) check_doc(); else load_doc(); } ////// Esecuzione del programma /////////// int ve6500(int argc, char** argv) { TPenna_app app; app.run(argc,argv,"Terminali portatili"); return 0; }