1425 lines
40 KiB
C++
1425 lines
40 KiB
C++
|
#include <applicat.h>
|
|||
|
#include <automask.h>
|
|||
|
#include <config.h>
|
|||
|
#include <execp.h>
|
|||
|
#include <golem.h>
|
|||
|
#include <progind.h>
|
|||
|
#include <reputils.h>
|
|||
|
#include <tabutil.h>
|
|||
|
#include <utility.h>
|
|||
|
#include <agasys.h>
|
|||
|
|
|||
|
#include "../ve/velib05.h"
|
|||
|
#include "../cg/cglib03.h"
|
|||
|
|
|||
|
#include "tf0.h"
|
|||
|
#include "tf0100a.h"
|
|||
|
|
|||
|
#include "../fe/felib.h"
|
|||
|
|
|||
|
#include <mov.h>
|
|||
|
#include <rmoviva.h>
|
|||
|
#include <anagiu.h>
|
|||
|
#include <comuni.h>
|
|||
|
#include <cfven.h>
|
|||
|
#include <nditte.h>
|
|||
|
#include <unloc.h>
|
|||
|
#include <causali.h>
|
|||
|
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// Globals
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
static XVT_SQLDB _db = NULL; // TFF sqlite db
|
|||
|
enum return_code
|
|||
|
{
|
|||
|
found, // Trovato
|
|||
|
movcustom, // Trovato in trasfatt
|
|||
|
nextmov, // Trovato ma cambiato movimento
|
|||
|
eof, // EOF rmoviva
|
|||
|
eofm, // EOF mov
|
|||
|
after // File mov su un movimento dopo rispetto a rmoviva
|
|||
|
};
|
|||
|
|
|||
|
enum filter_fatt
|
|||
|
{
|
|||
|
toSend, // Da inviare
|
|||
|
sent, // Inviate
|
|||
|
all // Tutte
|
|||
|
};
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// Utilities
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
// Cerca una stringa all'interno di una SLIST (Potrebbe diventare una funzione di XVT.h)
|
|||
|
static SLIST_ELT xvt_slist_find_str(SLIST list, const char* str)
|
|||
|
{
|
|||
|
SLIST_ELT e = NULL;
|
|||
|
for (e = xvt_slist_get_first(list); e; e = xvt_slist_get_next(list, e))
|
|||
|
{
|
|||
|
const char* val = xvt_slist_get(list, e, NULL);
|
|||
|
if (xvt_str_compare_ignoring_case(str, val) == 0)
|
|||
|
break;
|
|||
|
}
|
|||
|
return e;
|
|||
|
}
|
|||
|
|
|||
|
static bool haveRFSO(TString& codrfso)
|
|||
|
{
|
|||
|
codrfso = cache().get(LF_NDITTE, prefix().firm().codice(), "CODRFSO");
|
|||
|
if(codrfso == "") return false;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
static bool hasRFSO(TString tipocf, TString codcli, TString& codrfso)
|
|||
|
{
|
|||
|
codrfso = cache().get(LF_CLIFO, tipocf << "|" << codcli, "CODRFSO");
|
|||
|
if(codrfso == "") return false;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
// DA CONTROLLARE!!!!!
|
|||
|
static const char* decodTipo(TDocumento& doc)
|
|||
|
{
|
|||
|
if(doc.is_fattura())
|
|||
|
return "TD01";
|
|||
|
if(doc.is_nota_credito())
|
|||
|
return "TD04";
|
|||
|
return "TD05";
|
|||
|
}
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// TTrFa_record
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
// Contenitore di campi di un record di database SQLite
|
|||
|
class TTrFa_record : public TObject
|
|||
|
{
|
|||
|
TString8 _table;
|
|||
|
TToken_string _key;
|
|||
|
TAssoc_array _fields;
|
|||
|
|
|||
|
protected:
|
|||
|
void copy(const TTrFa_record& rec) { _table = rec._table; _key = rec._key; _fields = rec._fields; }
|
|||
|
const TString& var2str(const TString& fld, const TVariant& var) const;
|
|||
|
|
|||
|
public:
|
|||
|
void reset() { _fields.destroy(); }
|
|||
|
void set(const char* fld, const TVariant& var);
|
|||
|
void set(const char* fld, long var);
|
|||
|
void set(const char* fld, const char* var);
|
|||
|
void set(const char* fld, const real& var);
|
|||
|
void set(const char* fld, const TString& var);
|
|||
|
void set(const char* fld, const TDate& var);
|
|||
|
void set(const char* fld, bool var);
|
|||
|
const TVariant& get(const char* fld) const;
|
|||
|
|
|||
|
bool insert();
|
|||
|
bool remove();
|
|||
|
bool search();
|
|||
|
bool search(const char* k1, const char* k2, const char* k3 = NULL);
|
|||
|
|
|||
|
virtual TObject* dup() const { return new TTrFa_record(*this); }
|
|||
|
virtual bool ok() const { return _table.not_empty(); }
|
|||
|
|
|||
|
TTrFa_record& operator=(const TTrFa_record& rec) { copy(rec); return *this; }
|
|||
|
TTrFa_record(const TTrFa_record& rec) { copy(rec); }
|
|||
|
TTrFa_record(const char* table);
|
|||
|
};
|
|||
|
|
|||
|
// Imposta il valore di un campo variant
|
|||
|
void TTrFa_record::set(const char* fld, const TVariant& var)
|
|||
|
{
|
|||
|
CHECK(fld && *fld, "Null field name");
|
|||
|
|
|||
|
if (var.is_null())
|
|||
|
{
|
|||
|
_fields.remove(fld);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
TVariant* obj = (TVariant*)_fields.objptr(fld);
|
|||
|
if (obj != NULL)
|
|||
|
*obj = var;
|
|||
|
else
|
|||
|
_fields.add(fld, new TVariant(var));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Imposta il valore di un campo intero
|
|||
|
void TTrFa_record::set(const char* fld, long val)
|
|||
|
{
|
|||
|
const TVariant var(val);
|
|||
|
set(fld, var);
|
|||
|
}
|
|||
|
|
|||
|
// Imposta il valore di un campo stringa
|
|||
|
void TTrFa_record::set(const char* fld, const char* val)
|
|||
|
{
|
|||
|
if (val == NULL)
|
|||
|
set(fld, NULL_VARIANT);
|
|||
|
else
|
|||
|
{
|
|||
|
const TVariant var(val);
|
|||
|
set(fld, var);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Imposta il valore di un campo stringa
|
|||
|
void TTrFa_record::set(const char* fld, const TString& val)
|
|||
|
{
|
|||
|
const TVariant var(val);
|
|||
|
set(fld, var);
|
|||
|
}
|
|||
|
|
|||
|
// Imposta il valore di un campo numerico
|
|||
|
void TTrFa_record::set(const char* fld, const real& val)
|
|||
|
{
|
|||
|
const TVariant var(val);
|
|||
|
set(fld, var);
|
|||
|
}
|
|||
|
|
|||
|
// Imposta il valore di un campo data in formato ISO
|
|||
|
void TTrFa_record::set(const char* fld, const TDate& val)
|
|||
|
{
|
|||
|
if (val.ok())
|
|||
|
{
|
|||
|
const TVariant var(val);
|
|||
|
set(fld, var);
|
|||
|
}
|
|||
|
else
|
|||
|
set(fld, "");
|
|||
|
}
|
|||
|
|
|||
|
// Imposta il valore di un campo booleano
|
|||
|
void TTrFa_record::set(const char* fld, bool var)
|
|||
|
{
|
|||
|
set(fld, var ? "SI" : "NO");
|
|||
|
}
|
|||
|
|
|||
|
// Legge il valore di un campo variant
|
|||
|
const TVariant& TTrFa_record::get(const char* fld) const
|
|||
|
{
|
|||
|
const TVariant* var = (const TVariant*)_fields.objptr(fld);
|
|||
|
return var ? *var : NULL_VARIANT;
|
|||
|
}
|
|||
|
|
|||
|
// Converte un variant in una stringa valida per SQLite
|
|||
|
const TString& TTrFa_record::var2str(const TString& fldname, const TVariant& var) const
|
|||
|
{
|
|||
|
const TFieldtypes vt = var.type();
|
|||
|
if (vt == _realfld)
|
|||
|
{
|
|||
|
const TCurrency v(var.as_real(), "", ZERO, fldname.find("PRZ")>0 || fldname.find("PREZZO")>0);
|
|||
|
TString& tmp = get_tmp_string();
|
|||
|
tmp << '\'' << v.string() << '\''; tmp.replace(',','.');
|
|||
|
return tmp;
|
|||
|
}
|
|||
|
if (vt == _datefld)
|
|||
|
{
|
|||
|
TString& tmp = get_tmp_string();
|
|||
|
tmp << '\'' << var.as_date().string(full, '-', full, full, amg_date) << '\'';
|
|||
|
return tmp;
|
|||
|
}
|
|||
|
|
|||
|
const TString& str = var.as_string();
|
|||
|
|
|||
|
bool apici = vt == _alfafld;
|
|||
|
if (apici && str[0] != '0' && real::is_natural(str))
|
|||
|
apici = false;
|
|||
|
|
|||
|
if (!apici)
|
|||
|
return str;
|
|||
|
|
|||
|
TString& tmp = get_tmp_string();
|
|||
|
tmp = str;
|
|||
|
for (int a = str.rfind('\''); a >= 0; a--)
|
|||
|
{
|
|||
|
if (tmp[a] == '\'')
|
|||
|
tmp.insert("'", a);
|
|||
|
}
|
|||
|
tmp.insert("'", 0);
|
|||
|
tmp << '\'';
|
|||
|
return tmp;
|
|||
|
}
|
|||
|
|
|||
|
// Elimina il record in base ai campi chiave
|
|||
|
bool TTrFa_record::remove()
|
|||
|
{
|
|||
|
TString256 query;
|
|||
|
query << "DELETE FROM " << _table << " WHERE ";
|
|||
|
int nkf = 0;
|
|||
|
FOR_EACH_TOKEN(_key, fld)
|
|||
|
{
|
|||
|
const TVariant& var = get(fld);
|
|||
|
if (!var.is_null())
|
|||
|
{
|
|||
|
if (nkf++ > 0)
|
|||
|
query << " AND ";
|
|||
|
query << fld << '=' << var2str(fld, var) ;
|
|||
|
}
|
|||
|
}
|
|||
|
CHECKS(nkf >= 2, "Can't remove partial key on table ", (const char*)_table);
|
|||
|
query << ';';
|
|||
|
return xvt_sql_execute(_db, query, NULL, 0L) > 0;
|
|||
|
}
|
|||
|
|
|||
|
// Callback per la sottostante funzione search()
|
|||
|
static int tff_search_record(void* jolly, int cols, char** values, char** names)
|
|||
|
{
|
|||
|
TTrFa_record& rec = *(TTrFa_record*)jolly;
|
|||
|
for (int i = 0; i < cols; i++)
|
|||
|
rec.set(names[i], values[i]);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
// Carica un record in base ai campi chiave
|
|||
|
bool TTrFa_record::search()
|
|||
|
{
|
|||
|
CHECKS(_fields.items() >= _key.items(), "Can't search partial key on table ", _table);
|
|||
|
TString256 query;
|
|||
|
query << "SELECT * FROM " << _table << " WHERE ";
|
|||
|
FOR_EACH_TOKEN(_key, fld)
|
|||
|
{
|
|||
|
const TVariant& var = get(fld);
|
|||
|
if (!var.is_null())
|
|||
|
query << fld << '=' << var2str(fld, var) << " AND ";
|
|||
|
}
|
|||
|
query.rtrim(5);
|
|||
|
query << ';';
|
|||
|
return xvt_sql_execute(_db, query, tff_search_record, this) == 1;
|
|||
|
}
|
|||
|
|
|||
|
// Carica un record in base ad un massimo di 3 campi chiave
|
|||
|
bool TTrFa_record::search(const char* k1, const char* k2, const char* k3)
|
|||
|
{
|
|||
|
_fields.destroy();
|
|||
|
|
|||
|
set(_key.get(0), k1);
|
|||
|
set(_key.get(1), k2);
|
|||
|
if (k3 && *k3)
|
|||
|
set(_key.get(2), k3);
|
|||
|
|
|||
|
return search();
|
|||
|
}
|
|||
|
|
|||
|
// Aggiunge un record al db
|
|||
|
bool TTrFa_record::insert()
|
|||
|
{
|
|||
|
CHECKS(_fields.items() > _key.items(), "Can't insert empty record on table ", _table);
|
|||
|
|
|||
|
TString query, values;
|
|||
|
query << "INSERT INTO " << _table << "\n(";
|
|||
|
FOR_EACH_ASSOC_OBJECT(_fields, obj, fld, itm)
|
|||
|
{
|
|||
|
const TVariant& var = get(fld);
|
|||
|
if (!var.is_null())
|
|||
|
{
|
|||
|
query << fld << ',';
|
|||
|
values << var2str(fld, var) << ',';
|
|||
|
}
|
|||
|
}
|
|||
|
query.rtrim(1); values.rtrim(1);
|
|||
|
query << ")\nVALUES (" << values << ");";
|
|||
|
return xvt_sql_execute(_db, query, NULL, 0L) == 1;
|
|||
|
}
|
|||
|
|
|||
|
// Crea un record della tabella data ed imposta i nomi dei campi chiave
|
|||
|
TTrFa_record::TTrFa_record(const char* table) : _table(table), _key(15, ',')
|
|||
|
{
|
|||
|
_key = ini_get_string("./tff.ini", table, "INDEX_1");
|
|||
|
if (_key.empty())
|
|||
|
{
|
|||
|
// Cerco di costruire i nomi della chiave cercando la K, come in P1_KEYHEADERFATT
|
|||
|
TConfig cfg("tff.ini", table);
|
|||
|
TAssoc_array& fields = cfg.list_variables();
|
|||
|
FOR_EACH_ASSOC_STRING(fields, obj, key, str)
|
|||
|
{
|
|||
|
if (key[3] == 'K')
|
|||
|
_key.add(key);
|
|||
|
}
|
|||
|
}
|
|||
|
CHECKS(!_key.empty_items(), "Invalid primary key for table ", table);
|
|||
|
}
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// TTrFa_cursors
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
/*
|
|||
|
* Classe per la gestione dei cursori RMOVIVA e MOV
|
|||
|
*/
|
|||
|
class TTrFa_cursors : TObject
|
|||
|
{
|
|||
|
friend class TCursor;
|
|||
|
|
|||
|
TSorted_cursor* c_mov;
|
|||
|
TCursor* c_moviva;
|
|||
|
TCursor* c_trasfatt;
|
|||
|
TRelation* r_mov;
|
|||
|
TRelation* r_moviva;
|
|||
|
TRelation* r_trasfatt;
|
|||
|
|
|||
|
filter_fatt filFat;
|
|||
|
|
|||
|
bool filOk(bool s) { return (filFat == all) || (filFat == sent && s) || (filFat == toSend && !s); }
|
|||
|
int _next(bool init = false); // Si sposta avanti di un elemento
|
|||
|
|
|||
|
public:
|
|||
|
TTrFa_cursors();
|
|||
|
~TTrFa_cursors() { delete c_mov, c_moviva, r_mov, r_moviva, r_trasfatt, c_trasfatt; };
|
|||
|
long int getMovItems() { return c_mov->items(); }
|
|||
|
long int getIvaItems() { return c_moviva->items(); }
|
|||
|
long int getMovPos() { return c_mov->pos(); }
|
|||
|
long int getIvaPos() { return c_moviva->pos(); }
|
|||
|
TRectype getMov() { return c_mov->curr(); }
|
|||
|
TRectype getIva() { return c_moviva->curr(); }
|
|||
|
TRectype getTrasfatt() { return c_trasfatt->curr(); }
|
|||
|
int next(TAssoc_array& recimposte); // Legge tutto il prossimo movimento, in importi mette per ogni codiva la somma
|
|||
|
|
|||
|
int updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, TAssoc_array& recimposte, int cod = toSend);
|
|||
|
};
|
|||
|
|
|||
|
TTrFa_cursors::TTrFa_cursors() : filFat(all)
|
|||
|
{
|
|||
|
r_mov = new TRelation(LF_MOV);
|
|||
|
r_moviva = new TRelation(LF_RMOVIVA);
|
|||
|
r_trasfatt = new TRelation(LF_TRASFATT);
|
|||
|
c_mov = new TSorted_cursor(r_mov, "NUMREG");
|
|||
|
c_moviva = new TCursor(r_moviva);
|
|||
|
c_trasfatt = new TCursor(r_trasfatt);
|
|||
|
};
|
|||
|
|
|||
|
int TTrFa_cursors::next(TAssoc_array& recimposte)
|
|||
|
{
|
|||
|
int err = _next(true);
|
|||
|
while(err < nextmov)
|
|||
|
{
|
|||
|
TRectype mov = getMov(), miva = getIva(), cust = getTrasfatt();
|
|||
|
if(recimposte.is_key(miva.get("CODIVA")))
|
|||
|
{
|
|||
|
// Prelevo il record salvato
|
|||
|
TRectype app = *(TRectype*)recimposte.objptr(miva.get("CODIVA"));
|
|||
|
// Aggiorno i valori
|
|||
|
app.put("IMPONIBILE", app.get_real("IMPONIBILE") + (err == movcustom ? cust.get_real("IMPONIBILE") : miva.get_real("IMPONIBILE")));
|
|||
|
app.put("IMPOSTA", app.get_real("IMPOSTA") + (err == movcustom ? cust.get_real("IMPOSTA") : miva.get_real("IMPOSTA")));
|
|||
|
// Lo reinserisco
|
|||
|
recimposte.add(miva.get("CODIVA"), app, true);
|
|||
|
}
|
|||
|
else // Inserisco per la prima volta
|
|||
|
{
|
|||
|
// Creo un record di tipo tabella trasmissione fatture, tanto conterrebbe tutti i dati necessari
|
|||
|
TRectype app(LF_TRASFATT);
|
|||
|
// Inserisco i dati
|
|||
|
if(err == movcustom)
|
|||
|
{
|
|||
|
app.put("NUMREG", cust.get("NUMREG"));
|
|||
|
app.put("TIPO", cust.get("TIPO"));
|
|||
|
app.put("COD", cust.get("CODCF"));
|
|||
|
app.put("TIPODOC", cust.get("TIPODOC"));
|
|||
|
app.put("NUMDOC", cust.get("NUMDOC"));
|
|||
|
app.put("DATADOC", cust.get("DATADOC"));
|
|||
|
app.put("IMPONIBILE", cust.get("IMPONIBILE"));
|
|||
|
app.put("IMPOSTA", cust.get("IMPOSTA"));
|
|||
|
app.put("CODIVA", cust.get("CODIVA"));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
app.put("NUMREG", mov.get("NUMREG"));
|
|||
|
app.put("TIPO", mov.get("TIPO"));
|
|||
|
app.put("COD", mov.get("CODCF"));
|
|||
|
app.put("TIPODOC", mov.get("TIPODOC"));
|
|||
|
app.put("NUMDOC", mov.get("NUMDOC"));
|
|||
|
app.put("DATADOC", mov.get("DATADOC"));
|
|||
|
app.put("IMPONIBILE", miva.get("IMPONIBILE"));
|
|||
|
app.put("IMPOSTA", miva.get("IMPOSTA"));
|
|||
|
app.put("CODIVA", miva.get("CODIVA"));
|
|||
|
}
|
|||
|
// Salvo il record nell'array
|
|||
|
recimposte.add(app.get("CODIVA"), app);
|
|||
|
}
|
|||
|
err = _next();
|
|||
|
}
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Questa funzione si sposta sui due cursori trovando la prossima riga, se le righe sono finite si posiziona sul prossimo movimento o ritorna EOF
|
|||
|
*/
|
|||
|
int TTrFa_cursors::_next(bool init)
|
|||
|
{
|
|||
|
bool isNextMov = false;
|
|||
|
if(c_moviva->pos() == c_moviva->items())
|
|||
|
return eof; // A noi interessa solo rmoviva
|
|||
|
else
|
|||
|
{
|
|||
|
TRectype rigaMov = c_mov->curr(), rigaIva = c_moviva->curr(), rigaTF = c_trasfatt->curr();
|
|||
|
bool first = true;
|
|||
|
bool checkOk = false;
|
|||
|
// Posso capitare movimenti aggiunti dopo che non rientrano nel periodo che ci interessa, applico un controllino
|
|||
|
while(first || rigaMov.get_long("NUMREG") > rigaIva.get_long("NUMREG") || !filOk(checkOk))
|
|||
|
{
|
|||
|
first = false;
|
|||
|
|
|||
|
// Stratagemma terribile per evitare di saltare il primo record
|
|||
|
if(!init)
|
|||
|
{
|
|||
|
if(!c_moviva->next_match(0))
|
|||
|
return eof;
|
|||
|
}
|
|||
|
else init = false;
|
|||
|
|
|||
|
rigaMov = c_mov->curr();
|
|||
|
rigaIva = c_moviva->curr();
|
|||
|
rigaTF = c_trasfatt->curr();
|
|||
|
|
|||
|
while(rigaMov.get_long("NUMREG") < rigaIva.get_long("NUMREG"))
|
|||
|
{
|
|||
|
isNextMov = true; // Vale la pena fare un controllo aggiuntivo per questo? Il while verr<72> eseguito max 2 volte
|
|||
|
|
|||
|
if (!c_mov->next_match(0))
|
|||
|
return eofm;
|
|||
|
rigaMov = c_mov->curr();
|
|||
|
}
|
|||
|
|
|||
|
// Mi muovo finch<63> le righe non sono le stesse
|
|||
|
while(rigaTF.get_long("NUMREG") <= rigaIva.get_long("NUMREG") && rigaTF.get_long("NUMRIG") < rigaIva.get_long("NUMRIG") && c_trasfatt->pos() != c_trasfatt->items())
|
|||
|
{
|
|||
|
if(!c_mov->next_match(0)) // Non mi interessa se raggiungo la fine di questa tabella
|
|||
|
break;
|
|||
|
rigaTF = c_trasfatt->curr();
|
|||
|
}
|
|||
|
if(rigaTF.get_long("NUMREG") == rigaIva.get_long("NUMREG") && rigaTF.get_long("NUMRIG") == rigaIva.get_long("NUMRIG"))
|
|||
|
checkOk = rigaTF.get_bool("TFINVIO");
|
|||
|
else
|
|||
|
checkOk = rigaIva.get_bool("TFINVIO");
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if(isNextMov)
|
|||
|
{
|
|||
|
if(rigaTF.get_long("NUMREG") == rigaIva.get_long("NUMREG") && rigaTF.get_long("NUMRIG") == rigaIva.get_long("NUMRIG"))
|
|||
|
return movcustom;
|
|||
|
else
|
|||
|
return nextmov;
|
|||
|
}
|
|||
|
else
|
|||
|
return found;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int TTrFa_cursors::updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, TAssoc_array& recimposte, int cod)
|
|||
|
{
|
|||
|
filFat = (filter_fatt)cod;
|
|||
|
|
|||
|
TRectype filMov(r_mov->curr());
|
|||
|
int movKey = 1;
|
|||
|
|
|||
|
TString filter;
|
|||
|
|
|||
|
if(dal.empty()) dal = "20170101"; // Data in cui questo modulo <20> diventato valido
|
|||
|
if(al.empty()) al = TODAY;
|
|||
|
filter << "&&(BETWEEN(DATADOC," << dal.date2ansi() << ',' << al.date2ansi() << "))";
|
|||
|
|
|||
|
if(tipocf != 'T')
|
|||
|
{
|
|||
|
movKey = 3;
|
|||
|
filMov.put("TIPO", tipocf);
|
|||
|
// Se <20> selezionato un cliente specifico
|
|||
|
if(codcf > 0)
|
|||
|
filMov.put("CODCF", codcf);
|
|||
|
}
|
|||
|
else
|
|||
|
filMov = 0;
|
|||
|
|
|||
|
// Risetto mov
|
|||
|
delete c_mov;
|
|||
|
c_mov = new TSorted_cursor(r_mov, "NUMREG", TString("REG!=\"\"")<<filter, movKey, &filMov, &filMov);
|
|||
|
c_mov->items();
|
|||
|
c_mov->first_item();
|
|||
|
|
|||
|
// Preparo c_moviva
|
|||
|
TRectype filIva(r_moviva->curr());
|
|||
|
filIva.put("NUMREG", TRectype(c_mov->curr()).get_long("NUMREG"));
|
|||
|
|
|||
|
// Resetto rmoviva
|
|||
|
delete c_moviva;
|
|||
|
c_moviva = new TCursor(r_moviva, "", 1, &filIva);
|
|||
|
c_moviva->first_item();
|
|||
|
|
|||
|
// Preparo c_moviva
|
|||
|
TRectype filTF(r_trasfatt->curr());
|
|||
|
filTF.put("NUMREG", TRectype(c_mov->curr()).get_long("NUMREG"));
|
|||
|
|
|||
|
// Resetto trasfatt
|
|||
|
delete c_trasfatt;
|
|||
|
c_trasfatt = new TSorted_cursor(r_trasfatt, "NUMREG", "", 1, &filIva);
|
|||
|
c_trasfatt->first_item();
|
|||
|
|
|||
|
|
|||
|
// Mi posiziono sullo stesso Numero di registrazione
|
|||
|
if(c_mov->items() > 0 && c_moviva->items() > 0)
|
|||
|
{
|
|||
|
return next(recimposte);
|
|||
|
}
|
|||
|
|
|||
|
return eof;
|
|||
|
}
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// TTrFa_mask
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
class TTrFa_mask : public TAutomask
|
|||
|
{
|
|||
|
friend class TTrFa_cursors;
|
|||
|
|
|||
|
TMaskmode _mode;
|
|||
|
bool _sheet_dirty;
|
|||
|
bool _filter_changed;
|
|||
|
|
|||
|
protected:
|
|||
|
virtual void next_page(int p);
|
|||
|
const char * natura(const TString& codiva) const;
|
|||
|
real get_IVA(const TString& codiva) const;
|
|||
|
char revCharge(TString codcaus) const;
|
|||
|
TString findDetraib(TString codiva) const;
|
|||
|
|
|||
|
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
|||
|
//void fill();
|
|||
|
//void init();
|
|||
|
|
|||
|
public:
|
|||
|
void setFilterChanged() { _filter_changed = true; }
|
|||
|
void load_sheet();
|
|||
|
TTrFa_mask(TString msk) : TAutomask(msk), _filter_changed(true) {}
|
|||
|
};
|
|||
|
|
|||
|
void TTrFa_mask::next_page(int p)
|
|||
|
{
|
|||
|
TAutomask::next_page(p);
|
|||
|
if (_filter_changed)
|
|||
|
{
|
|||
|
TSheet_field & sf = sfield(F_RIGHE);
|
|||
|
if (curr_win() == sf.parent())
|
|||
|
{
|
|||
|
load_sheet();
|
|||
|
sf.force_update();
|
|||
|
_filter_changed = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
|||
|
{
|
|||
|
|
|||
|
switch (o.dlg())
|
|||
|
{
|
|||
|
case F_DATAINI:
|
|||
|
if (e == fe_init)
|
|||
|
o.set(ini_get_string(CONFIG_DITTA, "tf", "LastSend", "01-01-2017"));
|
|||
|
break;
|
|||
|
case F_DATAFIN:
|
|||
|
if (e == fe_init)
|
|||
|
o.set(TDate(TODAY));
|
|||
|
break;
|
|||
|
case F_TIPOCF:
|
|||
|
if(get(F_TIPOCF) != "T")
|
|||
|
{
|
|||
|
enable(F_CODCF);
|
|||
|
enable(F_RAGSOC);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
disable(F_CODCF);
|
|||
|
disable(F_RAGSOC);
|
|||
|
}
|
|||
|
break;
|
|||
|
case DLG_ALL:
|
|||
|
if (e == fe_button)
|
|||
|
{
|
|||
|
TSheet_field& docs = sfield(F_RIGHE);
|
|||
|
TString_array& sht = docs.rows_array();
|
|||
|
const int items = sht.items();
|
|||
|
|
|||
|
if (items > 0)
|
|||
|
{
|
|||
|
const TString4 select = *(sht.row(0).get(0)) == 'X' ? "" : "X";
|
|||
|
for (int i = 0; i < items; i++)
|
|||
|
sht.row(i).add(select, 0);
|
|||
|
docs.force_update();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
const short id = o.dlg();
|
|||
|
if (e == fe_modify && jolly == 1)
|
|||
|
{
|
|||
|
if (id >= A_NUMERO && id < A_COFI && id != A_FORZATA)
|
|||
|
{
|
|||
|
o.mask().set(A_FORZATA, true);
|
|||
|
}
|
|||
|
}
|
|||
|
if (e == fe_modify && jolly == 0)
|
|||
|
{
|
|||
|
if (id >= F_DATAINI && id <= F_FATTSEL)
|
|||
|
{
|
|||
|
setFilterChanged();
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
void TTrFa_mask::load_sheet()
|
|||
|
{
|
|||
|
const char tipocf = get(F_TIPOCF)[0];
|
|||
|
const long codcf = get_long(F_CODCF);
|
|||
|
TDate dal = get_date(F_DATAINI), al = get_date(F_DATAFIN);
|
|||
|
//TString key; key << "TIPOA=" << prefix().firm().get("TIPOA")<< ",CODANAGR=" << prefix().firm().get("CODANAGR");
|
|||
|
TString key; key << prefix().firm().get("TIPOA") << "|" << prefix().firm().get("CODANAGR");
|
|||
|
const TString pivaDitta = cache().get(LF_ANAG, key, "PAIV");
|
|||
|
const TString cofiDitta = cache().get(LF_ANAG, key, "COFI");
|
|||
|
|
|||
|
TTrFa_cursors c;
|
|||
|
|
|||
|
TSheet_field& sheet = sfield(F_RIGHE);
|
|||
|
TString_array& strarr = sheet.rows_array();
|
|||
|
|
|||
|
sheet.hide(); // Nascondo lo sheet per guadagnare un 20% di velocit<69> di caricamento, le ottimizzazioni da PRO!
|
|||
|
sheet.destroy();
|
|||
|
TAssoc_array recimposte;
|
|||
|
int next = c.updateFilters(tipocf, codcf, dal, al, recimposte, get_int(F_FATTSEL));
|
|||
|
while(next < eof)
|
|||
|
{
|
|||
|
TRectype mov(c.getMov()), miva(c.getIva()), mcust(c.getTrasfatt());
|
|||
|
TToken_string* row = new TToken_string;
|
|||
|
|
|||
|
// Carico i clienti
|
|||
|
TRelation r_cli(LF_CLIFO);
|
|||
|
TRectype filCli(r_cli.curr());
|
|||
|
filCli.put("TIPOCF", mov.get("TIPO"));
|
|||
|
filCli.put("CODCF", mov.get("CODCF"));
|
|||
|
TCursor c_cli(&r_cli, "", 1, &filCli, &filCli); c_cli.items();
|
|||
|
c_cli = 0;
|
|||
|
TRectype cli(c_cli.curr());
|
|||
|
|
|||
|
FOR_EACH_ASSOC_OBJECT(recimposte, h, iva, rec)
|
|||
|
{
|
|||
|
TRectype movimento = *(TRectype*)rec;
|
|||
|
row->add(next == movcustom ? mcust.get("TFINVIO") : miva.get("TFINVIO"), 0); //Forzo la posizione
|
|||
|
row->add(row[0] == "X"? "" : "X"); // Se <20> gi<67> stata spedita la riga non viene preselezionata
|
|||
|
row->add(next == movcustom ? "X" : "");
|
|||
|
row->add(movimento.get_long("NUMREG"));
|
|||
|
row->add(miva.get_long("NUMRIG"));
|
|||
|
row->add(cli.get("TIPOCF"));
|
|||
|
row->add(cli.get("CODCF"));
|
|||
|
row->add(cli.get_bool("OCCAS") ? "X" : "");
|
|||
|
row->add(cli.get("RAGSOC"));
|
|||
|
row->add(cli.get("CODRFSO"));
|
|||
|
|
|||
|
row->add(movimento.get("TIPODOC")); // Tipo documento
|
|||
|
row->add(movimento.get_long("NUMDOC")); // Numero documento
|
|||
|
row->add(movimento.get_date("DATADOC")); // Data documento
|
|||
|
row->add(natura(iva)); // NATURA!
|
|||
|
row->add(get_IVA(iva)); // Aliquota!
|
|||
|
row->add(findDetraib(iva)); // Detraibilit<69>
|
|||
|
row->add(movimento.get_real("IMPONIBILE")); // Imponibile
|
|||
|
row->add(movimento.get_real("IMPOSTA")); // Imposta
|
|||
|
row->add(revCharge(mov.get("CODCAUS"))); // Rev.Charge
|
|||
|
row->add(pivaDitta == cli.get("PAIV") ? 'X' : '\0'); // AutoFatt
|
|||
|
if(strcmp(row->get(19), "X") == 0) // Se <20> un autofattura
|
|||
|
{
|
|||
|
row->add(pivaDitta);
|
|||
|
row->add(cofiDitta);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
row->add(cli.get("PAIV"));
|
|||
|
row->add(cli.get("COFI"));
|
|||
|
}
|
|||
|
|
|||
|
strarr.add(row);
|
|||
|
}
|
|||
|
recimposte.destroy();
|
|||
|
next = c.next(recimposte);
|
|||
|
}
|
|||
|
sheet.force_update();
|
|||
|
sheet.show();
|
|||
|
}
|
|||
|
|
|||
|
TString TTrFa_mask::findDetraib(TString codiva) const
|
|||
|
{
|
|||
|
// Mi creo un cursore per i valori di indetraibilit<69>, cos<6F> facendo mi risparmio operazioni lente dopo
|
|||
|
static TRelation r_indetr(LF_TABCOM);
|
|||
|
static TRectype f_indetr(r_indetr.curr()); f_indetr.put("COD", "DET");
|
|||
|
static TCursor c_indetr(&r_indetr, "", 1, &f_indetr, &f_indetr);
|
|||
|
|
|||
|
TString codtab = cache().get("%IVA", codiva, "S4");
|
|||
|
if(codtab.full())
|
|||
|
{
|
|||
|
for(c_indetr = 0; c_indetr.pos() < c_indetr.items(); ++c_indetr)
|
|||
|
{
|
|||
|
TRectype row = c_indetr.curr();
|
|||
|
if(codtab == row.get("CODTAB"))
|
|||
|
return (CENTO - row.get_real("R0")).stringa(6,2);
|
|||
|
}
|
|||
|
}
|
|||
|
return "0.00";
|
|||
|
}
|
|||
|
|
|||
|
const char * TTrFa_mask::natura(const TString& codiva) const
|
|||
|
{
|
|||
|
const TRectype& ai = cache().get("%IVA", codiva);
|
|||
|
TString & natura = get_tmp_string(4);
|
|||
|
|
|||
|
natura = ai.get("S12");
|
|||
|
if(natura.blank())
|
|||
|
{
|
|||
|
const int tipo_iva11 = ai.get_int("S2");
|
|||
|
const bool revcharge = tipo_iva11 >= 31 && tipo_iva11 <= 38;
|
|||
|
const TString& tipo = ai.get("S1");
|
|||
|
const int tipo_vendite = ai.get_int("S7");
|
|||
|
|
|||
|
// N1 escluse ex art 15
|
|||
|
if (tipo_vendite == 5)
|
|||
|
natura = "N5"; // regime del margine
|
|||
|
else
|
|||
|
if (revcharge)
|
|||
|
natura = "N6"; // Inversione contabile (REVERSE CHARGE)
|
|||
|
else
|
|||
|
if (tipo == "NS")
|
|||
|
natura = "N2"; // Non soggetto
|
|||
|
else
|
|||
|
if (tipo == "NI")
|
|||
|
natura = "N3"; // Non imponibile
|
|||
|
else
|
|||
|
if (tipo == "ES")
|
|||
|
natura = "N4"; // Esente
|
|||
|
}
|
|||
|
return natura;
|
|||
|
}
|
|||
|
|
|||
|
real TTrFa_mask::get_IVA(const TString& codiva) const
|
|||
|
{
|
|||
|
const TRectype& ai = cache().get("%IVA", codiva);
|
|||
|
return ai.get_real("R0");
|
|||
|
}
|
|||
|
|
|||
|
char TTrFa_mask::revCharge(TString codcaus) const
|
|||
|
{
|
|||
|
const TRectype& caus = cache().get(LF_CAUSALI, codcaus);
|
|||
|
const int reg_spec = caus.get_int(CAU_REGSPIVA);
|
|||
|
if (reg_spec == 13 || reg_spec == 50 || reg_spec == 51) // reverse charge
|
|||
|
return 'X';
|
|||
|
return '\0';
|
|||
|
}
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// TTrFa_app
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
class TTrFa_app : public TSkeleton_application
|
|||
|
{
|
|||
|
TAnagrafica _ditta;
|
|||
|
TString16 _cofi;
|
|||
|
TFilename _dbname;
|
|||
|
TLog_report* _log;
|
|||
|
TString _logTFF;
|
|||
|
enum { _spedita, _invio, _forzata, _numero, _numriga, _tipocf, _codcf, _ocfpi, _ragsoc, _rfso, _codnum, _numdoc, _datadoc,
|
|||
|
_natura, _aliquota, _detraibile, _imponibile, _imposta, _reverse, _autofatt, _paiv, _codfis };
|
|||
|
|
|||
|
private:
|
|||
|
int parse_line(const TString& line, TString& var, TString& val) const;
|
|||
|
bool create_table(TScanner& TFF, const TString& table);
|
|||
|
bool addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr);
|
|||
|
bool setEsportato(TToken_string* strarr);
|
|||
|
//const TRectype* find_parent_row(const TRectype& rdoc) const;
|
|||
|
//int find_ancestors(const TRiga_documento& rdoc, TArray& ancestors) const;
|
|||
|
|
|||
|
protected:
|
|||
|
//const char* descrizione(const TRiga_documento& rdoc) const;
|
|||
|
//const TRectype& cco(const TRectype& doc) const; // Contratto/Convenzione/Offerta
|
|||
|
|
|||
|
void log(int severity, const char* msg);
|
|||
|
bool show_log();
|
|||
|
void set_IVA(const TString& codiva, TTrFa_record& TFF) const;
|
|||
|
void set_IVA(const TRiga_documento& rdoc, TTrFa_record& TFF) const;
|
|||
|
bool syncronizeDB();
|
|||
|
bool createDB();
|
|||
|
|
|||
|
public:
|
|||
|
virtual bool create();
|
|||
|
virtual bool destroy();
|
|||
|
virtual void main_loop();
|
|||
|
bool send(TTrFa_mask* msk);
|
|||
|
|
|||
|
TTrFa_app() : _log(NULL) {}
|
|||
|
};
|
|||
|
|
|||
|
void TTrFa_app::log(int severity, const char* msg)
|
|||
|
{
|
|||
|
if (severity < 0)
|
|||
|
{
|
|||
|
_logTFF = msg;
|
|||
|
} else
|
|||
|
if (_log == NULL)
|
|||
|
{
|
|||
|
_log = new TLog_report;
|
|||
|
if (_logTFF.full())
|
|||
|
{
|
|||
|
TString txt;
|
|||
|
txt << _logTFF << ": " << msg;
|
|||
|
_log->log(severity, txt);
|
|||
|
}
|
|||
|
else
|
|||
|
_log->log(severity, msg);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::show_log()
|
|||
|
{
|
|||
|
bool ok = true;
|
|||
|
if (_log)
|
|||
|
{
|
|||
|
_log->preview();
|
|||
|
delete _log;
|
|||
|
_log = NULL;
|
|||
|
ok = noyes_box(TR("Si desidera procedere con la generazione file xml?"));
|
|||
|
}
|
|||
|
return ok;
|
|||
|
}
|
|||
|
|
|||
|
void TTrFa_app::set_IVA(const TString& codiva, TTrFa_record& tff) const
|
|||
|
{/*
|
|||
|
const TRectype& ai = cache().get("%IVA", codiva);
|
|||
|
const real aliquota = ai.get("R0");
|
|||
|
tff.set("PI_ALIQUOTAIVA", aliquota);
|
|||
|
if (codiva.full())
|
|||
|
{
|
|||
|
if (aliquota.is_zero())
|
|||
|
tff.set("PI_NATURA", natura(codiva));
|
|||
|
else
|
|||
|
tff.set("PI_NATURA", "");
|
|||
|
}*/
|
|||
|
}
|
|||
|
|
|||
|
void TTrFa_app::set_IVA(const TRiga_documento& rdoc, TTrFa_record& tff) const
|
|||
|
{/*
|
|||
|
const TString8 codiva(rdoc.get(RDOC_CODIVA));
|
|||
|
const TRectype& ai = cache().get("%IVA", codiva);
|
|||
|
const real aliquota = ai.get("R0");
|
|||
|
tff.set("PI_ALIQUOTAIVA", aliquota);
|
|||
|
if (codiva.full())
|
|||
|
{
|
|||
|
if (aliquota.is_zero())
|
|||
|
tff.set("PI_NATURA", natura(codiva));
|
|||
|
else
|
|||
|
tff.set("PI_NATURA", "");
|
|||
|
}*/
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int TTrFa_app::parse_line(const TString& line, TString& var, TString& val) const
|
|||
|
{
|
|||
|
if (line.blank())
|
|||
|
return 0;
|
|||
|
|
|||
|
if (line[0] == '[')
|
|||
|
{
|
|||
|
var = line.mid(1);
|
|||
|
var.rtrim(1);
|
|||
|
val.cut(0);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
const int equal = line.find('=');
|
|||
|
if (equal < 6)
|
|||
|
return 0;
|
|||
|
var = line.left(equal); var.trim();
|
|||
|
val = line.mid(equal+1); val.trim();
|
|||
|
return 2;
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::create_table(TScanner& tff, const TString& table)
|
|||
|
{
|
|||
|
TString query, var, val;
|
|||
|
if (xvt_sql_table_exists(_db, table))
|
|||
|
{
|
|||
|
SLIST fields = xvt_sql_list_fields(_db, table);
|
|||
|
while (!tff.eof())
|
|||
|
{
|
|||
|
const TString& line = tff.line();
|
|||
|
const int n = parse_line(line, var, val);
|
|||
|
if (n <= 0)
|
|||
|
break;
|
|||
|
if (var.starts_with("INDEX_"))
|
|||
|
break;
|
|||
|
if (xvt_slist_find_str(fields, var) == NULL)
|
|||
|
{
|
|||
|
query.cut(0) << "ALTER TABLE " << table << " ADD COLUMN " << var << ' ' << val << " NOT NULL";
|
|||
|
if (val.find("INT") >= 0 || val.find("NUM") >= 0)
|
|||
|
query << " DEFAULT 0";
|
|||
|
else
|
|||
|
query << " DEFAULT ''";
|
|||
|
query << ";";
|
|||
|
xvt_sql_execute(_db, query, NULL, NULL); // Create table
|
|||
|
}
|
|||
|
}
|
|||
|
xvt_slist_destroy(fields);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
query << "CREATE TABLE " << table << " (";
|
|||
|
while (!tff.eof())
|
|||
|
{
|
|||
|
const TString& line = tff.line();
|
|||
|
const int n = parse_line(line, var, val);
|
|||
|
if (n <= 0)
|
|||
|
break;
|
|||
|
if (n == 1)
|
|||
|
{
|
|||
|
tff.push(line);
|
|||
|
break;
|
|||
|
}
|
|||
|
if (var.starts_with("INDEX_"))
|
|||
|
{
|
|||
|
query.rtrim(1); // toglie ultima ,
|
|||
|
query << ");";
|
|||
|
xvt_sql_execute(_db, query, NULL, NULL); // Create table
|
|||
|
query.cut(0);
|
|||
|
query << "CREATE UNIQUE INDEX "
|
|||
|
<< table << "_1 ON " << table
|
|||
|
<< " (" << val << ");";
|
|||
|
xvt_sql_execute(_db, query, NULL, NULL); // Create index
|
|||
|
break;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
query << "\n " << var << ' ' << val << " NOT NULL";
|
|||
|
if (val.find("INT") >= 0 || val.find("NUM") >= 0)
|
|||
|
query << " DEFAULT 0";
|
|||
|
else
|
|||
|
query << " DEFAULT ''";
|
|||
|
query << ",";
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::create()
|
|||
|
{
|
|||
|
open_files(LF_MOV, LF_RMOV, LF_RMOVIVA, LF_TABCOM, LF_ANAG,
|
|||
|
LF_CLIFO, LF_OCCAS, LF_CFVEN, LF_NDITTE, 0);
|
|||
|
|
|||
|
// Controllo preventivo dell'avvenuta conversione del tracciato record
|
|||
|
TRectype rmoviva(LF_RMOVIVA);
|
|||
|
|
|||
|
//if (rmoviva.type("TFINVIO") != _boolfld)
|
|||
|
//return error_box(TR("Database non convertito per il Trasferimento Elettronico"));
|
|||
|
|
|||
|
_ditta.init(LF_NDITTE, prefix().get_codditta());
|
|||
|
|
|||
|
_dbname = prefix().get_studio(); // base direcotry
|
|||
|
_dbname.add("sql"); make_dir(_dbname);
|
|||
|
TString16 d; d.format("TR%05ld.db", prefix().get_codditta());
|
|||
|
_dbname.add(d);
|
|||
|
|
|||
|
bool create = !_dbname.exist();
|
|||
|
_db = xvt_sql_open(_dbname, user(), "", _dbname.path());
|
|||
|
if (_db == NULL)
|
|||
|
return false;
|
|||
|
|
|||
|
if(create)
|
|||
|
{
|
|||
|
createDB();
|
|||
|
}
|
|||
|
return TSkeleton_application::create();
|
|||
|
}
|
|||
|
|
|||
|
// Sincronizzo il DB SQL con quello di campo
|
|||
|
bool TTrFa_app::syncronizeDB()
|
|||
|
{
|
|||
|
//xvt_sql_begin(_db);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::createDB()
|
|||
|
{
|
|||
|
const TFilename ini = "tff.ini";
|
|||
|
bool ok = ini.exist();
|
|||
|
if (ok)
|
|||
|
{
|
|||
|
xvt_sql_begin(_db);
|
|||
|
TScanner TFF(ini);
|
|||
|
while (ok && !TFF.eof())
|
|||
|
{
|
|||
|
const TString& p = TFF.line();
|
|||
|
if (p.starts_with("[TF") && p.ends_with("F]"))
|
|||
|
{
|
|||
|
TString16 table = p; table.strip("[]");
|
|||
|
ok = create_table(TFF, table);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ok)
|
|||
|
xvt_sql_commit(_db);
|
|||
|
else
|
|||
|
xvt_sql_rollback(_db);
|
|||
|
}
|
|||
|
else
|
|||
|
return cantread_box(ini);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::send(TTrFa_mask* msk)
|
|||
|
{
|
|||
|
// Mi carico i miei dati
|
|||
|
|
|||
|
TSheet_field& sheet = msk->sfield(F_RIGHE);
|
|||
|
bool ok;
|
|||
|
TProgress_monitor p(sheet.items(),"Esportazione fatture");
|
|||
|
FOR_EACH_SHEET_ROW(sheet, r, strarr)
|
|||
|
{
|
|||
|
//if(!p.add_status())
|
|||
|
//return false;
|
|||
|
if(strcmp(strarr->get(_invio), "X") != 0) continue; // Non mi interessa se non <20> selezionata
|
|||
|
|
|||
|
TString8 hfatt; // Codice univoco di 6 caratteri dell'ufficio P.A.
|
|||
|
TString20 bfatt; // Codice univoco di 20 caratteri del documento
|
|||
|
|
|||
|
hfatt.cut(0) << strarr->get(_tipocf) << "_" << strarr->get(_codcf);
|
|||
|
bfatt.cut(0) << TDate(strarr->get(_datadoc)).year() << "|" << strarr->get(_codnum) << "|" << strarr->get(_numdoc) << "|" << strarr->get(_numriga);
|
|||
|
|
|||
|
log(-1, bfatt);
|
|||
|
|
|||
|
// Preparo l'esportazione
|
|||
|
xvt_sql_begin(_db);
|
|||
|
|
|||
|
ok = addDT(hfatt, bfatt, strarr);
|
|||
|
|
|||
|
// Controllo in caso di errore
|
|||
|
if(!ok)
|
|||
|
{
|
|||
|
log(-1, "WTF!?");
|
|||
|
xvt_sql_rollback(_db);
|
|||
|
//return false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
xvt_sql_commit(_db);
|
|||
|
// Imposto l'esportazione
|
|||
|
setEsportato(strarr);
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::addDT(TString8& hfatt, TString20& bfatt, TToken_string* strarr)
|
|||
|
{
|
|||
|
const char* const paese = "IT";
|
|||
|
static const TFirm& firm = prefix().firm();
|
|||
|
|
|||
|
// <DatiTrassmissione>
|
|||
|
TTrFa_record tff0100f("TFF0100F");
|
|||
|
tff0100f.set("P1_KEYHEADERFATT", hfatt);
|
|||
|
tff0100f.set("P1_KEYBODYFATT", bfatt);
|
|||
|
|
|||
|
tff0100f.set("P1_TRASMITTPAESE", paese);
|
|||
|
tff0100f.set("P1_TRASMITTCOD", _cofi);
|
|||
|
tff0100f.set("P1_PRGINVIO", ""); // Ci pensa SiAggTF
|
|||
|
|
|||
|
tff0100f.set("P1_CODDEST", hfatt);
|
|||
|
TString80 tel; tel << firm.get(NDT_PTEL) << firm.get(NDT_TEL);
|
|||
|
tff0100f.set("P1_TELEFONO", tel);
|
|||
|
tff0100f.set("P1_MAIL", firm.get(NDT_MAIL));
|
|||
|
tff0100f.set("P1_GESTIONE", "D");
|
|||
|
tff0100f.insert();
|
|||
|
|
|||
|
// </DatiTrassmissione>
|
|||
|
|
|||
|
/********************************************************************************************************************
|
|||
|
* CessionarioCommit *
|
|||
|
********************************************************************************************************************/
|
|||
|
|
|||
|
// <CedentePrestatore>
|
|||
|
TTrFa_record tff0200f("TFF0200F");
|
|||
|
tff0200f.set("P2_KEYHEADERFATT", hfatt);
|
|||
|
tff0200f.set("P2_KEYBODYFATT", bfatt);
|
|||
|
tff0200f.remove();
|
|||
|
|
|||
|
if (_ditta.partita_IVA().full())
|
|||
|
{
|
|||
|
tff0200f.set("P2_FISCIVAPAESE", paese); // Sempre IT
|
|||
|
tff0200f.set("P2_FISCIVACOD", _ditta.partita_IVA());
|
|||
|
}
|
|||
|
tff0200f.set("P2_CODFISCALE", _ditta.codice_fiscale());
|
|||
|
if (_ditta.fisica())
|
|||
|
{
|
|||
|
tff0200f.set("P2_ANANOME", _ditta.nome());
|
|||
|
tff0200f.set("P2_ANACOGNOME", _ditta.cognome());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
tff0200f.set("P2_ANADENOMIN", _ditta.ragione_sociale());
|
|||
|
}
|
|||
|
|
|||
|
// DatiSede
|
|||
|
tff0200f.set("P2_SEDEIND", _ditta.via_residenza());
|
|||
|
tff0200f.set("P2_SEDENRCIVICO", _ditta.civico_residenza());
|
|||
|
tff0200f.set("P2_SEDECAP", _ditta.CAP_residenza());
|
|||
|
tff0200f.set("P2_SEDECOMUNE", _ditta.comune_residenza());
|
|||
|
tff0200f.set("P2_SEDEPROV", _ditta.provincia_residenza());
|
|||
|
tff0200f.set("P2_SEDENAZ", paese);
|
|||
|
|
|||
|
TString myrfso;
|
|||
|
if(haveRFSO(myrfso))
|
|||
|
{
|
|||
|
TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << myrfso.sub(1));
|
|||
|
|
|||
|
if(r_ana.get_char("TIPORFSO") == 'S') // Stabile Organizzazione
|
|||
|
{
|
|||
|
tff0200f.set("P2_STABORGIND", r_ana.get("INDRES"));
|
|||
|
tff0200f.set("P2_STABORGNRCIVICO", r_ana.get("CIVRES"));
|
|||
|
tff0200f.set("P2_STABORGCAP", r_ana.get("CAPRES"));
|
|||
|
TRectype r_comune = cache().get(LF_COMUNI, TString("|") << r_ana.get("COMRES"));
|
|||
|
tff0200f.set("P2_STABORGCOMUNE", r_comune.get("DENCOM"));
|
|||
|
tff0200f.set("P2_STABORGPROV", r_comune.get("PROVCOM"));
|
|||
|
tff0200f.set("P2_STABORGNAZ", "IT");
|
|||
|
}
|
|||
|
else // Rappresentante Fiscale
|
|||
|
{
|
|||
|
TTrFa_record tff0300f("TFF0300F");
|
|||
|
tff0300f.set("P3_KEYHEADERFATT", hfatt);
|
|||
|
tff0300f.set("P3_KEYBODYFATT", bfatt);
|
|||
|
tff0300f.remove();
|
|||
|
tff0300f.set("P3_FISCIVAPAESE", paese); // Io italiano posso avere un rappresentante fiscale italiano
|
|||
|
tff0300f.set("P3_FISCIVACODICE", r_ana.get("PAIV"));
|
|||
|
|
|||
|
if(r_ana.get_char("TIPOA") == 'G')
|
|||
|
{
|
|||
|
tff0300f.set("P3_ANADENOMI", r_ana.get("RAGSOC"));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
TString nomCom = r_ana.get("RAGSOC");
|
|||
|
tff0300f.set("P3_ANANOME", nomCom.sub(30));
|
|||
|
tff0300f.set("P3_ANACOGNOME", nomCom.sub(0,30));
|
|||
|
}
|
|||
|
tff0300f.set("P3_GESTIONE", "D");
|
|||
|
tff0300f.insert();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
tff0200f.set("P2_GESTIONE", "D");
|
|||
|
|
|||
|
tff0200f.insert();
|
|||
|
|
|||
|
/********************************************************************************************************************
|
|||
|
* Cedeprest *
|
|||
|
********************************************************************************************************************/
|
|||
|
|
|||
|
// </CedentePrestatore>
|
|||
|
|
|||
|
TAnagrafica cedeprest(LF_CLIFO, strarr->get_char(_tipocf), strarr->get_long(_codcf));
|
|||
|
TRectype r_cedeprest = cache().get(LF_CLIFO, TString(strarr->get_char(_tipocf)) << "|" << strarr->get_long(_codcf));
|
|||
|
TString statocli = cache().get("%STA", r_cedeprest.get("STATOCF"), "S2");
|
|||
|
// <CessionarioCommittente>
|
|||
|
|
|||
|
TTrFa_record tff0400f("TFF0400F");
|
|||
|
tff0400f.set("P4_KEYHEADERFATT", hfatt);
|
|||
|
tff0400f.set("P4_KEYBODYFATT", bfatt);
|
|||
|
tff0400f.remove();
|
|||
|
|
|||
|
// Autofattura
|
|||
|
if(strcmp(strarr->get(_autofatt),"X") == 0)
|
|||
|
{
|
|||
|
tff0400f.set("P4_FISCIVAPAESE", paese);
|
|||
|
tff0400f.set("P4_FISCIVACOD", _ditta.partita_IVA());
|
|||
|
tff0400f.set("P4_CODFISC", _ditta.codice_fiscale());
|
|||
|
}
|
|||
|
else // Fattura normale
|
|||
|
{
|
|||
|
if (cedeprest.stato_partita_IVA().full() && cedeprest.partita_IVA().full())
|
|||
|
{
|
|||
|
tff0400f.set("P4_FISCIVAPAESE", cedeprest.stato_partita_IVA());
|
|||
|
tff0400f.set("P4_FISCIVACOD", cedeprest.partita_IVA());
|
|||
|
}
|
|||
|
else
|
|||
|
tff0400f.set("P4_CODFISC", cedeprest.codice_fiscale());
|
|||
|
}
|
|||
|
|
|||
|
if (cedeprest.fisica())
|
|||
|
{
|
|||
|
tff0400f.set("P4_ANANOME", cedeprest.nome());
|
|||
|
tff0400f.set("P4_ANACOGNOME", cedeprest.cognome());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
tff0400f.set("P4_ANADENOM", cedeprest.ragione_sociale());
|
|||
|
}
|
|||
|
// DatiSede
|
|||
|
tff0400f.set("P4_SEDEIND", cedeprest.via_residenza());
|
|||
|
tff0400f.set("P4_SEDENRCIVICO", cedeprest.civico_residenza());
|
|||
|
tff0400f.set("P4_SEDECAP", cedeprest.CAP_residenza());
|
|||
|
tff0400f.set("P4_SEDECOMUNE", cedeprest.comune_residenza());
|
|||
|
tff0400f.set("P4_SEDEPROV", cedeprest.provincia_residenza());
|
|||
|
tff0400f.set("P4_SEDENAZ", statocli);
|
|||
|
tff0400f.set("P4_GESTIONE", "D");
|
|||
|
tff0400f.insert();
|
|||
|
|
|||
|
TString rfso;
|
|||
|
if(hasRFSO(strarr->get_char(_tipocf), strarr->get_long(_codcf), rfso))
|
|||
|
{
|
|||
|
TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << rfso.sub(1));
|
|||
|
TTrFa_record tff3100f("TFF3100F");
|
|||
|
tff3100f.set("PH_KEYHEADERFATT", hfatt);
|
|||
|
tff3100f.set("PH_KEYBODYFATT", bfatt);
|
|||
|
tff3100f.remove();
|
|||
|
|
|||
|
if(r_ana.get_char("TIPORFSO") == 'S') // Stabile Organizzazione
|
|||
|
{
|
|||
|
tff3100f.set("PH_STABORGIND", r_ana.get("INDRES"));
|
|||
|
tff3100f.set("PH_STABORGNRCIVICO", r_ana.get("CIVRES"));
|
|||
|
tff3100f.set("PH_STABORGCAP", r_ana.get("CAPRES"));
|
|||
|
TRectype r_comune = cache().get(LF_COMUNI, TString("|") << r_ana.get("COMRES"));
|
|||
|
tff3100f.set("PH_STABORGCOMUNE", r_comune.get("DENCOM"));
|
|||
|
tff3100f.set("PH_STABORGPROV", r_comune.get("PROVCOM"));
|
|||
|
tff3100f.set("PH_STABORGNAZ", "IT");
|
|||
|
}
|
|||
|
else // Rappresentante Fiscale
|
|||
|
{
|
|||
|
// La P.IVA del rappresentante fiscale deve essere in AT quindi non faccio alcun controllo,
|
|||
|
// se il valore nullo perch<63> Extra CEE non <20> un errore di campo (Anche perch<63> che senso ha un RF extra CEE?)
|
|||
|
tff3100f.set("PH_FISCIVAPAESE", r_ana.get("STATOPAIV") == "" ? "IT" : r_ana.get("STATOPAIV"));
|
|||
|
tff3100f.set("PH_FISCIVACODICE", r_ana.get("PAIV"));
|
|||
|
|
|||
|
if(r_ana.get_char("TIPOA") == 'G')
|
|||
|
{
|
|||
|
tff3100f.set("PH_ANADENOMI", r_ana.get("RAGSOC"));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
TString nomCom = r_ana.get("RAGSOC");
|
|||
|
tff3100f.set("PH_ANANOME", nomCom.sub(30));
|
|||
|
tff3100f.set("PH_ANACOGNOME", nomCom.sub(0,30));
|
|||
|
}
|
|||
|
}
|
|||
|
tff3100f.set("PH_GESTIONE", "D");
|
|||
|
tff3100f.insert();
|
|||
|
}
|
|||
|
|
|||
|
// </CessionarioCommittente>
|
|||
|
|
|||
|
/********************************************************************************************************************
|
|||
|
* Fattura *
|
|||
|
********************************************************************************************************************/
|
|||
|
|
|||
|
// <DatiFatturaBody>
|
|||
|
TTrFa_record tff0700f("TFF0700F");
|
|||
|
tff0700f.set("P7_KEYHEADERFATT", hfatt);
|
|||
|
tff0700f.set("P7_KEYBODYFATT", bfatt);
|
|||
|
tff0700f.remove();
|
|||
|
|
|||
|
tff0700f.set("P7_GESTIONE", "D");
|
|||
|
tff0700f.insert();
|
|||
|
|
|||
|
TTrFa_record tff2200f("TFF2200F");
|
|||
|
tff2200f.set("PL_KEYHEADERFATT", hfatt);
|
|||
|
tff2200f.set("PL_KEYBODYFATT", bfatt);
|
|||
|
tff2200f.remove();
|
|||
|
|
|||
|
tff2200f.set("PL_IMPONIBILE", strarr->get(_imponibile));
|
|||
|
tff2200f.set("PL_IMPOSTA", strarr->get(_imposta));
|
|||
|
tff2200f.set("PL_ALIQUOTAIVA", strarr->get(_aliquota));
|
|||
|
tff2200f.set("PL_NATURA", strarr->get(_natura));
|
|||
|
if(strcmp(strarr->get(_detraibile), "0.00") != 0)
|
|||
|
{
|
|||
|
tff2200f.set("PL_DETRAIBILE", strarr->get(_detraibile));
|
|||
|
}
|
|||
|
else if(false) // Sempre disabilitato!
|
|||
|
{
|
|||
|
tff2200f.set("PL_DEDUCIBILE", "SI");
|
|||
|
}
|
|||
|
|
|||
|
tff2200f.set("PL_GESTIONE", "D");
|
|||
|
tff2200f.insert();
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::setEsportato(TToken_string* strarr)
|
|||
|
{
|
|||
|
if(strcmp(strarr->get(_forzata), "X") == 0)
|
|||
|
{
|
|||
|
// Devo inserire la riga in trasfatt
|
|||
|
TRectype row(LF_TRASFATT);
|
|||
|
if(strcmp(strarr->get(_spedita), "X") == 0) // Controllo che non sia gi<67> stata spedita prima
|
|||
|
{
|
|||
|
row = cache().get(LF_TRASFATT, TString(strarr->get(_numero))<<"|"<<(strarr->get(_numriga)));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
row.put("NUMREG", strarr->get(_numero));
|
|||
|
row.put("NUMRIG", strarr->get(_numriga));
|
|||
|
}
|
|||
|
row.put("TIPODOC", strarr->get(_codnum));
|
|||
|
row.put("NDOC", strarr->get(_numdoc));
|
|||
|
row.put("DATADOC", strarr->get(_datadoc));
|
|||
|
row.put("IMPONIBILE", strarr->get(_imponibile));
|
|||
|
row.put("IMPOSTA", strarr->get(_imposta));
|
|||
|
row.put("REVCHARGE", strarr->get(_reverse));
|
|||
|
row.put("AUTOFATT", strarr->get(_autofatt));
|
|||
|
row.put("TFINVIO", "X");
|
|||
|
row.put("TFDATA", TDate(TODAY));
|
|||
|
|
|||
|
return row.write_rewrite(TLocalisamfile(LF_TRASFATT)) == NOERR;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
TRectype row = cache().get(LF_RMOVIVA, TString(strarr->get(_numero))<<"|"<<(strarr->get(_numriga)));
|
|||
|
row.put("TFINVIO", "X");
|
|||
|
row.put("TFDATA", TDate(TODAY));
|
|||
|
return row.rewrite(TLocalisamfile(LF_RMOVIVA)) == NOERR;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void TTrFa_app::main_loop()
|
|||
|
{
|
|||
|
TTrFa_mask msk("tf0100a");
|
|||
|
|
|||
|
while (msk.run() == K_ENTER)
|
|||
|
{
|
|||
|
TSheet_field& sheet = msk.sfield(F_RIGHE);
|
|||
|
TString msg("La tabella dei movimenti <20> vuota, vuoi caricarla con i filtri selezionati?");
|
|||
|
if(sheet.empty() && yesno_box(msg))
|
|||
|
{
|
|||
|
msk.load_sheet();
|
|||
|
}
|
|||
|
|
|||
|
send(&msk);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool TTrFa_app::destroy()
|
|||
|
{
|
|||
|
if (_cofi.full())
|
|||
|
ini_set_string(CONFIG_DITTA, "pa", "TRASMITTCOD", _cofi);
|
|||
|
|
|||
|
xvt_sql_close(_db); _db = NULL;
|
|||
|
return TSkeleton_application::destroy();
|
|||
|
}
|
|||
|
|
|||
|
int tf0100(int argc, char* argv[])
|
|||
|
{
|
|||
|
TTrFa_app t2t;
|
|||
|
t2t.run(argc, argv, TR("Trasferimento Fatture Elettroniche"));
|
|||
|
return 0;
|
|||
|
}
|