Alquileres #47

Merged
fede merged 24 commits from Alquileres into dev 2025-01-24 04:14:19 -03:00
74 changed files with 3944 additions and 87 deletions

4
.editorconfig Normal file
View File

@@ -0,0 +1,4 @@
[*.cs]
# CS8602: Dereference of a possibly null reference.
dotnet_diagnostic.CS8602.severity = suggestion

2
.gitignore vendored
View File

@@ -7,3 +7,5 @@
/Entidades/obj/
/Aspnet/obj/
/Modelo/bin/
Aspnet/bin/
node_modules/

View File

@@ -10,6 +10,7 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
<PackageReference Include="minio" Version="6.0.3" />
<PackageReference Include="QuestPDF" Version="2024.12.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
</ItemGroup>

View File

@@ -0,0 +1,35 @@
using Entidades.Dto;
namespace AlquilaFacil.Builder;
public class CanonDtoBuilder : Builder<CanonDto>{
public CanonDtoBuilder SetId(long id) {
data.Id = id;
return this;
}
public CanonDtoBuilder SetMesNum(int mesNum) {
data.MesNum = mesNum;
return this;
}
public CanonDtoBuilder SetMes(DateTime d){
data.Mes = d;
return this;
}
public CanonDtoBuilder SetMonto(Decimal monto) {
data.Monto = monto;
return this;
}
public CanonDtoBuilder SetDivisa(string divisa) {
data.Divisa = divisa;
return this;
}
public CanonDtoBuilder SetPago(bool p) {
data.Pago = p;
return this;
}
}

View File

@@ -0,0 +1,50 @@
using Entidades.Dto;
namespace AlquilaFacil.Builder;
public class ContratoDtoBuilder: Builder<ContratoDto> {
public ContratoDtoBuilder SetId(long id ){
data.id = id;
return this;
}
public ContratoDtoBuilder SetUbicacion(string ub){
data.Ubicacion = ub;
return this;
}
public ContratoDtoBuilder SetTipo(string tipo){
data.TipoPropiedad = tipo;
return this;
}
public ContratoDtoBuilder SetFechaInicio(DateTime fec) {
data.Fechainicio = fec;
return this;
}
public ContratoDtoBuilder SetInquilino(string inquilino){
data.Inquilino = inquilino;
return this;
}
public ContratoDtoBuilder SetPropietario(string propietario){
data.Propietario = propietario;
return this;
}
public ContratoDtoBuilder SetEstado(ulong habilitado, ulong cancelado) {
bool Habilitado = habilitado == 0?false:true;
bool Cancelado = cancelado == 0?false:true;
if (Habilitado == true && Cancelado == false){
data.Estado = "Alquiler Iniciado";
} else if (Cancelado == true && Habilitado == false) {
data.Estado = "Nunca Empezo Esta Cancelado";
} else if (Habilitado == false && Cancelado ==false){
data.Estado = "Esta en Proceso";
} else if (Habilitado == true && Cancelado == true){
data.Estado = "Terminado";
}
return this;
}
}

View File

@@ -0,0 +1,75 @@
using Entidades.Dto;
namespace AlquilaFacil.Builder;
public class ContratoPropiedadDtoBuilder : Builder<ContratoPropiedadDto>{
public ContratoPropiedadDtoBuilder SetId(long id ){
data.id = id;
return this;
}
public ContratoPropiedadDtoBuilder SetUbicacion(string ub){
data.Ubicacion = ub;
return this;
}
public ContratoPropiedadDtoBuilder SetTipo(string tipo){
data.TipoPropiedad = tipo;
return this;
}
public ContratoPropiedadDtoBuilder SetFechaInicio(DateTime fec) {
data.Fechainicio = fec;
return this;
}
public ContratoPropiedadDtoBuilder SetInquilino(string inquilino){
data.Inquilino = inquilino;
return this;
}
public ContratoPropiedadDtoBuilder SetPropietario(string propietario){
data.Propietario = propietario;
return this;
}
public ContratoPropiedadDtoBuilder SetEstado(ulong habilitado, ulong cancelado) {
bool Habilitado = habilitado == 0?false:true;
bool Cancelado = cancelado == 0?false:true;
if (Habilitado == true && Cancelado == false){
data.Estado = "Alquiler Iniciado";
} else if (Cancelado == true && Habilitado == false) {
data.Estado = "Nunca Empezo Esta Cancelado";
} else if (Habilitado == false && Cancelado ==false){
data.Estado = "Esta en Proceso";
} else if (Habilitado == true && Cancelado == true){
data.Estado = "Terminado";
}
return this;
}
public ContratoPropiedadDtoBuilder SetHabitaciones(int habitaciones){
data.Habitaciones = habitaciones;
return this;
}
public ContratoPropiedadDtoBuilder SetPiso(int piso){
data.Piso = piso;
return this;
}
public ContratoPropiedadDtoBuilder SetLetra(string letra){
data.Letra = letra;
return this;
}
public ContratoPropiedadDtoBuilder SetMesesAumento(int mesesAumento){
data.MesesAumento = mesesAumento;
return this;
}
public ContratoPropiedadDtoBuilder SetMesesDuracion(int mesesDurationContrato) {
data.MesesDuracion = mesesDurationContrato;
return this;
}
}

View File

@@ -0,0 +1,34 @@
using Entidades.Dto;
namespace AlquilaFacil.Builder;
public class DefectoDtoBuilder: Builder<DefectoDto> {
public DefectoDtoBuilder SetId(long id) {
data.Id = id;
return this;
}
public DefectoDtoBuilder SetDesc(string Descripcion){
data.Descripcion = Descripcion;
return this;
}
public DefectoDtoBuilder SetCosto(Decimal Costo){
data.Costo = Costo;
return this;
}
public DefectoDtoBuilder SetEstado(string estado){
data.Estado = estado;
return this;
}
public DefectoDtoBuilder SetIdContrato(long id){
data.Idcontrato = id;
return this;
}
public DefectoDtoBuilder SetPagaInquilino(ulong pag){
data.Pagainquilino=pag==1?"Si":"No";
return this;
}
public DefectoDtoBuilder SetDivisa(string divisa){
data.Divisa = divisa;
return this;
}
}

View File

@@ -0,0 +1,17 @@
using Entidades.Informes;
namespace AlquilaFacil.Builder;
public class InformesAlquilerBuilder: Builder<InformesAlquiler>{
public InformesAlquilerBuilder SetId(long id){
data.Id = id;
return this;
}
public InformesAlquilerBuilder SetUbicacion(string Ubicacion){
data.Ubicacion = Ubicacion;
return this;
}
public InformesAlquilerBuilder SetDivisa(string Divisa){
data.Divisa = Divisa;
return this;
}
}

View File

@@ -42,4 +42,9 @@ public class PrecontratoBuilder : Builder<Contrato> {
data.Fechainicio = fechaprimernotificacion;
return this;
}
public PrecontratoBuilder SetMesesDuracion(int mesesDuracionContrato){
data.MesesDurationContrato = mesesDuracionContrato;
return this;
}
}

View File

@@ -2,6 +2,7 @@ using System.Net;
using System.Text.Json;
using AlquilaFacil.Builder;
using AlquilaFacil.Config;
using AlquilaFacil.Facade;
using Entidades;
using Entidades.Dto;
using Microsoft.AspNetCore.Mvc;
@@ -16,11 +17,293 @@ namespace AlquilaFacil.Controllers;
[ApiController]
public class ContratoController: ControllerBase {
[HttpGet("api/contratos")] //WIP
public IActionResult ObtenerContratosPorUsuario([FromHeader(Name="Auth")]string Auth) {
return Ok();
[HttpPost("api/contrato/GenerarRecibo")]
public ActionResult GenerarRecibo([FromHeader(Name="Auth")]string Auth, MarcarPagoDto dto, bool html= true) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false){
validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) {
return Unauthorized();
}
}
if (dto.Idcontrato <= 0) return BadRequest(new { message = "No puede tener un contrato con id 0 o menor"});
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(dto.Idcontrato);
if (cont == null) return BadRequest(new { message = "No hay un contrato por ese id"});
if (cont.DniinquilinoNavigation == null || cont.DnipropietarioNavigation == null || cont.IdpropiedadNavigation == null ||
cont.IdpropiedadNavigation.IdtipropiedadNavigation == null) return BadRequest(new { message = "comunicate con el admin esta mal cargado el contratod de alguina forma"});
Canon? can = RepositorioCanons.Singleton.ObtenerCanonContrato(dto.fecha, dto.Idcontrato);
if (can == null) return BadRequest(new { message = "no hay un canon para ese contrato con esa fecha"});
if (can.IdreciboNavigation == null) return BadRequest(new { message = "No hay un recibo para ese canon"});
var cdb = new ContratoDtoBuilder()
.SetInquilino($"{cont.DniinquilinoNavigation.Nombre} {cont.DniinquilinoNavigation.Apellido}")
.SetUbicacion(cont.IdpropiedadNavigation.Ubicacion)
.SetPropietario($"{cont.DnipropietarioNavigation.Nombre} {cont.DnipropietarioNavigation.Apellido}")
.SetId(cont.Id)
.SetTipo(cont.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion)
.SetFechaInicio(cont.Fechainicio)
.SetEstado(cont.Habilitado, cont.Cancelado)
.Build();
var dof = new DocumentoFacade();
MemoryStream? memstr = new();
if (html){
dof.GenerarHtml(cdb, can.IdreciboNavigation, memstr);
return File(memstr, "text/html", "Recibo.html");
} else {
dof.GenerarPdf (cdb, can.IdreciboNavigation, memstr);
return File(memstr, "application/pdf", "Recibo.pdf");
}
}
[HttpPost("api/contratos/marcarPago")]
public IActionResult marcarPago([FromHeader(Name="Auth")]string Auth, MarcarPagoDto dto) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false)return Unauthorized();
if (dto.Idcontrato<=0) return BadRequest(new { message = "No puede existir un contrato con id 0 o menor"});
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null)return Unauthorized();
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(dto.Idcontrato);
if (cont == null) return BadRequest(new { message = "No hay un contrato por esa id"});
if (cli.Dni != cont.Dnipropietario) return BadRequest(new {message = "No sos propietario o intenta volviendote a logear"});
Canon? c = RepositorioCanons.Singleton.ObtenerCanonContrato(dto.fecha, dto.Idcontrato);
if (c == null) return BadRequest(new { message = "no hay un canon por esa id"});
Recibo re = new Recibo{
Monto = c.Monto,
Fecha = c.Fecha,
};
bool ret = RepositorioCanons.Singleton.SetRecibo(c, re);
return ret ?
Ok(new { message = "Se guardo correctamente"}):BadRequest(new { message = "No se pudo guardar"});
}
[HttpPost("api/contratos/realizarPago")]
public IActionResult realizarPago([FromHeader(Name="Auth")]string Auth, MarcarPagoDto dto) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) return Unauthorized();
if (dto.Idcontrato<=0) return BadRequest(new { message = "No puede existir un contrato con id 0 o menor"});
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null)return Unauthorized();
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(dto.Idcontrato);
if (cont == null) return BadRequest(new { message = "No hay un contrato por esa id"});
if (cli.Dni != cont.Dniinquilino) return BadRequest(new {message = "No sos inquilino o intenta volviendote a logear"});
Canon? c = RepositorioCanons.Singleton.ObtenerCanonContrato(dto.fecha, dto.Idcontrato);
if (c == null) return BadRequest(new { message = "no hay un canon por esa id"});
Recibo re = new Recibo{
Monto = c.Monto,
Fecha = c.Fecha,
};
bool ret = RepositorioCanons.Singleton.SetRecibo(c, re);
return ret ?
Ok(new { message = "Se guardo correctamente"}):BadRequest(new { message = "No se pudo guardar"});
}
[HttpPost("api/contratos/crearcanons")]
public IActionResult crearCanons([FromHeader(Name="Auth")]string Auth, CrearCanonsDto dto){
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false)return Unauthorized();
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return Unauthorized();
if (dto.idcontrato <=0) return BadRequest(new { message ="estan mal cargados los datos"});
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(dto.idcontrato);
if (cont == null) return BadRequest(new { message = "no hay un contrato por esa id"});
if (cli.Dni != cont.Dnipropietario) return BadRequest(new {message = "No sos el propietario o intenta volviendote a logear"});
var ret = RepositorioCanons.Singleton.CrearCanons(dto.aumento, dto.idcontrato);
return ret ?
Ok(new { message = "Se crearon los canons correctamente"}):BadRequest(new { message = "No se pudo guardar"});
}
[HttpGet("api/contratos/canon")]
public ActionResult getCanons([FromHeader(Name="Auth")]string Auth, int id = 0) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false){
validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) {
return Unauthorized();
}
}
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if(cli == null) return Unauthorized();
var cont = RepositorioContratos.Singleton.ObtenerContratoPorId(id);
if (cont == null) return BadRequest(new { message = "No existe el contrato"});
if ( cont.Dnipropietario != cli.Dni && cont.Dniinquilino != cli.Dni) return Unauthorized();
var list = RepositorioCanons.Singleton.ObtenerCanonsPorContrato(id);
if (list == null) return BadRequest(new { message = "No hay contrato por esa id"});
string divisa ="";
if (cont.Iddivisa == 0) divisa = "AR$"; else if (cont.Iddivisa == 1) divisa = "US$";
List<CanonDto> d = new();
foreach (var i in list) {
var c = new CanonDtoBuilder()
.SetId(i.Id)
.SetPago(i.Idrecibo==null?false:true)
.SetDivisa(divisa==""?"Ugh esta mal cargado la divisa en el contrato":divisa)
.SetMes(i.Fecha)
.SetMesNum(int.Parse((i.Fecha.Month - cont.Fechainicio.Month).ToString()) + 1)
.SetMonto(i.Monto)
.Build();
d.Add(c);
}
return Ok(d);
}
[HttpGet("api/contratos/propietario")]
public IActionResult ObtenerContratosPorPropietario([FromHeader(Name="Auth")]string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false) return Unauthorized();
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli==null) return Unauthorized();
var list = RepositorioContratos.Singleton.ObtenerContratosDePropietario(cli.Dni);
List<ContratoDto> dtos = new();
foreach (var i in list) {
if (i.DniinquilinoNavigation == null || i.IdpropiedadNavigation == null
|| i.DnipropietarioNavigation == null) continue;
var cont = new ContratoDtoBuilder()
.SetInquilino($"{i.DniinquilinoNavigation.Nombre} {i.DniinquilinoNavigation.Apellido}")
.SetUbicacion(i.IdpropiedadNavigation.Ubicacion)
.SetId(i.Id)
.SetPropietario($"{i.DnipropietarioNavigation.Nombre} {i.DnipropietarioNavigation.Apellido}")
.SetTipo(i.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion)
.SetFechaInicio(i.Fechainicio)
.SetEstado(i.Habilitado, i.Cancelado)
.Build();
dtos.Add(cont);
}
return Ok(dtos);
}
[HttpGet("api/contrato/propietario")]
public IActionResult ObtenerContratoPorPropietarioPorId([FromHeader(Name="Auth")]string Auth, int id=0) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false) return Unauthorized();
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli==null) return Unauthorized();
if (id <= 0) return BadRequest(new { message = "No hay propiedades con id igual o menor a 0"});
var i = RepositorioContratos.Singleton.ObtenerContratoPorId(id);
if (i == null || i.DniinquilinoNavigation == null ||
i.IdpropiedadNavigation == null || i.DnipropietarioNavigation == null)return BadRequest(new { message = "Fallo la query"});
if (cli.Dni != i.Dnipropietario) return BadRequest(new { message = "No sos el propietario"});
var cont = new ContratoPropiedadDtoBuilder()
.SetInquilino($"{i.DniinquilinoNavigation.Nombre} {i.DniinquilinoNavigation.Apellido}")
.SetUbicacion(i.IdpropiedadNavigation.Ubicacion)
.SetId(i.Id)
.SetPropietario($"{i.DnipropietarioNavigation.Nombre} {i.DnipropietarioNavigation.Apellido}")
.SetTipo(i.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion)
.SetFechaInicio(i.Fechainicio)
.SetEstado(i.Habilitado, i.Cancelado)
.SetHabitaciones(i.IdpropiedadNavigation.Canthabitaciones)
.SetPiso(i.IdpropiedadNavigation.Piso??0)
.SetLetra(i.IdpropiedadNavigation.Letra??"")
.SetMesesAumento(i.MesesHastaAumento)
.SetMesesDuracion(i.MesesDurationContrato)
.Build();
return Ok(cont);
}
[HttpGet("api/contratos/inquilino")]
public IActionResult ObtenerContratosPorInquilino([FromHeader(Name="Auth")]string Auth) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) return Unauthorized();
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli==null) return Unauthorized();
var list = RepositorioContratos.Singleton.ObtenerContratosDeInquilino(cli.Dni);
List<ContratoDto> dtos = new();
foreach (var i in list) {
if (i.DniinquilinoNavigation == null || i.IdpropiedadNavigation == null
|| i.DnipropietarioNavigation == null) continue;
var cont = new ContratoDtoBuilder()
.SetInquilino($"{i.DniinquilinoNavigation.Nombre} {i.DniinquilinoNavigation.Apellido}")
.SetUbicacion(i.IdpropiedadNavigation.Ubicacion)
.SetPropietario($"{i.DnipropietarioNavigation.Nombre} {i.DnipropietarioNavigation.Apellido}")
.SetId(i.Id)
.SetTipo(i.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion)
.SetFechaInicio(i.Fechainicio)
.SetEstado(i.Habilitado, i.Cancelado)
.Build();
dtos.Add(cont);
}
return Ok(dtos);
}
[HttpGet("api/contrato/inquilino")]
public IActionResult ObtenerContratoPorInquilinoPorId([FromHeader(Name="Auth")]string Auth, int id=0) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) return Unauthorized();
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli==null) return Unauthorized();
if (id <= 0) return BadRequest(new { message = "No hay propiedades con id igual o menor a 0"});
var i = RepositorioContratos.Singleton.ObtenerContratoPorId(id);
if (i == null || i.DniinquilinoNavigation == null ||
i.IdpropiedadNavigation == null || i.DnipropietarioNavigation == null)return BadRequest(new { message = "Fallo la query"});
if (cli.Dni != i.Dniinquilino) return BadRequest(new { message = "No sos el inquilino"});
var cont = new ContratoPropiedadDtoBuilder()
.SetInquilino($"{i.DniinquilinoNavigation.Nombre} {i.DniinquilinoNavigation.Apellido}")
.SetUbicacion(i.IdpropiedadNavigation.Ubicacion)
.SetId(i.Id)
.SetPropietario($"{i.DnipropietarioNavigation.Nombre} {i.DnipropietarioNavigation.Apellido}")
.SetTipo(i.IdpropiedadNavigation.IdtipropiedadNavigation.Descripcion)
.SetFechaInicio(i.Fechainicio)
.SetEstado(i.Habilitado, i.Cancelado)
.SetHabitaciones(i.IdpropiedadNavigation.Canthabitaciones)
.SetPiso(i.IdpropiedadNavigation.Piso??0)
.SetLetra(i.IdpropiedadNavigation.Letra??"")
.SetMesesAumento(i.MesesHastaAumento)
.SetMesesDuracion(i.MesesDurationContrato)
.Build();
return Ok(cont);
}
[HttpPost("api/contratos/precontrato")]
public IActionResult IniciarPrecontrato([FromHeader(Name = "Auth")]string Auth, [FromBody] PrecontratoDto dto) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
@@ -52,6 +335,7 @@ public class ContratoController: ControllerBase {
.SetMesesHastaAumento(dto.MesesHastaAumento)
.SetPropiedad(p.Id)
.SetFecha(DateTime.Parse(dto.fechaprimernotificacion))
.SetMesesDuracion(dto.MesesDuracionContrato)
.Build();
@@ -273,12 +557,56 @@ public class ContratoController: ControllerBase {
Ok(new { message = "se notifico al futuro inquilino"}): BadRequest(new { message = "No se pudo enviar la notificacion"});
}
[HttpGet("api/contrato/DocumentoFinal")]
public IActionResult ObtenerContratoFinal ([FromHeader(Name = "Auth")]string Auth, [FromQuery]long idcontrato) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false){
validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false) return Unauthorized();
}
if (idcontrato <= 0) return BadRequest(new {message = "La id no puede ser igual o menor a 0"});
Contrato? contr = RepositorioContratos.Singleton.ObtenerContratoPorId(idcontrato);
if (contr == null || contr.Dniinquilino == 0) return BadRequest(new { message = "No hay un contrato por esa id"});
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return BadRequest(new { message = "No hay un cliente por ese token"});
if (cli.Dni != contr.Dniinquilino && cli.Dni != contr.Dnipropietario) return BadRequest(new { message = "El token no corresponde con el del inquilino"});
try{
var memstream = new MemoryStream();
var goa = new GetObjectArgs()
.WithBucket("alquilafacil")
.WithObject(contr.UrlContrato)
.WithCallbackStream(stream => {
memstream.Position=0;
stream.CopyTo(memstream);
});
mc.GetObjectAsync(goa).Wait();
memstream.Position = 0;
if (memstream.Length == 0) return BadRequest(new { message = "El archivo está vacío" });
return File(memstream, "application/pdf", contr.UrlContrato);
} catch (Exception e){
Console.Error.WriteLine(e);
return BadRequest(new { message = "Fallo al intentar obtener el archivo del almacenamiento o este no existe"});
}
}
[HttpGet("api/contrato/getdocumento")]
public IActionResult ObtenerContrato([FromHeader(Name = "Auth")]string Auth, [FromQuery]long idcontrato) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) return Unauthorized();
if (validacion1 == false){
validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false) return Unauthorized();
}
if (idcontrato <= 0) return BadRequest(new {message = "La id no puede ser igual o menor a 0"});
@@ -414,6 +742,34 @@ public class ContratoController: ControllerBase {
}
}
[HttpGet("api/contratos/garantes")]
public IActionResult ObtenerGarantes([FromHeader(Name ="Auth")] string Auth, int idcontrato) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest();
if(idcontrato <= 0) return BadRequest();
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return BadRequest();
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(idcontrato);
if (cont == null) return BadRequest();
if (cont.Dniinquilino != cli.Dni && cont.Dnipropietario != cli.Dni) return BadRequest();
var list = cont.Idgarantes;
List<GaranteDto> l = new();
foreach (var i in list) {
l.Add(new GaranteDtoBuilder()
.SetCelular(i.Celular)
.SetDni(i.Dni)
.SetDomicilio(i.Domicilio)
.SetDomicilioLaboral(i.Domiciliolaboral)
.SetNombre(i.Nombre)
.SetApellido(i.Apellido)
.Build());
}
return Ok(l);
}
private string ValidarCancelarDto(CancelarPrecontratoDto dto) {
if (dto == null) return "dto nulo";
string ret = "";
@@ -458,7 +814,8 @@ public class ContratoController: ControllerBase {
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";
if (dto.MesesDuracionContrato <= 0) ret += "No puede tener 0 o menos meses de duracion\n";
if (dto.MesesDuracionContrato < dto.MesesHastaAumento) ret += "el tiempo hasta aumento no puede ser mayor de \n";
return ret;
}

View File

@@ -0,0 +1,95 @@
using AlquilaFacil.Builder;
using Entidades;
using Entidades.Dto;
using Microsoft.AspNetCore.Mvc;
using Modelo;
namespace AlquilaFacil.Controllers;
[ApiController]
public class DefectoController: ControllerBase {
[HttpGet("api/defectos")]
public IActionResult ObtenerDefectosEnContrato([FromHeader(Name = "Auth")] string Auth, long Idcontrato = 0) {
if (Idcontrato <= 0) return BadRequest( new { message = "La id de contrato no puede ser menor o igual a 0"});
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false){
validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) {
return Unauthorized();
}
}
Cliente? cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return Unauthorized();
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(Idcontrato);
if (cont == null) return BadRequest(new { message = "No hay contrato por esa id"});
if (cont.Dniinquilino != cli.Dni && cont.Dnipropietario != cli.Dni) return BadRequest(new { message = "no deberias tener acceso a esto"});
var l = RepositorioDefectos.Singleton.ObtenerDefectosPorIdContrato(Idcontrato);
List<DefectoDto> ll = new();
foreach (var i in l){
var n = new DefectoDtoBuilder()
.SetId(i.Id)
.SetDesc(i.Descripcion)
.SetCosto(i.Costo)
.SetEstado(i.IdestadoNavigation.Descipcion)
.SetIdContrato(i.Idcontrato??0)
.SetPagaInquilino(i.Pagainquilino)
.SetDivisa(i.IddivisaNavigation.Signo)
.Build();
ll.Add(n);
}
return Ok(ll);
}
[HttpPost("api/defecto")]
public IActionResult AltaDefecto([FromHeader(Name = "Auth")] string Auth, AltaDefectoDto data) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Inquilino");
if (validacion1 == false) return Unauthorized();
string r = ValidarDto(data);
if (r != "") return BadRequest(new { message = r });
Defecto defecto = new Defecto{
Costo = data.Costo,
Descripcion = data.Descripcion,
Idcontrato = data.Idcontrato,
Iddivisa = data.Iddivisa,
Pagainquilino = data.Pagainquilino==0?0Lu:1Lu,
Idestado = 1,
};
var b = RepositorioDefectos.Singleton.AltaDefecto(defecto);
return b ?Ok(new { message = "Se cargo el Defecto en el sistema"}):BadRequest(new { message ="No se pudo cargar el defecto en el sistema"});
}
private string ValidarDto(AltaDefectoDto d){
string ret ="";
if (d == null) return "Dto nulo";
if (d.Iddivisa <0 || d.Iddivisa>1) ret +="No son divisas validas\n";
if (d.Descripcion == "") ret+="La descripcion no puede estar vacia\n";
if (d.Idcontrato<=0)ret += "No puede haber un id de contrato igual o menor a 0\n";
return ret;
}
[HttpPut("api/defecto/marcarpago")]
public IActionResult MarcarPago([FromHeader(Name = "Auth")] string Auth, long iddefecto = 0) {
if (String.IsNullOrEmpty(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false) return Unauthorized();
if (iddefecto<=0) return BadRequest(new { message = "No hay canones con id 0 o menor"});
bool ret = RepositorioDefectos.Singleton.MarcarPago(iddefecto);
return ret ?
Ok(new { message = "Se marco como pagado" }):BadRequest(new { message = "Fallo el acceso a la base de datos o no se encontro el defecto" });
}
}

View File

@@ -0,0 +1,60 @@
using AlquilaFacil.Builder;
using Entidades.Informes;
using Microsoft.AspNetCore.Mvc;
using Modelo;
namespace AlquilaFacil.Controllers;
[ApiController]
public class EstadisticaController: ControllerBase {
[HttpGet("api/stats/alquileresIniciados")]
public IActionResult alquileresIniciadosEsteAño([FromHeader(Name ="Auth")]string Auth, int year) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes");
if (validacion1 == false) return Unauthorized();
var validacion2 = RepositorioContratos.Singleton.HayContratosEnAño(year);
if (validacion2 == false) return BadRequest(new { message = "No hay contratos en ese año"});
var a = RepositorioEstadisticas.Singleton.ObtenerDataIniciadosPorAño(year);
return Ok(a);
}
[HttpGet("api/tabla/alquileresIniciados")]
public IActionResult tablaalquileresIniciadosEsteAño([FromHeader(Name ="Auth")]string Auth, int year) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes");
if (validacion1 == false) return Unauthorized();
var validacion2 = RepositorioContratos.Singleton.HayContratosEnAño(year);
if (validacion2 == false) return BadRequest(new { message = "No hay contratos en ese año"});
var a = RepositorioEstadisticas.Singleton.TablaObtenerContratosIniciadosPorAño(year);
if (a == null) return BadRequest(new { message = "Fallo al obtener el contrato"});
List<InformesAlquiler> informe =new();
foreach (var i in a) {
var d = new InformesAlquilerBuilder()
.SetId(i.Id).SetUbicacion(i.IdpropiedadNavigation.Ubicacion)
.SetDivisa(i.IddivisaNavigation.Signo)
.Build();
informe.Add(d);
}
return Ok(informe);
}
[HttpGet("api/stats/duracionContrato")]
public IActionResult DuracionContrato([FromHeader(Name ="Auth")]string Auth) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes");
if (validacion1 == false) return Unauthorized();
var a = RepositorioEstadisticas.Singleton.ObtenerDataDuracionContratos();
return Ok(a);
}
[HttpGet("api/tabla/duracionContrato")]
public IActionResult TablaDuracionContrato([FromHeader(Name ="Auth")]string Auth) {
if (String.IsNullOrWhiteSpace(Auth)) return BadRequest("");
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Informes");
if (validacion1 == false) return Unauthorized();
var a = RepositorioEstadisticas.Singleton.TablaObtenerDataDuracionContratos();
return Ok(a);
}
}

View File

@@ -15,22 +15,25 @@ 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?)"});
IQueryable<Notificacione> notificaciones = RepositorioNotificaciones.Singleton.ObtenerNotificacionesDeUsuario(cli.Dni)
.Where(x=>x.Leido == leido);
List<NotificacionDto> noti = new();
Parallel.ForEach(notificaciones, i => {
foreach (Notificacione i in notificaciones) {
if(i.DniclienteNavigation == null || i.DniremitenteNavigation==null) return BadRequest(new { message = "Esta mal cargado el precontrato"});
var dto = new NotificacionDtoBuilder()
.SetRemitente(i.DniremitenteNavigation.Email)
.SetAccion(i.Accion)
.SetMensaje(i.Mensaje)
.SetRemitente(i.DniremitenteNavigation.Email??"")
.SetAccion(i.Accion??"")
.SetMensaje(i.Mensaje??"")
.SetFecha(i.Fecha)
.SetPropiedad(i.IdpropiedadNavigation.Id.ToString())
.SetReceptor(i.DniclienteNavigation.Email)
.SetPropiedad(i.Idpropiedad.ToString()??"")
.SetReceptor(i.DniclienteNavigation.Email??"")
.Build();
noti.Add(dto);
});
}
return Ok(noti);
}
@@ -92,4 +95,30 @@ public class NotificacionesController: ControllerBase {
return ret?
Ok(new {message = "Se envio la notificacion"}):BadRequest(new {message = "Fallo al intentar guardar la notificacion"});
}
[HttpPost("api/notificarInquilino")]
public IActionResult NotificarInq([FromHeader(Name ="Auth")]string Auth, [FromBody] AvisoInquilinoDto data) {
if (String.IsNullOrWhiteSpace(Auth)) return Unauthorized();
var validacion1 = RepositorioGrupos.Singleton.CheckGrupos(Auth, "Propietario");
if (validacion1 == false)return Unauthorized();
if (data.Mensaje == "") return BadRequest(new {message = "El campo Mensaje esta vacio"});
if (data.Idpropiedad <= 0) return BadRequest(new {message = "La id de propiedad no puede ser 0 o menor"});
Contrato? cont = RepositorioContratos.Singleton.ObtenerContratoPorId(data.Idpropiedad);
if (cont == null || cont.DniinquilinoNavigation == null || cont.DnipropietarioNavigation == null || cont.IdpropiedadNavigation == null) return BadRequest(new { message = "no hay un contrato por esa id"});
var n = new NotificacioneBuilder()
.SetAccion("Notificacion Inquilino")
.SetMensaje(data.Mensaje)
.SetLeido(false)
.SetDnicliente(cont.DniinquilinoNavigation.Dni)
.SetDniremitente(cont.DnipropietarioNavigation.Dni)
.SetIdpropiedad(cont.IdpropiedadNavigation.Id)
.SetFecha(DateTime.Now)
.Build();
var ret = RepositorioNotificaciones.Singleton.AltaNotificacion(n);
return ret?
Ok(new { message = "se envio el aviso" }):BadRequest(new { message = "Fallo al intentar enviar el aviso" });
}
}

View File

@@ -109,6 +109,7 @@ public class PropiedadesController: ControllerBase {
Letra = propiedad.Letra ?? null,
Piso = propiedad.Piso ?? null,
Monto = propiedad.Monto,
Iddivisa = propiedad.Iddivisa,
};
var ret = RepositorioPropiedades.Singleton.AñadirPropiedad(Prop);
@@ -141,7 +142,8 @@ public class PropiedadesController: ControllerBase {
Letra = propiedad.Letra ?? null,
Piso = propiedad.Piso ?? null,
IdServicios = servs,
Monto = propiedad.Monto
Monto = propiedad.Monto,
Iddivisa = propiedad.Iddivisa,
};
bool ret = RepositorioPropiedades.Singleton.PatchPropiedad(Prop);
@@ -225,6 +227,9 @@ public class PropiedadesController: ControllerBase {
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";
if (prop.Iddivisa<0 || prop.Iddivisa>1) ret += "se tiene que elejir entre AR$ y US$";
return ret;
}
@@ -244,6 +249,9 @@ public class PropiedadesController: ControllerBase {
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";
if (prop.Iddivisa<0 || prop.Iddivisa>1) ret += "se tiene que elejir entre AR$ y US$";
return ret;
}

View File

@@ -1,12 +0,0 @@
using Entidades;
using Entidades.Dto;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Modelo;
namespace AlquilaFacil.Controllers;
[ApiController]
public class ServiciosController: ControllerBase {
}

View File

@@ -0,0 +1,24 @@
using System.Runtime;
using System.Text;
using Entidades;
using Entidades.Dto;
namespace AlquilaFacil.Facade;
public class DocumentoFacade {
private readonly DocumentoGeneradorHtml d1 = new();
private readonly DocumentoGeneradorPdf d2 = new();
public void GenerarHtml(ContratoDto cd, Recibo r, MemoryStream memoryStream) {
string str = d1.GenerarHTML(cd, r);
StreamWriter writer = new StreamWriter(memoryStream, Encoding.UTF8);
writer.WriteAsync(str).Wait();
writer.FlushAsync().Wait();
memoryStream.Position = 0;
}
public void GenerarPdf(ContratoDto cd, Recibo r, MemoryStream memoryStream) {
var mem = d2.GenerarPdf(cd, r);
mem.CopyToAsync(memoryStream).Wait();
memoryStream.Position = 0;
}
}

View File

@@ -0,0 +1,45 @@
using Entidades;
using Entidades.Dto;
using Microsoft.AspNetCore.Routing.Template;
namespace AlquilaFacil.Facade;
public class DocumentoGeneradorHtml {
public string GenerarHTML(ContratoDto cd, Recibo r) {
string tmpl =$"""
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<div class="container mt-5">
<div class="card">
<div class="card-header text-white bg-primary">
AlquilaFácil
</div>
<div class="card-body">
<h5 class="card-title">Detalles</h5>
<p class="card-text">
<strong>ID:</strong> {cd.id}<br>
<strong>Ubicación:</strong> {cd.Ubicacion}<br>
<strong>Tipo de Propiedad:</strong> {cd.TipoPropiedad}<br>
<strong>Fecha de Inicio:</strong> {cd.Fechainicio}<br>
<strong>Inquilino:</strong> {cd.Inquilino}<br>
<strong>Propietario:</strong> {cd.Propietario}<br>
</p>
<hr>
<h5 class="card-title">Detalles del Recibo</h5>
<p class="card-text">
<strong>ID del Recibo:</strong> {r.Id}<br>
<strong>Fecha:</strong> {r.Fecha}<br>
<strong>Monto:</strong> {r.Monto}<br>
<h2><b>PAGO</b></h2>
</p>
</div>
</div>
</div>
</body>
</html>
"""; return tmpl;
}
}

View File

@@ -0,0 +1,67 @@
using Entidades;
using Entidades.Dto;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.IO;
namespace AlquilaFacil.Facade;
public class DocumentoGeneradorPdf {
public MemoryStream GenerarPdf(ContratoDto cd, Recibo r)
{
var pdfStream = new MemoryStream();
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Header().Text("AlquilaFácil").FontSize(20).SemiBold().FontColor(Colors.White);
page.Content().Column(column =>
{
column.Spacing(10);
column.Item().Border(1).Padding(10).Column(card =>
{
card.Item().Row(row =>
{
row.RelativeItem().Text("Detalles").FontSize(16).SemiBold();
});
card.Item().Column(body =>
{
body.Spacing(5);
body.Item().Text($"ID: {cd.id}").FontSize(12).Bold();
body.Item().Text($"Ubicación: {cd.Ubicacion}").FontSize(12);
body.Item().Text($"Tipo de Propiedad: {cd.TipoPropiedad}").FontSize(12);
body.Item().Text($"Fecha de Inicio: {cd.Fechainicio}").FontSize(12);
body.Item().Text($"Inquilino: {cd.Inquilino}").FontSize(12);
body.Item().Text($"Propietario: {cd.Propietario}").FontSize(12);
});
});
column.Item().Border(1).Padding(10).Column(card =>
{
card.Item().Row(row =>
{
row.RelativeItem().Text("Detalles del Recibo").FontSize(16).SemiBold();
});
card.Item().Column(body =>
{
body.Spacing(5);
body.Item().Text($"ID del Recibo: {r.Id}").FontSize(12).Bold();
body.Item().Text($"Fecha: {r.Fecha}").FontSize(12);
body.Item().Text($"Monto: {r.Monto}").FontSize(12);
body.Item().AlignCenter().Text("PAGO").FontSize(20).Bold();
});
});
});
});
}).GeneratePdf(pdfStream);
pdfStream.Position = 0;
return pdfStream;
}
}

View File

@@ -9,4 +9,5 @@ public class PropiedadesAdmin {
public string? Servicios {get;set;} = "";
public int Monto { get; set; }
public string Estado { get; set; } = "";
public int Iddivisa { get; set; }
}

View File

@@ -23,6 +23,8 @@ public partial class AlquilaFacilContext : DbContext
public virtual DbSet<Defecto> Defectos { get; set; }
public virtual DbSet<Divisa> Divisas { get; set; }
public virtual DbSet<EstadoPropiedad> EstadoPropiedads { get; set; }
public virtual DbSet<Estadodefecto> Estadodefectos { get; set; }
@@ -153,6 +155,8 @@ public partial class AlquilaFacilContext : DbContext
entity.HasIndex(e => e.Idventa, "FK_CON_VEN");
entity.HasIndex(e => e.Iddivisa, "FK_contdiv");
entity.Property(e => e.Id)
.HasColumnType("bigint(20)")
.HasColumnName("id");
@@ -174,6 +178,9 @@ public partial class AlquilaFacilContext : DbContext
entity.Property(e => e.Habilitado)
.HasColumnType("bit(1)")
.HasColumnName("habilitado");
entity.Property(e => e.Iddivisa)
.HasColumnType("int(11)")
.HasColumnName("iddivisa");
entity.Property(e => e.Idpropiedad)
.HasColumnType("int(11)")
.HasColumnName("idpropiedad");
@@ -183,6 +190,7 @@ public partial class AlquilaFacilContext : DbContext
entity.Property(e => e.Indiceactualizacion)
.HasPrecision(8)
.HasColumnName("indiceactualizacion");
entity.Property(e => e.MesesDurationContrato).HasColumnType("int(11)");
entity.Property(e => e.MesesHastaAumento).HasColumnType("int(11)");
entity.Property(e => e.Monto)
.HasPrecision(12)
@@ -204,6 +212,11 @@ public partial class AlquilaFacilContext : DbContext
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_CON_PROPI");
entity.HasOne(d => d.IddivisaNavigation).WithMany(p => p.Contratos)
.HasForeignKey(d => d.Iddivisa)
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_contdiv");
entity.HasOne(d => d.IdpropiedadNavigation).WithMany(p => p.Contratos)
.HasForeignKey(d => d.Idpropiedad)
.OnDelete(DeleteBehavior.Restrict)
@@ -249,6 +262,8 @@ public partial class AlquilaFacilContext : DbContext
entity.HasIndex(e => e.Idestado, "FK_DEF_EST");
entity.HasIndex(e => e.Iddivisa, "FK_defdiv");
entity.Property(e => e.Id)
.HasColumnType("bigint(20)")
.HasColumnName("id");
@@ -256,11 +271,14 @@ public partial class AlquilaFacilContext : DbContext
.HasPrecision(12)
.HasColumnName("costo");
entity.Property(e => e.Descripcion)
.HasMaxLength(40)
.HasMaxLength(100)
.HasColumnName("descripcion");
entity.Property(e => e.Idcontrato)
.HasColumnType("bigint(20)")
.HasColumnName("idcontrato");
entity.Property(e => e.Iddivisa)
.HasColumnType("int(11)")
.HasColumnName("iddivisa");
entity.Property(e => e.Idestado)
.HasColumnType("int(11)")
.HasColumnName("idestado");
@@ -273,12 +291,29 @@ public partial class AlquilaFacilContext : DbContext
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_DEF_CON");
entity.HasOne(d => d.IddivisaNavigation).WithMany(p => p.Defectos)
.HasForeignKey(d => d.Iddivisa)
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_defdiv");
entity.HasOne(d => d.IdestadoNavigation).WithMany(p => p.Defectos)
.HasForeignKey(d => d.Idestado)
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_DEF_EST");
});
modelBuilder.Entity<Divisa>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
entity.Property(e => e.Id)
.HasColumnType("int(11)")
.HasColumnName("id");
entity.Property(e => e.Signo)
.HasMaxLength(3)
.HasColumnName("signo");
});
modelBuilder.Entity<EstadoPropiedad>(entity =>
{
entity.HasKey(e => e.Id).HasName("PRIMARY");
@@ -472,6 +507,8 @@ public partial class AlquilaFacilContext : DbContext
entity.HasIndex(e => e.Idtipropiedad, "FK_PROP_TIPO");
entity.HasIndex(e => e.Iddivisa, "FK_propdiv");
entity.Property(e => e.Id)
.HasColumnType("int(11)")
.HasColumnName("id");
@@ -481,6 +518,9 @@ public partial class AlquilaFacilContext : DbContext
entity.Property(e => e.Dnipropietario)
.HasColumnType("bigint(20)")
.HasColumnName("dnipropietario");
entity.Property(e => e.Iddivisa)
.HasColumnType("int(11)")
.HasColumnName("iddivisa");
entity.Property(e => e.Idestado)
.HasColumnType("int(11)")
.HasColumnName("idestado");
@@ -506,6 +546,11 @@ public partial class AlquilaFacilContext : DbContext
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_PROP_PROPI");
entity.HasOne(d => d.IddivisaNavigation).WithMany(p => p.Propiedades)
.HasForeignKey(d => d.Iddivisa)
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_propdiv");
entity.HasOne(d => d.IdestadoNavigation).WithMany(p => p.Propiedades)
.HasForeignKey(d => d.Idestado)
.OnDelete(DeleteBehavior.Restrict)
@@ -596,6 +641,8 @@ public partial class AlquilaFacilContext : DbContext
entity.HasIndex(e => e.Idpropiedad, "FK_VEN_PROP");
entity.HasIndex(e => e.Iddivisa, "FK_ventdiv");
entity.Property(e => e.Id)
.HasColumnType("bigint(20)")
.HasColumnName("id");
@@ -611,6 +658,9 @@ public partial class AlquilaFacilContext : DbContext
entity.Property(e => e.IdVendedor)
.HasColumnType("bigint(20)")
.HasColumnName("idVendedor");
entity.Property(e => e.Iddivisa)
.HasColumnType("int(11)")
.HasColumnName("iddivisa");
entity.Property(e => e.Idestado)
.HasColumnType("int(11)")
.HasColumnName("idestado");
@@ -631,6 +681,11 @@ public partial class AlquilaFacilContext : DbContext
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_VEN_PROL");
entity.HasOne(d => d.IddivisaNavigation).WithMany(p => p.Venta)
.HasForeignKey(d => d.Iddivisa)
.OnDelete(DeleteBehavior.Restrict)
.HasConstraintName("FK_ventdiv");
entity.HasOne(d => d.IdestadoNavigation).WithMany(p => p.Venta)
.HasForeignKey(d => d.Idestado)
.OnDelete(DeleteBehavior.Restrict)

View File

@@ -33,12 +33,18 @@ public partial class Contrato
public ulong Cancelado { get; set; }
public int Iddivisa { get; set; }
public int MesesDurationContrato { get; set; }
public virtual ICollection<Defecto> Defectos { get; set; } = new List<Defecto>();
public virtual Cliente? DniinquilinoNavigation { get; set; }
public virtual Cliente? DnipropietarioNavigation { get; set; }
public virtual Divisa IddivisaNavigation { get; set; } = null!;
public virtual Propiedade? IdpropiedadNavigation { get; set; }
public virtual Venta? IdventaNavigation { get; set; }

View File

@@ -17,7 +17,11 @@ public partial class Defecto
public ulong Pagainquilino { get; set; }
public int Iddivisa { get; set; }
public virtual Contrato? IdcontratoNavigation { get; set; }
public virtual Divisa IddivisaNavigation { get; set; } = null!;
public virtual Estadodefecto? IdestadoNavigation { get; set; }
}

19
Entidades/Divisa.cs Normal file
View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace Entidades;
public partial class Divisa
{
public int Id { get; set; }
public string Signo { get; set; } = null!;
public virtual ICollection<Contrato> Contratos { get; set; } = new List<Contrato>();
public virtual ICollection<Defecto> Defectos { get; set; } = new List<Defecto>();
public virtual ICollection<Propiedade> Propiedades { get; set; } = new List<Propiedade>();
public virtual ICollection<Venta> Venta { get; set; } = new List<Venta>();
}

View File

@@ -0,0 +1,8 @@
namespace Entidades.Dto;
public class AltaDefectoDto {
public string Descripcion { get; set; } ="";
public Decimal Costo { get; set; }
public ulong Pagainquilino { get; set; }
public int Iddivisa { get; set; }
public long Idcontrato { get; set; }
}

View File

@@ -7,4 +7,5 @@ public class AltaPropiedadDto {
public string Email { get; set; } = string.Empty;
public int Idtipropiedad { get; set; }
public int Monto { get; set; }
public int Iddivisa { get; set; }
}

View File

@@ -0,0 +1,5 @@
namespace Entidades.Dto;
public class AvisoInquilinoDto {
public string Mensaje { get; set; } ="";
public long Idpropiedad { get; set; }
}

10
Entidades/Dto/CanonDto.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace Entidades.Dto;
public class CanonDto{
public long Id { get; set;}
public int MesNum { get; set;}
public DateTime Mes { get; set;}
public Decimal Monto { get; set;}
public string Divisa { get; set;} = "";
public bool Pago { get; set;}
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
public class ChartData
{
[JsonPropertyName("labels")]
public List<string> Labels { get; set; }=new();
[JsonPropertyName("datasets")]
public List<Dataset> Datasets { get; set; }=new();
}
public class Dataset
{
[JsonPropertyName("label")]
public string Label { get; set; } ="";
[JsonPropertyName("data")]
public List<string> Data { get; set; }= new();
[JsonPropertyName("borderWidth")]
public int BorderWidth { get; set; }=1;
}

View File

@@ -0,0 +1,11 @@
namespace Entidades.Dto;
public class ContratoDto {
public long id { get; set; }
public string Ubicacion { get; set; }="";
public string TipoPropiedad { get; set; }="";
public DateTime Fechainicio { get; set; }
public string Inquilino { get; set; }="";
public string Propietario { get; set; }="";
public string Estado {get; set;}="";
}

View File

@@ -0,0 +1,8 @@
namespace Entidades.Dto;
public class ContratoPropiedadDto : ContratoDto {
public int Habitaciones { get; set; }
public int Piso { get; set;}
public string Letra { get; set; } = "";
public int MesesAumento { get; set; }
public int MesesDuracion { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Entidades.Dto;
public class CrearCanonsDto {
public long idcontrato{ get; set; }
public decimal aumento{ get; set; }
}

View File

@@ -0,0 +1,10 @@
namespace Entidades.Dto;
public class DefectoDto {
public long Id { get; set;}
public string Descripcion { get; set;} ="";
public Decimal Costo { get; set;}
public string Estado { get; set;} ="";
public long Idcontrato { get; set;}
public string Pagainquilino { get; set;} ="";
public string Divisa { get; set;} ="";
}

View File

@@ -0,0 +1,6 @@
namespace Entidades.Dto;
public class MarcarPagoDto {
public long Idcontrato { get; set; }
public DateTime fecha { get; set; }
}

View File

@@ -1,3 +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);
public record PatchPropiedadDto(int id, string Ubicacion, int Canthabitaciones, int? Piso, string? Letra, string Email, int tipo, List<string> Servicios, int Monto, int Iddivisa);

View File

@@ -6,5 +6,6 @@ public class PrecontratoDto {
public int CantidadGarantes { get; set; }
public int MesesHastaAumento { get; set; }
public bool TieneOpcionVenta { get; set; }
public string fechaprimernotificacion { get; set; }
public string fechaprimernotificacion { get; set; } = "";
public int MesesDuracionContrato { get; set; }
}

View File

@@ -8,4 +8,5 @@ public class PropiedadesDto {
public string Tipo { get; set; } = "";
public string? Servicios {get;set;} = "";
public int Monto { get; set; }
public int Iddivisa { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace Entidades.Informes;
public class InformesAlquiler {
public long Id { get; set; }
public string Ubicacion { get; set; }="";
public string Divisa { get; set; }="";
}

View File

@@ -0,0 +1,17 @@
namespace Entidades.Informes;
public class InformesMeses {
public int Meses { get; set; }
public int Repes{ get; set; }
public string Semaforizacion {get {
switch(Repes.CompareTo(2)){
case 1:
return "🟢";
case 0:
return "🟡";
case -1:
return "🔴";
default:
return "";
}
}}
}

View File

@@ -8,7 +8,7 @@ public partial class Permiso
{
public int Id { get; set; }
public string? Descripcion { get; set; }
public string Descripcion { get; set; } = null!;
[JsonIgnore]
public virtual ICollection<Grupo> Idgrupos { get; set; } = new List<Grupo>();

View File

@@ -23,10 +23,14 @@ public partial class Propiedade
public decimal Monto { get; set; }
public int Iddivisa { get; set; }
public virtual ICollection<Contrato> Contratos { get; set; } = new List<Contrato>();
public virtual Cliente? DnipropietarioNavigation { get; set; }
public virtual Divisa IddivisaNavigation { get; set; } = null!;
public virtual EstadoPropiedad? IdestadoNavigation { get; set; }
public virtual TipoPropiedad IdtipropiedadNavigation { get; set; } = null!;

View File

@@ -21,12 +21,16 @@ public partial class Venta
public DateTime? Fechafinal { get; set; }
public int Iddivisa { get; set; }
public virtual ICollection<Contrato> Contratos { get; set; } = new List<Contrato>();
public virtual Cliente? IdCompradorNavigation { get; set; }
public virtual Cliente? IdVendedorNavigation { get; set; }
public virtual Divisa IddivisaNavigation { get; set; } = null!;
public virtual Estadoventa? IdestadoNavigation { get; set; }
public virtual Propiedade? IdpropiedadNavigation { get; set; }

4
Front/.prettierrc Normal file
View File

@@ -0,0 +1,4 @@
{
"tabWidth": 4,
"useTabs": false
}

Binary file not shown.

View File

@@ -5,6 +5,7 @@
<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 src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
<script>
// Configura el tema desde localStorage antes de cargar la aplicación
const savedTheme = localStorage.getItem("theme") || "light";

723
Front/package-lock.json generated Normal file
View File

@@ -0,0 +1,723 @@
{
"name": "front",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "front",
"version": "0.0.0",
"dependencies": {
"@sveltejs/kit": "^2.7.3",
"@sveltestrap/sveltestrap": "^6.2.7",
"chartjs": "^0.3.24",
"svelte-routing": "^2.13.0"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tsconfig/svelte": "^5.0.4",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.3",
"svelte": "^5.0.0",
"svelte-check": "^4.0.5",
"tslib": "^2.8.0",
"typescript": "^5.6.3",
"vite": "^5.4.10"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"license": "Apache-2.0",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.21.5",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@polka/url": {
"version": "1.0.0-next.28",
"license": "MIT"
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.24.0",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.24.0",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@sveltejs/kit": {
"version": "2.7.3",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
"cookie": "^0.6.0",
"devalue": "^5.1.0",
"esm-env": "^1.0.0",
"import-meta-resolve": "^4.1.0",
"kleur": "^4.1.5",
"magic-string": "^0.30.5",
"mrmime": "^2.0.0",
"sade": "^1.8.1",
"set-cookie-parser": "^2.6.0",
"sirv": "^3.0.0",
"tiny-glob": "^0.2.9"
},
"bin": {
"svelte-kit": "svelte-kit.js"
},
"engines": {
"node": ">=18.13"
},
"peerDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1",
"svelte": "^4.0.0 || ^5.0.0-next.0",
"vite": "^5.0.3"
}
},
"node_modules/@sveltejs/vite-plugin-svelte": {
"version": "4.0.0",
"license": "MIT",
"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0",
"debug": "^4.3.7",
"deepmerge": "^4.3.1",
"kleur": "^4.1.5",
"magic-string": "^0.30.12",
"vitefu": "^1.0.3"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22"
},
"peerDependencies": {
"svelte": "^5.0.0-next.96 || ^5.0.0",
"vite": "^5.0.0"
}
},
"node_modules/@sveltejs/vite-plugin-svelte-inspector": {
"version": "3.0.1",
"license": "MIT",
"dependencies": {
"debug": "^4.3.7"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22"
},
"peerDependencies": {
"@sveltejs/vite-plugin-svelte": "^4.0.0-next.0||^4.0.0",
"svelte": "^5.0.0-next.96 || ^5.0.0",
"vite": "^5.0.0"
}
},
"node_modules/@sveltestrap/sveltestrap": {
"version": "6.2.7",
"license": "MIT",
"dependencies": {
"@popperjs/core": "^2.11.8"
},
"peerDependencies": {
"svelte": "^4.0.0 || ^5.0.0 || ^5.0.0-next.0"
}
},
"node_modules/@tsconfig/svelte": {
"version": "5.0.4",
"dev": true,
"license": "MIT"
},
"node_modules/@types/cookie": {
"version": "0.6.0",
"license": "MIT"
},
"node_modules/@types/estree": {
"version": "1.0.6",
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.12.1",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-typescript": {
"version": "1.4.13",
"license": "MIT",
"peerDependencies": {
"acorn": ">=8.9.0"
}
},
"node_modules/aria-query": {
"version": "5.3.2",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/axobject-query": {
"version": "4.1.0",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/chartjs": {
"version": "0.3.24",
"license": "MIT"
},
"node_modules/chokidar": {
"version": "4.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/cookie": {
"version": "0.6.0",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/debug": {
"version": "4.3.7",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/deepmerge": {
"version": "4.3.1",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/devalue": {
"version": "5.1.1",
"license": "MIT"
},
"node_modules/esbuild": {
"version": "0.21.5",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.21.5",
"@esbuild/android-arm": "0.21.5",
"@esbuild/android-arm64": "0.21.5",
"@esbuild/android-x64": "0.21.5",
"@esbuild/darwin-arm64": "0.21.5",
"@esbuild/darwin-x64": "0.21.5",
"@esbuild/freebsd-arm64": "0.21.5",
"@esbuild/freebsd-x64": "0.21.5",
"@esbuild/linux-arm": "0.21.5",
"@esbuild/linux-arm64": "0.21.5",
"@esbuild/linux-ia32": "0.21.5",
"@esbuild/linux-loong64": "0.21.5",
"@esbuild/linux-mips64el": "0.21.5",
"@esbuild/linux-ppc64": "0.21.5",
"@esbuild/linux-riscv64": "0.21.5",
"@esbuild/linux-s390x": "0.21.5",
"@esbuild/linux-x64": "0.21.5",
"@esbuild/netbsd-x64": "0.21.5",
"@esbuild/openbsd-x64": "0.21.5",
"@esbuild/sunos-x64": "0.21.5",
"@esbuild/win32-arm64": "0.21.5",
"@esbuild/win32-ia32": "0.21.5",
"@esbuild/win32-x64": "0.21.5"
}
},
"node_modules/esm-env": {
"version": "1.0.0",
"license": "MIT"
},
"node_modules/esrap": {
"version": "1.2.2",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15",
"@types/estree": "^1.0.1"
}
},
"node_modules/fdir": {
"version": "6.4.0",
"dev": true,
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/globalyzer": {
"version": "0.1.0",
"license": "MIT"
},
"node_modules/globrex": {
"version": "0.1.2",
"license": "MIT"
},
"node_modules/import-meta-resolve": {
"version": "4.1.0",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/is-reference": {
"version": "3.0.2",
"license": "MIT",
"dependencies": {
"@types/estree": "*"
}
},
"node_modules/kleur": {
"version": "4.1.5",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/locate-character": {
"version": "3.0.0",
"license": "MIT"
},
"node_modules/magic-string": {
"version": "0.30.12",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/mri": {
"version": "1.2.0",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/mrmime": {
"version": "2.0.0",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/ms": {
"version": "2.1.3",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.7",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/picocolors": {
"version": "1.1.0",
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.4.47",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.1.0",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/prettier": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-svelte": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.3.tgz",
"integrity": "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"prettier": "^3.0.0",
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
}
},
"node_modules/readdirp": {
"version": "4.0.2",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/rollup": {
"version": "4.24.0",
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.6"
},
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=18.0.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.24.0",
"@rollup/rollup-android-arm64": "4.24.0",
"@rollup/rollup-darwin-arm64": "4.24.0",
"@rollup/rollup-darwin-x64": "4.24.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.24.0",
"@rollup/rollup-linux-arm-musleabihf": "4.24.0",
"@rollup/rollup-linux-arm64-gnu": "4.24.0",
"@rollup/rollup-linux-arm64-musl": "4.24.0",
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.0",
"@rollup/rollup-linux-riscv64-gnu": "4.24.0",
"@rollup/rollup-linux-s390x-gnu": "4.24.0",
"@rollup/rollup-linux-x64-gnu": "4.24.0",
"@rollup/rollup-linux-x64-musl": "4.24.0",
"@rollup/rollup-win32-arm64-msvc": "4.24.0",
"@rollup/rollup-win32-ia32-msvc": "4.24.0",
"@rollup/rollup-win32-x64-msvc": "4.24.0",
"fsevents": "~2.3.2"
}
},
"node_modules/sade": {
"version": "1.8.1",
"license": "MIT",
"dependencies": {
"mri": "^1.1.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.0",
"license": "MIT"
},
"node_modules/sirv": {
"version": "3.0.0",
"license": "MIT",
"dependencies": {
"@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0",
"totalist": "^3.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/svelte": {
"version": "5.1.9",
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@jridgewell/sourcemap-codec": "^1.5.0",
"@types/estree": "^1.0.5",
"acorn": "^8.12.1",
"acorn-typescript": "^1.4.13",
"aria-query": "^5.3.1",
"axobject-query": "^4.1.0",
"esm-env": "^1.0.0",
"esrap": "^1.2.2",
"is-reference": "^3.0.2",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",
"zimmerframe": "^1.1.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/svelte-check": {
"version": "4.0.5",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
"chokidar": "^4.0.1",
"fdir": "^6.2.0",
"picocolors": "^1.0.0",
"sade": "^1.7.4"
},
"bin": {
"svelte-check": "bin/svelte-check"
},
"engines": {
"node": ">= 18.0.0"
},
"peerDependencies": {
"svelte": "^4.0.0 || ^5.0.0-next.0",
"typescript": ">=5.0.0"
}
},
"node_modules/svelte-routing": {
"version": "2.13.0",
"license": "MIT"
},
"node_modules/tiny-glob": {
"version": "0.2.9",
"license": "MIT",
"dependencies": {
"globalyzer": "0.1.0",
"globrex": "^0.1.2"
}
},
"node_modules/totalist": {
"version": "3.0.1",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/tslib": {
"version": "2.8.0",
"dev": true,
"license": "0BSD"
},
"node_modules/typescript": {
"version": "5.6.3",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/vite": {
"version": "5.4.10",
"license": "MIT",
"dependencies": {
"esbuild": "^0.21.3",
"postcss": "^8.4.43",
"rollup": "^4.20.0"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": {
"fsevents": "~2.3.3"
},
"peerDependencies": {
"@types/node": "^18.0.0 || >=20.0.0",
"less": "*",
"lightningcss": "^1.21.0",
"sass": "*",
"sass-embedded": "*",
"stylus": "*",
"sugarss": "*",
"terser": "^5.4.0"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
"less": {
"optional": true
},
"lightningcss": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
},
"stylus": {
"optional": true
},
"sugarss": {
"optional": true
},
"terser": {
"optional": true
}
}
},
"node_modules/vitefu": {
"version": "1.0.3",
"license": "MIT",
"workspaces": [
"tests/deps/*",
"tests/projects/*"
],
"peerDependencies": {
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0"
},
"peerDependenciesMeta": {
"vite": {
"optional": true
}
}
},
"node_modules/zimmerframe": {
"version": "1.1.2",
"license": "MIT"
}
}
}

View File

@@ -12,6 +12,8 @@
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tsconfig/svelte": "^5.0.4",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.3",
"svelte": "^5.0.0",
"svelte-check": "^4.0.5",
"tslib": "^2.8.0",
@@ -22,6 +24,7 @@
"@sveltejs/kit": "^2.7.3",
"@sveltestrap/sveltestrap": "^6.2.7",
"chartjs": "^0.3.24",
"svelte-chartjs": "^3.1.5",
"svelte-routing": "^2.13.0"
}
}

View File

@@ -17,6 +17,11 @@
import AdminUsuarios from "./paginas/AdminUsuarios.svelte";
import AdminPropiedades from "./paginas/AdminPropiedades.svelte";
import Notificaciones from "./paginas/Notificaciones.svelte";
import ControlAlquileresInquilino from "./paginas/ControlAlquileresInquilino.svelte";
import ControlAlquileresPropietario from "./paginas/ControlAlquileresPropietario.svelte";
import ContratosPropietario from "./paginas/ContratosPropietario.svelte";
import ContratoInquilino from "./paginas/ContratoInquilino.svelte";
import Informes from "./paginas/Informes.svelte";
</script>
<Router>
@@ -60,6 +65,11 @@
<ProteRoute componente={PropPage}/>
</Route>
<!--Crear Cuenta Propietario-->
<Route path="/accion/6">
<ProteRoute componente={Informes}/>
</Route>
<!--Administrar Propiedades Dadas de Baja-->
<Route path="/accion/8">
<ProteRoute componente={MisPropiedadesDeBaja}/>
@@ -74,8 +84,16 @@
<Route path="/accion/10">
<ProteRoute componente={AdminPropiedades}/>
</Route>
<!-- Pantalla Control Alquileres Inquilino -->
<Route path="/accion/11">
<ProteRoute componente={ControlAlquileresInquilino}/>
</Route>
<!-- Pantalla Control Alquileres Propietario -->
<Route path="/accion/12">
<ProteRoute componente={ControlAlquileresPropietario}/>
</Route>
<!--Paginas info Grupo-->
<Route path="/grupo/Inquilino">
@@ -96,6 +114,15 @@
<ProteRoute componente={Notificaciones}/>
</Route>
<!--Contratos Propietarios-->
<Route path="/propietario/contratos">
<ProteRoute componente={ContratosPropietario}/>
</Route>
<!--Contratos Inquilino-->
<Route path="/inquilino/contratos">
<ProteRoute componente={ContratoInquilino}/>
</Route>
</Router>

View File

@@ -43,7 +43,13 @@
<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>
<strong>Monto:</strong>
{#if prop.iddivisa == 0}
AR$
{:else}
US$
{/if}
{prop.monto}<br>
<strong>Estado:</strong> {prop.estado}<br>
</p>
{#if prop.estado == "Disponible"}

View File

@@ -0,0 +1,59 @@
<script>
import { onDestroy, onMount } from 'svelte';
import Chart from 'chart.js/auto';
let {chartData, typec='bar'} = $props();
let chartContainer;
let instance;
onDestroy(() => {
if (instance) {
instance.destroy();
}
});
const createChart = () => {
if (instance) {
instance.destroy();
}
const ctx = chartContainer.getContext('2d');
instance = new Chart(ctx, {
type: typec,
data: {
labels: chartData.labels,
datasets: chartData.datasets.map(dataset => ({
label: dataset.label,
data: dataset.data.map(x => String(x)),
borderWidth: dataset.borderWidth
}))
},
options: {
responsive: true,
plugins: {
legend: {
position: 'top',
},
},
scales: {
x: {
beginAtZero: true,
},
y: {
beginAtZero: true,
},
},
},
});
};
onMount(createChart);
$effect(createChart);
</script>
<div class="card card-body">
<canvas bind:this={chartContainer}></canvas>
</div>

View File

@@ -0,0 +1,94 @@
<script lang="ts">
import { onMount } from "svelte";
import type { AltaDefectoDto } from "../types";
let { idcontrato, onConfirm
} : {
idcontrato: number, onConfirm:(data: AltaDefectoDto)=>void} = $props();
let formData: AltaDefectoDto = $state({
descripcion:"",
costo:0,
idcontrato:idcontrato,
iddivisa:0,
pagainquilino:0
});
async function handle(e:Event){
e.preventDefault();
onConfirm(formData);
}
let n:number = $state(0);
$effect(()=> {n = formData.descripcion.length});
</script>
<div class="container">
<form>
<div class="mb-3">
<label for="descripcion" class="form-label">Descripción</label>
<input
type="text"
id="descripcion"
class="form-control"
bind:value={formData.descripcion}
placeholder="Ingrese la descripción"
required
maxlength="100"
/>
<small class="form-text text-muted">
{n}/100
</small>
</div>
<div class="mb-3 input-group">
<span class="input-group-text">$</span>
<input
type="number"
id="costo"
class="form-control"
bind:value={formData.costo}
placeholder="Ingrese el costo"
step="0.01"
required
/>
</div>
<div class="mb-3">
<div class="form-check">
<input
type="radio"
id="danioUso"
class="form-check-input"
bind:group={formData.pagainquilino}
value="0"
required
/>
<label for="danioUso" class="form-check-label">Daño por uso</label>
</div>
<div class="form-check">
<input
type="radio"
id="danioEstructural"
class="form-check-input"
bind:group={formData.pagainquilino}
value="1"
/>
<label for="danioEstructural" class="form-check-label">Daño Estructural</label>
</div>
</div>
<div class="mb-3">
<label for="iddivisa" class="form-label">Divisa</label>
<select
id="iddivisa"
class="form-select"
bind:value={formData.iddivisa}
required
>
<option value="0">ARS</option>
<option value="1">USD</option>
</select>
</div>
<button type="submit" class="btn btn-primary" onclick={(e)=> handle(e)}>Subir</button>
</form>
</div>

View File

@@ -0,0 +1,56 @@
<script lang="ts">
let {onCancel, onConfirm}: {onCancel:()=>void, onConfirm:(message:string)=>void} = $props();
let message:string = $state("");
const maxLength = $state(100);
function handleConfirm(e:Event) {
e.preventDefault();
if (message.length <= maxLength) {
onConfirm(message);
onCancel();
}
}
</script>
<div
class="modal fade show d-block"
tabindex="-1"
style="background-color: rgba(0, 0, 0, 0.5);"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirmar acción</h5>
<button type="button" class="btn-close" aria-label="Close" onclick={onCancel}></button>
</div>
<div class="modal-body">
<form onsubmit={(e)=>handleConfirm(e)}>
<div class="mb-3">
<label for="message" class="form-label">Mensaje</label>
<input
type="text"
id="message"
class="form-control"
bind:value={message}
maxlength={maxLength}
required
/>
<div class="form-text">
Caracteres restantes: {maxLength - message.length}
</div>
</div>
</form>
</div>
<div class="modal-footer d-flex justify-content-between">
<button type="button" class="btn btn-secondary" onclick={onCancel}>
Cancelar
</button>
<button type="button" class="btn btn-primary" onclick={(e)=>handleConfirm(e)}>
Confirmar
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,44 @@
<script lang="ts">
let selectedOption = $state(false);
let {onClose, onSubmit}: {onClose:()=>void, onSubmit:(op:boolean)=>void} = $props();
const handleSubmit = (e:Event) => {
e.preventDefault();
onSubmit(selectedOption);
};
</script>
<div
class="modal show d-block"
tabindex="-1"
role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Selecciona una opción</h5>
<button type="button" class="btn-close" aria-label="Close" onclick={onClose}></button>
</div>
<div class="modal-body">
<form onsubmit={handleSubmit}>
<div class="form-group mb-3">
<label for="formatSelect">Formato</label>
<select
id="formatSelect"
class="form-select"
bind:value={selectedOption}
>
<option value="false">PDF</option>
<option value="true">HTML</option>
</select>
</div>
<button type="submit" class="btn btn-primary" onclick={handleSubmit}>Aceptar</button>
</form>
</div>
</div>
</div>
</div>

View File

@@ -1,16 +1,16 @@
<script lang="ts">
let { onClose, onSubmit } : {
onClose: () => void,
onSubmit: (data: { opcionVenta: boolean; cantGarantes: number; mesesHastaAumento: number }) => void
onSubmit: (data: { opcionVenta: boolean; cantGarantes: number; mesesHastaAumento: number, mesesDuracionContrato:number }) => void
} = $props();
let opcionVenta: boolean = $state(false);
let cantGarantes: number = $state(0);
let mesesHastaAumento: number = $state(0);
let mesesDuracionContrato:number =$state(0);
function handleSubmit(e:Event) {
e.preventDefault();
onSubmit({ opcionVenta, cantGarantes, mesesHastaAumento });
onSubmit({ opcionVenta, cantGarantes, mesesHastaAumento, mesesDuracionContrato });
onClose();
}
</script>
@@ -39,6 +39,10 @@
<label for="mesesHastaAumento">Meses Hasta Aumento</label>
<input type="number" class="form-control" id="mesesHastaAumento" bind:value={mesesHastaAumento} min="0" required />
</div>
<div class="form-group">
<label for="mesesDuracionContrato">Meses Duracion Contrato</label>
<input type="number" class="form-control" id="mesesDuracionContrato" bind:value={mesesDuracionContrato} min="0" required />
</div>
<div class="modal-footer d-flex justify-content-between">
<button type="button" class="btn btn-secondary" onclick={onClose}>Cancelar</button>
<button type="submit" class="btn btn-primary">Confirmar</button>

View File

@@ -68,7 +68,13 @@
<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>
<strong>Monto:</strong>
{#if prop.iddivisa == 0}
AR$
{:else}
US$
{/if}
{prop.monto}<br>
</p>
<button class="btn btn-primary" onclick={Consultar}>Alquilar</button>
</div>

View File

@@ -3,7 +3,7 @@
import ModalEstatico from "./ModalEstatico.svelte";
import ModificarPropiedadForm from "./modificarPropiedadForm.svelte";
let { id, ubicacion, tipo, letra, piso,canthabitaciones, servicios, btnbaja = "Baja", monto } = $props();
let { id, ubicacion, tipo, letra, piso,canthabitaciones, servicios, btnbaja = "Baja", monto, iddivisa = 0 } = $props();
import { urlG } from "../stores/urlStore";
@@ -45,10 +45,17 @@
<td>{piso}</td>
<td>{tipo}</td>
<td>{servicios}</td>
<td>
{#if iddivisa == 0}
AR$
{:else}
US$
{/if}
</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>
<button class="btn btn-outline-secondary btn-sm" onclick={()=> setmod()}>Modificar</button>
<button class="btn btn-outline-danger btn-sm" onclick={() => BajaPropiedad()}>{btnbaja}</button>
</td>
</tr>
{#if modal}
@@ -57,7 +64,7 @@
{#if modificar}
<tr transition:fade={{duration:100}}>
<td colspan="8">
<ModificarPropiedadForm {id} {ubicacion} {canthabitaciones} {letra} {piso} {tipo} {servicios} {monto}/>
<ModificarPropiedadForm {id} {ubicacion} {canthabitaciones} {letra} {piso} {tipo} {servicios} {monto} {iddivisa}/>
</td>
</tr>
{/if}

View File

@@ -2,7 +2,7 @@
import { urlG } from "../stores/urlStore";
import { onMount } from "svelte";
let { canthabitaciones, id, letra, piso, tipo, ubicacion, servicios, monto } = $props();
let { canthabitaciones, id, letra, piso, tipo, ubicacion, servicios, monto, iddivisa} = $props();
let serviciosSeleccionados: string[] = $state([]);
const serviciosDisponibles = ["Gas", "Internet", "Telefono", "Luz"];
@@ -53,7 +53,8 @@
ubicacion,
email,
servicios: serviciosSeleccionados,
monto
monto,
iddivisa
}),
});
if (response.ok) {
@@ -151,6 +152,29 @@
<label for="idtipopropiedad">Tipo de propiedad</label>
</div>
<div class="form-floating mb-3">
<h6 class="form-floating form-label">Moneda</h6>
<div class="form-check">
<input
type="radio"
class="form-check-input"
bind:group={iddivisa}
value={0}
id="moneda-ar"
/>
<label class="form-check-label" for="moneda-ar">AR$</label>
</div>
<div class="form-check">
<input
type="radio"
class="form-check-input"
bind:group={iddivisa}
value={1}
id="moneda-us"
/>
<label class="form-check-label" for="moneda-us">US$</label>
</div>
</div>
<div class="mb-3">
<h6 class="form-floating form-label">Servicios</h6>
{#each serviciosDisponibles as servicio}

View File

@@ -0,0 +1,424 @@
<script lang="ts">
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import { onMount } from "svelte";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import {urlG} from "../stores/urlStore";
import type { AltaDefectoDto, CanonDto, ContratoDto, ContratoPropiedadDto, DefectoDto, GaranteDto2 } from "../types";
import ModalPedirDoc from "../Componentes/ModalPedirDoc.svelte";
import FormAltaDefecto from "../Componentes/FormAltaDefecto.svelte";
let token:string = sessionStorage.getItem("token")||"";
let selMod:any =$state();
let showmodal:boolean = $state(false);
let canons:CanonDto[] = $state([]);
let garantes: GaranteDto2[] = $state([]);
let prop:ContratoPropiedadDto = $state({
estado:"",
fechainicio:"",
id:0,
inquilino:"",
propietario:"",
tipoPropiedad:"",
ubicacion:"",
habitaciones:0,
piso:0,
letra:"",
mesesAumento:0,
mesesDuracion:0,
});
let defectos:DefectoDto[] = $state([]);
let modaldata:string = $state("");
let contratoid:string = $state("");
onMount(()=>{
getparams();
obtenerDatosACargar();
});
async function obtenerDatosACargar() {
try {
const respPropiedad = fetch($urlG+"/api/contrato/inquilino?id="+contratoid, {
method: "GET",
headers: {
"Auth": String(token),
}
});
const respgarantes = fetch($urlG+"/api/contratos/garantes?idcontrato="+contratoid, {
method: "GET",
headers: {
"Auth": String(token),
}
});
const respCanons = fetch($urlG+"/api/contratos/canon?id="+contratoid, {
method: "GET",
headers: {
"Auth": String(token),
}
});
const respoDefect = fetch($urlG+"/api/defectos?Idcontrato="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
const [p, g, c, d] = await Promise.all([respPropiedad, respgarantes, respCanons, respoDefect]);
const datosPropiedad = await p.json();
const datosGarantes = await g.json();
const datosCanons = await c.json();
const datosDefect = await d.json();
prop = datosPropiedad;
garantes = datosGarantes;
canons = datosCanons;
defectos = datosDefect;
} catch {
modaldata = "Fallo hacer las request";
}
}
function getparams(){
const qs = window.location.search;
const par = new URLSearchParams(qs);
contratoid = par.get("id")||"";
}
async function refreshCanon() {
try {
const ret = await fetch($urlG+"/api/contratos/canon?id="+contratoid, {
method: "GET",
headers: {
"Auth": String(token),
}
});
if (!ret.ok){
let data = await ret.json();
modaldata = data.message;
return;
}
let data = await ret.json();
canons = data;
return;
} catch {
modaldata = "No se pudo obtener la lista de canones actualizada";
}
}
async function verContrato() {
if (prop.id <= 0) {
modaldata = "no hay contratos con id 0 o menor";
return;
}
try {
const resp = await fetch ($urlG+"/api/contrato/DocumentoFinal?idcontrato="+prop.id, {
method: "GET",
headers: {
"Auth": String(token),
}
});
if (!resp.ok) {
let blob = await resp.json();
modaldata=blob.message;
return;
}
let blob = await resp.blob();
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
setTimeout(() => URL.revokeObjectURL(blobUrl), 100000);
} catch {
modaldata= "fallo intentar hacer la request";
}
}
async function realizarpago(mes: Date) {
try {
const ret = await fetch($urlG+"/api/contratos/realizarPago", {
method: "POST",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({idcontrato:contratoid, fecha:mes}),
});
let data = await ret.json();
modaldata = data.message;
if (ret.ok){
refreshCanon()
return;
}
} catch {
modaldata = "Fallo al intentar hacer la request";
}
}
function generarTiket(mod:any) {
selMod = mod;
showmodal =true;
}
async function pedirdocumento(op:boolean) {
try {
const ret = await fetch($urlG+"/api/contrato/GenerarRecibo?html="+op, {
method: "POST",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({fecha: selMod.mes, idcontrato: contratoid})
});
if (!ret.ok) {
let blob = await ret.json();
modaldata=blob.message;
return;
}
let blob = await ret.blob();
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
setTimeout(() => URL.revokeObjectURL(blobUrl), 100000);
} catch {
modaldata = "Fallo al intentar hacer la request";
}
}
async function cargarDefecto(data: AltaDefectoDto) {
if(data.idcontrato ==0) data.idcontrato = prop.id;
try {
const r = await fetch($urlG+"/api/defecto", {
method: "POST",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
let dr = await r.json();
modaldata = dr.message;
if (r.ok) {
refreshDefectos();
}
}catch{
modaldata = "Fallo al intentar hacer la request";
}
}
async function refreshDefectos() {
try {
const r = await fetch($urlG+"/api/defectos?Idcontrato="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
let rr =await r.json();
defectos = rr;
} catch {
modaldata ="No se pudo pedir la lista de Defectos";
}
}
</script>
<NavBarAutocompletable/>
{#if modaldata}
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")}/>
{/if}
{#if showmodal}
<ModalPedirDoc onClose={()=>showmodal=false} onSubmit={pedirdocumento} />
{/if}
<div class="container-fluid mt-4 d-flex">
<div class="col-md-4 me-4">
<div class="card">
<div class="card-header text-center">Propiedad</div>
<div class="card-body">
<p><b>Tipo:</b> {prop.tipoPropiedad}</p>
<p><b>Ubicación:</b> {prop.ubicacion}</p>
<p><b>Propietario:</b> {prop.propietario}</p>
<p><b>Inquilino:</b> {prop.inquilino}</p>
<p><b>Habitaciones:</b> {prop.habitaciones}</p>
<p><b>Piso:</b> {prop.piso}</p>
<p><b>Letra:</b> {prop.letra}</p>
<p><b>Fecha Inicio:</b> {String(prop.fechainicio).split("T")[0]}</p>
<p><b>Estado:</b> {prop.estado}</p>
<button class="btn btn-secondary" onclick={verContrato}>
Ver Contrato
</button>
</div>
<div class="card-footer text-center">
IdContrato: {prop.id}
</div>
</div>
</div>
<div class="col d-flex flex-column">
<div class="accordion mb-4" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button
class="accordion-button"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseOne"
aria-expanded="true"
aria-controls="collapseOne"
>
Garantes
</button>
</h2>
<div
id="collapseOne"
class="accordion-collapse collapse show"
aria-labelledby="headingOne"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Dni</th>
<th>Nombre</th>
<th>Apellido</th>
<th>Domicilio</th>
<th>Dom. Laboral</th>
<th>Celular</th>
</tr>
</thead>
<tbody>
{#each garantes as g}
<tr>
<td>{g.dni}</td>
<td>{g.nombre}</td>
<td>{g.apellido}</td>
<td>{g.domicilio}</td>
<td>{g.domiciliolaboral}</td>
<td>{g.celular}</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseTwo"
aria-expanded="false"
aria-controls="collapseTwo"
>
Canons
</button>
</h2>
<div
id="collapseTwo"
class="accordion-collapse collapse"
aria-labelledby="headingTwo"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<div class="row">
{#each canons as canon}
<div class="col-6 mb-3">
<div class="card">
<div class="card-header text-center">
{canon.mesNum}/{prop.mesesDuracion}
</div>
<div class="card-body">
<p><strong>Mes:</strong> {String(canon.mes).split("T")[0]}</p>
<p><strong>Monto:</strong> {canon.monto}</p>
<p><strong>Divisa:</strong> {canon.divisa}</p>
<p><strong>Pago:</strong> {canon.pago ? "Sí" : "No"}</p>
</div>
<div class="card-footer d-flex justify-content-between">
<button class="btn btn-primary btn-xs" disabled={canon.pago} onclick={()=>realizarpago(canon.mes)}>
Pagar
</button>
<button class="btn btn-info btn-xs" disabled={!canon.pago} onclick={()=> generarTiket(canon)}>
Generar Tiket
</button>
</div>
</div>
</div>
{/each}
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="ht">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#ct"
aria-expanded="false"
aria-controls="ct"
>
Defectos
</button>
</h2>
<div
id="ct"
class="accordion-collapse collapse"
aria-labelledby="ht"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<div class="card">
<div class="card-header">
Notificar Defecto en Propiedad
</div>
<div class="card-body">
<FormAltaDefecto onConfirm={cargarDefecto} idcontrato={prop.id} />
</div>
<div class="card-footer">
</div>
</div>
<br>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Descripción</th>
<th>Costo</th>
<th>Estado</th>
<th>Paga Inquilino</th>
<th>Divisa</th>
</tr>
</thead>
<tbody>
{#if defectos.length == 0}
<tr>
<td colspan="6">No hay defectos que mostrar</td>
</tr>
{:else}
{#each defectos as defecto}
<tr>
<td>{defecto.descripcion}</td>
<td>{defecto.costo}</td>
<td>{defecto.estado}</td>
<td>{defecto.pagainquilino}</td>
<td>{defecto.divisa}</td>
</tr>
{/each}
{/if}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,516 @@
<script lang="ts">
import { onMount } from "svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import {urlG} from "../stores/urlStore";
import type { CanonDto, ContratoDto, ContratoPropiedadDto, DefectoDto, GaranteDto2 } from "../types";
import ModalConfirm from "../Componentes/ModalConfirm.svelte";
import ModalPedirDoc from "../Componentes/ModalPedirDoc.svelte";
import ModalNotificacion from "../Componentes/ModalNotificacion.svelte";
let token:string = sessionStorage.getItem("token")||"";
let interes:number = $state(0);
let selMod:any =$state();
let showmodal:boolean = $state(false);
let shownotif:boolean = $state(false);
let max:number=$state(0);
let canons:CanonDto[] = $state([]);
let garantes: GaranteDto2[] = $state([]);
let prop:ContratoPropiedadDto = $state({
estado:"",
fechainicio:"",
id:0,
inquilino:"",
propietario:"",
tipoPropiedad:"",
ubicacion:"",
habitaciones:0,
piso:0,
letra:"",
mesesAumento:0,
mesesDuracion:0,
});
let defectos:DefectoDto[] = $state([]);
let modaldata:string = $state("");
let contratoid:string = $state("");
onMount(async ()=>{
getparams();
await obtenerDatosACargar();
max = canons.at(-1).mesNum||0;
});
async function obtenerDatosACargar() {
try {
const respPropiedad = fetch($urlG+"/api/contrato/propietario?id="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
const respgarantes = fetch($urlG+"/api/contratos/garantes?idcontrato="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
const respCanons = fetch($urlG+"/api/contratos/canon?id="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
const respoDefect = fetch($urlG+"/api/defectos?Idcontrato="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
const [p, g, c, d] = await Promise.all([respPropiedad, respgarantes, respCanons, respoDefect]);
const datosPropiedad = await p.json();
const datosGarantes = await g.json();
const datosCanons = await c.json();
const datosDefect = await d.json();
prop = datosPropiedad;
garantes = datosGarantes;
canons = datosCanons;
defectos = datosDefect;
} catch {
modaldata = "Fallo hacer las request";
}
}
function getparams(){
const qs = window.location.search;
const par = new URLSearchParams(qs);
contratoid = par.get("id")||"";
}
async function submitnuevosCanones(e: Event) {
e.preventDefault();
try {
const ret = await fetch($urlG+"/api/contratos/crearcanons",{
method: "POST",
headers: {
"Auth" : String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({idcontrato: contratoid, aumento: interes})
});
let data = await ret.json();
modaldata = data.message;
if (ret.ok) {
refreshCanon();
}
} catch {
modaldata = "Fallo al intentar alcanzar el servidor";
}
}
async function verContrato() {
if (prop.id <= 0) {
modaldata = "no hay contratos con id 0 o menor";
return;
}
try {
const resp = await fetch ($urlG+"/api/contrato/DocumentoFinal?idcontrato="+prop.id, {
method: "GET",
headers: {
"Auth": String(token),
}
});
if (!resp.ok) {
let blob = await resp.json();
modaldata=blob.message;
return;
}
let blob = await resp.blob();
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
setTimeout(() => URL.revokeObjectURL(blobUrl), 100000);
} catch {
modaldata= "fallo intentar hacer la request";
}
}
async function refreshCanon() {
try {
const ret = await fetch($urlG+"/api/contratos/canon?id="+contratoid, {
method: "GET",
headers: {
"Auth": String(token),
}
});
if (!ret.ok){
let data = await ret.json();
modaldata = data.message;
return;
}
let data = await ret.json();
canons = data;
return;
} catch {
modaldata = "No se pudo obtener la lista de canones actualizada";
}
}
async function marcarPago(mes: Date) {
try {
const ret = await fetch($urlG+"/api/contratos/marcarPago", {
method: "POST",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({idcontrato:contratoid, fecha:mes}),
});
let data = await ret.json();
modaldata = data.message;
if (ret.ok){
refreshCanon()
return;
}
} catch {
modaldata = "Fallo al intentar hacer la request";
}
}
function generarTiket(mod:any) {
selMod = mod;
showmodal =true;
}
async function pedirdocumento(op:boolean) {
try {
const ret = await fetch($urlG+"/api/contrato/GenerarRecibo?html="+op, {
method: "POST",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({fecha: selMod.mes, idcontrato: contratoid})
});
if (!ret.ok) {
let blob = await ret.json();
modaldata=blob.message;
return;
}
let blob = await ret.blob();
const blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
setTimeout(() => URL.revokeObjectURL(blobUrl), 100000);
} catch {
modaldata = "Fallo al intentar hacer la request";
}
}
async function EscribirNotificacion(message:string) {
if (message =="") {
modaldata = "no se puede enviar un mensaje vacio";
return;
}
try {
const r = await fetch($urlG+"/api/notificarInquilino", {
method: "POST",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
body: JSON.stringify({
mensaje: message,
idpropiedad: prop.id
})
});
let data = await r.json();
modaldata = data.message;
} catch {
modaldata ="No se pudo enviar el mensaje";
}
}
function abrirModalNotif() {
shownotif = true;
}
async function marcarDefectoPago(defecto: DefectoDto) {
try{
const r = await fetch($urlG+"/api/defecto/marcarpago?iddefecto="+defecto.id, {
method: "PUT",
headers: {
"Auth": String(token),
"Content-Type": "application/json",
},
});
let dr = await r.json();
modaldata = dr.message;
if (r.ok) {
refreshDefectos();
}
}catch {
modaldata = "No se pudo marcar como pago";
}
}
async function refreshDefectos() {
try {
const r = await fetch($urlG+"/api/defectos?Idcontrato="+contratoid, {
method: "GET",
headers: {
"Auth": token,
}
});
let rr =await r.json();
defectos = rr;
} catch {
modaldata ="No se pudo pedir la lista de Defectos";
}
}
</script>
<NavBarAutocompletable/>
{#if modaldata}
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")}/>
{/if}
{#if showmodal}
<ModalPedirDoc onClose={()=>showmodal=false} onSubmit={pedirdocumento} />
{/if}
{#if shownotif}
<ModalNotificacion onCancel={()=>shownotif = false} onConfirm={EscribirNotificacion}/>
{/if}
<div class="container-fluid mt-4 d-flex">
<div class="col-md-4 me-4">
<div class="card">
<div class="card-header text-center">Propiedad</div>
<div class="card-body">
<p><b>Tipo:</b> {prop.tipoPropiedad}</p>
<p><b>Ubicación:</b> {prop.ubicacion}</p>
<p><b>Propietario:</b> {prop.propietario}</p>
<p><b>Inquilino:</b> {prop.inquilino}</p>
<p><b>Habitaciones:</b> {prop.habitaciones}</p>
<p><b>Piso:</b> {prop.piso}</p>
<p><b>Letra:</b> {prop.letra}</p>
<p><b>Fecha Inicio:</b> {String(prop.fechainicio).split("T")[0]}</p>
<p><b>Estado:</b> {prop.estado}</p>
<div class="d-flex justify-content-between">
<button class="btn btn-secondary" onclick={verContrato}>
Ver Contrato
</button>
<button class="btn btn-warning" onclick={abrirModalNotif}>
Enviar Notificacion
</button>
</div>
</div>
<div class="card-footer text-center">
IdContrato: {prop.id}
</div>
</div>
</div>
<div class="col d-flex flex-column">
<div class="accordion mb-4" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="headingOne">
<button
class="accordion-button"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseOne"
aria-expanded="true"
aria-controls="collapseOne"
>
Garantes
</button>
</h2>
<div
id="collapseOne"
class="accordion-collapse collapse show"
aria-labelledby="headingOne"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Dni</th>
<th>Nombre</th>
<th>Apellido</th>
<th>Domicilio</th>
<th>Dom. Laboral</th>
<th>Celular</th>
</tr>
</thead>
<tbody>
{#each garantes as g}
<tr>
<td>{g.dni}</td>
<td>{g.nombre}</td>
<td>{g.apellido}</td>
<td>{g.domicilio}</td>
<td>{g.domiciliolaboral}</td>
<td>{g.celular}</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingTwo">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseTwo"
aria-expanded="false"
aria-controls="collapseTwo"
>
Canons
</button>
</h2>
<div
id="collapseTwo"
class="accordion-collapse collapse"
aria-labelledby="headingTwo"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<div class="row">
{#each canons as canon}
<div class="col-6 mb-3">
<div class="card">
<div class="card-header text-center">
{canon.mesNum}/{prop.mesesDuracion}
</div>
<div class="card-body">
<p><strong>Mes:</strong> {String(canon.mes).split("T")[0]}</p>
<p><strong>Monto:</strong> {canon.monto}</p>
<p><strong>Divisa:</strong> {canon.divisa}</p>
<p><strong>Pago:</strong> {canon.pago ? "Sí" : "No"}</p>
</div>
<div class="card-footer d-flex justify-content-between">
<button class="btn btn-warning btn-xs" disabled={canon.pago} onclick={()=>marcarPago(canon.mes)}>
Marcar Pago
</button>
<button class="btn btn-info btn-xs" disabled={!canon.pago} onclick={()=> generarTiket(canon)}>
Generar Tiket
</button>
</div>
</div>
</div>
{/each}
{#if max < prop.mesesDuracion}
{$inspect(max)}
<div class="card">
<div class="card-header text-center">
Definir el interés para los siguientes Canones
</div>
<div class="card-body">
<form>
<div class="input-group">
<input
class="form-control"
type="number"
id="interes"
bind:value={interes}
min="0"
/>
<span class="input-group-text" id="basic-addon2">%</span>
</div>
<br />
<button
class="btn btn-primary"
type="submit"
onclick={(e) => submitnuevosCanones(e)}
>
Enviar
</button>
</form>
</div>
</div>
{/if}
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="ht">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#ct"
aria-expanded="false"
aria-controls="ct"
>
Defectos
</button>
</h2>
<div
id="ct"
class="accordion-collapse collapse"
aria-labelledby="ht"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Descripción</th>
<th>Costo</th>
<th>Estado</th>
<th>Paga Inquilino</th>
<th>Divisa</th>
<th></th>
</tr>
</thead>
<tbody>
{#if defectos.length == 0}
<tr>
<td colspan="6">No hay defectos que mostrar</td>
</tr>
{:else}
{#each defectos as defecto}
<tr>
<td>{defecto.descripcion}</td>
<td>{defecto.costo}</td>
<td>{defecto.estado}</td>
<td>{defecto.pagainquilino}</td>
<td>{defecto.divisa}</td>
<td>
{#if defecto.estado !== "Pagado"}
<button class="btn btn-secondary" onclick={()=>marcarDefectoPago(defecto)}>Marcar Pago</button>
{/if}
</td>
</tr>
{/each}
{/if}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,93 @@
<script lang="ts">
import { onMount } from "svelte";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import {urlG} from "../stores/urlStore";
import type { ContratoDto } from "../types";
import BotonVolverArriba from "../Componentes/BotonVolverArriba.svelte";
import { fade } from "svelte/transition";
import { navigate } from "svelte-routing";
let token: string = sessionStorage.getItem("token")|| "";
let alquileres: ContratoDto[] = $state([]);
let modaldata:string = $state("");
let showButton:boolean = $state(false);
onMount(()=>{
recuperarContratos();
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
const handleScroll = () => {
showButton = window.scrollY > 100;
};
async function recuperarContratos() {
try{
const responce = await fetch($urlG+"/api/contratos/inquilino", {
method: "GET",
headers: {
"Auth": String(token),
},
});
if (responce.ok){
let data = await responce.json();
alquileres = data;
return;
}
let data = await responce.json();
modaldata = data.message;
}catch{
modaldata = "fallo al intentar hacer la request";
}
}
</script>
<NavBarAutocompletable/>
{#if modaldata }
<ModalEstatico payload={modaldata} close={()=>!!(modaldata="")}/>
{/if}
<div class="container-fluid">
<BarraHorizontalConTexto text="Control Alquileres" />
<div class="row g-3">
{#each alquileres as alquiler}
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0 text-center">{alquiler.tipoPropiedad}</h5>
</div>
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted">{alquiler.ubicacion}</h6>
<p class="card-text">
<strong>Fecha de inicio:</strong> {new Date(alquiler.fechainicio).toLocaleDateString()}<br />
<strong>Inquilino:</strong> {alquiler.inquilino}<br />
<strong>Propietario:</strong> {alquiler.propietario}<br>
<strong>Id Propiedad: </strong>{alquiler.id}
</p>
<div class="d-flex justify-content-center">
<button class="btn btn-primary" onclick={()=>navigate("/inquilino/contratos?id="+alquiler.id)}>
Ver
</button>
</div>
</div>
<div class="card-footer text-center">
<strong>Estado:</strong> {alquiler.estado}
</div>
</div>
</div>
{/each}
</div>
</div>
{#if showButton }
<div transition:fade={{duration:100}}>
<BotonVolverArriba/>
</div>
{/if}

View File

@@ -0,0 +1,93 @@
<script lang="ts">
import { onMount } from "svelte";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import {urlG} from "../stores/urlStore";
import type { ContratoDto } from "../types";
import BotonVolverArriba from "../Componentes/BotonVolverArriba.svelte";
import { fade } from "svelte/transition";
import { navigate } from "svelte-routing";
let token: string = sessionStorage.getItem("token")|| "";
let alquileres: ContratoDto[] = $state([]);
let modaldata:string = $state("");
let showButton:boolean = $state(false);
onMount(()=>{
recuperarContratos();
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
const handleScroll = () => {
showButton = window.scrollY > 100;
};
async function recuperarContratos() {
try{
const responce = await fetch($urlG+"/api/contratos/propietario", {
method: "GET",
headers: {
"Auth": String(token),
},
});
if (responce.ok){
let data = await responce.json();
alquileres = data;
return;
}
let data = await responce.json();
modaldata = data.message;
}catch{
modaldata = "fallo al intentar hacer la request";
}
}
</script>
<NavBarAutocompletable/>
{#if modaldata }
<ModalEstatico payload={modaldata} close={()=>!!(modaldata="")}/>
{/if}
<div class="container-fluid">
<BarraHorizontalConTexto text="Control Alquileres" />
<div class="row g-3">
{#each alquileres as alquiler}
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0 text-center">{alquiler.tipoPropiedad}</h5>
</div>
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted">{alquiler.ubicacion}</h6>
<p class="card-text">
<strong>Fecha de inicio:</strong> {new Date(alquiler.fechainicio).toLocaleDateString()}<br />
<strong>Inquilino:</strong> {alquiler.inquilino}<br />
<strong>Propietario:</strong> {alquiler.propietario}<br>
<strong>Id Propiedad: </strong>{alquiler.id}
</p>
<div class="d-flex justify-content-center">
<button class="btn btn-primary" onclick={()=>navigate("/propietario/contratos?id="+alquiler.id)}>
Ver
</button>
</div>
</div>
<div class="card-footer text-center">
<strong>Estado:</strong> {alquiler.estado}
</div>
</div>
</div>
{/each}
</div>
</div>
{#if showButton }
<div transition:fade={{duration:100}}>
<BotonVolverArriba/>
</div>
{/if}

View File

@@ -0,0 +1,186 @@
<script lang="ts">
import { onMount } from "svelte";
import BarraHorizontalConTexto from "../Componentes/BarraHorizontalConTexto.svelte";
import NavBarAutocompletable from "../Componentes/NavBarAutocompletable.svelte";
import { Chart } from "chart.js";
import FChart from "../Componentes/Estadisticas/fChart.svelte";
import ModalEstatico from "../Componentes/ModalEstatico.svelte";
import {urlG} from "../stores/urlStore";
import type { ChartData } from "../types";
import { text } from "@sveltejs/kit";
let token = sessionStorage.getItem("token")||"";
let y = $state(2025);
let cdata:ChartData|any = $state();
let aldata:{id:number, ubicacion:string, divisa:string}|any = $state();
let chartMesesDuracion:ChartData|any = $state();
let tablaMesesDuracion:{meses:number, repes:number, semaforizacion:string}|any = $state();
let modaldata:string = $state("");
onMount(async() => {
await dataAlquileresporAño();
});
async function dataAlquileresporAño(year = 2025) {
try{
const rep = fetch($urlG+"/api/stats/alquileresIniciados?year="+year, {
method : "GET",
headers: {
"Auth": token,
}
});
const pre = fetch($urlG+"/api/tabla/alquileresIniciados?year="+year, {
method : "GET",
headers: {
"Auth": token,
}
});
let [r,p] = await Promise.all([rep, pre]);
let data = await r.json();
let data2 = await p.json();
cdata = data;
aldata = data2;
return;
}catch{
modaldata="Fallo al intentar alcanzar el servidor";
}
}
let visibleMesesDuracion:boolean = $state(false);
async function dataMesesDuracion() {
try{
const p1 = fetch($urlG+"/api/stats/duracionContrato", {
method : "GET",
headers: {
"Auth": token,
}
});
const p2 = fetch($urlG+"/api/tabla/duracionContrato", {
method : "GET",
headers: {
"Auth": token,
}
});
let [r1, r2] = await Promise.all([p1,p2]);
let [d1,d2] = await Promise.all([r1.json(), r2.json()])
chartMesesDuracion = d1;
tablaMesesDuracion = d2;
}catch {
modaldata="Fallo al intentar alcanzar el servidor";
}
}
</script>
{#if modaldata}
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")} />
{/if}
<NavBarAutocompletable/>
<div class="container-fluid">
<div class="row mt-4" >
<BarraHorizontalConTexto text="Estadisticas"/>
<div class="accordion" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header" id="hea1">
<button class="accordion-button"
type="button"
data-bs-toggle="collapse"
data-bs-target="#c1"
aria-expanded="true"
aria-controls="c1">
Alquileres en el ultimo año
</button>
</h2>
<div class="accordion-collapse collapse show" id="c1" data-bs-parent="#accordionExample">
<div class="accordion-body row">
<div class="col">
<div class="d-flex input-group">
<input class="form-control" type="number" bind:value={y}>
<button class="btn btn-primary" onclick={()=>dataAlquileresporAño(y)}><img src="/zoom.svg" aria-label="Lupa"></button>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>#</th>
<th>Ubicacion</th>
<th>Divisa</th>
</tr>
</thead>
<tbody>
{#each aldata as al}
<tr>
<td>{al.id}</td>
<td>{al.ubicacion}</td>
<td>{al.divisa}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="col">
{#if cdata}
<FChart chartData={cdata}/>
{/if}
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="hea2">
<button class="accordion-button"
data-bs-toggle="collapse"
data-bs-target="#c2"
onclick={()=>{
if(visibleMesesDuracion === true){
visibleMesesDuracion=false;
return;
} else if (visibleMesesDuracion== false){
dataMesesDuracion();
}
}}
>
Meses De Duracion
</button>
</h2>
<div class="accordion-collapse collapse" id="c2" data-bs-parent="#accordionExample">
<div class="accordion-body row">
<div class="col">
<p class="text-muted">Objetivo: <i>Mide la longitud de los contratos en meses y cuantos hay por cada longitud. por lo menos 2.</i></p>
<table class="table table-hover">
<thead>
<tr>
<th>Cantidad de meses</th>
<th>Repeticiones</th>
<th>Semaforización</th>
</tr>
</thead>
<tbody>
{#each tablaMesesDuracion as mes}
<tr>
<td>{mes.meses}</td>
<td>{mes.repes}</td>
<td>{mes.semaforizacion}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="col-md-4">
{#if chartMesesDuracion}
<FChart chartData={chartMesesDuracion} typec="pie"/>
{/if}
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -52,13 +52,16 @@
<th>Piso</th>
<th>Tipo</th>
<th>Servicios</th>
<th>Divisa</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} />
<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}
iddivisa={propiedad.iddivisa}/>
{/each}
</tbody>
</table>

View File

@@ -53,13 +53,14 @@
<th>Piso</th>
<th>Tipo</th>
<th>Servicios</th>
<th>Divisa</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}/>
<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} iddivisa={propiedad.iddivisa}/>
{/each}
</tbody>
</table>

View File

@@ -130,6 +130,11 @@
Selmens = {...mensaje};
return;
}
if (mensaje.accion === "Notificacion Inquilino") {
Selmens = {...mensaje};
return;
}
}
async function obtenerListaGarantes(idcontrato: number) {
@@ -156,8 +161,8 @@
}
}
async function handleEnviarmensaje2(data: {opcionVenta:boolean, cantGarantes:number, mesesHastaAumento:number}) {
if (data.opcionVenta == null || data.cantGarantes <=0 || data.mesesHastaAumento<=0) {
async function handleEnviarmensaje2(data: {opcionVenta:boolean, cantGarantes:number, mesesHastaAumento:number, mesesDuracionContrato:number}) {
if (data.opcionVenta == null || data.cantGarantes <=0 || data.mesesHastaAumento<=0 || data.mesesDuracionContrato <=0) {
modaldata = "Estan mal cargados los datos del form";
return;
}
@@ -170,8 +175,9 @@
cantidadGarantes: data.cantGarantes,
idPropiedad: Selmens.propiedad,
fechaprimernotificacion: fecha,
emailInquilino: localStorage.getItem("email"),
emailInquilino: Selmens.remitente,
emailPropietario: Selmens.receptor,
mesesDuracionContrato: data.mesesDuracionContrato
};
let responce = await fetch($urlG+"/api/contratos/precontrato", {
@@ -421,6 +427,8 @@
<ModalCheckYContrato {garantes} men={Selmens} onCancel={handleCancelPrecontrato} onClose={() => (Selmens.accion = "")} onConfirm={handleEnviarmensaje4}/>
{:else if Selmens.accion == "Aceptar Contrato"}
<ModalVeryAceptarContrato onClose={() => (Selmens.accion = "")} onConfirm={handleAceptarContrato} onCancel={handlerechazarcontrato} getContrato={ObtenerContrato} men={Selmens}/>
{:else if Selmens.accion == "Notificacion Inquilino"}
<ModalEstatico payload={Selmens.mensaje} close={()=> !!(Selmens.accion = "") }/>
{/if}
<div class="container">
@@ -459,7 +467,7 @@
<tbody>
{#if mensajes.length <= 0}
<tr>
<td colspan={mostrarleidos == false ? 6 : 5}>
<td colspan={mostrarleidos == false ? 7 : 6}>
<p>No hay Mensajes para leer</p>
</td>
</tr>
@@ -481,10 +489,11 @@
Expandir
</button>
{/if}
{#if men.accion === "ContratoCancelado" || men.accion === "Rechazo Contrato" ||
men.accion === "Aceptado Contrato"}
{#if (men.accion === "ContratoCancelado" || men.accion === "Rechazo Contrato" ||
men.accion === "Aceptado Contrato" || men.accion === "Notificacion Inquilino"
) && mostrarleidos == false}
<button
class="btn btn-outline-danger"
class="btn btn-outline-danger btn-sm"
onclick={() => marcarleido(men.fecha, localStorage.getItem("email")|| "", men)}>
Marcar Leido
</button>

View File

@@ -5,15 +5,16 @@
import type { Propiedad } from "../types";
import { urlG } from "../stores/urlStore";
let propiedad: Propiedad = {
let propiedad = $state({
ubicacion: "",
canthabitaciones: 1,
piso: 0,
letra: "",
email: localStorage.getItem("email") || "",
idtipropiedad: 1,
iddivisa:0,
monto: 1,
};
});
let token = sessionStorage.getItem("token");
let mostrarModal = $state(false);
@@ -116,6 +117,31 @@
/>
<label for="letra">Letra</label>
</div>
<div class="form-floating mb-3">
<h6 class="form-floating form-label">Moneda</h6>
<div class="form-check">
<input
type="radio"
class="form-check-input"
bind:group={propiedad.iddivisa}
value={0}
id="moneda-ar"
/>
<label class="form-check-label" for="moneda-ar">AR$</label>
</div>
<div class="form-check">
<input
type="radio"
class="form-check-input"
bind:group={propiedad.iddivisa}
value={1}
id="moneda-us"
/>
<label class="form-check-label" for="moneda-us">US$</label>
</div>
</div>
<div class="form-floating mb-3">
<select
id="idtipropiedad"

78
Front/src/types.d.ts vendored
View File

@@ -6,7 +6,8 @@ export type PropiedadDto = {
letra: string | null,
canthabitaciones: number,
servicios: string,
monto: number
monto: number,
iddivisa: number
}
export type AdminParametrosBusqueda = {
@@ -25,7 +26,8 @@ export type PropiedadAdmin = {
canthabitaciones: number,
servicios: string,
monto: number,
estado: string
estado: string,
iddivisa: number
}
export type Permiso = {
id: number;
@@ -52,7 +54,8 @@ export type Propiedad = {
letra: string,
email: string,
idtipropiedad: number,
monto: number
monto: number,
iddivisa: number
};
export type MensajeDto = {
@@ -73,3 +76,72 @@ export type GaranteDto = {
Celular: string;
Domiciliolaboral: string;
};
//inedito
export type GaranteDto2 = {
dni: number;
nombre: string;
apellido: string;
domicilio: string;
celular: string;
domiciliolaboral: string;
};
export type ContratoDto ={
id: number,
ubicacion:string,
tipoPropiedad:string,
fechainicio:Date,
inquilino:string,
propietario:string,
estado:string,
}
export type CanonDto = {
id:number,
mesNum:number,
mes:Date,
monto:number,
divisa:string,
pago:boolean
}
export type ContratoPropiedadDto ={
id: number,
ubicacion:string,
tipoPropiedad:string,
fechainicio:string,
inquilino:string,
propietario:string,
estado:string,
habitaciones:number,
piso:number,
letra:string,
mesesAumento:number,
mesesDuracion:number
}
export type DefectoDto ={
id:number,
descripcion:string,
costo:number,
estado:string,
idcontrato:number,
pagainquilino:string,
divisa:string,
}
export type AltaDefectoDto ={
descripcion:string,
costo:number,
pagainquilino:number,
iddivisa:number,
idcontrato:number
}
export type ChartData = {
labels: string[],
datasets: [{
label: string,
data:string[],
}]
}

View File

@@ -0,0 +1,91 @@
using Entidades;
using Microsoft.EntityFrameworkCore;
using Org.BouncyCastle.Math.EC.Rfc7748;
namespace Modelo;
public class RepositorioCanons: RepositorioBase<RepositorioCanons> {
public ICollection<Canon>? ObtenerCanonsPorContrato(int id) {
var con = Context;
var l = con.Contratos.Include(x=>x.Idcanons).FirstOrDefault(x => x.Id == id);
if (l == null) return null;
return l.Idcanons;
}
public Canon? ObtenerCanonContrato(DateTime f, long idcont) {
var con = Context;
Canon? cc = null;
var c = con.Contratos.Include(x=>x.Idcanons).ThenInclude(x=>x.IdreciboNavigation).FirstOrDefault(x => x.Id == idcont);
if (c == null) return null;
foreach (var j in c.Idcanons) {
if (j.Fecha == f) {
cc = j;
break;
}
}
return cc;
}
public bool SetRecibo(Canon c, Recibo re) {
var con = Context;
var cc = con.Canons
.Include(x=>x.Idcontratos)
.ThenInclude(x=>x.Idcanons)
.FirstOrDefault(x=>x.Id == c.Id);
if (cc == null) return false;
if (cc.Idcontratos.Count()!=1) return false;
Contrato ccc = cc.Idcontratos.First();
if (ccc.Cancelado == 1 || ccc.Habilitado == 0) return false;
con.Entry(ccc).Reference(x=>x.IdpropiedadNavigation).Load();
re.Id = (con.Recibos.Any()?con.Recibos.Max(x=>x.Id):0)+1;
con.Recibos.Add(re);
cc.Idrecibo = re.Id;
cc.Pagado = 1;
if (ccc.Idcanons.Where(x=>x.Pagado==1).Count() == ccc.MesesDurationContrato){
ccc.Cancelado = 1;
ccc.IdpropiedadNavigation.Idestado = 3;
}
return Guardar(con);
}
public bool CrearCanons(decimal aumento, long idcontrato) {
var con = Context;
aumento/=100;
aumento+=1;
var cont = con.Contratos.Include(x=>x.Idcanons).FirstOrDefault(x=>x.Id == idcontrato);
if (cont == null) return false;
int exist = cont.Idcanons.Count();
Canon? d = cont.Idcanons.OrderByDescending(x=>x.Fecha).FirstOrDefault();
if (d == null) return false;
if (exist == cont.MesesDurationContrato) return false;
if (exist+cont.MesesHastaAumento >= cont.MesesDurationContrato){
exist = cont.MesesDurationContrato-exist;
} else{
exist = cont.MesesHastaAumento;
}
cont.Monto = cont.Monto * aumento;
for (int i = 0; i < exist; i++){
Canon c = new Canon{
Fecha = d.Fecha.AddMonths(i==0?1:i+1),
Id = con.Canons.Count()+i+1,
Monto = cont.Monto,
Pagado = 0,
};
con.Canons.Add(c);
cont.Idcanons.Add(c);
}
return Guardar(con);
}
}

View File

@@ -1,4 +1,5 @@
using Entidades;
using Entidades.Dto;
using Microsoft.EntityFrameworkCore;
namespace Modelo;
@@ -22,9 +23,10 @@ public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
if (prop == null) return false;
prop.Idestado = 2;
c.Iddivisa = prop.Iddivisa;
c.Id = (con.Contratos.Any() ? con.Contratos.Max(x => x.Id) : 0) + 1;
c.Monto = prop.Monto;
con.Contratos.Add(c);
con.Notificaciones.Add(n);
@@ -92,6 +94,7 @@ public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
Contrato? contr = con.Contratos
.Include(x=>x.DnipropietarioNavigation)
.Include(x=>x.Idgarantes)
.Include(x=>x.DniinquilinoNavigation)
.Where(x=>x.Cancelado == 0 && x.Habilitado == 0)
.FirstOrDefault(x=>x.Id == idcontrato);
if (contr == null) return null;
@@ -119,19 +122,34 @@ public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
if (cont == null || cont.IdpropiedadNavigation==null) return false;
cont.Habilitado = 1;
cont.Fechainicio = DateTime.Now;
var fecha = cont.Fechainicio;
if (cont.MesesDurationContrato < cont.MesesHastaAumento) {
for (int i = 0; i < cont.MesesDurationContrato; i++) {
Canon can = new Canon{
Fecha = fecha.AddMonths(i),
Monto = cont.IdpropiedadNavigation.Monto,
Pagado = 0,
};
can.Id = (con.Canons.Any()? con.Canons.Count() :0)+1+i;
for (int i = 0; i < cont.MesesHastaAumento; i++) {
Canon can = new Canon{
con.Canons.Add(can);
cont.Idcanons.Add(can);
}
} else {
for (int i = 0; i < cont.MesesHastaAumento; i++) {
Canon can = new Canon{
Fecha = fecha.AddMonths(i),
Monto = cont.IdpropiedadNavigation.Monto,
Pagado = 0,
};
can.Id = (con.Canons.Any()? con.Canons.Count() :0)+1+i;
Monto = cont.IdpropiedadNavigation.Monto,
Pagado = 0,
};
can.Id = (con.Canons.Any()? con.Canons.Count() :0)+1+i;
con.Canons.Add(can);
cont.Idcanons.Add(can);
con.Canons.Add(can);
cont.Idcanons.Add(can);
}
}
return Guardar(con);
}
@@ -144,4 +162,43 @@ public class RepositorioContratos: RepositorioBase<RepositorioContratos> {
cont.IdpropiedadNavigation.Idestado = 1;
return Guardar(con);
}
public IQueryable<Contrato> ObtenerContratosDePropietario(long dni) {
var con = Context;
var l = con.Contratos
.Include(x=>x.DniinquilinoNavigation)
.Include(x=>x.DnipropietarioNavigation)
.Include(x=>x.IdpropiedadNavigation)
.ThenInclude(x=>x.IdtipropiedadNavigation)
.Where(x=>x.Dnipropietario == dni);
return l;
}
public IQueryable<Contrato> ObtenerContratosDeInquilino(long dni) {
var con = Context;
var l = con.Contratos
.Include(x=>x.DniinquilinoNavigation)
.Include(x=>x.DnipropietarioNavigation)
.Include(x=>x.IdpropiedadNavigation)
.ThenInclude(x=>x.IdtipropiedadNavigation)
.Where(x=>x.Dniinquilino == dni);
return l;
}
public Contrato? ObtenerContratoPorId(long idcontrato) {
var con = Context;
var l = con.Contratos
.Include(x=>x.Idgarantes)
.Include(x=>x.DniinquilinoNavigation)
.Include(x=>x.DnipropietarioNavigation)
.Include(x=>x.IdpropiedadNavigation)
.ThenInclude(x=>x.IdtipropiedadNavigation)
.FirstOrDefault(x=>x.Id == idcontrato);
return l;
}
public bool HayContratosEnAño(int year) {
var con = Context;
return con.Contratos.Where(x=>x.Fechainicio.Year == year).Any();
}
}

View File

@@ -0,0 +1,31 @@
using Entidades;
using Microsoft.EntityFrameworkCore;
namespace Modelo;
public class RepositorioDefectos: RepositorioBase<RepositorioDefectos> {
public bool AltaDefecto(Defecto defecto){
var con = Context;
defecto.Id = con.Defectos.Any()? con.Defectos.Count()+1 : 1;
con.Defectos.Add(defecto);
return Guardar(con);
}
public bool MarcarPago(long iddefecto){
var con = Context;
var d = con.Defectos.FirstOrDefault(x=>x.Id == iddefecto);
if (d == null)return false;
d.Idestado = 2;
return Guardar(con);
}
public IQueryable<Defecto> ObtenerDefectosPorIdContrato(long idcontrato){
var con = Context;
var l = con.Defectos
.Include(x=>x.IdestadoNavigation)
.Include(x=>x.IddivisaNavigation)
.Where(x=>x.Idcontrato == idcontrato);
return l;
}
}

View File

@@ -0,0 +1,72 @@
using Entidades;
using Entidades.Informes;
using Microsoft.EntityFrameworkCore;
namespace Modelo;
public class RepositorioEstadisticas: RepositorioBase<RepositorioEstadisticas> {
public ChartData? ObtenerDataIniciadosPorAño(int year){
var con = Context;
var contratosPorMes = con.Contratos
.Where(c => c.Habilitado == 1 && c.Fechainicio.Year == year)
.GroupBy(c => c.Fechainicio.Month)
.Select(g => new { Mes = g.Key, Cantidad = g.Count() })
.OrderBy(x => x.Mes).ToList();
if (!contratosPorMes.Any()) return null;
var data = new ChartData();
data.Labels = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"];
List<string> ddd = new List<string>(["0","0","0","0","0","0","0","0","0","0","0","0"]);
foreach (var contrato in contratosPorMes) {
ddd[contrato.Mes-1] = contrato.Cantidad.ToString();
}
Dataset dd = new();
dd.Data = ddd;
dd.Label = $"Alquileres por Mes del año {year}";
data.Datasets.Add(dd);
return data;
}
public ChartData? ObtenerDataDuracionContratos() {
var con = Context;
var meses = con.Contratos.Where(x=>x.Habilitado ==1)
.GroupBy(x=>x.MesesDurationContrato).Select(g=> new {Duracion = g.Key, Cantidad = g.Count()});
if(!meses.Any()) return null;
var data = new ChartData();
Dataset dd = new();
foreach (var mes in meses){
data.Labels.Add(mes.Duracion.ToString());
dd.Data.Add(mes.Cantidad.ToString());
}
dd.Label="Duracion Contratos";
data.Datasets.Add(dd);
return data;
}
public IQueryable<Contrato> TablaObtenerContratosIniciadosPorAño(int year) {
var con = Context;
var contratosPorMes = con.Contratos.Include(x=>x.IddivisaNavigation).Include(x=>x.IdpropiedadNavigation)
.Where(c => c.Habilitado == 1 && c.Fechainicio.Year == year);
return contratosPorMes;
}
public List<InformesMeses> TablaObtenerDataDuracionContratos() {
var con = Context;
var meses = con.Contratos.Where(x=>x.Habilitado ==1)
.GroupBy(x=>x.MesesDurationContrato).Select(g=> new {Duracion = g.Key, Cantidad = g.Count()});
List<InformesMeses> l = new();
foreach (var mes in meses){
l.Add(new InformesMeses{
Meses = mes.Duracion,
Repes = mes.Cantidad
});
}
return l;
}
}

View File

@@ -31,7 +31,8 @@ public class RepositorioNotificaciones : RepositorioBase<RepositorioNotificacion
var con = Context;
var notis = con.Notificaciones
.Include(x=>x.IdpropiedadNavigation)
.Include(x=>x.IdpropiedadNavigation)
.Include(x=>x.DniclienteNavigation)
.Include(x=>x.DniremitenteNavigation)
.Where(x => x.Dnicliente == dni);
return notis;
@@ -39,7 +40,7 @@ public class RepositorioNotificaciones : RepositorioBase<RepositorioNotificacion
public bool HayNotis(long dni) {
var con = Context;
bool hay = con.Notificaciones.Where(x=>x.Leido == false).Any();
bool hay = con.Notificaciones.Where(x=>x.Leido == false && x.Dnicliente == dni).Any();
return hay;
}
}

View File

@@ -13,7 +13,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
public IQueryable<PropiedadesDto> ListarPropiedades(){
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -53,7 +54,7 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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)
@p_dni_propietario, @p_id_tipo_propiedad, @p_monto, @iddivisa, @p_filas_insertadas)
""",
new MySqlParameter("@p_ubicacion", prop.Ubicacion),
new MySqlParameter("@p_cant_habitaciones", prop.Canthabitaciones),
@@ -62,6 +63,7 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
new MySqlParameter("@p_dni_propietario", prop.Dnipropietario),
new MySqlParameter("@p_id_tipo_propiedad", prop.Idtipropiedad),
new MySqlParameter("@p_monto",prop.Monto),
new MySqlParameter("@iddivisa", prop.Iddivisa),
filasInsertadasParam
);
@@ -80,6 +82,7 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
propi.Piso = prop.Piso;
propi.Letra = prop.Letra;
propi.Monto = prop.Monto;
propi.Iddivisa = prop.Iddivisa;
propi.IdServicios.Clear();
foreach(Servicio ser in prop.IdServicios) {
@@ -93,7 +96,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
public IQueryable<PropiedadesDto> ObtenerPropiedadesPorEmail(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
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,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN Clientes c ON c.dni = p.dnipropietario
JOIN TipoPropiedad tp ON tp.id = p.idtipropiedad
@@ -109,7 +113,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
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,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN Clientes c ON c.dni = p.dnipropietario
JOIN TipoPropiedad tp ON tp.id = p.idtipropiedad
@@ -189,7 +194,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -213,7 +219,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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, p.monto as Monto
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -232,7 +239,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -255,7 +263,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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, p.monto as Monto
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -272,7 +281,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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, p.monto as Monto
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -290,7 +300,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -315,7 +326,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -352,7 +364,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = 1
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -369,7 +382,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -387,7 +401,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -405,7 +420,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -423,7 +439,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -443,7 +460,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -468,7 +486,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -494,7 +513,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id
@@ -520,7 +540,8 @@ public class RepositorioPropiedades: RepositorioBase<RepositorioPropiedades> {
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
GROUP_CONCAT(DISTINCT s.descripcion SEPARATOR ', ') AS Servicios, p.monto as Monto, ep.descripcion AS Estado,
p.iddivisa as Iddivisa
FROM Propiedades p
JOIN EstadoPropiedad ep ON p.idestado = ep.id
JOIN TipoPropiedad tp ON p.idtipropiedad = tp.id

BIN
bun.lockb Executable file

Binary file not shown.

1
package.json Normal file
View File

@@ -0,0 +1 @@
{ "dependencies": { "chart.js": "^4.4.7" } }