Files correlati : Ricompilazione Demo : [ ] Commento :corretto errore di compilazione dovuto a nuova implementazione stampe git-svn-id: svn://10.65.10.50/trunk@11593 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			461 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			461 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <applicat.h>
 | |
| #include <automask.h>
 | |
| #include <execp.h>
 | |
| #include <form.h>
 | |
| #include <relation.h>
 | |
| #include <printer.h>
 | |
| #include <progind.h>
 | |
| #include <recarray.h>
 | |
| #include <utility.h>
 | |
| #include <utility.h>
 | |
| 
 | |
| #include <doc.h>
 | |
| #include <rdoc.h>
 | |
| 
 | |
| #include "..\mg\umart.h"
 | |
| #include "..\mg\anamag.h"
 | |
| #include "dl0.h"
 | |
| #include "dl0500.h"
 | |
| #include "dl0500a.h"
 | |
| #include "dl0500b.h"
 | |
| 
 | |
| //-----FORM--------------------------------------------------------------------------------------//
 | |
| 
 | |
| class TRicerca_form : public TForm
 | |
| {
 | |
| 
 | |
| public:
 | |
|   TRicerca_form();
 | |
|   virtual ~TRicerca_form();
 | |
| };
 | |
|   
 | |
| TRicerca_form::TRicerca_form() :TForm ("dl0500a")
 | |
| {
 | |
| } 
 | |
| 
 | |
| TRicerca_form::~TRicerca_form()
 | |
| { 
 | |
| }
 | |
| 
 | |
| //-----AUTOMASK---------------------------------------------------------------------------------//
 | |
|   
 | |
| class TRicerca_mask : public TAutomask
 | |
| {
 | |
|   TRelation * _rel;
 | |
|   TCursor * _cur;
 | |
| 
 | |
| protected:
 | |
|   bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | |
| public:
 | |
| 
 | |
|   TRicerca_mask();
 | |
|   
 | |
|   virtual ~TRicerca_mask(){};
 | |
| };
 | |
|   
 | |
| TRicerca_mask::TRicerca_mask() :TAutomask ("dl0500a")
 | |
| {
 | |
| }  
 | |
|   
 | |
| bool TRicerca_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | |
| { 
 | |
|   switch (o.dlg())
 | |
|   {
 | |
|   case F_P_BARCODE:
 | |
|   case F_P_GIAC:
 | |
|   case F_P_TITOLO:
 | |
|   case F_P_ARTISTA:
 | |
|   case F_P_COMPOSITORE:
 | |
|   case F_P_ETICHETTA:
 | |
|   case F_P_PREZZO:
 | |
|   case F_P_GENERE:
 | |
|   case F_P_TIPOSUPPORTO:
 | |
|     if (e == fe_close)
 | |
|     { 
 | |
|       for (int i = 8; i >= 0; i--)    //attenzione! e' necessario che gli ID dei bools siano contigui
 | |
|       {
 | |
|       if (get_bool(F_P_BARCODE+i))
 | |
|         break;
 | |
|       }
 | |
|       if (i < 0)
 | |
|         return error_box("Selezionare almeno un campo per la stampa");
 | |
|          
 | |
|     }
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| //-------SKELETON APPLICATION------------------------------------------------------------------------------//
 | |
| 
 | |
| enum TFilter_type { dl_normal, dl_date, dl_um };
 | |
| enum TFilter_comp { dl_eq, dl_gt, dl_lt, dl_match };
 | |
| 
 | |
| struct TFilter_exp : public TObject
 | |
| {
 | |
|   TFilter_type _type;
 | |
|   TString16 _field;
 | |
|   TFilter_comp _cmp;
 | |
|   TString80 _value;  
 | |
| 
 | |
|   TFilter_exp() : _type(dl_normal), _cmp(dl_eq) { }
 | |
| };
 | |
| 
 | |
| class TRicerca: public TSkeleton_application
 | |
| {
 | |
|   TRicerca_mask * _mask;
 | |
|   static TMask * _ordmask;
 | |
|   bool _barcode, _giac, _titolo, _artista, _compositore, _etichetta, _prezzo, _genere, _tiposupp;
 | |
| 
 | |
|   static TArray _filtro;
 | |
|   
 | |
| protected:
 | |
|   virtual bool create(void);
 | |
|   virtual bool destroy(void);
 | |
|   virtual void main_loop();
 | |
| 
 | |
|   static bool process_link(int id, const char * lnk);
 | |
|   static void genera_ordine();
 | |
|   static bool fast_filter(const TRelation* rel);
 | |
|   
 | |
| public:
 | |
|   void add_expr_filter(const char * field, short id, TFilter_comp cmp) const;
 | |
|   void add_meta_filter(const char * field, short id) const;
 | |
|   void add_range_filter(const char * field, short fid, short tid = -1) const;
 | |
| 
 | |
|   TRicerca() {}
 | |
|   virtual ~TRicerca() {}
 | |
| };
 | |
| 
 | |
| TArray TRicerca::_filtro;
 | |
| 
 | |
| // restituisce un riferimento all' applicazione
 | |
| inline TRicerca& app() { return (TRicerca&) main_app();}
 | |
| 
 | |
| //la maschera dl0500b, essendo statica, va dichiarata anche fuori dalla classe
 | |
| TMask * TRicerca::_ordmask = NULL;
 | |
| 
 | |
| // creazione dell'applicazione
 | |
| bool TRicerca::create()
 | |
| {                        
 | |
|   open_files(LF_ANAMAG, LF_UMART, LF_MAG, LF_DOC, LF_RCONDV, 0);
 | |
|   _mask = new TRicerca_mask;
 | |
|   
 | |
|   TConfig config("discolat.ini","ADVRES");
 | |
|   _barcode = config.get_bool("BARCODE");
 | |
|   _giac = config.get_bool("GIAC");
 | |
|   _titolo = config.get_bool("TITOLO");
 | |
|   _artista = config.get_bool("ARTISTA");
 | |
|   _compositore = config.get_bool("COMPOSITORE");
 | |
|   _etichetta = config.get_bool("ETICHETTA");
 | |
|   _prezzo = config.get_bool("PREZZO");
 | |
|   _genere = config.get_bool("GENERE");
 | |
|   _tiposupp = config.get_bool("TIPOSUPP");
 | |
|   _mask->set(F_P_BARCODE, _barcode);
 | |
|   _mask->set(F_P_GIAC, _giac);
 | |
|   _mask->set(F_P_TITOLO, _titolo);
 | |
|   _mask->set(F_P_ARTISTA, _artista);
 | |
|   _mask->set(F_P_COMPOSITORE, _compositore);
 | |
|   _mask->set(F_P_ETICHETTA, _etichetta);
 | |
|   _mask->set(F_P_PREZZO, _prezzo);
 | |
|   _mask->set(F_P_GENERE, _genere);
 | |
|   _mask->set(F_P_TIPOSUPPORTO, _tiposupp);
 | |
|   
 | |
|   const int leadtime = config.get_int("LEADTIME");
 | |
|   
 | |
|   _ordmask = new TMask("dl0500b");  //creazione della maschera intermedia per la generazione righe ordini
 | |
|   config.set_paragraph("SENDORD");
 | |
|   _ordmask->set(F_CODCF, config.get("CODDL"));
 | |
|   _ordmask->set(F_CODORD, config.get("CODORD"));
 | |
|   
 | |
|   TDate datacons(TODAY);
 | |
|   datacons += leadtime;  
 | |
|   _ordmask->set(F_DATACONS, datacons);
 | |
| 
 | |
|   return TSkeleton_application::create();
 | |
| }
 | |
| 
 | |
| // distruzione dell'applicazione
 | |
| bool TRicerca::destroy()
 | |
| { 
 | |
|   TConfig config("discolat.ini", "SENDORD");
 | |
|   config.set("CODDL", _ordmask->get(F_CODCF));
 | |
|   config.set("CODORD", _ordmask->get(F_CODORD));
 | |
|   delete _ordmask; 
 | |
|   delete _mask;
 | |
|   return TSkeleton_application::destroy();
 | |
| }
 | |
| 
 | |
| //aggiunge effettivamente un'espressione ad un filtro
 | |
| void TRicerca::add_expr_filter(const char * field, short id, TFilter_comp cmp) const
 | |
| {       
 | |
|   TMask_field& fld = _mask->field(id);  //prende il campo dalla maschera
 | |
|   if (!fld.empty())                     //..se non e' vuoto
 | |
|   {
 | |
|     TFilter_exp* fe = new TFilter_exp;
 | |
|     fe->_field = field;
 | |
|     fe->_cmp = cmp;
 | |
|     //se e' un campo data deve ANSIzzare il contenuto del campo per aggiungerlo al filtro
 | |
|     if (fld.class_id() == CLASS_DATE_FIELD) 
 | |
|     {
 | |
|       fe->_type = dl_date; 
 | |
|       const TDate date = fld.get();
 | |
|       fe->_value = date.string(ANSI);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (stricmp(field, "UM") == 0)
 | |
|         fe->_type = dl_um;
 | |
|       fe->_value = fld.get(); //aggiunge il contenuto del campo al filtro
 | |
|     }
 | |
|     _filtro.add(fe);
 | |
|   }
 | |
| }
 | |
| 
 | |
| //aggiunge ad un filtro una espressione con l'*
 | |
| void TRicerca::add_meta_filter(const char * field, short id) const
 | |
| {     
 | |
|   const TString& value = _mask->get(id);
 | |
|   TFilter_comp cmp = dl_eq;
 | |
|   if (value.find('*') >= 0 || value.find('?') >= 0)
 | |
|     cmp = dl_match;
 | |
|   add_expr_filter(field, id, cmp);  
 | |
| }
 | |
| 
 | |
| //aggiunge ad un filtro un range di valori presi due campi o da uno (se coincidenti) 
 | |
| void TRicerca::add_range_filter(const char * field, short fid, short tid) const
 | |
| {
 | |
|   if (tid > fid)
 | |
|   {
 | |
|     add_expr_filter(field, fid, dl_gt);
 | |
|     add_expr_filter(field, tid, dl_lt);  
 | |
|   }
 | |
|   else
 | |
|     add_expr_filter(field, fid, dl_eq);
 | |
| }
 | |
| 
 | |
| //metodo ascetico per generare le righe di uno sheet dalla setlinkhandler (vedi la chiamata + sotto)
 | |
| bool TRicerca::process_link(int id, const char * lnk)
 | |
| { 
 | |
|   TSheet_field& sheet = _ordmask->sfield(F_RIGHE);
 | |
|   TToken_string& row = sheet.row(-1);
 | |
|   row = "1";      //mette innanzitutto la qta di default (1)
 | |
|   row.add(lnk);   //poi ci aggiunge il codart     
 | |
|   sheet.check_row(sheet.items()-1);
 | |
|   
 | |
|   KEY k = _ordmask->run();
 | |
|   switch(k)
 | |
|   {
 | |
|     case K_ESC:
 | |
|       sheet.destroy(sheet.items()-1);
 | |
|       break;
 | |
|     case K_ENTER:
 | |
|       break;
 | |
|     default:
 | |
|       genera_ordine(); //chiama il metodo x la generazione dell'ordine
 | |
|       break;
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| // metodo x la generazione dell'ordine
 | |
| void TRicerca::genera_ordine()
 | |
| {
 | |
|   TFilename iniord;     //creazione di un file di configurazione temporaneo contenente i dati dell'ordine
 | |
|   iniord.temp("DL");    // il nome comincia con DL
 | |
|   TConfig ini(iniord,"Transaction");  //paragrafo Transaction del file iniord
 | |
|   ini.set("Action", "Insert");
 | |
|   
 | |
|   const TDate datacons = _ordmask->get(F_DATACONS);   //setta la data di consegna in base alla data di compilazione ordine
 | |
|   const TDate oggi(TODAY);                            //e al leadtime che legge nel file discolat.ini
 | |
|   const long leadtime = datacons - oggi;
 | |
|   if (leadtime > 0)
 | |
|   {
 | |
|     TConfig inidata("discolat.ini", "ADVRES");
 | |
|     inidata.set("LEADTIME", leadtime);
 | |
|   }
 | |
| 
 | |
| //paragrafo testata documento ordine  
 | |
|   TString16 para;            
 | |
|   para.format("%d",LF_DOC);
 | |
|   
 | |
|   ini.set_paragraph(para);   //paragrafo della testata: scrive tutti i parametri utili nell'ini
 | |
|   ini.set(DOC_PROVV, "D");                        
 | |
|   ini.set(DOC_ANNO, oggi.year());         //anno di compilazione ordine
 | |
|   ini.set(DOC_CODNUM, _ordmask->get(F_CODORD));   //codice numerazione ordine
 | |
|   ini.set(DOC_TIPODOC, _ordmask->get(F_TIPODOC)); //tipo documento dell'ordine
 | |
|   ini.set(DOC_TIPOCF, "F");
 | |
|   ini.set(DOC_CODCF, _ordmask->get(F_CODCF));   //codice fornitore
 | |
|   ini.set(DOC_DATACONS, datacons);              //data di consegna 
 | |
|   
 | |
|   TConfig inilist("cat2dl.ini", "PARAMS");      //codice del listino all'ingrosso
 | |
|   ini.set(DOC_CODLIST, inilist.get("LISTINGR"));
 | |
|   
 | |
| //l'ordine deve essere aggiunto come il successivo all'ultimo gia' presente nelle testate documento
 | |
|   TLocalisamfile doc(LF_DOC);                //prepara i dati della chiave 1 a meno del campo NDOC
 | |
|   doc.put(DOC_PROVV, ini.get(DOC_PROVV));
 | |
|   doc.put(DOC_ANNO, ini.get(DOC_ANNO));  
 | |
|   doc.put(DOC_CODNUM, ini.get(DOC_CODNUM));
 | |
|   const TRectype test(doc.curr());           //come record di confronto si prende quello corrente
 | |
|   doc.put(DOC_NDOC, "9999999");
 | |
|                                
 | |
| //paragrafi delle righe dell'ordine  
 | |
|   TSheet_field& sheet = _ordmask->sfield(F_RIGHE);   
 | |
|   TString80 codart;
 | |
|   for (int i = 0; i < sheet.items(); i++)
 | |
|   {
 | |
|     para.format("%d,%d",LF_RIGHEDOC,i+1);
 | |
|     ini.set_paragraph(para);
 | |
|     TToken_string& row = sheet.row(i);
 | |
|     real qta = row.get(0);        //la qta sta nel primo campo dello sheet...
 | |
|     codart = row.get(1);          //..il codart nella seconda
 | |
|     ini.set(RDOC_TIPORIGA, "01"); //tiporigamerce
 | |
|     ini.set(RDOC_CODART, codart);
 | |
| //    ini.set(RDOC_CODARTMAG, codart);   inutile
 | |
|     ini.set(RDOC_QTA, qta.string());    
 | |
|   }  
 | |
|   ini.set_paragraph("Transaction"); //forza la scrittura dell'ultimo paragrafo!
 | |
|   
 | |
| //prepara la stringa di esecuzione del programma degli ordini e lo lancia  
 | |
|   TString cmd;
 | |
|   cmd << "ve0 -0 /i" << iniord;
 | |
|   TExternal_app app(cmd);
 | |
|   app.run();
 | |
| 
 | |
|   sheet.destroy();  //accoppa lo sheet da cui e' nato l'ordine
 | |
|   ::remove(iniord); //sopprime il file temporaneo
 | |
| }
 | |
| 
 | |
| bool TRicerca::fast_filter(const TRelation* rel)
 | |
| {
 | |
|   for (int i = 0; i < _filtro.items(); i++)
 | |
|   {
 | |
|     const TFilter_exp& fe = (const TFilter_exp&)_filtro[i];
 | |
|     TString80 field_value;
 | |
|     switch (fe._type)
 | |
|     {
 | |
|     case dl_date:
 | |
|       {
 | |
|         const TDate d = rel->curr().get(fe._field);
 | |
|         field_value = d.string(ANSI);
 | |
|       }
 | |
|       break;
 | |
|     case dl_um:
 | |
|       {
 | |
|         TString80 key = rel->curr().get(ANAMAG_CODART);
 | |
|         key << "|1";
 | |
|         field_value = cache().get(LF_UMART, key, fe._field);
 | |
|       }
 | |
|       break;
 | |
|     default:
 | |
|       field_value = rel->curr().get(fe._field);
 | |
|     }
 | |
|     switch (fe._cmp)
 | |
|     {
 | |
|     case dl_lt:
 | |
|       if (field_value > fe._value)
 | |
|         return FALSE;
 | |
|       break;
 | |
|     case dl_gt:
 | |
|       if (field_value < fe._value)
 | |
|         return FALSE;
 | |
|       break;
 | |
|     case dl_match:
 | |
|       if (!field_value.match(fe._value))
 | |
|         return FALSE;
 | |
|       break;
 | |
|     default:
 | |
|       if (field_value != fe._value)
 | |
|         return FALSE;
 | |
|     }
 | |
|   }
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| void TRicerca::main_loop()
 | |
| {
 | |
|   while (_mask->run() == K_ENTER)
 | |
|   { 
 | |
|     //prende dalla maschera i booleani dei campi da stampare...
 | |
|     _barcode = _mask->get_bool(F_P_BARCODE);
 | |
|     _giac = _mask->get_bool(F_P_GIAC);
 | |
|     _titolo = _mask->get_bool(F_P_TITOLO);
 | |
|     _artista = _mask->get_bool(F_P_ARTISTA);
 | |
|     _compositore = _mask->get_bool(F_P_COMPOSITORE);
 | |
|     _etichetta = _mask->get_bool(F_P_ETICHETTA);
 | |
|     _prezzo = _mask->get_bool(F_P_PREZZO);
 | |
|     _genere = _mask->get_bool(F_P_GENERE);
 | |
|     _tiposupp = _mask->get_bool(F_P_TIPOSUPPORTO);
 | |
| 
 | |
|     //..e li scrive nel file ini
 | |
|     TConfig config("discolat.ini","ADVRES");
 | |
|     config.set("BARCODE", _barcode);
 | |
|     config.set("GIAC", _giac);
 | |
|     config.set("TITOLO", _titolo);
 | |
|     config.set("ARTISTA", _artista);
 | |
|     config.set("COMPOSITORE", _compositore);
 | |
|     config.set("ETICHETTA", _etichetta);
 | |
|     config.set("PREZZO", _prezzo);
 | |
|     config.set("GENERE", _genere);
 | |
|     config.set("TIPOSUPP", _tiposupp);
 | |
|   
 | |
|     //laboriosissima costruzione del filtro
 | |
|     _filtro.destroy();
 | |
|     add_range_filter(ANAMAG_CODART, F_DABARCODE, F_ABARCODE);
 | |
|     add_meta_filter(ANAMAG_USER2, F_ARTISTA);
 | |
|     add_meta_filter(ANAMAG_DESCR, F_TITOLO);
 | |
|     add_meta_filter(ANAMAG_USER3, F_COMPOSITORE);
 | |
|     add_meta_filter(ANAMAG_USER4, F_ETICHETTA);
 | |
|     
 | |
|     add_range_filter(ANAMAG_GRMERC, F_GENEREMUSICALE);    
 | |
|     add_range_filter(ANAMAG_USER5, F_DATAE_INI, F_DATAE_FIN);
 | |
|     add_range_filter(ANAMAG_USER6, F_DATAV_INI, F_DATAV_FIN);
 | |
| //caso sfigato: c'e' il tipo supporto tra i parametri di filtro!   
 | |
|     add_range_filter("UM", F_TIPOSUPPORTO);
 | |
|  
 | |
| // setta i links presenti nel form (sono gli elementi scritti in blu(b) su bianco(w))
 | |
| // procedimento standard in questi casi
 | |
|     TArray& arr = printer().links();
 | |
|     if (arr.items() == 0)
 | |
|       arr.add(new TToken_string("Ordina|b|w"));
 | |
|     printer().setlinkhandler(process_link);
 | |
| 
 | |
| //dopo il filtrone tocca al cursore x scandire i records    
 | |
|     TRicerca_form form;
 | |
| //ottimizzazione tempi di ricerca: caso di filtro semplice (senza AND, con ?= o ==) 
 | |
| 
 | |
|    form.cursor()->set_filterfunction(fast_filter, FALSE);
 | |
|     
 | |
| //setta il form columnwise
 | |
|     form.find_field('B', odd_page, FF_B_CODART).show(_barcode);
 | |
|     form.find_field('B', odd_page, FF_B_GIAC).show(_giac);
 | |
|     form.find_field('B', odd_page, FF_B_TITOLO).show(_titolo);
 | |
|     form.find_field('B', odd_page, FF_B_ARTISTA).show(_artista);
 | |
|     form.find_field('B', odd_page, FF_B_COMPOSITORE).show(_compositore);
 | |
|     form.find_field('B', odd_page, FF_B_ETICHETTA).show(_etichetta);;
 | |
|     form.find_field('B', odd_page, FF_B_PREZZO).show(_prezzo);
 | |
|     form.find_field('B', odd_page, FF_B_GENERE).show(_genere);
 | |
|     form.find_field('B', odd_page, FF_B_SUPPORTO).show(_tiposupp);
 | |
| //procedimento mistico di costruzione del form columnwise    
 | |
|     const int hh = 5; //altezza header = 5 righe
 | |
|     int rows[4];
 | |
|     rows[0] = hh - 2;
 | |
|     rows[1] = hh;
 | |
|     rows[2] = printer().formlen();
 | |
|     rows[3] = 0;
 | |
|     
 | |
|     form.genera_intestazioni(odd_page, hh - 1);
 | |
|     form.genera_fincatura(odd_page, hh - 2, rows[2], rows);
 | |
|     
 | |
|     form.print();
 | |
|   }
 | |
| }
 | |
| 
 | |
| int dl0500(int argc, char* argv[])
 | |
| {
 | |
|   TRicerca a ;
 | |
|   a.run(argc, argv, "Ricerca avanzata");
 | |
|   return 0;
 | |
| }
 |