implementado hasta el ultimo paso antes de hacer la tercera notificacion

This commit is contained in:
2025-01-08 02:53:31 -03:00
parent 9993e427e0
commit cf07c51eb1
18 changed files with 482 additions and 43 deletions

View File

@@ -0,0 +1,35 @@
using Entidades;
namespace AlquilaFacil.Builder;
public class GaranteBuilder : Builder<Garante> {
public GaranteBuilder SetNombre(string Nombre) {
data.Nombre = Nombre;
return this;
}
public GaranteBuilder SetApellido(string Apellido) {
data.Apellido = Apellido;
return this;
}
public GaranteBuilder SetDni(long Dni) {
data.Dni = Dni;
return this;
}
public GaranteBuilder SetDomicilio(string Domicilio) {
data.Domicilio = Domicilio;
return this;
}
public GaranteBuilder SetCelular(string Celular) {
data.Celular = Celular;
return this;
}
public GaranteBuilder SetDomicilioLaboral(string Domiciliolaboral) {
data.Domiciliolaboral = Domiciliolaboral;
return this;
}
}

View File

@@ -0,0 +1,45 @@
namespace AlquilaFacil.Builder;
using System;
using Entidades;
public class PrecontratoBuilder : Builder<Contrato> {
public PrecontratoBuilder SetHabilitado(){
data.Habilitado = 0;
return this;
}
public PrecontratoBuilder SetInquilino(long dniInq) {
data.Dniinquilino = dniInq;
return this;
}
public PrecontratoBuilder SetPropietario(long dniProp) {
data.Dnipropietario = dniProp;
return this;
}
public PrecontratoBuilder SetPropiedad(int idprop) {
data.Idpropiedad = idprop;
return this;
}
public PrecontratoBuilder SetCantidadGarantes(int cantgarante) {
data.Cantgarantemin = cantgarante;
return this;
}
public PrecontratoBuilder SetIndiceActializacionInicial() {
data.Indiceactualizacion = 0.000M;
return this;
}
public PrecontratoBuilder SetMesesHastaAumento(int meses) {
data.MesesHastaAumento = meses;
return this;
}
public PrecontratoBuilder SetFecha(DateTime fechaprimernotificacion){
data.Fechainicio = fechaprimernotificacion;
return this;
}
}

View File

@@ -1,15 +1,141 @@
using AlquilaFacil.Builder;
using Entidades;
using Entidades.Dto;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Modelo;
namespace AlquilaFacil.Controllers;
[ApiController]
public class ContratoController: ControllerBase {
[HttpGet("api/contratos")]
[HttpGet("api/contratos")] //WIP
public IActionResult ObtenerContratosPorUsuario([FromHeader(Name="Auth")]string Auth) {
return Ok();
}
[HttpPost("api/contratos/precontrato")]
public IActionResult IniciarPrecontrato([FromHeader(Name = "Auth")]string Auth, [FromBody] PrecontratoDto dto) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false) return Unauthorized();
string validacion2 = ValidarDtoPrecontrato(dto);
if (validacion2 != "") return BadRequest(new {message = validacion2});
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return BadRequest(new {message = "Tu token no corresponde a ningun cliente (volvete a logear)"});
if (cli.Email != dto.EmailPropietario) return BadRequest(new {message = "No Corresponde el email de propietario con el del token"});
Cliente? propi = RepositorioPropietario.Singleton.ObtenerPropietarioPorEmail(dto.EmailPropietario);
if (propi == null || propi.Dni == 0) return BadRequest(new {message = "No hay propietario por ese email"});
Cliente? inq = RepositorioInquilinos.Singleton.ObtenerInquilinoPorEmail(dto.EmailInquilino);
if (inq == null || inq.Dni == 0) return BadRequest(new {message = "No hay inquilinos por ese email"});
Propiedade? p = RepositorioPropiedades.Singleton.ObtenerPropiedadPorId(dto.IdPropiedad);
if (p == null || p.Id == 0) return BadRequest(new {message = "La id de propiedad no corresponde a una propiedad"});
var precontrato = new PrecontratoBuilder()
.SetHabilitado()
.SetPropietario(propi.Dni)
.SetInquilino(inq.Dni)
.SetCantidadGarantes(dto.CantidadGarantes)
.SetIndiceActializacionInicial()
.SetMesesHastaAumento(dto.MesesHastaAumento)
.SetPropiedad(p.Id)
.SetFecha(dto.fechaprimernotificacion)
.Build();
var notificacion = new NotificacioneBuilder()
.SetAccion("Carge Garantes")
.SetDniremitente(propi.Dni)
.SetDnicliente(inq.Dni)
.SetLeido(false)
.SetFecha(DateTime.Now)
.SetIdpropiedad(p.Id)
.SetMensaje($"El propietario {propi.Nombre} {propi.Apellido} te requiere que carges informacion de {dto.CantidadGarantes} Garantes")
.Build();
var ret = RepositorioContratos.Singleton.CargaPrecontrato(precontrato, notificacion);
return (ret)?
Ok(new {message = "Se Cargo el precontrato y envio una notificacion al inquilino"}):
BadRequest(new {message = "No se pudo cargar el precontrato"});
}
[HttpPut("api/contratos/addGarantes")]
public IActionResult AddGarantes([FromHeader(Name = "Auth")]string Auth, AltaGarantesDto dto) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) return Unauthorized();
var validacion2 = ValidarDtoAltaGarantes(dto);
if (validacion2 != "") return BadRequest(new {message = validacion2});
var validacion4 = RepositorioContratos.Singleton.CantidadGarantesEncontrato(dto.EmailInquilino, dto.Idpropiedad);
if (validacion4 <= 0 || dto.garantes.Count()!=validacion4) return BadRequest(new{message="Cantidad de garantes incorrecta"});
foreach (var i in dto.garantes) {
string validacion3 = ValidarDtoGarante(i);
if (validacion3 != "") return BadRequest( new { message = validacion3 });
}
List<Garante> gar = new();
foreach (var i in dto.garantes) {
Garante g = new GaranteBuilder()
.SetNombre(i.Nombre)
.SetApellido(i.Apellido)
.SetCelular(i.Celular)
.SetDomicilio(i.Domicilio)
.SetDni(i.Dni)
.SetDomicilioLaboral(i.Domiciliolaboral)
.Build();
gar.Add(g);
}
var ret = RepositorioContratos.Singleton.CargaGarantes(gar, dto.EmailInquilino, dto.Idpropiedad);
return ret ?
Ok(new {message = "Se Añadieron los Garantes"}):BadRequest(new { message = "Fallo la carga"});
}
private string ValidarDtoGarante(GaranteDto g){
string ret = "";
if (g == null) return "dto nulo";
if (g.Celular == "") ret += "No puede tener un numero de telefono vacio\n";
if (g.Nombre == "") ret += "No puede tener un nombre vacio\n";
if (g.Apellido == "") ret += "No puede tener un apellido vacio\n";
if (g.Domiciliolaboral == "") ret += "Tiene que especificar su domicilio laboral\n";
if (g.Domicilio == "") ret += "Tiene que especificar su domilio\n";
return ret;
}
private string ValidarDtoAltaGarantes(AltaGarantesDto dto){
string ret = "";
if (dto == null) return "dto nulo";
if (dto.garantes.Count()<=0) ret += "No se puede tener 0 o menos garantes\n";
if (dto.Idpropiedad<=0) ret += "la id de propiedad no puede ser igual o menor a 0\n";
if (dto.EmailInquilino == "") ret += "El email de inquilino no puede estar vacio\n";
return ret;
}
private string ValidarDtoPrecontrato( PrecontratoDto dto) {
string ret = "";
if (dto == null) return "dto nulo";
if (dto.CantidadGarantes<0) ret += "la cantidad de garantes necesarios no pueden ser menor a 0\n";
if (dto.EmailInquilino == "") ret += "el email del inquilino no puede ser nulo\n";
if (dto.EmailPropietario == "") ret += "el email del propietario no puede estar vacio\n";
if (dto.IdPropiedad <= 0) ret += "la id de propiedad no puede ser igual o menor a 0\n";
if (dto.MesesHastaAumento <= 0) ret += "No puede tener 0 o menos meses hasta el aumento\n";
return ret;
}
}

View File

@@ -15,19 +15,20 @@ public class NotificacionesController: ControllerBase {
var cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return BadRequest(new {message = "Fallo al intentar encontrar tu usuario (puede que te hayas logeado desde otro dispositivo?)"});
LinkedList<NotificacionDto> noti = new();
var notificaciones = cli.NotificacioneDniclienteNavigations.Where(x=>x.Leido == leido).ToList();
IQueryable<Notificacione> notificaciones = RepositorioNotificaciones.Singleton.ObtenerNotificacionesDeUsuario(cli.Dni)
.Where(x=>x.Leido == leido);
List<NotificacionDto> noti = new();
Parallel.ForEach(notificaciones, i => {
var dto = new NotificacionDtoBuilder()
.SetRemitente(i.DniremitenteNavigation.Nombre)
.SetRemitente(i.DniremitenteNavigation.Email)
.SetAccion(i.Accion)
.SetMensaje(i.Mensaje)
.SetFecha(i.Fecha)
.SetPropiedad(i.IdpropiedadNavigation.Ubicacion)
.Build();
.SetPropiedad(i.IdpropiedadNavigation.Id.ToString())
.Build();
noti.AddFirst(dto);
noti.Add(dto);
});
return Ok(noti);
}
@@ -53,7 +54,7 @@ public class NotificacionesController: ControllerBase {
[HttpPost("api/notificaciones/consultaAlquiler")]
public IActionResult ConsultaAlquiler([FromHeader(Name ="Auth")]string Auth, [FromBody] AltaNotificacionDto data) {
if (String.IsNullOrWhiteSpace(Auth)) return Unauthorized();
bool validacion1 = RepositorioUsuarios.Singleton.CheckToken(Auth, data.Remitente);
bool validacion1 = RepositorioUsuarios.Singleton.CheckToken(data.Remitente, Auth);
if (validacion1 == false) return BadRequest(new {message = "el token no corresponde a su usuario"});
if (data.Accion == "") return BadRequest(new{message = "El campo Accion esta vacio"});

View File

@@ -0,0 +1,9 @@
namespace Entidades.Dto;
public class AltaGarantesDto {
public string EmailInquilino { get; set; } = "";
public int Idpropiedad {get; set;}
public DateTime fecha { get; set;}
public List<GaranteDto> garantes{ get; set; } = new();
}

View File

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

View File

@@ -0,0 +1,16 @@
namespace Entidades.Dto;
public class GaranteDto {
public long Dni { get; set; }
public string Nombre { get; set; } = null!;
public string Apellido { get; set; } = null!;
public string Domicilio { get; set; } = null!;
public string Celular { get; set; } = null!;
public string Domiciliolaboral { get; set; } = null!;
}

View File

@@ -0,0 +1,10 @@
namespace Entidades.Dto;
public class PrecontratoDto {
public string EmailInquilino { get; set; } = "";
public string EmailPropietario { get; set; } = "";
public int IdPropiedad { get; set; }
public int CantidadGarantes { get; set; }
public int MesesHastaAumento { get; set; }
public bool TieneOpcionVenta { get; set; }
public DateTime fechaprimernotificacion { get; set; }
}

View File

@@ -2,15 +2,19 @@
import type { PropiedadDto } from "../types";
import ModalConfirm from "./ModalConfirm.svelte";
import {urlG} from "../stores/urlStore";
import ModalEstatico from "./ModalEstatico.svelte";
let { prop }: { prop: PropiedadDto } = $props();
let show: boolean = $state(false);
let token = sessionStorage.getItem("token");
let remitente = localStorage.getItem("email");
const accion = "Nuevo Alquiler";
let modaldata = $state("");
let mensaje = `Alquiler: ${prop.ubicacion} a ${remitente}`;
const message: string = "Queres consultar con el propietario por el alquiler? (esto le envia una notificacion y email al propietario)";
const accion = "Consulta Nuevo Alquiler";
function Consultar() {
show = true;
@@ -19,14 +23,18 @@
async function onConfirm() {
const propiedad = prop.id;
try {
const responce = await fetch($urlG+"/api/notificaciones", {
const responce = await fetch($urlG+"/api/notificaciones/consultaAlquiler", {
method: "POST",
headers: {
"Auth": String(token)
"Auth": String(token),
"Content-Type": "application/json"
},
body : JSON.stringify({remitente, accion, propiedad})
body : JSON.stringify({remitente, accion, mensaje, propiedad})
});
if (responce.ok){
let data = await responce.json();
}
} catch {
}
@@ -40,6 +48,11 @@
</script>
{#if modaldata}
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")} />
{/if}
<ModalConfirm {show} {message} title="Consulta" {onConfirm} {onCancel}/>
<div class="card text-center border shadow-sm">
<div class="card-header bg-primary text-white">

View File

@@ -3,26 +3,113 @@
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import type { MensajeDto } from "../types";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import { urlG } from "../stores/urlStore";
import ModalConfirm from "../Componentes/ModalConfirm.svelte";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import { text } from "@sveltejs/kit";
const token = sessionStorage.getItem("token");
let mensajes: MensajeDto[] = $state([]);
let showspinner:boolean =$state(false);
let mostrarleidos: boolean = $state(false);
let modaldata:string =$state("");
let Selmens: MensajeDto;
let show:boolean = $state(false);
let title:string = $state("");
let message:string = $state("");
onMount(async () => {
showspinner = true;
SinLeer();
})
async function SinLeer() {
mostrarleidos = false;
showspinner = true;
try{
const responce = await fetch($urlG+"/api/notificaciones?leido="+mostrarleidos, {
method: "GET",
headers: {
"Auth": String(token)
}
});
if (responce.ok) {
let data = await responce.json();
mensajes = data;
showspinner = false;
return;
}
let errordata = await responce.json();
modaldata = errordata.message;
} catch{
modaldata = "no se pudo obtener notificaciones";
}
}
async function Leidos() {
mostrarleidos = true;
showspinner = true;
try {
const responce = await fetch($urlG+"/api/notificaciones?leido="+true, {
method: "GET",
headers: {
"Auth": String(token)
}
});
if (responce.ok) {
let data = await responce.json();
mensajes = data;
showspinner = false;
return;
}
let errordata = await responce.json();
modaldata = errordata.message;
} catch {
modaldata = "no se pudo obtener notificaciones";
}
}
function setModalConfirm(men:MensajeDto){
Selmens = men;
message = "${}"
show = true;
}
async function marcarleido( fecha: Date, email: string, men:MensajeDto ) {
show = true;
try {
const responce = await fetch($urlG+"/api/notificaciones", {
method: "PUT",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({fecha, email}),
});
if (responce.ok) {
let data = await responce.json();
modaldata = data.message;
mensajes = mensajes.filter(m => m !== men);
return;
}
let dataerror = await responce.json();
modaldata = dataerror.message;
} catch {
modaldata = "no se pudo marcar como leido";
}
}
function abrirModal(mensaje: MensajeDto) {
Selmens = mensaje;
title = "Confirmar proceso de alquiler";
message ="Aceptar este proceso eliminará la propiedad del menú de búsqueda. Se informará al inquilino que debe pasar los datos de sus garantías. ¿Desea continuar?";
show = true;
}
</script>
<NavBarAutocompletable/>
@@ -31,8 +118,17 @@
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")} />
{/if}
<ModalConfirm
{show}
{title}
{message}
onCancel={() => (show = false)}
onConfirm={()=>1+1}
/>
<div class="container">
<br>
<BarraHorizontalConTexto text="Notificaciones"/>
<br>
<div class="btn-group">
<button class="btn btn-primary" class:active={mostrarleidos==false} onclick={SinLeer} >Sin Leer</button>
@@ -47,7 +143,7 @@
</div>
{:else}
<table class="table table-responsive table-striped table-hover">
<table class="table container-fluid table-responsive table-striped table-hover">
<thead>
<tr>
<th>Remitente</th>
@@ -55,19 +151,41 @@
<th>Mensaje</th>
<th>Fecha</th>
<th>Propiedad</th>
{#if mostrarleidos == false}
<th></th>
{/if}
</tr>
</thead>
<tbody>
{#each mensajes as men }
{#if mensajes.length <= 0}
<tr>
<td>men.remitente</td>
<td>men.accion</td>
<td>men.mensaje</td>
<td>men.fecha</td>
<td>men.propiedad</td>
<td colspan={mostrarleidos == false ? 6 : 5}>
<p>No hay Mensajes para leer</p>
</td>
</tr>
{:else}
{#each mensajes as men}
<tr>
<td>{men.remitente}</td>
<td>{men.accion}</td>
<td>{men.mensaje}</td>
<td>{men.fecha}</td>
<td>{men.propiedad}</td>
{#if mostrarleidos == false}
<td>
<button
class="btn btn-outline-primary btn-sm"
onclick={() => abrirModal(men)}
>
Expandir
</button>
</td>
{/if}
</tr>
{/each}
{/if}
</tbody>
</table>
{/if}

View File

@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
namespace Modelo;
public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
public IQueryable<Contrato>? ObtenerContratosPorEmailInquilino(string email){
public IQueryable<Contrato>? ObtenerContratosPorEmailInquilino(string email) {
var con = Context;
try{
var listcont = con.Contratos.Where(x=>x.DniinquilinoNavigation.Email == email);
@@ -12,4 +12,47 @@ public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
return null;
}
}
public bool CargaPrecontrato(Contrato? c = null, Notificacione? n = null) {
if (c == null || c.Habilitado == 1) return false;
if (n == null) return false;
var con = Context;
var prop = con.Propiedades.FirstOrDefault(x=>x.Id==c.Idpropiedad);
if (prop == null) return false;
prop.Idestado = 2;
c.Id = con.Contratos.Max(x=>x.Id)+1;
c.Monto = prop.Monto;
con.Contratos.Add(c);
con.Notificaciones.Add(n);
return Guardar(con);
}
public bool CargaGarantes(List<Garante> gar, string emailInquilino, int idpropiedad) {
var con = Context;
Contrato? contr = con.Contratos.Include(x=>x.DniinquilinoNavigation)
.FirstOrDefault(x=>x.Idpropiedad == idpropiedad &&
x.DniinquilinoNavigation.Email == emailInquilino &&
x.Habilitado == 0);
if (contr == null) return false;
foreach (var i in gar) {
i.Id = con.Garantes.Max(x=>x.Id)+1;
contr.Idgarantes.Add(i);
}
return Guardar(con);
}
public int CantidadGarantesEncontrato(string emailInquilino, int idpropiedad) {
var con = Context;
Contrato? contr = con.Contratos.Include(x=>x.DniinquilinoNavigation)
.FirstOrDefault(x=>x.Idpropiedad == idpropiedad &&
x.DniinquilinoNavigation.Email == emailInquilino &&
x.Habilitado == 0);
if (contr == null) return 0;
return contr.Cantgarantemin;
}
}

View File

@@ -32,4 +32,18 @@ public class RepositorioGrupos: RepositorioBase<RepositorioGrupos> {
});
return grupos;
}
public bool CheckGrupos(string token, string grupo){
var con = Context;
Cliente? cli = con.Clientes.Include(x=>x.Idgrupos).FirstOrDefault(x=>x.Token == token);
if (cli == null) return false;
Grupo? gru = con.Grupos.FirstOrDefault(x=>x.Nombre == grupo);
if (gru == null) return false;
if (cli.Idgrupos.Contains(gru)) return true;
return false;
}
}

View File

@@ -1,3 +1,4 @@
using Entidades;
using Entidades.Dto;
using Microsoft.EntityFrameworkCore;
@@ -15,5 +16,15 @@ public class RepositorioInquilinos: RepositorioBase<RepositorioInquilinos> {
return Context.Database.SqlQuery<InquilinoDto>(sqlq);
}
public Cliente? ObtenerInquilinoPorEmail(string Email){
var con = Context;
Cliente? cli = con.Clientes.Include(x=>x.Idgrupos).FirstOrDefault(x=>x.Email == Email);
if (cli == null || cli.Dni == 0) return null;
Grupo? gru = cli.Idgrupos.FirstOrDefault(x=>x.Id == 2);
if (gru == null) return null;
return cli;
}
}

View File

@@ -3,6 +3,7 @@ using System.Text;
using Entidades.Dto;
using Entidades;
using Microsoft.EntityFrameworkCore;
using System.Collections.Concurrent;
namespace Modelo;
@@ -20,7 +21,18 @@ public class RepositorioNotificaciones : RepositorioBase<RepositorioNotificacion
public bool AltaNotificacion(Notificacione n) {
var con = Context;
con.Notificaciones.Add(n);
return Guardar(con);
}
public IQueryable<Notificacione> ObtenerNotificacionesDeUsuario(long dni) {
var con = Context;
var notis = con.Notificaciones
.Include(x=>x.IdpropiedadNavigation)
.Include(x=>x.DniremitenteNavigation)
.Where(x => x.Dnicliente == dni);
return notis;
}
}

View File

@@ -34,6 +34,7 @@ public class RepositorioPermisos: RepositorioBase<RepositorioPermisos> {
/////////////////////////////////////////////////////////////////
//Esto esta comentado porque antes pasaba el string del path de la url, es una mala idea a muchos niveles
// abajo un comentario viejo mio
/////////////////////////////////////////////////////////////////
//me inspiré y hice un regex pero si eliminaba los primeros 8(?) caracteres del string era lo mismo
//Match match = Regex.Match(path, @"^/accion/(\d+)$");

View File

@@ -27,14 +27,9 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
}
public Propiedade? ObtenerPropiedadPorId(int Id) {
var con = Context;
Propiedade? prop = con.Propiedades.Include(x=>x.DnipropietarioNavigation).FirstOrDefault(x=>x.Id == Id);
FormattableString sqlq = $"""
SELECT * FROM Propiedades p
WHERE p.id = {Id}
LIMIT 1
""";
Propiedade? prop = Context.Database.SqlQuery<Propiedade>(sqlq).First();
if (prop == null || prop.Id == 0) {
return null;
}

View File

@@ -25,9 +25,10 @@ public class RepositorioPropietario: RepositorioBase<RepositorioPropietario> {
public Cliente? ObtenerPropietarioPorEmail(string email){
var con = Context;
Cliente? cli = con.Clientes.FirstOrDefault(x=>x.Email == email);
Cliente? cli = con.Clientes.Include(x=>x.Idgrupos).FirstOrDefault(x=>x.Email == email);
if (cli == null|| cli.Dni == 0) return null;
if (cli.Dni == 0 || cli == null) return null;
var grupo = cli.Idgrupos.FirstOrDefault(x=>x.Id == 1);
if (grupo == null) return null;
return cli;
}
}

View File

@@ -88,10 +88,6 @@ public class RepositorioUsuarios: RepositorioBase<RepositorioUsuarios> {
var usu = Context.Clientes.FirstOrDefault(x => x.Email == email);
if (usu == null) return false;
#if DEBUG
//Console.WriteLine(token + "\n" +usu.Token);
#endif
return usu.Token == token;
}