//Visualizzazione liquidazione acconti
#include <applicat.h>
#include <mask.h>
#include <tabutil.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 "cg4900.h"

#define ACCONTO_MIN_DA_VERSARE real(200000.0)

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;
  
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);

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();
  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();
  _nditte = new TRelation(LF_NDITTE);
  _ditte  = new TArray_sheet(-1, -1, 0, 0, "Selezione Ditte",
                             "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("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() != 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() != 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->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("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->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())
  {                         
    app().begin_wait();
    app()._year = atoi(f.get());
    app().build_nomiditte();
    app().build_ditte_sheet();  
    app().reset_fields();  
    app().end_wait();
  }
  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(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
  TLocalisamfile& dt = _nditte->lfile();
  TString fr(2);
  TTable lia("%LIA");

  for (dt.first(); !dt.eof(); dt.next())
  {     
    // check no archivi
    fr = "??";
    bool good = prefix().exist(dt.get_long("CODDITTA"));                        
    
    if (good) 
    {   
      // check no parametri liquidazione                                               
      lia.put("CODTAB", format("%05ld%d",dt.get_long("CODDITTA"),_year));
      if (lia.read() != NOERR) good = FALSE; 
      else fr = lia.get("S7");
    }
    else continue;

    TToken_string* d = new TToken_string(64);
    
    // add record 
    d->add(dt.get("CODDITTA"));
    d->add(dt.get("RAGSOC"));
    d->add(fr);
    
    _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 == DLG_SELECT)
      select_butt(m);
    else 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);
      video_vis();
    }
  } 
  _mask = NULL;
  set_firm(ditta);
  
  return FALSE;
}    

bool LiqAcc_app::video_vis()
{                                               
  TTable lia ("%LIA");
  TString16 y; y.format("%05ld%04d", _ditta, _year);
  lia.zero();
  lia.put("CODTAB", y);
  if (lia.read() != NOERR)   //da verificare se e' giusto
    return FALSE;           
  
  TConfig cnf(CONFIG_DITTA, "cg");
  bool liqdiff = cnf.get_bool("GeLiDi");  
  _tipo_acc = lia.get("S8");
  TString16 freqviva = lia.get("S7");
  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));
  
  // mask diverse per liq. differita oppure no
  TMask m(liqdiff ? "cg4900c" : "cg4900b");  
  
  m.field(F_IVAVEN).set(iva_ven.string());
  if (!liqdiff) 
  {
    m.field(F_NONFAT).set(non_fat.string());
    m.field(F_NONANN).set(non_ann.string());    
  }
  
  if (iva_ret.sign() <= 0)
    m.field(F_IVAREC).set(abs(iva_ret).string()); 
  else m.field(F_IVARED).set(iva_ret.string()); 
  
  m.field(F_IVARIM).set(iva_rim.string());
  m.field(F_IVAACQ).set((iva_acq + acq_intr).string());
  
  if (per_pro.is_zero()) 
    m.hide(F_PERPRO);
  else 
  {
    m.show(F_PERPRO);
    m.field(F_PERPRO).set(per_pro.string());
  }    
  
  m.field(F_CREPRE).set(cre_pre.string());
  m.field(F_ULTDET).set(ult_det.string());
  
  //risven = iva_ven + non_fat + non_ann + iva_ret + iva_rim;
  risven = iva_ven + non_fat + non_ann + iva_rim;
  if (iva_ret.sign() > 0)
    risven += iva_ret;
  
  m.field(F_RISVEN).set(risven.string()); 
  
  //risacq = iva_acq + acq_intr + cre_pre + ult_det + abs(iva_ret);
  risacq = iva_acq + acq_intr + cre_pre + ult_det;
  if (iva_ret.sign() < 0)
    risacq += abs(iva_ret);
  
  m.field(F_RISACQ).set(risacq.string());
  
  diff = risacq - risven;
  if (diff.sign() < 0)
  {
    m.show(F_IVADEB);
    m.hide(F_IVACRE);
    if (liqdiff) //se no e' gestito da maschera
      m.field(F_IVADEB).set(abs(diff).string());
  }
else if (diff.sign() > 0)
{
  m.hide(F_IVADEB);
  m.show(F_IVACRE);
  if (liqdiff)
    m.field(F_IVACRE).set(diff.string());
}   
else
{
  m.hide(F_IVADEB);
  m.hide(F_IVACRE);
}

if (acconto.sign() < 0)
{
  m.show(F_CREEVI);
  m.field(F_CREEVI).set(abs(acconto).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("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("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("Valori modificati: rieseguire il calcolo dell'acconto");
        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, "Visualizzazione liquidazione acconti");
  return 0;
}
