#include #include #include #include #include #include #include #include #include "777.h" #include "777100a.h" #include #include #include #include #include #include "base.h" #include "quadroc.h" /////////////////////////////////////////////////////////// // Dichiarazioni /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // TFormDylog /////////////////////////////////////////////////////////// class TRecordDylog; class TTrasferimentoDylog; class TFormDylog : public TForm { TCursor* _sortedcur; int _index; TArray _records; TPointer_array _positions; protected: bool compatible(const TRectype& r1, const TRectype& r2); void add_rec(TRectype& r1, const TRectype& r2); long raggruppa_c(); int first(); int next(); void transfer_section(TPrint_section& body, TRecordDylog& rec, TTrasferimentoDylog& file); char log2rec(int num, int& rpm) const; protected: virtual TCursor* cursor() { return _sortedcur ? _sortedcur : TForm::cursor(); } public: long trasfer(long codditta, TTrasferimentoDylog& file, const char* tipo); TFormDylog(const char* name); virtual ~TFormDylog(); }; /////////////////////////////////////////////////////////// // TTracciatiDylog /////////////////////////////////////////////////////////// class TTracciatiDylog : public TObject { TAssoc_array _form; public: TFormDylog& form(const char* quadro); void destroy(); TTracciatiDylog(); virtual ~TTracciatiDylog(); } _trcDylog; /////////////////////////////////////////////////////////// // TRecordDylog /////////////////////////////////////////////////////////// class TCacheDylog : public TObject { TArray _files; TAssoc_array _tables; public: const TRectype& get(int num, const char* key); const TRectype& get(int num, long key); void destroy(); TCacheDylog() { } virtual ~TCacheDylog() { } } _cacheDylog; const int REC_SIZE = 940; class TRecordDylog : public TObject { TString _buffer; protected: // TObject virtual TObject* dup() const { return new TRecordDylog(*this); } virtual void print_on(ostream& outs) const; virtual void read_from(istream& ins); public: void set(const char* val, char tipo, int pos, int len); const TRecordDylog& operator=(const TRecordDylog& rec) { _buffer = rec._buffer; return *this; } const TString& tipo_record() const { return _buffer.left(2); } void tipo_record(const char* tipo); bool valid() const; TRecordDylog(); TRecordDylog(const char* tipo); TRecordDylog(const TRecordDylog& rec); virtual ~TRecordDylog(); }; /////////////////////////////////////////////////////////// // TTrasferimentoDylog /////////////////////////////////////////////////////////// class TTrasferimentoDylog : public TObject { TFilename _name; ifstream* _in_stream; ofstream* _out_stream; public: bool open(const char* path = "", char mode = 'r'); bool close(); bool write(const TRecordDylog& rec); bool read(TRecordDylog& rec); bool eof() const { return _in_stream && _in_stream->eof(); } virtual bool ok() const; const char* default_name() const { return "TRA77099"; } TTrasferimentoDylog& operator<<(const TRecordDylog& rec) { write(rec); return *this; } TTrasferimentoDylog& operator>>(TRecordDylog& rec) { read(rec); return *this; } long append_quadro(const char* quadro, long codditta, TProgind& pi); bool split(const char* dest_path); void remove(); TTrasferimentoDylog(const char* name = "", char mode = 'r'); virtual ~TTrasferimentoDylog(); }; /////////////////////////////////////////////////////////// // Implementazioni /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // TFormDylog /////////////////////////////////////////////////////////// void TFormDylog::transfer_section(TPrint_section& body, TRecordDylog& rec, TTrasferimentoDylog& file) { TToken_string trc(16, ','); TString80 str; TCursor& cur = *cursor(); body.update(); for (word f = 0; f < body.fields(); f++) { TForm_item& fi = body.field(f); str = fi.get(); str.trim(); if (fi.shown() && str.not_empty()) { trc = fi.get_special_value("DYLOG"); if (trc.not_empty()) { const char tipo = trc[0]; const int pos = trc.get_int(1); const int len = trc.get_int(); rec.set(str, tipo, pos, len); } } } } bool TFormDylog::compatible(const TRectype& r1, const TRectype& r2) { if (r1.empty() || r2.empty()) return TRUE; if (r1.get_long(QUC_CODDITTA) != r2.get_long(QUC_CODDITTA)) return FALSE; if (r1.get_char(QUC_TIPOA) != r2.get_char(QUC_TIPOA)) return FALSE; if (r1.get_long(QUC_CODANAGR) != r2.get_long(QUC_CODANAGR)) return FALSE; if (r1.get_char(QUC_CAUSALE) != r2.get_char(QUC_CAUSALE)) return FALSE; if (r1.get_int(QUC_TASSAZIONE) != r2.get_int(QUC_TASSAZIONE)) return FALSE; const real p1 = r1.get_real(QUC_PERC); const real p2 = r2.get_real(QUC_PERC); bool yes = (p1 == ZERO && p2 != ZERO) || (p1 == p2); return yes; } void TFormDylog::add_rec(TRectype& r1, const TRectype& r2) { if (r1.empty()) r1 = r2; else { for (int f = r1.items()-1; f >= 0; f--) { const char* name = r1.fieldname(f); if (r1.type(name) == _realfld) { real val = r1.get_real(name); val += r2.get_real(name); r1.put(name, val); } } r1.put(QUC_PERC, r2.get(QUC_PERC)); } } long TFormDylog::raggruppa_c() { TCursor& cur = *cursor(); TRectype& rc = cur.curr(); _records.destroy(); for (cur = 0; cur.ok(); ++cur) { bool append = TRUE; const int last = _records.items()-1; if (last >= 0) { TRectype& sum = (TRectype&)_records[last]; if (compatible(sum, rc)) { add_rec(sum, rc); append = FALSE; } } if (append) { _records.add(rc); _positions.add_long(cur.pos()+1); } } return _records.items(); } int TFormDylog::first() { TCursor& cur = *cursor(); cur = 0; bool ok = cur.ok(); if (cur.file().num() == LF_QUAC) { if (ok) { raggruppa_c(); _index = 0; cur.curr() = (TRectype&)_records[0]; } } return ok ? NOERR : _iseof; } int TFormDylog::next() { TCursor& cur = *cursor(); bool ok; if (cur.file().num() == LF_QUAC) { _index++; ok = _index < _records.items(); if (ok) { cur = _positions.get_long(_index) - 1; cur.curr() = (TRectype&)_records[_index]; } } else { ++cur; ok = cur.ok(); } return ok ? NOERR : _iseof; } long TFormDylog::trasfer(long codditta, TTrasferimentoDylog& file, const char* tipo) { TCursor& cur = *cursor(); // Filtra il cursore sulla ditta corrente TRectype filter(cur.curr()); filter.zero(); filter.put(BSE_CODDITTA, codditta); cur.setregion(filter, filter); const long items = cur.items(); if (items > 0) // Se c'e almeno un record ... { cur.freeze(TRUE); // Per efficienza congela il cursore int err = first(); // Deve sempre tornare NOERR CHECKS(err == NOERR, "Invalid cursor ", tipo); TPrint_section& head = section('H', first_page); TPrint_section& body = section('B', odd_page); for (; err == NOERR; err = next()) { // Inizializza record col primo modulo TRecordDylog rec(tipo); transfer_section(head, rec, file); transfer_section(body, rec, file); file << rec; } cur.freeze(FALSE); } return items; } TFormDylog::TFormDylog(const char* name) : TForm(name), _sortedcur(NULL) { const char* key = NULL; switch (TForm::cursor()->file().num()) { case LF_QUAC: key = "CODDITTA|TIPOA|216@->RAGSOC|CODANAGR|CODCAUS|PERC"; case LF_QUAD: key = "CODDITTA|216@->RAGSOC|TIPOA|CODANAGR"; break; default : break; } if (key) _sortedcur = new TSorted_cursor(TForm::relation(), key); } TFormDylog::~TFormDylog() { if (_sortedcur) delete _sortedcur; } /////////////////////////////////////////////////////////// // TTracciatiDylog /////////////////////////////////////////////////////////// TFormDylog& TTracciatiDylog::form(const char* quadro) { CHECK(quadro && *quadro == 'S' && quadro[1] != '\0', "Codice quadro non valido"); const char* name; switch(quadro[1]) { case 'C': name = "77qc"; break; case 'F': name = "77qd"; break; case 'G': name = "77qdb"; break; case 'H': name = "77qd1"; break; case 'K': name = "77qsk"; break; case 'L': name = "77ql"; break; case 'P': name = "77qe"; break; case 'Q': name = "77qe1"; break; default : name = NULL; break; } TFormDylog* frm = (TFormDylog*)_form.objptr(name); if (frm == NULL) { frm = new TFormDylog(name); _form.add(name, frm); } return *frm; } void TTracciatiDylog::destroy() { _form.destroy(); } TTracciatiDylog::TTracciatiDylog() { } TTracciatiDylog::~TTracciatiDylog() { destroy(); // Non viene mai chiamato! } /////////////////////////////////////////////////////////// // TCacheDylog /////////////////////////////////////////////////////////// const TRectype& TCacheDylog::get(int num, const char* key) { TRecord_cache* rc = (TRecord_cache*)_files.objptr(num); if (rc == NULL) { rc = new TRecord_cache(num); _files.add(rc, num); } return rc->get(key); } const TRectype& TCacheDylog::get(int num, long key) { TString16 str; str << key; return get(num, str); } void TCacheDylog::destroy() { _files.destroy(); _tables.destroy(); } /////////////////////////////////////////////////////////// // TRecordDylog /////////////////////////////////////////////////////////// void TRecordDylog::print_on(ostream& outs) const { outs.write(_buffer, _buffer.size()); } void TRecordDylog::read_from(istream& ins) { ins.read(_buffer.get_buffer(), _buffer.size()); } void TRecordDylog::set(const char* val, char tipo, int pos, int len) { TString80 str(val); str.upper(); int lenstr = str.len(); if (tipo == 'N') { // Controlla date if (len == 8 && lenstr == 10 && str[2] == '-' && str[5] == '-') { int aaaa, mm, gg; sscanf(str, "%d-%d-%d", &gg, &mm, &aaaa); str.format("%04d%02d%02d", aaaa, mm, gg); lenstr = 8; } else // Controlla numeri reali if (len == 11) { const int point = str.find('.'); if (point >= 0) str.cut(lenstr = point); if (real::is_null(str)) { str = "0"; lenstr = 1; } } else // Controlla booleani if (len == 1 && lenstr <= 1 && (str[0] == 'X' || str[0] <= ' ')) { str = str[0] == 'X' ? "1" : "0"; lenstr = 1; } } if (lenstr > len) { #ifdef DBG NFCHECK("Campo troppo lungo: %s (max. %d)", val, len); #endif str.cut(lenstr = len); } if (lenstr != len) { if (tipo == 'N') str.right_just(len, '0'); else str.left_just(len); } _buffer.overwrite(str, pos-1); } bool TRecordDylog::valid() const { if (tipo_record().blank()) return FALSE; if (_buffer.right(3) != "A\r\n") return FALSE; return TRUE; } void TRecordDylog::tipo_record(const char* tipo) { _buffer.spaces(REC_SIZE); if (tipo && *tipo) { _buffer[0] = tipo[0]; _buffer[1] = tipo[1]; } _buffer.overwrite("A\r\n", REC_SIZE-3); } TRecordDylog::TRecordDylog() { tipo_record(NULL); } TRecordDylog::TRecordDylog(const char* tipo) { tipo_record(tipo); } TRecordDylog::TRecordDylog(const TRecordDylog& rec) : _buffer(rec._buffer) { } TRecordDylog::~TRecordDylog() { } /////////////////////////////////////////////////////////// // TTrasferimentoDylog /////////////////////////////////////////////////////////// bool TTrasferimentoDylog::open(const char* path, char mode) { CHECK(mode == 'r' || mode == 'w', "Invalid open mode"); close(); if (path && *path) { _name = path; _name.add(default_name()); } if (_name.empty()) _name = default_name(); if (mode == 'r') _in_stream = new ifstream(_name, ios::in | ios::nocreate | ios::binary); else _out_stream = new ofstream(_name, ios::out | ios::binary); return TRUE; } bool TTrasferimentoDylog::ok() const { if (_in_stream) return _in_stream->good() != 0; if (_out_stream) return _out_stream->good() != 0; return FALSE; } bool TTrasferimentoDylog::close() { if (_in_stream) { delete _in_stream; _in_stream = NULL; } if (_out_stream) { delete _out_stream; _out_stream = NULL; } return TRUE; } bool TTrasferimentoDylog::write(const TRecordDylog& rec) { bool ok = _out_stream != NULL; if (ok) (*_out_stream) << rec; return ok; } bool TTrasferimentoDylog::read(TRecordDylog& rec) { bool ok = _in_stream != NULL && !_in_stream->eof(); if (ok) { (*_in_stream) >> rec; ok = rec.valid(); } return ok; } long TTrasferimentoDylog::append_quadro(const char* quadro, long codditta, TProgind& pi) { TString str; str << "Trasferimento quadro " << quadro << " ditta " << codditta; pi.set_text(str); TFormDylog& frm = _trcDylog.form(quadro); long items = frm.trasfer(codditta, *this, quadro); return items; } bool TTrasferimentoDylog::split(const char* path) { close(); long totale[32]; memset(totale, 0, sizeof(totale)); long records = 0; TRecordDylog rec; long records_per_disk = 0; int volumes = 1; const bool magnetic = ::os_is_removable_drive(path); if (magnetic) { if (!yesno_box("Inserire il primo disco del trasferimento nell'unita' %s\n" "Tutti i dischi devono essere vuoti ed avere la stesso formato.\n" "Si desidera iniziare il trasferimento?", path)) return FALSE; unsigned long disk_size = ::os_get_disk_size(path); records_per_disk = long(disk_size / REC_SIZE - 2); volumes = int((records-1)/records_per_disk)+1; } TProgind pi(records, "Trasferimento records", FALSE, TRUE); // Read from start open("", 'r'); for (int volume = 1; volume <= volumes; volume++) { if (magnetic && volume > 1) { if (!yesno_box("Inserire il disco %d di %d:\n" "Si desidera proseguire il trasferimento?", volume, volumes)) { break; } } TTrasferimentoDylog outfile(path, 'w'); while (!outfile.ok()) { if (magnetic) { if (yesno_box("Errore di scrittura in %s\n" "Si desidera ritentare?", (const char*)path)) outfile.open(path, 'w'); else break; } else { error_box("Errore di scrittura in %s", (const char*)path); break; } } // Compila record di testata // Scrive record testata // Azzera totali memset(totale, 0, sizeof(totale)); long written = 0; while (read(rec)) { const TString& tipo_rec = rec.tipo_record(); if (tipo_rec == "AA" || tipo_rec == "ZZ") continue; const int pos = tipo_rec[1] - 'A'; if (pos >= 0 && pos < 26) { outfile << rec; totale[pos]++; written++; pi.addstatus(1); } else error_box("Tipo record non riconosciuto: %c", tipo_rec); if (magnetic && written > records_per_disk) break; } // Compila record di coda // Scrive record di coda } return TRUE; } // Cancella il file void TTrasferimentoDylog::remove() { close(); ::remove(_name); } TTrasferimentoDylog::TTrasferimentoDylog(const char* path, char mode) : _in_stream(NULL), _out_stream(NULL) { open(path, mode); } TTrasferimentoDylog::~TTrasferimentoDylog() { close(); } /////////////////////////////////////////////////////////// // main /////////////////////////////////////////////////////////// HIDDEN int anno_dic() { TConfig ini(CONFIG_STUDIO); return ini.get_int("AnnoDic"); } class TTransferDylog_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& of, TField_event fe, long jolly); public: TTransferDylog_msk(); virtual ~TTransferDylog_msk() { } }; bool TTransferDylog_msk::on_field_event(TOperable_field& of, TField_event fe, long jolly) { switch (of.dlg()) { case F_PATH: if (fe == fe_modify || fe == fe_close) { TFilename name = of.get(); if (!name.exist()) return error_box("Il percorso non e' valido"); } break; default: break; } return TRUE; } TTransferDylog_msk::TTransferDylog_msk() : TAutomask("777100a") { set(F_ANNO, anno_dic()); } class TTransferDylog_app : public TSkeleton_application { protected: virtual void main_loop(); }; void TTransferDylog_app::main_loop() { TTransferDylog_msk m; while (m.run() == K_ENTER) { TFilename tmp; tmp.tempdir(); TTrasferimentoDylog t(tmp, 'w'); TRecordDylog rec; TRelation rel_base(LF_BASE); TRectype da_rec(LF_BASE), a_rec(LF_BASE); da_rec.put(BSE_CODDITTA, m.get(F_DADITTA)); a_rec.put(BSE_CODDITTA, m.get(F_ADITTA)); TString filter; filter << "ANNODIC==" << anno_dic(); TCursor cur_base(&rel_base, filter, 1, &da_rec, &a_rec); TProgind pi(cur_base.items(), "Generazione file di trasferimento", FALSE, TRUE); cur_base.freeze(); for (cur_base = 0; cur_base.ok(); ++cur_base) { const TRectype& base = cur_base.curr(); const long codditta = base.get_long(BSE_CODDITTA); pi.addstatus(1); t.append_quadro("SC", codditta, pi); t.append_quadro("SF", codditta, pi); t.append_quadro("SG", codditta, pi); t.append_quadro("SH", codditta, pi); t.append_quadro("SL", codditta, pi); } pi.close_modal(); if (m.get(F_SUPPORTO) == "D") tmp = m.get(F_DISK); else tmp = m.get(F_PATH); t.split(tmp); t.remove(); } _trcDylog.destroy(); } int m777200(int argc, char* argv[]) { TTransferDylog_app app; app.run(argc, argv, "Invio Dylog"); return 0; }