#include #include #include #include #include #include "calib01.h" #include "ca2.h" #include "ca2200a.h" #include "movana.h" #include "rmovana.h" #include "rip.h" #include "rrip.h" //-------------------------------------------------------------------- // MASCHERA //-------------------------------------------------------------------- class TRib_movanal_msk : public TAutomask { protected: virtual bool on_field_event(TOperable_field& o, TField_event fe, long jolly); public: TRib_movanal_msk(); virtual ~TRib_movanal_msk(){}; }; TRib_movanal_msk::TRib_movanal_msk() :TAutomask ("ca2200a") { } bool TRib_movanal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { /* switch (o.dlg()) { case : break; default: break; }*/ return true; } //-------------------------------------------------------------------- // CLASSE PER RIPARTIZIONI RIGHE E TESTATE //-------------------------------------------------------------------- class TRipartizione : public TMultiple_rectype { public: TRipartizione(TString16 codice); }; TRipartizione::TRipartizione(TString16 codice) : TMultiple_rectype(LF_RIP) { add_file(LF_RRIP, RRIP_CODICE); if (codice.not_empty()) read(); } //-------------------------------------------------------------------- // APPLICAZIONE //-------------------------------------------------------------------- class TRib_movanal_app : public TSkeleton_application { TRib_movanal_msk * _mask; TCache_ripartizioni _cache_rip; bool _definitivo; virtual const char * extra_modules() const {return "cm";} //deve funzionare anche per le commesse protected: virtual bool create(); virtual bool destroy(); virtual void main_loop(); static bool cappotta_movimento(const TRelation& rel, void* pJolly); void implode_rows(const TRecord_array& input_rows, TRecord_array& compact_rows); bool explode_rows(const TRecord_array& input_rows, TRecord_array& output_rows); bool can_merge_rows(const TRectype& compact_rec, const TRectype& rec); bool ori_present(const TRectype& rec); public: TRib_movanal_app() {} }; bool TRib_movanal_app::create() { _mask = new TRib_movanal_msk; return TSkeleton_application::create(); } bool TRib_movanal_app::destroy() { delete _mask; return TSkeleton_application::destroy(); } static void copia_campo (const TRectype& src, const char* campo_src, TRectype& dst, const char* campo_dst) { const TString& valore = src.get(campo_src); if (!valore.blank()) dst.put(campo_dst, valore); } static void taglia_campo (TRectype& src, const char* campo_src, TRectype& dst, const char* campo_dst) { copia_campo(src, campo_src, dst, campo_dst); src.zero(campo_src); } bool TRib_movanal_app::can_merge_rows(const TRectype& compact_rec, const TRectype& rec) { return (compact_rec.get(RMOVANA_CODCCORI) == rec.get(RMOVANA_CODCCORI) && compact_rec.get(RMOVANA_CODCMSORI) == rec.get(RMOVANA_CODCMSORI) && compact_rec.get(RMOVANA_CODFASEORI) == rec.get(RMOVANA_CODFASEORI) && compact_rec.get(RMOVANA_CODCONTORI) == rec.get(RMOVANA_CODCONTORI) ); } bool TRib_movanal_app::ori_present(const TRectype& rec) { return (rec.get(RMOVANA_CODCCORI).not_empty() || rec.get(RMOVANA_CODCMSORI).not_empty() || rec.get(RMOVANA_CODFASEORI).not_empty() || rec.get(RMOVANA_CODCONTORI).not_empty()); } void TRib_movanal_app::implode_rows(const TRecord_array& input_rows, TRecord_array& compact_rows) { for (int r = 1; r <= input_rows.rows(); r++) { const TRectype& rec = input_rows.row(r); //record originale //se esiste almeno un campo origine compilato puo' implodere, senno' lascia perdere if (ori_present(rec)) { int i; for (i = compact_rows.rows(); i > 0; i--) //giro sulle righe gia' compattate per scoprire se { //il nostro record esiste gia' o e' da aggiungere const TRectype& nuovo_rec = compact_rows.row(i); // if (can_merge_rows(nuovo_rec, rec)) //se esiste gia'... break; } if (i > 0) //...aggiunge solo importo e sezione... { const TImporto imp_rec(rec.get_char(RMOVANA_SEZIONE), rec.get_real(RMOVANA_IMPORTO)); TRectype& compact_rec = compact_rows.row(i, false); //record originale TImporto imp_orig(compact_rec.get_char(RMOVANA_SEZIONE), compact_rec.get_real(RMOVANA_IMPORTO)); imp_orig += imp_rec; imp_orig.normalize(); compact_rec.put(RMOVANA_SEZIONE, imp_orig.sezione()); compact_rec.put(RMOVANA_IMPORTO, imp_orig.valore()); } else //...senno' aggiunge direttamente tutta la riga { TRectype* newrec = new TRectype(rec); //record destinazione newrec->put(RMOVANA_NUMRIG, compact_rows.rows() + 1); compact_rows.add_row(newrec); } } else { TRectype* newrec = new TRectype(rec); newrec->put(RMOVANA_NUMRIG, compact_rows.rows() + 1); compact_rows.add_row(newrec); } } //ripristina i campi originali sul record di destinazione for (int k = 1; k <= compact_rows.rows(); k++) { TRectype& compact_rec = compact_rows.row(k, false); if (ori_present(compact_rec)) { taglia_campo(compact_rec, RMOVANA_CODCCORI, compact_rec, RMOVANA_CODCCOSTO); taglia_campo(compact_rec, RMOVANA_CODCMSORI, compact_rec, RMOVANA_CODCMS); taglia_campo(compact_rec, RMOVANA_CODFASEORI, compact_rec, RMOVANA_CODFASE); taglia_campo(compact_rec, RMOVANA_CODCONTORI, compact_rec, RMOVANA_CODCONTO); } } } bool TRib_movanal_app::explode_rows(const TRecord_array& input_rows, TRecord_array& output_rows) { bool ho_cambiato_qualchecosa = false; for (int r = 1; r <= input_rows.rows(); r++) { const TRectype& rec = input_rows.row(r); const TRecord_array& rrip = _cache_rip.righe(rec.get(RMOVANA_CODCCOSTO), rec.get(RMOVANA_CODCMS)); if (rrip.rows() > 0) //ci sono righe di ripartizione { // Importo totale da distribuire arrotondato ai decimali della valuta di conto TGeneric_distrib distrib(rec.get_real(RMOVANA_IMPORTO), TCurrency::get_firm_dec()); // Calcolo tutte le percentuali da ripartire int i; for (i = 1; i <= rrip.rows(); i++) distrib.add(rrip[i].get_real(RRIP_RIPARTO)); for (i = 1; i <= rrip.rows(); i++) { TRectype* newrec = new TRectype(rec); newrec->put(RMOVANA_NUMRIG, output_rows.rows() + 1); const real imp = distrib.get(); // Legge la quota da distribuire newrec->put(RMOVANA_IMPORTO, imp); //e la mette nella nuova riga //poi copia i valori dei campi cdc,cms,fsc,in quelli di tipo ori (nello stesso record) copia_campo(rec, RMOVANA_CODCCOSTO, *newrec, RMOVANA_CODCCORI); copia_campo(rec, RMOVANA_CODCMS, *newrec, RMOVANA_CODCMSORI); copia_campo(rec, RMOVANA_CODFASE, *newrec, RMOVANA_CODFASEORI); copia_campo(rec, RMOVANA_CODCONTO, *newrec, RMOVANA_CODCONTORI); //e mette nei campi std i valori che trova nelle righe ripartizione copia_campo(rrip[i], RRIP_CODCOSTO, *newrec, RMOVANA_CODCCOSTO); copia_campo(rrip[i], RRIP_CODCMS, *newrec, RMOVANA_CODCMS); copia_campo(rrip[i], RRIP_CODFASE, *newrec, RMOVANA_CODFASE); copia_campo(rrip[i], RRIP_CODCONTO, *newrec, RMOVANA_CODCONTO); output_rows.add_row(newrec); ho_cambiato_qualchecosa = true; } } else //nessuna riga di ripartizione->aggiungo la riga input all'output { TRectype* newrec = new TRectype(rec); newrec->put(RMOVANA_NUMRIG, output_rows.rows() + 1); output_rows.add_row(newrec); } } return ho_cambiato_qualchecosa; } bool TRib_movanal_app::cappotta_movimento(const TRelation& rel, void* pJolly) { TRib_movanal_app& app = *(TRib_movanal_app*)pJolly; TAnal_mov& anal_mov = (TAnal_mov&)rel.curr(); //movimento analitica TRecord_array& input_rows = anal_mov.body(); //record_array con le righe del mov_anal (INPUT) //Per prima cosa prende le righe del movimento su RMOVANA e le ricompatta.. TRecord_array compact_rows = input_rows; //record array con le righe compattate da creare con la compact_rows.destroy_rows(); //implode_rows() //Imploditore app.implode_rows(input_rows, compact_rows); //..poi lo riesplode in tutte le righe che possono nascere secondo le regole delle ripartizioni! TRecord_array output_rows = input_rows; //crea il record_array di output come copia dell'INPUT.. output_rows.destroy_rows(); //..e poi lo pulisce bool do_rewrite = false; //Esploditore if (app.explode_rows(compact_rows, output_rows)) { input_rows = output_rows; //rimette i record elaborati negli originali do_rewrite = true; } if (app._definitivo) //se l'elaborazione e' definitiva... { anal_mov.put(MOVANA_BLOCCATO, 'X'); //..mette bloccato = X nella testata del movimento do_rewrite = true; } if (do_rewrite) //se ha elaborato delle righe e/o e' una elaborazione definitiva, riscrive la.. anal_mov.rewrite(rel.lfile()); //testata ed aggiorna i saldi return true; } void TRib_movanal_app::main_loop() { while (_mask->run() == K_ENTER) { //avvisa l'utente scapestrato che se fa una elaborazione definitiva blocchera' i movimenti //che processa _definitivo = _mask->get_bool(F_DEFINITIVO); //deve scandire il file MOVANA con chiave 2 (per data e numero di registrazione) TRelation rel_movana(LF_MOVANA); TRectype darec(LF_MOVANA), arec(LF_MOVANA); darec.put(MOVANA_DATAREG, _mask->get_date(F_DATAINI)); arec.put(MOVANA_DATAREG, _mask->get_date(F_DATAFIN)); TString filtro; filtro << "BLOCCATO!=\"X\""; TCursor cur_movana(&rel_movana, filtro, 2, &darec, &arec); const long items = cur_movana.items(); //usa la scan dei TCursor,quindi niente progind e for,x' gia' nel metodo if (items > 0) { bool run = yesno_box(FR("Si desidera elaborare %ld movimenti?"), items); if (run && _definitivo) run = yesno_box(FR("Selezionata l'elaborazione definitiva\nSi desidera proseguire?")); if (run) { rel_movana.lfile().set_curr(new TAnal_mov); //il record principale della rel e' un TMov_anal!! cur_movana.scan(cappotta_movimento, this, "Ribaltamento movimenti..."); } } else message_box(TR("Non ci sono movimenti da elaborare nel periodo selezionato")); } } int ca2200(int argc, char* argv[]) { TRib_movanal_app app; app.run(argc, argv, "Ribaltamento movimenti di analitica"); return 0; }