1997-08-18 14:20:21 +00:00
|
|
|
|
#include <prefix.h>
|
|
|
|
|
#include <progind.h>
|
1997-09-19 10:17:17 +00:00
|
|
|
|
#include <recarray.h>
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
#include "svlib01.h"
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
#include "svriep.h"
|
1997-09-19 10:17:17 +00:00
|
|
|
|
#include "svstat.h"
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
1997-08-26 13:40:34 +00:00
|
|
|
|
// Funzioni di utilita' comune
|
1997-08-05 09:24:21 +00:00
|
|
|
|
///////////////////////////////////////////////////////////
|
1997-10-06 10:22:47 +00:00
|
|
|
|
#define FREQ_CODES " GSQ12346A"
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-08-26 13:40:34 +00:00
|
|
|
|
TFrequenza_statistiche char2frequency(char c)
|
|
|
|
|
{
|
1997-10-06 10:22:47 +00:00
|
|
|
|
const TFixed_string list(FREQ_CODES);
|
1997-08-26 13:40:34 +00:00
|
|
|
|
TFrequenza_statistiche f = TFrequenza_statistiche(list.find(c));
|
|
|
|
|
return f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char frequency2char(TFrequenza_statistiche f)
|
|
|
|
|
{
|
1997-10-06 10:22:47 +00:00
|
|
|
|
const char* list = FREQ_CODES;
|
1997-08-26 13:40:34 +00:00
|
|
|
|
return list[f];
|
|
|
|
|
}
|
1997-08-18 14:20:21 +00:00
|
|
|
|
|
1997-10-06 10:22:47 +00:00
|
|
|
|
TString & char2freqname(char c)
|
|
|
|
|
{
|
|
|
|
|
static TString16 s;
|
|
|
|
|
const TFixed_string list(FREQ_CODES);
|
|
|
|
|
TToken_string std_descr("Giorno|Settimana|Quindicina|Mese|"
|
|
|
|
|
"Bimestre|Trimestre|Quadrimestre|Semestre|Anno");
|
|
|
|
|
s= std_descr.get(list.find(c)-1);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int last_period(const TDate & d, TFrequenza_statistiche f)
|
|
|
|
|
{
|
|
|
|
|
return last_period(d.year(),f);
|
|
|
|
|
}
|
|
|
|
|
|
1997-08-26 13:40:34 +00:00
|
|
|
|
int last_period(int anno, TFrequenza_statistiche f)
|
|
|
|
|
{
|
|
|
|
|
int n = 0;
|
|
|
|
|
switch(f)
|
1997-08-18 14:20:21 +00:00
|
|
|
|
{
|
1997-08-26 13:40:34 +00:00
|
|
|
|
case fs_giornaliera : n = 365 + (TDate::last_day(2, anno) == 29); break;
|
|
|
|
|
case fs_settimanale : n = 52; break;
|
|
|
|
|
case fs_quindicinale : n = 24; break;
|
|
|
|
|
case fs_mensile : n = 12; break;
|
|
|
|
|
case fs_bimestrale : n = 6; break;
|
|
|
|
|
case fs_trimestrale : n = 4; break;
|
|
|
|
|
case fs_quadrimestrale : n = 3; break;
|
|
|
|
|
case fs_semestrale : n = 2; break;
|
|
|
|
|
case fs_annuale : n = 1; break;
|
|
|
|
|
default: NFCHECK("Invalid frequency");
|
1997-08-18 14:20:21 +00:00
|
|
|
|
}
|
1997-08-26 13:40:34 +00:00
|
|
|
|
return n;
|
1997-08-18 14:20:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-08-26 13:40:34 +00:00
|
|
|
|
int divide(TFrequenza_statistiche f1, TFrequenza_statistiche f2)
|
1997-08-18 14:20:21 +00:00
|
|
|
|
{
|
1997-08-26 13:40:34 +00:00
|
|
|
|
CHECK(f1 >= f2 && f2 != fs_nulla, "Invalid frequency division");
|
|
|
|
|
|
|
|
|
|
if (f1 == f2)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
switch (f1)
|
|
|
|
|
{
|
|
|
|
|
case fs_annuale:
|
|
|
|
|
switch(f2)
|
|
|
|
|
{
|
|
|
|
|
case fs_semestrale : return 2;
|
|
|
|
|
case fs_quadrimestrale: return 3;
|
|
|
|
|
case fs_trimestrale : return 4;
|
|
|
|
|
case fs_bimestrale : return 6;
|
|
|
|
|
case fs_mensile : return 12;
|
|
|
|
|
case fs_quindicinale : return 24;
|
|
|
|
|
case fs_settimanale : return 52;
|
|
|
|
|
default : break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case fs_semestrale:
|
|
|
|
|
switch(f2)
|
|
|
|
|
{
|
|
|
|
|
case fs_trimestrale :return 2;
|
|
|
|
|
case fs_bimestrale :return 3;
|
|
|
|
|
case fs_mensile :return 6;
|
|
|
|
|
case fs_quindicinale :return 12;
|
|
|
|
|
case fs_settimanale :return 26;
|
|
|
|
|
default :break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case fs_quadrimestrale:
|
|
|
|
|
switch(f2)
|
|
|
|
|
{
|
|
|
|
|
case fs_bimestrale :return 2;
|
|
|
|
|
case fs_mensile :return 4;
|
|
|
|
|
case fs_quindicinale :return 8;
|
|
|
|
|
default :break;
|
|
|
|
|
}
|
|
|
|
|
case fs_trimestrale:
|
|
|
|
|
switch(f2)
|
|
|
|
|
{
|
|
|
|
|
case fs_mensile :return 3;
|
|
|
|
|
case fs_quindicinale :return 6;
|
|
|
|
|
case fs_settimanale :return 13;
|
|
|
|
|
default :break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case fs_bimestrale:
|
|
|
|
|
switch(f2)
|
|
|
|
|
{
|
|
|
|
|
case fs_mensile :return 2;
|
|
|
|
|
case fs_quindicinale :return 4;
|
|
|
|
|
default :break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case fs_mensile:
|
|
|
|
|
if (f2 == fs_quindicinale)
|
|
|
|
|
return 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
1997-08-18 14:20:21 +00:00
|
|
|
|
}
|
1997-08-26 13:40:34 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
1997-08-18 14:20:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-19 10:17:17 +00:00
|
|
|
|
//@cmember ritorna la parte "periodo" di una data (l'anno si ottiene da year())
|
|
|
|
|
// tutti i periodi cominciano da 1
|
1997-08-26 13:40:34 +00:00
|
|
|
|
int date2period(const TDate& datadoc, TFrequenza_statistiche freq)
|
1997-08-18 14:20:21 +00:00
|
|
|
|
{
|
1997-08-05 09:24:21 +00:00
|
|
|
|
int classe;
|
1997-08-26 13:40:34 +00:00
|
|
|
|
if (freq > fs_settimanale)
|
1997-08-05 09:24:21 +00:00
|
|
|
|
{
|
|
|
|
|
classe = datadoc.month();
|
1997-08-26 13:40:34 +00:00
|
|
|
|
switch(freq)
|
1997-08-05 09:24:21 +00:00
|
|
|
|
{
|
1997-08-18 14:20:21 +00:00
|
|
|
|
case fs_quindicinale:
|
1997-08-05 09:24:21 +00:00
|
|
|
|
classe = (classe-1) * 2 + 1;
|
|
|
|
|
if (datadoc.day() > 15) classe++;
|
1997-08-18 14:20:21 +00:00
|
|
|
|
break;
|
|
|
|
|
case fs_bimestrale:
|
|
|
|
|
classe = (classe-1) / 2 + 1;
|
|
|
|
|
break;
|
|
|
|
|
case fs_trimestrale:
|
|
|
|
|
classe = (classe-1) / 3 + 1;
|
|
|
|
|
break;
|
1997-08-26 13:40:34 +00:00
|
|
|
|
case fs_quadrimestrale:
|
|
|
|
|
classe = (classe-1) / 4 + 1;
|
|
|
|
|
break;
|
|
|
|
|
case fs_semestrale:
|
|
|
|
|
classe = (classe-1) / 6 + 1;
|
|
|
|
|
break;
|
|
|
|
|
case fs_annuale:
|
|
|
|
|
classe = 1;
|
|
|
|
|
break;
|
|
|
|
|
default: // fs_mensile
|
1997-08-18 14:20:21 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
1997-08-05 09:24:21 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const TDate primo(1, 1, datadoc.year());
|
|
|
|
|
classe = int(datadoc - primo);
|
1997-08-26 13:40:34 +00:00
|
|
|
|
if (freq == fs_settimanale)
|
|
|
|
|
{
|
1997-08-05 09:24:21 +00:00
|
|
|
|
classe /= 7;
|
1997-08-26 13:40:34 +00:00
|
|
|
|
if (classe > 51) classe = 51;
|
|
|
|
|
}
|
1997-08-05 09:24:21 +00:00
|
|
|
|
classe++;
|
|
|
|
|
}
|
|
|
|
|
return classe;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-19 10:17:17 +00:00
|
|
|
|
//@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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1997-08-26 13:40:34 +00:00
|
|
|
|
const TDate& floor(TDate& data, TFrequenza_statistiche freq)
|
|
|
|
|
{
|
|
|
|
|
switch (freq)
|
|
|
|
|
{
|
|
|
|
|
case fs_settimanale:
|
|
|
|
|
{
|
|
|
|
|
const TDate primo(1, 1, data.year());
|
|
|
|
|
int settimana = int((data - primo) / 7);
|
|
|
|
|
if (settimana > 51) settimana = 51;
|
|
|
|
|
data = primo;
|
|
|
|
|
data += settimana * 7;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case fs_quindicinale:
|
|
|
|
|
data.set_day(data.day() <= 15 ? 1 : 16);
|
|
|
|
|
break;
|
|
|
|
|
case fs_mensile:
|
|
|
|
|
data.set_day(1);
|
|
|
|
|
break;
|
|
|
|
|
case fs_bimestrale:
|
|
|
|
|
data.set_day(1);
|
|
|
|
|
data.set_month(((data.month()-1) / 2) * 2 + 1);
|
|
|
|
|
break;
|
|
|
|
|
case fs_trimestrale:
|
|
|
|
|
data.set_day(1);
|
|
|
|
|
data.set_month(((data.month()-1) / 3) * 3 + 1);
|
|
|
|
|
break;
|
|
|
|
|
case fs_quadrimestrale:
|
|
|
|
|
data.set_day(1);
|
|
|
|
|
data.set_month(((data.month()-1) / 4) * 4 + 1);
|
|
|
|
|
break;
|
|
|
|
|
case fs_semestrale:
|
|
|
|
|
data.set_day(1);
|
|
|
|
|
data.set_month(data.month() <= 6 ? 1 : 7);
|
|
|
|
|
break;
|
|
|
|
|
case fs_annuale:
|
|
|
|
|
data.set_day(1);
|
|
|
|
|
data.set_month(1);
|
|
|
|
|
break;
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TDate& ceil(TDate& data, TFrequenza_statistiche freq)
|
|
|
|
|
{
|
|
|
|
|
floor(data, freq);
|
|
|
|
|
switch (freq)
|
|
|
|
|
{
|
|
|
|
|
case fs_settimanale:
|
|
|
|
|
data += 6;
|
|
|
|
|
if (data.month() == 12 && data.day() >= 29)
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_quindicinale:
|
|
|
|
|
if (data.day() == 1)
|
|
|
|
|
data.set_day(15);
|
|
|
|
|
else
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_mensile:
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_bimestrale:
|
|
|
|
|
data.addmonth(1);
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_trimestrale:
|
|
|
|
|
data.addmonth(2);
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_quadrimestrale:
|
|
|
|
|
data.addmonth(3);
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_semestrale:
|
|
|
|
|
data.addmonth(5);
|
|
|
|
|
data.set_end_month();
|
|
|
|
|
break;
|
|
|
|
|
case fs_annuale:
|
|
|
|
|
data.set_month(12);
|
|
|
|
|
data.set_day(31);
|
|
|
|
|
break;
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// TStats_agg
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void TStats_agg::init()
|
|
|
|
|
{
|
|
|
|
|
_ditta = prefix().get_codditta();
|
|
|
|
|
|
|
|
|
|
TConfig ini(CONFIG_DITTA, "sv");
|
|
|
|
|
|
|
|
|
|
_frequenza = char2frequency(ini.get_char("Frequenza"));
|
|
|
|
|
_merce = ini.get_bool("StatMerce");
|
|
|
|
|
_prestazioni = ini.get_bool("StatPrestazioni");
|
|
|
|
|
_omaggi = ini.get_bool("StatOmaggi");
|
|
|
|
|
_omaggio_is_merce = ini.get_bool("OmaggioIsMerce");
|
|
|
|
|
|
|
|
|
|
_art_nocode = ini.get_bool("ArtNoCode");
|
|
|
|
|
_art_noanag = ini.get_bool("ArtNoAnag");
|
|
|
|
|
_art_noanag_grp = ini.get_bool("ArtNoAnagGrp");
|
|
|
|
|
|
|
|
|
|
_agente = ini.get_bool("AgenteGrp");
|
|
|
|
|
_cliente = ini.get_bool("ClienteGrp");
|
|
|
|
|
_zona = ini.get_bool("ZonaGrp");
|
|
|
|
|
_giacenza = ini.get_bool("GiacenzaGrp");
|
|
|
|
|
_magazzino = ini.get_bool("MagazzinoGrp");
|
1997-09-19 10:17:17 +00:00
|
|
|
|
_catvend = ini.get_bool("CatVendGrp");
|
1997-08-26 13:40:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TStats_agg::test_firm() const
|
|
|
|
|
{
|
|
|
|
|
const long ditta = prefix().get_codditta();
|
|
|
|
|
if (ditta > 0 && ditta != _ditta)
|
|
|
|
|
{
|
|
|
|
|
CHECK(_data.items() == 0, "Non cambiare ditta durante un'operazione di ricalcolo!");
|
|
|
|
|
((TStats_agg*)this)->init();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-19 10:17:17 +00:00
|
|
|
|
// scrive la chiave nel record
|
|
|
|
|
// utilizza la convenzione in TStats_agg::find per la tokenstring
|
1997-08-18 14:20:21 +00:00
|
|
|
|
void TStats_agg::put_key(TRectype& stat, TToken_string& key) const
|
|
|
|
|
{
|
|
|
|
|
CHECK(stat.num() == LF_SVRIEP, "Ci vuole un record delle statistiche");
|
|
|
|
|
stat.zero();
|
1997-08-26 13:40:34 +00:00
|
|
|
|
key.restart();
|
|
|
|
|
stat.put(SVR_ANNO, key.get());
|
1997-08-18 14:20:21 +00:00
|
|
|
|
stat.put(SVR_PERIODO, key.get());
|
|
|
|
|
stat.put(SVR_TIPODOC, key.get());
|
|
|
|
|
stat.put(SVR_TIPOART, key.get());
|
|
|
|
|
stat.put(SVR_CODART, key.get());
|
|
|
|
|
stat.put(SVR_UMQTA, key.get());
|
|
|
|
|
stat.put(SVR_CODAG, key.get());
|
1997-09-19 10:17:17 +00:00
|
|
|
|
stat.put(SVR_TIPOCF, key.get());
|
1997-08-18 14:20:21 +00:00
|
|
|
|
stat.put(SVR_CODCF, key.get());
|
1997-08-26 13:40:34 +00:00
|
|
|
|
stat.put(SVR_ZONA, key.get());
|
|
|
|
|
stat.put(SVR_GIAC, key.get());
|
|
|
|
|
stat.put(SVR_MAG, key.get());
|
1997-09-19 10:17:17 +00:00
|
|
|
|
stat.put(SVR_CATVEN, key.get());
|
1997-08-18 14:20:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-19 10:17:17 +00:00
|
|
|
|
// ricerca la chiave nell'assocarray
|
|
|
|
|
// la convenzione per la tokenstring <20> utilizzata in put_key
|
1997-08-05 09:24:21 +00:00
|
|
|
|
TStats_agg::TStats_data& TStats_agg::find(const TRiga_documento& rdoc)
|
|
|
|
|
{
|
1997-08-18 14:20:21 +00:00
|
|
|
|
test_firm();
|
|
|
|
|
|
1997-08-05 09:24:21 +00:00
|
|
|
|
const TDocumento& doc = rdoc.doc();
|
|
|
|
|
const TDate datadoc = doc.get(DOC_DATADOC);
|
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
TToken_string key(64);
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
|
|
|
|
key.add(datadoc.year());
|
1997-08-18 14:20:21 +00:00
|
|
|
|
key.add(date2period(datadoc));
|
|
|
|
|
key.add(doc.get(DOC_TIPODOC));
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
|
|
|
|
char tipo = rdoc.tipo().tipo();
|
1997-08-18 14:20:21 +00:00
|
|
|
|
if (tipo == RIGA_OMAGGI && _omaggio_is_merce)
|
|
|
|
|
tipo = RIGA_MERCE;
|
1997-08-05 09:24:21 +00:00
|
|
|
|
key.add(tipo);
|
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
TString80 codart;
|
|
|
|
|
if (tipo != RIGA_PRESTAZIONI)
|
|
|
|
|
{
|
|
|
|
|
codart = rdoc.get(RDOC_CODARTMAG);
|
|
|
|
|
if (codart.empty() && !_art_noanag_grp)
|
|
|
|
|
codart = rdoc.get(RDOC_CODART);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
codart = rdoc.get(RDOC_CODART);
|
1997-08-05 09:24:21 +00:00
|
|
|
|
key.add(codart);
|
1997-09-19 10:17:17 +00:00
|
|
|
|
// l'unit<69> di misura non viene MAI RAGGRUPPATA sul riepilogo statistiche!
|
1997-08-18 14:20:21 +00:00
|
|
|
|
key.add(rdoc.get(RDOC_UMQTA));
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
|
|
|
|
if (_agente)
|
|
|
|
|
key.add(doc.get(DOC_CODAG));
|
1997-08-18 14:20:21 +00:00
|
|
|
|
else
|
|
|
|
|
key.add("");
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
|
|
|
|
if (_cliente)
|
1997-09-19 10:17:17 +00:00
|
|
|
|
{
|
|
|
|
|
key.add(doc.get(DOC_TIPOCF));
|
1997-08-05 09:24:21 +00:00
|
|
|
|
key.add(doc.get(DOC_CODCF));
|
1997-09-19 10:17:17 +00:00
|
|
|
|
} else {
|
|
|
|
|
key.add("");
|
1997-08-18 14:20:21 +00:00
|
|
|
|
key.add("");
|
1997-09-19 10:17:17 +00:00
|
|
|
|
}
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-08-26 13:40:34 +00:00
|
|
|
|
if (_zona)
|
|
|
|
|
key.add(doc.get(DOC_ZONA));
|
|
|
|
|
else
|
|
|
|
|
key.add("");
|
|
|
|
|
|
1997-08-05 09:24:21 +00:00
|
|
|
|
if (_giacenza)
|
1997-08-18 14:20:21 +00:00
|
|
|
|
key.add(rdoc.get(RDOC_LIVELLO));
|
|
|
|
|
else
|
|
|
|
|
key.add("");
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
|
|
|
|
if (_magazzino)
|
1997-08-18 14:20:21 +00:00
|
|
|
|
key.add(rdoc.get(RDOC_CODMAG));
|
|
|
|
|
else
|
|
|
|
|
key.add("");
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-09-19 10:17:17 +00:00
|
|
|
|
if (_catvend)
|
|
|
|
|
key.add(doc.get(DOC_CATVEN));
|
|
|
|
|
else
|
|
|
|
|
key.add("");
|
|
|
|
|
|
1997-08-05 09:24:21 +00:00
|
|
|
|
TStats_data* ptr = (TStats_data*)_data.objptr(key);
|
|
|
|
|
if (ptr == NULL)
|
|
|
|
|
{
|
|
|
|
|
ptr = new TStats_data;
|
|
|
|
|
_data.add(key, ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TStats_agg::can_add(const TRiga_documento& rdoc) const
|
1997-08-18 14:20:21 +00:00
|
|
|
|
{
|
|
|
|
|
test_firm();
|
|
|
|
|
|
|
|
|
|
const TTipo_documento& tip = rdoc.doc().tipo();
|
|
|
|
|
bool ok = tip.statistiche();
|
|
|
|
|
|
|
|
|
|
if (ok)
|
1997-08-05 09:24:21 +00:00
|
|
|
|
{
|
1997-08-18 14:20:21 +00:00
|
|
|
|
const char tipo = rdoc.tipo().tipo();
|
|
|
|
|
switch(tipo)
|
|
|
|
|
{
|
|
|
|
|
case RIGA_MERCE : ok = _merce; break;
|
|
|
|
|
case RIGA_OMAGGI : ok = _omaggi; break;
|
|
|
|
|
case RIGA_PRESTAZIONI: ok = _prestazioni; break;
|
|
|
|
|
default : ok = FALSE; break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ok && !rdoc.is_articolo())
|
|
|
|
|
{
|
|
|
|
|
const TString& codart = rdoc.get(RDOC_CODART);
|
|
|
|
|
if (codart.empty())
|
|
|
|
|
ok = _art_nocode;
|
|
|
|
|
else
|
|
|
|
|
ok = _art_noanag;
|
1997-08-05 09:24:21 +00:00
|
|
|
|
}
|
1997-08-18 14:20:21 +00:00
|
|
|
|
|
1997-08-05 09:24:21 +00:00
|
|
|
|
return ok;
|
1997-08-18 14:20:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TStats_agg::reset()
|
|
|
|
|
{
|
|
|
|
|
_data.destroy();
|
1997-08-05 09:24:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TStats_agg::sub(const TRiga_documento& rdoc)
|
|
|
|
|
{
|
|
|
|
|
bool ok = can_add(rdoc);
|
|
|
|
|
if (ok)
|
|
|
|
|
{
|
|
|
|
|
TStats_data& data = find(rdoc);
|
|
|
|
|
data._quantita -= rdoc.quantita();
|
|
|
|
|
data._valore -= rdoc.imponibile();
|
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TStats_agg::add(const TRiga_documento& rdoc)
|
|
|
|
|
{
|
|
|
|
|
bool ok = can_add(rdoc);
|
|
|
|
|
if (ok)
|
|
|
|
|
{
|
|
|
|
|
TStats_data& data = find(rdoc);
|
1997-08-18 14:20:21 +00:00
|
|
|
|
|
1997-08-05 09:24:21 +00:00
|
|
|
|
data._valore += rdoc.imponibile();
|
1997-08-18 14:20:21 +00:00
|
|
|
|
real qta = rdoc.quantita();
|
|
|
|
|
if (qta.is_zero())
|
|
|
|
|
qta = 1.0;
|
|
|
|
|
data._quantita += qta;
|
1997-08-05 09:24:21 +00:00
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TStats_agg::update()
|
1997-08-18 14:20:21 +00:00
|
|
|
|
{
|
1997-09-19 10:17:17 +00:00
|
|
|
|
// eliminato perch<63> rompeva a Sandro
|
|
|
|
|
// TProgind pi(_data.items(), "Aggiornamento statistiche", FALSE, TRUE, 60);
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
test_firm();
|
|
|
|
|
|
|
|
|
|
bool ok = TRUE;
|
|
|
|
|
|
|
|
|
|
TToken_string key(64);
|
|
|
|
|
TLocalisamfile stat(LF_SVRIEP);
|
1997-09-19 10:17:17 +00:00
|
|
|
|
stat.set_curr(new TSVriep_record);
|
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
TRectype& curr = stat.curr();
|
|
|
|
|
|
|
|
|
|
_data.restart();
|
|
|
|
|
for (THash_object* h = _data.get_hashobj(); h; h = _data.get_hashobj())
|
|
|
|
|
{
|
1997-09-19 10:17:17 +00:00
|
|
|
|
//pi.addstatus(1);
|
1997-08-18 14:20:21 +00:00
|
|
|
|
|
|
|
|
|
TStats_data& data = (TStats_data&)h->obj();
|
|
|
|
|
if (data._quantita.is_zero() && data._valore.is_zero())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
key = h->key();
|
|
|
|
|
|
|
|
|
|
bool saved = FALSE;
|
|
|
|
|
while (!saved)
|
|
|
|
|
{
|
|
|
|
|
put_key(curr, key);
|
|
|
|
|
int err = stat.read(_isequal, _lock);
|
|
|
|
|
if (err != NOERR)
|
|
|
|
|
put_key(curr, key);
|
|
|
|
|
real quantita(curr.get(SVR_QUANTITA));
|
|
|
|
|
real valore(curr.get(SVR_VALORE));
|
|
|
|
|
quantita += data._quantita;
|
|
|
|
|
valore += data._valore;
|
|
|
|
|
curr.put(SVR_QUANTITA, quantita);
|
|
|
|
|
curr.put(SVR_VALORE, valore);
|
|
|
|
|
|
|
|
|
|
if (err == NOERR)
|
|
|
|
|
err = stat.rewrite();
|
|
|
|
|
else
|
|
|
|
|
err = stat.write();
|
|
|
|
|
|
|
|
|
|
switch(err)
|
|
|
|
|
{
|
|
|
|
|
case NOERR : saved = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case _isreinsert: break;
|
|
|
|
|
default : saved = !yesno_box("Errore %d nell'aggiornamento statistiche:"
|
|
|
|
|
"Si desidera ritentare?", err);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
1997-08-05 09:24:21 +00:00
|
|
|
|
}
|
1997-08-18 14:20:21 +00:00
|
|
|
|
reset();
|
1997-08-05 09:24:21 +00:00
|
|
|
|
|
1997-08-18 14:20:21 +00:00
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
1997-08-26 13:40:34 +00:00
|
|
|
|
TStats_agg::TStats_agg() : _ditta(-1)
|
1997-08-18 14:20:21 +00:00
|
|
|
|
{
|
1997-08-05 09:24:21 +00:00
|
|
|
|
}
|
1997-09-19 10:17:17 +00:00
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Record del file svriep
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
1997-09-25 16:51:52 +00:00
|
|
|
|
TSVriep_record:: TSVriep_record(): TVariable_rectype(LF_SVRIEP)
|
1997-09-19 10:17:17 +00:00
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
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 ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Cache
|
|
|
|
|
///////////////////////////////////////////////////////////
|
1997-09-25 16:51:52 +00:00
|
|
|
|
#define RWCACHE_SIZE 100
|
1997-09-19 10:17:17 +00:00
|
|
|
|
|
|
|
|
|
// 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: <20> 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<67> <20> 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<63> sia "N"uovo; al flush corregger<65> 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<69> (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)
|
|
|
|
|
{
|
|
|
|
|
}
|