1942 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1942 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 "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") / 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);
 | 
						||
	key.add(curr_comp(code));
 | 
						||
	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& 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, 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;
 | 
						||
  }
 | 
						||
}
 | 
						||
 |