Files correlati :mr2.exe Ricompilazione Demo : [ ] Commento :corretto errore di compilazione (aggiunto il metodo currency2um()) git-svn-id: svn://10.65.10.50/trunk@11099 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			3288 lines
		
	
	
		
			101 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			3288 lines
		
	
	
		
			101 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <applicat.h>
 | 
						||
#include <defmask.h>
 | 
						||
#include <progind.h>
 | 
						||
#include <sheet.h>
 | 
						||
#include <tabutil.h>
 | 
						||
#include <utility.h>
 | 
						||
#include <printer.h>
 | 
						||
#include <currency.h>
 | 
						||
#include <colmask.h>
 | 
						||
#include <urldefid.h>
 | 
						||
 | 
						||
#include "mrplib.h"
 | 
						||
#include "..\mg\mglib.h"
 | 
						||
#include "..\ve\velib.h"
 | 
						||
#include "..\ve\veconf.h"
 | 
						||
 | 
						||
#include "mr2100.h"
 | 
						||
#include "mr2100a.h"
 | 
						||
#include "mr2100c.h"
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMRP_record
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
void TMRP_record::add_ref(TMRP_docref * ref, TMRP_docrefs* &refs)
 | 
						||
{
 | 
						||
  if (ref != NULL)
 | 
						||
  {
 | 
						||
    if (refs == NULL) 
 | 
						||
      refs = new TMRP_docrefs();
 | 
						||
    refs->add(ref);
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_gross_req(const real & val, TMRP_internalref * ref)
 | 
						||
{
 | 
						||
  if (_internal_req == NULL)
 | 
						||
    _internal_req = new TMRP_internalrefs();
 | 
						||
  _internal_req->add(ref);
 | 
						||
  return add_gross_req(val);
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_gross_req(const real & val, TMRP_docref * ref)
 | 
						||
{
 | 
						||
  add_ref(ref, _requirements);
 | 
						||
  _gross_requirement += val;
 | 
						||
  return _gross_requirement;
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_sched_rec(const real & val, TMRP_docref * ref)
 | 
						||
{
 | 
						||
  add_ref(ref, _scheduls);
 | 
						||
  _sched_receipts += val;
 | 
						||
  return _sched_receipts;
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_planned_ord(const real & val, TMRP_docref * ref)
 | 
						||
{
 | 
						||
  add_ref(ref, _plans);
 | 
						||
  _planned_orders += val;
 | 
						||
  return _planned_orders;
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_resched_ord(const real & val)
 | 
						||
{
 | 
						||
  _resched_orders += val;
 | 
						||
  return _resched_orders;
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_unsched_ord(const real & val)
 | 
						||
{
 | 
						||
  _unsched_orders += val;
 | 
						||
  return _unsched_orders;
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_record::add_net_req(const real & val)
 | 
						||
{
 | 
						||
  _net_requirement += val;
 | 
						||
  return _net_requirement;
 | 
						||
}
 | 
						||
 | 
						||
TObject * TMRP_record::dup() const
 | 
						||
{
 | 
						||
  TMRP_record *o= new TMRP_record(_time);
 | 
						||
  o->TMRP_record::operator=(*this);
 | 
						||
  return o;
 | 
						||
}
 | 
						||
 | 
						||
TMRP_record & TMRP_record::operator=(const TMRP_record & a) 
 | 
						||
{
 | 
						||
  _gross_requirement=a._gross_requirement;
 | 
						||
  _on_hand=a._on_hand;          
 | 
						||
  _sched_receipts=a._sched_receipts;
 | 
						||
  _net_requirement=a._net_requirement;  
 | 
						||
  _planned_orders=a._planned_orders;   
 | 
						||
  _resched_orders=a._resched_orders;   
 | 
						||
 | 
						||
  if (a._plans) _plans = (TMRP_docrefs *)a._plans->dup();
 | 
						||
  if (a._scheduls) _scheduls = (TMRP_docrefs *)a._scheduls->dup();
 | 
						||
  if (a._requirements) _requirements = (TMRP_docrefs *)a._requirements->dup();
 | 
						||
  if (a._internal_req) _internal_req = (TMRP_internalrefs *)a._internal_req->dup();
 | 
						||
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
TMRP_record::TMRP_record(const TMRP_time& t)
 | 
						||
           : _time(t) 
 | 
						||
{
 | 
						||
  _plans = NULL;
 | 
						||
  _scheduls = NULL;
 | 
						||
  _requirements = NULL;
 | 
						||
  _internal_req = NULL;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMRP_line
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
TArticolo_giacenza *TMRP_line::_articolo_giac=NULL;
 | 
						||
TString16 TMRP_line::_substr;
 | 
						||
 | 
						||
void TMRP_line::lotti_riordino(real & minimo, real & increm) const 
 | 
						||
{ 
 | 
						||
  _articolo_giac->read(_codart);
 | 
						||
  const int i=_articolo_giac->find_mag("", _codmag);
 | 
						||
  if (i>=0)
 | 
						||
  {
 | 
						||
    const TRectype & rec=_articolo_giac->mag("").row(i);
 | 
						||
    minimo = rec.get_real(MAG_LOTTORIOR);
 | 
						||
    increm = rec.get_real(MAG_LOTTOIRIOR);
 | 
						||
  } else 
 | 
						||
    minimo=increm=0;
 | 
						||
  if (minimo.is_zero()) 
 | 
						||
    minimo = _articolo_giac->get_real(MAG_LOTTORIOR);
 | 
						||
  if (increm.is_zero()) 
 | 
						||
    increm = _articolo_giac->get_real(MAG_LOTTOIRIOR);
 | 
						||
}
 | 
						||
 | 
						||
int TMRP_line::add_son(const real& qta, TMRP_line* son)
 | 
						||
{
 | 
						||
  CHECK(son, "Can't add NULL TMRP_line son");
 | 
						||
  if (son == this)
 | 
						||
    fatal_box("Riga di MRP %sz %s padre di se stessa", (const char *)articolo(), (const char *)livgiac());
 | 
						||
  CHECK(son != this, "Hermafrodite TMRP_line");
 | 
						||
  _qta_sons.add(qta);
 | 
						||
  return _sons.add(son);
 | 
						||
}
 | 
						||
 | 
						||
bool TMRP_line::is_son(const TCodice_articolo& art) const
 | 
						||
{
 | 
						||
  for (int i = sons()-1; i >= 0; i--)
 | 
						||
  {
 | 
						||
    const TMRP_line& r = son(i);
 | 
						||
    if (r.articolo() == art)
 | 
						||
      break;
 | 
						||
  }
 | 
						||
  return i >= 0;
 | 
						||
}
 | 
						||
 | 
						||
int TMRP_line::compare(const TSortable& s) const
 | 
						||
{
 | 
						||
  const TMRP_line& line = (const TMRP_line&)s;
 | 
						||
  const bool imfather = sons() > 0;
 | 
						||
  const bool hesfather = line.sons() > 0;
 | 
						||
  if (imfather && (!hesfather || is_son(line.articolo())))
 | 
						||
    return +1;
 | 
						||
  if (hesfather && (!imfather || line.is_son(articolo())))
 | 
						||
    return -1;
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TObject* TMRP_line::dup() const
 | 
						||
{
 | 
						||
  TMRP_line * o=new TMRP_line(*this);
 | 
						||
  return o;
 | 
						||
}
 | 
						||
 | 
						||
TMRP_line & TMRP_line::operator=(const TMRP_line & a)
 | 
						||
{
 | 
						||
  //key
 | 
						||
  _codart=a._codart;
 | 
						||
  _livgiac=a._livgiac;
 | 
						||
  _codmag=a._codmag;
 | 
						||
  _codimp=a._codimp;
 | 
						||
  _codlin=a._codlin;
 | 
						||
  _codclifor=a._codclifor;
 | 
						||
  // contents
 | 
						||
  _descr=a._descr;
 | 
						||
  _sons=a._sons;
 | 
						||
  _qta_sons=a._qta_sons;
 | 
						||
  _req_per_bucket=a._req_per_bucket;
 | 
						||
  _final_product = a._final_product;
 | 
						||
 | 
						||
  _articolo_giac= new TArticolo_giacenza(a._articolo_giac->codice());
 | 
						||
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
TMRP_record& TMRP_line::record(int i) const
 | 
						||
{
 | 
						||
  TMRP_record* rec = (TMRP_record*)_req_per_bucket.objptr(i);
 | 
						||
  CHECKD(rec, "Invalid MRP record ", i);
 | 
						||
  return *rec;
 | 
						||
}
 | 
						||
 | 
						||
TMRP_record& TMRP_line::record(const TMRP_time& t) const
 | 
						||
{
 | 
						||
  const int last = last_bucket();
 | 
						||
  for (int i = 0; i <= last; i++)
 | 
						||
  {
 | 
						||
    TMRP_record& rec = record(i);
 | 
						||
    const int cmp = rec.time().compare(t);
 | 
						||
    if (cmp == 0)
 | 
						||
      return rec;
 | 
						||
    if (cmp > 0)
 | 
						||
    {
 | 
						||
      ((TArray&)_req_per_bucket).insert(NULL, i);
 | 
						||
      break;
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  TMRP_record* rec = new TMRP_record(t);
 | 
						||
  ((TArray&)_req_per_bucket).add(rec, i);
 | 
						||
  return *rec;
 | 
						||
}
 | 
						||
 | 
						||
// approssima in base al lotto minimo; prevede valori negativi
 | 
						||
real TMRP_line::sizeup_net_requirement(int i, const real &val, const real & oldnet)
 | 
						||
{
 | 
						||
  real req(oldnet);       // Azzera net requirement
 | 
						||
  if (val + oldnet < ZERO)
 | 
						||
  {
 | 
						||
    req = -(val + oldnet);   // Rende positiva la richiesta effettiva
 | 
						||
    
 | 
						||
    real lm,li;
 | 
						||
    lotti_riordino(lm,li);                         
 | 
						||
    if (req > lm) // Se la richiesta supera il lotto minimo 
 | 
						||
    {
 | 
						||
      if (li > ZERO)
 | 
						||
      {
 | 
						||
        // Calcola il numero di lotti incrementali
 | 
						||
        real lotti = (req - lm) / li;
 | 
						||
        lotti.ceil();
 | 
						||
        // La quantita' richiesta = minimo + lotti * dim.lotti
 | 
						||
        req = lm + lotti * li;
 | 
						||
      }
 | 
						||
    }
 | 
						||
    else
 | 
						||
      req = lm;   // Forza la richiesta almeno al lotto minimo
 | 
						||
    req += oldnet;
 | 
						||
  } 
 | 
						||
  set_net_req(i, req);
 | 
						||
  return req;
 | 
						||
}
 | 
						||
 | 
						||
const real& TMRP_line::add_gross_req(const TMRP_time& t, const real& val, TMRP_internalref * ref)
 | 
						||
{ return record(t).add_gross_req(val, ref); }
 | 
						||
 | 
						||
const real& TMRP_line::add_gross_req(const TMRP_time& t, const real& val, TMRP_docref * ref)
 | 
						||
{ return record(t).add_gross_req(val, ref); }
 | 
						||
 | 
						||
const real& TMRP_line::add_sched_rec(const TMRP_time& t, const real &val, TMRP_docref * ref)
 | 
						||
{return record(t).add_sched_rec(val, ref);}
 | 
						||
 | 
						||
const real& TMRP_line::add_planned_ord(const TMRP_time& t, const real &val, TMRP_docref * ref)
 | 
						||
{ return record(t).add_planned_ord(val, ref);}
 | 
						||
 | 
						||
const real& TMRP_line::add_resched_ord(int i, const real &val)
 | 
						||
{ return record(i).add_resched_ord(val); }
 | 
						||
 | 
						||
const real& TMRP_line::add_unsched_ord(int i, const real &val)
 | 
						||
{ return record(i).add_unsched_ord(val); }
 | 
						||
 | 
						||
const real & TMRP_line::set_net_req(int i, const real &val)
 | 
						||
{ 
 | 
						||
  if (val>ZERO)
 | 
						||
    return record(i).set_net_req(val); 
 | 
						||
  else
 | 
						||
    return record(i).set_net_req(ZERO); 
 | 
						||
}
 | 
						||
 | 
						||
const real & TMRP_line::add_net_req(const TMRP_time &t, const real &val)
 | 
						||
{return record(t).add_net_req(val); }
 | 
						||
 | 
						||
const real & TMRP_line::add_net_req(int i, const real &val)
 | 
						||
{ return record(i).add_net_req(val); }
 | 
						||
 | 
						||
const real & TMRP_line::set_on_hand(int i, const real &val)
 | 
						||
{ return record(i).set_on_hand(val);}
 | 
						||
 | 
						||
const real & TMRP_line::set_on_hand(const TMRP_time &t, const real &val)
 | 
						||
{ return record(t).set_on_hand(val);}
 | 
						||
 | 
						||
const TMRP_time& TMRP_line::lead_time(int i, TMRP_time& t, bool anticipate) const
 | 
						||
{
 | 
						||
  t = record(i).time();
 | 
						||
 | 
						||
  if (anticipate)
 | 
						||
  {
 | 
						||
    if (!cache().get(LF_DIST, articolo()).empty())
 | 
						||
    {
 | 
						||
      int days = cache().get(LF_DIST, articolo()).get_int("LEADTIME");
 | 
						||
      long hours = cache().get(LF_DIST, articolo()).get_long("LEADHOURS");
 | 
						||
      t.sub_time(days, hours);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      _articolo_giac->read(articolo());
 | 
						||
      TDate d = t.date();
 | 
						||
      d -= _articolo_giac->lead_time(codmagdep(), livgiac());
 | 
						||
      t.set(d, t.hour(), t.impianto(), t.linea());
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return t;
 | 
						||
}
 | 
						||
 | 
						||
real &TMRP_line::giacenza_attuale(real &g) const
 | 
						||
{
 | 
						||
  TDate d(TODAY);
 | 
						||
  return giacenza_attuale(g, d);
 | 
						||
}
 | 
						||
                         
 | 
						||
real &TMRP_line::giacenza_attuale(real &g, const TDate &d) const
 | 
						||
{
 | 
						||
  _articolo_giac->read(articolo());
 | 
						||
  g = _articolo_giac->giacenza_anno(codmagdep(),livgiac(),d.year());
 | 
						||
  return g;
 | 
						||
}
 | 
						||
 | 
						||
real &TMRP_line::scorta_minima(real &g) const
 | 
						||
{
 | 
						||
  TDate d(TODAY);
 | 
						||
  return scorta_minima(g,d);
 | 
						||
}
 | 
						||
 | 
						||
real &TMRP_line::scorta_minima(real &g, const TDate &d) const
 | 
						||
{
 | 
						||
  _articolo_giac->read(articolo());
 | 
						||
  g = _articolo_giac->scorta_minima(codmagdep(),livgiac(),d.year());
 | 
						||
  return g;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TMRP_line::TMRP_line(const char* art, const char* giac, 
 | 
						||
                      const char* mag, const char* magc, 
 | 
						||
                      const char* imp, const char* lin, 
 | 
						||
                      long codcli)
 | 
						||
         : _codart(art), _livgiac(giac), 
 | 
						||
           _codmag(mag), _codmag_coll(magc), 
 | 
						||
           _codimp(imp), _codlin(lin), _codclifor(codcli),
 | 
						||
           _final_product(FALSE)
 | 
						||
{ 
 | 
						||
  if (_articolo_giac==NULL)
 | 
						||
     _articolo_giac= new TArticolo_giacenza();
 | 
						||
}
 | 
						||
 | 
						||
TMRP_line::TMRP_line(const TMRP_line&a)
 | 
						||
{ 
 | 
						||
  TMRP_line::operator=(a);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMRP_lines
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
TMRP_lines::TMRP_lines(const TMRP_lines & a)
 | 
						||
{
 | 
						||
  TMRP_lines::operator=(a);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TObject* TMRP_lines::dup() const
 | 
						||
{
 | 
						||
  return new TMRP_lines(*this);
 | 
						||
}
 | 
						||
TMRP_lines & TMRP_lines::operator= (const TMRP_lines &a)
 | 
						||
{
 | 
						||
  TMRP_array::operator= (a);
 | 
						||
  _ignore_mag=a._ignore_mag;
 | 
						||
  _ignore_dep=a._ignore_dep;
 | 
						||
  _ignore_imp=a._ignore_imp;
 | 
						||
  _ignore_lin=a._ignore_lin;
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
TSortable* TMRP_lines::new_obj(const TToken_string& key) const
 | 
						||
{
 | 
						||
  TCodice_articolo art; key.get(0, art); art.trim();
 | 
						||
  TString16 gia; key.get(1, gia); gia.trim();
 | 
						||
  TString8 mag; key.get(2, mag); mag.trim();
 | 
						||
  TString8 magc; key.get(3, magc); magc.trim();
 | 
						||
  TString8 imp; key.get(4, imp); imp.trim();
 | 
						||
  TString8 lin; key.get(5, lin); lin.trim();
 | 
						||
  TString16 clifor ; key.get(6, clifor);
 | 
						||
  return new TMRP_line(art, gia, mag, magc, imp, lin, atol(clifor)); 
 | 
						||
}
 | 
						||
 | 
						||
TMRP_line* TMRP_lines::find(const TCodice_articolo& codart, const TString& gia, 
 | 
						||
                            const TString& mag, const TString& magc,
 | 
						||
                            const TString& imp, const TString& lin,
 | 
						||
                            long codcli,
 | 
						||
                            bool create)
 | 
						||
{
 | 
						||
  _key = codart;
 | 
						||
  _key.add(gia);
 | 
						||
  _key.trim(); // trim to trim giaclevel...
 | 
						||
  if (_ignore_mag) 
 | 
						||
  {
 | 
						||
    _key.add(" ",2);
 | 
						||
    _key.add(" ",3);
 | 
						||
  }
 | 
						||
  else 
 | 
						||
  {
 | 
						||
    if (_ignore_dep) 
 | 
						||
    {
 | 
						||
      _key.add(mag.left(3) ,2);
 | 
						||
      _key.add(magc.left(3),3);
 | 
						||
    } else {
 | 
						||
      _key.add(mag,2);
 | 
						||
      _key.add(magc,3);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  if (_ignore_imp) 
 | 
						||
    _key.add(" ",4);
 | 
						||
  else 
 | 
						||
    _key.add(imp,4);
 | 
						||
  if (_ignore_lin) 
 | 
						||
    _key.add(" ",5);
 | 
						||
  else 
 | 
						||
    _key.add(lin,5);
 | 
						||
 | 
						||
  _key.add(codcli,6);
 | 
						||
 | 
						||
  TSortable* s = create ? add_obj(_key) : find_obj(_key);
 | 
						||
  return (TMRP_line*)s;
 | 
						||
}
 | 
						||
 | 
						||
TMRP_lines::TMRP_lines() 
 | 
						||
          : _ignore_mag(FALSE), _ignore_dep(FALSE), _ignore_imp(FALSE), _ignore_lin(FALSE) 
 | 
						||
{ }
 | 
						||
 | 
						||
TMRP_lines::~TMRP_lines() 
 | 
						||
{ destroy(); }
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TRiga_ordine
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
#define COMPARE_ALL_CODES   13    // 
 | 
						||
#define COMPARE_COMPLETE    99    // 
 | 
						||
#define COMPARE_TDFA     -1     // 
 | 
						||
#define COMPARE_TDAF     -2     // 
 | 
						||
#define COMPARE_TFAD     -3     // 
 | 
						||
#define COMPARE_TFDA     -4     // 
 | 
						||
#define COMPARE_TAFD     -5     // 
 | 
						||
#define COMPARE_TADF     -6     // 
 | 
						||
#define COMPARE_DTFA     -7     // data documento + data di consegna + fornitore + articolo
 | 
						||
#define COMPARE_DATF     -8     // data documento + data di consegna + articolo + fornitore 
 | 
						||
#define COMPARE_ATFD     -9     // 
 | 
						||
#define COMPARE_ADTF     -10    // 
 | 
						||
#define COMPARE_TCFA     -11    // 
 | 
						||
#define COMPARE_TCAF     -12    // 
 | 
						||
#define COMPARE_TFAC     -13     // 
 | 
						||
#define COMPARE_TFCA     -14     // 
 | 
						||
#define COMPARE_TAFC     -15     // 
 | 
						||
#define COMPARE_TACF     -16     // 
 | 
						||
#define COMPARE_CTFA     -17     // data di consegna + data documento + fornitore + articolo
 | 
						||
#define COMPARE_CATF     -18     // data di consegna + data documento + articolo + fornitore 
 | 
						||
#define COMPARE_ATFC     -19     // 
 | 
						||
#define COMPARE_ACTF     -20    // 
 | 
						||
 | 
						||
class TRiga_ordine : public TToken_string
 | 
						||
{
 | 
						||
public:
 | 
						||
  int compare(const TToken_string& r, int level = COMPARE_ALL_CODES, bool ascending=TRUE) const;
 | 
						||
  int compare_field(TString &str0, TString &str1,short field_no) const;
 | 
						||
 | 
						||
  TRiga_ordine& operator=(TToken_string& r);
 | 
						||
  TRiga_ordine& operator+=(TRiga_ordine& r);
 | 
						||
 | 
						||
  TRiga_ordine() : TToken_string(128) { }
 | 
						||
  TRiga_ordine(const TDate& datadoc, const TDate& datacons, long forn, 
 | 
						||
               const TMRP_line& line, int bucket, const real & price);
 | 
						||
  virtual ~TRiga_ordine() { }
 | 
						||
};
 | 
						||
 | 
						||
int TRiga_ordine::compare(const TToken_string& riga, int level, bool ascending) const
 | 
						||
{
 | 
						||
  TString str0, str1;
 | 
						||
  int cmp = 0;
 | 
						||
  if (level>=0)
 | 
						||
  {
 | 
						||
    for (int i = 2; i <= level && i <= COMPARE_ALL_CODES  && cmp == 0; i++)
 | 
						||
    {
 | 
						||
      get(i, str0);
 | 
						||
      riga.get(i, str1);
 | 
						||
      cmp = compare_field(str0,str1,short(i+FIRST_FIELD));
 | 
						||
    }
 | 
						||
    if (level > COMPARE_ALL_CODES)
 | 
						||
    {
 | 
						||
      i = F_DOCANNODOC;
 | 
						||
      while (cmp == 0 && i <= F_DOCNRIGA)
 | 
						||
      {
 | 
						||
        get(i-FIRST_FIELD, str0);
 | 
						||
        riga.get(i-FIRST_FIELD, str1);
 | 
						||
        if (str1.blank()) // se la linea trovata non <20> riferita a un doc, va sempre bene
 | 
						||
          break; 
 | 
						||
        cmp = compare_field(str0,str1,short(i++));
 | 
						||
      }
 | 
						||
    }
 | 
						||
  } else {
 | 
						||
    // ordinamenti non standard
 | 
						||
    short f;
 | 
						||
    short fields_TFAD[] = {F_ORD_TYPE, F_FORNITORE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_DATADOC, F_DATACONS};
 | 
						||
    short fields_TFDA[] = {F_ORD_TYPE, F_FORNITORE, F_DATADOC, F_DATACONS, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4};
 | 
						||
    short fields_TDFA[] = {F_ORD_TYPE, F_DATADOC, F_DATACONS, F_FORNITORE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4};
 | 
						||
    short fields_TDAF[] = {F_ORD_TYPE, F_DATADOC, F_DATACONS, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_FORNITORE};
 | 
						||
    short fields_TAFD[] = {F_ORD_TYPE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_FORNITORE, F_DATADOC, F_DATACONS};
 | 
						||
    short fields_TADF[] = {F_ORD_TYPE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_DATADOC, F_DATACONS, F_FORNITORE};
 | 
						||
    short fields_DTFA[] = {F_DATADOC, F_DATACONS, F_ORD_TYPE, F_FORNITORE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4};
 | 
						||
    short fields_DATF[] = {F_DATADOC, F_DATACONS, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_ORD_TYPE, F_FORNITORE};
 | 
						||
    short fields_ATFD[] = {F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_ORD_TYPE, F_FORNITORE, F_DATADOC, F_DATACONS};
 | 
						||
    short fields_ADTF[] = {F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_ORD_TYPE, F_DATADOC, F_DATACONS, F_FORNITORE};
 | 
						||
 | 
						||
    short fields_TFAC[] = {F_ORD_TYPE, F_FORNITORE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_DATACONS, F_DATADOC};
 | 
						||
    short fields_TFCA[] = {F_ORD_TYPE, F_FORNITORE, F_DATACONS, F_DATADOC, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4};
 | 
						||
    short fields_TCFA[] = {F_ORD_TYPE, F_DATACONS, F_DATADOC, F_FORNITORE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4};
 | 
						||
    short fields_TCAF[] = {F_ORD_TYPE, F_DATACONS, F_DATADOC, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_FORNITORE};
 | 
						||
    short fields_TAFC[] = {F_ORD_TYPE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_FORNITORE, F_DATACONS, F_DATADOC};
 | 
						||
    short fields_TACF[] = {F_ORD_TYPE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_DATACONS, F_DATADOC, F_FORNITORE};
 | 
						||
    short fields_CTFA[] = {F_DATACONS, F_DATADOC, F_ORD_TYPE, F_FORNITORE, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4};
 | 
						||
    short fields_CATF[] = {F_DATACONS, F_DATADOC, F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_ORD_TYPE, F_FORNITORE};
 | 
						||
    short fields_ATFC[] = {F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_ORD_TYPE, F_FORNITORE, F_DATACONS, F_DATADOC};
 | 
						||
    short fields_ACTF[] = {F_ARTICOLO, F_LIV1, F_LIV2, F_LIV3, F_LIV4, F_ORD_TYPE, F_DATACONS, F_DATADOC, F_FORNITORE};
 | 
						||
 | 
						||
    for (int i = 0; i < 9 && cmp == 0; i++)
 | 
						||
    {
 | 
						||
      switch (level)
 | 
						||
      {
 | 
						||
        case COMPARE_TFAD:   f=fields_TFAD[i];         break;
 | 
						||
        case COMPARE_TFDA:   f=fields_TFDA[i];         break;
 | 
						||
        case COMPARE_TDFA:   f=fields_TDFA[i];         break;
 | 
						||
        case COMPARE_TDAF:   f=fields_TDAF[i];         break;
 | 
						||
        case COMPARE_TADF:   f=fields_TADF[i];         break;
 | 
						||
        case COMPARE_TAFD:   f=fields_TAFD[i];         break;
 | 
						||
        case COMPARE_DTFA:   f=fields_DTFA[i];         break;
 | 
						||
        case COMPARE_DATF:   f=fields_DATF[i];         break;
 | 
						||
        case COMPARE_ADTF:   f=fields_ADTF[i];         break;
 | 
						||
        case COMPARE_ATFD:   f=fields_ATFD[i];         break;
 | 
						||
 | 
						||
        case COMPARE_TFAC:   f=fields_TFAC[i];         break;
 | 
						||
        case COMPARE_TFCA:   f=fields_TFCA[i];         break;
 | 
						||
        case COMPARE_TCFA:   f=fields_TCFA[i];         break;
 | 
						||
        case COMPARE_TCAF:   f=fields_TCAF[i];         break;
 | 
						||
        case COMPARE_TACF:   f=fields_TACF[i];         break;
 | 
						||
        case COMPARE_TAFC:   f=fields_TAFC[i];         break;
 | 
						||
        case COMPARE_CTFA:   f=fields_CTFA[i];         break;
 | 
						||
        case COMPARE_CATF:   f=fields_CATF[i];         break;
 | 
						||
        case COMPARE_ACTF:   f=fields_ACTF[i];         break;
 | 
						||
        case COMPARE_ATFC:   f=fields_ATFC[i];         break;
 | 
						||
        default:
 | 
						||
          NFCHECK("Ordinamento sconosciuto");
 | 
						||
        break;
 | 
						||
      }
 | 
						||
      get(f - FIRST_FIELD, str0);
 | 
						||
      riga.get(f - FIRST_FIELD, str1);
 | 
						||
      cmp=compare_field(str0,str1,f);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return ascending ? cmp : -cmp;
 | 
						||
}
 | 
						||
 | 
						||
int TRiga_ordine::compare_field(TString &str0, TString &str1,short field_no) const
 | 
						||
{
 | 
						||
  int cmp;
 | 
						||
  switch (field_no)
 | 
						||
  {
 | 
						||
  case F_DATADOC: 
 | 
						||
  case F_DATACONS:
 | 
						||
    { 
 | 
						||
      if (str0 != str1)
 | 
						||
      {
 | 
						||
        const TDate mine(str0);
 | 
						||
        const TDate his(str1);
 | 
						||
        cmp = mine > his ? +1 : -1;
 | 
						||
      }
 | 
						||
      else
 | 
						||
        cmp = 0;
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_FORNITORE: // data doc
 | 
						||
    {
 | 
						||
      const long f0 = atol(str0);
 | 
						||
      const long f1 = atol(str1);
 | 
						||
      cmp = f0 == f1 ? 0 : (f0 > f1 ? +1 : -1);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  default:
 | 
						||
    cmp = str0.compare(str1);
 | 
						||
    break;
 | 
						||
  }
 | 
						||
  return cmp;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
TRiga_ordine& TRiga_ordine::operator=(TToken_string& r)
 | 
						||
{
 | 
						||
  this->TToken_string::operator=(r);
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
TRiga_ordine& TRiga_ordine::operator+=(TRiga_ordine& r)
 | 
						||
{
 | 
						||
  CHECK(compare(r) == 0, "Can't add incompatible order line");
 | 
						||
  
 | 
						||
  const real q = r.get(F_QUANTITA - FIRST_FIELD);
 | 
						||
  if (!q.is_zero())
 | 
						||
  {
 | 
						||
    real qta = get(F_QUANTITA - FIRST_FIELD);
 | 
						||
    qta += q; qta.round(5);
 | 
						||
    add(qta.is_zero() ? " " : qta.string(), F_QUANTITA - FIRST_FIELD);
 | 
						||
  }
 | 
						||
  return *this;
 | 
						||
}
 | 
						||
 | 
						||
TRiga_ordine::TRiga_ordine(const TDate& datadoc, const TDate& datacons, long forn, const TMRP_line& line, int bucket, const real& price)
 | 
						||
            : TToken_string(128)
 | 
						||
{
 | 
						||
  // Determino il tipo di ordine (PROD/ACQ)
 | 
						||
  bool art_prod = FALSE;
 | 
						||
  const TCodice_articolo& codart = line.articolo();
 | 
						||
  const TRectype& rec=cache().get(LF_DIST, codart);
 | 
						||
  if (rec.empty())
 | 
						||
    art_prod = cache().get(LF_ANAMAG, codart).get_bool(ANAMAG_ARTPROD);
 | 
						||
  else
 | 
						||
    art_prod = rec.get_bool("ARTPROD");
 | 
						||
 | 
						||
  add(" ",F_SELECTED - FIRST_FIELD);
 | 
						||
  add(art_prod ? "P" : "F", F_ORD_TYPE - FIRST_FIELD);
 | 
						||
  add(datadoc.string(),F_DATADOC - FIRST_FIELD);
 | 
						||
  add(datacons.string(),F_DATACONS - FIRST_FIELD);
 | 
						||
  add(line.codclifor() ? line.codclifor() : forn, F_FORNITORE - FIRST_FIELD);
 | 
						||
  add(line.articolo(),F_ARTICOLO - FIRST_FIELD);
 | 
						||
 | 
						||
  for (int l = livelli_giacenza().last_level(); l >= 1; l--)
 | 
						||
    add(line.livgiac(l), F_LIV1+l-1 - FIRST_FIELD);
 | 
						||
 | 
						||
  add(line.codmag(), F_MAGAZZINO - FIRST_FIELD);
 | 
						||
  add(line.coddep(),F_DEPOSITO - FIRST_FIELD);
 | 
						||
  add(line.codimp(),F_CODIMP - FIRST_FIELD);
 | 
						||
  add(line.codlin(),F_CODLIN - FIRST_FIELD);
 | 
						||
  real q = line.net_requirement(bucket);
 | 
						||
  //q -= line.planned_orders(bucket);
 | 
						||
  const TCodice_um um_nulla;
 | 
						||
  const TQuantita qta(line.articolo(), um_nulla, q);
 | 
						||
  if (!q.is_zero()) // cosi' non ci sono inestetici 0.0000 sulla maschera
 | 
						||
    add(qta.val().string(),F_QUANTITA - FIRST_FIELD);
 | 
						||
  add(qta.um(),F_UM - FIRST_FIELD);
 | 
						||
  add(price.string(),F_PREZZO - FIRST_FIELD);
 | 
						||
 | 
						||
  add(line.description(),F_DESCART - FIRST_FIELD);
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMRP_docref / TMRP_docrefs 
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
const TRectype& TMRP_docref::get_doc()
 | 
						||
{
 | 
						||
  TToken_string _key;
 | 
						||
  _key.add("D");
 | 
						||
  _key.add(_annodoc);
 | 
						||
  _key.add(_codnum);
 | 
						||
  _key.add(_numdoc);
 | 
						||
  return cache().get(LF_DOC,_key);
 | 
						||
}
 | 
						||
const TRectype& TMRP_docref::get_rdoc()
 | 
						||
{
 | 
						||
  TToken_string _key;
 | 
						||
  _key.add(_codnum);
 | 
						||
  _key.add(_annodoc);
 | 
						||
  _key.add("D");
 | 
						||
  _key.add(_numdoc);
 | 
						||
  _key.add(_numrig);
 | 
						||
  return cache().get(LF_RIGHEDOC,_key);
 | 
						||
}
 | 
						||
 | 
						||
const TDate& TMRP_docref::datadoc()
 | 
						||
{
 | 
						||
  static TDate d;
 | 
						||
  return d = get_doc().get_date(DOC_DATADOC);
 | 
						||
}
 | 
						||
const TDate& TMRP_docref::datacons()
 | 
						||
{
 | 
						||
  static TDate d;
 | 
						||
  const TRectype & rdoc = get_rdoc();
 | 
						||
  d = get_rdoc().get_date(RDOC_DATACONS);
 | 
						||
  if (!d.ok())
 | 
						||
    d=get_doc().get_date(DOC_DATACONS);
 | 
						||
  return d;
 | 
						||
}
 | 
						||
const TString & TMRP_docref::tipodoc()
 | 
						||
{
 | 
						||
  static TString8 s;
 | 
						||
  return s = get_doc().get(DOC_TIPODOC);
 | 
						||
}
 | 
						||
 | 
						||
char  TMRP_docref::statodoc()
 | 
						||
{
 | 
						||
  return get_doc().get_char(DOC_STATO);
 | 
						||
}
 | 
						||
 | 
						||
TMRP_docref::TMRP_docref(int anno, const char * codnum,long numdoc,int nriga,
 | 
						||
          const char *um, const real & qta, const real &prz)
 | 
						||
{
 | 
						||
  _annodoc = anno;
 | 
						||
  _codnum = codnum;
 | 
						||
  _numdoc = numdoc;
 | 
						||
  _numrig = nriga;
 | 
						||
  _um = um;
 | 
						||
  _qta = qta;
 | 
						||
  _prz = prz;
 | 
						||
}
 | 
						||
 | 
						||
TObject* TMRP_docref::dup() const
 | 
						||
{
 | 
						||
  TMRP_docref * o = new TMRP_docref(_annodoc, _codnum, _numdoc, _numrig, _um, _qta, _prz);
 | 
						||
  return o;
 | 
						||
}
 | 
						||
 | 
						||
TObject* TMRP_internalref::dup() const
 | 
						||
{
 | 
						||
  TMRP_internalref * o = new TMRP_internalref(*this);
 | 
						||
  return o;
 | 
						||
}
 | 
						||
TMRP_internalref::TMRP_internalref(TMRP_line *line, int bucket, const real & qta):
 | 
						||
  _line(line), _qta(qta), _bucket(bucket)
 | 
						||
{ 
 | 
						||
  _um = cache().get(LF_DIST,line->articolo()).get("UM");
 | 
						||
  _date = _line->record(bucket).time().date();
 | 
						||
}
 | 
						||
 | 
						||
TMRP_internalref::TMRP_internalref(const TMRP_internalref &r):
 | 
						||
  _line(r._line), _qta(r._qta) ,_date (r._date), _um(r._um), _bucket(r._bucket)
 | 
						||
{ }
 | 
						||
 | 
						||
TObject* TMRP_docrefs::dup() const
 | 
						||
{
 | 
						||
  TMRP_docrefs * o = new TMRP_docrefs();
 | 
						||
  *o = *this;
 | 
						||
  return o;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TLav_finder   Trova la prima lavorazione di un articolo
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
class TLav_finder : public TAssoc_array
 | 
						||
{
 | 
						||
  TDecoder _lnp;
 | 
						||
  bool _keep_imp;
 | 
						||
 | 
						||
public:
 | 
						||
  void init(bool ki = TRUE);
 | 
						||
  const TString& lin2imp(const TString& lin);
 | 
						||
  TLavorazione& art2lav(const TCodice_articolo& art);
 | 
						||
  void art2magimpline(const TCodice_articolo& art,
 | 
						||
                      TString& mag, TString& imp, 
 | 
						||
                      TString& lin);
 | 
						||
 | 
						||
  TLav_finder();
 | 
						||
  virtual ~TLav_finder() { }
 | 
						||
};
 | 
						||
 | 
						||
void TLav_finder::init(bool ki)
 | 
						||
{
 | 
						||
  _keep_imp = ki;
 | 
						||
  TAssoc_array::destroy();
 | 
						||
  _lnp.destroy();
 | 
						||
}
 | 
						||
 | 
						||
TLavorazione& TLav_finder::art2lav(const TCodice_articolo& art)
 | 
						||
{
 | 
						||
  TLavorazione* lav = (TLavorazione*)objptr(art);
 | 
						||
  if (lav == NULL)
 | 
						||
  {
 | 
						||
    TDistinta_tree tree;
 | 
						||
    TArray boom;
 | 
						||
    tree.set_root(art);
 | 
						||
    tree.explode(boom, FALSE, RAGGR_EXP_UMBASE, 1, "L");
 | 
						||
    TString80 codlav;
 | 
						||
    if (boom.items() > 0)
 | 
						||
      codlav = ((TRiga_esplosione&)boom[0]).articolo();
 | 
						||
    lav = new TLavorazione(codlav);
 | 
						||
    add(art, lav);
 | 
						||
  }
 | 
						||
  return *lav;
 | 
						||
}
 | 
						||
 | 
						||
void TLav_finder::art2magimpline(const TCodice_articolo& art,
 | 
						||
                                 TString& mag, TString& imp, 
 | 
						||
                                 TString& lin)
 | 
						||
{
 | 
						||
  TLavorazione& lav = art2lav(art);
 | 
						||
  if (imp.blank() && !lin.blank())
 | 
						||
    imp = _lnp.decode(lin);
 | 
						||
  lin.cut(0);
 | 
						||
  const int ll = _keep_imp ? lav.linee() : lav.linee_standard();
 | 
						||
  for (int l = 0; l < ll; l++)
 | 
						||
  {
 | 
						||
    const TString& linea = lav.cod_linea(l);
 | 
						||
    const bool goodimp = imp.empty() || _lnp.decode(linea) == imp;
 | 
						||
    if (l == 0 || goodimp)
 | 
						||
    { lin = linea; lin.trim(); }
 | 
						||
    if (goodimp) 
 | 
						||
      break;
 | 
						||
  }
 | 
						||
  if (lin.not_empty())
 | 
						||
  {
 | 
						||
    const TLinea_prod lnp(lin) ;
 | 
						||
    imp = lnp.codimp();
 | 
						||
    mag = lnp.codmagdep();
 | 
						||
  }
 | 
						||
  else
 | 
						||
  {
 | 
						||
    if (!_keep_imp)
 | 
						||
      imp = mag = "";
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
TLav_finder::TLav_finder() : _lnp("LNP", "S6"), _keep_imp(TRUE)
 | 
						||
{ }
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMatResPlanning
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
class TMatResMask : public TCalendar_mask
 | 
						||
{
 | 
						||
  TCondizione_vendita *_condv;
 | 
						||
 | 
						||
  TSelect_color_mask _sel_color; 
 | 
						||
  int _nodist_pos;   
 | 
						||
 | 
						||
  void clear_sheets();
 | 
						||
  int num_orders();
 | 
						||
  void round_field(TMask_field& fld, bool up) const;
 | 
						||
 | 
						||
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | 
						||
  int find_pos(const TRiga_ordine& r, int& cmp, int level=COMPARE_ALL_CODES) const;
 | 
						||
  void sort_orders();
 | 
						||
  bool orders_selected(char type, const char * dacatmer,const char * acatmer);
 | 
						||
  void select_orders(char type, const char * dacatmer, const char * acatmer);
 | 
						||
 | 
						||
public:
 | 
						||
 | 
						||
  int round_date(TDate& date, bool up = FALSE) const;
 | 
						||
  int add_order_line(long forn, const TMRP_line& l, int bucket);
 | 
						||
  
 | 
						||
  TSelect_color_mask & sel() { return _sel_color; }
 | 
						||
  TMatResMask();
 | 
						||
  virtual ~TMatResMask() { }
 | 
						||
};
 | 
						||
 | 
						||
class TMatResPlanning : public TSkeleton_application
 | 
						||
{
 | 
						||
  TMRP_lines _articles;
 | 
						||
  TLav_finder _artinfo;
 | 
						||
  TMatResMask* _mask;
 | 
						||
 | 
						||
private:  
 | 
						||
  bool gross2net_logic(TMRP_line &curr_article, int bucket, bool & sc_used);
 | 
						||
  bool load_gross_requirements();
 | 
						||
  bool load_planned_orders();
 | 
						||
  bool explode_articles();
 | 
						||
 | 
						||
  bool test_codnum(const TCodice_numerazione& num, TString_array& a) const;
 | 
						||
  int test_status(const TRectype& doc, TString_array& a) const;
 | 
						||
  bool has_confirmed_status(const TRectype& doc, TToken_string & riga ) const;
 | 
						||
 | 
						||
protected:
 | 
						||
  bool preprocess_cycle(); // req iniziale dai docs
 | 
						||
  bool net_requirement_cycle();
 | 
						||
  bool build_orders();
 | 
						||
 | 
						||
  static void print_except_header(TPrinter& pr);
 | 
						||
  static void print_orders_header(TPrinter& pr);
 | 
						||
  static void print_orders_body(TPrinter& pr, TToken_string *sheetrow);
 | 
						||
  static void set_body_order_line(TPrintrow &row, TToken_string *sheetrow);
 | 
						||
  bool print_risalita(TToken_string &row, int backlevel, bool dett_ord);
 | 
						||
  bool print_risalita(const TMRP_line & line, const TDate & d, int backlevel, bool dett_ord);
 | 
						||
  int print_internal_ref(const TMRP_internalref &iref, int backlevel, bool dett_ord);
 | 
						||
  int print_gross_ref(const TMRP_line& line, int bucket);
 | 
						||
  void print_exceptions(TExceptions_array &excepts);
 | 
						||
  bool print_exceptions(TMask &m);
 | 
						||
  bool print_planning(TMask &m);
 | 
						||
  
 | 
						||
  bool ask_save();
 | 
						||
  void save_orders(TAssoc_array& docs);
 | 
						||
 | 
						||
public:
 | 
						||
  virtual bool menu(MENU_TAG mt);
 | 
						||
  virtual void main_loop();
 | 
						||
  virtual bool firm_change_enabled() const { return FALSE; }
 | 
						||
 | 
						||
  void compute();
 | 
						||
  bool print_orders();
 | 
						||
  bool emit_orders();
 | 
						||
  void risalita(const TMask & m);
 | 
						||
  int round_date(TDate &d, bool up=FALSE) const {return _mask->round_date(d, up);}
 | 
						||
};
 | 
						||
 | 
						||
TMatResPlanning& app() { return (TMatResPlanning&)main_app(); }
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMatResMask
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
class TRisalita_mask : public TAutomask
 | 
						||
{
 | 
						||
  TMRP_line* _line;
 | 
						||
  bool add_total_row(int pos, const char * um , const real & lordo, const char * umpadre ,const real & lordopadre) ;
 | 
						||
protected:
 | 
						||
  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
 | 
						||
  bool add_total_rows();
 | 
						||
static compare_rows(TSheet_field &sf, int r1, int r2);
 | 
						||
 | 
						||
public:
 | 
						||
  int add_gross_ref(const TMRP_line& line, int bucket);
 | 
						||
  int add_internal_ref(const TMRP_internalref & iref);
 | 
						||
  TRisalita_mask(TMRP_line* line, const TDate & from, const TDate & to, bool is_buck0,int extraleadtime);
 | 
						||
  virtual ~TRisalita_mask() { }
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
int TMatResMask::round_date(TDate& date, bool up) const
 | 
						||
{
 | 
						||
  // Dimensione del bucket in giorni
 | 
						||
  const int bucket_size = get_int(F_BUCKET)*get_int(F_DAYXBUCK);
 | 
						||
 | 
						||
  // Riporta la data al primo lunedi prima dell'inizio
 | 
						||
  TDate inizio = get_date(F_DADATA);
 | 
						||
  int bucket;
 | 
						||
  if (bucket_size == 31) // mese solare
 | 
						||
  {
 | 
						||
    if (up)
 | 
						||
    {
 | 
						||
      date.set_end_month();
 | 
						||
      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
 | 
						||
  {
 | 
						||
    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 = 0;
 | 
						||
    else
 | 
						||
      bucket = days / bucket_size;
 | 
						||
    if (up) // Arrotonda alla fine del bucket
 | 
						||
      date = inizio + long((bucket+1 )* bucket_size - 1 /*-  get_int(F_LASTWRKDAY)*/);
 | 
						||
    else    // Arrotonda all'inizio del bucket  
 | 
						||
      date = inizio + long(bucket * bucket_size);
 | 
						||
  }
 | 
						||
  return bucket;
 | 
						||
}
 | 
						||
 | 
						||
void TMatResMask::round_field(TMask_field& fld, bool up) const
 | 
						||
{
 | 
						||
  TDate date = fld.get();
 | 
						||
  if (date.ok())
 | 
						||
  {
 | 
						||
    round_date(date, up);
 | 
						||
    fld.set(date);
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
int TMatResMask::num_orders()
 | 
						||
{
 | 
						||
  int n=0;
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  FOR_EACH_SHEET_ROW_BACK(s, r, row)
 | 
						||
    if (!real(row->get(F_QUANTITA-FIRST_FIELD)).is_zero()) 
 | 
						||
      n++;
 | 
						||
  return n;
 | 
						||
}
 | 
						||
bool TMatResMask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | 
						||
{
 | 
						||
  const char * confirm_msg="Le attuali %d righe di ordine verranno perse. Confermare?";
 | 
						||
  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:
 | 
						||
  case F_DAYXBUCK:
 | 
						||
    if (e == fe_modify)
 | 
						||
    {
 | 
						||
      round_field(field(F_DADATA), FALSE);
 | 
						||
      round_field(field(F_ADATA), TRUE);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_NUM_ORC:
 | 
						||
  case F_TIPI_ORC:
 | 
						||
  case F_NUM_ORF:
 | 
						||
  case F_TIPI_ORF:
 | 
						||
    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 riga");
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_ORDINI:
 | 
						||
    {
 | 
						||
      TSheet_field& s = (TSheet_field&)o;
 | 
						||
      switch(e)
 | 
						||
      {
 | 
						||
      case se_query_add:
 | 
						||
        return FALSE;
 | 
						||
      default:
 | 
						||
        break;
 | 
						||
      }
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_FORNITORE:
 | 
						||
    if (jolly == 5) // codice fornitore sullo sheet ordini
 | 
						||
    {
 | 
						||
      TSheet_field& so = sfield(F_ORDINI);
 | 
						||
      TToken_string &row = so.row(so.selected());
 | 
						||
      switch(e)
 | 
						||
      {
 | 
						||
        case fe_modify:
 | 
						||
        case fe_init:
 | 
						||
        {
 | 
						||
          real qta, price;
 | 
						||
          TString codart;
 | 
						||
          long codfor;
 | 
						||
          char tipocf;
 | 
						||
          row.get(F_FORNITORE - FIRST_FIELD, codfor);
 | 
						||
          row.get(F_ORD_TYPE - FIRST_FIELD, tipocf);
 | 
						||
          
 | 
						||
          if (tipocf == 'F')
 | 
						||
            if (codfor == 0L)
 | 
						||
            {
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
              row.get(F_QUANTITA - FIRST_FIELD, qta);
 | 
						||
              row.get(F_ARTICOLO - FIRST_FIELD, codart);
 | 
						||
              find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
 | 
						||
                  "F", codfor, codart, qta, price);
 | 
						||
              row.add(price.string(), F_PREZZO - FIRST_FIELD);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        break;
 | 
						||
      }      
 | 
						||
    }
 | 
						||
    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 DLG_QUIT:
 | 
						||
    if (e == fe_button && jolly == 0L)
 | 
						||
    {
 | 
						||
      const int it=num_orders();
 | 
						||
      if (it > 0 && !yesno_box(confirm_msg, it))
 | 
						||
        return FALSE;
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case DLG_CANCEL:
 | 
						||
    if (e == fe_button)
 | 
						||
      if (jolly == 0L)
 | 
						||
      {
 | 
						||
        TSheet_field& s = sfield(F_ORDINI);
 | 
						||
        const int it=s.items();
 | 
						||
        if (it==0 || yesno_box(confirm_msg, it))
 | 
						||
        {
 | 
						||
          enable(-1);
 | 
						||
          s.destroy();
 | 
						||
          s.force_update();
 | 
						||
        } else
 | 
						||
          return FALSE;
 | 
						||
      }
 | 
						||
    break;
 | 
						||
  case DLG_ELABORA:
 | 
						||
    if (e == fe_button && check_fields())
 | 
						||
    {
 | 
						||
      TSheet_field& s = sfield(F_ORDINI);
 | 
						||
      const int it=s.items();
 | 
						||
      if (it==0 || yesno_box(confirm_msg, it))
 | 
						||
      {
 | 
						||
        s.destroy();
 | 
						||
        app().compute();
 | 
						||
        enable(DLG_SAVEREC, s.items() > 0 && !get_bool(F_DISABLESAVE));
 | 
						||
        enable(-G_PREPROCESS, s.items() == 0);
 | 
						||
        sort_orders();
 | 
						||
        s.set_focus();
 | 
						||
      }
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_RISALITA:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      /*TSheet_field & sf= m.sfield(F_ORDINI);
 | 
						||
      TToken_string & row=sf.row(sf.selected());
 | 
						||
      TDate datacons(row.get(sf.cid2index(F_DATACONS)));*/
 | 
						||
      app().risalita(*this);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case F_RESORT_ORDINI:
 | 
						||
    if (e == fe_button)
 | 
						||
      sort_orders();
 | 
						||
    break;
 | 
						||
  case F_SELECT_ORD:
 | 
						||
    if (e == fe_button)
 | 
						||
      if (*get(F_SEL_ORD_TYPE)=='F')
 | 
						||
        select_orders('F', get(F_OF_DAGRMERC), get(F_OF_AGRMERC));
 | 
						||
      else
 | 
						||
        select_orders('P', get(F_OP_DAGRMERC), get(F_OP_AGRMERC));
 | 
						||
    break;
 | 
						||
  case DLG_SAVEREC:
 | 
						||
    if (e == fe_button && check_fields())
 | 
						||
    {
 | 
						||
      if (!app().emit_orders())
 | 
						||
        message_box("Nessun ordine generato");
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case DLG_PRINT:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      app().print_orders();
 | 
						||
      return FALSE;
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  case DLG_PROFILE:
 | 
						||
    if (e == fe_modify)
 | 
						||
    {
 | 
						||
      clear_sheets();
 | 
						||
      enable(-1);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  default:
 | 
						||
    break;
 | 
						||
  };
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void TMatResMask::clear_sheets()
 | 
						||
{
 | 
						||
  TSheet_field &sa=sfield(F_ORDINI);
 | 
						||
  if (sa.items()>0)
 | 
						||
  {
 | 
						||
    sa.destroy();   
 | 
						||
    sa.force_update();   
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
int TMatResMask::find_pos(const TRiga_ordine& r, int& cmp, int level) const
 | 
						||
{
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  TString_array& a = s.rows_array();
 | 
						||
  cmp = +1;
 | 
						||
  for (int i = 0; i < a.items(); i++)
 | 
						||
  {
 | 
						||
    const TRiga_ordine& riga = (const TRiga_ordine&)a[i];
 | 
						||
    cmp = r.compare(riga, level);
 | 
						||
    if (cmp == 0)
 | 
						||
      break;
 | 
						||
  }
 | 
						||
  return i;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// Aggiunge le righe d'ordine allo sheet
 | 
						||
int TMatResMask::add_order_line(long forn, const TMRP_line& line, int bucket)
 | 
						||
{
 | 
						||
  int pos;
 | 
						||
  TMRP_time deliv_time = line.time(bucket);
 | 
						||
  TMRP_time plan_time;
 | 
						||
  if (get_bool(F_IGN_LDTIME))
 | 
						||
    plan_time = line.time(bucket);
 | 
						||
  else
 | 
						||
    line.lead_time(bucket, plan_time, TRUE);
 | 
						||
  plan_time.sub_time(get_int(F_XTRA_PLTIME));
 | 
						||
 | 
						||
  TDate datadoc = plan_time.date();
 | 
						||
  round_date(datadoc);
 | 
						||
  TDate datacons = deliv_time.date();
 | 
						||
  round_date(datacons);
 | 
						||
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  TString_array& a = s.rows_array();
 | 
						||
  real q = line.net_requirement(bucket);  // Fabbisogno netto
 | 
						||
  TMRP_docrefs * pl_orders=NULL,*sc_orders=NULL;
 | 
						||
  if (get_bool(F_RESCHEDULING))
 | 
						||
    sc_orders = line.record(bucket).scheduls_refs();
 | 
						||
  pl_orders = line.record(bucket).plans_refs();
 | 
						||
  // le proposte di rescheduling sono da mettere su uno sheet a parte...
 | 
						||
  int nref = pl_orders != NULL ? pl_orders->items() : 0;
 | 
						||
  real qtaplan;   // Quantit<69> da pianificare
 | 
						||
  do 
 | 
						||
  {
 | 
						||
    TRiga_ordine* r = new TRiga_ordine(datadoc, datacons, forn, line, bucket, ZERO);
 | 
						||
    // Setta un codice numerazione (provvisorio) in base al tipo di ordine
 | 
						||
    const char ot = *r->get(F_ORD_TYPE - FIRST_FIELD);
 | 
						||
    r->add(get(ot == 'F' ? F_NUM_FORN : F_NUM_PROD) , F_DOCCODNUM - FIRST_FIELD);
 | 
						||
    
 | 
						||
    nref--;
 | 
						||
    if (nref >= 0)
 | 
						||
    {            
 | 
						||
      const TString& codnum = pl_orders->get_ref(nref).codnumdoc();
 | 
						||
      if (codnum == get(F_NUM_PROD) || codnum == get(F_NUM_FORN))
 | 
						||
      {
 | 
						||
        qtaplan = pl_orders->get_ref(nref).qta_residua();
 | 
						||
        qtaplan.round(5);
 | 
						||
        q.round(5);
 | 
						||
        qtaplan = q - qtaplan; // tengo solo in parte questo ordine ...
 | 
						||
        r->add(pl_orders->get_ref(nref).annodoc() , F_DOCANNODOC - FIRST_FIELD);
 | 
						||
        r->add(pl_orders->get_ref(nref).codnumdoc() , F_DOCCODNUM - FIRST_FIELD);
 | 
						||
        r->add(pl_orders->get_ref(nref).numdoc() , F_DOCNUM - FIRST_FIELD);
 | 
						||
        r->add(pl_orders->get_ref(nref).numrig() , F_DOCNRIGA - FIRST_FIELD);
 | 
						||
        r->add(qtaplan.is_zero() ? " " : qtaplan.string(), F_QUANTITA - FIRST_FIELD);
 | 
						||
        r->add(pl_orders->get_ref(nref).datacons().string() , F_DATACONS - FIRST_FIELD);
 | 
						||
        r->add(pl_orders->get_ref(nref).datadoc().string(), F_DATADOC - FIRST_FIELD);
 | 
						||
        q = ZERO;
 | 
						||
      } else
 | 
						||
        r->add(" " , F_QUANTITA - FIRST_FIELD);
 | 
						||
    } 
 | 
						||
    else 
 | 
						||
    {
 | 
						||
      r->add(q.is_zero() ? " " : q.string() , F_QUANTITA - FIRST_FIELD);
 | 
						||
      qtaplan = ZERO;
 | 
						||
    }
 | 
						||
    if ((nref >= 0 && (!qtaplan.is_zero() || get_bool(F_ALL_ORDERSCHANGES))) || // correggo un vecchio ordine ... 
 | 
						||
      (nref < 0 && !q.is_zero()) || // ... o ne genero uno nuovo
 | 
						||
      get_bool(F_ALL_MRPLINES)) // ...o voglio tutte le righe
 | 
						||
    {
 | 
						||
      int cmp = -1;
 | 
						||
      if (nref >= 0 && qtaplan < ZERO)
 | 
						||
        pos = find_pos(*r, cmp, COMPARE_COMPLETE);
 | 
						||
      else
 | 
						||
        pos = find_pos(*r, cmp, COMPARE_ALL_CODES);
 | 
						||
      
 | 
						||
      if (cmp == 0)
 | 
						||
      {
 | 
						||
        // RIGA GIA' PRESENTE
 | 
						||
        TRiga_ordine& riga = (TRiga_ordine&)a[pos];
 | 
						||
        const TString & codnum = riga.get(F_DOCCODNUM - FIRST_FIELD);
 | 
						||
//        if (!(codnum != get(F_NUM_PROD) && codnum != get(F_NUM_FORN)))
 | 
						||
        if (codnum == get(F_NUM_PROD) || codnum == get(F_NUM_FORN))  // Guy was here!
 | 
						||
          riga += *r;
 | 
						||
        delete r;
 | 
						||
        const TString & qta2or = riga.get(F_QUANTITA - FIRST_FIELD);
 | 
						||
        if (qta2or[0]==' ' && !
 | 
						||
          ((nref >= 0  && get_bool(F_ALL_ORDERSCHANGES)) // correzione ..
 | 
						||
          || get_bool(F_ALL_MRPLINES)))                  // ... o voglio tutte le righe
 | 
						||
        {
 | 
						||
          // riabilita i campi del doc
 | 
						||
          s.enable_cell(pos, F_ORD_TYPE - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_DATADOC - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_DATACONS - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_FORNITORE - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_MAGAZZINO - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_DEPOSITO - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_CODIMP - FIRST_FIELD);
 | 
						||
          s.enable_cell(pos, F_CODLIN - FIRST_FIELD);
 | 
						||
          a.destroy(pos); // no null rows if not desired
 | 
						||
        }
 | 
						||
      }
 | 
						||
      else
 | 
						||
      {
 | 
						||
        // RIGA DA AGGIUNGERE
 | 
						||
        a.add(r);
 | 
						||
        pos = a.items()-1;
 | 
						||
      }
 | 
						||
      if (nref >= 0)
 | 
						||
      {
 | 
						||
        const TString & codnum = pl_orders->get_ref(nref).codnumdoc();
 | 
						||
        TRiga_ordine& riga = (TRiga_ordine&)a[pos];
 | 
						||
        riga.add(codnum, F_DOCCODNUM - FIRST_FIELD);
 | 
						||
        riga.add(pl_orders->get_ref(nref).annodoc() , F_DOCANNODOC - FIRST_FIELD);
 | 
						||
        riga.add(pl_orders->get_ref(nref).numdoc() , F_DOCNUM - FIRST_FIELD);
 | 
						||
        riga.add(pl_orders->get_ref(nref).numrig() , F_DOCNRIGA - FIRST_FIELD);
 | 
						||
 | 
						||
        if (codnum != get(F_NUM_PROD) && codnum != get(F_NUM_FORN))
 | 
						||
          riga.add(" ", F_QUANTITA - FIRST_FIELD);
 | 
						||
        // disabilita i campi del doc
 | 
						||
        s.disable_cell(pos, F_ORD_TYPE - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_DATADOC - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_DATACONS - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_FORNITORE - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_MAGAZZINO - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_DEPOSITO - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_CODIMP - FIRST_FIELD);
 | 
						||
        s.disable_cell(pos, F_CODLIN - FIRST_FIELD);
 | 
						||
      }
 | 
						||
    }
 | 
						||
    else
 | 
						||
        delete r;
 | 
						||
  } while (nref >= 0 /*&& q > ZERO*/);
 | 
						||
  if (line.final_product())
 | 
						||
  {
 | 
						||
    COLOR back = _sel_color.get_back_color(_nodist_pos);
 | 
						||
    COLOR fore = _sel_color.get_fore_color(_nodist_pos);
 | 
						||
    
 | 
						||
    s.set_back_and_fore_color(back, fore, pos);
 | 
						||
  }
 | 
						||
  return pos;
 | 
						||
}
 | 
						||
 | 
						||
static int order_compare(TSheet_field &s,int i1,int i2, int sorttype)
 | 
						||
{
 | 
						||
  TMask &m=s.mask();
 | 
						||
  const bool ascending=!m.get_bool(F_SORT_ORDER);
 | 
						||
  const TRiga_ordine& r1 = (TRiga_ordine&)s.row(i1);
 | 
						||
  const TRiga_ordine& r2 = (TRiga_ordine&)s.row(i2);
 | 
						||
  return r1.compare(r2,sorttype,ascending);
 | 
						||
}
 | 
						||
static int order_compareDTFA(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_DTFA);}
 | 
						||
static int order_compareDATF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_DATF);}
 | 
						||
static int order_compareATFD(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_ATFD);}
 | 
						||
static int order_compareADTF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_ADTF);}
 | 
						||
static int order_compareTFAD(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TFAD);}
 | 
						||
static int order_compareTFDA(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TFDA);}
 | 
						||
static int order_compareTDFA(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TDFA);}
 | 
						||
static int order_compareTDAF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TDAF);}
 | 
						||
static int order_compareTAFD(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TAFD);}
 | 
						||
static int order_compareTADF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TADF);}
 | 
						||
 | 
						||
static int order_compareCTFA(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_CTFA);}
 | 
						||
static int order_compareCATF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_CATF);}
 | 
						||
static int order_compareATFC(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_ATFC);}
 | 
						||
static int order_compareACTF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_ACTF);}
 | 
						||
static int order_compareTFAC(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TFAC);}
 | 
						||
static int order_compareTFCA(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TFCA);}
 | 
						||
static int order_compareTCFA(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TCFA);}
 | 
						||
static int order_compareTCAF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TCAF);}
 | 
						||
static int order_compareTAFC(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TAFC);}
 | 
						||
static int order_compareTACF(TSheet_field &s,int i1,int i2)
 | 
						||
{  return order_compare(s,i1,i2,COMPARE_TACF);}
 | 
						||
 | 
						||
void TMatResMask::sort_orders()
 | 
						||
{ 
 | 
						||
  TWait_cursor clessidra;
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  TSheet_field& a = s;
 | 
						||
  int choose  = -(get_int(F_SORT)+ (get_bool(F_DATE_SORT_ORDER) ? 10 : 1));
 | 
						||
  switch (choose)
 | 
						||
  {
 | 
						||
    case COMPARE_ATFD:   a.sort(order_compareATFD); break;
 | 
						||
    case COMPARE_ADTF:   a.sort(order_compareADTF); break;
 | 
						||
    case COMPARE_DTFA:   a.sort(order_compareDTFA); break;
 | 
						||
    case COMPARE_DATF:   a.sort(order_compareDATF); break;
 | 
						||
    case COMPARE_TFAD:   a.sort(order_compareTFAD); break;
 | 
						||
    case COMPARE_TFDA:   a.sort(order_compareTFDA); break;
 | 
						||
    case COMPARE_TAFD:   a.sort(order_compareTAFD); break;
 | 
						||
    case COMPARE_TADF:   a.sort(order_compareTADF); break;
 | 
						||
    case COMPARE_TDAF:   a.sort(order_compareTDAF); break;
 | 
						||
    case COMPARE_TDFA:   a.sort(order_compareTDFA); break;
 | 
						||
 | 
						||
    case COMPARE_ATFC:   a.sort(order_compareATFC); break;
 | 
						||
    case COMPARE_ACTF:   a.sort(order_compareACTF); break;
 | 
						||
    case COMPARE_CTFA:   a.sort(order_compareCTFA); break;
 | 
						||
    case COMPARE_CATF:   a.sort(order_compareCATF); break;
 | 
						||
    case COMPARE_TFAC:   a.sort(order_compareTFAC); break;
 | 
						||
    case COMPARE_TFCA:   a.sort(order_compareTFCA); break;
 | 
						||
    case COMPARE_TAFC:   a.sort(order_compareTAFC); break;
 | 
						||
    case COMPARE_TACF:   a.sort(order_compareTACF); break;
 | 
						||
    case COMPARE_TCAF:   a.sort(order_compareTCAF); break;
 | 
						||
    case COMPARE_TCFA:   a.sort(order_compareTCFA); break;
 | 
						||
    default: 
 | 
						||
      return;
 | 
						||
  }
 | 
						||
  s.force_update();
 | 
						||
}
 | 
						||
 | 
						||
bool TMatResMask::orders_selected(char type, const char * dacatmer,const char * acatmer)
 | 
						||
{ 
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  const int it=s.items();
 | 
						||
  for (int r=0; r< it; r++)
 | 
						||
  {
 | 
						||
    if ( *s.cell(r, s.cid2index(F_ORD_TYPE))==type 
 | 
						||
      &&  *s.cell(r, s.cid2index(F_SELECTED))=='X')
 | 
						||
      if (*dacatmer <= ' ' || 
 | 
						||
          cache().get(LF_ANAMAG,s.cell(r, s.cid2index(F_ARTICOLO))).get(ANAMAG_GRMERC).left(3) >= dacatmer)
 | 
						||
        if (*acatmer <= ' ' || 
 | 
						||
            cache().get(LF_ANAMAG,s.cell(r, s.cid2index(F_ARTICOLO))).get(ANAMAG_GRMERC).left(3) <= acatmer)
 | 
						||
          return TRUE;
 | 
						||
  }
 | 
						||
  return FALSE;
 | 
						||
}
 | 
						||
 | 
						||
void TMatResMask::select_orders(char type, const char * dacatmer,const char * acatmer)
 | 
						||
{ 
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  bool on=!orders_selected(type, dacatmer, acatmer);
 | 
						||
  const int it=s.items();
 | 
						||
  for (int r=0; r< it; r++)
 | 
						||
  {
 | 
						||
    if ( *s.cell(r, s.cid2index(F_ORD_TYPE))==type )
 | 
						||
      if (*dacatmer <= ' ' || 
 | 
						||
          cache().get(LF_ANAMAG,s.cell(r, s.cid2index(F_ARTICOLO))).get(ANAMAG_GRMERC).left(3) >= dacatmer)
 | 
						||
        if (*acatmer <= ' ' || 
 | 
						||
            cache().get(LF_ANAMAG,s.cell(r, s.cid2index(F_ARTICOLO))).get(ANAMAG_GRMERC).left(3) <= acatmer)
 | 
						||
        {
 | 
						||
          s.row(r).add(on ? "X" : " ", s.cid2index(F_SELECTED));
 | 
						||
          s.force_update(r);
 | 
						||
        }
 | 
						||
  }
 | 
						||
  TString msg=format("Ordini %s %s",type=='F' ? "fornitore" : "di produzione" ,on ? "selezionati" :"de-selezionati");
 | 
						||
  xvt_statbar_set(msg);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
TMatResMask::TMatResMask() : TCalendar_mask("mr2100a"), _sel_color(sfield(F_ORDINI)) 
 | 
						||
{
 | 
						||
  _condv = NULL;
 | 
						||
  TSheet_field& sf = sfield(F_ORDINI);
 | 
						||
  
 | 
						||
  livelli_giacenza().set_sheet_columns(sf, F_LIV1);
 | 
						||
 | 
						||
  TConfig ini(CONFIG_DITTA, "mg");
 | 
						||
  if (!ini.get_bool("GESDEPOSITI", "mg"))
 | 
						||
  {
 | 
						||
    sf.delete_column(F_DEPOSITO);
 | 
						||
    sf.sheet_mask().hide(F_DEPOSITO);
 | 
						||
  }
 | 
						||
 | 
						||
  if (!ini.get_bool("GESTIMPIANTI", "mr"))
 | 
						||
  {
 | 
						||
    sf.delete_column(F_CODIMP); // Elimina colonna impianto
 | 
						||
    sf.sheet_mask().hide(F_CODIMP);
 | 
						||
    sf.sheet_mask().hide(F_DESCIMP);
 | 
						||
    
 | 
						||
    disable(F_NOIMP); // Forza l'ignoramento degli impianti
 | 
						||
    set(F_NOIMP, "X");
 | 
						||
  }                                  
 | 
						||
  _nodist_pos =_sel_color.add_color_def("NODIST", "Art.pianificati senza distinta", COLOR_YELLOW, COLOR_BLACK);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TRisalita_mask : 
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
TRisalita_mask::TRisalita_mask(TMRP_line* line, const TDate &fromdate, const TDate &todate, bool isbuck0, int extraleadtime)
 | 
						||
  : TAutomask("mr2100b.msk"), _line (line)
 | 
						||
{
 | 
						||
  TSheet_field& sf = sfield(F_ORDINI);
 | 
						||
  sf.disable();
 | 
						||
  livelli_giacenza().set_sheet_columns(sf, F_LIV1);
 | 
						||
  livelli_giacenza().set_mask_fields(*this, F_LIV1);
 | 
						||
  TConfig ini(CONFIG_DITTA, "mg");
 | 
						||
  if (!ini.get_bool("GESDEPOSITI", "mg"))
 | 
						||
  {
 | 
						||
    sf.delete_column(F_DEPOSITO);
 | 
						||
    sf.sheet_mask().hide(F_DEPOSITO);
 | 
						||
  }
 | 
						||
 | 
						||
  if (!ini.get_bool("GESTIMPIANTI", "mr"))
 | 
						||
  {
 | 
						||
    sf.delete_column(F_CODIMP); // Elimina colonna impianto
 | 
						||
    sf.sheet_mask().hide(F_CODIMP);
 | 
						||
    sf.sheet_mask().hide(F_DESCIMP);
 | 
						||
  }
 | 
						||
  TToken_string cod = line->articolo();
 | 
						||
  set(F_ARTICOLO,cod);
 | 
						||
  set(F_DESCART,line->description());
 | 
						||
  cod.add("1");
 | 
						||
  set(F_UM,cache().get(LF_UMART,cod).get("UM"));
 | 
						||
  for (int l = livelli_giacenza().last_level(); l>=1 ; l--)
 | 
						||
    set(F_LIV1+l-1, line->livgiac(l));
 | 
						||
  
 | 
						||
  bool has_internal_refs=FALSE;
 | 
						||
  real lordo,netto,plan,sched; 
 | 
						||
  for (int b = line->last_bucket(); b >= 0 ; b--)
 | 
						||
  {
 | 
						||
//    TMRP_time dtime = line->record(b).time();
 | 
						||
//    if (extraleadtime && line->sons() == 0)
 | 
						||
//      dtime.sub_time(extraleadtime);
 | 
						||
//    const TDate &d  = dtime.date();
 | 
						||
    const TDate &d = line->record(b).time().date();
 | 
						||
    if (isbuck0 || d >= fromdate)
 | 
						||
    {
 | 
						||
      set(F_FABB_DADATA, isbuck0 ? "" : fromdate);
 | 
						||
      set(F_FABB_ADATA, todate);
 | 
						||
      set(F_FABB_GIAC, line->record(b).on_hand().string());
 | 
						||
      if (d <= todate)
 | 
						||
      {
 | 
						||
        lordo += line->gross_requirement(b);
 | 
						||
        netto += line->net_requirement(b);
 | 
						||
        plan  += line->planned_orders(b);
 | 
						||
        sched += line->sched_receipts(b);
 | 
						||
        TMRP_internalrefs *irefs = line->record(b).internal_refs();
 | 
						||
        if (irefs)
 | 
						||
        {
 | 
						||
          int ir = 0;
 | 
						||
          while (ir < irefs->items())
 | 
						||
          {
 | 
						||
            TMRP_internalref &iref = irefs->get_ref(ir);
 | 
						||
            add_internal_ref(iref);
 | 
						||
            ir ++;
 | 
						||
          }
 | 
						||
          has_internal_refs = TRUE;
 | 
						||
        } else {
 | 
						||
          add_gross_ref(*line,b);
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  if (!has_internal_refs)
 | 
						||
    for (int c = F_ARTICOLO; c < F_DOCANNODOC; c++)
 | 
						||
      sf.delete_column(c);
 | 
						||
  add_total_rows();
 | 
						||
 | 
						||
  set(F_FABB_LORDO,lordo.string());
 | 
						||
  set(F_FABB_PIAN, plan.string());
 | 
						||
  set(F_FABB_SCHED, sched.string());
 | 
						||
  netto -= plan;
 | 
						||
  set(F_TOPLAN, netto.string());
 | 
						||
  netto += plan + sched;
 | 
						||
  set(F_FABB_NETTO,netto.string());
 | 
						||
}
 | 
						||
 | 
						||
bool TRisalita_mask::add_total_rows() 
 | 
						||
{
 | 
						||
  TSheet_field& sf = sfield(F_ORDINI);
 | 
						||
  if (sf.items() == 0)
 | 
						||
    return FALSE;
 | 
						||
  sf.sort(compare_rows);
 | 
						||
  TString codice(get(F_ARTICOLO)), codpadre, um;
 | 
						||
  const TCodice_um um_nulla;
 | 
						||
  TQuantita totale(codice, um_nulla, ZERO);
 | 
						||
  TQuantita parziale(totale), qta, lordopadre;
 | 
						||
  real val;
 | 
						||
 | 
						||
  int padri(0), riga(0);
 | 
						||
  TToken_string * row;
 | 
						||
  TString_array& ra = sf.rows_array();
 | 
						||
  while (row = (TToken_string *)ra.objptr(riga++))
 | 
						||
  {
 | 
						||
    if (codpadre != row->get(sf.cid2index(F_ARTICOLO)))
 | 
						||
    {
 | 
						||
      if (!codpadre.blank())
 | 
						||
      {
 | 
						||
        add_total_row(riga++, parziale.um(), parziale.val(), lordopadre.um(), lordopadre.val());
 | 
						||
        parziale.set_val(ZERO);
 | 
						||
        lordopadre.set_articolo(codpadre, um_nulla);
 | 
						||
        lordopadre.set_val(ZERO);
 | 
						||
        padri++;
 | 
						||
      }
 | 
						||
      codpadre = row->get(sf.cid2index(F_ARTICOLO));
 | 
						||
    }
 | 
						||
    // fabbisogno articolo
 | 
						||
    row->get(sf.cid2index(F_FABBISOGNO), val);
 | 
						||
    row->get(sf.cid2index(F_UMFABB), um);
 | 
						||
    qta.set(codice, um, val);
 | 
						||
    parziale += qta;
 | 
						||
    totale += qta;
 | 
						||
    // qta padre
 | 
						||
    row->get(sf.cid2index(F_QUANTITA), val);
 | 
						||
    row->get(sf.cid2index(F_UM), um);
 | 
						||
    qta.set(codpadre.blank() ? codice : codpadre, um, val);
 | 
						||
    lordopadre += qta;
 | 
						||
  }
 | 
						||
  add_total_row(riga++, parziale.um(), parziale.val(), lordopadre.um(), lordopadre.val());
 | 
						||
  if (padri > 0)
 | 
						||
    add_total_row(riga, totale.um(), totale.val(), "", ZERO);
 | 
						||
  sf.force_update();
 | 
						||
  return padri != 0;
 | 
						||
}
 | 
						||
 | 
						||
TRisalita_mask::compare_rows(TSheet_field &sf, int r1, int r2)
 | 
						||
{
 | 
						||
  TToken_string & s1 = sf.row(r1);
 | 
						||
  TToken_string & s2 = sf.row(r2);
 | 
						||
  static TString ss1, ss2;
 | 
						||
  s1.get(sf.cid2index(F_ARTICOLO), ss1);
 | 
						||
  s2.get(sf.cid2index(F_ARTICOLO), ss2);
 | 
						||
  int d = ss1.compare(ss2);
 | 
						||
  if (d == 0)
 | 
						||
  {
 | 
						||
    TDate d1,d2;
 | 
						||
    s1.get(sf.cid2index(F_DATACONS), ss1);
 | 
						||
    s2.get(sf.cid2index(F_DATACONS), ss2);
 | 
						||
    d1 = ss1;
 | 
						||
    d2 = ss2;
 | 
						||
    d = int (d1 - d2);
 | 
						||
    if (d == 0)
 | 
						||
    {
 | 
						||
      s1.get(sf.cid2index(F_FABBISOGNO), ss1);
 | 
						||
      s2.get(sf.cid2index(F_FABBISOGNO), ss2);
 | 
						||
      real r1(ss1),r2(ss2);
 | 
						||
      r1 -= r2;
 | 
						||
      d = r1.sign();
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return d;
 | 
						||
}
 | 
						||
 | 
						||
bool TRisalita_mask::add_total_row(int pos, const char * um , const real & lordo, const char * umpadre ,const real & lordopadre) 
 | 
						||
{
 | 
						||
  TSheet_field& sf = sfield(F_ORDINI);
 | 
						||
  sf.insert(--pos);
 | 
						||
  TToken_string & row = sf.row(pos);
 | 
						||
  row.add(um, sf.cid2index(F_UMFABB));
 | 
						||
  row.add(lordo.string(), sf.cid2index(F_FABBISOGNO));
 | 
						||
  row.add(umpadre, sf.cid2index(F_UM));
 | 
						||
  row.add(lordopadre.string(), sf.cid2index(F_QUANTITA));
 | 
						||
  sf.disable_row(pos);
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
bool TRisalita_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
 | 
						||
{
 | 
						||
  switch (o.dlg())
 | 
						||
  {
 | 
						||
    case F_RISALITA:
 | 
						||
    if (e == fe_button)
 | 
						||
    {
 | 
						||
      app().risalita(*this);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
  }
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
int TRisalita_mask::add_internal_ref(const TMRP_internalref &iref)
 | 
						||
{
 | 
						||
  const TMRP_line& line=*iref.line();
 | 
						||
  int bucket=iref.bucket();
 | 
						||
 | 
						||
  const TMRP_time &deliv_time = line.time(bucket);
 | 
						||
  TMRP_time doc_time;
 | 
						||
  line.lead_time(bucket,doc_time, TRUE);
 | 
						||
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  TString_array& a = s.rows_array();
 | 
						||
  TToken_string dockey;
 | 
						||
  TMRP_docrefs * gr_refs= line.record(bucket).requirements_refs();
 | 
						||
  int grref = gr_refs ? gr_refs->items() : 0;
 | 
						||
  TMRP_docrefs * pl_refs= line.record(bucket).plans_refs();
 | 
						||
  int plref = pl_refs ? pl_refs->items() : 0;
 | 
						||
  TMRP_docrefs * sr_refs = line.record(bucket).scheduls_refs();
 | 
						||
  int srref = sr_refs ? sr_refs->items() : 0;
 | 
						||
  real totreq = line.net_requirement(bucket);
 | 
						||
  totreq += line.sched_receipts(bucket);
 | 
						||
  real qtaplan(totreq);
 | 
						||
  real qtareq(totreq);
 | 
						||
  do {
 | 
						||
    TCodice_um um;
 | 
						||
    TToken_string r;
 | 
						||
    real q = iref.qta();
 | 
						||
    TMRP_docref * docref = NULL;
 | 
						||
    if (grref > 0)
 | 
						||
      docref = gr_refs->get_ref_ptr(--grref);
 | 
						||
    else if (srref > 0)
 | 
						||
      docref = sr_refs->get_ref_ptr(--srref);
 | 
						||
    else if (plref > 0)
 | 
						||
      docref = pl_refs->get_ref_ptr(--plref);
 | 
						||
    if (docref)
 | 
						||
    {
 | 
						||
      dockey.add("D",0);
 | 
						||
      dockey.add(docref->annodoc(),1);
 | 
						||
      dockey.add(docref->codnumdoc(),2);
 | 
						||
      dockey.add(docref->numdoc(),3);
 | 
						||
      //const TString & codnum = docref->codnumdoc();
 | 
						||
      qtaplan = docref->qta_residua();
 | 
						||
      qtaplan.round(5);
 | 
						||
      TQuantita qta(line.articolo(), docref->um(), docref->qta_residua());
 | 
						||
      qta.convert2umbase();
 | 
						||
      qtareq = qtareq - qta.val();
 | 
						||
      qtareq.round(5);
 | 
						||
      // qtareq = qtareq - qtaplan;
 | 
						||
      r.add(cache().get(LF_DOC,dockey).get(DOC_DATADOC),F_DATADOC - FIRST_FIELD); // data del documento di rif.
 | 
						||
      r.add(docref->annodoc() , F_DOCANNODOC - FIRST_FIELD);
 | 
						||
      r.add(docref->codnumdoc() , F_DOCCODNUM - FIRST_FIELD);
 | 
						||
      r.add(docref->numdoc() , F_DOCNUM - FIRST_FIELD);
 | 
						||
      r.add(docref->numrig() , F_DOCNRIGA - FIRST_FIELD);
 | 
						||
      r.add(qtaplan.string() , F_QUANTITA - FIRST_FIELD);
 | 
						||
      um = docref->um();
 | 
						||
    } 
 | 
						||
    else
 | 
						||
    {
 | 
						||
      qtaplan = qtareq;
 | 
						||
      r.add(doc_time.date().string(), F_DATADOC - FIRST_FIELD);
 | 
						||
    }
 | 
						||
    TQuantita qta(line.articolo(), um, qtaplan);
 | 
						||
    r.add(get(F_UM), F_UMFABB - FIRST_FIELD);
 | 
						||
    r.add(deliv_time.date().string(), F_DATACONS - FIRST_FIELD);
 | 
						||
    r.add(" ",F_FORNITORE - FIRST_FIELD);
 | 
						||
    r.add(line.articolo(),F_ARTICOLO - FIRST_FIELD);
 | 
						||
    const TString& liv = line.livgiac();
 | 
						||
    for (int l = livelli_giacenza().last_level(); l >= 1; l--)
 | 
						||
      r.add(line.livgiac(l), F_LIV1+l-1 - FIRST_FIELD);
 | 
						||
    r.add(line.codmag(), F_MAGAZZINO - FIRST_FIELD);
 | 
						||
    r.add(line.coddep(), F_DEPOSITO - FIRST_FIELD);
 | 
						||
    r.add(line.codimp(),F_CODIMP - FIRST_FIELD);
 | 
						||
    r.add(line.codlin(),F_CODLIN - FIRST_FIELD);
 | 
						||
    r.add("",F_PREZZO - FIRST_FIELD);
 | 
						||
    r.add(line.description(),F_DESCART - FIRST_FIELD);
 | 
						||
    r.add(qta.val().string(),F_QUANTITA - FIRST_FIELD);
 | 
						||
    r.add(qta.um(),F_UM - FIRST_FIELD);
 | 
						||
    // aggiunge il fabbisogno
 | 
						||
    qta.convert2umbase();
 | 
						||
    q = iref.qta() * qta.val() / totreq;
 | 
						||
    r.add(q.string(), F_FABBISOGNO - FIRST_FIELD);
 | 
						||
 | 
						||
    a.add(r);
 | 
						||
  } while ((grref > 0 || srref > 0 || plref > 0) && qtareq > ZERO);
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
int TRisalita_mask::add_gross_ref(const TMRP_line& line, int bucket)
 | 
						||
{
 | 
						||
  TSheet_field& s = sfield(F_ORDINI);
 | 
						||
  TString_array& a = s.rows_array();
 | 
						||
 | 
						||
  TToken_string dockey;
 | 
						||
  real totreq, qtaplan, qtareq;
 | 
						||
  TMRP_time deliv_time = line.time(bucket);
 | 
						||
  TMRP_time doc_time;
 | 
						||
  line.lead_time(bucket,doc_time, TRUE);
 | 
						||
  TToken_string r;
 | 
						||
  //const TString & codnum = docref->codnumdoc();
 | 
						||
  TMRP_docref * docref = NULL;
 | 
						||
  TMRP_docrefs * gr_refs= line.record(bucket).requirements_refs();
 | 
						||
  int grref = gr_refs ? gr_refs->items() : 0;
 | 
						||
  while (grref)
 | 
						||
  {
 | 
						||
    docref = gr_refs->get_ref_ptr(--grref);
 | 
						||
    qtaplan = docref->qta_residua();
 | 
						||
    qtaplan.round(5);
 | 
						||
    dockey.add("D",0);
 | 
						||
    dockey.add(docref->annodoc(),1);
 | 
						||
    dockey.add(docref->codnumdoc(),2);
 | 
						||
    dockey.add(docref->numdoc(),3);
 | 
						||
    r.add(cache().get(LF_DOC,dockey).get(DOC_DATADOC),F_DATADOC - FIRST_FIELD); // data del documento di rif.
 | 
						||
    r.add(docref->annodoc(), F_DOCANNODOC - FIRST_FIELD);
 | 
						||
    r.add(docref->codnumdoc(), F_DOCCODNUM - FIRST_FIELD);
 | 
						||
    r.add(docref->numdoc(), F_DOCNUM - FIRST_FIELD);
 | 
						||
    r.add(docref->numrig(), F_DOCNRIGA - FIRST_FIELD);
 | 
						||
    r.add(deliv_time.date().string(), F_DATACONS - FIRST_FIELD);
 | 
						||
    r.add(" ",F_FORNITORE - FIRST_FIELD);
 | 
						||
    const TCodice_um um_nulla;
 | 
						||
    const TQuantita qta(line.articolo(), docref->um(), qtaplan);
 | 
						||
    r.add(qta.val().string(),F_QUANTITA - FIRST_FIELD);
 | 
						||
    r.add(qta.um(),F_UM - FIRST_FIELD);
 | 
						||
    r.add(qtaplan.string(), F_FABBISOGNO - FIRST_FIELD);
 | 
						||
    r.add(qta.um(),F_UMFABB - FIRST_FIELD);
 | 
						||
    a.add(r);
 | 
						||
  }
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMatResPlanning
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
bool TMatResPlanning::test_codnum(const TCodice_numerazione& num, 
 | 
						||
                                  TString_array& a) const
 | 
						||
{
 | 
						||
  TString tmp;
 | 
						||
  for (int it=0 ; it< a.items(); it++ )
 | 
						||
  {
 | 
						||
    tmp = a.row(it).get(0);
 | 
						||
    if (tmp == num.codice()) return TRUE;
 | 
						||
  }
 | 
						||
  return FALSE;
 | 
						||
  bool yes = a.find(num.codice()) >= 0;
 | 
						||
  return yes;
 | 
						||
}
 | 
						||
 | 
						||
bool TMatResPlanning::has_confirmed_status(const TRectype& doc, 
 | 
						||
                                  TToken_string & riga ) const
 | 
						||
{
 | 
						||
  const char statodoc = doc.get_char(DOC_STATO);
 | 
						||
  const char state_def = riga.get_char(F_STATODEF - FIRST_FIELD);
 | 
						||
  return  (statodoc >= state_def);
 | 
						||
}
 | 
						||
int TMatResPlanning::test_status(const TRectype& doc, 
 | 
						||
                                  TString_array& a) const
 | 
						||
{
 | 
						||
  const TString16 tipodoc = doc.get(DOC_TIPODOC);
 | 
						||
  const char statodoc = doc.get_char(DOC_STATO);
 | 
						||
  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 char state_fr = riga.get_char(F_DASTATO - FIRST_FIELD);
 | 
						||
      const char state_to = riga.get_char(F_ASTATO - FIRST_FIELD);
 | 
						||
      if (statodoc >= state_fr && statodoc <= state_to)
 | 
						||
        return i;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return -1;
 | 
						||
}
 | 
						||
 | 
						||
static long table_items(const char* tab)
 | 
						||
{
 | 
						||
  TRelation tabrel(tab);
 | 
						||
  TCursor tabcur (&tabrel);
 | 
						||
  long tot = tabcur.items();
 | 
						||
  return tot;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 100%
 | 
						||
/////////// tested  : 100%
 | 
						||
bool TMatResPlanning::load_gross_requirements() 
 | 
						||
{
 | 
						||
  const TMatResMask& m = *_mask;
 | 
						||
  TDate date_fr = m.get(F_DADATA);
 | 
						||
  const int bucket_fr = m.round_date(date_fr, FALSE);
 | 
						||
 | 
						||
  TDate date_to = m.get(F_ADATA);
 | 
						||
  const int bucket_to = m.round_date(date_to, TRUE);
 | 
						||
 | 
						||
  const int year_fr = date_fr.year()  - (m.get_bool(F_DOC_YEAR_PREC) ? 1 : 0);
 | 
						||
  const int year_to = date_to.year();
 | 
						||
  const bool master = m.get(F_ORC_MASTER)[0] == 'M';  // Master Plan o Ordine Cliente
 | 
						||
  // azzera l'array _requirements
 | 
						||
  const bool nomag = m.get_bool(F_NOMAG);
 | 
						||
  const bool nodep = m.get_bool(F_NODEP);
 | 
						||
  const bool noimp = m.get_bool(F_NOIMP);
 | 
						||
  const bool nolin = m.get_bool(F_NOLIN);
 | 
						||
  _articles.ignore(nomag, nodep, noimp, nolin);
 | 
						||
  _articles.destroy();
 | 
						||
 
 | 
						||
  TTable num("%NUM");
 | 
						||
  TCodice_numerazione cod;
 | 
						||
 | 
						||
  TRelation rel(LF_DOC);
 | 
						||
  TCursor cur(&rel);
 | 
						||
  const TRectype& curr_doc = cur.curr();
 | 
						||
  TRectype filter_fr(curr_doc), filter_to(curr_doc);
 | 
						||
 | 
						||
  TString_array& n = m.sfield(F_NUM_ORC).rows_array();
 | 
						||
  TString_array& a = m.sfield(F_TIPI_ORC).rows_array();
 | 
						||
 | 
						||
  TProgind pi(table_items("%NUM"), "Caricamento fabbisogni lordi...", TRUE, TRUE);
 | 
						||
 | 
						||
  // 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))
 | 
						||
  {
 | 
						||
    pi.addstatus(1);
 | 
						||
    if (pi.iscancelled())
 | 
						||
      return FALSE;
 | 
						||
 | 
						||
    if (test_codnum(cod, n)) 
 | 
						||
    {
 | 
						||
      // 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_ANNO, year_fr);
 | 
						||
      filter_fr.put(DOC_CODNUM, cod.get("CODTAB"));
 | 
						||
      filter_to.put(DOC_PROVV, "D");
 | 
						||
      filter_to.put(DOC_ANNO, year_to);   
 | 
						||
      filter_to.put(DOC_CODNUM, cod.get("CODTAB"));
 | 
						||
      cur.setregion(filter_fr, filter_to);
 | 
						||
      TString cfilter;
 | 
						||
      cfilter << DOC_CODNUM << "==\"" << cod.get("CODTAB") << '"';
 | 
						||
      cur.setfilter(cfilter);
 | 
						||
      const long items = cur.items();
 | 
						||
      cur.freeze(TRUE);
 | 
						||
 | 
						||
      // Scandisce i documenti inevasi e considera solo 
 | 
						||
      // quelli con uno stato nel range corretto
 | 
						||
      for (cur = 0; cur.pos() < items; ++cur)    
 | 
						||
      {        
 | 
						||
        const bool evaso = curr_doc.get_bool(DOC_DOCEVASO);
 | 
						||
        if (evaso)
 | 
						||
          continue;
 | 
						||
 | 
						||
        TDate doc_cons = curr_doc.get(DOC_DATACONS);
 | 
						||
        if (!doc_cons.ok()) 
 | 
						||
          doc_cons = curr_doc.get(DOC_DATADOC);
 | 
						||
        
 | 
						||
        if (test_status(curr_doc, a)>=0)
 | 
						||
        {
 | 
						||
          // Scandisce le righe articolo e memorizza
 | 
						||
          // le quantita' richieste
 | 
						||
          TDocumento doc(cur.curr());
 | 
						||
          for (int r = doc.physical_rows(); r > 0; r--)
 | 
						||
          {
 | 
						||
            // Seleziona le righe articolo non ancora evase
 | 
						||
            const TRiga_documento& riga = doc[r];
 | 
						||
            
 | 
						||
            TDate datacons = riga.get(RDOC_DATACONS);
 | 
						||
            if (!datacons.ok()) datacons = doc_cons;
 | 
						||
            // Data consegna troppo avanti
 | 
						||
            if (datacons > date_to)
 | 
						||
              continue;
 | 
						||
 | 
						||
            if (riga.is_articolo())
 | 
						||
            {
 | 
						||
              const real qta = riga.qtaresidua();
 | 
						||
              if (qta > ZERO)
 | 
						||
              {
 | 
						||
                const TCodice_articolo art = riga.get(RDOC_CODARTMAG);
 | 
						||
                const TString16 liv = riga.get(RDOC_LIVELLO); 
 | 
						||
                const TString8 mag = nomag ? EMPTY_STRING : riga.get(RDOC_CODMAG).left(nodep ? 3 : 5); 
 | 
						||
                const TString8 imp = noimp ? EMPTY_STRING : riga.get(RDOC_IMPIANTO); 
 | 
						||
                const TString8 lin = nolin ? EMPTY_STRING : riga.get(RDOC_LINEA); 
 | 
						||
                const TCodice_um um = riga.get(RDOC_UMQTA);
 | 
						||
                TPrice prz(riga.prezzo(TRUE,TRUE));
 | 
						||
                TQuantita q(art, um, qta);
 | 
						||
                q.convert2umbase();
 | 
						||
                q.currency2umbase(prz);
 | 
						||
                TMRP_line* line = _articles.find(art, liv, mag, "", imp, lin, 0L);
 | 
						||
                if (line == NULL)
 | 
						||
                {
 | 
						||
                  // nuova linea
 | 
						||
                  line = _articles.find(art, liv, mag, "", imp, lin, 0L, TRUE);
 | 
						||
                  line->set_description(riga.get(RDOC_DESCR));
 | 
						||
                  line->set_final_product();
 | 
						||
                }
 | 
						||
                TString8 codnum = doc.get(DOC_CODNUM);
 | 
						||
                long docnum = doc.get_long(DOC_NDOC);
 | 
						||
                int numriga = riga.get_int(RDOC_NRIGA);
 | 
						||
                TMRP_docref * docref = new TMRP_docref(doc.get_int(DOC_ANNO), codnum, docnum,
 | 
						||
                            numriga, um, qta, prz.get_num());
 | 
						||
 | 
						||
                const TMRP_time t(datacons, 0, imp, lin);
 | 
						||
                line->add_gross_req(t, q.val(), docref);
 | 
						||
                if (master)
 | 
						||
                  line->add_net_req(t, q.val());
 | 
						||
              }
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
      cur.freeze(FALSE);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  return _articles.items() > 0L;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 100%
 | 
						||
/////////// tested  : 100%
 | 
						||
bool TMatResPlanning::explode_articles() 
 | 
						||
{
 | 
						||
  const TMatResMask& m = *_mask;
 | 
						||
  TDistinta_tree distinta; // albero distinta
 | 
						||
  TArray boom;             // array per i figli
 | 
						||
  int level = 1;
 | 
						||
  bool finiti = TRUE;
 | 
						||
  TProgind* pi = NULL;
 | 
						||
 | 
						||
  // Inizializza la cache delle lavorazioni
 | 
						||
  _artinfo.init(m.get_bool(F_KEEP_IMP)); 
 | 
						||
  
 | 
						||
  // Scandisce gli articoli inseriti dal gross requirements ed 
 | 
						||
  // accoda tutti gli articoli risultanti dalla loro esplosione
 | 
						||
  for (long a = 0; a < _articles.items(); a++)
 | 
						||
  {
 | 
						||
    if (pi && pi->isfinished())
 | 
						||
    {
 | 
						||
      delete pi;
 | 
						||
      pi = NULL;     
 | 
						||
      finiti = FALSE;
 | 
						||
    }
 | 
						||
    if (pi == NULL)
 | 
						||
    {
 | 
						||
      TString80 msg;
 | 
						||
      msg.format("Esplosione articoli (livello %d)", level++);
 | 
						||
      pi = new TProgind(_articles.items()-a, msg, TRUE, TRUE);
 | 
						||
    }
 | 
						||
    pi->addstatus(1);
 | 
						||
    if (pi->iscancelled())
 | 
						||
      return FALSE;
 | 
						||
 | 
						||
    TMRP_line& line = _articles[a];
 | 
						||
    distinta.set_global("_DISTINTA", line.articolo());
 | 
						||
    distinta.set_global("_MAGDEP"  , line.codmagdep());
 | 
						||
    distinta.set_global("_IMPIANTO", line.codimp());
 | 
						||
    distinta.set_global("_LINEA"   , line.codlin());
 | 
						||
    if (distinta.set_root(line.articolo(), "", 1.0 , line.livgiac()))
 | 
						||
    {
 | 
						||
      line.set_final_product(FALSE);
 | 
						||
      distinta.explode(boom, FALSE, RAGGR_EXP_UMBASE, 1, "AV");
 | 
						||
      for (int i = 0; i < boom.items(); i++)
 | 
						||
      {
 | 
						||
        const TRiga_esplosione& riga = (const TRiga_esplosione&)boom[i];
 | 
						||
        const TCodice_articolo& art = riga.articolo();
 | 
						||
        const TRectype& articolo=cache().get(LF_ANAMAG,art);
 | 
						||
        bool add=TRUE;
 | 
						||
        if (!articolo.get(ANAMAG_CODART).blank())
 | 
						||
        {
 | 
						||
          const char reorder_type=articolo.get_char(ANAMAG_RIORDINO);
 | 
						||
          if (reorder_type!='F' && reorder_type!=' ' && reorder_type!='\0') // e' a riordino
 | 
						||
            add=FALSE;
 | 
						||
        }
 | 
						||
        if (add)
 | 
						||
        {
 | 
						||
          // articolo gestito dall'MRP
 | 
						||
          TString8 mag = line.codmagdep();
 | 
						||
          TString8 imp = line.codimp();
 | 
						||
          TString8 lin = line.codlin();
 | 
						||
          _artinfo.art2magimpline(art, mag, imp, lin);
 | 
						||
          TMRP_line* son = _articles.find(art, riga.giacenza(),mag, "", imp, lin, 0L);
 | 
						||
          if (son == NULL)
 | 
						||
          {
 | 
						||
            son = _articles.find(art, riga.giacenza(), mag, "", imp, lin, 0L, TRUE);
 | 
						||
            son->set_description(distinta.describe(art));
 | 
						||
          }  
 | 
						||
          line.add_son(riga.val(), son);
 | 
						||
          distinta.describe(art);
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  if (pi != NULL) delete pi;
 | 
						||
 | 
						||
  return _articles.items() > 0;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 100%
 | 
						||
/////////// tested:
 | 
						||
bool TMatResPlanning::load_planned_orders() 
 | 
						||
{
 | 
						||
  const TMatResMask& m = *_mask;
 | 
						||
  TDate date_fr = m.get(F_DADATA);
 | 
						||
  const int bucket_fr = m.round_date(date_fr, FALSE);
 | 
						||
 | 
						||
  TDate date_to = m.get(F_ADATA);
 | 
						||
  const int bucket_to = m.round_date(date_to, TRUE);
 | 
						||
 | 
						||
  const int year_fr = date_fr.year() - (m.get_bool(F_DOC_YEAR_PREC) ? 1 : 0);
 | 
						||
  const int year_to = date_to.year();
 | 
						||
 | 
						||
  TTable num("%NUM");
 | 
						||
  TCodice_numerazione cod;
 | 
						||
 | 
						||
  TRelation rel(LF_DOC);
 | 
						||
  TCursor cur(&rel);
 | 
						||
  const TRectype& curr = cur.curr();
 | 
						||
  TRectype filter_fr(curr), filter_to(curr);
 | 
						||
 | 
						||
  TString_array& n = m.sfield(F_NUM_ORF).rows_array();
 | 
						||
  TString_array& a = m.sfield(F_TIPI_ORF).rows_array();
 | 
						||
 | 
						||
  TProgind pi(table_items("%NUM"), "Caricamento arrivi futuri...", TRUE, TRUE);
 | 
						||
 | 
						||
  // 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))
 | 
						||
  {
 | 
						||
    pi.addstatus(1);
 | 
						||
    if (pi.iscancelled())
 | 
						||
      return FALSE;
 | 
						||
 | 
						||
    if (test_codnum(cod, n)) 
 | 
						||
    {
 | 
						||
      // Filtra il cursore in modo da limitarlo alla numerazione
 | 
						||
      // corrente ed agli anni specificati dalle due date limite
 | 
						||
      filter_fr.put(DOC_PROVV, "D");
 | 
						||
      filter_fr.put(DOC_CODNUM, cod.get("CODTAB"));
 | 
						||
      filter_fr.put(DOC_ANNO, year_fr);
 | 
						||
      filter_to.put(DOC_PROVV, "D");
 | 
						||
      filter_to.put(DOC_CODNUM, cod.get("CODTAB"));
 | 
						||
      filter_to.put(DOC_ANNO, year_to);   
 | 
						||
      cur.setregion(filter_fr, filter_to);
 | 
						||
      TString cfilter;
 | 
						||
      cfilter << DOC_CODNUM << "==" << '"' << cod.get("CODTAB") << '"' ;
 | 
						||
      cur.setfilter(cfilter);
 | 
						||
      const long items = cur.items();
 | 
						||
      cur.freeze(TRUE);
 | 
						||
 | 
						||
      // Scandisce i documenti inevasi e considera solo 
 | 
						||
      // quelli con uno stato nel range corretto
 | 
						||
      for (cur = 0; cur.pos() < items; ++cur)    
 | 
						||
      {
 | 
						||
        const bool evaso = curr.get_bool(DOC_DOCEVASO);
 | 
						||
        if (evaso)
 | 
						||
          continue;
 | 
						||
 | 
						||
        const int sheetrow = test_status(curr, a);
 | 
						||
        if (sheetrow<0)
 | 
						||
          continue;
 | 
						||
 | 
						||
        // Data di consegna standard
 | 
						||
        TDate doc_cons = curr.get(DOC_DATACONS);
 | 
						||
        if (!doc_cons.ok()) 
 | 
						||
          doc_cons = curr.get(DOC_DATADOC);   
 | 
						||
        
 | 
						||
        // Scandisce le righe articolo e memorizza
 | 
						||
        // le quantita' richieste
 | 
						||
        TDocumento doc(cur.curr());
 | 
						||
        for (int r = doc.physical_rows(); r > 0; r--)
 | 
						||
        {
 | 
						||
          // Seleziona le righe articolo non ancora evase
 | 
						||
          const TRiga_documento& riga = doc[r];
 | 
						||
 | 
						||
          TDate consegna = riga.get(RDOC_DATACONS);
 | 
						||
          if (!consegna.ok())
 | 
						||
            consegna = doc_cons;
 | 
						||
          
 | 
						||
          // Data consegna troppo avanti
 | 
						||
          if (consegna > date_to) 
 | 
						||
            continue;
 | 
						||
 | 
						||
          if (riga.is_articolo())
 | 
						||
          {
 | 
						||
            const real qta = riga.qtaresidua();
 | 
						||
            if (qta > ZERO)
 | 
						||
            {
 | 
						||
              const TCodice_articolo art = riga.get(RDOC_CODARTMAG);
 | 
						||
              const TString16 liv = riga.get(RDOC_LIVELLO);
 | 
						||
              const TString8 mag = riga.get(RDOC_CODMAG);
 | 
						||
              const TString8 imp = riga.get(RDOC_IMPIANTO);
 | 
						||
              const TString8 lin = riga.get(RDOC_LINEA);
 | 
						||
              const long clifor = doc.get_long(DOC_CODCF);
 | 
						||
              TMRP_line* line = _articles.find(art, liv, mag, "", imp, lin, 0L);
 | 
						||
              if (line == NULL)
 | 
						||
              {
 | 
						||
                line = _articles.find(art, liv, mag, "", imp, lin, 0L, TRUE);
 | 
						||
                line->set_description(riga.get(RDOC_DESCR));
 | 
						||
              }
 | 
						||
              TPrice prz(riga.prezzo(TRUE,TRUE));
 | 
						||
              const TCodice_um um = riga.get(RDOC_UMQTA);
 | 
						||
              TQuantita q(art, um, qta);
 | 
						||
              q.convert2umbase();
 | 
						||
              q.currency2umbase(prz);
 | 
						||
              TString8 codnum = doc.get(DOC_CODNUM);
 | 
						||
              long docnum = doc.get_long(DOC_NDOC);
 | 
						||
              int numriga = riga.get_int(RDOC_NRIGA);
 | 
						||
              TMRP_docref * docref = new TMRP_docref(doc.get_int(DOC_ANNO), codnum, docnum,
 | 
						||
                          numriga, um, q.val(), prz.get_num());
 | 
						||
              const TMRP_time t(consegna, 0, imp, lin);
 | 
						||
              if (has_confirmed_status(doc, a.row(sheetrow)) || 
 | 
						||
                  (codnum != m.get(F_NUM_PROD) && codnum != m.get(F_NUM_FORN)))
 | 
						||
                line->add_sched_rec(t, q.val(), docref);
 | 
						||
              else
 | 
						||
                line->add_planned_ord(t, q.val(), docref);
 | 
						||
            }
 | 
						||
          }
 | 
						||
        }
 | 
						||
      }
 | 
						||
      cur.freeze(FALSE);
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  return _articles.items() > 0L;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 99%
 | 
						||
/////////// tested:   99%
 | 
						||
bool TMatResPlanning::preprocess_cycle()
 | 
						||
{
 | 
						||
  // costruisce il gross requirement dai DOC di planning
 | 
						||
  bool ok=load_gross_requirements();
 | 
						||
  // costruisce gli sched rec degli elementi dai DOCS ordini fornitore emessi
 | 
						||
  ok |= load_planned_orders();
 | 
						||
  if (ok)
 | 
						||
    // esplode l'array mediante la DIBA
 | 
						||
    return explode_articles();
 | 
						||
 | 
						||
/*
 | 
						||
  // costruisce il gross requirement dai DOC di planning
 | 
						||
  if (load_gross_requirements(m))
 | 
						||
    // esplode l'array mediante la DIBA
 | 
						||
    if (explode_articles(m))
 | 
						||
      // costruisce gli sched rec degli elementi dai DOCS ordini fornitore emessi
 | 
						||
      return load_planned_orders(m);
 | 
						||
*/
 | 
						||
  return FALSE;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 99%
 | 
						||
/////////// tested:
 | 
						||
// implementa la logica che porta dal fabbisogno lordo a quello netto
 | 
						||
// per quel bucket e riporta il balance on hand sul bucket successivo
 | 
						||
// ipotesi essenziale per il rescheduling: la chiamata della funzione 
 | 
						||
// deve essere fatta ciclicamente su tutti i bucket di un articolo 
 | 
						||
// prima di passare ad un altro articolo
 | 
						||
bool TMatResPlanning::gross2net_logic(TMRP_line &curr_article, int bucket, bool & sc_used)
 | 
						||
{
 | 
						||
  const TMatResMask& m = *_mask;
 | 
						||
 | 
						||
  const TDate& start_date =m.get_date(F_DADATA);
 | 
						||
  const bool lotsizing_p  =m.get_bool(F_LOTSIZING_P);
 | 
						||
  const bool lotsizing_f  =m.get_bool(F_LOTSIZING_F);
 | 
						||
  const bool use_leadtime =!m.get_bool(F_IGN_LDTIME);
 | 
						||
 | 
						||
  // Verifico se esiste gia' un fabbisogno netto
 | 
						||
  real sm,tmpreal = -curr_article.net_requirement(bucket);
 | 
						||
#ifdef DBG                                                                         
 | 
						||
    TString80 s;
 | 
						||
#endif
 | 
						||
  if (tmpreal >= ZERO) // Devo calcolare il fabbisogno netto
 | 
						||
  {  
 | 
						||
    tmpreal =  curr_article.on_hand(bucket);
 | 
						||
    tmpreal -= curr_article.gross_requirement(bucket);
 | 
						||
#ifdef DBG
 | 
						||
    if (curr_article.articolo() == "U01121")
 | 
						||
    {
 | 
						||
      s = tmpreal.string();
 | 
						||
      tmpreal.round(5);
 | 
						||
      s = tmpreal.string();
 | 
						||
    }  
 | 
						||
    if (curr_article.articolo() == "U00124")
 | 
						||
    {
 | 
						||
      s = tmpreal.string();
 | 
						||
      tmpreal.round(5);
 | 
						||
      s = tmpreal.string();
 | 
						||
    }  
 | 
						||
#endif
 | 
						||
    if (!sc_used)                                                      
 | 
						||
    {
 | 
						||
      curr_article.scorta_minima(sm, curr_article.time(bucket).date());
 | 
						||
      sc_used = TRUE;
 | 
						||
      tmpreal -= sm;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  // tmpreal += curr_article.planned_orders(bucket); //planned orders are not added here, but in build orders phase
 | 
						||
  if (!m.get_bool(F_RESCHEDULING))
 | 
						||
    tmpreal += curr_article.sched_receipts(bucket);//scheduled orders are not added if we reschedule them
 | 
						||
  
 | 
						||
  // adegua il quantitativo del fabbisogno netto in base al lot-sizing, se il valore risulta negativo 
 | 
						||
  const int n_figli = curr_article.sons();
 | 
						||
  real net_req;
 | 
						||
  if ((lotsizing_p && n_figli!=0 )||(lotsizing_f && n_figli==0) )
 | 
						||
    net_req = curr_article.sizeup_net_requirement(bucket, tmpreal);
 | 
						||
  else
 | 
						||
    net_req = curr_article.set_net_req(bucket, -tmpreal);
 | 
						||
 | 
						||
  // calcola la giacenza del bucket successivo
 | 
						||
  tmpreal += net_req;
 | 
						||
  if (tmpreal > ZERO)
 | 
						||
  {
 | 
						||
    const int nb = curr_article.next_bucket(bucket);
 | 
						||
    if (nb <= curr_article.last_bucket())
 | 
						||
      curr_article.set_on_hand(nb, tmpreal);
 | 
						||
  }
 | 
						||
 | 
						||
  // trasforma i fabbisogni totali nel fabbisogno lordo dei figli
 | 
						||
  net_req += curr_article.sched_receipts(bucket);
 | 
						||
  // net_req += curr_article.planned_orders(bucket);//planned orders are not added here, but in build orders phase
 | 
						||
  if (net_req > ZERO && n_figli)
 | 
						||
  {
 | 
						||
    TMRP_time lead_time, xlead_time; 
 | 
						||
    curr_article.lead_time(bucket, lead_time, use_leadtime);
 | 
						||
    const int xtradays = m.get_int(F_XTRA_LDTIME);
 | 
						||
    if (xtradays)
 | 
						||
    {
 | 
						||
      xlead_time = lead_time;
 | 
						||
      xlead_time.sub_time(xtradays);
 | 
						||
    }
 | 
						||
    for (int o = 0; o < n_figli; o++)
 | 
						||
    {
 | 
						||
      TMRP_line& article_son = curr_article.son(o);
 | 
						||
      tmpreal = net_req * curr_article.qta_son(o);
 | 
						||
      tmpreal.round(5);
 | 
						||
      if (tmpreal > ZERO) 
 | 
						||
      {
 | 
						||
        TMRP_internalref * iref = new TMRP_internalref( &curr_article, bucket, tmpreal);
 | 
						||
        if (xtradays && curr_article.sons())
 | 
						||
          article_son.add_gross_req(xlead_time, tmpreal, iref);
 | 
						||
        else
 | 
						||
          article_son.add_gross_req(lead_time, tmpreal, iref);
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 99%
 | 
						||
/////////// tested:
 | 
						||
bool TMatResPlanning::net_requirement_cycle()
 | 
						||
{
 | 
						||
  const TMatResMask& m = *_mask;
 | 
						||
 | 
						||
  bool ok = TRUE;
 | 
						||
  // ordina gli articoli
 | 
						||
  const long total = _articles.sort();
 | 
						||
 | 
						||
  TProgind pi(total, "Calcolo dei fabbisogni netti", FALSE, TRUE);
 | 
						||
 | 
						||
  // cicla iterativamente sugli elementi di _articles
 | 
						||
  for (long a = 0; a < total; a++)
 | 
						||
  {
 | 
						||
    pi.addstatus(1);
 | 
						||
 | 
						||
    TMRP_line& curr_article = _articles[a];
 | 
						||
 | 
						||
    const int last = curr_article.last_bucket();
 | 
						||
    if (last >= 0)
 | 
						||
    {
 | 
						||
      real curgiac;
 | 
						||
      curr_article.set_on_hand(0, curr_article.giacenza_attuale(curgiac, m.get_date(F_DADATA)));
 | 
						||
      bool sc_used = FALSE;
 | 
						||
      
 | 
						||
      for (int bucket = 0; ok && bucket <= last; bucket = curr_article.next_bucket(bucket))
 | 
						||
      {
 | 
						||
        // !?!?! la logica gross2net dovrebbe funzionare in termini di intervalli di date 
 | 
						||
        // (bucket-utente) piuttosto che  di bucket di MRPline (che possono essere pi<70> di uno
 | 
						||
        // in un intervallo, altrimenti i ragionamenti di scorte minime e lotti
 | 
						||
        // funzionano in modo sbagliato, perch<63> approssimano pi<70> volte
 | 
						||
        ok = gross2net_logic(curr_article, bucket, sc_used);
 | 
						||
        if (!ok)
 | 
						||
          break;
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return ok;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 100%
 | 
						||
/////////// tested  : 100%
 | 
						||
// genera le righe degli ordini di produzione o a fornitore
 | 
						||
bool TMatResPlanning::build_orders()
 | 
						||
{
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
 | 
						||
  TSheet_field& sf = m.sfield(F_ORDINI);
 | 
						||
  sf.destroy();
 | 
						||
 | 
						||
  const long tot = _articles.items();
 | 
						||
  if (tot > 0L)
 | 
						||
  {
 | 
						||
 | 
						||
    TProgind pi(tot, "Generazione righe ordini...", FALSE, TRUE);
 | 
						||
    for (long a = 0; a < tot; a++)
 | 
						||
    {
 | 
						||
      pi.addstatus(1);
 | 
						||
      const TMRP_line& line = _articles[a];
 | 
						||
 | 
						||
      const TRectype& anarec  = cache().get(LF_ANAMAG,line.articolo());
 | 
						||
      const TRectype& distrec = cache().get(LF_DIST,line.articolo());
 | 
						||
      const bool prod = distrec.get_bool("ARTPROD");
 | 
						||
//      const long forn = prod ? 0 : anarec.get_long("CODFORN");
 | 
						||
      long forn = 0;
 | 
						||
      if (!prod)
 | 
						||
      {                           
 | 
						||
        TString key;
 | 
						||
        key << line.codimp();
 | 
						||
        key.rpad(5);
 | 
						||
        key << line.articolo();
 | 
						||
        
 | 
						||
        forn = atol(cache().get("FIA", key, "I0"));
 | 
						||
        if (forn == 0L)
 | 
						||
          forn = anarec.get_long("CODFORN");
 | 
						||
      }
 | 
						||
      for (int b = line.last_bucket(); b >= 0; b--)
 | 
						||
      {
 | 
						||
/*      
 | 
						||
        const TMRP_record & rrr = line.record(b);
 | 
						||
        const real r0 = line.gross_requirement(b);
 | 
						||
        const real r1 = line.planned_orders(b);
 | 
						||
        const real r2 = line.sched_receipts(b);
 | 
						||
        real qta = line.net_requirement(b);
 | 
						||
        qta -= line.planned_orders(b);
 | 
						||
        qta.round(5);
 | 
						||
        if (!qta.is_zero() || 
 | 
						||
            line.planned_orders(b)>0 || 
 | 
						||
                line.sched_receipts(b)>line.gross_requirement(b))
 | 
						||
          m.add_order_line(forn, line, b);
 | 
						||
        else                              
 | 
						||
*/        
 | 
						||
          m.add_order_line(forn, line, b);
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  const int orders=sf.items();
 | 
						||
  if (orders==0)
 | 
						||
    message_box("Nessun ordine da emettere");
 | 
						||
  real price, qta;
 | 
						||
  TCodice_articolo codart;
 | 
						||
  FOR_EACH_SHEET_ROW(sf,n,row)
 | 
						||
  {
 | 
						||
    row->get(F_QUANTITA - FIRST_FIELD,qta);
 | 
						||
    row->get(F_ARTICOLO - FIRST_FIELD,codart);
 | 
						||
    long codcli=atol(row->get(F_FORNITORE - FIRST_FIELD));
 | 
						||
    const TRectype& rec=cache().get(LF_DIST, codart);
 | 
						||
    bool art_prod, art_acq;
 | 
						||
 | 
						||
    if (rec.empty())
 | 
						||
    {
 | 
						||
      art_acq=TRUE;
 | 
						||
      art_prod = cache().get(LF_ANAMAG, codart).get_bool(ANAMAG_ARTPROD);
 | 
						||
    } else {
 | 
						||
      art_prod = rec.get_bool("ARTPROD");
 | 
						||
      art_acq  = rec.get_bool("ARTACQ") || codcli!=0L;
 | 
						||
    }
 | 
						||
    TString4 tipoord = art_prod ? "P" : "F" ;
 | 
						||
    row->add(tipoord, F_ORD_TYPE - FIRST_FIELD);
 | 
						||
    sf.check_row(n);
 | 
						||
 | 
						||
    if (tipoord=="P")
 | 
						||
      tipoord=" ";
 | 
						||
    else
 | 
						||
      tipoord=m.get(F_TIPOCF_CONDV);
 | 
						||
    find_price(m.get(F_TIPOCV),m.get(F_CODCONDV),m.get(F_CATVEN_CV),
 | 
						||
        tipoord, codcli, codart, qta,  price);
 | 
						||
    row->add(price.string(), F_PREZZO - FIRST_FIELD);
 | 
						||
 | 
						||
    if (!art_prod || !art_acq)
 | 
						||
      sf.disable_cell(n,F_ORD_TYPE - FIRST_FIELD);
 | 
						||
 | 
						||
  }
 | 
						||
  sf.enable(!m.get_bool(F_DISABLESAVE));
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 0%
 | 
						||
 | 
						||
void TMatResPlanning::print_orders_header(TPrinter& pr)
 | 
						||
{
 | 
						||
  TString format;
 | 
						||
  TPrintrow row;
 | 
						||
  print_header(pr);
 | 
						||
  row.put("@48G@BSTAMPA PROPOSTE D'ORDINE DA M.R.P.");
 | 
						||
  pr.setheaderline(1,row);
 | 
						||
  row.reset();
 | 
						||
  set_body_order_line(row, NULL);
 | 
						||
  pr.setheaderline(3,row);
 | 
						||
  row.reset();
 | 
						||
  row.put((const char *)TString(131,'-'));
 | 
						||
  pr.setheaderline(4,row);
 | 
						||
}
 | 
						||
void TMatResPlanning::print_orders_body(TPrinter& pr, TToken_string *sheetrow)
 | 
						||
{
 | 
						||
  TPrintrow row;
 | 
						||
  // riga 1
 | 
						||
  set_body_order_line(row, sheetrow);
 | 
						||
 | 
						||
  // riga 2
 | 
						||
  pr.print(row);
 | 
						||
  row.reset();
 | 
						||
  int pos = 31;
 | 
						||
  row.put(format("@%dG%s", pos, (const char *)sheetrow->get(F_DESCART-FIRST_FIELD)));
 | 
						||
 | 
						||
  if (*sheetrow->get(F_DOCCODNUM-FIRST_FIELD) > ' ')
 | 
						||
  {
 | 
						||
    row.put(format("@%dGDocumento %s", pos+= 54+1, (const char *)sheetrow->get(F_DOCCODNUM-FIRST_FIELD)));
 | 
						||
    row.put(format("@%dG%d", pos+= 4+10+1, sheetrow->get_int(F_DOCANNODOC-FIRST_FIELD)));
 | 
						||
    row.put(format("@%dGn.%6ld", pos+= 4+1, sheetrow->get_long(F_DOCNUM-FIRST_FIELD)));
 | 
						||
    row.put(format("@%dGriga %3d", pos+= 2+6+1, sheetrow->get_int(F_DOCNRIGA-FIRST_FIELD)));
 | 
						||
  }
 | 
						||
  pr.print(row);
 | 
						||
}
 | 
						||
 | 
						||
void TMatResPlanning::set_body_order_line(TPrintrow &row, TToken_string *sheetrow)
 | 
						||
{
 | 
						||
  int pos = 0;
 | 
						||
  row.put(format("@b@%dG%1s", pos, sheetrow ? (const char *)sheetrow->get(F_ORD_TYPE-FIRST_FIELD): ""));
 | 
						||
  row.put(format("@%dG%6s", pos+= 1+1, sheetrow ? (const char *)sheetrow->get(F_FORNITORE-FIRST_FIELD): "CliFor"));
 | 
						||
  row.put(format("@%dG%s",  pos+= 6+1, sheetrow ? (const char *)sheetrow->get(F_DATADOC-FIRST_FIELD): "Data doc."));
 | 
						||
  row.put(format("@%dG%s",  pos+= 10+1, sheetrow ? (const char *)sheetrow->get(F_DATACONS-FIRST_FIELD): "Consegna"));
 | 
						||
  row.put(format("@%dG%s", pos+= 10+1, sheetrow ? (const char *)sheetrow->get(F_ARTICOLO-FIRST_FIELD): "Codice articolo"));
 | 
						||
  pos += 20+1;
 | 
						||
  for (int l = 1; l <= livelli_giacenza().last_level(); l++)
 | 
						||
  {
 | 
						||
    const int len = livelli_giacenza().code_length(l);
 | 
						||
    if (sheetrow == NULL)
 | 
						||
    {
 | 
						||
      if (l == 1)
 | 
						||
        row.put(format("@%dG%s", pos, "Livello"));
 | 
						||
    }
 | 
						||
    else
 | 
						||
      row.put(format("@%dG%s", pos, (const char *)sheetrow->get(F_LIV1+l-1-FIRST_FIELD)));
 | 
						||
    pos += len+1;
 | 
						||
  }
 | 
						||
  real r; 
 | 
						||
  if (sheetrow) 
 | 
						||
  {
 | 
						||
    sheetrow->get(F_QUANTITA-FIRST_FIELD, r);
 | 
						||
    row.put(format("@%dG%18s", pos, (const char *)r.string(18,5)));
 | 
						||
  } else {
 | 
						||
    row.put(format("@%dGQuantita'", pos+8));
 | 
						||
  }
 | 
						||
  row.put(format("@%dG%s", pos+= 18+1, sheetrow ? (const char *)sheetrow->get(F_UM-FIRST_FIELD): "UM"));
 | 
						||
  if (sheetrow) 
 | 
						||
    sheetrow->get(F_PREZZO-FIRST_FIELD, r);
 | 
						||
  TCurrency c(TRUE);
 | 
						||
  c.set_num(r);
 | 
						||
  row.put(format("@%dG%18s", pos+=2+1, sheetrow ? (const char *)c.string(): "Prezzo"));
 | 
						||
  row.put(format("@%dG%3s", pos+=18+1, sheetrow ? (const char *)sheetrow->get(F_MAGAZZINO-FIRST_FIELD): "Mag."));
 | 
						||
  row.put(format("@%dG%2s", pos+= 3+1, sheetrow ? (const char *)sheetrow->get(F_DEPOSITO-FIRST_FIELD): ""));
 | 
						||
  row.put(format("@%dG%5s", pos+= 2+1, sheetrow ? (const char *)sheetrow->get(F_CODIMP-FIRST_FIELD): "Imp."));
 | 
						||
  row.put(format("@%dG%5s", pos+= 5+1, sheetrow ? (const char *)sheetrow->get(F_CODLIN-FIRST_FIELD): "Linea"));
 | 
						||
  pos += 5+1;
 | 
						||
}
 | 
						||
 | 
						||
/////////// tested  : 0%
 | 
						||
// stampa le proposte d'ordine
 | 
						||
bool TMatResPlanning::print_orders()
 | 
						||
{
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
  TSheet_field& sf = m.sfield(F_ORDINI);
 | 
						||
  if (sf.items() < 1)
 | 
						||
  {
 | 
						||
    message_box("Nessun ordine da stampare");
 | 
						||
    return FALSE;
 | 
						||
  }    
 | 
						||
  TMask pmask("mr2100c.msk");
 | 
						||
  pmask.set(S_LIV_RISALITA,1);
 | 
						||
  while (pmask.run() != K_ESC)
 | 
						||
  {
 | 
						||
    if (pmask.get(S_PRINTTYPE)[0] == 'O')
 | 
						||
    {
 | 
						||
      print_planning(pmask);
 | 
						||
    } else {
 | 
						||
      print_exceptions(pmask);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
bool TMatResPlanning::print_planning(TMask &pmask)
 | 
						||
{
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
  TSheet_field& sf = m.sfield(F_ORDINI);
 | 
						||
  TPrinter& pr = printer();
 | 
						||
  pr.open();
 | 
						||
  if (pmask.get_bool(S_RISALITA))
 | 
						||
  {
 | 
						||
    TIndwin(60,"Ordinamento proposte per articolo/data...",FALSE);
 | 
						||
    sf.sort(order_compareADTF);
 | 
						||
    sf.force_update();
 | 
						||
  }
 | 
						||
  pr.setheaderhandler(print_orders_header);
 | 
						||
  pr.headerlen(6);
 | 
						||
  pr.setfooterhandler(print_footer);
 | 
						||
  pr.footerlen(2);
 | 
						||
    
 | 
						||
  TString last_key;
 | 
						||
  TString key;
 | 
						||
  FOR_EACH_SHEET_ROW(sf, r, row)
 | 
						||
  {
 | 
						||
    if (!pmask.get_bool(S_SELECTEDONLY) || *row->get(sf.cid2index(F_SELECTED)) == 'X')
 | 
						||
    {
 | 
						||
      key = row->get(sf.cid2index(F_ARTICOLO));
 | 
						||
      key << row->get(sf.cid2index(F_DATACONS));
 | 
						||
      if (last_key.blank())
 | 
						||
        last_key = key;
 | 
						||
      print_orders_body(pr,row);
 | 
						||
      if (pmask.get_bool(S_RISALITA) /*&& (key != last_key || sf.items() == r)*/)
 | 
						||
      {
 | 
						||
        print_risalita(*row, pmask.get_int(S_LIV_RISALITA), pmask.get_bool(S_DETT_ORDINI));
 | 
						||
        last_key=key;
 | 
						||
      }
 | 
						||
      if (pmask.get_bool(S_INTERLINEA))
 | 
						||
      {
 | 
						||
        TPrintrow prow;
 | 
						||
        pr.print(prow);
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  pr.close();
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TMatResPlanning::print_risalita(TToken_string &row, int ris_level, bool dett_ord )
 | 
						||
{
 | 
						||
  TPrinter& pr = printer();
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
  TSheet_field& sf = m.sfield(F_ORDINI);
 | 
						||
  // rintraccia la TMRPline per la risalita
 | 
						||
  TString art;
 | 
						||
  TString16 liv;
 | 
						||
  TString8 mag, magc, imp, lin;
 | 
						||
  long codcf;
 | 
						||
  codcf = row.get_long(sf.cid2index(F_FORNITORE));
 | 
						||
  row.get(sf.cid2index(F_ARTICOLO), art);
 | 
						||
  for (int l= livelli_giacenza().last_level(); l>=1; l--)
 | 
						||
    livelli_giacenza().pack_grpcode(liv, row.get(sf.cid2index(F_LIV1+l-1)), l);
 | 
						||
  add_magcode(mag, row.get(sf.cid2index(F_MAGAZZINO)));
 | 
						||
  add_depcode(mag, row.get(sf.cid2index(F_DEPOSITO )));
 | 
						||
  row.get(sf.cid2index(F_CODIMP), imp);
 | 
						||
  row.get(sf.cid2index(F_CODLIN), lin);
 | 
						||
        
 | 
						||
  TMRP_line* line = _articles.find(art, liv, mag, magc, imp, lin, codcf);
 | 
						||
  if (!line)
 | 
						||
    line = _articles.find(art, liv, mag, magc, imp, lin, 0L);
 | 
						||
  if (line)
 | 
						||
  {
 | 
						||
    print_risalita(*line, row.get(sf.cid2index(F_DATACONS)), ris_level, dett_ord);
 | 
						||
    return TRUE;
 | 
						||
  }
 | 
						||
  else 
 | 
						||
  {
 | 
						||
    TPrintrow prow;
 | 
						||
    prow.put(format("@32gRisalita: impossibile rintracciare la proposta originale"));
 | 
						||
    pr.print(prow);
 | 
						||
    return FALSE;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
bool TMatResPlanning::print_risalita(const TMRP_line & line, const TDate &date, int backlevel, bool dett_ord)
 | 
						||
{
 | 
						||
  TPrinter& pr = printer();
 | 
						||
  TDate todate(date);
 | 
						||
  TDate fromdate = todate;
 | 
						||
  const bool isbuck0 = (round_date(fromdate) == 0);
 | 
						||
  round_date(todate,TRUE);
 | 
						||
  int rows=0;
 | 
						||
  //int extraleadtime = _mask->get_int(F_XTRA_LDTIME);
 | 
						||
  real on_hand, lordo, netto, plan, sched;
 | 
						||
  for (int b = line.last_bucket(); b >= 0 ; b--)
 | 
						||
  {
 | 
						||
    //TMRP_time dtime = line.record(b).time();
 | 
						||
    //if (extraleadtime && line.sons() == 0)
 | 
						||
    //  dtime.sub_time(extraleadtime);
 | 
						||
    //const TDate &d  = dtime.date();
 | 
						||
    const TDate &d = line.record(b).time().date();
 | 
						||
    if ((isbuck0 || d >= fromdate))
 | 
						||
    {
 | 
						||
      if (d <= todate)
 | 
						||
      {
 | 
						||
        on_hand = line.record(b).on_hand();
 | 
						||
        lordo += line.gross_requirement(b);
 | 
						||
        netto += line.net_requirement(b);
 | 
						||
        plan  += line.planned_orders(b);
 | 
						||
        sched += line.sched_receipts(b);
 | 
						||
        TMRP_internalrefs *irefs = line.record(b).internal_refs();
 | 
						||
        if (irefs)
 | 
						||
        {
 | 
						||
          int ir = 0;
 | 
						||
          while (ir < irefs->items())
 | 
						||
          {
 | 
						||
            TMRP_internalref &iref = irefs->get_ref(ir);
 | 
						||
            rows += print_internal_ref(iref, backlevel, dett_ord);
 | 
						||
            ir ++;
 | 
						||
          }
 | 
						||
        } else {
 | 
						||
          rows += print_gross_ref(line, b);
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  if (rows==0)
 | 
						||
    return FALSE;
 | 
						||
  TPrintrow prow;
 | 
						||
  int pos = 30;
 | 
						||
  prow.put(format("@%dg Totale fabbisogno lordo %s", pos, lordo.string(18,5)));
 | 
						||
  pr.print(prow);
 | 
						||
  prow.put(format("@%dg Giacenza iniziale       %s", pos, on_hand.string(18,5)));
 | 
						||
  pr.print(prow);                                 
 | 
						||
  if (dett_ord)
 | 
						||
  {
 | 
						||
    prow.put(format("@%dg Ordini pianificati      %s", pos, plan.string(18,5)));
 | 
						||
    pr.print(prow);
 | 
						||
    prow.put(format("@%dg Ordini confermati       %s", pos, sched.string(18,5)));
 | 
						||
    pr.print(prow);
 | 
						||
  }
 | 
						||
  sched += plan;
 | 
						||
  prow.put(format("@%dg Totale ordinato         %s", pos, sched.string(18,5)));
 | 
						||
  pr.print(prow);
 | 
						||
  netto -= plan;
 | 
						||
  prow.put(format("@%dg Totale da pianificare   %s", pos, netto.string(18,5)));
 | 
						||
  pr.print(prow);
 | 
						||
  if (backlevel>1 || backlevel<0)
 | 
						||
  { 
 | 
						||
    prow.reset();
 | 
						||
    pr.print(prow);
 | 
						||
  }
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
int TMatResPlanning::print_internal_ref(const TMRP_internalref &iref, int backlevel, bool dett_ord)
 | 
						||
{
 | 
						||
  TPrinter& pr = printer();
 | 
						||
  int rows=0;
 | 
						||
  const TMRP_line& line=*iref.line();
 | 
						||
  int bucket=iref.bucket();
 | 
						||
  const TMRP_time &deliv_time = line.time(bucket);
 | 
						||
  {
 | 
						||
    TMRP_time doc_time;
 | 
						||
    line.lead_time(bucket,doc_time, TRUE);
 | 
						||
    TDate docdate = doc_time.date();
 | 
						||
  
 | 
						||
    TToken_string dockey;
 | 
						||
    TMRP_docrefs * gr_refs= line.record(bucket).requirements_refs();
 | 
						||
    int grref = gr_refs ? gr_refs->items() : 0;
 | 
						||
    TMRP_docrefs * pl_refs= line.record(bucket).plans_refs();
 | 
						||
    int plref = pl_refs ? pl_refs->items() : 0;
 | 
						||
    TMRP_docrefs * sr_refs = line.record(bucket).scheduls_refs();
 | 
						||
    int srref = sr_refs ? sr_refs->items() : 0;
 | 
						||
    real totreq = line.net_requirement(bucket);
 | 
						||
    totreq += line.sched_receipts(bucket);
 | 
						||
    real qtaplan(totreq);
 | 
						||
    real qtareq(totreq);
 | 
						||
    do {
 | 
						||
      TCodice_um um;
 | 
						||
      TPrintrow r1, r2;
 | 
						||
      real q = iref.qta();
 | 
						||
      TMRP_docref * docref = NULL;
 | 
						||
      if (grref > 0)
 | 
						||
        docref = gr_refs->get_ref_ptr(--grref);
 | 
						||
      else if (srref > 0)
 | 
						||
        docref = sr_refs->get_ref_ptr(--srref);
 | 
						||
      else if (plref > 0)
 | 
						||
        docref = pl_refs->get_ref_ptr(--plref);
 | 
						||
      if (docref)
 | 
						||
      {
 | 
						||
        dockey.add("D",0);
 | 
						||
        dockey.add(docref->annodoc(),1);
 | 
						||
        dockey.add(docref->codnumdoc(),2);
 | 
						||
        dockey.add(docref->numdoc(),3);
 | 
						||
        qtaplan = docref->qta_residua();
 | 
						||
        qtaplan.round(5);
 | 
						||
        TQuantita qta(line.articolo(), docref->um(), docref->qta_residua());
 | 
						||
        qta.convert2umbase();
 | 
						||
        qtareq = qtareq - qta.val();
 | 
						||
        qtareq.round(5);
 | 
						||
        // documento di rif.
 | 
						||
        docdate = cache().get(LF_DOC,dockey).get(DOC_DATADOC); 
 | 
						||
        r2.put(format("@86gDocumento %s",(const char *)docref->codnumdoc() ));
 | 
						||
        r2.put(format("@101g%d",docref->annodoc() ));
 | 
						||
        r2.put(format("@106gn.%6ld",docref->numdoc()));
 | 
						||
        r2.put(format("@115griga %3d",docref->numrig()));
 | 
						||
        um = docref->um();
 | 
						||
      } 
 | 
						||
      else
 | 
						||
      {
 | 
						||
        qtaplan = qtareq;
 | 
						||
      }
 | 
						||
      TQuantita qta(line.articolo(), um, qtaplan);
 | 
						||
      r1.put(format("@9g%s", (const char *) docdate.string()));
 | 
						||
      r1.put(format("@20g%s", (const char *)deliv_time.date().string()));
 | 
						||
      r1.put(format("@31g%s", (const char *)line.articolo()));
 | 
						||
      int pos= 52;
 | 
						||
      for (int l = 1; l <= livelli_giacenza().last_level(); l++)
 | 
						||
      {
 | 
						||
        r1.put(format("@%dg%s",pos, (const char *)line.livgiac(l)));
 | 
						||
        pos += livelli_giacenza().code_length(l)+1;
 | 
						||
      }
 | 
						||
      // aggiunge il fabbisogno
 | 
						||
      r1.put(format("@%dg%s", pos+18+1+2+1,  (const char *)qta.val().string(15,2)));
 | 
						||
      r1.put(format("@%dg%s", pos+18+1+2+1+15+1, (const char *)qta.um()));
 | 
						||
      qta.convert2umbase();
 | 
						||
      q = iref.qta() / totreq * qta.val();
 | 
						||
      r1.put(format("@%dg%s", pos, (const char *)q.string(18,5)));
 | 
						||
      r1.put(format("@%dg%s", pos+=18+1, (const char *)"\"\""));
 | 
						||
      pos +=2+1+15+1;
 | 
						||
      r1.put(format("@%dg%s", pos+=2+1,  (const char *)line.codmag()));
 | 
						||
      r1.put(format("@%dg%s", pos+=3+1,  (const char *)line.coddep()));
 | 
						||
      r1.put(format("@%dg%s", pos+=2+1,  (const char *)line.codimp()));
 | 
						||
      r1.put(format("@%dg%s",  pos+=5+1, (const char *)line.codlin()));
 | 
						||
 | 
						||
      r2.put(format("@31g%s", (const char *)line.description()));
 | 
						||
  
 | 
						||
      pr.print(r1);
 | 
						||
      pr.print(r2);
 | 
						||
      rows++;
 | 
						||
    } while ((grref > 0 || srref > 0 || plref > 0) && qtareq > ZERO);
 | 
						||
  }
 | 
						||
  if (--backlevel != 0)
 | 
						||
    print_risalita(line, deliv_time.date(), backlevel, dett_ord);
 | 
						||
  return rows;
 | 
						||
}
 | 
						||
 | 
						||
int TMatResPlanning::print_gross_ref(const TMRP_line& line, int bucket)
 | 
						||
{
 | 
						||
return 0;
 | 
						||
  TPrinter& pr = printer();
 | 
						||
 | 
						||
  TToken_string dockey;
 | 
						||
 | 
						||
  real totreq, qtaplan, qtareq;
 | 
						||
  TMRP_time deliv_time = line.time(bucket);
 | 
						||
  TMRP_time doc_time;
 | 
						||
  line.lead_time(bucket,doc_time, TRUE);
 | 
						||
  TPrintrow r;
 | 
						||
  //const TString & codnum = docref->codnumdoc();
 | 
						||
  TMRP_docref * docref = NULL;
 | 
						||
  TMRP_docrefs * gr_refs= line.record(bucket).requirements_refs();
 | 
						||
  int grref = gr_refs ? gr_refs->items() : 0;
 | 
						||
  while (grref)
 | 
						||
  {
 | 
						||
    docref = gr_refs->get_ref_ptr(--grref);
 | 
						||
    qtaplan = docref->qta_residua();
 | 
						||
    qtaplan.round(5);
 | 
						||
    dockey.add("D",0);
 | 
						||
    dockey.add(docref->annodoc(),1);
 | 
						||
    dockey.add(docref->codnumdoc(),2);
 | 
						||
    dockey.add(docref->numdoc(),3);
 | 
						||
    // data del documento di rif.
 | 
						||
    //r.put(format("", add(cache().get(LF_DOC,dockey).get(DOC_DATADOC))); 
 | 
						||
    r.put(format("@82g%d",docref->annodoc()));
 | 
						||
    r.put(format("@86g%s",(const char *) docref->codnumdoc()));
 | 
						||
    r.put(format("@90g%ld", docref->numdoc()));
 | 
						||
    r.put(format("@100g%riga n.d", docref->numrig()));
 | 
						||
    //r.put(format("", deliv_time.date().string());
 | 
						||
    const TCodice_um um_nulla;
 | 
						||
    const TQuantita qta(line.articolo(), docref->um(), qtaplan);
 | 
						||
    r.put(format("@10g%s", (const char *)qta.val().string()));
 | 
						||
    r.put(format("@30g%s", (const char *)qta.um()));
 | 
						||
    r.put(format("@50g%s", (const char *)qtaplan.string()));
 | 
						||
    r.put(format("@70g%s", (const char *)qta.um()));
 | 
						||
  }
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
void TMatResPlanning::save_orders(TAssoc_array& docs)
 | 
						||
{
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
 | 
						||
  FOR_EACH_ASSOC_OBJECT(docs, hash, str, obj)
 | 
						||
  {
 | 
						||
    TDocumento& doc = (TDocumento&)*obj;
 | 
						||
    int err;
 | 
						||
    if (doc.get_long(DOC_NDOC))
 | 
						||
    {
 | 
						||
      // riscrittura; elimina righe con qta zero
 | 
						||
      if (!m.get_bool(F_ALL_ORDERSCHANGES))
 | 
						||
        for (int numriga = doc.physical_rows(); numriga >0 ; numriga--)
 | 
						||
        {
 | 
						||
          if (doc[numriga].get_real(RDOC_QTA).is_zero())
 | 
						||
            doc.destroy_row(numriga, TRUE);
 | 
						||
        }
 | 
						||
      err = doc.rewrite();
 | 
						||
    }
 | 
						||
    else
 | 
						||
      // generazione
 | 
						||
      err = doc.write();
 | 
						||
    if (err != NOERR)
 | 
						||
      doc.read(); // unlock
 | 
						||
  }
 | 
						||
  
 | 
						||
  docs.destroy();
 | 
						||
}
 | 
						||
 | 
						||
bool TMatResPlanning::ask_save()
 | 
						||
{
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
  TSheet_field& sf = m.sfield(F_ORDINI);
 | 
						||
  
 | 
						||
  int tot = 0;
 | 
						||
  FOR_EACH_SHEET_ROW(sf, r, row)
 | 
						||
  {
 | 
						||
    TToken_string& riga = *row;
 | 
						||
    if (*riga.get(0) == 'X')
 | 
						||
      tot++;
 | 
						||
  }
 | 
						||
  
 | 
						||
  bool yes = TRUE;
 | 
						||
  if (tot > 0)
 | 
						||
    yes = yesno_box("Si desidera elaborare %d righe?", tot);
 | 
						||
  return yes;  
 | 
						||
}
 | 
						||
 | 
						||
/////////// finished: 90%
 | 
						||
/////////// tested  : 90%
 | 
						||
// genera gli ordini di produzione o a fornitore
 | 
						||
bool TMatResPlanning::emit_orders()
 | 
						||
{
 | 
						||
  TMatResMask& m = *_mask;
 | 
						||
 | 
						||
  TSheet_field& sf = m.sfield(F_ORDINI);
 | 
						||
  const bool divide_by_date = m.get_bool(F_DIVIDEBYDATE);
 | 
						||
  const bool divide_by_art = m.get_bool(F_DIVIDEBYART);
 | 
						||
  TTipo_documento tipo_doc_forn(m.get(F_TIPO_FORN ));
 | 
						||
  TTipo_documento tipo_doc_prod(m.get(F_TIPO_PROD ));
 | 
						||
 | 
						||
  TDate today(TODAY);
 | 
						||
  int docf = 0, docp = 0;
 | 
						||
  TAssoc_array docs;
 | 
						||
  TToken_string key;
 | 
						||
  int ignore_docdate_too_soon = 0;
 | 
						||
  int ignore_duedate_lt_docdate = 0;
 | 
						||
  
 | 
						||
  if (!ask_save())
 | 
						||
    return FALSE;
 | 
						||
  
 | 
						||
  TProgind pi(sf.items(), "Generazione ordini", FALSE, TRUE);
 | 
						||
  
 | 
						||
  FOR_EACH_SHEET_ROW(sf, r, row)
 | 
						||
  {
 | 
						||
    pi.addstatus(1);
 | 
						||
  
 | 
						||
    TToken_string& riga = *row;
 | 
						||
    if (*riga.get(0) == 'X')
 | 
						||
    {
 | 
						||
      bool ok=TRUE;
 | 
						||
      const bool newdoc = riga.get_long(F_DOCNUM - FIRST_FIELD) == 0L;
 | 
						||
      const TDate datadoc = riga.get(sf.cid2index(F_DATADOC));
 | 
						||
      const TDate datacon = riga.get(sf.cid2index(F_DATACONS));
 | 
						||
      const char type = riga.get_char(sf.cid2index(F_ORD_TYPE));
 | 
						||
      const bool prod = type == 'P';
 | 
						||
      const long forn = prod ? 0 : riga.get_long(sf.cid2index(F_FORNITORE));
 | 
						||
      const long numdoc = riga.get_long(sf.cid2index(F_DOCNUM));
 | 
						||
      real qta(riga.get(sf.cid2index(F_QUANTITA)));
 | 
						||
      const TString16 realcodnum =  riga.get(sf.cid2index(F_DOCCODNUM));
 | 
						||
 | 
						||
      riga.add(" ",sf.cid2index(F_OK));
 | 
						||
      if (qta.is_zero())
 | 
						||
        continue;
 | 
						||
      if (datadoc < today && newdoc)
 | 
						||
        if (ignore_docdate_too_soon != K_ENTER && ignore_docdate_too_soon != K_ESC)
 | 
						||
        {
 | 
						||
          TYesnoallnone_box b(format("Riga %d: data di emissione del documento (%s) inferiore a quella odierna. Confermare?",r+1,(const char *)datadoc.string()), K_NO);
 | 
						||
          ignore_docdate_too_soon = b.run();
 | 
						||
        }
 | 
						||
        if (ignore_docdate_too_soon == K_NO || ignore_docdate_too_soon == K_ESC)
 | 
						||
          continue;
 | 
						||
      if (datacon < datadoc && newdoc)
 | 
						||
        if (ignore_duedate_lt_docdate != K_ENTER && ignore_duedate_lt_docdate != K_ESC)
 | 
						||
        {
 | 
						||
          TYesnoallnone_box b(format("Riga %d: data di consegna (%s) inferiore a quella di emissione del documento (%s). Confermare?",r+1,(const char *)datacon.string(), (const char *)datadoc.string()), K_NO);
 | 
						||
          ignore_duedate_lt_docdate = b.run();
 | 
						||
        }
 | 
						||
        if (ignore_duedate_lt_docdate == K_NO || ignore_duedate_lt_docdate == K_ESC)
 | 
						||
          continue;
 | 
						||
      if (forn == 0L && newdoc)
 | 
						||
      { 
 | 
						||
        if ((prod && !tipo_doc_prod.clifo_optional()) ||
 | 
						||
          (!prod && !tipo_doc_forn.clifo_optional()))
 | 
						||
        {
 | 
						||
          error_box("Codice fornitore mancante alla riga %d", r+1);
 | 
						||
          continue;
 | 
						||
        }
 | 
						||
      }
 | 
						||
      key.cut(0);
 | 
						||
      if (newdoc)
 | 
						||
      {
 | 
						||
        key.add(type);
 | 
						||
        key.add(forn);
 | 
						||
        key.add(datadoc.string());
 | 
						||
        key.add(divide_by_date ? datacon.string() : " ");
 | 
						||
        key.add(divide_by_art ? riga.get(sf.cid2index(F_ARTICOLO)) : " ");
 | 
						||
      } 
 | 
						||
      else 
 | 
						||
      {
 | 
						||
        key.format("%c%ld",prod ? 'P':'F',numdoc);
 | 
						||
      }
 | 
						||
      TDocumento* doc = (TDocumento*)docs.objptr(key);
 | 
						||
      if (doc == NULL)
 | 
						||
      {
 | 
						||
        if (docs.items() >= 200)
 | 
						||
          save_orders(docs);
 | 
						||
      
 | 
						||
        TString16 codnum = m.get(prod ? F_NUM_PROD : F_NUM_FORN );
 | 
						||
        const TString& tipdoc = m.get(prod ? F_TIPO_PROD: F_TIPO_FORN );
 | 
						||
        if (numdoc)
 | 
						||
        {
 | 
						||
          if (codnum != realcodnum)
 | 
						||
            codnum = realcodnum;
 | 
						||
        }
 | 
						||
        doc = new TDocumento('D', datadoc.year(), codnum, 0);
 | 
						||
        doc->set_tipo(tipdoc);
 | 
						||
        TRectype& testata = doc->head();
 | 
						||
        if (numdoc)
 | 
						||
        {
 | 
						||
          doc->put(DOC_NDOC, numdoc);
 | 
						||
          ok = doc->read()==NOERR;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
          testata.put(DOC_DATADOC, datadoc);
 | 
						||
          testata.put(DOC_DATACONS, divide_by_date ? datacon : datadoc);
 | 
						||
        }
 | 
						||
        if (ok)
 | 
						||
        {
 | 
						||
          if (prod)
 | 
						||
          {
 | 
						||
            testata.put(DOC_TIPOCF, "F");  // Il fornitore 0 sono io
 | 
						||
            docp++;
 | 
						||
          }
 | 
						||
          else
 | 
						||
          {
 | 
						||
            testata.put(DOC_TIPOCF, "F");
 | 
						||
            testata.put(DOC_CODCF, forn);
 | 
						||
            docf++;
 | 
						||
          }
 | 
						||
          testata.put(DOC_CAUSMAG, doc->tipo().caus_mov());
 | 
						||
          docs.add(key, doc);
 | 
						||
        }
 | 
						||
      }
 | 
						||
      if (ok)
 | 
						||
      {
 | 
						||
        int numriga = riga.get_int(sf.cid2index(F_DOCNRIGA));
 | 
						||
        TRiga_documento& rdoc = numdoc ? (*doc)[numriga] : doc->new_row(m.get(prod ? F_RIGA_PROD : F_RIGA_FORN));
 | 
						||
        if (numdoc)
 | 
						||
          qta += rdoc.get_real(RDOC_QTA);
 | 
						||
        rdoc.put(RDOC_CODART, riga.get(sf.cid2index(F_ARTICOLO)));
 | 
						||
      
 | 
						||
        TString80 str;
 | 
						||
        for (int l= livelli_giacenza().last_level(); l>=1; l--)
 | 
						||
          livelli_giacenza().pack_grpcode(str, riga.get(sf.cid2index(F_LIV1+l-1)), l);
 | 
						||
        rdoc.put(RDOC_LIVELLO,str);
 | 
						||
      
 | 
						||
        add_magcode(str,riga.get(sf.cid2index(F_MAGAZZINO)));
 | 
						||
        add_depcode(str,riga.get(sf.cid2index(F_DEPOSITO)));
 | 
						||
        rdoc.put(RDOC_CODMAG, str);
 | 
						||
            
 | 
						||
        rdoc.put(RDOC_IMPIANTO, riga.get(sf.cid2index(F_CODIMP)));
 | 
						||
        rdoc.put(RDOC_LINEA, riga.get(sf.cid2index(F_CODLIN)));
 | 
						||
        rdoc.put(RDOC_QTA, qta);
 | 
						||
  
 | 
						||
        rdoc.put(RDOC_UMQTA, riga.get(sf.cid2index(F_UM)));
 | 
						||
        rdoc.put(RDOC_PREZZO, riga.get(sf.cid2index(F_PREZZO)));
 | 
						||
        rdoc.put(RDOC_DESCR, riga.get(sf.cid2index(F_DESCART)));
 | 
						||
        if (!divide_by_date)
 | 
						||
          rdoc.put(RDOC_DATACONS,datacon.string());
 | 
						||
          
 | 
						||
        TString16 cod;
 | 
						||
        if (forn > 0)
 | 
						||
        {
 | 
						||
          cod.format("F|%ld", forn);
 | 
						||
          cod = cache().get(LF_CFVEN, cod, CFV_ASSFIS);
 | 
						||
        }
 | 
						||
        if (cod.empty())
 | 
						||
          cod = cache().get(LF_ANAMAG, riga.get(sf.cid2index(F_ARTICOLO)), ANAMAG_CODIVA);
 | 
						||
        rdoc.put(RDOC_CODIVA, cod);    
 | 
						||
  
 | 
						||
        riga.add("X",sf.cid2index(F_OK));
 | 
						||
      } 
 | 
						||
    }
 | 
						||
  }
 | 
						||
  save_orders(docs);
 | 
						||
  
 | 
						||
  if (sf.items())
 | 
						||
  {
 | 
						||
    FOR_EACH_SHEET_ROW_BACK(sf, r, row)
 | 
						||
    {
 | 
						||
      if ((*row->get(sf.cid2index(F_SELECTED)) == 'X' && *row->get(sf.cid2index(F_OK))=='X')
 | 
						||
        || real(row->get(sf.cid2index(F_QUANTITA))).is_zero())
 | 
						||
      {
 | 
						||
        if (m.get_bool(F_ALL_ORDERSCHANGES))
 | 
						||
          row->add("", sf.cid2index(F_QUANTITA));
 | 
						||
        else
 | 
						||
          sf.destroy(r, FALSE);
 | 
						||
      }
 | 
						||
    }
 | 
						||
    sf.force_update();
 | 
						||
  }
 | 
						||
  m.enable(DLG_SAVEREC, sf.items() > 0);
 | 
						||
 | 
						||
  return TRUE;
 | 
						||
}
 | 
						||
 | 
						||
void TMatResPlanning::compute()
 | 
						||
{
 | 
						||
  if (preprocess_cycle()) // req iniziale dai docs
 | 
						||
    if (net_requirement_cycle())
 | 
						||
      build_orders();
 | 
						||
}
 | 
						||
 | 
						||
void TMatResPlanning::risalita(const TMask & m)
 | 
						||
{
 | 
						||
  TSheet_field & sf= m.sfield(F_ORDINI);
 | 
						||
  TToken_string & row=sf.row(sf.selected());
 | 
						||
  TString art;
 | 
						||
  TString16 liv;
 | 
						||
  TString8 mag, magc, imp, lin;
 | 
						||
  long codcf;
 | 
						||
  codcf = row.get_long(sf.cid2index(F_FORNITORE));
 | 
						||
  row.get(sf.cid2index(F_ARTICOLO), art);
 | 
						||
  for (int l= livelli_giacenza().last_level(); l>=1; l--)
 | 
						||
    livelli_giacenza().pack_grpcode(liv, row.get(sf.cid2index(F_LIV1+l-1)), l);
 | 
						||
  add_magcode(mag, row.get(sf.cid2index(F_MAGAZZINO)));
 | 
						||
  add_depcode(mag, row.get(sf.cid2index(F_DEPOSITO )));
 | 
						||
  row.get(sf.cid2index(F_CODIMP), imp);
 | 
						||
  row.get(sf.cid2index(F_CODLIN), lin);
 | 
						||
 | 
						||
  if (art.blank())
 | 
						||
    return;
 | 
						||
  TMRP_line* line = _articles.find(art, liv, mag, magc, imp, lin, codcf);
 | 
						||
  if (!line)
 | 
						||
    line = _articles.find(art, liv, mag, magc, imp, lin, 0L);
 | 
						||
  if (line)
 | 
						||
  {
 | 
						||
    TDate todate(row.get(sf.cid2index(F_DATACONS)));
 | 
						||
    TDate fromdate = todate;
 | 
						||
    round_date(fromdate);
 | 
						||
    round_date(todate,TRUE);
 | 
						||
    
 | 
						||
    TRisalita_mask *rismask;
 | 
						||
    rismask = new TRisalita_mask(line, fromdate, todate, fromdate <= _mask->get_date(F_DADATA),_mask->get_int(F_XTRA_LDTIME));
 | 
						||
    rismask->run();
 | 
						||
    delete rismask;
 | 
						||
  } else
 | 
						||
    message_box("Impossibile rintracciare la riga d'ordine indicata tra quelle generate in MRP");
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
bool TMatResPlanning::print_exceptions(TMask &m)
 | 
						||
{
 | 
						||
  TExceptions_array e;
 | 
						||
  bool anticipi  = m.get_bool(S_HURRYUP_EXCEPT);
 | 
						||
  bool posticipi = m.get_bool(S_DELAY_EXCEPT);
 | 
						||
  bool extra     = m.get_bool(S_EXTRA_EXCEPT);   
 | 
						||
  if (_articles.items()>0)
 | 
						||
  {
 | 
						||
    // PER OGNI ARTICOLO ...
 | 
						||
    const long max_mrp_rows=_articles.items();
 | 
						||
    TProgind pi=((max_mrp_rows+1) ,"Ricerca eccezioni...", TRUE, TRUE);
 | 
						||
    for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
 | 
						||
    {
 | 
						||
      pi.addstatus(1);
 | 
						||
      if (pi.iscancelled()) 
 | 
						||
        return FALSE;
 | 
						||
      TMRP_line &mrpline=_articles[mrp_row];
 | 
						||
      mrpline.reset_excepts();
 | 
						||
      mrpline.find_ad_excepts(anticipi, posticipi, e);
 | 
						||
      if (extra)
 | 
						||
        mrpline.find_extra_excepts(_mask->get_bool(F_DIVIDEBYART)||_mask->get_bool(F_DIVIDEBYDATE), e);
 | 
						||
    } // ... for each article
 | 
						||
  }
 | 
						||
  if (e.items()<=0)
 | 
						||
    message_box("Nessuna eccezione rilevata");
 | 
						||
  else
 | 
						||
    print_exceptions(e); 
 | 
						||
  return e.items()>0;
 | 
						||
}
 | 
						||
 | 
						||
void TMatResPlanning::print_except_header(TPrinter& pr)
 | 
						||
{
 | 
						||
  TString format;
 | 
						||
  TPrintrow row;
 | 
						||
  print_header(pr);
 | 
						||
  row.put("@48G@BSTAMPA TABULATO ECCEZIONI DA M.R.P.");
 | 
						||
  pr.setheaderline(1,row);
 | 
						||
  row.reset();
 | 
						||
  row.put((const char *)TString(131,'-'));
 | 
						||
  pr.setheaderline(4,row);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void TMatResPlanning::print_exceptions(TExceptions_array &excepts)
 | 
						||
{
 | 
						||
  if (excepts.items())
 | 
						||
  {
 | 
						||
    TPrinter& pr = printer();
 | 
						||
    pr.open();
 | 
						||
  
 | 
						||
    pr.setheaderhandler(print_except_header);
 | 
						||
    pr.headerlen(6);
 | 
						||
    pr.setfooterhandler(print_footer);
 | 
						||
    pr.footerlen(2);
 | 
						||
    TString_array keys;
 | 
						||
    TToken_string key, lastkey;
 | 
						||
    TString tmp;
 | 
						||
    excepts.get_keys(keys);
 | 
						||
    keys.sort();
 | 
						||
    int header=0;
 | 
						||
    for (int k=0; k< keys.items(); k++)
 | 
						||
    {
 | 
						||
      key = keys.row(k);
 | 
						||
      key.get(0,tmp);
 | 
						||
      if (tmp != lastkey.get(0))
 | 
						||
        header = 0;
 | 
						||
      else if (key.get(1,tmp)&& tmp != lastkey.get(1))
 | 
						||
        header = 0;
 | 
						||
      else if (key.get(2,tmp) && tmp != lastkey.get(2))
 | 
						||
        header = 1;
 | 
						||
      else 
 | 
						||
        header = 2;
 | 
						||
      const TException & e = (const TException &)excepts[key];
 | 
						||
      const TMRP_line &line = e.mrpline();
 | 
						||
      line.print_exception(e.from(), e.to(), e.qta(), header);
 | 
						||
      lastkey = key;
 | 
						||
    }
 | 
						||
    pr.close();
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
bool TMatResPlanning::menu(MENU_TAG mt)
 | 
						||
{             
 | 
						||
  bool ok = TRUE;
 | 
						||
  if (mt == MENU_ITEM(1))
 | 
						||
    _mask->sel().run();
 | 
						||
  else
 | 
						||
    ok = TSkeleton_application::menu(mt);
 | 
						||
  return ok;  
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void TMatResPlanning::main_loop()
 | 
						||
{
 | 
						||
  open_files(LF_TABCOM, LF_TAB, LF_DOC, LF_RIGHEDOC, 0);
 | 
						||
  open_files(LF_CLIFO, LF_CFVEN, LF_OCCAS, LF_INDSP,LF_CONDV, 0);
 | 
						||
  open_files(LF_ANAMAG, LF_DIST, LF_RDIST, 0);
 | 
						||
  open_files(LF_MAG, LF_STOMAG, LF_DESLIN, LF_CODCORR, 0);
 | 
						||
 | 
						||
  _mask = new TMatResMask;
 | 
						||
  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 (!prassid.get_bool("GES", NULL, A_CONTRATTI) ||
 | 
						||
    !prassid.get_bool("GESCONCC"))
 | 
						||
      _mask->disable(F_TIPOCF_CONDV);
 | 
						||
 | 
						||
  while (_mask->run()!=K_QUIT);
 | 
						||
 | 
						||
  delete _mask;
 | 
						||
}
 | 
						||
 | 
						||
void print_header(TPrinter& pr)
 | 
						||
{
 | 
						||
  TString format;
 | 
						||
  TPrintrow row;
 | 
						||
  TLocalisamfile firm(LF_NDITTE);
 | 
						||
  TLocalisamfile anag(LF_ANAG);
 | 
						||
  firm.put("CODDITTA",main_app().get_firm());
 | 
						||
  firm.read();
 | 
						||
  anag.put("TIPOA",firm.get("TIPOA"));
 | 
						||
  anag.put("CODANAGR",firm.get("CODANAGR"));
 | 
						||
  anag.read();
 | 
						||
  format << "@2g" << anag.get("RAGSOC")<< "@80g@>@110gPagina @#";
 | 
						||
  row.put(format);
 | 
						||
  pr.setheaderline(0,row);
 | 
						||
}
 | 
						||
 | 
						||
void print_footer(TPrinter& pr)
 | 
						||
{
 | 
						||
  TPrintrow row;
 | 
						||
  pr.setfooterline(1,row);
 | 
						||
}
 | 
						||
 | 
						||
int mr2100(int argc, char* argv[])
 | 
						||
{
 | 
						||
  TMatResPlanning a;
 | 
						||
  
 | 
						||
  a.run(argc, argv, "Material Requirements Planning");
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 |