// ve6100.cpp: programma di contabilizzazione documenti // Orgiastica visione... // L'anatra del dubbio dalle labbra di Vermouth. //****************************************************************************** // \\\\\\\\ e * // b \\\\\\\\ b * // \\\\\\\\ e r d l * // \\\\\\\\ * // \\\\\\\\ i V o e h * // L \\\\\\\\ * // \\\\\\\\ b d * // o \\\\\\\\ m a * // +++++++++++++++++++++++++ b t * // ++++++++++++++++++++++++++--------------------------------------------------| // ++++++++++++++++++++++++++--------------------------------------------------| // ++++++++++++++++++++++++ |---------------------------------------| // u //////// u |---------------------------------------| // ' //////// a | /\ /\ | // //////// i | r / \ r / \ | // a //////// \|/ / \ / \ l | // ////////-----------------*---\ a / t \ / a \ /| // //////// /|\ \ / \ / \ / | // d //////// n | \ / \ / \ / | // //////// l d | \/ a \/ l \/ | //-----------------------------------------------------------------------------| // // Scared uh? #include #include #include #include #include #include #include #include "velib04.h" #include "../cg/cgsaldac.h" #include "ve6100a.h" // TContabilizzazione_app // Applicazione di contabilizzazione documenti class TContabilizzazione_app : public TApplication { TString16 _cod_el; // codice elaborazione immesso TDate _data_reg; // data di registrazione immessa TDate _data_ini; // data di inizio intervallo TDate _data_fine; // data di fine intervallo bool _auto_data; // se TRUE prende in automatico la data di registrazione dalla data documento TMask *_msk; // maschera di selezione dati TArray_sheet *_num_sheet; // Array sheet selezionabile dei codici numerazione TString_array _tipi_doc; // Array di stringhe contenente i tipi documenti da elaborare virtual const char * extra_modules() const {return "dt";} protected: // TApplication // Contabilizza i documenti void contabilize(); // Le 4 seguenti non hanno bisogno di commenti virtual bool menu(MENU_TAG mt); virtual bool create(); virtual bool destroy(); virtual void on_config_change(); // Handler del codice elaborazione differita static bool handle_cod_eld(TMask_field& f, KEY k); // Handler dell'intervallo di date static bool handle_data_range(TMask_field& f, KEY k); // Handler della data di registrazione static bool handle_data_reg(TMask_field& f, KEY k); // Handler del pulsante di selezione codici numerazione static bool handle_select(TMask_field& f, KEY k); // Ritorna il TArray_sheet contenente le selezioni sui codici numerazione // Costruisce lo sheet dei codici numerazione void build_num_sheet(); TArray_sheet* get_num_sheet() const { return _num_sheet; } // Coontrolla se lo stato ed il tipo del documento sono validi e rispettano la selezione bool doc_tipo_stato_ok(const TRectype& doc); public: TContabilizzazione_app() {_msk = NULL; _num_sheet = NULL;} virtual ~TContabilizzazione_app() { } }; inline TContabilizzazione_app& app() { return (TContabilizzazione_app&) main_app(); } bool TContabilizzazione_app::handle_data_range(TMask_field& f, KEY k) { if (k==K_ENTER && f.dirty()) { TMask& m = f.mask(); if (m.get_bool(F_DATA_AUTO)) return TRUE; // Skip controls if data is automatic TDate da(m.get_date(F_DATA_INI)); TDate a(m.get_date(F_DATA_FIN)); m.field(F_DATA_REG).set_dirty(); if ((a - da) > 15) { f.error_box(TR("L'intervallo tra le date non puo' eccedere i 15 giorni.")); return FALSE; } if (f.dlg() == F_DATA_FIN) m.set(F_DATA_REG,f.get()); } if (f.focusdirty()) { TMask& m = f.mask(); if (!m.get_bool(F_DATA_AUTO) && f.dlg() == F_DATA_FIN) m.set(F_DATA_REG,f.get()); } return TRUE; } bool TContabilizzazione_app::handle_data_reg(TMask_field& f, KEY k) { if (k==K_ENTER && f.dirty()) { TMask& m = f.mask(); TDate data_reg(f.get()); if (data_reg == botime) return TRUE; TDate da(m.get_date(F_DATA_INI)); if ((data_reg - da) > 15) { f.error_box(TR("L'intervallo tra la data di registrazione e la data di inizio non puo' eccedere i 15 giorni.")); return FALSE; } if (data_reg < da) { f.error_box(TR("La data di registrazione non puo' essere minore della data di inizio.")); return FALSE; } } return TRUE; } bool TContabilizzazione_app::handle_cod_eld(TMask_field& f, KEY k) { if (f.to_check(k) && k == K_TAB) // se e' cambiato ricostruisce anche lo sheet dei codici numerazione { app()._cod_el = f.get(); // aggiorna il codice elaborazione per la build_num_sheet() f.mask().disable(DLG_OK); app().build_num_sheet(); } return TRUE; } bool TContabilizzazione_app::handle_select(TMask_field& f, KEY k) { if (k == K_SPACE) { TMask& m = f.mask(); TArray_sheet* s = app().get_num_sheet(); if (s->run()) { if (s->checked() != 0) // Hai selezionato qualcosa ? m.enable(DLG_OK); // allora abilita il pulsante di conferma else m.disable(DLG_OK); } } return TRUE; } void TContabilizzazione_app::build_num_sheet() { _num_sheet->destroy(); _tipi_doc.destroy(); TTable num("%NUM"); TString s1,s2,s3; TContabilizzazione* cont = new TContabilizzazione(_cod_el); if (!cont->empty()) { TToken_string t; TString16 tipo; for (int i=0;itipo_iniziale(i); if (tipo.not_empty()) { t = tipo; t.add(cont->stato_iniziale(i)); // Stato iniziale _tipi_doc.add(t); // Aggiunge questo tipo documento alla lista } } long pos=0l; for (num.first();num.good();num.next(),pos++) // scorre tutte le numerazioni possibili { TToken_string t,z; t.add(" "); t.add(num.get("CODTAB")); t.add(num.get("S0")); _num_sheet->add(t); s2 = num.get("S2"); // reperisce i tipi documento validi per questa numerazione for (int x = 0; x <= s2.len(); x += 4) z.add(s2.mid(x,4)); bool found = FALSE; for (int i = _tipi_doc.last(); !found && i >= 0; i--) found |= (s2.find(((TToken_string &)_tipi_doc[i]).get(0)) >= 0); if (found) _num_sheet->enable_row(pos); else _num_sheet->disable_row(pos); } } delete cont; } bool TContabilizzazione_app::doc_tipo_stato_ok(const TRectype& doc) // Verifica che il tipo documento corrente esista tra i tipi previsti dalla elaborazione // differita selezionata { bool found = FALSE; const TString16 tipo = doc.get(DOC_TIPODOC); const char stato = doc.get_char(DOC_STATO); const int items = _tipi_doc.items(); for (int i=0;iset_handler(F_CODICE_ELAB,handle_cod_eld); _msk->set_handler(F_DATA_INI,handle_data_range); _msk->set_handler(F_DATA_FIN,handle_data_range); //_msk->set_handler(F_DATA_REG,handle_data_reg); _msk->set_handler(DLG_USER,handle_select); _num_sheet = new TArray_sheet(-1,-1,-4,-4,"Codici numerazione", "@1|Cod. numerazione|Descrizione@50"); dispatch_e_menu(BAR_ITEM_ID(1)); return TRUE; } bool TContabilizzazione_app::destroy() { if (_msk) delete _msk; if (_num_sheet) delete _num_sheet; return TApplication::destroy(); } bool TContabilizzazione_app::menu(MENU_TAG mt) { while (_msk->run() == K_ENTER) { _cod_el = _msk->get(F_CODICE_ELAB); _data_ini = _msk->get_date(F_DATA_INI); _data_fine = _msk->get_date(F_DATA_FIN); _data_reg = _msk->get_date(F_DATA_REG); _auto_data = _msk->get_bool(F_DATA_AUTO); contabilize(); } return FALSE; } void TContabilizzazione_app::contabilize() { TRelation doc_rel(LF_DOC); TRectype da(LF_DOC); TRectype a(LF_DOC); const long items = _num_sheet->items(); int year_from = _data_ini.year(); int year_to = _data_fine.year(); TString16 codnum; TString msg,filt_expr; TToken_string nums; TContabilizzazione cont(_cod_el); // Compone la lista dei documenti da elaborare cont.set_auto(_auto_data); // Setta il flag per il settaggio automatico della data di registrazione del movimento for (long i=0L; ichecked(i)) // Costruisce una espressione sul codice numerazione: "CODNUM="x0" || CODNUM="x1" || ..." { codnum = _num_sheet->row(i).get(1); filt_expr << "(CODNUM=\""; filt_expr << codnum << "\")||"; nums.add(codnum); } } filt_expr.rtrim(2); da.put(DOC_DATADOC,_data_ini); da.put(DOC_PROVV,"D"); da.put(DOC_ANNO,year_from); a.put(DOC_DATADOC,_data_fine); a.put(DOC_PROVV,"D"); a.put(DOC_ANNO,year_to); // Se ho una sola numerazione ottimizzo la setregion! if (nums.items() == 1) { da.put(DOC_CODNUM, nums); a.put(DOC_CODNUM, nums); filt_expr.cut(0); // Il filtro diventa inutile } // Cursore complessivo con limiti di data (chiave 3). Viene sfruttata l'ottimizzazione // sulla costruzione dei cursori nel caso i campi presenti nell'espressione siano campi // chiave, nel nostro caso CODNUM soddisfa i requisiti. TCursor doc_cur(&doc_rel,filt_expr,3,&da,&a); const TRecnotype cur_items = doc_cur.items(); if (cur_items > 0) { TLista_documenti lista_in,lista_out; doc_cur.freeze(); msg = "Selezione documenti dal "; msg << _data_ini.string() << " al "; msg << _data_fine.string(); TProgind p(cur_items,msg,FALSE,TRUE); const TRectype& cur_rec = doc_cur.curr(); // Scorre tutti i documenti che rientrano nell'intervallo selezionato for (doc_cur = 0; doc_cur.pos() < cur_items; ++doc_cur) { p.addstatus(1); // controlla che il tipo documento e lo stato siano coerenti con la ELD selezionata if (nums.get_pos(cur_rec.get("CODNUM")) >= 0 && doc_tipo_stato_ok(cur_rec)) { TDocumento* doc = new TDocumento; if (doc->read(doc_cur.curr()) == NOERR) // legge il documento lista_in.add(doc); // Viene aggiunto alla lista dei documenti else delete doc; } } cont.elabora(lista_in,lista_out,_data_reg); if (cont.processed_docs() > 0L) message_box(FR("Totale documenti contabilizzati: %ld"), cont.processed_docs()); } else warning_box(TR("Non vi sono documenti da contabilizzare per le numerazioni selezionate.")); xvtil_statbar_set(""); } int ve6100 (int argc, char **argv) { TContabilizzazione_app a; a.run(argc,argv,"Contabilizzazione documenti"); return TRUE; }