#include #include #include #include #include #include #include "../mg/mglib.h" #include "bs0.h" #include "../ve/condv.h" #include "../ve/rcondv.h" /////////////////////////////////////////////////////////// // 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 /////////////////////////////////////////////////////////// class TBeeStore_sync : public TSkeleton_application { TString16 _dsn; TFilename _sqlog; TLog_report* _log; 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); 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_scontrini(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; } // Carica da Bee Store i record con Origine=1, cioč 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("DATAAGG"); TDate dtultagg = odbc.get("DtUltAgg").as_date(); if (!dtultagg.ok()) dtultagg = TODAY; str.format("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) { file.put("UTENTE", "BEESTORE"); file.put("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) { 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 nella tabella %s"), n, out_table); _log->log(0, ""); _log->log(0, str); 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 << " ("; FOR_EACH_ARRAY_ROW(fields, sr, srow) str << (sr ? ", " : "") << srow->get(0); str << ", Origine, Errore, DTUltAgg"; str << ")\nVALUES ("; FOR_EACH_ARRAY_ROW(fields, ir, irow) { if (ir) { str << ", "; if (str.len() - str.rfind('\n') > 80) str << '\n'; } const TFixed_string cfld = irow->get(1); if (cfld.find("SCONTO")>=0) { real sconto; const TString& exp = in_set.get(cfld).as_string(); 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') { const TVariant& var = in_set.get(cfld); str << var2sql(var); } else if (cfld.find("->") > 0) { const TVariant& var = in_set.get(cfld); str << var2sql(var); } else str << cfld; } str << ", 2, 0, GETDATE()"; str << ");"; if (odbc.exec(str) <= 0) _log->log(1, 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); } TString& append_select_range(TString& q, const TDate& dal, const TDate& al) { q << "\nSELECT (UTENTE!=\"BEESTORE\")"; if (dal.ok() || al.ok()) { 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) { TString q; q << "USE " << table; append_select_range(q, 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) { TString4 q; q << logicnum; sync_table(q, out_table, fields, dal, al); } 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; query << "USE GMC"; append_select_range(query, dal, al); 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; query << "USE " << LF_ANAMAG; append_select_range(query, 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); } 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); str.cut(0) << "USE " << LF_RCONDV << "\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; TMov_mag* doc = NULL; for (bool ok = mov.move_first(); ok; ok = mov.move_next()) { const TString80 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()); } 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()) { TTimerind ti(10, TR("Connessione a SQL Server"), false, false); ti.force_update(); 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("SyncVAL")) sync_val(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("Bee Store")); return 0; }