#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 /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // TForm770 /////////////////////////////////////////////////////////// class TRecord770; class TTrasferimento770; class TForm770 : 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, int rigo, TRecord770& rec, TTrasferimento770& file); char log2rec(int num, int& rpm) const; protected: virtual TCursor* cursor() { return _sortedcur ? _sortedcur : TForm::cursor(); } public: long trasfer(long codditta, TTrasferimento770& file, char tipo, int rpm); TForm770(const char* name); virtual ~TForm770(); }; /////////////////////////////////////////////////////////// // TRecord770 /////////////////////////////////////////////////////////// enum { FIELD_SIZE = 16, BLOCK_SIZE = 24, USEABLE_SIZE = 3997, TOTAL_SIZE = 4000 }; struct TField770 : public TObject { TString _desc; int _pos; // Base 1 int _len; char _type; // A/N }; class TTracciato770 : public TObject { char _tipo; TArray _fields; protected: int add_field(const char* name, char type, int pos, int len); int add_filler(char type, int pos, int len) { return add_field("Filler", type, pos, len); } public: const TField770& field(int pos) const; void auto_fill(TString& buffer) const; TTracciato770(char tipo); virtual ~TTracciato770(); }; class TTracciati770 : public TObject { TArray _trc; TAssoc_array _form; public: const TTracciato770& tracciato(char tipo); TForm770& form(const char* quadro, char& tipo, int& rpm); void destroy(); TTracciati770(); virtual ~TTracciati770(); } _trc770; class TCache770 : 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(); TCache770() { } virtual ~TCache770() { } } _cache770; class TRecord770 : public TObject { TString _buffer; protected: // TObject virtual TObject* dup() const { return new TRecord770(*this); } virtual void print_on(ostream& outs) const; virtual void read_from(istream& ins); protected: // TObject const TTracciato770& tracciato() const { return _trc770.tracciato(tipo_record()); } const TField770& get_field(int pos) const { return tracciato().field(pos); } void set(const TField770& fld, const char* val); int calculate_blocks(const char* val) const; bool fill(const TRectype& rec); bool fill_e(const TRectype& rec); bool fill_comune(const TRectype& rec_anagr, int whichcom, bool swapcap, int offset); bool fill_residenza(const TRectype& rec_anagr, int offset, int whichcom, bool swapcap); bool fill_telefono(const TRectype& rec_anagr, int offset); bool fill_persona(const TRectype& rec_anagr, int offset, int gap); public: void set(int pos, const char* val); void set(int pos, int val); void set(int pos, long val); void set(int pos, const real& val); void set(int pos, const TDate& val); void set(int pos, char val); void set(int pos, bool val); bool add(const char* code, const char* val); const char* get(int pos, TString& str) const; int get_int(int pos) const; char get_char(int pos) const; const TRecord770& operator=(const TRecord770& rec) { _buffer = rec._buffer; return *this; } const TRecord770& operator=(const TRectype& rec) { fill(rec); return *this; } char tipo_record() const { return _buffer[0]; } void tipo_record(char tipo) { _buffer[0] = tipo; tracciato().auto_fill(_buffer); } void azzera_campi_non_posizionali(); void set_magnetic_support(bool mag) { _buffer[3997] = mag ? 'A' : ' '; } bool valid() const; TRecord770(); TRecord770(char tipo); TRecord770(const TRecord770& rec); TRecord770(const TRectype& rec); virtual ~TRecord770(); }; /////////////////////////////////////////////////////////// // TTrasferimento770 /////////////////////////////////////////////////////////// class TTrasferimento770 : public TObject { TFilename _name; ifstream* _in_stream; ofstream* _out_stream; public: bool open(const char* path = "", char mode = 'r'); bool close(); bool write(const TRecord770& rec); bool read(TRecord770& rec); bool eof() const { return _in_stream && _in_stream->eof(); } const char* default_name() const { return "MOD77098"; } TTrasferimento770& operator<<(const TRecord770& rec) { write(rec); return *this; } TTrasferimento770& operator>>(TRecord770& rec) { read(rec); return *this; } long append_quadro(const char* quadro, long codditta, TProgind& pi); bool split(const char* dest_path); void remove(); TTrasferimento770(const char* name = "", char mode = 'r'); virtual ~TTrasferimento770(); }; /////////////////////////////////////////////////////////// // Implementazioni /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// // TForm770 /////////////////////////////////////////////////////////// void TForm770::transfer_section(TPrint_section& body, int rigo, TRecord770& rec, TTrasferimento770& file) { TString16 basecode, code; 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()) { basecode = fi.get_special_value("TRASFER"); if (basecode.not_empty()) { if (fi.fields() > 0) { const TFieldref& fr = ((TForm_string&)fi).field(0); const int num = fr.file(); const char* fn = fr.name(); const TFieldtypes ft = cur.curr(num).type(fn); switch (ft) { case _boolfld: if (!str.blank()) str = "1"; str.right_just(16); break; case _datefld: if (str.len() == 10 && str[2] == '-' && str[5] == '-') { str[2] = str[3]; str[3] = str[4]; str[4] = str[8]; str[5] = str[9]; str.cut(6); str.right_just(16); } break; case _realfld: if (str.len() > 3) str.rtrim(3); case _intfld: case _longfld: str.right_just(16); break; default: break; } } const int vero_rigo = atoi(basecode.mid(2, 2)) + rigo; code.format("%c%c%02d%c%c00", basecode[0], basecode[1], vero_rigo, basecode[4], basecode[5]); if (!rec.add(code, str)) { file << rec; rec.azzera_campi_non_posizionali(); rec.add(code, str); } } } } } bool TForm770::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 TForm770::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 TForm770::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 TForm770::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 TForm770::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 TForm770::trasfer(long codditta, TTrasferimento770& file, char rectype, int rpm) { 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 // Inizializza record col primo modulo TRecord770 rec(rectype); int modulo = 1; int rigo = 0; rec.set(6, modulo); int err = first(); // Deve sempre tornare NOERR TPrint_section& head = section('H', first_page); transfer_section(head, rigo, rec, file); for (; err == NOERR; err = next()) { TPrint_section& body = section('B', odd_page); transfer_section(body, rigo, rec, file); rigo++; if (rigo >= rpm) { // Scrivi record se non vuoto if (rec.get_char(7) > ' ') file << rec; // Avanza al prossimo modulo ed azzera la riga rigo = 0; modulo++; rec.azzera_campi_non_posizionali(); rec.set(6, modulo); transfer_section(head, rigo, rec, file); } } // Ultimo record parzialmente compilato if (rec.get_char(7) > ' ') file << rec; cur.freeze(FALSE); } return items; } TForm770::TForm770(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); } TForm770::~TForm770() { if (_sortedcur) delete _sortedcur; } /////////////////////////////////////////////////////////// // TTracciato770 /////////////////////////////////////////////////////////// int TTracciato770::add_field(const char* name, char type, int pos, int len) { TField770* info = new TField770; info->_desc = name; info->_type = type; info->_pos = pos; info->_len = len; _fields.add(info); return _fields.items(); } const TField770& TTracciato770::field(int pos) const { TField770* info = (TField770*)_fields.objptr(pos-1); CHECKD(info, "Campo non valido ", pos); return *info; } void TTracciato770::auto_fill(TString& buffer) const { buffer.fill(' ', TOTAL_SIZE); for (int f = _fields.last(); f >= 0; f--) { const TField770& info = (const TField770&)_fields[f]; if (info._desc == "Filler") { const char fill = info._type == 'N' ? '0' : ' '; char* index = buffer.get_buffer(); index += info._pos - 1; memset(index, fill, info._len); } } buffer[0] = _tipo; buffer.overwrite("\r\n", TOTAL_SIZE-2); } TTracciato770::TTracciato770(char tipo) : _tipo(tipo) { if (strchr("AEFGHZ", tipo) == NULL) NFCHECK("Tipo record non valido: %c", tipo); add_field("Tipo record", 'A', 1, 1); // 1 add_filler('N', 2, 2); // 2 if (tipo == 'A' || tipo == 'Z') { add_filler('N', 4, 2); // 3 add_field("Numero totale volumi inviati", 'N', 6, 3); add_field("Progressivo del volume inviato", 'N', 9, 3); add_field("Data di emissione", 'N', 12, 6); add_field("Codice fornitura", 'N', 18, 5); if (tipo == 'A') { add_field("Tipo fornitore", 'N', 23, 1); // 8 add_field("Codice fiscale del fornitore", 'A', 24, 16); add_field("Cognome del fornitore", 'A', 40, 60); add_field("Data di nascita del fornitore", 'N', 100, 8); add_field("Comune o stato", 'A', 108, 40); add_field("Provincia di nascita", 'A', 148, 2); add_field("Indirizzo", 'A', 150, 35); add_field("C.A.P.", 'N', 185, 5); add_field("Comune di residenza", 'A', 190, 40); add_field("Provincia di residenza", 'A', 230, 2); add_field("Indirizzo di residenza", 'A', 232, 35); add_field("C.A.P. di residenza", 'N', 267, 5); } else { add_field("Numero complessivo di record", 'N', 23, 9); // 8 add_filler('N', 32, 9); add_field("Numero record di tipo 'E'", 'N', 41, 9); add_field("Numero record di tipo 'F'", 'N', 50, 9); add_field("Numero record di tipo 'G'", 'N', 59, 9); add_field("Numero record di tipo 'H'", 'N', 68, 9); add_filler('A', 77, 3921); add_field("Supporto magnetico", 'A',3998, 1); } } if (tipo >= 'E' && tipo <= 'H') { add_field("Codice fiscale del soggetto dichiarante", 'A', 4, 16); // 3 add_field("Protocollo", 'A', 20, 25); add_field("Spazio riservato all'applicazione", 'A', 45, 35); if (tipo == 'E') { add_field("Data di presentazione", 'N', 80, 6); // 6 add_field("Numero progressivo del pacco", 'N', 86, 7); add_field("Numero sequenza all'interno del pacco", 'N', 93, 3); add_field("Cognome", 'A', 96, 60); add_field("Nome", 'A',120, 20); add_filler('A',140, 16); add_field("Dichiarazione integrativa", 'N',156, 1); // 12 add_field("Data di nascita del dichiarante", 'N',157, 6); add_field("Sesso", 'A',163, 1); add_field("Comune o Stato estero di nascita", 'A',164, 40); add_field("Sigla provincia di nascita del dic", 'A',204, 2); add_field("Mese di variazione residenza o domicilio",'N',206, 2); add_field("Anno variazione residenza o domicilio", 'N',208, 2); add_field("Comune di residenza o domicilio dich", 'A',210, 40); add_field("Sigla provincia di resid o domicilio", 'A',250, 2); // 20 add_field("Indirizzo residenza o domicilio", 'A',252, 35); add_field("CAP residenza o domicilio", 'N',287, 5); add_field("Codice attivitą F", 'A',292, 5); add_field("Telefono F", 'A',297, 13); add_field("Mese variazione sede legale", 'N',310, 2); add_field("Anno variazione sede legale", 'N',312, 2); add_field("Comune della sede legale", 'A',314, 40); add_field("Sigla provincia sede legale", 'A',354, 2); add_field("Indirizzo sede legale", 'A',356, 35); add_field("CAP sede legale", 'N',391, 5); // 30 add_field("Mese variazione domicilio fiscale", 'N',396, 2); add_field("Anno variazione domicilio fiscale", 'N',398, 2); add_field("Comune domicilio fiscale", 'N',400, 40); add_field("Sigla provincia domicilio fiscale", 'N',440, 2); add_field("Indirizzo domicilio fiscale", 'A',442, 35); add_field("CAP domicilio fiscale", 'N',477, 5); add_field("Codice attivitą G", 'A',482, 5); add_field("Stato", 'N',487, 1); add_field("Natura giuridica", 'N',488, 2); add_field("Situazione", 'N',490, 1); // 40 add_field("Telefono G", 'A',491, 13); add_field("Codice fiscale", 'A',504, 16); add_field("Codice carica", 'N',520, 1); add_field("Cognome rappresentante", 'A',521, 24); add_field("Nome del rappresentante", 'A',545, 20); add_field("Sesso del rappresentante", 'A',565, 1); add_field("Data nascita rappresentante", 'N',566, 6); add_field("Comune nascita rappresentante", 'A',572, 40); add_field("Sigla provincia nascita rap", 'A',612, 2); add_field("Comune residenza anagrafica rap", 'A',614, 40); // 50 add_field("Sigla residenza anagrafica nascita rap", 'A',654, 2); add_field("CAP residenza anagrafica rap", 'N',656, 5); add_field("Indirizzo residenza anagrafica rap", 'A',661, 35); add_field("Telefono rap", 'A',696, 13); add_field("Casella quadro SA", 'N',709, 1); add_field("Casella quadro SB", 'N',710, 1); add_field("Casella quadro SC", 'N',711, 1); add_field("Casella quadro SD", 'N',712, 1); add_field("Casella quadro SE", 'N',713, 1); add_field("Casella quadro SF", 'N',714, 1); // 60 add_field("Casella quadro SG", 'N',715, 1); add_field("Casella quadro SH", 'N',716, 1); add_field("Casella quadro SK", 'N',717, 1); add_field("Casella quadro SL", 'N',718, 1); add_field("Casella quadro SM", 'N',719, 1); add_field("Casella quadro SN", 'N',720, 1); add_field("Casella quadro SP", 'N',721, 1); add_field("Casella quadro SQ", 'N',722, 1); add_field("Casella quadro SR", 'N',723, 1); add_field("Casella quadro SS", 'N',724, 1); // 70 add_field("Casella quadro ST", 'N',725, 1); add_field("Casella quadro SU", 'N',726, 1); add_field("Casella quadro SV", 'N',727, 1); add_field("Casella quadro SW", 'N',728, 1); add_field("Casella quadro SZ", 'N',729, 1); add_field("Firma presidente o compon organo contr", 'N',730, 1); add_field("Firma del dichiarante", 'N',731, 1); add_field("Codice fiscale del CAAF", 'N',732, 11); add_field("Numero iscrizione all'albo", 'N',743, 5); add_field("Codice fiscale Direttore Tecnico CAAF", 'A',748, 16); // 80 add_field("Casella controlli", 'N',764, 1); add_field("Dichiarazione non compilata", 'N',765, 1); add_field("Dichiarazione non firmata", 'N',766, 1); add_field("Dichiarazione incompleta", 'N',767, 1); add_field("Altri casi 1", 'N',768, 1); add_field("Altri casi 2", 'N',769, 1); add_field("Dichiarazione smarrita", 'N',770, 1); } else { add_field("Numero modulo", 'N', 80, 6); // 6 add_field("Campi non posizionali", 'A', 86, 24); // 7 add_field("Supporto magnetico", 'A', 3998, 1); // 8 } } } TTracciato770::~TTracciato770() { } /////////////////////////////////////////////////////////// // TTracciati770 /////////////////////////////////////////////////////////// const TTracciato770& TTracciati770::tracciato(char tipo) { const int pos = tipo-'A'; TTracciato770* trc = (TTracciato770*)_trc.objptr(pos); if (trc == NULL) { trc = new TTracciato770(tipo); _trc.add(trc, pos); } return *trc; } TForm770& TTracciati770::form(const char* quadro, char& tipo, int& rpm) { CHECK(quadro && *quadro == 'S' && quadro[1] != '\0', "Codice quadro non valido"); const char* name; switch(quadro[1]) { case 'C': name = "77qc"; tipo = 'F'; rpm = 11; break; case 'F': name = "77qd"; tipo = 'G'; rpm = 9; break; case 'G': name = "77qdb"; tipo = 'G'; rpm = 9; break; case 'H': name = "77qd1"; tipo = 'G'; rpm = 9; break; case 'K': name = "77qsk"; tipo = 'G'; rpm = 31; break; case 'L': name = "77ql"; tipo = 'G'; rpm = 22; break; case 'P': name = "77qe"; tipo = 'G'; rpm = 14; break; case 'Q': name = "77qe1"; tipo = 'G'; rpm = 15; break; default : name = NULL; break; } TForm770* frm = (TForm770*)_form.objptr(name); if (frm == NULL) { frm = new TForm770(name); _form.add(name, frm); } return *frm; } void TTracciati770::destroy() { _trc.destroy(); _form.destroy(); } TTracciati770::TTracciati770() { } TTracciati770::~TTracciati770() { destroy(); // Non viene mai chiamato! } /////////////////////////////////////////////////////////// // TCache770 /////////////////////////////////////////////////////////// const TRectype& TCache770::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& TCache770::get(int num, long key) { TString16 str; str << key; return get(num, str); } void TCache770::destroy() { _files.destroy(); _tables.destroy(); } /////////////////////////////////////////////////////////// // TRecord770 /////////////////////////////////////////////////////////// void TRecord770::print_on(ostream& outs) const { outs.write(_buffer, TOTAL_SIZE); } void TRecord770::read_from(istream& ins) { _buffer.fill(' ', TOTAL_SIZE); ins.read(_buffer.get_buffer(), TOTAL_SIZE); } void TRecord770::set(const TField770& fld, const char* val) { TString80 str(val); str.upper(); int lenstr = str.len(); if (lenstr > fld._len) { #ifdef DBG NFCHECK("Campo troppo lungo: %s (max. %d)", val, fld._len); #endif str.cut(lenstr = fld._len); } if (lenstr != fld._len) { str.trim(); if (fld._type == 'N') str.right_just(fld._len); else str.left_just(fld._len); } _buffer.overwrite(str, fld._pos-1); } void TRecord770::set(int pos, const char* val) { const TField770& fld = tracciato().field(pos); set(fld, val); } void TRecord770::set(int pos, int val) { const TField770& fld = tracciato().field(pos); CHECKD(fld._type == 'N', "Invalid numeric field ", pos); TString16 str; str.format("%d", val); set(fld, str); } void TRecord770::set(int pos, long val) { const TField770& fld = tracciato().field(pos); CHECKD(fld._type == 'N', "Invalid numeric field ", pos); TString16 str; str.format("%ld", val); set(fld, str); } void TRecord770::set(int pos, const real& val) { const TField770& fld = tracciato().field(pos); CHECKD(fld._type == 'N', "Invalid numeric field ", pos); const char* str = val.string(fld._len, 0); set(fld, str); } void TRecord770::set(int pos, const TDate& val) { const TField770& fld = tracciato().field(pos); CHECKD(fld._type == 'N' && (fld._len == 6 || fld._len == 8), "Invalid date field ", pos); const char* str; if (fld._len == 8) str = val.string(full, '\0', full, full, gma_date); else str = val.string(brief, '\0', full, full, gma_date); set(fld, str); } void TRecord770::set(int pos, char val) { const TField770& fld = get_field(pos); CHECKD(fld._type == 'A' && fld._len == 1, "Invalid char field ", pos); const char str[2] = { val, '\0' }; set(fld, str); } void TRecord770::set(int pos, bool val) { const TField770& fld = get_field(pos); CHECKD(fld._type == 'N' && fld._len == 1, "Invalid boolean field ", pos); const char str[2] = { val ? '1' : '0', '\0' }; set(fld, str); } const char* TRecord770::get(int pos, TString& str) const { const TField770& fld = get_field(pos); str = _buffer.mid(fld._pos-1, fld._len); return str.trim(); } int TRecord770::get_int(int pos) const { TString16 str; get(pos, str); return atoi(str); } char TRecord770::get_char(int pos) const { const TField770& fld = get_field(pos); CHECKD(fld._type == 'A', "Invalid char field ", pos); return _buffer[fld._pos-1]; } // Calcola i blocchi necessari per contenere la stringa val int TRecord770::calculate_blocks(const char* val) const { // Il primo blocco contiene 16 caratteri, // gli altri solo 15 perche' c'e' anche il + int blocks = 1; const int len = strlen(val); if (len > 16) blocks += (len-17) / 15 + 1; return blocks; } // Azzera tutti i campi non posizionali dei record di tipo F, G e H void TRecord770::azzera_campi_non_posizionali() { CHECK(strchr("FGH", tipo_record()) != NULL, "Impossibile azzerare un record senza campi non posizionali"); char* buf = _buffer.get_buffer() + 85; memset(buf, ' ', TOTAL_SIZE-88); } // Aggiunge un campo non posizionale ai record di tipo F, G e H bool TRecord770::add(const char* code, const char* val) { CHECK(strchr("FGH", tipo_record()) != NULL, "Impossibile aggiungere campi non posizionali"); CHECKS(code && strlen(code) == 8, "Invalid field code ", code); CHECKS(val && *val, "Can't add empty field ", code); // Cerca il primo posto libero for (int pos = 85; pos < USEABLE_SIZE; pos += BLOCK_SIZE) { if (_buffer[pos] == ' ') break; } const int free_blocks = (USEABLE_SIZE - pos) / BLOCK_SIZE; const int needed_blocks = calculate_blocks(val); const bool ok = free_blocks >= needed_blocks; if (ok) // Se ci sono abbastanza blocchi liberi { TString80 str(val); str.upper(); const int lenstr = str.len(); for (int i = 0; i < lenstr; ) { _buffer.overwrite(code, pos); pos += 8; if (i != 0) { _buffer.overwrite("+", pos); pos++; } const int maxlen = 15 + (i == 0); const TString& substr = str.mid(i, maxlen); _buffer.overwrite(substr, pos); pos += maxlen; i += maxlen; } } return ok; } bool TRecord770::fill_persona(const TRectype& rec_anagr, int offset, int gap) { TString16 key = rec_anagr.get(ANA_CODANAGR); const TRectype& rec_anafis = _cache770.get(LF_ANAGFIS, key); set(0+offset, rec_anagr.get(ANA_RAGSOC).left(24)); set(1+offset, rec_anagr.get(ANA_RAGSOC).mid(30, 20)); if (gap) { offset += gap; set(2+offset, rec_anafis.get_date(ANF_DATANASC)); set(3+offset, rec_anafis.get(ANF_SESSO)); } else { set(2+offset, rec_anafis.get(ANF_SESSO)); set(3+offset, rec_anafis.get_date(ANF_DATANASC)); } key = rec_anafis.get(ANF_COMNASC); if (key.not_empty()) { key.insert(" |"); const TRectype& rec_comnasc = _cache770.get(LF_COMUNI, key); set(4+offset, rec_comnasc.get(COM_DENCOM).left(40)); set(5+offset, rec_comnasc.get(COM_PROVCOM).left(2)); } return TRUE; } bool TRecord770::fill_telefono(const TRectype& rec_anagr,int offset) { TString80 key = rec_anagr.get(ANA_PTELRF); if (key.not_empty()) key << '-'; key << rec_anagr.get(ANA_TELRF); key.cut(13); set(offset, key); return key.not_empty(); } bool TRecord770::fill_comune(const TRectype& rec_anagr, int whichcom, bool swapcap, int offset) { bool use_comres; if (whichcom < 0) use_comres = rec_anagr.get(ANA_COMRF).empty(); else use_comres = whichcom ? TRUE : FALSE; TString80 key = rec_anagr.get(use_comres ? ANA_COMRES : ANA_COMRF); if (key.not_empty()) { key.insert(" |"); const TRectype& rec_comres = _cache770.get(LF_COMUNI, key); set(0+offset, rec_comres.get(COM_DENCOM).left(40)); set(1+offset, rec_comres.get(COM_PROVCOM).left(2)); key = rec_anagr.get(use_comres ? ANA_INDRES : ANA_INDRF); if (key.not_empty()) key << ','; key << rec_anagr.get(use_comres ? ANA_CIVRES : ANA_CIVRF); key.cut(35); if (swapcap) { set(3+offset, key); set(2+offset, rec_anagr.get(use_comres ? ANA_CAPRES : ANA_CAPRF)); } else { set(2+offset, key); set(3+offset, rec_anagr.get(use_comres ? ANA_CAPRES : ANA_CAPRF)); } } return key.not_empty(); } bool TRecord770::fill_residenza(const TRectype& rec_anagr, int offset, int whichcom, bool swapcap) { bool use_comres; if (whichcom < 0) use_comres = rec_anagr.get(ANA_COMRF).empty(); else use_comres = whichcom ? TRUE : FALSE; const TDate data_var_df = rec_anagr.get(use_comres ? ANA_DVARSLORES : ANA_DVARDF); set(0+offset, data_var_df.month()); set(1+offset, data_var_df.year() % 100); return fill_comune(rec_anagr, whichcom, swapcap, 2+offset); } bool TRecord770::fill_e(const TRectype& rec) { TString80 key; // Stringa multiuso tipo_record('E'); key = rec.get(BSE_CODDIC); if (key.empty()) key = rec.get(BSE_CODDITTA); const TRectype& rec_nditte = _cache770.get(LF_NDITTE, key); if (rec_nditte.empty()) return error_box("Non esiste la ditta %s", (const char*)key); const char tipoa = rec_nditte.get_char(NDT_TIPOA); const long codan = rec_nditte.get_long(NDT_CODANAGR); key.cut(0); key << tipoa << '|' << rec_nditte.get(NDT_CODANAGR); const TRectype& rec_anagr = _cache770.get(LF_ANAG, key); if (rec_anagr.empty()) return error_box("Non esiste la persona %s", (const char*)key); set(3, rec_anagr.get(ANA_COFI)); // Codice fiscale del dichiarante if (tipoa == 'F') { fill_persona(rec_anagr, 9, 2); // 9 - 16 fill_residenza(rec_anagr, 17, -1, FALSE); // 17 - 22 set(23, rec_nditte.get(NDT_CODATTPREV)); fill_telefono(rec_anagr, 24); } else { set(9, rec_anagr.get(ANA_RAGSOC)); fill_residenza(rec_anagr, 25, 1, FALSE); fill_residenza(rec_anagr, 31, 0, FALSE); set(37, rec_nditte.get(NDT_CODATTPREV)); const TRectype& rec_anagiu = _cache770.get(LF_ANAGGIU, codan); set(38, rec_anagiu.get(ANG_STATOSOC)); set(39, rec_anagiu.get(ANG_NATGIU)); set(40, rec_anagiu.get(ANG_SITSOC)); fill_telefono(rec_anagr, 41); } // Rappresentante key = rec_nditte.get(NDT_RAPPR); if (key.not_empty()) { key.insert("F|"); const TRectype& rec_anagr = _cache770.get(LF_ANAG, key); if (!rec_anagr.empty()) { set(42, rec_anagr.get(ANA_COFI)); // Codice fiscale del dichiarante fill_persona(rec_anagr, 44, 0); // 44- 49 fill_comune(rec_anagr, -1, TRUE, 50); fill_telefono(rec_anagr, 54); } } TDecoder basebis(LF_BASEBIS, BSE_QCOMP); key = rec.get(BSE_TIPOQUA); key << '|' << rec.get(BSE_CODDITTA); key = basebis.decode(key); key.left_just(21); for (int q = 0; q < 21; q++) { const bool yes = key[q] > ' '; set(55+q, yes); } return TRUE; } // Assegna un rectype (serve solo per il quadro base) bool TRecord770::fill(const TRectype& rec) { bool ok = FALSE; switch(rec.num()) { case LF_BASE: ok = fill_e(rec); break; default: NFCHECK("Unsupported record assignment"); break; } return ok; } bool TRecord770::valid() const { char tipo = tipo_record(); bool ok = (tipo > ' ') && (strchr("AEFGHZ", tipo) != NULL); return ok; } TRecord770::TRecord770() : _buffer(TOTAL_SIZE, ' ') { } TRecord770::TRecord770(char tipo) : _buffer(TOTAL_SIZE, ' ') { tipo_record(tipo); } TRecord770::TRecord770(const TRecord770& rec) : _buffer(rec._buffer) { } TRecord770::TRecord770(const TRectype& rec) { fill(rec); } TRecord770::~TRecord770() { } /////////////////////////////////////////////////////////// // TTrasferimento770 /////////////////////////////////////////////////////////// bool TTrasferimento770::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 TTrasferimento770::close() { if (_in_stream) { delete _in_stream; _in_stream = NULL; } if (_out_stream) { delete _out_stream; _out_stream = NULL; } return TRUE; } bool TTrasferimento770::write(const TRecord770& rec) { bool ok = _out_stream != NULL; if (ok) (*_out_stream) << rec; return ok; } bool TTrasferimento770::read(TRecord770& rec) { bool ok = _in_stream != NULL && !_in_stream->eof(); if (ok) { (*_in_stream) >> rec; ok = rec.valid(); } return ok; } long TTrasferimento770::append_quadro(const char* quadro, long codditta, TProgind& pi) { TString80 str; str << "Trasferimento quadro " << quadro << " ditta " << codditta; pi.set_text(str); char tipo; int rpm; TForm770& frm = _trc770.form(quadro, tipo, rpm); long items = frm.trasfer(codditta, *this, tipo, rpm); return items; } bool TTrasferimento770::split(const char* path) { close(); long totale[4]; memset(totale, 0, sizeof(totale)); long records = fsize(_name) / TOTAL_SIZE; TRecord770 rec; if (records > 0) { open("", 'r'); TProgind pi(records, "Conteggio records da trasferire", FALSE, TRUE); while (read(rec)) { pi.addstatus(1); const int pos = rec.tipo_record() - 'E'; if (pos >= 0 && pos < 4) totale[pos]++; } records = totale[0]+totale[1]+totale[2]+totale[3]; } else return FALSE; 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 / TOTAL_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; } } TTrasferimento770 outfile(path, 'w'); // Compila record di testata rec.tipo_record('A'); if (magnetic) { rec.set(4, volumes); rec.set(5, volume); } const TDate data_emissione(TODAY); rec.set(6, data_emissione); rec.set(7, "77098"); rec.set_magnetic_support(magnetic); outfile << rec; // Scrive record testata // Azzera totali memset(totale, 0, sizeof(totale)); long written = 0; while (read(rec)) { const char tipo_rec = rec.tipo_record(); if (tipo_rec == 'A' || tipo_rec == 'Z') continue; const int pos = tipo_rec - 'E'; if (pos >= 0 && pos < 4) { rec.set_magnetic_support(magnetic); 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 rec.tipo_record('Z'); if (magnetic) { rec.set(4, volumes); rec.set(5, volume); rec.set_magnetic_support(magnetic); } rec.set(6, data_emissione); rec.set(7, "77098"); rec.set(8, written); for (int r = 0; r < 4; r++) rec.set(10+r, totale[r]); // Scrive record di coda outfile << rec; } return TRUE; } // Cancella il file void TTrasferimento770::remove() { close(); ::remove(_name); } TTrasferimento770::TTrasferimento770(const char* path, char mode) : _in_stream(NULL), _out_stream(NULL) { open(path, mode); } TTrasferimento770::~TTrasferimento770() { close(); } /////////////////////////////////////////////////////////// // main /////////////////////////////////////////////////////////// HIDDEN int anno_dic() { TConfig ini(CONFIG_STUDIO); return ini.get_int("AnnoDic"); } class TTransfer770_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& of, TField_event fe, long jolly); public: TTransfer770_msk(); virtual ~TTransfer770_msk() { } }; bool TTransfer770_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; } TTransfer770_msk::TTransfer770_msk() : TAutomask("777100a") { set(F_ANNO, anno_dic()); } class TTransfer770_app : public TSkeleton_application { protected: virtual void main_loop(); }; void TTransfer770_app::main_loop() { TTransfer770_msk m; while (m.run() == K_ENTER) { TFilename tmp; tmp.tempdir(); TTrasferimento770 t(tmp, 'w'); TRecord770 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); rec = base; t << rec; // Append quadro base 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("SK", codditta, pi); t.append_quadro("SL", codditta, pi); t.append_quadro("SP", codditta, pi); t.append_quadro("SQ", 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(); } _trc770.destroy(); } int m777100(int argc, char* argv[]) { TTransfer770_app app; app.run(argc, argv, "Invio"); return 0; }