#include "dblib.h" #include #include #include #include #include "../mg/mglib.h" #include "../mg/anamag.h" #include "db0100a.h" /////////////////////////////////////////////////////////// // Funzione di richiesta stringa che andra' in libreria /////////////////////////////////////////////////////////// #include bool query_string(const char* prompt, TString& str, int width = 50, const char* flags= "") { int maskwidth = width+2; if (maskwidth < 26) maskwidth = 26; if (maskwidth > 78) maskwidth = 78; TMask m(prompt, 1, maskwidth, 5); m.add_string(DLG_USER, 0, "", 1, 1, width, flags, width > 76 ? 76 : width); m.add_button(DLG_CANCEL, 0, "", -12, -1, 10, 2); m.add_button(DLG_OK, 0, "", -22, -1, 10, 2); m.set(DLG_USER, str); bool ok = m.run() == K_ENTER; if (ok) str = m.get(DLG_USER); return ok; } /////////////////////////////////////////////////////////// // TDistinta_sheet /////////////////////////////////////////////////////////// class TDistinta_sheet : public TSheet { 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(); 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()); row.add(re.giacenza()); row.add(re.um()); row.add(re.val().string(0, 5)); row.add(re.livello()); row.add(re.ordinamento()); } TDistinta_sheet::TDistinta_sheet() : TSheet(-1, -1, 0, 20, "Esplosione", "Tipo|Codice@20|Giacenza@15|UM|Quantita'@18R|Liv.@R|Sort@8R") { } /////////////////////////////////////////////////////////// // TQuery_mask /////////////////////////////////////////////////////////// class TQuery_mask : public TAutomask { TDistinta_tree& _tree; TToken_string _curr; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: const TToken_string& curr() const { return _curr; } void restart_tree(); TQuery_mask(TDistinta_tree& tree); virtual ~TQuery_mask() { } }; void TQuery_mask::restart_tree() { _tree.restart(); while (!_tree.is_leaf()) { _tree.expand(); _tree.goto_firstson(); if (_tree.has_rbrother()) break; } TTree_field& tf = tfield(F_TREE); tf.win().update_thumb(0, 0); tf.win().force_update(); } bool TQuery_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 TCodice_articolo val = o.get(); if (val.not_empty() && _tree.has_root()) { long pos = _tree.find_node(val); if (pos <= 0) { if (_tree.set_root(val)) pos = 1; } if (pos > 0) { tf.select_current(); do { _tree.expand(); } while (_tree.goto_father()); pos = _tree.find_node(val, SCAN_PRE_ORDER | SCAN_IGNORING_UNEXPANDED); TField_window& win = tf.win(); const TPoint& range = win.range(); if (pos > range.y) win.set_scroll_max(win.columns(), pos+win.rows()); win.update_thumb(-1, pos-1); win.force_update(); tf.set_focus(); } } else { _tree.set_root(val); } tf.win().force_update(); } case F_SORT: if (e == fe_init || e == fe_modify) { int sk = atoi(o.get()); _tree.set_sort_key(sk); if (e == fe_modify) restart_tree(); } break; case F_TREE: if (e == fe_modify) { _tree.curr_id(_curr); TCodice_articolo code; _tree.curr_code(code); set(F_CODICE, code); } break; case DLG_SELECT: if (e == fe_button) { const TString& str = get(F_CODICE); if (str.not_empty()) set(F_CODICEQ, str); else return FALSE; } break; case F_COPY: if (e == fe_button) { const TString oldcode = get(F_CODICE); TLocalisamfile dist(LF_DIST); dist.put("CODDIST", oldcode); if (dist.read() == NOERR) { TString newcode; if (query_string("Nuovo codice", newcode, 20, "U")) { if (newcode.not_empty() && newcode != oldcode) { dist.put("CODDIST", newcode); const int err = dist.write(); if (err == NOERR) { TRecord_array rdist(LF_RDIST, "NRIG"); rdist.renum_key("CODDIST", oldcode); if (rdist.read(rdist.key()) == NOERR) { rdist.renum_key("CODDIST", newcode); rdist.write(); } } else { if (err == _isreinsert) error_box("La distinta '%s' e' gia' stata inserita", (const char*)newcode); else error_box("Errore %d durante la registrazione della distinta '%s'", err, (const char*)newcode); } } } } else error_box("Il codice '%s' non corrisponde ad una distinta valida", (const char*)oldcode); } break; case F_EXPLODE: if (e == fe_button) { TCodice_articolo art = get(F_CODICE); if (art.not_empty()) { _tree.set_root(art); restart_tree(); } if (_tree.goto_root()) { _tree.curr_code(art); TString80 caption; caption << "Esplosione " << art; TMask m("db0100c"); m.set_caption(caption); m.set(F_SORT, get(F_SORT)); m.set(F_ARTICOLI, "X"); m.set(F_LAVORAZIONI, "X"); m.set(F_VIRTUALI, "X"); if (m.run() == K_ENTER) { TDistinta_sheet a; a.set_caption(caption); int sk = m.get_int(F_SORT); int md = m.get_int(F_MAXDEPTH); int gr = m.get_int(F_GROUPMODE); bool mb = m.get_bool(F_MATBASE); bool lq = m.get_bool(F_LASTQTA); 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 (fi.len() == 3) fi.cut(0); _tree.explode(a.rows_array(), mb, gr, md, fi, sk, lq); a.run(); } } } break; default: break; } return TRUE; } TQuery_mask::TQuery_mask(TDistinta_tree& dt) : TAutomask("db0100a"), _tree(dt) { TTree_field& tree = tfield(F_TREE); tree.set_tree(&_tree); } /////////////////////////////////////////////////////////// // TDistinta_mask /////////////////////////////////////////////////////////// class TDistinta_mask : public TAutomask { TDistinta_tree& _tree; TRecord_cache _ord; bool on_distsheet_event(TOperable_field& o, TField_event e, long jolly); bool on_parmsheet_event(TOperable_field& o, TField_event e, long jolly); protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); bool test_row(const TToken_string& row); public: TDistinta_mask(TDistinta_tree& dt); virtual ~TDistinta_mask() { } }; bool TDistinta_mask::test_row(const TToken_string& row) { const TCodice_articolo father = get(F_CODICE); TCodice_articolo code; row.get(1, code); bool ok = code != father; if (ok && _tree.find_node(father) > 0) { TToken_string path; _tree.curr_id(path); path.add(code); ok = !_tree.is_cyclic(path); } if (!ok) error_box("Il codice '%s' non puo' essere utilizzato\n" "in quanto la distinta risulterebbe ciclica.", (const char*)code); // Se e' una lavorazione if (get(F_TIPO)[0] == 'L') { ok = row[0] == 'L' && _tree.is_lav(code); if (!ok) error_box("Il codice '%s' non e' una lavorazione", (const char*)code); } return ok; } bool TDistinta_mask::on_distsheet_event(TOperable_field& o, TField_event e, long jolly) { const short id = o.dlg(); switch (id) { case F_SHEET: if (e == se_notify_add || e == se_notify_modify || e == fe_close) { TSheet_field& sheet = (TSheet_field&)o; const int nrig = int(jolly); TToken_string& row = sheet.row(nrig); switch(e) { case se_notify_add: row.add("A", F_TIPOCOMP-FIRST_FIELD); // Forza il listbox ad articolo row.add("1", F_EXPR-FIRST_FIELD); break; case se_notify_modify: return test_row(row); case fe_close: { TString80 code; for (int n = sheet.items()-1; n >= 0; n--) { const TToken_string& row = sheet.row(n); row.get(F_CODART-FIRST_FIELD, code); if (!code.blank()) { if (!test_row(row)) return FALSE; } else sheet.destroy(n); } } if (sheet.items() == 0) error_box("E' necessario inserire almeno una riga nella distinta"); break; default: break; } } break; case F_CODART: case F_CODLAV: case F_CODDIS: if (e == fe_modify || e == fe_init) { TMask& m = o.mask(); const TEdit_field& ef = (const TEdit_field&)o; const TRectype& rec = ef.browse()->cursor()->curr(); switch(rec.num()) { case LF_ANAMAG: m.set(F_DESCOMP, rec.get(ANAMAG_DESCR)); m.enable(F_UMEXPR); if (m.get(F_UMEXPR).empty()) { const TCodice_articolo art = o.get(); const TQuantita qta(art); m.set(F_UMEXPR, qta.um()); } break; case LF_DIST : m.set(F_DESCOMP, rec.get("DESCR")); m.set(F_UMEXPR, rec.get("UM")); m.disable(F_UMEXPR); break; default : m.set(F_DESCOMP, rec.get("S0")); m.set(F_UMEXPR, rec.get("S6")); m.disable(F_UMEXPR); break; } } break; case F_EXPR: if (e == fe_modify) { const TString& str = o.get(); if (str.not_empty()) { TDistinta_expr expr; if (expr.set(str)) { if (expr.numvar() > 0) { TDecoder var("VAR"); for (int v = expr.numvar()-1; v >= 0; v--) { const char* name = expr.varname(v); if (var.decode(name).empty()) return error_box("La variabile %s non e' definita in tabella", name); } } else o.set(expr.as_string()); } else return error_box("Errore di sintassi: %s", expr.last_token()); } else return error_box("L'espressione deve essere specificata"); } break; case F_SORT1: case F_SORT2: case F_SORT3: case F_SORT4: case F_SORT5: if (e == fe_modify && o.empty()) { TString16 key; key << (o.dlg() - F_SORT1 + 1); bool completo = _ord.get(key).get_bool("B0"); if (completo) return error_box("Il criterio di ordinamento %s deve essere specificato", (const char*)key); } break; default: break; } return TRUE; } bool TDistinta_mask::on_parmsheet_event(TOperable_field& o, TField_event e, long jolly) { const short id = o.dlg(); switch (id) { case F_PARAM: if (e == fe_modify || e == fe_close) { const TString& str = o.get(); if (!isalpha(str[0]) && str[0] != '_') return error_box("Il nome del parametro deve iniziare con un carattere alfabetico o con _"); for (const char* s = str; *s; s++) { if (!isalnum(*s) && *s != '_') return error_box("Il nome del parametro puo' contenere solo caratteri alfanumerici o _"); } } break; default: break; } return TRUE; } static _sort_key = 0; static int compare_sheet_rows(const TObject** o1, const TObject** o2) { TToken_string* s1 = (TToken_string*)*o1; TToken_string* s2 = (TToken_string*)*o2; const int key_pos = F_SORT1 - FIRST_FIELD + _sort_key - 1; long k1 = s1->get_long(key_pos); long k2 = s2->get_long(key_pos); if (k1 == 0) k1 = 100000000L; if (k2 == 0) k2 = 100000000L; return k1 == k2 ? 0 : (k1 > k2 ? +1 : -1); } bool TDistinta_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { const short id = o.dlg(); switch (id) { case F_CODICE: if (e == fe_init) { bool virtuale = TRUE; const TString& code = o.get(); const char type = _tree.get_type(code); switch(type) { case 'A': { set(F_TIPO, "A", TRUE); TDecoder mag(LF_ANAMAG, ANAMAG_DESCR); set(F_DESCR, mag.decode(code)); const TQuantita qta(code); set(F_UM, qta.um()); } break; case 'L': { set(F_TIPO, "L", TRUE); TTable lav("LAV"); lav.put("CODTAB", code); if (lav.read() == NOERR) { set(F_DESCR, lav.get("S0")); set(F_UM, lav.get("S6")); set(F_PREZZO, lav.get("R0")); } } break; default: set(F_TIPO, "V", TRUE); break; } } break; case F_SORT: if (e == fe_modify) { TSheet_field& sf = sfield(F_SHEET); _sort_key = atoi(o.get()); if (_sort_key > 0) { TString_array& a = sf.rows_array(); a.TArray::sort(compare_sheet_rows); } else { TRelation rel(LF_DIST); sf.autoload(rel); } sf.force_update(); } break; case F_SHEET: return on_distsheet_event(o, e, jolly); default: if (id >= 101 && id < 500) // E' in uno sheet? { switch (jolly) { case 1 : return on_distsheet_event(o, e, jolly); case 2 : return on_parmsheet_event(o, e, jolly); default: break; } } break; } return TRUE; } TDistinta_mask::TDistinta_mask(TDistinta_tree& dt) : TAutomask("db0100b"), _tree(dt), _ord("ORD") { TSheet_field& sf = sfield(F_SHEET); TMask& sm = sf.sheet_mask(); TString16 key; int i; for (i = 4; i >= 0; i--) { key.format("%d", i+1); const bool kill = _ord.get(key).empty(); if (kill) { const short id = F_SORT1+i; sm.hide(id); sf.delete_column(id); } } TCodgiac_livelli cgl; for (i = 4; i > 0; i--) { const short id = F_LIV1+i; const bool kill = !cgl.enabled(i); if (kill) { sm.hide(id); sf.delete_column(id); } else { const TString & header = cgl.name(i); const int len = header.len() + 1; const int f_len = cgl.code_length(i); sf.set_column_header(id, header); sf.set_column_width(id, (len > f_len ? len : f_len) * 8); } } } /////////////////////////////////////////////////////////// // TDistinta_app /////////////////////////////////////////////////////////// class TDistinta_app : public TRelation_application { TDistinta_tree _tree; TRelation* _therel; TQuery_mask* _querymask; TDistinta_mask* _themask; int _mode; void parms2rel(const TMask& m); protected: virtual bool user_create(); virtual bool user_destroy(); virtual TRelation* get_relation() const { return _therel; } virtual bool changing_mask(int mode); virtual TMask* get_mask(int mode); virtual int read(TMask& m); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); public: }; bool TDistinta_app::user_create() { _therel = new TRelation(LF_DIST); _querymask = new TQuery_mask(_tree); _themask = new TDistinta_mask(_tree); return TRUE; } bool TDistinta_app::user_destroy() { delete _themask; delete _querymask; delete _therel; return TRUE; } bool TDistinta_app::changing_mask(int mode) { bool was_query = _mode == MODE_QUERY || _mode == MODE_QUERYINS; bool is_query = mode == MODE_QUERY || mode == MODE_QUERYINS; return was_query != is_query; } TMask* TDistinta_app::get_mask(int mode) { const bool is_query = mode == MODE_QUERY || mode == MODE_QUERYINS; _mode = mode; return is_query ? (TMask*)_querymask : (TMask*)_themask; } int TDistinta_app::read(TMask& m) { const int err = TRelation_application::read(m); if (err == NOERR) { TSheet_field& sheet = m.sfield(F_SHEET); FOR_EACH_SHEET_ROW(sheet, nrig, row) sheet.check_row(nrig); TToken_string memo(1024, '\n'); memo = _therel->curr().get("PARAMETRI"); const int righe = memo.items(); TSheet_field& params = m.sfield(F_PARAMS); params.destroy(); for (int i = 0; i < righe; i++) { TToken_string& row = params.row(i); memo.get(i, row); int equal = row.find('='); if (equal > 0) row[equal] = '|'; } } return err; } void TDistinta_app::parms2rel(const TMask& m) { TToken_string memo(1024, '\n'); TSheet_field& parms = m.sfield(F_PARAMS); TString var; FOR_EACH_SHEET_ROW(parms, r, row) { var = row->get(0); if (!var.blank()) { memo.add(var); memo << '='; memo << row->get(); } } _therel->curr().put("PARAMETRI", memo); // Azzera albero per rispecchiare eventuali modifiche _querymask->restart_tree(); } int TDistinta_app::write(const TMask& m) { parms2rel(m); return TRelation_application::write(m); } int TDistinta_app::rewrite(const TMask& m) { parms2rel(m); return TRelation_application::rewrite(m); } /////////////////////////////////////////////////////////// // db0100 gestione distinte /////////////////////////////////////////////////////////// int db0100(int argc, char* argv[]) { TDistinta_app a; a.run(argc, argv, "Distinta base"); return 0; }