// 774100.cpp - Generazione quadro L        
//
// 774 -0 S (livello di studio)    oppure      
// 774 -0 D (livello di ditta)
//
// Lista modifiche
//
// 21.12.95 Azzera solo i record con AP=anno dichiarazione (nf)
//  8.01.96 Scambiate nel quadrol la chiave 2 con la 1 (nf)
//
#include <execp.h>                              
#include <printapp.h>
#include <progind.h>
#include <tabutil.h>
#include <utility.h>
#include <urldefid.h>

#include "rpag.h"
#include "rver.h"
#include "scperc.h"
#include "quadrol.h"
#include "774100.h"
#include "77lib.h"

// inizializzato in TGenera::set() 
// usato in filter_func()
HIDDEN TGenera* this_genera = NULL;
// Possibili esiti della dialog-box di configurazione parametri di gen.
HIDDEN const int UNCHANGED = 0;
HIDDEN const int CHANGED   = 1;
HIDDEN const int ESCI      = 2;

void TVersamenti::set (TSchedaP& sc, const long numvers)
{
  _key.format("%4ld%c%4ld%4d%4ld", sc.codditta(),sc.tipoa(),sc.codanagr(),sc.nprog(),numvers);
  add(_key);
}

bool TVersamenti::find (TSchedaP& sc, const long numvers)
{
  _key.format("%4ld%c%4ld%4d%4ld", sc.codditta(),sc.tipoa(),sc.codanagr(),sc.nprog(),numvers);
  return is_key(_key);
}

// Accetta un record solo se:
//   l'anno della data-pagamento == annodic  E
//   il pagamento e' collegato ad un versamento (non importa quale)
bool filter_func (const TRelation* rel)
{         
  const TRectype& rec = rel->curr();
  const TDate datapag = rec.get(PAG_DATAPAG); 
  const int anno      = datapag.year();
  const int annod     = this_genera->_annodic;
  const long nvers    = rec.get_long(PAG_NUMVERS); 
  
  return anno == annod && nvers > 0L;
} 
 
bool TGenera::causale1015(int causale)
{     
  TTable ca7("%CA7");
  TString dep; 
  int artbil = 0;

  ca7.zero();   
  dep = format("%02d", causale);
  ca7.put("CODTAB", dep);
  const bool ok = ca7.read() == NOERR;
  
  if (!ok) ca7.zero();
  
  _ab1015 = ca7.get_int("I3"); 
  _ct1015 = ca7.get_int("I0");
  _cq1015 = ca7.get    ("S1");
  
  return ok;
}     

void TGenera::causale(int causale)
{     
  TTable ca7("%CA7");
  TString dep; 
  
  _codqua = "";
  
  ca7.zero();   
  dep.format("%02d", causale);
  ca7.put("CODTAB", dep);
  if (ca7.read() == NOERR)   
  {
    _codqua  = ca7.get("S1");
    _artbil  = ca7.get_int("I3");
    _codtrib = ca7.get_int("I0");
  }
}     

bool TGenera::set(const long codditta, TConfig* cnf, const char* section)
{ 
  this_genera = this;
  
  // controllo presenza causale 1015 
  const int causale  = cnf->get_int("CoCa1015", section);
  if (causale) 
  {
    if (!causale1015(causale))
      return warning_box("Manca la causale 1015 nella tabella causali");
  }
  else
    return warning_box("Manca la causale 1015 nei parametri di studio");

  // conferma di generazione
  TString scritta;
  scritta.format("Confermare generazione dei versamenti\nper la ditta %ld?", codditta); 
  if (!yesno_box(scritta))
    return TRUE;
    
  // valorizzo anno dichiarazione e codice ditta per cui generare
  _codditta = codditta;
  _annodic  = (int)cnf->get_long(ANNO_SEL, section);

  // preparo cursore su righe di versamento
  TRelation     rel(LF_RPAG);
  TString filt; filt.format("CODDITTA=%ld", codditta);
  TCursor cur(&rel,filt,1);
  cur.set_filterfunction (filter_func);
  
  // azzeramento versamenti quadro L
  azzera_quadroL();
  
  // generazione versamenti quadro L 
  // (se ritorna una richiesta di fine non prosegue con l'arrotondamento)
  bool ok_gen = genera_riga(&cur);
  if (ok_gen)
    arrotonda();
    
  return ok_gen;
}                

int TGenera::controllo_parametri()
{
  TLocalisamfile base (LF_BASE);
  base.setkey(1);
  base.zero();
  base.put("CODDITTA", _codditta);
  const int rc = base.read();
  if (rc == NOERR)
  {
    TString appname; 
    appname.format("776mod -4 %c",_liv);
    
    TExternal_app a (appname);
    a.run();
      
    TMailbox m;
    TMessage* msg = m.next_s("");
    int subj;
    // 1 => uscito con Registra
    // 0 => uscito con Quit
    if (msg != NULL)
    {
      subj = atoi(msg->body());
      if (subj) 
        return CHANGED;
      else
        return ESCI;
    }
  }
#ifdef DBG             
  if (rc != NOERR)
    return warning_box("Errore di lettura su base cod. %d", rc);
#endif
  return UNCHANGED;  
}

bool TGenera::azzera_quadroL()
{
  TRelation rl(LF_QUAL); 
  TRectype& curr = rl.curr();
  curr.put("CODDITTA", _codditta);
  
  TCursor cl(&rl,"",1, &curr, &curr);
  
  const TRecnotype cl_items = cl.items();   
  cl.freeze();
    
  TString scritta; 
  scritta.format("Azzeramento quadro ST per la ditta %ld", _codditta);
  TProgind progn(cl_items, scritta, FALSE, TRUE);
  
  for (cl=0; cl.pos() < cl_items; ++cl)
  {
    progn.addstatus(1);
  
// solo quelli dell'anno dichiarazione 
    if (curr.get_int(QUL_QLAP) != _annodic)    
      continue;  

// solo quelli di quadri SC/SE/SF/SG    
    const TString& quadro = curr.get(QUL_QLCODQUA);
    if (quadro != "LA" && quadro != "SF" && quadro != "SG")
      continue; 

// rimozione record     
    rl.remove();
  }                    
  
  return TRUE;
}                           

void TGenera::dati_rver(TLocalisamfile& rver,TSchedaP& sch, long numvers)
{  
  rver.zero(); 
  rver.put(VER_CODDITTA, sch.codditta());  
  rver.put(VER_TIPOA,    sch.tipoa());
  rver.put(VER_CODANAGR, sch.codanagr());
  rver.put(VER_NPROG,    sch.nprog());
  rver.put(VER_NRIGA,  (long)numvers);
  rver.read();
  if (rver.bad())
    rver.zero();
  
  _ver1015 = rver.get_bool(VER_VERS1015);  
  _ritver  = rver.get_real(VER_IMPVERS);
  
  if (_ver1015)
  {         
    //Prendo i dati su flags LF_BASE 
    TLocalisamfile base(LF_BASE);
    
    base.setkey(1);
    base.zero();
    base.put("CODDITTA", _codditta);
    if (base.read(_isequal) == NOERR)
    {
      _datavers = base.get_date("DATAVERS"); 
      _mesepag  = 12;
      _luovers  = base.get_char("LUOVERS");
      _tipover  = base.get_char("TIPOVERS");
      _serie    = base.get     ("SERIE");
      _numero   = base.get     ("NUMERO");
      if (_tipover == DELEGA_BANCARIA)   
      {
        _sNprog = _numero.mid(5); 
        _sNprog.trim();   
        _numero.cut(5); 
      }
      else 
        _sNprog = ""; 
      
              
      // riporto gli estremi sulla riga di versamento 
      // della scheda 
      rver.reread(_testandlock);
      rver.put("DATAVERS", _datavers);
      rver.put("TIPOVERS", _tipover);
      rver.put("SERIE",    _serie);
      rver.put("NUMERO",   _numero); 
      rver.put("PROGBANC",_sNprog);
      rver.put("LUOVERS",  _luovers);
      rver.rewrite();
      rver.reread(_unlock);
    }
  }
  else
  {
    _datavers = rver.get_date(VER_DATAVERS);
    _luovers  = rver.get_char(VER_LUOVERS);
    _tipover  = rver.get_char(VER_TIPOVERS);
    _serie    = rver.get(VER_SERIE);
    _numero   = rver.get(VER_NUMERO);
    _sNprog   = rver.get(VER_PROGBANC);
    _sNprog.trim();
    if (_tipover == DELEGA_BANCARIA && _sNprog != "000000")
      _numero << _sNprog;
  }    
}                                    

void TGenera::dati_scperc(TSchedaP& sch)
{
  TLocalisamfile scperc(LF_SCPERC);
  int codtrib = 0;
  
  scperc.setkey(1);
  scperc.zero();
  scperc.put(SPR_CODDITTA, sch.codditta());
  scperc.put(SPR_TIPOA,    sch.tipoa());
  scperc.put(SPR_CODANAGR, sch.codanagr());
  scperc.put(SPR_NPROG,    sch.nprog());      
  if (scperc.read(_isequal) == NOERR) 
    _causale = scperc.get_int(SPR_CODCAUS);
}

void TGenera::arrotonda()
{ 
  TString16 filt; 
  real importo = ZERO;
  
  filt.format("CODDITTA=%ld", _codditta);
  
  TRelation* rl = new TRelation(LF_QUAL);
  TCursor* cl = new TCursor(rl,filt,1);
  TRecnotype cl_items = cl->items();   
  cl->freeze();
    
  (*cl) = 0L;
  
  TString scritta(60); 
  scritta.format("Arrotondamento ritenute versate per la ditta %ld", _codditta); 
  TProgind  progn(cl_items, scritta, FALSE, TRUE);
  TLocalisamfile& fl = cl->file();
  
  for (int i = 0; i < cl_items; i++, ++(*cl))
  {
    progn.addstatus(1);
    importo = fl.get_real(QUL_QLRITVER);
    importo = round_770(importo);
    fl.put(QUL_QLRITVER, importo);
    fl.rewrite();
  }  
  
  delete cl;
  delete rl;
}

bool TGenera::genera_riga(TCursor* cur)
{ 
  TLocalisamfile ql  (LF_QUAL);
  TLocalisamfile rver(LF_RVER); 
  real      riteff,ritver;  
  long      numvers,codanagr,codp;  
  char      tipoa,tipop;
  int       nprog,nprogp;   
  bool      prima_volta = TRUE;
  bool      gia_fatto   = FALSE;
  TString   perc,percp;             
                                
  const TRecnotype items_rpag = cur->items();        
  TString   scritta(60); 
  scritta.format("Generazione versamenti per la ditta %ld", _codditta);
  TProgind  progn(items_rpag, scritta, FALSE, TRUE);

  riteff = ZERO;  
  ritver = ZERO; 
  
  _righe_gia_presenti = new TVersamenti;
  _righe_gia_presenti->destroy();
  
  tipop  = 'Z';
  codp   = 99999;      
  nprogp = 9999;

  TSchedaP scheda_prec;
  
  cur->freeze();
  (*cur) = 0L;
  for (int i = 0; i < items_rpag; i++, ++(*cur), progn.addstatus(1))
  { 
// Leggo i dati su RPAG                                   
    TDate datapag(cur->curr().get(PAG_DATAPAG));    
    _mesepag = datapag.month();
    _annopag = datapag.year();
    riteff   = cur->curr().get_real(PAG_RITENUTA);
    numvers  = cur->curr().get_long(PAG_NUMVERS); 
    tipoa    = cur->curr().get_char(PAG_TIPOA);
    codanagr = cur->curr().get_long(PAG_CODANAGR);
    nprog    = cur->curr().get_int (PAG_NPROG);

    TSchedaP scheda_corr(_codditta, tipoa, codanagr, nprog);    
    dati_rver(rver,scheda_corr,numvers);
    
    if (scheda_corr != scheda_prec)
    {
      dati_scperc(scheda_corr);          
      causale(_causale);
    }
    scheda_prec.set(_codditta,tipoa,codanagr,nprog);    

// Se e' tributo1015 posso evitare di controllare il codice quadro      
    if (!_ver1015) 
    {
      if (_codqua != "LA" && _codqua != "SF" && _codqua != "SG") 
        continue;
    }      
    else                        
      if (!gia_fatto)
      { 
        gia_fatto = TRUE;
        const int cp = controllo_parametri();
        if (cp == CHANGED)
          dati_rver(rver,scheda_corr,numvers);  
        else
          if (cp == ESCI)
            return FALSE;  // ho premuto il bottone FINE
      }
          
    ql.setkey(1);
    ql.zero(); 
    ql.put(QUL_CODDITTA, _codditta);
    ql.put(QUL_QLMP,     _mesepag);
    ql.put(QUL_QLAP,     _annopag);
    ql.put(QUL_QLDV,     _datavers);
    ql.put(QUL_QLLV,     _luovers);
    ql.put(QUL_QLTV,     _tipover); 
    
    if (_ver1015)
    {
      ql.put(QUL_QLCT,     _ct1015);
      ql.put(QUL_QLAB,     _ab1015);  
      ql.put(QUL_QLCODQUA, _cq1015);
    }  
    else    
    {                 
      ql.put(QUL_QLCT,     _codtrib);
      ql.put(QUL_QLAB,     _artbil);  
      ql.put(QUL_QLCODQUA, _codqua);
    }  
    ql.put(QUL_QLSERIE,  _serie);
    ql.put(QUL_QLNUMERO, _numero);
    TRectype dep(ql.curr());
        
    if (ql.read(_isequal, _lock) == NOERR)
    {
      _riteff = ql.get_real(QUL_QLRITEFF);
      _riteff += riteff; 
      ql.put(QUL_QLRITEFF, _riteff);

      if (!_righe_gia_presenti->find(scheda_corr,numvers))
      {
        ritver  = ql.get_real(QUL_QLRITVER);
        ritver += _ritver;
        ql.put(QUL_QLRITVER, ritver);
      }
      ql.rewrite();
    }
    else
    { 
      ql.zero();
      ql.curr() = dep;
      ql.put(QUL_QLRITEFF, riteff);
      ql.put(QUL_QLRITVER, _ritver);
      ql.write();                  
    }                                   
    _righe_gia_presenti->set(scheda_corr,numvers);
  }           
  cur->freeze(FALSE);

  return TRUE;
}
                           

class TGenera_versamenti : public TApplication
{
    char        _liv;
    TString16   _section;
    TConfig*    _cnf;
  public:
    TGenera*    _genera;
    TLocalisamfile  *_rver, *_rpag, *_base, *_scperc, *_ql;
  public:
    virtual bool create();        
    virtual bool menu(MENU_TAG m);
    virtual bool destroy();

    TGenera&    genera() { return *_genera; }
    
  public:
    TGenera_versamenti(char livello = 'S') : _liv(toupper(livello)) {}
    ~TGenera_versamenti() {}
};

TGenera_versamenti& app() { return (TGenera_versamenti&)main_app(); }

bool TGenera_versamenti::menu(MENU_TAG m)
{
  long  codditta, codditta_prec;
  int   i = 0;  
  TConfig cnf_user(CONFIG_USER);
  
  if (m == BAR_ITEM_ID(1))
  {
    codditta_prec = get_firm_770();
    while ((codditta = cnf_user.get_long(DITTE_SEL, _section, i++)) != 0L) 
    {
      set_firm_770(codditta);
      if (!_genera->set(codditta, _cnf, _section))
        break;
    }
    set_firm_770(codditta_prec);  
    return FALSE;               
  }
    
  return FALSE;
}

bool TGenera_versamenti::create()
{
  TApplication::create();
  _rver     = new TLocalisamfile(LF_RVER);
  _rpag     = new TLocalisamfile(LF_RPAG);
  _scperc   = new TLocalisamfile(LF_SCPERC);
  _base     = new TLocalisamfile(LF_BASE);    
  _ql       = new TLocalisamfile(LF_QUAL);    
  _genera   = new TGenera('s');  
  _cnf      = new TConfig(CONFIG_STUDIO);

  _section = name();
  _section.cut(2);

  dispatch_e_menu (BAR_ITEM_ID(1));  
  return TRUE;
}

bool TGenera_versamenti::destroy()
{
  delete _rver;
  delete _rpag;
  delete _scperc;
  delete _base;
  delete _ql;
  delete _genera;
  delete _cnf;
  return TApplication::destroy();  
}  

int m74100 (int argc, char* argv[])
{
  TGenera_versamenti a(*argv[2]);
  a.run(argc, argv, "Generazione versamenti");
  return 0;
}