//Visualizzazione liquidazione acconti
#include <applicat.h>
#include <currency.h>
#include <mask.h>
#include <tabutil.h> 
#include <recarray.h>
#include <relation.h>
#include <sheet.h>
#include <urldefid.h>
#include <prefix.h>
#include <printer.h>
#include <progind.h>
#include <utility.h>
#include <config.h>

#include "cglib03.h"
#include "cg4900.h"

class LiqAcc_app : public TApplication
{
  TRelation*    _nditte;
  TArray_sheet* _ditte;
  TArray        _nomiditte;
  TMask*        _mask;
  TTable*       _lia,* _lam;  
  
  int       _year;
  long      _ditta;
  bool      _registra;         
  TString16 _tipo_acc;
  
  real _non_fat, _non_ann;
  
protected:               
  virtual bool create(); 
  virtual bool destroy();
  virtual bool menu(MENU_TAG);
  
  // handlers             
  static bool set_ditta(TMask_field&, KEY);
  static bool set_ragsoc(TMask_field&, KEY);
  static bool ch_year_handler(TMask_field& f, KEY key);
  static bool msk_risul(TMask_field& f, KEY key);
  static bool msk_hide(TMask& m, KEY key);
  static bool msk_recalc_2000(TMask_field& f, KEY key);
public:                                                  

  static LiqAcc_app& app() { return (LiqAcc_app&)main_app(); }
  void build_ditte_sheet();
  void build_nomiditte();
  void reset_fields();
  bool vis_acc();
  bool video_vis_1999();
  bool video_vis_2000();
  bool select_butt(TMask& m);
  
  LiqAcc_app() : _ditte(NULL), _nomiditte(100), _registra(FALSE) {}
};

bool LiqAcc_app::create()
{ 
  TApplication::create(); 

  TDate oggi(TODAY);                    
  _year = oggi.year();
	open_files(LF_TAB, LF_TABCOM, LF_NDITTE, 0);
  _nditte = new TRelation(LF_NDITTE);
  _ditte  = new TArray_sheet(-1, -1, -4, -4, TR("Selezione Ditte"),
                             HR("Cod.@5|Ragione Sociale@50|Vers."));  
  
  _lia = new TTable("%LIA");  
  _lam = new TTable("LAM");  
  
  begin_wait();
  build_nomiditte();
  build_ditte_sheet();
  end_wait();
  
  dispatch_e_menu(BAR_ITEM(1));
  
  return TRUE; 
}

bool LiqAcc_app::destroy()
{                                  
  delete _lia;
  delete _ditte;
  delete _nditte;
  
  return TApplication::destroy();
}

// handlers 
bool LiqAcc_app::msk_hide(TMask& m,KEY k)
{
  if (k == K_SHIFT+K_F7)  //&& app()._registra)
  {
    TMask m1("cg4900d");
    m1.field(F_TIPO).set(app()._tipo_acc);
    for (bool stop1 = FALSE; !stop1;)
    {
      KEY k1 = m1.run();
      switch(k1)
      {
      case K_ESC: 
      case K_QUIT: 
        if (m1.dirty())
        {
          KEY k = yesnocancel_box(TR("Registrazione modifiche effettuate?"));
          if (k ==  K_YES)
          {
            TString16 tipo (m1.get(F_TIPO));
            TTable lia ("%LIA");
            TString16 y; y.format("%05ld%04d", app()._ditta, app()._year);
            lia.zero();
            lia.put("CODTAB", y);
            if (lia.read(_isequal, _lock) != NOERR)   
              return FALSE; 
            lia.put("S8", tipo);
            lia.rewrite(); 
          } 
          if (k == K_YES || k == K_NO) 
            stop1 = TRUE;
          break;  
        } 
        else stop1 = TRUE;
        break;      
      case K_SAVE:     
        if (m1.dirty())
        {
          TString16 tipo (m1.get(F_TIPO));
          TTable lia ("%LIA");
          TString16 y; y.format("%05ld%04d", app()._ditta, app()._year);
          lia.zero();
          lia.put("CODTAB", y);
          if (lia.read(_isequal, _lock) != NOERR)   
            return FALSE;
          lia.put("S8", tipo);
          lia.rewrite();
        } 
        break;
      } //switch
    } //for    
  }
  return TRUE;
}

bool LiqAcc_app::msk_risul(TMask_field& f, KEY k)
{
  if (k == K_TAB && f.focusdirty())
  {
    real iva_ven(f.mask().get(F_IVAVEN));
    real iva_red(f.mask().get(F_IVARED));
    real iva_rim(f.mask().get(F_IVARIM));
    real non_fat(f.mask().get(F_NONFAT));
    real non_ann(f.mask().get(F_NONANN));        
    
    real risven = ZERO;
    risven = iva_ven + iva_red + iva_rim + non_fat + non_ann;
    real risacq (f.mask().get(F_RISACQ));
    if (risacq - risven < ZERO) 
    {
      f.mask().show(F_IVADEB);
      f.mask().hide(F_IVACRE);
    }
    else if (risacq - risven > ZERO)
    {
      f.mask().hide(F_IVADEB);
      f.mask().show(F_IVACRE);
    }   
    else
    {
      f.mask().hide(F_IVADEB);
      f.mask().hide(F_IVACRE);
    }
  }
  return TRUE;
}

bool LiqAcc_app::set_ditta(TMask_field& f, KEY k)
{                               
  bool found = TRUE;

  if (k == K_F9)
    return app().select_butt(f.mask());

  if (k == K_TAB && f.focusdirty())
  {
    found = FALSE;
    TString ditta = f.get();
    for (int i = 0; i < app()._ditte->items(); i++)
    { 
      TToken_string& row = app()._ditte->row(i);
      if (ditta == row.get(0))
      { 
        if (app()._ditte->row_enabled(i))
        {
          f.mask().field(F_CODDITTA).set(row.get(0));
          f.mask().field(F_RAGSOC).set(row.get(1));
          found = TRUE;
        }
        else 
        { 
          warning_box(FR("Non sono definiti i parametri liquidazione per la ditta %ld"),
                      atol(ditta));
          f.reset(); 
        }
        break;
      }
    }
  }
  if (!found) f.reset(); 
  return found;
}

bool LiqAcc_app::set_ragsoc(TMask_field& f, KEY k)
{   
  bool found = TRUE;

  if (k == K_F9)
    return app().select_butt(f.mask());

  if (k == K_TAB && f.focusdirty())
  {
    found = FALSE;
    TString ditta = f.get();
    for (int i = 0; i < app()._ditte->items(); i++)
    { 
      TToken_string& row = app()._ditte->row(i);
      TString ts(row.get(1));
      if (ts.find(ditta) != -1)
      { 
        if (app()._ditte->row_enabled(i))
        {
          f.mask().field(F_CODDITTA).set(row.get(0));
          f.mask().field(F_RAGSOC).set(row.get(1));
          found = TRUE;
          break;
        }
      }
    }
  } 
  if (!found) f.reset(); 
  return found;  
}

bool LiqAcc_app::ch_year_handler(TMask_field& f, KEY key)
{                                                    
  if (key == K_TAB && f.focusdirty())
  {                         
    TWait_cursor hourglass;
    app()._year = atoi(f.get());
    app().build_nomiditte();
    app().build_ditte_sheet();  
    app().reset_fields();  
  }
  return TRUE;
} 

void LiqAcc_app::build_ditte_sheet()
{
  // build sheet
  _ditte->destroy();
  for (int i = 0; i < _nomiditte.items(); i++)
  {
    TToken_string* d = new TToken_string(64);
    *d = (TToken_string&)_nomiditte[i];
    const char vers = d->get_char(2);
    bool selectable = vers == '?';
    const long pos = _ditte->add(d);     
    if (selectable)  _ditte->disable_row(pos);
  }     
}

void LiqAcc_app::reset_fields()
{
  _mask->field(F_CODDITTA).set("");
  _mask->field(F_RAGSOC).set("");
}

bool LiqAcc_app::select_butt(TMask& m)
{
  if (_ditte->run() == K_ENTER)
  {
    TToken_string& row = _ditte->row(_ditte->selected()); 
    m.field(F_CODDITTA).set(row.get(0));
    m.field(F_RAGSOC).set(row.get(1));
    return TRUE;        
  }
  return FALSE;
}

void LiqAcc_app::build_nomiditte()
{                 
  _nomiditte.destroy();
  // ricostruire _nomiditte e rifare build_ditte_sheet
  TCursor cur(_nditte, "", 1);
	TRectype & dt = _nditte->curr();
	const TRecnotype items = cur.items();

  for (cur = 0L; cur.pos() < items; ++cur)
  {     
    // check no archivi
    if (prefix().exist(dt.get_long("CODDITTA"))) 
    {   
      // check no parametri liquidazione                                               
      TString key;
			TToken_string d;
			
			// add record 
			d.add(dt.get_long("CODDITTA"));
			d.add(dt.get("RAGSOC"));

			key.format("%05ld%d", dt.get_long("CODDITTA"), _year);
      
			const TRectype & lia = cache().get("%LIA", key);

			d.add(lia.empty() ? "??" : lia.get("S7"));
			_nomiditte.add(d);  
    }

  }
}

bool LiqAcc_app::menu(MENU_TAG m)
{
  if (m == BAR_ITEM(1))
    return vis_acc();       
  
  return TApplication::menu(m);
}

bool LiqAcc_app::vis_acc()
{               
  long ditta = get_firm();
  
  TMask m("cg4900a");  

  KEY k;
  _mask = &m;
  
  m.set_handler(F_CODDITTA, set_ditta);   
  m.set_handler(F_RAGSOC,   set_ragsoc);   
  m.set_handler(F_YEAR,     ch_year_handler);   

  while ((k = m.run()) != K_ESC)
  { 
    if (k == K_ENTER)
    { 
      if (m.get(F_CODDITTA).empty() || m.get(F_RAGSOC).empty())  
      { 
        beep();
        continue;
      }
      _ditta = m.get_long(F_CODDITTA); 
      _year = m.get_int(F_YEAR);
      set_firm(_ditta);
      
      TIva_round ir;
      ir.set_default_iva_mode(_year, FALSE);
      
      if (_year >= 2000)
        video_vis_2000();
      else               
        video_vis_1999();
    }
  } 
  _mask = NULL;
  set_firm(ditta);
  
  return FALSE;
}    

bool LiqAcc_app::video_vis_1999()
{                                               
  TTable lia ("%LIA");
  TString16 y; y.format("%05ld%04d", _ditta, _year);
  lia.zero();
  lia.put("CODTAB", y);
  if (lia.read(_isequal, _lock) != NOERR)   //da verificare se e' giusto
    return FALSE;           
  
  // TConfig cnf(CONFIG_DITTA, "cg");
  // MI3262..
  bool liqdiff  = lia.get_bool("B1");//= cnf.get_bool("GeLiDi");  
  
  _tipo_acc = lia.get("S8");
  TString16 freqviva = lia.get("S7");
  TInteressi_IVA_table ver;
  if (ver.read(_year,12)!=NOERR)
    warning_box(FR("Errore %d in lettura tabella versamenti ed interessi."),ver.status());
  const real acconto_min_da_versare = ver.get(I_ACCONTOIVA);
  real acconto = ZERO;
  real iva_ven = ZERO;
  real iva_acq = ZERO;  
  real iva_ret = ZERO;
  real iva_rim = ZERO;
  real ult_det = ZERO;
  real per_pro = ZERO;   
  real non_fat = ZERO;
  real non_ann = ZERO;
  real risven  = ZERO;
  real risacq  = ZERO;
  real diff = ZERO;
  
  acconto = lia.get_real("R4");
  iva_ven = lia.get_real("R7");
  iva_acq = lia.get_real("R8");  
  iva_ret = lia.get_real("R9");
  iva_rim = lia.get_real("R10");
  ult_det = lia.get_real("R11");
  per_pro = lia.get_real("R12");   
  non_fat = lia.get_real("R13");
  non_ann = lia.get_real("R14");
  
  TToken_string ff(lia.get("S1"),'!');
  real cre_pre (ff.get(0));
  real acq_intr (ff.get(1));
  
  TMask m(liqdiff ? "cg4900c" : "cg4900b");
  
  m.field(F_IVAVEN).set(iva_ven.string());
  if (!liqdiff) 
  {
    m.set(F_NONFAT, non_fat);
    m.set(F_NONANN, non_ann);
  }
  
  if (iva_ret <= ZERO)
    m.set(F_IVAREC, -iva_ret); 
  else 
    m.set(F_IVARED, iva_ret); 
  
  m.set(F_IVARIM, iva_rim);
  m.set(F_IVAACQ, iva_acq);
  
  if (per_pro.is_zero()) 
    m.hide(F_PERPRO);
  else 
  {
    m.show(F_PERPRO);
    m.set(F_PERPRO, per_pro);
  }    
  
  m.set(F_CREPRE, cre_pre);
  m.set(F_ULTDET, ult_det);
  
  risven = iva_ven + non_fat + non_ann + iva_rim;
  if (iva_ret.sign() > 0)
    risven += iva_ret;
  
  m.set(F_RISVEN, risven); 
  
  risacq = iva_acq + cre_pre + ult_det; //MI2213
  if (iva_ret < ZERO)
    risacq -= iva_ret;
  
  m.set(F_RISACQ, risacq);
  
  diff = risacq - risven;
  if (diff < ZERO)
  {
    m.show(F_IVADEB);
    m.hide(F_IVACRE);
    if (liqdiff) //se no e' gestito da maschera 
      m.set(F_IVADEB, -diff);
  }
  else if (diff > ZERO)
  {
    m.hide(F_IVADEB);
    m.show(F_IVACRE);
    if (liqdiff)
      m.set(F_IVACRE, diff);
  }   
  else
  {
    m.hide(F_IVADEB);
    m.hide(F_IVACRE);
  }
  
  if (acconto.sign() < 0)
  {
    m.show(F_CREEVI);            
    real tmp = abs(acconto);
    m.field(F_CREEVI).set(tmp.string());
    m.hide(F_ACCVER);
    m.hide(F_ACCNVER);
  }
  else if (acconto.sign() > 0 && acconto > acconto_min_da_versare)  
  {
    m.hide(F_CREEVI); 
    m.hide(F_ACCNVER);
    m.show(F_ACCVER);
    m.field(F_ACCVER).set(acconto.string());
  }
  else if (acconto.sign() > 0 && acconto <= acconto_min_da_versare)
  {
    m.hide(F_CREEVI); 
    m.show(F_ACCNVER);
    m.hide(F_ACCVER);
    m.field(F_ACCNVER).set(acconto.string());
  }
  else  //==0
  {
    m.hide(F_CREEVI); 
    m.hide(F_ACCNVER);
    m.hide(F_ACCVER);
  }
  
  if (!liqdiff)
  {
    m.set_handler(F_NONFAT, msk_risul);
    m.set_handler(F_NONANN, msk_risul);
  }
  m.set_handler(msk_hide);  
  
  for (bool stop = FALSE; !stop;)
  {
    KEY k = m.run();        
    
    switch(k)
    {
    case K_ESC: 
    case K_QUIT: 
      if (m.dirty())
      {
        KEY k = yesnocancel_box(TR("Registrazione modifiche effettuate?"));
  
        if (k ==  K_YES)
        {
          if (!liqdiff)
          {
            real nf (m.get(F_NONFAT));
            real na (m.get(F_NONANN));
            if (nf != non_fat || na != non_ann)
              message_box(TR("Valori modificati: rieseguire il calcolo dell'acconto"));
            lia.put("R13", nf);
            lia.put("R14", na);
            lia.rewrite();   
          }  
        }
        if (k == K_YES || k == K_NO) 
          stop = TRUE;
        break;  
      } 
      else stop = TRUE;
      break;      
    case K_SAVE:     
      _registra = TRUE;
      if (m.dirty())
      {
        if (!liqdiff)
        {
          real nf (m.get(F_NONFAT));
          real na (m.get(F_NONANN));
          if (nf != non_fat || na != non_ann)
            message_box(TR("Valori modificati: rieseguire il calcolo dell'acconto"));
          lia.put("R13", nf);
          lia.put("R14", na);
          lia.rewrite();   
        }
      }
      break; 
    }
  }  
  return TRUE;
}    

HIDDEN void set_fields(TMask& m , short pos, short neg, const real& val)
{
  switch (val.sign())
  {
  case 0: 
    m.hide(pos); 
    m.hide(neg); 
    break;
  case 1:
    m.show(pos);  
    m.hide(neg);
    m.set(pos, val);
    break;
  default:  
    m.hide(pos);  
    m.show(neg);
    m.set(neg, -val);
    break;
  }
}

HIDDEN void round_imposta(real& n)
{
  TIva_round ir;
  ir.round(n);
}

bool LiqAcc_app::msk_recalc_2000(TMask_field& f, KEY k)
{
  if (f.to_check(k))
  {              
    TMask& m = f.mask();
    real& non_fat = app()._non_fat;
    real& non_ann = app()._non_ann;

    real periodo, risultato;
    
    if (m.field(F_IVADEB).shown())
      periodo += m.get_real(F_IVA_DEB);
    if (m.field(F_IVA_CRE).shown())
      periodo -= m.get_real(F_IVA_CRE);
    
    if (m.field(F_IVADEB).shown())
      risultato += m.get_real(F_IVADEB);
    if (m.field(F_IVACRE).shown())
      risultato -= m.get_real(F_IVACRE);
    
    periodo -= non_fat + non_ann;
    risultato -= non_fat + non_ann;
    
    non_fat = m.get_real(F_NONFAT); round_imposta(non_fat); m.set(F_NONFAT, non_fat);
    non_ann = m.get_real(F_NONANN); round_imposta(non_ann); m.set(F_NONANN, non_ann);
    
    periodo += non_fat + non_ann;    
    risultato += non_fat + non_ann;    
    
    set_fields(m, F_IVA_DEB, F_IVA_CRE, periodo);
    set_fields(m, F_IVADEB, F_IVACRE, risultato);
  }
  return TRUE;
}

bool LiqAcc_app::video_vis_2000()
{                                               
  TTable lia ("%LIA");
  TString16 key; key.format("%05ld%04d", _ditta, _year);
  lia.put("CODTAB", key);
  if (lia.read(_isequal, _lock) != NOERR)   
    return FALSE;           
    
  const bool liqdiff = lia.get_bool("B1");   // MI3262..
  
  _tipo_acc = lia.get("S8");
  const TString16 freqviva = lia.get("S7");
  
  TInteressi_IVA_table ver;
  if (ver.read(_year,12)!=NOERR)
    warning_box(FR("Errore %d in lettura tabella versamenti ed interessi."), ver.status());
  
  const real acconto_min_da_versare = ver.get(I_ACCONTOIVA);
  real acconto = lia.get("R4");  // Acconto di Dicembre
  real iva_ven = lia.get("R7");  // Iva vendite annotata fino al 20/12
  real iva_acq = lia.get("R8");  // Iva acquisti annotata fino al 20/12
  real iva_ret = lia.get("R9");  // Rettifiche
  real iva_rim = lia.get_real("R10");
  real ult_det = lia.get_real("R11");
  
  if (!liqdiff)
  {
    _non_fat = lia.get_real("R13"); // Iva non fatturata
    _non_ann = lia.get_real("R14"); // Iva non annotata
  }
  else
    _non_fat = _non_ann = ZERO;
  
  TToken_string ff(lia.get("S1"),'!');
  const real cre_pre = ff.get(0);
  const real acq_intr = ff.get(1);
  
  TMask m(liqdiff ? "cg4900f" : "cg4900e");

  if (iva_ret > ZERO)
    iva_ven += iva_ret;
  m.set(F_IVAVEN, iva_ven);
  
  if (!liqdiff) 
  {
    m.set(F_NONFAT, _non_fat);
    m.set(F_NONANN, _non_ann);
  }
  
  if (iva_ret < ZERO)
    iva_acq -= iva_ret;
  m.set(F_IVA_DET, iva_acq); // Iva che si detrae fino al 20/12    
  
  const real iva_deb_cre = iva_ven + _non_fat + _non_ann - iva_acq;
  set_fields(m, F_IVA_DEB, F_IVA_CRE, iva_deb_cre);
  
  m.set(F_CREPRE, cre_pre);
  
  const real risultato = iva_deb_cre - cre_pre;
  set_fields(m, F_IVADEB, F_IVACRE, risultato);
  
  if (acconto < ZERO)
  {
    m.show(F_CREEVI);            
    m.set(F_CREEVI, -acconto);
    m.hide(F_ACCVER);
    m.hide(F_ACCNVER);
  }
  else if (acconto == ZERO)
  {
    m.hide(F_CREEVI); 
    m.hide(F_ACCNVER);
    m.hide(F_ACCVER);
  }
  else if (acconto > acconto_min_da_versare)  
  {
    m.hide(F_CREEVI); 
    m.hide(F_ACCNVER);
    m.show(F_ACCVER);
    m.set(F_ACCVER, acconto);
  }
  else if (acconto <= acconto_min_da_versare)
  {
    m.hide(F_CREEVI); 
    m.show(F_ACCNVER);
    m.hide(F_ACCVER);
    m.set(F_ACCNVER, acconto);
  }
  
  if (!liqdiff)
  {
    m.set_handler(F_NONFAT, msk_recalc_2000);
    m.set_handler(F_NONANN, msk_recalc_2000);
  }
  m.set_handler(msk_hide);  
  
  for (bool stop = FALSE; !stop;)
  {
    KEY k = m.run();        
    
    switch(k)
    {
    case K_ESC: 
    case K_QUIT: 
      if (!liqdiff && m.dirty())
      {
        KEY k = yesnocancel_box(TR("Registrare le modifiche effettuate?"));
        if (k ==  K_YES)
        {
          warning_box(TR("E' necessario rieseguire il calcolo dell'acconto"));
          const real nf = m.get(F_NONFAT);
          const real na = m.get(F_NONANN);
          lia.put("R13", nf);
          lia.put("R14", na);
          lia.rewrite();   
        }
        if (k == K_YES || k == K_NO) 
          stop = TRUE;
        break;  
      } 
      else stop = TRUE;
      break;      
    case K_SAVE:     
      _registra = TRUE;
      if (!liqdiff && m.dirty())
      {
        warning_box(TR("E' necessario rieseguire il calcolo dell'acconto"));
        const real nf = m.get(F_NONFAT);
        const real na = m.get(F_NONANN);
        lia.put("R13", nf);
        lia.put("R14", na);
        lia.rewrite();   
      }
      break; 
    }
  }  
  return TRUE;
}    

int cg4900(int argc, char* argv[])
{
  LiqAcc_app app;

  app.run(argc, argv, TR("Visualizzazione liquidazione acconti"));
  
	return 0;
}