campo-sirio/mr/mr2200.cpp
alex a29e4b43d4 Patch level : 2.1 048
Files correlati     : mr0.exe mr1.exe mr2.exe
Ricompilazione Demo : [ ]
Commento            :
Bug 0000135

 Implementare la gestione multilingua


git-svn-id: svn://10.65.10.50/trunk@12087 c028cbd2-c16b-5b4b-a496-9718f37d4682
2004-05-18 11:17:26 +00:00

3767 lines
122 KiB
C++
Executable File
Raw Blame History

#include "mr2200.h"
#include "mr2200a.h"
#include "mr2200b.h"
#include <cfven.h>
#include <urldefid.h>
class TMSPCheck_mask : public TAutomask
{
protected:
int _col, _row, _constr_row, _last_col, _last_row;
TPlanning_mask * _main_mask;
TSheet_field * _sheet;
protected:
int max_rows() {return _sheet->items();}
void go_top();
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
bool move_to(int dlg);
virtual void check_pos_range();
virtual int fill_mask(const bool show=TRUE);
virtual bool is_constraint(int row);
virtual bool is_article(int row);
virtual int find_constr_row(int row);
public:
virtual void gopos_mainmask();
void gopos(int row, int col);
void fix_actual_pos();
short last_row(){ return _last_row;}
short last_col(){ return _last_col;}
TMSPCheck_mask(TPlanning_mask * main_mask);
TMSPCheck_mask(TPlanning_mask * main_mask,const char * m,TSheet_field * s );
};
class TCRPCheck_mask : public TMSPCheck_mask
{
protected:
virtual void check_pos_range();
virtual int fill_mask(const bool show=TRUE);
virtual bool is_constraint(int row);
virtual bool is_article(int row);
virtual int find_constr_row(int row);
public:
TCRPCheck_mask(TPlanning_mask * main_mask);
};
// sotto-maschera di riepilogo di alcune opzione della maschera principale
class TPlann_sub_mask : public TAutomask
{
protected:
TPlanning_mask *_m;
void copy_fields_from();
void copy_fields_to();
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TPlann_sub_mask(TPlanning_mask &m, const char * name);
virtual ~TPlann_sub_mask() {}
};
class TSave_mask : public TPlann_sub_mask
{
TExceptions_array _exceptions;
protected:
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TSave_mask(TPlanning_mask &m);
virtual ~TSave_mask() {}
};
class TPrint_mask : public TPlann_sub_mask
{
protected:
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TPrint_mask(TPlanning_mask &m);
virtual ~TPrint_mask() {}
};
///////////////////////////////////////////////////////////
// Maschera di reassunto
///////////////////////////////////////////////////////////
void TPlann_sub_mask::copy_fields_from()
{
for (int i = fields()-1; i >=0; i--)
{
const TMask_field & destfld = fld(i);
const int dlg = destfld.dlg();
if (dlg > DLG_USER && _m->id2pos(dlg)>=0)
{
if (destfld.is_sheet())
{
TSheet_field & sfld = (TSheet_field & )fld(i);
CHECK(_m->field(dlg).is_sheet(),"Impossibile copiare un campo non sheet su uno sheet");
TSheet_field & srcfld = _m->sfield(dlg);
for (int it = 0; it <srcfld.items(); it++)
{
const TToken_string & r=srcfld.row(it);
sfld.row(it) = r;
}
}
else
set(dlg, _m->get(dlg));
}
}
}
void TPlann_sub_mask::copy_fields_to()
{
for (int i = fields()-1; i >=0; i--)
{
const int dlg = fld(i).dlg();
if (dlg > DLG_USER && _m->id2pos(dlg)>=0)
_m->set(dlg, get(dlg));
}
}
TPlann_sub_mask::TPlann_sub_mask(TPlanning_mask &m, const char * name) :
TAutomask(name)
{
_m = &m;
copy_fields_from();
}
bool TPlann_sub_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case DLG_QUIT:
copy_fields_to();
save_profile();
break;
}
return TRUE;
}
///////////////////////////////////////////////////////////
// Maschera stampa
///////////////////////////////////////////////////////////
TPrint_mask::TPrint_mask(TPlanning_mask &m) :
TPlann_sub_mask(m, "mr2200f.msk") {}
bool TPrint_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_MSP_RESORT:
if (e==fe_button)
{
copy_fields_to();
_m->sortMSPsheet();
}
break;
case F_SHOWPERC:
case F_SHOWDETAILS:
case F_LOADTYPE:
if (e == fe_modify)
{
copy_fields_to();
_m->on_field_event((TOperable_field&)_m->field(F_LOADTYPE), fe_modify, jolly );
}
break;
case DLG_QUIT:
if (e == fe_button)
{
switch (get(S_PRINTTYPE)[0])
{
case 'C':
_m->print_capacities(); break;
case 'O':
{
TString row_filter=get(F_PRINT_ROW_FILTER);
_m->print_articles(get_int(F_PRINT_FROM_COL),get_int(F_PRINT_NUM_COL), row_filter); break;
}
case 'E':
{
TExceptions_array e;
if (_m->find_exceptions(e, get_bool(S_HURRYUP_EXCEPT),get_bool(S_DELAY_EXCEPT),get_bool(S_EXTRA_EXCEPT), get_bool(S_STOCKBRK_EXCEPT), get_bool(S_CODEMISS_EXCEPT), TRUE))
_m->print_exceptions(e);
}
break;
}
}
default:
TPlann_sub_mask::on_field_event(o,e,jolly);
}
return TRUE;
}
///////////////////////////////////////////////////////////
// Maschera salvataggio
///////////////////////////////////////////////////////////
TSave_mask::TSave_mask(TPlanning_mask &m) :
TPlann_sub_mask(m, "mr2200e.msk")
{
_m = &m;
copy_fields_from();
}
bool TSave_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_SAVE_OPT:
if (e == se_query_add)
return FALSE;
break;
case DLG_QUIT:
_m->find_exceptions(_exceptions, TRUE,TRUE,TRUE,FALSE,TRUE);
if (_m->salva_documenti(_exceptions, sfield(F_SAVE_OPT))<0)
_m->elabora(); // necessario per ricaricare i rif alle righe
if (_exceptions.items())
{
if (yesno_box(FR("%d eccezioni rilevate. Stampo il tabulato ?"),_exceptions.items()))
_m->print_exceptions(_exceptions);
else
message_box(TR("Controllare il tabulato eccezioni."));
}
break;
default:
TPlann_sub_mask::on_field_event(o,e,jolly);
}
return TRUE;
}
///////////////////////////////////////////////////////////
// Maschera principale
///////////////////////////////////////////////////////////
bool TPlanning_mask::_week_complete;
void TPlanning_mask::get_week_year(const TDate &d, int &week, int &year)
{
week = d.week();
year = d.year();
const int wday = TDate(1,1,year).wday();
if (_week_complete)
{
if (wday != 1)
week --;
if (week == 0 )
{
week = 52;
year --;
}
} else {
if (week > 52)
{
week = 1;
year ++;
}
}
}
// Arrotonda la data al bucket e ne restituisce il numero (data iniziale==bucket 0)
int TPlanning_mask::round_date(TDate& date, bool up, bool towrkday) const
{
int bucket;
TDate inizio(starting_date());
if (bucket_mese())
{
if (up)
{
date.set_end_month();
if (towrkday)
{
int wday = date.wday();
wday = (7-wday) % 7;
wday -= get_int(F_LASTWRKDAY);
if (wday<0)
date += wday;
}
}
else
date.set_day(1);
bucket = (date.year()-inizio.year())*12 + date.month() - inizio.month();
if (bucket<0) bucket = -1;
}
else
{
// Dimensione del bucket in giorni
const int bucket_size = days_per_bucket();
// Riporta la data al primo lunedi prima dell'inizio
if (bucket_size>1) // non vado a giorni
{
const int wday = inizio.wday();
if (wday > 1) inizio -= wday-1;
}
// Calcola il bucket di appartenenza
const int days = int(date - inizio);
if (days<0)
bucket = -1;
else
bucket = days / bucket_size;
if (bucket_size > 1) // multipli settimanali
{
if (up || days<0) // Arrotonda alla fine del bucket
date = inizio + long((bucket+1 )* bucket_size - 1 - (towrkday ? get_int(F_LASTWRKDAY) : 0));
else // Arrotonda all'inizio del bucket
date = inizio + long(bucket * bucket_size);
}
}
return bucket;
}
// restituisce il numero del bucket (data iniziale==bucket 0)
int TPlanning_mask::bucket(const TDate& date) const
{
int bucket;
TDate inizio(starting_date());
if (bucket_mese())
{
// bucket = inizio.month() - date.month();
bucket = date.month() - inizio.month() + (date.year() - inizio.year())*12;
if (bucket<0) bucket = -1;
}
else
{
// Dimensione del bucket in giorni
const int bucket_size = days_per_bucket();
// Riporta la data al primo lunedi prima dell'inizio
if (bucket_size>1) // non vado a giorni
{
const int wday = inizio.wday();
if (wday > 1) inizio -= wday-1;
}
// Calcola il bucket di appartenenza
const int days = int(date - inizio);
if (days<0)
bucket = -1;
else
bucket = days / bucket_size;
}
return bucket;
}
void TPlanning_mask::round_field(TMask_field& fld, bool up, bool towrkday) const
{
TDate date = fld.get();
if (date.ok())
{
round_date(date, up, towrkday);
fld.set(date);
}
}
int TPlanning_mask::test_codnum(const TCodice_numerazione& num) const
{
int r=0;
for (int s = 2; s > 0; s--)
{
const short id = s == _Doc_planning ? F_NUM_PLA : F_NUM_ORC;
TString_array& nums = sfield(id).rows_array();
for (int i = nums.items()-1; i >= 0; i--)
{
const char* t = nums.row(i).get(0);
if (num.codice() == t)
{
r|=s; break;
}
}
}
return r;
}
bool TPlanning_mask::test_tipodoc_num(const TSheet_field &sheet_num ,const TSheet_field &sheet_type)
{
TString16 tipo;
TString_array& nums = sheet_num.rows_array();
TString_array& types = sheet_type.rows_array();
for (int j = types.items()-1; j >= 0; j--)
{
bool ok=FALSE;
tipo = types.row(j).get(0) ;
for (int i = nums.items()-1; i >= 0; i--)
{
TCodice_numerazione num(nums.row(i).get(0));
for (int n = num.ntipi_doc()-1;n >= 0; n--)
{
const char* t = num.tipo_doc(n);
if (tipo == t)
ok = TRUE;
}
}
if (!ok)
return error_box(FR("Il tipo '%s' non appartiene a nessuna delle numerazioni scelte"),(const char * )tipo);
}
return TRUE;
}
int TPlanning_mask::test_status(const TRectype& doc, int s) const
{
const short id = (s & _Doc_planning) ? F_TIPI_PLA : F_TIPI_ORC;
TSheet_field& sf = sfield(id);
const int idfr = sf.cid2index(F_DASTATO);
const int idto = sf.cid2index(F_ASTATO);
const TString16 tipodoc = doc.get(DOC_TIPODOC);
const int statodoc = doc.get_int(DOC_STATO);
TString_array& a = sf.rows_array();
for (int i = a.items()-1; i >= 0 ; i--)
{
TToken_string& riga = a.row(i);
const char* t = riga.get(0);
if (tipodoc == t)
{
const int state_fr = riga.get_int(idfr);
const int state_to = riga.get_int(idto);
if (statodoc >= state_fr && statodoc <= state_to)
return i;
}
}
return -1;
}
bool TPlanning_mask::has_confirmed_status(const TRectype &doc, TToken_string &riga) const
{
const char statodoc = doc.get_char(DOC_STATO);
char def_status = riga.get_char(F_STATODEF-FIRST_FIELD);
return def_status > ' ' ? statodoc >= def_status : FALSE;
}
bool TPlanning_mask::has_confirmed_status(const TRectype &doc) const
{
int sheetrow = test_status(doc, _Doc_planning);
TToken_string & riga = sfield(F_TIPI_PLA).row(sheetrow);
return has_confirmed_status(doc, riga);
}
bool TPlanning_mask::has_confirmed_status(const char * codnum, const char *tipodoc, char stato) const
{
TRectype doc(LF_DOC);
doc.put(DOC_CODNUM, codnum);
doc.put(DOC_TIPODOC, tipodoc);
doc.put(DOC_STATO, stato);
return has_confirmed_status(doc);
}
// Metodo standard per contare gli elementi di una tabella
// in attesa di tempi migliori per le librerie
/*
static long table_items(const char* tab)
{
TRelation tabrel(tab);
TCursor tabcur (&tabrel);
long tot = tabcur.items();
return tot;
}
*/
bool TPlanning_mask::elabora()
{
clear_sheets();
if (carica_documenti())
{
TSheet_field& s = sfield(F_ARTICOLI);
fill_sheet();
const bool some_lines=s.items() > 0;
enable(-G_PREPROCESS, !some_lines);
enable(-G_POSTPROCESS, some_lines);
if (some_lines)
{
s.select(2);
s.set_focus();
on_field_event((TOperable_field&)field(F_SHOWPRICES), fe_modify, 0L);
on_field_event((TOperable_field&)field(F_MSP_SORT), fe_init, 0L );
}
return some_lines;
}
return FALSE;
}
bool TPlanning_mask::carica_documenti()
{
const bool ignore_mag=get_bool(F_NOMAG_IN);
const bool ignore_imp=get_bool(F_NOIMP_IN);
const bool ignore_lin=get_bool(F_NOLIN_IN);
const bool ignore_cli=get_bool(F_NOCLI_IN);
const bool ignore_allcli=get_bool(F_NOCLI_OUT);
const bool is_master_sched = get_bool(F_MSCHEDULEPLAN);
const bool two_level = get_bool(F_2LEVEL_MSP);
TDate date_fr(starting_date());
const int bucket_fr = round_date(date_fr, FALSE);
TDate date_to = get(F_ADATA);
const int bucket_to = round_date(date_to, TRUE);
const TString80 f_art(get(F_FRART));
const bool f_art_fill = !f_art.empty();
TString80 t_art(get(F_TOART));
const bool t_art_fill = !t_art.empty();
TString16 f_grm(get(F_FRGRM)); f_grm.rpad(3);
f_grm << get(F_FRSGM); f_grm.trim();
const bool f_grm_fill = !f_grm.empty();
TString16 t_grm(get(F_TOGRM)); t_grm.rpad(3);
t_grm << get(F_FRSGM); t_grm.trim();
const bool t_grm_fill = !t_grm.empty();
const bool filtered = f_art_fill || t_art_fill || f_grm_fill || t_grm_fill;
const int year_fr = date_fr.year() - (get_bool(F_DOC_YEAR_PREC) ? 1 : 0);
const int year_to = date_to.year();
TTable num("%NUM");
TCodice_numerazione cod;
TRelation rel(LF_DOC);
TCursor cur(&rel);
const TRectype& curr = cur.curr();
TRectype filter_fr(curr), filter_to(curr);
_articles.destroy();
_constraints.destroy();
_proposed_articles.destroy();
// Scandisce tutte le numerazioni considerando solo quelle
// contenenti i tipi documento specificati nella maschera
for (int err = cod.first(num); err == NOERR; err = cod.next(num))
{
const int tn = test_codnum(cod);
if (tn)
{
// Filtra il cursore in modo da limitarlo alla numerazione
// corrente ed agli anni specificati dalle due date limite
filter_fr.put(DOC_PROVV, "D");
filter_fr.put(DOC_CODNUM, cod.get("CODTAB"));
filter_fr.put(DOC_ANNO, year_fr);
filter_to.put(DOC_PROVV, "D");
filter_to.put(DOC_CODNUM, cod.get("CODTAB"));
filter_to.put(DOC_ANNO, year_to);
cur.setregion(filter_fr, filter_to);
TString cfilter;
cfilter << DOC_CODNUM << "==" << '"' << cod.get("CODTAB")<< '"';
cur.setfilter(cfilter);
const long items = cur.items();
cur.freeze(TRUE);
// Scandisce i documenti inevasi e considera solo
// quelli con uno stato nel range corretto
TString msg;
msg.format(FR("Caricamento documenti %s (numerazione '%s')"),tn & _Doc_vincoli ? "ordine":"di planning",(const char *)cod.codice());
TProgind pi(items,msg , TRUE, TRUE);
for (cur = 0; cur.pos() < items; ++cur)
{
pi.addstatus(1);
if (pi.iscancelled())
return FALSE;
const bool evaso = curr.get_bool(DOC_DOCEVASO);
if (evaso)
continue;
// Calcola data di consegna per righe che non ce l'hanno
TDate datacons = curr.get(DOC_DATACONS);
if (!datacons.ok())
datacons = curr.get(DOC_DATADOC);
const int sheetrow=test_status(curr, tn);
if (sheetrow < 0)
continue;
// Scandisce le righe articolo e memorizza
// le quantita' richieste
TDocumento doc(cur.curr());
for (int r = doc.physical_rows(); r > 0; r--)
{
// Seleziona le righe articolo non ancora evase
const TRiga_documento& riga = doc[r];
if (riga.is_articolo())
{
const TCodice_articolo art = riga.get(RDOC_CODARTMAG);
const real qta = riga.qtaresidua();
bool ok = qta > ZERO;
if (ok && filtered)
{
if (ok && f_art_fill)
ok = art >= f_art;
if (ok && t_art_fill)
ok = art <= t_art;
if (ok && f_grm_fill)
ok = cache().get(LF_ANAMAG, art, ANAMAG_GRMERC) >= f_grm;
if (ok && t_grm_fill)
ok = cache().get(LF_ANAMAG, art, ANAMAG_GRMERC) <= t_grm;
}
if (ok)
{
const TString16 liv = livelli_giacenza().enabled() ? riga.get(RDOC_LIVELLO) : "";
const long cli = (ignore_cli && (tn & _Doc_vincoli)) ||ignore_allcli ? 0 : doc.get_long(DOC_CODCF) ;
const TString8 mag = ignore_mag && (tn & _Doc_vincoli) ? "" : riga.get(RDOC_CODMAG);
const TString8 magc = ignore_mag && (tn & _Doc_vincoli) ? "" : riga.get(RDOC_CODMAGC);
const TString8 imp = ignore_imp && (tn & _Doc_vincoli) ? "" : riga.get(RDOC_IMPIANTO);
const TString8 lin = ignore_lin && (tn & _Doc_vincoli) ? "" : riga.get(RDOC_LINEA);
const TCodice_um um = riga.get(RDOC_UMQTA);
TQuantita q(art, um, qta);
q.convert2umbase();
TDate consegna = riga.get(RDOC_DATACONS);
if (!consegna.ok())
consegna = datacons;
TDate consegna_upper(consegna);
int buck = round_date(consegna_upper,tn & _Doc_vincoli) - bucket_fr + 1;
if ((tn & _Doc_vincoli) && consegna_upper>consegna && !bucket_mese())
buck--;
if (buck < 0) buck = 0; else
if (buck > LAST_BUCKET) buck = LAST_BUCKET;
TMSP_constraint* line;
if (tn & _Doc_vincoli)
{
line = _constraints.find(cli, art, liv, imp, lin, mag, TRUE);
line->set_mastercode_check(two_level && !distinta_master(art));
}
else {
line = _articles.find(cli, art, liv, imp, lin, mag, magc, TRUE);
}
if (line->description().empty())
line->set_description(riga.get(RDOC_DESCR));
if (buck >= 0 && buck <= LAST_BUCKET)
{
int annodoc=riga.get_int(RDOC_ANNO);
TString8 codnum(cod.codice());
TString4 tiporiga(riga.get(RDOC_TIPORIGA));
char provv= riga.get_char(RDOC_PROVV);
long numdoc = riga.get_long(RDOC_NDOC);
int numrig = riga.get_int(RDOC_NRIGA);
real prz = riga.get_int(RDOC_PREZZO);
prz = prz / qta * q.val();
line->add_rigaref(buck, codnum, annodoc, numdoc, numrig, q.um(), q.val(), prz);// memorizza la provenienza dal doc
}
if (tn & _Doc_planning)
{
// controlla lo stato definitivo dei documenti
// appartenenti alla numerazione da generare
const bool confirmed = has_confirmed_status(rel.lfile().curr(), sfield(F_TIPI_PLA).row(sheetrow));
if (confirmed)
{
//line->qta_locked(buck) = TRUE;
line->qta_min(buck) += q.val();
} else {
//add_MRP_bucket(*find_propose(cli, art, liv, imp, lin, mag, magc, TRUE), buck, q.val());
}
}
line->qta(buck) += q.val();
real price;
find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
get(F_TIPOCF), cli, art,
line->qta(buck), price);
line->price(buck) = price;
}
}
}
}
cur.freeze(FALSE);
}
}
return _constraints.items() > 0L || _articles.items() > 0L;
}
// cerca il vincolo "migliore" secondo la logica :
// - stesso magazzino , impianto e linea
// - stesso magazzino e impianto
// - stesso magazzino
// - stesso impianto e linea
// - stessa linea
TMSP_constraint* TPlanning_mask::find_constraint(const TMSP_line& l, bool force_insert)
{
const bool ignore_mag=get_bool(F_NOMAG_IN);
const bool ignore_imp=get_bool(F_NOIMP_IN);
const bool ignore_lin=get_bool(F_NOLIN_IN);
const bool ignore_cli=get_bool(F_NOCLI_IN);
TString8 codmag=ignore_mag ? "" : l.codmagdep();
TString8 codimp=ignore_imp ? "" : l.codimp();
TString8 codlin=ignore_lin ? "" : l.codlin();
long codcli=ignore_cli ? 0L : l.codclifor() ;
// se il magazzino o l'impianto non e' indicato sul vincolo cerca di individuarlo
// in base ai default di linea/impianto
if (codimp.blank())
{
if (!codlin.blank())
{
TLinea_prod &linea_prod=*::get_linea(codlin);
codimp=linea_prod.codimp();
}
}
if (codmag.blank())
{
if (!codlin.blank())
{
TLinea_prod &linea_prod=*::get_linea(codlin);
codmag=linea_prod.codmagdep();
} else
if (!codimp.blank())
{
TImpianto &impianto=*::get_impianto(codimp);
codmag=impianto.codmagdep();
}
}
// cerca il vincolo con - stesso magazzino , impianto e linea
TMSP_constraint* c = _constraints.find(codcli, l.articolo(), l.livgiac(), codimp, codlin, codmag);
if (c == NULL )
{
long try_cli = codcli;
do {
if (!codmag.blank())
{
// cerca il vincolo con - stesso magazzino e impianto
c =_constraints.find(try_cli, l.articolo(), l.livgiac(), codimp, "", codmag);
if (c == NULL)
// cerca il vincolo con - stesso magazzino
c =_constraints.find(try_cli, l.articolo(), l.livgiac(), "", "", codmag);
}
if (c == NULL)
// cerca il vincolo con - stesso impianto e linea
c =_constraints.find(try_cli, l.articolo(), l.livgiac(), codimp, codlin, "");
if (c == NULL)
// cerca il vincolo con - stessa impianto
c =_constraints.find(try_cli, l.articolo(), l.livgiac(), codimp, "" , "");
if (try_cli == 0 )
try_cli = -1;
if (try_cli >0 )
try_cli = 0; // cerca il vincolo con altro fornitore
} while (c == NULL && try_cli >= 0);
}
if (c == NULL && force_insert)
{
// MA STO VINCOLO MANCA PROPRIO! ALLORA LO INSERISCO
c = _constraints.find(codcli, l.articolo(), l.livgiac(), codimp, codlin, codmag, TRUE);
if (c->description().blank())
c->set_description(l.description());
c->set_mastercode_check(get_bool(F_2LEVEL_MSP) && !distinta_master(l.articolo()));
}
return c;
}
// cerca la riga del vincolo e se non la trova
int TPlanning_mask::find_constr_row(TMSP_constraint& cons)
{
TSheet_field& sf = sfield(F_ARTICOLI);
const int maxart=sf.items();
for (int r=0; r <maxart; r++)
{
TToken_string &row=sf.row(r);
TString16 liv;
if (livelli_giacenza().enabled())
{
livelli_giacenza().pack_grpcode(liv, row.get(sf.cid2index(F_LIV1)),1);
livelli_giacenza().pack_grpcode(liv, row.get(sf.cid2index(F_LIV2)),2);
livelli_giacenza().pack_grpcode(liv, row.get(sf.cid2index(F_LIV3)),3);
livelli_giacenza().pack_grpcode(liv, row.get(sf.cid2index(F_LIV4)),4);
liv.trim();
}
TString16 imp(row.get(sf.cid2index(F_CODIMP)));imp.trim();
TString16 lin(row.get(sf.cid2index(F_CODLIN)));lin.trim();
TString16 mag;
add_magcode(mag, row.get(sf.cid2index(F_MAGAZZINO)));
add_depcode(mag, row.get(sf.cid2index(F_DEPOSITO )));
if (sf.cell_disabled(r, sf.cid2index(F_BUCKET1)))
{
if (cons.codclifor()==row.get_long(sf.cid2index(F_CLIENTE)) &&
cons.articolo() == row.get(sf.cid2index(F_ARTICOLO)) &&
cons.livgiac() == liv&&
cons.codimp()== imp &&
cons.codlin()==lin &&
cons.codmagdep()==mag )
return r;
else
r+=2;
}
}
// aggiunge le tre linee
TToken_string& row = sf.row(-1);
cons.fill_sheet_row(row, *this);
cons.set_on_sheet();
sf.disable_cell(sf.items()-1, -1);
//linea della giacenza prog
TToken_string& rowgiac = sf.row(-1);
copy_sheet_row(rowgiac,row);
sf.disable_cell(sf.items()-1, -1);
//linea articolo (vuota)
TMSP_line line(cons);
line.fill_sheet_row(sf.row(-1), *this);
rowgiac.add(TR("** Giacenza teorica"),F_DESCART-FIRST_FIELD);
row.add(TR("** Ordini "),F_DESCART-FIRST_FIELD);
r = sf.items()-3+2;
if (cons.codclifor())
sf.disable_cell(r,sf.cid2index(F_CLIENTE));
TArticolo_giacenza art(cons.articolo());
init_bucket0(art, r);
return r-2;
}
void TPlanning_mask::set_sheet_header()
{
TSheet_field& sl = sfield(F_LINEE);
TSheet_field& sf = sfield(F_ARTICOLI);
sf.enable_column(F_CLIENTE,!get_bool(F_NOCLI_OUT));
sf.set_column_header(F_CLIENTE-FIRST_FIELD,*get(F_TIPOCF)=='C' ? TR("Cliente") : TR("Fornitore"));
const TDate date_to = get(F_ADATA);
const int bucket_size = days_per_bucket();
const bool show_week = get_bool(F_SHOW_WEEK) && bucket_size>=7;
const bool show_price = get_bool(F_SHOWPRICES);
TDate d(starting_date());
int year, week;
TString str;
for (int b = 0; b <= LAST_BUCKET; b++)
{
round_date(d);
const bool on=(b > 0 && b < LAST_BUCKET && d < date_to);
sf.enable_column(F_BUCKET0 + b*2, on);
sf.enable_column(F_BUCKET0 + b*2+1, on && show_price );
sf.set_column_width(F_BUCKET0+1+b*2-FIRST_FIELD, show_price ? 140 : 0);
sl.enable_column(F_LBUCKET0 + b, on);
if (show_week)
{
get_week_year(d, week, year);
str = "S.";
str << week << '-' << year;
}
else
str = d.string();
switch(b)
{
case 0: str.insert("< "); break;
case LAST_BUCKET: str.insert(">= "); break;
default: d += bucket_size; break;
}
sl.set_column_header(F_LBUCKET0 + b, str);
str.insert(TR("Qta "));
sf.set_column_header(F_BUCKET0 + b*2, str);
str.overwrite(TR("Prz"));
sf.set_column_header(F_BUCKET0 + b*2 +1, str);
}
sf.force_update();
sl.force_update();
}
void TPlanning_mask::enable_codes(int row, bool on)
{
TSheet_field& sf = sfield(F_ARTICOLI);
const bool ignore_cli=get_bool(F_NOCLI_IN);
const bool ignore_imp=get_bool(F_NOIMP_IN);
const bool ignore_lin=get_bool(F_NOLIN_IN);
const bool ignore_mag=get_bool(F_NOMAG_IN);
sf.enable_cell(row,F_CLIENTE-FIRST_FIELD, on&& ignore_cli);
sf.enable_cell(row,F_CODIMP-FIRST_FIELD, on && ignore_imp);
sf.enable_cell(row,F_CODLIN-FIRST_FIELD, on && ignore_lin);
sf.enable_cell(row,F_MAGAZZINO-FIRST_FIELD, on && ignore_mag);
sf.enable_cell(row,F_DEPOSITO-FIRST_FIELD, on && ignore_mag);
sf.enable_cell(row,F_MAG_COLL-FIRST_FIELD, on && ignore_mag);
sf.enable_cell(row,F_DEP_COLL-FIRST_FIELD, on && ignore_mag);
}
void TPlanning_mask::fill_sheet()
{
set_sheet_header();
TSheet_field& sl = sfield(F_LINEE);
TSheet_field& sf = sfield(F_ARTICOLI);
TMSP_constraint* last_constraint = NULL;
TWait_cursor hourglass;
// *************
// parte 1: introduce gli articoli ed i loro vincoli associati
const long totart = _articles.sort();
for (long i = 0; i < totart; i++)
{
TMSP_line& line = _articles[i];
TMSP_constraint* curr_constraint = find_constraint(line,TRUE);
int new_row = -1;
for (int nrow = int (sf.items()) - 1; nrow >=0; nrow--)
{
if (sf.cell_disabled(nrow, F_BUCKET1-FIRST_FIELD))
{
last_constraint = _constraints.find(sf.row(nrow));
if (last_constraint == curr_constraint)
{
new_row = nrow + 1;
break;
}
}
}
if (last_constraint != curr_constraint)
{
// aggiunge la linea di vincolo
TToken_string& consrow = sf.row(-1);
curr_constraint->fill_sheet_row(consrow, *this);
consrow.add(TR("** Ordini "),F_DESCART-FIRST_FIELD);
sf.disable_cell(sf.items()-1, -1);
// aggiunge la linea della giacenza prog
TToken_string& rowgiac = sf.row(-1);
copy_sheet_row(rowgiac,consrow);
rowgiac.add(TR("** Giacenza teorica"),F_DESCART-FIRST_FIELD);
sf.disable_cell(sf.items()-1, -1);
// last_constraint = curr_constraint;
curr_constraint->set_on_sheet();
// int new_row=sf.items();
}
sf.insert(new_row);
TToken_string& row = sf.row(new_row);
line.fill_sheet_row(row, *this);
disable_codes(new_row);
if (curr_constraint->codclifor())
sf.disable_cell(new_row,sf.cid2index(F_CLIENTE));
}
// *************
// parte 2: introduce i rimanenti vincoli non relativi ad articoli caricati
const long totcon = _constraints.sort();
for (long j = 0; j < totcon; j++)
{
TMSP_constraint& cons = _constraints[j];
if (!cons.is_on_sheet())
{
// aggiunge le tre linee
TToken_string& consrow = sf.row(-1);
cons.fill_sheet_row(consrow, *this);
cons.set_on_sheet();
sf.disable_cell(sf.items()-1, -1);
//linea della giacenza prog
TToken_string& rowgiac = sf.row(-1);
copy_sheet_row(rowgiac,consrow);
sf.disable_cell(sf.items()-1, -1);
//linea articolo (vuota)
TMSP_line line(cons);
line.fill_sheet_row(sf.row(-1), *this);
rowgiac.add(TR("** Giacenza teorica"),F_DESCART-FIRST_FIELD);
consrow.add(TR("** Ordini "),F_DESCART-FIRST_FIELD);
if (consrow.get_long(sf.cid2index(F_CLIENTE)))
sf.disable_cell(sf.items()-1,sf.cid2index(F_CLIENTE));
}
}
TArticolo_giacenza art;
for (int r = sf.items()-1; r >0 ; )
{
// init bucket 0
TCodice_articolo codart(sf.cell(r,sf.cid2index(F_ARTICOLO)));
if (codart.blank())
r = r-2;
art.read(codart);
r=init_bucket0(art, r);
}
sortMSPsheet();
sf.force_update();
}
// ritorna il numero del bucket dell'eventuali proposte +1
// (NO_PROPOSE se nessuna proposta)
int TPlanning_mask::insert_propose(bool verbose)
{
int firstbuck=NO_PROPOSE;
if (_proposed_articles.items()>0L)
{
add_or_sub_propose(+1);
const long new_rows=_proposed_articles.items();
TDate firstdate(get_date(F_ADATA));
for (long new_row=0; new_row < new_rows; new_row++)
{
const TDate & d=_proposed_articles[new_row].time(0).date() ;
firstdate=min(firstdate,d);
}
firstbuck=int(bucket(firstdate) - bucket(starting_date()))+1;
}
return firstbuck;
}
bool TPlanning_mask::remove_propose(bool verbose)
{
bool remove = FALSE;
bool remove_all = FALSE;
bool some = _proposed_articles.items() > 0L; // proposte attuali
if (some)
remove = (!verbose || yesno_box(TR("Vuoi annullare le nuove proposte?")));
if (!some && verbose)
{
if (load_MRP_lines(_actual_plan))
{
some = _mrp_articles.items() > 0L;
if (some)
{
remove = (noyes_box(TR("Vuoi annullare tutte le pianificazioni non confermate?")));
if (remove && get_bool(F_RESCHEDULING) && noyes_box(TR("Vuoi annullare anche le pianificazioni confermate?")))
remove_all = TRUE;
}
if (!remove)
message_box(TR("Nessuna pianificazione da annullare"));
else
_proposed_articles = _mrp_articles;
}
}
if (remove)
{
add_or_sub_propose(-1, remove_all);
_proposed_articles.destroy();
}
return TRUE;
}
void TPlanning_mask::highlight(int row, int col, bool on)
{
COLOR back = on ? _sel_color.get_back_color(_npr_pos) : NORMAL_BACK_COLOR;
COLOR fore = on ? _sel_color.get_fore_color(_npr_pos) : NORMAL_COLOR;
sfield(F_ARTICOLI).set_back_and_fore_color(back, fore, row, col);
}
void TPlanning_mask::add_or_sub_propose(char sign, bool scheduled)
{
CHECK(sign <0 || !scheduled, "Le qta schedulate possono solo venire sottratte");
TWait_cursor hourglass;
const long new_rows=_proposed_articles.items();
TSheet_field& sf = sfield(F_ARTICOLI);
for (long new_row=0; new_row < new_rows; new_row++)
{
const TMRP_line & a=_proposed_articles[new_row];
TMSP_line line(a.codclifor(), a.articolo(), a.livgiac(), a.codimp(), a.codlin(), a.codmagdep(), a.codmagdep_coll());
bool line_found=FALSE;
TMSP_constraint* constraint= find_constraint(line,FALSE);
if (constraint==NULL)
{
CHECK( sign>0, "Impossibile trovare il vincolo da soddisfare...");
// aggiunge le tre linee
constraint=new TMSP_constraint(line);
TToken_string& row = sf.row(-1);
constraint->fill_sheet_row(row, *this);
constraint->set_on_sheet();
sf.disable_cell(sf.items()-1, -1);
//linea della giacenza prog
TToken_string& rowgiac = sf.row(-1);
copy_sheet_row(rowgiac,row);
sf.disable_cell(sf.items()-1, -1);
//linea articolo (vuota)
TToken_string& emptyrowc = sf.row(-1);
rowgiac.add(TR("** Giacenza teorica"),F_DESCART-FIRST_FIELD);
row.add(TR("** Ordini "),F_DESCART-FIRST_FIELD);
}
int art_row;
for (art_row=int(sf.items())-1;art_row >=0; art_row--)
{
TToken_string &row=sf.row(art_row);
long codcli;
TCodice_articolo codart ;
TString16 liv;
TString8 mag, magc, codimp, codlin, codum;
msprow2codes(row,codcli,codart,liv, mag, magc, codimp, codlin, codum);
if (!sf.cell_disabled(art_row, F_BUCKET1-FIRST_FIELD))
{
line_found=(a.codclifor()==codcli && a.articolo()==codart && a.livgiac()==liv
&& a.codimp()==codimp && a.codlin()==codlin && a.codmagdep()==mag );
if (line_found)
break;
} else {
TMSP_constraint* currcons=_constraints.find(codcli, codart, liv, codimp, codlin, mag);
if (constraint==currcons)
break;
}
}
if (!line_found)
{
art_row++;
sf.insert(art_row);
TToken_string& predrow = sf.row(art_row-1);
TToken_string& artrow = sf.row(art_row);
constraint->fill_sheet_row(artrow, *this,TRUE);
artrow.add(predrow.get_long(F_PRIORITA-FIRST_FIELD), F_PRIORITA-FIRST_FIELD);
artrow.add(get(F_TIPOCF),F_TIPOCF_SHEET-FIRST_FIELD);
artrow.add(a.codclifor(), F_CLIENTE-FIRST_FIELD);
artrow.add(a.codimp(), F_CODIMP-FIRST_FIELD);
artrow.add(a.codlin(), F_CODLIN-FIRST_FIELD);
TString8 str=a.codmagdep().left(3);
artrow.add(str, F_MAGAZZINO-FIRST_FIELD);
str=a.codmagdep().mid(3);
artrow.add(str, F_DEPOSITO-FIRST_FIELD);
str=a.codmagdep_coll().left(3);
artrow.add(str, F_MAG_COLL-FIRST_FIELD);
str=a.codmagdep_coll().mid(3);
artrow.add(str, F_DEP_COLL-FIRST_FIELD);
}
TToken_string& artrow = sf.row(art_row);
const int lastbuck = _proposed_articles[new_row].last_bucket();
for (int nbucket=0; nbucket<=lastbuck ; nbucket++)
{
int b = bucket( _proposed_articles[new_row].time(nbucket).date() );
real art_per_buck(artrow.get(F_BUCKET1 + b*2 - FIRST_FIELD));
real prop = _proposed_articles[new_row].planned_orders(nbucket);
if (sign>0)
art_per_buck += prop;
else
{
if (b>=0)
{
if (scheduled)
prop += _proposed_articles[new_row].sched_receipts(nbucket);
if (art_per_buck > prop)
art_per_buck -= prop;
else
art_per_buck = ZERO;
}
}
highlight(art_row, F_BUCKET1 + b*2, prop != ZERO && art_per_buck != ZERO);
artrow.add(art_per_buck.string(), F_BUCKET1 + b*2 - FIRST_FIELD);
real price;
if (!art_per_buck.is_zero())
find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
get(F_TIPOCF), a.codclifor(), a.articolo(),
art_per_buck, price);
artrow.add(price.string(), F_BUCKET1 + b*2 + 1 - FIRST_FIELD);
}
test_art_row(art_row,FALSE);
}
sf.force_update();
}
void TPlanning_mask::check_articles()
{
TSheet_field& sf = sfield(F_ARTICOLI);
int items=sf.items();
if (items==0)
{
message_box(TR("Nessun articolo da verificare"));
return;
}
TMSPCheck_mask cm(this);
int curr_row=sf.selected();
const bool is_disabled=sf.cell_disabled(curr_row,F_BUCKET1-FIRST_FIELD) ;
const bool is_constr=(is_disabled && curr_row>0 && sf.cell_disabled(curr_row-1,F_BUCKET1-FIRST_FIELD));
if (is_disabled && !is_constr)
curr_row++;
cm.gopos(curr_row, 1);
cm.run();
cm.gopos_mainmask();
}
void TPlanning_mask::check_capacities()
{
TSheet_field& sf = sfield(F_LINEE);
int items=sf.items();
if (items==0)
{
message_box(TR("Nessun carico di linea da verificare"));
return;
}
TCRPCheck_mask cm(this);
cm.run();
set_focus_field(sf.dlg());
sf.set_focus_cell(cm.last_row(),cm.last_col()+F_LBUCKET0);
}
bool TPlanning_mask::sortMSPsheet()
{
TWait_cursor hg;
TSheet_field& a = sfield(F_ARTICOLI);
switch (-get_int(F_MSP_SORT))
{
case SORT_BY_CAL: a.sort(TRiga_articolo::order_compareCAL); break;
case SORT_BY_CLA: a.sort(TRiga_articolo::order_compareCLA); break;
case SORT_BY_ACL: a.sort(TRiga_articolo::order_compareACL); break;
case SORT_BY_ALC: a.sort(TRiga_articolo::order_compareALC); break;
case SORT_BY_LCA: a.sort(TRiga_articolo::order_compareLCA); break;
case SORT_BY_LAC: a.sort(TRiga_articolo::order_compareLAC); break;
case SORT_BY_PCAL: a.sort(TRiga_articolo::order_comparePCAL); break;
case SORT_BY_PCLA: a.sort(TRiga_articolo::order_comparePCLA); break;
case SORT_BY_PACL: a.sort(TRiga_articolo::order_comparePACL); break;
case SORT_BY_PALC: a.sort(TRiga_articolo::order_comparePALC); break;
case SORT_BY_PLCA: a.sort(TRiga_articolo::order_comparePLCA); break;
case SORT_BY_PLAC: a.sort(TRiga_articolo::order_comparePLAC); break;
case SORT_BY_AC: a.sort(TRiga_articolo::order_compareAC); break;
case SORT_BY_CA: a.sort(TRiga_articolo::order_compareCA); break;
case SORT_BY_PAC: a.sort(TRiga_articolo::order_comparePAC); break;
case SORT_BY_PCA: a.sort(TRiga_articolo::order_comparePCA); break;
default:
return FALSE;
}
a.force_update();
return TRUE;
}
bool TPlanning_mask::sortCRPsheet()
{
TWait_cursor hg;
TSheet_field& a = sfield(F_LINEE);
a.sort();
a.force_update();
return TRUE;
}
void TPlanning_mask::add_MRP_bucket(TMRP_line& new_article, int nbucket, const real &curr_arts)
{
TDate data_buck;
data_buck=starting_date();
data_buck+=days_per_bucket()*(nbucket-1);
round_date(data_buck);
TMRP_time t(data_buck, 0, "", "");
new_article.add_planned_ord(t, curr_arts );
}
void TPlanning_mask::propose(int row)
{
const bool useextralines=get_bool(F_USENONSTDLIN_MSP);
const bool useextrahours=get_bool(F_USEEXTRAHRS_MSP) ;
set(F_USENONSTDLIN_CRP ,useextralines ? "X" : "");
set(F_USEEXTRAHRS_CRP ,useextrahours ? "X" : "");
const TString& rt = get(F_RECALC_TYPE);
if (rt=="1")
propose_1stJIT(_first_fit_logic,TRUE,TRUE, row);
else if (rt=="1_INFH")
propose_1stJIT(_first_fit_logic,TRUE,FALSE, row);
else if (rt=="1_INF")
propose_1stJIT(_first_fit_logic,FALSE,FALSE, row);
else if (rt=="JIT")
propose_1stJIT(_JIT_logic,TRUE,TRUE, row);
else if (rt=="JIT_INFH")
propose_1stJIT(_JIT_logic,TRUE,FALSE, row);
else if (rt=="JIT_INF")
propose_1stJIT(_JIT_logic,FALSE,FALSE, row);
else if (rt=="UNIL")
propose_1stJIT(_uniform_logic,TRUE,FALSE, row);
else if (rt=="UNI")
propose_1stJIT(_uniform_logic,FALSE,FALSE, row);
// aggiorna lo sheet delle capacita'
}
// propone secondo la logica FirstFit o JIT
void TPlanning_mask::propose_1stJIT(TMSP_logic logic, bool check_machine, bool check_human, int numriga)
{
const bool useextralines=get_bool(F_USENONSTDLIN_MSP);
const bool useextrahours=get_bool(F_USEEXTRAHRS_MSP) ;
const bool lotsizing=get_bool(F_LOTSIZING) ;
const bool no_outcapacity=get_bool(F_OUTOFCAPACITY) ;
bool ok=TRUE;
TWait_cursor clessidra;
// per sicurezza devo (ri-)calcolare il carico attuale.....
_capacities.destroy();
if (check_machine || check_human)
{
if (ok = load_MRP_lines(_actual_plan))
{
gross2net(_actual_plan,FALSE);
ok = general_review(check_machine, check_human, useextralines, useextrahours,FALSE, no_outcapacity,0, 0,_actual_plan, logic, TR("Calcolo carico minimo..."));
}
}
// (two) levels master scheduling
TMRP_lines last_propose;
int buck=NO_PROPOSE;
for (int level=1; ok && level <= 2; level++)
{
if (ok = load_MRP_lines(_stock_break, level, numriga))
{
_proposed_articles.destroy();
gross2net(_stock_break, lotsizing);
const char * msg;
msg = (level == 1) ? TR("Calcolo nuove proposte (articoli non Master)") :TR("Calcolo nuove proposte");
const int anticipomin=get_int((level == 2) ? F_ANTICIPOMIN : F_ANTICIPOMIN2);
const int anticipomax=get_int((level == 2) ? F_ANTICIPOMAX : F_ANTICIPOMAX2);
if (ok = general_review(check_machine, check_human, useextralines, useextrahours,lotsizing, no_outcapacity,anticipomin,anticipomax,_stock_break, logic, msg))
{
int buck2 = insert_propose(FALSE);
buck = min (buck,buck2);
if (level!=2)
last_propose.add(_proposed_articles);
else
{
_proposed_articles.add(last_propose);
if (buck!=NO_PROPOSE)
{
TDate dbuck(starting_date());
dbuck +=buck*days_per_bucket();
round_date(dbuck);
message_box(FR("Quantita' proposte a partire dal %s (colonna %d)"), (const char *)dbuck.string(),buck);
}
else
message_box(TR("Nessuna nuova proposta"));
}
}
else
_proposed_articles = last_propose;
}
}
if (!ok)
remove_propose();
_capacities.sort();
}
// propone i valori con logica first-fit
// cerca il primo bucket con capacit<69> produttiva
bool TPlanning_mask::general_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode, TMSP_logic logic, const char * msg )
{
const bool ignore_mag=get_bool(F_NOMAG_IN);
const bool ignore_imp=get_bool(F_NOIMP_IN);
const bool ignore_lin=get_bool(F_NOLIN_IN);
TLavorazione *curr_labor;
TLinea_prod linea_prod;
TArray labors;
const long max_mrp_rows=_mrp_articles.items();
TProgind pi((max_mrp_rows+1)*LAST_BUCKET ,msg, TRUE, TRUE);
for (int bucket = 0; bucket < LAST_BUCKET ; bucket++)
{
pi.addstatus(1);
for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
{
pi.addstatus(1);
if (pi.iscancelled())
return FALSE;
TMRP_line &mrpline=_mrp_articles[mrp_row];
TDate data_buck(starting_date());
data_buck+=days_per_bucket()*(bucket-1);
round_date(data_buck);
const TMRP_time mrp_time(data_buck, 0, "","");
TMRP_record & mrp_rec= mrpline.record(mrp_time);
real pieces, curr_arts, art_per_buck(mrp_rec.net_requirement()); // quantit<69> da produrre nel bucket
if (art_per_buck>ZERO)
{
int lastbuck =mrpline.last_bucket();
TString16 livello_di_giacenza(mrpline.livgiac());
TString8 codlin(mrpline.codlin());
TString8 codimp(mrpline.codimp());
dist_tree().set_global("_LIVELLO",livello_di_giacenza);
dist_tree().set_global("_IMPIANTO",codimp);
dist_tree().set_global("_LINEA",codlin);
dist_tree().set_global("_MAGDEP",mrpline.codmagdep());
bool no_limits=(logic == _uniform_logic && !check_machine)
|| !dist_tree().set_root(mrpline.articolo());
if (!no_limits)
{
TRiga_esplosione * l=dist_tree().first_critical_labor(labors);
no_limits=(l==NULL);
if (!no_limits)
{
curr_labor=TDistinta_tree::find_labor(l);
// cerca le linee sulle quali e' possibile eseguire questa lavorazione
// e la carica con la lavorazione relativa all'articolo corrente
const int lineestd = curr_labor->linee_standard();
const int maxlinee = useextralines ? curr_labor->linee() : lineestd;
TCRP_line *crpline_art,*crpline_lin,*crpline_imp,*crpline_firm;
real load, capacity, unit_load, hload, hcapacity, unit_hload ; // carichi di linea
int nbucket, lower_buck, upper_buck;
int attemp=1; // primo tentativo: rimane entro i vincoli di minimo e massimo anticipo utilizando solo le linee STD
// secondo tentativo: rimane entro i vincoli di minimo e massimo anticipo utilizando anche le linee non STD
// terzo tentativo: supera i vincoli di minimo e massimo anticipo utilizando anche le linee non STD
art_per_buck.round(5);
//if (nbucket>bucket)
if (art_per_buck > mrpline.net_requirement(lastbuck) && mode != _actual_plan)
{
// il sotto stock si propagherebbe fino alla fine ?
art_per_buck = mrpline.net_requirement(lastbuck) ;
mrpline.set_net_req(bucket,art_per_buck);
}
while (art_per_buck > ZERO && attemp <= 3)
{
if (logic == _JIT_logic)
{
lower_buck = (attemp <= 2 ? bucket-anticipomax/days_per_bucket() : 1);
upper_buck = bucket - anticipomin/days_per_bucket();
} else {
lower_buck = bucket - anticipomax/days_per_bucket();
upper_buck = (attemp <= 2 ? bucket-anticipomin/days_per_bucket(): LAST_BUCKET);
}
if (lower_buck<1)
lower_buck=1;
if (upper_buck>bucket)
upper_buck=bucket;
nbucket= (logic == _JIT_logic) ? upper_buck : lower_buck;
while (art_per_buck > ZERO // ho un sotto-stock da risolvere
&& nbucket>=lower_buck && nbucket <= upper_buck) // sono entro il range definito
{
int nlinea, numlinee;
if (ignore_lin || codlin.blank() )
{
nlinea=(attemp == 2 ? lineestd : 0 ) ;
numlinee=(attemp == 1 ? lineestd : maxlinee ) ;
} else {
nlinea= curr_labor->find_linea(codlin);
if (nlinea<0)
{
error_box(FR("La linea %s non e' in grado di produrre l'articolo %s"), (const char * )codlin, (const char *) _mrp_articles[mrp_row].articolo());
break;
}
numlinee=nlinea+1;
}
while (art_per_buck > ZERO && nlinea >= 0 && nlinea<numlinee && nbucket <= upper_buck)
{
// scelgo la linea
linea_prod= cache().get("LNP",curr_labor->cod_linea(nlinea));
TString8 codimplin=linea_prod.codimp();
if ( ignore_imp || codimp.blank() || codimp == codimplin)
{
crpline_lin = _capacities.find(linea_prod);
if (crpline_lin == NULL)
crpline_lin = compute_capacity(linea_prod,useextralines, useextrahours);
crpline_art = _capacities.find(codimplin, linea_prod.codice(), mrpline.articolo(), mrpline.codclifor(),TRUE);
crpline_imp = _capacities.find(codimplin);
crpline_firm = _capacities.find();
int human_level = 1;
if ( linea_prod.personale_dedicato())
human_level = 3;
else if (linea_prod.get_impianto() && linea_prod.get_impianto()->personale_dedicato())
human_level = 2;
// individua il massimo caricabile sulla linea
unit_load = l->val()*curr_labor->um_temporale().converti_in_ore()/curr_labor->produttiv_linea(nlinea);
unit_hload = unit_load*curr_labor->numpers_linea(nlinea);
capacity = check_machine ? crpline_lin->capacity(nbucket).machine() : MAXCAPACITY;
load = crpline_lin->load(nbucket).machine();
switch (human_level)
{
case 3:
hcapacity = crpline_lin->capacity(nbucket).human() ;
hload = crpline_lin->load(nbucket).human();
break;
case 2:
hcapacity = crpline_imp->capacity(nbucket).human() ;
hload = crpline_imp->load(nbucket).human();
break;
default:
hcapacity = crpline_firm->capacity(nbucket).human() ;
hload = crpline_firm->load(nbucket).human();
break;
}
curr_arts = art_per_buck;
if (logic == _uniform_logic)
curr_arts /= upper_buck > nbucket ? (upper_buck-nbucket+1) : 1;
if (mode == _stock_break /*|| no_outcapacity*/)
{
// ridimensiona al massimo numero di articoli dovuto alle macchine
capacity *= (100.0+get_int(F_EXTRACAPACITY))/100.0;
if (load + curr_arts * unit_load > capacity )
{
curr_arts = (capacity - load ) / unit_load;
curr_arts.floor();
}
hcapacity *= (100.0+get_int(F_EXTRAHCAPACITY))/100.0;
// ridimensiona al massimo numero di articoli dovuto alle macchine
if (check_human && hload + curr_arts * unit_hload > hcapacity)
{
curr_arts = (hcapacity - hload) / unit_hload;
curr_arts.floor();
}
/*
// elimina i picchi di capacita' (errato)
if (curr_arts != art_per_buck && mode == _actual_plan)
{
TMRP_line* new_article = _proposed_articles.find(mrpline.codice(),
mrpline.livgiac(), mrpline.codmagdep(),
linea_prod.codimp() , linea_prod.codice(), mrpline.codcli(), TRUE);
add_MRP_bucket(*new_article, nbucket, curr_arts-art_per_buck );
}*/
}
if (curr_arts>ZERO)
{
// aggiunge il carico macchina
art_per_buck -= curr_arts;
load= curr_arts * unit_load;
crpline_art->load(nbucket).add_machine(load);
crpline_lin->load(nbucket).add_machine(load);
// aggiunge il numero pezzi
pieces = curr_arts * cache().get(LF_ANAMAG,mrpline.articolo()).get_real(ANAMAG_PPCONF);
crpline_art->load(nbucket).add_pieces(pieces);
crpline_lin->load(nbucket).add_pieces(pieces);
crpline_imp->load(nbucket).add_pieces(pieces);
// aggiunge l'impegno finanziario
pieces = curr_arts * cache().get(LF_ANAMAG,mrpline.articolo()).get_real(ANAMAG_COSTSTD);
crpline_art->load(nbucket).add_money(pieces);
crpline_lin->load(nbucket).add_money(pieces);
crpline_imp->load(nbucket).add_money(pieces);
hload = load*curr_labor->numpers_linea(nlinea);
switch (human_level)
{
case 3:
crpline_lin->load(nbucket).add_human(hload);
case 2:
crpline_imp->load(nbucket).add_human(hload);
case 1:
crpline_firm->load(nbucket).add_human(hload);
}
crpline_art->load(nbucket).add_human(hload) ;
if (mode == _stock_break)
{
TString8 codmag(mrpline.codmagdep());
TString8 codmagc(mrpline.codmagdep_coll());
if (codmag.blank())
codmag = linea_prod.codmagdep();
if (codmagc.blank())
codmagc = linea_prod.codmagdep_coll();
TMRP_line* new_article = find_propose(mrpline.codclifor(), mrpline.articolo(),
mrpline.livgiac(), codimplin , linea_prod.codice(), codmag, codmagc, TRUE);
add_MRP_bucket(*new_article, nbucket, curr_arts);
}
}
} else
error_box("Articolo %s: impianto %s incompatibile con la linea %s",(const char *)mrpline.articolo(), (const char *)codimp, (const char *)linea_prod.codice());
if (logic == _uniform_logic)
nbucket++;
else
nlinea++;
} // ciclo sulle linee
if (logic == _first_fit_logic)
nbucket++;
else
if (logic != _uniform_logic)
nbucket--;
}
attemp++; // altro tentativo
} // ciclo di risoluzione dei sotto-stock
}
// qui andrebbe aggiunta la gestione di pi<70> lavorazioni critiche, ora disabled
// l=dist_tree().next_critical_labor(labors);
}
if (mode == _stock_break)
{
if (no_limits) // nessuna lavorazione da controllare o capacita' infinita
{
int nbucket, lower_buck, upper_buck;
if (logic == _uniform_logic)
{
lower_buck = bucket - anticipomax/days_per_bucket();
upper_buck = bucket-anticipomin/days_per_bucket();
} else if (logic == _first_fit_logic) {
lower_buck = bucket - anticipomax/days_per_bucket();
upper_buck = lower_buck;
} else {
upper_buck = bucket - anticipomin/days_per_bucket();
lower_buck = upper_buck;
}
if (lower_buck<1)
lower_buck=1;
if (upper_buck>bucket)
upper_buck=bucket;
nbucket = lower_buck;
//if (nbucket>bucket) // sono oltre il bucket attuale ?...
if (art_per_buck > mrpline.net_requirement(lastbuck)) // il sotto stock si propagherebbe fino alla fine del periodo?
{
art_per_buck = mrpline.net_requirement(lastbuck) ;
mrpline.set_net_req(bucket,art_per_buck);
}
while (nbucket <= upper_buck)
{
long codclifor = mrpline.codclifor() ;
TString16 codmagdep = mrpline.codmagdep();
if (is_acq_planning() && codclifor == 0L)
{
TArticolo art(mrpline.articolo());
codclifor = art.get_long(ANAMAG_CODFORN);
if (codclifor == 0L)
codclifor = _standard_for;
if (codclifor != 0L && codmagdep.empty())
{
TString16 key; key.format("F|%ld", codclifor);
const TRectype & venrec = cache().get(LF_CFVEN, key);
codmagdep = venrec.get(CFV_CODMAG);
if (codmagdep.not_empty())
{
codmagdep.left_just(3);
codmagdep << venrec.get(CFV_CODDEP);
}
}
}
if (codmagdep.empty())
{
if (codmagdep.empty())
{
codmagdep = _magazzini.standardmag();
codmagdep.left_just(3);
codmagdep << _magazzini.standarddep();
}
}
TMRP_line* new_article = find_propose(codclifor, mrpline.articolo(), mrpline.livgiac(),
mrpline.codimp() , mrpline.codlin(), codmagdep, mrpline.codmagdep_coll(), TRUE);
curr_arts = art_per_buck;
if (logic == _uniform_logic)
curr_arts /= (upper_buck-nbucket+1);
add_MRP_bucket(*new_article, nbucket, curr_arts);
art_per_buck -= curr_arts;
nbucket++;
}
}
// gestione del pending
real pending(art_per_buck);
pending -= mrpline.net_requirement(bucket);
if (pending != ZERO || art_per_buck != ZERO)
{
const TDate lastdate = mrpline.record(lastbuck).time().date();
int b=bucket+1;
do {
data_buck=starting_date();
data_buck+=days_per_bucket()*(b-1);
round_date(data_buck);
const TMRP_time t(data_buck, 0, "","");
if (b <= lastbuck)
mrpline.add_net_req(b, pending);
else
mrpline.add_net_req(t, art_per_buck); // ?!?!?! perche?
b++;
} while (lastdate > data_buck);
}
}
}
}
}
return TRUE;
}
bool TPlanning_mask::capacity_review(bool useextralines, bool useextrahours)
{
bool ok;
TWait_cursor clessidra;
if (!load_MRP_lines(_actual_plan))
return FALSE;
gross2net(_actual_plan);
_capacities.destroy();
const char *msg=TR("Calcolo carico attuale...");
if (get(F_RECALC_TYPE).left(1)=="1")
ok = general_review(TRUE, TRUE, useextralines, useextrahours, FALSE, FALSE, 0, 0, _actual_plan,_first_fit_logic, msg);
else if (get(F_RECALC_TYPE).left(3)=="JIT")
ok = general_review(TRUE, TRUE, useextralines, useextrahours, FALSE, FALSE, 0, 0, _actual_plan,_first_fit_logic, msg);
_capacities.sort();
return ok;
}
TCRP_line *TPlanning_mask::compute_capacity(TLinea_prod &lineaprod, bool useextralines, bool useextrahours)
{
TString8 codlin(lineaprod.codice());
TString8 codimp(lineaprod.codimp());
TMRP_calendar & cal = TMRP_time::get_calendar("", codlin);
TMRP_calendar & cal_imp = TMRP_time::get_calendar(codimp);
TMRP_calendar & cal_firm = TMRP_time::get_calendar();
CHECK(_capacities.find(lineaprod,FALSE)==NULL,"Errore: impossibile ricalcolare la capacit<69> di una linea produttiva");
TCRP_line *crpline_lin,*crpline_imp,*crpline_firm;
crpline_lin =_capacities.find(lineaprod, "", 0L,TRUE);
const bool compute_imp = (_capacities.find(codimp, "", "", 0L)==NULL);
crpline_imp =_capacities.find(codimp, "", "", 0L, TRUE);
const bool compute_firm = (_capacities.find("", "", "", 0L)==NULL);
crpline_firm=_capacities.find("", "", "", 0L, TRUE);
// calcola la capacita'
TDate data_buck=starting_date();
TDate next_data_buck = data_buck;
real capacity,human,human_imp,human_firm;
for (int b=1; b<LAST_BUCKET ; b++)
{
capacity=ZERO;
human=ZERO;
human_imp=ZERO;
human_firm=ZERO;
next_data_buck += days_per_bucket();
round_date(next_data_buck);
while (data_buck < next_data_buck)
{
cal.add_oremacchina(capacity, data_buck,useextrahours);
if (lineaprod.personale_dedicato())
cal.add_oreuomo(human, data_buck,useextrahours);
if (compute_imp && lineaprod.get_impianto() && lineaprod.get_impianto()->personale_dedicato())
cal_imp.add_oreuomo(human_imp, data_buck,useextrahours);
if (compute_firm)
cal_firm.add_oreuomo(human_firm, data_buck,useextrahours);
++data_buck;
}
crpline_lin->capacity(b).set_machine(capacity);
if (human > ZERO)
{
crpline_lin->capacity(b).set_human(human);
// crpline_imp->capacity(b).set_human(human+crpline_imp->capacity(b).human());
// crpline_firm->capacity(b).set_human(human+crpline_firm->capacity(b).human());
}
if (human_imp > ZERO)
{
crpline_imp->capacity(b).set_human(human_imp+crpline_imp->capacity(b).human());
// crpline_firm->capacity(b).set_human(human_imp+crpline_firm->capacity(b).human());
}
if (human_firm > ZERO)
crpline_firm->capacity(b).set_human(human_firm+crpline_firm->capacity(b).human());
}
return crpline_lin;
}
TMRP_line* TPlanning_mask::find_propose(
long codcli, const char * codart,const char * liv,
const char * codimp,const char * codlin,
const char * mag, const char * magcoll, bool Force)
{
return _proposed_articles.find(codart, liv, mag, magcoll, codimp, codlin, codcli, Force);
}
// carica le MRP line dallo sheet articoli
void TPlanning_mask::msprow2codes(TToken_string &row,long &clifor, TCodice_articolo &art ,
TString & liv, TString & mag, TString & magc, TString & imp, TString & lin, TString & um)
{
clifor = row.get_long(F_CLIENTE-FIRST_FIELD);
art = row.get(F_ARTICOLO-FIRST_FIELD);
if (livelli_giacenza().enabled())
{
livelli_giacenza().pack_grpcode(liv, row.get(F_LIV1-FIRST_FIELD),1);
livelli_giacenza().pack_grpcode(liv, row.get(F_LIV2-FIRST_FIELD),2);
livelli_giacenza().pack_grpcode(liv, row.get(F_LIV3-FIRST_FIELD),3);
livelli_giacenza().pack_grpcode(liv, row.get(F_LIV4-FIRST_FIELD),4);
liv.trim();
}
add_magcode(mag,row.get(F_MAGAZZINO-FIRST_FIELD));
add_depcode(mag,row.get(F_DEPOSITO-FIRST_FIELD));
add_magcode(magc,row.get(F_MAG_COLL-FIRST_FIELD));
add_depcode(magc,row.get(F_DEP_COLL-FIRST_FIELD));
imp = row.get(F_CODIMP-FIRST_FIELD); imp.trim();
lin = row.get(F_CODLIN-FIRST_FIELD); lin.trim();
um = row.get(F_UM-FIRST_FIELD); um.trim();
}
void TPlanning_mask::crprow2codes(TToken_string &row, TString & imp, TString & lin, long &clifor, TCodice_articolo &art ,
TString & liv, TString & um)
{
clifor=0L;
//clifor = row.get_long(F_CLIENTE-FIRST_FIELD);
//art = row.get(F_ARTICOLO-FIRST_FIELD);
//livelli_giacenza().pack_grpcode(liv, row.get(F_LIV1-FIRST_FIELD),1);
//livelli_giacenza().pack_grpcode(liv, row.get(F_LIV2-FIRST_FIELD),2);
//livelli_giacenza().pack_grpcode(liv, row.get(F_LIV3-FIRST_FIELD),3);
//livelli_giacenza().pack_grpcode(liv, row.get(F_LIV4-FIRST_FIELD),4);
imp = row.get(F_CODIMPCRP-FIRST_FIELD); imp.trim();
lin = row.get(F_CODLINCRP-FIRST_FIELD); lin.trim();
um = row.get(F_LUM-FIRST_FIELD); um.trim();
}
// carica le MRP line dallo sheet articoli
bool TPlanning_mask::load_MRP_lines(TMSP_mode mode, int level, int numriga)
{
TSheet_field& sa = sfield(F_ARTICOLI);
if (sa.items()==0)
{
message_box(TR("Nessun articolo da valutare"));
return FALSE;
}
TWait_cursor hourglass;
int first_row=-1, last_row=-1;
if (numriga >= 0)
{
TRiga_articolo::find_block(sa, numriga, first_row, last_row);
first_row--;
}
const int a_buck0 = sa.cid2index(F_BUCKET0);
TDate data_buck;
_mrp_articles.destroy();
// calcola gli impegni di produzione per gli articoli dello sheet
TMRP_line* curr_article=NULL;
int added_on = -1;
bool skip=FALSE;
FOR_EACH_SHEET_ROW(sa, r, row) if (!sa.cell_disabled(r, a_buck0+2) || sa.cell_disabled(r+1, a_buck0+2))
{
if (first_row < 0 || r >=first_row && r <=last_row)
{
const bool is_constraint=sa.cell_disabled(r, a_buck0+2);
if (is_constraint)
{
bool is_second_level;
const int prior=get_int(F_2LEVEL_PRIORITY);
if (prior>0)
is_second_level=(atoi(row->get(F_PRIORITA-FIRST_FIELD))>=prior);
else
is_second_level=(row->get_char(F_MASTERCODE-FIRST_FIELD)==MASTERCODE_CHAR);
skip = (level == 1 && !is_second_level || level == 2 && is_second_level );
}
if (!skip)
{
long clifor;
TCodice_articolo art ;
TString16 liv;
TString8 mag, magc, imp, lin;
TCodice_um um ;
msprow2codes(*row, clifor, art, liv, mag, magc, imp, lin, um);
if ((is_constraint && mode == _stock_break ) ||
(!is_constraint && mode == _actual_plan) ||
(is_constraint && mode == _rescheduling) )
{
curr_article = _mrp_articles.find(art, liv, mag, magc, imp, lin, clifor ,TRUE);
added_on = -1;
}
TMSP_line* mspline = _articles.find(*row, FALSE);
if ((mode == _stock_break ) ||
(!is_constraint && mode == _actual_plan) ||
(!is_constraint && mode == _rescheduling) )
for (int nbucket=LAST_BUCKET-1; nbucket>=0 ; nbucket--)
{
data_buck=starting_date();
data_buck+=days_per_bucket()*(nbucket-1);
round_date(data_buck);
const TMRP_time t(data_buck, 0, imp, lin);
real qta=row->get(a_buck0+nbucket*2);
TQuantita q(art, um, qta);
q.convert2umbase();
real rq(mspline ? mspline->qta_min(nbucket) : ZERO);
// mette i vincoli nel gross req
// e le celle normali negli sched receipts
switch (mode)
{
case _rescheduling:
if ((!qta.is_zero() || !rq.is_zero() || added_on>nbucket)&&
(nbucket>0))
{
curr_article->add_planned_ord(t, q.val());
if (mspline)
{
// transfer docs' refs
TMRP_docref * ref = mspline->first_rigaref(nbucket);
while (ref)
{
if (has_confirmed_status(ref->codnumdoc(),ref->tipodoc(),ref->statodoc()))
curr_article->add_sched_rec(t, ref->qta_residua(), ref);
ref = mspline->next_rigaref(nbucket);
}
}
added_on = nbucket;
}
break;
case _actual_plan:
if (!qta.is_zero())
{
if (curr_article)
{
curr_article->add_sched_rec(t, rq);
curr_article->add_planned_ord(t, q.val() - rq);
added_on = nbucket;
}
}
else if (added_on > nbucket)
curr_article->set_on_hand(t, ZERO); // per settare tutti i bucket precedenti
break;
case _stock_break:
if (!qta.is_zero())
{
if (is_constraint)
{
curr_article->add_gross_req(t, q.val());
} else {
curr_article->add_sched_rec(t, rq);
curr_article->add_planned_ord(t, q.val() - rq);
}
TMRP_record dbg = curr_article->record(t);
added_on = nbucket;
} else
if (added_on > nbucket || added_on == 0 && nbucket == 0 )
curr_article->set_on_hand(t, get_bool(F_MSCHEDULEPLAN) && nbucket == 0 ?
curr_article->giacenza_attuale(qta,data_buck) : ZERO);
break;
}
}
}
}
}
return TRUE;
}
// already_net: dice se le quantit<69> presenti sono da considerare gia' come net req o
// se devo prenderle come scheduled rec e il net req lo devo calcolare di conseguenza
bool TPlanning_mask::gross2net(TMSP_mode mode, bool lotsizing)
{
// ***********
// gross 2 net
const long max_mrp_rows=_mrp_articles.items();
for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
{
// calcola il fabbisogno netto e lo riporta sul bucket seguente
TMRP_line & mrpline = _mrp_articles[mrp_row];
const int last = mrpline.last_bucket();
real netreq, giacres, resched, need;
for (int bucket = 0; bucket <= last; bucket = mrpline.next_bucket(bucket))
{
switch (mode)
{
case _actual_plan:
netreq = mrpline.planned_orders(bucket);
netreq += mrpline.sched_receipts(bucket);
mrpline.set_net_req(bucket, netreq);
break;
case _stock_break:
giacres = mrpline.on_hand(bucket);
giacres -= mrpline.gross_requirement(bucket);
//if (bucket == 0)
giacres += mrpline.planned_orders(bucket);
giacres += mrpline.sched_receipts(bucket);
if (lotsizing)
netreq = mrpline.sizeup_net_requirement(bucket, giacres, netreq);
else
{
netreq = -giacres;
netreq = mrpline.set_net_req(bucket, netreq);
}
const int nb = mrpline.next_bucket(bucket);
if (nb <= mrpline.last_bucket())
mrpline.set_on_hand(nb, giacres);
break;
}
}
}
return max_mrp_rows>0;
}
const TDate & TPlanning_mask::starting_date() const
{
if (!_start_date.ok())
{
TDate &nakedate = ((TPlanning_mask *)(this))->_start_date;
if (get_date(F_DADATA).ok())
nakedate = get_date(F_DADATA);
else
{
nakedate = TODAY;
round_date(nakedate, TRUE, FALSE);
nakedate+=1;
}
}
return _start_date;
}
int TPlanning_mask::days_per_bucket() const
{
return get_int(F_DAYXBUCK) * (get_int(F_BUCKETS) ? get_int(F_BUCKETS) : get_int(F_BUCKET));
}
bool TPlanning_mask::bucket_mese() const
{
return *get(F_BUCKETS) == 'M';
}
void TPlanning_mask::clear_sheets()
{
_start_date = NULLDATE;
_proposed_articles.destroy();
_mrp_articles.destroy();
TSheet_field &sa=sfield(F_ARTICOLI);
if (sa.items()>0)
{
sa.destroy();
sa.force_update();
}
TSheet_field &sl=sfield(F_LINEE);
if (sl.items()>0)
{
sl.destroy();
sl.force_update();
}
xvt_statbar_set("");
enable(-G_PREPROCESS);
disable(-G_POSTPROCESS);
field(F_DADATA).set_focus();
}
// **********
// imposta il bucket 0 ; se i flag sulla maschera sono settati,
// - sulla riga delle giacenze progressive : somma la giacenza iniziale
// - sulla riga dell'ordinato progressivo => sottrae la giacenza iniziale
// **********
// valore di ritorno:restituisce l'ultima linea dello sheet processata
int TPlanning_mask::init_bucket0(TArticolo_giacenza &art, int r)
{
TSheet_field& sf = sfield(F_ARTICOLI);
const bool add_giac=get_bool(F_MSCHEDULEPLAN);// nettifica la giacenza
// Calcola l'indice c della riga con la giacenza prog
const int b0 = sf.cid2index(F_BUCKET0);
const int b1 = sf.cid2index(F_BUCKET1);
real planned;
for (int c = r; c > 1; c--)
{
if (sf.cell_disabled(c, b1))
break;
planned += real(sf.cell(c, b0));
}
TToken_string &giac_row=sf.row(c);
TToken_string &ord_row=sf.row(c-1);
TToken_string &art_row=sf.row(r);
// calcola codice di magazzino e di livello
TString16 livello;
if (livelli_giacenza().enabled())
{
livelli_giacenza().pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV1)),1);
livelli_giacenza().pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV2)),2);
livelli_giacenza().pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV3)),3);
livelli_giacenza().pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV4)),4);
livello.trim();
}
TString16 codmag;
add_magcode(codmag, giac_row.get(sf.cid2index(F_MAGAZZINO)));
add_depcode(codmag, giac_row.get(sf.cid2index(F_DEPOSITO)));
// calcola i bucket 0
TQuantita prog_giac(art.codice(),giac_row.get(sf.cid2index(F_UM)),planned);
if (add_giac)
{
real giac=art.giacenza_anno(codmag, livello, starting_date().year());
prog_giac +=giac;
}
// ??? prog_giac += giac_row.get(b0);
prog_giac -= ord_row.get(b0);
giac_row.add(prog_giac.val().string(), b0);
if (ord_row.get_char(F_MASTERCODE-FIRST_FIELD) == MASTERCODE_CHAR)
art_row.add(get_int(F_2LEVEL_PRIORITY),F_PRIORITA-FIRST_FIELD);
do_test_art_row(r,c,r,FALSE);
return c-2;
}
bool TPlanning_mask::do_test_art_row(int r, int first, int last, bool signal)
{
TSheet_field& sf = sfield(F_ARTICOLI);
TMask & smask= sf.sheet_mask();
TToken_string & curr_row=sf.row(r);
TToken_string & constr_row=sf.row(first-1);
TToken_string & giac_row=sf.row(first);
// **********
// setta la priorita' su tutte le righe del blocco
const int prior =curr_row.get_int(sf.cid2index(F_PRIORITA));
const int old_prior=constr_row.get_int(sf.cid2index(F_PRIORITA));
if (old_prior != prior)
{
for (int i = first-1; i<=last; i++)
{
sf.row( i ).add(prior , sf.cid2index(F_PRIORITA));
sf.force_update(i);
}
}
// **********
// calcola la giacenza proiettata
TCodice_articolo codart(curr_row.get(sf.cid2index(F_ARTICOLO)));
if (codart.blank()) // Controllo di DEBUG
{
if (signal)
{
error_box(FR("Articolo nullo nella riga %d"), r+1);
signal = FALSE;
}
return signal;
}
TArticolo_giacenza art(codart);
TString16 liv;
TString8 mag,imp,lin;
long codcli=constr_row.get_long(F_CLIENTE-FIRST_FIELD);
imp=constr_row.get(sf.cid2index(F_CODIMP));
lin=constr_row.get(sf.cid2index(F_CODLIN));
if (livelli_giacenza().enabled())
{
livelli_giacenza().pack_grpcode(liv, constr_row.get(sf.cid2index(F_LIV1)),1);
livelli_giacenza().pack_grpcode(liv, constr_row.get(sf.cid2index(F_LIV2)),2);
livelli_giacenza().pack_grpcode(liv, constr_row.get(sf.cid2index(F_LIV3)),3);
livelli_giacenza().pack_grpcode(liv, constr_row.get(sf.cid2index(F_LIV4)),4);
liv.trim();
}
add_magcode(mag, constr_row.get(sf.cid2index(F_MAGAZZINO)));
add_depcode(mag, constr_row.get(sf.cid2index(F_DEPOSITO)));
real soglia;
switch (*get(F_SOGLIAATT))
{
case 'S':
soglia = art.scorta_minima(mag, liv, 0, FALSE); break;
case 'R':
soglia = art.scorta_minima(mag, liv, 0, TRUE); break;
default:
soglia = ZERO;
}
const int b0 = sf.cid2index(F_BUCKET0);
TQuantita vincolo(codart,giac_row.get(sf.cid2index(F_UM)),ZERO);
TQuantita totale(vincolo),qta(vincolo);
totale += real(sf.cell(first, b0));// giacenza iniziale
for (int b = 1; b < LAST_BUCKET; b++)
{
vincolo.set_val(real(sf.cell(first-1, b0+b*2)));
for (int i = first+1; i <= last; i++)
{
totale += real(sf.cell(i, b0+b*2)); // somma alla giacenza le produzioni
}
totale -= real(sf.cell(first-1, b0+b*2)); // detrae le uscite
giac_row.add(totale.val().string(), b0+b*2);
if (signal && totale.val() < soglia)
{
TString err;
TDate d = starting_date() + long(days_per_bucket() * (b-1));
round_date(d);
err << TR("Riga ") << first+1 << ": Vincolo non ripettato al " << d;
beep();
signal =FALSE;
xvt_statbar_set(err);
}
}
sf.force_update(first);
if (signal) xvt_statbar_set("");
// **********
// aggancia i master di 2' livello
if (constr_row.get_char(sf.cid2index(F_MASTERCODE))==MASTERCODE_CHAR)
{
TMSP_constraint*currconstr=_constraints.find(codcli, codart, liv, imp, lin, mag);
CHECK (currconstr, "Impossibile trovare il vincolo dell'articolo di 1' livello");
TMSP_line2 *art2ndlev;
currconstr->reset_unused_line2();
r = last;
while (r>first)
{
TToken_string & curr_row=sf.row(r);
// aggancia i master di 2' livello
if (art2ndlev=currconstr->use_mspline2(curr_row))
do_test_art_2ndlevel(art2ndlev);
else
if (signal)
message_box(FR("Impossibile determinare l'articolo Master per %s"),(const char*)currconstr->articolo());
r--;
}
while (art2ndlev=currconstr->get_unused_line2())
{
do_test_art_2ndlevel(art2ndlev,TRUE);
currconstr->discard_line2(art2ndlev);
}
}
return signal;
}
//
// controlla la dipendenza tra articoli MAster e dipendenti
void TPlanning_mask::do_test_art_2ndlevel(TMSP_line2 *art2ndlev, bool erase)
{
TSheet_field& sf = sfield(F_ARTICOLI);
TMask & smask= sf.sheet_mask();
int i=0;
TMaster_code *mc;
while ((mc=art2ndlev->get_mastercode(i++))!=NULL)
{
TMSP_constraint* master_constr=_constraints.find(art2ndlev->constraint().codclifor(),mc->articolo()
, mc->livello(), mc->codimp(), mc->codlin(), mc->codmagdep());
if (master_constr==NULL)
{
master_constr=_constraints.find(art2ndlev->constraint().codclifor(),mc->articolo(), mc->livello(), mc->codimp(), mc->codlin(), mc->codmagdep(), TRUE);
}
int mrow= find_constr_row(*master_constr);
TMSP_constraint* upperline=master_constr->get_upperline(art2ndlev->constraint());
real difference;
bool changed=FALSE;
for (int b = 0; b <= LAST_BUCKET; b++)
{
const int b2=b-int(((real)(mc->leadtime()/days_per_bucket()+0.5)).integer());
if (b2>=0)
{
if (!erase)
difference= art2ndlev->constraint().qta(b2)*mc->expr();
if (upperline)
difference -= upperline->qta(b2);
else
upperline = master_constr->add_upperline(art2ndlev->constraint());
if (difference != ZERO)
{
upperline->qta(b2) = upperline->qta(b2) + difference;
master_constr->qta(b2) = master_constr->qta(b2) + difference;
// ricostruisce il vincolo della linea master sullo sheet
TToken_string &master_row=sf.row(mrow);
master_row.add(master_constr->qta(b2).string(),sf.cid2index(F_BUCKET0+b2*2));
changed=TRUE;
}
}
}
if (changed)
{
sf.force_update(mrow);
int first,last;
TRiga_articolo::find_block(sf, mrow+2, first, last);
do_test_art_row(mrow+2, first, last, FALSE);
}
}
}
// compatta le linee togliendo i doppioni
bool TPlanning_mask::pack_article_sheet(int r, int first, int last)
{
TSheet_field& sf = sfield(F_ARTICOLI);
TToken_string &art_row = sf.row(r);
bool packed = FALSE;
for (int curr=last; curr >=first; curr--) if (curr != r)
{
TToken_string &curr_row=sf.row(curr);
if (art_row.get_long(F_CLIENTE-FIRST_FIELD) == curr_row.get_long(F_CLIENTE-FIRST_FIELD))
if (TRiga_articolo ::order_compare(art_row, curr_row,15)==0)
{
packed = TRUE;
TToken_string work_row = curr_row;
for (int bucket=0; packed && bucket<=LAST_BUCKET ; bucket++)
{
real qta1(art_row.get(F_BUCKET1 + bucket*2 - FIRST_FIELD));
real qta2(work_row.get(F_BUCKET1 + bucket*2 - FIRST_FIELD));
real prz1(art_row.get(F_BUCKET1 +1 + bucket*2 - FIRST_FIELD));
real prz2(work_row.get(F_BUCKET1 +1 + bucket*2 - FIRST_FIELD));
if (!prz1.is_zero() && !qta2.is_zero() && prz1 != prz2)
packed = FALSE;
if (qta2.is_zero())
work_row.add(prz1.string(), F_BUCKET1 + 1 + bucket*2 - FIRST_FIELD);
qta2 += qta1;
work_row.add(qta2.string(), F_BUCKET1 + bucket*2 - FIRST_FIELD);
}
if (packed)
{
curr_row = work_row;
sf.destroy(r);
}
}
}
if (packed)
{
sf.select(first);
sf.force_update();
}
return packed;
}
// controllo linee in modo interattivo
bool TPlanning_mask::test_art_row(int r, bool signal)
{
bool ok = TRUE;
TSheet_field& sf = sfield(F_ARTICOLI);
int first,last;
if (TRiga_articolo::find_block(sf, r, first, last))
{
if (signal && pack_article_sheet(r, first+1, last))
TRiga_articolo::find_block(sf, first+1, first, last);
TToken_string & curr_row=sf.row(r);
const bool err = do_test_art_row(r, first, last, signal);
if (signal)
{
// interactive mode:
TMSP_line* line = _articles.find(curr_row, FALSE);
if (line)
{
real value,goodvalue;
for (int b = 0 ; b < LAST_BUCKET; b++)
{
value = (curr_row.get(sf.cid2index(F_BUCKET0 + b*2)));
goodvalue = line->qta_locked(b);
if (!goodvalue.is_zero())
{
if (value != goodvalue)
{
error_box(FR("Impossibile modificare la quantita' per l'articolo %s, colonna %d"),(const char *)line->articolo(),b);
do_events();
ok = FALSE;
}
} else {
goodvalue = line->qta_min(b);
if (value < goodvalue)
{
if (!get_bool(F_RESCHEDULING) || get_int(F_RESCHED_ALERT))
{
TString msg (format(FR("%s %s confermati per l'articolo %s, colonna %d"),(const char *)line->qta_min(b).string(),(const char *)line->um(),(const char *)line->articolo(),b));
if (get_bool(F_RESCHEDULING))
{
if (err)
xvt_statbar_set(msg);
} else {
error_box(msg);
ok = FALSE;
}
do_events();
}
}
}
if (!ok)
{
curr_row.add(goodvalue.string(), sf.cid2index(F_BUCKET0 + b*2));
sf.force_update(r);
}
}
}
}
}
return ok;
}
bool TPlanning_mask::test_load_row(int r, bool signal)
{
TSheet_field& sf = sfield(F_LINEE);
const int narticoli=sf.items();
if (narticoli<=r)
return TRUE;
// Calcola l'indice c della riga con la capacita'
const int b0 = sf.cid2index(F_LBUCKET0);
const int b1 = sf.cid2index(F_LBUCKET1);
for (int c = r; c > 0; c--)
{
if (sf.cell_disabled(c, b1))
break;
}
// Calcola l'indice r della riga totale di linea
if (r == c) r++;
TToken_string &row=sf.row(c);
real capacita, carico;
for (int b = 1; b < LAST_BUCKET; b++)
{
capacita=real(sf.cell(c, b0+b*2));
carico=real(sf.cell(r, b0+b*2));
if (signal && capacita < carico)
{
TString err;
TDate d = starting_date() + long(days_per_bucket() * (b-1));
round_date(d);
err << TR("Riga ") << c+1 << TR(": capacit<69> superata al ") << d;
beep();
signal =FALSE;
xvt_statbar_set(err);
}
}
if (signal) xvt_statbar_set("");
return signal;
}
// copia i dati della riga al di fuori delle informazioni dei bucket
void TPlanning_mask::copy_sheet_row(TToken_string & newrow, const TToken_string & row)
{
const TSheet_field& sf = sfield(F_ARTICOLI);
const int b0 = sf.cid2index(F_BUCKET0);
TString str;
for (int i = 0; i < b0; i++)
{
row.get(i, str);
newrow.add(str, i);
}
}
int TPlanning_mask::salva_cella(int r, int b, TPlan_docs &doc_rows, TToken_string& save_opt )
{
static long last_clifor = -1;
static long act_clifor = -1;
static TString *default_codmagdep=NULL;
TSheet_field& sf = sfield(F_ARTICOLI);
const int b0 = sf.cid2index(F_BUCKET0);
const int um = sf.cid2index(F_UM);
const TDate date_to = get(F_ADATA);
const TDate from(starting_date());
const int bucket_size = days_per_bucket();
const bool number_by_cli = get_bool(F_NUMBERBYCLI);
const bool number_by_week = get_bool(F_NUMBERBYWEEK);
TDate datacons = from + long(bucket_size * (b-1));
//if (datacons > date_to)
// return FALSE;
round_date(datacons, !bucket_mese());
TToken_string & row = sf.row(r);
TMSP_line &line = *_articles.find(row, TRUE);
TMSP_constraint *constraint = find_constraint(line);
TMRP_line *mrpline = _mrp_articles.find(constraint->articolo(),constraint->livgiac(),
constraint->codmagdep(),constraint->codmagdep_coll(), constraint->codimp(), constraint->codlin(), constraint->codclifor());
if ((*save_opt.get(F_DA_MAGAZZ-FIRST_FIELD)<=' ' || line.codmagdep() >= save_opt.get(F_DA_MAGAZZ-FIRST_FIELD)) &&
(*save_opt.get(F_A_MAGAZZ-FIRST_FIELD)<=' ' || line.codmagdep() <= save_opt.get(F_A_MAGAZZ-FIRST_FIELD)) &&
(*save_opt.get(F_DA_IMPIANTO-FIRST_FIELD)<=' ' || line.codimp() >= save_opt.get(F_DA_IMPIANTO-FIRST_FIELD)) &&
(*save_opt.get(F_A_IMPIANTO-FIRST_FIELD)<=' ' || line.codimp() <= save_opt.get(F_A_IMPIANTO-FIRST_FIELD)))
{
const TString8 new_tipodoc(save_opt.get(F_TIPO_PLAN-FIRST_FIELD));
const TString8 new_codnum(save_opt.get(F_NUM_PLAN-FIRST_FIELD));
TDate datadoc = datacons;
switch (*get(F_LEADTIME))
{
case 'I': // leadtime gia' calcolato sugli input
datacons += cache().get(LF_ANAMAG,line.articolo()).get_real(ANAMAG_GIORNIRIOR).integer();
break;
case 'O': // leadtime da calcolare sugli output
datadoc -= cache().get(LF_ANAMAG,line.articolo()).get_real(ANAMAG_GIORNIRIOR).integer();
break;
}
round_date(datadoc);
int new_anno = datadoc.year();
int new_week = datadoc.week();
if (number_by_week)
get_week_year(datadoc, new_week, new_anno);
const long new_numdoc = (number_by_cli ? line.codclifor() * 100L : 0L)+
(number_by_week ? new_week : 0L);
const int new_numrig = 0;
TString8 codnum;
int anno;
long numdoc;
int numrig;
real old, val,new_val(row.get(b0 + b*2));
if (mrpline && mrpline->last_bucket() >= b-1)
{
// *************
// rescheduling checks
const real & pl = mrpline->planned_orders(b-1);
const real & sr = mrpline->sched_receipts(b-1);
const real & uo = mrpline->unsched_orders(b-1);
const real & ro = mrpline->resched_orders(b-1);
if (new_val.sign() > 0) // devo pianificare qualcosa...
{
real movable = ro - uo;
if (movable.sign()) // ... ma posso spostare la qta da altrove
{
real moved = fnc_min(new_val, movable);
new_val -= moved;
mrpline->record(b-1).add_unsched_ord(moved);
}
// new_val -= sr;
}
}
TMRP_docref *rdr=line.first_rigaref(b);
bool found=FALSE;
while (rdr || found==FALSE && new_val.sign() > 0)
{
if (rdr==NULL && !found)
{
found=TRUE;
rdr=new TMRP_docref(new_anno,new_codnum,new_numdoc,new_numrig,row.get(sf.cid2index(F_UM)),ZERO,ZERO);
line.add_rigaref(b, rdr);
}
old = rdr->qta_residua();
codnum = rdr->codnumdoc();
anno = rdr->annodoc();
numdoc = rdr->numdoc();
numrig = rdr->numrig();
//if (rdr->codnum()==new_codnum && rdr->annodoc() == new_anno && rdr->numdoc() == new_numdoc)
if (rdr->codnumdoc() == new_codnum)
{
TToken_string keydoc("D");
keydoc.add(anno);
keydoc.add(codnum);
keydoc.add(numdoc);
const TRectype & docrec = cache().get(LF_DOC,keydoc);
if (docrec.empty() ||
new_tipodoc == docrec.get(DOC_TIPODOC) && !has_confirmed_status(docrec))
{
val = new_val;
new_val = ZERO;
if (val != old) // c'e' una modifica da salvare
{
// determina il codice cliente/fornitore
act_clifor = row.get_long(sf.cid2index(F_CLIENTE));
if (last_clifor >= 0 && last_clifor != act_clifor)
doc_rows.flush(datacons, NULL);
last_clifor = act_clifor;
// inserisce la riga di documento
const real incr = val-old;
TRiga_documento& riga = doc_rows.add_to_row(rdr, incr);
if (riga.get(RDOC_CODART).empty())
{
riga.put(RDOC_CODART, line.articolo());
riga.put(RDOC_CODARTMAG, line.articolo());
riga.put(RDOC_LIVELLO, line.livgiac());
riga.put(RDOC_CHECKED, "X");
if (!line.codmagdep().blank())
riga.put(RDOC_CODMAG, line.codmagdep());
else
{
if (default_codmagdep==NULL)
{
default_codmagdep = new TString8();
add_magcode(*default_codmagdep,_magazzini.standardmag());
add_depcode(*default_codmagdep,_magazzini.standarddep());
}
riga.put(RDOC_CODMAG, *default_codmagdep);
}
riga.put(RDOC_CODMAGC, line.codmagdep_coll());
riga.put(RDOC_LINEA, line.codlin());
riga.put(RDOC_IMPIANTO, line.codimp());
riga.put(RDOC_UMQTA, row.get(sf.cid2index(F_UM)));
riga.put(RDOC_DATACONS, datacons);
riga.put(RDOC_DESCR, row.get(sf.cid2index(F_DESCART)));
TRectype& doc = (TRectype&)riga.doc().head();
if (doc.get(DOC_DATACONS).empty())
{
doc.put(DOC_DATACONS, datacons);
doc.put(DOC_TIPOCF, get(F_TIPOCF));
doc.put(DOC_CODCF, line.codclifor());
}
doc.put(DOC_DATADOC, from);
// Calcola codice iva per la riga in base al fornitore o all'articolo
TString16 cod;
cod.format("%c|%ld", get(F_TIPOCF)[0], line.codclifor());
cod = cache().get(LF_CFVEN, cod, CFV_ASSFIS);
if (cod.empty())
cod = cache().get(LF_ANAMAG, line.articolo(), ANAMAG_CODIVA);
riga.put(RDOC_CODIVA, cod);
}
if (val == ZERO)
{
line.remove_rigaref(b);
enable_codes(r);
}
else
{
line.qta(b) -= old;
line.qta(b) += rdr->qta_residua();
disable_codes(r);
}
sf.force_update(r);
}
}
else
{
//if (new_anno==anno && new_codnum==codnum && new_numdoc==numdoc)
new_val -= old;
}
}
else
found = TRUE;
rdr=line.next_rigaref(b);
} // ciclo di aggiornamento dei riferimenti ai docs
return 1;
} // filtro sulle righe
return 0;
}
int TPlanning_mask::salva_documenti(TExceptions_array &excepts, TSheet_field & save_opt)
{
TAssoc_array error_on_row;
int some=0,somefilter=0;
for (int saveit=save_opt.items()-1; saveit>=0; saveit--)
{
if (*save_opt.row(saveit).get(save_opt.cid2index(F_SEL4SAVE))>' ')
{
somefilter++;
TString save_numplan (save_opt.row(saveit).get(F_NUM_PLAN-FIRST_FIELD));
TString save_tipoplan (save_opt.row(saveit).get(F_TIPO_PLAN-FIRST_FIELD));
TString save_rigaplan (save_opt.row(saveit).get(F_RIGA_PLAN-FIRST_FIELD));
TPlan_docs doc_rows(save_numplan, save_tipoplan, save_rigaplan);
const TSheet_field& sf = sfield(F_ARTICOLI);
const int b1 = sf.cid2index(F_BUCKET1);
const TDate from(starting_date());
const bool ordiniXarticolo = get_bool(F_DIVIDEBYART);
const bool ordiniXscadenza = get_bool(F_DIVIDEBYDATE);
if (ordiniXscadenza && ordiniXarticolo)
if (!noyes_box(TR("E' stato scelto di generare un ordine diverso per ogni articolo e scadenza: confermare?")))
return 0;
if (!(ordiniXscadenza || ordiniXarticolo))
if (!noyes_box(TR("E' stato scelto di generare un unico ordine per ogni articolo e scadenza: confermare?")))
return 0;
TProgind pi(LAST_BUCKET*sf.items(), TR("Emissione documenti") , FALSE, TRUE);
if (ordiniXscadenza)
{
// *************************
// Generazione per scadenza:
long act_clifor =-1 ;
long last_clifor =-1 ;
for (int b = 1; b < LAST_BUCKET; b++)
{
long recs=0L;
TDate datacons = from + long(days_per_bucket() * (b-1));
round_date(datacons);
FOR_EACH_SHEET_ROW(sf, r, row)
{
pi.addstatus(1);
if (!sf.cell_disabled(r, b1))
if (row->get_long(F_CLIENTE-FIRST_FIELD) || cache().get("%TIP",save_opt.row(saveit).get(F_TIPO_PLAN-FIRST_FIELD)).get_bool("B5"))
salva_cella(r, b, doc_rows, save_opt.row(saveit));
else
{
TString8 key;
key.format("%d",r);
if (row->get_long(F_BUCKET0+b-FIRST_FIELD)!=0L && !error_on_row.is_key(key))
{
error_box(FR("Riga %d: manca l'indicazione del codice %s"),r+1,get(F_TIPOCF)[0] == 'F' ? "fornitore" : "cliente");
error_on_row.add(key,NULL);
}
}
if (ordiniXarticolo)
recs = doc_rows.flush(datacons, row->get(sf.cid2index(F_ARTICOLO)));
}
pi.addstatus(1);
if (!ordiniXarticolo)
recs += doc_rows.flush(datacons, NULL);
if (recs > 0L)
some += 1;
else if (recs < 0L)
some = -1;
}
}
else
{
// *************************
// Generazione per articolo:
FOR_EACH_SHEET_ROW(sf, r, row)
if (!sf.cell_disabled(r, b1))
{
for (int b = 1; b < LAST_BUCKET; b++)
{
pi.addstatus(1);
if (row->get_long(F_CLIENTE-FIRST_FIELD) || cache().get("%TIP",save_opt.row(saveit).get(F_TIPO_PLAN-FIRST_FIELD)).get_bool("B5"))
salva_cella(r, b, doc_rows, save_opt.row(saveit));
else
{
TString8 key;
key.format("%d",r);
if (row->get_long(F_BUCKET0+b-FIRST_FIELD)!=0L && !error_on_row.is_key(key))
{
error_box(FR("Riga %d: manca l'indicazione del codice %s"),r+1,get(F_TIPOCF)[0] == 'F' ? "fornitore" : "cliente");
error_on_row.add(key,NULL);
}
}
}
long recs = 0L;
if (ordiniXarticolo)
recs = doc_rows.flush(NULLDATE,row->get(sf.cid2index(F_ARTICOLO)));
if (recs > 0L)
some += 1;
else if (recs < 0L)
some = -1;
}
if (!ordiniXarticolo)
some = int(doc_rows.flush(NULLDATE,""));
}
switch (some)
{
case 0:
message_box(FR("Nessun documento generato o modificato \n(numerazione %s, tipo %s)"),
(const char *)save_numplan,(const char *)save_tipoplan);
break;
case -1:
if (!yesno_box(FR("Problemi nella registrazione dei documenti.\n(numerazione %s, tipo %s)\nRipeto l'elaborazione ?"),
(const char *)save_numplan,(const char *)save_tipoplan))
some = 0;
break;
}
}
}
if (somefilter == 0)
message_box(TR("Nessuna opzione di registrazione selezionata"));
return some;
}
bool TPlanning_mask::on_savefields_event(long jolly)
{
TSheet_field & sf = sfield(F_SAVE_OPT);
int nriga = jolly>=0 ? (int)jolly : sf.items()-1;
TString tmp;
do
{
{
tmp = sf.row(nriga).get(sf.cid2index(F_NUM_PLAN));
if (tmp.empty())
return TRUE;
const TSheet_field& num_s = sfield(F_NUM_PLA);
FOR_EACH_SHEET_ROW_BACK(num_s, r, row)
if (tmp == row->get(num_s.cid2index(F_NUMERAZ)))
break;
if (r < 0)
return sf.error_box(FR("Numerazione '%s' non inclusa tra quelle di planning"), (const char *)tmp);
}
{
tmp = sf.row(nriga).get(sf.cid2index(F_TIPO_PLAN));
const TSheet_field& tipo_s = sfield(F_TIPI_PLA);
FOR_EACH_SHEET_ROW_BACK(tipo_s, r, row)
if (tmp == row->get(tipo_s.cid2index(F_TIPO)))
break;
if (r < 0)
return sf.error_box(FR("Tipo documento '%s' non incluso tra quelli di planning"), (const char *)tmp);
}
} while (--nriga >= 0 && jolly < 0);
return TRUE;
}
bool TPlanning_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
const char * confirm_msg=FR("Le modifiche non registrate sulle attuali %d linee di articoli verranno perse: confermare?");
switch (o.dlg())
{
case F_DADATA:
if (e == fe_modify)
{
_start_date = NULLDATE;
round_field(o, FALSE);
}
break;
case F_ADATA:
if (e == fe_modify)
round_field(o, TRUE, FALSE);
break;
case F_BUCKET:
if (e == fe_modify)
{
on_field_event((TOperable_field& )field(F_DADATA), fe_modify, jolly);
on_field_event((TOperable_field& )field(F_ADATA), fe_modify, jolly);
}
break;
case F_YEAR:
case F_IMPIANTO:
case F_LINEA:
if (e == fe_modify || (o.dlg() == F_YEAR && e == fe_init ))
update_calendar(F_CALENDAR, F_YEAR, F_IMPIANTO, F_LINEA);
break;
case F_TIPI_ORC:
case F_TIPI_PLA:
if (e == fe_init)
{
TSheet_field& s = (TSheet_field&)o;
if (s.items() == 0)
{
s.row(0);
s.force_update();
}
}
if (e == fe_close)
{
const TSheet_field& s = (const TSheet_field&)o;
FOR_EACH_SHEET_ROW_BACK(s, r, row)
if (!row->empty_items())
{
bool ok;
if (o.dlg()==F_TIPI_PLA)
ok=test_tipodoc_num(sfield(F_NUM_PLA), s );
else
ok=test_tipodoc_num(sfield(F_NUM_ORC), s );
return ok;
}
return error_box(TR("E' necessario inserire almeno una riga"));
}
break;
case F_SAVE_OPT:
if (e == se_leave)
on_savefields_event(jolly);
break;
case F_ARTICOLI:
{
static TToken_string _curr_art_row;
TSheet_field& s = (TSheet_field&)o;
const int righe = s.items();
const int nriga = int(jolly);
switch(e)
{
case se_query_add:
return jolly > 1 && righe > 0;
case se_notify_add:
if (jolly > 0)
{
const TToken_string& prev = s.row(nriga-1);
TToken_string& curr = s.row(nriga);
copy_sheet_row(curr,prev);
int rconstr = TRiga_articolo::find_block_constr(s, nriga);
TToken_string& constr = s.row(rconstr);
if (constr.get_long(s.cid2index(F_CLIENTE)))
s.disable_cell(nriga,s.cid2index(F_CLIENTE));
}
break;
case se_leave:
if (nriga >= 0 && nriga < righe)
{
const TToken_string &art_row= s.row(nriga);
if (_curr_art_row != s.row(nriga))
{
const bool ok=test_art_row(nriga);
if (!ok)
_curr_art_row.cut(0);
else
_curr_art_row= s.row(nriga);
return ok;
}
}
break;
case se_enter:
//if (nriga < righe)
// _curr_art_row= s.row(nriga);
break;
default:
break;
}
}
break;
case F_MSP_RESORT:
if (e==fe_button)
sortMSPsheet();
break;
case F_LINEE:
{
switch(e)
{
case se_query_add:
return FALSE;
case se_leave:
test_load_row((int)jolly);
break;
}
}
break;
case F_CRP_RESORT:
if (e==fe_button)
sortCRPsheet();
break;
case H_CODIMP:
if (e == fe_modify)
{
const TSheet_field& s = sfield(F_ARTICOLI);
TMask & m=s.sheet_mask();
if (!m.get(F_CODLIN).blank())
m.set(F_CODIMP,o.get());
}
break;
case F_CODIMP:
if (jolly == 6 && e == fe_modify)
{
const TString & val = o.get();
if (!val.empty())
{
const TSheet_field& s = sfield(F_ARTICOLI);
TMask & m = s.sheet_mask();
TImpianto &unita_prod=*::get_impianto(val);
if (m.get(F_MAGAZZINO).blank())
{
TString8 codmagdep(unita_prod.codmagdep());
if (!codmagdep.blank())
{
m.set(F_MAGAZZINO,::get_magcode(codmagdep));
m.set(F_DEPOSITO,::get_depcode(codmagdep));
}
}
if (*unita_prod.codmagdep_coll()>' '&& m.get(F_MAG_COLL).blank())
{
TString8 codmagdep_coll(unita_prod.codmagdep_coll());
if (!codmagdep_coll.blank())
{
m.set(F_MAG_COLL,::get_magcode(codmagdep_coll));
m.set(F_DEP_COLL,::get_depcode(codmagdep_coll));
}
}
}
}
break;
case F_CODLIN:
if (jolly == 6 && e == fe_modify)
{
const TString & val = o.get();
if (!val.empty())
{
const TSheet_field& s = sfield(F_ARTICOLI);
TMask & m = s.sheet_mask();
TLinea_prod &unita_prod=*::get_linea(val);
if (m.get(F_MAGAZZINO).blank())
{
TString8 codmagdep(unita_prod.codmagdep());
if (!codmagdep.blank())
{
m.set(F_MAGAZZINO,::get_magcode(codmagdep));
m.set(F_DEPOSITO,::get_depcode(codmagdep));
}
}
if (*unita_prod.codmagdep_coll()>' '&& m.get(F_MAG_COLL).blank())
{
TString8 codmagdep_coll(unita_prod.codmagdep_coll());
if (!codmagdep_coll.blank())
{
m.set(F_MAG_COLL,::get_magcode(codmagdep_coll));
m.set(F_DEP_COLL,::get_depcode(codmagdep_coll));
}
}
}
}
break;
case F_MAGAZZINO:
if (jolly == 6 && e == fe_modify)
{
const TSheet_field& s = sfield(F_ARTICOLI);
TMask & m = s.sheet_mask();
if (m.get(F_MAGAZZINO).blank())
{
TString8 codmagdep(_magazzini.standardmag());
m.set(F_MAGAZZINO,::get_magcode(codmagdep));
m.set(F_DEPOSITO,::get_depcode(codmagdep));
}
if (m.get(F_MAGAZZINO).blank())
m.set(F_DEPOSITO,"");
}
break;
case F_DEPOSITO:
if (jolly == 6 && e == fe_modify)
{
const TSheet_field& s = sfield(F_ARTICOLI);
TMask & m = s.sheet_mask();
if (m.get(F_DEPOSITO).blank())
{
// controla se il magazzino richiede dep
if (_magazzini.get(m.get(F_MAGAZZINO)).get_bool("B0"))
return FALSE;
}
}
break;
case F_BUCKET1:
case F_BUCKET2:
case F_BUCKET3:
case F_BUCKET4:
case F_BUCKET5:
case F_BUCKET6:
case F_BUCKET7:
case F_BUCKET8:
case F_BUCKET9:
case F_BUCKET10:
case F_BUCKET11:
case F_BUCKET12:
case F_BUCKET13:
case F_BUCKET14:
if (e == fe_modify)
{
const TSheet_field& s = sfield(F_ARTICOLI);
TMask & m=s.sheet_mask();
TMask_field &fprice=m.field(o.dlg()+1);
real qta(o.get());
real price(fprice.get());
if (!qta.is_zero() && price.is_zero())
find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
m.get(F_TIPOCF_SHEET), m.get_long(F_CLIENTE), m.get(F_ARTICOLO),
qta , price);
fprice.set(price.string());
highlight(s.selected(), o.dlg(), qta != ZERO);
}
break;
case DLG_CANCEL:
if (e == fe_button)
if (jolly == 0L)
{
TSheet_field& s = sfield(F_ARTICOLI);
int lineeart=s.items();
if (lineeart==0 || !s.dirty() || yesno_box(confirm_msg,lineeart))
{
clear_sheets();
} else
return FALSE;
}
break;
case DLG_ELABORA:
if (e == fe_button )
{
if (is_page_crp())
{
if (capacity_review(get_bool(F_USENONSTDLIN_CRP) ,get_bool(F_USEEXTRAHRS_CRP) ))
{
on_field_event((TOperable_field&)field(F_LOADTYPE), fe_modify, jolly );
sfield(F_LINEE).set_focus();
}
} else if (check_fields())
{
TSheet_field& s = sfield(F_ARTICOLI);
int lineeart=s.items();
if (lineeart==0 || !s.dirty() || yesno_box(confirm_msg,lineeart))
{
if (get_int(F_YEAR)==0)
{
set(F_YEAR,get_date(F_DADATA).ok() ? get_date(F_DADATA).year() :TDate(TODAY).year());
on_field_event((TOperable_field&)field(F_YEAR), fe_modify, jolly );
}
elabora();
}
}
}
break;
case F_CANCEL_MSP:
if (e == fe_button)
{
remove_propose(TRUE);
}
break;
case F_RECALC_MSP:
if (e == fe_button && check_fields())
{
remove_propose();
propose();
on_field_event((TOperable_field&)field(F_LOADTYPE), fe_modify, 0L);
sfield(F_ARTICOLI).set_focus();
}
break;
case F_CHECK:
if (e == fe_button)
{
if (is_page_crp())
check_capacities();
else
check_articles();
}
break;
case F_PRINT:
if (e == fe_button)
{
TPrint_mask pm(*this);
while (pm.run() != K_ESC) ;
}
break;
case F_RECALCLINE:
if (e == fe_button)
{
TSheet_field& s = sfield(F_ARTICOLI);
int curr_row=s.selected();
s.update_row(curr_row);
propose(curr_row);
s.update_mask(curr_row);
}
break;
case F_CHECKLINE:
if (e == fe_button)
{
TSheet_field& s = sfield(F_ARTICOLI);
TMSPCheck_mask cm(this);
cm.disable(-G_MOVIMENTO);
int curr_row=s.selected();
s.update_row(curr_row);
const bool is_disabled=s.cell_disabled(curr_row,F_BUCKET1-FIRST_FIELD) ;
const bool is_constr=(is_disabled && curr_row>0 && s.cell_disabled(curr_row-1,F_BUCKET1-FIRST_FIELD));
if (is_disabled && !is_constr)
curr_row++;
cm.gopos(curr_row, 1);
cm.run();
//cm.gopos_mainmask();
}
break;
case F_DOCUMENTI_OUT:
if (e == fe_button)
{
TSheet_field& s = sfield(F_ARTICOLI);
int curr_row=s.selected();
TMSP_line *l = _articles.find(s.row(curr_row));
if (l)
{
TLista_docref m(l,TR("Documenti pianificati"), starting_date(), days_per_bucket());
if (m.reset_bucket_field())
{
if (m.run() != K_ESC)
m.edit_checked();
}
return TRUE;
}
message_box(TR("Nessun ordine pianificato per la riga corrente"));
}
break;
case F_DOCUMENTI_IN:
case F_VINCOLI_IN:
case F_VINCOLI_OUT:
if (e == fe_button)
{
TSheet_field& s = sfield(F_ARTICOLI);
int curr_row=s.selected();
while (curr_row && !s.cell_disabled(curr_row,F_BUCKET1-FIRST_FIELD))
curr_row--;
TMSP_constraint *c = _constraints.find(s.row(curr_row));
if (c)
{
switch (o.dlg())
{
case F_DOCUMENTI_IN:
{
TLista_docref m(c,TR("Documenti vincolo"),starting_date(), days_per_bucket());
if (m.reset_bucket_field())
{
if (m.run()!= K_ESC)
m.edit_checked();
return TRUE;
}
}
break;
case F_VINCOLI_IN:
{
TLista_upperlines m(c,starting_date(), days_per_bucket());
if (m.reset_bucket_field())
m.run();
else
message_box(TR("Nessun vincolo interno sulla riga corrente"));
return TRUE;
}
break;
case F_VINCOLI_OUT:
{
TLista_mastercodes m(c, s.row(s.selected()), starting_date(), days_per_bucket());
if (m.reset_bucket_field())
m.run();
else
message_box(TR("Nessun articolo Master dipendente dalla riga corrente"));
return TRUE;
}
break;
}
}
message_box(TR("Nessun vincolo per la riga corrente"));
}
break;
case F_SHOW_WEEK:
case F_SHOWPRICES:
if (e == fe_modify)
set_sheet_header();
break;
case F_SHOWDETAILS:
case F_SHOWPERC:
if (e == fe_modify)
on_field_event((TOperable_field&)field(F_LOADTYPE), fe_modify, jolly );
break;
case F_LOADTYPE:
if (e == fe_modify)
{
// *************
// fill sheet of capacities
const bool as_percentage=get_bool(F_SHOWPERC);
const char load_type=*get(F_LOADTYPE);
TSheet_field& sl = sfield(F_LINEE);
sl.destroy();
const long max_capacities=_capacities.items();
for (long c=0; c<max_capacities ; c++)
{
TCRP_line &crpline = _capacities[c];
if (load_type != 'M' || !crpline.codlin().blank())
{
const bool is_not_article=crpline.codart().blank();
if (is_not_article)
{
crpline.fill_capacity_row(sl.row(-1), load_type , as_percentage);
sl.disable_cell(sl.items()-1, -1);
}
if (is_not_article || get_bool(F_SHOWDETAILS))
crpline.fill_load_row(sl.row(-1), load_type, as_percentage);
}
}
sl.force_update();
}
break;
case DLG_SAVEREC:
if (e == fe_button)
{
if (on_savefields_event(-1))
{
TSave_mask save_mask(*this);
while (save_mask.run() != K_ESC);
}
}
break;
case DLG_PROFILE:
break;
case DLG_QUIT:
if (e == fe_button)
if (jolly == 0L)
{
TSheet_field& s = sfield(F_ARTICOLI);
int lineeart=s.items();
if (lineeart>0 && s.dirty() && !yesno_box(confirm_msg,lineeart))
return FALSE;
}
break;
default:
break;
}
return TRUE;
}
TPlanning_mask::TPlanning_mask(const char * name)
: TCalendar_mask(name), _sel_color(sfield(F_ARTICOLI))
{
init();
}
TPlanning_mask::TPlanning_mask()
: TCalendar_mask("mr2200a"), _sel_color(sfield(F_ARTICOLI))
{
init();
}
void TPlanning_mask::init()
{
TSheet_field& sf = sfield(F_ARTICOLI);
sf.set_append(FALSE);
for (short l = 0; l < 4; l++)
livelli_giacenza().set_sheetcolumn(sf, F_LIV1+l, l+1);
TConfig ini(CONFIG_DITTA, "mg");
if (!ini.get_bool("GESDEPOSITI"))
{
sf.delete_column(F_DEPOSITO);
sf.sheet_mask().hide(F_DEPOSITO);
}
if (!ini.get_bool("GESMULTIMAG"))
{
sf.sheet_mask().disable(F_MAGAZZINO);
}
if (!ini.get_bool("GESTIMPIANTI", "mr"))
{
hide(F_IMPIANTO);
sf.delete_column(F_CODIMP);
sf.sheet_mask().hide(F_CODIMP);
sf.sheet_mask().hide(F_DESCIMP);
}
_week_complete = ini.get_bool("WEEKCOMPLETE", "mr");
_standard_for = ini.get_long("CODFOR", "mr");
sfield(F_LINEE).disable();
// sfield(F_TESTE).disable();
load_profile();
_npr_pos =_sel_color.add_color_def("PROP", TR("Nuove proposte"), COLOR_YELLOW, COLOR_BLACK);
}
void TMSPCheck_mask::go_top()
{
gopos(2,1);
if (move_to(FC_UP))
if (move_to(FC_UP))
fill_mask();
fix_actual_pos();
}
void TMSPCheck_mask::gopos_mainmask()
{
TSheet_field &sf=_main_mask->sfield(F_ARTICOLI);
int curr_row=last_row();
while (sf.cell_disabled(curr_row,F_BUCKET1-FIRST_FIELD) )
curr_row++;
sf.select(curr_row/*,TRUE*/);
_main_mask->set_focus_field(sf.dlg());
sf.set_focus_cell(curr_row, last_col()*2+F_BUCKET0);
}
TMSPCheck_mask::TMSPCheck_mask(TPlanning_mask * main_mask, const char *m,TSheet_field * s):
TAutomask(m), _main_mask(main_mask) , _sheet(s)
{
_last_col=_last_row=_constr_row=-1;
}
TMSPCheck_mask::TMSPCheck_mask(TPlanning_mask * main_mask):
TAutomask("mr2200b.msk"), _main_mask(main_mask), _sheet(&main_mask->sfield(F_ARTICOLI))
{
livelli_giacenza().set_mask_fields(*this, FC_LIV1);
_last_col=_last_row=_constr_row=-1;
go_top();
set(FC_MINBUCK2CHECK,0L);
set(FC_MAXBUCK2CHECK,LAST_BUCKET);
}
//valori di ritorno:
// 0 : nessun errore
// 1 : esistono modifiche
// 2 : esistono nuove proposta
// 4 : giacenza media superiore al voluto
// 8 : sotto stock
int TMSPCheck_mask::fill_mask(const bool show_fields)
{
int error=0;
if (_last_col==_col && _last_row==_row)
return error;
const bool is_constr=is_constraint(_row);
TToken_string &row=_sheet->row(_row);
long codcli ;
TCodice_articolo codart;
TString16 liv;
TString8 mag, magc, codimp, codlin;
TString4 um;
_main_mask->msprow2codes(row, codcli, codart, liv, mag, magc, codimp, codlin, um);
TArticolo_giacenza art(codart);
if (_last_row!=_row)
{
_constr_row=find_constr_row(_row);
set(FC_RIGA,_row+1);
field(FC_CODCLI).set_prompt(_main_mask->get(F_TIPOCF)[0]=='C' ? "Cliente":"Fornitore");
set(FC_CODCLI,codcli, TRUE);
set(FC_CODART,codart, TRUE);
for (int l= livelli_giacenza().last_level(); l >= 1 ; l--)
set(FC_LIV1+l-1, livelli_giacenza().unpack_grpcode(liv,l), TRUE);
set(FC_CODIMP,codimp, TRUE);
set(FC_CODLIN,codlin, TRUE);
set(FC_CODMAG,mag.left(3), TRUE);
set(FC_CODDEP,mag.mid(3), TRUE);
//set(FC_CODMAG_C,magc.left(3), TRUE);
//set(FC_CODDEP_C,magc.mid(3), TRUE);
}
set(FC_BUCKET,_col);
TDate data_buck(_main_mask->starting_date());
data_buck += (_main_mask->days_per_bucket())*(_col);
_main_mask->round_date(data_buck);
data_buck -= 1;
set(FC_DATE2,_col==LAST_BUCKET ? "" : data_buck.string());
_main_mask->round_date(data_buck);
set(FC_DATE1,_col==0 ? "" : data_buck.string());
set(FC_IS_VINCOLO,is_constr ? "X" : " ");
field(FC_IS_VINCOLO).on_hit();
if (!is_constr)
{
real art_per_buck(row.get(F_BUCKET0 + _col*2 - FIRST_FIELD));
set(FC_FINAL_VALUE,art_per_buck.string());
TMRP_line* new_article = _main_mask->find_propose(codcli, codart, liv, codimp, codlin, mag, magc);
TMSP_line* old_article = _main_mask->find_article(codcli, codart, liv, codimp, codlin, mag, magc);
real old_value=ZERO;
real new_value=ZERO;
if (old_article)
{
old_value=old_article->qta(_col);
}
if (new_article)
{
TMRP_time t(data_buck,0,"","");
TMRP_record& mrprec = new_article->record(t);
new_value=mrprec.sched_receipts();
if (new_value > ZERO)
error|=2;
}
set(FC_STARTING_VALUE,old_value.string());
set(FC_PROPOSED_VALUE,new_value.string());
show(FC_PROPOSED_VALUE,!new_value.is_zero());
show(FC_STARTING_VALUE,!old_value.is_zero());
if (old_value != art_per_buck)
error|=1;
// mostra i campi
hide(FC_GIAC);
hide(FC_UNDERSTOCK);
}
if (_constr_row>=0)
{
// calcola il sotto stock
real stock(_sheet->cell(_constr_row,F_BUCKET0 + _col*2 - FIRST_FIELD));
real soglia;
switch (*_main_mask->get(F_SOGLIAATT))
{
case 'R':
soglia = art.scorta_minima(mag, liv, 0, TRUE);
if (!soglia.is_zero()) break;
case 'S':
soglia = art.scorta_minima(mag, liv, 0, FALSE); break;
default:
soglia = ZERO;
}
soglia = soglia -0.01;
bool stockbreak = stock < soglia;
bool overgiac = FALSE;
set(FC_GIAC,stock.string());
show(FC_GIAC, stock > ZERO);
stock = soglia - stock;
set(FC_UNDERSTOCK,stock.string());
show(FC_UNDERSTOCK, stockbreak);
error|=stockbreak ? 8 : 0;
// calcola i giorni di permanenza
stock = - stock;
real giorni=ZERO;
if (!stockbreak)
{
int bucket=0;
int buck_days = _main_mask->days_per_bucket();
real prev_stock(_sheet->cell(_constr_row,F_BUCKET0 + 2*_col - 1 - FIRST_FIELD));
real delivery(_sheet->cell(_constr_row-1,F_BUCKET0 + 2*_col - FIRST_FIELD));
stock=stock-prev_stock+delivery;
if (stock > ZERO)
{
real residuo=stock;
residuo.round(2);
while (residuo > ZERO && (_col + bucket)<LAST_BUCKET)
{
delivery = _sheet->cell(_constr_row-1,F_BUCKET0 + 2*_col + bucket - FIRST_FIELD);
if (delivery < prev_stock)
{
prev_stock-=delivery;
delivery=ZERO;
} else {
delivery-=prev_stock;
prev_stock=ZERO;
}
residuo-= delivery;
if (residuo < ZERO) residuo=ZERO;
giorni+= residuo;
bucket++;
}
giorni = buck_days*giorni / stock;
const int maxdays(_main_mask->get_int(F_MAXGIORNIGIAC));
overgiac=(giorni.integer() > maxdays);
error|=overgiac ? 4 : 0;
}
}
set(FC_GIORNIGIAC,giorni.string());
set(FC_OVERGIORNIGIAC,giorni.string());
show(FC_GIORNIGIAC, !overgiac);
show(FC_OVERGIORNIGIAC,overgiac);
}
if (get_int(FC_FINDFILTER)==-1)
{
return codart==get(FC_ARTICLE2FIND);
}
else if (get_int(FC_FINDFILTER)==-2)
{
if (is_constr)
{
return _sheet->row(_row-1).get_char(F_MASTERCODE-FIRST_FIELD)==MASTERCODE_CHAR;
}
return FALSE;
}
else
return error;
}
void TMSPCheck_mask::fix_actual_pos()
{
_last_col=_col;
_last_row=_row;
}
void TMSPCheck_mask::gopos(int row, int col)
{
_row=row >= 0 ? row : 0;
_col=col;
fill_mask();
fix_actual_pos();
}
bool TMSPCheck_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
if (e==fe_button)
{
const int dlg=o.dlg();
bool redo=TRUE;
const int findfilter=get_int(FC_FINDFILTER);
const TString4 old_movefilter(get(FC_MOVEFILTER));
const TString4 new_movefilter(findfilter & 1 ? "" : "C");
switch (dlg)
{
case FC_UP_BAD:
case FC_LEFT_BAD:
case FC_DOWN_BAD:
case FC_RIGHT_BAD:
set(FC_MOVEFILTER,new_movefilter);
break;
}
switch (dlg)
{
case FC_UP_BAD:
if (redo = move_to(FC_UP))
_col = LAST_BUCKET+1;
case FC_LEFT_BAD:
while (redo)
{
while ((findfilter>0 || _col>LAST_BUCKET) && move_to(FC_LEFT))
{
int err=fill_mask() ;
fix_actual_pos();
if (findfilter<0 && err || err & findfilter)
{
set(FC_MOVEFILTER,old_movefilter);
return TRUE;
}
}
if (redo = move_to(FC_UP))
_col = LAST_BUCKET+1;
}
message_box(TR("Ricerca terminata"));
break;
case FC_DOWN_BAD:
if (redo = move_to(FC_DOWN))
_col = -1;
case FC_RIGHT_BAD:
while (redo)
{
while ((findfilter>0 || _col<0)&& move_to(FC_RIGHT))
{
int err=fill_mask() ;
fix_actual_pos();
if (findfilter<0 && err || err & findfilter)
{
set(FC_MOVEFILTER,old_movefilter);
return TRUE;
}
}
if (redo = move_to(FC_DOWN))
_col = -1;
}
message_box(TR("Ricerca terminata"));
break;
default:
move_to(dlg);
fill_mask();
fix_actual_pos();
}
set(FC_MOVEFILTER,old_movefilter);
}
return TRUE;
}
int TMSPCheck_mask::find_constr_row(int row)
{
while (row >=0 )
{
if (is_constraint(row))
return row;
row--;
}
return -1;
}
bool TMSPCheck_mask::is_constraint(int row)
{
return (row > 0
&& _sheet->cell_disabled(row, F_BUCKET1-FIRST_FIELD)
&& _sheet->cell_disabled(row-1, F_BUCKET1-FIRST_FIELD));
}
bool TMSPCheck_mask::is_article(int row)
{
return !_sheet->cell_disabled(row, F_BUCKET1-FIRST_FIELD);
}
bool TMSPCheck_mask::move_to(int dlg)
{
const bool constraints=*get(FC_MOVEFILTER)!='A';
const bool articles=*get(FC_MOVEFILTER)!='C';
CHECK(constraints||articles, "N'do cazzo muovo?");
const int max_rows=_sheet->items();
bool skip_row=TRUE;
int old_row=_row;
switch (dlg)
{
case FC_DOWNLEFT:
case FC_DOWNRIGHT:
case FC_DOWN:
while (_row < max_rows-1)
{
_row++;
if (constraints && is_constraint(_row) || articles && is_article(_row))
break;
}
if (dlg==FC_DOWNRIGHT) _col++;
if (dlg==FC_DOWNLEFT) _col--;
break; // se non sono sulla linea giusta, torno indietro
case FC_UPRIGHT:
case FC_UPLEFT:
case FC_UP:
while (_row >0 )
{
_row--;
if (constraints && is_constraint(_row) || articles && is_article(_row))
break;
}
if (dlg==FC_UPRIGHT) _col++;
if (dlg==FC_UPLEFT) _col--;
break;
case FC_LEFT:
_col--;
break;
case FC_RIGHT:
_col++;
break;
}
if (!((articles && is_article(_row) ) || (constraints && is_constraint(_row))))
_row=old_row;
check_pos_range();
if (_last_col==_col && _last_row==_row)
return FALSE;
return TRUE;
}
void TMSPCheck_mask::check_pos_range()
{
int max_cols=max(get_int(FC_MINBUCK2CHECK),min(get_int(FC_MAXBUCK2CHECK),LAST_BUCKET));
if (max_cols==0) max_cols=LAST_BUCKET;
int min_cols=max(get_int(FC_MINBUCK2CHECK),0);
if (min_cols>max_cols) min_cols=max_cols;
const bool constraints=*get(FC_MOVEFILTER)!='A';
const int max_rows=_sheet->items();
if (_row>=max_rows) _row=max_rows-1;
if (_row< (constraints ? 1 : 2) ) _row++;
if (_col>=max_cols) _col=max_cols;
if (_col<min_cols+1) _col=min_cols;
}
///////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////
TCRPCheck_mask::TCRPCheck_mask(TPlanning_mask * main_mask):
TMSPCheck_mask(main_mask, "mr2200c.msk", & main_mask->sfield(F_LINEE))
{
go_top();
set(FC_MINBUCK2CHECK,0L);
set(FC_MAXBUCK2CHECK,LAST_BUCKET);
}
void TCRPCheck_mask::check_pos_range()
{
const bool constraints=*get(FC_MOVEFILTER)!='A';
const int max_rows=_sheet->items();
if (_row>=max_rows) _row=max_rows-1;
if (_row< (constraints ? 0 : 1) ) _row++;
if (_col>=LAST_BUCKET) _col=LAST_BUCKET-1;
if (_col<1) _col=1;
}
bool TCRPCheck_mask::is_constraint(int row)
{
return (row > 0
&& !_sheet->cell_disabled(row, F_LBUCKET1-FIRST_FIELD)
&& _sheet->cell_disabled(row-1, F_LBUCKET1-FIRST_FIELD));
}
bool TCRPCheck_mask::is_article(int row)
{
return (*_sheet->row(row).get(F_CODARTCRP-FIRST_FIELD)>' ');
}
int TCRPCheck_mask::find_constr_row(int row)
{
const int max=max_rows();
while (row < max)
{
if (is_constraint(row))
return row;
row++;
}
return -1;
}
int TCRPCheck_mask::fill_mask(const bool show_fields)
{
int error=0;
if (_last_col==_col && _last_row==_row)
return error;
const bool is_constr=is_constraint(_row);
TSheet_field& sf = _main_mask->sfield(F_LINEE);
TToken_string &row=sf.row(_row);
long codcli ;
TCodice_articolo codart;
TString16 liv, codimp, codlin, um;
_main_mask->crprow2codes(row,codimp, codlin,codcli,codart,liv,um);
if (_last_row!=_row)
{
_constr_row=find_constr_row(_row);
set(FC_RIGA,_row+1);
set(FC_CODIMP,codimp);
set(FC_CODLIN,codlin);
set(FC_CODCLI,codcli);
set(FC_CODART,codart);
}
set(FC_BUCKET,_col);
TDate data_buck(_main_mask->starting_date());
data_buck += (_main_mask->days_per_bucket())*(_col-1);
_main_mask->round_date(data_buck);
set(FC_DATE1,data_buck.string());
_main_mask->round_date(data_buck,TRUE);
set(FC_DATE2,data_buck.string());
set(FC_IS_VINCOLO,is_constr ? "X" : " ");
field(FC_IS_VINCOLO).on_hit();
if (!is_constr)
{
// articolo
real art_load(_sheet->cell(_row ,F_LBUCKET1 + _col - 1 - FIRST_FIELD));
set(FC_ART_LOAD,art_load.string());
}
if (_constr_row>=0)
{
// vincolo
real load(_sheet->cell(_constr_row ,F_LBUCKET1 + _col - 1 - FIRST_FIELD));
set(FC_LOAD,load.string());
show(FC_LOAD,load>ZERO);
real capacity(_sheet->cell(_constr_row -1 ,F_LBUCKET1 + _col - 1 - FIRST_FIELD));
const bool positive=capacity>ZERO;
set(FC_CAPACITY,capacity.string());
show(FC_CAPACITY,positive);
capacity-=load;
const bool out=capacity<ZERO;
set(FC_CAPACITY_REM,capacity.string());
if (out)
{
capacity=-capacity;
error|=8;
}
set(FC_CAPACITY_OUT,capacity.string());
show(FC_CAPACITY_REM,positive && !out);
show(FC_CAPACITY_OUT,positive && out);
}
return error;
}
///////////////////////////////////////////////////////////
// Applicazione principale
///////////////////////////////////////////////////////////
void TPlanning_app ::openfiles()
{
open_files(LF_TABCOM, LF_TAB, LF_DOC, LF_RIGHEDOC, 0);
open_files(LF_CLIFO, LF_CFVEN, LF_OCCAS, LF_INDSP, LF_CONDV, 0);
open_files(LF_MAG, LF_MOVMAG, LF_RMOVMAG, 0);
open_files(LF_ANAMAG, LF_DIST, LF_RDIST, LF_MRPREPORT, 0);
}
bool TPlanning_app ::create()
{
openfiles();
_m = new TPlanning_mask();
_m->field(F_MSCHEDULEPLAN).set(" ");
return TSkeleton_application::create();
}
void TPlanning_app::main_loop()
{
TConfig prassid(CONFIG_DITTA, "ve"); // apre il file di configurazione della ditta corrente
if (prassid.get_bool("GES", NULL, A_LISTINI))
{
mask().enable(F_CATVEN_CV,prassid.get_bool("GESLISCV"));
}
else
{
mask().disable(F_TIPOCV);
mask().disable(F_CATVEN_CV);
}
while (mask().run()!=K_QUIT) ;
}
int mr2200(int argc, char* argv[])
{
TPlanning_app a;
a.run(argc, argv, TR("Pianificazione ordini"));
return 0;
}