#include <applicat.h>
#include <automask.h>
#include <config.h>
#include <isam.h>
#include <progind.h>
#include <recarray.h>
#include <relation.h>

#include "vesirio.h"
#include "vesirioa.h"

#include "doc.h"
#include "rdoc.h"
#include "mov.h"
#include "rmov.h"
#include "partite.h"
#include "rmoviva.h"
#include "velib.h"

//=====MASCHERA============================================================//
class TToas400_mask : public TAutomask
{

protected:
  bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
  TToas400_mask();  
  virtual ~TToas400_mask() {};
};

TToas400_mask::TToas400_mask() :TAutomask ("vesirioa") {}

bool TToas400_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
  switch (o.dlg())
  {
  case F_BOLLE :
  case F_FATTURE :
  case F_MOVCONT :
    if (e == fe_close)
    {
      if (!get_bool(F_BOLLE) && !get_bool(F_FATTURE) && !get_bool(F_MOVCONT))     //deve essere selezionata almeno 1 situaz.
        return error_box("Selezionare almeno uno dei tipi documento da esportare");     
    }
    break;
  case F_DATA_TRASF :
    if (e == fe_close)
    {
      if ((get_date(F_DATA_TRASF) < get_date(F_DATA_ULT_TRASF_B))&&(get_bool(F_BOLLE)))
        return error_box("La data di trasferimento bolle non e' congruente");
      if ((get_date(F_DATA_TRASF) < get_date(F_DATA_ULT_TRASF_F))&&(get_bool(F_FATTURE)))
        return error_box("La data di trasferimento fatture non e' congruente");
      if ((get_date(F_DATA_TRASF) < get_date(F_DATA_ULT_TRASF_M))&&(get_bool(F_MOVCONT)))
        return error_box("La data di trasferimento movimenti contabili non e' congruente");
    }
    break;
  default: break;
  }
  return TRUE;
}

//=====APPLICAZIONE====================================================//
class TToas400 : public TSkeleton_application
{
  TToas400_mask* _mask;
  TDate _dataultb, _dataultf, _dataultm, _datacurr;
  TString _trrpath;

protected:
  void copia_rigadoc(TRectype& recdest, const TRectype& recsource, const TRectype& rectestata) const;
  bool genera_righedoc(const TString& path, char tipo);

  void copia_documento(TRectype& recdest, const TRectype& recsource, const TRectype& recriga) const;
  bool genera_documenti(const TString& path, char tipo);

  void copia_rigamov(TRectype& recdest, const TRectype& recsource) const;
  bool genera_righemov(const TString& path);

  void copia_rigaiva(TRectype& recdest, const TRectype& recsource) const;
  bool genera_righeiva(const TString& path);

  void copia_movimento(TRectype& recdest, const TRectype& recsource, const TRectype& recriga, const TRectype& recpartita) const;
  bool genera_movimenti(const TString& path);

  bool genera_bolle(const TString& path);
  bool genera_fatture(const TString& path);
  bool genera_movcont(const TString& path);

  void azzera_campi(TRectype& rectozero) const;
  int separa_sconti(const TString& sconto, TToken_string& sconti4) const;
  void ini2mask();

public:
  virtual bool create();
  virtual bool destroy();
  virtual void main_loop();
};


bool TToas400::create()
{
  open_files(LF_DOC, 0);
  _mask = new TToas400_mask;
  
  return TSkeleton_application::create();
}

bool TToas400::destroy()
{
  delete _mask;
  return TSkeleton_application::destroy();
}

void TToas400::ini2mask()
{
//carica i parametri di trasferimento dal ditta.ini
  TConfig fileini(CONFIG_DITTA, "Sirio");
  _trrpath = fileini.get("PATH");
  _dataultb = fileini.get("DATAULTB");
  _dataultf = fileini.get("DATAULTF");
  _dataultm = fileini.get("DATAULTM");

  _mask->set(F_PATH, _trrpath);

  TToken_string ultimo;

  _mask->set(F_DATA_ULT_TRASF_B, _dataultb);
  ultimo = fileini.get("bolle", NULL, -1, "2004|B01");
  _mask->set(F_NUM_B, ultimo.get(1));
  
  _mask->set(F_DATA_ULT_TRASF_F, _dataultf);
  ultimo = fileini.get("fatt", NULL, -1, "2004|FAA");
  _mask->set(F_NUM_F, ultimo.get(1));
  
  _mask->set(F_DATA_ULT_TRASF_M, _dataultm);
}

//_________________________________________________________________________________________________________________________
//DOCUMENTI DI VENDITA

//metodo per la copia delle righe documenti (bolle/fatture) sul file .dbf di destinazione
void TToas400::copia_rigadoc(TRectype& recdest, const TRectype& recsource, const TRectype& rectestata) const
{
  azzera_campi(recdest);  //mette 0 in tutti i campi numerici (compresi quelli che non saranno riempiti)
  
  TString4 coddep = recsource.get(RDOC_CODMAG).left(3);
  recdest.put("I6CDEP", coddep);                              //cod.deposito
  
  recdest.put("I6CCLI",rectestata.get(DOC_CODCF));             //cod.cliente (da testata)
  recdest.put("I6TDO1",rectestata.get(DOC_TIPODOC));           //tipodoc (da testata)
  recdest.put("I6CNMV",rectestata.get(DOC_CODNUM));            //cod.num.doc (da testata)
  recdest.put("I6NDOC",recsource.get(RDOC_NDOC));             //num.doc (=testata)
  recdest.put("I6NRIG",recsource.get(RDOC_NRIGA));            //num.riga
  recdest.put("I6TRIG", "1");                                 //tiporiga 1 (sono solo riga merce)
  recdest.put("I6CART",recsource.get(RDOC_CODARTMAG));        //cod.art
  recdest.put("I6CLIN",recsource.get(RDOC_LINEA));            //cod.linea (x MRP?)
  recdest.put("I6DCO1",recsource.get(RDOC_DESCR).left(35));   //descriz.1
  recdest.put("I6DCO2",recsource.get(RDOC_DESCR).mid(35));    //descriz.2 
  recdest.put("I6CUMI",recsource.get(RDOC_UMQTA));            //unit� di misura
  recdest.put("I6CIVA",recsource.get(RDOC_CODIVA));           //cod.iva
  
  real qta = recsource.get(RDOC_QTA);
  if (qta.is_zero())
    qta = 9999999999999.0;
  recdest.put("I6QARM",qta);                                  //quantit� (9999999999999 se 0; mah?)
  
  real prezzoven = recsource.get(RDOC_PREZZO);                
  if (prezzoven.is_zero())
    prezzoven = 9999999999999.0;
  recdest.put("I6LUNI",prezzoven);                            //prezzo vendita unitario lordo(9999999999999 se 0; mah?)
  
  const TString& sconto = recsource.get(RDOC_SCONTO);
  if (sconto.not_empty())   //%sconto   (achtung! x as400 � % x eurocampo una espressione)
  {
    TToken_string sconti4;
    int s = separa_sconti(sconto, sconti4);   //metodo che separa l'espressione di sconto
    char campo[7] = "I6PSR1";  
    for (int i = 0; i < s; i++)
    {
      campo[5] = '1'+i;
      recdest.put(campo, sconti4.get(i));    //mette nei campi i valori degli sconti
    }                                    
  }
  
  recdest.put("I6PPR1",recsource.get(RDOC_PERCPROV));         //%provvigione 1
  
  TString area;
  area << "   " << "000000000000000000";
  const TRectype& tiporiga = cache().get("%TRI", recsource.get(RDOC_TIPORIGA));
  TString8 codriga;
  switch (tiporiga.get_char("S7"))
  {
    case 'C': codriga = "SM"; break;
    case 'O': codriga = "OG"; break;
    default: codriga = "  "; break;
  }
  area << codriga;  
  recdest.put("I6AREA", area);      //campo personalizzabile: ci va una strana stringa...mah?
  
}

//metodo che "fraziona" la formula di sconto riga nei suoi componenti; se ci sono 4 o + numeri -> mette nel quarto numero
//lo sconto complessivo di quelli dal quarto in avanti
int TToas400::separa_sconti(const TString& sconto, TToken_string& sconti4) const
{
    sconti4.cut(0);  
// Elimina gli spazi molesti sulla stringa dello sconto (ovviamente copiata, X' l'originale non si tocca)
    TString sconto_orig = sconto;
    sconto_orig.strip_spaces( );
//aggiunge un segno iniziale + qualora non esistesse alcun segno
    if (sconto_orig[0] != '+' &&  sconto_orig[0] != '-')
      sconto_orig.insert("+");
//assegna agli elementi della token_string i valori numerici ed i segni    
    int numsconti = 0;
    for (int i=0; sconto_orig[i]; i++)
    { 

//se il carattere � un segno -> devo cambiare elemento della token string (mettendo '|' ma non nel caso del primo segno)
      if (sconto_orig[i] == '+' || sconto_orig[i] == '-')
      { 
        if (numsconti++ > 0)    //incrementa numsconti di 1 
          sconti4 << '|';
        if (numsconti > 3)  
          break;
      }
      
//se numero -> scrive il carattere sulla token_string..     
      sconti4 << sconto_orig[i];
    }
    
//adesso piazza nel quarto elemento i valori degli elementi dal quarto in avanti
    const TString oltre = sconto_orig.mid(i);
    if (oltre.not_empty())
    {
      TString pipo;
      real psconto;    
      scontoexpr2perc(oltre, 0, pipo, psconto);
      psconto = 100 - 100*psconto;                 //lo mette in percentuale
      psconto.round(2);                            //arrotonda al secondo decimale    
      sconti4.add(psconto.string(),3);             //aggiunge psconto alla posizione 4
    }
    return sconti4.items();
}

// tipo -> B=bolle, F=fatture                                                                     
bool TToas400::genera_righedoc(const TString& path, char t)
{ 
//Crea il file vuoto delle righe documenti
  const char* tipor = t == 'B' ? "rbolle" : "rfatt";
  TFilename trrrig = path; trrrig.add(tipor); trrrig.ext("trr");
  TFilename siriorig = path; siriorig.add(tipor); siriorig.ext("dbf");

  TExternisamfile righe(siriorig, trrrig);
  righe.zap();

//lettura da prassid.ini dell'ultima bolla/fattura trasferita
//ATTENZIONE!La numerazione documenti � unica per bolle e fatture rispettivamente! Ovvero non � possibile trasferire 2 tipi
//di fatture con codice diverso (o 2 tipi di bolle con codice diverso)  
  TConfig fileini(CONFIG_DITTA, "Sirio");
  TToken_string ultimo = fileini.get(tipor+1, NULL, -1, t == 'B' ? "2004|B01" : "2004|FAA");
  
//scandisce il file doc.dbf alla ricerca dei documenti non ancora esportati...
  TRelation rel(LF_RIGHEDOC);
  TString expr;
  expr << "CODNUM==CODNUM|ANNO==ANNO|NDOC==NDOC|PROVV==PROVV" ;
  rel.add(LF_DOC, expr);    //aggiunge alla relazione (in origine sulle righe) il file delle testate x' necessita di alcuni campi di questo file

//..intanto si memorizza il record di partenza, che � quello successivo all'ultimo trasferito..
  TRectype& recsource = rel.curr();
  recsource.put(RDOC_PROVV, "D");
  recsource.put(RDOC_ANNO, ultimo.get(0));
  recsource.put(RDOC_CODNUM, ultimo.get(1));
  recsource.put(RDOC_NDOC, ultimo.get_long(2)+1);

//..quindi si crea il filtro ed il cursore per scandire il file delle righe documento..  
  TString filtro;
  filtro << "(CODNUM==\"" << ultimo.get(1) << "\")";
  _datacurr = _mask->get_date(F_DATA_TRASF);
  filtro << "&&(ANSI(33->DATADOC)<=" << _datacurr.date2ansi() << ")";
  TCursor cur(&rel, "", 1, &recsource);
  cur.setfilter(filtro, true);
  const long items = cur.items();
  cur.freeze();
  
  TString caption; caption << "Elaborazione " << tipor << "...";
  TProgind pi(items, caption, TRUE, TRUE);

//..prepara i record di origine e destinazione e procede al trasferimanto dati campo per campo  
  TRectype& recdest = righe.curr();     
  const TRectype& testata = rel.curr(LF_DOC);
  int nriga = 1;
  long ultimodoc = 0;
  
  for (cur = 0L; cur.pos() < items; ++cur)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;
    
    long currdoc = recsource.get_long(RDOC_NDOC);
    if (currdoc != ultimodoc)
    {
      ultimodoc = currdoc;
      nriga = 1;
    }
    const TString& codartmag = recsource.get(RDOC_CODARTMAG);
    if (codartmag.not_empty())   //vogliamo solo righe merce!
    { 
      recsource.put(RDOC_NRIGA, nriga++); //incrementa il numero riga se rigamerce
      copia_rigadoc(recdest, recsource, testata); 
      const int err = righe.write();
      if (err != NOERR)
        return error_box("Errore %d di registrazione %s", err, tipor); 
    }

  }
  
  return !pi.iscancelled();
}

void TToas400::copia_documento(TRectype& recdest, const TRectype& recsource, const TRectype& recriga) const
{
  
  azzera_campi (recdest); //mette 0 in tutti i campi numerici (compresi quelli che non saranno riempiti)
  
  TString4 coddep = recriga.get(RDOC_CODMAG).left(3);  
  recdest.put("I5CDEP", coddep);                      //cod. deposito (viene preso = a quello della prima riga! mah!?)
  
  recdest.put("I5CCLI", recsource.get(DOC_CODCF));    //cod.cliente
  recdest.put("I5TDO1", recsource.get(DOC_TIPODOC));  //tipo doc. appl.esterno         
  recdest.put("I5CNMV", recsource.get(DOC_CODNUM));   //cod.num.appl.esterno
  recdest.put("I5UDOC", recsource.get_date(DOC_DATADOC).string(ANSI));  //data doc.appl.esterno
  recdest.put("I5NDOC", recsource.get(DOC_NDOC));     //num.doc.appl.esterno
  recdest.put("I5CPAG", recsource.get(DOC_CODPAG));   //cod.condizione pagamento
  
  TString16 codabicab = recsource.get(DOC_CODABIA);
  codabicab << recsource.get(DOC_CODCABA);
  recdest.put("I5CABI", codabicab);                 //codice banca abi cab
  
  recdest.put("I5CLIG", recsource.get(DOC_CODLIN));   //cod.lingua
  recdest.put("I5CPOR", recsource.get(DOC_CODPORTO)); //cod.porto
  recdest.put("I5CMEZ", recsource.get(DOC_CODSPMEZZO));  //cod.mezzo
  recdest.put("I5CVE1", recsource.get(DOC_CODVETT1));   //cod.vett.1
  recdest.put("I5CVE2", recsource.get(DOC_CODVETT2));   //cod.vett.2
  recdest.put("I5CVE3", recsource.get(DOC_CODVETT3));   //cod.vett.3
  recdest.put("I5CZON", recsource.get(DOC_ZONA));       //cod.zona
  
  const TRectype& tpdoc = cache().get("%TIP", recsource.get(DOC_TIPODOC));
  recdest.put("I5CCVE", tpdoc.get("S6"));            //cod.causale di vendita
  recdest.put("I5CCMO", tpdoc.get("S9"));     //cod.caus.magazzino su tabella tipodocumenti batbtip 
  
  recdest.put("I5CVAL", recsource.get(DOC_CODVAL));      //cod.valuta
  
  const bool is_controeuro = recsource.get_bool(DOC_CONTROEURO); //valore cambio
  real cambio = recsource.get_real(DOC_CAMBIO);
  if (!is_controeuro && cambio > ZERO)
    cambio = 1936.27/cambio;
  recdest.put("I5ICAM", cambio); 

  recdest.put("I5CAG1", recsource.get(DOC_CODAG));       //cod.agente
  recdest.put("I5CASP", recsource.get(DOC_ASPBENI1));     //cod. aspetto beni
  recdest.put("I5PSCA", recsource.get(DOC_SCONTOPERC));   //sconto testata documento
  recdest.put("I5NCLP", recsource.get(DOC_NCOLLI));      //num.colli
  
  real pnetto = recsource.get_real(DOC_PNETTO);
  recdest.put("I5QPNE", pnetto);      //peso netto merce
  real plordo  = pnetto;
  
  const TString4 umpnetto = recsource.get(DOC_UMPNETTO);    //peso lordo (se non ha un'unica unit� di misura tra pnetto e tara
  const TString4 umtara = recsource.get(DOC_UMTARA);        //fa plordo = pnetto
  if (umpnetto == umtara)
    plordo += recsource.get_real(DOC_TARA);
  recdest.put("I5QPLO", plordo);
  
}

// tipo -> B=bolle, F=fatture                                                                     
bool TToas400::genera_documenti(const TString& path, char t)
{                                                          
  const char* tipo = t == 'B' ? "bolle" : "fatt";
 
//crea il file delle testate delle bolle utilizzando bolle.trr come tracciato record
  TFilename siriodoc = path; siriodoc.add(tipo); siriodoc.ext("dbf");
  TFilename trrdoc = path; trrdoc.add(tipo); trrdoc.ext("trr");

  TExternisamfile documenti(siriodoc, trrdoc);
  documenti.zap();

//lettura da prassid.ini dell'ultima bolla/fattura trasferita (se non la trova, di default mette B01|2002|D|0)  
  TConfig fileini(CONFIG_DITTA, "Sirio");
  TToken_string ultimo = fileini.get(tipo, NULL, -1, t == 'B' ? "2004|B01" : "2004|FAA");
  
//scandisce il file doc.dbf alla ricerca dei documenti non ancora esportati...
  TRelation rel(LF_DOC);
  TString expr;
  expr << "PROVV==PROVV|ANNO==ANNO|CODNUM==CODNUM|NDOC==NDOC";
  rel.add(LF_RIGHEDOC, expr);    //aggiunge alla relazione (in origine sulle testate) il file delle righe x' necessita di alcuni campi di questo file

//..intanto si memorizza il record di partenza, che � quello successivo all'ultimo trasferito..
  TRectype& recsource = rel.curr();
  recsource.put(DOC_PROVV, "D");
  recsource.put(DOC_ANNO, ultimo.get(0));
  recsource.put(DOC_CODNUM, ultimo.get(1));
  recsource.put(DOC_NDOC, ultimo.get_long(2)+1);
//..quindi si crea il filtro ed il cursore per scandire il file delle testate documento..  
  TString filtro;
  filtro << "CODNUM==\"" << ultimo.get(1) << "\"";
  _datacurr = _mask->get_date(F_DATA_TRASF);
  filtro << "&&(ANSI(DATADOC)<=" << _datacurr.date2ansi() << ")";
  TCursor cur(&rel, filtro, 1, &recsource);
  const long items = cur.items();
  cur.freeze();
  
  TString caption; caption << "Elaborazione " << tipo << "...";
  TProgind pi(items, caption, TRUE, TRUE);

//..prepara i record di origine e destinazione e procede al trasferimanto dati campo per campo  
  TRectype& recdest = documenti.curr();
  const TRectype& righe = rel.curr(LF_RIGHEDOC);
  for (cur = 0; cur.pos() < items; ++cur)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;
      
    copia_documento(recdest, recsource, righe);  //copia i files delle testate  
    
    const int err = documenti.write();
    if (err != NOERR)
      return error_box("Errore %d di registrazione %s", err, tipo);
    
    // Calcola identificatore ultimo record trasferito
    ultimo = recsource.get(DOC_ANNO);
    ultimo.add(recsource.get(DOC_CODNUM));
    ultimo.add(recsource.get(DOC_NDOC));
  } 

  const bool ok = !pi.iscancelled();
  if (ok)
  {
    fileini.set(tipo, ultimo);
    TString16 tipodata; tipodata << "DATAULT" << t;
    fileini.set(tipodata, _datacurr);
  }

  return ok;
}

//___________________________________________________________________________________________________________________________
//MOVIMENTI CONTABILI

bool TToas400::genera_righemov(const TString& path)
{                                                          
//crea il file vuoto delle righe movimenti utilizzando rmovc.trr come tracciato record
  TFilename siriomov = path; siriomov.add("rmovc"); siriomov.ext("dbf");
  TFilename trrmov = path; trrmov.add("rmovc"); trrmov.ext("trr");

  TExternisamfile righe(siriomov, trrmov);
  righe.zap();
//lettura da prassid.ini dell'ultimo movimento trasferito  
  TConfig fileini(CONFIG_DITTA, "Sirio");
  TToken_string ultimo = fileini.get("Movimenti");
  
//scandisce il file rmov.dbf alla ricerca delle righe movimento non ancora esportate...
  TRelation rel(LF_RMOV);

//..intanto si memorizza il record di partenza, che � quello successivo all'ultimo trasferito..
  TRectype& recsource = rel.curr();
  recsource.put(RMV_NUMREG, ultimo.get_long(0));
  recsource.put(RMV_NUMRIG, ultimo.get(1));

//..quindi si crea il filtro ed il cursore per scandire il file delle righe documento..
  TString filtro;
  filtro << "NUMREG==\"" << ultimo.get(0) << "\"";
  TCursor cur(&rel, "", 1, &recsource);
  const long items = cur.items();
  cur.freeze();
  
  TString caption; caption << "Elaborazione righe movimenti...";
  TProgind pi(items, caption, TRUE, TRUE);

//..prepara i record di origine e destinazione e procede al trasferimanto dati campo per campo  
  TRectype& recdest = righe.curr();
  const TRectype& testata = rel.curr(LF_MOV);
  int nriga = 1;
  long ultimomov = 0;
  
  for (cur = 0L; cur.pos() < items; ++cur)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;
    
    long currmov = recsource.get_long(RMV_NUMREG);
    if (currmov != ultimomov)
    {
      ultimomov = currmov;
      nriga = 1;
    }
//    const TString& tipocausale = recsource.get(RMOV_);
//    if (tipocausale == )     //vogliamo solo righe pagamento!
    { 
      recsource.put(RMV_NUMRIG, nriga++); //incrementa il numero riga se rigapagamento 
      copia_rigamov(recdest, recsource);      
      const int err = righe.write();
      if (err != NOERR)
        return error_box("Errore %d di registrazione righe movimenti", err);
    }
  } 

  const bool ok = !pi.iscancelled();
  return ok;
}

void TToas400::copia_rigamov(TRectype& recdest, const TRectype& recsource) const
{
  recdest.zero();
}

/* Molto probabilmente inutile
void TToas400::copia_rigaiva(TRectype& recdest, const TRectype& recsource) const
{
  recdest.zero();
}

bool TToas400::genera_righeiva(const TString& path)
{                                                          
//crea il file delle testate delle bolle utilizzando bolle.trr come tracciato record
  TFilename siriomov = path; siriomov.add("rmoviva"); siriomov.ext("dbf");
  TFilename trrmov = path; trrmov.add("rmoviva"); trrmov.ext("trr");

  TExternisamfile movimenti(siriomov, trrmov);
  movimenti.zap();
//lettura da prassid.ini dell'ultima bolla trasferita (se non la trova, di default mette B01|2002|D|0)  
  TConfig fileini(CONFIG_DITTA, "Sirio");
  TToken_string ultimo = fileini.get("Movimenti");
  
//scandisce il file doc.dbf alla ricerca dei documenti non ancora esportati...
  TRelation rel(LF_RMOVIVA);

//..intanto si memorizza il record di partenza, che � quello successivo all'ultimo trasferito..
  TRectype& recsource = rel.curr();
  recsource.put(MOV_NUMREG, ultimo.get(0));

  TCursor cur(&rel, "", 1, &recsource);
  const long items = cur.items();
  cur.freeze();
  
  TString caption; caption << "Elaborazione righe IVA...";
  TProgind pi(items, caption, TRUE, TRUE);

//..prepara i record di origine e destinazione e procede al trasferimanto dati campo per campo  
  TRectype& recdest = movimenti.curr();
  for (cur = 0; cur.pos() < items; ++cur)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;
      
    copia_rigaiva(recdest, recsource);  
    
    const int err = movimenti.write();
    if (err != NOERR)
      return error_box("Errore %d di registrazione righe iva", err);
  } 

  const bool ok = !pi.iscancelled();
  return ok;
}
*/

bool TToas400::genera_movimenti(const TString& path)
{                                                          
//crea il file delle testate dei movimenti contabili di pagamento utilizzando movc.trr come tracciato record
  TFilename siriomov = path; siriomov.add("movc"); siriomov.ext("dbf");
  TFilename trrmov = path; trrmov.add("movc"); trrmov.ext("trr");

  TExternisamfile movimenti(siriomov, trrmov);
  movimenti.zap();
//lettura da prassid.ini dell'ultimo movimento trasferito (se non lo trova, di default mette 1|MOV 
  TConfig fileini(CONFIG_DITTA, "Sirio");
  TToken_string ultimo = fileini.get("Movimenti", NULL, -1, "0");
  
//scandisce il file mov.dbf alla ricerca dei movimenti non ancora esportati...
  TRelation rel(LF_MOV);
//aggiunge alla relazione il file delle righemov e quello delle partite (gli servono per alcuni campi)
  rel.add(LF_RMOV, "NUMREG==NUMREG");
  rel.add(LF_PARTITE, "NUMREG==NUMREG", 2);

//..intanto si memorizza il record di partenza, che � quello successivo all'ultimo trasferito..
  TRectype& recsource = rel.curr();
  recsource.put(MOV_NUMREG, ultimo.get_long(0));

//..quindi si crea il filtro ed il cursore per scandire il file delle testate movimenti..  
  TString filtro;
  filtro << "NUMREG==\"" << ultimo.get(0) << "\"";  
  TCursor cur(&rel, filtro, 1, &recsource);
  const long items = cur.items();
  cur.freeze();
  
  TString caption; caption << "Elaborazione movimenti...";
  TProgind pi(items, caption, TRUE, TRUE);

//..prepara i record di origine e destinazione e procede al trasferimanto dati campo per campo  
  TRectype& recdest = movimenti.curr();
  const TRectype& righe = rel.curr(LF_RMOV);
  const TRectype& partite = rel.curr(LF_PARTITE);
  for (cur = 0; cur.pos() < items; ++cur)
  {
    pi.addstatus(1);
    if (pi.iscancelled())
      break;
      
    copia_movimento(recdest, recsource, righe, partite);  
    
    const int err = movimenti.write();
    if (err != NOERR)
      return error_box("Errore %d di registrazione movimenti", err);
    
    // Calcola identificatore ultimo record trasferito
    ultimo = recsource.get(MOV_NUMREG);
  } 

  const bool ok = !pi.iscancelled();
  if (ok)
  {
    fileini.set("Movimenti", ultimo);
    fileini.set("DATAULTM", _datacurr);
  }

  return ok;
}


void TToas400::copia_movimento(TRectype& recdest, const TRectype& recsource, const TRectype& recriga, const TRectype& recpartita) const
{
  azzera_campi (recdest);  //mette 0 in tutti i campi numerici (compresi quelli che non saranno riempiti)
  
  recdest.put("CMTMCO", "Z"); //misterioso campo in cui va scritta Z; � il campo Zorro?
  recdest.put("CMUREG", recsource.get_date(MOV_DATAREG).string(ANSI));   //data registraz. contabile (data competenza) (in formato string)
  recdest.put("CMNPRO", recsource.get(MOV_NUMREG));     //numero registraz. contabile (numero operazione)
  recdest.put("CMUDOC", recsource.get_date(MOV_DATADOC).string(ANSI));    //data documento
  recdest.put("CMNDCM", recsource.get(MOV_NUMDOC));     //numero documento
  recdest.put("CMFADA", recsource.get(RMV_SEZIONE));    //flag mov dare avere (preso dalla prima rigamov)
  recdest.put("CMITOD", recsource.get(MOV_TOTDOC));     //importo in valuta di bilancio (totale documento)
  
  TString16 codcli;
  codcli << "C   " << recsource.get(MOV_CODCF);
  recdest.put("CMCPIA", codcli);    //codice cliente
  
  TDate data = recsource.get_date(MOV_DATADOC);
  TString8 dataok = data.string(ANSI);
  dataok.cut(6);
  recdest.put("CMUAMR", dataok);                   //data documento in formato YYYYMM per pareggio con fattura
  
  recdest.put("CMNRIP", recsource.get(MOV_NUMDOC));      //num.doc. fattura per pareggio con fattura (=CMNDCM)

  recdest.put("CMTCAU", "P");                     //tipo causale movimento:solo Pagamenti (filtro in genera movimenti)
  
//  recdest.put("CMTEFF", recsource.get(MOV_));     //tipo del pagamento
  
//  recdest.put("CMUSCA", recsource.get(MOV_));       //data scadenza

  recdest.put("CMCVAL", recsource.get(MOV_CODVAL));  //codice valuta estera
  recdest.put("CMICAM", recsource.get(MOV_CAMBIO));  //cambio
  recdest.put("CMITOV", recsource.get(MOV_TOTDOCVAL)); //totale doc in valuta
  
  recdest.put("CMDMO1", recsource.get(MOV_DESCR).left(25)); //prima descrizione
  recdest.put("CMDMO2", recsource.get(MOV_DESCR).mid(25));  //seconda descrizione
  
  recdest.put("CMUREB", recsource.get_date(MOV_DATACOMP).string(ANSI)); //data di registrazione
}

//___________________________________________________________________________________________________________________________
//GENERALE

void TToas400::azzera_campi(TRectype& rectozero) const
{ 
  rectozero.zero();  //svuota i campi
  int numfields = rectozero.items();
  for (int i = 0 ; i < numfields; i++)
  { 
    const char* fieldname = rectozero.fieldname(i);
    switch (rectozero.type(fieldname))
    {
      case _intfld:
      case _longfld:
      case _realfld:
      case _datefld:
      case _intzerofld:
      case _longzerofld:
        rectozero.put(fieldname, "0");
        break;
        
      default: break;      
    }    
  }    
}


bool TToas400::genera_bolle(const TString& path)
{                     
  bool ok = genera_righedoc(path, 'B');
  if (ok)
    ok = genera_documenti(path, 'B');
  return ok;
}

bool TToas400::genera_fatture(const TString& path)
{                     
  bool ok = genera_righedoc(path, 'F');
  if (ok)
    ok = genera_documenti(path, 'F');
  return ok;  
}

bool TToas400::genera_movcont(const TString& path)
{
  bool ok = genera_righemov(path);
/*  Molto probabilmente inutile
  if (ok)
    ok = genera_righeiva(path);
*/    
  if (ok)
    ok = genera_movimenti(path);
  return ok;  
}

void TToas400::main_loop()
{   
  // Prececchiamo tutto
  _mask->set(F_BOLLE,"X");
  _mask->set(F_FATTURE,"X");
//  _mask->set(F_MOVCONT,"X");  da accendere quando ci sara' il tracciato dei movimenti

  while (true)
  { 
    ini2mask(); //inizializza la maschera con i parametri di configurazione
    if (_mask->run() != K_ENTER)
      break;

    const TString& path = _mask->get(F_PATH);  
    bool ok = true;

    if (ok && _mask->get_bool(F_BOLLE))
      ok = genera_bolle(path);
    if (ok && _mask->get_bool(F_FATTURE))
      ok = genera_fatture(path);
    if (ok && _mask->get_bool(F_MOVCONT))
      ok = genera_movcont(path);

    if (ok) //se almeno uno dei trasferimenti e' andato a buon fine, registra il PATH sul ditta.ini
    {
      _trrpath = _mask->get(F_PATH);
      TConfig fileini(CONFIG_DITTA, "Sirio");
      fileini.set("PATH", _trrpath);
    }
  }
}

//===================================================================//
int vesirio1(int argc, char* argv[])
{ 
  TToas400 a;
  a.run(argc,argv,TR("Esportazione documenti ad AS400"));
  return 0;
}