#include #include "../ve/velib.h" #include "../ve/velib04.h" #include "calib01.h" #include "calib02.h" #include "ca3883.h" #include "movana.h" #include "rmovana.h" #include "panapdc.h" #include "commesse.h" #include "fasi.h" #include "saldana.h" //////////////////////////////////////////////////////////////////////////////////////// // Classe per ricavare l'indicatore di bilancio dei conti analitici riclassificati e non //////////////////////////////////////////////////////////////////////////////////////// TObject* TIndbil_cache::key2obj(const char* key) { TString80 conto = key; if (_usepdcc && conto.len() == 12 && real::is_natural(conto)) { TLocalisamfile panapdc(LF_PANAPDC); panapdc.setkey(2); const int gr = atoi(conto.left(3)); const int co = atoi(conto.mid(3,3)); const long so = atol(conto.mid(6,6)); TRectype& panapdrec = panapdc.curr(); int i; for (i = 2; i >= 0; i--) { panapdrec.zero(); panapdrec.put(PANAPDC_GRUPPO, gr); if (i > 0) panapdrec.put(PANAPDC_CONTO, co); if (i == 2) panapdrec.put(PANAPDC_SOTTOCONTO, so); //occhio al prefisso! panapdrec.put(PANAPDC_CODCONTO, _prefix); if (panapdc.read(_isgteq) == NOERR) { bool found = panapdrec.get_int(PANAPDC_GRUPPO) == gr; if (found) found = panapdrec.get_int(PANAPDC_CONTO) == (i > 0 ? co : 0); if (found) found = panapdrec.get_long(PANAPDC_SOTTOCONTO) == (i > 1 ? so : 0L); if (found && _prefix.full()) found = panapdrec.get(PANAPDC_CODCONTO).starts_with(_prefix); if (found) { conto = panapdrec.get(PANAPDC_CODCONTO); if (cache().get(LF_PCONANA, conto).empty()) error_box(FR("Non esiste piu' il conto %s cui era legato %d %d %ld"), (const char*)conto, gr, co, so); else break; } } } //se non trova il corrispondente conto analitico azzera il conto per il prossimo giro if (i < 0) conto.cut(0); } //conto analitico TAnal_bill bill(conto); int indbil = bill.indicatore_bilancio(); TToken_string* ib = new TToken_string; *ib << indbil; ib->add(conto); return ib; } int TIndbil_cache::get_indbil(const TString& conto, TString& conto_anale) { int indicatore = 0; TToken_string* ib = (TToken_string*)objptr(conto); if (ib != NULL) { indicatore = ib->get_int(0); ib->get(1, conto_anale); } return indicatore; } void TIndbil_cache::set_prefix(const char* prefix) { if (_prefix != prefix) { _prefix = prefix; destroy(); } } TIndbil_cache::TIndbil_cache() { TConfig& cfg = ca_config(); _usepdcc = cfg.get_bool("UsePdcc"); } /////////////////////////////////////////////////////////////////// // roba del recordset /////////////////////////////////////////////////////////////////// const TFixed_string CMS_DEL_CAZZO("@@@@@@@@@@@@@@@@@@@@"); static int righe_compare(const TObject** o1, const TObject** o2) { TAssoc_array& a1 = *(TAssoc_array*)*o1; TAssoc_array& a2 = *(TAssoc_array*)*o2; int cmp = 0; const int l1 = atoi(*(TString*)a1.objptr("LEVEL")); const int l2 = atoi(*(TString*)a2.objptr("LEVEL")); cmp = l1 - l2; if (cmp == 0) { const TString& c1 = *(TString*)a1.objptr("CODCMS"); const TString& c2 = *(TString*)a2.objptr("CODCMS"); cmp = c1.compare(c2); if (cmp == 0) { const TString& f1 = *(TString*)a1.objptr("FASE"); const TString& f2 = *(TString*)a2.objptr("FASE"); cmp = f1.compare(f2); if (cmp == 0) { const TString& d1 = *(TString*)a1.objptr("CDC"); const TString& d2 = *(TString*)a2.objptr("CDC"); cmp = d1.compare(d2); } else { const int z1 = c1.starts_with("detr_"); const int z2 = c2.starts_with("detr_"); if (z1 || z2) cmp = z1 - z2; } } } return cmp; } ////////////////////////////////////////////////////////////////////////////////////// //Classe di recordset speciale per stampe con saldana, rmovana, rdoc (ca3800, ca3900) ////////////////////////////////////////////////////////////////////////////////////// bool TPrint_saldana_recordset::move_to(TRecnotype pos) { _curr = pos; return pos >= 0 && pos < items(); } void TPrint_saldana_recordset::parse_bill(const TString& bill, TString& conto) const { TConfig& cfg = ca_config(); const TMultilevel_code_info& pconana_info = ca_multilevel_code_info(LF_PCONANA); const int pconana_levels = pconana_info.levels(); const int prefix = cfg.get_int("PdcPrefix")-1; //lunghezza dell'eventuale prefisso di gruppo e conto const int prefix_len = (prefix >= 0) ? pconana_info.total_len(prefix) : 0; //quanto e' lungo il codice del conto da considerare? E' il livello - il prefisso const int conto_end = pconana_info.total_len(_depth) - prefix_len; //stringa con cio' che segue il prefisso ed e' richiesto conto = bill.mid(prefix_len, conto_end); } int TPrint_saldana_recordset::estrai_saldi(const TRectype& saldana, const int indbil, TImporto& saldo, TImporto& saldop, const bool cms_detraz) const { int flag = 0; saldo.reset(); saldop.reset(); //stampa bilancio di commessa ca3800 (_tipo=8) if (_tipo == 8) { switch (_tipostima) { case 'R': //CostiConsuntivi RicaviConsuntivi (Cc/Rc) (le detrazioni saranno ovviamente sempre e solo consuntive) { const TImporto imp_saldo(saldana.get_char(SALDANA_SEZIONE), saldana.get_real(SALDANA_SALDO)); if (!imp_saldo.is_zero()) { if (indbil == 3) //indbil=3 costi { saldo = imp_saldo; flag = 1; } else //indbil=4 ricavi { saldop = imp_saldo; flag = 2; } } } break; case 'C': //CostiConsuntivi RicaviPreventivi (Cc/Rp) { if (indbil == 3) //costi: sempre e solo consuntivi, sia righe commessa che detrazione { const TImporto imp_saldo(saldana.get_char(SALDANA_SEZIONE), saldana.get_real(SALDANA_SALDO)); saldo = imp_saldo; flag |= saldo.is_zero() ? 0 : 1; } else //indbil=4 ricavi: preventivi per righe commessa, consuntivi o preventivi per detrazioni (dipende da scelta utente) { if (cms_detraz && _detrazioni_consuntive) { const TImporto imp_saldo(saldana.get_char(SALDANA_SEZIONE), saldana.get_real(SALDANA_SALDO)); saldo = imp_saldo; flag |= saldo.is_zero() ? 0 : 1; } else { const TImporto imp_saldop(saldana.get_char(SALDANA_SEZIONEP), saldana.get_real(SALDANA_SALDOP)); const TImporto imp_saldov(saldana.get_char(SALDANA_SEZIONEV), saldana.get_real(SALDANA_SALDOV)); saldop = imp_saldop; saldop += imp_saldov; flag |= saldop.is_zero() ? 0 : 2; } } } break; case 'T': //CostiPreventivi RicaviPreventivi (Cc/Rp) = Tempo //nel caso stia calcolando le detrazioni di anni precedenti (cms_detraz) va sempre preso il consuntivo!! if (cms_detraz && _detrazioni_consuntive) { const TImporto imp_saldo(saldana.get_char(SALDANA_SEZIONE), saldana.get_real(SALDANA_SALDO)); saldo = imp_saldo; flag |= saldo.is_zero() ? 0 : 1; } else //in tutti gli altri casi vanno bene i preventivi { const TImporto imp_saldop(saldana.get_char(SALDANA_SEZIONEP), saldana.get_real(SALDANA_SALDOP)); const TImporto imp_saldov(saldana.get_char(SALDANA_SEZIONEV), saldana.get_real(SALDANA_SALDOV)); saldop = imp_saldop; saldop += imp_saldov; flag |= saldop.is_zero() ? 0 : 2; } break; } //switch (_tipostima)... } //if(_tipo=8... // stampa stima ricavi ca3900 (_tipo=9) else { const TImporto imp_saldo(saldana.get_char(SALDANA_SEZIONE), saldana.get_real(SALDANA_SALDO)); saldo = imp_saldo; flag |= saldo.is_zero() ? 0 : 1; const TImporto imp_saldop(saldana.get_char(SALDANA_SEZIONEP), saldana.get_real(SALDANA_SALDOP)); const TImporto imp_saldov(saldana.get_char(SALDANA_SEZIONEV), saldana.get_real(SALDANA_SALDOV)); saldop = imp_saldop; saldop += imp_saldov; flag |= saldop.is_zero() ? 0 : 2; /* correzione per ottenere la sezione in base all'indicatore di bilancio inutile per ora... const char sezione_positiva = (indbil == 2 || indbil == 3) ? 'D' : 'A'; saldo.normalize(sezione_positiva); saldop.normalize(sezione_positiva);*/ } return flag; } TAssoc_array& TPrint_saldana_recordset::get_row(TAssoc_array& cms, const char* chiave, const int indice, const TString& codcms, const TString& fase, const TString& cdc, const TString& descrizione) const { //cerca se la commessa (e l'eventuale fase) esistono gia' nell'assocarray delle commesse TAssoc_array* riga_array = (TAssoc_array*)cms.objptr(chiave); //se non esiste la crea! if (riga_array == NULL) { riga_array = new TAssoc_array; TString4 str_indice; //l'indice va stringato per l'assoc_array str_indice << indice; riga_array->add("LEVEL", str_indice); riga_array->add("CODCMS", codcms); if (_tipo == 8) { riga_array->add("FASE", fase); riga_array->add("CDC", cdc); } riga_array->add("DESCRIZ", descrizione); //inizializza i campi importo sicuramente presenti (modifica DECISIVA) //senza questa inizializzazione, nel caso trovasse campi nulli (in realta' 0), il bastardo.. //..anziche' considerarli 0 ci mette l'ultimo valore != che ha in memoria nella stessa posizione.. //..facendo sballare tutti i conti! //bilancio commessa ca3800 (_tipo=8) if (_tipo == 8) { riga_array->add("RICAVI", EMPTY_STRING); riga_array->add("COSTI", EMPTY_STRING); } //stima ricavi ca3900 (_tipo=9) else { riga_array->add("COS_BDG", EMPTY_STRING); riga_array->add("COS_MAT", EMPTY_STRING); riga_array->add("RIC_BDG", EMPTY_STRING); riga_array->add("RIC_MAT", EMPTY_STRING); } //aggiunge la riga all'array-one cms.add(chiave, riga_array); } return *riga_array; } //for ca3800 only! void TPrint_saldana_recordset::aggiorna_importo(TAssoc_array& riga_array, const TString& livello, const int indbil, const TRectype& saldana, const bool is_detrazione) const { TString* str_imp = (TString*)riga_array.objptr(livello); if (str_imp == NULL) { str_imp = new TString; riga_array.add(livello, str_imp); } //dare o avere? const char sezione = indbil == 3 ? 'D' : 'A'; TImporto imp(sezione, real(*str_imp)); //ci sono tutti i tipi di saldo, ma solo quelli che rientrano nei parametri iniziali.. //..verranno considerati (_tipostima,indbil) TImporto imp_saldo, imp_saldop; estrai_saldi(saldana, indbil, imp_saldo, imp_saldop, is_detrazione); if (is_detrazione) // Se è una detrazione deve sottrarre l'importo = scambia la sezione { imp_saldo.swap_section(); imp_saldop.swap_section(); } imp += imp_saldo; imp += imp_saldop; imp.normalize(sezione); *str_imp = imp.valore().string(); } //for ca3800 only! real TPrint_saldana_recordset::calcola_avanzamento_tempo() const { real avanzamento; TDate dataini, datafine; const TString& codfase = get("FASE").as_string(); const TString& codcdc = get("CDC").as_string(); //fase specificata (si usa l'avanzamento sulla fase solo se questa dipende dalle commesse; se fosse indipendente.. //..basare l'avanzamento su di essa sarebbe assurdo (le fasi indipendenti non possono avere datainizio e datafine) if (codfase.full() && ca_config().get("FathFasi") == "CMS") { const TRectype& rec_fasi = cache().get(LF_FASI, codfase); dataini = rec_fasi.get(FASI_DATAINIZIO); datafine = rec_fasi.get(FASI_DATAFINE); } if (!dataini.ok()) { const TString& codcms = get("CODCMS").as_string(); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); ca_durata_commessa(rec_commesse, dataini, datafine); } //Si prende la data fine (detta _datacalcolo) perchè si vuole la situazione alla data (eventualmente tale data è.. //..la fine dell'esercizio) if (datafine < _datacalcolo) avanzamento = CENTO; //se invece prosegue anche dopo la data di fine... else { const long time_gone = _datacalcolo - dataini; const long durata = datafine - dataini; avanzamento = ((real)(time_gone * CENTO) / durata); } return avanzamento; } //for ca3900 only! void TPrint_saldana_recordset::incrementa_importo(TAssoc_array& riga_array, const TString& livello, const int indbil, const TImporto& saldo, const bool inverti) const { TString* str_imp = (TString*)riga_array.objptr(livello); if (str_imp == NULL) { str_imp = new TString; riga_array.add(livello, str_imp); } //dare o avere? const char sezione = indbil == 3 ? 'D' : 'A'; TImporto imp(sezione, real(*str_imp)); if (inverti) // Devo sottrarre l'importo = gli scambio la sezione imp -= saldo; else imp += saldo; imp.normalize(sezione); *str_imp = imp.valore().string(); } //metodo usato solo per la stima ricavi ca3900 (_tipo=9) void TPrint_saldana_recordset::aggiorna_importi(TAssoc_array& riga_array, const int indbil, const TRectype& saldana, const int tempo) const { const bool is_detrazione = tempo < 0; const bool is_prev_futuro = tempo > 0; const bool inverti = is_detrazione; TString8 livello; TImporto imp_saldo, imp_saldop; estrai_saldi(saldana, indbil, imp_saldo, imp_saldop, false); //richiesta Dinamica-Crpa: nelle detrazioni comandano sempre i maturati (quindi i saldo); i preventivi.. //..vengono posti uguali ai maturati d'ufficio if (is_detrazione) imp_saldop = imp_saldo; else { if (is_prev_futuro) imp_saldo.reset(); } //saldi normali:Maturato if (!imp_saldo.is_zero()) { livello.format("%s_MAT", indbil == 3 ? "COS" : "RIC"); incrementa_importo(riga_array, livello, indbil, imp_saldo, inverti); } //saldi preventivi:Budget if (!imp_saldop.is_zero()) { livello.format("%s_BDG", indbil == 3 ? "COS" : "RIC"); incrementa_importo(riga_array, livello, indbil, imp_saldop, inverti); } } //trova la sezione del report in cui ricade in base alle date int TPrint_saldana_recordset::ricava_sezione_di_stampa(const TRectype& rec_commesse, const TDate& datainiesc, const TDate& datafinesc) const { int indice = -1; //data iniziale commessa TDate dataini, datafine; ca_durata_commessa(rec_commesse, dataini, datafine); //Le commesse vengono suddivise in varie sezioni in base alle loro date di inizio/fine/proroga.. //..e al fatto che possono essere di appoggio (Adolf rikiesten!) secondo lo schema: // _ 0 terminano nell'anno selezionato / iniziate nel passato // _ 1 terminano nell'anno selezionato / iniziate nell'anno selezionato // _ 2 terminano nel futuro / iniziate nel passato // _ 3 terminano nel futuro / iniziate nell'anno selezionato // _ 4 di appoggio / terminano nell'anno selezionato / iniziate nell'anno selezionato // (indice 1 ma di appoggio in pratica) //e' inutile considerare le commesse terminate prima dell'esercizio selezionato.. //..cioe' nel passato oppure che iniziano nel futuro! if (datafine >= datainiesc && dataini <= datafinesc) { //indice e' il parametro che stabilisce in quale sezione del report viene stampata la commessa //se la commessa termina prima della fine dell'esercizio selezionato -> indice 0, altrimenti.. //..indice 2 indice = datafine <= datafinesc ? 0 : 2; //se poi la commessa inizia dopo la data inizio esercizio selezionato -> l'indice va incrementato.. //..di una unita' (viene spostata nella sezione di stampa successiva) if (dataini >= datainiesc) indice++; //controlla se la commessa e' di appoggio e di indice 1 (inizia e finisce nell'anno selezionato) //in questo caso la commessa ha indice 4 e va nella sezione distaccata in fondo al report (Adolf!) if (indice == 1) { const bool cms_appoggio = rec_commesse.get_bool(COMMESSE_APPOGGIO); if (cms_appoggio) indice = 4; } } return indice; } void TPrint_saldana_recordset::ricava_chiave_cdc_fase(const TString& codcms, const TString& fase, const TString& cdc, TString& chiave) const { //ci sono filtri o raggruppamenti per fase o centro di costo? chiave = codcms; //selezione fasi solo su bilancio commessa (_tipo=8) if (_tipo == 8 && (_tipostampa >= 1 && _tipostampa <= 3)) { //se vuole entrambi i livelli di dettaglio occorre sapere chi e' il babbo delle fasi o dei cdc if (_tipostampa == 3) { //le fasi sono figlie dei cdc? if (ca_multilevel_code_info(LF_FASI).parent() == LF_CDC) chiave << '|' << cdc << '|' << fase; else //in ogni altro caso (figlie delle commesse o di nessuno...) chiave << '|' << fase << '|' << cdc; } else //livelli di dettaglio semplici { if (_tipostampa == 1) chiave << '|' << fase; //dettaglia x fase else chiave << '|' << cdc; //dettaglia x cdc } } } const TDate TPrint_saldana_recordset::calcola_min_datacomp(const TDate& datainiesc, const TDate& datafinesc) const { TDate data_min_comp = datainiesc; TISAM_recordset recset("USE COMMESSE"); const TRectype& rec_commessa = recset.cursor()->curr(); for (bool ok = recset.move_first(); ok; ok = recset.move_next()) { TDate dataini, datafine; ca_durata_commessa(rec_commessa, dataini, datafine); if (datafine >= datainiesc && dataini < data_min_comp) data_min_comp = dataini; } return data_min_comp; } const TString& TPrint_saldana_recordset::crea_select(const int logicnum) { TString select = ca_create_user_select_clause(logicnum); //void ca_append_and(TString& query, const TString& clause) switch (_tipostampa) { case 0: break; case 1: case 4: if (_fase.full()) { TString clause; clause << ca_dollar2fieldname(logicnum, "$(FAS)") << "=\"" << _fase << "\""; ca_append_and(select, clause); } break; case 2: case 8: if (_cdc.full()) { TString clause; clause << ca_dollar2fieldname(logicnum, "$(CDC)") << "=\"" << _cdc << "\""; ca_append_and(select, clause); } break; case 3: if (_fase.full() || _cdc.full()) { TString clause; if (_fase.full() && _cdc.full()) clause << "(" << ca_dollar2fieldname(logicnum, "$(FAS)") << "=\"" << _fase << "\")&&(" << ca_dollar2fieldname(logicnum, "$(CDC)") << "=\"" << _cdc << "\")"; else { if (_fase.full()) clause << ca_dollar2fieldname(logicnum, "$(FAS)") << "=\"" << _fase << "\""; else clause << ca_dollar2fieldname(logicnum, "$(CDC)") << "=\"" << _cdc << "\""; } ca_append_and(select, clause); } break; } return get_tmp_string() = select; } //crea la query base per la scansione dei SALDANA; si usa nelle parse_saldana e parse_saldana_futuri const TString& TPrint_saldana_recordset::crea_query_saldana() { const TString& select = crea_select(LF_SALDANA); TString query; query = "USE SALDANA"; if (select.full()) query << " SELECT " << select; return get_tmp_string() = query; } //aggiorna l'arrayone cms con i saldana void TPrint_saldana_recordset::parse_saldana(TAssoc_array* cms, const TDate& datainiesc, const TDate& datafinesc) { TString query; //se ca3800... if (_tipo == 8) { query = crea_query_saldana(); //stampa standard non a vita intera per la 3800 if (!_vitaintera) { TEsercizi_contabili esc; TDate datainiesc, datafinesc; esc.code2range(_anno, datainiesc, datafinesc); query << "\nTO ANNO="; //ACHTUNG! Se non si sceglie l'intero esercizio corrente i saldi sono quelli finali dell'esercizio precedente! //Saranno poi integrati dai saldi volanti creati da movana e doc if (_datacalcolo == datafinesc) query << _anno; else query << (_anno - 1); } } //if(_tipo==8.. if (_tipo == 9) { //non vanno considerati saldi di esercizi futuri a quello scelto!!! query = "USE SALDANA"; } TISAM_recordset saldana_set(query); const TRectype& saldana = saldana_set.cursor()->curr(); const long saldana_items = saldana_set.items(); TProgind pi(saldana_items, "Scansione saldi correnti...", true, true); for (bool ok = saldana_set.move_first(); ok; ok = saldana_set.move_next()) { //progind tanto per gradire if (!pi.addstatus(1)) break; const TString& codconto = saldana.get(SALDANA_CONTO); //trova l'indicatore di bilancio TString80 conto_anale; const int indbil = _indicatori.get_indbil(codconto, conto_anale); //solo i Costi(3) ed i Ricavi(4) devono essere considerati per la stampa if (indbil == 3 || indbil == 4) { //gruppo e conto servono solo per il caso _tipo=8 ma vanno dichiarati e ricavati.. //..qui in modo che siano a disposizione delle commesse del cazzo poco sotto const char* gruppo = indbil == 3 ? "COSTI" : "RICAVI"; TString80 conto; parse_bill(conto_anale, conto); //estrae i dati di commessa e le date relative;le date servono successivamente per stabilire... //..le sezioni in cui compariranno le commesse nella stampa const TString80 codcms = saldana.get(SALDANA_COMMESSA); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); //indice: indica la sezione di report in cui apparariranno i valori! const int indice = ricava_sezione_di_stampa(rec_commesse, datainiesc, datafinesc); //anno sul record di saldana;serve un pò dappertutto sotto const int anno_saldo = saldana.get_int(SALDANA_ANNO); //e' inutile considerare le commesse terminate prima dell'esercizio selezionato.. //..cioe' nel passato oppure che iniziano nel futuro! Solo le commesse con indice non.. //..negativo sopravvivono! if (indice >= 0) { //ci sono filtri o raggruppamenti per fase o centro di costo? const TString80 fase = saldana.get(SALDANA_FASE); const TString80 cdc = saldana.get(SALDANA_COSTO); //ricava la chiave completa per l'assoc_array comprendendo eventuali fasi e/o cdc TString80 chiave; ricava_chiave_cdc_fase(codcms, fase, cdc, chiave); //riempie le righe degli array da mandare poi in stampa //dapprima le righe normali.. //bilancio di commessa ca3800 (_tipo=8) if (_tipo == 8) { TAssoc_array& riga_array = get_row(cms[indice], chiave, indice, codcms, fase, cdc, rec_commesse.get(COMMESSE_DESCRIZ)); //aggiunge gli importi e normalizza aggiorna_importo(riga_array, gruppo, indbil, saldana); aggiorna_importo(riga_array, conto, indbil, saldana); //aggiorna totali della commessa (importi per codcms senza tener conto di fase o cdc) TAssoc_array& riga_tot = get_row(_totali[indice], codcms, indice, codcms, EMPTY_STRING, EMPTY_STRING, gruppo); aggiorna_importo(riga_tot, gruppo, indbil, saldana); } //stima ricavi ca3900 (_tipo=9) else { #ifdef DBG if (codcms == "AS09MB4RETECO" && indice == 3) int cazzone = 1; #endif TAssoc_array& riga_array = get_row(cms[indice], chiave, indice, codcms, EMPTY_STRING, EMPTY_STRING, rec_commesse.get(COMMESSE_DESCRIZ)); //aggiunge gli importi e normalizza if (anno_saldo > _anno) // gestione saldo nel futuro { if (indice > 1) // considera i saldop solo se è una commessa che termina nel futuro! aggiorna_importi(riga_array, indbil, saldana, anno_saldo - _anno); } else aggiorna_importi(riga_array, indbil, saldana, 0); // gestione saldo passato e presente } //if(tipo==8) } //if (datafine >= datainiesc &&... //RIGHE COMMESSA DETRAZIONE: esistono solo se la commessa e' iniziata prima dell'anno //selezionato e se ha a che fare con quello in corso,quindi l'indice e' 0 o 2 //indice è stato ricavato un tot di righe addietro... if (indice == 0 || indice == 2) { //aggiorna il record speciale con la somma dei saldi con anno anteriore a quello.. //..selezionato sulla maschera (CRPA request) if (anno_saldo < _anno) { TString16 cazzo_cod; cazzo_cod.format("detr_al_%04d", _anno - 1); TString cazzo_descr = "DETRAZIONE PER COMPETENZA FINO AL "; cazzo_descr << (_anno - 1); TAssoc_array& riga_array = get_row(cms[indice], CMS_DEL_CAZZO, indice, cazzo_cod, EMPTY_STRING, EMPTY_STRING, cazzo_descr); if (_tipo == 8) { //calcolo delle detrazioni (is_detrazione = true) aggiorna_importo(riga_array, gruppo, indbil, saldana, true); aggiorna_importo(riga_array, conto, indbil, saldana, true); } else { aggiorna_importi(riga_array, indbil, saldana, anno_saldo - _anno); } } //if(anno<_anno... } //if(indice... } //if (indbil == 3 ||... } //for(bool ok=saldana.move_first().. } //aggiorna l'arrayone cms con i saldana void TPrint_saldana_recordset::parse_saldana_futuri() { //calcola i saldi futuri per avere i totali da cui ricavare gli avanzamenti TString query = crea_query_saldana(); TEsercizi_contabili esc; TDate datainiesc, datafinesc; esc.code2range(_anno, datainiesc, datafinesc); int anno = _anno; //se la datacalcolo coincide con la data finale dell'esercizio i saldi futuri partono dall'anno successivo if (_datacalcolo == datafinesc) anno++; query << "\nFROM ANNO=" << anno; TISAM_recordset saldana_set(query); const TRectype& saldana = saldana_set.cursor()->curr(); const long saldana_items = saldana_set.items(); TProgind pi(saldana_items, "Scansione saldi futuri...", true, true); for (bool ok = saldana_set.move_first(); ok; ok = saldana_set.move_next()) { //progind tanto per gradire if (!pi.addstatus(1)) break; const TString& codconto = saldana.get(SALDANA_CONTO); //trova l'indicatore di bilancio TString80 conto_anale; const int indbil = _indicatori.get_indbil(codconto, conto_anale); //solo i Costi(3) ed i Ricavi(4) devono essere considerati per la stampa if (indbil == 3 || indbil == 4) { //gruppo e conto servono solo per il caso _tipo=8 ma vanno dichiarati e ricavati.. //..qui in modo che siano a disposizione delle commesse del cazzo poco sotto const char* gruppo = indbil == 3 ? "COSTI" : "RICAVI"; TString80 conto; parse_bill(conto_anale, conto); TImporto saldo, saldop; const int flag = estrai_saldi(saldana, indbil, saldo, saldop, false); //estrae i dati di commessa e le date relative;le date servono successivamente per stabilire... //..le sezioni in cui compariranno le commesse nella stampa const TString& codcms = saldana.get(SALDANA_COMMESSA); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); //indice: indica la sezione di report in cui apparariranno i valori! const int indice = ricava_sezione_di_stampa(rec_commesse, datainiesc, datafinesc); //e' inutile considerare le commesse terminate prima dell'esercizio selezionato.. //..cioe' nel passato oppure che iniziano nel futuro! Solo le commesse con indice non.. //..negativo sopravvivono! if (indice >= 0) { //ci sono filtri o raggruppamenti per fase o centro di costo? const TString& fase = saldana.get(SALDANA_FASE); const TString& cdc = saldana.get(SALDANA_COSTO); //ricava la chiave completa per l'assoc_array comprendendo eventuali fasi e/o cdc TString80 chiave; ricava_chiave_cdc_fase(codcms, fase, cdc, chiave); //aggiorna totali della commessa (importi per codcms senza tener conto di fase o cdc) TAssoc_array& riga_tot = get_row(_totali[indice], codcms, indice, codcms, EMPTY_STRING, EMPTY_STRING, gruppo); aggiorna_importo(riga_tot, gruppo, indbil, saldana); } } } } ///////////////////////////////////////////// // RIGHE MOVIMENTI ANALITICI ///////////////////////////////////////////// //elabora realmente la riga analitica che gli viene passata (serve sia per le rmovana pure (chiamata dalla parse_rmovava()).. //..che per quelle create contabilizzando un documento (chiamata dalla parse_rdoc_ordini()) void TPrint_saldana_recordset::elabora_rmovana(TAssoc_array* cms, const TDate& datainiesc, const TDate& datafinesc, const TRectype& movana, const TRectype& rmovana) { const char tipomov = movana.get_char(MOVANA_TIPOMOV); //la data iniziale è la datacomp sulla testata per tutte le righe const TDate datacomp = movana.get_date(MOVANA_DATACOMP); const TString& codcms = rmovana.get(RMOVANA_CODCMS); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); const int indice = ricava_sezione_di_stampa(rec_commesse, datainiesc, datafinesc); //solo le righe con commessa buona (indice >= 0) vengono considerate if (indice >= 0) { //ci sono filtri o raggruppamenti per fase o centro di costo? const TString& fase = rmovana.get(RMOVANA_CODFASE); const TString& cdc = rmovana.get(RMOVANA_CODCCOSTO); //se la riga è risultata buona ricava la chiave completa per l'assoc_array comprendendo eventuali.. //..fasi e/o cdc TString80 chiave; ricava_chiave_cdc_fase(codcms, fase, cdc, chiave); //calcola la "durata complessiva" della riga, ovvero l'intervallo di tempo per cui essa risulta valida //la data fine ci fa sudare un pò //di base è pari a datafcomp di testata (che è sempre esistente, mal che vada è uguale a datacomp) TDate datafcomp = movana.get_date(MOVANA_DATAFCOMP); //se invece è un movimento cazzuto con il calcolo automatico della data di morte (dataexpire)... if (movana.get_bool(MOVANA_AUTOFCOMP)) { //data del cazzo che serve per non rovinare datacomp, che è la data sulla riga, non quella iniziale di cms TDate datainicms; ca_durata_commessa(rec_commesse, datainicms, datafcomp); } //se siamo in presenza di un movimento senza datafcomp (inserito precdentemente alla nascita di datafcomp.. //..per tutti i movimenti, come nel gestore dei movana mette datafcomp = datacomp; if (!datafcomp.ok()) datafcomp = datacomp; //Attenzionissima! Se il movimento presenta una data fine competenza anteriore all'inizio dell'esercizio considerato.. //..va scartato perchè sarà incluso nei saldi finali dell'esercizio precedente! if (datafcomp < datainiesc) return; //finalmente la tanto agognata vita della riga di movana! //si aggiunge 1 perchè se un movimento ha datacomp=datafcomp (come in generale accade) in realtà.. //..il poveretto vive un giorno, non 0 const long vita_totale_riga = datafcomp - datacomp + 1; //riproporzionamento dell'importo di riga in base alla frazione di vita di riga interessata real importo = rmovana.get_real(RMOVANA_IMPORTO); if (vita_totale_riga > 1) { //trova la frazione di vita della riga che interessa l'esercizio corrente const TDate inizio_inter = fnc_max(datainiesc, datacomp); const TDate fine_inter = fnc_min(_datacalcolo, datafcomp); //si aggiunge anche qui 1 per gli stessi motivi della vita_totale const long vita_frazione_riga = fine_inter - inizio_inter + 1; //il riproporzionamento vale solo per i movimenti che durano più di 1 giorno e con una vita_frazione.. //..< vita_totale (il contrario sarebbe un errore!). I movimenti tutti nel futuro risultano con.. //..vita_frazione negativa e quindi non sono considerati //Anche le commesse tutte nel futuro rispetto a datacalcolo danno origine a una vita_frazione negativa.. //..parando il culo al povero programma if (vita_frazione_riga > 1 && vita_frazione_riga < vita_totale_riga) { importo = vita_frazione_riga * importo / vita_totale_riga; importo.round(2); } } //dopo tutto sto panegirico sul riproporzionamento finalmente si passa ad aggiornare gli array di stampa.. //..con gli importi aggiustati if (!importo.is_zero()) { #ifdef DBG if (codcms == "AS08LB4CRPATI") const int cazzone = 1; #endif const TString& codconto = rmovana.get(RMOVANA_CODCONTO); //trova l'indicatore di bilancio TString80 conto_anale; const int indbil = _indicatori.get_indbil(codconto, conto_anale); //solo i Costi(3) ed i Ricavi(4) devono essere considerati per la stampa if (indbil == 3 || indbil == 4) { //gruppo e conto servono solo per il caso _tipo=8 ma vanno dichiarati e ricavati.. //..qui in modo che siano a disposizione delle commesse del cazzo poco sotto const char* gruppo = indbil == 3 ? "COSTI" : "RICAVI"; TString80 conto; parse_bill(conto_anale, conto); //importo della riga già eventualmente riproporzionato prima (e sicuramente > 0) const TImporto importo_riga(rmovana.get_char(RMOVANA_SEZIONE), importo); //riga array da aggiungere agli arrayoni da mandare in stampa TAssoc_array& riga_array = get_row(cms[indice], chiave, indice, codcms, fase, cdc, rec_commesse.get(COMMESSE_DESCRIZ)); TRectype saldana(LF_SALDANA); saldana.put(SALDANA_ANNO, _anno); saldana.put(SALDANA_CONTO, conto_anale); saldana.put(SALDANA_COSTO, cdc); saldana.put(SALDANA_COMMESSA, codcms); saldana.put(SALDANA_FASE, fase); switch(tipomov) { case 'P': saldana.put(SALDANA_SEZIONEP, importo_riga.sezione()); saldana.put(SALDANA_SALDOP, importo_riga.valore()); break; case 'V': saldana.put(SALDANA_SEZIONEV, importo_riga.sezione()); saldana.put(SALDANA_SALDOV, importo_riga.valore()); break; default: saldana.put(SALDANA_SEZIONE, importo_riga.sezione()); saldana.put(SALDANA_SALDO, importo_riga.valore()); #ifdef DBG if (codcms == "FP08MB24005RN") { ofstream movimenti("C:/temp/movimenti.txt", ios::app); movimenti << rmovana.get(RMOVANA_NUMREG) << '\t' << rmovana.get(RMOVANA_DATACOMP) << '\t' << rmovana.get(RMOVANA_IMPORTO) << '\t' << rmovana.get(RMOVANA_SEZIONE) << '\t' << importo_riga.valore() << '\t' << importo_riga.sezione() << endl; } #endif break; } //aggiunge gli importi e normalizza aggiorna_importo(riga_array, gruppo, indbil, saldana); aggiorna_importo(riga_array, conto, indbil, saldana); } } } //if(indice>=0)... } //aggiorna l'arrayone cms con le rmovana presenti nel periodo di calcolo dell'ultimo esercizio void TPrint_saldana_recordset::parse_rmovana(TAssoc_array* cms, const TDate& datainiesc, const TDate& datafinesc) { const TDate min_datacomp = calcola_min_datacomp(datainiesc, datafinesc); //cerca tutte le rmovana che soddisfano gli innumerevoli parametri TString query; query << "USE RMOVANA KEY 3\n"; const TString& select = crea_select(LF_RMOVANA); if (select.full()) query << " SELECT " << select; query << "\nJOIN MOVANA INTO NUMREG==NUMREG" << "\nFROM DATACOMP=#MINDATACOMP" << "\nTO DATACOMP=#DATACALCOLO"; TISAM_recordset recset(query); recset.set_var("#DATACALCOLO", _datacalcolo); recset.set_var("#MINDATACOMP", min_datacomp); const TRecnotype recset_items = recset.items(); //se ci sono movana che non expirano prima dell'inizio esercizio e la cui datacomp è anteriore a datacalcolo... if (recset_items > 0) { //record correntemente in esame di rmovana e movana const TRectype& rmovana = recset.cursor()->curr(); const TRectype& movana = recset.cursor()->curr(LF_MOVANA); //simpatica progind per intrattenere l'utonto TProgind pi(recset_items, "Scansione movimenti...", true, true); #ifdef DBG { ofstream movimenti("C:/temp/movimenti.txt"); movimenti << endl; } #endif for (bool ok = recset.move_first(); ok; ok = recset.move_next()) //giro sui vari rmovana... { //aggiornamento progind intrattenitiva if (!pi.addstatus(1)) break; //metodo per generare i saldi alla data della riga analitica in base alla vita della riga elabora_rmovana(cms, datainiesc, datafinesc, movana, rmovana); } //for(bool ok=recset.move_first()... } //if(recset_items>0... } //aggiorna l'arrayone cms con le righedoc non ancora contabilizzate void TPrint_saldana_recordset::parse_rdoc_ordini(TAssoc_array* cms, const TDate& datainiesc, const TDate& datafinesc) { //solo le numerazioni con almeno un tipo documento ordine interessano TString_array num_ordini, tip_ordini; const int numerazioni_tipo_ordine = numerazioni_ordini(num_ordini, tip_ordini); #ifdef DBG //file di controllo degli ordini elaborati ofstream ordini("c:/temp/ordini.txt"); ofstream mov_da_ordini("c:/temp/mov_da_ordini.txt"); #endif for (int n = 0; n < numerazioni_tipo_ordine; n++) { const TString4 codnum = num_ordini.row(n); //cerca tutte le righe documento che soddisfano i numerosi (fin troppo) parametri //joina DOC perchè abbiamo un decisivo filtro sul range di date TString query; query << "USE RDOC KEY 1\n"; query << "SELECT (BETWEEN(DOC.DATADOC,#DATAINIES,#DATACALCOLO))&&(RIGAEVASA!=\"X\")"; //filtro su cdc/cms/fasi (fatto come per saldi e rmovana; in tutti i files.. //..i nomi dei campi sono diversi! -> tentiamo con il metodo automaggico const TString& select = crea_select(LF_RIGHEDOC); if (select.full()) { query << "&&(" << select << ")"; } query << "\nJOIN DOC INTO PROVV==PROVV ANNO==ANNO CODNUM==CODNUM NDOC==NDOC" << "\nFROM CODNUM=#CODNUM ANNO=#ANNO PROVV=D" << "\nTO CODNUM=#CODNUM ANNO=#ANNO PROVV=D"; TISAM_recordset recset(query); recset.set_var("#ANNO", (long)_datacalcolo.year()); recset.set_var("#CODNUM", TVariant(codnum)); recset.set_var("#DATAINIES", datainiesc); recset.set_var("#DATACALCOLO", _datacalcolo); const TRecnotype recset_items = recset.items(); //simpatica progind per intrattenere l'utonto TProgind pi(recset_items, "Scansione ordini inevasi...", true, true); //memorizza l'ultimo doc per evitare doppioni in caso di doc con più righe (rielaborerebbe.. //..lo stesso documento tante volte quante sono le sue righe!) TString old_key; //misterioso oggetto necessario per contabilizzare il documento in osservazione TContabilizzazione_analitica cont_anal; for (bool ok = recset.move_first(); ok; ok = recset.move_next()) //giro sulle varie rdoc... { //aggiornamento progind intrattenitiva if (!pi.addstatus(1)) break; const TRectype& curr_doc = recset.cursor()->curr(LF_DOC); //controlla se il documento contenente la riga è davvero un ordine ricontrollando il suo tipo nell'array.. //..con i tipi validi; se non lo fosse...ciao ciao rigadocumento! const TString& tipodoc = curr_doc.get(DOC_TIPODOC); if (tip_ordini.find(tipodoc) < 0) continue; //ovviamente non è finita qui... //la riga documento non deve risultare contabilizzata! infatti, se lo fosse, i suoi valori apparirebbero.. //..nella sezione delle rmovana const long numregca = curr_doc.get_long(DOC_NUMREGCA); //se la rigadoc non è stata contabilizzata.. if (numregca == 0) { //magico trucco per non dover ricontabilizzare lo stesso documento tante volte quante sono le righe consecutive const TString curr_key = curr_doc.build_key(); if (curr_key == old_key) continue; else old_key = curr_key; //crea il documento virtuale in memoria; se non è ordine oppure lo è ma è già evaso, lo saltiamo!!! ole'! TDocumento doc(curr_doc); if (!doc.is_ordine() || doc.is_evaso()) continue; //il documento virtuale è adesso un ordine non evaso //tarocchiamo il documento prendendo solo le righe non evase (almeno una ci sarà, perchè la query del recordset.. //..richiedeva che la rigadoc fosse non evasa, quindi quella riga nel doc esiste, magari in compagnia di altre) bool mov_da_ord = false; for (int r = doc.body().last_row(); r > 0; r = doc.body().pred_row(r)) { TRiga_documento& rigadoc = doc[r]; //trattamento delle righe non evase di tipo merce o prestazione if (rigadoc.is_merce() || rigadoc.is_prestazione()) { if (!rigadoc.is_evasa()) { //trasforma tutte le righe a valore, assegnando al prezzo il valore del residuo const real valore = rigadoc.valore(true, false, AUTO_DECIMALS); const real residuo = rigadoc.valore(false, false, AUTO_DECIMALS); //ovviamente questo è vero se il residuo è > 0; se fosse nullo sarebbe evasa in pratica //..se fosse maggiore sarebbe riga del cazzo if (residuo > ZERO) { rigadoc.put(RDOC_QTA, UNO); rigadoc.put(RDOC_PREZZO, residuo); #ifdef DBG //file di controllo in output TString80 cdc = rigadoc.get(RDOC_CODCOSTO); TString80 cms = rigadoc.get(RDOC_CODCMS); if (cdc.empty()) cdc = doc.get(DOC_CODCOSTO); if (cms.empty()) cms = doc.get(DOC_CODCMS); if (cdc == "BO04" && cms == "AS10MB4RETECO") { ordini << rigadoc.get(RDOC_PROVV) << '\t' << rigadoc.get(RDOC_ANNO) << '\t' << rigadoc.get(RDOC_CODNUM) << '\t' << rigadoc.get(RDOC_NDOC) << '\t' << rigadoc.get(RDOC_NRIGA) << '\t' << rigadoc.get(RDOC_CODART) << '\t' << rigadoc.get(RDOC_TIPORIGA) << '\t' << valore.stringa() << '\t' << residuo.stringa() << endl; mov_da_ord = true; } #endif } else doc.body().destroy_row(r, true); //righe a residuo 0 ma non flaggate come evase (errori) } else doc.body().destroy_row(r, true); //se la riga fosse evasa la salta e compatta il documento } } //movana nevessario per la contabilizzazione analitica del documento TAnal_mov movana; //finalmente contabilizza il documento in memoria cont_anal.elabora(doc, 0, NULL, false, movana, false); movana.put(MOVANA_TIPOMOV, ' '); //controlla che la riga in esame abbia realmente la cms/cdc/fas indicata nel filtro; //procedimento necessario per evitare di prendere righe appartenenti a docs elaborati //perchè contenenti 1 riga con cms corretta ed altre righe con cms sbagliate for (int j = 1; j <= movana.rows(); j++) { const TRectype& rmovana = movana.body()[j]; if (_cdc.not_empty() && rmovana.get(RMOVANA_CODCCOSTO) != _cdc) continue; if (_fase.not_empty() && rmovana.get(RMOVANA_CODFASE) != _fase) continue; //metodo per il calcolo importo riga riproporzionato //metodo per generare i saldi alla data della riga analitica in base alla vita della riga elabora_rmovana(cms, datainiesc, datafinesc, movana, rmovana); #ifdef DBG //file di controllo in output if (mov_da_ord) { mov_da_ordini << movana.get(MOVANA_DANNO) << '\t' << movana.get(MOVANA_DCODNUM) << '\t' << movana.get(MOVANA_DNDOC) << '\t' << rmovana.get(RMOVANA_CODCMS) << '\t' << rmovana.get(RMOVANA_CODCCOSTO) << '\t' << rmovana.get(RMOVANA_SEZIONE) << '\t' << rmovana.get_real(RMOVANA_IMPORTO).stringa() << endl; } #endif } //for int j... } } //for (bool ok = recset.... } //for (int n = 0; n < numerazioni... } //aggiorna l'arrayone cms con le righedoc non ancora contabilizzate void TPrint_saldana_recordset::parse_rdoc_fatture(TAssoc_array* cms, const TDate& datainiesc, const TDate& datafinesc) { //solo le numerazioni con almeno un tipo documento fattura interessano TString_array num_fatture, tip_fatture; const int numerazioni_tipo_fattura = numerazioni_fatture(num_fatture, tip_fatture); #ifdef DBG ofstream fatture("c:/temp/fatture.txt", ios::app); #endif for (int n = 0; n < numerazioni_tipo_fattura; n++) { const TString4 codnum = num_fatture.row(n); //cerca tutte le righe documento che soddisfano i numerosi (fin troppo) parametri //joina DOC perchè abbiamo un decisivo filtro sul range di date TString query; query << "USE DOC" << "\nSELECT (STR(NUMREGCA=0))&&(BETWEEN(DATADOC,#DATAINIES,#DATACALCOLO))" << "\nFROM PROVV=D ANNO=#ANNO CODNUM=#CODNUM" << "\nTO PROVV=D ANNO=#ANNO CODNUM=#CODNUM"; TISAM_recordset recset(query); recset.set_var("#ANNO", (long)_datacalcolo.year()); recset.set_var("#CODNUM", TVariant(codnum)); recset.set_var("#DATAINIES", datainiesc); recset.set_var("#DATACALCOLO", _datacalcolo); const TRecnotype recset_items = recset.items(); //simpatica progind per intrattenere l'utonto TProgind pi(recset_items, "Scansione altri documenti da contabilizzare...", true, true); //misterioso oggetto necessario per contabilizzare il documento in osservazione TContabilizzazione_analitica cont_anal; for (bool ok = recset.move_first(); ok; ok = recset.move_next()) //giro sulle varie rdoc... { //aggiornamento progind intrattenitiva if (!pi.addstatus(1)) break; const TRectype& curr_doc = recset.cursor()->curr(); //controlla se il documento contenente la riga è davvero un ordine ricontrollando il suo tipo nell'array.. //..con i tipi validi; se non lo fosse...ciao ciao rigadocumento! const TString& tipodoc = curr_doc.get(DOC_TIPODOC); if (tip_fatture.find(tipodoc) < 0) continue; //crea il documento virtuale in memoria; TDocumento doc(curr_doc); //se il documento non ha una numerazione valida per la contabilizzazione analitica lo deve saltare //E' il caso di quelle fatture figlie di FDR che sono già state contabilizzate in quel momento (come FDR).. //..e quindi non devono essere ricontabilizzate come fatture vere e proprie (es. FAQ) const int num_rows = doc.physical_rows(); bool is_fdr = false; for (int k = 1; k <= num_rows && !is_fdr; k++) { const TRiga_documento& riga = doc[k]; const TRectype* riga_babbo = riga.find_original_rdoc(); if (riga_babbo != NULL && riga_babbo->get(RDOC_PROVV).not_empty()) { const TString& key(riga_babbo->get(RDOC_CODNUM)); const TCodice_numerazione& num = TDocumento::codice_numerazione(key); if (num.fattura_emettere_ricevere()) is_fdr = true; } } if (is_fdr) continue; //movana nevessario per la contabilizzazione analitica del documento TAnal_mov movana; //finalmente contabilizza il documento in memoria cont_anal.elabora(doc, 0, NULL, false, movana, false); movana.put(MOVANA_TIPOMOV, ' '); //controlla che la riga in esame abbia realmente la cms/cdc/fas indicata nel filtro; //procedimento necessario per evitare di prendere righe appartenenti a docs elaborati //perchè contenenti 1 riga con cms corretta ed altre righe con cms sbagliate for (int j = 1; j <= movana.rows(); j++) { const TRectype& rmovana = movana.body()[j]; if (_cdc.not_empty() && rmovana.get(RMOVANA_CODCCOSTO) != _cdc) continue; if (_fase.not_empty() && rmovana.get(RMOVANA_CODFASE) != _fase) continue; //ulteriore controllo in base ai permessi utente! se il record non rispetta i permessi viene saltato! if (!ca_filter_record(rmovana)) continue; //metodo per il calcolo importo riga riproporzionato //metodo per generare i saldi alla data della riga analitica in base alla vita della riga elabora_rmovana(cms, datainiesc, datafinesc, movana, rmovana); #ifdef DBG //file di controllo in output if (rmovana.get(RMOVANA_CODCMS) == "FP08MB24005RN") { fatture << movana.get(MOVANA_DANNO) << '\t' << movana.get(MOVANA_DCODNUM) << '\t' << movana.get(MOVANA_DNDOC) << '\t' << rmovana.get(RMOVANA_CODCMS) << '\t' << rmovana.get(RMOVANA_CODCCOSTO) << '\t' << rmovana.get(RMOVANA_SEZIONE) << '\t' << rmovana.get_real(RMOVANA_IMPORTO).stringa() << endl; } #endif } //for int j... } //for (bool ok = recset.... } //for (int n = 0; n < numerazioni... } //metodo principale di riempimento degli array da mandare in stampa void TPrint_saldana_recordset::create_lines_to_print() { //ricava date limite di esercizio TEsercizi_contabili esc; TDate datainiesc, datafinesc; esc.code2range(_anno, datainiesc, datafinesc); //array con le commesse divise sui vari livelli di sezione di stampa TAssoc_array cms[NUM_LEVELS]; // 1) // calcolo dei saldi come sono in SALDANA // 1_a) calcolo dei saldi alla data fine esercizio (vale per entrambi i tipi di stampa, ovvero _tipo=8 e _tipo=9) parse_saldana(cms, datainiesc, datafinesc); // 1_b) calcolo dei saldi futuri, ovvero con esercizio futuro a quello scelto per il calcolo dei saldi if (_tipo == 8) parse_saldana_futuri(); // 2) // calcolo dei saldi ad una data diversa da una data di fine esercizio (saldi alla data di adolfica richiesta) // serve solo per il bilancio di commessa (_tipo = 8) if (_tipo == 8) { if ((_datacalcolo < datafinesc) && !_vitaintera) { // 2_a) calcolo dei saldi da righe movimenti analitici e quindi senza saldana parse_rmovana(cms, datainiesc, datafinesc); } //if((_datacalcoloremove_obj(); if (strcmp(k, CMS_DEL_CAZZO) == 0) cazzo_cms = obj; else _righe.add(obj); // Copia nella destinazione la riga corrente e la toglie dall'originale } if (cazzo_cms != NULL) _righe.add(cazzo_cms); } //for(int... _righe.sort(righe_compare); //sorting delle commesse } void TPrint_saldana_recordset::requery() { //***Metodo principale per la creazione della intera stampa*** //Messo nella requery perchè sempre chiamata qualsiasi sia il tipo di stampa create_lines_to_print(); } const TVariant& TPrint_saldana_recordset::get(unsigned int column) const { return NULL_VARIANT; } const TVariant& TPrint_saldana_recordset::get(const char* column_name) const { if (_curr >= 0 && _curr < items()) { if (*column_name == '#') column_name++; TVariant& var = get_tmp_var(); if (strcmp(column_name, "ANNO") == 0) { var.set(_anno); } else if (strcmp(column_name, "TIPOSTIMA") == 0) { switch (_tipostima) { case 'T': var.set("T"); break; case 'C': var.set("C"); break; case 'R': var.set("R"); break; default: break; } } else if (strcmp(column_name, "DEPTH") == 0) { var.set(_depth); } else if (strcmp(column_name, "DETRCONS") == 0) { var.set(_detrazioni_consuntive == true ? "X" : ""); } else if (strcmp(column_name, "VITAINTERA") == 0) { var.set(_vitaintera == true ? "SI" : "NO"); } else if (strcmp(column_name, "STAMPAFASI") == 0) { var.set((_tipostampa == 1 || _tipostampa == 3) ? "X" : ""); } else if (strcmp(column_name, "FASESPEC") == 0) { if (_tipostampa == 1 || _tipostampa == 3 || _tipostampa == 4) var.set(_fase); else var.set(EMPTY_STRING); } else if (strcmp(column_name, "STAMPACDC") == 0) { var.set((_tipostampa == 2 || _tipostampa == 3) ? "X" : ""); } else if (strcmp(column_name, "CDCSPEC") == 0) { if (_tipostampa == 2 || _tipostampa == 3 || _tipostampa == 8) var.set(_cdc); else var.set(EMPTY_STRING); } else if (strcmp(column_name, "DATAINI") == 0) { const TString& codcms = get("CODCMS").as_string(); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); var.set(rec_commesse.get(COMMESSE_DATAINIZIO)); } else if (strcmp(column_name, "DATAFINE") == 0) { const TString& codcms = get("CODCMS").as_string(); const TRectype& rec_commesse = cache().get(LF_COMMESSE, codcms); TDate datafine = rec_commesse.get(COMMESSE_DATAPROR); if (!datafine.ok()) datafine = rec_commesse.get(COMMESSE_DATAFINE); var.set(datafine); } else if (strcmp(column_name, "AVANZAMENTO") == 0) { //Calcola lo stato di avanzamento della commessa in caso di stima x Tempo real avanzamento; if (_tipostima == 'T') { avanzamento = calcola_avanzamento_tempo(); } else //se stima e' di tipo Costi/Ricavi invece....Allah!! { TAssoc_array& riga = (TAssoc_array&)_righe[_curr]; const real val = get("RICAVI").as_real(); if (!val.is_zero()) { const int indice = get("LEVEL").as_int(); const TString& codcms = get("CODCMS").as_string(); #ifdef DBG if (codcms == "FP08PB2202INN") const int cazzone = 1; #endif TAssoc_array& riga_tot = get_row((TAssoc_array&)_totali[indice], codcms, indice, codcms, EMPTY_STRING, EMPTY_STRING, "RICAVI"); const TString* stric = (const TString*)riga_tot.objptr("RICAVI"); if (stric && stric->full()) { const real totric = *stric; if (!totric.is_zero()) avanzamento = val * CENTO / totric; } } } var.set(avanzamento); } else //if(strcmp(column_name,AVANZAMENTO... { TAssoc_array& riga = (TAssoc_array&)_righe[_curr]; if (strncmp(column_name, "RECORD.", 7) == 0) column_name += 7; if (strcmp(column_name, "COS_PERC") == 0) { const int indice = get("LEVEL").as_int(); if (_forza_maturato && indice <= 1) var.set(CENTO); else { const TString* val_bdg = (TString*)riga.objptr("COS_BDG"); if (val_bdg == NULL || real::is_null(*val_bdg)) var.set(CENTO); else { const TString* val_mat = (TString*)riga.objptr("COS_MAT"); if (val_mat == NULL || real::is_null(*val_mat)) var.set(ZERO); else { const real bdg(*val_bdg); const real mat(*val_mat); real perc = mat * CENTO / bdg; perc.round(2); var.set(perc); } } } } else { const TString* val = (TString*)riga.objptr(column_name); if (val) var.set(*val); else var.set_null(); } } return var; } return NULL_VARIANT; } void TPrint_saldana_recordset::set_filter(const TMask& msk, const TString& curr_sublevel) { _fase = _cdc = ""; _forza_maturato = false; //tira su un po' di parametri dalla maschera... _anno = msk.get_int(F_ESERCIZIO); _datacalcolo = msk.get_date(F_FINE_ES); //prende anche il prefix TString80 prefix; for (short id = F_PRE1; id <= F_PRE3 && msk.id2pos(id) > 0; id++) prefix << msk.get(id); _indicatori.set_prefix(prefix); //solo per ca3800 if (_tipo == 8) { _tipostima = msk.get(F_TIPOSTIMA)[0]; _vitaintera = msk.get_bool(F_VITAINTERA); _include_documenti = msk.get_bool(F_INCLUDE_DOCUMENTI); _depth = msk.get_int(F_DEPTH); _tipostampa = msk.get_int(F_TIPOSTAMPA); _detrazioni_consuntive = msk.get_bool(F_DETR_CONS); //in base al tipo di stampa selezionata setta un po' di parametri switch (_tipostampa) { case 1: _fase = msk.get(F_FASE); _cdc.cut(0); break; case 2: _cdc = msk.get(F_CDC); _fase.cut(0); break; case 3: _fase = msk.get(F_FASE); _cdc = msk.get(F_CDC); break; case 4: _fase = curr_sublevel; break; case 8: _cdc = curr_sublevel; break; default: break; } } //if(tipo==8.. if (_tipo == 9) { _forza_maturato = msk.get_bool(F_FORZA_MATURATO); } }