#include #include #include #include #include #include #include #include #include "../cg/cglib01.h" #include "../ve/velib.h" #include "ha2.h" #include "ha2100a.h" const char* const APPNAME = TR("Procedura Esselunga: generazione file Privat"); /////////////////////////////////////////////////////////// // TAutomask /////////////////////////////////////////////////////////// class THardy_esselunga_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: THardy_esselunga_mask(); virtual ~THardy_esselunga_mask() {}; }; THardy_esselunga_mask::THardy_esselunga_mask() : TAutomask ("ha2100a") { } bool THardy_esselunga_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_DATAINI: if (e == fe_close || e == fe_modify) { //se la data iniziale è piena -> l'anno deve essere lo stesso nelle 2 date; //se invece è vuota -> la data iniziale viene presa come la data iniziale dell'esercizio della data finale... //..ma questo qui non serve e viene rinviato alla query principale del recordset const TDate datafin = get_date(F_DATAFIN); TEsercizi_contabili esc; const int datafin_esc = esc.date2esc(datafin); TDate dataini = o.get(); if (dataini.ok()) { const int dataini_esc = esc.date2esc(dataini); if (datafin_esc != dataini_esc) return error_box("Le date devono appartenere allo stesso esercizio!"); } } break; default: break; } return true; } /////////////////////////////////////// // TSkeleton_application /////////////////////////////////////// class THardy_esselunga : public TSkeleton_application { protected: void elabora(const TMask& mask); long genera_recordset(const TMask& mask, TISAM_recordset& recset); void elabora_documenti(const TMask& mask, TISAM_recordset& recset, TLog_report& log); void check_date(const TDate& datafine, TDate& dataini); bool check_cliente(const long codcf); public: virtual void main_loop(); virtual bool create(); }; //metodo per ricavare la data iniziale di elaborazione qualora l'utonto non la metta e l'esercizio da usare void THardy_esselunga::check_date(const TDate& datafine, TDate& dataini) { TEsercizi_contabili esc; TDate datafine_tmp = datafine; const int esercizio = esc.date2esc(datafine); esc.code2range(esercizio, dataini, datafine_tmp); } //metodo che filtra tutti i documenti in base ai parametri della maschera long THardy_esselunga::genera_recordset(const TMask& mask, TISAM_recordset& recset) { TString query; query << "USE DOC "; TString filt_expr; // aggiungo alla query le condizioni sulle numerazioni selezionare da maschera TSheet_field& sheet = mask.sfield(F_SHEETDOC); const long items = sheet.items(); if (items > 0) { TString16 codnum; filt_expr << " SELECT "; FOR_EACH_SHEET_ROW(sheet, r, row) { codnum = row->get(0); if (codnum.not_empty()) { filt_expr << "(CODNUM==\""; filt_expr << codnum << "\") OR"; } } filt_expr.rtrim(2); query << filt_expr; } query << "\nFROM DATADOC=#DATAINI PROVV=D ANNO=#ANNO"; query << "\nTO DATADOC=#DATAFIN PROVV=D ANNO=#ANNO"; recset.set(query); //settaggio delle variabili const TDate datafin = mask.get_date(F_DATAFIN); TDate dataini = mask.get_date(F_DATAINI); //se la data iniziale è vuota deve coincidere con l'inizio dell'esercizio della data finale (obbligatoria!) int esc = datafin.year(); if (!dataini.ok()) check_date(datafin, dataini); recset.set_var("#ANNO", long(esc)); recset.set_var("#DATAINI", dataini); recset.set_var("#DATAFIN", datafin); return recset.items(); } /* //metodo che riempie un array con tutti i contratti del cliente passatogli (in base alla tipologia di contratti da elaborare) int THardy_esselunga::find_contratti_cliente(const long codcf, const TMask& mask, TArray& contratti_cliente) { contratti_cliente.destroy(); //deve cercare tutti i contratti del cliente e metterli nell'array TString query; query << "USE DOC KEY 4"; query << "\nSELECT ((TIPODOC=#A_TIPODOC)||(TIPODOC=#R_TIPODOC)||(TIPODOC=#P_TIPODOC))"; query << "\nFROM TIPOCF=C CODCF=#CODCF"; query << "\nTO TIPOCF=C CODCF=#CODCF"; TISAM_recordset recset(query); //settaggio delle variabili //il codice numerazione lo trova nella configurazione Hardy, e lo deve scegliere in base alla tipologia di contratti che sta esaminando! TConfig config(CONFIG_DITTA, "ha"); const TString& tip_ant = config.get("CoAntTip"); const TString& tip_rifa = config.get("CoRifaTip"); const TString& tip_post = config.get("CoPostTip"); recset.set_var("#A_TIPODOC", tip_ant); recset.set_var("#R_TIPODOC", tip_rifa); recset.set_var("#P_TIPODOC", tip_post); recset.set_var("#CODCF", codcf); const long n_contratti = recset.items(); //questo serve solo al sagace programmatore //aggiunge i contratti all'array: solo quelli in auge nel periodo di calcolo selezionato sulla maschera! for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { //contratti anticipo 'A': datainizio esiste sempre, datafine non esiste (va ad esaurimento) //contratti posticipo 'P': datainizio esiste sempre, datafine può non esistere //contratti rifatturazione 'R': come contratti anticipo //controlla validità del contratto con le date scelte per l'elaborazione dei documenti const TDate data_ini_contratto = recset.get(DOC_DATACOMP).as_date(); TDate data_ini_elab = mask.get_date(F_DADATA); const TDate data_fine_elab = mask.get_date(F_ADATA); if (!data_ini_elab.ok()) check_date(data_fine_elab, data_ini_elab); //quindi la datainizio vale per tutti allo stesso modo (è obbligatoria nei contratti) //se l'elaborazione finisce prima che cominci il contratto -> il contratto non serve a nulla if (data_ini_contratto > data_fine_elab) continue; //la data fine vale invece solo per i contratti 'P' e potrebbe non esserci (contratti senza scadenza) TDate data_fine_contratto; //se la data fine contratto non è valida (ma è presente!) non dobbiamo fare nulla, perchè il contratto non va elaborato data_fine_contratto = recset.get(DOC_DATAFCOMP).as_date(); if (data_fine_contratto.ok()) { if (data_fine_contratto < data_ini_elab) continue; } //ci tocca istanziarci un contratto_premi TContratto_premi* curr_contratto = new TContratto_premi(recset.cursor()->curr()); //azzeratore del campo con il totale reso per elaborazione, nel caso di contratti Anticipo/Rifatturazione, riga spese const char tipo_contr = curr_contratto->tipo_contratto(); if (tipo_contr == 'A' || tipo_contr == 'R') { FOR_EACH_PHYSICAL_RDOC(*curr_contratto, r, rdoc) { if (rdoc->get(RDOC_TIPORIGA) == HARDY_TIPORIGA_SOMMA) { rdoc->zero(RCA_2_RESO_CORRENTE); break; } } } contratti_cliente.add(curr_contratto); } return contratti_cliente.items(); } bool THardy_esselunga::aggiorna_contratti(const TRiga_documento& rdoc, TContratto_premi& contratto) { bool elaborato = false; const char tipo_contratto = contratto.tipo_contratto(); //parametri della riga fattura TString80 rdoc_codart = rdoc.get(RDOC_CODART); rdoc_codart.trim(); const real rdoc_qta = rdoc.get_real(RDOC_QTA); const TString4 rdoc_umqta = rdoc.get(RDOC_UMQTA); FOR_EACH_PHYSICAL_RDOC(contratto, rm, rigamerce) { const TString& rigamerce_codart = rigamerce->get(RDOC_CODART); //se trova il codart in una delle righe di contratto... if (rdoc_codart == rigamerce_codart) { const real rigamerce_premio = rigamerce->get_real(RC_1_PREMIO); //se il premio non è nullo procede all'aggiornamento del restituito (solo contratti A/R e righe spese) e del bonus (tutti i contratti e righe merce) if (rigamerce_premio != ZERO) { //normalizzazione della qta const TString& umqta_tot = rigamerce->get(RDOC_UMQTA); //prende la UM dal contratto che farà da riferimento! TArticolo articolo(rdoc_codart); const real normalized_rdoc_qta = articolo.convert_to_um(rdoc_qta, umqta_tot, rdoc_umqta, true); //aggiornamento delle righe di tipo spesa (verigh02) per aggiornare le somme restituite nel caso di contratti di anticipo/rifatturazione if (tipo_contratto == 'A' || tipo_contratto == 'R') { FOR_EACH_PHYSICAL_RDOC(contratto, ra, rigacontratto) { //cerca una riga anticipo da evadere sul contratto per aggiornare la somma restituita sull'anticipo if (rigacontratto->is_spese()) { //si informa su quale fosse la somma anticipata const real somma_anticipata = rigacontratto->get_real(RCA_2_ANTICIPATO); //aggiorna la somma restituita dovuta al contratto (parte da zero per ogni elaborazione di NAC) real somma_restituita = rigacontratto->get_real(RCA_2_RESO_CORRENTE); //controlla che il contratto non sia per caso già stato pareggiato! quindi il reso deve essere < dell'anticipato per procedere //la somma restituita deve essere incrementata per la qta di merce (caffè) che c'è sulla riga della fattura in esame... //..moltiplicata per il premio che c'è nella riga di tipo merce del contratto in esame somma_restituita += normalized_rdoc_qta * rigamerce_premio; rigacontratto->put(RCA_2_RESO_CORRENTE, somma_restituita); elaborato = true; break; } } //FOR_EACH_PHYSICAL.. fine casino sulla riga di tipo spese } //if(tipo_contratto == "A"... //questo va bene invece per ogni riga merce (verigh01), sia per contratti di tipo A/R che di tipo P if (rigamerce->is_merce()) { real somma_bonus = rigamerce->get_real(RC_1_BONUS); somma_bonus += normalized_rdoc_qta * rigamerce_premio; rigamerce->put(RC_1_BONUS, somma_bonus); rigamerce->add(RDOC_QTA, normalized_rdoc_qta); //riscrive sul campo di appoggio del contratto elaborato = true; } } //if(rigamerce_premio != ZERO... } //if(rdoc_codart... } //FOR_EACH_PHYSICAL.. return elaborato; } */ void THardy_esselunga::elabora_documenti(const TMask& mask, TISAM_recordset& recset, TLog_report& log) { TProgind pi(recset.items(), TR("Elaborazione documenti in corso..."), true, true); for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { if (!pi.addstatus(1)) break; const long codcf = recset.get(DOC_CODCF).as_int(); // verificare se il cliente appartiene alla dipendenza selezionata e se ha tutti i parametri per poter essere inviato if (check_cliente(codcf)) { TDocumento* doc = new TDocumento(recset.cursor()->curr()); // passo tutte le righe del documento all'AS400recordset FOR_EACH_PHYSICAL_RDOC(*doc, r, rigadoc) { } //FOR_EACH... delete doc; } // if check_cliente... } //for (bool ok = recset.move_first()... //se elaborazione definitiva -> cambia lo stato ai documenti di vendita elaborati, mettendolo uguale.. //..a quello deciso in configurazione const bool definitivo = mask.get_bool(F_DEFINITIVO); if (definitivo) { } } bool THardy_esselunga::check_cliente(const long codcf) { return true; } void THardy_esselunga::elabora(const TMask& mask) { TLog_report log(APPNAME); log.kill_duplicates(); log.log(0, ""); TISAM_recordset recset(""); const long items = genera_recordset(mask, recset); if (items == 0) log.log(1, "Non esistono documenti che soddisfano i parametri selezionati."); elabora_documenti(mask, recset, log); log.print_or_preview(); } void THardy_esselunga::main_loop() { THardy_esselunga_mask mask; while (mask.run() == K_ENTER) elabora(mask); } bool THardy_esselunga::create() { open_files(LF_DOC, LF_RIGHEDOC, 0); return TSkeleton_application::create(); } int ha2100 (int argc, char* argv[]) { THardy_esselunga elabapp; elabapp.run(argc, argv, APPNAME); return 0; }