57662b88e6
Files correlati : db0.exe db0500a.msk db0500b.msk db1.exe db1100a.msk Attivata la descrizione della distinta in immissione Copiato l’articolo nel codice distinta in ricerca Impostata l’unità di misura nella pagina disponibilità dell’esplosione Stampate la descrizione di distinta a e di riga nell’ esplosione git-svn-id: svn://10.65.10.50/branches/R_10_00@24001 c028cbd2-c16b-5b4b-a496-9718f37d4682
1968 lines
42 KiB
C++
Executable File
1968 lines
42 KiB
C++
Executable File
#include <ctype.h>
|
||
#include <stdlib.h>
|
||
|
||
#include <urldefid.h>
|
||
#include <config.h>
|
||
#include <currency.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"
|
||
#include "dist.h"
|
||
#include "rdist.h"
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Cache fattori di conversione
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TConversionCache : public TCache
|
||
{
|
||
TLocalisamfile _umart;
|
||
|
||
private:
|
||
virtual TObject* key2obj(const char* key);
|
||
|
||
public:
|
||
TConversionCache();
|
||
};
|
||
|
||
TObject* TConversionCache::key2obj(const char* key)
|
||
{
|
||
TToken_string str = key;
|
||
_umart.put(UMART_CODART, str.get(0));
|
||
_umart.put(UMART_UM, str.get());
|
||
_umart.setkey(2);
|
||
|
||
real num;
|
||
if (_umart.read() == NOERR)
|
||
num = _umart.get_real(UMART_FC);
|
||
else
|
||
num = UNO; // Should never happen
|
||
return new fraction(num, UNO);
|
||
}
|
||
|
||
TConversionCache::TConversionCache()
|
||
: _umart(LF_UMART)
|
||
{ }
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TQuantita'
|
||
///////////////////////////////////////////////////////////
|
||
|
||
const fraction& TQuantita::get_factor(const TCodice_um& um) const
|
||
{
|
||
static TConversionCache* factors = NULL;
|
||
if (factors == NULL)
|
||
factors = new TConversionCache;
|
||
|
||
TString80 code;
|
||
code << _articolo << '|' << (um.blank() ? _um : um);
|
||
const fraction* conv = (const fraction*)factors->objptr(code);
|
||
return *conv;
|
||
}
|
||
|
||
void TQuantita::find_umbase(TCodice_um& um) const
|
||
{
|
||
TString80 code;
|
||
code << _articolo << "|1";
|
||
const TString& new_um = cache().get(LF_UMART, code, UMART_UM);
|
||
if (new_um.blank())
|
||
um = cache().get("LAV", _articolo, "S6");
|
||
else
|
||
um = new_um;
|
||
}
|
||
|
||
void TQuantita::find_umdist(TCodice_um& um) const
|
||
{
|
||
um = cache().get(LF_DIST, _articolo, UMART_UM);
|
||
if (um.blank())
|
||
find_umbase(um);
|
||
}
|
||
|
||
void TQuantita::set_articolo(const TString& art, const TString& um)
|
||
{
|
||
_articolo = art;
|
||
|
||
if (isalnum(um[0]))
|
||
_um = um;
|
||
else
|
||
{
|
||
if (um.blank())
|
||
find_umbase(_um);
|
||
else
|
||
find_umdist(_um);
|
||
}
|
||
|
||
if (!art.blank() && _um.blank())
|
||
NFCHECK("Unita' di misura nulla per %s", (const char*)art);
|
||
}
|
||
|
||
void TQuantita::copy(const TQuantita& q)
|
||
{
|
||
_articolo = q._articolo;
|
||
_um = q._um;
|
||
_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.blank() || to_um.blank())
|
||
return;
|
||
if (from_um != to_um && !val.is_zero())
|
||
{
|
||
const fraction& mul = get_factor(from_um);
|
||
const fraction& div = get_factor(to_um);
|
||
val = mul / div * fraction(val, UNO);
|
||
TArticolo::round_um(val, to_um);
|
||
}
|
||
}
|
||
|
||
void TQuantita::convert2umdist()
|
||
{
|
||
TCodice_um dummy;
|
||
find_umdist(dummy);
|
||
if (dummy != _um)
|
||
{
|
||
convert(_val, _um, dummy);
|
||
_um = dummy;
|
||
}
|
||
}
|
||
|
||
void TQuantita::convert2umbase()
|
||
{
|
||
TCodice_um dummy;
|
||
find_umbase(dummy);
|
||
if (dummy != _um)
|
||
{
|
||
convert(_val, _um, dummy);
|
||
_um = dummy;
|
||
}
|
||
}
|
||
|
||
|
||
void TQuantita::currency2umbase(TCurrency& val) const
|
||
{
|
||
TCodice_um ub;
|
||
find_umbase(ub);
|
||
if (_um != ub && !val.is_zero())
|
||
{
|
||
const fraction& mul = get_factor(_um);
|
||
const fraction& div = get_factor(ub);
|
||
const real v = fraction(val.get_num(), UNO) * mul / div;
|
||
val.set_num(v);
|
||
}
|
||
}
|
||
|
||
real TQuantita::base_val() const
|
||
{
|
||
TCodice_um dummy;
|
||
find_umbase(dummy);
|
||
if (dummy != _um) // Se non sono gia' la base...
|
||
{
|
||
real v = _val;
|
||
convert(v, _um, dummy);
|
||
return v;
|
||
}
|
||
return _val;
|
||
}
|
||
|
||
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()
|
||
{ }
|
||
|
||
TQuantita::TQuantita(const TString& art, const TString& 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 file
|
||
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");
|
||
}
|
||
|
||
real TLavorazione::prezzo() const
|
||
{
|
||
real p = get_real("R10");
|
||
if (p.is_zero())
|
||
{
|
||
if (is_euro_value("")) // Se la ditta <20> in Euro
|
||
{
|
||
TPrice pr(get_real("R0") / real(1936.27));
|
||
p = pr.get_num();
|
||
}
|
||
else
|
||
p = get_real("R0"); // Vecchio prezzo in lire
|
||
}
|
||
return p;
|
||
}
|
||
|
||
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);
|
||
}
|
||
_linee.replace(SAFE_PIPE_CHR,'|');
|
||
}
|
||
|
||
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);
|
||
str.replace('|',SAFE_PIPE_CHR);
|
||
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();
|
||
}
|
||
|
||
real TLavorazione::raw_produttiv_linea(int l)
|
||
{
|
||
return real(_linee.get(l*3+2));
|
||
}
|
||
|
||
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)
|
||
*this = cache().get("LAV", cod);
|
||
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;
|
||
|
||
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::father_code(TCodice_articolo& code) const
|
||
{
|
||
const int it = _path.items();
|
||
_path.get(it - 2, (TString &)_tmp);
|
||
isola_codice((TString &)_tmp);
|
||
code = _tmp;
|
||
return code.not_empty();
|
||
}
|
||
|
||
bool TDistinta_tree::father_giaclev(TString& code, int levnum) const
|
||
{
|
||
const int it = _path.items();
|
||
_path.get(it - 2, (TString &) _tmp);
|
||
_tmp.get(1, code);
|
||
if (levnum>0)
|
||
{
|
||
code = livgiac().unpack_grpcode(code, levnum);
|
||
code.trim();
|
||
}
|
||
return code.not_empty();
|
||
}
|
||
|
||
bool TDistinta_tree::path_code(TCodice_articolo& code, const TToken_string &path) const
|
||
{
|
||
path.get(-2, (TString &)_tmp);
|
||
isola_codice((TToken_string &)_tmp);
|
||
code = _tmp;
|
||
return code.not_empty();
|
||
}
|
||
|
||
bool TDistinta_tree::path_giaclev(TString& code, int levnum, const TToken_string &path) const
|
||
{
|
||
path.get(-2, (TString &)_tmp);
|
||
_tmp.get(1, code);
|
||
if (levnum>0)
|
||
{
|
||
code = livgiac().unpack_grpcode(code, levnum);
|
||
code.trim();
|
||
}
|
||
return code.not_empty();
|
||
}
|
||
|
||
int TDistinta_tree::curr_comp(TString& code) const
|
||
{
|
||
_path.get(-2, (TString &)_tmp);
|
||
_tmp.get(2, code);
|
||
return atoi(code);
|
||
}
|
||
|
||
long TDistinta_tree::curr_sort() const
|
||
{
|
||
_path.get(-2, (TString &)_tmp);
|
||
return ((TToken_string &)_tmp).get_long(3);
|
||
}
|
||
|
||
const char* TDistinta_tree::curr_um(TCodice_um& code) const
|
||
{
|
||
_path.get(-2, (TString &)_tmp);
|
||
_tmp.get(4, code);
|
||
return code;
|
||
}
|
||
|
||
real TDistinta_tree::last_qta(bool vis_ghost) const
|
||
{
|
||
const int last = _path.items()-1;
|
||
int from = last - 1;
|
||
TCodice_articolo art;
|
||
TCodice_um um;
|
||
real val;
|
||
real tot = 1.0;
|
||
TQuantita qta;
|
||
|
||
if (!vis_ghost)
|
||
{
|
||
for (int i = from ; i >= 0; i--)
|
||
{
|
||
_path.get(i, (TString &)_tmp);
|
||
if (((TToken_string &)_tmp).get_char(6) != 'G')
|
||
{
|
||
from = i + 1;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (from < 0)
|
||
from = 0;
|
||
|
||
for (int i = 0; i <= last; i++)
|
||
{
|
||
_path.get(i, (TString &) _tmp);
|
||
_tmp.get(5, val);
|
||
_tmp.get(0, art);
|
||
_tmp.get(4, um);
|
||
if (i > 0)
|
||
{
|
||
qta.set_val(val);
|
||
qta.convert2umdist();
|
||
val = qta.val();
|
||
}
|
||
qta.set(art, um, ZERO);
|
||
int tprec = tot.precision();
|
||
int vprec = val.precision();
|
||
if (tprec + vprec > 15)
|
||
{
|
||
while (tprec + vprec > 16)
|
||
{
|
||
if (tprec > vprec)
|
||
--tprec;
|
||
else
|
||
--vprec;
|
||
}
|
||
tot.round(tprec);
|
||
val.round(vprec);
|
||
}
|
||
#ifdef DBG
|
||
TString s(tot.string());
|
||
TString s1(val.string());
|
||
#endif
|
||
if (i >= from)
|
||
tot *= val;
|
||
#ifdef DBG
|
||
s = tot.string();
|
||
#endif
|
||
if (tot.is_zero())
|
||
break;
|
||
}
|
||
if (tot.precision() > 15)
|
||
tot.round(15);
|
||
return tot;
|
||
}
|
||
|
||
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, (TString &) _tmp);
|
||
_tmp.get(5, val);
|
||
// if (i < last)
|
||
_tmp.get(0, art);
|
||
_tmp.get(4, um);
|
||
if (i > 0)
|
||
{
|
||
qta.set_val(val);
|
||
qta.convert2umdist();
|
||
val = qta.val();
|
||
}
|
||
qta.set(art, um, ZERO);
|
||
int tprec = tot.precision();
|
||
int vprec = val.precision();
|
||
if (tprec + vprec > 15)
|
||
{
|
||
while (tprec + vprec > 16)
|
||
{
|
||
if (tprec > vprec)
|
||
--tprec;
|
||
else
|
||
--vprec;
|
||
}
|
||
tot.round(tprec);
|
||
val.round(vprec);
|
||
}
|
||
#ifdef DBG
|
||
TString s(tot.string());
|
||
TString s1(val.string());
|
||
#endif
|
||
tot *= val;
|
||
#ifdef DBG
|
||
s = tot.string();
|
||
#endif
|
||
if (tot.is_zero())
|
||
break;
|
||
}
|
||
if (tot.precision() > 15)
|
||
tot.round(15);
|
||
return tot;
|
||
}
|
||
|
||
char TDistinta_tree::path_type(const TToken_string & path) const
|
||
{
|
||
path.get(-2, (TString &)_tmp);
|
||
char ap = ((TToken_string &) _tmp).get_char(6);
|
||
if (ap == ' ') ap = 'G';
|
||
return ap;
|
||
}
|
||
|
||
int TDistinta_tree::path_depth(const TToken_string & path) const
|
||
{
|
||
int depth = path.items()-1;
|
||
if (_ignore_ghost)
|
||
{
|
||
for (int i = depth; i > 0; i--)
|
||
{
|
||
path.get(i, (TString &)_tmp);
|
||
char ap = ((TToken_string &)_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);
|
||
if (!push_vars())
|
||
return FALSE;
|
||
for (const char* t = str.get(); t; t = str.get())
|
||
{
|
||
_path.add(t);
|
||
if (!push_vars())
|
||
return FALSE;
|
||
}
|
||
}
|
||
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
|
||
{
|
||
TString & descr = get_tmp_string();
|
||
describe(codart, descr);
|
||
return descr;
|
||
}
|
||
|
||
bool TDistinta_tree::describe(const TCodice_articolo& codart, TString& descr) const
|
||
{
|
||
TToken_string key;
|
||
TCodice_articolo code = codart;
|
||
|
||
father_code(code);
|
||
key.add(code);
|
||
|
||
const int ccomp = curr_comp(code);
|
||
|
||
if (ccomp == 0)
|
||
descr = cache().get(LF_DIST, codart, DIST_DESCR);
|
||
else
|
||
{
|
||
key.add(ccomp);
|
||
descr = cache().get(LF_RDIST, key, RDIST_DESCR);
|
||
}
|
||
|
||
if (descr.not_empty())
|
||
return TRUE;
|
||
descr = cache().get(LF_ANAMAG, codart, ANAMAG_DESCR);
|
||
if (descr.not_empty())
|
||
return TRUE;
|
||
|
||
descr = cache().get("LAV", codart, "S0");
|
||
if (descr.not_empty())
|
||
return TRUE;
|
||
|
||
const TRectype& rec = cache().get(LF_DIST, codart);
|
||
descr = rec.get("DESCR");
|
||
return !rec.empty();
|
||
}
|
||
|
||
bool TDistinta_tree::get_livgiac_on_descr(int l) const
|
||
{
|
||
if (livgiac().enabled(l))
|
||
return _livgiac_on_descr[l-1];
|
||
return FALSE;
|
||
}
|
||
|
||
bool TDistinta_tree::set_livgiac_on_descr(int l, bool on)
|
||
{
|
||
if (livgiac().enabled(l))
|
||
return _livgiac_on_descr[l-1]=on;
|
||
return FALSE;
|
||
}
|
||
|
||
bool TDistinta_tree::get_description(TString& desc) const
|
||
{
|
||
TCodice_articolo codart; curr_code(codart);
|
||
TString des;
|
||
|
||
desc.cut(0);
|
||
if (get_qta_on_descr())
|
||
{
|
||
TCodice_um code; curr_um(code);
|
||
desc << curr_qta().string() << ' ' << code << ' ' << get_descr_separator() << ' ';
|
||
}
|
||
desc << codart << get_descr_separator() << ' ';
|
||
if (!describe(codart, des))
|
||
desc << "???";
|
||
else
|
||
{
|
||
desc << des << ' ';
|
||
for (int l = 1; l <= livgiac().last_level(); l++)
|
||
if (get_livgiac_on_descr(l))
|
||
{
|
||
TString16 giaclev; curr_giaclev(giaclev,l);
|
||
if (!giaclev.empty() )
|
||
desc << des << ' ' << livgiac().name(l) << ' ' << giaclev;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
TImage* TDistinta_tree::image(bool selected) const
|
||
{
|
||
TImage* img = NULL;
|
||
if (is_cyclic())
|
||
img = get_res_icon(10203);
|
||
else
|
||
{
|
||
if (is_leaf())
|
||
{
|
||
TCodice_articolo art; curr_code(art);
|
||
if (art == "???")
|
||
img = get_res_icon(10203);
|
||
else
|
||
img = get_res_image(BMP_FILE);
|
||
}
|
||
else
|
||
img = TBidirectional_tree::image(selected);
|
||
}
|
||
return img;
|
||
}
|
||
|
||
bool TDistinta_tree::restart()
|
||
{
|
||
return shrink_all();
|
||
}
|
||
|
||
bool TDistinta_tree::set_root(const TQuantita& qta, const char* livgiac)
|
||
{
|
||
bool ok = has_child_num(qta.articolo(), 1);
|
||
if (ok)
|
||
{
|
||
_tmp = qta.articolo(); // codice
|
||
_tmp.add(livgiac); // livgiac
|
||
_tmp.add('0');
|
||
_tmp.add('0');
|
||
_tmp.add(qta.um()); // unita' di misura
|
||
_tmp.add(qta.val().string()); // quantita
|
||
_tmp.add(get_type(qta.articolo()));
|
||
|
||
_root = _tmp;
|
||
ok = restart();
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TDistinta_tree::set_root(const TCodice_articolo& art,
|
||
const char* um, real qta,
|
||
const char* livgiac)
|
||
{
|
||
bool ok = has_child_num(art, 1);
|
||
if (ok)
|
||
{
|
||
const TCodice_um umart = um;
|
||
const TQuantita q(art, umart, qta);
|
||
ok = set_root(q, livgiac);
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TDistinta_tree::set_root(const TRectype & rec)
|
||
{
|
||
const int logicnum = rec.num();
|
||
TCodice_articolo art;
|
||
TCodice_um umart;
|
||
TString16 livgiac;
|
||
real qta;
|
||
clear_globals();
|
||
|
||
switch (logicnum)
|
||
{
|
||
case LF_RIGHEDOC:
|
||
art = rec.get(RDOC_CODARTMAG);
|
||
if (art.empty())
|
||
art = rec.get(RDOC_CODART);
|
||
umart = rec.get(RDOC_UMQTA);
|
||
qta = rec.get_real(RDOC_QTA);
|
||
livgiac = rec.get(RDOC_LIVELLO);
|
||
set_global("_MAGDEP", rec.get(RDOC_CODMAG));
|
||
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);
|
||
livgiac = rec.get(RMOVMAG_LIVGIAC);
|
||
set_global("_MAGDEP", rec.get(RMOVMAG_CODMAG));
|
||
set_global("_LINEA", rec.get(RMOVMAG_LINEA));
|
||
set_global("_IMPIANTO", rec.get(RMOVMAG_IMPIANTO));
|
||
break;
|
||
default:
|
||
NFCHECK("set root con un record (file n. %d) non previsto", logicnum);
|
||
break;
|
||
}
|
||
return set_root(art, umart, qta, livgiac);
|
||
}
|
||
|
||
bool TDistinta_tree::has_root() const
|
||
{
|
||
return _root.not_empty();
|
||
}
|
||
|
||
bool TDistinta_tree::goto_root()
|
||
{
|
||
bool ok = has_root();
|
||
if (ok)
|
||
{
|
||
_path = _root;
|
||
_stack.destroy();
|
||
ok = 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, (TString &)_tmp);
|
||
TCodice_articolo mycod; _tmp.get(0, mycod); mycod.trim();
|
||
for (int i = last-1; i >= 0; i--)
|
||
{
|
||
path.get(i, (TString &)_tmp);
|
||
isola_codice((TToken_string &)_tmp);
|
||
if (_tmp == mycod)
|
||
{
|
||
cyclic = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return cyclic;
|
||
}
|
||
|
||
static int compare_rdist_key(const TObject** o1, const TObject** o2)
|
||
{
|
||
TToken_string* s1 = (TToken_string*)(*o1);
|
||
TToken_string* s2 = (TToken_string*)(*o2);
|
||
|
||
long sk1 = s1->get_long(3);
|
||
long sk2 = s2->get_long(3);
|
||
if (sk1 == 0 && sk2 == 0)
|
||
{
|
||
sk1 = s1->get_long(2);
|
||
sk2 = s2->get_long(2);
|
||
}
|
||
else
|
||
{
|
||
if (sk1 == 0) sk1 = 100000000L;
|
||
if (sk2 == 0) sk2 = 100000000L;
|
||
}
|
||
return sk1 == sk2 ? 0 : (sk1 > sk2 ? +1 : -1);
|
||
}
|
||
|
||
const TRectype& TDistinta_tree::find_head(const TCodice_articolo& art) const
|
||
{
|
||
const TRectype& rec = cache().get(LF_DIST, art);
|
||
return rec;
|
||
}
|
||
|
||
const TRectype* TDistinta_tree::find_child(const TCodice_articolo& father, int child) const
|
||
{
|
||
TString80 key = father;
|
||
key << '|' << child;
|
||
const TRectype& rec = cache().get(LF_RDIST,key);
|
||
return &rec;
|
||
}
|
||
|
||
bool TDistinta_tree::has_child_num(const TCodice_articolo& father, int child) const
|
||
{
|
||
const TRectype* rec = find_child(father, child);
|
||
return rec && !rec->empty();
|
||
}
|
||
|
||
int TDistinta_tree::build_children_list(const TCodice_articolo& father, TArray& children) const
|
||
{
|
||
TToken_string key(39, TREE_SEPARATOR);
|
||
for (int nrig = 1; ; nrig++)
|
||
{
|
||
const TRectype* rec = find_child(father, nrig);
|
||
if (rec == NULL || rec->empty())
|
||
break;
|
||
key.add(rec->get("CODCOMP"),0);
|
||
key.add(rec->get("LIVELLO"),1);
|
||
key.add(nrig,2);
|
||
if (_sort > 0)
|
||
{
|
||
TString16 field; field.format("SORT%d", _sort);
|
||
key.add(rec->get(field), 3);
|
||
}
|
||
children.add(key);
|
||
}
|
||
const int total = children.items();
|
||
if (total > 1 && _sort != 0)
|
||
{
|
||
children.sort((COMPARE_FUNCTION)compare_rdist_key);
|
||
}
|
||
return total;
|
||
}
|
||
|
||
bool TDistinta_tree::set_curr(const TCodice_articolo& key, int child) const
|
||
{
|
||
const TRectype* c = child > 0 ? find_child(key, child) : NULL;
|
||
if (c != NULL)
|
||
(TRectype&)_curr = *c;
|
||
else
|
||
((TRectype&)_curr).zero();
|
||
return c != NULL;
|
||
}
|
||
|
||
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);
|
||
// TString16 livgiac; curr_giaclev(livgiac);
|
||
set_curr(key, 1);
|
||
// Se ci sono almeno due figli ed e' necessario ordinare
|
||
if (_sort != 0 && has_child_num(key, 2))
|
||
{
|
||
TArray children;
|
||
build_children_list(key, children);
|
||
const int first = ((TToken_string*)children.objptr(0))->get_int(2);
|
||
set_curr(key, first);
|
||
}
|
||
return !_curr.empty();
|
||
}
|
||
|
||
bool TDistinta_tree::add_child()
|
||
{
|
||
TCodice_articolo comp = _curr.get("CODCOMP");
|
||
TString tmp,tmp2;
|
||
if (_curr.get_char("TIPO") == 'V') // Espando la variabile
|
||
{
|
||
tmp = get_string(comp);
|
||
if (tmp.blank() || tmp.len() > comp.size())
|
||
tmp = "???";
|
||
comp = tmp;
|
||
}
|
||
_path.add(comp); // 0 - Codice articolo
|
||
|
||
_path << TREE_SEPARATOR;
|
||
tmp = _curr.get(RDIST_LIVELLO);
|
||
if (livgiac().enabled())
|
||
{
|
||
TString fgiaclev; father_giaclev(fgiaclev);
|
||
// ereditarieta'
|
||
for (int l= 0 ; l < 4; l++) if (livgiac().enabled(l+1))
|
||
{
|
||
tmp2 = livgiac().unpack_grpcode(tmp, l+1);
|
||
if (_curr.get(RDIST_TIPO_LIV)[l]=='E')
|
||
{
|
||
tmp2 = livgiac().unpack_grpcode(fgiaclev, l+1);
|
||
livgiac().pack_grpcode(tmp, tmp2 , l+1);
|
||
}
|
||
}
|
||
}
|
||
|
||
_path << tmp; // 1 Livello giacenza
|
||
long num = _curr.get_long(RDIST_NRIG);
|
||
_path << TREE_SEPARATOR << num; // 2 Numero componente
|
||
if (_sort > 0)
|
||
{
|
||
TString16 field; field << "SORT" << _sort;
|
||
num = _curr.get_long(field);
|
||
}
|
||
_path << TREE_SEPARATOR << num; // 3 Numero ordinamento
|
||
|
||
_path << TREE_SEPARATOR << _curr.get(RDIST_UM); // 4 Unita' di misura
|
||
|
||
const TString& expr = _curr.get(RDIST_EXPR);
|
||
const real qta = evaluate_numexpr(expr);
|
||
_path << TREE_SEPARATOR << qta; // 5 Quantita'
|
||
_path << TREE_SEPARATOR << get_type(comp); // 6 - Articolo, Lavorazione, Virtuale, Ghost
|
||
|
||
push_vars();
|
||
return TRUE;
|
||
}
|
||
|
||
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)
|
||
return add_child();
|
||
return ok;
|
||
}
|
||
|
||
bool TDistinta_tree::has_rbrother() const
|
||
{
|
||
const int last = _path.items()-1;
|
||
if (last <= 0)
|
||
return FALSE;
|
||
|
||
TString80 key; _path.get(last-1, key);
|
||
isola_codice(key);
|
||
const TCodice_articolo father(key);
|
||
const int curr_nrig = curr_comp(key);
|
||
|
||
if (_sort != 0)
|
||
{
|
||
TArray children;
|
||
const int last = build_children_list(father, children)-1;
|
||
if (last > 0) // Ci sono almeno due fratelli
|
||
{
|
||
int c;
|
||
|
||
for (c = last; c >= 0; c--)
|
||
{
|
||
const int nrig = ((TToken_string*)children.objptr(c))->get_int(2);
|
||
if (nrig == curr_nrig)
|
||
break;
|
||
}
|
||
if (c >= 0 && c < last)
|
||
{
|
||
const int brother = ((TToken_string*)children.objptr(c+1))->get_int(2);
|
||
set_curr(father, brother);
|
||
}
|
||
else
|
||
set_curr(father, -1);
|
||
}
|
||
else
|
||
set_curr(father, -1);
|
||
}
|
||
else
|
||
{
|
||
set_curr(father, curr_nrig+1);
|
||
}
|
||
|
||
return !_curr.empty();
|
||
}
|
||
|
||
bool TDistinta_tree::goto_rbrother()
|
||
{
|
||
const bool ok = has_rbrother();
|
||
if (ok)
|
||
{
|
||
kill_child();
|
||
return add_child();
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TDistinta_tree::has_lbrother() const
|
||
{
|
||
const int last = _path.items()-1;
|
||
if (last <= 0)
|
||
return FALSE;
|
||
|
||
TString80 key; _path.get(last-1, key);
|
||
isola_codice(key);
|
||
const TCodice_articolo father(key);
|
||
const int curr_nrig = curr_comp(key);
|
||
|
||
if (_sort != 0)
|
||
{
|
||
TArray children;
|
||
const int last = build_children_list(father, children)-1;
|
||
if (last > 0) // Ci sono almeno due fratelli
|
||
{
|
||
int c = 0;
|
||
for (c = last; c > 0; c--)
|
||
{
|
||
const int nrig = ((TToken_string*)children.objptr(c))->get_int(2);
|
||
if (nrig == curr_nrig)
|
||
break;
|
||
}
|
||
if (c > 0)
|
||
{
|
||
const int brother = ((TToken_string*)children.objptr(c-1))->get_int(2);
|
||
set_curr(father, brother);
|
||
}
|
||
else
|
||
set_curr(father, -1); // reset
|
||
}
|
||
else
|
||
set_curr(father, -1); // reset
|
||
}
|
||
else
|
||
{
|
||
const int brother = curr_nrig - 1;
|
||
set_curr(father, brother);
|
||
}
|
||
|
||
return !_curr.empty();
|
||
}
|
||
|
||
bool TDistinta_tree::goto_lbrother()
|
||
{
|
||
const bool ok = has_lbrother();
|
||
if (ok)
|
||
{
|
||
kill_child();
|
||
return 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);
|
||
return !has_child_num(key, 1);
|
||
}
|
||
|
||
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);
|
||
const TString& desc = cache().get(LF_ANAMAG, code, ANAMAG_DESCR);
|
||
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);
|
||
const TString& desc = cache().get("LAV", code, "S0");
|
||
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 (has_child_num(c, 1)) // E' una distinta
|
||
{
|
||
const TString& artprod = find_head(c).get("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 = cache().get("VAR", var, "B0");
|
||
return vt.blank() ? _strexpr : _numexpr;
|
||
}
|
||
|
||
void TDistinta_tree::pop_vars()
|
||
{
|
||
_stack.pop();
|
||
}
|
||
|
||
bool TDistinta_tree::is_global(const char* var)
|
||
{
|
||
const char * gvars[] = {"_IMPIANTO","_LINEA",
|
||
"_MAGDEP","_MAGAZZINO","_DEPOSITO",
|
||
"_DISTINTA", "_RADICE",
|
||
"_LIVELLO","_LIV1","_LIV2","_LIV3", "_LIV4",
|
||
NULL};
|
||
const char ** gvar=gvars;
|
||
for (; *gvar; gvar++)
|
||
if (strcmp(*gvar, var)==0)
|
||
return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
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 (!val || ((TString *)val)->blank())
|
||
val = global_default_str(name);
|
||
}
|
||
else
|
||
{
|
||
if (!val || ((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("_MAGDEP",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;
|
||
}
|
||
if (strcmp(var, "_RADICE")==0)
|
||
{
|
||
TString & _codice = get_tmp_string();
|
||
_codice = _root;
|
||
isola_codice(_codice);
|
||
return _codice;
|
||
}
|
||
if (strncmp(var, "_LIV",4)==0)
|
||
{
|
||
switch (var[4])
|
||
{
|
||
case 'E': curr_giaclev(_varvalue); break;
|
||
case '1': curr_giaclev(_varvalue,1);break;
|
||
case '2': curr_giaclev(_varvalue,2);break;
|
||
case '3': curr_giaclev(_varvalue,3);break;
|
||
case '4': curr_giaclev(_varvalue,4);break;
|
||
}
|
||
return _varvalue;
|
||
}
|
||
if (strcmp(var, "_MAGAZZINO")==0 || strcmp(var, "_DEPOSITO")==0)
|
||
{
|
||
TString* val = (TString*)get_global("_MAGDEP", CLASS_STRING);
|
||
if (val)
|
||
{
|
||
_varvalue =* val;
|
||
switch (var[1])
|
||
{
|
||
case 'M': _varvalue.cut(3); break; // cod magazzino
|
||
case 'D': _varvalue = _varvalue.mid(3);break; // cod deposito
|
||
}
|
||
return _varvalue;
|
||
}
|
||
}
|
||
TObject* val = get_global(var, CLASS_STRING);
|
||
if (val)
|
||
return (const TString&)*val;
|
||
return EMPTY_STRING;
|
||
}
|
||
|
||
bool TDistinta_tree::exist(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)
|
||
return true;
|
||
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 true;
|
||
|
||
return false;
|
||
}
|
||
|
||
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();
|
||
}
|
||
|
||
|
||
bool TDistinta_tree::push_vars()
|
||
{
|
||
bool ok = TRUE;
|
||
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 = find_head(art).get("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 = (char*)strchr(str, '=');
|
||
if (equal)
|
||
{
|
||
*equal = '\0';
|
||
var = str; var.trim();
|
||
expr = equal + 1;
|
||
const TTypeexp exprtype = get_var_type(var);
|
||
if (e.set(expr, exprtype))
|
||
{
|
||
evaluate(e);
|
||
if (exprtype == _numexpr)
|
||
vars->add(var, e.as_real());
|
||
else
|
||
vars->add(var, e.as_string());
|
||
} else {
|
||
error_box("Errore nella distinta '%s'",(const char *)art);
|
||
ok = FALSE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
struct TExplosion_params
|
||
{
|
||
int _root_depth;
|
||
TArray* _array;
|
||
TString16 _filter;
|
||
int _raggruppa;
|
||
int _max_depth;
|
||
int _sort_key;
|
||
bool _materiali_base;
|
||
bool _ignore_ghost;
|
||
bool _stop_prod;
|
||
};
|
||
|
||
static bool explode_callback(TTree& node, void* jolly, word when)
|
||
{
|
||
if (when == SCAN_PRE_ORDER)
|
||
{
|
||
const TExplosion_params& ep = *(const TExplosion_params*)jolly;
|
||
|
||
TDistinta_tree& tree = (TDistinta_tree&)node;
|
||
|
||
if (tree.is_root())
|
||
return FALSE; // Don't explode root
|
||
|
||
const bool is_leaf = tree.is_leaf();
|
||
TCodice_articolo art; tree.curr_code(art);
|
||
const char type = tree.curr_type();
|
||
static long stop_depth = -1;
|
||
const int curr_depth = tree.curr_depth();
|
||
|
||
if (ep._materiali_base)
|
||
{
|
||
bool is_prod = FALSE;
|
||
if (ep._stop_prod)
|
||
{
|
||
if (stop_depth > 0)
|
||
{
|
||
if (curr_depth > stop_depth)
|
||
return FALSE;
|
||
else
|
||
stop_depth = -1;
|
||
}
|
||
if (stop_depth < 0)
|
||
{
|
||
is_prod = (type == 'A') && cache().get(LF_ANAMAG, art).get_bool(ANAMAG_ARTPROD);
|
||
if (is_prod)
|
||
stop_depth = curr_depth ;
|
||
}
|
||
}
|
||
|
||
if (!is_leaf && !is_prod)
|
||
{
|
||
if (ep._max_depth <= 0 || curr_depth < ep._max_depth)
|
||
return FALSE; // Please, leaves only
|
||
}
|
||
}
|
||
|
||
if (is_leaf)
|
||
{
|
||
if (art == "???")
|
||
return FALSE;
|
||
}
|
||
|
||
if (ep._sort_key > 0) // Se sort_key <= 0 accetta tutto comunque
|
||
{
|
||
const long sk = tree.curr_sort();
|
||
if (sk <= 0)
|
||
return false; // Non fa parte dell'ordinamento
|
||
}
|
||
|
||
if (ep._filter.find(type) < 0)
|
||
return false;
|
||
|
||
TRiga_esplosione* er = new TRiga_esplosione(tree, ep._filter.find('G') >= 0, tree.curr());
|
||
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& row1 = (TRiga_esplosione&)boom[i];
|
||
|
||
if (mode == RAGGR_EXP_UMBASE || mode == RAGGR_EXP_BASE)
|
||
row1.convert2umbase(); else
|
||
if (mode == RAGGR_EXP_UMDIST || mode == RAGGR_EXP_DIST)
|
||
row1.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& row2 = (TRiga_esplosione&)boom[j];
|
||
if (row1.articolo() != row2.articolo())
|
||
continue;
|
||
|
||
if (mode == RAGGR_EXP_EACHUM && row1.um() != row2.um())
|
||
continue;
|
||
|
||
row1 += row2;
|
||
boom.destroy(j, true);
|
||
}
|
||
}
|
||
}
|
||
/* if (mode == RAGGR_EXP_UMBASE ||
|
||
mode == RAGGR_EXP_UMDIST ||
|
||
mode == RAGGR_EXP_EACHUM)
|
||
{
|
||
for (int i = 0; i < boom.items(); i++)
|
||
{
|
||
TRiga_esplosione& row = (TRiga_esplosione&)boom[i];
|
||
|
||
if (row.path().find("00.73.00.0030") > 0)
|
||
int i = 1;
|
||
if (row.path().find("00.73.00.0028") > 0)
|
||
int i = 1;
|
||
if (row.curr_qta() == ZERO)
|
||
boom.destroy(i,true);
|
||
}
|
||
} */
|
||
return boom.items();
|
||
}
|
||
|
||
int TDistinta_tree::explode(TArray& boom,
|
||
bool mb, TExplosion_grouping gr, int md,
|
||
const char* filter, int sk, bool sp)
|
||
{
|
||
const int old_sk = get_sort_key();
|
||
const int old_md = get_max_depth();
|
||
const bool old_iv = get_ignore_ghost();
|
||
const bool old_sp = get_stop_prod();
|
||
|
||
TExplosion_params ep;
|
||
ep._root_depth = curr_depth();
|
||
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;
|
||
ep._stop_prod = sp;
|
||
|
||
set_sort_key (abs(ep._sort_key)); // Sort key puo' essere negativa per includere anche quelli senza!
|
||
set_max_depth(ep._max_depth);
|
||
set_ignore_ghost(ep._ignore_ghost);
|
||
set_stop_prod(ep._stop_prod);
|
||
|
||
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);
|
||
set_stop_prod(old_sp);
|
||
|
||
if (gr != RAGGR_EXP_NONE)
|
||
raggruppa(boom, gr);
|
||
|
||
return boom.items();
|
||
}
|
||
|
||
TCodgiac_livelli &TDistinta_tree::livgiac() const
|
||
{
|
||
if (_livgiac==NULL)
|
||
((TDistinta_tree *)this)->_livgiac = new TCodgiac_livelli();
|
||
return *_livgiac;
|
||
}
|
||
TDistinta_tree::TDistinta_tree()
|
||
: _sort(0), _max_depth(0), _ignore_ghost(FALSE),
|
||
_livgiac(NULL),_qta_on_descr(FALSE),_descr_sep('-'),
|
||
_tmp(80, TREE_SEPARATOR), _curr(LF_RDIST)
|
||
{
|
||
memset(_livgiac_on_descr, 0, sizeof(_livgiac_on_descr));
|
||
}
|
||
|
||
TDistinta_tree::~TDistinta_tree()
|
||
{
|
||
if (_livgiac)
|
||
delete _livgiac;
|
||
}
|
||
|
||
TRiga_esplosione *TDistinta_tree::first_critical_labor(TArray & labors, TExplosion_grouping raggum)
|
||
{
|
||
TRiga_esplosione *l=first_labor(labors, raggum);
|
||
while (l)
|
||
{
|
||
TLavorazione labor(l->articolo());
|
||
for (int lnp=0 ; lnp < labor.linee();lnp++)
|
||
{
|
||
if (!cache().get("LNP",labor.cod_linea(lnp)).get_bool("B9"))
|
||
// escluso dal CRP
|
||
return l;
|
||
}
|
||
l=(TRiga_esplosione *)labors.succ_item();
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
TRiga_esplosione *TDistinta_tree::next_critical_labor(TArray & labors)
|
||
{
|
||
return next_labor(labors);
|
||
}
|
||
|
||
|
||
TRiga_esplosione *TDistinta_tree::first_labor(TArray & labors, TExplosion_grouping raggum)
|
||
{
|
||
explode(labors,FALSE,raggum, 1,"L");
|
||
TRiga_esplosione *l=(TRiga_esplosione *)labors.first_item();
|
||
return l;
|
||
}
|
||
|
||
TRiga_esplosione *TDistinta_tree::next_labor(TArray & labors)
|
||
{
|
||
if (labors.items()==0)
|
||
return NULL;
|
||
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, bool vis_ghost, const TRectype* rec)
|
||
{
|
||
tree.curr_code(_comp); _comp.trim();
|
||
tree.father_code(_dist); _dist.trim();
|
||
TCodice_um um; tree.curr_um(um);
|
||
real val = tree.curr_qta();
|
||
set(_comp, um, val);
|
||
_last_qta = tree.last_qta(vis_ghost); // Puo' sempre servire anche questa
|
||
_curr_qta = tree.curr_qta();
|
||
tree.curr_giaclev(_giac);
|
||
_tipo = tree.curr_type();
|
||
_sort = tree.curr_sort();
|
||
_mat_base = false;
|
||
// set path and code
|
||
tree.curr_id(_path); // path
|
||
if (rec != NULL)
|
||
_rdist = new TRectype(*rec);
|
||
else
|
||
_rdist = NULL;
|
||
}
|
||
|
||
const char * TRiga_esplosione::father(const char * types) const
|
||
{
|
||
TString & _tmp_path = get_tmp_string();
|
||
|
||
_tmp_path = _path;
|
||
while (TRUE)
|
||
{
|
||
const int index = _tmp_path.rfind('|');
|
||
if (index == -1)
|
||
return "";
|
||
else
|
||
{
|
||
_tmp_path.cut(index);
|
||
char type = _tmp_path[index-1];
|
||
if (types == NULL || strchr(types, type))
|
||
break;
|
||
}
|
||
}
|
||
return _tmp_path;
|
||
}
|
||
|
||
TRiga_esplosione::TRiga_esplosione(const TDistinta_tree& tree, bool vis_ghost, const TRectype * rec)
|
||
{
|
||
init(tree, vis_ghost, rec);
|
||
}
|
||
|
||
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;
|
||
_last_qta = re._last_qta;
|
||
_curr_qta = re._curr_qta;
|
||
if (re._rdist != NULL)
|
||
_rdist = new TRectype(*re._rdist);
|
||
else
|
||
_rdist = NULL;
|
||
|
||
}
|
||
|
||
TRiga_esplosione::TRiga_esplosione()
|
||
: TQuantita()
|
||
{
|
||
_tipo = '\0';
|
||
_sort = 0L;
|
||
_mat_base = FALSE;
|
||
_rdist = NULL;
|
||
}
|
||
|
||
TUm_tempo::TUm_tempo(char c)
|
||
{
|
||
switch (c)
|
||
{
|
||
case 'M': // minutes
|
||
_ore=1.0/60.0;
|
||
break;
|
||
case 'S': // seconds
|
||
_ore=1.0/3600.0;
|
||
break;
|
||
case 'H': // hours
|
||
default:
|
||
_ore=1.0;
|
||
break;
|
||
}
|
||
}
|
||
|