1993 lines
63 KiB
C++
Executable File
1993 lines
63 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 <printer.h>
|
|
#include <progind.h>
|
|
|
|
#include "../cg/cglib01.h"
|
|
#include "../mg/mglib.h"
|
|
#include "../ve/velib.h"
|
|
#include "dblib.h"
|
|
|
|
#include "dist.h"
|
|
#include "rdist.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};
|
|
|
|
struct _ParmStruct
|
|
{
|
|
seltype _selections;
|
|
expltype _explosion;
|
|
valtype _valorization;
|
|
bool _advanced_val;
|
|
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, _sort_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;
|
|
TToken_string _cod_corr;
|
|
|
|
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; }
|
|
const TString& codici_corrispontenti(char tipo) const;
|
|
TRiga_esplosione2print() : _cod_corr(80, '\n') {};
|
|
TRiga_esplosione2print(const TDistinta_tree& tree, const char *codmag);
|
|
TRiga_esplosione2print(const TRiga_esplosione& re, const char *codmag);
|
|
~TRiga_esplosione2print() {};
|
|
};
|
|
|
|
const TString& TRiga_esplosione2print::codici_corrispontenti(char tipo) const
|
|
{
|
|
TRectype key(LF_CODCORR);
|
|
key.put("CODART", articolo());
|
|
TRecord_array a(key, "NRIGA");
|
|
|
|
TToken_string& lista = (TToken_string&)_cod_corr; // Fool the compiler
|
|
lista.cut(0);
|
|
|
|
const int last = a.last_row();
|
|
for (int i = a.first_row(); i > 0 && i <= last; i = a.succ_row(i))
|
|
{
|
|
const TRectype& row = a.row(i);
|
|
if (tipo < ' ' || row.get_char("TIPO") == tipo)
|
|
lista.add(row.get("CODARTALT"));
|
|
}
|
|
return lista;
|
|
}
|
|
|
|
TRiga_esplosione2print::TRiga_esplosione2print(const TDistinta_tree& tree, const char *codmag)
|
|
: TRiga_esplosione(tree), _codmag(codmag), _cod_corr(80, '\n')
|
|
{
|
|
}
|
|
|
|
TRiga_esplosione2print::TRiga_esplosione2print(const TRiga_esplosione& re, const char *codmag)
|
|
: TRiga_esplosione(re), _codmag(codmag), _cod_corr(80, '\n')
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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(const TArray& exp_array);
|
|
real res2produce_by_father(const TRiga_esplosione& re) const;
|
|
|
|
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(); }
|
|
|
|
static TArticolo_cache& cache_articoli() { return _f->_art_cache; }
|
|
|
|
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;
|
|
int _default_code_width;
|
|
|
|
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_nodo(TDistinta_tree & node, _CallBackStruct & c)
|
|
{
|
|
TAssoc_array* valori = c._a;
|
|
TToken_string path;
|
|
node.curr_id(path);
|
|
|
|
real * valore = (real *) valori->objptr(path);
|
|
|
|
if (valore != NULL)
|
|
return *valore;
|
|
|
|
_ParmStruct * pp = c._p;
|
|
real totale;
|
|
TCodice_articolo codart;
|
|
TString16 liv;
|
|
TCodice_um um;
|
|
const TString& annoes = pp->_anno_es;
|
|
const TString& catven = pp->_catven;
|
|
TString16 codmag;
|
|
TString& codlist = pp->_codlist;
|
|
const bool dettagliata = pp->_advanced_val;
|
|
bool valorizzato = false;
|
|
const char tipo = node.curr_type();
|
|
real valore_un;
|
|
|
|
node.curr_um(um);
|
|
node.curr_code(codart);
|
|
node.curr_giaclev(liv);
|
|
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
|
|
}
|
|
|
|
if (dettagliata && tipo == 'A')
|
|
{
|
|
TArticolo_giacenza & art = TExplode_distinta_form::cache_articoli().art(codart);
|
|
const valtype art_tipo = (valtype)art.get_int(ANAMAG_VALDIST);
|
|
|
|
if (art_tipo > no_val)
|
|
{
|
|
const TDate inizio_val = art.get_date(ANAMAG_DATAVDIST);
|
|
if (pp->_obs_date >= inizio_val)
|
|
{
|
|
switch (art_tipo)
|
|
{
|
|
case last_cost: valore_un = art.ultimo_costo(annoes); break;
|
|
case last2cost: valore_un = art.media_costi(annoes); break;
|
|
case std_cost: valore_un = art.costo_standard(annoes); break;
|
|
case average_cost: valore_un = art.costo_medio(annoes, codmag, liv); break;
|
|
case pond_cost: valore_un = art.costo_mediopond(annoes, codmag, liv); break;
|
|
case LIFO_annuale: valore_un = art.LIFO_annuale(annoes, codmag, liv); break;
|
|
case FIFO_annuale: valore_un = art.FIFO_annuale(annoes, codmag, liv); break;
|
|
case LIFO_storico: valore_un = art.LIFO(annoes, codmag, liv); break;
|
|
case FIFO_storico: valore_un = art.FIFO(annoes, codmag, liv); break;
|
|
case prezzo_listino: valore_un = art.prezzo_listino(annoes, catven, codlist); break;
|
|
default: NFCHECK("Tipo valorizzazione errato: %d", (valtype) art_tipo);
|
|
}
|
|
|
|
valore_un = art.convert_to_um(valore_un, um);
|
|
valorizzato = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!valorizzato)
|
|
{
|
|
if (node.has_son())
|
|
{
|
|
for (bool ok = node.goto_firstson(); ok ; ok = node.goto_rbrother())
|
|
valore_un += valorizza_nodo(node, c);
|
|
node.goto_father();
|
|
}
|
|
else
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case 'A':
|
|
{
|
|
TArticolo_giacenza & art = TExplode_distinta_form::cache_articoli().art(codart);
|
|
const valtype val = pp->_valorization;
|
|
|
|
switch (val)
|
|
{
|
|
case last_cost: valore_un = art.ultimo_costo(annoes); break;
|
|
case last2cost: valore_un = art.media_costi(annoes); break;
|
|
case std_cost: valore_un = art.costo_standard(annoes); break;
|
|
case average_cost: valore_un = art.costo_medio(annoes, codmag, liv); break;
|
|
case pond_cost: valore_un = art.costo_mediopond(annoes, codmag, liv); break;
|
|
case LIFO_annuale: valore_un = art.LIFO_annuale(annoes, codmag, liv); break;
|
|
case FIFO_annuale: valore_un = art.FIFO_annuale(annoes, codmag, liv); break;
|
|
case LIFO_storico: valore_un = art.LIFO(annoes, codmag, liv); break;
|
|
case FIFO_storico: valore_un = art.FIFO(annoes, codmag, liv); break;
|
|
case prezzo_listino: valore_un = art.prezzo_listino(annoes, catven, codlist); break;
|
|
default: NFCHECK("Tipo valorizzazione errato: %d", val); break;
|
|
}
|
|
valore_un = art.convert_to_um(valore_un, um);
|
|
}
|
|
break;
|
|
case 'L':
|
|
{
|
|
TLavorazione lav(codart);
|
|
valore_un = lav.prezzo();
|
|
}
|
|
break;
|
|
case 'D':
|
|
valore_un = real(cache().get(LF_DIST, codart, "PREZZO"));
|
|
break;
|
|
case 'V':
|
|
NFCHECK("L'articolo %s porca COVER", (const char*)codart);
|
|
break;
|
|
default :
|
|
NFCHECK("L'articolo %s non esiste", (const char*)codart);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
valori->add(path, valore_un);
|
|
const real qta = node.last_qta(); // NON node.curr_qta();
|
|
const real valore_totale = valore_un * qta;
|
|
|
|
return valore_totale;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////
|
|
// 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);
|
|
from.put(RDOC_CODNUM, rec.get(DOC_CODNUM));
|
|
from.put(RDOC_ANNO, rec.get(DOC_ANNO));
|
|
from.put(RDOC_PROVV, rec.get(DOC_PROVV));
|
|
|
|
TString filter;
|
|
|
|
int nkey = 1;
|
|
|
|
// Se NDOC non è settato effettua il filtro su tutti i documenti di questa numerazione
|
|
const long ndoc = rec.get_long(DOC_NDOC);
|
|
if (ndoc > 0)
|
|
{
|
|
from.put(RDOC_NDOC, ndoc);
|
|
filter = "CODART==\"";
|
|
filter << codice() << "\"";
|
|
}
|
|
else
|
|
{
|
|
nkey = 2;
|
|
from.put(RDOC_CODART, codice());
|
|
}
|
|
|
|
TRelation rdoc(LF_RIGHEDOC);
|
|
TCursor cur(&rdoc, filter, nkey, &from, &from);
|
|
const TRecnotype items = cur.items();
|
|
|
|
if (items > 0)
|
|
{
|
|
TWait_cursor hourglass;
|
|
cur.freeze();
|
|
|
|
filter = TR("Calcolo ordinato fornitori ");
|
|
filter << rec.get(DOC_CODNUM);
|
|
filter << "/" << codice();
|
|
|
|
TProgind *pi = items > 32 ? new TProgind(items, filter, FALSE, TRUE) : NULL;
|
|
for (cur = 0L; cur.pos() < items; ++cur)
|
|
{
|
|
// Calcola la qta residua
|
|
if (pi) pi->addstatus(1L);
|
|
|
|
const TRectype& rec = cur.curr();
|
|
if (!rec.get_bool(RDOC_RIGAEVASA))
|
|
{
|
|
real 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)
|
|
{
|
|
// 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
|
|
TEsercizi_contabili ese;
|
|
|
|
// 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);
|
|
int prev = ese.pred(atoi(annoes)); // Controllo anche l'anno precedente
|
|
while (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);
|
|
prev = ese.pred(prev);
|
|
}
|
|
}
|
|
|
|
// Rimuove eventuali elementi rimasti, anche se questo metodo viene effettivamente chiamato una sola
|
|
// volta per articolo.
|
|
_ordinato_fornitori.destroy();
|
|
// Azzera l'array...
|
|
int i;
|
|
|
|
for (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
|
|
{
|
|
int eser = atoi(p->_anno_es);
|
|
TRectype doc(LF_DOC);
|
|
|
|
while (eser > 0)
|
|
{
|
|
doc.put(DOC_CODNUM, t.get(0));
|
|
doc.put(DOC_ANNO, eser);
|
|
doc.put(DOC_PROVV, "D");
|
|
calcola_ordinato_documento(doc);
|
|
eser = ese.pred(eser);
|
|
}
|
|
}
|
|
else // Se invece vi sono piu' tipi doc. per questa numerazione e' necessario considerare le testate doc.
|
|
if (items >= 3)
|
|
{
|
|
int eser = atoi(p->_anno_es);
|
|
TRectype from(LF_DOC), to(LF_DOC);
|
|
TString filter;
|
|
|
|
while (eser > 0)
|
|
{
|
|
from.zero();
|
|
from.put(DOC_CODNUM, t.get(0));
|
|
from.put(DOC_ANNO, eser);
|
|
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());
|
|
eser = ese.pred(eser);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
TString4 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;
|
|
const TRiga_esplosione2print& re = (const TRiga_esplosione2print&) _exploded_tree[_curr_row];
|
|
const char tipo = re.tipo();
|
|
|
|
if (code[0] != '_')
|
|
{
|
|
const char tiporiga = t.get()[0];
|
|
if (tipo == tiporiga)
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case 'A':
|
|
{
|
|
valore = cache().get(LF_ANAMAG, re.articolo(), code);
|
|
break;
|
|
}
|
|
case 'L':
|
|
{
|
|
const TLavorazione lav(re.articolo());
|
|
valore = lav.get(code);
|
|
|
|
break;
|
|
}
|
|
case 'V':
|
|
{
|
|
TLocalisamfile& dist = relation()->lfile();
|
|
dist.put("CODDIST", re.articolo());
|
|
if (dist.read() == NOERR)
|
|
valore = dist.get(code);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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")
|
|
{
|
|
switch (tipo)
|
|
{
|
|
case 'L':
|
|
{
|
|
const TLavorazione lav(re.articolo());
|
|
valore = lav.descr();
|
|
}
|
|
break;
|
|
case 'V':
|
|
valore = cache().get(LF_DIST, re.articolo(), "DESCR");
|
|
break;
|
|
default:
|
|
valore = cache().get(LF_ANAMAG, re.articolo(), ANAMAG_DESCR);
|
|
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));
|
|
if (lv.full())
|
|
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 = cache().get(LF_ANAMAG, re.articolo(), ANAMAG_CODFORN);
|
|
}
|
|
else
|
|
if (code == "_CODCORR")
|
|
{
|
|
const char tipo = t.get()[0];
|
|
valore = re.codici_corrispontenti(tipo);
|
|
}
|
|
}
|
|
f.set(valore);
|
|
return true;
|
|
}
|
|
|
|
real TExplode_distinta_form::res2produce_by_father(const TRiga_esplosione& re) const
|
|
{
|
|
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);
|
|
}
|
|
|
|
TString8 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(const TArray& exp_array)
|
|
{
|
|
TString noexplode_path("*****");
|
|
const bool dettagliata = _p->_advanced_val;
|
|
const int rows = exp_array.items();
|
|
for (int i = 0; i < rows; i++)
|
|
{
|
|
const TRiga_esplosione& re = (const 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
|
|
TString8 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 (dettagliata && re.path().starts_with(noexplode_path))
|
|
continue;
|
|
|
|
if (re.articolo() == "00.73.00.0010")
|
|
int cazzone = 1;
|
|
|
|
real r = res2produce_by_father(re);
|
|
if (_p->_fabbisogno && _p->_explosion == scalare)
|
|
r *= re.last_qta(); // In UM locale...
|
|
else
|
|
r *= re.val(); // In UM locale...
|
|
|
|
if (dettagliata && tipo == 'A')
|
|
{
|
|
TArticolo_giacenza& art = TExplode_distinta_form::cache_articoli().art(re.articolo());
|
|
const valtype art_tipo = (valtype)art.get_int(ANAMAG_VALDIST);
|
|
|
|
if (art_tipo > no_val)
|
|
{
|
|
const TDate inizio_val = art.get_date(ANAMAG_DATAVDIST);
|
|
if (_p->_obs_date >= inizio_val)
|
|
noexplode_path = re.path();
|
|
}
|
|
}
|
|
|
|
if (r.is_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
|
|
|
|
const real min_ref = _p->_liv_attenzione == 'S' ? aaa.get_scmin(_p->_anno_es, codmag, liv) : ZERO;
|
|
const real zero_ref = aaa.convert_to_um(min_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 && r > ZERO) // Aggiunto r>0 il 28-09-2012 per GF
|
|
{
|
|
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)
|
|
{
|
|
const TString k = re.path(); // I nodi sono cachati con tutto il path in modo da essere univoci
|
|
|
|
if (_valori.objptr(k) == NULL)
|
|
r2p->set_unitary_value(ZERO);
|
|
else
|
|
r2p->set_unitary_value(*((real*)_valori.objptr(k)));
|
|
|
|
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())
|
|
{
|
|
// 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();
|
|
|
|
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';
|
|
|
|
TArray explosion_array;
|
|
_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());
|
|
valorizza_nodo(_distinta, 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(TR("Impossibile posizionare l'albero"));
|
|
}
|
|
|
|
// Ordina le righe di esplosione per livello/articolo/giacenza
|
|
int 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 ;
|
|
}
|
|
|
|
// Ordina le righe di esplosione per fornitore/articolo/giacenza
|
|
int compare_print_rows_forn(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)
|
|
{
|
|
TArticolo_cache& ac = TExplode_distinta_form::cache_articoli();
|
|
long f1 = atol(ac.get(r1.articolo()).get(ANAMAG_CODFORN));
|
|
long f2 = atol(ac.get(r2.articolo()).get(ANAMAG_CODFORN));
|
|
diff = f1 < f2 ? -1 : (f1 == f2 ? 0 : +1);
|
|
}
|
|
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)
|
|
{
|
|
if (_p->_sort_for)
|
|
_exploded_tree.sort(compare_print_rows_forn);
|
|
else
|
|
_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++)
|
|
{
|
|
TPrintrow& r = body.row(j);
|
|
const TFixed_string t(r.row());
|
|
if (!t.blank())
|
|
pr.print(r);
|
|
}
|
|
}
|
|
|
|
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_char(13) == '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))
|
|
{
|
|
const TDate d(TODAY);
|
|
TToken_string& t = s.row(r);
|
|
t.add(d.string(),s.cid2index(F_DATACONS));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
const int TEsplosione_distinta_app::date2period(const TDate& d)
|
|
{
|
|
const int items = _date_array.items();
|
|
int i;
|
|
|
|
for (i = 0; i<items; i++)
|
|
{
|
|
const TDate& limit = (const 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(s.cid2index(F_CODDIS));
|
|
const TCodice_um u = s.row(i).get(s.cid2index(F_UMEXPR));
|
|
if (articolo == art && um == u)
|
|
{
|
|
ok = f.yesno_box(FR("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);
|
|
TDate d(TODAY);
|
|
srcrow.add(d.string(),s.cid2index(F_DATACONS));
|
|
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, LF_CODCORR, 0);
|
|
|
|
_mask = new TMask("db1100a");
|
|
TSheet_field& sa = _mask->sfield(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");
|
|
|
|
TForm_item& fi_cod = _form->find_field('B', odd_page, 1);
|
|
_default_code_width = fi_cod.width();
|
|
|
|
_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();
|
|
|
|
if (items > 0)
|
|
{
|
|
TProgind p(items,TR("Estrazione distinte da esplodere da documenti..."));
|
|
c.freeze();
|
|
for (c = 0L; c.pos() < items; ++c)
|
|
{
|
|
if (!p.addstatus(1))
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_mask->get(F_DADIST).full() || _mask->get(F_ADIST).full())
|
|
{
|
|
TISAM_recordset dist("USE DIST\nFROM CODDIST=#DADIST\nTO CODDIST=#ADIST");
|
|
dist.set_var("#DADIST", _mask->get(F_DADIST));
|
|
dist.set_var("#ADIST", _mask->get(F_ADIST));
|
|
|
|
TProgind p(dist.items(), TR("Estrazione distinte..."));
|
|
TToken_string row;
|
|
for (bool ok = dist.move_first(); ok; ok = dist.move_next())
|
|
{
|
|
if (!p.addstatus(1))
|
|
break;
|
|
row = dist.get(DIST_CODDIST).as_string();
|
|
row.add(dist.get(DIST_UM).as_string(), 9);
|
|
row.add(1);
|
|
row.add(TDate(TODAY));
|
|
|
|
TDist2Explode* de = new TDist2Explode;
|
|
de->set(row, *_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);
|
|
}
|
|
}
|
|
|
|
|
|
// Aggiunge le righe dallo spreadsheet
|
|
TSheet_field& sa = _mask->sfield(F_SHEETART);
|
|
const int righe = sa.items();
|
|
if (righe > 0)
|
|
{
|
|
TProgind p(righe,TR("Estrazione distinte da esplodere..."));
|
|
for (int i = 0; i < righe; i++)
|
|
{
|
|
if (!p.addstatus(1L))
|
|
break;
|
|
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,TR("Creazione lista numerazioni in corso..."), FALSE, FALSE);
|
|
|
|
TString_array a;
|
|
TRelation reltip("%TIP");
|
|
const TRectype & tip = reltip.curr();
|
|
TCursor curtip(&reltip);
|
|
const TRecnotype items = curtip.items();
|
|
|
|
for (curtip = 0L; curtip.pos() < items; ++curtip)
|
|
{
|
|
TTipo_documento tp(tip);
|
|
|
|
if (tp.is_ordine() && tp.tipocf() == 'F') // Ordine a fornitore
|
|
a.add(tp.codice());
|
|
}
|
|
|
|
// Poi si interseca questa lista con quella delle numerazioni
|
|
TRelation relnum("%NUM");
|
|
TRectype & num = relnum.curr();
|
|
TCursor curnum(&relnum);
|
|
const TRecnotype itemsnum = curnum.items();
|
|
TToken_string t;
|
|
TString s;
|
|
int r=0;
|
|
|
|
for (curnum = 0L; curnum.pos() <itemsnum; ++curnum)
|
|
{
|
|
|
|
_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 = _default_code_width;
|
|
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 ? FR("@cValore da ord./prod.") : FR("@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);
|
|
xvtil_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._advanced_val = _mask->get_bool(F_ADVANCED_EXPL);
|
|
_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._sort_for = _mask->get_bool(F_SORTFOR);
|
|
_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, TR("Stampa esplosione"));
|
|
delete a;
|
|
return 0;
|
|
}
|