Files correlati : Ricompilazione Demo : [ ] Commento :terminato fido git-svn-id: svn://10.65.10.50/trunk@17855 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			817 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			817 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include "velib07.h"
 | ||
| 
 | ||
| #include <pconti.h>
 | ||
| 
 | ||
| #include "../cg/cgsaldac.h"
 | ||
| #include "../cg/cglib02.h"
 | ||
| #include "../db/dblib.h"
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TMateriali_base_recordset
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| const TVariant& TMateriali_base_recordset::get(const char* column_name) const
 | ||
| {
 | ||
| 	if (column_name[0] != '#')
 | ||
| 	{
 | ||
| 		TVariant& var = get_tmp_var();
 | ||
| 		int rownum = current_row();
 | ||
| 
 | ||
| 		if (reverse())
 | ||
| 			rownum = items() - 1 - rownum;
 | ||
| 
 | ||
| 		const	TRiga_esplosione* row = (const TRiga_esplosione*)boom().objptr(rownum);
 | ||
| 		
 | ||
| 		if (row != NULL)
 | ||
|  		{
 | ||
|    	  const TFixed_string name(column_name);
 | ||
|  		  if (name == "LASTQTA")
 | ||
| 				var = row->last_qta();
 | ||
| 			else
 | ||
| 				if (name == "TOTQTA")
 | ||
| 					var = row->val();
 | ||
| 				else
 | ||
| 				{
 | ||
| 					if (rownum != _lastrow)
 | ||
| 					{
 | ||
| 						((TMateriali_base_recordset *) this)->_lastrow = rownum;
 | ||
| 						const TCodice_articolo & comp  = row->componente();
 | ||
| 						const TCodice_articolo & dist  = row->distinta();
 | ||
| 						TLocalisamfile rd(LF_RDIST);
 | ||
| 
 | ||
| 						rd.setkey(2);
 | ||
| 						rd.put("CODCOMP", comp);
 | ||
| 						rd.put("CODDIST", dist);
 | ||
| 						if (rd.read() == NOERR)
 | ||
| 							*_rdist = rd.curr();
 | ||
| 					}
 | ||
| 					
 | ||
| 					
 | ||
| 					if (_rdist != NULL)
 | ||
| 					{
 | ||
| 						const TString & v = _rdist->get(column_name);
 | ||
| 
 | ||
| 						var = v;
 | ||
| 					}
 | ||
| 				}
 | ||
| 		}
 | ||
| 		return var;
 | ||
| 	}
 | ||
| 	return TRecordset::get(column_name);
 | ||
| }
 | ||
| 
 | ||
| const TVariant& TMateriali_base_recordset::get(unsigned int column) const
 | ||
| {
 | ||
| 	const TRecordset_column_info & ci  = column_info(column);
 | ||
| 	return get(ci._name);
 | ||
| }
 | ||
| 
 | ||
| void TMateriali_base_recordset::requery()
 | ||
| {
 | ||
| 	_boom.destroy();
 | ||
| 	int pos1 = query_text().find("MATBASE");
 | ||
| 	if (pos1 > 0)
 | ||
| 	{
 | ||
| 		pos1 += 7;
 | ||
| 		set_reverse(query_text()[pos1] == '-');
 | ||
| 		if (reverse())
 | ||
| 			pos1++;
 | ||
| 		int pos = query_text().find("==", pos1);
 | ||
| 		int pos2 = -1;
 | ||
| 		if (pos > 0)
 | ||
| 		{
 | ||
| 			TString val(query_text().mid(pos + 2));
 | ||
| 			pos2 = val.find("FILTER");
 | ||
| 
 | ||
| 			if (pos2 > 0)
 | ||
| 				val.cut(pos2 - 1);
 | ||
| 
 | ||
| 			if (val.starts_with("\"") || val.starts_with("'"))
 | ||
| 			{
 | ||
| 				val.ltrim(1);
 | ||
| 				val.rtrim(1);
 | ||
| 			}
 | ||
| 			else
 | ||
| 			{
 | ||
| 				TVariant var = get(val);
 | ||
| 				val = var.as_string();
 | ||
| 			}
 | ||
| 
 | ||
| 			const TCodice_articolo art(val);
 | ||
|      	TDistinta_tree	distinta;
 | ||
| 			if (distinta.set_root(art))
 | ||
| 			{
 | ||
| 				while (isspace(query_text()[pos1]))
 | ||
| 					pos1++;
 | ||
| 				const int level = atoi(query_text().mid(pos1));
 | ||
| 				if (level > 0 || query_text()[pos1] =='0')
 | ||
| 					while (isdigit(query_text()[pos1]))
 | ||
| 						pos1++;
 | ||
| 				while (isspace(query_text()[pos1]))
 | ||
| 					pos1++;
 | ||
| 				TString8 filter;
 | ||
| 				if (query_text()[pos1] != 'S')
 | ||
| 					while (isalpha(query_text()[pos1]))
 | ||
| 						filter << query_text()[pos1++];
 | ||
| 				distinta.explode(_boom, true, RAGGR_EXP_NONE, level, filter);
 | ||
| 			}
 | ||
| 			pos = query_text().find("FILTER", pos);
 | ||
| 			if (pos > 0) 
 | ||
| 			{
 | ||
| 				pos = query_text().find("==", pos);
 | ||
| 				if (pos > 0) 
 | ||
| 				{
 | ||
| 					TString val(query_text().mid(pos + 2));
 | ||
| 
 | ||
| 					if (val.starts_with("\"") || val.starts_with("'"))
 | ||
| 					{
 | ||
| 						val.ltrim(1);
 | ||
| 						val.rtrim(1);
 | ||
| 					}
 | ||
| 					else
 | ||
| 					{
 | ||
| 						TVariant var = get(val);
 | ||
| 						val = var.as_string();
 | ||
| 					}
 | ||
| 					const int items = _boom.items();
 | ||
| 					for (int i = 0; i < items; i++)
 | ||
| 					{
 | ||
| 						const	TRiga_esplosione * row = (const TRiga_esplosione *)_boom.objptr(i);
 | ||
| 						if ( row != NULL && row->componente() != val)
 | ||
| 							_boom.destroy(i);
 | ||
| 					} 
 | ||
| 					_boom.pack();
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| TMateriali_base_recordset::TMateriali_base_recordset(const char* use) : _query(use)
 | ||
| {
 | ||
| 	_lastrow = -1;
 | ||
| 	_rdist = new TRectype(LF_RDIST);
 | ||
| 	const int nfields = _rdist->items();
 | ||
| 	
 | ||
| 	int pos = 1;
 | ||
| 	for ( int i = 0 ; i < nfields; i++)
 | ||
| 	{
 | ||
| 		TRecordset_column_info * ci = new TRecordset_column_info;
 | ||
| 
 | ||
| 		ci->_name = _rdist->fieldname(i);
 | ||
| 		ci->_pos = pos;
 | ||
| 		ci->_type = _rdist->type(ci->_name);
 | ||
| 
 | ||
| 		const int len = _rdist->length(ci->_name);
 | ||
| 
 | ||
| 		pos += len;
 | ||
| 		ci->_width = len;
 | ||
| 		_column.add(ci);
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TScalare_recordset
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| void TScalare_recordset::requery()
 | ||
| {
 | ||
|   boom().destroy();
 | ||
| 	int pos1 = query_text().find("SCALARE");
 | ||
| 	if (pos1 > 0)
 | ||
| 	{
 | ||
| 		pos1 += 7;
 | ||
| 		set_reverse(query_text()[pos1] == '-');
 | ||
| 		if (reverse())
 | ||
| 			pos1++;
 | ||
| 		int pos = query_text().find("==", pos1);
 | ||
| 		if (pos > 0)
 | ||
| 		{
 | ||
| 			TString val(query_text().mid(pos + 2));
 | ||
| 
 | ||
| 			if (val.starts_with("\"") || val.starts_with("'"))
 | ||
| 			{
 | ||
| 				val.ltrim(1);
 | ||
| 				val.rtrim(1);
 | ||
| 			}
 | ||
| 			else
 | ||
| 			{
 | ||
| 				TVariant var = get(val);
 | ||
| 				val = var.as_string();
 | ||
| 			}
 | ||
| 
 | ||
| 			const TCodice_articolo art(val);
 | ||
|     	TDistinta_tree	distinta;
 | ||
| 			if (distinta.set_root(art))
 | ||
| 			{
 | ||
| 				while (isspace(query_text()[pos1]))
 | ||
| 					pos1++;
 | ||
| 				const int level = atoi(query_text().mid(pos1));
 | ||
| 				if (level > 0 || query_text()[pos1] =='0')
 | ||
| 					while (isdigit(query_text()[pos1]))
 | ||
| 						pos1++;
 | ||
| 				while (isspace(query_text()[pos1]))
 | ||
| 					pos1++;
 | ||
| 				TString8 filter;
 | ||
| 				if (query_text()[pos1] != 'S')
 | ||
| 					while (isalpha(query_text()[pos1]))
 | ||
| 						filter << query_text()[pos1++];
 | ||
| 				distinta.explode(boom(), false, RAGGR_EXP_NONE, level, filter);
 | ||
| 			}
 | ||
| 			pos = query_text().find("FILTER", pos);
 | ||
| 			if (pos > 0) 
 | ||
| 			{
 | ||
| 				pos = query_text().find("==", pos);
 | ||
| 				if (pos > 0) 
 | ||
| 				{
 | ||
| 					TString val(query_text().mid(pos + 2));
 | ||
| 
 | ||
| 					if (val.starts_with("\"") || val.starts_with("'"))
 | ||
| 					{
 | ||
| 						val.ltrim(1);
 | ||
| 						val.rtrim(1);
 | ||
| 					}
 | ||
| 					else
 | ||
| 					{
 | ||
| 						TVariant var = get(val);
 | ||
| 						val = var.as_string();
 | ||
| 					}
 | ||
| 					const int items = boom().items();
 | ||
| 					for (int i = 0; i < items; i++)
 | ||
| 					{
 | ||
| 						const	TRiga_esplosione * row = (const TRiga_esplosione *)boom().objptr(i);
 | ||
| 						if ( row != NULL && row->componente() != val)
 | ||
| 							boom().destroy(i);
 | ||
| 					}
 | ||
| 					boom().pack();
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TDocument_cache
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| TObject* TDocument_cache::key2obj(const char* key)
 | ||
| {
 | ||
|   TToken_string k(key);
 | ||
|   const char provv = *k.get(0);
 | ||
|   const int anno = k.get_int();
 | ||
|   const TString4 codnum= k.get();
 | ||
|   const long ndoc = k.get_long();
 | ||
|   TDocumento* doc = new TDocumento(provv, anno, codnum, ndoc);
 | ||
|   doc->get("IMPONIBILI"); // Bastardata per far funzionare la successiva dirty_fields
 | ||
|   doc->dirty_fields();
 | ||
|   return doc;
 | ||
| }
 | ||
| 
 | ||
| TDocumento& TDocument_cache::doc(const TRectype& rec)
 | ||
| {
 | ||
|   TToken_string key;
 | ||
|   key = rec.get(DOC_PROVV);
 | ||
|   key.add(rec.get(DOC_ANNO));
 | ||
|   key.add(rec.get(DOC_CODNUM));
 | ||
|   key.add(rec.get(DOC_NDOC));
 | ||
|   TDocumento& d =  *(TDocumento*)objptr(key);
 | ||
|   return d;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| TDocument_cache:: TDocument_cache() : TCache(3) 
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| TDocument_cache:: ~TDocument_cache()
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TDocument_recordset
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| const TVariant& TDocument_recordset::get_field(int num, const char* field) const
 | ||
| {
 | ||
|   if (*field != '#')
 | ||
|   {
 | ||
|     const int idx = relation()->log2ind(num);
 | ||
|     if (idx < 0)
 | ||
|       return NULL_VARIANT;
 | ||
|     const int logic = num > 0 ? num : relation()->file(idx).num();
 | ||
|     if (logic == LF_DOC || logic == LF_RIGHEDOC)
 | ||
|     {
 | ||
|       const TRectype& rec = relation()->file(idx).curr();
 | ||
|       // Se non e' un campo standard, ma e' calcolato da una formula...
 | ||
|       if (rec.type(field) == _nullfld && strncmp(field, "G1:", 3) != 0) 
 | ||
|       {
 | ||
|         const TDocumento& doc = ((TDocument_cache&)_cache).doc(rec);
 | ||
|         TVariant& var = get_tmp_var();
 | ||
| 
 | ||
|         if (xvt_str_compare_ignoring_case(field, "SEGNO") == 0)
 | ||
|         {
 | ||
|           var = doc.is_nota_credito() ? -UNO : UNO;   
 | ||
|         } else
 | ||
|         if (xvt_str_compare_ignoring_case(field, "IS_COSTO") == 0)
 | ||
|         {
 | ||
| 			    bool costo = (doc.tipo().is_costo()) || (!doc.tipo().is_ricavo() && doc.get_char(DOC_TIPOCF)=='F');
 | ||
|           var = costo ? UNO : ZERO;
 | ||
|         } else
 | ||
|         if (xvt_str_compare_ignoring_case(field, "IS_RICAVO") == 0)
 | ||
|         {
 | ||
| 			    bool ricavo = (doc.tipo().is_ricavo()) || (!doc.tipo().is_costo() && doc.get_char(DOC_TIPOCF)=='C');
 | ||
|           var = ricavo ? UNO : ZERO;
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           const TFieldref ref(field, logic);
 | ||
|           if (logic == LF_DOC)
 | ||
|           {
 | ||
|             var = ref.read(doc);
 | ||
|           }
 | ||
|           else
 | ||
|           {
 | ||
|             const int nriga = rec.get_int(RDOC_NRIGA);
 | ||
|             if (nriga > 0 && nriga <= doc.rows())
 | ||
|             {
 | ||
|               const TRiga_documento& rdoc = doc[nriga];
 | ||
|               var = ref.read(rdoc);
 | ||
|             }
 | ||
|             else
 | ||
|               var = NULL_VARIANT;
 | ||
|           }
 | ||
|         }
 | ||
|         return var;     
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return TISAM_recordset::get_field(num, field);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| // TDocument_report
 | ||
| ///////////////////////////////////////////////////////////
 | ||
| 
 | ||
| bool TDocument_report::set_recordset(const TString& query)
 | ||
| {
 | ||
| 	if (query.find("MATBASE") > 0)
 | ||
| 		return TReport::set_recordset(new TMateriali_base_recordset(query));
 | ||
| 	if (query.find("SCALARE") > 0)
 | ||
| 		return TReport::set_recordset(new TScalare_recordset(query));
 | ||
| 
 | ||
|   return TReport::set_recordset(new TDocument_recordset(query));
 | ||
| }
 | ||
| 
 | ||
| bool TDocument_report::load(const char* name)
 | ||
| {
 | ||
|   const bool ok = TReport::load(name);
 | ||
|   if (ok)
 | ||
|   {
 | ||
|     // Purtroppo il recordset delle sottosezioni deve essere reimpostato a mano
 | ||
|     for (int i = 11; i <= 999; i++)
 | ||
|     {
 | ||
|       TReport_section* sec = find_section('B', i);
 | ||
|       if (sec != NULL)
 | ||
|       {
 | ||
|         TRecordset* recset = sec->recordset();
 | ||
|         if (recset != NULL)
 | ||
|         {
 | ||
|           const TString use = recset->query_text();
 | ||
| 					if (use.find("MATBASE") > 0)
 | ||
| 						recset = new TMateriali_base_recordset(use);
 | ||
| 					else
 | ||
| 						if (use.find("SCALARE") > 0)
 | ||
| 							recset = new TScalare_recordset(use);
 | ||
| 						else
 | ||
|           recset = new TDocument_recordset(use);
 | ||
|           sec->set_recordset(recset);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return ok;
 | ||
| }
 | ||
| 
 | ||
| void TDocument_report::output_values(const TRectype& rec, const TString& output)
 | ||
| {
 | ||
|   TToken_string out(output, '!');
 | ||
|   TString curr;
 | ||
|   for (const char * str = out.get(0); str; str = out.get())
 | ||
|   { // scansione sugli elementi dell'output
 | ||
|     curr = str;
 | ||
|     int poseq = curr.find('='); // divide la stringa corrente in lvalue e rvalue
 | ||
|     if (poseq < 0)
 | ||
|     {
 | ||
|       curr_field()->set(rec.get(curr));
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       int posrv = poseq+1;
 | ||
|       if (poseq >= 0 && curr[posrv] == '=')
 | ||
|         posrv++;
 | ||
|       TString16 fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale
 | ||
|       const TString& dat = rec.get(curr.mid(posrv)); // preleva il nome del campo del file alla destra dell'uguale e lo legge dal record
 | ||
|       TReport_field* campo = field(fld);
 | ||
|       if (campo != NULL)
 | ||
|         campo->set(dat);
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| void TDocument_report::reset_values(const TString& output)
 | ||
| {
 | ||
|   TToken_string out(output, '!');
 | ||
|   TString curr;
 | ||
|   for (const char * str = out.get(0); str; str = out.get())
 | ||
|   { // scansione sugli elementi dell'output
 | ||
|     curr = str;
 | ||
|     int poseq = curr.find('='); // divide la stringa corrente in lvalue e rvalue
 | ||
|     if (poseq < 0)
 | ||
|     {
 | ||
|       curr_field()->set("");
 | ||
|     }
 | ||
|     else
 | ||
|     {
 | ||
|       TString16 fld(curr.left(poseq)); // preleva il nome del campo del form alla sinistra dell'uguale
 | ||
|       TReport_field* campo = field(fld);
 | ||
|       if (campo != NULL)
 | ||
|         campo->set("");
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| bool TDocument_report::msg_parent_doc(TVariant_stack& stack)
 | ||
| {
 | ||
|   TReport_field& cf = *curr_field();
 | ||
| 
 | ||
| 	int idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_DOC);
 | ||
| 
 | ||
|   if (idx < 0)
 | ||
| 		return false;
 | ||
| 
 | ||
| 	const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr();
 | ||
| 	TDocumento & doc  = (TDocumento &)((TDocument_recordset*)recordset())->doc(rec);
 | ||
| 	const TRiga_documento * rdoc = NULL;
 | ||
| 
 | ||
| 	  // Se il campo corrente non appartiene al body allora cerco la prima riga documento buona!
 | ||
|   if (cf.section().type() == 'B')
 | ||
| 	{
 | ||
| 	  idx = ((TISAM_recordset*)recordset())->cursor()->relation()->log2ind(LF_RIGHEDOC);
 | ||
| 		if (idx < 0)
 | ||
| 			return false;
 | ||
| 
 | ||
| 		const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr();
 | ||
| 		const int n = rec.get_long("NRIGA");
 | ||
| 
 | ||
| 		rdoc = &(doc[n]);
 | ||
| 	}
 | ||
| 	else
 | ||
|   {
 | ||
|     const TRiga_documento * first_desc = NULL;
 | ||
| 
 | ||
|     for (int r = 1; r <= doc.physical_rows(); r++)
 | ||
|     {
 | ||
|       const TRiga_documento& row = doc[r];
 | ||
|       if (row.get(RDOC_DANDOC).not_empty())
 | ||
|       {
 | ||
|         if (row.is_descrizione())
 | ||
|         {
 | ||
|           if (first_desc == NULL)
 | ||
|             first_desc = &row;  // Non e' una riga buona, ma nemmeno da buttare!
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|           rdoc = &row;
 | ||
|           break; // Ho trovato la riga buona!
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     if (rdoc == NULL && first_desc != NULL)
 | ||
| 	    rdoc = first_desc;
 | ||
|   }
 | ||
| 
 | ||
|   int level = stack.pop().as_int();   
 | ||
|   for (; rdoc != NULL && level > 0; level--)
 | ||
|     rdoc = (const TRiga_documento *)(rdoc->find_original_rdoc());
 | ||
| 
 | ||
|   const TString& values = stack.pop().as_string();
 | ||
|   const bool is_full = stack.peek().as_bool();
 | ||
|     
 | ||
|   if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty())
 | ||
|   {
 | ||
|     const char provv      = rdoc->get_char(RDOC_PROVV);
 | ||
|     const int anno        = rdoc->get_int(RDOC_ANNO);
 | ||
|     const TString4 codnum = rdoc->get(RDOC_CODNUM);
 | ||
|     const long ndoc       = rdoc->get_long(RDOC_NDOC);         
 | ||
|       
 | ||
|     if (is_full)
 | ||
|     {
 | ||
|       TDocumento doc(provv, anno, codnum, ndoc);
 | ||
|       output_values(doc, values);
 | ||
|     }
 | ||
|     else  
 | ||
|     {                               
 | ||
|       TToken_string key;
 | ||
|       key.add(provv); key.add(anno); key.add(codnum); key.add(ndoc);
 | ||
|       const TRectype& doc = cache().get(LF_DOC, key);
 | ||
|       output_values(doc, values);
 | ||
|     }
 | ||
|   }
 | ||
|   else
 | ||
|     reset_values(values);
 | ||
|   
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| bool TDocument_report::msg_parent_row(TVariant_stack& stack)
 | ||
| {
 | ||
| 	int idx = ((TISAM_recordset*)recordset())->cursor()->relation()->log2ind(LF_RIGHEDOC);
 | ||
| 	if (idx < 0)
 | ||
| 		return false;
 | ||
| 
 | ||
| 	const TRectype& rec = ((TISAM_recordset*)recordset())->cursor()->relation()->file(idx).curr();
 | ||
| 	const int n = rec.get_long("NRIGA");
 | ||
| 	idx =((TISAM_recordset *)recordset())->cursor()->relation()->log2ind(LF_DOC);
 | ||
| 
 | ||
|   if (idx < 0)
 | ||
| 		return false;
 | ||
| 
 | ||
| 	TDocumento & doc  = (TDocumento &)((TDocument_recordset*)recordset())->doc(rec);
 | ||
| 
 | ||
| 	const TRiga_documento * rdoc = &(doc[n]);
 | ||
| 
 | ||
| 	  // Se il campo corrente non appartiene al body allora cerco la prima riga documento buona!
 | ||
|   
 | ||
|   int level = stack.pop().as_int();
 | ||
|   for (; rdoc != NULL && level > 0; level--)
 | ||
|     rdoc = (const TRiga_documento *)(rdoc->find_original_rdoc());
 | ||
| 
 | ||
|   const TString& values = stack.pop().as_string();
 | ||
|   const bool is_full = stack.peek().as_bool();
 | ||
|   
 | ||
|   if (rdoc != NULL && rdoc->get(RDOC_PROVV).not_empty())
 | ||
|   {
 | ||
|     if (is_full)
 | ||
|     {
 | ||
|       const char provv      = rdoc->get_char(RDOC_PROVV);
 | ||
|       const int anno        = rdoc->get_int(RDOC_ANNO);
 | ||
|       const TString4 codnum = rdoc->get(RDOC_CODNUM);
 | ||
|       const long ndoc       = rdoc->get_long(RDOC_NDOC);
 | ||
|       TDocumento doc(provv, anno, codnum, ndoc);
 | ||
|       output_values(doc[rdoc->get_int(RDOC_NRIGA)], values);
 | ||
|     }
 | ||
|     else
 | ||
|       output_values(*rdoc, values);
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| size_t TDocument_report::get_usr_words(TString_array& words) const
 | ||
| {
 | ||
|   TReport::get_usr_words(words);
 | ||
|   
 | ||
|   const char* const name[] = { "DOC_PARENT_DOC", "DOC_PARENT_ROW", NULL };
 | ||
| 
 | ||
|   ((TDocument_report*)this)->_first_msg = words.items(); // Calcola il primo numero disponibile
 | ||
|   for (size_t i = 0; name[i] != NULL; i++)
 | ||
|     words.add(name[i]);
 | ||
|   
 | ||
|   return words.items();
 | ||
| }
 | ||
| 
 | ||
| bool TDocument_report::execute_usr_word(unsigned int opcode, TVariant_stack& stack)
 | ||
| {
 | ||
|   if (opcode < _first_msg)
 | ||
|     return TReport::execute_usr_word(opcode, stack);
 | ||
|   opcode -= _first_msg;
 | ||
|   switch (opcode)
 | ||
|   {
 | ||
|   case 0 : msg_parent_doc(stack); break;
 | ||
|   case 1 : msg_parent_row(stack); break;
 | ||
|   default: break;
 | ||
|   }
 | ||
| 
 | ||
|   while (!stack.pop().is_null());  // Svuota eventuali parametri variabili inutilizzati
 | ||
| 
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| /////////////////////////////////////////
 | ||
| //  Metodi non appartenenti a classi
 | ||
| /////////////////////////////////////////
 | ||
| 
 | ||
| // METODI PER IL CALCOLO DEL FIDO
 | ||
| 
 | ||
| //estrazioni mastri clienti e/o fornitori
 | ||
| static const TString_array& mastro(char tipocf)
 | ||
| {
 | ||
|   static TString_array m[2];
 | ||
|   const TString_array& a = m[tipocf == 'C' ? 0 : 1];
 | ||
| 
 | ||
|   if (a.empty())
 | ||
|   {
 | ||
|     TISAM_recordset mastri("USE PCON SELECT (CONTO!=\"\")&&(SOTTOCONTO=\"\")");
 | ||
|     for (bool ok = mastri.move_first(); ok; ok = mastri.move_next())
 | ||
|     {
 | ||
|       const int gruppo = mastri.get(PCN_GRUPPO).as_int();
 | ||
|       const int conto = mastri.get(PCN_CONTO).as_int();
 | ||
|       const int indbil = mastri.get(PCN_INDBIL).as_int();
 | ||
|       const char tipocf = mastri.get(PCN_TMCF).as_string()[0];
 | ||
|       TToken_string info;
 | ||
|       info.add(gruppo);
 | ||
|       info.add(conto);
 | ||
|       info.add(indbil);
 | ||
|       m[tipocf == 'C' ? 0 : 1].add(info);
 | ||
|     }
 | ||
|   }
 | ||
|   return a;
 | ||
| }
 | ||
| 
 | ||
| static real calcola_saldo_contabile(const char tipocf, const long codcf, const TDate& datacalc)
 | ||
| {
 | ||
|   real saldone;
 | ||
| 
 | ||
|   TEsercizi_contabili esc;
 | ||
|   TDate datainies, datafines;
 | ||
|   const int codes = esc.date2esc(datacalc);
 | ||
|   if (codes > 0)      
 | ||
|     esc.code2range(codes, datainies, datafines);
 | ||
|   else
 | ||
|   {
 | ||
|     datainies = datacalc;
 | ||
|     datainies.set_day(1);
 | ||
|     datainies.set_month(1);
 | ||
|   }
 | ||
| 
 | ||
|   const TString_array& a = mastro(tipocf);
 | ||
| 
 | ||
|   //per tutti i mastri selezionati va a calcolare il saldo del cliente/fornitore in input
 | ||
|   FOR_EACH_ARRAY_ROW(a, i, row)
 | ||
|   {
 | ||
|     const int gruppo = row->get_int(0);
 | ||
|     const int conto = row->get_int(1);
 | ||
|     const int indbil = row->get_int(2);
 | ||
| 
 | ||
|     TSaldo saldo;
 | ||
|     real saldo_periodo = saldo.saldo_periodo(gruppo, conto, codcf, datainies, datacalc, indbil, false);
 | ||
| 
 | ||
|     saldone += saldo_periodo;
 | ||
|   }
 | ||
|   return saldone;
 | ||
| }
 | ||
| 
 | ||
| static TImporto get_importo(const TISAM_recordset& partite, const char* sezione, const char* valore)
 | ||
| {
 | ||
|   const char sez = partite.get(sezione).as_string()[0];
 | ||
|   const real val = partite.get(valore).as_real();
 | ||
|   return TImporto(sez, val);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static real calcola_esposto_da_saldaconto (const char tipocf, const long codcf, const TDate& datacalc, const int riskdays)
 | ||
| {
 | ||
|   //estrae le righe partita relative a pagamenti successivi alla data di rischio (e con tipopag >2,<7)
 | ||
|   TString query;
 | ||
|   query << "USE PART\nSELECT BETWEEN(DATAPAG,#DATASBF,0)&&BETWEEN(TIPOPAG,2,7)\n";
 | ||
|   query << "FROM TIPOC=#TIPOCF GRUPPO=0 CONTO=0 SOTTOCONTO=#CODCF ANNO=#ANNO\n";
 | ||
|   query << "TO TIPOC=#TIPOCF GRUPPO=0 CONTO=0 SOTTOCONTO=#CODCF";
 | ||
| 
 | ||
|   TISAM_recordset partite(query);
 | ||
| 
 | ||
|   TString4 str_tipocf = tipocf;
 | ||
|   partite.set_var("#TIPOCF", TVariant(str_tipocf));
 | ||
|   partite.set_var("#CODCF", codcf);
 | ||
|   partite.set_var("#DATACALC", datacalc);
 | ||
|   //data considerante i giorni di rischio ammessi dall'utonto
 | ||
|   TDate data_sbf = datacalc;
 | ||
|   data_sbf -= riskdays;
 | ||
|   partite.set_var("#DATASBF", data_sbf);  //data salvo buon fine
 | ||
|   partite.set_var("#ANNO", TVariant((long)data_sbf.year()));
 | ||
| 
 | ||
| 
 | ||
|   //importone somma degli importi delle righe del recordset
 | ||
|   TImporto importone_esposto;
 | ||
| 
 | ||
|   for (bool ok = partite.move_first(); ok; ok = partite.move_next())
 | ||
|   {
 | ||
|     TImporto importo_riga;
 | ||
| 
 | ||
|     //fatture,note di credito,pagamenti
 | ||
|     TImporto importo_partita = get_importo(partite, PART_SEZ, PART_IMPORTO);
 | ||
|     importo_riga += importo_partita;
 | ||
| 
 | ||
|     //pagamenti (tm=3), insoluti (tm=5), pagamenti insoluti(tm=6)
 | ||
|     if (partite.get(PART_TIPOMOV).as_int() >= tm_pagamento)
 | ||
|     {
 | ||
|       TImporto importo_abbuono = get_importo(partite, PART_SEZABB, PART_ABBUONI);
 | ||
|       importo_riga += importo_abbuono;
 | ||
|       //pagamenti in valuta
 | ||
|       if (!partite.get(PART_CODVAL).is_empty())
 | ||
|       {
 | ||
|         TImporto importo_diff_cambio = get_importo(partite, PART_SEZDIFCAM, PART_DIFFCAM);
 | ||
|         importo_riga += importo_diff_cambio;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     //somma importi presenti sulla riga partita (fatture, pagamenti, insoluti, pagamenti insoluti)
 | ||
|     importone_esposto += importo_riga;
 | ||
| 
 | ||
|   }
 | ||
|   //la normalizzazione del totale delle partite va fatta in base al fatto che si parli di 'C'liente o 'F'ornitore
 | ||
|   const char sezione_finale = (tipocf == 'C') ? 'A' : 'D';
 | ||
|   importone_esposto.normalize(sezione_finale);
 | ||
| 
 | ||
|   //valore in output
 | ||
|   real esposto;
 | ||
|   esposto += importone_esposto.valore();
 | ||
|   
 | ||
|   return esposto;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static real calcola_fido_da_documenti(const char tipocf, const long codcf, const TDate& datacalc)
 | ||
| {
 | ||
|   real totalone;
 | ||
|   TConfig config(CONFIG_DITTA, "ve");
 | ||
| 
 | ||
|   //scansione delle righe FIDO_XX(j)=.. sul paragrafo di configurazione VE per avere i parametri di numerazione/tipo..
 | ||
|   //..da considerare
 | ||
| 	for (int j = 0;;j++)
 | ||
| 	{
 | ||
| 		const TString& num_fido = config.get("FIDO_NUM", NULL, j);
 | ||
|     //se manca la numerazione si pu<70> fermare,in quanto non pu<70> esistere un tipo senza numerazione
 | ||
|     if (num_fido.blank())
 | ||
| 			break;
 | ||
|     const TString& tipo_fido = config.get("FIDO_TIP", NULL, j);
 | ||
|     const TString4 da_stato_fido = config.get("FIDO_DASTA", NULL, j);
 | ||
|     const TString4 a_stato_fido = config.get("FIDO_ASTA", NULL, j);
 | ||
|     const bool residuo_fido = config.get_bool("FIDO_RES", NULL, j);
 | ||
| 
 | ||
|     //per la numerazione scelta queryzza gli archivi alla ricerca dei documenti che rientrano nei parametri
 | ||
|     TString query;
 | ||
|     query << "USE DOC KEY 2\n";
 | ||
|     query << "SELECT (CODNUM=#CODNUM)&&(TIPODOC=#TIPODOC)&&(BETWEEN(STATO,#DASTATO,#ASTATO))\n";
 | ||
|     query << "FROM TIPOCF=#TIPOCF CODCF=#CODCF PROVV='D'\n";
 | ||
|     query << "TO TIPOCF=#TIPOCF CODCF=#CODCF PROVV='D' ANNO=#ANNO DATADOC=#DATACALC";
 | ||
| 
 | ||
|     TISAM_recordset documenti(query);
 | ||
| 
 | ||
|     const char str_tipocf[2] = { tipocf, 0 };
 | ||
|     documenti.set_var("#TIPOCF", TVariant(str_tipocf));
 | ||
|     documenti.set_var("#CODCF", codcf);
 | ||
|     documenti.set_var("#ANNO", TVariant((long)datacalc.year()));
 | ||
|     documenti.set_var("#DATACALC", datacalc);
 | ||
|     documenti.set_var("#CODNUM", TVariant(num_fido));
 | ||
|     documenti.set_var("#TIPODOC", TVariant(tipo_fido));
 | ||
|     documenti.set_var("#DASTATO", TVariant(da_stato_fido));
 | ||
|     documenti.set_var("#ASTATO", TVariant(a_stato_fido));
 | ||
| 
 | ||
|     const int items = documenti.items();
 | ||
| 
 | ||
|     //adesso che ha i documenti che cercava..
 | ||
|     for (bool ok = documenti.move_first(); ok; ok = documenti.move_next())
 | ||
|     {
 | ||
|       const TDocumento doc(documenti.cursor()->curr());
 | ||
|       //deve tener conto di eventuali docs in valuta
 | ||
|       TCurrency_documento totdoc(ZERO, doc);
 | ||
| 
 | ||
|       //documento a residuo (tipo ordini)
 | ||
|       if (residuo_fido)
 | ||
|       {
 | ||
|         totdoc.set_num(doc.valore(false, true));
 | ||
|       }
 | ||
|       else  //documento normale (tipo fattura)
 | ||
|       {
 | ||
|         totdoc.set_num(doc.totale_doc());
 | ||
|       }
 | ||
| 
 | ||
|       totdoc.change_to_firm_val();
 | ||
| 
 | ||
|       //le nac vanno con segno rovesciato
 | ||
|       if (doc.is_nota_credito())
 | ||
|         totdoc = -totdoc;
 | ||
| 
 | ||
|       totalone += totdoc.get_num();
 | ||
|     }
 | ||
| 	}
 | ||
| 
 | ||
|   return totalone;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| //metodo per il calcolo fido di un cliente ad una data definita
 | ||
| real calcola_fido_cliente (const char tipocf, const long codcf, const TDate& datacalc, const int riskdays)
 | ||
| {
 | ||
|   //PRIMA PARTE: controlla i movimenti
 | ||
|   real saldo_contabile = calcola_saldo_contabile(tipocf, codcf, datacalc);
 | ||
|   //SECONDA PARTE: controlla il saldaconto
 | ||
|   real esposto_saldaconto = calcola_esposto_da_saldaconto(tipocf, codcf, datacalc, riskdays);
 | ||
|   //TERZA PARTE: controlla i documenti
 | ||
|   real tot_documenti = calcola_fido_da_documenti(tipocf, codcf, datacalc);
 | ||
| 
 | ||
|   return saldo_contabile + esposto_saldaconto + tot_documenti;
 | ||
| }
 | ||
| 
 | ||
| // FINE METODI PER IL CALCOLO DEL FIDO
 |