// *******************************
// LIBRERIA  di magazzino 
// *******************************
#ifndef __MGLIB_H 
#define __MGLIB_H

#ifndef __MASK_H
#include <mask.h>
#endif 

#ifndef __MULTIREC_H
#include <multirec.h> 
#endif

#ifndef __FORM_H
#include <form.h>
#endif

#ifndef __ANAMAG_H 
#include "../mg/anamag.h" 
#endif

#ifndef __UMART_H 
#include "../mg/umart.h"
#endif

#ifndef __CODCORR_H 
#include "../mg/codcorr.h"
#endif

#ifndef __DESLIN_H 
#include "../mg/deslin.h"
#endif

#ifndef __MAG_H 
#include "../mg/mag.h"
#endif

#ifndef __STOMAG_H 
#include "../mg/stomag.h"
#endif

#ifndef __MOVMAG_H 
#include "../mg/movmag.h"
#endif

#ifndef __RMOVMAG_H 
#include "../mg/rmovmag.h"
#endif

// campi comuni alla maschere di magazzino
typedef enum
{
  riga_dadocumento = 'D', // derivata da documento
  riga_automatica  = 'A', // generata da causale collegata
  riga_nongenerata = ' '  // immissione diretta del mov.
} TTipo_rigamovmag;

typedef enum  
{
  valorizz_ultcos, 
  valorizz_mediacos, 
  valorizz_przlist, 
  valorizz_coststd, 
  valorizz_costmedio,
  valorizz_costmediopond,
  valorizz_FIFOa,
  valorizz_LIFOa, 
  valorizz_FIFO,
  valorizz_LIFO,
  valorizz_FIFOr,
  valorizz_LIFOr
} TTipo_valorizz;

extern const char* const nome_valorizz(TTipo_valorizz tipo);

const char* const zero_fields[] = 
{ 
  MAG_GIAC, MAG_PRODFIN, MAG_INCL, MAG_ACL, MAG_NLABEL, 
  MAG_RIM, MAG_VALRIM, MAG_ACQ, MAG_VALACQ, MAG_ENT, MAG_VALENT, 
  MAG_VEN, MAG_VALVEN, MAG_USC, MAG_VALUSC, MAG_ORDF, MAG_VALORDF, 
  MAG_ORDC, MAG_VALORDC, MAG_SCARTI, MAG_VALSCARTI, MAG_PRODCOMP,
  "USER1", "USERVAL1", "USER2", "USERVAL2", "USER3", "USERVAL3", 
  "USER4", "USERVAL4", "USER5", "USERVAL5", "USER6", "USERVAL6", 
  NULL
};

class TArticolo : public TMultiple_rectype
{          
protected:
  TString _codice;
  // la get_str supporta anche la sintassi:
  //     #LF->fieldname              
  //  oppure:
  //     #LF_par1->fieldname              
  // dove:
  //   LF = numero logico del sottofile collegato (LF_UMART, LF_DESLIN, LF_CODCORR
  //   par1 = chiave dell'indice del file collegato
  //          se par1 comincia con '#', esso indica il numero progressivo nell'indice 
  //          (es:#49_#1: prima unit� di misura)
  //   fieldname = nome del campo nel file collegato
  virtual const TString & get_str(const char* fieldname) const ;
  virtual void set_body_key(TRectype & rowrec); 

public:

  virtual int read(const char * cod, word op = _isequal, word lockop = _nolock);
  virtual int read(TRectype & rec, word op = _isequal, word lockop = _nolock);

  virtual TObject* dup() const { return new TArticolo(codice()); }

  // restituisce il codice (e' un reference "sicuro" ad una stringa interna)
  const TString& codice() const;
  const TString& descrizione(const char * lingua = NULL) const;

  bool unlock() ;
  bool lock_and_prompt(word lockop = _testandlock);
  void update_ultcosti(const real& costo, const TDate& data, long numreg, int numrig);
  void set_prezzo_vendita(const real& prezzo, const char* um = NULL);

  int find_um(const char * um, int from = 0) const;
  int find_deslin(const char * deslin, int from = 0) const;
  int find_codcorr(const char * codcorr, int from = 0) const;

	bool is_first_um(const char * ums) const { return um().rows() > 0 ? find_um(ums) == 1: false; }
	const char * first_um() const { return um().rows() > 0 ? um()[1].get(UMART_UM) : ""; }

  static void round_um(real& v, const char* to_um);
  real convert_to_um(const real& v, const TString& to_um, const TString& from_um = EMPTY_STRING, bool arrotonda = true);

  TRecord_array & um() const { return body(LF_UMART); }
  TRecord_array & deslin() const { return body(LF_DESLIN); }
  TRecord_array & codcorr() const { return body(LF_CODCORR); }

	TArticolo(const char* codice = NULL);
  TArticolo(const TRectype& rec);
	virtual ~TArticolo() {}
};  

class TArticolo_giacenza : public TArticolo
{          
  int _anno_mag, _anno_sto;
  
protected:
  // la get_str supporta anche la sintassi:
  //     #LF->fieldname              
  //     #LF_par1->fieldname              
  //     #LF_par1_par2->fieldname              
  //     #LF_par1_par2_par3->fieldname              
  // dove:
  //   LF = numero logico del sottofile collegato (LF_UMART, LF_DESLIN, LF_CODCORR
  //   par1, par2, par3 = varie parti della chiave dell'indice del file collegato
  //          il numero di queste parti ed il loro valore dipende dal file collegato
  //          se parX comincia per # rappresenta il numero progressivo nell'indice 
  //   fieldname = nome del campo nel file collegato
  virtual const TString & get_str(const char* fieldname) const ;
  virtual void set_body_key(TRectype & rowrec);
  void set_anno_mag (int anno = 0);
	void set_anno_mag (const char * anno) { set_anno_mag(atoi(anno)); }
  void set_anno_sto (int anno = 0);
  void set_anno_sto (const char * anno) { set_anno_sto(atoi(anno)); }
  void reset_anno_mag () { set_anno_mag();}
  void reset_anno_sto () { set_anno_sto();}
  bool is_last_esercizio(int annoes) const;
	bool is_last_esercizio(const char* annoes) const { return is_last_esercizio(atoi(annoes));}
  bool is_deletable(const TRectype& mag) const;

	void copia_valori(TRectype& rec, const char * catven, const char * codlist, real & przlist);
	void copia_storico(TRecord_array& nrstorico,  int annoes, const char * codmag, int annoprec, real rim, real valrim, const char * catven, const char * codlist, real & przlist);
  void add_storico(TRecord_array& nrstorico, int annoes,const char * codmag, const real & qta, const real & prz, const char * catven, const char * codlist, real & przlist);

	void copia_storico(TRecord_array& nrstorico,  const char * annoes, const char * codmag, const char * annoprec, real rim, real valrim, const char * catven, const char * codlist, real & przlist) {	copia_storico(nrstorico, atoi(annoes), codmag, atoi(annoprec), rim, valrim, catven, codlist, przlist); }
	void add_storico(TRecord_array& nrstorico, const char * annoes,const char * codmag, const real & qta, const real & prz, const char * catven, const char * codlist, real & przlist) { add_storico(nrstorico, atoi(annoes), codmag, qta, prz, catven, codlist, przlist); }

public:

  virtual TObject* dup() const { return new TArticolo_giacenza(codice()); }
  virtual void zero(char c = '\0');

  int find_mag(TRecord_array& rmag, const char * codmag = NULL, const char * livello = NULL, int from = 0) const ;
  int find_storico(TRecord_array& rsto, const char * codmag = NULL, int from = 0) const;
  int find_mag(int annoes, const char * codmag = NULL, const char * livello = NULL, int from = 0) const ;
  int find_storico(int annoesrif, const char * codmag = NULL, int from = 0) const;
	int find_mag(const char * annoes, const char * codmag = NULL, const char * livello = NULL, int from = 0) const { return find_mag(atoi(annoes), codmag, livello, from); }
	int find_storico(const char * annoesrif, const char * codmag = NULL, int from = 0) const { return find_storico(atoi(annoesrif), codmag, from); }

  TRecord_array & mag(int annoes) const;
	TRecord_array & mag(const char * annoes) const { return mag(atoi(annoes));}
  TRecord_array & storico(int annoesrif) const;
  TRecord_array & storico(const char * annoesrif) const { return mag(atoi(annoesrif));}
  
  // calcola disponibilit� (anche complessiva su pi� depositi o magazzini)
  // solo_giac indica di fare il calcolo della sola giacenza
  real disponibilita(const char * annoes, const char * codmag, const char * livello, bool solo_giac=FALSE) const;
  // La seguente funzione riporta le rimanenze finali dell'esercizio oldes come
  // rimanenze iniziali dell'esercizio newes, valorizzando secondo il tipo passato
  // Si suppone che i saldi siano coerenti con i movimenti (effettuare una rebuild_balances()
  // di oldes.
	bool riporta_saldi(int oldes, int newes, const TTipo_valorizz tipo, 
                     const char* catven, const char* codlis, bool save_to_disk = true);

  // Identica alla precedente con gli esercizi passati come stringhe
  bool riporta_saldi(const char * oldes, const char* newes, const TTipo_valorizz tipo, 
                     const char * catven ,const char * codlist, bool save_to_disk = true) {	return riporta_saldi(atoi(oldes), atoi(newes), tipo, catven, codlist, save_to_disk);}
  bool azzera_saldi(int codes, int codespre, bool save_to_disk = true);
  bool azzera_saldi(const char* codes, bool save_to_disk = true) { return azzera_saldi(atoi(codes), save_to_disk); }
  
	// valorizzazioni
  real ultimo_costo(int  annoes) const;
  real media_costi(int annoes) const;
  real prezzo_listino(int annoes, const char * catven ,const char * codlist) const;
  real costo_standard(int annoes) const;
  real costo_medio(int annoes, const char * codmag, const char * livello) const; 
  real costo_mediopond(int annoes, const char * codmag, const char * livello) const; 
  real LIFO_annuale(int annoes, const char * codmag, const char * livello,
            bool giacenza_effettiva = true, bool valorizza_componenti = true) const;
  real FIFO_annuale(int annoes, const char * codmag, const char * livello,
            bool giacenza_effettiva = true, bool valorizza_componenti = true) const;
  real LIFO(int annoes, const char * codmag, const char * livello,
            bool giacenza_effettiva = true, bool valorizza_componenti = true) const;
  real FIFO(int annoes, const char * codmag, const char * livello,
            bool giacenza_effettiva = true, bool valorizza_componenti = true) const;
  real LIFO_ragionieristico(int annoes, const char * codmag, const char * livello,
                            bool giacenza_effettiva = true, bool valorizza_componenti = true) const;
  real FIFO_ragionieristico(int annoes, const char * codmag, const char * livello,
                            bool giacenza_effettiva = true, bool valorizza_componenti = true) const;

	real ultimo_costo(const char * annoes) const { return ultimo_costo(atoi(annoes));}
	real media_costi(const char * annoes) const { return media_costi(atoi(annoes));}
	real prezzo_listino(const char * annoes, const char * catven ,const char * codlist) const { return prezzo_listino(atoi(annoes), catven ,codlist);}
	real costo_standard(const char * annoes) const { return costo_standard(atoi(annoes));} 
	real costo_medio(const char * annoes, const char * codmag, const char * livello) const { return costo_medio(atoi(annoes), codmag, livello); }
	real costo_mediopond(const char * annoes, const char * codmag, const char * livello) const { return costo_mediopond(atoi(annoes), codmag, livello); }
  real LIFO_annuale(const char * annoes, const char * codmag, const char * livello,
										bool giacenza_effettiva = true, bool valorizza_componenti = true) const { return LIFO_annuale(atoi(annoes), codmag, livello, giacenza_effettiva, valorizza_componenti); }
  real FIFO_annuale(const char * annoes, const char * codmag, const char * livello,
										bool giacenza_effettiva = true, bool valorizza_componenti = true) const { return FIFO_annuale(atoi(annoes), codmag, livello, giacenza_effettiva, valorizza_componenti);}
  real LIFO(const char * annoes, const char * codmag, const char * livello,
						bool giacenza_effettiva = true, bool valorizza_componenti = true) const { return LIFO(atoi(annoes), codmag, livello, giacenza_effettiva, valorizza_componenti ); }
  real FIFO(const char * annoes, const char * codmag, const char * livello,
						bool giacenza_effettiva = true, bool valorizza_componenti = true) const { return FIFO(atoi(annoes), codmag, livello, giacenza_effettiva, valorizza_componenti); }
  real LIFO_ragionieristico(const char * annoes, const char * codmag, const char * livello,
														bool giacenza_effettiva = true, bool valorizza_componenti = true) const { return LIFO_ragionieristico(atoi(annoes), codmag, livello, giacenza_effettiva, valorizza_componenti);}
  real FIFO_ragionieristico(const char * annoes, const char * codmag, const char * livello,
														bool giacenza_effettiva = true, bool valorizza_componenti = true) const { return FIFO_ragionieristico(atoi(annoes), codmag, livello, giacenza_effettiva, valorizza_componenti );}

	void agg_storicoLIFO (int annoes, const char * codmag, bool giac_eff, bool valorizza_componenti, const char * catven, const char * codlist, real & przlist) ;
  void agg_storicoFIFO (int annoes, const char * codmag, bool giac_eff, bool valorizza_componenti, const char * catven, const char * codlist, real & przlist) ;
  void agg_storico(int annoes, const char * codmag, bool giac_eff, bool valorizza_componenti, const real& val, const char * catven, const char * codlist, real & przlist) ;
	
	void agg_storicoLIFO (const char * annoes, const char * codmag, bool giac_eff, bool valorizza_componenti, const char * catven, const char * codlist, real & przlist) {	agg_storicoLIFO (atoi(annoes), codmag, giac_eff, valorizza_componenti, catven, codlist, przlist); }
	void agg_storicoFIFO (const char * annoes, const char * codmag, bool giac_eff, bool valorizza_componenti, const char * catven, const char * codlist, real & przlist) { agg_storicoFIFO (atoi(annoes), codmag, giac_eff, valorizza_componenti, catven, codlist, przlist); }
	void agg_storico(const char * annoes, const char * codmag, bool giac_eff, bool valorizza_componenti, const real& val, const char * catven, const char * codlist, real & przlist) { return agg_storico(atoi(annoes), codmag, giac_eff, valorizza_componenti, val, catven, codlist, przlist);}
                              
	real giacenza_corretta(const TRectype & rec , bool giacenza_effettiva, bool valorizza_componenti) const;

  void put_ultimo_costo(const real& costo, const TDate& data);
  void put_costo_standard(const real& costo);

  real giacenza_anno(const char* codmag, const char* livello, int anno) const;
  real scorta_minima(const char* codmag, const char* livello, int anno=0, bool liv_riordino=FALSE) const;
  long lead_time(const char* codmag, const char* livello, int anno=0) const;

  TArticolo_giacenza(const char* codice = NULL);
  TArticolo_giacenza(const TRectype& rec);
  virtual ~TArticolo_giacenza() {}
};  

class TArticolo_giacenza_data : public TArticolo_giacenza
{ 
protected:
	virtual int write(TBaseisamfile&) const { return _iseof; }
  virtual int rewrite(TBaseisamfile&) const { return _iseof; }
  virtual int remove(TBaseisamfile&) const { return _iseof; }

public:
  void al(const TDate& data, const char* codmag = NULL, const char* livello = NULL,
          TTipo_valorizz tipo = valorizz_costmedio, const char* catven = NULL, const char* codlis = NULL);
  
  TArticolo_giacenza_data(const char* codice = NULL);
  TArticolo_giacenza_data(const TRectype& rec);
};

class TArticolo_giacenza_loadable : public TArticolo_giacenza_data
{ 
public:
  void load(TIsamtempfile& f);
  TArticolo_giacenza_loadable(const char* codice = NULL);
  TArticolo_giacenza_loadable(const TRectype& rec);
};

TArticolo & cached_article(const char * codart);
TArticolo_giacenza & cached_article_balances(const char * codart);

// *******************************
// LIBRERIA DI utility del magazzino
// *******************************
#define MAX_COD_LEVELS 10
  
class TR_automa;
  
class TMetachar : public TObject
{
  TR_automa * _au;
  TString _language;

protected:
  void set_language(const char * language); // setta l'automa che ricosce il linguaggio passato
  void add_tran(int statenum,unsigned char symbol,int next);// aggiunge le transizioni all'automa

public:
  // @cmember restituisce la lunghezza massima della stringa che soddisfa il formato passato
  static int maxstrlen(const char * format);

  const char * language() const;  // restituisce la stringa di metacaratteri del linguaggio riconosciuto
  bool recognized(const char * pattern);

  bool has_opzchars(const char * pattern);
  bool has_mandchars(const char * pattern);

  const char* const mand_chars() {return "0LA&"; }   
  const char* const opz_chars() {return "#9?ac"; }     

  TMetachar(const char * str);
  TMetachar();
  virtual ~TMetachar();
};

class TCodice_livelli : public TObject
{
  long _last_firm;

  bool        _autoinsert[MAX_COD_LEVELS];
  bool        _codiceadata[MAX_COD_LEVELS];
  int         _code_length[MAX_COD_LEVELS];
  TString     _name[MAX_COD_LEVELS];
  TString     _picture[MAX_COD_LEVELS];
  int         _last_level;
  TDecoder    *_gruppi;

protected:
  bool _lev_enabled;
  TArray _metachars;

  void load(bool e, const char *tabcod,const char *tabgrp);  
  void add_metachar(int lev);
  
  void update_firm();
  void test_firm();
    
public:
  // Ritorna il numero massimo di livelli possibili
  virtual inline int max_levels() const {return MAX_COD_LEVELS;}
  // Ritorna il numero di livelli abilitati
  int last_level() const { return enabled() ? _last_level : 0; }
  // Abilita la gestione dei livelli 
  void enable(bool on=true) ; 
  // Ritorna se la gestione dei livelli � abilitata
  const bool enabled() const ; 
  // Ritorna se il livello specificato � abilitato
  const bool enabled(int levnum) const ; 
  // Ritorna il nome (descrizione) di quel livello
  const TString & name(int levnum) const ;   
  // Ritorna la stringa di picture per i codici gruppo di quel livello
  const TString & picture(int levnum) const;
  // Ritorna la lunghezza dei codici gruppo di quel livello
  const int code_length(int levnum) const ;      
  // Ritorna la posizione iniziale del codice gruppo di quel livello
  const int code_start(int levnum) const ;      
  // Ritorna la lunghezza del codice compatto fino a quel livello
  const int packed_length(int levnum) const ;    
  // Restituisce se esiste il gruppo dato il codice (compatto e non)
  const int group_search(const char * code, int levnum) const;
  const int group_search_packed(const char * packed_code, int levnum) const;
  // Restituisce la descrizione del gruppo dato il codice (compatto e non)
  const TString & group_descr(const char * code, int levnum) const; 
  const TString & group_descr_packed(const char * packed_code, int levnum) const; 

  
  // Setta il prompt del campo sulla maschera
  void set_mask_field(TMask &m,int field, int lev) const;
  // Setta i prompt dei campi livelli di codice sulla maschera
  void set_mask_fields(TMask &m,int firstfield) const;
  // Setta la colonna del campo livello codice di uno sheet in base alle abilitazioni 
  void set_sheetcolumn(TSheet_field &fld_righe,int field, int lev) const;
  // Setta le colonne dei campi livello codice di uno sheet in base alle abilitazioni 
  void set_sheet_columns(TSheet_field &sht, short dlg) const;
  // costruisce il codice compatto e viceversa  
  void pack_maskgrpcodes(TString & pc, const TMask & m, int field, int level) const;
  void pack_grpcode(TString & pc, const TString &codlev, const int levnum) const;     // Inserisce il codice del gruppo del livello levnum in pc
  const TString& unpack_grpcode(const TString & pc, const int levnum) const; // Estrae il codice del gruppo del livello levnum da pc
  // costruisce il codice della tabella di decodifica dei livelli
  TString build_tabcode(const TString & code, const int levnum) const ;
  TString build_tabcode_packed(const TString & pcode, const int levnum) const ;

  // Restituisce il formato previsto per il codice (default==ultimo livello)
  const char* code_format(int levnum=-1) const ; 
  // Restituisce se <p codepart> e' riconosciuto come codice articolo (default==ultimo livello)
  bool fit_to_format(const char *codepart, int levnum=-1) const ;
  // Ritorna se il livello � abilitato all'autoinserimento
  const bool autoinsert (int levnum) const ; 
  // Tenta l'autoinserimento; Ritorna se l'operazione ha avuto successo
  const bool autoinsert(int levnum, TString & newcode) const;
  const bool autoinsert(int levnum, TMask_field & fld) const;
  // Ritorna se il codice del livello rappresenta una data
  const bool codiceadata(int levnum) const ; 

/*  bool has_mandchars(const char * pattern);
  bool has_opzchars(const char * pattern);
  const char * opz_chars();
  const char * mand_chars();*/

  virtual void init() pure;

  TCodice_livelli();          // costruttore
  virtual ~TCodice_livelli(); // distruttore
};


class TCodart_livelli : public TCodice_livelli
{
public:
  virtual inline int max_levels() const  {return 10;} 
  virtual void init();

  TCodart_livelli();  // costruttore
  virtual ~TCodart_livelli() ; // distruttore
};


class TCodgiac_livelli : public TCodice_livelli
{
public:
  virtual inline int max_levels() const  {return 4;} 
  virtual void init();

  TCodgiac_livelli();  // costruttore
  virtual ~TCodgiac_livelli() {}; // distruttore
};


// *********************
// classe che incapsula tutti i magazzini 
class TMagazzini : public TRecord_cache
{
  TString8 _stdmag, _stddep;
  TConfig *_mgconfig;
  long _last_firm;
  bool _gestmag ;
  bool _gestdep ;
  char _gestubi ;
  bool _gestmultimag;
private:
  void init();
  void test_firm() const;

public:
  const TString & standardmag() const 
    {test_firm() ; return _stdmag;} 
  const TString & standarddep() const 
    {test_firm() ; return _stddep;}   
  bool gestmag(bool verbose=FALSE) const ;
  bool gestdep() const ;
  bool gestubi_man() const  ;
  bool gestubi_tab() const ;
  bool gestmultimag() const ;

  TMagazzini();
  virtual ~TMagazzini();
};


// *********************
// classe che incapsula le causali di magazzino (record della tabella CAU)
typedef enum
{
  s_giac,
  s_acq,s_ent,
  s_ven,s_usc,
  s_ordc,s_ordf,
  s_acl,s_incl,
  s_prodc,s_prodf,
  s_rim,
  s_scart,
  s_label,
  s_user1,
  s_user2,
  s_user3,
  s_user4,
  s_user5,
  s_user6,
	s_dotin,
	s_dotod,
	s_dottm,
	s_consanno,
	s_consmese
} TTipo_saldomag; 

class TCausale_magazzino : public TRectype
{
public:
  const TString & codice() const {return get("CODTAB");}
  const TString & descr() const {return get("S0");}
  const TString & qta_doc() const {return get("S5");}
  char tipoprz() const {return get_char("S6");}
  char tipomov() const {return get_char("S7");}
  const TString & raggfisc() const {return get("S8");}
  const TString & caus_collegata() const {return get("S9");}
  int sgn(TTipo_saldomag fieldname) const;
  bool update_qta() const {return !get_bool("B1");}
  bool update_val() const {return !get_bool("B0");}
  bool update_ultcos() const  {return get_bool("B2");}
  bool esplodente() const {return get_bool("B3");}
  bool scarica_artprod() const {return get_bool("B4");}
  bool movimenta_sospesi() const {return get_bool("B5");}
  bool scarica_alternativi() const {return get_bool("B6");}
	bool aggiorna_clifo() const {return get_bool("B7");}
  const TString & default_magdep() const {return get("S10");}
  const char *default_mag() const {return get("S10").mid(0,3);}
  const char *default_dep() const {return get("S10").mid(3,2);}
  bool has_default_mag() const {return *default_mag() > ' '; }
  bool has_default_dep() const {return *default_dep() > ' '; }
  bool is_fiscale();
  TCausale_magazzino(const char * codice);
  TCausale_magazzino(const TRectype &r);
  virtual ~TCausale_magazzino() {}
};


TCausale_magazzino & cached_causale_magazzino(const char * codcaus);

class TSaldo_mag;
class TSaldo_mag_clifo;

// classe per la definizione dei movimenti di magazzino
// ( un movimento (testata+righe) == un oggetto TMov_mag )
class TMov_mag : public TMultiple_rectype
{
  int _annoes;     // codice esercizio del movimento
  TDate _datacomp;      // data di competenza
  TAssoc_array _saldi_mag;  
  TAssoc_array _saldi_mag_clifo; 

protected:
//  virtual void load_rows_file(int logicnum);
  virtual void set_body_key(TRectype & rowrec);
  virtual bool key_complete();
  virtual bool renum(); // rinumerazione ;

  // ************ gestione saldi
  // @member: aggiorna i saldi
  void add_saldi(const bool plus = true);
  // @member: effettua l'aggiornamento dei saldi relativi alle giacenze interessate al movimento
  bool update_balances(bool lock = true) ;
  // @member: effettua l'aggiornamento dei saldi di una giacenza
  void update_balances(TRectype & magrec, const TSaldo_mag & s) ;
  // @member: effettua l'aggiornamento dei saldi di una giacenza sulle gacenze per ciente/fornitore
  void update_balances_clifo(TRectype & clifomagrec, const TSaldo_mag_clifo & s);
// @member: effettua l'aggiornamento di un saldo di una giacenza
  void update_balance(TRectype & rec, const char * fieldname, const real& diff, int sgn) const;

  void giac_putkey(TRectype& mag, const TSaldo_mag & s);
	void giac_putkey_clifo(TRectype& clifomag, const TSaldo_mag_clifo & s);
  bool lock_anamag(const char *codart);
  bool unlock_anamag(const char *codart) ;
  virtual const char * codmag_rauto(int r) const { return NULL;}
  virtual const char * prezzo_rauto(int r) const { return NULL;}

  // aggiunge le righe automatiche e da esplosione 
  void  add_extrarows() const;
  // aggiunge le righe automatiche 
  bool  add_autorows() const;
  // aggiunge le righe da esplosione 
  bool  add_explrows() const;
public:
// IO ad alto livello
  virtual const char *get_next_key() ;
  virtual int remove(TBaseisamfile& f) const ;
  virtual void zero(char c = '\0');// azzeramento ;
	virtual int read(TBaseisamfile& f, word op = _isequal, word lockop = _nolock);
  virtual int write(TBaseisamfile& f) const ;
  virtual int rewrite(TBaseisamfile& f) const ;
  bool force_update_bal();
	TArticolo & articolo(int row) const { return cached_article(body()[row].get(RMOVMAG_CODART));}
	TArticolo_giacenza & articolo_giacenza(int row) const { return cached_article_balances(body()[row].get(RMOVMAG_CODART));}
  TCausale_magazzino& causale(int row) const;
    const TCausale_magazzino& causale(const char* cod = NULL) const;
	void renum_mov(const long numreg);

  
  // @member: effettua l'aggiornamento dei saldi di una giacenza
  void update_balances(TRectype& magrec, int numrig, bool plus = true);
	void update_balances_clifo(TRectype& cliforec, int numrig, bool plus = true);
  
  //
  int codice_esercizio(const TDate &d);

  // costruttori e distruttori
  TMov_mag();
  TMov_mag(long numreg);
  virtual ~TMov_mag();
  
};

bool rebuild_balances(int annoes,  
  const TTipo_valorizz tipo=valorizz_costmediopond, 
  const char* catven=NULL, 
  const char* codlis=NULL);

#define FORM_MAXGIACLEV 4 // numero di livelli giacenza nel form
#define FORM_MAXARTLEV 8 // numero di livelli codice nel form
#define UNKNOWN_NAME "-"

typedef enum {
  mg_normale,   // Codice o descrizione
  mg_ragg_fisc, // Raggr. Fiscale + Codice Articolo
  mg_cat_merc,  // Cat. Merceologica[1..3] + Codice Articolo
  mg_scat_merc  // Cat. Merceologica[1..5] + Codice Articolo  
} TTipo_ordinamento_mg;

class TForm_stampemg : public TForm 
{
  bool _permag;
  int _fromlivgiac,_tolivgiac,_fromlivart,_tolivart;
  TTipo_ordinamento_mg _ordering;

protected:
  bool setdettaglio(bool show, int fromlivart,int livart,int fromlivgiac,int livgiac,bool dettgiac);
  void add_giaclev(TString &levname,int from,int to);
  real ordinato(int flag) const;  // Ordinato fornitori - clienti
  
public:

public:
  void gruppogiac(TForm_item &cf, TToken_string &s);
  void gruppoart(TForm_item &cf, TToken_string &s);
  void codgruppogiac(TForm_item &cf, TToken_string &s);
  virtual bool validate(TForm_item &cf, TToken_string &s);
  void set_ordering(const TTipo_ordinamento_mg t);
  TTipo_ordinamento_mg get_ordering() const { return _ordering; }
  bool setdett_perart(bool totaliart, int fromlivart,int livart,bool totaligiac, int fromlivgiac,int livgiac,bool showmag, bool showdep);
  bool setdett_permag(bool totaliart, int fromlivart,int livart,bool totaligiac, int fromlivgiac, int livgiac,bool showmag, bool showdep,bool showdett);
  TForm_stampemg(const char *name,const char *code) ;
  virtual ~TForm_stampemg();
};


class TStampemg_mask: public TMask
{
  TMagazzini _magazz_ini;
public:
  void enable_livellicodice() ;
  void set_livellicodice() ;
  TMagazzini & magazz_ini() {return _magazz_ini;}
  TStampemg_mask(const char * name) : TMask(name){;}
  virtual ~TStampemg_mask(){}
};

TCodgiac_livelli &livelli_giacenza();
TCodart_livelli &livelli_articolo();

class TCondizione_vendita : public TObject
{
  TString80 _sconto;
  TString4 _codiva;
  real _prezzo;
  real _provv;
  real _molt_sconto;
  TLocalisamfile _condv;
  TLocalisamfile _rcondv;
  TLocalisamfile _sconti;
  TLocalisamfile * _anamag; // file passato e posizionato esternamente
  TLocalisamfile * _umart;  // file passato e posizionato esternamente
  TConfig * _config_ditta;
  bool _load_mask;
  bool _ivarid;
 
  bool cerca(int tiporicerca,const char * cod, const real & qta, const char *um=NULL, bool ignore_umart = false);    
  
protected:
  TRectype& testa() const { return  (_condv.curr()); }
  TRectype& riga() const { return  (_rcondv.curr()); }
  TLocalisamfile& anamag() const { CHECK(_anamag, "Anagrafica di magazzino non inizializzata") ; return *_anamag; }
  TLocalisamfile& umart() const { CHECK(_umart, "Anagrafica di unita' di misura magazzino non inizializzata") ; return *_umart; }
  
public:
  real get_prezzo() const { return _prezzo; }
  
  TConfig& config_ditta() const { return *_config_ditta; }
  void set_config( TConfig & ditta){ _config_ditta = &ditta; }
  void set_anamag(TLocalisamfile & anamag) { _anamag = &anamag; }
  void set_umart(TLocalisamfile & umart) { _umart = &umart; }

  bool gestum() const { return _condv.get_bool("GESTUM"); }
  
  // prepara la ricerca 
  void put_condv(const char *tipocv,const char * codcv,const char *catven,const char *tipocf,const char *codcf);
  void put_listino(const char * codlist,const char *catven);
  void put_contratto(const char * codcontr,const char *tipocf,const char *codcf);
  void put_offerta(const char * codoff);
  // ricerca il codice 
  bool ricerca(const char * cod, const real& qta = ZERO, bool ignore_umart = false) ;

  TCondizione_vendita(TConfig * _ditta = NULL, TLocalisamfile * anamag = NULL, TLocalisamfile * umart = NULL);    
  virtual ~TCondizione_vendita() {}
};


#define TIPOREG_VEN 1
#define TIPOREG_ACQ 2
#define TIPOREG_IVA 3
#define TIPOREG_INCPAG 4
#define TIPOREG_GIO 5
#define TIPOREG_LIBSOC 6
#define TIPOREG_CESPIT 7
#define TIPOREG_INVENT 8
#define TIPOREG_GIOMAG 9

class TRegistro_std : public TRectype
{           
  TString80 _intest;

protected:
  bool read(const char* cod, int year);

public:
  int year() const;
  const TString& code() const ;

  const TString & descr() const { return get("S0"); }
  int tipo() const { return get_int("I0"); }

  const TString & cod_intest() const { return get("S7"); }
  const TString intest() const;
  const TString & luogo_conserv() const { return get("S1"); }
  int pag_stampate() const{ return get_int("I1"); }
  int pag_numerate() const{ return get_int("I2"); }
  TDate vidimazione() const { return get_date("D0"); }
  TDate scadenza() const { return get_date("D1"); }
  TDate last_print() const { return get_date("D3"); }
  bool stampa_intditta() const { return get_bool("B9"); }
  
  void set_pag_stampate(int p) { put("I1",p); }
  void set_last_print(const TDate d) { put("D3",d); }

  bool write(bool re) const ;
  bool rewrite() const {return write(true);}
  int lock();
  int unlock();
  
  TRegistro_std(const char* code = "", int year = 0);  
  virtual ~TRegistro_std() {}
};

const char * add_magcode(TString & codmagdep, const char * m);
const char * add_depcode(TString & codmagdep, const char * d);
const char * get_magcode(TString & codmagdep);
const char * get_depcode(TString & codmagdep);
bool riporta_ordinato();
void update_clifogiac(TRectype & rec, const TRectype & oldrec);
void reset_clifogiac(TRectype & rec, const TRectype & oldrec, bool closed);

#endif //__MGLIB_H