campo-sirio/cg/cgsalda3.cpp
guy 1159b1d092 Patch level : 10.0
Files correlati     : cg2.exe
Ricompilazione Demo : [ ]
Commento            :
Abilitate ricerche per codice alternativo


git-svn-id: svn://10.65.10.50/branches/R_10_00@22584 c028cbd2-c16b-5b4b-a496-9718f37d4682
2012-02-23 16:50:46 +00:00

846 lines
20 KiB
C++
Executable File

#include "cgsalda3.h"
#include <diction.h>
#include <relation.h>
#include <urldefid.h>
#include <causali.h>
#include <mov.h>
///////////////////////////////////////////////////////////
// TPartite_cache
///////////////////////////////////////////////////////////
// Callback per scansione cursore
static bool fill_games(const TRelation& rel, void* pJolly)
{
TPartite_cache& a = *(TPartite_cache*)pJolly;
a.add_game(rel.curr());
return true;
}
// Carica la lista delle partite.
void TPartite_cache::set_bill(TPartite_array& games, const TBill& conto, long numreg,
const TString& codval, TSolder_tree_flags flags)
{
_games = &games;
_bill = conto;
_numreg = numreg;
_codval = codval;
destroy();
TRelation partite(LF_PARTITE);
TRectype& rec = partite.curr();
const char tipocf = conto.tipo();
if (tipocf > ' ')
{
rec.put(PART_TIPOCF, tipocf);
rec.put(PART_SOTTOCONTO, conto.codclifo());
}
else
{
rec.put(PART_GRUPPO, conto.gruppo());
rec.put(PART_CONTO, conto.conto());
rec.put(PART_SOTTOCONTO, conto.sottoconto());
}
flags = TSolder_tree_flags(flags & sct_all_games); // Ignora eventuale flag di valuta
TString filter;
if (flags != sct_all_games && numreg > 0 && numreg < 999999)
filter << '(' << PART_NREG << "==\"" << numreg << "\")";
if (flags == sct_open_games || flags == sct_closed_games)
{
if (filter.full())
filter << "||";
filter << "(" << PART_CHIUSA << ((flags & sct_open_games)!=0 ? "!=" : "==") << "\"X\")";
}
TCursor cur(&partite, filter, 1, &rec, &rec);
cur.scan(fill_games, this);
for (TPartita* p = games.first(); p != NULL; p = games.next()) if (!p->is_on_file())
add_game(*p);
}
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);
g = &_games->partita(_bill, anno, numero);
}
return g;
}
const TString& TPartite_cache::build_key(int anno, const char* partita) const
{
TString8 numpart = partita;
numpart.trim();
TString& tmp = get_tmp_string(16);
tmp.format("%04d|%s", anno, (const char*)numpart);
return tmp;
}
int TPartite_cache::game_id(int anno, const char* numpart) const
{
const TString& key = build_key(anno, numpart);
return TString_array::find(key);
}
bool TPartite_cache::add_game(int anno, const char* partita)
{
const TString& key = build_key(anno, partita);
const bool can_add = TString_array::find(key) < 0;
if (can_add)
add(key);
return can_add;
}
bool TPartite_cache::add_game(const TRectype& partita)
{
if (!same_values(partita.get(PART_CODVAL), _codval))
return false;
return add_game(partita.get_int(PART_ANNO), partita.get(PART_NUMPART));
}
bool TPartite_cache::add_game(const TPartita& partita)
{
if (!same_values(partita.codice_valuta(), _codval))
return false;
return add_game(partita.anno(), partita.numero());
}
///////////////////////////////////////////////////////////
// TSolder_tree
///////////////////////////////////////////////////////////
TPartita* TSolder_tree::partita() const
{
int index = -1; _curr.get(0, index);
return _cache.find(index);
}
TRiga_partite* TSolder_tree::riga_partita() const
{
TRiga_partite* fatt = NULL;
if (_curr.items() >= 2)
{
TPartita* g = partita();
if (g != NULL)
{
int nriga = 1; _curr.get(1, nriga);
if (nriga > 0 && nriga < g->UNASSIGNED)
return &g->riga(nriga);
}
}
return fatt;
}
TRiga_scadenze* TSolder_tree::scadenza() const
{
TRiga_scadenze* scad = NULL;
if (_curr.items() >= 3)
{
TPartita* g = partita();
if (g != NULL)
{
int nriga = 1; _curr.get(1, nriga);
int nrata = 1; _curr.get(2, nrata);
if (nrata > 0 && nrata < g->UNASSIGNED && g->esiste(nriga, nrata))
scad = &g->rata(nriga, nrata);
}
}
return scad;
}
TRectype* TSolder_tree::pagamento() const
{
TRectype* rpag = NULL;
if (_curr.items() >= 4)
{
TPartita* g = partita();
if (g != NULL)
{
int nriga = 1; _curr.get(1, nriga);
int nrata = 1; _curr.get(2, nrata);
int nrigp = 2; _curr.get(3, nrigp);
if (g->esiste(nriga, nrata, nrigp))
rpag = &g->pagamento(nriga, nrata, nrigp);
}
}
return rpag;
}
bool TSolder_tree::goto_root()
{
const bool can_be_done = has_root();
if (can_be_done)
_curr = "0"; // Prima partita della lista
else
_curr.cut(0);
return can_be_done;
}
bool TSolder_tree::goto_firstson()
{
const int level = _curr.items();
if (level <= 0 || level >= 4)
return false;
TPartita* g = partita();
if (g == NULL) // Dovrebbe funzionare sempre per level > 0
return false;
if (level == 1)
{
int riga = g->prima_fattura();
bool ok = riga > 0 && riga < TPartita::UNASSIGNED;
if (!ok && g->unassigned().rows() > 0)
{
riga = TPartita::UNASSIGNED;
ok = true;
}
if (ok)
_curr.add(riga);
return ok;
}
const int riga = _curr.get_int(1);
if (level == 2)
{
if (riga == TPartita::UNASSIGNED)
{
_curr.add(TPartita::UNASSIGNED);
return true;
}
const bool ok = g->esiste(riga, 1);
if (ok)
_curr.add(1);
return ok;
}
const int rata = _curr.get_int(2);
if (level == 3)
{
int nrigp = 0;
if (rata != TPartita::UNASSIGNED)
{
const TRiga_scadenze& scad = g->rata(riga, rata);
nrigp = scad.first();
}
else
{
nrigp = g->unassigned().first_row();
}
const bool ok = g->esiste(riga, rata, nrigp);
if (ok)
_curr.add(nrigp);
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;
}
TPartita& g = _cache.game(index);
const int riga = _curr.get_int(1);
if (level == 2) // Esite la prossima riga?
{
bool ok = false;
if (riga > 0 && riga < g.UNASSIGNED)
{
int nriga = riga+1; // good guess :-)
for (nriga = g.succ(riga); g.esiste(nriga); nriga = g.succ(nriga))
{
const TRiga_partite& rp = g.riga(nriga);
if (rp.is_fattura())
break;
}
ok = g.esiste(nriga);
if (!ok && g.unassigned().rows() > 0)
{
nriga = g.UNASSIGNED;
ok = true;
}
if (ok)
_curr.add(nriga, 1);
}
return ok;
}
const int rata = _curr.get_int(2);
if (level == 3) // Esiste la prossima rata?
{
bool ok = false;
if (rata > 0 && rata < g.UNASSIGNED)
{
const int nrata = rata+1;
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
{
int npag = 0;
if (rata > 0 && rata < g.UNASSIGNED)
{
const TRiga_scadenze& scad = g.rata(riga, rata);
npag = scad.succ(pag);
}
else
npag = g.unassigned().succ_row(pag);
const bool ok = g.esiste(riga, rata, npag);
if (ok)
_curr.add(npag, 3);
return ok;
}
return false;
}
bool TSolder_tree::could_have_son() const
{
const int level = _curr.items();
if (level <= 0 || level >= 4)
return false; // Sono su di un pagamento
const TPartita* g = partita();
if (g == NULL)
return false;
int riga = 0; _curr.get(1, riga);
if (level == 2) // Sono su di una riga fattura o non assegnata
return riga == g->UNASSIGNED || g->esiste(riga, 1);
if (level == 3) // Sono su di una rata o non assegnata
{
int rata = 0; _curr.get(2, rata);
return rata == g->UNASSIGNED || g->esiste(riga, rata);
}
return true;
}
bool TSolder_tree::has_son() const
{
bool ok = could_have_son();
if (ok)
{
TSolder_tree& me = (TSolder_tree&)*this;
const TString16 old = me._curr;
ok = me.goto_firstson();
me._curr = old;
}
return ok;
}
bool TSolder_tree::has_root() const
{ return _cache.items() > 0; }
bool TSolder_tree::has_father() const
{ return _curr.find(_curr.separator()) > 0; }
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;
}
TPartita& g = _cache.game(index);
const int riga = _curr.get_int(1);
if (level == 2) // Esite la precedente riga?
{
int nriga = 0;
if (riga == g.UNASSIGNED)
nriga = g.last();
else
nriga = g.pred(riga);
while (nriga > 0 && !g.riga(nriga).is_fattura())
nriga = g.pred(nriga);
const bool ok = nriga > 0;
if (ok)
_curr.add(nriga, 1);
return ok;
}
const int rata = _curr.get_int(2);
if (level == 3) // Esiste la precedente rata?
{
bool ok = false;
if (riga != g.UNASSIGNED && rata != g.UNASSIGNED)
{
const int nrata = rata-1;
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
{
int npag = 0;
if (riga == g.UNASSIGNED || rata == g.UNASSIGNED)
{
npag = g.unassigned().pred_row(pag);
}
else
{
const TRiga_scadenze& scad = g.rata(riga, rata);
npag = scad.pred(pag);
}
const bool ok = npag > 0;
if (ok)
_curr.add(npag, 3);
return ok;
}
return false;
}
void TSolder_tree::set_var_imp(TVariant& var, const TImporto& imp, bool in_value) const
{
if (!imp.is_zero())
{
const TCurrency cur(imp.valore(), in_value ? _codval : EMPTY_STRING);
var = cur.string(true);
}
else
var.set_null();
}
void TSolder_tree::set_var_real(TVariant& var, const real& imp, bool in_value) const
{
if (!imp.is_zero())
{
TCurrency cur(imp, in_value ? (const char*)_codval : "");
if (in_value != show_val())
{
if (in_value)
cur.change_to_firm_val();
else
cur.change_value(_codval, _cambio);
}
var = cur.string(true);
}
}
TFieldtypes TSolder_tree::get_var(const TString& name, TVariant& var) const
{
const int level = _curr.items();
if (level == 0) // Should never happen :-)
{
if (name == PART_DESCR)
var = _cache.bill().descrizione();
return var.type();
}
TPartita& g = *partita();
if (name == PART_CODVAL)
{
var = _codval;
return _alfafld;
}
if (level == 1)
{
if (name == PART_DESCR)
{
TString8 numpart = g.numero(); numpart.trim();
TString16 desc; desc << g.anno() << '/' << numpart;
var = desc;
} else
if (name == PART_NUMDOC || name == PART_DATADOC)
{
int r = g.prima_fattura();
if (r <= 0) r = g.first();
var = g.riga(r).get(name);
} else
if (name == "DARE" || name == "AVERE")
{
if (!g.chiusa()) // Ignora saldi sicuramente nulli
{
const bool sv = show_val();
const TImporto saldo = g.calcola_saldo(sv);
if (saldo.sezione() == name[0])
set_var_imp(var, saldo, sv);
}
}
return var.type();
}
int nriga = 1; _curr.get(1, nriga);
if (level == 2)
{
if (nriga > 0 && nriga < g.UNASSIGNED && g.esiste(nriga))
{
const TRiga_partite& riga = g.riga(nriga);
if (name == PART_DESCR)
{
TString desc = riga.get(PART_DESCR);
if (desc.blank())
{
const long nreg = riga.get_long(PART_NREG);
if (nreg > 0)
desc = cache().get(LF_MOV, nreg, MOV_DESCR);
if (desc.blank())
desc = cache().get(LF_CAUSALI, riga.get(PART_CODCAUS), CAU_DESCR);
}
var = desc;
} else
if (name == "DARE" || name == "AVERE")
{
const bool sv = show_val();
const TImporto imp = riga.importo(sv);
if (imp.sezione() == name[0])
set_var_imp(var, imp, sv);
}
else
{
// NUMDOC, DATADOC, NREG
if (riga.TRectype::exist(name))
var = riga.get(name);
}
}
else
{
if (name == PART_DESCR)
var = TR("Pagamenti non assegnati");
else
{
if (g.unassigned().rows() == 1)
{
const int nriga = g.unassigned().first_row();
const TRiga_partite& riga = g.riga(nriga);
const TFieldtypes ft = riga.type(name);
switch (ft)
{
case _nullfld: break;
case _intfld:
case _intzerofld:
case _longfld:
case _longzerofld:
{
const TString& n = riga.get(name);
if (!real::is_null(n))
var = n;
}
break;
case _realfld: set_var_real(var, riga.get_real(name), false); break;
default : var = riga.get(name); break;
}
}
}
}
return var.type();
}
int nrata = 1; _curr.get(2, nrata);
if (level == 3)
{
if (nrata > 0 && nrata < g.UNASSIGNED && g.esiste(nriga, nrata))
{
const TRiga_partite& fatt = g.riga(nriga);
const TRiga_scadenze& rata = fatt.rata(nrata);
if (name == PART_DESCR)
{
TString16 desc;
desc << nrata << '/' << fatt.rate();
var = desc;
} else
if (name == PART_NUMDOC)
var = fatt.get(name); else
if (name == PART_DATADOC)
var = rata.get(SCAD_DATASCAD); else
if (name == "DARE" || name == "AVERE")
{
const bool sv = show_val();
const TImporto imp = rata.importo(sv);
if (imp.sezione() == name[0])
set_var_imp(var, imp, sv);
}
}
else
{
if (name == PART_DESCR)
var = TR("Rata non assegnata");
}
return var.type();
}
int npag = 2; _curr.get(3, npag);
if (g.esiste(nriga, nrata, npag))
{
const TRectype& pag = g.pagamento(nriga, nrata, npag);
const TRiga_partite& rpag = g.riga(npag);
const tipo_movimento tipo = rpag.tipo();
if (name == PART_DESCR)
{
switch(tipo)
{
case tm_nota_credito : var = TR("Nota di credito"); break;
case tm_insoluto : var = TR("Insoluto"); break;
case tm_pagamento_insoluto: var = TR("Pagamento insoluto"); break;
default : var = TR("Pagamento"); break;
}
} else
if (name == "DARE" || name == "AVERE")
{
if (rpag.sezione() == name[0])
{
const bool sv = show_val();
const real imp = pag.get_real(sv ? PAGSCA_IMPORTOVAL : PAGSCA_IMPORTO);
set_var_imp(var, TImporto(rpag.sezione(), imp), sv);
}
} else
if (name == PAGSCA_ABBUONI)
{
set_var_real(var, rpag.get_real(name), show_val());
} else
if (name == PAGSCA_DIFFCAM)
{
if (_codval.full() && !show_val())
set_var_real(var, rpag.get_real(name), false);
} else
if (name == PAGSCA_RITENUTE)
{
if (_codval.empty())
set_var_real(var, rpag.get_real(name), false);
} else
if (name == PAGSCA_RITSOC)
{
if (_codval.empty())
set_var_real(var, rpag.get_real(name), false);
} else
if (name == PART_DATADOC)
{
var = rpag.get(name);
if (var.is_zero())
var = rpag.get(PART_DATAREG);
} else
if (rpag.TRectype::exist(name))
var = rpag.get(name);
}
return var.type();
}
bool TSolder_tree::get_description(TString& desc) const
{
TVariant var; get_var(PART_DESCR, var);
desc = var.as_string();
return !var.is_null();
}
// Flags: 3 = tutte le partite; 8 = mostra in valuta
void TSolder_tree::set_root(TPartite_array& games, const TBill& conto, long numreg, int numrig,
const TString& codval, const real& cambio, TSolder_tree_flags flags)
{
_num_rig = numrig;
_flags = flags;
if (is_true_value(codval))
{
_codval = codval;
_cambio = cambio;
if (_cambio <= ZERO)
_cambio = UNO;
}
else
{
_codval.cut(0);
_cambio = ZERO;
// Ignora visualizzazione importi in valuta in assenza di vera valuta
_flags = TSolder_tree_flags(_flags & ~sct_show_val);
}
_cache.set_bill(games, conto, numreg, _codval, _flags);
goto_root();
}
bool TSolder_tree::marked() const
{
bool yes = false;
const int level = _curr.items();
if (level >= 1)
{
const TPartita& g = *partita();
if (level == 1)
yes = !g.chiusa();
else
{
int nriga = 1; _curr.get(1, nriga);
if (nriga > 0 && nriga < g.UNASSIGNED)
{
const TRiga_partite& riga = g.riga(nriga);
yes = riga.get_long(PART_NREG) == _cache.num_reg();
if (!yes && level == 3)
{
int nrata = 1; _curr.get(2, nrata);
const TRiga_scadenze& scad = g.rata(nriga, nrata);
yes = !scad.chiusa();
}
}
}
}
return yes;
}
TImage* TSolder_tree::image(bool selected) const
{
const int level = _curr.items();
short id = 0;
switch (level)
{
case 1:
{
TPartita* p = partita();
id = p && p->chiusa() ? BMP_DIRDNSEL : BMP_DIRDN;
}
break;
case 2:
{
const TRiga_partite* s = riga_partita();
id = s && s->get_bool(PART_CHIUSA) ? BMP_FILECHK : BMP_FILE;
}
break;
case 3:
{
const TRiga_scadenze* s = scadenza();
id = s && s->chiusa() ? BMP_DIRDNSEL : BMP_DIRDN;
}
break;
case 4:
{
int nrigp = 0; _curr.get(3, nrigp);
if (nrigp > 0)
{
const TRiga_partite& rp = partita()->riga(nrigp);
switch (rp.tipo())
{
case tm_pagamento_insoluto: // Alias tm_pagamento
case tm_pagamento: id = BMP_PAGAMENTO; break;
default: id = BMP_INSOLUTO; break;
}
}
else
id = BMP_FILE;
}
break;
default: break;
}
return id > 0 ? get_res_image(id) : TTree::image(selected);
}
bool TSolder_tree::goto_game(int anno, const char* numpart, int nriga, int nrata, int nrigp)
{
// Controllo cge la partita sia tra quelle possibili in cache
const int idx = _cache.game_id(anno, numpart);
if (idx < 0)
return false;
// Costruisco la chiave del nodo desiderato: idx|nriga|nrata|nrigp
TToken_string key;
key.add(idx);
if (nriga > 0)
{
key.add(nriga);
if (nrata > 0)
{
key.add(nrata);
if (nrigp > 0)
key.add(nrigp);
}
}
return goto_node(key);
}
bool TSolder_tree::goto_single_game(int anno, const char* numpart, int nriga, int nrata, int nrigp)
{
// Controllo se per caso la partita non sia gia' in cache
if (_cache.game_id(anno, numpart) < 0)
{
TPartite_array& giochi = _cache.partite();
if (!giochi.exist(_cache.bill(), anno, numpart))
return false;
}
// Svuoto la cache e ci metto la sola partita desiderata
_cache.destroy();
_cache.add_game(anno, numpart);
expand_all(); // Espando tutto l'alberello
// Posiziono l'albero normalmente
return goto_game(anno, numpart, nriga, nrata, nrigp);
}