Files correlati : Ricompilazione Demo : [ ] Commento : Riportata la versione 01.05 patch 282 git-svn-id: svn://10.65.10.50/trunk@8019 c028cbd2-c16b-5b4b-a496-9718f37d4682
3802 lines
118 KiB
C++
Executable File
3802 lines
118 KiB
C++
Executable File
#include <applicat.h>
|
||
#include <colors.h>
|
||
#include <defmask.h>
|
||
#include <progind.h>
|
||
#include <tabutil.h>
|
||
#include <xvtility.h>
|
||
#include <utility.h>
|
||
|
||
#include "mrplib.h"
|
||
#include "../mg/mglib.h"
|
||
#include "../ve/velib.h"
|
||
#include "../ve/veconf.h"
|
||
|
||
#include "mr2100.h"
|
||
|
||
#include "mr2200a.h"
|
||
#include "mr2200b.h"
|
||
|
||
|
||
const real MAXCAPACITY("999999999.99");
|
||
///////////////////////////////////////////////////////////
|
||
// triga ordine
|
||
///////////////////////////////////////////////////////////
|
||
#define SORT_BY_CAL -1 // cliente / articolo / impianto-linea
|
||
#define SORT_BY_CLA -2 //
|
||
#define SORT_BY_ALC -3 //
|
||
#define SORT_BY_ACL -4 //
|
||
#define SORT_BY_LAC -5 //
|
||
#define SORT_BY_LCA -6 //
|
||
|
||
enum TMSP_mode {_actual_schedule, _stock_break};
|
||
enum TMSP_logic {_first_fit_logic, _JIT_logic};
|
||
|
||
|
||
class TMSP_constraint;
|
||
class TMSP_constraints;
|
||
class TMSP_mask;
|
||
|
||
class TRiga_articolo : public TToken_string
|
||
{
|
||
public:
|
||
static int order_compare(TSheet_field & s, int i1, int i2, int level);
|
||
static int order_compare( const TToken_string& r1 , const TToken_string& r2 , int level);
|
||
static int compare_field(TString &str0, TString &str1,short field_no) ;
|
||
static int order_compareCAL(TSheet_field & s, int i1, int i2);
|
||
static int order_compareCLA(TSheet_field & s, int i1, int i2);
|
||
static int order_compareALC(TSheet_field & s, int i1, int i2);
|
||
static int order_compareACL(TSheet_field & s, int i1, int i2);
|
||
static int order_compareLAC(TSheet_field & s, int i1, int i2);
|
||
static int order_compareLCA(TSheet_field & s, int i1, int i2);
|
||
static bool find_block(const TSheet_field& sf, const int riga, int &first_row, int &last_row );
|
||
|
||
int compare(const TToken_string& r, int level) const;
|
||
TRiga_articolo& operator=(TToken_string& r);
|
||
TRiga_articolo& operator+=(TRiga_articolo& r);
|
||
|
||
TRiga_articolo() : TToken_string(128) { }
|
||
TRiga_articolo(const TMSP_constraint & line);
|
||
virtual ~TRiga_articolo() { }
|
||
};
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TMSP_record
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TMSP_record : public TObject
|
||
{
|
||
public:
|
||
long _numdoc;
|
||
int _numrig;
|
||
real _qta;
|
||
real _price;
|
||
|
||
TMSP_record() : _numdoc(0L), _numrig(0) { }
|
||
};
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TMSP_record_array;
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TMSP_record_array : public TObject
|
||
{
|
||
TArray _buckets;
|
||
|
||
public:
|
||
int items() const { return _buckets.items(); }
|
||
int last() const { return _buckets.last(); }
|
||
int pred(int i) const { return _buckets.pred(i); }
|
||
|
||
TMSP_record& operator[](int b);
|
||
};
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TCRP_line ; carichi di linea
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TCapacita_prod : public TSortable
|
||
{
|
||
real _capacity; // Capacita' macchina
|
||
real _human_capacity; // Capacita' macchina
|
||
real _load; // Carico macchina
|
||
real _human_load; // Carico uomo
|
||
|
||
// static TDecoder* _umart1; // Decoder per trovare unita' base articolo
|
||
// static TDecoder* _umart2; // Decoder per trovare conversione
|
||
// static TDecoder* _umdist; // Decoder per trovare unita' base distinta
|
||
|
||
protected:
|
||
virtual int compare(const TSortable& s) const;
|
||
virtual TObject* dup() const { return new TCapacita_prod(*this); }
|
||
|
||
void copy(const TCapacita_prod& q);
|
||
real get_factor(const TCodice_um& um) const;
|
||
void convert(real& val, const TCodice_um& from_um, const TCodice_um& to_um) const;
|
||
|
||
public:
|
||
const TCapacita_prod& operator =(const TCapacita_prod& q)
|
||
{ copy(q); return q; }
|
||
|
||
void set(const real& cap, const real& load);
|
||
void set_capacity(const real& cap){_capacity=cap;}
|
||
void set_human_capacity(const real& cap){_human_capacity=cap;}
|
||
void set_load(const real& load) {_load=load;}
|
||
void set_human_load(const real& load) {_human_load=load;}
|
||
|
||
void add_capacity(const real& cap){_capacity+=cap;}
|
||
void add_human_capacity(const real& cap){_human_capacity+=cap;}
|
||
void add_load(const real& load) {_load+=load;}
|
||
void add_human_load(const real& load) {_human_load+=load;}
|
||
|
||
real & capacity() {return _capacity;}
|
||
real & load() {return _load;}
|
||
real & human_capacity() {return _human_capacity;}
|
||
real & human_load() {return _human_load;}
|
||
|
||
TCapacita_prod ();
|
||
TCapacita_prod (const real& cap, const real& load);
|
||
TCapacita_prod (const TCapacita_prod & q) { copy(q); }
|
||
virtual ~TCapacita_prod () {}
|
||
};
|
||
|
||
|
||
class TCRP_line : public TSortable
|
||
{
|
||
TString8 _lineap, _imp;
|
||
TString _desc;
|
||
bool _on_sheet;
|
||
|
||
TArray _bucket;
|
||
|
||
|
||
protected:
|
||
virtual int compare(const TSortable& s) const;
|
||
TCapacita_prod& bucket(int n) ;
|
||
TCapacita_prod& operator[](int n)
|
||
{return bucket(n);}
|
||
|
||
public:
|
||
|
||
const TString& codimp() const { return _imp; }
|
||
const TString& codlin() const { return _lineap; }
|
||
const TString& desc() const { return _desc; }
|
||
void set_desc(const char* str) { _desc = str; }
|
||
|
||
int last() const { return _bucket.last(); }
|
||
int pred(int i) const { return _bucket.pred(i); }
|
||
|
||
real& capacity(int b) { return bucket(b).capacity(); }
|
||
real& load(int b) { return bucket(b).load(); }
|
||
real& human_capacity(int b) { return bucket(b).human_capacity(); }
|
||
real& human_load(int b) { return bucket(b).human_load(); }
|
||
|
||
void set_capacity(int b,const real & v ) { bucket(b).set_capacity(v); }
|
||
void set_human_capacity(int b,const real & v ) { bucket(b).set_human_capacity(v); }
|
||
// void set_load(int b, const real & v) { bucket(b).set_load(v); }
|
||
// void set_human_capacity(int b,const real & v ) { bucket(b).set_human_capacity(v); }
|
||
// void set_human_load(int b, const real & v) { bucket(b).set_human_load(v); }
|
||
|
||
// void add_capacity(int b,const real & v ) { bucket(b).add_capacity(v); }
|
||
void add_load(int b, const real & v) { bucket(b).add_load(v); }
|
||
// void add_human_capacity(int b,const real & v ) { bucket(b).add_human_capacity(v); }
|
||
void add_human_load(int b, const real & v) { bucket(b).add_human_load(v); }
|
||
|
||
void fill_capacity_row(TToken_string& row, bool percent=FALSE);
|
||
void fill_load_row(TToken_string& row, bool percent=FALSE);
|
||
void fill_hcapacity_row(TToken_string& row, bool percent=FALSE);
|
||
void fill_hload_row(TToken_string& row, bool percent=FALSE);
|
||
|
||
bool is_on_sheet() const { return _on_sheet; }
|
||
void set_on_sheet(bool on = TRUE) { _on_sheet = on; }
|
||
|
||
//TCRP_line(const TString& codlin);
|
||
TCRP_line(const TString& codimp,const TString& codlin);
|
||
virtual ~TCRP_line() { }
|
||
};
|
||
|
||
|
||
class TCRP_lines : public TMRP_array
|
||
{
|
||
protected:
|
||
virtual TSortable* new_obj(const TToken_string& key) const;
|
||
|
||
public:
|
||
TCRP_line* find(const TLinea_prod& linea_prod,
|
||
const char * codart="", long codcli=0L, bool create=FALSE);
|
||
TCRP_line* find(const char * codimp="", const char * codlin="",
|
||
const char * codart="", long codcli=0L, bool create=FALSE);
|
||
TCRP_line& operator[](long n) const
|
||
{ return (TCRP_line&)find_obj(n); }
|
||
};
|
||
|
||
class TMaster_code : public TObject
|
||
{
|
||
TString _code;
|
||
TString _liv;
|
||
TString _um;
|
||
TString _codimp;
|
||
TString _codlin;
|
||
TString _codmag;
|
||
real _expr;
|
||
real _leadtime;
|
||
public:
|
||
const char *articolo() const {return _code;}
|
||
const char *livello() const {return _liv;}
|
||
const char *um() const {return _um;}
|
||
const real &expr() const {return _expr;}
|
||
const real &leadtime() const {return _leadtime;}
|
||
const char *codimp() const {return _codimp;}
|
||
const char *codlin() const {return _codlin;}
|
||
const char *codmag() const {return _codmag;}
|
||
|
||
TMaster_code(const char *code, const char *liv, const char *ummaster, const real &expr, const real &leadtime, const char *codimp, const char *codlin, const char *codmag);
|
||
TMaster_code(const char *code, const char *liv,const char *ummaster, const real &expr, int leadtime, const char *codimp, const char *codlin, const char *codmag);
|
||
virtual ~TMaster_code() {}
|
||
};
|
||
|
||
class TMSP_constraints : public TMRP_array
|
||
{
|
||
protected:
|
||
virtual TSortable* new_obj(const TToken_string& key) const;
|
||
|
||
public:
|
||
TMSP_constraint* find(long cliente,const TString& codart,const TString& giac,
|
||
const TString& imp, const TString& lin, const TString& mag,
|
||
bool create=FALSE) ;
|
||
|
||
TMSP_constraint& operator[](long n) const
|
||
{ return (TMSP_constraint&)find_obj(n); }
|
||
};
|
||
|
||
|
||
class TMSP_constraint : public TSortable
|
||
{
|
||
long _cliente;
|
||
TCodice_articolo _codart;
|
||
TString16 _giac;
|
||
TString8 _imp, _lin;
|
||
TString8 _mag;
|
||
TString _desc;
|
||
|
||
bool _on_sheet;
|
||
TArray _mastercodes; // codici di livello 2 per articoli NON master
|
||
TMSP_constraints _upperlines; // vincoli dei codici di livello 1 per articoli master
|
||
|
||
TMSP_record_array _bucket_qta;
|
||
|
||
protected:
|
||
virtual int compare(const TSortable& s) const;
|
||
|
||
public:
|
||
long cliente() const { return _cliente; }
|
||
const TCodice_articolo& codice() const { return _codart; }
|
||
const TString& livgiac() const { return _giac; }
|
||
const TString& codimp() const { return _imp; }
|
||
const TString& codlin() const { return _lin; }
|
||
const TString& codmag() const { return _mag; }
|
||
const TString& desc() const { return _desc; }
|
||
void set_desc(const char* str) { _desc = str; }
|
||
|
||
bool riga(int b, long& ndoc, int& nriga);
|
||
void set_riga(int b, long ndoc, int nriga);
|
||
// master sched. a due livelli:
|
||
void add_mastercode(TMaster_code * mc);
|
||
TMaster_code * get_mastercode(int i=0);
|
||
bool has_mastercodes() const ;
|
||
void add_upperline(TMSP_constraint& constr);
|
||
TMSP_constraint* get_upperline(TMSP_constraint& constr);
|
||
bool has_upperlines() const ;
|
||
|
||
int last() const { return _bucket_qta.last(); }
|
||
int pred(int i) const { return _bucket_qta.pred(i); }
|
||
|
||
virtual real& qta(int b) { return _bucket_qta[b]._qta; }
|
||
virtual real& price(int b) { return _bucket_qta[b]._price; }
|
||
|
||
virtual void fill_sheet_row(TToken_string& row, const TMSP_mask & m, bool codes_only=FALSE);
|
||
|
||
bool is_on_sheet() const { return _on_sheet; }
|
||
void set_on_sheet(bool on = TRUE) { _on_sheet = on; }
|
||
|
||
TMSP_constraint & operator=(const TMSP_constraint & line);
|
||
|
||
TMSP_constraint(long cliente,
|
||
const TCodice_articolo& codart,
|
||
const TString& giac,
|
||
const TString& imp, const TString& lin,
|
||
const TString& mag);
|
||
TMSP_constraint(TMSP_constraint & cons);
|
||
virtual ~TMSP_constraint() { }
|
||
};
|
||
|
||
// linee contenenti pianificazioni
|
||
class TMSP_line : public TMSP_constraint
|
||
{
|
||
public:
|
||
|
||
virtual void fill_sheet_row(TToken_string& row, const TMSP_mask & m, bool codes_only=FALSE);
|
||
TMSP_line(long cliente, const TCodice_articolo& codart,
|
||
const TString& giac, const TString& mag,
|
||
const TString& imp, const TString& lin);
|
||
TMSP_line(TMSP_line & line);
|
||
TMSP_line(TMSP_constraint & cons);
|
||
virtual ~TMSP_line() { }
|
||
};
|
||
|
||
|
||
class TMSP_lines : public TMRP_array
|
||
{
|
||
protected:
|
||
virtual TSortable* new_obj(const TToken_string& key) const;
|
||
|
||
public:
|
||
TMSP_line* find(long cliente, const TString& art, const TString& gia,
|
||
const TString& imp, const TString& lin, const TString& mag,
|
||
bool create=FALSE);
|
||
|
||
TMSP_line* find(const TToken_string& row, TCodice_livelli & levels, bool create=FALSE);
|
||
|
||
TMSP_line& operator[](long i) const
|
||
{ return (TMSP_line&)find_obj(i); }
|
||
};
|
||
|
||
|
||
|
||
class TMSP_mask : public TCalendar_mask
|
||
{
|
||
TCodgiac_livelli _livelli;
|
||
// quantit<69> provenienti dai documenti "ordine":
|
||
TMSP_constraints _constraints;
|
||
|
||
// quantit<69> provenienti dai documenti "planning" (commesse):
|
||
TMSP_lines _articles;
|
||
|
||
// quantit<69> per il processo di nettificazione/sizing in caso di generazione dell'MSP
|
||
TMRP_lines _mrp_articles;
|
||
// proposte del sistema
|
||
TMRP_lines _proposed_articles, _proposed_1stlevel;
|
||
|
||
// capacit<69> linea per linea
|
||
TCRP_lines _capacities;
|
||
|
||
// albero per le ricerche sulle dist
|
||
TDistinta_tree _dist_tree;
|
||
|
||
|
||
protected:
|
||
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
|
||
bool load_MRP_lines(TMSP_mode mode, int level=0);
|
||
bool nettify_MRP_lines(bool already_net, bool lotsizing=FALSE);
|
||
void add_MRP_bucket(TMRP_line& new_article, int nbucket, const real &curr_arts);
|
||
// proposta automatica del sistema
|
||
bool general_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode, TMSP_logic logic );
|
||
bool insert_propose(bool verbose=FALSE) ;
|
||
bool remove_propose(bool verbose=FALSE) ;
|
||
void add_or_sub_propose(char sign);
|
||
|
||
void propose_1stJIT(TMSP_logic logic, bool check_m, bool check_h);
|
||
// void propose_firstfit(bool check_m, bool check_h);
|
||
// bool firstfit_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode);
|
||
// void propose_JIT(bool check_m, bool check_h);
|
||
// bool JIT_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode);
|
||
// controlli
|
||
bool sort_sheet();
|
||
void check_articles();
|
||
void check_capacities();
|
||
void pack_article_sheet();
|
||
// capacity review
|
||
bool capacity_review(bool useextralines, bool useextrahours);
|
||
TCRP_line *compute_capacity(TLinea_prod &lineaprod, bool useextralines, bool useextrahours);
|
||
|
||
TMSP_constraint* find_constraint(const TMSP_line& l,bool force_insert=FALSE);
|
||
int find_constr_row(const TMSP_constraint& c);
|
||
|
||
bool do_test_art_row(int r, int c, bool signal);
|
||
bool test_art_row(int r, bool signal=TRUE);
|
||
bool test_load_row(int r, bool signal=TRUE);
|
||
int init_bucket0(TArticolo_giacenza &art, int r);
|
||
|
||
void copy_sheet_row(TToken_string & newrow, const TToken_string & row);
|
||
|
||
void clear_sheets();
|
||
|
||
bool distinta_master(const char *code);
|
||
int find_distinta_master(const char * code, TString & master, TString & livmaster,TString & um,real & expr, TString & imp,TString & lin,TString & magdep, int fromindex=0);
|
||
|
||
public:
|
||
const TCodgiac_livelli& livelli_giac() const {return _livelli;}
|
||
|
||
void msprow2codes(TToken_string &row, long &clifor, TCodice_articolo &art ,
|
||
TString & liv, TString & mag, TString & imp, TString & lin, TString & um);
|
||
void crprow2codes(TToken_string &row, TString & imp, TString & lin, long &clifor, TCodice_articolo &art ,
|
||
TString & liv, TString & um);
|
||
TMRP_line* find_propose(long codcli, const char * codart,const char * liv,
|
||
const char * codimp,const char * codlin,const char * mag,
|
||
bool Force=FALSE);
|
||
TMSP_line* find_article(long cli, const char *art, const char *liv,
|
||
const char *imp, const char *lin, const char *mag,bool Force=FALSE)
|
||
{return _articles.find(cli, art, liv, imp, lin, mag, Force);}
|
||
|
||
|
||
int days_per_bucket() const;
|
||
|
||
int round_date(TDate& date, bool up = FALSE) const;
|
||
void round_field(TMask_field& fld, bool up) const;
|
||
|
||
int test_codnum(const TCodice_numerazione& num) const;
|
||
bool test_tipodoc_num( const TSheet_field &sheet_num , const TSheet_field &sheet_type) ;
|
||
|
||
bool test_status(const TRectype& doc, int tipo) const;
|
||
bool carica_documenti();
|
||
void fill_sheet();
|
||
void salva_documenti();
|
||
|
||
TMSP_mask();
|
||
virtual ~TMSP_mask() { }
|
||
};
|
||
|
||
class TMSPCheck_mask : public TAutomask
|
||
{
|
||
protected:
|
||
int _col, _row, _constr_row, _last_col, _last_row;
|
||
TMSP_mask * _main_mask;
|
||
TSheet_field * _sheet;
|
||
protected:
|
||
int max_rows() {return _sheet->items();}
|
||
void go_top();
|
||
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
bool move_to(int dlg);
|
||
virtual void check_pos_range();
|
||
virtual int fill_mask(const bool show=TRUE);
|
||
virtual bool is_constraint(int row);
|
||
virtual bool is_article(int row);
|
||
virtual int find_constraint(int row);
|
||
public:
|
||
void gopos(int row, int col);
|
||
virtual void gopos_mainmask();
|
||
void fix_actual_pos();
|
||
short last_row(){ return _last_row;}
|
||
short last_col(){ return _last_col;}
|
||
|
||
TMSPCheck_mask(TMSP_mask * main_mask);
|
||
TMSPCheck_mask(TMSP_mask * main_mask,const char * m,TSheet_field * s );
|
||
};
|
||
|
||
|
||
class TCRPCheck_mask : public TMSPCheck_mask
|
||
{
|
||
protected:
|
||
virtual void check_pos_range();
|
||
virtual int fill_mask(const bool show=TRUE);
|
||
virtual bool is_constraint(int row);
|
||
virtual bool is_article(int row);
|
||
virtual int find_constraint(int row);
|
||
public:
|
||
TCRPCheck_mask(TMSP_mask * main_mask);
|
||
};
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
TMSP_record& TMSP_record_array::operator[](int b)
|
||
{
|
||
CHECKD(b >= 0, "Invalid TMSP_record_array ", b);
|
||
TMSP_record* rec = (TMSP_record*)_buckets.objptr(b);
|
||
if (rec == NULL)
|
||
{
|
||
rec = new TMSP_record;
|
||
_buckets.add(rec, b);
|
||
}
|
||
return *rec;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TCapacita_prod::TCapacita_prod () :
|
||
_capacity(), _load()
|
||
{ }
|
||
|
||
TCapacita_prod::TCapacita_prod (const real& cap, const real& load) :
|
||
_capacity(cap), _load(load)
|
||
{ }
|
||
|
||
void TCapacita_prod::set(const real& cap, const real& load)
|
||
{ _capacity=(cap);_load=(load);}
|
||
|
||
void TCapacita_prod::copy (const TCapacita_prod & q)
|
||
{
|
||
_capacity=q._capacity; // Valore attuale
|
||
_load=q._load; // Valore attuale
|
||
}
|
||
|
||
int TCapacita_prod::compare(const TSortable& s) const
|
||
{
|
||
TCapacita_prod& c=(TCapacita_prod&)s;
|
||
real r=_capacity-c._capacity;
|
||
return r.sign();
|
||
}
|
||
|
||
|
||
TCRP_line::TCRP_line(const TString& codimp,const TString& codlin)
|
||
: _lineap(codlin),_on_sheet(FALSE)
|
||
{
|
||
if (!codlin.blank())
|
||
{
|
||
TTable tablnp("LNP");
|
||
tablnp.put("CODTAB",_lineap);
|
||
tablnp.read();
|
||
_desc = tablnp.get("S0");
|
||
_imp = tablnp.get("S6");
|
||
}
|
||
else
|
||
{
|
||
_imp = codimp ;
|
||
if (!codimp.blank())
|
||
{
|
||
TTable tabimp("IMP");
|
||
tabimp.put("CODTAB",_imp);
|
||
tabimp.read();
|
||
_desc = tabimp.get("S0");
|
||
}
|
||
else
|
||
{
|
||
_desc = "Totale ditta";
|
||
}
|
||
}
|
||
}
|
||
|
||
int TCRP_line::compare(const TSortable& s) const
|
||
{
|
||
const TCRP_line& c = (const TCRP_line&)s;
|
||
int cmp = _imp.compare(c._imp);
|
||
if (cmp == 0)
|
||
{
|
||
cmp = _lineap.compare(c._lineap);
|
||
}
|
||
return cmp;
|
||
}
|
||
|
||
// carica una riga di sheet con i dati dell'oggetto vincolo
|
||
void TCRP_line::fill_capacity_row(TToken_string& row, bool percent)
|
||
{
|
||
row.add(codimp(),F_CODIMPCRP -FIRST_FIELD);
|
||
row.add(codlin(),F_CODLINCRP -FIRST_FIELD);
|
||
|
||
row.add(percent ? "%": "ore",F_LUM -FIRST_FIELD);
|
||
|
||
real r;
|
||
for (int bu = last(); bu > 0; bu = pred(bu))
|
||
{
|
||
r=capacity(bu);
|
||
if (!r.is_zero())
|
||
row.add(percent ? "100" : r.string(), bu + F_LBUCKET0 -FIRST_FIELD); // buckets
|
||
else
|
||
row.add("", bu + F_LBUCKET0 -FIRST_FIELD);
|
||
}
|
||
}
|
||
void TCRP_line::fill_hcapacity_row(TToken_string& row, bool percent)
|
||
{
|
||
row.add(codimp(),F_CODIMPCRP -FIRST_FIELD);
|
||
row.add(codlin(),F_CODLINCRP -FIRST_FIELD);
|
||
|
||
row.add(percent ? "%": "ore",F_LUM -FIRST_FIELD);
|
||
|
||
real r;
|
||
for (int bu = last(); bu > 0; bu = pred(bu))
|
||
{
|
||
r=human_capacity(bu);
|
||
if (!r.is_zero())
|
||
row.add(percent ? "100" : r.string(), bu + F_LBUCKET0 -FIRST_FIELD); // buckets
|
||
else
|
||
row.add("", bu + F_LBUCKET0 -FIRST_FIELD);
|
||
}
|
||
}
|
||
|
||
// carica una riga di sheet con i dati dell'oggetto vincolo
|
||
void TCRP_line::fill_load_row(TToken_string& row, bool percent)
|
||
{
|
||
row.add(codimp(),F_CODIMPCRP -FIRST_FIELD);
|
||
row.add(codlin(),F_CODLINCRP -FIRST_FIELD);
|
||
|
||
row.add(percent ? "%": "ore",F_LUM -FIRST_FIELD);
|
||
|
||
real r;
|
||
for (int bu = last(); bu > 0; bu = pred(bu))
|
||
{
|
||
r=percent ? (capacity(bu).is_zero() ? ZERO : (100L * load(bu) / capacity(bu))) : load(bu) ;
|
||
row.add(r.string(), bu + F_LBUCKET0 -FIRST_FIELD); // buckets
|
||
}
|
||
}
|
||
void TCRP_line::fill_hload_row(TToken_string& row, bool percent)
|
||
{
|
||
row.add(codimp(),F_CODIMPCRP -FIRST_FIELD);
|
||
row.add(codlin(),F_CODLINCRP -FIRST_FIELD);
|
||
|
||
row.add(percent ? "%": "ore",F_LUM -FIRST_FIELD);
|
||
|
||
real r;
|
||
for (int bu = last(); bu > 0; bu = pred(bu))
|
||
{
|
||
r=percent ? (human_capacity(bu).is_zero() ? ZERO :(100L * human_load(bu) / human_capacity(bu))) : human_load(bu) ;
|
||
row.add(r.string(), bu + F_LBUCKET0 -FIRST_FIELD); // buckets
|
||
}
|
||
}
|
||
|
||
|
||
TCapacita_prod& TCRP_line::bucket(int n)
|
||
{
|
||
TCapacita_prod *o;
|
||
o=(TCapacita_prod *)_bucket.objptr(n);
|
||
if (o==NULL)
|
||
{
|
||
o=new TCapacita_prod();
|
||
_bucket.add(o,n);
|
||
}
|
||
return *o;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TCRP_lines ; carichi delle varie linee
|
||
///////////////////////////////////////////////////////////
|
||
|
||
|
||
TSortable* TCRP_lines::new_obj(const TToken_string& key) const
|
||
{
|
||
TString8 codimp, codlin;
|
||
key.get(0,codimp);
|
||
key.get(1,codlin);
|
||
return new TCRP_line(codimp, codlin);
|
||
}
|
||
|
||
TCRP_line* TCRP_lines::find(const TLinea_prod& linea_prod, const char * codart, long codcli, bool create)
|
||
{
|
||
/* _key=linea_prod.codimp();
|
||
_key.add(linea_prod.codice());
|
||
TSortable* s = create ? add_obj(_key) : find_obj(_key);
|
||
return (TCRP_line*)s;*/
|
||
return find(linea_prod.codimp(), linea_prod.codice(),codart, codcli, create);
|
||
}
|
||
|
||
TCRP_line* TCRP_lines::find(const char * codimp, const char * codlin, const char * codart, long codcli, bool create)
|
||
{
|
||
_key.add(codimp,0);
|
||
_key.add(codlin,1);
|
||
_key.add(codart,2); // articolo
|
||
_key.add(format("%ld",codcli),3); // cliente
|
||
TSortable* s = create ? add_obj(_key) : find_obj(_key);
|
||
return (TCRP_line*)s;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TMaster_code
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TMaster_code::TMaster_code(const char *code, const char *liv,const char *ummaster, const real &expr, const real &leadtime, const char *codimp, const char *codlin, const char *codmag)
|
||
: _code(code), _liv (liv), _um(ummaster), _expr(expr), _leadtime(leadtime),
|
||
_codimp(codimp), _codlin(codlin), _codmag(codmag)
|
||
{
|
||
}
|
||
TMaster_code::TMaster_code(const char *code, const char *liv,const char *ummaster, const real &expr, int leadtime, const char *codimp, const char *codlin, const char *codmag)
|
||
: _code(code), _liv (liv), _um(ummaster), _expr(expr), _leadtime(format("%d",leadtime)),
|
||
_codimp(codimp), _codlin(codlin), _codmag(codmag)
|
||
{
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TMSP_constraint
|
||
///////////////////////////////////////////////////////////
|
||
int TMSP_constraint::compare(const TSortable& s) const
|
||
{
|
||
const TMSP_constraint& c = (const TMSP_constraint&)s;
|
||
const long diff = _cliente - c._cliente;
|
||
int cmp = diff == 0L ? 0 : (diff > 0 ? +1 : -1);
|
||
if (cmp == 0)
|
||
{
|
||
cmp = _codart.compare(c._codart);
|
||
if (cmp == 0)
|
||
{
|
||
cmp = _giac.compare(c._giac);
|
||
if (cmp == 0)
|
||
{
|
||
cmp = _imp.compare(c._imp);
|
||
if (cmp == 0)
|
||
cmp = _mag.compare(c._mag);
|
||
}
|
||
}
|
||
}
|
||
return cmp;
|
||
}
|
||
|
||
|
||
// carica una riga di sheet con i dati dell'oggetto vincolo
|
||
void TMSP_constraint::fill_sheet_row(TToken_string& row, const TMSP_mask & m, bool codes_only)
|
||
{
|
||
const TCodgiac_livelli& livelli=m.livelli_giac();
|
||
TString tipocf(m.get(F_TIPOCF));
|
||
|
||
row.add(m.get_bool(F_NOCLI_IN) ? "" : tipocf,F_TIPOCF_SHEET-FIRST_FIELD);
|
||
|
||
row.add(format("%ld", cliente()),F_CLIENTE-FIRST_FIELD);
|
||
row.add(codice(),F_ARTICOLO-FIRST_FIELD);
|
||
row.add(" ",F_PRIORITA-FIRST_FIELD);
|
||
|
||
const TString& liv = livgiac();
|
||
for (int l = 1; l <= 4; l++)
|
||
{
|
||
if (livelli.enabled(l))
|
||
row.add(livelli.unpack_grpcode(liv,l),F_LIV1+l-1-FIRST_FIELD);
|
||
else
|
||
row.add(" ",F_LIV1+l-1-FIRST_FIELD);
|
||
}
|
||
|
||
row.add(desc(),F_DESCART-FIRST_FIELD);
|
||
row.add(codimp(),F_CODIMP-FIRST_FIELD);
|
||
row.add(codlin(),F_CODLIN-FIRST_FIELD);
|
||
|
||
TString8 str = _mag.left(3);
|
||
row.add(str, F_MAGAZZINO-FIRST_FIELD);
|
||
str = _mag.mid(3);
|
||
row.add(str,F_DEPOSITO-FIRST_FIELD);
|
||
|
||
const TCodice_um um;
|
||
const TQuantita qta_art(codice(), um, ZERO);
|
||
row.add(qta_art.um(),F_UM-FIRST_FIELD);
|
||
|
||
if (codes_only)
|
||
return;
|
||
real needs=ZERO;
|
||
const int last_buck= last();
|
||
for (int bu = 0; bu <= last_buck; bu ++)
|
||
{
|
||
needs=qta(bu);
|
||
row.add(needs.string(), bu*2+F_BUCKET0-FIRST_FIELD);
|
||
needs=price(bu);
|
||
row.add(needs.string(), bu*2+F_BUCKET0+1-FIRST_FIELD);
|
||
}
|
||
row.add(has_mastercodes() ? "M" : " ",F_MASTERCODE-FIRST_FIELD);
|
||
}
|
||
|
||
bool TMSP_constraint::riga(int buck, long& ndoc, int& nrig)
|
||
{
|
||
TMSP_record& b = _bucket_qta[buck];
|
||
ndoc = b._numdoc;
|
||
nrig = b._numrig;
|
||
return ndoc > 0L && nrig > 0;
|
||
}
|
||
|
||
void TMSP_constraint::set_riga(int buck, long ndoc, int nrig)
|
||
{
|
||
TMSP_record& b = _bucket_qta[buck];
|
||
b._numdoc = ndoc;
|
||
b._numrig = nrig;
|
||
}
|
||
|
||
bool TMSP_constraint::has_mastercodes() const
|
||
{
|
||
return _mastercodes.items()>0;
|
||
}
|
||
|
||
void TMSP_constraint::add_mastercode(TMaster_code *mc)
|
||
{
|
||
_mastercodes.add(mc);
|
||
}
|
||
|
||
TMaster_code *TMSP_constraint::get_mastercode(int i)
|
||
{
|
||
if (i>=0 && i < _mastercodes.items());
|
||
return (TMaster_code *) _mastercodes.objptr(i);
|
||
return NULL;
|
||
}
|
||
|
||
bool TMSP_constraint::has_upperlines() const
|
||
{
|
||
return _upperlines.items()>0;
|
||
}
|
||
|
||
void TMSP_constraint::add_upperline(TMSP_constraint& mc)
|
||
{
|
||
if (_upperlines.items()==0)
|
||
{
|
||
// aggiunge se stesso
|
||
TMSP_constraint * myself=_upperlines.find(cliente(), codice(), livgiac(),
|
||
codimp(),codlin(),codmag(),TRUE);
|
||
*myself=*this;
|
||
}
|
||
_upperlines.find(mc.cliente(), mc.codice(), mc.livgiac(),
|
||
mc.codimp(),mc.codlin(),mc.codmag(),TRUE);
|
||
}
|
||
|
||
TMSP_constraint* TMSP_constraint::get_upperline(TMSP_constraint& mc)
|
||
{
|
||
return _upperlines.find(mc.cliente(), mc.codice(), mc.livgiac(),
|
||
mc.codimp(),mc.codlin(),mc.codmag(),FALSE);
|
||
}
|
||
|
||
TMSP_constraint & TMSP_constraint::operator=(const TMSP_constraint & line)
|
||
{
|
||
_cliente=line.cliente();
|
||
_codart=line.codice();
|
||
_giac=line.livgiac();
|
||
_imp=line.codimp();
|
||
_lin=line.codlin();
|
||
_mag=line.codmag();
|
||
_on_sheet=_on_sheet;
|
||
_desc=line.desc();
|
||
_bucket_qta=line._bucket_qta;
|
||
return *this;
|
||
}
|
||
|
||
|
||
TMSP_constraint::TMSP_constraint(long cliente,
|
||
const TCodice_articolo& codart,
|
||
const TString& giac,
|
||
const TString& imp,
|
||
const TString& lin,
|
||
const TString& mag)
|
||
: _cliente(cliente), _codart(codart), _giac(giac),
|
||
_imp(imp), _lin(lin), _mag(mag),_on_sheet(FALSE)
|
||
{ }
|
||
|
||
TMSP_constraint::TMSP_constraint(TMSP_constraint & line)
|
||
: _cliente(line.cliente()), _codart(line.codice()), _giac(line.livgiac()),
|
||
_imp(line.codimp()), _lin(line.codlin()), _mag(line.codmag()), _on_sheet(FALSE),
|
||
_desc(line.desc())
|
||
{
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TMSP_constraints
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TSortable* TMSP_constraints::new_obj(const TToken_string& key) const
|
||
{
|
||
long cli; key.get(0, cli);
|
||
TCodice_articolo art; key.get(1, art); art.trim();
|
||
TString16 gia; key.get(2, gia); gia.trim();
|
||
TString8 imp; key.get(3, imp); imp.trim();
|
||
TString8 lin; key.get(4, lin); lin.trim();
|
||
TString8 mag; key.get(5, mag); mag.trim();
|
||
return new TMSP_constraint(cli, art, gia, imp, lin, mag);
|
||
}
|
||
|
||
TMSP_constraint* TMSP_constraints::find(long cliente,
|
||
const TString& art,
|
||
const TString& gia,
|
||
const TString& imp,
|
||
const TString& lin,
|
||
const TString& mag,
|
||
bool create)
|
||
{
|
||
_key.format("%ld", cliente);
|
||
_key.add(art);_key.trim();
|
||
_key.add(gia);_key.trim();
|
||
_key.add(imp);_key.trim();
|
||
_key.add(lin);_key.trim();
|
||
_key.add(mag);_key.trim();
|
||
TSortable* s = create ? add_obj(_key) : find_obj(_key);
|
||
TMSP_constraint *c=(TMSP_constraint*)s;
|
||
if (create)
|
||
{
|
||
if (c->desc().blank())
|
||
c->set_desc(cache().get(LF_ANAMAG,art).get("DESCR"));
|
||
}
|
||
return c;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////
|
||
// TMSP_line
|
||
///////////////////////////////////////////////////////////
|
||
|
||
|
||
void TMSP_line::fill_sheet_row(TToken_string& row, const TMSP_mask & m, bool codes_only)
|
||
{
|
||
TMSP_constraint::fill_sheet_row(row, m, codes_only);
|
||
row.add(m.get(F_TIPOCF),F_TIPOCF_SHEET-FIRST_FIELD);
|
||
}
|
||
|
||
TMSP_line::TMSP_line(long cliente, const TCodice_articolo& codart,
|
||
const TString& giac, const TString& imp,
|
||
const TString& lin, const TString& mag)
|
||
: TMSP_constraint(cliente, codart, giac, imp, lin,mag)
|
||
{ }
|
||
|
||
TMSP_line::TMSP_line(TMSP_constraint & cons)
|
||
:TMSP_constraint(cons)
|
||
{ }
|
||
TMSP_line::TMSP_line(TMSP_line & line)
|
||
:TMSP_constraint((TMSP_constraint &)line)
|
||
{
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TMSP_lines
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TSortable* TMSP_lines::new_obj(const TToken_string& key) const
|
||
{
|
||
long cliente; key.get(0, cliente);
|
||
TCodice_articolo art; key.get(1, art); art.trim();
|
||
TString gia; key.get(2, gia); gia.trim();
|
||
TString imp; key.get(3, imp); imp.trim();
|
||
TString lin; key.get(4, lin); lin.trim();
|
||
TString mag; key.get(5, mag); mag.trim();
|
||
return new TMSP_line(cliente, art, gia, imp, lin, mag);
|
||
}
|
||
|
||
TMSP_line* TMSP_lines::find(long cliente,
|
||
const TString& art,
|
||
const TString& gia, const TString& imp,
|
||
const TString& lin, const TString& mag,
|
||
bool create)
|
||
{
|
||
_key.format("%ld", cliente);
|
||
_key.add(art);
|
||
_key.add(gia);
|
||
_key.add(imp);
|
||
_key.add(lin);
|
||
_key.add(mag);
|
||
TSortable* s = create ? add_obj(_key) : find_obj(_key);
|
||
return (TMSP_line*)s;
|
||
}
|
||
|
||
TMSP_line* TMSP_lines::find(const TToken_string& row, TCodice_livelli & livelli ,bool create)
|
||
{
|
||
TString80 str,giaclev;
|
||
_key.cut(0);
|
||
|
||
for (int i = 0; i <= 11; i++)
|
||
{
|
||
row.get(i, str);
|
||
str.trim();
|
||
switch (i+FIRST_FIELD)
|
||
{
|
||
case F_LIV1:
|
||
case F_LIV2:
|
||
case F_LIV3:
|
||
livelli.pack_grpcode(giaclev, str, i+FIRST_FIELD-F_LIV1+1); break;
|
||
case F_LIV4:
|
||
livelli.pack_grpcode(giaclev, str, 4);
|
||
giaclev.trim();
|
||
_key.add(giaclev);
|
||
break; // Concatena i livelli
|
||
case F_MAGAZZINO:
|
||
_key.add(str);
|
||
row.get(i+1, str);
|
||
str.trim();
|
||
_key << str;
|
||
break; // Concatena magazzini e depositi
|
||
case F_CLIENTE:
|
||
if (str.blank()) str = "0";
|
||
case F_ARTICOLO:
|
||
case F_CODIMP:
|
||
case F_CODLIN:
|
||
_key.add(str); break; // Aggiungi normalmente
|
||
}
|
||
}
|
||
TSortable* s = create ? add_obj(_key) : find_obj(_key);
|
||
return (TMSP_line*)s;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TPlan_docs
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TPlan_docs : public TMRP_array
|
||
{
|
||
TString16 _num, _doc, _rig;
|
||
|
||
protected:
|
||
virtual TSortable* new_obj(const TToken_string& key) const;
|
||
|
||
public:
|
||
TDocumento& find(int anno, long num);
|
||
|
||
TRiga_documento& add_to_row(int anno, long num, int riga, const real& qta);
|
||
long flush(const TDate& data);
|
||
|
||
TPlan_docs(const char* num, const char* tip, const char* rig);
|
||
virtual ~TPlan_docs() { }
|
||
};
|
||
|
||
TSortable* TPlan_docs::new_obj(const TToken_string& key) const
|
||
{
|
||
int anno; key.get(0, anno);
|
||
long num; key.get(1, num);
|
||
|
||
TDocumento* doc = new TDocumento('D', anno, _num, num);
|
||
doc->head().put(DOC_TIPODOC, _doc);
|
||
return doc;
|
||
}
|
||
|
||
TDocumento& TPlan_docs::find(int anno, long num)
|
||
{
|
||
_key.format("%d|%ld", anno, num);
|
||
return *(TDocumento*)add_obj(_key);
|
||
}
|
||
|
||
TRiga_documento& TPlan_docs::add_to_row(int anno, long num, int riga, const real& qta)
|
||
{
|
||
TDocumento& doc = find(anno, num);
|
||
if (riga <= 0 || riga > doc.physical_rows())
|
||
{
|
||
TRiga_documento& r = doc.new_row(_rig);
|
||
riga = r.get_int(RDOC_NRIGA);
|
||
}
|
||
TRiga_documento& rdoc = doc[riga];
|
||
real val = rdoc.get(RDOC_QTA);
|
||
val += qta;
|
||
if (val <= ZERO)
|
||
rdoc.put(RDOC_QTA, ZERO);
|
||
else
|
||
rdoc.put(RDOC_QTA, val);
|
||
|
||
return rdoc;
|
||
}
|
||
|
||
long TPlan_docs::flush(const TDate& data)
|
||
{
|
||
const long tot = items();
|
||
if (tot > 0L)
|
||
{
|
||
TString msg;
|
||
msg << "Registrazione dei documenti di planning per il " << data;
|
||
TProgind pi(tot, msg, FALSE, TRUE);
|
||
TLocalisamfile lfdoc(LF_DOC);
|
||
for (long d = 0; d < tot; d++)
|
||
{
|
||
pi.addstatus(1);
|
||
TDocumento& doc = (TDocumento&)find_obj(d);
|
||
for (int r = doc.physical_rows(); r > 0; r--)
|
||
{
|
||
const TRiga_documento& riga = doc[r];
|
||
if (riga.is_articolo() && riga.quantita() == ZERO)
|
||
doc.destroy_row(r, TRUE);
|
||
}
|
||
if (doc.physical_rows())
|
||
doc.write(lfdoc);
|
||
else
|
||
doc.remove(lfdoc);
|
||
}
|
||
destroy();
|
||
}
|
||
return tot;
|
||
}
|
||
|
||
TPlan_docs::TPlan_docs(const char* num, const char* tip, const char* rig)
|
||
: _num(num), _doc(tip), _rig(rig)
|
||
{
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// ritorna se tutto OK
|
||
bool TRiga_articolo::find_block(const TSheet_field& sf, const int riga, int &first_row, int &last_row )
|
||
{
|
||
const int narticoli=sf.items();
|
||
if (narticoli<=riga)
|
||
return FALSE;
|
||
// Calcola l'indice c della riga coi vincoli
|
||
const int b1 = sf.cid2index(F_BUCKET1);
|
||
|
||
for (first_row = riga; first_row > 0; first_row--)
|
||
{
|
||
if (sf.cell_disabled(first_row, b1))
|
||
break;
|
||
}
|
||
if (first_row+1 < narticoli && sf.cell_disabled(first_row+1, b1)) first_row++;
|
||
// Calcola l'indice r dell'ultima riga articoli
|
||
last_row = riga;
|
||
if (last_row <= first_row) last_row=first_row+1;
|
||
for ( ; last_row < narticoli-1; last_row++)
|
||
{
|
||
if (sf.cell_disabled(last_row+1, b1))
|
||
break;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
int TRiga_articolo::order_compare( const TToken_string &r1 , const TToken_string &r2 , int level)
|
||
{
|
||
TString16 str0, str1;
|
||
int cmp = 0;
|
||
if (level>=0)
|
||
{
|
||
for (int i = 2; i <= level && cmp == 0; i++)
|
||
{
|
||
r1.get(i, str0);
|
||
r2.get(i, str1);
|
||
cmp=TRiga_articolo::compare_field(str0,str1,short(i+FIRST_FIELD));
|
||
}
|
||
} else {
|
||
// ordinamenti non standard
|
||
short f;
|
||
short fields_ACL[] = {F_PRIORITA, F_ARTICOLO, F_CLIENTE, F_SORTCODIMP, F_SORTCODLIN};
|
||
short fields_ALC[] = {F_PRIORITA, F_ARTICOLO, F_SORTCODIMP, F_SORTCODLIN, F_CLIENTE};
|
||
short fields_LAC[] = {F_PRIORITA, F_SORTCODIMP, F_SORTCODLIN, F_ARTICOLO, F_CLIENTE};
|
||
short fields_LCA[] = {F_PRIORITA, F_SORTCODIMP, F_SORTCODLIN, F_CLIENTE, F_ARTICOLO};
|
||
short fields_CLA[] = {F_PRIORITA, F_CLIENTE, F_SORTCODIMP, F_SORTCODLIN, F_ARTICOLO};
|
||
short fields_CAL[] = {F_PRIORITA, F_CLIENTE, F_ARTICOLO, F_SORTCODIMP, F_SORTCODLIN};
|
||
for (int i = 0; i < 5 && cmp == 0; i++)
|
||
{
|
||
switch (level)
|
||
{
|
||
case SORT_BY_CAL:
|
||
f=fields_CAL[i]; break;
|
||
case SORT_BY_CLA:
|
||
f=fields_CLA[i]; break;
|
||
case SORT_BY_LCA:
|
||
f=fields_LCA[i]; break;
|
||
case SORT_BY_LAC:
|
||
f=fields_LAC[i]; break;
|
||
case SORT_BY_ACL:
|
||
f=fields_ACL[i]; break;
|
||
case SORT_BY_ALC:
|
||
f=fields_ALC[i]; break;
|
||
default:
|
||
NFCHECK("Ordinamento sconosciuto");
|
||
break;
|
||
}
|
||
r1.get(f-FIRST_FIELD, str0);
|
||
r2.get(f-FIRST_FIELD, str1);
|
||
cmp=TRiga_articolo::compare_field(str0,str1,f);
|
||
}
|
||
}
|
||
return cmp;
|
||
}
|
||
|
||
|
||
// aggiunge li codici di linea/impianto se non presenti usando i default sulle lavorazioni critiche
|
||
// cio' permette di ordinare per impianto anche le linee di ordine che non hanno solitamente
|
||
// questa indicazione ma solo il codice articolo
|
||
void complete_codlinea(TToken_string &r2, bool ignore_imp)
|
||
{
|
||
static TDistinta_tree *_dist_tree=NULL;
|
||
|
||
TString8 swp;
|
||
r2.get(F_SORTCODLIN-FIRST_FIELD,swp);
|
||
if (swp.blank())
|
||
{
|
||
r2.get(F_CODLIN-FIRST_FIELD,swp);
|
||
if (swp.blank())
|
||
{
|
||
if (_dist_tree==NULL)
|
||
_dist_tree= new TDistinta_tree();
|
||
if (_dist_tree->set_root(r2.get(F_ARTICOLO-FIRST_FIELD)))
|
||
{
|
||
TString codimp(r2.get(F_CODIMP-FIRST_FIELD));
|
||
TArray labors;
|
||
TRiga_esplosione * l=_dist_tree->first_critical_labor(labors);
|
||
if (l)
|
||
{
|
||
TLavorazione *curr_labor=TDistinta_tree::find_labor(l);
|
||
CHECK(curr_labor,"Lavorazione non trovata");
|
||
for (int nlinea=0; nlinea <curr_labor->linee_standard(); nlinea ++)
|
||
{
|
||
const TRectype &linea_prod= cache().get("LNP",curr_labor->cod_linea(nlinea));
|
||
if ( ignore_imp || codimp.blank() || codimp==linea_prod.get("S6"))
|
||
{
|
||
r2.add(linea_prod.get("CODTAB"), F_SORTCODLIN-FIRST_FIELD);
|
||
r2.add(linea_prod.get("S6"), F_SORTCODIMP-FIRST_FIELD);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
r2.add('\255', F_SORTCODLIN-FIRST_FIELD);
|
||
}
|
||
else
|
||
{
|
||
r2.add(swp, F_SORTCODLIN-FIRST_FIELD);
|
||
r2.get(F_CODLIN-FIRST_FIELD,swp);
|
||
r2.add(swp, F_SORTCODIMP-FIRST_FIELD);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
int TRiga_articolo::order_compare(TSheet_field & s, int i1, int i2, int level)
|
||
{
|
||
TMask &m=s.mask();
|
||
const bool ascending=!m.get_bool(F_MSP_SORT_ORDER);
|
||
int first1, first2, last1, last2;
|
||
|
||
if (find_block(s, i1, first1, last1 )) first1--;
|
||
if (find_block(s, i2, first2, last2 )) first2--;
|
||
|
||
const TToken_string &r1 = s.row(i1);
|
||
const TToken_string &r2 = s.row(i2);
|
||
if (s.cell_enabled(i1, F_BUCKET1-FIRST_FIELD) && s.cell_enabled(i2, F_BUCKET1-FIRST_FIELD) )
|
||
{
|
||
// confronto tra righe dello stesso vincolo
|
||
if (first1 == first2 )
|
||
return order_compare( r1 , r2 , level) * (ascending ? 1 : -1);
|
||
} else {
|
||
if (first1 != first2 && first1==i1 && first2==i2 )
|
||
{
|
||
TToken_string &blockr1=(TToken_string &)r1;
|
||
TToken_string &blockr2=(TToken_string &)r2;;
|
||
complete_codlinea(blockr1, m.get_bool(F_NOIMP_IN));
|
||
complete_codlinea(blockr2, m.get_bool(F_NOIMP_IN));
|
||
// confronto tra blocchi ed eventuale swap direttamente qui nella compare
|
||
int cmp = order_compare(blockr1 , blockr2 , level) * (ascending ? 1 : -1);
|
||
if (cmp > 0)
|
||
{
|
||
for (int bubble=first2; bubble<=last2; bubble++)
|
||
{
|
||
for (int r=bubble; r>bubble+first1-first2; r--)
|
||
{
|
||
s.swap_rows(r, r-1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int TRiga_articolo::order_compareCAL(TSheet_field & s, int i1, int i2)
|
||
{ return TRiga_articolo::order_compare(s, i1, i2,SORT_BY_CAL);}
|
||
int TRiga_articolo::order_compareCLA(TSheet_field & s, int i1, int i2)
|
||
{ return TRiga_articolo::order_compare(s, i1, i2,SORT_BY_CLA);}
|
||
int TRiga_articolo::order_compareALC(TSheet_field & s, int i1, int i2)
|
||
{ return TRiga_articolo::order_compare(s, i1, i2,SORT_BY_ALC);}
|
||
int TRiga_articolo::order_compareACL(TSheet_field & s, int i1, int i2)
|
||
{ return TRiga_articolo::order_compare(s, i1, i2,SORT_BY_ACL);}
|
||
int TRiga_articolo::order_compareLAC(TSheet_field & s, int i1, int i2)
|
||
{ return TRiga_articolo::order_compare(s, i1, i2,SORT_BY_LAC);}
|
||
int TRiga_articolo::order_compareLCA(TSheet_field & s, int i1, int i2)
|
||
{ return TRiga_articolo::order_compare(s, i1, i2,SORT_BY_LCA);}
|
||
|
||
int TRiga_articolo::compare_field(TString &str0, TString &str1,short field_no)
|
||
{
|
||
int cmp;
|
||
switch (field_no)
|
||
{
|
||
case F_CLIENTE:
|
||
{
|
||
const long f0 = atol(str0);
|
||
const long f1 = atol(str1);
|
||
cmp = f0 == f1 ? 0 : (f0 > f1 ? +1 : -1);
|
||
}
|
||
break;
|
||
case F_PRIORITA:
|
||
cmp = -str0.compare(str1);
|
||
break;
|
||
default:
|
||
cmp = str0.compare(str1);
|
||
break;
|
||
}
|
||
return cmp;
|
||
}
|
||
|
||
TRiga_articolo& TRiga_articolo::operator=(TToken_string& r)
|
||
{
|
||
this->TToken_string::operator=(r);
|
||
return *this;
|
||
}
|
||
|
||
TRiga_articolo& TRiga_articolo::operator+=(TRiga_articolo& r)
|
||
{
|
||
NFCHECK( "Can't add incompatible order line");
|
||
return *this;
|
||
}
|
||
|
||
TRiga_articolo::TRiga_articolo(const TMSP_constraint& line)
|
||
: TToken_string(128)
|
||
{
|
||
format("%ld", line.cliente());
|
||
add(line.codice(),F_CLIENTE-FIRST_FIELD);
|
||
add(" ",F_PRIORITA-FIRST_FIELD);
|
||
|
||
const TString& liv = line.livgiac();
|
||
for (int l = 1; l <= 4; l++)
|
||
{
|
||
if (livelli_giac().enabled(l))
|
||
add(livelli_giac().unpack_grpcode(liv,l),F_LIV1+l-1-FIRST_FIELD);
|
||
else
|
||
add(" ",F_LIV1+l-1-FIRST_FIELD);
|
||
}
|
||
|
||
add(line.desc(),F_DESCART-FIRST_FIELD);
|
||
add(line.codimp(),F_CODIMP-FIRST_FIELD);
|
||
add(line.codlin(),F_CODLIN-FIRST_FIELD);
|
||
|
||
TString8 str = line.codmag().left(3);
|
||
add(str, F_MAGAZZINO-FIRST_FIELD);
|
||
str = line.codmag().mid(3);
|
||
add(str, F_DEPOSITO-FIRST_FIELD);
|
||
|
||
const TCodice_um um;
|
||
const TQuantita qta_art(line.codice(), um, ZERO);
|
||
add(qta_art.um(),F_UM-FIRST_FIELD);
|
||
|
||
TMSP_constraint& lin=(TMSP_constraint& )line;
|
||
const int last_buck= line.last();
|
||
for (int bu = 0; bu <= last_buck; bu ++)
|
||
{
|
||
add(lin.qta(bu).string(), bu*2+F_BUCKET0-FIRST_FIELD);
|
||
}
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Maschera principale
|
||
///////////////////////////////////////////////////////////
|
||
|
||
|
||
// Arrotonda la data al bucket e ne restituisce il numero (data iniziale==bucket 0)
|
||
int TMSP_mask::round_date(TDate& date, bool up) const
|
||
{
|
||
// Dimensione del bucke in giorni
|
||
int bucket_size = days_per_bucket();
|
||
|
||
// Riporta la data al primo lunedi prima dell'inizio
|
||
TDate inizio = get(F_DADATA);
|
||
const int wday = inizio.wday();
|
||
if (wday > 1) inizio -= wday-1;
|
||
|
||
// Calcola il bucket di appartenenza
|
||
const int days = int(date - inizio);
|
||
const int bucket = days / bucket_size;
|
||
|
||
if (up) // Arrotonda alla fine del bucket
|
||
date = inizio + long((bucket+1 )* bucket_size - 1);
|
||
else // Arrotonda all'inizio del bucket
|
||
date = inizio + long(bucket * bucket_size);
|
||
|
||
return bucket;
|
||
}
|
||
|
||
void TMSP_mask::round_field(TMask_field& fld, bool up) const
|
||
{
|
||
TDate date = fld.get();
|
||
if (date.ok())
|
||
{
|
||
round_date(date, up);
|
||
fld.set(date);
|
||
}
|
||
}
|
||
|
||
int TMSP_mask::test_codnum(const TCodice_numerazione& num) const
|
||
{
|
||
int r=0;
|
||
for (int s = 2; s > 0; s--)
|
||
{
|
||
const short id = s == 2 ? F_NUM_PLA : F_NUM_ORC;
|
||
TString_array& nums = sfield(id).rows_array();
|
||
for (int i = nums.items()-1; i >= 0; i--)
|
||
{
|
||
const char* t = nums.row(i).get(0);
|
||
if (num.codice() == t)
|
||
{
|
||
r|=s; break;
|
||
}
|
||
}
|
||
}
|
||
return r;
|
||
}
|
||
|
||
bool TMSP_mask::test_tipodoc_num(const TSheet_field &sheet_num ,const TSheet_field &sheet_type)
|
||
{
|
||
TString16 tipo;
|
||
TString_array& nums = sheet_num.rows_array();
|
||
TString_array& types = sheet_type.rows_array();
|
||
for (int j = types.items()-1; j >= 0; j--)
|
||
{
|
||
bool ok=FALSE;
|
||
tipo = types.row(j).get(0) ;
|
||
const char * cazzoinculo=(const char * )tipo;
|
||
for (int i = nums.items()-1; i >= 0; i--)
|
||
{
|
||
TCodice_numerazione num(nums.row(i).get(0));
|
||
for (int n = num.ntipi_doc()-1;n >= 0; n--)
|
||
{
|
||
const char* t = num.tipo_doc(n);
|
||
if (tipo == t)
|
||
ok = TRUE;
|
||
}
|
||
}
|
||
if (!ok)
|
||
return error_box("Il tipo '%s' non appartiene a nessuna delle numerazioni scelte",(const char * )tipo);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
bool TMSP_mask::test_status(const TRectype& doc, int s) const
|
||
{
|
||
const short id = (s & 2) ? F_TIPI_PLA : F_TIPI_ORC;
|
||
TSheet_field& sf = sfield(id);
|
||
const int idfr = sf.cid2index(F_DASTATO);
|
||
const int idto = sf.cid2index(F_ASTATO);
|
||
|
||
const TString16 tipodoc = doc.get(DOC_TIPODOC);
|
||
const int statodoc = doc.get_int(DOC_STATO);
|
||
bool yes = FALSE;
|
||
|
||
TString_array& a = sf.rows_array();
|
||
for (int i = a.items()-1; i >= 0 && !yes; i--)
|
||
{
|
||
TToken_string& riga = a.row(i);
|
||
const char* t = riga.get(0);
|
||
if (tipodoc == t)
|
||
{
|
||
const int state_fr = riga.get_int(idfr);
|
||
const int state_to = riga.get_int(idto);
|
||
yes = statodoc >= state_fr && statodoc <= state_to;
|
||
}
|
||
}
|
||
|
||
return yes;
|
||
}
|
||
|
||
// Metodo standard per contare gli elementi di una tabella
|
||
// in attesa di tempi migliori per le librerie
|
||
/*
|
||
static long table_items(const char* tab)
|
||
{
|
||
TRelation tabrel(tab);
|
||
TCursor tabcur (&tabrel);
|
||
long tot = tabcur.items();
|
||
return tot;
|
||
}
|
||
*/
|
||
|
||
bool TMSP_mask::carica_documenti()
|
||
{
|
||
const bool ignore_mag=get_bool(F_NOMAG_IN);
|
||
const bool ignore_imp=get_bool(F_NOIMP_IN);
|
||
const bool ignore_lin=get_bool(F_NOLIN_IN);
|
||
const bool ignore_cli=get_bool(F_NOCLI_IN);
|
||
const bool ignore_allcli=get_bool(F_NOCLI_OUT);
|
||
const bool is_master_sched = get_bool(F_MSCHEDULEPLAN);
|
||
const bool two_level = get_bool(F_2LEVEL_MSP);
|
||
|
||
|
||
TDate date_fr = get(F_DADATA);
|
||
const int bucket_fr = round_date(date_fr, FALSE);
|
||
TDate date_to = get(F_ADATA);
|
||
const int bucket_to = round_date(date_to, TRUE);
|
||
|
||
const int year_fr = date_fr.year();
|
||
const int year_to = date_to.year();
|
||
|
||
const TString& numplan = get(F_NUM_PLAN);
|
||
|
||
TTable num("%NUM");
|
||
TCodice_numerazione cod;
|
||
|
||
TRelation rel(LF_DOC);
|
||
TCursor cur(&rel);
|
||
const TRectype& curr = cur.curr();
|
||
TRectype filter_fr(curr), filter_to(curr);
|
||
|
||
_articles.destroy();
|
||
_constraints.destroy();
|
||
_proposed_articles.destroy();
|
||
|
||
// Scandisce tutte le numerazioni considerando solo quelle
|
||
// contenenti i tipi documento specificati nella maschera
|
||
for (int err = cod.first(num); err == NOERR; err = cod.next(num))
|
||
{
|
||
const int tn = test_codnum(cod);
|
||
if (tn)
|
||
{
|
||
// Filtra il cursore in modo da limitarlo alla numerazione
|
||
// corrente ed agli anni specificati dalle due date limite
|
||
filter_fr.put(DOC_PROVV, "D");
|
||
filter_fr.put(DOC_CODNUM, cod.get("CODTAB"));
|
||
filter_fr.put(DOC_ANNO, year_fr);
|
||
filter_to.put(DOC_PROVV, "D");
|
||
filter_to.put(DOC_CODNUM, cod.get("CODTAB"));
|
||
filter_to.put(DOC_ANNO, year_to);
|
||
cur.setregion(filter_fr, filter_to);
|
||
TString cfilter;
|
||
cfilter << DOC_CODNUM << "==" << '"' << cod.get("CODTAB")<< '"';
|
||
cur.setfilter(cfilter);
|
||
const long items = cur.items();
|
||
cur.freeze(TRUE);
|
||
|
||
// Scandisce i documenti inevasi e considera solo
|
||
// quelli con uno stato nel range corretto
|
||
TString msg;
|
||
msg.format("Caricamento documenti %s (numerazione '%s')",tn & 1 ? "ordine":"di planning",(const char *)cod.codice());
|
||
TProgind pi(items,msg , TRUE, TRUE);
|
||
for (cur = 0; cur.pos() < items; ++cur)
|
||
{
|
||
pi.addstatus(1);
|
||
if (pi.iscancelled())
|
||
return FALSE;
|
||
const bool evaso = curr.get_bool(DOC_DOCEVASO);
|
||
if (evaso)
|
||
continue;
|
||
|
||
// Calcola data di consegna per righe che non ce l'hanno
|
||
TDate datacons = curr.get(DOC_DATACONS);
|
||
if (!datacons.ok())
|
||
datacons = curr.get(DOC_DATADOC);
|
||
|
||
if (!test_status(curr, tn))
|
||
continue;
|
||
|
||
// Scandisce le righe articolo e memorizza
|
||
// le quantita' richieste
|
||
TDocumento doc(cur.curr());
|
||
for (int r = doc.physical_rows(); r > 0; r--)
|
||
{
|
||
// Seleziona le righe articolo non ancora evase
|
||
const TRiga_documento& riga = doc[r];
|
||
if (riga.is_articolo())
|
||
{
|
||
const real qta = riga.qtaresidua();
|
||
if (qta > ZERO)
|
||
{
|
||
const TCodice_articolo art = riga.get(RDOC_CODARTMAG);
|
||
const TString16 liv = _livelli.enabled() ? riga.get(RDOC_LIVELLO) : "";
|
||
const long cli = (ignore_cli && (tn & 1)) ||ignore_allcli ? 0 : doc.get_long(DOC_CODCF) ;
|
||
const TString16 mag = ignore_mag && (tn & 1) ? "" : riga.get(RDOC_CODMAG);
|
||
const TString16 imp = ignore_imp && (tn & 1) ? "" : riga.get(RDOC_IMPIANTO);
|
||
const TString16 lin = ignore_lin && (tn & 1) ? "" : riga.get(RDOC_LINEA);
|
||
const TCodice_um um = riga.get(RDOC_UMQTA);
|
||
TQuantita q(art, um, qta);
|
||
q.convert2umbase();
|
||
|
||
TDate consegna = riga.get(RDOC_DATACONS);
|
||
if (!consegna.ok())
|
||
consegna = datacons;
|
||
int buck = round_date(consegna) - bucket_fr + 1;
|
||
if (buck < 0) buck = 0; else
|
||
if (buck > LAST_BUCKET) buck = LAST_BUCKET;
|
||
|
||
TMSP_constraint* line;
|
||
if (tn & 1)
|
||
{
|
||
line = _constraints.find(cli, art, liv, imp, lin, mag, TRUE);
|
||
if (two_level && !distinta_master(art))
|
||
{
|
||
TString master, ummaster, livmaster,impmaster(imp), linmaster(lin),magmaster;
|
||
real expr;
|
||
if (!line->has_mastercodes())
|
||
{
|
||
int i=0;
|
||
while ((i=find_distinta_master(art, master, livmaster, ummaster, expr, impmaster, linmaster, magmaster,i)+1) >0)
|
||
{
|
||
TMSP_constraint*masterline=_constraints.find(cli, master , livmaster, imp, lin, mag, TRUE);
|
||
masterline->add_upperline(*line);
|
||
line->add_mastercode(new TMaster_code (master, livmaster, ummaster, expr, cache().get(LF_ANAMAG,master).get_real(ANAMAG_GIORNIRIOR), imp, lin, mag));
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
line = _articles. find(cli, art, liv, imp, lin, mag, TRUE);
|
||
}
|
||
|
||
if (line->desc().empty())
|
||
line->set_desc(riga.get(RDOC_DESCR));
|
||
|
||
if (buck > 0 && buck < LAST_BUCKET && cod.codice() == numplan)
|
||
{
|
||
long numdoc;
|
||
int numrig;
|
||
if (!line->riga(buck, numdoc, numrig))
|
||
{
|
||
numdoc = riga.get_long(RDOC_NDOC);
|
||
numrig = riga.get_int(RDOC_NRIGA);
|
||
line->set_riga(buck, numdoc, numrig);// memorizza la provenienza dal doc
|
||
}
|
||
}
|
||
|
||
line->qta(buck) += q.val();
|
||
real price;
|
||
find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
|
||
get(F_TIPOCF), cli, art,
|
||
line->qta(buck), price);
|
||
line->price(buck) = price;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
cur.freeze(FALSE);
|
||
}
|
||
}
|
||
|
||
return _constraints.items() > 0L || _articles.items() > 0L;
|
||
}
|
||
|
||
// cerca il vincolo "migliore" secondo la logica :
|
||
// - stesso magazzino , impianto e linea
|
||
// - stesso magazzino e impianto
|
||
// - stesso magazzino
|
||
// - stesso impianto e linea
|
||
// - stessa linea
|
||
TMSP_constraint* TMSP_mask::find_constraint(const TMSP_line& l, bool force_insert)
|
||
{
|
||
const bool ignore_mag=get_bool(F_NOMAG_IN);
|
||
const bool ignore_imp=get_bool(F_NOIMP_IN);
|
||
const bool ignore_lin=get_bool(F_NOLIN_IN);
|
||
const bool ignore_cli=get_bool(F_NOCLI_IN);
|
||
|
||
TString16 codmag=ignore_mag ? "" : l.codmag();
|
||
TString16 codimp=ignore_imp ? "" : l.codimp();
|
||
TString16 codlin=ignore_lin ? "" : l.codlin();
|
||
long codcli=ignore_cli ? 0L : l.cliente() ;
|
||
// se il magazzino o l'impianto non e' indicato sul vincolo cerca di individuarlo
|
||
// in base ai default di linea/impianto
|
||
if (codimp.blank())
|
||
{
|
||
if (!codlin.blank())
|
||
{
|
||
TLinea_prod &linea_prod=*::get_linea(codlin);
|
||
codimp=linea_prod.codimp();
|
||
}
|
||
}
|
||
if (codmag.blank())
|
||
{
|
||
if (!codlin.blank())
|
||
{
|
||
TLinea_prod &linea_prod=*::get_linea(codlin);
|
||
codmag=linea_prod.codmagdep();
|
||
} else
|
||
if (!codimp.blank())
|
||
{
|
||
TImpianto &impianto=*::get_impianto(codimp);
|
||
codmag=impianto.codmagdep();
|
||
}
|
||
}
|
||
|
||
// cerca il vincolo con - stesso magazzino , impianto e linea
|
||
TMSP_constraint* c = _constraints.find(codcli, l.codice(), l.livgiac(), codimp, codlin, codmag);
|
||
if (c == NULL )
|
||
{
|
||
if (!codmag.blank())
|
||
{
|
||
// cerca il vincolo con - stesso magazzino e impianto
|
||
c =_constraints.find(codcli, l.codice(), l.livgiac(), codimp, "", codmag);
|
||
if (c == NULL)
|
||
// cerca il vincolo con - stesso magazzino
|
||
c =_constraints.find(codcli, l.codice(), l.livgiac(), "", "", codmag);
|
||
}
|
||
if (c == NULL)
|
||
// cerca il vincolo con - stesso impianto e linea
|
||
c =_constraints.find(codcli, l.codice(), l.livgiac(), codimp, codlin, "");
|
||
if (c == NULL)
|
||
// cerca il vincolo con - stessa impianto
|
||
c =_constraints.find(codcli, l.codice(), l.livgiac(), codimp, "" , "");
|
||
}
|
||
if (c == NULL && force_insert)
|
||
{
|
||
// MA STO VINCOLO MANCA PROPRIO! ALLORA LO INSERISCO
|
||
c = _constraints.find(codcli, l.codice(), l.livgiac(), codimp, codlin, codmag, TRUE);
|
||
if (c->desc().blank())
|
||
c->set_desc(l.desc());
|
||
}
|
||
return c;
|
||
}
|
||
|
||
int TMSP_mask::find_constr_row(const TMSP_constraint& c)
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
const int maxart=sf.items();
|
||
for (int r=0; r <maxart; r++)
|
||
{
|
||
TToken_string &row=sf.row(r);
|
||
TString16 liv;
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV1)),1);
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV2)),2);
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV3)),3);
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV4)),4);
|
||
TString16 imp(row.get(sf.cid2index(F_CODIMP)));imp.trim();
|
||
TString16 lin(row.get(sf.cid2index(F_CODLIN)));lin.trim();
|
||
TString16 mag;
|
||
add_magcode(mag, row.get(sf.cid2index(F_MAGAZZINO)));
|
||
add_depcode(mag, row.get(sf.cid2index(F_DEPOSITO )));
|
||
if (sf.cell_disabled(r, sf.cid2index(F_BUCKET1)))
|
||
{
|
||
if (c.cliente()==row.get_long(sf.cid2index(F_CLIENTE)) &&
|
||
c.codice() == row.get(sf.cid2index(F_ARTICOLO)) &&
|
||
c.livgiac() == liv&&
|
||
c.codimp()== imp &&
|
||
c.codlin()==lin &&
|
||
c.codmag()==mag )
|
||
return r;
|
||
else
|
||
r+=2;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
|
||
void TMSP_mask::fill_sheet()
|
||
{
|
||
//TSheet_field& su = sfield(F_TESTE);
|
||
TSheet_field& sl = sfield(F_LINEE);
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
|
||
sf.enable_column(F_CLIENTE,!get_bool(F_NOCLI_OUT));
|
||
sf.set_column_header(F_CLIENTE-FIRST_FIELD,*get(F_TIPOCF)=='C' ? "Cliente" : "Fornitore");
|
||
|
||
const TDate date_to = get(F_ADATA);
|
||
const int bucket_size = days_per_bucket();
|
||
TDate d = get(F_DADATA);
|
||
TString16 str;
|
||
for (int b = 0; b <= LAST_BUCKET; b++)
|
||
{
|
||
if (b > 0 && b < LAST_BUCKET)
|
||
{
|
||
sf.enable_column(F_BUCKET0 + b*2, d < date_to);
|
||
sf.enable_column(F_BUCKET0 + b*2+1, d < date_to);
|
||
sl.enable_column(F_LBUCKET0 + b, d < date_to);
|
||
//su.enable_column(F_LBUCKET0 + b, d < date_to);
|
||
}
|
||
str = d.string();
|
||
switch(b)
|
||
{
|
||
case 0: str.insert("< "); break;
|
||
//case 9: /* Nothing!! */ ; break;
|
||
case LAST_BUCKET: str.insert(">= "); break;
|
||
default: d += bucket_size; break;
|
||
}
|
||
sf.set_column_header(F_BUCKET0 + b*2, str);
|
||
sf.set_column_header(F_BUCKET0 + b*2 +1, str);
|
||
sl.set_column_header(F_LBUCKET0 + b, str);
|
||
//su.set_column_header(F_LBUCKET0 + b, str);
|
||
}
|
||
|
||
TMSP_constraint* last_constraint = NULL;
|
||
|
||
const long totart = _articles.sort();
|
||
TWait_cursor hourglass;
|
||
for (long i = 0; i < totart; i++)
|
||
{
|
||
TMSP_line& line = _articles[i];
|
||
TMSP_constraint* curr_constraint = find_constraint(line,TRUE);
|
||
if (last_constraint != curr_constraint)
|
||
{
|
||
// aggiunge la linea di vincolo
|
||
TToken_string& consrow = sf.row(-1);
|
||
curr_constraint->fill_sheet_row(consrow, *this);
|
||
consrow.add("** Ordini ",F_DESCART-FIRST_FIELD);
|
||
sf.disable_cell(sf.items()-1, -1);
|
||
// aggiunge la linea della giacenza prog
|
||
TToken_string& rowgiac = sf.row(-1);
|
||
copy_sheet_row(rowgiac,consrow);
|
||
rowgiac.add("** Giacenza teorica",F_DESCART-FIRST_FIELD);
|
||
sf.disable_cell(sf.items()-1, -1);
|
||
last_constraint = curr_constraint;
|
||
curr_constraint->set_on_sheet();
|
||
}
|
||
TToken_string& row = sf.row(-1);
|
||
line.fill_sheet_row(row, *this);
|
||
}
|
||
const long totcon = _constraints.sort();
|
||
for (long j = 0; j < totcon; j++)
|
||
{
|
||
TMSP_constraint& cons = _constraints[j];
|
||
if (!cons.is_on_sheet())
|
||
{
|
||
// aggiunge le tre linee
|
||
TToken_string& row = sf.row(-1);
|
||
cons.fill_sheet_row(row, *this);
|
||
cons.set_on_sheet();
|
||
sf.disable_cell(sf.items()-1, -1);
|
||
//linea della giacenza prog
|
||
TToken_string& rowgiac = sf.row(-1);
|
||
copy_sheet_row(rowgiac,row);
|
||
sf.disable_cell(sf.items()-1, -1);
|
||
//linea articolo (vuota)
|
||
TMSP_line line(cons);
|
||
line.fill_sheet_row(sf.row(-1), *this);
|
||
rowgiac.add("** Giacenza teorica",F_DESCART-FIRST_FIELD);
|
||
row.add("** Ordini ",F_DESCART-FIRST_FIELD);
|
||
}
|
||
}
|
||
for (int r = sf.items()-1; r >0 ; )
|
||
{
|
||
// init bucket 0
|
||
TCodice_articolo codart(sf.cell(r,sf.cid2index(F_ARTICOLO)));
|
||
if (codart.blank())
|
||
r = r-2;
|
||
TArticolo_giacenza art(codart);
|
||
r=init_bucket0(art, r);
|
||
}
|
||
sf.force_update();
|
||
}
|
||
|
||
bool TMSP_mask::distinta_master(const char *code)
|
||
{
|
||
const TRectype &rec=cache().get(LF_DIST,code);
|
||
if (rec.empty()) return FALSE;
|
||
return rec.get_bool("MASTER");
|
||
}
|
||
|
||
int TMSP_mask::find_distinta_master(const char * code, TString & master,TString & livmaster,TString & um, real & expr, TString & imp,TString & lin,TString & magdep, int fromindex)
|
||
{
|
||
TArray sons;
|
||
if (_dist_tree.set_root(code))
|
||
{
|
||
_dist_tree.explode(sons, FALSE, RAGGR_EXP_NONE, 1);
|
||
TRiga_esplosione* riga;
|
||
while (riga=(TRiga_esplosione* )sons.objptr(fromindex))
|
||
{
|
||
if (distinta_master(riga->articolo()))
|
||
{
|
||
master=riga->articolo();
|
||
livmaster=riga->livello();
|
||
um =riga->um();
|
||
expr =riga->val();
|
||
return fromindex;
|
||
}
|
||
fromindex=sons.succ(fromindex);
|
||
}
|
||
}
|
||
master="";
|
||
return -1;
|
||
}
|
||
|
||
bool TMSP_mask::insert_propose(bool verbose)
|
||
{
|
||
if (_proposed_articles.items()<=0L)
|
||
{
|
||
if (verbose)
|
||
message_box("Nessuna nuova proposta");
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
add_or_sub_propose(+1);
|
||
const long new_rows=_proposed_articles.items();
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
int firstbuck;
|
||
TDate firstdate(get_date(F_ADATA));
|
||
for (long new_row=0; new_row < new_rows; new_row++)
|
||
{
|
||
const TDate & d=_proposed_articles[new_row].time(0).date() ;
|
||
firstdate=min(firstdate,d);
|
||
}
|
||
firstbuck=int((firstdate- get_date(F_DADATA))/days_per_bucket())+1;
|
||
if (verbose)
|
||
message_box("Quantita' proposte a partire dal %s (colonna %0d)", (const char *)firstdate.string(), int(firstbuck));
|
||
}
|
||
return TRUE;
|
||
}
|
||
bool TMSP_mask::remove_propose(bool verbose)
|
||
{
|
||
if (_proposed_articles.items()<=0L)
|
||
{
|
||
if (verbose)
|
||
message_box("Nessuna proposta da annullare");
|
||
return FALSE;
|
||
}
|
||
add_or_sub_propose(-1);
|
||
_proposed_articles.destroy();
|
||
return TRUE;
|
||
}
|
||
|
||
void TMSP_mask::add_or_sub_propose(char sign)
|
||
{
|
||
const long new_rows=_proposed_articles.items();
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
for (long new_row=0; new_row < new_rows; new_row++)
|
||
{
|
||
const TMRP_line & a=_proposed_articles[new_row];
|
||
TMSP_line line(a.codcli(), a.codice(), a.livgiac(), a.codimp(), a.codlin(), a.codmag());
|
||
|
||
bool line_found=FALSE;
|
||
TMSP_constraint* constraint= find_constraint(line,FALSE);
|
||
if (constraint==NULL)
|
||
{
|
||
CHECK( sign>0, "Impossibile trovare il vincolo da soddisfare...");
|
||
// aggiunge le tre linee
|
||
constraint=new TMSP_constraint(line);
|
||
TToken_string& row = sf.row(-1);
|
||
constraint->fill_sheet_row(row, *this);
|
||
constraint->set_on_sheet();
|
||
sf.disable_cell(sf.items()-1, -1);
|
||
//linea della giacenza prog
|
||
TToken_string& rowgiac = sf.row(-1);
|
||
copy_sheet_row(rowgiac,row);
|
||
sf.disable_cell(sf.items()-1, -1);
|
||
//linea articolo (vuota)
|
||
TToken_string& emptyrowc = sf.row(-1);
|
||
rowgiac.add("** Giacenza teorica",F_DESCART-FIRST_FIELD);
|
||
row.add("** Ordini ",F_DESCART-FIRST_FIELD);
|
||
}
|
||
int art_row;
|
||
for (art_row=int(sf.items())-1;art_row >=0; art_row--)
|
||
{
|
||
TToken_string &row=sf.row(art_row);
|
||
long codcli;
|
||
TCodice_articolo codart ;
|
||
TString16 liv, mag, codimp, codlin, codum;
|
||
msprow2codes(row,codcli,codart,liv, mag, codimp, codlin, codum);
|
||
|
||
if (!sf.cell_disabled(art_row, F_BUCKET1-FIRST_FIELD))
|
||
{
|
||
line_found=(a.codcli()==codcli && a.codice()==codart && a.livgiac()==liv
|
||
&& a.codimp()==codimp && a.codlin()==codlin && a.codmag()==mag );
|
||
if (line_found)
|
||
break;
|
||
} else {
|
||
TMSP_constraint* currcons=_constraints.find(codcli, codart, liv, codimp, codlin, mag);
|
||
if (constraint==currcons)
|
||
break;
|
||
}
|
||
}
|
||
if (!line_found)
|
||
{
|
||
art_row++;
|
||
sf.insert(art_row);
|
||
TToken_string& artrow = sf.row(art_row);
|
||
constraint->fill_sheet_row(artrow, *this,TRUE);
|
||
artrow.add(a.codimp(), F_CODIMP-FIRST_FIELD);
|
||
artrow.add(a.codlin(), F_CODLIN-FIRST_FIELD);
|
||
TString16 str=a.codmag().left(3);
|
||
artrow.add(str, F_MAGAZZINO-FIRST_FIELD);
|
||
str=a.codmag().mid(3);
|
||
artrow.add(str, F_DEPOSITO-FIRST_FIELD);
|
||
}
|
||
TToken_string& artrow = sf.row(art_row);
|
||
const int lastbuck =_proposed_articles[new_row].last_bucket();
|
||
//TDate data_buck;
|
||
for (int bucket=0; bucket<=lastbuck ; bucket++)
|
||
{
|
||
int b= int((_proposed_articles[new_row].time(bucket).date() - get_date(F_DADATA))/days_per_bucket());
|
||
|
||
real art_per_buck(artrow.get(F_BUCKET1 + b*2 - FIRST_FIELD));
|
||
if (sign>0)
|
||
art_per_buck+=_proposed_articles[new_row].sched_receipts(bucket);
|
||
else
|
||
{
|
||
if (art_per_buck >= _proposed_articles[new_row].sched_receipts(bucket))
|
||
art_per_buck-=_proposed_articles[new_row].sched_receipts(bucket);
|
||
else
|
||
art_per_buck=ZERO;
|
||
}
|
||
artrow.add(art_per_buck.string(), F_BUCKET1 + b*2 - FIRST_FIELD);
|
||
real price;
|
||
if (!art_per_buck.is_zero())
|
||
find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
|
||
get(F_TIPOCF), a.codcli(), a.codice(),
|
||
art_per_buck, price);
|
||
artrow.add(price.string(), F_BUCKET1 + b*2 + 1 - FIRST_FIELD);
|
||
}
|
||
test_art_row(art_row,FALSE);
|
||
}
|
||
sf.force_update();
|
||
}
|
||
|
||
|
||
// compatta le linee togliendo i doppioni
|
||
void TMSP_mask::pack_article_sheet()
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
TToken_string lastrow;
|
||
for (int art_row=int(sf.items())-1; art_row >=0; art_row--)
|
||
{
|
||
if (!sf.cell_disabled(art_row, F_BUCKET1-FIRST_FIELD))
|
||
{
|
||
TToken_string &row=sf.row(art_row);
|
||
long codcli = atol(row.get(F_CLIENTE-FIRST_FIELD));
|
||
TCodice_articolo codart = row.get(F_ARTICOLO-FIRST_FIELD);
|
||
TString16 codimp= row.get(F_CODIMP-FIRST_FIELD);
|
||
TString16 codlin= row.get(F_CODLIN-FIRST_FIELD);
|
||
TString16 liv;
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV1)),1);
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV2)),2);
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV3)),3);
|
||
_livelli.pack_grpcode(liv, row.get(sf.cid2index(F_LIV4)),4);
|
||
TString16 mag;
|
||
add_magcode(mag, row.get(F_MAGAZZINO-FIRST_FIELD));
|
||
add_depcode(mag, row.get(F_DEPOSITO-FIRST_FIELD));
|
||
|
||
for (int bucket=0; bucket<=LAST_BUCKET ; bucket++)
|
||
{
|
||
real art_per_buck(lastrow.get(F_BUCKET1 + bucket*2 - FIRST_FIELD));
|
||
row.add(art_per_buck.string(), F_BUCKET1 + bucket*2 - FIRST_FIELD);
|
||
}
|
||
}
|
||
}
|
||
sf.force_update();
|
||
}
|
||
|
||
|
||
void TMSP_mask::check_articles()
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
int items=sf.items();
|
||
if (items==0)
|
||
{
|
||
message_box("Nessun articolo da verificare");
|
||
return;
|
||
}
|
||
TMSPCheck_mask cm(this);
|
||
cm.run();
|
||
cm.gopos_mainmask();
|
||
}
|
||
|
||
void TMSP_mask::check_capacities()
|
||
{
|
||
TSheet_field& sf = sfield(F_LINEE);
|
||
int items=sf.items();
|
||
if (items==0)
|
||
{
|
||
message_box("Nessun carico di linea da verificare");
|
||
return;
|
||
}
|
||
TCRPCheck_mask cm(this);
|
||
cm.run();
|
||
set_focus_field(sf.dlg());
|
||
sf.set_focus_cell(cm.last_row(),cm.last_col()+F_LBUCKET0);
|
||
}
|
||
|
||
bool TMSP_mask::sort_sheet()
|
||
{
|
||
TWait_cursor hg;
|
||
TSheet_field& a = sfield(F_ARTICOLI);
|
||
bool ok=TRUE;
|
||
switch (-get_int(F_MSP_SORT))
|
||
{
|
||
case SORT_BY_CAL:
|
||
a.sort(TRiga_articolo::order_compareCAL); break;
|
||
case SORT_BY_CLA:
|
||
a.sort(TRiga_articolo::order_compareCLA); break;
|
||
case SORT_BY_ACL:
|
||
a.sort(TRiga_articolo::order_compareACL); break;
|
||
case SORT_BY_ALC:
|
||
a.sort(TRiga_articolo::order_compareALC); break;
|
||
case SORT_BY_LCA:
|
||
a.sort(TRiga_articolo::order_compareLCA); break;
|
||
case SORT_BY_LAC:
|
||
a.sort(TRiga_articolo::order_compareLAC); break;
|
||
default:
|
||
return FALSE;
|
||
}
|
||
a.force_update();
|
||
return ok;
|
||
}
|
||
|
||
void TMSP_mask::add_MRP_bucket(TMRP_line& new_article, int nbucket, const real &curr_arts)
|
||
{
|
||
TDate data_buck;
|
||
data_buck=get_date(F_DADATA);
|
||
data_buck+=days_per_bucket()*(nbucket-1);
|
||
TMRP_time t(data_buck, 0, "", "");
|
||
new_article.add_sched_rec(t, curr_arts );
|
||
}
|
||
|
||
|
||
void TMSP_mask::propose_1stJIT(TMSP_logic logic, bool check_machine, bool check_human)
|
||
{
|
||
const bool useextralines=get_bool(F_USENONSTDLIN_MSP);
|
||
const bool useextrahours=get_bool(F_USEEXTRAHRS_MSP) ;
|
||
const bool lotsizing=get_bool(F_LOTSIZING) ;
|
||
const bool no_outcapacity=get_bool(F_OUTOFCAPACITY) ;
|
||
const int anticipomin=get_int(F_ANTICIPOMIN);
|
||
const int anticipomax=get_int(F_ANTICIPOMAX);
|
||
bool ok=TRUE;
|
||
// per sicurezza devo (ri-)calcolare il carico attuale.....
|
||
_capacities.destroy();
|
||
if (check_machine || check_human)
|
||
{
|
||
if (ok = load_MRP_lines(_actual_schedule))
|
||
{
|
||
nettify_MRP_lines(TRUE,FALSE);
|
||
ok = general_review(check_machine, check_human, useextralines, useextrahours,FALSE, no_outcapacity,0, 0,_actual_schedule, logic);
|
||
}
|
||
}
|
||
// (two) levels master scheduling
|
||
TMRP_lines _1stlevel;
|
||
bool some=FALSE;
|
||
for (int level=1; ok && level <= 2; level++)
|
||
{
|
||
if (ok = load_MRP_lines(_stock_break,level))
|
||
{
|
||
_proposed_articles.destroy();
|
||
nettify_MRP_lines(FALSE, lotsizing);
|
||
if (ok = general_review(check_machine, check_human, useextralines, useextrahours,lotsizing, no_outcapacity,anticipomin,anticipomax,_stock_break, logic))
|
||
some = insert_propose(some || level==2);
|
||
if (level==1)
|
||
_1stlevel=_proposed_articles;
|
||
if (level==2)
|
||
_proposed_articles.add(_1stlevel);
|
||
}
|
||
}
|
||
if (!ok)
|
||
remove_propose();
|
||
_capacities.sort();
|
||
}
|
||
|
||
/*
|
||
void TMSP_mask::propose_firstfit(bool check_machine, bool check_human)
|
||
{
|
||
const bool useextralines=get_bool(F_USENONSTDLIN_MSP);
|
||
const bool useextrahours=get_bool(F_USEEXTRAHRS_MSP) ;
|
||
const bool lotsizing=get_bool(F_LOTSIZING) ;
|
||
const bool no_outcapacity=get_bool(F_OUTOFCAPACITY) ;
|
||
const int anticipomin=get_int(F_ANTICIPOMIN);
|
||
const int anticipomax=get_int(F_ANTICIPOMAX);
|
||
bool ok=TRUE;
|
||
// per sicurezza devo (ri-)calcolare il carico attuale.....
|
||
_capacities.destroy();
|
||
if (check_machine || check_human)
|
||
{
|
||
if (ok = load_MRP_lines(_actual_schedule))
|
||
{
|
||
nettify_MRP_lines(TRUE,FALSE);
|
||
ok = firstfit_review(check_machine, check_human, useextralines, useextrahours,FALSE, no_outcapacity,0, 0,_actual_schedule);
|
||
}
|
||
}
|
||
// (two) levels master scheduling
|
||
TMrp_lines _1stlevel;
|
||
for (int level=1; level <= 2; level++)
|
||
{
|
||
if (ok && (ok = load_MRP_lines(_stock_break,level)))
|
||
{
|
||
nettify_MRP_lines(FALSE, lotsizing);
|
||
if (ok = firstfit_review(check_machine, check_human, useextralines, useextrahours,lotsizing, no_outcapacity,anticipomin,anticipomax,_stock_break))
|
||
{
|
||
insert_propose();
|
||
_1stlevel=_proposed_articles();
|
||
|
||
}
|
||
}
|
||
}
|
||
if (!ok)
|
||
remove_propose();
|
||
_capacities.sort();
|
||
}
|
||
|
||
// propone i valori con logica Just-in-time
|
||
void TMSP_mask::propose_JIT(bool check_machine, bool check_human)
|
||
{
|
||
const bool useextralines=get_bool(F_USENONSTDLIN_MSP);
|
||
const bool useextrahours=get_bool(F_USEEXTRAHRS_MSP) ;
|
||
const bool lotsizing=get_bool(F_LOTSIZING) ;
|
||
const bool no_outcapacity=get_bool(F_OUTOFCAPACITY) ;
|
||
const int anticipomin=get_int(F_ANTICIPOMIN);
|
||
const int anticipomax=get_int(F_ANTICIPOMAX);
|
||
bool ok=TRUE;
|
||
// per sicurezza devo (ri-)calcolare il carico attuale.....
|
||
_capacities.destroy();
|
||
if (check_machine || check_human)
|
||
{
|
||
if (ok = load_MRP_lines(_actual_schedule))
|
||
{
|
||
nettify_MRP_lines(TRUE, FALSE);
|
||
ok = JIT_review(check_machine, check_human, useextralines, useextrahours,FALSE, no_outcapacity,0, 0,_actual_schedule);
|
||
}
|
||
}
|
||
// (two) levels master scheduling
|
||
for (int level=1; level < 2; level++)
|
||
{
|
||
if (ok && (ok = load_MRP_lines(_stock_break, 1)))
|
||
{
|
||
nettify_MRP_lines(FALSE, lotsizing);
|
||
if (ok = JIT_review(check_machine, check_human, useextralines, useextrahours,FALSE, no_outcapacity,anticipomin,anticipomax,_stock_break))
|
||
insert_propose();
|
||
}
|
||
}
|
||
if (!ok)
|
||
remove_propose();
|
||
_capacities.sort();
|
||
}
|
||
|
||
|
||
bool TMSP_mask::firstfit_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode)
|
||
{
|
||
return general_review(check_machine, check_human, useextralines, useextrahours,lotsizing, no_outcapacity, anticipomin,anticipomax, mode, _first_fit_logic);
|
||
}
|
||
|
||
|
||
bool TMSP_mask::JIT_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode)
|
||
{
|
||
return general_review(check_machine, check_human, useextralines, useextrahours,lotsizing, no_outcapacity, anticipomin,anticipomax, mode, _JIT_logic);
|
||
}
|
||
*/
|
||
|
||
// propone i valori con logica first-fit
|
||
// cerca il primo bucket con capacit<69> produttiva
|
||
bool TMSP_mask::general_review(bool check_machine, bool check_human, bool useextralines, bool useextrahours,bool lotsizing, bool no_outcapacity, int anticipomin,int anticipomax, TMSP_mode mode, TMSP_logic logic )
|
||
{
|
||
const bool ignore_mag=get_bool(F_NOMAG_IN);
|
||
const bool ignore_imp=get_bool(F_NOIMP_IN);
|
||
const bool ignore_lin=get_bool(F_NOLIN_IN);
|
||
TLavorazione *curr_labor;
|
||
TLinea_prod linea_prod;
|
||
TArray labors;
|
||
|
||
const long max_mrp_rows=_mrp_articles.items();
|
||
const char *msg;
|
||
if (mode == _actual_schedule)
|
||
msg="Calcolo carico attuale";
|
||
else
|
||
msg="Calcolo nuove proposte";
|
||
TProgind pi(max_mrp_rows,msg, TRUE, TRUE);
|
||
|
||
for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
|
||
{
|
||
pi.addstatus(1);
|
||
if (pi.iscancelled())
|
||
return FALSE;
|
||
TMRP_line &mrpline=_mrp_articles[mrp_row];
|
||
TString16 livello_di_giacenza(mrpline.livgiac());
|
||
TString16 codlin(mrpline.codlin());
|
||
TString16 codimp(mrpline.codimp());
|
||
bool no_labor=!_dist_tree.set_root(mrpline.codice());
|
||
if (!no_labor)
|
||
{
|
||
TDate data_buck;
|
||
// la logica del ciclo sulle lav e' da invertire: prima il bucket , poi le lavorazioni
|
||
// se si vogliono caricare pi<70> lavorazioni
|
||
TRiga_esplosione * l=_dist_tree.first_critical_labor(labors);
|
||
no_labor=(l==NULL);
|
||
if (!no_labor)
|
||
{
|
||
curr_labor=TDistinta_tree::find_labor(l);
|
||
// cerca le linee sulle quali e' possibile eseguire questa lavorazione
|
||
// e la carica con la lavorazione relativa all'articolo corrente
|
||
const int lineestd = curr_labor->linee_standard();
|
||
const int maxlinee = useextralines ? curr_labor->linee() : lineestd;
|
||
TCRP_line *crpline,*crpline_imp,*crpline_firm;
|
||
const int lastbuck =mrpline.last_bucket();
|
||
for (int bucket=0; bucket<=lastbuck ; bucket++)
|
||
{
|
||
real curr_arts, art_per_buck(mrpline.net_requirement(bucket)); // quantit<69> da produrre nel bucket
|
||
real load, capacity, unit_load, hload, hcapacity, unit_hload ; // carichi di linea
|
||
int nbucket, lower_buck, upper_buck;
|
||
int attemp=1; // primo tentativo: rimane entro i vincoli di minimo e massimo anticipo utilizando solo le linee STD
|
||
// secondo tentativo: rimane entro i vincoli di minimo e massimo anticipo utilizando anche le linee non STD
|
||
// terzo tentativo: supera i vincoli di minimo e massimo anticipo utilizando anche le linee non STD
|
||
art_per_buck.round(5);
|
||
while (art_per_buck > ZERO && attemp <= 3)
|
||
{
|
||
if (logic == _first_fit_logic)
|
||
{
|
||
lower_buck = bucket - anticipomax/days_per_bucket();
|
||
upper_buck = (attemp <= 2 ? bucket-anticipomin/days_per_bucket(): LAST_BUCKET);
|
||
nbucket=lower_buck;
|
||
} else {
|
||
lower_buck = (attemp <= 2 ? bucket-anticipomax/days_per_bucket(): 0);
|
||
upper_buck = bucket - anticipomin/days_per_bucket();
|
||
nbucket=upper_buck;
|
||
}
|
||
if (lower_buck<1)
|
||
lower_buck=1;
|
||
if (nbucket<1)
|
||
nbucket=1;
|
||
do {
|
||
int nlinea, numlinee;
|
||
|
||
if (ignore_lin || codlin.blank() )
|
||
{
|
||
nlinea=(attemp == 2 ? lineestd : 0 ) ;
|
||
numlinee=(attemp == 1 ? lineestd : maxlinee ) ;
|
||
} else {
|
||
nlinea= curr_labor->find_linea(codlin);
|
||
if (nlinea<0)
|
||
{
|
||
error_box("La linea %s non e' in grado di produrre l'articolo %s", (const char * )codlin, (const char *) _mrp_articles[mrp_row].codice());
|
||
break;
|
||
}
|
||
numlinee=nlinea+1;
|
||
}
|
||
while (art_per_buck > ZERO && nlinea >= 0 && nlinea<numlinee)
|
||
{
|
||
// scelgo la linea
|
||
linea_prod= cache().get("LNP",curr_labor->cod_linea(nlinea));
|
||
if ( ignore_imp || codimp.blank() || codimp == linea_prod.codimp())
|
||
{
|
||
crpline=_capacities.find(linea_prod);
|
||
if (crpline==NULL)
|
||
crpline=compute_capacity(linea_prod,useextralines, useextrahours);
|
||
crpline_imp =_capacities.find(linea_prod.codimp());
|
||
crpline_firm=_capacities.find();
|
||
int human_level=1;
|
||
if ( linea_prod.personale_dedicato())
|
||
human_level=3;
|
||
else if (linea_prod.get_impianto()->personale_dedicato())
|
||
human_level=2;
|
||
// individua il massimo caricabile sulla linea
|
||
unit_load = l->val()*curr_labor->um_temporale().converti_in_ore()/curr_labor->produttiv_linea(nlinea);
|
||
unit_hload=unit_load*curr_labor->numpers_linea(nlinea);
|
||
|
||
capacity = check_machine ? crpline->capacity(nbucket) : MAXCAPACITY;
|
||
load = crpline->load(nbucket);
|
||
switch (human_level)
|
||
{
|
||
case 3:
|
||
hcapacity = crpline->human_capacity(nbucket) ;
|
||
hload = crpline->human_load(nbucket);
|
||
break;
|
||
case 2:
|
||
hcapacity = crpline_imp->human_capacity(nbucket) ;
|
||
hload = crpline_imp->human_load(nbucket);
|
||
break;
|
||
default:
|
||
hcapacity = crpline_firm->human_capacity(nbucket) ;
|
||
hload = crpline_firm->human_load(nbucket);
|
||
break;
|
||
}
|
||
// ridimensiona al massimo numero di articoli dovuto alle macchine
|
||
curr_arts = art_per_buck ;
|
||
if (mode != _actual_schedule /*|| no_outcapacity*/)
|
||
{
|
||
if (load + curr_arts * unit_load > capacity )
|
||
{
|
||
curr_arts = (capacity - load ) / unit_load;
|
||
curr_arts.floor();
|
||
}
|
||
// ridimensiona al massimo numero di articoli dovuto alle macchine
|
||
if (check_human && hload + curr_arts * unit_hload > hcapacity)
|
||
{
|
||
curr_arts = (hcapacity - hload) / unit_hload;
|
||
curr_arts.floor();
|
||
}
|
||
/*
|
||
// elimina i picchi di capacita' (errato)
|
||
if (curr_arts != art_per_buck && mode == _actual_schedule)
|
||
{
|
||
TMRP_line* new_article = _proposed_articles.find(mrpline.codice(),
|
||
mrpline.livgiac(), mrpline.codmag(),
|
||
linea_prod.codimp() , linea_prod.codice(), mrpline.codcli(), TRUE);
|
||
add_MRP_bucket(*new_article, nbucket, curr_arts-art_per_buck );
|
||
}*/
|
||
}
|
||
if (curr_arts>ZERO)
|
||
{
|
||
// aggiunge il carico macchina
|
||
art_per_buck-=curr_arts;
|
||
load= curr_arts * unit_load;
|
||
crpline->add_load(nbucket, load );
|
||
// aggiunge il carico uomo
|
||
load*=curr_labor->numpers_linea(nlinea);
|
||
switch (human_level)
|
||
{
|
||
case 3:
|
||
crpline->add_human_load(nbucket, load );
|
||
case 2:
|
||
crpline_imp->add_human_load(nbucket, load );
|
||
default:
|
||
crpline_firm->add_human_load(nbucket, load );
|
||
}
|
||
if (mode == _stock_break)
|
||
{
|
||
TMRP_line* new_article = find_propose(mrpline.codcli(), mrpline.codice(),
|
||
mrpline.livgiac(), linea_prod.codimp() , linea_prod.codice(), mrpline.codmag(), TRUE);
|
||
add_MRP_bucket(*new_article, nbucket, curr_arts);
|
||
}
|
||
}
|
||
} else
|
||
error_box("Articolo %s: impianto %s incompatibile con la linea %s",(const char *)mrpline.codice(), (const char *)codimp, (const char *)linea_prod.codice());
|
||
nlinea++;
|
||
} // ciclo sulle linee
|
||
if (logic == _first_fit_logic)
|
||
nbucket++;
|
||
else
|
||
nbucket--;
|
||
} while(art_per_buck > ZERO && nbucket>=lower_buck && nbucket <= upper_buck );
|
||
attemp++; // altro tentativo
|
||
}
|
||
}
|
||
l=_dist_tree.next_critical_labor(labors);
|
||
}
|
||
}
|
||
if (no_labor) // nessuna lavorazione da controllare o capacita' infinita
|
||
{
|
||
if (mode == _stock_break)
|
||
{
|
||
const int lastbuck =mrpline.last_bucket();
|
||
for (int b=0; b<=lastbuck ; b++)
|
||
{
|
||
real art_per_buck(mrpline. net_requirement(b));// quantit<69> da produrre nel bucket
|
||
if (art_per_buck > ZERO)
|
||
{
|
||
int nbucket;
|
||
if (logic == _first_fit_logic)
|
||
nbucket = b - anticipomax/days_per_bucket();
|
||
else
|
||
nbucket = b - anticipomin/days_per_bucket();
|
||
if (nbucket<1)
|
||
nbucket=1;
|
||
TMRP_line* new_article = find_propose(mrpline.codcli(), mrpline.codice(), mrpline.livgiac(),
|
||
mrpline.codimp() , mrpline.codlin(), mrpline.codmag(), TRUE);
|
||
add_MRP_bucket(*new_article, nbucket, art_per_buck);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
bool TMSP_mask::capacity_review(bool useextralines, bool useextrahours)
|
||
{
|
||
bool ok;
|
||
if (!load_MRP_lines(_actual_schedule))
|
||
return FALSE;
|
||
nettify_MRP_lines(TRUE);
|
||
|
||
_capacities.destroy();
|
||
if (get(F_RECALC_TYPE).left(1)=="1")
|
||
ok = general_review(TRUE, TRUE, useextralines, useextrahours, FALSE, FALSE, 0, 0, _actual_schedule,_first_fit_logic);
|
||
else if (get(F_RECALC_TYPE).left(3)=="JIT")
|
||
ok = general_review(TRUE, TRUE, useextralines, useextrahours, FALSE, FALSE, 0, 0, _actual_schedule,_first_fit_logic);
|
||
|
||
_capacities.sort();
|
||
return ok;
|
||
}
|
||
|
||
|
||
TCRP_line *TMSP_mask::compute_capacity(TLinea_prod &lineaprod, bool useextralines, bool useextrahours)
|
||
{
|
||
TMRP_calendar & cal = TMRP_time::get_calendar("", lineaprod.codice());
|
||
TMRP_calendar & cal_imp = TMRP_time::get_calendar("", lineaprod.codimp());
|
||
TMRP_calendar & cal_firm = TMRP_time::get_calendar("");
|
||
CHECK(_capacities.find(lineaprod,FALSE)==NULL,"Errore: impossibile ricalcolare la capacita' di una linea produttiva");
|
||
|
||
TCRP_line *crpline,*crpline_imp,*crpline_firm;
|
||
crpline =_capacities.find(lineaprod, "", 0L,TRUE);
|
||
const bool compute_imp = (_capacities.find(lineaprod.codimp(), "", "", 0L)==NULL);
|
||
crpline_imp =_capacities.find(lineaprod.codimp(), "", "", 0L, TRUE);
|
||
const bool compute_firm = (_capacities.find("", "", "", 0L)==NULL);
|
||
crpline_firm=_capacities.find("", "", "", 0L, TRUE);
|
||
|
||
// calcola la capacita'
|
||
TDate data_buck=get_date(F_DADATA);
|
||
real capacity,human,human_imp,human_firm;
|
||
for (int b=1; b<LAST_BUCKET ; b++)
|
||
{
|
||
capacity=ZERO;
|
||
human=ZERO;
|
||
human_imp=ZERO;
|
||
human_firm=ZERO;
|
||
for (int day=days_per_bucket()-1; day>=0 ; day--)
|
||
{
|
||
cal.add_oremacchina(capacity, data_buck,useextrahours);
|
||
if (lineaprod.personale_dedicato())
|
||
cal.add_oreuomo(human, data_buck,useextrahours);
|
||
if (compute_imp && lineaprod.get_impianto()->personale_dedicato())
|
||
cal_imp.add_oreuomo(human_imp, data_buck,useextrahours);
|
||
if (compute_firm)
|
||
cal_firm.add_oreuomo(human_firm, data_buck,useextrahours);
|
||
++data_buck;
|
||
}
|
||
crpline->set_capacity(b,capacity);
|
||
if (human > ZERO)
|
||
{
|
||
crpline->set_human_capacity(b,human);
|
||
crpline_imp->set_human_capacity(b,human+crpline_imp->human_capacity(b));
|
||
crpline_firm->set_human_capacity(b,human+crpline_firm->human_capacity(b));
|
||
}
|
||
else
|
||
crpline->set_human_capacity(b,ZERO);
|
||
if (human_imp > ZERO)
|
||
{
|
||
crpline_imp->set_human_capacity(b,human_imp+crpline_imp->human_capacity(b));
|
||
crpline_firm->set_human_capacity(b,human_imp+crpline_firm->human_capacity(b));
|
||
}
|
||
else
|
||
crpline_imp->set_human_capacity(b,ZERO);
|
||
if (human_firm > ZERO)
|
||
crpline_firm->set_human_capacity(b,human_firm+crpline_firm->human_capacity(b));
|
||
}
|
||
return crpline;
|
||
}
|
||
|
||
TMRP_line* TMSP_mask::find_propose(
|
||
long codcli, const char * codart,const char * liv,
|
||
const char * codimp,const char * codlin,
|
||
const char * mag, bool Force)
|
||
{
|
||
return _proposed_articles.find(codart,liv,mag,codimp,codlin,codcli, Force);
|
||
}
|
||
|
||
// carica le MRP line dallo sheet articoli
|
||
void TMSP_mask::msprow2codes(TToken_string &row,long &clifor, TCodice_articolo &art ,
|
||
TString & liv, TString & mag, TString & imp, TString & lin, TString & um)
|
||
{
|
||
clifor = row.get_long(F_CLIENTE-FIRST_FIELD);
|
||
art = row.get(F_ARTICOLO-FIRST_FIELD);
|
||
_livelli.pack_grpcode(liv, row.get(F_LIV1-FIRST_FIELD),1);
|
||
_livelli.pack_grpcode(liv, row.get(F_LIV2-FIRST_FIELD),2);
|
||
_livelli.pack_grpcode(liv, row.get(F_LIV3-FIRST_FIELD),3);
|
||
_livelli.pack_grpcode(liv, row.get(F_LIV4-FIRST_FIELD),4);
|
||
add_magcode(mag,row.get(F_MAGAZZINO-FIRST_FIELD));
|
||
add_depcode(mag,row.get(F_DEPOSITO-FIRST_FIELD));
|
||
imp = row.get(F_CODIMP-FIRST_FIELD); imp.trim();
|
||
lin = row.get(F_CODLIN-FIRST_FIELD); lin.trim();
|
||
um = row.get(F_UM-FIRST_FIELD); um.trim();
|
||
}
|
||
|
||
void TMSP_mask::crprow2codes(TToken_string &row, TString & imp, TString & lin, long &clifor, TCodice_articolo &art ,
|
||
TString & liv, TString & um)
|
||
{
|
||
clifor=0L;//clifor = row.get_long(F_CLIENTE-FIRST_FIELD);
|
||
//art = row.get(F_ARTICOLO-FIRST_FIELD);
|
||
//_livelli.pack_grpcode(liv, row.get(F_LIV1-FIRST_FIELD),1);
|
||
//_livelli.pack_grpcode(liv, row.get(F_LIV2-FIRST_FIELD),2);
|
||
//_livelli.pack_grpcode(liv, row.get(F_LIV3-FIRST_FIELD),3);
|
||
//_livelli.pack_grpcode(liv, row.get(F_LIV4-FIRST_FIELD),4);
|
||
imp = row.get(F_CODIMPCRP-FIRST_FIELD); imp.trim();
|
||
lin = row.get(F_CODLINCRP-FIRST_FIELD); lin.trim();
|
||
um = row.get(F_LUM-FIRST_FIELD); um.trim();
|
||
}
|
||
// carica le MRP line dallo sheet articoli
|
||
bool TMSP_mask::load_MRP_lines(TMSP_mode mode, int level)
|
||
{
|
||
TSheet_field& sa = sfield(F_ARTICOLI);
|
||
if (sa.items()==0)
|
||
{
|
||
message_box("Nessun articolo da valutare");
|
||
return FALSE;
|
||
}
|
||
const int a_buck0 = sa.cid2index(F_BUCKET0);
|
||
TDate data_buck;
|
||
|
||
_mrp_articles.destroy();
|
||
// calcola gli impegni di produzione per gli articoli dello sheet
|
||
bool skip=FALSE;
|
||
TMRP_line* last_constraint = NULL;
|
||
FOR_EACH_SHEET_ROW(sa, r, row) if (!sa.cell_disabled(r, a_buck0+2) || sa.cell_disabled(r+1, a_buck0+2))
|
||
{
|
||
const bool is_constraint=sa.cell_disabled(r, a_buck0+2);
|
||
if (is_constraint)
|
||
{
|
||
const bool has_mastercodes=(*row->get(F_MASTERCODE-FIRST_FIELD)=='M');
|
||
skip = (level == 1 && !has_mastercodes || level == 2 && has_mastercodes );
|
||
}
|
||
if (!skip)
|
||
{
|
||
long clifor;
|
||
TCodice_articolo art ;
|
||
TString16 liv,mag, imp, lin;
|
||
TCodice_um um ;
|
||
msprow2codes(*row,clifor, art , liv, mag, imp, lin, um);
|
||
|
||
TMRP_line* curr_article = _mrp_articles.find(art, liv, mag, imp, lin, clifor ,TRUE);
|
||
if (is_constraint)
|
||
last_constraint=curr_article;
|
||
|
||
bool added_some=FALSE;
|
||
for (int nbucket=LAST_BUCKET-1; nbucket>=0 ; nbucket--)
|
||
{
|
||
data_buck=get_date(F_DADATA);
|
||
data_buck+=days_per_bucket()*nbucket;
|
||
const TMRP_time t(data_buck, 0, imp, lin);
|
||
real qta=row->get(a_buck0+nbucket*2);
|
||
if (qta != ZERO)
|
||
{
|
||
TQuantita q(art, um, qta);
|
||
q.convert2umbase();
|
||
// mette i vincoli nel gross req
|
||
// e le celle normali negli sched receipts
|
||
switch (mode)
|
||
{
|
||
case _actual_schedule:
|
||
if (!is_constraint)
|
||
{
|
||
curr_article->add_gross_req(t, q.val());
|
||
curr_article->add_sched_rec(t, q.val());
|
||
}
|
||
break;
|
||
case _stock_break:
|
||
if (is_constraint)
|
||
{
|
||
curr_article->add_gross_req(t, q.val());
|
||
last_constraint=curr_article;
|
||
} else {
|
||
if (last_constraint)
|
||
last_constraint->add_sched_rec(t, q.val());
|
||
}
|
||
break;
|
||
}
|
||
added_some=TRUE;
|
||
} else
|
||
if (added_some)
|
||
curr_article->set_on_hand(t, ZERO);
|
||
if (nbucket == 0)
|
||
curr_article->set_on_hand(t, curr_article->giacenza_attuale(qta,data_buck));
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// is_net_requirement: dice se le quantit<69> presenti sono da considerare gia' come net req o
|
||
// se devo prenderle come scheduled rec e il net req lo devo calcolare di conseguenza
|
||
bool TMSP_mask::nettify_MRP_lines(bool already_net, bool lotsizing)
|
||
{
|
||
// ***********
|
||
// gross 2 net
|
||
const long max_mrp_rows=_mrp_articles.items();
|
||
for (long mrp_row=0; mrp_row < max_mrp_rows; mrp_row++)
|
||
{
|
||
// calcola il fabbisogno netto e lo riporta sul bucket seguente
|
||
TMRP_line & mrp_line = _mrp_articles[mrp_row];
|
||
const int last = mrp_line.last_bucket();
|
||
for (int bucket = 0; bucket <= last; bucket = mrp_line.next_bucket(bucket))
|
||
{
|
||
real netreq,giacres;
|
||
if (already_net)
|
||
{
|
||
// generazione del master schedule plan; le quantit<69> sono da considerare nette
|
||
netreq= mrp_line.sched_receipts(bucket);
|
||
giacres=0;
|
||
mrp_line.set_net_req(bucket, netreq );
|
||
} else {
|
||
// generazione delle pianificazioni (commesse, Master Production Plan (non per famiglie), prove di budget ecc)
|
||
giacres = mrp_line.on_hand(bucket);
|
||
giacres += mrp_line.sched_receipts(bucket);
|
||
giacres -= mrp_line.gross_requirement(bucket);
|
||
if (lotsizing)
|
||
netreq = mrp_line.sizeup_net_requirement(bucket, giacres);
|
||
else
|
||
{
|
||
netreq = -giacres;
|
||
netreq = mrp_line.set_net_req(bucket, netreq);
|
||
}
|
||
giacres += netreq;
|
||
}
|
||
if (giacres > ZERO)
|
||
{
|
||
const int nb = mrp_line.next_bucket(bucket);
|
||
if (nb <= mrp_line.last_bucket())
|
||
mrp_line.set_on_hand(nb, giacres);
|
||
}
|
||
}
|
||
}
|
||
return max_mrp_rows>0;
|
||
}
|
||
|
||
|
||
int TMSP_mask::days_per_bucket() const
|
||
{
|
||
return get_int(F_DAYXBUCK) * (get_int(F_BUCKETS) ? get_int(F_BUCKETS) : get_int(F_BUCKET));
|
||
}
|
||
|
||
void TMSP_mask::clear_sheets()
|
||
{
|
||
TSheet_field &sa=sfield(F_ARTICOLI);
|
||
if (sa.items()>0)
|
||
{
|
||
sa.destroy();
|
||
sa.force_update();
|
||
}
|
||
TSheet_field &sl=sfield(F_LINEE);
|
||
if (sl.items()>0)
|
||
{
|
||
sl.destroy();
|
||
sl.force_update();
|
||
}
|
||
// sfield(F_TESTE).destroy();
|
||
// sfield(F_TESTE).force_update();
|
||
xvt_statbar_set("");
|
||
}
|
||
|
||
// **********
|
||
// imposta il bucket 0 ; se i flag sulla maschera sono settati,
|
||
// - sulla riga delle giacenze progressive : somma la giacenza iniziale
|
||
// - sulla riga dell'ordinato progressivo => sottrae la giacenza iniziale
|
||
// **********
|
||
// valore di ritorno:restituisce l'ultima linea dello sheet processata
|
||
int TMSP_mask::init_bucket0(TArticolo_giacenza &art, int r)
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
|
||
const bool add_giac=get_bool(F_MSCHEDULEPLAN);// nettifica la giacenza
|
||
|
||
// Calcola l'indice c della riga con la giacenza prog
|
||
const int b0 = sf.cid2index(F_BUCKET0);
|
||
const int b1 = sf.cid2index(F_BUCKET1);
|
||
real planned;
|
||
for (int c = r; c > 1; c--)
|
||
{
|
||
if (sf.cell_disabled(c, b1))
|
||
break;
|
||
planned += real(sf.cell(c, b0));
|
||
}
|
||
TToken_string &giac_row=sf.row(c);
|
||
TToken_string &ord_row=sf.row(c-1);
|
||
// calcola codice di magazzino e di livello
|
||
TString16 livello;
|
||
_livelli.pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV1)),1);
|
||
_livelli.pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV2)),2);
|
||
_livelli.pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV3)),3);
|
||
_livelli.pack_grpcode(livello, giac_row.get(sf.cid2index(F_LIV4)),4);
|
||
TString16 codmag;
|
||
add_magcode(codmag, giac_row.get(sf.cid2index(F_MAGAZZINO)));
|
||
add_depcode(codmag, giac_row.get(sf.cid2index(F_DEPOSITO)));
|
||
// calcola i bucket 0
|
||
TQuantita prog_giac(art.codice(),giac_row.get(sf.cid2index(F_UM)),planned);
|
||
real giac=art.giacenza_anno(codmag, livello, get_date(F_DADATA).year());
|
||
if (add_giac)
|
||
prog_giac +=giac;
|
||
prog_giac += giac_row.get(b0);
|
||
|
||
giac_row.add(prog_giac.val().string(), b0);
|
||
do_test_art_row(r,c,FALSE);
|
||
|
||
return c-2;
|
||
}
|
||
|
||
bool TMSP_mask::do_test_art_row(int r, int c, bool signal)
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
TMask & smask= sf.sheet_mask();
|
||
TToken_string & curr_row=sf.row(r);
|
||
TToken_string & constr_row=sf.row(c-1);
|
||
TToken_string & giac_row=sf.row(c);
|
||
TCodice_articolo codart(curr_row.get(sf.cid2index(F_ARTICOLO)));
|
||
const int b0 = sf.cid2index(F_BUCKET0);
|
||
|
||
// calcola la giacenza proiettata
|
||
TQuantita vincolo(codart,giac_row.get(sf.cid2index(F_UM)),ZERO);
|
||
TQuantita totale(vincolo),qta(vincolo);
|
||
totale += real(sf.cell(c, b0));// giacenza iniziale
|
||
for (int b = 1; b < LAST_BUCKET; b++)
|
||
{
|
||
vincolo.set_val(real(sf.cell(c-1, b0+b*2)));
|
||
for (int i = c+1; i <= r; i++)
|
||
{
|
||
totale += real(sf.cell(i, b0+b*2)); // somma alla giacenza le produzioni
|
||
}
|
||
totale -= real(sf.cell(c-1, b0+b*2)); // detrae le uscite
|
||
giac_row.add(totale.val().string(), b0+b*2);
|
||
if (signal && totale.val() < 0)
|
||
{
|
||
TString err;
|
||
const int bucket_size = days_per_bucket();
|
||
const TDate d = get_date(F_DADATA) + long(bucket_size * (b-1));
|
||
err << "Riga " << c+1 << ": Vincolo non ripettato al " << d;
|
||
beep();
|
||
signal =FALSE;
|
||
xvt_statbar_set(err);
|
||
}
|
||
}
|
||
sf.force_update(c);
|
||
if (signal) xvt_statbar_set("");
|
||
|
||
if (constr_row.get_char(sf.cid2index(F_MASTERCODE))=='M')
|
||
{
|
||
// aggancia i master di 2' livello
|
||
TString16 liv;
|
||
_livelli.pack_grpcode(liv, curr_row.get(sf.cid2index(F_LIV1)),1);
|
||
_livelli.pack_grpcode(liv, curr_row.get(sf.cid2index(F_LIV2)),2);
|
||
_livelli.pack_grpcode(liv, curr_row.get(sf.cid2index(F_LIV3)),3);
|
||
_livelli.pack_grpcode(liv, curr_row.get(sf.cid2index(F_LIV4)),4);
|
||
TString16 imp(curr_row.get(sf.cid2index(F_CODIMP)));//imp.trim();
|
||
TString16 lin(curr_row.get(sf.cid2index(F_CODLIN)));//lin.trim();
|
||
TString16 mag;
|
||
add_magcode(mag, curr_row.get(sf.cid2index(F_MAGAZZINO)));
|
||
add_depcode(mag, curr_row.get(sf.cid2index(F_DEPOSITO)));
|
||
|
||
TMSP_line mspline(curr_row.get_long(F_CLIENTE-FIRST_FIELD), codart, liv, imp, lin, mag);
|
||
TMSP_constraint*currconstr=find_constraint(mspline);
|
||
|
||
CHECK (currconstr, "Impossibile trovare il vincolo dell'articolo di 1' livello");
|
||
int i=0;
|
||
TMaster_code *mc;
|
||
while ((mc=currconstr->get_mastercode(i++))!=NULL)
|
||
{
|
||
TMSP_constraint* line_master=_constraints.find(currconstr->cliente(),mc->articolo()
|
||
, mc->livello(), mc->codimp(), mc->codlin(), mc->codmag());
|
||
CHECK (line_master, "Impossibile trovare il vincolo dell'articolo di 2' livello");
|
||
CHECK (line_master->has_upperlines(), "La linea master non risulta avere dipendenze di alcun tipo");
|
||
|
||
int mrow= find_constr_row(*line_master);
|
||
real q2make(giac_row.get(sf.cid2index(F_BUCKET0)));
|
||
for (int b = 1; b <= LAST_BUCKET; b++)
|
||
{
|
||
const int b2=b-int(long(mc->leadtime()/days_per_bucket()+0.5));
|
||
if (b2>=0)
|
||
{
|
||
q2make=real(giac_row.get(sf.cid2index(F_BUCKET0+b*2)))+
|
||
real(constr_row.get(sf.cid2index(F_BUCKET0+b*2)))-
|
||
real(giac_row.get(sf.cid2index(F_BUCKET0+b*2-2)));
|
||
if (q2make > ZERO)
|
||
q2make = (q2make)*mc->expr();
|
||
else
|
||
q2make = ZERO;
|
||
TMSP_constraint* upperline=line_master->get_upperline(*currconstr);
|
||
real oldq2make=upperline->qta(b2);
|
||
real totale2make=line_master->qta(b2);
|
||
line_master->qta(b2) = line_master->qta(b2) - upperline->qta(b2) + q2make;
|
||
upperline->qta(b2) = q2make;
|
||
|
||
TToken_string &master_row=sf.row(mrow);
|
||
master_row.add(line_master->qta(b2).string(),sf.cid2index(F_BUCKET0+b2*2));
|
||
}
|
||
}
|
||
sf.force_update(mrow);
|
||
int first,last;
|
||
TRiga_articolo::find_block(sf, mrow+2, first, last);
|
||
do_test_art_row(last, first, signal);
|
||
}
|
||
}
|
||
return c-2;
|
||
}
|
||
|
||
|
||
bool TMSP_mask::test_art_row(int r, bool signal)
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
int c;
|
||
if (!TRiga_articolo::find_block(sf, r, c, r))
|
||
return TRUE;
|
||
else
|
||
{
|
||
TToken_string & curr_row=sf.row(r);
|
||
TToken_string & constr_row=sf.row(c-1);
|
||
// setta la priorita' su tutte le righe del blocco
|
||
const int prior =curr_row.get_int(sf.cid2index(F_PRIORITA));
|
||
const int old_prior=constr_row.get_int(sf.cid2index(F_PRIORITA));
|
||
if (old_prior != prior)
|
||
{
|
||
for (int i = c-1; i<=r; i++)
|
||
{
|
||
sf.row( i ).add(prior , sf.cid2index(F_PRIORITA));
|
||
sf.force_update(i);
|
||
}
|
||
}
|
||
}
|
||
return do_test_art_row(r, c, signal);
|
||
}
|
||
|
||
bool TMSP_mask::test_load_row(int r, bool signal)
|
||
{
|
||
TSheet_field& sf = sfield(F_LINEE);
|
||
const int narticoli=sf.items();
|
||
if (narticoli<=r)
|
||
return TRUE;
|
||
// Calcola l'indice c della riga con la capacita'
|
||
const int b0 = sf.cid2index(F_LBUCKET0);
|
||
const int b1 = sf.cid2index(F_LBUCKET1);
|
||
|
||
for (int c = r; c > 0; c--)
|
||
{
|
||
if (sf.cell_disabled(c, b1))
|
||
break;
|
||
}
|
||
// Calcola l'indice r della riga totale di linea
|
||
if (r == c) r++;
|
||
TToken_string &row=sf.row(c);
|
||
real capacita, carico;
|
||
for (int b = 1; b < LAST_BUCKET; b++)
|
||
{
|
||
capacita=real(sf.cell(c, b0+b*2));
|
||
carico=real(sf.cell(r, b0+b*2));
|
||
if (signal && capacita < carico)
|
||
{
|
||
TString err;
|
||
const int bucket_size = days_per_bucket();
|
||
const TDate d = get_date(F_DADATA) + long(bucket_size * (b-1));
|
||
err << "Riga " << c+1 << ": capacita' superata al " << d;
|
||
beep();
|
||
signal =FALSE;
|
||
xvt_statbar_set(err);
|
||
}
|
||
}
|
||
if (signal) xvt_statbar_set("");
|
||
return signal;
|
||
}
|
||
|
||
|
||
void TMSP_mask::salva_documenti()
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
const int b0 = sf.cid2index(F_BUCKET0);
|
||
const int b1 = sf.cid2index(F_BUCKET1);
|
||
const int um = sf.cid2index(F_UM);
|
||
const TDate date_to = get(F_ADATA);
|
||
|
||
TPlan_docs doc_rows(get(F_NUM_PLAN), get(F_TIPO_PLAN), get(F_RIGA_PLAN));
|
||
|
||
const TDate from = get(F_DADATA);
|
||
const int bucket_size = days_per_bucket();
|
||
const bool number_by_cli = get_bool(F_NUMBERBYCLI);
|
||
|
||
for (int b = 1; b < LAST_BUCKET; b++)
|
||
{
|
||
const TDate data = from + long(bucket_size * (b-1));
|
||
if (data > date_to)
|
||
break;
|
||
|
||
const int anno = data.year();
|
||
|
||
FOR_EACH_SHEET_ROW(sf, r, row) if (!sf.cell_disabled(r, b1))
|
||
{
|
||
TMSP_line& line = *_articles.find(*row, _livelli, TRUE);
|
||
|
||
const real& old = line.qta(b);
|
||
const real val = row->get(b0 + b*2);
|
||
if ((get(F_DA_MAGAZZ).empty() || line.codmag() >= get(F_DA_MAGAZZ)) &&
|
||
(get(F_A_MAGAZZ).empty() || line.codmag() <= get(F_A_MAGAZZ)) &&
|
||
(get(F_DA_IMPIANTO).empty() || line.codimp() >= get(F_DA_IMPIANTO)) &&
|
||
(get(F_A_IMPIANTO).empty() || line.codimp() <= get(F_A_IMPIANTO)))
|
||
{
|
||
if (old != val)
|
||
{
|
||
long numdoc = 0L;
|
||
int numrig = 0;
|
||
|
||
if (!line.riga(b, numdoc, numrig))
|
||
{
|
||
if (number_by_cli)
|
||
numdoc = line.cliente() * 100L;
|
||
numdoc += data.week();
|
||
}
|
||
const real incr = val-old;
|
||
TRiga_documento& riga = doc_rows.add_to_row(anno, numdoc, numrig, incr);
|
||
if (riga.get(RDOC_CODART).empty())
|
||
{
|
||
riga.put(RDOC_CODART, line.codice());
|
||
riga.put(RDOC_CODARTMAG, line.codice());
|
||
riga.put(RDOC_LIVELLO, line.livgiac());
|
||
riga.put(RDOC_CHECKED, "X");
|
||
riga.put(RDOC_CODMAG, line.codmag());
|
||
riga.put(RDOC_LINEA, line.codlin());
|
||
riga.put(RDOC_IMPIANTO, line.codimp());
|
||
riga.put(RDOC_UMQTA, row->get(sf.cid2index(F_UM)));
|
||
riga.put(RDOC_DATACONS, data);
|
||
riga.put(RDOC_DESCR, row->get(sf.cid2index(F_DESCART)));
|
||
|
||
TRectype& doc = (TRectype&)riga.doc().head();
|
||
if (doc.get(DOC_DATACONS).empty())
|
||
{
|
||
doc.put(DOC_DATACONS, data);
|
||
doc.put(DOC_TIPOCF, "C");
|
||
doc.put(DOC_CODCF, line.cliente());
|
||
}
|
||
doc.put(DOC_DATADOC, from);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
doc_rows.flush(data);
|
||
}
|
||
}
|
||
|
||
// copia i dati della riga al di fuori delle informazioni dei bucket
|
||
void TMSP_mask::copy_sheet_row(TToken_string & newrow, const TToken_string & row)
|
||
{
|
||
const TSheet_field& sf = sfield(F_ARTICOLI);
|
||
const int b0 = sf.cid2index(F_BUCKET0);
|
||
TString str;
|
||
for (int i = 0; i < b0; i++)
|
||
{
|
||
row.get(i, str);
|
||
newrow.add(str, i);
|
||
}
|
||
}
|
||
|
||
bool TMSP_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{
|
||
const char * confirm_msg="Le attuali %d linee di articoli verranno perse. Confermi?";
|
||
switch (o.dlg())
|
||
{
|
||
case F_DADATA:
|
||
if (e == fe_modify)
|
||
round_field(o, FALSE);
|
||
break;
|
||
case F_ADATA:
|
||
if (e == fe_modify)
|
||
round_field(o, TRUE);
|
||
break;
|
||
case F_BUCKET:
|
||
if (e == fe_modify)
|
||
{
|
||
round_field(field(F_DADATA), FALSE);
|
||
round_field(field(F_ADATA), TRUE);
|
||
}
|
||
break;
|
||
case F_YEAR:
|
||
case F_IMPIANTO:
|
||
case F_LINEA:
|
||
if (e == fe_modify || (o.dlg() == F_YEAR && e == fe_init ))
|
||
update_calendar(F_CALENDAR, F_YEAR, F_IMPIANTO, F_LINEA);
|
||
break;
|
||
case F_TIPI_ORC:
|
||
case F_TIPI_PLA:
|
||
if (e == fe_init)
|
||
{
|
||
TSheet_field& s = (TSheet_field&)o;
|
||
if (s.items() == 0)
|
||
{
|
||
s.row(0);
|
||
s.force_update();
|
||
}
|
||
}
|
||
if (e == fe_close)
|
||
{
|
||
const TSheet_field& s = (const TSheet_field&)o;
|
||
FOR_EACH_SHEET_ROW_BACK(s, r, row)
|
||
if (!row->empty_items())
|
||
{
|
||
bool ok;
|
||
if (o.dlg()==F_TIPI_PLA)
|
||
ok=test_tipodoc_num(sfield(F_NUM_PLA), s );
|
||
else
|
||
ok=test_tipodoc_num(sfield(F_NUM_ORC), s );
|
||
return ok;
|
||
}
|
||
return error_box("E' necessario inserire almeno una riga");
|
||
}
|
||
break;
|
||
|
||
case F_NUM_PLAN:
|
||
if (e == fe_close)
|
||
{
|
||
const TSheet_field& s = sfield(F_NUM_PLA);
|
||
FOR_EACH_SHEET_ROW_BACK(s, r, row)
|
||
if (o.get() == row->get(s.cid2index(F_NUMERAZ))) return TRUE;
|
||
return error_box("Numerazione non inclusa tra quelle di planning");
|
||
}
|
||
break;
|
||
case F_TIPO_PLAN:
|
||
if (e == fe_close)
|
||
{
|
||
const TSheet_field& s = sfield(F_TIPI_PLA);
|
||
FOR_EACH_SHEET_ROW_BACK(s, r, row)
|
||
if (o.get() == row->get(s.cid2index(F_TIPO))) return TRUE;
|
||
return error_box("Tipo documento non incluso tra quelli di planning");
|
||
}
|
||
break;
|
||
case F_ARTICOLI:
|
||
{
|
||
TSheet_field& s = (TSheet_field&)o;
|
||
switch(e)
|
||
{
|
||
case se_query_add:
|
||
return jolly > 1 && s.items() > 0;
|
||
case se_notify_add:
|
||
if (jolly > 0)
|
||
{
|
||
const TToken_string& prev = s.row(int(jolly-1));
|
||
TToken_string& curr = s.row(int(jolly));
|
||
copy_sheet_row(curr,prev);
|
||
}
|
||
break;
|
||
case se_leave:
|
||
test_art_row((int)jolly);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case F_MSP_RESORT:
|
||
if (e==fe_button)
|
||
sort_sheet();
|
||
break;
|
||
case F_LINEE:
|
||
{
|
||
TSheet_field& s = (TSheet_field&)o;
|
||
switch(e)
|
||
{
|
||
case se_query_add:
|
||
return FALSE;
|
||
case se_leave:
|
||
test_load_row((int)jolly);
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
case F_CRP_RESORT:
|
||
break;
|
||
case F_BUCKET1:
|
||
case F_BUCKET2:
|
||
case F_BUCKET3:
|
||
case F_BUCKET4:
|
||
case F_BUCKET5:
|
||
case F_BUCKET6:
|
||
case F_BUCKET7:
|
||
case F_BUCKET8:
|
||
case F_BUCKET9:
|
||
case F_BUCKET10:
|
||
case F_BUCKET11:
|
||
case F_BUCKET12:
|
||
if (e == fe_modify)
|
||
{
|
||
const TSheet_field& s = sfield(F_ARTICOLI);
|
||
TMask & m=s.sheet_mask();
|
||
TMask_field &fprice=m.field(o.dlg()+1);
|
||
real qta(o.get());
|
||
real price(fprice.get());
|
||
if (!qta.is_zero() && price.is_zero())
|
||
find_price(get(F_TIPOCV),get(F_CODCONDV),get(F_CATVEN_CV),
|
||
m.get(F_TIPOCF_SHEET), m.get_long(F_CLIENTE), m.get(F_ARTICOLO),
|
||
qta , price);
|
||
fprice.set(price.string());
|
||
}
|
||
case DLG_CANCEL:
|
||
if (e == fe_button)
|
||
if (jolly == 0L)
|
||
{
|
||
TSheet_field& s = sfield(F_ARTICOLI);
|
||
int lineeart=s.items();
|
||
if (lineeart==0 || yesno_box(confirm_msg,lineeart))
|
||
{
|
||
enable(-1);
|
||
clear_sheets();
|
||
} else
|
||
return FALSE;
|
||
}
|
||
break;
|
||
case DLG_ELABORA:
|
||
if (e == fe_button && check_fields())
|
||
{
|
||
TSheet_field& s = sfield(F_ARTICOLI);
|
||
int lineeart=s.items();
|
||
if (lineeart==0 || yesno_box(confirm_msg,lineeart))
|
||
{
|
||
clear_sheets();
|
||
if (carica_documenti())
|
||
{
|
||
fill_sheet();
|
||
enable(DLG_SAVEREC, s.items() > 0);
|
||
enable(-1, s.items() == 0);
|
||
s.set_focus();
|
||
on_field_event((TOperable_field&)field(F_SHOWPRICES), fe_modify, jolly );
|
||
on_field_event((TOperable_field&)field(F_MSP_SORT), fe_init, jolly );
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case F_CANCEL_MSP:
|
||
if (e == fe_button)
|
||
{
|
||
remove_propose(TRUE);
|
||
}
|
||
break;
|
||
case F_RECALC_MSP:
|
||
if (e == fe_button && check_fields())
|
||
{
|
||
remove_propose();
|
||
const bool useextralines=get_bool(F_USENONSTDLIN_MSP);
|
||
const bool useextrahours=get_bool(F_USEEXTRAHRS_MSP) ;
|
||
set(F_USENONSTDLIN_CRP ,useextralines ? "X" : "");
|
||
set(F_USEEXTRAHRS_CRP ,useextrahours ? "X" : "");
|
||
if (get(F_RECALC_TYPE)=="1")
|
||
propose_1stJIT(_first_fit_logic,TRUE,TRUE);
|
||
else if (get(F_RECALC_TYPE)=="1_INFH")
|
||
propose_1stJIT(_first_fit_logic,TRUE,FALSE);
|
||
else if (get(F_RECALC_TYPE)=="1_INF")
|
||
propose_1stJIT(_first_fit_logic,FALSE,FALSE);
|
||
else if (get(F_RECALC_TYPE)=="JIT")
|
||
propose_1stJIT(_JIT_logic,TRUE,TRUE);
|
||
else if (get(F_RECALC_TYPE)=="JIT_INFH")
|
||
propose_1stJIT(_JIT_logic,TRUE,FALSE);
|
||
else if (get(F_RECALC_TYPE)=="JIT_INF")
|
||
propose_1stJIT(_JIT_logic,FALSE,FALSE);
|
||
// aggiorna lo sheet delle capacita'
|
||
on_field_event((TOperable_field&)field(F_LOADTYPE), fe_modify, jolly );
|
||
sfield(F_ARTICOLI).set_focus();
|
||
}
|
||
break;
|
||
case F_RECALC_CRP:
|
||
if (e == fe_button && check_fields())
|
||
{
|
||
if (capacity_review(get_bool(F_USENONSTDLIN_CRP) ,get_bool(F_USEEXTRAHRS_CRP) ))
|
||
{
|
||
on_field_event((TOperable_field&)field(F_LOADTYPE), fe_modify, jolly );
|
||
sfield(F_LINEE).set_focus();
|
||
}
|
||
}
|
||
break;
|
||
case F_CHECK_MSP:
|
||
if (e == fe_button)
|
||
{
|
||
check_articles();
|
||
}
|
||
break;
|
||
case F_CHECKLINE:
|
||
if (e == fe_button)
|
||
{
|
||
const TSheet_field& s = sfield(F_ARTICOLI);
|
||
TMSPCheck_mask cm(this);
|
||
cm.disable(-G_MOVIMENTO);
|
||
int curr_row=s.selected();
|
||
const bool is_disabled=s.cell_disabled(curr_row,F_BUCKET1-FIRST_FIELD) ;
|
||
const bool is_constr=(is_disabled && curr_row>0 && s.cell_disabled(curr_row-1,F_BUCKET1-FIRST_FIELD));
|
||
if (is_disabled && !is_constr)
|
||
curr_row++;
|
||
cm.gopos(curr_row, 1);
|
||
cm.run();
|
||
cm.gopos_mainmask();
|
||
}
|
||
break;
|
||
case F_SHOWPRICES:
|
||
if (e == fe_modify)
|
||
{
|
||
TSheet_field& s = sfield(F_ARTICOLI);
|
||
const bool on = get_bool(F_SHOWPRICES);
|
||
for (int b=LAST_BUCKET ; b>=0 ; b--)
|
||
{
|
||
s.set_column_width(F_BUCKET0+1+b*2-FIRST_FIELD, on ? 140 : 0);
|
||
s.enable_column(F_BUCKET0+1+b*2-FIRST_FIELD, on && b>0 && b < LAST_BUCKET);
|
||
// ^^^^- da sostituire con un piu' elegante (ma non implementato): s.show(F_BUCKET0+1+b*2-FIRST_FIELD,on);
|
||
}
|
||
s.force_update();
|
||
}
|
||
case F_CHECK_CRP:
|
||
if (e == fe_button)
|
||
{
|
||
check_capacities();
|
||
}
|
||
break;
|
||
case F_SHOWPERC:
|
||
if (e == fe_modify)
|
||
on_field_event((TOperable_field&)field(F_LOADTYPE), fe_modify, jolly );
|
||
break;
|
||
case F_LOADTYPE:
|
||
if (e == fe_modify)
|
||
{
|
||
// *************
|
||
// fill sheet of capacities
|
||
const bool as_percentage=get_bool(F_SHOWPERC);
|
||
const bool show_human=*get(F_LOADTYPE)=='H';
|
||
TSheet_field& sl = sfield(F_LINEE);
|
||
sl.destroy();
|
||
//TSheet_field& su = sfield(F_TESTE);
|
||
//su.destroy();
|
||
const long max_capacities=_capacities.items();
|
||
for (long c=0; c<max_capacities ; c++)
|
||
{
|
||
TCRP_line &crpline = _capacities[c];
|
||
if (show_human)
|
||
{
|
||
crpline.fill_hcapacity_row(sl.row(-1), as_percentage);
|
||
sl.disable_cell(sl.items()-1, -1);
|
||
crpline.fill_hload_row(sl.row(-1), as_percentage);
|
||
} else {
|
||
if (!crpline.codlin().blank())
|
||
{
|
||
crpline.fill_capacity_row(sl.row(-1), as_percentage);
|
||
sl.disable_cell(sl.items()-1, -1);
|
||
crpline.fill_load_row(sl.row(-1), as_percentage);
|
||
}
|
||
}
|
||
}
|
||
sl.force_update();
|
||
}
|
||
break;
|
||
case DLG_SAVEREC:
|
||
if (e == fe_button)
|
||
{
|
||
salva_documenti();
|
||
//clear_sheets();
|
||
//disable(DLG_SAVEREC);
|
||
//enable_default(-1);
|
||
//field(F_BUCKET).on_hit();
|
||
}
|
||
break;
|
||
case DLG_PROFILE:
|
||
if (e == fe_modify)
|
||
{
|
||
clear_sheets();
|
||
enable(-1);
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
TMSP_mask::TMSP_mask()
|
||
: TCalendar_mask("mr2200a")
|
||
{
|
||
TSheet_field& sf = sfield(F_ARTICOLI);
|
||
sf.set_append(FALSE);
|
||
|
||
for (short l = 0; l < 4; l++)
|
||
_livelli.set_sheetcolumn(sf, F_LIV1+l, l+1);
|
||
|
||
TConfig ini(CONFIG_DITTA, "mg");
|
||
if (!ini.get_bool("GESDEPOSITI"))
|
||
{
|
||
sf.delete_column(F_DEPOSITO);
|
||
sf.sheet_mask().hide(F_DEPOSITO);
|
||
}
|
||
if (!ini.get_bool("GESMULTIMAG"))
|
||
{
|
||
sf.sheet_mask().disable(F_MAGAZZINO);
|
||
}
|
||
|
||
if (!ini.get_bool("GESTIMPIANTI", "mr"))
|
||
{
|
||
hide(F_IMPIANTO);
|
||
sf.delete_column(F_CODIMP);
|
||
sf.sheet_mask().hide(F_CODIMP);
|
||
sf.sheet_mask().hide(F_DESCIMP);
|
||
}
|
||
sfield(F_LINEE).disable();
|
||
// sfield(F_TESTE).disable();
|
||
|
||
load_profile();
|
||
}
|
||
|
||
|
||
void TMSPCheck_mask::go_top()
|
||
{
|
||
gopos(2,1);
|
||
if (move_to(FC_UP))
|
||
if (move_to(FC_UP))
|
||
fill_mask();
|
||
fix_actual_pos();
|
||
}
|
||
|
||
void TMSPCheck_mask::gopos_mainmask()
|
||
{
|
||
TSheet_field &sf=_main_mask->sfield(F_ARTICOLI);
|
||
int curr_row=last_row();
|
||
while (sf.cell_disabled(curr_row,F_BUCKET1-FIRST_FIELD) )
|
||
curr_row++;
|
||
|
||
sf.select(curr_row,TRUE);
|
||
_main_mask->set_focus_field(sf.dlg());
|
||
sf.set_focus_cell(curr_row, last_col()*2+F_BUCKET0);
|
||
}
|
||
|
||
TMSPCheck_mask::TMSPCheck_mask(TMSP_mask * main_mask, const char *m,TSheet_field * s):
|
||
TAutomask(m), _main_mask(main_mask) , _sheet(s)
|
||
{
|
||
_last_col=_last_row=_constr_row=-1;
|
||
go_top();
|
||
}
|
||
|
||
TMSPCheck_mask::TMSPCheck_mask(TMSP_mask * main_mask):
|
||
TAutomask("mr2200b.msk"), _main_mask(main_mask), _sheet(&main_mask->sfield(F_ARTICOLI))
|
||
{
|
||
_last_col=_last_row=_constr_row=-1;
|
||
go_top();
|
||
}
|
||
|
||
//valori di ritorno:
|
||
// 0 : nessun errore
|
||
// 1 : esistono modifiche
|
||
// 2 : esistono nuove proposta
|
||
// 4 : giacenza media superiore al voluto
|
||
// 8 : sotto stock
|
||
int TMSPCheck_mask::fill_mask(const bool show_fields)
|
||
{
|
||
int error=0;
|
||
if (_last_col==_col && _last_row==_row)
|
||
return error;
|
||
|
||
const bool is_constr=is_constraint(_row);
|
||
TToken_string &row=_sheet->row(_row);
|
||
|
||
long codcli ;
|
||
TCodice_articolo codart;
|
||
TString16 liv, mag, codimp, codlin, um;
|
||
_main_mask->msprow2codes(row,codcli,codart,liv,mag,codimp, codlin, um);
|
||
|
||
if (_last_row!=_row)
|
||
{
|
||
_constr_row=find_constraint(_row);
|
||
set(FC_RIGA,_row+1);
|
||
set(FC_CODCLI,codcli,TRUE);
|
||
set(FC_CODART,codart,TRUE);
|
||
set(FC_CODIMP,codimp,TRUE);
|
||
set(FC_CODLIN,codlin,TRUE);
|
||
set(FC_CODMAG,mag.left(3),TRUE);
|
||
set(FC_CODDEP,mag.mid(3),TRUE);
|
||
}
|
||
set(FC_BUCKET,_col);
|
||
TDate data_buck(_main_mask->get_date(F_DADATA));
|
||
data_buck += (_col)*_main_mask->days_per_bucket()-1;
|
||
set(FC_DATE2,_col==LAST_BUCKET ? "" : data_buck.string());
|
||
data_buck -= _main_mask->days_per_bucket()-1;
|
||
set(FC_DATE1,_col==0 ? "" : data_buck.string());
|
||
|
||
set(FC_IS_VINCOLO,is_constr ? "X" : " ");
|
||
field(FC_IS_VINCOLO).on_hit();
|
||
if (!is_constr)
|
||
{
|
||
real art_per_buck(row.get(F_BUCKET0 + _col*2 - FIRST_FIELD));
|
||
set(FC_FINAL_VALUE,art_per_buck.string());
|
||
TMRP_line* new_article = _main_mask->find_propose(codcli, codart,liv,codimp,codlin,mag);
|
||
TMSP_line* old_article = _main_mask->find_article(codcli, codart,liv,codimp,codlin,mag);
|
||
|
||
real old_value=ZERO;
|
||
real new_value=ZERO;
|
||
if (old_article)
|
||
{
|
||
old_value=old_article->qta(_col);
|
||
}
|
||
if (new_article)
|
||
{
|
||
TMRP_time t(data_buck,0,"","");
|
||
TMRP_record& mrprec = new_article->record(t);
|
||
new_value=mrprec.sched_receipts();
|
||
if (new_value > ZERO)
|
||
error|=2;
|
||
}
|
||
set(FC_STARTING_VALUE,old_value.string());
|
||
set(FC_PROPOSED_VALUE,new_value.string());
|
||
show(FC_PROPOSED_VALUE,!new_value.is_zero());
|
||
show(FC_STARTING_VALUE,!old_value.is_zero());
|
||
if (old_value != art_per_buck)
|
||
error|=1;
|
||
// mostra i campi
|
||
hide(FC_GIAC);
|
||
hide(FC_UNDERSTOCK);
|
||
}
|
||
if (_constr_row>=0)
|
||
{
|
||
// calcola il sotto stock
|
||
real stock(_sheet->cell(_constr_row,F_BUCKET0 + _col*2 - FIRST_FIELD));
|
||
bool stockbreak=stock<ZERO;
|
||
bool overgiac=FALSE;
|
||
set(FC_GIAC,stock.string());
|
||
stock=-stock;
|
||
set(FC_UNDERSTOCK,stock.string());
|
||
show(FC_GIAC, !stockbreak);
|
||
show(FC_UNDERSTOCK, stockbreak);
|
||
error|=stockbreak ? 8 : 0;
|
||
// calcola i giorni di permanenza
|
||
stock=-stock;
|
||
real giorni=ZERO;
|
||
if (!stockbreak)
|
||
{
|
||
int bucket=0;
|
||
int buck_days = _main_mask->days_per_bucket();
|
||
real prev_stock(_sheet->cell(_constr_row,F_BUCKET0 + 2*_col - 1 - FIRST_FIELD));
|
||
real delivery(_sheet->cell(_constr_row-1,F_BUCKET0 + 2*_col - FIRST_FIELD));
|
||
stock=stock-prev_stock+delivery;
|
||
if (stock > ZERO)
|
||
{
|
||
real residuo=stock;
|
||
while (residuo > ZERO && (_col + bucket)<LAST_BUCKET)
|
||
{
|
||
delivery = _sheet->cell(_constr_row-1,F_BUCKET0 + 2*_col + bucket - FIRST_FIELD);
|
||
if (delivery < prev_stock)
|
||
{
|
||
prev_stock-=delivery;
|
||
delivery=ZERO;
|
||
} else {
|
||
delivery-=prev_stock;
|
||
prev_stock=ZERO;
|
||
}
|
||
residuo-= delivery;
|
||
if (residuo < ZERO) residuo=ZERO;
|
||
giorni+= residuo;
|
||
bucket++;
|
||
}
|
||
giorni = buck_days*giorni / stock;
|
||
const int maxdays(_main_mask->get_int(F_MAXGIORNIGIAC));
|
||
overgiac=(giorni.integer() > maxdays);
|
||
error|=overgiac ? 4 : 0;
|
||
}
|
||
}
|
||
set(FC_GIORNIGIAC,giorni.string());
|
||
set(FC_OVERGIORNIGIAC,giorni.string());
|
||
show(FC_GIORNIGIAC, !overgiac);
|
||
show(FC_OVERGIORNIGIAC,overgiac);
|
||
}
|
||
|
||
return error;
|
||
}
|
||
|
||
void TMSPCheck_mask::fix_actual_pos()
|
||
{
|
||
_last_col=_col;
|
||
_last_row=_row;
|
||
}
|
||
|
||
void TMSPCheck_mask::gopos(int row, int col)
|
||
{
|
||
_row=row;
|
||
_col=col;
|
||
fill_mask();
|
||
fix_actual_pos();
|
||
}
|
||
|
||
|
||
bool TMSPCheck_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{
|
||
if (e==fe_button)
|
||
{
|
||
const int dlg=o.dlg();
|
||
bool redo=TRUE;
|
||
const TString4 old_movefilter(get(FC_MOVEFILTER));
|
||
const TString4 new_movefilter(get_int(FC_FINDFILTER) & 1 ? "" : "C");
|
||
switch (dlg)
|
||
{
|
||
case FC_UP_BAD:
|
||
set(FC_MOVEFILTER,new_movefilter);
|
||
if (redo = move_to(FC_UP))
|
||
_col = LAST_BUCKET+1;
|
||
case FC_LEFT_BAD:
|
||
set(FC_MOVEFILTER,new_movefilter);
|
||
while (redo)
|
||
{
|
||
while (move_to(FC_LEFT))
|
||
{
|
||
int err=fill_mask() ;
|
||
fix_actual_pos();
|
||
if (err & get_int(FC_FINDFILTER))
|
||
{
|
||
set(FC_MOVEFILTER,old_movefilter);
|
||
return TRUE;
|
||
}
|
||
}
|
||
if (redo = move_to(FC_UP))
|
||
_col = LAST_BUCKET+1;
|
||
}
|
||
message_box("Ricerca terminata");
|
||
break;
|
||
|
||
case FC_DOWN_BAD:
|
||
set(FC_MOVEFILTER,new_movefilter);
|
||
if (redo = move_to(FC_DOWN))
|
||
_col = -1;
|
||
case FC_RIGHT_BAD:
|
||
set(FC_MOVEFILTER,new_movefilter);
|
||
while (redo)
|
||
{
|
||
while (redo && move_to(FC_RIGHT))
|
||
{
|
||
int err=fill_mask() ;
|
||
fix_actual_pos();
|
||
if (err & get_int(FC_FINDFILTER))
|
||
{
|
||
set(FC_MOVEFILTER,old_movefilter);
|
||
return TRUE;
|
||
}
|
||
}
|
||
if (redo = move_to(FC_DOWN))
|
||
_col = -1;
|
||
}
|
||
message_box("Ricerca terminata");
|
||
break;
|
||
|
||
default:
|
||
move_to(dlg);
|
||
fill_mask();
|
||
fix_actual_pos();
|
||
}
|
||
set(FC_MOVEFILTER,old_movefilter);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
int TMSPCheck_mask::find_constraint(int row)
|
||
{
|
||
while (row >=0 )
|
||
{
|
||
if (is_constraint(row))
|
||
return row;
|
||
row--;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
bool TMSPCheck_mask::is_constraint(int row)
|
||
{
|
||
return (row > 0
|
||
&& _sheet->cell_disabled(row, F_BUCKET1-FIRST_FIELD)
|
||
&& _sheet->cell_disabled(row-1, F_BUCKET1-FIRST_FIELD));
|
||
}
|
||
bool TMSPCheck_mask::is_article(int row)
|
||
{
|
||
return !_sheet->cell_disabled(row, F_BUCKET1-FIRST_FIELD);
|
||
}
|
||
|
||
bool TMSPCheck_mask::move_to(int dlg)
|
||
{
|
||
const bool constraints=*get(FC_MOVEFILTER)!='A';
|
||
const bool articles=*get(FC_MOVEFILTER)!='C';
|
||
|
||
CHECK(constraints||articles, "N'do cazzo muovo?");
|
||
const int max_rows=_sheet->items();
|
||
bool skip_row=TRUE;
|
||
int old_row=_row;
|
||
switch (dlg)
|
||
{
|
||
case FC_DOWNLEFT:
|
||
case FC_DOWNRIGHT:
|
||
case FC_DOWN:
|
||
while (_row < max_rows-1)
|
||
{
|
||
_row++;
|
||
if (constraints && is_constraint(_row) || articles && is_article(_row))
|
||
break;
|
||
}
|
||
if (dlg==FC_DOWNRIGHT) _col++;
|
||
if (dlg==FC_DOWNLEFT) _col--;
|
||
break; // se non sono sulla linea giusta, torno indietro
|
||
case FC_UPRIGHT:
|
||
case FC_UPLEFT:
|
||
case FC_UP:
|
||
while (_row >0 )
|
||
{
|
||
_row--;
|
||
if (constraints && is_constraint(_row) || articles && is_article(_row))
|
||
break;
|
||
}
|
||
if (dlg==FC_UPRIGHT) _col++;
|
||
if (dlg==FC_UPLEFT) _col--;
|
||
break;
|
||
case FC_LEFT:
|
||
_col--;
|
||
break;
|
||
case FC_RIGHT:
|
||
_col++;
|
||
break;
|
||
}
|
||
if (!((articles && is_article(_row) ) || (constraints && is_constraint(_row))))
|
||
_row=old_row;
|
||
check_pos_range();
|
||
if (_last_col==_col && _last_row==_row)
|
||
return FALSE;
|
||
return TRUE;
|
||
}
|
||
|
||
void TMSPCheck_mask::check_pos_range()
|
||
{
|
||
int max_cols=min(get_int(FC_MAXBUCK2CHECK),LAST_BUCKET);
|
||
if (max_cols==0) max_cols=LAST_BUCKET;
|
||
|
||
const bool constraints=*get(FC_MOVEFILTER)!='A';
|
||
const int max_rows=_sheet->items();
|
||
if (_row>=max_rows) _row=max_rows-1;
|
||
if (_row< (constraints ? 1 : 2) ) _row++;
|
||
if (_col>=max_cols) _col=max_cols;
|
||
if (_col<1) _col=0;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
//
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TCRPCheck_mask::TCRPCheck_mask(TMSP_mask * main_mask):
|
||
TMSPCheck_mask(main_mask, "mr2200c.msk", & main_mask->sfield(F_LINEE))
|
||
{
|
||
}
|
||
|
||
void TCRPCheck_mask::check_pos_range()
|
||
{
|
||
const bool constraints=*get(FC_MOVEFILTER)!='A';
|
||
const int max_rows=_sheet->items();
|
||
if (_row>=max_rows) _row=max_rows-1;
|
||
if (_row< (constraints ? 0 : 1) ) _row++;
|
||
if (_col>=LAST_BUCKET) _col=LAST_BUCKET-1;
|
||
if (_col<1) _col=1;
|
||
}
|
||
|
||
bool TCRPCheck_mask::is_constraint(int row)
|
||
{
|
||
return (row > 0
|
||
&& !_sheet->cell_disabled(row, F_LBUCKET1-FIRST_FIELD)
|
||
&& _sheet->cell_disabled(row-1, F_LBUCKET1-FIRST_FIELD));
|
||
}
|
||
|
||
bool TCRPCheck_mask::is_article(int row)
|
||
{
|
||
return (*_sheet->row(row).get(F_CODARTCRP-FIRST_FIELD)>' ');
|
||
}
|
||
|
||
int TCRPCheck_mask::find_constraint(int row)
|
||
{
|
||
const int max=max_rows();
|
||
while (row < max)
|
||
{
|
||
if (is_constraint(row))
|
||
return row;
|
||
row++;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int TCRPCheck_mask::fill_mask(const bool show_fields)
|
||
{
|
||
int error=0;
|
||
if (_last_col==_col && _last_row==_row)
|
||
return error;
|
||
|
||
const bool is_constr=is_constraint(_row);
|
||
TSheet_field& sf = _main_mask->sfield(F_LINEE);
|
||
TToken_string &row=sf.row(_row);
|
||
|
||
long codcli ;
|
||
TCodice_articolo codart;
|
||
TString16 liv, codimp, codlin, um;
|
||
_main_mask->crprow2codes(row,codimp, codlin,codcli,codart,liv,um);
|
||
|
||
if (_last_row!=_row)
|
||
{
|
||
_constr_row=find_constraint(_row);
|
||
set(FC_RIGA,_row+1);
|
||
set(FC_CODIMP,codimp);
|
||
set(FC_CODLIN,codlin);
|
||
set(FC_CODCLI,codcli);
|
||
set(FC_CODART,codart);
|
||
}
|
||
set(FC_BUCKET,_col);
|
||
TDate data_buck(_main_mask->get_date(F_DADATA));
|
||
data_buck += (_col)*_main_mask->days_per_bucket()-1;
|
||
set(FC_DATE2,data_buck.string());
|
||
data_buck -= _main_mask->days_per_bucket()-1;
|
||
set(FC_DATE1,data_buck.string());
|
||
|
||
set(FC_IS_VINCOLO,is_constr ? "X" : " ");
|
||
field(FC_IS_VINCOLO).on_hit();
|
||
if (!is_constr)
|
||
{
|
||
// articolo
|
||
real art_load(_sheet->cell(_row ,F_LBUCKET1 + _col - 1 - FIRST_FIELD));
|
||
set(FC_ART_LOAD,art_load.string());
|
||
}
|
||
if (_constr_row>=0)
|
||
{
|
||
// vincolo
|
||
real load(_sheet->cell(_constr_row ,F_LBUCKET1 + _col - 1 - FIRST_FIELD));
|
||
set(FC_LOAD,load.string());
|
||
show(FC_LOAD,load>ZERO);
|
||
real capacity(_sheet->cell(_constr_row -1 ,F_LBUCKET1 + _col - 1 - FIRST_FIELD));
|
||
const bool positive=capacity>ZERO;
|
||
set(FC_CAPACITY,capacity.string());
|
||
show(FC_CAPACITY,positive);
|
||
capacity-=load;
|
||
const bool out=capacity<ZERO;
|
||
set(FC_CAPACITY_REM,capacity.string());
|
||
if (out)
|
||
{
|
||
capacity=-capacity;
|
||
error|=8;
|
||
}
|
||
set(FC_CAPACITY_OUT,capacity.string());
|
||
show(FC_CAPACITY_REM,positive && !out);
|
||
show(FC_CAPACITY_OUT,positive && out);
|
||
}
|
||
return error;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Applicazione principale
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TMSP_app : public TSkeleton_application
|
||
{
|
||
protected:
|
||
virtual void main_loop();
|
||
virtual bool firm_change_enabled() const { return FALSE; }
|
||
|
||
public:
|
||
TMSP_app() {}
|
||
};
|
||
|
||
|
||
void TMSP_app ::main_loop()
|
||
{
|
||
open_files(LF_TABCOM, LF_TAB, LF_DOC, LF_RIGHEDOC, 0);
|
||
open_files(LF_CLIFO, LF_CFVEN, LF_OCCAS, LF_INDSP, LF_CONDV, 0);
|
||
open_files(LF_MAG, LF_ANAMAG, LF_DIST, LF_RDIST, 0);
|
||
|
||
TMSP_mask m;
|
||
TConfig prassid(CONFIG_DITTA, "ve"); // apre il file di configurazione della ditta corrente
|
||
if (prassid.get_bool("GES", NULL, A_LISTINI))
|
||
{
|
||
m.enable(F_CATVEN_CV,prassid.get_bool("GESLISCV"));
|
||
}
|
||
else
|
||
{
|
||
m.disable(F_TIPOCV);
|
||
m.disable(F_CATVEN_CV);
|
||
}
|
||
while (m.run()!=K_QUIT) ;
|
||
}
|
||
|
||
int mr2200(int argc, char* argv[])
|
||
{
|
||
TMSP_app a;
|
||
a.run(argc, argv, "Master Schedule Planning");
|
||
return 0;
|
||
}
|
||
|