Files correlati : Ricompilazione Demo : [ ] Commento : sistemati riporti git-svn-id: svn://10.65.10.50/trunk@20616 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1623 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1623 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include "mrplib.h"
 | |
| 
 | |
| #include <colors.h>
 | |
| #include <defmask.h>
 | |
| #include <diction.h>
 | |
| #include <image.h>
 | |
| #include <progind.h>
 | |
| #include <tabutil.h>
 | |
| 
 | |
| //***********************************
 | |
| // 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]<start)
 | |
|       {
 | |
|         // OK 100%
 | |
|         if (_inizturno[pt] + _lungturno[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);
 | |
|   }
 | |
| }
 | |
| 
 |