From 99dc7b28d5639512877d2102986df423fcfcaed2 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 24 Jan 2025 04:19:40 -0300 Subject: [PATCH 01/23] =?UTF-8?q?a=C3=B1adido=20skeleton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Aspnet/Controllers/VentaController.cs | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Aspnet/Controllers/VentaController.cs diff --git a/Aspnet/Controllers/VentaController.cs b/Aspnet/Controllers/VentaController.cs new file mode 100644 index 0000000..443d1d6 --- /dev/null +++ b/Aspnet/Controllers/VentaController.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Mvc; + +namespace AlquilaFacil.Controllers; +[ApiController] +public class VentaController:ControllerBase { + [HttpPost("/api/ventas/ejercerOpcionVenta")] + public IActionResult EjercerOpcionVenta(long idcontrato) { + + } + + [HttpPost("/api/ventas/subirReciboPago")] + public IActionResult SubirRecibo([FromForm]IFormFile file, long idventa ) { + + } + [HttpPost("/api/ventas/propietarioverifica")] + public IActionResult PropietarioVerifica(long idventa) { + + } + + [HttpGet("/api/venta")] + public IActionResult ObtenerVenta(long idventa) { + + } + + [HttpGet("/api/ventas")] + public IActionResult ObtenerVenta(long idventa) { + + } + + [HttpGet("/api/contrato/tieneopcionventa")] + public IActionResult TieneOpcionVenta(long idcontrato) { + + } +} \ No newline at end of file -- 2.52.0 From f8692ccdf08c2fdafa68639db2313098e886a025 Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 24 Jan 2025 16:24:43 -0300 Subject: [PATCH 02/23] migracion: ahora la fecha de inicio no es opcional --- Entidades/Venta.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Entidades/Venta.cs b/Entidades/Venta.cs index 200b45c..d1118be 100644 --- a/Entidades/Venta.cs +++ b/Entidades/Venta.cs @@ -17,7 +17,7 @@ public partial class Venta public int? Idpropiedad { get; set; } - public DateTime Fechainicio { get; set; } + public DateTime? Fechainicio { get; set; } public DateTime? Fechafinal { get; set; } -- 2.52.0 From 2b481e2ae2fb07e82938f03d93b5fd482c54a30c Mon Sep 17 00:00:00 2001 From: fede Date: Fri, 24 Jan 2025 21:31:37 -0300 Subject: [PATCH 03/23] falta interfaz venta --- .../DtoBuilder/OpcionVentaDtoBuilder.cs | 25 ++++ Aspnet/Builder/PrecontratoBuilder.cs | 5 + Aspnet/Controllers/ContratoController.cs | 15 ++- Aspnet/Controllers/VentaController.cs | 101 +++++++++++++- Entidades/Dto/OpcionVentaDto.cs | 8 ++ Entidades/Dto/PrecontratoDto.cs | 2 + Front/src/Componentes/ModalPrecontrato.svelte | 21 ++- Front/src/paginas/ContratoInquilino.svelte | 124 +++++++++++++++++- Front/src/paginas/ContratosPropietario.svelte | 93 ++++++++++++- Front/src/paginas/Notificaciones.svelte | 7 +- Front/src/types.d.ts | 8 ++ Modelo/RepositorioContratos.cs | 37 +++++- Modelo/RepositorioVentas.cs | 26 ++++ 13 files changed, 457 insertions(+), 15 deletions(-) create mode 100644 Aspnet/Builder/DtoBuilder/OpcionVentaDtoBuilder.cs create mode 100644 Entidades/Dto/OpcionVentaDto.cs create mode 100644 Modelo/RepositorioVentas.cs diff --git a/Aspnet/Builder/DtoBuilder/OpcionVentaDtoBuilder.cs b/Aspnet/Builder/DtoBuilder/OpcionVentaDtoBuilder.cs new file mode 100644 index 0000000..8df2256 --- /dev/null +++ b/Aspnet/Builder/DtoBuilder/OpcionVentaDtoBuilder.cs @@ -0,0 +1,25 @@ +using Entidades.Dto; + +namespace AlquilaFacil.Builder; +public class OpcionVentaDtoBuilder: Builder{ + public OpcionVentaDtoBuilder SetId(long id) { + data.Id = id; + return this; + } + public OpcionVentaDtoBuilder SetMonto(decimal monto) { + data.Monto = monto; + return this; + } + public OpcionVentaDtoBuilder SetDivisa(string divisa) { + data.Divisa = divisa; + return this; + } + public OpcionVentaDtoBuilder SetEnOrden(bool v) { + data.EnOrden = v; + return this; + } + public OpcionVentaDtoBuilder SetFueEjercido(int idestado) { + data.FueEjercido = idestado==1?false:true; + return this; + } +} \ No newline at end of file diff --git a/Aspnet/Builder/PrecontratoBuilder.cs b/Aspnet/Builder/PrecontratoBuilder.cs index 5e58b57..5d20313 100644 --- a/Aspnet/Builder/PrecontratoBuilder.cs +++ b/Aspnet/Builder/PrecontratoBuilder.cs @@ -47,4 +47,9 @@ public class PrecontratoBuilder : Builder { data.MesesDurationContrato = mesesDuracionContrato; return this; } + + public PrecontratoBuilder SetOpcionVenta(bool tieneOpcionVenta){ + data.Tieneopcionventa = tieneOpcionVenta == false?0Lu:1Lu; + return this; + } } \ No newline at end of file diff --git a/Aspnet/Controllers/ContratoController.cs b/Aspnet/Controllers/ContratoController.cs index fa6c146..6c6e822 100644 --- a/Aspnet/Controllers/ContratoController.cs +++ b/Aspnet/Controllers/ContratoController.cs @@ -336,6 +336,7 @@ public class ContratoController: ControllerBase { .SetPropiedad(p.Id) .SetFecha(DateTime.Parse(dto.fechaprimernotificacion)) .SetMesesDuracion(dto.MesesDuracionContrato) + .SetOpcionVenta(dto.TieneOpcionVenta) .Build(); @@ -349,7 +350,18 @@ public class ContratoController: ControllerBase { .SetMensaje($"El propietario {propi.Nombre} {propi.Apellido} te requiere que carges informacion de {dto.CantidadGarantes} Garantes") .Build(); - var ret = RepositorioContratos.Singleton.CargaPrecontrato(precontrato, notificacion); + bool ret; + if (dto.TieneOpcionVenta==false){ + ret = RepositorioContratos.Singleton.CargaPrecontrato(precontrato, notificacion); + } else { + Venta v = new Venta{ + Idestado = 1, + Iddivisa = dto.iddivisa, + Monto = dto.MontoOpcion, + }; + ret = RepositorioContratos.Singleton.CargaPrecontratoOpcionVenta(precontrato, notificacion, v); + } + if (ret) { ret = RepositorioNotificaciones.Singleton.MarcarComoLeido(cli.Dni, DateTime.Parse(dto.fechaprimernotificacion)); } @@ -816,6 +828,7 @@ public class ContratoController: ControllerBase { if (dto.MesesHastaAumento <= 0) ret += "No puede tener 0 o menos meses hasta el aumento\n"; if (dto.MesesDuracionContrato <= 0) ret += "No puede tener 0 o menos meses de duracion\n"; if (dto.MesesDuracionContrato < dto.MesesHastaAumento) ret += "el tiempo hasta aumento no puede ser mayor de \n"; + if (dto.TieneOpcionVenta == true && dto.MontoOpcion <=0) ret +="No puede tener un monto de venta negativo o 0"; return ret; } diff --git a/Aspnet/Controllers/VentaController.cs b/Aspnet/Controllers/VentaController.cs index 443d1d6..2fa2822 100644 --- a/Aspnet/Controllers/VentaController.cs +++ b/Aspnet/Controllers/VentaController.cs @@ -1,12 +1,42 @@ +using AlquilaFacil.Builder; +using Entidades; +using Entidades.Dto; using Microsoft.AspNetCore.Mvc; +using Modelo; namespace AlquilaFacil.Controllers; [ApiController] public class VentaController:ControllerBase { - [HttpPost("/api/ventas/ejercerOpcionVenta")] - public IActionResult EjercerOpcionVenta(long idcontrato) { + [HttpPost("/api/ventas/ejercerOpcionVenta")] + public IActionResult EjercerOpcionVenta([FromHeader(Name="Auth")]string Auth, [FromQuery]long idcontrato=0) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino"); + if (validacion1 == false) { + return Unauthorized(); + } + if (idcontrato <= 0) return BadRequest(new { message = "No pueden hacer cotratos con id 0 o menor"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + Contrato? cont = RepositorioVentas.Singleton.ObtenerVentaPorContrato(idcontrato); + if (cont == null || cont.IdventaNavigation == null) return BadRequest(new { message = "no hay un contrato por esa id"}); + if (cont.Tieneopcionventa == 0) return BadRequest(new { message = "No tiene opcion de venta"}); + if (puedeEjercer(cont) == false) return BadRequest(new { message = "No cumple con los requisitos para ejercer la opcion de compra"}); + + Venta venta = cont.IdventaNavigation; + venta.IdVendedor = cont.Dnipropietario; + venta.IdComprador = cont.Dniinquilino; + venta.Idpropiedad = cont.Idpropiedad; + venta.Fechainicio = DateTime.Now; + + bool ret = RepositorioVentas.Singleton.PatchVenta(venta); + + return ret? + Ok(new { message = "Se ejercio la opcion de venta"}): + BadRequest(new { message = "No se pude ejercer la opcion de venta"}); } + /* [HttpPost("/api/ventas/subirReciboPago")] public IActionResult SubirRecibo([FromForm]IFormFile file, long idventa ) { @@ -27,8 +57,71 @@ public class VentaController:ControllerBase { } - [HttpGet("/api/contrato/tieneopcionventa")] - public IActionResult TieneOpcionVenta(long idcontrato) { + */ + [HttpGet("/api/opcionventa")] + public IActionResult ObtenerDto([FromHeader(Name="Auth")]string Auth, long idcontrato=0) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false){ + validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino"); + if (validacion1 == false) { + return Unauthorized(); + } + } + if (idcontrato == 0) return BadRequest(new { message = "No existen contatos validos para la id 0"}); + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + Contrato? cont = RepositorioVentas.Singleton.ObtenerVentaPorContrato(idcontrato); + if (cont == null) return BadRequest(new { message = "No hay un contrato por esa id"}); + + var dto = new OpcionVentaDtoBuilder() + .SetId(cont.Idventa??0) + .SetMonto(cont.IdventaNavigation.Monto) + .SetDivisa(cont.IdventaNavigation.IddivisaNavigation.Signo) + .SetEnOrden(puedeEjercer(cont)) + .SetFueEjercido(cont.IdventaNavigation.Idestado??0) + .Build(); + + return Ok(dto); + } + + private bool puedeEjercer(Contrato c) { + bool ret = c.Idcanons.All(x => x.Pagado == 1); + + if (ret) { + var canonConFechaMasTardia = c.Idcanons.OrderByDescending(x => x.Fecha).FirstOrDefault(); + + if (canonConFechaMasTardia != null && canonConFechaMasTardia.Fecha.Year >= DateTime.Now.Year + && canonConFechaMasTardia.Fecha.Month >= DateTime.Now.Month) { + ret = true; + }else{ + ret = false; + } + } + + return ret; + } + + [HttpGet("/api/contrato/tieneopcionventa")] + public IActionResult TieneOpcionVenta([FromHeader(Name="Auth")]string Auth, long idcontrato=0) { + var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario"); + if (validacion1 == false){ + validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino"); + if (validacion1 == false) { + return Unauthorized(); + } + } + + if (idcontrato == 0) return BadRequest(new { message = "No existen contatos validos para la id 0"}); + + Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth); + if (cli == null) return Unauthorized(); + + Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(idcontrato); + if (cont == null) return BadRequest(new { message = "No hay un contrato por esa id"}); + if (cont.Dniinquilino !=cli.Dni && cont.Dnipropietario != cli.Dni) return Unauthorized(); + + return Ok( new { message = cont.Tieneopcionventa}); } } \ No newline at end of file diff --git a/Entidades/Dto/OpcionVentaDto.cs b/Entidades/Dto/OpcionVentaDto.cs new file mode 100644 index 0000000..3f11e1d --- /dev/null +++ b/Entidades/Dto/OpcionVentaDto.cs @@ -0,0 +1,8 @@ +namespace Entidades.Dto; +public class OpcionVentaDto{ + public long Id { get; set;} + public decimal Monto { get; set;} + public string Divisa { get; set;} =""; + public bool EnOrden { get; set;} + public bool FueEjercido { get; set; } +} \ No newline at end of file diff --git a/Entidades/Dto/PrecontratoDto.cs b/Entidades/Dto/PrecontratoDto.cs index 650e075..d1a76fa 100644 --- a/Entidades/Dto/PrecontratoDto.cs +++ b/Entidades/Dto/PrecontratoDto.cs @@ -8,4 +8,6 @@ public class PrecontratoDto { public bool TieneOpcionVenta { get; set; } public string fechaprimernotificacion { get; set; } = ""; public int MesesDuracionContrato { get; set; } + public Decimal MontoOpcion {get; set; } + public int iddivisa { get; set; } } \ No newline at end of file diff --git a/Front/src/Componentes/ModalPrecontrato.svelte b/Front/src/Componentes/ModalPrecontrato.svelte index 6f04d38..a44bdf9 100644 --- a/Front/src/Componentes/ModalPrecontrato.svelte +++ b/Front/src/Componentes/ModalPrecontrato.svelte @@ -1,16 +1,19 @@ @@ -25,11 +28,23 @@
+ \ 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 13/23] =?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 14/23] 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 15/23] 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 16/23] 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 18/23] 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 19/23] =?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 20/23] =?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 21/23] 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 22/23] 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 23/23] 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}