campo-sirio/src/ce/ce4100.cpp
bonazzi ac3bc208e9 Patch level : 12.0 426
Files correlati     : ce0.exe ce0a00.rep ce3.exe ce4.exe ce3900.msk ce3900b.rep ce4100a.msk ce4100b.mskce ce4500a.rep cemenu.men

MODIFICHE CRPA

Coefficiente di durata nella tabella esercizi cespiti
Ordinamento per cespite nella stampa inventario sintetico
Stampa etichette cespiti
Copia della ripartizione cespiti da un esercizio a un altro
Stampa del costo storico e del residuo nella stampa cespiti per analitica


git-svn-id: svn://10.65.10.50/branches/R_10_00@23998 c028cbd2-c16b-5b4b-a496-9718f37d4682
2017-07-26 00:22:02 +00:00

675 lines
20 KiB
C++
Executable File
Raw Blame History

#include <automask.h>
#include <defmask.h>
#include <progind.h>
#include <recarray.h>
#include <relapp.h>
#include <utility.h>
#include "../ca/commesse.h"
#include "../ca/calib01.h"
#include "../cg/cglib01.h"
#include "celib.h"
#include "salcecms.h"
#include "ce2101.h"
#include "ce4100a.h"
#include "ce4100b.h"
#include "cespi.h"
struct date_commessa : public TObject
{
TDate _dataini_cms, _datafine_cms;
};
class TCesp_anal_mask;
class TCesp_anal: public TRelation_application
{
TCesp_anal_mask *_msk; // maschera principale
TRelation *_rel; // relazione principale
//metodi virtuali obbligatori per gli oggetti TRelation_application
protected:
virtual bool user_create();
virtual bool user_destroy();
virtual TMask* get_mask(int mode) { return (TMask *)_msk; }
virtual bool changing_mask(int mode) { return false;}
virtual void init_query_mode(TMask& m);
virtual void init_query_insert_mode(TMask& m);
virtual void init_insert_mode(TMask& m);
virtual void init_modify_mode(TMask& m);
virtual bool remove();
public:
virtual TRelation* get_relation() const { return _rel; }
virtual ~TCesp_anal() {}
};
TCesp_anal & app() { return (TCesp_anal &) main_app(); }
//=============================================================================================
//maschera
class TCesp_anal_mask: public TAutomask
{
int _pos_cms, _pos_fase, _pos_cdc, _pos_dtiniuse, _pos_dtfinuse, _pos_util,
_pos_dtinicms, _pos_dtfincms, _pos_dtprorcms;
protected:
real check_perc_tot();
int calc_date_cespite(TDate& dtini, TDate& dtfine);
void calc_date_limite(const TString& codcms, TDate& dtini, TDate& dtfine);
void calc_percutil();
public:
virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
real TCesp_anal_mask::somma_perc() const;
TCesp_anal_mask();
};
TCesp_anal_mask::TCesp_anal_mask() : TAutomask ("ce4100a")
{
//setta le posizioni dei campi dello sheet
TSheet_field& sf_righe = sfield(F_RIGHE);
_pos_cms = sf_righe.cid2index(S_CODCMS);
_pos_fase = sf_righe.cid2index(S_CODFASE);
_pos_cdc = sf_righe.cid2index(S_CODCDC);
_pos_dtiniuse = sf_righe.cid2index(S_DTINIUSE);
_pos_dtfinuse = sf_righe.cid2index(S_DTFINUSE);
_pos_util = sf_righe.cid2index(S_PERCUTIL);
_pos_dtinicms = sf_righe.cid2index(S_DTINICMS);
_pos_dtfincms = sf_righe.cid2index(S_DTFINCMS);
_pos_dtprorcms = sf_righe.cid2index(S_DTPRORCMS);
//mette i checktype sui campi dello sheet in base alla configurazione..
//..analitica della ditta
TConfig& cfg = ca_config();
TMask& sf_righe_msk = sf_righe.sheet_mask();
if (cfg.get_bool("CmsRequired"))
{
TEdit_field& e_cms = sf_righe_msk.efield(S_CODCMS);
e_cms.check_type(CHECK_REQUIRED);
}
if (cfg.get_bool("CdcRequired"))
{
TEdit_field& e_cdc = sf_righe_msk.efield(S_CODCDC);
e_cdc.check_type(CHECK_REQUIRED);
}
if (cfg.get_bool("FscRequired"))
{
TEdit_field& e_fase = sf_righe_msk.efield(S_CODFASE);
e_fase.check_type(CHECK_REQUIRED);
}
}
real TCesp_anal_mask::check_perc_tot()
{
TSheet_field& ss = sfield(F_RIGHE);
real tot_perc;
FOR_EACH_SHEET_ROW(ss,i,r)
tot_perc += real(r->get(_pos_util));
return tot_perc;
}
int TCesp_anal_mask::calc_date_cespite(TDate& dtini, TDate& dtfine)
{
//si informa sulla vita del cespite
const TString& idcespite = get(F_IDCESPITE);
//controlla che il cespite sia vivo nell'esercizio selezionato e quanto dura tale esistenza
const TRectype& rec_cespi = cache().get(LF_CESPI, idcespite);
const TDate dtcomp = rec_cespi.get_date(CESPI_DTCOMP);
const TDate dtalien = rec_cespi.get_date(CESPI_DTALIEN);
const int anno = get_int(F_ESERCIZIO);
TEsercizi_contabili esc;
esc.code2range(anno, dtini, dtfine);
long durata = dtfine - dtini + 1;
if (dtalien.ok())
{
//cespite alienato prima dell'esercizio
if (dtalien < dtini)
return 0;
//cespite alienato durante l'esercizio
if (dtalien < dtfine)
dtfine = dtalien;
}
if (dtcomp.ok())
{
//cespite acquistato dopo l'esercizio
if (dtcomp.ok() && dtcomp > dtfine)
return 0;
//cespite acquistato durante l'esercizio
if (dtcomp.ok() && dtcomp > dtini)
dtini = dtcomp;
}
//durata "cespitizzata" dell'esercizio
durata = dtfine - dtini + 1;
return durata;
}
void TCesp_anal_mask::calc_date_limite(const TString& codcms, TDate& dtini, TDate& dtfine)
{
//date limite coincidenti con date vita cespite nell'esercizio (caso standard, senza commessa)
const TDate dtinicesp = get_date(F_INIZIO_CES);
const TDate dtfincesp = get_date(F_FINE_CES);
//se invece la commessa viene aggiunta, le sue date limite influenzano il limite di uso!
if (codcms.full())
{
const TRectype& rec_cms = cache().get(LF_COMMESSE, codcms);
ca_durata_commessa(rec_cms, dtini, dtfine);
//se le date di commessa sforano l'esercizio selezionato, vengono ricondotte alle date..
//..dell'esercizio stesso
if (dtfine.ok() && (dtfine > dtfincesp))
dtfine = dtfincesp;
if ((dtini.ok()) && (dtini < dtinicesp))
dtini = dtinicesp;
}
else
{
dtfine = dtfincesp;
dtini = dtinicesp;
}
}
//questo <20> il metodo supermagico ed iperdecisivo per calcolare la %utilizzo in base a tutti i dati..
//..vaganti nella maschera e nello sheet. E' il cuore del programma!
void TCesp_anal_mask::calc_percutil()
{
//ripartisce in automatico le percentuali di utilizzo analizzando le durate e le compresenze..
//..delle commesse sullo sheet nell'anno selezionato, oltre che ovviamente la durata del cespite..
//..nell'anno selezionato
// 1) stabilisce la durata dell'esercizio per il cespite: infatti pu<70> essere stato comprato o venduto..
//..nel corso dell'esercizio stesso
TDate dtini, dtfine;
//durata "cespitizzata" dell'esercizio
const long durata = calc_date_cespite(dtini, dtfine);
// 2) chiave generale su cui mettere le quote che non appartengono ad alcuna..
//..commessa! La si trova nella configurazione esercizio cespiti (tanto per incasinarci..
//..la vita), ovvero tabella CCE
const TString& anno = get(F_ESERCIZIO);
const TRectype& rec_cce = cache().get("CCE", anno);
//trova per l'anno sulla maschera quali sono i valori standard;
TToken_string key_genspa;
key_genspa.add(rec_cce.get("S2"), _pos_cdc);
key_genspa.add(rec_cce.get("S3"), _pos_cms);
key_genspa.add(rec_cce.get("S4"), _pos_fase);
//conatore dei giorni cui casca la chiave genspa
long giorni_genspa = 0L;
TSheet_field& sf_righe = sfield(F_RIGHE);
TPointer_array giorni_commessa;
int riga_genspa = -1;
// 3) giro su tutti i giorni inclusi tra le date limite in modo da trovare i giorni utili..
//..di ciascuna commessa e gli eventuali giorni vuoti da scaricare in genspa
for (TDate data = dtini; data <= dtfine; ++data)
{
bool almeno_una = false;
FOR_EACH_SHEET_ROW(sf_righe, r, row)
{
TToken_string key_riga;
key_riga.add(row->get(_pos_cms));
key_riga.add(row->get(_pos_fase));
key_riga.add(row->get(_pos_cdc));
//la commessa genspa non va calcolata qui!
if (key_riga != key_genspa)
{
const TDate dt_ini_use = row->get(_pos_dtiniuse);
const TDate dt_fin_use = row->get(_pos_dtfinuse);
//se la data in esame appartiene allintrvallo date di utilizzo sulla riga
if (data >= dt_ini_use && data <= dt_fin_use)
{
const long giorni = giorni_commessa.get_long(r) + 1;
giorni_commessa.add_long(giorni, r);
almeno_una = true;
}
}
else
riga_genspa = r;
} //FOR_EACH_SHEET_ROW...
//se la data in questione non appartiene all'intervallo di utilizzo di nessuna riga..
//..->la data <20> scoperta e va a finire nel calderone del genspa
if (!almeno_una)
giorni_genspa ++;
} //for(TDate...
// 4) attenzione alla commesse generica di riempimento (cms_genspa!) se non esiste va aggiunta
//se invece la cms_genspa ha gi<67> la sua riga -> deve solo aggiornare la %util (lo fa dopo..
//..assieme alle commesse normali)
if (riga_genspa < 0 && giorni_genspa > 0)
{
TToken_string& row_genspa = sf_righe.row(-1);
row_genspa = key_genspa;
row_genspa.add(dtini, _pos_dtinicms);
row_genspa.add(dtfine, _pos_dtfincms);
//aggiunge la commessa genspa all'array dei giorni_commessa, in modo che venga poi considerata..
//..nel riproporzionamento successivo con il distrib
riga_genspa = sf_righe.items() - 1;
}
//se la riga genspa esiste (sia che l'abbia appena creata che esistesse da tempo immemorabile)...
//..calcola la % di giorni genspa nell'esercizio cespitizzato (<28> la %util di genspa)
real perc_genspa = ZERO;
if (riga_genspa >= 0)
{
giorni_commessa.add_long(giorni_genspa, riga_genspa);
perc_genspa = giorni_genspa * CENTO / durata;
perc_genspa.round(2);
sf_righe.row(riga_genspa).add(perc_genspa.string(), _pos_util);
}
// 5) procede a caricare un distrib con i valori di giorni_commessa
TGeneric_distrib tamoil(CENTO - perc_genspa, 2);
for (int i = 0 ; i < sf_righe.items(); i++)
{
if (i != riga_genspa)
tamoil.add(giorni_commessa.get_long(i));
}
// 6) adesso scarica il distrib, mettendo la % di ogni commessa nel campo di %di utilizzo
FOR_EACH_SHEET_ROW(sf_righe, gg, linea)
{
if (gg != riga_genspa)
linea->add(tamoil.get().string(), _pos_util);
}
//..e alla fine vediamo che succede!
sf_righe.force_update();
}
bool TCesp_anal_mask::on_field_event(TOperable_field& o, TField_event e, long jolly)
{
switch (o.dlg())
{
//maschera principale
//-------------------
//case F_IDCESPITE:
case F_IDCESPITE_N:
case F_ESERCIZIO:
if (e == fe_modify || e == fe_close)
{
//nel caso vengano cambiati il cespite e/o l'esercizio, deve controllare la vita del cespite..
//..nell'esercizio
TDate dtinies = get_date(F_INIZIO_ES);
TDate dtfines = get_date(F_FINE_ES);
if (calc_date_cespite(dtinies, dtfines) <= 0)
return error_box("Cespite NON appartenente all'esercizio selezionato!");
set(F_INIZIO_CES, dtinies);
set(F_FINE_CES, dtfines);
}
break;
case F_RIGHE:
//all'uscita della riga...
if (e == se_notify_modify)
{
//controllo di duplicazione chiave della riga (cms/fase/cdc)
TAssoc_array keys_list;
TSheet_field& ss = sfield(F_RIGHE);
FOR_EACH_SHEET_ROW(ss,i,r)
{
const TString& cms = r->get(_pos_cms);
const TString& cdc = r->get(_pos_cdc);
const TString& fase = r->get(_pos_fase);
TToken_string row_key;
row_key.add(cms, _pos_cms);
row_key.add(fase, _pos_fase);
row_key.add(cdc, _pos_cdc);
if (keys_list.is_key(row_key))
return error_box("Codice riga %s duplicato", (const char *)row_key);
keys_list.add(row_key);
}
}
break;
//maschera di riga sheet
//----------------------
//controllo sulle date limite di utilizzo: se c'<27> la commessa le date lim uso devono ricadere..
//..all'interno della vita della commessa, se invece la commessa non c'<27> le date lim uso devono..
//..ricadere all'interno della vita utile del cespite nell'esercizio
case S_CODCDC:
if (e == fe_modify && !o.empty())
{
TMask& mask_riga = o.mask();
const int anno = get_int(F_ESERCIZIO);
TDate dtini, dtfine;
TEsercizi_contabili esc;
esc.code2range(anno, dtini, dtfine);
calc_date_cespite(dtini, dtfine);
TDate dtiniuse = mask_riga.get_date(S_DTINIUSE);
if (dtiniuse.empty())
mask_riga.set(S_DTINIUSE, dtini);
TDate dtfinuse = mask_riga.get_date(S_DTFINUSE);
if (dtfinuse.empty())
mask_riga.set(S_DTFINUSE, dtfine);
}
break;
case S_CODCMS:
if (e == fe_modify && !o.empty())
{
TMask& mask_riga = o.mask();
const TString& codcms = o.get();
TDate dtini, dtfine;
calc_date_limite(codcms, dtini, dtfine);
TDate dtiniuse = mask_riga.get_date(S_DTINIUSE);
if (dtiniuse.empty())
mask_riga.set(S_DTINIUSE, dtini);
TDate dtfinuse = mask_riga.get_date(S_DTFINUSE);
if (dtfinuse.empty())
mask_riga.set(S_DTFINUSE, dtfine);
}
break;
case S_DTINIUSE:
if (e == fe_modify || e == fe_close)
{
TDate dtini, dtfine;
const TString& codcms = o.mask().get(S_CODCMS);
calc_date_limite(codcms, dtini, dtfine);
const TDate dtiniuse = o.get();
if (dtiniuse.ok() && dtiniuse < dtini)
return error_box("La data inizio uso non pu<70> essere antecedente alla data inizio commessa!");
}
break;
case S_DTFINUSE:
if (e == fe_modify || e == fe_close)
{
TDate dtini, dtfine;
const TString& codcms = o.mask().get(S_CODCMS);
calc_date_limite(codcms, dtini, dtfine);
const TDate dtfinuse = o.get();
if (dtfinuse.ok() && dtfinuse > dtfine)
return error_box("La data fine uso non pu<70> essere successiva alla data fine commessa!");
}
break;
//bottoni
//-------
case DLG_CALCPERC:
if (e == fe_button)
{
//in caso di richiesta esplicita di ricalcolo, viene ordinato lo sheet..
//..in base al primo campo (in genere cms) e poi effettuato il calcolo
TSheet_field& sf_righe = sfield(F_RIGHE);
sf_righe.sort();
calc_percutil();
}
break;
case DLG_COPY:
if (e == fe_button)
{
TMask m("ce4100b");
const TDitta_cespiti& cce = ditta_cespiti();
const int esercizio_corrente = cce.esercizio_corrente();
int esercizio = get_int(F_ESERCIZIO);
if (esercizio == esercizio_corrente)
{
TEsercizi_contabili esc;
esercizio = esc.pred(esercizio_corrente);
}
m.set(F_ESERCIZIO1, esercizio);
if (m.run() == K_ENTER)
{
const TString8 anno_src(m.get(F_ESERCIZIO1));
const TString8 anno_dest(m.get(F_ESERCIZIO2));
if (anno_src < anno_dest)
{
TLocalisamfile f(LF_SALCECMS);
TRectype rec(f.curr());
TRectype from(f.curr());
TRectype to(f.curr());
from.put(SALCECMS_CODES, anno_dest);
to.put(SALCECMS_CODES, anno_dest);
{
TCursor sal(new TRelation(LF_SALCECMS), "", 2, &from, &to);
const long items = sal.items();
sal.freeze();
TProgind progind1(items, format(FR("Cancellazione anno %s in corso..."), (const char *) anno_dest), false, true);
for (sal = 0; sal.pos() < items; ++sal)
{
progind1.addstatus(1);
sal.curr().remove(f);
}
}
{
from.put(SALCECMS_CODES, anno_src);
to.put(SALCECMS_CODES, anno_src);
TCursor sal(new TRelation(LF_SALCECMS), "", 2, &from, &to);
const long items = sal.items();
TString80 idcespite;
TRecord_array * recarray = NULL;
sal.freeze();
TProgind progind2(items, format(FR("Generazione anno %s in corso..."), (const char *) anno_dest), false, true);
for (sal = 0; sal.pos() < items; ++sal)
{
rec = sal.curr();
if (idcespite.full())
{
if (idcespite != rec.get(SALCECMS_IDCESPITE))
{
TCespite cespite(idcespite);
cespite.load_saldi(1, atoi((const char *)anno_src));
if (cespite.res_amm() > ZERO && recarray->rows() > 0)
{
TGeneric_distrib d(CENTO, 2);
recarray->pack();
int items = recarray->last_row();
for (int i = recarray->first_row(); i <= items; i = recarray->succ_row(i))
d.add(recarray->row(i).get_real(SALCECMS_PERCUTIL));
for (int i = recarray->first_row(); i <= items; i = recarray->succ_row(i))
{
TRectype & r = (*recarray)[i];
r.put(SALCECMS_PERCUTIL, d.get());
}
recarray->write(true);
}
delete recarray;
recarray = NULL;
}
#ifdef DBG_VERBOSE
else
message_box(FR("Cespite %s ammortizzato"), (const char*) idcespite);
#endif
}
progind2.addstatus(1);
idcespite = rec.get(SALCECMS_IDCESPITE);
if (recarray == NULL)
{
TToken_string key;
key.add(idcespite);
key.add(anno_dest);
recarray = new TRecord_array(key, LF_SALCECMS);
}
TString80 codcms = rec.get(SALCECMS_CODCMS);
TString80 codcms_new = codcms;
if (codcms == "4.6.11.27/2014")
int i = 1;
const int pos = codcms_new.find(anno_src);
if (pos >= 0)
{
codcms_new.overwrite(anno_dest, pos);
const TRectype & commessa_new = cache().get(LF_COMMESSE, codcms_new);
if (!commessa_new.empty())
{
rec.put(SALCECMS_CODCMS, codcms_new);
codcms = codcms_new;
}
}
const TRectype & commessa = cache().get(LF_COMMESSE, codcms);
if(!commessa.get_bool(COMMESSE_CHIUSA))
{
rec.put(SALCECMS_CODES, anno_dest);
recarray->add_row(rec);
}
#ifdef DBG_VERBOSE
else
message_box(FR("Commessa %s chiusa"), (const char*) rec.get(SALCECMS_CODCMS));
#endif
}
if (idcespite.full())
{
TCespite cespite(idcespite);
cespite.load_saldi(1, atoi((const char *)anno_src));
if (cespite.res_amm() > ZERO && recarray->rows() > 0)
{
TGeneric_distrib d(CENTO, 2);
recarray->pack();
int items = recarray->last_row();
for (int i = recarray->first_row(); i <= items; i = recarray->succ_row(i))
d.add(recarray->row(i).get_real(SALCECMS_PERCUTIL));
for (int i = recarray->first_row(); i <= items; i = recarray->succ_row(i))
{
TRectype & r = (*recarray)[i];
r.put(SALCECMS_PERCUTIL, d.get());
}
recarray->write(true);
}
delete recarray;
recarray = NULL;
}
#ifdef DBG_VERBOSE
else
message_box(FR("Cespite %s ammortizzato"), (const char*) idcespite);
#endif
}
}
else
error_box(FR("Non posso copiare il %s nel %s"), (const char *) anno_src, (const char *) anno_dest);
}
}
break;
case DLG_SAVEREC:
if (e == fe_button)
{
const real perc_tot = check_perc_tot();
if (perc_tot != CENTO)
{
const bool proseguo = yesno_box("Percentuale complessiva diversa da 100%.\nRegistrare ugualmente?");
if (!proseguo)
return false;
}
}
break;
default:
break;
}
return true;
}
//===============================================================================================
//Applicazione
//metodi per la maschera
//abilita i campi per inserimento nuovo cespite,attivando i campi del gruppo 2 (che fanno riferimento al file LF_CESPI)
void TCesp_anal::init_query_insert_mode(TMask& m)
{
m.enable(-2);
m.show(-2);
m.hide(-1);
}
//abilita i campi per ricercare un cespite gia' inserito,attivando i campi del gruppo 1(LF_SALCECMS)
void TCesp_anal::init_query_mode(TMask& m)
{
m.show(-1);
m.hide(-2);
m.set(F_DESC,"");
}
void TCesp_anal::init_insert_mode(TMask& m)
{
m.hide(-1);
m.disable(-2);
}
void TCesp_anal::init_modify_mode(TMask& m)
{
m.hide(-2);
}
bool TCesp_anal::remove()
{
_rel->read(_isequal, _unlock);
TSheet_field& sf = _msk->sfield(F_RIGHE);
int err = sf.record()->remove();
return err == NOERR;
}
bool TCesp_anal::user_create()
{
_rel = new TRelation(LF_SALCECMS);
_msk = new TCesp_anal_mask;
return true;
}
bool TCesp_anal::user_destroy()
{
delete _rel;
delete _msk;
return true;
}
int ce4100(int argc, char* argv[])
{
TCesp_anal a;
a.run(argc,argv,TR("Ripartizione analitica cespiti"));
return 0;
}