#include #include #include #include #include #include "../cg/cglib01.h" #include "calib01.h" #include "calib02.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 TAnal_report_mask { protected: virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly); void save_to_ini(); void load_from_ini(); public: TRib_movanal_msk(); }; void TRib_movanal_msk::save_to_ini() { TConfig ini(CONFIG_DITTA, "ca"); // Cancella tutte le variabili di pareggio int j; for (j = 1; ini.remove("Pareggio", j); j++); TSheet_field& sf = sfield(F_RIGHE); const int idx = sf.cid2index(F_CODCAUS); // Salva tutte le righe dello sheet nel formato // Pareggio(1) = Causale|Costo|Commessa|Fase j = 0; FOR_EACH_SHEET_ROW(sf, i, row) { TToken_string par = row->get(idx); // Codice causale if (!par.blank()) { TAnal_bill bill; const int flags = get_row_bill(sf, i, bill); if (flags != 0) { if (flags & 1) par.add(bill.costo(), 1); if (flags & 2) par.add(bill.commessa(), 2); if (flags & 4) par.add(bill.fase(), 3); ini.set("Pareggio", par, NULL, true, ++j); } } } } void TRib_movanal_msk::load_from_ini() { // Svuota lo sheet TSheet_field& sf = sfield(F_RIGHE); sf.destroy(); // Carica tutte le variabili di pareggio nello sheet TConfig ini(CONFIG_DITTA, "ca"); TToken_string par; for (int j = 1; ; j++) { par = ini.get("Pareggio", NULL, j); if (par.empty_items()) break; const TAnal_bill bill("", par.get(1), par.get(2), par.get(3)); set_row_bill(sf, -1, bill); } } bool TRib_movanal_msk::on_field_event(TOperable_field& o, TField_event e, long jolly) { switch (o.dlg()) { case F_DATAINI: case F_DATAFIN: if (e == fe_close) { const int anno = get_int(F_ANNO); TEsercizi_contabili esc; //..le date devono essere incluse nell'esercizio selezionato! const TDate data(o.get()); if (!data.empty() && esc.date2esc(data) != anno) return error_box(TR("La data deve appartenere all'anno selezionato")); } break; case DLG_OK: case DLG_SAVEREC: if (e == fe_button) save_to_ini(); break; default: break; } return TAnal_report_mask::on_field_event(o, e, jolly); } TRib_movanal_msk::TRib_movanal_msk() : TAnal_report_mask("ca2200a") { create_sheet(F_RIGHE); load_from_ini(); } //-------------------------------------------------------------------- // APPLICAZIONE //-------------------------------------------------------------------- class TRib_movanal_app : public TSkeleton_application { TCache_ripartizioni _cache_rip; bool _definitivo; TAssoc_array _caus_cms; virtual const char* extra_modules() const { return "cm"; } //deve funzionare anche per le commesse protected: virtual void main_loop(); bool explode_rows(const TRecord_array& input_rows, TRecord_array& output_rows, const int annoes); bool pareggia_commessa(TAnal_mov& anal_mov); public: bool cappotta_movimento(TAnal_mov& anal_mov); TRib_movanal_app(){} }; bool TRib_movanal_app::explode_rows(const TRecord_array& input_rows, TRecord_array& output_rows, const int annoes) { bool ho_cambiato_qualchecosa = false; for (int r = 1; r <= input_rows.rows(); r++) { const TRectype& rec = input_rows.row(r); TAnal_bill zio(rec); const int rmovana_indbil = zio.indicatore_bilancio(); const TAnal_ripartizioni_batch& rrip = _cache_rip.righe(rec.get(RMOVANA_CODCCOSTO), rec.get(RMOVANA_CODCMS), annoes, rmovana_indbil); //ci sono righe di ripartizione const int righe_ripartizione = rrip.rows(); bool ripartisci = righe_ripartizione > 0; if (ripartisci) { // 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 <= righe_ripartizione; i++) distrib.add(rrip[i].get_real(RRIP_RIPARTO)); for (i = 1; i <= righe_ripartizione; i++) { const real imp = distrib.get(); // Legge la quota da distribuire if (imp != ZERO) { TRectype* newrec = new TRectype(rec); newrec->put(RMOVANA_NUMRIG, output_rows.rows() + 1); 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) ca_copia_campo(rec, RMOVANA_CODCCOSTO, *newrec, RMOVANA_CODCCORI); ca_copia_campo(rec, RMOVANA_CODCMS, *newrec, RMOVANA_CODCMSORI); ca_copia_campo(rec, RMOVANA_CODFASE, *newrec, RMOVANA_CODFASEORI); ca_copia_campo(rec, RMOVANA_CODCONTO, *newrec, RMOVANA_CODCONTORI); //e mette nei campi std i valori che trova nelle righe ripartizione ca_copia_campo(rrip[i], RRIP_CODCOSTO, *newrec, RMOVANA_CODCCOSTO); ca_copia_campo(rrip[i], RRIP_CODCMS, *newrec, RMOVANA_CODCMS); ca_copia_campo(rrip[i], RRIP_CODFASE, *newrec, RMOVANA_CODFASE); ca_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::pareggia_commessa(TAnal_mov& anal_mov) { bool ho_cambiato_qualchecosa = false; const TString& codcaus = anal_mov.get(MOVANA_CODCAUS); const TAnal_bill* cms = (const TAnal_bill*)_caus_cms.objptr(codcaus); if (cms != NULL) // La causale del movimento e' tra quelle da pareggiare { const TImporto totdoc(anal_mov.get_char(MOVANA_SEZIONE), anal_mov.get_real(MOVANA_TOTDOC)); if (!totdoc.is_zero()) // Movimento da pareggiare { TRecord_array& body = anal_mov.body(); // Cerco la commessa/fase/costo tra le righe esistenti int i; for (i = body.last_row(); i > 0; i--) { const TRectype& row = body[i]; if ((cms->costo().blank() || row.get(RMOVANA_CODCCOSTO) == cms->costo()) && (cms->commessa().blank() || row.get(RMOVANA_CODCMS) == cms->commessa()) && (cms->fase().blank() || row.get(RMOVANA_CODFASE) == cms->fase())) break; } // Se non trovo nessuna riga compatibile, me la creo if (i <= 0) { TRectype& rmovana = anal_mov.new_row(); rmovana.put(RMOVANA_DESCR, TR("Pareggio commessa")); rmovana.put(RMOVANA_CODCCOSTO, cms->costo()); rmovana.put(RMOVANA_CODCMS, cms->commessa()); rmovana.put(RMOVANA_CODFASE, cms->fase()); i = rmovana.get_int(RMOVANA_NUMRIG); } // Sottraggo all'importo della riga il totale documento, // il quale verra' quindi azzerato TRectype& rmovana = body[i]; TImporto importo(rmovana.get_char(RMOVANA_SEZIONE), rmovana.get_real(RMOVANA_IMPORTO)); importo -= totdoc; importo.normalize(); rmovana.put(RMOVANA_SEZIONE, importo.sezione()); rmovana.put(RMOVANA_IMPORTO, importo.valore()); anal_mov.put(MOVANA_TOTDOC, ZERO); ho_cambiato_qualchecosa = true; } } return ho_cambiato_qualchecosa; } bool TRib_movanal_app::cappotta_movimento(TAnal_mov& anal_mov) { 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(); intanto le azzera per sicurezza //Imploditore ca_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 (explode_rows(compact_rows, output_rows, anal_mov.get_int(MOVANA_ANNOES))) { input_rows = output_rows; //rimette i record elaborati negli originali do_rewrite = true; } if (pareggia_commessa(anal_mov)) do_rewrite = true; if (_definitivo) //se l'elaborazione e' definitiva... { anal_mov.put(MOVANA_BLOCCATO, 'X'); //..mette bloccato = X nella testata del movimento do_rewrite = true; } return do_rewrite; //se ha elaborato delle righe e/o e' una elaborazione definitiva, riscrive la.. } static bool cappotta_callback(const TRelation& rel, void* pJolly) { TRib_movanal_app& app = *(TRib_movanal_app*)pJolly; const long numreg = rel.curr().get_long(MOVANA_NUMREG); TAnal_mov anal_mov(numreg); //se va tutto bene riscrive l'intero movimento analitico con conseguente ricalcolo saldi if (app.cappotta_movimento(anal_mov)) anal_mov.rewrite(rel.lfile()); return true; } void TRib_movanal_app::main_loop() { TRib_movanal_msk mask; 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); const TDate & dal = mask.get_date(F_DATAINI); darec.put(MOVANA_DATACOMP, dal); const TDate & al = mask.get_date(F_DATAFIN); arec.put(MOVANA_DATACOMP, al); _cache_rip.set_esercizio(mask.get_int(F_ANNO)); TCursor cur_movana(&rel_movana, "BLOCCATO!=\"X\"", 2, &darec, &arec); const long items = cur_movana.items(); if (items > 0) { bool run = yesno_box(FR("Si desidera elaborare %ld movimenti?"), items); if (run && _definitivo) run = yesno_box(TR("E' stata selezionata l'elaborazione definitiva\nSi desidera proseguire?")); if (run) { // Riempie la lista della causali dei movimenti da pareggiare _caus_cms.destroy(); TSheet_field& sf = mask.sfield(F_RIGHE); const int pos_codcaus = sf.cid2index(F_CODCAUS); FOR_EACH_SHEET_ROW(sf, i, row) { const TString4 codcaus = row->get(pos_codcaus); if (codcaus.full()) { TAnal_bill* bill = new TAnal_bill; if (mask.get_row_bill(sf, i, *bill) != 0) _caus_cms.add(codcaus, bill); else delete bill; } } cur_movana.scan(cappotta_callback, this, TR("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, TR("Ribaltamento movimenti di analitica")); return 0; }