#include #include #include #include #include #include #include #include "../ca/movana.h" #include "../ca/calib01.h" #include "../ca/calib02.h" #include "cg2200.h" #include "cg2101.h" #include "cglib01.h" #include "cglib02.h" class TProvvisori_msk : public TAutomask { char _provv; // Tipo provvisori da cancellare TString16 _from_date, _to_date; // Range date da considerare TString16 _from_caus, _to_caus; // Causali movimenti da considerare long _from_numreg, _to_numreg; // Range movimenti da considerare TCursor_sheet* _sheet; TRelation* _rel; TCursor* _cur; bool _update_cursor; static TProvvisori_msk* _msk; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); static bool filter(const TRelation* rel); void update_search(short id, const TString& fil); public: TCursor& update_cursor(bool use_argv = FALSE); TCursor_sheet* get_selection_sheet(); TCursor& get_cursor() { return _cur ? *_cur : update_cursor(); } void notify_update_needed() { _update_cursor = TRUE; } TProvvisori_msk(); ~TProvvisori_msk(); }; TProvvisori_msk* TProvvisori_msk::_msk = NULL; bool TProvvisori_msk::filter(const TRelation* rel) { TProvvisori_msk& a = *_msk; const TRectype& mov = rel->curr(); const char provv = mov.get_char(MOV_PROVVIS); bool ok = (a._provv <= ' ' && provv > ' ') || (a._provv > ' ' && a._provv == provv); if (ok) { const char* caus = mov.get(MOV_CODCAUS); ok = a._from_caus <= caus && (a._to_caus.empty() || a._to_caus >= caus); } if (ok) { const long numreg = mov.get_long(MOV_NUMREG); ok = numreg >= a._from_numreg && (a._to_numreg == 0 || numreg <= a._to_numreg); } return ok; } // Filtra il cursore in base ai campi della maschera o i parametri da linea di comando TCursor& TProvvisori_msk::update_cursor(bool use_argv) { _provv = ' '; _from_date = _to_date = ""; _from_caus = _to_caus = ""; _from_numreg = _to_numreg = 0; if (!use_argv) { _provv = get(F_PROVV)[0]; _from_date = get(F_FROMDATE); _to_date = get(F_TODATE); _from_caus = get(F_FROMCAUS); _to_caus = get(F_TOCAUS); _from_numreg = get_long(F_FROMREG); _to_numreg = get_long(F_TOREG); } else { if (main_app().argc() > 2) _provv = main_app().argv(2)[0]; } if (_rel == NULL) _rel = new TRelation(LF_MOV); if (_cur == NULL) _cur = new TCursor(_rel, "", 2); TRectype from_rec(LF_MOV), to_rec(LF_MOV); if (_from_date.not_empty()) from_rec.put(MOV_DATAREG, _from_date); if (_to_date.not_empty()) to_rec.put(MOV_DATAREG, _to_date); _cur->freeze(FALSE); _cur->set_filterfunction(filter); _cur->setregion(from_rec, to_rec); _cur->items(); _cur->freeze(TRUE); _update_cursor = FALSE; if (_sheet) _sheet->uncheck(-1); // Annulla la selezione corrente return *_cur; } // Ritorma lo sheet con i movimenti selezionati // Se non si seleziona nulla equivale ad aver selezionato tutto e torna NULL // come quando non si fa nessuna selezione // Aggiorna anche il campo F_SELECTED TCursor_sheet* TProvvisori_msk::get_selection_sheet() { if (_sheet && _update_cursor) update_cursor(); // Update cursor and uncheck all selection const long total = get_cursor().items(); // Numero totale di movimenti provvisori long sel_items = total; // Per default li considero tutti selezionati if (_sheet) // Controllo se c'e' selezione parziale sel_items = _sheet->checked(); if (sel_items == 0L || sel_items > total) // Nessuna selezione = tutti selezionati sel_items = total; set(F_SELECTED, sel_items); // Aggiorno campo a video return sel_items < total ? _sheet : NULL; // Ritorno NULL se tutti selezionati } void TProvvisori_msk::update_search(short id, const TString& fil) { TBrowse* b = efield(id).browse(); b->set_filter(fil); b->cursor()->update(); } bool TProvvisori_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_PROVV: if (e == fe_init || e == fe_modify) { TString16 fil = "PROVVIS"; switch (o.get()[0]) { case 'C': fil << "=\"C\""; break; case 'P': fil << "=\"P\""; break; default : fil << "!=\"\""; break; } update_search(F_FROMDATE, fil); update_search(F_TODATE, fil); update_search(F_FROMREG, fil); update_search(F_TOREG, fil); notify_update_needed(); } break; case F_FROMDATE: case F_TODATE: if (e == fe_modify) { notify_update_needed(); } else if (e == fe_close) { // Non è carino lasciare vuote le date se non si seleziona nulla esplicitamente if (get(F_TODATE).empty() && get(F_FROMDATE).empty() && get_long(F_SELECTED) == 0L) return error_box(TR("E' necessario specificare almeno una data")); } break; case DLG_SELECT: if (e == fe_button) { if (_sheet == NULL) // Devo creare sheet di delezione { TBrowse* br = efield(F_FROMREG).browse(); // Copia intestazione dal campo della maschera! TToken_string head = br->head(); head.insert("@1|"); // Aggiunge prima colonna di selezione TToken_string flds = br->items(); flds.insert(" |"); // Aggiunge prima colonna vuota _sheet = new TCursor_sheet(&get_cursor(), flds, TR("Selezione"), head, 0, 1); } if (_update_cursor) // Aggiorna filtri cursore se necessario update_cursor(); _sheet->run(); // Mostra sheet di selezione get_selection_sheet(); // Aggiorna F_SELECTED return FALSE; } break; default: if (e == fe_modify) // Se viene modificato un campo qualsiasi ... notify_update_needed(); // ... ricorda che devi aggiornare il cursore la prossima volta break; } return TRUE; } TProvvisori_msk::TProvvisori_msk() : TAutomask("cg2200a"), _sheet(NULL), _rel(NULL), _cur(NULL), _update_cursor(TRUE) { _msk = this; } TProvvisori_msk::~TProvvisori_msk() { _msk = NULL; if (_sheet != NULL) delete _sheet; if (_cur) delete _cur; if (_rel) delete _rel; } class TProvvisori_app : public TSkeleton_application { TSaldo_agg _saldi; protected: // TApplication virtual bool create(); virtual bool destroy(); virtual void main_loop(); protected: TCursor& create_cursor(TMask* m); public: void inizia_saldi(const TRectype& mov); void aggiungi_saldi(const TRectype& rmov, bool lettura); void aggiorna_saldi(); void aggiorna_analitica(const long numreg); bool confirm_provv(TCursor& cur, TProgind& pi, TCursor_sheet* sheet= NULL); bool delete_provv(TCursor& cur, TProgind& pi, TCursor_sheet* sheet= NULL); void auto_delete(TCursor& cur); TProvvisori_app() {}; virtual ~TProvvisori_app() {} }; inline TProvvisori_app& app() { return (TProvvisori_app&)main_app(); } bool TProvvisori_app::create() { open_files(LF_TAB, LF_MOV, LF_CAUSALI, LF_SALDI, NULL); return TSkeleton_application::create(); } bool TProvvisori_app::destroy() { return TSkeleton_application::destroy(); } void TProvvisori_app::inizia_saldi(const TRectype& r) { CHECK(r.num() == LF_MOV, "Voglio un movimento"); _saldi.reset(); tiposal tsal = normale; const TString4 c = r.get(MOV_CODCAUS); if (c.not_empty()) { const TRectype& cau = cache().get(LF_CAUSALI, c); if (!cau.empty()) { const char movap = cau.get_char(CAU_MOVAP); if (movap == 'A') tsal = apertura; else if (movap == 'C') tsal = chiusura; } } _saldi.set_tipo_saldo(tsal); _saldi.set_anno_es(r.get_int(MOV_ANNOES)); _saldi.set_num_ulmov(r.get_long(MOV_NUMREG)); _saldi.set_data_ulmov(r.get_date(MOV_DATAREG)); } void TProvvisori_app::aggiungi_saldi(const TRectype& r, bool lettura) { CHECK(r.num() == LF_RMOV, "Voglio la riga di un movimento"); TBill conto; conto.get(r); TImporto importo(r.get_char(RMV_SEZIONE), r.get_real(RMV_IMPORTO)); _saldi.set_movprovv(lettura); // In lettura sono tutti provvisori _saldi.aggiorna(conto, importo, !lettura); // In lettura devo sottrarre l'importo } void TProvvisori_app::aggiorna_saldi() { _saldi.registra(); } void TProvvisori_app::aggiorna_analitica(const long numreg) { //cerca un eventuale movimento analitico collegato al contabile provvisorio in via d'estinzione TLocalisamfile movana(LF_MOVANA); movana.setkey(3); movana.put(MOVANA_NUMREGCG, numreg); //se trova il movana da accoppare... if (movana.read() == NOERR) { TAnal_mov movana_to_kill(movana.curr()); movana_to_kill.remove(movana); } } bool TProvvisori_app::confirm_provv(TCursor& cur, TProgind& pi, TCursor_sheet* sheet) { TLocalisamfile& mov = cur.file(LF_MOV); TLocalisamfile rmov(LF_RMOV); if (sheet && sheet->checked() == 0) sheet = NULL; for (cur = 0; cur.pos() < cur.items(); ++cur) { if (sheet && !sheet->checked(cur.pos())) continue; const long numreg = mov.get_long(MOV_NUMREG); inizia_saldi(mov.curr()); int err = cur.lock(); for (int rig = 1; err == NOERR; rig++) { rmov.put(RMV_NUMREG, numreg); rmov.put(RMV_NUMRIG, rig); if (rmov.read(_isequal, _lock) != NOERR) break; aggiungi_saldi(rmov.curr(), TRUE); aggiungi_saldi(rmov.curr(), FALSE); } if (err == NOERR) { mov.zero(MOV_PROVVIS); err = mov.rewrite(); if (err == NOERR) { aggiorna_saldi(); pi.addstatus(1); } } if (err != NOERR) return error_box(FR("Errore nella conferma del movimento %ld"), numreg); } return TRUE; } bool TProvvisori_app::delete_provv(TCursor& cur, TProgind& pi, TCursor_sheet* sheet) { TLocalisamfile& mov = cur.file(LF_MOV); TLocalisamfile rmov(LF_RMOV); TLocalisamfile rmoviva(LF_RMOVIVA); if (sheet && sheet->checked() == 0) sheet = NULL; TString error(256); for (cur = 0; cur.pos() < cur.items(); ++cur) { if (sheet && !sheet->checked(cur.pos())) continue; const long numreg = mov.get_long(MOV_NUMREG); mov.setkey(1); // Isam bug on remove with key != 1 mov.put(MOV_NUMREG, numreg); int err = mov.read(_isequal, _lock); if (err != NOERR) return error_box(FR("Errore %d nel bloccare il record %ld"), err, numreg); inizia_saldi(mov.curr()); int rig; for (rig = 1; err == NOERR; rig++) { rmov.put(RMV_NUMREG, numreg); rmov.put(RMV_NUMRIG, rig); if (rmov.read(_isequal, _lock) != NOERR) break; aggiungi_saldi(rmov.curr(), TRUE); err = rmov.remove(); if (err != NOERR) error.format(FR("riga contabile %d"), rig); } for (rig = 1; err == NOERR; rig++) { rmoviva.put(RMI_NUMREG, numreg); rmoviva.put(RMI_NUMRIG, rig); if (rmoviva.read(_isequal, _lock) != NOERR) break; err = rmov.remove(); if (err != NOERR) error.format(FR("riga IVA %d"), rig); } if (err == NOERR) { err = mov.remove(); if (err != NOERR) error = TR("testata"); } if (err == NOERR) { aggiorna_saldi(); aggiorna_analitica(numreg); //elimina anche il movimento analitico collegato if (!pi.addstatus(1)) return warning_box(TR("Procedura interrotta dall'utente")); } else return error_box(FR("Errore %d nella cancellazione della %s del movimento %ld"), err, (const char*)error, numreg); } return TRUE; } void TProvvisori_app::auto_delete(TCursor& cur) { const long total = cur.items(); TProgind pi(total, TR("Cancellazione movimenti provvisori"), TRUE, TRUE); delete_provv(cur, pi); } void TProvvisori_app::main_loop() { TProvvisori_msk m; if (argc() > 2) { TCursor& cur = m.update_cursor(TRUE); auto_delete(cur); return; } m.reset(); while (TRUE) { KEY key = m.run(); if (key != K_ENTER && key != K_DEL) break; TString16 from_d = m.get(F_FROMDATE); if (key == K_ENTER) { const TDate da(from_d); const TLibro_giornale lg(da.year()); const TDate lp(lg.last_print()); if (da < lp) { from_d = lp.string(); error_box(FR("Il libro giornale e stato stampato il %s:\n" "La data inizio elaborazione deve essere almeno il %s"), (const char*)from_d, (const char*)from_d); m.set(F_FROMDATE, from_d); continue; } } // Recupera sheet dei selezionati ed aggiorna F_SELECTED TCursor_sheet* sheet = m.get_selection_sheet(); const long total = m.get_long(F_SELECTED); if (total <= 0) { warning_box(TR("Nessun movimento selezionato")); continue; } TString action; if (key == K_ENTER) action.format(FR("Conferma di %ld movimenti."), total); else action.format(FR("Cancellazione di %ld movimenti."), total); TString caption; caption << action << TR("\nSi desidera continuare?"); if (!yesno_box(caption)) continue; action[0] = toupper(action[0]); TProgind pi(total, action, TRUE, TRUE); if (key == K_ENTER) confirm_provv(m.get_cursor(), pi, sheet); else delete_provv(m.get_cursor(), pi, sheet); } } int cg2200(int argc, char** argv) { TProvvisori_app a; a.run(argc, argv, TR("Gestione provvisori")); return 0; }