#include #include #include #include #include #include #include #include #include #include "pt0195100a.h" #include "../cg/cglib01.h" #include "../ve/velib.h" #include "clifo.h" #include "comuni.h" //--------------------------------- // TAutomask //--------------------------------- class TImpDoc0195_mask : public TAutomask { protected: bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TImpDoc0195_mask(); virtual ~TImpDoc0195_mask(){}; }; TImpDoc0195_mask::TImpDoc0195_mask() :TAutomask ("pt0195100a") { } bool TImpDoc0195_mask::on_field_event(TOperable_field& f, TField_event e, long jolly) { switch (f.dlg()) { //giochetto per avere la lista dei files validi nella directory di trasferimento! case F_NAME: if (e == fe_button) { TArray_sheet as(-1, -1, 72, 20, TR("Selezione file"), "File@32"); TFilename path = get(F_PATH); path.add("t*.txt"); //files delle testate list_files(path, as.rows_array()); TFilename name; FOR_EACH_ARRAY_ROW(as.rows_array(), i, row) { name = *row; *row = name.name(); } if (as.run() == K_ENTER) { f.set(as.row(as.selected())); } } break; default: break; } return true; } //-------------------------------- // TFile_text //-------------------------------- class TImpDoc0195_file: public TFile_text { protected: virtual void validate(TCursor& cur,TRecord_text &rec, TToken_string &val, TString& str); public: TImpDoc0195_file(const TString& file_name, char tipo); virtual ~TImpDoc0195_file() { } }; TImpDoc0195_file::TImpDoc0195_file(const TString& file_name, char tipo) : TFile_text(file_name, tipo == 'T' ? "pt0195100t.ini" : "pt0195100d.ini") { } void TImpDoc0195_file::validate(TCursor& cur,TRecord_text &rec, TToken_string &s, TString& str) { const TString code(s.get(0)); TString valore = str; if (code == "_UPPERCASE") { valore.upper(); } else NFCHECK("Macro non definita: %s", (const char *)code); str = valore; } //---------------------------------- // TSkeleton_application //---------------------------------- class TImpDoc0195 : public TSkeleton_application { TImpDoc0195_mask* _msk; TImpDoc0195_file* _trasfile; TLocalisamfile* _clienti; TTable* _banche; TConfig* _configfile; TRelation* _rel; TCursor* _cur; TProgind* _prog; long _numreg; virtual const char * extra_modules() const {return "ba";} protected: bool transfer_testata(); bool transfer_dettaglio(); void update_bank(const TString& abi, const TString& cab, const TString& descr); void split_phone_number(const TString& numerone, TString& prefisso, TString& numero); bool decifra_codici(const TRecord_text& curr, TString& codnum, TString& tipodoc) const; public: virtual bool create(); virtual bool destroy(); virtual void main_loop(); TImpDoc0195() {} }; TImpDoc0195& app() { return (TImpDoc0195&) main_app(); } bool TImpDoc0195::create() { _configfile = new TConfig("pt0195conf.ini"); _msk = new TImpDoc0195_mask(); _clienti = new TLocalisamfile(LF_CLIFO); _banche = new TTable("%BAN"); return TSkeleton_application::create(); } bool TImpDoc0195::destroy() { delete _banche; delete _clienti; delete _msk; delete _configfile; return TApplication::destroy(); } void TImpDoc0195::update_bank(const TString& abi, const TString& cab, const TString& descr) { if (!abi.blank()) { _banche->put("CODTAB", abi); if(_banche->read() != NOERR) { _banche->put("CODTAB", abi); _banche->put("S0", descr); _banche->write(); } if (!cab.blank()) { TString16 abicab = abi; abicab << cab; _banche->put("CODTAB", abicab); if(_banche->read() != NOERR) { _banche->put("CODTAB", abicab); _banche->put("S0", descr); _banche->write(); } } } } void TImpDoc0195::split_phone_number(const TString& numerone, TString& prefisso, TString& numero) { const int slash = numerone.find('/'); if (slash > 0 && slash <= 10) { prefisso = numerone.left(slash); numero = numerone.mid(slash+1); } else { prefisso.cut(0); numero = numerone; } } bool TImpDoc0195::decifra_codici(const TRecord_text& curr, TString& codnum, TString& tipodoc) const { //metodo cervellotico per decifrare la chiave numerazion-tipo documento TString4 codice(curr.get(0)); codice << curr.get(1); TToken_string coppia_codici = _configfile->get(codice, "CODNUM"); const bool ok = !coppia_codici.empty_items(); if (ok) { codnum = coppia_codici.get(0); //codnum doc=primo elemento della tokenstring tipodoc = coppia_codici.get(1); //tipo doc=secondo elementodella tokenstring } else warning_box(TR("Non esiste una numerazione in configurazione per il codice %s"), (const char*)codice); return ok; } bool TImpDoc0195::transfer_testata() { // file da trasferire (testata) // costruire il nome del file con path + T + data formattata come indicato in analisi TFilename file = _msk->get(F_PATH); file.add(_msk->get(F_NAME)); file.ext("txt"); _trasfile = new TImpDoc0195_file(file, 'T'); _trasfile->open(file,'r'); const long dimension = fsize(file); TProgind pi(dimension,"Importazione testate, clienti e banche in corso..."); int err = NOERR; TRecord_text curr; curr.set_type("T"); TString4 codnum, tipodoc; while (_trasfile->read(curr) == NOERR && !pi.iscancelled() && err == NOERR) { pi.setstatus(_trasfile->read_file()->tellg()); if (!decifra_codici (curr, codnum, tipodoc)) continue; const long numdoc = atol(curr.get(2)); TString16 tempdata = curr.get(3); tempdata.strip("-"); const TDate datdoc(tempdata); const long clicod = atol(curr.get(5)); // creo il documento, se esiste cancello le righe perche' le ricreo successivamente TDocumento* doc = new TDocumento('D', datdoc.year(), codnum, numdoc); const bool isnew = doc->rows() == 0; if (!isnew) doc->body().destroy_rows(); // Parametri di testata da prendere dal conf.ini TAssoc_array& parametri_testata = _configfile->list_variables("HEAD"); //assegna ai campi della testata i valori letti nel paragrafo [HEAD] del file di configurazione FOR_EACH_ASSOC_STRING(parametri_testata, ho, k, wstr) { doc->put(k, wstr); } //azzera il raggruppamento effetti se nota di credito if (curr.get(1) == "C") doc->put(DOC_RAGGREFF, ""); doc->put(DOC_TIPODOC, tipodoc); doc->put(DOC_DATADOC, datdoc); doc->put(DOC_STATO, 1); doc->put(DOC_TIPOCF, "C"); doc->put(DOC_CODCF, clicod); TString4 codpag = curr.get(6); doc->put(DOC_CODPAG, codpag); const TPagamento pag(codpag); if (pag.n_rate() == 0) doc->put(DOC_RAGGREFF, ""); else { const TTipo_pag tipopag = (TTipo_pag)pag.tipo_rata(0); if (tipopag != _ric_ban) doc->put(DOC_RAGGREFF, ""); } TString4 valuta = curr.get(7); if (is_firm_value(valuta)) valuta.cut(0); doc->put(DOC_CODVAL, valuta); // memorizzo il codiceiva in CODIVA (campo virtuale!) per metterla successivamente nelle righe doc->put("CODIVA", curr.get(10)); //aggiunge o aggiorna il record sul file dei clifo _clienti->put(CLI_TIPOCF, "C"); _clienti->put(CLI_CODCF, clicod); _clienti->setkey(1); //chiave 1 di scansione del file const bool client_found = _clienti->read() == NOERR; //aggiunge tutti i campi passati via testata documento //le prime 2 righe vanno rifatte per evitare che venga vuotato il record in caso di.. //..fallimento della read() _clienti->put(CLI_TIPOCF, "C"); _clienti->put(CLI_CODCF, clicod); _clienti->put(CLI_RAGSOC, curr.get(13)); _clienti->put(CLI_INDCF, curr.get(14)); // azzeramento del civico chiesto da Benetti in data 01/06/2007 _clienti->zero(CLI_CIVCF); _clienti->put(CLI_LOCCF, curr.get(15)); const TString8 cap = curr.get(17).left(5); _clienti->put(CLI_CAPCF, cap); TString80 comune = curr.get(16); comune.rtrim(3); comune.trim(); const TString& codcom = cap2comune(cap, comune); if (codcom.blank()) _clienti->put(CLI_LOCCF, comune); _clienti->put(CLI_COMCF, codcom); const TString& cf = curr.get(19); _clienti->put(CLI_COFI, cf); //codice fiscale const TString& stato_e_piva = curr.get(20); _clienti->put(CLI_STATOPAIV, stato_e_piva.left(2)); _clienti->put(CLI_PAIV, stato_e_piva.mid(2)); //partita iva _clienti->put(CLI_CODPAG, codpag); const TString8 codabi = curr.get(21).left(5); _clienti->put(CLI_CODABI, codabi); doc->put(DOC_CODABIA, codabi); const TString8 codcab = curr.get(22).left(5); _clienti->put(CLI_CODCAB, codcab); doc->put(DOC_CODCABA, codcab); const TString80 desban = curr.get(24); //e adesso tocca alle banche... update_bank(codabi, codcab, desban); //e poi i telefoni.. TString16 prefisso; TString80 numero; split_phone_number(curr.get(25), prefisso, numero); _clienti->put(CLI_PTEL, prefisso); _clienti->put(CLI_TEL, numero); split_phone_number(curr.get(26), prefisso, numero); _clienti->put(CLI_PTEL2, prefisso); _clienti->put(CLI_TEL2, numero); split_phone_number(curr.get(27), prefisso, numero); _clienti->put(CLI_PTEL3, prefisso); _clienti->put(CLI_TEL3, numero); _clienti->put(CLI_MAIL, curr.get(31)); //scrive 'sto benedetto file dei clienti! if (client_found) //se trova il record con il codice cliente immesso lo riscrive.. _clienti->rewrite(); else //..se invece e' nuovo lo scrive _clienti->write(); //ed infine scrive i docs if (isnew) doc->write(); else doc->rewrite(); if (doc != NULL) delete doc; } _trasfile->close(); delete _trasfile; return true; } bool TImpDoc0195::transfer_dettaglio() { // numero ultimo documento long last_doc = 0L; int last_year = 0; TString4 last_codnum; //flag di almeno 1 riga trasferita per questo documento bool transferred_row = false; TString4 codnum, tipodoc; // file da trasferire (dettaglio) // costruire il nome del file con path + D + data formattata come indicato in analisi TFilename file = _msk->get(F_PATH); file.add("D"); file << _msk->get(F_NAME).mid(1); file.ext("txt"); _trasfile = new TImpDoc0195_file(file, 'D'); _trasfile->open(file,'r'); const long dimension = fsize(file); TProgind pi(dimension,"Importazione dettaglio in corso..."); TToken_string excl_art = _configfile->get("XCL_ART", "MAIN"); TDocumento* doc = NULL; int err = NOERR; TRecord_text curr; curr.set_type("D"); while (_trasfile->read(curr) == NOERR && !pi.iscancelled() && err == NOERR) { pi.setstatus(_trasfile->read_file()->tellg()); //decifra i codici numerazione e tipo documento if (!decifra_codici (curr, codnum, tipodoc)) continue; const long numdoc = atol(curr.get(2)); // non sappiamo nulla sull'ordinamento del file dettaglio, qundi presuppongo // che le righe possano essere anche disordinate // se non lo sono si puo' migliorare di molto il ciclo di lettura // e non creare tutte le volte il documento TString16 tiporiga = curr.get(5); tiporiga.trim();tiporiga.upper(); TString80 dcontod = curr.get(6); dcontod.trim(); dcontod.upper(); TString80 dcontoc = curr.get(8); dcontoc.trim(); dcontoc.upper(); if (numdoc != last_doc) { if (transferred_row == false && last_doc > 0) { TDocumento doc_to_remove('D', last_year, last_codnum, last_doc); doc_to_remove.remove(); } TString16 tempdata = curr.get(3); tempdata.strip("-"); const TDate datdoc(tempdata); last_year = datdoc.year(); last_codnum = codnum; last_doc = numdoc; transferred_row = false; } // in CODART ci va messo il conto esteso della riga di tipo RICAVO const TString80 codart = dcontod[0] == 'C' ? dcontoc : dcontod; //vanno passate solo le righe di tipo RICAVO // righe da passare, verificare la condizione (potrebbe essere ||) if (tiporiga == "RICAVI" && dcontod != "XXXXXXXXXX" && dcontoc != "XXXXXXXXXX" && excl_art.get_pos(codart) < 0) { //costruisce il documento della riga corrente doc = new TDocumento('D', last_year, codnum, numdoc); // cre nuova riga TRiga_documento& rdoc = doc->new_row("01"); // Crea una riga // Parametri di riga da prendere dal conf.ini TAssoc_array& parametri_riga = _configfile->list_variables("ROW"); //assegna ai campi della rigaa i valori letti nel paragrafo [ROW] del file di configurazione FOR_EACH_ASSOC_STRING(parametri_riga, ho, k, wstr) { rdoc.put(k, wstr); } rdoc.put(RDOC_GENERATA, "X"); rdoc.put(RDOC_DESCR, "Riga generata"); rdoc.put(RDOC_CODART, codart); //riempimento di CODARTMAG const TRectype& rec_anamag = cache().get(LF_ANAMAG, codart); if (!rec_anamag.empty()) rdoc.put(RDOC_CODARTMAG, codart); rdoc.put(RDOC_CHECKED, "X"); rdoc.put(RDOC_QTA, "1"); rdoc.put(RDOC_CODIVA, doc->get("CODIVA")); real prezzo = curr.get(7); prezzo /= CENTO; rdoc.put(RDOC_PREZZO, prezzo); //riscrive l'intero documento per aggiornare la testata con i totali (mitico!) doc->rewrite(); //accoppa il simpatico ma ora inutile doc provvisoriamente creato e sfruttato if (doc != NULL) delete doc; //aggiorna il booleano di trasferimento righe transferred_row = true; } } //rimuove eventuale ultimo documento non valido if (transferred_row == false && last_doc > 0) { TDocumento doc_to_remove('D', last_year, last_codnum, last_doc); doc_to_remove.remove(); } _trasfile->close(); delete _trasfile; return true; } void TImpDoc0195::main_loop() { KEY tasto; _msk->set(F_PATH, _configfile->get("PATH", "MAIN")); _msk->set(F_NAME, _configfile->get("NAME", "MAIN")); tasto = _msk->run(); if (tasto == K_ENTER) { _configfile->set("PATH", _msk->get(F_PATH), "MAIN"); _configfile->set("NAME", _msk->get(F_NAME), "MAIN"); if (transfer_testata()) { if (transfer_dettaglio()) { message_box(TR("Trasferimento documenti completato")); } } } } int pt0195100 (int argc, char* argv[]) { TImpDoc0195 main_app; main_app.run(argc, argv, TR("Importazione documenti Volvo")); return TRUE; }