#include "tp0900a.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../ve/velib.h" #include "../ve/velib07.h" /////////////////////////////////////////////////////////// // MASCHERA /////////////////////////////////////////////////////////// class TDichiarazione_CONAI_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TDichiarazione_CONAI_mask(); virtual ~TDichiarazione_CONAI_mask() {} }; TDichiarazione_CONAI_mask::TDichiarazione_CONAI_mask() : TAutomask("tp0900a") { } bool TDichiarazione_CONAI_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_FIRM: if (e == fe_init || e == fe_modify) o.check(RUNNING_CHECK); break; default: break; } return true; } ///////////////////////////////////////////////////////////// // REPORT ///////////////////////////////////////////////////////////// class TDichiarazione_CONAI_report : public TReport { protected: virtual bool use_mask() { return false; } public: TDichiarazione_CONAI_report() {} }; ///////////////////////////////////////////////////////////// // CSV RECORDSET ///////////////////////////////////////////////////////////// class TDichiarazione_CONAI_csv_recordset : public TCSV_recordset { protected: //virtual const TVariant& get(const char* field_name) const; public: TDichiarazione_CONAI_csv_recordset(); }; TDichiarazione_CONAI_csv_recordset::TDichiarazione_CONAI_csv_recordset() : TCSV_recordset("CSV(,)\n") {} /////////////////////////////////////////////////////////// // APPLICAZIONE /////////////////////////////////////////////////////////// class TDichiarazione_CONAI : public TSkeleton_application { protected: real clifo_conai(const TCli_for& clifo, const TCONAI_class conai_specie, TString& paiv) const; void elabora(const TMask& mask) const; void scrivi_csv(const TRectype& prima_riga, TDichiarazione_CONAI_csv_recordset& csv, const TCONAI_class conai_specie, const TString& conai_codart) const; void scrivi_csv_doc_con_riga_generata(TDocumento& doc, const int n_riga_generata, TDichiarazione_CONAI_csv_recordset& csv, const TCONAI_class conai_specie) const; void scrivi_csv_doc_speciale(TDocumento& doc, TDichiarazione_CONAI_csv_recordset& csv, const TCONAI_class conai_specie, const TString& conai_codart) const; public: virtual bool create(); virtual void main_loop(); }; // Percentuale di esenzione CONAI di clifo real TDichiarazione_CONAI::clifo_conai(const TCli_for& clifo, const TCONAI_class conai_specie, TString& paiv) const { const TRectype& cfven_rec = clifo.vendite(); real cfven_perces_conai = ZERO; if (conai_configured_class(conai_specie)) cfven_perces_conai = cfven_rec.get_real(conai_esenzione_name(conai_specie, LF_CFVEN)); //nuovo metodo con logica rovesciata (fino al prossimo cambio di idea!) paiv = clifo.get(CLI_COFI); if (paiv.empty()) { paiv = clifo.get(CLI_PAIV); paiv << " (PI)"; } return cfven_perces_conai; } //riempie recordset con le righe CONAI del documento che contiene una riga generata CONAI void TDichiarazione_CONAI::scrivi_csv_doc_con_riga_generata(TDocumento& doc, const int n_riga_generata, TDichiarazione_CONAI_csv_recordset& csv, const TCONAI_class conai_specie) const { //prende dalla riga i dati che gli servono per fare vari calcoli const TRiga_documento& riga_generata = doc[n_riga_generata]; const TString80 conai_codart = riga_generata.get(RDOC_CODART); //questo ci serve per trovare le righe conai const real totale_qta_assogg = riga_generata.get_real(RDOC_QTA); //questo ci serve per le quantita' assoggetate o no TGeneric_distrib agip(totale_qta_assogg, 5); //distrib per ridistribuire le % dei quantitativi assoggetati TArray qta_AB_conai; //array con le quantita' conai totali (A+B) //scopre se il doc e' una NAC const bool is_nac = doc.is_nota_credito(); //prende la data del documento const TDate& datadoc = doc.data(); //prende il cliente ed i suoi dati const TCli_for& clifo = doc.clifor(); TString16 clifo_paiv; //cerca la percentuale di esenzione conai sul cliente (controllo) const real cfven_perc_conai = clifo_conai(clifo, conai_specie, clifo_paiv); const int nrighe = doc.rows(); //ciclo di creazione del distrib con le quote conai for (int j = 1; j <= nrighe; j++) { const TRiga_documento& rdoc = doc[j]; //quantita' totale conai (A + B) sul report const real n = rdoc.calc_conai_qta(conai_specie); if (n != ZERO) { qta_AB_conai.add(n, j); //va calcolato con il metodo apposito //quantita' assoggettata (B) sul report agip.add(n); } } //ciclo di riempimento delle righe csv;scandisce solo l'array con i valori compilati FOR_EACH_ARRAY_ROW(qta_AB_conai, i, obj) { const TRiga_documento& rdoc = doc[i]; //servono SOLO le righe CONAI!!!!! //se non e' stata definita la sottocategoria conai (maiali!!) va messa uguale a quella generica TString4 sottocat = rdoc.get(conai_sottocat_name(conai_specie)); //puo' capitare che la sottocategoria sia stata troncata alla categoria if (sottocat.len() == 2) sottocat << "99"; //creazione di un nuovo record da esportare csv.new_rec(""); //riempie i campi del record del csv //codnum-anno-ndoc-datadoc-codcli-cofi-nriga-codagg1-sottocat-prezzo-um-conai(AB)-conai(B)-conai(A) //parte chiave della riga csv.set(0, TVariant(rdoc.get(RDOC_CODNUM))); csv.set(1, TVariant(rdoc.get(RDOC_ANNO))); csv.set(2, TVariant(rdoc.get(RDOC_NDOC))); csv.set(3, TVariant(datadoc)); csv.set(4, TVariant(clifo.codice())); csv.set(5, TVariant(clifo_paiv)); csv.set(6, TVariant(rdoc.get(RDOC_CODART))); csv.set(7, TVariant(rdoc.get(RDOC_NRIGA))); //codici conai csv.set(8, TVariant(sottocat.left(2))); //codice materiale conai (es. carta, legno...) csv.set(9, TVariant(sottocat)); //sottocodice materiale (es. carta imballo, busta...) //prezzo const real prezzo = riga_generata.get_real(RDOC_PREZZO); //va preso dalla riga generata csv.set(10, TVariant(prezzo)); //um conai const TString4 umqta = cache().get("SPP", conai_codart, "S7"); //unita' di misura dalla tabella SPP csv.set(11, TVariant(umqta)); //quantita' totale conai (A + B) sul report (le NAC hanno segno rovesciato) real qta_tot_conai = (const real&)qta_AB_conai[i]; if (is_nac) qta_tot_conai = -qta_tot_conai; csv.set(15, TVariant(qta_tot_conai)); //quantita' assoggettata (B) sul report (le NAC hanno segno rovesciato) real qta_assoggettata_conai = agip.get(); //se non trova un prezzo nella riga generata la % di esenzione CONAI e' 100 if (prezzo == ZERO) { //se trova la % di esenzione al 100 non puo' assoggettare conai! qta_assoggettata_conai = ZERO; } if (is_nac) qta_assoggettata_conai = -qta_assoggettata_conai; csv.set(13, TVariant(qta_assoggettata_conai)); //quantita' esente conai (A) sul report const real qta_esente_conai = qta_tot_conai - qta_assoggettata_conai; csv.set(12, TVariant(qta_esente_conai)); //valore totale contributo (BxC) sul report const real totale_contrib_conai = qta_assoggettata_conai * prezzo; csv.set(14, TVariant(totale_contrib_conai)); //percentuale di esenzione conai const TVariant rdoc_perc_conai = rdoc.get_real(conai_esenzione_name(conai_specie, LF_RIGHEDOC)); csv.set(16, rdoc_perc_conai); //percentuale di esenzione conai in cfven csv.set(17, TVariant(cfven_perc_conai)); } } //riempie recordset con le righe CONAI del documento che NON ha una riga generata CONAI;trattasi di documenti.. //..farlocchi costruiti ad arte per correggere le vaccate dei rompiscatolifici void TDichiarazione_CONAI::scrivi_csv_doc_speciale(TDocumento& doc, TDichiarazione_CONAI_csv_recordset& csv, const TCONAI_class conai_specie, const TString& conai_codart) const { //scopre se il doc e' una NAC const bool is_nac = doc.is_nota_credito(); //prende la data del documento const TDate& datadoc = doc.data(); //prende il cliente ed i suoi dati const TCli_for& clifo = doc.clifor(); TString16 clifo_paiv; //cerca la percentuale di esenzione conai sul cliente (controllo) const real cfven_perc_conai = clifo_conai(clifo, conai_specie, clifo_paiv); const int nrighe = doc.rows(); //ciclo di riempimento delle righe csv;scandisce solo l'array con i valori compilati for (int i = 1; i <= nrighe; i++) { const TRiga_documento& rdoc = doc[i]; //se non e' stata definita la sottocategoria conai (maiali!!) va messa uguale a quella generica TString4 sottocat = rdoc.get(conai_sottocat_name(conai_specie)); //puo' capitare che la sottocategoria sia stata troncata alla categoria if (sottocat.len() == 2) sottocat << "99"; //creazione di un nuovo record da esportare csv.new_rec(""); //riempie i campi del record del csv //codnum-anno-ndoc-datadoc-codcli-cofi-nriga-codagg1-sottocat-prezzo-um-conai(AB)-conai(B)-conai(A) //parte chiave della riga csv.set(0, TVariant(rdoc.get(RDOC_CODNUM))); csv.set(1, TVariant(rdoc.get(RDOC_ANNO))); csv.set(2, TVariant(rdoc.get(RDOC_NDOC))); csv.set(3, TVariant(datadoc)); csv.set(4, TVariant(clifo.codice())); csv.set(5, TVariant(clifo_paiv)); csv.set(6, TVariant(rdoc.get(RDOC_CODART))); csv.set(7, TVariant(rdoc.get(RDOC_NRIGA))); //codici conai csv.set(8, TVariant(sottocat.left(2))); //codice materiale conai (es. carta, legno...) csv.set(9, TVariant(sottocat)); //sottocodice materiale (es. carta imballo, busta...) //prezzo const real prezzo = rdoc.get_real(RDOC_PREZZO); //va preso dalla riga stessa csv.set(10, TVariant(prezzo)); //um conai const TString4 umqta = cache().get("SPP", conai_codart, "S7"); //unita' di misura dalla tabella SPP csv.set(11, TVariant(umqta)); //quantita' totale conai (A + B) sul report (le NAC hanno segno rovesciato) real qta_tot_conai = rdoc.get_real(RDOC_QTA); if (is_nac) qta_tot_conai = -qta_tot_conai; csv.set(15, TVariant(qta_tot_conai)); //percentuale di esenzione conai al 100%? const real rdoc_perc_conai = rdoc.get_real(conai_esenzione_name(conai_specie, LF_RIGHEDOC)); // ex QTAGG2 //quantita' assoggettata (B) sul report (le NAC hanno segno rovesciato, ma avendolo gia' gia' rovesciato.. //..in precedenza non deve fare nulla!) real qta_assoggettata_conai = qta_tot_conai; if (rdoc_perc_conai >= CENTO) // Guy: Mi pare strano gestire solo il caso 100% qta_assoggettata_conai = ZERO; csv.set(13, TVariant(qta_assoggettata_conai)); //quantita' esente conai (A) sul report const real qta_esente_conai = qta_tot_conai - qta_assoggettata_conai; //deve essere sempre ZERO! csv.set(12, TVariant(qta_esente_conai)); //valore totale contributo (BxC) sul report const real totale_contrib_conai = qta_assoggettata_conai * prezzo; csv.set(14, TVariant(totale_contrib_conai)); //percentuale di esenzione conai csv.set(16, TVariant(rdoc_perc_conai)); //percentuale di esenzione conai in cfven csv.set(17, TVariant(cfven_perc_conai)); } } //crea il documento che contiene la riga che gli viene passata,cerca la riga generata ed in base al risultato della ricerca chiama.. //..il metodo adatto void TDichiarazione_CONAI::scrivi_csv(const TRectype& prima_riga, TDichiarazione_CONAI_csv_recordset& csv, const TCONAI_class conai_specie, const TString& conai_codart) const { //crea la testata delle righedoc per poter fare vari calcoli (e intanto il tempo se ne va...) const int anno = prima_riga.get_int(RDOC_ANNO); const TString4 codnum = prima_riga.get(RDOC_CODNUM); const long numdoc = prima_riga.get_long(RDOC_NDOC); //documento della prima riga e quindi anche di tutte le altre righe conai TDocumento doc('D', anno, codnum, numdoc); //controlli sul cliente const TCli_for& clifo = doc.clifor(); const bool addconai = clifo.vendite().get_bool(CFV_ADDCONAI); //se il cliente non c'entra con il conai e' inutile perdere tempo! if (addconai) { //cerca la riga generata (in tal caso e' un documento con righe CONAI giuste) const int nrighe = doc.rows(); int n_riga_generata = 0; for (int j = 1; j <= nrighe; j++) { const TRiga_documento& rdoc = doc[j]; //c'è la riga generata con codart di tipo conai (sia automatica che manuale)? if (rdoc.get(RDOC_CODART) == conai_codart && (rdoc.is_spese() || rdoc.is_generata())) { n_riga_generata = j; break; } } if (n_riga_generata > 0) scrivi_csv_doc_con_riga_generata(doc, n_riga_generata, csv, conai_specie); else scrivi_csv_doc_speciale(doc, csv, conai_specie, conai_codart); } } static int compare_csv_rows_specie(const TObject** o1, const TObject** o2) { TToken_string& s1 = *(TToken_string*)*o1; TToken_string& s2 = *(TToken_string*)*o2; //deve ordinare sul campo sottocat = codice specie conai (campo 8) const TString& c1 = s1.get(8); const TString& c2 = s2.get(8); int cmp = c1.compare(c2); // sotto ordinamento per codice cliente (campo 4) if (cmp == 0) { const TString& c1 = s1.get(4); const TString& c2 = s2.get(4); cmp = c1.compare(c2); // sotto-sotto ordinamento per ndoc (campo 2) if (cmp == 0) { const TString& c1 = s1.get(2); const TString& c2 = s2.get(2); cmp = c1.compare(c2); } } return cmp; } static int compare_csv_rows_cofi(const TObject** o1, const TObject** o2) { TToken_string& s1 = *(TToken_string*)*o1; TToken_string& s2 = *(TToken_string*)*o2; //deve ordinare sul campo cofi/piva (campo 5) const TString& c1 = s1.get(5); const TString& c2 = s2.get(5); int cmp = c1.compare(c2); return cmp; } static int compare_csv_rows_datadoc(const TObject** o1, const TObject** o2) { TToken_string& s1 = *(TToken_string*)*o1; TToken_string& s2 = *(TToken_string*)*o2; //deve ordinare sul campo datadoc (campo 3) const TDate c1 = s1.get(3); const TDate c2 = s2.get(3); int cmp = c1 - c2; // sotto-sotto ordinamento per ndoc (campo 2) if (cmp == 0) { const long c1 = s1.get_long(2); const long c2 = s2.get_long(2); cmp = c1 - c2; } return cmp; } //metodo di base per la ricerca delle righe documento che soddisfano i parametri dell'utonto void TDichiarazione_CONAI::elabora(const TMask& mask) const { //Tanto per cominciare stabilisce il range di date... const int anno = mask.get_int(F_ANNO); TDate dataini(1, 1, anno); TDate datafin(31, 12, anno); const int tipo_periodo = mask.get_int(F_PERIODO); //se il periodo scelto non e' un anno intero... switch (tipo_periodo) { case 2: { const int mese = mask.get_int(F_TRIMESTRE); dataini.set_month(mese - 2); datafin = dataini; datafin.addmonth(2); datafin.set_end_month(); } break; case 3: { const int mese = mask.get_int(F_MESE); dataini.set_month(mese); datafin = dataini; datafin.set_end_month(); } break; default: break; } //Adesso tocca al codice articolo in base alla specie CONAI const TCONAI_class conai_specie = (TCONAI_class)mask.get_int(F_SPECIECONAI); TConfig ditta_ini(CONFIG_DITTA, "ve"); TVariant codart; const char* nome_report = ""; //report di tipo 6.1 scelto in base alla specie conai switch (conai_specie) { case CONAI_ACC: codart = ditta_ini.get("CODACC"); //acciaio nome_report = "tp0900ac.rep"; break; case CONAI_ALL: codart = ditta_ini.get("CODALL"); //alluminio nome_report = "tp0900al.rep"; break; case CONAI_CAR: codart = ditta_ini.get("CODCAR"); //carta nome_report = "tp0900ca.rep"; break; case CONAI_PLA: codart = ditta_ini.get("CODPLA"); //plastica nome_report = "tp0900pl.rep"; break; case CONAI_LEG: codart = ditta_ini.get("CODLEG"); //legno nome_report = "tp0900le.rep"; break; case CONAI_VET: codart = ditta_ini.get("CODVET"); //vetro nome_report = "tp0900ve.rep"; break; default: break; } //In caso il tipo stampa NON sia con il modello 6.1 basato sulla specie conai ma di tipo 6.3 basato sui.. //fornitori e le loro esenzioni, oppure l'allegato del 6.1 il report va rinominato perche' e' unico const int tipostampa = mask.get_int(F_TIPOSTAMPA); switch (tipostampa) { case 1: break; //se modello 6.1 va bene quello che ha stabilito nel precedente switch case 2: nome_report = "tp0900sc.rep"; //scheda elenco fatture allegata al 6.1 break; case 3: nome_report = "tp0900es.rep"; //modello 6.3 quantita' in esenzione break; case 4: nome_report = "tp0900li.rep"; //lista clienti in esenzione break; default: break; } //Adesso prende le numerazioni e i tipi documento TSheet_field& sf = mask.sfield(F_TIPI); //la query e' sulle righe documento //cerca le righe con numerazione e tipo indicate nello sheet;prende sia le righe che generano CONAI (per avere il codice conai,.. //..le quantita' etc) e le righe generate da CONAI (per avere i prezzi) TString query; TString scat_fieldname(conai_sottocat_name(conai_specie)); if (scat_fieldname.blank()) return; scat_fieldname.insert("RG1:"); query << "USE RDOC\n"; query << "SELECT BETWEEN(33.DATADOC,#DADATA,#ADATA)&&(33.TIPODOC==#TIPODOC)&&(" << scat_fieldname <<"!=\"\")\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"; //crea il recordset principale relativo alle righe originali CONAI ed assegna subito i valori delle variabili che restano costanti al cambio.. //..numerazione/tipo: sono le date ed il codice articolo TDocument_recordset rdoc(query); rdoc.set_var("#ANNO", TVariant((long)anno)); rdoc.set_var("#DADATA", dataini); rdoc.set_var("#ADATA", datafin); //rdoc.set_var("#CODART", codart); //creazione del csv recordset che verra' riempito dai record del recordset rdoc TDichiarazione_CONAI_csv_recordset* csv = new TDichiarazione_CONAI_csv_recordset; //quante righe dello sheet processa? const long tot_items = sf.items(); //Visto che e' possibile avere una secchiata di numerazioni, gli tocca fare un giro per ogni numerazione FOR_EACH_SHEET_ROW(sf, r, row) { //estrazione definitiva dei record che soddisfano il casino di parametri richiesti rdoc.set_var("#CODNUM", TVariant(row->get(0))); rdoc.set_var("#TIPODOC", TVariant(row->get(2))); //quanti record validi ha trovato? const long items = rdoc.items(); /*#ifdef DBG warning_box("Hai trovato %ld righe di %s! Ti sembrano abbastanza?", items, row->get(0)); #endif*/ //E crea pure la progind.. TProgind pi(tot_items, TR("Generazione righe..."), true, true); long last_ndoc = 0; //Scansione del recordset trovato for (bool ok = rdoc.move_first(); ok; ok = rdoc.move_next()) { if (!pi.addstatus(1)) break; const long ndoc = rdoc.get(RDOC_NDOC).as_int(); if (ndoc != last_ndoc) { scrivi_csv(rdoc.cursor()->curr(), *csv, conai_specie, codart.as_string()); last_ndoc = ndoc; } } //for(bool ok = rdoc.move_first(.. } //FOR_EACH... //riordinamento del file secondo il tipo di stampa selezionato: switch (tipostampa) { case 1: csv->sort(compare_csv_rows_specie); //Mod.6.1: specie conai, codice cliente, numero documento break; case 2: csv->sort(compare_csv_rows_datadoc); //Allegato 6.1: datadoc break; case 3: csv->sort(compare_csv_rows_cofi); //Mod.6.3: piva e cofi break; case 4: csv->sort(compare_csv_rows_cofi); //Lista clienti in esenzione: piva e cofi break; default: break; } //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->insert_rec(0); //riempie i campi del primo record del csv in modo da avere l'intestazione csv->set(0, "CODNUM"); csv->set(1, "ANNO"); csv->set(2, "NDOC"); csv->set(3, "DATADOC"); csv->set(4, "CODCLI"); csv->set(5, "COFICLI"); csv->set(6, "CODART"); csv->set(7, "NRIGA"); csv->set(8, "CLASSE"); csv->set(9, "SOTTOCL"); csv->set(10, "PREZZO"); csv->set(11, "UM"); csv->set(12, "CONAI A"); csv->set(13, "CONAI B"); csv->set(14, "CONAI BxC"); csv->set(15, "CONAI A+B"); csv->set(16, "INDETDOC"); csv->set(17, "INDETCLI"); TFilename path = mask.get(F_PATH); path.lower(); if (path.ends_with("xls") || path.ends_with("slk")) csv->save_as(path, fmt_silk); else csv->save_as(path); //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 TDichiarazione_CONAI_report rep; bool ok = rep.load(nome_report); if (ok) { //setta il recordset... //deve settare almeno un campo manualmente perche' funzioni la mask2report csv->set_var("#EMAIL", TVariant("Manca la email"), true); rep.set_recordset(csv); //..e poi carica i valori sulla maschera nel report!!!! rep.mask2report(mask); TReport_book book; ok = book.add(rep); if (ok) book.print_or_preview(); } } void TDichiarazione_CONAI::main_loop() { TDichiarazione_CONAI_mask mask; while (mask.run() == K_ENTER) { elabora(mask); } } bool TDichiarazione_CONAI::create() { if (!has_module(DCAUT)) return error_box(TR("Modulo non autorizzato")); return TSkeleton_application::create(); } int tp0900(int argc, char* argv[]) { TDichiarazione_CONAI dc; dc.run(argc, argv, TR("Dichiarazione CONAI")); return 0; }