#include #include #include #include #include #include #include #include #include "at0.h" #include "atlib.h" // nomi campi maschera #include "at0400a.h" // nomi dei campi #include "soggetti.h" #include "sezioni.h" #include "convoc.h" #include "rconvoc.h" #define ALIAS_CTD -700 #define ALIAS_TCS -200 #define IDON_SI "SI" #define IDON_AF "AF" class TGestioneConvocazioni: public TRelation_application { static bool filter_func_convoc(const TRelation* rel); TMask* _msk; TRelation* _rel; TRelation* _tmprel; TRelation* _relsog; TCursor* _cur; // cursore per selezione soggetti TIsamtempfile* _tmpconv; TIsamtempfile* _tmprconv; TLocalisamfile* _rconvoc; TLocalisamfile* _soggetti; TLocalisamfile* _sezioni; TRecord_array* _sconvocati; // sheet convocati long _lastcod; // progressivo convocazione da assegnare long _numero; // numero convocazione TDate _data; // data convocazione TString16 _punto; // punto di prelievo TString16 _tipo; // tipo donazione TString16 _codsez; // codice sezione convocata TString16 _codsot; // codice sottogruppo TDate _dataini; bool _tutti, _ritarda; int _maxrit; bool _inserimento; protected: virtual bool user_create(); virtual bool user_destroy(); virtual const char* get_next_key(); virtual int scrivi(const TMask& m, bool ri); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual int read(TMask& m); virtual bool remove(); virtual bool changing_mask(int mode) { return FALSE; } virtual TMask* get_mask( int mode = 0) { return _msk; } virtual TRelation* get_relation() const { return _rel; } virtual void init_query_insert_mode(TMask& m); virtual void init_query_mode(TMask& m) { _inserimento = FALSE; init_query_insert_mode(m);}; virtual void init_modify_mode(TMask& m); virtual void init_insert_mode(TMask& m) { _inserimento = TRUE; init_modify_mode(m); } static bool nome_handler(TMask_field& f, KEY k); static bool codice_handler(TMask_field& f, KEY k); static bool convocati_notify(TSheet_field& s, int r, KEY k); static bool esegui_handler(TMask_field& f, KEY k); static bool data_handler(TMask_field&f, KEY k); static bool dataini_handler(TMask_field&f, KEY k); static bool sezione_handler(TMask_field&f, KEY k); public: virtual void print(); TGestioneConvocazioni() {} }; HIDDEN inline TGestioneConvocazioni& app() { return (TGestioneConvocazioni&) main_app(); } void TGestioneConvocazioni::init_query_insert_mode(TMask& m) { disable_menu_item(M_FILE_NEW); m.hide(-1); m.show(-2); m.enable(-3); } void TGestioneConvocazioni::init_modify_mode(TMask& m) { m.show(-1); m.hide(-2); if (app()._inserimento) m.enable(-3); else m.disable(-3); } bool TGestioneConvocazioni::filter_func_convoc(const TRelation* rel) { bool filtrato = FALSE; TRectype& sog = rel->curr(); const long codice = sog.get_long(SOG_CODICE); const TString16 cat = sog.get(SOG_CATDON); const char stato = modstato_tcs(sog.get(SOG_STATO)); const TString16 escluso = sog.get(SOG_ESCLUSO); const TString16 modconv = sog.get(SOG_MODCONV); const bool dimesso = rel->lfile(ALIAS_CTD).get_bool("B0"); filtrato = (cat.not_empty() && (stato == 'I' || stato == 'F') && !dimesso && escluso.empty()); if (filtrato) filtrato = ((modconv.empty()) || (modconv == "PO") || (modconv == "IN")); if (filtrato) { filtrato = FALSE; const TString16 punto = sog.get(SOG_PUNTORACC); const TString16 codsez = sog.get(SOG_CODSEZ); const TString16 codsot = sog.get(SOG_CODSOT); if (app()._codsez.not_empty()) { filtrato = (codsez == app()._codsez); if ((filtrato) && (app()._codsot.not_empty())) filtrato = (codsot == app()._codsot); if (filtrato) filtrato = ((punto == app()._punto) || punto.empty()); } else filtrato = (punto == app()._punto); if (app()._tutti && !filtrato) filtrato = (punto == app()._punto); // filtro per data prossima donazione //const TDate dataprossi = sog.get(SOG_DATAPROSSI); //filtrato = (dataprossi.ok()) && (dataprossi <= data) && filtrato; // filtro per intervallo tra cartoline/solleciti/ritardatari if (filtrato) { filtrato = FALSE; const TDate data = app()._data; //TDate data = app()._dataini; prima era cosi' const int numconv = sog.get_int(SOG_NUMCONV); const TDate dataultconv = sog.get(SOG_DATACONV); const TDate dataultsol = sog.get(SOG_DATAULTSOL); TRectype& sez = rel->curr(LF_SEZIONI); const int giocarsol = sez.get_int(SEZ_GIOCARSOL); const int giosolsol = sez.get_int(SEZ_GIOSOLSOL); const int gioultsol = sez.get_int(SEZ_GIOULTSOL); const int giorit = sez.get_int(SEZ_GIOPERRIT); const int numsol = sez.get_int(SEZ_NUMMAXSOL); if (numconv == 0) filtrato = TRUE; else if ((numconv == 1) && (data-dataultconv>=giocarsol)) filtrato = TRUE; else if ((numconv >= 2 && numconv <= numsol-1) && (data-dataultconv >= giosolsol)) filtrato = TRUE; else if ((numconv == numsol && numsol > 0) && (data-dataultconv >= gioultsol)) filtrato = TRUE; else if ((numconv > numsol && numsol > 0) && (app()._ritarda) && (data-dataultsol<=app()._maxrit) && (data-dataultconv>=giorit)) filtrato = TRUE; } } return filtrato; } bool TGestioneConvocazioni::sezione_handler(TMask_field& f, KEY k) { if (f.to_check(k)) //if (f.to_check(k)) { TMask& m = f.mask(); //if (m.get(F_DATAINI).empty() && (m.mode() == MODE_INS)) if (m.mode() == MODE_INS) { //const TString16 codsez = m.get(F_CODSEZ); //const TString16 codsot = m.get(F_CODSOT); TLocalisamfile sez(LF_SEZIONI); sez.setkey(1); TRectype& recsez = sez.curr(); recsez.zero(); recsez.put(SEZ_CODSEZ, m.get(F_CODSEZ)); recsez.put(SEZ_CODSOT, m.get(F_CODSOT)); if (sez.read() == NOERR) { TDate data = sez.get_date(SEZ_DATAULTCON); ++data; if (data <= m.get_date(F_DATA) && data.ok()) { m.set(F_DATAINI, data); m.check_field(F_DATAINI); } } } } return TRUE; } bool TGestioneConvocazioni::data_handler(TMask_field& f, KEY k) { if (f.to_check(k)) { const TDate data = f.get(); const int giorno = data.wday(); TString16 datagio = ""; switch (giorno) { case 1: datagio = "Lunedi"; break; case 2: datagio = "Martedi"; break; case 3: datagio = "Mercoledi"; break; case 4: datagio = "Giovedi"; break; case 5: datagio = "Venerdi"; break; case 6: datagio = "Sabato"; break; case 7: datagio = "Domenica"; break; } f.mask().set(F_DATAGIO,datagio); } return TRUE; } bool TGestioneConvocazioni::dataini_handler(TMask_field& f, KEY k) { if (f.to_check(k)) { const TDate data = f.get(); if (data > f.mask().get_date(F_DATA)) return f.error_box("ATTENZIONE! La data iniziale non puo' essere superiore alla data finale"); const int giorno = data.wday(); TString16 datagio = ""; switch (giorno) { case 1: datagio = "Lunedi"; break; case 2: datagio = "Martedi"; break; case 3: datagio = "Mercoledi"; break; case 4: datagio = "Giovedi"; break; case 5: datagio = "Venerdi"; break; case 6: datagio = "Sabato"; break; case 7: datagio = "Domenica"; break; } f.mask().set(F_DATAINIGIO,datagio); } return TRUE; } bool TGestioneConvocazioni::esegui_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TMask& m = f.mask(); TCursor* cur = app()._cur; app()._numero = m.get_long(F_NUMERO); app()._data = m.get(F_DATA); app()._punto = m.get(F_PUNTO); //app()._tutti = m.get_bool(F_TUTTI); app()._tutti = TRUE; app()._tipo = m.get(F_TIPO); app()._codsez = m.get(F_CODSEZ); app()._codsot = m.get(F_CODSOT); app()._dataini = m.get(F_DATAINI); if (app()._dataini.empty()) app()._dataini = app()._data; app()._ritarda = m.get_bool(F_RITARDA); app()._maxrit = m.get_int(F_MAXRIT); if (app()._numero == 0 || !app()._data.ok() || app()._punto.empty() || app()._tipo.empty()) return f.error_box("Mancano i dati fondamentali per la convocazione"); // filtro per sezione //TRectype da(LF_SOGGETTI); //if (app()._codsez.not_empty()) // da.put(SOG_CODSEZ, app()._codsez); //if (app()._codsot.not_empty()) // da.put(SOG_CODSOT, app()._codsot); //cur->setregion(da, da); //TString filtro; // filtro per non esclusi e modalita di convocazione //filtro << '(' << SOG_ESCLUSO << " == \"\")"; //filtro << " && (" << SOG_MODCONV << " == \"\" || " << SOG_MODCONV << " == \"PO\" || " << SOG_MODCONV << " == \"IN\")"; // filtro per categoria donatori non vuota e non dimessi // e non escluso e idoneo //filtro.format("(CATDON != \"\") && (%d->B0 == \"\") && (ESCLUSO == \"\") && ((%d->S6 == \"I\" ) || (%d->S6 == \"F\"))",ALIAS_CTD,ALIAS_TCS,ALIAS_TCS); // filtro per punto di prelievo //filtro << " && "; //if (app()._codsez.empty()) // filtro << format("(PUNTORACC == \"%s\")",(const char*)app()._punto); //else // filtro << "(PUNTORACC == \"\")"; // filtro per data donazione non vuota // e <= data inizio convocazione // per ora subito SI // lo facciamo con la set_filterfunction //cur->setfilter((const char*) filtro, TRUE); const TDate data = app()._data; const TDate dataini = app()._dataini; TDate datalimite = dataini; datalimite.set_year(datalimite.year()-2); // filtro per data prossima donazione TRectype da(LF_SOGGETTI); TRectype a(LF_SOGGETTI); da.put(SOG_DATAPROSSI,datalimite); a.put(SOG_DATAPROSSI,data); cur->setregion(da, a); cur->set_filterfunction(filter_func_convoc, TRUE); TSheet_field& s = (TSheet_field&)m.field(F_CONVOCATI); s.destroy(); TRectype& rec = cur->curr(); TRectype& sez = cur->curr(LF_SEZIONI); int nconv=0; int nsoll=0; int nrit=0; TDate datasog = data; const int giorni = (int)(data-dataini); // giorni su cui suddividere la chiamata -1 const int dim = giorni+1; int* numperdata = new int[dim]; int quanti = ((int)(cur->items())/(giorni+1))+1; // quanti donatori per giorno if (quanti < 1) quanti = 1; for (int i=0; iitems(); int r=0; TProgind prg (last, "Elaborazione in corso... Prego attendere", FALSE, TRUE, 30); for ( *cur=0; cur->pos() < last; ++(*cur) ) { prg.addstatus(1); TDate datarif(NULLDATE); const int numconv = rec.get_int(SOG_NUMCONV); const TDate dataultconv = rec.get(SOG_DATACONV); const TDate dataultsol = rec.get(SOG_DATAULTSOL); const TDate dataprossi = rec.get(SOG_DATAPROSSI); const int giocarsol = sez.get_int(SEZ_GIOCARSOL); const int giosolsol = sez.get_int(SEZ_GIOSOLSOL); const int gioultsol = sez.get_int(SEZ_GIOULTSOL); const int giorit = sez.get_int(SEZ_GIOPERRIT); const int numsol = sez.get_int(SEZ_NUMMAXSOL); char chiamata = ' '; if (numconv == 0) { chiamata = 'C'; datarif = dataprossi; } else { if ((numconv == 1) && (data-dataultconv>=giocarsol)) { chiamata = 'S'; datarif = dataultconv+(long)giocarsol; } else { if ((numconv >= 2 && numconv <= numsol-1) && (data-dataultconv >= giosolsol)) { chiamata = 'S'; datarif = dataultconv+(long)giosolsol; } else { if ((numconv == numsol && numsol > 0) && (data-dataultconv >= gioultsol)) { chiamata = 'S'; datarif = dataultconv+(long)gioultsol; } else { if ((numconv > numsol && numsol > 0) && (app()._ritarda) && (data-dataultsol<=app()._maxrit) && (data-dataultconv>=giorit)) { chiamata = 'R'; datarif = dataultconv+(long)giorit; } } } } } switch (chiamata) { case 'C': nconv++; break; case 'S': nsoll++; break; case 'R': nrit++; break; } if (giorni > 0) { datasog = NULLDATE; int partenza; if (datarif <= dataini) partenza = 0; else partenza = (int)(datarif-dataini); for (int r=partenza;r<=giorni;r++) { if ((numperdata[r]add(LF_RCONVOC, "CODICE==CODICE"); _msk = new TMask("at0400a"); _rel = new TRelation(LF_CONVOC); _relsog = new TRelation(LF_SOGGETTI); _relsog->add("CTD", "CODTAB==CATDON",1,0,-ALIAS_CTD); _relsog->add("TCS", "CODTAB==STATO",1,0,-ALIAS_TCS); _relsog->add(LF_SEZIONI, "CODSEZ==CODSEZ|CODSOT==CODSOT"); // ordinamento per data prossima donazione _cur = new TCursor(_relsog, "", 5); _rconvoc = new TLocalisamfile(LF_RCONVOC); _soggetti = new TLocalisamfile(LF_SOGGETTI); _sconvocati = new TRecord_array(LF_RCONVOC,RCV_PROGCONV); _msk->set_handler(F_ESEGUI,esegui_handler); _msk->set_handler(F_DATA,data_handler); _msk->set_handler(F_DATAINI,dataini_handler); _msk->set_handler(F_CODSEZ,sezione_handler); _msk->set_handler(F_CODSOT,sezione_handler); TSheet_field& sc = (TSheet_field&)_msk->field(F_CONVOCATI); sc.set_notify(convocati_notify); sc.sheet_mask().set_handler(F_S_NOME,nome_handler); sc.sheet_mask().set_handler(F_S_CODICE,codice_handler); _rel->lfile().last(); _lastcod = _rel->lfile().get_long(COV_NUMERO); enable_menu_item(M_FILE_PRINT); return TRUE; } bool TGestioneConvocazioni::user_destroy() { delete _sconvocati; delete _soggetti; delete _rconvoc; delete _cur; delete _relsog; delete _rel; delete _msk; delete _tmprel; delete _tmprconv; delete _tmpconv; return TRUE; } const char* TGestioneConvocazioni::get_next_key() { // autonumerazione progressiva delle convocazioni _rel->lfile().last(); _lastcod = _rel->lfile().get_long(COV_NUMERO); return format("%d|%ld", F_NUMERO, _lastcod+1 ); } bool TGestioneConvocazioni::remove() { // cancella convocati // cancella testata convocazione bool ok = TRUE; // cancella convocati // prima cancella dall'archivio soggetti la data ultima convocazione TLocalisamfile soggetti(LF_SOGGETTI); soggetti.setkey(1); TLocalisamfile rconvoc(LF_RCONVOC); rconvoc.setkey(3); for (int r=1; r<=_sconvocati->rows(); r++) { const TRectype& riga = _sconvocati->row(r); const long codice = riga.get_long(RCV_CODICE); const TDate dataconv = riga.get_date(RCV_DATACONV); soggetti.put(SOG_CODICE,codice); if (soggetti.read() == NOERR) { int numconv = soggetti.get_int(SOG_NUMCONV); if (numconv > 0) { numconv--; soggetti.put(SOG_NUMCONV,numconv); rconvoc.put(RCV_CODICE,codice); rconvoc.put(RCV_DATACONV,dataconv); if (rconvoc.read() == NOERR) { --rconvoc; const long codprec = rconvoc.get_long(RCV_CODICE); if (codprec == codice) soggetti.put(SOG_DATACONV, rconvoc.get(RCV_DATACONV)); else { soggetti.put(SOG_DATACONV, NULLDATE); soggetti.put(SOG_DATAULTSOL, NULLDATE); } if (numconv == 1) soggetti.put(SOG_DATAULTSOL, NULLDATE); } else { soggetti.put(SOG_DATACONV, NULLDATE); soggetti.put(SOG_DATAULTSOL, NULLDATE); } } else { soggetti.put(SOG_DATACONV, NULLDATE); soggetti.put(SOG_DATAULTSOL, NULLDATE); } soggetti.rewrite(); } } int err = _sconvocati->remove(); if (err == _iseof || err == _isemptyfile) err = NOERR; if (err == NOERR) { TLocalisamfile sez(LF_SEZIONI); sez.setkey(1); sez.zero(); sez.put(SEZ_CODSEZ, app()._codsez); sez.put(SEZ_CODSOT, app()._codsot); if (sez.read() == NOERR) { TLocalisamfile convoc(LF_CONVOC); convoc.setkey(3); convoc.put(COV_CODSEZ, app()._codsez); convoc.put(COV_CODSOT, app()._codsot); convoc.put(COV_DATA, app()._data); convoc.read(); --convoc; TDate dataini = convoc.get_date(COV_DATAINI); TDate datanulla(NULLDATE); while (!convoc.eof() && (dataini == datanulla)) { --convoc; dataini = convoc.get_date(COV_DATAINI); } if ((convoc.get(COV_CODSEZ) == app()._codsez) && (convoc.get(COV_CODSOT) == app()._codsot)) sez.put(SEZ_DATAULTCON, convoc.get_date(COV_DATA)); else sez.put(SEZ_DATAULTCON,NULLDATE); sez.rewrite(); } } // cancella la testata if (err == NOERR) ok = TRelation_application::remove(); return (ok && err == NOERR); } int TGestioneConvocazioni::read(TMask& m) { int err = TRelation_application::read(m); if (err == NOERR) { TRectype* key = new TRectype(LF_RCONVOC); key->put(RCV_NUMERO, m.get(F_NUMERO)); err = _sconvocati->read(key); if (err == NOERR) { TLocalisamfile soggetti(LF_SOGGETTI); TSheet_field& s = (TSheet_field&)m.field(F_CONVOCATI); s.destroy(); for (int r=1; r<=_sconvocati->rows(); r++) { TToken_string& row = s.row(r-1); const TRectype& riga = _sconvocati->row(r); const TString& codice = riga.get(RCV_CODICE); row.add(codice); soggetti.put(SOG_CODICE,codice); if (soggetti.read() != NOERR) soggetti.zero(); row.add(soggetti.get(SOG_COGNOME)); row.add(soggetti.get(SOG_NOME)); row.add(riga.get(RCV_DATACONV)); row.add(riga.get(RCV_CHIAMATA)); row.add(riga.get(RCV_STAMPATO)); row.add(riga.get(RCV_ANNULLATO)); row.add(soggetti.get(SOG_DATANASC)); row.add(soggetti.get(SOG_CATDON)); row.add(soggetti.get(SOG_TESSAVIS)); row.add(soggetti.get(SOG_CODSEZ)); row.add(soggetti.get(SOG_CODSOT)); } } else if (err == _iseof || err == _isemptyfile) err = NOERR; } return err; } int TGestioneConvocazioni::write(const TMask& m) { long curcod = m.get_long(F_NUMERO); if (curcod > _lastcod) _lastcod = curcod; _inserimento = FALSE; return TGestioneConvocazioni::scrivi(m, FALSE); } int TGestioneConvocazioni::rewrite(const TMask& m) { return TGestioneConvocazioni::scrivi(m, TRUE); } int TGestioneConvocazioni::scrivi(const TMask& m, bool ri) { // questo trucco è autorizzato dal capo! //TMask& hmask = (TMask&) m; //TDate oggi(TODAY); //hmask.set(F_DATAULTAGG,oggi); //hmask.set(F_UTENULTAGG,user()); int err = ri ? TRelation_application::rewrite(m) : TRelation_application::write(m); if (err == NOERR) { TLocalisamfile sez(LF_SEZIONI); sez.setkey(1); sez.zero(); sez.put(SEZ_CODSEZ, app()._codsez); sez.put(SEZ_CODSOT, app()._codsot); if (sez.read() == NOERR) { sez.put(SEZ_DATAULTCON, app()._data); sez.rewrite(); } TLocalisamfile soggetti(LF_SOGGETTI); _sconvocati->destroy_rows(); TSheet_field& s = (TSheet_field&)m.field(F_CONVOCATI); TRectype* key = new TRectype(LF_RCONVOC); key->put(RCV_NUMERO, m.get(F_NUMERO)); _sconvocati->set_key(key); for (int r=s.items(); r>0; r--) { TToken_string& row = s.row(r-1); TRectype& rec = _sconvocati->row(r,TRUE); const long codice = row.get_long(0); const TDate dataconv = row.get(3); const char chiamata = row.get_char(4); rec.put(RCV_CODICE,codice); rec.put(RCV_DATACONV,dataconv); rec.put(RCV_CHIAMATA,chiamata); rec.put(RCV_STAMPATO,row.get(5)); rec.put(RCV_ANNULLATO,row.get(6)); // aggiornamento archivio soggetti soggetti.put(SOG_CODICE,codice); if (soggetti.read() == NOERR) { if (chiamata == 'S') soggetti.put(SOG_DATAULTSOL,dataconv); if (!(soggetti.get_date(SOG_DATACONV) == dataconv)) { soggetti.put(SOG_DATACONV,dataconv); int numconv = soggetti.get_int(SOG_NUMCONV); soggetti.put(SOG_NUMCONV,numconv+1); } soggetti.rewrite(); } } err = ri ? _sconvocati->rewrite() : _sconvocati->write(); } return err; } bool TGestioneConvocazioni::convocati_notify(TSheet_field& s, int r, KEY k) { bool result = TRUE; switch (k) { case K_CTRL+K_DEL: // avvenuta cancellazione riga { int numconv = s.mask().get_int(F_NUMCONV); s.mask().set(F_NUMCONV,numconv-1); } break; case K_CTRL+K_TAB: // uscita riga { TToken_string& row = s.row(r); const long codsog = row.get_long(0); if (codsog != 0) for (int i=s.items()-1; i>=0; i--) { if (i != r) { TToken_string& row = s.row(i); if (codsog == row.get_long(0)) return s.sheet_mask().field(F_S_CODICE).error_box("Soggetto gia' inserito"); } } else { const char* cognome = row.get(1); if ((cognome != NULL) && (cognome != "\0")) s.sheet_mask().field(F_S_NOME).set_focusdirty(); //s.set_focus_cell(r,2); } } break; case K_CTRL+K_INS: { int numconv = s.mask().get_int(F_NUMCONV); s.mask().set(F_NUMCONV,numconv+1); } break; case K_INS: //result = FALSE; break; } return result; } void TGestioneConvocazioni::print() { TForm elenco("ATCONVOC"); TCursor& cur = *elenco.cursor(); if (_inserimento) { message_box("Convocazione non registrata; non è possibile la stampa"); } else { TLocalisamfile& convoc = cur.file(); const long numero = app()._msk->get_long(F_NUMERO); convoc.put(COV_NUMERO, numero); cur.read(); elenco.print(-1); } } int at0400(int argc, char* argv[]) { TGestioneConvocazioni a; a.run(argc, argv, "Gestione convocazione"); return 0; }