From 00d4ec8a0edbcfa8a0bb1c839e82e8c120702e9e Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 27 Jan 2025 16:40:02 -0300 Subject: [PATCH 01/16] =?UTF-8?q?migracion:=20a=C3=B1adido=20entidades=20A?= =?UTF-8?q?uditoria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Entidades/Alquilafacilcontext.cs | 55 ++++++++++++++++++++++++++++++++ Entidades/Cliente.cs | 2 ++ Entidades/Log.cs | 17 ++++++++++ Entidades/Logdetalle.cs | 21 ++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 Entidades/Log.cs create mode 100644 Entidades/Logdetalle.cs diff --git a/Entidades/Alquilafacilcontext.cs b/Entidades/Alquilafacilcontext.cs index 286427c..e860832 100644 --- a/Entidades/Alquilafacilcontext.cs +++ b/Entidades/Alquilafacilcontext.cs @@ -35,6 +35,10 @@ public partial class AlquilaFacilContext : DbContext public virtual DbSet Grupos { get; set; } + public virtual DbSet Logs { get; set; } + + public virtual DbSet LogDetalles { get; set; } + public virtual DbSet Notificaciones { get; set; } public virtual DbSet Permisos { get; set; } @@ -417,6 +421,57 @@ public partial class AlquilaFacilContext : DbContext .HasColumnName("nombre"); }); + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.Fecha, e.Dniusuario }).HasName("PRIMARY"); + + entity.ToTable("Log"); + + entity.HasIndex(e => e.Dniusuario, "fk_log_clientes"); + + entity.Property(e => e.Fecha) + .HasColumnType("datetime") + .HasColumnName("fecha"); + entity.Property(e => e.Dniusuario) + .HasColumnType("bigint(20)") + .HasColumnName("dniusuario"); + entity.Property(e => e.Accion) + .HasMaxLength(255) + .HasColumnName("accion"); + + entity.HasOne(d => d.DniusuarioNavigation).WithMany(p => p.Logs) + .HasForeignKey(d => d.Dniusuario) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_log_clientes"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => new { e.Fecha, e.Dniusuario, e.NombreTabla, e.Columna }).HasName("PRIMARY"); + + entity.ToTable("LogDetalle"); + + entity.Property(e => e.Fecha) + .HasColumnType("datetime") + .HasColumnName("fecha"); + entity.Property(e => e.Dniusuario) + .HasColumnType("bigint(20)") + .HasColumnName("dniusuario"); + entity.Property(e => e.NombreTabla).HasColumnName("nombreTabla"); + entity.Property(e => e.Columna).HasColumnName("columna"); + entity.Property(e => e.ValorAnterior) + .HasColumnType("text") + .HasColumnName("valorAnterior"); + entity.Property(e => e.ValorNuevo) + .HasColumnType("text") + .HasColumnName("valorNuevo"); + + entity.HasOne(d => d.Log).WithMany(p => p.LogDetalles) + .HasForeignKey(d => new { d.Fecha, d.Dniusuario }) + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("LogDetalle_ibfk_1"); + }); + modelBuilder.Entity(entity => { entity.HasKey(e => new { e.Dnicliente, e.Fecha }).HasName("PRIMARY"); diff --git a/Entidades/Cliente.cs b/Entidades/Cliente.cs index 9f69cbb..4fe77e0 100644 --- a/Entidades/Cliente.cs +++ b/Entidades/Cliente.cs @@ -27,6 +27,8 @@ public partial class Cliente public virtual ICollection ContratoDnipropietarioNavigations { get; set; } = new List(); + public virtual ICollection Logs { get; set; } = new List(); + public virtual ICollection NotificacioneDniclienteNavigations { get; set; } = new List(); public virtual ICollection NotificacioneDniremitenteNavigations { get; set; } = new List(); diff --git a/Entidades/Log.cs b/Entidades/Log.cs new file mode 100644 index 0000000..99d4ca5 --- /dev/null +++ b/Entidades/Log.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; + +namespace Entidades; + +public partial class Log +{ + public DateTime Fecha { get; set; } + + public long Dniusuario { get; set; } + + public string Accion { get; set; } = null!; + + public virtual Cliente DniusuarioNavigation { get; set; } = null!; + + public virtual ICollection LogDetalles { get; set; } = new List(); +} diff --git a/Entidades/Logdetalle.cs b/Entidades/Logdetalle.cs new file mode 100644 index 0000000..4a9485c --- /dev/null +++ b/Entidades/Logdetalle.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace Entidades; + +public partial class LogDetalle +{ + public DateTime Fecha { get; set; } + + public long Dniusuario { get; set; } + + public string NombreTabla { get; set; } = null!; + + public string Columna { get; set; } = null!; + + public string? ValorAnterior { get; set; } + + public string? ValorNuevo { get; set; } + + public virtual Log Log { get; set; } = null!; +} -- 2.52.0 From 7b1e70999f4832a5312a535e276b0fad06494c9a Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 27 Jan 2025 16:40:47 -0300 Subject: [PATCH 02/16] =?UTF-8?q?a=C3=B1adida=20fecha=20de=20finalizacion?= =?UTF-8?q?=20de=20venta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modelo/RepositorioVentas.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modelo/RepositorioVentas.cs b/Modelo/RepositorioVentas.cs index df962af..4ab7596 100644 --- a/Modelo/RepositorioVentas.cs +++ b/Modelo/RepositorioVentas.cs @@ -12,7 +12,7 @@ public class RepositorioVentas: RepositorioBase { vent.IdpropiedadNavigation.Idestado=3; vent.Idestado=3; - + vent.Fechafinal = DateTime.Now; return Guardar(con); } -- 2.52.0 From 17fae0e777eda1d41cd7f26d49fba23721905c93 Mon Sep 17 00:00:00 2001 From: fede Date: Mon, 27 Jan 2025 20:13:15 -0300 Subject: [PATCH 03/16] =?UTF-8?q?feat:=20implementado=20todo=20lo=20de=20a?= =?UTF-8?q?uditoria=20tocaria=20testearlo=20nom=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Aspnet/Controllers/AdminController.cs | 5 +- Aspnet/Controllers/ContratoController.cs | 25 +++--- Aspnet/Controllers/DefectoController.cs | 10 ++- Aspnet/Controllers/GruposController.cs | 22 ----- Aspnet/Controllers/PermisosController.cs | 23 ----- Aspnet/Controllers/PropiedadesController.cs | 6 +- Aspnet/Controllers/VentaController.cs | 4 +- Modelo/Facade/AuditoriaFacade.cs | 98 +++++++++++++++++++++ Modelo/Facade/FiltroCambios.cs | 6 ++ Modelo/Facade/PersistenciaLog.cs | 11 +++ Modelo/Facade/ValidadorCambios.cs | 6 ++ Modelo/RepositorioBase.cs | 8 ++ Modelo/RepositorioCanons.cs | 8 +- Modelo/RepositorioContratos.cs | 24 +++-- Modelo/RepositorioDefectos.cs | 6 +- Modelo/RepositorioGrupos.cs | 13 --- Modelo/RepositorioPermisos.cs | 14 --- Modelo/RepositorioPropiedades.cs | 14 +-- Modelo/RepositorioUsuarios.cs | 9 +- Modelo/RepositorioVentas.cs | 7 +- 20 files changed, 204 insertions(+), 115 deletions(-) delete mode 100644 Aspnet/Controllers/GruposController.cs delete mode 100644 Aspnet/Controllers/PermisosController.cs create mode 100644 Modelo/Facade/AuditoriaFacade.cs create mode 100644 Modelo/Facade/FiltroCambios.cs create mode 100644 Modelo/Facade/PersistenciaLog.cs create mode 100644 Modelo/Facade/ValidadorCambios.cs diff --git a/Aspnet/Controllers/AdminController.cs b/Aspnet/Controllers/AdminController.cs index 759c19d..409aaae 100644 --- a/Aspnet/Controllers/AdminController.cs +++ b/Aspnet/Controllers/AdminController.cs @@ -117,8 +117,11 @@ public class AdminController: ControllerBase if (validacion1 == false) return Unauthorized(); if (id <= 0) return BadRequest(new { message = "Falto indicar id Propiedad"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); - var ret = RepositorioPropiedades.Singleton.BajaPropiedad(id); + var ret = RepositorioPropiedades.Singleton.BajaPropiedad(id, cli.Dni); return ret ? Ok(new {message = "Se cambio el estado de la propiedad"}): BadRequest(new { message = "No se pudo dar de baja"}); } diff --git a/Aspnet/Controllers/ContratoController.cs b/Aspnet/Controllers/ContratoController.cs index 6c6e822..23d34f7 100644 --- a/Aspnet/Controllers/ContratoController.cs +++ b/Aspnet/Controllers/ContratoController.cs @@ -85,7 +85,7 @@ public class ContratoController: ControllerBase { Fecha = c.Fecha, }; - bool ret = RepositorioCanons.Singleton.SetRecibo(c, re); + bool ret = RepositorioCanons.Singleton.SetRecibo(c, re, cli.Dni); return ret ? Ok(new { message = "Se guardo correctamente"}):BadRequest(new { message = "No se pudo guardar"}); @@ -114,7 +114,7 @@ public class ContratoController: ControllerBase { Fecha = c.Fecha, }; - bool ret = RepositorioCanons.Singleton.SetRecibo(c, re); + bool ret = RepositorioCanons.Singleton.SetRecibo(c, re, cli.Dni); return ret ? Ok(new { message = "Se guardo correctamente"}):BadRequest(new { message = "No se pudo guardar"}); } @@ -133,7 +133,7 @@ public class ContratoController: ControllerBase { if (cont == null) return BadRequest(new { message = "no hay un contrato por esa id"}); if (cli.Dni != cont.Dnipropietario) return BadRequest(new {message = "No sos el propietario o intenta volviendote a logear"}); - var ret = RepositorioCanons.Singleton.CrearCanons(dto.aumento, dto.idcontrato); + var ret = RepositorioCanons.Singleton.CrearCanons(dto.aumento, dto.idcontrato, cli.Dni); return ret ? Ok(new { message = "Se crearon los canons correctamente"}):BadRequest(new { message = "No se pudo guardar"}); } @@ -352,14 +352,14 @@ public class ContratoController: ControllerBase { bool ret; if (dto.TieneOpcionVenta==false){ - ret = RepositorioContratos.Singleton.CargaPrecontrato(precontrato, notificacion); + ret = RepositorioContratos.Singleton.CargaPrecontrato(cli.Dni, precontrato, notificacion); } else { Venta v = new Venta{ Idestado = 1, Iddivisa = dto.iddivisa, Monto = dto.MontoOpcion, }; - ret = RepositorioContratos.Singleton.CargaPrecontratoOpcionVenta(precontrato, notificacion, v); + ret = RepositorioContratos.Singleton.CargaPrecontratoOpcionVenta(precontrato, notificacion, v, cli.Dni); } if (ret) { @@ -411,7 +411,7 @@ public class ContratoController: ControllerBase { var contr = RepositorioContratos.Singleton.ObtenerContrato(dto.EmailInquilino, dto.Idpropiedad); if (contr == null) return BadRequest(new { message = "No existe el contrato o ya fue activado"}); - var ret = RepositorioContratos.Singleton.CargaGarantes(gar, dto.EmailInquilino, dto.Idpropiedad); + var ret = RepositorioContratos.Singleton.CargaGarantes(gar, dto.EmailInquilino, dto.Idpropiedad, cli.Dni); if (ret) { Console.WriteLine(dto.fecha); RepositorioNotificaciones.Singleton.MarcarComoLeido(cli.Dni, dto.fecha); @@ -440,6 +440,9 @@ public class ContratoController: ControllerBase { var validacion2 = ValidarCancelarDto(dto); if (validacion2 != "") return BadRequest(new {message = validacion2}); + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli==null) return Unauthorized(); + Cliente? pro = RepositorioPropietario.Singleton.ObtenerPropietarioPorEmail(dto.EmailPropietario); if (pro == null) return BadRequest(new {message = "No Existe Usuario con ese email"}); if (pro.Token != Auth) return BadRequest(new {message = "El token de auth no corresponde al token el usuario propietario"}); @@ -451,10 +454,10 @@ public class ContratoController: ControllerBase { var inq = RepositorioInquilinos.Singleton.ObtenerInquilinoPorEmail(dto.EmailInquilino); if (inq == null) return BadRequest(new {message = "No hay un inquilino por ese email"}); - var ret = RepositorioContratos.Singleton.CancelarPrecontrato(dto.EmailInquilino, dto.idpropiedad); + var ret = RepositorioContratos.Singleton.CancelarPrecontrato(dto.EmailInquilino, dto.idpropiedad, cli.Dni); if (ret) { prop.Idestado = 1; - ret = RepositorioPropiedades.Singleton.PatchPropiedad(prop); + ret = RepositorioPropiedades.Singleton.PatchPropiedad(prop, pro.Dni); if (ret){ RepositorioNotificaciones.Singleton.MarcarComoLeido(pro.Dni, dto.fecha); var noti = new NotificacioneBuilder() @@ -549,7 +552,7 @@ public class ContratoController: ControllerBase { bool ret = await subirContrato(contrato, nuevoNombreArchivo); if(ret == false) return BadRequest(new {message = "No se pudo subir el archivo"}); - ret = RepositorioContratos.Singleton.AddUrl(contr.Id, nuevoNombreArchivo); + ret = RepositorioContratos.Singleton.AddUrl(contr.Id, nuevoNombreArchivo, cli.Dni); if (ret == false) return BadRequest(new { message = "No se pudo guardar la url del contrato" }); var noti = new NotificacioneBuilder() @@ -670,7 +673,7 @@ public class ContratoController: ControllerBase { if (cli == null) return BadRequest(new { message = "No hay un cliente por ese token"}); if (cli.Dni != contr.Dniinquilino) return BadRequest(new { message = "El token no corresponde con el del inquilino"}); - bool ret = RepositorioContratos.Singleton.AceptarContrato(dto.Idcontrato); + bool ret = RepositorioContratos.Singleton.AceptarContrato(dto.Idcontrato, cli.Dni); if (ret == false) return BadRequest(new { message ="fallo al aceptar el contrato"}); RepositorioNotificaciones.Singleton.MarcarComoLeido(cli.Dni, dto.Fecha); @@ -707,7 +710,7 @@ public class ContratoController: ControllerBase { if (cli == null) return BadRequest(new { message = "No hay un cliente por ese token"}); if (cli.Dni != contr.Dniinquilino) return BadRequest(new { message = "El token no corresponde con el del inquilino"}); - var ret = RepositorioContratos.Singleton.CancelarPrecontrato(dto.Idcontrato); + var ret = RepositorioContratos.Singleton.CancelarPrecontrato(dto.Idcontrato, cli.Dni); if (ret == false) return BadRequest(new {message = "Fallo al intentar cancelar el precontrato"}); RepositorioNotificaciones.Singleton.MarcarComoLeido(cli.Dni, dto.Fecha); diff --git a/Aspnet/Controllers/DefectoController.cs b/Aspnet/Controllers/DefectoController.cs index a7f9fef..6096e7c 100644 --- a/Aspnet/Controllers/DefectoController.cs +++ b/Aspnet/Controllers/DefectoController.cs @@ -53,6 +53,9 @@ public class DefectoController: ControllerBase { var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino"); if (validacion1 == false) return Unauthorized(); + Cliente? cli =RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + string r = ValidarDto(data); if (r != "") return BadRequest(new { message = r }); @@ -65,7 +68,7 @@ public class DefectoController: ControllerBase { Idestado = 1, }; - var b = RepositorioDefectos.Singleton.AltaDefecto(defecto); + var b = RepositorioDefectos.Singleton.AltaDefecto(defecto, cli.Dni); return b ?Ok(new { message = "Se cargo el Defecto en el sistema"}):BadRequest(new { message ="No se pudo cargar el defecto en el sistema"}); } @@ -86,8 +89,11 @@ public class DefectoController: ControllerBase { var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); if (validacion1 == false) return Unauthorized(); + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli==null) return Unauthorized(); + if (iddefecto<=0) return BadRequest(new { message = "No hay canones con id 0 o menor"}); - bool ret = RepositorioDefectos.Singleton.MarcarPago(iddefecto); + bool ret = RepositorioDefectos.Singleton.MarcarPago(iddefecto, cli.Dni); return ret ? Ok(new { message = "Se marco como pagado" }):BadRequest(new { message = "Fallo el acceso a la base de datos o no se encontro el defecto" }); diff --git a/Aspnet/Controllers/GruposController.cs b/Aspnet/Controllers/GruposController.cs deleted file mode 100644 index be028f2..0000000 --- a/Aspnet/Controllers/GruposController.cs +++ /dev/null @@ -1,22 +0,0 @@ -#if DEBUG -using Microsoft.AspNetCore.Mvc; -using Modelo; -namespace AlquilaFacil.Controllers; - -[ApiController] -public class GruposController: ControllerBase { - [HttpPost("api/admin/grupos")] - public IActionResult CrearGrupo([FromBody] AdminGrupo grupo, [FromHeader(Name = "Auth")] string Auth) { - if (!string.IsNullOrEmpty(Auth)) return BadRequest(); - var ret2 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 10); - if (ret2 == false) return BadRequest(ret2); - - if (String.IsNullOrEmpty(grupo.descripcion)) return BadRequest(); - - bool ret = RepositorioGrupos.Singleton.CrearGrupo(grupo.descripcion); - return (ret) ? Ok(ret) : BadRequest(); - } -} - -public record AdminGrupo(string descripcion); -#endif \ No newline at end of file diff --git a/Aspnet/Controllers/PermisosController.cs b/Aspnet/Controllers/PermisosController.cs deleted file mode 100644 index a63f9a1..0000000 --- a/Aspnet/Controllers/PermisosController.cs +++ /dev/null @@ -1,23 +0,0 @@ -#if DEBUG -using System.Text.Json; -using Microsoft.AspNetCore.Mvc; -using Modelo; -namespace AlquilaFacil.Controllers; - -[ApiController] -public class PermisosController: ControllerBase { - [HttpPost("api/admin/permisos")] - public IActionResult CrearPermisos([FromBody] AdminPermiso permiso, [FromHeader(Name = "Auth")] string Auth) { - if (!string.IsNullOrEmpty(Auth)) return BadRequest(); - var ret2 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 11); - if (ret2 == false) return BadRequest(ret2); - - if (String.IsNullOrEmpty(permiso.descripcion)) return BadRequest(); - - bool ret = RepositorioPermisos.Singleton.CrearPermiso(permiso.descripcion); - return (ret) ? Ok(ret) : BadRequest(); - } -} - -public record AdminPermiso(string descripcion); -#endif \ No newline at end of file diff --git a/Aspnet/Controllers/PropiedadesController.cs b/Aspnet/Controllers/PropiedadesController.cs index 26f34b6..8b3ed9b 100644 --- a/Aspnet/Controllers/PropiedadesController.cs +++ b/Aspnet/Controllers/PropiedadesController.cs @@ -146,7 +146,7 @@ public class PropiedadesController: ControllerBase { Iddivisa = propiedad.Iddivisa, }; - bool ret = RepositorioPropiedades.Singleton.PatchPropiedad(Prop); + bool ret = RepositorioPropiedades.Singleton.PatchPropiedad(Prop, cli.Dni); return (ret)? Ok(new {message = "Fue modificado Correctamente"}): BadRequest(new {message = "Fallo al modificar la base de datos"}); @@ -203,11 +203,13 @@ public class PropiedadesController: ControllerBase { if (servicio.idServicios.Count() < 1) return BadRequest(new {message ="Falta añadir servicios"}); if (servicio.idServicios.Any(x => x<= 0)) return BadRequest(new {message ="No tienen haber ids negativas o cero de servicio"}); + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + var serv = RepositorioServicios.Singleton.ObtenerServiciosPorPropiedad(servicio.propiedadid); var repetidos = serv.Intersect(servicio.idServicios); - bool ret = RepositorioPropiedades.Singleton.BajaServiciosAPropiedad(servicio.propiedadid, servicio.idServicios); + bool ret = RepositorioPropiedades.Singleton.BajaServiciosAPropiedad(servicio.propiedadid, servicio.idServicios, cli.Dni); return ret ? Ok(new {message ="Se Eliminaron los servicios seleccionados de la propiedad"}) : BadRequest(new {message ="Fallo al eliminarse los servicios de la propiedad"}); diff --git a/Aspnet/Controllers/VentaController.cs b/Aspnet/Controllers/VentaController.cs index b9857dd..b9cb319 100644 --- a/Aspnet/Controllers/VentaController.cs +++ b/Aspnet/Controllers/VentaController.cs @@ -36,7 +36,7 @@ public class VentaController:ControllerBase { venta.Idpropiedad = cont.Idpropiedad; venta.Fechainicio = DateTime.Now; - bool ret = RepositorioVentas.Singleton.PatchVenta(venta); + bool ret = RepositorioVentas.Singleton.PatchVenta(venta, cli.Dni); return ret? Ok(new { message = "Se ejercio la opcion de venta"}): @@ -72,7 +72,7 @@ public class VentaController:ControllerBase { bool ret = await subirContrato(file, nuevoNombreArchivo); if(ret == false) return BadRequest(new {message = "No se pudo subir el archivo"}); - ret = RepositorioVentas.Singleton.SetUrlRecibo(venta.Id, nuevoNombreArchivo); + ret = RepositorioVentas.Singleton.SetUrlRecibo(venta.Id, nuevoNombreArchivo, cli.Dni); if (ret == false) return BadRequest(new { message = "no se pudo guardar el nombre del archivo subido"}); return Ok(new { message = "Se Subio el Recibo"}); diff --git a/Modelo/Facade/AuditoriaFacade.cs b/Modelo/Facade/AuditoriaFacade.cs new file mode 100644 index 0000000..d455c70 --- /dev/null +++ b/Modelo/Facade/AuditoriaFacade.cs @@ -0,0 +1,98 @@ +using Entidades; +using Microsoft.EntityFrameworkCore; + +namespace Modelo.Facade; +public class AuditoriaFacade { + private readonly AlquilaFacilContext _context; + private readonly FiltroCambios _filtradoDeCambios=new(); + private readonly ValidadorDeCambios _validadorDeCambios=new(); + private readonly PersistenciaLog _persistenciaDeLog=new(); + + public AuditoriaFacade(AlquilaFacilContext context) { + _context = context; + } + + public void GenerarLog(long dniUsuario, string v) { + var cambios = _filtradoDeCambios.FiltrarCambios(_context.ChangeTracker.Entries()); + + var fechaActual = DateTime.Now; + + var log = new Log{ + Fecha = fechaActual, + Dniusuario = dniUsuario, + Accion = v + }; + + log.LogDetalles = ProcesarCambios(cambios, fechaActual, dniUsuario); + + _persistenciaDeLog.GuardarLog(log, log.LogDetalles); + } + + private List ProcesarCambios(IEnumerable cambios, + DateTime fechaActual, long dniUsuario) { + + var logDetalles = new List(); + foreach (var cambio in cambios) { + var nombreTabla = cambio.Entity.GetType().Name; + Console.WriteLine($"Entidad: {cambio.Entity.GetType().Name}, Estado: {cambio.State}"); + + switch (cambio.State) { + case EntityState.Modified: + foreach (var propiedad in cambio.OriginalValues.Properties) { + if (propiedad.Name == "Token") break; + var valorAnterior = cambio.OriginalValues[propiedad]?.ToString(); + var valorNuevo = cambio.CurrentValues[propiedad]?.ToString(); + + if (_validadorDeCambios.ValidarCambio(valorAnterior??"", valorNuevo??"")) { + logDetalles.Add(new LogDetalle { + Fecha = fechaActual, + Dniusuario = dniUsuario, + NombreTabla = nombreTabla, + Columna = propiedad.Name, + ValorAnterior = valorAnterior, + ValorNuevo = valorNuevo + }); + } + } + break; + + case EntityState.Added: + foreach (var propiedad in cambio.CurrentValues.Properties) { + if (propiedad.Name == "Token") break; + var valorNuevo = cambio.CurrentValues[propiedad]?.ToString(); + + logDetalles.Add(new LogDetalle { + Fecha = fechaActual, + Dniusuario = dniUsuario, + NombreTabla = nombreTabla, + Columna = propiedad.Name, + ValorAnterior = null, + ValorNuevo = valorNuevo + }); + } + break; + + case EntityState.Deleted: + foreach (var propiedad in cambio.OriginalValues.Properties) { + if (propiedad.Name == "Token") break; + var valorAnterior = cambio.OriginalValues[propiedad]?.ToString(); + + logDetalles.Add(new LogDetalle { + Fecha = fechaActual, + Dniusuario = dniUsuario, + NombreTabla = nombreTabla, + Columna = propiedad.Name, + ValorAnterior = valorAnterior, + ValorNuevo = null + }); + } + break; + + default: + Console.WriteLine($"Estado no manejado: {cambio.State}"); + break; + } + } + return logDetalles; + } +} diff --git a/Modelo/Facade/FiltroCambios.cs b/Modelo/Facade/FiltroCambios.cs new file mode 100644 index 0000000..7aa6d1c --- /dev/null +++ b/Modelo/Facade/FiltroCambios.cs @@ -0,0 +1,6 @@ +namespace Modelo.Facade; +public class FiltroCambios { + public IEnumerable FiltrarCambios(IEnumerable cambios) { + return cambios.Where(c => c.Entity.GetType().Name != "EntidadExcluida"); + } +} diff --git a/Modelo/Facade/PersistenciaLog.cs b/Modelo/Facade/PersistenciaLog.cs new file mode 100644 index 0000000..7b51b5d --- /dev/null +++ b/Modelo/Facade/PersistenciaLog.cs @@ -0,0 +1,11 @@ +using Entidades; +namespace Modelo.Facade; +public class PersistenciaLog { + private AlquilaFacilContext _context {get{return new AlquilaFacilContext();}} + public void GuardarLog(Log log, IEnumerable detalles) { + var con = _context; + con.Logs.Add(log); + con.LogDetalles.AddRange(detalles); + con.SaveChanges(); + } +} diff --git a/Modelo/Facade/ValidadorCambios.cs b/Modelo/Facade/ValidadorCambios.cs new file mode 100644 index 0000000..f49a25f --- /dev/null +++ b/Modelo/Facade/ValidadorCambios.cs @@ -0,0 +1,6 @@ +namespace Modelo.Facade; +public class ValidadorDeCambios { + public bool ValidarCambio(string valorAnterior, string valorNuevo) { + return !string.IsNullOrEmpty(valorNuevo) && valorAnterior != valorNuevo; + } +} diff --git a/Modelo/RepositorioBase.cs b/Modelo/RepositorioBase.cs index 11eeabc..26a4142 100644 --- a/Modelo/RepositorioBase.cs +++ b/Modelo/RepositorioBase.cs @@ -1,4 +1,6 @@ using Entidades; +using Microsoft.EntityFrameworkCore; +using Modelo.Facade; namespace Modelo; @@ -9,6 +11,12 @@ public abstract class RepositorioBase private static readonly S instance = new(); public static S Singleton { get { return instance; }} + public void GenerarLog(AlquilaFacilContext context, long dni, string accion) { + var Auditoria = new AuditoriaFacade(context); + + Auditoria.GenerarLog(dni, accion??""); + return; + } public bool Guardar(AlquilaFacilContext context) { bool ret = false; try diff --git a/Modelo/RepositorioCanons.cs b/Modelo/RepositorioCanons.cs index f1811da..ecb8ce2 100644 --- a/Modelo/RepositorioCanons.cs +++ b/Modelo/RepositorioCanons.cs @@ -27,7 +27,7 @@ public class RepositorioCanons: RepositorioBase { return cc; } - public bool SetRecibo(Canon c, Recibo re) { + public bool SetRecibo(Canon c, Recibo re, long dni) { var con = Context; var cc = con.Canons .Include(x=>x.Idcontratos) @@ -51,10 +51,12 @@ public class RepositorioCanons: RepositorioBase { ccc.IdpropiedadNavigation.Idestado = 3; } + GenerarLog(con, dni, $"Set Recibo"); + return Guardar(con); } - public bool CrearCanons(decimal aumento, long idcontrato) { + public bool CrearCanons(decimal aumento, long idcontrato, long dni) { var con = Context; aumento/=100; @@ -86,6 +88,8 @@ public class RepositorioCanons: RepositorioBase { con.Canons.Add(c); cont.Idcanons.Add(c); } + GenerarLog(con, dni, $"Crear Canones"); + return Guardar(con); } } \ No newline at end of file diff --git a/Modelo/RepositorioContratos.cs b/Modelo/RepositorioContratos.cs index efdc58c..8016950 100644 --- a/Modelo/RepositorioContratos.cs +++ b/Modelo/RepositorioContratos.cs @@ -14,7 +14,7 @@ public class RepositorioContratos: RepositorioBase { } } - public bool CargaPrecontrato( Contrato? c = null, Notificacione? n = null) { + public bool CargaPrecontrato(long dni, Contrato? c = null, Notificacione? n = null) { if (c == null || c.Habilitado == 1) return false; if (n == null) return false; var con = Context; @@ -29,10 +29,10 @@ public class RepositorioContratos: RepositorioBase { con.Contratos.Add(c); con.Notificaciones.Add(n); - + GenerarLog(con, dni, $"CargaPrecontrato"); return Guardar(con); } - public bool CargaGarantes(List gar, string emailInquilino, int idpropiedad) { + public bool CargaGarantes(List gar, string emailInquilino, int idpropiedad, long dni) { var con = Context; Contrato? contr = con.Contratos.Include(x=>x.DniinquilinoNavigation).Include(x=>x.Idgarantes) .FirstOrDefault(x=>x.Idpropiedad == idpropiedad && @@ -48,7 +48,7 @@ public class RepositorioContratos: RepositorioBase { con.Garantes.Add(i); contr.Idgarantes.Add(i); } - + GenerarLog(con, dni, $"Alta Garantes"); return Guardar(con); } @@ -75,7 +75,7 @@ public class RepositorioContratos: RepositorioBase { } - public bool CancelarPrecontrato(string emailInquilino, int idpropiedad) { + public bool CancelarPrecontrato(string emailInquilino, int idpropiedad, long dni) { var con = Context; Contrato? contr = con.Contratos.Include(x=>x.DniinquilinoNavigation) .FirstOrDefault(x=>x.Idpropiedad == idpropiedad && @@ -86,6 +86,7 @@ public class RepositorioContratos: RepositorioBase { if (contr == null || contr.IdpropiedadNavigation == null) return false; contr.Cancelado = 1; contr.IdpropiedadNavigation.Idestado = 1; + GenerarLog(con, dni, $"Cancelar Precontrato"); return Guardar(con); } @@ -101,16 +102,17 @@ public class RepositorioContratos: RepositorioBase { return contr; } - public bool AddUrl(long id, string nuevoNombreArchivo) { + public bool AddUrl(long id, string nuevoNombreArchivo, long dni) { var con = Context; Contrato? contrato = con.Contratos .FirstOrDefault(x=>x.Id == id); if (contrato == null) return false; contrato.UrlContrato = nuevoNombreArchivo; + GenerarLog(con, dni, $"Añadido contrato"); return Guardar(con); } - public bool AceptarContrato(long idcontrato) { + public bool AceptarContrato(long idcontrato, long dni) { var con = Context; Contrato? cont = con.Contratos .Include(x=>x.Idcanons) @@ -151,15 +153,18 @@ public class RepositorioContratos: RepositorioBase { cont.Idcanons.Add(can); } } + GenerarLog(con, dni, $"Aceptado contrato"); return Guardar(con); } - public bool CancelarPrecontrato(long idcontrato) { + public bool CancelarPrecontrato(long idcontrato, long dni) { var con = Context; Contrato? cont = con.Contratos.Include(x=>x.IdpropiedadNavigation).FirstOrDefault(x=>x.Id ==idcontrato && x.Habilitado ==0); if (cont == null|| cont.IdpropiedadNavigation==null) return false; cont.Cancelado = 1; cont.IdpropiedadNavigation.Idestado = 1; + GenerarLog(con, dni, $"Cancelar Precontrato"); + return Guardar(con); } @@ -214,7 +219,7 @@ public class RepositorioContratos: RepositorioBase { return Guardar(con); } - public bool CargaPrecontratoOpcionVenta(Contrato c, Notificacione n, Venta v) { + public bool CargaPrecontratoOpcionVenta(Contrato c, Notificacione n, Venta v, long dni) { if (c == null || c.Habilitado == 1) return false; if (n == null) return false; var con = Context; @@ -233,6 +238,7 @@ public class RepositorioContratos: RepositorioBase { con.Ventas.Add(v); con.Contratos.Add(c); con.Notificaciones.Add(n); + GenerarLog(con, dni, $"Carga Precontrato con opcion venta"); return Guardar(con); } diff --git a/Modelo/RepositorioDefectos.cs b/Modelo/RepositorioDefectos.cs index df62251..fbbf099 100644 --- a/Modelo/RepositorioDefectos.cs +++ b/Modelo/RepositorioDefectos.cs @@ -4,18 +4,20 @@ using Microsoft.EntityFrameworkCore; namespace Modelo; public class RepositorioDefectos: RepositorioBase { - public bool AltaDefecto(Defecto defecto){ + public bool AltaDefecto(Defecto defecto, long dni){ var con = Context; defecto.Id = con.Defectos.Any()? con.Defectos.Count()+1 : 1; con.Defectos.Add(defecto); + GenerarLog(con, dni, $"Alta Defecto: {defecto.Id}"); return Guardar(con); } - public bool MarcarPago(long iddefecto){ + public bool MarcarPago(long iddefecto, long dni){ var con = Context; var d = con.Defectos.FirstOrDefault(x=>x.Id == iddefecto); if (d == null)return false; d.Idestado = 2; + GenerarLog(con, dni, $"Marcado Pago Defecto: {iddefecto}"); return Guardar(con); } diff --git a/Modelo/RepositorioGrupos.cs b/Modelo/RepositorioGrupos.cs index 81cc13d..2f5a476 100644 --- a/Modelo/RepositorioGrupos.cs +++ b/Modelo/RepositorioGrupos.cs @@ -4,19 +4,6 @@ using Microsoft.EntityFrameworkCore; namespace Modelo; public class RepositorioGrupos: RepositorioBase { - public bool CrearGrupo(string descripcion) - { - var con = Context; - - int mx = con.Grupos.Max(grupo => grupo.Id); - Grupo gru = new Grupo{ - Id = mx+1, - Nombre = descripcion, - }; - con.Grupos.Add(gru); - - return Guardar(con); - } public IQueryable ListarPermisosDeGrupo(string grupo) { var con = Context; diff --git a/Modelo/RepositorioPermisos.cs b/Modelo/RepositorioPermisos.cs index e92a993..a5d4445 100644 --- a/Modelo/RepositorioPermisos.cs +++ b/Modelo/RepositorioPermisos.cs @@ -49,18 +49,4 @@ public class RepositorioPermisos: RepositorioBase { return tienePermiso; } - -#if DEBUG - public bool CrearPermiso(string descripcion) { - var con = Context; - int mx = con.Permisos.Max(x => x.Id); - - Permiso per = new Permiso{ - Id = mx+1, - Descripcion = descripcion - }; - con.Permisos.Add(per); - return Guardar(con); - } -#endif } \ No newline at end of file diff --git a/Modelo/RepositorioPropiedades.cs b/Modelo/RepositorioPropiedades.cs index 62ba127..3439afe 100644 --- a/Modelo/RepositorioPropiedades.cs +++ b/Modelo/RepositorioPropiedades.cs @@ -70,7 +70,7 @@ public class RepositorioPropiedades: RepositorioBase { return (int)filasInsertadasParam.Value == 1? true: false; } - public bool PatchPropiedad(Propiedade prop) { + public bool PatchPropiedad(Propiedade prop, long dni) { var con = Context; Propiedade? propi = con.Propiedades.Include(x=>x.IdServicios).FirstOrDefault(x=>x.Id == prop.Id); @@ -90,7 +90,7 @@ public class RepositorioPropiedades: RepositorioBase { if (servi == null) return false; propi.IdServicios.Add(servi); } - + GenerarLog(con, dni, $"Se modificó: {prop.Id}"); return Guardar(con); } @@ -156,23 +156,23 @@ public class RepositorioPropiedades: RepositorioBase { }else{ prop.Idestado = 1; } - + GenerarLog(con, cli.Dni, $"Baja propiedad: {prop.Id}"); return Guardar(con); } - public bool BajaPropiedad(int id) { + public bool BajaPropiedad(int id, long dni) { var con = Context; Propiedade? prop = con.Propiedades.FirstOrDefault(x=>x.Id == id); if (prop == null||prop.Dnipropietario == 0) return false; prop.Idestado = prop.Idestado == 3 ? 1 : 3; - + GenerarLog(con, dni, $"Baja propiedad: {prop.Id}"); return Guardar(con); } - public bool BajaServiciosAPropiedad(int idprop, List idserv) { + public bool BajaServiciosAPropiedad(int idprop, List idserv, long dni) { var con = Context; Propiedade? prop = con.Propiedades.Include(x=>x.IdServicios).FirstOrDefault(x => x.Id == idprop); if (prop == null) return false; @@ -186,7 +186,7 @@ public class RepositorioPropiedades: RepositorioBase { prop.IdServicios.Remove(servicio); } } - + GenerarLog(con, dni, $"Baja servicios a propiedad: {prop.Id}"); return Guardar(con); } diff --git a/Modelo/RepositorioUsuarios.cs b/Modelo/RepositorioUsuarios.cs index f0dd6af..2b2684f 100644 --- a/Modelo/RepositorioUsuarios.cs +++ b/Modelo/RepositorioUsuarios.cs @@ -28,6 +28,7 @@ public class RepositorioUsuarios: RepositorioBase { if (cli.Dni == 0) return false; cli.Idgrupos.Add(grupo); + GenerarLog(con, cli.Dni, $"Alta Inquilino: {cli.Dni}"); return Guardar(con); } @@ -52,6 +53,7 @@ public class RepositorioUsuarios: RepositorioBase { if (cli.Dni == 0) return false; cli.Idgrupos.Add(grupo); + GenerarLog(con, cli.Dni, $"Alta Propietario: {cli.Dni}"); return Guardar(con); } @@ -67,7 +69,8 @@ public class RepositorioUsuarios: RepositorioBase { public bool CheckUsuario(LoginDto logindto) { - + if (logindto.Contraseña ==null)return false; + string Contraseña = HacerHash(logindto.Contraseña); Cliente? usu = Context.Clientes.FirstOrDefault(a => a.Email == logindto.Email); @@ -137,6 +140,7 @@ public class RepositorioUsuarios: RepositorioBase { } cli.Idgrupos.Add(gru); + GenerarLog(con, cli.Dni, $"Añadir grupo: {gru.Nombre}"); return Guardar(con); } @@ -150,6 +154,7 @@ public class RepositorioUsuarios: RepositorioBase { return false; } cli.Idgrupos.Remove(gru); + GenerarLog(con, cli.Dni, $"Eliminar de grupo: {gru.Nombre}"); return Guardar(con); } @@ -164,7 +169,7 @@ public class RepositorioUsuarios: RepositorioBase { } else { cli.Habilitado = 0; } - + GenerarLog(con, cli.Dni, $"Baja cliente id: {cli.Dni}"); return Guardar(con); } diff --git a/Modelo/RepositorioVentas.cs b/Modelo/RepositorioVentas.cs index 4ab7596..647cce6 100644 --- a/Modelo/RepositorioVentas.cs +++ b/Modelo/RepositorioVentas.cs @@ -51,7 +51,7 @@ public class RepositorioVentas: RepositorioBase { return venta; } - public bool PatchVenta(Venta venta) { + public bool PatchVenta(Venta venta, long dni) { var con = Context; var a = con.Ventas.FirstOrDefault(x=>x.Id == venta.Id); @@ -60,15 +60,16 @@ public class RepositorioVentas: RepositorioBase { a.Idpropiedad = venta.Idpropiedad; a.Fechainicio = venta.Fechainicio; a.Idestado=2; - + GenerarLog(con, dni, $"Se Ejercio la opcion de venta para la propiedad: {venta.Idpropiedad}"); return Guardar(con); } - public bool SetUrlRecibo(long id, string nuevoNombreArchivo) { + public bool SetUrlRecibo(long id, string nuevoNombreArchivo, long dni) { var con = Context; var venta = con.Ventas.FirstOrDefault(x=>x.Id == id); if (venta==null) return false; venta.UrlRecibo = nuevoNombreArchivo; + GenerarLog(con, dni, $"Se seteo el recibo con nombre: {nuevoNombreArchivo}"); return Guardar(con); } } \ No newline at end of file -- 2.52.0 From c7880b03b3b8181d595fe7380d78a13119e9d9b6 Mon Sep 17 00:00:00 2001 From: fede Date: Tue, 28 Jan 2025 01:30:50 -0300 Subject: [PATCH 04/16] api para obtener datos de los logs --- Aspnet/Controllers/LogsController.cs | 52 ++++++++++++++++++++++++++++ Entidades/Logs/LogDetalleDto.cs | 9 +++++ Entidades/Logs/LogDto.cs | 7 ++++ Modelo/RepositorioLogs.cs | 19 ++++++++++ 4 files changed, 87 insertions(+) create mode 100644 Aspnet/Controllers/LogsController.cs create mode 100644 Entidades/Logs/LogDetalleDto.cs create mode 100644 Entidades/Logs/LogDto.cs create mode 100644 Modelo/RepositorioLogs.cs diff --git a/Aspnet/Controllers/LogsController.cs b/Aspnet/Controllers/LogsController.cs new file mode 100644 index 0000000..fa3544c --- /dev/null +++ b/Aspnet/Controllers/LogsController.cs @@ -0,0 +1,52 @@ +using Entidades.Dto; +using Microsoft.AspNetCore.Mvc; +using Modelo; + +namespace AlquilaFacil.Controllers; + +[ApiController] +public class LogsController: ControllerBase { + + [HttpGet("/api/Logs")] + public IActionResult ObtenerLogs([FromHeader(Name = "Auth")] string Auth, long pag=1) { + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes"); + if (validacion1 == false) return Unauthorized(); + if (pag<=0) return BadRequest(new { message = "no puede haber una pagina 0 o menor"}); + + pag-=1; + + var l = RepositorioLogs.Singleton.ObtenerLogsPaginado(pag); + List ll = new(); + foreach (var i in l) { + ll.Add(new LogDto{ + Fecha = i.Fecha, + Accion = i.Accion, + Dniusuario = i.Dniusuario, + }); + } + return Ok(ll); + } + + [HttpGet("/api/Logs/detalle")] + public IActionResult ObtenerLogs([FromHeader(Name = "Auth")] string Auth, [FromQuery]DateTime fecha, [FromQuery]long idusuario) { + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes"); + if (validacion1 == false) return Unauthorized(); + if (idusuario<=0) return BadRequest(new { message = "no puede haber un id 0 o menor"}); + + var l = RepositorioLogs.Singleton.ObtenerDetallesLogs(fecha, idusuario); + List ll = new(); + foreach (var i in l) { + ll.Add(new LogDetalleDto{ + Fecha = i.Fecha, + Dniusuario = i.Dniusuario, + NombreTabla = i.NombreTabla, + Columna = i.Columna, + ValorAnterior = i.ValorAnterior, + ValorNuevo = i.ValorNuevo, + }); + } + return Ok(ll); + } +} \ No newline at end of file diff --git a/Entidades/Logs/LogDetalleDto.cs b/Entidades/Logs/LogDetalleDto.cs new file mode 100644 index 0000000..195d831 --- /dev/null +++ b/Entidades/Logs/LogDetalleDto.cs @@ -0,0 +1,9 @@ +namespace Entidades.Dto; +public class LogDetalleDto { + public DateTime Fecha { get; set; } + public long Dniusuario { get; set; } + public string NombreTabla { get; set; } = null!; + public string Columna { get; set; } = null!; + public string? ValorAnterior { get; set; } + public string? ValorNuevo { get; set; } +} \ No newline at end of file diff --git a/Entidades/Logs/LogDto.cs b/Entidades/Logs/LogDto.cs new file mode 100644 index 0000000..998ac45 --- /dev/null +++ b/Entidades/Logs/LogDto.cs @@ -0,0 +1,7 @@ +namespace Entidades.Dto; +public class LogDto { + public DateTime Fecha { get; set; } + public long Dniusuario { get; set; } + public string Accion { get; set; } = null!; +} + diff --git a/Modelo/RepositorioLogs.cs b/Modelo/RepositorioLogs.cs new file mode 100644 index 0000000..18f2d8f --- /dev/null +++ b/Modelo/RepositorioLogs.cs @@ -0,0 +1,19 @@ +using System.Linq; +using Entidades; +using Microsoft.EntityFrameworkCore; + +namespace Modelo; +public class RepositorioLogs: RepositorioBase { + public ICollection ObtenerDetallesLogs(DateTime fecha, long idusuario) { + var con = Context; + var d = con.Logs.Include(x=>x.LogDetalles) + .FirstOrDefault(x => x.Fecha == fecha && x.Dniusuario == idusuario); + return d.LogDetalles; + } + + public IQueryable? ObtenerLogsPaginado(int pag) { + var con = Context; + var l = con.Logs.Skip(10*pag).Take(10); + return l; + } +} \ No newline at end of file -- 2.52.0 From 72f277ab6c254cfa190a5c780256c43fa7b2e558 Mon Sep 17 00:00:00 2001 From: fede Date: Wed, 29 Jan 2025 01:59:16 -0300 Subject: [PATCH 05/16] lucas me pidio las lineas de codigo --- Aspnet/Controllers/AdminController.cs | 11 +- Aspnet/Controllers/LogsController.cs | 12 +- Aspnet/Controllers/VentaController.cs | 2 +- Entidades/Alquilafacilcontext.cs | 7 +- Entidades/Logdetalle.cs | 2 + Front/src/App.svelte | 6 + Front/src/Componentes/ModalLogs.svelte | 63 ++++++++++ .../src/Componentes/PaginacionStepper.svelte | 8 -- Front/src/paginas/VerLogs.svelte | 109 ++++++++++++++++++ Front/src/types.d.ts | 15 +++ Modelo/Facade/AuditoriaFacade.cs | 69 +++++++---- Modelo/Facade/PersistenciaLog.cs | 7 +- Modelo/RepositorioLogs.cs | 14 ++- Modelo/RepositorioUsuarios.cs | 8 +- 14 files changed, 289 insertions(+), 44 deletions(-) create mode 100644 Front/src/Componentes/ModalLogs.svelte create mode 100644 Front/src/paginas/VerLogs.svelte diff --git a/Aspnet/Controllers/AdminController.cs b/Aspnet/Controllers/AdminController.cs index 409aaae..50e76be 100644 --- a/Aspnet/Controllers/AdminController.cs +++ b/Aspnet/Controllers/AdminController.cs @@ -38,12 +38,15 @@ public class AdminController: ControllerBase var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9); if (validacion1 == false) return Unauthorized(); + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return BadRequest(new { message = "No hay un cliente por ese token"}); + if (data.email == "" || data.grupo == "") return BadRequest(new { message = "Faltan datos en la request" }); var ret = RepositorioUsuarios.Singleton.CheckGrupo(data.email, data.grupo); if (ret) return BadRequest(new { message = $"El usuario ya pertenece al grupo {data.grupo}"}); - var ret2 = RepositorioUsuarios.Singleton.AñadirClienteAGrupo(data.email, data.grupo); + var ret2 = RepositorioUsuarios.Singleton.AñadirClienteAGrupo(data.email, data.grupo, cli.Dni); return ret2 ? Ok(new {message = "Se Añadio al Grupo"}): BadRequest(new { message = "Fallo al añadirse al Grupo" }); } @@ -54,6 +57,10 @@ public class AdminController: ControllerBase var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9); if (validacion1 == false) return Unauthorized(); + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return BadRequest(new { message = "No hay un cliente por ese token"}); + + if (data.email == "" || data.grupo == "") return BadRequest(new { message = "Faltan datos en la request" }); //una ward para que no me bloquee a mi mismo de tener acceso a admin @@ -74,7 +81,7 @@ public class AdminController: ControllerBase if ( ret5 == null || ret5.Where(x=>x.Habilitado == 0).Count() > 0) return BadRequest(new { message = "Aun tenes alquileres pendientes o fallo al intentar obtener la lista de alquileres, no se puede dar de baja"}); } - var ret2 = RepositorioUsuarios.Singleton.EliminarClienteAGrupo(data.email, data.grupo); + var ret2 = RepositorioUsuarios.Singleton.EliminarClienteAGrupo(data.email, data.grupo, cli.Dni); return ret2 ? Ok(new {message = $"Se elimino del Grupo: {data.grupo}"}): BadRequest(new { message = "Fallo al añadirse al Grupo" }); } diff --git a/Aspnet/Controllers/LogsController.cs b/Aspnet/Controllers/LogsController.cs index fa3544c..c232bd1 100644 --- a/Aspnet/Controllers/LogsController.cs +++ b/Aspnet/Controllers/LogsController.cs @@ -8,7 +8,7 @@ namespace AlquilaFacil.Controllers; public class LogsController: ControllerBase { [HttpGet("/api/Logs")] - public IActionResult ObtenerLogs([FromHeader(Name = "Auth")] string Auth, long pag=1) { + public IActionResult ObtenerLogs([FromHeader(Name = "Auth")] string Auth, int pag=1) { if (String.IsNullOrEmpty(Auth)) return Unauthorized(); var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes"); if (validacion1 == false) return Unauthorized(); @@ -49,4 +49,14 @@ public class LogsController: ControllerBase { } return Ok(ll); } + + [HttpGet("/api/Logs/cantPag")] + public IActionResult cantidadPaginas([FromHeader(Name = "Auth")] string Auth){ + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes"); + if (validacion1 == false) return Unauthorized(); + + int c = RepositorioLogs.Singleton.ObtenerCantidadPaginas(); + return Ok(c); + } } \ No newline at end of file diff --git a/Aspnet/Controllers/VentaController.cs b/Aspnet/Controllers/VentaController.cs index b9cb319..ce2e1f7 100644 --- a/Aspnet/Controllers/VentaController.cs +++ b/Aspnet/Controllers/VentaController.cs @@ -44,7 +44,7 @@ public class VentaController:ControllerBase { } [HttpPost("/api/ventas/subirReciboPago")] - public async Task SubirRecibo([FromHeader(Name="Auth")]string Auth, [FromForm]IFormFile file, long idventa ) { + public async Task SubirRecibo([FromHeader(Name="Auth")]string Auth, IFormFile file, long idventa ) { if (String.IsNullOrWhiteSpace(Auth)) return Unauthorized(); var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); if (validacion1 == false){ diff --git a/Entidades/Alquilafacilcontext.cs b/Entidades/Alquilafacilcontext.cs index e860832..8ab6073 100644 --- a/Entidades/Alquilafacilcontext.cs +++ b/Entidades/Alquilafacilcontext.cs @@ -447,10 +447,15 @@ public partial class AlquilaFacilContext : DbContext modelBuilder.Entity(entity => { - entity.HasKey(e => new { e.Fecha, e.Dniusuario, e.NombreTabla, e.Columna }).HasName("PRIMARY"); + entity.HasKey(e => new { e.Id, e.Fecha, e.Dniusuario, e.NombreTabla, e.Columna }).HasName("PRIMARY"); entity.ToTable("LogDetalle"); + entity.HasIndex(e => new { e.Fecha, e.Dniusuario }, "LogDetalle_ibfk_1"); + + entity.Property(e => e.Id) + .HasColumnType("int(11)") + .HasColumnName("id"); entity.Property(e => e.Fecha) .HasColumnType("datetime") .HasColumnName("fecha"); diff --git a/Entidades/Logdetalle.cs b/Entidades/Logdetalle.cs index 4a9485c..db3946f 100644 --- a/Entidades/Logdetalle.cs +++ b/Entidades/Logdetalle.cs @@ -17,5 +17,7 @@ public partial class LogDetalle public string? ValorNuevo { get; set; } + public int Id { get; set; } + public virtual Log Log { get; set; } = null!; } diff --git a/Front/src/App.svelte b/Front/src/App.svelte index d5c2f3f..430f80e 100644 --- a/Front/src/App.svelte +++ b/Front/src/App.svelte @@ -24,6 +24,7 @@ import Informes from "./paginas/Informes.svelte"; import CompraYVentas from "./paginas/CompraYVenta.svelte"; import Ventas from "./paginas/Ventas.svelte"; + import VerLogs from "./paginas/VerLogs.svelte"; @@ -72,6 +73,11 @@ + + + + + diff --git a/Front/src/Componentes/ModalLogs.svelte b/Front/src/Componentes/ModalLogs.svelte new file mode 100644 index 0000000..28638a3 --- /dev/null +++ b/Front/src/Componentes/ModalLogs.svelte @@ -0,0 +1,63 @@ + + + \ No newline at end of file diff --git a/Front/src/Componentes/PaginacionStepper.svelte b/Front/src/Componentes/PaginacionStepper.svelte index 839947e..b57f0f8 100644 --- a/Front/src/Componentes/PaginacionStepper.svelte +++ b/Front/src/Componentes/PaginacionStepper.svelte @@ -1,6 +1,5 @@ diff --git a/Front/src/paginas/VerLogs.svelte b/Front/src/paginas/VerLogs.svelte new file mode 100644 index 0000000..8b29a8c --- /dev/null +++ b/Front/src/paginas/VerLogs.svelte @@ -0,0 +1,109 @@ + + + + +{#if modaldata} + !!(modaldata = "")}/> +{/if} + +{#if showmodal} + !!(showmodal=!showmodal)} log={ll}/> +{/if} + +
+ + + + + + + + + + + + {#each Logs as l} + + + + + + + {/each} + +
FechaId UsuarioAccion
{l.fecha}{l.dniusuario}{l.accion} + +
+ +
\ No newline at end of file diff --git a/Front/src/types.d.ts b/Front/src/types.d.ts index a23eeec..175ed29 100644 --- a/Front/src/types.d.ts +++ b/Front/src/types.d.ts @@ -164,4 +164,19 @@ export type VentasDto = { nombreComprador:string, idComprador:number, estado:string, +} + +export type LogDto = { + fecha:Date, + dniusuario:number, + accion:string +} + +export type LogDetalleDto = { + fecha:Date, + dniusuario:number, + nombreTabla:string, + columna:string, + valorAnterior:string, + valorNuevo:string } \ No newline at end of file diff --git a/Modelo/Facade/AuditoriaFacade.cs b/Modelo/Facade/AuditoriaFacade.cs index d455c70..949f7e9 100644 --- a/Modelo/Facade/AuditoriaFacade.cs +++ b/Modelo/Facade/AuditoriaFacade.cs @@ -44,14 +44,21 @@ public class AuditoriaFacade { var valorNuevo = cambio.CurrentValues[propiedad]?.ToString(); if (_validadorDeCambios.ValidarCambio(valorAnterior??"", valorNuevo??"")) { - logDetalles.Add(new LogDetalle { - Fecha = fechaActual, - Dniusuario = dniUsuario, - NombreTabla = nombreTabla, - Columna = propiedad.Name, - ValorAnterior = valorAnterior, - ValorNuevo = valorNuevo - }); + if (!_context.LogDetalles.Any(ld => + ld.Fecha == fechaActual && + ld.Dniusuario == dniUsuario && + ld.NombreTabla == nombreTabla && + ld.Columna == propiedad.Name)) + { + logDetalles.Add(new LogDetalle { + Fecha = fechaActual, + Dniusuario = dniUsuario, + NombreTabla = nombreTabla, + Columna = propiedad.Name, + ValorAnterior = valorAnterior, + ValorNuevo = valorNuevo + }); + } } } break; @@ -61,14 +68,21 @@ public class AuditoriaFacade { if (propiedad.Name == "Token") break; var valorNuevo = cambio.CurrentValues[propiedad]?.ToString(); - logDetalles.Add(new LogDetalle { - Fecha = fechaActual, - Dniusuario = dniUsuario, - NombreTabla = nombreTabla, - Columna = propiedad.Name, - ValorAnterior = null, - ValorNuevo = valorNuevo - }); + if (!_context.LogDetalles.Any(ld => + ld.Fecha == fechaActual && + ld.Dniusuario == dniUsuario && + ld.NombreTabla == nombreTabla && + ld.Columna == propiedad.Name)) + { + logDetalles.Add(new LogDetalle { + Fecha = fechaActual, + Dniusuario = dniUsuario, + NombreTabla = nombreTabla, + Columna = propiedad.Name, + ValorAnterior = null, + ValorNuevo = valorNuevo + }); + } } break; @@ -77,14 +91,21 @@ public class AuditoriaFacade { if (propiedad.Name == "Token") break; var valorAnterior = cambio.OriginalValues[propiedad]?.ToString(); - logDetalles.Add(new LogDetalle { - Fecha = fechaActual, - Dniusuario = dniUsuario, - NombreTabla = nombreTabla, - Columna = propiedad.Name, - ValorAnterior = valorAnterior, - ValorNuevo = null - }); + if (!_context.LogDetalles.Any(ld => + ld.Fecha == fechaActual && + ld.Dniusuario == dniUsuario && + ld.NombreTabla == nombreTabla && + ld.Columna == propiedad.Name)) + { + logDetalles.Add(new LogDetalle { + Fecha = fechaActual, + Dniusuario = dniUsuario, + NombreTabla = nombreTabla, + Columna = propiedad.Name, + ValorAnterior = valorAnterior, + ValorNuevo = null + }); + } } break; diff --git a/Modelo/Facade/PersistenciaLog.cs b/Modelo/Facade/PersistenciaLog.cs index 7b51b5d..90342a7 100644 --- a/Modelo/Facade/PersistenciaLog.cs +++ b/Modelo/Facade/PersistenciaLog.cs @@ -4,8 +4,13 @@ public class PersistenciaLog { private AlquilaFacilContext _context {get{return new AlquilaFacilContext();}} public void GuardarLog(Log log, IEnumerable detalles) { var con = _context; + int j = 1; + foreach (var i in log.LogDetalles) { + i.Id = j; + j++; + } con.Logs.Add(log); - con.LogDetalles.AddRange(detalles); + //con.LogDetalles.AddRange(detalles); con.SaveChanges(); } } diff --git a/Modelo/RepositorioLogs.cs b/Modelo/RepositorioLogs.cs index 18f2d8f..b558a56 100644 --- a/Modelo/RepositorioLogs.cs +++ b/Modelo/RepositorioLogs.cs @@ -4,11 +4,21 @@ using Microsoft.EntityFrameworkCore; namespace Modelo; public class RepositorioLogs: RepositorioBase { - public ICollection ObtenerDetallesLogs(DateTime fecha, long idusuario) { + public int ObtenerCantidadPaginas() { + var con = Context; + float a = con.Logs.Count()/10f; + int b = (int)a; + if (b != a){ + b++; + } + return b; + } + + public IOrderedEnumerable ObtenerDetallesLogs(DateTime fecha, long idusuario) { var con = Context; var d = con.Logs.Include(x=>x.LogDetalles) .FirstOrDefault(x => x.Fecha == fecha && x.Dniusuario == idusuario); - return d.LogDetalles; + return d.LogDetalles.OrderBy(x=>x.Id); } public IQueryable? ObtenerLogsPaginado(int pag) { diff --git a/Modelo/RepositorioUsuarios.cs b/Modelo/RepositorioUsuarios.cs index 2b2684f..fae8e0d 100644 --- a/Modelo/RepositorioUsuarios.cs +++ b/Modelo/RepositorioUsuarios.cs @@ -129,7 +129,7 @@ public class RepositorioUsuarios: RepositorioBase { return list; } - public bool AñadirClienteAGrupo(string email, string grupo) { + public bool AñadirClienteAGrupo(string email, string grupo, long dni) { var con = Context; var cli = con.Clientes.Include(x => x.Idgrupos).FirstOrDefault(x => x.Email == email); @@ -140,11 +140,11 @@ public class RepositorioUsuarios: RepositorioBase { } cli.Idgrupos.Add(gru); - GenerarLog(con, cli.Dni, $"Añadir grupo: {gru.Nombre}"); + GenerarLog(con, dni, $"Añadir grupo: {gru.Nombre}"); return Guardar(con); } - public bool EliminarClienteAGrupo(string email, string grupo) { + public bool EliminarClienteAGrupo(string email, string grupo, long dniresponsable) { var con = Context; var cli = con.Clientes.Include(x => x.Idgrupos).FirstOrDefault(x => x.Email == email); @@ -154,7 +154,7 @@ public class RepositorioUsuarios: RepositorioBase { return false; } cli.Idgrupos.Remove(gru); - GenerarLog(con, cli.Dni, $"Eliminar de grupo: {gru.Nombre}"); + GenerarLog(con, dniresponsable, $"Eliminar de grupo: {gru.Nombre}"); return Guardar(con); } -- 2.52.0 From ccf909e825ed133894fd308a1340950b04682269 Mon Sep 17 00:00:00 2001 From: fede Date: Wed, 29 Jan 2025 02:47:40 -0300 Subject: [PATCH 06/16] =?UTF-8?q?arreglada=20una=20cosa=20en=20form=20defe?= =?UTF-8?q?ctos=20y=20tambien=20a=C3=B1adido=20soporte=20daltonismo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Front/src/Componentes/FormAltaDefecto.svelte | 4 ++-- Front/src/paginas/Informes.svelte | 21 +++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Front/src/Componentes/FormAltaDefecto.svelte b/Front/src/Componentes/FormAltaDefecto.svelte index 2cf9067..1b05669 100644 --- a/Front/src/Componentes/FormAltaDefecto.svelte +++ b/Front/src/Componentes/FormAltaDefecto.svelte @@ -59,7 +59,7 @@ id="danioUso" class="form-check-input" bind:group={formData.pagainquilino} - value="0" + value="1" required /> @@ -70,7 +70,7 @@ id="danioEstructural" class="form-check-input" bind:group={formData.pagainquilino} - value="1" + value="0" /> diff --git a/Front/src/paginas/Informes.svelte b/Front/src/paginas/Informes.svelte index 0802bd7..11cc20c 100644 --- a/Front/src/paginas/Informes.svelte +++ b/Front/src/paginas/Informes.svelte @@ -2,21 +2,19 @@ import { onMount } from "svelte"; import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte"; import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte"; - import { Chart } from "chart.js"; import FChart from "../Componentes/Estadisticas/fChart.svelte"; import ModalEstatico from "../Componentes/ModalEstatico.svelte"; import {urlG} from "../stores/urlStore"; import type { ChartData } from "../types"; - import { text } from "@sveltejs/kit"; let token = sessionStorage.getItem("token")||""; let y = $state(2025); let cdata:ChartData|any = $state(); - let aldata:{id:number, ubicacion:string, divisa:string}|any = $state(); + let aldata:{id:number, ubicacion:string, divisa:string}[]= $state([]); let chartMesesDuracion:ChartData|any = $state(); - let tablaMesesDuracion:{meses:number, repes:number, semaforizacion:string}|any = $state(); + let tablaMesesDuracion:{meses:number, repes:number, semaforizacion:string}[] = $state([]); let modaldata:string = $state(""); @@ -74,6 +72,18 @@ modaldata="Fallo al intentar alcanzar el servidor"; } } + + function toggleModoDaltonico() { + if (tablaMesesDuracion== null) return; + + tablaMesesDuracion.forEach(item => { + if (item.semaforizacion === '🟢') { + item.semaforizacion = '🔵'; + } else if (item.semaforizacion === '🔵') { + item.semaforizacion = '🟢'; + } + }); + } {#if modaldata} @@ -103,7 +113,7 @@
- +
@@ -154,6 +164,7 @@

Objetivo: Mide la longitud de los contratos en meses y cuantos hay por cada longitud. por lo menos 2.

+ Activar Modo Daltónico
-- 2.52.0 From 333ee5d326430fd5d5bd892013e7f489ac25a9e7 Mon Sep 17 00:00:00 2001 From: fede Date: Thu, 30 Jan 2025 00:44:04 -0300 Subject: [PATCH 07/16] centrado stepper y invertido orden de logs --- Front/src/paginas/VerLogs.svelte | 8 +++++--- Modelo/RepositorioLogs.cs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Front/src/paginas/VerLogs.svelte b/Front/src/paginas/VerLogs.svelte index 8b29a8c..1ba00e3 100644 --- a/Front/src/paginas/VerLogs.svelte +++ b/Front/src/paginas/VerLogs.svelte @@ -14,7 +14,7 @@ let modaldata:string = $state(""); let showmodal:boolean =$state(false); let ll:LogDto|any = $state({}); - let cantpag:number = $state(100); + let cantpag:number = $state(0); onMount(()=>{ obtenerLogs(); @@ -105,5 +105,7 @@ {/each}
- -
\ No newline at end of file +
+ +
+ diff --git a/Modelo/RepositorioLogs.cs b/Modelo/RepositorioLogs.cs index b558a56..d03d46b 100644 --- a/Modelo/RepositorioLogs.cs +++ b/Modelo/RepositorioLogs.cs @@ -23,7 +23,7 @@ public class RepositorioLogs: RepositorioBase { public IQueryable? ObtenerLogsPaginado(int pag) { var con = Context; - var l = con.Logs.Skip(10*pag).Take(10); + var l = con.Logs.OrderByDescending(x=>x.Fecha).Skip(10*pag).Take(10); return l; } } \ No newline at end of file -- 2.52.0 From ac2de7117991a54f4e0c7b27eea6996f9d0a02db Mon Sep 17 00:00:00 2001 From: fede Date: Thu, 30 Jan 2025 04:47:37 -0300 Subject: [PATCH 08/16] bueno ahora se pueden modificar los clientes --- Aspnet/Controllers/AdminController.cs | 49 +++++++++++ Entidades/Admin/UpdateUsuarioAdmin.cs | 8 ++ .../ModalModificarPropietarios.svelte | 54 ++++++++++++ Front/src/paginas/AdminUsuarios.svelte | 87 ++++++++++++++++--- Front/src/types.d.ts | 8 ++ Modelo/RepositorioUsuarios.cs | 15 ++++ 6 files changed, 210 insertions(+), 11 deletions(-) create mode 100644 Entidades/Admin/UpdateUsuarioAdmin.cs create mode 100644 Front/src/Componentes/ModalModificarPropietarios.svelte diff --git a/Aspnet/Controllers/AdminController.cs b/Aspnet/Controllers/AdminController.cs index 50e76be..04286d8 100644 --- a/Aspnet/Controllers/AdminController.cs +++ b/Aspnet/Controllers/AdminController.cs @@ -21,6 +21,46 @@ public class AdminController: ControllerBase return Ok(list); } + [HttpGet("api/admin/cliente")] + public IActionResult ObtenerCliente([FromHeader(Name ="Auth")]string Auth, long dni = 0){ + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9); + if (validacion1 == false) return Unauthorized(); + if (dni <= 0) return BadRequest(new { message = "No puede haber un dni 0 o menor"}); + + Cliente? cambio = RepositorioUsuarios.Singleton.ObtenerClientePorDni(dni); + if (cambio == null) BadRequest(new { message = "no hay un cliente por ese dni"}); + + UpdateUsuarioAdmin a = new UpdateUsuarioAdmin{ + Apellido = cambio.Apellido, + Celular = cambio.Celular, + Domicilio = cambio.Domicilio, + Nombre = cambio.Nombre, + }; + + return Ok(a); + } + + [HttpPatch("api/admin/cliente")] + public IActionResult PatchCliente([FromHeader(Name ="Auth")]string Auth, [FromBody]UpdateUsuarioAdmin dto, [FromQuery]long dni=0){ + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9); + if (validacion1 == false) return Unauthorized(); + if (dni <= 0) return BadRequest(new { message = "No puede haber un dni 0 o menor"}); + + var validacion2 = checkdto(dto); + if (validacion2 != "") return BadRequest(new { message = validacion2}); + + Cliente?cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + bool ret = RepositorioUsuarios.Singleton.PatchUsuario(dto, dni, cli.Dni); + + return ret? + Ok(new { message = "Se actualizaron los datos"}): + BadRequest(new { message = "Fallo al guardar los datos"}); + } + [HttpGet("api/admin/clientes/grupo")] public IActionResult GetGruposByCliente([FromHeader(Name ="Auth")]string Auth, [FromQuery]long Dni){ if (String.IsNullOrEmpty(Auth)) return Unauthorized(); @@ -159,4 +199,13 @@ public class AdminController: ControllerBase int ret = RepositorioPropiedades.Singleton.CuantasPaginasBusqueda(cantidadHabitaciones, servicios, tipoPropiedad, 0); return Ok(new { message = ret}); } + + private string checkdto(UpdateUsuarioAdmin d){ + string ret =""; + if (d.Nombre=="") ret+="Campo Nombre vacio\n"; + if (d.Apellido=="") ret+="Campo Apellido vacio\n"; + if (d.Celular=="") ret+="Campo Celular vacio\n"; + if (d.Domicilio=="")ret+="Campo Domicilio vacio\n"; + return ret; + } } \ No newline at end of file diff --git a/Entidades/Admin/UpdateUsuarioAdmin.cs b/Entidades/Admin/UpdateUsuarioAdmin.cs new file mode 100644 index 0000000..97846fc --- /dev/null +++ b/Entidades/Admin/UpdateUsuarioAdmin.cs @@ -0,0 +1,8 @@ +namespace Entidades.Admin; +public class UpdateUsuarioAdmin { + public string Nombre { get; set; } = null!; + public string Apellido { get; set; } = null!; + public string Domicilio { get; set; } = null!; + public string Celular { get; set; } = null!; + +} \ No newline at end of file diff --git a/Front/src/Componentes/ModalModificarPropietarios.svelte b/Front/src/Componentes/ModalModificarPropietarios.svelte new file mode 100644 index 0000000..8a0f07b --- /dev/null +++ b/Front/src/Componentes/ModalModificarPropietarios.svelte @@ -0,0 +1,54 @@ + + + \ No newline at end of file diff --git a/Front/src/paginas/AdminUsuarios.svelte b/Front/src/paginas/AdminUsuarios.svelte index 2bca06b..da3c5d2 100644 --- a/Front/src/paginas/AdminUsuarios.svelte +++ b/Front/src/paginas/AdminUsuarios.svelte @@ -1,11 +1,13 @@ @@ -148,13 +205,18 @@ !!(modaldata = "")}/> {/if} +{#if showModificarCliente} +!!(showModificarCliente = false)} + onConfirm={patchCliente}/> +{/if} +
-
+
- +
@@ -171,14 +233,17 @@ {/each} @@ -186,7 +251,7 @@
Dni{cli.email} {#if cli.habilitado} - {:else} - {/if} +
-
+
@@ -208,11 +273,11 @@ {/each} {:else if SelCliente != null} - + {:else} - + {/if} diff --git a/Front/src/types.d.ts b/Front/src/types.d.ts index 175ed29..89acc40 100644 --- a/Front/src/types.d.ts +++ b/Front/src/types.d.ts @@ -179,4 +179,12 @@ export type LogDetalleDto = { columna:string, valorAnterior:string, valorNuevo:string +} + +export type UpdateCliente = { + dni:number, + nombre:string, + apellido:string, + domicilio:string, + celular:string, } \ No newline at end of file diff --git a/Modelo/RepositorioUsuarios.cs b/Modelo/RepositorioUsuarios.cs index fae8e0d..08bec3f 100644 --- a/Modelo/RepositorioUsuarios.cs +++ b/Modelo/RepositorioUsuarios.cs @@ -3,6 +3,7 @@ using System.Text; using Entidades.Dto; using Entidades; using Microsoft.EntityFrameworkCore; +using Entidades.Admin; namespace Modelo; @@ -186,4 +187,18 @@ public class RepositorioUsuarios: RepositorioBase { if (cli == null|| cli.Dni == 0) return null; return cli; } + + public bool PatchUsuario(UpdateUsuarioAdmin dto, long dni, long responsabledni) { + var con = Context; + var usu = con.Clientes.FirstOrDefault(x=>x.Dni ==dni); + if (usu == null) return false; + + usu.Nombre = dto.Nombre; + usu.Apellido = dto.Apellido; + usu.Celular = dto.Celular; + usu.Domicilio = dto.Domicilio; + + GenerarLog(con, responsabledni, "Patch Usuario"); + return Guardar(con); + } } -- 2.52.0 From 029f8e5fce8392a1e3b90d2c0178009b2fb40f22 Mon Sep 17 00:00:00 2001 From: fede Date: Thu, 30 Jan 2025 17:24:03 -0300 Subject: [PATCH 09/16] hecho rf 16 --- Aspnet/Controllers/EstadisticaController.cs | 13 +++++ Front/src/paginas/ContratosPropietario.svelte | 47 +++++++++++++++++-- Modelo/RepositorioEstadisticas.cs | 29 ++++++++++++ 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/Aspnet/Controllers/EstadisticaController.cs b/Aspnet/Controllers/EstadisticaController.cs index 93db4df..b00e5d9 100644 --- a/Aspnet/Controllers/EstadisticaController.cs +++ b/Aspnet/Controllers/EstadisticaController.cs @@ -17,6 +17,19 @@ public class EstadisticaController: ControllerBase { var a = RepositorioEstadisticas.Singleton.ObtenerDataIniciadosPorAño(year); return Ok(a); } + + [HttpGet("api/contrato/stats")] + public IActionResult ObtenerMesesPagos([FromHeader(Name ="Auth")]string Auth, long idcontrato=0){ + if (String.IsNullOrWhiteSpace(Auth)) return BadRequest(""); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) return Unauthorized(); + + if (idcontrato<=0) return BadRequest(new {message = "No puede tener un id contrato menor o igual a 0"}); + + var ret = RepositorioEstadisticas.Singleton.ObtenerDatosPagosContrato(idcontrato); + return Ok(ret); + } + [HttpGet("api/tabla/alquileresIniciados")] public IActionResult tablaalquileresIniciadosEsteAño([FromHeader(Name ="Auth")]string Auth, int year) { if (String.IsNullOrWhiteSpace(Auth)) return BadRequest(""); diff --git a/Front/src/paginas/ContratosPropietario.svelte b/Front/src/paginas/ContratosPropietario.svelte index db9e19e..8e4c246 100644 --- a/Front/src/paginas/ContratosPropietario.svelte +++ b/Front/src/paginas/ContratosPropietario.svelte @@ -3,12 +3,12 @@ import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte"; import ModalEstatico from "../Componentes/ModalEstatico.svelte"; import {urlG} from "../stores/urlStore"; - import type { CanonDto, ContratoDto, ContratoPropiedadDto, DefectoDto, GaranteDto2, OpcionVentaDto } from "../types"; + import type { CanonDto, ChartData, ContratoDto, ContratoPropiedadDto, DefectoDto, GaranteDto2, OpcionVentaDto } from "../types"; import ModalConfirm from "../Componentes/ModalConfirm.svelte"; import ModalPedirDoc from "../Componentes/ModalPedirDoc.svelte"; import ModalNotificacion from "../Componentes/ModalNotificacion.svelte"; import { navigate } from "svelte-routing"; - + import FChart from "../Componentes/Estadisticas/fChart.svelte"; let token:string = sessionStorage.getItem("token")||""; @@ -16,6 +16,7 @@ let selMod:any =$state(); let showmodal:boolean = $state(false); let shownotif:boolean = $state(false); + let chartData:ChartData|any = $state(); let max:number=$state(0); @@ -47,8 +48,26 @@ await obtenerDatosACargar(); max = canons.at(-1).mesNum||0; opcionVenta(); - + await setChartData(); }); + async function setChartData() { + try{ + const r = await fetch($urlG+"/api/contrato/stats?idcontrato="+contratoid, { + method: "GET", + headers: { + "Auth": String(token), + } + }); + let data = await r.json(); + if (r.ok){ + chartData = data; + return; + } + modaldata = data.message; + }catch{ + modaldata = "no se pudo obtener el chartdata"; + } + } async function opcionVenta() { try { @@ -309,7 +328,6 @@ if (r.ok) { refreshDefectos(); } - }catch { modaldata = "No se pudo marcar como pago"; } @@ -424,6 +442,27 @@ +
+

+ +

+
+
+
+ {#if chartData != null} + + {/if} +
+
+
+

- {#if !necesitaRecibo} + {#if !necesitaRecibo && venta.estado !="Vendido"}

-- 2.52.0 From b98cf77807859fac03dc21c5feb8835d69ff53fc Mon Sep 17 00:00:00 2001 From: fede Date: Thu, 30 Jan 2025 18:11:14 -0300 Subject: [PATCH 11/16] ahora genera csv para excel --- Front/src/paginas/ContratosPropietario.svelte | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/Front/src/paginas/ContratosPropietario.svelte b/Front/src/paginas/ContratosPropietario.svelte index 8e4c246..d363aef 100644 --- a/Front/src/paginas/ContratosPropietario.svelte +++ b/Front/src/paginas/ContratosPropietario.svelte @@ -348,6 +348,35 @@ } } + + function generarCSVEstadistica() { + let contenido = ["Categorias", ...chartData.datasets.map((d: { label: any; }) => d.label)].join(",") + "\n"; + + chartData.labels.forEach((label: any, index: string | number) => { + let fila = [label, ...chartData.datasets.map((d: { data: { [x: string]: any; }; }) => d.data[index])].join(","); + contenido += fila + "\n"; + }); + + contenido += "\n"; + + + if (canons.length > 0) { + contenido += "ID,Mes Num,Mes,Monto,Divisa,Pago\n"; + canons.forEach(c => { + let fila = [c.id, c.mesNum, String(c.mes).split("T")[0], c.monto, c.divisa, c.pago ? "Sí" : "No"].join(","); + contenido += fila + "\n"; + }); + } + + let blob = new Blob([contenido], { type: "text/csv" }); + let url = URL.createObjectURL(blob); + let a = document.createElement("a"); + a.href = url; + a.download = "chart_data.csv"; + a.click(); + URL.revokeObjectURL(url); + + } @@ -455,10 +484,13 @@
-
+
{#if chartData != null} {/if} +
@@ -508,7 +540,6 @@
{/each} {#if max < prop.mesesDuracion} - {$inspect(max)}
Definir el interés para los siguientes Canones -- 2.52.0 From 68745cab5ec71a9fa77b51f4130bfadc894bed11 Mon Sep 17 00:00:00 2001 From: fede Date: Thu, 30 Jan 2025 23:27:47 -0300 Subject: [PATCH 12/16] =?UTF-8?q?Est=C3=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Aspnet/Controllers/AdminController.cs | 206 +++++++++++++++ Aspnet/Controllers/ContratoController.cs | 4 +- Entidades/Admin/NotificarAdmin.cs | 6 + Front/src/App.svelte | 13 +- Front/src/paginas/ContratoAdmin.svelte | 316 +++++++++++++++++++++++ Front/src/paginas/ControlPagos.svelte | 93 +++++++ Modelo/RepositorioCanons.cs | 10 +- Modelo/RepositorioContratos.cs | 13 + Modelo/RepositorioNotificaciones.cs | 5 +- 9 files changed, 660 insertions(+), 6 deletions(-) create mode 100644 Entidades/Admin/NotificarAdmin.cs create mode 100644 Front/src/paginas/ContratoAdmin.svelte create mode 100644 Front/src/paginas/ControlPagos.svelte diff --git a/Aspnet/Controllers/AdminController.cs b/Aspnet/Controllers/AdminController.cs index 04286d8..008551d 100644 --- a/Aspnet/Controllers/AdminController.cs +++ b/Aspnet/Controllers/AdminController.cs @@ -6,11 +6,217 @@ using Entidades; using System.Linq.Expressions; using AlquilaFacil.StrategyBusquedaAdmin; using System.Diagnostics; +using AlquilaFacil.Builder; +using Minio.DataModel.Args; +using Minio; +using AlquilaFacil.Config; +using System.Text.Json; namespace AlquilaFacil.Controllers; [ApiController] public class AdminController: ControllerBase { + + [HttpGet("api/contratos/controlPagos")] + public IActionResult obtenerContratosInpagos([FromHeader(Name = "Auth")] string Auth) { + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 14); + if (validacion1 == false) return Unauthorized(); + + var contratos = RepositorioContratos.Singleton.ObtenerContratosInpagos(); + + List dtos = new(); + foreach (var i in contratos) { + if (i.DniinquilinoNavigation == null || i.IdpropiedadNavigation == null + || i.DnipropietarioNavigation == null) continue; + + var cont = new ContratoDtoBuilder() + .SetInquilino($"{i.DniinquilinoNavigation.Nombre} {i.DniinquilinoNavigation.Apellido}") + .SetUbicacion(i.IdpropiedadNavigation.Ubicacion) + .SetPropietario($"{i.DnipropietarioNavigation.Nombre} {i.DnipropietarioNavigation.Apellido}") + .SetId(i.Id) + .SetTipo(i.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion) + .SetFechaInicio(i.Fechainicio) + .SetEstado(i.Habilitado, i.Cancelado) + .Build(); + dtos.Add(cont); + } + return Ok(dtos); + } + + [HttpGet("api/contratos/controlPagos/propiedad")] + public IActionResult obtenerPropiedad([FromHeader(Name = "Auth")] string Auth, int id = 0) { + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Admin"); + if (validacion1 == false) return Unauthorized(); + + if (id <= 0) return BadRequest(new { message = "No hay propiedades con id igual o menor a 0"}); + var i = RepositorioContratos.Singleton.ObtenerContratoPorId(id); + if (i == null || i.DniinquilinoNavigation == null || + i.IdpropiedadNavigation == null || i.DnipropietarioNavigation == null)return BadRequest(new { message = "Fallo la query"}); + + var cont = new ContratoPropiedadDtoBuilder() + .SetInquilino($"{i.DniinquilinoNavigation.Nombre} {i.DniinquilinoNavigation.Apellido}") + .SetUbicacion(i.IdpropiedadNavigation.Ubicacion) + .SetId(i.Id) + .SetPropietario($"{i.DnipropietarioNavigation.Nombre} {i.DnipropietarioNavigation.Apellido}") + .SetTipo(i.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion) + .SetFechaInicio(i.Fechainicio) + .SetEstado(i.Habilitado, i.Cancelado) + .SetHabitaciones(i.IdpropiedadNavigation.Canthabitaciones) + .SetPiso(i.IdpropiedadNavigation.Piso??0) + .SetLetra(i.IdpropiedadNavigation.Letra??"") + .SetMesesAumento(i.MesesHastaAumento) + .SetMesesDuracion(i.MesesDurationContrato) + .Build(); + + return Ok(cont); + } + + private readonly IMinioClient mc; + public AdminController(IMinioClient minioClient) { + mc = minioClient; + if (mc == null){ + MinioConfigcus? mcon = JsonSerializer.Deserialize(System.IO.File.ReadAllText("./settings.json"))?? null; + if (mcon == null) throw new Exception(); + + mc = new MinioClient().WithCredentials(mcon.usr, mcon.scrt) + .WithEndpoint("192.168.1.11:9000") + .WithSSL(false) + .Build(); + } + } + [HttpGet("/api/admin/contrato/verDocumento")] + public IActionResult verDocumento([FromHeader(Name = "Auth")] string Auth, int idcontrato = 0){ + if (String.IsNullOrWhiteSpace(Auth)) return BadRequest(""); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Admin"); + if (validacion1 == false) return Unauthorized(); + + if (idcontrato <= 0) return BadRequest(new {message = "La id no puede ser igual o menor a 0"}); + + Contrato? contr = RepositorioContratos.Singleton.ObtenerContratoPorId(idcontrato); + + try{ + var memstream = new MemoryStream(); + + var goa = new GetObjectArgs() + .WithBucket("alquilafacil") + .WithObject(contr.UrlContrato) + .WithCallbackStream(stream => { + memstream.Position=0; + stream.CopyTo(memstream); + }); + + mc.GetObjectAsync(goa).Wait(); + memstream.Position = 0; + + if (memstream.Length == 0) return BadRequest(new { message = "El archivo está vacío" }); + + return File(memstream, "application/pdf", contr.UrlContrato); + + } catch (Exception e){ + Console.Error.WriteLine(e); + return BadRequest(new { message = "Fallo al intentar obtener el archivo del almacenamiento o este no existe"}); + } + } + + [HttpGet("api/admin/contrato/canons")] + public IActionResult ObtenerCanones([FromHeader(Name="Auth")]string Auth, int id = 0){ + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Admin"); + if (validacion1 == false) return Unauthorized(); + + var cont = RepositorioContratos.Singleton.ObtenerContratoPorId(id); + if (cont == null) return BadRequest(new { message = "No existe el contrato"}); + + var list = RepositorioCanons.Singleton.ObtenerCanonsPorContrato(id); + if (list == null) return BadRequest(new { message = "No hay contrato por esa id"}); + + DateTime date = DateTime.Now; + bool ret =list.Any(x=>x.Pagado ==0 && date > x.Fecha); + if (ret == true) return BadRequest(new { message = "Este contrato no tiene canones vencidos"}); + + string divisa =""; + if (cont.Iddivisa == 0) divisa = "AR$"; else if (cont.Iddivisa == 1) divisa = "US$"; + + List d = new(); + + foreach (var i in list) { + var c = new CanonDtoBuilder() + .SetId(i.Id) + .SetPago(i.Idrecibo==null?false:true) + .SetDivisa(divisa==""?"Ugh esta mal cargado la divisa en el contrato":divisa) + .SetMes(i.Fecha) + .SetMesNum(int.Parse((i.Fecha.Month - cont.Fechainicio.Month).ToString()) + 1) + .SetMonto(i.Monto) + .Build(); + d.Add(c); + } + + return Ok(d); + } + + [HttpPost("api/admin/contrato/marcarPago")] + public IActionResult realizarPago([FromHeader(Name="Auth")]string Auth, MarcarPagoDto dto) { + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Admin"); + if (validacion1 == false) return Unauthorized(); + + if (dto.Idcontrato<=0) return BadRequest(new { message = "No puede existir un contrato con id 0 o menor"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null)return Unauthorized(); + + Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(dto.Idcontrato); + if (cont == null) return BadRequest(new { message = "No hay un contrato por esa id"}); + + Canon? c = RepositorioCanons.Singleton.ObtenerCanonContrato(dto.fecha, dto.Idcontrato); + if (c == null) return BadRequest(new { message = "no hay un canon por esa id"}); + + Recibo re = new Recibo{ + Monto = c.Monto, + Fecha = DateTime.Now, + }; + + bool ret = RepositorioCanons.Singleton.SetRecibo(c, re, cli.Dni, "Admin Marca Recibo Como Pago"); + return ret ? + Ok(new { message = "Se guardo correctamente"}):BadRequest(new { message = "No se pudo guardar"}); + } + + [HttpPost("api/admin/notificarInquilino")] + public IActionResult NotificarInquilino([FromHeader(Name ="Auth")]string Auth, NotificarAdmin data){ + if (String.IsNullOrEmpty(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Admin"); + if (validacion1 == false) return Unauthorized(); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null)return Unauthorized(); + + if (data.Mensaje == "") return BadRequest(new {message = "El campo Mensaje esta vacio"}); + if (data.Idcontrato <= 0) return BadRequest(new {message = "La id de contrato no puede ser 0 o menor"}); + if (data.Idcanon <= 0) return BadRequest(new {message = "La id de contrato no puede ser 0 o menor"}); + + Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(data.Idcontrato); + if (cont == null || cont.DniinquilinoNavigation == null || cont.DnipropietarioNavigation == null || cont.IdpropiedadNavigation == null) return BadRequest(new { message = "no hay un contrato por esa id"}); + + Canon? can = RepositorioCanons.Singleton.ObtenerCanonPorId(data.Idcanon); + if (can == null)return BadRequest(new { message = "No existe un canon por esa id"}); + + var n = new NotificacioneBuilder() + .SetAccion("Notificacion Inquilino") + .SetMensaje(data.Mensaje) + .SetLeido(false) + .SetDnicliente(cont.DniinquilinoNavigation.Dni) + .SetDniremitente(cont.DnipropietarioNavigation.Dni) + .SetIdpropiedad(cont.IdpropiedadNavigation.Id) + .SetFecha(DateTime.Now) + .Build(); + var ret = RepositorioNotificaciones.Singleton.AltaNotificacion(n, cli.Dni); + return ret? + Ok(new { message = "se envio el aviso" }):BadRequest(new { message = "Fallo al intentar enviar el aviso" }); + + } + [HttpGet("api/admin/clientes")] public IActionResult GetClientes([FromHeader(Name ="Auth")]string Auth){ if (String.IsNullOrEmpty(Auth)) return Unauthorized(); diff --git a/Aspnet/Controllers/ContratoController.cs b/Aspnet/Controllers/ContratoController.cs index 23d34f7..1f45809 100644 --- a/Aspnet/Controllers/ContratoController.cs +++ b/Aspnet/Controllers/ContratoController.cs @@ -82,7 +82,7 @@ public class ContratoController: ControllerBase { Recibo re = new Recibo{ Monto = c.Monto, - Fecha = c.Fecha, + Fecha = DateTime.Now, }; bool ret = RepositorioCanons.Singleton.SetRecibo(c, re, cli.Dni); @@ -111,7 +111,7 @@ public class ContratoController: ControllerBase { Recibo re = new Recibo{ Monto = c.Monto, - Fecha = c.Fecha, + Fecha = DateTime.Now, }; bool ret = RepositorioCanons.Singleton.SetRecibo(c, re, cli.Dni); diff --git a/Entidades/Admin/NotificarAdmin.cs b/Entidades/Admin/NotificarAdmin.cs new file mode 100644 index 0000000..2205b50 --- /dev/null +++ b/Entidades/Admin/NotificarAdmin.cs @@ -0,0 +1,6 @@ +namespace Entidades.Admin; +public class NotificarAdmin { + public string Mensaje { get; set; }=""; + public long Idcontrato{get;set;} + public long Idcanon {get; set;} +} \ No newline at end of file diff --git a/Front/src/App.svelte b/Front/src/App.svelte index 430f80e..31600b2 100644 --- a/Front/src/App.svelte +++ b/Front/src/App.svelte @@ -25,6 +25,8 @@ import CompraYVentas from "./paginas/CompraYVenta.svelte"; import Ventas from "./paginas/Ventas.svelte"; import VerLogs from "./paginas/VerLogs.svelte"; + import ControlPagos from "./paginas/ControlPagos.svelte"; + import ContratoAdmin from "./paginas/ContratoAdmin.svelte"; @@ -108,6 +110,11 @@ + + + + + @@ -141,6 +148,10 @@ - + + + + + diff --git a/Front/src/paginas/ContratoAdmin.svelte b/Front/src/paginas/ContratoAdmin.svelte new file mode 100644 index 0000000..57f3e94 --- /dev/null +++ b/Front/src/paginas/ContratoAdmin.svelte @@ -0,0 +1,316 @@ + + + + +{#if modaldata} + !!(modaldata = "")}/> +{/if} + +{#if shownotif} + shownotif = false} onConfirm={EscribirNotificacion}/> +{/if} + +
+
+
+
Propiedad
+
+

Tipo: {prop.tipoPropiedad}

+

Ubicación: {prop.ubicacion}

+

Propietario: {prop.propietario}

+

Inquilino: {prop.inquilino}

+

Habitaciones: {prop.habitaciones}

+

Piso: {prop.piso}

+

Letra: {prop.letra}

+

Fecha Inicio: {String(prop.fechainicio).split("T")[0]}

+

Estado: {prop.estado}

+ +
+ +
+
+
+
+
+

+ +

+
+
+

Este Cliente no tiene GruposEste Cliente no tiene Grupos
Seleccione un cliente para ver sus gruposSeleccione un cliente para ver sus grupos
+ + + + + + + + + + + + {#each garantes as g} + + + + + + + + + {/each} + +
DniNombreApellidoDomicilioDom. LaboralCelular
{g.dni}{g.nombre}{g.apellido}{g.domicilio}{g.domiciliolaboral}{g.celular}
+
+
+
+ +
+

+ +

+
+
+
+ {#each canons as canon} +
+
+
+ {canon.mesNum}/{prop.mesesDuracion} +
+
+

Mes: {String(canon.mes).split("T")[0]}

+

Monto: {canon.monto}

+

Divisa: {canon.divisa}

+

Pago: {canon.pago ? "Sí" : "No"}

+
+ +
+
+ {/each} +
+
+
+
+
+
+ \ No newline at end of file diff --git a/Front/src/paginas/ControlPagos.svelte b/Front/src/paginas/ControlPagos.svelte new file mode 100644 index 0000000..9baa86e --- /dev/null +++ b/Front/src/paginas/ControlPagos.svelte @@ -0,0 +1,93 @@ + + + + +{#if modaldata } + !!(modaldata="")}/> +{/if} + +
+ +
+ Lista de contratos que tienen canones atrasados +
+
+
+ {#if alquileres == null} +
+
+ Loading... +
+
+ {:else} + {#if alquileres.length == 0} +

+ No hay Alquileres que deban meses +

+ {/if} + {#each alquileres as alquiler} +
+
+
+
{alquiler.tipoPropiedad}
+
+
+
{alquiler.ubicacion}
+

+ Fecha de inicio: {new Date(alquiler.fechainicio).toLocaleDateString()}
+ Inquilino: {alquiler.inquilino}
+ Propietario: {alquiler.propietario}
+ Id Propiedad: {alquiler.id} +

+
+ +
+
+ +
+
+ {/each} + {/if} +
+
\ No newline at end of file diff --git a/Modelo/RepositorioCanons.cs b/Modelo/RepositorioCanons.cs index ecb8ce2..584e811 100644 --- a/Modelo/RepositorioCanons.cs +++ b/Modelo/RepositorioCanons.cs @@ -27,7 +27,13 @@ public class RepositorioCanons: RepositorioBase { return cc; } - public bool SetRecibo(Canon c, Recibo re, long dni) { + public Canon? ObtenerCanonPorId(long id){ + var con = Context; + var cnn = con.Canons.FirstOrDefault(x=>x.Id == id); + return cnn; + } + + public bool SetRecibo(Canon c, Recibo re, long dni, string mensaje= "Set Recibo") { var con = Context; var cc = con.Canons .Include(x=>x.Idcontratos) @@ -51,7 +57,7 @@ public class RepositorioCanons: RepositorioBase { ccc.IdpropiedadNavigation.Idestado = 3; } - GenerarLog(con, dni, $"Set Recibo"); + GenerarLog(con, dni, mensaje); return Guardar(con); } diff --git a/Modelo/RepositorioContratos.cs b/Modelo/RepositorioContratos.cs index 8016950..5119af3 100644 --- a/Modelo/RepositorioContratos.cs +++ b/Modelo/RepositorioContratos.cs @@ -242,4 +242,17 @@ public class RepositorioContratos: RepositorioBase { return Guardar(con); } + + public IQueryable ObtenerContratosInpagos() { + var con = Context; + DateTime d = DateTime.Now; + var l = con.Contratos + .Include(x=>x.DniinquilinoNavigation) + .Include(x=>x.DnipropietarioNavigation) + .Include(x=>x.IdpropiedadNavigation) + .ThenInclude(x=>x.IdtipropiedadNavigation) + .Include(x=>x.Idcanons) + .Where(x=>x.Idcanons.Any(x=>x.Pagado ==0 && d > x.Fecha)); + return l; + } } diff --git a/Modelo/RepositorioNotificaciones.cs b/Modelo/RepositorioNotificaciones.cs index d925c9a..f10ba47 100644 --- a/Modelo/RepositorioNotificaciones.cs +++ b/Modelo/RepositorioNotificaciones.cs @@ -20,10 +20,13 @@ public class RepositorioNotificaciones : RepositorioBase Date: Fri, 31 Jan 2025 20:15:08 -0300 Subject: [PATCH 13/16] =?UTF-8?q?a=C3=B1adido=20m=C3=A1s=20tama=C3=B1o=20a?= =?UTF-8?q?l=20estadopropiedad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Entidades/Alquilafacilcontext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entidades/Alquilafacilcontext.cs b/Entidades/Alquilafacilcontext.cs index 8ab6073..1412713 100644 --- a/Entidades/Alquilafacilcontext.cs +++ b/Entidades/Alquilafacilcontext.cs @@ -328,7 +328,7 @@ public partial class AlquilaFacilContext : DbContext .HasColumnType("int(11)") .HasColumnName("id"); entity.Property(e => e.Descripcion) - .HasMaxLength(11) + .HasMaxLength(30) .HasColumnName("descripcion"); }); -- 2.52.0 From af231344b6fde0921d87750a5a7729385f98e5ec Mon Sep 17 00:00:00 2001 From: fede Date: Sat, 1 Feb 2025 02:29:34 -0300 Subject: [PATCH 14/16] este es el trabajo de hoy --- Aspnet/Controllers/PropiedadesController.cs | 33 ++++++++++ Aspnet/Controllers/VentaController.cs | 63 +++++++++++++++++++ Entidades/Dto/PropiedadesVentaDto.cs | 12 ++++ Entidades/Dto/SetVentaDto.cs | 6 ++ Front/src/App.svelte | 7 ++- .../ModalPublicarPropiedadParaVenta.svelte | 44 +++++++++++++ Front/src/Componentes/RowPropiedad.svelte | 22 +++++-- Front/src/paginas/BuscarVentas.svelte | 14 +++++ Front/src/types.d.ts | 6 ++ Modelo/RepositorioPropiedades.cs | 9 +++ Modelo/RepositorioVentas.cs | 29 +++++++++ 11 files changed, 240 insertions(+), 5 deletions(-) create mode 100644 Entidades/Dto/PropiedadesVentaDto.cs create mode 100644 Entidades/Dto/SetVentaDto.cs create mode 100644 Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte create mode 100644 Front/src/paginas/BuscarVentas.svelte diff --git a/Aspnet/Controllers/PropiedadesController.cs b/Aspnet/Controllers/PropiedadesController.cs index 8b3ed9b..d346b59 100644 --- a/Aspnet/Controllers/PropiedadesController.cs +++ b/Aspnet/Controllers/PropiedadesController.cs @@ -25,6 +25,39 @@ public class PropiedadesController: ControllerBase { return Ok(ret); } + [HttpGet("/api/propiedades/Venta")] + public IActionResult ObtenerPropiedadesParaVenta([FromHeader(Name = "Auth")] string Auth, int pag = 0) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + + if (pag<=0) return BadRequest(new { message = "no existe una pagina 0"}); + + pag-=1; + + var props = RepositorioPropiedades.Singleton.ObtenerPropiedadesEnVenta(pag); + if (props == null) return BadRequest(new { message = "no tengo claro que fallo creo que no existen propiedades en venta"}); + + List l = new(); + + foreach (var i in props) { + var p = new PropiedadesVentaDto{ + Id = i.Id, + Ubicacion = i.Ubicacion, + Canthabitaciones = i.Canthabitaciones, + Divisa = i.IddivisaNavigation.Signo, + Letra = i.Letra??"", + Monto = i.Monto, + Piso = i.Piso??0, + Servicios =string.Join(", ", i.IdServicios.Select(s => s.Descripcion)), + Tipo = i.IdtipropiedadNavigation.Descripcion, + }; + l.Add(p); + } + return Ok(l); + } + [HttpGet("api/propiedad")] public IActionResult ObtenerPropiedadPorId(int Id, [FromHeader(Name = "Auth")] string Auth) { if (String.IsNullOrEmpty(Auth)) return Unauthorized(); diff --git a/Aspnet/Controllers/VentaController.cs b/Aspnet/Controllers/VentaController.cs index ce2e1f7..8740e53 100644 --- a/Aspnet/Controllers/VentaController.cs +++ b/Aspnet/Controllers/VentaController.cs @@ -14,6 +14,69 @@ namespace AlquilaFacil.Controllers; [ApiController] public class VentaController:ControllerBase { + [HttpGet("/api/propiedad/EstaALaVenta")] + public IActionResult EstaALaVenta([FromHeader(Name="Auth")]string Auth, int idprop=0) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + if (idprop<=0) return BadRequest(new { message = "No hay propiedades con id 0 o menor"}); + + Propiedade? prop = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(idprop); + if (prop == null) return BadRequest(new { message = "No hay propiedades por ese id"}); + return Ok(new { EstaAVenta = prop.Idestado ==4?true:false}); + } + + [HttpPut("/api/propiedad/setPropiedadAVenta")] + public IActionResult setPropiedadAVenta([FromHeader(Name="Auth")]string Auth, SetVentaDto dto) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + + if (dto.iddivisa != 0 && dto.iddivisa!=1) return BadRequest(new { message = "no hay una divisa por esa id"}); + if (dto.idpropiedad<=0) return BadRequest(new { message = "No hay propiedades con id 0 o menor"}); + if (dto.monto<1) return BadRequest(new { message = "No se pueden hacer ventas por montos menores a 1"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + Propiedade? prop = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(dto.idpropiedad); + if (prop == null) return BadRequest(new { message = "No hay propiedades por ese id"}); + + if (cli.Dni != prop.Dnipropietario) return Unauthorized(); + + var ret = RepositorioVentas.Singleton.SetVenta(prop.Id, dto.monto, dto.iddivisa, cli.Dni); + return ret? + Ok(new { message = "Se puso la propiedad de venta"}) : BadRequest(new { message = "No se pudo poner a la Venta"}); + } + + [HttpPut("/api/propiedad/unsetPropiedadAVenta")] + public IActionResult unsetPropiedadAVenta([FromHeader(Name="Auth")]string Auth, SetVentaDto dto) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + + if (dto.iddivisa != 0 && dto.iddivisa!=1) return BadRequest(new { message = "no hay una divisa por esa id"}); + if (dto.idpropiedad<=0) return BadRequest(new { message = "No hay propiedades con id 0 o menor"}); + if (dto.monto<1) return BadRequest(new { message = "No se pueden hacer ventas por montos menores a 1"}); + + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + Propiedade? prop = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(dto.idpropiedad); + if (prop == null) return BadRequest(new { message = "No hay propiedades por ese id"}); + + if (cli.Dni != prop.Dnipropietario) return Unauthorized(); + + bool ret = RepositorioVentas.Singleton.UnSetVenta(prop.Id, dto.monto, dto.iddivisa, cli.Dni); + + return ret? + Ok(new { message = "Se Bajo la propiedad de venta"}) : BadRequest(new { message = "No se pudo Bajar de venta"}); + } + [HttpPost("/api/ventas/ejercerOpcionVenta")] public IActionResult EjercerOpcionVenta([FromHeader(Name="Auth")]string Auth, [FromQuery]long idcontrato=0) { var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino"); diff --git a/Entidades/Dto/PropiedadesVentaDto.cs b/Entidades/Dto/PropiedadesVentaDto.cs new file mode 100644 index 0000000..84cfc2b --- /dev/null +++ b/Entidades/Dto/PropiedadesVentaDto.cs @@ -0,0 +1,12 @@ +namespace Entidades.Dto; +public class PropiedadesVentaDto { + public int Id { get; set; } + public string Ubicacion { get; set; } = ""; + public int Canthabitaciones { get; set; } + public int Piso { get; set; } + public string Letra { get; set; } = ""; + public string Tipo { get; set; } = ""; + public string? Servicios {get;set;} = ""; + public decimal Monto { get; set; } + public string Divisa { get; set; }=""; +} \ No newline at end of file diff --git a/Entidades/Dto/SetVentaDto.cs b/Entidades/Dto/SetVentaDto.cs new file mode 100644 index 0000000..7debd54 --- /dev/null +++ b/Entidades/Dto/SetVentaDto.cs @@ -0,0 +1,6 @@ +namespace Entidades.Dto; +public class SetVentaDto { + public int idpropiedad {get; set;} + public decimal monto {get; set;} + public int iddivisa {get; set;} +} \ No newline at end of file diff --git a/Front/src/App.svelte b/Front/src/App.svelte index 31600b2..ccb6c09 100644 --- a/Front/src/App.svelte +++ b/Front/src/App.svelte @@ -27,6 +27,7 @@ import VerLogs from "./paginas/VerLogs.svelte"; import ControlPagos from "./paginas/ControlPagos.svelte"; import ContratoAdmin from "./paginas/ContratoAdmin.svelte"; + import BuscarVentas from "./paginas/BuscarVentas.svelte"; @@ -115,6 +116,10 @@
+ + + + @@ -149,7 +154,7 @@ - + diff --git a/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte b/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte new file mode 100644 index 0000000..64a749b --- /dev/null +++ b/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte @@ -0,0 +1,44 @@ + + + diff --git a/Front/src/Componentes/RowPropiedad.svelte b/Front/src/Componentes/RowPropiedad.svelte index d94093d..0897188 100644 --- a/Front/src/Componentes/RowPropiedad.svelte +++ b/Front/src/Componentes/RowPropiedad.svelte @@ -6,12 +6,14 @@ let { id, ubicacion, tipo, letra, piso,canthabitaciones, servicios, btnbaja = "Baja", monto, iddivisa = 0 } = $props(); import { urlG } from "../stores/urlStore"; + import ModalPublicarPropiedadParaVenta from "./ModalPublicarPropiedadParaVenta.svelte"; let modal: boolean = $state(false); let modalpayload: string = $state(""); let modificar: boolean = $state(false); - + let showPublicarVenta: boolean = $state(false); + function setmod(){ modificar = !modificar; } @@ -35,6 +37,13 @@ console.error(e); } } + + function setventa() { + showPublicarVenta = true; + } + async function sendMod() { + + } @@ -53,9 +62,10 @@ {/if} {monto} - - - + + + + {#if modal} @@ -68,3 +78,7 @@ {/if} + +{#if showPublicarVenta} + !!(showPublicarVenta = false)} onConfirm={sendMod}/> +{/if} \ No newline at end of file diff --git a/Front/src/paginas/BuscarVentas.svelte b/Front/src/paginas/BuscarVentas.svelte new file mode 100644 index 0000000..14cb3b0 --- /dev/null +++ b/Front/src/paginas/BuscarVentas.svelte @@ -0,0 +1,14 @@ + + + + +
+ + +
\ No newline at end of file diff --git a/Front/src/types.d.ts b/Front/src/types.d.ts index 89acc40..844d360 100644 --- a/Front/src/types.d.ts +++ b/Front/src/types.d.ts @@ -187,4 +187,10 @@ export type UpdateCliente = { apellido:string, domicilio:string, celular:string, +} + +export type setVenta = { + idpropiedad:number, + monto:number, + iddivisa:number, } \ No newline at end of file diff --git a/Modelo/RepositorioPropiedades.cs b/Modelo/RepositorioPropiedades.cs index 3439afe..f0afd83 100644 --- a/Modelo/RepositorioPropiedades.cs +++ b/Modelo/RepositorioPropiedades.cs @@ -611,4 +611,13 @@ public class RepositorioPropiedades: RepositorioBase { return (int)Math.Ceiling((double)totalRegistros / registrosPorPagina); } + + public IQueryable? ObtenerPropiedadesEnVenta(int pag){ + var con = Context; + + var props = con.Propiedades.Include(x=>x.IdServicios).Include(x=>x.IddivisaNavigation) + .Include(c=>c.IdtipropiedadNavigation) + .Where(x=>x.Idestado ==4).Skip(pag*10).Take(10); + return props; + } } \ No newline at end of file diff --git a/Modelo/RepositorioVentas.cs b/Modelo/RepositorioVentas.cs index 647cce6..cc203fb 100644 --- a/Modelo/RepositorioVentas.cs +++ b/Modelo/RepositorioVentas.cs @@ -72,4 +72,33 @@ public class RepositorioVentas: RepositorioBase { GenerarLog(con, dni, $"Se seteo el recibo con nombre: {nuevoNombreArchivo}"); return Guardar(con); } + + public bool SetVenta(int idpropiedad, decimal monto, int iddivisa, long dni) { + var con = Context; + Propiedade? cont = con.Propiedades.Include(x=>x.Contratos).FirstOrDefault(x=>x.Id == idpropiedad); + if (cont==null) return false; + if (cont.Idestado == 2 || cont.Idestado == 4) return false; + if (cont.Contratos.Any(x=>x.Habilitado == 1 && x.Cancelado == 0)) return false; + + cont.Monto = monto; + cont.Iddivisa = iddivisa; + cont.Idestado = 4; + GenerarLog(con, dni, "Se puso la propiedad de venta"); + return Guardar(con); + } + + public bool UnSetVenta(int id, decimal monto, int iddivisa, long dni) { + var con = Context; + Propiedade? cont = con.Propiedades.Include(x=>x.Venta).Include(x=>x.Contratos).FirstOrDefault(x=>x.Id == id); + if (cont==null) return false; + if (cont.Idestado != 4) return false; + if (cont.Contratos.Any(x=>x.Habilitado == 1 && x.Cancelado == 0)) return false; + if (cont.Venta.Any(x=>x.Idestado != 3)) return false; + + cont.Monto = monto; + cont.Iddivisa = iddivisa; + cont.Idestado = 4; + GenerarLog(con, dni, "Se Bajo la propiedad de venta"); + return Guardar(con); + } } \ No newline at end of file -- 2.52.0 From 2a8ba5a9f423831ef7f228ffd336f0a1494abba8 Mon Sep 17 00:00:00 2001 From: fede Date: Sat, 1 Feb 2025 18:10:24 -0300 Subject: [PATCH 15/16] feat: hecha la parte de gestion de propiedades en venta --- Aspnet/Controllers/PropiedadesController.cs | 30 ++++ Front/src/App.svelte | 7 + .../ModalPublicarPropiedadParaVenta.svelte | 23 ++- Front/src/Componentes/NavBarLogin.svelte | 2 +- Front/src/Componentes/RowPropiedad.svelte | 24 ++- .../src/paginas/MisPropiedadesEnVenta.svelte | 159 ++++++++++++++++++ Front/src/types.d.ts | 13 ++ Modelo/RepositorioPropiedades.cs | 7 + Modelo/RepositorioVentas.cs | 2 +- 9 files changed, 257 insertions(+), 10 deletions(-) create mode 100644 Front/src/paginas/MisPropiedadesEnVenta.svelte diff --git a/Aspnet/Controllers/PropiedadesController.cs b/Aspnet/Controllers/PropiedadesController.cs index d346b59..25bf243 100644 --- a/Aspnet/Controllers/PropiedadesController.cs +++ b/Aspnet/Controllers/PropiedadesController.cs @@ -58,6 +58,36 @@ public class PropiedadesController: ControllerBase { return Ok(l); } + [HttpGet("api/propiedades/Venta/Propietario")] + public IActionResult ObtenerPropiedadesVentaDePropietario( [FromHeader(Name = "Auth")] string Auth){ + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + var props = RepositorioPropiedades.Singleton.ObtenerPropiedadesAVentaPorDni(cli.Dni); + List ll = new(); + + foreach (var i in props) { + var a = new PropiedadesDto { + id = i.Id, + Ubicacion = i.Ubicacion, + canthabitaciones = i.Canthabitaciones, + Iddivisa = i.Iddivisa, + letra = i.Letra??"", + Monto = (int)i.Monto, //mmmm + piso = i.Piso??0, + Servicios = string.Join(", ", i.IdServicios.Select(x => x.Descripcion)), + Tipo = i.IdtipropiedadNavigation.Descripcion, + }; + ll.Add(a); + } + return Ok(ll); + } + [HttpGet("api/propiedad")] public IActionResult ObtenerPropiedadPorId(int Id, [FromHeader(Name = "Auth")] string Auth) { if (String.IsNullOrEmpty(Auth)) return Unauthorized(); diff --git a/Front/src/App.svelte b/Front/src/App.svelte index ccb6c09..b5870a8 100644 --- a/Front/src/App.svelte +++ b/Front/src/App.svelte @@ -28,6 +28,7 @@ import ControlPagos from "./paginas/ControlPagos.svelte"; import ContratoAdmin from "./paginas/ContratoAdmin.svelte"; import BuscarVentas from "./paginas/BuscarVentas.svelte"; + import MisPropiedadesEnVenta from "./paginas/MisPropiedadesEnVenta.svelte"; @@ -116,10 +117,16 @@ + + + + + + diff --git a/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte b/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte index 64a749b..ea0d4ff 100644 --- a/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte +++ b/Front/src/Componentes/ModalPublicarPropiedadParaVenta.svelte @@ -1,12 +1,17 @@ @@ -14,7 +19,7 @@ diff --git a/Front/src/Componentes/NavBarLogin.svelte b/Front/src/Componentes/NavBarLogin.svelte index 59c245f..343e94c 100644 --- a/Front/src/Componentes/NavBarLogin.svelte +++ b/Front/src/Componentes/NavBarLogin.svelte @@ -1,7 +1,7 @@ diff --git a/Front/src/paginas/MisPropiedadesEnVenta.svelte b/Front/src/paginas/MisPropiedadesEnVenta.svelte new file mode 100644 index 0000000..e295a42 --- /dev/null +++ b/Front/src/paginas/MisPropiedadesEnVenta.svelte @@ -0,0 +1,159 @@ + + + + +{#if modaldata} + !!(modaldata = "")}/> +{/if} + +{#if showBajaVenta} + !!(showBajaVenta=false)} onConfirm={submitBajaVenta}/> +{/if} + +
+ + + + + + + + + + + + + + + + + + + {#if propiedades == null} + + + + {:else if propiedades.length <=0} + + + + {:else} + {#each propiedades as p} + + + + + + + + + + + + + {#if modificar} + + + + {/if} + {/each} + {/if} + +
#ubicacionHabitacionesLetraPisoTipoServiciosDivisaMonto
+
+ Cargando... +
No hay propiedades en venta para este usuario
{p.id}{p.ubicacion}{p.canthabitaciones}{p.letra}{p.piso}{p.tipo}{p.servicios} + {#if p.iddivisa == 0} + AR$ + {:else} + US$ + {/if} + {p.monto} + + +
+ +
+
diff --git a/Front/src/types.d.ts b/Front/src/types.d.ts index 844d360..bba5a58 100644 --- a/Front/src/types.d.ts +++ b/Front/src/types.d.ts @@ -193,4 +193,17 @@ export type setVenta = { idpropiedad:number, monto:number, iddivisa:number, +} + +export type PatchPropiedad = { + id:number, + ubicacion:string, + canthabitaciones:number, + piso:number, + letra:string, + email:string, + tipo:number, + servicios: string[], + monto:number, + iddivisa:number } \ No newline at end of file diff --git a/Modelo/RepositorioPropiedades.cs b/Modelo/RepositorioPropiedades.cs index f0afd83..e5fe33c 100644 --- a/Modelo/RepositorioPropiedades.cs +++ b/Modelo/RepositorioPropiedades.cs @@ -620,4 +620,11 @@ public class RepositorioPropiedades: RepositorioBase { .Where(x=>x.Idestado ==4).Skip(pag*10).Take(10); return props; } + + public IQueryable ObtenerPropiedadesAVentaPorDni(long dni) { + var con = Context; + var l = con.Propiedades.Include(x=>x.IdServicios).Include(x=>x.IdtipropiedadNavigation) + .Where(x=>x.Dnipropietario == dni && x.Idestado ==4); + return l; + } } \ No newline at end of file diff --git a/Modelo/RepositorioVentas.cs b/Modelo/RepositorioVentas.cs index cc203fb..f81ec4d 100644 --- a/Modelo/RepositorioVentas.cs +++ b/Modelo/RepositorioVentas.cs @@ -97,7 +97,7 @@ public class RepositorioVentas: RepositorioBase { cont.Monto = monto; cont.Iddivisa = iddivisa; - cont.Idestado = 4; + cont.Idestado = 3; GenerarLog(con, dni, "Se Bajo la propiedad de venta"); return Guardar(con); } -- 2.52.0 From e7747455eca42a7a3a1041be100f32bec5098c37 Mon Sep 17 00:00:00 2001 From: fede Date: Sun, 2 Feb 2025 20:14:39 -0300 Subject: [PATCH 16/16] funcionalidad terminada --- .../Controllers/NotificacionesController.cs | 34 +++++ Aspnet/Controllers/PropiedadesController.cs | 5 +- Aspnet/Controllers/VentaController.cs | 76 +++++++++ .../src/Componentes/PaginacionStepper.svelte | 2 +- Front/src/paginas/BuscarVentas.svelte | 144 +++++++++++++++++- .../src/paginas/MisPropiedadesEnVenta.svelte | 4 - Front/src/paginas/Notificaciones.svelte | 64 +++++++- Front/src/types.d.ts | 12 ++ Modelo/RepositorioNotificaciones.cs | 6 + Modelo/RepositorioPropiedades.cs | 9 +- Modelo/RepositorioVentas.cs | 11 +- 11 files changed, 352 insertions(+), 15 deletions(-) diff --git a/Aspnet/Controllers/NotificacionesController.cs b/Aspnet/Controllers/NotificacionesController.cs index 3fadadd..76dc46b 100644 --- a/Aspnet/Controllers/NotificacionesController.cs +++ b/Aspnet/Controllers/NotificacionesController.cs @@ -121,4 +121,38 @@ public class NotificacionesController: ControllerBase { return ret? Ok(new { message = "se envio el aviso" }):BadRequest(new { message = "Fallo al intentar enviar el aviso" }); } + + [HttpPost("api/notificar/ConsultaCompra")] + public IActionResult EnviarConsultaCompra([FromHeader(Name ="Auth")]string Auth, AltaNotificacionDto dto) { + if (String.IsNullOrWhiteSpace(Auth)) return Unauthorized(); + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false){ + validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino"); + if (validacion1 == false) { + return Unauthorized(); + } + } + + if (dto.Accion == "") return BadRequest(new{message = "El campo Accion esta vacio"}); + if (dto.Mensaje == "") return BadRequest(new {message = "El campo Mensaje esta vacio"}); + + Cliente?cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + + Propiedade? prop = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(dto.Propiedad); + if (prop == null) return BadRequest(new { message = "No hay una propiedad con id 0 o menor"}); + + var n = new NotificacioneBuilder() + .SetAccion("Consulta Compra") + .SetMensaje(dto.Mensaje) + .SetLeido(false) + .SetDnicliente(prop.Dnipropietario??0) + .SetDniremitente(cli.Dni) + .SetIdpropiedad(prop.Id) + .SetFecha(DateTime.Now) + .Build(); + var ret2= RepositorioNotificaciones.Singleton.AltaNotificacion(n, cli.Dni); + return ret2? + Ok(new { message = "se envio el aviso" }):BadRequest(new { message = "Fallo al intentar enviar el aviso" }); + + } } \ No newline at end of file diff --git a/Aspnet/Controllers/PropiedadesController.cs b/Aspnet/Controllers/PropiedadesController.cs index 25bf243..5b03bbc 100644 --- a/Aspnet/Controllers/PropiedadesController.cs +++ b/Aspnet/Controllers/PropiedadesController.cs @@ -55,7 +55,10 @@ public class PropiedadesController: ControllerBase { }; l.Add(p); } - return Ok(l); + + int cantpag = RepositorioPropiedades.Singleton.ObtenerPaginasDePropiedadesEnVenta(); + + return Ok(new { propiedades = l, cantpaginas = cantpag}); } [HttpGet("api/propiedades/Venta/Propietario")] diff --git a/Aspnet/Controllers/VentaController.cs b/Aspnet/Controllers/VentaController.cs index 8740e53..6518713 100644 --- a/Aspnet/Controllers/VentaController.cs +++ b/Aspnet/Controllers/VentaController.cs @@ -14,6 +14,82 @@ namespace AlquilaFacil.Controllers; [ApiController] public class VentaController:ControllerBase { + [HttpPost("api/venta/AceptarConsultaVenta")] + public IActionResult AceptarConsultaVenta([FromHeader(Name="Auth")]string Auth, NotificacionMarcarLeidoDto dto) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + if (dto.Email == "") return BadRequest(new { message = "Falta dato Email"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) Unauthorized(); + if (cli.Email != dto.Email) return BadRequest(new {message = "El token de autorizacion no corresponde a tu usuario"}); + RepositorioNotificaciones.Singleton.MarcarComoLeido(cli.Dni, dto.Fecha); + + Notificacione? n = RepositorioNotificaciones.Singleton.ObtenerNotificacionPorKeys(cli.Dni, dto.Fecha); + if (n == null) return BadRequest(new { message = "No se encuentra la notificacion"}); + + Propiedade? prop = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(n.Idpropiedad); + if (prop == null) return BadRequest(new { message = "No se encuentra una propiedad por ese id"}); + Venta? v = new Venta{ + Fechainicio = DateTime.Now, + IdVendedor = prop.Dnipropietario, + IdComprador = n.Dniremitente, + Monto = prop.Monto, + Idpropiedad = prop.Id, + Iddivisa = prop.Iddivisa, + Idestado = 2, + + }; + + bool ret = RepositorioVentas.Singleton.IniciarVenta(v, cli.Dni); + if (ret){ + var noti = new NotificacioneBuilder() + .SetAccion("Notificacion") + .SetMensaje("Debe Realizar el pago para que se registre el traspaso de la propiedad") + .SetLeido(false) + .SetDnicliente(n.Dniremitente) + .SetDniremitente(n.Dnicliente) + .SetIdpropiedad(n.Idpropiedad) + .SetFecha(DateTime.Now) + .Build(); + ret = RepositorioNotificaciones.Singleton.AltaNotificacion(noti); + } + return ret? + Ok(new { message = "Se inicio la venta"}):BadRequest(new { message ="fallo al iniciar la venta"}); + } + + [HttpPost("api/venta/CancelarConsultaVenta")] + public IActionResult CancelarConsultaVenta([FromHeader(Name="Auth")]string Auth, NotificacionMarcarLeidoDto dto) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false) { + return Unauthorized(); + } + + if (dto.Email == "") return BadRequest(new { message = "Falta dato Email"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) Unauthorized(); + if (cli.Email != dto.Email) return BadRequest(new {message = "El token de autorizacion no corresponde a tu usuario"}); + + RepositorioNotificaciones.Singleton.MarcarComoLeido(cli.Dni, dto.Fecha); + Notificacione? n = RepositorioNotificaciones.Singleton.ObtenerNotificacionPorKeys(cli.Dni, dto.Fecha); + var noti = new NotificacioneBuilder() + .SetAccion("Notificacion") + .SetMensaje("El propietario no quiere vender") + .SetLeido(false) + .SetDnicliente(n.Dniremitente) + .SetDniremitente(n.Dnicliente) + .SetIdpropiedad(n.Idpropiedad) + .SetFecha(DateTime.Now) + .Build(); + + var ret = RepositorioNotificaciones.Singleton.AltaNotificacion(noti); + return ret ? + Ok(new{message = "Se Envio una notificacion"}):BadRequest(new{message = "Fallo al Descartar Consulta"}); + } + [HttpGet("/api/propiedad/EstaALaVenta")] public IActionResult EstaALaVenta([FromHeader(Name="Auth")]string Auth, int idprop=0) { var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); diff --git a/Front/src/Componentes/PaginacionStepper.svelte b/Front/src/Componentes/PaginacionStepper.svelte index b57f0f8..e62e219 100644 --- a/Front/src/Componentes/PaginacionStepper.svelte +++ b/Front/src/Componentes/PaginacionStepper.svelte @@ -12,7 +12,7 @@ let array = $derived.by(()=> Array.from({ length: cantpag }, (_, i) => i + 1)); -{#if cantpag>1} +{#if cantpag>0}