From 038ca2cab5ee1f4b864c51e44a7d17238d27a41a Mon Sep 17 00:00:00 2001 From: luca Date: Thu, 3 Jun 2010 15:04:50 +0000 Subject: [PATCH] Patch level :10.0 Files correlati : Ricompilazione Demo : [ ] Commento : cespiti per analitica in corso git-svn-id: svn://10.65.10.50/trunk@20539 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- ce/ce0100.cpp | 5 +- ce/ce4100.cpp | 371 ++++++++++++++++++++++++++++--------------------- ce/ce4100a.uml | 21 ++- 3 files changed, 225 insertions(+), 172 deletions(-) diff --git a/ce/ce0100.cpp b/ce/ce0100.cpp index 04d7c2c1b..65a977c3a 100755 --- a/ce/ce0100.cpp +++ b/ce/ce0100.cpp @@ -15,8 +15,6 @@ #include "cetbccb.h" #include "cetbccc.h" -#include "../ca/calib01.h" - #define MIN_CAT_COM 40 #ifndef TTable_application @@ -192,6 +190,7 @@ TCCE_mask::TCCE_mask() : TAutomask("cetbcce") if (has_ca) { enable_page(1, true); +/* QUESTO NON E' ASSOLUTAMENTE DETTO; E' DA VERIFICARE! //se ha l'analitica gli tocca pure controllare la configurazione per sapere.. //..quali campi diventano obbligatori! TConfig& cfg = ca_config(); @@ -210,7 +209,7 @@ TCCE_mask::TCCE_mask() : TAutomask("cetbcce") { TEdit_field& e_fase = efield(F_CODFASE); e_fase.check_type(CHECK_REQUIRED); - } + }*/ } else enable_page(1, false); diff --git a/ce/ce4100.cpp b/ce/ce4100.cpp index d53d0a00f..d062553df 100755 --- a/ce/ce4100.cpp +++ b/ce/ce4100.cpp @@ -20,11 +20,13 @@ struct date_commessa : public TObject class TCesp_anal_mask: public TAutomask { - int _pos_cms, _pos_fase, _pos_cdc, _pos_dtiniuse, _pos_dtfinuse, _pos_util; + int _pos_cms, _pos_fase, _pos_cdc, _pos_dtiniuse, _pos_dtfinuse, _pos_util, + _pos_dtinicms, _pos_dtfincms, _pos_dtprorcms; protected: - int calc_durata_esercizio_cespitizzata(TDate& dtinies, TDate& dtfines); + 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); @@ -44,6 +46,9 @@ TCesp_anal_mask::TCesp_anal_mask() : TAutomask ("ce4100a") _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 @@ -67,38 +72,48 @@ TCesp_anal_mask::TCesp_anal_mask() : TAutomask ("ce4100a") } } -real TCesp_anal_mask::somma_perc() const -{ - 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_durata_esercizio_cespitizzata(TDate& dtinies, TDate& dtfines) +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, dtinies, dtfines); + esc.code2range(anno, dtini, dtfine); - //vita cespite - const TString& cespite = get(F_IDCESPITE); - const TRectype& rec_cespi = cache().get(LF_CESPI, cespite); - const TDate& dtcomp = rec_cespi.get_date(CESPI_DTCOMP); - const TDate& dtalien = rec_cespi.get_date(CESPI_DTALIEN); - //cespite acquistato durante l'esercizio - if (dtcomp.ok() && dtcomp > dtinies) - dtinies = dtcomp; - //cespite alienato durante l'esercizio - if (dtalien.ok() && dtalien < dtfines) - dtfines = dtalien; + 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 - const int durata = dtfines - dtinies + 1; + 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) @@ -124,6 +139,121 @@ void TCesp_anal_mask::calc_date_limite(const TString& codcms, TDate& dtini, TDat } } + +//questo è 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ò 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 è 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à 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 (è 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()) @@ -132,72 +262,45 @@ bool TCesp_anal_mask::on_field_event(TOperable_field& o, TField_event e, long jo //maschera principale //------------------- case F_IDCESPITE: + case F_IDCESPITE_N: case F_ESERCIZIO: - if (e == fe_modify) + 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); - calc_durata_esercizio_cespitizzata(dtinies, dtfines); + 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: - if (e == se_notify_add) //quando si aggiunge una riga... + //all'uscita della riga... + if (e == se_notify_modify) { - TSheet_field& ss = (TSheet_field&)o; - - //propone come date iniziale e finale di uso quelle dell'esercizio selezionato! - const int anno = get_int(F_ESERCIZIO); - TDate dtinies, dtfines; - TEsercizi_contabili esc; - esc.code2range(anno, dtinies, dtfines); - calc_durata_esercizio_cespitizzata(dtinies, dtfines); - TToken_string& new_row = ss.row(jolly); - new_row.add(dtinies, _pos_dtiniuse); - new_row.add(dtfines, _pos_dtfinuse); - - //mette nel campo %util il valore max possibile al momento - real residuo = CENTO - somma_perc(); - if (residuo > 0) - { - TToken_string& row = ss.row(jolly); - row.add(residuo.string(),_pos_util); - } - } - if (e == fe_close && (insert_mode() || edit_mode())) - { - //controllo sulle percentuali totali di un cespite - if (somma_perc() != CENTO) - return noyes_box("La percentuale complessiva di utilizzo del cespite e' diversa da 100" - "\nSi desidera proseguire ugualmente?"); - + //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) { - //controllo di esistenza codici commessa e cdc const TString& cms = r->get(_pos_cms); - if (cms.blank()) - return error_box("Specificare la commessa sulla riga %d", i+1); const TString& cdc = r->get(_pos_cdc); - if (cdc.blank()) - return error_box("Specificare il centro di costo sulla riga %d", i+1); - //controllo di duplicazione chiave della riga (cms/fase/cdc) - TToken_string row_key; - row_key.add(cms); const TString& fase = r->get(_pos_fase); - row_key.add(fase); - row_key.add(cdc); + + 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); } + //ricalcola le percentuali !!! + calc_percutil(); } break; @@ -206,23 +309,60 @@ bool TCesp_anal_mask::on_field_event(TOperable_field& o, TField_event e, long jo //controllo sulle date limite di utilizzo: se c'è la commessa le date lim uso devono ricadere.. //..all'interno della vita della commessa, se invece la commessa non c'è 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 = get(S_CODCMS); + const TString& codcms = o.mask().get(S_CODCMS); calc_date_limite(codcms, dtini, dtfine); - if (o.get() < dtini) + const TDate dtiniuse = o.get(); + if (dtiniuse < dtini) return error_box("La data inizio uso non può essere antecedente alla data inizio commessa!"); } break; + case S_DTFINUSE: if (e == fe_modify || e == fe_close) { TDate dtini, dtfine; - const TString& codcms = get(S_CODCMS); + const TString& codcms = o.mask().get(S_CODCMS); calc_date_limite(codcms, dtini, dtfine); - if (o.get() > dtfine) + const TDate dtfinuse = o.get(); + if (dtfinuse > dtfine) return error_box("La data fine uso non può essere successiva alla data fine commessa!"); } break; @@ -232,94 +372,11 @@ bool TCesp_anal_mask::on_field_event(TOperable_field& o, TField_event e, long jo case DLG_CALCPERC: if (e == fe_button) { - //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ò essere stato comprato o venduto.. - //..nel corso dell'esercizio stesso - TDate dtini, dtfine; - //durata "cespitizzata" dell'esercizio - const int durata = calc_durata_esercizio_cespitizzata(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; - + //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); - 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 è 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à la sua riga -> deve solo aggiornare la %util (lo fa dopo.. - //..assieme alle commesse normali) - if (riga_genspa < 0) - { - TToken_string& row_genspa = sf_righe.row(-1); - row_genspa = key_genspa; - //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; - } - giorni_commessa.add_long(giorni_genspa, riga_genspa); - - // 5) procede a caricare un distrib con i valori di giorni_commessa - TGeneric_distrib tamoil(CENTO, 2); - for (int i = 0 ; i < sf_righe.items(); i++) - 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) - linea->add(tamoil.get().string(), _pos_util); - - //..e alla fine vediamo che succede! - sf_righe.force_update(); + sf_righe.sort(); + calc_percutil(); } break; diff --git a/ce/ce4100a.uml b/ce/ce4100a.uml index 42b0bb4ba..dc46c9af8 100755 --- a/ce/ce4100a.uml +++ b/ce/ce4100a.uml @@ -77,18 +77,14 @@ STRING F_IDCESPITE 10 BEGIN PROMPT 1 4 "Cespite " FLAGS "UZ" - USE LF_SALCECMS SELECT NRIGA==1 + USE LF_SALCECMS KEY 2 SELECT NRIGA==1 JOIN LF_CESPI INTO IDCESPITE==IDCESPITE - INPUT CODES F_ESERCIZIO + INPUT CODES F_ESERCIZIO SELECT INPUT IDCESPITE F_IDCESPITE DISPLAY "Codice@10" IDCESPITE DISPLAY "Descrizione@50" LF_CESPI->DESC DISPLAY "Cat." LF_CESPI->CODCAT - DISPLAY "Commessa@20" CODCMS - DISPLAY "Fase@10" CODFASE - DISPLAY "Centro di costo@20" CODCDC - DISPLAY "Data Acq.@10" LF_CESPI->DTCOMP - DISPLAY "Data Ali.@10" LF_CESPI->DTALIEN + DISPLAY "Esercizio" CODES OUTPUT F_IDCESPITE IDCESPITE OUTPUT F_IDCESPITE_N IDCESPITE OUTPUT F_DESC LF_CESPI->DESC @@ -131,7 +127,7 @@ END STRING F_DESC_N 60 50 BEGIN - PROMPT 24 6 "" + PROMPT 24 4 "" USE LF_CESPI KEY 3 INPUT DESC F_DESC_N DISPLAY "Descrizione@50" DESC @@ -188,7 +184,7 @@ ENDPAGE ENDMASK //maschera di riga dello sheet -PAGE "Riga" -1 -1 76 8 +PAGE "Riga" -1 -1 76 9 STRING S_CODCMS 20 BEGIN @@ -286,23 +282,24 @@ BEGIN FLAGS "U" FIELD PERCUTIL CHECKTYPE REQUIRED + FLAGS "D" END DATE S_DTINICMS BEGIN - PROMPT 1 2 "Inizio " + PROMPT 1 2 "Inizio " FLAGS "D" END DATE S_DTFINCMS BEGIN - PROMPT 22 2 "Fine " + PROMPT 30 2 "Fine " FLAGS "D" END DATE S_DTPRORCMS BEGIN - PROMPT 44 2 "Proroga " + PROMPT 54 2 "Proroga " FLAGS "D" END