#include #include #include #include #include #include #include #include "sl0100a.h" #include "sl0101.h" #include "sl0200.h" #include "../ca/calib01.h" #include "../ve/velib.h" #include "../db/rdist.h" #include "../mg/anamag.h" #include "../ca/commesse.h" /////////////////////////////////////////////////////////// // TSAL_app /////////////////////////////////////////////////////////// class TSAL_app : public TRelation_application { TMask* _qmsk; TMask* _emsk; TRelation* _rel; protected: int save_rows(const TMask& m); virtual const char* extra_modules() const { return "ci"; } const char* record_description(const TRelation& r) const; bool save_and_print(TPrtype mode); public: virtual bool user_create(); virtual bool user_destroy(); virtual bool changing_mask(int mode) { return true; } virtual TMask* get_mask(int mode) { return mode == MODE_QUERY ? _qmsk : _emsk; } virtual TRelation* get_relation() const { return _rel; } virtual bool has_filtered_cursor() const { return true; } virtual TCursor& get_filtered_cursor() const; virtual bool get_next_key(TToken_string& key); virtual void init_insert_mode(TMask& m); virtual void init_modify_mode(TMask& m); virtual int read(TMask& m); virtual int write(const TMask& m); virtual int rewrite(const TMask& m); virtual bool remove(); virtual void print(); bool report(const char* name); void update_tools(TMask& m); }; inline TSAL_app& app() { return (TSAL_app&)main_app(); } /////////////////////////////////////////////////////////// // TSAL_msk /////////////////////////////////////////////////////////// // Classe di base per maschere preventivi (query ed edit) class TSAL_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: const TString& fget(const char* fld) const; void fset(const char* fld, const TString& val, int hit=0x0); TSAL_msk(const char* name) { read_mask(name, 0, 8); set_handlers(); } }; TMask_field* TSAL_msk::parse_field(TScanner& s) { if (s.key() == "TL") set_full_screen_interface(page_win(1), true); return TAutomask::parse_field(s); } // Legge il valore di un campo multiplo (commessa, fase, ...) da maschera e lo restituisce come unico valore const TString& TSAL_msk::fget(const char* fld) const { TString& val = get_tmp_string(); FOR_EACH_MASK_FIELD(*this, i, f) { const TFieldref* fr = f->field(); if (fr != NULL && fr->name() == fld) { if (fr->from() > 0 || fr->to() > 0) val.overwrite(f->get(), fr->from()); else { val = f->get(); break; } } } return val; } // Spezza un valore unico su pių sottocampi (commessa, fase, ...) void TSAL_msk::fset(const char* fld, const TString& val, int hit) { FOR_EACH_MASK_FIELD(*this, i, f) { const TFieldref* fr = f->field(); if (fr != NULL && fr->name() == fld) { if (fr->from() > 0 || fr->to() > 0) { const TString& str = val.sub(fr->from(), fr->to()); f->set(str); } else f->set(val); if ((f->active() || f->ghost())) { f->set_dirty(); if (hit & 0x2) f->check(); if (hit & 0x1) f->on_hit(); } } } } bool TSAL_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { // switch (o.dlg()) // { // 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) { const TString& cms = fget(RDOC_CODCMS); const TRectype& rec = cache().get(LF_COMMESSE, cms); if (rec.get_bool(COMMESSE_CHIUSA)) return error_box(FR("Impossibile utilizzare la commessa chiusa %s"), (const char*)cms); } } // break; // } return true; } /////////////////////////////////////////////////////////// // TSAL_qmsk /////////////////////////////////////////////////////////// class TSAL_qmsk : public TSAL_msk { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); bool choose_best(TCursor& cur, const char* codtab); public: TSAL_qmsk(); }; // Inizialmente seleziona solo i documenti cliente static const char* m_tipocf = "C"; static bool tipoc_filter(const TRelation* rel) { const TCodice_numerazione& codnum = cached_numerazione(rel->curr().get("CODTAB")); for (int i = 0; ; i++) { const TString& td = codnum.tipo_doc(i); if (td.blank()) break; const TTipo_documento& tipodoc = cached_tipodoc(td); TFilename ini; tipodoc.profile_name(ini); if (ini.custom_path()) { const TString& tipocf = ini_get_string(ini, "MAIN", "TIPOCF"); if (tipocf == m_tipocf) return true; } } return false; } // Seleziona solo gli ordini static bool ord_filter(const TRelation* rel) { return rel->curr().get_int("I1") == 3 && tipoc_filter(rel); } // Seleziona solo le bolle static bool sal_filter(const TRelation* rel) { return rel->curr().get_int("I1") == 1 && tipoc_filter(rel); } bool TSAL_qmsk::choose_best(TCursor& cur, const char* codtab) { const TRecnotype recs = cur.items(); if (recs > 0) { cur.freeze(); TRecnotype best = 0; double score = 0; for (cur = 0L; cur.pos() < recs; ++cur) { const TString& cod = cur.curr().get("CODTAB"); const double s = xvt_str_fuzzy_compare(cod, codtab); if (s > score) { score = s; best = cur.pos(); } } cur = best; cur.freeze(false); } return recs > 0; } bool TSAL_qmsk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_TIPOCF: if (e == fe_modify) { m_tipocf = get(F_TIPOCF); // Seleziona Clienti o Fornitori on_field_event(efield(F_CODNUM_ORD), fe_init, 0); on_field_event(efield(F_CODNUM), fe_init, 0); } break; case F_CODNUM_ORD: if (e == fe_init) { TEdit_field& codnum_ord = (TEdit_field&)o; TCursor& cur_ord = *codnum_ord.browse()->cursor(); cur_ord.set_filterfunction(ord_filter); if (choose_best(cur_ord, "ORC")) codnum_ord.browse()->do_output(STARTING_CHECK); } break; case F_CODNUM: if (e == fe_init) { TEdit_field& codnum_sal = (TEdit_field&)o; TCursor& cur_sal = *codnum_sal.browse()->cursor(); cur_sal.set_filterfunction(sal_filter); if (choose_best(cur_sal, "SAL")) { codnum_sal.browse()->do_output(RUNNING_CHECK); e = fe_modify; } } if (e == fe_modify && !o.empty()) { const TString& sal = o.get(); const TCodice_numerazione& codnum = cached_numerazione(sal); int best = 0; double score = 0; for (int i = 0; ; i++) { const TString& td = codnum.tipo_doc(i); if (td.blank()) break; const double s = xvt_str_fuzzy_compare(td, sal); if (s > score) { score = s; best = i; } } set(F_TIPODOC, codnum.tipo_doc(best), 0x2); } break; case F_NSAL: if (e == fe_modify && !o.empty()) { static bool blocked = false; if (!blocked) { blocked = true; const int nsal = atoi(o.get()); TEdit_field& fld_nsal = efield(F_NDOC); TCursor& cur_nsal = *fld_nsal.browse()->cursor(); int n = 0; for (cur_nsal = 0L; cur_nsal.ok(); ++cur_nsal) { n = cur_nsal.curr().get_int(DOC_NUMANT); if (n == nsal) break; } if (nsal > n) { o.reset(); send_key(K_SPACE, DLG_NEWREC, &o); } else { fld_nsal.browse()->do_output(); stop_run(K_AUTO_ENTER); } blocked = false; } } break; default: if (e == fe_modify && o.is_edit() && o.dlg() > F_CDC0) // Probabile commessa? { const TFieldref* fr = o.field(); if (fr != NULL && fr->name() == DOC_CODCMS) // Campo commessa { const TRectype& cur = ((TEdit_field&)o).browse()->cursor()->curr(); const long codcf = cur.get_long(COMMESSE_CODCF); if (codcf > 0) set(F_CLIFO, codcf); const int anno = cur.get_int(COMMESSE_ANNO); if (anno > 0) set(F_ANNO_ORD, anno); } } break; } return TSAL_msk::on_field_event(o, e, jolly); } TSAL_qmsk::TSAL_qmsk() : TSAL_msk("sl0100a") { TMask_field& cdc0 = field(F_CDC0); RCT rct0; cdc0.get_rect(rct0); const int yca = rct0.top / ROWY + 1; // Riga del primo campo di analitica short idcdc, idcms, idfase, idconto; ca_create_fields_ext(*this, 0, 2, yca, F_CDC0+1, idcdc, idcms, idfase, idconto, DOC_CODCOSTO, DOC_CODCMS /*, DOC_FASCMS */); // Niente fasi qui! set_handlers(); } /////////////////////////////////////////////////////////// // TSAL_emsk /////////////////////////////////////////////////////////// class TSAL_emsk : public TSAL_msk { TSAL_tree* _tree; TString80 _idfase, _iddist, _edit_fase; int _edit_dist, _edit_misu; int _curr_dist, _curr_misu; bool _locked; 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, const TDate& dt); void update_dist_qta(); bool on_misu_event(TOperable_field& o, TField_event e, long jolly); bool on_dist_event(TOperable_field& o, TField_event e, long jolly); 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_totdoc(); bool sync_tree(); bool msk2rec(const TMask& msk, TRectype& rec) const; public: TSAL_tree& tree(bool reset = false); TSAL_emsk(); }; TSAL_tree& TSAL_emsk::tree(bool reset) { if (_tree == NULL) { _tree = new TSAL_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 rec2field(TMask_field& f, const TRectype& rec) { const TFieldref* fr = f.field(); if (fr == NULL) 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 { const TString& val = fr->read(rec); f.set(val); if (!f.empty() && f.is_edit() && f.shown()) { const TBrowse* b = ((TEdit_field&)f).browse(); if (b != NULL) { const TFixed_string inf = b->get_input_fields(); const TFixed_string outf = b->get_output_fields(); if (outf.find('|') > 0) // C'č un pipe nell'output, per cui ci sono almeno due campi di output { f.check(STARTING_CHECK); } } } } return true; } static bool chk_field(TMask_field& f) { const TFieldref* fr = f.field(); if (fr == NULL) { if (f.ghost()) return f.on_hit(); } return true; } // Riempie gli sheet di articoli e misure della distinta selezionata bool TSAL_emsk::set_dist(const TString& idd) { TSAL_tree& t = tree(); bool ok = idd.full(); if (_iddist != idd) { _iddist = idd; // Svuota sheet misure TSheet_field& s = sfield(F_MISURE); s.hide(); s.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(); TMask& m = s.sheet_row_mask(n); FOR_EACH_MASK_FIELD(m, i, f) if (f->field()) rec2field(*f, rec); FOR_EACH_MASK_FIELD(m, i, c) if (c->is_edit()) chk_field(*c); s.update_row(n++); } _locked = false; } // Visualizza nuovamente lo sheet eventualemente riempito s.force_update(); s.show(); } _curr_dist = -1; if (ok && t.goto_node(idd)) { _curr_dist = 0; while(t.goto_lbrother()) _curr_dist++; } return ok; } bool TSAL_emsk::set_dist(int row) { TSAL_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 TSAL_emsk::set_fase(const TString& idfase) { _idfase = idfase; // Svuota lo sheet delle distinte TSheet_field& d = sfield(F_DISTINTE); d.destroy(); TString idd; TSAL_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) if (f->field()) rec2field(*f, rec); FOR_EACH_MASK_FIELD(m, i, c) if (c->is_edit()) chk_field(*c); d.update_row(n++); } while (t.goto_rbrother()); } } d.force_update(); set_dist(idd); return ok; } bool TSAL_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 TSAL_emsk::on_key(KEY k) { if (k == K_SHIFT + K_F12) { enable(F_STATO); return true; } return TAutomask::on_key(k); } /* bool TSAL_emsk::on_fasi_button(TOperable_field& o, TField_event e, long jolly) { TSAL_tree& t = tree(); TTree_field& fasi = t.owner(); TSAL_level pl = sl_documento; if (fasi.goto_selected()) pl = t.level(); else return false; if (pl == sl_documento && o.dlg() == F_FASENEW) pl = sl_fase1; if (pl < sl_fase1 || pl > sl_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; default: break; } o.enable(); fasi.select_current(); fasi.force_update(); return true; } */ bool TSAL_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; switch (e) { case fe_modify: if (fasi.goto_selected()) { modified = true; TSAL_tree& t = tree(); TSAL_level td = t.level(); if (td > sl_documento) { can_edit = true; can_goup = t.has_lbrother(); can_godn = t.has_rbrother(); if (td < sl_distinta) // Cambio fase { TString16 id; t.curr_id(id); set_fase(id); } else { while (td > sl_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); return true; } bool TSAL_emsk::on_dist_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case S_CODART: if (e == fe_modify && !o.empty()) { const TString& codart = o.get(); TMask& m = o.mask(); TToken_string tok; tok << codart << "|1"; const TString& um = cache().get(LF_UMART, tok, "UM"); if (um.full()) m.set(S_UMART, um); TEdit_field& iva = m.efield(S_CODIVA); if (iva.empty()) on_dist_event(iva, fe_init, jolly); } break; case S_CODIVA: if ((e == fe_init || e == fe_close) && o.empty()) { const TString& codcms = fget(DOC_CODCMS); TString4 codiva = cache().get(LF_COMMESSE, codcms, COMMESSE_CODIVA); if (codiva.blank()) { const TString& codart = o.mask().get(S_CODART); codiva = cache().get(LF_ANAMAG, codart, ANAMAG_CODIVA); } o.set(codiva); } 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: { TSAL_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_fase = _idfase; _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(_edit_fase, r, false); if (rec != NULL) { const TSheet_field& sheet = (TSheet_field&)o; const TMask& m = sheet.sheet_row_mask(r); msk2rec(m, *rec); sync_tree(); } } break; case se_notify_del: if (_curr_dist >= 0) { TSAL_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; } bool TSAL_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 = sfield(F_MISURE); 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_fase = _idfase; _edit_dist = _curr_dist; _edit_misu = _curr_misu = jolly; break; case se_leave: case se_notify_modify: if (_edit_dist >= 0 && _edit_misu >= 0) { TSAL_tree& t = tree(); t.dist(_edit_fase, _edit_dist, false); TString idd; t.curr_id(idd); TRectype* rec = t.misu(idd, _edit_misu, false); 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) { TSAL_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 TSAL_emsk::update_dist(const real& val, const TDate& dt_new) { TSheet_field& dist = sfield(F_DISTINTE); TToken_string& row = dist.row(_curr_dist); row.add(val.string(), dist.cid2index(S_QTA)); if (dt_new.ok()) { TDate dt_old; row.get(dist.cid2index(S_DATALAV), dt_old); if (dt_new > dt_old) row.add(dt_new.string(), dist.cid2index(S_DATALAV)); } dist.update_mask(_curr_dist); TOperable_field& o = dist.sheet_row_mask(_curr_dist).efield(S_QTA); 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 TSAL_emsk::update_dist_qta() { if (_curr_dist >= 0) { TSheet_field& sheet = sfield(F_MISURE); real tot; TDate data_lavori; FOR_EACH_SHEET_ROW(sheet, i, row) { tot += real(row->get(sheet.cid2index(106))); // 106 = totale const TDate data = row->get(); if (data > data_lavori) data_lavori = data; } update_dist(tot, data_lavori); sync_tree(); } } struct SAL_tot : public TObject { real _totdoc; real _sicurezza; real _esclusi; real _t_totdoc; real _t_sicurezza; real _t_esclusi; }; static bool calc_totdoc(TTree& tree, void* jolly, word) { const TSAL_tree& t = (const TSAL_tree&)tree; const TRectype& rec = *t.curr_row(); if (t.level(rec) == sl_distinta) { const real qta = rec.get(RDOC_QTA); // da 3 a 5 decimali const real prz = rec.get(RDOC_PREZZO); // da 0 a 3 decimali if (!qta.is_zero() && !prz.is_zero()) { const int tipo = rec.get_int(RDOC_TIPODET); // 0=lavori, ..., 3=Sicurezza, 4=esclusi const TCurrency parziale(real(qta * prz)); // arrotonda all'euro const real& imp = parziale.get_num(); SAL_tot& tot = *(SAL_tot*)jolly; tot._totdoc += imp; switch (tipo) { case 3: tot._sicurezza += imp; break; case 4: tot._esclusi += imp; break; default: break; } } } return false; } bool TSAL_emsk::sync_totdoc() { TSAL_tree& t = tree(); if (!t.goto_root()) return false; const bool attivo = get(F_TIPOCF)[0] != 'F'; const TRectype& doc = *t.curr_row(); real importo_base, sicurezza_cantiere; TString4 codiva; SAL_tot tot; t.scan_depth_first(calc_totdoc, &tot); if (t.goto_firstson()) { const TRiga_documento* row = (TRiga_documento*)t.curr_row(); const TRectype* ord = row->find_original_doc(); if (ord != NULL) { const TVariable_rectype ordine(*ord); importo_base = ordine.get_real("TOTDOC"); if (!attivo) { TDocumento orig(*ord); FOR_EACH_PHYSICAL_RDOC(orig, r, rdoc) { codiva = rdoc->get(RDOC_CODIVA); if (codiva.full()) break; } } } } const TRectype& cantiere = cache().get(LF_COMMESSE, doc.get(DOC_CODCMS)); const real& lor = tot._totdoc; const real& esc = tot._esclusi; real sic = tot._sicurezza; real prib; if (attivo) { if (importo_base.is_zero()) importo_base = cantiere.get_real(COMMESSE_IMPORTOB); sicurezza_cantiere = cantiere.get_real(COMMESSE_SICUREZZA); prib = cantiere.get_real(COMMESSE_RIBASSO); if (codiva.blank()) codiva = cantiere.get(COMMESSE_CODIVA); } set(F_SAL_LOR, lor); if (sic.is_zero() && !importo_base.is_zero()) { sic = lor * sicurezza_cantiere / importo_base; sic.round(2); } set(F_SAL_SIC, sic); set(F_SAL_ESC, esc); const real sicesc = sic + esc; set(F_SAL_SIC2, sicesc); const real idr = lor - sicesc; set(F_SAL_IDR, idr); set(F_SAL_PRIB, prib); real rib = idr * prib / CENTO; rib.round(2); set(F_SAL_RIB, rib); const real irb = idr - rib; set(F_SAL_IRB, irb); const real sal = irb + sicesc; set(F_SAL_SAL, sal); real pgar = ZERO; const TString& exp_gar = get(F_PGARANZIA); if (exp_gar.full()) { TString80 dummy; if (scontoexpr2perc(exp_gar, false, dummy, pgar)) pgar = (UNO-pgar)*CENTO; } set(F_SAL_PGAR, pgar); real gar = sal * pgar / CENTO; gar.round(2); set(F_SAL_GAR, gar); real ant = ZERO; real pant = ZERO; const TString& exp_ant = get(F_PANTICIPO); if (exp_ant.full()) { TString80 dummy; real eant = ZERO; if (scontoexpr2perc(exp_ant, false, dummy, eant)) { pant = (UNO-eant)*CENTO; ant = sal * pant / CENTO; ant.round(2); } } set(F_SAL_PANT, pant); set(F_SAL_ANT, ant); const real net = sal - ant - gar; set(F_SAL_NET, net); real piva = ZERO; if (codiva.full()) piva = real(cache().get("%IVA", codiva, "R0")); real iva = net * piva / CENTO; iva.round(2); set(F_SAL_PIVA, piva); set(F_SAL_IVA, iva); set(F_SAL_TOT, real(net + iva)); return !sal.is_zero(); } bool TSAL_emsk::sync_tree() { TSAL_tree& t = tree(); TTree_field& tf = t.owner(); tf.force_update(); return sync_totdoc(); } bool TSAL_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: if (e == fe_button) return on_fasi_button(o, e, jolly); break; */ case F_DISTINTE: return on_dist_event(o, e, jolly); case F_MISURE: return on_misu_event(o, e, jolly); case DLG_PRINT: if (e == fe_button) app().report("sl1600"); break; case B_PRINT_LIB: if (e == fe_button) app().report("sl1400"); break; case B_PRINT_REG: if (e == fe_button) app().report("sl1500"); break; case DLG_ELABORA: if (e == fe_button) { const TString16 cod = sl_trova_elaborazione(*this); if (cod.full()) { app().rewrite(*this); sl_genera_documento(app().get_relation()->curr(), cod); } } break; case DLG_ARCHIVE: if (e == fe_button) { } break; case F_SAL_TOT: if (e == fe_init && o.empty()) sync_totdoc(); break; default: if (jolly > 0 && o.dlg() >= DLG_USER && o.dlg() < 2*DLG_USER) // Sheet mask events { if (e == fe_modify) { switch (jolly) { case 1: return on_dist_event(o, e, jolly); case 2: return on_misu_event(o, e, jolly); default: CHECK(false, "Unknown sheet field event"); break; } } } break; } return TSAL_msk::on_field_event(o, e, jolly); } void TSAL_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); } TSAL_emsk::TSAL_emsk() : TSAL_msk("sl0100b"), _tree(NULL), _locked(false) { TMask_field& cdc0 = field(F_CDC0); RCT rct0; cdc0.get_rect(rct0); const int yca = rct0.top / ROWY + 1; // Riga del primo campo di analitica short idcdc, idcms, idfase, idconto; ca_create_fields_ext(*this, 0, 2, yca, F_CDC0+1, idcdc, idcms, idfase, idconto, DOC_CODCOSTO, DOC_CODCMS /*, DOC_FASCMS */); // Niente fasi qui! set_sheet_color(F_DISTINTE, COLOR_YELLOW); set_sheet_color(F_MISURE, COLOR_GRAY); } /////////////////////////////////////////////////////////// // TSAL_app /////////////////////////////////////////////////////////// bool TSAL_app::user_create() { open_files(LF_TAB, LF_TABCOM, LF_CLIFO, LF_ANAMAG, LF_UMART, LF_DOC, LF_RIGHEDOC, LF_COMMESSE, LF_FASI, 0); _rel = new TRelation(LF_DOC); _qmsk = new TSAL_qmsk; _emsk = new TSAL_emsk; return true; } bool TSAL_app::user_destroy() { delete _emsk; delete _qmsk; delete _rel; return true; } const char* TSAL_app::record_description(const TRelation& r) const { TString& tmp = get_tmp_string(); tmp << title() << " n." << r.curr().get(DOC_NUMANT); return tmp; } TCursor& TSAL_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; } int TSAL_app::read(TMask& m) { int err = TRelation_application::read(m); if (err == NOERR) { const TRectype& doc = get_relation()->curr(); TSAL_tree& t = ((TSAL_emsk&)m).tree(); t.load(doc); } return err; } static bool tree_save_row(TTree& tree, void* jolly, word /*flags*/) { TSAL_tree& t = (TSAL_tree&)tree; const TRectype* rec = t.curr_row(); if (rec && !rec->empty() && rec->num() == LF_RIGHEDOC) { const char* full_field[] = { RDOC_DESCR, RDOC_QTA, RDOC_PREZZO, RDOC_QTAGG1, RDOC_QTAGG2, RDOC_QTAGG3, RDOC_QTAGG4, RDOC_QTAGG5, RDOC_DATACONS, NULL } ; bool one_full = false; for (int f = 0; full_field[f] && !one_full; f++) { if (f == 0) one_full = rec->get(full_field[f]).full(); else one_full = !rec->get_real(full_field[f]).is_zero(); } if (one_full) { 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_QTAEVASA, rec->get(RDOC_QTAEVASA)); 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)); row.put(RDOC_DATACONS, rec->get(RDOC_DATACONS)); row.put(RDOC_TIPOCOLL, rec->get(RDOC_TIPOCOLL)); row.put(RDOC_IDRIGACOLL,rec->get(RDOC_IDRIGACOLL)); row.put(RDOC_TIPODET, rec->get(RDOC_TIPODET)); row.put(RDOC_CODCMS, doc.get(RDOC_CODCMS)); // Commessa/cantiere da DOC row.put(RDOC_FASCMS, rec->get(RDOC_FASCMS)); // Fase specifica da riga } } return false; // Don't stop scan } int TSAL_app::save_rows(const TMask& m) { TSAL_emsk& sm = (TSAL_emsk&)m; TSAL_tree& tree = sm.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 const TString80 cdc = sm.fget(DOC_CODCOSTO); const TString80 cms = sm.fget(DOC_CODCMS); TRecord_array& rdoc = doc.body(); rdoc.renum_key(RDOC_CODCOSTO, cdc); rdoc.renum_key(RDOC_CODCMS, cms); rdoc.renum_key(RDOC_DAPROVV, "D"); rdoc.renum_key(RDOC_DAANNO, _qmsk->get(F_ANNO_ORD)); rdoc.renum_key(RDOC_DACODNUM, _qmsk->get(F_CODNUM_ORD)); rdoc.renum_key(RDOC_DANDOC, _qmsk->get(F_NDOC_ORD)); FOR_EACH_MASK_FIELD(sm, i, f) { const TFieldref* fr = f->field(); if (fr != NULL) { const TString& value = f->get(); if (fr->name().starts_with("G1:")) { const TString& fname = fr->name().mid(3); doc.put(fname, value); } else fr->write(value, doc.head()); } } const int err = doc.rewrite(get_relation()->file()); return err; } int TSAL_app::write(const TMask& m) { get_relation()->curr().zero("G1"); int err = TRelation_application::write(m); if (err == NOERR) err = save_rows(m); return err; } int TSAL_app::rewrite(const TMask& m) { get_relation()->curr().zero("G1"); int err = TRelation_application::rewrite(m); if (err == NOERR) err = save_rows(m); return err; } bool TSAL_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 TSAL_app::update_tools(TMask& m) { const bool is_edit = m.edit_mode(); bool can_print = is_edit; if (can_print) { TFilename rep = "sl1400.rep"; // Libretto delle misure can_print = rep.custom_path(); } m.enable(DLG_NEWREC, is_edit); m.enable(DLG_PRINT, can_print); m.enable(DLG_ELABORA, sl_trova_elaborazione(m).full()); m.enable(B_PRINT_LIB, can_print); m.enable(B_PRINT_REG, can_print); m.disable(F_STATO); // Enable with F12 } bool TSAL_app::get_next_key(TToken_string& key) { const char provv = _qmsk->get(F_PROVV)[0]; const int anno = _qmsk->get_int(F_ANNO); const TString& codnum = _qmsk->get(F_CODNUM); if (anno < 2000 || codnum.blank()) return false; // Rinumera con anno e numerazione validi long newdoc = 1L; TLocalisamfile doc(LF_DOC); doc.put(DOC_PROVV, provv); doc.put(DOC_ANNO, anno); doc.put(DOC_CODNUM, codnum); doc.put(DOC_NDOC, 9999999); int err = doc.read(_isgreat); if (err == NOERR) err = doc.prev(); else err = doc.last(); if (err == NOERR && doc.get(DOC_CODNUM) == codnum) newdoc += doc.get_long(DOC_NDOC); key.cut(0); key.add(F_PROVV); key.add(provv); key.add(F_ANNO); key.add(anno); key.add(F_CODNUM); key.add(codnum); key.add(F_NDOC); key.add(newdoc); return true; } void TSAL_app::init_insert_mode(TMask& m) { TRelation_application::init_insert_mode(m); m.set(F_DATADOC, TDate(TODAY)); long nsal = 1; const char ord_provv = _qmsk->get(F_PROVV)[0]; const int ord_anno = _qmsk->get_int(F_ANNO_ORD); const TString& ord_codnum = _qmsk->get(F_CODNUM_ORD); const long ord_ndoc = _qmsk->get_long(F_NDOC_ORD); TString filter; filter.format("DAPROVV=%c DAANNO=%d DACODNUM=%s DANDOC=%ld", ord_provv, ord_anno, (const char*)ord_codnum, ord_ndoc); TString query; query << "USE 34 KEY 4\nJOIN 33 INTO PROVV=PROVV ANNO=ANNO CODNUM==CODNUM NDOC==NDOC\n" << "FROM " << filter << "\nTO " << filter; TISAM_recordset rsal(query); if (rsal.move_last()) nsal += rsal.cursor()->curr(LF_DOC).get_int(DOC_NUMANT); m.set(F_NSAL, nsal); TSAL_tree& t = ((TSAL_emsk&)m).tree(); const TRectype* model = &rsal.cursor()->curr(LF_DOC); // Usa come modello l'ultimo SAL if (nsal <= 1) // Primo SAL { const TEdit_field& fld_ord = _qmsk->efield(F_NDOC_ORD); model = &fld_ord.browse()->cursor()->curr(LF_DOC); // Usa come modello l'ordine // Copia anticipo e granzia cliente if (model->get_char(DOC_TIPOCF) != 'F') { const TRectype& cms = cache().get(LF_COMMESSE, model->get(DOC_CODCMS)); m.set(F_PANTICIPO, cms.get(COMMESSE_ANTICIPO)); m.set(F_PGARANZIA, cms.get(COMMESSE_GARANZIA)); } } TSAL_msk& sm = (TSAL_msk&)m; FOR_EACH_MASK_FIELD(sm, i, f) { if (f->empty() && f->active() && f->field() != NULL) { const TString& name = f->field()->name(); sm.fset(name, model->get(name), 0x2); } } t.load(*model, nsal); update_tools(m); } void TSAL_app::init_modify_mode(TMask& m) { TRelation_application::init_modify_mode(m); update_tools(m); } void TSAL_app::print() { app().report("sl1400"); } bool TSAL_app::report(const char* name) { static bool already_printing = false; if (already_printing) return false; already_printing = true; TFilename rep = name; rep.ext("rep"); if (!rep.custom_path()) return cantread_box(rep.name()); if (rewrite(*_emsk) != NOERR) return cantwrite_box("SAL"); TFilename ini; ini.tempdir(); ini.add(name); ini.ext("ini"); if (ini.full()) { TConfig cfg(ini, "Transaction"); cfg.set("Action", printer().printtype() == screenvis ? "Preview" : "Print"); cfg.set_paragraph("Vars"); cfg.remove_all(); TSAL_msk& sm = *(TSAL_msk*)_emsk; FOR_EACH_MASK_FIELD(sm, i, f) if (f->is_edit() && !f->empty()) { const TFieldref* field = f->field(); if (field != NULL && field->from() == 0) { const TString& name = field->name(); cfg.set(name, sm.fget(name)); } } cfg.set(RDOC_DAPROVV, _qmsk->get(F_PROVV)); cfg.set(RDOC_DAANNO, _qmsk->get(F_ANNO_ORD)); cfg.set(RDOC_DACODNUM, _qmsk->get(F_CODNUM_ORD)); cfg.set(RDOC_DANDOC, _qmsk->get(F_NDOC_ORD)); } TString cmd; cmd << "ba8 -4 " << rep; if (ini.exist()) cmd << " -i" << ini; TExternal_app a(cmd); a.run(); already_printing = false; return true; } int sl0100(int argc, char* argv[]) { TSAL_app a; a.run(argc, argv, TR("S.A.L.")); return 0; }