#include #include #include #include #include #include <../ve/velib.h> #include "bs0.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() { 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 { 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; TLog_report* _log; protected: bool save_doc(TDocumento* 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); void sync_table(const int logicnum, const char* out_table, const TString_array& fields, const TDate& dal); void sync_iva(const TDate& dal); void sync_ums(const TDate& dal); void sync_lines(const TDate& dal); void sync_catmer(const TDate& dal); void sync_anamag(const TDate& dal); void sync_scontrini(const TDate& dal); public: virtual void main_loop(); }; const TString& date2sql(const TDate& d) { TString& tmp = get_tmp_string(); tmp.format("DATEFROMPARTS(%d,%d,%d)", d.year(), d.month(), d.day()); return tmp; } const TString& var2sql(const TVariant& var) { TString& tmp = get_tmp_string(); switch (var.type()) { case _boolfld: tmp = var.as_bool() ? "1" : "0"; break; case _datefld: tmp = date2sql(var.as_date()); 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 << ")\n" << "SELECT * FROM " << 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[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); } void TBeeStore_sync::sync_table(const char* table, const char* out_table, const TString_array& fields, const TDate& dal) { TString q; q << "USE " << table << " SELECT BETWEEN(DATAAGG,"<< dal.date2ansi() << ",0)"; 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) { TString4 q; q << logicnum; sync_table(q, out_table, fields, dal); } void TBeeStore_sync::sync_ums(const TDate& dal) { TString_array fields; fields.add("CodUntMis|CODTAB"); fields.add("DSUntMis|S0"); sync_table("%UMS", "tieUntMisura", fields, dal); } void TBeeStore_sync::sync_iva(const TDate& dal) { 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); } void TBeeStore_sync::sync_lines(const TDate& dal) { TString_array fields; fields.add("CodLinea|CODTAB"); fields.add("DSLinea|S0"); TString query; query << "USE GMC SELECT (CODTAB?='???')"; if (dal.ok()) query << "&&(BETWEEN(DATAAGG,"<< dal.date2ansi() << ",0))"; TISAM_recordset lin(query); sync_table(lin, "tieLineeArt", fields); } void TBeeStore_sync::sync_catmer(const TDate& dal) { TString_array fields; fields.add("CodCategoriaMerceologica|CODTAB"); fields.add("DSCategoriaMerceologica|S0"); fields.add("CodTipoEtichetta|''"); sync_table("GMC", "tieCategorieMerceologiche", fields, dal); } void TBeeStore_sync::sync_anamag(const TDate& dal) { 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 47\nJOIN 49 INTO CODART==CODART"; if (dal.ok()) query << "\nSELECT BETWEEN(DATAAGG,"<< dal.date2ansi() << ",0)"; TISAM_recordset art(query); sync_table(art, "tieArticoli", fields); } bool TBeeStore_sync::save_doc(TDocumento* doc) const { if (doc != NULL && doc->rows() > 0) { const int err = doc->write(); if (err != NOERR) { TString msg; msg.format(FR("Errore %d in registrazione scontrino %s/%d del %s"), err, (const char*)doc->get(DOC_CODNUM), doc->get_long(DOC_NDOC), (const char*)doc->get(DOC_DATADOC)); _log->log(2, msg); msg << TR("\nSi desidera proseguire ugualmente?"); if (!noyes_box(msg)) return false; } } return true; } void TBeeStore_sync::sync_scontrini(const TDate& dal) { const TString4 codnum = ini_get_string(CONFIG_DITTA, "bs", DOC_CODNUM); const TString4 tipodoc = ini_get_string(CONFIG_DITTA, "bs", DOC_TIPODOC); if (codnum.blank() || tipodoc.blank()) { _log->log(2, "Configurare numerazione e tipo documento per movimenti Bee Store"); return; } TString str(255); str << "ODBC(" << _dsn << ")\n"; str << "SELECT * FROM tieDMovMag WHERE Origine=1"; if (dal.ok()) str << " AND DataMov>=" << date2sql(dal); str << "\nORDER BY NumMov,NumRiga"; TODBC_recordset mov(str); TProgress_monitor pi(mov.items(), str); TString num_mov; TDocumento* 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_doc(doc)) break; delete doc; num_mov = nm; const TDate datadoc = mov.get("DataMov").as_date(); doc = new TDocumento('D', datadoc.year(), codnum, 0L); doc->put(DOC_TIPODOC, tipodoc); doc->put(DOC_DATADOC, datadoc); const TString& codval = mov.get("CodValuta").as_string(); if (is_true_value(codval)) { doc->put(DOC_CODVAL, codval); doc->put(DOC_CAMBIO, mov.get("CambioValuta").as_string()); } } TRiga_documento& rdoc = doc->new_row("01"); rdoc.put(RDOC_CODART, mov.get("CodArticolo").as_string()); rdoc.put(RDOC_CODARTMAG, mov.get("CodArticolo").as_string()); rdoc.put(RDOC_CHECKED, true); rdoc.put(RDOC_UMQTA, mov.get("CodUntMis").as_string()); rdoc.put(RDOC_PREZZO, mov.get("PrzCassaValuta").as_real()); } save_doc(doc); } void TBeeStore_sync::main_loop() { TBeeStore_mask mask; _dsn = ini_get_string(CONFIG_DITTA, "bs", "DSN", "BEESTORE"); while (mask.run() == K_ENTER) { mask.autosave(); // Rende definitivi tutti i paramentri in [bs] _log = new TLog_report; const TDate dal = mask.get_date("SyncDate"); if (mask.get_bool("SyncUMS")) sync_ums(dal); if (mask.get_bool("SyncIVA")) sync_iva(dal); if (mask.get_bool("SyncLinee")) sync_lines(dal); if (mask.get_bool("SyncCatMer")) sync_catmer(dal); if (mask.get_bool("SyncAnamag")) sync_anamag(dal); if (mask.get_bool("SyncSontr")) sync_scontrini(dal); _log->preview(); delete _log; _log = NULL; } } int bs0200(int argc, char* argv[]) { TBeeStore_sync bss; bss.run(argc, argv, TR("Bee Store")); return 0; }