#include #include #include #include #include #include #include "../ca/calib01.h" #include "../ca/commesse.h" #include "../ca/cfcms.h" #include "rilore.h" #include "cilib.h" #include "ci1350.h" #include "ci1300a.h" /////////////////////////////////////////////////////////// // Report /////////////////////////////////////////////////////////// class TRil_ore_ris_report : public TReport { unsigned int _first_msg; unsigned int _golem_opcode; long _codcf; TString _codtpl; protected: virtual bool use_mask() { return false; } virtual size_t get_usr_words(TString_array& words) const; virtual bool execute_usr_word(unsigned int opcode, TVariant_stack& stack); public: void set_codcf(long codcf) { _codcf = codcf; } void set_codtpl(const char *cod) { _codtpl = cod; } TRil_ore_ris_report(bool mensile, bool beneficiario); }; size_t TRil_ore_ris_report::get_usr_words(TString_array& words) const { TReport::get_usr_words(words); const char* const name[] = { "LOGO_LAVORO", "LOGO_BENEF", NULL }; ((TRil_ore_ris_report*)this)->_first_msg = words.items(); // Calcola il primo numero disponibile ((TRil_ore_ris_report*)this)->_golem_opcode = words.find("GOLEM"); size_t i; for (i = 0; name[i] != NULL; i++) words.add(name[i]); return i; } bool TRil_ore_ris_report::execute_usr_word(unsigned int opcode, TVariant_stack& stack) { bool ok = true; if (opcode >= _first_msg) { opcode -= _first_msg; switch (opcode) { case 0: { TToken_string key("C"); TString id("LOGO_LAV"); id << _codtpl; stack.push(id); key.add(_codcf); stack.push(CLI_OGGETTI); stack.push(key); stack.push(LF_CLIFO); execute_usr_word(21, stack); } break; case 1: { TToken_string key("C"); TString id("LOGO_BENEF"); id << _codtpl; stack.push(id); key.add(_codcf); stack.push(CLI_OGGETTI); stack.push(key); stack.push(LF_CLIFO); execute_usr_word(21, stack); } break; default: ok = false; break; } } else ok = TReport::execute_usr_word(opcode, stack); return ok; } TRil_ore_ris_report::TRil_ore_ris_report(bool mensile, bool beneficiario) : _codcf(0L) { TFilename report_name; if (mensile) report_name = "ci1300a"; else report_name = "ci1300b"; if (beneficiario) report_name << "b"; load(report_name); set_recordset(new TRil_ore_recordset); } /////////////////////////////////////////////////////////// // Maschera /////////////////////////////////////////////////////////// class TRil_ore_ris_mask : public TSimpleAutomask { protected: // virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void elabora_risorsa(const TString& curr_risorsa, const int curr_mese, const bool ignore, TReport& rep) const; const TString & tipostampa() const { return get(F_TIPOSTAMPA); } const bool mensile() const { return tipostampa() == "M";} const bool per_beneficiario() const { return get_bool(F_BENEFICIARIO); } const real proponi_costo(const char *codlist, const char * tipo, const char * codice, const char * tpora, int mese, int anno) const ; public: void elabora() const; TRil_ore_ris_mask(); virtual ~TRil_ore_ris_mask() {} }; TRil_ore_ris_mask::TRil_ore_ris_mask() : TSimpleAutomask("ci1300a") { } /*bool TRil_ore_ris_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { return true; } */ const real TRil_ore_ris_mask::proponi_costo(const char *codlist, const char * tipo, const char * codice, const char * tpora, int mese, int anno) const { real r; const TDate dal(1, mese, anno); TRisoatt_key chiave(codlist, tipo[0], codice, dal, tpora); const TRectype & rec = cache().get("&ROA", chiave); if (rec.empty()) { if (chiave.cod().full() && chiave.tpora().full()) { TModule_table tab("ROA"); tab.put("CODTAB", chiave); const int err = tab.read(); if (err != _isemptyfile) { chiave.overwrite("????????", 21, 8); if (err != _iseof) tab.prev(); if (tab.get("CODTAB").match(chiave)) r = tab.get_real("R1"); } } } else r = rec.get_real("R1"); return r; } void TRil_ore_ris_mask::elabora_risorsa(const TString& curr_risorsa, const int curr_mese, const bool ignore, TReport& rep) const { const int tipo_ordinamento = get_int(F_ORDINAMENTO); const int anno = get_int(F_ANNO); const int mese = mensile() ? curr_mese : 0; const bool calc_ore_lav = rep.field("F1.98") != NULL; //date del periodo TDate inizio_periodo, fine_periodo; ci_inizio_fine_periodo(mensile(), anno, mese, inizio_periodo, fine_periodo); //creare un assoc_array con chiave TToken_string cms-sede-fase(1) o sede-cms-fase(2) in base ai parametri.. //..indicati sulla maschera //se tipo_stampa = 'M'ensile: il contenuto dell'assoc_array sarà: tot_Prev - 31 valori giornalieri Consuntivi - tot_Consuntivo //se tipo_stampa = 'A'nnuale: il contenuto dell'assoc_array sarà: tot_Prev - 12 valori mensili Consuntivi - tot_Consuntivo TAssoc_array righe; TString_array tpass; for (TDate data = inizio_periodo; data <= fine_periodo; ++data) { int i = data - inizio_periodo + 1; if (data.wday() > 5) tpass.add("WE", i); else if (data.is_holiday()) tpass.add("PH", i); } const TVariant tiporisorsa = get(F_RISOATT); //query sul file delle ore in chiave 3: TIPO+TIPORA+CODICE+.....frega niente altro TString query; query << "USE RILORE KEY 3"; query << "\nFROM TIPO=#TIPO TIPORA=#TPRA CODICE=#CODICE"; query << "\nTO TIPO=#TIPO TIPORA=#TPRA CODICE=#CODICE"; TRil_ore_cms_recordset rilore_recset(query); rilore_recset.set_var("#TPRA", tiporisorsa); rilore_recset.set_var("#CODICE", curr_risorsa); if (!ignore && calc_ore_lav)// && rep.field("F1.201") != nullptr) { for (int d = 1; d <= 31; ++d) { TString8 fld = "H0."; fld << 200 + d; if (rep.exist(fld)) rep.field(fld)->set(""); } } //aggiunta Adolfica: lista di commesse da considerare separatamente più commessa borraccione.. //..con tutte le altre TSheet_field& lista = sfield(F_RIGHE); rilore_recset.set_list(lista.rows_array(), ignore); TString tipo_commessa_beneficiario; long codfin = 0L; if (per_beneficiario()) { tipo_commessa_beneficiario = get(F_CODTPL); codfin = get_long(F_CODFIN); } //un giro con le ore a 'P'reventivo, uno con quelle a 'C'onsuntivo for (int i = 0; i < 2; i++) { const TVariant tipo = i == 0 ? "P" : "C"; const char tipo_ora = i == 0 ? 'P' : 'C'; //serve solo per rendere comprensibili gli if( che seguono rilore_recset.set_var("#TIPO", tipo); const long rilore_recset_items = rilore_recset.items(); for (bool ok = rilore_recset.move_first(); ok; ok = rilore_recset.move_next()) { const TString80 codcosto = rilore_recset.get_string(RILORE_CODCOSTO); TString80 codcms = rilore_recset.get_string(RILORE_CODCMS); const TString16 codfase = rilore_recset.get_string(RILORE_CODFASE); //date limite qta ore sul record del file LF_RILORE TDate ini_rilore = rilore_recset.get_date(RILORE_DADATA); TDate fine_rilore = rilore_recset.get_date(RILORE_ADATA); //adatta le date alla commessa se quest'ultima è contenuta nell'intervallo (può essere più breve.. //..dell'intervallo selezionato, oppure sovrapporsi solo parzialmente) //se sta stampando per cdc -> fine_cms e ini_cms sono vuoti se non c'è la cms e non fa la trimmatura TDate inizio_int, fine_int; long giorni_lavorativi = ci_calcola_giorni_lavorativi_intersezione(ini_rilore, fine_rilore, inizio_periodo, fine_periodo, inizio_int, fine_int); //se i giorni lavorativi non ci sono è inutile procedere if (giorni_lavorativi <= 0) continue; const long giorni_lavorativi_rilore = ci_calcola_giorni_lavorativi(ini_rilore, fine_rilore); if (giorni_lavorativi_rilore > 0) { const real tot_ore = rilore_recset.get_real(RILORE_QTAORE); const real tot_ore_uso_risorsa_nel_periodo = tot_ore * giorni_lavorativi / giorni_lavorativi_rilore; const TString8 tpora = rilore_recset.get_string(RILORE_TPORA); const TString8 tpassenza = cache().get("&ORE", tpora, "S2"); //crea la chiave per l'assoc_array TToken_string key; if (ignore) key = OTHER_ACTIVITIES; else { if (per_beneficiario() && codcms.full()) { const TString & codtipo = cache().get(LF_COMMESSE, codcms, COMMESSE_CODTIPO); bool altre = true; if (codtipo == tipo_commessa_beneficiario) { TToken_string key_fin(codcms); key_fin.add("C"); key_fin.add(1); if (atol(cache().get(LF_CFCMS, key_fin, CFCMS_CODCF)) == codfin) altre = false; } if (altre) key = OTHER_ACTIVITIES; } if (key != OTHER_ACTIVITIES) { switch (tipo_ordinamento) { case 1: key.add(codcms); break; case 2: key.add(codcms); key.add(codcosto); break; case 3: key.add(codcms); key.add(codfase); break; case 4: key.add(codcms); key.add(codcosto); key.add(codfase); break; case 5: key.add(codcosto); break; case 6: key.add(codcosto); key.add(codcms); break; case 7: key.add(codcosto); key.add(codfase); break; case 8: key.add(codcosto); key.add(codcms); key.add(codfase); break; default: break; } } } //se la chiave non esiste già nell'assoc_array allora crea l'elemento TToken_string* record = (TToken_string*)righe.objptr(key); if (record == NULL) { record = new TToken_string; righe.add(key, record); } if (tipo_ora == 'P') //'P'reventivo (aggiorna solo il totale) { real prev = record->get(0); prev += tot_ore_uso_risorsa_nel_periodo; record->add(prev.string(), 0); } else //'C'onsuntivo (aggiorna tutte le caselle dei giorni lavorativi) { const real ore_al_giorno = tot_ore / giorni_lavorativi_rilore; for (TDate data = inizio_int; data <= fine_int; ++data) { if (giorni_lavorativi_rilore == 1 || ci_is_ferial_day(data)) { const int index = mensile() ? data.day() : data.month(); real prev = record->get(index); prev += ore_al_giorno; record->add(prev.string(), index); real tot = record->get(32); tot += ore_al_giorno; record->add(tot.string(), 32); real totcosto = record->get(34); real costo = rilore_recset.get_real(RILORE_COSTO); if (costo == ZERO) { TString16 codlis = rilore_recset.get_string(RILORE_CODLIST); if (codlis.blank()) codlis = cache().get(LF_COMMESSE, codcms, COMMESSE_LISRILCN); costo = proponi_costo(codlis, rilore_recset.get_string(RILORE_TIPORA), rilore_recset.get_string(RILORE_CODICE), tpora, data.month(), data.year()); } totcosto += ore_al_giorno * costo; record->add(totcosto.string(), 34); record->add(costo.string(), 35); int i = data - inizio_periodo + 1; if (tpassenza.full()) { TString8 tp = tpass.objptr(i) == nullptr ? EMPTY_STRING : tpass.row(i); if (tp.blank()) tpass.add(tpassenza, i); } else if (calc_ore_lav) { real totorelav = record->get(33); totorelav += ore_al_giorno; record->add(totorelav.string(), 33); } } } //for (TDate data = inizio_int.. } //if (tipo_ora == 'P').. } //if (giorni_lavorativi_rilore > 0).. } //for (bool ok = rilore_recset.move_first();.. } //for (int i = 0; i < 2; i++)... if (calc_ore_lav && rep.field("H0.201") != nullptr) { for (int d = 1; d <= 31; ++d) { TString8 fld = "H0."; fld << 200 + d; TString val = rep.field(fld)->get().as_string(); if (val.blank()) { if (tpass.objptr(d) != nullptr) { const TString8 tp = tpass.row(d); rep.field(fld)->set(tp); } else rep.field(fld)->set(""); } } } //prende il recordset in opera dal report per fargli le set_var TRil_ore_recordset* recset = (TRil_ore_recordset*)rep.recordset(); //tenta la mask2report per far apparire sul report i campi di selezione della maschera rep.mask2report(*this); TString4 code; code.format("%02d", curr_mese); recset->set_var("#MESE", code, true); //finita l'elaborazione che ha riempito l'assoc_array, asegna il medesimo ad un.. //..csv_recordset e poi sbatte quest'ultimo (ordinato) nel report //Il tutto nel magico metodo che segue! ci_fill_recset_from_ass(righe, rep); //campo a mano per fare scattare la mask2report() rep.recordset()->set_var("#CODRIS", curr_risorsa, true); } //metodo di alto livello per filtrare su ris/att e chiamare i metodi di livello inferiore per elaborare la singola ris/att void TRil_ore_ris_mask::elabora() const { //book di stampa TReport_book book; //stampa mensile o annuale? TRil_ore_ris_report rep(mensile(), per_beneficiario()); rep.set_codcf(get_long(F_CODFIN)); rep.set_codtpl(get(F_CODTPL)); int da_mese = 1; int a_mese = 1; if (mensile()) { da_mese = get_int(F_DA_MESE); a_mese = get_int(F_A_MESE); } if (rep.field(REP_FIELD("H1", REP_DATE)) != nullptr) { const bool show = !get_bool(F_STAMPADATA); rep.field(REP_FIELD("H1", REP_DATEP))->show(show); rep.field(REP_FIELD("H1", REP_DATE))->show(show); } //giro su tutti i mesi; se stampa annuale o mese unico -> un giro solo for (int m = da_mese; m <= a_mese; m++) { if (mensile()) format_report_month(get_int(F_ANNO), m, rep); //query sulla tabella interessata (risorse o attrezzature) TString16 da_ris_att, a_ris_att; TString query_ris_att; TString msg; const char tiporisorsa = get(F_RISOATT)[0]; if (tiporisorsa == 'R') { da_ris_att = get(F_DA_CODRIS); a_ris_att = get(F_A_CODRIS); query_ris_att << "USE RSS"; msg << "Scansione risorse..."; } else { da_ris_att = get(F_DA_CODATT); a_ris_att = get(F_A_CODATT); query_ris_att << "USE ATR"; "Scansione attrezzature..."; } query_ris_att << "\nFROM CODTAB=#DACODICE"; query_ris_att << "\nTO CODTAB=#ACODICE"; TISAM_recordset recset_ris_att(query_ris_att); recset_ris_att.set_var("#DACODICE", da_ris_att); recset_ris_att.set_var("#ACODICE", a_ris_att); const long recset_ris_att_items = recset_ris_att.items(); TSheet_field& lista = sfield(F_RIGHE); //se la stampa ha come chiave principale il CDC, lo sheet (che e' nascosto!) va vuotato in quanto potrebbe avere elementi.. //..dovuti al profilo della maschera che produrrebbero una stampa non desiderata (per ora!, verra' il momento in cui il CRPA.. //..cambiera' idea..) const int tipo_ordinamento = get_int(F_ORDINAMENTO); if (tipo_ordinamento >= 5) lista.reset(); //Come gestire la lista delle commesse particolari //a) nel caso la lista sia vuota il giro di stampa è unico, considerando tutte le cms/cdc //b) nel caso la lista abbia elementi(cms/cdc), viene fatto un primo giro sui soli elementi della lista,... //poi un successivo su tutte le cms/cdc che non apparivano nella lista const int ignore_start = 0; const int ignore_end = !lista.empty(); TProgind pi(recset_ris_att_items, msg, true, true); //per ogni risorsa/attrezzatura dell'elenco genera un report singolo che viene riempito nella elabora_risorsa e.. //..aggiunto al book per la stampa finale for (bool ok = recset_ris_att.move_first(); ok; ok = recset_ris_att.move_next()) { if (!pi.addstatus(1)) break; const TString80 curr_risorsa = recset_ris_att.cursor()->curr().get("CODTAB"); //setta un nuovo recset al report: se non lo facesse il recset sarebbe sempre il medesimo per ogni.. //..risorsa (ovvero assoc_array) e quindi si incrementerebbe all'ignoranza TRil_ore_recordset* recset = new TRil_ore_recordset; rep.set_recordset(recset); for (int ignore = ignore_start; ignore <= ignore_end; ignore++) elabora_risorsa(curr_risorsa, m, ignore!=0, rep); //stampa un report per risorsa book.add(rep); } ////for (bool ok = recset_ris_att.move_first()... } //for (int m = da_mese; .. //e alla fine stampa il book book.preview(); } /////////////////////////////////////////////////////////// // Applicazione /////////////////////////////////////////////////////////// class TRil_ore_ris : public TSkeleton_application { protected: public: virtual void main_loop(); }; void TRil_ore_ris::main_loop() { TRil_ore_ris_mask mask; while (mask.run() == K_ENTER) { mask.elabora(); } } int ci1300(int argc, char* argv[]) { TRil_ore_ris sd; sd.run(argc, argv, "Rilevazione ore per Risorsa - Attrezzatura"); return 0; }