Files correlati : Ricompilazione Demo : [ ] Commento : cambiata chiamata a funzione ridefinita git-svn-id: svn://10.65.10.50/trunk@18399 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			4592 lines
		
	
	
		
			145 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4592 lines
		
	
	
		
			145 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include "mr2200.h"
 | 
						||
#include "mr2200a.h"
 | 
						||
#include "mr2200b.h"
 | 
						||
 | 
						||
#include <defmask.h>
 | 
						||
#include <progind.h>
 | 
						||
#include <tabutil.h>
 | 
						||
#include <urldefid.h>
 | 
						||
#include <utility.h>
 | 
						||
 | 
						||
#include "../ve/veconf.h"
 | 
						||
 | 
						||
class TMSPCheck_mask : public TAutomask
 | 
						||
{
 | 
						||
protected:
 | 
						||
  int _col, _row, _constr_row, _last_col, _last_row;
 | 
						||
  TPlanning_mask * _main_mask;
 | 
						||
  TSheet_field * _sheet;
 | 
						||
 | 
						||
  int max_rows() const { 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() const { return _last_row;}
 | 
						||
  short last_col() const { 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;
 | 
						||
  default:
 | 
						||
    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;
 | 
						||
    const TString_array& nums = sfield(id).rows_array();
 | 
						||
    for (int i = nums.last(); i >= 0; i--)
 | 
						||
    {
 | 
						||
      TToken_string& str = (TToken_string&)nums.row(i);
 | 
						||
      const char* t = str.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) 
 | 
						||
{
 | 
						||
  TString_array& nums = sheet_num.rows_array();
 | 
						||
  TString_array& types = sheet_type.rows_array();
 | 
						||
  for (int j = types.last(); j >= 0; j--)
 | 
						||
  {
 | 
						||
    bool ok = false;
 | 
						||
    const TString4 tipo = types.row(j).get(0) ;
 | 
						||
    for (int i = nums.last(); 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::test_special(const TString & num) const
 | 
						||
{
 | 
						||
	const TRectype & rec = cache().get("%NUM", num);
 | 
						||
 | 
						||
  return rec.get_bool("B9");
 | 
						||
}
 | 
						||
 | 
						||
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()
 | 
						||
{
 | 
						||
  bool some_lines = false;
 | 
						||
  clear_sheets();
 | 
						||
  if (carica_documenti())
 | 
						||
  {
 | 
						||
    fill_sheet();
 | 
						||
    TSheet_field& s = sfield(F_ARTICOLI);
 | 
						||
    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;
 | 
						||
}
 | 
						||
 | 
						||
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 order_break=get_bool(F_SINGLE_DOC);
 | 
						||
  const bool is_master_sched = get_bool(F_MSCHEDULEPLAN);
 | 
						||
  const bool two_level = get_bool(F_2LEVEL_MSP);
 | 
						||
	const int depth = get_int(F_RIFERIMENTO_MSP);
 | 
						||
 | 
						||
	_mrp_articles.ignore(false, false, false, false, !order_break);
 | 
						||
  _proposed_articles.ignore(false, false, false, false, !order_break);
 | 
						||
	_proposed_1stlevel.ignore(false, false, false, false, !order_break);
 | 
						||
	
 | 
						||
		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 TCodice_articolo f_art(get(F_FRART));
 | 
						||
  const bool f_art_fill = f_art.full();
 | 
						||
  const TCodice_articolo t_art(get(F_TOART));
 | 
						||
  const bool t_art_fill = t_art.full();
 | 
						||
  TString8 f_grm(get(F_FRGRM)); f_grm.rpad(3);
 | 
						||
  f_grm << get(F_FRSGM); f_grm.trim();
 | 
						||
  const bool f_grm_fill = f_grm.full();
 | 
						||
  TString8 t_grm(get(F_TOGRM)); t_grm.rpad(3);
 | 
						||
  t_grm << get(F_FRSGM); t_grm.trim();
 | 
						||
  const bool t_grm_fill = t_grm.full();
 | 
						||
	TString8 imp; 
 | 
						||
 | 
						||
	if (!ignore_imp)
 | 
						||
		imp = get(F_IMP);
 | 
						||
 | 
						||
  const bool filtered = f_art_fill || t_art_fill || f_grm_fill || t_grm_fill || imp.full();
 | 
						||
 | 
						||
  const int year_fr = date_fr.year() - (get_bool(F_DOC_YEAR_PREC) ? 1 : 0);
 | 
						||
  const int year_to = date_to.year();
 | 
						||
	TDate datalim(date_fr);
 | 
						||
	const int days = days_per_bucket();
 | 
						||
 | 
						||
	datalim -= get_int(F_LIM);
 | 
						||
 | 
						||
  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();
 | 
						||
 | 
						||
      // 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;  
 | 
						||
        const bool ignore_prec = get_bool(F_IGNORE_PREC);
 | 
						||
 | 
						||
//        if (ignore_prec && (tn & _Doc_planning) && (datacons < date_fr))
 | 
						||
//          continue;
 | 
						||
				const bool skip = ignore_prec && (tn & _Doc_planning) && (datacons < date_fr);
 | 
						||
        
 | 
						||
				if (skip)
 | 
						||
					if (datacons < datalim)
 | 
						||
						continue;
 | 
						||
        // Scandisce le righe articolo e memorizza
 | 
						||
        // le quantita' richieste
 | 
						||
        const 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 && imp.not_empty())
 | 
						||
							{
 | 
						||
								const TString & r_imp = riga.get(RDOC_IMPIANTO);
 | 
						||
								ok = (imp == r_imp);
 | 
						||
							}
 | 
						||
            }
 | 
						||
            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); 
 | 
						||
              TString80 da_rdoc_key;
 | 
						||
 | 
						||
							if  (order_break)
 | 
						||
							{
 | 
						||
								if ((tn & _Doc_vincoli) && (depth == 0))
 | 
						||
								{
 | 
						||
									da_rdoc_key.format("%-4s%4dD%7ld%4d", 
 | 
						||
										    (const char *) riga.get(RDOC_CODNUM), riga.get_int(RDOC_ANNO), 
 | 
						||
			                  riga.get_long(RDOC_NDOC), riga.get_int(RDOC_IDRIGA));
 | 
						||
								}
 | 
						||
								else
 | 
						||
									da_rdoc_key.format("%-4s%4dD%7ld%4d", 
 | 
						||
										    (const char *) riga.get(RDOC_DACODNUM), riga.get_int(RDOC_DAANNO), 
 | 
						||
			                  riga.get_long(RDOC_DANDOC), riga.get_int(RDOC_DAIDRIGA));
 | 
						||
							}
 | 
						||
              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 = NULL;
 | 
						||
 | 
						||
              if (tn & _Doc_vincoli)
 | 
						||
              {        
 | 
						||
                line = _constraints.find(cli, art, liv, imp, lin, mag, magc, da_rdoc_key, true);
 | 
						||
                line->set_mastercode_check(two_level && !distinta_master(art));
 | 
						||
              }
 | 
						||
              else
 | 
						||
							{
 | 
						||
								if (skip)
 | 
						||
								{
 | 
						||
									const long p = riga.get_long(RDOC_PRIORITY);
 | 
						||
			            TMSP_constraint* linec = _constraints.find(cli, art, liv, imp, ignore_lin ? "" : lin, mag, magc, da_rdoc_key, false);
 | 
						||
 | 
						||
									if (linec != NULL)
 | 
						||
									{
 | 
						||
										if (p > linec->priority())
 | 
						||
										{
 | 
						||
											linec->priority(p);
 | 
						||
											line = _articles.find(cli, art, liv, imp, lin, mag, magc, da_rdoc_key, true);
 | 
						||
				              if (line->description().blank())
 | 
						||
								        line->set_description(riga.get(RDOC_DESCR));
 | 
						||
										}
 | 
						||
									}
 | 
						||
									continue;
 | 
						||
								}
 | 
						||
								line = _articles.find(cli, art, liv, imp, lin, mag, magc, da_rdoc_key, true);
 | 
						||
              }
 | 
						||
 | 
						||
              if (line->description().blank())
 | 
						||
                line->set_description(riga.get(RDOC_DESCR));      
 | 
						||
 | 
						||
              if (buck >= 0 && buck <= LAST_BUCKET)
 | 
						||
              {
 | 
						||
                const int annodoc=riga.get_int(RDOC_ANNO); 
 | 
						||
                TString4 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 * q.val() / qta; 
 | 
						||
                TMRP_docref* dr = line->add_rigaref(buck, codnum, annodoc, numdoc, numrig, q.um(), q.val(), prz);// memorizza la provenienza dal doc
 | 
						||
 | 
						||
                long p = riga.get_long(RDOC_PRIORITY);
 | 
						||
                const bool user_defined_priority = p > 0;
 | 
						||
                if (!user_defined_priority)
 | 
						||
                {
 | 
						||
                  const TString& priority_formula = get(F_PRIORITY);
 | 
						||
                  if (!priority_formula.blank())
 | 
						||
                  {
 | 
						||
                    TExpression expr(priority_formula);
 | 
						||
                    if (expr.numvar() > 0)
 | 
						||
                    {
 | 
						||
                      for (int i = expr.numvar()-1; i >= 0; i--)
 | 
						||
                      {
 | 
						||
                        const TString vn(expr.varname(i));
 | 
						||
											  if (vn == "DATE_PRIORITY")
 | 
						||
											  {
 | 
						||
                          real buck_priority;
 | 
						||
                          if (tn & _Doc_vincoli)
 | 
						||
                          {
 | 
						||
                            buck_priority = date_to - consegna;
 | 
						||
                            if (buck_priority < ZERO)
 | 
						||
                              buck_priority = ZERO;
 | 
						||
                          }
 | 
						||
												  expr.setvar(i, buck_priority);
 | 
						||
											  }
 | 
						||
											  else
 | 
						||
											  {
 | 
						||
												  const TFieldref fr(vn, 0);
 | 
						||
												  switch (fr.file())
 | 
						||
												  {
 | 
						||
												  case LF_DOC:
 | 
						||
													  expr.setvar(i, fr.read(doc));
 | 
						||
													  break;
 | 
						||
												  case LF_RIGHEDOC:
 | 
						||
													  expr.setvar(i, fr.read(riga));
 | 
						||
													  break;
 | 
						||
												  default:
 | 
						||
													  {
 | 
						||
														  const TRectype& recart = cache().get(LF_ANAMAG, art);
 | 
						||
														  expr.setvar(i, fr.read(recart));
 | 
						||
													  }
 | 
						||
													  break;
 | 
						||
												  }
 | 
						||
											  }
 | 
						||
                      }
 | 
						||
                      p = expr.as_real().integer();
 | 
						||
                    }
 | 
						||
                  }
 | 
						||
                }
 | 
						||
								if (p > line->priority())
 | 
						||
									line->priority(p);
 | 
						||
              }
 | 
						||
              
 | 
						||
              if (!skip)
 | 
						||
							{
 | 
						||
              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.full())
 | 
						||
    {
 | 
						||
      TLinea_prod &linea_prod=*::get_linea(codlin);
 | 
						||
      codimp=linea_prod.codimp();
 | 
						||
    }                                
 | 
						||
  }
 | 
						||
  if (codmag.blank())
 | 
						||
  {
 | 
						||
    if (codlin.full())
 | 
						||
    {
 | 
						||
      TLinea_prod &linea_prod=*::get_linea(codlin);
 | 
						||
      codmag=linea_prod.codmagdep();
 | 
						||
    }
 | 
						||
		else
 | 
						||
		{
 | 
						||
      if (codimp.full())
 | 
						||
      {
 | 
						||
        TImpianto &impianto=*::get_impianto(codimp);
 | 
						||
        codmag=impianto.codmagdep();
 | 
						||
      } 
 | 
						||
		}
 | 
						||
  }
 | 
						||
 | 
						||
	TString da_rdoc_key(l.da_rdoc_key());
 | 
						||
 | 
						||
  // cerca il vincolo con - stesso magazzino , impianto e  linea
 | 
						||
   TMSP_constraint* c = _constraints.find(codcli, l.articolo(), l.livgiac(), codimp, codlin, codmag, EMPTY_STRING, da_rdoc_key);
 | 
						||
  if (c == NULL )
 | 
						||
  {
 | 
						||
    long try_cli = codcli;
 | 
						||
    do {
 | 
						||
      if (codmag.full())
 | 
						||
      {
 | 
						||
        // cerca il vincolo con - stesso magazzino e impianto 
 | 
						||
        c =_constraints.find(try_cli, l.articolo(), l.livgiac(), codimp, "", codmag, EMPTY_STRING,  da_rdoc_key);
 | 
						||
        if (c == NULL)
 | 
						||
          // cerca il vincolo con - stesso magazzino 
 | 
						||
          c =_constraints.find(try_cli, l.articolo(), l.livgiac(), "", "", codmag, EMPTY_STRING,  da_rdoc_key);
 | 
						||
      } 
 | 
						||
      if (c == NULL)
 | 
						||
        // cerca il vincolo con - stesso impianto e  linea 
 | 
						||
        c =_constraints.find(try_cli, l.articolo(), l.livgiac(), codimp, codlin, "", EMPTY_STRING,  da_rdoc_key);
 | 
						||
      if (c == NULL)
 | 
						||
        // cerca il vincolo con - stessa impianto
 | 
						||
        c =_constraints.find(try_cli, l.articolo(), l.livgiac(), codimp, "" , "", EMPTY_STRING,  da_rdoc_key);
 | 
						||
      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, EMPTY_STRING, l.da_rdoc_key(), 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();
 | 
						||
	int r;
 | 
						||
 | 
						||
  for (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();
 | 
						||
    }
 | 
						||
    TString8 imp(row.get(sf.cid2index(F_CODIMP)));imp.trim();
 | 
						||
    TString8 lin(row.get(sf.cid2index(F_CODLIN)));lin.trim();
 | 
						||
    TString8 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);
 | 
						||
	TString8 codnum = cons.da_rdoc_key().left(4);
 | 
						||
	codnum.trim();
 | 
						||
	const bool special = test_special(codnum);
 | 
						||
 | 
						||
	highlight_row(sf.items() - 1, special);
 | 
						||
  cons.fill_sheet_row(row, *this, TR("** Ordini "));
 | 
						||
  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, TR("** Giacenza teorica"));
 | 
						||
	highlight_row(sf.items() - 1, special);
 | 
						||
  sf.disable_cell(sf.items()-1, -1);
 | 
						||
  //linea articolo (vuota)
 | 
						||
  TMSP_line line(cons);
 | 
						||
	highlight_row(sf.items() - 1, special);
 | 
						||
  r = sf.items()-3+2;  // vacca
 | 
						||
 | 
						||
  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;
 | 
						||
	bool special = false;
 | 
						||
  // *************
 | 
						||
  // 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);
 | 
						||
		TString8 codnum = curr_constraint->da_rdoc_key().left(4);
 | 
						||
 | 
						||
		codnum.trim();
 | 
						||
		const bool special = test_special(codnum);
 | 
						||
    int new_row = -1;
 | 
						||
    
 | 
						||
    for (int nrow = 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, TR("** Ordini "));
 | 
						||
 | 
						||
			highlight_row(sf.items()-1, special);
 | 
						||
      sf.disable_cell(sf.items()-1, -1);
 | 
						||
      // aggiunge la linea della giacenza prog
 | 
						||
      TToken_string& rowgiac = sf.row(-1);
 | 
						||
      copy_sheet_row(rowgiac,consrow, TR("** Giacenza teorica"));
 | 
						||
			highlight_row(sf.items()-1, special);
 | 
						||
      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, "");
 | 
						||
		highlight_row(new_row, special);
 | 
						||
    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
 | 
						||
			TString8 codnum = cons.da_rdoc_key().left(4);
 | 
						||
 | 
						||
			codnum.trim();
 | 
						||
			const bool special = test_special(codnum);
 | 
						||
      TToken_string& consrow = sf.row(-1);
 | 
						||
      cons.fill_sheet_row(consrow, *this, TR("** Ordini "));
 | 
						||
      cons.set_on_sheet();
 | 
						||
			highlight_row(sf.items()-1, special);
 | 
						||
      sf.disable_cell(sf.items()-1, -1);
 | 
						||
      //linea della giacenza prog
 | 
						||
      TToken_string& rowgiac = sf.row(-1);
 | 
						||
      copy_sheet_row(rowgiac,consrow, TR("** Giacenza teorica"));
 | 
						||
			highlight_row(sf.items()-1, special);
 | 
						||
      sf.disable_cell(sf.items()-1, -1);
 | 
						||
      //linea articolo (vuota)
 | 
						||
      TMSP_line line(cons);
 | 
						||
      line.fill_sheet_row(sf.row(-1), *this, "");
 | 
						||
      if (consrow.get_long(sf.cid2index(F_CLIENTE)))
 | 
						||
        sf.disable_cell(sf.items()-1,sf.cid2index(F_CLIENTE));
 | 
						||
 | 
						||
			highlight_row(sf.items()-1, special);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  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_row(int row, bool on)
 | 
						||
{                             
 | 
						||
  COLOR back = on ? _sel_color.get_back_color(_con_pos) : NORMAL_BACK_COLOR;
 | 
						||
  COLOR fore = on ? _sel_color.get_fore_color(_con_pos) : NORMAL_COLOR;
 | 
						||
  
 | 
						||
  sfield(F_ARTICOLI).set_back_and_fore_color(back, fore, row);
 | 
						||
}
 | 
						||
 | 
						||
void TPlanning_mask::highlight(int row, int col, bool on, bool special)
 | 
						||
{  
 | 
						||
	COLOR back;
 | 
						||
	COLOR fore;
 | 
						||
 | 
						||
	if (special)
 | 
						||
	{
 | 
						||
	  back = on ? _sel_color.get_back_color(_npr_pos) : _sel_color.get_back_color(_con_pos);
 | 
						||
		fore = on ? _sel_color.get_fore_color(_npr_pos) : _sel_color.get_fore_color(_con_pos);
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
	  back = on ? _sel_color.get_back_color(_npr_pos) : NORMAL_BACK_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(), a.da_rdoc_key());
 | 
						||
 | 
						||
    bool line_found = false;
 | 
						||
    TMSP_constraint*  constraint = find_constraint(line, false);
 | 
						||
    if (constraint == NULL)
 | 
						||
    {
 | 
						||
			if (sign < 0)
 | 
						||
				continue;
 | 
						||
//    aggiunge le tre linee
 | 
						||
			constraint = find_constraint(line, true);
 | 
						||
      TToken_string& row = sf.row(-1);
 | 
						||
      constraint->fill_sheet_row(row, *this, TR("** Ordini "));
 | 
						||
      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, TR("** Giacenza teorica"));
 | 
						||
      sf.disable_cell(sf.items()-1, -1);
 | 
						||
      //linea articolo (vuota)
 | 
						||
      TToken_string& emptyrowc = sf.row(-1);
 | 
						||
    }
 | 
						||
    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;
 | 
						||
      TString80 da_rdoc_key;
 | 
						||
 | 
						||
      msprow2codes(row,codcli,codart,liv, mag, magc, codimp, codlin, codum, da_rdoc_key);
 | 
						||
 | 
						||
      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 && a.da_rdoc_key() == da_rdoc_key);
 | 
						||
        if (line_found)
 | 
						||
          break;
 | 
						||
      } else {
 | 
						||
        TMSP_constraint*  currcons=_constraints.find(codcli, codart, liv, codimp, codlin, mag, magc, da_rdoc_key);
 | 
						||
        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();
 | 
						||
		TString8 codnum = constraint->da_rdoc_key().left(4);
 | 
						||
 | 
						||
		codnum.trim();
 | 
						||
		const bool special = test_special(codnum);
 | 
						||
 | 
						||
		highlight_row(art_row, special);
 | 
						||
    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, special);
 | 
						||
      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_id(cm.last_row(),cm.last_col()+F_LBUCKET0);
 | 
						||
}
 | 
						||
 | 
						||
bool TPlanning_mask::sortMSPsheet()
 | 
						||
{
 | 
						||
  TWait_cursor hg;
 | 
						||
  TSheet_field& a = sfield(F_ARTICOLI);
 | 
						||
  const int ss = get_int(F_MSP_SORT);
 | 
						||
  switch (-ss)
 | 
						||
  {
 | 
						||
  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_LPAC:  a.sort(TRiga_articolo::order_compareLPAC); 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();
 | 
						||
  
 | 
						||
  // Accende i bottoni di spostamento righe solo se si ordina per periorita'
 | 
						||
  enable(F_PRIORITY_HI, ss < SORT_BY_PRIORITY);
 | 
						||
  enable(F_PRIORITY_LO, ss < SORT_BY_PRIORITY);
 | 
						||
  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(_proposed_articles);
 | 
						||
 | 
						||
	last_propose.destroy();
 | 
						||
  int buck=NO_PROPOSE;
 | 
						||
  for (int level=1; ok && level <= 2; level++)
 | 
						||
  {
 | 
						||
    ok = load_MRP_lines(_stock_break, level, numriga);
 | 
						||
    if (ok)
 | 
						||
    {
 | 
						||
      _proposed_articles.destroy();
 | 
						||
      gross2net(_stock_break, lotsizing);
 | 
						||
      const char* 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);
 | 
						||
      ok = general_review(check_machine, check_human, useextralines, useextrahours,lotsizing, no_outcapacity,anticipomin,anticipomax,_stock_break, logic, msg);
 | 
						||
      if (ok)
 | 
						||
      {
 | 
						||
        const 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();
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void TPlanning_mask::review_cell(long mrp_row, int bucket, 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, bool firstfitxbucket)
 | 
						||
{
 | 
						||
  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);
 | 
						||
 | 
						||
      TMRP_line &mrpline = _mrp_articles[mrp_row];
 | 
						||
			TToken_string * row = mrpline.sheet_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 art_per_buck = mrp_rec.net_requirement(); // quantit<69> da produrre nel bucket
 | 
						||
 | 
						||
      if (art_per_buck > ZERO)
 | 
						||
      {
 | 
						||
        real pieces, curr_arts; 
 | 
						||
  
 | 
						||
        int lastbuck = mrpline.last_bucket();
 | 
						||
        TString16 livello_di_giacenza(mrpline.livgiac());
 | 
						||
        TString8 codlin(mrpline.codlin());
 | 
						||
        TString8 codimp(mrpline.codimp());
 | 
						||
				if (row != NULL)
 | 
						||
				{
 | 
						||
					codlin = row->get(F_CODLIN-FIRST_FIELD);
 | 
						||
					codimp = row->get(F_CODIMP-FIRST_FIELD);
 | 
						||
				}
 | 
						||
        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)
 | 
						||
        {
 | 
						||
					TArray labors;
 | 
						||
          TRiga_esplosione * l=dist_tree().first_critical_labor(labors);
 | 
						||
 | 
						||
          no_limits = (l == NULL);
 | 
						||
 | 
						||
					bool first_buck = true;
 | 
						||
 | 
						||
          if (!no_limits)
 | 
						||
          {
 | 
						||
						TLavorazione *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;
 | 
						||
						const real perc_min_lav = curr_labor->percentuale_minima();
 | 
						||
            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);
 | 
						||
            }
 | 
						||
 | 
						||
            int max_attempts = 3;
 | 
						||
 | 
						||
            // non anticipare articoli che potrebbero avere figli non anticipati automaticamente
 | 
						||
            if (!no_limits && get_bool(F_NOANTICIPI_MSP)) 
 | 
						||
              max_attempts = 2;
 | 
						||
 | 
						||
            while (art_per_buck > ZERO && attemp <= max_attempts) 
 | 
						||
            {
 | 
						||
              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();
 | 
						||
								if (firstfitxbucket)
 | 
						||
									upper_buck = LAST_BUCKET;
 | 
						||
								else
 | 
						||
									upper_buck = (attemp <= 2 ? bucket-anticipomin/days_per_bucket(): LAST_BUCKET);
 | 
						||
              }
 | 
						||
              if (lower_buck<1)
 | 
						||
                lower_buck=1;
 | 
						||
              if (!firstfitxbucket && upper_buck>bucket) 
 | 
						||
                upper_buck=bucket;
 | 
						||
              nbucket= (logic == _JIT_logic) ? upper_buck : lower_buck;
 | 
						||
 | 
						||
							int nlinea = -1, numlinee;
 | 
						||
                
 | 
						||
              if (ignore_lin || codlin.blank() )
 | 
						||
              {
 | 
						||
								if (codlin.blank())
 | 
						||
								{
 | 
						||
                nlinea=(attemp == 2 ? lineestd : 0 ) ;
 | 
						||
                numlinee=(attemp == 1 ? lineestd : maxlinee ) ;
 | 
						||
								}
 | 
						||
								else  // l'utente ha fissato la linea
 | 
						||
								{
 | 
						||
									if (attemp == 1)
 | 
						||
									{
 | 
						||
										nlinea = curr_labor->find_linea(codlin);
 | 
						||
										numlinee = nlinea + 1;
 | 
						||
									}
 | 
						||
									if (nlinea < 0)
 | 
						||
									{
 | 
						||
										nlinea = 0;
 | 
						||
										numlinee = (attemp < 3 ? 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  // ho un sotto-stock da risolvere
 | 
						||
                && nlinea >= 0 && nlinea<numlinee && nbucket>=lower_buck && nbucket <= upper_buck)  // sono entro il range definito
 | 
						||
              {
 | 
						||
                while (art_per_buck > ZERO && nlinea >= 0 && nlinea<numlinee && nbucket <= upper_buck)
 | 
						||
                {
 | 
						||
                  // scelgo la linea
 | 
						||
									TLinea_prod linea_prod(cache().get("LNP",curr_labor->cod_linea(nlinea)));
 | 
						||
									real perc_min = linea_prod.tempo_minimo();
 | 
						||
 | 
						||
									if (perc_min == ZERO)
 | 
						||
										perc_min = perc_min_lav;
 | 
						||
                  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 && first_buck && perc_min > ZERO)
 | 
						||
										{
 | 
						||
											real arts_min = art_per_buck * perc_min / CENTO; arts_min.round(5);
 | 
						||
 | 
						||
											if (arts_min > curr_arts)
 | 
						||
												curr_arts = ZERO;
 | 
						||
										}
 | 
						||
                    if (curr_arts > ZERO)
 | 
						||
                    {
 | 
						||
											first_buck = false;
 | 
						||
                      // 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
 | 
						||
                      const real 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);
 | 
						||
                      crpline_lin->load(nbucket).add_human(hload);
 | 
						||
                      crpline_imp->load(nbucket).add_human(hload);
 | 
						||
                      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, mrpline.da_rdoc_key(), 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) ||
 | 
						||
                      (logic == _first_fit_logic && firstfitxbucket))
 | 
						||
                    nbucket++;
 | 
						||
                  else
 | 
						||
                    nlinea++;
 | 
						||
                } // ciclo sulle linee
 | 
						||
								if (logic == _first_fit_logic && firstfitxbucket)
 | 
						||
									nlinea++;
 | 
						||
								else
 | 
						||
								{
 | 
						||
                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 = 0, lower_buck = 0, upper_buck = 0;
 | 
						||
            switch (logic)
 | 
						||
            {
 | 
						||
            case _uniform_logic:
 | 
						||
              lower_buck = bucket - anticipomax/days_per_bucket();
 | 
						||
              upper_buck = bucket-anticipomin/days_per_bucket();
 | 
						||
              break;
 | 
						||
            case _first_fit_logic:
 | 
						||
              lower_buck = bucket - anticipomax/days_per_bucket();
 | 
						||
              upper_buck = lower_buck;
 | 
						||
              break;
 | 
						||
            default:
 | 
						||
              upper_buck = bucket - anticipomin/days_per_bucket();
 | 
						||
              lower_buck = upper_buck;
 | 
						||
              break;
 | 
						||
            } 
 | 
						||
            if (lower_buck < 1)
 | 
						||
              lower_buck = 1;
 | 
						||
            if (upper_buck < lower_buck)  // Oppure bucket??????????????
 | 
						||
              upper_buck = lower_buck;
 | 
						||
            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())
 | 
						||
              {                       
 | 
						||
                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(), mrpline.da_rdoc_key(), 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); 
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
}
 | 
						||
    
 | 
						||
// 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 long max_mrp_rows=_mrp_articles.items();
 | 
						||
  
 | 
						||
	if (max_mrp_rows == 0)
 | 
						||
    return true;
 | 
						||
 | 
						||
  for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
 | 
						||
  {
 | 
						||
		TMRP_line &mrpline = _mrp_articles[mrp_row];
 | 
						||
		TToken_string * row = mrpline.sheet_row();
 | 
						||
		TString8 codlin(mrpline.codlin());
 | 
						||
    TString8 codimp(mrpline.codimp());
 | 
						||
		if (row != NULL)
 | 
						||
		{
 | 
						||
			codlin = row->get(F_CODLIN-FIRST_FIELD);
 | 
						||
			codimp = row->get(F_CODIMP-FIRST_FIELD);
 | 
						||
		}
 | 
						||
		
 | 
						||
		TLinea_prod linea_prod(cache().get("LNP", codlin));
 | 
						||
    
 | 
						||
    if (_capacities.find(linea_prod) == NULL)
 | 
						||
			compute_capacity(linea_prod,useextralines, useextrahours);
 | 
						||
	}
 | 
						||
 | 
						||
	const bool firstfitxbucket = get_bool(F_FFBUCKET_MSP) ; 
 | 
						||
 | 
						||
	if (firstfitxbucket)
 | 
						||
		return inverse_general_review(check_machine, check_human, useextralines, useextrahours, lotsizing, no_outcapacity, anticipomin, anticipomax, mode, logic, msg);
 | 
						||
 | 
						||
  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;
 | 
						||
			review_cell(mrp_row, bucket, check_machine, check_human, useextralines, useextrahours, lotsizing, no_outcapacity, anticipomin, anticipomax, mode, logic, msg,  false);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
bool TPlanning_mask::inverse_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 long max_mrp_rows=_mrp_articles.items();
 | 
						||
  
 | 
						||
	if (max_mrp_rows == 0)
 | 
						||
    return true;
 | 
						||
 | 
						||
  TProgind pi((max_mrp_rows+1)*LAST_BUCKET ,msg, true, true);
 | 
						||
 | 
						||
  for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
 | 
						||
  {
 | 
						||
    pi.addstatus(1);
 | 
						||
	  for (int bucket = 0; bucket < LAST_BUCKET ; bucket++)
 | 
						||
		{
 | 
						||
		  pi.addstatus(1);
 | 
						||
      if (pi.iscancelled()) 
 | 
						||
        return false;
 | 
						||
			review_cell(mrp_row, bucket, check_machine, check_human, useextralines, useextrahours, lotsizing, no_outcapacity, anticipomin, anticipomax, mode, logic, msg,  true);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  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)
 | 
						||
{
 | 
						||
  const TString8 codlin = lineaprod.codice();
 | 
						||
  const TString8 codimp = lineaprod.codimp();
 | 
						||
  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)
 | 
						||
    {
 | 
						||
      const TMRP_calendar& cal = TMRP_time::get_calendar(codimp, codlin);
 | 
						||
      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())
 | 
						||
      {
 | 
						||
        const TMRP_calendar& cal_imp = TMRP_time::get_calendar(codimp);
 | 
						||
				int nturni = useextrahours ? cal.turni_max(data_buck) :cal.turni_min(data_buck);
 | 
						||
 | 
						||
        cal_imp.add_oreuomo(human_imp, data_buck,useextrahours, nturni);
 | 
						||
      }
 | 
						||
      if (compute_firm)
 | 
						||
      {
 | 
						||
        const TMRP_calendar& cal_firm = TMRP_time::get_calendar();
 | 
						||
        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)
 | 
						||
    {
 | 
						||
      const real hmin = crpline_imp->capacity(b).human();
 | 
						||
 | 
						||
			if (hmin < human_imp)
 | 
						||
				crpline_imp->capacity(b).set_human(human_imp);
 | 
						||
 | 
						||
//      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, const char * da_rdoc_key, bool force)
 | 
						||
{
 | 
						||
  return _proposed_articles.find(codart, liv, mag, magcoll, codimp, codlin, codcli,	da_rdoc_key, 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, TString & da_rdoc_key)
 | 
						||
{
 | 
						||
    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();
 | 
						||
 | 
						||
		const TString val = row.get(F_DESCART-FIRST_FIELD);
 | 
						||
		const int pos = val.find('<EFBFBD>');
 | 
						||
		if (pos >= 0)
 | 
						||
			da_rdoc_key = val.mid(pos+1);
 | 
						||
		else
 | 
						||
			da_rdoc_key = EMPTY_STRING;
 | 
						||
}
 | 
						||
 | 
						||
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.empty())
 | 
						||
    return message_box(TR("Nessun articolo da valutare"));
 | 
						||
  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 = 0L;
 | 
						||
        TCodice_articolo art ;
 | 
						||
        TString16 liv;
 | 
						||
        TString8 mag, magc, imp, lin;
 | 
						||
        TCodice_um um ;
 | 
						||
				TString80 da_rdoc_key;
 | 
						||
 | 
						||
        msprow2codes(*row, clifor, art, liv, mag, magc, imp, lin, um, da_rdoc_key);
 | 
						||
 | 
						||
          
 | 
						||
        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,	da_rdoc_key ,true);
 | 
						||
          added_on = -1;
 | 
						||
        }
 | 
						||
 | 
						||
				if (!is_constraint && curr_article->sheet_row() == NULL)
 | 
						||
					curr_article->set_row(row);
 | 
						||
        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;
 | 
						||
        default:
 | 
						||
          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
 | 
						||
{
 | 
						||
  const int cestini = get_int(F_BUCKETS);
 | 
						||
  return get_int(F_DAYXBUCK) * (cestini > 0 ? cestini : get_int(F_BUCKET));
 | 
						||
}
 | 
						||
 | 
						||
bool TPlanning_mask::bucket_mese() const
 | 
						||
{
 | 
						||
  return get(F_BUCKETS)[0] == 'M';
 | 
						||
}
 | 
						||
 | 
						||
void TPlanning_mask::clear_sheets()
 | 
						||
{
 | 
						||
  _start_date = NULLDATE;
 | 
						||
  _proposed_articles.destroy();
 | 
						||
  _mrp_articles.destroy();
 | 
						||
 | 
						||
  TSheet_field &sa=sfield(F_ARTICOLI);
 | 
						||
	
 | 
						||
	sa.set_line_number_width(4);
 | 
						||
  if (sa.items()>0)
 | 
						||
  {
 | 
						||
    sa.destroy();   
 | 
						||
    sa.force_update();   
 | 
						||
  }
 | 
						||
  TSheet_field &sl=sfield(F_LINEE);
 | 
						||
 | 
						||
	sl.set_line_number_width(4);
 | 
						||
  if (sl.items()>0)
 | 
						||
  {
 | 
						||
    sl.destroy();
 | 
						||
    sl.force_update();
 | 
						||
  }
 | 
						||
  xvtil_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;
 | 
						||
	int c;
 | 
						||
 | 
						||
  for (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' e la linea su tutte le righe del blocco
 | 
						||
  TString16 prior = curr_row.get(sf.cid2index(F_PRIORITA)); prior.trim();
 | 
						||
  TString16 old_prior=constr_row.get(sf.cid2index(F_PRIORITA)); old_prior.trim();
 | 
						||
  if (prior != old_prior)
 | 
						||
  {
 | 
						||
    if (prior.full())
 | 
						||
    {
 | 
						||
      for (int i = first-1; i<=last; i++)
 | 
						||
      {
 | 
						||
        sf.row( i ).add(prior , sf.cid2index(F_PRIORITA));
 | 
						||
        sf.force_update(i);
 | 
						||
      }
 | 
						||
    }
 | 
						||
    else
 | 
						||
      sf.row(r).add(old_prior, sf.cid2index(F_PRIORITA));
 | 
						||
 | 
						||
  }
 | 
						||
  TString8 codlin = curr_row.get(sf.cid2index(F_CODLIN)); prior.trim();
 | 
						||
  constr_row.add(codlin , sf.cid2index(F_CODLIN));
 | 
						||
  sf.force_update(first - 1);
 | 
						||
  // **********
 | 
						||
  // 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;
 | 
						||
  }
 | 
						||
  
 | 
						||
  const TArticolo_giacenza art(codart);
 | 
						||
  const long codcli=constr_row.get_long(F_CLIENTE-FIRST_FIELD);
 | 
						||
  const TString8 imp = constr_row.get(sf.cid2index(F_CODIMP));
 | 
						||
  const TString8 lin = constr_row.get(sf.cid2index(F_CODLIN));
 | 
						||
  TString16 liv;
 | 
						||
  TString8 mag;
 | 
						||
	TString80 da_rdoc_key;
 | 
						||
 | 
						||
  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)));
 | 
						||
 | 
						||
	const TString val = constr_row.get(sf.cid2index(F_BUCKET));
 | 
						||
	const int pos = val.find('<EFBFBD>');
 | 
						||
 | 
						||
	if (pos >= 0)
 | 
						||
		da_rdoc_key = val.mid(pos+1);
 | 
						||
 | 
						||
  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;
 | 
						||
      xvtil_statbar_set(err);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  sf.force_update(first);
 | 
						||
  if (signal) xvtil_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, EMPTY_STRING, da_rdoc_key);
 | 
						||
  
 | 
						||
    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(), EMPTY_STRING, art2ndlev->constraint().da_rdoc_key());
 | 
						||
    if (master_constr==NULL)
 | 
						||
      master_constr=_constraints.find(art2ndlev->constraint().codclifor(),mc->articolo(), mc->livello(), mc->codimp(), mc->codlin(), mc->codmagdep(), EMPTY_STRING, art2ndlev->constraint().da_rdoc_key()) ;
 | 
						||
 | 
						||
    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,LAST_BUCKET)==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)
 | 
						||
                    xvtil_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);
 | 
						||
	int c;
 | 
						||
  
 | 
						||
  for (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;
 | 
						||
      xvtil_statbar_set(err);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  if (signal) xvtil_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 char * desc)
 | 
						||
{
 | 
						||
  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);
 | 
						||
  }
 | 
						||
	if (desc && *desc)
 | 
						||
	{
 | 
						||
		newrow.get(F_DESCART - FIRST_FIELD, str);
 | 
						||
 | 
						||
		const int pos = str.find('<EFBFBD>');
 | 
						||
		TString val(desc);
 | 
						||
 | 
						||
		if (pos >= 0)
 | 
						||
			val << '<EFBFBD>' << str.mid(pos + 1); 
 | 
						||
 | 
						||
		newrow.add(val, F_DESCART - FIRST_FIELD);
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
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);
 | 
						||
	const TString80 art(row.get(F_ARTICOLO - FIRST_FIELD));
 | 
						||
	
 | 
						||
	if (art.blank())
 | 
						||
		return false;
 | 
						||
 | 
						||
  TMSP_line       &line    = *_articles.find(row, true);
 | 
						||
	TMRP_line       *mrpline = NULL;
 | 
						||
  TMSP_constraint *constraint = find_constraint(line);
 | 
						||
	
 | 
						||
	if (constraint != NULL) // Added by Guy
 | 
						||
	{
 | 
						||
		mrpline   = _mrp_articles.find(constraint->articolo(), constraint->livgiac(),
 | 
						||
																	 constraint->codmagdep(), "", constraint->codimp(),
 | 
						||
																	 constraint->codlin(), constraint->codclifor(),
 | 
						||
																	 constraint->da_rdoc_key());
 | 
						||
	}
 | 
						||
  
 | 
						||
  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 TString4 new_tipodoc(save_opt.get(F_TIPO_PLAN-FIRST_FIELD));
 | 
						||
      const TString4 new_codnum(save_opt.get(F_NUM_PLAN-FIRST_FIELD));
 | 
						||
      TDate datadoc = datacons;
 | 
						||
      switch (get(F_LEADTIME)[0])
 | 
						||
      {
 | 
						||
        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;
 | 
						||
				default:
 | 
						||
					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;
 | 
						||
      TString4 codnum;         
 | 
						||
      int anno = 0;
 | 
						||
      long numdoc = 0L;
 | 
						||
      int numrig = 0;
 | 
						||
    
 | 
						||
      real 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...
 | 
						||
        {
 | 
						||
          const real movable = ro - uo;
 | 
						||
          if (!movable.is_zero()) // ... ma posso spostare la qta da altrove
 | 
						||
          {
 | 
						||
            const real moved = fnc_min(new_val, movable);
 | 
						||
            new_val -= moved;
 | 
						||
            mrpline->record(b-1).add_unsched_ord(moved);
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }   
 | 
						||
      TMRP_docref *rdr = line.first_rigaref(b);
 | 
						||
			bool found = false;
 | 
						||
 | 
						||
      while (rdr || !found && 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);
 | 
						||
        }
 | 
						||
        const real old_val = rdr->qta_residua();
 | 
						||
        codnum = rdr->codnumdoc();
 | 
						||
        anno   = rdr->annodoc();
 | 
						||
        numdoc = rdr->numdoc();
 | 
						||
        numrig = rdr->numrig();
 | 
						||
        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))
 | 
						||
          {
 | 
						||
						const long old_priority = line.priority();
 | 
						||
						const long priority = row.get_long(sf.cid2index(F_PRIORITA));
 | 
						||
						const TString8 old_codlin(line.codlin());
 | 
						||
						TString8 codlin(row.get(sf.cid2index(F_CODLIN))); codlin.trim();
 | 
						||
 | 
						||
            val = new_val; new_val = ZERO;
 | 
						||
           if (val != old_val || codlin != old_codlin || priority != old_priority) // 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_val;
 | 
						||
              TRiga_documento& riga = doc_rows.add_to_row(rdr, incr);
 | 
						||
              if (priority > 0)
 | 
						||
                riga.put(RDOC_PRIORITY, priority);
 | 
						||
              riga.put(RDOC_LINEA, codlin);
 | 
						||
              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_IMPIANTO, line.codimp());
 | 
						||
                riga.put(RDOC_UMQTA, row.get(sf.cid2index(F_UM)));
 | 
						||
                riga.put(RDOC_DATACONS, datacons);
 | 
						||
								TString descr(line.description());
 | 
						||
 | 
						||
								if (descr.blank())
 | 
						||
									 descr = cache().get(LF_ANAMAG, line.articolo(), ANAMAG_DESCR);
 | 
						||
								riga.put(RDOC_DESCR, descr);
 | 
						||
 | 
						||
								TMSP_constraint *c = find_constraint(line);
 | 
						||
 | 
						||
                if (c != NULL)
 | 
						||
                {
 | 
						||
		              const TRectype* dardoc = NULL;
 | 
						||
 | 
						||
									for (int buck = b; (dardoc == NULL) && (buck < LAST_BUCKET); buck++)
 | 
						||
									{
 | 
						||
										const int refs = c->rigarefs(buck);
 | 
						||
										if (refs > 0)
 | 
						||
										{
 | 
						||
											const TMRP_docref* dr = c->rigaref(buck, 0);
 | 
						||
											dardoc = &dr->get_rdoc();
 | 
						||
										}
 | 
						||
									}
 | 
						||
									if (dardoc == NULL && b > 0)
 | 
						||
									{
 | 
						||
										for (int buck = b - 1; (dardoc == NULL) && (buck >= 0); buck--)
 | 
						||
										{
 | 
						||
											const int refs = c->rigarefs(buck);
 | 
						||
											if (refs > 0)
 | 
						||
											{
 | 
						||
											  const TMRP_docref* dr = c->rigaref(buck, 0);
 | 
						||
											  dardoc = &dr->get_rdoc();
 | 
						||
                      }
 | 
						||
                    }
 | 
						||
									}
 | 
						||
									if (dardoc != NULL)
 | 
						||
									{
 | 
						||
										const int depth = get_int(F_RIFERIMENTO_MSP);
 | 
						||
										riga.set_original_rdoc_key(*dardoc, depth);
 | 
						||
										riga.put(RDOC_QTAGG5, dardoc->get_int(RDOC_QTAGG5));                // Per ora memorizziamo in QTAGG5, scelto a caso
 | 
						||
									}
 | 
						||
									else
 | 
						||
                  {
 | 
						||
										TString msg; msg.format(FR("Riferimento non trovato : riga %d"), r);
 | 
						||
                    xvtil_statbar_set(msg);
 | 
						||
                    beep();
 | 
						||
                  }
 | 
						||
                }
 | 
						||
								else
 | 
						||
                {
 | 
						||
									TString msg; msg.format(FR("Vincolo non trovato : riga %"), r);
 | 
						||
                  xvtil_statbar_set(msg);
 | 
						||
                  beep();
 | 
						||
                }
 | 
						||
 | 
						||
                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_val;
 | 
						||
                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_val;
 | 
						||
          }
 | 
						||
        }
 | 
						||
        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--)
 | 
						||
  {
 | 
						||
    TToken_string& save_opt_row = save_opt.row(saveit);
 | 
						||
	
 | 
						||
		if (*save_opt_row.get(save_opt.cid2index(F_SEL4SAVE)) > ' ')
 | 
						||
    {
 | 
						||
      somefilter++;
 | 
						||
      const TString4 save_numplan (save_opt_row.get(F_NUM_PLAN-FIRST_FIELD));
 | 
						||
      const TString4 save_tipoplan (save_opt_row.get(F_TIPO_PLAN-FIRST_FIELD));
 | 
						||
      const TString4 save_rigaplan (save_opt_row.get(F_RIGA_PLAN-FIRST_FIELD));
 | 
						||
      const bool clifo_is_optional = cache().get("%TIP",save_opt_row.get(F_TIPO_PLAN-FIRST_FIELD)).get_bool("B5");
 | 
						||
      
 | 
						||
      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 (clifo_is_optional || row->get_long(F_CLIENTE-FIRST_FIELD))
 | 
						||
                salva_cella(r, b, doc_rows, save_opt_row);
 | 
						||
              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.get(F_TIPO_PLAN-FIRST_FIELD)).get_bool("B5"))
 | 
						||
                salva_cella(r, b, doc_rows, save_opt_row);
 | 
						||
              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;
 | 
						||
  TString4 tmp;
 | 
						||
  do 
 | 
						||
  {
 | 
						||
    {
 | 
						||
      tmp = sf.row(nriga).get(sf.cid2index(F_NUM_PLAN));
 | 
						||
      if (tmp.blank())
 | 
						||
        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 != art_row)
 | 
						||
          {
 | 
						||
            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:
 | 
						||
	case F_BUCKET15:
 | 
						||
  case F_BUCKET16:
 | 
						||
  case F_BUCKET17:
 | 
						||
  case F_BUCKET18:
 | 
						||
  case F_BUCKET19:
 | 
						||
  case F_BUCKET20:
 | 
						||
  case F_BUCKET21:
 | 
						||
  case F_BUCKET22:
 | 
						||
  case F_BUCKET23:
 | 
						||
  case F_BUCKET24:
 | 
						||
	case F_BUCKET25:
 | 
						||
  case F_BUCKET26:
 | 
						||
  case F_BUCKET27:
 | 
						||
  case F_BUCKET28:
 | 
						||
  case F_BUCKET29:
 | 
						||
  case F_BUCKET30:
 | 
						||
    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());
 | 
						||
			if (qta != ZERO)
 | 
						||
				highlight(s.selected(), o.dlg(), true, false);
 | 
						||
    }
 | 
						||
    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);
 | 
						||
        const 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();
 | 
						||
        }
 | 
						||
        // Controlla se e' stato richiesto il salvataggio automatico e se posso salvare
 | 
						||
        if (main_app().argc() >= 2 && field(DLG_SAVEREC).active()) 
 | 
						||
        {
 | 
						||
          TString param = main_app().argv(2);
 | 
						||
          param.upper();
 | 
						||
          if (param.find("AUTOR") > 0)           // Lancia salvataggio batch
 | 
						||
            send_key(K_CTRL+'R', 0);
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
    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;
 | 
						||
  case F_SHRINK_ALL:
 | 
						||
  case F_ZOOM_ALL:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      TSheet_field& s = sfield(F_ARTICOLI);
 | 
						||
      const int size = o.dlg() == F_SHRINK_ALL ? 1 : -1;
 | 
						||
      int first_master = -1;
 | 
						||
      FOR_EACH_SHEET_ROW(s, i, row)
 | 
						||
      {
 | 
						||
        const bool is_child = s.cell_disabled(i, 18);
 | 
						||
        if (is_child) 
 | 
						||
          s.set_row_height(i, size);
 | 
						||
        else
 | 
						||
        {
 | 
						||
          if (first_master < 0)
 | 
						||
            first_master = i;
 | 
						||
        }
 | 
						||
      }
 | 
						||
      if (size == 1 && first_master > 0)
 | 
						||
        s.select(first_master, true); 
 | 
						||
      else
 | 
						||
        s.select(0, true); 
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_SHRINK_ROW:
 | 
						||
  case F_ZOOM_ROW:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      TSheet_field& s = sfield(F_ARTICOLI);
 | 
						||
      const int r = s.selected();
 | 
						||
      if (r > 0 && r < s.items())
 | 
						||
      {
 | 
						||
        const int size = o.dlg() == F_SHRINK_ROW ? 1 : -1;
 | 
						||
        int i = r-1;
 | 
						||
        for (; i >= 0; i--)
 | 
						||
        {
 | 
						||
          const bool is_child = s.cell_disabled(i, 18);
 | 
						||
          if (is_child)
 | 
						||
            s.set_row_height(i, size);
 | 
						||
          else
 | 
						||
            break;
 | 
						||
        }
 | 
						||
        s.select(size < 0 ? i+1 : r, true);
 | 
						||
      }
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_PRIORITY_ST:
 | 
						||
    if (e == fe_button && 
 | 
						||
        yesno_box(TR("Si desidera rinumerare automaticamente le priorita'?")))
 | 
						||
    {
 | 
						||
			TSheet_field& s = sfield(F_ARTICOLI);
 | 
						||
      const int pri_pos = s.cid2index(F_PRIORITA);
 | 
						||
			int priority = 0;
 | 
						||
			for(int i = s.items()-1; i >= 0; i--)
 | 
						||
			{
 | 
						||
				priority += 2;
 | 
						||
        int nf = -1, nl = -1;
 | 
						||
        const bool nextok = TRiga_articolo::find_block(s, i, nf, nl);
 | 
						||
				nf--;
 | 
						||
				if (nextok && nf >= 0 && nl >= 0)
 | 
						||
        {
 | 
						||
					for (int j = nf ; j <= i; j++)
 | 
						||
	          s.row(j).add(priority, pri_pos);
 | 
						||
        }
 | 
						||
				i = nf;
 | 
						||
			}
 | 
						||
      s.force_update();
 | 
						||
		}
 | 
						||
		break;
 | 
						||
  case F_PRIORITY_HI:
 | 
						||
  case F_PRIORITY_LO:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      TSheet_field& s = sfield(F_ARTICOLI);
 | 
						||
      const int curr = s.selected();
 | 
						||
      int cf = -1, cl = -1; 
 | 
						||
      const bool currok = TRiga_articolo::find_block(s, curr, cf, cl);
 | 
						||
      cf--;
 | 
						||
      if (currok)
 | 
						||
      {
 | 
						||
        const int next = o.dlg() == F_PRIORITY_LO ? cl+1 : cf-1;
 | 
						||
        int nf = -1, nl = -1;
 | 
						||
        const bool nextok = TRiga_articolo::find_block(s, next, nf, nl);
 | 
						||
        nf--;
 | 
						||
        if (nextok && cf != nf) // Scambio possibile solo su due gruppi distinti
 | 
						||
        {
 | 
						||
          if (get_int(F_MSP_SORT) == 7) // Sort by line/priority/ecc..
 | 
						||
          {
 | 
						||
            const int lin_pos = s.cid2index(F_SORTCODLIN);
 | 
						||
            TString8 old_lin; s.row(cf).get(lin_pos, old_lin);
 | 
						||
            TString8 new_lin; s.row(nf).get(lin_pos, new_lin);
 | 
						||
            if (old_lin != new_lin)
 | 
						||
              return warning_box(TR("Non e' possibile scambiare prodotti su linee diverse"));
 | 
						||
          }
 | 
						||
 | 
						||
          const int pri_pos = s.cid2index(F_PRIORITA);
 | 
						||
          const long old_pri = s.row(cl).get_long(pri_pos);
 | 
						||
          const long new_pri = s.row(nl).get_long(pri_pos);
 | 
						||
          
 | 
						||
          TArray& a = s.rows_array();
 | 
						||
          TPointer_array old_rows, new_rows;
 | 
						||
          int i;
 | 
						||
          for (i = cf; i <= cl; i++)
 | 
						||
          {
 | 
						||
            s.row(i).add(new_pri, pri_pos);
 | 
						||
            old_rows.add(a.remove(i));
 | 
						||
          }
 | 
						||
          for (i = nf; i <= nl; i++)
 | 
						||
          {
 | 
						||
            s.row(i).add(old_pri, pri_pos);
 | 
						||
            new_rows.add(a.remove(i));
 | 
						||
          }        
 | 
						||
          for (i = cf; i <= cl; i++)
 | 
						||
          {
 | 
						||
            const int j = i-cf;
 | 
						||
            a.add(old_rows.remove(j), nf+j);
 | 
						||
            s.force_update(nf+j);
 | 
						||
          }
 | 
						||
          for (i = nf; i <= nl; i++)
 | 
						||
          {
 | 
						||
            const int j = i-nf;
 | 
						||
            a.add(new_rows.remove(j), cf+j);
 | 
						||
            s.force_update(cf+j);
 | 
						||
          }
 | 
						||
          set_focus_field(F_ARTICOLI); // SOLO cosi' la riga riprende il focus ...
 | 
						||
          s.select(nl, 0);                // ... "forzato" da questa chiamata
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
    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();
 | 
						||
}
 | 
						||
 | 
						||
static bool handle_subcodice(TMask_field &fld, KEY k)
 | 
						||
{
 | 
						||
  TMask &mask=fld.mask();
 | 
						||
  if (k == K_TAB && (fld.focusdirty()||!mask.is_running())) //c'e' qualcosa nel campo
 | 
						||
  { 
 | 
						||
    //quale e' l'ultimo campo valido per codart in multilevel?
 | 
						||
    short id_last = fld.dlg();
 | 
						||
    while (id_last <= F_LIVART9 && mask.id2pos(id_last+1) > 0)
 | 
						||
      id_last++;
 | 
						||
    
 | 
						||
    if (fld.empty())
 | 
						||
    {
 | 
						||
      //gira su tutti i campi di livart esistenti e successivi al livello corrente
 | 
						||
      for(short id = fld.dlg()+1; id <= id_last; id++)
 | 
						||
      {
 | 
						||
        mask.set(id, "");
 | 
						||
        mask.disable(id);
 | 
						||
      }
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      const int pos = mask.id2pos(fld.dlg()+1);
 | 
						||
      if (pos > 0)
 | 
						||
      {
 | 
						||
        TMask_field& next_fld = mask.fld(pos);
 | 
						||
        next_fld.enable();
 | 
						||
      }
 | 
						||
    }
 | 
						||
//riempie in automatico il campo codice complessivo
 | 
						||
    TString80 stringone;
 | 
						||
    bool completo = true;
 | 
						||
    for(short id = F_LIVART1; id <= id_last; id++)
 | 
						||
    {
 | 
						||
      const TString& val = mask.get(id);
 | 
						||
      if (val.blank())
 | 
						||
      {
 | 
						||
        completo = false;
 | 
						||
        break;
 | 
						||
      }
 | 
						||
      stringone << val;
 | 
						||
    }
 | 
						||
    
 | 
						||
    mask.set(F_CODART, stringone, fld.dlg()==id_last ? 0x3 : 0x0);
 | 
						||
  }
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
static bool handle_codice(TMask_field &fld, KEY k)
 | 
						||
{
 | 
						||
  if (k == K_TAB && fld.focusdirty() && !fld.empty())
 | 
						||
  {
 | 
						||
    TSheet_field& sheet = fld.mask().sfield(F_ARTICOLI);
 | 
						||
    bool found = false;
 | 
						||
    FOR_EACH_SHEET_ROW(sheet, i, row)
 | 
						||
    {
 | 
						||
      if (fld.get() == row->get(2))
 | 
						||
      {
 | 
						||
        sheet.select(i);
 | 
						||
        found = true;
 | 
						||
        break;
 | 
						||
      }
 | 
						||
    }
 | 
						||
    if (!found)
 | 
						||
      fld.error_box(TR("Articolo non pianificato"));
 | 
						||
 | 
						||
  }
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
static bool handle_interval(TMask_field &fld, KEY k)
 | 
						||
{
 | 
						||
  if (fld.to_check(k, true))
 | 
						||
  {
 | 
						||
		TPlanning_mask & m = ((TPlanning_mask &)fld.mask());
 | 
						||
		const TDate & from = m.get_date(F_DADATA);
 | 
						||
		TDate to(m.get_date(F_DADATA));
 | 
						||
		int days = m.days_per_bucket();
 | 
						||
 | 
						||
		if (days < 7)
 | 
						||
			days = 7;
 | 
						||
		to += days;
 | 
						||
 | 
						||
		m.calendar().set_highlight_interval(from, to);
 | 
						||
  }
 | 
						||
  return true;
 | 
						||
}
 | 
						||
 | 
						||
void TPlanning_mask::create_browse1(TEdit_field& kfld, int level, short key_id, short des_id, const TCodart_livelli &cal)
 | 
						||
{
 | 
						||
  TFilename tmp; tmp.temp();
 | 
						||
  ofstream out(tmp);
 | 
						||
 | 
						||
  out << "USE GCA" << endl; //usa la tabella dei livelli articolo
 | 
						||
 | 
						||
  const short id = key_id + level - 1;
 | 
						||
  const TString& prompt = cal.name(level);
 | 
						||
  const TString& picture = cal.picture(level);
 | 
						||
  out << "IN CODTAB[1,1] \"" << level << "\"" << endl;
 | 
						||
  out << "IN CODTAB[2,0] " << id << endl;
 | 
						||
  out << "DI \"" << prompt;
 | 
						||
  const int length = cal.code_length(level);
 | 
						||
  if (length > prompt.len())
 | 
						||
    out << '@' << length;
 | 
						||
  out << "\" CODTAB[2,0]" << endl;
 | 
						||
  out << "DI \"" << TR("Descrizione") << "@50\" S0" << endl; 
 | 
						||
  out << "OU " << id << " CODTAB[2,0]" << endl;
 | 
						||
  out << "OU " << (des_id + level -1) << " S0" << endl;
 | 
						||
 | 
						||
  out << "EN" << endl;
 | 
						||
  out.close();
 | 
						||
 | 
						||
  TScanner scan(tmp);
 | 
						||
  while (scan.pop() != "EN")
 | 
						||
    kfld.parse_item(scan);
 | 
						||
 | 
						||
  xvt_fsys_removefile(tmp);
 | 
						||
}
 | 
						||
 | 
						||
void TPlanning_mask::create_browse2(TEdit_field& kfld, int level, short key_id, short des_id, const TCodart_livelli &cal)
 | 
						||
{
 | 
						||
  TFilename tmp; tmp.temp();
 | 
						||
  ofstream out(tmp);
 | 
						||
 | 
						||
  out << "USE GCA KE 2 SELECT CODTAB[1,1]=='" << level << "'" << endl;  //cerca per descrizione
 | 
						||
 | 
						||
  const short id = des_id + level - 1;
 | 
						||
  out << "IN S0 " << id << endl;
 | 
						||
  out << "DI \"" << TR("Descrizione") << "@50\" S0" << endl;
 | 
						||
  
 | 
						||
  const TString& prompt = cal.name(level);
 | 
						||
  out << "DI \"" << prompt;
 | 
						||
  const int length = cal.code_length(level);
 | 
						||
  if (length > prompt.len())
 | 
						||
    out << '@' << length;
 | 
						||
  out << "\" CODTAB[2,0]" << endl;
 | 
						||
 | 
						||
  out << "CO OU " << (key_id + level -1) << endl;
 | 
						||
  out << "EN" << endl;
 | 
						||
  out.close();
 | 
						||
 | 
						||
  TScanner scan(tmp);
 | 
						||
  while (scan.pop() != "EN")
 | 
						||
    kfld.parse_item(scan);
 | 
						||
 | 
						||
  xvt_fsys_removefile(tmp);
 | 
						||
}
 | 
						||
 | 
						||
int TPlanning_mask::create_codart_fields(int x, int y, short key_id, short des_id)
 | 
						||
{
 | 
						||
  const TCodart_livelli cal;
 | 
						||
  const int last_level = cal.last_level();
 | 
						||
  int tab0 = x;
 | 
						||
  int i;
 | 
						||
  for (i = 1; i <= last_level; i++) //cicla su tutti i livelli del codart abilitati
 | 
						||
  {
 | 
						||
    // codice livello articolo
 | 
						||
    const short kid = key_id+i-1;
 | 
						||
    const TString& picture = cal.picture(i); 
 | 
						||
    
 | 
						||
    TString4 flags = "BU";
 | 
						||
    if (picture[0] == '0')
 | 
						||
      flags << 'Z';
 | 
						||
 | 
						||
    TEdit_field& kfld = add_string(kid, 3, "", tab0, y, picture.len(), flags);
 | 
						||
    kfld.set_key(1);
 | 
						||
    create_browse1(kfld, i, key_id, des_id, cal);
 | 
						||
 | 
						||
    kfld.set_handler(handle_subcodice);
 | 
						||
    tab0 += picture.len()+3;
 | 
						||
  }
 | 
						||
  for (i = 1; i <= last_level; i++)
 | 
						||
  {
 | 
						||
    // descrizione livello articolo
 | 
						||
    const short did = des_id+i-1;
 | 
						||
    TEdit_field& dfld = add_string(did, 3, "", 200, y, 50, "", 50);
 | 
						||
    dfld.set_key(1);
 | 
						||
    create_browse2(dfld, i, key_id, des_id, cal);
 | 
						||
  }
 | 
						||
  
 | 
						||
  return cal.last_level();
 | 
						||
}
 | 
						||
 | 
						||
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);
 | 
						||
  
 | 
						||
  create_codart_fields(10, 4, F_LIVART1, F_DESART1);
 | 
						||
  set_handler(F_CODART, handle_codice);
 | 
						||
  set_handler(F_DADATA, handle_interval);
 | 
						||
  set_handler(F_BUCKETS, handle_interval);
 | 
						||
 | 
						||
 | 
						||
  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);
 | 
						||
  _con_pos =_sel_color.add_color_def("CONST", TR("Vincoli speciali"), blend_colors(COLOR_WHITE, COLOR_YELLOW, 0.60), COLOR_BLACK);
 | 
						||
	
 | 
						||
	TCalendar_field & cf = (TCalendar_field &) field(F_CALENDAR);
 | 
						||
 | 
						||
	cf.set_immediate_write();
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
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_id(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;
 | 
						||
	TString80 da_rdoc_key;
 | 
						||
 | 
						||
  _main_mask->msprow2codes(row, codcli, codart, liv, mag, magc, codimp, codlin, um, da_rdoc_key);
 | 
						||
  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, da_rdoc_key);
 | 
						||
    TMSP_line* old_article = _main_mask->find_article(codcli, codart, liv, codimp, codlin, mag, magc, da_rdoc_key);
 | 
						||
 | 
						||
    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;
 | 
						||
    default: 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;
 | 
						||
  default:
 | 
						||
    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::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
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
bool TPlanning_app::menu(MENU_TAG mt)
 | 
						||
{             
 | 
						||
  bool ok = TRUE;
 | 
						||
  if (mt == MENU_ITEM_ID(1))
 | 
						||
  {
 | 
						||
		TSelect_color_mask & s = _m->sel();
 | 
						||
    s.run();
 | 
						||
  }
 | 
						||
  else
 | 
						||
    ok = TSkeleton_application::menu(mt);
 | 
						||
  return ok;  
 | 
						||
}
 | 
						||
 | 
						||
void TPlanning_app ::openfiles()
 | 
						||
{
 | 
						||
  open_files(LF_TABCOM, LF_TAB, LF_DOC, LF_RIGHEDOC, LF_CLIFO, LF_CFVEN, LF_OCCAS, LF_INDSP, LF_CONDV, 
 | 
						||
             LF_MAG, LF_MOVMAG, LF_RMOVMAG, 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);
 | 
						||
  }
 | 
						||
 | 
						||
  if (argc() > 1)                     // Controllo automatismi
 | 
						||
  {
 | 
						||
    TString param = argv(2);
 | 
						||
    param.upper();
 | 
						||
    if (param.find("AUTO") > 0)
 | 
						||
      mask().send_key(K_CTRL+'L', 0); // Lancia elaborazione batch
 | 
						||
  }
 | 
						||
 | 
						||
  while (mask().run()!=K_QUIT) ;
 | 
						||
}
 | 
						||
 | 
						||
int mr2200(int argc, char* argv[])
 | 
						||
{
 | 
						||
  TPlanning_app a;
 | 
						||
  a.run(argc, argv, TR("Pianificazione ordini"));
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
 |