e1b494f330
git-svn-id: svn://10.65.10.50/branches/R_10_00@23048 c028cbd2-c16b-5b4b-a496-9718f37d4682
591 lines
15 KiB
C++
591 lines
15 KiB
C++
#include "sl0100a.h"
|
||
#include "sl0101.h"
|
||
|
||
#include <diction.h>
|
||
#include <mask.h>
|
||
#include <reputils.h>
|
||
#include <urldefid.h>
|
||
|
||
#include "../ca/calib01.h"
|
||
#include "../ca/fasi.h"
|
||
#include "../ve/velib.h"
|
||
|
||
static bool cmscpy(TRectype& dst, const TRectype& src)
|
||
{
|
||
const TString& cms_in = src.get(RDOC_CODCMS);
|
||
if (cms_in.blank())
|
||
{
|
||
NFCHECK("Commessa nulla");
|
||
return false;
|
||
}
|
||
const TString& cms_out = dst.get(RDOC_CODCMS);
|
||
if (cms_in == cms_out)
|
||
return true;
|
||
|
||
if (!cms_out.blank())
|
||
NFCHECK("Commessa incoerente");
|
||
|
||
dst.put(RDOC_CODCMS, cms_in);
|
||
return true;
|
||
}
|
||
|
||
bool TSAL_tree::add_lastson(TObject* obj)
|
||
{
|
||
CHECK(obj != NULL && obj->is_kind_of(CLASS_RECTYPE), "Record non valido per SAL");
|
||
TRectype& rec = *(TRectype*)obj;
|
||
CHECK(rec.get(RDOC_TIPORIGA).full(), "TIPORIGA vuoto");
|
||
cmscpy(rec, *curr_row());
|
||
bool done = false;
|
||
if (goto_firstson()) // Se ha almeno un figlio ...
|
||
{
|
||
while (goto_rbrother()); // ... allora vai all'ultimo fratello
|
||
done = add_rbrother(obj); // ed aggiungi ultimo fratello
|
||
}
|
||
else
|
||
done = add_son(obj); // Aggiungi primogenito
|
||
return done;
|
||
}
|
||
|
||
TSAL_level TSAL_tree::last_fase_level() const
|
||
{
|
||
return (TSAL_level)_picture_fasi.items();
|
||
}
|
||
|
||
bool TSAL_tree::goto_last_fase(TSAL_level sublevel)
|
||
{
|
||
bool ok = goto_root() && goto_firstson();
|
||
if (ok)
|
||
{
|
||
while (goto_rbrother()); // goto last son
|
||
|
||
if (sublevel > sl_fase1)
|
||
{
|
||
//TSAL_level max_lev = last_fase_level();
|
||
//if (sublevel < max_lev)
|
||
// max_lev = sublevel;
|
||
|
||
while (level() < sublevel)
|
||
{
|
||
if (goto_firstson())
|
||
while (goto_rbrother());
|
||
else
|
||
break;
|
||
}
|
||
|
||
ok = level() == sublevel;
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TSAL_tree::goto_last_dist()
|
||
{
|
||
bool ok = goto_last_fase(sl_distinta); // sl_distinta = dummy value for maximum depth
|
||
if (ok)
|
||
while (goto_rbrother());
|
||
return ok;
|
||
}
|
||
|
||
TRectype* TSAL_tree::new_row(TSAL_level level) const
|
||
{
|
||
const TMask& m = owner().mask();
|
||
TRectype* rec = new TRectype(level == sl_documento ? LF_DOC : LF_RIGHEDOC);
|
||
rec->put(RDOC_PROVV, 'D');
|
||
rec->put(RDOC_ANNO, m.get(F_ANNO));
|
||
rec->put(RDOC_CODNUM, m.get(F_CODNUM));
|
||
rec->put(RDOC_NDOC, m.get(F_NDOC));
|
||
TString cantiere;
|
||
for (short id = F_CDC0+1; m.id2pos(id) > 0; id++)
|
||
cantiere << m.get(id);
|
||
rec->put(RDOC_CODCMS, cantiere);
|
||
switch (level)
|
||
{
|
||
case sl_documento:
|
||
rec->put(DOC_NUMANT, m.get(F_NSAL));
|
||
break;
|
||
case sl_distinta:
|
||
rec->put(RDOC_TIPORIGA, tipo_dist());
|
||
rec->put(RDOC_DESCR, TR("Nuova distinta"));
|
||
cmscpy(*rec, *curr_row());
|
||
break;
|
||
case sl_misura:
|
||
rec->put(RDOC_TIPORIGA, tipo_misu());
|
||
rec->put(RDOC_DESCR, TR("Nuova misura"));
|
||
cmscpy(*rec, *curr_row());
|
||
break;
|
||
default:
|
||
rec->put(RDOC_TIPORIGA, tipo_fasi());
|
||
rec->put(RDOC_DESCR, TR("Nuova fase"));
|
||
rec->put(RSAL_LEVEL, level-sl_fase1);
|
||
break;
|
||
}
|
||
|
||
return rec;
|
||
}
|
||
|
||
static bool find_fase_cb(TTree& node, void* jolly, word /*when*/)
|
||
{
|
||
const TSAL_tree& tree = (TSAL_tree&)node;
|
||
const TSAL_level lev = tree.level();
|
||
if (lev < sl_fase1 || lev >= sl_distinta)
|
||
return false;
|
||
|
||
const TString& fascms = *((TString*)jolly);
|
||
const TRectype& rec = *tree.curr_row();
|
||
const TString& fase = rec.get(RDOC_FASCMS);
|
||
return fase == fascms;
|
||
}
|
||
|
||
|
||
TRectype* TSAL_tree::fase(const TString& fase, bool create)
|
||
{
|
||
TRectype* rec = NULL;
|
||
if (goto_root() && scan_breadth_first(find_fase_cb, (void*)&fase))
|
||
rec = curr_row();
|
||
else if (create)
|
||
{
|
||
if (goto_root())
|
||
{
|
||
rec = new_row(sl_fase1);
|
||
rec->put(RDOC_FASCMS, fase);
|
||
TToken_string key; key = rec->get(RDOC_CODCMS); key.add(fase);
|
||
TString80 descr = cache().get(LF_FASI, key, FASI_DESCRIZ);
|
||
if (descr.empty())
|
||
{
|
||
key.add(" ", 0);
|
||
descr = cache().get(LF_FASI, key, FASI_DESCRIZ);
|
||
}
|
||
if (descr.full())
|
||
rec->put(RDOC_DESCR, descr);
|
||
add_lastson(rec);
|
||
}
|
||
}
|
||
return rec;
|
||
}
|
||
|
||
TRectype* TSAL_tree::dist(const TString& fase, int n, bool create)
|
||
{
|
||
TRectype* rec = NULL;
|
||
if (goto_node(fase))
|
||
{
|
||
if (goto_firstson())
|
||
{
|
||
int i = 0;
|
||
for (; i < n && goto_rbrother(); i++);
|
||
if (i < n)
|
||
{
|
||
if (create)
|
||
add_rbrother(rec = new_row(sl_distinta));
|
||
}
|
||
else
|
||
rec = curr_row();
|
||
}
|
||
else
|
||
{
|
||
if (create)
|
||
add_son(rec = new_row(sl_distinta));
|
||
}
|
||
}
|
||
return rec;
|
||
}
|
||
|
||
TRectype* TSAL_tree::misu(const TString& dist, int n, bool create)
|
||
{
|
||
TRectype* rec = NULL;
|
||
if (goto_node(dist))
|
||
{
|
||
CHECKS(level() == sl_distinta, "Distinta non valida", (const char*)dist);
|
||
if (goto_firstson())
|
||
{
|
||
int i = level() == sl_misura ? 0 : -1;
|
||
while (i < n && goto_rbrother())
|
||
if (level() == sl_misura) i++;
|
||
if (i < n)
|
||
{
|
||
if (create)
|
||
add_rbrother(rec = new_row(sl_misura));
|
||
}
|
||
else
|
||
rec = curr_row();
|
||
}
|
||
else
|
||
{
|
||
if (create && n == 0)
|
||
add_son(rec = new_row(sl_misura));
|
||
}
|
||
}
|
||
return rec;
|
||
}
|
||
|
||
TSAL_level TSAL_tree::level(const TRectype& rec) const
|
||
{
|
||
TSAL_level lev = sl_documento;
|
||
if (rec.num() == LF_RIGHEDOC)
|
||
{
|
||
const TString& t = rec.get(RDOC_TIPORIGA);
|
||
if (t.full())
|
||
{
|
||
lev = sl_fase1;
|
||
if (t == _strFasi)
|
||
lev = TSAL_level(lev + rec.get_int(RSAL_LEVEL)); else
|
||
if (t == _strDist)
|
||
lev = sl_distinta; else
|
||
if (t == _strMisu)
|
||
lev = sl_misura;
|
||
}
|
||
}
|
||
return lev;
|
||
}
|
||
|
||
TSAL_level TSAL_tree::level() const
|
||
{
|
||
TSAL_level lev = sl_documento;
|
||
TRectype* rec = curr_row();
|
||
if (rec != NULL)
|
||
lev = level(*rec);
|
||
return lev;
|
||
}
|
||
|
||
bool TSAL_tree::could_have_son() const
|
||
{ return level() < sl_distinta; }
|
||
|
||
bool TSAL_tree::get_description(TString& str) const
|
||
{
|
||
const TRectype* rec = curr_row();
|
||
bool ok = rec != NULL && !rec->empty();
|
||
if (ok)
|
||
{
|
||
if (rec->num() == LF_DOC)
|
||
{
|
||
const TMask& m = owner().mask();
|
||
str.cut(0) << TR("SAL ") << m.get(F_NSAL) << TR(" del ") << m.get(F_DATADOC);
|
||
} else
|
||
if (rec->num() == LF_RIGHEDOC)
|
||
{
|
||
str = rec->get(RDOC_DESCR);
|
||
if (str.blank())
|
||
str = rec->get(RDOC_CODCMS);
|
||
}
|
||
else
|
||
NFCHECK("Bad tree record");
|
||
}
|
||
else
|
||
NFCHECK("NULL tree record");
|
||
return ok;
|
||
}
|
||
|
||
TFieldtypes TSAL_tree::get_var(const TString& name, TVariant& var) const
|
||
{
|
||
TFieldtypes ft = _nullfld;
|
||
const TRectype* rec = curr_row();
|
||
if (rec != NULL && !rec->empty())
|
||
{
|
||
if (rec->num() == LF_DOC)
|
||
{
|
||
const TMask& m = owner().mask();
|
||
if (name == RDOC_CODART)
|
||
{
|
||
var = m.get(F_NDOC);
|
||
ft = _alfafld;
|
||
} else
|
||
if (name == RDOC_DESCR)
|
||
{
|
||
TString str; get_description(str);
|
||
const int spc = str.find('\n');
|
||
if (spc > 0) str.cut(spc);
|
||
var = str;
|
||
ft = _alfafld;
|
||
} else
|
||
if (name == RDOC_PREZZO || name == RSAL_COSTO)
|
||
{
|
||
real c, p; ((TSAL_tree*)this)->ricalcola(c, p);
|
||
if (name == RDOC_PREZZO )
|
||
var = p.stringa(0,2);
|
||
else
|
||
var = c.stringa(0,2);
|
||
ft = _realfld;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ft = rec->type(name);
|
||
if (ft > _nullfld)
|
||
{
|
||
const TSAL_level livello = level(*rec);
|
||
if (ft == _realfld)
|
||
{
|
||
if ((name == RDOC_PREZZO || name == RSAL_COSTO) && livello == sl_distinta)
|
||
{
|
||
real c, p; ((TSAL_tree*)this)->ricalcola(c, p);
|
||
if (name == RDOC_PREZZO )
|
||
var = p.stringa(0,2);
|
||
else
|
||
var = c.stringa(0,2);
|
||
}
|
||
else
|
||
var = rec->get_real(name).stringa(0, 2);
|
||
}
|
||
else
|
||
{
|
||
if (name == RDOC_CODART && livello < sl_distinta)
|
||
{
|
||
TString16 fase = rec->get(RDOC_FASCMS);
|
||
if (fase.blank())
|
||
{
|
||
fase = rec->get(RDOC_CODART);
|
||
if (livello < _picture_fasi.items())
|
||
{
|
||
const TString& pic = _picture_fasi.row(livello-1);
|
||
const int len = pic.len();
|
||
if (pic[0] == '0')
|
||
fase.right_just(len, '0');
|
||
else
|
||
fase.left_just(len, ' ');
|
||
}
|
||
((TRectype*)rec)->put(RDOC_FASCMS, fase);
|
||
}
|
||
var = fase;
|
||
}
|
||
else
|
||
var = rec->get(name);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ft;
|
||
}
|
||
|
||
|
||
TImage* TSAL_tree::image(bool sel) const
|
||
{
|
||
const TSAL_level pl = level();
|
||
if (pl <= sl_distinta)
|
||
{
|
||
const bool ex = expanded();
|
||
if (has_son())
|
||
return get_res_image(ex ? BMP_DIRDNSEL : BMP_DIRSEL);
|
||
else
|
||
return get_res_image(ex ? BMP_DIRDN : BMP_DIR);
|
||
}
|
||
return TObject_tree::image(sel);
|
||
}
|
||
|
||
// Aggiunge un record alla fine dell'albero in base al tipo della riga (usato solo in lettura iniziale)
|
||
bool TSAL_tree::append_row(const TRectype& rec)
|
||
{
|
||
const TSAL_level pl = level(rec);
|
||
if (pl == sl_documento)
|
||
{
|
||
// Se aggiungo un documento allora svuoto albero e ricreo radice
|
||
if (goto_root())
|
||
kill_node();
|
||
return add_son(rec);
|
||
} else
|
||
if (pl == sl_distinta)
|
||
{
|
||
const TString16 fascms = rec.get(RDOC_FASCMS);
|
||
bool ok = false;
|
||
if (fascms.full())
|
||
ok = fase(fascms, true) != NULL;
|
||
else
|
||
ok = goto_last_dist();
|
||
return ok && add_lastson(rec);
|
||
} else
|
||
if (pl == sl_misura)
|
||
{
|
||
if (goto_last_dist())
|
||
return add_lastson(rec);
|
||
}
|
||
else
|
||
{
|
||
goto_root();
|
||
while (level() < pl)
|
||
{
|
||
if (goto_firstson())
|
||
while (goto_rbrother());
|
||
else
|
||
break;
|
||
}
|
||
if (level() < pl)
|
||
return add_lastson(rec);
|
||
else
|
||
return add_rbrother(rec);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
bool TSAL_tree::ricalcola(real& costo, real& prezzo)
|
||
{
|
||
bool ok = false;
|
||
const TSAL_level lev = level();
|
||
costo = prezzo = ZERO;
|
||
if (lev < sl_distinta && has_son())
|
||
{
|
||
TString16 id; curr_id(id);
|
||
for (bool go = goto_firstson(); go; go = goto_rbrother())
|
||
{
|
||
real c, p;
|
||
if (ricalcola(c, p))
|
||
{
|
||
costo += c;
|
||
prezzo += p;
|
||
}
|
||
}
|
||
ok = goto_node(id);
|
||
if (lev >= sl_fase1)
|
||
{
|
||
TRectype& rec = *curr_row();
|
||
rec.put(RDOC_QTA, 1);
|
||
rec.put(RSAL_COSTO, costo);
|
||
rec.put(RDOC_PREZZO, prezzo);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ok = lev == sl_distinta;
|
||
if (ok)
|
||
{
|
||
const TRectype& rec = *curr_row();
|
||
const real qta = rec.get_real(RDOC_QTA);
|
||
if (!qta.is_zero())
|
||
{
|
||
costo = qta * rec.get_real(RSAL_COSTO);
|
||
prezzo = qta * rec.get_real(RDOC_PREZZO);
|
||
}
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TSAL_tree::load(const TRectype& doc, int nsal)
|
||
{
|
||
TLog_report log;
|
||
|
||
// Lettura righe documento
|
||
TToken_string keytok;
|
||
keytok.add(doc.get(DOC_CODNUM));
|
||
keytok.add(doc.get(DOC_ANNO));
|
||
keytok.add(doc.get(DOC_PROVV));
|
||
keytok.add(doc.get(DOC_NDOC));
|
||
TRecord_array rdoc(keytok, LF_RIGHEDOC);
|
||
|
||
// Svuota automaticamente albero e crea documento radice
|
||
bool done = append_row(doc);
|
||
if (done)
|
||
{
|
||
// Caricamento righe nell'albero
|
||
const int last_row = rdoc.last_row();
|
||
TString16 curr_fase;
|
||
for (int r = rdoc.first_row(); r > 0 && r <= last_row; r = rdoc.succ_row(r))
|
||
{
|
||
TRectype& rr = rdoc[r];
|
||
const TSAL_level sl = level(rr);
|
||
|
||
const TString& fase = rr.get(RDOC_FASCMS);
|
||
if (fase.blank())
|
||
{
|
||
if (sl < sl_distinta)
|
||
curr_fase = rr.get(RDOC_CODART);
|
||
rr.put(RDOC_FASCMS, curr_fase);
|
||
}
|
||
else
|
||
curr_fase = fase;
|
||
|
||
// Gestione copia da ordine o SAL precedente
|
||
if (nsal > 0 && sl >= sl_distinta)
|
||
{
|
||
if (sl >= sl_misura)
|
||
continue; // Non copiare le misure!
|
||
|
||
const real qta = rr.get(RDOC_QTA);
|
||
if (nsal == 1) // nsal=1 -> copia da ordine
|
||
{
|
||
rr.put(RDOC_DAIDRIGA, rr.get(RDOC_IDRIGA));
|
||
rr.put(RDOC_QTAGG1, qta); // Inizializza totale riga ordine
|
||
rr.put(RDOC_QTAGG2, ZERO); // Totale SAL precedenti (nessuno nel primo SAL)
|
||
rr.put(RDOC_QTAGG3, qta); // Residuo (nel primo SAL <20> uguale alla qta)
|
||
|
||
const TString& sconto = rr.get(RDOC_SCONTO);
|
||
if (sconto.full())
|
||
{
|
||
const real impns = prezzo_scontato(rr.get_real(RDOC_PREZZO), sconto);
|
||
if (!impns.is_zero())
|
||
rr.put(RDOC_PREZZO, impns);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
rr.add(RDOC_QTAGG2, qta); // Aggiorna totale precedente quando copi da SAL
|
||
rr.add(RDOC_QTAGG3,-qta); // Aggiorna residuo quando copi da SAL
|
||
}
|
||
rr.zero(RDOC_QTA); // Azzera quantit<69> sempre
|
||
}
|
||
if (!append_row(rr))
|
||
{
|
||
TString msg;
|
||
msg.format("Impossibile caricare la riga %d di tipo %s:\n%s",
|
||
rr.get_int(RDOC_NRIGA), (const char*)rr.get(RDOC_TIPORIGA),
|
||
(const char*)rr.get(RDOC_DESCR));
|
||
log.log(2, msg);
|
||
done = false;
|
||
}
|
||
} // fine caricamento riga
|
||
|
||
TMask& m = owner().mask();
|
||
if (nsal > 1) // A partire dal secondo sal aggiorno i progressivi di testata P_SAL_*
|
||
{
|
||
const TDocumento prec(doc);
|
||
FOR_EACH_MASK_FIELD(m, i, f)
|
||
{
|
||
const TFieldref* ref = f->field();
|
||
if (ref != NULL && ref->name().starts_with("G1:P_SAL_"))
|
||
{
|
||
const real p_val = ref->read(prec);
|
||
|
||
TString16 name = ref->name(); name.ltrim(5);
|
||
const real val = prec.get(name);
|
||
const real progr = p_val + val;
|
||
f->set(progr.string());
|
||
}
|
||
}
|
||
}
|
||
const real p_sic2 = m.get_real(F_P_SAL_SIC) + m.get_real(F_P_SAL_ESC);
|
||
m.set(F_P_SAL_SIC2, p_sic2);
|
||
}
|
||
else
|
||
{
|
||
TString msg; msg.format("Impossibile caricare il documento %s", (const char*)keytok);
|
||
log.log(2, msg);
|
||
}
|
||
|
||
// Espansione della sola radice
|
||
shrink_all(); goto_root(); expand();
|
||
owner().force_update();
|
||
|
||
if (!done)
|
||
log.preview();
|
||
|
||
return done;
|
||
}
|
||
|
||
|
||
TSAL_tree::TSAL_tree(TTree_field& owner) : _owner(owner)
|
||
{
|
||
// Legge i tipi riga standard per determinare i nodi dell'albero
|
||
_strFasi = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaFase", "05");
|
||
_strDist = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaDist", "P1");
|
||
_strMisu = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaMisu", "P2");
|
||
|
||
TConfig& cfg = ca_config();
|
||
for (int i = 1; i <= 4; i++)
|
||
{
|
||
const TString& pic = cfg.get("Fsc", "ca", i);
|
||
if (pic.full())
|
||
_picture_fasi.add(pic);
|
||
else
|
||
break;
|
||
}
|
||
}
|
||
|