view Agendas/trunk/src/Agendas.Domain/Agenda.cs @ 285:c8f378272407

#123: Patrocinadores de las vans.
author juanjose.montesdeocaarbos
date Sat, 31 Dec 2011 14:45:55 -0300
parents 79942e030118
children
line wrap: on
line source

using System;
using System.Collections.Generic;
using System.Linq;
using AltNetHispano.Agendas.Domain.Exceptions;
using AltNetHispano.Agendas.Domain.Repositories;

namespace AltNetHispano.Agendas.Domain
{
	public class Agenda
	{
		private readonly IEventoRepository _eventosRepository;
		private readonly IPersonaRepository _personaRepository;
		private readonly IPatrocinadorRepository _patrocinadorRepository;

		private readonly IPublicador _publicador;

		public Agenda(IPublicador publicador, IEventoRepository eventosRepository,
					  IPersonaRepository personaRepository, IPatrocinadorRepository patrocinadorRepository)
		{
			_publicador = publicador;
			_patrocinadorRepository = patrocinadorRepository;
			_personaRepository = personaRepository;
			_eventosRepository = eventosRepository;
		}

		public Evento GetEvento(Guid eventoId)
		{
			Evento evento = _eventosRepository.Get(eventoId);
			if (evento == null)
				throw new EventoNotFoundException(eventoId);
			return evento;
		}

		public IList<Evento> GetEventosActivos(EventoState state)
		{
			return _eventosRepository.GetByState(state) ?? new List<Evento>();
		}

		public IList<Evento> GetEventosActivos()
		{
			return _eventosRepository.GetActivos() ?? new List<Evento>();
		}

		public IEnumerable<Evento> GetHistorico()
		{
			return _eventosRepository.GetByState(EventoPublicadoState.GetInstance()) ?? new List<Evento>();
		}

		public EventoResultado ModificarEvento(Guid eventoId, string titulo, IEnumerable<Guid> ponentesId, DateTime? fechaInicio, DateTime? fechaTermino, string urlInvitacion)
		{
			Evento evento = GetEvento(eventoId);

			if (evento.Tipo == TipoEvento.Van && (ponentesId == null || !ponentesId.Any(id => id != Guid.Empty)))
				return new EventoResultado(false, "Debe indicar el ponente para este tipo de evento", null);

			if (evento.Titulo != titulo)
				evento.CambiarTitulo(titulo);

			if (evento.FechaInicio == null && fechaInicio != null && evento.FechaTermino == null && fechaTermino != null)
				evento.Agendar(fechaInicio, fechaTermino, urlInvitacion);
			else if (evento.FechaInicio != fechaInicio || evento.UrlInvitacion != urlInvitacion || evento.FechaTermino != fechaTermino)
				evento.Actualizar(fechaInicio, fechaTermino, urlInvitacion);

			var r = ActualizarPonentes(evento, ponentesId, Accion.Modificar);
			if (!r.Succeful) return r;

			Notify(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento modificado", warnings);
		}

		public EventoResultado ModificarPropuesta(Guid id, string titulo, IEnumerable<Guid> ponentesId, string urlInvitacion)
		{
			return ModificarEvento(id, titulo, ponentesId, null, null, urlInvitacion);
		}

		public EventoResultado Proponer(string titulo, IEnumerable<Guid> ponentesId, string urlInvitacion, TipoEvento tipo)
		{
			if (string.IsNullOrWhiteSpace(titulo))
				return new EventoResultado(false, "Debe indicar el título del evento", null);

			var evento = Evento.Proponer(titulo, urlInvitacion, tipo);

			var r = ActualizarPonentes(evento, ponentesId, null);
			if (!r.Succeful) return r;

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento propuesto", warnings);
		}

		public EventoResultado Agendar(string titulo, IEnumerable<Guid> ponentesId, DateTime? fechaInicio, DateTime? fechaTermino, string urlInvitacion, TipoEvento tipo)
		{
			if (!fechaInicio.HasValue)
				return new EventoResultado(false, "Debe indicar la fecha", null);
			if (!fechaTermino.HasValue)
				return new EventoResultado(false, "Debe indicar la hora y duración", null);
			if (tipo == TipoEvento.Van && (ponentesId == null || !ponentesId.Any(id => id != Guid.Empty)))
				return new EventoResultado(false, "Debe indicar el ponente para este tipo de evento", null);

			var existeOtroEvento = _eventosRepository.GetNoPropuestoByTitulo(titulo);
			if (existeOtroEvento != null)
				return new EventoResultado(false,
										   string.Format(
											   "Ya existe un evento con el mismo título ({0}) del {1}, por favor ingrese otro.",
											   titulo, existeOtroEvento.FechaInicio.Value.ToShortDateString()), null);

			Evento evento = _eventosRepository.GetPropuestaByTitulo(titulo);

			foreach (var e in _eventosRepository.GetActivos())
			{
				if (!e.Equals(evento) && fechaInicio <= e.FechaTermino && fechaTermino >= e.FechaInicio)
				{
					return new EventoResultado(false, string.Format("El evento que está intentando agendar entra en conflicto con '{0}'", e.Titulo), null);
				}
			}

			if (evento == null)
				evento = Evento.Agendar(titulo, fechaInicio.Value, fechaTermino.Value, urlInvitacion, tipo);
			else
				evento.Agendar(fechaInicio, fechaTermino, urlInvitacion);

			var r = ActualizarPonentes(evento, ponentesId, null);
			if (!r.Succeful) return r;

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento creado", warnings);
		}

		private EventoResultado ActualizarPonentes(Evento evento, IEnumerable<Guid> ponentesId, Accion? action)
		{
			var ponentes = new List<Persona>();
			if (ponentesId != null)
			{
				foreach (var ponenteId in ponentesId.Where(id => id != Guid.Empty))
				{
					var colaborador = _personaRepository.Get(ponenteId);
					if (colaborador == null)
						return new EventoResultado(false, string.Format("No se encontró el colaborador indicado ({0})", ponenteId),
												   null);
					ponentes.Add(colaborador);
				}
				evento.ActualizarPonentes(ponentes, action);
			}
			return new EventoResultado(true, "Ponentes actualizados", null);
		}

		public EventoResultado Confirmar(Guid eventoId)
		{
			Evento evento = GetEvento(eventoId);

			evento.Confirmar();

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento confirmado.", warnings);
		}

		public EventoResultado Publicar(Guid eventoId, short numeroOrden, string urlWiki, TimeSpan duracion)
		{
			if (numeroOrden <= 0)
				return new EventoResultado(false, "Número de Orden fuera de rango", null);

			if (string.IsNullOrWhiteSpace(urlWiki))
				return new EventoResultado(false, "Url Wiki incorrecto", null);

			if (duracion.Hours.Equals(0) && duracion.Minutes.Equals(0))
				return new EventoResultado(false, "Duración fuera de rango", null);

			if (_eventosRepository.GetByState(EventoPublicadoState.GetInstance()).Any(e => e.NumeroOrden.Equals(numeroOrden)))
			{
				return new EventoResultado(false, "El número de evento ya se encuentra en uso", null);
			}

			var evento = GetEvento(eventoId);

			if (evento.Patrocinadores.Count() == 0)
				return new EventoResultado(false, "La VAN debe tener al menos un Patrocinador para ser publicada.", null);

			evento.Publicar(numeroOrden, urlWiki, duracion);

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento publicado", warnings);
		}

		public EventoResultado Cancelar(Guid eventoId)
		{
			Evento evento = GetEvento(eventoId);

			evento.Cancelar();

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento cancelado", warnings);
		}

		public EventoResultado Descartar(Guid eventoId)
		{
			Evento evento = GetEvento(eventoId);

			evento.Descartar();

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento descartado", warnings);
		}

		public EventoResultado ReProponer(Guid eventoId)
		{
			Evento evento = GetEvento(eventoId);

			evento.ReProponer();

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento re-prpuesto", warnings);
		}

		public EventoResultado ReAgendar(Guid eventoId)
		{
			Evento evento = GetEvento(eventoId);

			evento.ReAgendar();

			Notify(evento);

			_eventosRepository.Save(evento);

			var warnings = evento.GetLogsNews().Where(l => !l.Successful);

			return new EventoResultado(true, "Evento re-agendado", warnings);
		}

		public void IndicarPatrocinadores(Guid eventoId, IEnumerable<Guid> patrocinadores)
		{
			var evento = GetEvento(eventoId);

			var agregar = new List<Patrocinador>();
			var quitar = new List<Patrocinador>();

			if (patrocinadores != null)
			{
				foreach (var patrocinadorId in patrocinadores)
				{
					if (!evento.Patrocinadores.Any(p => p.Id == patrocinadorId))
					{
						var patrocinador = _patrocinadorRepository.Get(patrocinadorId);
						agregar.Add(patrocinador);
					}
				}

				foreach (var patrocinador in evento.Patrocinadores)
				{
					if (!patrocinadores.Any(p => p == patrocinador.Id))
						quitar.Add(patrocinador);
				}
			}

			foreach (var patrocinador in agregar)
				evento.AddPatrocinador(patrocinador);

			foreach (var patrocinador in quitar)
				evento.RemovePatrocinador(patrocinador);
		}

		private void Notify(Evento evento)
		{
			var tracks = evento.GetTrackNews();
			if (_publicador != null)
				_publicador.Publicar(tracks);
		}

		//TODO: este método ya no se debería usar
		public void RegistrarPonente(string nombre, string mail, string twitter, string blog)
		{
			var ponente = new Persona(nombre, mail, twitter, blog);
			_personaRepository.Save(ponente);
		}

	}
}