#include #include #include #include #include #include #include #include #include #include #include "../ce/ammce.h" #include "../ce/cespi.h" #include "../ce/salce.h" #include "../cg/cg2103.h" #include "../cg/cglib01.h" #include "lv4.h" #include "lv4100.h" #include "lv4500a.h" #include "lvlib.h" #define T_N "N" #define T_X "X" ///////////////////////////////// //// LAUNDRY_RECORDSET //// ///////////////////////////////// //Classe TLaundry_recordset: è un TAS400_recordset "intelligente" class TLaundry_recordset : public TAS400_recordset { public: void add_field(const char* name, const char* tipo, int pos, int len); TLaundry_recordset(const int rec_length); }; //ADD_FIELD: aggiunge i campi al recordset void TLaundry_recordset::add_field(const char* name, const char* tipo, int pos, int len) { CHECK(name[1]=='.', "Campo orfano di tracciato"); const TFixed_string str_tipo(tipo); TFieldtypes ft = _alfafld; if (str_tipo.ends_with("N")) ft = _intzerofld; create_field(name, -1, len, ft); } //costruttore TLaundry_recordset::TLaundry_recordset(const int rec_lenght) : TAS400_recordset("AS400()") { TString16 query; query << "AS400(" << rec_lenght << ")"; TFilename cazzone; parse_query(query, cazzone); } //////////////////////////// //// TCONTI_CACHE //// //////////////////////////// //classe TConti_cache class TConti_cache : public TCache { protected: virtual TObject* key2obj(const char* key); public: const TBill& decodifica_conti(const long mastro, const long conto); }; //KEY2OBJ: ridefinisco il metodo virtuale key2obj in modo che mi restituisca quello di cui ho bisogno TObject* TConti_cache::key2obj(const char* key) { TLocalisamfile riclpdc(LF_RICLPDC); riclpdc.setkey(3); riclpdc.put("TIPORIC", "CGCONTI"); riclpdc.put("CODICE", key); if(riclpdc.read() == NOERR) return new TBill(riclpdc.get_int("GRUPPO"), riclpdc.get_int("CONTO"), riclpdc.get_long("SOTTOCONTO")); return new TBill; } //DECODIFICA_CONTI: restituisce il TBill dato codice mastro e conto del COGECO const TBill& TConti_cache::decodifica_conti(const long mastro, const long conto) { TString16 codice; codice.format("%06ld%06ld", mastro, conto); const TBill* bill = (TBill*)objptr(codice); return *bill; } ////////////////////////////////// //// TDECODIFICA_CODICI //// ////////////////////////////////// //classe TDecodifica_codici class TDecodifica_codici : public TObject { TAssoc_array _tab; TConti_cache _conti; protected: void riempi_array(); const TString& decodifica(const char* tabella, const int codice); public: const TString& decodifica_causali(const int cau_cog); const TString& decodifica_condpag(const int condpag_cog); const TString& decodifica_codiva(const int codiva_cog); const TString& decodifica_regiva(const int regiva_cog); const TString& decodifica_valute(const int val_cog); const TBill& decodifica_conto(const long mastro, const long conto); TDecodifica_codici(); }; //RIEMPI_ARRAY: riempe l'Assoc_array che contiene i dati per fare la decodifica void TDecodifica_codici::riempi_array() { TString query; query << "USE MULTIREL\n" << "FROM COD=\"CG\"\n" << "TO COD=\"CG\""; TISAM_recordset recset(query); for(bool ok = recset.move_first(); ok; ok = recset.move_next()) { const TString& codice = recset.get("COD").as_string().mid(2); const TString& data = recset.get("DATA").as_string(); const TString& first = recset.get("FIRST").as_string(); //faccio un Assoc_array di Assoc_array TAssoc_array* tab = (TAssoc_array*)_tab.objptr(codice); if(tab == NULL) { tab = new TAssoc_array; _tab.add(codice, tab); } tab->add(data, first); } } //DECODIFICA: fa la decodica vera e propria const TString& TDecodifica_codici::decodifica(const char* tabella, const int codice) { //se non ho ancora caricato l'array, lo faccio if(_tab.empty()) riempi_array(); TAssoc_array* tab = (TAssoc_array*)_tab.objptr(tabella); //se esite, restituisco la decodifica, altrimenti stringa vuota if(tab != NULL && codice > 0) { TString8 cod; cod << codice; const TString* data = (const TString*)tab->objptr(cod); if(data != NULL) return *data; } return EMPTY_STRING; } //DECODIFICA_CAUSALI: decodifico da COGECO a Campo la causale const TString& TDecodifica_codici::decodifica_causali(const int cau_cog) { return decodifica("CAU", cau_cog); } //DECODIFICA_CONDPAG: decodifico da COGECO a Campo la condizione di pagamento const TString& TDecodifica_codici::decodifica_condpag(const int condpag_cog) { return decodifica("CDP", condpag_cog); } //DECODIFICA_CODIVA: decodifico da COGECO a Campo il codice IVA const TString& TDecodifica_codici::decodifica_codiva(const int codiva_cog) { return decodifica("IVA", codiva_cog); } //DECODIFICA_REGIVA: decodifico da COGECO a Campo il registro IVA const TString& TDecodifica_codici::decodifica_regiva(const int regiva_cog) { return decodifica("REG", regiva_cog); } //DECODIFICA_VALUTE: decodifico da COGECO a Campo la valuta const TString& TDecodifica_codici::decodifica_valute(const int val_cog) { return decodifica("VAL", val_cog); } //DECODIFICA_CONTO: decodifico da COGECO a Campo il conto const TBill& TDecodifica_codici::decodifica_conto(const long mastro, const long conto) { return _conti.decodifica_conti(mastro, conto); } //costruttore TDecodifica_codici::TDecodifica_codici() {} //////////////////////////////// //// TIMPORTA_FAT_REC //// //////////////////////////////// //Classe TImporta_fat_rec class TImporta_fat_rec : public TLaundry_recordset { protected: virtual TRecnotype new_rec(const char* trc); public: TImporta_fat_rec(const TFilename& filename); }; ///////////////////////////////////////////////////////////// // Recordset specifici per i dati da trasferire INPUT ///////////////////////////////////////////////////////////// TRecnotype TImporta_fat_rec::new_rec(const char* trc) { if (trc && *trc > ' ') { TString rec; rec << trc << "\r\n"; return TText_recordset::new_rec(rec); } return -1; } //questo invece è il metodo magico che vale per il caricamento da file esterno TImporta_fat_rec::TImporta_fat_rec(const TFilename& filename) : TLaundry_recordset(89) { TFilename cazzone; //as400 con lunghezza 89 e chiave lunga 1 (a partire dal ventesimo carattere): è il tipo record parse_query("AS400(89,1,20)", cazzone); //Tipo record C add_field("C.NDOC", T_N, 1, 6); add_field("C.DATADOC", T_N, 7, 8); add_field("C.NPART", T_N, 15, 6); add_field("C.TIPOMOV", T_X, 21, 1); add_field("C.SEZIONE", T_X, 22, 1); add_field("C.CODCF", T_N, 23, 6); add_field("C.IMPORTO", T_X, 29, 13); add_field("C.CODVAL", T_X, 42, 4); add_field("C.CODPAG", T_X, 46, 4); add_field("C.DATASCAD", T_N, 50, 8); add_field("C.ABICAB", T_N, 58, 12); add_field("C.CODCAU", T_N, 70, 4); add_field("C.REGIVA", T_X, 74, 1); add_field("C.NREGIVA", T_N, 75, 2); add_field("C.NPROG", T_N, 77, 11); //Tipo record G add_field("G.NDOC", T_N, 1, 6); add_field("G.DATADOC", T_N, 7, 8); add_field("G.NPART", T_N, 15, 6); add_field("G.TIPOMOV", T_X, 21, 1); add_field("G.SEZIONE", T_X, 22, 1); add_field("G.IMPORTO", T_X, 23, 13); add_field("G.CODMASTRO", T_N, 36, 6); add_field("G.CODCONTO", T_N, 42, 6); //Tipo record I add_field("I.NDOC", T_N, 1, 6); add_field("I.DATADOC", T_N, 7, 8); add_field("I.NPART", T_N, 15, 6); add_field("I.TIPOMOV", T_X, 21, 1); add_field("I.SEZIONE", T_X, 22, 1); add_field("I.IMPONIBILE", T_X, 23, 13); add_field("I.IMPOSTA", T_X, 36, 11); add_field("I.CODIVA", T_N, 47, 4); add_field("I.CODMASTRO", T_N, 36, 6); add_field("I.CODCONTO", T_N, 42, 6); //Tipo record R add_field("R.NDOC", T_N, 1, 6); add_field("R.DATADOC", T_N, 7, 8); add_field("R.NPART", T_N, 15, 6); add_field("R.TIPOMOV", T_X, 21, 1); add_field("R.NRATA", T_N, 22, 6); add_field("R.IMPRATA", T_X, 28, 13); add_field("R.TIPORATA", T_X, 41, 1); add_field("R.DATASCAD", T_N, 42, 8); TText_recordset::load_file(filename); } //////////////////////////////// //// TIMPORTA_FAT_MSK //// //////////////////////////////// //Classe TImporta_fat_msk class TImporta_fat_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TImporta_fat_msk(); }; TImporta_fat_msk::TImporta_fat_msk() :TAutomask ("lv4500a") {} bool TImporta_fat_msk::on_field_event(TOperable_field& f, TField_event e, long jolly) { return true; } //////////////////////////////// //// TIMPORTA_FAT_APP //// //////////////////////////////// //Classe TImporta_fat_app class TImporta_fat_app : public TSkeleton_application { TImporta_fat_msk* _msk; TDecodifica_codici* _codici; protected: bool search_gr_sp_ca(const int gruppo, const char* specie, const int categoria); const TFilename crea_tmpdir() const; const TFilename crea_nomefile(const long ndoc) const; const int segno_testata(const char sezione, const TCausale& cau) const; const int segno_riga(const char sezione, const TCausale& cau) const; const TString16 genera_real(const TVariant importo, const int segno = 1) const; const TString80 riclassifica_pconti(); TConfig* genera_testata(TImporta_fat_rec& recset, TFilename& tmpdir); void genera_righe_iva(TImporta_fat_rec& recset, TConfig& conf, int nriga, const TString& codcau); void genera_rate(TImporta_fat_rec& recset, TConfig& conf, int nriga); void elabora_file(const TFilename& tmpdir); void elimina_file(const TFilename& tmpdir); public: virtual bool create(); virtual bool destroy(); virtual void main_loop(); void transfer(const TFilename& file); }; bool TImporta_fat_app::search_gr_sp_ca(const int gruppo, const char* specie, const int categoria) { return true; } //CREA_TMPDIR: crea la directory temporanea e restituisce il suo nome const TFilename TImporta_fat_app::crea_tmpdir() const { TFilename tmpdir; tmpdir.tempdir(); tmpdir.add("fatture"); make_dir(tmpdir); return tmpdir; } //CREA_NOMEFILE: genera il nome del file dal numero documento const TFilename TImporta_fat_app::crea_nomefile(const long ndoc) const { TString strname; strname.format("%06ld", ndoc); strname << ".ini"; return strname; } //SEGNO_TESTATA: restituisce + o - uno a seconda che la sezione della riga in esame //e quella della prima riga della causale siano uguali o opposte const int TImporta_fat_app::segno_testata(const char sezione, const TCausale& cau) const { return cau.sezione_clifo() == sezione ? 1 : -1; } //SEGNO_TESTATA: restituisce + o - uno a seconda che la sezione della riga in esame //e quella della prima riga della causale siano opposte o uguali const int TImporta_fat_app::segno_riga(const char sezione, const TCausale& cau) const { return cau.sezione_clifo() == sezione ? -1 : 1; } //GENERA_REAL: crea il numero reale, aggiungendo i decimali e tenendo conto del segno corretto const TString16 TImporta_fat_app::genera_real(const TVariant importo, const int segno) const { real imp = importo.as_real(); imp /= CENTO; imp *= segno; return imp.string(); } //GENERA_TESTATA: genero il paragrafo testata TConfig* TImporta_fat_app::genera_testata(TImporta_fat_rec& recset, TFilename& tmpdir) { const long ndoc = recset.get("C.NDOC").as_int(); const TDate datadoc = recset.get("C.DATADOC").as_date(); const TCausale cau(recset.get("C.CODCAU").as_string()); const int segno = segno_testata(recset.get("C.SEZIONE").as_string()[0], cau); TFilename nomefile = tmpdir; nomefile << '\\' << crea_nomefile(ndoc); TConfig* conf = new TConfig(nomefile); conf->set_paragraph("Transaction"); //setto il paragrafo [Transaction] del file ini conf->set("Action","INSERT"); conf->set("Mode", "AUTO"); TString paragraph; paragraph.format("%d", LF_MOV); conf->set_paragraph(paragraph); //setto il paragrafo [23] del file ini (testata) conf->set(MOV_ANNOES, datadoc.year()); conf->set(MOV_DATAREG, datadoc); conf->set(MOV_DATACOMP, datadoc); conf->set(MOV_DATADOC, datadoc); conf->set(MOV_NUMDOC, ndoc); conf->set(MOV_CODCAUS, _msk->get_bool(F_DECCAU) ? atol(_codici->decodifica_causali(recset.get("C.CODCAU").as_int())) : recset.get("C.CODCAU").as_int()); conf->set(MOV_ANNOIVA, datadoc.year()); conf->set(MOV_REG, _codici->decodifica_regiva(recset.get("C.REGIVA").as_int())); conf->set(MOV_PROTIVA, recset.get("C.NREGIVA").as_int()); conf->set(MOV_CODVAL, _msk->get_bool(F_DECVAL) ? _codici->decodifica_valute(recset.get("C.CODVAL").as_int()) : recset.get("C.CODVAL").as_string()); conf->set(MOV_TIPO, 'C'); conf->set(MOV_CODCF, recset.get("C.CODCF").as_int()); conf->set(MOV_TOTDOC, genera_real(recset.get("C.IMPORTO"), segno)); conf->set(MOV_CODPAG, _msk->get_bool(F_DECCDP) ? atol(_codici->decodifica_condpag(recset.get("C.CODPAG").as_int())) : recset.get("C.CODPAG").as_int()); return conf; } //GENERA_RIGHE_IVA: genero le righe IVA void TImporta_fat_app::genera_righe_iva(TImporta_fat_rec& recset, TConfig& conf, int nriga, const TString& codcau) { const TDate datadoc = recset.get("I.DATADOC").as_date(); const char sezione = recset.get("I.SEZIONE").as_string()[0]; const TCausale cau(codcau); const int segno = segno_riga(sezione, cau); const TBill& conto = _codici->decodifica_conto(recset.get("I.CODMASTRO").as_int(), recset.get("I.CODCONTO").as_int()); TString paragraph; paragraph.format("%d,%d", LF_RMOVIVA, ++nriga); conf.set_paragraph(paragraph); conf.set(RMI_ANNOES, datadoc.year()); conf.set(RMI_CODIVA, _msk->get_bool(F_DECCODIVA) ? atol(_codici->decodifica_codiva(recset.get("I.CODIVA").as_int())) : recset.get("I.CODIVA").as_int()); conf.set(RMI_IMPONIBILE, genera_real(recset.get("I.IMPONIBILE"), segno)); conf.set(RMI_IMPOSTA, genera_real(recset.get("I.IMPOSTA"), segno)); conf.set(RMI_GRUPPO, conto.gruppo()); conf.set(RMI_CONTO, conto.conto()); conf.set(RMI_SOTTOCONTO, conto.sottoconto()); } //GENERA_RATE: genero le righe su SCAD void TImporta_fat_app::genera_rate(TImporta_fat_rec& recset, TConfig& conf, int nriga) { TString paragraph; paragraph.format("%d,%d", LF_RMOVIVA, ++nriga); conf.set_paragraph(paragraph); const TDate datadoc = recset.get("R.DATADOC").as_date(); conf.set(SCAD_ANNO, datadoc.year()); conf.set(SCAD_NUMPART, recset.get("R.NPART").as_int()); conf.set(SCAD_NRIGA, nriga); conf.set(SCAD_NRATA, recset.get("R.NRATA").as_int()); //??? CODPAG ???// conf.set(SCAD_TIPOPAG, recset.get("R.TIPOPAG").as_int()); conf.set(SCAD_IMPORTO, genera_real(recset.get("R.IMPORTO"))); conf.set(SCAD_IMPORTOVAL, genera_real(recset.get("R.IMPORTO"))); //NON SO IN QUALE DEI DUE VADA conf.set(SCAD_DATASCAD, recset.get("R.DATASCAD").as_date()); //??? ABI CAB GRUPPO CONTO SOTTOCONTO ???// } //ELABORA_FILE: chiamo la prima nota su tutti gli ini che ho generato void TImporta_fat_app::elabora_file(const TFilename& tmpdir) { TString app; app << "cg2 -0 -i" << tmpdir << "/*.ini"; TExternal_app primanota(app); primanota.run(true); } //ELIMINA_FILE: elimino tutti i file che ho elaborato DA IMPLEMENTARE void TImporta_fat_app::elimina_file(const TFilename& tmpdir) { } void TImporta_fat_app::transfer(const TFilename& file) { TImporta_fat_rec recset(file); TConfig* configfile = NULL; TFilename tmpdir = crea_tmpdir(); int nrigai, nrigar; TProgind pi(recset.items(), "Importazione in corso...", true, true); TString16 codcau; for(bool ok = recset.move_first(); ok; ok = recset.move_next()) { if (!pi.addstatus(1)) break; const char tipomov = recset.get("TIPOMOV").as_string()[0]; switch(tipomov) { case 'C': { if(configfile != NULL) delete configfile; codcau = recset.get("C.CODCAU").as_string(); configfile = genera_testata(recset, tmpdir); nrigai = nrigar = 0; } break; case 'I': genera_righe_iva(recset, *configfile, nrigai, codcau); break; case 'R': genera_rate(recset, *configfile, nrigar); break; default: break; } } if(configfile != NULL) delete configfile; elabora_file(tmpdir); } bool TImporta_fat_app::create() { _msk = new TImporta_fat_msk(); _codici = new TDecodifica_codici(); return TSkeleton_application::create(); } bool TImporta_fat_app::destroy() { delete _msk; return TApplication::destroy(); } void TImporta_fat_app::main_loop() { if ( _msk->run() == K_ENTER) { //genero il nome del file da caricare TFilename file = _msk->get(F_NAME); if(!file.exist()) { error_box(TR("Il file selezionato non esiste; si prega di controllare")); return; } transfer(file); } } int lv4500 (int argc, char* argv[]) { TImporta_fat_app main_app; main_app.run(argc, argv, TR("Importazione fatture COGECO")); return true; }