#include "sl0100a.h" #include "sl0101.h" #include #include #include #include #include "../ca/calib01.h" #include "../ca/fasi.h" #include "../ve/velib.h" static bool cmscpy(TRectype& dst, const TRectype& src) { const TString& cms_in = src.get(RDOC_CODCMS); if (cms_in.blank()) { NFCHECK("Commessa nulla"); return false; } const TString& cms_out = dst.get(RDOC_CODCMS); if (cms_in == cms_out) return true; if (!cms_out.blank()) NFCHECK("Commessa incoerente"); dst.put(RDOC_CODCMS, cms_in); return true; } bool TSAL_tree::add_lastson(TObject* obj) { CHECK(obj != NULL && obj->is_kind_of(CLASS_RECTYPE), "Record non valido per SAL"); TRectype& rec = *(TRectype*)obj; CHECK(rec.get(RDOC_TIPORIGA).full(), "TIPORIGA vuoto"); cmscpy(rec, *curr_row()); bool done = false; if (goto_firstson()) // Se ha almeno un figlio ... { while (goto_rbrother()); // ... allora vai all'ultimo fratello done = add_rbrother(obj); // ed aggiungi ultimo fratello } else done = add_son(obj); // Aggiungi primogenito return done; } TSAL_level TSAL_tree::last_fase_level() const { return (TSAL_level)_picture_fasi.items(); } bool TSAL_tree::goto_last_fase(TSAL_level sublevel) { bool ok = goto_root() && goto_firstson(); if (ok) { while (goto_rbrother()); // goto last son if (sublevel > sl_fase1) { //TSAL_level max_lev = last_fase_level(); //if (sublevel < max_lev) // max_lev = sublevel; while (level() < sublevel) { if (goto_firstson()) while (goto_rbrother()); else break; } ok = level() == sublevel; } } return ok; } bool TSAL_tree::goto_last_dist() { bool ok = goto_last_fase(sl_distinta); // sl_distinta = dummy value for maximum depth if (ok) while (goto_rbrother()); return ok; } TRectype* TSAL_tree::new_row(TSAL_level level) const { const TMask& m = owner().mask(); TRectype* rec = new TRectype(level == sl_documento ? LF_DOC : LF_RIGHEDOC); rec->put(RDOC_PROVV, 'D'); rec->put(RDOC_ANNO, m.get(F_ANNO)); rec->put(RDOC_CODNUM, m.get(F_CODNUM)); rec->put(RDOC_NDOC, m.get(F_NDOC)); TString cantiere; for (short id = F_CDC0+1; m.id2pos(id) > 0; id++) cantiere << m.get(id); rec->put(RDOC_CODCMS, cantiere); switch (level) { case sl_documento: rec->put(DOC_NUMANT, m.get(F_NSAL)); break; case sl_distinta: rec->put(RDOC_TIPORIGA, tipo_dist()); rec->put(RDOC_DESCR, TR("Nuova distinta")); cmscpy(*rec, *curr_row()); break; case sl_misura: rec->put(RDOC_TIPORIGA, tipo_misu()); rec->put(RDOC_DESCR, TR("Nuova misura")); cmscpy(*rec, *curr_row()); break; default: rec->put(RDOC_TIPORIGA, tipo_fasi()); rec->put(RDOC_DESCR, TR("Nuova fase")); rec->put(RSAL_LEVEL, level-sl_fase1); break; } return rec; } static bool find_fase_cb(TTree& node, void* jolly, word /*when*/) { const TSAL_tree& tree = (TSAL_tree&)node; const TSAL_level lev = tree.level(); if (lev < sl_fase1 || lev >= sl_distinta) return false; const TString& fascms = *((TString*)jolly); const TRectype& rec = *tree.curr_row(); const TString& fase = rec.get(RDOC_FASCMS); return fase == fascms; } TRectype* TSAL_tree::fase(const TString& fase, bool create) { TRectype* rec = NULL; if (goto_root() && scan_breadth_first(find_fase_cb, (void*)&fase)) rec = curr_row(); else if (create) { if (goto_root()) { rec = new_row(sl_fase1); rec->put(RDOC_FASCMS, fase); TToken_string key; key = rec->get(RDOC_CODCMS); key.add(fase); TString80 descr = cache().get(LF_FASI, key, FASI_DESCRIZ); if (descr.empty()) { key.add(" ", 0); descr = cache().get(LF_FASI, key, FASI_DESCRIZ); } if (descr.full()) rec->put(RDOC_DESCR, descr); add_lastson(rec); } } return rec; } TRectype* TSAL_tree::dist(const TString& fase, int n, bool create) { TRectype* rec = NULL; if (goto_node(fase)) { if (goto_firstson()) { int i = 0; for (; i < n && goto_rbrother(); i++); if (i < n) { if (create) add_rbrother(rec = new_row(sl_distinta)); } else rec = curr_row(); } else { if (create) add_son(rec = new_row(sl_distinta)); } } return rec; } TRectype* TSAL_tree::misu(const TString& dist, int n, bool create) { TRectype* rec = NULL; if (goto_node(dist)) { CHECKS(level() == sl_distinta, "Distinta non valida", (const char*)dist); if (goto_firstson()) { int i = level() == sl_misura ? 0 : -1; while (i < n && goto_rbrother()) if (level() == sl_misura) i++; if (i < n) { if (create) add_rbrother(rec = new_row(sl_misura)); } else rec = curr_row(); } else { if (create && n == 0) add_son(rec = new_row(sl_misura)); } } return rec; } TSAL_level TSAL_tree::level(const TRectype& rec) const { TSAL_level lev = sl_documento; if (rec.num() == LF_RIGHEDOC) { const TString& t = rec.get(RDOC_TIPORIGA); if (t.full()) { lev = sl_fase1; if (t == _strFasi) lev = TSAL_level(lev + rec.get_int(RSAL_LEVEL)); else if (t == _strDist) lev = sl_distinta; else if (t == _strMisu) lev = sl_misura; } } return lev; } TSAL_level TSAL_tree::level() const { TSAL_level lev = sl_documento; TRectype* rec = curr_row(); if (rec != NULL) lev = level(*rec); return lev; } bool TSAL_tree::could_have_son() const { return level() < sl_distinta; } bool TSAL_tree::get_description(TString& str) const { const TRectype* rec = curr_row(); bool ok = rec != NULL && !rec->empty(); if (ok) { if (rec->num() == LF_DOC) { const TMask& m = owner().mask(); str.cut(0) << TR("SAL ") << m.get(F_NSAL) << TR(" del ") << m.get(F_DATADOC); } else if (rec->num() == LF_RIGHEDOC) { str = rec->get(RDOC_DESCR); if (str.blank()) str = rec->get(RDOC_CODCMS); } else NFCHECK("Bad tree record"); } else NFCHECK("NULL tree record"); return ok; } TFieldtypes TSAL_tree::get_var(const TString& name, TVariant& var) const { TFieldtypes ft = _nullfld; const TRectype* rec = curr_row(); if (rec != NULL && !rec->empty()) { if (rec->num() == LF_DOC) { const TMask& m = owner().mask(); if (name == RDOC_CODART) { var = m.get(F_NDOC); ft = _alfafld; } else if (name == RDOC_DESCR) { TString str; get_description(str); const int spc = str.find('\n'); if (spc > 0) str.cut(spc); var = str; ft = _alfafld; } else if (name == RDOC_PREZZO || name == RSAL_COSTO) { real c, p; ((TSAL_tree*)this)->ricalcola(c, p); if (name == RDOC_PREZZO ) var = p.stringa(0,2); else var = c.stringa(0,2); ft = _realfld; } } else { ft = rec->type(name); if (ft > _nullfld) { const TSAL_level livello = level(*rec); if (ft == _realfld) { if ((name == RDOC_PREZZO || name == RSAL_COSTO) && livello == sl_distinta) { real c, p; ((TSAL_tree*)this)->ricalcola(c, p); if (name == RDOC_PREZZO ) var = p.stringa(0,2); else var = c.stringa(0,2); } else var = rec->get_real(name).stringa(0, 2); } else { if (name == RDOC_CODART && livello < sl_distinta) { TString16 fase = rec->get(RDOC_FASCMS); if (fase.blank()) { fase = rec->get(RDOC_CODART); if (livello < _picture_fasi.items()) { const TString& pic = _picture_fasi.row(livello-1); const int len = pic.len(); if (pic[0] == '0') fase.right_just(len, '0'); else fase.left_just(len, ' '); } ((TRectype*)rec)->put(RDOC_FASCMS, fase); } var = fase; } else var = rec->get(name); } } } } return ft; } TImage* TSAL_tree::image(bool sel) const { const TSAL_level pl = level(); if (pl <= sl_distinta) { const bool ex = expanded(); if (has_son()) return get_res_image(ex ? BMP_DIRDNSEL : BMP_DIRSEL); else return get_res_image(ex ? BMP_DIRDN : BMP_DIR); } return TObject_tree::image(sel); } // Aggiunge un record alla fine dell'albero in base al tipo della riga (usato solo in lettura iniziale) bool TSAL_tree::append_row(const TRectype& rec) { const TSAL_level pl = level(rec); if (pl == sl_documento) { // Se aggiungo un documento allora svuoto albero e ricreo radice if (goto_root()) kill_node(); return add_son(rec); } else if (pl == sl_distinta) { const TString16 fascms = rec.get(RDOC_FASCMS); bool ok = false; if (fascms.full()) ok = fase(fascms, true) != NULL; else ok = goto_last_dist(); return ok && add_lastson(rec); } else if (pl == sl_misura) { if (goto_last_dist()) return add_lastson(rec); } else { goto_root(); while (level() < pl) { if (goto_firstson()) while (goto_rbrother()); else break; } if (level() < pl) return add_lastson(rec); else return add_rbrother(rec); } return false; } bool TSAL_tree::ricalcola(real& costo, real& prezzo) { bool ok = false; const TSAL_level lev = level(); costo = prezzo = ZERO; if (lev < sl_distinta && has_son()) { TString16 id; curr_id(id); for (bool go = goto_firstson(); go; go = goto_rbrother()) { real c, p; if (ricalcola(c, p)) { costo += c; prezzo += p; } } ok = goto_node(id); if (lev >= sl_fase1) { TRectype& rec = *curr_row(); rec.put(RDOC_QTA, 1); rec.put(RSAL_COSTO, costo); rec.put(RDOC_PREZZO, prezzo); } } else { ok = lev == sl_distinta; if (ok) { const TRectype& rec = *curr_row(); const real qta = rec.get_real(RDOC_QTA); if (!qta.is_zero()) { costo = qta * rec.get_real(RSAL_COSTO); prezzo = qta * rec.get_real(RDOC_PREZZO); } } } return ok; } bool TSAL_tree::load(const TRectype& doc, int nsal) { TLog_report log; // Lettura righe documento 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)); TRecord_array rdoc(keytok, LF_RIGHEDOC); // Svuota automaticamente albero e crea documento radice bool done = append_row(doc); if (done) { // Caricamento righe nell'albero const int last_row = rdoc.last_row(); TString16 curr_fase; for (int r = rdoc.first_row(); r > 0 && r <= last_row; r = rdoc.succ_row(r)) { TRectype& rr = rdoc[r]; const TSAL_level sl = level(rr); const TString& fase = rr.get(RDOC_FASCMS); if (fase.blank()) { if (sl < sl_distinta) curr_fase = rr.get(RDOC_CODART); rr.put(RDOC_FASCMS, curr_fase); } else curr_fase = fase; // Gestione copia da ordine o SAL precedente if (nsal > 0 && sl >= sl_distinta) { if (sl >= sl_misura) continue; // Non copiare le misure! const real qta = rr.get(RDOC_QTA); if (nsal == 1) // nsal=1 -> copia da ordine { rr.put(RDOC_DAIDRIGA, rr.get(RDOC_IDRIGA)); rr.put(RDOC_QTAGG1, qta); // Inizializza totale riga ordine rr.put(RDOC_QTAGG2, ZERO); // Totale SAL precedenti (nessuno nel primo SAL) rr.put(RDOC_QTAGG3, qta); // Residuo (nel primo SAL è uguale alla qta) const TString& sconto = rr.get(RDOC_SCONTO); if (sconto.full()) { const real impns = prezzo_scontato(rr.get_real(RDOC_PREZZO), sconto); if (!impns.is_zero()) rr.put(RDOC_PREZZO, impns); } } else { rr.add(RDOC_QTAGG2, qta); // Aggiorna totale precedente quando copi da SAL rr.add(RDOC_QTAGG3,-qta); // Aggiorna residuo quando copi da SAL } rr.zero(RDOC_QTA); // Azzera quantità sempre } if (!append_row(rr)) { TString msg; msg.format("Impossibile caricare la riga %d di tipo %s:\n%s", rr.get_int(RDOC_NRIGA), (const char*)rr.get(RDOC_TIPORIGA), (const char*)rr.get(RDOC_DESCR)); log.log(2, msg); done = false; } } // fine caricamento riga TMask& m = owner().mask(); if (nsal > 1) // A partire dal secondo sal aggiorno i progressivi di testata P_SAL_* { const TDocumento prec(doc); FOR_EACH_MASK_FIELD(m, i, f) { const TFieldref* ref = f->field(); if (ref != NULL && ref->name().starts_with("G1:P_SAL_")) { const real p_val = ref->read(prec); TString16 name = ref->name(); name.ltrim(5); const real val = prec.get(name); const real progr = p_val + val; f->set(progr.string()); } } } const real p_sic2 = m.get_real(F_P_SAL_SIC) + m.get_real(F_P_SAL_ESC); m.set(F_P_SAL_SIC2, p_sic2); } else { TString msg; msg.format("Impossibile caricare il documento %s", (const char*)keytok); log.log(2, msg); } // Espansione della sola radice shrink_all(); goto_root(); expand(); owner().force_update(); if (!done) log.preview(); return done; } TSAL_tree::TSAL_tree(TTree_field& owner) : _owner(owner) { // Legge i tipi riga standard per determinare i nodi dell'albero _strFasi = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaFase", "05"); _strDist = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaDist", "P1"); _strMisu = ini_get_string(CONFIG_DITTA, "pe", "TipoRigaMisu", "P2"); TConfig& cfg = ca_config(); for (int i = 1; i <= 4; i++) { const TString& pic = cfg.get("Fsc", "ca", i); if (pic.full()) _picture_fasi.add(pic); else break; } }