campo-sirio/mr/mrplib.cpp

1609 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;
TProgress_monitor pi(last, TR("Ordinamento"), false);
for (long i = 0; i < last; i++)
{
pi.add_status();
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;
}
}
}
}
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, 11);
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);
}
}