Files correlati : db0.exe db0500a.msk db0500b.msk db1.exe db1100a.msk Attivata la descrizione della distinta in immissione Copiato l’articolo nel codice distinta in ricerca Impostata l’unità di misura nella pagina disponibilità dell’esplosione Stampate la descrizione di distinta a e di riga nell’ esplosione git-svn-id: svn://10.65.10.50/branches/R_10_00@24001 c028cbd2-c16b-5b4b-a496-9718f37d4682
2016 lines
64 KiB
C++
Executable File
2016 lines
64 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")
|
|
{
|
|
|
|
TToken_string fa(re.path(), '~');
|
|
TToken_string key(fa.get(0));
|
|
TToken_string tmp("", '~');
|
|
TString code;
|
|
|
|
TToken_string & p = (TToken_string &) re.path();
|
|
p.get(-2, (TString &)tmp);
|
|
tmp.get(2, code);
|
|
|
|
if (code == "0")
|
|
valore = cache().get(LF_DIST, key, DIST_DESCR);
|
|
else
|
|
{
|
|
key.add(code); // ??????
|
|
valore = cache().get(LF_RDIST, key, RDIST_DESCR);
|
|
}
|
|
|
|
if (valore.blank())
|
|
{
|
|
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();
|
|
TSheet_field& sa = (TSheet_field&) _mask->field(F_SHEETART);
|
|
int righe = sa.items();
|
|
|
|
if (items+righe > 0)
|
|
{
|
|
TProgind p(items+righe,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
|
|
// sa = _mask->sfield(F_SHEETART);
|
|
// 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;
|
|
}
|