campo-sirio/db/dblib.cpp
alex 7da1be4f90 Patch level : XX.312
Files correlati     :
Ricompilazione Demo : [ ]
Commento            : Riportata la versione 01.05 patch 312


git-svn-id: svn://10.65.10.50/trunk@8093 c028cbd2-c16b-5b4b-a496-9718f37d4682
1999-04-26 15:58:05 +00:00

1616 lines
33 KiB
C++
Executable File

#include <ctype.h>
#include <stdlib.h>
#include <urldefid.h>
#include <lffiles.h>
#include <utility.h>
#include "tabutil.h"
#include "dblib.h"
#include "../mg/anamag.h"
#include "../mg/umart.h"
#include "../mg/rmovmag.h"
#include "../include/rdoc.h"
///////////////////////////////////////////////////////////
// TQuantita'
///////////////////////////////////////////////////////////
TDecoder* TQuantita::_umart1 = NULL;
TDecoder* TQuantita::_umart2 = NULL;
TDecoder* TQuantita::_umdist = NULL;
real TQuantita::get_factor(const TCodice_um& um) const
{
real fc = 1.0;
if (_articolo.blank())
{
NFCHECK("Unita' di misura generica non supportata");
}
else
{
if (_umart2 == NULL)
{
_umart2 = new TDecoder(LF_UMART, UMART_FC, 2);
_umart2->test_file_changes();
_umart2->set_items_limit(256);
}
TString80 code;
code << _articolo << '|' << (um.empty() ? _um : um);
const TString& val = _umart2->decode(code);
if (val.not_empty())
fc = real(val);
}
return fc;
}
real TQuantita::find_umbase(TCodice_um& um)
{
if (_umart1 == NULL)
{
_umart1 = new TDecoder(LF_UMART, UMART_UM, 1);
_umart1->test_file_changes();
_umart1->set_items_limit(256);
}
TString80 code;
code << _articolo << "|1";
const TString& new_um = _umart1->decode(code);
if (new_um.blank())
{
if (_umdist == NULL)
{
_umdist = new TDecoder(LF_DIST, UMART_UM, 1);
_umdist->test_file_changes();
_umdist->set_items_limit(256);
}
um = _umdist->decode(_articolo);
}
else
um = new_um;
return 1.0;
}
real TQuantita::find_umdist(TCodice_um& um)
{
if (_umdist == NULL)
{
_umdist = new TDecoder(LF_DIST, UMART_UM, 1);
_umdist->test_file_changes();
_umdist->set_items_limit(256);
}
um = _umdist->decode(_articolo);
if (um.blank())
find_umbase(um);
return get_factor(um);
}
void TQuantita::set_articolo(const TCodice_articolo& art,
const TCodice_um& um)
{
_articolo = art;
if (isalnum(um[0]))
{
_um = um;
_conv = get_factor(_um);
}
else
{
if (um.blank())
_conv = find_umbase(_um);
else
_conv = find_umdist(_um);
}
if (!art.blank() && _um.blank())
NFCHECK("Unita' di misura nulla per %s", (const char*)art);
CHECK(_conv > ZERO, "Invalid conversion factor");
}
void TQuantita::copy(const TQuantita& q)
{
_articolo = q._articolo;
_um = q._um;
_conv = q._conv;
_val = q._val;
}
void TQuantita::convert(real& val, const TCodice_um& from_um,
const TCodice_um& to_um) const
{
CHECK(!from_um.blank() && !to_um.blank(), "Unita' di misura nulla");
if (from_um != to_um)
{
if (!val.is_zero())
{
const real mul = get_factor(from_um);
const real div = get_factor(to_um);
val *= mul;
val /= div;
}
}
}
void TQuantita::convert2umdist()
{
TCodice_um dummy;
_conv = find_umdist(dummy);
if (dummy != _um)
{
convert(_val, _um, dummy);
_um = dummy;
}
}
void TQuantita::convert2umbase()
{
TCodice_um dummy;
find_umbase(dummy);
if (dummy != _um)
{
CHECK(_conv > ZERO, "Invalid conversion factor");
_val *= _conv;
_um = dummy;
_conv = 1.0;
}
}
real TQuantita::base_val() const
{
CHECK(_conv > ZERO, "Invalid conversion factor");
real v = _conv * _val;
return v;
}
int TQuantita::compare(const TSortable& s) const
{
const TQuantita& q = (const TQuantita&)s;
real qta = q._val;
if (_um != q._um)
convert(qta, q._um, _um);
qta -= _val;
return -qta.sign();
}
const TQuantita& TQuantita::operator +=(const real& qta)
{
_val += qta;
return *this;
}
const TQuantita& TQuantita::operator -=(const real& qta)
{
_val -= qta;
return *this;
}
const TQuantita& TQuantita::operator +=(const TQuantita& q)
{
if (!_um.blank())
{
real qta = q._val;
if (_um != q._um)
convert(qta, q._um, _um);
_val += qta;
}
else
copy(q);
return *this;
}
const TQuantita& TQuantita::operator -=(const TQuantita& q)
{
real qta = q._val;
if (_um != q._um)
convert(qta, q._um, _um);
_val -= qta;
return *this;
}
const TQuantita& TQuantita::operator =(const real& q)
{
CHECK(!_um.blank(), "Unita' di misura nulla");
_val = q;
return *this;
}
const TQuantita& TQuantita::operator *=(const real& q)
{
CHECK(!_um.blank(), "Unita' di misura nulla");
_val *= q;
return *this;
}
const TQuantita& TQuantita::operator /=(const real& q)
{
CHECK(!_um.blank(), "Unita' di misura nulla");
_val /= q;
return *this;
}
TQuantita::TQuantita()
: _conv(1.0)
{ }
TQuantita::TQuantita(const TCodice_articolo& art, const TCodice_um& um, const real& val)
{
set(art, um, val);
}
TQuantita::TQuantita(const TQuantita& q)
{ copy(q); }
TQuantita::~TQuantita()
{
}
///////////////////////////////////////////////////////////
// TLavorazione
///////////////////////////////////////////////////////////
// @cmember Legge il file <p f> con il tipo di record
int TLavorazione::read(TBaseisamfile& f, word op , word lockop)
{
int err=TRectype::read(f, op, lockop );
get_linee();
return err;
}
// @cmember Legge il file <p f> con il tipo di record alla posizione desiderata
int TLavorazione::readat(TBaseisamfile& f, TRecnotype nrec, word lockop )
{
int err=TRectype::readat(f, nrec, lockop );
get_linee();
return err;
}
// @cmember Aggiunge il record al file
int TLavorazione::write(TBaseisamfile& f) const
{
((TLavorazione *)this)->put_linee();
return TRectype::write(f) ;
}
// @cmember Riscrive il record sul fil
int TLavorazione::rewrite(TBaseisamfile& f) const
{
((TLavorazione *)this)->put_linee();
return TRectype::rewrite(f) ;
}
const char * TLavorazione::cod_impianto(int l)
{
return cache().get("LNP",cod_linea(l)).get("S6");
}
void TLavorazione::reset_linee()
{
_linee.cut(0);
}
void TLavorazione::get_linee()
{
char esse[3] ="S1";
reset_linee();
for (char s = '1'; s <= '5'; s++)
{
esse[1]=s;
_linee << get(esse);
}
}
void TLavorazione::put_linee()
{
char esse[3]= "S1";
int from=0, len=70;
TString str;
for (char s='1'; s<='5'; s++)
{
if (s > '3') len=20;
esse[1]=s;
str=_linee.mid(from,len);
put(esse, str);
from+=len;
}
}
int TLavorazione::linee() const
{
return _linee.items()/3;
}
int TLavorazione::linee_standard() const
{
const int maxl = get_int("I1");
const int lin = linee();
return (maxl > 0 && maxl < lin) ? maxl : lin;
}
/*const TString& TLavorazione::linea(int l) const
{
const int n = l / 14;
CHECKD(n >= 0 && n <= 2, "Bad linea index ", l);
char esse[3] = { 'S', char('1'+ n), '\0' };
TString& str = _linee.cod_linea();
const int pos = (l % 14) * 5;
return str.mid(pos, 5);
}*/
const char * TLavorazione::cod_linea(int l)
{
return _linee.get(l*3);
}
const int TLavorazione::raw_numpers_linea(int l)
{
return atoi(_linee.get(l*3+1));
}
const int TLavorazione::numpers_linea(int l)
{
real np(raw_numpers_linea(l));
if (np.is_zero())
np = get_real("R2");
return (int)np.integer();
}
const real TLavorazione::raw_produttiv_linea(int l)
{
return real(_linee.get(l*3+2));
}
const real TLavorazione::produttiv_linea(int l)
{
real prod(raw_produttiv_linea(l));
if (prod.is_zero())
prod = get_real("R1");
return prod;
}
const int TLavorazione::find_linea(const TString& linea)
{
_linee.restart();
if (linea.empty()) // Se la linea da cercare e' blank, ritorna la prima disponibile
return 0;
for (int l = 0; ;l++)
{
const char* c = _linee.get(l*3);
if (!c || *c == '\0')
break;
if (linea == c)
return l;
}
return -1;
}
bool TLavorazione::set_cod_linea(int l, const char *c)
{
_linee.add(c, l*3);
return _linee.len()<250;
}
bool TLavorazione::set_numpers_linea(int l, int pers)
{
_linee.add(pers,l*3+1);
return _linee.len()<250;
}
bool TLavorazione::set_produttiv_linea(int l, real & prod)
{
_linee.add(prod.string(),l*3+2);
return _linee.len()<250;
}
TLavorazione::TLavorazione(const char* cod)
: TRectype(LF_TAB)
{
if (cod && *cod)
{
TTable lav("LAV");
put("CODTAB", cod);
read(lav);
} else
settab("LAV");
}
TRectype & TLavorazione::operator =(const TRectype& rec)
{
TRectype::operator =(rec);
get_linee();
return *this;
}
TLavorazione::TLavorazione(const TRectype& rec) : TRectype(rec)
{ get_linee();}
TLavorazione::TLavorazione(const TLavorazione& rec) : TRectype(rec)
{ _linee = rec._linee;}
///////////////////////////////////////////////////////////
// TDistinta_expr
///////////////////////////////////////////////////////////
bool TDistinta_expr::print_error(const char* msg) const
{
return error_box(msg);
}
TDistinta_expr::TDistinta_expr()
: TExpression(_numexpr, FALSE)
{
}
///////////////////////////////////////////////////////////
// TDistinta_tree
///////////////////////////////////////////////////////////
#define TREE_SEPARATOR '~'
const TRectype* TDistinta_tree::_curr = NULL;
TToken_string TDistinta_tree::_tmp(80, TREE_SEPARATOR);
bool TDistinta_tree::isola_codice(TString& code) const
{
int comma = code.find(TREE_SEPARATOR);
if (comma > 0)
code.cut(comma);
return code.not_empty();
}
bool TDistinta_tree::curr_code(TCodice_articolo& code) const
{
_path.get(-2, _tmp);
isola_codice(_tmp);
code = _tmp;
return code.not_empty();
}
/*
bool TDistinta_tree::curr_father(TCodice_articolo& code) const
{
const int level=_path.items();
code.cut(0);
if (level==1)
return FALSE;
_path.get(level-1, _tmp);
isola_codice(_tmp);
code = _tmp;
return code.not_empty();
}*/
bool TDistinta_tree::curr_giac(TString& code) const
{
_path.get(-2, _tmp);
_tmp.get(1, code);
return code.not_empty();
}
int TDistinta_tree::curr_comp(TString& code) const
{
_path.get(-2, _tmp);
_tmp.get(2, code);
return atoi(code);
}
long TDistinta_tree::curr_sort() const
{
_path.get(-2, _tmp);
return _tmp.get_long(3);
}
const char* TDistinta_tree::curr_um(TCodice_um& code) const
{
_path.get(-2, _tmp);
_tmp.get(4, code);
return code;
}
real TDistinta_tree::curr_qta() const
{
real tot = 1.0;
const int last = _path.items()-1;
TCodice_articolo art;
TCodice_um um;
real val;
TQuantita qta;
for (int i = 0; i <= last; i++)
{
_path.get(i, _tmp);
_tmp.get(5, val);
if (i < last)
{
_tmp.get(0, art);
_tmp.get(4, um);
qta.set(art, um, val);
qta.convert2umdist();
val = qta.val();
}
tot *= val;
if (tot.is_zero())
break;
}
return tot;
}
char TDistinta_tree::curr_type() const
{
_path.get(-2, _tmp);
char ap = _tmp.get_char(6);
return ap;
}
int TDistinta_tree::curr_depth() const
{
int depth = _path.items()-1;
if (_ignore_ghost)
{
for (int i = depth; i > 0; i--)
{
_path.get(i, _tmp);
char ap = _tmp.get_char(6);
if (ap == 'G') depth--;
}
}
return depth;
}
bool TDistinta_tree::goto_node(const TString &id)
{
if (id != _path)
{
_stack.destroy();
TToken_string str = id;
_path = str.get(0);
push_vars();
for (const char* t = str.get(); t; t = str.get())
{
_path.add(t);
push_vars();
}
}
return TRUE;
}
struct TFind_node_data
{
TCodice_articolo _id;
long _count;
};
HIDDEN bool find_node_callback(TTree& tree, void* jolly, word flags)
{
if (flags == SCAN_PRE_ORDER)
{
TFind_node_data& data = *(TFind_node_data*)jolly;
data._count++;
TDistinta_tree& dt = (TDistinta_tree&)tree;
TCodice_articolo id; dt.curr_code(id);
if (data._id == id)
return TRUE;
}
return FALSE;
}
long TDistinta_tree::find_node(const TCodice_articolo& str, word flags)
{
if (goto_root())
{
TFind_node_data fnd;
fnd._id = str;
fnd._count = 0;
if (scan_breadth_first(find_node_callback, &fnd, flags))
return fnd._count;
}
return 0L;
}
void TDistinta_tree::node2id(const TObject* node, TString& id) const
{
id = *(TToken_string*)node;
}
TObject* TDistinta_tree::curr_node() const
{
return (TObject*)&_path;
}
const TString& TDistinta_tree::describe(const TCodice_articolo& codart) const
{
const TString& da = ((TDecoder&)_mag).decode(codart);
if (da.not_empty())
return da;
const TString& dl = ((TDecoder&)_lav).decode(codart);
if (dl.not_empty())
return dl;
const TString& dd = cache().get(LF_DIST,codart, "DESCR");
return dd;
}
bool TDistinta_tree::get_description(TString& desc) const
{
TCodice_articolo codart; curr_code(codart);
desc = describe(codart);
if (desc.empty())
{
desc = codart;
desc << " - ???";
}
else
{
desc.insert(" - ", 0);
desc.insert(codart, 0);
}
return TRUE;
}
TImage* TDistinta_tree::image(bool selected) const
{
TImage* img;
if (is_cyclic())
img = get_res_image(BMP_STOP);
else
{
if (is_leaf())
{
TCodice_articolo art; curr_code(art);
if (art == "???")
img = get_res_image(BMP_STOP);
else
img = get_res_image(BMP_FILE);
}
else
img = TBidirectional_tree::image(selected);
}
return img;
}
void TDistinta_tree::restart()
{
_vars.destroy();
_mag.destroy();
_lav.destroy();
rec_cache(LF_RDIST).destroy();
shrink_all();
}
bool TDistinta_tree::set_root(const TQuantita& qta)
{
const bool ok = find(qta.articolo(), 1) != NULL;
if (ok)
{
_tmp = qta.articolo();
_tmp.add(' ');
_tmp.add('0');
_tmp.add('0');
_tmp.add(qta.um());
_tmp.add(qta.val().string());
_tmp.add(get_type(qta.articolo()));
_root = _tmp;
restart();
}
return ok;
}
bool TDistinta_tree::set_root(const TCodice_articolo& art,
const char* um, real qta)
{
bool ok = find(art, 1) != NULL;
if (ok)
{
const TCodice_um umart = um;
const TQuantita q(art, umart, qta);
ok = set_root(q);
}
return ok;
}
bool TDistinta_tree::set_root(const TRectype & rec)
{
const int logicnum = rec.num();
TCodice_um umart;
TCodice_articolo art;
real qta;
clear_globals();
switch (logicnum)
{
case LF_RIGHEDOC:
art = rec.get(RDOC_CODARTMAG);
umart = rec.get(RDOC_UMQTA);
qta = rec.get_real(RDOC_QTA);
set_global("_MAGAZZINO", rec.get(RDOC_CODMAG));
set_global("_LIVELLO", rec.get(RDOC_LIVELLO));
set_global("_LINEA", rec.get(RDOC_LINEA));
set_global("_IMPIANTO", rec.get(RDOC_IMPIANTO));
break;
case LF_RMOVMAG:
art = rec.get(RMOVMAG_CODART);
umart = rec.get(RMOVMAG_UM);
qta = rec.get_real(RMOVMAG_QUANT);
set_global("_MAGAZZINO", rec.get(RMOVMAG_CODMAG));
set_global("_LIVELLO", rec.get(RMOVMAG_LIVGIAC));
set_global("_LINEA", ZERO);
set_global("_IMPIANTO", ZERO);
break;
default:
NFCHECK("set root con un record (file n. %d) non previsto", logicnum);
break;
}
return set_root(art, umart, qta);
}
bool TDistinta_tree::has_root() const
{
return _root.not_empty();
}
bool TDistinta_tree::goto_root()
{
const bool ok = has_root();
if (ok)
{
_path = _root;
_stack.destroy();
push_vars();
}
return ok;
}
bool TDistinta_tree::is_cyclic(const TToken_string& path) const
{
bool cyclic = FALSE;
const int last = path.items()-1;
if (last > 0)
{
path.get(-2, _tmp);
TCodice_articolo mycod; _tmp.get(0, mycod);
for (int i = last-1; i >= 0; i--)
{
path.get(i, _tmp);
isola_codice(_tmp);
if (_tmp == mycod)
{
cyclic = TRUE;
break;
}
}
}
return cyclic;
}
static int _sort_key;
static int compare_rdist(const TObject** o1, const TObject** o2)
{
const TRectype* r1 = (const TRectype*)(*o1);
const TRectype* r2 = (const TRectype*)(*o2);
TString16 field;
field << "SORT" << _sort_key;
long k1 = r1->get_long(field);
long k2 = r2->get_long(field);
if (k1 == 0 && k2 == 0)
{
k1 = r1->get_long("NRIG");
k2 = r2->get_long("NRIG");
}
else
{
if (k1 == 0) k1 = 100000000L;
if (k2 == 0) k2 = 100000000L;
}
return k1 == k2 ? 0 : (k1 > k2 ? +1 : -1);
}
static int compare_rdist_key(const TObject** o1, const TObject** o2)
{
const TToken_string* s1 = (const TToken_string *)(*o1);
const TToken_string* s2 = (const TToken_string *)(*o2);
const TRectype& r1 = cache().get(LF_RDIST,*s1);
const TRectype& r2 = cache().get(LF_RDIST,*s2);
TString16 field;
field << "SORT" << _sort_key;
long sk1 = r1.get_long(field);
long sk2 = r2.get_long(field);
if (sk1 == 0 && sk2 == 0)
{
sk1 = r1.get_long("NRIG");
sk2 = r2.get_long("NRIG");
}
else
{
if (sk1 == 0) sk1 = 100000000L;
if (sk2 == 0) sk2 = 100000000L;
}
return sk1 == sk2 ? 0 : (sk1 > sk2 ? +1 : -1);
}
const TRectype* TDistinta_tree::find(const TCodice_articolo& father, int child) const
{
TString80 key = father;
key << '|' << child;
const TRectype& rec = cache().get(LF_RDIST,key);
return rec.empty() ? NULL : &rec;
}
int TDistinta_tree::build_children_pointers(const TCodice_articolo& father, TPointer_array& children) const
{
for (int nrig = 1; ; nrig++)
{
const TRectype* rec = find(father, nrig);
if (rec == NULL)
break;
children.add((TRectype*)rec);
}
const int total = children.items();
if (total > 1 && _sort > 0)
{
_sort_key = _sort;
children.sort(compare_rdist);
}
return total;
}
int TDistinta_tree::build_children_list(const TCodice_articolo& father, TArray& children) const
{
TToken_string key;
for (int nrig = 1; ; nrig++)
{
const TRectype* rec = find(father, nrig);
if (rec == NULL)
break;
key.add(father,0);
key.add(nrig,1);
children.add(key);
}
const int total = children.items();
if (total > 1 && _sort > 0)
{
_sort_key = _sort;
children.sort((COMPARE_FUNCTION)compare_rdist_key);
}
return total;
}
bool TDistinta_tree::has_son() const
{
if (_max_depth > 0)
{
const int depth = curr_depth();
if (depth >= _max_depth)
return FALSE;
}
if (is_cyclic())
return FALSE;
TCodice_articolo key; curr_code(key);
_curr = find(key, 1);
// Se ci sono almeno due figli ed e' necessario ordinare
if (_sort > 0 && find(key, 2) != NULL)
{
TPointer_array children;
const int total = build_children_pointers(key, children);
_curr = (TRectype*)children.objptr(0);
}
return _curr != NULL;
}
void TDistinta_tree::add_child()
{
TCodice_articolo comp = _curr->get("CODCOMP");
if (_curr->get_char("TIPO") == 'V') // Espando la variabile
{
TString cod = get_string(comp);
if (cod.blank() || cod.len() > comp.size())
cod = "???";
comp = cod;
}
_path.add(comp); // 0 - Codice articolo
_path << TREE_SEPARATOR << _curr->get("LIVELLO");// Livello giacenza
long num = _curr->get_long("NRIG");
_path << TREE_SEPARATOR << num; // Numero componente
if (_sort > 0)
{
TString16 field; field << "SORT" << _sort;
num = _curr->get_long(field);
}
_path << TREE_SEPARATOR << num; // Numero ordinamento
_path << TREE_SEPARATOR << _curr->get("UM"); // Unita' di misura
const TString& expr = _curr->get("EXPR");
const real qta = evaluate_numexpr(expr);
_path << TREE_SEPARATOR << qta; // Quantita'
_path << TREE_SEPARATOR << get_type(comp); // 6 - Articolo, Lavorazione, Virtuale, Ghost
push_vars();
}
void TDistinta_tree::kill_child()
{
// Distrugge l'ultimo stack delle variabili
pop_vars();
// Toglie l'ultimo elemento dal path
const int pipe = _path.rfind('|');
_path.cut(pipe);
}
bool TDistinta_tree::goto_firstson()
{
const bool ok = has_son();
if (ok)
add_child();
return ok;
}
bool TDistinta_tree::has_rbrother() const
{
const int last = _path.items()-1;
if (last < 1)
return FALSE;
TString80 key; _path.get(last-1, key);
isola_codice(key);
const TCodice_articolo father(key);
curr_comp(key);
if (_sort > 0)
{
TPointer_array children;
const int last = build_children_pointers(father, children)-1;
if (last > 0) // Ci sono almeno due fratelli
{
for (int c = last; c >= 0; c--)
{
const TRectype& rec = (const TRectype&)children[c];
if (rec.get("NRIG") == key)
break;
}
if (c >= 0 && c < last)
_curr = &(TRectype&)children[c+1];
else
_curr = NULL;
}
else
_curr = NULL;
}
else
{
const int brother = atoi(key) + 1;
_curr = find(father, brother);
}
return _curr != NULL;
}
bool TDistinta_tree::goto_rbrother()
{
const bool ok = has_rbrother();
if (ok)
{
kill_child();
add_child();
}
return ok;
}
bool TDistinta_tree::has_lbrother() const
{
const int last = _path.items()-1;
if (last < 1)
return FALSE;
TString80 key; _path.get(last-1, key);
isola_codice(key);
const TCodice_articolo father(key);
curr_comp(key);
if (_sort > 0)
{
TPointer_array children;
const int last = build_children_pointers(father, children)-1;
if (last > 0) // Ci sono almeno due fratelli
{
for (int c = last; c > 0; c--)
{
const TRectype& rec = (const TRectype&)children[c];
if (rec.get("NRIG") == key)
break;
}
if (c > 0)
_curr = &(TRectype&)children[c-1];
else
_curr = NULL;
}
else
_curr = NULL;
}
else
{
const int brother = atoi(key) - 1;
if (brother > 0)
_curr = find(father, brother);
else
_curr = NULL;
}
return _curr != NULL;
}
bool TDistinta_tree::goto_lbrother()
{
const bool ok = has_lbrother();
if (ok)
{
kill_child();
add_child();
}
return ok;
}
bool TDistinta_tree::has_father() const
{
const int items = _path.items();
return items > 1;
}
bool TDistinta_tree::goto_father()
{
const bool ok = has_father();
if (ok)
kill_child();
return ok;
}
bool TDistinta_tree::is_root() const
{
const int items = _path.items();
return items <= 1;
}
bool TDistinta_tree::is_leaf() const
{
TCodice_articolo key; curr_code(key);
const TRectype* first_son = find(key, 1);
return first_son == NULL;
}
bool TDistinta_tree::is_mag(const char* c) const
{
TCodice_articolo code = c;
if (code.blank())
curr_code(code);
const TString& desc = ((TDistinta_tree*)this)->_mag.decode(code);
return desc.not_empty();
}
bool TDistinta_tree::is_lav(const char* c) const
{
TCodice_articolo code = c;
if (code.blank())
curr_code(code);
const TString& desc = ((TDistinta_tree*)this)->_lav.decode(code);
return desc.not_empty();
}
char TDistinta_tree::get_type(const char* c) const
{
char type = ' '; // Tipo sconosciuto
if (c && *c > ' ')
{
if (is_mag(c))
type = 'A'; // Articolo di magazzino
else
{
if (is_lav(c))
type = 'L'; // Lavorazione
else
{
if (find(c, 1)) // E' una distinta
{
const TString& artprod = cache().get(LF_DIST, c, "ARTPROD");
if (artprod.blank())
type = 'G'; // Distinta fantasma
else
type = 'V'; // Distinta virtuale
}
}
}
}
return type;
}
void TDistinta_tree::set_sort_key(int k)
{
CHECKD(k >= 0 && k <= 5, "Chiave distinta errata: ", k);
_sort = k;
}
TTypeexp TDistinta_tree::get_var_type(const char* var)
{
const TString& vt = _vars.decode(var);
return vt.blank() ? _strexpr : _numexpr;
}
void TDistinta_tree::pop_vars()
{
_stack.pop();
}
void TDistinta_tree::clear_globals()
{
_globals.destroy();
}
void TDistinta_tree::set_global(const char* name, const char* val)
{
TString* str = new TString(val);
_globals.add(name, str, TRUE);
}
void TDistinta_tree::set_global(const char* name, const real& val)
{
_globals.add(name, val, TRUE);
}
TObject * TDistinta_tree::get_global(const char* name, word classname)
{
// defaults
TObject* val = _globals.objptr(name);
if (val && val->class_id() != classname)
return NULL;
if (classname==CLASS_STRING )
{
if (((TString *)val)->blank())
val = global_default_str(name);
}
else
{
if (((real *)val)->is_zero())
val = global_default_real(name);
}
return val;
}
TObject * TDistinta_tree::global_default_str(const char* name)
{
TConfig ini(CONFIG_DITTA,"db");
TObject* val=NULL;
int c=0;
TToken_string var;
while (!(var = ini.get("GLOBAL_STR",NULL,c++)).blank())
{
if (strcmp(var.get(0),name)==0 && *var.get(1)>' ')
{
val= new TString(var.get(1));
break;
}
}
if (!val)
{
// more defaults
ini.set_paragraph("mr");
if (strcmp("_IMPIANTO",name)==0)
val= new TString(ini.get("DEFAULT_CODIMP"));
else if (strcmp("_LINEA",name)==0)
val= new TString(ini.get("DEFAULT_CODLIN"));
else
{
ini.set_paragraph("mg");
//
//if (strcmp("_MAGAZZINO",name))
// val= new TString(ini.get("DEFAULT_CODMAGDEP"));
}
}
if (val)
_globals.add(name, val ,TRUE);
return val;
}
TObject * TDistinta_tree::global_default_real(const char* name)
{
TConfig ini(CONFIG_DITTA,"db");
TObject* val=NULL;
int c=0;
TToken_string var;
while (!(var = ini.get("GLOBAL_REAL",NULL,c++)).blank())
{
if (strcmp(var.get(0),name)==0 && *var.get(1)>' ')
{
val= new real(var.get(1));
break;
}
}
if (val)
_globals.add(name, val ,TRUE);
return val;
}
const TString& TDistinta_tree::get_string(const char* var)
{
// local vars
for (int s = 0; s < _stack.count(); s++)
{
TAssoc_array& a = (TAssoc_array&)_stack.peek(s);
const TObject* val = a.objptr(var);
if (val)
{
if (val->class_id() == CLASS_STRING)
return (const TString&)*val;
}
}
// globals & special vars
static TCodice_articolo _varvalue;
if (strcmp(var, "_DISTINTA")==0)
{
curr_code(_varvalue);
return _varvalue;
}
TObject* val = get_global(var, CLASS_STRING);
if (val)
return (const TString&)*val;
return EMPTY_STRING;
}
const real& TDistinta_tree::get_real(const char* var)
{
for (int s = 0; s < _stack.count(); s++)
{
TAssoc_array& a = (TAssoc_array&)_stack.peek(s);
const TObject* val = a.objptr(var);
if (val)
{
if (val->class_id() != CLASS_STRING)
return (const real&)*val;
else
break;
}
else
{
val = a.objptr("_GHOST");
if (val == NULL) // Non sono ghost per cui non posso andar oltre
break;
}
}
const TObject* val = _globals.objptr(var);
if (val && val->class_id() != CLASS_STRING)
return (const real&)*val;
return ZERO;
}
void TDistinta_tree::evaluate(TDistinta_expr& e)
{
for (int v = e.numvar()-1; v >= 0; v--)
{
TString name = e.varname(v);
name.upper();
const TTypeexp vartype = get_var_type(name);
if (vartype == _numexpr)
e.setvar(v, get_real(name));
else
e.setvar(v, get_string(name));
}
}
real TDistinta_tree::evaluate_numexpr(const char* str)
{
TDistinta_expr e;
e.set(str, _numexpr);
evaluate(e);
return e.as_real();
}
void TDistinta_tree::evaluate_strexpr(const char* str, TString& res)
{
TDistinta_expr e;
e.set(str, _strexpr);
evaluate(e);
res = e.as_string();
}
void TDistinta_tree::push_vars()
{
TAssoc_array* vars = new TAssoc_array;
_stack.push(vars);
const char tipo = curr_type();
if (tipo == 'G')
vars->add("_GHOST", real(1.0));
TCodice_articolo art; curr_code(art);
const TString& memo_field = cache().get(LF_DIST, art, "PARAMETRI");
if (!memo_field.blank())
{
TString var, expr;
TDistinta_expr e;
TToken_string memo(memo_field, '\n');
for (const char* str = memo.get(0); str; str = memo.get())
{
char* equal = strchr(str, '=');
if (equal)
{
*equal = '\0';
var = str; var.trim();
expr = equal + 1;
const TTypeexp exprtype = get_var_type(var);
e.set(expr, exprtype);
evaluate(e);
if (exprtype == _numexpr)
vars->add(var, e.as_real());
else
vars->add(var, e.as_string());
}
}
}
}
struct TExplosion_params
{
TArray* _array;
TString16 _filter;
int _raggruppa;
int _max_depth;
int _sort_key;
bool _materiali_base;
bool _ignore_ghost;
};
static bool explode_callback(TTree& node, void* jolly, word when)
{
if (when == SCAN_PRE_ORDER)
{
TDistinta_tree& tree = (TDistinta_tree&)node;
if (tree.is_root())
return FALSE; // Don't explode roots
const TExplosion_params& ep = *(const TExplosion_params*)jolly;
const bool is_leaf = tree.is_leaf();
if (ep._materiali_base && !is_leaf)
{
if (ep._max_depth <= 0 || tree.curr_depth() < ep._max_depth)
return FALSE; // Please, leaves only
}
if (is_leaf)
{
TCodice_articolo art; tree.curr_code(art);
if (art == "???")
return FALSE;
}
if (ep._sort_key > 0)
{
const long sk = tree.curr_sort();
if (sk <= 0)
return FALSE; // Non fa parte dell'ordinamento
}
const char type = tree.curr_type();
if (ep._filter.find(type) < 0)
return FALSE;
TRiga_esplosione* er = new TRiga_esplosione(tree);
er->set_mat_base(is_leaf);
ep._array->add(er);
}
return FALSE;
}
int TDistinta_tree::raggruppa(TArray& boom, TExplosion_grouping mode) const
{
for (int i = 0; i < boom.items(); i++)
{
TRiga_esplosione& qta1 = (TRiga_esplosione&)boom[i];
if (mode == RAGGR_EXP_UMBASE || mode == RAGGR_EXP_BASE)
qta1.convert2umbase(); else
if (mode == RAGGR_EXP_UMDIST || mode == RAGGR_EXP_DIST)
qta1.convert2umdist();
if (mode == RAGGR_EXP_UMBASE ||
mode == RAGGR_EXP_UMDIST ||
mode == RAGGR_EXP_EACHUM)
{
for (int j = boom.items()-1; j > i; j--)
{
TRiga_esplosione& qta2 = (TRiga_esplosione&)boom[j];
if (qta1.articolo() != qta2.articolo())
continue;
if (mode == RAGGR_EXP_EACHUM && qta1.um() != qta2.um())
continue;
qta1 += qta2;
boom.destroy(j, TRUE);
}
}
}
return boom.items();
}
int TDistinta_tree::explode(TArray& boom,
bool mb, TExplosion_grouping gr, int md,
const char* filter, int sk)
{
const int old_sk = get_sort_key();
const int old_md = get_max_depth();
const bool old_iv = get_ignore_ghost();
TExplosion_params ep;
ep._array = &boom;
ep._materiali_base = mb;
ep._raggruppa = gr;
ep._max_depth = md;
ep._sort_key = sk;
ep._filter = filter;
if (ep._filter.empty())
ep._filter = "ALV";
ep._ignore_ghost = ep._filter.find('G') < 0;
set_sort_key (ep._sort_key);
set_max_depth(ep._max_depth);
set_ignore_ghost(ep._ignore_ghost);
boom.destroy(); // Non si sa mai!
scan_depth_first(explode_callback, &ep);
set_sort_key(old_sk);
set_max_depth(old_md);
set_ignore_ghost(old_iv);
if (gr != RAGGR_EXP_NONE)
raggruppa(boom, gr);
return boom.items();
}
TDistinta_tree::TDistinta_tree()
: _sort(0), _max_depth(0), _ignore_ghost(FALSE),
_vars("VAR", "B0"), _mag(LF_ANAMAG, "DESCR"),
_lav("LAV")
{
}
TDistinta_tree::~TDistinta_tree()
{
}
TRiga_esplosione *TDistinta_tree::first_critical_labor(TArray & labors, TExplosion_grouping raggum)
{
return first_labor(labors,raggum);
}
TRiga_esplosione *TDistinta_tree::next_critical_labor(TArray & labors)
{
return next_labor(labors);
}
TRiga_esplosione *TDistinta_tree::first_labor(TArray & labors, TExplosion_grouping raggum)
{
static TLavorazione *curr_labor=NULL;
explode(labors,FALSE,raggum, 1,"L");
TRiga_esplosione *l=(TRiga_esplosione *)labors.first_item();
return l;
}
TRiga_esplosione *TDistinta_tree::next_labor(TArray & labors)
{
TRiga_esplosione *l=(TRiga_esplosione *)labors.succ_item();
return l;
}
TLavorazione *TDistinta_tree::find_labor(TRiga_esplosione *l)
{
static TLavorazione *curr_labor=NULL;
if (l)
{
if (curr_labor==NULL) curr_labor=new TLavorazione();
curr_labor->put("CODTAB",l->articolo());
TTable tablav("LAV");
curr_labor->read(tablav);
return curr_labor;
}
return NULL;
}
///////////////////////////////////////////////////////////
// TRiga_esplosione
///////////////////////////////////////////////////////////
void TRiga_esplosione::init(const TDistinta_tree& tree)
{
TCodice_articolo art; tree.curr_code(art);
TCodice_um um; tree.curr_um(um);
real val = tree.curr_qta();
set(art, um, val);
tree.curr_giac(_giac);
_tipo = tree.curr_type();
_sort = tree.curr_sort();
_mat_base = FALSE;
// set path and code
tree.curr_id(_path); // path
}
static TString _tmp_path;
const char * TRiga_esplosione::father()
{
_tmp_path = _path;
const int index = _tmp_path.rfind('|');
_tmp_path.cut(index == -1 ? 0 : index);
return _tmp_path;
}
TRiga_esplosione::TRiga_esplosione(const TDistinta_tree& tree)
{
init(tree);
}
TRiga_esplosione::TRiga_esplosione(const TRiga_esplosione& re)
: TQuantita(re)
{
_giac = re._giac;
_tipo = re._tipo;
_path = re._path;
_sort = re._sort;
_mat_base = re._mat_base;
}
TRiga_esplosione::TRiga_esplosione()
: TQuantita()
{
_tipo = '\0';
_sort = 0L;
_mat_base = FALSE;
}
TUm_tempo::TUm_tempo(char c)
{
switch (c)
{
case 'M': // minutes
_ore=1/60;
break;
case 'S': // seconds
_ore=1/60/60;
break;
case 'H': // hours
default:
_ore=1;
break;
}
}