#include #include #include #include #include #include #include #include #include #include #include #include "calib01.h" #include "calib02.h" #include "calibmsk.h" #include "../cg/cg2103.h" #include "cdc.h" #include "commesse.h" #include "fasi.h" #include "movana.h" #include "rmovana.h" #include "rip.h" #include "rrip.h" #include "saldana.h" /////////////////////////////////////////////////////////// // TConfig_anal /////////////////////////////////////////////////////////// class TConfig_anal : public TConfig { bool _has_ca; bool _has_cm; public: virtual const TString& get(const char* var, const char* section = NULL, int index = -1, const char* def = ""); TConfig_anal(); }; TConfig_anal::TConfig_anal() : TConfig(CONFIG_DITTA, "ca"), _has_ca(dongle().active(CAAUT)), _has_cm(dongle().active(CMAUT)) { } const TString& TConfig_anal::get(const char* varname, const char* section, int index, const char* def) { if (_has_ca) return TConfig::get(varname, section, index, def); if (_has_cm) { const TFixed_string var(varname); TString& tmp = get_tmp_string(); //se il valore della variabile sul .ini e' vuoto controlla se e' possibile assegnarlo di default if (var == "AttFasi") tmp = "X"; else if (var == "Level" && index == 1) tmp = "CMS"; else if (var == "Cms" && index == 1) tmp = TConfig::get(var, section, 1, "LLLLLLLLLLLLLLLLLLLL"); else if (var == "CmsDes" && index == 1) tmp = TR("Commessa"); else if (var == "Fsc" && index == 1) tmp = TConfig::get(var, section, 1, "LLLLLLLLLL"); else if (var == "FscDes" && index == 1) tmp = TR("Fase"); else if (var == "EdMask") tmp = "ca0300a"; else if (var == "UsePdcc") tmp = "X"; return tmp; } return EMPTY_STRING; } TConfig& ca_config(bool force_reload) { static TConfig_anal* cfg = NULL; if (cfg == NULL || force_reload) { if (cfg != NULL) delete cfg; cfg = new TConfig_anal; } return *cfg; } /////////////////////////////////////////////////////////// // TMultilevel_code_info /////////////////////////////////////////////////////////// int TMultilevel_code_info::levels() const { return _picture.items(); } const TString& TMultilevel_code_info::picture(int level) const { if (level < 0 || level >= levels()) return EMPTY_STRING; return _picture.row(level); } bool TMultilevel_code_info::is_required(int level) const { return level <= 0; } bool TMultilevel_code_info::is_numeric_picture(int level) const { const TString& pic = picture(level); if (pic.full()) { int i; // Tutti 0 e 9 for (i = 0; pic[i] == '0' || pic[i] == '9'; i++); if (pic[i] == '\0') return true; } return false; } int TMultilevel_code_info::len(int level) const { return picture(level).len(); } int TMultilevel_code_info::total_len(int level) const { const int max_lev = levels(); if (level < 0) // -1 = fino al penultimo level = max_lev+level-1; int l = 0; for (int i = 0; i <= level && i < max_lev; i++) l += picture(i).len(); return l; } const TString& TMultilevel_code_info::prompt(int level) const { if (level < 0 || level >= _prompt.items()) return EMPTY_STRING; return _prompt.row(level); } const TFieldref& TMultilevel_code_info::fieldref(int level, int key) const { const TArray& a = key <= 1 ? _key1_fields : _key2_fields; const TFieldref& fr = (const TFieldref&)a[level]; return fr; } const char* TMultilevel_code_info::get_key_fieldname(int k) const { const RecDes& rd = prefix().get_recdes(_logicnum); CHECKD(k > 0 && k <= rd.NKeys, "Invalid key ", k); const KeyDes& ky = rd.Ky[k-1]; int idx = 0; if (k == 1 && (_logicnum == LF_TAB || _logicnum == LF_TABCOM || _logicnum == LF_FASI)) idx = 1; const int pos = ky.FieldSeq[idx] % MaxFields; return rd.Fd[pos].Name; } bool TMultilevel_code_info::get_cfg_vars(TString& key, TString& des) const { switch (_logicnum) { case LF_PCONANA : key = "Pdci"; des = "PdciDes"; break; case LF_CDC : key = "CdC"; des = "CdCDes"; break; case LF_COMMESSE: key = "Cms"; des = "CmsDes"; break; case LF_FASI : key = "Fsc"; des = "FscDes"; break; default: break; } return key.not_empty(); } void TMultilevel_code_info::add_fieldref(int k, int from, int to) { TArray& a = k == 1 ? _key1_fields : _key2_fields; TString80 str = get_key_fieldname(k); if (from > 0) str << '[' << from << ',' << to << ']'; TFieldref* fr = new TFieldref(str, _logicnum); a.add(fr); } int TMultilevel_code_info::pack(TString& code) const { code.strip("|"); return levels(); } int TMultilevel_code_info::unpack(TString& code) const { const int lev = levels(); if (lev > 1) { for (int i = lev-2; i >= 0; i--) code.insert("|", total_len(i)); } return lev; } TMultilevel_code_info::TMultilevel_code_info(int logicnum) : _logicnum(logicnum), _parentnum(0) { if (_logicnum == LF_PCON) { _key1_fields.add(new TFieldref(PCN_GRUPPO, LF_PCON)); _picture.add("999"); _prompt.add(TR("Gruppo")); _key1_fields.add(new TFieldref(PCN_CONTO, LF_PCON)); _picture.add("999"); _prompt.add(TR("Conto")); _key1_fields.add(new TFieldref(PCN_SOTTOCONTO, LF_PCON)); _picture.add("999999"); _prompt.add(TR("Sottoconto")); _key2_fields.add(new TFieldref(PCN_DESCR, LF_PCON)); } else { TConfig& cfg = ca_config(); if (logicnum == LF_FASI) { const TString& father = cfg.get("FathFasi"); if (father == "CMS") _parentnum = LF_COMMESSE; else if (father == "CDC") _parentnum = LF_CDC; if (_parentnum != 0) { const TMultilevel_code_info& info = ca_multilevel_code_info(_parentnum); for (int i = 0; i < info.levels(); i++) { _prompt.add(info.prompt(i)); _picture.add(info.picture(i)); TFieldref fr = info.fieldref(i); fr.set_name("CODCMSFAS"); _key1_fields.add(fr); } } } TString16 keyvar, desvar; get_cfg_vars(keyvar, desvar); int from = 1, to = 1; for (int level = 1; ; level++) { const TString& prompt = cfg.get(desvar, NULL, level); if (prompt.blank()) break; _prompt.add(prompt); const TString& picture = cfg.get(keyvar, NULL, level); _picture.add(picture); const int keylen = picture.len(); to = from+keylen-1; add_fieldref(1, from, to); from = to+1; } add_fieldref(2, 0, 0); } const TRectype rec(logicnum); rec.get_relapp(_editor); } const TMultilevel_code_info& ca_multilevel_code_info(int logicnum) { static TArray* cache = NULL; if (cache == NULL) cache = new TArray; TMultilevel_code_info* info = (TMultilevel_code_info*)cache->objptr(logicnum); if (info == NULL) { info = new TMultilevel_code_info(logicnum); cache->add(info, logicnum); } return *info; } const TMultilevel_code_info* ca_multilevel_code_info_by_index(int level) { static int _logicnum[3] = { -1, -1, -1 }; int logic = 0; if (level >= 0 && level < 3) { // Riempie lista dei livelli, ad esempio: // LF_COMMESSE, LF_FASI, LF_CDC oppure LF_COMMESSE, LF_CDC, ecc... if (_logicnum[0] < 0) { TConfig& cfg = ca_config(); const TString& lev1 = cfg.get("Level", NULL, 1); if (lev1.full()) { const TMultilevel_code_info& fasi = ca_multilevel_code_info(LF_FASI); int k = 0; _logicnum[k] = lev1 == "CDC" ? LF_CDC : LF_COMMESSE; if (fasi.parent() == _logicnum[k]) _logicnum[++k] = LF_FASI; const TString& lev2 = cfg.get("Level", NULL, 2); if (lev2.full()) { _logicnum[++k] = _logicnum[0] == LF_COMMESSE ? LF_CDC : LF_COMMESSE; if (fasi.parent() == _logicnum[k]) _logicnum[++k] = LF_FASI; } } else memset(_logicnum, 0, sizeof(_logicnum)); } logic = _logicnum[level]; } return logic > 0 ? &ca_multilevel_code_info(logic) : NULL; } bool ca_test_multilevel_field(TEdit_field& fld, int level) { const int logic = fld.browse()->cursor()->curr().num(); const TMultilevel_code_info& info = ca_multilevel_code_info(logic); const TString& pic = info.picture(level); const TString& val = fld.get(); bool ok = val.len() <= pic.len(); for (int i = 0; val[i] && ok; i++) { const char v = val[i]; const char p = pic[i]; switch (p) { case 'A': ok = (v >= '0' && v <= '9') || (v >= 'A' && v <= 'Z'); break; case '0': ok = (v >= '0' && v <= '9'); break; case '9': ok = (v == ' ') || (v >= '0' && v <= '9'); break; default : break; } } if (!ok) { TString msg; msg << TR("Il codice non rispetta il formato impostato nella configurazione") << '\n' << val << " <> " << pic; return fld.error_box(msg); } return ok; } /////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////// const char* ca_dollar2fieldname(int logic, const char* dollar) { CHECKS(dollar && *dollar == '$', "False dollar", dollar); //cerca il nome del campo della variabile dollarata nel file logic in questione if (xvt_str_compare_ignoring_case(dollar, "$(CDC)") == 0) { switch (logic) { case LF_DOC: return DOC_CODCOSTO; case LF_RIGHEDOC: return RDOC_CODCOSTO; case LF_RMOVANA: return RMOVANA_CODCCOSTO; case LF_SALDANA: return SALDANA_COSTO; default : return CDC_CODCOSTO; } } if (xvt_str_compare_ignoring_case(dollar, "$(CMS)") == 0) { switch (logic) { case LF_DOC: return DOC_CODCMS; case LF_RIGHEDOC: return RDOC_CODCMS; case LF_FASI: return FASI_CODCMSFAS; case LF_RMOVANA: return RMOVANA_CODCMS; case LF_SALDANA: return SALDANA_COMMESSA; default : return COMMESSE_CODCOSTO; } } if (xvt_str_compare_ignoring_case(dollar, "$(FAS)") == 0) { switch (logic) { case LF_DOC: return DOC_FASCMS; case LF_RIGHEDOC: return RDOC_FASCMS; case LF_RMOVANA: return RMOVANA_CODFASE; case LF_SALDANA: return SALDANA_FASE; default : return FASI_CODFASE; } } return NULL; } void ca_append_and(TString& query, const TString& clause) { if (clause.full()) { if (query.full()) { query.insert("("); query << ")&&(" << clause << ")"; } else query = clause; } } static const TString& ca_get_user_permissions(const TString& utente, const int logic) { TString select; const TString gruppo(cache().get(LF_USER, utente, "GROUPNAME")); if (gruppo.full()) select = ca_get_user_permissions(gruppo, logic); TFilename fileconf = firm2dir(-1); // Directory dati fileconf.add("config"); // + Directory config fileconf.add("ca0900conf.ini"); TConfig ini_permessi(fileconf); if (ini_permessi.set_paragraph(utente)) { const char* fieldname = NULL; switch (logic) { case LF_COMMESSE: fieldname = "Cms"; break; case LF_CDC: fieldname = "Cdc"; break; case LF_FASI: fieldname = "Fas"; break; default: break; } if (fieldname != NULL) { const TString& expr = ini_permessi.get(fieldname); ca_append_and(select, expr); //che programma sono che chiamo questa funzione? const TFilename prog_name = main_app().argv(0); TString16 key = prog_name.name_only(); key << " " << main_app().argv(1); TToken_string row(80, SAFE_PIPE_CHR); for (int r = 0;; r++) { row = ini_permessi.get("Prog", NULL, r); if (row.blank()) break; if (key == row.get(0)) { int column = 0; switch (logic) { case LF_COMMESSE: column = 1; break; case LF_CDC: column = 2; break; case LF_FASI: column = 3; break; default: break; } const TString& prog_expr = row.get(column); ca_append_and(select, prog_expr); } //if (key == row.get(0))... } //for (int r = 0;; r++)... } //if (fieldname... } //if (ini_permessi.set... return select.full() ? (get_tmp_string() = select) : EMPTY_STRING; } static const TString& ca_get_user_permissions_or_empty(const TString& utente, const int logic) { const TString& perm = ca_get_user_permissions(utente, logic); if (perm.full()) { TString& subclause = get_tmp_string(); subclause << "(" << perm << ")||($("; switch (logic) { case LF_CDC: subclause << "CDC"; break; case LF_COMMESSE: subclause << "CMS"; break; case LF_FASI: subclause << "FAS"; break; default: break; } subclause << ")==\"\")"; return subclause; } return EMPTY_STRING; } const TString& ca_create_user_select_clause(int logic) { static TArray clauses; TString* clause = (TString*)clauses.objptr(logic); if (clause == NULL) { clause = new TString; switch (logic) { case LF_CDC: case LF_COMMESSE: case LF_FASI: *clause = ca_get_user_permissions(user(), logic); break; case LF_DOC: case LF_RIGHEDOC: case LF_RMOVANA: case LF_SALDANA: ca_append_and(*clause, ca_get_user_permissions_or_empty(user(), LF_CDC)); ca_append_and(*clause, ca_get_user_permissions_or_empty(user(), LF_COMMESSE)); ca_append_and(*clause, ca_get_user_permissions_or_empty(user(), LF_FASI)); break; default: break; } for (int dollar = clause->find("$("); dollar >= 0; dollar = clause->find("$(", dollar)) { const int closed = clause->find(')', dollar + 4); const TString& before = clause->left(dollar); const TString& field = clause->sub(dollar, closed + 1); const TString& after = clause->mid(closed + 1); clause->cut(0) << before << ca_dollar2fieldname(logic, field) << after; } clauses.add(clause, logic); } return *clause; } bool ca_filter_record(const TRectype& rec) { bool good = true; const TString& filter = ca_create_user_select_clause(rec.num()); if (filter.full()) { TExpression expr(filter, _strexpr); for (int v = expr.numvar() - 1; v >= 0; v--) { const char* field = expr.varname(v); expr.setvar(v, rec.get(field)); } good = expr.as_bool(); } return good; } bool ca_filter_function(const TRelation* rel) { return rel != NULL && ca_filter_record(rel->curr()); } static void ca_append_select_clause(ostream& out, int level, int logic, bool upper_limit) { TString str; if (logic == LF_PCON) { switch (level) { case 0: str = "CONTO==\"\""; break; case 1: str = "SOTTOCONTO==\"\""; break; default: break; } } else { const TMultilevel_code_info& mci = ca_multilevel_code_info(logic); const int last_level = mci.levels()-1; if (last_level > 0) { CHECKD(level>=0 && level <= last_level, "Bad analitic level ", level); const TFieldref& key = mci.fieldref(level); if (level > 0 && !upper_limit) { str << "STR("; str << "(NUM(LEN(" << key.name() << "))>" << key.from() << ')'; // SE LEN(CODCONTO)>=4 } if (level < last_level) { if (str.empty()) str = "STR("; else str << "&&"; str << "(NUM(LEN(" << key.name() << "))<=" << key.to() << ')'; // SE LEN(CODCONTO)<=7 } if (str.not_empty()) str << ')'; } } const TString & condition = ca_create_user_select_clause(logic); if (condition.full()) { if (str.full()) { str.insert("("); str << ")&&"; } str << '(' << condition << ')'; } if (str.full()) out << " SE " << str << '\n'; } static void ca_append_run_clause(ostream& out, int logicnum) { const TString& app = ca_multilevel_code_info(logicnum).editor(); if (app.not_empty()) out << "AD RU " << app << '\n'; } static void init_tmp_filename(TFilename& name) { name.tempdir(); name.add("tmp.msk"); } void ca_create_browse1(TEdit_field& kfld, int level, int logic, short key_id, short des_id) { const TMultilevel_code_info& main_info = ca_multilevel_code_info(logic); bool add_select = false; if (logic == LF_FASI) { const int par = main_info.parent(); if (par > 0) { const TMultilevel_code_info& parinfo = ca_multilevel_code_info(par); if (level < parinfo.levels()) logic = par; else add_select = true; } } const TMultilevel_code_info& mci = ca_multilevel_code_info(logic); TFilename tmp; init_tmp_filename(tmp); ofstream out(tmp); out << "US " << logic << '\n'; ca_append_select_clause(out, level, logic, add_select); ca_append_run_clause(out, logic); bool req = false; if ((logic == LF_COMMESSE || logic == LF_CDC) && kfld.mask().get_sheet()) // Sono in una maschera di riga? { TConfig& ini = ca_config(); if (logic == LF_COMMESSE) req = ini.get_bool("CmsRequired"); else req = ini.get_bool("CdcRequired"); } for (int i = 0; i <= level; i++) { const TString& picture = mci.picture(i); const TString& prompt = mci.prompt(i); const TFieldref& field = mci.fieldref(i); const int length = field.to() - field.from(); out << "IN " << field << ' ' << (key_id+i); if (add_select && field.name() == FASI_CODCMSFAS) out << " SE"; out << '\n'; out << "DI \"" << prompt; if (length > prompt.len()) out << '@' << length; out << "\" " << field << '\n'; out << "OU " << (key_id+i) << ' ' << field << '\n'; } const TFieldref& field = mci.fieldref(0, 2); out << "DI \"" << TR("Descrizione") << "@50\" " << field << '\n'; if (logic == LF_COMMESSE) { out << "DI \"" << TR("Proroga") << "\" PROROGA" << '\n'; out << "DI \"" << TR("Data") << "@10" << "\" DATAPROR" << '\n'; out << "DI \"" << TR("Chiusa") << "\" CHIUSA" << '\n'; } out << "OU " << (des_id+level) << ' ' << field << '\n'; out << "CH " << (req ? "RE" : "NO") << '\n'; out << "FI " << main_info.fieldref(level) << '\n'; out << "EN" << '\n'; out.close(); TScanner scan(tmp); while (scan.pop() != "EN") kfld.parse_item(scan); xvt_fsys_remove_file(tmp); } void ca_create_browse2(TEdit_field& kfld, int level, int logic, short key_id) { const TMultilevel_code_info& main_info = ca_multilevel_code_info(logic); bool add_select = false; if (logic == LF_FASI) { const int par = main_info.parent(); if (par > 0) { const TMultilevel_code_info& parinfo = ca_multilevel_code_info(par); if (level < parinfo.levels()) logic = par; else add_select = true; } } const TMultilevel_code_info& mci = ca_multilevel_code_info(logic); const TFieldref& field = mci.fieldref(0, 2); TString str2; str2 << field; TFilename tmp; init_tmp_filename(tmp); ofstream out(tmp); out << "US " << logic << " KE 2" << '\n'; ca_append_select_clause(out, level, logic, add_select); ca_append_run_clause(out, logic); out << "IN " << str2 << ' ' << kfld.dlg() << '\n'; out << "DI \"" << TR("Descrizione") << "@50\" " << str2 << '\n'; out << "OU " << kfld.dlg() << ' ' << str2 << '\n'; for (int i = 0; i <= level; i++) { const TString& picture = mci.picture(i); const TString& prompt = mci.prompt(i); const TFieldref& field = mci.fieldref(i); const int length = field.to() - field.from(); out << "DI \"" << prompt; if (length > prompt.len()) { out << '@' << length; if (mci.is_numeric_picture(i)) out << 'R'; } out << "\" " << field << '\n'; out << "OU " << (key_id+i) << ' ' << field << '\n'; } if (logic == LF_COMMESSE) { out << "DI \"" << HR("Proroga") << "\" PROROGA" << '\n'; out << "DI \"" << HR("Data") << "@10" << "\" DATAPROR" << '\n'; out << "DI \"" << HR("Chiusa") << "\" CHIUSA" << '\n'; } out << "CH NO" << '\n'; if (level == main_info.levels()-1) out << "FI " << main_info.fieldref(0, 2) << '\n'; out << "EN" << '\n'; out.close(); TScanner scan(tmp); while (scan.pop() != "EN") kfld.parse_item(scan); xvt_fsys_remove_file(tmp); } int ca_create_fields(TMask& msk, int page, int logicnum, int x, int y, short key_id, short des_id, unsigned int mode, const char* fieldname, int from ) { TWait_cursor hourglass; const TMultilevel_code_info& mci = ca_multilevel_code_info(logicnum); int maxkeylen = 0, maxdeslen = 0; for (int level = 0; level < mci.levels(); level++) { const TString& prompt = mci.prompt(level); const TString& picture = mci.picture(level); const int keylen = picture.len(); const int deslen = prompt.len(); if (keylen > maxkeylen) maxkeylen = keylen; if (deslen > maxdeslen) maxdeslen = deslen; } maxdeslen++; const int tab0 = x; const int tab1 = tab0 + maxdeslen + maxkeylen + 4; if (key_id > 0 && (mode == 0 || (mode & 0x1) != 0)) { for (int i = 0; i < mci.levels(); i++) { const short kid = key_id+i; const TString& picture = mci.picture(i); TString80 prompt = mci.prompt(i); prompt.left_just(maxdeslen); const char* flags = picture[0] == '0' || picture[0] == '9' ? "BUZ" : "BU"; TEdit_field* kfld = NULL; if (mci.is_numeric_picture(i)) // Numeric kfld = &msk.add_number(kid, page, prompt, tab0, y+i, picture.len(), flags); else kfld = &msk.add_string(kid, page, prompt, tab0, y+i, picture.len(), flags); ca_create_browse1(*kfld, i, logicnum, key_id, des_id); if ((mode & 0x1) != 0 && fieldname == NULL) kfld->set_key(1); // Ho specificato un nome di campo speciale if (fieldname && *fieldname) { const TFieldref& fr = *kfld->field(); TString80 str; str.format("%s[%d,%d]", fieldname, fr.from()+from+1, fr.to()+from); kfld->set_field(str); } } } if (des_id > 0 && (mode == 0 || (mode & 0x2) != 0)) { for (int i = 0; i < mci.levels(); i++) { const short did = des_id+i; TEdit_field& dfld = msk.add_string(did, page, "", tab1, y+i, 50, "B", 72+tab0-tab1); ca_create_browse2(dfld, i, logicnum, key_id); if ((mode & 0x2) != 0 && fieldname == NULL) dfld.set_key(2); else dfld.set_field(""); } } return mci.levels(); } int ca_create_fields_compact(TMask& msk, int page, int logicnum, int x, int y, short key_id, short des_id, unsigned int mode, const char* fieldname, int from ) { TWait_cursor hourglass; const TMultilevel_code_info& mci = ca_multilevel_code_info(logicnum); int par_items = 0; if (logicnum == LF_FASI) { if (mci.parent() == LF_CDC) par_items = ca_multilevel_code_info(LF_CDC).levels(); else if (mci.parent() == LF_COMMESSE) par_items = ca_multilevel_code_info(LF_COMMESSE).levels(); } const int items = par_items > 0 ? par_items : mci.levels(); int maxkeylen = 0, maxdeslen = 0; for (int level = 0; level < mci.levels(); level++) { const TString& picture = mci.picture(level); const int keylen = picture.len(); int deslen = 0; if ((level == 0 && items == 1) || (level == par_items && mci.levels() - par_items == 1)) deslen = mci.prompt(level).len(); else deslen = logicnum != LF_FASI || mci.parent() > 0 ? 8 : 4 ; if (deslen > maxdeslen) maxdeslen = deslen; if (keylen > maxkeylen) maxkeylen = keylen; } maxdeslen++; const int tab0 = x; int offset = 0; int desc_offset = 0; int row_offset = 0; if (key_id > 0 && (mode == 0 || (mode & 0x1) != 0)) { for (int i = 0; i < mci.levels(); i++) { const short kid = key_id+i; const TString& picture = mci.picture(i); TString80 prompt; if (i == 0) { int ln = logicnum; if (ln == LF_FASI && mci.parent() > 0) ln = mci.parent(); switch (ln) { case LF_PCONANA : prompt = items == 1 ? mci.prompt(i) : "Conto"; break; case LF_COMMESSE : prompt = items == 1 ? mci.prompt(i) : "Commessa"; break; case LF_CDC : prompt = items == 1 ? mci.prompt(i) : "C. Costo"; break; case LF_FASI : prompt = items == 1 ? mci.prompt(i) : "Fase"; break; default: prompt = "Conto"; break; } } else if (i == par_items) prompt = mci.levels() - par_items == 1 ? mci.prompt(i) : "Fase" ; if (prompt.full()) prompt.left_just(maxdeslen); const char* flags = picture[0] == '0' || picture[0] == '9' ? "BUZG" : "BUG"; TEdit_field* kfld = NULL; if (mci.is_numeric_picture(i)) // Numeric kfld = &msk.add_number(kid, page, prompt, tab0 + offset, y + row_offset, picture.len(), flags); else kfld = &msk.add_string(kid, page, prompt, tab0 + offset, y + row_offset, picture.len(), flags); ca_create_browse1(*kfld, i, logicnum, key_id, des_id); if ((mode & 0x1) != 0 && fieldname == NULL) kfld->set_key(1); // Ho specificato un nome di campo speciale if (fieldname && *fieldname) { const TFieldref& fr = *kfld->field(); TString80 str; str.format("%s[%d,%d]", fieldname, fr.from()+from+1, fr.to()+from); kfld->set_field(str); } TString war; war << mci.prompt(i) << ' ' << TR("assente"); kfld->set_warning(war); offset += prompt.len() + picture.len() + 4; if (desc_offset < offset) desc_offset = offset; if (i == par_items - 1) { row_offset++; offset = 0; } // Copio il checktype nel campo fantasma per colorare correttamente la colonna if (msk.get_sheet() != NULL && kfld->required()) msk.efield(kid-100).check_type(kfld->check_type()); } } row_offset = 0; const int tab1 = tab0 + desc_offset + 4; if (des_id > 0 && (mode == 0 || (mode & 0x2) != 0)) { for (int i = 0; i < mci.levels(); i++) { const short did = des_id+i; TEdit_field& dfld = (i < mci.levels() - 1) && (i != par_items -1) ? msk.add_string(did, page, "", 50, 50, 50, "B") : msk.add_string(did, page, "", tab1, y + row_offset, 50, "B", 72+tab0-tab1); ca_create_browse2(dfld, i, logicnum, key_id); if ((mode & 0x2) != 0 && fieldname == NULL) dfld.set_key(2); else dfld.set_field(""); if (i == par_items - 1) row_offset++; } } return mci.levels(); } int ca_create_fields_ext(TMask& m, int page, int x, int y, short first_id, short& first_cdc, short& first_cms, short& first_fase, short& first_conto, const char* cdc_fld, const char* cms_fld, const char* fase_fld, const char* conto_fld) { int numero_campi = 0; const TMultilevel_code_info& fasinfo = ca_multilevel_code_info(LF_FASI); TConfig& ini = ca_config(); short dlg = first_id; for (int i = 0; i < 2; i++) { const TString& level = ini.get("Level", NULL, i+1); // Legge il livello 1 o 2 if (level == "CDC" && cdc_fld) // Crea centro di costo { if (fasinfo.parent() == LF_CDC) { int h = ca_multilevel_code_info(LF_CDC).levels(); const int sh = ca_create_fields_compact(m, 0, LF_FASI, x, y, dlg, dlg + 50); y += 2; first_cdc = dlg; first_fase = first_cdc + h; dlg += sh; numero_campi += sh; } else { const int sh = ca_create_fields_compact(m, 0, LF_CDC, x, y++, dlg, dlg + 50); first_cdc = dlg; dlg += sh; numero_campi += sh; } } else if (level == "CMS" && cms_fld) // Crea commessa { if (fasinfo.parent() == LF_COMMESSE) { int h = ca_multilevel_code_info(LF_COMMESSE).levels(); const int sh = ca_create_fields_compact(m, 0, LF_FASI, x, y, dlg, dlg + 50); y += 2; first_cms = dlg; first_fase = first_cms + h; dlg += sh; numero_campi += sh; } else { const int sh = ca_create_fields_compact(m, 0, LF_COMMESSE, x, y++, dlg, dlg + 50); first_cms = dlg; dlg += sh; numero_campi += sh; } } } if (fasinfo.levels() > 0 && fasinfo.parent() <= 0 && fase_fld) //Crea fase { const int sh = ca_create_fields_compact(m, 0, LF_FASI, x, y++, dlg, dlg + 50); first_fase = dlg; dlg += sh; numero_campi += sh; } if (conto_fld) //Crea conto { const bool use_pdcc = ini.get_bool("UsePdcc"); const int logicnum = use_pdcc ? LF_PCON : LF_PCONANA; const int nfields = ca_create_fields_compact(m, 0, logicnum, x, y++, dlg, dlg + 50); first_conto = nfields; dlg += nfields; numero_campi += nfields; } if (m.get_sheet() != NULL) //Se è una maschera di riga, sistemo le colonne delle sheet { TSheet_field& s = *m.get_sheet(); for (short id = first_id + 116; id >= first_id + 100; id--) { const int pos = m.id2pos(id); if (pos >= 0) { TMask_field& f = m.fld(pos); const int size = f.size(); TString80 prompt = f.prompt(); prompt.trim(); if (prompt.blank()) { TToken_string ts(((TEditable_field &)f).get_warning(), ' '); prompt = ts.get(0); } s.set_column_header(id, prompt); s.set_column_justify(id, f.is_kind_of(CLASS_REAL_FIELD)); s.set_column_width(id, (max(3+size, prompt.len()+1)) * CHARX); s.enable_column(id); m.efield(id-100).check_type(f.check_type()); // Copio il checktype nel campo fantasma per colorare correttamente la colonna } else s.delete_column(id); } } return numero_campi; } void ca_get_fields(TMask& m, TString& cdc, TString& cms, TString& fase, TString& conto, const short first_cdc, const short first_cms, const short first_fase, const short first_conto, const TString80 cdc_fld, const TString80 cms_fld, const TString80 fase_fld, const TString80 conto_fld) { TString val; cdc.cut(0); cms.cut(0); fase.cut(0); conto.cut(0); if (!cdc_fld.empty()) for (short id = first_cdc; id < first_cdc + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != cdc_fld) break; val = fld.get(); val.rpad(fld.size()); cdc << val; } cdc.trim(); if (!cms_fld.empty()) for (short id = first_cms; id < first_cms + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != cms_fld) break; val = fld.get(); val.rpad(fld.size()); cms << val; } cms.trim(); if (!fase_fld.empty()) for (short id = first_fase; id < first_fase + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != fase_fld) break; val = fld.get(); val.rpad(fld.size()); fase << val; } fase.trim(); if (!conto_fld.empty()) for (short id = first_conto; id <= first_conto + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != conto_fld) break; val = fld.get(); val.rpad(fld.size()); conto << val; } conto.trim(); } void ca_get_row_fields(TSheet_field& sheet, const int selected_row, TString& cdc, TString& cms, TString& fase, TString& conto, const short first_cdc, const short first_cms, const short first_fase, const short first_conto, const TString80 cdc_fld, const TString80 cms_fld, const TString80 fase_fld, const TString80 conto_fld) { TString val; cdc.cut(0); cms.cut(0); fase.cut(0); conto.cut(0); TToken_string& row = sheet.row(selected_row); TMask& m = sheet.sheet_mask(); if (!cdc_fld.empty()) for (short id = first_cdc; id < first_cdc + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != cdc_fld) break; val = row.get(sheet.cid2index(id)); val.rpad(fld.size()); cdc << val; } cdc.trim(); if (!cms_fld.empty()) for (short id = first_cms; id < first_cms + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != cms_fld) break; val = row.get(sheet.cid2index(id)); val.rpad(fld.size()); cms << val; } cms.trim(); if (!fase_fld.empty()) for (short id = first_fase; id < first_fase + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != fase_fld) break; val = row.get(sheet.cid2index(id)); val.rpad(fld.size()); fase << val; } fase.trim(); if (!conto_fld.empty()) for (short id = first_conto; id <= first_conto + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != conto_fld) break; val = row.get(sheet.cid2index(id)); val.rpad(fld.size()); conto << val; } conto.trim(); } void ca_put_row_fields(TSheet_field& sheet, const int selected_row, TString& cdc, TString& cms, TString& fase, TString& conto, const short first_cdc, const short first_cms, const short first_fase, const short first_conto, const TString80 cdc_fld, const TString80 cms_fld, const TString80 fase_fld, const TString80 conto_fld) { TMask& m = sheet.sheet_mask(); TToken_string& row = sheet.row(selected_row); int pos = 0; if (!cdc_fld.empty()) for (short id = first_cdc; id < first_cdc + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != cdc_fld) break; const int len = fld.size(); row.add(cdc.mid(pos, len), sheet.cid2index(id)); pos += len; } pos = 0; if (!cms_fld.empty()) for (short id = first_cms; id < first_cms + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != cms_fld) break; const int len = fld.size(); row.add(cdc.mid(pos, len), sheet.cid2index(id)); pos += len; } pos = 0; if (!fase_fld.empty()) for (short id = first_fase; id < first_fase + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != fase_fld) break; const int len = fld.size(); row.add(cdc.mid(pos, len), sheet.cid2index(id)); pos += len; } pos = 0; if (!conto_fld.empty()) for (short id = first_conto; id < first_conto + 4; id++) { TMask_field& fld = m.field(id); if(fld.prompt() != conto_fld) break; const int len = fld.size(); row.add(cdc.mid(pos, len), sheet.cid2index(id)); } } /////////////////////////////////////////////////////////// // TAnal_tree_pos /////////////////////////////////////////////////////////// struct TAnal_tree_pos : public TObject { TRecnotype _pos; TToken_string _key; bool _is_father; void as_string(TString& id) const; TRecnotype pos() const { return _pos; } bool is_father() const { return _is_father; } int level() const { return _key.items(); } void reset(); void set(const char * key, TRecnotype pos, bool is_father); TAnal_tree_pos() : _pos(0), _is_father(false) {} TAnal_tree_pos(const TAnal_tree_pos& p) : _pos(p._pos), _is_father(p._is_father), _key(p._key) {} TAnal_tree_pos(const char* id); }; void TAnal_tree_pos::as_string(TString& id) const { id.format("%ld|%c|%s", _pos, _is_father ? 'F' : 'S', (const char*)_key); } void TAnal_tree_pos::set(const char * key, TRecnotype pos, bool is_father) { _key = key; _pos = _key.full() ? pos : 0; _is_father = is_father; } void TAnal_tree_pos::reset() { _key.cut(0); _pos = 0; _is_father = false; } TAnal_tree_pos::TAnal_tree_pos(const char* id) { TToken_string ts(id); _pos = ts.get_long(0); _is_father = ts.get_char(1) == 'F'; int pipe = ts.find(ts.separator()); pipe = ts.find(ts.separator(), pipe+1); _key = ts.mid(pipe+1); } class TAnal_tree : public TBidirectional_tree { TCursor* _curs; TCursor* _father_curs; int _fathfasi; bool _is_father; TAnal_tree_pos _curr; protected: virtual void node2id(const TObject* node, TString& id) const; virtual bool could_have_son() const; virtual bool has_son() const; virtual bool has_father() const; virtual bool goto_firstson(); virtual bool goto_rbrother(); virtual bool goto_node(const TString &id); virtual TObject* curr_node() const; virtual bool goto_father(); virtual bool goto_lbrother(); virtual bool get_description(TString& desc) const; virtual TImage* image(bool selected) const; protected: void update_curr(); int level_of(const TToken_string& key) const; int level_of_file() const; const TToken_string& curr_of_file() const; int curr_level() const; int max_level() const; const TToken_string& father_of(const TToken_string& key) const; const TToken_string& father_of_file() const; bool repos() const; public: virtual bool goto_root(); TAnal_tree(int logicnum); virtual ~TAnal_tree(); }; /////////////////////////////////////////////////////////// // TAnal_msk /////////////////////////////////////////////////////////// #define F_TREE 99 short TSimple_anal_msk::get_field_id(int n, int k) const { short id = 0; if (n >= 0 && n < fieldrefs(1)) { if (k == 1) id = F_KEY1+n; else id = F_DES1+n; } return id; } bool TSimple_anal_msk::test_key_field(short id) { TEdit_field& fld = efield(id); const int level = id - F_KEY1; return ca_test_multilevel_field(fld, level); } bool TSimple_anal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_TREE: if (e == fe_modify) { if (edit_mode() && !dirty()) set_mode(MODE_QUERY); if (query_mode()) { const TTree_field& fld = (const TTree_field&)o; const TTree& tree = *fld.tree(); TToken_string curr; tree.curr_id(curr); TEdit_field* last = NULL; for (int i = 0; ; i++) { const short id = get_field_id(i); if (id <= 0) break; const char* tok = curr.get(i+2); TEdit_field& e = efield(id); e.set(tok); e.show(); //attenzione!!! modifica necessaria per poter ripulire in automatico i campi inutili al cambio struttura.. //..del piano dei conti (selezionandone una diversa sull'albero della maschera) e per non avere un warning.. //..dalla last->check() che andrebbe a fare la check su un campo vuoto if (tok && *tok) last = &e; } if (last != NULL) { if (last->check()) stop_run(K_AUTO_ENTER); else warning_box(FR("L'utente %s non ha accesso a questo record"), (const char*)user()); } } else beep(0); } break; case F_KEY1: case F_KEY2: case F_KEY3: case F_KEY4: if ((jolly == 0) &&(e == fe_modify || e == fe_close)) return test_key_field(o.dlg()); break; default: break; } return true; } int TSimple_anal_msk::compute_offset() const { int delta = 0; RCT rct; xvt_vobj_get_client_rect(TASK_WIN, &rct); if (rct.right > 720) delta = (rct.right - 720) / 2 / CHARX; if (delta > 0) { int ln = get_logicnum(); if (ln == LF_FASI) { const TString& ff = ca_config().get("FathFasi"); if (ff.full()) ln = (ff == "CMS") ? LF_COMMESSE : LF_CDC; } TLocalisamfile lif(ln); const TRecnotype recs = lif.items(); if (recs > 2048) // Niente alberi enormi ... per ora delta = 0; } return delta; } void TSimple_anal_msk::read(const char* name) { const int delta = compute_offset(); if (delta > 0) { TFilename outname; init_tmp_filename(outname); TFilename inpname = name; inpname.ext("msk"); inpname.custom_path(); ofstream out(outname); TString line; int status = 0; TScanner inp(inpname); while (!inp.eof()) { line = inp.line(); switch (status) { case 0: if (line.starts_with("PA")) status = 1; // Ho trovato la prima pagina break; case 1: if (line.starts_with("PR")) // Ho trovato un prompt sulla prima pagina { TToken_string l(line, ' '); int x = l.get_int(1); if (x >= 0) { x += delta; l.add(x, 1); line = l; } } else if (line.starts_with("PA")) // Ho finito la prima pagina { status = 2; } break; default: break; } out << line << endl; } out.close(); read_mask(outname, 0, 0); xvt_fsys_remove_file(outname); set_source_file(inpname); } else read_mask(name, 0, 0); create_key_fields(); create_tree_field(); } short TSimple_anal_msk::create_tree_field() { short id = 0; const int delta = compute_offset(); if (delta > 0) { id = F_TREE; add_tree(id, 0, 0, 1, (delta-1)*2, -1); TAnal_tree* t = new TAnal_tree(get_logicnum()); tfield(id).set_tree(t); t->goto_root(); t->expand(); } set_handlers(); return id; } void TSimple_anal_msk::update_tree_field() { const int pos = id2pos(F_TREE); if (pos >= 0) { TTree_field& t = tfield(F_TREE); t.win().force_update(); } } int TSimple_anal_msk::fieldrefs(int k) const { int n = 1; if (k == 1) { const TMultilevel_code_info& mci = ca_multilevel_code_info(get_logicnum()); n = mci.levels(); } return n; } const TFieldref& TSimple_anal_msk::fieldref(int n, int k) const { const TMultilevel_code_info& mci = ca_multilevel_code_info(get_logicnum()); return mci.fieldref(n, k); } const TToken_string& TSimple_anal_msk::get_key_value(const TRectype& rec, int c) const { TToken_string& val = get_tmp_string(); const int tot = fieldrefs(c); for (int i = 0; i < tot; i++) { const TFieldref& field = fieldref(i, c); val.add(field.read(rec)); } return val; } const TToken_string& TSimple_anal_msk::get_key_value(int c) const { TToken_string& val = get_tmp_string(); for (TEditable_field* f = get_key_field(c, true); f != NULL; f = get_key_field(c, false)) { val.add(f->get()); } return val; } int TSimple_anal_msk::create_key_fields() { const int logic = get_logicnum(); const short kid = get_field_id(0, 1); const short did = get_field_id(0, 2); const int x = compute_offset()+3; const int y = 1; const int n = ca_create_fields(*this, 0, logic, x, y, kid, did, 0x1); const int m = ca_create_fields(*this, 0, logic, x, y, kid, did, 0x2); first_focus(kid); return n; } /////////////////////////////////////////////////////////// // TAnal_tree /////////////////////////////////////////////////////////// const TToken_string& TAnal_tree::curr_of_file() const { const TRectype& rec = _is_father ? _father_curs->curr() : _curs->curr(); const TMultilevel_code_info& mci = ca_multilevel_code_info(rec.num()); TToken_string& k = get_tmp_string(); for (int i = 0; i < mci.levels(); i++) { const TFieldref& fld = mci.fieldref(i); k.add(fld.read(rec)); } for (int j = k.len()-1; j >= 0; j--) { if (k[j] == ' ' || k[j] == k.separator()) k.cut(j); else break; } return k; } int TAnal_tree::level_of(const TToken_string& k) const { return k.items(); } int TAnal_tree::level_of_file() const { const TToken_string& str = curr_of_file(); return level_of(str); } int TAnal_tree::curr_level() const { return level_of(_curr._key); } int TAnal_tree::max_level() const { const int logic = _curs->relation()->lfile().num(); const TMultilevel_code_info& mci = ca_multilevel_code_info(logic); return mci.levels(); } const TToken_string& TAnal_tree::father_of(const TToken_string& key) const { const int pos = key.rfind(key.separator()); if (pos <= 0) return EMPTY_STRING; TToken_string& k = get_tmp_string(); k = key.left(pos); return k; } const TToken_string& TAnal_tree::father_of_file() const { const TToken_string& k = curr_of_file(); return father_of(k); } void TAnal_tree::update_curr() { _curr.set(curr_of_file(), _is_father ? _father_curs->pos() : _curs->pos(), _is_father); } bool TAnal_tree::repos() const { bool ok = false; if (_curr.level() > 0) { if (_is_father) { if (_father_curs->pos() != _curr.pos()) ((TCursor&)*_father_curs) = _curr.pos(); } else { if (_curs->pos() != _curr.pos()) ((TCursor&) *_curs) = _curr.pos(); } ok = true; } return ok; } void TAnal_tree::node2id(const TObject* node, TString& id) const { const TAnal_tree_pos* pos = (const TAnal_tree_pos*)node; pos->as_string(id); } bool TAnal_tree::goto_root() { bool ok = false; //gestione speciale per le fasi con babbo if (_father_curs != NULL) { if (_father_curs->items() > 0) { *_father_curs = 0L; _is_father = true; update_curr(); ok = true; } else _curr.reset(); } else //caso standard (cms, cdc, fasi senza babbo) { if (_curs->items() > 0) { *_curs = 0L; update_curr(); ok = true; } else _curr.reset(); } return ok; } bool TAnal_tree::has_father() const { return _curr.level() > 1; } bool TAnal_tree::could_have_son() const { return _curr.level() < max_level(); } bool TAnal_tree::has_son() const { if (!could_have_son()) return false; if (_is_father && _father_curs) { const int father_logic = _father_curs->file().num(); // LF_COMMESSE o LF_CDC const TMultilevel_code_info& fci = ca_multilevel_code_info(father_logic); const int son_lev = _curr.level() + 1; if (son_lev > fci.levels()) { TLocalisamfile& fasi = _curs->file(); fasi.zero(); fasi.put(FASI_CODCMSFAS, _curr._key); return fasi.read(_isgteq) == NOERR && fasi.get(FASI_CODCMSFAS) == _curr._key; } } return TBidirectional_tree::has_son(); } bool TAnal_tree::goto_firstson() { bool ok = _curr.level() < max_level() && repos(); if (ok) { if (_is_father && _father_curs) { const TMultilevel_code_info& fci = ca_multilevel_code_info(_father_curs->file().num()); const int son_lev = _curr.level() + 1; if (son_lev > fci.levels()) { TRectype& rec = _curs->curr(); rec.zero(); rec.put(FASI_CODCMSFAS, _curr._key); ok = _curs->read() >= 0 && rec.get(FASI_CODCMSFAS) == _curr._key; if (ok) { _is_father = false; // Forzo cursore fasi prima della update_curr update_curr(); } else repos(); return ok; } } TCursor& c = _is_father ? *_father_curs : *_curs; ok = c.pos() < c.items(); if (ok) { ++c; ok = father_of_file() == _curr._key; if (ok) update_curr(); } } return ok; } bool TAnal_tree::goto_rbrother() { bool ok = false; if (repos()) { TCursor& c = _is_father ? *_father_curs : *_curs; const TToken_string curr_father = father_of(_curr._key); ++c; while (ok = c.pos() < c.items()) { const int lev = level_of_file(); if (lev <= _curr.level()) { const TToken_string& next_father = father_of_file(); ok = next_father == curr_father; break; } ++c; } if (ok) update_curr(); } return ok; } bool TAnal_tree::goto_node(const TString &id) { const TAnal_tree_pos ap(id); const TRecnotype rec = ap.pos(); _is_father = ap.is_father(); TCursor& c = _is_father ? *_father_curs : *_curs; if (rec >= 0L && rec < c.items()) { c = rec; update_curr(); return true; } return false; } bool TAnal_tree::goto_father() { const int lev = _curr.level(); bool ok = lev > 1; if (ok) { const int logicnum = _curs->relation()->lfile().num(); if (logicnum == LF_FASI && !_is_father) { const TMultilevel_code_info& mci = ca_multilevel_code_info(logicnum); if (mci.parent() != 0) { const TMultilevel_code_info& fci = ca_multilevel_code_info(mci.parent()); _is_father = fci.levels() <= lev-1; } } TCursor& c = *(_is_father ? _father_curs : _curs); TRectype& rec = c.curr(); rec.zero(); const TMultilevel_code_info& mci = ca_multilevel_code_info(rec.num()); for (int i = 0; i < lev-1; i++) { const char* val = _curr._key.get(i); const TFieldref& fld = mci.fieldref(i); fld.write(val, rec); } ok = c.read() == NOERR; if (ok) { update_curr(); CHECKD(_curr.level() < lev, "Invalid analitic node level: father=son=", lev); } } return ok; } bool TAnal_tree::goto_lbrother() { bool ok = false; if (repos()) { const TString curr_father = father_of(_curr._key); TCursor& c = _is_father ? *_father_curs : *_curs; --c; while (ok = c.pos() > 0L) { const int lev = level_of_file(); if (lev <= _curr.level()) { const TString& next_father = father_of_file(); ok = next_father == curr_father; break; } --c; } if (ok) update_curr(); } return ok; } TObject* TAnal_tree::curr_node() const { return (TObject*)&_curr; } bool TAnal_tree::get_description(TString& desc) const { const bool ok = repos(); if (ok) { const int lev = _curr.level(); if (lev > 0) { TCursor& c = _is_father ? *_father_curs : *_curs; const TRectype& rec = c.curr(); const TMultilevel_code_info& mci = ca_multilevel_code_info(rec.num()); const TFieldref& fld1 = mci.fieldref(lev-1, 1); const TFieldref& fld2 = mci.fieldref(0, 2); desc = fld1.read(rec); desc << ' ' << fld2.read(rec); } } return ok; } TImage* TAnal_tree::image(bool selected) const { short bmp_id = BMP_FILE; if (has_son()) bmp_id = selected ? BMP_DIRDN : BMP_DIR; return get_res_image(bmp_id); } TAnal_tree::TAnal_tree(int logicnum) : _curs(NULL), _father_curs(NULL), _is_father(false) { TString select; _curs = new TCursor(new TRelation(logicnum), ca_create_user_select_clause(logicnum)); _fathfasi = 0; if (logicnum == LF_FASI) { const TString& ff = ca_config().get("FathFasi"); if (ff.full()) { _fathfasi = (ff == "CMS") ? LF_COMMESSE : LF_CDC; _father_curs = new TCursor(new TRelation(_fathfasi), ca_create_user_select_clause(_fathfasi)); } } } TAnal_tree::~TAnal_tree() { delete _curs; } /////////////////////////////////////////////////////////// // TAnal_app /////////////////////////////////////////////////////////// void TAnal_app::init_key_fields(TSimple_anal_msk & m) const { int maxlev = 0; for (maxlev = 0; maxlev < 4; maxlev++) { const short id = m.get_field_id(maxlev, 1); if (id <= 0 || m.id2pos(id) < 0) break; m.disable(id); const short did = m.get_field_id(maxlev, 2); m.disable(did); } bool found = false; for (int i = maxlev-1; i >= 0; i--) { const short id = m.get_field_id(i, 1); TEdit_field& e = m.efield(id); const short did = m.get_field_id(i, 2); TEdit_field& d = m.efield(did); if (e.empty()) { e.hide(); d.hide(); } else { e.show(); e.check(STARTING_CHECK); //trattamento speciale per il FIELD delle descrizioni; senza questo if(, si avrebbe la descrizione dell'ultimo.. //..campo in tutte le descrizioni precedenti! 15/05/2009 TString80 key2; if (!found) { key2 << m.fieldref(0, 2); found = true; } d.set_field(key2); d.show(); d.enable(); m.first_focus(d.dlg()); d.enable_check(false); } } } TRelation* TAnal_app::create_relation() const { return new TRelation(_msk->get_logicnum()); } bool TAnal_app::user_create() { _msk = create_mask(); _rel = create_relation(); return true; } void TAnal_app::init_query_mode(TMask& mask) { TSimple_anal_msk& m = (TSimple_anal_msk&)mask; for (int i = 0; ; i++) { const short id = m.get_field_id(i, 1); if (id <= 0 || m.id2pos(id) < 0) break; TEdit_field& e = m.efield(id); e.show(); e.enable(); const short did = m.get_field_id(i, 2); TEdit_field& d = m.efield(did); d.show(); d.enable(); d.enable_check(); d.set_field(""); } m.first_focus(m.get_field_id(0, 1)); } void TAnal_app::init_modify_mode(TMask& mask) { init_key_fields((TSimple_anal_msk &)mask); } void TAnal_app::init_insert_mode(TMask& mask) { init_key_fields((TSimple_anal_msk &)mask); } int TAnal_app::write(const TMask& m) { _msk->update_tree_field(); return TRelation_application::write(m); } int TAnal_app::rewrite(const TMask& m) { _msk->update_tree_field(); return TRelation_application::rewrite(m); } bool TAnal_app::user_destroy() { if (_msk != NULL) delete _msk; if (_rel != NULL) delete _rel; return true; } /////////////////////////////////////////////////////////// // TAnal_mov /////////////////////////////////////////////////////////// const char * TAnal_mov::row_anal_code(int logicnum, int row) const { const TMultilevel_code_info & c = ca_multilevel_code_info(logicnum); const int levels = c.levels(); TString & code = get_tmp_string(); for (int i = 0; i < levels; i++) { TFieldref fr = c.fieldref(i); if (fr.name() == "CODCOSTO") fr.set_name(RMOVANA_CODCCOSTO); if (logicnum == LF_FASI && fr.name() == "CODCMSFAS") continue; const TString & s = fr.read(body()[row]); if (s.full()) { if (code.full()) code << " "; code << s; } } return code; } const char * TAnal_mov::row_code(int row) const { const TMultilevel_code_info & fasi = ca_multilevel_code_info(LF_FASI); TConfig& cfg = ca_config(); bool fase_added = false; const TString16 codfase(row_anal_code(LF_FASI, row)); bool fase_to_add = codfase.full(); TString code; for (int i = 0; i < 2; i++) { const TString& level = cfg.get("Level", NULL, i+1); // Legge il livello 1 o 2 if (level == "CDC") // Crea centro di costo { const TString & codcdc = row_anal_code(LF_CDC, row); if (codcdc.full()) { if (code.full()) code << " "; code << codcdc; } if (fase_to_add && fasi.parent() == LF_CDC) { if (code.full()) code << " "; code << codfase; fase_to_add = false; } } else if (level == "CMS") // Crea centro di costo { const TString & codcms = row_anal_code(LF_COMMESSE, row); if (codcms.full()) { if (code.full()) code << " "; code << codcms; } if (fase_to_add && fasi.parent() == LF_COMMESSE) { if (code.full()) code << " "; code << codfase; fase_to_add = false; } } } if (fase_to_add) { if (code.full()) code << " "; code << codfase; } return get_tmp_string() = code; } void TAnal_mov::saldo_set_reset(const TRectype& row, bool reset) { const int dec = TCurrency::get_firm_dec(); const TImporto imp_row(row.get_char(RMOVANA_SEZIONE), row.get_real(RMOVANA_IMPORTO)); const int esc_iniziale = get_int(MOVANA_ANNOES); int esc_finale = esc_iniziale; //che movimento e'? TToken_string annies; annies.add(esc_iniziale); const char tipomov = get_char(MOVANA_TIPOMOV); // i movimenti analitici possono avere una data di scadenza come la mozzarella const TDate datacomp = get_date(MOVANA_DATACOMP); TDate datafcomp = get_date(MOVANA_DATAFCOMP); //caso cazzuto della scadenza con la fine della commessa (come nella stampa bilancio commessa) if (get_bool(MOVANA_AUTOFCOMP)) { const TString& codcms = row.get(RMOVANA_CODCMS); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); //data del cazzo che serve per non rovinare datacomp, che è la data sulla riga, non quella iniziale di cms TDate datainicms; ca_durata_commessa(rec_commesse, datainicms, datafcomp); } if (datafcomp.ok() && datafcomp > datacomp) { TEsercizi_contabili esc; esc_finale = esc.date2esc(datafcomp); if (esc_finale < esc_iniziale) //se l'esercizio di scadenza non esiste ancora perche' troppo futuro... esc_finale = esc_iniziale + datafcomp.year() - datacomp.year(); //...se lo genera if (esc_finale > esc_iniziale) { for (int a = esc_iniziale + 1; a <= esc_finale; a++) annies.add(a); } } TToken_string key; key.add(tipomov); key.add(esc_iniziale); key.add(row.get(RMOVANA_CODCCOSTO)); key.add(row.get(RMOVANA_CODCMS)); key.add(row.get(RMOVANA_CODFASE)); key.add(row.get(RMOVANA_CODCONTO)); if (annies.items() > 1) //saldi spammati su piu' anni { TToken_string giorni_annies; //lista dei giorni di saldo per annoes TEsercizi_contabili esc; TDate inizio_esc_iniziale, fine_esc_iniziale; esc.code2range(esc_iniziale, inizio_esc_iniziale, fine_esc_iniziale); giorni_annies.add(fine_esc_iniziale - datacomp + 1); //primo esercizio TDate inizio_esc_finale, fine_esc_finale; for (int a = 1; a < annies.items() - 1; a++) { const int curr_esc = annies.get_int(a); esc.code2range(curr_esc, inizio_esc_finale, fine_esc_finale); giorni_annies.add(fine_esc_finale - inizio_esc_finale + 1); //esercizi intermedi } esc.code2range(esc_finale, inizio_esc_finale, fine_esc_finale); giorni_annies.add(datafcomp - inizio_esc_finale + 1); //ultimo esercizio //Adesso che ha l'elenco dei giorni impegnati per esercizio, scatta il casino del distributore.. TGeneric_distrib texaco(imp_row.valore(), dec); FOR_EACH_TOKEN(giorni_annies, gg) texaco.add(real(gg)); FOR_EACH_TOKEN(annies, es) { TImporto curr_imp(imp_row.sezione(), texaco.get()); key.add(es, 1); //sistema l'anno di esercizio nella chiave TImporto* imp = (TImporto*)_saldi.objptr(key); if (imp == NULL) { imp = new TImporto; _saldi.add(key, imp); } if (reset) *imp -= curr_imp; else *imp += curr_imp; if (ca_ori_present(row)) { TImporto* impind = (TImporto*)_saldind.objptr(key); if (impind == NULL) { impind = new TImporto; _saldind.add(key, impind); } if (reset) *impind -= curr_imp; else *impind += curr_imp; } } } else //saldo in un solo anno (caso standard) { TImporto* imp = (TImporto*)_saldi.objptr(key); if (imp == NULL) { imp = new TImporto; _saldi.add(key, imp); } if (reset) *imp -= imp_row; else *imp += imp_row; if (ca_ori_present(row)) { TImporto* impind = (TImporto*)_saldind.objptr(key); if (impind == NULL) { impind = new TImporto; _saldind.add(key, impind); } if (reset) *impind -= imp_row; else *impind += imp_row; } imp->valore().round(dec); } } void TAnal_mov::load_saldi(bool reset) { if (reset) { _saldi.destroy(); _saldind.destroy(); } const TRecord_array& a = body(LF_RMOVANA); for (int i = a.last_row(); i > 0; i--) { const TRectype& row = a[i]; saldo_set_reset(row, reset); //aggiunge o toglie la riga corrente ai saldi in memoria } } void TAnal_mov::update_saldi(bool kill) { if (!kill) load_saldi(false); save_saldi(); if (kill) _saldi.destroy(); else load_saldi(true); } bool TAnal_mov::save_saldi(const int annoes) { TLocalisamfile saldi(LF_SALDANA); FOR_EACH_ASSOC_OBJECT(_saldi, h, k, o) { const TImporto& imp = *(const TImporto*)o; if (!imp.is_zero()) { TToken_string key = k; const char tipo = key.get_char(0); const int anno = key.get_int(1); //Controlla se deve veramente salvre i saldi che ha calcolato bool save_for_true = true; //se annoes = 0 -> registrazione movimento analitico -> save_for_true = true -> salva! //se invece trova un anno e' in fase ricostruzione saldi! Deve fare delle considerazioni.. if (annoes != 0) { if (annoes > 0) //se annoes e' positivo -> sono saldi normali -> salva! save_for_true = anno == annoes; else //se annoes e' negativo -> sono preventivi futuri -> salva solo se abs(anno)>annoes (senno' non sei nel futuro!) save_for_true = anno > -annoes; } if (!save_for_true) //se non deve salvare davvero il saldo -> continua continue; saldi.put(SALDANA_ANNO, anno); saldi.put(SALDANA_COSTO, key.get(2)); saldi.put(SALDANA_COMMESSA, key.get(3)); saldi.put(SALDANA_FASE, key.get(4)); saldi.put(SALDANA_CONTO, key.get(5)); int err = saldi.read(_isequal, _lock); if (err != NOERR) { //Richiesta specifica del nostro Fuhrer! I saldi appartenenti ad esercizi futuri NON ancora aperti vanno.. //..comunque registrati!!! // TEsercizi_contabili esc; // if (esc.exist(anno)) { saldi.zero(); saldi.put(SALDANA_ANNO, anno); saldi.put(SALDANA_COSTO, key.get(2)); saldi.put(SALDANA_COMMESSA, key.get(3)); saldi.put(SALDANA_FASE, key.get(4)); saldi.put(SALDANA_CONTO, key.get(5)); err = saldi.write(); if (err != NOERR) cantwrite_box(saldi.name()); } // else // continue; // NON devo dare errori fuorvianti causa saldi nel futuro che ci saranno ma non vanno scritti } if (err == NOERR) { const char* fld_sez = NULL; const char* fld_val = NULL; switch (tipo) { case 'P': fld_sez = SALDANA_SEZIONEP; fld_val = SALDANA_SALDOP; break; case 'V': fld_sez = SALDANA_SEZIONEV; fld_val = SALDANA_SALDOV; break; default : fld_sez = SALDANA_SEZIONE; fld_val = SALDANA_SALDO; break; } TImporto saldo(saldi.get_char(fld_sez), saldi.get_real(fld_val)); saldo += imp; saldo.normalize(); saldi.put(fld_sez, saldo.sezione()); saldi.put(fld_val, saldo.valore()); const TImporto * ind = (const TImporto*) _saldind.objptr(key); if (ind != NULL) { const TImporto& impind = *(const TImporto*)ind; switch (tipo) { case 'P': fld_sez = SALDANA_SEZIONEIP; fld_val = SALDANA_SALDOIP; break; case 'V': fld_sez = SALDANA_SEZIONEIV; fld_val = SALDANA_SALDOIV; break; default : fld_sez = SALDANA_SEZIONEI; fld_val = SALDANA_SALDOI; break; } TImporto saldoind(saldi.get_char(fld_sez), saldi.get_real(fld_val)); saldoind += impind; saldoind.normalize(); saldi.put(fld_sez, saldoind.sezione()); saldi.put(fld_val, saldoind.valore()); } err = saldi.rewrite(); } if (err != NOERR) return error_box(FR("Impossibile aggiornare i saldi: errore %d"), err); } } return true; } int TAnal_mov::readat(TBaseisamfile& f, TRecnotype nrec, word lockop) { const int err = TMultiple_rectype::readat(f, nrec, lockop); load_saldi(true); return err; } int TAnal_mov::read(TBaseisamfile& f, word op, word lockop) { const int err = TMultiple_rectype::read(f, op, lockop); load_saldi(true); return err; } // Riporta su tutte le righe la data di competenza e l'esercizio dellla testata //Aggiorna datafcomp e dataexpire sulla testata (dataexpire può dipendere dalle righe se si utilizza il calcolo.. //..automatico di dataexpire in base alle commesse sulle righe! Adolf ne sa una più del Teufel...) void TAnal_mov::update_datacomp() const { body().renum_key(RMOVANA_ANNOES, get(MOVANA_ANNOES)); body().renum_key(RMOVANA_DATACOMP, get(MOVANA_DATACOMP)); //aggiorna datafcomp (se non specificata deve coincidere con datacomp) TDate datafcomp = get(MOVANA_DATAFCOMP); if (!datafcomp.ok()) { datafcomp = get(MOVANA_DATACOMP); ((TAnal_mov*)this)->put(MOVANA_DATAFCOMP, datafcomp); } } int TAnal_mov::write(TBaseisamfile& f) const { update_datacomp(); const int err = TMultiple_rectype::write(f); if (err == NOERR) ((TAnal_mov*)this)->update_saldi(false); return err; } int TAnal_mov::rewrite(TBaseisamfile& f) const { update_datacomp(); const int err = TMultiple_rectype::rewrite(f); if (err == NOERR) ((TAnal_mov*)this)->update_saldi(false); return err; } int TAnal_mov::remove(TBaseisamfile& f) const { const int err = TMultiple_rectype::remove(f); if (err == NOERR) ((TAnal_mov*)this)->update_saldi(true); return err; } int TAnal_mov::read(long numreg, word lock) { put(MOVANA_NUMREG, numreg); const int err = TMultiple_rectype::read(_isequal, lock); load_saldi(true); return err; } int TAnal_mov::read_cgnum(long numreg, word lock) { TLocalisamfile f(num()); f.setkey(3); f.put(MOVANA_NUMREGCG, numreg); int err = f.read(_isequal); f.setkey(1); if (err == NOERR) { put(MOVANA_NUMREG, f.get(MOVANA_NUMREG)); if ((err = TMultiple_rectype::read(_isequal, lock)) == NOERR) load_saldi(true); } return err; } void TAnal_mov::zero(char c) { TMultiple_rectype::zero(c); kill_saldi(); } void TAnal_mov::update_totdoc() { TImporto totdoc; for (int i = rows(); i > 0; i--) { const TRectype& riga = body().row(i); TImporto imp_riga(riga.get_char(RMOVANA_SEZIONE), riga.get_real(RMOVANA_IMPORTO)); totdoc += imp_riga; } totdoc.normalize(); put(MOVANA_TOTDOC, totdoc.valore()); put(MOVANA_SEZIONE, totdoc.sezione()); } TAnal_mov::TAnal_mov(long numreg) : TMultiple_rectype(LF_MOVANA) { add_file(LF_RMOVANA, RMOVANA_NUMRIG); if (numreg > 0) read(numreg); } TAnal_mov::TAnal_mov(const TRectype& rec) : TMultiple_rectype(LF_MOVANA) { add_file(LF_RMOVANA, RMOVANA_NUMRIG); long numreg = 0; switch(rec.num()) { case LF_MOV: case LF_RMOV: case LF_RMOVIVA: { TLocalisamfile movana(LF_MOVANA); movana.setkey(3); movana.put(MOVANA_NUMREGCG, rec.get(MOV_NUMREG)); if (movana.read() == NOERR) numreg = movana.get_long(MOVANA_NUMREG); } break; default: numreg = rec.get_long(MOVANA_NUMREG); break; } if (numreg > 0) read(numreg); } /////////////////////////////////////////////////////////// // TAnal_ripartizioni_batch ////////////////////////////////////////////////////////// int TAnal_ripartizioni_batch::indbil() const { return head().get_int(RIP_INDBIL); } char TAnal_ripartizioni_batch::tiporip() const { return head().get_char(RIP_TIPO); } int TAnal_ripartizioni_batch::modorip() const { return head().get_int(RIP_TIPORIP); } int TAnal_ripartizioni_batch::read (const char tiporip, const char* codice) { TLocalisamfile rip(LF_RIP); _rip.put(RIP_TIPO, tiporip); //solo tipi batch! _rip.put(RIP_CODICE, codice); int err = _rip.read(rip); //leggi il record dal file if (err == NOERR) { TRectype rrip(LF_RRIP); rrip.put(RRIP_TIPO, tiporip); rrip.put(RRIP_CODICE, codice); TRecord_array::read(rrip); } return err; } int TAnal_ripartizioni_batch::read_rip_4(TLocalisamfile& rip, const char* codcosto, const char* commessa, const char* fase, const int annoes, const int indbil, const int classe_mov) const { rip.put(RIP_TIPO, "B"); //solo tipi batch, unici per chiave cdc/cms/fase rip.put(RIP_CODCOSTO, codcosto); rip.put(RIP_CODCMS, commessa); rip.put(RIP_CODFASE, fase); rip.put(RIP_ANNOES, annoes); rip.put(RIP_INDBIL, indbil); rip.put(RIP_CLASSEMOV, classe_mov); return rip.read(); } int TAnal_ripartizioni_batch::read (const char* codcosto, const char* commessa, const char* fase, const int annoes, const int indbil, const int classe_mov) { CHECKD(classe_mov > 0, "Classe movimento non valida ", classe_mov); TLocalisamfile rip(LF_RIP); rip.setkey(4); int err = read_rip_4(rip, codcosto, commessa, fase, annoes, indbil, classe_mov); if (err != NOERR) err = read_rip_4(rip, codcosto, commessa, fase, annoes, indbil, 0); //la put va rifatta perche' potrebbe essersi spostato al record successivo!!! //se fallisce il primo tentativo prova con lo stesso anno e indbil=0 if (err != NOERR && indbil != 0) { err = read_rip_4(rip, codcosto, commessa, fase, annoes, 0, classe_mov); if (err != NOERR) err = read_rip_4(rip, codcosto, commessa, fase, annoes, 0, 0); } //se fallisce ancora riprova con anno=0 e lo stesso indbil if (err != NOERR && annoes != 0) { err = read_rip_4(rip, codcosto, commessa, fase, 0, indbil, classe_mov); if (err != NOERR) err = read_rip_4(rip, codcosto, commessa, fase, 0, indbil, 0); //estremo tentativo con annoes e indbil = 0 if (err != NOERR && indbil != 0) { err = read_rip_4(rip, codcosto, commessa, fase, 0, 0, classe_mov); if (err != NOERR) err = read_rip_4(rip, codcosto, commessa, fase, 0, 0, 0); } } if (err == NOERR) err = read('B', rip.get(RIP_CODICE)); //per chiave 4 solo tipo B (batch) return err; } int TAnal_ripartizioni_batch::read_rip_3(TLocalisamfile& rip, const char tiporip, const int gr, const int co, const long sot, const int annoes, const int indbil, const int classe_mov) const { rip.put(RIP_TIPO, tiporip); //tipo 'P' oppure tipo 'I', che sono quelli che vanno per conto rip.put(RIP_GRUPPO, gr); rip.put(RIP_CONTO, co); rip.put(RIP_SOTTOCONTO, sot); rip.put(RIP_ANNOES, annoes); rip.put(RIP_INDBIL, indbil); rip.put(RIP_CLASSEMOV, classe_mov); return rip.read(); } int TAnal_ripartizioni_batch::read (const char tiporip, const int gr, const int co, const long sot, const int annoes, const int indbil, const int classe_mov) { CHECKD(classe_mov > 0, "Classe movimento non valida ", classe_mov); TLocalisamfile rip(LF_RIP); rip.setkey(3); int err = read_rip_3(rip, tiporip, gr, co, sot, annoes, indbil, classe_mov); if (err != NOERR) err = read_rip_3(rip, tiporip, gr, co, sot, annoes, indbil, 0); //la put va rifatta perche' potrebbe essersi spostato al record successivo!!! //se fallisce il primo tentativo prova con lo stesso anno e indbil=0 if (err != NOERR && indbil != 0) { err = read_rip_3(rip, tiporip, gr, co, sot, annoes, 0, classe_mov); if (err != NOERR) err = read_rip_3(rip, tiporip, gr, co, sot, annoes, 0, 0); } //se fallisce ancora riprova con anno=0 e lo stesso indbil if (err != NOERR && annoes != 0) { err = read_rip_3(rip, tiporip, gr, co, sot, 0, indbil, classe_mov); if (err != NOERR) err = read_rip_3(rip, tiporip, gr, co, sot, 0, indbil, 0); //estremo tentativo con annoes e indbil = 0 if (err != NOERR && indbil != 0) { err = read_rip_3(rip, tiporip, gr, co, sot, 0, 0, classe_mov); if (err != NOERR) err = read_rip_3(rip, tiporip, gr, co, sot, 0, 0, 0); } } _multirip = false; if (err == NOERR) { err = read(tiporip, rip.get(RIP_CODICE)); //per chiave 3 sia tiporip=P che tiporip=I const TString curr_key = rip.curr().build_key(3); //cerca eventuali altre ripartizioni sorelle (con codice diverso ma stessi parametri) if (rip.next() == NOERR) { const TString next_key = rip.curr().build_key(3); _multirip = curr_key == next_key; } } return err; } int TAnal_ripartizioni_batch::find_sister_rips(TString_array& lista_rips) const { lista_rips.destroy(); TToken_string key; //ci sono più ripartizioni possibili... if (has_multirip()) { //relazione e cursore su chiave 3 (TIPO+GRUPPO+CONTO+SOTTOCONTO+ANNOES+INDBIL+CLASSEMOV) sul file LF_RIP alla.. //..ricerca di eventuali ripartizioni sorelle TRelation rel_rip(LF_RIP); TCursor cur_rip(&rel_rip, "", 3, &head(), &head()); for (cur_rip = 0; cur_rip.pos() < cur_rip.items(); ++cur_rip) { key.cut(0); key.add(cur_rip.curr().get(RIP_CODICE)); key.add(cur_rip.curr().get(RIP_DESCRIZ)); lista_rips.add(key); } } else //c'è solo una ripartizione { key.add(head().get_long(RIP_CODICE)); key.add(head().get(RIP_DESCRIZ)); lista_rips.add(key); } //restituisce il numero di ripartizioni trovate (nel TString_array c'è l'elenco) return lista_rips.items(); } TAnal_ripartizioni_batch::TAnal_ripartizioni_batch() : TRecord_array (LF_RRIP, RRIP_NRIGA), _rip(LF_RIP), _multirip(false) { } /////////////////////////////////////////////////////////// // TCache_ripartizioni /////////////////////////////////////////////////////////// TObject* TCache_ripartizioni::key2obj(const char* key) { TToken_string parametro(key); const int nkey = parametro.get_int(0); TAnal_ripartizioni_batch* rip = new TAnal_ripartizioni_batch; switch (nkey) { case 3: { const int gruppo = parametro.get_int(1); const int conto = parametro.get_int(2); const long sottoconto = parametro.get_long(3); const int anno = parametro.get_int(4); const int indbil = parametro.get_int(5); const int classe_mov = parametro.get_int(6); //solo i movimenti a pareggio hanno chiave 3 rip->read('P', gruppo, conto, sottoconto, anno, indbil, classe_mov); } break; case 5: { const int gruppo = parametro.get_int(1); const int conto = parametro.get_int(2); const long sottoconto = parametro.get_long(3); const int anno = parametro.get_int(4); const int indbil = parametro.get_int(5); const int classe_mov = parametro.get_int(6); //solo i movimenti interattivi e di conversione hanno chiave 5 rip->read('I', gruppo, conto, sottoconto, anno, indbil, 1); } break; default: //chiave 4: normali ripartizioni batch { const TString80 codcosto = parametro.get(1); const TString80 commessa = parametro.get(2); const TString16 fase = parametro.get(3); const int anno = parametro.get_int(4); const int indbil = parametro.get_int(5); const int classe_mov = parametro.get_int(6); rip->read(codcosto, commessa, fase, anno, indbil, classe_mov); } break; } //ripartizioni costo/ricavo (quelle bonazziche sui saldi) //stabilisce i coefficienti di ripartizione al volo in base al peso economico della commessa/cdc/fase/conto che trova.. //..sulla riga di ripartizione; ovviamente tali valori sono soggetti a cambiamento tutte le volte che ci sono righe.. //..analitiche che interessano tali paramtri (cms/cdc ecc.); sono ripartizioni dinamiche per il controllo dei costi/ricavi.. //..ad una data if (rip->modorip() == 1) //modorip=1 -> costo/ricavo { bool some_value = false; const int items = rip->rows(); //deve sapere se usare i saldi in Dare o Avere in base al fatto che l'utente voglia un analisi proporzionata.. //..sui Costi o sui Ricavi; lo legge dalla configurazione della CA; se non lo trova settato lo mette in automatico.. //..a Costi const char sezione_di_riferimento = ca_config().get_char("SezRif"); for (int i = 1; i <= items; i++) { TRectype & rec = (*rip)[i]; const TAnal_bill bill(rec); //calcola il saldo usando come parametri (cms/cdc/fsc/conto) quelli che trova sulla riga di ripartizione const TSaldanal& s = ca_saldo(bill, _dal, _al, _saldanal_consuntivo); //in base a C/R stabilisce quali saldi considerare e in quale sezione normalizzare real val; if (sezione_di_riferimento == 'R') //in Ricavi normalizza in Avere val = s._avere.valore(); else //in Costi normalizza in Dare val = s._dare.valore(); //saldi nulli non contano if (val < ZERO) val = ZERO; //usa il valore del saldo non nullo per stabilire il "peso" della riga di ripartizione some_value |= !val.is_zero(); rec.put(RRIP_RIPARTO, val); } if (!some_value) { for (int i = 1; i <= items; i++) { TRectype& rec = (*rip)[i]; rec.put(RRIP_RIPARTO, 1); } } } return (TObject*)rip; } void TCache_ripartizioni::set_esercizio(const int codes) { if (codes != _codes) { TEsercizi_contabili e; const TEsercizio& esc = e.esercizio(codes); _codes = codes; _dal = esc.inizio(); _al = esc.fine(); destroy(); } } const TAnal_ripartizioni_batch& TCache_ripartizioni::righe(const char* costo, const char* commessa, const char* fase, const int annoes, const int indbil, const char tipomov) { //classi di movimento: se preventivi 2, se normali 1 int classe_movimento; if (tipomov == 'P' || tipomov == 'V') classe_movimento = 2; else classe_movimento = 1; TToken_string parametro; parametro << "4|" << costo << '|' << commessa << '|' << fase << '|' << annoes << '|' << indbil << '|' << classe_movimento; //per chiave 4 return *(const TAnal_ripartizioni_batch*)objptr(parametro); } const TAnal_ripartizioni_batch& TCache_ripartizioni::righe(const TBill& bill, const int annoes, const char tipomov) { //classi di movimento: se preventivi 2, se normali 1 int classe_movimento; if (tipomov == 'P' || tipomov == 'V') classe_movimento = 2; else classe_movimento = 1; TToken_string parametro; parametro << "3|" << bill.gruppo() << '|' << bill.conto() << '|' << bill.sottoconto() << '|' << annoes << '|' << bill.indicatore_bilancio() << '|' << classe_movimento; //per chiave 3 return *(const TAnal_ripartizioni_batch*)objptr(parametro); } const TAnal_ripartizioni_batch& TCache_ripartizioni::righe(const TAnal_bill& bill, const int annoes, const int indbil, const char tipomov) { TConfig& config = ca_config(); const bool use_pdcc = config.get_bool("UsePdcc"); //usa il piano dei conti contabile if (use_pdcc) { const TString& contone = bill.conto(); const int gr = atoi(contone.mid(0,3)); const int co = atoi(contone.mid(3,3)); const long so = atol(contone.mid(6,6)); const TBill zio(gr, co, so); const TAnal_ripartizioni_batch& rb = righe(zio, annoes, tipomov); //ha trovato una ripartizione? if (rb.rows() > 0) return rb; } //se non riesce a trovare una ripartizione per conto (chiave 3, tipo 'P') prova con la chiave 4 (cdc/cms/fase, tipo 'B') return righe(bill.costo(), bill.commessa(), bill.fase(), annoes, indbil, tipomov); } const TAnal_ripartizioni_batch& TCache_ripartizioni::righe_interattive(const TBill& bill, const int annoes, const char tipomov) { //classi di movimento: se preventivi 2, se normali 1 int classe_movimento; if (tipomov == 'P' || tipomov == 'V') classe_movimento = 2; else classe_movimento = 1; //sempre questo per cacnv TToken_string parametro; parametro << "5|" << bill.gruppo() << '|' << bill.conto() << '|' << bill.sottoconto() << '|' << annoes << '|' << bill.indicatore_bilancio() << '|' << classe_movimento; //per chiave 5 return *(const TAnal_ripartizioni_batch*)objptr(parametro); } TCache_ripartizioni::TCache_ripartizioni() { _codes = 0; } /////////////////////////////////////////////////////////// // Metodi per la ricompattazione delle righe ripartite /////////////////////////////////////////////////////////// bool ca_can_merge_rows(const TRectype& compact_rec, const TRectype& rec) { return compact_rec.get(RMOVANA_CODCCORI) == rec.get(RMOVANA_CODCCORI) && compact_rec.get(RMOVANA_CODCMSORI) == rec.get(RMOVANA_CODCMSORI) && compact_rec.get(RMOVANA_CODFASEORI) == rec.get(RMOVANA_CODFASEORI) && compact_rec.get(RMOVANA_CODCONTORI) == rec.get(RMOVANA_CODCONTORI); } bool ca_can_pack_rows(const TRectype& compact_rec, const TRectype& rec) { return compact_rec.get(RMOVANA_CODCCOSTO) == rec.get(RMOVANA_CODCCOSTO) && compact_rec.get(RMOVANA_CODCMS) == rec.get(RMOVANA_CODCMS) && compact_rec.get(RMOVANA_CODFASE) == rec.get(RMOVANA_CODFASE) && compact_rec.get(RMOVANA_CODCONTO) == rec.get(RMOVANA_CODCONTO)&& compact_rec.get(RMOVANA_CODCCORI) == rec.get(RMOVANA_CODCCORI) && compact_rec.get(RMOVANA_CODCMSORI) == rec.get(RMOVANA_CODCMSORI) && compact_rec.get(RMOVANA_CODFASEORI) == rec.get(RMOVANA_CODFASEORI) && compact_rec.get(RMOVANA_CODCONTORI) == rec.get(RMOVANA_CODCONTORI); } bool ca_ori_present(const TRectype& rec) { return (rec.get(RMOVANA_CODCCORI).not_empty() || rec.get(RMOVANA_CODCMSORI).not_empty() || rec.get(RMOVANA_CODFASEORI).not_empty() || rec.get(RMOVANA_CODCONTORI).not_empty()); } bool ca_ori_present(const TRecordset & rec) { return (rec.get(RMOVANA_CODCCORI).as_string().not_empty() || rec.get(RMOVANA_CODCMSORI).as_string().not_empty() || rec.get(RMOVANA_CODFASEORI).as_string().not_empty() || rec.get(RMOVANA_CODCONTORI).as_string().not_empty()); } void ca_taglia_campo(TRectype& src, const char* campo_src, TRectype& dst, const char* campo_dst) { ca_copia_campo(src, campo_src, dst, campo_dst); src.zero(campo_src); } void ca_copia_campo(const TRectype& src, const char* campo_src, TRectype& dst, const char* campo_dst) { const TString& valore = src.get(campo_src); if (valore.full()) dst.put(campo_dst, valore); } bool ca_implode_rows(const TRecord_array& input_rows, TRecord_array& compact_rows) { bool implosion_done = false; const int last_row = input_rows.last_row(); for (int r = input_rows.first_row(); r > 0 && r <= last_row; r = input_rows.succ_row(r)) { const TRectype& rec = input_rows.row(r); //record originale //se esiste almeno un campo origine compilato puo' implodere, senno' lascia perdere if (ca_ori_present(rec)) { //controlla se e' un pareggio e non una ripartizione if (rec.get(RMOVANA_CODCONTORI).blank()) continue; int i = 0; for (i = compact_rows.rows(); i > 0; i--) //giro sulle righe gia' compattate per scoprire se { //il nostro record esiste gia' o e' da aggiungere const TRectype& nuovo_rec = compact_rows.row(i); // if (ca_can_merge_rows(nuovo_rec, rec)) //se esiste gia'... break; } if (i > 0) //...aggiunge solo importo e sezione... { const TImporto imp_rec(rec.get_char(RMOVANA_SEZIONE), rec.get_real(RMOVANA_IMPORTO)); TRectype& compact_rec = compact_rows.row(i, false); //record originale TImporto imp_orig(compact_rec.get_char(RMOVANA_SEZIONE), compact_rec.get_real(RMOVANA_IMPORTO)); imp_orig += imp_rec; imp_orig.normalize(); compact_rec.put(RMOVANA_SEZIONE, imp_orig.sezione()); compact_rec.put(RMOVANA_IMPORTO, imp_orig.valore()); } else //...senno' aggiunge direttamente tutta la riga { TRectype* newrec = new TRectype(rec); //record destinazione newrec->put(RMOVANA_NUMRIG, compact_rows.rows() + 1); compact_rows.add_row(newrec); } implosion_done = true; //ha imploso almeno 1 riga!!! } else { TRectype* newrec = new TRectype(rec); newrec->put(RMOVANA_NUMRIG, compact_rows.rows() + 1); compact_rows.add_row(newrec); } } //ripristina i campi originali sul record di destinazione for (int k = 1; k <= compact_rows.rows(); k++) { TRectype& compact_rec = compact_rows.row(k, false); if (ca_ori_present(compact_rec)) { ca_taglia_campo(compact_rec, RMOVANA_CODCCORI, compact_rec, RMOVANA_CODCCOSTO); ca_taglia_campo(compact_rec, RMOVANA_CODCMSORI, compact_rec, RMOVANA_CODCMS); ca_taglia_campo(compact_rec, RMOVANA_CODFASEORI, compact_rec, RMOVANA_CODFASE); ca_taglia_campo(compact_rec, RMOVANA_CODCONTORI, compact_rec, RMOVANA_CODCONTO); } } return implosion_done; } /////////////////////////////////////////////////////////////////////////////////////// //metodi per ricavare informazioni sulla configurazione (usati per ora nel rendiconto) /////////////////////////////////////////////////////////////////////////////////////// //metodo per ricavare la stringa dei codici dai campi dello sheet bool ca_extract_sheet_field(const TSheet_field& sheet, const int row, const int logicnum, TString& codice) { TMask& mask_sheet = sheet.sheet_mask(); //maschera di riga codice.cut(0); FOR_EACH_MASK_FIELD(mask_sheet, i, f) //giro sui campi della maschera di riga { const TFieldref* fr = f->field(); //campo corrente della maschera if (fr != NULL && f->is_edit()) //deve essere un campo di tipo edit { TEdit_field& e = *(TEdit_field*)f; //visto che è di tipo edit può creare l'edit_field per farne la browse if (e.browse() != NULL) { const TCursor& cur = *e.browse()->cursor(); const int ln = cur.file().num(); //Allah! dal campo ricava il cursore sul file di numero ln if (ln == logicnum && cur.key() == 1 && !e.empty()) { const TString& parte_codice = e.get(); codice << parte_codice; } else { if (codice.full()) break; } } } } return codice.full(); } /////////////////////////////////////////////////////////////////////////////////////// //calcola la durata di una commessa e le sue date di inizio e fine /////////////////////////////////////////////////////////////////////////////////////// long ca_durata_commessa(const TRectype& rec_commesse, TDate& dataini, TDate& datafine) { //date iniziale e finale commessa dataini = rec_commesse.get_date(COMMESSE_DATAINIZIO); datafine = rec_commesse.get_date(COMMESSE_DATAFINE); //per la data fine deve tener conto di eventuali proroghe.. if (rec_commesse.get_bool(COMMESSE_PROROGA)) { const TDate datapror = rec_commesse.get_date(COMMESSE_DATAPROR); if (datapror.ok()) datafine = datapror; } //se almeno una delle due date risultasse incompleta.. if (!dataini.ok() || !datafine.ok()) { //prende l'anno TEsercizi_contabili esc; int anno = rec_commesse.get_int(COMMESSE_ANNO); //se non trova un anno valido (non sono ammesse commesse prima del XX secolo!) if (anno <= 1900) { //prova con dataini, se è buona... if (dataini.ok()) anno = esc.date2esc(dataini); else { //allora prova con datafine, se è buona... if (datafine.ok()) anno = esc.date2esc(datafine); else anno = esc.first(); //se nessuna data è buona mette l'anno = al primo esercizio } } //se entrambe le date fossero vuote, visto che comunque adesso l'anno ce l'ha, le può ricavare... // Probabilmente le prossime 3 righe andrebbero cancellate: si assume una commessa per un anno if (!dataini.ok() && !datafine.ok()) esc.code2range(anno, dataini, datafine); else //solo una data o nessuna data non buona { TDate dummy; //dataini viene messa = ad inizio anno commessa if (!dataini.ok()) esc.code2range(anno, dataini, dummy); //datafine viene messa = alla data di scadenza dell'ultimo esercizio valido + 1 anno (mantiene corrette le sezioni di stampa) if (!datafine.ok()) esc.code2range(esc.last() + 1, dummy, datafine); } } //if (!dataini.ok() || !datafine.ok()) return datafine - dataini + 1; }