campo-sirio/ce/ce3300.cpp

593 lines
22 KiB
C++
Raw Normal View History

#include <applicat.h>
#include <form.h>
#include <printer.h>
#include <recarray.h>
#include <utility.h>
#include "ce3.h"
#include "celib.h"
#include "..\cg\cglib01.h"
#include "ce2101.h"
#include "ce3300a.h"
#include "ce3300.h"
#include "ammce.h"
#include "ammmv.h"
#include "cespi.h"
#include "movam.h"
#include "movce.h"
#include "salce.h"
//===============================================================================================//
//-----FORM--------------------------------------------------------------------------------------//
class TForm_prospettocesp : public TForm_cespiti
{
public:
virtual bool validate(TForm_item &cf, TToken_string &s);
void set_testata() {set_header(1,TRUE);}
void set_pedata() {set_footer(1,FALSE); set_footer(1,TRUE);}
TPrint_section& get_body() {return section('B', odd_page);}
TForm_prospettocesp();
virtual ~TForm_prospettocesp();
};
TForm_prospettocesp::TForm_prospettocesp() :TForm_cespiti ("ce3300a") //costruttore
{
}
TForm_prospettocesp::~TForm_prospettocesp()
{
}
bool TForm_prospettocesp::validate(TForm_item &cf, TToken_string &s)
{
return TForm_cespiti::validate(cf,s); //richiama la validate standard della classe genitore (TForm_cespiti)
}
//==============================================================================================//
//-----AUTOMASK---------------------------------------------------------------------------------//
class TStampaprospetto_mask : public TAutomask
{
TRelation * _rel;
TCursor * _cur;
protected:
bool on_field_event(TOperable_field& o, TField_event e, long jolly);
public:
TStampaprospetto_mask();
virtual ~TStampaprospetto_mask(){};
};
TStampaprospetto_mask::TStampaprospetto_mask() :TAutomask ("ce3300a")
{
ditta_cespiti().init_mask(* this);
}
bool TStampaprospetto_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
case F_SITFISC :
if (e == fe_close)
{
if (!get_bool(F_SITFISC) && !get_bool(F_SITCIV) && !get_bool(F_SITGEST)) //deve essere selezionata almeno 1 situaz.
return error_box("Selezionare almeno una delle Situazioni da stampare");
}
break;
default: break;
}
return TRUE;
}
//=======================================================================================================================//
struct TTotali : public TObject
{
real _tot_csto;
real _tot_riv;
real _tot_riveser;
real _tot_acqincr;
real _tot_cesselim2;
real _tot_fondinieser;
real _tot_incr;
real _tot_cesselim3;
real _tot_reinplus;
real _tot_ammnor;
real _tot_ammacc;
real _tot_ammant;
void azzera();
TTotali& operator += (const TTotali& t);
};
void TTotali::azzera()
{
_tot_csto = 0;
_tot_riv = 0;
_tot_riveser = 0;
_tot_acqincr = 0;
_tot_cesselim2 = 0;
_tot_fondinieser = 0;
_tot_incr = 0;
_tot_cesselim3 = 0;
_tot_reinplus = 0;
_tot_ammnor = 0;
_tot_ammacc = 0;
_tot_ammant = 0;
}
//-----------------------------------------------------------------------------------------------------------------------//
TTotali& TTotali::operator += (const TTotali& t)
{
_tot_csto += t._tot_csto;
_tot_riv += t._tot_riv;
_tot_riveser += t._tot_riveser;
_tot_acqincr += t._tot_acqincr;
_tot_cesselim2 += t._tot_cesselim2;
_tot_fondinieser += t._tot_fondinieser;
_tot_incr += t._tot_incr;
_tot_cesselim3 += t._tot_cesselim3;
_tot_reinplus += t._tot_reinplus;
_tot_ammnor += t._tot_ammnor;
_tot_ammacc += t._tot_ammacc;
_tot_ammant += t._tot_ammant;
return *this; //ritorna se stesso, quindi i valori dei totali
}
//=======================================================================================================================//
//-----SKELETON APPLICATION----------------------------------------------------------------------------------------------//
class TStampa_prospetto : public TSkeleton_application
{
TStampaprospetto_mask * _mask;
TForm_prospettocesp * _form;
protected:
virtual bool create();
virtual bool destroy();
virtual void main_loop();
void set_intestazione( const int tipo, const int ordinamento);
void set_pavimentazione();
void stampa_totali_cat(const TString& codicecat, const TString& descrcat); //stampa sul form i valori totali per categoria
void stampa_totali_tipo(TTipo_cespite tcesp); //stampa sul form i valori totali per tipo cespite (materiale, immateriale, pluriennale)
void stampa_totali_generali(); //stampa sul form i valori totali per tutti i cespiti
void fill_body(const TTotali& tot); //riempie il campo body con tutti i totali
void print_body(); //stampa effettivamente il body
void set_field(int id, const real& val); //mette in un campo del body odd un valore numerico
void set_field(int id, const char* val); //mette in un campo del body odd una stringa
void aggiorna_totali(TCursor& cur, const int tipo, TTipo_cespite tcesp); //calcola effettivamente i totali di ciascuna categoria
public:
TStampa_prospetto() {}
private:
TDate _dataini;
TDate _datafine;
TTotali _cat, _mtr, _gen; //sono i tre set di totali (categoria, materiali, generali)
};
bool TStampa_prospetto::create()
{
open_files(LF_CESPI, LF_SALCE, LF_AMMCE, LF_MOVCE, LF_AMMMV, 0);
_mask = new TStampaprospetto_mask;
_form = new TForm_prospettocesp;
return TSkeleton_application::create();
}
bool TStampa_prospetto::destroy()
{
delete _mask;
delete _form;
return TSkeleton_application::destroy();
}
//------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::set_intestazione( const int tipo, const int ordinamento)
{
// scrive l'header first, contenente i dati della ditta e dell'esercizio
_form->find_field('H', first_page, FR_CODDITTA).set(_mask->get(F_CODDITTA));
_form->find_field('H', first_page, FR_RAGSOC).set(_mask->get(F_DESCRDITTA));
_form->find_field('H', first_page, FR_GRUPPO).set(_mask->get(F_GRUPPO));
_form->find_field('H', first_page, FR_D_GRUPPO).set(_mask->get(F_D_GRUPPO));
_form->find_field('H', first_page, FR_SPECIE).set(_mask->get(F_SPECIE));
_form->find_field('H', first_page, FR_D_SPECIE).set(_mask->get(F_D_SPECIE));
_form->find_field('H', first_page, FR_DATAINIZIO).set(_dataini);
_form->find_field('H', first_page, FR_DATAFINE).set(_datafine);
// in base all'ordinamento (per categoria o per impianto) scrive la riga con codice e descrizione
if (ordinamento == 0)
{
_form->find_field('H', first_page, FR_INT_COD).set("@bCat.@r");
_form->find_field('H', first_page, FR_INT_DESC).set("@bDescrizione categoria@r");
}
else
{
_form->find_field('H', first_page, FR_INT_COD).set("Imp.");
_form->find_field('H', first_page, FR_INT_DESC).set(" Descr. impianto");
}
//in base al(ai) tipo(i) di situazione cambia una riga dell'header
switch(tipo)
{
case 1:
_form->find_field('H', first_page, FR_SITUAZIONE).set("fiscale");
break;
case 2:
_form->find_field('H', first_page, FR_SITUAZIONE).set("civilistica");
break;
case 3:
_form->find_field('H', first_page, FR_SITUAZIONE).set("gestionale");
break;
}
_form->set_testata();
}
//-----------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::set_pavimentazione()
{
_form->set_pedata();
}
//-----------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::print_body()
{
set_pavimentazione(); // stampa il fondo pagina
TPrint_section& body = _form->get_body();
body.update();
if (body.height() > printer().rows_left())
printer().formfeed();
for (word i = 0; i < body.height(); i++) // stampa le righe del body
printer().print(body.row(i));
}
//-----------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::stampa_totali_cat(const TString& codicecat, const TString& descrcat )
{
// scrive codice e descrizione della categoria di cui stampa i valori
set_field(FR_TC_CAT,codicecat);
set_field(FR_TC_D_CAT,descrcat);
// riempie il body con i totali per categoria
fill_body(_cat);
// stampa effettivamente il body sul form
print_body();
// somma sui totali materiali
_mtr += _cat;
_gen += _cat;
}
//-------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::stampa_totali_tipo(TTipo_cespite tcesp)
{
// scrive il tipo di cespiti di cui calcola il totale
set_field(FR_TC_CAT,"");
TString80 tipodescr = "TOTALI BENI ";
switch (tcesp)
{
case tc_pluriennale: tipodescr << "PLURIENNALI"; break;
case tc_immateriale: tipodescr << "IMMATERIALI"; break;
default: tipodescr << "MATERIALI"; break;
}
set_field(FR_TC_D_CAT,tipodescr);
// riempie il body con i totali per tipologia cespite (per situazione)
fill_body(_mtr);
// stampa effettivamente il body sul form
print_body();
}
//-------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::stampa_totali_generali()
{
// scrive TOTALI GENERALI
set_field(FR_TC_CAT,"");
set_field(FR_TC_D_CAT,"TOTALI GENERALI");
// riempie il body con i totali generali per situazione selezionata
fill_body(_gen);
// stampa effettivamente il body sul form
print_body();
}
//-------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::set_field(int id, const real& val)
{
_form->find_field('B', odd_page, id).set(val.string());
}
//-------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::set_field(int id, const char* val)
{
_form->find_field('B', odd_page, id).set(val);
}
//-------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::fill_body(const TTotali& tot)
{
// riempie il body odd, contenente i totali; lo fa chiamando la set_field per ogni campo
set_field(FR_TC_CSTO,tot._tot_csto);
set_field(FR_TC_TOTRIV,tot._tot_riv);
real tempval1 = tot._tot_csto+tot._tot_riv;
set_field(FR_TC_VALINIES,tempval1);
set_field(FR_TC_RIVALES,tot._tot_riveser);
set_field(FR_TC_ACQINCR,tot._tot_acqincr);
set_field(FR_TC_CESSELIM2,tot._tot_cesselim2);
tempval1 += tot._tot_riveser + tot._tot_acqincr - tot._tot_cesselim2;
set_field(FR_TC_VALBIL,tempval1);
set_field(FR_TC_FONDINIES,tot._tot_fondinieser);
set_field(FR_TC_INCR,tot._tot_incr);
set_field(FR_TC_CESSELIM3,tot._tot_cesselim3);
set_field(FR_TC_REINPLUS,tot._tot_reinplus);
set_field(FR_TC_AMMNOR,tot._tot_ammnor);
set_field(FR_TC_AMMACC,tot._tot_ammacc);
set_field(FR_TC_AMMANT,tot._tot_ammant);
real tempval2 = tot._tot_fondinieser + tot._tot_incr - tot._tot_cesselim3 + tot._tot_reinplus + tot._tot_ammnor + tot._tot_ammacc +tot._tot_ammant;
set_field(FR_TC_FONDBIL,tempval2);
tempval2 = tempval1 - tempval2;
set_field(FR_TC_RESBIL,tempval2);
}
//-------------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::aggiorna_totali(TCursor& cur, const int tipo, TTipo_cespite tcesp)
{
// valori della riga 1 (dipendenti da tipo solo le rivgf/rivgc)
TRectype& recsalce = cur.curr(LF_SALCE);
real csto = recsalce.get(SALCE_CSTO);
if (tipo == 1)
{
real vnonamm1 = recsalce.get(SALCE_VNONAMM);
_cat._tot_csto += csto - vnonamm1;
}
else
_cat._tot_csto += csto;
real riv75 = recsalce.get(SALCE_RIV75);
real riv83 = recsalce.get(SALCE_RIV83);
real riv90 = recsalce.get(SALCE_RIV90);
real riv91 = recsalce.get(SALCE_RIV91);
if (tipo == 1)
{
real rivgf = recsalce.get(SALCE_RIVGF);
_cat._tot_riv += riv75 + riv83 + riv90 + riv91 + rivgf;
}
else
{
real rivgc = recsalce.get(SALCE_RIVGC);
_cat._tot_riv += riv75 + riv83 + riv90 + riv91 + rivgc;
}
// valori della riga 2 (e, gi<67> che si fa la scansione dei movimenti, anche i valori dei movam della riga 3)
// (i valori della riga 2 non dipendono da tipo, mentre quelli della riga 3 si, in quanto hanno movam)
TRectype recmovce(LF_MOVCE);
recmovce.put(MOVCE_IDCESPITE, cur.curr().get(CESPI_IDCESPITE));
TRelation relmovce(LF_MOVCE);
// viene aggiunta la relazione su movam (che contiene il filtro su tpamm dovuto al tipo di situazione scelto nella maschera)..
TString expr;
expr << "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==" << tipo;
relmovce.add(LF_MOVAM, expr);
//.. e quindi viene aggiunta la relazione su ammmv (che contiene il filtro su tpamm dovuto al tipo di situazione scelto nella
// maschera) utilizzando la stessa espressione di filtro, in quanto la chiave di ammmv <20> identica a quella di movam (ol<6F>!)
relmovce.add(LF_AMMMV, expr);
TCursor curmovce (&relmovce, "", 2, &recmovce, &recmovce);
long num1 = curmovce.items();
curmovce.freeze();
real amv_ammnor;
real amv_ammacc;
real amv_ammant;
for (curmovce=0; curmovce.pos()<num1; ++curmovce)
{
const TRectype& mov = curmovce.curr();
const TRectype& amm = curmovce.curr(LF_MOVAM);
const TRectype& amv = curmovce.curr(LF_AMMMV);
const TDate dtmov = mov.get(MOVCE_DTMOV);
if (dtmov >= _dataini && dtmov <= _datafine)
{
const TString8 codmov = mov.get(MOVCE_CODMOV);
const char tmc = cache().get("%TMC", codmov, "S6")[0]; //prende il valore del campo S6 nella tabella tipi movimento
const char segno = mov.get_char(MOVCE_SEGNO);
const real signum = segno == '-' ? -1.0 : +1.0; //serve per sommare i movimenti con il loro segno effettivo
riv75 = mov.get_real(MOVCE_RIV75);
riv83 = mov.get_real(MOVCE_RIV83);
riv90 = mov.get_real(MOVCE_RIV90);
riv91 = mov.get_real(MOVCE_RIV91);
csto = mov.get_real(MOVCE_CSTO);
// inquietante modo di selezionare la rivg (rivgf o rivgc) in base al tipo senza usare una if else!
real rivg = mov.get_real(tipo == 1 ? MOVCE_RIVGF : MOVCE_RIVGC);
real vnonamm2 = mov.get_real(MOVCE_VNONAMM);
real qnor = amm.get_real(MOVAM_QNOR);
real qacc = amm.get_real(MOVAM_QACC);
real qant = amm.get_real(MOVAM_QANT);
if (tmc == 'R')
_cat._tot_riveser += (riv75 + riv83 + riv90 + riv91 + rivg) * signum;
if (tmc == 'I' || (tmc <= ' ' && segno == '+'))
{
_cat._tot_acqincr += (csto - vnonamm2 + riv75 + riv83 + riv90 + riv91 + rivg) * signum;
_cat._tot_incr += (qnor + qacc + qant) * signum;
}
if (tmc == 'E' || (tmc <= ' ' && segno == '-'))
{
_cat._tot_cesselim2 += (csto - vnonamm2 + riv75 + riv83 + riv90 + riv91 + rivg) * (-signum);
_cat._tot_cesselim3 += (qnor + qant + qacc) * (-signum);
}
if (tmc == 'P')
_cat._tot_reinplus += (mov.get_real(MOVCE_PLUSREIN)) * signum;
// solo nei casi con tipo =2 e/o 3 viene preso l'ammortamento da ammmv (che verr<72> poi sommato nella riga 4, pi<70> sotto, a quello
// preso da ammce); l'ammortamento viene preso qui in quanto <20> relativo ai movimenti che vengono qui scanditi
if (tipo != 1)
{
amv_ammnor += (amv.get_real(AMMMV_QNOR)) * signum;
amv_ammacc += (amv.get_real(AMMMV_QACC)) * signum;
amv_ammant += (amv.get_real(AMMMV_QANT)) * signum;
}
} //fine controllo sulle date
} //fine scansione sui movimenti
// valori delle righe 3 e 4 di ammce (questi valori dipendono dal tipo di situazione selezionato nella maschera)
// record con chiave idcespite,codes,tpamm
TRectype recammce(LF_AMMCE);
recammce.put(AMMCE_IDCESPITE, cur.curr().get(CESPI_IDCESPITE));
recammce.put(AMMCE_CODES, _mask->get(F_ESERCIZIO));
// filtro sul tpamm (va messo per non prendere tutti gli ammortamenti (dei 3 tipi) assieme)
expr.cut(0);
expr << AMMCE_TPAMM << "=" << tipo;
TRelation relammce(LF_AMMCE);
TCursor curammce (&relammce, expr, 1, &recammce, &recammce);
long num2 = curammce.items();
curammce.freeze();
// scandisce gli ammce del cespite (al massimo 2 per ogni codes, ovvero iniziale e finale)
for (curammce=0; curammce.pos()<num2; ++curammce)
{
const TRectype& amm = curammce.curr();
// se tpsaldo = 1 (inizio) gli ammortamenti sono....
if (amm.get_int(AMMCE_TPSALDO) == 1)
{
real qnor = amm.get_real(AMMCE_QNOR);
real qacc = amm.get_real(AMMCE_QACC);
real qant = amm.get_real(AMMCE_QANT);
_cat._tot_fondinieser += qnor + qant +qacc;
}
// se invece tpsaldo = 2 (fine) gli ammortamenti sono....
else
{
_cat._tot_ammnor += amm.get_real(AMMCE_QNOR);
_cat._tot_ammacc += amm.get_real(AMMCE_QACC);
_cat._tot_ammant += amm.get_real(AMMCE_QANT);
// se, mentre tpsaldo=2, ho anche tpamm =2 e/o 3, gli ammortamenti devono tenere conto anche di quelli sui movimenti, calcolati
// durante la scansione dei movimenti
if (tipo != 1)
{
_cat._tot_ammnor += amv_ammnor;
_cat._tot_ammacc += amv_ammacc;
_cat._tot_ammant += amv_ammant;
}
}
} // fine scansione sugli ammce
} // fine routine
//-----------------------------------------------------------------------------------------------------------------------//
void TStampa_prospetto::main_loop()
{
_mask->set(F_SITFISC,"X");
while (_mask->run() == K_ENTER)
{
// record su esercizio,gruppo,specie
TRectype rec(LF_CESPI);
const int esercizio = _mask->get_int(F_ESERCIZIO);
rec.put(CESPI_CODCGRA, _mask->get(F_GRUPPO));
rec.put(CESPI_CODSPA, _mask->get(F_SPECIE));
// relazione su lf_cespi e lf_salce
TRelation relcespi(LF_CESPI);
TString espr;
espr << "IDCESPITE==IDCESPITE|CODES==" << esercizio;
relcespi.add(LF_SALCE,espr);
// filtro su esercizio gruppo specie e data acquisto cespite sia <= alla data fine esercizio selezionato
TString filtro;
_dataini = _mask->get_date(F_INIZIO_ES);
_datafine = _mask->get_date(F_FINE_ES);
filtro << "(CODCGRA=\"" << _mask->get(F_GRUPPO)<< "\")&&" ;
filtro << "(CODSPA=\"" << _mask->get(F_SPECIE)<< "\")&&" ;
filtro << "(" << LF_SALCE << "->CODES=" << esercizio << ")&&" ;
filtro << "(ANSI(" << LF_CESPI << "->DTCOMP)<=" << _datafine.string(ANSI) << ")";
// prepara il cursore di tipo sorted perch<63> ho due tipi di ordinamento possibili: per categoria e per impianto
const int ordinamento = _mask->get_int(F_ORDINA);
TString ordin = ordinamento == 0 ? CESPI_CODCAT : CESPI_CODIMP;
ordin << "|" <<CESPI_IDCESPITE;
TSorted_cursor sortcur (&relcespi, ordin, filtro, 1, &rec, &rec);
sortcur.setregion(rec,rec);
sortcur.setfilter(filtro,TRUE);
long num = sortcur.items();
sortcur.freeze();
printer().open();
// scansione sulle 3 possibili situazioni stampabili
for (int j = 1; j <= 3; j++)
{
// stampa solo le situazioni selezionate
if (j == 1 && !_mask->get_bool(F_SITFISC))
continue;
if (j == 2 && !_mask->get_bool(F_SITCIV))
continue;
if (j == 3 && !_mask->get_bool(F_SITGEST))
continue;
// setta l'intestazione del form...
set_intestazione(j, ordinamento);
// ed il fondo pagina
set_pavimentazione();
// gestione categorie ed effettivo main loop di stampa
// azzera i totali generali (se mai non lo fossero)
_gen.azzera();
// scansiona sui 3 tipi di cespite (materiale, immateriale, pluriennale)
for (int i = 0; i <= 2; i++)
{
const TTipo_cespite tipocespite = (TTipo_cespite)i; // trasforma l'intero i in un tipo cespite
TString16 currcodcat = "@@"; //codice categoria iniziale (non si pu<70> metterlo nullo perch<63> potrebbe esistere)
TString80 currdescat = "";
_mtr.azzera(); // azzeratore tipi cespite (materiali, immateriali, pluriennali)
for (sortcur=0; sortcur.pos()<num; ++sortcur) //scansione su tutti i cespiti della categoria indicata in precedenza
{
const TCespite ces(sortcur.curr());
if (ces.tipo() == tipocespite) //considera solo i cespiti del tipo attualmente selezionato
{
const TString16 codcat = sortcur.curr().get(ordinamento == 0 ? CESPI_CODCAT : CESPI_CODIMP);
if (codcat != currcodcat) //cambia categoria
{
if (currcodcat != "@@")
stampa_totali_cat(currcodcat,currdescat); //serve per stampare l'ultima categoria (perch<63> ogni categoria viene stampata quando inizia la scansione della successiva)
_cat.azzera();
currcodcat = codcat;
if (ordinamento == 0) //se ordinato (ed aggregato) per categoria...
currdescat = ces.categoria().get("S0");
else //se ordinato (ed aggregato) per impianto...
currdescat = cache().get("CIM", currcodcat, "S0");
}
aggiorna_totali (sortcur, j, tipocespite);
}
} // fine scansione cespiti della categoria selezionata
if (currcodcat != "@@")
stampa_totali_cat(currcodcat,currdescat);
stampa_totali_tipo(tipocespite);
} // fine scansione tipi cespite
stampa_totali_generali();
// salta una pagina al termine della situazione stampata
printer().formfeed();
} // fine scansione su situazione da stampare (civilistica,fiscale,gestionale)
printer().close();
}
}
int ce3300(int argc, char* argv[])
{
TStampa_prospetto a;
a.run(argc,argv,"Stampa prospetto cespiti");
return 0;
}