#include #include #include #include #include #include #include #include #include #include #include "velib.h" #include "../cg/cgsaldac.h" #include "ve7100a.h" class TContabil_tsys : public TContabilizzazione // velib04b { ofstream * _output_file; TConfig * _conf; protected: virtual error_type write_all(TDocumento& doc, TMovimentoPN & movimento); public: void open(); void close(); void format_num(real num, int len, TString & s); void format_signed(real num, int len, TString & s); TContabil_tsys(const char* cod, TConfig * c = NULL) : TContabilizzazione(cod), _output_file(NULL), _conf(c) {} TContabil_tsys(const TRectype& rec, TConfig * c = NULL) : TContabilizzazione(rec), _output_file(NULL), _conf(c) {} virtual ~TContabil_tsys(); }; void TContabil_tsys::open() { TFilename outname(_conf->get("OutputFile")); if (xvt_fsys_is_removable_drive(outname)) message_box("Inserisci un disco vuoto nel drive %c e premi Ok", outname[0]); _output_file = new ofstream(outname, ios::binary|ios::app); } void TContabil_tsys::close() { TFilename outname(_conf->get("OutputFile")); delete _output_file; _output_file = NULL; ifstream input_file(outname); for (char c = input_file.get();!input_file.eof();c = input_file.get()) if (c == '!') { message_box("Carattere non valido nel file"); break; } } void TContabil_tsys::format_num(real num, int len, TString & s) { TString format; format.fill('@', len); s = num.string(format); } void TContabil_tsys::format_signed(real num, int len, TString & s) { format_num(num, len - 1, s); s << (num.sign() >= 0 ? '+' : '-'); } TContabil_tsys::~TContabil_tsys() { if (_output_file != NULL) delete _output_file; } void check_len(const char * step, TString& row, int part_len, bool reset_counter = FALSE) { #ifdef DBG static int expected_len = 0; if (reset_counter) expected_len = 0; expected_len += part_len; const int len = row.len(); if (len != expected_len) { const TString last_part(row.right(part_len)); error_box("Passo %s Stringa %s - lunghezza record %d errata (attesa %d)", step, (const char *) last_part, len, expected_len); } #endif } error_type TContabil_tsys::write_all(TDocumento& doc, TMovimentoPN_VE & movimento) // Scrive il movimento e le scadenze, gestendo la rinumerazione se il movimento e' gia presente { // N.B: _error non viene settato, per non stampare il messaggio di errore 2 volte. // basta solo ritornare qualcosa di != da no_error, per evitare le operazioni successive // a write_all TString row(4500); TRectype& head = movimento.lfile().curr(); const int iva_items = movimento.iva_items(); const int cg_items = movimento.cg_items(); TCurrency c(ZERO); const real dec = c.decimals(); const real molt = pow(10.0, dec); if (test_swap()) { const real totdoc = -head.get_real(MOV_TOTDOC); head.put(MOV_TOTDOC, totdoc); for (int i = iva_items - 1 ; i >= 0; i--) { TRectype & rec_iva = movimento.iva(i); const real imponibile = -rec_iva.get_real(RMI_IMPONIBILE); const real imposta = -rec_iva.get_real(RMI_IMPOSTA); rec_iva.put(RMI_IMPONIBILE, imponibile); rec_iva.put(RMI_IMPOSTA, imposta); } } TString work(256); format_num(real(_conf->get("CodDitta")), 5, work); row << work << "10"; TString key; key << doc.get(DOC_TIPOCF) << "|"; key << doc.get(DOC_CODCF); const TRectype & rec = cache().get(LF_CLIFO, key); const bool pers_fisica = rec.get("TIPOPERS") == "F"; work = rec.get("RAGSOC"); int posnome = 0; if (pers_fisica) { TString cogn(work.mid(31)); work.left(30); work.trim(); posnome = work.len() + 1; work << " " << cogn; } row << work.sleft(32).rpad(32); work = rec.get("INDCF"); TString80 civ(rec.get("CIVCF")); if (civ.not_empty()) work << ", " << civ; row << work.sleft(30).rpad(30) << rec.get("CAPCF"); work = rec.get("LOCALITACF"); key = rec.get("STATOCF"); key << "|" << rec.get("COMCF"); const TRectype & com = cache().get(LF_COMUNI, key); work << " " << com.get("DENCOM"); work.trim(); row << work.sleft(25).rpad(25); row << com.get("PROVCOM").sleft(2).rpad(2); row << rec.get("COFI").sleft(16).rpad(16); format_num(real(rec.get("PAIV")), 11, work); row << work; row << (pers_fisica ? "S" : "N"); format_num((real)posnome, 2, work); key = head.get(MOV_CODCAUS); const TRectype & caus = cache().get(LF_CAUSALI, key); row << work << key << caus.get("DESCR").sleft(15).rpad(15); row << head.get(MOV_DESCR).sleft(18).rpad(18); work = doc.get_date(DOC_DATADOC).string(brief); row << work.left(2); row << work.mid(3, 2); row << work.mid(6); format_num(real(doc.get(DOC_NDOC)), 5, work); row << work << "00"; format_num(real(doc.get(DOC_NDOC)), 6, work); row << work << doc.get(DOC_ANNO).right(2); for (int i = 0; i < 8 ;i++) { if (i < iva_items) { TRectype & rec_iva = movimento.iva(i); format_signed(rec_iva.get_real(RMI_IMPONIBILE) * molt, 12, work); row << work; key = rec_iva.get(RMI_CODIVA); const TRectype & tab_iva = cache().get("%IVA", key); format_num(tab_iva.get_real("CODTAB"), 3, work); row << work; format_num(ZERO, 1, work); row << work; format_signed(rec_iva.get_real(RMI_IMPOSTA) * molt, 11, work); row << work; } else { format_signed(ZERO, 12, work); row << work; format_num(ZERO, 3, work); row << work; format_num(ZERO, 1, work); row << work; format_signed(ZERO, 11, work); row << work; } } format_signed(head.get_real(MOV_TOTDOC) * molt, 12, work); row << work; for (i = 0; i < 8 ;i++) { if (i + 1 < cg_items) { TRectype & rec_cg = movimento.cg(i + 1); const int gruppo = rec_cg.get_int(RMV_GRUPPO); const int conto = rec_cg.get_int(RMV_CONTO); const long sottoconto = rec_cg.get_long(RMV_SOTTOCONTO); const real codconto = (gruppo % 100) * 100000 + (conto % 100) * 1000 + (sottoconto % 1000); format_num(codconto, 7, work); row << work; format_signed(rec_cg.get_real(RMV_IMPORTO) * molt, 12, work); row << work; } else { format_num(ZERO, 7, work); row << work; format_signed(ZERO, 12, work); row << work; } } int padding_rows = 80; real pagato = doc.get_real(DOC_IMPPAGATO); if (pagato != ZERO) { padding_rows = 78; const int gruppo = _conf->get_int("CassGruppo"); const int conto = _conf->get_int("CassConto"); const long sottoconto = _conf->get_long("CassaSottoC"); const real codconto = (gruppo % 100) * 100000 + (conto % 100) * 1000 + (sottoconto % 1000); char sez = movimento.cg(0).get_char(RMV_SEZIONE); format_num(codconto, 7, work); row << work << sez; format_signed(pagato * molt, 12, work); row << work; work = ""; work.spaces(18); row << work; format_num(real(doc.get(DOC_NDOC)), 6, work); row << work << doc.get(DOC_ANNO).right(2); row << "9999999" << sez == 'D' ? 'A' : 'D'; format_signed(pagato * molt, 12, work); row << work; work = ""; work.spaces(18); row << work; format_num(real(doc.get(DOC_NDOC)), 6, work); row << work << doc.get(DOC_ANNO).right(2); } for (i = 0; i < padding_rows ;i++) { format_num(ZERO, 7, work); row << work << " "; format_signed(ZERO, 12, work); row << work; work = ""; work.spaces(18); row << work; format_num(ZERO, 6, work); row << work; format_num(ZERO, 2, work); row << work; check_len("Filler", row, 46); } if (row.len() != 4248) { error_box("Documento %s - lunghezza record %d errata", (const char *)doc.get(DOC_NDOC), row.len()); return generic_error; } else *_output_file << ((const char *) row); format_num(real(_conf->get("CodDitta")), 5, row); row << "11" ; check_len("Dati intra", row, 7, TRUE); format_signed(ZERO, 14, work); row << zeros.sleft(7) << spaces.sleft(3) << work; check_len("Dati intra", row, 24); for (i = 0 ; i < 20 ; i++) { row << spaces.sleft(8); format_signed(ZERO, 12, work); row << work << work << spaces.sleft(1) << work << work << work; check_len("Dati intra", row, 69); row << spaces.sleft(2) << zeros.sleft(9) << spaces.sleft(4) ; check_len("Dati intra", row, 15); } row << zeros.sleft(12) << zeros.sleft(3) << zeros.sleft(22) << zeros.sleft(4) << spaces.sleft(8) << zeros.sleft(24); check_len("770", row, 73); row << spaces.sleft(28) << zeros.sleft(10); check_len("770", row, 38); int len = row.len(); TRectype cp = cache().get("%CPG", doc.get("CODPAG")); TString16 codpag(cp.get("I9")); // if (codpag.empty()) // codpag = doc.get("CODPAG"); codpag = codpag.sleft(3).lpad(3, '0'); row << codpag; work = doc.get("CODABIA").sleft(5).rpad(5); work << doc.get("CODCABA").sleft(5).rpad(5); const TRectype & ban = cache().get("BAN", work); row << work << ban.get("S0").sleft(30).rpad(30) << zeros.sleft(6); check_len("Riba", row, 49); TPagamento & pag = doc.pagamento(); const int nrate = pag.n_rate(); format_num(nrate, 2, work); row << work; format_signed(head.get_real(MOV_TOTDOC) * molt, 12, work); row << work; check_len("Riba", row, 14); TDate data_inizio = doc.get_date(DOC_DATAINSC); if (!data_inizio.ok()) data_inizio = doc.get_date(DOC_DATADOC); pag.set_inizio(data_inizio); pag.set_total(head.get_real(MOV_TOTDOC), ZERO, ZERO); pag.set_rate_auto(); for (i = 0 ; i < 12 ; i++) { if (i < nrate) { format_num(i + 1, 2, work); row << work; TDate dsc = pag.data_rata(i); work = dsc.string(brief); row << work.left(2); row << work.mid(3, 2); row << work.mid(6); const int tipo = pag.tipo_rata(i); row << rata_types[tipo]; check_len("Riba", row, 9); real imprata = pag.importo_rata(i); format_signed(imprata * molt, 12, work); if (work[11] == '-') work[11] == '+'; row << work; format_signed(doc.bolli(imprata, AUTO_DECIMALS, _netto) * molt, 12, work); if (work[11] == '-') work[11] == '+'; row << work; check_len("Riba", row, 24); static char tipocf = doc.get_char(DOC_TIPOCF); bool avere = (tipocf == 'C' && imprata >= ZERO) || (tipocf == 'F' && imprata < ZERO); row << (avere ? "A" : "D") << "0"; check_len("Riba", row, 2); } else { row << "000000000"; format_signed(ZERO, 12, work); row << work << work << " 0"; check_len("Riba", row, 35); } } len = row.len(); row << spaces.left(1943); if (row.len() != 4248) { error_box("Documento %s - lunghezza record %d errata", (const char *)doc.get(DOC_NDOC), row.len()); return generic_error; } else *_output_file << ((const char *) row); inc_processed_docs(); return no_error; } // TContabil_tsys_app // Applicazione di contabilizzazione documenti class TContabil_tsys_app : public TApplication { TString16 _cod_el; // codice elaborazione immesso TDate _data_reg; // data di registrazione immessa TDate _data_ini; // data di inizio intervallo TDate _data_fine; // data di fine intervallo bool _auto_data; // se TRUE prende in automatico la data di registrazione dalla data documento TMask *_msk; // maschera di selezione dati TArray_sheet *_num_sheet; // Array sheet selezionabile dei codici numerazione TString_array _tipi_doc; // Array di stringhe contenente i tipi documenti da elaborare protected: // TApplication // Contabilizza i documenti void contabilize(TConfig & c); // Le 4 seguenti non hanno bisogno di commenti virtual bool menu(MENU_TAG mt); virtual bool create(); virtual bool destroy(); virtual void on_config_change(); // Handler del codice elaborazione differita static bool handle_cod_eld(TMask_field& f, KEY k); // Handler dell'intervallo di date static bool handle_data_range(TMask_field& f, KEY k); // Handler della data di registrazione static bool handle_data_reg(TMask_field& f, KEY k); // Handler del pulsante di selezione codici numerazione static bool handle_select(TMask_field& f, KEY k); // Ritorna il TArray_sheet contenente le selezioni sui codici numerazione // Costruisce lo sheet dei codici numerazione void build_num_sheet(); TArray_sheet* get_num_sheet() const { return _num_sheet; } // Coontrolla se lo stato ed il tipo del documento sono validi e rispettano la selezione bool doc_tipo_stato_ok(const TRectype& doc); public: TContabil_tsys_app() {_msk = NULL; _num_sheet = NULL;} virtual ~TContabil_tsys_app() { } }; inline TContabil_tsys_app& app() { return (TContabil_tsys_app&) main_app(); } bool TContabil_tsys_app::handle_data_range(TMask_field& f, KEY k) { if (k==K_ENTER && f.dirty()) { TMask& m = f.mask(); TDate da(m.get_date(F_DATA_INI)); TDate a(m.get_date(F_DATA_FIN)); if (a < da) { f.error_box("La data di inizio deve essere minore della data di fine."); return FALSE; } } return TRUE; } bool TContabil_tsys_app::handle_data_reg(TMask_field& f, KEY k) { if (k==K_ENTER && f.dirty()) { TMask& m = f.mask(); TDate data_reg(f.get()); TDate da(m.get_date(F_DATA_INI)); if (data_reg < da) { f.error_box("La data di registrazione non puo' essere minore della data di inizio."); return FALSE; } } return TRUE; } bool TContabil_tsys_app::handle_cod_eld(TMask_field& f, KEY k) { if (f.to_check(k) && k == K_TAB) // se e' cambiato ricostruisce anche lo sheet dei codici numerazione { app()._cod_el = f.get(); // aggiorna il codice elaborazione per la build_num_sheet() f.mask().disable(DLG_OK); app().build_num_sheet(); } return TRUE; } bool TContabil_tsys_app::handle_select(TMask_field& f, KEY k) { if (k == K_SPACE) { TMask& m = f.mask(); TArray_sheet* s = app().get_num_sheet(); if (s->run()) { if (s->checked() != 0) // Hai selezionato qualcosa ? m.enable(DLG_OK); // allora abilita il pulsante di conferma else m.disable(DLG_OK); } } return TRUE; } void TContabil_tsys_app::build_num_sheet() { _num_sheet->destroy(); _tipi_doc.destroy(); TTable num("%NUM"); TString s1,s2,s3; TContabil_tsys* cont = new TContabil_tsys(_cod_el); if (!cont->empty()) { TToken_string t; TString16 tipo; for (int i=0;itipo_iniziale(i); if (tipo.not_empty()) { t = tipo; t.add(cont->stato_iniziale(i)); // Stato iniziale _tipi_doc.add(t); // Aggiunge questo tipo documento alla lista } } long pos=0l; for (num.first();num.good();num.next(),pos++) // scorre tutte le numerazioni possibili { TToken_string t,z; t.add(" "); t.add(num.get("CODTAB")); t.add(num.get("S0")); _num_sheet->add(t); s2 = num.get("S2"); // reperisce i tipi documento validi per questa numerazione for (int x = 0; x <= s2.len(); x += 4) z.add(s2.mid(x,4)); bool found = FALSE; for (int i = _tipi_doc.last(); !found && i >= 0; i--) found |= z.find(((TToken_string &)_tipi_doc[i]).get(0)) >= 0; if (found) _num_sheet->enable_row(pos); else _num_sheet->disable_row(pos); } } delete cont; } bool TContabil_tsys_app::doc_tipo_stato_ok(const TRectype& doc) // Verifica che il tipo documento corrente esista tra i tipi previsti dalla elaborazione // differita selezionata { bool found = FALSE; const TString16 tipo = doc.get(DOC_TIPODOC); const char stato = doc.get_char(DOC_STATO); const int items = _tipi_doc.items(); for (int i=0;iset_handler(F_CODICE_ELAB,handle_cod_eld); _msk->set_handler(F_DATA_INI,handle_data_range); _msk->set_handler(F_DATA_FIN,handle_data_range); //_msk->set_handler(F_DATA_REG,handle_data_reg); _msk->set_handler(DLG_USER,handle_select); _num_sheet = new TArray_sheet(-1,-1,-4,-4,"Codici numerazione", "@1|Cod. numerazione|Descrizione@50"); dispatch_e_menu(BAR_ITEM(1)); return TRUE; } bool TContabil_tsys_app::destroy() { if (_msk) delete _msk; if (_num_sheet) delete _num_sheet; return TApplication::destroy(); } bool TContabil_tsys_app::menu(MENU_TAG mt) { TConfig c(CONFIG_STUDIO, "TeamSystem"); _msk->set(F_OUTPUT, c.get("OutputFile", NULL, -1, "a:\\trafat")); _msk->set(F_CODDITTA, c.get("CodDitta")); _msk->set(F_GRUPPO, c.get("CassGruppo")); _msk->set(F_CONTO, c.get("CassConto")); _msk->set(F_SOTTOCONTO, c.get("CassaSottoC")); while (_msk->run() == K_ENTER) { _cod_el = _msk->get(F_CODICE_ELAB); _data_ini = _msk->get_date(F_DATA_INI); _data_fine = _msk->get_date(F_DATA_FIN); _data_reg = _data_fine; c.set("OutputFile", _msk->get(F_OUTPUT)); c.set("CodDitta", _msk->get(F_CODDITTA)); c.set("CassGruppo", _msk->get(F_GRUPPO)); c.set("CassConto", _msk->get(F_CONTO)); c.set("CassaSottoC", _msk->get(F_SOTTOCONTO)); _auto_data = TRUE; contabilize(c); } return FALSE; } void TContabil_tsys_app::contabilize(TConfig &c) { TRelation doc_rel(LF_DOC); TRectype da(LF_DOC); TRectype a(LF_DOC); const long items = _num_sheet->items(); int year_from = _data_ini.year(); int year_to = _data_fine.year(); bool ok = TRUE; TString16 codnum; TString msg,filt_expr; TToken_string nums; TContabil_tsys cont(_cod_el, &c); cont.open(); // Compone la lista dei documenti da elaborare cont.set_auto(_auto_data); // Setta il flag per il settaggio automatico della data di registrazione del movimento da.put("DATADOC",_data_ini); da.put("PROVV","D"); da.put("ANNO",year_from); a.put("DATADOC",_data_fine); a.put("PROVV","D"); a.put("ANNO",year_to); filt_expr << "("; for (long i=0L; ichecked(i)) // Costruisce una espressione sul codice numerazione: "CODNUM="x0" || CODNUM="x1" || ..." { codnum = _num_sheet->row(i).get(1); filt_expr << "(CODNUM=\""; filt_expr << codnum << "\")||"; nums.add(codnum); } filt_expr.rtrim(2); filt_expr << ")"; // Cursore complessivo con limiti di data (chiave 3). Viene sfruttata l'ottimizzazione // sulla costruzione dei cursori nel caso i campi presenti nell'espressione siano campi // chiave, nel nostro caso CODNUM soddisfa i requisiti. TCursor doc_cur(&doc_rel,filt_expr,3,&da,&a); const long cur_items = doc_cur.items(); // Scorre tutti i documenti che rientrano nell'intervallo selezionato if (cur_items == 0) { warning_box("Non vi sono documenti da contabilizzare per le numerazioni selezionate."); return; } doc_cur.freeze(); msg = "Selezione documenti dal "; msg << _data_ini.string() << " al "; msg << _data_fine.string(); TLista_documenti lista_in,lista_out; if (cur_items > 0) // if inutile tanto per provocare la chiusura della TProgind { TProgind p(cur_items,msg,FALSE,TRUE); const TRectype& cur_rec = doc_cur.curr(); for (doc_cur = 0; doc_cur.pos() < cur_items; ++doc_cur) { p.addstatus(1); // controlla che il tipo documento e lo stato siano coerenti con la ELD selezionata if (nums.find(cur_rec.get("CODNUM")) >= 0 && doc_tipo_stato_ok(cur_rec)) { TDocumento* doc = new TDocumento; if (doc->read(doc_cur.curr()) == NOERR) // legge il documento lista_in.add(doc); // Viene aggiunto alla lista dei documenti else delete doc; } } } if (cont.elabora(lista_in,lista_out,_data_reg)) { TProgind p(cur_items,"Aggiornamento stato documenti",FALSE,TRUE); const TRectype& cur_rec = doc_cur.curr(); TDocumento* doc = new TDocumento; for (doc_cur = 0; doc_cur.pos() < cur_items; ++doc_cur) { p.addstatus(1); // controlla che il tipo documento e lo stato siano coerenti con la ELD selezionata if (nums.find(cur_rec.get("CODNUM")) >= 0 && doc_tipo_stato_ok(cur_rec)) { if (doc->read(doc_cur.curr()) == NOERR) // legge il documento cont.change_doc_status(*doc); } } delete doc; if (cont.processed_docs() > 0L) message_box("Totale documenti trasferiti: %ld", cont.processed_docs()); } cont.close(); xvt_statbar_set(""); } int ve7100 (int argc, char **argv) { TContabil_tsys_app a; a.run(argc,argv,"Trasferimento documenti a Team System"); return TRUE; }