#include "halib.h" #include "hacnvlib.h" #include "hacnv200a.h" #include #include #include #include #include #include #include #include #include #include #include #include #include const char* const APPNAME = TR("Conversione movimenti"); /////////////////////////////////////////////////////////// // Movimenti /////////////////////////////////////////////////////////// class THardy_movimenti : public THardy_transfer { int _anno; // parametri per la query TDate _dadata, _adata; // parametri per la query TConfig* _conf; // ini in compilazione long _kmovcont; // movimento contabile in esame TArray* _righeiva; // array dele righe iva hardy TArray* _righecont; // array delle righe contabili hardy TAssoc_array* _ivaind; // array dei codici iva con % di indetraibilità TAssoc_array* _ivaoma; // array dei codici iva per gli omaggi protected: bool scrivi_righe(); bool scrivi_righecont(); bool test_movcont(); bool conto_is_costoricavo(const int gr); bool test_moviva(); void conto2campo(const TString& hd_tipoc, const TString& hd_key, TString4& tipoc, int& gr, int& co, long& so); void rec2ini(const TRectype& rec); void recset2rec(const TODBC_recordset& recset, TRectype& rec, const TString_array& lista_campi); real get_imponibile(const TRectype& rec); public: virtual bool trasferisci(); THardy_movimenti(const int anno, const TDate dadata, const TDate adata); }; // carica il record campo con il record hardy in base alla configurazione void THardy_movimenti::recset2rec(const TODBC_recordset& recset, TRectype& rec, const TString_array& lista_campi) { TString campo_dest, campo_orig, valore, str; FOR_EACH_ARRAY_ROW(lista_campi,i,row) { row->get(0, campo_dest); row->get(1, campo_orig); if (campo_orig.full()) { if (campo_orig[0] == '_') { if (campo_orig.starts_with("_SCONTO")) // è uno sconto (ca..o!) { valore.cut(0); real sconto; TString8 field; for (int i = 1; i < 6; i++) { field.format("Sconto%1d",i); sconto = get_real(field); sconto.round(2); if (sconto != ZERO) { valore << sconto.string(); valore << "+"; } } if (valore.len()>0) valore = valore.left(valore.len()-1); } else if (campo_orig.starts_with("_REAL")) // è un real { const TString80 campo = campo_orig.after(','); real r = recset.get(campo).as_real(); valore = r.string(); } else if (campo_orig.starts_with("_ROUND")) // arrotondo a due decimali { const TString80 campo = campo_orig.after(','); real contenuto = recset.get(campo).as_real(); contenuto.round(2); valore = contenuto.string(); } else if (campo_orig.starts_with("_FISSO")) // valore fisso indicato in configurazione { valore = campo_orig.after(','); valore.trim(); } else if (campo_orig.starts_with("_STREXPR")) // formato _STREXPR, espressione { TExpression expr(campo_orig.after(','), _strexpr); for (int v = 0; v < expr.numvar(); v++) { const char* varname = expr.varname(v); expr.setvar(v, recset.get(varname).as_string()); } valore = expr.as_string(); valore.trim(); } else if (campo_orig.starts_with("_TAB")) // formato _TAB,,, { TToken_string elabora(campo_orig, ','); const TString4 tab = elabora.get(1); // tabella da leggere const TString16 codtab = recset.get(elabora.get()).as_string(); const TString16 campotab = elabora.get(); valore = cache().get(tab, codtab, campotab); } else if (campo_orig.starts_with("_TRADUCI")) { const TString80 campo = campo_orig.after(','); const TString80 contenuto = recset.get(campo).as_string(); TConfig& ini = config(); valore = ini.get(contenuto,campo); } else valore.cut(0); } else valore = recset.get(campo_orig).as_string(); rec.put(campo_dest, valore); } } } // calcola conto campo a partire da conto hardy void THardy_movimenti::conto2campo(const TString& hd_tipoc, const TString& hd_key, TString4& tipoc, int& gr, int& co, long& so) { TConfig& ini = config(); char tipocc = hd_tipoc[0]; switch (tipocc) { case 'S': { tipoc = " "; hd_key2conto(hd_key, gr, co, so); } break; case 'C': { tipoc = "C"; gr = ini.get_int("CLI_GRUPPO", "Mastri"); co = ini.get_int("CLI_CONTO", "Mastri"); so = hd_key2cli(hd_key); } break; case 'F': { tipoc = "F"; gr = ini.get_int("FOR_GRUPPO", "Mastri"); co = ini.get_int("FOR_CONTO", "Mastri"); so = hd_key2forn(hd_key); } break; default: break; } } // verifica in configurazione se il conto è costo o ricavo bool THardy_movimenti::conto_is_costoricavo(const int gr) { TConfig& ini = config(); const int costi = ini.get_int("COSTI_GRUPPO", "Mastri"); const int ricavi = ini.get_int("RICAVI_GRUPPO", "Mastri"); return ((gr == costi) || (gr == ricavi)); } // verifica se il movimento è iva e nel caso riempie array delle righe iva bool THardy_movimenti::test_moviva() { // verifico se è un movimento iva: esiste un record in MovIvaT TString query; query << query_header(); query << "SELECT * " "FROM dbo.MovIvaT " "WHERE KMovconT="; query << _kmovcont; TODBC_recordset recset(query); long kregivat = -1; if (recset.items() > 0) { bool ok=recset.move_first(); if (ok) { kregivat = recset.get("KRegivaT").as_int(); // aggiorna_testata movimento già scritta su ini con i nuovi dati di testata const TString& key = recset.get("IdConto").as_string(); TString4 hdtipoc = recset.get("IdContoTp").as_string(); TString4 tipoc = " "; int gr, co; long so; gr = 0; co = 0; so = 0; conto2campo(hdtipoc, key, tipoc, gr, co, so); _conf->set(MOV_TIPO, tipoc); _conf->set(MOV_CODCF, so); real totdoc = recset.get("TotDocumento").as_real(); _conf->set(MOV_TOTDOC, totdoc.string(0,2)); } } // leggo le righe iva e costrisco array corrispondente TString_array lista_campi_righeiva; TConfig& ini = config(); ini.list_variables(lista_campi_righeiva, true, "RMOVIVA", true); TString query_righe; query_righe << query_header(); query_righe << "SELECT * " "FROM dbo.MovIva " "WHERE KRegivaT="; query_righe << kregivat; TODBC_recordset recset_righe(query_righe); _righeiva->destroy(); TLocalisamfile rmoviva(LF_RMOVIVA); TRectype& rec_rmoviva = rmoviva.curr(); for (bool ok=recset_righe.move_first();ok;ok=recset_righe.move_next()) { recset2rec(recset_righe, rec_rmoviva, lista_campi_righeiva); const TString& key = recset_righe.get("IdConto").as_string(); TString4 hdtipoc = recset_righe.get("IdContoTp").as_string(); TString4 tipoc; tipoc = " "; int gr, co; long so; gr = 0; co = 0; so = 0; conto2campo(hdtipoc, key, tipoc, gr, co, so); rec_rmoviva.put(RMI_TIPOC, tipoc); rec_rmoviva.put(RMI_GRUPPO, gr); rec_rmoviva.put(RMI_CONTO, co); rec_rmoviva.put(RMI_SOTTOCONTO, so); _righeiva->add(new TRectype(rec_rmoviva)); } return (kregivat > 0); } // riempie array delle righe contabili bool THardy_movimenti::test_movcont() { TString_array lista_campi_righe; TConfig& ini = config(); ini.list_variables(lista_campi_righe, true, "RMOV", true); TString query_righe; query_righe << query_header(); query_righe << "SELECT * " "FROM dbo.MovContabili " "WHERE KMovconT="; query_righe << _kmovcont; TODBC_recordset recset_righe(query_righe); _righecont->destroy(); TLocalisamfile rmov(LF_RMOV); TRectype& rec_rmov = rmov.curr(); for (bool ok=recset_righe.move_first();ok;ok=recset_righe.move_next()) { recset2rec(recset_righe, rec_rmov, lista_campi_righe); const TString& key = recset_righe.get("IdConto").as_string(); TString4 hdtipoc = recset_righe.get("IdContoTp").as_string(); TString4 tipoc; tipoc = " "; int gr, co; long so; gr = 0; co = 0; so = 0; conto2campo(hdtipoc, key, tipoc, gr, co, so); TString4 sezione = "D"; real imp_dare = recset_righe.get("Dare").as_real(); real imp_avere = recset_righe.get("Avere").as_real(); if (imp_dare.is_zero()) sezione = "A"; rec_rmov.put(RMV_SEZIONE, sezione); rec_rmov.put(RMV_IMPORTO, (imp_avere.is_zero() ? imp_dare : imp_avere)); rec_rmov.put(RMV_TIPOC, tipoc); rec_rmov.put(RMV_GRUPPO, gr); rec_rmov.put(RMV_CONTO, co); rec_rmov.put(RMV_SOTTOCONTO, so); _righecont->add(new TRectype(rec_rmov)); } return true; } // scrive il record passato sull'ini corrente void THardy_movimenti::rec2ini(const TRectype& rec) { for (int i=0; iset(fieldname, value); } } // scrive su ini le righe contabili bool THardy_movimenti::scrivi_righecont() { TString paragraph; int nrigac = 1; for (int i=0;i<_righecont->items();i++) { TRectype& rec_rmov = *(TRectype*)_righecont->objptr(i); paragraph.format("%d,%d",LF_RMOV, nrigac++); _conf->set_paragraph(paragraph); // riga contabile rec2ini(rec_rmov); } return true; } // calcola imponibile della riga iva passata: // 1. se è una riga con iva indetraibile verifico il conto 4 sulla causale // se il conto c'è, l'imponibile è imponibile della riga // se il conto non c'è calcolo iva indetraibile utilizzando la % e la sommo all'imponibile // 2. se è una riga con iva normale, l'imponibile è imponibliie della riga real THardy_movimenti::get_imponibile(const TRectype& rec) { real imponibile = rec.get_real(RMI_IMPONIBILE); const char* codiva = rec.get(RMI_CODIVA); if (_ivaind->is_key(codiva)) { TString16 causale = get_str("IdCausale"); causale << "|4"; const TString& gruppo = cache().get(LF_RCAUSALI, causale, RCA_GRUPPO); if (gruppo.blank()) { real& perc = (real&)_ivaind->find(codiva); imponibile = imponibile+(imponibile*perc)/100; } } return imponibile; } // gestisce tutto il procedimento di scrittura su ini delle righe iva e contabili bool THardy_movimenti::scrivi_righe() { const int ndec = TCurrency::get_firm_dec(false); TString paragraph; int nrigai = 1; // contatore righe iva TConfig& ini = config(); TString8 ivaesente = ini.get("IVA_ESENTE", "Mastri"); TToken_string gruppi_mov = ini.get("GRUPPI_MOV", "Mastri"); // se è un movimento iva metto in atto il meccanismo di ricerca per assegnare le aliquote ai conti if (_righeiva->items()>0) { // primo passo: scartare le righe contabili con gruppi non presenti nella lista GRUPPI_MOV for (int i=0;i<_righecont->items();i++) { TRectype& rec_rmov = *(TRectype*)_righecont->objptr(i); const char* gruppo = rec_rmov.get(RMV_GRUPPO); if ((gruppi_mov.find(gruppo))<0) _righecont->destroy(i); } _righecont->pack(); // secondo passo: per ogni riga iva cerco importo uguale in righe contabili, // se lo trovo assegno quel codice iva al conto contabile trovato e cancello la riga iva e la riga contabile for (int i=0;i<_righeiva->items();i++) { TRectype& rec_rmoviva = *(TRectype*)_righeiva->objptr(i); real imponibile = get_imponibile(rec_rmoviva); for (int j=0;j<_righecont->items();j++) { TRectype& rec_rmov = *(TRectype*)_righecont->objptr(j); real importo = rec_rmov.get_real(RMV_IMPORTO); if (importo == imponibile) { rec_rmoviva.put(RMI_TIPOC, rec_rmov.get(RMV_TIPOC)); rec_rmoviva.put(RMI_GRUPPO, rec_rmov.get(RMV_GRUPPO)); rec_rmoviva.put(RMI_CONTO, rec_rmov.get(RMV_CONTO)); rec_rmoviva.put(RMI_SOTTOCONTO, rec_rmov.get(RMV_SOTTOCONTO)); paragraph.format("%d,%d",LF_RMOVIVA, nrigai++); _conf->set_paragraph(paragraph); // riga iva rec2ini(rec_rmoviva); const char* codiva = rec_rmoviva.get(RMI_CODIVA); // se iva utilizzata per gli omaggi, devo fare un'altra riga iva identica ma con importo avere con iva esente if (_ivaoma->is_key(codiva)) { paragraph.format("%d,%d",LF_RMOVIVA, nrigai++); _conf->set_paragraph(paragraph); // riga iva rec2ini(rec_rmoviva); // sostituisco codice iva e importo (-) importo = -importo; _conf->set(RMI_CODIVA, ivaesente); // codice iva esente per quadrare il movimento _conf->set(RMI_IMPONIBILE, importo.string(0,2)); // imponibile negativo _conf->set(RMI_IMPOSTA, ""); // imposta zero } _righecont->destroy(j, true); j = _righecont->items(); // _righeiva->destroy(i); rec_rmoviva.zero(); } } } _righecont->pack(); // terzo passo: per ogni riga iva rimasta distribuisco importo su tutti i conti rimasti in righe cont. for (int i=0;i<_righeiva->items();i++) { TRectype& rec_rmoviva = *(TRectype*)_righeiva->objptr(i); if (!rec_rmoviva.empty()) { real imponibile = rec_rmoviva.get_real(RMI_IMPONIBILE); real imposta = rec_rmoviva.get_real(RMI_IMPOSTA); TGeneric_distrib dimponibile(imponibile, ndec); TGeneric_distrib dimposta(imposta, ndec); for (int j=0;j<_righecont->items();j++) { TRectype& rec_rmov = *(TRectype*)_righecont->objptr(j); real importo = rec_rmov.get_real(RMV_IMPORTO); dimponibile.add(importo); dimposta.add(importo); } for (int j=0;j<_righecont->items();j++) { TRectype& rec_rmov = *(TRectype*)_righecont->objptr(j); real importo = dimponibile.get(); real imposta = dimposta.get(); rec_rmoviva.put(RMI_TIPOC, rec_rmov.get(RMV_TIPOC)); rec_rmoviva.put(RMI_GRUPPO, rec_rmov.get(RMV_GRUPPO)); rec_rmoviva.put(RMI_CONTO, rec_rmov.get(RMV_CONTO)); rec_rmoviva.put(RMI_SOTTOCONTO, rec_rmov.get(RMV_SOTTOCONTO)); rec_rmoviva.put(RMI_IMPONIBILE, importo); rec_rmoviva.put(RMI_IMPOSTA, imposta); paragraph.format("%d,%d",LF_RMOVIVA, nrigai++); _conf->set_paragraph(paragraph); // riga iva rec2ini(rec_rmoviva); } } } _righecont->destroy(); } // scrivo su ini le righe contabili rimaste (tutte se il mov non è iva) scrivi_righecont(); return true; } // procedura principale di conversione bool THardy_movimenti::trasferisci() { // creazione array delle aliquote iva con % indetraibilità e degli omaggi // leggere la tabella hardy AliquoteIVA _ivaind->destroy(); _ivaoma->destroy(); TString query_iva; query_iva << query_header(); query_iva << "SELECT * " "FROM dbo.AliquoteIVA "; TODBC_recordset recset_iva(query_iva); for (bool ok=recset_iva.move_first();ok;ok=recset_iva.move_next()) { const char* codiva = recset_iva.get("IdIva").as_string(); real ind = recset_iva.get("Indetraibilita").as_real(); const int flomaggio = recset_iva.get("FlOmaggio").as_int(); if (ind != ZERO) { real* oggetto = new real(); _ivaind->add(codiva, (TObject*)oggetto); } if (flomaggio > 0) { real* oggetto = new real(); _ivaoma->add(codiva, (TObject*)oggetto); } } // query su testate movimenti TString16 dastr, astr; dastr.format("%4d-%2d-%2d", _dadata.year(), _dadata.month(), _dadata.day()); astr.format("%4d-%2d-%2d", _adata.year(), _adata.month(), _adata.day()); TString query = "SELECT * " "FROM dbo.MovContabiliT " "WHERE Esercizio="; query << _anno; query << " AND DataMovimento>= '"; query << dastr; query << "' AND DataMovimento<= '"; query << astr; query << "' ORDER BY DataMovimento "; TRecordset& recset = create_recordset(query); TConfig& ini = config(); TString_array lista_campi; ini.list_variables(lista_campi, true, "MOV", true); TFilename outdir; outdir = ini.get("PATH", "Main"); TString80 listfiles = outdir; listfiles << "\\ha*.ini"; TString_array transactions; list_files(listfiles, transactions); FOR_EACH_ARRAY_ROW(transactions, row, name) remove(*name); _conf = NULL; long ntran = 1L; TString paragraph; THardy_iterator hi(this); while (++hi) { _kmovcont = recset.get("KMovconT").as_int(); // numero movimento testata if (_conf != NULL) delete _conf; _conf = NULL; TFilename temp(outdir); temp.add(format("ha%06ld", ntran++)); temp.ext("ini"); if (temp.exist()) temp.fremove(); _conf = new TConfig(temp); _conf->set_paragraph("Transaction"); _conf->set("Action","INSERT"); _conf->set("Mode", "AUTO"); paragraph.format("%d",LF_MOV); _conf->set_paragraph(paragraph); // testata movimento aggiorna_ini(*_conf, lista_campi); // verifica se è un mov. iva e nel caso aggiorna testata e array righe iva bool iva = test_moviva(); // legge righe contabili e aggiorna array righe cont. test_movcont(); // scrive RMOV e /o RMOVIVA a partire da array righe letti da db hardy bool ok = scrivi_righe(); #ifdef DBG TString msg; if (ok) msg << (iva ? TR("Movimento iva "): TR("Movimento contabile ")) << _kmovcont << TR(" generato nel file ") << temp; else { ntran--; if (temp.exist()) temp.fremove(); msg << (iva ? TR("Il movimento iva "): TR("Il movimento contabile ")) << _kmovcont << TR(" ha generato un errore, non è stato convertito "); } log(msg); #endif } if (_conf != NULL) delete _conf; if (yesno_box(FR("Si desidera confermare l'importazione di %ld movimenti"), ntran-1)) { TString app; app << "cg2 -0 -i" << outdir << "/ha*.ini"; TExternal_app primanota(app); primanota.run(true); TString msg; msg << TR("Importazione completata"); log(msg); } else { TString msg; msg << TR("Importazione annullata"); log(msg); } return true; } THardy_movimenti::THardy_movimenti(const int anno, const TDate dadata, const TDate adata) : _anno(anno), _dadata(dadata), _adata(adata) { _righeiva = new TArray; _righecont = new TArray; _ivaind = new TAssoc_array; _ivaoma = new TAssoc_array; } /////////////////////////////////////////////////////////// // TConvMovimentiHardy_mask /////////////////////////////////////////////////////////// class TConvMovimentiHardy_mask : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void serialize(bool bSave); public: void trasferisci(); TConvMovimentiHardy_mask(); virtual ~TConvMovimentiHardy_mask(); }; // Funzione di trasferimento dati da/verso file .ini con lo stesso nome della maschera // Andrebbe messo in libreria void TConvMovimentiHardy_mask::serialize(bool bSave) { TFilename n = source_file(); n.ext("ini"); // Construisce il nome del .ini in base al .msk TConfig cfg(n, "Main"); // Crea il file di configurazione TString4 id; for (int i = fields()-1; i >= 0; i--) // Scandisce tutti i campi della maschera ... { TMask_field& f = fld(i); if (f.active() && f.is_loadable()) // ... selezionando solo quelli editabili { id.format("%d", f.dlg()); if (bSave) // A seconda del flag di scrittura ... cfg.set(id, f.get()); // ... o scrive sul .ini else f.set(cfg.get(id)); // ... o legge dal .ini } } } void TConvMovimentiHardy_mask::trasferisci() { TString query_header; query_header << "ODBC(" << get(F_DSN) << ',' << get(F_USR) << ',' << get(F_PWD) << ")\n"; TReport_book book; THardy_log log; bool rep_to_print = false; bool go_on = true; const int anno = get_int(F_ANNO); const TDate dadata = get_date(F_DADATA); const TDate adata = get_date(F_ADATA); if (go_on && (anno!=0)) { THardy_movimenti pc(anno, dadata, adata); pc.init(TR("Movimenti contabili"), query_header, log); go_on = pc.trasferisci(); book.add(log); rep_to_print = true; } if (rep_to_print && book.pages() > 0) book.preview(); } bool TConvMovimentiHardy_mask::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case DLG_OK: if (e == fe_button) serialize(true); break; default: break; } return true; } TConvMovimentiHardy_mask::TConvMovimentiHardy_mask() : TAutomask("hacnv200a") { serialize(false); } TConvMovimentiHardy_mask::~TConvMovimentiHardy_mask() { } /////////////////////////////////////////////////////////// // TConvMovimentiHardy /////////////////////////////////////////////////////////// class TConvMovimentiHardy : public TSkeleton_application { protected: virtual void main_loop(); }; void TConvMovimentiHardy::main_loop() { TConvMovimentiHardy_mask mask; while (mask.run() == K_ENTER) mask.trasferisci(); } int hacnv200(int argc, char* argv[]) { TConvMovimentiHardy ih; ih.run(argc, argv, APPNAME); return 0; }