#include #include #include "sv2.h" #include "svlib01.h" #include "sv2100a.h" #include "svriep.h" class TRicalcolo_stats : public TSkeleton_application { static TStats_agg _agg; static TAssoc_array _tipi_doc; static TDate _datalast; static bool tipi_stat_filter(const TRelation* r); protected: virtual void main_loop(); virtual bool create(); virtual void on_config_change(); public: static bool datein_handler(TMask_field& f, KEY k); static bool datefin_handler(TMask_field& f, KEY k); bool kill_stats(const TDate& dfr, const TDate& dto); void calc_stats(const TDate& dfr, const TDate& dto); }; TStats_agg TRicalcolo_stats::_agg; TDate TRicalcolo_stats::_datalast; TAssoc_array TRicalcolo_stats::_tipi_doc; bool TRicalcolo_stats::create() { open_files(LF_TABCOM, 0); // File comuni open_files(LF_TAB, LF_CLIFO, LF_OCCAS, 0); // File ditta open_files(LF_CFVEN, LF_DOC, LF_RIGHEDOC, 0); // File vendite return TSkeleton_application::create(); } void TRicalcolo_stats::on_config_change() { _agg.init(); TWait_cursor hourglass; TISAM_recordset tip("USE %TIP"); const TRectype& rec_tip = tip.cursor()->curr(); for (bool ok = tip.move_first(); ok; ok = tip.move_next()) { if (rec_tip.get_bool("B2")) // E' un tipo per le statistiche _tipi_doc.add(rec_tip.get("CODTAB"), NULL); } TDate datamin = TDate(TODAY); datamin.set_day(1); datamin.set_month(1); TISAM_recordset doc("USE DOC KEY 3"); const TRectype& rec_doc = doc.cursor()->curr(); for (bool ok = doc.move_first(); ok; ok = doc.move_next()) { const TString& tipodoc = rec_doc.get(DOC_TIPODOC); if (_tipi_doc.is_key(tipodoc)) { TDate dd = rec_doc.get(DOC_DATADOC); if (dd.ok()) { datamin = floor(dd, _agg.frequency()); break; } else { const int anno = rec_doc.get_int(DOC_ANNO); if (anno > 1900) { datamin = TDate(1, 1, anno); break; } } } } _datalast = ini_get_string(CONFIG_DITTA, "sv", "UltimoCalcolo"); if (_datalast < datamin) { _datalast = datamin; --_datalast; } ceil(_datalast, _agg.frequency()); } bool TRicalcolo_stats::kill_stats(const TDate& dfr, const TDate& dto) { TFast_isamfile fdoc(LF_SVRIEP); TRelation rel(LF_SVRIEP); TRectype recfrom(LF_SVRIEP), recto(LF_SVRIEP); if (dfr.ok()) { recfrom.put(SVR_ANNO, dfr.year()); recfrom.put(SVR_PERIODO, _agg.date2period(dfr)); } if (dto.ok()) { recto.put(SVR_ANNO, dto.year()); recto.put(SVR_PERIODO, _agg.date2period(dto)); } TCursor cur(&rel, "", 1, &recfrom, &recto); const long items = cur.items(); TProgress_monitor pi(items, TR("Azzeramento statistiche"), false); cur.freeze(); for (cur = 0; cur.pos() < items; ++cur) { pi.add_status(); const int err = rel.remove(); if (err != NOERR) return error_box(FR("Errore %d durante l'azzeramento archivi"), err); } return true; } bool TRicalcolo_stats::tipi_stat_filter(const TRelation* r) { return _tipi_doc.is_key(r->curr().get(DOC_TIPODOC)); } void TRicalcolo_stats::calc_stats(const TDate& dfr, const TDate& dto) { TFast_isamfile fdoc(LF_DOC); TRectype recfrom(LF_DOC), recto(LF_DOC); if (dfr.ok()) { recfrom.put(DOC_DATADOC, dfr); recfrom.put(DOC_PROVV, "D"); } if (dto.ok()) { recto.put(DOC_DATADOC, dto); recto.put(DOC_PROVV, "D"); } TRelation rel(LF_DOC); TCursor cur(&rel, "PROVV='D'", 3, &recfrom, &recto); cur.set_filterfunction(tipi_stat_filter); TRecnotype items = 0; { TProgress_monitor pi(1, TR("Selezione documenti"), false); items = cur.items(); } cur.freeze(); TString msg; msg << TR("Ricalcolo"); if (dfr.ok()) msg << TR(" dal ") << dfr; if (dto.ok()) msg << TR(" al ") << dto; TProgress_monitor pi(items, msg, false); TRecnotype records = 0; _agg.reset(); const TRectype& curr = rel.curr(); for (cur = 0; cur.pos() < items; ++cur) { pi.add_status(); const TString& tipodoc = curr.get(DOC_TIPODOC); if (!_tipi_doc.is_key(tipodoc)) continue; // Dovrebbe già essere filtrato const TDocumento doc(rel.curr()); const bool nota_cr = doc.tipo().nota_credito(); FOR_EACH_PHYSICAL_RDOC(doc, r, rdoc) { if (nota_cr) _agg.sub(*rdoc); else _agg.add(*rdoc); } records++; if (records % 1000 == 0) { _agg.update(); TString m; m << msg << '\n' << records << TR(" documenti elaborati"); pi.set_text(m); xvt_app_process_pending_events(); } } _agg.update(); if (_agg.empty()) warning_box(TR("L'archivio riepilogativo delle statistiche ora ricalcolato risulta vuoto")); } bool TRicalcolo_stats::datein_handler(TMask_field& f, KEY k) { if (f.to_check(k)) { const TMask& m = f.mask(); const bool def = m.get_bool(F_DEFINITIVE); const TDate data = f.get(); TDate inizio = data; floor(inizio, _agg.frequency()); if (data != inizio) f.set(inizio.string()); TDate consiglio = _datalast; ++consiglio; if (def) { if (inizio > consiglio) return f.error_box(FR("Impossibile effettuare la ricostruzione statistiche\nda una data successiva al %s"), consiglio.stringa()); } else { if (inizio < consiglio) return f.error_box(FR("Impossibile effettuare la ricostruzione statistiche\nda una data antecedente il %s"), consiglio.stringa()); } } return true; } bool TRicalcolo_stats::datefin_handler(TMask_field& f, KEY k) { if (f.to_check(k)) { const TMask& m = f.mask(); const TDate inizio = m.get_bool(F_FROMDATE); const TDate data = f.get(); TDate fine = data; ceil(fine, _agg.frequency()); if (data != fine) f.set(fine.string()); if (fine <= inizio) return f.error_box(FR("Impossibile effettuare la ricostruzione statistiche\nfino ad una data antecedente il %s"), inizio.stringa()); } return true; } void TRicalcolo_stats::main_loop() { if (argc() >= 3 && xvt_str_same(argv(2), "-A")) { TDate dto(TODAY); ceil(dto, _agg.frequency()); TDate dfr = dto; floor(dfr, _agg.frequency()); dfr.addmonth(-12); if (dfr <= _datalast) { dfr = _datalast; ++dfr; } if (kill_stats(dfr, dto)) calc_stats(dfr, dto); } else { TMask m("sv2100a"); m.set_handler(F_FROMDATE, datein_handler); m.set_handler(F_TODATE, datefin_handler); if (_datalast.ok()) { TDate fd = _datalast; ++fd; m.set(F_FROMDATE, fd); m.set(F_LASTDATE, _datalast); } while (m.run() == K_ENTER) { const bool def = m.get_bool(F_DEFINITIVE); const TDate dfr(m.get(F_FROMDATE)); const TDate dto(m.get(F_TODATE)); if (kill_stats(dfr, def ? TDate() : dto)) calc_stats(dfr, dto); if (def) { _datalast = dto.ok() ? dto : TDate(TODAY); ini_set_string(CONFIG_DITTA, "sv", "UltimoCalcolo", _datalast); m.set(F_LASTDATE, _datalast); } } } } int sv2100(int argc, char* argv[]) { TRicalcolo_stats app; app.run(argc, argv, TR("Ricalcolo statistiche")); return 0; }