git-svn-id: svn://10.65.10.50/branches/R_10_00@23149 c028cbd2-c16b-5b4b-a496-9718f37d4682
1182 lines
33 KiB
C++
1182 lines
33 KiB
C++
#include <applicat.h>
|
||
#include <assoc.h>
|
||
#include <automask.h>
|
||
#include <config.h>
|
||
#include <ODBCrset.h>
|
||
#include <progind.h>
|
||
#include <reputils.h>
|
||
#include <utility.h>
|
||
|
||
#include "../mg/mglib.h"
|
||
#include "../cg/cglib01.h"
|
||
|
||
#include "bs0.h"
|
||
|
||
#include "../fe/felib.h"
|
||
#include "../ve/condv.h"
|
||
#include "../ve/rcondv.h"
|
||
|
||
#include <comuni.h>
|
||
#include <clifo.h>
|
||
#include <cfven.h>
|
||
|
||
#define BS_DTULTAGG "DtUltAgg"
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TBeeStore_cache
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TBeeStore_cache : TCache
|
||
{
|
||
protected:
|
||
virtual TObject* key2obj(const char* key)
|
||
{
|
||
const char tipo = *key;
|
||
const long codice = atol(key+1);
|
||
return new TAnagrafica(LF_CLIFO, tipo, codice);
|
||
}
|
||
|
||
public:
|
||
const TAnagrafica& anag(char tipo, long codice)
|
||
{
|
||
CHECKD((tipo == 'C' || tipo == 'F') && codice > 0L, "Codice cli/for non valido", codice);
|
||
TString8 key; key.format("%c%06ld", tipo, codice);
|
||
const TAnagrafica* a = (const TAnagrafica*)objptr(key);
|
||
return *a;
|
||
}
|
||
const TAnagrafica& anag(const TRectype& rec)
|
||
{
|
||
const char tipo = rec.get_char(CLI_TIPOCF);
|
||
const long codice = rec.get_long(CLI_CODCF);
|
||
return anag(tipo, codice);
|
||
}
|
||
const TAnagrafica& anag(const TISAM_recordset& rec)
|
||
{ return anag(rec.cursor()->curr()); }
|
||
};
|
||
|
||
static TBeeStore_cache _anagr;
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TBeeStore_mask
|
||
///////////////////////////////////////////////////////////
|
||
|
||
class TBeeStore_mask : public TAutomask
|
||
{
|
||
protected:
|
||
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
|
||
|
||
public:
|
||
void autoload();
|
||
void autosave() const;
|
||
|
||
bool get_bool(const char* fld)
|
||
{ TMask_field* f = find_by_fieldname(fld); return f ? f->get().full() : false; }
|
||
|
||
TDate get_date(const char* fld)
|
||
{ TMask_field* f = find_by_fieldname(fld); return TDate(f ? f->get() : EMPTY_STRING); }
|
||
|
||
TBeeStore_mask() : TAutomask("bs0200a") { autoload(); }
|
||
~TBeeStore_mask() { autosave(); }
|
||
};
|
||
|
||
bool TBeeStore_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
|
||
{ return true; }
|
||
|
||
void TBeeStore_mask::autoload()
|
||
{
|
||
// Carica i valori default dei parametri dal [bs] in ditta,ini
|
||
FOR_EACH_MASK_FIELD(*this, i, f)
|
||
{
|
||
const TFieldref* fr = f->field();
|
||
if (fr != NULL)
|
||
f->set(ini_get_string(CONFIG_DITTA, "bs", fr->name()));
|
||
}
|
||
}
|
||
|
||
void TBeeStore_mask::autosave() const
|
||
{
|
||
// Salva i valori dei parametri in [bs] in ditta,ini
|
||
FOR_EACH_MASK_FIELD(*this, i, f)
|
||
{
|
||
const TFieldref* fr = f->field();
|
||
if (fr != NULL)
|
||
ini_set_string(CONFIG_DITTA, "bs", fr->name(), f->get());
|
||
}
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TBeeStore_sync
|
||
///////////////////////////////////////////////////////////
|
||
|
||
typedef bool TFieldEvaluator(const TISAM_recordset& rec, const char* fldname, const char* expr, TVariant& var);
|
||
|
||
class TBeeStore_sync : public TSkeleton_application
|
||
{
|
||
TString16 _dsn;
|
||
TFilename _sqlog;
|
||
TLog_report* _log;
|
||
|
||
private:
|
||
const TString& comune(const TRecordset& recset, const char* fld_cap, const char* fld_den) const;
|
||
bool split_phone(const TRecordset& odbc, const char* number, TIsamfile& clifo, const char* pre, const char* num) const;
|
||
void load_clifo(char tipocf);
|
||
void save_clifo(const TDate& dal, const TDate& al);
|
||
|
||
protected:
|
||
bool save_and_delete_doc(TMov_mag*& doc) const;
|
||
|
||
void load_origine_1(TISAM_recordset& out_set, const char* in_table, const TString_array& pairs);
|
||
void save_origine_2(TISAM_recordset& in_set, const char* out_table, const TString_array& pairs, TFieldEvaluator* feval = NULL);
|
||
|
||
void sync_table(TISAM_recordset& in_set, const char* out_table,
|
||
const TString_array& pairs);
|
||
void sync_table(const char* in_table, const char* out_table,
|
||
const TString_array& fields, const TDate& dal, const TDate& al);
|
||
void sync_table(const int logicnum, const char* out_table,
|
||
const TString_array& fields, const TDate& dal, const TDate& al);
|
||
|
||
void sync_iva (const TDate& dal, const TDate& al);
|
||
void sync_ums (const TDate& dal, const TDate& al);
|
||
void sync_lines (const TDate& dal, const TDate& al);
|
||
void sync_catmer (const TDate& dal, const TDate& al);
|
||
void sync_val (const TDate& dal, const TDate& al);
|
||
void sync_anamag (const TDate& dal, const TDate& al);
|
||
void sync_barcode (const TDate& dal, const TDate& al);
|
||
void sync_scontrini(const TDate& dal, const TDate& al);
|
||
void sync_clifo (const TDate& dal, const TDate& al);
|
||
void sync_listino (const TString& listino);
|
||
|
||
public:
|
||
virtual bool create();
|
||
virtual void main_loop();
|
||
};
|
||
|
||
// Converte una TDate in una data SQL
|
||
const TString& date2sql(const TDate& d)
|
||
{
|
||
TString& tmp = get_tmp_string();
|
||
if (d.ok())
|
||
tmp.format("'%02d-%02d-%04d'", d.day(), d.month(), d.year());
|
||
else
|
||
tmp = "NULL";
|
||
return tmp;
|
||
}
|
||
|
||
// Coverte un qualsiasi TVariant in stringa SQL
|
||
const TString& var2sql(const TVariant& var)
|
||
{
|
||
TString& tmp = get_tmp_string();
|
||
switch (var.type())
|
||
{
|
||
case _nullfld:
|
||
tmp = "NULL";
|
||
break;
|
||
case _boolfld:
|
||
tmp = var.as_bool() ? "1" : "0";
|
||
break;
|
||
case _datefld:
|
||
tmp = date2sql(var.as_date());
|
||
break;
|
||
case _intfld:
|
||
case _longfld:
|
||
var.as_string(tmp);
|
||
break;
|
||
case _realfld:
|
||
if (var.is_empty())
|
||
tmp = "0";
|
||
else
|
||
{
|
||
tmp = var.as_real().string(0, 2);
|
||
if (tmp.ends_with(".00"))
|
||
tmp.rtrim(3);
|
||
}
|
||
break;
|
||
default:
|
||
{
|
||
var.as_string(tmp);
|
||
const int pos = tmp.find('\'');
|
||
if (pos >= 0)
|
||
{
|
||
for (int i = tmp.len()-1; i >= pos; i--)
|
||
if (tmp[i] == '\'') tmp.insert("'", i);
|
||
}
|
||
tmp.insert("'");
|
||
tmp << "'";
|
||
}
|
||
break;
|
||
}
|
||
return tmp;
|
||
}
|
||
|
||
// Coverte una qualsiasi espressione in stringa SQL
|
||
const TString& expr2sql(const TISAM_recordset& set, const char* expr)
|
||
{
|
||
TVariant var;
|
||
TExpression e(expr, _strexpr, true);
|
||
if (e.numvar() == 0)
|
||
{
|
||
if (real::is_natural(expr))
|
||
var = atoi(expr);
|
||
else
|
||
var = expr;
|
||
} else
|
||
if (e.numvar() == 1 && xvt_str_same(e.varname(0), expr))
|
||
{
|
||
var = set.get(expr);
|
||
}
|
||
else
|
||
{
|
||
for (int v = e.numvar()-1; v >= 0; v--)
|
||
{
|
||
var = set.get(e.varname(v));
|
||
if (var.is_real() || var.is_bool())
|
||
e.setvar(v, var.as_real());
|
||
else
|
||
e.setvar(v, var.as_string());
|
||
}
|
||
var = e.as_string();
|
||
}
|
||
return var2sql(var);
|
||
}
|
||
|
||
// Carica da BeeStore i record con Origine=1, cio<69> generati da lui ed eventualmente aggiorna i corrispondenti in Campo
|
||
void TBeeStore_sync::load_origine_1(TISAM_recordset& out_set, const char* in_table, const TString_array& pairs)
|
||
{
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\nSELECT ";
|
||
FOR_EACH_ARRAY_ROW(pairs, f, row)
|
||
str << row->get(0) << ',';
|
||
str.rtrim(1); // toglie ultima virgola
|
||
str << "\nFROM " << in_table << " WHERE (Origine=1);";
|
||
|
||
TODBC_recordset odbc(str);
|
||
const TRecnotype n = odbc.items();
|
||
if (n > 0)
|
||
{
|
||
TLocalisamfile& file = out_set.cursor()->file();
|
||
const RecDes& rd = file.curr().rec_des();
|
||
TToken_string key_fields;
|
||
for (int i = 0; i < rd.Ky->NkFields; i++)
|
||
{
|
||
const int nf = rd.Ky[0].FieldSeq[i] % MaxFields;
|
||
key_fields.add(rd.Fd[nf].Name);
|
||
}
|
||
|
||
str.format(TR("Importazione %ld record dalla tabella %s"), n, in_table);
|
||
_log->log(0, "");
|
||
_log->log(0, str);
|
||
|
||
TProgress_monitor pi(n, str);
|
||
for (bool ok = odbc.move_first(); ok; ok = odbc.move_next())
|
||
{
|
||
file.zero();
|
||
TString80 cfld, bfld; // Campo field e BeeStore field
|
||
FOR_EACH_ARRAY_ROW(pairs, p, row)
|
||
{
|
||
bfld = row->get(0);
|
||
cfld = row->get();
|
||
const int pos = key_fields.get_pos(cfld);
|
||
if (pos >= 0)
|
||
{
|
||
const TVariant& var = odbc.get(bfld);
|
||
if (!var.is_null())
|
||
file.put(cfld, var.as_string());
|
||
if (pos == key_fields.items()-1)
|
||
break;
|
||
}
|
||
}
|
||
|
||
int err = file.read(_isequal, _lock);
|
||
if (err == NOERR)
|
||
{
|
||
bool dirty = false;
|
||
const TDate dataagg = file.get(CLI_DATAAGG);
|
||
TDate dtultagg = odbc.get(BS_DTULTAGG).as_date();
|
||
if (!dtultagg.ok()) dtultagg = TODAY;
|
||
|
||
str = "record";
|
||
FOR_EACH_TOKEN(key_fields, f)
|
||
str << ' ' << file.get(f);
|
||
|
||
if (dtultagg >= dataagg)
|
||
{
|
||
FOR_EACH_ARRAY_ROW(pairs, r,row)
|
||
{
|
||
bfld = row->get(0);
|
||
cfld = row->get();
|
||
if (cfld[0] >= 'A' && cfld.find("->") < 0 && key_fields.get_pos(cfld) < 0) // Aggiorno solo i campi NON chiave
|
||
{
|
||
const TString& vec = file.get(cfld);
|
||
const TString& nov = odbc.get(bfld).as_string();
|
||
if (nov != vec)
|
||
{
|
||
if (!dirty)
|
||
str << ' ' << bfld << "='" << nov << '\'';
|
||
file.put(cfld, nov);
|
||
dirty = true;
|
||
}
|
||
}
|
||
}
|
||
if (dirty)
|
||
{
|
||
TRectype& rec = file.curr();
|
||
if (rec.exist(CLI_UTENTE))
|
||
rec.put(CLI_UTENTE, "BEESTORE");
|
||
if (rec.exist(CLI_DATAAGG))
|
||
rec.put(CLI_DATAAGG, dtultagg);
|
||
}
|
||
else
|
||
str << " Nessuna variazione pertinente";
|
||
}
|
||
else
|
||
str << " Data di ultimo aggiornamento obsoleta";
|
||
if (dirty)
|
||
{
|
||
if (file.rewrite() == 0)
|
||
_log->log(1, str);
|
||
else
|
||
{
|
||
TString80 err; err << TR("ERRORE ") << err << TR(" aggiornando il ");
|
||
str.insert(err);
|
||
_log->log(2, str);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_log->log(0, str);
|
||
file.reread(_unlock);
|
||
}
|
||
} else
|
||
if (err == _iskeynotfound)
|
||
{
|
||
file.zero();
|
||
FOR_EACH_ARRAY_ROW(pairs, r,row)
|
||
{
|
||
bfld = row->get(0);
|
||
cfld = row->get();
|
||
if (cfld[0] >= 'A' && cfld.find("->"))
|
||
{
|
||
const TString& nov = odbc.get(bfld).as_string();
|
||
file.put(cfld, nov);
|
||
}
|
||
}
|
||
if (file.write() == 0)
|
||
_log->log(1, str);
|
||
else
|
||
{
|
||
TString80 msg; msg << TR("ERRORE ") << err << TR(" inserendo il ");
|
||
str.insert(msg);
|
||
_log->log(2, str);
|
||
}
|
||
}
|
||
}
|
||
|
||
str.cut(0) << "DELETE FROM " << in_table << " WHERE Origine=1;";
|
||
odbc.exec(str);
|
||
}
|
||
}
|
||
|
||
void TBeeStore_sync::save_origine_2(TISAM_recordset& in_set, const char* out_table, const TString_array& fields, TFieldEvaluator* fval)
|
||
{
|
||
const TRecnotype n = in_set.items();
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\n";
|
||
TODBC_recordset odbc(str);
|
||
|
||
str.cut(0) << "DELETE FROM " << out_table << " WHERE Origine=2;";
|
||
odbc.exec(str);
|
||
|
||
str.format(TR("Esportazione %ld record in %s"), n, out_table);
|
||
_log->log(0, "");
|
||
_log->log(0, str);
|
||
|
||
const TRectype& curr = in_set.cursor()->curr();
|
||
|
||
TProgress_monitor pi(n, str);
|
||
for (bool ok = in_set.move_first(); ok; ok = in_set.move_next())
|
||
{
|
||
|
||
str.cut(0) << "INSERT INTO " << out_table << "\n(";
|
||
FOR_EACH_ARRAY_ROW(fields, sr, srow)
|
||
str << (sr ? ", " : "") << srow->get(0);
|
||
str << ", Origine, Errore, "BS_DTULTAGG;
|
||
str << ")\nVALUES (";
|
||
|
||
FOR_EACH_ARRAY_ROW(fields, ir, irow)
|
||
{
|
||
if (ir) str << ", ";
|
||
if (fval)
|
||
{
|
||
const char* fname = irow->get(0); // BeeStore field name
|
||
const char* fexpr = irow->get(); // Campo expression
|
||
TVariant var;
|
||
if (fval(in_set, fname, fexpr, var))
|
||
{
|
||
str << var2sql(var);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
const TFixed_string cfld = irow->get(1);
|
||
if (cfld.find("SCONTO")>=0)
|
||
{
|
||
real sconto;
|
||
const TString& exp = curr.get(cfld);
|
||
if (exp.full())
|
||
{
|
||
if (real::is_natural(exp))
|
||
sconto = real(exp);
|
||
else
|
||
{
|
||
TString80 goodexp; real val_perc;
|
||
if (scontoexpr2perc(exp, false, goodexp, val_perc) && val_perc != UNO)
|
||
{
|
||
sconto = CENTO - CENTO*val_perc;
|
||
sconto.round(5);
|
||
}
|
||
}
|
||
}
|
||
str << var2sql(sconto);
|
||
} else
|
||
if ((cfld[0] >= 'A' && cfld[0] <= 'Z') || cfld.find("->") > 0)
|
||
str << expr2sql(in_set, cfld);
|
||
else
|
||
str << cfld;
|
||
}
|
||
|
||
str << ", 2, 0, GETDATE()";
|
||
str << ");";
|
||
|
||
const long err = odbc.exec(str);
|
||
if (err <= 0)
|
||
{
|
||
TParagraph_string par(str, 75);
|
||
if (par.items() > 4)
|
||
{
|
||
str.cut(0);
|
||
bool values = false;
|
||
FOR_EACH_TOKEN(par, s)
|
||
{
|
||
if (str.full() && !values)
|
||
{
|
||
values = _strnicmp(s, "VALUES", 6) == 0;
|
||
if (!values)
|
||
continue;
|
||
}
|
||
str << s << '\n';
|
||
}
|
||
str.trim();
|
||
}
|
||
_log->log(1, str);
|
||
str.format("SQL error %d", abs(err));
|
||
_log->log(2, str);
|
||
}
|
||
|
||
if (!pi.add_status())
|
||
break;
|
||
}
|
||
|
||
odbc.exec("COMMIT;");
|
||
}
|
||
|
||
void TBeeStore_sync::sync_table(TISAM_recordset& in_set, const char* out_table, const TString_array& fields)
|
||
{
|
||
load_origine_1(in_set, out_table, fields);
|
||
save_origine_2(in_set, out_table, fields);
|
||
}
|
||
|
||
static TString& build_query(const char* table, const TDate& dal, const TDate& al)
|
||
{
|
||
TString& q = get_tmp_string();
|
||
q << "USE " << table;
|
||
if (dal.ok() || al.ok())
|
||
q << "SELECT BETWEEN(DATAAGG," << dal.date2ansi() << ',' << al.date2ansi() << ")";
|
||
return q;
|
||
}
|
||
|
||
static TString& build_query(const int logicnum, const TDate& dal, const TDate& al)
|
||
{
|
||
const TRectype rec(logicnum);
|
||
TString& q = get_tmp_string();
|
||
q << "USE " << logicnum;
|
||
|
||
if (rec.exist(CLI_UTENTE))
|
||
q << " SELECT (UTENTE!=\"BEESTORE\")";
|
||
|
||
if ((dal.ok() || al.ok()) && rec.exist(CLI_DATAAGG))
|
||
{
|
||
if (q.find(" SELECT ") < 0)
|
||
q << " SELECT ";
|
||
else
|
||
q << "&&";
|
||
q << "(BETWEEN(DATAAGG," << dal.date2ansi() << ',' << al.date2ansi() << "))";
|
||
}
|
||
return q;
|
||
}
|
||
|
||
|
||
void TBeeStore_sync::sync_table(const char* table, const char* out_table,
|
||
const TString_array& fields, const TDate& dal, const TDate& al)
|
||
{
|
||
const TString& q = build_query(table, dal, al);
|
||
TISAM_recordset set(q);
|
||
sync_table(set, out_table, fields);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_table(const int logicnum, const char* out_table,
|
||
const TString_array& fields, const TDate& dal, const TDate& al)
|
||
{
|
||
const TString& q = build_query(logicnum, dal, al);
|
||
TISAM_recordset set(q);
|
||
sync_table(set, out_table, fields);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_ums(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodUntMis|CODTAB");
|
||
fields.add("DSUntMis|S0");
|
||
sync_table("%UMS", "tieUntMisura", fields, dal, al);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_iva(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodIva|CODTAB");
|
||
fields.add("CodIvaSt|CODTAB");
|
||
fields.add("DSIva|S0");
|
||
fields.add("Aliquota|R0");
|
||
|
||
sync_table("%IVA", "tieIva", fields, dal, al);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_lines(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodLinea|CODTAB");
|
||
fields.add("DSLinea|S0");
|
||
|
||
TString query = build_query("GMC", dal, al);
|
||
if (query.find("SELECT") < 0)
|
||
query << " SELECT ";
|
||
else
|
||
query << "&&";
|
||
query << "(CODTAB?='???')";
|
||
|
||
TISAM_recordset lin(query);
|
||
sync_table(lin, "tieLineeArt", fields);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_catmer(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodCategoriaMerceologica|CODTAB");
|
||
fields.add("DSCategoriaMerceologica|S0");
|
||
fields.add("CodTipoEtichetta|''");
|
||
|
||
sync_table("GMC", "tieCategorieMerceologiche", fields, dal, al);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_anamag(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodPadre|"ANAMAG_CODART);
|
||
fields.add("DSArticolo|"ANAMAG_DESCR);
|
||
fields.add("DSArticoloAgg|"ANAMAG_DESCRAGG"[1,70]");
|
||
fields.add("CodUntMagazzino|49->UM");
|
||
fields.add("CodIva|"ANAMAG_CODIVA);
|
||
fields.add("CodLinea|"ANAMAG_GRMERC"[1,3]");
|
||
fields.add("CodCategMerceologica|"ANAMAG_GRMERC);
|
||
fields.add("Bloccato|"ANAMAG_SOSPESO);
|
||
|
||
TString query = build_query(LF_ANAMAG, dal, al);
|
||
query << "\nJOIN " << LF_UMART << " INTO CODART==CODART";
|
||
|
||
TISAM_recordset art(query);
|
||
sync_table(art, "tieArticoli", fields);
|
||
|
||
fields.destroy();
|
||
fields.add("CodArticolo|"ANAMAG_CODART);
|
||
fields.add("CodPadre|"ANAMAG_CODART);
|
||
save_origine_2(art, "tieArtVarianti", fields);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_barcode(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodArticolo|"ANAMAG_CODART);
|
||
fields.add("BarCode|"ANAMAG_DESCR);
|
||
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\nSELECT ";
|
||
FOR_EACH_ARRAY_ROW(fields, f, row)
|
||
str << row->get(0) << ',';
|
||
str.rtrim(1); // toglie ultima virgola
|
||
str << "\nFROM tieArtBarCode WHERE (Origine=1);";
|
||
|
||
TODBC_recordset odbc(str);
|
||
const TRecnotype n = odbc.items();
|
||
if (n > 0)
|
||
{
|
||
TProgress_monitor pi(n, "Importazione codici a barre");
|
||
for (bool go = odbc.move_first(); go; go = odbc.move_next())
|
||
{
|
||
const TCodice_articolo ca = odbc.get("CodArticolo").as_string();
|
||
const TCodice_articolo bc = odbc.get("BarCode").as_string();
|
||
int tipo = 0;
|
||
switch (bc.len())
|
||
{
|
||
case 8: tipo = 8; break;
|
||
case 13: tipo = 1; break;
|
||
default: break;
|
||
}
|
||
if (tipo)
|
||
{
|
||
TRecord_array codcor(ca, LF_CODCORR);
|
||
int n = 0;
|
||
for (n = codcor.last_row(); n > 0; n = codcor.pred_row(n))
|
||
{
|
||
const TRectype& row = codcor.row(n);
|
||
if (row.get("CODARTALT") == bc && row.get_int("TIPO") == tipo)
|
||
break; // trovato!
|
||
}
|
||
if (n <= 0)
|
||
{
|
||
TRectype& row = codcor.row(-1, true); // Add new row
|
||
row.put("CODARTALT", bc);
|
||
row.put("TIPO", tipo);
|
||
codcor.rewrite();
|
||
}
|
||
}
|
||
if (!pi.add_status())
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
static bool ClifoEvaluator(const TISAM_recordset& rec, const char* fldname, const char* expr, TVariant& var)
|
||
{
|
||
const TAnagrafica& a = _anagr.anag(rec);
|
||
|
||
if (xvt_str_same(fldname, "Cod_PK"))
|
||
{
|
||
TLocalisamfile& cfv = rec.cursor()->file(LF_CFVEN);
|
||
TString80 codprcf = cfv.get(CFV_CODPRCF);
|
||
if (codprcf.blank() || codprcf[0] == 'C') // Anagrafica gestita da Campo
|
||
{
|
||
const char t = cfv.get_char(CLI_TIPOCF);
|
||
const long c = cfv.get_long(CLI_CODCF);
|
||
TString8 cod_pk; cod_pk.format("C%06ld%c", c, t);
|
||
if (cod_pk != codprcf)
|
||
{
|
||
cfv.put(CFV_CODPRCF, codprcf = cod_pk);
|
||
cfv.rewrite();
|
||
}
|
||
}
|
||
var = codprcf;
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Cognome"))
|
||
{
|
||
if (a.fisica())
|
||
var = a.cognome();
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Nome"))
|
||
{
|
||
if (a.fisica())
|
||
var = a.nome();
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Indirizzo"))
|
||
{
|
||
TString ind;
|
||
ind << a.via_residenza() << ',' << a.civico_residenza();
|
||
const TString& loc = a.localita_residenza();
|
||
if (loc.full()) ind << ',' << loc;
|
||
ind.strip_double_spaces();
|
||
var = ind;
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Citta"))
|
||
{
|
||
var = a.comune_residenza();
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Provincia"))
|
||
{
|
||
var = a.provincia_residenza();
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "ComuneNascita"))
|
||
{
|
||
var = a.comune_nascita();
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "PVNascita"))
|
||
{
|
||
var = a.provincia_nascita();
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Telefono") || xvt_str_same(fldname, "Cellulare") || xvt_str_same(fldname, "CellulareSMS"))
|
||
{
|
||
const char* suff = (*fldname == 'C') ? (strlen(fldname)>9 ? "3" : "2") : "";
|
||
TString8 pref; pref << "PTEL" << suff;
|
||
TString80 tele; tele << "TEL" << suff;
|
||
TString80 str; rec.get(pref).as_string(str); str << ' ' << rec.get(tele).as_string();
|
||
str.strip_double_spaces();
|
||
char* s = str.get_buffer();
|
||
for (const char* f = s; *f; f++)
|
||
{
|
||
if (*f == ' ' || (*f >= '0' && *f <= '9'))
|
||
{
|
||
if (f > s) *s = *f;
|
||
s++;
|
||
}
|
||
}
|
||
*s = '\0';
|
||
}
|
||
|
||
if (xvt_str_same(fldname, "Tipo"))
|
||
{
|
||
var = a.fisica() ? 1 : 2;
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Cliente"))
|
||
{
|
||
const char tipocf = rec.get(CLI_TIPOCF).as_string()[0];
|
||
var = tipocf == 'C';
|
||
return true;
|
||
}
|
||
if (xvt_str_same(fldname, "Fornitore"))
|
||
{
|
||
const char tipocf = rec.get(CLI_TIPOCF).as_string()[0];
|
||
var = tipocf == 'F';
|
||
return true;
|
||
}
|
||
if (_strnicmp(fldname,"Cli_",4) == 0)
|
||
{
|
||
const char tipocf = rec.get(CLI_TIPOCF).as_string()[0];
|
||
return tipocf != 'C';
|
||
}
|
||
if (_strnicmp(fldname,"For_",4) == 0)
|
||
{
|
||
const char tipocf = rec.get(CLI_TIPOCF).as_string()[0];
|
||
return tipocf != 'F';
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
const TString& TBeeStore_sync::comune(const TRecordset& recset, const char* fld_cap, const char* fld_den) const
|
||
{
|
||
TString8 cap; if (fld_cap && *fld_cap) cap = recset.get(fld_cap).as_string().left(5);
|
||
TString80 den; if (fld_den && *fld_den) den = recset.get(fld_den).as_string();
|
||
return ::cap2comune(cap, den);
|
||
}
|
||
|
||
bool TBeeStore_sync::split_phone(const TRecordset& odbc, const char* number, TIsamfile& clifo, const char* pre, const char* num) const
|
||
{
|
||
TString pn = odbc.get(number).as_string();
|
||
if (pn.full())
|
||
{
|
||
pn.strip_double_spaces();
|
||
const int maxpref = clifo.curr().length(pre);
|
||
int split = -1;
|
||
for (int i = 0; pn[i] && i <= maxpref; i++)
|
||
{
|
||
if (!isdigit(pn[i]))
|
||
{
|
||
split = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (split > 1)
|
||
{
|
||
clifo.put(pre, pn.left(split));
|
||
clifo.put(num, pn.mid(split+1));
|
||
}
|
||
else
|
||
{
|
||
clifo.put(pre, "");
|
||
clifo.put(num, pn);
|
||
}
|
||
}
|
||
return pn.full();
|
||
}
|
||
|
||
void TBeeStore_sync::load_clifo(char tipocf)
|
||
{
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\nSELECT * FROM tieAnagCFP WHERE (Origine=1)AND";
|
||
str << '(' << (tipocf == 'F' ? "Fornitore" : "Cliente") << "=1);";
|
||
|
||
TFast_isamfile clifo(LF_CLIFO);
|
||
|
||
TODBC_recordset odbc(str);
|
||
const TRecnotype n = odbc.items();
|
||
|
||
str.cut(0) << TR("Importazione ") << (tipocf == 'F' ? TR("Fornitori") : TR("Clienti"));
|
||
TProgress_monitor pi(n, str);
|
||
for (bool ok = odbc.move_first(); ok; ok = odbc.move_next())
|
||
{
|
||
long codcf = odbc.get(tipocf == 'F' ? "For_CodFor" : "Cli_CodCG").as_int();
|
||
if (codcf <= 0)
|
||
{
|
||
const TString& cod_pk = odbc.get("Cod_PK").as_string();
|
||
if (cod_pk[0] == 'C' && cod_pk.len() == 8 && cod_pk[7] == tipocf)
|
||
codcf = atol(cod_pk.mid(1,6));
|
||
}
|
||
|
||
if (codcf > 0)
|
||
{
|
||
clifo.put(CLI_TIPOCF, tipocf);
|
||
clifo.put(CLI_CODCF, codcf);
|
||
if (clifo.read(_isequal) != NOERR)
|
||
{
|
||
clifo.zero();
|
||
clifo.put(CLI_TIPOCF, tipocf);
|
||
clifo.put(CLI_CODCF, codcf);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
codcf = 1L;
|
||
if (tipocf == 'F')
|
||
{
|
||
if (clifo.last() == NOERR && clifo.get_char(CLI_TIPOCF)=='F')
|
||
codcf += clifo.get_long(CLI_CODCF);
|
||
}
|
||
else
|
||
{
|
||
clifo.put(CLI_TIPOCF, 'F');
|
||
clifo.put(CLI_CODCF, 0);
|
||
if (clifo.read(_isgteq) == NOERR)
|
||
{
|
||
if (clifo.prev() == NOERR && clifo.get_char(CLI_TIPOCF)=='C')
|
||
codcf += clifo.get_long(CLI_CODCF);
|
||
}
|
||
}
|
||
clifo.zero();
|
||
clifo.put(CLI_TIPOCF, tipocf);
|
||
clifo.put(CLI_CODCF, codcf);
|
||
clifo.write();
|
||
|
||
TLocalisamfile cfv(LF_CFVEN);
|
||
cfv.put(CFV_TIPOCF, tipocf);
|
||
cfv.put(CFV_CODCF, codcf);
|
||
TString8 codprcf; codprcf.format("C%06ld%c", codcf, tipocf);
|
||
cfv.put(CFV_CODPRCF, codprcf);
|
||
cfv.write();
|
||
}
|
||
clifo.put(CLI_RAGSOC, odbc.get("RagSoc").as_string());
|
||
|
||
const int tipo = odbc.get("Tipo").as_int(); // 1=Fisica; 2=Giuridica; 3=Altro
|
||
if (tipo == 1)
|
||
{
|
||
clifo.put(CLI_SESSO, odbc.get("Sesso").as_string());
|
||
clifo.put(CLI_DATANASC, odbc.get("DTNascita").as_date());
|
||
clifo.put(CLI_COMNASC, comune(odbc, "", "ComuneNascita"));
|
||
clifo.put(CLI_TIPOPERS, 'F');
|
||
}
|
||
else
|
||
clifo.put(CLI_TIPOPERS, 'G');
|
||
|
||
TToken_string indirizzo(odbc.get("Indirizzo").as_string(), ',');
|
||
TString ind = indirizzo.get(0);
|
||
TString civ = indirizzo.get();
|
||
TString loc = indirizzo.get();
|
||
if (civ.len() > 10)
|
||
{
|
||
if (loc.full())
|
||
ind << ' ' << civ;
|
||
else
|
||
loc = civ;
|
||
civ.cut(0);
|
||
}
|
||
clifo.put(CLI_INDCF, ind.left(50));
|
||
|
||
split_phone(odbc, "Telefono", clifo, CLI_PTEL, CLI_TEL);
|
||
split_phone(odbc, "Cellulare", clifo, CLI_PTEL2, CLI_TEL2);
|
||
split_phone(odbc, "CellulareSMS", clifo, CLI_PTEL3, CLI_TEL3);
|
||
clifo.put(CLI_MAIL, odbc.get("EMail").as_string());
|
||
|
||
clifo.put(CLI_UTENTE, "BEESTORE");
|
||
TDate dua = odbc.get(BS_DTULTAGG).as_date();
|
||
if (!dua.ok()) dua = TDate(TODAY);
|
||
clifo.put(CLI_DATAAGG, dua);
|
||
|
||
clifo.rewrite();
|
||
|
||
if (!pi.add_status())
|
||
break;
|
||
}
|
||
}
|
||
|
||
void TBeeStore_sync::save_clifo(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("Cod_PK|"CLI_CODCF);
|
||
fields.add("RagSoc|"CLI_RAGSOC);
|
||
fields.add("Cognome|"CLI_RAGSOC);
|
||
fields.add("Nome|"CLI_RAGSOC);
|
||
fields.add("Indirizzo|"CLI_INDCF);
|
||
fields.add("Citta|"CLI_COMCF);
|
||
fields.add("Cap|"CLI_CAPCF);
|
||
fields.add("Provincia|");
|
||
fields.add("Telefono|PTEL+TEL");
|
||
fields.add("Cellulare|PTEL2+TEL2");
|
||
fields.add("CellulareSMS|PTEL3+TEL3");
|
||
fields.add("EMail|"CLI_MAIL);
|
||
fields.add("PartitaIva|"CLI_PAIV);
|
||
fields.add("CodFiscale|"CLI_COFI);
|
||
fields.add("Tipo|1");
|
||
fields.add("Sesso|"CLI_SESSO);
|
||
fields.add("DTNascita|"CLI_DATANASC);
|
||
fields.add("ComuneNascita|"CLI_COMNASC);
|
||
fields.add("PVNascita|");
|
||
fields.add("Cliente|");
|
||
fields.add("Fornitore|");
|
||
fields.add("For_CodFor|"CLI_CODCF);
|
||
fields.add("For_Blocco|"CLI_SOSPESO);
|
||
fields.add("Cli_CodCG|"CLI_CODCF);
|
||
fields.add("Cli_Blocco|"CLI_SOSPESO);
|
||
fields.add("MagInserAnagrafica|1");
|
||
fields.add("CodStato|"CLI_STATOCF);
|
||
fields.add("Annullato|0");
|
||
|
||
TString query = build_query(LF_CLIFO, dal, al);
|
||
query << "\nJOIN " << LF_CFVEN << " INTO TIPOCF==TIPOCF CODCF==CODCF";
|
||
|
||
TISAM_recordset clifo(query);
|
||
save_origine_2(clifo, "tieAnagCFP", fields, ClifoEvaluator);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_clifo(const TDate& dal, const TDate& al)
|
||
{
|
||
load_clifo('C');
|
||
load_clifo('F');
|
||
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\n";
|
||
TODBC_recordset clifo(str);
|
||
str << "DELETE FROM tieAnagCFP WHERE Origine=1;";
|
||
clifo.exec(str); // Elimina tutte le anagrafiche importate da BeeStore
|
||
|
||
save_clifo(dal, al);
|
||
}
|
||
|
||
bool TBeeStore_sync::save_and_delete_doc(TMov_mag*& doc) const
|
||
{
|
||
int err = 0;
|
||
if (doc != NULL)
|
||
{
|
||
if (doc->rows() > 0)
|
||
{
|
||
TLocalisamfile mm(LF_MOVMAG);
|
||
err = doc->write(mm);
|
||
if (err != NOERR)
|
||
{
|
||
TString msg;
|
||
msg.format(FR("Errore %d in registrazione scontrino %ld del %s"), err,
|
||
doc->get_long(MOVMAG_NUMREG), (const char*)doc->get(MOVMAG_DATAREG));
|
||
_log->log(2, msg);
|
||
msg << TR("\nSi desidera proseguire ugualmente?");
|
||
if (noyes_box(msg))
|
||
err = 0;
|
||
}
|
||
}
|
||
delete doc;
|
||
doc = NULL;
|
||
}
|
||
return err == 0;
|
||
}
|
||
|
||
void TBeeStore_sync::sync_val(const TDate& dal, const TDate& al)
|
||
{
|
||
TString_array fields;
|
||
fields.add("CodValuta|CODTAB");
|
||
fields.add("DSValuta|S0");
|
||
fields.add("Simbolo|CODTAB");
|
||
sync_table("%VAL", "tieValute", fields, dal, al);
|
||
}
|
||
|
||
void TBeeStore_sync::sync_listino(const TString& listino)
|
||
{
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\n";
|
||
TODBC_recordset prz(str);
|
||
|
||
str = "DELETE FROM tiePrzVendita WHERE Origine=1";
|
||
prz.exec(str); // Ignora tutti i listini di BeeStore
|
||
|
||
str.cut(0) << "USE " << LF_RCONDV << " SELECT " << LF_ANAMAG << ".CODART!=\"\""
|
||
<< "\nJOIN " << LF_ANAMAG << " INTO CODART==CODRIGA"
|
||
<< "\nFROM TIPO=L TIPORIGA=A COD=" << listino
|
||
<< "\nTO TIPO=L TIPORIGA=A COD=" << listino;
|
||
TISAM_recordset lis(str);
|
||
if (lis.move_first())
|
||
{
|
||
TString16 eur; eur << "CodValuta|'" << TCurrency::get_euro_val() << "'";
|
||
|
||
TString16 key; key << "L||||" << listino;
|
||
const TRectype& condv = cache().get(LF_CONDV, key);
|
||
|
||
TDate dt_inizio = condv.get(CONDV_VALIN);
|
||
if (!dt_inizio.ok()) dt_inizio = TDate(1,1,2000);
|
||
TDate dt_fine = condv.get(CONDV_VALFIN);
|
||
if (dt_fine < dt_inizio) dt_fine = TDate(31,12,2100);
|
||
|
||
TString descr; descr << "DSListino|'" << condv.get(CONDV_DESCR) << '\'';
|
||
TString dtini; dtini << "DTInizio|'" << dt_inizio.string() << '\'';
|
||
TString dtfin; dtfin << "DTFine|'" << dt_fine.string() << '\'';
|
||
|
||
TString_array fields;
|
||
fields.add("Cod_PK|"RCONDV_CODRIGA);
|
||
fields.add("CodPadre|"RCONDV_CODRIGA);
|
||
//fields.add("CodArticolo|"RCONDV_CODRIGA); // NON metterlo!
|
||
fields.add("TipoPrezzo|'1'"); // 1=Listino
|
||
fields.add(eur);
|
||
fields.add("Prezzo|"RCONDV_PREZZO);
|
||
fields.add("Prezzo2|0");
|
||
fields.add("Sconto|"RCONDV_SCONTO);
|
||
if (real::is_natural(listino))
|
||
fields.add("NumListino|"RCONDV_COD);
|
||
fields.add(descr);
|
||
fields.add(dtini);
|
||
fields.add(dtfin);
|
||
|
||
save_origine_2(lis, "tiePrzVendita", fields);
|
||
}
|
||
}
|
||
|
||
void TBeeStore_sync::sync_scontrini(const TDate& dal, const TDate& al)
|
||
{
|
||
const TString8 codcaus = ini_get_string(CONFIG_DITTA, "bs", MOVMAG_CODCAUS);
|
||
if (codcaus.blank())
|
||
{
|
||
_log->log(2, "Configurare parametri per movimenti Bee Store");
|
||
return;
|
||
}
|
||
|
||
TString str(255);
|
||
str << "ODBC(" << _dsn << ")\n";
|
||
str << "SELECT * FROM tieDMovMag WHERE Origine=1";
|
||
if (dal.ok() || al.ok())
|
||
{
|
||
str << " AND DataMov";
|
||
if (dal.ok() && al.ok())
|
||
str << " BETWEEN " << date2sql(dal) << " AND " << date2sql(al);
|
||
else
|
||
{
|
||
if (dal.ok())
|
||
str << ">=" << date2sql(dal);
|
||
else
|
||
str << "<=" << date2sql(al);
|
||
}
|
||
}
|
||
str << "\nORDER BY NumMov,NumRiga";
|
||
|
||
TODBC_recordset mov(str);
|
||
TProgress_monitor pi(mov.items(), str);
|
||
|
||
TString num_mov, nm;
|
||
TMov_mag* doc = NULL;
|
||
|
||
for (bool ok = mov.move_first(); ok; ok = mov.move_next())
|
||
{
|
||
nm = mov.get("NumMov").as_string();
|
||
if (nm != num_mov)
|
||
{
|
||
if (!save_and_delete_doc(doc))
|
||
break;
|
||
num_mov = nm;
|
||
const TDate datadoc = mov.get("DataMov").as_date();
|
||
doc = new TMov_mag;
|
||
doc->put(MOVMAG_CODCAUS, codcaus);
|
||
doc->put(MOVMAG_DATAREG, datadoc);
|
||
}
|
||
TRectype& rdoc = doc->new_row();
|
||
rdoc.put(RMOVMAG_CODART, mov.get("CodArticolo").as_string());
|
||
rdoc.put(RMOVMAG_UM, mov.get("CodUntMis").as_string());
|
||
rdoc.put(RMOVMAG_PREZZO, mov.get("PrzCassaValuta").as_real());
|
||
if (!pi.add_status())
|
||
break;
|
||
}
|
||
save_and_delete_doc(doc); // Salva ultimo documento in sospeso
|
||
}
|
||
|
||
|
||
bool TBeeStore_sync::create()
|
||
{
|
||
_dsn = ini_get_string(CONFIG_DITTA, "bs", "DSN", "BEESTORE");
|
||
_sqlog = ini_get_string(CONFIG_DITTA, "bs", "Log", "");
|
||
|
||
if (_dsn.full())
|
||
{
|
||
TProgress_monitor ti(1, TR("Connessione a SQL Server"), false);
|
||
TString query; query << "ODBC(" << _dsn << ")\nSELECT * FROM tieValute;";
|
||
TODBC_recordset recset(query);
|
||
recset.move_first();
|
||
if (_sqlog.full() && _sqlog.is_relative_path())
|
||
{
|
||
TFilename n; n.tempdir();
|
||
n.add(_sqlog.name());
|
||
_sqlog = n;
|
||
}
|
||
recset.set_log_file(_sqlog);
|
||
return TSkeleton_application::create();
|
||
}
|
||
return error_box(FR("Impossibile connettersi al DSN '%s'"), (const char*)_dsn);
|
||
|
||
}
|
||
|
||
void TBeeStore_sync::main_loop()
|
||
{
|
||
TBeeStore_mask mask;
|
||
|
||
while (mask.run() == K_ENTER)
|
||
{
|
||
mask.autosave(); // Rende definitivi tutti i paramentri in [bs]
|
||
_log = new TLog_report;
|
||
|
||
const TDate dal = mask.get_date("SyncDateFrom");
|
||
const TDate al = mask.get_date("SyncDateTo");
|
||
|
||
if (mask.get_bool("SyncUMS"))
|
||
sync_ums(dal, al);
|
||
if (mask.get_bool("SyncIVA"))
|
||
sync_iva(dal, al);
|
||
if (mask.get_bool("SyncLinee"))
|
||
sync_lines(dal, al);
|
||
if (mask.get_bool("SyncCatMer"))
|
||
sync_catmer(dal, al);
|
||
if (mask.get_bool("SyncAnamag"))
|
||
sync_anamag(dal, al);
|
||
if (mask.get_bool("SyncBarCode"))
|
||
sync_barcode(dal, al);
|
||
if (mask.get_bool("SyncVAL"))
|
||
sync_val(dal, al);
|
||
if (mask.get_bool("SyncClifo"))
|
||
sync_clifo(dal, al);
|
||
if (mask.get("SyncListino").full())
|
||
sync_listino(mask.get("SyncListino"));
|
||
if (mask.get_bool("SyncSontr"))
|
||
sync_scontrini(dal, al);
|
||
|
||
_log->preview();
|
||
delete _log;
|
||
_log = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
int bs0200(int argc, char* argv[])
|
||
{
|
||
TBeeStore_sync bss;
|
||
bss.run(argc, argv, TR("BeeStore Synchronizer"));
|
||
return 0;
|
||
}
|