#include #include #include #include #include #include #include #include #include #include #include #include "ba7300.h" class TFile_selector : public TAutomask { TArray_sheet* _sht; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TFile_selector(); virtual ~TFile_selector(); }; bool TFile_selector::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_FILE: if (e == fe_button) { const int nfile = atoi(o.get()); FOR_EACH_SHEET_ROW_BACK((*_sht), i, row) { if (row->get_int(0) == nfile) { _sht->select(i); break; } } switch (_sht->run()) { case K_ENTER: { TToken_string& row = _sht->row(-1); set(o.dlg(), row.get(0)); e = fe_modify; } break; default: break; } } if (e == fe_modify) { const TPrefix& pref = prefix(); const int total = pref.items(); const int nfile = atoi(o.get()); FOR_EACH_SHEET_ROW_BACK((*_sht), i, row) { if (row->get_int(0) == nfile) { set(o.dlg()+1, row->get(1)); break; } } TList_field& lb = (TList_field&)field(F_KEY); if (i < 0) { lb.replace_items("", ""); return error_box("Inserire un numero di file valido"); } TLocalisamfile f(nfile); const RecDes& rd = *f.curr().rec_des(); TToken_string codes, items; for (i = 1; i <= rd.NKeys; i++) { codes.add(i); items.add("Chiave "); items << i; } lb.replace_items(codes, items); lb.set("1"); } break; case F_KEY: if (e == fe_modify) { const int nkey = atoi(o.get()); const int nfile = get_int(F_FILE); if (nfile >= LF_USER && nkey > 0) { TLocalisamfile f(nfile); const RecDes& rd = *f.curr().rec_des(); const KeyDes& kd = rd.Ky[nkey-1]; TToken_string str("", '+'); for (int i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; str.add(rf.Name); } set(o.dlg()+1, str); } } break; default: break; } return TRUE; } static int find_edit_apps(TConfig& cfg, void* jolly) { TBit_array& ba = *(TBit_array*)jolly; TAssoc_array& ass = cfg.list_variables(); FOR_EACH_ASSOC_STRING(ass, obj, key, val) { if (strncmp(key, "Edit_", 5) == 0) { const int nfile = atoi(key+5); ba.set(nfile); } } return 0; } TFile_selector::TFile_selector() : TAutomask("ba7300a") { TIndwin iw(0, "Inizializzazione Editors...", FALSE, FALSE); _sht = new TArray_sheet(-1,-1,-6,-6,"Selezione archivio", "Numero@6R|Descrizione@50|Editor|E-Mail"); const TPrefix& pref = prefix(); const int total = pref.items(); TString app, mail; TBit_array edit_apps, mail_apps; TConfig ini("install.ini", "Main"); ini.for_each_paragraph(find_edit_apps, &edit_apps); TConfig inidit(CONFIG_DITTA, "MailTransactions"); TAuto_token_string filter; for (int f = 0; inidit.exist("Filter", f); f++) { filter = inidit.get("Filter", NULL, f); const int num = filter.get_int(1); mail_apps.set(num); } for (int i = LF_USER; i < total; i++) { const bool can_edit = edit_apps[i]; const bool can_mail = mail_apps[i]; if (can_edit || can_mail) { app.cut(0); if (can_edit && i > LF_TAB) { TLocalisamfile f(i); f.get_relapp(app); } mail = can_mail ? "X" : ""; TToken_string* row = new TToken_string; *row << i; row->add(pref.description(*row)); row->add(app); row->add(mail); _sht->rows_array().add(row); } } } TFile_selector::~TFile_selector() { delete _sht; } /////////////////////////////////////////////////////////// // TBrowser_sheet /////////////////////////////////////////////////////////// class TBrowser_sheet : public TCursor_sheet { public: TBrowser_sheet(TCursor* c, const char* f, const char* t, const char* h); }; TBrowser_sheet::TBrowser_sheet(TCursor* c, const char* f, const char* t, const char* h) : TCursor_sheet(c, f, t, h, 0x3, 1) { TToken_string tag = "Selezione"; add_tag_buttons(tag); } /////////////////////////////////////////////////////////// // TRecord_selector /////////////////////////////////////////////////////////// class TRecord_selector : public TAutomask { TRelation* _relation; TCursor* _cursor; TToken_string _fields, _head; protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); bool add_special_field(short id, const RecFieldDes& rf, int x, int y); void add_browse_field(const RecFieldDes& rf); int create_fields(const char* title, const RecDes& rd, int nkey, short id, int starty); public: TCursor& cursor() { return *_cursor; } TToken_string& fields() { return _fields; } TRecord_selector(const TFile_selector& fm); virtual ~TRecord_selector(); }; bool TRecord_selector::on_field_event(TOperable_field& o, TField_event e, long jolly) { if (o.dlg() >= 201 && e == fe_button) { const char* title = _cursor->file().description(); TBrowser_sheet cs(_cursor, _fields, title, _head); const short first_id = o.dlg() >= 301 ? 301 : 201; TRectype& rec = _cursor->curr(); rec.zero(); if (_fields.not_empty()) { short id = first_id; FOR_EACH_TOKEN(_fields, tok) { if (id2pos(id) > 0) rec.put(tok, get(id++)); else break; } const TRecnotype pos = _cursor->read(); cs.select(pos); } const KEY k = cs.run(); switch (k) { case K_ENTER: { short id = first_id; FOR_EACH_TOKEN(_fields, tok) { if (id2pos(id) > 0) set(id++, rec.get(tok)); else break; } } break; case K_INS: { TString str; if (_cursor->file().get_relapp(str)) { TExternal_app app(str); app.run(); } else error_box("Il file non è associato ad un editor"); } break; case K_CTRL+'G': { const char* const inifile = "trans.ini"; TConfig ini(inifile, "Transaction"); ini.remove_all(); ini.set("Action", "Modify"); TString str; str << _cursor->file().num(); ini.set_paragraph(str); ini.remove_all(); TToken_string row = cs.row(-1); TString16 field; for (int i = 0; ; i++) { _fields.get(i, field); if (field.not_empty()) ini.set(field, row.get(i)); else break; } ini.set_paragraph("Transaction"); // Forza il flush if (_cursor->file().get_relapp(str)) { str << " /i" << inifile; TExternal_app app(str); app.run(); } else error_box("Il file non è associato ad un editor"); } break; default: break; } } return TRUE; } bool TRecord_selector::add_special_field(short id, const RecFieldDes& rf, int x, int y) { TString16 prompt = rf.Name; prompt.lower(); prompt[0] = toupper(prompt[0]); prompt.left_just(14); const logicnum = get_int(F_FILE); if (logicnum == LF_DOC && strcmp(rf.Name, "PROVV") == 0) { add_list(id, 0, prompt, x, y, 12, "", "D|P", "Definitivo|Provvisiorio"); return TRUE; } if (strcmp(rf.Name, "TIPOCF") == 0) { add_list(id, 0, prompt, x, y, 9, "", "C|F", "Cliente|Fornitore"); return TRUE; } return FALSE; } int TRecord_selector::create_fields(const char* title, const RecDes& rd, int nkey, short id, int starty) { TString prompt; int i; int x = 2; const KeyDes& kd = rd.Ky[nkey]; const int nf = kd.NkFields; int rows = 1; for (i = 0; i < nf; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; if (x + rf.Len + 16 > 76) { x = 2; rows++; } x += (rf.Len+16) > 38 ? 76 : 38; } add_groupbox(-1, 0, title, 1, starty, 80, rows+2); int y = starty+1; x = 2; for (i = 0; i < nf; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; prompt = rf.Name; prompt.lower(); prompt[0] = toupper(prompt[0]); prompt.left_just(14); if (x + rf.Len + 16 > 76) { x = 2; y++; } switch (rf.TypeF) { case _intfld: case _longfld: case _realfld: case _wordfld: add_number(id+i, 0, prompt, x, y, rf.Len, "BU"); break; case _intzerofld: case _longzerofld: add_number(id+i, 0, prompt, x, y, rf.Len, "BUZ"); break; case _datefld: add_date(id+i, 0, prompt, x, y, "B"); break; case _boolfld: add_boolean(id+i, 0, prompt, x, y); break; case _alfafld: case _charfld: default: if (!add_special_field(id+i, rf, x, y)) add_string(id+i, 0, prompt, x, y, rf.Len, "BU"); break; } x += (rf.Len+16) > 38 ? 76 : 38; } return y+1; } void TRecord_selector::add_browse_field(const RecFieldDes& rf) { if (_fields.get_pos(rf.Name) < 0) { TString16 prompt = rf.Name; _fields.add(prompt); prompt.lower(); prompt[0] = toupper(prompt[0]); const int len = min(rf.Len, 50); if (len > prompt.len()) prompt << '@' << len; _head.add(prompt); } } TRecord_selector::TRecord_selector(const TFile_selector& fm) : TAutomask("ba7300a") { for (short id = F_FILE; id <= F_SENDMAIL; id++) { set(id, fm.get(id)); if (id < F_SENDMAIL) field(id).disable(); } const int logicnum = get_int(F_FILE); const int nkey = get_int(F_KEY)-1; _relation = new TRelation(logicnum); _cursor = new TCursor(_relation, "", nkey+1); const RecDes& rd = *_relation->curr().rec_des(); const KeyDes& kd = rd.Ky[nkey]; int i; for (i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; add_browse_field(rf); } for (int k = 0; k < rd.NKeys; k++) if (k != nkey) { const KeyDes& kd = rd.Ky[k]; for (i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; add_browse_field(rf); } } for (i = 0; i < rd.NFields && _head.items() < 6; i++) { const RecFieldDes& rf = rd.Fd[i]; add_browse_field(rf); } int y = 5; y = create_fields("@bDal record", rd, nkey, 201, y); create_fields("@bAl record", rd, nkey, 301, y+1); set_handlers(); } TRecord_selector::~TRecord_selector() { delete _cursor; delete _relation; } /////////////////////////////////////////////////////////// // MailFlood app /////////////////////////////////////////////////////////// class TMail_flood_app : public TSkeleton_application { virtual void main_loop(); protected: void send_records(TCursor& cur); void send_mails(TCursor& cur); void fill_rows(const TRectype& parent, int logicnum, TConfig& ini) const; public: void fill_key(const TRectype& curr, TConfig& ini) const; void fill_transaction(const TRectype& curr, TConfig& ini) const; void send_selected(TRecord_selector& m); }; inline TMail_flood_app& app() { return (TMail_flood_app&)main_app(); } /////////////////////////////////////////////////////////// // Main /////////////////////////////////////////////////////////// void TMail_flood_app::fill_key(const TRectype& curr, TConfig& ini) const { TString16 para; para << curr.num(); ini.set_paragraph(para); ini.remove_all(); const RecDes& rd = *curr.rec_des(); const KeyDes& kd = rd.Ky[0]; for (int i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; const char* field = rf.Name; ini.set(field, curr.get(field)); } } void TMail_flood_app::send_records(TCursor& cur) { TFilename dir; dir.tempdir(); dir.add("transpos"); ::mkdir(dir); const TRectype& curr = cur.curr(); cur.freeze(); const long items = cur.items(); TProgind pi(items, "Generazione transazioni...", FALSE, TRUE); TString16 para; para << curr.num(); // Paragrafo con i campi TFilename ininame; for (cur = 0; cur.pos() < items; ++cur) { pi.addstatus(1); ininame = dir; ininame << SLASH << "tr" << cur.pos() << ".ini"; TConfig ini(ininame, "Transaction"); ini.set("Action", "Link"); ini.set("Mode", "A"); fill_key(curr, ini); } TString appname; if (cur.file().get_relapp(appname)) { appname << " /i" << dir << SLASH << "tr*.ini"; TExternal_app app(appname); app.run(); } for (long i = 0; i < items; i++) { ininame = dir; ininame << SLASH << "tr" << i << ".ini"; ::remove(ininame); } ::rmdir(dir); } void TMail_flood_app::fill_rows(const TRectype& parent, int logicnum, TConfig& ini) const { TLocalisamfile rowsfile(logicnum); // Carico tracciato record! TRectype& rec = rowsfile.curr(); TString16 numfield; const RecDes& rd = *rec.rec_des(); const KeyDes& kd = rd.Ky[0]; for (int i = 0; i < kd.NkFields; i++) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = rd.Fd[nf]; const char* field = rf.Name; if (i < kd.NkFields-1) rec.put(field, parent.get(field)); // Copia nella riga la chiave 1 della testata else numfield = field; // Memorizza campo numeratore } TRecord_array arr(rec, numfield); for (int r = arr.first_row(); r > 0 && r <= arr.rows(); r = arr.succ_row(r)) { const TRectype& row = arr[r]; TString16 para; para << row.num() << ',' << r; ini.set_paragraph(para); for (int i = row.items()-1; i >= 0; i--) { const char* name = row.fieldname(i); if (strcmp(name, "G1") != 0) { TFieldref fr(name, 0); fr.write(ini, para, row.get(name)); } } } } void TMail_flood_app::fill_transaction(const TRectype& rec, TConfig& ini) const { TString16 para; para << rec.num(); ini.set_paragraph(para); for (int i = rec.items()-1; i >= 0; i--) { const char* name = rec.fieldname(i); TFieldref fr(name, 0); fr.write(ini, para, rec.get(name)); } switch (rec.num()) { case LF_ANAMAG: fill_rows(rec, LF_UMART, ini); break; case LF_DIST: fill_rows(rec, LF_RDIST, ini); break; case LF_DOC: fill_rows(rec, LF_RIGHEDOC, ini); break; case LF_MOV: fill_rows(rec, LF_RMOV, ini); fill_rows(rec, LF_RMOVIVA, ini); break; default: break; }; } void TMail_flood_app::send_mails(TCursor& cur) { const TRectype& rec = cur.curr(); TFilename ininame; ininame.tempdir(); ininame.add("trans.ini"); cur.freeze(); const long items = cur.items(); TProgind pi(items, "Spedizione transazioni...", TRUE, TRUE); const long ditta = main_app().get_firm(); for (cur = 0; cur.pos() < items; ++cur) { pi.addstatus(1); if (pi.iscancelled()) break; const bool ok = ::can_dispatch_transaction(rec); if (ok) { TConfig ini(ininame, "Transaction"); ini.set("Action", "Modify"); ini.set("Firm", ditta); ini.set("Mode", "A"); fill_transaction(rec, ini); } if (ok) { ::dispatch_transaction(rec, ininame); ::remove(ininame); } } } void TMail_flood_app::send_selected(TRecord_selector& m) { TCursor cur = m.cursor(); TRectype recfrom = cur.curr(); TRectype recto = cur.curr(); recfrom.zero(); recto.zero(); for (int i = 0; ; i++) { if (m.id2pos(201+i) < 0) break; const char* field = m.fields().get(i); recfrom.put(field, m.get(201+i)); recto.put(field, m.get(301+i)); } cur.setregion(recfrom, recto); const long items = cur.items(); if (items > 0) { if (yesno_box("Confermare l'invio di %ld transazioni", items)) { if (m.get_bool(F_SENDMAIL)) send_mails(cur); else send_records(cur); } } else warning_box("Nessun record da inviare"); } void TMail_flood_app::main_loop() { TFile_selector fm; while (fm.run() == K_ENTER) { TRecord_selector rm(fm); while (rm.run() == K_ENTER) send_selected(rm); } } int ba7300(int argc, char* argv[]) { TMail_flood_app ma; ma.run(argc, argv, "Sincronicity"); return 0; }