#include #include #include #include #include "ps0713600a.h" #include #include #include #include "ps0713lib.h" #include "../ca/calib01.h" #include "../ca/calib02.h" #include "../ca/movana.h" #include "../ca/rmovana.h" //////////////////////////////////// //// TIMPORTA_FAT_FOR_MSK //// //////////////////////////////////// //Classe TImporta_fat_for_msk class TImporta_fat_for_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); public: TImporta_fat_for_msk(const char* name); }; TImporta_fat_for_msk::TImporta_fat_for_msk(const char* name) :TAutomask(name) {} //ON_FIELD_EVENT: metodo che gestisce i comportamenti dei vari campi della maschera //(per adesso segnaposto) bool TImporta_fat_for_msk::on_field_event(TOperable_field& f, TField_event e, long jolly) { return true; } //////////////////////////////////// //// TIMPORTA_FAT_FOR_APP //// //////////////////////////////////// //classe TImporta_fat_for_app class TImporta_fat_for_app : public TSkeleton_application { TImporta_fat_for_msk* _msk; protected: virtual bool check_autorization() const { return false; } virtual const char * extra_modules() const { return "ve"; } virtual void main_loop(); public: //metodi per l'acquisizione dei dati da file e i calcoli da effettura eprima dell'importazione void scan_file(TVB_recset& file, TAssoc_array& righean, TAssoc_array& righecg) const; bool calcola_quadratura(TAssoc_array& righean, TCommessa_string& kmax, real& quad); bool importa(const TFilename& name, TAssoc_array& righean, TAssoc_array& righecg); //metodi per l'importazione vera e propria long genera_movcg(); void genera_analitica(TAssoc_array& righean, TCommessa_string& kmax, const real& quad, const long numregcg); void importa_fat(TAssoc_array& righecg, TCommessa_string& kmax, const real& quad, TConfig* configfile, const long numregcg); void importa_fat_ric(TAssoc_array& righecg, TCommessa_string& kmax, const real& quad, TConfig* configfile, const long numregcg); void gestione_ini(TAssoc_array& righecg, TCommessa_string& kmax, const real& quad, const long numregcg); bool transfer(); }; void TImporta_fat_for_app::scan_file(TVB_recset& file, TAssoc_array& righean, TAssoc_array& righecg) const { TProgind pi(file.items(), "Scansione file in corso ...", true, true); //scorro il file, saltando le eventuali righe vuote, e riempio i due array, //quello delle righe di analitica e quello delle righe di contabilità generale; //l'analitica va raggruppata per CODCMS - GRUPPO - CONTO - SOTTOCONTO, //metre la contabilità generale solo per CODCMS (che corrisponde all'IDLAVORO) for (bool ok = file.move_first(); ok ;ok = file.move_next()) { if (!pi.addstatus(1)) break; //evito di analizzare eventuali righe vuote if(file.empty()) continue; //idlavoro const TString16 idlavoro = file.get(0).as_string(); //imponibile TString16 tmp = file.get(1).as_string(); tmp.replace(',','.'); tmp.strip("\""); const real imp = tmp; //gruppo const int gruppo = file.get(2).as_int(); //gruppo const int conto = file.get(3).as_int(); //gruppo const int sotco = file.get(4).as_int(); //chiave del TAssoc_array dell'analatica TCommessa_string keyan(idlavoro, gruppo, conto, sotco); //riempio l'array dell'analitica if(righean.is_key(keyan)) { real& imponibile = *(real*)righean.objptr(keyan); imponibile += imp; } else righean.add(keyan, imp); //riempio l'array della contabilità generale if(righecg.is_key(keyan.contostr())) { real& imponibile = *(real*)righecg.objptr(keyan.contostr()); imponibile += imp; } else righecg.add(keyan.contostr(), imp); } } //CALCOLA_QUADRATURA: metodo che calcola l'ammontare dell'evetuale riga di quadratura del documento bool TImporta_fat_for_app::calcola_quadratura(TAssoc_array& righean, TCommessa_string& kmax, real& quad) { //calcolo qaul'è la massima tolleranza consentita //(da analisi la tolleranza è un centesimo per riga) const real quadmax = righean.items() * 0.01; real quadra = ZERO; real max = ZERO; bool ok = true; real totimp = ZERO; //scorro tutte le righe, eventualmente ragguppate, tenendo traccia di qual'è quella che ha imponibile maggiore //e arrotondando i vari imponibili a due decimali FOR_EACH_ASSOC_OBJECT(righean, obj, key, itm) { real& imp = *(real*)itm; if(imp > max) { max = imp; kmax = key; } const real tmp = imp; imp.round(2); quadra += tmp - imp; totimp += tmp; } if(quadra <= quadmax) { quad = quadra; quad.round(2); } else { error_box(TR("L'arrotondamento effettuato sul documento supera la tolleranza consentita")); quad = ZERO; ok = false; } if(totimp != _msk->get_real(F_IMPON)) { error_box(TR("Il totale Imponibile delle righe non corrisponde al valore riportato sulla maschera")); ok = false; } return ok; } //IMPORTA: metodo che popola l'assoc_array delle righe e calcola la quadratura bool TImporta_fat_for_app::importa(const TFilename& name, TAssoc_array& righean, TAssoc_array& righecg) { TVB_recset file(name, ','); scan_file(file, righean, righecg); return true; } //GENERA_MOVCG: metodo che genera la testata del movimento di prima nota long TImporta_fat_for_app::genera_movcg() { TISAM_recordset movrec("USE MOV"); movrec.move_last(); long numreg = movrec.get(MOV_NUMREG).as_int(); numreg++; TLocalisamfile mov(LF_MOV); mov.put(MOV_NUMREG, numreg); mov.put(MOV_DATACOMP, _msk->get_date(F_DATAREG)); mov.put(MOV_DATAREG, _msk->get_date(F_DATAREG)); mov.write(); return numreg; } //GENERA_ANALITICA: metodo che genera il movimento di contabilità analitica void TImporta_fat_for_app::genera_analitica(TAssoc_array& righean, TCommessa_string& kmax, const real& quad, const long numregcg) { TProgind pi(righean.items(), "Importazione analitica in corso...", true, true); TToken_string key; key.add(_msk->get(F_CODCAU)); key.add(1); key.add(1); const TRectype& causale = cache().get(LF_RCAUSALI, key); const int anno = _msk->get_date(F_DATADOC).year(); key.add(2, 1); const TRectype& causale1 = cache().get(LF_RCAUSALI, key); //instanzio il movimento di analitica TAnal_mov anmo(0); anmo.put(MOVANA_NUMREGCG, numregcg); anmo.put(MOVANA_DATACOMP, _msk->get_date(F_DATAREG)); anmo.put(MOVANA_DATAREG, _msk->get_date(F_DATAREG)); anmo.put(MOVANA_CODCAUS, _msk->get(F_CODCAU)); anmo.put(MOVANA_ANNOES, anno); //aggiungo i campi relativi ai documenti solo quando li ho a disposizione if(_msk->get_int(F_TIPOFAT) == 1) { const real iva = cache().get("%IVA", _msk->get(F_CODIVA), "R0"); real totimponibile = ZERO; real totimposta = ZERO; //calcolo dei totali FOR_EACH_ASSOC_OBJECT(righean, obj, keyar, itm) { real& imp = *(real*)itm; imp.round(2); totimponibile += imp; real imposta = imp * iva / CENTO; imposta.round(2); totimposta += imposta; } if (quad > ZERO) { totimponibile += quad; real imposta = quad * iva / CENTO; imposta.round(2); totimposta += imposta; } const real totdoc = totimponibile + totimposta; anmo.put(MOVANA_DATADOC, _msk->get_date(F_DATADOC)); anmo.put(MOVANA_NUMDOC, _msk->get_long(F_NDOC)); anmo.put(MOVANA_TOTDOC, totdoc.string()); } //per ogni oggetto dell'assoc_array, creo una riga di analitica FOR_EACH_ASSOC_OBJECT(righean, obj, keyar, itm) { if (!pi.addstatus(1)) break; TCommessa_string& row = (TCommessa_string)keyar; const TString& idlav = row.idlavoro(); const int gruppo = row.gruppo(); TString8 grup; grup.format("%03d", gruppo); const int conto = row.conto(); TString8 cont; cont.format("%03d", conto); const int sotco = row.sotco(); TString16 sotc; sotc.format("%06ld", sotco); TString80 codconto; codconto << grup << cont << sotc; real& imp = *(real*)itm; imp.round(2); if (!imp.is_zero()) { TRectype& ranmo = anmo.new_row(); ranmo.put(RMOVANA_ANNOES, anno); ranmo.put(RMOVANA_SEZIONE, causale1.get("SEZIONE")); ranmo.put(RMOVANA_CODCONTO, codconto); ranmo.put(RMOVANA_CODCMS, idlav); ranmo.put(RMOVANA_IMPORTO, imp); } } if(quad > ZERO) { TImporto importo(causale.get("SEZIONE")[0], quad); const int gruppo = kmax.gruppo(); TString8 grup; grup.format("%03d", gruppo); const int conto = kmax.conto(); TString8 cont; cont.format("%03d", conto); const int sotco = kmax.sotco(); TString16 sotc; sotc.format("%06ld", sotco); TString80 codconto; codconto << grup << cont << sotc; TRectype& ranmo = anmo.new_row(); ranmo.put(RMOVANA_ANNOES, anno); ranmo.put(RMOVANA_SEZIONE, causale.get("SEZIONE")); ranmo.put(RMOVANA_CODCONTO, codconto); ranmo.put(RMOVANA_CODCMS, kmax.idlavoro()); ranmo.put(RMOVANA_IMPORTO, importo.valore().string()); } TLocalisamfile fmov(LF_MOVANA); anmo.write(fmov); } //IMPORTA_FAT: metodo che genera l'ini per l'importazione delle fatture a fornitore void TImporta_fat_for_app::importa_fat(TAssoc_array& righecg, TCommessa_string& kmax, const real& quad, TConfig* configfile, const long numregcg) { const TDate datareg = _msk->get_date(F_DATAREG); const TDate datadoc = _msk->get_date(F_DATADOC); const long ndoc = _msk->get_long(F_NDOC); const TString4 codiva = _msk->get(F_CODIVA); const long codcf = _msk->get_long(F_CODFOR); const TString4 codcau = _msk->get(F_CODCAU); const int anno = datadoc.year(); TToken_string key; key.add(codcau); key.add(1); const TRectype& causale = cache().get(LF_RCAUSALI, key); const real iva = cache().get("%IVA", codiva, "R0"); real totimponibile = ZERO; real totimposta = ZERO; //calcolo dei totali FOR_EACH_ASSOC_OBJECT(righecg, obj, keyar, itm) { real& imp = *(real*)itm; imp.round(2); totimponibile += imp; real imposta = imp * iva / CENTO; imposta.round(2); totimposta += imposta; } if (quad > ZERO) { totimponibile += quad; real imposta = quad * iva / CENTO; imposta.round(2); totimposta += imposta; } const real totdoc = totimponibile + totimposta; TProgind pi(righecg.items(), "Importazione in corso...", true, true); configfile->set_paragraph("23"); //setto il paragrafo [23] del file ini (testata) configfile->set(MOV_NUMREG, numregcg); configfile->set(MOV_DATADOC, datadoc); configfile->set(MOV_NUMDOC, ndoc); configfile->set(MOV_CODCAUS, codcau); configfile->set(MOV_TIPO, 'F'); configfile->set(MOV_CODCF, codcf); configfile->set(MOV_TOTDOC, totdoc.string()); int nrigaiv = 0; //per ogni riga dell'assoc_array, creo un paragrafo riga FOR_EACH_ASSOC_OBJECT(righecg, obj, keyar1, itm1) { if (!pi.addstatus(1)) break; real& imp = *(real*)itm1; imp.round(2); if (!imp.is_zero()) { TString8 paragraph; paragraph.format("%d,%d", LF_RMOVIVA, ++nrigaiv); configfile->set_paragraph(paragraph); configfile->set(RMI_NUMRIG, nrigaiv); TImporto importo('D', imp); real rimposta = imp * iva / CENTO; rimposta.round(2); TToken_string bill(keyar1); configfile->set(RMI_ANNOES, anno); configfile->set(RMI_IMPONIBILE, importo.valore().string()); configfile->set(RMI_CODIVA, codiva); configfile->set(RMI_IMPOSTA, rimposta.string()); configfile->set(RMI_GRUPPO, bill.get(0)); configfile->set(RMI_CONTO, bill.get(1)); configfile->set(RMI_SOTTOCONTO, bill.get(2)); configfile->set(RMI_TIPOATT, 1); } } //se c'è bisogno, faccio una riga in più if(quad > ZERO) { TString8 paragraph; paragraph.format("%d,%d", LF_RMOVIVA, ++nrigaiv); configfile->set_paragraph(paragraph); configfile->set(RMI_NUMRIG, nrigaiv); TImporto importo('D', quad); real rimposta = importo.valore() * iva / CENTO; rimposta.round(2); configfile->set(RMI_ANNOES, anno); configfile->set(RMI_IMPONIBILE, importo.valore().string()); configfile->set(RMI_CODIVA, codiva); configfile->set(RMI_IMPOSTA, rimposta.string()); configfile->set(RMI_GRUPPO, kmax.gruppo()); configfile->set(RMI_CONTO, kmax.conto()); configfile->set(RMI_SOTTOCONTO, kmax.sotco()); configfile->set(RMI_TIPOATT, 1); } TString8 paragraph; paragraph.format("%d,%d", LF_RMOVIVA, ++nrigaiv); configfile->set_paragraph(paragraph); } //IMPORTA_FAT_RIC: metodo che genera l'ini per l'importazione delle fatture da ricevere //(attenzione: genero righe IVA) void TImporta_fat_for_app::importa_fat_ric(TAssoc_array& righecg, TCommessa_string& kmax, const real& quad, TConfig* configfile, const long numregcg) { const TDate datareg = _msk->get_date(F_DATAREG); const TDate datadoc = _msk->get_date(F_DATADOC); const long ndoc = _msk->get_long(F_NDOC); const TString4 codiva = _msk->get(F_CODIVA); const long codcf = _msk->get_long(F_CODFOR); const TString4 codcau = _msk->get(F_CODCAU); const int anno = datadoc.year(); TToken_string key; key.add(codcau, 0); key.add(1, 1); const TRectype& causale = cache().get(LF_RCAUSALI, key); const real iva = cache().get("%IVA", codiva, "R0"); real totimp = _msk->get_real(F_IMPON); totimp.round(2); real totdoc = totimp; totdoc.round(2); TProgind pi(righecg.items(), "Importazione in corso...", true, true); configfile->set_paragraph("23"); //setto il paragrafo [23] del file ini (testata) configfile->set(MOV_NUMREG, numregcg); configfile->set(MOV_DATAREG, datareg); configfile->set(MOV_CODCAUS, codcau); int nrigaco = 1; //prima riga: serve a bilanaciare le altre TString8 paragraph; paragraph.format("%d,%d", LF_RMOV, 1); configfile->set_paragraph(paragraph); configfile->set(RMV_NUMRIG, 1); TImporto importo(causale.get("SEZIONE")[0], totdoc); configfile->set(RMV_ANNOES, anno); configfile->set(RMV_SEZIONE, causale.get("SEZIONE")); configfile->set(RMV_IMPORTO, importo.valore().string()); configfile->set(RMV_TIPOC, causale.get("TIPOCF")); configfile->set(RMV_GRUPPO, causale.get("GRUPPO")); configfile->set(RMV_CONTO, causale.get("CONTO")); configfile->set(RMV_SOTTOCONTO, _msk->get_long(F_CODFOR)); configfile->set(RMV_TIPOC, "F"); configfile->set(RMV_ROWTYPE, "T"); key.add(2,1); const TRectype& causale2 = cache().get(LF_RCAUSALI, key); //per ogni oggetto dell'assoc_array, preparo un paragrafo riga FOR_EACH_ASSOC_OBJECT(righecg, obj, keyar, itm) { if (!pi.addstatus(1)) break; real& imp = *(real*)itm; imp.round(2); if (!imp.is_zero()) { TString8 paragraph; paragraph.format("%d,%d", LF_RMOV, ++nrigaco); configfile->set_paragraph(paragraph); configfile->set(RMV_NUMRIG, nrigaco); TImporto importo(causale2.get("SEZIONE")[0], imp); const real rimposta = imp * iva / CENTO; TToken_string bill(keyar); configfile->set(RMV_ANNOES, anno); configfile->set(RMV_SEZIONE, causale2.get("SEZIONE")); configfile->set(RMV_IMPORTO, importo.valore().string()); configfile->set(RMV_GRUPPO, bill.get(0)); configfile->set(RMV_CONTO, bill.get(1)); configfile->set(RMV_SOTTOCONTO, bill.get(2)); } } //se serve, faccio una riga in più if(quad > ZERO) { TString8 paragraph; paragraph.format("%d,%d", LF_RMOV, ++nrigaco); configfile->set_paragraph(paragraph); configfile->set(RMV_NUMRIG, nrigaco); TImporto importo(causale2.get("SEZIONE")[0], quad); configfile->set(RMV_ANNOES, anno); configfile->set(RMV_SEZIONE, causale2.get("SEZIONE")); configfile->set(RMV_IMPORTO, importo.valore().string()); configfile->set(RMV_GRUPPO, kmax.gruppo()); configfile->set(RMV_CONTO, kmax.conto()); configfile->set(RMV_SOTTOCONTO, kmax.sotco()); } paragraph.format("%d,%d", LF_RMOVIVA, ++nrigaco); configfile->set_paragraph(paragraph); } //GESTIONE_INI: metodo che si occupa di generare il file ini e di importarlo effettivamente void TImporta_fat_for_app::gestione_ini(TAssoc_array& righe, TCommessa_string& kmax, const real& quad, const long numregcg) { TLocalisamfile mov(LF_MOV); mov.put(MOV_NUMREG, numregcg); mov.remove(); TConfig* configfile = NULL; TFilename tmpdir; tmpdir.tempdir(); TFilename filename = tmpdir; filename.add("atsfor01.ini"); configfile = new TConfig(filename, "Transaction"); //setto il paragrafo [Transaction] del file ini configfile->set_paragraph("Transaction"); configfile->set("Action","INSERT"); configfile->set("Mode","AUTO"); const int tipofat = _msk->get_int(F_TIPOFAT); switch(tipofat) { case 1: importa_fat(righe, kmax, quad, configfile, numregcg); break; case 2: importa_fat_ric(righe, kmax, quad, configfile, numregcg); break; default: break; } TString app; app << "cg2 -0 -i" << tmpdir << SLASH << "ats*.ini"; TExternal_app primanota(app); primanota.run(); filename.fremove(); } bool TImporta_fat_for_app::transfer() { //genero il nome del file da caricare TString path = _msk->get(F_PATH); bool trovato = false; bool esiste = false; bool importato = false; TAssoc_array righean; TAssoc_array righecg; TCommessa_string kmax; if(_msk->get(F_NAME1).full()) { esiste = true; TFilename name = path; name.add(_msk->get(F_NAME1)); if(name.exist()) { trovato = true; importato = importa(name, righean, righecg); } } if(importato) { real quad; TCommessa_string kmax; calcola_quadratura(righean, kmax, quad); long numregcg = genera_movcg(); genera_analitica(righean, kmax, quad, numregcg); gestione_ini(righecg, kmax, quad, numregcg); } else { if(!esiste) warning_box(TR("E' necessario specidicare almeno uno dei due file")); else if(!trovato) error_box(TR("Nessuno dei due file indicati esiste")); else message_box(TR("Elaborazione terminata")); } return true; } void TImporta_fat_for_app::main_loop() { _msk = new TImporta_fat_for_msk("ps0713600a"); while (_msk->run() == K_ENTER) { if (transfer()) message_box(TR("Importazione spese completata")); else warning_box(TR("L'importazione spese non e' stata completata in modo corretto\nSi prega di correggere gli errori segnalati")); } } TImporta_fat_for_app& app() { return (TImporta_fat_for_app&) main_app(); } int ps0713600 (int argc, char* argv[]) { TImporta_fat_for_app main_app; main_app.run(argc, argv, TR("Importazione Spese")); return true; }