// Applicazione di generazione reports & stampe per MRP #include #include #include #include #include #include "mrplib.h" #include "../ve/velib.h" #include "../mg/mglib.h" #include "mr1.h" #include "mr1100a.h" #include #include #include #define LF_MRPREP 132 #define LAST_BUCKET 12 // Tipi di stampa enum tipo_stampa { articoli, // produzione articoli nel tempo linee, // carico linee scheduling, // scheduling delle linee available // Tipo di stampa non definita: ordinata per articoli e stampa del carico della linea }; // I tipi di stampa si identificano secondo la seguente tabella, tramite l'intersezione // tra l'ordinamento ed il valore impostati: /* |----------------------+ |quantita | carico | -----------+----------------------- articoli |articoli | available| -----------+----------------------+ linea |scheduling | linee | -----------+----------------------- */ enum tipo_ordinamento { articolo, linea }; enum tipo_valore { quantita, carico }; enum tipo_dettaglio { det_articolo, det_giacenza, det_impianto, det_linea }; /////////////////////////////////////////////////////////// // _TCapacitaLinea, usato per calcolare le capacita' delle linee /////////////////////////////////////////////////////////// class _TCapacitaLinea : public TObject { TArray _cap_min, // Array 1..LAST_BUCKET-1 di capacita' minime _cap_max; // Array 1..LAST_BUCKET-1 di capacita' massime public: TArray& cap_min() { return _cap_min; } TArray& cap_max() { return _cap_max; } _TCapacitaLinea() ; virtual ~_TCapacitaLinea() {} }; _TCapacitaLinea::_TCapacitaLinea() { for (int i = 0; i= 0, "Invalid TMRP_rep_record_array ", b); TMRP_rep_record* qta = (TMRP_rep_record*)_buckets.objptr(b); if (qta == NULL) { qta = new TMRP_rep_record; _buckets.add(qta, b); } return *qta; } /////////////////////////////////////////////////////////// // TMRP_rep_line /////////////////////////////////////////////////////////// class TMRP_rep_line : public TSortable { TCodice_articolo _codart; TString16 _giac, _imp, _lin, _um; TMRP_rep_record_array _bucket; protected: virtual int compare(const TSortable& s) const; public: const TCodice_articolo& codice() const { return _codart; } const TString& livgiac() const { return _giac; } const TString& codimp() const { return _imp; } const TString& codlin() const { return _lin; } const TString& um() const { return _um; } int last() const { return _bucket.last(); } int pred(int i) const { return _bucket.pred(i); } real& qta(int b) { return _bucket[b]._qta; } void fill(TRectype& record, TAssoc_array* capacita = NULL); TMRP_rep_line(const TCodice_articolo& codart, const TString& giac, const TString& imp, const TString& lin, const TString& um); virtual ~TMRP_rep_line() { } }; void TMRP_rep_line::fill(TRectype& record, TAssoc_array* capacita) { record.zero(); record.put("TIPO", "R"); record.put("CODART", _codart); record.put("LIVELLO", _giac); record.put("IMPIANTO", _imp); record.put("LINEA", _lin); record.put("UM", _um); TString16 campo; for (int b = last(); b >= 0; b = pred(b)) { switch(b) { case 0: campo = "QTAFIRST"; break; case LAST_BUCKET: campo = "QTALAST"; break; default: campo.format("QTA%d", b); break; } record.put(campo, qta(b)); } if (capacita) for (b=1; bobjptr(_lin); if (cl) { TArray& cmin = cl->cap_min(); TArray& cmax = cl->cap_max(); campo.format("CMIN%d", b); record.put(campo, (real&)cmin[b-1]); // Capacita' minima... campo.format("CMAX%d", b); record.put(campo, (real&)cmax[b-1]); // e massima } } } int TMRP_rep_line::compare(const TSortable& s) const { const TMRP_rep_line& c = (const TMRP_rep_line&)s; int cmp = _codart.compare(c._codart); if (cmp == 0) { cmp = _giac.compare(c._giac); if (cmp == 0) { cmp = _imp.compare(c._imp); if (cmp == 0) { cmp = _lin.compare(c._lin); if (cmp == 0) cmp = _um.compare(c._um); } } } return cmp; } TMRP_rep_line::TMRP_rep_line(const TCodice_articolo& codart, const TString& giac, const TString& imp, const TString& lin, const TString& um) : _codart(codart), _giac(giac), _imp(imp), _lin(lin), _um(um) { } /////////////////////////////////////////////////////////// // TMRP_rep_lines /////////////////////////////////////////////////////////// class TMRP_rep_lines : public TMRP_array { protected: virtual TSortable* new_obj(const TToken_string& key) const; public: TMRP_rep_line* find(const TCodice_articolo& codart, const TString& giac, const TString& imp, const TString& lin, const TString& um, bool create); TMRP_rep_line& operator[](long n) const { return (TMRP_rep_line&)find_obj(n); } }; TSortable* TMRP_rep_lines::new_obj(const TToken_string& key) const { TCodice_articolo art; key.get(0, art); TString gia; key.get(1, gia); TString imp; key.get(2, imp); TString lin; key.get(3, lin); TString um ; key.get(4, um); return new TMRP_rep_line(art, gia, imp, lin, um); } TMRP_rep_line* TMRP_rep_lines::find(const TCodice_articolo& codart, const TString& giac, const TString& imp, const TString& lin, const TString& um, bool create) { _key = codart; _key.add(giac); _key.add(imp); _key.add(lin); _key.add(um); TSortable* s = create ? add_obj(_key) : find_obj(_key); return (TMRP_rep_line*)s; } /////////////////////////////////////////////////////////// // MRP report generator mask /////////////////////////////////////////////////////////// class TRepgen_mask : public TCalendar_mask { protected: void calcola_capacita(TAssoc_array&) const ; bool test_tipodoc_num( const TSheet_field &sheet_num , const TSheet_field &sheet_type) ; virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void round_field(TMask_field& fld, bool up) const; public: int round_date(TDate& date, bool up) const; bool elabora() const; TRepgen_mask(); virtual ~TRepgen_mask() { } }; bool TRepgen_mask::test_tipodoc_num(const TSheet_field &sheet_num ,const TSheet_field &sheet_type) { TString16 tipo; TString_array& nums = sheet_num.rows_array(); TString_array& types = sheet_type.rows_array(); for (int j = types.items()-1; j >= 0; j--) { bool ok=FALSE; tipo = types.row(j).get(0) ; for (int i = nums.items()-1; i >= 0; i--) { TCodice_numerazione num(nums.row(i).get(0)); for (int n = num.ntipi_doc()-1;n >= 0; n--) { const char* t = num.tipo_doc(n); if (tipo == t) ok = TRUE; } } if (!ok) return error_box("Il tipo '%s' non appartiene a nessuna delle numerazioni scelte",(const char*)tipo); } return TRUE; } int TRepgen_mask::round_date(TDate& date, bool up) const { // Dimensione del bucket in giorni int bucket_size = get_int(F_BUCKET) * 7; if (bucket_size < 7) bucket_size = 7; // Riporta la data al primo lunedi prima dell'inizio TDate inizio = get(F_DADATA); const int wday = inizio.wday(); if (wday > 1) inizio -= wday-1; // Calcola il bucket di appartenenza const int days = int(date - inizio); const int bucket = days / bucket_size; if (up) // Arrotonda alla fine del bucket date = inizio + long((bucket+1) * bucket_size - 1); else // Arrotonda all'inizio del bucket date = inizio + long(bucket * bucket_size); return bucket; } void TRepgen_mask::round_field(TMask_field& fld, bool up) const { TDate date = fld.get(); if (date.ok()) { round_date(date, up); fld.set(date); } } void TRepgen_mask::calcola_capacita(TAssoc_array& capacita) const { if (capacita.items() == 0) return; const bool carico_uomo = get_bool(F_MANLOAD); const TDate df(get_date(F_DADATA)); const TDate dt(get_date(F_ADATA)); TDate wd1,wd2; TString16 codimp; capacita.restart(); TProgind pi(capacita.items(), "Calcolo capacita linee", FALSE, TRUE); THash_object* ho = capacita.get_hashobj(); for (;ho != NULL; ho = capacita.get_hashobj()) { pi.addstatus(1L); const TString& linea = ho->key(); _TCapacitaLinea& cl = (_TCapacitaLinea&) ho->obj(); TLinea_prod lp(linea); codimp = lp.codimp(); TMRP_calendar& mc = TMRP_time::get_calendar(codimp, linea); TArray& cap_min = cl.cap_min(); TArray& cap_max = cl.cap_max(); for (wd1 = df; wd1 <= dt; ++wd1) // Piglia tutte le date nel range! (very, very heavy...) { wd2 = wd1; const int bucket = round_date(wd2, FALSE); // da 0 a 10 al massimo if (bucket > 10) break; // Fine real & v1 = (real&) cap_min[bucket]; v1 += carico_uomo ? mc.add_oreuomo(v1, wd1) : mc.add_oremacchina(v1, wd1); real & v2 = (real&) cap_max[bucket]; v2 += carico_uomo ? mc.add_oreuomo_max(v2, wd1) : mc.add_oremacchina_max(v2, wd1); } } } bool TRepgen_mask::elabora() const { TRelation rel(LF_RIGHEDOC); TCursor cur(&rel); const TRectype& riga = cur.curr(); TRectype filter_fr(riga), filter_to(riga); const TDate date_fr = get(F_DADATA); const int year_fr = date_fr.year(); TDate date_to = get(F_ADATA); const int year_to = date_to.year(); const int bucket_size = get_int(F_BUCKET) * 7; const TExplosion_grouping raggr = (TExplosion_grouping)get_int(F_RAGGRUM); const tipo_valore ts = (tipo_valore) get_int(F_VAL2PRINT); const bool carico_uomo = get_bool(F_MANLOAD); const int last_bucket = round_date(date_to,TRUE)+1; TString16 ws; TDistinta_tree distinta; TArray lav_array; TMRP_rep_lines articles; TAssoc_array capacita; TString msg; TSheet_field& numerazioni = sfield(F_NUMERAZIONI); FOR_EACH_SHEET_ROW(numerazioni, r, row) { const TString16 codnum = row->get(0); // Filtra il cursore in modo da limitarlo alla numerazione // corrente ed agli anni specificati dalle due date limite filter_fr.put(RDOC_PROVV, "D"); filter_fr.put(RDOC_CODNUM, codnum); filter_fr.put(RDOC_ANNO, year_fr); filter_to.put(RDOC_PROVV, "D"); filter_to.put(RDOC_CODNUM, codnum); filter_to.put(RDOC_ANNO, year_to); cur.setregion(filter_fr, filter_to); const long items = cur.items(); cur.freeze(TRUE); msg = "Elaborazione numerazione "; msg << codnum; TProgind pi(items, msg, FALSE, TRUE); // Scandisce le righe dei documenti for (cur = 0; cur.pos() < items; ++cur) { pi.addstatus(1); const TCodice_articolo art = riga.get(RDOC_CODARTMAG); if (art.not_empty()) { TDate datacons = riga.get(RDOC_DATACONS); // Seleziona tutte le righe! Altrimenti LAST_BUCKET non viene mai settato //if (datacons <= date_to) { real qta; if (!riga.get_bool(RDOC_RIGAEVASA)) { qta = riga.get_real(RDOC_QTA); qta -= riga.get_real(RDOC_QTAEVASA); } // Seleziona le righe articolo non ancora evase if (qta > ZERO) { const TString16 liv = riga.get(RDOC_LIVELLO); const TString16 imp = riga.get(RDOC_IMPIANTO); const TString16 lin = riga.get(RDOC_LINEA); const TCodice_um um = riga.get(RDOC_UMQTA); TQuantita q(art, um, qta); int bucket = 0; if (datacons >= date_fr) { bucket = round_date(datacons, FALSE) + 1; if (bucket > last_bucket) bucket = LAST_BUCKET; } // Calcoli per carico if (ts == carico) { distinta.set_root(riga); real ore,tot; TRiga_esplosione * llav = distinta.first_labor(lav_array, raggr); TLavorazione * lavorazione = TDistinta_tree::find_labor(llav); while (llav) { const int linea = lavorazione->find_linea(lin); const real prod_linea = lavorazione->produttiv_linea(linea); ore = (llav->val() * lavorazione->um_temporale().converti_in_ore()) / prod_linea; if (carico_uomo) ore *= lavorazione->numpers_linea(linea); //rep.qta(bucket) += ore; tot += ore; llav = distinta.next_labor(lav_array); } if (tot > ZERO) { TMRP_rep_line& rep = *articles.find(art, liv, imp, lin, ws, TRUE); rep.qta(bucket) += tot; } // Sbatte nella cache le linee di cui dopo calcolera' le capacita' minime e massime // In modo che il calcolo venga effettuato una volta sola per ogni linea. if (capacita.objptr(lin) == NULL) capacita.add(lin, new _TCapacitaLinea); // Vuoto per ora... lo riempie poco piu' giu' } else // Produzione articoli nel tempo & scheduling linee { TMRP_rep_line& rep = *articles.find(art, liv, imp, lin, q.um(), TRUE); switch (raggr) { case RAGGR_EXP_UMBASE: q.convert2umbase(); break; case RAGGR_EXP_UMDIST: q.convert2umdist(); break; default: break; } rep.qta(bucket) += q.val(); } } } } } cur.freeze(FALSE); } if (ts == carico && get_bool(F_CAPACITA)) calcola_capacita(capacita); const long total = articles.items(); TProgind pi(total, "Generazione file", FALSE, TRUE); TMask_field& fld = field(F_FILENAME); TFilename filename = fld.get(); if (filename.empty()) filename.temp("mrprep"); fld.set(filename); filename.insert("%"); TIsamtempfile rep(LF_MRPREP, filename); // Scrive la testata (Record tipo "H"); rep.put("TIPO","H"); rep.put("CODART", date_fr.string()); rep.put("LIVELLO", get(F_ADATA)); rep.put("IMPIANTO", bucket_size); rep.put("LINEA", ts == quantita ? "Q" : "C"); rep.write(); for (long i = 0; i < total; i++) { pi.addstatus(1); articles[i].fill(rep.curr(), ts == carico ? &capacita : NULL); int err = rep.write(); if (err != NOERR) rep.rewrite(); } return rep.good(); } bool TRepgen_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch(o.dlg()) { case F_DADATA: if (e == fe_modify) round_field(o, FALSE); break; case F_ADATA: if (e == fe_modify) round_field(o, TRUE); break; case F_BUCKET: if (e == fe_modify) { round_field(field(F_DADATA), FALSE); round_field(field(F_ADATA), TRUE); } break; case F_NUMERAZIONI: if (e == fe_init) { TSheet_field& s = (TSheet_field&)o; if (s.items() == 0) { s.row(0); s.force_update(); } } if (e == fe_close) { const TSheet_field& s = (const TSheet_field&)o; FOR_EACH_SHEET_ROW_BACK(s, r, row) if (!row->empty_items()) return TRUE; return error_box("E' necessario inserire almeno una numerazione"); } break; case F_TIPI: if (e == fe_init) { TSheet_field& s = (TSheet_field&)o; if (s.items() == 0) { s.row(0); s.force_update(); } } if (e == fe_close) { const TSheet_field& s = (const TSheet_field&)o; FOR_EACH_SHEET_ROW_BACK(s, r, row) if (!row->empty_items()) { const bool ok=test_tipodoc_num(sfield(F_NUMERAZIONI), s ); return ok; } return error_box("E' necessario inserire almeno una riga"); } break; case F_YEAR: case F_IMPIANTO: case F_LINEA: if (e == fe_modify) update_calendar(F_CALENDAR, F_YEAR, F_IMPIANTO, F_LINEA); break; case DLG_PRINT: case DLG_ELABORA: if (e == fe_button) { if (check_fields()) save_profile(); if (o.dlg() == DLG_ELABORA) elabora(); } break; default: break; } return TRUE; } TRepgen_mask::TRepgen_mask() : TCalendar_mask("mr1100a") { load_profile(); } /////////////////////////////////////////////////////////// // MRP Form /////////////////////////////////////////////////////////// class TMRP_form : public TForm { TCodgiac_livelli *_codgiac; int _level; protected: virtual bool validate(TForm_item &, TToken_string &); // gestione dei messaggi estesi nei campi public: TMRP_form(const char* name, TCodgiac_livelli* c, int l); virtual ~TMRP_form() {} ; }; TMRP_form::TMRP_form(const char* name, TCodgiac_livelli* c, int l) : TForm(name) { _codgiac = c; _level = l; } bool TMRP_form::validate(TForm_item &cf, TToken_string &s) { const TString code(s.get(0)); if (code == "_MRP") { TLocalisamfile& rep = cf.form().cursor()->file(); TString action(s.get(1)); TString livello, descr; if (action == "DESCRLIV") { if (_level > 0) livello = rep.get("LIVELLO"); if (livello.not_empty()) { for (int lev=1; lev <= _level; lev++) { if (!_codgiac->enabled(lev)) continue; const int starts = _codgiac->code_start(lev) -1; const int length = _codgiac->code_length(lev); descr << "/"; descr << livello.mid(starts,length); } descr << " " << _codgiac->name(_level); descr << " " << _codgiac->group_descr(livello,_level); } cf.set(descr); } else if (action == "LOAD") { //CALCOLO percentuale carico // MESSAGE _MRP,LOAD,, // formula: #id campo1 * 100 / #id campo2 // prende i contenuti dei campi specificati e ne calcola il rapporto % come indicato real v1(cf.find_field(s.get(2)).get()); real v2(cf.find_field(s.get(3)).get()); v1 *= 100; if (v2 != ZERO) v1 /= v2; if (v1 > ZERO && v1 <= 100.0) cf.set(v1.string("##@,@@ %")); else if (v1 <= ZERO) cf.set(""); else cf.set("*****"); } // Ignore any other command } return TForm::validate(cf, s); } /////////////////////////////////////////////////////////// // MRP report file generator /////////////////////////////////////////////////////////// class TMRP_repgen : public TSkeleton_application { TRepgen_mask * _m; TMRP_form * _form; TLocalisamfile * _mrprep; TCodgiac_livelli *_codgiac; int _livello; tipo_ordinamento _tipo_ord; tipo_valore _tipo_val; tipo_dettaglio _dettaglio; protected: void set_buckets_description(); void set_buckets(); void set_form(); virtual bool create(); virtual bool destroy(); virtual void main_loop(); public: TMRP_repgen() { _m = NULL; } virtual ~TMRP_repgen() {} }; bool TMRP_repgen::create() { _m = new TRepgen_mask; _mrprep = new TLocalisamfile(LF_MRPREP); _codgiac = new TCodgiac_livelli; if (!_codgiac->enabled()) _m->hide(F_LIVDET); return TSkeleton_application::create(); } bool TMRP_repgen::destroy() { delete _codgiac; if (_m) delete _m; if (_mrprep) delete _mrprep; return TSkeleton_application::destroy(); } void TMRP_repgen::set_buckets_description() { TString descr; TDate fd = _m->get_date(F_DADATA); TDate td = _m->get_date(F_ADATA); TConfig ini(CONFIG_DITTA, "mr"); const bool week_complete = ini.get_bool("WEEKCOMPLETE"); int bucket_size = _m->get_int(F_BUCKET) * 7; if (bucket_size < 7) bucket_size = 7; int weekd, yeard; const short first_id = 3; const short last_id = 15; --fd; descr.format("\nAl %s", (const char*)fd); if (bucket_size == 7) { fd.get_week_year(weekd, yeard, week_complete); descr << "\nSett. " << weekd << ' ' << yeard; } _form->find_field('B', odd_page, first_id).set_col_head(descr); TDate wd; for (;fd <= td;) { ++fd; descr.format("Dal %s\nAl ", (const char*)fd); fd += bucket_size-1; wd = fd; descr << (const char*)fd; const short id = first_id+_m->round_date(wd,FALSE)+1; if (id >= last_id) break; if (bucket_size == 7) { wd.get_week_year(weekd, yeard, week_complete); descr << "\nSett. " << weekd << ' ' << yeard; } _form->find_field('B', odd_page, id).set_col_head(descr); } descr.format("Dal %s", (const char*)wd); if (bucket_size == 7) { wd.get_week_year(weekd, yeard, week_complete); descr << "\n\nSett. " << weekd << ' ' << yeard; } _form->find_field('B', odd_page, last_id).set_col_head(descr); } void TMRP_repgen::set_buckets() { TString tmp; TDate last_date = _m->get_date(F_ADATA); // Calcola l'ultimo bucket visibile: // Il bucket iniziale e quello finale dovrebbero essere sempre visibili const short last_bucket = _m->round_date(last_date,TRUE)+1; // Disabilita le colonne in base al numero di buckets da visualizzare const short first_id = 4; // Bucket 1 const short last_id = 14; // Bucket 11 for (short id = first_id+last_bucket; id <= last_id; id++) _form->find_field('B',odd_page,id).disable(); // Nella stampa scheduling linee, non esiste un totale per linea/impianto ma per articolo/liv giacenza for (id = first_id+last_bucket+100; id <= (last_id+100); id++) _form->find_field('B',odd_page,id).disable(); set_buckets_description(); // Show delle subsections necessarie TToken_string sections; const bool tl = _tipo_ord == linea; switch (_dettaglio) { case det_articolo: sections = tl ? "IMPIANTI|LINEE" : ""; break; case det_giacenza: sections = tl ? "IMPIANTI|LINEE|ARTICOLI" : "ARTICOLI"; break; case det_impianto: sections = tl ? "" : "ARTICOLI|LIVELLI"; break; case det_linea: sections = tl ? "IMPIANTI" : "ARTICOLI|LIVELLI|IMPIANTI"; break; default: break; } const int items = sections.items(); for (int i=0; ifind_field('B', odd_page, sections.get(i)).show(); if ((tl && _dettaglio == det_giacenza) || (!tl && _dettaglio >= det_giacenza)) if (_livello > 0) { tmp.format("LIVELLO[1,%d]", _codgiac->packed_length(_livello)); _form->find_field('B', odd_page, "LIVELLI").setcondition(tmp,_strexpr); } if (tl && _m->get_bool(F_CAPACITA)) // Abilitato il calcolo capacita/carico linea? { _form->find_field('B', odd_page, 238).show(); const short lid = 240 + (last_bucket >= LAST_BUCKET ? 11 : last_bucket); for (short id = 240; idfind_field('B', odd_page, id).show(); } if (tl && _tipo_val == quantita) // Stampa scheduling, disabilita totali per linea/impianto) { // Abilita i campi per l'unita di misura sui totali per livello giac. e articolo _form->find_field('B', odd_page, 2).show(); _form->find_field('B', odd_page, 302).show(); _form->find_field('B', odd_page, 402).show(); _form->find_field('B', odd_page, 502).show(); for (short id = 201; id <= 215; id++) _form->find_field('B', odd_page, id).hide(); // Riga totale linea for (id = 101; id <= 115; id++) _form->find_field('B', odd_page, id).hide(); // Riga totale impianto } if (!tl && _tipo_val == carico) // Stampa carico per articoli { // Nasconde la colonna delle unita' di misura. // Il calcolo capacita' non ha senso e quindi viene omesso in // stampa, sebbene sia possibile effettuarne il calcolo. _form->find_field('B', odd_page, 2).hide(); _form->find_field('B', odd_page, 102).hide(); _form->find_field('B', odd_page, 202).hide(); _form->find_field('B', odd_page, 302).hide(); _form->find_field('B', odd_page, 402).hide(); } // Prende il titolo della stampa dal nome profilo _form->find_field('H', odd_page,4).set(_m->get(DLG_PROFILE)); } void TMRP_repgen::set_form() { TString expr,tmp; TString from(_m->get(_tipo_ord == articolo ? F_ARTFROM : F_IMPIANTOFROM)); TString to(_m->get(_tipo_ord == articolo ? F_ARTTO : F_IMPIANTOTO)); expr.format("(TIPO==\"R\")"); if (_tipo_ord == articolo) { if (from.not_empty()) { expr << "&&"; tmp.format("(CODART>=\"%s\")",(const char*)from); expr << tmp; } if (to.not_empty()) { if (expr.not_empty()) expr << "&&"; tmp.format("(CODART<=\"%s\")",(const char*)to); expr << tmp; } } else { if (from.not_empty()) { expr << "&&"; tmp.format("(IMPIANTO>=\"%s\")",(const char*)from); expr << tmp; } if (to.not_empty()) { if (expr.not_empty()) expr << "&&"; tmp.format("(IMPIANTO<=\"%s\")",(const char*)to); expr << tmp; } from = _m->get(F_LINEAFROM); to = _m->get(F_LINEAFROM); if (from.not_empty()) { if (expr.not_empty()) expr << "&&"; tmp.format("(LINEA>=\"%s\")",(const char*)from); expr << tmp; } if (to.not_empty()) { if (expr.not_empty()) expr << "&&"; tmp.format("(LINEA<=\"%s\")",(const char*)to); expr << tmp; } } if (expr.not_empty()) // Filtronzo... il filtro gonzo _form->cursor()->setfilter(expr); set_buckets(); } void TMRP_repgen::main_loop() { while (_m->run() != K_QUIT) { const bool use_file = _m->get_bool(F_USAFILE); if (use_file || _m->elabora()) { _tipo_ord = (tipo_ordinamento) _m->get_int(F_ORDINAMENTO); _tipo_val = (tipo_valore) _m->get_int(F_VAL2PRINT); _livello = _m->get_int(F_LIVDET); TFilename fname(_m->get(F_FILENAME)); // Presente 24 ore su 24 fname.insert("%"); // e questo dove lo mettiamo? const bool delfile = !_m->get_bool(F_GENREPORT) && !use_file; if (delfile) _m->reset(F_FILENAME); // Utilizza questo file per la stampa del form TIsamtempfile * report = new TIsamtempfile(LF_MRPREP,fname, FALSE, delfile); TRelation* rel; _dettaglio = (tipo_dettaglio) _m->get_int(_tipo_ord == articolo ? F_DETTAGLIO1 : F_DETTAGLIO2); _form = new TMRP_form(_tipo_ord == articolo ? "mr1100a" : "mr1100b", _codgiac, _livello); rel = _form->relation(); rel->replace(report); set_form(); const int hh = 7; const int fl = printer().formlen(); int rows[4]; // Righe orizzontali rows[0] = hh-4; rows[1] = hh; rows[2] = fl; rows[3] = 0; _form->genera_intestazioni(odd_page, hh-3); _form->genera_fincatura(odd_page, hh-4, fl, rows); // stampa if (_form->cursor()->items() > 0) _form->print(); // report non va cancellato, poiche' ne viene fatta la sostituzione nella relazione del form // quindi la delete viene gia' fatta alla distruzione di _form delete _form; } } } int mr1100(int argc, char* argv[]) { TMRP_repgen a; a.run(argc, argv, "Generazione MRP reports"); return 0; }