#include #include #include #include #include #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à 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") { // è un articolo (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 è 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à 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") { // è un articolo (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) { // è 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à 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 =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 è suddivisa per unità 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 è 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; fname(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à 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à 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à 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; }