#include #include #include #include #include #include #include #include "dblib.h" #include "db1300a.h" #include "db0500a.h" /////////////////////////////////////////////////////////// // TXmas_tree /////////////////////////////////////////////////////////// class TXmas_tree : public TDistinta_tree { TIsamtempfile *_dist, *_rdist; TRecord_cache *_cache_dist, *_cache_rdist; protected: virtual const TRectype& find_head(const TCodice_articolo& art) const; virtual const TRectype* find_child(const TCodice_articolo& art, int child) const; public: bool add_head(const TCodice_articolo& art); bool add_child(const TRectype& rec); void add_branch(TDistinta_tree& dt); TXmas_tree(); virtual ~TXmas_tree(); }; HIDDEN bool _ignore_zero = TRUE; const TRectype& TXmas_tree::find_head(const TCodice_articolo& art) const { const TRectype& rec = _cache_dist->get(art); return rec; } const TRectype* TXmas_tree::find_child(const TCodice_articolo& art, int child) const { TString80 key; key.format("%s|%d", (const char*)art, child); const TRectype& rec = _cache_rdist->get(key); return rec.empty() ? NULL : &rec; } bool TXmas_tree::add_head(const TCodice_articolo& art) { bool added = FALSE; if (find_head(art).empty()) { TRectype& rec = _dist->curr(); rec = cache().get(LF_DIST, art); if (rec.empty()) rec.put("CODDIST", art); const int err = rec.write(*_dist); _cache_dist->discard(art); added = err == NOERR; } return added; } bool TXmas_tree::add_child(const TRectype& rec) { int err = rec.write(*_rdist); return err == NOERR; } void TXmas_tree::add_branch(TDistinta_tree& dt) { TString old_node; dt.curr_id(old_node); // Memorizza posizione while (dt.has_father()) { const real qta = dt.last_qta(); if (::_ignore_zero && qta.is_zero()) break; // Inutile proseguire TCodice_um um; dt.curr_um(um); TCodice_articolo art; dt.curr_code(art); add_head(art); dt.goto_father(); TCodice_articolo father; dt.curr_code(father); TString80 level; dt.curr_giaclev(level); const TRectype* child = NULL; int c; for (c = 1; ; c++) { child = find_child(art, c); if (child == NULL) break; if (child->get("CODCOMP") != father) continue; if (!level.blank() && child->get("LIVELLO") != level) continue; if (child->get_real("EXPR") == qta) break; } if (child == NULL) { TRectype& curr = _rdist->curr(); curr.put("CODDIST", art); curr.put("NRIG", c); curr.put("TIPO", "A"); curr.put("CODCOMP", father); curr.put("LIVELLO", level); curr.put("UM", um); curr.put("EXPR", qta); int err = curr.write(*_rdist); TString k; k.format("%s|%d", (const char *) art, c); _cache_rdist->discard(k); CHECKD(err == NOERR, "Rdist write error ", err); } } dt.goto_node(old_node); // Ripristina posizione } TXmas_tree::TXmas_tree() { _dist = new TIsamtempfile(LF_DIST, NULL, TRUE, TRUE); _cache_dist = new TRecord_cache(_dist); _cache_dist->test_file_changes(TRUE); _rdist = new TIsamtempfile(LF_RDIST, NULL, TRUE, TRUE); _cache_rdist = new TRecord_cache(_rdist); _cache_rdist->test_file_changes(TRUE); set_qta_on_descr(TRUE); // Stampa anche le quantita } TXmas_tree::~TXmas_tree() { // I file temporanei vengono cancellati dai distruttori // delle record cache che li contengono delete _cache_dist; delete _cache_rdist; } /////////////////////////////////////////////////////////// // TDistinta_sheet /////////////////////////////////////////////////////////// class TDistinta_sheet : public TSheet { TCodgiac_livelli _livgiac; TArray _data; protected: virtual void get_row(long n, TToken_string& row); virtual long get_items() const { return _data.items(); } public: TArray& rows_array() { return _data; } TDistinta_sheet(int numlev); virtual ~TDistinta_sheet() { } }; void TDistinta_sheet::get_row(long n, TToken_string& row) { const TRiga_esplosione& re = (const TRiga_esplosione&)_data[int(n)]; row.cut(0); row.add(re.tipo()); row.add(re.articolo()); if (_livgiac.enabled(1)) row.add(_livgiac.unpack_grpcode(re.giacenza(),1)); if (_livgiac.enabled(2)) row.add(_livgiac.unpack_grpcode(re.giacenza(),2)); if (_livgiac.enabled(3)) row.add(_livgiac.unpack_grpcode(re.giacenza(),3)); if (_livgiac.enabled(4)) row.add(_livgiac.unpack_grpcode(re.giacenza(),4)); row.add(re.um()); row.add(re.val().string(0, 5)); row.add(re.livello()); row.add(re.ordinamento()); } TDistinta_sheet::TDistinta_sheet(int numlev) : TSheet(-1, -1, 76, 20, TR("Implosione"), numlev == 4 ? HR("Tipo|Codice@20|Liv.1@10|Liv.2@6|Liv.3@6|Liv.4@6|UM|Quantita'@18R|Liv.@R|Sort@8R") : numlev == 3 ? HR("Tipo|Codice@20|Liv.1@10|Liv.2@6|Liv.3@6|UM|Quantita'@18R|Liv.@R|Sort@8R") : numlev == 2 ? HR("Tipo|Codice@20|Liv.1@10|Liv.2@6|UM|Quantita'@18R|Liv.@R|Sort@8R") : numlev == 1 ? HR("Tipo|Codice@20|Liv.1@10|UM|Quantita'@18R|Liv.@R|Sort@8R") : HR("Tipo|Codice@20|UM|Quantita'@18R|Liv.@R|Sort@8R")) { } /////////////////////////////////////////////////////////// // Display_mask /////////////////////////////////////////////////////////// class TDisplay_mask : public TAutomask { TAssoc_array& _xmas; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void print_tree(TXmas_tree& tree); public: TDisplay_mask(TAssoc_array& xmas); virtual ~TDisplay_mask() { } }; static bool print_node(TTree& t, void* p, word flags) { TXmas_tree& tree = (TXmas_tree&)t; TBit_array& righette = *(TBit_array*)p; const int depth = tree.curr_depth(); const int tab = (depth-1)*3; TString descr; tree.get_description(descr); TPrintrow row; if (tab >= 0) row.put("+--", tab); row.put(descr); for (int d = 1; d < depth; d++) if (righette[d]) row.put("!", (d-1)*3); printer().print(row); righette.set(depth, tree.has_rbrother()); return FALSE; } void TDisplay_mask::print_tree(TXmas_tree& tree) { TPrinter& p = printer(); p.resetheader(); p.resetfooter(); TCodice_articolo art; TString descr; tree.goto_root(); tree.curr_code(art); tree.describe(art, descr); TPrintrow header; header.put(FR("@bSTAMPA IMPLOSIONE ")); header.put(art); header.put(" - "); header.put(descr); p.setheaderline(0, header); p.setheaderline(1, NULL); TPrintrow footer; footer.put(FR("Pag.@#"), 36); p.setfooterline(0, NULL); p.setfooterline(1, footer); p.setfooterline(2, NULL); p.open(); TBit_array righette; tree.scan_depth_first(print_node, &righette); p.formfeed(); p.close(); } bool TDisplay_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODICE: if (e == fe_modify) { TTree_field& tf = tfield(F_TREE); const int code = atoi(o.get()); TXmas_tree* tree = (TXmas_tree*)_xmas.first_item(); for (int i = 1; i < code; i++) tree = (TXmas_tree*)_xmas.succ_item(); if (tf.tree() != tree) { tf.set_tree(tree); tf.win().force_update(); } } break; case F_EXPLODE: if (e == fe_button) { TXmas_tree* t = (TXmas_tree*)tfield(F_TREE).tree(); if (t && t->goto_root()) { TXmas_tree& tree = *t; TCodice_articolo art; tree.curr_code(art); TString80 caption; caption << TR("Lista d'implosione ") << art; TMask m("db0500c"); m.set_caption(caption); m.set(F_ARTICOLI, "X"); m.set(F_LAVORAZIONI, "X"); m.set(F_VIRTUALI, "X"); if (m.run() == K_ENTER) { TCodgiac_livelli livgiac; TDistinta_sheet a(livgiac.last_level()); a.set_caption(caption); int sk = m.get_int(F_SORT); int md = m.get_int(F_MAXDEPTH); TExplosion_grouping gr = TExplosion_grouping(m.get_int(F_GROUPMODE)); bool mb = m.get_bool(F_MATBASE); TString16 fi; if (m.get_bool(F_ARTICOLI)) fi << 'A'; if (m.get_bool(F_LAVORAZIONI)) fi << 'L'; if (m.get_bool(F_VIRTUALI)) fi << 'V'; if (m.get_bool(F_GHOST)) fi << 'G'; if (tree.goto_root()) { TIndwin iw(0, TR("Elaborazione in corso..."), FALSE, FALSE); tree.explode(a.rows_array(), mb, gr, md, fi, sk); } a.run(); } } } break; case DLG_PRINT: if (e == fe_button) { TXmas_tree* t = (TXmas_tree*)tfield(F_TREE).tree(); if (t) print_tree(*t); return FALSE; // Non chiudere la maschera! } break; default: break; } return TRUE; } TDisplay_mask::TDisplay_mask(TAssoc_array& xmas) : TAutomask("db1300b"), _xmas(xmas) { TTree_field& tf = tfield(F_TREE); TList_sheet* ls = efield(F_CODICE).sheet(); TString_array& rows = ls->rows_array(); rows.destroy(); TString16 code; TString str; TToken_string disp; int i = 0; FOR_EACH_ASSOC_OBJECT(_xmas, obj, key, item) if (item != NULL) { code.format("%03d", ++i); disp = key; disp.replace('|', ' '); disp.insert("|", 0); disp.insert(code, 0); TXmas_tree* albero = (TXmas_tree*)item; albero->goto_root(); albero->get_description(str); disp.add(str); rows.add(disp); if (item && tf.tree() == NULL) { tf.set_tree(albero); set(F_CODICE, code); } } } /////////////////////////////////////////////////////////// // Implosion_mask /////////////////////////////////////////////////////////// class TImplosion_mask : public TAutomask { TAssoc_array _xmas; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); int find_roots(const char* articolo, TAssoc_array& roots) const; void implode_slow(); void implode_medium(); void implode_fast(); public: void implode(); void display(); TImplosion_mask(); virtual ~TImplosion_mask(); }; bool TImplosion_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { return TRUE; } HIDDEN bool implode_callback(TTree& tree, void* jolly, word flags) { if (flags == SCAN_PRE_ORDER) { TDistinta_tree& dt = (TDistinta_tree&)tree; TAssoc_array* a = (TAssoc_array*)jolly; TCodice_articolo code; dt.curr_code(code); if (a->is_key(code)) // Cerca articolo senza livello { TXmas_tree* x = (TXmas_tree*)a->objptr(code); if (x == NULL) { x = new TXmas_tree; a->add(code, x, TRUE); } x->add_branch(dt); } TString80 curliv; dt.curr_giaclev(curliv); if (!curliv.blank()) { TString80 key = code; key << '|' << curliv; if (a->is_key(key)) { TXmas_tree* x = (TXmas_tree*)a->objptr(key); if (x == NULL) { x = new TXmas_tree; a->add(key, x, TRUE); } x->add_branch(dt); } } } return FALSE; } int TImplosion_mask::find_roots(const char* articolo, TAssoc_array& roots) const { TRelation rel(LF_RDIST); TCursor cur(&rel, "", 2); TRectype only(LF_RDIST); TAssoc_array ass[2]; int c = 0; // Array dei children = 0; fathers = 1 ass[c].add(articolo, NULL); const char* cap = FR("Livello %d - Articoli %ld"); TString caption; caption.format(cap, 0, 0L); TIndwin iw(0, caption, TRUE, FALSE); for (int loop = 0; ass[c].items() > 0 && loop < 50; loop++) { if (iw.iscancelled()) break; caption.format(cap, loop, ass[c].items()); iw.set_text(caption); FOR_EACH_ASSOC_OBJECT(ass[c], obj, key, item) { only.put("CODCOMP", key); cur.setregion(only, only); const TRecnotype items = cur.items(); if (items > 0) { cur.freeze(TRUE); for (cur = 0L; cur.pos() < cur.items(); ++cur) { const TString& father = cur.curr().get("CODDIST"); ass[!c].add(father, NULL); } cur.freeze(FALSE); } else roots.add(key); } ass[c].destroy(); // Distruggi i children c = !c; // Scambia i children coi fathers } return roots.items(); } void TImplosion_mask::implode_slow() { TRelation rel(LF_DIST); TRectype dist_f(LF_DIST), dist_t(LF_DIST); dist_f.put("CODDIST", get(F_DA_ARTICOLO)); dist_t.put("CODDIST", get(F_AD_ARTICOLO)); TCursor cur(&rel, "", 1, &dist_f, &dist_t); long items = 0; if (get_bool(F_USECATMER)) { rel.add(LF_ANAMAG, "CODART==CODDIST"); TString filter; for (int f = 0; f < 2; f++) { const TString& cm = get(F_DA_CATMER+f); const int cmlen = cm.len(); if (cmlen > 0) { if (filter.not_empty()) filter << "&&"; filter << '(' << LF_ANAMAG << "->" << ANAMAG_GRMERC; if (cmlen < 5) filter << "[1," << cmlen << ']'; filter << (f ? '<' : '>') << "=\"" << cm << "\")"; } } cur.setfilter(filter, TRUE); TIndwin iw(0, TR("Creazione lista articoli da esplodere..."), FALSE, FALSE); items = cur.items(); } else { TWait_cursor hourglass; items = cur.items(); } cur.freeze(); TString caption; caption << TR("Esplosione di ") << items << TR(" articoli in corso..."); TProgind pi(items, caption, TRUE, TRUE); TSheet_field& vars = sfield(F_VARS); if (vars.items() == 0) vars.row(-1); // Crea almeno una riga vuota const TRectype& curr = cur.curr(); TCodice_articolo articolo; TString livello; TCodgiac_livelli livgiac; TDistinta_tree dt; TSheet_field& a = sfield(F_ARTS); TString80 key; FOR_EACH_SHEET_ROW(a, r, row) { key = row->get(1); if (!key.blank()) { if (row->get_char(3) > ' ') { key << '|' << row->get(3); key << row->get(); key << row->get(); key << row->get(); key.rtrim(); } _xmas.add(key, NULL); } } for (cur = 0L; cur.pos() < items; ++cur) { #ifdef DBG if (pi.addstatus(1)) { unsigned long h, m; TFile_cache::stats(h, m); TString80 msg; msg.format("Hits %lu - Misses %lu", h, m); xvtil_statbar_set(msg); } #else pi.addstatus(1); #endif if (pi.iscancelled()) break; // Scansione di tutte le righe abilitate FOR_EACH_SHEET_ROW(vars, r, row) { dt.clear_globals(); dt.set_global("_IMPIANTO", row->get(0)); dt.set_global("_LINEA", row->get(1)); dt.set_global("_MAGAZZINO", row->get(2)); dt.set_global("_DEPOSITO", row->get(3)); vars.check_row(r); livgiac.pack_maskgrpcodes(livello, vars.sheet_mask(), 105, 4); articolo = curr.get("CODDIST"); dt.set_root(articolo, "", 1.0, livello); dt.scan_depth_first(implode_callback, &_xmas); } } } void TImplosion_mask::implode_medium() { const TCodice_articolo da_art = get(F_DA_ARTICOLO); const TCodice_articolo ad_art = get(F_AD_ARTICOLO); TSheet_field& a = sfield(F_ARTS); FOR_EACH_SHEET_ROW(a, r, row) { const TCodice_articolo articolo = row->get(1); if (articolo.blank()) continue; TString livello; if (row->get_char(3) > ' ') { livello = row->get(3); livello << row->get(); livello << row->get(); livello << row->get(); livello.rtrim(); } TString key; key = articolo; if (livello.not_empty()) key << '|' << livello; _xmas.add(key, NULL); TAssoc_array roots; const long items = find_roots(articolo, roots); if (items > 0) { TString caption; caption << TR("Esplosione di ") << items << TR(" articoli in corso..."); TProgind pi(items, caption, TRUE, TRUE); TSheet_field& vars = sfield(F_VARS); if (vars.items() == 0) vars.row(-1); // Crea almeno una riga vuota TDistinta_tree dt; TCodgiac_livelli livgiac; FOR_EACH_ASSOC_OBJECT(roots, obj, key, item) { if (pi.addstatus(1)) { #ifdef DBG unsigned long h, m; TFile_cache::stats(h, m); TString80 msg; msg.format("Hits %lu - Misses %lu", h, m); xvtil_statbar_set(msg); #endif } else break; const TCodice_articolo articolo = key; if (articolo < da_art) continue; if (ad_art.not_empty() && articolo > ad_art) continue; // Scansione di tutte le righe abilitate FOR_EACH_SHEET_ROW(vars, r, row) { dt.clear_globals(); dt.set_global("_IMPIANTO", row->get(0)); dt.set_global("_LINEA", row->get(1)); dt.set_global("_MAGAZZINO", row->get(2)); dt.set_global("_DEPOSITO", row->get(3)); vars.check_row(r); livgiac.pack_maskgrpcodes(livello, vars.sheet_mask(), 105, 4); dt.set_root(articolo, "", 1.0, livello); dt.scan_depth_first(implode_callback, &_xmas); } } } } } void TImplosion_mask::implode_fast() { TRelation rel(LF_RDIST); TRectype only(LF_RDIST); TSheet_field& a = sfield(F_ARTS); FOR_EACH_SHEET_ROW(a, r, row) { const TCodice_articolo articolo = row->get(1); if (articolo.blank()) continue; TString livello; if (row->get_char(3) > ' ') { livello = row->get(3); livello << row->get(); livello << row->get(); livello << row->get(); livello.rtrim(); } only.put("CODCOMP", articolo); TCursor cur(&rel, "", 2, &only, &only); const TRecnotype items = cur.items(); if (items > 0) { cur.freeze(); TXmas_tree* tree = new TXmas_tree; int child = 0; for (cur = 0L; cur.pos() < items; ++cur) { TRectype& curr = cur.curr(); if (livello.not_empty() && curr.get("LIVELLO") != livello) continue; const TCodice_articolo father = curr.get("CODDIST"); curr.put("CODDIST", articolo); curr.put("NRIG", ++child); curr.put("TIPO", "A"); curr.put("CODCOMP", father); tree->add_child(curr); } if (child > 0) { tree->add_head(articolo); tree->set_root(articolo); TString80 key = articolo; if (livello.not_empty()) key << '|' << livello; _xmas.add(key, tree); } else delete tree; } } } void TImplosion_mask::implode() { _xmas.destroy(); _ignore_zero = !get_bool(F_DISPLAY_ZERO); if (get_bool(F_FASTIMPLODE)) { if (get_bool(F_ONLYONE)) implode_fast(); else implode_medium(); } else implode_slow(); TProgind pi(_xmas.items(), TR("Espansione albero di implosione...")); TCodice_articolo articolo; TString livello; FOR_EACH_ASSOC_OBJECT(_xmas, obj, key, item) if (item != NULL) { pi.addstatus(1); TToken_string row(key); articolo = row.get(0); livello = row.get(); TXmas_tree* x = (TXmas_tree*)item; x->set_root(articolo, "", 1.0, livello); x->expand_all(); } } void TImplosion_mask::display() { TDisplay_mask* m = new TDisplay_mask(_xmas); m->run(); delete m; } TImplosion_mask::TImplosion_mask() : TAutomask("db1300a") { TCodgiac_livelli liv; TSheet_field& a = sfield(F_ARTS); liv.set_sheet_columns(a, F_LEV1); a.row(0); TSheet_field& v = sfield(F_VARS); liv.set_sheet_columns(v, 105); v.row(0); } TImplosion_mask::~TImplosion_mask() { } /////////////////////////////////////////////////////////// // Implosion Application /////////////////////////////////////////////////////////// class TImplosion : public TSkeleton_application { TImplosion_mask* _impl; public: virtual bool create(); virtual void main_loop(); virtual bool destroy(); void reset_tree(); }; bool TImplosion::create() { open_files(LF_TAB, LF_TABCOM, LF_DIST, LF_RDIST, LF_ANAMAG, LF_UMART, NULL); _impl = new TImplosion_mask; // Inutile testare i cambiamenti dei file rec_cache(LF_TAB).test_file_changes(FALSE); const int lf[] = { LF_UMART, LF_ANAMAG, LF_DIST, LF_RDIST, 0 }; for (int i = 0; lf[i]; i++) { int maxsize = 4096; if (lf[i] == LF_RDIST) maxsize *= 4; rec_cache(lf[i]).set_items_limit(maxsize); rec_cache(lf[i]).test_file_changes(FALSE); } return TSkeleton_application::create(); } void TImplosion::main_loop() { while (_impl->run() != K_QUIT) { _impl->implode(); _impl->display(); } } bool TImplosion::destroy() { delete _impl; return TSkeleton_application::destroy(); } int db1300(int argc, char* argv[]) { TImplosion bum; bum.run(argc, argv, TR("Implosione")); return 0; }