27 Commits

Author SHA1 Message Date
28b0a6b785 asd 2025-01-05 15:59:38 -03:00
2fa110bb89 fix missing <br> 2025-01-02 14:58:59 -03:00
45ebdb24be Merge pull request 'AdminUsuarios' (#33) from AdminUsuarios into LogicaContratos
Reviewed-on: #33
2025-01-02 14:55:52 -03:00
a89852804d añadido signo peso 2025-01-02 14:53:29 -03:00
8c5d0108a1 fix: bug no da de alta el usuario 2025-01-01 18:06:40 -03:00
872415cdde feat: terminado tema desabilitacion cliente 2024-12-31 20:24:08 -03:00
f1c9632855 avances añadido listado de clientes y sus grupos 2024-12-31 01:53:49 -03:00
bb860b1a16 wip: logica contrato 2024-12-30 17:41:45 -03:00
f9204cd835 cambio de entidad y cosas svlete
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-12-24 00:31:53 -03:00
6f34d628c4 fix: corrijiendo caracteres de nueva linea 2024-12-23 21:21:26 -03:00
76bcec58d2 fixeado spinner 2024-12-21 22:01:57 -03:00
3f08dcfc81 añadido tema oscuro, y programada la funcion de busqueda 2024-12-21 19:16:47 -03:00
990f866a71 WIP: primer avance con la Busqueda de Propiedades
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-12-07 19:05:07 -03:00
dbc255dd4b fix: añadir grupo a cliente falla 2024-12-06 17:34:08 -03:00
c8daa303e4 scale: Variable Global $urlG 2024-12-06 17:33:40 -03:00
edaf8c6600 añado archivo busqueda 2024-12-06 17:31:36 -03:00
9216efc59f Merge pull request 'FuncionesPropietario' (#24) from FuncionesPropietario into dev
Reviewed-on: #24
2024-12-06 00:07:24 -03:00
5a26fe8bd1 fix: Alta Dice Baja
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-12-06 00:05:43 -03:00
dee2031d87 feat: ahora se pueden ver las propiedades dadas de baja y añadido el tema de los servicios
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-12-06 00:01:31 -03:00
5289c07d84 arreglado tema de permisos
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-12-04 17:52:17 -03:00
646cf3e009 feat: modificar propiedad
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-12-04 17:44:25 -03:00
c116c924cd más avances
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-11-30 18:45:14 -03:00
28cf77ad18 chore: @debug
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-11-30 14:09:19 -03:00
00cce75fad feat: listar propiedades y baja propiedad
Signed-off-by: fede <federico.nicolas.polidoro@gmail.com>
2024-11-30 14:07:12 -03:00
29f7dc4efe Feat: commit antes de mostrar el codigo.
- Añadido alta propiedad
- Arreglado alta inq/prop
- Añadida pantalla de menu
2024-11-26 08:36:03 -03:00
e9b3baa9ca Fix: Ya no salen los links en azul 2024-11-24 23:12:59 -03:00
aa36454730 Merge pull request 'Fix: botones se salen de la pantalla' (#17) from fixbotones into dev
Reviewed-on: #17
2024-11-24 22:48:08 -03:00
66 changed files with 2233 additions and 266 deletions

View File

@@ -0,0 +1,149 @@
using Microsoft.AspNetCore.Mvc;
using Modelo;
using Entidades.Admin;
using Entidades.Dto;
using Entidades;
namespace AlquilaFacil.Controllers;
[ApiController]
public class AdminController: ControllerBase
{
[HttpGet("api/admin/clientes")]
public IActionResult GetClientes([FromHeader(Name ="Auth")]string Auth){
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9);
if (validacion1 == false) return Unauthorized();
IEnumerable<UsuarioAdmin>list = RepositorioUsuarios.Singleton.GetClientes();
return Ok(list);
}
[HttpGet("api/admin/clientes/grupo")]
public IActionResult GetGruposByCliente([FromHeader(Name ="Auth")]string Auth, [FromQuery]long Dni){
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 tener un dni con numero negativo o cero"});
IEnumerable<GrupoAdmin> list = RepositorioGrupos.Singleton.ObtenerGruposPorDni(Dni);
return Ok(list);
}
[HttpPatch("api/admin/cliente/addGrupo")]
public IActionResult AddGrupoACliente([FromHeader(Name = "Auth")]string Auth, [FromBody]EmailGrupo data){
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9);
if (validacion1 == false) return Unauthorized();
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);
return ret2 ? Ok(new {message = "Se Añadio al Grupo"}): BadRequest(new { message = "Fallo al añadirse al Grupo" });
}
[HttpPatch("api/admin/cliente/rmGrupo")]
public IActionResult RmGrupoACliente([FromHeader(Name = "Auth")]string Auth, [FromBody]EmailGrupo data){
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 9);
if (validacion1 == false) return Unauthorized();
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
if (data.email == "celu@fedesrv.ddns.net" && data.grupo == "Admin") return BadRequest(new { message = "Si hago esto me estaria bloqueando la cuenta a mi mismo" });
var ret = RepositorioUsuarios.Singleton.CheckGrupo(data.email, data.grupo);
if (!ret) return BadRequest(new { message = $"El usuario no pertenece al grupo {data.grupo}"});
if (data.grupo == "Propietario") {
IQueryable<PropiedadesDto> ret3 = RepositorioPropiedades.Singleton.ObtenerPropiedadesPorEmail(data.email);
if (ret3.Count() > 0){
bool ret4 = RepositorioPropiedades.Singleton.BajaPropiedades(data.email);
if (ret4 == false) return BadRequest(new { message = "No se pudo dar de baja las propiedades"});
}
}
if (data.grupo == "Inquilino") {
var ret5 = RepositorioContratos.Singleton.ObtenerContratosPorEmailInquilino(data.email);
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);
return ret2 ? Ok(new {message = $"Se elimino del Grupo: {data.grupo}"}): BadRequest(new { message = "Fallo al añadirse al Grupo" });
}
[HttpDelete("api/admin/cliente")]
public IActionResult BajaCliente([FromHeader(Name ="Auth")]string Auth, long Dni){
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 tener un Dni menor o igual a 0"});
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorDni(Dni);
if (cli == null) return BadRequest(new {message = "No existe un cliente con ese numero de dni"});
bool esPropietario = RepositorioUsuarios.Singleton.CheckGrupo(cli.Email, "Propietario");
bool esInquilino = RepositorioUsuarios.Singleton.CheckGrupo(cli.Email, "Inquilino");
if (esPropietario) {
IQueryable<PropiedadesDto> ret3 = RepositorioPropiedades.Singleton.ObtenerPropiedadesPorEmail(cli.Email);
if (ret3.Count() > 0){
bool ret4 = RepositorioPropiedades.Singleton.BajaPropiedades(cli.Email);
if (ret4 == false) return BadRequest(new { message = "No se pudo dar de baja las propiedades"});
}
}
if (esInquilino) {
var ret5 = RepositorioContratos.Singleton.ObtenerContratosPorEmailInquilino(cli.Email);
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"});
}
// lo da de baja si no tiene el grupo propietario y no tiene alquileres pendientes
var ret = RepositorioUsuarios.Singleton.BajaCliente(Dni);
return Ok(ret);
}
[HttpDelete("api/admin/propiedad")]
public IActionResult BajaPropiedad([FromHeader(Name = "Auth")] string Auth, int id = 0) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 10);
if (validacion1 == false) return Unauthorized();
if (id <= 0) return BadRequest(new { message = "Falto indicar id Propiedad"});
var ret = RepositorioPropiedades.Singleton.BajaPropiedad(id);
return ret ?
Ok(new {message = "Se cambio el estado de la propiedad"}): BadRequest(new { message = "No se pudo dar de baja"});
}
[HttpGet("api/admin/busqueda/paginada")]
public IActionResult FiltroPropiedadesPaginado([FromHeader(Name = "Auth")]string Auth, int cantidadHabitaciones = 0, int tipoPropiedad = 0, [FromQuery]string servicios = "", int pag = 1) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 10);
if (validacion1 == false) return Unauthorized();
IQueryable<PropiedadesAdmin>? props = null;
pag -= 1;
var clave = $"{(cantidadHabitaciones != 0 ? "1" : "0")}{(tipoPropiedad != 0 ? "1" : "0")}{(!string.IsNullOrEmpty(servicios) ? "1" : "0")}";
var gen = AdminBusquedaContext.Singleton;
var estrategia = gen.ObtenerEstrategia(clave);
props = estrategia.Filtrar(servicios, cantidadHabitaciones, tipoPropiedad, pag);
return Ok(props);
}
[HttpGet("api/admin/busqueda/cantPag")]
public IActionResult CantidadPaginas([FromHeader(Name = "Auth")]string Auth, int cantidadHabitaciones = 0, int tipoPropiedad = 0, [FromQuery]string servicios = "") {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 10);
if (validacion1 == false) return Unauthorized();
int ret = RepositorioPropiedades.Singleton.CuantasPaginasBusqueda(cantidadHabitaciones, servicios, tipoPropiedad, 0);
return Ok(new { message = ret});
}
}

View File

@@ -0,0 +1,49 @@
using Entidades.Dto;
using Modelo;
using Microsoft.AspNetCore.Mvc;
namespace AlquilaFacil.Controllers;
[ApiController]
public class BusquedaController: ControllerBase {
[HttpGet("api/busqueda")]
public IActionResult FiltroPropiedades([FromHeader(Name = "Auth")]string Auth, int cantidadHabitaciones = 0, int tipoPropiedad = 0, [FromQuery]string servicios = "") {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 3);
if (validacion1 == false) return Unauthorized();
IQueryable<PropiedadesDto>? props = null;
if (servicios == ""){
//no hay parametros de busqueda
if (cantidadHabitaciones == 0 && tipoPropiedad == 0 ) props = RepositorioPropiedades.Singleton.ListarPropiedades();
//Solo Habitaciones
if (cantidadHabitaciones != 0 && tipoPropiedad == 0) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorHabitaciones(cantidadHabitaciones);
//Solo TipoPropiedad
if (cantidadHabitaciones == 0 && tipoPropiedad != 0) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorTipo(tipoPropiedad);
//Habitaciones y TipoPropiedad
if (cantidadHabitaciones != 0 && tipoPropiedad != 0) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorHabitaciones_Tipo(cantidadHabitaciones, tipoPropiedad);
} else {
//Solo se filtra por servicios
if (cantidadHabitaciones == 0 && tipoPropiedad == 0 ) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorServicios(servicios);
//Servicios y habitaciones
if (cantidadHabitaciones != 0 && tipoPropiedad == 0) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorHabitaciones_Servicios(cantidadHabitaciones, servicios);
//Tipo y Servicios
if (cantidadHabitaciones == 0 && tipoPropiedad != 0) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorTipo_Servicios(tipoPropiedad, servicios);
// Todos los parametros
if (cantidadHabitaciones != 0 && tipoPropiedad != 0) props = RepositorioPropiedades.Singleton.ObtenerPropiedesPorHabitaciones_Tipo_Servicios(cantidadHabitaciones, tipoPropiedad, servicios);
}
return Ok(props);
}
[HttpGet("api/busqueda/cantPag")]
public IActionResult GetCantPag([FromHeader(Name = "Auth")]string Auth, int cantidadHabitaciones = 0, int tipoPropiedad = 0, [FromQuery]string servicios = "") {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 3);
if (validacion1 == false) return Unauthorized();
int ret = RepositorioPropiedades.Singleton.CuantasPaginasBusqueda(cantidadHabitaciones, servicios, tipoPropiedad, 1);
return Ok(new { message = ret});
}
}

View File

@@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
using Modelo;
namespace AlquilaFacil.Controllers;
[ApiController]
public class ContratoController: ControllerBase {
[HttpGet("api/contratos")]
public IActionResult ObtenerContratosPorUsuario([FromHeader(Name="Auth")]string Auth) {
return Ok();
}
}

View File

@@ -26,13 +26,13 @@ public class InquilinoController: ControllerBase
[HttpPost("api/inquilino")]
public IActionResult Post([FromBody] CrearClienteDto cid, [FromHeader(Name = "Auth")] string Auth) {
if (!string.IsNullOrEmpty(Auth)) return BadRequest();
if (string.IsNullOrEmpty(Auth)) return BadRequest(new {message = "El String Auth Esta Vacio"});
var ret3 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 4);
if (ret3 == false) return BadRequest(ret3);
if (ret3 == false) return BadRequest(new {message = "Falló el permiso"});
var ret = verificarCrearUsuario(cid);
if (ret != "") return BadRequest(ret);
if (ret != "") return BadRequest(new {message = ret});
var cli = new Cliente {
Dni = cid.dni,
@@ -45,7 +45,7 @@ public class InquilinoController: ControllerBase
};
bool ret2 = RepositorioUsuarios.Singleton.AltaInquilino(cli);
return (ret2) ? Ok() : BadRequest(ret);
return (ret2) ? Ok(new {message = "Se dio de alta la cuenta"}) : BadRequest(new {message = "Fallo Dar de Alta El inquilino"});
}
private string verificarCrearUsuario(CrearClienteDto cid) {

View File

@@ -1,6 +1,5 @@
using Entidades;
using Entidades.Dto;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Modelo;
@@ -12,6 +11,7 @@ public class PropiedadesController: ControllerBase {
public IActionResult ListarPropiedades([FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 12);
if (validacion1 == false) validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 2);
if (validacion1 == false) return Unauthorized();
var ret = RepositorioPropiedades.Singleton.ListarPropiedades();
@@ -24,27 +24,42 @@ public class PropiedadesController: ControllerBase {
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 12);
if (validacion1 == false) return Unauthorized();
if (Id < 0) return BadRequest("la id de propiedad no puede ser negativa");
if (Id < 0) return BadRequest(new {message ="la id de propiedad no puede ser negativa"});
var ret = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(Id);
if (ret == null) return BadRequest("No existe la propiedad");
if (ret == null) return BadRequest(new {message ="No existe la propiedad"});
return Ok(ret);
}
[HttpGet("api/propiedades/Propietario")]
public IActionResult ObtenerPropiedadesPorPropietario (
[FromBody] string email,
[FromHeader(Name = "Email")] string email,
[FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 12);
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 2);
if (validacion1 == false) return Unauthorized();
email = email.Trim();
if (String.IsNullOrEmpty(email)) return BadRequest("falta campo email");
if (String.IsNullOrEmpty(email)) return BadRequest(new {message ="falta campo email"});
var ret = RepositorioPropiedades.Singleton.ObtenerPropiedadesPorEmail(email);
IQueryable<PropiedadesDto> ret = RepositorioPropiedades.Singleton.ObtenerPropiedadesPorEmail(email);
return Ok(ret);
}
[HttpGet("api/propiedades/Propietario/Bajas")]
public IActionResult ObtenerPropiedadesPorPropietarioBajas (
[FromHeader(Name = "Email")] string email,
[FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 8);
if (validacion1 == false) return Unauthorized();
email = email.Trim();
if (String.IsNullOrEmpty(email)) return BadRequest(new {message ="falta campo email"});
IQueryable<PropiedadesDto> ret = RepositorioPropiedades.Singleton.ObtenerPropiedadesDeBajaPorEmail(email);
return Ok(ret);
}
@@ -58,71 +73,107 @@ public class PropiedadesController: ControllerBase {
if (validacion2 != "") return BadRequest(new { message = validacion2 });
Cliente? cli = RepositorioPropietario.Singleton.ObtenerPropietarioPorEmail(propiedad.Email);
if (cli == null) return BadRequest("El email no corresponde a un propietario");
if (cli == null) return BadRequest(new { message = "El email no corresponde a un propietario"});
Propiedade Prop = new Propiedade{
Canthabitaciones = propiedad.Canthabitaciones,
Dnipropietario = cli.Dni,
Idtipropiedad = propiedad.Idtipropiedad,
Ubicacion = propiedad.Ubicacion,
Letra = propiedad.Letra != null ? propiedad.Letra : null,
Piso = propiedad.Piso != null ? propiedad.Piso : null,
Letra = propiedad.Letra ?? null,
Piso = propiedad.Piso ?? null,
Monto = propiedad.Monto,
};
var ret = RepositorioPropiedades.Singleton.AñadirPropiedad(Prop);
return (ret)?
Ok("Fue Cargado Correctamente") :
BadRequest("Fallo al momento de añadir la propiedad a la base de datos");
Ok(new { message = "Fue Cargado Correctamente"}) :
BadRequest(new { message = "Fallo al momento de añadir la propiedad a la base de datos"});
}
[HttpPatch("api/propiedad")]
public IActionResult PatchPropiedad([FromBody] PatchPropiedadDto propiedad, [FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 2);
if (validacion1 == false) return Unauthorized();
string validacion2 = ValidarPropiedad(propiedad);
if (validacion2 != "") return BadRequest(new { message = validacion2 });
Cliente? cli = RepositorioPropietario.Singleton.ObtenerPropietarioPorEmail(propiedad.Email);
if (cli == null) return BadRequest(new { message = "El email no corresponde a un propietario"});
List<Servicio> servs = RepositorioServicios.Singleton.ObtenerServiciosPorDescripcion(propiedad.Servicios);
Propiedade Prop = new Propiedade{
Id = propiedad.id,
Canthabitaciones = propiedad.Canthabitaciones,
Dnipropietario = cli.Dni,
Idtipropiedad = propiedad.tipo,
Ubicacion = propiedad.Ubicacion,
Letra = propiedad.Letra ?? null,
Piso = propiedad.Piso ?? null,
IdServicios = servs,
Monto = propiedad.Monto
};
bool ret = RepositorioPropiedades.Singleton.PatchPropiedad(Prop);
return (ret)?
Ok(new {message = "Fue modificado Correctamente"}):
BadRequest(new {message = "Fallo al modificar la base de datos"});
}
[HttpDelete("api/propiedad")]
public IActionResult BajaPropiedad(int id, [FromHeader(Name = "Auth")] string Auth){
public IActionResult BajaPropiedad(int id, [FromHeader(Name = "Auth")] string Auth, [FromHeader(Name = "Email")] string email){
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 2);
if (validacion1 == false) return Unauthorized();
if (id <= 0) return BadRequest("No es una id valida");
if (String.IsNullOrEmpty(email)) return BadRequest(new { message = "Fallo al identificarse el usuario"});
if (id <= 0) return BadRequest(new { message = "No es una id valida"});
var ret = RepositorioPropiedades.Singleton.BajaPropiedad(id);
Cliente? propie = RepositorioPropietario.Singleton.ObtenerPropietarioPorEmail(email);
var ret = RepositorioPropiedades.Singleton.BajaPropiedad(id, propie);
return ret ?
Ok(new {message = $"la propiedad con id {id} fue dada de baja"}):
BadRequest("Fallo al dar de baja la propiedad");
Ok(new { message = $"Se Cambio el estado de la propiedad con id {id}"}):
BadRequest(new {message="Fallo al cambiar el estado de la propiedad"});
}
[HttpPut("api/propiedades/addServicio")]
public IActionResult AñadirServicio([FromBody] ServicioAPropiedadDto Servicios, [FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 8);
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 2);
if (validacion1 == false) return Unauthorized();
if (Servicios.propiedadid <= 0) return BadRequest("No puede tener una id negativa o cero");
if (Servicios.idServicios.Count() < 1) return BadRequest("Falta añadir servicios");
if (Servicios.idServicios.Any(x => x<= 0)) return BadRequest("No tienen haber ids negativas o cero de servicio");
if (Servicios.propiedadid <= 0) return BadRequest(new {message ="No puede tener una id negativa o cero"});
if (Servicios.idServicios.Count() < 1) return BadRequest(new {message ="Falta añadir servicios"});
if (Servicios.idServicios.Any(x => x<= 0)) return BadRequest(new {message ="No tienen haber ids negativas o cero de servicio"});
var serv = RepositorioServicios.Singleton.ObtenerServiciosPorPropiedad(Servicios.propiedadid);
bool validacion2 = Servicios.idServicios.Any(x => serv.Contains(x));
if (validacion2 == true) return BadRequest("Hay elementos repetidos");
if (validacion2 == true) return BadRequest(new {message ="Hay elementos repetidos"});
bool ret = RepositorioPropiedades.
Singleton.AñadirServicioAPropiedad(Servicios.propiedadid, Servicios.idServicios);
return ret ?
Ok("Los Servicios Se Cargaron correctamente a la propiedad") : BadRequest("No se pudo Cargar los Servicios a la propiedad");
Ok(new {message ="Los Servicios Se Cargaron correctamente a la propiedad"}) : BadRequest(new {message ="No se pudo Cargar los Servicios a la propiedad"});
}
[HttpPut("api/propiedades/RmServicio")]
public IActionResult EliminarServicio([FromBody] ServicioAPropiedadDto servicio, [FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 13);
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 2);
if (validacion1 == false) return Unauthorized();
if (servicio.propiedadid <= 0) return BadRequest("No puede tener una id negativa o cero");
if (servicio.idServicios.Count() < 1) return BadRequest("Falta añadir servicios");
if (servicio.idServicios.Any(x => x<= 0)) return BadRequest("No tienen haber ids negativas o cero de servicio");
if (servicio.propiedadid <= 0) return BadRequest(new {message ="No puede tener una id negativa o cero"});
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"});
var serv = RepositorioServicios.Singleton.ObtenerServiciosPorPropiedad(servicio.propiedadid);
@@ -131,7 +182,7 @@ public class PropiedadesController: ControllerBase {
bool ret = RepositorioPropiedades.Singleton.BajaServiciosAPropiedad(servicio.propiedadid, servicio.idServicios);
return ret ?
Ok("Se Eliminaron los servicios seleccionados de la propiedad") : BadRequest("Fallo al eliminarse los servicios de la propiedad");
Ok(new {message ="Se Eliminaron los servicios seleccionados de la propiedad"}) : BadRequest(new {message ="Fallo al eliminarse los servicios de la propiedad"});
}
@@ -140,11 +191,34 @@ public class PropiedadesController: ControllerBase {
string ret = "";
if (String.IsNullOrEmpty(prop.Email)) ret += "Falta Definir un email de propietario\n";
if (prop.Canthabitaciones < 0) ret += "No se puede tener una cantidad de habitaciones negativa\n";
if (prop.Idtipropiedad <= 0) ret += "No tiene un tipo de propiedad asociada";
if (prop.Idtipropiedad <= 0) ret += "No tiene un tipo de propiedad asociada\n";
if (String.IsNullOrEmpty(prop.Ubicacion)) ret += "Tiene que definir la ubicacion de la propiedad\n";
if (prop.Monto<=1) ret += "El monto tiene que ser como minimo mayor a 0";
return ret;
}
}
private string ValidarPropiedad(PatchPropiedadDto prop) {
if (prop == null) return "Esta mal formado el body de la request";
string ret = "";
if (prop.id <1) ret += "No Cargo el dato de id";
if (String.IsNullOrEmpty(prop.Email)) ret += "Falta Definir un email de propietario\n";
if (prop.id <1 ) ret += "No puede haber una id menor a 1\n";
if (prop.Canthabitaciones < 0) ret += "No se puede tener una cantidad de habitaciones negativa\n";
if (prop.tipo <= 0) ret += "No tiene un tipo de propiedad asociada\n";
if (String.IsNullOrEmpty(prop.Ubicacion)) ret += "Tiene que definir la ubicacion de la propiedad\n";
if (prop.Monto<=1) ret += "El monto tiene que ser como minimo mayor a 0";
return ret;
}
}

View File

@@ -21,7 +21,7 @@ public class PropietarioController: ControllerBase {
return Ok(ret);
}
[HttpPost("api/propietarios")]
[HttpPost("api/propietario")]
public IActionResult AltaPropietario([FromBody]CrearClienteDto Propietario,
[FromHeader(Name = "Auth")] string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();

View File

@@ -0,0 +1,2 @@
namespace Entidades.Admin;
public record EmailGrupo(string email, string grupo);

View File

@@ -0,0 +1,7 @@
namespace Entidades.Admin;
public class GrupoAdmin {
public int Id {get; set;} = 0;
public String Descripcion {get; set;} = "";
public List<Entidades.Admin.PermisoAdmin> Permisos {get; set;} = new();
}

View File

@@ -0,0 +1,6 @@
namespace Entidades.Admin;
public class PermisoAdmin {
public int Id {get; set;}
public String Descripcion {get; set;} = "";
}

View File

@@ -0,0 +1,8 @@
namespace Entidades.Admin;
public record UsuarioAdmin {
public long Dni { get; set; } = 0;
public string Nombre { get; set; } = "";
public string Email { get; set; } = "";
public ulong Habilitado { get; set; }
}

View File

@@ -178,6 +178,7 @@ public partial class AlquilaFacilContext : DbContext
entity.Property(e => e.Indiceactualizacion)
.HasPrecision(8)
.HasColumnName("indiceactualizacion");
entity.Property(e => e.MesesHastaAumento).HasColumnType("int(11)");
entity.Property(e => e.Monto)
.HasPrecision(12)
.HasColumnName("monto");
@@ -378,7 +379,7 @@ public partial class AlquilaFacilContext : DbContext
.HasColumnType("int(11)")
.HasColumnName("id");
entity.Property(e => e.Descripcion)
.HasMaxLength(15)
.HasMaxLength(25)
.HasColumnName("descripcion");
entity.HasMany(d => d.Idgrupos).WithMany(p => p.Idpermisos)
@@ -435,6 +436,9 @@ public partial class AlquilaFacilContext : DbContext
.HasMaxLength(1)
.IsFixedLength()
.HasColumnName("letra");
entity.Property(e => e.Monto)
.HasPrecision(10)
.HasColumnName("monto");
entity.Property(e => e.Piso)
.HasColumnType("int(11)")
.HasColumnName("piso");

View File

@@ -27,6 +27,8 @@ public partial class Contrato
public ulong Habilitado { get; set; }
public int MesesHastaAumento { get; set; }
public virtual ICollection<Defecto> Defectos { get; set; } = new List<Defecto>();
public virtual Cliente? DniinquilinoNavigation { get; set; }

View File

@@ -6,4 +6,5 @@ public class AltaPropiedadDto {
public string? Letra { get; set; } = null;
public string Email { get; set; } = string.Empty;
public int Idtipropiedad { get; set; }
public int Monto { get; set; }
}

View File

@@ -0,0 +1,3 @@
namespace Entidades.Dto;
public record BusquedaDto(int Id, string Ubicacion, string? Servicios = "");

View File

@@ -0,0 +1,7 @@
namespace Entidades.Dto;
//WIP
public class CrearContratoDto {
public int Meses {get; set;}
public int Idpropiedad {get; set;}
}

View File

@@ -0,0 +1,3 @@
namespace Entidades.Dto;
public record PatchPropiedadDto(int id, string Ubicacion, int Canthabitaciones, int? Piso, string? Letra, string Email, int tipo, List<string> Servicios, int Monto);

View File

@@ -3,7 +3,9 @@ public class PropiedadesDto {
public int id { get; set; }
public string Ubicacion { get; set; } = "";
public int canthabitaciones { get; set; }
public string piso { get; set; } = "";
public int piso { get; set; }
public string letra { get; set; } = "";
public string TipoPropiedad { get; set; } = "";
}
public string Tipo { get; set; } = "";
public string? Servicios {get;set;} = "";
public int Monto { get; set; }
}

View File

@@ -21,6 +21,8 @@ public partial class Propiedade
public int? Idestado { get; set; }
public decimal Monto { get; set; }
public virtual ICollection<Contrato> Contratos { get; set; } = new List<Contrato>();
public virtual Cliente? DnipropietarioNavigation { get; set; }

Binary file not shown.

View File

@@ -5,7 +5,11 @@
<link rel="icon" type="image/png" href="/favicon.svg" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Configura el tema desde localStorage antes de cargar la aplicación
const savedTheme = localStorage.getItem("theme") || "light";
document.documentElement.setAttribute("data-bs-theme", savedTheme);
</script>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AlquilaFacil</title>
</head>

View File

@@ -21,6 +21,7 @@
"dependencies": {
"@sveltejs/kit": "^2.7.3",
"@sveltestrap/sveltestrap": "^6.2.7",
"chartjs": "^0.3.24",
"svelte-routing": "^2.13.0"
}
}

View File

@@ -0,0 +1,14 @@
<!--
unicode: "fec0"
version: "3.2"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M8 9a3 3 0 1 1 -3 3l.005 -.176a3 3 0 0 1 2.995 -2.824" />
<path d="M16 5a7 7 0 0 1 0 14h-8a7 7 0 0 1 0 -14zm0 2h-8a5 5 0 1 0 0 10h8a5 5 0 0 0 0 -10" />
</svg>

After

Width:  |  Height:  |  Size: 327 B

View File

@@ -0,0 +1,14 @@
<!--
unicode: "febf"
version: "3.2"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M16 9a3 3 0 1 1 -3 3l.005 -.176a3 3 0 0 1 2.995 -2.824" />
<path d="M16 5a7 7 0 0 1 0 14h-8a7 7 0 0 1 0 -14zm0 2h-8a5 5 0 1 0 0 10h8a5 5 0 0 0 0 -10" />
</svg>

After

Width:  |  Height:  |  Size: 328 B

19
Front/public/zoom.svg Normal file
View File

@@ -0,0 +1,19 @@
<!--
tags: [find, magnifier, magnifying glass]
version: "1.0"
unicode: "fdaa"
-->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="white"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" />
<path d="M21 21l-6 -6" />
</svg>

After

Width:  |  Height:  |  Size: 369 B

View File

@@ -6,11 +6,17 @@
import InfoPage from './paginas/info.svelte';
import InqPage from "./paginas/inquilino.svelte";
import PropPage from "./paginas/propietario.svelte";
import MisPropiedades from "./paginas/MisPropiedades.svelte";
import MisPropiedadesDeBaja from "./paginas/MisPropiedadesDeBaja.svelte";
import FrontAdmin from "./paginas/grupos/AdminG.svelte";
import FrontEstadistica from "./paginas/grupos/EstadisticaG.svelte";
import FrontInformes from "./paginas/grupos/InformesG.svelte";
import FrontInquilino from "./paginas/grupos/InquilinoG.svelte";
import FrontPropietario from "./paginas/grupos/PropietarioG.svelte";
import PublicarPropiedad from "./paginas/PublicarPropiedad.svelte";
import PublicarPropiedad from "./paginas/PublicarPropiedad.svelte";
import BusquedaPropiedades from "./paginas/BusquedaPropiedades.svelte";
import ControlUsuarios from "./paginas/AdminUsuarios.svelte";
import ControlPropiedades from "./paginas/AdminPropiedades.svelte";
import Notificaciones from "./paginas/Notificaciones.svelte";
</script>
<Router>
@@ -33,16 +39,38 @@
<ProteRoute componente={PublicarPropiedad}/>
</Route>
<!--Mis Propiedades-->
<Route path="/accion/2">
<ProteRoute componente={MisPropiedades}/>
</Route>
<!--Buscar Propiedades-->
<Route path="/accion/3">
<ProteRoute componente={BusquedaPropiedades}/>
</Route>
<!--Crear Cuenta Inquilino-->
<Route path="/accion/4">
<ProteRoute componente={InqPage}/>
</Route>
<!--Crear Cuenta Propietario-->
<Route path="/accion/5">
<ProteRoute componente={PropPage}/>
</Route>
<!--Administrar Propiedades Dadas de Baja-->
<Route path="/accion/8">
<ProteRoute componente={MisPropiedadesDeBaja}/>
</Route>
<!-- Pantalla Control Usuarios -->
<Route path="/accion/9">
<ProteRoute componente={ControlUsuarios}/>
</Route>
<!--Paginas info Grupo-->
<Route path="/grupo/Inquilino">
<ProteRoute componente={FrontInquilino}/>
</Route>
@@ -52,9 +80,15 @@
<Route path="/grupo/Admin">
<ProteRoute componente={FrontAdmin}/>
</Route>
<Route path="/grupo/Estadistica">
<ProteRoute componente={FrontEstadistica}/>
<Route path="/grupo/Informes">
<ProteRoute componente={FrontInformes}/>
</Route>
<!--Notificaciones-->
<Route path="/notificaciones">
<ProteRoute componente={Notificaciones}/>
</Route>
</Router>

View File

@@ -1,11 +1,11 @@
<script lang="ts">
let prop = $props();
let {text} = $props();
</script>
<div class="row">
<div class="col"><hr></div>
<div class="col-auto"><h5>{prop.text}</h5></div>
<div class="col-auto"><h5>{text}</h5></div>
<div class="col"><hr></div>
</div>

View File

@@ -0,0 +1,14 @@
<script lang="ts">
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: "smooth" });
};
</script>
<button
class="btn btn-primary position-fixed bottom-0 end-0 mb-4 me-4 p-3"
on:click={scrollToTop}
title="Ir arriba"
style="z-index: 1000; "
>
</button>

View File

@@ -18,16 +18,24 @@
let domicilio: string = $state("")
let celular: string = $state("")
const token = sessionStorage.getItem("token");
async function submitForm(event: any) {
event.preventDefault();
try {
let response = await fetch(url, {
method: 'POST',
headers: {
'Auth' : String(token),
'Content-Type' : 'application/json',
},
body: JSON.stringify({dni, nombre, apellido, domicilio, celular, email, contraseña})
});
if (response.ok){
const errorData = await response.json();
errorMessage = errorData.message;
showAlert = true;
}
if (!response.ok) {
const errorData = await response.json();
errorMessage = errorData.message;

View File

@@ -1,6 +1,8 @@
<script lang="ts">
import { onMount } from "svelte";
import { writable } from "svelte/store";
import { urlG } from "../stores/urlStore";
import { links, navigate } from "svelte-routing";
type Permiso = {
id: number;
@@ -21,7 +23,7 @@
const match = path.match(/\/grupo\/(.+)/);
const grupo = match ? match[1] : null;
try {
const response = await fetch("http://localhost:5007/api/acciones/grupo",{
const response = await fetch(String($urlG)+"/api/acciones/grupo",{
method: 'POST',
headers: {
'Auth' : String(token),
@@ -37,12 +39,15 @@
console.error(e);
}
}
function redirijir(path: string){
navigate(path);
}
</script>
<div class="list-group">
<div class="list-group border border-success" use:links>
{#each $permisos as item}
<a href="/accion/{item.id}" class="list-group-item list-group-item-action">
<a class="list-group-item list-group-item-action" href="/accion/{item.id}">
{item.descripcion}
</a>
{/each}
</div>
</div>

View File

@@ -1,11 +1,11 @@
<script>
import { CardHeader, CardTitle, Button, Card, Input, Form, CardBody, FormGroup } from '@sveltestrap/sveltestrap';
import { navigate } from 'svelte-routing';
import { urlG } from "../stores/urlStore";
let email = $state("")
let contraseña = $state("")
let errorMessage = $state("")
let showAlert = false;
// @ts-ignore
async function submitForm(event) {
@@ -13,7 +13,7 @@
const data = {email, contraseña};
try{
const response = await fetch("http://127.0.0.1:5007/api/login",{
const response = await fetch(String($urlG)+"/api/login",{
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -25,12 +25,10 @@
if (!response.ok){
const errorData = await response.json()
errorMessage = errorData.message;
showAlert = true;
return;
}
const ret = await response.json();
localStorage.clear();
localStorage.setItem('email', ret.email);
sessionStorage.setItem('token', ret.token);
//setTimeout(() => console.log("50ms") ,50);
@@ -42,7 +40,7 @@
</script>
<Card class="position-sticky top-50 start-50 translate-middle-x" style="width: 20rem; height: auto;" theme="auto" color="dark" outline>
<Card class="position-sticky top-50 start-50 translate-middle-x border border-success" style="width: 20rem; height: auto;" theme="auto" outline>
<CardHeader>
<CardTitle>Iniciar Sesión</CardTitle>
</CardHeader>

View File

@@ -0,0 +1,18 @@
<script lang="ts">
import { Modal } from '@sveltestrap/sveltestrap';
const toggle = () => (open = !open);
let {payload, close = toggle, iscomponent = false } = $props();
let open = $state(true);
</script>
<div>
<Modal body isOpen={open} toggle={close}>
{#if iscomponent == false}
{payload}
{:else}
{@render payload()}
{/if}
</Modal>
</div>

View File

@@ -1,28 +1,23 @@
<script lang="ts">
import { Navbar, NavbarBrand, NavbarToggler, NavItem, Nav, NavLink, Collapse } from "@sveltestrap/sveltestrap";
import { Navbar, NavbarBrand, NavbarToggler, Nav, Collapse } from "@sveltestrap/sveltestrap";
import { onMount } from "svelte";
import { writable } from 'svelte/store';
import { link, links } from "svelte-routing";
import './css/popup.css';
import type { Grupo } from "../types";
import { urlG } from "../stores/urlStore";
import { navigate } from "svelte-routing";
let isOpen: boolean = $state(false);
type Permiso = {
id: number;
descripcion: string;
};
type Grupo = {
id: number;
nombre: string;
idpermisos: Permiso[];
};
const permisos = writable<Grupo[]>([]);
const email = localStorage.getItem('email');
const token = sessionStorage.getItem('token');
async function obtenerPermisos(){
try {
const response = await fetch("http://localhost:5007/api/acciones",{
const response = await fetch(String($urlG)+"/api/acciones",{
method: 'GET',
headers: {
'Auth' : String(token),
@@ -46,23 +41,42 @@
})
function redirijir(path: string){
location.replace(path);
navigate(path);
}
let theme = $state(localStorage.getItem("theme") ?? "light");
const toggleTheme = () => {
theme = theme === "light" ? "dark" : "light";
document.body.setAttribute("data-bs-theme", theme);
localStorage.setItem("theme", theme);
};
</script>
<Navbar container="xxl" expand="md" color="dark-subtle">
<NavbarBrand href="/">
AlquilaFacil
</NavbarBrand>
<div class="badge">
<a href="/Menu">
<img src="/home.svg" alt="Volver al Menú"/>
</a>
<div>
<div class="badge" style="background-color: turquoise;" use:links>
<a href="/Menu">
<img src="/home.svg" alt="Volver al Menú"/>
</a>
</div>
<button class="badge btn" onclick={toggleTheme} style="background-color: cadetblue;">
{#if theme === "light" }
<img src="/toggle-left.svg" alt=""/>
{:else}
<img src="/toggle-right.svg" alt=""/>
{/if}
</button>
<button class="badge btn btn-info" onclick={()=>navigate("/notificaciones")}>
<img src="/bell.svg" alt="">
</button>
</div>
<NavbarToggler on:click={() => (isOpen = !isOpen)} />
<Collapse isOpen={isOpen} navbar expand="md">
<Nav class="ms-auto" navbar>
<Nav class="ms-auto" navbar >
{#each $permisos as item }
<div class="dropdown">
<div class="btn-group" style="margin-left: 3px; margin-top: 3px">
@@ -70,9 +84,9 @@
<button class="btn btn-secondary dropdown-toggle dropdown-toggle-split" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu dropdown-menu-end" >
<ul class="dropdown-menu dropdown-menu-end" use:links>
{#each item.idpermisos as perm}
<li class="dropdown-item"><a class="link-underline-opacity-0 link-underline" href="/accion/{perm.id}">{perm.descripcion}</a></li>
<a class="dropdown-item link-underline-opacity-0 link-underline" href="/accion/{perm.id}" >{perm.descripcion}</a>
<li><hr class="dropdown-divider"></li>
{/each}
</ul>

View File

@@ -0,0 +1,74 @@
<script lang="ts">
import "./css/dotted-line.css";
import { navigate } from 'svelte-routing';
let canthabitaciones = $state(0);
let servicios = ["Gas", "Internet", "Telefono", "Luz"];
let serviciosSel = $state([]);
let tipo = $state(0);
async function formsubmit (e){
e.preventDefault();
const url = window.location.pathname;
const goto = url+"?cantidadHabitaciones="+canthabitaciones+"&tipoPropiedad="+tipo+"&servicios="+serviciosSel.join(",");
window.location.replace(goto);
}
</script>
<form class="card p-3 border border-succes">
<div>Busqueda Filtrada
<div class="dotted-line">
</div>
<div class="form-floating mb-3">
<input
type="number"
id="canthabitaciones"
class="form-control"
bind:value={canthabitaciones}
min="1"
placeholder="Cantidad de Habitaciones"
required
/>
<label for="canthabitaciones">Cantidad de Habitaciones</label>
</div>
<div class="mb-3">
<h6 class="form-floating form-label">Servicios</h6>
{#each servicios as servicio}
<div class="form-check">
<input
type="checkbox"
class="form-check-input"
bind:group={serviciosSel}
value={servicio}
id={`servicio-${servicio}`}
/>
<label class="form-check-label" for={`servicio-${servicio}`}>
{servicio}
</label>
</div>
{/each}
</div>
<div class="form-floating mb-3">
<select id="idtipo" class="form-select" bind:value={tipo} required>
<option value="1">Casa</option>
<option value="2">Piso</option>
<option value="3">Departamento</option>
<option value="4">Galpon</option>
<option value="5">LocalComercial</option>
<option value="6">Oficina</option>
</select>
<label for="idtipopropiedad">Tipo de propiedad</label>
</div>
<button type="submit" class="btn btn-primary w-100 d-flex align-items-center justify-content-center" onclick={formsubmit}>
Buscar
<img src="/zoom.svg" alt="" class="ms-2" style="height: 1.2em;" />
</button>
</form>

View File

@@ -0,0 +1,27 @@
<script lang="ts">
import type { PropiedadDto } from "../types";
let { prop }: { prop: PropiedadDto } = $props();
</script>
<div class="card text-center border shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">{prop.tipo}</h5>
</div>
<div class="card-body">
<div class="card-img-top mb-3">
<i class="bi bi-building" style="font-size: 3rem;"></i>
</div>
<h6 class="card-title">{prop.ubicacion}</h6>
<p class="card-text">
<strong>Habitaciones:</strong> {prop.canthabitaciones}<br>
<strong>Piso:</strong> {prop.piso || "N/A"}<br>
<strong>Letra:</strong> {prop.letra || "N/A"}<br>
<strong>Servicios:</strong> {prop.servicios || "Sin servicios especificados"}<br>
<strong>Monto:</strong> ${prop.monto}<br>
</p>
<button class="btn btn-primary">Consultar</button>
</div>
<div class="card-footer text-muted">
ID Propiedad: {prop.id}
</div>
</div>

View File

@@ -0,0 +1,63 @@
<script lang="ts">
import { fade } from "svelte/transition";
import ModalEstatico from "./ModalEstatico.svelte";
import ModificarPropiedadForm from "./modificarPropiedadForm.svelte";
let { id, ubicacion, tipo, letra, piso,canthabitaciones, servicios, btnbaja = "Baja", monto } = $props();
import { urlG } from "../stores/urlStore";
let modal: boolean = $state(false);
let modalpayload: string = $state("");
let modificar: boolean = $state(false);
function setmod(){
modificar = !modificar;
}
async function BajaPropiedad(){
modal = false;
try {
const responce = await fetch(String($urlG)+"/api/propiedad?id="+id, {
method: "DELETE",
headers:{
'Auth' : String(sessionStorage.getItem("token")),
'Email' : String(localStorage.getItem("email"))
},
});
const json = await responce.json();
modalpayload = json.message;
modal = true;
window.location.reload();
}catch (e){
console.error(e);
}
}
</script>
<tr in:fade>
<td>{id}</td>
<td>{ubicacion}</td>
<td>{canthabitaciones}</td>
<td>{letra}</td>
<td>{piso}</td>
<td>{tipo}</td>
<td>{servicios}</td>
<td>{monto}</td>
<td class="text-end">
<button class="btn btn-outline-secondary" onclick={()=> setmod()}>Modificar</button>
<button class="btn btn-outline-danger" onclick={() => BajaPropiedad()}>{btnbaja}</button>
</td>
</tr>
{#if modal}
<ModalEstatico payload={modalpayload}/>
{/if}
{#if modificar}
<tr transition:fade={{duration:100}}>
<td colspan="8">
<ModificarPropiedadForm {id} {ubicacion} {canthabitaciones} {letra} {piso} {tipo} {servicios} {monto}/>
</td>
</tr>
{/if}

View File

@@ -1,54 +1,55 @@
<script>
import { onMount } from 'svelte';
import { navigate } from 'svelte-routing';
import { writable } from 'svelte/store';
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import { urlG } from "../stores/urlStore";
let { componente } = $props();
let { componente } = $props();
const isAuthenticated = writable(false);
const isVerified = writable(false);
const isAuthenticated = writable(false);
const isVerified = writable(false);
const redirect = window.location.pathname;
const email = localStorage.getItem('email');
const token = sessionStorage.getItem('token');
const redirect = window.location.pathname;
const email = localStorage.getItem('email');
const token = sessionStorage.getItem('token');
const handleAccess = async () => {
try {
const response = await fetch('http://127.0.0.1:5007/api/login/validar', {
method: 'POST',
headers: {
'Auth': String(token),
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, redirect }),
credentials: "include"
});
if (response.ok) {
isAuthenticated.set(true); // Actualiza el store
}
} catch (error) {
console.error('Error durante la autenticación:', error);
} finally {
isVerified.set(true); // Marca la verificación como completada
const handleAccess = async () => {
try {
const response = await fetch($urlG+"/api/login/validar", {
method: 'POST',
headers: {
'Auth': String(token),
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, redirect }),
credentials: "include"
});
if (response.ok) {
isAuthenticated.set(true); // Actualiza el store
}
};
} catch (error) {
console.error('Error durante la autenticación:', error);
} finally {
isVerified.set(true); // Marca la verificación como completada
}
};
onMount(() => {
handleAccess();
});
</script>
onMount(() => {
handleAccess();
});
</script>
{#if !$isVerified}
<div class="spinner-border position-absolute top-50 start-50 translate-middle" role="status">
<span class="visually-hidden">Cargando</span>
</div>
{#if !$isVerified}
<div class="d-flex justify-content-center position-absolute top-50 start-50">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
{:else}
{#if $isAuthenticated}
{@render componente()}
{:else}
{#if $isAuthenticated}
{@render componente()}
{:else}
{navigate('/')}
{/if}
{window.location.replace('/')}
{/if}
{/if}

View File

@@ -0,0 +1,5 @@
.dotted-line {
border: none;
border-top: 2px dashed #757575; /* Línea punteada de 2px de grosor y color negro */
margin: 20px 0; /* Márgenes opcionales */
}

View File

@@ -32,7 +32,17 @@
display: block;
}
.popup.show {
animation: rollDown 0.5s ease forwards;
display: block;
}
.dropdown-menu.hide {
animation: rollUp 0.5s ease forwards;
display: block;
}
}
.popup.hide {
animation: rollUp 0.5s ease forwards;
display: block;
}

View File

@@ -0,0 +1,173 @@
<script lang="ts">
import { urlG } from "../stores/urlStore";
import { onMount } from "svelte";
let { canthabitaciones, id, letra, piso, tipo, ubicacion, servicios, monto } = $props();
let serviciosSeleccionados: string[] = $state([]);
const serviciosDisponibles = ["Gas", "Internet", "Telefono", "Luz"];
onMount(() => {
switch (tipo) {
case "Casa":
tipo = "1";
break;
case "Piso":
tipo = "2";
break;
case "Departamento":
tipo = "3";
break;
case "Galpon":
tipo = "4";
break;
case "LocalComercial":
tipo = "5";
break;
case "Oficina":
tipo = "6";
break;
}
serviciosSeleccionados = servicios.split(", ");
});
let showAlert: boolean = $state(false);
let errorMessage: string = $state("");
const token = sessionStorage.getItem("token");
const email = localStorage.getItem("email");
async function submitForm(e: Event) {
e.preventDefault();
try {
let response = await fetch(String($urlG + "/api/propiedad"), {
method: "PATCH",
headers: {
Auth: String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({
id,
canthabitaciones,
letra,
piso,
tipo,
ubicacion,
email,
servicios: serviciosSeleccionados,
monto
}),
});
if (response.ok) {
location.reload();
}
if (!response.ok) {
const errorData = await response.json();
errorMessage = errorData.message;
showAlert = true;
}
} catch (e) {
throw new Error("Fallo al enviar el formulario para crear un inquilino");
}
}
</script>
{#if showAlert}
<div class="alert alert-warning alert-dismissible fade show" role="alert">
<strong>{errorMessage}</strong>
<button
type="button"
class="btn-close close"
aria-label="Close"
data-bs-dismiss="alert"
></button>
</div>
{/if}
<form onsubmit={submitForm} class="card card-body">
<div class="form-floating mb-3">
<input
type="text"
id="ubicacion"
class="form-control"
bind:value={ubicacion}
placeholder="Ubicación"
required
/>
<label for="ubicacion">Ubicación</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="canthabitaciones"
class="form-control"
bind:value={canthabitaciones}
min="1"
placeholder="Cantidad de Habitaciones"
required
/>
<label for="canthabitaciones">Cantidad de Habitaciones</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="piso"
class="form-control"
bind:value={piso}
min="0"
placeholder="Piso"
/>
<label for="piso">Piso</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="monto"
class="form-control"
bind:value={monto}
min="1"
placeholder={monto}
/>
<label for="monto">Monto</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
id="letra"
class="form-control"
bind:value={letra}
maxlength="1"
placeholder="Letra"
/>
<label for="letra">Letra</label>
</div>
<div class="form-floating mb-3">
<select id="idtipo" class="form-select" bind:value={tipo} required>
<option value="1">Casa</option>
<option value="2">Piso</option>
<option value="3">Departamento</option>
<option value="4">Galpon</option>
<option value="5">LocalComercial</option>
<option value="6">Oficina</option>
</select>
<label for="idtipopropiedad">Tipo de propiedad</label>
</div>
<div class="mb-3">
<h6 class="form-floating form-label">Servicios</h6>
{#each serviciosDisponibles as servicio}
<div class="form-check">
<input
type="checkbox"
class="form-check-input"
bind:group={serviciosSeleccionados}
value={servicio}
id={`servicio-${servicio}`}
/>
<label class="form-check-label" for={`servicio-${servicio}`}>
{servicio}
</label>
</div>
{/each}
</div>
<button type="submit" class="btn btn-primary">Enviar</button>
</form>

View File

@@ -0,0 +1,89 @@
<script lang="ts">
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import PublicacionPropiedad from "../Componentes/PublicacionPropiedad.svelte";
import PanelBusqueda from "../Componentes/PanelBusqueda.svelte";
import VolverArriba from "../Componentes/BotonVolverArriba.svelte";
import { onMount } from "svelte";
import { fade } from "svelte/transition";
import {urlG} from "../stores/urlStore"
import type { PropiedadDto } from "../types";
let showButton = $state(false);
let propiedades: PropiedadDto[] = $state([]);
let token = sessionStorage.getItem("token");
const handleScroll = () => {
showButton = window.scrollY > 100;
};
onMount(() => {
checkparametros()?
busqueda():
cargaPropiedades();
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
function checkparametros(){
const params = new URLSearchParams(window.location.search);
if (params.has('cantidadHabitaciones') && params.has('tipoPropiedad')
&& params.has('servicios') ) {
return true;
}
return false
}
async function cargaPropiedades(){
const response = await fetch(String($urlG)+"/api/propiedades", {
method: "GET",
headers: {
"Auth": String(token),
}
});
if (response.ok){
propiedades = await response.json();
}
}
async function busqueda(){
const params = new URLSearchParams(window.location.search);
let hab = params.get('cantidadHabitaciones');
let tipo = params.get('tipoPropiedad');
let serv = params.get('servicios');
const response = await fetch(String($urlG)+"/api/busqueda"+"?cantidadHabitaciones="+hab+
"&tipoPropiedad="+tipo+"&servicios="+serv, {
method: "GET",
headers: {
"Auth": String(token),
}
});
if (response.ok){
propiedades = await response.json();
}
}
</script>
<NavBarAutocompletable/>
<div class="container mt-4">
<div class="row">
<div class="col col-md-8 order-2">
{#each propiedades as item}
<PublicacionPropiedad prop={item} />
<br>
{/each}
</div>
<div class="col-md-4 order-1">
<PanelBusqueda/>
<br>
</div>
</div>
{#if showButton }
<div transition:fade={{duration:100}}>
<VolverArriba/>
</div>
{/if}
</div>

View File

@@ -0,0 +1,241 @@
<script lang="ts">
import { onMount } from "svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import type { Cliente, Grupo } from "../types";
import {urlG} from "../stores/urlStore";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import { fade, fly } from "svelte/transition";
let Clientes: Cliente[] = $state([]);
let Grupos:any[] = $state([]);
let modaldata = $state();
let token = sessionStorage.getItem("token");
let showAddmenu: boolean = $state(false);
let grupo:string = $state("");
let SelCliente: Cliente = $state();
onMount(async () => {
try{
const response = await fetch($urlG+"/api/admin/clientes", {
method: "GET",
headers: {
"Auth": String(token),
}
})
if (response.ok) {
let data: Cliente[] = await response.json();
Clientes = data;
return;
}
modaldata = "fallo al asignar la lista de clientes";
} catch {
modaldata = "fallo al intentar obtener la lista de clientes";
}
});
async function cargaGrupos(cli: Cliente){
try {
const response = await fetch($urlG+"/api/admin/clientes/grupo?Dni="+cli.dni, {
method: "GET",
headers: {
"Auth": String(token),
},
});
if (response.ok){
let data = await response.json();
Grupos = data;
showAddmenu = true;
SelCliente = cli;
return;
}
modaldata = await response.json();
} catch {
modaldata = "no se pudo obtener la lista de grupos";
}
}
async function bajaCliente(event:Event, cli:Cliente) {
//WIP añadir una flag para que muestre que no se pudo dar se alta/baja
event.stopPropagation();
try {
const response = await fetch($urlG+"/api/admin/cliente?Dni="+cli.dni, {
method: "DELETE",
headers: {
"Auth": String(token),
}
});
if(response.ok){
let data = await response.json();
modaldata = data.message;
cli.habilitado = !cli.habilitado;
}
} catch {
modaldata = "";
}
}
async function añadirGrupo(e:Event, cli: Cliente, grupo:string){
e.preventDefault();
if (cli.dni == 0 || cli.email == "" || grupo == ""){
modaldata = "No se selecciono un cliente o Grupo";
return;
}
const email = cli.email;
try {
const response = await fetch($urlG+"/api/admin/cliente/addGrupo", {
method: "PATCH",
headers: {
"Auth": String(token),
'Content-Type' : 'application/json',
},
body: JSON.stringify({email, grupo})
});
if (response.ok){
let data = await response.json();
modaldata = data.message;
cargaGrupos(cli);
return;
}
let data = await response.json();
modaldata = data.message;
} catch {
modaldata = "Falla la conexion al servidor";
}
}
async function BajaGrupo(e:Event, cli: Cliente, grupo:string){
e.preventDefault();
if (cli.dni == 0 || cli.email == "" || grupo == ""){
modaldata = "No se selecciono un cliente o Grupo";
return;
}
const email = cli.email;
if (grupo === "Propietario"){
if (confirm("Sos propietario si te desactivas de ese rol tus propiedades se van a dar de baja, Estas seguro?") == false) return;
}
try {
const response = await fetch($urlG+"/api/admin/cliente/rmGrupo", {
method: "PATCH",
headers: {
"Auth": String(token),
'Content-Type' : 'application/json',
},
body: JSON.stringify({email, grupo})
});
if (response.ok){
let data = await response.json();
modaldata = data.message;
cargaGrupos(cli);
return;
}
let data = await response.json();
modaldata = data.message;
} catch {
modaldata = "Falla la conexion al servidor";
}
}
</script>
<NavBarAutocompletable/>
{#if modaldata}
<ModalEstatico payload={modaldata} close={()=> !!(modaldata = "")}/>
{/if}
<div class="content-fluid align-items-start">
<div class="row">
<div class="col" style="padding-right: 2px;">
<BarraHorizontalConTexto text="Clientes"/>
<div style="height:70vh; overflow-y: auto; max-width: 100%">
<table class="table table-responsive table-sm table-striped table-hover table-bordered">
<thead>
<tr>
<th>Dni</th>
<th>Nombre/Apellido</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
{#each Clientes as cli}
<tr onclick={() => cargaGrupos(cli)} in:fade>
<td>{cli.dni}</td>
<td>{cli.nombre}</td>
<td>{cli.email}</td>
<td>
{#if cli.habilitado}
<button class="btn btn-outline-warning" onclick={(e) => bajaCliente(e, cli)}>
Baja
</button>
{:else}
<button class="btn btn-outline-success" onclick={(e) => bajaCliente(e, cli)}>
Alta
</button>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
<div class="col"style="padding-left: 2px;">
<BarraHorizontalConTexto text="Grupos del Cliente Seleccionado"/>
<table class="table table-striped table-responsive table-sm table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Descripcion</th>
<th></th>
</tr>
</thead>
<tbody>
{#if Grupos.length>0}
{#each Grupos as g}
<tr in:fade>
<td>{g.id}</td>
<td>{g.descripcion}</td>
<td><button class="btn btn-outline-danger" onclick={(e)=>BajaGrupo(e, SelCliente, g.descripcion)}>Baja</button></td>
</tr>
{/each}
{:else if SelCliente != null}
<tr>
<td colspan="2">Este Cliente no tiene Grupos</td>
</tr>
{:else}
<tr>
<td colspan="2">Seleccione un cliente para ver sus grupos</td>
</tr>
{/if}
</tbody>
</table>
{#if showAddmenu}
<div in:fade>
<BarraHorizontalConTexto text="Añadir Grupos al Usuario"/>
<form class="card card-body" onsubmit={(e) => añadirGrupo(e,SelCliente, grupo)}>
<div class="mb-3">
<label for="userRole" class="form-label">Seleccionar Grupo</label>
<select id="userRole" class="form-select" bind:value={grupo}>
<option value="Propietario">Propietario</option>
<option value="Inquilino">Inquilino</option>
<option value="Admin">Admin</option>
<option value="Informes">Informes</option>
</select>
</div>
<button class="btn btn-primary" type="submit">Añadir</button>
</form>
</div>
{/if}
</div>
</div>
</div>

View File

@@ -0,0 +1,68 @@
<script lang="ts">
import { onMount } from "svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte" ;
import { writable } from 'svelte/store';
import RowPropiedad from "../Componentes/RowPropiedad.svelte";
import type { PropiedadDto } from "../types";
import { urlG } from "../stores/urlStore";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
let propiedades = writable<PropiedadDto[]>([]);
let email = localStorage.getItem("email");
let token = sessionStorage.getItem("token");
let fallo: boolean = $state(false);
onMount(async ()=> {
try {
const responce = await fetch(String($urlG)+"/api/propiedades/Propietario", {
method: "GET",
headers: {
'Auth': String(token),
'Email' : String(email),
'Content-Type' : "application/json"
},
});
if (responce.ok){
const json = await responce.json();
propiedades.set(json);
return;
}
if (!responce.ok){
fallo = true;
}
} catch (e){
console.error(e);
}
});
</script>
<NavBarAutocompletable/>
<BarraHorizontalConTexto text="Propiedades dadas de Alta"/>
<div class="container table-responsive">
<table class="container-fluid table-responsive table table-striped table-bordered">
<thead>
<tr>
<th>#</th>
<th>ubicacion</th>
<th>Habitaciones</th>
<th>Letra</th>
<th>Piso</th>
<th>Tipo</th>
<th>Servicios</th>
<th>Monto</th>
<th></th>
</tr>
</thead>
<tbody>
{#each $propiedades as propiedad}
<RowPropiedad id={propiedad.id} ubicacion={propiedad.ubicacion} letra={propiedad.letra} piso={propiedad.piso} tipo={propiedad.tipo} canthabitaciones={propiedad.canthabitaciones} servicios={propiedad.servicios} monto={propiedad.monto} />
{/each}
</tbody>
</table>
</div>
{#if fallo}
<div class="container alert alert-danger">Fallo al intentar Obtener la lista de propiedades</div>
{/if}

View File

@@ -0,0 +1,69 @@
<script lang="ts">
import { onMount } from "svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte" ;
import { writable } from 'svelte/store';
import RowPropiedad from "../Componentes/RowPropiedad.svelte";
import type { PropiedadDto } from "../types";
import { urlG } from "../stores/urlStore";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
let propiedades = writable<PropiedadDto[]>([]);
let email = localStorage.getItem("email");
let token = sessionStorage.getItem("token");
let fallo: boolean = $state(false);
onMount(async ()=> {
try {
const responce = await fetch(String($urlG)+"/api/propiedades/Propietario/Bajas", {
method: "GET",
headers: {
'Auth': String(token),
'Email' : String(email),
'Content-Type' : "application/json"
},
});
if (responce.ok){
const json = await responce.json();
propiedades.set(json);
return;
}
if (!responce.ok){
fallo = true;
}
} catch (e){
console.error(e);
}
});
</script>
<NavBarAutocompletable/>
<BarraHorizontalConTexto text="Propiedades dadas de Baja"/>
<div class="container table-responsive">
<table class="table-responsive table table-striped table-bordered">
<thead>
<tr>
<th>#</th>
<th>ubicacion</th>
<th>Habitaciones</th>
<th>Letra</th>
<th>Piso</th>
<th>Tipo</th>
<th>Servicios</th>
<th>Monto</th>
<th></th>
</tr>
</thead>
<tbody>
{#each $propiedades as propiedad}
<RowPropiedad id={propiedad.id} ubicacion={propiedad.ubicacion} letra={propiedad.letra} piso={propiedad.piso} tipo={propiedad.tipo} canthabitaciones={propiedad.canthabitaciones} servicios={propiedad.servicios} btnbaja={"Alta"} monto={propiedad.monto}/>
{/each}
</tbody>
</table>
</div>
{#if fallo}
<div class="container alert alert-danger">Fallo al intentar Obtener la lista de propiedades</div>
{/if}

View File

@@ -0,0 +1,7 @@
<script lang="ts">
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
</script>
<NavBarAutocompletable/>

View File

@@ -1,91 +1,141 @@
<script lang="ts">
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
type Propiedad = {
ubicacion: string,
canthabitaciones: number,
piso: number,
letra: string,
email: string,
idtipropiedad: number,
}
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import type { Propiedad } from "../types";
import { urlG } from "../stores/urlStore";
let propiedad: Propiedad = {
ubicacion: "",
canthabitaciones: 1,
piso: 0,
letra: "",
email: "",
email: localStorage.getItem("email") || "",
idtipropiedad: 1,
monto: 1,
};
const submitForm = () => {
console.log("Formulario enviado:", propiedad);
};
let token = sessionStorage.getItem("token");
let mostrarModal = $state(false);
let datosModal = $state("");
const submitForm = async (e: Event) => {
e.preventDefault();
mostrarModal = false;
try {
const response = await fetch(String($urlG)+"/api/propiedad", {
method: 'POST',
headers: {
'Auth': String(token),
'Content-Type': "application/json"
},
body: JSON.stringify(propiedad),
});
const json = await response.json();
datosModal = json.message;
mostrarModal =true;
} catch (e) {
console.error(e);
}
};
</script>
<NavBarAutocompletable/>
<div class="container mt-4">
<h2>Registrar Propiedad</h2>
<form on:submit|preventDefault={submitForm}>
<div class="form-floating mb-3">
<input
type="text"
id="ubicacion"
class="form-control"
bind:value={propiedad.ubicacion}
placeholder="Ubicación"
required
/>
<label for="ubicacion">Ubicación</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="canthabitaciones"
class="form-control"
bind:value={propiedad.canthabitaciones}
min="1"
placeholder="Cantidad de Habitaciones"
required
/>
<label for="canthabitaciones">Cantidad de Habitaciones</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="piso"
class="form-control"
bind:value={propiedad.piso}
min="0"
placeholder="Piso"
/>
<label for="piso">Piso</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
id="letra"
class="form-control"
bind:value={propiedad.letra}
maxlength="1"
placeholder="Letra"
/>
<label for="letra">Letra</label>
</div>
<div class="form-floating mb-3">
<select
id="idtipropiedad"
class="form-select"
bind:value={propiedad.idtipropiedad}
required
>
<option value="1">Casa</option>
<option value="2">Departamento</option>
<option value="3">Oficina</option>
</select>
<label for="idtipropiedad">Tipo de Propiedad</label>
</div>
<button type="submit" class="btn btn-primary">Enviar</button>
</form>
<NavBarAutocompletable />
<div class="container-fluid mt-4 row">
<div class="col-sm">
<BarraHorizontalConTexto text={"Formulario Alta propiedad"}/>
Este es un formulario con el objetivo de que usted pueda registrar las propiedades <b>suyas</b> que quiera hacer visibles a las busquedas de inquilinos.
<br><br>
<BarraHorizontalConTexto text={"Indicaciones"}/>
Para poder cargar la propiedad deberá especificar su ubicacion, la cantidad de habitaciones que posée, en caso de ser un edificio el piso, y letra, y que tipo de propiedad és (casa, departamento, oficina...).
</div>
<div class="col">
<h2>Registrar Propiedad</h2>
<form class="card card-body" onsubmit={submitForm}>
<div class="form-floating mb-3">
<input
type="text"
id="ubicacion"
class="form-control"
bind:value={propiedad.ubicacion}
placeholder="Ubicación"
required
/>
<label for="ubicacion">Ubicación</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="canthabitaciones"
class="form-control"
bind:value={propiedad.canthabitaciones}
min="1"
placeholder="Cantidad de Habitaciones"
required
/>
<label for="canthabitaciones">Cantidad de Habitaciones</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="piso"
class="form-control"
bind:value={propiedad.piso}
min="0"
placeholder="Piso"
/>
<label for="piso">Piso</label>
</div>
<div class="form-floating mb-3">
<input
type="number"
id="monto"
class="form-control"
bind:value={propiedad.monto}
min="1"
placeholder="1"
/>
<label for="monto">Monto</label>
</div>
<div class="form-floating mb-3">
<input
type="text"
id="letra"
class="form-control"
bind:value={propiedad.letra}
maxlength="1"
placeholder="Letra"
/>
<label for="letra">Letra</label>
</div>
<div class="form-floating mb-3">
<select
id="idtipropiedad"
class="form-select"
bind:value={propiedad.idtipropiedad}
required
>
<option value="1">Casa</option>
<option value="2">Piso</option>
<option value="3">Departamento</option>
<option value="4">Galpon</option>
<option value="5">LocalComercial</option>
<option value="6">Oficina</option>
</select>
<label for="idtipropiedad">Tipo de Propiedad</label>
</div>
<button type="submit" class="btn btn-primary">Enviar</button>
</form>
</div>
</div>
{#if mostrarModal == true}
<ModalEstatico payload={datosModal} />
{/if}

View File

@@ -7,7 +7,7 @@ import NavBarAutocompletable from "../../Componentes/NavBarAutocompletable.svelt
<NavBarAutocompletable/>
<div class="container mt-5">
<div class="text-center mb-4">
<h1>Perfil del Administrador</h1>
<h1>Menu del Administrador</h1>
<p>Gestiona las cuentas de usuarios, propiedades y permisos desde aquí.</p>
</div>
<ListaAcciones/>

View File

@@ -1,5 +0,0 @@
<script lang="ts">
import NavBarAutocompletable from "../../Componentes/NavBarAutocompletable.svelte";
</script>
<NavBarAutocompletable/>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import ListaAcciones from "../../Componentes/ListaAcciones.svelte";
import NavBarAutocompletable from "../../Componentes/NavBarAutocompletable.svelte";
</script>
<NavBarAutocompletable/>
<div class="container mt-5">
<div class="text-center mb-4">
<h1>Menu Informes</h1>
<p>Visualice estadisticas e informes aqui.</p>
</div>
<ListaAcciones/>
</div>

View File

@@ -7,7 +7,7 @@ import NavBarAutocompletable from "../../Componentes/NavBarAutocompletable.svelt
<div class="container mt-5">
<div class="text-center mb-4">
<h1>Perfil del Inquilino</h1>
<h1>Menu del Inquilino</h1>
<p>Gestiona tus Pagos y Busca Propiedades desde aquí.</p>
</div>
<ListaAcciones/>

View File

@@ -6,7 +6,7 @@
<NavBarAutocompletable/>
<div class="container mt-5">
<div class="text-center mb-4">
<h1>Perfil del Propietario</h1>
<h1>Menu del Propietario</h1>
<p>Gestiona tus propiedades y servicios desde aquí.</p>
</div>
<ListaAcciones/>

View File

@@ -1,14 +1,15 @@
<script lang="ts">
import FormPostInq from "../Componentes/FormPostCli.svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import { urlG } from "../stores/urlStore";
import TextBar from "../Componentes/BarraHorizontalConTexto.svelte";
</script>
<NavBarAutocompletable/>
<div class="container">
<div class="container-fluid">
<div class="row align-items-start">
<div class="col">
<div class="col-sm">
<br><br>
<TextBar text="Formulario Alta Inquilino" />
Este es un formulario para crear una cuenta de Propietario.
@@ -29,7 +30,7 @@
</div>
<div class="col">
<br>
<FormPostInq url="http://127.0.0.1:5007/api/inquilino"/>
<FormPostInq url={String($urlG)+"/api/inquilino"}/>
</div>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import Login from "../Componentes/login.svelte"
import Login from "../Componentes/LoginPanel.svelte"
import Navbar from "../Componentes/NavBarLogin.svelte";
</script>

View File

@@ -1,6 +1,15 @@
<script>
import NavBarAuto from "../Componentes/NavBarAutocompletable.svelte";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import NavBarAuto from "../Componentes/NavBarAutocompletable.svelte";
</script>
<NavBarAuto/>
hol
<div class="container d-flex justify-content-center align-items-center h-50 text-center">
<div>
<br><br>
<BarraHorizontalConTexto text={"¡Bienvenido a AlquilaFacil!"} />
<p class="lead mt-3">Por favor, elige una de las opciones disponibles en la barra de navegación superior.</p>
<BarraHorizontalConTexto text={""}/>
</div>
</div>

View File

@@ -2,13 +2,14 @@
import FormPostInq from "../Componentes/FormPostCli.svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import TextBar from "../Componentes/BarraHorizontalConTexto.svelte";
import { urlG } from "../stores/urlStore";
</script>
<NavBarAutocompletable/>
<div class="container">
<div class="container-fluid">
<div class="row align-items-start">
<div class="col">
<div class="col-sm">
<br><br>
<TextBar text="Formulario Alta Propietario" />
Este es un formulario para crear una cuenta de Inquilino.
@@ -28,7 +29,7 @@
</div>
<div class="col">
<br>
<FormPostInq url="http://127.0.0.1:5007/api/propietario"/>
<FormPostInq url={String($urlG)+'/api/propietario'}/>
</div>
</div>
</div>

View File

@@ -0,0 +1,3 @@
import { readable, type Readable } from 'svelte/store';
export const urlG: Readable<string> = readable('http://localhost:5007');

37
Front/src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,37 @@
export type PropiedadDto = {
id: number,
ubicacion: string,
tipo: string,
piso: string | null,
letra: string | null,
canthabitaciones: number,
servicios: string,
monto: number
}
export type Permiso = {
id: number;
descripcion: string;
};
export type Cliente = {
dni: number,
nombre: string,
email: string,
habilitado: boolean
}
export type Grupo = {
id: number;
nombre: string;
idpermisos: Permiso[];
};
export type Propiedad = {
ubicacion: string,
canthabitaciones: number,
piso: number,
letra: string,
email: string,
idtipropiedad: number,
monto: number
};

View File

@@ -17,5 +17,4 @@
"moduleDetection": "force"
},
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -1,6 +1,4 @@
using System.Collections.ObjectModel;
using Entidades;
using Microsoft.EntityFrameworkCore;
using Entidades;
namespace Modelo;
@@ -18,7 +16,7 @@ public abstract class RepositorioBase<S>
context.SaveChanges();
context.Dispose();
ret = true;
} catch (DbUpdateException ex)
} catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}

View File

@@ -0,0 +1,15 @@
using Entidades;
using Microsoft.EntityFrameworkCore;
namespace Modelo;
public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
public IQueryable<Contrato>? ObtenerContratosPorEmailInquilino(string email){
var con = Context;
try{
var listcont = con.Contratos.Where(x=>x.DniinquilinoNavigation.Email == email);
return listcont;
} catch {
return null;
}
}
}

View File

@@ -1,6 +1,5 @@
#if DEBUG
using Entidades;
using Entidades.Admin;
using Microsoft.EntityFrameworkCore;
namespace Modelo;
@@ -23,6 +22,14 @@ public class RepositorioGrupos: RepositorioBase<RepositorioGrupos> {
var con = Context;
return con.Grupos.Where(x=>x.Nombre == grupo).SelectMany(x => x.Idpermisos);
}
}
#endif
public IQueryable<GrupoAdmin> ObtenerGruposPorDni(long Dni) {
var con = Context;
var grupos = con.Clientes.Where(x=>x.Dni == Dni).SelectMany(x=>x.Idgrupos)
.Select(x=> new GrupoAdmin{
Id = x.Id,
Descripcion = x.Nombre,
});
return grupos;
}
}

View File

@@ -1,19 +1,24 @@
using System;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.ConstrainedExecution;
using System.Data;
using Entidades;
using Entidades.Dto;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Modelo;
using MySql.Data.MySqlClient;
public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades>
{
public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
public IQueryable<PropiedadesDto> ListarPropiedades(){
FormattableString sqlq = $"""
SELECT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS TipoPropiedad FROM Propiedades p
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
@@ -36,27 +41,89 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades>
return prop;
}
public bool AñadirPropiedad(Propiedade? prop){
public bool AñadirPropiedad(Propiedade? prop) {
if (prop == null) return false;
var con = Context;
int count = con.Propiedades.Count()+1;
prop.Id = count;
prop.Idestado = 1;
con.Propiedades.Add(prop);
var con = Context;
if (string.IsNullOrEmpty(prop.Letra)) prop.Letra = "_";
var filasInsertadasParam = new MySqlParameter("@p_filas_insertadas", SqlDbType.Int)
{
Direction = ParameterDirection.Output
};
// Ejecutar el procedimiento almacenado
var row = con.Database.ExecuteSqlRaw(
$"""
CALL InsertarPropiedad(@p_ubicacion, @p_cant_habitaciones, @p_piso, @p_letra,
@p_dni_propietario, @p_id_tipo_propiedad, @p_monto, @p_filas_insertadas)
""",
new MySqlParameter("@p_ubicacion", prop.Ubicacion),
new MySqlParameter("@p_cant_habitaciones", prop.Canthabitaciones),
new MySqlParameter("@p_piso", prop.Piso),
new MySqlParameter("@p_letra", prop.Letra),
new MySqlParameter("@p_dni_propietario", prop.Dnipropietario),
new MySqlParameter("@p_id_tipo_propiedad", prop.Idtipropiedad),
new MySqlParameter("@p_monto",prop.Monto),
filasInsertadasParam
);
return (int)filasInsertadasParam.Value == 1? true: false;
}
public bool PatchPropiedad(Propiedade prop) {
var con = Context;
Propiedade? propi = con.Propiedades.Include(x=>x.IdServicios).FirstOrDefault(x=>x.Id == prop.Id);
if (propi == null) return false;
propi.Canthabitaciones = prop.Canthabitaciones;
propi.Idtipropiedad = prop.Idtipropiedad;
propi.Ubicacion = prop.Ubicacion;
propi.Piso = prop.Piso;
propi.Letra = prop.Letra;
propi.Monto = prop.Monto;
propi.IdServicios.Clear();
foreach(Servicio ser in prop.IdServicios) {
var servi = con.Servicios.FirstOrDefault(x=>x.Id == ser.Id);
if (servi == null) return false;
propi.IdServicios.Add(servi);
}
return Guardar(con);
}
public IQueryable<PropiedadesDto> ObtenerPropiedadesPorEmail(string email) {
FormattableString sqlq = $"""
SELECT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion as TipoPropiedad From Propiedades p
SELECT p.id, p.ubicacion as Ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion as Tipo, GROUP_CONCAT(IFNULL(s.descripcion, '') SEPARATOR ', ') AS Servicios, p.monto as Monto
FROM Propiedades p
JOIN Clientes c ON c.dni = p.dnipropietario
JOIN TipoPropiedad tp ON tp.id = p.idtipropiedad
WHERE c.email = {email}
LEFT JOIN Servicio_Propiedad ps ON ps.idPropiedad = p.id
LEFT JOIN Servicios s ON s.Id = ps.idServicio
WHERE c.email = {email} AND p.idestado = 1
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public IQueryable<PropiedadesDto> ObtenerPropiedadesDeBajaPorEmail(string email) {
FormattableString sqlq = $"""
SELECT p.id, p.ubicacion as Ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion as Tipo, GROUP_CONCAT(IFNULL(s.descripcion, '') SEPARATOR ', ') AS Servicios, p.monto as Monto
FROM Propiedades p
JOIN Clientes c ON c.dni = p.dnipropietario
JOIN TipoPropiedad tp ON tp.id = p.idtipropiedad
LEFT JOIN Servicio_Propiedad ps ON ps.idPropiedad = p.id
LEFT JOIN Servicios s ON s.Id = ps.idServicio
WHERE c.email = {email} AND p.idestado = 3
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
@@ -75,11 +142,19 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades>
return Guardar(con);
}
public bool BajaPropiedad(int id) {
public bool BajaPropiedad(int id, Cliente? cli) {
if (cli == null) return false;
var con = Context;
Propiedade? prop = con.Propiedades.Find(id);
Propiedade? prop = con.Propiedades.FirstOrDefault(x=>x.Id == id);
if (prop == null) return false;
prop.Idestado = 3;
if (prop.Dnipropietario != cli.Dni) return false;
if(prop.Idestado == 1){
prop.Idestado = 3;
}else{
prop.Idestado = 1;
}
return Guardar(con);
@@ -102,5 +177,410 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades>
}
return Guardar(con);
}
public IQueryable<PropiedadesDto> ObtenerPropiedesPorHabitaciones_Tipo_Servicios(int habitaciones, int tipo, string servicios) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {habitaciones} AND p.idtipropiedad = {tipo}
AND EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public IQueryable<PropiedadesDto> ObtenerPropiedesPorHabitaciones_Tipo(int cantidadHabitaciones, int tipoPropiedad) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {cantidadHabitaciones} AND p.idtipropiedad = {tipoPropiedad}
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public IQueryable<PropiedadesDto>? ObtenerPropiedesPorServicios(string servicios) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public IQueryable<PropiedadesDto>? ObtenerPropiedesPorHabitaciones(int cantidadHabitaciones) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {cantidadHabitaciones}
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public IQueryable<PropiedadesDto>? ObtenerPropiedesPorTipo(int tipoPropiedad) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.idtipropiedad = {tipoPropiedad}
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public IQueryable<PropiedadesDto>? ObtenerPropiedesPorHabitaciones_Servicios(int cantidadHabitaciones, string servicios) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {cantidadHabitaciones}
AND EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret; }
public IQueryable<PropiedadesDto>? ObtenerPropiedesPorTipo_Servicios(int tipoPropiedad, string servicios) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.idtipropiedad = {tipoPropiedad}
AND EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
public bool BajaPropiedades(string email) {
var con = Context;
try {
IQueryable<Propiedade> listprop = con.Propiedades.Where(x=>x.DnipropietarioNavigation.Email == email);
foreach (var item in listprop) {
item.Idestado = 3;
}
} catch {
return false;
}
return Guardar(con);
}
public IQueryable<PropiedadesDto> ListarPropiedadesPorPagina(int pag) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Context.Database.SqlQuery<PropiedadesDto>(sqlq);
return ret;
}
///////////////ADMIN
public IQueryable<PropiedadesAdmin> ListarPropiedadesPorPaginaAdmin(int pag) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorHabitacionesPaginado(int cantidadHabitaciones, int pag) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {cantidadHabitaciones}
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorTipoPaginado(int tipoPropiedad, int pag) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.idtipropiedad = {tipoPropiedad}
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorHabitaciones_TipoPaginado(int cantidadHabitaciones, int tipoPropiedad, int pag) {
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {cantidadHabitaciones} AND p.idtipropiedad = {tipoPropiedad}
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorServiciosPaginado(string servicios, int pag) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorHabitaciones_Servicios_Paginado(int cantidadHabitaciones, string servicios, int pag) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {cantidadHabitaciones}
AND EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorTipo_Servicios_Paginado(int tipoPropiedad, string servicios, int pag) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.idtipropiedad = {tipoPropiedad}
AND EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public IQueryable<PropiedadesAdmin> ObtenerPropiedesPorHabitaciones_Tipo_Servicios_Paginado(int habitaciones, int tipo, string servicios, int pag) {
string serviciosEscapados = string.Join(",", servicios.Split(',').Select(s => s.Trim()));
FormattableString sqlq = $"""
SELECT DISTINCT p.id, p.ubicacion, p.canthabitaciones, p.piso, p.letra, tp.descripcion AS Tipo,
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
JOIN Servicio_Propiedad sp on p.id =sp.idPropiedad
JOIN Servicios s on sp.idServicio =s.id
WHERE p.canthabitaciones = {habitaciones} AND p.idtipropiedad = {tipo}
AND EXISTS (
SELECT 1
FROM Servicio_Propiedad sp2
JOIN Servicios s2 ON sp2.idServicio = s2.id
WHERE sp2.idPropiedad = p.id
AND FIND_IN_SET(s2.descripcion, {serviciosEscapados})
)
GROUP BY p.id
LIMIT 10 OFFSET {pag*10}
""";
var ret = Singleton.Context.Database.SqlQuery<PropiedadesAdmin>(sqlq);
return ret;
}
public int CuantasPaginas(int estado = 0) {
var con = Context;
double inter;
int ret;
if (estado == 0){
inter = con.Propiedades.Count()/10.0;
} else {
inter = con.Propiedades.Where(x=>x.Idestado == estado).Count();
}
if (inter == 0.00) return 0;
ret = (int)Math.Ceiling(inter);
return ret;
}
public int CuantasPaginasBusqueda(int habitaciones, string servicios, int tipoPropiedad, int estado) {
int registrosPorPagina = 10;
var query = Context.Propiedades
.Include(p => p.IdestadoNavigation)
.Include(p => p.IdtipropiedadNavigation)
.Include(p => p.IdServicios)
.AsQueryable();
if (habitaciones > 0) {
query = query.Where(p => p.Canthabitaciones == habitaciones);
}
if (estado > 0){
query = query.Where(x=>x.Idestado == estado);
}
if (tipoPropiedad > 0) {
query = query.Where(p => p.Idtipropiedad == tipoPropiedad);
}
if (!string.IsNullOrWhiteSpace(servicios)) {
var listaServicios = servicios.Split(',').Select(s => s.Trim()).ToList();
query = query.Where(p =>
p.IdServicios.Any(sp =>
listaServicios.Contains(sp.Descripcion)));
}
int totalRegistros = query.Distinct().Count();
return (int)Math.Ceiling((double)totalRegistros / registrosPorPagina);
}
}

View File

@@ -24,15 +24,8 @@ public class RepositorioPropietario: RepositorioBase<RepositorioPropietario> {
}
public Cliente? ObtenerPropietarioPorEmail(string email){
FormattableString sqlq = $"""
SELECT * FROM Clientes c
JOIN cliente_Grupos cg ON cg.idgrupo = 1
WHERE c.email = {email}
LIMIT 1
""";
Cliente? cli = Context.Database.SqlQuery<Cliente?>(sqlq).First();
var con = Context;
Cliente? cli = con.Clientes.FirstOrDefault(x=>x.Email == email);
if (cli == null|| cli.Dni == 0) return null;
if (cli.Dni == 0 || cli == null) return null;
return cli;

View File

@@ -8,4 +8,9 @@ public class RepositorioServicios: RepositorioBase<RepositorioServicios> {
.SelectMany(x => x.IdServicios)
.Select(x=>x.Id);
}
public List<Servicio> ObtenerServiciosPorDescripcion(List<string> servs){
var servicios = Context.Servicios.Where(x=> servs.Contains(x.Descripcion)).ToList();
return servicios;
}
}

View File

@@ -10,45 +10,45 @@ public class RepositorioUsuarios: RepositorioBase<RepositorioUsuarios> {
public bool AltaInquilino(Cliente cli) {
var con = Context;
Grupo? grupo;
//check por si la cuenta ya existe (puede ser propietario)
Cliente? cli2 = con.Clientes.Find(cli.Dni);
Cliente? cli2 = con.Clientes.FirstOrDefault(x=>x.Email == cli.Email);
if (cli2 != null) {
cli = cli2;
grupo = con.Grupos.Find(2);
if (grupo == null || grupo.Id == 0) return false;
cli2.Idgrupos.Add(grupo);
return Guardar(con);
}
var grupo = con.Grupos.Find(2);
grupo = con.Grupos.Find(2);
if (grupo == null || grupo.Id == 0) return false;
con.Clientes.Add(cli);
Guardar(con);
con = Context;
cli = con.Clientes.Find(cli.Dni) ?? new();
if (cli.Dni == 0) return false;
cli.Idgrupos.Add(grupo);
return Guardar(con);
}
public bool AltaPropietario(Cliente cli) {
var con = Context;
Grupo? grupo;
//check por si la cuenta ya existe (puede ser propietario)
Cliente? cli2 = con.Clientes.Find(cli.Dni);
if (cli2 != null) {
cli = cli2;
grupo = con.Grupos.Find(1);
if (grupo == null || grupo.Id == 0) return false;
cli2.Idgrupos.Add(grupo);
return Guardar(con);
}
var grupo = con.Grupos.Find(1);
grupo = con.Grupos.Find(1);
if (grupo == null || grupo.Id == 0) return false;
con.Clientes.Add(cli);
Guardar(con);
con = Context;
cli = con.Clientes.Find(cli.Dni) ?? new();
if (cli.Dni == 0) return false;
cli.Idgrupos.Add(grupo);
@@ -119,4 +119,62 @@ public class RepositorioUsuarios: RepositorioBase<RepositorioUsuarios> {
return ret;
}
public IEnumerable<Entidades.Admin.UsuarioAdmin> GetClientes(){
var con = Context;
var list = con.Clientes.ToList().Select(x => new Entidades.Admin.UsuarioAdmin {
Dni = x.Dni,
Email = x.Email,
Nombre = x.Nombre+" "+x.Apellido,
Habilitado = x.Habilitado});
return list;
}
public bool AñadirClienteAGrupo(string email, string grupo) {
var con = Context;
var cli = con.Clientes.Include(x => x.Idgrupos).FirstOrDefault(x => x.Email == email);
var gru = con.Grupos.FirstOrDefault(x => x.Nombre == grupo);
if (cli == null || gru == null) {
return false;
}
cli.Idgrupos.Add(gru);
return Guardar(con);
}
public bool EliminarClienteAGrupo(string email, string grupo) {
var con = Context;
var cli = con.Clientes.Include(x => x.Idgrupos).FirstOrDefault(x => x.Email == email);
var gru = con.Grupos.FirstOrDefault(x => x.Nombre == grupo);
if (cli == null || gru == null) {
return false;
}
cli.Idgrupos.Remove(gru);
return Guardar(con);
}
public bool BajaCliente(long dni) {
var con = Context;
Cliente? cli = con.Clientes.Include(x=>x.Idgrupos).FirstOrDefault(x=>x.Dni == dni);
if (cli == null) return false;
if (cli.Habilitado == 0) {
cli.Habilitado = 1;
} else {
cli.Habilitado = 0;
}
return Guardar(con);
}
public Cliente? ObtenerClientePorDni(long dni) {
var con = Context;
Cliente? cli = con.Clientes.FirstOrDefault(x=>x.Dni == dni);
return cli;
}
}

View File

@@ -1,2 +1,2 @@
run:
dotnet run --project Aspnet/AlquilaFacil.csproj
dotnet watch run --project Aspnet/AlquilaFacil.csproj