// Invio contabilita'

#include <math.h>  

#include <applicat.h>
#include <mask.h>
#include <relation.h>
#include <tabutil.h>
#include <utility.h>
#include <config.h>
#include <urldefid.h> 
#include <prefix.h>
#include <lffiles.h>  
#include <progind.h>
#include <nditte.h>  
#include <mov.h>
#include <rmov.h>
#include <rmoviva.h> 
#include <causali.h>
#include <rcausali.h>
#include <clifo.h>
#include <pconti.h>
#include <comuni.h>
#include <occas.h>

#include "cg2900.h"   
#include "cglib04.h"

HIDDEN      TString80 TEMP;

HIDDEN int date2esc(const TDate& d, int* prevesc = NULL);

class TInv_cont : public TApplication
{ 
  enum { BUFSIZE = 4096 };
  
  TTransfer_file _tras_file;
  TProgind*      _prog;
  
  TString     _control_rec, _trasf, _std, _stato, _marker, _nome_simbolico;
  TString     _files, _codcaus, _numdoc, _reg, _codpag, _tipodoc, _codcausm;
  TString     _ocfpi, _ragsococc, _indocc, _capocc, _localocc, _provocc, _codvali;
  bool        _esiste_ditta, _esiste_record, _inviato;
  long        _ditta, _protiva, _uprotiva, _codcf, _numrec, _tot_rec;           
  long        _dim_tot, _dim_disk;
  int         _num;                             
  TDate       _data, _datadoc, _data74ter,_datalimsk,_dataregiva;
  real        _corrlire, _cambioi, _corrval;

public:        
  virtual bool create();
  virtual bool destroy();
  virtual bool menu(MENU_TAG m);         
  
  bool    main_loop();
  
  bool    esiste_tabella_studio();
  bool    record_controllo();  
  bool    esegui_controlli();
  bool    leggi_trasfer();
  bool    controlli();
  bool    sub_controlli();
  bool    tabella_ditta();
  bool    controlla_stato_invio();
  bool    numero_data();
  void    leggi_record_controllo();          
  void    codifica_ditta (TMask& m);
  bool    testata_mov_PN (long numreg);
  bool    testata_mov_IVA(long numreg);
  void    cerca_occasionale();
  void    cerca_comune_occas(const TString& com);

  void    crea_marker(TMask& m);
  void    setta_parametri_record(TMask& m,const TString& flag);
  void    setta_tabella_studio(TMask& m, bool flag_ditta = TRUE);
  void    setta_tabella_ditta(TMask& m, const char* flag, bool comp = TRUE);
  void    crea_record_controllo(TMask& m);
  
  bool    invio_contabilita(TMask& m);
  bool    invio_tab_cau(TString& key,TMask& m);
  bool    invio_clifo  (TString& key,TMask& m);
  bool    invio_pcon   (TString& key,TMask& m);
  bool    invio_mov_PN (TString& key,TMask& m);
  bool    invio_mov_IVA(TString& key,TMask& m);    

  void    aggiorna_marker(TString& token, int pos);
  void    calcola_totale_record();
  bool    controlla_valore(const TString& val, int lim);
  void    primanota_inviata(long numreg);
  void    iva_inviata(long numreg);
  
  const char* converti (TString& data_AS400);
  const char* riconverti (TString& data_PC);
  const char* cerca_provincia(const TString& comcf); 
  
  static bool setta_maschera_hnd(TMask_field& f, KEY k);

  int   calcola_numero_dischi(TMask& m);
  FILE* chiedi_disco(const char* name, int disk, char floppy, bool lettura);
  long  determina_dimensione(FILE* f);                          
  bool  scrivi_disco(char floppy, int disk, const char* work, FILE* i, TProgind& w);
  
  TInv_cont() {};
};                                      

HIDDEN TInv_cont& app() { return (TInv_cont &) main_app(); }

FILE* TInv_cont::chiedi_disco(const char* name, int disk, char floppy, bool lettura) 
{ 
  message_box("Inserire il disco %d nel drive %c:", disk, floppy);

  //  name.ext(format("%03d", disk));
  
  FILE* f = NULL;                                                           
  bool retry = TRUE;
  while (retry)
  {               
    f = fopen(name, lettura ? "rb" : "wb");
    if (f == NULL) 
      retry = yesno_box("Il file %s non e' accessibile: riprovare?", (const char*)name);
    else
    {
      retry = FALSE; 
      fclose(f);
    }
  }  

  return f;
} 

long TInv_cont::determina_dimensione(FILE* f) 
{     
  CHECK(f, "Can't measure NULL file");
  fseek(f, 0, SEEK_END);
  const long s = ftell(f);
  fseek(f, 0, SEEK_SET);
  return s;
}

bool TInv_cont::scrivi_disco(char floppy, int disk, const char* work, 
                             FILE* i, TProgind& w) 
{               
  //  const TFilename from(filename);          // File da splittare

  //  TFilename work;
  //  work << floppy << ":/" << from.name();   // File su dischetto

  chiedi_disco(work, disk, floppy, FALSE);                                   
  
  TString str;
  str.format("%02d", disk);
  aggiorna_marker(str,31);                 // Aggiorna il num. progr. disco su marker
  
  TString path_m;
  path_m << floppy << ":\\marker";           

  TString path_t;
  path_t << floppy << ":\\trasfer";
  
  fcopy(_marker,path_m);                    // Copia il marker su disco

  //FILE* i = fopen(from, "rb");
  FILE* o = fopen(path_t, "wb");
  
  //if (i == NULL) return error_box("Impossibile aprire il file '%s'", from);
  
  //TProgind w(_dim_disk, "Trasferimento su dischetti in corso... Prego attendere", TRUE, TRUE, 40);
  
  TString buffer(BUFSIZE);
  
  long tot_scritti = BUFSIZE;
  
  while (tot_scritti <= _dim_disk)
  {
    const word letti = fread((char*)(const char*)buffer, 1, BUFSIZE, i);
    
    long scritti = fwrite((char*)(const char*)buffer, letti, 1, o);
    
    tot_scritti += letti;
    
    if (letti < BUFSIZE) break;
    
    w.addstatus(letti);
  }
  
  //fclose(i);
  fclose(o);

  return TRUE;
}

bool TInv_cont::main_loop()
{                     
  TString str;
  bool ripartenza = FALSE;
  
  if (!esiste_tabella_studio()) return FALSE;
  
  if (!esegui_controlli()) return FALSE;
  
  TMask msk ("cg2900a");
  KEY tasto;
  
  if (_ditta != 0)       
  {
    msk.set(F_DITTAINV, _ditta);
    msk.disable(F_DITTAINV);
    codifica_ditta(msk);
    msk.set(F_NUMULINV, _num);
    msk.set(F_DATAULIN, _data.string());
    msk.set(F_STATO,    _stato);
    
    TString uselab = _tras_file.ult_file();
    TString chiave = _tras_file.key();
    msk.set(F_USELAB,   uselab);
    msk.set(F_CHIAVE,   chiave);
    msk.set(F_DATALIM,  _data.string());
    msk.disable(F_DATALIM);
    
    ripartenza = TRUE;
  }
  
  msk.disable(F_NUMULINV);
  msk.disable(F_DATAULIN);
  msk.disable(F_STATO);
  msk.disable(F_USELAB);
  msk.disable(F_CHIAVE);

  if (!ripartenza)
    msk.set_handler(F_DITTAINV, setta_maschera_hnd);
  
  tasto = msk.run();
  
  if (tasto != K_ENTER) return FALSE;

  _datalimsk = msk.get(F_DATALIM);
  
  if (!ripartenza)
  {                                
    crea_marker(msk);                 //Crea il record con le informazioni sul marker                 
    setta_parametri_record(msk,"F");  //Aggiorna parametri contabili ditta           
    setta_tabella_studio(msk);        //Aggiorna la tabella studio per invio
    setta_tabella_ditta(msk,"F");     //Aggiorna la tabella ditta per invio
    crea_record_controllo(msk);       //Crea il record di controllo sul file trasfer
  }
  
  if (!invio_contabilita(msk))
    return FALSE;
  
  calcola_totale_record();
  str.format("%06ld", _tot_rec);
  aggiorna_marker(str,23);
  
  TMask mask ("cg2900b");
  KEY k;
  
  k = mask.run();
  
  if (k == K_ENTER)
  {
    int  num_disk = calcola_numero_dischi(mask);
    char floppy   = mask.get(F_FLOPPY)[0];
    
    str.format("%02d", num_disk);
    aggiorna_marker(str,29);

    const TFilename from(_trasf);          // File da splittare

    TFilename work;
    work << floppy << ":/" << from.name();   // File su dischetto
    
    FILE* i = fopen(from, "rb");                                             
    
    if (i == NULL) return error_box("Impossibile aprire il file '%s'", from);
    
    TProgind w(_dim_tot, "Trasferimento su dischetti in corso... Prego attendere", TRUE, TRUE, 60);
    
    for (int j = 0; j < num_disk; j++)
    {
      scrivi_disco(floppy,j+1,work,i,w);
    }
    fclose(i);

    setta_tabella_studio(msk,FALSE);    //Aggiorna la tabella studio per invio
    setta_tabella_ditta(msk," ",FALSE); //Aggiorna la tabella ditta per invio
    setta_parametri_record(msk," ");    //Aggiorna parametri contabili ditta           
    
    _tras_file.open(_trasf);
    leggi_record_controllo();
    TString record(256);  
    record.format("%-256s",(const char*) record);
    _control_rec.overwrite(record,0);
    _tras_file.write_control_rec(_control_rec,256);
    
    fremove(_marker);
    fremove(_trasf);
  }
  
  return FALSE;
}

int TInv_cont::calcola_numero_dischi(TMask& msk)
{        
  int numdisc = 0;
  
  FILE* t = fopen(_trasf, "rb");
  if (t == NULL) return error_box("Impossibile aprire il file '%s'", _trasf);
  
  long dim_t = determina_dimensione(t);  //Determina la dimensione del trasfer
  fclose(t);
  
  FILE* m = fopen(_marker, "rb");
  if (m == NULL) return error_box("Impossibile aprire il file '%s'", _marker);
  
  long dim_m = determina_dimensione(m);  // Determina la dimensione del marker
  fclose(m);
  
  _dim_tot = dim_t + dim_m;         // Determina la dimensione totale           
  
  int  item = msk.get_int(F_DIM);       
  
  switch (item)
  {
  case 1 :
    _dim_disk = 1400000L;
    break;
  case 2 :
    _dim_disk = 1200000L;
    break;
  case 3 :
    _dim_disk = 720000L;
    break;
  case 4 :
    _dim_disk = 360000L;
    break;            
    default :
    break;  
  };
  
  if (_dim_tot < _dim_disk)
    numdisc = 1;
  else
  {  
    //double dischi = _dim_tot / _dim_disk;
    //numdisc = (int)ceil(dischi);
    numdisc = int(_dim_tot / _dim_disk);
    if ( (_dim_tot % _dim_disk) != 0)
      numdisc += 1;
  }
  
  return numdisc;
}

HIDDEN int date2esc(const TDate& d, int* prevesc)
{                   
  if (prevesc) *prevesc = 0;
  TTable esc("ESC");
  for (int err = esc.first(); err == NOERR; err = esc.next())
  {
    const TDate ia(esc.get("D0"));   // Data inizio esercizio
    const TDate fa(esc.get("D1"));   // Data fine esercizio
    const anno = esc.get_int("CODTAB");  
    if (d >= ia && d <= fa)
      return anno;
    if (prevesc) *prevesc = anno; 
  } 
  return 0;
}

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

  dispatch_e_menu (BAR_ITEM(1));

  return TRUE;
}

bool TInv_cont::destroy()
{ 
  return TApplication::destroy();
}                                

void TInv_cont::leggi_record_controllo()
{
  _tras_file.read_control_rec();
  _control_rec = _tras_file.record();
}

const char* TInv_cont::converti (TString& data_AS400)
{
  TEMP = data_AS400.mid(4,2);
  TEMP << "-" <<data_AS400.mid(2,2);
  TEMP << "-" <<data_AS400.mid(0,2);
  return TEMP;
}

const char* TInv_cont::riconverti (TString& data_PC)
{
  TEMP = data_PC.mid(8,2);
  TEMP << data_PC.mid(3,2);
  TEMP << data_PC.mid(0,2);
  return TEMP;
}

bool TInv_cont::esiste_tabella_studio()
{
  TTable ins ("%INS");
  
  ins.zero();        
  
  if (ins.first() == NOERR)
  {
    if (ins.empty())
      return error_box("Codice STUDIO NON ATTIVATO in tabella invii");
    else
    { 
      _nome_simbolico = ins.get("CODTAB");
      long ditta = ins.get_long("I0");
      if (ditta != 0)
      {
        _esiste_ditta = TRUE;
        _ditta = ditta;
      }
      else
      {             
        _esiste_ditta = FALSE;
        _ditta = 0;
      }
    }
  }
  else
    return error_box("Codice STUDIO NON ATTIVATO in tabella invii");  
  
  return TRUE;  
}  

bool TInv_cont::leggi_trasfer()
{ 
  _trasf = ""; 
  _trasf = firm2dir(0);
  _trasf << "\\trasfer";
  
  _tras_file.open(_trasf);
  
  if (_tras_file.exist())
  {  
    if (_tras_file.read_control_rec())
    {
      _control_rec = _tras_file.record();
      if (!record_controllo())
        return FALSE;
    }
    else
      return FALSE;
  } 
  else
    return FALSE;
  
  return TRUE; 
}

bool TInv_cont::record_controllo()
{
  TString tiporecord = _control_rec.sub(0,2);
  
  if (tiporecord != " 1")
    return FALSE;
  
  return TRUE;
}

bool TInv_cont::esegui_controlli()
{  
  _esiste_record = leggi_trasfer();
  
  if (!controlli()) return FALSE;

  return TRUE;
}

void TInv_cont::setta_parametri_record(TMask& m,const TString& flag)
{ 
  long ditta = m.get_long(F_DITTAINV);
  set_firm(ditta);
  
  TConfig conf (CONFIG_DITTA);
  conf.set("FlStInv", flag);
}

bool TInv_cont::controlli()
{ 
  if (!_esiste_ditta && !_esiste_record) return TRUE; //Mi trovo in una condizione normale
  
  if (_esiste_ditta && !_esiste_record)
    return error_box("Rilevato stato di ripartenza con dati contradditori: programma interrotto");
  
  if (!_esiste_ditta && _esiste_record)
    return error_box("Rilevato stato di ripartenza con dati contradditori: programma interrotto");
  
  if (_esiste_ditta && _esiste_record)
  {
    if (!sub_controlli())
      return error_box("Rilevato stato di ripartenza con dati contradditori: programma interrotto");
  }
  
  return TRUE;
}   

bool TInv_cont::sub_controlli()
{
  long ditta_trasfer = atol(_control_rec.sub(25,29));
  
  if (_ditta == ditta_trasfer)
  {
    if (!prefix().exist(_ditta))
      return FALSE;
    
    if (!tabella_ditta())
      return FALSE;
  }          
  else
    return FALSE;

  if (!controlla_stato_invio())  
    return FALSE;
  
  if (!numero_data())
    return FALSE;    
  
  return TRUE;  
}

bool TInv_cont::tabella_ditta()
{
  TTable ind ("%IND");
  TString dep;
  
  dep.format("%05d", _ditta);
  
  ind.zero();
  ind.put("CODTAB", dep);
  if (ind.read() == NOERR) 
  {
    _stato = ind.get("S6");
    _num   = ind.get_int("I0");
    _data  = ind.get_date("D0");
    
    _files = "";
    if (ind.get_bool("B0"))
      _files << "W";
    
    if (ind.get_bool("B1"))
      _files << "A";
    
    if (ind.get_bool("B2"))
      _files << "P";        
    
    if (ind.get_bool("B3"))
      _files << "Z";
    
    if (ind.get_bool("B4"))
      _files << "U";
    
    if (ind.get_bool("B5"))
      _files << "B";
    
    return TRUE;
  }  
  
  return FALSE;  
}

bool TInv_cont::controlla_stato_invio()
{ 
  set_firm(_ditta);
  
  TConfig conf(CONFIG_DITTA);           
  _std = conf.get("FlStInv");
  
  if (_stato != _std)
    return FALSE;
  else
  {                  
    TString uselab = _tras_file.ult_file();
    
    if (_stato == "D" && uselab != " ")
      return FALSE;
  }                
  
  return TRUE;
}

bool TInv_cont::numero_data()
{                                        
  int     num  = _tras_file.nultras();
  TString str  = _tras_file.dataultras();
  TDate data (str);
  
  if (_num != num || data != _data)
    return FALSE;
  
  return TRUE;
}

void TInv_cont::codifica_ditta(TMask& m)
{
  TLocalisamfile ditte (LF_NDITTE);
  
  long ditta = m.get_long(F_DITTAINV);
  
  ditte.setkey(1);
  ditte.zero();
  ditte.put(NDT_CODDITTA, ditta);
  if (ditte.read() == NOERR)
  {
    TString ragsoc = ditte.get(NDT_RAGSOC);
    m.set(F_RAGSOC, ragsoc);
  }
}

bool TInv_cont::setta_maschera_hnd(TMask_field& f, KEY k)
{
  if ( (k == K_TAB || k == K_ENTER) && f.mask().is_running())
  {            
    app()._ditta = f.mask().get_long(F_DITTAINV);
    if (!app().tabella_ditta())
      return error_box("La ditta indicata non e' presente sulla tabella ditta per invio");
    
    if (!prefix().exist(app()._ditta))
      return error_box("La ditta indicata non e' abilitata alla contabilita'");

    if (app()._stato != "")
      return error_box("Lo stato ultimo trasferimento non puo' essere significativo");
    
    f.mask().set(F_DITTAINV, app()._ditta);
    app().codifica_ditta(f.mask());
    f.mask().set(F_NUMULINV, app()._num);
    f.mask().set(F_DATAULIN, app()._data.string());
    f.mask().set(F_STATO,    app()._stato);    
  }
  
  return TRUE;
}

void TInv_cont::crea_marker(TMask& m)
{   
  TString str;
  
  _marker = ""; 
  _marker = firm2dir(0);
  _marker << "\\marker";
  
  FILE* i;

  const word size = 64;
  TString buffer(size); 
  buffer.spaces();
  
  if ( (i = fopen(_marker,"w+t")) != NULL)
  { 
    str = format("%-10s", (const char*) _nome_simbolico);
    buffer.overwrite(str,0);
    long ditta = m.get_long(F_DITTAINV);
    str = format("%04d", ditta);
    buffer.overwrite(str,10);
    int num = m.get_int(F_NUMULINV);
    num++;
    str = format("%03d", num);
    buffer.overwrite(str,14);
    TString data (m.get(F_DATALIM));
    str = riconverti(data);
    buffer.overwrite(str,17);               
    
    const word scritti = fwrite((char*)(const char*)buffer,sizeof(char),size,i);
    
    fclose(i);
  }    
}

void TInv_cont::aggiorna_marker(TString& token, int pos)
{   
  TString str;
  
  _marker = ""; 
  _marker = firm2dir(0);
  _marker << "\\marker";
  
  FILE* i;

  const word size = 64;
  TString buffer(size); 
  //buffer.spaces();
  
  if ( (i = fopen(_marker,"r+t")) != NULL)
  { 
    const word letti = fread((char*)(const char*)buffer,sizeof(char),size,i);
    buffer.overwrite(token,pos);
    fseek(i, 0L, SEEK_SET);
    const word scritti = fwrite((char*)(const char*)buffer,sizeof(char),size,i);
    
    fclose(i);
  }    
}

void TInv_cont::calcola_totale_record()
{
  _tras_file.open(_trasf);
  leggi_record_controllo();
  
  TString sigle = _control_rec.sub(38,47);
  sigle.trim();
  
  _tot_rec = 0;
  
  for (int i = 0; i < sigle.len(); i++)
  {
    long tot_rec = atol(_control_rec.mid((i * 6) + 47,6));
    _tot_rec += tot_rec;
  }
}

void TInv_cont::setta_tabella_studio(TMask& m,bool flag_ditta)
{
  TTable ins ("%INS");
  TString dep;
  long ditta;
  
  if (flag_ditta)
    ditta = m.get_long(F_DITTAINV);
  else
    ditta = 0;
  
  dep.format("%-10s", (const char*) _nome_simbolico);
  
  ins.zero();
  ins.put("CODTAB", dep);
  if (ins.read() == NOERR)
  {
    ins.put("I0", ditta);
    ins.rewrite();
  }
  else
    warning_box("Tabella studio per invio NON AGGIORNATA");
}

void TInv_cont::setta_tabella_ditta(TMask& m,const char* flag, bool comp)
{
  TTable ind ("%IND");
  TString dep;
  
  long ditta = m.get_long(F_DITTAINV);
  
  dep.format("%05d", ditta);
  
  ind.zero();
  ind.put("CODTAB", dep);
  if (ind.read() == NOERR) 
  {                    
    int num = m.get_int(F_NUMULINV);
    num++;
    TDate data (m.get(F_DATALIM)); 
    
    ind.put("S6", flag);                                
    if (comp)
    {
      ind.put("I0", (long)num);
      ind.put("D0", data);
    }
    ind.rewrite();
  }  
  else
    warning_box("Tabella ditta per invio NON AGGIORNATA");  
}

void TInv_cont::crea_record_controllo(TMask& m)
{            
  int size = 256;
  TString buffer(256);
  TString str;
  
  if (_tras_file.exist())
    _tras_file.open(_trasf);
  else 
  {
    _tras_file.open(_trasf,TRUE);   //Metto il parametro TRUE (che di default e' FALSE), perche' voglio creare un file che non e' ancore esistente
    
    buffer.spaces();   
    buffer.overwrite(" 1",0);                             //Tipo record
    
    str = format("%-10s", (const char*) _nome_simbolico);
    buffer.overwrite(str,15);                             //Nome studio
    
    long ditta = m.get_long(F_DITTAINV);
    str = format("%04d", ditta);
    buffer.overwrite(str,25);                             //Ditta inviante
    
    int num = m.get_int(F_NUMULINV);
    num++;
    str = format("%03d", num);
    buffer.overwrite(str,29);                             //Numero progr. invio
    
    TString data (m.get(F_DATALIM));
    str = riconverti(data);
    buffer.overwrite(str,32);                             //Data limite invio
    
    str = format("%-9s", (const char*) _files);
    buffer.overwrite(str,38);
    
    str = _files.sub(0,1);
    buffer.overwrite(str,240);
    
    if (!_tras_file.write_control_rec(buffer, size))   
      warning_box("Il record di controllo del file trasfer non e' stato aggiornato correttamente");
  }  
  _tras_file.close();  
} 

const char* TInv_cont::cerca_provincia(const TString& comcf)
{
  TLocalisamfile comuni(LF_COMUNI);
  
  comuni.setkey(1);
  comuni.zero();
  comuni.put(COM_COM, comcf);
  if (comuni.read() == NOERR)
    TEMP = comuni.get(COM_PROVCOM);
  else
    TEMP = "";

  return TEMP;
}

bool TInv_cont::invio_contabilita(TMask& m)
{
  char    uselab;
  TString record(256),key,nrec;
  int     posiz,i;
  char    sigla;               

  _tras_file.open(_trasf);
  
  leggi_record_controllo();
  
  uselab = (_tras_file.ult_file())[0];
  
  if (uselab == ' ')            //Significa che sono in caso di ripartenza ma ho
    return TRUE;                //gia' trasferito tutti gli archivi e devo solo fare la copia su dischi
  
  posiz  = _files.find(uselab); //Ritorna la posizione della sigla all'interno della schiera
  key    = _tras_file.key(); 
  key.trim();                 
  nrec   = _control_rec.sub(47,101);
  
  for (i = posiz; i < _files.len();i++)
  {                 
    sigla    = _files[i];
    _numrec  = atol(nrec.mid(i * 6,6));
    
    switch (sigla)        
    {
    case 'W': 
      if (!invio_tab_cau(key,m))
        return FALSE;
      break;
      
    case 'A':
      if (!invio_clifo(key,m))
        return FALSE;
      break;
      
    case 'P':
      if (!invio_pcon(key,m))
        return FALSE;
      break;
      
    case 'Z':
      if (!invio_mov_PN(key,m))
        return FALSE;
      break;
      
    case 'U':
      if (!invio_mov_IVA(key,m))
        return FALSE;
      break;
      
    default:
      break;
    };             
    key = "";
  }                    

  // Finito di trasferire tutti gli archivi pulisco la sigla ultimo file da elaborare  
  _tras_file.open(_trasf);
  leggi_record_controllo();
  _control_rec.overwrite(" ",240);
  _tras_file.write_control_rec(_control_rec,256);
  _tras_file.close();
  
  return TRUE;
}

bool TInv_cont::controlla_valore(const TString& val,int lim)
{
  if (real::is_natural(val))
  {
    int app = atoi(val);
    if (app > lim)
      return FALSE;
  }
  else
    if (val.len() > 1)
      return FALSE;
  
  return TRUE;
}

bool TInv_cont::invio_tab_cau(TString& key,TMask& m)
{                      
  int size = 256;
  TString record(size);
  TString cod;
  TLocalisamfile cau (LF_CAUSALI);

  long cicli = cau.items();
  cicli -= _numrec;
  _prog = new TProgind(cicli,"Invio tabella causali in corso... Prego attendere.",FALSE);
  
  if (key == "")                  
    cau.first();
  else           
  {
    cod = key.mid(2,3);
    cau.setkey(1);
    cau.zero();
    cau.put(CAU_CODCAUS, cod);
    cau.read();
  }
  
  for (; !cau.eof(); cau.next())
  { 
    TString str;
    
    _prog->addstatus(1);
    _tras_file.open(_trasf);
    
    record.spaces();                                                     
    
    // Se trovo un codice causale alfanumerico l'invio deve essere interrotto
    const char* codcau = cau.get(CAU_CODCAUS);
    if (codcau && *codcau && !real::is_natural(codcau) )
      return error_box("Rilevato un codice causale alfanumerico nella causale %-3s: impossibile proseguire",codcau);
    str.format("%03s", codcau);
    record.overwrite("W1",0);                    //Tipo record
    record.overwrite(str,2);                     //Codice causale
    
    
    //Salvataggio della sigla e della chiave sul record di controllo del file trasfer
    leggi_record_controllo();
    TString chiave,app;
    chiave.format("%2s%03s", (const char*) "W1", codcau);
    app.format("%-15s", (const char*) chiave);
    _control_rec.overwrite("W",240);
    _control_rec.overwrite(app,241);
    //_tras_file.write_control_rec(_control_rec,size);
    //_tras_file.close();
    
    TString descr = cau.get(CAU_DESCR);
    descr.format("%-.20s", (const char*) descr); 
    record.overwrite(descr,15);                  //Descrizione
    
    TString tipodoc = cau.get(CAU_TIPODOC);
    record.overwrite(tipodoc,35);                //Tipo documento
    
    //Se trovo un registro IVA con lunghezza maggiore di 1 l'invio deve essere interrotto
    TString reg = cau.get(CAU_REG);
    if (!controlla_valore(reg,9))
      return error_box("Rilevato un registro IVA con lunghezza superiore a 1 nella causale %03s: impossibile proseguire", codcau);
    record.overwrite(reg,37);                    //Registro IVA
    
    bool alleg = cau.get_bool(CAU_ALLEG);
    if (alleg)
      record.overwrite("X",38);
    else                                         //Flag esclusione tipo documento da allegato
      record.overwrite(" ",38);
    
    int m770 = atoi(cau.get(CAU_M770));
    str = format("%1d", m770);  
    record.overwrite(str,39);                    //Collegamento modello 770
    
    TString cespiti = cau.get(CAU_COLLCESP);
    record.overwrite(cespiti,40);                //Collegamento cespiti
    
    bool numdoc = cau.get_bool(CAU_NUMDOC);
    if (numdoc)
      record.overwrite("1",206);
    else                                         //Flag immissione numero documento
      record.overwrite("0",206);
    
    bool datadoc = cau.get_bool(CAU_DATADOC);
    if (datadoc)
      record.overwrite("1",207);
    else                                         //Flag immissione data documento
      record.overwrite("0",207);                                                 
    
    const char* codcausim = cau.get(CAU_CODCAUSIM);
    if (codcausim && *codcausim && !real::is_natural(codcausim) )
      return error_box("Rilevato un codice causale per incasso immediato alfanumerico nella causale %03s: impossibile proseguire",codcau);
    str.format("%03s", codcausim);
    record.overwrite(str,209);             //Codice causale per incasso immediato
    
    bool intracom = cau.get_bool(CAU_INTRACOM);
    if (intracom)
      record.overwrite("X",246);
    else                                         //Flag per operazioni intracomunitarie
      record.overwrite(" ",246);                                                       
    
    bool valintra = cau.get_bool(CAU_VALINTRA);
    if (valintra)
      record.overwrite("X",247);
    else                                         //Gestione valuta per oper. intracomunitarie
      record.overwrite(" ",247);                                                             
    
    bool ritfatt = cau.get_bool(CAU_RITFATT);
    if (ritfatt)
      record.overwrite("X",248);
    else                                         //Flag causale per fattura ricevuta in ritardo
      record.overwrite(" ",248);                                                               
    
    bool autofatt = cau.get_bool(CAU_AUTOFATT);
    if (autofatt)
      record.overwrite("X",249);
    else                                         //Autofattura art.34
      record.overwrite(" ",249);  
    
    int num = 0;    
    int pos_gcs = 41;
    int pos_sez = 191;
    _codcaus = cau.get(CAU_CODCAUS);
    
    TLocalisamfile rcau (LF_RCAUSALI);        
    
    do
    {
      num++;
      
      rcau.setkey(1);
      rcau.zero();
      rcau.put(RCA_CODCAUS, _codcaus);
      rcau.put(RCA_NRIGA,   num);

      if (rcau.read() == NOERR)
      {
        int     g   = rcau.get_int (RCA_GRUPPO);
        int     c   = rcau.get_int (RCA_CONTO);  
        
        if (g > 99)
          return error_box("Rilevato un gruppo composto da 3 cifre nella causale %03s riga %d: impossibile proseguire",codcau,num);
        
        if (c > 99)
          return error_box("Rilevato un conto composto da 3 cifre nella causale %03s riga %d: impossibile proseguire",codcau,num);
        
        long    s   = rcau.get_long(RCA_SOTTOCONTO);
        TString sez = rcau.get     (RCA_SEZIONE);

        str = format("%02d", g);
        record.overwrite(str,pos_gcs);      //Gruppo
        pos_gcs += 2;
        str = format("%02d", c);
        record.overwrite(str,pos_gcs);      //Conto
        pos_gcs += 2;
        str = format("%06ld", s);
        record.overwrite(str,pos_gcs);      //Sottoconto
        pos_gcs += 6;
        
        record.overwrite(sez,pos_sez);      //Sezione
        pos_sez++;
      }
      else
      {
        int     g   = 0;
        int     c   = 0;
        long    s   = 0;
        TString sez = " ";

        str = format("%02d", g);
        record.overwrite(str,pos_gcs);      //Gruppo
        pos_gcs += 2;
        str = format("%02d", c);
        record.overwrite(str,pos_gcs);      //Conto
        pos_gcs += 2;
        str = format("%06ld", s);
        record.overwrite(str,pos_gcs);      //Sottoconto
        pos_gcs += 6;
        
        record.overwrite(sez,pos_sez);      //Sezione
        pos_sez++;        
      }           
      
      if (num == 15)
      {   
        TString cau_app;
        
        rcau.next(); 
        if (!rcau.eof())
          cau_app = rcau.get(RCA_CODCAUS);
        else
          cau_app = "";
        
        if (_codcaus == cau_app)
          return error_box("Rilevata una causale con piu' di 15 righe: impossibile proseguire");
      }
    }
    while (num < 15);
    
    _numrec++;            
    TString stringa;
    stringa.format("%06ld", _numrec);
    int posiz = _files.find("W");
    _control_rec.overwrite(stringa,((posiz * 6) + 47));
    _tras_file.write_control_rec(_control_rec,size);
    _tras_file.close();

    _tras_file.open(_trasf,TRUE);
    _tras_file.write_control_rec(record,size);
    _tras_file.close();
  } 
  delete _prog;
  
  //Inizializzo l'ultima sigla file elaborato su trasfer con la sigla del file successivo da inviare
  //e inizializzo la chiave, altrimenti se si blocca l'invio subito dopo aver finito un file si rischia di 
  //ritrasferire l'ultimo record quando si riparte; inoltre non si riesce a inviare il file successivo perche'
  //la chiave e' compilata con i dati del file precedente.
  _tras_file.open(_trasf);
  leggi_record_controllo();
  TString chiave,app,sigla;
  app.format("%-15s", (const char*) chiave);
  char sigla_p = _tras_file.ult_file()[0];
  int posiz    = _files.find(sigla_p);
  TString nuova_sigla = " ";
  if (posiz < _files.len())
    nuova_sigla = _files.mid(posiz+1,1);
  
  _control_rec.overwrite(nuova_sigla,240);
  _control_rec.overwrite(app,241);
  _tras_file.write_control_rec(_control_rec,size);
  _tras_file.close();
  
  setta_tabella_ditta(m,"D",FALSE);
  setta_parametri_record(m,"D");
  
  return TRUE;
}

bool TInv_cont::invio_clifo(TString& key,TMask& m)
{
  int size = 256;
  TString record(size);
  char tipocf;
  long codcf;
  TLocalisamfile clifo (LF_CLIFO);

  long cicli = clifo.items();
  cicli -= _numrec;
  _prog = new TProgind(cicli,"Invio anagrafica Clienti / Fornitori in corso... Prego attendere.",FALSE);
  
  if (key == "")                  
    clifo.first();
  else           
  { 
    tipocf = (key.mid(2,1))[0];
    codcf  = atol(key.mid(3,6));
    clifo.setkey(1);
    clifo.zero();
    clifo.put(CLI_TIPOCF, tipocf);
    clifo.put(CLI_CODCF,  codcf);
    clifo.read();
  }
  
  for (; !clifo.eof(); clifo.next())
  { 
    TString str;
    
    _prog->addstatus(1);
    _tras_file.open(_trasf);
    
    record.spaces();                                                     
    
    // Il tipocf su PC e'      C = cliente  F = fornitore.
    // Il tipocf su AS400 e'   1 = cliente  2 = fornitore.
    TString  tipo_cod;
    
    char tipo = clifo.get_char(CLI_TIPOCF);
    if (tipo == 'C')
      tipo_cod = "1";
    else             
      if (tipo == 'F')
        tipo_cod = "2";

    record.overwrite("A1",0);                    //Tipo record
    record.overwrite(tipo_cod,2);                //Tipo cliente/fornitore
    
    long codice = clifo.get_long(CLI_CODCF);
    str.format("%06ld", codice);
    record.overwrite(str,3);                     //Codice cliente/fornitore
    
    //Salvataggio della chiave sul record di controllo del file trasfer
    leggi_record_controllo();
    TString chiave,app;
    chiave.format("%2s%s%06ld", (const char*) "A1", (const char*) tipo_cod, codice);
    app.format("%-15s", (const char*) chiave);
    _control_rec.overwrite("A",240);
    _control_rec.overwrite(app,241);
    //    _tras_file.write_control_rec(_control_rec,size);
    //    _tras_file.close();
    
    //Il tipo persona su PC e'     F = fisica     G = giuridica
    //Il tipo persona su AS400 e'  0 = giuridica  1 = fisica
    char tipop = clifo.get_char(CLI_TIPOPERS);
    TString tipopers;
    
    if (tipop == 'F')
      tipopers = "1";
    else
      if (tipop == 'G')
        tipopers = "0";
    
    record.overwrite(tipopers,15);               //Tipo persona
    
    TString ragsoc = clifo.get(CLI_RAGSOC);
    TString cognome = ragsoc.mid(0,30);
    TString nome    = ragsoc.mid(30,20);
    str.format("%-30s", (const char*) cognome);  //Cognome o I ragione sociale
    record.overwrite(str,16);
    str.format("%-20s", (const char*) nome);
    record.overwrite(str,46);                    //Nome o II ragione sociale
    
    //Se la partita IVA e' maggiore di 11 il programma di invio viene fermato
    TString paiv = clifo.get(CLI_PAIV);
    if (paiv.len() > 11)
      return error_box("Rilevata partita IVA con piu' di 11 caratteri in codice %c%d: impossibile proseguire",tipo,codice);
    str.format("%-11s", (const char*) paiv);
    record.overwrite(str,66);                    //Partita IVA
    
    TString cofi = clifo.get(CLI_COFI);
    str.format("%-16s", (const char*) cofi);
    record.overwrite(str,77);                    //Codice fiscale
    
    TString indcf = clifo.get(CLI_INDCF);
    TString civcf = clifo.get(CLI_CIVCF);
    int lind = indcf.len();
    int lciv = civcf.len();
    int totlen = lind + lciv + 1;
    if (totlen < 36)
      indcf << " " << civcf;

    str.format("%-35s", (const char*) indcf);
    record.overwrite(str,93);                    //Indirizzo
    
    TString capcf = clifo.get(CLI_CAPCF);
    record.overwrite(capcf,128);                 //Codice di avviamento postale
    
    TString localita = clifo.get(CLI_LOCCF);
    str.format("%-.20s", (const char*) localita);
    record.overwrite(str,133);                   //Localita'
    
    TString comcf = clifo.get(CLI_COMCF);
    TString provincia = cerca_provincia(comcf);  
    str.format("%-2s", (const char*) provincia);
    record.overwrite(str,153);                   //Provincia
    
    TString ptel = clifo.get(CLI_PTEL);
    TString tel  = clifo.get(CLI_TEL);
    TString appoggio;
    appoggio << ptel << " " << tel;   
    if (appoggio.len() > 12)
      warning_box("Rilevato numero telefonico troppo lungo in codice %c%ld: impossibile inviare",tipo,codice);
    else                                         //Numero telefono
      record.overwrite(appoggio,155);
    
    TString alleg = clifo.get(CLI_ALLEG);
    record.overwrite(alleg,167);                 //Flag gestione allegato
    
    int gruppo = clifo.get_int(CLI_GRUPPORIC);
    int conto  = clifo.get_int(CLI_CONTORIC);
    
    if (gruppo > 99)
      return error_box("Rilevato gruppo costo/ricavo composto da 3 cifre in codice %c%d: impossibile proseguire",tipo,codice);
    
    if (conto > 99)
      return error_box("Rilevato conto costo/ricavo composto da 3 cifre in codice %c%d: impossibile proseguire",tipo,codice);
    
    long sottoc = clifo.get_long(CLI_SOTTOCRIC);
    str.format("%02d", gruppo);
    record.overwrite(str,168);                   //Gruppo di costo/ricavo
    str.format("%02d", conto);
    record.overwrite(str,170);                   //Conto di costo/ricavo
    str.format("%06ld", sottoc);
    record.overwrite(str,172);                   //sottoconto di costo/ricavo

    long codalleg = clifo.get_long(CLI_CODALLEG);
    str.format("%06ld", codalleg);
    record.overwrite(str,179);
    
    //Se il codice di pagamento e' superiore alle 2 cifre l'invio deve essere interrotto
    TString codpag = clifo.get(CLI_CODPAG);
    if (!controlla_valore(codpag,99))
      return error_box("Rilevato un codice di pagamento composto da 3 o piu' cifre in codice %c%d: impossibile proseguire",tipo,codice);
    
    str.format("%-2s", (const char*) codpag);

    _numrec++;            
    TString stringa;
    stringa.format("%06ld", _numrec);
    int posiz = _files.find("A");
    _control_rec.overwrite(stringa,((posiz * 6) + 47));
    _tras_file.write_control_rec(_control_rec,size);
    _tras_file.close();
    
    _tras_file.open(_trasf,TRUE);
    _tras_file.write_control_rec(record,size);
    _tras_file.close();
  } 
  delete _prog;  

  //Inizializzo l'ultima sigla file elaborato su trasfer con la sigla del file successivo da inviare
  //e inizializzo la chiave, altrimenti se si blocca l'invio subito dopo aver finito un file si rischia di 
  //ritrasferire l'ultimo record quando si riparte; inoltre non si riesce a inviare il file successivo perche'
  //la chiave e' compilata con i dati del file precedente.
  _tras_file.open(_trasf);
  leggi_record_controllo();
  TString chiave,app,sigla;
  app.format("%-15s", (const char*) chiave);
  char sigla_p = _tras_file.ult_file()[0];
  int posiz    = _files.find(sigla_p);
  TString nuova_sigla = " ";
  if (posiz < _files.len())
    nuova_sigla = _files.mid(posiz+1,1);
  
  _control_rec.overwrite(nuova_sigla,240);
  _control_rec.overwrite(app,241);
  _tras_file.write_control_rec(_control_rec,size);
  _tras_file.close();

  setta_tabella_ditta(m,"D",FALSE);
  setta_parametri_record(m,"D");
  
  return TRUE;
}

bool TInv_cont::invio_pcon(TString& key,TMask& m)
{
  int size = 256;
  TString record(size);
  int  gruppo,conto;
  long sottoc;
  TLocalisamfile pcon (LF_PCON);

  long cicli = pcon.items();
  cicli -= _numrec;
  _prog = new TProgind(cicli,"Invio anagrafica Piano dei Conti in corso... Prego attendere.",FALSE);
  
  if (key == "")                  
    pcon.first();
  else           
  { 
    gruppo = atoi(key.mid(2,2));
    conto  = atoi(key.mid(4,2));
    sottoc = atol(key.mid(6,6));
    pcon.setkey(1);
    pcon.zero();
    pcon.put(PCN_GRUPPO,     gruppo);
    pcon.put(PCN_CONTO,      conto);
    pcon.put(PCN_SOTTOCONTO, sottoc);
    pcon.read();
  }
  
  for (; !pcon.eof(); pcon.next())
  { 
    TString str;
    
    _prog->addstatus(1);
    _tras_file.open(_trasf);
    
    record.spaces();                                                     
    
    int  g = pcon.get_int (PCN_GRUPPO); 
    
    if (g > 99)
      return error_box("Rilevato un gruppo composto da 3 cifre in %03d: impossibile proseguire",g);
    
    int  c = pcon.get_int (PCN_CONTO);
    
    if (c > 99)
      return error_box("Rilevato un conto composto da 3 cifre in %03d: impossibile proseguire",c);
    
    long s = pcon.get_long(PCN_SOTTOCONTO);

    // Se si tratta di un GRUPPO 

    if (g != 0 && c == 0 && s == 0)
    {                                                
      //Salvataggio della sigla e della chiave sul record di controllo del file trasfer
      leggi_record_controllo();
      TString chiave,app;
      chiave.format("%2s%02d%02d%06ld", (const char*) "P1", g, c, s);
      app.format("%-15s", (const char*) chiave);
      _control_rec.overwrite("P",240);
      _control_rec.overwrite(app,241);
      //      _tras_file.write_control_rec(_control_rec,size);
      //      _tras_file.close();
      
      record.overwrite("P1",0);                  //Tipo record
      str.format("%02d", g);
      record.overwrite(str,2);                   //Gruppo
      
      TString descr (pcon.get(PCN_DESCR));
      str.format("%-.30s", (const char*) descr);
      record.overwrite(str,15);                  //Descrizione gruppo
    }
    
    // Se si tratta di un CONTO

    if (g != 0 && c != 0 && s == 0)
    {
      //Salvataggio della sigla e della chiave sul record di controllo del file trasfer
      leggi_record_controllo();
      TString chiave,app;
      chiave.format("%2s%02d%02d%06ld", (const char*) "P2", g, c, s);
      app.format("%-15s", (const char*) chiave);
      _control_rec.overwrite("P",240);
      _control_rec.overwrite(app,241);
      //      _tras_file.write_control_rec(_control_rec,size);
      //      _tras_file.close();
      
      record.overwrite("P2",0);                  //Tipo record
      str.format("%02d", g);
      record.overwrite(str,2);                   //Gruppo
      
      str.format("%02d", c);
      record.overwrite(str,4);                   //Conto
      
      TString descr (pcon.get(PCN_DESCR));
      str.format("%-.30s", (const char*) descr);
      record.overwrite(str,15);                  //Descrizione conto
      
      int indbil = pcon.get_int(PCN_INDBIL);
      str.format("%d", indbil);
      record.overwrite(str,45);                  //Indicatore di bilancio
      
      TString tmcf = pcon.get(PCN_TMCF);
      record.overwrite(tmcf,46);                 //Flag conto cliente/fornitore
      
      bool stsottbil = pcon.get_bool(PCN_STSOTTBIL);
      if (stsottbil)
        str = "0";
      else
        str = "1";
      record.overwrite(str,47);                  //Flag stampa dettaglio sottoconti su bilancio

      // Classe IV direttiva CEE
      
      TString sez = pcon.get(PCN_SEZIVD);
      if (sez == "0")
        sez = " ";
      record.overwrite(sez,48);                  //Sezione IV dir
      
      TString let = pcon.get(PCN_LETTIVD);
      record.overwrite(let,49);                  //Lettera IV dir
      
      int numrom = atoi(pcon.get(PCN_NUMRIVD));
      str.format("%03d", numrom);
      record.overwrite(str,60);                  //Numero arabo corrispondente al numero romano
      TString numr = itor(numrom);
      str.format("%-8s", (const char*) numr);
      record.overwrite(str,50);                  //Numero romano IV dir
      
      int num = pcon.get_int(PCN_NUMIVD);
      str.format("%02d", num);
      record.overwrite(str,58);                  //Numero arabo IV dir

      // Classe IV direttiva CEE di segno opposto
      
      TString sezop = pcon.get(PCN_SEZIVDOPP);
      if (sezop == "0")
        sezop = " ";
      record.overwrite(sezop,63);                //Sezione IV dir
      
      TString letop = pcon.get(PCN_LETTIVDOPP);
      record.overwrite(letop,64);                //Lettera IV dir
      
      int numromop = atoi(pcon.get(PCN_NUMRIVDOPP));
      str.format("%03d", numromop);
      record.overwrite(str,75);                  //Numero arabo corrispondente al numero romano
      TString numrop = itor(numromop);
      str.format("%-8s", (const char*) numrop);
      record.overwrite(str,65);                  //Numero romano IV dir
      
      int numop = pcon.get_int(PCN_NUMIVDOPP);
      str.format("%02d", numop);
      record.overwrite(str,73);                  //Numero arabo IV dir      
    }
    
    // Se si tratta di un SOTTOCONTO

    if (g != 0 && c != 0 && s != 0)
    {
      //Salvataggio della sigla e della chiave sul record di controllo del file trasfer
      leggi_record_controllo();
      TString chiave,app;
      chiave.format("%2s%02d%02d%06ld", (const char*) "P3", g, c, s);
      app.format("%-15s", (const char*) chiave);
      _control_rec.overwrite("P",240);
      _control_rec.overwrite(app,241);
      //      _tras_file.write_control_rec(_control_rec,size);
      //      _tras_file.close();
      
      record.overwrite("P3",0);                  //Tipo record
      str.format("%02d", g);
      record.overwrite(str,2);                   //Gruppo
      
      str.format("%02d", c);
      record.overwrite(str,4);                   //Conto
      
      str.format("%06ld", s);
      record.overwrite(str,6);                   //Sottoconto
      
      TString descr (pcon.get(PCN_DESCR));
      str.format("%-.30s", (const char*) descr);
      record.overwrite(str,15);                  //Descrizione sottoconto
      
      int tipospric = pcon.get_int(PCN_TIPOSPRIC);
      str.format("%d", tipospric);
      record.overwrite(str,45);                  //Tipo costo/ricavo
      
      int ricser = pcon.get_int(PCN_RICSER);
      if (ricser == 0)
        str = " ";
      else
        str.format("%d", ricser);                      
      record.overwrite(str,46);                  //Tipo attivita'

      // Classe IV direttiva CEE
      
      TString sez = pcon.get(PCN_SEZIVD);
      if (sez == "0")
        sez = " ";
      record.overwrite(sez,47);                  //Sezione IV dir
      
      TString let = pcon.get(PCN_LETTIVD);
      record.overwrite(let,48);                  //Lettera IV dir
      
      int numrom = atoi(pcon.get(PCN_NUMRIVD));
      str.format("%03d", numrom);
      record.overwrite(str,59);                  //Numero arabo corrispondente al numero romano
      TString numr = itor(numrom);
      str.format("%-8s", (const char*) numr);
      record.overwrite(str,49);                  //Numero romano IV dir
      
      int num = pcon.get_int(PCN_NUMIVD);
      str.format("%02d", num);
      record.overwrite(str,57);                  //Numero arabo IV dir

      // Classe IV direttiva CEE di segno opposto
      
      TString sezop = pcon.get(PCN_SEZIVDOPP);
      if (sezop == "0")
        sezop = " ";
      record.overwrite(sezop,62);                //Sezione IV dir
      
      TString letop = pcon.get(PCN_LETTIVDOPP);
      record.overwrite(letop,63);                //Lettera IV dir
      
      int numromop = atoi(pcon.get(PCN_NUMRIVDOPP));
      str.format("%03d", numromop);
      record.overwrite(str,74);                  //Numero arabo corrispondente al numero romano
      TString numrop = itor(numromop);
      str.format("%-8s", (const char*) numrop);
      record.overwrite(str,64);                  //Numero romano IV dir
      
      int numop = pcon.get_int(PCN_NUMIVDOPP);
      str.format("%02d", numop);
      record.overwrite(str,72);                  //Numero arabo IV dir      
    }

    _numrec++;            
    TString stringa;
    stringa.format("%06ld", _numrec);
    int posiz = _files.find("P");
    _control_rec.overwrite(stringa,((posiz * 6) + 47));
    _tras_file.write_control_rec(_control_rec,size);
    _tras_file.close();
    
    _tras_file.open(_trasf,TRUE);
    _tras_file.write_control_rec(record,size);
    _tras_file.close();
  } 
  delete _prog;  

  //Inizializzo l'ultima sigla file elaborato su trasfer con la sigla del file successivo da inviare
  //e inizializzo la chiave, altrimenti se si blocca l'invio subito dopo aver finito un file si rischia di 
  //ritrasferire l'ultimo record quando si riparte; inoltre non si riesce a inviare il file successivo perche'
  //la chiave e' compilata con i dati del file precedente.
  _tras_file.open(_trasf);
  leggi_record_controllo();
  TString chiave,app,sigla;
  app.format("%-15s", (const char*) chiave);
  char sigla_p = _tras_file.ult_file()[0];
  int posiz    = _files.find(sigla_p);
  TString nuova_sigla = " ";
  if (posiz < _files.len())
    nuova_sigla = _files.mid(posiz+1,1);
  
  _control_rec.overwrite(nuova_sigla,240);
  _control_rec.overwrite(app,241);
  _tras_file.write_control_rec(_control_rec,size);
  _tras_file.close();

  setta_tabella_ditta(m,"D",FALSE);  
  setta_parametri_record(m,"D");
  
  return TRUE;
}

bool TInv_cont::testata_mov_PN(long numreg)
{
  TLocalisamfile mov (LF_MOV);
  
  mov.setkey(1);
  mov.zero();
  mov.put(MOV_NUMREG, numreg);
  if (mov.read() == NOERR)
  {
    _datadoc  = mov.get_date(MOV_DATADOC);
    _numdoc   = mov.get     (MOV_NUMDOC);
    _reg      = mov.get     (MOV_REG);
    _codcausm = mov.get     (MOV_CODCAUS);
    _codpag   = mov.get     (MOV_CODPAG);
    _tipodoc  = mov.get     (MOV_TIPODOC);
    _protiva  = mov.get_long(MOV_PROTIVA);
    _uprotiva = mov.get_long(MOV_UPROTIVA);
    _inviato  = mov.get_bool(MOV_INVIATO);
  }           
  else
    return FALSE;
  
  return TRUE;
}

void TInv_cont::primanota_inviata(long numreg)
{
  TLocalisamfile mov (LF_MOV);
  
  mov.setkey(1);
  mov.zero();
  mov.put(MOV_NUMREG, numreg);
  if (mov.read() == NOERR)
  {
    mov.put(MOV_INVIATO, "X");
    mov.rewrite();
  }
}

bool TInv_cont::invio_mov_PN(TString& key,TMask& m)
{
  int size = 256;
  TString record(size);
  long numreg,nreg_p;
  int  numrig;
  TLocalisamfile rmov (LF_RMOV);
  
  nreg_p = -1;
  
  long cicli = rmov.items();
  cicli -= _numrec;
  _prog = new TProgind(cicli,"Invio Movimenti di primanota in corso... Prego attendere.",FALSE);
  
  if (key == "")                  
    rmov.first();
  else           
  { 
    numreg = atol(key.mid(2,6));
    numrig = atoi(key.mid(8,2));
    rmov.setkey(1);
    rmov.zero();
    rmov.put(RMV_NUMREG, numreg);
    rmov.put(RMV_NUMRIG, numrig);
    rmov.read();
  }
  
  for (; !rmov.eof(); rmov.next())
  { 
    TString str;
    
    _prog->addstatus(1);  
    
    _tras_file.open(_trasf);
    
    record.spaces();                                                     
    
    long nreg = rmov.get_long(RMV_NUMREG);
    int  nrig = rmov.get_int (RMV_NUMRIG);

    if (nreg != nreg_p)
      if (!testata_mov_PN(nreg))
        return error_box("Rilevata riga mancante di testata: impossibile proseguire");
    
    if (_inviato) continue; //Se il movimento e' gia' stato inviato non lo posso piu' inviare
    //cosi' come le sue righe di primanota e iva
    
    //Salvataggio della chiave sul record di controllo del file trasfer
    leggi_record_controllo();
    TString chiave,app;
    chiave.format("%2s%06ld%02d", (const char*) "Z1", nreg, nrig);
    app.format("%-15s", (const char*) chiave);
    _control_rec.overwrite("Z",240);
    _control_rec.overwrite(app,241);
    //    _tras_file.write_control_rec(_control_rec,size);
    //    _tras_file.close();

    TDate datareg (rmov.get(RMV_DATAREG)); 
    
    TString dataregstr = datareg.string();
    TString datalimstr = _datalimsk.string();
    
    if (datareg > _datalimsk) continue; //Se la data di operazione e' maggiore di quella
    //indicata nella maschera iniziale, il
    //movimento deve essere scartato.
    if (nreg > 999999)
      return error_box("Rilevato un numero di registrazione composto da 7 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    
    if (nrig > 99)
      return error_box("Rilevato un numero di riga composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    
    record.overwrite("Z1",0);                    //Tipo record
    
    str.format("%06ld", nreg);
    record.overwrite(str,2);                     //Numero di registrazione
    
    str.format("%02d", nrig);
    record.overwrite(str,8);                     //Numero di riga
    
    nreg_p = nreg;

    TString datastr = datareg.string();
    str = riconverti(dataregstr);
    record.overwrite(str,15);                    //Data di registrazione

    //Determino il segnalino della competenza
    int segnalino;
    
    int annoes = rmov.get_int(RMV_ANNOES);
    int anno   = date2esc(datareg);
    if (annoes == anno)
      segnalino = 0;
    else
      segnalino = 1;
    str.format("%d", segnalino);
    record.overwrite(str,21);                    //Segnalino della competenza
    
    TString datadocstr = _datadoc.string();                    
    str = riconverti(datadocstr);
    record.overwrite(str,22);                    //Data documento
    
    str.format("%-7s", (const char*) _numdoc);
    record.overwrite(str,28);
    
    if (!controlla_valore(_reg,9))
      return error_box("Rilevato un codice registro IVA composto da 2 o piu' cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    record.overwrite(_reg,35);                   //Codice registro IVA
    
    str.format("%05d", _protiva);
    record.overwrite(str,36);                    //Numero protocollo IVA
    
    // Se trovo un codice causale alfanumerico l'invio deve essere interrotto
    const char* cod_causm = (const char*)_codcausm;
    if (_codcausm != "")
      if (!real::is_natural(cod_causm))
        return error_box("Rilevato un codice causale alfanumerico in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%03s", (const char*)_codcausm);
    record.overwrite(str,41);                     //Codice causale
    
    TString descr = rmov.get(RMV_DESCR);
    str.format("%-.30s", (const char*) descr);
    record.overwrite(str,44);                     //Descrizione riga di movimento
    
    int gruppo = rmov.get_int(RMV_GRUPPO);
    if (gruppo > 99)
      return error_box("Rilevato un gruppo di partita composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%02d", gruppo);
    record.overwrite(str,74);                     //Gruppo di partita
    
    int conto = rmov.get_int(RMV_CONTO);
    if (conto > 99)
      return error_box("Rilevato un conto di partita composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);  
    str.format("%02d", conto);
    record.overwrite(str,76);                     //Conto di partita
    
    long sottoc = rmov.get_long(RMV_SOTTOCONTO);
    str.format("%06ld", sottoc);
    record.overwrite(str,78);                     //Sottoconto di partita
    
    TString sez = rmov.get(RMV_SEZIONE);
    str.format("%s", (const char*) sez);
    record.overwrite(str,84);                     //Sezione importo
    
    int gruppoc = rmov.get_int(RMV_GRUPPOC);
    if (gruppoc > 99)
      return error_box("Rilevato un gruppo di contropartita composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%02d", gruppoc);
    record.overwrite(str,85);                     //Gruppo di contropartita
    
    int contoc = rmov.get_int(RMV_CONTOC);
    if (contoc > 99)
      return error_box("Rilevato un conto di contropartita composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);    
    str.format("%02d", contoc);
    record.overwrite(str,87);                     //Conto di contropartita
    
    long sottocc = rmov.get_long(RMV_SOTTOCONTOC);
    str.format("%06ld", sottocc);
    record.overwrite(str,89);                     //Sottoconto di contropartita
    
    if (!controlla_valore(_codpag,99))
      return error_box("Rilevato un codice di pagamento composto da 3 o piu' cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%-2s", (const char*) _codpag);
    record.overwrite(str,95);                     //Codice di pagamento
    
    real importo (rmov.get_real(RMV_IMPORTO));
    str.format("%011s", (const char*) importo.string());
    record.overwrite(str,97);                     //Importo riga di movimento
    
    str.format("%05d", _uprotiva);
    record.overwrite(str,108);                    //Ultimo numero di protocollo IVA
    
    TString tipoc = rmov.get(RMV_TIPOC);
    record.overwrite(tipoc,219);                  //Flag cliente/fornitore
    
    record.overwrite(_tipodoc,220);               //Tipo documento

    _numrec++;            
    TString stringa;
    stringa.format("%06ld", _numrec);
    int posiz = _files.find("Z");
    _control_rec.overwrite(stringa,((posiz * 6) + 47));
    _tras_file.write_control_rec(_control_rec,size);
    _tras_file.close();
    
    _tras_file.open(_trasf,TRUE);
    _tras_file.write_control_rec(record,size);
    _tras_file.close();                      
    
    primanota_inviata(nreg);
  } 
  delete _prog;  

  //Inizializzo l'ultima sigla file elaborato su trasfer con la sigla del file successivo da inviare
  //e inizializzo la chiave, altrimenti se si blocca l'invio subito dopo aver finito un file si rischia di 
  //ritrasferire l'ultimo record quando si riparte; inoltre non si riesce a inviare il file successivo perche'
  //la chiave e' compilata con i dati del file precedente.
  _tras_file.open(_trasf);
  leggi_record_controllo();
  TString chiave,app,sigla;
  app.format("%-15s", (const char*) chiave);
  char sigla_p = _tras_file.ult_file()[0];
  int posiz    = _files.find(sigla_p);
  TString nuova_sigla = " ";
  if (posiz < _files.len())
    nuova_sigla = _files.mid(posiz+1,1);
  
  _control_rec.overwrite(nuova_sigla,240);
  _control_rec.overwrite(app,241);
  _tras_file.write_control_rec(_control_rec,size);
  _tras_file.close();
  
  setta_tabella_ditta(m,"D",FALSE);
  setta_parametri_record(m,"D");
  
  return TRUE;
}

bool TInv_cont::testata_mov_IVA(long numreg)
{
  TLocalisamfile mov (LF_MOV);
  
  mov.setkey(1);
  mov.zero();
  mov.put(MOV_NUMREG, numreg);
  if (mov.read() == NOERR)
  {
    _codcf      = mov.get_long(MOV_CODCF);
    _data74ter  = mov.get_date(MOV_DATA74TER);
    _corrlire   = mov.get_real(MOV_CORRLIRE);
    _codvali    = mov.get     (MOV_CODVALI);
    _cambioi    = mov.get_real(MOV_CAMBIOI);
    _corrval    = mov.get_real(MOV_CORRVALUTA);
    _ocfpi      = mov.get     (MOV_OCFPI);
    _dataregiva = mov.get_date(MOV_DATAREG);                            
    _inviato    = mov.get_bool(MOV_INVIVA);
    if (_ocfpi.not_empty())
      cerca_occasionale();
  }           
  else
    return FALSE;
  
  return TRUE;
}

void TInv_cont::iva_inviata(long numreg)
{
  TLocalisamfile mov (LF_MOV);
  
  mov.setkey(1);
  mov.zero();
  mov.put(MOV_NUMREG, numreg);
  if (mov.read() == NOERR)
  {
    mov.put(MOV_INVIVA, "X");
    mov.rewrite();
  }
}

void TInv_cont::cerca_occasionale()
{
  TLocalisamfile occas (LF_OCCAS);
  
  occas.setkey(1);
  occas.zero();
  occas.put(OCC_CFPI, _ocfpi);
  if (occas.read() == NOERR)
  {
    _ragsococc  = occas.get(OCC_RAGSOC);
    _indocc     = occas.get(OCC_INDIR);
    _capocc     = occas.get(OCC_CAP);
    TString com = occas.get(OCC_COM);
    cerca_comune_occas(com);
  }                         
  else
  {
    _ragsococc = "";
    _indocc    = "";
    _capocc    = "";
    _localocc  = "";
    _provocc   = "";
  }
}

void TInv_cont::cerca_comune_occas(const TString& com)
{
  TLocalisamfile comuni (LF_COMUNI);
  
  comuni.setkey(1);
  comuni.zero();
  comuni.put(COM_COM, com);
  if (comuni.read() == NOERR)
  {
    _localocc = comuni.get(COM_DENCOM);
    _provocc  = comuni.get(COM_PROVCOM);
  }
}                                       

bool TInv_cont::invio_mov_IVA(TString& key,TMask& m)
{
  int size = 256;
  TString record(size);
  long numreg,nreg_p;
  int  numrig;
  int  numero_righe = 0;
  TLocalisamfile rmoviva (LF_RMOVIVA);
  
  nreg_p = -1;
  
  long cicli = rmoviva.items();
  cicli -= _numrec;
  _prog = new TProgind(cicli,"Invio Movimenti iva in corso... Prego attendere.",FALSE);
  
  if (key == "")                  
    rmoviva.first();
  else           
  { 
    numreg = atol(key.mid(2,6));
    numrig = atoi(key.mid(8,2));
    rmoviva.setkey(1);
    rmoviva.zero();
    rmoviva.put(RMI_NUMREG, numreg);
    rmoviva.put(RMI_NUMRIG, numrig);
    rmoviva.read();
  }
  
  for (; !rmoviva.eof(); rmoviva.next())
  { 
    TString str;
    
    _prog->addstatus(1);
    
    _tras_file.open(_trasf);
    
    record.spaces();                                                     
    
    long nreg = rmoviva.get_long(RMI_NUMREG);
    int  nrig = rmoviva.get_int (RMI_NUMRIG);

    if (nreg != nreg_p) 
    { 
      numero_righe = 0;
      if (!testata_mov_IVA(nreg))
        return error_box("Rilevata riga mancante di testata: impossibile proseguire");
    }
    
    if (_inviato) continue;
    
    if (_dataregiva > _datalimsk) continue;      
    
    //Salvataggio della chiave sul record di controllo del file trasfer
    leggi_record_controllo();
    TString chiave,app;
    chiave.format("%2s%06ld%02d", (const char*) "U1", nreg, nrig);
    app.format("%-15s", (const char*) chiave);
    _control_rec.overwrite("U",240);
    _control_rec.overwrite(app,241);
    //    _tras_file.write_control_rec(_control_rec,size);
    //    _tras_file.close();

    if (nreg > 999999)
      return error_box("Rilevato un numero di registrazione composto da 7 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    
    if (nrig > 99)
      return error_box("Rilevato un numero di riga composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    
    record.overwrite("U1",0);                    //Tipo record
    
    str.format("%06ld", nreg);
    record.overwrite(str,2);                     //Numero di registrazione
    
    str.format("%02d", nrig);
    record.overwrite(str,8);                     //Numero di riga
    
    numero_righe++;
    if (numero_righe > 9)
      return error_box("Rilevata una registrazione IVA con piu' di 9 righe: impossibile proseguire");
    
    nreg_p = nreg;
    
    str.format("%06ld", _codcf);
    record.overwrite(str,15);                    //Codice cliente/fornitore
    
    real imponibile (rmoviva.get_real(RMI_IMPONIBILE));
    str.format("%011s", (const char*) imponibile.string());
    record.overwrite(str,21);                    //Imponibile

    //Se trovo un codice iva composto da piu' di 2 cifre l'invio viene interrotto    
    TString codiva (rmoviva.get(RMI_CODIVA));
    if ( codiva && *codiva && !real::is_natural(codiva) )
      return error_box("Rilevato un codice IVA alfanumerico in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    if (!controlla_valore(codiva,99))
      return error_box("Rilevato un codice IVA composto da 3 o piu' cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%02s", (const char*) codiva);
    record.overwrite(str,32);                    //Codice iva
    
    real imposta (rmoviva.get_real(RMI_IMPOSTA));
    str.format("%09s", (const char*) imposta.string());
    record.overwrite(str,34);                    //Imposta
    
    int tipocr = rmoviva.get_int(RMI_TIPOCR);
    str.format("%01d", tipocr);
    record.overwrite(str,43);                    //Tipo costo/ricavo
    
    int tipodet = rmoviva.get_int(RMI_TIPODET);
    str.format("%01d", tipodet);
    record.overwrite(str,44);                    //Tipo detraibilita'
    
    int gruppo = rmoviva.get_int(RMI_GRUPPO);
    if (gruppo > 99)
      return error_box("Rilevato un gruppo composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%02d", gruppo);
    record.overwrite(str,45);                    //Gruppo
    
    int conto = rmoviva.get_int(RMI_CONTO);
    if (conto > 99)
      return error_box("Rilevato un conto composto da 3 cifre in %07ld riga %03d: impossibile proseguire",nreg,nrig);
    str.format("%02d", conto);
    record.overwrite(str,47);                    //Conto
    
    long sottoc = rmoviva.get_long(RMI_SOTTOCONTO);
    str.format("%06ld", sottoc);
    record.overwrite(str,49);                    //Sottoconto
    
    TString data74terstr = _data74ter.string();
    str = riconverti(data74terstr);
    record.overwrite(str,55);                    //Data per registri 74 TER
    
    if (_ocfpi.not_empty())
    {
      str.format("%-.25s", (const char*) _ragsococc);
      record.overwrite(str,61);                  //Ragione sociale cliente occasionale
      
      str.format("%-.22s", (const char*) _indocc);
      record.overwrite(str,86);                  //indirizzo cliente occasionale
      
      str.format("%-.18s", (const char*) _localocc);
      record.overwrite(str,108);                 //Localita cliente occasionale
      
      str.format("%-5s", (const char*) _capocc);
      record.overwrite(str,126);                 //Codice avviamento postale cliente occasionale
      
      str.format("%-.2s", (const char*) _provocc);
      record.overwrite(str,131);                 //Provincia cliente occasionale
    }

    int tipoatt = rmoviva.get_int(RMI_TIPOATT);
    str.format("%01d", tipoatt);
    record.overwrite(str,133);                   //Tipo attivita'
    
    str.format("%011s", (const char*) _corrlire.string());
    record.overwrite(str,135);                   //Corrispettivo in lire
    
    record.overwrite(_codvali,146);              //Codice valuta
    
    str.format("%011s", (const char*) _cambioi.string());
    record.overwrite(str,149);                   //Cambio
    
    str.format("%014s", (const char*) _corrval.string());
    record.overwrite(str,160);                   //Corrispettivo in valuta

    _numrec++;            
    TString stringa;
    stringa.format("%06ld", _numrec);
    int posiz = _files.find("U");
    _control_rec.overwrite(stringa,((posiz * 6) + 47));
    _tras_file.write_control_rec(_control_rec,size);
    _tras_file.close();
    
    _tras_file.open(_trasf,TRUE);
    _tras_file.write_control_rec(record,size);
    _tras_file.close();
    
    iva_inviata(nreg);
  } 
  delete _prog;  

  //Inizializzo l'ultima sigla file elaborato su trasfer con la sigla del file successivo da inviare
  //e inizializzo la chiave, altrimenti se si blocca l'invio subito dopo aver finito un file si rischia di 
  //ritrasferire l'ultimo record quando si riparte; inoltre non si riesce a inviare il file successivo perche'
  //la chiave e' compilata con i dati del file precedente.
  _tras_file.open(_trasf);
  leggi_record_controllo();
  TString chiave,app,sigla;
  app.format("%-15s", (const char*) chiave);
  char sigla_p = _tras_file.ult_file()[0];
  int posiz    = _files.find(sigla_p);
  TString nuova_sigla = " ";
  if (posiz < _files.len())
    nuova_sigla = _files.mid(posiz+1,1);
  
  _control_rec.overwrite(nuova_sigla,240);
  _control_rec.overwrite(app,241);
  _tras_file.write_control_rec(_control_rec,size);
  _tras_file.close();

  setta_tabella_ditta(m,"D",FALSE);
  setta_parametri_record(m,"D");
  
  return TRUE;
}

bool TInv_cont::menu(MENU_TAG m)
{
  if (m == BAR_ITEM(1))
    return main_loop(); 
  return FALSE;
}

int cg2900 (int argc, char* argv[])
{                                
  TInv_cont a;
  
  a.run(argc,argv, "Invio contabilita'");

  return TRUE;
}
