#include #include #include #include #include #include "ce2101.h" #include "celib.h" #include "ammce.h" #include "ammmv.h" #include "catdi.h" #include "cespi.h" #include "movam.h" #include "movce.h" #include "salce.h" #include "../cg/cglib01.h" /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// HIDDEN void log(const char* fmt, ...) { /* #ifdef DBG char msg[256]; va_list argptr; va_start(argptr,fmt); vsprintf(msg,fmt,argptr); va_end(argptr); FILE* f = fopen("trace.log", "a"); if (f != NULL) { fprintf(f, "%s\n", msg); fclose(f); } #endif */ } // Azzera i campi fld del record rec // Cerified 100% HIDDEN void zero_fields(TRectype& rec, const char* fld0, const char* fld1, const char* fld2 = NULL, const char* fld3 = NULL, const char* fld4 = NULL, const char* fld5 = NULL, const char* fld6 = NULL, const char* fld7 = NULL, const char* fld8 = NULL, const char* fld9 = NULL, const char* fld10 = NULL, const char* fld11 = NULL) { rec.zero(fld0); rec.zero(fld1); if (fld2 && *fld2) rec.zero(fld2); if (fld3 && *fld3) rec.zero(fld3); if (fld4 && *fld4) rec.zero(fld4); if (fld5 && *fld5) rec.zero(fld5); if (fld6 && *fld6) rec.zero(fld6); if (fld7 && *fld7) rec.zero(fld7); if (fld8 && *fld8) rec.zero(fld8); if (fld9 && *fld9) rec.zero(fld9); if (fld10 && *fld10) rec.zero(fld10); if (fld11 && *fld11) rec.zero(fld11); } // Somma i campi fld del record rec // Cerified 100% HIDDEN real sum_fields(const TRectype& rec, const char* fld0, const char* fld1, const char* fld2 = NULL, const char* fld3 = NULL, const char* fld4 = NULL, const char* fld5 = NULL, const char* fld6 = NULL, const char* fld7 = NULL, const char* fld8 = NULL, const char* fld9 = NULL, const char* fld10 = NULL, const char* fld11 = NULL) { real sum = rec.get_real(fld0); sum += rec.get_real(fld1); if (fld2 && *fld2) sum += rec.get_real(fld2); if (fld3 && *fld3) sum += rec.get_real(fld3); if (fld4 && *fld4) sum += rec.get_real(fld4); if (fld5 && *fld5) sum += rec.get_real(fld5); if (fld6 && *fld6) sum += rec.get_real(fld6); if (fld7 && *fld7) sum += rec.get_real(fld7); if (fld8 && *fld8) sum += rec.get_real(fld8); if (fld9 && *fld9) sum += rec.get_real(fld9); if (fld10 && *fld10) sum += rec.get_real(fld10); if (fld11 && *fld11) sum += rec.get_real(fld11); return sum; } /////////////////////////////////////////////////////////// // TCespite /////////////////////////////////////////////////////////// // Limite massimo per ammortamento "immediato" // Certified 99% real TCespite::un_milione() const { static real million; if (million.is_zero()) { million = 1000000.0; if (is_euro_value("")) // Se la ditta corrente e' in Euro { million /= 1936.27; million.round(2); } } return million; } // Riempie la chiave principale di un record di SALCE // Certified 100% void TCespite::fill_sal_key(TRectype& salce, int esercizio, int tpsal) const { salce.zero(); salce.put(SALCE_IDCESPITE, get(CESPI_IDCESPITE)); salce.put(SALCE_CODES, esercizio); salce.put(SALCE_TPSALDO, tpsal); } // Riempie la chiave principale di un record di AMMCE // Certified 100% void TCespite::fill_amm_key(TRectype& ammce, int esercizio, int tpsal) const { ammce.zero(); ammce.put(AMMCE_IDCESPITE, get(CESPI_IDCESPITE)); ammce.put(AMMCE_CODES, esercizio); ammce.put(AMMCE_TPSALDO, tpsal); ammce.put(AMMCE_TPAMM, _tipo_sit); } // Lettura ed eventuale creazione dei saldi iniziali e progressivi // Certified 99% void TCespite::read_sal(int esercizio) { TLocalisamfile salce(LF_SALCE); fill_sal_key(salce.curr(), esercizio, 1); if (salce.read() == NOERR) { _salini = salce.curr(); // Il campo VNONAMMC nasce solo nel 2006, prima era da intendersi uguale a VNONAMM if (!_salini.get_real(SALCE_VNONAMM).is_zero() && _salini.get_real(SALCE_VNONAMMC).is_zero()) { TDate di, df; ditta_cespiti().esercizio_corrente(di, df); if (di < TDate(4,7,2006)) _salini.put(SALCE_VNONAMMC, _salini.get(SALCE_VNONAMM)); } } else { fill_sal_key(_salini, esercizio, 1); _salini.write(salce); } _salpro = _salini; _salpro.put(SALCE_TPSALDO, 2); } // Lettura ed eventuale creazione degli ammortamenti iniziali e progressivi // Certified 99% void TCespite::read_amm(int esercizio) { TLocalisamfile ammce(LF_AMMCE); TRectype& curr = ammce.curr(); fill_amm_key(curr, esercizio, 1); if (ammce.read() == NOERR) _ammini = curr; else { fill_amm_key(_ammini, esercizio, 1); _ammini.write(ammce); } fill_amm_key(curr, esercizio, 2); if (ammce.read() == NOERR) _ammpro = curr; else { fill_amm_key(_ammpro, esercizio, 2); _ammpro.write(ammce); } _ammpro.put(AMMCE_QNORP, _ammini.get(AMMCE_QNOR)); _ammpro.put(AMMCE_QACCP, _ammini.get(AMMCE_QACC)); _ammpro.put(AMMCE_QANTP, _ammini.get(AMMCE_QANT)); _ammpro.put(AMMCE_QPERSEP, _ammini.get(AMMCE_QPERSE)); _ammpro.put(AMMCE_FPRIVATOP, _ammini.get(AMMCE_FPRIVATO)); _ammpro.put(AMMCE_QPPRIVATEP, _ammini.get(AMMCE_QPPRIVATE)); _ammpro.put(AMMCE_SCELTE, _ammini.get(AMMCE_SCELTE)); _ammpro.put(AMMCE_FRINGEBEN, _ammini.get(AMMCE_FRINGEBEN)); zero_fields(_ammpro, AMMCE_MSG01, AMMCE_MSG02, AMMCE_MSG03, AMMCE_MSG04, AMMCE_MSG05, AMMCE_MSGD05, AMMCE_MSG06, NULL); const real cde = ditta_cespiti().coefficiente_durata_esercizio(); if (cde != UNO) _ammpro.put(AMMCE_MSG02, "X"); const int uso_promiscuo = get_int(CESPI_USOPROM); if (uso_promiscuo > 1) _ammpro.put(AMMCE_MSG03, "X"); } // Salva SALPRO // Certified 100% void TCespite::save_sal() const { if (!_in_memory) { TLocalisamfile salce(LF_SALCE); int err = _salpro.rewrite_write(salce); if (err != NOERR) error_box(FR("Errore %d durante la scrittura sui saldi del cespite %s"), err, (const char*)get(CESPI_IDCESPITE)); log(FR("- Scrittura salpro %d: errore %d"), _tipo_sit, err); } } // Salva AMMPRO // Certified 100% void TCespite::save_amm() const { if (_in_memory) { if (_fraction > ZERO && _fraction < UNO) // Simulazione con data limite operazioni { const TDitta_cespiti& cce = ditta_cespiti(); const char* field[] = { AMMCE_QNOR, AMMCE_QANT, AMMCE_QACC, AMMCE_QPERSE, AMMCE_FPRIVATO, AMMCE_QPPRIVATE, NULL }; for (int i = 0; field[i]; i++) { real val = _ammpro.get(field[i]); val *= _fraction; cce.arrotonda(val); ((TRectype&)_ammpro).put(field[i], val); } } } else { TLocalisamfile ammce(LF_AMMCE); int err = _ammpro.rewrite_write(ammce); if (err != NOERR) error_box(TR("Errore %d durante la scrittura sugli ammortamenti del cespite %s"), err, (const char*)get(CESPI_IDCESPITE)); log(TR("- Scrittura ammpro %d: errore %d"), _tipo_sit, err); } } // Ritorna il record della categoria del cespite // Certified 100% const TRectype& TCespite::categoria() const { const int gruppo = get_int(CESPI_CODCGRA); const TString4 specie = get(CESPI_CODSPA); const int categ = get_int(CESPI_CODCAT); return ditta_cespiti().categoria(gruppo, specie, categ); } // Tipo del cespite: 0 = Materiale, 1 = Immateriale, 2 = Pluriennale // Attenzione: analisi, foxpro, neurocampo // Codifica: M I P 1 2 3 0 1 2 // Certified 100% TTipo_cespite TCespite::tipo() const { const int tc = categoria().get_int("I0"); return tc==0 ? tc_materiale : (tc==1 ? tc_immateriale : tc_pluriennale); } TTipoFabbricato TCespite::fabbricato() const { TTipoFabbricato tf = tf_nessuno; switch (get_int(CESPI_FABBR06)) { case 1: tf = tf_industriale; break; case 2: tf = tf_altro; break; default: break; } CHECK(tf == tf_nessuno || veicolo() == tv_nessuno, "Fabbricato veicolato"); return tf; } TTipoVeicolo TCespite::veicolo() const { TTipoVeicolo tv = tv_nessuno; // Normalmente non sono un veicolo! switch (get_int(CESPI_FLGTPVEI)) { case 2: tv = tv_automobile; break; case 3: tv = tv_motociclo; break; case 4: tv = tv_ciclomotore; break; case 5: tv = tv_altro; break; default: break; } CHECK(tv == tv_nessuno || fabbricato() == tf_nessuno, "Veicolo fabbricato"); return tv; } bool TCespite::auto_o_moto() const { const TTipoVeicolo tv = veicolo(); return tv >= tv_automobile && tv <= tv_ciclomotore; } // Registra un messaggio 5 su AMMPRO // Certified 100% void TCespite::set_msg05(const char* msg) { _ammpro.put("MSG05", "X"); _ammpro.put("MSGD05", msg); save_amm(); } // Controlla se un cespite è valido, nel senso che si puo' calcolarne l'ammortamento // Certified 75% bool TCespite::valido() { log(TR("- Controllo validita`")); const TDitta_cespiti& dc = ditta_cespiti(); TDate ini_es, fin_es; const int esercizio = dc.esercizio_corrente(ini_es, fin_es); // Legge ammpro per scriverci eventuali messaggi read_amm(esercizio); // Cespite alienato const TDate alienazione = get_date(CESPI_DTALIEN); if (alienazione.ok() && alienazione < ini_es) { set_msg05(TR("cespite completamente eliminato.")); return false; } // Categoria non ammortizzabile const TRectype& cat = categoria(); if (cat.get_bool("B0")) { set_msg05(TR("categoria non ammortizzabile.")); return false; } // Cespite non ancora completato const TDate completamento = get_date(CESPI_DTCOMP); if (!completamento.ok() || completamento > fin_es) { set_msg05(TR("cespite non completato.")); return false; } // Cespite materiale non in funzione // Immateriali, no tuir, non in funzione const TTipo_cespite tc = tipo(); if (tc == tc_materiale || (tc == tc_immateriale && !get_bool(CESPI_TUIR))) { const TDate funzione = get_date(CESPI_DTFUNZ); if (!funzione.ok() || funzione > fin_es) { set_msg05(TR("cespite non ancora entrato in funzione.")); return false; } } // Materiali no TUIR, non conseguiti ricavi // Pluriennali, non conseguiti ricavi if ((tc == tc_materiale && !get_bool(CESPI_TUIR)) || tc == tc_pluriennale) { if (dc.rinvio_ammortamento_ai_primi_ricavi()) { const TDate& ricavi = dc.data_primi_ricavi(); if (!ricavi.ok() || ricavi > fin_es) { set_msg05(TR("non sono ancora stati conseguiti ricavi.")); return false; } } } // Pluriennali nuovi, decorrenza ammortamento anno successivo if (tc == tc_pluriennale && cat.get_bool("B1")) { if (completamento >= ini_es && completamento <= fin_es) { set_msg05(TR("decorrenza ammortamenti dall'esercizio successivo.")); return false; } } return true; } // Calcola il valore ammortizzabile di un cespite in base a quanto scritto in SALPRO // Certified 50% real TCespite::val_amm() const { real val = sum_fields(_salpro, SALCE_CSTO, SALCE_RIV75, SALCE_RIV83); val -= sum_fields(_salpro, SALCE_PLUSREIN, SALCE_VNONAMM); const bool leasing = get_bool(CESPI_LEASING); if (_tipo_sit == 1 || leasing) val += _salpro.get_real(SALCE_RIVGF); else if (_tipo_sit == 2 && !leasing) val += _salpro.get_real(SALCE_RIVGC); const real riv90 = _salpro.get_real(SALCE_RIV90); const real riv91 = _salpro.get_real(SALCE_RIV91); if (!riv90.is_zero() || !riv91.is_zero()) { const int annipost90 = _salpro.get_int(SALCE_ANNIPOST90); if (!riv91.is_zero() || annipost90 >= 3) val += riv90; val += riv91; } // Novita' 2006: gestione VNONAMM06 e VNONAMMC if (_tipo_sit == 1) { val -= _salpro.get_real(SALCE_VNONAMM06); // Considero i fabbricati solo in fiscale } if (_tipo_sit == 2) { val += _salpro.get_real(SALCE_VNONAMM); // Metto nuovamente il VNONAMM fiscale ... val -= _salpro.get_real(SALCE_VNONAMMC); // ... poi tolgo il civilistico } return val; } // Calcola il residuo ammortizzabile di un cespite in base a quanto scritto in SALPRO e AMMPRO // Certified 75% real TCespite::res_amm() const { const real valamm = val_amm(); // Valore ammortizzabile // Fondo ammortamento const real fondo = sum_fields(_ammpro, AMMCE_QNORP, AMMCE_QANTP, AMMCE_QACCP, AMMCE_QPERSEP, AMMCE_QPPRIVATEP, AMMCE_FPRIVATOP); const real resamm = valamm - fondo; // Residuo da ammortizzare return resamm; } // Cerca nella tabella dei limiti l'ultima data precedente alla fine esercizio passata come parametro // Certified 90% TRectype& date2limit(const TDate& d) { static TAssoc_array limits; // const TString16 key = d.string(ANSI); // Non serve l'intera data: tabella del c.... TString4 key; key.format("%04d", d.year()); TRectype* lim = (TRectype*)limits.objptr(key); if (lim == NULL) { TTable clm("%CLM"); bool ok = clm.last() == NOERR; if (ok) { TDate datalim = clm.get_date("CODTAB"); ok = d >= datalim; while (!ok) { if (clm.prev() != NOERR) break; datalim = clm.get("CODTAB"); ok = d >= datalim; } } lim = new TRectype(clm.curr()); if (!ok) // Should never happen! lim->zero(); limits.add(key, lim); } return *lim; } // Calcola il limite massimo ammortizzabile per il tipo di veicolo // Certified 90% real TCespite::get_limit() const { real limite = -1.0; // Partiamo con limite non valido che in realtà e' considerato +infinito // Mi pare inutile cercare limiti se è un veicolo senza limiti! if (auto_o_moto()) { TDate inies, fines; ditta_cespiti().esercizio_corrente(inies, fines); const TRectype& clm = date2limit(fines); // Questo if contiene la funzione fox cerca_limite // Stabilisce il limite in base al tipo di veicolo ed al suo uso if (!clm.empty()) { const TTipoVeicolo tipo_veicolo = veicolo(); switch(tipo_veicolo) { case tv_automobile: switch (get_int(CESPI_USOPROM)) { case 1: break; // Uso strumentale deducibile al 100% case 3: limite = clm.get_real("R1"); break; // Agenti/rappresentanti default: limite = clm.get_real("R0"); break; // 2,4,5 = casi standard } break; case tv_motociclo : limite = clm.get_real("R2"); break; // Limite motocicli case tv_ciclomotore: limite = clm.get_real("R3"); break; // Limite ciclomotori default: break; } } } return limite; } real TCespite::percentuale_deducibilita() const { real percento; const int uso_promiscuo = get_int(CESPI_USOPROM); switch (uso_promiscuo) { case 2: // Beni in uso promiscuo percento = 50; if (ditta_cespiti().legge_223_06()) // Ormai sempre false { if (auto_o_moto()) // Automobili, motocicli e ciclomotori { if (ditta_cespiti().professionista()) percento = 25; else percento = ZERO; } } break; case 3: percento = 80; break; // Agenti/rappresentanti case 4: percento = 40; break; // Uso promiscuo a dipententi case 5: percento = 90; break; // Fringe benefit case 6: percento = 80; break; // Cellulari case 7: percento = 20; break; // Uso promiscuo 2013 case 8: percento = 70; break; // Uso promiscuo 2013 default: percento = CENTO; break; // Beni strumentali al 100% } return percento; } // Calcola spese manutenzione da scrivere su SALPRO // Certified 75% real TCespite::calcola_spese_manutenzione(const real& valamm) { const TDitta_cespiti& cce = ditta_cespiti(); real vspmanu = valamm; if (!cce.esercizio_costituzione()) { const real limite = get_limit(); // se limite < 0 significa infinito if (limite > ZERO && vspmanu > limite) vspmanu = limite; vspmanu *= cce.coefficiente_durata_esercizio(); } const real perded = percentuale_deducibilita(); if (perded < CENTO) vspmanu = vspmanu * perded / CENTO; // Non arrotondare qui! Altrove serve così com'è return vspmanu; } void TCespite::prepara_saldi(bool is_valid) { log("- Preparazione saldi tipo %d", _tipo_sit); const TDitta_cespiti& cce = ditta_cespiti(); TDate inies, fines; const int esercizio = cce.esercizio_corrente(inies, fines); read_sal(esercizio); if (is_valid) { const int tpspeman = get_int(CESPI_TPSPEMAN); if ((tpspeman == 2 || tpspeman == 3) && inies.year() > cce.anno_tuir()) { const real valamm = val_amm(); real vspmanu = calcola_spese_manutenzione(valamm); cce.arrotonda(vspmanu); _salpro.put(SALCE_VSPMANU, vspmanu); } } else { _salpro.zero(SALCE_VSPMANU); } save_sal(); } // Incrementa il campo fdst del record dst col campo fsrc del record src in base al segno specificato // Certified 100% void TCespite::incr_field(TRectype& dst, const char* fdst, const TRectype& src, const char* fsrc, char segno) const { const real num = src.get_real(fsrc); if (!num.is_zero()) { real val = dst.get_real(fdst); if (segno == '-') val -= num; else val += num; dst.put(fdst, val); } } void TCespite::decr_field(TRectype& dst, const char* fdst, const TRectype& src, const char* fsrc, char segno) const { incr_field(dst, fdst, src, fsrc, segno == '+' ? '-' : '+'); } // Applica tutte le rettifice al movimento tmv // Certified 50% void TCespite::applica_rettifiche(TRectype& tmv, TRectype& tmvam) { TRelation rel(LF_MOVCE); TString expr; expr << "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==\"" << _tipo_sit << '"'; rel.add(LF_MOVAM, expr); const TString16 id = get(CESPI_IDCESPITE); // Il cursore delle rettifiche usa la chiave 2: IDCESPITE+IDMOV // Per cui parto a selezionare le possibili rettifiche dal movimento da rettificare ... TRectype fromret(LF_MOVCE); fromret.put(MOVCE_IDCESPITE, id); fromret.put(MOVCE_IDMOV, tmv.get(MOVCE_IDMOV)); // ... in poi TRectype toret(LF_MOVCE); toret.put(MOVCE_IDCESPITE, id); TString filtro; filtro << MOVCE_IDRET << "==\"" << tmv.get(MOVCE_IDMOV) << "\""; // Confronto alfabetico! TCursor movcur(&rel, filtro, 2, &fromret, &toret); const long items = movcur.items(); if (items > 0) // Se ci sono rettifiche { log("- Applicazione %ld rettifiche al movimento %s", items, (const char*)tmv.get(MOVCE_IDMOV)); movcur.freeze(); const char segno_mov = tmv.get_char(MOVCE_SEGNO); for (movcur = 0L; movcur.pos() < items; ++movcur) { test_rip(rel); // Testa la necessità di eventuali ripartizioni TRectype& movret = rel.curr(); const char segno_ret = movret.get_char(MOVCE_SEGNO); const char segno = segno_mov == segno_ret ? '+' : '-'; incr_field(tmv, MOVCE_NUMELE, movret, MOVCE_NUMELE, segno); incr_field(tmv, MOVCE_CSTO, movret, MOVCE_CSTO, segno); incr_field(tmv, MOVCE_PLUSREIN, movret, MOVCE_PLUSREIN, segno); incr_field(tmv, MOVCE_RIV75, movret, MOVCE_RIV75, segno); incr_field(tmv, MOVCE_RIV83, movret, MOVCE_RIV83, segno); incr_field(tmv, MOVCE_RIV90, movret, MOVCE_RIV90, segno); incr_field(tmv, MOVCE_RIV91, movret, MOVCE_RIV91, segno); incr_field(tmv, MOVCE_RIVGF, movret, MOVCE_RIVGF, segno); incr_field(tmv, MOVCE_RIVGC, movret, MOVCE_RIVGC, segno); incr_field(tmv, MOVCE_IMPVEN, movret, MOVCE_IMPVEN, segno); incr_field(tmv, MOVCE_VNONAMM, movret, MOVCE_VNONAMM, segno); incr_field(tmv, MOVCE_VNONAMMC, movret, MOVCE_VNONAMMC, segno); incr_field(tmv, MOVCE_VNONAMM06,movret, MOVCE_VNONAMM06,segno); if (rel.is_first_match(LF_MOVAM)) { const TRectype& ammret = rel.curr(LF_MOVAM); incr_field(tmvam, MOVAM_QNOR, ammret, MOVAM_QNOR, segno); incr_field(tmvam, MOVAM_QANT, ammret, MOVAM_QANT, segno); incr_field(tmvam, MOVAM_QACC, ammret, MOVAM_QACC, segno); incr_field(tmvam, MOVAM_QPERSE, ammret, MOVAM_QPERSE, segno); incr_field(tmvam, MOVAM_FPRIVATO, ammret, MOVAM_FPRIVATO, segno); incr_field(tmvam, MOVAM_QPPRIVATE, ammret, MOVAM_QPPRIVATE, segno); } } } } void TCespite::aggiorna_salpro(const TRectype& tmv, const TRectype& tmvam, char segno) { log(TR("= Aggiornamento saldi ed ammortamenti progressivi")); incr_field(_salpro, SALCE_NUMELE, tmv, MOVCE_NUMELE, segno); incr_field(_salpro, SALCE_CSTO, tmv, MOVCE_CSTO, segno); incr_field(_salpro, SALCE_PLUSREIN, tmv, MOVCE_PLUSREIN, segno); incr_field(_salpro, SALCE_RIV75, tmv, MOVCE_RIV75, segno); incr_field(_salpro, SALCE_RIV83, tmv, MOVCE_RIV83, segno); incr_field(_salpro, SALCE_RIV90, tmv, MOVCE_RIV90, segno); incr_field(_salpro, SALCE_RIV91, tmv, MOVCE_RIV91, segno); incr_field(_salpro, SALCE_RIVGF, tmv, MOVCE_RIVGF, segno); incr_field(_salpro, SALCE_RIVGC, tmv, MOVCE_RIVGC, segno); incr_field(_salpro, SALCE_VNONAMM, tmv, MOVCE_VNONAMM, segno); incr_field(_salpro, SALCE_VSPMANU, tmv, "VSPMANU", segno); // Campo virtuale su tmv! // Nuova gestione fabbricati Legge 223/06 incr_field(_salpro, SALCE_VNONAMM06, tmv, MOVCE_VNONAMM06, segno); incr_field(_salpro, SALCE_VNONAMMC, tmv, MOVCE_VNONAMMC, segno); save_sal(); incr_field(_ammpro, AMMCE_QNORP, tmvam, MOVAM_QNOR, segno); incr_field(_ammpro, AMMCE_QACCP, tmvam, MOVAM_QACC, segno); incr_field(_ammpro, AMMCE_QANTP, tmvam, MOVAM_QANT, segno); incr_field(_ammpro, AMMCE_QPERSEP, tmvam, MOVAM_QPERSE, segno); incr_field(_ammpro, AMMCE_FPRIVATOP, tmvam, MOVAM_FPRIVATO, segno); incr_field(_ammpro, AMMCE_QPPRIVATEP, tmvam, MOVAM_QPPRIVATE, segno); save_amm(); } // Calcola il valore ammortizzabile del movimento tmv // Certified 50% real TCespite::mov_val_amm(const TRectype& tmv) const { const real riv90 = tmv.get_real(MOVCE_RIV90); const real riv91 = tmv.get_real(MOVCE_RIV91); real val = sum_fields(tmv, MOVCE_CSTO, MOVCE_RIV75, MOVCE_RIV83); val += riv90 + riv91 - tmv.get_real(MOVCE_VNONAMM); const bool leasing = get_bool(CESPI_LEASING); if (_tipo_sit == 1 || leasing) val += tmv.get_real(MOVCE_RIVGF); if (_tipo_sit == 2 && !leasing) val += tmv.get_real(MOVCE_RIVGC); const int anni_post90 = _salini.get_int(SALCE_ANNIPOST90); const int anni_post91 = _salini.get_int(SALCE_ANNIPOST91); if (riv91 == ZERO) { if (anni_post90 < 3) val -= riv90; } else { if (anni_post91 == 0) val -= riv90; } if (anni_post91 == 0) val -= riv91; // Legge 223/06 val -= tmv.get_real(MOVCE_VNONAMM06); if (_tipo_sit == 2) { val += tmv.get_real(MOVCE_VNONAMM); // Recupero VNONAMM fiscale ... val -= tmv.get_real(MOVCE_VNONAMMC); // ... sottraggo il civilistico } return val; } // Calcola il residuo da ammortizzare del movimento tmv // Certified 50% real TCespite::mov_res_amm(const TRectype& tmv, const TRectype& tmvam) const { const real valamm = mov_val_amm(tmv); const real fondam = sum_fields(tmvam, MOVAM_QNOR, MOVAM_QANT, MOVAM_QACC, MOVAM_QPERSE, MOVAM_FPRIVATO, MOVAM_QPPRIVATE); const real resamm = valamm - fondam; return resamm; } // Funzione chiamata da rip_elem e rip_costo // Cerified 90% void TCespite::rip_jolly(TRelation& rel, const real& num, const real& den, int mode) { const TDitta_cespiti& cce = ditta_cespiti(); if (mode & 0x1) { TRectype& movsem = rel.curr(LF_MOVCE); const char* flm[] = { MOVCE_CSTO, MOVCE_PLUSREIN, MOVCE_RIV75, MOVCE_RIV83, MOVCE_RIV90, MOVCE_RIV91, MOVCE_RIVGF, MOVCE_RIVGC, MOVCE_VNONAMM, MOVCE_VNONAMMC, MOVCE_VNONAMM06, NULL }; for (int i = 0; flm[i]; i++) { real n = _salpro.get_real(flm[i]); if (!n.is_zero() && num != den) { n = n * num / den; cce.arrotonda(n); } movsem.put(flm[i], n); } if (!_in_memory) rel.lfile(LF_MOVCE).rewrite(); } if (mode & 0x2) { TRectype& movam = rel.curr(LF_MOVAM); const char* fla[] = { MOVAM_QNOR, MOVAM_QANT, MOVAM_QACC, MOVAM_QPERSE, MOVAM_FPRIVATO, MOVAM_QPPRIVATE, NULL }; TString16 afl; for (int i = 0; fla[i]; i++) { afl = fla[i]; afl << 'P'; real n = _ammpro.get_real(afl); if (!n.is_zero() && num != den) { n = n * num / den; cce.arrotonda(n); } movam.put(fla[i], n); } if (!_in_memory) rel.lfile(LF_MOVAM).rewrite(); } } // Riproporzionare importi a partire dal numero di elementi // Certified 100% void TCespite::rip_elem(TRelation& rel, int mode) { log(TR("# Ripartizionamento importi in base agli elementi")); const real den = _salpro.get_real(SALCE_NUMELE); if (den > ZERO) { const real num = rel.curr(LF_MOVCE).get_real(MOVCE_NUMELE); rip_jolly(rel, num, den, mode); } else log(FR("! - Numero elementi non valido: %s"), den.string()); } // Riproporzionare importi a partire dal costo storico // Certified 100% void TCespite::rip_costo(TRelation& rel, int mode) { log(TR("# Ripartizionamento importi in base al costo storico")); const real den = _salpro.get_real(SALCE_CSTO); if (den > ZERO) { const real num = rel.curr(LF_MOVCE).get_real(MOVCE_CSTO); rip_jolly(rel, num, den, mode); } else log(FR("! - Costo non valido: %s"), den.string()); } // Testa la necessità di eventuali ripartizioni int TCespite::test_rip(TRelation& rel) { int rip_flag = 0x0; if (_salpro.get_long(SALCE_NUMELE) == 0L || _salpro.get_real(SALCE_CSTO).is_zero()) return rip_flag; const TRectype& movsem = rel.curr(); // Considera solo eliminazioni che SPESSO hanno segno '-' ma non sempre: prima testava solo segno - const TString4 tpmov = movsem.get(MOVCE_CODMOV); const TRectype& tmc = cache().get("%TMC", tpmov); if (tmc.get_char("S6") != 'E') return rip_flag; const TRectype& movam = rel.curr(LF_MOVAM); bool null_movam = null_fields(movam, MOVAM_QNOR, MOVAM_QANT, MOVAM_QACC, MOVAM_QPERSE, MOVAM_QPPRIVATE, MOVAM_FPRIVATO); if (null_movam) rip_flag |= 0x1; // Determina se considerare le rivalutazioni fiscali o civilistiche const bool leasing = get_bool(CESPI_LEASING); const char* riv_gen_fc = NULL; if (_tipo_sit==1 || leasing) riv_gen_fc = MOVCE_RIVGF; else if (_tipo_sit==2 && !leasing) riv_gen_fc = MOVCE_RIVGC; bool null_movce = null_fields(movsem, MOVCE_PLUSREIN, MOVCE_RIV75, MOVCE_RIV83, MOVCE_RIV90, MOVCE_RIV91, MOVCE_VNONAMM, MOVCE_VNONAMMC, MOVCE_VNONAMM06, riv_gen_fc); if (null_movce) rip_flag |= 0x2; if (rip_flag != 0) { if (movsem.get_real(MOVCE_CSTO).is_zero()) rip_elem(rel, rip_flag); else rip_costo(rel, rip_flag); } return rip_flag; } // Calcola una quota di ammortamento: semplicemente moltiplica il valore ammortizzabile // per una percentuale ed ottiene la quota. // Se questa supera il residuo da ammortizzare allora pone la quota uguale al residuo e // ricalcola la percentuale effettiva real TCespite::calc_quota(const real& valamm, const real& perric, const real& residuo, real& pereff, TRelation* mov /* =NULL */) { // Caso anomalo di percentuale o valore nulli if (perric <= ZERO || valamm <= ZERO) { pereff = ZERO; return ZERO; } // Caso normale real quota = valamm * perric / CENTO; pereff = perric; const TDitta_cespiti& cce = ditta_cespiti(); if (mov != NULL && cce.ragguaglio_ammortamenti_parti_vendute()) { TRectype& ammmv = mov->curr(LF_AMMMV); if (!ammmv.get_bool(AMMMV_FZQUO) && !ammmv.get_bool(AMMMV_FZPER)) { TDate inies, fines; cce.esercizio_corrente(inies, fines); const TDate dtmov = mov->curr(LF_MOVCE).get_date(MOVCE_DTMOV); const TDate dtcomp = get_date(CESPI_DTCOMP); const long giorni_possesso = dtmov - fnc_max(inies, dtcomp) + 1; const long giorni_esercizio = fines - inies + 1; quota = quota * giorni_possesso / giorni_esercizio; TString256 note; note.format( FR("Ammortamenti ragguagliati a %d giorni di possesso su %d d'esercizio"), giorni_possesso, giorni_esercizio); ammmv.put(AMMMV_NOTE, note); } else ammmv.zero(AMMMV_NOTE); // nessuna nota da registrare } const real coeff_durata = cce.coefficiente_durata_esercizio(); quota *= coeff_durata; cce.arrotonda(quota); if (quota > residuo) quota = residuo; pereff = (quota * CENTO) / (coeff_durata * valamm); return quota; } // Calcolo delle quote perse // Certified 50% real TCespite::calc_quote_perse(const real& valamm, const real& peric, const real& residuo, const real& quotamm, bool mov_vend, const TDate& dtmov) { const TDitta_cespiti& cce = ditta_cespiti(); const real coeff_durata = cce.coefficiente_durata_esercizio(); real quota = valamm * coeff_durata * peric / CENTO; if (mov_vend) { TDate inies, fines; cce.esercizio_corrente(inies, fines); const TDate dtcomp = get_date(CESPI_DTCOMP); const real giorni_possesso = dtmov - fnc_max(inies, dtcomp) + 1; const real giorni_esercizio = fines - inies + 1; quota = quota * giorni_possesso / giorni_esercizio; } cce.arrotonda(quota); if (quota < residuo) { const bool amm_rit = ammini_get_bool(AMMCE_AMMRIT); if (quota > quotamm && !amm_rit) quota -= quotamm; else quota = ZERO; } else quota = ZERO; return quota; } void TCespite::agg_quota(const real& movvalamm, TRectype& rec, const char* field, bool calcq) { const real percento = percentuale_deducibilita(); if (percento < CENTO) { const real mva = (rec.num() == LF_AMMMV) ? movvalamm : val_amm(); real clim = mva; if (auto_o_moto()) // Auto, motociclo, ciclomotore { clim = get_limit(); if (clim < ZERO || mva < clim) clim = mva; } const TDitta_cespiti& cce = ditta_cespiti(); const real quotat = rec.get_real(field); const real limcsto = clim / mva; real campo = quotat * limcsto * percento / CENTO; cce.arrotonda(campo); rec.put(field, campo); if (strcmp(field, "QNOR") == 0) rec.put("FPRIVATO", quotat - campo); else rec.put("FPRIVATO", rec.get_real("FPRIVATO") + quotat - campo); if (calcq) { const real quotap = rec.get_real("QPERSE"); real qp = quotap * limcsto * percento / CENTO; cce.arrotonda(qp); rec.put("QPERSE", qp); rec.put("QPPRIVATE", quotap - qp); } } } HIDDEN const TString& catdi_get(const TRectype* pcatdi, const char* name, int sit) { if (pcatdi != NULL) { if (sit != 1) { TString16 fname(name); fname.overwrite("PC", 0); return pcatdi->get(fname); } return pcatdi->get(name); } else CHECK(false, "NULL CATDI record"); return EMPTY_STRING; } // Non sempre basta prendere un campo da AMMINI così com'è: // in base al campo SCELTE esistono campi speciali da prelevare dalle categorie // con le seguenti "semplici" modalità const TString& TCespite::ammini_get(const char* pstar) const { TString16 val = _ammini.get(pstar); TToken_string special = "AMMRIT|CSCEN|PNOR|PACC|PANT"; const int fld = special.get_pos(pstar); if (fld >= 0) // Should ALWAYS happen: tuttavia non è affatto grave! { const TDitta_cespiti& dc = ditta_cespiti(); const TRectype* pcatdi = NULL; const TRectype* pcac = NULL; // L'utente fa le sue scelte: ma saranno sensate e coerenti? int scelte = _ammini.get_int(AMMCE_SCELTE); if (scelte != 1) // Cerco se esiste un record appropriato su CATDI { const int anno = dc.esercizio_corrente(); const int gruppo = get_int(CESPI_CODCGRA); const TString4 specie = get(CESPI_CODSPA); const int categ = get_int(CESPI_CODCAT); TString80 key; key.format("%d|%d|%s|%d", anno, gruppo, (const char*)specie, categ); const TRectype& catdi = cache().get(LF_CATDI, key); if (!catdi.empty()) { pcatdi = &catdi; scelte = 2; } else scelte = 0; // Non trovato: riprova con CAC } if (scelte == 0) // Cerco se esiste un record appropriato su CAC { const TRectype& cac = categoria(); if (!cac.empty()) pcac = &cac; else scelte = 1; // Non trovato: usa direttamente AMMCE } if (scelte != 1) // L'utente non ha fatto una esplicita scelta per cespite! { const TTipo_cespite tc = tipo(); switch (fld) { case 0: // AMMRIT case 1: // CSCEN if (tc == tc_materiale && scelte == 2) val = pcatdi->get(pstar); break; case 2: // PNOR switch (tc) { case tc_materiale: { TDate dtfunz = get_date(CESPI_DTFUNZ); if (!dtfunz.ok()) { TDate dtdummy; dc.esercizio_corrente(dtfunz, dtdummy); } const int anno_funz = dtfunz.year(); if (scelte == 2) { if (anno_funz < 1988) val = catdi_get(pcatdi, CATDI_PFNORVN, _tipo_sit); else val = catdi_get(pcatdi, anno_funz < 1989 ? CATDI_PFNORVT : CATDI_PFNORNT, _tipo_sit); } else val = pcac->get(anno_funz < 1989 ? "R12" : "R11"); } break; case tc_immateriale: if (scelte == 2) val = catdi_get(pcatdi, CATDI_PFNORVN, _tipo_sit); else val = pcac->get("R13"); break; case tc_pluriennale: if (scelte == 2) val = catdi_get(pcatdi, CATDI_PFNORVN, _tipo_sit); else val = pcac->get("R15"); break; default: break; } break; case 3: // PACC if (tc == tc_materiale && scelte == 2) val = catdi_get(pcatdi, CATDI_PFACC, _tipo_sit); break; case 4: // PANT if (tc == tc_materiale && scelte == 2) { TDate dtfunz = get_date(CESPI_DTFUNZ); if (!dtfunz.ok()) { TDate dtdummy; dc.esercizio_corrente(dtfunz, dtdummy); } const int anno_funz = dtfunz.year(); if (anno_funz < 1988) val = catdi_get(pcatdi, CATDI_PFANTVN, _tipo_sit); else val = catdi_get(pcatdi, anno_funz < 1989 ? CATDI_PFANTVT : CATDI_PFANTNT, _tipo_sit); } break; default: CHECKS(0, "Unknown special field ", pstar); break; } } } return get_tmp_string() = val; } bool TCespite::ammini_get_bool(const char* pfield) const { const TString& val = ammini_get(pfield); return val.full(); } real TCespite::ammini_get_real(const char* pfield) const { const real val = ammini_get(pfield); return val; } void TCespite::ammpro_put_perc(const char* pfield, const real& p) { real perc = p; perc.round(3); _ammpro.put(pfield, perc); } void TCespite::calc_perc(TRelation& rel, const TRectype& tmv, const TRectype& tmvam) { const TDitta_cespiti& cce = ditta_cespiti(); const real coeff = cce.coefficiente_durata_esercizio(); TRectype& ammmv = rel.curr(LF_AMMMV); if (ammmv.get_bool(AMMMV_FZQUO)) // Forzatura per quote { // Leggo comunque le percentuali teoriche ammmv.put(AMMMV_PNOR, ammini_get(AMMCE_PNOR)); ammmv.put(AMMMV_PACC, ammini_get(AMMCE_PACC)); ammmv.put(AMMMV_PANT, ammini_get(AMMCE_PANT)); real resamm = mov_res_amm(tmv, tmvam) - ammmv.get_real(AMMMV_FPRIVATO); if (resamm > ZERO) { real penor; if (resamm < ammmv.get_real(AMMMV_QNOR)) { ammmv.put(AMMMV_QNOR, resamm); penor = resamm / coeff * CENTO / mov_val_amm(tmv); } else //caso per le forzature { penor = ammmv.get_real(AMMMV_QNOR) / coeff * CENTO / mov_val_amm(tmv); } ammmv.put(AMMMV_PENOR, penor); ammmv.put(AMMMV_PNOR, penor); // Per chiarezza di stampa resamm -= ammmv.get_real(AMMMV_QNOR); if (resamm > ZERO) { real peacc; if (resamm < ammmv.get_real(AMMMV_QACC)) { ammmv.put(AMMMV_QACC, resamm); peacc = resamm / coeff * CENTO / mov_val_amm(tmv); } else { peacc = ammmv.get_real(AMMMV_QACC) / coeff * CENTO / mov_val_amm(tmv); } ammmv.put(AMMMV_PEACC, peacc); ammmv.put(AMMMV_PACC, peacc); // Per chiarezza di stampa resamm -= ammmv.get_real(AMMMV_QACC); } else zero_fields(ammmv, AMMMV_QANT, AMMMV_PEANT, AMMMV_QACC, AMMMV_PEACC, NULL); // Controllo se residuo a zero per finire if (resamm > ZERO) { real peant; // Controllo se forzato anche quota anticipato if (resamm < ammmv.get_real(AMMMV_QANT)) { ammmv.put(AMMMV_QANT, resamm); peant = resamm / coeff * CENTO / mov_val_amm(tmv); } else { peant = ammmv.get_real(AMMMV_QANT) / coeff * CENTO / mov_val_amm(tmv); } ammmv.put(AMMMV_PEANT, peant); ammmv.put(AMMMV_PANT, peant); // Per chiarezza di stampa } else { ammmv.zero(AMMMV_QANT); ammmv.zero(AMMMV_PEANT); } } else { zero_fields(ammmv, AMMMV_QNOR, AMMMV_PENOR, AMMMV_QANT, AMMMV_PEANT, AMMMV_QACC, AMMMV_PEACC, NULL); } } else if (ammmv.get_bool(AMMMV_FZPER)) // Forzatura percentuali { ammmv.put(AMMMV_PENOR, ammmv.get(AMMMV_PNOR)); ammmv.put(AMMMV_PEANT, ammmv.get(AMMMV_PANT)); ammmv.put(AMMMV_PEACC, ammmv.get(AMMMV_PACC)); real resamm = mov_res_amm(tmv, tmvam) - ammmv.get_real(AMMMV_FPRIVATO); if (resamm > ZERO) { const real penor = ammmv.get_real(AMMMV_PENOR); real per_eff; const real qnor = calc_quota(mov_val_amm(tmv), penor, resamm, per_eff, &rel); ammmv.put(AMMMV_QNOR, qnor); ammmv.put(AMMMV_PENOR, per_eff); resamm -= qnor; const real peacc = ammmv.get_real(AMMMV_PEACC); if (resamm > ZERO && peacc > ZERO) { const real qacc = calc_quota(mov_val_amm(tmv), peacc, resamm, per_eff, &rel); ammmv.put(AMMMV_QACC, qacc); ammmv.put(AMMMV_PEACC, per_eff); resamm -= qacc; } const real peant = ammmv.get_real(AMMMV_PEANT); if (resamm > ZERO && peant > ZERO) { const real qant = calc_quota(mov_val_amm(tmv), peant, resamm, per_eff, &rel); ammmv.put(AMMMV_QANT, qant); ammmv.put(AMMMV_PANT, per_eff); } } else { zero_fields(ammmv, AMMMV_QNOR, AMMMV_PENOR, AMMMV_QANT, AMMMV_PEANT, AMMMV_QACC, AMMMV_PEACC, NULL); } } else // Nessuna forzatura { // Leggo percentuali teoriche da ammini ammmv.put(AMMMV_PNOR, ammini_get(AMMCE_PNOR)); ammmv.put(AMMMV_PANT, ammini_get(AMMCE_PANT)); ammmv.put(AMMMV_PACC, ammini_get(AMMCE_PACC)); ammmv.put(AMMMV_PENOR, ammmv.get(AMMMV_PNOR)); ammmv.put(AMMMV_PEANT, ammmv.get(AMMMV_PANT)); ammmv.put(AMMMV_PEACC, ammmv.get(AMMMV_PACC)); if (_salini.get_int(SALCE_ANNIAMM) == 0 && tipo() == tc_materiale && !cce.professionista()) { real mva1 = mov_val_amm(tmv); // Valore ammortizzabile di un singolo elemento if (mva1 > ZERO) { const real numele = _salpro.get_real(SALCE_NUMELE)+tmv.get_real(MOVCE_NUMELE); if (numele > ZERO) mva1 /= numele; } if (ammini_get_bool(AMMCE_CSCEN) && mva1 < un_milione()) { ammmv.put(AMMMV_PENOR, CENTO); ammmv.zero(AMMMV_PEANT); ammmv.zero(AMMMV_PEACC); } else { const TDate dtmov = tmv.get_date(MOVCE_DTMOV); if (!cce.primo_ammortamento_100(dtmov, ammmv.get_int(AMMMV_TPAMM), auto_o_moto())) { ammmv.put(AMMMV_PENOR, ammmv.get_real(AMMMV_PNOR)/2.0); ammmv.put(AMMMV_PEANT, ammmv.get_real(AMMMV_PANT)/2.0); ammmv.put(AMMMV_PEACC, ammmv.get_real(AMMMV_PACC)/2.0); } } } real resamm = mov_res_amm(tmv, tmvam); if (resamm > ZERO) { // Calcolare quota ammortamento normale const real valamm = mov_val_amm(tmv); const real penor = ammmv.get_real(AMMMV_PENOR); // Attenzione: usare PENOR, non PNOR! real per_eff; const real qnor = calc_quota(valamm, penor, resamm, per_eff, &rel); ammmv.put(AMMMV_QNOR, qnor); ammmv.put(AMMMV_PENOR, per_eff); // Calcolare quote perse const TDate dtmov = tmv.get_date(MOVCE_DTMOV); const real quote_perse = calc_quote_perse(valamm, per_eff, resamm, qnor, true, dtmov); if (_tipo_sit == 1 && get_int(CESPI_USOPROM) > 1) agg_quota(valamm, ammmv, "QNOR", true); else { ammmv.zero(AMMMV_FPRIVATO); ammmv.zero(AMMMV_QPPRIVATE); } // Togliere FPRIVATO solo ora, in quanto ricalcolato da calc_quota resamm -= ammmv.get_real(AMMMV_QNOR) + ammmv.get_real(AMMMV_FPRIVATO); // Calcolare quota ammortamento accelerato if (resamm > ZERO && ammmv.get_real(AMMMV_PEACC) > ZERO && ammmv.get_real(AMMMV_QPERSE) == ZERO) { const real peacc = ammmv.get_real(AMMMV_PEACC); const real qacc = calc_quota(valamm, peacc, resamm, per_eff, &rel); ammmv.put(AMMMV_QACC, qacc); ammmv.put(AMMMV_PEACC, per_eff); if (_tipo_sit == 1 && get_int(CESPI_USOPROM) > 1) agg_quota(valamm, ammmv, "QACC", false); else ammmv.zero(AMMMV_FPRIVATO); } else { ammmv.zero(AMMMV_QACC); ammmv.zero(AMMMV_PEACC); } // Calcolare quota ammortamento anticipato resamm -= ammmv.get_real(AMMMV_QACC); if (tipo() == tc_materiale && _salini.get_int(SALCE_ANNIAMM) <= 2) { const real peant = ammmv.get_real(AMMMV_PEANT); if (resamm > ZERO && peant > ZERO && ammmv.get_real(AMMMV_QPERSE) == ZERO) { const real qant = calc_quota(valamm, peant, resamm, per_eff, &rel); ammmv.put(AMMMV_QANT, qant); ammmv.put(AMMMV_PEANT, per_eff); if (_tipo_sit == 1 && get_int(CESPI_USOPROM) > 1) agg_quota(valamm, ammmv, "QANT", false); else ammmv.zero(AMMMV_FPRIVATO); } else { ammmv.zero(AMMMV_QANT); ammmv.zero(AMMMV_PEANT); } } } else { zero_fields(ammmv, AMMMV_QNOR, AMMMV_PENOR, AMMMV_QANT, AMMMV_PEANT, AMMMV_QACC, AMMMV_PEACC, AMMMV_FPRIVATO, AMMMV_QPERSE, AMMMV_QPPRIVATE, NULL); } } } // Calcolo ammortamento per quote // Certified 99% void TCespite::calc_anni(TRectype& ammmv, const TRectype& tmv, const TRectype& tmvam) { const int anniamm = _salini.get_int(SALCE_ANNIAMM); const int anniric = get_int(CESPI_ANNIRIC); if (anniamm >= anniric) { ammmv.zero(AMMMV_QNOR); return; } const TTipo_cespite tc = tipo(); const int vincolo = get_int(CESPI_VINCOLO); if ((tc == tc_pluriennale && vincolo == 2) || (tc == tc_immateriale && anniric > 0) || (tc == tc_materiale && anniric > 0)) { const real qnor = mov_res_amm(tmv, tmvam) / (anniric - anniamm); ammmv.put(AMMMV_QNOR, qnor); } else if (tc == tc_immateriale && vincolo == 3) { const real qnor = mov_val_amm(tmv) / anniric; ammmv.put(AMMMV_QNOR, qnor); } const real resamm = mov_res_amm(tmv, tmvam); real qnor = ammmv.get_real(AMMMV_QNOR); if (resamm < qnor) { qnor = resamm; ammmv.put(AMMMV_QNOR, qnor); } const real penor = qnor * CENTO / mov_val_amm(tmv); ammmv.put(AMMMV_PENOR, penor); } void TCespite::amm_mov_ven(TRelation& rel, const TRectype& tmv, const TRectype& tmvam) { const TTipo_cespite tc = tipo(); const bool leasing = get_bool(CESPI_LEASING); const int anniric = get_int(CESPI_ANNIRIC); if ((tc == tc_materiale && !leasing) || (tc == tc_immateriale && anniric == 0)) calc_perc(rel, tmv, tmvam); else calc_anni(rel.curr(LF_AMMMV), tmv, tmvam); } real TCespite::mov_r90_escl_ven(const TRectype& tmv) { real val; if (tmv.get_real(MOVCE_RIV91).is_zero()) { if (_salini.get_int(SALCE_ANNIPOST90) < 3) val = tmv.get_real(MOVCE_RIV90); } else { if (_salini.get_int(SALCE_ANNIPOST91) < 3) val = tmv.get_real(MOVCE_RIV90); } return val; } real TCespite::mov_r91_escl_ven(const TRectype& tmv) { real val; if (_salini.get_int(SALCE_ANNIPOST91) == 0) val = tmv.get_real(MOVCE_RIV91); return val; } real TCespite::mov_val_ven(const TRectype& tmv) { real val = sum_fields(tmv, MOVCE_CSTO, MOVCE_RIV75, MOVCE_RIV83, MOVCE_RIV90, MOVCE_RIV91); val -= tmv.get_real(MOVCE_PLUSREIN); const bool leasing = get_bool(CESPI_LEASING); if (_tipo_sit == 1 || leasing) val += tmv.get_real(SALCE_RIVGF); else if (_tipo_sit == 2 && !leasing) val += tmv.get_real(SALCE_RIVGC); val -= mov_r90_escl_ven(tmv); val -= mov_r91_escl_ven(tmv); return val; } // Calcolo plusvalenza o minusvalenza void TCespite::cal_valenza(const TRectype& tmv, const TRectype& tmvam, TRectype& ammmv) { const real fondo = sum_fields(ammmv, AMMMV_QNOR, AMMMV_QACC, AMMMV_QANT) + sum_fields(tmvam, MOVAM_QNOR, MOVAM_QACC, MOVAM_QANT); const real privato = ammmv.get_real(AMMMV_FPRIVATO) + tmvam.get_real(MOVAM_FPRIVATO); const real totfondo = fondo + privato; real ratio; if (!privato.is_zero() && !totfondo.is_zero()) ratio = privato / totfondo; real resparven = mov_val_ven(tmv) - totfondo; if (resparven < ZERO && (mov_r90_escl_ven(tmv) != ZERO || mov_r91_escl_ven(tmv) != ZERO)) resparven = ZERO; const real prezzo = tmv.get_real(MOVCE_IMPVEN); real plusminus = prezzo - resparven; if (ratio > ZERO) { const TDitta_cespiti& dc = ditta_cespiti(); plusminus *= ratio; dc.arrotonda(plusminus); } ammmv.put(AMMMV_PLUS, plusminus > ZERO ? plusminus : ZERO); ammmv.put(AMMMV_MINUS, plusminus < ZERO ? -plusminus : ZERO); } void TCespite::elabora_mov_neg(TRelation& rel, TRectype& tmv, TRectype& tmvam) { log(TR("= Elaborazione movimento con segno -")); const TString4 tpmov = tmv.get(MOVCE_CODMOV); // Tipo movimento da non confondere col tipo documento! const TRectype& tmc = cache().get("%TMC", tpmov); TRectype& ammmv = rel.curr(LF_AMMMV); bool apv = false; // Ho calcolato l'ammortamente del venduto sul movimento? if (ditta_cespiti().ammortamento_parti_vendute()) { if (tmc.get_bool("B4")) // Possibile ammortamento su movimento { amm_mov_ven(rel, tmv, tmvam); apv = true; // Si, ho calcolato } } if (!apv) // Se non ho calcolato allora azzero zero_fields(ammmv, AMMMV_PNOR, AMMMV_PACC, AMMMV_PANT, AMMMV_QNOR, AMMMV_QACC, AMMMV_QANT, AMMMV_QPERSE, AMMMV_FPRIVATO, AMMMV_QPPRIVATE, NULL); const bool cpm = tmc.get_bool("B5"); if (cpm) // Calcolo plus/minus valenza cal_valenza(tmv, tmvam, ammmv); if (!_in_memory) rel.lfile(LF_AMMMV).rewrite(); else //se e' _in_memory deve aggiornare il record _ammmv che sara' passato al programma di collegamento... //..cespiti con contabilita' { if (apv || cpm) { _movce.add(tmv); _movam.add(tmvam); _ammmv.add(ammmv); } } } // Scandisce tutti i movimenti del cespite fino alla data_limite void TCespite::scansione_movimenti(const TDate& data_limite, bool is_valid) { log(TR("- Scansione movimenti")); TDitta_cespiti& cce = ditta_cespiti(); TDate inies, fines; cce.esercizio_corrente(inies, fines); TRelation rel(LF_MOVCE); TRectype& movsem = rel.curr(); const TString16 idcespite = get(CESPI_IDCESPITE); movsem.put(MOVCE_IDCESPITE, idcespite); TString filtro; filtro << "(IDRET==\"\")&&(ANSI(DTMOV)>=\"" << inies.date2ansi() << "\")"; if (data_limite.ok()) filtro << "&&(ANSI(DTMOV)<=\"" << data_limite.date2ansi() << "\")"; TCursor cur(&rel, filtro, 2, &movsem, &movsem); const long items = cur.items(); if (items > 0) // Continua solo se esistono movimenti { cur.freeze(); // Aggiungo astutamente solo ora i file alla relazione TString expr; expr << "IDCESPITE==IDCESPITE|IDMOV==IDMOV|TPAMM==\"" << _tipo_sit << '"'; rel.add(LF_MOVAM, expr); rel.add(LF_AMMMV, expr); TRectype& movam = rel.curr(LF_MOVAM); TRectype& ammmv = rel.curr(LF_AMMMV); // Creo record campione per totale movimento + relative rettifiche TVariable_rectype tmv(LF_MOVCE); tmv.add_field(new TVariable_field("VSPMANU")); // Totali ammortamenti: praticamente trattasi di estensione del record tmv TRectype tmvam(LF_MOVAM); for (cur = 0L; cur.pos() < items; ++cur) { log("= Lettura movimento %s", (const char*)movsem.get(MOVCE_IDMOV)); if (!rel.is_first_match(LF_MOVAM)) { movam.zero(); movam.put(MOVAM_IDCESPITE, idcespite); movam.put(MOVAM_IDMOV, movsem.get(MOVCE_IDMOV)); movam.put(MOVAM_TPAMM, _tipo_sit); rel.lfile(LF_MOVAM).write(); } test_rip(rel); // Testa la necessità di eventuali ripartizioni su movsem e/o movam tmv = movsem; tmvam = movam; applica_rettifiche(tmv, tmvam); const char segno = movsem.get_char(MOVCE_SEGNO); if (segno == '-' && is_valid) { if (!rel.is_first_match(LF_AMMMV)) // Crea ammmv se necessario { ammmv.zero(); ammmv.put(AMMMV_IDCESPITE, movsem.get(MOVCE_IDCESPITE)); ammmv.put(AMMMV_IDMOV, movsem.get(MOVCE_IDMOV)); ammmv.put(AMMMV_TPAMM, _tipo_sit); rel.lfile(LF_AMMMV).write(); } elabora_mov_neg(rel, tmv, tmvam); } if (is_valid) { if (inies.year() > cce.anno_tuir()) // Controllo praticamente obsoleto (sempre vero) { const int tpspeman = get_int(CESPI_TPSPEMAN); if ((tpspeman == 2 || tpspeman == 3) || (tpspeman == 4 && cce.esente_art14())) { const real valamm = mov_val_amm(tmv); real vspmanu = calcola_spese_manutenzione(valamm); if (!vspmanu.is_zero()) { const TDate dtmov = movsem.get_date(MOVCE_DTMOV); // ??? const real giorni_residui = fines - dtmov + (segno=='-' ? 0 : 1); const real giorni_esercizio = fines - inies + 1; vspmanu = vspmanu * giorni_residui / giorni_esercizio; cce.arrotonda(vspmanu); } tmv.put("VSPMANU", vspmanu); } } } else { tmv.zero("VSPMANU"); } aggiorna_salpro(tmv, tmvam, segno); } } // If esistono movimenti } bool TCespite::controllo_fringe_benefit() { real fringe_benefit = ammini_get_real(AMMCE_FRINGEBEN); if (fringe_benefit <= ZERO) return false; // Niente fringe benefit: inutile continuare! const TDitta_cespiti& dc = ditta_cespiti(); // SOLO situazione fiscale di veicoli in uso a dipendenti dal 2006 if (_tipo_sit != 1 || !get_bool(CESPI_VEIDIP) || !auto_o_moto() || !dc.legge_223_06()) return false; fringe_benefit *= dc.coefficiente_durata_esercizio(); dc.arrotonda(fringe_benefit); const real quote = sum_fields(_ammpro, AMMCE_QNOR, AMMCE_QACC, AMMCE_QANT); if (quote > fringe_benefit) { log(TR("- Aggiornamento quote in base al fringe benefit")); const char* const qfld[3] = { AMMCE_QNOR, AMMCE_QACC, AMMCE_QANT }; const char* const pfld[3] = { AMMCE_PNOR, AMMCE_PACC, AMMCE_PANT }; real sforamento = quote - fringe_benefit; _ammpro.add(AMMCE_QPERSE, sforamento); // Incremento le quote perse for (int i = 2; i >= 0 && sforamento > ZERO; i--) { const real old_quota = _ammpro.get_real(qfld[i]); if (old_quota > ZERO) // C'e' trippa per gatti in questa quota? { real new_quota; // Nuova quota ridotta per coprire lo sforamento if (old_quota >= sforamento) { new_quota = old_quota - sforamento; sforamento = ZERO; } else { new_quota = ZERO; sforamento -= old_quota; } _ammpro.put(qfld[i], new_quota); // Aggiorno la quota // Ricalcolo anche la percentuale di conseguenza const real old_perc = _ammpro.get_real(pfld[i]); const real new_perc = old_perc * new_quota / old_quota; ammpro_put_perc(pfld[i], new_perc); } } } return true; } void TCespite::calc_amm_residui(bool is_valid) { log("- Calcolo ammortamenti residui"); if (!is_valid) { zero_fields(_ammpro, AMMCE_PNOR, AMMCE_PACC, AMMCE_PANT, AMMCE_QNOR, AMMCE_QACC, AMMCE_QANT, AMMCE_QPERSE, AMMCE_FPRIVATO, AMMCE_QPPRIVATE, NULL); save_amm(); return; } const TDitta_cespiti& cce = ditta_cespiti(); TDate inies, fines; cce.esercizio_corrente(inies, fines); const bool fzper = _ammpro.get_bool(AMMCE_FZPER); const bool fzquo = _ammpro.get_bool(AMMCE_FZQUO); const bool is_forz = fzper || fzquo; // Forzatura sul cespite const TTipo_cespite tc = tipo(); const bool leasing = get_bool(CESPI_LEASING); const int anniric = get_int(CESPI_ANNIRIC); if ((tc == tc_materiale && !leasing) || (tc == tc_immateriale && anniric <= 0) || is_forz) { const real coeff_durata = cce.coefficiente_durata_esercizio(); if (fzquo) // Forzatura quota { real resamm = res_amm() - _ammpro.get_real(AMMCE_FPRIVATO); if (resamm > ZERO) { real qnor = _ammpro.get_real(AMMCE_QNOR); if (resamm < qnor) _ammpro.put(AMMCE_QNOR, qnor = resamm); // Forzo la quota uguale al residuo const real pnor = qnor / coeff_durata * CENTO / val_amm(); ammpro_put_perc(AMMCE_PNOR, pnor); resamm -= qnor; if (resamm > ZERO) { real qacc = _ammpro.get_real(AMMCE_QACC); if (resamm < qacc) _ammpro.put(AMMCE_QACC, qacc = resamm); // Forzo la quota uguale al residuo const real pacc = qacc / coeff_durata * CENTO / val_amm(); ammpro_put_perc(AMMCE_PACC, pacc); resamm -= qacc; } else { zero_fields(_ammpro, AMMCE_QACC, AMMCE_PACC, NULL); } if (resamm > ZERO) { real qant = _ammpro.get_real(AMMCE_QANT); if (resamm < qant) _ammpro.put(AMMCE_QANT, qant = resamm); // Forzo la quota uguale al residuo const real pant = qant / coeff_durata * CENTO / val_amm(); ammpro_put_perc(AMMCE_PANT, pant); resamm -= qant; } else { zero_fields(_ammpro, AMMCE_QANT, AMMCE_PANT, NULL); } } else { zero_fields(_ammpro, AMMCE_QNOR, AMMCE_PNOR, AMMCE_QANT, AMMCE_PANT, AMMCE_QACC, AMMCE_PACC, AMMCE_QPERSE, AMMCE_FPRIVATO, AMMCE_QPPRIVATE, NULL); } } else if (fzper) // Forzatura percentuale { real resamm = res_amm() - _ammpro.get_real(AMMCE_FPRIVATO); if (resamm > ZERO) { const real valamm = val_amm(); const real pnor = _ammpro.get_real(AMMCE_PNOR); real per_eff; const real qnor = calc_quota(valamm, pnor, resamm, per_eff); _ammpro.put(AMMCE_QNOR, qnor); ammpro_put_perc(AMMCE_PNOR, per_eff); resamm -= qnor; } else { zero_fields(_ammpro, AMMCE_QNOR, AMMCE_PNOR, AMMCE_QANT, AMMCE_PANT, AMMCE_QACC, AMMCE_PACC, AMMCE_QPERSE, AMMCE_FPRIVATO, AMMCE_QPPRIVATE, NULL); } const real pacc = _ammpro.get_real(AMMCE_PACC); if (resamm > ZERO && pacc > ZERO) { const real valamm = val_amm(); real per_eff; const real qacc = calc_quota(valamm, pacc, resamm, per_eff); _ammpro.put(AMMCE_QACC, qacc); ammpro_put_perc(AMMCE_PACC, per_eff); resamm -= qacc; } else zero_fields(_ammpro, AMMCE_QACC, AMMCE_PACC, NULL); const real pant = _ammpro.get_real(AMMCE_PANT); if (resamm > ZERO && pant > ZERO) { const real valamm = val_amm(); real per_eff; const real qant = calc_quota(valamm, pant, resamm, per_eff); _ammpro.put(AMMCE_QANT, qant); ammpro_put_perc(AMMCE_PANT, per_eff); resamm -= qant; } else zero_fields(_ammpro, AMMCE_QANT, AMMCE_PANT, NULL); } else // Nessuna forzatura { // Leggo percentuali teoriche da AMMINI _ammpro.put(AMMCE_PNOR, ammini_get_real(AMMCE_PNOR)); _ammpro.put(AMMCE_PANT, ammini_get_real(AMMCE_PANT)); _ammpro.put(AMMCE_PACC, ammini_get_real(AMMCE_PACC)); // Percentuale minima quote perse real pmat = get_real(CESPI_PMAT) / 2.0; const TDate dtfunz = get_date(CESPI_DTFUNZ); if (tc == tc_materiale && _salini.get_int(SALCE_ANNIAMM) == 0 && !cce.professionista() && dtfunz >= inies) { // Calcolo il valore di un singolo elemento per vedere se e' inferiore al milione di lire real vam1 = val_amm(); if (vam1 > ZERO) { const real numele = _salpro.get_real(SALCE_NUMELE); if (numele > ZERO) vam1 /= numele; } if (ammini_get_bool(AMMCE_CSCEN) && vam1 < un_milione()) { _ammpro.put(AMMCE_PNOR, CENTO); _ammpro.zero(AMMCE_PANT); _ammpro.zero(AMMCE_PACC); _ammpro.put(AMMCE_MSG04, "X"); // Ammortamento totale } else { if (cce.ammortamento_proporzionale() && get_bool(CESPI_AMMPROP)) { const real durata_esercizio = fines - inies + 1; const real giorni_possesso = fines - dtfunz + 1; const real coeff = giorni_possesso / durata_esercizio; ammpro_put_perc(AMMCE_PNOR, ammini_get_real(AMMCE_PNOR)*coeff); ammpro_put_perc(AMMCE_PANT, ammini_get_real(AMMCE_PANT)*coeff); ammpro_put_perc(AMMCE_PACC, ammini_get_real(AMMCE_PACC)*coeff); pmat *= coeff; pmat.round(3); _ammpro.put(AMMCE_MSG06, "X"); // Ammortamento proporzionale nel primo esercizio } else { if (!cce.primo_ammortamento_100(dtfunz, _ammpro.get_int(AMMCE_TPAMM), auto_o_moto())) { ammpro_put_perc(AMMCE_PNOR, ammini_get_real(AMMCE_PNOR)/2.0); ammpro_put_perc(AMMCE_PANT, ammini_get_real(AMMCE_PANT)/2.0); ammpro_put_perc(AMMCE_PACC, ammini_get_real(AMMCE_PACC)/2.0); pmat /= 2.0; pmat.round(3); _ammpro.put(AMMCE_MSG01, "X"); // Ammortamento al 40-50-80-90% nel primo esercizio } } } } real resamm = res_amm(); if (resamm > ZERO) { const real valamm = val_amm(); const real pnor = _ammpro.get_real(AMMCE_PNOR); real per_eff; const real qnor = calc_quota(valamm, pnor, resamm, per_eff); _ammpro.put(AMMCE_QNOR, qnor); ammpro_put_perc(AMMCE_PNOR, per_eff); const real quote_perse = calc_quote_perse(valamm, pmat, resamm, qnor, false, TDate()); _ammpro.put(AMMCE_QPERSE, quote_perse); const int uso_promiscuo = get_int(CESPI_USOPROM); if (_tipo_sit == 1 && uso_promiscuo > 1) agg_quota(valamm, _ammpro, AMMCE_QNOR, true); else zero_fields(_ammpro, AMMCE_FPRIVATO, AMMCE_QPPRIVATE, NULL); resamm -= qnor + _ammpro.get_real(AMMCE_FPRIVATO); const real pacc = _ammpro.get_real(AMMCE_PACC); if (resamm > ZERO && pacc > ZERO && quote_perse.is_zero()) { const real qacc = calc_quota(val_amm(), pacc, resamm, per_eff); _ammpro.put(AMMCE_QACC, qacc); ammpro_put_perc(AMMCE_PACC, per_eff); if (_tipo_sit == 1 && uso_promiscuo > 1) agg_quota(valamm, _ammpro, AMMCE_QACC, false); else _ammpro.zero(AMMCE_FPRIVATO); resamm -= qacc; } else zero_fields(_ammpro, AMMCE_PACC, AMMCE_QACC, NULL); const int anniamm = _salini.get_int(SALCE_ANNIAMM); if (tc != tc_materiale || anniamm > 2) { zero_fields(_ammpro, AMMCE_PANT, AMMCE_QANT, NULL); } else { const real pant = _ammpro.get_real(AMMCE_PANT); if (resamm > ZERO && pant > ZERO) { const real qant = calc_quota(val_amm(), pant, resamm, per_eff); _ammpro.put(AMMCE_QANT, qant); ammpro_put_perc(AMMCE_PANT, per_eff); if (_tipo_sit == 1 && uso_promiscuo > 1) agg_quota(valamm, _ammpro, AMMCE_QANT, false); else _ammpro.zero(AMMCE_FPRIVATO); } else zero_fields(_ammpro, AMMCE_PANT, AMMCE_QANT, NULL); } } else { zero_fields(_ammpro, AMMCE_PNOR, AMMCE_PACC, AMMCE_PANT, AMMCE_QNOR, AMMCE_QACC, AMMCE_QANT, AMMCE_QPERSE, AMMCE_FPRIVATO, AMMCE_QPPRIVATE, NULL); } } } else { // Calcolo ammortamenti per anni real resamm = res_amm(); if (resamm > ZERO) { const int anniamm = _salini.get_int(SALCE_ANNIAMM); const int vincolo = get_int(CESPI_VINCOLO); real qnor; // Valore non calcolato if ((tc == tc_pluriennale && vincolo == 2 && ammini_get_real(AMMCE_PNOR).is_zero()) || (tc == tc_immateriale && anniric > 0) || (tc == tc_materiale && anniric > 0)) { if (anniric > anniamm) qnor = resamm / (anniric - anniamm); } else if (tc == tc_pluriennale && vincolo == 3) { if (anniric > anniamm) qnor = val_amm() / anniric; } else if (tc == tc_pluriennale && vincolo == 1) { if (anniric > 0) qnor = val_amm() / anniric; else qnor = val_amm() * ammini_get_real(AMMCE_PNOR) / CENTO; } else if (tc == tc_pluriennale && vincolo == 2 && ammini_get_real(AMMCE_PNOR) > ZERO) { if (anniric > anniamm) qnor = val_amm() * ammini_get_real(AMMCE_PNOR) / CENTO; } if (resamm < qnor) qnor = resamm; cce.arrotonda(qnor); _ammpro.put(AMMCE_QNOR, qnor); const real valore = val_amm(); if (qnor > ZERO && valore > ZERO) { const real pnor = qnor * CENTO / valore; ammpro_put_perc(AMMCE_PNOR, pnor); } else _ammpro.zero(AMMCE_PNOR); } else { _ammpro.zero(AMMCE_PNOR); _ammpro.zero(AMMCE_QNOR); } } // Controlli preliminari per evitare un inutile calcolo del fringe benefit if (is_valid && _tipo_sit == 1 && tc == tc_materiale && !leasing) controllo_fringe_benefit(); save_amm(); } void TCespite::agg_spe_man(bool is_valid) { if (_tipo_sit != 1 || !is_valid || tipo() != tc_materiale || _in_memory) return; const real vspmanu = _salpro.get(SALCE_VSPMANU); if (vspmanu > ZERO) { log(TR("- Aggiornamento spese di manutenzione")); TDitta_cespiti& cce = ditta_cespiti(); const int tpspeman = get_int(CESPI_TPSPEMAN); const char* field = NULL; // Nome del campo da incrementare if (tpspeman == 2 || (tpspeman == 4 && !cce.esente_art14())) field = "R2"; else if (tpspeman == 3) field = "R3"; if (field != NULL) { int es; TString4 gr, sp; cce.get_attivita(es, gr, sp); TString16 key; key.format("%04d%s%s", es, (const char*)gr, (const char*)sp); TTable ccb("CCB"); ccb.put("CODTAB", key); const int err = ccb.read(); if (err != NOERR) { ccb.zero(); ccb.put("CODTAB", key); } real speman = ccb.get_real(field); if (tpspeman == 3) speman += vspmanu * 0.25; // 25% else speman += vspmanu * 0.05; // 5% cce.arrotonda(speman); ccb.put(field, speman); ccb.put("D0", TDate(TODAY)); if (err == NOERR) ccb.rewrite(); else ccb.write(); } } } bool TCespite::calc_amm(int tipo_sit, const TDate& data_limite, bool recalc_spe_man, bool in_memory) { _tipo_sit = tipo_sit; _in_memory = in_memory; if (in_memory) { TDate ini_es, fin_es; const int cod_es = ditta_cespiti().esercizio_corrente(ini_es, fin_es); if (data_limite >= ini_es && data_limite < fin_es) { real giorni = data_limite - ini_es + 1; real totali = fin_es - ini_es + 1; // se sono a fine mese di un anno normale approssimo al mese commerciale if ((totali == 365 || totali == 366) && data_limite.is_end_month()) { giorni /= 30; giorni.round(); totali = 12; // totali /= 30; totali.round(); } _fraction = giorni / totali; } } const TString16 idcespite = get(CESPI_IDCESPITE); // Keep it handy for debug purposes log(FR("* Inizio calcolo situazione %d cespite %s"), tipo_sit, (const char*)idcespite); #ifdef DBG if (tipo_sit == 1 && atol(idcespite) == 1362) tipo_sit = 1; // Put your breakpoint here #endif const bool is_valid = valido(); prepara_saldi(is_valid); scansione_movimenti(data_limite, is_valid); calc_amm_residui(is_valid); if (recalc_spe_man) agg_spe_man(is_valid); log(FR("* Fine calcolo situazione %d cespite %s"), tipo_sit, (const char*)idcespite); log(""); return is_valid; } int TCespite::read(const char* id) { TLocalisamfile cespi(LF_CESPI); put(CESPI_IDCESPITE, id); int err = TRectype::read(cespi, _isequal, _nolock); if (err != NOERR) zero(); _salini.zero(); _salpro.zero(); _ammini.zero(); _ammpro.zero(); _ammmv.destroy(); _movam.destroy(); _movce.destroy(); return err; } void TCespite::load_saldi(const int tiposit, const int esercizio) { _tipo_sit = tiposit; TLocalisamfile salce(LF_SALCE); fill_sal_key(salce.curr(), esercizio, 1); if (salce.read() == NOERR) { _salini = salce.curr(); // Il campo VNONAMMC nasce solo nel 2006, prima era da intendersi uguale a VNONAMM if (!_salini.get_real(SALCE_VNONAMM).is_zero() && _salini.get_real(SALCE_VNONAMMC).is_zero()) { if (esercizio <= 2006) // Uso improprio dell'esercizio come anno solare _salini.put(SALCE_VNONAMMC, _salini.get(SALCE_VNONAMM)); } } else _salini.zero(); fill_sal_key(salce.curr(), esercizio, 2); if (salce.read() == NOERR) _salpro = salce.curr(); else _salpro = _salini; TLocalisamfile ammce(LF_AMMCE); fill_amm_key(ammce.curr(), esercizio, 1); if (ammce.read() == NOERR) _ammini = ammce.curr(); else _ammini.zero(); fill_amm_key(ammce.curr(), esercizio, 2); if (ammce.read() == NOERR) _ammpro = ammce.curr(); else _ammpro = _ammini; _ammmv.destroy(); const TDate dtalien = get(CESPI_DTALIEN); TEsercizi_contabili esc; TDate inies, fines; esc.code2range(esercizio, inies, fines); if (!dtalien.ok() || dtalien >= inies) { TRelation rel(LF_AMMMV); TRectype& ammmv = rel.curr(); ammmv.put(AMMMV_IDCESPITE, get(CESPI_IDCESPITE)); TString8 filter; filter.format("%s==%d", AMMMV_TPAMM, tiposit); TCursor cur(&rel, filter, 1, &ammmv, &ammmv); const TRecnotype items = cur.items(); if (items > 0) { cur.freeze(); // Astutamente faccio solo ora il join rel.add(LF_MOVCE, "IDMOV==IDMOV"); TRectype& movce = rel.curr(LF_MOVCE); for (cur = 0L; cur.pos() < items; ++cur) { const TDate dtmov = movce.get(MOVCE_DTMOV); if (dtmov >= inies && dtmov <= fines) { _ammmv.add(ammmv); TToken_string key; key.add(get(CESPI_IDCESPITE)); key.add(movce.get(MOVCE_IDMOV)); key.add(tiposit); const TRectype& movam = cache().get(LF_MOVAM, key); if (!movam.empty()) _movam.add(movam); } } } } } TCespite::TCespite() : TRectype(LF_CESPI), _salini(LF_SALCE), _salpro(LF_SALCE), _ammini(LF_AMMCE), _ammpro(LF_AMMCE) { } TCespite::TCespite(const char* id) : TRectype(LF_CESPI), _salini(LF_SALCE), _salpro(LF_SALCE), _ammini(LF_AMMCE), _ammpro(LF_AMMCE) { read(id); } TCespite::TCespite(const TRectype& rec) : TRectype(rec), _salini(LF_SALCE), _salpro(LF_SALCE), _ammini(LF_AMMCE), _ammpro(LF_AMMCE) { }