
#include <applicat.h>  
#include <relapp.h>
#include <tabapp.h>  
#include <strings.h>
#include <stdtypes.h>
#include <tabutil.h>
#include <utility.h> 
#include <modaut.h>
#include <prefix.h>

#include "ab0200.h"

class TPconAb : public TRelation_application
{
  TMask*           _msk;
  TRelation*       _rel;
  TLocalisamfile*  _pcon;
  
  TString      _codice;
  int          _indbil,_newindbil;               
  bool         _isparametri;
  
protected:
  virtual bool user_create();
  virtual bool user_destroy();
  virtual int  rewrite(const TMask& m);
  virtual int  write  (const TMask& m);  
  virtual bool remove();
  virtual TRelation* get_relation() const { return _rel; }
  virtual TMask* get_mask(int mode) {return _msk;}
  virtual bool changing_mask(int mode) {return FALSE;}  
  virtual void init_query_mode  (TMask&);
  virtual void init_modify_mode (TMask&);    
  virtual void init_insert_mode (TMask&);    
  
public:                    

  static bool ContoSezBilOpp(TMask_field& f, KEY key);
  static bool IndBil        (TMask_field& f, KEY key);
  static bool LivelloStrutt (TMask_field& f, KEY key);  
  const char * extra_modules() const { return format("%d",CGAUT); }
  
  void   ScriviContoSezOpp  (const TString& codice, const TString& val);
  
  TPconAb() {} ;
};                    
/*
   TPconAb::TPconAb(const char* codice, char indbil): _codice(codice), _indbil(indbil)
   {
   }
   */
// Handler che controlla, nel caso venga scelto un conto di sezione opposta gia' esistente,
// l'indicatore di bilancio del conto di sezione opposta e' "opposto" rispetto al conto
// "di partenza". Controlla inoltre, nel caso il conto di sezione opposta abbia a sua volta
// un conto di sezione opposta significativo, che quest'ultimo coincida con il conto "di partenza".

bool TPconAb::ContoSezBilOpp(TMask_field& f, KEY k)
{
  if ( (k == K_TAB && f.mask().is_running()) || k == K_ENTER)
  {
    TLocalisamfile pcon (LF_ABPCON);
    
    TString16 codice (f.get());                           
    
    pcon.setkey(1);
    pcon.zero();
    pcon.put("CODCBL", codice);
    if (pcon.read() == NOERR)
    {
      int indbilI  = f.mask().get_int(F_INDBIL);
      int indbilII = pcon.get_int("INDBIL");
      
      if (indbilI == 1 && indbilII != 2)
        return f.warning_box("L'indicatore di bilancio del conto di sezione opposta deve essere una passivita'");
      
      if (indbilI == 2 && indbilII != 1)
        return f.warning_box("L'indicatore di bilancio del conto di sezione opposta deve essere un'attivita'");
      
      if (indbilI == 3 && indbilII != 4)
        return f.warning_box("L'indicatore di bilancio del conto di sezione opposta deve essere un ricavo");
      
      if (indbilI == 4 && indbilII != 3)
        return f.warning_box("L'indicatore di bilancio del conto di sezione opposta deve essere un costo");
      
      TString16 codice1 (f.mask().get(F_CODICE));                         
      TString16 codice2 (pcon.get("CODCONTR"));
      
      if (codice2 != "" && codice1 != codice2)
        return f.warning_box("Il conto di sezione opposta risulta diverso dal conto di sezione di partenza");
    }
  }
  
  return TRUE;
}                                                   

// Handler che abilita il campo "Conto di sezione opposta" se l'indicatore
// di bilancio e' compreso tra 1 e 4, e lo disabilita in tutti gli altri casi.

bool TPconAb::IndBil(TMask_field& f, KEY k)
{
  if (k == K_SPACE) 
  {
    int indbil = atoi(f.get());
    
    if (indbil == 1 || indbil == 2 || indbil == 3 || indbil == 4)
      f.mask().enable(F_CODCONTR);
    else
      f.mask().disable(F_CODCONTR);
  }
  
  return TRUE;
}

// Handler che controlla la validita' del campo "Livello di struttura":
// il suo valore deve essere >= 1 e <= 99.

bool TPconAb::LivelloStrutt(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.mask().is_running())
  {
    int livello = atoi(f.get());
    
    if (livello < 1 || livello > 99)
      return f.warning_box("Valore non valido per livello struttura");
  }
  
  return TRUE;
}

void TPconAb::init_query_mode(TMask&)
{
  if (_isparametri)
  {
    _msk->set(F_CODCONTR, _codice);
    _msk->set(F_INDBIL,   _newindbil);
    _msk->disable(F_CODCONTR);
    _msk->disable(F_INDBIL);  
  }
}                           

void TPconAb::init_modify_mode(TMask&)
{
  if (_isparametri)
  {
    _msk->set(F_CODCONTR, _codice);
    _msk->set(F_INDBIL,   _newindbil);
    _msk->disable(F_CODCONTR);
    _msk->disable(F_INDBIL);
  }
}    

void TPconAb::init_insert_mode(TMask&)
{
  if (_isparametri)
  {
    _msk->set(F_CODCONTR, _codice);
    _msk->set(F_INDBIL,   _newindbil);
    _msk->disable(F_CODCONTR);
    _msk->disable(F_INDBIL);  
  }
}    

void TPconAb::ScriviContoSezOpp(const TString& codice, const TString& val)
{
  TLocalisamfile pcon (LF_ABPCON);
  
  pcon.setkey(1);
  pcon.zero();
  pcon.put("CODCBL", codice);
  if (pcon.read() == NOERR)
  {
    pcon.put("CODCONTR", val);
    pcon.rewrite();
  }
}

int TPconAb::rewrite(const TMask& m)
{ 
  TString16 codopp = _rel->curr(LF_ABPCON).get("CODCONTR");
  ScriviContoSezOpp(codopp,"");
  
  m.autosave(_rel);
  
  codopp = m.get(F_CODCONTR);
  TString16 val (m.get(F_CODICE));
  ScriviContoSezOpp(codopp,val);
  
  return _rel->rewrite();
}

int TPconAb::write(const TMask& m)
{
  TString16 codopp (m.get(F_CODCONTR));
  TString16 val (m.get(F_CODICE));
  ScriviContoSezOpp(codopp,val);

  m.autosave(_rel);
  
  return _rel->write();
}

bool TPconAb::remove()
{ 
  TString16 codopp = _rel->curr(LF_ABPCON).get("CODCONTR");
  
  ScriviContoSezOpp(codopp,"");

  return TRelation_application::remove();
}

bool TPconAb::user_create()
{  
  _pcon = new TLocalisamfile (LF_ABPCON);
  
  _rel  = new TRelation (LF_ABPCON);
  
  _msk  = new TMask("ab0200a") ;
  
  _pcon->zero();
  _pcon->read(_isgteq);
  
  _msk->set_handler(F_CODCONTR, ContoSezBilOpp);
  _msk->set_handler(F_INDBIL,   IndBil);
  _msk->set_handler(F_LIVELLO,  LivelloStrutt);                                                                    
  
  _isparametri = FALSE;                       
  
  if (argc() == 5 || argc() == 4) // solo si viene specificato codice e indbil, non importa se l'ultimo e' l'utente
  {              
    // Originariamente dava un GPF, se non si controllava quanti parametri ci sono sulla riga di comando,
    // inoltre non ha senso una linea cosi' fatta:
    // ab0 -1 /uPRASSI <indbil>
    // perche' cosi' prende come _codice l'utente. (Basta che sia diverso da /uPRASSI)
    // Percio' l'analisi dei parametri viene cosi' cambiata: l'utente e' sempre l'ultimo parametro,
    // quindi si avranno o 3 (2) o 5(4) parametri, di cui l'ultimo e' sempre l'utente (parametro 3 o 5)
    // mentre i parametri 3 e 4 saranno il codice  e indbil. E' percio' fondamentale controllare
    // il numero dei parametri.                                                       
    _codice = argv(2);
    _indbil = atoi(argv(3));                  
    if (_indbil == 1) _newindbil = 2;
    if (_indbil == 2) _newindbil = 1;
    if (_indbil == 3) _newindbil = 4;
    if (_indbil == 4) _newindbil = 3;
    
    _isparametri = TRUE;
  }
  
  set_search_field(F_CODICE);

  return TRUE;
}

bool TPconAb::user_destroy()
{
  delete _msk;
  delete _rel;
  delete _pcon;

  return TRUE;
}

int ab0200(int argc, char* argv[])
{          
  TPconAb a;
  
  a.run(argc, argv, "Piano dei Conti");

  return TRUE;
}



