#include "cg2102.h" #include "cg2107.h" #include "cg2100e.h" #include "cgsaldac.h" #include #include #include #include /////////////////////////////////////////////////////////// // TPartite_cache /////////////////////////////////////////////////////////// class TPartite_cache : public TString_array { TBill _bill; long _numreg; public: const TBill& bill() const { return _bill; } long num_reg() const { return _numreg; } void set_bill(const TBill& conto, long numreg, bool all); bool has_game(int id) const { return id >= 0 && id < items(); } TPartita* find(int index) const; // Find by index (0 based) TPartita& game(int index) const { return *find(index); } }; // Callback per scansione cursore static bool fill_games(const TRelation& rel, void* pJolly) { TString_array& a = *(TString_array*)pJolly; TString16 key, last_key; const TRectype& rec = rel.curr(); key.format("%d|%s", rec.get_int(PART_ANNO), (const char*)rec.get(PART_NUMPART)); const int last = a.items()-1; if (last >= 0) last_key = a.row(last); if (key != last_key) a.add(key); return true; } void TPartite_cache::set_bill(const TBill& conto, long numreg, bool all) { _bill = conto; _numreg = numreg; destroy(); TRelation partite(LF_PARTITE); TRectype& rec = partite.curr(); rec.put(PART_TIPOCF, conto.tipo()); rec.put(PART_GRUPPO, conto.tipo() > ' ' ? 0 : conto.gruppo()); rec.put(PART_CONTO, conto.tipo() > ' ' ? 0 : conto.conto()); rec.put(PART_SOTTOCONTO, conto.sottoconto()); TString filter; filter << '(' << PART_NUMRIG << "<9999)"; if (!all) filter << "&&((" << PART_CHIUSA << "!='X')||(" << PART_NREG << "==" << numreg << "))"; TCursor cur(&partite, filter, 1, &rec, &rec); cur.scan(fill_games, this); } TPartita* TPartite_cache::find(int idx) const { TPartita* g = NULL; if (has_game(idx)) { const TToken_string& str = row(idx); int anno; str.get(0, anno); TString8 numero; str.get(1, numero); TPartite_array& giochi = app().partite(); g = &giochi.partita(_bill, anno, numero); } return g; } /////////////////////////////////////////////////////////// // TSolder_tree /////////////////////////////////////////////////////////// class TSolder_tree : public TBidirectional_tree { TPartite_cache _cache; TToken_string _curr; public: virtual bool goto_root(); virtual bool goto_firstson(); virtual bool goto_rbrother(); virtual bool goto_node(const TString &id) { _curr = id; return true; } virtual bool has_son() const; virtual bool has_rbrother() const; virtual TObject* curr_node() const { return (TObject*)&_curr; } virtual void node2id(const TObject* obj, TString& id) const { id = *(TString*)obj; } virtual bool has_root() const { return _cache.bill().ok(); } virtual bool has_father() const { return _curr.not_empty(); } virtual bool has_lbrother() const; virtual bool goto_father(); virtual bool goto_lbrother(); virtual bool get_description(TString& desc) const; virtual bool marked() const; public: void set_root(const TBill& conto, long numreg, bool all); TPartita* partita() const; }; TPartita* TSolder_tree::partita() const { int index = -1; _curr.get(0, index); TPartita* g = _cache.find(index); return g; } bool TSolder_tree::goto_root() { _curr.cut(0); return _cache.bill().ok(); } bool TSolder_tree::goto_firstson() { const int level = _curr.items(); if (level >= 4) return false; const TPartita* g = partita(); // Funziona per level <= 1 if (g == NULL) return false; if (level == 0) { _curr = "0"; return true; // Basta il test precedente g!=NULL } if (level == 1) { const int riga = g->first(); const bool ok = riga > 0 && riga < 9999; if (ok) _curr.add(riga); return ok; } const int riga = _curr.get_int(1); if (level == 2) { const bool ok = g->esiste(riga, 1); if (ok) _curr.add(1); return ok; } const int rata = _curr.get_int(2); if (level == 3) { const TRiga_scadenze& scad = g->rata(riga, rata); const int p = scad.first(); const bool ok = p > 0 && p < 9999; if (ok) _curr.add(p); return ok; } return false; } bool TSolder_tree::goto_rbrother() { const int level = _curr.items(); if (level == 0) // Il prossimo clifo non esiste mai per progetto return false; const int index = _curr.get_int(0); if (level == 1) // Esite la prossima partita? { const bool ok = _cache.find(index+1) != NULL; if (ok) _curr.add(index+1, 0); return ok; } const TPartita& g = _cache.game(index); const int riga = _curr.get_int(1); if (level == 2) // Esite la prossima riga? { const int nriga = g.succ(riga); const bool ok = nriga > riga && nriga < 9999; if (ok) _curr.add(nriga, 1); return ok; } const int rata = _curr.get_int(2); if (level == 3) // Esiste la prossima rata? { const int nrata = rata+1; const bool ok = g.esiste(riga, nrata); if (ok) _curr.add(nrata, 2); return ok; } const int pag = _curr.get_int(3); if (level == 4) // Esiste il prossimo pagamento { const TRiga_scadenze& scad = g.rata(riga, rata); const int npag = scad.succ(pag); const bool ok = g.esiste(riga, rata, npag); if (ok) _curr.add(npag, 3); return ok; } return false; } bool TSolder_tree::has_son() const { TSolder_tree& me = (TSolder_tree&)*this; const TString16 old = me._curr; const bool ok = me.goto_firstson(); me._curr = old; return ok; } bool TSolder_tree::has_rbrother() const { TSolder_tree& me = (TSolder_tree&)*this; const TString16 old = me._curr; const bool ok = me.goto_rbrother(); me._curr = old; return ok; } bool TSolder_tree::has_lbrother() const { TSolder_tree& me = (TSolder_tree&)*this; const TString16 old = me._curr; const bool ok = me.goto_lbrother(); me._curr = old; return ok; } bool TSolder_tree::goto_father() { const bool ok = has_father(); if (ok) { const int pipe = _curr.rfind(_curr.separator()); if (pipe >= 0) _curr.cut(pipe); else _curr.cut(0); } return ok; } bool TSolder_tree::goto_lbrother() { const int level = _curr.items(); if (level == 0) // Il precedente clifo non esiste mai per progetto return false; const int index = _curr.get_int(0); if (level == 1) // Esite la precedente partita? { const bool ok = index > 0; if (ok) _curr.add(index-1, 0); return ok; } const TPartita& g = _cache.game(index); const int riga = _curr.get_int(1); if (level == 2) // Esite la precedente riga? { const int nriga = g.pred(riga); const bool ok = nriga > 0 && nriga < 9999; if (ok) _curr.add(nriga, 1); return ok; } const int rata = _curr.get_int(2); if (level == 3) // Esiste la precedente rata? { const int nrata = rata-1; const bool ok = nrata > 0; if (ok) _curr.add(nrata, 2); return ok; } const int pag = _curr.get_int(3); if (level == 4) // Esiste il precedente pagamento { const TRiga_scadenze& scad = g.rata(riga, rata); const int npag = scad.pred(pag); const bool ok = npag > 0; if (ok) _curr.add(npag, 3); return ok; } return false; } bool TSolder_tree::get_description(TString& desc) const { const int level = _curr.items(); if (level == 0) // Il prossimo clifo non esiste mai per progetto { desc = _cache.bill().descrizione(); desc.strip_double_spaces(); return true; } const TPartita& g = *partita(); if (level == 1) { desc.cut(0) << g.anno() << '/' << g.numero(); desc.strip(" "); return true; } int nriga = 1; _curr.get(1, nriga); const TRiga_partite& riga = g.riga(nriga); if (level == 2) { desc = riga.get(PART_DESCR); return true; } int nrata = 1; _curr.get(2, nrata); const TRiga_scadenze& scad = riga.rata(nrata); if (level == 3) { desc = TR("Rata"); desc << ' ' << nrata << ' ' << scad.get(SCAD_DATASCAD); return true; } int npag = 2; _curr.get(3, npag); const TRectype& pag = scad.row(npag); if (level == 4) { const TRiga_partite& rpag = g.riga(npag); const tipo_movimento tipo = rpag.tipo(); switch(tipo) { case tm_insoluto: desc = TR("Insoluto"); break; case tm_pagamento_insoluto: desc = TR("Pagamento insoluto"); break; default: desc = TR("Pagamento"); break; } desc << ' ' << rpag.get(PART_DATAPAG); return true; } desc = _curr; return true; } void TSolder_tree::set_root(const TBill& conto, long numreg, bool all) { _cache.set_bill(conto, numreg, all); } bool TSolder_tree::marked() const { bool yes = false; const int level = _curr.items(); if (level >= 2) { const TPartita& g = *partita(); int nriga = 1; _curr.get(1, nriga); const TRiga_partite& riga = g.riga(nriga); yes = riga.get_long(PART_NREG) == _cache.num_reg(); } return yes; } /////////////////////////////////////////////////////////// // TNew_game_mask /////////////////////////////////////////////////////////// class TNew_game_mask : public TAutomask { const TBill& _conto; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TNew_game_mask(const TBill& conto); }; bool TNew_game_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { bool ok = true; switch (o.dlg()) { case 102: if (e == fe_modify || e == fe_close) { const int anno = get_int(101); const char* part = get(102); const TPartita p(_conto, anno, part); if (p.first() > 0) ok = error_box("La partita %d/%s esiste gia'", anno, part); } break; default: break; } return ok; } TNew_game_mask::TNew_game_mask(const TBill& conto) : TAutomask(TR("Nuova partita"), 1, 24, 5), _conto(conto) { TReal_field& anno = add_number(101, 0, PR("Anno "), 1, 1, 4, "A"); anno.check_type(CHECK_REQUIRED); const char* flags = TPartita::allineamento_richiesto(_conto.tipo()) == 'R' ? "R" : ""; TEdit_field& partita = add_string(102, 0, PR("Partita "), 1, 2, 6, flags); partita.check_type(CHECK_REQUIRED); add_button(DLG_OK, 0, "", -12, -1, 10, 2); add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2); set_handlers(); } /////////////////////////////////////////////////////////// // TEasySolder_mask /////////////////////////////////////////////////////////// // Forse andrebbe in libreria! void TEasySolder_mask::set_imp(short id, const TImporto& imp) { TEdit_field& e = efield(id); CHECK(e.size() >= 15, "Campo troppo piccolo per contenere un importo"); if (!imp.is_zero()) { const TCurrency c(imp.valore()); TString80 str; str << c.string(true) << ' ' << imp.sezione(); e.set(str); } else e.reset(); } bool TEasySolder_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_NEWREC: if (e == fe_button) { TNew_game_mask m(_conto.tipo()); if (m.run() == K_ENTER) { } } break; case F_TUTTE: if (e == fe_modify) { TSolder_tree& t = *(TSolder_tree*)_tree; const bool all = o.get().full(); t.set_root(_conto, _numreg, all); if (t.goto_root()) t.expand(); TTree_field& tfp = tfield(F_PARTITE); tfp.win().force_update(); } break; case F_PARTITE: if (e == fe_modify) { TSolder_tree& t = *(TSolder_tree*)_tree; TToken_string curr; t.curr_id(curr); const int level = curr.items(); if (level > 0) { const TPartita& p = *t.partita(); TImporto saldo, doc, pag, imp; p.calcola_saldo(saldo, doc, pag, imp); set_imp(F_DOCUMENTI_P, doc); set_imp(F_PAGAMENTI_P, pag); set_imp(F_IMPORTI_P, imp); set_imp(F_SALDO_P, saldo); } if (level > 1) { const TPartita& p = *t.partita(); const int nriga = curr.get_int(1); const TRiga_partite& r = p.riga(nriga); TImporto imp(r.get_char(PART_SEZ), r.get_real(PART_IMPORTO)); set(F_DATA_R, r.get(PART_DATADOC)); set_imp(F_IMPORTO_R, imp); } if (level > 2) { const int nriga = curr.get_int(1); const TRiga_partite& r = t.partita()->riga(nriga); const int nrata = curr.get_int(2); const TRiga_scadenze& s = r.rata(nrata); TImporto doc = s.importo(false); TImporto pag = s.importo_pagato(false); TImporto saldo = s.residuo(false); set(F_DATA_S, s.get(SCAD_DATASCAD)); set_imp(F_IMPORTO_S, doc); set_imp(F_PAGAMENTI_S, pag); set_imp(F_SALDO_S, saldo); } if (level > 3) { const int nriga = curr.get_int(1); const TRiga_partite& rf = t.partita()->riga(nriga); const int nrata = curr.get_int(2); const TRiga_scadenze& s = rf.rata(nrata); const int nrigp = curr.get_int(3); const TRectype& p = s.row(nrigp); const TRiga_partite& rp = t.partita()->riga(nrigp); const TImporto pag(rp.get_char(PART_SEZ), p.get_real(PAGSCA_IMPORTO)); const TImporto abb(rp.get_char(PART_SEZABB), p.get_real(PAGSCA_ABBUONI)); const TImporto dif(rp.get_char(PART_SEZDIFCAM), p.get_real(PAGSCA_DIFFCAM)); set(F_DATA_PAG, rp.get(PART_DATAPAG)); set_imp(F_IMPORTO_PAG, pag); set_imp(F_ABBUONI_PAG, abb); set_imp(F_DIFFCAM_PAG, dif); } show(-10, level > 0); show(-20, level > 1); show(-30, level > 2); show(-40, level > 3); } break; default: break; } return true; } void TEasySolder_mask::init(const TBill& conto, long numreg, int numrig) { _conto = conto; _numreg= numreg; _numrig = numrig; _changed = false; if (_tree == NULL) { _tree = new TSolder_tree; tfield(F_PARTITE).set_tree(_tree); } TSolder_tree& t = *(TSolder_tree*)_tree; t.set_root(_conto, _numreg, get_bool(F_TUTTE)); if (t.goto_root()) t.expand(); } TEasySolder_mask::TEasySolder_mask(const TBill& conto, long numreg, int numrig) : TAutomask("cg2100e"), _tree(NULL) { init(conto, numreg, numrig); } TEasySolder_mask::~TEasySolder_mask() { if (_tree) delete _tree; }