// 77lib.h - utilita' varie per modulo 770
#ifndef __77LIB_H
#define __77LIB_H            

#include <mask.h>
#include <real.h>
#include <sheet.h>

class TSchedaP;

// Flag di record del dichiarante (quadro I "globale")
#define COD_QUA_I_DIC   'D'
#define DELEGA_BANCARIA 'B'
#define DISTINTA        'D'
#define CC_POSTALE      'C'

////////////////////////////////////////////////////////////////////////
//                
// Parametri pacchetto/utente
//
////////////////////////////////////////////////////////////////////////

// L'anno di dichiarazione selezionato nei parametri di studio 770.
// (Usato anche in 773100a.uml)
#define ANNO_SEL  "AnnoDic"
// Elenco di ditte selezionate da un utente. Array in CONFIG_USER
#define DITTE_SEL "DitteSel"
#define ST_MODULO "StSuModulo"
#define ST_DATA   "StDataMod"
#define ST_DOC    "StDocNoPag"

// La ditta corrente per il 770 -  s/get_firm_770() usano questo
#define DITTA_770 "Ditta770"  

// Arrotonda modificato { 1500 -> 1000 (e non 2000 come in round(-3)) }
real round_770(const real& importo);

// Cerca di stabilire se il titolare della ditta e' PF o PG
char tipo_persona (long codditta);                    

////////////////////////////////////////////////////////////////////////
//                
// Dipendenti
//
////////////////////////////////////////////////////////////////////////
// Stabilisce se coddip esiste
bool esiste_dipendente(const long codditta, const long coddip);
// Stabilisce se coddip e' un (erede o un deceduto) o no
bool is_dipendente(const long codditta, const long coddip);
// Stabilisce se coddip e' un erede 
bool is_erede(const long codditta, const long coddip);
// Stabilisce se coddip e' deceduto
bool is_deceduto(const long codditta, const long coddip);

bool scrivi_erede(const long codditta, const long deceduto, const long erede);
bool riscrivi_erede(const long codditta, const long deceduto, const long erede, const long val);

// Determina se esiste un pagamento con annopag = anno passato come par.
bool esiste_pag_in_anno(TSchedaP& sch, const int anno=0, const TDate& data_da=NULLDATE, const TDate& data_a=NULLDATE, const int annocomp=0);
// La stessa cosa tra due date
bool esiste_pag_in_periodo(TSchedaP& sch, const TDate& data_da, const TDate& data_a);
                             
                             
////////////////////////////////////////////////////////////////////////
//                
// Dichiarazioni & quadri
//
////////////////////////////////////////////////////////////////////////

typedef enum { estinto=0, normale, dichiarante } TipoDitta;

// Controlla se esiste la dic
bool exist_dichiar_770 (long codditta, bool sogg_dich= FALSE);
// Immette una dichiarazione
bool enter_dichiar_770 (long codditta, int annodic=0, bool sogg_dich= FALSE);    
// Ritorna l'anno sui parametri di studio
int anno_770();                                            

// Conta il numero di persone fisiche e non della ditta codit per quadro "quadro"
// Mette i totali nei due parametri passati per riferimento
int conta_tipiper(const long codit, TString& quadro, int* NumFisiche, int* NumNoFisiche);

// Ritorna il numero di quadri L aggiuntivi 
int num_quadri_L_agg(const long codditta);   

// Ritorna il numero di quadri N,P,Q,R,S,T aggiuntivi
int num_quadri_N_agg(const long codditta);

// TRUE se la codditta e' sogg. dichiarante
bool sogg_dic    (const long codditta);    
// Ritorna il codice del sogg. dichiarante oppure 0
long sogg_estinto(const long codditta);

// Ritorna la ditta corrente selezionata
long get_firm_770();                    
// Setta la ditta 'codditta' come corrente
void set_firm_770(const long codditta);


////////////////////////////////////////////////////////////////////////
//                
// Utility varie
//
////////////////////////////////////////////////////////////////////////
bool ricerca(const TMask& m);
bool modifica(const TMask& m);
bool inserimento(const TMask& m);
// Ritorna il codice fiscale del titolare di codditta
const char* cod_fis(const long codditta);    
// Ritorna la descrizione della causale
const char* get_desc_cau(const char* codcau);
bool esiste_perc(char tipoa, const long codanag);   
// Ritorna l'indirizzo secondo la regola : prima domicilio poi residenza
// formattazione token_string : localit�|indirizzo|num.civico|cap|provincia 
TToken_string get_anag_address(char tip_anagr, long cod_anagr);        

////////////////////////////////////////////////////////////////////////////
// E' un array sheet in cui si puo' decidere di visualizzare solo i 
// primi "visible" campi. I campi successivi vengono mantenuti in un
// TArray e possono essere letti da programma ma NON vengono visualizzati
////////////////////////////////////////////////////////////////////////////
class TNikArray_sheet : public TArray_sheet
{
    TArray          _interno;
    int             _visible_items;
  public:             
    TNikArray_sheet(short x, short y, short dx, short dy, const char* caption,
               const char* head, byte buttons = 0, WINDOW parent = NULL_WIN,
               int visible=0)
     : TArray_sheet(x, y, dx, dy, caption,head, buttons),
       _visible_items(visible)  {}

    bool destroy(int i = -1);
    long add(TToken_string& s);
    TToken_string& row(int i);
};



////////////////////////////////////////////////////////////////////////
//                
// Schede, versamenti, pagamenti, percipienti....
//
////////////////////////////////////////////////////////////////////////

const int SCHEDA_NON_ESISTENTE = -2;

class TSchedaP
{    
  private:
    long      _codditta;
    char      _tipoa;
    long      _codanagr;
    int       _nprog;
    real      _spese_doc, _compenso_doc;
    TDate     _data_doc;

  public:
    bool  read();
    long  codditta() const { return _codditta; }
    char  tipoa()    const { return _tipoa; }
    long  codanagr() const { return _codanagr; }
    int   nprog()    const { return _nprog; }

    real    compenso_doc() const;
    real    spese_doc() const;  
    int     anno_doc() const;   
     
    bool operator == (const TSchedaP& sch) const 
    { 
      return (_codditta == sch.codditta() && _tipoa == sch.tipoa() &&
              _codanagr == sch.codanagr() && _nprog == sch.nprog()) ; 
    }
    
    bool operator != (const TSchedaP& sch) const 
    { 
      return (_codditta != sch.codditta() || _tipoa != sch.tipoa() ||
              _codanagr != sch.codanagr() || _nprog != sch.nprog()) ; 
    }

    bool not_empty() const { return _codditta != 0L && _tipoa != '\0' && 
                                    _codanagr != 0L && _nprog != 0; }
    bool ok() const { return not_empty(); }
    
    void set(const long codditta=0L, const char tipoa=0, const long codanagr=0L, const int nprog=0)
    { 
      _codditta=codditta; _tipoa=tipoa; _codanagr=codanagr; _nprog=nprog;
    }                            
// Cancella la scheda con tutte le sue righe di pag. e vers.
    int remove();
        
    TSchedaP (const long codditta=0L, const char tipoa=0, const long codanagr=0L, const int nprog=0);
    TSchedaP (const TRectype& rec);
    ~TSchedaP();
};

class TPercipiente
{    
  private:
    long  _codditta;
    char  _tipoa;
    long  _codanagr;

  public:
    long codditta() const { return _codditta; }
    char tipoa() const { return _tipoa; }
    long codanagr() const { return _codanagr; }

    bool not_empty() const { return _tipoa != '\0' && _codanagr != 0L; }
    bool ok() const { return not_empty(); }
        
    bool operator == (const TPercipiente& sch) const 
      { 
        return _tipoa == sch.tipoa() && _codanagr == sch.codanagr() ; 
      }
    
    bool operator != (const TPercipiente& sch) const 
      { 
        return _tipoa != sch.tipoa() || _codanagr != sch.codanagr() ; 
      }

    void set(const char tipoa=0, const long codanagr=0L)
    { 
      _tipoa=tipoa; _codanagr=codanagr;
    }                            

// Determina se esiste almeno una scheda per questo perc.
    bool esiste_scheda();
// Cancella tutte le schede di questo percipiente
    bool elimina_schede();        

    TPercipiente (const long codditta=0L, const char tipoa='\0', const long codanagr=0L) :
      _codditta(codditta), _tipoa(tipoa), _codanagr(codanagr) {}  

    TPercipiente (const TRectype& rec);
};

class TVersamento
{    
  protected:
    long    _codditta;
    char    _tipoa;
    long    _codanagr;
    int     _nprog;
    int     _nriga;
    real    _importo_versato;
    
  public:
    long  codditta() const { return _codditta; }
    char  tipoa()    const { return _tipoa; }
    long  codanagr() const { return _codanagr; }
    int   nprog()    const { return _nprog; }
    int   nriga()    const { return _nriga; }
    real    importo_versato() const { return _importo_versato; }
    
    void  set_importo_versato(real& imp) { _importo_versato = imp; }
    
    virtual TVersamento& operator = (const TVersamento& sch)
    { 
      _codditta = sch.codditta();
      _tipoa    = sch.tipoa();
      _codanagr = sch.codanagr();
      _nprog    = sch.nprog();
      _nriga    = sch.nriga();   
      return *this;
    }
    
    bool operator == (const TVersamento& sch) const 
    { 
      return (_codditta == sch.codditta() && _tipoa == sch.tipoa() &&
              _codanagr == sch.codanagr() && _nprog == sch.nprog() &&
              _nriga    == sch.nriga()) ; 
    }
    
    bool operator != (const TVersamento& sch) const 
    { 
      return (_codditta != sch.codditta() || _tipoa != sch.tipoa() ||
              _codanagr != sch.codanagr() || _nprog != sch.nprog() ||
              _nriga    != sch.nriga()) ; 
    }

    virtual void set(const long codditta=0L, const char tipoa=0, const long codanagr=0L, const int nprog=0, const int nriga=0, const real& impvers=ZERO);
    virtual void set(TToken_string& row);
    
    bool not_empty() const { return _codditta != 0L && _tipoa != '\0' && 
                                    _codanagr != 0L && _nprog != 0 && _nriga != 0; }
    
    bool ok() const { return not_empty(); }
    
    TVersamento (const long codditta=0L, const char tipoa=0, const long codanagr=0L, const int nprog=0, const int nriga=0, const real& impvers=ZERO) :
      _codditta(codditta), _tipoa(tipoa), _codanagr(codanagr), _nprog(nprog), _nriga(nriga) 
    {}  

    TVersamento(const TRectype& rec);
};

// per suddividere il versamento sui vari pagamenti
// e per ricordarsi i versamenti gia' visti
class TVersamento_stampa : public TVersamento
{
  private:
    TAssoc_array  _vers;  
    real      _importo_versato_residuo;
    real      _importo_versato;
    int       _status;  // esito read_pags
    int       _num_pags;  // numero di pagamenti collegati    
    bool      _gia_letti_pag;
    int       _num_last_pag;  // numero dell'ultimo pagamento
    
  public:    
    virtual void set(const long codditta=0L, const char tipoa=0, const long codanagr=0L, const int nprog=0, const int nriga=0, const real& impvers=ZERO);
    virtual TVersamento_stampa& operator = (const TVersamento_stampa& sch)
    { 
      _codditta = sch.codditta();
      _tipoa    = sch.tipoa();
      _codanagr = sch.codanagr();
      _nprog    = sch.nprog();
      _nriga    = sch.nriga();   
      _importo_versato = sch.importo_versato();
      return *this;
    }

    int   read_pags(TLocalisamfile* pagf=NULL);   // legge i pagamenti collegati
    int   num_pags(TLocalisamfile* pag=NULL);
    bool  last_pag(const int npag) const { return npag == _num_last_pag; }
    real  importo_versato() const { return _importo_versato; }
    void  set_importo_versato(const real& imp) { _importo_versato = imp; }

    void  add(TVersamento& vers);
    bool  find(TVersamento& vers);

    real  vers_stampa(TLocalisamfile* rpag, const int nriga_pag, const real& vers, const real& rit);
    real  importo_versato_residuo() const { return _importo_versato_residuo; }

    TVersamento_stampa(const long codditta=0L, const char tipoa=0, const long codanagr=0L, const int nprog=0, const int nriga=0, const real& impvers=ZERO);
};


////////////////////////////////////////////////////////////////////////////
// Collegamento CG - 770
////////////////////////////////////////////////////////////////////////////

typedef enum { nessuno=0, fattura=1, pagamento=3, versamento=4,
               occasionale=6, pagamento_piu_perc=7 } TTipo_coll;

struct TLink770
{
  TTipo_coll  _tipo_coll;
  char      _immissione;
  char      _tipo;
  long      _codanagr;
  long      _numreg;
  TString16   _numdoc;
  TString16   _datadoc;
  real      _spese;
  real      _compenso;
  real      _imposte;
  real      _ritenute;
  real      _totdoc;
             
  bool read(const char* msg);
               
  TLink770();
};

// struttura completa riga di pagamento   
// con overloading dell'operatore di confronto "=="
// con overloading dell'operatore di assegnazione da un TRectype
struct Pag_struct
{
  TDate datapag;
  real imponibile;
  real perc;
  real ritenuta;
  real compenso;
  real netto;
  long numvers;
  real spesa;
  real ctssnperc;
  real ctssncomp;
  real ritlorda;
  real controbb;
  real detfamil;
  real detlavdip;
  real totdet;
  int giolavdip;
  real impcpa;
  real somregconv;
  real alqimp10;
  TString16 cod10;
  real utpagati;
  real utspett;
  real ritutpag;
  real ritutspe; 
  real nquote;  
  real somnsrit;
  real ammlordo;
  real quotaprov;
  real impnetto;
  real comnetto; 
	long numreg;
  
  // overloading operatore di confronto
  int operator==(Pag_struct& s);        
  
  // overloading operatore di assegnazione
  // ritorna per riferimento la struttura
  // compilata con i valori del record passato
  Pag_struct& operator=(TRectype & rec);  
  
  // overloading operatore di assegnazione
  // ritorna per riferimento la struttura
  // incrementata dai valori della struttura passata 
  Pag_struct& operator+=(Pag_struct& s); 
};  

#endif