campo-sirio/src/tf/tf0100.cpp
mtollari 03060c3e0e Patch level : 12.0 412
Files correlati     : 
Commento            : Aggiunta bolla doganale, ottimizzata funzione salvataggio record

git-svn-id: svn://10.65.10.50/branches/R_10_00@23898 c028cbd2-c16b-5b4b-a496-9718f37d4682
2017-06-30 12:57:07 +00:00

1990 lines
56 KiB
C++
Raw Blame History

#include "tf0.h"
// Le definizioni sono qua
#include "tf0100b.h"
#include <dongle.h> // dongle()
#include <odbcrset.h> // Oracle Recset
#include <mov.h>
#include <rmoviva.h>
#include <anagiu.h>
#include <comuni.h>
#include <cfven.h>
#include <nditte.h>
#include <unloc.h>
#include <causali.h>
/////////////////////////////////////////////////////////////////////////////////////
// Utilities
/////////////////////////////////////////////////////////////////////////////////////
// Le funzioni quelle belle
TString getTipoDoc(int id)
{
TString ret;
switch(id)
{
case B_TIPO_AUTOFATT:
ret = "AF";
break;
case B_TIPO_FATTACQ:
ret = "FA";
break;
case B_TIPO_FATTFISC:
ret = "FF";
break;
case B_TIPO_FATTVEN:
ret = "FV";
break;
case B_TIPO_NOTC:
ret = "NC";
break;
case B_TIPO_NOTD:
ret = "ND";
break;
case B_TIPO_STORDOC:
ret = "ST";
break;
case B_TIPO_BOLLADOG:
ret = "BD";
break;
/*
case B_TIPO_CORRNINC:
ret = "CN";
break;
case B_TIPO_CORR:
ret = "CR";
break;
case B_TIPO_FATTSC:
ret = "FS";
break;
case B_TIPO_RICFIS:
ret = "RF";
break;
case B_TIPO_RICFISNI:
ret = "RN";
break;
case B_TIPO_SCONT:
ret = "SC";
break;
case B_TIPO_SCONTNI:
ret = "SN";
break;
*/
default:
ret = "ERR";
break;
}
return ret;
}
int getTipoDoc(TString id)
{
int ret = -1;
if(id == "AF") ret = B_TIPO_AUTOFATT;
else if(id == "BD") ret = B_TIPO_BOLLADOG;
// else if(id == "CN") ret = B_TIPO_CORRNINC;
// else if(id == "CR") ret = B_TIPO_CORR;
else if(id == "FA") ret = B_TIPO_FATTACQ;
else if(id == "FF") ret = B_TIPO_FATTFISC;
// else if(id == "FS") ret = B_TIPO_FATTSC;
else if(id == "FV") ret = B_TIPO_FATTVEN;
else if(id == "NC") ret = B_TIPO_NOTC;
else if(id == "ND") ret = B_TIPO_NOTD;
// else if(id == "RF") ret = B_TIPO_RICFIS;
// else if(id == "RN") ret = B_TIPO_RICFISNI;
// else if(id == "SC") ret = B_TIPO_SCONT;
// else if(id == "SN") ret = B_TIPO_SCONTNI;
else if(id == "ST") ret = B_TIPO_STORDOC;
return ret;
}
TRectype getTrasFatt(TString reg, TString codiva)
{
TString key = reg; key << "|" << codiva;
return cache().get(LF_TRASFATT, key);
}
TRectype getCli(TString tipocf, TString codcf)
{
if(tipocf != "O")
{
TString key = tipocf; key << "|" << codcf;
return cache().get(LF_CLIFO, key);
}
// Cliente occasionale!
else
{
TRectype cli(LF_CLIFO);
TRectype occas = cache().get(LF_OCCAS, codcf);
cli.put("RAGSOC" , occas.get("RAGSOC"));
cli.put("CODRFSO" , "");
cli.put("PAIV" , occas.get("PAIV"));
cli.put("COFI" , occas.get("COFI"));
return cli;
}
}
// 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;
}
// Controlla se l'azienda ha un RFSO
static bool haveRFSO(TString& codrfso)
{
codrfso = cache().get(LF_NDITTE, prefix().firm().codice(), "CODRFSO");
if(codrfso == "") return false;
return true;
}
/* Ritorno il tipo di documento
* TD01: Fattura
* TD04: Nota di credito
* TD05: Nota di debito
* NO-> TD07: Fattura semplificata
* NO-> TD08: NC semplificata
* TD10: Fatt di acquisto intra beni
* TD11: Fatt di acquisto intra servizi
*/
static const char* decodTipo(TToken_string* strarr)
{
TRectype mov = cache().get(LF_MOV, strarr->get(_numero));
TCausale caus(mov.get("CODCAUS"), mov.get_int("ANNOIVA"));
TString tipodoc; tipodoc << strarr->get(_codnum);
// Le autofatture possono essere solo di tipo TDO1 e le bolle doganali nel dubbio pure
if(tipodoc == "AF" || tipodoc == "BD")
return "TD01";
else if(tipodoc == "FA" || tipodoc == "FV")
{
// Potrebbe essere normale o intra
if(!caus.intra())
return "TD01";
else
{
// Controlliamo se <20> di beni o servizi
// Per capire se sono beni o servizi devo prendere il movimento, e trovare quale dei due ha un importo pi<70> alto
TAssoc_array intraval;
TRelation r_moviva(LF_RMOVIVA);
TRectype filter(r_moviva.curr()); filter.put("NUMREG", strarr->get(_numero));
TCursor c_moviva(&r_moviva, "", 1, &filter, &filter);
for(c_moviva = 0; c_moviva.pos() < c_moviva.items(); ++c_moviva)
{
TRectype row = c_moviva.curr();
real importo = row.get_real("IMPONIBILE");
// La chiave deve essere formata da CODIVA, GRUPPO + CONTO + SOTTOCONTO
TString keyAssoc; keyAssoc << row.get("CODIVA") << "|" << row.get("GRUPPO") << "|" << row.get("CONTO") << "|" << row.get("SOTTOCONTO");
if(intraval.is_key(keyAssoc))
{
importo += *(real*)intraval.objptr(keyAssoc);
intraval.add(keyAssoc, importo, true);
}
else
{
intraval.add(keyAssoc, importo);
}
}
// Adesso che ho tutti i totali divisi per CODIVA e GCS vado a pescare il valore maggiore
TString keyMax = "";
real max = ZERO;
TString_array keys;
intraval.get_keys(keys);
for(int i = 0; i < keys.items(); i++)
{
TString key = *(TString*)keys.objptr(i);
real valItem = *(real*)intraval.objptr(key);
if(valItem > max)
{
keyMax = key;
max = valItem;
}
}
// Una volta che ho trovato il nostro vincitore vado a prendere il tipo di fattura dal GCS
TString keyPCon = keyMax.ssub(keyMax.find('|') + 1);
if(cache().get(LF_PCON, keyPCon, "RICSER") == "1")
return "TD11";
else
return "TD10";
}
}
else if(tipodoc == "NC")
return "TD04";
else if(tipodoc == "ND")
return "TD05";
else
return tipodoc;
}
/* Salvo il record modificato in TFCustom */
bool saveRec(TToken_string row, bool esportato)
{
static TLocalisamfile trasfatt(LF_TRASFATT);
// Devo inserire la riga in trasfatt
TRectype rCust(LF_TRASFATT);
if(strcmp(row.get(_spedita), "X") == 0) // Controllo che non sia gi<67> stata spedita prima
{
TString key = row.get(_numero); key << "|"<< row.get(_aliquota);
rCust = cache().get(LF_TRASFATT, key);
}
// Controllo non si sa mai
if(rCust.empty())
{
rCust.put("NUMREG", row.get(_numero));
}
rCust.put("TIPO", row.get(_tipocf));
rCust.put("CODCF", row.get(_codcf));
rCust.put("OCCAS", row.get(_occas));
rCust.put("TIPODOC", row.get(_codnum));
rCust.put("NUMDOC", row.get(_numdoc));
rCust.put("DATAREG", row.get(_datareg));
rCust.put("DATADOC", row.get(_datadoc));
rCust.put("IMPONIBILE", row.get(_imponibile));
rCust.put("IMPOSTA", row.get(_importoIVA));
rCust.put("CODIVA", row.get(_aliquota));
rCust.put("AUTOFATT", row.get(_autofatt));
if(esportato)
{
rCust.put("TFINVIO", true);
rCust.put("TFDATA", TDate(TODAY));
}
return rCust.write_rewrite(trasfatt) == NOERR;
}
/////////////////////////////////////////////////////////////////////////////////////
// TTrFa_record
/////////////////////////////////////////////////////////////////////////////////////
// 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("IMPONIBILE")>0 || fldname.find("IMPOSTA")>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);
if (k2 && *k2)
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
/////////////////////////////////////////////////////////////////////////////////////
TTrFa_cursors::~TTrFa_cursors()
{
if(c_rmoviva != NULL)
delete c_rmoviva;
}
int TTrFa_cursors::next(TAssoc_array& recimposte, bool& ok, TString& tipocf, TString& codcf)
{
// Azzero recimposte
recimposte.destroy();
// Return code
return_code err;
// Record
TRectype record = _next(err, tipocf, codcf);
if(record.get("NUMREG") == "42094")
bool tolla = true;
while(err < nextmov)
{
// Se ho trovato un record custom o non trovo il suo codiva tra i record custom lo salvo
if(recimposte.is_key(record.get("CODIVA")))
{
// Prelevo il record salvato
TRectype app = *(TRectype*)recimposte.objptr(record.get("CODIVA"));
// Aggiorno i valori
app.put("IMPONIBILE", app.get_real("IMPONIBILE") + record.get_real("IMPONIBILE"));
app.put("IMPOSTA", app.get_real("IMPOSTA") + record.get_real("IMPOSTA"));
// Lo reinserisco
recimposte.add(record.get("CODIVA"), app, true);
}
else // Inserisco per la prima volta
{
// Salvo il record nell'array
recimposte.add(record.get("CODIVA"), record);
}
record = _next(err, tipocf, codcf);
}
ok = err != eof;
return err;
}
/*
* Questa funzione precarica un array associativo con il movimento diviso per codiva e lo ritorna
*/
TRectype TTrFa_cursors::_next(return_code& code, TString& tipocf, TString& codcf)
{
TString numMov = c_rmoviva->get("23.NUMREG").as_string();
// Record di ritorno
TRectype retRec(LF_TRASFATT);
// Controllo che non sia il primo record del movimento
if(_newMov)
{
_newMov = false;
// Se <20> un cliente occasionale passo "O"
if(c_rmoviva->get("23.OCFPI").as_string() != "")
{
tipocf = "O";
codcf = c_rmoviva->get("23.OCFPI").as_string();
}
else
{
tipocf = c_rmoviva->get("23.TIPO").as_string();
codcf = c_rmoviva->get("23.CODCF").as_string();
}
}
else
{
TString codiva;
do
{
// Se ritorna false ho finito i records
if(!c_rmoviva->move_next())
{
code = eof;
return retRec;
}
else
{
// Controllo se ho cambiato movimento
_newMov = numMov != c_rmoviva->get("23.NUMREG").as_string();
}
} // Ciclo finch<63> non trovo un nuovo movimento o trovo cod IVA gi<67> presi da cust
while(!checkRecord(c_rmoviva) || (!_newMov && _alqCust.get_pos(codiva) > -1));
}
// Se ho cambiato movimento ritorno, legger<65> poi al prossimo giro
if(_newMov)
{
_alqCust.cut(0);
code = nextmov;
return retRec;
}
else
code = found;
// Controllo dell'esistenza di un record custom in tasfatt
retRec = getTrasFatt(c_rmoviva->get("23.NUMREG").as_string(), c_rmoviva->get("25.CODIVA").as_string());
if(retRec.empty())
{
code = found;
// Carico il record
retRec.put("NUMREG", c_rmoviva->get("23.NUMREG").as_int());
retRec.put("TIPO", c_rmoviva->get("23.TIPO").as_string());
retRec.put("CODCF", c_rmoviva->get("23.CODCF").as_string());
retRec.put("OCCAS", c_rmoviva->get("23.OCFPI").as_string());
retRec.put("TIPODOC", c_rmoviva->get("23.TIPODOC").as_string());
retRec.put("NUMDOC", c_rmoviva->get("23.NUMDOC").as_string());
retRec.put("DATAREG", c_rmoviva->get("23.DATAREG").as_date());
retRec.put("DATADOC", c_rmoviva->get("23.DATADOC").as_date());
retRec.put("IMPONIBILE", c_rmoviva->get("25.IMPONIBILE").as_real());
retRec.put("IMPOSTA", c_rmoviva->get("25.IMPOSTA").as_real());
retRec.put("CODIVA", c_rmoviva->get("25.CODIVA").as_string());
retRec.put("TIPODET", c_rmoviva->get("25.TIPODET").as_string());
}
else
{
_alqCust.add(c_rmoviva->get("25.CODIVA").as_string());
code = foundcust;
}
return retRec;
}
/* Utilizzo questa funzione per filtrare al meglio i record, tutti i casi che devo omettere verranno rilevati e ritorneranno false
* Nota bene: viene sfruttato un puntatore di TISA_Recordset per non creare nuovi oggetti e velocizzare la chiamata
* a questo punto il programma non ha ancora creato un record di $trasfatt con i dati che mi interessano
*/
bool TTrFa_cursors::checkRecord(TISAM_recordset* rec)
{
TString codiva = rec->get("25.CODIVA").as_string();
// Tolgo i non soggetti
TCodiceIVA cod(codiva);
if(cod.tipo() == "NS")
return false;
// Clienti
if(rec->get("23.TIPO").as_string() == "C")
{
// Tolgo tutti i movimenti di sola IVA e in reverse charge o di tipo 3 (Acquisto di beni e servizi di soggetti non residenti)
TCausale caus(rec->get("23.CODCAUS").as_string());
if(caus.soloiva() && (caus.reverse_charge() || caus.regime_speciale() == 3))
return false;
}
return true;
}
int TTrFa_cursors::updateFilters(const char tipocf, const long codcf, TDate dal, TDate al, int cod)
{
TString query = "USE RMOVIVA\n";
query << "SELECT (23.REG!=\"\")&&BETWEEN(23.DATAREG,#DADATAREG,#ADATAREG)&&(23.TIPO=\"" << tipocf << "\")";
if(codcf > 0)
query<<"&&STR((23.CODCF=#CODCF))";
/*
switch(cod)
{
case toSend:
query<<"&&(23.TFINVIO!=\"X\")";
break;
case sent:
query<<"&&(23.TFINVIO=\"X\")";
break;
default:
break;
}
*/
query << "\nJOIN MOV INTO NUMREG==NUMREG\n";
c_rmoviva = new TISAM_recordset(query);
if(dal.empty()) dal = "20170101"; // Data in cui questo modulo <20> diventato valido
if(al.empty()) al = TODAY;
c_rmoviva->set_var("#DADATAREG", dal);
c_rmoviva->set_var("#ADATAREG", al);
if(codcf > 0)
c_rmoviva->set_var("#CODCF", codcf);
if(c_rmoviva->items() > ZERO)
{
_newMov = true;
return c_rmoviva->items();
}
return -1;
}
/////////////////////////////////////////////////////////////////////////////////////
// TTrFa_mask
/////////////////////////////////////////////////////////////////////////////////////
TTrFa_mask::~TTrFa_mask()
{
TSheet_field& sheet = sfield(F_RIGHE);
if(!sheet.empty())
sheet.destroy();
}
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 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;
case F_RIGHE:
if (e == se_notify_add)
{
TSheet_field& s = (TSheet_field&)o;
TToken_string& row = s.row(jolly);
row.add(nuovo_progr(), s.cid2index(A_NUMERO));
} else
if (e == se_query_del)
{
TSheet_field& s = (TSheet_field&)o;
TToken_string& row = s.row(jolly);
const TRecnotype progr = row.get_long(0);
return progr >= MOV_CUSTOM;
}
break;
case A_DATAREG:
{
// Mi interessa solo fe_edit
if(e != fe_modify) break;
// Controllo che la data sia < della data documento e l'esercizio sia quello richiesto
TDate datareg = o.get(), datadoc = o.mask().get(A_DATADOC);
if(datareg >= get_date(F_DATAINI) && datareg <= get_date(F_DATAFIN))
{
// Controllo la data del documento
if(datadoc.ok())
{
if(datadoc > datareg)
{
error_box("La data del documento <20> antecedente a quella di registrazione");
o.set("");
}
}
}
else
{
error_box("La data di registrazione non appartiene al periodo corrente");
o.set("");
}
}
break;
case A_DATADOC:
{
// Mi interessa solo fe_edit
if(e != fe_modify) break;
TDate datareg = o.mask().get(A_DATAREG), datadoc = o.get();
// Controllo la data di registrazione
if(datareg.ok())
{
if(datadoc > datareg)
{
error_box("La data del documento <20> antecedente a quella di registrazione");
o.set("");
}
}
}
break;
case A_ALIQUOTA:
if(e == fe_modify)
{
// Calcolo la natura
o.mask().set(A_NATURA, natura(o.get()));
// Se esiste un imponibile calcolo l'imposta
real imponibile = o.mask().get(A_IMPONIBILE), imposta = ZERO;
if(imponibile > 0)
{
imposta = imponibile * real(cache().get("%IVA", o.get(), "R0")) / 100;
o.mask().set(A_IMPOSTA, imposta.round(2).string());
}
}
break;
case A_IMPONIBILE:
if(e == fe_modify)
{
// Se esiste l'iva calcolo l'imposta
real imponibile = o.get(), imposta = ZERO;
TString codiva = o.mask().get(A_ALIQUOTA);
if(codiva != "")
{
imposta = imponibile * real(cache().get("%IVA", codiva, "R0")) / 100;
o.mask().set(A_IMPOSTA, imposta.round(2).string());
}
}
break;
case A_IMPOSTA:
if(e == fe_modify)
{
// Controllo dell'esistenza sia di codiva che dell'imponibile e verifico che l'importo immesso sia corretto
real imponibile = o.mask().get(A_IMPONIBILE), imposta = ZERO;
TString codiva = o.mask().get(A_ALIQUOTA);
if(codiva != "" && imponibile > ZERO)
{
imposta = imponibile * real(cache().get("%IVA", codiva, "R0")) / 100; imposta = imposta.round(2);
// Controllo che l'aliquota calcolata sia == a quella che ho qua
real impostaInserita = o.get();
if(impostaInserita != imposta)
{
TString msg;
msg << "Attenzione!! Il valore immesso " << impostaInserita.string() << "<EFBFBD> non <20> corretto!\n";
msg << "Valore corretto: " << imposta.string() << "<EFBFBD>\nVuoi proseguire?";
if(!yesno_box(msg))
{
o.set(imposta.string());
}
}
}
}
case A_TIPOCF:
case A_CODCF:
case A_OCFPI:
{
if(e != fe_modify) break;
TString tipocf, codcf;
// Controllo se <20> un cliente occasionale
tipocf = "O";
codcf = o.mask().get(A_OCFPI);
if(codcf.empty())
{
tipocf = o.mask().get(A_TIPOCF);
codcf = o.mask().get(A_CODCF);
}
TRectype app = getCli(tipocf, codcf);
o.mask().set(A_RAGSOC, app.get("RAGSOC"));
o.mask().set(A_RFSO, app.get("CODRFSO"));
o.mask().set(A_RAGSOCRFSO, getRFSO(app.get("CODRFSO")));
o.mask().set(A_PAIV, app.get("PAIV"));
o.mask().set(A_COFI, app.get("COFI"));
// Controllo autofattura
TString key; key << prefix().firm().get("TIPOA") << "|" << prefix().firm().get("CODANAGR");
TString piva = cache().get(LF_ANAG, key, "PAIV");
if(piva == app.get("PAIV"))
{
// Autofattura!
o.mask().set(A_AUTOFATT, "X");
}
}
case DLG_SAVEREC:
if(e == fe_button)
saveAll();
break;
case DLG_ARCHIVE:
if(e == fe_button)
checkAll();
break;
case DLG_EDIT:
if(e == fe_button)
{
TSheet_field& sheet = sfield(F_RIGHE);
if(sheet.items() > 0)
{
sheet.esporta();
}
else
{
warning_box("Impossibile esportare una griglia vuota");
}
}
break;
default:
break;
}
const short id = o.dlg();
if (e == fe_modify && jolly == 1)
{
if (id >= START_SHEET && id < END_SHEET && id != A_FORZATA)
{
o.mask().set(A_FORZATA, true);
}
}
if (e == fe_modify && jolly == 0)
{
if (id >= START_MASK && id <= END_MASK)
{
setFilterChanged();
}
if(id >= START_BOOLEAN && id <= END_BOOLEAN)
saveConfig();
}
return true;
}
void TTrFa_mask::loadConfig()
{
// Rilevo i tipi scelti
TToken_string tipidoc(ini_get_string(CONFIG_DITTA, "tf", "TIPIDOC"));
// Potrei fare un for su TToken_string ma non darebbe la possibilit<69> di flaggare tutto in caso di prima installazione
for(int pos = 0; pos < tipidoc.items(); pos++)
{
int field = getTipoDoc(tipidoc.get(pos));
if(field != -1)
set(field, "X");
}
}
void TTrFa_mask::saveConfig()
{
TToken_string tipidoc;
for(int id = START_BOOLEAN; id <= END_BOOLEAN; id++)
{
if(get_bool(id))
{
tipidoc.add(getTipoDoc(id));
}
}
ini_set_string(CONFIG_DITTA, "tf", "TIPIDOC", tipidoc);
}
/* salvo tutti i record modificati */
bool TTrFa_mask::saveAll()
{
TSheet_field& sheet = sfield(F_RIGHE);
//TString_array& strarr = sheet.rows_array();
TString mod = "";
FOR_EACH_SHEET_ROW(sheet, r, strarr)
{
strarr->get(_forzata, mod);
if(mod == "X")
{
bool ok, retry = false;
do
{
ok = saveRec(*strarr);
if(!ok)
{
TString msg = "Errore durante il salvataggio del movimento ";
msg << "alla riga " << r << "\nRitentare?";
retry = yesno_box(msg);
}
} while(retry && !ok);
if(!ok)
return false;
}
}
return true;
}
bool TTrFa_mask::checkAll()
{
// Controllo di avere uno sheet pieno
if(!checkNotEmpty()) return true;
if(yesno_box("Controllare tutti i C.F. P.IVA?"))
{
TExternal_app servizio("cg1 -2 L");
servizio.run();
}
static TPrinter stampa;
stampa.reset();
stampa.open();
TPrintrow riga;
riga.put(TR("------------------ Controllo Errori TF -------------------"), 30);
stampa.setheaderline(1, riga);
riga.reset();
riga.put("N.Registrazione", 0);
riga.put("N.Documento", 20);
riga.put("Tipo errore", 40);
stampa.setheaderline(3, riga);
riga.reset();
riga.put(TR("Tutti i record errati sono stati segnati con il codice \"Errore\" e non verranno inviati"), 0);
stampa.setheaderline(2, riga);
riga.reset();
stampa.setheaderline(4, riga);
TSheet_field& sheet = sfield(F_RIGHE);
FOR_EACH_SHEET_ROW(sheet, r, strarr)
{
checkRec(&stampa, *strarr);
}
stampa.close();
return true;
}
inline void printError(TPrinter* stampa, TString movimento, TString documento, TString msgerr)
{
TPrintrow riga;
riga.put(movimento, 0);
riga.put(documento, 20);
riga.put(msgerr, 40);
stampa->print(riga);
}
bool TTrFa_mask::checkRec(TPrinter* stampa, TToken_string rec)
{
bool ok = true;
TString numMov = rec.get(_numero), numDoc = rec.get(_numdoc);
TString msgerr;
TString coderr;
// Controllo date ***********************************************************************************
TDate reg = rec.get(_datareg), doc = rec.get(_datadoc);
if(reg < doc)
{
ok = false;
msgerr.cut(0) << "Data registrazione precedente alla data del documento";
printError(stampa, numMov, numDoc, msgerr);
coderr << "1;";
}
// Controllo aliquota, imponibile e imposta *********************************************************
TCodiceIVA codiva(rec.get(_aliquota));
TString nat = rec.get(_natura), realNat(natura(rec.get(_aliquota)));
nat.ltrim(); // Se vuoto arriva con uno spazio
real imponibile = rec.get(_imponibile), imposta = rec.get(_importoIVA);
if(nat != realNat)
{
msgerr.cut(0) << "Natura del movimento errata, valore dichiarato: " << nat << " valore corretto: " << realNat;
printError(stampa, numMov, numDoc, msgerr);
coderr << "2;";
}
real realImp = imponibile * codiva.percentuale() / CENTO;
realImp.round(2);
if(imposta != realImp)
{
msgerr.cut(0) << "Imposta errata, valore dichiarato: " << imposta.string() << " valore corretto: " << realImp.string();
printError(stampa, numMov, numDoc, msgerr);
coderr << "3;";
}
// Controllo Stato ***********************************************************************************
/*
TRectype clifo = getCli(rec.get(_tipocf), rec.get(_codcf));
if(clifo.get("STATOCF") == "" &&
*/
// Flaggo il record con i messaggi di errore
if(!ok)
{
rec.add("E", _invio);
rec.add(coderr, _coderr);
}
return ok;
}
bool TTrFa_mask::checkNotEmpty()
{
TSheet_field& sheet = sfield(F_RIGHE);
TString msg;
if(sheet.empty())
msg = "La tabella dei movimenti <20> vuota, vuoi caricarla con i filtri selezionati?";
else if(_filter_changed)
msg = "I filtri sono stati cambiati, vuoi ricaricare la tabella con i nuovi filtri selezionati?";
if(msg.full() && yesno_box(msg))
{
_filter_changed = false;
load_sheet();
}
return sheet.full();
}
TRecnotype TTrFa_mask::nuovo_progr() const
{
static TRectype app(LF_TRASFATT);
app.last(TLocalisamfile(LF_TRASFATT));
// Lo inizializzo solo la prima volta poi incremento
static TRecnotype numreg = app.get_long("NUMREG") > MOV_CUSTOM ? app.get_long("NUMREG") : MOV_CUSTOM;
numreg++;
return numreg;
}
void TTrFa_mask::load_sheet()
{
const char tipo = get(F_TIPOCF)[0];
const long codice = 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!
if(!sheet.empty())
sheet.destroy();
TAssoc_array recimposte;
int items = c.updateFilters(tipo, codice, dal, al, get_int(F_FATTSEL));
for(bool ok = true; items > 0 && ok;)
{
TString tipocf, codcf;
int err = c.next(recimposte, ok, tipocf, codcf);
// Carico i clienti
TRectype cli = getCli(tipocf, codcf);
FOR_EACH_ASSOC_OBJECT(recimposte, h, iva, rec)
{
TToken_string* row = new TToken_string;
TRectype movimento = *(TRectype*)rec;
// Controllo che sia un tipo documento da leggere
if(!get_bool(getTipoDoc(movimento.get("TIPODOC")))) continue;
/* Siccome mi cambiano l'ordine ogni volta e non ho voglia di cambiare tutto ovunque
* basta settare i valori negli enum e lo sheet
*/
TRectype isCust = getTrasFatt(movimento.get("NUMREG"), iva);
row->add(isCust.get_bool("TFINVIO") ? "X" : "", _spedita); // Spedita
row->add("X"); // Da spedire, sempre!
row->add(isCust.full() ? "X" : "", _forzata); // Modificato
row->add(movimento.get_long("NUMREG"), _numero); // Numero registrazione
row->add(movimento.get_date("DATAREG"), _datareg); // Data Registrazione
row->add(movimento.get("TIPO"), _tipocf); // Tipo Cli/For
row->add(movimento.get("CODCF"), _codcf); // Codice Cli/For
row->add(movimento.get("OCCAS"), _occas); // Codice Occasionale
row->add(cli.get("RAGSOC"), _ragsoc); // Ragione sociale
row->add(cli.get("CODRFSO"), _rfso); // Codice RF/SO
row->add(getRFSO(cli.get("CODRFSO")), _ragsocrfso); // Ragione Sociale RF/SO
row->add(movimento.get("TIPODOC"), _codnum); // Tipo documento
row->add(movimento.get("NUMDOC"), _numdoc); // Numero documento
row->add(movimento.get_date("DATADOC"), _datadoc); // Data documento
row->add(natura(iva), _natura); // NATURA!
row->add(iva, _aliquota); // Codice aliquota!
row->add(findDetraib(movimento.get("TIPODET")), _detraibile); // Detraibilit<69>
row->add(movimento.get_real("IMPONIBILE"), _imponibile); // Imponibile
row->add(movimento.get_real("IMPOSTA"), _importoIVA); // Imposta
row->add(revCharge(movimento.get("NUMREG")), _reverse); // Rev.Charge
/*
* Possono esistere movimenti custom dove il cliente ha una partita IVA propria
* ma <20> stato flaggato l'autofattura, quindi in trasfat <20> presente il codice cliente con PIVA e CODFIS della ditta.
* Controllo sia il movimento che il cliente
*/
if(movimento.get("AUTOFATT") == "X" || pivaDitta == cli.get("PAIV")) // Se <20> un autofattura
{
row->add("X", _autofatt); // AutoFatt
row->add(pivaDitta, _paiv); // P.IVA
row->add(cofiDitta, _codfis); // Codice Fiscale
}
else
{
row->add("", _autofatt); // AutoFatt
row->add(cli.get("PAIV"), _paiv); // P.IVA
row->add(cli.get("COFI"), _codfis); // Codice Fiscale
}
strarr.add(row);
}
recimposte.destroy();
}
sheet.force_update();
sheet.show();
}
TString TTrFa_mask::findDetraib(TString tipodet) const
{
real perc = cache().get("%DET", tipodet, "R0");
return perc.stringa(6,2);
}
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");
return natura;
}
real TTrFa_mask::get_IVA(const TString& codiva) const
{
const TRectype& ai = cache().get("%IVA", codiva);
return ai.get_real("R0");
}
TString TTrFa_mask::revCharge(TString numreg) const
{
// Controllo se la causale ha il reverse charge, se il cliente non l'ha impostata giusta sono ARAZZI suoi
TString key = numreg;
TCausale caus(cache().get(LF_MOV, key, "CODCAUS"));
return caus.reverse_charge() ? "X" : "";
}
TString TTrFa_mask::getRFSO(TString codrfso) const
{
TString key; key << codrfso[0] << "|" << codrfso.mid(1);
return cache().get(LF_ANAG, key, "RAGSOC");
}
TTrFa_mask::TTrFa_mask(TString msk)
: TAutomask(msk), _filter_changed(true)
{
loadConfig();
}
/////////////////////////////////////////////////////////////////////////////////////
// TTrFa_app
/////////////////////////////////////////////////////////////////////////////////////
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;
}
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("TF%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)
{
// Aggiungo il valore di default in TFNUM
TTrFa_record tfnum("TFNUM00F");
tfnum.set("PJNKEY", "00001");
tfnum.set("PJNINV", "0000000000");
ok = tfnum.insert();
}
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)
{
// Controllo se <20> la prima esecuzione, in caso positivo chiedo se vuole controllare p.iva e cf
bool first = ini_get_bool(CONFIG_DITTA, "tf", "FirstExec", true);
if(first)
{
if(yesno_box("Stai eseguendo il programma per la prima volta,\nvuoi controllare di avere tutti i Codici Fiscali e Partite IVA corrette?"))
{
TExternal_app checkApp("cg1 -2 L");
checkApp.run();
}
ini_set_bool(CONFIG_DITTA, "tf", "FirstExec", false);
}
// Mi carico i miei dati
TSheet_field& sheet = msk->sfield(F_RIGHE);
// Booleano per appendere i record nel db
/***********************************************************************************************
* Esporto
***********************************************************************************************/
xvt_sql_begin(_db);
bool ok;
// Testata
ok = tff0100(sheet);
if(ok)
{
// Anagrafica
ok = tff0400(sheet);
if(ok)
// Documenti
ok = tff0700(sheet);
}
if(!ok)
{
log(-1, "WTF!?");
xvt_sql_rollback(_db);
return false;
}
if(xvt_sql_commit(_db))
{
message_box("Ho esportato correttamente!");
// Imposto l'esportazione
if(yesno_box("Vuoi segnare i record esportati?"))
setEsportato(sheet);
}
else
message_box("Errore durante il salvataggio delle modifiche");
return true;
}
TString TTrFa_app::getKey(TToken_string* strarr)
{
return strarr->get_char(_tipocf) == 'C' ? DTE_PROVV : DTR_PROVV;
}
TString TTrFa_app::getHeader(TToken_string* strarr)
{
/*
// Chiave header (20): TIPOCF(1) + NANANANANA(10) + CODCF(6)
TString header; header.format("%c3753N4108E%06ld", strarr->get_char(_tipocf), strarr->get_int(_codcf));
return header;
*/
/* Devo crearmi una struttura dove immagazzino delle strutture di clienti e all'interno ci metto i numeratori che mi chiedono
* Cos<6F> facendo mando a puttane persino l'append che potevo tranquillamente implementare prima e creare fastidiose query per capire dove cazzo sto
*/
// Chiave header (20): TIPOCF(1) + CODCF(6)
static long int idHeader = 0L;
// Cerco/Aggiungo il Clifo all'std::map
TString keyMap; keyMap << strarr->get_char(_tipocf) << "|" << strarr->get_int(_codcf);
clifoDoc app;
// Non <20> presente e lo inserisco per la chiave body
if(mCliDoc.find(keyMap) == mCliDoc.end())
{
idHeader++;
app.contCliFo = idHeader;
app.countDoc = 0L;
mCliDoc.insert(std::pair<TString,clifoDoc>(keyMap, app));
}
TString header; header.format("%c%06ld", strarr->get_char(_tipocf), strarr->get_int(_codcf));
// Ritorno l'header
return header;
}
TString TTrFa_app::getBody(TToken_string* strarr, bool add)
{
/*
// Chiave body (20): TIPODOC(2) + DATADOC[YEAR](4) + NUMDOC(7) + AAA(3) + CODALIQUOTA(4)
TDate datadoc(strarr->get(_datadoc));
TString body; body.format("%02s%04d%07s%04s", strarr->get(_codnum), datadoc.year(), strarr->get(_numdoc), strarr->get(_aliquota));
return body;
*/
/* Sembra che utilizzare identificatori chiari e sensati in questo mondo non <20> concesso, quindi adesso vi sbatto un bell'ID numerico
* Ok per OGNI cliente devo assegnarli un identificativo del numero della fattura
*/
TString keyMap; keyMap << strarr->get_char(_tipocf) << "|" << strarr->get_int(_codcf);
clifoDoc app = mCliDoc[keyMap];
if(add)
app.countDoc += 1;
mCliDoc[keyMap] = app;
TString body; body.format("%010d%010d", app.contCliFo, app.countDoc);
return body;
}
bool TTrFa_app::tff0100(TSheet_field& sheet)
{
const char* const paese = "IT";
static const TFirm& firm = prefix().firm();
// Controllo la presenza di clienti e fornitori
// Scandisco in maniera ignorante sperando di beccare subito un cliente e un fornitore
bool cli = false, fo = false;
FOR_EACH_SHEET_ROW(sheet, r, strarr)
{
if(strarr->get_char(_tipocf) == 'C')
cli = true;
else
fo = true;
if(cli & fo) break;
}
// Metto qua il numero di telefono per dopo
TString80 tel; tel << firm.get(NDT_PTEL) << firm.get(NDT_TEL);
bool ok = true;
if(cli)
{
TTrFa_record dte("TFF0100F");
// Controllo la presenza di un caricamento in attesa
if(dte.search(DTE_PROVV))
{
bool sent = dte.get("P1_KEYPRGINVIO").as_string() == DTE_PROVV;
if(sent)
{
TString msg = "<EFBFBD> presente un'altra esportazione non ancora elaborata vuoi eliminarla?";
if(yesno_box(msg))
{
if(!emptyTables(DTE_PROVV))
{
error_box("Fallita eliminazione record!!!");
return false;
}
}
else
return false;
}
}
dte.set("P1_KEYPRGINVIO", DTE_PROVV);
dte.set("P1_TRASMITTPAESE", paese);
dte.set("P1_TRASMITTCOD", _cofi);
dte.set("P1_TIPOINVIO", "DTE");
dte.set("P1_TELEFONO", tel);
dte.set("P1_MAIL", firm.get(NDT_MAIL));
dte.set("P1_GESTIONE", "");
ok = dte.insert();
if(!ok) return false;
ok = tff0200(DTE_PROVV);
if(!ok) return false;
}
if(fo)
{
TTrFa_record dtr("TFF0100F");
// Controllo la presenza di un caricamento in attesa
if(dtr.search(DTR_PROVV))
{
bool sent = dtr.get("P1_KEYPRGINVIO").as_string() == DTR_PROVV;
TString msg = "<EFBFBD> presente un'altra esportazione non ancora elaborata vuoi eliminarla?";
if(sent)
{
if(yesno_box(msg))
{
if(!emptyTables(DTE_PROVV))
{
error_box("Fallita eliminazione record!!!");
return false;
}
}
else
return false;
}
}
dtr.set("P1_KEYPRGINVIO", DTR_PROVV);
dtr.set("P1_TRASMITTPAESE", paese);
dtr.set("P1_TRASMITTCOD", _cofi);
dtr.set("P1_TIPOINVIO", "DTR");
dtr.set("P1_TELEFONO", tel);
dtr.set("P1_MAIL", firm.get(NDT_MAIL));
dtr.set("P1_GESTIONE", "");
ok = dtr.insert();
if(!ok) return false;
ok = tff0200(DTR_PROVV);
if(!ok) return false;
}
return ok;
}
bool TTrFa_app::tff0200(TString key)
{
/********************************************************************************************************************
* Cedeprest *
********************************************************************************************************************/
// <CedentePrestatore>
TTrFa_record tff0200f("TFF0200F");
tff0200f.set("P2_KEYPRGINVIO", key);
if (_ditta.partita_IVA().full())
{
tff0200f.set("P2_FISCIVAPAESE", _ditta.stato_partita_IVA()); // 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());
if(_ditta.italiano()) // Campo ritornerebbe "EE" se estero
tff0200f.set("P2_SEDEPROV", _ditta.provincia_residenza());
tff0200f.set("P2_SEDENAZ", _ditta.stato_residenzaISO());
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
{
bool ok = tff0300(key, r_ana);
if(!ok) return false;
}
}
tff0200f.set("P2_GESTIONE", "");
return tff0200f.insert();
}
bool TTrFa_app::tff0300(TString key, TRectype r_ana)
{
TTrFa_record tff0300f("TFF0300F");
tff0300f.set("P3_KEYPRGINVIO", key);
TString stato = r_ana.get("STATOPAIV") == "" ? "IT" : r_ana.get("STATOPAIV");
tff0300f.set("P3_FISCIVAPAESE", stato);
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");
return tff0300f.insert();
}
bool TTrFa_app::tff0400(TSheet_field& sheet)
{
// Siccome non siamo in grado di fare delle join devo in qualche modo evitare di caricare clienti gi<67> caricati quindi mi salvo tutto in un bel TToken_string e controllo
// Era troppo complicato fare una join codice cliente con i documenti per prendere solo quelli valorizzati.
TToken_string clifoSent = "";
bool ok = true;
TProgress_monitor p(sheet.items(),"Caricamento Clienti/Fornitori");
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
// Controllo il clifo, se non c'<27> lo aggiungo altrimenti salto sto giro
TString checkClifo; checkClifo << strarr->get_char(_tipocf) << strarr->get_long(_codcf);
if(clifoSent.get_pos(checkClifo) < 0)
clifoSent.add(checkClifo);
else
continue;
TAnagrafica cedeprest(LF_CLIFO, strarr->get_char(_tipocf), strarr->get_long(_codcf));
TString keyCedPrest; keyCedPrest << strarr->get_char(_tipocf) << "|" << strarr->get_long(_codcf);
TRectype r_cedeprest = cache().get(LF_CLIFO, keyCedPrest);
TString statocli = cache().get("%STA", r_cedeprest.get("STATOCF"), "S10");
// Se rimane vuoto <20> italiano
if(statocli == "")
statocli = "IT";
TTrFa_record tff0400f("TFF0400F");
tff0400f.set("P4_KEYPRGINVIO", getKey(strarr));
tff0400f.set("P4_KEYHEADERFATT", getHeader(strarr));
// Autofattura
if(strcmp(strarr->get(_autofatt),"X") == 0)
{
tff0400f.set("P4_FISCIVAPAESE", _ditta.stato_partita_IVA());
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");
ok = tff0400f.insert();
// Controllo dopo l'inserimento del tff0400
if(!ok) return false;
TString rfso = strarr->get(_rfso);
if(rfso.full())
{
TRectype r_ana = cache().get(LF_ANAG, TString(myrfso[0]) << rfso.sub(1));
ok = tff3100(strarr, r_ana);
}
// E dopo l'inserimento del tff3100
if(!ok) return false;
}
return ok;
}
bool TTrFa_app::tff0700(TSheet_field& sheet)
{
/********************************************************************************************************************
* Fattura *
********************************************************************************************************************/
// Mentre per i clienti <20> una porcata per le fatture non posso fare altrimenti, potrebbe essere che i clienti mettono righe in fondo customizzate spezzando fatture
TToken_string fattSent = "";
bool ok = true;
TProgress_monitor p(sheet.items(), "Caricamento Fatture");
TString oldKey = "";
int numRiga;
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
TString checkFatt; checkFatt << strarr->get_char(_tipocf) << "|" << strarr->get_long(_codcf) << "|" << strarr->get(_numdoc);
if(fattSent.get_pos(checkFatt) < 0)
{
fattSent.add(checkFatt);
// <DatiFatturaBody>
TTrFa_record tff0700f("TFF0700F");
tff0700f.set("P7_KEYPRGINVIO", getKey(strarr));
tff0700f.set("P7_KEYHEADERFATT", getHeader(strarr));
tff0700f.set("P7_KEYBODYFATT", getBody(strarr));
tff0700f.set("P7_TIPODOC", decodTipo(strarr));
tff0700f.set("P7_DATA", toDate(strarr->get(_datadoc)));
tff0700f.set("P7_NUMERO", strarr->get(_numdoc));
tff0700f.set("P7_DATAREG", toDate(strarr->get(_datareg))); // Obbligatoria nei DTR
tff0700f.set("P7_GESTIONE", "");
ok = tff0700f.insert();
// Controllo dopo l'inserimento del tff0700f
if(!ok) return false;
}
// In qualsiasi caso va messa la riga ma prima elaboro il numero della riga!
TString newKey = getBody(strarr, false);
if(oldKey != newKey)
{
numRiga = 1;
oldKey = newKey;
}
else
numRiga++;
ok = tff2200(strarr, numRiga);
// E dopo l'inserimento del tff2200
if(!ok) return false;
}
return ok;
}
bool TTrFa_app::tff2200(TToken_string* strarr, int nriga)
{
TTrFa_record tff2200f("TFF2200F");
tff2200f.set("PL_KEYPRGINVIO", getKey(strarr));
tff2200f.set("PL_KEYHEADERFATT", getHeader(strarr));
tff2200f.set("PL_KEYBODYFATT", getBody(strarr, false));
TString numriga; numriga.format("%020d", nriga);
tff2200f.set("PL_KEYBODYDETT", numriga);
tff2200f.set("PL_IMPONIBILE", real(strarr->get(_imponibile))); // Se li converto in real una volta passati vengono parsati da var2str nel formato che vuole l'agenzia delle entrate
tff2200f.set("PL_IMPOSTA", real(strarr->get(_importoIVA)));
real aliquota = cache().get("%IVA", strarr->get(_aliquota), "R0");
tff2200f.set("PL_ALIQUOTAIVA", aliquota);
tff2200f.set("PL_NATURA", strarr->get(_natura));
real det(strarr->get(_detraibile));
// Nella conversione la vigola viene persa e 100,00 diventa 10.000 quindi divido
det /= CENTO;
if(det > ZERO)
{
tff2200f.set("PL_DETRAIBILE", det);
}
else if(false) // Sempre disabilitato!
{
tff2200f.set("PL_DEDUCIBILE", "SI");
}
tff2200f.set("PL_GESTIONE", "D");
return tff2200f.insert();
}
bool TTrFa_app::tff3100(TToken_string* strarr, TRectype r_ana)
{
TTrFa_record tff3100f("TFF3100F");
tff3100f.set("PH_KEYPRGINVIO", getKey(strarr));
tff3100f.set("PH_KEYHEADERFATT", getHeader(strarr));
if(_append)
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?)
TString stato = r_ana.get("STATOPAIV") == "" ? "IT" : r_ana.get("STATOPAIV");
tff3100f.set("PH_FISCIVAPAESE", stato);
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");
return tff3100f.insert();
}
bool TTrFa_app::setEsportato(TSheet_field& sheet)
{
bool ok = true;
TProgress_monitor p(sheet.items(),"Segno l'esportazione sui records");
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
if(strcmp(strarr->get(_forzata), "X") == 0)
{
ok = saveRec(*strarr, true);
if(!ok) return false;
}
else
{
TRectype row = cache().get(LF_MOV, TString(strarr->get(_numero)));
row.put("TFINVIO", "X");
row.put("TFDATA", TDate(TODAY).string());
ok = row.rewrite(TLocalisamfile(LF_MOV)) == NOERR;
if(!ok) return false;
}
}
return ok;
}
bool TTrFa_app::emptyTables(TString key)
{
TString query;
query << "DELETE FROM TFF0100F WHERE P1_KEYPRGINVIO = '" << key << "';\n";
query << "DELETE FROM TFF0200F WHERE P2_KEYPRGINVIO = '" << key << "';\n";
query << "DELETE FROM TFF0300F WHERE P3_KEYPRGINVIO = '" << key << "';\n";
query << "DELETE FROM TFF0400F WHERE P4_KEYPRGINVIO = '" << key << "';\n";
query << "DELETE FROM TFF0700F WHERE P7_KEYPRGINVIO = '" << key << "';\n";
query << "DELETE FROM TFF2200F WHERE PL_KEYPRGINVIO = '" << key << "';\n";
query << "DELETE FROM TFF3100F WHERE PH_KEYPRGINVIO = '" << key << "';\n";
return xvt_sql_execute(_db, query, NULL, NULL) >= 0;
}
void TTrFa_app::main_loop()
{
TTrFa_mask msk("tf0100a");
while (msk.run() == K_ENTER)
{
if(msk.checkNotEmpty())
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;
}