#include #include #include #include #include #include #include "lvlib.h" #include "lvrconsplan.h" #include "lvpasplan.h" #include "lv2.h" #include "lv2200a.h" /////////////////////////////////////////////////////////// // TGestione_planning maschera /////////////////////////////////////////////////////////// class TGestione_planning_mask : public TAutomask { TToken_string _rigaoriginale; private: void fill_sheet(); bool changed(TToken_string& oldrow, TToken_string& newrow, short id); int codice_riga(const TDate& data); void aggiorna_plan(); void rewrite_all(TToken_string& rigamodificata, TDate& data, long codplan); bool cancella_riga(); void nuova_riga(); public: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); TGestione_planning_mask (const char* name) : TAutomask(name) {} }; //questa funzione si occupa di riempire lo sheet dinamicamente in base ai parametri che l'utente decide void TGestione_planning_mask::fill_sheet() { if (field(F_DADATA).empty() || field(F_ADATA).empty()) return; TString query = "USE LVRCONSPLAN KEY 2"; const long coditi = get_long(F_CODITI); const long codcli = get_long(F_CODCF); if (coditi || codcli) { query << " SELECT "; if (codcli > 0) query << "(CODCF=" << codcli << ')'; if (coditi > 0) { if (codcli > 0) query << "&&"; query << "(CODITI=" << coditi << ')'; } } query << "\n"; query << "FROM DTCONS=" << get(F_DADATA) << "\n"; query << "TO DTCONS=" << get(F_ADATA) << "\n"; TISAM_recordset plan(query); TProgind pi(plan.items(), TR("Elaborazione dati planning in corso..."), true, true); TSheet_field& sheet = sfield(F_PLAN); TMask& sheetmask = sheet.sheet_mask(); TRelation& rel = *plan.cursor()->relation(); //accesso al file delle righe sheet.destroy(); for (bool ok = plan.move_first(); ok; ok = plan.move_next()) { if (!pi.addstatus(1)) break; TToken_string& row = sheet.row(-1); //crea una nuova riga dello sheet //scandisco nella maschera tutti i campi che hanno un field FOR_EACH_MASK_FIELD(sheetmask,i,f) { const TFieldref* fr = f->field(); //leggo il valore dalla relation if (fr != NULL) { const int pos = sheet.cid2index(f->dlg()); row.add(fr->read(rel),pos); //metto il valore letto nella posizione corretta nella TToken_string } } sheet.check_row(sheet.items()-1); //fa fare alla maschera la decodifica dei codici e aggiorna la TToken_string } sheet.force_update(); } //funzione che confronta due due campi di una TToken_string e restitusce true se sono diversi bool TGestione_planning_mask::changed(TToken_string& oldrow, TToken_string& newrow, short id) { const TSheet_field& sheet = sfield(F_PLAN); const int i = sheet.cid2index(id); const TFixed_string oldval(oldrow.get(i)); const TFixed_string newval(newrow.get(i)); return oldval != newval; } //questa funzione trova il primo codiceriga libero per un certo codplan int TGestione_planning_mask::codice_riga(const TDate& data) { const long codplan = data.date2ansi(); //per ora memorizzo zero int ptriga = 0; //se esiste almeno una riga, memorizzo il codriga dell'ultima TISAM_recordset rplan("USE LVRCONSPLAN KEY 1\nFROM CODPLAN=#CODPLAN\nTO CODPLAN=#CODPLAN"); rplan.set_var("#CODPLAN",TVariant(codplan)); if (rplan.move_last()) ptriga = rplan.get(LVRCONSPLAN_CODRIGA).as_int(); ptriga++; //incremento il codriga interessato return ptriga; } //questa funzione gestisce l'aggiornamanto dinamico dello sheet void TGestione_planning_mask::aggiorna_plan() { //bool che indicano se effettivamente devo fare una rewrite dei dati... //...se ho modificato un autista e/o un mezzo, questo va modificato su tutte... //...le righe di quel planning se confermato dall'utente bool dorewrite = false; bool updatecar = false; //variabili che mi premettono di lavorare sullo sheet TSheet_field& sheet = sfield(F_PLAN); TToken_string rigamodificata = sheet.row(sheet.selected()); //metto in una stringa la riga che sto analizzando //instanzio un isam file sulla tabella dei planning TLocalisamfile rplan(LF_LVRCONSPLAN); //creo il codplan const int posdata = sheet.cid2index(F_S_DATA); TDate data = _rigaoriginale.get(posdata); long codplan = data.date2ansi(); const long codplanor = codplan ; //creo il codriga const int posriga = sheet.cid2index(F_S_RIGA); int codriga = _rigaoriginale.get_int(posriga); //se esiste almeno una riga per quel planning, leggo il record corrispondente if (codriga > 0) { rplan.zero(); rplan.put(LVRCONSPLAN_CODPLAN,codplanor); rplan.put(LVRCONSPLAN_CODRIGA,codriga); rplan.read(); } //se ho modificato la data di una riga esistente, o se se ho creata una nuova, allora if (changed(_rigaoriginale,rigamodificata,F_S_DATA) || codriga <= 0) { //se esiste almeno una riga, elimino quella che voglio modifcare if (codriga > 0) rplan.remove(); //creo i nuovi codplan e codriga data = rigamodificata.get(posdata); codplan = data.date2ansi(); codriga = codice_riga(data); //creo la nuova riga rplan.zero(); rplan.put(LVRCONSPLAN_CODPLAN,codplan); rplan.put(LVRCONSPLAN_CODRIGA,codriga); rplan.put(LVRCONSPLAN_CODPLANOR,codplanor); //scrivo la nuova riga rplan.write(); //modifico anche la TToken_string così da evitare errori al momento della rewrite rigamodificata.add(data,posdata); rigamodificata.add(codriga,posriga); dorewrite = true; } //se viene modificato un periodo di sospensione e/o una modalità di passaggio... //...e/o un codice itinerario su una riga, devo fare la rewrite di quella riga //ATTENZIONE: la modifica di un itinerario implica anche la modifica di autista e mezzo... //...mettendo quelli previsti per il nuovo itinerario if (changed(_rigaoriginale,rigamodificata,F_S_PERSOSPVAR) || changed(_rigaoriginale,rigamodificata,F_S_MODPASS) || changed(_rigaoriginale,rigamodificata,F_S_ITI)) dorewrite = true; //se viene modificato un autista e/o un mezzo devo fare la rewrite di quella riga... //... e riaggiornare anche tutte le righe di quell'itinerario in quella data con i nuovi parametri if (changed(_rigaoriginale,rigamodificata,F_S_CODAUT) || changed(_rigaoriginale,rigamodificata,F_S_CODMEZ)) dorewrite = updatecar = true; //se devo fare una rewrite: if (dorewrite) { TMask& m = sheet.sheet_mask(); //per ogni campo della maschera che ha un field, ci scrivo dentro il nuovo valore FOR_EACH_MASK_FIELD(m,i,f) { const TFieldref* rf = f->field(); if (rf != NULL) { const char* val = rigamodificata.get(sheet.cid2index(f->dlg())); rf->write(val,rplan.curr()); } } rplan.curr().zero(LVRCONSPLAN_CONSSTD); lv_set_update_info(rplan.curr()); rplan.rewrite(); if (updatecar) rewrite_all(rigamodificata, data, codplan); } return; } void TGestione_planning_mask::rewrite_all(TToken_string& rigamodificata, TDate& data, long codplan) { //instanzio una variabile di sheet TSheet_field& sheet = sfield(F_PLAN); //instanzio un isam file sulla tabella dei planning TLocalisamfile rplan(LF_LVRCONSPLAN); //se ho modificato autista e/o mezzo, allora: TString msg; msg << "Si desidera apportare le stesse modifiche\n" << " sull'autista e/o sul mezzo su tutte le righe\n" << " del planning in data " << data << "?"; if (yesno_box(msg)) { //recupero dai dati modificati i nuovi valori di autista e mezzo const int codaut = rigamodificata.get_int(sheet.cid2index(F_S_CODAUT)); const TString8 codmez= rigamodificata.get(sheet.cid2index(F_S_CODMEZ)); //recupero il codice itinerario su cui sto facendo la modifica const long coditi = rigamodificata.get_long(sheet.cid2index(F_S_ITI)); //instanzio un recordset sui planning, filtrando sui coditi TISAM_recordset recrplan("USE LVRCONSPLAN SELECT CODITI=#CODITI\nFROM CODPLAN=#CODPLAN\nTO CODPLAN=#CODPLAN"); recrplan.set_var("#CODPLAN",codplan); recrplan.set_var("#CODITI",coditi); TRectype& rec = recrplan.cursor()->curr(); for (bool ok = recrplan.move_first(); ok; ok = recrplan.move_next()) { //cambio autista e mezzo rec.put(LVRCONSPLAN_CODAUT,codaut); rec.put(LVRCONSPLAN_CODMEZ,codmez); rec.zero(LVRCONSPLAN_CONSSTD); lv_set_update_info(rec); //faccio l'effettiva rewrite rec.rewrite(rplan); } } fill_sheet(); return; } //questa funzione elimina una riga dal planning bool TGestione_planning_mask::cancella_riga() { int err=NOERR; //variabile che mi permette di lavorare sullo sheet TSheet_field& sheet = sfield(F_PLAN); //instanzio un isam file sulla tabella dei planning TLocalisamfile rplan(LF_LVRCONSPLAN); //creo il codplan const int posdata = sheet.cid2index(F_S_DATA); TDate data = _rigaoriginale.get(posdata); long codplan = data.date2ansi(); //creo il codriga const int posriga = sheet.cid2index(F_S_RIGA); int codriga = _rigaoriginale.get_int(posriga); //se esiste almeno una riga per quel planning, leggo il record corrispondente if (codriga > 0) { rplan.zero(); rplan.put(LVRCONSPLAN_CODPLAN,codplan); rplan.put(LVRCONSPLAN_CODRIGA,codriga); err = rplan.remove(); } return err == NOERR; } //questa funzione genera una nuova riga di planning e propone sullo sheet i campi che può riempire void TGestione_planning_mask::nuova_riga() { TSheet_field& sheet = sfield(F_PLAN); TToken_string& rigamodificata = sheet.row(sheet.selected()); rigamodificata.add(get_date(F_DADATA),sheet.cid2index(F_S_DATA)); if (!field(F_CODCF).empty()) { rigamodificata.add(get_long(F_CODCF),sheet.cid2index(F_S_CODCF)); rigamodificata.add(get(F_RAGSOCCLI),sheet.cid2index(F_S_RAGSOCCLI)); } if (!field(F_CODITI).empty()) rigamodificata.add(get_long(F_CODITI),sheet.cid2index(F_S_ITI)); sheet.check_row(sheet.selected()); //fa fare alla maschera la decodifica dei codici e aggiorna la TToken_string return; } //questa funzione gestisce i vari eenti che si verificano sui campi della maschera bool TGestione_planning_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { //se questi campi vengono riempiti, allora riempi lo sheet opportunamante case F_DADATA: case F_ADATA: case F_CODITI: case F_CODCF: if (e == fe_modify) { fill_sheet(); } break; //analisi delle operazioni sullo sheet case F_PLAN: switch (e) { case se_query_modify: //se viene selezionata una riga, la salvo in una variabile globale { TSheet_field& sheet = (TSheet_field&)o; _rigaoriginale = sheet.row(sheet.selected()); } break; case se_notify_modify: //se avviene una modifica, aggiorna il planning e lo sheet aggiorna_plan(); fill_sheet(); break; case se_notify_del: //se viene eliminata una riga dallo sheet, cancellala anche dal file cancella_riga(); break; case se_query_add: //se si decide di fare una modifica sullo sheet, ma i campi data della testata sono vuoti, rifiutati if (field(F_DADATA).empty()) return false; break; case se_notify_add: //se si aggiunge una riga nuova allo sheet, svuota la var globale e aggiungi la riga anche al file _rigaoriginale = ""; nuova_riga(); break; default: break; } break; //quando riempio il campo data dello sheet, decodifica il giorno di consegna case F_S_DATA: if (e == fe_modify || e == fe_init) { const TDate dtcons = o.get(); const TString16 ggcons = itow(dtcons.wday()); o.mask().set(F_S_GIORNO,ggcons); } break; //quando riempio il campo itinerario dell sheet, recupero i dati di autista e mezzo da &ITI case F_S_ITI: if (e == fe_modify && !o.empty()) { TMask& msk = o.mask(); const TRectype& iti = cache().get("&ITI",o.get()); if (!iti.empty()) { const bool riganuova = msk.get_int(F_S_RIGA) <= 0; if (riganuova || msk.field(F_S_CODAUT).empty()) msk.set(F_S_CODAUT,iti.get("S1")); if (riganuova || msk.field(F_S_CODMEZ).empty()) msk.set(F_S_CODMEZ,iti.get("S2")); } } break; //quando riempio il campo cliente sullo sheet controllo se posso proporre dei dati di default sul planning case F_S_CODCF: if (e == fe_modify && !o.empty()) { TMask& msk = o.mask(); //maschera di sheet TLocalisamfile pplan(LF_LVPASPLAN); pplan.put(LVPASPLAN_CODCF,msk.get(F_S_CODCF)); pplan.put(LVPASPLAN_CODCONT,msk.get(F_S_CODCONT)); pplan.put(LVPASPLAN_GGCONS,msk.get_date(F_S_DATA).wday()); int err = pplan.read(_isgteq); //se trovo dei dati validi sulla tabella LF_LVPASPLAN, riempio tutti i campi che riesco,... //...utilizzando anche la tabella &ITI if (err == NOERR) { msk.set(F_S_ITI,pplan.get_int(LVPASPLAN_CODITI),true); msk.set(F_S_ORDFER,pplan.get_int(LVPASPLAN_ORDFERM)); msk.set(F_S_MODPASS,pplan.get_char(LVPASPLAN_MODPASS)); } } break; default: break; } return true; } /////////////////////////////////////////////////////////// // TGestione_planning applicazione /////////////////////////////////////////////////////////// class TGestione_planning_app : public TSkeleton_application { TGestione_planning_mask* _msk; protected: virtual bool create(); virtual bool destroy(); public: bool transfer(); virtual void main_loop(); }; bool TGestione_planning_app::create() { _msk = new TGestione_planning_mask("lv2200a"); return TSkeleton_application::create(); } bool TGestione_planning_app::destroy() { delete _msk; return TApplication::destroy(); } bool TGestione_planning_app::transfer() { return true; } void TGestione_planning_app::main_loop() { while (_msk->run() == K_ENTER) transfer(); } int lv2200(int argc, char* argv[]) { TGestione_planning_app app; app.run(argc, argv, TR("Gestione planning")); return 0; }