campo-sirio/ca/ca2200.cpp
luca e9a4e4b36b Patch level :4.0 nopatch
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :correzioni dovute al passaggio al nuovo compilatore


git-svn-id: svn://10.65.10.50/trunk@14698 c028cbd2-c16b-5b4b-a496-9718f37d4682
2006-12-29 14:16:28 +00:00

414 lines
14 KiB
C++
Executable File

#include <applicat.h>
#include <automask.h>
#include <defmask.h>
#include <recarray.h>
#include <relation.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 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();
void implode_rows(const TRecord_array& input_rows, TRecord_array& compact_rows) const;
bool explode_rows(const TRecord_array& input_rows, TRecord_array& output_rows);
bool ori_present(const TRectype& rec) const;
void copia_campo(const TRectype& src, const char* campo_src, TRectype& dst, const char* campo_dst) const;
void taglia_campo(TRectype& src, const char* campo_src, TRectype& dst, const char* campo_dst) const;
bool can_merge_rows(const TRectype& compact_rec, const TRectype& rec) const;
bool pareggia_commessa(TAnal_mov& anal_mov);
public:
bool cappotta_movimento(TAnal_mov& anal_mov);
};
void TRib_movanal_app::copia_campo(const TRectype& src, const char* campo_src,
TRectype& dst, const char* campo_dst) const
{
const TString& valore = src.get(campo_src);
if (!valore.blank())
dst.put(campo_dst, valore);
}
void TRib_movanal_app::taglia_campo(TRectype& src, const char* campo_src,
TRectype& dst, const char* campo_dst) const
{
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) const
{
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) const
{
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) const
{
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 = 0;
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::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()
//Imploditore
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))
{
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);
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);
darec.put(MOVANA_DATAREG, mask.get_date(F_DATAINI));
arec.put(MOVANA_DATAREG, mask.get_date(F_DATAFIN));
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);
FOR_EACH_SHEET_ROW(sf, i, row)
{
const TString4 codcaus = row->get(0);
if (!codcaus.blank())
{
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;
}