Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione AGA 1.7 patch 349 git-svn-id: svn://10.65.10.50/trunk@10708 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1040 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1040 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
// Applicazione di generazione reports & stampe per MRP
 | 
						|
#include <applicat.h>
 | 
						|
#include <form.h>
 | 
						|
#include <relation.h>
 | 
						|
#include <printer.h>
 | 
						|
#include <progind.h>
 | 
						|
 | 
						|
#include "mrplib.h"
 | 
						|
#include "../ve/velib.h"
 | 
						|
#include "../mg/mglib.h"
 | 
						|
 | 
						|
#include "mr1.h"
 | 
						|
#include "mr1100a.h"
 | 
						|
#include <defmask.h>
 | 
						|
 | 
						|
#include <doc.h>
 | 
						|
#include <rdoc.h>
 | 
						|
 | 
						|
#define LF_MRPREP    132
 | 
						|
 | 
						|
#define LAST_BUCKET 12
 | 
						|
 | 
						|
// Tipi di stampa 
 | 
						|
enum tipo_stampa {
 | 
						|
  articoli,   // produzione articoli nel tempo
 | 
						|
  linee,      // carico linee
 | 
						|
  scheduling, // scheduling delle linee
 | 
						|
  available   // Tipo di stampa non definita: ordinata per articoli e stampa del carico della linea
 | 
						|
};
 | 
						|
 | 
						|
// I tipi di stampa si identificano secondo la seguente tabella, tramite l'intersezione
 | 
						|
// tra l'ordinamento ed il valore impostati:
 | 
						|
/*
 | 
						|
     
 | 
						|
                   |----------------------+
 | 
						|
                   |quantita   | carico   |
 | 
						|
        -----------+-----------------------
 | 
						|
        articoli   |articoli   | available|
 | 
						|
        -----------+----------------------+
 | 
						|
        linea      |scheduling | linee    |
 | 
						|
        -----------+-----------------------
 | 
						|
          
 | 
						|
 */
 | 
						|
enum tipo_ordinamento {
 | 
						|
  articolo,
 | 
						|
  linea
 | 
						|
};
 | 
						|
 | 
						|
enum tipo_valore {
 | 
						|
  quantita,
 | 
						|
  carico
 | 
						|
};
 | 
						|
 | 
						|
enum tipo_dettaglio {
 | 
						|
  det_articolo,
 | 
						|
  det_giacenza,
 | 
						|
  det_impianto,
 | 
						|
  det_linea
 | 
						|
};
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// _TCapacitaLinea, usato per calcolare le capacita' delle linee
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class _TCapacitaLinea : public TObject
 | 
						|
{ 
 | 
						|
  TArray _cap_min, // Array 1..LAST_BUCKET-1 di capacita' minime
 | 
						|
         _cap_max; // Array 1..LAST_BUCKET-1 di capacita' massime
 | 
						|
  
 | 
						|
public:
 | 
						|
  TArray& cap_min() { return _cap_min; }
 | 
						|
  TArray& cap_max() { return _cap_max; }
 | 
						|
  _TCapacitaLinea() ;
 | 
						|
  virtual ~_TCapacitaLinea() {}
 | 
						|
};
 | 
						|
 | 
						|
_TCapacitaLinea::_TCapacitaLinea()
 | 
						|
{
 | 
						|
  for (int i = 0; i<LAST_BUCKET-1; i++)
 | 
						|
  {
 | 
						|
    _cap_min.add(new real);
 | 
						|
    _cap_max.add(new real);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TMRP_rep_record
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TMRP_rep_record : public TObject
 | 
						|
{
 | 
						|
public:
 | 
						|
  real _qta;
 | 
						|
  
 | 
						|
  TMRP_rep_record() { }
 | 
						|
};
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TMRP_rep_record_array;
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TMRP_rep_record_array : public TObject
 | 
						|
{
 | 
						|
  TArray _buckets;
 | 
						|
 | 
						|
public:
 | 
						|
  int items() const { return _buckets.items(); }
 | 
						|
  int last() const { return _buckets.last(); }
 | 
						|
  int pred(int i) const { return _buckets.pred(i); }
 | 
						|
 | 
						|
  TMRP_rep_record& operator[](int b);
 | 
						|
};
 | 
						|
 | 
						|
TMRP_rep_record& TMRP_rep_record_array::operator[](int b)
 | 
						|
{
 | 
						|
  CHECKD(b >= 0, "Invalid TMRP_rep_record_array ", b);
 | 
						|
  TMRP_rep_record* qta = (TMRP_rep_record*)_buckets.objptr(b);
 | 
						|
  if (qta == NULL)
 | 
						|
  {
 | 
						|
    qta = new TMRP_rep_record;
 | 
						|
    _buckets.add(qta, b);
 | 
						|
  }
 | 
						|
  return *qta;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TMRP_rep_line
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TMRP_rep_line : public TSortable
 | 
						|
{
 | 
						|
  TCodice_articolo _codart;
 | 
						|
  TString16 _giac, _imp, _lin, _um;
 | 
						|
 | 
						|
  TMRP_rep_record_array _bucket;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual int compare(const TSortable& s) const;
 | 
						|
 | 
						|
public:
 | 
						|
  const TCodice_articolo& codice() const { return _codart; }
 | 
						|
  const TString& livgiac() const { return _giac; }
 | 
						|
  const TString& codimp() const { return _imp; }
 | 
						|
  const TString& codlin() const { return _lin; }
 | 
						|
  const TString& um() const { return _um; }
 | 
						|
 | 
						|
  int last() const { return _bucket.last(); }
 | 
						|
  int pred(int i) const { return _bucket.pred(i); }
 | 
						|
 | 
						|
  real& qta(int b) { return _bucket[b]._qta; }
 | 
						|
  
 | 
						|
  void fill(TRectype& record, TAssoc_array* capacita = NULL);
 | 
						|
 | 
						|
  TMRP_rep_line(const TCodice_articolo& codart, 
 | 
						|
                const TString& giac, const TString& imp,
 | 
						|
                const TString& lin, const TString& um);
 | 
						|
  virtual ~TMRP_rep_line() { }
 | 
						|
};
 | 
						|
 | 
						|
void TMRP_rep_line::fill(TRectype& record, TAssoc_array* capacita)
 | 
						|
{
 | 
						|
  record.zero();
 | 
						|
  record.put("TIPO", "R");
 | 
						|
  record.put("CODART", _codart);
 | 
						|
  record.put("LIVELLO", _giac);
 | 
						|
  record.put("IMPIANTO", _imp);
 | 
						|
  record.put("LINEA", _lin);
 | 
						|
  record.put("UM", _um);
 | 
						|
  TString16 campo;
 | 
						|
  for (int b = last(); b >= 0; b = pred(b))
 | 
						|
  {
 | 
						|
    switch(b)
 | 
						|
    {
 | 
						|
    case 0: 
 | 
						|
      campo = "QTAFIRST"; break;
 | 
						|
    case LAST_BUCKET:
 | 
						|
      campo = "QTALAST"; break;
 | 
						|
    default:
 | 
						|
      campo.format("QTA%d", b); break;
 | 
						|
    }
 | 
						|
    record.put(campo, qta(b));
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (capacita)
 | 
						|
    for (b=1; b<LAST_BUCKET; b++)
 | 
						|
    {
 | 
						|
      _TCapacitaLinea* cl = (_TCapacitaLinea*)capacita->objptr(_lin);
 | 
						|
      if (cl)
 | 
						|
      { 
 | 
						|
        TArray& cmin = cl->cap_min();
 | 
						|
        TArray& cmax = cl->cap_max();
 | 
						|
        campo.format("CMIN%d", b);
 | 
						|
        record.put(campo, (real&)cmin[b-1]); // Capacita' minima...
 | 
						|
        campo.format("CMAX%d", b);
 | 
						|
        record.put(campo, (real&)cmax[b-1]); // e massima
 | 
						|
      }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int TMRP_rep_line::compare(const TSortable& s) const
 | 
						|
{
 | 
						|
  const TMRP_rep_line& c = (const TMRP_rep_line&)s;
 | 
						|
  int cmp = _codart.compare(c._codart);
 | 
						|
  if (cmp == 0)
 | 
						|
  {
 | 
						|
    cmp = _giac.compare(c._giac);
 | 
						|
    if (cmp == 0)
 | 
						|
    {
 | 
						|
      cmp = _imp.compare(c._imp);
 | 
						|
      if (cmp == 0)
 | 
						|
      {
 | 
						|
        cmp = _lin.compare(c._lin);
 | 
						|
        if (cmp == 0)
 | 
						|
          cmp = _um.compare(c._um);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return cmp;
 | 
						|
}
 | 
						|
 | 
						|
TMRP_rep_line::TMRP_rep_line(const TCodice_articolo& codart, 
 | 
						|
                             const TString& giac, 
 | 
						|
                             const TString& imp, const TString& lin,
 | 
						|
                             const TString& um)
 | 
						|
: _codart(codart), _giac(giac), _imp(imp), _lin(lin), _um(um)
 | 
						|
{ }
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TMRP_rep_lines
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TMRP_rep_lines : public TMRP_array
 | 
						|
{
 | 
						|
protected:
 | 
						|
  virtual TSortable* new_obj(const TToken_string& key) const;
 | 
						|
 | 
						|
public:
 | 
						|
  TMRP_rep_line* find(const TCodice_articolo& codart, 
 | 
						|
                      const TString& giac, const TString& imp, 
 | 
						|
                      const TString& lin, const TString& um,
 | 
						|
                      bool create);
 | 
						|
  TMRP_rep_line& operator[](long n) const
 | 
						|
  { return (TMRP_rep_line&)find_obj(n); }
 | 
						|
};
 | 
						|
 | 
						|
TSortable* TMRP_rep_lines::new_obj(const TToken_string& key) const
 | 
						|
{
 | 
						|
  TCodice_articolo art; key.get(0, art);
 | 
						|
  TString          gia; key.get(1, gia);
 | 
						|
  TString          imp; key.get(2, imp);
 | 
						|
  TString          lin; key.get(3, lin);
 | 
						|
  TString          um ; key.get(4, um);
 | 
						|
  return new TMRP_rep_line(art, gia, imp, lin, um);
 | 
						|
}
 | 
						|
 | 
						|
TMRP_rep_line* TMRP_rep_lines::find(const TCodice_articolo& codart,
 | 
						|
                                    const TString& giac,
 | 
						|
                                    const TString& imp,
 | 
						|
                                    const TString& lin,
 | 
						|
                                    const TString& um,
 | 
						|
                                    bool create)
 | 
						|
{
 | 
						|
  _key = codart;
 | 
						|
  _key.add(giac);
 | 
						|
  _key.add(imp);
 | 
						|
  _key.add(lin);
 | 
						|
  _key.add(um);
 | 
						|
  TSortable* s = create ? add_obj(_key) : find_obj(_key);
 | 
						|
  return (TMRP_rep_line*)s;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// MRP report generator mask
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TRepgen_mask : public TCalendar_mask
 | 
						|
{
 | 
						|
protected:
 | 
						|
  void calcola_capacita(TAssoc_array&) const ;
 | 
						|
  bool test_tipodoc_num( const TSheet_field &sheet_num , const TSheet_field &sheet_type) ;
 | 
						|
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | 
						|
 | 
						|
  void round_field(TMask_field& fld, bool up) const;
 | 
						|
 | 
						|
public:
 | 
						|
  int round_date(TDate& date, bool up) const;
 | 
						|
  bool elabora() const;
 | 
						|
  TRepgen_mask();
 | 
						|
  virtual ~TRepgen_mask() { }
 | 
						|
};
 | 
						|
 | 
						|
bool TRepgen_mask::test_tipodoc_num(const  TSheet_field &sheet_num ,const  TSheet_field &sheet_type) 
 | 
						|
{
 | 
						|
  TString16 tipo;
 | 
						|
  TString_array& nums = sheet_num.rows_array();
 | 
						|
  TString_array& types = sheet_type.rows_array();
 | 
						|
  for (int j = types.items()-1; j >= 0; j--)
 | 
						|
  {
 | 
						|
    bool ok=FALSE;
 | 
						|
    tipo = types.row(j).get(0) ;
 | 
						|
    for (int i = nums.items()-1; i >= 0; i--)
 | 
						|
    {
 | 
						|
      TCodice_numerazione num(nums.row(i).get(0));
 | 
						|
      for (int n = num.ntipi_doc()-1;n >= 0; n--)
 | 
						|
      {
 | 
						|
        const char* t = num.tipo_doc(n);
 | 
						|
        if (tipo == t)
 | 
						|
          ok = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (!ok) 
 | 
						|
      return error_box("Il tipo '%s' non appartiene a nessuna delle numerazioni scelte",(const char*)tipo);
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int TRepgen_mask::round_date(TDate& date, bool up) const
 | 
						|
{
 | 
						|
  // Dimensione del bucket in giorni
 | 
						|
  int bucket_size = get_int(F_BUCKET) * 7;
 | 
						|
  if (bucket_size < 7) bucket_size = 7;
 | 
						|
 | 
						|
  // Riporta la data al primo lunedi prima dell'inizio
 | 
						|
  TDate inizio = get(F_DADATA);
 | 
						|
  const int wday = inizio.wday();
 | 
						|
  if (wday > 1) inizio -= wday-1;
 | 
						|
 | 
						|
  // Calcola il bucket di appartenenza
 | 
						|
  const int days = int(date - inizio);
 | 
						|
  const int bucket = days / bucket_size;
 | 
						|
 | 
						|
  if (up) // Arrotonda alla fine del bucket
 | 
						|
    date = inizio + long((bucket+1) * bucket_size - 1);
 | 
						|
  else    // Arrotonda all'inizio del bucket  
 | 
						|
    date = inizio + long(bucket * bucket_size);
 | 
						|
 | 
						|
  return bucket;
 | 
						|
}
 | 
						|
 | 
						|
void TRepgen_mask::round_field(TMask_field& fld, bool up) const
 | 
						|
{
 | 
						|
  TDate date = fld.get();
 | 
						|
  if (date.ok())
 | 
						|
  {
 | 
						|
    round_date(date, up);
 | 
						|
    fld.set(date);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TRepgen_mask::calcola_capacita(TAssoc_array& capacita) const
 | 
						|
{
 | 
						|
  if (capacita.items() == 0)
 | 
						|
    return;
 | 
						|
 | 
						|
  const bool carico_uomo = get_bool(F_MANLOAD);
 | 
						|
  const TDate df(get_date(F_DADATA));
 | 
						|
  const TDate dt(get_date(F_ADATA));
 | 
						|
  TDate wd1,wd2;
 | 
						|
  TString16 codimp;
 | 
						|
  
 | 
						|
  capacita.restart();
 | 
						|
  TProgind pi(capacita.items(), "Calcolo capacita linee", FALSE, TRUE);
 | 
						|
  THash_object* ho = capacita.get_hashobj();
 | 
						|
  for (;ho != NULL; ho = capacita.get_hashobj())
 | 
						|
  {
 | 
						|
    pi.addstatus(1L);
 | 
						|
    const TString& linea = ho->key();
 | 
						|
    _TCapacitaLinea& cl = (_TCapacitaLinea&) ho->obj();
 | 
						|
    TLinea_prod lp(linea);
 | 
						|
    codimp = lp.codimp();
 | 
						|
    
 | 
						|
    TMRP_calendar& mc = TMRP_time::get_calendar(codimp, linea);
 | 
						|
    TArray& cap_min = cl.cap_min();
 | 
						|
    TArray& cap_max = cl.cap_max();
 | 
						|
    
 | 
						|
    for (wd1 = df; wd1 <= dt; ++wd1) // Piglia tutte le date nel range! (very, very heavy...)
 | 
						|
    {
 | 
						|
      wd2 = wd1;
 | 
						|
      const int bucket = round_date(wd2, FALSE); // da 0 a 10 al massimo
 | 
						|
      if (bucket > 10)
 | 
						|
        break; // Fine
 | 
						|
      real & v1 = (real&) cap_min[bucket];
 | 
						|
      v1 += carico_uomo ? mc.add_oreuomo(v1, wd1)   : mc.add_oremacchina(v1, wd1);
 | 
						|
      real & v2 = (real&) cap_max[bucket];
 | 
						|
      v2 += carico_uomo ? mc.add_oreuomo_max(v2, wd1) : mc.add_oremacchina_max(v2, wd1);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TRepgen_mask::elabora() const
 | 
						|
{
 | 
						|
  TRelation rel(LF_RIGHEDOC);
 | 
						|
  TCursor cur(&rel);
 | 
						|
  const TRectype& riga = cur.curr();
 | 
						|
  TRectype filter_fr(riga), filter_to(riga);
 | 
						|
 | 
						|
  const TDate date_fr = get(F_DADATA);
 | 
						|
  const int year_fr = date_fr.year();
 | 
						|
  TDate date_to = get(F_ADATA);
 | 
						|
  const int year_to = date_to.year();
 | 
						|
  const int bucket_size = get_int(F_BUCKET) * 7;
 | 
						|
  const TExplosion_grouping raggr = (TExplosion_grouping)get_int(F_RAGGRUM);
 | 
						|
  const tipo_valore ts = (tipo_valore) get_int(F_VAL2PRINT);
 | 
						|
  const bool carico_uomo = get_bool(F_MANLOAD);
 | 
						|
  const int last_bucket = round_date(date_to,TRUE)+1;
 | 
						|
  
 | 
						|
  TString16 ws;
 | 
						|
 | 
						|
  TDistinta_tree distinta;
 | 
						|
  TArray  lav_array;
 | 
						|
 | 
						|
  TMRP_rep_lines articles;
 | 
						|
  TAssoc_array capacita;
 | 
						|
  
 | 
						|
  TString msg;
 | 
						|
  TSheet_field& numerazioni = sfield(F_NUMERAZIONI);
 | 
						|
  FOR_EACH_SHEET_ROW(numerazioni, r, row)
 | 
						|
  {
 | 
						|
    const TString16 codnum = row->get(0);
 | 
						|
    // Filtra il cursore in modo da limitarlo alla numerazione
 | 
						|
    // corrente ed agli anni specificati dalle due date limite
 | 
						|
    filter_fr.put(RDOC_PROVV, "D");
 | 
						|
    filter_fr.put(RDOC_CODNUM, codnum);
 | 
						|
    filter_fr.put(RDOC_ANNO, year_fr);
 | 
						|
 | 
						|
    filter_to.put(RDOC_PROVV, "D");
 | 
						|
    filter_to.put(RDOC_CODNUM, codnum);
 | 
						|
    filter_to.put(RDOC_ANNO, year_to);   
 | 
						|
    
 | 
						|
    cur.setregion(filter_fr, filter_to);
 | 
						|
    const long items = cur.items();
 | 
						|
    cur.freeze(TRUE);
 | 
						|
 | 
						|
    msg = "Elaborazione numerazione "; msg << codnum;
 | 
						|
    TProgind pi(items, msg, FALSE, TRUE);
 | 
						|
 | 
						|
    // Scandisce le righe dei documenti
 | 
						|
    for (cur = 0; cur.pos() < items; ++cur)    
 | 
						|
    {        
 | 
						|
      pi.addstatus(1);
 | 
						|
      const TCodice_articolo art = riga.get(RDOC_CODARTMAG);
 | 
						|
      if (art.not_empty())
 | 
						|
      {
 | 
						|
        TDate datacons = riga.get(RDOC_DATACONS);
 | 
						|
        // Seleziona tutte le righe! Altrimenti LAST_BUCKET non viene mai settato 
 | 
						|
        //if (datacons <= date_to)
 | 
						|
        {
 | 
						|
          real qta;
 | 
						|
          if (!riga.get_bool(RDOC_RIGAEVASA))
 | 
						|
          {
 | 
						|
            qta = riga.get_real(RDOC_QTA);
 | 
						|
            qta -= riga.get_real(RDOC_QTAEVASA);
 | 
						|
          }
 | 
						|
          // Seleziona le righe articolo non ancora evase
 | 
						|
          if (qta > ZERO)
 | 
						|
          {
 | 
						|
            const TString16 liv = riga.get(RDOC_LIVELLO); 
 | 
						|
            const TString16 imp = riga.get(RDOC_IMPIANTO); 
 | 
						|
            const TString16 lin = riga.get(RDOC_LINEA); 
 | 
						|
            const TCodice_um um = riga.get(RDOC_UMQTA);
 | 
						|
            
 | 
						|
            TQuantita q(art, um, qta);
 | 
						|
            int bucket = 0;
 | 
						|
 | 
						|
            if (datacons >= date_fr) 
 | 
						|
            {
 | 
						|
              bucket = round_date(datacons, FALSE) + 1;
 | 
						|
              if (bucket > last_bucket)
 | 
						|
                bucket = LAST_BUCKET;
 | 
						|
            }
 | 
						|
 | 
						|
            // Calcoli per carico
 | 
						|
            if (ts == carico)
 | 
						|
            {
 | 
						|
              distinta.set_root(riga);
 | 
						|
              real ore,tot;
 | 
						|
              
 | 
						|
              TRiga_esplosione * llav = distinta.first_labor(lav_array, raggr);
 | 
						|
              TLavorazione * lavorazione = TDistinta_tree::find_labor(llav);
 | 
						|
              
 | 
						|
              while (llav)
 | 
						|
              {
 | 
						|
                const int linea = lavorazione->find_linea(lin);
 | 
						|
                
 | 
						|
                const real prod_linea = lavorazione->produttiv_linea(linea);
 | 
						|
                ore = (llav->val() * lavorazione->um_temporale().converti_in_ore()) / prod_linea;
 | 
						|
                if (carico_uomo)
 | 
						|
                  ore *= lavorazione->numpers_linea(linea);
 | 
						|
                
 | 
						|
                //rep.qta(bucket) += ore;
 | 
						|
                tot += ore;
 | 
						|
                llav = distinta.next_labor(lav_array);
 | 
						|
              }
 | 
						|
              
 | 
						|
              if (tot > ZERO)
 | 
						|
              {
 | 
						|
                TMRP_rep_line& rep = *articles.find(art, liv, imp, lin, ws, TRUE);
 | 
						|
                rep.qta(bucket) += tot;
 | 
						|
              }
 | 
						|
              
 | 
						|
              
 | 
						|
              // Sbatte nella cache le linee di cui dopo calcolera' le capacita' minime e massime
 | 
						|
              // In modo che il calcolo venga effettuato una volta sola per ogni linea.
 | 
						|
              if (capacita.objptr(lin) == NULL)
 | 
						|
                capacita.add(lin, new _TCapacitaLinea); // Vuoto per ora... lo riempie poco piu' giu'
 | 
						|
            }
 | 
						|
            else // Produzione articoli nel tempo & scheduling linee
 | 
						|
            {
 | 
						|
              TMRP_rep_line& rep = *articles.find(art, liv, imp, lin, q.um(), TRUE);
 | 
						|
              switch (raggr)
 | 
						|
              {
 | 
						|
               case RAGGR_EXP_UMBASE:
 | 
						|
                  q.convert2umbase();
 | 
						|
                  break;
 | 
						|
               case RAGGR_EXP_UMDIST:
 | 
						|
                  q.convert2umdist();
 | 
						|
                  break;
 | 
						|
               default: break;   
 | 
						|
              }
 | 
						|
              rep.qta(bucket) += q.val();
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    cur.freeze(FALSE);
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (ts == carico && get_bool(F_CAPACITA))
 | 
						|
    calcola_capacita(capacita);
 | 
						|
 | 
						|
  const long total = articles.items();
 | 
						|
  TProgind pi(total, "Generazione file", FALSE, TRUE);
 | 
						|
 | 
						|
  TMask_field& fld = field(F_FILENAME);
 | 
						|
  TFilename filename = fld.get();
 | 
						|
 | 
						|
  if (filename.empty())
 | 
						|
    filename.temp("mrprep");
 | 
						|
 | 
						|
  fld.set(filename);
 | 
						|
 | 
						|
  filename.insert("%");
 | 
						|
 | 
						|
  TIsamtempfile rep(LF_MRPREP, filename);
 | 
						|
  
 | 
						|
  // Scrive la testata (Record tipo "H");
 | 
						|
  rep.put("TIPO","H");
 | 
						|
  rep.put("CODART", date_fr.string());
 | 
						|
  rep.put("LIVELLO", get(F_ADATA));
 | 
						|
  rep.put("IMPIANTO", bucket_size);
 | 
						|
  rep.put("LINEA", ts == quantita  ? "Q" : "C");
 | 
						|
  rep.write();
 | 
						|
  
 | 
						|
  for (long i = 0; i < total; i++)
 | 
						|
  {
 | 
						|
    pi.addstatus(1);
 | 
						|
    articles[i].fill(rep.curr(), ts == carico ? &capacita : NULL);
 | 
						|
    int err = rep.write();
 | 
						|
    if (err != NOERR)
 | 
						|
      rep.rewrite();
 | 
						|
  }
 | 
						|
  return rep.good();
 | 
						|
}
 | 
						|
 | 
						|
bool TRepgen_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | 
						|
{
 | 
						|
  switch(o.dlg())
 | 
						|
  {
 | 
						|
  case F_DADATA:
 | 
						|
    if (e == fe_modify)
 | 
						|
      round_field(o, FALSE);
 | 
						|
    break;
 | 
						|
  case F_ADATA:
 | 
						|
    if (e == fe_modify)
 | 
						|
      round_field(o, TRUE);
 | 
						|
    break;
 | 
						|
  case F_BUCKET:
 | 
						|
    if (e == fe_modify)
 | 
						|
    {
 | 
						|
      round_field(field(F_DADATA), FALSE);
 | 
						|
      round_field(field(F_ADATA), TRUE);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case F_NUMERAZIONI:
 | 
						|
    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()) return TRUE;
 | 
						|
      return error_box("E' necessario inserire almeno una numerazione");
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case F_TIPI:
 | 
						|
    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()) 
 | 
						|
        {
 | 
						|
          const bool ok=test_tipodoc_num(sfield(F_NUMERAZIONI), s );
 | 
						|
          return ok;
 | 
						|
        }
 | 
						|
      return error_box("E' necessario inserire almeno una riga");
 | 
						|
    }
 | 
						|
    break;                      
 | 
						|
  case F_YEAR:
 | 
						|
  case F_IMPIANTO:
 | 
						|
  case F_LINEA:
 | 
						|
    if (e == fe_modify)
 | 
						|
      update_calendar(F_CALENDAR, F_YEAR, F_IMPIANTO, F_LINEA);
 | 
						|
    break;
 | 
						|
  case DLG_PRINT:
 | 
						|
  case DLG_ELABORA:
 | 
						|
    if (e == fe_button)
 | 
						|
    {
 | 
						|
      if (check_fields())
 | 
						|
        save_profile();
 | 
						|
      if (o.dlg() == DLG_ELABORA)
 | 
						|
        elabora();
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
TRepgen_mask::TRepgen_mask() 
 | 
						|
            : TCalendar_mask("mr1100a") 
 | 
						|
{ 
 | 
						|
  load_profile(); 
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// MRP Form
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TMRP_form : public TForm
 | 
						|
{
 | 
						|
  TCodgiac_livelli *_codgiac;
 | 
						|
  int               _level;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual bool validate(TForm_item &, TToken_string &); // gestione dei messaggi estesi nei campi
 | 
						|
 | 
						|
public:
 | 
						|
  TMRP_form(const char* name, TCodgiac_livelli* c, int l);
 | 
						|
  virtual ~TMRP_form() {} ;
 | 
						|
};
 | 
						|
 | 
						|
TMRP_form::TMRP_form(const char* name, TCodgiac_livelli* c, int l) : TForm(name)
 | 
						|
{
 | 
						|
  _codgiac  = c;
 | 
						|
  _level = l;
 | 
						|
}
 | 
						|
 | 
						|
bool TMRP_form::validate(TForm_item &cf, TToken_string &s)
 | 
						|
{
 | 
						|
  const TString code(s.get(0)); 
 | 
						|
  
 | 
						|
  if (code == "_MRP")
 | 
						|
  {
 | 
						|
    TLocalisamfile& rep = cf.form().cursor()->file();
 | 
						|
    TString action(s.get(1));
 | 
						|
    TString livello, descr;
 | 
						|
    if (action == "DESCRLIV")
 | 
						|
    {
 | 
						|
      if (_level > 0)
 | 
						|
        livello = rep.get("LIVELLO");
 | 
						|
      if (livello.not_empty())
 | 
						|
      {
 | 
						|
        for (int lev=1; lev <= _level; lev++)
 | 
						|
        {
 | 
						|
          if (!_codgiac->enabled(lev))
 | 
						|
            continue;
 | 
						|
          const int starts = _codgiac->code_start(lev) -1;
 | 
						|
          const int length   = _codgiac->code_length(lev);
 | 
						|
          descr << "/";
 | 
						|
          descr << livello.mid(starts,length);
 | 
						|
        }
 | 
						|
        descr << "   " << _codgiac->name(_level);
 | 
						|
        descr << " " << _codgiac->group_descr(livello,_level);
 | 
						|
      }
 | 
						|
      cf.set(descr);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    if (action == "LOAD")
 | 
						|
    {
 | 
						|
      //CALCOLO percentuale carico
 | 
						|
      // MESSAGE _MRP,LOAD,<id campo1>,<id campo2>
 | 
						|
      // formula:  #id campo1 * 100 / #id campo2
 | 
						|
      // prende i contenuti dei campi specificati e ne calcola il rapporto % come indicato
 | 
						|
      real v1(cf.find_field(s.get(2)).get());
 | 
						|
      real v2(cf.find_field(s.get(3)).get());
 | 
						|
      
 | 
						|
      v1 *= 100;
 | 
						|
      if (v2 != ZERO)
 | 
						|
        v1 /= v2;
 | 
						|
      if (v1 > ZERO && v1 <= 100.0)
 | 
						|
        cf.set(v1.string("##@,@@ %"));
 | 
						|
      else
 | 
						|
        if (v1 <= ZERO)
 | 
						|
          cf.set("");
 | 
						|
        else
 | 
						|
          cf.set("*****");
 | 
						|
    }
 | 
						|
    // Ignore any other command
 | 
						|
  }
 | 
						|
  return TForm::validate(cf, s);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// MRP report file generator
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TMRP_repgen : public TSkeleton_application
 | 
						|
{
 | 
						|
  TRepgen_mask     * _m;
 | 
						|
  TMRP_form        * _form;
 | 
						|
  TLocalisamfile   * _mrprep;
 | 
						|
  TCodgiac_livelli *_codgiac;
 | 
						|
  int               _livello;
 | 
						|
  tipo_ordinamento  _tipo_ord;
 | 
						|
  tipo_valore       _tipo_val;
 | 
						|
  tipo_dettaglio    _dettaglio;
 | 
						|
  
 | 
						|
protected:  
 | 
						|
  void set_buckets_description();
 | 
						|
  void set_buckets();
 | 
						|
  void set_form();
 | 
						|
  virtual bool create(); 
 | 
						|
  virtual bool destroy(); 
 | 
						|
  virtual void main_loop();
 | 
						|
 | 
						|
public:
 | 
						|
  TMRP_repgen() { _m = NULL; }
 | 
						|
  virtual ~TMRP_repgen() {}
 | 
						|
};
 | 
						|
 | 
						|
bool TMRP_repgen::create()
 | 
						|
{
 | 
						|
  _m = new TRepgen_mask;
 | 
						|
  _mrprep = new TLocalisamfile(LF_MRPREP);
 | 
						|
  _codgiac = new  TCodgiac_livelli;
 | 
						|
  if (!_codgiac->enabled())
 | 
						|
    _m->hide(F_LIVDET);
 | 
						|
  return TSkeleton_application::create();
 | 
						|
}
 | 
						|
 | 
						|
bool TMRP_repgen::destroy()
 | 
						|
{
 | 
						|
  delete _codgiac;
 | 
						|
  if (_m)
 | 
						|
    delete _m;
 | 
						|
  if (_mrprep)
 | 
						|
    delete _mrprep;
 | 
						|
  return TSkeleton_application::destroy();
 | 
						|
}
 | 
						|
 | 
						|
void TMRP_repgen::set_buckets_description()
 | 
						|
{
 | 
						|
  TString descr;
 | 
						|
  TDate fd = _m->get_date(F_DADATA);
 | 
						|
  TDate td = _m->get_date(F_ADATA);
 | 
						|
  
 | 
						|
  TConfig ini(CONFIG_DITTA, "mr");
 | 
						|
  const bool week_complete = ini.get_bool("WEEKCOMPLETE");
 | 
						|
  
 | 
						|
  int bucket_size = _m->get_int(F_BUCKET) * 7;
 | 
						|
  if (bucket_size < 7) bucket_size = 7;
 | 
						|
  
 | 
						|
  int weekd, yeard;
 | 
						|
  
 | 
						|
  const short first_id = 3;
 | 
						|
  const short last_id  = 15;
 | 
						|
  --fd;
 | 
						|
  descr.format("\nAl  %s", (const char*)fd);
 | 
						|
  if (bucket_size == 7)
 | 
						|
  {
 | 
						|
    fd.get_week_year(weekd, yeard, week_complete);
 | 
						|
    descr << "\nSett. " << weekd << ' ' << yeard;
 | 
						|
  }
 | 
						|
  _form->find_field('B', odd_page, first_id).set_col_head(descr);
 | 
						|
  TDate wd;
 | 
						|
  for (;fd <= td;)
 | 
						|
  {
 | 
						|
    ++fd;
 | 
						|
    descr.format("Dal %s\nAl  ", (const char*)fd);
 | 
						|
    fd += bucket_size-1;
 | 
						|
    wd = fd;
 | 
						|
    descr << (const char*)fd;
 | 
						|
    const short id = first_id+_m->round_date(wd,FALSE)+1;
 | 
						|
    if (id >= last_id)
 | 
						|
      break;
 | 
						|
    if (bucket_size == 7)
 | 
						|
    {
 | 
						|
      wd.get_week_year(weekd, yeard, week_complete);
 | 
						|
      descr << "\nSett. " << weekd << ' ' << yeard;
 | 
						|
    }
 | 
						|
    _form->find_field('B', odd_page, id).set_col_head(descr);
 | 
						|
  }
 | 
						|
  descr.format("Dal %s", (const char*)wd);
 | 
						|
  if (bucket_size == 7)
 | 
						|
  {
 | 
						|
    wd.get_week_year(weekd, yeard, week_complete);
 | 
						|
    descr << "\n\nSett. " << weekd << ' ' << yeard;
 | 
						|
  }
 | 
						|
  _form->find_field('B', odd_page, last_id).set_col_head(descr);
 | 
						|
}
 | 
						|
 | 
						|
void TMRP_repgen::set_buckets()
 | 
						|
{
 | 
						|
  TString tmp;
 | 
						|
  TDate last_date = _m->get_date(F_ADATA);
 | 
						|
 | 
						|
  // Calcola l'ultimo bucket visibile: 
 | 
						|
  // Il bucket iniziale e quello finale dovrebbero essere sempre visibili
 | 
						|
  const short last_bucket = _m->round_date(last_date,TRUE)+1;
 | 
						|
 | 
						|
  // Disabilita le colonne in base al numero di buckets da visualizzare
 | 
						|
  const short first_id = 4;   // Bucket  1
 | 
						|
  const short last_id  = 14;  // Bucket  11
 | 
						|
 | 
						|
  for (short id = first_id+last_bucket; id <= last_id; id++)
 | 
						|
     _form->find_field('B',odd_page,id).disable();
 | 
						|
 | 
						|
  // Nella stampa scheduling linee, non esiste un totale per linea/impianto ma per articolo/liv giacenza
 | 
						|
  for (id = first_id+last_bucket+100; id <= (last_id+100); id++)
 | 
						|
     _form->find_field('B',odd_page,id).disable();
 | 
						|
 | 
						|
  set_buckets_description();
 | 
						|
  
 | 
						|
  // Show delle subsections necessarie
 | 
						|
  TToken_string sections;
 | 
						|
  const bool tl = _tipo_ord == linea;
 | 
						|
  
 | 
						|
  switch (_dettaglio)
 | 
						|
  {
 | 
						|
    case det_articolo:
 | 
						|
      sections = tl ? "IMPIANTI|LINEE" : "";
 | 
						|
      break;
 | 
						|
    case det_giacenza:
 | 
						|
      sections = tl ? "IMPIANTI|LINEE|ARTICOLI" :  "ARTICOLI";
 | 
						|
      break;
 | 
						|
    case det_impianto:
 | 
						|
      sections = tl ? "" : "ARTICOLI|LIVELLI";
 | 
						|
      break;
 | 
						|
    case det_linea:
 | 
						|
      sections = tl ? "IMPIANTI" : "ARTICOLI|LIVELLI|IMPIANTI";
 | 
						|
      break;
 | 
						|
    default: break;
 | 
						|
  }
 | 
						|
  
 | 
						|
  const int items = sections.items();
 | 
						|
  for (int i=0; i<items; i++)
 | 
						|
    _form->find_field('B', odd_page, sections.get(i)).show();
 | 
						|
 | 
						|
  if ((tl && _dettaglio == det_giacenza) || (!tl && _dettaglio >= det_giacenza))
 | 
						|
    if (_livello > 0)
 | 
						|
    {
 | 
						|
      tmp.format("LIVELLO[1,%d]", _codgiac->packed_length(_livello));
 | 
						|
      _form->find_field('B', odd_page, "LIVELLI").setcondition(tmp,_strexpr);
 | 
						|
    }
 | 
						|
  
 | 
						|
  if (tl && _m->get_bool(F_CAPACITA)) // Abilitato il calcolo capacita/carico linea?
 | 
						|
  {
 | 
						|
    _form->find_field('B', odd_page, 238).show();
 | 
						|
    const short lid = 240 + (last_bucket >= LAST_BUCKET ? 11 : last_bucket);
 | 
						|
    for (short id = 240; id<lid; id++)
 | 
						|
      _form->find_field('B', odd_page, id).show();
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (tl && _tipo_val == quantita) // Stampa scheduling, disabilita totali per linea/impianto)
 | 
						|
  {
 | 
						|
    // Abilita i campi per l'unita di misura sui totali per livello giac. e articolo
 | 
						|
    _form->find_field('B', odd_page, 2).show();
 | 
						|
    _form->find_field('B', odd_page, 302).show();
 | 
						|
    _form->find_field('B', odd_page, 402).show();
 | 
						|
    _form->find_field('B', odd_page, 502).show();
 | 
						|
    for (short id = 201; id <= 215; id++)
 | 
						|
      _form->find_field('B', odd_page, id).hide(); // Riga totale linea
 | 
						|
    for (id = 101; id <= 115; id++)
 | 
						|
      _form->find_field('B', odd_page, id).hide(); // Riga totale impianto
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (!tl && _tipo_val == carico) // Stampa carico per articoli
 | 
						|
  {
 | 
						|
    // Nasconde la colonna delle unita' di misura.
 | 
						|
    // Il calcolo capacita' non ha senso e quindi viene omesso in
 | 
						|
    // stampa, sebbene sia possibile effettuarne il calcolo.
 | 
						|
    _form->find_field('B', odd_page, 2).hide();
 | 
						|
    _form->find_field('B', odd_page, 102).hide();
 | 
						|
    _form->find_field('B', odd_page, 202).hide();
 | 
						|
    _form->find_field('B', odd_page, 302).hide();
 | 
						|
    _form->find_field('B', odd_page, 402).hide();
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Prende il titolo della stampa dal nome profilo
 | 
						|
  _form->find_field('H', odd_page,4).set(_m->get(DLG_PROFILE));
 | 
						|
}
 | 
						|
 | 
						|
void TMRP_repgen::set_form()
 | 
						|
{
 | 
						|
  TString expr,tmp;
 | 
						|
  TString from(_m->get(_tipo_ord == articolo ? F_ARTFROM : F_IMPIANTOFROM));
 | 
						|
  TString to(_m->get(_tipo_ord == articolo ? F_ARTTO : F_IMPIANTOTO));
 | 
						|
 | 
						|
  expr.format("(TIPO==\"R\")");
 | 
						|
  if (_tipo_ord == articolo)
 | 
						|
  {
 | 
						|
    if (from.not_empty())
 | 
						|
    {
 | 
						|
      expr << "&&";  
 | 
						|
      tmp.format("(CODART>=\"%s\")",(const char*)from);
 | 
						|
      expr << tmp;
 | 
						|
    }
 | 
						|
    if (to.not_empty())
 | 
						|
    {
 | 
						|
      if (expr.not_empty())
 | 
						|
        expr << "&&";  
 | 
						|
      tmp.format("(CODART<=\"%s\")",(const char*)to);
 | 
						|
      expr << tmp;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (from.not_empty())
 | 
						|
    {
 | 
						|
      expr << "&&";  
 | 
						|
      tmp.format("(IMPIANTO>=\"%s\")",(const char*)from);
 | 
						|
      expr << tmp;
 | 
						|
    }
 | 
						|
  
 | 
						|
    if (to.not_empty())
 | 
						|
    {
 | 
						|
      if (expr.not_empty())
 | 
						|
        expr << "&&";  
 | 
						|
      tmp.format("(IMPIANTO<=\"%s\")",(const char*)to);
 | 
						|
      expr << tmp;
 | 
						|
    }
 | 
						|
  
 | 
						|
  
 | 
						|
    from = _m->get(F_LINEAFROM);
 | 
						|
    to   = _m->get(F_LINEAFROM);
 | 
						|
  
 | 
						|
    if (from.not_empty())
 | 
						|
    {
 | 
						|
      if (expr.not_empty())
 | 
						|
        expr << "&&";  
 | 
						|
      tmp.format("(LINEA>=\"%s\")",(const char*)from);
 | 
						|
      expr << tmp;
 | 
						|
    }
 | 
						|
  
 | 
						|
    if (to.not_empty())
 | 
						|
    {
 | 
						|
      if (expr.not_empty())
 | 
						|
        expr << "&&";  
 | 
						|
      tmp.format("(LINEA<=\"%s\")",(const char*)to);
 | 
						|
      expr << tmp;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (expr.not_empty()) // Filtronzo... il filtro gonzo
 | 
						|
    _form->cursor()->setfilter(expr);
 | 
						|
  
 | 
						|
  set_buckets();
 | 
						|
}
 | 
						|
 | 
						|
void TMRP_repgen::main_loop()
 | 
						|
{
 | 
						|
  while (_m->run() != K_QUIT)
 | 
						|
  {
 | 
						|
    const bool use_file = _m->get_bool(F_USAFILE);
 | 
						|
    if (use_file || _m->elabora())
 | 
						|
    {
 | 
						|
      _tipo_ord       = (tipo_ordinamento) _m->get_int(F_ORDINAMENTO);
 | 
						|
      _tipo_val       = (tipo_valore)      _m->get_int(F_VAL2PRINT);
 | 
						|
      _livello    = _m->get_int(F_LIVDET);
 | 
						|
      TFilename fname(_m->get(F_FILENAME)); // Presente 24 ore su 24
 | 
						|
      fname.insert("%"); // e questo dove lo mettiamo?
 | 
						|
      const bool delfile = !_m->get_bool(F_GENREPORT) && !use_file;
 | 
						|
      
 | 
						|
      if (delfile)
 | 
						|
        _m->reset(F_FILENAME);
 | 
						|
      // Utilizza questo file per la stampa del form
 | 
						|
      TIsamtempfile * report = new TIsamtempfile(LF_MRPREP,fname, FALSE, delfile);
 | 
						|
      TRelation* rel;
 | 
						|
      _dettaglio  = (tipo_dettaglio) _m->get_int(_tipo_ord == articolo ? F_DETTAGLIO1 : F_DETTAGLIO2);
 | 
						|
      _form = new TMRP_form(_tipo_ord == articolo ? "mr1100a" : "mr1100b", _codgiac, _livello);
 | 
						|
      rel = _form->relation();
 | 
						|
      rel->replace(report);
 | 
						|
      set_form();
 | 
						|
      
 | 
						|
      const int hh = 7;
 | 
						|
      const int fl = printer().formlen();
 | 
						|
      
 | 
						|
      int rows[4];         // Righe orizzontali
 | 
						|
      rows[0] = hh-4;
 | 
						|
      rows[1] = hh;
 | 
						|
      rows[2] = fl;
 | 
						|
      rows[3] = 0;
 | 
						|
      _form->genera_intestazioni(odd_page, hh-3);
 | 
						|
      _form->genera_fincatura(odd_page, hh-4, fl, rows);
 | 
						|
  
 | 
						|
      // stampa
 | 
						|
      if (_form->cursor()->items() > 0)
 | 
						|
        _form->print();
 | 
						|
      // report non va cancellato, poiche' ne viene fatta la sostituzione nella relazione del form
 | 
						|
      // quindi la delete viene gia' fatta alla distruzione di _form
 | 
						|
      delete _form;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int mr1100(int argc, char* argv[])
 | 
						|
{
 | 
						|
  TMRP_repgen a;
 | 
						|
  a.run(argc, argv, "Generazione MRP reports");
 | 
						|
  return 0;
 | 
						|
}
 |