#include "ps0099100a.h" #include #include #include #include #include #include "../cg/cglib01.h" #include "../ve/velib07.h" /////////////////////////////////////////////////////////// // MASCHERA /////////////////////////////////////////////////////////// class TStatistiche_ANIVAL_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TStatistiche_ANIVAL_mask(); virtual ~TStatistiche_ANIVAL_mask() {} }; TStatistiche_ANIVAL_mask::TStatistiche_ANIVAL_mask() : TAutomask("ps0099100a") { } bool TStatistiche_ANIVAL_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_ANNO: if (e == fe_modify && !o.empty()) { TEsercizi_contabili esc; TDate inies, fines; if (esc.code2range(atoi(o.get()), inies, fines)) { set(F_DADATA, inies); set(F_ADATA, fines); } } break; case F_DADATA: case F_ADATA: if (e == fe_close) { const int anno = get_int(F_ANNO); TEsercizi_contabili esc; //..le date devono essere incluse nell'esercizio selezionato! const TDate data = o.get(); if (!data.empty() && esc.date2esc(data) != anno) return error_box(TR("La data deve appartenere all'anno selezionato")); } break; default: break; } return true; } ///////////////////////////////////////////////////////////// // REPORT ///////////////////////////////////////////////////////////// class TStatistiche_ANIVAL_report : public TReport { protected: virtual bool use_mask() { return false; } public: TStatistiche_ANIVAL_report() {} }; ///////////////////////////////////////////////////////////// // CSV RECORDSET ///////////////////////////////////////////////////////////// class TStatistiche_ANIVAL_csv_recordset : public TCSV_recordset { real _tot[13]; //array con i totali per mese (e anno) protected: //virtual const TVariant& get(const char* field_name) const; long trova_riga(const TString& codart); public: TStatistiche_ANIVAL_csv_recordset(); void aggiungi_riga(const TRiga_documento& riga); void compila_intestazione(); void calcola_percentuali(); }; TStatistiche_ANIVAL_csv_recordset::TStatistiche_ANIVAL_csv_recordset() : TCSV_recordset("CSV(\"\t\")") //tab separated { //create_field("CODART", -1, 20, _alfafld); //codart } void TStatistiche_ANIVAL_csv_recordset::compila_intestazione() { insert_rec(0); //riempie i campi del primo record del csv in modo da avere l'intestazione set(0, "CODART"); set(1, "DESCRIZIONE"); set(2, "GENNAIO"); set(3, "%GEN"); set(4, "FEBBRAIO"); set(5, "%FEB"); set(6, "MARZO"); set(7, "%MAR"); set(8, "APRILE"); set(9, "%APR"); set(10, "MAGGIO"); set(11, "%MAG"); set(12, "GIUGNO"); set(13, "%GIU"); set(14, "LUGLIO"); set(15, "%LUG"); set(16, "AGOSTO"); set(17, "%AGO"); set(18, "SETTEMBRE"); set(19, "%SET"); set(20, "OTTOBRE"); set(21, "%OTT"); set(22, "NOVEMBRE"); set(23, "%NOV"); set(24, "DICEMBRE"); set(25, "%DIC"); set(26, "ANNO"); set(27, "%ANNO"); } //metodo plutonico di ricerca dicotomica su una colonna di csv_recordset long TStatistiche_ANIVAL_csv_recordset::trova_riga(const TString& codart) { long first = 0; long last = items() - 1; long riga = -1; while(first <= last) { const long guess = (first + last) / 2; move_to(guess); const TString& guess_codart = get(0).as_string(); const int diff = guess_codart.compare(codart); if (diff == 0) { riga = guess; break; } if (diff > 0) { last = guess - 1; } else { first = guess + 1; } } return riga; } //funzione di ordinamento per il campo codart (campo 0 sul csv) static int compare_csv_rows_codart(const TObject** o1, const TObject** o2) { TToken_string& s1 = *(TToken_string*)*o1; TToken_string& s2 = *(TToken_string*)*o2; //deve ordinare sul campo codart const TString& c1 = s1.get(0); const TString& c2 = s2.get(0); int cmp = c1.compare(c2); return cmp; } //metodo per la scrittura del csv void TStatistiche_ANIVAL_csv_recordset::aggiungi_riga(const TRiga_documento& riga) { //creazione di un nuovo record da esportare //esiste già questo codart? const TString80 codart = riga.get(RDOC_CODART); long numriga = trova_riga(codart); if (numriga < 0) { //codart new_rec(""); set(0, TVariant(codart)); //descrart const TString& descrart = cache().get(LF_ANAMAG, codart, ANAMAG_DESCR); set(1, TVariant(descrart)); //re-sorting per codart sort(compare_csv_rows_codart); numriga = trova_riga(codart); CHECKS(numriga >= 0, "Articolo bastardo ", (const char*)codart); } //riempimento del record secondo il tracciato: // codart+descrart+12*[impns+%incid] //datadoc (serve a stabilire in quale colonna andrà a sommarsi l'importo della riga corrente const TDate datadoc = riga.doc().get_date(DOC_DATADOC); const int mese = datadoc.month(); const int column = mese * 2; //le colonne dei mesi sono gennaio=2,febbraio=4,marzo=6... //importo const real importo = riga.importo(true, false); //importo riga corrente real importone = get(column).as_real(); //importo totale della colonna mese corrispondente nel csv importone += importo; //aggiunge l'importo riga all'importone articolo del mese nel csv set(column, importone); //riscrive l'importone aggiornato nella sua colonna.. //..(in formato stringa, cioè con la "," e non il "." //aggiorna l'importone del mese (ricordarsi che l'array parte da 0 quindi ci va -1 nell'indice) _tot[mese - 1] += importo; //aggiorna anche il totale annuale _tot[12] += importo; } void TStatistiche_ANIVAL_csv_recordset::calcola_percentuali() { //%incidenza articolo sul mese = imp_articolo mese / imp tot mese for (bool ok = move_first(); ok; ok = move_next()) { real totale_anno; for (int i = 2; i <= 24; i += 2) { const real imp_art_mese = get(i).as_real(); //ricordando che l'array parte da 0 const real perc = imp_art_mese * CENTO / _tot[i/2 - 1]; //calcola la % incidenza articolo sul totale per quel mese set(i + 1, perc); totale_anno += imp_art_mese; } set(26, totale_anno); const real perc_anno = totale_anno * CENTO / _tot[12]; //calcola la % incidenza articolo sul totale annuale set(27, perc_anno); } } /////////////////////////////////////////////////////////// // APPLICAZIONE /////////////////////////////////////////////////////////// class TStatistiche_ANIVAL : public TSkeleton_application { virtual bool check_autorization() const {return false;} virtual const char * extra_modules() const {return "ve";} protected: void elabora(const TMask& mask) const; public: virtual bool create(); virtual void main_loop(); }; //metodo di base per la ricerca delle righe documento che soddisfano i parametri dell'utonto void TStatistiche_ANIVAL::elabora(const TMask& mask) const { TString query; //scatta la query per la costruzione del recordset query << "USE RDOC KEY 1\n"; query << "SELECT ((CODARTMAG!=\"\")&&(BETWEEN(33->DATADOC,#DADATA,#ADATA))&&(BETWEEN(CODARTMAG,#DACODART,#ACODART)))\n"; query << "JOIN DOC INTO PROVV==PROVV ANNO==ANNO CODNUM==CODNUM NDOC==NDOC\n"; query << "FROM CODNUM=#CODNUM ANNO=#ANNO PROVV='D'\n"; query << "TO CODNUM=#CODNUM ANNO=#ANNO PROVV='D'\n"; TDocument_recordset righe(query); righe.set_var("#CODNUM", TVariant(mask.get(F_CODNUM))); righe.set_var("#DADATA", mask.get_date(F_DADATA)); righe.set_var("#ADATA", mask.get_date(F_ADATA)); righe.set_var("#ANNO", TVariant((long)mask.get_int(F_ANNO))); righe.set_var("#DACODART", TVariant(mask.get(F_DACODART))); righe.set_var("#ACODART", TVariant(mask.get(F_ACODART))); //se trova (si spera!) almeno una rigadoc buona comincia il bello del programma const long righe_items = righe.items(); if (righe_items > 0) { //E crea pure la progind.. TProgind pi(righe_items, TR("Generazione file statanival.xls"), true, true); //creazione del csv recordset che verra' riempito dai record del recordset righe TStatistiche_ANIVAL_csv_recordset* csv = new TStatistiche_ANIVAL_csv_recordset; //Scansione del recordset trovato for (bool ok = righe.move_first(); ok; ok = righe.move_next()) { if (!pi.addstatus(1)) break; const TDocumento& doc = righe.doc(righe.cursor()->curr()); const int nriga = righe.get(RDOC_NRIGA).as_int(); //scrive sul CSV i campi che servono al file di excel e al report csv->aggiungi_riga(doc[nriga]); } //aggiorna le colonne delle percentuali csv->calcola_percentuali(); //se richiesto il file in formato excel... if (mask.get_bool(F_EXCEL)) { //crea la riga con le intestazioni dei campi e la mette all'inizio csv->compila_intestazione(); //salva il file come richiesto TString path = mask.get(F_PATH); path.lower(); path << "\\statanival.xls"; csv->save_as(path, fmt_silk); //accoppa la riga con le intestazioni dei campi csv->destroy(0); #ifdef DBG xvt_sys_goto_url(path, "open"); #endif } //creazione del report di stampa TStatistiche_ANIVAL_report rep; bool ok = rep.load("ps0099100a"); //setta il recordset... rep.set_recordset(csv); if (ok) { TReport_book book; ok = book.add(rep); if (ok) book.print_or_preview(); } } //if(righe_items>0... } void TStatistiche_ANIVAL::main_loop() { TStatistiche_ANIVAL_mask mask; while (mask.run() == K_ENTER) { elabora(mask); } } bool TStatistiche_ANIVAL::create() { //se non ha le vendite è impossibile da utilizzare if (!has_module(VEAUT)) return error_box(TR("Modulo non autorizzato")); return TSkeleton_application::create(); } int ps0099100(int argc, char* argv[]) { TStatistiche_ANIVAL stat_anal; stat_anal.run(argc, argv, TR("Statistiche ANIVAL")); return 0; }