示例#1
0
 /// <summary>
 /// Crea una rata di pagamento condomino valida.
 /// </summary>
 public VersamentiRate(VersamentoSoggetto versamento, RataSoggetto rata, decimal importo)
 {
     Versamento = versamento;
     Rata = rata;
     Importo = importo;
     if (Rata != null)
         Rata.Versamenti.Add(this);
     if (Versamento != null)
         Versamento.Rate.Add(this);
 }
        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;
        }
        private VersamentoSoggettoDTO setDto(VersamentoSoggetto item, bool rate)
        {
            try
            {
                var dto = new VersamentoSoggettoDTO
                {
                    ID = item.ID,
                    Version = item.Version,
                    IdEsercizio = item.Esercizio.ID,
                    DescrizioneEsercizio = item.Esercizio.DisplayName,
                    IdCondominio = item.Esercizio.CondominioRiferimento.ID,
                    Condominio = item.Esercizio.CondominioRiferimento.DisplayName,
                    Importo = item.Importo,
                    DataPagamento = item.Data,
                    NumeroAssegno = item.NumeroAssegno,
                    NumeroProtocollo = item.NumeroProtocollo,
                    Causale = item.Causale,
                    Nota = item.Nota,
                    IsDeleteAllow = item.Esercizio.Stato != StatoEsercizioEnum.Chiuso,
                    IdSoggetto = item.Soggetto.ID,
                    IdPersona = item.Soggetto.Persona.ID,
                    DescrizioneSoggetto = item.Soggetto.DisplayName,
                    IdUnitaImmobiliare = item.Soggetto.UnitaImmobiliare.ID,
                    DescrizioneUnitaImmobiliare = item.Soggetto.UnitaImmobiliare.Descrizione,
                    OrdineUnitaImmobiliare = item.Soggetto.UnitaImmobiliare.Ordine.GetValueOrDefault(),
                    TipoUnitaImmobiliare = item.Soggetto.UnitaImmobiliare.TipoUnitaImmobiliare.Descrizione,
                    Interno = item.Soggetto.UnitaImmobiliare.InternoCompleto,
                    Scala = item.Soggetto.UnitaImmobiliare.GruppoStabileRiferimento.Descrizione,
                    DisplayName = item.Soggetto.DisplayName,
                    Tipo = item.Tipo.ToString(),
                    NumeroDocumenti = item.Documenti.Count,
                    TipoVersamentoDopoChiusura = item.TipoVersamentoDopoChiusura,
                    TipoVersamentoPrimaApertura = item.TipoVersamentoPrimaApertura,
                    IsAllowUpdate = getVersamentiCondominiService().IsAllowUpdate(item).FatalMessage 
                };

                if (item.MovimentoContabilePatrimoniale != null)
                {
                    dto.IdMovimentoContabile = item.MovimentoContabilePatrimoniale.ID;
                    dto.IdTestataMovimentoContabile = item.MovimentoContabilePatrimoniale.Testata.ID;
                    dto.IdConto = item.MovimentoContabilePatrimoniale.ContoRiferimento.ID;
                    if (item.MovimentoContabilePatrimoniale.SottoContoRiferimento != null)
                        dto.IdSottoConto = item.MovimentoContabilePatrimoniale.SottoContoRiferimento.ID;
                    else if (item.MovimentoContabilePatrimoniale.ContoCorrenteBancario != null && item.MovimentoContabilePatrimoniale.ContoRiferimento.Codice == getPianoContiService().GetCodiceContoBancario())
                        dto.IdSottoConto = item.MovimentoContabilePatrimoniale.ContoCorrenteBancario.ID * -1;

                    if (item.MovimentoContabilePatrimoniale.EvasioneBancaria != null)
                        dto.IdEvasioneBancaria = item.MovimentoContabilePatrimoniale.EvasioneBancaria.ID;
                }

                if (item.File != null)
                    dto.IdFileCbi = item.File.ID;

                if (item.SoggettoEffettivo != null)
                {
                    dto.IdSoggettoEffettivo = item.SoggettoEffettivo.ID;
                    dto.DescrizioneSoggettoEffettivo = item.SoggettoEffettivo.DisplayName;
                }
                
                // Richiesto dettaglio rate .....
                if (item.Rate.Count > 0 && rate)
                {
                    decimal importoVersamentoRate = 0;
                    foreach (var versamento in item.Rate)
                    {
                        var rata = new RataVersamentoDTO
                        {
                            DataScadenza = versamento.Rata.DataScadenza,
                            Descrizione = versamento.Rata.PianoRatealeDettaglio.Descrizione,
                            IdRata = versamento.Rata.ID,
                            ImportoRata = versamento.Rata.Importo,
                            ImportoVersamento = versamento.Importo,
                            StatoRata = versamento.Rata.Stato
                        };

                        dto.Rate.Add(rata);
                        importoVersamentoRate += rata.ImportoVersamento;
                    }

                    dto.IdRataPrincipale = dto.Rate[0].IdRata;
                    dto.DescrizioneRata = dto.Rate[0].Descrizione;

                    // Se il versamento supera l'importo delle rate è stato registrato il residuo fuori piano rateale
                    if (dto.Importo > importoVersamentoRate)
                    {
                        dto.Rate.Add(new RataVersamentoDTO
                        {
                            IdRata = 0,
                            DataScadenza = null,
                            Descrizione = "Versamento fuori piano rateale",
                            ImportoRata = 0,
                            ImportoVersamento = dto.Importo - importoVersamentoRate,
                            StatoRata = StatoRataEnum.Inserita,
                        });
                    }
                }
                // .... il dettaglio rate non è richiesto, compongo solo la descrizione
                else
                {
                    if (item.Rate.Count > 0)
                    {
                        foreach (var versamentoRate in item.Rate)
                        {
                            if (!string.IsNullOrEmpty(dto.DescrizioneRata))
                                dto.DescrizioneRata += " - ";
                            dto.DescrizioneRata += versamentoRate.Rata.PianoRatealeDettaglio.Descrizione;
                        }
                    }
                    else
                        dto.DescrizioneRata = "Versamento fuori piano rateale";
                }

                return dto;
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato nella conversione in DTO - {0} - id:{1}", ex, Library.Utility.GetMethodDescription(), item.ID);
                throw;
            }
        }
 public VersamentoSoggettoDTO GetByDomainEntity(VersamentoSoggetto item)
 {
     try
     {
         return setDto(item, true);
     }
     catch (Exception ex)
     {
         _log.ErrorFormat("Errore nel caricamento dei versamenti dei condomini - {0} - id:{1}", ex, Library.Utility.GetMethodDescription(), item.ID);
         throw;
     }
 }
        public IList<ResultVersamento> InsertVersamentoByPersona(int idEsercizio, int idConto, int? idSottoConto, DateTime dataVersamento, string numeroAssegno, string causale, string nota, int? idMovimentoBancario, List<RataPersonaDTO> rate, LogTransazione logTransazione, TipoVersamentoDopoChiusuraEnum? tipoVersamentoDopoChiusura, TipoVersamentoPrimaAperturaEnum? tipoVersamentoPrimaApertura)
        {
            var message = string.Empty;

            TestataMovimentoContabile testata = null;
            MovimentoContabile movimentoPatrimoniale = null;
            var result = new List<ResultVersamento>();
            try
            {
                var esercizio = _daoFactory.GetEsercizioDao().GetById(idEsercizio, false);

                // ------------------------------------------------------
                //  Trovo l'esercizio contabile, se  non è esiste oppure se è chiuso
                //  interrompo l'operazione di versamento
                // ------------------------------------------------------
                var esercizioContabile = esercizio;
                if (esercizio.Gestione == GestioneEsercizioEnum.Ordinario)
                {
                    esercizioContabile = _daoFactory.GetEsercizioDao().GetEsercizioCompetenza(esercizio.CondominioRiferimento, dataVersamento);
                    if (esercizioContabile == null || esercizioContabile.Stato == StatoEsercizioEnum.Chiuso)
                    {
                        var messageEsercizio = esercizioContabile == null ? "l'esercizio di competenza non è ancora stato aperto" : $"l'esercizio '{esercizioContabile.DisplayName}' è chiuso";
                        return new List<ResultVersamento> { new ResultVersamento(null, null, null, null, null, $"Non è possibile registrare il versamento in data {dataVersamento.ToShortDateString()} perchè {messageEsercizio}.")};
                    }
                }

                // La richiesta del versamento può avvenire solo se il versamento è successivo alla data di chiusura dell'esercizio
                if (dataVersamento <= esercizio.DataChiusura.GetValueOrDefault())
                    tipoVersamentoDopoChiusura = null;

                var listaRate = rate.Where(item => item.Selezionabile && item.ImportoVersamento > 0)
                        .GroupBy(item => item.IdSoggetto)
                        .Select(rateSoggetto => rateSoggetto);

                foreach (var ratePerSoggetto in listaRate)
                {
                    var importo = ratePerSoggetto.Sum(item => item.ImportoVersamento.GetValueOrDefault());

                    // ========================================================
                    //  Creo il versamento e i relativi movimenti economici
                    // ========================================================
                    var progressivo = _protocolloService.GetProgressivo(TipoProtocollo.VersamentoCondomino, esercizio);
                    if (progressivo.Progressivo == null)
                    {
                        var resultVersamenti = new List<ResultVersamento> {new ResultVersamento(null, null, null, null, null, progressivo.Message)};
                        return resultVersamenti;
                    }

                    var protocollo = progressivo.Progressivo;
                    var versamento = new VersamentoSoggetto(esercizio, _daoFactory.GetSoggettoCondominioDao().GetById(ratePerSoggetto.Key, false), _daoFactory.GetContoDao().GetById(idConto, false), dataVersamento, importo, protocollo.Value, TipoVersamentoSoggettoEnum.Manuale, logTransazione, tipoVersamentoDopoChiusura, tipoVersamentoPrimaApertura) {NumeroAssegno = numeroAssegno, Causale = causale, Nota = nota};

                    if (idSottoConto != null)
                    {
                        if (idSottoConto > 0)
                            versamento.SottoContoPatrimoniale = _daoFactory.GetSottoContoDao().GetById(idSottoConto.Value, false);
                        else if (idSottoConto < 0)
                            versamento.ContoBancario = _daoFactory.GetDatiBancariCondominiDao().GetById(idSottoConto.Value * -1, false);
                    }

                    var rateDaEmettere = new List<RataSoggetto>();
                    if (rate != null)
                    {
                        foreach (var rataDto in ratePerSoggetto)
                        {
                            if (rataDto.ID > 0)
                            {
                                var rata = _daoFactory.GetRataSoggettoDao().GetById(rataDto.ID, false);
                                var versamentoRata = new VersamentiRate(versamento, rata, rataDto.ImportoVersamento.GetValueOrDefault());

                                // ----------------------------------------------------
                                // Se la rata non è stata emessa devo creare movimento
                                // ----------------------------------------------------
                                if (rata.Stato == StatoRataEnum.Inserita)
                                    rateDaEmettere.Add(rata);
                                rata.SetStato();
                            }
                        }
                    }

                    var testateContabili = _movimentoContabileService.SetMovimentiVersamentoCondomino(testata, movimentoPatrimoniale, esercizioContabile, versamento, versamento.Data, null, null, idMovimentoBancario, null, logTransazione);
                    testata = testateContabili[0];
                    setRataVersamentoDopoChiusura(versamento, esercizioContabile, logTransazione);

                    // Salvataggi
                    _daoFactory.GetVersamentoSoggettoDao().SaveOrUpdate(versamento);

                    var testateMovimenti = testata.Movimenti.Where(item => item.ContoRiferimento.ID == versamento.ContoPatrimoniale.ID).ToList();
                    if (testateMovimenti.Count > 1)
                        _log.ErrorFormat("ATTENZIONE: Trovato più di una testata di movimento - {0} - versamento:{1} - conto:{1} - testate:{2}", Utility.GetMethodDescription(), versamento.ID, versamento.ContoPatrimoniale.ID, testateMovimenti.Aggregate(string.Empty, (current, movimentoContabile) => current + movimentoContabile.ID));

                    movimentoPatrimoniale = testateMovimenti.FirstOrDefault();
                    int? idMovimentoPatrimoniale = null;
                    if (movimentoPatrimoniale != null)
                        idMovimentoPatrimoniale = movimentoPatrimoniale.ID;

                    result.Add(new ResultVersamento(setVersamentoRicevutaDTO(versamento), versamento.ID, protocollo, idMovimentoPatrimoniale, getDescrizioneVersamentoConfermato(versamento), message));
                }
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato nel metodo - {0} - esercizio:{1} - conto:{2} - sottoconto:{3} - dataVersamento:{4} - numeroAssegno:{5} - causale:{6}", ex, Utility.GetMethodDescription(), idEsercizio, idConto, idSottoConto.GetValueOrDefault(), dataVersamento, numeroAssegno, causale);
                throw;
            }

            return result;
        }
        private MovimentoContabile getMovimentoContabileEconomico(VersamentoSoggetto versamento)
        {
            MovimentoContabile movimentoEconomico = null;
            if (versamento.MovimentoContabilePatrimoniale != null)
                movimentoEconomico = versamento.MovimentoContabilePatrimoniale.Testata.Movimenti.FirstOrDefault(item => item.Segno == "A" && item.Importo == versamento.Importo && (item.CondominoRiferimento == null || item.CondominoRiferimento.ID == versamento.Soggetto.ID));

            return movimentoEconomico;
        }
        public ResultVersamento InsertVersamentoCondomino(int idEsercizio, int idSoggetto, int idConto, int? idSottoConto, DateTime dataVersamento, decimal importo, string numeroAssegno, string causale, string nota, int? idMovimentoBancario, List<RataSoggettoVersataDTO> rate, LogTransazione logTransazione, TipoVersamentoDopoChiusuraEnum? tipoVersamentoDopoChiusura = null, TipoVersamentoPrimaAperturaEnum? tipoVersamentoPrimaApertura = null)
        {
            int? protocollo = null;
            int? idMovimentoContabile = null;
            int? idVersamento = null;
            var message = string.Empty;
            var descrizione = string.Empty;
            VersamentoSoggetto versamento = null;

            try
            {
                var contoPatrimoniale = _daoFactory.GetContoDao().Find(idConto, false);
                if(contoPatrimoniale == null)
                    return new ResultVersamento(null, null, null, null, null, "Non è stato trovato il conto patrimoniale (banca/cassa) selezionato.");

                // ========================================================
                //  Creo il versamento e i relativi movimenti economici
                // ========================================================
                var esercizio = _daoFactory.GetEsercizioDao().GetById(idEsercizio, false);

                var soggetto = _daoFactory.GetSoggettoCondominioDao().Find(idSoggetto, false);
                if(soggetto == null)
                    return new ResultVersamento(null, null, null, null, null, "Il condomino non è più presente in archivio");

                // ------------------------------------------------------
                //  Trovo l'esercizio contabile, se  non è esiste oppure se è chiuso
                //  interrompo l'operazione di versamento
                // ------------------------------------------------------
                var esercizioContabile = esercizio;
                if (esercizio.Gestione == GestioneEsercizioEnum.Ordinario)
                {
                    esercizioContabile = _daoFactory.GetEsercizioDao().GetEsercizioCompetenza(esercizio.CondominioRiferimento, dataVersamento);
                    if (esercizioContabile == null || esercizioContabile.Stato == StatoEsercizioEnum.Chiuso)
                    {
                        var messageEsercizio = esercizioContabile == null ? "l'esercizio di competenza non è ancora stato aperto" : $"l'esercizio '{esercizioContabile.DisplayName}' è chiuso";
                        return new ResultVersamento(null, null, null, null, null, $"Non è possibile registrare il versamento in data {dataVersamento.ToShortDateString()} perchè {messageEsercizio}.");
                    }
                }
                
                var progressivo = _protocolloService.GetProgressivo(TipoProtocollo.VersamentoCondomino, esercizio);

                // La richiesta del versamento può avvenire solo se il versamento è successivo alla data di chiusura dell'esercizio
                if (dataVersamento <= esercizio.DataChiusura.GetValueOrDefault())
                    tipoVersamentoDopoChiusura = null;

                if (progressivo.Progressivo == null)
                    message = progressivo.Message + string.Empty;
                else
                {
                    protocollo = progressivo.Progressivo;

                    versamento = new VersamentoSoggetto(esercizio, soggetto, contoPatrimoniale, dataVersamento, importo, protocollo.Value, TipoVersamentoSoggettoEnum.Manuale, logTransazione, tipoVersamentoDopoChiusura, tipoVersamentoPrimaApertura) {NumeroAssegno = numeroAssegno, Causale = causale, Nota = nota};

                    if (idSottoConto != null)
                    {
                        if (idSottoConto > 0)
                            versamento.SottoContoPatrimoniale = _daoFactory.GetSottoContoDao().GetById(idSottoConto.Value, false);
                        else if (idSottoConto < 0)
                            versamento.ContoBancario = _daoFactory.GetDatiBancariCondominiDao().GetById(idSottoConto.Value * -1, false);
                    }

                    var testateContabili = _movimentoContabileService.SetMovimentiVersamentoCondomino(null, null, esercizioContabile, versamento, versamento.Data, null, null, idMovimentoBancario, null, logTransazione);
                    var versamentiRate = setRataVersamentoDopoChiusura(versamento, esercizioContabile, logTransazione);

                    if (rate != null)
                    {
                        foreach (var rataDto in rate)
                        {
                            if (rataDto.IdRata > 0)
                            {
                                var rata = _daoFactory.GetRataSoggettoDao().Find(rataDto.IdRata, false);
                                if(rata != null)
                                {
                                    var versamentoRata = new VersamentiRate(versamento, rata, rataDto.ImportoVersamento);
                                    rata.SetStato();
                                }
                            }
                        }
                    }

                    _daoFactory.GetVersamentoSoggettoDao().SaveOrUpdate(versamento);

                    idVersamento = versamento.ID;
                    idMovimentoContabile = versamento.MovimentoContabilePatrimoniale.ID;
                    descrizione = getDescrizioneVersamentoConfermato(versamento);
                }
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato nel metodo: {0} - esercizio:{1} - conto:{1} - sottoconto:{2} - soggetto:{3} - dataVersamento:{4:d} - importo:{5} - numeroAssegno:{6} - causale:{7}", ex, Utility.GetMethodDescription(), idEsercizio, idConto, idSottoConto.GetValueOrDefault(), idSoggetto, dataVersamento, importo, numeroAssegno, causale);
                throw;
            }

            return new ResultVersamento(setVersamentoRicevutaDTO(versamento), idVersamento, protocollo, idMovimentoContabile, descrizione, message);
        }
 private string getDescrizioneVersamentoConfermato(VersamentoSoggetto versamento)
 {
     return versamento.Importo.ToString("c") + " - Rate Unità Immobiliare:" + versamento.Soggetto.UnitaImmobiliare.Ordine + " - Tipo:" + versamento.Soggetto.UnitaImmobiliare.TipoUnitaImmobiliare.Descrizione;
 }
        //private VersamentiRate setRataVersamentoPrimaApertura(VersamentoSoggetto versamento, Esercizio esercizio, LogTransazione logTransazione)
        //{
        //    VersamentiRate rataVersamento = null;
        //    LogTransazione logTransazioneRata = null;
        //    if (esercizio.Gestione == GestioneEsercizioEnum.Ordinario && esercizio.Stato == StatoEsercizioEnum.Aperto && versamento.TipoVersamentoPrimaApertura == TipoVersamentoPrimaAperturaEnum.RicEsPrec)
        //    {
        //        var pianoRatealeDettaglio = _daoFactory.GetPianoRatealeDettaglioDao().GetRataVersamentoPrimaApertura(esercizio);
        //        if (pianoRatealeDettaglio == null)
        //        {
        //            var pianoRateale = _daoFactory.GetPianoRatealeDao().GetByEsercizio(esercizio);
        //            LogTransazione logTransazioneDettaglio = null;
        //            if (pianoRateale == null)
        //                pianoRateale = new PianoRateale(esercizio, TipoAccorpamentoRateEnum.Nessuno, logTransazione);
        //            else
        //                logTransazioneDettaglio = logTransazione;
        //            pianoRatealeDettaglio = new PianoRatealeDettaglio(pianoRateale, esercizio.DataChiusura, null, 0, false, logTransazioneDettaglio)
        //            {
        //                Descrizione = "Versamenti eseguiti prima della apertura",
        //                IsAcconto = true,
        //                VersamentiDopoChiusura = true
        //            };
        //        }
        //        else
        //            logTransazioneRata = logTransazione;

        //        var rataSoggetto = new RataSoggetto(pianoRatealeDettaglio, versamento.Soggetto, versamento.Data, versamento.Importo, logTransazioneRata);
        //        rataVersamento = new VersamentiRate(versamento, rataSoggetto, versamento.Importo);
        //        rataSoggetto.SetStato();
        //    }

        //    return rataVersamento;
        //}

        private VersamentoSoggettoRicevutaDTO setVersamentoRicevutaDTO(VersamentoSoggetto versamento)
        {
            if (versamento != null)
            {
                var condominio = versamento.Esercizio.CondominioRiferimento;

                var banca = versamento.ContoBancario ?? condominio.DatiBancariPrincipale;
                var abiCab = new AbiCab(null);
                if (banca != null)
                    abiCab = _daoFactory.GetAbiCabDao().GetByAbiCab(banca.Abi, banca.Cab);

                var dto = new VersamentoSoggettoRicevutaDTO
                {
                    ID = versamento.ID,
                    Banca = abiCab != null ?
                        $"{abiCab.DescrizioneAbi} - {abiCab.DescrizioneCab} - {(banca != null ? banca.DisplayName : "<N.D.>")}"
                        : string.Empty,
                    Causale = versamento.Causale,
                    CodiceNominativoVersamento = versamento.Soggetto.UnitaImmobiliare.InternoCompleto,
                    NominativoVersamento = versamento.Soggetto.DisplayName,
                    OrdineNominativoVersamento = versamento.Soggetto.UnitaImmobiliare.Ordine.GetValueOrDefault(),
                    IdCondominio = condominio.ID,
                    DescrizioneCondominio = "CONDOMINIO " + condominio.Descrizione,
                    IdEsercizio = versamento.Esercizio.ID,
                    Data = versamento.Data,
                    CoordinateBancarie = banca != null ? banca.Iban : "<N.D.>",
                    Importo = versamento.Importo,
                    ImportoLettere = CifreLettere.CalcolaLettere(versamento.Importo),
                    NominativoAmministratore = condominio.Azienda.Amministratore != null ? condominio.Azienda.Amministratore.DisplayName : string.Empty,
                    NumeroRicevuta = versamento.NumeroProtocollo
                };

                if (!string.IsNullOrEmpty(versamento.Nota))
                    dto.NominativoVersamento += " (" + versamento.Nota.Trim() + ")";

                return dto;
            }

            return null;
        }
        private VersamentiRate setRataVersamentoDopoChiusura(VersamentoSoggetto versamento, Esercizio esercizio, LogTransazione logTransazione)
        {
            VersamentiRate rataVersamento = null;
            LogTransazione logTransazioneRata = null;
            if (esercizio.Gestione == GestioneEsercizioEnum.Ordinario && esercizio.Stato == StatoEsercizioEnum.Aperto && versamento.TipoVersamentoDopoChiusura == TipoVersamentoDopoChiusuraEnum.RicEsSucc)
            {
                var pianoRatealeDettaglio = _daoFactory.GetPianoRatealeDettaglioDao().GetRataVersamentoDopoChiusura(esercizio);
                if (pianoRatealeDettaglio == null)
                {
                    var pianoRateale = _daoFactory.GetPianoRatealeDao().GetByEsercizio(esercizio);
                    LogTransazione logTransazioneDettaglio = null;
                    if (pianoRateale == null)
                        pianoRateale = new PianoRateale(esercizio, TipoAccorpamentoRateEnum.Nessuno, logTransazione);
                    else
                        logTransazioneDettaglio = logTransazione;
                    pianoRatealeDettaglio = new PianoRatealeDettaglio(pianoRateale, esercizio.DataApertura, null, 0, false, logTransazioneDettaglio)
                    {
                        Descrizione = "Versamenti eseguiti dopo la chiusura",
                        IsAcconto = true,
                        VersamentiDopoChiusura = true
                    };
                }
                else
                    logTransazioneRata = logTransazione;

                var rataSoggetto = new RataSoggetto(pianoRatealeDettaglio, versamento.Soggetto, versamento.Data, versamento.Importo, logTransazioneRata);
                rataVersamento = new VersamentiRate(versamento, rataSoggetto, versamento.Importo);
                rataSoggetto.SetStato();
            }

            return rataVersamento;
        }
        public AuthorizationMessages IsAllowUpdate(VersamentoSoggetto versamento)
        {
            var fatalMessage = string.Empty;
            var warnMessage = string.Empty;

            try
            {
                if (versamento != null)
                {
                    if (versamento.Esercizio.Stato == StatoEsercizioEnum.Chiuso)
                        fatalMessage += "Il versamento è relativo ad un esercizio chiuso" + Environment.NewLine;
                    if(versamento.TestataMovimentoDopoChiusura != null && versamento.TestataMovimentoDopoChiusura.EsercizioRiferimento.Stato == StatoEsercizioEnum.Chiuso)
                        fatalMessage += string.Format("Il movimento è stato registrato automaticamente in relazione a versamenti effettuati dopo la chiusura dell'esercizio.{0}L'esercizio di riferimento è chiuso{0}", Environment.NewLine);
                    if (versamento.MovimentoContabilePatrimoniale != null)
                    {
                        if (versamento.MovimentoContabilePatrimoniale.Testata.EsercizioRiferimento.Stato == StatoEsercizioEnum.Chiuso)
                            fatalMessage += "Il versamento è associato ad un movimento contabile relativo ad un esercizio chiuso" + Environment.NewLine;
                        if(_movimentoContabileService.IsAllowDataRegistrazione(new[] { versamento.Esercizio.CondominioRiferimento.ID }, null, versamento.MovimentoContabilePatrimoniale.Testata.DataRegistrazione.GetValueOrDefault()).Count > 0)
                            fatalMessage += "Il versamento è associato ad un movimento contabile relativo ad un esercizio chiuso" + Environment.NewLine;
                    }
                }

            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore nel controllo di autorizzazione di aggiornamento di un versamento - {0} - versamento:{1}", ex, Utility.GetMethodDescription(), versamento?.ID.ToString(CultureInfo.InvariantCulture) ?? "<NULL>");
                throw;
            }

            return new AuthorizationMessages(fatalMessage, warnMessage);
        }
        public ResultVersamento InsertVersamentoCondomino(Esercizio esercizio, RataSoggetto rata, DatiBancariCondomini banca, Conto contoBancario, CausaleContabile causaleVersamento, Conto contoVersamentoCondomini, DateTime dataVersamento, FileCBI file, LogTransazione logTransazione, TipoVersamentoDopoChiusuraEnum? tipoVersamentoDopoChiusura = null, TipoVersamentoPrimaAperturaEnum? tipoVersamentoPrimaApertura = null)
        {
            int? protocollo = null;
            int? idMovimentoContabile = null;
            var message = string.Empty;
            var descrizione = string.Empty;
            VersamentoSoggetto versamento = null;

            // La richiesta del versamento può avvenire solo se il versamento è successivo alla data di chiusura dell'esercizio
            if (dataVersamento <= esercizio.DataChiusura.GetValueOrDefault())
                tipoVersamentoDopoChiusura = null;

            // La richiesta del versamento prima dell'apertura può avvenire solo se il versamento è precedente alla data di apertura dell'esercizio
            if (dataVersamento >= esercizio.DataApertura.GetValueOrDefault())
                tipoVersamentoPrimaApertura = null;
            try
            {
                // ----------------------------------------------------
                //  Creo Versamento
                // ----------------------------------------------------
                if (string.IsNullOrEmpty(message))
                {
                    var progressivo = _protocolloService.GetProgressivo(TipoProtocollo.VersamentoCondomino, esercizio);
                    if (progressivo.Progressivo != null)
                    {
                        protocollo = progressivo.Progressivo;

                        // ------------------------------------------------------
                        //  Trovo l'esercizio contabile, se non esiste oppure se è chiuso
                        //  interrompo l'operazione di versamento
                        // ------------------------------------------------------
                        var esercizioContabile = esercizio;
                        if (esercizioContabile.Gestione == GestioneEsercizioEnum.Ordinario || (esercizioContabile.Gestione == GestioneEsercizioEnum.Straordinario && (esercizioContabile.Stato == StatoEsercizioEnum.Chiuso || esercizioContabile.DataChiusura.GetValueOrDefault() < dataVersamento)))
                        {
                            esercizioContabile = _daoFactory.GetEsercizioDao().GetEsercizioCompetenza(esercizio.CondominioRiferimento, dataVersamento);
                            if (esercizioContabile == null || esercizioContabile.Stato == StatoEsercizioEnum.Chiuso)
                            {
                                var messageEsercizio = esercizioContabile == null ? "l'esercizio di competenza non è ancora stato aperto" : $"l'esercizio '{esercizioContabile.DisplayName}' è chiuso";
                                return new ResultVersamento(null, null, null, null, null, $"Non è possibile registrare il versamento in data {dataVersamento.ToShortDateString()} perchè {messageEsercizio}.");
                            }
                        }

                        try
                        {
                            versamento = new VersamentoSoggetto(esercizio, rata.Soggetto, contoBancario, dataVersamento, rata.Importo, file, banca, logTransazione, tipoVersamentoDopoChiusura, tipoVersamentoPrimaApertura);
                            _movimentoContabileService.SetMovimentiVersamentoCondomino(null, null, esercizioContabile, versamento, dataVersamento, causaleVersamento, contoVersamentoCondomini, null, file, logTransazione);
                        }
                        catch (InvalidDataException exception)
                        {
                            _log.ErrorFormat("Errore inaspettato nella registrazione del versamento del condomino - {0} - esercizio:{1} - rata:{2}", Utility.GetMethodDescription(), esercizioContabile.ID, rata.ID);
                            if (versamento != null)
                            {
                                if (logTransazione != null)
                                {
                                    logTransazione.Versamenti.Remove(versamento);
                                    versamento.LogTransazione = null;
                                }

                                if (file != null)
                                {
                                    file.Versamenti.Remove(versamento);
                                    versamento.File = null;
                                }

                                esercizio.VersamentiCondomini.Remove(versamento);
                                versamento.Esercizio = null;

                                rata.Soggetto.Versamenti.Remove(versamento);
                                versamento.Soggetto = null;

                                versamento = null;
                            }
                            return new ResultVersamento(null, null, null, null, null, $"Non è possibile registrare il versamento in data {dataVersamento.ToShortDateString()} perchè {exception.Message}.");
                        }
                        
                        setRataVersamentoDopoChiusura(versamento, esercizioContabile, logTransazione);

                        // ---------------------------------------------------------------------
                        // Se la rata non è ancora stata pagata associo il versamento alla rata
                        // ---------------------------------------------------------------------
                        // se la rata è già stata pagata, oppure se l'esercizio di riferimento è chiuso viene registrata come rata fuori piano rateale
                        if (rata.Stato != StatoRataEnum.Pagata && rata.Stato != StatoRataEnum.ParzialmentePagata && rata.Esercizio.Stato == StatoEsercizioEnum.Aperto )
                        {
                            var versamentoRata = new VersamentiRate(versamento, rata, rata.Importo);
                            rata.SetStato();
                        }
                        else
                        {
                            versamento.Causale = $"Versamento fuori piano rateale perchè la rata si trova in stato di {rata.Stato}";
                        }

                        idMovimentoContabile = versamento.MovimentoContabilePatrimoniale.ID;
                        descrizione = getDescrizioneVersamentoConfermato(versamento);
                    }
                    else
                        message += progressivo.Message + Environment.NewLine;
                }
            }
            catch (Exception ex)
            {
                _log.ErrorFormat("Errore inaspettato nel metodo: {0} - rata:{1} - dataVersamento:{2}", ex, Utility.GetMethodDescription(), rata.ID, dataVersamento);
                throw;
            }

            return new ResultVersamento(setVersamentoRicevutaDTO(versamento), null, protocollo, idMovimentoContabile, descrizione, message);
        }