#include #include #include #include #include #include "777.h" #include "777100a.h" #include #include #include #include #include #include "base.h" #include "quadroc.h" /////////////////////////////////////////////////////////// // Dichiarazioni /////////////////////////////////////////////////////////// HIDDEN int anno_dic() { static int anno = 0; if (anno == 0) { TConfig ini(CONFIG_STUDIO, "77"); anno = ini.get_int("AnnoDic"); } return anno; } /////////////////////////////////////////////////////////// // 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, int extra_offset = 0); 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 /////////////////////////////////////////////////////////// const int REC_SIZE = 940; // Lunghezza intero record const int HDR_SIZE = 35; // Lunghezza testata record 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; } void tipo_record(const char* tipo); bool valid() const; TRecordDylog(); TRecordDylog(const char* tipo, const char* cfdich); TRecordDylog(const TRecordDylog& rec); virtual ~TRecordDylog(); }; /////////////////////////////////////////////////////////// // TTrasferimentoDylog /////////////////////////////////////////////////////////// class TTrasferimentoDylog : public TObject { TFilename _name; ifstream* _in_stream; ofstream* _out_stream; TString16 _defname; 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 TString& default_name(); 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, int extra_offset) { TToken_string trc(32, ','); TString80 str; // body.update(); // Per un errore sui form 1.4 lo faccio io a mano body.reset(); for (word i = 0; i < body.fields(); i++) { TForm_item& fi = body.field(i); if (fi.enabled()) fi.update(); } for (word f = 0; f < body.fields(); f++) { TForm_item& fi = body.field(f); str = fi.get(); str.trim(); if (fi.shown() && fi.enabled()) { 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 + HDR_SIZE + extra_offset, len); } } } } // Obsoleto 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)); } } // Obsoleto 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) // Obsoleto { 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) // Obsoleto { _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 TRectype& ditta = cache().get(LF_NDITTE, codditta); TString16 codanagr; codanagr << ditta.get_char(NDT_TIPOA) << '|' << ditta.get_long(NDT_CODANAGR); const TRectype& pers = cache().get(LF_ANAG, codanagr); const TString16 cfdich = pers.get(ANA_COFI); const char* td = NULL; switch (tipo[1]) { case 'A': td = "AU"; break; case 'T': td = "T0"; break; default : break; } const long items = cur.items(); if (items > 0) // Se c'e almeno un record ... { cur.freeze(TRUE); // Per efficienza congela il cursore TPrint_section& body = section('B', odd_page); for (int err = first(); err == NOERR; err = next()) { // Inizializza record col primo modulo TRecordDylog rec(td, cfdich); transfer_section(body, rec, file); // Il quadro ST contiene un array di 3 sotto-record da azzerare per la Dylog! if (stricmp(td, "T0") == 0) { cur.curr().zero(); for (int i = 1; i < 3; i++) transfer_section(body, rec, file, i*91); } 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_QUALA: 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 != '\0' && quadro[1] != '\0', "Codice quadro non valido"); const char* name; switch(quadro[1]) { case 'A': name = "77qla"; break; case 'T': name = "77qst"; 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! } /////////////////////////////////////////////////////////// // 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("%02d%02d%04d", gg, mm, aaaa); 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 if (tipo == 'N') 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); } bool TRecordDylog::valid() const { if (_buffer[0] != 'P') return FALSE; if (_buffer[1] == ' ' || _buffer[2] == ' ') return FALSE; return TRUE; } void TRecordDylog::tipo_record(const char* tipo) { _buffer.spaces(REC_SIZE); _buffer[0] = 'P'; // Linea Prassi if (tipo && *tipo) { _buffer[1] = tipo[0]; _buffer[2] = tipo[1]; } } TRecordDylog::TRecordDylog() { tipo_record(NULL); } TRecordDylog::TRecordDylog(const char* tipo, const char* cf) { tipo_record(tipo); if (cf && *cf) set(cf, 'A', 3, 16); // Codice fiscale dichiarante } TRecordDylog::TRecordDylog(const TRecordDylog& rec) : _buffer(rec._buffer) { } TRecordDylog::~TRecordDylog() { } /////////////////////////////////////////////////////////// // TTrasferimentoDylog /////////////////////////////////////////////////////////// const TString& TTrasferimentoDylog::default_name() { if (_defname.empty()) { const int anno = anno_dic()+1; _defname.format("TRA7%02d", anno % 100); } return _defname; } 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::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) { rec.tipo_record(NULL); // Invalida il record (*_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 records = 0; TRecordDylog rec; long records_per_disk = 0; int volumes = 1; const bool magnetic = ::xvt_fsys_is_removable_drive(path) != 0; 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 = ::xvt_fsys_get_disk_size(path, 'b') != 0; 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; } } // Azzera totali long written = 0; while (read(rec)) { outfile << rec; written++; pi.addstatus(1); if (magnetic && written >= records_per_disk) break; } } 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 /////////////////////////////////////////////////////////// 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)); TCursor cur_base(&rel_base, "", 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) { pi.addstatus(1); const TRectype& base = cur_base.curr(); const long codditta = base.get_long(BSE_CODDITTA); if (codditta > 0) // Strano, ma puo' succedere { t.append_quadro("LA", codditta, pi); t.append_quadro("ST", 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; }