campo-sirio/ca/ca2200.cpp

312 lines
10 KiB
C++
Raw Normal View History

#include <applicat.h>
#include <automask.h>
#include <progind.h>
#include <recarray.h>
#include <relation.h>
#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;
}