campo-sirio/pa/pa0100.cpp

672 lines
18 KiB
C++
Raw Normal View History

#include <applicat.h>
#include <dongle.h>
#include <progind.h>
#include <utility.h>
#include "../ve/velib05.h"
#include "pa0.h"
#include "../fe/felib.h"
#include <nditte.h>
/////////////////////////////////////////////////////////////////////////////////////
// Globals
/////////////////////////////////////////////////////////////////////////////////////
XVT_SQLDB _db = NULL; // PAF sqlite db
/////////////////////////////////////////////////////////////////////////////////////
// TPaf_record
/////////////////////////////////////////////////////////////////////////////////////
class TPaf_record : public TObject
{
TString8 _table;
TToken_string _key;
TAssoc_array _fields;
protected:
void copy(const TPaf_record& rec) { _table = rec._table; _key = rec._key; _fields = rec._fields; }
const TString& var2str(const TVariant& var) const;
public:
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 TPaf_record(*this); }
virtual bool ok() const { return _table.not_empty(); }
TPaf_record& operator=(const TPaf_record& rec) { copy(rec); return *this; }
TPaf_record(const TPaf_record& rec) { copy(rec); }
TPaf_record(const char* table);
};
void TPaf_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));
}
}
void TPaf_record::set(const char* fld, long val)
{
const TVariant var(val);
set(fld, var);
}
void TPaf_record::set(const char* fld, const char* val)
{
if (val == NULL)
set(fld, NULL_VARIANT);
else
{
const TVariant var(val);
set(fld, var);
}
}
void TPaf_record::set(const char* fld, const TString& val)
{
const TVariant var(val);
set(fld, var);
}
void TPaf_record::set(const char* fld, const real& val)
{
const char* str = val.string(0, 2);
set(fld, str);
}
void TPaf_record::set(const char* fld, const TDate& var)
{
const char* str = var.string(full, '-', full, full, amg_date);
set(fld, str);
}
void TPaf_record::set(const char* fld, bool var)
{
set(fld, var ? "SI" : "NO");
}
const TVariant& TPaf_record::get(const char* fld) const
{
const TVariant* var = (const TVariant*)_fields.objptr(fld);
return var ? *var : NULL_VARIANT;
}
const TString& TPaf_record::var2str(const TVariant& var) const
{
const TString& str = var.as_string();
bool apici = var.type() == _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;
}
bool TPaf_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(var) ;
}
}
CHECKS(nkf >= 2, "Can't remove partial key on table ", (const char*)_table);
query << ';';
return xvt_sql_execute(_db, query, NULL, 0L) > 0;
}
static int paf_search_record(void* jolly, int cols, char** names, char** values)
{
TPaf_record& rec = *(TPaf_record*)jolly;
for (int i = 0; i < cols; i++)
rec.set(names[i], values[i]);
return 0;
}
bool TPaf_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(var) << " AND ";
}
query.rtrim(5);
query << ';';
return xvt_sql_execute(_db, query, paf_search_record, this) == 1;
}
bool TPaf_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();
}
bool TPaf_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(var) << ',';
}
}
query.rtrim(1); values.rtrim(1);
query << ")\nVALUES (" << values << ");";
return xvt_sql_execute(_db, query, NULL, 0L) == 1;
}
TPaf_record::TPaf_record(const char* table) : _table(table), _key(15, ',')
{
_key = ini_get_string("./paf.ini", table, "INDEX_1");
if (_key.empty())
{
TConfig cfg("paf.ini", table);
TAssoc_array& fields = cfg.list_variables();
FOR_EACH_ASSOC_STRING(fields, obj, key, str)
{
if (key[2] == 'K')
_key.add(key);
}
}
CHECKS(_key.full(), "Invalid primary key for table ", table);
}
/////////////////////////////////////////////////////////////////////////////////////
// TDoc2Paf
/////////////////////////////////////////////////////////////////////////////////////
class TDoc2Paf : public TSkeleton_application
{
TAnagrafica _cessionario;
private:
int parse_line(const TString& line, TString& var, TString& val) const;
void create_table(TScanner& paf, const TString& table);
protected:
const TString& cessionario();
const TString& fattura(const TDocumento& doc);
void elabora(TDocumentoEsteso& doc);
void elabora(const TRectype& rec);
void elabora(const TDoc_key& key);
void elabora(const TFilename& ini);
public:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
};
const TString& TDoc2Paf::cessionario()
{
if (!_cessionario.ok())
_cessionario.init(LF_NDITTE, prefix().get_codditta());
const TString& piva = _cessionario.partita_IVA();
return piva.full() ? piva : _cessionario.codice_fiscale();
}
const TString& TDoc2Paf::fattura(const TDocumento& doc)
{
TString& key = get_tmp_string();
key << doc.get_date(DOC_DATADOC).date2ansi() << '/'
<< doc.numerazione() << '/' << doc.numero();
return key;
}
void TDoc2Paf::elabora(TDocumentoEsteso& doc)
{
const TFirm& firm = prefix().firm();
TString8 prginv; prginv.format("%05d", ini_get_int("./paf.ini", "Main", "PRGINV") + 1);
ini_set_string("./paf.ini", "Main", "PRGINV", prginv);
// <DatiTrassmissione>
TPaf_record paf0100f("PAF0100F");
paf0100f.set("P1KHFATT", cessionario());
paf0100f.set("P1KBFATT", fattura(doc));
paf0100f.remove();
paf0100f.set("P1PAESE", "IT");
paf0100f.set("P1CODICE", _cessionario.partita_IVA());
paf0100f.set("P1PRGINV", prginv);
paf0100f.set("P1FTRASM", "SDI10");
TString80 tel; tel << firm.get(NDT_PTEL) << firm.get(NDT_TEL);
paf0100f.set("P1TELEF", tel);
paf0100f.set("P1MAIL", firm.get(NDT_MAIL));
paf0100f.insert();
// </DatiTrassmissione>
// <CedentePrestatore>
TPaf_record paf0200f("PAF0200F");
paf0200f.set("P2KHFATT", paf0100f.get("P1KHFATT"));
paf0200f.set("P2KBFATT", paf0100f.get("P1KBFATT"));
paf0200f.remove();
paf0200f.set("P2PAESE", paf0100f.get("P1PAESE"));
paf0200f.set("P2CODICE", _cessionario.partita_IVA());
paf0200f.set("P2FISCA", _cessionario.codice_fiscale());
if (_cessionario.fisica())
{
paf0200f.set("P2NOME", _cessionario.nome());
paf0200f.set("P2COGN", _cessionario.cognome());
}
else
{
paf0200f.set("P2DENOM", _cessionario.ragione_sociale());
}
paf0200f.set("P2RFISC", "RF01");
// DatiSede
paf0200f.set("P2SINDI", _cessionario.indirizzo_residenza());
paf0200f.set("P2SCOMU", _cessionario.comune_residenza());
paf0200f.set("P2SPROV", _cessionario.provincia_residenza());
paf0200f.set("P2SNAZI", paf0100f.get("P1PAESE"));
// DatiStabile
paf0200f.set("P2OINDI", _cessionario.indirizzo_residenza());
paf0200f.set("P2OCOMU", _cessionario.comune_residenza());
paf0200f.set("P2OPROV", _cessionario.provincia_residenza());
paf0200f.set("P2ONAZI", paf0100f.get("P1PAESE"));
paf0200f.insert();
// </CedentePrestatore>
// <CessionarioCommittente>
TAnagrafica cliente('C', doc.get_long(DOC_CODCF));
TPaf_record paf0400f("PAF0400F");
paf0400f.set("P4KHFATT", paf0100f.get("P1KHFATT"));
paf0400f.set("P4KBFATT", paf0100f.get("P1KBFATT"));
paf0400f.remove();
paf0400f.set("P4PAESE", paf0100f.get("P1PAESE"));
paf0400f.set("P4CODICE", cliente.partita_IVA());
paf0400f.set("P4FISCA", cliente.codice_fiscale());
if (_cessionario.fisica())
{
paf0400f.set("P4NOME", cliente.nome());
paf0400f.set("P4COGN", cliente.cognome());
}
else
{
paf0400f.set("P4DENOM", cliente.ragione_sociale());
}
paf0400f.set("P4RFISC", "RF01");
// DatiSede
paf0400f.set("P4SINDI", cliente.indirizzo_residenza());
paf0400f.set("P4SCOMU", cliente.comune_residenza());
paf0400f.set("P4SPROV", cliente.provincia_residenza());
paf0400f.set("P4SNAZI", "IT");
paf0400f.insert();
// </CessionarioCommittente>
// <DatiGenerali>
TPaf_record paf0700f("PAF0700F");
paf0700f.set("P7KHFATT", paf0100f.get("P1KHFATT"));
paf0700f.set("P7KBFATT", paf0100f.get("P1KBFATT"));
paf0700f.set("P7TDOC", doc.tipo().codice());
paf0700f.set("P7DIVISA", "EUR"); // Aggiungere codice ISO 4217 a tabella divise (%VAL)
paf0700f.set("P7DATA", doc.data());
paf0700f.set("P7NUME", doc.numero());
paf0700f.insert();
TPaf_record paf2700f("PAF2700F");
paf2700f.set("PQKHFATT", paf0100f.get("P1KHFATT"));
paf2700f.set("PQKBFATT", paf0100f.get("P1KBFATT"));
paf2700f.set("PQITDOC", doc.totale_doc());
paf2700f.set("PQCAUS", doc.tipo().descrizione());
paf2700f.set("PQART73", true);
paf2700f.insert();
// </DatiGenerali>
// <DatiBeniServizi>
TPaf_record paf1800f("PAF1800F");
paf1800f.set("PIKHFATT", paf0100f.get("P1KHFATT"));
paf1800f.set("PIKBFATT", paf0100f.get("P1KBFATT"));
paf1800f.remove(); // Cancella tutte le righe documento
long pinlin = 1;
FOR_EACH_PHYSICAL_RDOC(doc, r, rdoc)
{
paf1800f.set("PINLIN", pinlin++);
paf1800f.set("PIDESC", rdoc->get(RDOC_DESCR));
if (rdoc->is_merce())
{
paf1800f.set("PIQTA", rdoc->quantita());
paf1800f.set("PIUNMIS", rdoc->get(RDOC_UMQTA));
paf1800f.set("PIPREZ", rdoc->prezzo(true, false));
paf1800f.set("PIPRZT", rdoc->importo(true, false));
const real aliquota = cache().get("%IVA", rdoc->get(RDOC_CODIVA), "R0");
paf1800f.set("PIAIVA", aliquota);
}
paf1800f.insert();
}
// </DatiBeniServizi>
// <DatiRiepilogo>
TPaf_record paf2200f("PAF2200F");
paf2200f.set("PLKHFATT", paf0100f.get("P1KHFATT"));
paf2200f.set("PLKBFATT", paf0100f.get("P1KBFATT"));
paf2200f.remove(); // Cancella tutte le righe di riepilogo IVA
TAssoc_array& tiva = doc.tabella_iva(false);
FOR_EACH_ASSOC_OBJECT(tiva, obj, key, itm)
{
const TRiepilogo_iva& riva = *(const TRiepilogo_iva*)itm;
const real aliquota = riva.cod_iva().percentuale();
paf2200f.set("PLALIVA", aliquota);
paf2200f.set("PLIMPO", riva.imponibile());
paf2200f.set("PLIMPS", riva.imposta());
const char* eiva = doc.get_bool(DOC_LIQDIFF) || doc.get_bool(DOC_IVAXCASSA) ? "E" : "I";
paf2200f.set("PLEIVA", eiva);
paf2200f.insert();
}
// </DatiRiepilogo>
}
void TDoc2Paf::elabora(const TRectype& rec)
{
TDocumentoEsteso doc(rec);
elabora(doc);
}
void TDoc2Paf::elabora(const TDoc_key& key)
{
TRectype rec(LF_DOC);
rec.put(DOC_PROVV, key.provv());
rec.put(DOC_ANNO, key.anno());
rec.put(DOC_CODNUM, key.codnum());
rec.put(DOC_NDOC, key.ndoc());
elabora(rec);
}
void TDoc2Paf::elabora(const TFilename& ini)
{
TConfig cfg(ini, "33");
const int anno = cfg.get_int(DOC_ANNO);
const long ndoc = cfg.get_long(DOC_NDOC);
const TFixed_string codnum(cfg.get(DOC_CODNUM)); // lascio sapientemente per ultima la get di una stringa
const TDoc_key key(anno, codnum, ndoc);
elabora(key);
}
void TDoc2Paf::main_loop()
{
bool is_batch = false;
for (int a = 1; a < argc(); a++)
{
TFilename ini = argv(a);
if (ini.starts_with("-i", true) || ini.starts_with("/i", true))
ini.ltrim(2);
if (ini.exist())
{
is_batch = true;
elabora(ini);
}
else
{
if (ini.find('*') >= 0 || ini.find('?') >= 0)
{
TString_array f; list_files(ini, f);
FOR_EACH_ARRAY_ROW(f, r, row)
{
ini = *row;
if (ini.exist())
{
is_batch = true;
elabora(ini);
}
}
}
}
}
if (!is_batch)
{
const char* title = TR("Fatture Pubblica Amministrazione");
TArray_sheet sht(-1, 3, 78, -3,
title, HR("@1|Anno|Cod.|Numero|Cliente|Ragione Sociale@50"));
TISAM_recordset clifo_pa("USE 20 SELECT ALLEG=7\nTO TIPOCF=C");
const TRecnotype n = clifo_pa.items();
if (n > 0)
{
TProgress_monitor pi(n, title);
for (bool okc = clifo_pa.move_first(); okc; okc = clifo_pa.move_next())
{
if (!pi.addstatus(1))
break;
TISAM_recordset doc_pa("USE 33 KEY 2\nSELECT BETWEEN(STATO,2,5)\nFROM TIPOCF=C CODCF=#CLIENTE\nTO TIPOCF=C CODCF=#CLIENTE");
doc_pa.set_var("#CLIENTE", clifo_pa.get(CLI_CODCF));
for (bool okd = doc_pa.move_first(); okd; okd = doc_pa.move_next())
{
const TTipo_documento& td = cached_tipodoc(doc_pa.get(DOC_TIPODOC).as_string());
if (!td.is_fattura())
continue;
TToken_string* row = new TToken_string;
row->add(doc_pa.get(DOC_ANNO).as_int(), 1);
row->add(doc_pa.get(DOC_CODNUM).as_string());
row->add(doc_pa.get(DOC_NDOC).as_int());
const long codcf = doc_pa.get(DOC_CODCF).as_int();
row->add(codcf);
TString8 key; key.format("C|%ld", codcf);
row->add(cache().get(LF_CLIFO, key, CLI_RAGSOC));
sht.add(row);
}
}
}
while (sht.run() == K_ENTER)
{
FOR_EACH_CHECKED_ROW(sht, r, riga)
{
const int anno = riga->get_int(1);
const long ndoc = riga->get_long(3);
const TFixed_string codnum(riga->get(2)); // lascio sapientemente per ultima la get di una stringa
const TDoc_key key(anno, codnum, ndoc);
elabora(key);
}
}
}
}
int TDoc2Paf::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;
}
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;
}
void TDoc2Paf::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 (n == 1) // paragraph!
{
paf.push(line);
break;
}
if (var.starts_with("INDEX_"))
continue;
if (xvt_slist_find_str(fields, var) == NULL)
{
query.cut(0) << "ALTER TABLE " << table << " ADD COLUMN " << var << ' ' << val << ';';
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
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 << ',';
}
}
}
}
bool TDoc2Paf::create()
{
TFilename n = prefix().get_studio(); // base direcotry
n.add("sql"); n.add("paf.db");
_db = xvt_sql_open(n, user(), "", n.path());
if (_db == NULL)
return false;
n = "paf.ini";
if (n.exist())
{
TScanner paf(n);
while (!paf.eof())
{
const TString& p = paf.line();
if (p.starts_with("[PAF"))
{
const TString8 table = p.mid(1, 8);
create_table(paf, table);
}
}
}
else
return cantread_box(n);
return TSkeleton_application::create();
}
bool TDoc2Paf::destroy()
{
xvt_sql_close(_db); _db = NULL;
return TSkeleton_application::destroy();
}
int pa0100(int argc, char* argv[])
{
TDoc2Paf d2p;
d2p.run(argc, argv, TR("Fatturazione P.A."));
return 0;
}