diff --git a/sv/svlib01.cpp b/sv/svlib01.cpp index df953f42c..2782cb30a 100755 --- a/sv/svlib01.cpp +++ b/sv/svlib01.cpp @@ -1,9 +1,14 @@ #include #include +#include #include "svlib01.h" #include "svriep.h" +#include "svstat.h" +#include "..\mg\anamag.h" +#include "..\pr\agenti.h" +#include "..\ve\clifor.h" /////////////////////////////////////////////////////////// // Funzioni di utilita' comune @@ -110,6 +115,8 @@ int divide(TFrequenza_statistiche f1, TFrequenza_statistiche f2) return 0; } +//@cmember ritorna la parte "periodo" di una data (l'anno si ottiene da year()) +// tutti i periodi cominciano da 1 int date2period(const TDate& datadoc, TFrequenza_statistiche freq) { int classe; @@ -155,6 +162,18 @@ int date2period(const TDate& datadoc, TFrequenza_statistiche freq) return classe; } +//@cmember +long date2long(const TDate d, TFrequenza_statistiche f) +{ + return long(d.year())*long(last_period(d.year(),f))+date2period(d,f); +} + +long period2long(const int anno, const int periodo, TFrequenza_statistiche f) +{ + return long(anno)*long(last_period(anno,f))+periodo; +} + + const TDate& floor(TDate& data, TFrequenza_statistiche freq) { switch (freq) @@ -268,6 +287,7 @@ void TStats_agg::init() _zona = ini.get_bool("ZonaGrp"); _giacenza = ini.get_bool("GiacenzaGrp"); _magazzino = ini.get_bool("MagazzinoGrp"); + _catvend = ini.get_bool("CatVendGrp"); } void TStats_agg::test_firm() const @@ -280,6 +300,8 @@ void TStats_agg::test_firm() const } } +// scrive la chiave nel record +// utilizza la convenzione in TStats_agg::find per la tokenstring void TStats_agg::put_key(TRectype& stat, TToken_string& key) const { CHECK(stat.num() == LF_SVRIEP, "Ci vuole un record delle statistiche"); @@ -292,12 +314,16 @@ void TStats_agg::put_key(TRectype& stat, TToken_string& key) const stat.put(SVR_CODART, key.get()); stat.put(SVR_UMQTA, key.get()); stat.put(SVR_CODAG, key.get()); + stat.put(SVR_TIPOCF, key.get()); stat.put(SVR_CODCF, key.get()); stat.put(SVR_ZONA, key.get()); stat.put(SVR_GIAC, key.get()); stat.put(SVR_MAG, key.get()); + stat.put(SVR_CATVEN, key.get()); } +// ricerca la chiave nell'assocarray +// la convenzione per la tokenstring è utilizzata in put_key TStats_agg::TStats_data& TStats_agg::find(const TRiga_documento& rdoc) { test_firm(); @@ -326,6 +352,7 @@ TStats_agg::TStats_data& TStats_agg::find(const TRiga_documento& rdoc) else codart = rdoc.get(RDOC_CODART); key.add(codart); + // l'unità di misura non viene MAI RAGGRUPPATA sul riepilogo statistiche! key.add(rdoc.get(RDOC_UMQTA)); if (_agente) @@ -334,9 +361,13 @@ TStats_agg::TStats_data& TStats_agg::find(const TRiga_documento& rdoc) key.add(""); if (_cliente) + { + key.add(doc.get(DOC_TIPOCF)); key.add(doc.get(DOC_CODCF)); - else + } else { key.add(""); + key.add(""); + } if (_zona) key.add(doc.get(DOC_ZONA)); @@ -353,6 +384,11 @@ TStats_agg::TStats_data& TStats_agg::find(const TRiga_documento& rdoc) else key.add(""); + if (_catvend) + key.add(doc.get(DOC_CATVEN)); + else + key.add(""); + TStats_data* ptr = (TStats_data*)_data.objptr(key); if (ptr == NULL) { @@ -429,7 +465,8 @@ bool TStats_agg::add(const TRiga_documento& rdoc) bool TStats_agg::update() { - TProgind pi(_data.items(), "Aggiornamento statistiche", FALSE, TRUE, 60); +// eliminato perché rompeva a Sandro +// TProgind pi(_data.items(), "Aggiornamento statistiche", FALSE, TRUE, 60); test_firm(); @@ -437,12 +474,14 @@ bool TStats_agg::update() TToken_string key(64); TLocalisamfile stat(LF_SVRIEP); + stat.set_curr(new TSVriep_record); + TRectype& curr = stat.curr(); _data.restart(); for (THash_object* h = _data.get_hashobj(); h; h = _data.get_hashobj()) { - pi.addstatus(1); + //pi.addstatus(1); TStats_data& data = (TStats_data&)h->obj(); if (data._quantita.is_zero() && data._valore.is_zero()) @@ -488,3 +527,324 @@ bool TStats_agg::update() TStats_agg::TStats_agg() : _ditta(-1) { } + +/////////////////////////////////////////////////////////// +// Record del file svriep +/////////////////////////////////////////////////////////// + +TSVriep_record:: TSVriep_record(): TVariable_rectype(LF_SVRIEP), + _anamag(LF_ANAMAG), + _clifor(LF_CLIFO), + _agenti(LF_AGENTI), + _magazz(LF_MAG), + _tipodoc("%NUM"), + _catven("CVE"), + _zone("ZON"), + _ums("%UMS") +{} + +TSVriep_record::~TSVriep_record() +{} + +const TString & TSVriep_record::get_str(const char* fieldname) const +{ + static TString80 chiavi; + chiavi=TRectype::get_str(SVR_CHIAVI); + + if (strcmp(fieldname,SVR_CODART)==0) + return chiavi.mid(0,20); + else if (strcmp(fieldname,SVR_CODAG)==0) + return chiavi.mid(20,5); + else if (strcmp(fieldname,SVR_TIPOCF)==0) + return chiavi.mid(25,1); + else if (strcmp(fieldname,SVR_CODCF)==0) + return chiavi.mid(26,6); + else if (strcmp(fieldname,SVR_ZONA)==0) + return chiavi.mid(32,3); + else if (strcmp(fieldname,SVR_GIAC)==0) + return chiavi.mid(35,15); + else if (strcmp(fieldname,SVR_CATVEN)==0) + return chiavi.mid(50,3); + else if (strcmp(fieldname,SVR_MAG)==0) + return chiavi.mid(53,3); + else + return TRectype::get_str(fieldname); +} + + +void TSVriep_record::put_str(const char* fieldname, const char* val) +{ + static TString80 chiavi; + chiavi=TRectype::get_str(SVR_CHIAVI); + + if (strcmp(fieldname,SVR_CODART)==0) + chiavi.overwrite(val,0); + else if (strcmp(fieldname,SVR_CODAG)==0) + chiavi.overwrite(val,20); + else if (strcmp(fieldname,SVR_TIPOCF)==0) + chiavi.overwrite(val,25); + else if (strcmp(fieldname,SVR_CODCF)==0) + chiavi.overwrite(val,26); + else if (strcmp(fieldname,SVR_ZONA)==0) + chiavi.overwrite(val,32); + else if (strcmp(fieldname,SVR_GIAC)==0) + chiavi.overwrite(val,35); + else if (strcmp(fieldname,SVR_CATVEN)==0) + chiavi.overwrite(val,50); + else if (strcmp(fieldname,SVR_MAG)==0) + chiavi.overwrite(val,53); + else + { + TRectype::put_str(fieldname,val); + return ; + } + TRectype::put_str(SVR_CHIAVI,chiavi); + return ; +} + + +const TString& TSVriep_record::get_part(const char *lev_code) const +{ + static TString park(' ',25); + + int lev_code_num=atoi(lev_code+1); + switch (*lev_code) + { + case 'D': // tipo documento + return get(SVR_TIPODOC); + case 'A': // articolo + if (lev_code_num==0) + { + park=get(SVR_CODART); + return park.rpad(25); + } + else + { + park =_liv_art.unpack_grpcode(get(SVR_CODART),lev_code_num); + return park.rpad(_liv_art.code_length(lev_code_num)); + } + case 'L': // liv giac + CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente"); + park = _liv_giac.unpack_grpcode(get(SVR_GIAC),lev_code_num); + return park.rpad(_liv_giac.code_length(lev_code_num)); + case 'V': // cat. vendita + park=get(SVR_CATVEN); + return park.rpad(3); + case 'C': // cliente / fornitore + park.format("%c%6d",get_char(SVR_TIPOCF),get_int(SVR_CODCF)); + return park; + case 'G': // agente + park.format("%5d",get_int(SVR_CODAG)); + return park; + case 'M': // mag + park=get(SVR_MAG); + return park.rpad(3); + case 'Z': // zona + park=get(SVR_ZONA); + return park.rpad(3); + case 'U': // unità di misura + park=get(SVR_UMQTA); + return park.rpad(3); + default: + fatal_box("ai chent recognaiz the code of the key part!"); + return ""; + } +} + +const TString& TSVriep_record::get_descrpart(const char *lev_code) +{ + int lev_code_num=atoi(lev_code+1); + switch (*lev_code) + { + case 'D': // tipo documento + return _tipodoc.get(get(SVR_TIPODOC)).get("S0"); + case 'A': // articolo + if (lev_code_num==0 || lev_code_num== _liv_art.last_level()) + { + return _anamag.get(get(SVR_CODART)).get(ANAMAG_DESCR); + } + else + { + return _liv_art.group_descr(get(SVR_CODART),lev_code_num); + } + case 'L': // liv giac + CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente"); + //return _liv_giac.group_descr(unpack_grpcode(get(SVR_GIAC),lev_code_num),lev_code_num); + case 'V': // cat. vendita + return _catven.get(get(SVR_CATVEN)).get("S0"); + case 'C': // cliente + { + TToken_string cod; + cod.add(get_char(SVR_TIPOCF)); + cod.add(get_int(SVR_CODCF)); + return _clifor.get(cod).get(CLI_RAGSOC); + } + case 'G': // agente + return _agenti.get(get(SVR_CODAG)).get(AGE_RAGSOC); + case 'M': // mag + return _magazz.get(get(SVR_MAG)).get("S0"); + case 'Z': // zona + return _zone.get(get(SVR_ZONA)).get("S0"); + case 'U': // Unità di misura + return _ums.get(get(SVR_UMQTA)).get("S0"); + default: + fatal_box("ai chent recognaiz the code of the key part!"); + return ""; + } +} + + + +/////////////////////////////////////////////////////////// +// Cache +/////////////////////////////////////////////////////////// +#define RWCACHE_SIZE 10 + +// funzione di default: prende una chiave a caso chiave +const TString & TRWrecord_cache::getkey2discard() +{ + THash_object * o=get_some_obj(); + CHECK(o,"E' stata chiamata la funzione getkey2discard con la cache vuota"); + return o->key(); +} + +void TRWrecord_cache::discard(const TString & vittima) +{ + if (items()) + { + if (_flags.is_key(vittima)) + { + const char fl=((TString &)_flags[vittima])[1]; + // record modificato o nuovo + int err; + TRectype & rec=(TRectype & )TRecord_cache::get(vittima); + file().curr()=rec; + if (fl == 'D') + { + err=file().rewrite(); + if (err!=NOERR) + error_box("Errore nella riscrittura della cache"); + } else { + err=file().write(); + if (err!=NOERR) + if (err == _isreinsert) + file().rewrite(); + else + error_box("Errore nella scrittura della cache"); + } + _flags.remove(vittima); + + } + _cache.remove(vittima); + } +} + +const TRectype& TRWrecord_cache::get(const char* chiave) +{ + if (items()>=RWCACHE_SIZE) + discard(getkey2discard()); + const TRectype & rec=TRecord_cache::get(chiave); + if (io_result() != NOERR) + { + // record non trovato: è nuovo + _flags.add(chiave,new TString("N")); + } + return rec; +} + +void TRWrecord_cache::put(const TRectype &r) +{ + test_firm(); + + TToken_string cachekey; + if (!r.empty()) + { + const RecDes* recd = r.rec_des(); // Descrizione del record della testata + const KeyDes& kd = recd->Ky[key_number()-1]; // Elenco dei campi della chiave + for (int i = file().tab() ? 1: 0; i < kd.NkFields; i++) // Riempie la chiave selezionata + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = recd->Fd[nf]; + cachekey.add(r.get(rf.Name)); + } + } + + TObject* obj = _cache.objptr(cachekey); + + if (obj != NULL) + { + // esiste in cache ; tenta di settare il flag a "D"irty; se il flag esiste già è a + TRectype & rec=(TRectype &)*obj; + rec=r; + _flags.add(cachekey , new TString("D")); + } else { + // non esiste in cache + obj = rec2obj(r); + _cache.add(cachekey, obj); + // qui assume che non esista nemmeno su file, perciò sia "N"uovo; al flush correggerà l'errore + _flags.add(cachekey , new TString("N")); + } + if (items()>=RWCACHE_SIZE) + discard(getkey2discard()); +} + + +void TRWrecord_cache::clear() +{ + while (items()>0) + { + const TString & vittima=getkey2discard(); + if (_flags.is_key(vittima)) + _flags.remove(vittima); + _cache.remove(vittima); + } +} + + +void TRWrecord_cache::flush() +{ + while (items()>0) + discard(TRWrecord_cache::getkey2discard()); +} + +THash_object * TRWrecord_cache::get_some_obj() +{ + if (items()==0) + return NULL; + THash_object * o; + while ((o=_cache.get_hashobj()) == NULL) ; + return o; +} + +TRWrecord_cache::TRWrecord_cache(int num, int key, bool lock) + :TRecord_cache(num,key) +{ + if (lock) + file().lock(); +} + +TRWrecord_cache::~TRWrecord_cache() +{ + flush(); +} + + +// cerca di restituire una chiave di bassa priorità (livello +const TString & TStat_cache::getkey2discard() +{ + THash_object * o; + CHECK(items()>0,"E' stata chiamata la funzione getkey2discard con la cache vuota"); + while ((o=_cache.get_hashobj()) == NULL) ; + if (((TRectype &)o->obj()).get_int(SVS_LIVELLO)<=1) + { + while ((o=_cache.get_hashobj()) == NULL) ; + if (((TRectype &)o->obj()).get_int(SVS_LIVELLO)==0) + while ((o=_cache.get_hashobj()) == NULL) ; + } + return o->key(); +} + +TStat_cache ::TStat_cache (bool lock): + TRWrecord_cache( LF_SVSTAT,1,lock) +{ +} diff --git a/sv/svlib01.h b/sv/svlib01.h index 9ab9df3e0..c88e6694b 100755 --- a/sv/svlib01.h +++ b/sv/svlib01.h @@ -9,6 +9,12 @@ #include "..\ve\velib.h" #endif +#ifndef __TABUTIL_H +#include +#endif + +#include "..\mg\mglib.h" + enum TFrequenza_statistiche { fs_nulla, fs_giornaliera, fs_settimanale, fs_quindicinale, fs_mensile, fs_bimestrale, @@ -17,22 +23,28 @@ enum TFrequenza_statistiche { fs_nulla, fs_giornaliera, // Converte una carattere in una frequenza delle statisitiche TFrequenza_statistiche char2frequency(char c); -// Converte una frequenza delle statisitiche in un carattere +//Converte una frequenza delle statisitiche in un carattere char frequency2char(TFrequenza_statistiche f); -// Arrotondamento di una data alla frequenza specificata +//Arrotondamento di una data alla frequenza specificata const TDate& floor(TDate& data, TFrequenza_statistiche freq); const TDate& ceil(TDate& data, TFrequenza_statistiche freq); -// Ritorna il rapporto tra le frequenze: 0 se impossibile stabilirlo +//Ritorna il rapporto tra le frequenze: 0 se impossibile stabilirlo int divide(TFrequenza_statistiche f1, TFrequenza_statistiche f2); -// Ritorna l'ultimo perido di un anno (primo = 1) +//Ritorna l'ultimo periodo di un anno (primo = 1) int last_period(int anno, TFrequenza_statistiche freq); -// Converte una data nella classe temporale definita dalla frequenza +//Ritorna la parte "periodo" di una data (l'anno si ottiene da year()) int date2period(const TDate& data, TFrequenza_statistiche freq); - + +//Converte una data in un long in base alla frequenza passata +long date2long(const TDate d, TFrequenza_statistiche f); + +//Converte una coppia anno+periodo in un long in base alla frequenza passata +long period2long(const int anno, const int periodo, TFrequenza_statistiche f); + class TStats_agg : public TObject { class TStats_data : public TObject @@ -47,7 +59,7 @@ class TStats_agg : public TObject TFrequenza_statistiche _frequenza; bool _merce, _prestazioni, _omaggi, _omaggio_is_merce; bool _art_nocode, _art_noanag, _art_noanag_grp; - bool _agente, _cliente, _zona, _articolo, _giacenza, _magazzino; + bool _agente, _cliente, _zona, _articolo, _giacenza, _magazzino,_catvend; protected: void test_firm() const; @@ -74,6 +86,7 @@ public: bool grp_articolo() const { test_firm(); return _articolo; } bool grp_giacenza() const { test_firm(); return _giacenza; } bool grp_magazzino() const { test_firm(); return _magazzino; } + bool grp_catven() const { test_firm(); return _catvend; } bool omaggio_is_merce() const { test_firm(); return _omaggio_is_merce; } @@ -81,4 +94,51 @@ public: virtual ~TStats_agg() { } }; +class TSVriep_record : public TVariable_rectype +{ + TCodart_livelli _liv_art; + TCodgiac_livelli _liv_giac; + TRecord_cache _anamag,_clifor,_agenti,_magazz,_tipodoc,_catven,_zone,_ums; + +public: + const TString& get_part(const char *lev_code) const; + const TString& get_descrpart(const char *lev_code); + + virtual const TString & get_str(const char* fieldname) const; + virtual void put_str(const char* fieldname, const char* val); + TSVriep_record(); + virtual ~TSVriep_record(); +}; + + +class TRWrecord_cache : public TRecord_cache +{ + TAssoc_array _flags; + +protected: + THash_object * get_some_obj(); + virtual const TString & getkey2discard(); +public: + virtual void discard(const TString & k); + virtual void put(const TRectype &r); + virtual const TRectype& get(const char* chiave); + + void clear(); + void flush(); + + TRWrecord_cache(int num, int key = 1, bool lock=FALSE); + TRWrecord_cache(const char* table, int key = 1, bool lock=FALSE); + virtual ~TRWrecord_cache() ; +}; + +class TStat_cache : public TRWrecord_cache +{ +protected: + virtual const TString & getkey2discard(); +public: + TStat_cache (bool lock=FALSE); + virtual ~TStat_cache() + {} +}; #endif +