public static JornadaDbRow FromJornada(Jornada jornada, string usuario)
        {
            var jornadaDbRow = new JornadaDbRow
            {
                IdJornada = jornada.Id,
                Fecha = jornada.Dia,
                Entrada = jornada.Inicio,
                Salida = jornada.Fin,
                Usuario = usuario
            };

            foreach (var pausa in jornada.Pausas)
            {
                var pausaDbRow = new PausaDbRow
                {
                    IdPausa = pausa.Id,
                    IdJornada = jornada.Id,
                    Inicio = pausa.Inicio,
                    Fin = pausa.Fin
                };

                jornadaDbRow.Pausas.Add(pausaDbRow);
            }

            return jornadaDbRow;
        }
        public void ActualizarJornada(
            [Greedy]Jornada jornada)
        {
            var database = new Database(DatabaseHelper.Database);
            var sut = new PetaPocoJornadaCommands(database);

            sut.CrearJornada(jornada, DatabaseHelper.Usuario);

            var jornadaDbRow = database.FirstOrDefault<JornadaDbRow>(
                "Select * from Jornadas where IdJornada = @0", jornada.Id);

            jornadaDbRow.Should().NotBeNull();

            // Modificamos
            var nuevaPausa = new Pausa(jornada.Fin.Value, jornada.Fin.Value.AddHours(2));
            var idJornada = jornada.Id;
            jornada = new Jornada(
                jornada.Inicio,
                jornada.Fin.Value.AddDays(1),
                jornada.Pausas.Skip(1).Union(new[] { nuevaPausa }).ToArray());
            jornada.Id = idJornada;

            sut.ActualizarJornada(jornada, DatabaseHelper.Usuario);

            jornadaDbRow = database.FirstOrDefault<JornadaDbRow>(
                "Select * from Jornadas where IdJornada = @0", jornada.Id);

            jornadaDbRow.Should().NotBeNull();

            database.Execute("DELETE FROM Pausas WHERE IdJornada = @0", jornada.Id);
            database.Execute("DELETE FROM Jornadas WHERE IdJornada = @0", jornada.Id);
        }
        public void ActualizarJornada(Jornada jornada, string usuario)
        {
            var jornadaActual = Jornadas.FirstOrDefault(j => j.Id == jornada.Id);

            if (ReferenceEquals(jornada, jornadaActual) == false)
            {
                var index = Jornadas.IndexOf(jornadaActual);
                Jornadas.RemoveAt(index);
                Jornadas.Insert(index, jornada);
            }
        }
        public void CrearJornada(Jornada jornada, string usuario)
        {
            var maxId = 0;

            if (Jornadas.Any())
            {
                maxId = Jornadas.Max(j => j.Id);
            }

            jornada.Id = maxId + 1;
            Jornadas.Add(jornada);
        }
        public void ActualizarJornada(Jornada jornada, string usuario)
        {
            var jornadaDbRowActual = JornadaDbRow.FromJornada(jornada, usuario);

            // Obtener los datos de la jornada existente
            var query = Sql.Builder
                .Append("SELECT * ")
                .Append("FROM Jornadas J")
                .Append("LEFT JOIN Pausas P ON P.IdJornada = J.IdJornada")
                .Append("WHERE  J.IdJornada = @0", jornada.Id);

            var jornadaDbRowExistente = this.database
                .Fetch<JornadaDbRow, PausaDbRow, JornadaDbRow>(
                new JornadaDbRowPausaDbRowRelator().MapIt,
                query)
                .SingleOrDefault();

            if (jornadaDbRowExistente == null)
            {
                throw new InvalidOperationException("La jornada que intenta actualizar no existe. IdJornada = " + jornada.Id);
            }

            using (var transaction = this.database.GetTransaction())
            {
                this.database.Update("Jornadas", "IdJornada", jornadaDbRowActual);

                var pausasParaEliminar = jornadaDbRowExistente.Pausas.Select(p => p.IdPausa)
                                         .Except(jornadaDbRowActual.Pausas.Select(p => p.IdPausa));

                foreach (var pausaNuevaActualizar in jornadaDbRowActual.Pausas)
                {
                    if (pausaNuevaActualizar.IdPausa == -1)
                    {
                        this.database.Insert("Pausas", "IdPausa", true, pausaNuevaActualizar);
                    }
                    else
                    {
                        this.database.Update("Pausas", "IdPausa", pausaNuevaActualizar);
                    }
                }

                foreach (var idPausaEliminar in pausasParaEliminar)
                {
                    this.database.Execute("DELETE FROM Pausas WHERE IdPausa = @0", idPausaEliminar);
                }

                transaction.Complete();
            }
        }
        public void NoSePuedeIniciarJornadaConJornadaIniciada(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            string usuario)
        {
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);

            Action action = () => sut.IniciarJornada(usuario);

            action.ShouldThrow<InvalidOperationException>()
                .WithMessage("Ya existe una jornada iniciada. Debe terminar la jornada iniciada antes de iniciar una nueva.");
            commandsMock.Verify(c => c.CrearJornada(It.IsAny<Jornada>(), usuario), Times.Never());
        }
        public void NoSePuedeIniciarPausaConFechaAnteriorAlInicioDeLaJornada(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            string usuario)
        {
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            timeProviderMock.Setup(t => t.Now).Returns(jornada.Inicio.AddHours(-1));

            Action accion = () => sut.IniciarPausa(usuario);

            accion.ShouldThrow<InvalidOperationException>()
                .WithMessage("No se puede iniciar una pausa en una fecha anterior al inicio de la jornada.");
            commandsMock.Verify(c => c.ActualizarJornada(jornada, usuario), Times.Never());
        }
        public void IniciarJornada(string usuario)
        {
            var ultimaJornada = this.jornadaQueries.ObtenerUltimaJornada(usuario);

            if (ultimaJornada.EstaIniciado)
            {
                throw new InvalidOperationException("Ya existe una jornada iniciada. Debe terminar la jornada iniciada antes de iniciar una nueva.");
            }

            var existeJornadaParaDiaNuevaJornada = this.jornadaQueries.ExisteJornada(usuario, this.timeProvider.Today);

            if (existeJornadaParaDiaNuevaJornada)
            {
                throw new InvalidOperationException("Ya existe una jornada para la fecha indicada.");
            }

            var nuevaJornada = new Jornada(this.timeProvider.Now);
            this.jornadaCommands.CrearJornada(nuevaJornada, usuario);
        }
        public void DiaConFechaValida(
            [Frozen]Mock<HttpContextBase> httpContextMock,
            [Frozen]Mock<IIdentity> identityMock,
            [Frozen]Mock<IJornadaQueries> queriesMock,
            string usuario,
            Jornada jornada)
        {
            identityMock.Setup(x => x.Name).Returns(usuario);
            queriesMock.Setup(x => x.ObtenerJornada(usuario, jornada.Inicio.Date)).Returns(jornada);

            var sut = new InformeController(queriesMock.Object);
            sut.ControllerContext = new ControllerContext(httpContextMock.Object, new RouteData(), sut);

            var response = sut.Dia(new CriteriosBusquedaFechaViewModel { Fecha = jornada.Inicio.Date });

            response.Model.Should().BeOfType<InformeJornadaViewModel>();
            var model = (InformeJornadaViewModel)response.Model;
            model.Jornada.Should().Be(jornada);
        }
        public static JornadaViewModel FormJornada(Jornada jornada, string usuario)
        {
            var vm = new JornadaViewModel
            {
                Usuario = usuario,
                Id = jornada.Id,
                Dia = jornada.Dia.ToShortDateString(),
                Inicio = jornada.Inicio.ToString("dd/MM/yyyy HH:mm", CultureInfo.CurrentCulture),
                Fin = jornada.Fin.HasValue ? jornada.Fin.Value.ToString("dd/MM/yyyy HH:mm", CultureInfo.CurrentCulture) : string.Empty,
                Pausas = jornada.Pausas.Select(p => new PausaViewModel
                {
                    Id = p.Id,
                    Inicio = p.Inicio.ToString("dd/MM/yyyy HH:mm", CultureInfo.CurrentCulture),
                    Fin = p.Fin.HasValue ? p.Fin.Value.ToString("dd/MM/yyyy HH:mm", CultureInfo.CurrentCulture) : string.Empty,
                })
            };

            return vm;
        }
        public void ActualSinError(
            [Frozen]Mock<HttpContextBase> httpContextMock,
            [Frozen]Mock<IIdentity> identityMock,
            [Frozen]Mock<IJornadaService> serviceMock,
            [Frozen]Mock<IJornadaQueries> queriesMock,
            string usuario,
            Jornada jornada)
        {
            identityMock.Setup(x => x.Name).Returns(usuario);
            queriesMock.Setup(x => x.ObtenerUltimaJornada(usuario)).Returns(jornada);

            var sut = new SituacionController(serviceMock.Object, queriesMock.Object);
            sut.ControllerContext = new ControllerContext(httpContextMock.Object, new RouteData(), sut);

            var response = sut.Actual();

            response.Model.Should().BeOfType<JornadaViewModel>();
            var model = (JornadaViewModel)response.Model;
            model.Jornada.Should().Be(jornada);
            model.Error.Should().BeNull();
        }
        public void NoSePuedeIniciarJornadaSiYaExisteJornadaParaElNuevoDia(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            DateTime finJornada,
            DateTime diaNuevaJornada,
            string usuario)
        {
            jornada.Finalizar(finJornada);
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            queriesMock.Setup(q => q.ExisteJornada(usuario, diaNuevaJornada)).Returns(true);
            timeProviderMock.Setup(t => t.Today).Returns(diaNuevaJornada);

            Action action = () => sut.IniciarJornada(usuario);

            action.ShouldThrow<InvalidOperationException>()
                .WithMessage("Ya existe una jornada para la fecha indicada.");
            commandsMock.Verify(c => c.CrearJornada(It.IsAny<Jornada>(), usuario), Times.Never());
        }
        public void UnaJornadaIniciadaConUltimaPausaTerminadaNoTienePausaIniciada()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var inicioPausa = fixture.CreateAnonymous<DateTime>();
            var finPausa = fixture.CreateAnonymous<DateTime>();
            var pausa = new Pausa(inicioPausa, finPausa);

            var sut = new Jornada(inicioJornada, pausa);

            sut.PausaIniciada.Should().BeNull();
        }
        public void NoSePuedeTerminarJornadaSiLaUltimaJornadaEstaTerminada(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            DateTime finJornada,
            string usuario)
        {
            jornada.Finalizar(finJornada);
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            timeProviderMock.Setup(t => t.Now).Returns(jornada.Inicio.AddHours(8));

            Action accion = () => sut.TerminarJornada(usuario);

            accion.ShouldThrow<InvalidOperationException>()
                .WithMessage("No se puede terminar un periodo ya terminado.");
            commandsMock.Verify(c => c.ActualizarJornada(jornada, usuario), Times.Never());
        }
        public void UnaJornadaNoTerminadaSinPausasSePuedeTerminar()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var finJornada = fixture.CreateAnonymous<DateTime>();

            var sut = new Jornada(inicioJornada);

            sut.Finalizar(finJornada);

            sut.EstaIniciado.Should().BeFalse();
        }
        public void UnaJornadaTerminadaNoPuedeTerminarUnaPausa()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var finPausa = fixture.CreateAnonymous<DateTime>();
            var finJornada = fixture.CreateAnonymous<DateTime>();

            var sut = new Jornada(inicioJornada, finJornada);

            Assert.Throws<InvalidOperationException>(() => sut.TerminarPausa(finPausa));
        }
        public void UnaJornadaNoTerminadaNoPuedeTerminarPausaSiNoHayUnaPausaIniciada()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var finPausa = fixture.CreateAnonymous<DateTime>();

            var sut = new Jornada(inicioJornada);
            sut.PausaIniciada.Should().BeNull();

            Assert.Throws<InvalidOperationException>(
                () => sut.TerminarPausa(finPausa));
        }
        public void UnaJornadaNoTerminadaPuedeIniciarUnaPausa()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var inicioPausa = fixture.CreateAnonymous<DateTime>();

            var sut = new Jornada(inicioJornada);
            sut.PausaIniciada.Should().BeNull();

            sut.IniciarPausa(inicioPausa);

            sut.PausaIniciada.Should().NotBeNull();
        }
        public void UnaJornadaNoTerminadaConUnaOausaIniciadaNoSePuedeTerminar()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var inicioPausa = fixture.CreateAnonymous<DateTime>();
            var finJornada = fixture.CreateAnonymous<DateTime>();
            var pausa = new Pausa(inicioPausa);

            var sut = new Jornada(inicioJornada, pausa);

            Assert.Throws<InvalidOperationException>(
                () => sut.Finalizar(finJornada));
        }
        public void UnaJornadaNoTerminadaNoPuedeIniciarPausaSiYaHayUnaPausaIniciada()
        {
            var fixture = new Fixture();
            var inicioJornada = fixture.CreateAnonymous<DateTime>();
            var inicioPausa1 = fixture.CreateAnonymous<DateTime>();
            var inicioPausa2 = fixture.CreateAnonymous<DateTime>();
            var pausa = new Pausa(inicioPausa1);

            var sut = new Jornada(inicioJornada, pausa);
            sut.PausaIniciada.Should().NotBeNull();

            Assert.Throws<InvalidOperationException>(
                () => sut.IniciarPausa(inicioPausa2));
        }
        public void SePuedeTerminarPausaEnCondicionesCorrectas(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            DateTime inicioPausa,
            string usuario)
        {
            jornada.IniciarPausa(inicioPausa);
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            timeProviderMock.Setup(t => t.Now).Returns(inicioPausa.AddHours(1));

            sut.TerminarPausa(usuario);

            commandsMock.Verify(c => c.ActualizarJornada(jornada, usuario), Times.Once());
        }
        public void UnaJornadaIniciadaSinPausasNoTienePausaIniciada()
        {
            var fixture = new Fixture();
            var inicio = fixture.CreateAnonymous<DateTime>();

            var sut = new Jornada(inicio);

            sut.PausaIniciada.Should().BeNull();
        }
        public void NoSePuedeTerminarPausaConFechaAnteriorAInicioPausa(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            DateTime inicioPausa,
            string usuario)
        {
            jornada.IniciarPausa(inicioPausa);
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            timeProviderMock.Setup(t => t.Now).Returns(inicioPausa.AddHours(-1));

            Action accion = () => sut.TerminarPausa(usuario);

            accion.ShouldThrow<InvalidOperationException>()
                .WithMessage("La fecha de finalización debe ser posterior a la fecha de inicio.");
            commandsMock.Verify(c => c.ActualizarJornada(jornada, usuario), Times.Never());
        }
        public Jornada ToJornada()
        {
            var pausas = new List<Pausa>(this.Pausas.Count);

            foreach (var pausa in this.Pausas)
            {
                if (pausa.Fin.HasValue)
                {
                    pausas.Add(new Pausa(pausa.Inicio, pausa.Fin.Value) { Id = pausa.IdPausa });
                }
                else
                {
                    pausas.Add(new Pausa(pausa.Inicio) { Id = pausa.IdPausa });
                }
            }

            Jornada jornada;

            if (this.Salida.HasValue)
            {
                jornada = new Jornada(this.Entrada, this.Salida.Value, pausas.ToArray());
            }
            else
            {
                jornada = new Jornada(this.Entrada, pausas.ToArray());
            }

            jornada.Id = this.IdJornada;

            return jornada;
        }
        public void CrearJornada(Jornada jornada, string usuario)
        {
            var jornadaDbRow = JornadaDbRow.FromJornada(jornada, usuario);

            using (var transaction = this.database.GetTransaction())
            {
                this.database.Insert("Jornadas", "IdJornada", true, jornadaDbRow);
                jornada.Id = jornadaDbRow.IdJornada;

                var pausas = jornada.Pausas.Zip(jornadaDbRow.Pausas, (p, pdb) => new { Pausa = p, PausaDbRow = pdb });

                foreach (var pausa in pausas)
                {
                    pausa.PausaDbRow.IdJornada = jornadaDbRow.IdJornada;
                    this.database.Insert("Pausas", "IdPausa", true, pausa.PausaDbRow);
                    pausa.Pausa.Id = pausa.PausaDbRow.IdPausa;
                }

                transaction.Complete();
            }
        }
        public void SePuedeIniciarJornadaConVerificacionesCorrectas(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            DateTime finJornada,
            DateTime diaNuevaJornada,
            string usuario)
        {
            jornada.Finalizar(finJornada);
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            queriesMock.Setup(q => q.ExisteJornada(usuario, diaNuevaJornada)).Returns(false);
            timeProviderMock.Setup(t => t.Now).Returns(diaNuevaJornada);

            sut.IniciarJornada(usuario);

            commandsMock.Verify(c => c.CrearJornada(It.IsAny<Jornada>(), usuario), Times.Once());
        }
        public void NoSePuedeTerminarPausaSiNoHayPausaIniciada(
            [Frozen]Mock<IJornadaQueries> queriesMock,
            [Frozen]Mock<IJornadaCommands> commandsMock,
            [Frozen]Mock<ITimeProvider> timeProviderMock,
            JornadaService sut,
            Jornada jornada,
            string usuario)
        {
            queriesMock.Setup(q => q.ObtenerUltimaJornada(usuario)).Returns(jornada);
            timeProviderMock.Setup(t => t.Now).Returns(jornada.Inicio.AddHours(1));

            Action accion = () => sut.TerminarPausa(usuario);

            accion.ShouldThrow<InvalidOperationException>()
                .WithMessage("No se puede terminar una pausa cuando no hay una pausa iniciada.");
            commandsMock.Verify(c => c.ActualizarJornada(jornada, usuario), Times.Never());
        }