campo-sirio/sv/sv1200.cpp
augusto 981f75391f Stampa su carta
git-svn-id: svn://10.65.10.50/trunk@5270 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-09-25 16:52:57 +00:00

1585 lines
42 KiB
C++
Executable File
Raw Blame History

#include <printapp.h>
#include <mask.h>
#include <progind.h>
#include <urldefid.h>
#include <xvtility.h>
#include "../mg/mglib.h"
#include "sv1.h"
#include "sv1200a.h"
#include "sv1200b.h"
#include "svlib01.h"
#include "svriep.h"
#include "svstat.h"
#include "..\mg\umart.h"
#include "..\mg\anamag.h"
#include "..\pr\agenti.h"
#include "..\ve\clifor.h"
///////////////////////////////////////////////////////////
// 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)
{
for (int i = n; i > 0; i--)
{
_periodo++;
if (_periodo > last_period(_anno, _frequenza))
{
_anno++;
_periodo = 1;
}
}
}
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;
_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;
if (p < _periodo_inizio)
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_CONFRONTI='C', LINEA_TARGET='T'}; // codici per le righe
TMask * _msk,*_print_msk;
TStats_agg _stats;
TFrequenza_colonne _freq;
TCodart_livelli* _liv_art;
TCodgiac_livelli* _liv_giac;
TRecord_cache *_magazz,*_tipodoc,*_catven,*_zone,*_ums;
TLocalisamfile * _umart,*_anamag,*_clifor,*_agenti;
TLocalisamfile * _outstat;
TToken_string _key;
TString _last_key;
TArray _files;
bool _ragg_per_um;
TStat_cache * _cache;
int _last_lev_grp;
TArray _group_recs;
private:
const TString& partkey_name(const char *lev_code) ;
const TString& get_part(const char *lev_code, TSVriep_record & rieprec) const;
const TString& get_descrpart(const char *lev_code, TSVriep_record &rieprec);
void set_ragg_per_um();
void put_column(TRectype & statrec,int col,TSVriep_record& curr);
const real fc_um(TRectype & statrec,const TSVriep_record& rieprec);
void invalid_columns(TRectype & statrec);
void standardize_um(TSVriep_record& rieprec, bool force=FALSE);
void azzera_file();
void update_file(const char * key, const char * code,const char tipo, const int level, const int col, TSVriep_record& curr);
void genera_file();
void esporta_file();
bool filtro_chiavi(TSVriep_record &curr);
// 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 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_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_rows_colonne(int &row, TString & r, TRectype &strec);
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);
public:
TMask& selmask() { return *_msk; }
TMask& printmask() { return *_print_msk; }
virtual bool menu(MENU_TAG);
};
inline TStampa_stat& app() { return (TStampa_stat&)main_app(); }
bool TStampa_stat::preprocess_page(int file, int count)
{
if (!file)
{
;
}
return TPrint_application::preprocess_page(file,count);
}
print_action TStampa_stat::postprocess_page(int file, int count)
{
if (!file)
{
return (_outstat->next()==NOERR) ? REPEAT_PAGE : NEXT_PAGE;
}
return TPrint_application::postprocess_page(file,count);
}
bool TStampa_stat::set_print(int i)
{
_outstat->first();
bool ok=printmask().run() != K_QUIT;
return (ok);
}
#define LARG_COLCODICE 49
#define POS_PRIMACOL 50
#define PICTURE_VALORI "###.###.###.###"
#define LARG_COLVAL 16
#define PICTURE_QUANTITA "###.###.###,###"
#define LARG_COLQTA 16
#define PICTURE_PERCENT "###.###.###,##"
#define LARG_COLPERC 7
#define PICTURE (*selmask().get(F_TIPODATO)=='V'? PICTURE_VALORI:PICTURE_QUANTITA)
void TStampa_stat::set_page(int file, int count)
{
// prepara la pagina di stampa
const int max_rows=selmask().sfield(F_CHIAVE).items();
TRectype & strec=_outstat->curr();
const int level=strec.get_int(SVS_LIVELLO);
TString r;
int row=0;
// *****************
// gestione totali di raggruppamento
while (level!=max_rows && level>_last_lev_grp)
{
// ho lasciato un livello "basso"
TRectype & rec_grp1=(TRectype &)_group_recs[_last_lev_grp+1];
TRectype & rec_grp2=(TRectype &)_group_recs[_last_lev_grp+2];
const int lencode=rec_grp2.get(SVS_CODICE).len();
r << "@" << (max_rows-_last_lev_grp)*2 <<"g";
r << "Totale " << partkey_name(rec_grp1.get(SVS_LEVCODE));
r << " " << rec_grp1.get(SVS_CODICE).mid(lencode);
set_rows_colonne(row, r ,rec_grp1);
_last_lev_grp++;
r = "";
}
if (_last_lev_grp!=strec.get_int(SVS_LIVELLO))
_last_lev_grp=strec.get_int(SVS_LIVELLO);
if (level>0)
{
// salva i record dei livelli di raggruppamento
if (level==max_rows)
strec.put(SVS_CODICE,"");
_group_recs.add(strec,level);
}
// *****************
// gestione delle "righe"
if (level != max_rows && *strec.get(SVS_TIPO)==LINEA_DATI)
{
TRectype & _rec_grp=(TRectype &)_group_recs[level+1];
const int lencode=_rec_grp.get(SVS_CODICE).len();
r << "@" << (max_rows-level)*2 <<"g";
r << partkey_name(strec.get(SVS_LEVCODE));
r << " " << strec.get(SVS_CODICE).mid(lencode);
if (level==0)
{
set_rows_colonne(row, r,strec);
} else {
reset_row(++row);
set_row(row,(const char *)r);
}
}
// *****************
// separatore di righe
if (printmask().get_bool(F_STRAFFRONTO))
{
reset_row(++row);
set_row(row,"");
}
}
// fa le set row per la "riga" contenente i valori delle colonne di statistica
void TStampa_stat::set_rows_colonne(int &row,TString & r, TRectype &strec)
{
//**********
// setta le colonne
TString colname,r1;
int largcolonna = *selmask().get(F_TIPODATO)=='V' ? LARG_COLVAL : LARG_COLQTA; // valori o quantit<69>
const int max_rows=selmask().sfield(F_CHIAVE).items();
const bool sttotriga=printmask().get_bool(F_STTOTALIRIGA);
const int numcolonne = selmask().get_bool(F_PERIODO);
for (int col=0; col < numcolonne; col++) // colonne
{
colname << SVS_COLNAME << col;
r << "@" << POS_PRIMACOL+col*(sttotriga ? largcolonna+LARG_COLPERC : largcolonna) <<"g";
r1=r;
switch (*printmask().get(F_TIPORAFFRONTO))
{
case AS_VALUE:
r << strec.get_real(colname).string(PICTURE);
break;
case AS_DIFF:
r << strec.get_real(colname).string(PICTURE);
break;
case AS_PERC:
r << strec.get_real(colname).string(PICTURE_PERCENT);
break;
}
// colonna con la percentuale rispetto al totale di riga
if (sttotriga)
{
r << "@" << POS_PRIMACOL+col*(largcolonna+LARG_COLPERC)+largcolonna <<"g";
r << real(strec.get_real(colname)/strec.get_real(SVS_TOTALERIGA)*100.0).string(PICTURE_PERCENT);
r << "%%";
}
// riga con i totali di colonna
if (printmask().get_bool(F_STTOTALICOL))
{
TRectype & _rec_totale=(TRectype &)_group_recs[max_rows];
if (!_rec_totale.get_real(colname).is_zero())
{
r1 << real(strec.get_real(colname)/_rec_totale.get_real(colname)*100.0).string(PICTURE_PERCENT);
r1 << "%%";
}
}
}
// colonna totale di riga
if (sttotriga)
{
r << "@" << POS_PRIMACOL+numcolonne*(largcolonna+LARG_COLPERC) <<"g";
r << strec.get_real(SVS_TOTALERIGA).string(PICTURE);
r << "@" << POS_PRIMACOL+numcolonne*(largcolonna+LARG_COLPERC)+largcolonna <<"g";
r << real(100).string(PICTURE_PERCENT);
r << "%%";
}
// *****************
// stampa la riga
reset_row(++row);
set_row(row,(const char *)r);
// *****************
// stampa totale di colonna
if (printmask().get_bool(F_STTOTALICOL))
{
reset_row(++row);
set_row(row,(const char *)r1);
}
}
void TStampa_stat::preprocess_header()
{}
void TStampa_stat::preprocess_footer()
{}
bool TStampa_stat::user_create()
{
_print_msk= NULL;
_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);
_msk->sfield(F_CHIAVE).set_notify(chiave_notify);
TMask& sm = _msk->sfield(F_CHIAVE).sheet_mask();
sm.set_handler(S_CAMPO, campo_handler);
_files.add(new TLocalisamfile(LF_SVRIEP));
_files.add(new TLocalisamfile(LF_SVSTAT));
// cache R/W per le statistiche
_cache= new TStat_cache();
// oggetti per la gestione delle parti del codice
_liv_art = new TCodart_livelli;
_liv_giac = new TCodgiac_livelli;
_ums = new TRecord_cache("%UMS");
_tipodoc = new TRecord_cache("%NUM");
_catven = new TRecord_cache("CVE");
_zone = new TRecord_cache("ZON");
_umart = new TLocalisamfile(LF_UMART);
_anamag = new TLocalisamfile(LF_ANAMAG);
_clifor = new TLocalisamfile(LF_CLIFO);
_agenti = new TLocalisamfile(LF_AGENTI);
_outstat = new TLocalisamfile(LF_SVSTAT);
// cursore di stampa
add_file(LF_SVSTAT);
//add_cursor(new TCursor(new TRelation(LF_SVSTAT)));
// impone force setpage
force_setpage();
set_real_picture("");
return TRUE;
}
bool TStampa_stat::user_destroy()
{
delete _msk;
if (_print_msk) delete _print_msk;
delete _liv_art;
delete _liv_giac;
// cancella le cache
delete _cache;
delete _ums;
// cancella i files
delete _umart;
delete _anamag;
delete _clifor;
delete _agenti;
delete _outstat;
return TRUE;
}
bool TStampa_stat::menu(MENU_TAG )
{
TMask& m = selmask();
TSheet_field& sheet = m.sfield(F_CHIAVE);
TString tmp;
KEY k;
while ((k = m.run()) != K_QUIT)
{
set_column_frequency();
_key.cut(0);
for (int r = 0; r < sheet.items(); r++)
{
tmp = sheet.row(r).get(0);
if (!tmp.blank())
_key.add(tmp);
}
if (k == K_SAVE)
{
set_ragg_per_um();
genera_file();
esporta_file();
} else {
set_printmask();
do_print(1);
}
}
return FALSE;
}
void TStampa_stat::fill_field_list(TMask& m)
{
// opzioni per il tipo di dato
TList_field& tipoart = (TList_field&)m.field(F_TIPOART);
TToken_string codes, descr;
codes = "M|P";
descr = "Merce|Prestazioni";
if (!_stats.omaggio_is_merce())
{
codes.add("O");
descr.add("Omaggi");
}
tipoart.replace_items(codes, descr);
// 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;
for (int l = 0; l <= cal.last_level(); l++)
{
if (l && !cal.enabled(l))
continue;
row = "A";
if (l) row << l;
row.add("Codice articolo");
if (l) row << '[' << l << ']';
list.add(row);
}
TCodgiac_livelli& cgl = *_liv_giac;
for (l = 0; l <= cgl.last_level(); l++)
{
if (l && !cgl.enabled(l))
continue;
row = "L";
if (l) row << l;
row.add("Livello giacenza");
if (l) row << '[' << l << ']';
list.add(row);
}
list.add("U|Unita' di misura");
list.add("D|Tipo documento");
list.add("V|Categoria vendita");
list.add("C|Codice cliente");
list.add("G|Codice agente");
list.add("Z|Codice zona");
list.add("M|Codice magazzino");
}
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);
if (_stats.frequency() == fs_settimanale)
{
multiplo.reset();
multiplo.disable();
}
else
multiplo.enable();
TToken_string std_codes("G|S|Q|1|2|3|4|6|A");
TToken_string std_descr("Giorni|Settimane|Quindicine|Mesi|"
"Bimestri|Trimestri|Quadrimestri|Semestri|Anni");
TToken_string codes(8), descr(80);
switch(_stats.frequency())
{
case fs_giornaliera : codes = std_codes; break;
case fs_settimanale : codes = "S|3|6|A"; break;
case fs_quindicinale : codes = std_codes.mid(4); break;
case fs_mensile : codes = std_codes.mid(6); 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;
}
TString tmp;
for (const char* cod = codes.get(0); cod; cod = codes.get())
{
tmp = cod;
const int pos = std_codes.get_pos(tmp);
CHECK(pos >= 0, "Invalid frequency char");
tmp = std_descr.get(pos);
descr.add(tmp);
}
multiplo.replace_items(codes, descr);
// 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, const int level, const int col, TSVriep_record& curr)
{
CHECK(col>=0,"Le colonne partono da 0");
static TRectype statrec(LF_SVSTAT);
TToken_string cachekey(key);
cachekey.rtrim();
cachekey.add(tipo);
statrec = _cache->get(cachekey);
if (_cache->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);
if (_msk->get(F_TIPODATO)=="Q")
statrec.put(SVS_UMQTA,curr.get(SVR_UMQTA));
}
if (*lev_code== 'T') // totale generale
statrec.put(SVS_DESCR,"Totale generale");
else
statrec.put(SVS_DESCR,get_descrpart(lev_code,curr).left(SVS_LEN_DESCR));
put_column(statrec,col,curr);
_cache->put(statrec);
}
// aggiorna la colonna del record statrec con i dati di SVriep
void TStampa_stat::put_column(TRectype & statrec,int col,TSVriep_record& rieprec)
{
real r,fc;
static TString colname("Rxx");
CHECK(col>=0,"Le colonne partono da 0");
colname=SVS_COLNAME;
colname << col;
r=statrec.get_real(colname);
if (_msk->get(F_TIPODATO)=="V")
{
r+=rieprec.get_real(SVR_VALORE);
statrec.put(colname,r);
statrec.put(SVS_TOTALERIGA,statrec.get_real(SVS_TOTALERIGA)+rieprec.get_real(SVR_VALORE));
} else {
if (statrec.get(SVR_UMQTA).not_empty())
{
if ((fc=fc_um(statrec,rieprec))==0.0)
invalid_columns(statrec);
else
{
r+=rieprec.get_real(SVR_QUANTITA)*fc;
statrec.put(colname,r);
statrec.put(SVS_TOTALERIGA,statrec.get_real(SVS_TOTALERIGA)+rieprec.get_real(SVR_QUANTITA)*fc);
}
} // no UM ? no valid data!
}
}
// 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)
{
static TString um;
real fc;
if (rieprec.get(SVR_TIPOART)=="M")
{
// <20> un articolo (<M>erce); converto alla UM principale dell'art.
_umart->setkey(1);
_umart->put(UMART_CODART,rieprec.get(SVR_CODART));
_umart->put(UMART_NRIGA,1);
_umart->read();
um=_umart->get(UMART_UM);
fc=_umart->get_real(UMART_FC);
} else {
// non <20> un articolo: converte in base alla UM di riferimento in tabella
um=_ums->get(um).get("S7");
fc=_ums->get(um).get_real("R10");
}
if (um!=rieprec.get(SVS_UMQTA))
{
// conversione tra UM diverse
fc=fc*rieprec.get_real(SVR_QUANTITA);
rieprec.put(SVR_QUANTITA,fc);
rieprec.put(SVR_UMQTA,um);
}
}
}
// aggiunge al valore passat la quantit<69> del record riep, correggendola con il fattore di conv. necessario
const real TStampa_stat::fc_um(TRectype & statrec,const TSVriep_record& rieprec)
{
static TString um;
real fc(1.0);
um=rieprec.get(SVR_UMQTA);
if (um!=statrec.get(SVS_UMQTA))
{
// converte in base alla UM di riferimento in tabella
if (rieprec.get(SVR_TIPOART)=="M")
{
// <20> un articolo (<M>erce)
_umart->setkey(2);
_umart->put(UMART_CODART,rieprec.get(SVR_CODART));
_umart->put(UMART_UM,rieprec.get(SVR_UMQTA));
if (_umart->read()==NOERR)
{
fc=_umart->get_real(UMART_FC);
_umart->put(UMART_UM,statrec.get(SVS_UMQTA));
if (_umart->read()==NOERR)
{
// <20> una UM dell'articolo: uso i fc per convertirla
um=_umart->get(UMART_UM);
fc=fc/_umart->get_real(UMART_FC);
}
} else
fatal_box("Archivio $UMART inconsistente con $RDOC"); // altrimenti ... errore di inconsistenza!
}
if (um != statrec.get(SVS_UMQTA))
{
um=_ums->get(um).get("S7");
fc=_ums->get(um).get_real("R10");
}
if (um != statrec.get(SVS_UMQTA))
{
// impossibile associare al totale una unit<69> di misura
fc = 0.0;
}
}
return fc;
}
// rende non validi i valori delle colonne
void TStampa_stat::invalid_columns(TRectype & statrec)
{
statrec.put(SVS_UMQTA,"");
char colname[9];
for (int col=0; col <SVS_NUMCOLONNE; col ++)
{
sprintf(colname,"%s%d",SVS_COLNAME,col);
statrec.put(colname,0);
}
statrec.put(SVS_TOTALERIGA,0);
}
bool TStampa_stat::filtro_chiavi(TSVriep_record &curr)
{
TSheet_field & s_chiave = selmask().sfield(F_CHIAVE);
const int num_liv_output=s_chiave.items();
TString est1,est2;
bool ok=TRUE;
for (int l=0; ok && l< num_liv_output; l++)
{
static TString code_campo;
static TString val_stringa;
int val_intero;
code_campo=s_chiave.cell(l,s_chiave.cid2index(S_CAMPO));
if (code_campo=="C") // cliente/fornitore ha in testa il TIPOCF
val_intero=atoi(get_part(code_campo,curr)+1);
else if (code_campo=="G") // agente <20> numerico
val_intero=atoi(get_part(code_campo,curr));
else
{
val_stringa=get_part(code_campo,curr);
val_stringa.trim();
}
if (!(est1=s_chiave.cell(l,s_chiave.cid2index(S_DAL))).blank())
{
if (code_campo=="C" || code_campo=="G") // cliente/fornitore o agente sono numerici
ok &= val_intero>=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=="C" || code_campo=="G") // cliente/fornitore o agente sono numerici
ok &= val_intero<=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))=='U')
{
_ragg_per_um=FALSE;
return;
}
}
_ragg_per_um=TRUE;
}
void TStampa_stat::genera_file()
{
const TMask& m = selmask();
const char alg=m.get(F_TIPOCALC)[0];
const int columns = m.get_int(F_PERIODO); //numero di colonne osservate
const int col_anno =m.get_int(F_COL_ANNO); //numero di colonne che formano un "Anno"
const int first_col = - (alg=='M' ? col_anno-1:0); // prima colonna dati da osservare
const int first_raffr = -m.get_int(F_RAFFRONTO)- (alg=='M' ? 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);
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);
curr.put(SVR_ANNO,m.get_date(F_DATARAF).year());
curr.put(SVR_PERIODO,_stats.date2period(m.get_date(F_DATARAF)));
int err = riep.read(_isgteq);
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());
TProgind statusbar(date2long(m.get_date(F_DATAFIN),_stats.frequency())-start_status
, "Creazione del file di output", FALSE, TRUE, 60);
azzera_file();
_cache->clear();
// **********************
// ciclo principale: scorre il riepilogo statistiche per anno+periodo
// e genera i risultati in una cache
for (; err == NOERR &&
(curr.get_int(SVR_ANNO)<=m.get_date(F_DATAFIN).year() ||
(curr.get_int(SVR_ANNO)==m.get_date(F_DATAFIN).year() &&
curr.get_int(SVR_PERIODO)<=_stats.date2period(m.get_date(F_DATAFIN))))
; 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 < columns)
{
standardize_um(curr); //!?!? eventualmente sarebbe utile forzare l'uso della standard se <20> una riga non comprendente l'articolo
// costruisce il file statistiche...
TString key,um;
for (int l=0; l< num_liv_output; l++)
{
static TString lev_code;
lev_code=s_chiave.cell(l,s_chiave.cid2index(S_CAMPO));
key << get_part(lev_code,curr);
// setta il ragne in base all'algoritmo (Valori/progressivi/mobili)
const int range=(alg=='V'? col : alg=='P' ? ((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(" Totale","T",LINEA_DATI,num_liv_output,c,curr);
if (*s_chiave.cell(l,s_chiave.cid2index(S_TOTALE))=='X')
for (int c=max(col,0);c <= range ; c++)
update_file(key,lev_code,LINEA_DATI,num_liv_output-l-1,c,curr);
}
if (first_raffr !=first_col && col >= first_raffr && col<=first_raffr+columns) // periodo da confrontare
{
if (l==0)
for (int c=max(col,0); c <= range; c++)
update_file(" Totale","T",LINEA_CONFRONTI, num_liv_output , c -first_raffr,curr);
if (*s_chiave.cell(l,s_chiave.cid2index(S_TOTALE))=='X')
for (int c=max(col,0); c <= range; c++)
update_file(key,lev_code,LINEA_CONFRONTI,num_liv_output-l-1, c -first_raffr , curr);
}
}
}
} // filtro
} // ciclo
statusbar.setstatus(date2long(m.get_date(F_DATAFIN),_stats.frequency())-start_status);
_cache->flush();
}
void TStampa_stat::set_printmask()
{
TMask &mp=selmask();
if (_print_msk) delete _print_msk;
_print_msk= new TMask("sv1200b");
const nlivelli=mp.sfield(F_CHIAVE).items();
TString80 nomeliv;
for (int f=0; f<nlivelli; f++)
{
nomeliv="Stampa totale ";
nomeliv << partkey_name(mp.sfield(F_CHIAVE).cell(f,mp.sfield(F_CHIAVE).cid2index(S_CAMPO)));
printmask().add_boolean(F_FLAGSTOTALI+f, 0 ,nomeliv,2+36*int(f/(18-Y_FLAGSTOTALI)),Y_FLAGSTOTALI+(f% (18-Y_FLAGSTOTALI)));
}
if (mp.get_date(F_DATARAF).empty())
{
printmask().field(F_STRAFFRONTO).disable();
printmask().field(F_TIPORAFFRONTO).disable();
}
}
void TStampa_stat::esporta_file()
{}
void TStampa_stat::azzera_file()
{
TLocalisamfile stat(LF_SVSTAT);
int err=NOERR;
while (err==NOERR)
{
err=stat.first();
if (err==NOERR)
err=stat.remove();
}
}
const TString& TStampa_stat::partkey_name(const char *lev_code)
{
static TString park(' ',25);
int lev_code_num=atoi(lev_code+1);
switch (*lev_code)
{
case 'D': // tipo documento
park="tipo documento";
break;
case 'A': // articolo
if (lev_code_num)
park =_liv_art->name(lev_code_num);
else
park="articolo";
break;
case 'L': // liv giac
CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente");
park =_liv_giac->name(lev_code_num);
break;
case 'V': // cat. vendita
park="categoria di vendita";
break;
case 'C': // cliente / fornitore
park="cliente";
break;
case 'G': // agente
park="agente";
break;
case 'M': // mag
park="magazzino";
break;
case 'Z': // zona
park="zona";
break;
case 'U': // unit<69> di misura
park="unita' di misura";
break;
default:
fatal_box("ai chent recognaiz the code of the key part!");
return "";
}
return park;
}
const TString& TStampa_stat::get_part(const char *lev_code, TSVriep_record &rieprec) const
{
static TString park(' ',25);
int lev_code_num=atoi(lev_code+1);
switch (*lev_code)
{
case 'D': // tipo documento
return rieprec.get(SVR_TIPODOC);
case 'A': // articolo
if (lev_code_num==0)
{
park=rieprec.get(SVR_CODART);
return park.rpad(25);
}
else
{
park =_liv_art->unpack_grpcode(rieprec.get(SVR_CODART),lev_code_num);
return park.rpad(_liv_art->code_length(lev_code_num));
}
case 'L': // liv giac
CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente");
park = _liv_giac->unpack_grpcode(rieprec.get(SVR_GIAC),lev_code_num);
return park.rpad(_liv_giac->code_length(lev_code_num));
case 'V': // cat. vendita
park=rieprec.get(SVR_CATVEN);
return park.rpad(3);
case 'C': // cliente / fornitore
park.format("%c%6d",rieprec.get_char(SVR_TIPOCF),rieprec.get_int(SVR_CODCF));
return park;
case 'G': // agente
park.format("%5d",rieprec.get_int(SVR_CODAG));
return park;
case 'M': // mag
park=rieprec.get(SVR_MAG);
return park.rpad(3);
case 'Z': // zona
park=rieprec.get(SVR_ZONA);
return park.rpad(3);
case 'U': // unit<69> di misura
park=rieprec.get(SVR_UMQTA);
return park.rpad(3);
default:
fatal_box("ai chent recognaiz the code of the key part!");
return "";
}
}
const TString& TStampa_stat::get_descrpart(const char *lev_code, TSVriep_record &rieprec)
{
int lev_code_num=atoi(lev_code+1);
switch (*lev_code)
{
case 'D': // tipo documento
return _tipodoc->get(rieprec.get(SVR_TIPODOC)).get("S0");
case 'A': // articolo
if (lev_code_num==0 || lev_code_num== _liv_art->last_level())
{
_anamag->put(ANAMAG_CODART,rieprec.get(SVR_CODART));
_anamag->read();
return _anamag->get(ANAMAG_DESCR);
}
else
{
return _liv_art->group_descr(rieprec.get(SVR_CODART),lev_code_num);
}
case 'L': // liv giac
CHECK(lev_code_num>0,"I livelli di giacenza sono utilizzabili solo singolarmente");
return _liv_giac->group_descr(rieprec.get(SVR_GIAC),lev_code_num);
case 'V': // cat. vendita
return _catven->get(rieprec.get(SVR_CATVEN)).get("S0");
case 'C': // cliente
{
_clifor->put(CLI_TIPOCF,rieprec.get_char(SVR_TIPOCF));
_clifor->put(CLI_CODCF,rieprec.get_int(SVR_CODCF));
_clifor->read();
return _clifor->get(CLI_RAGSOC);
}
case 'G': // agente
_agenti->put(AGE_CODAGE,rieprec.get(SVR_CODAG));
return _agenti->get(AGE_RAGSOC);
case 'M': // mag
return _magazz->get(rieprec.get(SVR_MAG)).get("S0");
case 'Z': // zona
return _zone->get(rieprec.get(SVR_ZONA)).get("S0");
case 'U': // Unit<69> di misura
return _ums->get(rieprec.get(SVR_UMQTA)).get("S0");
default:
fatal_box("ai chent recognaiz the code of the key part!");
return "";
}
}
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;
if (k == K_SPACE)
{
TMask& m = f.mask();
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);
}
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);
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");
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);
sheet.check_row(r);
}
sheet.force_update();
}
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;
return ok;
}
bool TStampa_stat::test_field(const TString& cod, TMask_field& f) const
{
bool ok = TRUE;
switch(cod[0])
{
case 'A':
if (cod[1] != '\0' && !_liv_art->enabled())
ok = f.error_box("I livelli di codice articolo non sono abilitati");
break;
case 'L':
if (!_stats.grp_giacenza())
ok = f.error_box("Le statistiche sono raggruppate per livello di giacenza");
else if (!_liv_giac->enabled())
ok = f.error_box("I livelli di giacenza non sono abilitati");
break;
case 'C':
if (!_stats.grp_cliente())
ok = f.error_box("Le statistiche sono raggruppate per cliente");
break;
case 'G':
if (!_stats.grp_agente())
ok = f.error_box("Le statistiche sono raggruppate per agente");
break;
case 'M':
if (!_stats.grp_magazzino())
ok = f.error_box("Le statistiche sono raggruppate per magazzino");
break;
case 'Z':
if (!_stats.grp_zona())
ok = f.error_box("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] == 'A' || campo[0] == 'L'))
{
char str[2]; str[0] = campo[0]; str[1] = '\0';
found = used.get_pos(str) >= 0;
}
if (found)
{
ok = error_box("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)
{
bool ok = TRUE;
if (f.to_check(k))
ok = app().test_field(f.get(), f);
return ok;
}
///////////////////////////////////////////////////////////
// Pseudo main
///////////////////////////////////////////////////////////
int sv1200(int argc, char* argv[])
{
TStampa_stat mainapp;
mainapp.run(argc, argv, "Stampa statistiche");
return 0;
}