#include #include #include #include #include #include #include #include #include "../ca/calib01.h" #include "../mg/mglib.h" #include "../ve/velib.h" #include "pe1400.h" #include "pe1401.h" #include "pe1500.h" #include "../db/rdist.h" #include "../mg/anamag.h" #include "../ca/commesse.h" static real ricarico2perc(const TString& exp) { real val_perc = UNO; if (exp.full()) { TString80 num; bool dec = false; // Flag che indica se si attende l'inizio di un numero bool startnum = true; // Flag che indica se siamo all'inizio di un numero int errorchar = ' '; bool valid = true; // Flag che indica se sono nella parte decimale di un numero for (const char* s = exp; *s && errorchar == ' '; s++) { const char c = *s; switch(c) { case '+': case '-': // Se ero in in numero ... if( !startnum ) { // Aggiunge il numero alla sequenza const real val = num; val_perc *= ( CENTO + val ) / CENTO; } // Inizia il nuovo numero num = (c == '-') ? "-" : "+"; startnum = true; dec = false; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': num << c; startnum = false; break; case '.': case ',': if(!dec) { if( startnum ) num << '0'; // Se occorreva un numero ci metto lo 0 num << '.'; // Interpreto la virgola come punto dec = true; startnum = true; } else errorchar = c; // Se siamo già nella parte decimale segnala un errore break; case ' ': break; default: errorchar = c; break; } } // Controlla la validità valid = errorchar == ' '; if (valid) { // Aggiunge l'ultimo numero preso const real val = num; val_perc *= ( CENTO + val ) / CENTO; } } return val_perc; } /////////////////////////////////////////////////////////// // TPreventivo_app /////////////////////////////////////////////////////////// class TPreventivo_app : public TRelation_application { TMask* _qmsk; TMask* _emsk; TRelation* _rel; bool _revisioning; TString8 _codelab; protected: int save_rows(const TMask& m); virtual const char* extra_modules() const { return "ci"; } bool save_and_print(TPrtype mode); public: virtual bool user_create(); virtual bool user_destroy(); virtual bool changing_mask(int mode) { return !(_revisioning && mode == MODE_INS); } virtual TMask* get_mask(int mode) { return mode == MODE_QUERY ? _qmsk : _emsk; } virtual TRelation* get_relation() const { return _rel; } virtual bool get_next_key(TToken_string& key); virtual bool has_filtered_cursor() const { return true; } virtual TCursor& get_filtered_cursor() const; virtual void init_insert_mode(TMask& m); virtual void init_modify_mode(TMask& m); virtual const char* record_description(const TRelation& rel) const; virtual int read(TMask& m); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual bool remove(); virtual void print(); virtual void preview(); void update_tools(TMask& m); bool set_elab_code(const TString& cod) { _codelab = cod; return cod.full(); } }; inline TPreventivo_app& app() { return (TPreventivo_app&)main_app(); } /////////////////////////////////////////////////////////// // TPreventivo_nmsk /////////////////////////////////////////////////////////// class TPreventivo_nmsk : public TAutomask { TString4 _codnum; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TPreventivo_nmsk(const TString& codnum); }; bool TPreventivo_nmsk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_ANNO: if (e == fe_modify && !o.empty()) on_field_event(efield(F_NDOC), fe_init, 0L); break; case F_NDOC: if (e == fe_init) { long n = 1; TString query; query << "USE DOC" << "\nFROM PROVV=D ANNO=#ANNO CODNUM=#CODNUM" << "\nTO PROVV=D ANNO=#ANNO CODNUM=#CODNUM"; TISAM_recordset recset(query); recset.set_var("#ANNO", get(F_ANNO)); recset.set_var("#CODNUM", _codnum); if (recset.move_last()) { const TCodice_numerazione& num = cached_numerazione(_codnum); const int revlen = num.revision_len(); TString8 ndoc = recset.get(DOC_NDOC).as_string(); if (revlen > 0) ndoc.rtrim(revlen); n += atol(ndoc); } o.set(n); } else if (e == fe_modify || e == fe_close) { TString8 ndoc; const TCodice_numerazione& num = cached_numerazione(_codnum); const int revlen = num.revision_len(); if (revlen > 0) ndoc.format("%d%0*d", atoi(o.get()), revlen, 1); else ndoc = o.get(); TLocalisamfile doc(LF_DOC); doc.put(DOC_PROVV, "D"); doc.put(DOC_ANNO, get(F_ANNO)); doc.put(DOC_CODNUM, _codnum); doc.put(DOC_NDOC, ndoc); if (doc.read() == NOERR) return error_box("Preventivo già esistente"); } break; default: break; } return true; } TPreventivo_nmsk::TPreventivo_nmsk(const TString& codnum) : TAutomask(TR("Nuovo preventivo"), 1, 30, 6), _codnum(codnum) { const TCodice_numerazione& num = cached_numerazione(_codnum); const int revlen = num.revision_len(); add_number(F_NDOC, 0, PR("Codice "), 13, 1, 7-revlen).check_type(CHECK_REQUIRED); add_number(F_ANNO, 0, PR("Anno "), 1, 1, 4, "A").check_type(CHECK_REQUIRED); add_button(DLG_OK, 0, "", -12, -1, 9, 2); add_button(DLG_CANCEL, 0, "", -22, -1, 9, 2); set_handlers(); } /////////////////////////////////////////////////////////// // TPreventivo_msk /////////////////////////////////////////////////////////// // Classe di base per maschere preventivi (query ed edit) class TPreventivo_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); virtual TMask_field* parse_field(TScanner& s); public: int revision_length() const; int split_ndoc(long ndoc, int& nprev, int& nrev) const; int join_ndoc(int nprev, int nrev, long& ndoc) const; TPreventivo_msk(const char* name) { read_mask(name, 0, 8); set_handlers(); } }; TMask_field* TPreventivo_msk::parse_field(TScanner& s) { if (s.key() == "TL") set_full_screen_interface(page_win(1), true); return TAutomask::parse_field(s); } int TPreventivo_msk::revision_length() const { int rl = 0; const TString& codnum = get(F_CODNUM); if (codnum.full()) { const TCodice_numerazione& num = cached_numerazione(codnum); rl = num.revision_len(); } return rl; } int TPreventivo_msk::split_ndoc(long ndoc, int& nprev, int& nrev) const { nprev = nrev = 0; const int revlen = revision_length(); if (revlen > 0) { TString8 sdoc; sdoc << ndoc; if (sdoc.len() > revlen) { nrev = atoi(sdoc.right(revlen)); nprev = atoi(sdoc.rtrim(revlen)); } } else nprev = ndoc; return revlen; } int TPreventivo_msk::join_ndoc(int nprev, int nrev, long& ndoc) const { ndoc = 0L; const int revlen = revision_length(); if (revlen > 0) { ndoc = nprev; for (int i = 0; i < revlen; i++) ndoc *= 10; ndoc += nrev > 0 ? nrev : 1; } else ndoc = nprev; return revlen; } bool TPreventivo_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_CODNUM: if (e == fe_init || e == fe_modify) { if (o.empty()) { TCursor& c = *((TEdit_field&)o).browse()->cursor(); c = 0L; o.set(c.curr().get("CODTAB")); o.check(); } int revlen = 0; if (!o.empty()) { const TCodice_numerazione& num = cached_numerazione(o.get()); revlen = num.revision_len(); set(F_TIPODOC, num.tipo_doc(0), 0x3); } if (revlen > 0) { RCT rct; TEdit_field& prv = efield(F_NPREV); prv.set_len(7-revlen); prv.get_rect(rct); rct.right = rct.left + CHARX * (8-revlen); prv.set_rect(rct); TEdit_field& rev = efield(F_NREV); rev.set_len(revlen); rev.get_rect(rct); rct.right = rct.left + CHARX * (revlen+1); rev.set_rect(rct); show(F_NREV); } else hide(F_NREV); } break; case F_NDOC: if (!o.empty() && (e == fe_init || e == fe_modify)) { const long ndoc = atol(o.get()); int nprev = 0, nrev = 0; const int revlen = split_ndoc(ndoc, nprev, nrev); set(F_NPREV, nprev); set(F_NREV, nrev); if (revlen == 0) reset(F_NPREV); } break; default: if ((e == fe_modify || e == fe_close) && (!o.empty() && o.is_edit())) { const TFieldref* fr = o.field(); if (fr != NULL && fr->name() == RDOC_CODCMS) { TRelation rel(LF_RIGHEDOC); o.mask().autosave(rel); const TString& cms = rel.curr().get(RDOC_CODCMS); const TRectype& rec = cache().get(LF_COMMESSE, cms); if (rec.get_bool(COMMESSE_CHIUSA)) return error_box(FR("Impossibile utilizzare la commesa chiusa %s"), (const char*)cms); } } break; } return true; } /////////////////////////////////////////////////////////// // TPreventivo_qmsk /////////////////////////////////////////////////////////// class TPreventivo_qmsk : public TPreventivo_msk { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TPreventivo_qmsk() : TPreventivo_msk("pe1400a") {} }; bool TPreventivo_qmsk::on_field_event(TOperable_field& o, TField_event e, long jolly) { return TPreventivo_msk::on_field_event(o, e, jolly); } /////////////////////////////////////////////////////////// // TPreventivo_emsk /////////////////////////////////////////////////////////// class TPreventivo_emsk : public TPreventivo_msk { TPreventivo_tree* _tree; TString _idfase, _iddist; int _edit_dist, _edit_dett, _edit_misu; int _curr_dist, _curr_dett, _curr_misu; bool _locked, _has_db; private: bool on_fasi_button(TOperable_field& btn, TField_event e, long jolly); bool on_fasi_event(TTree_field& s, TField_event e, long jolly); bool set_fase(const TString& idf); bool set_dist(const TString& idd); bool set_dist(int row); void update_dist(const real& val, int column); void update_dist_qta(); void update_dist_costo(); bool on_dett_event(TOperable_field& o, TField_event e, long jolly); bool on_misu_event(TOperable_field& o, TField_event e, long jolly); bool on_dist_event(TOperable_field& o, TField_event e, long jolly); real get_costo(const TString& codart, TString& um, TString& iva) const; protected: virtual bool on_key(KEY k); virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void set_sheet_color(short id, COLOR col); bool sync_tree(); bool msk2rec(const TMask& msk, TRectype& rec) const; public: TPreventivo_tree& tree(bool reset = false); TPreventivo_emsk(); }; TPreventivo_tree& TPreventivo_emsk::tree(bool reset) { if (_tree == NULL) { _tree = new TPreventivo_tree(tfield(F_FASI)); reset = true; } if (reset) { TRectype doc(LF_DOC); doc.put(DOC_PROVV, 'D'); doc.put(DOC_ANNO, get(F_ANNO)); doc.put(DOC_CODNUM, get(F_CODNUM)); doc.put(DOC_NDOC, get(F_NDOC)); _tree->append_row(doc); TTree_field& tf = tfield(F_FASI); tf.set_tree(_tree); tf.hide_leaves(); } return *_tree; } static bool set_and_check(TMask_field& f, const TRectype& rec) { const TFieldref* fr = f.field(); if (fr == NULL) { if (f.ghost()) return f.on_hit(); return false; } if (fr->name() == RDOC_DESCR) { TString descr(255); descr = rec.get(RDOC_DESCR); if (rec.get_bool(RDOC_DESCLUNGA)) descr << rec.get(RDOC_DESCEST); f.set(descr); } else { f.set(fr->read(rec)); if (!f.empty() && f.is_edit() && f.shown()) { const TBrowse* b = ((TEdit_field&)f).browse(); if (b != NULL) { const TFixed_string of = b->get_output_fields(); if (of.find('|') > 0) // C'è un pipe nell'output, per cui ci sono almeno due campi di output f.check(STARTING_CHECK); } } } return true; } // Riempie gli sheet di articoli e misure della distinta selezionata bool TPreventivo_emsk::set_dist(const TString& idd) { TPreventivo_tree& t = tree(); bool ok = idd.full(); if (_iddist != idd) { _iddist = idd; // Svuota sheet articoli TSheet_field& a = sfield(F_ARTICOLI); a.hide(); a.destroy(); // Svuota sheet misure TSheet_field& m = sfield(F_MISURE); m.hide(); m.destroy(); // Scandisce i figli della distinta e li smista tra i due sheet ok = idd.full() && t.goto_node(idd); if (ok) { _locked = true; // Diabilita ricalcolo prezzi int n = 0; for (bool ok = t.goto_firstson(); ok; ok = t.goto_rbrother()) { const TRectype& rec = *t.curr_row(); TSheet_field& s = rec.get(RDOC_TIPORIGA) == t.tipo_dett() ? a : m; TMask& m = s.sheet_row_mask(n); FOR_EACH_MASK_FIELD(m, i, f) set_and_check(*f, rec); s.update_row(n++); } _locked = false; } // Visualizza nuovamente i due sheet eventualemente riempiti a.force_update(); a.show(); m.force_update(); m.show(); } _curr_dist = -1; if (ok && t.goto_node(idd)) { _curr_dist = 0; while(t.goto_lbrother()) _curr_dist++; } return ok; } bool TPreventivo_emsk::set_dist(int row) { TPreventivo_tree& t = tree(); bool ok = _idfase.full() && t.dist(_idfase, row) != NULL; if (ok) { TString16 idd; t.curr_id(idd); ok = set_dist(idd); CHECK(ok && row == _curr_dist, "Distinta sospetta"); } return ok; } // Riempie lo sheet delle distinte della fase selezionata bool TPreventivo_emsk::set_fase(const TString& idfase) { _idfase = idfase; // Svuota lo sheet delle distinte TSheet_field& d = sfield(F_DISTINTE); d.destroy(); TString idd; TPreventivo_tree& t = tree(); bool ok = idfase.full() && t.goto_node(idfase); if (ok) { // Scandisce le distinte della fase corrente if (t.goto_firstson()) { t.curr_id(idd); // Memorizza la prima distinta per dopo... int n = 0; do { const TRectype& rec = *t.curr_row(); TMask& m = d.sheet_row_mask(n); FOR_EACH_MASK_FIELD(m, i, f) set_and_check(*f, rec); d.update_row(n++); } while (t.goto_rbrother()); } } d.force_update(); set_dist(idd); return ok; } bool TPreventivo_emsk::msk2rec(const TMask& msk, TRectype& rec) const { TRelation rel(rec.num()); rel.curr() = rec; msk.autosave(rel); rec = rel.curr(); const TString& desc = msk.get(RDOC_DESCR); const int maxlen = rec.length(RDOC_DESCR); int spc = desc.find('\n'); if (spc >= 0 || desc.len() > maxlen) { if (spc < 0 || spc > maxlen) { spc = desc.left(maxlen).rfind(' '); if (spc < maxlen/2) spc = maxlen; } rec.put(RDOC_DESCR, desc.left(spc)); rec.put(RDOC_DESCLUNGA, "X"); rec.put(RDOC_DESCEST, desc.mid(spc)); } else { rec.put(RDOC_DESCR, desc); rec.zero(RDOC_DESCLUNGA); rec.put(RDOC_DESCEST, ""); } return !rec.empty(); } bool TPreventivo_emsk::on_key(KEY k) { if (k == K_SHIFT + K_F12) { enable(F_STATO); return true; } return TAutomask::on_key(k); } bool TPreventivo_emsk::on_fasi_button(TOperable_field& o, TField_event e, long jolly) { TPreventivo_tree& t = tree(); TTree_field& fasi = t.owner(); TPreventivo_level pl = pl_documento; if (fasi.goto_selected()) pl = t.level(); else return false; if (pl == pl_documento && o.dlg() == F_FASENEW) pl = pl_fase1; if (pl < pl_fase1 || pl > pl_distinta) return false; o.disable(); switch (o.dlg()) { case F_FASENEW: { TMask m("Nuovo", 1, 46, 7); m.add_string(S_CODART, 0, "Codice ", 1, 1, 20).check_type(CHECK_REQUIRED); m.add_string(S_DESCR, 0, "Descrizione ", 1, 2, 50, "", 30).check_type(CHECK_REQUIRED); m.add_button(DLG_OK, 0, "", -12, -1, 10, 2); m.add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2); if (m.run() == K_ENTER) { TRectype* rec = t.new_row(pl); rec->put(RDOC_CODART, m.get(S_CODART)); rec->put(RDOC_DESCR, m.get(S_DESCR)); if (tree().level() == pl) t.add_rbrother(rec); else { t.append_row(*rec); delete rec; } } } break; case F_FASEDIT: { TRectype& rec = *t.curr_row(); TMask m("Modifica", 1, 46, 7); m.add_string(S_CODART, 0, "Codice ", 1, 1, 20).check_type(CHECK_REQUIRED); m.add_string(S_DESCR, 0, "Descrizione ", 1, 2, 50, "", 30).check_type(CHECK_REQUIRED); m.add_button(DLG_OK, 0, "", -13, -1, 10, 2); m.add_button(DLG_DELREC, 0, "", -23, -1, 10, 2); m.add_button(DLG_CANCEL, 0, "", -33, -1, 10, 2); m.set(S_CODART, rec.get(RDOC_CODART)); m.set(S_DESCR, rec.get(RDOC_DESCR)); switch (m.run()) { case K_ENTER: rec.put(RDOC_CODART, m.get(S_CODART)); rec.put(RDOC_DESCR, m.get(S_DESCR)); break; case K_DEL: t.kill_node(); break; default: break; } } break; case F_FASEUP: t.swap_left(); if (pl == pl_distinta) { TString16 id; t.curr_id(id); set_fase(_idfase); t.goto_node(id); } break; case F_FASEDN: t.swap_right(); if (pl == pl_distinta) { TString16 id; t.curr_id(id); set_fase(_idfase); t.goto_node(id); } break; case F_FASELT: if (pl > pl_fase1 && pl < pl_distinta && t.push_up()) t.curr_row()->put(RPRV_LEVEL, t.curr_depth()-1); break; case F_FASERT: if (pl >= pl_fase1 && pl < t.last_fase_level() && t.push_down()) t.curr_row()->put(RPRV_LEVEL, t.curr_depth()-1); break; default: break; } o.enable(); fasi.select_current(); fasi.force_update(); return true; } bool TPreventivo_emsk::on_fasi_event(TTree_field& fasi, TField_event e, long jolly) { bool modified = false; bool can_edit = false; bool can_goup = false; bool can_godn = false; bool can_golt = false; bool can_gort = false; switch (e) { case fe_modify: if (fasi.goto_selected()) { modified = true; TPreventivo_tree& t = tree(); TPreventivo_level td = t.level(); if (td > pl_documento) { can_edit = true; can_goup = t.has_lbrother(); can_godn = t.has_rbrother(); if (td >= pl_fase1 && td < pl_distinta) // Cambio fase { can_golt = td > pl_fase1; can_gort = td < t.last_fase_level(); TString16 id; t.curr_id(id); set_fase(id); } else { while (td > pl_distinta) { t.goto_father(); td = t.level(); } TString idd; t.curr_id(idd); if (t.goto_father()) { TString idf; t.curr_id(idf); if (idf != _idfase) set_fase(idf); } set_dist(idd); } } } break; default: break; } if (modified) { enable(F_FASEDIT, can_edit); enable(F_FASEUP, can_goup); enable(F_FASEDN, can_godn); enable(F_FASELT, can_golt); enable(F_FASERT, can_gort); } return true; } bool TPreventivo_emsk::on_dist_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case D_CODDIS: case D_CODART: if (e == fe_modify && !o.empty()) { const TString& codart = o.get(); TRecord_array rdist(codart, LF_RDIST); if (rdist.rows() > 0 && sfield(F_ARTICOLI).empty()) { TPreventivo_tree& t = tree(); while (t.dett(_iddist, 0)) t.kill_node(); const int last = rdist.last_row(); int n = 0; for (int r = rdist.first_row(); r > 0 && r <= last; r = rdist.succ_row(r)) { const TRectype& rd = rdist.row(r); const TCodice_articolo codart = rd.get(RDIST_CODCOMP); TString80 desc = rd.get(RDIST_DESCR); if (desc.empty()) desc = cache().get(LF_ANAMAG, codart, ANAMAG_DESCR); TRectype* rec = t.dett(_iddist, n++, true); rec->put(RDOC_CODART, codart); rec->put(RDOC_DESCR, desc); rec->put(RDOC_UMQTA, rd.get(RDIST_UM)); rec->put(RDOC_QTA, rd.get(RDIST_EXPR)); } t.goto_node(_iddist); sync_tree(); // Forza aggiornamento dello sheet const TString16 id = _iddist; _iddist.cut(0); set_dist(id); } TString4 um, iva; const real costo = get_costo(codart, um, iva); TMask& m = o.mask(); m.set(D_UM, um); m.set(D_COSTO, costo, 0x3); } break; case D_COSTO: if (e == fe_modify && !o.empty()) { const TString& ric = get(F_RICARICO); if (ric.full()) { TMask& m = o.mask(); const real k = ricarico2perc(ric); const real prezzo = real(o.get()) * k; m.set(o.dlg()+1, prezzo); } } break; case F_DISTINTE: switch (e) { case se_enter: _edit_dist = -1; set_dist(_curr_dist = jolly); break; case se_query_add: return _idfase.full(); case se_notify_add: { TPreventivo_tree& t = tree(); TRectype* rec = t.dist(_idfase, _curr_dist = jolly, true); if (rec != NULL) sync_tree(); } break; case se_query_modify: if (jolly != _curr_dist) set_dist(jolly); _edit_dist = _curr_dist = jolly; break; case se_leave: case se_notify_modify: if (_edit_dist >= 0) { const int r = _edit_dist; // Memorizza numero riga corrente _edit_dist = -1; // Annulla numero riga corrente TRectype* rec = tree().dist(_idfase, r, true); if (rec != NULL) { const TMask& m = ((TSheet_field&)o).sheet_row_mask(r); msk2rec(m, *rec); sync_tree(); } } break; case se_notify_del: if (_curr_dist >= 0) { TPreventivo_tree& t = tree(); TRectype* rec = t.dist(_idfase, _curr_dist); if (rec != NULL) { t.kill_node(); sync_tree(); } } break; default: break; } break; default: break; } return true; } real TPreventivo_emsk::get_costo(const TString& codart, TString& um, TString& iva) const { real costo = ZERO; const int tc = get_int(F_TIPOCOSTO); const TArticolo_giacenza& art = cached_article_balances(codart); TEsercizi_contabili esc; const int annoes = esc.date2esc(get_date(F_DATADOC)); switch (tc) { case 1 : costo = art.ultimo_costo(annoes); break; case 2 : costo = art.media_costi(annoes); break; case 4 : costo = art.costo_standard(annoes); break; case 5 : costo = art.costo_medio(annoes, "", ""); break; case 6 : costo = art.costo_mediopond(annoes, "", ""); break; default: break; } if (costo.is_zero()) costo = art.get_real(ANAMAG_COSTSTD); um = art.um().row(1).get(UMART_UM); iva = art.get(ANAMAG_CODIVA); return costo; } bool TPreventivo_emsk::on_dett_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case S_CODART: if (e == fe_modify && !o.empty() && !_locked) { const TString& codart = o.get(); TString4 um, iva; const real costo = get_costo(codart, um, iva); TMask& m = o.mask(); if (um.full()) m.set(S_UMART, um, 0x3); if (iva.full() && m.get(S_CODIVA).blank()) m.set(S_CODIVA, iva, 0x3); if (!costo.is_zero()) m.set(S_COSTO, costo, 0x3); } break; case F_ARTICOLI: switch (e) { case se_query_add: return _iddist.full(); case se_notify_add: { TPreventivo_tree& t = tree(); TRectype* rec = t.dett(_iddist, _curr_dett = jolly, true); if (rec != NULL) sync_tree(); } break; case se_enter: _edit_dett = -1; _curr_dett = jolly; break; case se_query_modify: _edit_dett = _curr_dett = jolly; break; case se_leave: case se_notify_modify: if (_edit_dett >= 0) { const int r = _edit_dett; _edit_dett = -1; TPreventivo_tree& t = tree(); TRectype* rec = t.dett(_iddist, r, true); if (rec != NULL) { const TMask& m = ((TSheet_field&)o).sheet_row_mask(r); msk2rec(m, *rec); sync_tree(); update_dist_costo(); } } break; case se_notify_del: if (_curr_dett >= 0) { TPreventivo_tree& t = tree(); TRectype* rec = t.dett(_iddist, _curr_dett); if (rec != NULL) { t.kill_node(); update_dist_costo(); sync_tree(); } } break; default: break; } break; default: break; } return true; } bool TPreventivo_emsk::on_misu_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case 102: case 103: case 104: case 105: if (e == fe_modify && _curr_misu >= 0 && _curr_dist >= 0) { TSheet_field& misure = *o.mask().get_sheet(); TEdit_field& tot = o.mask().efield(106); tot.validate(K_TAB); misure.row(_curr_misu).add(tot.get(), 5); update_dist_qta(); } break; case F_MISURE: switch (e) { case se_query_add: return _iddist.full(); case se_notify_add: tree().misu(_iddist, _edit_misu = jolly, true); break; case se_enter: _edit_misu = -1; _curr_misu = jolly; break; case se_query_modify: _edit_misu = _curr_misu = jolly; break; case se_leave: case se_notify_modify: if (_iddist.full() && _edit_misu >= 0) { TPreventivo_tree& t = tree(); TRectype* rec = t.misu(_iddist, _edit_misu, true); if (rec != NULL) { TSheet_field& sheet = ((TSheet_field&)o); const TMask& m = sheet.sheet_row_mask(_edit_misu); msk2rec(m, *rec); update_dist_qta(); } _edit_misu = -1; } break; case se_notify_del: if (_curr_misu >= 0) { TPreventivo_tree& t = tree(); TRectype* rec = t.misu(_iddist, _curr_misu); if (rec != NULL) { t.kill_node(); update_dist_qta(); } } break; default: break; } default: break; } return true; } void TPreventivo_emsk::update_dist(const real& val, int column) { TSheet_field& dist = sfield(F_DISTINTE); dist.row(_curr_dist).add(val.string(), column); dist.update_mask(_curr_dist); TOperable_field& o = dist.sheet_row_mask(_curr_dist).efield(105); on_dist_event(o, fe_modify, 1); dist.force_update(_curr_dist); TRectype* rec = tree().dist(_idfase, _curr_dist); if (rec) msk2rec(dist.sheet_row_mask(_curr_dist), *rec); } void TPreventivo_emsk::update_dist_costo() { if (_curr_dist >= 0) { TSheet_field& sheet = sfield(F_ARTICOLI); real costo, prezzo; FOR_EACH_SHEET_ROW(sheet, i, row) { const real q = row->get(3); const real c = row->get(); const real p = row->get(); costo += q*c; prezzo += q*p; } if (!costo.is_zero()) update_dist(costo, 4); if (!prezzo.is_zero()) update_dist(prezzo, 5); } } void TPreventivo_emsk::update_dist_qta() { if (_curr_dist >= 0) { TSheet_field& sheet = sfield(F_MISURE); real tot; FOR_EACH_SHEET_ROW(sheet, i, row) tot += real(row->get(5)); update_dist(tot, 3); } } bool TPreventivo_emsk::sync_tree() { TPreventivo_tree& t = tree(); TTree_field& tf = t.owner(); tf.force_update(); return true; } static bool ricarica(TTree& tree, void* jolly, word) { const TPreventivo_tree& t = (const TPreventivo_tree&)tree; if (t.level() == pl_distinta) { TRectype* rec = t.curr_row(); const real cos = rec->get(RPRV_COSTO); const real k = *(real*)jolly; rec->put(RDOC_PREZZO, cos * k); } return false; } bool TPreventivo_emsk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_STATO: if ((e == fe_init || e == fe_close) && o.empty()) o.set("1"); if (e == fe_modify && !o.empty()) app().update_tools(*this); break; case F_FASI: return on_fasi_event((TTree_field&)o, e, jolly); case F_FASENEW: case F_FASEDIT: case F_FASEDEL: case F_FASEUP: case F_FASEDN: case F_FASERT: case F_FASELT: if (e == fe_button) return on_fasi_button(o, e, jolly); break; case F_DISTINTE: return on_dist_event(o, e, jolly); case F_ARTICOLI: return on_dett_event(o, e, jolly); case F_MISURE: return on_misu_event(o, e, jolly); case DLG_COPY: if (e == fe_button && edit_mode()) { TPreventivo_nmsk m(get(F_CODNUM)); if (m.run() == K_ENTER) { const TDate datadoc(TODAY); const int nprev = m.get_int(F_NDOC); const int nrev = 1; long ndoc = 0; join_ndoc(nprev, nrev, ndoc); set(F_NPREV, nprev); set(F_NREV, nrev); set(F_NDOC, ndoc); set(F_STATO, 1); set(F_DATADOC, datadoc); set(F_ANNO, m.get_int(F_ANNO)); set_mode(MODE_INS); stop_run(K_SAVE); } return true; } break; case DLG_PRINT: if (e == fe_button) main_app().print(); break; case DLG_PREVIEW: if (e == fe_button) main_app().preview(); break; case DLG_ELABORA: if (e == fe_button) { const TString& cod = pe_trova_elaborazione(*this, 'O'); if (cod.full()) { TPreventivo_app& relapp = (TPreventivo_app&)main_app(); if (relapp.set_elab_code(cod)) stop_run(K_SAVE); } } break; case DLG_ARCHIVE: if (e == fe_button) { const TString& cod = pe_trova_elaborazione(*this, 'F'); if (cod.full()) { TPreventivo_app& relapp = (TPreventivo_app&)main_app(); if (relapp.set_elab_code(cod)) stop_run(K_SAVE); } } break; case F_RICARICO: if (e == fe_modify && !o.empty()) { // Controllo che ci sia almeno una fase prima di ricalcolare tutto TPreventivo_tree& t = tree(); if (t.goto_root() && t.has_son() && yesno_box(TR("Si desidera applicare il nuovo ricarico a tutte fasi?"))) { if (t.goto_root()) { const real perc = ricarico2perc(o.get()); t.scan_depth_first(ricarica, (void*)&perc); sync_tree(); set_fase(""); } } } break; default: if (jolly > 0 && o.dlg() >= 101 && o.dlg() < 300) // Sheet mask events { if (e == fe_modify) { switch (jolly) { case 1: return on_dist_event(o, e, jolly); case 2: return on_dett_event(o, e, jolly); case 3: return on_misu_event(o, e, jolly); default: CHECK(false, "Unknown sheet field event"); break; } } } break; } return TPreventivo_msk::on_field_event(o, e, jolly); } void TPreventivo_emsk::set_sheet_color(short id, COLOR col) { const COLOR rgb = blend_colors(NORMAL_BACK_COLOR, col, 0.75); TSheet_field& s = sfield(id); s.set_back_and_fore_color(rgb, NORMAL_COLOR, -1); } TPreventivo_emsk::TPreventivo_emsk() : TPreventivo_msk("pe1400b"), _tree(NULL), _locked(false), _has_db(false) { int yca = 21; // Riga del primo campo di analitica TMask_field* grp = find_by_id(F_CDC0); if (grp) { RCT rct0; grp->get_rect(rct0); yca = rct0.top / ROWY + 1; } short idcdc = 0, idcms = 0, idfase = 0, idconto = 0; ca_create_fields_ext(*this, 0, 2, yca, F_CDC0+1, idcdc, idcms, idfase, idconto, DOC_CODCOSTO, DOC_CODCMS, NULL); // Niente fasi qui! set_sheet_color(F_DISTINTE, COLOR_YELLOW); set_sheet_color(F_ARTICOLI, COLOR_GREEN); set_sheet_color(F_MISURE, COLOR_GRAY); _has_db = dongle().active(DBAUT); if (_has_db) { TISAM_recordset dist("USE DIST"); _has_db = dist.items() >= 4; } TMask& dist = sfield(F_DISTINTE).sheet_mask(); TList_field& tipoa = dist.lfield(D_TIPOA); const TToken_string cod = tipoa.get_codes(); if (!_has_db && cod.items() >= 2) { TToken_string* m1 = tipoa.message(1); tipoa.replace_items("A", TR("Articolo")); if (m1 != NULL) { TToken_string* m0 = tipoa.message(0); if (m0 != NULL) *m0 = *m1; } tipoa.disable(); } } /////////////////////////////////////////////////////////// // TPreventivo_app /////////////////////////////////////////////////////////// bool TPreventivo_app::user_create() { if (ca_config().get_int("Authorizations") < 2) return error_box("E' necessario configurare la contabilità analitica o industriale"); open_files(LF_TAB, LF_TABCOM, LF_CLIFO, LF_DOC, LF_RIGHEDOC, LF_COMMESSE, LF_FASI, 0); _rel = new TRelation(LF_DOC); _qmsk = new TPreventivo_qmsk; _emsk = new TPreventivo_emsk; return true; } bool TPreventivo_app::user_destroy() { delete _emsk; delete _qmsk; delete _rel; return true; } TCursor& TPreventivo_app::get_filtered_cursor() const { TEdit_field& f = _qmsk->efield(F_NDOC); TCursor& cur = *f.browse()->cursor(); if (cur.items() == 0) // A volte deve scantarsi ... f.check(); // ... forzo ricalcolo elementi return cur; } bool TPreventivo_app::get_next_key(TToken_string& key) { TPreventivo_msk& m = (TPreventivo_msk&)curr_mask(); const TEdit_field& codnum = m.efield(F_CODNUM); if (codnum.empty()) return codnum.error_box(TR("Inserire un codice numerazione")); const int revlen = m.revision_length(); long ndoc = 0; int nprev = 0, nrev = 0; if (m.query_mode() || revlen == 0) { TCursor& cur = get_filtered_cursor(); const TRecnotype i = cur.items(); if (i > 0) { cur = i-1; ndoc = cur.curr().get_long(DOC_NDOC); m.split_ndoc(ndoc, nprev, nrev); } nprev++; nrev = 1; m.join_ndoc(nprev, nrev, ndoc); } else { // Trucchi per evitare l'azzeramento della maschera _revisioning = true; m.set_mode(MODE_QUERY); ndoc = m.get_long(F_NDOC); m.split_ndoc(ndoc, nprev, nrev); nrev++; m.join_ndoc(nprev, nrev, ndoc); m.set(F_NDOC, ndoc, 0x3); } key.format("%d|%ld", F_NDOC, ndoc); return true; } int TPreventivo_app::read(TMask& m) { int err = TRelation_application::read(m); if (err == NOERR) { const TRectype& doc = get_relation()->curr(); TToken_string keytok; keytok.add(doc.get(DOC_CODNUM)); keytok.add(doc.get(DOC_ANNO)); keytok.add(doc.get(DOC_PROVV)); keytok.add(doc.get(DOC_NDOC)); const TRecord_array rdoc(keytok, LF_RIGHEDOC); TPreventivo_tree& t = ((TPreventivo_emsk&)m).tree(); t.append_row(doc); const int last_row = rdoc.last_row(); for (int r = rdoc.first_row(); r > 0 && r <= last_row; r = rdoc.succ_row(r)) t.append_row(rdoc[r]); t.shrink_all(); t.goto_root(); t.expand(); t.owner().force_update(); m.set(F_FASEMAX, pe_numero_fasi(rdoc)); } _codelab.cut(0); // Azzera in ogni caso l'elaborazione return err; } static bool tree_save_row(TTree& tree, void* jolly, word /*flags*/) { TPreventivo_tree& t = (TPreventivo_tree&)tree; const TRectype* rec = t.curr_row(); if (rec && !rec->empty() && rec->num() == LF_RIGHEDOC) { const real costo = rec->get(RPRV_COSTO); const real price = rec->get(RDOC_PREZZO); const TString& descr = rec->get(RDOC_DESCR); if (descr.full() || !costo.is_zero() || !price.is_zero()) { TDocumento& doc = *(TDocumento*)jolly; const TString4 tiporiga = rec->get(RDOC_TIPORIGA); TRectype& row = doc.new_row(tiporiga); const TString80 codart = rec->get(RDOC_CODART); TString80 codartmag; if (codart.full()) codartmag = cache().get(LF_ANAMAG, codart, ANAMAG_CODART); for (int f = rec->items()-1; f > 5; f--) { const char* fld = rec->fieldname(f); if (rec->type(fld) == _memofld) break; const TString& src = rec->get(fld); if (src.full()) { const TString& dst = row.get(fld); if (dst.blank()) row.put(fld, src); } } row.put(RDOC_IDRIGA, row.get(RDOC_NRIGA)); row.put(RDOC_TIPORIGA, rec->get(RDOC_TIPORIGA)); row.put(RDOC_QTA, rec->get(RDOC_QTA)); row.put(RDOC_DESCR, rec->get(RDOC_DESCR)); row.put(RDOC_DESCLUNGA, rec->get(RDOC_DESCLUNGA)); row.put(RDOC_DESCEST, rec->get(RDOC_DESCEST)); row.put(RDOC_CODART, codart); row.put(RDOC_CODARTMAG, codartmag); row.put(RDOC_CHECKED, codartmag.full()); row.put(RDOC_UMQTA, rec->get(RDOC_UMQTA)); row.put(RDOC_QTAGG1, rec->get(RDOC_QTAGG1)); row.put(RDOC_QTAGG2, rec->get(RDOC_QTAGG2)); row.put(RDOC_QTAGG3, rec->get(RDOC_QTAGG3)); row.put(RDOC_QTAGG4, rec->get(RDOC_QTAGG4)); row.put(RDOC_QTAGG5, rec->get(RDOC_QTAGG5)); row.put(RDOC_PREZZO, rec->get(RDOC_PREZZO)); // Make sure of coherent level on final record const TPreventivo_level pl = t.level(*rec); if (pl > pl_fase1 && pl < pl_distinta) row.put(RPRV_LEVEL, int(t.curr_depth() - 1)); // Don't assume RPRV_LEVEL = pl-pl_fase1 else row.zero(RPRV_LEVEL); } } return false; // Don't stop scan } int TPreventivo_app::save_rows(const TMask& m) { TPreventivo_tree& tree = ((TPreventivo_emsk&)m).tree(); TDocumento doc(get_relation()->curr()); doc.destroy_rows(); if (tree.goto_root() && tree.goto_firstson()) tree.scan_depth_first(tree_save_row, &doc); // Estrae campi analitica da maschera principale e li riporta sulle righe TString cms, cos; FOR_EACH_MASK_FIELD(m, i, f) if (f->active() && f->is_edit() && f->dlg() >= F_CDC0) { const TFieldref* fref = f->field(); if (fref != NULL) { if (fref->name() == DOC_CODCMS) cms << f->get(); if (fref->name() == DOC_CODCOSTO) cos << f->get(); } } TRecord_array& rdoc = doc.body(); rdoc.renum_key(RDOC_CODCMS, cms); rdoc.renum_key(RDOC_CODCOSTO, cos); const int err = doc.rewrite(get_relation()->file()); if (err == NOERR && _codelab.full()) pe_genera_documento(doc, _codelab, 'O'); _codelab.cut(0); // Azzera in ogni caso l'elaborazione return err; } int TPreventivo_app::write(const TMask& m) { int err = TRelation_application::write(m); if (err == NOERR) err = save_rows(m); return err; } int TPreventivo_app::rewrite(const TMask& m) { int err = TRelation_application::rewrite(m); if (err == NOERR) err = save_rows(m); return err; } bool TPreventivo_app::remove() { bool done = TRelation_application::remove(); if (done) { const TRectype& rec = get_relation()->curr(); TToken_string keytok; keytok.add(rec.get(DOC_CODNUM)); keytok.add(rec.get(DOC_ANNO)); keytok.add(rec.get(DOC_PROVV)); keytok.add(rec.get(DOC_NDOC)); TRecord_array rdoc(keytok, LF_RIGHEDOC); rdoc.remove(); } return done; } void TPreventivo_app::update_tools(TMask& m) { const bool is_edit = m.edit_mode(); const bool can_ord = is_edit && pe_trova_elaborazione(m, 'O').full(); const bool can_fab = is_edit && pe_trova_elaborazione(m, 'F').full(); bool can_print = is_edit; if (can_print) { const TTipo_documento& tip = cached_tipodoc(m.get(DOC_TIPODOC)); TFilename rep; can_print = tip.main_print_profile(rep, 0x2); } m.enable(DLG_COPY, is_edit); m.enable(DLG_NEWREC, is_edit); m.enable(DLG_ELABORA, can_ord); m.enable(DLG_ARCHIVE, can_fab); m.enable(DLG_PRINT, can_print); m.enable(DLG_PREVIEW, can_print); m.disable(F_STATO); // Enable with F12 } void TPreventivo_app::init_insert_mode(TMask& m) { _revisioning = false; TRelation_application::init_insert_mode(m); m.set(F_DATADOC, TDate(TODAY)); update_tools(m); const TMultilevel_code_info& fi = ca_multilevel_code_info(LF_FASI); const int fasemax = fi.levels() - fi.parent_levels(); m.set(F_FASEMAX, fasemax); } void TPreventivo_app::init_modify_mode(TMask& m) { _revisioning = false; TRelation_application::init_modify_mode(m); update_tools(m); } bool TPreventivo_app::save_and_print(TPrtype mode) { static bool already_printing = false; if (already_printing) return false; already_printing = true; if (rewrite(*_emsk) != NOERR) return already_printing = false; TString commandline; commandline << "ve1 -2" << ' ' << _emsk->get(F_CODNUM) << ' ' << _emsk->get(F_ANNO) << " D " << _emsk->get(F_NDOC); switch (mode) { case exportprinter: commandline << " E P"; break; case fileprinter : commandline << " P P"; break; case screenvis : commandline << " A P"; break; default : commandline << " S D"; break; } TExternal_app interattivo( commandline ); if (interattivo.run() == NOERR) { TLocalisamfile& f = _rel->file(); f.zero(); f.put(DOC_PROVV, 'D'); f.put(DOC_ANNO, _emsk->get(F_ANNO)); f.put(DOC_CODNUM, _emsk->get(F_CODNUM)); f.put(DOC_NDOC, _emsk->get(F_NDOC)); f.read(); curr_mask().set(F_STATO, f.get(DOC_STATO)); } already_printing = false; return true; } void TPreventivo_app::print() { save_and_print(winprinter); } void TPreventivo_app::preview() { save_and_print(screenvis); } const char* TPreventivo_app::record_description(const TRelation& rel) const { const TString4 tipodoc = rel.curr().get(DOC_TIPODOC); const TString& desc = cache().get("%TIP", tipodoc, "S0"); return desc.empty() ? title() : desc; } int pe1400(int argc, char* argv[]) { TPreventivo_app a; a.run(argc, argv, TR("Preventivi")); return 0; }