#include #include #include #include #include "lvlib.h" #include "lv0.h" #include "lv0500a.h" #include "lvpasplan.h" #include "lvperisop.h" //////////////// // MASCHERA // //////////////// class TPass_plan_contr_mask : public TAutomask { private: void proponi_orario(); void nuovo_persosp(); protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TPass_plan_contr_mask(); }; void TPass_plan_contr_mask::proponi_orario() { TSheet_field& sheet = sfield(F_PASPLAN); TToken_string& rigamodificata = sheet.row(sheet.items()-1); rigamodificata.add("00:00",sheet.cid2index(F_S_ORA)); return; } //questa funzione viene richiamata ogni volta che si aggiunge una riga allo sheet dei periodi di sospensione... //...e propone il codice del periodo in automatico void TPass_plan_contr_mask::nuovo_persosp() { //recupero il codcf e il codcont dalla maschera const long codcli = get_long(F_CODCF); const long codcont = get_long(F_CODCONT); int codper; //codice periodo di sospensione //variabili per lavorare sullo sheet TSheet_field& sheet = sfield(F_PERSOSP); TToken_string& rigamodificata = sheet.row(sheet.items()-1); //se è la prima riga che inserisco, cerco l'ultimo CODPER per la coppia... //...cliente - contratto sulla tabella, e lo incremento di 1 if (sheet.items()==1) { TISAM_recordset psosp("USE LVPERISOSP\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); psosp.set_var("#CODCF",codcli); psosp.set_var("#CODCONT",codcont); psosp.move_last(); codper = psosp.get("LVPERISOSP_CODPER").as_int()+1; } else //se esistono già altre righe, prendo il codice dalla riga precedente, e lo incremento di 1 { TToken_string& rigaprecedente = sheet.row(sheet.items()-2); codper = rigaprecedente.get_int(sheet.cid2index(F_S_CODPER))+1; } rigamodificata.add(codper,sheet.cid2index(F_S_CODPER)); //metto in codper nella posizione giusta sulla TToken_string return; } bool TPass_plan_contr_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_PASPLAN: switch (e) { case se_notify_add: proponi_orario(); default: break; } case F_PERSOSP: switch (e) { case se_notify_add: //se si aggiunge una riga nuova allo sheet nuovo_persosp(); break; default: break; } default: break; } return true; } TPass_plan_contr_mask::TPass_plan_contr_mask() :TAutomask("lv0500a") {} //////////////////// // Applicazione // //////////////////// class TPass_plan_contr : public TRelation_application { TPass_plan_contr_mask* _mask; TRelation* _rel; long _codcli; long _codcont; private: void fill_pasplan(const long codcli, const long codcont); //riempie i passaggi planning per contratto void fill_persosp(const long codcli, const long codcont); //riempie i periodi di sospensione int find_pass(TSheet_field& s,const int ggcons, const int coditi) const; //controlla se esiste una passaggio int find_sosp(TSheet_field& s,const int codper) const; //controlla se esiste un periodo di sospensione int write_pasplan(TSheet_field& pasplan, const long codcli, const long codcont); //scrive i passaggi planning per contratto int write_persosp(TSheet_field& persosp, const long codcli, const long codcont); //scrive i periodi di sospensione int remove_pasplan(TSheet_field& pasplan, const long codcli, const long codcont); //cancella i passaggi planning per contratto int remove_persosp(TSheet_field& persosp, const long codcli, const long codcont); //cancella i periodi di sospensionE protected: virtual void init_query_mode(TMask& m); virtual bool user_create(); virtual bool user_destroy(); virtual int read(TMask& m); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual bool remove(); virtual TMask* get_mask(int mode) { return _mask; } virtual bool changing_mask(int mode) { return false; } public: virtual TRelation* get_relation() const {return (TRelation*)_rel;} }; /////////////////////////////////////////// //// FUNZIONI PER READ //// /////////////////////////////////////////// //FILL_PASPLAN: questa funzione riempie lo sheet dei passaggi contratto per planning, se ne sono stati già inseriti... //...per la coppia cliente - contratto selezionata, se no propone un insieme di righe vuote,... //...una per ogni giorno della settimana void TPass_plan_contr::fill_pasplan(const long codcli,const long codcont) { //preparo il recordset su LVPASPLAN TISAM_recordset pplan("USE LVPASPLAN\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); pplan.set_var("#CODCF",codcli); pplan.set_var("#CODCONT",codcont); TProgind pi(pplan.items(), TR("Elaborazione dati passaggi planning per contratto in corso..."), true, true); TSheet_field& sheet = _mask->sfield(F_PASPLAN); TMask& sheetmask = sheet.sheet_mask(); TRelation& rel = *pplan.cursor()->relation(); //accesso al file delle righe sheet.destroy(); if (pplan.items()>0) { for (bool ok = pplan.move_first(); ok; ok = pplan.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) row.add(fr->read(rel),sheet.cid2index(f->dlg())); //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 } } else { //questo ciclo crea le sette righe vuote TString ora = "00:00"; for (int i = 1; i<=7; ++i) { TToken_string& row = sheet.row(-1); //crea una nuova riga dello sheet row.add(i,sheet.cid2index(F_S_GGCONS)); //aggiunge al posto giusto il numero del giorno della settimana row.add(ora,sheet.cid2index(F_S_ORA)); //propone l'ora di arrivo in automatico sheet.check_row(sheet.items()-1); //forza la maschera a fare la decodifica dei codici } } sheet.force_update(); //forza l'update dello sheet, in modo da rendere visibili i cambiamneti fatti return; } //FILL_PERSOSP: questa funzione riempie lo sheet dei periodi di sospensione, recuperando eventualmente i dati già inseriti... //...nella tabella dei periodi di sospensione (LVPERISOSP) per la coppia cliente - contratto selezionata void TPass_plan_contr::fill_persosp(const long codcli,const long codcont) { //preparo il recordset su LVPERISOSP TISAM_recordset psosp("USE LVPERISOSP\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); psosp.set_var("#CODCF",codcli); psosp.set_var("#CODCONT",codcont); TProgind pi(psosp.items(), TR("Elaborazione dati periodi di sospensione in corso..."), true, true); TSheet_field& sheet = _mask->sfield(F_PERSOSP); TMask& sheetmask = sheet.sheet_mask(); TRelation& rel = *psosp.cursor()->relation(); //accesso al file delle righe sheet.destroy(); for (bool ok = psosp.move_first(); ok; ok = psosp.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) row.add(fr->read(rel),sheet.cid2index(f->dlg())); //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(); //forza l'update dello sheet, in modo da rendere visibili i cambiamneti fatti return; } //READ: ridefinizione metodo read() delle TRelation int TPass_plan_contr::read(TMask& m) { //i due campi di testata DEVONO essere pieni tutte e due if (_mask->field(F_CODCF).empty() || _mask->field(F_CODCONT).empty()) return !NOERR; //recupero i dati della testata const long codcli = _mask->get_long(F_CODCF); const long codcont = _mask->get_long(F_CODCONT); fill_pasplan(codcli,codcont); fill_persosp(codcli,codcont); return NOERR; } /////////////////////////////////////////// //// FUNZIONI PER WRITE E REWRITE //// /////////////////////////////////////////// //FIND_PASS: questa funziona controlla se una coppia giorno di consegna - itinerario che esiste sul file, //esiste ancora sullo sheet (se non esiste è stato cancellato) int TPass_plan_contr::find_pass(TSheet_field& s,const int ggcons, const int coditi) const { int r=-1; //per ogni riga dello sheet, leggi giorno di consegna e itinerario, //e se esiste interrompi restituendo un valore positivo, //se no arriva fino in fondo e resituisci -1 for (r=s.items()-1;r>=0;r--) { const int gc = s.row(r).get_int(s.cid2index(F_S_GGCONS)); const int ci = s.row(r).get_int(s.cid2index(F_S_ITI)); if (ggcons == gc && coditi == ci) break; } return r; } //FIND_SOSP: questa funziona controlla se un periodo di sospensione che esiste sul file, //esiste ancora sullo sheet (se non esiste è stato cancellato) int TPass_plan_contr::find_sosp(TSheet_field& s,const int codper) const { int r=-1; //per ogni riga dello sheet, leggi codice del periodo di sospensione, //e se esiste interrompi restituendo un valore positivo, //se no arriva fino in fondo e resituisci -1 for (r=s.items()-1;r>=0;r--) { const int cp = s.row(r).get_int(s.cid2index(F_S_CODPER)); if (codper == cp) break; } return r; } //WRITE_PASPLAN: questa funzione scrive i dati sul file 164 (LVPASPLAN) int TPass_plan_contr::write_pasplan(TSheet_field& pasplan, const long codcli, const long codcont) { //instanzio un TISAM_recordset TISAM_recordset pplan("USE LVPASPLAN\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); pplan.set_var("#CODCF",codcli); pplan.set_var("#CODCONT",codcont); int err = NOERR; //instanzio un TLocalisamfile TLocalisamfile& file = pplan.cursor()->file(); //per ogni riga del recordset for (bool ok=pplan.move_first(); ok; ok=pplan.move_next()) { //leggo il giorno di consegna e il codice itinerario const int ggcons = pplan.get(LVPASPLAN_GGCONS).as_int(); const int coditi = pplan.get(LVPASPLAN_CODITI).as_int(); //tutte le righe del TISAM_recordset che NON SONO nel TRecord_array vanno eliminate dal file if (find_pass(pasplan,ggcons,coditi) < 0) file.remove(); } //Maschera di sheet TMask& msk = pasplan.sheet_mask(); //per ogni riga dello sheet FOR_EACH_SHEET_ROW(pasplan,r,row) { file.zero(); //putto nel file codcli e codcont (sempre gli stessi) file.put(LVPASPLAN_CODCF,codcli); file.put(LVPASPLAN_CODCONT,codcont); //per ogno campo della maschera di sheet FOR_EACH_MASK_FIELD(msk,i,f) { //prendo il FIELD a cui si riferiscono const TFieldref*fr = f->field(); //se efftivamente il campo ha un field di riferimento if (fr!= NULL) { const int pos=pasplan.cid2index(f->dlg()); //salvo la sua posizione all'inetrno dello sheet fr->write(row->get(pos),file.curr()); //scrivo il valore che sto leggendo nel record corrente del file } } //setto le informazioni di creazione e/o aggiornamento del record /*if (file.curr().get(LVPERISOSP_UTCREAZ).empty()) lv_set_creation_info(file.curr()); else lv_set_update_info(file.curr());*/ err = file.rewrite_write(); //o faccio la rewrite, o faccio la write } return err; } //WRITE_PERSOSP: questa funzione scrive i dati sul file 165 (LVPERISOSP) int TPass_plan_contr::write_persosp(TSheet_field& persosp, const long codcli, const long codcont) { if (_mask->field(F_CODCF).empty() || _mask->field(F_CODCONT).empty()) return !NOERR; //instanzio un TISAM_recordset TISAM_recordset psosp("USE LVPERISOSP\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); psosp.set_var("#CODCF",codcli); psosp.set_var("#CODCONT",codcont); int err = NOERR; //instanzio un TLocalisamfile TLocalisamfile& file = psosp.cursor()->file(); //per ogni riga del recordset for (bool ok=psosp.move_first(); ok; ok=psosp.move_next()) { //leggo il codice del periodo di sospensione const int sosp = psosp.get(LVPERISOSP_CODPER).as_int(); //tutte le righe del TISAM_recordset che NON SONO nel TRecord_array vanno eliminate dal file if (find_sosp(persosp,sosp) < 0) file.remove(); } //creo un TRectype TRectype& rec = file.curr(); //Maschera di sheet TMask& msk = persosp.sheet_mask(); //per ogni riga dello sheet FOR_EACH_SHEET_ROW(persosp,r,row) { //azzero il record rec.zero(); //putto nel record codcli e codcont (sempre gli stessi) rec.put(LVPERISOSP_CODCF,codcli); rec.put(LVPERISOSP_CODCONT,codcont); //per ogni campo della mashera di sheet FOR_EACH_MASK_FIELD(msk,i,f) { //prendo il FIELD a cui si riferiscono const TFieldref* fr = f->field(); //se efftivamente il campo ha un field di riferimento if (fr!= NULL) { const char* field = fr->name(); //salvo il nome del campo const int pos = persosp.cid2index(f->dlg()); //salvo la sua posizione all'inetrno dello sheet rec.put(field,row->get(pos)); //putto il suo valore nel record che sto costruendo } } //setto le informazioni di creazione e/o aggiornamento del record if (rec.get(LVPERISOSP_UTCREAZ).empty()) lv_set_creation_info(rec); else lv_set_update_info(rec); err = file.rewrite_write(); //o faccio la rewrite, o faccio la write } return err; } //WRITE: ridefinizione metodo write delle TRelation int TPass_plan_contr::write(const TMask& m) { if (_mask->field(F_CODCF).empty() || _mask->field(F_CODCONT).empty()) return !NOERR; const long codcli = _mask->get_long(F_CODCF); const long codcont = _mask->get_long(F_CODCONT); int err_1; int err_2; //variabili per lavorare sugli sheet TSheet_field& pasplan = _mask->sfield(F_PASPLAN); TSheet_field& persosp = _mask->sfield(F_PERSOSP); if (pasplan.items() > 0) err_1 = write_pasplan(pasplan,codcli,codcont); if (persosp.items() > 0) err_2 = write_persosp(persosp,codcli,codcont); return err_1 && err_2; } //ridefinizione metodo rewrite delle TRelation int TPass_plan_contr::rewrite(const TMask& m) { if (_mask->field(F_CODCF).empty() || _mask->field(F_CODCONT).empty()) return !NOERR; const long codcli = _mask->get_long(F_CODCF); const long codcont = _mask->get_long(F_CODCONT); int err_1; int err_2; //variabili per lavorare sugli sheet TSheet_field& pasplan = _mask->sfield(F_PASPLAN); TSheet_field& persosp = _mask->sfield(F_PERSOSP); if (pasplan.items() > 0) err_1 = write_pasplan(pasplan,codcli,codcont); if (persosp.items() > 0) err_2 = write_persosp(persosp,codcli,codcont); return err_1 && err_2; } /////////////////////////////////////////// //// FUNZIONI PER REMOVE //// /////////////////////////////////////////// //REMOVE_PASPLAN: elimina tutte le righe dei passaggi per la coppia cliente - contratto selezionata int TPass_plan_contr::remove_pasplan(TSheet_field& pasplan, const long codcli, const long codcont) { //instanzio un TISAM_recordset TISAM_recordset pplan("USE LVPASPLAN\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); pplan.set_var("#CODCF", codcli); pplan.set_var("#CODCONT", codcont); int tmp = pplan.items(); int err = NOERR; //instanzio un TLocalisamfile TLocalisamfile& file = pplan.cursor()->file(); //per ogni riga del recordset for (bool ok=pplan.move_first(); ok; ok=pplan.move_next()) { err = file.remove(); } return err; } //REMOVE_PERSOSP: elimina tutte le righe dei periodi di sospensione per la coppia cliente - contratto selezionata int TPass_plan_contr::remove_persosp(TSheet_field& persosp, const long codcli, const long codcont) { //instanzio un TISAM_recordset TISAM_recordset psosp("USE LVPERISOSP\n FROM CODCF=#CODCF CODCONT=#CODCONT\nTO CODCF=#CODCF CODCONT=#CODCONT"); psosp.set_var("#CODCF",codcli); psosp.set_var("#CODCONT",codcont); int err = NOERR; //instanzio un TLocalisamfile TLocalisamfile& file = psosp.cursor()->file(); //per ogni riga del recordset for (bool ok=psosp.move_first(); ok; ok=psosp.move_next()) { err = file.remove(); } return err; } //REMOVE: ridefinizione del metodo remove delle TRelation bool TPass_plan_contr::remove() { if (_mask->field(F_CODCF).empty() || _mask->field(F_CODCONT).empty()) return !NOERR; //valori recuperati dalla testata const long codcli = _mask->get_long(F_CODCF); const long codcont = _mask->get_long(F_CODCONT); //variabili per lavorare sugli sheet TSheet_field& pasplan = _mask->sfield(F_PASPLAN); TSheet_field& persosp = _mask->sfield(F_PERSOSP); int err_1 = remove_pasplan(pasplan,codcli,codcont); int err_2 = remove_persosp(persosp,codcli,codcont); return err_1 && err_2; } /////////////////////////////////////////// //// METODI PRIVATI //// /////////////////////////////////////////// //questa funzione forza i campi F_CODCF e F_CODCONT quando... //...vengono passati come parametri al programma void TPass_plan_contr::init_query_mode(TMask& m) { if (_codcli > 0) { m.set(F_CODCF,_codcli); m.set(F_CODCONT,_codcont,0x2); if (find(0)) modify_mode(); } } //costruttore bool TPass_plan_contr::user_create() { _rel = new TRelation(LF_LVCONDV); _mask = new TPass_plan_contr_mask; //se gli sono stati passati più parametri, allora setto le variabili globali _codcli e _codcont... //...con i parametri desiderati, se no li setto a zero if (argc() > 2) { _codcli = atol(argv(2)); _codcont = atol(argv(3)); } else { _codcli = 0; _codcont = 0; } return true; } //distruttore bool TPass_plan_contr::user_destroy() { delete _mask; return true; } int lv0500(int argc, char* argv[]) { TPass_plan_contr a; a.run(argc, argv, TR("Archivi Lavanderie")); return 0; }