1441 lines
39 KiB
C++
1441 lines
39 KiB
C++
#include <applicat.h>
|
|
#include <automask.h>
|
|
#include <dongle.h>
|
|
#include <execp.h>
|
|
#include <progind.h>
|
|
#include <recarray.h>
|
|
#include <recset.h>
|
|
#include <relation.h>
|
|
#include <reputils.h>
|
|
#include <tabutil.h>
|
|
#include <utility.h>
|
|
#include <validate.h>
|
|
|
|
#include "../fe/felib.h"
|
|
|
|
#include "ef0301.h"
|
|
#include "ef1100a.h"
|
|
|
|
#include "clifo.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Globals
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static XVT_SQLDB _db = NULL; // SEPA sqlite db
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// 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;
|
|
}
|
|
|
|
// Aggiorna il file dst se più vecchio di src (Potrebbe diventare una funzione di XVT.h)
|
|
bool xvt_fsys_fupdate(const char* src, const char* dst)
|
|
{
|
|
bool ok = false;
|
|
if (xvt_fsys_file_exists(src))
|
|
{
|
|
const long tsrc = xvt_fsys_file_attr(src, XVT_FILE_ATTR_MTIME);
|
|
if (tsrc > 0)
|
|
{
|
|
long tdst = 0;
|
|
if (xvt_fsys_file_exists(dst))
|
|
tdst = xvt_fsys_file_attr(dst, XVT_FILE_ATTR_MTIME);
|
|
if (tsrc > tdst)
|
|
ok = xvt_fsys_fcopy(src, dst) != 0;
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// TJava_profile
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class TJava_profile : public TObject
|
|
{
|
|
TFilename _path;
|
|
TString_array _row;
|
|
bool _dirty;
|
|
|
|
protected:
|
|
const TString& path2prop(const char* path) const;
|
|
|
|
public:
|
|
void set(const char* key, const char* value);
|
|
void save();
|
|
TJava_profile(const char* path);
|
|
~TJava_profile() { if (_dirty) save(); }
|
|
};
|
|
|
|
// Converte una stringa in un percorso per un file profile di Java
|
|
const TString& TJava_profile::path2prop(const char* path) const
|
|
{
|
|
TFilename percorso;
|
|
for (const char* c = path; *c; c++)
|
|
{
|
|
if (*c == ':' || is_slash(*c))
|
|
percorso << '\\';
|
|
percorso << *c;
|
|
}
|
|
return get_tmp_string() = percorso;
|
|
}
|
|
|
|
|
|
void TJava_profile::set(const char* key, const char* value)
|
|
{
|
|
_dirty = true;
|
|
FOR_EACH_ARRAY_ROW(_row, r, line)
|
|
{
|
|
if (line->starts_with(key, true))
|
|
{
|
|
const int equal = line->find('=');
|
|
if (equal > 0)
|
|
{
|
|
line->cut(equal + 1);
|
|
*line << path2prop(value);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
TToken_string* prop = new TToken_string(50, '=');
|
|
prop->add(key); prop->add(path2prop(value));
|
|
_row.add(prop);
|
|
}
|
|
|
|
void TJava_profile::save()
|
|
{
|
|
ofstream out(_path);
|
|
if (out.good())
|
|
{
|
|
FOR_EACH_ARRAY_ROW(_row, r, line) if (line->full())
|
|
out << *line << endl;
|
|
_dirty = false;
|
|
}
|
|
else
|
|
cantwrite_box(_path);
|
|
}
|
|
|
|
TJava_profile::TJava_profile(const char* path) : _path(path), _dirty(false)
|
|
{
|
|
TScanner s(_path);
|
|
while (!s.eof())
|
|
{
|
|
const TString& line = s.line();
|
|
if (line.full())
|
|
_row.add(new TToken_string(line, '='));
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// TSEPA_record
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Contenitore di campi di un record di database SQLite
|
|
class TSEPA_record : public TObject
|
|
{
|
|
TString8 _table;
|
|
TToken_string _key;
|
|
TAssoc_array _fields;
|
|
|
|
protected:
|
|
void copy(const TSEPA_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 TSEPA_record(*this); }
|
|
virtual bool ok() const { return _table.not_empty(); }
|
|
|
|
TSEPA_record& operator=(const TSEPA_record& rec) { copy(rec); return *this; }
|
|
TSEPA_record(const TSEPA_record& rec) { copy(rec); }
|
|
TSEPA_record(const char* table);
|
|
};
|
|
|
|
// Imposta il valore di un campo variant
|
|
void TSEPA_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 TSEPA_record::set(const char* fld, long val)
|
|
{
|
|
const TVariant var(val);
|
|
set(fld, var);
|
|
}
|
|
|
|
// Imposta il valore di un campo stringa
|
|
void TSEPA_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 TSEPA_record::set(const char* fld, const TString& val)
|
|
{
|
|
const TVariant var(val);
|
|
set(fld, var);
|
|
}
|
|
|
|
// Imposta il valore di un campo numerico
|
|
void TSEPA_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 TSEPA_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 TSEPA_record::set(const char* fld, bool var)
|
|
{
|
|
set(fld, var ? "TRUE" : "FALSE");
|
|
}
|
|
|
|
// Legge il valore di un campo variant
|
|
const TVariant& TSEPA_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& TSEPA_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().date2ansi(); // Data ANSI = YYYYMMDD
|
|
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 TSEPA_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 db_search_record(void* jolly, int cols, char** values, char** names)
|
|
{
|
|
TSEPA_record& rec = *(TSEPA_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 TSEPA_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, db_search_record, this) == 1;
|
|
}
|
|
|
|
// Carica un record in base ad un massimo di 3 campi chiave
|
|
bool TSEPA_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 TSEPA_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
|
|
TSEPA_record::TSEPA_record(const char* table) : _table(table), _key(15, ',')
|
|
{
|
|
_key = ini_get_string("./sepa.ini", table, "INDEX_1");
|
|
if (_key.empty())
|
|
{
|
|
// Cerco di costruire i nomi della chiave cercando la K, come in P1_KEYHEADERFATT
|
|
TConfig cfg("sepa.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);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// TSEPA_mask
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class TSEPA_mask : public TAutomask
|
|
{
|
|
TAssoc_array _banche;
|
|
|
|
protected:
|
|
void append(TSheet_field& s, TToken_string& row, TISAM_recordset& dist, const char* fld);
|
|
void fill_sheet();
|
|
|
|
protected:
|
|
virtual bool on_field_event(TOperable_field& o, TField_event fe, long jolly);
|
|
const TString& banca(const char* abi, const char* cab);
|
|
|
|
public:
|
|
TSEPA_mask() : TAutomask("ef1100a") {}
|
|
};
|
|
|
|
const TString& TSEPA_mask::banca(const char* abi, const char* cab)
|
|
{
|
|
TString16 cod; cod << abi << cab;
|
|
TString* desc = (TString*)_banche.objptr(cod);
|
|
if (desc == NULL)
|
|
{
|
|
desc = new TString;
|
|
_banche.add(cod, desc);
|
|
|
|
TString16 ban;
|
|
ban << abi;
|
|
TString dabi = cache().get("%BAN", ban, "S0");
|
|
ban << cab;
|
|
TString dcab = cache().get("%BAN", ban, "S0");
|
|
if (dcab.starts_with(dabi))
|
|
*desc = dcab;
|
|
else
|
|
*desc << dabi << ' ' << dcab;
|
|
}
|
|
return *desc;
|
|
}
|
|
|
|
void TSEPA_mask::fill_sheet()
|
|
{
|
|
TSheet_field& s = sfield(F_SHEET);
|
|
s.hide();
|
|
s.destroy();
|
|
|
|
TString query;
|
|
query << "USE EFFETTI KEY 3"
|
|
<< "\nSELECT (TIPOCF=#TIPOCF)&&(TIPOPAG=#TIPOPAG)&&(NRIGADIST=1)";
|
|
if (!get_bool(F_SHOWALL))
|
|
query << "&&(EFFCOMP!=\"X\")";
|
|
|
|
if (!field(F_ABI).empty())
|
|
{
|
|
query << "&&(STR(";
|
|
query << "(CODABIP=#ABI)";
|
|
if (!field(F_CAB).empty())
|
|
query << "&&(CODCABP=#CAB)";
|
|
query << "))";
|
|
}
|
|
query << "\nFROM DATASCAD=#DATA";
|
|
|
|
TISAM_recordset dist(query);
|
|
dist.set_var("#TIPOCF", get(F_TIPOCF));
|
|
dist.set_var("#TIPOPAG", get(F_TIPO));
|
|
dist.set_var("#DATA", get(F_DATA));
|
|
dist.set_var("#ABI", get(F_ABI));
|
|
dist.set_var("#CAB", get(F_CAB));
|
|
|
|
TProgress_monitor pi(dist.items(), TR("Selezione disitinte"));
|
|
const TRelation& rel = *dist.cursor()->relation();
|
|
const TRectype& curr = rel.curr();
|
|
for (bool ok = dist.move_first(); ok; ok = dist.move_next())
|
|
{
|
|
TToken_string& row = s.row(-1);
|
|
FOR_EACH_MASK_FIELD(s.sheet_mask(), i, f) if (f->field() != NULL)
|
|
{
|
|
const char* val = f->field()->read(curr);
|
|
row.add(val, s.cid2index(f->dlg()));
|
|
}
|
|
|
|
TDistinta dist(curr);
|
|
real importo;
|
|
FOR_EACH_ARRAY_ITEM(dist.righe(), i, obj)
|
|
{
|
|
const TRectype& eff = *(const TRectype*)obj;
|
|
importo += eff.get_real(EFF_IMPORTO);
|
|
}
|
|
row.add(importo.string(), s.cid2index(S_IMPORTO));
|
|
|
|
const TString& desc = banca(curr.get(EFF_CODABIP), curr.get(EFF_CODCABP));
|
|
row.add(desc, s.cid2index(S_BANCA));
|
|
|
|
row.add(curr.get(EFF_EFFCONT));
|
|
row.add(curr.get(EFF_EFFCOMP));
|
|
|
|
if (!pi.add_status())
|
|
break;
|
|
}
|
|
|
|
s.force_update();
|
|
s.show();
|
|
}
|
|
|
|
bool TSEPA_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
|
{
|
|
switch (o.dlg())
|
|
{
|
|
case F_DATA:
|
|
if (e == fe_init)
|
|
{
|
|
TDate d(TODAY); d.set_day(1); d.addmonth(-3);
|
|
o.set(d.string());
|
|
}
|
|
case F_TIPO:
|
|
case F_TIPOCF:
|
|
case F_CAB:
|
|
case F_SHOWALL:
|
|
if (e == fe_modify && is_running())
|
|
fill_sheet();
|
|
break;
|
|
case F_SHEET:
|
|
if (e == fe_init)
|
|
fill_sheet();
|
|
if (e == se_query_add || e == se_query_del)
|
|
return false;
|
|
break;
|
|
default: break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// TSEPA_app
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class TSEPA_app : public TSkeleton_application
|
|
{
|
|
TAnagrafica _ditta;
|
|
TString16 _cofi, _cuc;
|
|
TFilename _dbname, _dbon, _drid;
|
|
TLog_report* _log;
|
|
TString _logpaf;
|
|
|
|
protected:
|
|
int parse_line(const TString& line, TString& var, TString& val) const;
|
|
bool create_table(TScanner& paf, const TString& table);
|
|
TDate data_scadenza(const TRectype& eff) const;
|
|
|
|
real genera_BON(const TString& PmtInfId, const TEffetto& eff);
|
|
bool genera_dist_BON(char td, long nd, TLog_report& log);
|
|
bool genera_SEPA_BON(const TMask& m, TLog_report& log);
|
|
|
|
real genera_RID(const TString& PmtInfId, const TEffetto& eff, TLog_report& log);
|
|
bool genera_dist_RID(char td, long nd, TLog_report& log);
|
|
bool genera_SEPA_RID(const TMask& m, TLog_report& log);
|
|
bool convert_apos(const TString& xml) const;
|
|
bool genera_xml(int tipo, bool tuttapost);
|
|
void completa(TDistinta& dist) const;
|
|
|
|
public:
|
|
virtual bool create();
|
|
virtual void main_loop();
|
|
virtual bool destroy();
|
|
};
|
|
|
|
int TSEPA_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 TSEPA_app::create_table(TScanner& paf, const TString& table)
|
|
{
|
|
TString query, var, val;
|
|
if (xvt_sql_table_exists(_db, table))
|
|
{
|
|
SLIST fields = xvt_sql_list_fields(_db, table);
|
|
while (!paf.eof())
|
|
{
|
|
const TString& line = paf.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 (!paf.eof())
|
|
{
|
|
const TString& line = paf.line();
|
|
const int n = parse_line(line, var, val);
|
|
if (n <= 0)
|
|
break;
|
|
if (n == 1)
|
|
{
|
|
paf.push(line);
|
|
break;
|
|
}
|
|
if (var.starts_with("INDEX_"))
|
|
{
|
|
query.rtrim(1); // toglie ultima ,
|
|
query << ");";
|
|
xvt_sql_execute(_db, query, NULL, NULL); // Create table
|
|
|
|
if (val.full())
|
|
{
|
|
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 TSEPA_app::create()
|
|
{
|
|
if (!has_module(SEAUT))
|
|
return error_box(TR("Si richiede l'attivazione del modulo SEPA"));
|
|
|
|
const long cd = prefix().get_codditta();
|
|
if (cd <= 0 || !prefix().is_firm())
|
|
return cantread_box(TR("Ditta corrente"));
|
|
|
|
open_files(LF_TAB, LF_TABCOM, LF_TABMOD, LF_ANAG, LF_CLIFO,
|
|
LF_CFVEN, LF_CFBAN, LF_NDITTE, LF_EFFETTI, LF_REFFETTI, 0);
|
|
_ditta.init(LF_NDITTE, cd);
|
|
|
|
// Crea cartelle di lavoro: C:\CAMPO\DATI\SEPA\BON e C:\CAMPO\DATI\\SEPA\RID
|
|
_dbname = firm2dir(cd); _dbname.rtrim(6); _dbname.add("SEPA"); make_dir(_dbname);
|
|
_dbon = _dbname; _dbon.add("BON"); make_dir(_dbon);
|
|
_drid = _dbname; _drid.add("RID"); make_dir(_drid);
|
|
|
|
// Crea file di lavoro: C:\CAMPO\DATI\00001A\SEPA\SEPA.db
|
|
TString16 name; name.format("SEPA%05d.db", cd);
|
|
_dbname.add(name);
|
|
_db = xvt_sql_open(_dbname, user(), "", _dbname.path());
|
|
if (_db == NULL)
|
|
return cantread_box(_dbname);
|
|
|
|
const TFilename ini = "sepa.ini";
|
|
bool ok = ini.exist();
|
|
if (ok)
|
|
{
|
|
xvt_sql_begin(_db);
|
|
TScanner sepa(ini);
|
|
while (ok && !sepa.eof())
|
|
{
|
|
const TString& p = sepa.line();
|
|
if (p.starts_with("[SE") && p.ends_with("00F]"))
|
|
{
|
|
TString16 table = p; table.strip("[]");
|
|
ok = create_table(sepa, table);
|
|
}
|
|
}
|
|
|
|
if (ok)
|
|
xvt_sql_commit(_db);
|
|
else
|
|
xvt_sql_rollback(_db);
|
|
}
|
|
else
|
|
return cantread_box(ini);
|
|
|
|
_cofi = ini_get_string(CONFIG_DITTA, "ef", "TRASMITTCOD");
|
|
if (_cofi.blank())
|
|
_cofi = _ditta.codice_fiscale();
|
|
|
|
_cuc = ini_get_string(CONFIG_DITTA, "ef", "CUC");
|
|
|
|
return ok && TSkeleton_application::create();
|
|
}
|
|
|
|
bool TSEPA_app::destroy()
|
|
{
|
|
if (_cofi.full())
|
|
ini_set_string(CONFIG_DITTA, "ef", "TRASMITTCOD", _cofi);
|
|
|
|
xvt_sql_close(_db); _db = NULL;
|
|
return TSkeleton_application::destroy();
|
|
}
|
|
|
|
// Id univoco distinta
|
|
static bool SEPA_MsgId(const TRectype& dist, TString& id)
|
|
{
|
|
const long firm = prefix().get_codditta();
|
|
const char tipo = dist.get_char(EFF_TIPODIST);
|
|
const long num = dist.get_long(EFF_NDIST);
|
|
const int abi = dist.get_int(EFF_CODABIP);
|
|
const int cab = dist.get_int(EFF_CODCABP);
|
|
id.format("%05ld-%c%05d-%05d%05d", firm, tipo, num, abi, cab);
|
|
CHECKS(id.len() <= 26, "MsgId più lungo di 26 caratteri ", id);
|
|
return abi > 0 && cab > 0;
|
|
}
|
|
|
|
// Instruction Identification
|
|
static bool SEPA_InstrId(const TRectype& eff, TString& id)
|
|
{
|
|
const char tipo = eff.get_char(EFF_TIPODIST);
|
|
const long num = eff.get_long(EFF_NDIST);
|
|
const int nriga = eff.get_int(EFF_NRIGADIST);
|
|
id.format("%c%05ld-%05d", tipo, num, nriga);
|
|
return nriga > 0;
|
|
}
|
|
|
|
static void AS400_date_time(TString& d, TString& t)
|
|
{
|
|
const struct tm& lt = *xvt_time_now();
|
|
d.format("%04d%02d%02d", lt.tm_year+1900, lt.tm_mon, lt.tm_mday);
|
|
t.format("%02d%02d%02d", lt.tm_hour, lt.tm_min, lt.tm_sec);
|
|
}
|
|
|
|
static const char* tipo_sequenza(const TRectype& eff)
|
|
{
|
|
const TRectype& mandato = cache().get("&MAN", eff.get(EFF_MANDATO));
|
|
if (!mandato.empty())
|
|
{
|
|
const TString& s = mandato.get("S6");
|
|
if (s.full())
|
|
return s;
|
|
}
|
|
return "RCUR";
|
|
}
|
|
|
|
|
|
TDate TSEPA_app::data_scadenza(const TRectype& eff) const
|
|
{
|
|
const TDate oggi(TODAY);
|
|
TDate dt = eff.get(EFF_DSCVAL);
|
|
if (!dt.ok() || dt < oggi)
|
|
dt = eff.get_date(EFF_DATASCAD);
|
|
if (!dt.ok() || dt < oggi)
|
|
{
|
|
dt = oggi;
|
|
// dt.set_end_month(); // Forse per RID
|
|
}
|
|
return dt;
|
|
}
|
|
|
|
|
|
real TSEPA_app::genera_BON(const TString& PmtInfId, const TEffetto& eff)
|
|
{
|
|
TSEPA_record body("SEBOD00F");
|
|
|
|
TString instr_id; SEPA_InstrId(eff, instr_id);
|
|
body.set("SED001", PmtInfId);
|
|
body.set("SED002", instr_id);
|
|
body.set("SED003", "SUPP");
|
|
body.set("SED004", ""); // Prtry
|
|
body.set("SED005", "EUR");
|
|
const real imp = eff.get_real(EFF_IMPORTO);
|
|
body.set("SED006", imp);
|
|
|
|
const TAnagrafica creditor(eff);
|
|
body.set("SED009", creditor.ragione_sociale());
|
|
body.set("SED010", "ADDR"); // Tipo indirizzo 2.6.2.1
|
|
//body.set("SET011", divisione);
|
|
//body.set("SET012", sotto-divisione);
|
|
body.set("SED013", creditor.via_residenza());
|
|
body.set("SED014", creditor.civico_residenza());
|
|
body.set("SED015", creditor.CAP_residenza());
|
|
body.set("SED016", creditor.comune_residenza());
|
|
body.set("SED017", creditor.provincia_residenza());
|
|
body.set("SED018", creditor.stato_partita_IVA());
|
|
body.set("SED019", creditor.partita_IVA().full() ? creditor.partita_IVA() : creditor.codice_fiscale());
|
|
body.set("SED020", "ADE");
|
|
body.set("SED021", creditor.stato_partita_IVA());
|
|
body.set("SED022", eff.get(EFF_IBAN));
|
|
body.insert();
|
|
|
|
TString16 codbnp; codbnp << eff.get(EFF_CODABIP) << eff.get(EFF_CODCABP) << eff.get(EFF_PROGBNP);
|
|
const TRectype& bnp = cache().get("BNP", codbnp);
|
|
const bool sepa_dett = bnp.get_bool("B3");
|
|
|
|
// Dettagli fatture pagate
|
|
const TRecord_array reff(eff.get(EFF_NPROGTR), LF_REFFETTI);
|
|
for (int r = reff.first_row(); r > 0 && r <= reff.last_row(); r = reff.succ_row(r))
|
|
{
|
|
const TRectype& riga = reff[r];
|
|
|
|
TSEPA_record rata("SEBOF00F");
|
|
rata.set("SEF001", PmtInfId);
|
|
rata.set("SEF002", instr_id);
|
|
rata.set("SEF003", (long)r);
|
|
rata.set("SEF004", "CINV"); // Commercial Invoice (oppure DEBN, CREN?)
|
|
TString doc_id;
|
|
doc_id << riga.get(REFF_ANNO) << '/' << riga.get(REFF_NFATT);
|
|
doc_id.strip_spaces();
|
|
|
|
const TString& cup = eff.get(EFF_CUP);
|
|
if (cup.full())
|
|
doc_id << " CUP-" << cup;
|
|
else
|
|
{
|
|
const TString& cig = eff.get(EFF_CIG);
|
|
if (cig.full())
|
|
doc_id << " CIG-" << cig;
|
|
}
|
|
rata.set("SEF007", doc_id);
|
|
rata.set("SEF008", riga.get_date(REFF_DATAFATT));
|
|
rata.set("SEF009", riga.get_real(REFF_IMPFATT));
|
|
rata.set("SEF011", riga.get_real(REFF_IMPORTO));
|
|
if (!sepa_dett) // NON STRUTTURATO
|
|
{
|
|
TString desc;
|
|
const TCurrency tot = riga.get_real(REFF_IMPFATT);
|
|
const TCurrency pag = riga.get_real(REFF_IMPORTO);
|
|
if (tot > pag)
|
|
{
|
|
desc.format(FR("Fatt:%s Data %s Tot:%s Pag:%s"),
|
|
(const char*)doc_id, (const char*)riga.get(REFF_DATAFATT),
|
|
tot.string(), pag.string());
|
|
}
|
|
else
|
|
{
|
|
desc.format(FR("Fatt:%s Data:%s Imp:%s"),
|
|
(const char*)doc_id, (const char*)riga.get(REFF_DATAFATT),
|
|
pag.string());
|
|
}
|
|
if (r > 1)
|
|
desc.insert(" - ");
|
|
rata.set("SEF012", desc);
|
|
}
|
|
|
|
rata.insert();
|
|
}
|
|
|
|
return imp;
|
|
}
|
|
|
|
void TSEPA_app::completa(TDistinta& dist) const
|
|
{
|
|
TLocalisamfile eff(LF_EFFETTI);
|
|
for (int i = 0; i < dist.items(); i++)
|
|
{
|
|
TEffetto& r = dist[i];
|
|
r.put(EFF_EFFCOMP, true);
|
|
r.rewrite(eff);
|
|
}
|
|
}
|
|
|
|
bool TSEPA_app::genera_dist_BON(char td, long nd, TLog_report& log)
|
|
{
|
|
TDistinta dist(td, nd);
|
|
|
|
TAssoc_array subdist;
|
|
|
|
for (int i = 0; i < dist.items(); i++)
|
|
{
|
|
const TEffetto& eff = dist[i];
|
|
const char* ts = tipo_sequenza(eff);
|
|
if (ts && *ts)
|
|
{
|
|
const TDate data = data_scadenza(eff);
|
|
TString16 key; key.format("%s_%ld", ts, data.date2ansi());
|
|
TArray* list = (TArray*)subdist.objptr(key);
|
|
if (list == NULL)
|
|
{
|
|
list = new TArray;
|
|
subdist.add(key, list);
|
|
}
|
|
list->add(eff);
|
|
}
|
|
else
|
|
{
|
|
TString msg;
|
|
msg << TR("Tipo sequenza non valido alla riga ")
|
|
<< eff.get(EFF_NRIGADIST) << TR(" della distinta ") << nd;
|
|
log.log(2, msg);
|
|
}
|
|
}
|
|
|
|
if (subdist.empty())
|
|
return false;
|
|
|
|
// Identificativo univoco messaggio
|
|
TString msg_id; SEPA_MsgId(dist[0], msg_id);
|
|
|
|
TString8 msg_date, msg_time;
|
|
AS400_date_time(msg_date, msg_time);
|
|
|
|
// In AS400 non si gestiscono le sottodistinte, per cui creo una distinta per ogni sottodisitinta
|
|
FOR_EACH_ASSOC_OBJECT(subdist, hobj, key, itm)
|
|
{
|
|
const TArray& trans = objptr2array(itm);
|
|
|
|
TSEPA_record head("SEBOT00F");
|
|
|
|
// Il codice univoco diventa MsgId + Id
|
|
TString PmtInfId; PmtInfId << msg_id << '-' << msg_date.left(8);
|
|
log.log(0, PmtInfId);
|
|
|
|
head.set("SET001", PmtInfId); // MsgId
|
|
|
|
// Nel file XML viene richiesta data/ora in formato ISO, qui invece ci sono due campi distinti à la AS400
|
|
head.set("SET002", msg_date); // CreDtTm data
|
|
head.set("SET0021", msg_time); // CreDtTm ora
|
|
|
|
head.set("SET003", long(trans.items())); // NbOfTxs
|
|
head.set("SET004", ZERO); // totale
|
|
head.set("SET005", _ditta.ragione_sociale()); // Nm
|
|
|
|
const TEffetto& e0 = dist[0];
|
|
TString16 codtab = e0.get(EFF_CODABIP); codtab << e0.get(EFF_CODCABP);
|
|
TString4 prog = e0.get(EFF_PROGBNP);
|
|
if (prog.full()) codtab << prog;
|
|
const TRectype& bnp = cache().get("BNP", codtab);
|
|
|
|
TString8 cuc = bnp.get("S5"); // CUC specifico per banca di presentazione
|
|
if (cuc.blank()) cuc = _cuc; // CUC generale della ditta corrente
|
|
|
|
head.set("SET006", cuc); // Id
|
|
head.set("SET007", "CBI"); // Issr
|
|
|
|
head.set("SET008", "TRF"); // TRF,CHK,TRA
|
|
head.set("SET009", "NORM"); // Priority2Code: NORM o HIGH
|
|
|
|
const TDate ReqdExctnDt = data_scadenza(e0);
|
|
head.set("SET010", ReqdExctnDt); // Data richiesta dal mittente YYYY-MM-DD
|
|
|
|
// 2.6.1 AT-02 Name of the originator
|
|
head.set("SET011", _ditta.ragione_sociale()); // Cdtr
|
|
head.set("SET012", "ADDR"); // AddressType2Code 2.6.2.1
|
|
//head.set("SET013", divisione);
|
|
//head.set("SET014", sotto-divisione);
|
|
head.set("SET015", _ditta.via_residenza());
|
|
head.set("SET016", _ditta.civico_residenza());
|
|
head.set("SET017", _ditta.CAP_residenza());
|
|
head.set("SET018", _ditta.comune_residenza());
|
|
head.set("SET019", _ditta.provincia_residenza());
|
|
|
|
head.set("SET020", _ditta.stato_partita_IVA()); // Alpha-2 code
|
|
head.set("SET021", _ditta.partita_IVA());
|
|
head.set("SET022", "ADE");
|
|
head.set("SET023", _ditta.stato_partita_IVA());
|
|
|
|
head.set("SET024", bnp.get("S3"));
|
|
//head.set("SET025", BIC); ???
|
|
head.set("SET026", codtab.left(5));
|
|
head.set("SET027", "SLEV");
|
|
|
|
real totale;
|
|
|
|
FOR_EACH_ARRAY_ITEM(trans, r, peff)
|
|
{
|
|
const TEffetto& e = *(TEffetto*)peff;
|
|
totale += genera_BON(PmtInfId, e);
|
|
}
|
|
|
|
head.set("SET004", totale);
|
|
|
|
head.insert();
|
|
}
|
|
|
|
completa(dist);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TSEPA_app::genera_SEPA_BON(const TMask& msk, TLog_report& log)
|
|
{
|
|
xvt_sql_begin(_db);
|
|
|
|
TString query;
|
|
|
|
query = "DELETE FROM SEBOT00F;";
|
|
xvt_sql_execute(_db, query, NULL, 0L);
|
|
|
|
query = "DELETE FROM SEBOD00F;";
|
|
xvt_sql_execute(_db, query, NULL, 0L);
|
|
|
|
query = "DELETE FROM SEBOF00F;";
|
|
xvt_sql_execute(_db, query, NULL, 0L);
|
|
|
|
const TSheet_field& sht = msk.sfield(F_SHEET);
|
|
TRecnotype nd = 0;
|
|
FOR_EACH_SHEET_ROW(sht, r, row) if (row->get_char(0) == 'X')
|
|
{
|
|
char tipo = '\0'; row->get(1, tipo);
|
|
long numd = 0L; row->get(2, numd);
|
|
if (genera_dist_BON(tipo, numd, log))
|
|
nd++;
|
|
}
|
|
|
|
if (nd > 0)
|
|
xvt_sql_commit(_db);
|
|
else
|
|
xvt_sql_rollback(_db);
|
|
|
|
return nd > 0;
|
|
}
|
|
|
|
real TSEPA_app::genera_RID(const TString& PmtInfId, const TEffetto& eff, TLog_report& log)
|
|
{
|
|
TSEPA_record body("SERID00F");
|
|
|
|
TString instr_id; SEPA_InstrId(eff, instr_id);
|
|
body.set("SERD01", PmtInfId);
|
|
body.set("SERD02", instr_id);
|
|
body.set("SERD03", "SUPP");
|
|
body.set("SERD04", "EUR");
|
|
const real imp = eff.get_real(EFF_IMPORTO);
|
|
body.set("SERD05", imp);
|
|
body.set("SERD06", "SLEV");
|
|
|
|
TString80 cmndt = eff.get(EFF_MANDATO);
|
|
TDate dmndt = cache().get("&MAN", cmndt, "D0");
|
|
if (cmndt.blank())
|
|
{
|
|
TString msg;
|
|
msg << TR("Codice mandato assente in ") << instr_id;
|
|
log.log(1, msg);
|
|
cmndt = instr_id;
|
|
dmndt = eff.get_date(EFF_DATADIST);
|
|
}
|
|
body.set("SERD07", cmndt); // Codice mandato
|
|
body.set("SERD08", dmndt); // Data mandato
|
|
body.set("SERD09", "0"); // era FALSE e non funzionava
|
|
|
|
const TAnagrafica debitor(eff);
|
|
body.set("SERD11", debitor.ragione_sociale());
|
|
body.set("SERD121", "ADDR"); // Tipo indirizzo 2.6.2.1
|
|
//body.set("SERD12", divisione);
|
|
//body.set("SERD13", sotto-divisione);
|
|
body.set("SERD14", debitor.via_residenza());
|
|
body.set("SERD15", debitor.civico_residenza());
|
|
body.set("SERD16", debitor.CAP_residenza());
|
|
body.set("SERD17", debitor.comune_residenza());
|
|
body.set("SERD18", debitor.provincia_residenza());
|
|
body.set("SERD19", debitor.stato_partita_IVA());
|
|
body.set("SERD20", debitor.fisica() ? 1L : 0L);
|
|
body.set("SERD22", debitor.partita_IVA().full() ? debitor.partita_IVA() : debitor.codice_fiscale());
|
|
body.set("SERD23", "ADE");
|
|
body.set("SERD24", debitor.stato_partita_IVA());
|
|
|
|
body.set("SERD25", eff.get(EFF_IBAN));
|
|
body.set("SERD26", "SUPP");
|
|
body.set("SERD27", "CRED");
|
|
|
|
body.insert();
|
|
|
|
TString16 codbnp; codbnp << eff.get(EFF_CODABIP) << eff.get(EFF_CODCABP) << eff.get(EFF_PROGBNP);
|
|
const TRectype& bnp = cache().get("BNP", codbnp);
|
|
|
|
// Dettagli fatture pagate
|
|
const TRecord_array reff(eff.get(EFF_NPROGTR), LF_REFFETTI);
|
|
for (int r = reff.first_row(); r > 0 && r <= reff.last_row(); r = reff.succ_row(r))
|
|
{
|
|
const TRectype& riga = reff[r];
|
|
|
|
TSEPA_record rata("SERIF00F");
|
|
rata.set("SERF01", PmtInfId);
|
|
rata.set("SERF02", instr_id);
|
|
rata.set("SERF03", (long)r);
|
|
TString doc_id;
|
|
doc_id << riga.get_date(REFF_DATAFATT).year() << '-' << riga.get(REFF_NFATT);
|
|
doc_id.strip_spaces();
|
|
rata.set("SERF07", doc_id);
|
|
rata.set("SERF08", riga.get_date(REFF_DATAFATT));
|
|
rata.set("SERF09", riga.get_real(REFF_IMPFATT));
|
|
rata.set("SERF11", riga.get_real(REFF_IMPORTO));
|
|
rata.set("SERF12", cmndt); // Codice mandato
|
|
rata.set("SERF13", dmndt); // Data mandato
|
|
|
|
rata.insert();
|
|
}
|
|
|
|
return imp;
|
|
}
|
|
|
|
bool TSEPA_app::genera_dist_RID(char td, long nd, TLog_report& log)
|
|
{
|
|
TDistinta dist(td, nd);
|
|
TAssoc_array subdist;
|
|
for (int i = 0; i < dist.items(); i++)
|
|
{
|
|
const TEffetto& eff = dist[i];
|
|
const TDate data = data_scadenza(eff);
|
|
TString8 key; key << data.date2ansi();
|
|
TArray* list = (TArray*)subdist.objptr(key);
|
|
if (list == NULL)
|
|
{
|
|
list = new TArray;
|
|
subdist.add(key, list);
|
|
}
|
|
list->add(eff);
|
|
}
|
|
|
|
if (subdist.empty())
|
|
return false;
|
|
|
|
// Identificativo univoco messaggio
|
|
TString msg_id; SEPA_MsgId(dist[0], msg_id);
|
|
|
|
TString8 msg_date, msg_time;
|
|
AS400_date_time(msg_date, msg_time);
|
|
|
|
// In AS400 non si gestiscono le sottodistinte, per cui creo una distinta per ogni sottodisitinta
|
|
FOR_EACH_ASSOC_OBJECT(subdist, hobj, key, itm)
|
|
{
|
|
const TArray& trans = objptr2array(itm);
|
|
|
|
TSEPA_record head("SERIT00F");
|
|
|
|
// Il codice univoco diventa MsgId + Id
|
|
TString PmtInfId; PmtInfId << msg_id << '-' << key;
|
|
log.log(0, PmtInfId);
|
|
|
|
head.set("SERT01", PmtInfId); // MsgId
|
|
|
|
// Nel file XML viene richiesta data/ora in formato ISO, qui invece ci sono due campi distinti à la AS400
|
|
head.set("SERT02", msg_date); // CreDtTm data
|
|
head.set("SERT021", msg_time); // CreDtTm ora
|
|
|
|
head.set("SERT03", long(trans.items())); // NbOfTxs
|
|
head.set("SERT04", ZERO); // totale
|
|
head.set("SERT05", _ditta.ragione_sociale()); // Nm
|
|
|
|
const TEffetto& e0 = dist[0];
|
|
TString16 codtab = e0.get(EFF_CODABIP); codtab << e0.get(EFF_CODCABP);
|
|
TString4 prog = e0.get(EFF_PROGBNP);
|
|
if (prog.full()) codtab << prog;
|
|
const TRectype& bnp = cache().get("BNP", codtab);
|
|
|
|
TString8 cuc = bnp.get("S5");
|
|
if (cuc.blank()) cuc = _cuc;
|
|
|
|
head.set("SERT06", cuc); // Id
|
|
head.set("SERT07", "CBI"); // Issr
|
|
|
|
head.set("SERT08", PmtInfId); // Progressivo
|
|
head.set("SERT09", "DD");
|
|
head.set("SERT10", "SEPA");
|
|
|
|
|
|
head.set("SERT11", "CORE"); // Codice strumento (CORE, COR1, B2B)
|
|
head.set("SERT12", "FRST"); // Tipo sequenza incasso
|
|
head.set("SERT13", "SUPP");
|
|
|
|
const TDate ReqdExctnDt = data_scadenza(e0);
|
|
head.set("SERT14", ReqdExctnDt); // Data richiesta dal mittente YYYY-MM-DD
|
|
|
|
head.set("SERT15", _ditta.ragione_sociale());
|
|
head.set("SERT16", "ADDR");
|
|
//head.set("SERT17", "Divisione");
|
|
//head.set("SERT18", "Sotto-divisione");
|
|
head.set("SERT19", _ditta.via_residenza());
|
|
head.set("SERT20", _ditta.civico_residenza());
|
|
head.set("SERT21", _ditta.CAP_residenza());
|
|
head.set("SERT22", _ditta.comune_residenza());
|
|
head.set("SERT23", _ditta.provincia_residenza());
|
|
head.set("SERT24", _ditta.stato_partita_IVA()); // Alpha-2 code
|
|
head.set("SERT25", _ditta.fisica() ? 1L : 0L);
|
|
|
|
head.set("SERT27", cuc); // Id
|
|
head.set("SERT28", "CBI"); // Issr
|
|
|
|
const TString& iban = bnp.get("S3");
|
|
TString msg;
|
|
if (iban.blank() || iban_check(iban, msg) != 0)
|
|
{
|
|
msg.insert(TR("IBAN errato: "));
|
|
log.log(2, msg);
|
|
}
|
|
|
|
head.set("SERT29", iban); // IBAN
|
|
head.set("SERT30", codtab.left(5));
|
|
|
|
head.set("SERT31", _ditta.ragione_sociale());
|
|
head.set("SERT32", "ADDR");
|
|
//head.set("SERT33", "Divisione");
|
|
//head.set("SERT34", "Sotto-divisione");
|
|
head.set("SERT35", _ditta.via_residenza());
|
|
head.set("SERT36", _ditta.civico_residenza());
|
|
head.set("SERT37", _ditta.CAP_residenza());
|
|
head.set("SERT38", _ditta.comune_residenza());
|
|
head.set("SERT39", _ditta.provincia_residenza());
|
|
head.set("SERT40", _ditta.stato_partita_IVA()); // Alpha-2 code
|
|
|
|
const TString& cid = bnp.get("S4");
|
|
if (cid.blank())
|
|
{
|
|
msg = TR("Creditor ID mancante sulla banca di presentazione");
|
|
log.log(2, msg);
|
|
}
|
|
head.set("SERT41", cid);
|
|
head.set("SERT42", "SEPA");
|
|
head.set("SERT43", "ADE");
|
|
head.set("SERT44", cid.left(2)); // Alpha-2 code
|
|
|
|
real totale;
|
|
FOR_EACH_ARRAY_ITEM(trans, r, peff)
|
|
{
|
|
const TEffetto& e = *(TEffetto*)peff;
|
|
totale += genera_RID(PmtInfId, e, log);
|
|
}
|
|
head.set("SERT04", totale);
|
|
|
|
head.insert();
|
|
}
|
|
completa(dist);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool TSEPA_app::genera_SEPA_RID(const TMask& msk, TLog_report& log)
|
|
{
|
|
xvt_sql_begin(_db);
|
|
|
|
TString query;
|
|
|
|
query = "DELETE FROM SERIT00F;";
|
|
xvt_sql_execute(_db, query, NULL, 0L);
|
|
|
|
query = "DELETE FROM SERID00F;";
|
|
xvt_sql_execute(_db, query, NULL, 0L);
|
|
|
|
query = "DELETE FROM SERIF00F;";
|
|
xvt_sql_execute(_db, query, NULL, 0L);
|
|
|
|
const TSheet_field& sht = msk.sfield(F_SHEET);
|
|
|
|
TRecnotype nd = 0;
|
|
FOR_EACH_SHEET_ROW(sht, r, row) if (row->get_char(0) == 'X')
|
|
{
|
|
char tipo = '\0'; row->get(1, tipo);
|
|
long numd = 0L; row->get(2, numd);
|
|
if (genera_dist_RID(tipo, numd, log))
|
|
nd++;
|
|
}
|
|
|
|
if (nd > 0)
|
|
xvt_sql_commit(_db);
|
|
else
|
|
xvt_sql_rollback(_db);
|
|
|
|
return nd > 0;
|
|
}
|
|
|
|
bool TSEPA_app::convert_apos(const TString& xml) const
|
|
{
|
|
TString line(1024);
|
|
char* buf = line.get_buffer();
|
|
|
|
TString_array text;
|
|
|
|
FILE* txt = NULL; fopen_s(&txt, xml, "r");
|
|
if (!txt)
|
|
return false;
|
|
|
|
bool converted = false;
|
|
while (!feof(txt))
|
|
{
|
|
fgets(buf, line.size(), txt);
|
|
for(char* a = buf; a;)
|
|
{
|
|
char* apos = strstr(a, "'");
|
|
if (apos)
|
|
{
|
|
memcpy(apos, "'", 6);
|
|
converted = true;
|
|
a = apos+6;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
text.add(line);
|
|
}
|
|
fclose(txt);
|
|
txt = NULL;
|
|
|
|
if (converted)
|
|
{
|
|
fopen_s(&txt, xml, "w");
|
|
if (txt)
|
|
{
|
|
FOR_EACH_ARRAY_ROW(text, i, row)
|
|
fputs(*row, txt);
|
|
fclose(txt);
|
|
}
|
|
}
|
|
|
|
return txt != NULL;
|
|
}
|
|
|
|
|
|
bool TSEPA_app::genera_xml(int tipo, bool tuttapost)
|
|
{
|
|
#define SEPABASE "SIAGGSE"
|
|
|
|
TFilename tmp = SEPABASE; tmp.add("ConnectionDefault");
|
|
if (!tmp.exist())
|
|
{
|
|
char buff[128] = { 0 };
|
|
time_t t = { 0 }; localtime(&t);
|
|
ctime_s(buff, sizeof(buff), &t);
|
|
|
|
ofstream o(tmp);
|
|
o << "#Connection Default Properties" << endl;
|
|
o << '#' << buff << endl;
|
|
}
|
|
if (tmp.exist())
|
|
{
|
|
TJava_profile prop(tmp);
|
|
TFilename dbu; dbu << "jdbc:sqlite:" << _dbname;
|
|
prop.set("database.type", "sqllite");
|
|
prop.set("database.url", dbu);
|
|
prop.set("classForName", "org.sqlite.JDBC");
|
|
if (tipo == 8)
|
|
{
|
|
prop.set("path.SEPA.RID", _drid);
|
|
prop.set("path.SEPA.RID.log", _drid);
|
|
}
|
|
else
|
|
{
|
|
prop.set("path.SEPA.BON", _dbon);
|
|
prop.set("path.SEPA.BON.log", _dbon);
|
|
}
|
|
}
|
|
|
|
if (tipo == 8)
|
|
tmp = SEPABASE"\\lancioSDDxx.bat";
|
|
else
|
|
tmp = SEPABASE"\\lancioSCTxx.bat";
|
|
|
|
tmp.make_absolute_path();
|
|
|
|
const time_t tStart = ::time(NULL);
|
|
|
|
DIRECTORY old_dir; xvt_fsys_get_dir(&old_dir);
|
|
DIRECTORY new_dir; xvt_fsys_convert_str_to_dir(tmp.path(), &new_dir);
|
|
xvt_fsys_set_dir(&new_dir);
|
|
|
|
TString8 str_firm; str_firm.format("%05d", prefix().get_codditta());
|
|
tmp << ' ' << str_firm;
|
|
TExternal_app app(tmp);
|
|
const bool good = app.run() == NOERR;
|
|
if (good)
|
|
xvt_sys_sleep(3000);
|
|
else
|
|
error_box(FR("Impossibile eseguire %s"), (const char*)tmp);
|
|
xvt_fsys_set_dir(&old_dir);
|
|
|
|
if (good && tuttapost)
|
|
{
|
|
TString_array xmls;
|
|
TFilename f = tipo == 8 ? _drid : _dbon; f.add("*.xml");
|
|
list_files(f, xmls);
|
|
FOR_EACH_ARRAY_ROW(xmls, r, xml)
|
|
{
|
|
const time_t tXml = xvt_fsys_file_attr(*xml, XVT_FILE_ATTR_MTIME);
|
|
if (tXml >= tStart)
|
|
convert_apos(*xml);
|
|
}
|
|
}
|
|
|
|
return good;
|
|
}
|
|
|
|
|
|
void TSEPA_app::main_loop()
|
|
{
|
|
TSEPA_mask m;
|
|
while (m.run() == K_ENTER)
|
|
{
|
|
const int tipo = m.get_int(F_TIPO);
|
|
const bool tuttapost = m.get_bool(F_APOS);
|
|
|
|
TLog_report log(tipo == 8 ? "RID SEPA" : "Bonifici SEPA");
|
|
|
|
if (_cuc.blank())
|
|
{
|
|
log.log(2, TR("E' necessario inserire il codice CUC nei parametri degli effetti"));
|
|
_cuc = "GEB00000";
|
|
}
|
|
|
|
if (tipo == 9)
|
|
genera_SEPA_BON(m, log);
|
|
else
|
|
genera_SEPA_RID(m, log);
|
|
genera_xml(tipo, tuttapost);
|
|
|
|
log.preview();
|
|
}
|
|
}
|
|
|
|
int ef1100(int argc, char* argv[])
|
|
{
|
|
TSEPA_app a;
|
|
a.run(argc, argv, TR("Bonifici/RID SEPA"));
|
|
return 0;
|
|
}
|
|
|
|
|
|
|