Files correlati :ca0.exe,ca0900a.msk,ca3.exe,camenu.men Ricompilazione Demo : [ ] Commento : programma anti-angcas funzionante per il bilancio di commessa; da installare e provare a dinamica git-svn-id: svn://10.65.10.50/branches/R_10_00@21381 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			3135 lines
		
	
	
		
			84 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			3135 lines
		
	
	
		
			84 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | ||
| #include <config.h>
 | ||
| #include <dongle.h>
 | ||
| #include <modaut.h>
 | ||
| #include <tree.h>
 | ||
| #include <treectrl.h>
 | ||
| #include <urldefid.h>
 | ||
| 
 | ||
| #include <mov.h>
 | ||
| #include <pconti.h>
 | ||
| #include <doc.h>
 | ||
| #include <rdoc.h>
 | ||
| 
 | ||
| #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)
 | ||
|   {
 | ||
|     TString& tmp = get_tmp_string();
 | ||
|     const TFixed_string var(varname);
 | ||
|     //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 = "LLLLLLLLLLLLLLLLLLLL"; else
 | ||
|     if (var == "CmsDes" && index == 1)
 | ||
|       tmp = TR("Commessa"); else
 | ||
|     if (var == "Fsc" && index == 1)
 | ||
|       tmp = "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)
 | ||
| {
 | ||
|   static TConfig_anal* cfg = NULL;
 | ||
|   if (cfg == NULL || force)
 | ||
|   {
 | ||
|     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
 | ||
| {
 | ||
|   bool yes = level <= 0;
 | ||
|   return yes;
 | ||
| }
 | ||
| 
 | ||
| bool TMultilevel_code_info::is_numeric_picture(int level) const
 | ||
| {
 | ||
|   const TString& pic = picture(level);
 | ||
|   if (pic.blank())
 | ||
|     return false;
 | ||
| 
 | ||
|   for (int i = 0; pic[i]; i++)
 | ||
|     if (pic[i] != '0' && pic[i] != '9')
 | ||
|       return false;
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| 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);
 | ||
|       TString8 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);
 | ||
| 
 | ||
|   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 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 \"" << TR("Proroga") << "\" PROROGA" << '\n';
 | ||
| 		out << "DI \"" << TR("Data") << "@10" << "\" DATAPROR" << '\n';
 | ||
| 		out << "DI \"" << TR("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' ? "BUZ" : "BU";
 | ||
| 
 | ||
| 			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);
 | ||
|       }
 | ||
| 			kfld->set_warning(mci.prompt(i));
 | ||
| 			offset += prompt.len() + picture.len() + 4;
 | ||
| 			if (desc_offset < offset)
 | ||
| 				desc_offset = offset;
 | ||
| 			if (i == par_items - 1)
 | ||
| 			{
 | ||
| 				row_offset++;
 | ||
| 				offset = 0;
 | ||
| 			}
 | ||
|     }
 | ||
|   }
 | ||
|   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, unsigned int mode,
 | ||
|                          short& first_cdc, short& first_cms, short& first_fase, short& first_conto,
 | ||
|                          const TString80 cdc_fld, const TString80 cms_fld, const TString80 fase_fld, const TString80 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.empty())  // 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(!cms_fld.empty())
 | ||
|     {
 | ||
| 		  if (level == "CMS")  // 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.empty())  //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.empty())  //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 <20> 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();
 | ||
|         const TString prompt = ((TEditable_field &)f).get_warning();
 | ||
|         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);
 | ||
|       }
 | ||
|       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(name);
 | ||
|   }
 | ||
|   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 <20> 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, _testandlock);
 | ||
|       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();
 | ||
|         }
 | ||
| //        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<70> dipendere dalle righe se si utilizza il calcolo..
 | ||
| //..automatico di dataexpire in base alle commesse sulle righe! Adolf ne sa una pi<70> 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<70> 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'<27> 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'<27> 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 <20> di tipo edit pu<70> 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 <20> buona...
 | ||
|       if (dataini.ok())
 | ||
|         anno = esc.date2esc(dataini); 
 | ||
|       else
 | ||
|       {
 | ||
|         //allora prova con datafine, se <20> buona...
 | ||
|         if (datafine.ok())
 | ||
|           anno = esc.date2esc(datafine); 
 | ||
|         else
 | ||
|           anno = esc.first(); //se nessuna data <20> buona mette l'anno = al primo esercizio
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     //se entrambe le date fossero vuote, visto che comunque adesso l'anno ce l'ha, le pu<70> ricavare..
 | ||
|     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;
 | ||
| }
 | ||
| 
 | ||
| 
 |