Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 1.7 patch 054 aga sul main trunk git-svn-id: svn://10.65.10.50/trunk@9659 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			1820 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1820 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
// Stampa esplosione distinte
 | 
						|
// Ma ke freddo fa!?
 | 
						|
// ...
 | 
						|
// & God took away Ish 2 create Isha
 | 
						|
// Warning: TAssoc_array heavily used in this App
 | 
						|
// ...
 | 
						|
// Señor... donde esta El Jefe!?
 | 
						|
// Ola! Estrella querida... Yo soy El Jefe!
 | 
						|
 | 
						|
#include <applicat.h>
 | 
						|
#include <form.h>
 | 
						|
#include <mask.h>
 | 
						|
#include <printer.h>
 | 
						|
#include <progind.h>
 | 
						|
#include <sheet.h>
 | 
						|
#include <tabutil.h>
 | 
						|
 | 
						|
#include "../cg/cglib01.h"
 | 
						|
#include "../mg/mglib.h"
 | 
						|
#include "../ve/velib.h"
 | 
						|
 | 
						|
#include "dblib.h"
 | 
						|
#include <doc.h>
 | 
						|
#include <rdoc.h>
 | 
						|
#include "../mg/anamag.h"
 | 
						|
 | 
						|
#include "db1100a.h"
 | 
						|
 | 
						|
#define DIST_HEAD    0
 | 
						|
 | 
						|
/////////////////////////////////////////////////////////
 | 
						|
// Inizio ammenicoli di supporto
 | 
						|
/////////////////////////////////////////////////////////
 | 
						|
 | 
						|
enum seltype  { by_num, by_date };
 | 
						|
enum expltype { mat_base, scalare};
 | 
						|
enum valtype  { no_val, last_cost, average_cost, pond_cost, last2cost, std_cost, LIFO_annuale, LIFO_storico, FIFO_annuale, FIFO_storico ,prezzo_listino};
 | 
						|
 | 
						|
struct _ParmStruct
 | 
						|
{
 | 
						|
  seltype         _selections;
 | 
						|
  expltype        _explosion;
 | 
						|
  valtype         _valorization;
 | 
						|
  TExplosion_grouping         _group_by;
 | 
						|
  TString_array   _numerazioni;
 | 
						|
  TString16       _anno_es, _catven, _codlist, _from_num, _to_num, _sl_mag, _mb_mag; // Ma perche'...
 | 
						|
  TDate           _from_date, _to_date, _obs_date;
 | 
						|
  long            _from_doc, _to_doc;
 | 
						|
  int             _year, _periods, _det_lev, _ordering;
 | 
						|
  bool            _last_qta, 
 | 
						|
                  _vis_art, _vis_lav, _vis_vir, _vis_gho, 
 | 
						|
                  _fabbisogno, _no_fabbis_fin, _no_zero_ord,
 | 
						|
                  _val_magmb, _val_depmb, _newpage, _det_ord_for,
 | 
						|
                  _separate_dist, _separate_giac,
 | 
						|
                  _add_orc, _add_orf, _add_prf, _add_prc, _add_acl, _add_incl,
 | 
						|
                  _normal_disp;
 | 
						|
  char            _liv_attenzione;                  
 | 
						|
};
 | 
						|
 | 
						|
struct _CallBackStruct
 | 
						|
{
 | 
						|
  _ParmStruct*  _p;
 | 
						|
  TAssoc_array* _a;
 | 
						|
};
 | 
						|
 | 
						|
static TString __key;
 | 
						|
static TDate   __last_period;
 | 
						|
static TDate   __current_period;
 | 
						|
static TString __current_art;
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TArticolo_giacenza_static
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// 
 | 
						|
// Particolarita' della classe: il metodo "vero" per calcolare
 | 
						|
// la disponibilita' viene chiamato solo la prima volta, poi viene sempre 
 | 
						|
// tenuto in memoria per eventuali aggiornamenti sulle qta, in modo
 | 
						|
// da non fare calcoli pocciosi sul file delle giacenza
 | 
						|
 | 
						|
class TArticolo_giacenza_static : public TArticolo_giacenza
 | 
						|
{
 | 
						|
  bool _calc;
 | 
						|
  real _disp; // Disponibilita': sempre espressa in UM base!!
 | 
						|
              // Prima di effettuare addizioni/sottrazioni ricordarsi di convertire  
 | 
						|
  TArray _ordinato_fornitori; // Array di real per l'ordinato fornitori (espressi in UM BASE)
 | 
						|
  TString16 _umbase;
 | 
						|
 | 
						|
protected:  
 | 
						|
  void calc_ordinato_fornitori(_ParmStruct *p, const char * codmag, const char * livello);
 | 
						|
  void calcola_ordinato_documento(TRectype& rec);
 | 
						|
public:
 | 
						|
  const real & ordinato_fornitori(const int p); // ritorna l'ordinato fornitori per il periodo indicato
 | 
						|
  const real get_scmin(const char * annoes, const char * codmag, const char * livello);
 | 
						|
  real& static_disp(_ParmStruct* p, const char * codmag, const char * livello);
 | 
						|
  TArticolo_giacenza_static(const char* codice = NULL);
 | 
						|
  TArticolo_giacenza_static(const TRectype& rec);
 | 
						|
  virtual ~TArticolo_giacenza_static() {}
 | 
						|
};
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TArticolo_cache
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
class TArticolo_cache : public TRecord_cache
 | 
						|
{
 | 
						|
protected:
 | 
						|
  virtual TObject* rec2obj(const TRectype& rec) const;
 | 
						|
  
 | 
						|
public:
 | 
						|
  TArticolo_giacenza_static& art(const char* key);
 | 
						|
  TArticolo_cache();
 | 
						|
  virtual ~TArticolo_cache() { }
 | 
						|
};
 | 
						|
 | 
						|
TArticolo_cache::TArticolo_cache()
 | 
						|
             : TRecord_cache(LF_ANAMAG, 1)
 | 
						|
{ }        
 | 
						|
 | 
						|
TObject* TArticolo_cache::rec2obj(const TRectype& curr) const
 | 
						|
{
 | 
						|
  TArticolo_giacenza_static * a = new TArticolo_giacenza_static(curr);
 | 
						|
  return a;
 | 
						|
}
 | 
						|
 | 
						|
TArticolo_giacenza_static& TArticolo_cache::art(const char* key)
 | 
						|
{
 | 
						|
  TArticolo_giacenza_static& art = (TArticolo_giacenza_static&)query(key);
 | 
						|
  return art;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TRiga_esplosione2print
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TRiga_esplosione2print : public TRiga_esplosione
 | 
						|
{
 | 
						|
  real _fabbisogno;
 | 
						|
  real _disponibilita;
 | 
						|
  real _value, _unitario;
 | 
						|
  real _qta2order; 
 | 
						|
  real _residuo;
 | 
						|
  real _ordfor;
 | 
						|
  real _totordfor;
 | 
						|
  TDate _dtacons;
 | 
						|
  TString8 _codmag;
 | 
						|
 | 
						|
public:
 | 
						|
  const TString& mag() const             { return _codmag; }
 | 
						|
  const TDate& datacons() const          { return _dtacons;       }
 | 
						|
  const real& fabbisogno() const         { return _fabbisogno;    }
 | 
						|
  const real& disponibilita() const      { return _disponibilita; }
 | 
						|
  const real& value() const              { return _value;         }
 | 
						|
  const real& unitary_value() const      { return _unitario;      }
 | 
						|
  const real& qta2order() const          { return _qta2order;     }
 | 
						|
  const real& residuo() const            { return _residuo;       }
 | 
						|
  const real& ordfor() const             { return _ordfor;        }
 | 
						|
  const real& totordfor() const          { return _totordfor;     }
 | 
						|
  void  set_mag(const char *s)           { _codmag = s;        }
 | 
						|
  void  set_datacons(const TDate& d)     { _dtacons = d;       }
 | 
						|
  void  set_fabbisogno(const real& r)    { _fabbisogno    = r; }
 | 
						|
  void  set_disponibilita(const real& r) { _disponibilita = r; }
 | 
						|
  void  set_value(const real& r)         { _value         = r; }
 | 
						|
  void  set_unitary_value(const real& r) { _unitario      = r; }
 | 
						|
  void  set_residuo(const real& r)       { _residuo       = r; }
 | 
						|
  void  set_qta2order(const real& r)     { _qta2order     = r; }
 | 
						|
  void  set_ordfor(const real& r)        { _ordfor        = r; }
 | 
						|
  void  set_totordfor(const real& r)     { _totordfor     = r; }
 | 
						|
  TRiga_esplosione2print() {};
 | 
						|
  TRiga_esplosione2print(const TDistinta_tree& tree, const char *codmag);
 | 
						|
  TRiga_esplosione2print(const TRiga_esplosione& re, const char *codmag);
 | 
						|
  ~TRiga_esplosione2print() {};  
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
TRiga_esplosione2print::TRiga_esplosione2print(const TDistinta_tree& tree, const char *codmag)
 | 
						|
                : TRiga_esplosione(tree), _codmag(codmag)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
TRiga_esplosione2print::TRiga_esplosione2print(const TRiga_esplosione& re, const char *codmag)
 | 
						|
                : TRiga_esplosione(re), _codmag(codmag)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TDist2Explode
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
class TDist2Explode : public TObject
 | 
						|
{
 | 
						|
  TCodice_articolo _cod;
 | 
						|
  TString16        _livgiac;
 | 
						|
  TCodice_um       _um;
 | 
						|
  TString8         _imp, _lin, _mag;
 | 
						|
  real             _qta;
 | 
						|
  TDate            _datacons;
 | 
						|
  TDate            _data_per; // Data limite del periodo del quale fa parte questa distinta da esplodere
 | 
						|
  bool             _acq_ven;
 | 
						|
 | 
						|
protected:
 | 
						|
  void set(const TMask& msk);
 | 
						|
  
 | 
						|
public:
 | 
						|
  TRiga_esplosione* head_obj();
 | 
						|
  void set(const TRiga_documento& r, const TMask& msk);
 | 
						|
  void set(TToken_string& t, const TMask& msk);
 | 
						|
  void set_cod(const char* c) { _cod = c; }
 | 
						|
  void set_liv(const char* l) { _livgiac = l; }
 | 
						|
  void set_imp(const char* i) { _imp = i; }
 | 
						|
  void set_lin(const char* l) { _lin = l; }
 | 
						|
  void set_mag(const char* m) { _mag = m; }
 | 
						|
  void set_um (const char* u) { _um = u;}
 | 
						|
  void set_qta(const real& q) { _qta = q;}
 | 
						|
  void set_datacons(const TDate& d) { _datacons = d; }
 | 
						|
  void set_acq(const bool b)        { _acq_ven = b; }
 | 
						|
  real&  qta()             { return _qta;}
 | 
						|
  const TDate& datacons()  { return _datacons;}
 | 
						|
  const TDate& data_per()  { return _data_per;}
 | 
						|
  const bool&  acqven()    { return _acq_ven; }
 | 
						|
  const TString& imp()     { return _imp; }
 | 
						|
  const TString& lin()     { return _lin; }
 | 
						|
  const TString& mag()     { return _mag; }
 | 
						|
  const TCodice_um& um()   { return _um; }
 | 
						|
  const TString& liv()     { return _livgiac; }
 | 
						|
  const TCodice_articolo& cod() { return _cod; }
 | 
						|
  const char * key();
 | 
						|
  TDist2Explode () {};
 | 
						|
  virtual ~TDist2Explode() {};  
 | 
						|
};
 | 
						|
  
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TExplode_distinta_form
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
class TExplode_distinta_form : public TForm
 | 
						|
{
 | 
						|
  static TExplode_distinta_form *_f; // Yes, I am THIS.
 | 
						|
  TDistinta_tree  _distinta;      // Albero della distinta
 | 
						|
  TArticolo_cache _art_cache;     // Cache di articoli con disponibilita
 | 
						|
  TArray          _exploded_tree; // Righe di eplosione
 | 
						|
  TAssoc_array    _valori;        // Righe dei valori dei nodi e delle foglie
 | 
						|
  TAssoc_array    _prodorder;       // Righe dei residui (solo semilavorati/nodi)
 | 
						|
  TAssoc_array    _prodordert;       // Righe dei residui (solo semilavorati/nodi)
 | 
						|
  TAssoc_array    _disponib;       // Righe dei residui (solo semilavorati/nodi)
 | 
						|
  TDist2Explode   *_d;            // Distinta corrente da esplodere
 | 
						|
  _ParmStruct     *_p;            // Struttura dei parametri
 | 
						|
  int             _curr_row;      // Riga corrente della distinta esplosa da stampare
 | 
						|
 | 
						|
protected:  
 | 
						|
  void print_header(TPrinter& p);
 | 
						|
  void print_footer(TPrinter& p);
 | 
						|
  static void dist_header_handler(TPrinter& p);
 | 
						|
  static void dist_footer_handler(TPrinter& p);
 | 
						|
  virtual bool validate(TForm_item &, TToken_string &);
 | 
						|
  void set_explosion_rows(TArray& exp_array);
 | 
						|
  real res2produce_by_father(TRiga_esplosione& re);
 | 
						|
 | 
						|
public:
 | 
						|
  void print_explosion_rows();
 | 
						|
  void reset_rows(bool firsttime = TRUE);
 | 
						|
  void set_distinta(TDist2Explode* dd)   { _d = dd; }
 | 
						|
  void set_parameters(_ParmStruct* ps);
 | 
						|
  void explode_and_print();
 | 
						|
  void reset_cache() { _art_cache.destroy(); }
 | 
						|
  TExplode_distinta_form(const char *);
 | 
						|
  virtual ~TExplode_distinta_form();
 | 
						|
};
 | 
						|
 | 
						|
TExplode_distinta_form* TExplode_distinta_form::_f = NULL;
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TEsplosione_distinta_app
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TEsplosione_distinta_app : public TSkeleton_application
 | 
						|
{
 | 
						|
  TMask          *_mask;
 | 
						|
  TDocumento     *_doc;
 | 
						|
  TExplode_distinta_form *_form;
 | 
						|
  TAssoc_array    _dist_list;
 | 
						|
  TArray          _date_array;
 | 
						|
  TCodgiac_livelli *_liv_giac;
 | 
						|
  // Dati "i/n/m/putati" ma non ancora condannati...
 | 
						|
  _ParmStruct    _parameters;
 | 
						|
  
 | 
						|
protected:
 | 
						|
  static bool sheet_notify(TSheet_field& s, int r, KEY key); 
 | 
						|
  virtual bool create(); 
 | 
						|
  virtual bool destroy(); 
 | 
						|
  virtual void main_loop();
 | 
						|
  static bool  check_articoli(TMask_field& f, KEY k);
 | 
						|
  void compile_list();
 | 
						|
  void compile_periods();
 | 
						|
  void compile_numeration_list();
 | 
						|
  virtual void print();
 | 
						|
public:
 | 
						|
  const int date2period(const TDate&);
 | 
						|
  const TDate& date_period(const TDate&);
 | 
						|
  TEsplosione_distinta_app() {};
 | 
						|
  virtual ~TEsplosione_distinta_app() {};
 | 
						|
};
 | 
						|
 | 
						|
inline TEsplosione_distinta_app& app() { return (TEsplosione_distinta_app&)main_app(); }
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////////////
 | 
						|
// Callback & funzione per valorizzazione nodi
 | 
						|
///////////////////////////////////////////////////////////////////
 | 
						|
static real valorizza(const TRiga_esplosione& re, const _CallBackStruct* c)
 | 
						|
{
 | 
						|
  CHECK(c, "Invalid parameter struct passed");
 | 
						|
  real total;
 | 
						|
  TString80 dis(re.articolo());
 | 
						|
  TString16 liv(re.giacenza());
 | 
						|
  
 | 
						|
  if (dis.not_empty())
 | 
						|
  {
 | 
						|
    TAssoc_array* valori = c->_a;
 | 
						|
    _ParmStruct * pp = c->_p;
 | 
						|
    TString80 cod(dis);
 | 
						|
    
 | 
						|
    if (liv.not_empty())
 | 
						|
      cod << ',' << liv;
 | 
						|
 | 
						|
    real* val = (real*)valori->objptr(cod);
 | 
						|
    if (val == NULL)
 | 
						|
    { 
 | 
						|
      const char tipo = re.tipo();
 | 
						|
      switch (tipo)
 | 
						|
      {
 | 
						|
      case 'A':
 | 
						|
        {
 | 
						|
          TArticolo_giacenza art(dis);
 | 
						|
          TString& annoes  = pp->_anno_es;
 | 
						|
          TString& catven  = pp->_catven;
 | 
						|
          TString& codlist = pp->_codlist;
 | 
						|
          TString16 codmag;
 | 
						|
          
 | 
						|
          if (pp->_val_magmb) // Se non c'e' _val_magmb non c'e' nemmeno _val_depmb
 | 
						|
          {                   // Quindi codmag rimane a zero e la valorizzazione viene fatta su tutti i mag.
 | 
						|
            codmag = pp->_mb_mag;
 | 
						|
            if (!pp->_val_depmb && codmag.len() > 3)
 | 
						|
              codmag.cut(3); // se non deve valorizzare sul deposito lo accorciamo
 | 
						|
          }
 | 
						|
          
 | 
						|
          switch (pp->_valorization)
 | 
						|
          {
 | 
						|
          case last_cost:      total = art.ultimo_costo(annoes); break;
 | 
						|
          case last2cost:      total = art.media_costi(annoes); break;
 | 
						|
          case std_cost:       total = art.costo_standard(annoes); break;
 | 
						|
          case average_cost:   total = art.costo_medio(annoes, codmag, liv); break;
 | 
						|
          case pond_cost:      total = art.costo_mediopond(annoes, codmag, liv); break;
 | 
						|
          case LIFO_annuale:   total = art.LIFO_annuale(annoes, codmag, liv); break;
 | 
						|
          case FIFO_annuale:   total = art.FIFO_annuale(annoes, codmag, liv); break;
 | 
						|
          case LIFO_storico:   total = art.LIFO(annoes, codmag, liv); break;
 | 
						|
          case FIFO_storico:   total = art.FIFO(annoes, codmag, liv); break;
 | 
						|
          case prezzo_listino: total = art.prezzo_listino(annoes, catven, codlist); break;
 | 
						|
          default: NFCHECK("Tipo valorizzazione errato: %d", pp->_valorization);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      case 'L':
 | 
						|
        {
 | 
						|
          total = real(cache().get("LAV", dis, "R0"));
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      case 'V':
 | 
						|
        {
 | 
						|
          total = real(cache().get(LF_DIST, dis, "PREZZO"));
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      default :
 | 
						|
        NFCHECK("L'articolo %s non esiste", (const char*)dis);
 | 
						|
      }
 | 
						|
      valori->add(cod, total);
 | 
						|
    }
 | 
						|
    else
 | 
						|
      total = *val;
 | 
						|
  }  
 | 
						|
 | 
						|
  return total;
 | 
						|
}
 | 
						|
 | 
						|
static bool valorizza_nodo(TTree& node, void* jolly, word when)
 | 
						|
{
 | 
						|
  if (when == SCAN_PRE_ORDER)
 | 
						|
  {
 | 
						|
    TArray exploded;
 | 
						|
    TToken_string __path;
 | 
						|
    _CallBackStruct* c = (_CallBackStruct*) jolly;
 | 
						|
    TAssoc_array*    valori = c->_a;
 | 
						|
    TDistinta_tree& dist_node = (TDistinta_tree&) node;
 | 
						|
    
 | 
						|
    dist_node.curr_id(__path);
 | 
						|
    if (dist_node.goto_firstson())
 | 
						|
    {
 | 
						|
      dist_node.explode(exploded, TRUE, RAGGR_EXP_BASE);
 | 
						|
      dist_node.goto_node(__path);
 | 
						|
 | 
						|
      const int items = exploded.items(); // Se 0 siamo su di una foglia...
 | 
						|
      real totale; // Somma dei valori di tutti i materiali di base sottostanti
 | 
						|
 | 
						|
      for (int i = 0; i < items; i++)
 | 
						|
      {
 | 
						|
        TRiga_esplosione& re = (TRiga_esplosione&) exploded[i];
 | 
						|
        // Valore per questa riga (NB si sta calcolando il valore unitario dei componenti di UNA distinta)
 | 
						|
        // ed intanto memorizza i valori dei singoli materiali di base in cache
 | 
						|
        // Per i materiali di base si memorizza soltanto il cod.articolo+liv.giac
 | 
						|
        totale += re.val() * valorizza(re, c);
 | 
						|
      }
 | 
						|
      
 | 
						|
      // Memorizza nell'array il valore di questo nodo memorizzato in total
 | 
						|
      // La chiave per questo nodo e' tutto il path dalla radice...(comprensivo di livello di gaicenza)
 | 
						|
      real* val = (real*)valori->objptr(__path);
 | 
						|
      if (val == NULL)
 | 
						|
        valori->add(__path, totale);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/////////////////////////////////////////////////////////////
 | 
						|
// Implementazione metodi di TArticolo_giacenza_static
 | 
						|
/////////////////////////////////////////////////////////////
 | 
						|
TArticolo_giacenza_static::TArticolo_giacenza_static(const char* codice)
 | 
						|
  : TArticolo_giacenza(codice), _calc(FALSE)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
TArticolo_giacenza_static::TArticolo_giacenza_static(const TRectype& rec)
 | 
						|
  : TArticolo_giacenza(rec), _calc(FALSE)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
const real & TArticolo_giacenza_static::ordinato_fornitori(const int p)
 | 
						|
{
 | 
						|
  // con p ==0 ritorna il totale ordinato fornitori
 | 
						|
  const real * r = (real *)_ordinato_fornitori.objptr(p);
 | 
						|
  return r ? *r : ZERO;
 | 
						|
}
 | 
						|
 | 
						|
const real TArticolo_giacenza_static::get_scmin(const char * annoes, const char * codmag, const char * livello)
 | 
						|
{
 | 
						|
  real r;
 | 
						|
  const int i = find_mag(annoes, codmag, livello);
 | 
						|
  if (i > 0)
 | 
						|
  {
 | 
						|
    TRecord_array& ra = mag(annoes);
 | 
						|
    r = ra[i].get_real("SCORTAMIN");
 | 
						|
  }
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
void TArticolo_giacenza_static::calcola_ordinato_documento(TRectype& rec)
 | 
						|
{
 | 
						|
  CHECK(rec.num() == LF_DOC, "E' necessario passare un record di LF_DOC");
 | 
						|
  
 | 
						|
  TRectype from(LF_RIGHEDOC), to(LF_RIGHEDOC);
 | 
						|
  TString filter;
 | 
						|
      
 | 
						|
  filter = "CODART==\"";
 | 
						|
  filter << codice() << "\"";
 | 
						|
  from.zero();
 | 
						|
  from.put(RDOC_CODNUM, rec.get(DOC_CODNUM));
 | 
						|
  from.put(RDOC_ANNO,   rec.get(DOC_ANNO));
 | 
						|
  from.put(RDOC_PROVV,  rec.get(DOC_PROVV));
 | 
						|
  from.put(RDOC_NDOC,   rec.get(DOC_NDOC)); // Se NDOC non è settato effettua il filtro su tutti i documenti di questa numerazione
 | 
						|
  
 | 
						|
  to = from;
 | 
						|
      
 | 
						|
  TRelation rdoc(LF_RIGHEDOC);
 | 
						|
  TCursor cur(&rdoc, filter, 1, &from, &to);
 | 
						|
  const TRecnotype items = cur.items();
 | 
						|
  TProgind *pi = NULL;
 | 
						|
  real val;      
 | 
						|
  
 | 
						|
  filter = "Calcolo ordinato fornitori in corso. ";
 | 
						|
  filter << rec.get(DOC_CODNUM);
 | 
						|
  filter << "/" << codice();
 | 
						|
 | 
						|
  if (items > 10)
 | 
						|
    pi = new TProgind(items, filter, FALSE, TRUE);
 | 
						|
  
 | 
						|
  for (cur = 0L; cur.pos() < items; ++cur)
 | 
						|
  {
 | 
						|
    // Calcola la qta residua
 | 
						|
    if (pi) pi->addstatus(1L);
 | 
						|
      
 | 
						|
    TRectype& rec = cur.curr();
 | 
						|
    if (!rec.get_bool(RDOC_RIGAEVASA))
 | 
						|
    {
 | 
						|
      val = rec.get_real(RDOC_QTA) - rec.get_real(RDOC_QTAEVASA);
 | 
						|
      // Converte il valore della quantità in UM base
 | 
						|
      val = convert_to_um(val, _umbase, rec.get(RDOC_UMQTA));
 | 
						|
      if (val < ZERO)
 | 
						|
        val = ZERO;
 | 
						|
    }
 | 
						|
    // Aggiorna il valore ordinato del periodo relativo
 | 
						|
    real& rr = (real&) _ordinato_fornitori[app().date2period(rec.get_date(RDOC_DATACONS))];
 | 
						|
    rr += val;
 | 
						|
  }
 | 
						|
 | 
						|
  if (pi) 
 | 
						|
    delete pi;
 | 
						|
}
 | 
						|
 | 
						|
void TArticolo_giacenza_static::calc_ordinato_fornitori(_ParmStruct* p, const char * codmag, const char * livello)
 | 
						|
{
 | 
						|
  // Calcolo del dettaglio ordinato fornitori, chiamata UNA sola volta per ogni articolo
 | 
						|
  // ad ogni stampa
 | 
						|
  
 | 
						|
  // Toglie l'ordinato fornitori dalla disponibilita
 | 
						|
  if (p->_add_orf)
 | 
						|
  {
 | 
						|
    TString16 annoes(p->_anno_es);
 | 
						|
    TRecord_array & rmag = mag(annoes);
 | 
						|
    for (int i = find_mag(annoes, codmag, livello); i > 0; 
 | 
						|
      i = find_mag(annoes, codmag, livello, i)) 
 | 
						|
      _disp -= rmag.row(i).get_real(MAG_ORDF);
 | 
						|
    TEsercizi_contabili ese;
 | 
						|
    const int prev = ese.pred(atoi(annoes));     // Controllo anche l'anno precedente
 | 
						|
    if (prev > 0)                        
 | 
						|
    {
 | 
						|
      TString16 oldannoes;  oldannoes.format("%04d", prev);
 | 
						|
      TRecord_array & rmag = mag(oldannoes);
 | 
						|
      for (int i = find_mag(oldannoes, codmag, livello); i > 0; 
 | 
						|
        i = find_mag(oldannoes, codmag, livello, i)) 
 | 
						|
        _disp -= rmag.row(i).get_real(MAG_ORDF);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Rimuove eventuali elementi rimasti, anche se questo metodo viene effettivamente chiamato una sola
 | 
						|
  // volta per articolo.
 | 
						|
  _ordinato_fornitori.destroy();
 | 
						|
  // Azzera l'array...
 | 
						|
  for (int i=0; i <= p->_periods; i++)
 | 
						|
    _ordinato_fornitori.add(new real);
 | 
						|
      
 | 
						|
  //Scorre tutte le numerazioni
 | 
						|
  TString_array& a = p->_numerazioni;
 | 
						|
      
 | 
						|
  for (i = a.last(); i >= 0; i--)
 | 
						|
  {
 | 
						|
    TToken_string& t = (TToken_string&) a[i];
 | 
						|
    const int items = t.items();
 | 
						|
    
 | 
						|
    if (items == 2) // Un solo tipo documento: scorre solo le righe di questa numerazione
 | 
						|
    {
 | 
						|
      TRectype doc(LF_DOC);
 | 
						|
      
 | 
						|
      doc.put(DOC_CODNUM, t.get(0));
 | 
						|
      doc.put(DOC_ANNO, p->_year);
 | 
						|
      doc.put(DOC_PROVV,  "D");
 | 
						|
 | 
						|
      calcola_ordinato_documento(doc);
 | 
						|
 | 
						|
      doc.put(DOC_CODNUM, t.get(0));
 | 
						|
      doc.put(DOC_ANNO, p->_year - 1);
 | 
						|
      doc.put(DOC_PROVV,  "D");
 | 
						|
      calcola_ordinato_documento(doc);
 | 
						|
    }
 | 
						|
    else // Se invece vi sono piu' tipi doc. per questa numerazione e' necessario considerare le testate doc.
 | 
						|
      if (items >= 3)
 | 
						|
      {
 | 
						|
        TRectype from(LF_DOC), to(LF_DOC);
 | 
						|
        TString filter;
 | 
						|
        
 | 
						|
        from.zero();
 | 
						|
        from.put(DOC_CODNUM, t.get(0));
 | 
						|
        from.put(DOC_ANNO,   p->_year);
 | 
						|
        from.put(DOC_PROVV,  "D");
 | 
						|
        to = from;
 | 
						|
        
 | 
						|
        for (int j=2; j<=items; j++)
 | 
						|
        {
 | 
						|
          filter << "(TIPODOC==\"";
 | 
						|
          filter << t.get(j-1);
 | 
						|
          filter << "\")||";
 | 
						|
        }
 | 
						|
        filter.rtrim(2);
 | 
						|
        
 | 
						|
        TRelation doc(LF_DOC);
 | 
						|
        TCursor cur(&doc, filter, 1, &from, &to);
 | 
						|
        
 | 
						|
        for (cur = 0L; cur.pos() < cur.items(); ++cur)
 | 
						|
          // Per ogni documento scorre le sue righe
 | 
						|
          calcola_ordinato_documento(cur.curr());
 | 
						|
        from.zero();
 | 
						|
        from.put(DOC_CODNUM, t.get(0));
 | 
						|
        from.put(DOC_ANNO,   p->_year - 1);
 | 
						|
        from.put(DOC_PROVV,  "D");
 | 
						|
        to = from;
 | 
						|
        cur.setregion(from, to);
 | 
						|
        for (cur = 0L; cur.pos() < cur.items(); ++cur)
 | 
						|
            // Per ogni documento scorre le sue righe
 | 
						|
          calcola_ordinato_documento(cur.curr());
 | 
						|
      }
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Progressivizza gli importi
 | 
						|
  const int periods = p->_periods;
 | 
						|
  if (periods > 1)
 | 
						|
  {
 | 
						|
    for (i=2; i <= periods ; i++)
 | 
						|
    {
 | 
						|
      real& rr =  (real&)_ordinato_fornitori[i];
 | 
						|
      rr       += (real&)_ordinato_fornitori[i-1];
 | 
						|
      if (i== periods)
 | 
						|
      {                
 | 
						|
        real& zz = (real&)_ordinato_fornitori[0]; // Totale...
 | 
						|
        zz += rr;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    real& rr =  (real&)_ordinato_fornitori[1];
 | 
						|
    real& zz = (real&)_ordinato_fornitori[0]; // Totale...
 | 
						|
    zz += rr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
real& TArticolo_giacenza_static::static_disp(_ParmStruct* p, const char * codmag, const char * livello)
 | 
						|
{
 | 
						|
  if (!_calc)
 | 
						|
  {
 | 
						|
    _calc =TRUE;
 | 
						|
    const char * annoes = p->_anno_es;
 | 
						|
    _disp = ZERO;
 | 
						|
  
 | 
						|
    TRecord_array & rmag = mag(annoes);
 | 
						|
    for (int i = find_mag(annoes, codmag, livello); i > 0; 
 | 
						|
      i = find_mag(annoes, codmag, livello, i)) 
 | 
						|
    {                                    
 | 
						|
      const TRectype & rec = rmag.row(i);
 | 
						|
      _disp += rec.get_real(MAG_GIAC);
 | 
						|
      if (p->_add_orf)
 | 
						|
        _disp += rec.get_real(MAG_ORDF);
 | 
						|
      if (p->_add_orc) 
 | 
						|
        _disp -= rec.get_real(MAG_ORDC);
 | 
						|
      if (p->_add_prf)
 | 
						|
        _disp += rec.get_real(MAG_PRODFIN);
 | 
						|
      if (p->_add_prc)
 | 
						|
        _disp -= rec.get_real(MAG_PRODCOMP);
 | 
						|
      if (p->_add_acl)
 | 
						|
        _disp += rec.get_real(MAG_ACL);
 | 
						|
      if (p->_add_incl)
 | 
						|
        _disp -= rec.get_real(MAG_INCL);
 | 
						|
    }
 | 
						|
    if ((p->_add_orc || p->_add_orf) && !riporta_ordinato())      // Se l-ordinato viene riportato
 | 
						|
    {                                 
 | 
						|
      TEsercizi_contabili ese;
 | 
						|
      const int prev = ese.pred(atoi(annoes));     // Controllo anche l'anno precedente
 | 
						|
      if (prev > 0)                        
 | 
						|
      {
 | 
						|
        TString16 oldannoes;  oldannoes.format("%04d", prev);
 | 
						|
        const TRecord_array& oldrmag = mag(oldannoes);
 | 
						|
        for (int i = find_mag(oldannoes, codmag, livello); i > 0; 
 | 
						|
          i = find_mag(oldannoes, codmag, livello, i)) 
 | 
						|
        {                                    
 | 
						|
          const TRectype& rec = oldrmag.row(i);
 | 
						|
          if (p->_add_orf)
 | 
						|
            _disp += rec.get_real(MAG_ORDF);  // Sommo l'ordinato fornitori
 | 
						|
          if (p->_add_orc) 
 | 
						|
            _disp -= rec.get_real(MAG_ORDC);  // Sottraggo l'ordinato clienti
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    _umbase = ((TRectype&)(um()[1])).get("UM");
 | 
						|
 | 
						|
    // Calcola ordinato fornitori di questo articolo, suddividendo per periodi
 | 
						|
    // L'ordinato viene espresso nell'unità di misura principale, per poi essere riconvertita in
 | 
						|
    // quella esplicitata nella riga di esplosione
 | 
						|
    if (p->_det_ord_for)
 | 
						|
      calc_ordinato_fornitori(p, codmag, livello);
 | 
						|
  }
 | 
						|
  return _disp;
 | 
						|
}
 | 
						|
 | 
						|
/////////////////////////////////////////////////////////////
 | 
						|
// Implementazione metodi di TExplode_distinta_form
 | 
						|
/////////////////////////////////////////////////////////////
 | 
						|
TExplode_distinta_form::TExplode_distinta_form(const char * n) : TForm(n)
 | 
						|
{
 | 
						|
  _d = NULL; 
 | 
						|
  _p = NULL;
 | 
						|
  _f = this;
 | 
						|
  TPrinter& pr = printer();
 | 
						|
  
 | 
						|
  pr.setheaderhandler(dist_header_handler);
 | 
						|
  TPrint_section& head = section('H');
 | 
						|
  pr.headerlen(head.height());
 | 
						|
  
 | 
						|
  pr.setfooterhandler(dist_footer_handler);
 | 
						|
  const TPrint_section& foot = section('F');
 | 
						|
  pr.footerlen(foot.height());
 | 
						|
}
 | 
						|
 | 
						|
TExplode_distinta_form::~TExplode_distinta_form()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::set_parameters(_ParmStruct* ps)
 | 
						|
{
 | 
						|
  _p = ps;
 | 
						|
  // Accende o spegne le colonne a seconda di stampa disponibilita/valorizzazione
 | 
						|
  for (short i = 7; i<=9; i++)
 | 
						|
    find_field('B',odd_page,i).enable(_p->_fabbisogno); // Colonne disponibilita...
 | 
						|
 | 
						|
  find_field('B',odd_page,10).enable(_p->_valorization != no_val); // Valorizzazione
 | 
						|
  find_field('B',odd_page,11).enable(_p->_valorization != no_val); // Valore unitario
 | 
						|
 | 
						|
  find_field('B',odd_page,12).enable(_p->_det_ord_for);  // Dettaglio ord. fornitori
 | 
						|
  find_field('B',odd_page,13).enable(_p->_det_ord_for);  // Dettaglio ord. fornitori
 | 
						|
  find_field('B',odd_page,14).enable(_p->_det_ord_for);  // Codice fornitore
 | 
						|
}
 | 
						|
   
 | 
						|
void TExplode_distinta_form::print_header(TPrinter& pr)
 | 
						|
{
 | 
						|
  TPrint_section& head = section('H');
 | 
						|
 | 
						|
  head.update(); 
 | 
						|
 | 
						|
  const word r = head.height()-1;
 | 
						|
  
 | 
						|
  for (word j = 0; j <= r; j++)
 | 
						|
    pr.setheaderline(j, head.row(j));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TExplode_distinta_form::print_footer(TPrinter& pr)
 | 
						|
{
 | 
						|
  const bool p = page(pr)>0;
 | 
						|
  TPrint_section& foot = section('F',p ? odd_page : last_page);
 | 
						|
 | 
						|
  foot.update();
 | 
						|
  word r = foot.height();
 | 
						|
 | 
						|
  for (word j = 0; j < r; j++)
 | 
						|
    pr.setfooterline(j, foot.row(j));
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::dist_header_handler(TPrinter& pr)
 | 
						|
{
 | 
						|
  pr.resetheader();
 | 
						|
  _f->print_header(pr);    
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::dist_footer_handler(TPrinter& pr)
 | 
						|
{
 | 
						|
  pr.resetfooter();
 | 
						|
  _f->print_footer(pr);
 | 
						|
} 
 | 
						|
 | 
						|
bool TExplode_distinta_form::validate(TForm_item &f, TToken_string &t)
 | 
						|
{
 | 
						|
  const TString16 subcommand(t.get(0)); // Sub-comandante Marcos
 | 
						|
 | 
						|
  if (subcommand != "_DISTINTA")
 | 
						|
    return TForm::validate(f, t);
 | 
						|
  
 | 
						|
  const TString16 code(t.get(1)); // codice del messaggio
 | 
						|
  TString256 valore;
 | 
						|
  TRiga_esplosione2print& re = (TRiga_esplosione2print&) _exploded_tree[_curr_row];
 | 
						|
  const char tipo = re.tipo();
 | 
						|
 | 
						|
  if (code == "_COD")
 | 
						|
  {      
 | 
						|
    int liv = re.livello();
 | 
						|
    if (liv > 0)                // Calcola indentazione
 | 
						|
    {   
 | 
						|
      if (_p->_separate_dist)
 | 
						|
      {       
 | 
						|
        if (liv > 10) liv = 10;
 | 
						|
        if (_p->_ordering)
 | 
						|
          valore.format("%8ld%*s", re.ordinamento(), liv, "");
 | 
						|
        else  
 | 
						|
          valore.spaces(liv);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      valore = "@B";            // Radice in grassetto
 | 
						|
    valore << re.articolo();
 | 
						|
  }
 | 
						|
  else
 | 
						|
    if (code == "_DES")
 | 
						|
    {
 | 
						|
      const TRelation* rel = relation();
 | 
						|
      
 | 
						|
      switch (tipo)
 | 
						|
      {
 | 
						|
        case 'A':
 | 
						|
        {
 | 
						|
          valore = _art_cache.get(re.articolo()).get(ANAMAG_DESCR);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        case 'L':
 | 
						|
        {
 | 
						|
          TTable& lav = (TTable&) rel->lfile("LAV");
 | 
						|
          lav.put("CODTAB", re.articolo());
 | 
						|
          if (lav.read() == NOERR)
 | 
						|
            valore = lav.get("S0");
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        case 'V':
 | 
						|
        {
 | 
						|
          TLocalisamfile& dist = rel->lfile();
 | 
						|
          dist.put("CODDIST", re.articolo());
 | 
						|
          if (dist.read() == NOERR)
 | 
						|
            valore = dist.get("DESCR");
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
      }
 | 
						|
      if (livelli_giacenza().enabled())
 | 
						|
      {
 | 
						|
        TString lv = re.giacenza();
 | 
						|
        for (int l = livelli_giacenza().last_level(); l > 0 ; l--)
 | 
						|
          lv.insert(" ",livelli_giacenza().packed_length(l));
 | 
						|
        valore.insert(lv);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
      if (code == "_LIV")
 | 
						|
      {
 | 
						|
        if (_p->_separate_dist && re.livello() > 0)
 | 
						|
          valore << re.livello();
 | 
						|
      }
 | 
						|
      else
 | 
						|
        if (code == "_DCO")
 | 
						|
        {
 | 
						|
          //if (re.articolo() == _d->cod())
 | 
						|
            valore = re.datacons();
 | 
						|
        }
 | 
						|
        else
 | 
						|
            if (code == "_UM")
 | 
						|
            {
 | 
						|
              valore = re.um();
 | 
						|
            }
 | 
						|
            else
 | 
						|
              if (code == "_FAB")
 | 
						|
              {
 | 
						|
                valore = re.fabbisogno().string();
 | 
						|
              }
 | 
						|
              else
 | 
						|
                if (code == "_DIS")
 | 
						|
                {
 | 
						|
                  valore = re.disponibilita().string();
 | 
						|
                }
 | 
						|
                else
 | 
						|
                  if (code == "_ORDPROD")
 | 
						|
                  {
 | 
						|
                    valore = re.qta2order().string();
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                    if (code == "_RESIDUO")
 | 
						|
                    {
 | 
						|
                      valore = re.residuo().string();
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                      if (code == "_VALORE")
 | 
						|
                      {
 | 
						|
                        valore = re.value().string();
 | 
						|
                      }
 | 
						|
                      else
 | 
						|
                        if (code == "_VALOREUNIT")
 | 
						|
                        {
 | 
						|
                          valore = re.unitary_value().string();
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                          if (code == "_ORDFOR")
 | 
						|
                          {
 | 
						|
                            valore = re.ordfor().string();
 | 
						|
                          }
 | 
						|
                          else
 | 
						|
                            if (code == "_TOTORDFOR")
 | 
						|
                            {
 | 
						|
                              valore = re.totordfor().string();
 | 
						|
                            }
 | 
						|
                            else
 | 
						|
                              if (code == "_CODFORN")
 | 
						|
                              {                      
 | 
						|
                                valore = _art_cache.get(re.articolo()).get(ANAMAG_CODFORN);
 | 
						|
                              }
 | 
						|
  f.set(valore);
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
real TExplode_distinta_form::res2produce_by_father(TRiga_esplosione& re)
 | 
						|
{
 | 
						|
  real r;
 | 
						|
 | 
						|
  if (!_p->_fabbisogno) // Se non e' abilitata il calcolo del fabbisogno/disponibilita
 | 
						|
    r = _d->qta();   // ritorna la qta della distinta come residuo da produrre
 | 
						|
  else
 | 
						|
  {
 | 
						|
    // Se sta esaminando la riga della "radice"ritorna la qta richiesta, altrimenti :
 | 
						|
    // per esplosione ai mat.base, ritorna il residuo da produrre per la distinta "radice";
 | 
						|
    // per l'esplosione e' scalare ritorna il residuo del padre di questo nodo.
 | 
						|
    
 | 
						|
    if (re.livello() == 0)
 | 
						|
      r = _d->qta();
 | 
						|
    else
 | 
						|
    {
 | 
						|
      TToken_string pstr;
 | 
						|
      if (_p->_explosion == mat_base)
 | 
						|
        re.path().get(0, pstr);
 | 
						|
      else
 | 
						|
      {
 | 
						|
        TString16 fi;
 | 
						|
        if (_p->_vis_art) fi << 'A';
 | 
						|
        if (_p->_vis_lav) fi << 'L';
 | 
						|
        if (_p->_vis_vir) fi << 'V';  
 | 
						|
        if (_p->_vis_gho) fi << 'G';  
 | 
						|
        pstr = re.father(fi);
 | 
						|
      }
 | 
						|
 | 
						|
      TString16 codmag = _distinta.path_depth(pstr) < 1 ? (TString &)_d->mag() : (TString &)_p->_sl_mag;
 | 
						|
      if (codmag.blank()) codmag = _d->mag();
 | 
						|
 | 
						|
      TString g;
 | 
						|
      TCodice_articolo a;
 | 
						|
      _distinta.path_code(a, pstr);
 | 
						|
      _distinta.path_giaclev(g, 0, pstr);
 | 
						|
      TString80 key;
 | 
						|
      key.format("%-20s|%-15s|%-5s",  (const char*)a, (const char*)g, (const char*)codmag);
 | 
						|
      real * rs = (real*)_prodorder.objptr(key);
 | 
						|
      r = rs != NULL ? *rs : ZERO; // Se er padre non ha residui... smette de fatica'
 | 
						|
    }
 | 
						|
  }  
 | 
						|
  return r;
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::set_explosion_rows(TArray& exp_array)
 | 
						|
{
 | 
						|
  const int rows = exp_array.items();
 | 
						|
  real r;
 | 
						|
  TString k;
 | 
						|
 | 
						|
  for (int i = 0; i < rows; i++)
 | 
						|
  {
 | 
						|
    TRiga_esplosione& re = (TRiga_esplosione&) exp_array[i];
 | 
						|
    const char tipo = re.tipo();
 | 
						|
    const bool is_head = i == DIST_HEAD;
 | 
						|
 | 
						|
    // Se si tratta dell'articolo distinta da esplodere, calcola la disponibilita'
 | 
						|
    // prendendo il magazzino indicato sulla riga stessa
 | 
						|
    // Se invece e' un componente, prende cio' che e' stato indicato dall'utente per quanto 
 | 
						|
    // riguarda se e' materiale di base o semilavorato
 | 
						|
    // Il livello di giacenza lo si prende dall'articolo distinta da esplodere 
 | 
						|
    // oppure dalla riga esplosione se non stiamo stampando la testata della distinta
 | 
						|
    // il cod. esercizio e' calc. come sempre
 | 
						|
    TString codmag = is_head ? _d->mag() : re.mat_base() ? (const TString&)_p->_mb_mag : (const TString&)_p->_sl_mag;
 | 
						|
    if (codmag.blank()) codmag = _d->mag();
 | 
						|
    const TString& liv    = is_head ? _d->liv() : re.giacenza();
 | 
						|
    
 | 
						|
    // Il fabbisogno e': nr. componenti di questo articolo per residuo da produrre del padre
 | 
						|
                                       
 | 
						|
    if (_p->_fabbisogno && _p->_explosion == scalare)
 | 
						|
      r = re.last_qta() * res2produce_by_father(re); // In UM locale... 
 | 
						|
    else  
 | 
						|
      r = re.val() * res2produce_by_father(re);      // In UM locale... 
 | 
						|
 | 
						|
    if (r == ZERO)
 | 
						|
    {
 | 
						|
      if (_p->_fabbisogno)   // Calcolo disponibilita'
 | 
						|
      {
 | 
						|
        // Compone la chiave da cercare nella cache: CODART|CODMAG|LIVELLO
 | 
						|
        // ovvio che tutti i campi debbono essre paddati alla loro massima lunghezza
 | 
						|
        // Al TArticolo_cache importa solo del CODART in ricerca... i campi seguenti vengono ignorati
 | 
						|
        // anche se nel TAssoc_array interno vengono cmq memorizzati come chiave
 | 
						|
        __key.format("%-20s|%-15s|%-5s",  (const char*)re.articolo(), (const char*) liv, (const char*) codmag);
 | 
						|
        _prodorder.add(__key, ZERO, TRUE);
 | 
						|
      }
 | 
						|
      continue; // Don't store in _exploded_tree if there's no need
 | 
						|
    }
 | 
						|
    
 | 
						|
    TRiga_esplosione2print* r2p = NULL;
 | 
						|
    int pos = -1;
 | 
						|
    if (!_p->_separate_dist)
 | 
						|
    {
 | 
						|
      for (pos = _exploded_tree.items()-1; pos>=0; pos--)
 | 
						|
      {
 | 
						|
        r2p = (TRiga_esplosione2print *)_exploded_tree.objptr(pos);
 | 
						|
        if (re.articolo() == r2p->articolo() && 
 | 
						|
          re.um() == r2p->um() &&
 | 
						|
            (re.giacenza() == r2p->giacenza()) &&
 | 
						|
            codmag == r2p->mag())
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (pos <0)
 | 
						|
    {
 | 
						|
      r2p =  new TRiga_esplosione2print(re, codmag);
 | 
						|
      _exploded_tree.add(r2p,pos);
 | 
						|
    }
 | 
						|
                                                          
 | 
						|
    r2p->set_fabbisogno(r + r2p->fabbisogno());
 | 
						|
    
 | 
						|
    if (_p->_fabbisogno)   // Calcolo disponibilita'
 | 
						|
    {
 | 
						|
      // Compone la chiave da cercare nella cache: CODART|CODMAG|LIVELLO
 | 
						|
      // ovvio che tutti i campi debbono essre paddati alla loro massima lunghezza
 | 
						|
      // Al TArticolo_cache importa solo del CODART in ricerca... i campi seguenti vengono ignorati
 | 
						|
      // anche se nel TAssoc_array interno vengono cmq memorizzati come chiave
 | 
						|
      __key.format("%-20s|%-15s|%-5s",  (const char*)re.articolo(), (const char*) liv, (const char*) codmag);
 | 
						|
      TArticolo_giacenza_static& aaa = _art_cache.art(__key);
 | 
						|
  
 | 
						|
      // Si ricorda che la disponibilita' e' calcolata in UM base!!
 | 
						|
      // Quindi e' opportuno effettuare la conversione nell'unita' di misura
 | 
						|
      // del presente articolo....
 | 
						|
      const bool is_new = _prodordert.objptr(__key)==NULL;
 | 
						|
  
 | 
						|
      real sottostock = is_new ? ZERO : (real &)_prodordert[__key] ;
 | 
						|
      if (tipo != 'A') 
 | 
						|
      { 
 | 
						|
        // Distinte Virtuali e Lavorazioni non hanno disponibilita', quindi sono sempre da produrre        
 | 
						|
  
 | 
						|
        r2p->set_disponibilita(ZERO);
 | 
						|
        r2p->set_residuo(ZERO);
 | 
						|
        if (tipo == 'V')
 | 
						|
        {
 | 
						|
          TQuantita q (r2p->articolo(), r2p->um(), r);
 | 
						|
          q.convert2umbase();
 | 
						|
          _prodorder.add(__key, q.val(), TRUE); // Memorizza nei residui...
 | 
						|
          q += sottostock;
 | 
						|
          _prodordert.add(__key, q.val(), TRUE); // Memorizza nei residui...
 | 
						|
        }
 | 
						|
      } else { 
 | 
						|
        // Disponibilita, qta da ordinare e residuo vengono calcolati solo per le righe Articolo
 | 
						|
        
 | 
						|
        real zero_ref(_p->_liv_attenzione == 'S' ? aaa.get_scmin(_p->_anno_es, codmag, liv) : ZERO);
 | 
						|
        zero_ref = aaa.convert_to_um(zero_ref, re.um());
 | 
						|
  
 | 
						|
        real qta2order,disponib;
 | 
						|
        if (is_new) 
 | 
						|
        {
 | 
						|
          if (re.livello()==0 && _p->_no_fabbis_fin)
 | 
						|
            disponib = ZERO;
 | 
						|
          else
 | 
						|
            disponib = aaa.static_disp(_p, codmag, liv);
 | 
						|
        }
 | 
						|
        else  
 | 
						|
          disponib = (real &)_disponib[__key];
 | 
						|
        if (is_new || _p->_separate_dist)
 | 
						|
          r2p->set_disponibilita(disponib);
 | 
						|
        disponib -= sottostock;
 | 
						|
        // Converte in UM della riga attuale
 | 
						|
        disponib = aaa.convert_to_um(disponib, re.um());
 | 
						|
  
 | 
						|
        if (_d->acqven())
 | 
						|
          disponib += r;
 | 
						|
        else
 | 
						|
          disponib -= r;
 | 
						|
        
 | 
						|
        if (disponib > zero_ref)
 | 
						|
        {
 | 
						|
          disponib -= zero_ref;
 | 
						|
          qta2order = ZERO;
 | 
						|
        } else {
 | 
						|
          qta2order = zero_ref - disponib;
 | 
						|
          disponib = ZERO;
 | 
						|
        }
 | 
						|
        r2p->set_residuo(disponib);
 | 
						|
        r2p->set_qta2order(qta2order);
 | 
						|
  
 | 
						|
        // Ri-Converte in UM base per aggiornare gli Assocarray
 | 
						|
        disponib = aaa.convert_to_um(disponib, "");
 | 
						|
        qta2order = aaa.convert_to_um(qta2order, "");
 | 
						|
        _disponib.add (__key,  disponib, TRUE);
 | 
						|
        _prodorder.add(__key, real(qta2order - sottostock), TRUE);
 | 
						|
        _prodordert.add(__key, qta2order, TRUE);
 | 
						|
  
 | 
						|
        if (_p->_det_ord_for)
 | 
						|
        {
 | 
						|
          real of;
 | 
						|
          
 | 
						|
          of = aaa.ordinato_fornitori(app().date2period(_d->data_per()));
 | 
						|
          of = aaa.convert_to_um(of, re.um());
 | 
						|
          r2p->set_ordfor(of); // Ordinato fornitori per questo periodo espresso in UM esplicitata dalla riga esplosione
 | 
						|
          
 | 
						|
          of = aaa.ordinato_fornitori(0);
 | 
						|
          of = aaa.convert_to_um(of, re.um());
 | 
						|
          r2p->set_totordfor(of); // Ordinato fornitori totale espresso in UM esplicitata dalla riga esplosione
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }  
 | 
						|
    
 | 
						|
    // Il valore lo calcola per qualsiasi tipo riga
 | 
						|
    if (_p->_valorization > no_val)
 | 
						|
    {
 | 
						|
      if (re.mat_base())
 | 
						|
      {
 | 
						|
        k = re.articolo();
 | 
						|
        if (re.giacenza().not_empty())
 | 
						|
          k << ',' << re.giacenza();
 | 
						|
      }
 | 
						|
      else
 | 
						|
        k = re.path(); // I nodi sono cachati con tutto il path in modo da essere univoci
 | 
						|
        
 | 
						|
      if (_valori.objptr(k) == NULL)
 | 
						|
        r = ZERO;
 | 
						|
      else
 | 
						|
        r = *(real*)_valori.objptr(k);
 | 
						|
      if (re.mat_base())  
 | 
						|
        r2p->set_unitary_value(r);
 | 
						|
      else  
 | 
						|
        r2p->set_unitary_value(r / re.val());
 | 
						|
      
 | 
						|
      if (_p->_fabbisogno)
 | 
						|
        r = r2p->unitary_value() * r2p->qta2order();
 | 
						|
      else
 | 
						|
        r = r2p->unitary_value() * r2p->fabbisogno();
 | 
						|
      r2p->set_value(r);
 | 
						|
    }
 | 
						|
 | 
						|
    if (is_head)
 | 
						|
      r2p->set_datacons(_d->datacons());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::reset_rows(bool firsttime)
 | 
						|
{
 | 
						|
  _exploded_tree.destroy();
 | 
						|
  _valori.destroy();
 | 
						|
  _prodorder.destroy();                               
 | 
						|
  if (firsttime)
 | 
						|
  {
 | 
						|
    _prodordert.destroy();
 | 
						|
    _disponib.destroy();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::explode_and_print()
 | 
						|
{
 | 
						|
  // Explode & deflagrate...
 | 
						|
  
 | 
						|
  _distinta.clear_globals();
 | 
						|
  _distinta.set_global("_IMPIANTO", _d->imp());
 | 
						|
  _distinta.set_global("_LINEA", _d->lin());
 | 
						|
  _distinta.set_global( "_MAGDEP", _d->mag());
 | 
						|
 | 
						|
  if (!_distinta.set_root(_d->cod(), _d->um(), 1.0, _d->liv()))
 | 
						|
    return;
 | 
						|
    
 | 
						|
  TWait_cursor clepsy;
 | 
						|
 | 
						|
  // Inizializza lo sfondo delle pagine normali se no col piffero che stampa la fincatura...
 | 
						|
  set_background(3, TRUE);
 | 
						|
  _distinta.restart();
 | 
						|
  if (_distinta.goto_root())
 | 
						|
  {
 | 
						|
    TArray explosion_array;
 | 
						|
    TPrintrow p;
 | 
						|
    TString16 fi;
 | 
						|
    
 | 
						|
      // Reset delle righe in caso di dist separate o cambio periodo
 | 
						|
    if (_p->_separate_dist
 | 
						|
          || (_p->_separate_giac && _d->cod() != __current_art)
 | 
						|
          || (__current_period.ok() && _d->data_per() > __current_period))
 | 
						|
      print_explosion_rows();
 | 
						|
 | 
						|
    __current_art    = _d->cod();
 | 
						|
    __current_period = _d->data_per();
 | 
						|
 | 
						|
    if (_p->_vis_art) fi << 'A';
 | 
						|
    if (_p->_vis_lav) fi << 'L';
 | 
						|
    if (_p->_vis_vir) fi << 'V';  
 | 
						|
    if (_p->_vis_gho) fi << 'G';  
 | 
						|
 | 
						|
    _distinta.curr_code((TCodice_articolo& )_d->cod());
 | 
						|
    _distinta.explode(explosion_array, _p->_explosion == mat_base, _p->_group_by, 
 | 
						|
      _p->_det_lev, fi, _p->_ordering);
 | 
						|
    // Dopo l'esplosione mette in testa all'array la riga di definizione della Distinta stessa:
 | 
						|
    // codice + UM + Fabbisogno  (sostanzialmente si tratta di un TRiga_esplosione)
 | 
						|
    explosion_array.insert(_d->head_obj(), 0);
 | 
						|
 | 
						|
    
 | 
						|
    // Effettua la valorizzazione scorrendo i nodi...
 | 
						|
    if (_p->_valorization > no_val)
 | 
						|
    {
 | 
						|
      _CallBackStruct setter; // 
 | 
						|
                              // Dog programming on...
 | 
						|
      setter._p = _p;         // 
 | 
						|
      setter._a = &_valori;   //
 | 
						|
      _distinta.set_root(_d->cod(), "", 1.0, _d->liv());
 | 
						|
      _distinta.scan_depth_first(valorizza_nodo, &setter);
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Ora scorre l'array locale delle righe esplosione, settando quello
 | 
						|
    // vero (_exploded_tree) con le TRiga_esplosione2print necessarie
 | 
						|
    // ed i valori corretti (fabbisogno, disponibilita, residuo, da ordinare e valore)
 | 
						|
    set_explosion_rows(explosion_array);
 | 
						|
  }
 | 
						|
  else
 | 
						|
    error_box("Impossibile posizionare l'albero");
 | 
						|
}
 | 
						|
 | 
						|
compare_print_rows(const TObject** o1, const TObject** o2)
 | 
						|
{
 | 
						|
  TRiga_esplosione2print & r1 =(TRiga_esplosione2print &)(**o1);
 | 
						|
  TRiga_esplosione2print & r2 =(TRiga_esplosione2print &)(**o2);
 | 
						|
  const int l1 = r1.livello();
 | 
						|
  const int l2 = r2.livello();
 | 
						|
  int diff = 0;
 | 
						|
  if (l1 == 0 || l2 == 0)
 | 
						|
    diff = l1 - l2;
 | 
						|
  if (diff == 0)
 | 
						|
    diff = r1.articolo().compare(r2.articolo());
 | 
						|
  if (diff == 0)
 | 
						|
    diff = r1.giacenza().compare(r2.giacenza());
 | 
						|
  return diff ;
 | 
						|
}
 | 
						|
 | 
						|
void TExplode_distinta_form::print_explosion_rows()
 | 
						|
{
 | 
						|
  const int righe = _exploded_tree.items();
 | 
						|
  if (righe <= 0)
 | 
						|
    return;
 | 
						|
  if (!_p->_separate_dist)
 | 
						|
    _exploded_tree.sort(compare_print_rows);
 | 
						|
  // Inizializza lo sfondo delle pagine normali se no col piffero che stampa la fincatura...
 | 
						|
  set_background(3, TRUE);
 | 
						|
 | 
						|
  TArray explosion_array;
 | 
						|
  TPrintrow p;
 | 
						|
  TString16 fi;
 | 
						|
    
 | 
						|
  TPrint_section& body = section('B');
 | 
						|
  TPrinter& pr = printer();
 | 
						|
    
 | 
						|
  // Setta pure la data sul form item di testa...
 | 
						|
  // Se e' cambiato il periodo effettua un form feed di separazione
 | 
						|
  TPrint_section& head = section('H');
 | 
						|
  head.find_field(4).set(_d->data_per());
 | 
						|
    
 | 
						|
  // Ad ogni cambio periodo effettua un formfeed...
 | 
						|
  // Be careful: evitare di stampare doppio form feed di separazione in caso
 | 
						|
  // di Separa distinte e cambio periodo contemporaneamente
 | 
						|
  if (!_p->_newpage && __last_period.ok() && __last_period < __current_period) 
 | 
						|
    pr.formfeed();
 | 
						|
 | 
						|
  __last_period = __current_period;
 | 
						|
    
 | 
						|
  set_last_page(FALSE);
 | 
						|
    
 | 
						|
  // This is GoodStuff... browse all rows & print'em
 | 
						|
  for (_curr_row=0; _curr_row<righe; _curr_row++)
 | 
						|
  {
 | 
						|
    body.update();
 | 
						|
       
 | 
						|
    if (_p->_fabbisogno && _p->_no_zero_ord)
 | 
						|
    {
 | 
						|
      const real fabb = body.find_field(8).get();
 | 
						|
      if (fabb.is_zero())
 | 
						|
        continue;
 | 
						|
    }
 | 
						|
      
 | 
						|
    const word h = body.height();
 | 
						|
    if (pr.rows_left() <= (h+1))
 | 
						|
      pr.formfeed();
 | 
						|
    for (word j = 0; j < h; j++)
 | 
						|
      pr.print(body.row(j));
 | 
						|
  }
 | 
						|
    
 | 
						|
  set_last_page(TRUE); 
 | 
						|
    
 | 
						|
  // form feed su opzione parametro...
 | 
						|
  if (_p->_newpage)
 | 
						|
    pr.formfeed();
 | 
						|
  else // Altrimenti aggiunge una riga mezza ciucciata...
 | 
						|
    pr.print(p);
 | 
						|
 | 
						|
  // Reset delle righe in caso di dist separate o cambio periodo
 | 
						|
  reset_rows(FALSE);
 | 
						|
  return ;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TDist2Explode
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
// Implementation of base object used in skantacazz 2 be stored in a TAssoc_array so we can order it
 | 
						|
//
 | 
						|
 | 
						|
TRiga_esplosione * TDist2Explode::head_obj()
 | 
						|
{
 | 
						|
  TDistinta_tree tree;
 | 
						|
  TQuantita qta(_cod, _um, real(1.00));
 | 
						|
  tree.set_root(qta, liv());
 | 
						|
  TRiga_esplosione * re = new TRiga_esplosione(tree);
 | 
						|
  return re;
 | 
						|
}
 | 
						|
 | 
						|
void TDist2Explode::set(const TMask& msk)
 | 
						|
{
 | 
						|
  if (_imp.blank())
 | 
						|
    _imp = msk.get(F_IMPIANTO);
 | 
						|
  if (_lin.blank())
 | 
						|
    _lin = msk.get(F_LINEA);
 | 
						|
}
 | 
						|
 | 
						|
void TDist2Explode::set(const TRiga_documento& r, const TMask& msk)
 | 
						|
{
 | 
						|
  _cod      = r.get(RDOC_CODART);
 | 
						|
  _livgiac  = r.get(RDOC_LIVELLO);
 | 
						|
  _um       = r.get(RDOC_UMQTA);
 | 
						|
  _mag      = r.get(RDOC_CODMAG);
 | 
						|
  _imp      = r.get(RDOC_IMPIANTO);
 | 
						|
  _lin      = r.get(RDOC_LINEA);
 | 
						|
  _qta      = r.get_real("QTARES"); // Virtual field... must exist!!
 | 
						|
  _datacons = r.get_date(RDOC_DATACONS);
 | 
						|
  if (!_datacons.ok())
 | 
						|
    _datacons = r.doc().get_date(DOC_DATACONS);
 | 
						|
  _acq_ven  = r.doc().get(DOC_TIPOCF) == "F" ? TRUE : FALSE;
 | 
						|
  _data_per = app().date_period(_datacons);
 | 
						|
  set(msk);
 | 
						|
}
 | 
						|
 | 
						|
void TDist2Explode::set(TToken_string& t, const TMask& msk)
 | 
						|
{
 | 
						|
  _cod = t.get(0);
 | 
						|
  _livgiac = t.get(1);
 | 
						|
  _livgiac << t.get(2);
 | 
						|
  _livgiac << t.get(3);
 | 
						|
  _livgiac << t.get(4);
 | 
						|
  _livgiac.trim();      
 | 
						|
  _imp = t.get(5);
 | 
						|
  _lin = t.get(6);
 | 
						|
  _mag.format("%3s", (const char*)t.get(7));
 | 
						|
  _mag << t.get(8);
 | 
						|
  _mag.trim();
 | 
						|
  _um  = t.get(9);
 | 
						|
  _qta = t.get(10);
 | 
						|
  _datacons = t.get(12);
 | 
						|
  _acq_ven  = t.get(13)[0] == 'X' ? TRUE : FALSE;
 | 
						|
  _data_per = app().date_period(_datacons);
 | 
						|
  set(msk);
 | 
						|
}
 | 
						|
 | 
						|
const char* TDist2Explode::key()
 | 
						|
{
 | 
						|
  __key.format("%3d%-20s%-15s%-2s%-5s%-5s%-5s", 
 | 
						|
    app().date2period(_datacons), (const char*)_cod, (const char*) _livgiac, 
 | 
						|
    (const char*)_um, (const char*)_mag, (const char*)_imp, (const char*)_lin);
 | 
						|
  return (const char*)__key;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////////////
 | 
						|
// Implementazione metodi di TEsplosione_distinta_app
 | 
						|
///////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
bool TEsplosione_distinta_app::sheet_notify(TSheet_field& s, int r, KEY key) 
 | 
						|
{
 | 
						|
  if (key==(K_CTRL+K_INS))
 | 
						|
  {
 | 
						|
    TDate d(TODAY);
 | 
						|
    TToken_string& t = s.row(r);
 | 
						|
    t.add(d.string(),10);
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
const int TEsplosione_distinta_app::date2period(const TDate& d)
 | 
						|
{ 
 | 
						|
  const int items = _date_array.items();
 | 
						|
  for (int i = 0; i<items; i++)
 | 
						|
  {
 | 
						|
    const TDate& limit = (TDate&)_date_array[i];
 | 
						|
    if (d <= limit)
 | 
						|
      break;
 | 
						|
  }
 | 
						|
  if (i == items) // Didn't find my way...
 | 
						|
    return 0;
 | 
						|
  return i+1;
 | 
						|
}
 | 
						|
 | 
						|
const TDate& TEsplosione_distinta_app::date_period(const TDate& d)
 | 
						|
{
 | 
						|
  const int period = date2period(d);
 | 
						|
  return (TDate&)_date_array[period ? period -1 : 0];
 | 
						|
}
 | 
						|
 | 
						|
bool TEsplosione_distinta_app::check_articoli(TMask_field& f, KEY k)
 | 
						|
{
 | 
						|
  if (k == K_ENTER && f.dlg() == F_QTA)
 | 
						|
  {
 | 
						|
    TMask& m = f.mask();
 | 
						|
      
 | 
						|
    TSheet_field& s = *m.get_sheet();
 | 
						|
    const int selected = s.selected();
 | 
						|
    TToken_string& row = s.row(selected);
 | 
						|
    bool ok;
 | 
						|
 | 
						|
    if (!row.empty_items())
 | 
						|
    {
 | 
						|
      const TCodice_articolo articolo(m.get(F_CODDIS));
 | 
						|
      const TCodice_um       um(m.get(F_UMEXPR));
 | 
						|
      const int items = s.items();
 | 
						|
      const short F = F_QTA - 101;
 | 
						|
      for (int i = 0; i < items; i++) 
 | 
						|
        if (i != selected && !s.row(i).empty_items()) // Articolo/unita' di misura gia' usata... chiede se gabolarli assieme...
 | 
						|
        { 
 | 
						|
          const TCodice_articolo art = s.row(i).get(0);
 | 
						|
          const TCodice_um u = s.row(i).get(7);
 | 
						|
          if (articolo == art && um == u)
 | 
						|
          {
 | 
						|
            ok = f.yesno_box("L'articolo %s (UM %s) e' gia' stato utilizzato al rigo %d.\n"
 | 
						|
                             "Si desidera sommare le quantita' nello stesso rigo?", 
 | 
						|
                             (const char*) articolo, (const char*) um, i+1);
 | 
						|
            if (ok)
 | 
						|
            { 
 | 
						|
              int src = selected, dst = i;
 | 
						|
              if (src < dst)
 | 
						|
                { int tmp = src; src = dst; dst = tmp; }
 | 
						|
              TToken_string& srcrow = s.row(src);
 | 
						|
              TToken_string& dstrow = s.row(dst);
 | 
						|
              
 | 
						|
              real tot = dstrow.get(F);
 | 
						|
              tot += real(srcrow.get(F)); 
 | 
						|
              dstrow.add(tot.string(), F);
 | 
						|
 | 
						|
              s.force_update(dst);
 | 
						|
              srcrow.cut(0);
 | 
						|
              s.force_update(src);
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
bool TEsplosione_distinta_app::create()
 | 
						|
{
 | 
						|
  open_files(LF_TAB, LF_TABCOM, LF_UMART, LF_OCCAS, LF_CLIFO, LF_DIST, 0);
 | 
						|
  open_files(LF_DOC, LF_RIGHEDOC, LF_INDSP, LF_CFVEN, LF_MAG, LF_STOMAG, 0);
 | 
						|
  _mask = new TMask("db1100a");
 | 
						|
  TSheet_field& sa = (TSheet_field&) _mask->field(F_SHEETART);
 | 
						|
  sa.sheet_mask().set_handler(F_QTA, check_articoli);
 | 
						|
  sa.set_notify(sheet_notify);
 | 
						|
  _mask->set(F_ARTICOLI, "X");
 | 
						|
  _mask->set(F_LAVORAZIONI, "X");
 | 
						|
  _mask->set(F_VIRTUALI, "X");
 | 
						|
  if (!livelli_giacenza().enabled()) //TBI
 | 
						|
    _mask->hide(F_SEPARATE_GIAC);
 | 
						|
    
 | 
						|
    
 | 
						|
 | 
						|
  rec_cache(LF_TAB).test_file_changes(FALSE);
 | 
						|
 | 
						|
  const int lf[] = { LF_UMART, LF_ANAMAG, LF_DIST, LF_RDIST, 0 };
 | 
						|
  for (int i = 0; lf[i]; i++)
 | 
						|
  {
 | 
						|
    int maxsize = 4096; 
 | 
						|
    if (lf[i] == LF_RDIST) 
 | 
						|
      maxsize *= 4;
 | 
						|
    rec_cache(lf[i]).set_items_limit(maxsize);
 | 
						|
    rec_cache(lf[i]).test_file_changes(FALSE);
 | 
						|
  }  
 | 
						|
 | 
						|
  _form = new TExplode_distinta_form("db1100a");
 | 
						|
  _liv_giac = new TCodgiac_livelli;
 | 
						|
  _liv_giac->set_sheetcolumn(sa, F_LIV1, 1);
 | 
						|
  _liv_giac->set_sheetcolumn(sa, F_LIV2, 2);
 | 
						|
  _liv_giac->set_sheetcolumn(sa, F_LIV3, 3);
 | 
						|
  _liv_giac->set_sheetcolumn(sa, F_LIV4, 4);
 | 
						|
  TConfig conf(CONFIG_DITTA, "mg");
 | 
						|
  const bool depositi = conf.get_bool("GESDEPOSITI");
 | 
						|
  sa.enable_column(F_DEP-F_CODDIS,depositi);
 | 
						|
  _mask->show(-G_DEPOSITI, depositi);
 | 
						|
  const bool listini = conf.get_bool("GES", "ve", 1);
 | 
						|
  _mask->enable(-G_LISTINO, listini);
 | 
						|
  _mask->enable(F_CATVEN_LIST, listini && conf.get_bool("GESLISCV", "ve"));
 | 
						|
  _mask->set(F_IMPIANTO, conf.get("DEFAULT_CODIMP", "mr"));
 | 
						|
  _mask->set(F_LINEA, conf.get("DEFAULT_CODLIN", "mr"));
 | 
						|
 | 
						|
  _doc = new TDocumento;
 | 
						|
  
 | 
						|
  //Compila la lista di codici numerazione validi per la ricerca dell'ordinato fornitori
 | 
						|
  compile_numeration_list();
 | 
						|
  
 | 
						|
  return TSkeleton_application::create();
 | 
						|
}
 | 
						|
 | 
						|
bool TEsplosione_distinta_app::destroy()
 | 
						|
{
 | 
						|
  delete _liv_giac;
 | 
						|
  delete _form;
 | 
						|
  delete _mask;
 | 
						|
  delete _doc;
 | 
						|
  return TSkeleton_application::destroy();
 | 
						|
}
 | 
						|
 | 
						|
void TEsplosione_distinta_app::compile_periods()
 | 
						|
{
 | 
						|
  TDate oggi(TODAY),dday;
 | 
						|
  
 | 
						|
  _date_array.destroy();
 | 
						|
  const long ndays = _parameters._obs_date - oggi;
 | 
						|
  const long daysperiod = ndays / _parameters._periods;
 | 
						|
  
 | 
						|
  dday = oggi;
 | 
						|
  
 | 
						|
  for (int i = 0; i < _parameters._periods; i++)
 | 
						|
  {
 | 
						|
    dday += daysperiod;
 | 
						|
    if (i == _parameters._periods -1)
 | 
						|
      dday = _parameters._obs_date;
 | 
						|
    _date_array.add(dday);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TEsplosione_distinta_app::compile_list()
 | 
						|
{
 | 
						|
  _dist_list.destroy();
 | 
						|
  
 | 
						|
  TDocumento& doc = *_doc;
 | 
						|
  TString key;
 | 
						|
  TRectype from(LF_DOC);
 | 
						|
  from.put(DOC_ANNO, _parameters._year);
 | 
						|
  from.put(DOC_PROVV, "D");
 | 
						|
  from.put(DOC_CODNUM, _parameters._from_num);
 | 
						|
  from.put(DOC_DATADOC, _parameters._from_date);
 | 
						|
  from.put(DOC_NDOC, _parameters._from_doc);
 | 
						|
  
 | 
						|
  TRectype to(from);
 | 
						|
  to.put(DOC_CODNUM, _parameters._to_num);
 | 
						|
  to.put(DOC_DATADOC, _parameters._to_date);
 | 
						|
  to.put(DOC_NDOC, _parameters._to_doc);
 | 
						|
  
 | 
						|
  TString filter_expr;
 | 
						|
  
 | 
						|
  if (_parameters._selections == by_date && _parameters._from_num.not_empty() && _parameters._to_num.not_empty())
 | 
						|
    filter_expr.format("(%s>=\"%s\")&&(%s<=\"%s\")", 
 | 
						|
       DOC_CODNUM, (const char*) _parameters._from_num, 
 | 
						|
       DOC_CODNUM, (const char*) _parameters._to_num);
 | 
						|
  
 | 
						|
  // Filtra i documenti
 | 
						|
  TLocalisamfile dist(LF_DIST);
 | 
						|
  TRelation r(LF_DOC);
 | 
						|
  TCursor c(&r, filter_expr, _parameters._selections == by_num ? 1 : 3);
 | 
						|
  c.setregion(from,to);
 | 
						|
  const bool null_sel = _parameters._from_num.empty() || _parameters._to_num.empty();
 | 
						|
  const long items = null_sel ? 0L : c.items();
 | 
						|
  TSheet_field& sa = (TSheet_field&) _mask->field(F_SHEETART);
 | 
						|
  const int righe = sa.items();
 | 
						|
  
 | 
						|
  TProgind p(items+righe,"Estrazione distinte da esplodere...", TRUE, TRUE);
 | 
						|
  c.freeze();
 | 
						|
  for (c = 0L; c.pos() < items; ++c)
 | 
						|
  {
 | 
						|
    p.addstatus(1);
 | 
						|
    if (p.iscancelled())
 | 
						|
      break;
 | 
						|
    if (doc.read(c.curr()) == NOERR)
 | 
						|
    {
 | 
						|
      const int rows = doc.rows();
 | 
						|
      for (int i = 1; i <= rows; i++)
 | 
						|
      {
 | 
						|
        dist.put("CODDIST", doc[i].get(RDOC_CODART));
 | 
						|
        if (doc[i].is_articolo() && dist.read() == NOERR) // Aggiunge le righe che sono solo effettivamente articoli di magazzino e distinte
 | 
						|
        {
 | 
						|
          TDist2Explode * de = new TDist2Explode;
 | 
						|
          de->set(doc[i], *_mask);
 | 
						|
          key = de->key();
 | 
						|
          const bool is_key = _dist_list.is_key(key);
 | 
						|
          if (is_key)
 | 
						|
          {
 | 
						|
            TDist2Explode * dd = (TDist2Explode*)_dist_list.objptr(key);
 | 
						|
            // Check whether we've 2 convert in base UM...
 | 
						|
            if (de->acqven()) // Se acquisto sottrae...
 | 
						|
              de->qta() = dd->qta() - de->qta();
 | 
						|
            else
 | 
						|
              de->qta() += dd->qta(); // altrimenti aggiunge
 | 
						|
          }
 | 
						|
          _dist_list.add(key, de, TRUE);
 | 
						|
          if (de->qta() == ZERO)
 | 
						|
            _dist_list.remove(key);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Aggiunge le righe dallo spreadsheet
 | 
						|
  for (int i = 0; i < righe; i++)
 | 
						|
  {
 | 
						|
    p.addstatus(1L);
 | 
						|
    if (!sa.row(i).empty_items())
 | 
						|
    {
 | 
						|
      TDist2Explode * de = new TDist2Explode;
 | 
						|
      de->set(sa.row(i), *_mask);
 | 
						|
      key = de->key();
 | 
						|
      const bool is_key = _dist_list.is_key(key);
 | 
						|
      if (is_key)
 | 
						|
      {
 | 
						|
        TDist2Explode * dd = (TDist2Explode*)_dist_list.objptr(key);
 | 
						|
        // Check 2 see whether we've 2 convert in base UM...
 | 
						|
        if (de->acqven()) // Se acquisto sottrae...
 | 
						|
          de->qta() = dd->qta() - de->qta();
 | 
						|
        else
 | 
						|
          de->qta() += dd->qta(); // altrimenti aggiunge
 | 
						|
      }
 | 
						|
      _dist_list.add(key, de, TRUE);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TEsplosione_distinta_app::compile_numeration_list()
 | 
						|
{
 | 
						|
  // Reperisce prima la lista dei tipi documento che siano Ordini fornitore
 | 
						|
  TProgind p(0,"Creazione lista numerazioni in corso...", FALSE, FALSE);
 | 
						|
  
 | 
						|
  TString_array a;
 | 
						|
  TTable tip("%TIP");
 | 
						|
  
 | 
						|
  for (tip.first(); tip.good(); tip.next())
 | 
						|
  {
 | 
						|
    TTipo_documento tp(tip.curr());
 | 
						|
    if (tp.is_ordine() && tp.tipocf() == 'F') // Ordine a fornitore
 | 
						|
      a.add(tp.codice());
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Poi si interseca questa lista con quella delle numerazioni
 | 
						|
  TTable num("%NUM");
 | 
						|
  TToken_string t;
 | 
						|
  TString s;
 | 
						|
  int r=0;
 | 
						|
  
 | 
						|
  for (num.first(); num.good(); num.next())
 | 
						|
  {
 | 
						|
 | 
						|
    _parameters._numerazioni.add(num.get("CODTAB"));
 | 
						|
    TToken_string& riga = (TToken_string&)_parameters._numerazioni[r++];
 | 
						|
 | 
						|
    s = num.get("S2"); // Lista dei tipi documento validi
 | 
						|
    t = "";
 | 
						|
    
 | 
						|
    for (int x = 0; x <= s.len(); x += 4)
 | 
						|
      t.add(s.mid(x,4));
 | 
						|
    
 | 
						|
    // Scorre i tipi documento ordine fornitore esistenti
 | 
						|
    for  (int i = a.last(); i >= 0; i--)
 | 
						|
    {
 | 
						|
      // Se il tipo documento esiste in questa numerazione...
 | 
						|
      TToken_string& ai = (TToken_string &) a[i];
 | 
						|
      if (t.find(ai.get(0)) >= 0)
 | 
						|
        // Aggiunge questo tipo documento alla lista per la numerazione corrente
 | 
						|
        riga.add(ai.get(0));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TEsplosione_distinta_app::print()
 | 
						|
{
 | 
						|
  TString       chiave;
 | 
						|
  TString_array chiavi;
 | 
						|
  _dist_list.get_keys(chiavi);
 | 
						|
  chiavi.sort(); // sort by : period+codart+livgiac+...
 | 
						|
  const int items = chiavi.items();
 | 
						|
  
 | 
						|
  if (items == 0)
 | 
						|
    return;
 | 
						|
    
 | 
						|
  // Settaggio parametri del form (fincature)
 | 
						|
  TPrinter& pr = printer();
 | 
						|
  pr.open();
 | 
						|
  const int hh = 7;
 | 
						|
  const int fl = pr.formlen();
 | 
						|
      
 | 
						|
  int rows[4];         // Righe orizzontali
 | 
						|
  rows[0] = hh-3;
 | 
						|
  rows[1] = hh;
 | 
						|
  rows[2] = fl-1;
 | 
						|
  rows[3] = 0;
 | 
						|
  
 | 
						|
  // Calcola la larghezza della colonna codice
 | 
						|
  TForm_item& fi_cod = _form->find_field('B', odd_page, 1); 
 | 
						|
  int c_width = 20;
 | 
						|
  if (_parameters._separate_dist)
 | 
						|
  {
 | 
						|
    c_width += 10;
 | 
						|
    if (_parameters._ordering)
 | 
						|
      c_width += 9;
 | 
						|
  }
 | 
						|
  fi_cod.width() = c_width;
 | 
						|
 | 
						|
  // Mostra la colonna Livello se necessario
 | 
						|
  TForm_item& fi_liv = _form->find_field('B', odd_page, 4); 
 | 
						|
  fi_liv.show(_parameters._separate_dist);
 | 
						|
  
 | 
						|
  // Setta l'intestazione corretta per la colonna del valore distinta
 | 
						|
  TForm_item& fi_val = _form->find_field('B', odd_page, 10); 
 | 
						|
  fi_val.set_col_head(_parameters._fabbisogno ? "@cValore da ord./prod." : "@cValore");
 | 
						|
  
 | 
						|
  _form->set_parameters(&_parameters);
 | 
						|
  _form->genera_intestazioni(odd_page, hh-2);
 | 
						|
  _form->genera_fincatura(odd_page, hh-3, fl-1, rows);
 | 
						|
  _form->reset_cache(); // Resetta ad ogni stampa
 | 
						|
  
 | 
						|
  // Ciclo per distinta: tutte quelle dei documenti indicati
 | 
						|
  // E tutte quelle indicate singolarmente nello spreadsheet dell'articolo
 | 
						|
  // Stampa esplosione distinta, nell'ordine specificato: periodo+codice+livello+um+mag
 | 
						|
  __current_period = __last_period = 0L;
 | 
						|
  
 | 
						|
  _form->reset_rows();
 | 
						|
  for (int i = 0 ; i<items; i++)
 | 
						|
  {
 | 
						|
    chiave = (TString&) chiavi[i];
 | 
						|
    _form->set_distinta((TDist2Explode*)_dist_list.objptr(chiave)); // Setta la distinta corrente
 | 
						|
    _form->explode_and_print(); // Esplode & Stampa sta distinta
 | 
						|
#ifdef DBG
 | 
						|
    unsigned long h, m;
 | 
						|
    TFile_cache::stats(h, m);
 | 
						|
    TString80 msg;
 | 
						|
    msg.format("Hits %lu  -  Misses %lu", h, m); 
 | 
						|
    xvt_statbar_set(msg);
 | 
						|
#endif    
 | 
						|
  }
 | 
						|
  _form->print_explosion_rows();
 | 
						|
  // Formfeed finale solo in caso non sia stata indicata la 
 | 
						|
  // separazione delle esplosioni (altrimenti ne fa 2...)
 | 
						|
  if (!_parameters._newpage)
 | 
						|
    pr.formfeed();
 | 
						|
  pr.close();
 | 
						|
}
 | 
						|
 | 
						|
void TEsplosione_distinta_app::main_loop()
 | 
						|
{
 | 
						|
  while (_mask->run()!=K_QUIT)
 | 
						|
  {
 | 
						|
    TDate df(1,1,1998);
 | 
						|
    TDate dt(31,12,1998);
 | 
						|
    // Raccolta dati dalla maschera
 | 
						|
    _parameters._selections   = (seltype) _mask->get_int(F_TIPOSEL);
 | 
						|
    _parameters._explosion    = (expltype) _mask->get_int(F_STAMPA);
 | 
						|
    _parameters._valorization = (valtype) _mask->get_int(F_VALORIZZAZIONE);
 | 
						|
    _parameters._group_by  = (TExplosion_grouping) _mask->get_int(F_GROUPMODE);
 | 
						|
    _parameters._year      = _mask->get_int(F_ANNO);
 | 
						|
    _parameters._from_num  = _mask->get(F_NUMFROM); 
 | 
						|
    _parameters._to_num    = _mask->get(F_NUMTO);
 | 
						|
    
 | 
						|
    // Setta le date di default (dal primo all'ultimo dell'anno)
 | 
						|
    df.set_year(_parameters._year);
 | 
						|
    dt.set_year(_parameters._year);
 | 
						|
 | 
						|
    _parameters._from_date = _mask->get_date(F_EMISFROM);
 | 
						|
    if (_parameters._from_date.empty())
 | 
						|
      _parameters._from_date = df;
 | 
						|
 | 
						|
    _parameters._to_date   = _mask->get_date(F_EMISTO);
 | 
						|
    if (_parameters._to_date.empty())
 | 
						|
      _parameters._to_date = dt;
 | 
						|
    
 | 
						|
    _parameters._from_doc  = _mask->get_long(F_NDOCFROM);
 | 
						|
    _parameters._to_doc    = _mask->get_long(F_NDOCTO);
 | 
						|
    _parameters._obs_date  = _mask->get_date(F_DATAOBS);
 | 
						|
    _parameters._periods   = _mask->get_int(F_PERIODS);
 | 
						|
    _parameters._det_lev   = _mask->get_int(F_DETTAGLIO);
 | 
						|
    _parameters._ordering  = _mask->get_int(F_SORT);
 | 
						|
    if (_mask->get_bool(F_NOIGNORE)) _parameters._ordering *= -1;
 | 
						|
    _parameters._vis_art   = _mask->get_bool(F_ARTICOLI);
 | 
						|
    _parameters._vis_vir   = _mask->get_bool(F_VIRTUALI);
 | 
						|
    _parameters._vis_lav   = _mask->get_bool(F_LAVORAZIONI);
 | 
						|
    _parameters._vis_gho   = _mask->get_bool(F_GHOST);
 | 
						|
    _parameters._fabbisogno= _mask->get_bool(F_FABBISOGNO);
 | 
						|
    _parameters._no_fabbis_fin= _mask->get_bool(F_FABBISOGNO_FIN);
 | 
						|
    _parameters._no_zero_ord = _mask->get_bool(F_NOZEROORD);
 | 
						|
    _parameters._sl_mag    = _mask->get(F_SLMAG); _parameters._sl_mag << _mask->get(F_SLDEP);
 | 
						|
    _parameters._mb_mag    = _mask->get(F_MBMAG); _parameters._mb_mag << _mask->get(F_MBDEP);
 | 
						|
    _parameters._val_magmb = _mask->get_bool(F_VALMAGMB);
 | 
						|
    _parameters._val_depmb = _mask->get_bool(F_VALDEPMB);
 | 
						|
    _parameters._liv_attenzione  = _mask->get(F_LIVATTENZ)[0];
 | 
						|
    _parameters._newpage = _mask->get_bool(F_NEWPAGE);
 | 
						|
    _parameters._det_ord_for    = _mask->get_bool(F_DETORDFOR);
 | 
						|
    _parameters._separate_dist = _mask->get_bool(F_SEPARATE_DIST);
 | 
						|
    _parameters._separate_giac = _mask->get_bool(F_SEPARATE_GIAC); 
 | 
						|
    _parameters._add_orc = _mask->get_bool(F_ORCLI4DISP);
 | 
						|
    _parameters._add_orf = _mask->get_bool(F_ORFOR4DISP);
 | 
						|
    _parameters._add_prf = _mask->get_bool(F_INPRF4DISP);
 | 
						|
    _parameters._add_prc = _mask->get_bool(F_INPRC4DISP);
 | 
						|
    _parameters._add_incl = _mask->get_bool(F_INCLV4DISP);
 | 
						|
    _parameters._add_acl = _mask->get_bool(F_ACLV4DISP);
 | 
						|
    _parameters._normal_disp = _parameters._add_orc && _parameters._add_orf &&
 | 
						|
                               _parameters._add_prf && _parameters._add_prc &&
 | 
						|
                               _parameters._add_acl && _parameters._add_acl;
 | 
						|
    
 | 
						|
    // Credo che il seguente anno esercizio sia calcolato
 | 
						|
    // in modo abbastanza schifoso, visto che si e' in possesso del solo anno solare
 | 
						|
    // Da controllare in futuro ...
 | 
						|
    TDate d(TODAY);
 | 
						|
    d.set_year(_parameters._year);
 | 
						|
    TEsercizi_contabili esc;
 | 
						|
    _parameters._anno_es.format("%04d",esc.date2esc(d));
 | 
						|
    _parameters._catven=_mask->get(F_CATVEN_LIST);
 | 
						|
    _parameters._codlist=_mask->get(F_CODLIST);
 | 
						|
    
 | 
						|
    // Compila la lista di testate termo-nucleare-globale 
 | 
						|
    // delle distinte da esplodere nell'universo conosciuto    
 | 
						|
    compile_periods();
 | 
						|
    compile_list();
 | 
						|
    
 | 
						|
    // Stampa...
 | 
						|
    print();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// db1100 stampa esplosione distinte
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
int db1100(int argc, char* argv[])
 | 
						|
{
 | 
						|
  TEsplosione_distinta_app *a = new TEsplosione_distinta_app;
 | 
						|
  a->run(argc, argv, "Stampa esplosione");
 | 
						|
  delete a;
 | 
						|
  return 0;
 | 
						|
}
 |