public string AperturaContiPatrimoniali(Esercizio esercizio)
        {
            try
            {
                var message = string.Empty;

                if (esercizio.GetEsercizioPrecedente() != null)
                {
                    var testata = new TestataMovimentoContabile(esercizio, esercizio.DataApertura, TipoTestataMovimentoContabileEnum.Automatica, null) { AperturaChiusuraConti = true };
                    var causale = _daoFactory.GetCausaleContabileDao().GetByCodice("AC");
                    var contoTransitorio = _daoFactory.GetContoDao().GetByCodice(esercizio.ID, esercizio.CondominioRiferimento.ID, "999");

                    // ---------------------------------------------------------------------------------------
                    //  Registro tutti movimenti di apertura dei conti
                    // ---------------------------------------------------------------------------------------
                    var index = 0;
                    var testate = _daoFactory.GetTestataMovimentoContabileDao().GetTestateMovimentiByEsercizioCausale(esercizio.GetEsercizioPrecedente(), _daoFactory.GetCausaleContabileDao().GetByCodice("OC")).Where(item => item.AperturaChiusuraConti).ToList();
                    if (testate.Count > 1)
                    {
                        _log.ErrorFormat("ATTENZIONE: Trovata più di una testata con causale di chiusura 'OC' nell'esercizio - {0} - esercizio:{1}", Utility.GetMethodDescription(), esercizio.ID);
                        return string.Format("Trovata più di una testata di chiusura nell'esercizio: '{0}'", esercizio.DisplayName);
                    }
                    else if(testate.Count == 0)
                    {
                        _log.ErrorFormat("ATTENZIONE: Non è stata trovata nessuna causale di chiusura 'OC' nell'esercizio - {0} - esercizio:{1}", Utility.GetMethodDescription(), esercizio.ID);
                        return string.Format("Non è stata trovata nessuna testata di chiusura nell'esercizio: '{0}'", esercizio.DisplayName);
                    }
                    else
                    {
                        foreach (var movimento in testate[0].Movimenti)
                        {
                            var importo = movimento.GetImportoSenzaSegno();
                            index++;
                            if (movimento.ContoRiferimento.Codice != "998")
                            {
                                new MovimentoContabile(testata, causale, index, movimento.ContoRiferimento, importo, invertiSegno(movimento.Segno))
                                {
                                    Descrizione = movimento.Descrizione.Replace("Chiusura", "Apertura"),
                                    Stato = StatoMovimentoContabileEnum.Evaso,
                                    FornitoreRiferimento = movimento.FornitoreRiferimento,
                                    CondominoRiferimento = movimento.CondominoRiferimento,
                                    ContoCorrenteBancario = movimento.ContoCorrenteBancario,
                                    SottoContoRiferimento = movimento.SottoContoRiferimento
                                };
                            }
                            else
                            {
                                new MovimentoContabile(testata, causale, index, contoTransitorio, importo, invertiSegno(movimento.Segno))
                                {
                                    Descrizione = movimento.Descrizione.Replace("Chiusura", "Apertura"),
                                    Stato = StatoMovimentoContabileEnum.Evaso,
                                    FornitoreRiferimento = movimento.FornitoreRiferimento,
                                    CondominoRiferimento = movimento.CondominoRiferimento,
                                    ContoCorrenteBancario = movimento.ContoCorrenteBancario,
                                    SottoContoRiferimento = movimento.SottoContoRiferimento
                                };
                                
                            }
                        }

                        _daoFactory.GetTestataMovimentoContabileDao().SaveOrUpdate(testata);
                    }

                }

                return message;
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato durante l'apertura dei conti patrimoniali - {0} - esercizio:{1}", ex, Utility.GetMethodDescription(), esercizio.ID);
                throw;
            }
        }
        public IList<TestataMovimentoContabile> SetMovimentiVersamentoCondomino(TestataMovimentoContabile testata, MovimentoContabile movimentoPatrimonialeAttivo, Esercizio esercizio, VersamentoSoggetto versamento, DateTime dataRegistrazione, CausaleContabile causale, Conto contoVersamentoCondomini, int? idMovimentoBancario, FileCBI file, LogTransazione logTransazione)
        {
            var testate = new List<TestataMovimentoContabile>();
            if(causale == null)
                causale = _daoFactory.GetCausaleContabileDao().GetByCodice("RR");
            if (contoVersamentoCondomini == null)
                contoVersamentoCondomini = _daoFactory.GetContoDao().GetByCodice(esercizio.ID, esercizio.CondominioRiferimento.ID, _pianoContiService.GetCodiceContoVersamentiCondomini());
            bool evasioneBancaria = false;
            
            // ================================================================================
            //  Registrazione Movimenti Contabili per Versamento Condomino
            // ================================================================================
            var rateVersate = string.Empty;
            foreach (var versamentoRata in versamento.Rate)
            {
                if (!string.IsNullOrEmpty(rateVersate))
                    rateVersate += ", ";
                rateVersate += versamentoRata.Rata.PianoRatealeDettaglio.Progressivo;
            }
            if (!string.IsNullOrEmpty(rateVersate))
                rateVersate = "(" + rateVersate + ")";

            var descrizione = $"Versamento Rata di {versamento.Soggetto.DisplayName} {rateVersate}";
            
            // ------------------------------------------------
            // Testata
            // ------------------------------------------------
            if (testata == null)
            {
                testata = new TestataMovimentoContabile(esercizio, dataRegistrazione, TipoTestataMovimentoContabileEnum.Automatica, file, logTransazione)
                {
                    Descrizione = descrizione
                };
            }

            testate.Add(testata);
            var message = IsAllowDataRegistrazione(new List<int>(), testata.EsercizioRiferimento, testata.DataRegistrazione.GetValueOrDefault());
            if (message.Count > 0)
            {
                var ex = new InvalidDataException($"La data di registrazione {testata.DataRegistrazione.GetValueOrDefault()} non è valida");
                _log.FatalFormat("Data di registrazione non valida - {0} - data:{1} - versamento:{2} - message:{3}", ex, Utility.GetMethodDescription(), testata.DataRegistrazione.GetValueOrDefault(), versamento.ID, message.Aggregate(string.Empty, (current, str) => current + string.Format("{0}{1}", message, Environment.NewLine)));
                throw ex;
            }

            var numeroRiga = testata.Movimenti.Count;

            // ------------------------------------------------
            // Crediti V/S Condomini - a Saldo
            // ------------------------------------------------
            numeroRiga++;
            var movimentoPatrimoniale = new MovimentoContabile(testata, causale, numeroRiga, contoVersamentoCondomini, versamento.Importo, "A")
            {
                CondominoRiferimento = versamento.Soggetto, 
                Descrizione = descrizione
            };

            // ------------------------------------------------
            // Banca / Cassa
            // ------------------------------------------------
            if (movimentoPatrimonialeAttivo == null)
            {
                evasioneBancaria = true;
                numeroRiga++;
                movimentoPatrimonialeAttivo = new MovimentoContabile(testata, causale, numeroRiga, versamento.ContoPatrimoniale, versamento.Importo, "D")
                {
                    Descrizione = descrizione,
                    SottoContoRiferimento = versamento.SottoContoPatrimoniale,
                    ContoCorrenteBancario = versamento.ContoBancario,
                    NumeroAssegno = versamento.NumeroAssegno
                };
            }
            else
                movimentoPatrimonialeAttivo.Importo = movimentoPatrimonialeAttivo.GetImportoSenzaSegno() + versamento.Importo;

            // ================================================================================
            //  SOLO ESERCIZI ORDINARI
            //  Se la data di registrazione è successiva alla data di chiusura dell'esercizio
            //  registro i movimenti, usando un contro transitorio, che permette di rilevare
            //  il versamento nello stato patrimoniale dell'esercizio.
            // ================================================================================
            if (versamento.TipoVersamentoDopoChiusura.GetValueOrDefault() == TipoVersamentoDopoChiusuraEnum.Giroconto  && esercizio.Gestione == GestioneEsercizioEnum.Ordinario)
            {
                var esercizioPrecedente = esercizio.GetEsercizioPrecedente();
                if (esercizioPrecedente != null)
                {
                    var causaleVersamentiCondominiDopoChiusura = _daoFactory.GetCausaleContabileDao().GetByCodice("VS");
                    var contoVersamentiDopoChiusura = _pianoContiService.GetContoVersamentiSuccessiviAllaChiusura(esercizio);
                    try
                    {
                        if (movimentoPatrimoniale.CondominoRiferimento != null)
                        {
                            var descrizioneStorno = string.Format("Versamento dopo data chiusura - {0} del {1} {2}", movimentoPatrimoniale.CondominoRiferimento.DisplayName, movimentoPatrimoniale.Testata.DataRegistrazione.GetValueOrDefault().ToShortDateString(), rateVersate);

                            // ---------------------------------------------------------------------------------------
                            // Movimenti per storno e riconoscimento versamenti ai condomini
                            // Nuova testata nell'esercizio precedente per registrare lo storno
                            // ---------------------------------------------------------------------------------------
                            var numeroRigaStorno = 0;
                            var testataStorno = new TestataMovimentoContabile(esercizioPrecedente, esercizioPrecedente.DataChiusura, TipoTestataMovimentoContabileEnum.Automatica, file, logTransazione)
                            {
                                Descrizione = descrizioneStorno
                            };
                            testate.Add(testataStorno);

                            numeroRigaStorno++;
                            var movimentoVersamento = new MovimentoContabile(testataStorno, causaleVersamentiCondominiDopoChiusura, numeroRigaStorno, movimentoPatrimoniale.ContoRiferimento, movimentoPatrimoniale.Importo, movimentoPatrimoniale.Segno)
                            {
                                CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                Descrizione = descrizioneStorno
                            };

                            numeroRigaStorno++;
                            var movimentoContoTemporaneo = new MovimentoContabile(testataStorno, causaleVersamentiCondominiDopoChiusura, numeroRigaStorno, contoVersamentiDopoChiusura, movimentoPatrimoniale.Importo, invertiSegno(movimentoPatrimoniale.Segno))
                            {
                                CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                Descrizione = descrizioneStorno
                            };

                            // ---------------------------------------------------------------------------------------
                            // Nella stessa testata del versamento originale aggiungo il movimento di chiusura del conto temporaneo
                            // ---------------------------------------------------------------------------------------
                            numeroRiga++;
                            var descrizioneChiusuraStorno = string.Format("Chiusura dello storno del versamento dopo data chiusura - {0} del {1} {2}", movimentoPatrimoniale.CondominoRiferimento.DisplayName, movimentoPatrimoniale.Testata.DataRegistrazione.GetValueOrDefault().ToShortDateString(), rateVersate);
                            var movimentoVersamentoChiusura = new MovimentoContabile(testata, causaleVersamentiCondominiDopoChiusura, numeroRiga, movimentoPatrimoniale.ContoRiferimento, movimentoPatrimoniale.Importo, invertiSegno(movimentoPatrimoniale.Segno))
                            {
                                CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                Descrizione = descrizioneChiusuraStorno
                            };

                            numeroRiga++;
                            var movimentoContoTemporaneoChiusura = new MovimentoContabile(testata, causaleVersamentiCondominiDopoChiusura, numeroRiga, contoVersamentiDopoChiusura, movimentoPatrimoniale.Importo, movimentoPatrimoniale.Segno)
                            {
                                CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                Descrizione = descrizioneChiusuraStorno
                            };
                            versamento.TestataMovimentoDopoChiusura = testataStorno;
                        }
                    }
                    catch (Exception ex)
                    {
                        _log.ErrorFormat("Errore inaspettato durante la registrazione dei movimenti per i versamenti eseguiti dopo la chiusura - SINGOLO MOVIMENTO - {0} - esercizio:{1} - movimento:{2}", ex, Utility.GetMethodDescription(), esercizio.ID, movimentoPatrimoniale.ID);
                        throw;
                    }
                }
                else
                {
                    _log.ErrorFormat("Esercizio precedente a null - {0} - versamento:{1} - esercizio:{2}", Utility.GetMethodDescription(), versamento.ID, esercizio.ID);
                }
            }

            // ================================================================================
            //  SOLO ESERCIZI ORDINARI - bugid#6223
            //  Se la data di registrazione è antecedente alla data di apertura dell'esercizio
            //  registro i movimenti, usando un contro transitorio, che permette di rilevare
            //  il versamento nello stato patrimoniale dell'esercizio.
            // ================================================================================
            if (versamento.TipoVersamentoPrimaApertura.GetValueOrDefault() == TipoVersamentoPrimaAperturaEnum.Giroconto && esercizio.Gestione == GestioneEsercizioEnum.Ordinario)
            {
                var annoSuccessivo = _daoFactory.GetAnnoGestionaleDao().GetAnnoSuccessivo(esercizio.AnnoGestionale.ID);
                if (annoSuccessivo != null)
                {
                    if (annoSuccessivo.EsercizioOrdinario != null)
                    {
                        var causaleVersamentiCondominiPrimaApertura = _daoFactory.GetCausaleContabileDao().GetByCodice("VA");
                        var contoVersamentiPrecedentiAllaApertura = _pianoContiService.GetContoVersamentiPrecedentiAllaApertura(esercizio);
                        try
                        {
                            if (movimentoPatrimoniale.CondominoRiferimento != null)
                            {
                                var descrizioneStorno = string.Format("Versamento prima della data di apertura - {0} del {1} {2}", movimentoPatrimoniale.CondominoRiferimento.DisplayName, movimentoPatrimoniale.Testata.DataRegistrazione.GetValueOrDefault().ToShortDateString(), rateVersate);

                                // ---------------------------------------------------------------------------------------
                                // Movimenti per storno e riconoscimento versamenti ai condomini
                                // Nuova testata nell'esercizio successivo per registrare lo storno
                                // ---------------------------------------------------------------------------------------
                                var numeroRigaStorno = 0;
                                var testataStorno = new TestataMovimentoContabile(annoSuccessivo.EsercizioOrdinario, annoSuccessivo.EsercizioOrdinario.DataApertura, TipoTestataMovimentoContabileEnum.Automatica, file, logTransazione)
                                {
                                    Descrizione = descrizioneStorno
                                };
                                testate.Add(testataStorno);

                                numeroRigaStorno++;
                                var movimentoVersamento = new MovimentoContabile(testataStorno, causaleVersamentiCondominiPrimaApertura, numeroRigaStorno, movimentoPatrimoniale.ContoRiferimento, movimentoPatrimoniale.Importo, movimentoPatrimoniale.Segno)
                                {
                                    CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                    Descrizione = descrizioneStorno
                                };

                                numeroRigaStorno++;
                                var movimentoContoTemporaneo = new MovimentoContabile(testataStorno, causaleVersamentiCondominiPrimaApertura, numeroRigaStorno, contoVersamentiPrecedentiAllaApertura, movimentoPatrimoniale.Importo, invertiSegno(movimentoPatrimoniale.Segno))
                                {
                                    CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                    Descrizione = descrizioneStorno
                                };

                                // ---------------------------------------------------------------------------------------
                                // Nella stessa testata del versamento originale aggiungo il movimento di chiusura del conto temporaneo
                                // ---------------------------------------------------------------------------------------
                                numeroRiga++;
                                var descrizioneChiusuraStorno = string.Format("Chiusura dello storno del versamento prima della data di apertura - {0} del {1} {2}", movimentoPatrimoniale.CondominoRiferimento.DisplayName, movimentoPatrimoniale.Testata.DataRegistrazione.GetValueOrDefault().ToShortDateString(), rateVersate);
                                var movimentoVersamentoChiusura = new MovimentoContabile(testata, causaleVersamentiCondominiPrimaApertura, numeroRiga, movimentoPatrimoniale.ContoRiferimento, movimentoPatrimoniale.Importo, invertiSegno(movimentoPatrimoniale.Segno))
                                {
                                    CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                    Descrizione = descrizioneChiusuraStorno
                                };

                                numeroRiga++;
                                var movimentoContoTemporaneoChiusura = new MovimentoContabile(testata, causaleVersamentiCondominiPrimaApertura, numeroRiga, contoVersamentiPrecedentiAllaApertura, movimentoPatrimoniale.Importo, movimentoPatrimoniale.Segno)
                                {
                                    CondominoRiferimento = movimentoPatrimoniale.CondominoRiferimento,
                                    Descrizione = descrizioneChiusuraStorno
                                };
                                versamento.TestataMovimentoDopoChiusura = testataStorno;
                            }
                        }
                        catch (Exception ex)
                        {
                            _log.ErrorFormat("Errore inaspettato durante la registrazione dei movimenti per i versamenti eseguiti dopo la chiusura - SINGOLO MOVIMENTO - {0} - esercizio:{1} - movimento:{2}", ex, Utility.GetMethodDescription(), esercizio.ID, movimentoPatrimoniale.ID);
                            throw;
                        }                        
    
                    }
                }
                else
                {
                    _log.ErrorFormat("Esercizio successivo a null - {0} - versamento:{1} - esercizio:{2}", Utility.GetMethodDescription(), versamento.ID, esercizio.ID);
                }
            }

            // ================================================================================
            //  Evado il corrispondente Movimento Bancario
            // ================================================================================
            if (evasioneBancaria && idMovimentoBancario != null)
            {
                EvadiMovimento(string.Format("Evasione automatica per contabilizzazione versamento condomino del {0}", dataRegistrazione.ToShortDateString()), new List<MovimentoContabile> { movimentoPatrimonialeAttivo }, new List<int> { idMovimentoBancario.Value }, dataRegistrazione, logTransazione);
                _log.DebugFormat("Evasione automatica per contabilizzazione versamento condomino - {0} - movimento economico:{1} - movimento bancario:{2} - data registrazione:{3}", Utility.GetMethodDescription(), movimentoPatrimoniale.ID, idMovimentoBancario.GetValueOrDefault(), dataRegistrazione);
            }
            versamento.MovimentoContabilePatrimoniale = movimentoPatrimonialeAttivo;

            return testate;
        }
 public string TrasferimentoSaldiSubentri(Esercizio esercizio)
 {
     var message = string.Empty;
     var esercizioPrecedente = esercizio.GetEsercizioPrecedente();
     if (esercizioPrecedente != null)
     {
         var subentri = _daoFactory.GetSubentroUnitaImmobiliareDao().GetByDataCondominio(esercizio.CondominioRiferimento.ID, esercizioPrecedente.DataApertura.GetValueOrDefault(), esercizioPrecedente.DataChiusura.GetValueOrDefault(), true);
         foreach (var subentroUnita in subentri)
         {
             var unita = subentroUnita;
             var saldi = from item in esercizio.Saldi
                         where item.Soggetto.ID == unita.SoggettoUscente.ID
                         select item;
             foreach (var saldo in saldi)
             {
                 if(subentroUnita.SoggettoEntrante.Tipo == subentroUnita.SoggettoUscente.Tipo)
                     saldo.Soggetto = subentroUnita.SoggettoEntrante;
             }
         }
     }
     return message;
 }
        private IList<ReportRipartizioneBilancioDTO> getReportItemsPreventivo(Esercizio esercizio, RendicontoAnnuale rendicontoDaUsare, IList<SoggettoCondominio> soggettiAttivi, int? idStabile, int? idScala, bool ripartizioneProprietarioConduttore, bool accorpamentoUnita, bool inversioneSaldi, bool calcoloPerSubentro, bool addebitiCondominio, bool addebitiDirettiStabileScala, bool dettaglioSottoConto)
        {
            var condominio = esercizio.CondominioRiferimento;
            var idEsercizio = esercizio.ID;
            var lista = new Dictionary<string, ReportRipartizioneBilancioDTO>();

            // =============================================================================================
            //  Se esiste devo proporre lo storico
            // =============================================================================================
            var listaStorico = getStoricoRiparto(idEsercizio, idStabile, idScala, addebitiDirettiStabileScala, TipoRendiconto.Preventivo);
            if (listaStorico.Any())
            {
                return listaStorico.Where(item => item.IdConto > 0).ToList();
            }
            else
            {
                // =============================================================================================
                //  Ricalcolo i saldi solo se ho un esercizio precedente aperto
                // =============================================================================================
                var esercizioPrecedente = esercizio.GetEsercizioPrecedente();
                if (esercizioPrecedente != null && esercizioPrecedente.Stato == StatoEsercizioEnum.Aperto)
                    _saldoContabileService.TrasferimentoSaldiNuovoEsercizio(esercizio.ID, this, calcoloPerSubentro);

                //====================================================================================
                //  Raggruppo gli importi del preventivo per Conto, Sottoconto, Lotto, Stabile e Scala
                //====================================================================================
                IList<ReportRipartizioneBilancioDTO> consuntivo = null;
                if (rendicontoDaUsare.Conti.Any(item => item.GetConto().IsRipartoLetture))
                {
                    // Il calcolo dal consuntivo, necessario per ripartire il preventivo se presente un conto a letture, deve sempre essere calcolato senza accorpamenti
                    // bugid#4171
                    if (esercizioPrecedente != null)
                        consuntivo = GetDataSourceRipartizioneBilancioConsuntivo(esercizioPrecedente.ID, null, null, null, null, idStabile, idScala, ripartizioneProprietarioConduttore, accorpamentoUnita, TipoAccorpamentoRateEnum.Nessuno, inversioneSaldi, calcoloPerSubentro, addebitiCondominio, addebitiDirettiStabileScala, null).ToList();
                }

                var importiConto = new List<ImportiContoSottocontoDTO>();
                foreach (var rendicontoAnnualeConto in rendicontoDaUsare.Conti.Where(item => !item.GetConto().IsSpesePersonali))
                {
                    if (!addebitiCondominio || !addebitiDirettiStabileScala || (rendicontoAnnualeConto.Stabile == null && rendicontoAnnualeConto.GruppoStabile == null))
                    {
                        if (!addebitiDirettiStabileScala ||
                            (
                                (idStabile == null || (rendicontoAnnualeConto.Stabile != null && rendicontoAnnualeConto.Stabile.ID == idStabile.GetValueOrDefault())) &&
                                (idScala == null || (rendicontoAnnualeConto.GruppoStabile != null && rendicontoAnnualeConto.GruppoStabile.ID == idScala.GetValueOrDefault()))
                            ))
                        {
                            int? idSottoConto = null;
                            if (dettaglioSottoConto)
                            {
                                if (rendicontoAnnualeConto.SottoContoRiferimento != null)
                                    idSottoConto = rendicontoAnnualeConto.SottoContoRiferimento.ID;
                                else
                                    idSottoConto = rendicontoAnnualeConto.GetConto().ID *-1;
                            }

                            int? idStabileConto = null;
                            if (rendicontoAnnualeConto.Stabile != null)
                                idStabileConto = rendicontoAnnualeConto.Stabile.ID;

                            int? idScalaConto = null;
                            if (rendicontoAnnualeConto.GruppoStabile != null)
                                idScalaConto = rendicontoAnnualeConto.GruppoStabile.ID;

                            var importoConto = new ImportiContoSottocontoDTO
                            {
                                Conto = rendicontoAnnualeConto.GetConto().ID,
                                SottoConto = idSottoConto,
                                Stabile = idStabileConto,
                                Scala = idScalaConto,
                                ImportoProprieta =
                                    _ripartizioneService.GetImportoCompetenza(
                                        rendicontoAnnualeConto.Importo.GetValueOrDefault(),
                                        rendicontoAnnualeConto.GetConto(),
                                        rendicontoAnnualeConto.SottoContoRiferimento,
                                        TipoSoggetto.Proprietario),
                                ImportoConduzione =
                                    _ripartizioneService.GetImportoCompetenza(
                                        rendicontoAnnualeConto.Importo.GetValueOrDefault(),
                                        rendicontoAnnualeConto.GetConto(),
                                        rendicontoAnnualeConto.SottoContoRiferimento,
                                        TipoSoggetto.Conduttore)
                            };

                            addImporto(importoConto, importiConto);
                        }

                    }
                }

                //====================================================================================
                //  Eseguo il riparto
                //====================================================================================
                var millesimi = _daoFactory.GetMillesimoDao().GetByCondominio(condominio.ID);
                var millesimiGroupByConto = millesimi.GroupBy(item => item.ContoRiferimento.ID).ToList();
                var unitaImmobiliari = _daoFactory.GetUnitaImmobiliareDao().GetByCondominio(condominio.ID).ToDictionary(item => item.ID);
                var conti = _daoFactory.GetContoDao().GetByCondominio(condominio.ID).ToDictionary(item => item.ID);
                var soggetti = soggettiAttivi.ToDictionary(item => item.ID);
                var riparto = new List<SpeseUnitaRipartoDTO>();
                foreach (var importiContoSottocontoDTO in importiConto)
                    riparto.AddRange(getRiparto(importiContoSottocontoDTO, millesimiGroupByConto, consuntivo, esercizio, dettaglioSottoConto));

                // ------------------------------------------------------------------
                // Proprietari attivi
                // ------------------------------------------------------------------
                var listaProprietariAttivi = new Dictionary<int, IList<SoggettoCondominio>>();
                var proprietariSoggettiAttivi = new Dictionary<int, SoggettoCondominio>();
                foreach (var soggettoCondominio in soggettiAttivi.Where(item => item.Tipo == TipoSoggetto.Proprietario))
                {
                    if (soggettoCondominio.Principale.GetValueOrDefault())
                    {
                        if (proprietariSoggettiAttivi.ContainsKey(soggettoCondominio.UnitaImmobiliare.ID))
                        {
                            if (soggettoCondominio.DataInizio.GetValueOrDefault() > proprietariSoggettiAttivi[soggettoCondominio.UnitaImmobiliare.ID].DataInizio.GetValueOrDefault() || proprietariSoggettiAttivi[soggettoCondominio.UnitaImmobiliare.ID].DataFine != null)
                                proprietariSoggettiAttivi[soggettoCondominio.UnitaImmobiliare.ID] = soggettoCondominio;
                        }
                        else
                            proprietariSoggettiAttivi.Add(soggettoCondominio.UnitaImmobiliare.ID, soggettoCondominio);
                    }

                    if (listaProprietariAttivi.ContainsKey(soggettoCondominio.UnitaImmobiliare.ID))
                        listaProprietariAttivi[soggettoCondominio.UnitaImmobiliare.ID].Add(soggettoCondominio);
                    else
                        listaProprietariAttivi.Add(soggettoCondominio.UnitaImmobiliare.ID, new List<SoggettoCondominio> { soggettoCondominio });
                }

                // ------------------------------------------------------------------
                // Conduttori attivi
                // ------------------------------------------------------------------
                var conduttoriSoggettiAttivi = new Dictionary<int, IList<SoggettoCondominio>>();
                foreach (var soggettoCondominioUnita in soggettiAttivi.Where(item => item.Tipo == TipoSoggetto.Conduttore).GroupBy(item => item.UnitaImmobiliare))
                    conduttoriSoggettiAttivi.Add(soggettoCondominioUnita.Key.ID, soggettoCondominioUnita.ToList());

                var soggettiAttiviByUnitaImmobiliare = new Dictionary<int, IList<SoggettoCondominio>>();
                foreach (var soggettoCondominioUnita in soggettiAttivi.GroupBy(item => item.UnitaImmobiliare))
                    soggettiAttiviByUnitaImmobiliare.Add(soggettoCondominioUnita.Key.ID, soggettoCondominioUnita.ToList());

                // ------------------------------------------------------------------
                // Aggiungo le spese personali (NON sono soggette a riparto)
                // ------------------------------------------------------------------
                foreach (var rendicontoAnnualeConto in rendicontoDaUsare.Conti.Where(item => item.GetConto().IsSpesePersonali))
                {
                    riparto.AddRange(rendicontoAnnualeConto.DettagliUnita.Select(spesa => new SpeseUnitaRipartoDTO
                    {
                        ID = spesa.ID,
                        IdConto = rendicontoAnnualeConto.GetConto().ID,
                        IdUnita = spesa.Unita.ID,
                        UnitaMisuraMillesimo = "PC",
                        ImportoConduttore = _ripartizioneService.GetImportoCompetenza(spesa.Importo.GetValueOrDefault(), rendicontoAnnualeConto.GetConto(), rendicontoAnnualeConto.SottoContoRiferimento, TipoSoggetto.Conduttore),
                        ImportoProprietario = _ripartizioneService.GetImportoCompetenza(spesa.Importo.GetValueOrDefault(), rendicontoAnnualeConto.GetConto(), rendicontoAnnualeConto.SottoContoRiferimento, TipoSoggetto.Proprietario)
                    }));
                }

                //=====================================================================================================
                //  Elaborazione delle ripartizioni
                //=====================================================================================================
                var index = 0;
                foreach (var spesa in riparto)
                {
                    try
                    {
                        index++;
                        var conto = conti.ContainsKey(spesa.IdConto) ? conti[spesa.IdConto] : _daoFactory.GetContoDao().GetById(spesa.IdConto, false);
                        var unita = unitaImmobiliari.ContainsKey(spesa.IdUnita.GetValueOrDefault()) ? unitaImmobiliari[spesa.IdUnita.GetValueOrDefault()] : _daoFactory.GetUnitaImmobiliareDao().GetById(spesa.IdUnita.GetValueOrDefault(), false);

                        SottoConto sottoconto = null;
                        if (spesa.IdSottoConto > 0)
                            sottoconto = conto.SottoConti.FirstOrDefault(item => item.ID == spesa.IdSottoConto.Value);

                        // -------------------------------------------------------
                        // Verifica se appartiene a scala e/o stabile selezionato
                        // -------------------------------------------------------
                        if (idStabile != null)
                        {
                            if (unita.GruppoStabileRiferimento.PalazzinaRiferimento.ID != idStabile.Value)
                                continue;
                        }

                        if (idScala != null)
                        {
                            if (unita.GruppoStabileRiferimento.ID != idScala.Value)
                                continue;
                        }

                        // -------------------------
                        // Proprietario
                        // -------------------------
                        SoggettoCondominio proprietarioPrincipale = null;
                        if(proprietariSoggettiAttivi.ContainsKey(spesa.IdUnita.GetValueOrDefault()))
                            proprietarioPrincipale = proprietariSoggettiAttivi[spesa.IdUnita.GetValueOrDefault()];

                        // Se il proprietario non è presente lo cerco tra tutti i proprietari
                        if (proprietarioPrincipale == null)
                        {
                            proprietarioPrincipale = (from item in unita.Proprietari
                                                      where
                                                          item.DataInizio == null ||
                                                          item.DataInizio.Value < esercizio.DataChiusura
                                                      orderby item.DataInizio.GetValueOrDefault() descending
                                                      select item).FirstOrDefault();

                            _log.DebugFormat("Non trovato proprietario principale - {0} - unità:{1} - esercizio:{2}", Utility.GetMethodDescription(), spesa.IdUnita, idEsercizio.ToString());
                        }

                        var importoProprieta = spesa.ImportoProprietario;
                        if (importoProprieta != 0)
                        {
                            var soggProp = new List<ImportiDTO>();
                            if (!accorpamentoUnita)
                            {
                                var soggPropRip = (conto.SoggettiRipartizione.Where(itemSogg =>
                                                itemSogg.PercentualeRipartizione > 0 &&
                                                itemSogg.Soggetto.Tipo == TipoSoggetto.Proprietario &&
                                                itemSogg.Soggetto.UnitaImmobiliare.ID == spesa.IdUnita)).ToList();

                                // In presenza di ripartizioni personalizzate occorre dividere l'importo addebito alla proprietà tra i diversi proprietari
                                if (soggPropRip.Count > 0)
                                {
                                    var totaleSoggPropRip = soggPropRip.Sum(item => item.PercentualeRipartizione);
                                    soggProp.AddRange(from sogg in soggPropRip
                                                      let soggettoRipartizione = sogg.Soggetto
                                                      select new ImportiDTO
                                                      {
                                                          Id = soggettoRipartizione.ID,
                                                          Importo = (importoProprieta.GetValueOrDefault() * sogg.PercentualeRipartizione) / totaleSoggPropRip
                                                      });
                                }
                                else if (soggPropRip.Count == 0)
                                {
                                    IList<SoggettoCondominio> proprietariAttivi = new List<SoggettoCondominio>();
                                    if(listaProprietariAttivi.ContainsKey(spesa.IdUnita.GetValueOrDefault()))
                                        proprietariAttivi = listaProprietariAttivi[spesa.IdUnita.GetValueOrDefault()];

                                    if (proprietariAttivi.Count == 0 && proprietarioPrincipale != null)
                                        proprietariAttivi.Add(proprietarioPrincipale);

                                    soggProp.AddRange(proprietariAttivi.Select(soggAttivo => new ImportiDTO { Id = soggAttivo.ID, Importo = (importoProprieta.GetValueOrDefault() * soggAttivo.PercentualeRiferimento.GetValueOrDefault()) / 100 }));
                                }
                            }
                            else
                                soggProp.Add(new ImportiDTO(proprietarioPrincipale.ID, importoProprieta.GetValueOrDefault()));

                            foreach (var idSogg in soggProp)
                            {
                                try
                                {
                                    if (idSogg.Importo != 0)
                                    {
                                        var key = spesa.IdConto + "_" + spesa.IdUnita;
                                        if (!accorpamentoUnita)
                                            key += "_" + idSogg.Id;
                                        key += "_PROP";

                                        ReportRipartizioneBilancioDTO item;
                                        if (lista.ContainsKey(key))
                                            item = lista[key];
                                        else
                                        {
                                            item = new ReportRipartizioneBilancioDTO();
                                            lista.Add(key, item);
                                            item.IdPartecipante = idSogg.Id;
                                            item.Importo = 0;
                                            item.IdConto = spesa.IdConto;
                                            item.IdUnitaImmobiliare = spesa.IdUnita.GetValueOrDefault();
                                            item.IdStabile = unita.GruppoStabileRiferimento.PalazzinaRiferimento.ID;
                                            item.IdGruppoStabile = unita.GruppoStabileRiferimento.ID;

                                            item.DisabilitaStampaMillesimi = conto.IsSpesePersonali || conto.DisabilitaMillesimiRiparto;

                                            var codice = string.Empty;
                                            if (conto.Codice != null)
                                                codice = conto.Codice;
                                            item.CodiceConto = codice;

                                            item.DescrizioneConto = !string.IsNullOrEmpty(conto.DescrizioneBilancio) && !dettaglioSottoConto
                                                                        ? conto.DescrizioneBilancio
                                                                        : conto.Descrizione;

                                            if (dettaglioSottoConto)
                                            {
                                                var codiceSottoConto = string.Empty;
                                                var descrizioneSottoConto = string.Empty;
                                                if (sottoconto != null)
                                                {
                                                    if (!string.IsNullOrEmpty(sottoconto.Codice))
                                                        codiceSottoConto = sottoconto.Codice;
                                                    descrizioneSottoConto = sottoconto.Descrizione;
                                                }
                                                else if (spesa.IdSottoConto < 0)
                                                {
                                                    descrizioneSottoConto = item.DescrizioneConto;
                                                    codiceSottoConto = item.CodiceConto;
                                                }

                                                item.CodiceSottoConto = codiceSottoConto;
                                                item.DescrizioneSottoConto = descrizioneSottoConto;
                                                item.IdSottoConto = spesa.IdSottoConto;
                                            }

                                            item.OrdineConto = conto.Ordine;
                                            item.TipoUnitaImmobiliare = unita.TipoUnitaImmobiliare.Descrizione;

                                            item.DescrizioneGruppoStabile = unita.GruppoStabileRiferimento.Descrizione;
                                            item.OrdineGruppoStabile = unita.GruppoStabileRiferimento.Ordine;
                                            item.DescrizioneStabile = unita.GruppoStabileRiferimento.PalazzinaRiferimento.Descrizione;
                                            item.OrdineStabile = unita.GruppoStabileRiferimento.PalazzinaRiferimento.Ordine;
                                            item.OrdineUnitaImmobiliare = unita.Ordine.GetValueOrDefault();
                                            item.SubalternoUnitaImmobiliare = unita.Subalterno;
                                            item.PianoUnitaImmobiliare = unita.Piano;
                                            item.InternoUnitaImmobiliare = getInternoUnitaImmobiliare(unita);

                                            item.Millesimi = spesa.ValoreMillesimo;
                                            item.UnitaMisuraMillesimi = spesa.UnitaMisuraMillesimo;

                                            if (!accorpamentoUnita)
                                            {
                                                var sogg = findSoggettoCondominio(idSogg.Id, soggetti);
                                                item.DataUscitaPartecipante = getDataUscita(sogg);
                                                item.Nominativo = sogg.DisplayName;
                                                item.IdPersona = sogg.Persona.ID;
                                            }
                                            else
                                            {
                                                item.DataUscitaPartecipante = getDataUscita(proprietarioPrincipale);
                                                item.Nominativo = proprietarioPrincipale.UnitaImmobiliare.Descrizione;
                                                item.IdPartecipante = proprietarioPrincipale.ID;
                                                item.IdPersona = proprietarioPrincipale.Persona.ID;
                                            }

                                            item.OrdinePartecipante = 10;
                                            item.TipoNominativo = "PROP";

                                            item.TipoNominativoEffettivo = findSoggettoCondominio(item.IdPartecipante, soggetti).Tipo.ToString().Substring(0, 1);
                                            item.NumeroColonne = 1;

                                            item.IdGruppoStabileAddebito = spesa.IdGruppoStabileAddebito;
                                            item.IdStabileAddebito = spesa.IdStabileAddebito;
                                        }
                                        item.Importo += idSogg.Importo;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    _log.ErrorFormat("Errore inaspettato durante la lettura del datasource per il riparto del consuntivo - SPESE PROPRIETARI - {0} - soggetto:{1} - spesa:{2} - esercizio:{3}", ex, Utility.GetMethodDescription(), idSogg.Id, spesa.ID, idEsercizio);
                                    throw;
                                }
                            }
                        }

                        // -------------------------
                        // Conduttore
                        // -------------------------
                        if (spesa.ImportoConduttore != 0)
                        {
                            var soggCond = new List<ImportiDTO>();
                            if (!accorpamentoUnita)
                            {
                                var soggCondRip = (conto.SoggettiRipartizione.Where(
                                    itemSogg => itemSogg.PercentualeRipartizione > 0 &&
                                                itemSogg.Soggetto.Tipo == TipoSoggetto.Conduttore &&
                                                itemSogg.Soggetto.UnitaImmobiliare.ID == spesa.IdUnita)).ToList();

                                if (soggCondRip.Count > 0)
                                {
                                    var totaleSoggCondRip = soggCondRip.Sum(item => item.PercentualeRipartizione);
                                    soggCond.AddRange(soggCondRip.Select(sogg => new ImportiDTO
                                    {
                                        Id = sogg.Soggetto.ID,
                                        Importo = (spesa.ImportoConduttore.GetValueOrDefault() * sogg.PercentualeRipartizione) / totaleSoggCondRip
                                    }));
                                }
                                else if (soggCondRip.Count == 0)
                                {
                                    var conduttoriAttivi = new List<SoggettoCondominio>();
                                    if(conduttoriSoggettiAttivi.ContainsKey(spesa.IdUnita.GetValueOrDefault()))
                                        conduttoriAttivi = conduttoriSoggettiAttivi[spesa.IdUnita.GetValueOrDefault()].Where(item => item.PercentualeRiferimento > 0).ToList();
                                    if (!conduttoriAttivi.Any())
                                    {
                                        if(listaProprietariAttivi.ContainsKey(spesa.IdUnita.GetValueOrDefault()))
                                            conduttoriAttivi.AddRange(listaProprietariAttivi[spesa.IdUnita.GetValueOrDefault()]);
                                    }

                                    soggCond.AddRange(conduttoriAttivi.Select(soggAttivo => new ImportiDTO
                                    {
                                        Id = soggAttivo.ID,
                                        Importo = (spesa.ImportoConduttore.GetValueOrDefault() * soggAttivo.PercentualeRiferimento.GetValueOrDefault()) / 100
                                    }));
                                }
                            }
                            else if (proprietarioPrincipale != null)
                                soggCond.Add(new ImportiDTO(proprietarioPrincipale.ID, spesa.ImportoConduttore.GetValueOrDefault()));
                            else
                            {
                                _log.ErrorFormat("Unità immobiliare senza proprietario principale - {0} - idUnita:{1}", Utility.GetMethodDescription(), unita.ID);
                                throw new InvalidDataException($"L'unità immobiliare {unita.Descrizione} non ha un proprietario principale");
                            }

                            foreach (var idSogg in soggCond)
                            {
                                try
                                {
                                    if (idSogg.Importo != 0)
                                    {
                                        var key = spesa.IdConto + "_" + spesa.IdUnita;
                                        if (!accorpamentoUnita)
                                            key += "_" + idSogg.Id;
                                        key += "_COND";

                                        ReportRipartizioneBilancioDTO item;
                                        if (lista.ContainsKey(key))
                                            item = lista[key];
                                        else
                                        {
                                            item = new ReportRipartizioneBilancioDTO();
                                            lista.Add(key, item);
                                            item.IdPartecipante = idSogg.Id;
                                            item.Importo = 0;
                                            item.IdConto = spesa.IdConto;
                                            item.IdStabile = unita.GruppoStabileRiferimento.PalazzinaRiferimento.ID;
                                            item.IdGruppoStabile = unita.GruppoStabileRiferimento.ID;
                                            item.IdUnitaImmobiliare = spesa.IdUnita.GetValueOrDefault();

                                            item.DisabilitaStampaMillesimi = conto.IsSpesePersonali || conto.DisabilitaMillesimiRiparto;

                                            var codice = string.Empty;
                                            if (conto.Codice != null)
                                                codice = conto.Codice;
                                            item.CodiceConto = codice;

                                            item.DescrizioneConto = !string.IsNullOrEmpty(conto.DescrizioneBilancio) && !dettaglioSottoConto
                                                                        ? conto.DescrizioneBilancio
                                                                        : conto.Descrizione;
                                            item.OrdineConto = conto.Ordine;

                                            if (dettaglioSottoConto)
                                            {
                                                var codiceSottoConto = string.Empty;
                                                var descrizioneSottoConto = string.Empty;
                                                if (sottoconto != null)
                                                {
                                                    if (!string.IsNullOrEmpty(sottoconto.Codice))
                                                        codiceSottoConto = sottoconto.Codice;
                                                    descrizioneSottoConto = sottoconto.Descrizione;
                                                }
                                                else if (spesa.IdSottoConto < 0)
                                                {
                                                    descrizioneSottoConto = item.DescrizioneConto;
                                                    codiceSottoConto = item.CodiceConto;
                                                }

                                                item.CodiceSottoConto = codiceSottoConto;
                                                item.DescrizioneSottoConto = descrizioneSottoConto;
                                                item.IdSottoConto = spesa.IdSottoConto;
                                            }

                                            item.TipoUnitaImmobiliare = unita.TipoUnitaImmobiliare.Descrizione;

                                            item.DescrizioneGruppoStabile = unita.GruppoStabileRiferimento.Descrizione;
                                            item.DescrizioneStabile = unita.GruppoStabileRiferimento.PalazzinaRiferimento.Descrizione;
                                            item.OrdineGruppoStabile = unita.GruppoStabileRiferimento.Ordine;
                                            item.OrdineStabile = unita.GruppoStabileRiferimento.PalazzinaRiferimento.Ordine;
                                            item.OrdineUnitaImmobiliare = unita.Ordine.GetValueOrDefault();
                                            item.SubalternoUnitaImmobiliare = unita.Subalterno;
                                            item.PianoUnitaImmobiliare = unita.Piano;
                                            item.InternoUnitaImmobiliare = getInternoUnitaImmobiliare(unita);
                                            item.Millesimi = spesa.ValoreMillesimo;
                                            item.UnitaMisuraMillesimi = spesa.UnitaMisuraMillesimo;

                                            if (!accorpamentoUnita)
                                            {
                                                var sogg = findSoggettoCondominio(idSogg.Id, soggetti);
                                                item.DataUscitaPartecipante = getDataUscita(sogg);
                                                item.Nominativo = sogg.DisplayName;
                                                item.IdPersona = sogg.Persona.ID;
                                            }
                                            else
                                            {
                                                item.DataUscitaPartecipante = getDataUscita(proprietarioPrincipale);
                                                item.Nominativo = proprietarioPrincipale.UnitaImmobiliare.Descrizione;
                                                item.IdPartecipante = proprietarioPrincipale.ID;
                                                item.IdPersona = proprietarioPrincipale.Persona.ID;
                                            }

                                            item.OrdinePartecipante = 20;
                                            item.TipoNominativo = "COND";
                                            item.TipoNominativoEffettivo = ripartizioneProprietarioConduttore ? "C" : findSoggettoCondominio(item.IdPartecipante, soggetti).Tipo.ToString().Substring(0, 1);

                                            item.NumeroColonne = 1;
                                        }

                                        item.Importo += idSogg.Importo;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    _log.ErrorFormat("Errore inaspettato durante la lettura del datasource per il riparto del consuntivo - SPESE CONDUTTORI - {0} - soggetto:{1} - spesa:{2} - esercizio:{3}", ex, Utility.GetMethodDescription(), idSogg.Id, spesa.ID, idEsercizio);
                                    throw;
                                }
                            }
                        }

                    }
                    catch (Exception ex)
                    {
                        _log.ErrorFormat("Errore inaspettato durante la lettura del datasource per il riparto del consuntivo - SPESE - {0} - spesa:{1} - esercizio:{2}", ex, Utility.GetMethodDescription(), spesa.ID, idEsercizio);
                        throw;
                    }
                }

                //==============================================================================================================
                //  Elaborazione SUBENTRI per avere una riga per ogni soggetto
                //==============================================================================================================
                elaboraSubentri(esercizio, accorpamentoUnita, lista, soggettiAttiviByUnitaImmobiliare, conti, dettaglioSottoConto);

                // ======================================================
                //  Rielaborazione nominativi
                // ======================================================
                elaborazioneNominativi(lista.Values);

                return lista.Values.ToList();
            }
        }
Exemple #5
0
        private void addPreventivoPerUnita(CalcoloBilancioPreventivoDTO preventivo, Esercizio esercizio, IList<ImportiDTO> importi)
        {
            var listaUnita = _daoFactory.GetUnitaImmobiliareDao().GetByCondominio(esercizio.CondominioRiferimento.ID);
            foreach (var unita in listaUnita)
            {
                try
                {
                    if (preventivo.DettaglioUnita.All(item => item.IdUnita != unita.ID))
                    {
                        var calcoloUnita = new CalcoloUnitaBilancioPreventivoDTO
                        {
                            Descrizione = unita.Descrizione,
                            IdTestata = preventivo.ID,
                            IdUnita = unita.ID,
                            Ordine = unita.Ordine.GetValueOrDefault()
                        };

                        if (esercizio.GetEsercizioPrecedente() != null && importi != null)
                        {
                            // Consuntivo anno precedente
                            var unita1 = unita;
                            var importoDTO = (importi.Where(importo => importo.Id == unita1.ID)).SingleOrDefault();
                            if (importoDTO != null)
                                calcoloUnita.ImportoConsuntivo = importoDTO.Importo;

                            // Per ora evito di proporre un importo in base al consuntivo o preventivo dell'anno precedente
                            //// Preventivo attuale proposto
                            //if (variazione != null)
                            //{
                            //    if (riferimentoVariazione == TipoRendiconto.Consuntivo && calcoloUnita.ImportoConsuntivo != null)
                            //        calcoloUnita.ImportoPreventivo = calcoloUnita.ImportoConsuntivo + ((calcoloUnita.ImportoConsuntivo * variazione) / 100);
                            //    else if (riferimentoVariazione == TipoRendiconto.Preventivo && calcoloUnita.ImportoPreventivoAnnoPrecedente != null)
                            //        calcoloUnita.ImportoPreventivo = calcoloUnita.ImportoPreventivoAnnoPrecedente + ((calcoloUnita.ImportoPreventivoAnnoPrecedente * variazione) / 100);
                            //}
                        }

                        preventivo.DettaglioUnita.Add(calcoloUnita);
                    }
                }
                catch (Exception ex)
                {
                    _log.ErrorFormat("Errore inaspettato durante la creazione della lista per l'inserimento dei valori di preventivo - CALCOLO PREVENTIVO PER SOTTOCONTO - SPESE PERSONALI - {0} - idEsercizio:{1} - conto:{2} - sottoconto:{3}", ex, Utility.GetMethodDescription(), esercizio.ID, preventivo.IdConto, preventivo.IdSottoConto);
                    throw;
                }
            }        
        }