campo-sirio/sv/sv1200.cpp
guy 4acae88bb6 Migliorata gestione simboli speciali all'interno dei codici articolo (prima venivano filtrate solo le descrizioni)
git-svn-id: svn://10.65.10.50/branches/R_10_00@22897 c028cbd2-c16b-5b4b-a496-9718f37d4682
2013-09-11 09:51:51 +00:00

2772 lines
77 KiB
C++
Executable File
Raw Blame History

#include <currency.h>
#include <fraction.h>
#include <mask.h>
#include <msksheet.h>
#include <printapp.h>
#include <progind.h>
#include <tabutil.h>
#include "sv1.h"
#include "sv1200a.h"
#include "sv1200b.h"
#include "sv1200c.h"
#include "svlib01.h"
#include "svriep.h"
#include "svstat.h"
#include "../mg/anamag.h"
#include "../mg/mglib.h"
#include "../mg/umart.h"
#include "../pr/agenti.h"
#include "../ve/clifor.h"
#define STR_TOTGEN "T"
#define STR_TIPODOC "D"
#define STR_UMISURA "U"
#define STR_ARTICOLO "A"
#define STR_LIVGIAC "L"
#define STR_CATVEN "V"
#define STR_CLIFOR "C"
#define STR_CLIFIELD "H"
#define STR_AGENTE "G"
#define STR_MAGAZZ "M"
#define STR_ZONA "Z"
#define STR_ARTFIELD "B"
#define CHR_TOTGEN 'T'
#define CHR_TIPODOC 'D'
#define CHR_UMISURA 'U'
#define CHR_ARTICOLO 'A'
#define CHR_LIVGIAC 'L'
#define CHR_CATVEN 'V'
#define CHR_CLIFOR 'C'
#define CHR_CLI 'C'
#define CHR_CLIFIELD 'H'
#define CHR_FOR 'F'
#define CHR_AGENTE 'G'
#define CHR_MAGAZZ 'M'
#define CHR_ZONA 'Z'
#define CHR_ARTFIELD 'B'
#define COMP_AS_VALUE 'V'
#define COMP_AS_DIFF 'D'
#define COMP_AS_PERC 'P'
#define COLONNA_VALORE "V"
#define COLONNA_QTA "Q"
#define COLONNA_ENTRAMBI "E"
#define ALG_VALORI 'V'
#define ALG_PROGRESSIVI 'P'
#define ALG_MOBILI 'M'
#define LARG_COLCODICE 49
#define POS_PRIMACOL 51
#define PICTURE_VALORI "#.###.###.##@"
#define LARG_COLVAL 14
#define PICTURE_QUANTITA "#.###.##@,@##"
#define LARG_COLQTA 14
#define PICTURE_PERCENT "###@,@"
#define LARG_COLPERC 8
#define FORMWIDTH 150
#define DEFAULT_OUTFILE "outstat0"
///////////////////////////////////////////////////////////
// Utility
///////////////////////////////////////////////////////////
const char* safe_string(const TString& str)
{
TString256 tmp = str;
tmp.replace('#', '=');
tmp.replace('$', 'S');
tmp.replace('%', '/');
tmp.replace('@', 'a');
tmp.replace('&', 'e');
if (tmp != str)
return get_tmp_string() = tmp;
return str;
}
///////////////////////////////////////////////////////////
// TPeriodo
///////////////////////////////////////////////////////////
class TPeriodo : public TSortable
{
static TFrequenza_statistiche _frequenza;
int _anno;
int _periodo;
protected:
virtual int compare(const TSortable& s) const;
void set(const TPeriodo& ap) { set(ap._anno, ap._periodo); }
public:
static void set_frequency(TFrequenza_statistiche f)
{ CHECK(f != fs_nulla, "Frequenza nulla"); _frequenza = f; }
static TFrequenza_statistiche frequency() { return _frequenza; }
int operator -(const TPeriodo& ap) const;
int difference(const TPeriodo& p, TFrequenza_statistiche freq) const;
const TPeriodo& operator +=(int n);
const TPeriodo& sum(int n, TFrequenza_statistiche freq);
TDate first_day() const;
TDate last_day() const;
void set_year(int y);
void set_period(int p);
void set(int y, int p) { set_year(y); set_period(p); }
void set(const TDate& d);
const TPeriodo& operator=(const TPeriodo& ap) { set(ap); return ap; }
const TPeriodo& operator=(const TDate& d) { set(d); return *this; }
TPeriodo() : _anno(1900), _periodo(1) { }
TPeriodo(int anno, int periodo) { set(anno, periodo); }
TPeriodo(const TDate& d) { set(d); }
TPeriodo(const TPeriodo& ap) { set(ap); }
virtual ~TPeriodo() { }
};
TFrequenza_statistiche TPeriodo::_frequenza = fs_nulla;
int TPeriodo::compare(const TSortable& s) const
{
const TPeriodo& ap = (const TPeriodo&)s;
int diff = _anno - ap._anno;
if (diff == 0)
diff = _periodo - ap._periodo;
return diff;
}
int TPeriodo::operator -(const TPeriodo& ap) const
{
int result = 0;
int annomin, periodomin, annomax, periodomax;
const bool swapped = compare(ap) < 0;
if (swapped)
{
annomin = _anno;
periodomin = _periodo;
annomax = ap._anno;
periodomax = ap._periodo;
}
else
{
annomin = ap._anno;
periodomin = ap._periodo;
annomax = _anno;
periodomax = _periodo;
}
if (annomin < annomax)
{
result += last_period(annomin, _frequenza) - periodomin + 1;
for (annomin++; annomin < annomax; annomin++)
result += last_period(annomin, _frequenza);
periodomin = 1;
}
result += periodomax - periodomin;
return swapped ? -result : result;
}
int TPeriodo::difference(const TPeriodo& p, TFrequenza_statistiche freq) const
{
CHECK(freq > _frequenza, "Incomputable difference");
const TDate d1 = first_day();
const TDate d2 = p.first_day();
const TFrequenza_statistiche old_freq = _frequenza;
_frequenza = freq;
const TPeriodo p1(d1);
const TPeriodo p2(d2);
const int diff = p1 - p2;
_frequenza = old_freq;
return diff;
}
const TPeriodo& TPeriodo::operator +=(int n)
{
// Sembra orrendo ma per ora e' modo piu' sicuro!
if (n >= 0)
{
int lp = last_period(_anno, _frequenza);
for (int i = n; i > 0; i--)
{
_periodo++;
if (_periodo > lp)
{
_anno++;
_periodo = 1;
lp = last_period(_anno, _frequenza);
}
}
}
else
{
for (int i = n; i < 0; i++)
{
_periodo--;
if (_periodo <= 0)
{
_anno--;
_periodo = last_period(_anno, _frequenza);
}
}
}
return *this;
}
const TPeriodo& TPeriodo::sum(int n, TFrequenza_statistiche freq)
{
CHECK(freq > _frequenza, "Incomputable sum");
TDate d = first_day();
const TFrequenza_statistiche old_freq = _frequenza;
_frequenza = freq;
TPeriodo p1(d);
p1 += n;
d = p1.first_day();
_frequenza = old_freq;
set(d);
return *this;
}
TDate TPeriodo::first_day() const
{
TDate d(1, 1, _anno);
switch(_frequenza)
{
case fs_annuale : break;
case fs_semestrale : if (_periodo > 1) d.set_month(7); break;
case fs_quadrimestrale: d.set_month((_periodo - 1) * 4 + 1); break;
case fs_trimestrale : d.set_month((_periodo - 1) * 3 + 1); break;
case fs_bimestrale : d.set_month((_periodo - 1) * 2 + 1); break;
case fs_mensile : d.set_month(_periodo); break;
case fs_quindicinale : d.set_month((_periodo - 1) / 2 + 1);
if ((_periodo & 0x1) == 0) d.set_day(16);
break;
case fs_settimanale : d += 7 * (_periodo - 1); break;
case fs_giornaliera : d += _periodo - 1;
}
return d;
}
TDate TPeriodo::last_day() const
{
TDate d = first_day();
ceil(d, _frequenza);
return d;
}
void TPeriodo::set_year(int y)
{
CHECKD(y >= 1900 && y < 3000, "Bad year ", y);
_anno = y;
}
void TPeriodo::set_period(int p)
{
CHECKD(p > 0 && p <= last_period(_anno, _frequenza), "Bad period ", p);
_periodo = p;
}
void TPeriodo::set(const TDate& d)
{
set(d.year(), date2period(d, _frequenza));
}
///////////////////////////////////////////////////////////
// TFrequenza_colonne
///////////////////////////////////////////////////////////
class TFrequenza_colonne : public TObject
{
TFrequenza_statistiche _frequenza;
int _multiplo;
TPeriodo _periodo_inizio;
TDate _data_inizio;
public:
void init(TFrequenza_statistiche f, int m, const TDate& d);
int period2column(const TPeriodo& p) const;
int date2column(const TDate& d) const;
TDate column_first_day(int n) const;
TDate column_last_day(int n) const;
const TPeriodo& inizio() const { return _periodo_inizio; }
};
void TFrequenza_colonne::init(TFrequenza_statistiche f, int m, const TDate& d)
{
// _frequenza = (f == fs_nulla || m <= 0) ? TPeriodo::frequency() : f;
_frequenza = (f == fs_nulla || m >0) ? TPeriodo::frequency() : f;
_multiplo = (m <= 0) ? divide(_frequenza, TPeriodo::frequency()) : m;
_periodo_inizio = d;
_data_inizio = _periodo_inizio.first_day();
}
int TFrequenza_colonne::period2column(const TPeriodo& p) const
{
int result;
if (_multiplo > 0)
{
int diff = p - _periodo_inizio;
result = diff / _multiplo;
// Corregge arrotondamento per periodi inferiori a _periodo_inizio
// ad esempio: -1 / 12 = 0 e non -1 (risultato corretto)
if (diff < 0 && ((diff % _multiplo) != 0))
result--;
}
else
result = p.difference(_periodo_inizio, _frequenza);
return result;
}
int TFrequenza_colonne::date2column(const TDate& d) const
{
const TPeriodo p(d);
return period2column(p);
}
TDate TFrequenza_colonne::column_first_day(int n) const
{
TPeriodo p(_periodo_inizio);
if (_multiplo > 0)
p += n * _multiplo;
else
p.sum(n, _frequenza);
TDate d = p.first_day();
return d;
}
TDate TFrequenza_colonne::column_last_day(int n) const
{
TDate d = column_first_day(n+1);
--d;
return d;
}
///////////////////////////////////////////////////////////
// Stampa statistiche
///////////////////////////////////////////////////////////
class TStampa_stat : public TPrint_application
{
enum { MAX_ROWS = 8 }; // numero massimo di raggruppamenti
enum { LINEA_DATI='D', LINEA_RAFFRONTI='R', LINEA_TARGET='T'}; // codici per le righe
TMask * _msk, *_print_msk,*_export_msk;
TStats_agg _stats;
TFrequenza_colonne _freq;
TCodart_livelli* _liv_art;
TCodgiac_livelli* _liv_giac;
TRecord_cache *_tipodoc,*_catven, *_umart;
TToken_string _key;
TString _last_key;
TRectype * _last_data;
TString_array _des_fld;
TString_array _file_fld;
TString_array _key_fld;
TString_array _field_fld;
bool _ragg_per_um;
// ******************
// costruzione file di Output
TStat_cache * _svcache; // cache R/W per le statistiche
int _last_lev_grp, // livello dell'ultimo raggruppamento incontrato
_liv_riga; // livello della riga
TArray _group_recs; // array dei record dei raggruppamenti
TArray _group_recs_raff; // array dei record dei raggruppamenti (raffronti)
int _indent[MAX_ROWS];// array delle posizione di indentazione
real _totval_riga[SVS_NUMCOLONNE]; //array dei totali degli "anni" della riga
real _totqta_riga[SVS_NUMCOLONNE]; //array dei totali degli "anni" della riga
int _colpage, // numero di pagina ripetuta per contenere in larghezza tutte le colonne
_last_page; // ultima pagina della "prima copia"
int _larg[7];
int _largcol, // larghezza di una colonna
_numcol_dati, // numero di colonne contenenti dati
_numcol, // numero totale di colonne (dati+totali)
_pagewidth, // larghezza di una pagina
_col_anno ; // numero di colonne che formano un "Anno" (=periodo di rif.)
bool _st_totr; // flag stampa totali di riga
bool _st_totc; // flag stampa totali di colonna
bool _st_tota; // flag stampa totali di "anno"
bool _st_val; // Stampa valori
bool _st_qta; // Stampa quantita'
bool _st_um; // Stampa UM
bool _st_uni; // Stampa valori/quantita'
TString16 _valid_types;// Stringa contenente i tipi di riga da stampare
// ******************
// stampa file di Output
TString _wrk_row, _save_code; // stringhe di lavoro per le righe di stampa
TRelation * _rel; // relazione per la stampa
private:
void put_column(TRectype & statrec,int col, const TSVriep_record& curr);
const real fc_um(const TRectype& statrec,const TSVriep_record& rieprec);
void invalid_columns(TRectype & statrec);
void standardize_um(TSVriep_record& rieprec, bool force=FALSE);
// generazione del file di output
void set_ragg_per_um();
bool filtro_chiavi(TSVriep_record &curr);
void update_file(const char * key, const char * code,const char tipo, const int level, const int col, TSVriep_record& curr, const TString & fld, int row);
void genera_file(const char *outfn);
// handler per i campi di maschera
static bool chiave_notify(TSheet_field& f, int r, KEY k);
static bool chiave_handler(TMask_field& f, KEY k);
static bool campo_handler(TMask_field& f, KEY k);
static bool artfld_handler(TMask_field& f, KEY k);
static bool filename_handler(TMask_field& f, KEY k);
static bool codice_handler(TMask_field& f, KEY k);
static bool multiplo_handler(TMask_field& f, KEY k);
static bool numero_handler(TMask_field& f, KEY k);
static bool periodo_handler(TMask_field& f, KEY k);
static bool dataini_handler(TMask_field& f, KEY k);
static bool datafin_handler(TMask_field& f, KEY k);
static bool raffronto_handler(TMask_field& f, KEY k);
static bool dataraf_handler(TMask_field& f, KEY k);
protected:
virtual bool user_create();
virtual bool user_destroy();
virtual bool set_print(int i);
virtual void set_page(int file, int count);
virtual bool preprocess_print(int file, int counter) ;
virtual print_action postprocess_print(int file, int counter);
virtual bool preprocess_page(int file, int counter);
virtual print_action postprocess_page(int file, int counter);
virtual void preprocess_header();
virtual void preprocess_footer();
virtual void on_config_change();
void set_descr(int& row);
int handle_levchange(int row,const int level);
int set_rows_colonne(int row, const TRectype &strec);
void set_row_atpos(char section,int row,const char * f,int pos);
void set_filled_row(char section,int row,char c,int pos, int len);
void reset_grplevels();
bool test_field(const TString& cod, TMask_field& f) const;
void set_printmask();
void fill_field_list(TMask& m);
void set_frequency();
bool set_column_frequency();
bool recalc_period();
TString& build_key(const TRectype& rec);
const TString& nome_colonna1(int c, TString& nome);
const TString& nome_colonna2(int c, TString& nome);
const TString& nome_totale(int t, TString& nome);
const TString& partkey_name(const char *lev_code, int row, TString& park) const;
const TString& get_part(TString & lev_code, TSVriep_record & rieprec, const TString & fld); // const;
const TString& get_descrpart(const char *lev_code, TSVriep_record &rieprec, const TString & fld, int row);
void adjust_record(TRectype &strec, int from) const;
int numlevels() const { return selmask().sfield(F_CHIAVE).items(); }
public:
TMask& selmask() const { return *_msk; }
TMask& printmask() const { return *_print_msk; }
TMask& expmask() const { return *_export_msk; }
virtual bool menu(MENU_TAG);
};
inline TStampa_stat& app() { return (TStampa_stat&)main_app(); }
print_action TStampa_stat::postprocess_print(int file, int count)
{
reset_footer();
reset_header();
_last_page=get_page_number();
_colpage++;
//printer().formfeed();
return TPrint_application::postprocess_print(file,count);
}
bool TStampa_stat::preprocess_page(int file, int count)
{
return TPrint_application::preprocess_page(file,count);
}
print_action TStampa_stat::postprocess_page(int file, int count)
{
reset_print();
return TPrint_application::postprocess_page(file,count);
}
bool TStampa_stat::set_print(int i)
{
if (printmask().run() == K_QUIT)
return FALSE;
_st_totr=printmask().get_bool(F_STTOTALIRIGA);
_st_totc=printmask().get_bool(F_STTOTALICOL);
_st_tota=printmask().get_bool(F_STTOTALIANNO);
_largcol = 0;
for (int l = 0; l < 7; l++)
_larg[l] = 0;
if (_st_val)
{
_largcol += LARG_COLVAL;
_larg[0] = LARG_COLVAL;
if (printmask().get_bool(F_STRAFFRONTO))
{
switch (printmask().get(F_TIPORAFFRONTO)[0])
{
case COMP_AS_DIFF:
_largcol += LARG_COLVAL;
_larg[1] = LARG_COLVAL;
break;
case COMP_AS_PERC:
_largcol += LARG_COLPERC;
_larg[1] = LARG_COLPERC;
break;
case COMP_AS_VALUE:
default:
break;
}
}
if (_st_totr)
{
_largcol += LARG_COLPERC;
_larg[2] = LARG_COLPERC;
}
}
if (_st_qta)
{
_largcol += LARG_COLQTA;
_larg[3] = LARG_COLVAL;
if (printmask().get_bool(F_STRAFFRONTO))
{
switch (printmask().get(F_TIPORAFFRONTO)[0])
{
case COMP_AS_DIFF:
_largcol += LARG_COLVAL;
_larg[4] = LARG_COLVAL;
break;
case COMP_AS_PERC:
_largcol += LARG_COLPERC;
_larg[4] = LARG_COLPERC;
break;
case COMP_AS_VALUE:
default:
break;
}
}
if (_st_totr)
{
_largcol += LARG_COLPERC;
_larg[5] = LARG_COLPERC;
}
}
if (_st_uni)
{
_largcol += LARG_COLVAL;
_larg[6] = LARG_COLVAL;
}
if (_largcol <= 0)
_largcol = 1;
_numcol_dati = selmask().get_int(F_PERIODO);
_col_anno =min(_numcol_dati,printmask().get_int(F_COLANNO)); //numero di colonne che formano un "Anno"
if (_col_anno <= 0) _col_anno = 12; // ???
_numcol = _numcol_dati+ (_st_tota ? int((_numcol_dati -1)/_col_anno+1) : 0);
_pagewidth=POS_PRIMACOL+int((printer().calc_num_cols()-POS_PRIMACOL)/_largcol)*_largcol;
while (_pagewidth > 256)
_pagewidth -= _largcol;
// reset delle variabili per la gestione di gruppi ai vari livelli
_colpage=1;
_last_page=0;
reset_grplevels();
// setta header e footer
int row=0;
// resetta _save_code per stampare linee raffronti nel caso non abbiano la corrispondente linea dati
_save_code = "";
reset_header();
reset_footer();
printer().footerlen(3);
return TRUE;
}
bool TStampa_stat::preprocess_print(int file, int counter)
{
return TRUE;
}
void TStampa_stat::preprocess_footer()
{
set_filled_row('F',1,'_',0,_pagewidth);
_wrk_row.format(FR("Pagina @#"),get_page_number()-_last_page*(_colpage-1));
set_row_atpos('F',2,_wrk_row,(_colpage-1)*_pagewidth+(_pagewidth-9)/2);
}
void TStampa_stat::preprocess_header()
{
int bkg=0,col=0,row=0,lastrow;
// *****************
// header
set_header(++row,"");
set_header(++row,"");
if (selmask().get(F_DESCR).empty())
set_row_atpos('H',++row,FR("@bStampa statistiche "),0);
else
{
_wrk_row.format("@b%s",(const char *)selmask().get(F_DESCR));
set_row_atpos('H',++row,(const char *)_wrk_row,0);
_wrk_row.format(FR("dal %s al %s "),(const char *)selmask().get(F_DATAINI),(const char *)selmask().get(F_DATAFIN));
set_row_atpos('H',row,(const char *)_wrk_row,51);
if (printmask().get_bool(F_STRAFFRONTO ))
{
_wrk_row.format(FR("confrontata con i corrispondenti periodi a partire dal %s"),(const char *)selmask().get(F_DATARAF));
set_row_atpos('H',++row,(const char *)_wrk_row,0);
}
}
set_header(++row,"");
set_row_atpos('H',++row,FR(" Codice @23gDescrizione"),0);
lastrow=row;
for (int c=0; c < _numcol; c++) // colonne
{
if (_st_tota && c && (((c+1)%(_col_anno+1))==0 || c==_numcol-1) )
{
nome_totale(1+int((c-1)/_col_anno), _wrk_row);
set_row_atpos('H',row,_wrk_row,POS_PRIMACOL+c*_largcol+_largcol/2 );
}
else
{
TString col1, col2;
int pos = POS_PRIMACOL+c*_largcol;
nome_colonna1(col, col1);
nome_colonna2(col, col2);
col1 << ' ' << col2;
const int l = col1.len();
TParagraph_string s(col1, _largcol);
col1 = s.get();
col1.center_just(_largcol);
set_row_atpos('H', row, col1, pos);
col2 = s.get();
if (col2.empty())
lastrow = row + 1;
else
{
col2.center_just(_largcol);
set_row_atpos('H', row + 1, col2, pos);
lastrow = row + 2;
}
if (_st_val)
{
pos += _larg[0];
set_row_atpos('H',lastrow,TR("Valore"), pos - 7);
if (printmask().get_bool(F_STRAFFRONTO))
{
pos += _larg[1];
switch (printmask().get(F_TIPORAFFRONTO)[0])
{
case COMP_AS_DIFF:
set_row_atpos('H',lastrow,TR("Differenza"), pos - 11);
break;
case COMP_AS_PERC:
set_row_atpos('H',lastrow,TR("%%Diff"), pos - 7);
break;
case COMP_AS_VALUE:
default:
break;
}
}
if (_st_totr)
{
set_row_atpos('H', lastrow, TR("Perc."), pos);
pos += _larg[2];
}
}
if (_st_qta)
{
pos += _larg[3];
set_row_atpos('H',lastrow,TR("Quantita'"),pos - 12);
if (printmask().get_bool(F_STRAFFRONTO))
{
pos += _larg[4];
switch (printmask().get(F_TIPORAFFRONTO)[0])
{
case COMP_AS_DIFF:
set_row_atpos('H',lastrow,TR("Differenza"), pos - 13);
break;
case COMP_AS_PERC:
set_row_atpos('H',lastrow,TR("%%Diff"), pos - 7);
break;
case COMP_AS_VALUE:
default:
break;
}
}
if (_st_totr)
{
set_row_atpos('H', lastrow, TR("Perc."), pos);
pos += _larg[5];
}
}
if (_st_uni)
set_row_atpos('H',lastrow,TR("Valore medio"), pos + _larg[6] - 12);
col++;
}
}
row=lastrow;
set_header(++row,"");
// *****************
// background
const int lasthline=(printmask().get_bool(F_STRAFFRONTO )? 5 :4);
_wrk_row.format("PnW1l(1,2,%d,2)l(1,%d,%d,%d)l(1,%d,%d,%d)",_pagewidth,lasthline,_pagewidth,lasthline,row,_pagewidth,row);
row++;
set_background(_wrk_row);
}
const TString& TStampa_stat::nome_colonna1(int c, TString& s_park)
{
const char code_freq=selmask().get(F_MULTIPLO)[0];
const TFrequenza_statistiche freq = char2frequency(code_freq);
const TFrequenza_statistiche maskfreq = char2frequency(selmask().get(F_FREQUENZA)[0]);
const int numero=selmask().get_int(F_NUMERO); // numero di periodi in una col
const TDate din=selmask().get(F_DATAINI); // data iniziale
const int start=date2period(din,freq); // periodo della prima colonna
const int lastp=last_period(din,freq); // numero di periodi in un anno
if (freq == maskfreq && numero > 1 && maskfreq != fs_giornaliera)
{
// numerico; pu<70> essere un qualsiasi multiplo della freq
s_park.format("%s %d<>%d",(const char *)char2freqname(code_freq),1+(start+c*numero-1)%lastp , 1+(start+(c+1)*numero-2)%lastp);
}
else
{
if (freq == maskfreq && maskfreq == fs_giornaliera && numero>1)
{
// Le date vanno da qualsiasi giorno a qualsiasi giorno
TDate dfrom(app()._freq.column_first_day(c));
s_park.format("Dal %s",(const char *)dfrom.string());
}
else
switch (freq)
{
case fs_giornaliera:
{
TDate d = din; d += c*numero;
s_park.format("%s",(const char*)itow(d.wday()));
}
break;
case fs_settimanale:
case fs_quindicinale:
case fs_bimestrale:
case fs_trimestrale:
case fs_quadrimestrale:
case fs_semestrale:
s_park.format("%d^%s",1+(start+c-1)%lastp,(const char *)char2freqname(code_freq));
break;
case fs_annuale:
s_park.format(FR("Anno %d"),din.year()+start+c-1);
break;
case fs_mensile:
s_park.format("%s",itom(start+c) );
break;
}
}
// s_park.center_just(_largcol);
return s_park;
}
const TString& TStampa_stat::nome_colonna2(int c, TString& s_park)
{
const TDate din=selmask().get(F_DATAINI); // data iniziale
const char code_freq=selmask().get(F_MULTIPLO)[0];
const int numero=selmask().get_int(F_NUMERO); // numero di periodi in una col
const TFrequenza_statistiche freq = char2frequency(code_freq);
const TFrequenza_statistiche maskfreq = char2frequency(selmask().get(F_FREQUENZA)[0]);
const int lastp=last_period(din,freq); // numero di periodi in un anno
const int start=date2period(din,freq); // periodo della prima colonna
s_park.cut(0);
if (freq == maskfreq && numero > 1 && maskfreq==fs_giornaliera)
{
const TDate dto = app()._freq.column_last_day(c);
s_park.format(FR("Al %s"),(const char *)dto.string());
}
else
{
switch (freq)
{
case fs_giornaliera:
{
TDate d = din; d += c*numero;
s_park.format("%s",(const char *)d.string());
}
break;
case fs_mensile:
s_park.format("%d",din.year()+int((start+c-1)/lastp));
break;
case fs_settimanale:
case fs_quindicinale:
case fs_bimestrale:
case fs_trimestrale:
case fs_quadrimestrale:
case fs_semestrale:
s_park.format(FR(" anno %d"),din.year()+int((start+c-1)/lastp));
break;
default:
break;
}
}
return s_park;
}
const TString& TStampa_stat::nome_totale(int c, TString& s_park)
{
const char code_freq=selmask().get(F_MULTIPLO)[0];
s_park.cut(0);
{
switch (code_freq)
{
case fs_giornaliera: // giorno
case fs_settimanale:
case fs_quindicinale:
case fs_mensile:
case fs_bimestrale:
case fs_trimestrale:
case fs_quadrimestrale:
case fs_semestrale:
case fs_annuale:
default:
s_park.format(FR("Totale %d"),c);
}
}
return s_park;
}
void TStampa_stat::set_descr(int& row)
{
const int MAX_DESC_LEN = 27;
TRectype& strec = current_cursor()->curr();
TParagraph_string descr("",MAX_DESC_LEN); // Spezzatura manuale, per evitare righe accavallate
TString r(255);
const int lastlev = numlevels();
const int level = strec.get_int(SVS_LIVELLO);
int lencode = 0;
if (_group_recs.objptr(level+1))
{
const TRectype& rec_grp= (const TRectype&)_group_recs[level+1];
lencode = rec_grp.get(SVS_CODICE).len();
}
adjust_record(strec,lencode);
partkey_name(strec.get(SVS_LEVCODE), lastlev - level - 1, r);
r.upper(0,0);
if (r.blank())
r.cut(0);
else
r << ' ';
r << safe_string(strec.get(SVS_CODICE).mid(lencode));
descr = safe_string(strec.get(SVS_DESCR));
if (descr.full())
r << "@23g" << descr.get(0);
set_row_atpos('R',++row,(const char *)r,_indent[level]);
// Seconda riga eventuale...
const int items = descr.items();
if (items > 1)
{
r = descr.get(1);
// Sfrutta al massimo la seconda riga, mettendo anche il terzo elemento
// e cmq trimmando al 25o carattere
if (items > 2) // Guy: come pu<70> succedere visto che TParagraph_string descr("", MAX_DESC_LEN)
{
r << ' ' << descr.get(2);
r.cut(MAX_DESC_LEN);
}
r.insert("@23g");
set_row_atpos('R',++row, (const char*)r,_indent[level]);
}
}
void TStampa_stat::set_page(int file, int count)
{
// prepara la pagina di stampa
TRectype& strec = current_cursor()->curr();
const int level = strec.get_int(SVS_LIVELLO);
const int lastlev = numlevels();
int row=0;
// *****************
// gestione totali di raggruppamento
row = handle_levchange(row, level);
const char tipo_riga = *strec.get(SVS_TIPO);
if (level > 0)
{
// salva i record dei livelli di raggruppamento
if (level == lastlev)
strec.zero(SVS_CODICE);
switch (tipo_riga)
{
case LINEA_DATI:
_group_recs.add(strec,level);
break;
case LINEA_RAFFRONTI:
_group_recs_raff.add(strec,level);
break;
default:
break;
}
}
// *****************
// gestione delle "righe"
if (level != lastlev &&
printmask().get_bool(F_FLAGSTOTALI+lastlev-level))
{
switch (tipo_riga)
{
case LINEA_DATI:
if (level >= _liv_riga)
{
_save_code = strec.get(SVS_CODICE);
set_descr(row);
}
if (level == _liv_riga)
row = set_rows_colonne(row, strec);
break;
case LINEA_RAFFRONTI:
if (printmask().get_bool(F_STRAFFRONTO))
{
const TString& codice = strec.get(SVS_CODICE);
if (_save_code != codice)
{
TRectype stempty(LF_SVSTAT);
stempty.put(SVS_CODICE, codice);
stempty.put(SVS_LEVCODE,strec.get(SVS_LEVCODE));
stempty.put(SVS_LIVELLO,strec.get(SVS_LIVELLO));
stempty.put(SVS_TIPO,strec.get(SVS_TIPO));
set_descr(row);
row = set_rows_colonne(row, stempty);
}
if (level == _liv_riga)
row = set_rows_colonne(++row, strec);
}
break;
default:
break;
}
}
// *****************
// totale generale e break di livello
if (current_cursor()->pos() == current_cursor()->items()-1)
{
handle_levchange(row, numlevels());
}
}
// fa le set row per la "riga" contenente i valori delle colonne di statistica
int TStampa_stat::set_rows_colonne(int row, const TRectype &strec)
{
TRectype &last_data = *_last_data;
TString16 colname;
TString r_totc;
real col_value;
bool aggiungi_perc=TRUE;
int col=0; // contatore di colonna corrente
int position; // posizione fisica della colonna corrente
// **********
// setta i totali di riga
if (strec.get_char(SVS_TIPO)==LINEA_DATI ||
strec.get_char(SVS_TIPO)==LINEA_RAFFRONTI &&
printmask().get(F_TIPORAFFRONTO)[0]==COMP_AS_VALUE)
{
for (col = 0; col < _numcol_dati; col++)
{
colname.format("%c%d", SVS_VALCOLNAME, col);
const int idx = int(col/_col_anno);
if (col%_col_anno == 0)
_totval_riga[idx] = _totqta_riga[idx] = ZERO;
_totval_riga[idx] += strec.get_real(colname);
colname.format("%c%d", SVS_QTACOLNAME, col);
_totqta_riga[idx] += strec.get_real(colname);
}
}
// **********
// setta le colonne
TString pictures[3];
TCurrency currency;
for (int t = 0; t < 3; t++)
{
TString& pic = pictures[t];
if (t == 1)
{
pic = PICTURE_QUANTITA;
continue;
}
currency.set_price(t == 2);
const int dec = currency.decimals();
pic = PICTURE_VALORI;
if (dec > 0)
{
pic << ',';
for (int d = 0; d < dec; d++) pic << '@';
if (pic.len() > LARG_COLVAL)
{
pic.ltrim(pic.len() - LARG_COLVAL);
if (pic[0] == '.') pic[0] = '#';
}
}
}
col = 0;
for (int c = 0; c < _numcol_dati; c++)
{
const int idx = int(c / _col_anno);
position = POS_PRIMACOL + col*_largcol;
for (int t = 0; t < 3; t++) // Ciclo su valore, quantita' e unitario
{
if (t == 0 && !_st_val)
continue;
if (t == 1 && !_st_qta)
continue;
if (t == 2 && !_st_uni)
continue;
const real& tot_riga = t == 1 ? _totqta_riga[idx] : _totval_riga[idx];
colname.format("%c%d", t == 1 ? SVS_QTACOLNAME : SVS_VALCOLNAME, c);
const TString& PICT = pictures[t];
real colval = strec.get_real(colname);
if (t == 2)
{
colname.format("%c%d", SVS_QTACOLNAME, c);
const fraction valun(colval, strec.get_real(colname));
colval = valun;
}
TString80 colstr = colval.string(PICT);
if (t == 1 && _st_um)
{
TString4 um;
um << " ";
um << strec.get("UMQTA");
colstr.overwrite(um, 0);
}
int offset = (t - 1) * 3;
if (offset >= 0)
position += _larg[offset + 0] + _larg[offset + 1] + _larg[offset + 2];
offset += 3;
switch (strec.get_char(SVS_TIPO))
{
case LINEA_DATI:
last_data=strec;
set_row_atpos('R',row,colstr,position);
break;
case LINEA_RAFFRONTI:
switch (printmask().get(F_TIPORAFFRONTO)[0])
{
case COMP_AS_VALUE:
set_row_atpos('R',row, colstr,position);
break;
case COMP_AS_DIFF:
if (t < 2)
{
set_row_atpos('R',row, colstr,position);
set_row_atpos('R',row,((real)(last_data.get_real(colname)-strec.get_real(colname))).string(PICT),position + _larg[offset]);
}
break;
case COMP_AS_PERC:
if (t < 2)
{
set_row_atpos('R', row, colstr, position);
if (!colval.is_zero())
{
real p = CENTO * (last_data.get_real(colname) - colval) / colval; p.round(1);
set_row_atpos('R',row,p.string(PICTURE_PERCENT),position + _larg[offset] );
}
aggiungi_perc=FALSE;
}
break;
}
break;
case LINEA_TARGET: // v2.0
set_row_atpos('R',row,colstr,position);
break;
default:
break;
}
if (t < 2 && strec.get_char(SVS_TIPO) == LINEA_DATI)
{
// colonna con la percentuale rispetto al totale di riga
if (_st_totr && aggiungi_perc && !tot_riga.is_zero())
{
const int pos = position + _larg[offset] + _larg[offset + 1];
real p = CENTO * colval / tot_riga; p.round(1);
set_row_atpos('R',row,p.string(PICTURE_PERCENT),pos);
}
// riga con i totali di colonna
if (_st_totc && aggiungi_perc )
{
TRectype & _rec_totale=(TRectype &)_group_recs[numlevels()];
const real tot = _rec_totale.get_real(colname);
if (!tot.is_zero())
{
real p = CENTO * colval / tot; p.round(1);
r_totc = p.string(PICTURE_PERCENT);
set_row_atpos('R',row+1,(const char *)r_totc,position+_largcol-LARG_COLPERC);
}
else
set_row_atpos('R',row+1,"",0);
// aggiunge comunque una riga vuota per la spaziatura
}
// colonna con il totale di un "anno"
if (_st_tota && aggiungi_perc && (((c+1)%_col_anno)==0 || c== _numcol_dati-1))
{
col++;
int position_a = position + _largcol;
set_row_atpos('R',row,(const char *)tot_riga.string(PICT),position_a);
if (_st_totr && aggiungi_perc)
{
set_row_atpos('R',row,(const char *)real(100).string(PICTURE_PERCENT),position_a + _larg[offset]);
}
}
}
}
col++;
}
if (_st_totc)
++row;
return row;
}
void TStampa_stat::set_filled_row(char section,int row,char c,int pos,int len)
{
const int MAX=100; // limite massimo per una singola set_row; 5 char per costruire la goto
while (len> MAX )
{
_wrk_row.fill(c,MAX);
set_row_atpos(section,row,(const char *)_wrk_row,pos);
len-=MAX;
pos+=MAX;
}
_wrk_row.fill(c,len);
set_row_atpos(section,row,(const char *)_wrk_row,pos);
}
// fa le set_row per la "riga" contenente i valori delle colonne di statistica
void TStampa_stat::set_row_atpos(char section,int nrow,const char * f,int pos)
{
TString256 ss;
if (pos <= _colpage*_pagewidth)
{
int l = strlen(f);
const int firstpos=(_colpage-1)*_pagewidth;
if (pos+l >= firstpos)
{
// there's something to print in this page!
if (pos+l > _colpage*_pagewidth)
{
l=_colpage*_pagewidth-pos;
repeat_print();
}
ss.format("@%03dg",max(pos, firstpos ) % _pagewidth);
if (pos< firstpos)
ss.overwrite(f+firstpos-pos,5);
else
ss.overwrite(f,5);
ss.cut(5+l); // !?!? this cause trouble if special couples are used at the middle of the string:
// "@b" or "%%" can be split into two non-significant chars
}
//else : too much to the left: already printed!
}
else //: too much to the right: will be printed next time!
repeat_print();
switch (section)
{
case 'R': set_row(nrow,ss); break;
case 'H': set_header(nrow,ss); break;
case 'F': set_footer(nrow,ss); break;
default : break;
}
}
// stampa i totali ad ogni break di livello
int TStampa_stat::handle_levchange(int row, const int level)
{
while (level > _last_lev_grp)
{
// ho lasciato un livello "basso"
_last_lev_grp++;
if (_last_lev_grp > _liv_riga && printmask().get_bool(F_FLAGSTOTALI+numlevels()-_last_lev_grp)
|| _last_lev_grp==numlevels())
{
if (_group_recs.objptr(_last_lev_grp) == NULL)
{
NFCHECK("Totali inconsistenti");
}
else
{
TRectype& rec_grp1=(TRectype &)_group_recs[_last_lev_grp];
int lencode=0;
if (_last_lev_grp < numlevels())
{
TRectype & rec_grp2=(TRectype &)_group_recs[_last_lev_grp+1];
lencode=rec_grp2.get(SVS_CODICE).len();
}
adjust_record(rec_grp1,lencode);
set_filled_row('R',++row,'_',POS_PRIMACOL,_largcol * _numcol );
partkey_name(rec_grp1.get(SVS_LEVCODE), numlevels() - _last_lev_grp - 1, _wrk_row);
_wrk_row.insert(FR("@bTotale "), 0);
_wrk_row << ' ' << rec_grp1.get(SVS_CODICE).mid(lencode);
_wrk_row << ' ' << safe_string(rec_grp1.get(SVS_DESCR).left(23));
//_wrk_row.cut(LARG_COLCODICE); there are also @ chars!
set_row_atpos('R',++row,(const char*)_wrk_row,_indent[_last_lev_grp]);
row = set_rows_colonne(row, rec_grp1);
if (printmask().get_bool(F_STRAFFRONTO ))
{
TRectype& rec_grp_raff=(TRectype &)_group_recs_raff[_last_lev_grp];
if (_group_recs_raff.objptr(level+1))
{
const TRectype& rec_grp= (const TRectype&)_group_recs_raff[level+1];
lencode = rec_grp.get(SVS_CODICE).len();
}
adjust_record(rec_grp_raff,lencode);
row = set_rows_colonne(++row, rec_grp_raff);
}
}
}
}
if (_last_lev_grp != level)
_last_lev_grp = level;
return row;
}
void TStampa_stat::reset_grplevels()
{
_last_lev_grp = numlevels();
_liv_riga = _last_lev_grp+1;
_group_recs.destroy();
_group_recs_raff.destroy();
int pos=0;
for (int l = 0; l <= _last_lev_grp; l++)
{
if (printmask().get_bool(F_FLAGSTOTALI+l))
{
_liv_riga = _last_lev_grp-l;
_indent[_liv_riga] = pos*2;
pos++;
}
else
_indent[_last_lev_grp-l] = 0;
}
}
bool TStampa_stat::user_create()
{
// ************
// files: documenti e statistiche
open_files(LF_RIGHEDOC, LF_CONDV, LF_RCONDV, LF_ANAMAG, LF_SCONTI, LF_UMART, LF_TAB, LF_TABCOM, LF_CLIFO,
LF_CFVEN, LF_INDSP, LF_OCCAS, LF_MOVMAG, LF_RMOVMAG,LF_PROVV, 0);
open_files(LF_SVRIEP,LF_SVSTAT,LF_AGENTI, 0);
_stats.init();
if (_stats.frequency()==fs_nulla)
return error_box(TR("E' necessario impostare la frequenza statistica per la ditta"));
// ************
// maschere
_msk = new TMask("sv1200a");
_msk->set_handler(F_CODICE, codice_handler);
_msk->set_handler(F_MULTIPLO, multiplo_handler);
_msk->set_handler(F_NUMERO, numero_handler);
_msk->set_handler(F_PERIODO, periodo_handler);
_msk->set_handler(F_DATAINI, dataini_handler);
_msk->set_handler(F_DATAFIN, datafin_handler);
_msk->set_handler(F_RAFFRONTO, raffronto_handler);
_msk->set_handler(F_DATARAF, dataraf_handler);
_msk->set_handler(F_CHIAVE, chiave_handler);
TMask& sm = _msk->sfield(F_CHIAVE).sheet_mask();
sm.set_handler(S_CAMPO, campo_handler);
sm.set_handler(S_ARTFLD, artfld_handler);
_print_msk = new TMask("sv1200b");
_export_msk = new TMask("sv1200c");
_export_msk->set_handler(F_FILENAME, filename_handler);
// ************
// oggetti per la gestione delle parti del codice
_liv_art = new TCodart_livelli;
_liv_giac = new TCodgiac_livelli;
_tipodoc = new TRecord_cache("%TIP");
_catven = new TRecord_cache("CVE");
_umart = new TRecord_cache(LF_UMART, 2);
// _spp = new TTable("SPP");
// _prs = new TTable("PRS");
// ************
// cursore di stampa
add_file(LF_SVSTAT);
add_cursor(new TCursor(new TRelation(LF_SVSTAT)));
// cache per l'output
_svcache=NULL;
set_real_picture("");
_last_data = new TRectype(LF_SVSTAT);
return TRUE;
}
bool TStampa_stat::user_destroy()
{
// maschere
delete _msk;
delete _print_msk;
delete _export_msk;
// livelli di codice
delete _liv_art;
delete _liv_giac;
// cancella le cache
delete _tipodoc;
delete _catven;
delete _umart;
// cancella i files
delete _last_data;
delete current_cursor()->relation();
return TRUE;
}
bool TStampa_stat::menu(MENU_TAG )
{
TMask& m = selmask();
TSheet_field& sheet = m.sfield(F_CHIAVE);
TString tmp;
KEY k;
m.set(F_STAMPA_VAL, "X");
while ((k = m.run()) != K_QUIT)
{
_numcol_dati = m.get_int(F_PERIODO);
_st_val = m.get_bool(F_STAMPA_VAL);
_st_qta = m.get_bool(F_STAMPA_QTA);
_st_um = _st_qta && m.get_bool(F_STAMPA_UM);
_st_uni = m.get_bool(F_STAMPA_UNI);
_valid_types = "";
if (m.get_bool(F_TIPOART1))
_valid_types << RIGA_MERCE;
if (m.get_bool(F_TIPOART2))
_valid_types << RIGA_PRESTAZIONI;
if (m.get_bool(F_TIPOART3))
_valid_types << RIGA_SPESEDOC;
if (m.get_bool(F_TIPOART4))
_valid_types << RIGA_OMAGGI;
set_column_frequency();
_key.cut(0);
TSheet_field & s_chiave = selmask().sfield(F_CHIAVE);
TFilename des_file_name("sv1200.ini");
TConfig c(des_file_name, "Descriptions");
for (int r = 0; r < sheet.items(); r++)
{
tmp = sheet.row(r).get(0);
if (!tmp.blank())
_key.add(tmp);
const bool is_anamag = tmp == STR_ARTFIELD;
TRelation rel(is_anamag ? LF_ANAMAG : LF_CLIFO);
TRelation_description rd(rel);
if (tmp == STR_ARTFIELD || tmp == STR_CLIFIELD)
{
TString16 field(s_chiave.cell(r,s_chiave.cid2index(S_ARTFLD)));
if (c.exist(field,2))
{
TToken_string t(c.get(field, "Descriptions", 2));
_file_fld.add(t.get(), r);
_key_fld.add(t.get(), r);
_field_fld.add(t.get(), r);
}
if (c.exist(field,1))
_des_fld.add(c.get(field, "Descriptions", 1), r);
else
{
int pos = field.find('[');
TString16 sub;
if (pos > 0)
{
sub = field.mid(pos);
field.cut(pos);
}
TString des(rd.get_field_description(field));
des << sub;
_des_fld.add(des, r);
}
}
}
if (k == K_SAVE)
{
set_ragg_per_um();
TTable psv("PSV");
psv.put("CODTAB", m.get(F_CODICE));
if (psv.read() == NOERR)
expmask().set(F_FILENAME, psv.get("S3")); // File precaricato da PSV->S3
if (expmask().run()!=K_ESC)
{
TFilename fname(expmask().get(F_FILENAME));
fname.insert("%");
genera_file(fname);
}
} else {
TFilename fname("svs");
genera_file(fname);
TIsamtempfile * f = new TIsamtempfile(LF_SVSTAT,fname,FALSE,TRUE);
set_printmask();
current_cursor()->relation()->replace(f);
// Forza la ricostruzione del cursore...
current_cursor()->setfilter("CODICE>=\"A\"");
current_cursor()->setfilter("");
do_print(1);
current_cursor()->relation()->replace(new TLocalisamfile(LF_SVSTAT));
}
}
return FALSE;
}
void TStampa_stat::fill_field_list(TMask& m)
{
// opzioni per il tipo di dato
m.enable(F_TIPOART4, !_stats.omaggio_is_merce());
// opzioni per i campi della chiave
TSheet_field& s = m.sfield(F_CHIAVE);
TMask& sm = s.sheet_mask();
TString_array& list = sm.efield(S_CAMPO).sheet()->rows_array();
list.destroy();
TToken_string row(80);
TCodart_livelli& cal = *_liv_art;
bool is_articolo = FALSE;
int l;
for (l = 0; l <= cal.last_level(); l++)
{
if (l && !cal.enabled(l))
continue;
is_articolo = TRUE;
row = STR_ARTICOLO;
if (l) row << l;
row.add(TR("Codice articolo"));
if (l) row << '[' << l << ']';
list.add(row);
}
if (is_articolo)
{
row = STR_ARTFIELD;
row.add(TR("Campo dell'anagrafica articoli"));
list.add(row);
}
TCodgiac_livelli& cgl = *_liv_giac;
for (l = 0; l <= cgl.last_level(); l++)
{
if (l && !cgl.enabled(l))
continue;
row = STR_LIVGIAC;
if (l) row << l;
row.add(TR("Livello giacenza"));
if (l) row << '[' << l << ']';
list.add(row);
}
row = "D";
row.add(TR("Tipo documento"));
list.add(row);
row = "V";
row.add(TR("Categoria vendita"));
list.add(row);
row = "C";
row.add(TR("Codice cliente/fornitore"));
list.add(row);
row = STR_CLIFIELD;
row.add(TR("Campo dell'anagrafica clienti/fornitori"));
list.add(row);
row = "Z";
row.add(TR("Codice zona"));
list.add(row);
row = "G";
row.add(TR("Codice agente"));
list.add(row);
row = "M";
row.add(TR("Codice magazzino"));
list.add(row);
}
void TStampa_stat::set_frequency()
{
TPeriodo::set_frequency(_stats.frequency());
TMask& m = selmask();
char freq[2] = { frequency2char(_stats.frequency()), '\0' };
m.set(F_FREQUENZA, freq);
TList_field& multiplo = (TList_field&)m.field(F_MULTIPLO);
TToken_string codes(8), descr(80);
switch(_stats.frequency())
{
case fs_giornaliera : codes = "G|S|Q|1|2|3|4|6|A"; break;
case fs_settimanale : codes = "S|3|6|A"; break;
case fs_quindicinale : codes = "Q|1|2|3|4|6|A"; break;
case fs_mensile : codes = "1|2|3|4|6|A"; break;
case fs_bimestrale : codes = "2|4|6|A"; break;
case fs_trimestrale : codes = "3|6|A"; break;
case fs_quadrimestrale: codes = "4|A"; break;
case fs_semestrale : codes = "6|A"; break;
case fs_annuale : codes = "A"; break;
default :break;
}
for (const char* cod = codes.get(0); cod; cod = codes.get())
descr.add(char2freqname(cod[0]));
multiplo.replace_items(codes, descr);
if (_stats.frequency() == fs_settimanale)
{
if (m.focus_field().dlg() == F_MULTIPLO)
m.set_focus_field(F_NUMERO); // scappa dal campo
multiplo.reset();
multiplo.disable();
}
else
multiplo.enable();
// setta la durata dell'anno
//m.set(F_COL_ANNO, last_period(1992,_stats.frequency()));
}
void TStampa_stat::on_config_change()
{
_stats.init();
_liv_art->init();
_liv_giac->init();
set_frequency();
fill_field_list(*_msk);
}
bool TStampa_stat::set_column_frequency()
{
const TMask& m = selmask();
const TDate data_inizio = m.get(F_DATAINI);
bool ok = data_inizio.year() >= 1900;
if (ok)
{
const TFrequenza_statistiche multiplo = char2frequency(m.get(F_MULTIPLO)[0]);
const int numero = m.get_int(F_NUMERO);
_freq.init(multiplo, numero, data_inizio);
}
return ok;
}
TString& TStampa_stat::build_key(const TRectype& rec)
{
_last_key.cut(0);
TString16 tmp;
for (const char* field = _key.get(0); field; field = _key.get())
{
tmp = field;
switch(tmp[0])
{
case 'A':
if (tmp[1] > '0')
{
const int liv = tmp[1] - '0';
const int start = _liv_art->code_start(liv);
const int len = _liv_art->code_length(liv);
tmp = rec.get(SVR_CODART).mid(start, len);
_last_key << tmp;
}
else
_last_key << rec.get(SVR_CODART);
break;
default:
break;
}
}
return _last_key;
}
void TStampa_stat::update_file(const char * key, const char *lev_code,const char tipo_dato, const int level, const int col, TSVriep_record& curr, const TString & fld, int row)
{
CHECK(col>=0,"Le colonne partono da 0");
static TRectype* statrec = NULL;
if (statrec == NULL)
statrec = new TRectype(LF_SVSTAT);
TToken_string cachekey(key);
cachekey.rtrim(); // necessario perch<63> la chiave sia buona per l'hash table
if (cachekey.blank())
cachekey.add(" ");
cachekey.add(tipo_dato);
*statrec = _svcache->get(cachekey);
if (_svcache->io_result()!=NOERR)
{
// nuovo record;
statrec->put(SVS_CODICE,key);
statrec->put(SVS_LEVCODE,lev_code);
statrec->put(SVS_LIVELLO,level);
statrec->put(SVS_TIPO,tipo_dato);
statrec->put(SVS_UMQTA,curr.get(SVR_UMQTA));
}
if (*lev_code== CHR_TOTGEN) // totale generale
statrec->put(SVS_DESCR,"");
else
{
TString descr = safe_string(get_descrpart(lev_code,curr,fld, row));
if (descr.len() > SVS_LEN_DESCR)
descr.cut(SVS_LEN_DESCR);
statrec->put(SVS_DESCR, descr);
}
put_column(*statrec,col,curr);
_svcache->put(*statrec);
}
// aggiorna la colonna del record statrec con i dati di SVriep
void TStampa_stat::put_column(TRectype& statrec, int col, const TSVriep_record& rieprec)
{
if (col < 0 || col > SVS_NUMCOLONNE)
return;
if (_st_qta || _st_uni)
{
const TString16 um(rieprec.get(SVR_UMQTA));
if (um.not_empty())
{
const real fc = fc_um(statrec,rieprec);
if (fc.is_zero())
invalid_columns(statrec);
else
{
const real qta = rieprec.get_real(SVR_QUANTITA) * fc;
TString4 colname; colname.format("%c%d", SVS_QTACOLNAME, col);
statrec.add(colname, qta);
//statrec.put(SVS_TOTALERIGA,statrec.get_real(SVS_TOTALERIGA)+rieprec.get_real(SVR_QUANTITA)*fc);
}
} // no UM ? no valid data!
}
if (_st_val || _st_uni)
{
const real val = rieprec.get_real(SVR_VALORE);
TString4 colname; colname.format("%c%d", SVS_VALCOLNAME, col);
statrec.add(colname, val);
//statrec.put(SVS_TOTALERIGA, statrec.get_real(SVS_TOTALERIGA)+rieprec.get_real(SVR_VALORE));
}
}
// Converte le UM scrivendo la nuova UM sul record e restituendo il fattore di conv.
void TStampa_stat::standardize_um(TSVriep_record& rieprec, bool force)
{
if (force || _ragg_per_um)
{
TString4 um("N."); // Unita' di default NON valida!
real fc;
const char tipoart = rieprec.get_char(SVR_TIPOART);
if (tipoart==RIGA_MERCE || tipoart==RIGA_OMAGGI)
{
// <20> un articolo (<M>erce); converto alla UM principale dell'art.
TString key(rieprec.get(SVR_CODART));
key << "|1";
const TRectype& rec_umart = cache().get(LF_UMART, key);
um = rec_umart.get(UMART_UM);
fc = rec_umart.get_real(UMART_FC);
}
else
{
// non <20> un articolo: converte in base alla UM di riferimento in tabella
const TRectype& ums = cache().get("%UMS", um);
um = ums.get("S7");
fc = ums.get_real("R10");
}
if (um != rieprec.get(SVS_UMQTA))
{
// conversione tra UM diverse
const real qta = rieprec.get_real(SVR_QUANTITA);
rieprec.put(SVR_QUANTITA, fc * qta);
rieprec.put(SVR_UMQTA, um);
}
}
}
// Calcola il fattore di conversione necessario per passare da rieprec a statrec
const real TStampa_stat::fc_um(const TRectype& statrec,const TSVriep_record& rieprec)
{
real fc = UNO;
const TString4 statum = statrec.get(SVS_UMQTA);
TString4 um = rieprec.get(SVR_UMQTA);
if (um != statum)
{
// converte in base alla UM di riferimento in tabella
const char tipoart = rieprec.get_char(SVR_TIPOART);
if (tipoart==RIGA_MERCE || tipoart==RIGA_OMAGGI)
{
// <20> un articolo (<M>erce)
TString80 art = rieprec.get(SVR_CODART); art.trim();
TLocalisamfile umart(LF_UMART);
umart.setkey(2);
umart.put(UMART_CODART, art);
umart.put(UMART_UM, um);
if (umart.read() == NOERR)
{
fc = umart.get_real(UMART_FC);
umart.put(UMART_UM, statum);
if (umart.read() == NOERR)
{
// <20> una UM dell'articolo: uso i fc per convertirla
um = umart.get(UMART_UM);
fc /= umart.get_real(UMART_FC);
}
}
else
{
error_box(FR("L'articolo '%s' non ha l'unit<69> di misura %s\n"
"ma esistono statistiche che la utilizzano ugualmente"),
(const char*)art, (const char*)um);
}
}
if (um != statum) // Non sono riuscito a trovare una conversione certa ...
{ // ... allora provo con le unita' di misura standard
const TRectype& ums = cache().get("%UMS", um);
um = ums.get("S7");
fc = ums.get_real("R10");
}
if (um != statum)
{
// impossibile associare al totale una unit<69> di misura
fc = ZERO;
}
}
return fc;
}
// rende non validi i valori delle colonne
void TStampa_stat::invalid_columns(TRectype& statrec)
{
statrec.zero(SVS_UMQTA);
TString8 colname;
for (int col = 0; col < SVS_NUMCOLONNE; col++)
{
colname.format("%C%d", SVS_QTACOLNAME, col);
statrec.zero(colname);
}
//statrec.put(SVS_TOTALERIGA,0);
}
// funzione di filtro del cursore
bool TStampa_stat::filtro_chiavi(TSVriep_record &curr)
{
// !?!?! static
TString16 code_campo(" ");
TString16 fld_campo;
// !?!?! static
TString val_stringa(32,' ');
TSheet_field & s_chiave = selmask().sfield(F_CHIAVE);
const int num_liv_output=s_chiave.items();
TString est1,est2;
bool ok=TRUE;
// Verifica che il tipoarticolo corrisponda con quello richiesto dall'utente
ok = _valid_types.find(curr.get_char(SVR_TIPOART)) >= 0;
for (int l=0; ok && l< num_liv_output; l++)
{
code_campo=s_chiave.cell(l,s_chiave.cid2index(S_CAMPO));
fld_campo=s_chiave.cell(l,s_chiave.cid2index(S_ARTFLD));
if (code_campo==STR_CLIFOR) // cliente/fornitore ha in testa il TIPOCF
{
// ok &= curr.get_char(SVR_TIPOCF)==; !?!?! manca la selezione dei soli cli o for
val_stringa=get_part(code_campo,curr, fld_campo)+1;
} else {
val_stringa=get_part(code_campo,curr, fld_campo);
val_stringa.trim();
}
if (!(est1=s_chiave.cell(l,s_chiave.cid2index(S_DAL))).blank())
{
if (code_campo==STR_CLIFOR) // cliente/fornitore e' numerico
ok &= (atoi((const char *)val_stringa) >= atoi((const char *)est1));
else
ok &= (val_stringa>=est1);
}
if (ok && !(est2=s_chiave.cell(l,s_chiave.cid2index(S_AL))).blank())
{
if (code_campo==STR_CLIFOR) // cliente/fornitore e' numerico
ok &= (atoi((const char *)val_stringa) <= atoi((const char *)est2));
else
ok &= val_stringa<=est2;
}
}
return ok;
}
// ritorna se la query <20> suddivisa per unit<69> di misura
void TStampa_stat::set_ragg_per_um()
{
TSheet_field & s_chiave = selmask().sfield(F_CHIAVE);
for (int l=0; l< s_chiave.items(); l++)
{
if (*s_chiave.cell(l,s_chiave.cid2index(S_CAMPO))==CHR_UMISURA)
{
_ragg_per_um=FALSE;
return;
}
}
_ragg_per_um=TRUE;
}
void TStampa_stat::genera_file(const char *outfn)
{
TString key; // chiave per il record del file statistiche
const TMask& m = selmask();
const char alg=m.get(F_TIPOCALC)[0];
const int first_col = - (alg==ALG_MOBILI ? _col_anno-1:0); // prima colonna dati da osservare
const int first_raffr = -m.get_int(F_RAFFRONTO)- (alg==ALG_MOBILI ? _col_anno-1:0);// prima colonna dati da confrontare
const int first_data = first_raffr ; // prima colonna dati
TSheet_field & s_chiave = m.sfield(F_CHIAVE);
// file di OUTPUT
_svcache = new TStat_cache(new TIsamtempfile(LF_SVSTAT,outfn,TRUE,FALSE));
// file di INPUT
TLocalisamfile riep(LF_SVRIEP);
riep.set_curr(new TSVriep_record);
TSVriep_record& curr = (TSVriep_record&) riep.curr();
const TRecfield fr_anno(curr, SVR_ANNO);
const TRecfield fr_periodo(curr, SVR_PERIODO);
const bool dok = m.get_date(F_DATARAF).ok();
const TDate dd = m.get_date(dok ? F_DATARAF : F_DATAINI);
curr.put(SVR_ANNO, dd.year());
curr.put(SVR_PERIODO, _stats.date2period(dd));
const int num_liv_output=s_chiave.items();
const long start_status=period2long(curr.get_int(SVR_ANNO),curr.get_int(SVR_PERIODO),_stats.frequency());
const TDate datafin = m.get_date(F_DATAFIN);
const int yearfin = datafin.year();
const int periofin = _stats.date2period(datafin);
TProgind statusbar(period2long(datafin.year(), periofin,_stats.frequency())-start_status,
TR("Creazione del file di output"), FALSE, TRUE);
_svcache->zap();
// **********************
// ciclo principale: scorre il riepilogo statistiche per anno+periodo
// e genera i risultati in una cache
TString16 levcode;
TString16 fld;
for (int err = riep.read(_isgteq); err == NOERR &&
(curr.get_int(SVR_ANNO) < yearfin ||
(curr.get_int(SVR_ANNO) == yearfin &&
curr.get_int(SVR_PERIODO) <= periofin))
; err = riep.next())
{
statusbar.setstatus(period2long(curr.get_int(SVR_ANNO),curr.get_int(SVR_PERIODO),_stats.frequency())-start_status);
if (filtro_chiavi(curr))
{
const TPeriodo periodo(fr_anno, fr_periodo);
const int col = _freq.period2column(periodo);
if (col >= first_data && col < _numcol_dati)
{
// NOTA: eventualmente sarebbe utile forzare l'uso della UM standard se <20> una riga
// non comprendente l'articolo ......
standardize_um(curr);
// costruisce il file statistiche...
key.cut(0);
for (int l=0; l< num_liv_output; l++)
{
levcode=s_chiave.cell(l,s_chiave.cid2index(S_CAMPO));
fld=s_chiave.cell(l,s_chiave.cid2index(S_ARTFLD));
key << get_part(levcode,curr, fld);
if (key.len() > 79)
int i = 1;
// setta il range in base all'algoritmo (Valori/progressivi/mobili)
const int range=(alg==ALG_VALORI ? col : alg==ALG_PROGRESSIVI ? ((1+int(col/_col_anno))*_col_anno-1) : (col+_col_anno-1));
if (col>=first_col) // periodo da osservare
{
if (l==0)
for (int c=max(col,0);c <= range ; c++)
update_file(" ",STR_TOTGEN,LINEA_DATI,num_liv_output,c,curr, fld, l);
if (*s_chiave.cell(l,s_chiave.cid2index(S_TOTALE))=='X')
for (int c=max(col,0);c <= range ; c++)
update_file(key,levcode,LINEA_DATI,num_liv_output-l-1,c,curr, fld, l);
}
if (first_raffr !=first_col && col >= first_raffr && col<first_raffr+_numcol_dati) // periodo da confrontare
{
if (l==0)
//for (int c=max(col,0); c <= range; c++)
for (int c=col; c <= range; c++)
update_file(" "/*" Totale"*/,STR_TOTGEN,LINEA_RAFFRONTI, num_liv_output , c -first_raffr,curr, fld, l);
if (*s_chiave.cell(l,s_chiave.cid2index(S_TOTALE))=='X')
//for (int c=max(col,0); c <= range; c++)
for (int c=col; c <= range; c++)
update_file(key,levcode,LINEA_RAFFRONTI,num_liv_output-l-1, c -first_raffr , curr, fld, l);
}
}
}
} // filtro
} // ciclo
statusbar.setstatus(period2long(datafin.year(), periofin, _stats.frequency())-start_status);
_svcache->flush();
delete _svcache;
}
void TStampa_stat::set_printmask()
{
TMask &mp=selmask();
// visualizza i checkbox per i totali
const int nlivelli = mp.sfield(F_CHIAVE).items();
TString80 nomeliv;
printmask().field(F_FLAGSTOTALI).set("X");
TSheet_field& sc = mp.sfield(F_CHIAVE);
for (int f=0; f<MAX_ROWS; f++)
{
TMask_field & flfl=printmask().field(F_FLAGSTOTALI+f+1);
if (f<nlivelli )
{
partkey_name(sc.cell(f,sc.cid2index(S_CAMPO)), f, nomeliv);
nomeliv.insert(TR("Stampa totale "), 0);
flfl.set_prompt(nomeliv);
flfl.show();
if (*sc.cell(f,sc.cid2index(S_TOTALE))!=' ')
{
flfl.enable();
flfl.set("X");
} else {
flfl.disable();
flfl.set(" ");
}
} else
flfl.hide();
}
// campi per il raffronto
if (mp.get_date(F_DATARAF).empty())
{
printmask().field(F_STRAFFRONTO).hide();
printmask().field(F_TIPORAFFRONTO).hide();
} else {
printmask().field(F_STRAFFRONTO).show();
printmask().field(F_TIPORAFFRONTO).show();
}
// visualizza ed eventualmente abilita il campo colonne in un anno
printmask().set(F_COLANNO, mp.get(F_COL_ANNO));
if (mp.field(F_COL_ANNO).enabled()) // venduto, no progressivo o mobile
{
printmask().enable(F_COLANNO);
}
else
{
printmask().disable(F_COLANNO);
}
}
const TString& TStampa_stat::partkey_name(const char *lev_code, int row, TString& park) const
{
const int lev_code_num=atoi(lev_code+1);
switch (*lev_code)
{
case CHR_TIPODOC: // tipo documento
park=TR("tipo documento");
break;
case CHR_ARTICOLO: // articolo
if (lev_code_num)
park =_liv_art->name(lev_code_num);
else
park=" ";
break;
case CHR_LIVGIAC: // liv giac
CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente");
park =_liv_giac->name(lev_code_num);
break;
case CHR_CATVEN: // cat. vendita
park=TR("cat. ven.");
break;
case CHR_CLI: // cliente
park=TR("cliente ");
break;
case CHR_CLIFIELD: // campo anagrafica
park=EMPTY_STRING;
break;
case CHR_FOR: // fornitore
park=TR("fornitore ");
break;
case CHR_AGENTE: // agente
park=TR("agente ");
break;
case CHR_MAGAZZ: // mag
park=TR("magazzino");
break;
case CHR_ZONA: // zona
park=TR("zona");
break;
case CHR_UMISURA: // unit<69> di misura
park=TR("unita' di misura");
break;
case CHR_TOTGEN: // totale generale
park=TR("generale");
break;
case CHR_ARTFIELD: // campo anagrafica
park=_des_fld.row(row);
break;
default:
NFCHECK("ai chent recognaiz the code (%s) of the key part!", lev_code);
park = " ";
break;
}
return park;
}
// strippa gli spazi dal codice di questo livello
// toglie il carattere 'C' o 'F' dal codice clientefor e lo mette come codice di livello
void TStampa_stat::adjust_record(TRectype &strec, int from) const
{
char lev_code=strec.get_char(SVS_LEVCODE);
if (lev_code==CHR_CLIFOR)
{
TString codprec = strec.get(SVS_CODICE).left(from);
TString s = strec.get(SVS_CODICE).mid(from);
while ((lev_code=s.shift())==' ');
codprec << s;
strec.put(SVS_LEVCODE, lev_code);
strec.put(SVS_CODICE, codprec);
}
else
{
if (from)
{
TString codprec=strec.get(SVS_CODICE).left(from);
TString s = strec.get(SVS_CODICE).mid(from);
while ((lev_code=s.shift())==' ');
codprec << lev_code << s;
strec.put(SVS_CODICE,codprec);
}
}
}
const TString& TStampa_stat::get_part(TString & lev_code, TSVriep_record &rieprec, const TString & fld) // const
{
static TString park(25, ' ');
int lev_code_num=atoi(lev_code+1);
switch (lev_code[0])
{
case CHR_TIPODOC: // tipo documento
park = rieprec.get(SVR_TIPODOC);
break;
case CHR_ARTICOLO: // articolo
if (lev_code_num==0)
{
park=rieprec.get(SVR_CODART);
park.rpad(25);
break;
}
else
{
park =_liv_art->unpack_grpcode(rieprec.get(SVR_CODART),lev_code_num);
park.rpad(_liv_art->code_length(lev_code_num));
break;
}
case CHR_ARTFIELD: // campo dell' anagrafica articolo
{
const char t = rieprec.get_char(SVR_TIPOART);
const TRectype anamag(LF_ANAMAG);
int l = anamag.length(fld);
if (l > 40)
l = 40;
if (t == RIGA_MERCE || t == RIGA_OMAGGI)
{
park = cache().get(LF_ANAMAG, rieprec.get(SVR_CODART), fld);
park.cut(l);
park.rpad(l);
}
else
park.spaces(l);
}
break;
case CHR_LIVGIAC: // liv giac
CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente");
park = _liv_giac->unpack_grpcode(rieprec.get(SVR_GIAC),lev_code_num);
park.rpad(_liv_giac->code_length(lev_code_num));
break;
case CHR_CATVEN: // cat. vendita
park=rieprec.get(SVR_CATVEN);
park.rpad(3);
break;
case CHR_FOR: // cliente / fornitore
case CHR_CLI: // cliente / fornitore
if (rieprec.get_char(SVR_TIPOCF)>' ')
lev_code[0]=rieprec.get_char(SVR_TIPOCF);
park.format("%c%6ld",lev_code[0],rieprec.get_long(SVR_CODCF));
break;
case CHR_CLIFIELD: // campo dell' anagrafica cliente
{
TString8 key;
key.format("%c|%ld", rieprec.get_char(SVR_TIPOCF),rieprec.get_long(SVR_CODCF));
const TRectype clifo(LF_CLIFO);
int l = clifo.length(fld);
if (l > 40)
l = 40;
park = cache().get(LF_CLIFO, key, fld);
park.cut(l);
park.rpad(l);
}
break;
case CHR_AGENTE: // agente
park.format("%5s",(const char*)rieprec.get(SVR_CODAG));
break;
case CHR_MAGAZZ: // mag
park=rieprec.get(SVR_MAG);
park.rpad(3);
break;
case CHR_ZONA: // zona
park=rieprec.get(SVR_ZONA);
park.rpad(3);
break;
case CHR_UMISURA: // unit<69> di misura
park=rieprec.get(SVR_UMQTA);
park.rpad(3);
break;
default:
NFCHECK("ai chent recognaiz the code of the key part!");
park= " ";
}
if (park.blank())
park.replace(' ','?');
return park;
}
const TString& TStampa_stat::get_descrpart(const char *lev_code, TSVriep_record &rieprec, const TString & fld, int row)
{
int lev_code_num=atoi(lev_code+1);
switch (*lev_code)
{
case CHR_TIPODOC: // tipo documento
{
const TString16 tipodoc = rieprec.get(SVR_TIPODOC);
const TString& descr = _tipodoc->get(tipodoc).get("S0");
return descr;
}
case CHR_ARTICOLO: // articolo
{
const char t = rieprec.get_char(SVR_TIPOART);
switch (t)
{
case RIGA_MERCE:
case RIGA_OMAGGI:
if (lev_code_num==0 || lev_code_num== _liv_art->last_level())
{
const TRectype & rec = cache().get(LF_ANAMAG, rieprec.get(SVR_CODART));
return rec.get(ANAMAG_DESCR);
}
else
{
return _liv_art->group_descr(rieprec.get(SVR_CODART),lev_code_num);
}
break;
case RIGA_PRESTAZIONI:
return cache().get("PRS", rieprec.get(SVR_CODART), "S0");
break;
case RIGA_SPESEDOC:
return cache().get("SPP", rieprec.get(SVR_CODART), "S0");
break;
default:
break;
}
}
case CHR_ARTFIELD: // campo anagrafica
{
if (_file_fld.objptr(row) != NULL)
{
TString16 tab(_file_fld.row(row));
int file = atoi(tab);
const TRectype & anag = cache().get(LF_ANAMAG, rieprec.get(SVR_CODART));
TFieldref f;
f = _key_fld.row(row);
const TString & key = f.read(anag);
if (key.not_empty())
{
if (file != 0)
{
const TRectype & rec = cache().get(file, key);
return rec.get(_field_fld.row(row));
}
else
{
const TRectype & rec = cache().get(tab, key);
return rec.get(_field_fld.row(row));
}
}
}
return EMPTY_STRING;
}
break;
case CHR_LIVGIAC: // liv giac
CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente");
return _liv_giac->group_descr(rieprec.get(SVR_GIAC),lev_code_num);
case CHR_CATVEN: // cat. vendita
return _catven->get(rieprec.get(SVR_CATVEN)).get("S0");
case CHR_FOR: // fornitore
case CHR_CLI: // cliente
{
TToken_string key;
key.add(rieprec.get_char(SVR_TIPOCF));
key.add(rieprec.get_long(SVR_CODCF));
return cache().get(LF_CLIFO, key, CLI_RAGSOC);
}
case CHR_CLIFIELD: // campo anagrafica
{
if (_file_fld.objptr(row) != NULL)
{
TString16 tab(_file_fld.row(row));
int file = atoi(tab);
TToken_string k;
k.add(rieprec.get_char(SVR_TIPOCF));
k.add(rieprec.get_long(SVR_CODCF));
const TRectype & clifo = cache().get(LF_CLIFO, k);
TFieldref f;
f = _key_fld.row(row);
const TString & key = f.read(clifo);
if (key.not_empty())
{
if (file != 0)
{
const TRectype & rec = cache().get(file, key);
return rec.get(_field_fld.row(row));
}
else
{
const TRectype & rec = cache().get(tab, key);
return rec.get(_field_fld.row(row));
}
}
}
return EMPTY_STRING;
}
case CHR_AGENTE: // agente
return cache().get(LF_AGENTI, rieprec.get(SVR_CODAG), AGE_RAGSOC);
case CHR_MAGAZZ: // mag
return cache().get("MAG", rieprec.get(SVR_MAG), "S0");
case CHR_ZONA: // zona
return cache().get("ZON", rieprec.get(SVR_ZONA), "S0");
case CHR_UMISURA: // Unit<69> di misura
return cache().get("%UMS", rieprec.get(SVR_UMQTA), "S0");
default:
NFCHECK("ai chent recognaiz the code of the key part!");
return EMPTY_STRING;
}
}
bool TStampa_stat::recalc_period()
{
bool ok = set_column_frequency();
TMask& m = selmask();
if (ok)
{
TDate data(m.get(F_DATAFIN));
if (data.ok())
{
int col = _freq.date2column(data);
if (col < 0) col = 0;
if (col > 35) col = 35;
data = app()._freq.column_last_day(col);
m.set(F_DATAFIN, data);
m.set(F_PERIODO, col+1);
ok = TRUE;
}
data = m.get(F_DATARAF);
if (data.ok())
{
int col = _freq.date2column(data);
m.set(F_RAFFRONTO, -col);
}
}
return ok;
}
bool TStampa_stat::multiplo_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
TMask& m = f.mask();
if (k == K_SPACE || k == K_ENTER)
{
TFrequenza_statistiche base = char2frequency(m.get(F_FREQUENZA)[0]);
TFrequenza_statistiche freq = char2frequency(f.get()[0]);
if (base == freq)
{
m.enable(F_NUMERO);
}
else
{
int n = divide(freq, base);
m.set(F_NUMERO, n);
m.disable(F_NUMERO);
}
// setta la durata dell'anno
m.set(F_COL_ANNO, last_period(1992,freq));
app().recalc_period();
}
return ok;
}
bool TStampa_stat::numero_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
if (f.to_check(k))
app().recalc_period();
return ok;
}
bool TStampa_stat::periodo_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
if (f.to_check(k))
{
int col = atoi(f.get());
if (col > 0 && col <= 36)
{
if (app().set_column_frequency())
{
TDate d = app()._freq.column_last_day(col-1);
f.mask().set(F_DATAFIN, d);
}
}
}
return ok;
}
bool TStampa_stat::dataini_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
if (k == K_TAB && f.focusdirty())
{
TMask& m = f.mask();
TDate data(f.get());
const TFrequenza_statistiche base = char2frequency(m.get(F_FREQUENZA)[0]);
const TFrequenza_statistiche freq = char2frequency(m.get(F_MULTIPLO)[0]);
// floor(data, divide(freq, base) == 0 ? freq : base); // perche'?
floor(data, freq);
f.set(data.string());
app().recalc_period();
}
return ok;
}
bool TStampa_stat::datafin_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
if (k == K_TAB && f.focusdirty())
{
app().recalc_period();
}
return ok;
}
bool TStampa_stat::raffronto_handler(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
if (app().set_column_frequency())
{
const int col = atoi(f.get());
if (col > 0)
{
TDate data = app()._freq.column_first_day(-col);
f.mask().set(F_DATARAF, data);
}
else
f.mask().reset(F_DATARAF);
}
}
return TRUE;
}
bool TStampa_stat::dataraf_handler(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
TMask& m = f.mask();
TDate data(f.get());
if (data.ok())
{
if (app().set_column_frequency())
{
int col = app()._freq.date2column(data);
if (col < 0)
{
m.set(F_RAFFRONTO, -col);
data = app()._freq.column_first_day(col);
f.set(data.string());
}
else
data = botime;
}
}
if (!data.ok())
m.reset(F_RAFFRONTO);
}
return TRUE;
}
bool TStampa_stat::codice_handler(TMask_field& f, KEY k)
{
if (k == K_TAB && f.focusdirty())
{
TMask& m = f.mask();
if (app().set_column_frequency())
{
int col = m.get_int(F_RAFFRONTO);
if (col > 0)
{
TDate data = app()._freq.column_first_day(-col);
m.set(F_DATARAF, data);
}
}
// Record corrente della tabella statistiche
const TRectype& rec = ((TEdit_field&)f).browse()->cursor()->curr();
TSheet_field& sheet = m.sfield(F_CHIAVE);
sheet.destroy();
TToken_string s1 = rec.get("S1");
TToken_string s2 = rec.get("S2");
TToken_string s4 = rec.get("S4");
TString s5 = rec.get("S5");
if (s4.not_empty())
if (s4[s4.len() - 1] == '|' && s5[0] == '|') s4 << " ";
s4 <<s5;
int r = 0;
for (const char* cod = s1.get(0); cod; cod = s1.get(), r++)
{
TToken_string& row = sheet.row(r);
row = cod;
cod = s2.get(r);
row.add(cod);
row.add("");
row.add("");
row.add("");
cod = s4.get(r);
row.add(cod);
sheet.check_row(r);
}
sheet.force_update();
}
return TRUE;
}
bool TStampa_stat::filename_handler(TMask_field& f, KEY k)
{
if (k == K_TAB && !f.empty())
{
TFilename fn(f.get());
fn.ext("dbf");
TFilename path(fn.path());
path.rtrim(1); // Toglie la slash dal path
if (!path.exist())
return f.error_box(FR("Cartella %s non trovata"),(const char *)path);
else
if (fn.exist())
return f.yesno_box(FR("File %s esistente: sovrascrivo"), (const char*)fn);
}
return TRUE;
}
bool TStampa_stat::chiave_notify(TSheet_field& s, int r, KEY k)
{
bool ok = TRUE;
if (k == K_INS)
ok = s.items() < MAX_ROWS;
else if (k == K_CTRL+ K_INS)
s.row(r).add("X",1);
else if (k == K_CTRL+ K_TAB)
{
const int maxr=s.items();
// elimina il flag calcolo totali
if (r<maxr)
{
if (*s.row(r).get(1)!=' ')
{
// posso tenere abilitato il totale?
if (r>0 && *s.row(r-1).get(1)==' ')
{
s.row(r).add(" ",1);
s.force_update(r);
}
} else {
// disabilito i totale seguenti
for (r++;r < maxr; r++)
if (*s.row(r).get(1)!=' ')
{
s.row(r).add(" ",1);
s.force_update(r);
}
}
}
}
return ok;
}
bool TStampa_stat::test_field(const TString& cod, TMask_field& f) const
{
bool ok = TRUE;
switch(cod[0])
{
case CHR_ARTICOLO:
if (cod[1] != '\0' && !_liv_art->enabled())
ok = f.error_box(TR("I livelli di codice articolo non sono abilitati"));
break;
case CHR_LIVGIAC:
if (!_stats.grp_giacenza())
ok = f.error_box(TR("Le statistiche sono raggruppate per livello di giacenza"));
else if (!_liv_giac->enabled())
ok = f.error_box(TR("I livelli di giacenza non sono abilitati"));
break;
case CHR_CLIFOR:
if (!_stats.grp_cliente())
ok = f.error_box(TR("Le statistiche sono raggruppate per cliente/fornitore"));
break;
case CHR_AGENTE:
if (!_stats.grp_agente())
ok = f.error_box(TR("Le statistiche sono raggruppate per agente"));
break;
case CHR_MAGAZZ:
if (!_stats.grp_magazzino())
ok = f.error_box(TR("Le statistiche sono raggruppate per magazzino"));
break;
case CHR_ZONA:
if (!_stats.grp_zona())
ok = f.error_box(TR("Le statistiche sono raggruppate per zona"));
break;
default : break;
}
return ok;
}
bool TStampa_stat::chiave_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
if (k == K_ENTER)
{
TSheet_field& sheet = (TSheet_field&)f;
TToken_string used;
TString16 campo;
for (int r = 0; r < sheet.items(); r++)
{
TToken_string& row = sheet.row(r);
campo = row.get(0);
if (campo.blank())
continue;
ok = app().test_field(campo, f);
bool found = used.get_pos(campo) >= 0;
if (!found && (campo[0] == CHR_ARTICOLO || campo[0] == CHR_LIVGIAC))
{
const char str[2] = { campo[0], '\0' };
found = used.get_pos(str) >= 0;
}
if (campo[0] != CHR_ARTFIELD && found)
{
ok = error_box(FR("Il codice %s inserito alla riga %d e' gia'\n"
"utilizzato in una riga precedente."),
(const char*)campo, r+1);
}
else
used.add(campo);
}
}
return ok;
}
bool TStampa_stat::campo_handler(TMask_field& f, KEY k)
{
if (f.to_check(k, TRUE))
{
const bool is_fld = f.get()== STR_ARTFIELD || f.get()== STR_CLIFIELD;
if (!is_fld)
f.mask().reset(S_ARTFLD);
f.mask().field(S_ARTFLD).check_type(is_fld ? CHECK_REQUIRED : CHECK_NONE);
f.mask().enable(S_ARTFLD, is_fld);
return app().test_field(f.get(), f);
}
return TRUE;
}
bool TStampa_stat::artfld_handler(TMask_field& f, KEY k)
{
bool ok = TRUE;
switch (k)
{
case K_TAB:
case K_ENTER:
if (!f.empty() && f.to_check(k))
{
const bool is_anamag = f.mask().get(S_CAMPO) == "B";
const TRectype rec(is_anamag ? LF_ANAMAG : LF_CLIFO);
TString16 field = f.get();
int pos = field.find('[');
if (pos > 0)
field.cut(pos);
if (!rec.exist(field))
ok = f.error_box(FR("Il campo '%s' non esiste."), (const char*)field);
}
break;
case K_F9:
{
const bool is_anamag = f.mask().get(S_CAMPO) == "B";
TRelation rel(is_anamag ? LF_ANAMAG : LF_CLIFO);
TRelation_description rd(rel);
if (rd.choose_field(f.get()))
f.set(rd.field_name());
}
break;
default:
break;
}
return ok;
}
///////////////////////////////////////////////////////////
// Pseudo main
///////////////////////////////////////////////////////////
int sv1200(int argc, char* argv[])
{
TStampa_stat mainapp;
mainapp.run(argc, argv, TR("Stampa statistiche"));
return 0;
}