Files correlati : Ricompilazione Demo : [ ] Commento :incluso il treectrl git-svn-id: svn://10.65.10.50/trunk@16095 c028cbd2-c16b-5b4b-a496-9718f37d4682
589 lines
14 KiB
C++
Executable File
589 lines
14 KiB
C++
Executable File
#include "cg2102.h"
|
|
#include "cg2107.h"
|
|
|
|
#include "cg2100e.h"
|
|
#include "cgsaldac.h"
|
|
|
|
#include <defmask.h>
|
|
#include <diction.h>
|
|
#include <relation.h>
|
|
#include <treectrl.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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");
|
|
TString80 str;
|
|
if (!imp.is_zero())
|
|
{
|
|
const TCurrency c(imp.valore());
|
|
str << c.string(true) << ' ' << imp.sezione();
|
|
}
|
|
e.set(str);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|