#include "mrplib.h" #include #include #include #include #include #include //*********************************** // Utility //*********************************** TMRP_config & mrp_config() { static TMRP_config *_confditta=NULL; if (_confditta==NULL) _confditta= new TMRP_config(); return *_confditta; } int TMRP_config::ora_inizio_turno(int i) { return (int)inizio_turno(i) / 60; // numero di minuti } int TMRP_config::min_inizio_turno(int i) { return (int)inizio_turno(i) % 60; // numero di minuti } int TMRP_config::inizio_turno(int i) { return get_int("TINIZIO","mr", i); } int TMRP_config::ore_durata_turno(int i) { return (int)durata_turno(i) / 60; } int TMRP_config::min_durata_turno(int i) { return (int)durata_turno(i) % 60; } int TMRP_config::durata_turno(int i) { return get_int("TDURATA", "mr", i); } int TMRP_config::numpers_turno(int t) { return get_int("NUMPERS", "mr", t); } void TMRP_config::set_inizio_turno(int i,int ore, int minuti) { const int time = ore * 60 + minuti; set_inizio_turno(i,time); } void TMRP_config::set_durata_turno(int i,int ore, int minuti) { const int time = ore * 60 + minuti; set_durata_turno(i,time); } void TMRP_config::set_inizio_turno(int i,int time) { set("TINIZIO", time, "mr", true, i); } void TMRP_config::set_durata_turno(int i,int time) { set("TDURATA", time, "mr", true, i); } /////////////////////////////////////////////////////////// // TMRP_time ////////////////////////////////////////////////////////// TAssoc_array TMRP_time::_frate_indovino; TMRP_calendar& TMRP_time::get_calendar(const char* codimp,const char* codlin) { TToken_string k; k.add(codimp); k.add(codlin); TMRP_calendar* cal = (TMRP_calendar*)_frate_indovino.objptr(k); if (cal == NULL) { if (_frate_indovino.items() > 64) // troppi calendari fanno male alla salute... { const THash_object* rnd = _frate_indovino.random_hash_object(); if (rnd != NULL) _frate_indovino.remove(rnd->key()); // Cancella uno a caso } cal = new TMRP_calendar(codlin, codimp); _frate_indovino.add(k, cal); } return *cal; } TMRP_calendar& TMRP_time::calendario() { return TMRP_time::get_calendar(_imp, _lin); } int TMRP_time::compare(const TSortable& s) const { const TMRP_time& t = (const TMRP_time&)s; int res; if (_date == t._date) res = _hour - t._hour; else res = _date > t._date ? +1 : -1; return res; } TMRP_time& TMRP_time::add_time(int days, long hours, bool macchina) { const TMRP_calendar& cal = calendario(); if (days != 0) { cal.next_working_day(_date, days); _hour = 0; } while (hours != 0) { real junk; const int ore = macchina ? cal.add_oremacchina(junk, _date) : cal.add_oreuomo(junk, _date); const long tot = _hour + hours; if (tot < 0 || tot > ore) { if (hours >= 0) { cal.next_working_day(_date); hours -= ore - _hour; _hour = 0; } else { cal.prev_working_day(_date); hours += _hour; _hour = macchina ? cal.add_oremacchina(junk, _date) : cal.add_oreuomo(junk,_date); } } else { _hour = int(tot); hours = 0; } } return *this; } void TMRP_time::set(const TDate& d, int h, const char* imp, const char* lin) { _date = d; _hour = h; _imp = imp; _lin = lin; } TMRP_time::TMRP_time() : _hour(0) { } TMRP_time::TMRP_time(const TDate& d, int h, const char* imp, const char* lin) : _date(d), _hour(h), _imp(imp), _lin(lin) { } /////////////////////////////////////////////////////////// // TMRP_array /////////////////////////////////////////////////////////// TSortable* TMRP_array::add_obj(const TToken_string& key) { TSortable* obj = (TSortable*)_by_key.objptr(key); if (obj == NULL) { obj = new_obj(key); _by_key.add(key, obj); _by_idx.add(obj); } return obj; } void TMRP_array::add(TMRP_array &a, bool force) { TString_array keys; a._by_key.get_keys(keys); for (int o=keys.items()-1; o >= 0; o--) { TString& key = keys.row(o); TSortable* obj = (TSortable*)a._by_key.objptr(key)->dup(); TSortable* oldobj = (TSortable*)_by_key.objptr(key); if (oldobj == NULL || force) { _by_key.add(key, obj); _by_idx.add(obj); } } } TMRP_array & TMRP_array::operator=(const TMRP_array& a) { _by_key=a._by_key; _by_idx=a._by_idx; return *this; } TMRP_array::TMRP_array(const TMRP_array& a) { *this = TMRP_array::operator=(a); } // Ordina gli articoli secondo il noto algoritmo Fantini-Truffelli // per array di oggetti su cui non e' definito un ordinamento completo long TMRP_array::sort() { const long last = items()-1; TProgind* pi = NULL; if (last >= 16) pi = new TProgind(last, TR("Ordinamento"), false, true); else begin_wait(); for (long i = 0; i < last; i++) { if (pi) pi->addstatus(1); TSortable* best = &find_obj(i); bool swapped = true; while (swapped) { swapped = false; for (long j = i+1; j <= last; j++) { const TSortable& other = find_obj(j); if (other.compare(*best) > 0) { best = (TSortable*)_by_idx.remove(int(j), true); _by_idx.TArray::insert(best, int(i)); swapped = true; } } } } if (pi) delete pi; else end_wait(); return last+1; } void TMRP_array::destroy() { _by_key.destroy(); _by_idx.destroy(); } /////////////////////////////////////////////////////////// // TMRP_calendar /////////////////////////////////////////////////////////// TString16 TMRP_calendar::_days; TToken_string TMRP_calendar::_holidays; void TMRP_calendar::init_default() { TMRP_config& cfg = mrp_config(); // Inizializza i turni dei 5 giorni feriali a 1 // Inizializza i turni di sabato e domenica a 0 // Inizializza i turni dei giorni festivi a 0 if (_days.empty()) _days = cfg.get("Turni", NULL, -1, "1111100011111000"); // Inizializza la lista delle feste comandate tranne Lunedi' dell'Angelo if (_holidays.empty()) _holidays = cfg.get("Feste", NULL, -1, "01-01|06-01|25-04|01-05|02-06|15-08|01-11|08-12|25-12|26-12"); TUnita_produttiva* up = NULL; if (_codlin.full()) up=new TLinea_prod(_codlin); else if (_codimp.full()) up=new TImpianto(_codimp); for (int t = 0; t < 8; t++) { if (up) { // turni di linea o impianto _lungturno[t] = up->durata_turno(t); _inizturno[t] = up->inizio_turno(t); _persturno[t] = up->numpers_turno(t); } else { // turni di ditta _lungturno[t] = cfg.durata_turno(t); _inizturno[t] = cfg.inizio_turno(t); _persturno[t] = cfg.numpers_turno(t); } if (_lungturno[t] <= 0) break; } if (up != NULL) delete up; } bool TMRP_calendar::is_holiday(const TDate& date) const { if (_holidays.empty()) ((TMRP_calendar*)this)->init_default(); const int d = date.day(); const int m = date.month(); TString8 str; str.format("%02d-%02d", d, m); bool festa = _holidays.find(str) >= 0; if (!festa && m >= 3 && m <= 4 && date.wday() == 1) { TDate angelo(date); angelo.set_easter(); ++angelo; festa = (date == angelo); } return festa; } bool TMRP_calendar::is_red(const TDate& date) const { return date.wday() == 7 || is_holiday(date); } // Serve per aggiungere le feste dei Patroni void TMRP_calendar::declare_holiday(int g, int m) { TString8 str; str.format("%02d-%02d", g, m); if (_holidays.find(str) < 0) _holidays.add(str); } void TMRP_calendar::suppress_holiday(int g, int m) { TString8 str; str.format("%02d-%02d", g, m); const int pos = _holidays.find(str); if (pos >= 0) { const TString& tail = _holidays.mid(pos+6); _holidays.cut(pos); _holidays << tail; } } TString& TMRP_calendar::turni_del_mese(char tipo, int year, int month) const { TString8 key; key.format("%04d%02d", year, month); TString* str = NULL; if (tipo == 'L') str = (TString*)_exc_lin.objptr(key); else str = (TString*)_exc_imp.objptr(key); if (str == NULL) { TString16 codtab = tipo == 'L' ? _codlin : _codimp; codtab << key; str = new TString80; *str = cache().get(tipo == 'L' ? "CAL" : "CAI", codtab, "S1"); str->rpad(62); if (tipo == 'L') ((TAssoc_array&)_exc_lin).add(key, str); else ((TAssoc_array&)_exc_imp).add(key, str); } return *str; } int TMRP_calendar::write_cal(char tipo) const { int err = NOERR; TTable cal((tipo == 'L') ? "CAL" : "CAI"); TAssoc_array& ass = (TAssoc_array&)(tipo == 'L' ? _exc_lin : _exc_imp); TString16 codtab; FOR_EACH_ASSOC_STRING(ass, hash, key, str) { codtab = tipo == 'L' ? _codlin : _codimp; codtab << key; cal.zero(); cal.put("CODTAB", codtab); const TFixed_string s1(str); if (s1.full()) { const int anno = atoi(codtab.mid(5, 4)); const int mese = atoi(codtab.mid(9, 2)); TString80 s0; if (tipo == 'L') { s0 = TR("Linea"); s0 << ' ' << _codlin; } else { s0 = TR("Impianto"); s0 << ' ' << _codimp; } s0 << ' ' << anno << ' ' << itom(mese); cal.put("S0", s0); cal.put("S1", s1); err = cal.write(); if (err != NOERR) err = cal.rewrite(); if (err != NOERR) { error_box(FR("Errore %d nell'aggiornamento del calendario %s"), err, (const char*)codtab); break; } } else err = cal.remove(); } return err; } int TMRP_calendar::remove_cal(const TString& code, char tipo) const { /* Metodo antico: statisticamente corretto TTable cal(tipo == 'L' ? "CAL" : "CAI"); TString16 codtab = code; codtab.rpad(5); cal.put("CODTAB", codtab); for (int err = cal.read(_isgteq); err == NOERR; err = cal.next()) { if (cal.get("CODTAB").starts_with(codtab)) cal.remove(); else break; } */ // Metodo standard: piu' sicuro TString8 code5 = code; code5.rpad(5); TRelation rel(tipo == 'L' ? "CAL" : "CAI"); TString80 filter; filter << "CODTAB[1,5]=='" << code5 << '\''; TCursor cur(&rel, filter); const TRecnotype tot = cur.items(); cur.freeze(); for (cur = 0; cur.pos() < tot; ++cur) rel.remove(); /* Metodo moderno: sicuro ma richiede recordset TString8 code5 = code; code5.rpad(5); TString80 query; query << "USE " << (tipo == 'L' ? "CAL" : "CAI") << "\n" << "SELECT CODTAB[1,5]=='" << code5 << "'\n"; TISAM_recordset set(query); for (bool ok = set.move_first(); ok; ok set.move_next()) set.cursor()->relation().remove(); */ return NOERR; } int TMRP_calendar::turni(const TDate& data, int& mini, int& maxi, bool as_is) const { const int year = data.year(); const int month = data.month(); const int day = data.day(); TMRP_calendar& myself = (TMRP_calendar&)*this; mini = maxi = -1; if (_codlin.full()) { const TString& turn = turni_del_mese('L', year, month); mini = turn[day-1] - '0'; maxi = turn[day+30] - '0'; if (as_is || (mini >= 0 && maxi >= 0)) return 3; } if (_codimp.full()) { const TString& turn = turni_del_mese('I', year, month); mini = turn[day-1] - '0'; maxi = turn[day+30] - '0'; if (as_is || (mini >= 0 && maxi >= 0)) return 2; } const int giorno = data.wday() - 1; // Controlla se e' festa infrasettimanale (giorno = 6 = domenica) if (giorno != 6 && is_holiday(data)) { if (mini < 0) mini = _days[7] - '0'; if (maxi < 0) maxi = _days[15] - '0'; if (mini >= 0 && maxi >= 0) return 1; } // Usa giorni default if (_days.empty()) ((TMRP_calendar*)this)->init_default(); if (mini < 0) mini = _days[giorno] - '0'; if (maxi < 0) maxi = _days[giorno+8] - '0'; return 0; } int TMRP_calendar::set_turni(const TDate& data, int mini, int maxi) { const int year = data.year(); const int month = data.month(); const int day = data.day(); TString16 str; if (_codlin.full()) { TString& turn = turni_del_mese('L', year, month); if (mini >= 0 && mini <= 9) turn[day-1] = '0' + mini; else turn[day-1] = ' '; if (maxi >= 0 && maxi <= 9) turn[day+30] = '0' + maxi; else turn[day+30] = ' '; return 3; } if (_codimp.full()) { TString& turn = turni_del_mese('I', year, month); if (mini >= 0 && mini <= 9) turn[day-1] = '0' + mini; else turn[day-1] = ' '; if (maxi >= 0 && maxi <= 9) turn[day+30] = '0' + maxi; else turn[day+30] = ' '; return 2; } const int giorno = data.wday() - 1; // Controlla se e' festa infrasettimanale if (giorno != 6 && is_holiday(data)) { if (mini >= 0 && mini <= 9) _days[7] = '0' + mini; else _days[7] = ' '; if (maxi >= 0 && maxi <= 9) _days[15] = '0' + maxi; else _days[15] = ' '; return 1; } if (mini >= 0 && mini <= 9) _days[giorno] = '0' + mini; else _days[giorno] = '0'; if (maxi >= 0 && maxi <= 9) _days[giorno+8] = '0' + maxi; else _days[giorno+8] = '0'; return 0; } int TMRP_calendar::add_oreuomo(real & var,const TDate& date, bool max, int turni) const { long minuti = 0L; const int tm = turni >= 0 ? turni :(max ? turni_max(date) : turni_min(date)); for (int t = tm-1; t >= 0; t--) minuti += _lungturno[t] * _persturno[t]; const int ore = int(minuti / 60L); var += ore; return ore; } int TMRP_calendar::add_oreuomo_max(real & var,const TDate& date) const { return add_oreuomo(var, date,true); } int TMRP_calendar::add_oremacchina(real& var,const TDate& date, bool max) const { const int tm = max ? turni_max(date) : turni_min(date); real minuti(ZERO); for (int t = tm-1; t >= 0; t--) { int lungturno = _lungturno[t]; const int start=_inizturno[t]; const int end=_inizturno[t]+_lungturno[t]-1; for (int pt = t-1; lungturno>0 && pt >= 0; pt--) { int overlap ; if (_inizturno[pt] end) overlap = end + 1 - start ; else overlap = _inizturno[pt] + _lungturno[pt] -1 - start; } else { if (end > _inizturno[pt]+_lungturno[pt]) overlap = _lungturno[pt]; else overlap = end + 1 - _inizturno[pt] ; } if (overlap >= 0) lungturno -= overlap; } minuti += lungturno; } minuti /= 60.0; var +=(minuti); return int(minuti.integer()); } int TMRP_calendar::add_oremacchina_max(real & var,const TDate& date) const { return add_oremacchina(var, date, true); } int TMRP_calendar::write() const { if (_codlin.full()) return write_cal('L'); if (_codimp.full()) return write_cal('I'); if (_days.full()) { TConfig cfg(CONFIG_DITTA, "mr"); cfg.set("Turni", _days); cfg.set("Feste", _holidays); } return NOERR; } int TMRP_calendar::remove() const { if (_codlin.full()) return remove_cal(_codlin, 'L'); if (_codimp.full()) return remove_cal(_codimp, 'I'); return NOERR; } void TMRP_calendar::set(const char* linea, const char* impianto) { _exc_lin.destroy(); _exc_imp.destroy(); _days.cut(0); _codlin = linea; _codlin.rpad(5); _codimp = impianto; _codimp.rpad(5); if (_codlin.full()) { const TRectype & lnp = cache().get("LNP", _codlin); _codlin = lnp.get("CODTAB"); if (impianto == NULL) _codimp = lnp.get("S6"); } if (_codimp.full()) _codimp = cache().get("IMP", _codimp, "CODTAB"); _codlin.rpad(5); // Servono sempre paddati! _codimp.rpad(5); } char TMRP_calendar::tipo() const { if (_codlin.full()) return 'L'; if (_codimp.full()) return 'I'; return 'S'; } TDate& TMRP_calendar::next_working_day(TDate& work, int gap) const { const int delta = gap >= 0 ? +1 : -1; const int steps = gap >= 0 ? gap : -gap; for (int i = 0; i < steps; i++) { do work += delta; while (turni_min(work) <= 0); } return work; } TMRP_calendar::TMRP_calendar(const char* linea, const char* impianto) { set(linea, impianto); init_default(); } /////////////////////////////////////////////////////////// // TCalendar_win /////////////////////////////////////////////////////////// class TCalendar_win : public TField_window { int _anno; TMRP_calendar* _calendario; bool _immediate_write; protected: virtual long handler(WINDOW win, EVENT* ep); virtual void update(); public: void set_immediate_write(bool on = true) { _immediate_write = on; } void set_calendar(TMRP_calendar* cal, int year = 0); TMRP_calendar* get_calendar() { return _calendario; } TCalendar_win(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner); virtual ~TCalendar_win() { } }; long TCalendar_win::handler(WINDOW win, EVENT* ep) { switch (ep->type) { case E_MOUSE_DOWN: if (_calendario) { const PNT& where = ep->v.mouse.where; RCT rct; xvt_vobj_get_client_rect(win, &rct); const int month = where.v * 13 / rct.bottom; if (month >= 1 && month <= 12) { const int day = where.h * 33 / rct.right - 1; const int last = TDate::last_day(month, _anno); if (day >= 1 && day <= last) { const bool is_std=_calendario->tipo()=='S' ; TString calname; switch (_calendario->tipo()) { case 'S': calname=TR("Calendario standard"); break; case 'I': calname=TR("Calendario impianto "); calname << '"'<< _calendario->impianto() << '"'; break; case 'L': calname=TR("Calendario linea "); calname << '"'<< _calendario->linea() << '"'; break; } TMask m(calname, 1, 40, 8); m.add_static(DLG_NULL, 0, TR("Turni del giorno "), 1, 1); m.add_date(101, 0, "", 1, 2, "D"); m.add_string(102, 0, "", 19, 2, 9, "D"); m.add_boolean(103, 0, TR("Festa"), 31, 2, is_std ? "":"D"); if (is_std) { m.add_list(104, 0, TR("Turni minimi "), 1, 4, 8, "", "0|1|2|3|4|5|6|7|8", "Nessuno|1 turno|2 turni|3 turni|4 turni|5 turni|6 turni|7 turni|8 turni"); m.add_list(105, 0, TR("Turni massimi "), 1, 5, 8, "", "0|1|2|3|4|5|6|7|8", "Nessuno|1 turno|2 turni|3 turni|4 turni|5 turni|6 turni|7 turni|8 turni"); } else { m.add_list(104, 0, TR("Turni minimi "), 1, 4, 8, "", " |0|1|2|3|4|5|6|7|8", "Standard|Nessuno|1 turno|2 turni|3 turni|4 turni|5 turni|6 turni|7 turni|8 turni"); m.add_list(105, 0, TR("Turni massimi "), 1, 5, 8, "", " |0|1|2|3|4|5|6|7|8", "Standard|Nessuno|1 turno|2 turni|3 turni|4 turni|5 turni|6 turni|7 turni|8 turni"); } m.add_number(106, 0, "= ", 31, 4, 1, "D"); m.add_number(107, 0, "= ", 31, 5, 1, "D"); m.add_button(DLG_OK, 0, "", -12, -1, 10, 2); m.add_button(DLG_CANCEL, 0, "", -22, -1, 10, 2); const TDate d(day, month, _anno); const bool festa = _calendario->is_holiday(d); m.set(101, d.string()); m.set(102, itow(d.wday())); m.set(103, festa ? "X" : ""); int mini, maxi; _calendario->turni(d, mini, maxi, true); m.set(104, mini); m.set(105, maxi); _calendario->turni(d, mini, maxi, FALSE); m.set(106, mini); m.set(107, maxi); if (m.run() == K_ENTER && m.dirty()) { const char mi = m.get(104)[0]; mini = (mi == ' ') ? -1 : mi-'0'; const char ma = m.get(105)[0]; maxi = (ma == ' ') ? -1 : ma-'0'; _calendario->set_turni(d, mini, maxi); const bool fe = m.get_bool(103); if (fe != festa) { if (fe) _calendario->declare_holiday(d.day(), d.month()); else _calendario->suppress_holiday(d.day(), d.month()); } if (_immediate_write) _calendario->write(); owner().set_dirty(); force_update(); } } } } break; default: break; } return TField_window::handler(win, ep); } void TCalendar_win::update() { const TDate today(TODAY); const int this_year = today.year(); const int this_month = today.month(); const int this_day = today.day(); RCT rct; xvt_vobj_get_client_rect(win(), &rct); TField_window::update(); TFilename month; month.format("calend%02d.jpg", this_month); if (month.exist()) { TImage bmp(month); int x = (rct.right - bmp.width()) / 2; int y = (rct.bottom - bmp.height()) / 2; bmp.draw(win(), x, y); } _pixmap = true; TMRP_calendar* defcal = NULL; TMRP_calendar* cal = _calendario; if (cal == NULL) { defcal = new TMRP_calendar(); cal = defcal; } if (cal->from().ok() || cal->to().ok()) { TDate from = cal->from(); TDate to = cal->to(); if (from.year() < _anno) from = TDate(1,1, _anno); if (to.year() > _anno) to = TDate(31, 12, _anno); set_brush(FOCUS_BACK_COLOR); hide_pen(); for (TDate d = from ; d <= to; ++d) { RCT rect; rect.left = rct.right * (d.day() + 1) / 33; rect.right = rct.right * (d.day() + 2) / 33; rect.top = rct.bottom * d.month() / 13; rect.bottom = rct.bottom * (d.month() + 1) / 13; xvt_dwin_draw_rect(win(), &rect); } set_brush(NORMAL_BACK_COLOR); } TString16 str; str << _anno; set_color(NORMAL_COLOR, NORMAL_BACK_COLOR); if (_anno == this_year) set_font(NULL, XVT_FS_BOLD); stringat(1, 1, str); if (_anno == this_year) set_font(); int i, j; for (i = 1; i <= 31; i++) { set_pen(NORMAL_COLOR, i == 1 ? 2 : 0); const int x = rct.right * (i+1) / 33; line(x, 0, x, rct.bottom); str.format("%2d", i); if (i == this_day) set_font(NULL, XVT_FS_BOLD); stringat(x+2, 0, str); if (i == this_day) set_font(); } for (j = 1; j <= 12; j++) { set_pen(NORMAL_COLOR, j == 1 ? 2 : 0); const int y = rct.bottom * j / 13; line(0, y, rct.right, y); str = itom(j); str.cut(3); if (j == this_month) set_font(NULL, XVT_FS_BOLD); stringat(1, y, str); if (j == this_month) set_font(); } for (j = 1; j <= 12; j++) { const int y = rct.bottom * j / 13; const int last = TDate::last_day(j, _anno); for (i = 1; i <= last; i++) { const int x = rct.right * (i+1) / 33; const TDate data(i, j, _anno); int tmin, tmax; cal->turni(data, tmin, tmax); COLOR colore = COLOR_BLACK; if (cal->is_red(data)) colore = COLOR_RED; else { if (tmin != 0) { const TDate ieri = data-1L; if (cal->turni_min(ieri) == 0) { const TDate domani = data+1L; if (cal->turni_min(domani) == 0) colore = COLOR_MAGENTA; } } else colore = COLOR_BLUE; } set_color(colore, COLOR_WHITE); if (j == this_month && i == this_day) set_font(NULL, XVT_FS_BOLD); str.format("%d", tmin); stringat(x+2, y, str); str.format(" %d", tmax); stringat(x+2, y + CHARY, str); if (j == this_month && i == this_day) set_font(); // Rimette a posto il font } } if (defcal != NULL) delete defcal; _pixmap = FALSE; } void TCalendar_win::set_calendar(TMRP_calendar* cal, int year) { _calendario = cal; if (year > 0) _anno = year; else _anno = TDate(TODAY).year(); } TCalendar_win::TCalendar_win(int x, int y, int dx, int dy, WINDOW parent, TWindowed_field* owner) : TField_window(x, y, dx, dy, parent, owner) { _immediate_write = false; xvt_sbar_set_range(win(), HSCROLL, 0, 0); xvt_sbar_set_range(win(), VSCROLL, 0, 0); set_calendar(NULL); } /////////////////////////////////////////////////////////// // TCalendar_field /////////////////////////////////////////////////////////// void TCalendar_field::set_immediate_write(bool on) { TCalendar_win& cw = (TCalendar_win&)win(); cw.set_immediate_write(on); } TField_window* TCalendar_field::create_window(int x, int y, int dx, int dy, WINDOW parent) { return new TCalendar_win(x, y, dx, dy, parent, this); } void TCalendar_field::set_calendar(TMRP_calendar* cal, int year) { TCalendar_win& cw = (TCalendar_win&)win(); cw.set_calendar(cal, year); cw.force_update(); } /////////////////////////////////////////////////////////// // TCalendar_mask /////////////////////////////////////////////////////////// /* void TCalendar_mask::make_profile_name(TFilename& f) const { f =::firm2dir(-1); // Directory dati f.add("config"); // Directory config f.add(user()); // Directory config if (!f.exist()) make_dir(f); f.add(source_file()); // Nome Maschera f.ext("ini"); // Estensione } void TCalendar_mask::save_profile() { TFilename prof; make_profile_name(prof); ofstream ini(prof); for (int i = 0; i < fields(); i++) { TMask_field& f = fld(i); if (f.is_loadable()) { if (f.is_sheet()) { TSheet_field& s = (TSheet_field&)f; FOR_EACH_SHEET_ROW(s, r, row) ini << f.dlg() << '[' << r << "] = " << *row << endl; } else { ini << f.dlg() << " = " << f.get() << endl; } } } } void TCalendar_mask::load_profile() { TFilename prof; make_profile_name(prof); if (prof.exist()) { TScanner ini(prof); while (ini.good()) { TString& line = ini.line(); int id, idx; const int num = sscanf(line, "%d[%d] = ", &id, &idx); if (num > 0 && id2pos(id) >= 0) // Riga valida { TMask_field& f = field(id); if (f.is_loadable()) { const int eq = line.find('='); line.ltrim(eq+2); // Considera solo il valore del campo if (num == 1) f.set(line); else if (num == 2 && f.is_sheet()) { TSheet_field& sf = (TSheet_field&)f; if (idx == 0) sf.destroy(); // Cancella tutto se inserisci la prima riga sf.row(idx) = line; } } } } } } */ TMask_field* TCalendar_mask::parse_field(TScanner& scanner) { const TString& k = scanner.key(); if (k == "CA") return new TCalendar_field(this); return TAutomask::parse_field(scanner); } void TCalendar_mask::update_calendar(short calendar, short year, short plant, short line) { TCalendar_field& cf = (TCalendar_field&)field(calendar); TString8 linea = line > 0 ? get(line) : EMPTY_STRING; TString8 impianto = plant > 0 ? get(plant) : EMPTY_STRING; int anno = year >= 0 ? get_int(year) : 0; _calendar.set(linea, impianto); cf.set_calendar(&_calendar, anno); } TCalendar_mask::TCalendar_mask(const char* name, int num) { read_mask(name, num, 0); set_handlers(); } //*********************************** //******** TImpianto * get_impianto(const char * codice) { static TImpianto *buffer=NULL; if (!buffer) buffer= new TImpianto(); *buffer=cache().get("IMP",codice); return buffer; } TLinea_prod* get_linea(const char * codice) { static TLinea_prod *buffer=NULL; if (!buffer) buffer= new TLinea_prod(); *buffer=cache().get("LNP",codice); return buffer; } const char *TUnita_produttiva::erre1(int t) { static char _erre[4] = "R0"; _erre[1]='0'+char(t); CHECK(t>=0 && t<8, "Errore nel numero di turno"); return _erre; } const char *TUnita_produttiva::erre2(int t) { static char _erre[4] = "R10"; _erre[2]='0'+char(t); CHECK(t>=0 && t<8, "Errore nel numero di turno"); return _erre; } #define M_INIZIO 10000L #define M_DURATA 1L //#define M_PERSON 0.05 // inizio turno int TUnita_produttiva::inizio_turno(int t) { real r=get_real(erre1(t)); r=r/M_INIZIO; const int i=(int)r.round().integer(); return i; } void TUnita_produttiva::set_inizio_turno(int t,int time) { real r(time); r = r * M_INIZIO; r = r + long(TUnita_produttiva::durata_turno(t))*M_DURATA; put(erre1(t), r); } // durata turno int TUnita_produttiva::durata_turno(int t) { real r=get_real(erre1(t)); r=r-real(long(TUnita_produttiva::inizio_turno(t))*M_INIZIO); r=r/M_DURATA; const int i=(int)r.round().integer(); return i; } void TUnita_produttiva::set_durata_turno(int t,int time) { real r(TUnita_produttiva::inizio_turno(t)); r = r * M_INIZIO; r = r + long(time)*M_DURATA; put(erre1(t), r); } // persone per turno int TUnita_produttiva::raw_numpers_turno(int t) { real r(get_real(erre2(t))); return (int)r.round().integer(); } int TUnita_produttiva::numpers_turno(int t) { int val; if (TUnita_produttiva::personale_dedicato()) { val=raw_numpers_turno(t); if (val==0) val=get_int("I1"); } else val= mrp_config().numpers_turno(t); return val; /*int r=raw_numpers_turno(t); if (r==0) return numpers_turno(); else return r;*/ } void TUnita_produttiva::set_numpers_turno(int t, int pers) { real r(pers); put(erre2(t), r); } void TUnita_produttiva::set_inizio_turno(int t,int ore, int minuti) { const int time=ore*60+minuti; set_inizio_turno(t,time); } void TUnita_produttiva::set_durata_turno(int t,int ore, int minuti) { const int time=ore*60+minuti; set_durata_turno(t,time); } int TUnita_produttiva::ora_inizio_turno(int t) { return inizio_turno(t)/60; } int TUnita_produttiva::min_inizio_turno(int t) { return inizio_turno(t)%60; } int TUnita_produttiva::ore_durata_turno(int t) { return durata_turno(t)/60; } int TUnita_produttiva::min_durata_turno(int t) { return durata_turno(t)%60; } const char * TUnita_produttiva::codmag() const { TString16 s(codmagdep()); return s.sub(0,3); } const char * TUnita_produttiva::coddep() const { TString16 s(codmagdep()); return s.sub(3,5); } TRectype & TUnita_produttiva::operator=(const TRectype & rec) { TRectype ::operator=(rec); return *this ; } // *************************** // ****** TImpianto TImpianto::TImpianto(const char* cod) : TUnita_produttiva() { settab("IMP"); if (cod && *cod) { const TRectype & rec = cache().get("IMP", cod); *this = rec; } } // *************************** // ****** TLinea_prod TRectype & TImpianto::operator=(const TRectype & rec) { TUnita_produttiva::operator=(rec); return *this ; } TRectype & TLinea_prod::operator=(const TRectype & rec) { TUnita_produttiva::operator=(rec); return *this ; } const char * TLinea_prod::codimp() const { return get("S6"); } TLinea_prod::TLinea_prod(const char* cod ) : TUnita_produttiva() { settab("LNP"); if (cod && *cod) { const TRectype & rec = cache().get("LNP", cod); *this = rec; } } const char * TLinea_prod::codmagdep() const { const char * cod=TUnita_produttiva::codmagdep() ; if (*cod==0) { TImpianto* imp=((TLinea_prod *)this)->get_impianto(); if (imp) return imp->codmagdep(); } return cod; } const char * TLinea_prod::codmagdep_coll() const { const char * cod=TUnita_produttiva::codmagdep_coll() ; if (*cod==0) { TImpianto* imp=((TLinea_prod *)this)->get_impianto(); if (imp) return imp->codmagdep_coll(); } return cod; } int TLinea_prod::inizio_turno(int t) { int val; if (TUnita_produttiva::num_turni()!=0) val=TUnita_produttiva::inizio_turno(t); else { TImpianto* imp=get_impianto(); if (imp && imp->num_turni()!=0) val=imp->inizio_turno(t); else val=mrp_config().inizio_turno(t); } return val; } int TLinea_prod::durata_turno(int t) { int val; if (TUnita_produttiva::num_turni()!=0) val=TUnita_produttiva::durata_turno(t); else { TImpianto* imp=get_impianto(); if (imp && imp->num_turni()!=0) val=imp->durata_turno(t); else val=mrp_config().durata_turno(t); } return val; } int TLinea_prod::numpers_turno(int t) { int val; if (TUnita_produttiva::num_turni()!=0) val=TUnita_produttiva::numpers_turno(t); else { TImpianto* imp=get_impianto(); if (imp) val=imp->numpers_turno(t); } return val; } int TLinea_prod::priority() { return get_int("I3"); } int TLinea_prod::num_turni() { int val=TUnita_produttiva::num_turni(); if (val==0) { TImpianto* imp=get_impianto(); if (imp) val=imp->num_turni(); if (val==0) val=mrp_config().num_turni(); } return val; } TImpianto * TLinea_prod::get_impianto() const { const char * imp = codimp(); if (imp && *imp) return ::get_impianto(imp); else return NULL; } void find_price(const TString &tipocv, const TString &codcv, const TString &codcatven, const char *tipocf, long codcf, const char * codice, const real & qta, real & price) { static TCondizione_vendita *_condv =NULL; bool retry=true; if (_condv == NULL) _condv = new TCondizione_vendita(new TConfig (CONFIG_DITTA)); switch (tipocv[0]) { case 'C': if (codcf == 0L && _condv->config_ditta().get_bool("GESCONCC", "ve")) break; // necessario il codice del cli/for case 'O': case 'L': { TString8 strcodcf; if (codcf > 0) strcodcf.format("%ld",codcf); _condv->put_condv(tipocv,codcv,codcatven, tipocf, strcodcf); if (_condv->ricerca(codice, qta)) { price = _condv->get_prezzo(); retry=FALSE; } } break; default: break; } if (retry) { TToken_string key(codice); key.add(1); price = cache().get(LF_UMART,key).get_real(UMART_PREZZO); } } void TProduzione::init() { add_file(LF_RRILPROD, "NRIGA"); } TProduzione::TProduzione() : TMultiple_rectype(LF_RILPROD) { init(); } TProduzione::TProduzione(const TProduzione & d) : TMultiple_rectype(LF_RILPROD) { init(); copy(d); } TProduzione::TProduzione(const char* codart, TDate datacons, int prog) : TMultiple_rectype(LF_RILPROD) { init(); if (prog <= 0) { prog = 0; set_key(*this, codart, datacons, prog); } else read_art(codart, datacons, prog); } // Funzione statica utile a tutti gli utenti di LF_DOC e LF_RIGHEDOC void TProduzione::set_key(TRectype& rec, const char* codart, TDate datacons, int prog) { CHECK(codart && *codart, "Codice articolo nullo"); CHECK(datacons.ok(), "Data di consegna non valida "); rec.put("CODART", codart); rec.put("DATA", datacons); rec.put("PROG", prog); } bool TProduzione::renum() { TLocalisamfile f(LF_RILPROD); TRectype& cmp = head(); int n = 0; f.curr() = cmp; f.put("PROG", 999); const int err = f.read(_isgreat); if (err != _isemptyfile) { if (err == NOERR) f.prev(); if (f.get("CODART") == cmp.get("CODART") && f.get("DATA") == cmp.get_date("DATA")) n = f.get_int("PROG"); } cmp.put("PROG", n + 1); return true; } int TProduzione::read_art(const char* codart, TDate datacons, int prog, word op, word lockop) { TLocalisamfile f(LF_RILPROD); zero(); set_key(*this, codart, datacons, prog); if (prog == 0) { TRectype& cmp = head(); f.curr() = cmp; f.put("PROG", 999); const int err = f.read(_isgreat); if (err != _isemptyfile) { if (err == NOERR) f.prev(); if (f.get("CODART") == cmp.get("CODART") && f.get("DATA") == cmp.get_date("DATA")) cmp.put("PROG", f.get("PROG")); else return _iskeynotfound; } else return _iskeynotfound; } return TMultiple_rectype::read(f, op, lockop); } int TProduzione::read_ordp(const char* codnum, int anno, char provv, long ndoc, int nriga, word op, word lockop) { TLocalisamfile f(LF_RILPROD); f.setkey(4); f.put("CODNUM", codnum); f.put("ANNO", anno); f.put("PROVV", "D"); f.put("NDOC", ndoc); f.put("NRIGA", nriga); int err = f.read(); head() = f.curr(); f.setkey(1); if (err == NOERR) err = TMultiple_rectype::read(f, op, lockop); else zero(); return err; } int TProduzione::read_bolp(const char* codnum, int anno, char provv, long ndoc, int nriga, word op, word lockop) { TLocalisamfile f(LF_RILPROD); f.setkey(5); f.put("CODNUM", codnum); f.put("ANNO", anno); f.put("PROVV", "D"); f.put("NDOC", ndoc); f.put("NRIGA", nriga); int err = f.read(); head() = f.curr(); f.setkey(1); if (err == NOERR) err = TMultiple_rectype::read(f, op, lockop); else zero(); return err; } void TProduzione::copy_data(TRectype& dst, const TRectype& src) { // Memorizza tutti i campi chiave const TString codart = dst.get("CODART"); const TDate datacons = dst.get_date("DATA"); const int prog = dst.get_int("PROG"); const int nriga = dst.num() == LF_RRILPROD ? dst.get_int("NRIGA") : 0; // Copia tutto il record dst = src; // Ripristina tutti i campi chiave set_key(dst, codart, datacons, prog); if (nriga > 0) dst.put("NRIGA", nriga); } void TProduzione::copy_contents(const TProduzione& src) { copy_data(head(), src.head()); destroy_rows(); const int rows = src.rows(); for (int i = 1; i <= rows ; i++) { const TRectype & s = src.body()[i]; TRectype & r = new_row(); copy_data(r, s); } }