#include #include #include #include #include #include "tabutil.h" #include "dblib.h" #include "../mg/anamag.h" #include "../mg/umart.h" #include "../mg/rmovmag.h" #include "../include/rdoc.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

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

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 è 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); 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 { 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 = find_child(qta.articolo(), 1) != NULL; 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 = find_child(art, 1) != NULL; 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.empty() ? NULL : &rec; } 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) 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::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); _curr = find_child(key, 1); // Se ci sono almeno due figli ed e' necessario ordinare if (_sort != 0 && find_child(key, 2) != NULL) { TArray children; build_children_list(key, children); const int first = ((TToken_string*)children.objptr(0))->get_int(2); _curr = find_child(key, first); } return _curr != NULL; } 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("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("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("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("UM"); // 4 Unita' di misura const TString& expr = _curr->get("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); _curr = find_child(father, brother); } else _curr = NULL; } else _curr = NULL; } else { _curr = find_child(father, curr_nrig+1); } return _curr != NULL; } 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; 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); _curr = find_child(father, brother); } else _curr = NULL; } else _curr = NULL; } else { const int brother = curr_nrig - 1; if (brother > 0) _curr = find_child(father, brother); else _curr = NULL; } return _curr != NULL; } 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); const TRectype* first_son = find_child(key, 1); return first_son == NULL; } bool TDistinta_tree::is_mag(const char* c) const { TCodice_articolo code = c; if (code.blank()) curr_code(code); // const TString& desc = ((TDistinta_tree*)this)->_mag.decode(code); 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 (find_child(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) { 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 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) { 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; 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; } }