añadido front para que el admin suba el contrato

This commit is contained in:
2025-07-26 02:42:30 -03:00
parent 98414a5ec7
commit 5d944b0ee4
7 changed files with 652 additions and 2 deletions

View File

@@ -0,0 +1,45 @@
using Microsoft.AspNetCore.Mvc;
using Modelo;
[ApiController]
public class CargarContratoAdminController: ControllerBase{
[HttpGet("api/admin/contrato/data")]
public IActionResult GetData([FromHeader(Name ="Auth")]string Auth) {
var cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return BadRequest(new { message = "No hay usuario por ese token"});
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 20);
if (validacion1 == false) return Unauthorized();
var divisas = RepositorioDivisas.Singleton.ObtenerDivisas();
var propiedades = RepositorioPropiedades.Singleton.ListarPropiedades().ToList()
.Select(x=> new {id = x.id,
ubicacion = x.Ubicacion});
var inquilinos = RepositorioInquilinos.Singleton.GetInquilinos().ToList()
.Select(x=>new {dni=x.Dni, nombre = x.Nombre});
var propietarios = RepositorioPropietario.Singleton.GetPropietarios().ToList()
.Select(x=>new {dni=x.Dni, nombre = x.Nombre});
return Ok(new {divisas,
propiedades,
inquilinos,
propietarios});
}
[HttpGet("api/admin/contrato/propieades")]
public IActionResult GetPropiedadesPorPropietario([FromHeader(Name ="Auth")]string Auth, long dnipropietario){
var cli = RepositorioUsuarios.Singleton.ObtenerClientePorToken(Auth);
if (cli == null) return BadRequest(new { message = "No hay usuario por ese token"});
var validacion1 = RepositorioPermisos.Singleton.CheckPermisos(Auth, 20);
if (validacion1 == false) return Unauthorized();
var propiedades = RepositorioPropiedades.Singleton.ObtenerPropiedadEnAlquilerPorDni(dnipropietario);
return Ok(propiedades);
}
}

View File

@@ -0,0 +1,6 @@
namespace Entidades.Dto;
public class PropietarioDto{
public string Nombre {get; set;} = "";
public long Dni {get; set;}
public string Apellido {get; set;} = "";
}

View File

@@ -35,6 +35,7 @@
import GestionPemisos from "./paginas/GestionPemisos.svelte"; import GestionPemisos from "./paginas/GestionPemisos.svelte";
import UsuarioPanel from "./paginas/UsuarioPanel.svelte"; import UsuarioPanel from "./paginas/UsuarioPanel.svelte";
import CrearUsuario from "./paginas/CrearUsuario.svelte"; import CrearUsuario from "./paginas/CrearUsuario.svelte";
import CargarContratoAdmin from "./paginas/CargarContratoAdmin.svelte";
</script> </script>
<Router> <Router>
@@ -147,6 +148,10 @@
<ProteRoute componente={CrearUsuario} /> <ProteRoute componente={CrearUsuario} />
</Route> </Route>
<!-- Cargar Contrato Admin -->
<Route path="/accion/20">
<ProteRoute componente={CargarContratoAdmin}/>
</Route>
<!-- Pagina Ventas --> <!-- Pagina Ventas -->
<Route path="/Ventas"> <Route path="/Ventas">

View File

@@ -0,0 +1,568 @@
<script>
import { onMount } from 'svelte';
import NavBarAutocompletable from '../Componentes/NavBarAutocompletable.svelte';
import { urlG } from '../stores/urlStore';
import ModalEstatico from '../Componentes/ModalEstatico.svelte';
let contrato = $state({
id: 0,
cantgarantemin: 0,
dniinquilino: 0n,
dnipropietario: 0n,
iddivisa: 0,
idpropiedad: 0,
idventa: 0n,
indiceactualizacion: 0,
mesesDurationContrato: 0,
mesesHastaAumento: 0,
monto: 0,
tieneopcionventa: false,
archivoContrato: null,
divisaOpcionVenta: 0,
montoOpcionVenta: 0,
garantes: []
});
let modaldata = $state("");
let token = sessionStorage.getItem("token");
let busquedaDivisa = $state('');
let busquedaDivisaOpVenta = $state('');
let busquedaPropiedad = $state('');
let busquedaInquilino = $state('');
let busquedaPropietario = $state('');
let divisas = $state([]);
let propiedades = $state([]);
let inquilinos = $state([]);
let propietarios = $state([]);
$effect(() => {
const currentLength = contrato.garantes.length;
if (contrato.cantgarantemin > currentLength) {
// Agregar garantes faltantes
for (let i = currentLength; i < contrato.cantgarantemin; i++) {
contrato.garantes = [...contrato.garantes, {
dni: '',
nombre: '',
apellido: '',
domicilio: '',
celular: '',
domicilioLaboral: ''
}];
}
} else if (contrato.cantgarantemin < currentLength) {
// Remover garantes excedentes
contrato.garantes = contrato.garantes.slice(0, contrato.cantgarantemin);
}
});
onMount(async () => {
obtenerDatos();
});
async function obtenerDatos(){
try{
const req = await fetch($urlG + "/api/admin/contrato/data", {
method: "GET",
headers: {
"Auth": token || "",
}
});
const data = await req.json();
if (req.ok){
({ divisas, propiedades, inquilinos, propietarios } = data);
return;
}
modaldata = data.message;
}catch{
modaldata = "Fallo la request";
}
}
function handleFileChange(event) {
const file = event.target.files[0];
if (file) {
contrato.archivoContrato = file;
}
}
let divisasFiltradas = $derived(
divisas.filter(d =>
!busquedaDivisa ||
d.signo?.toLowerCase().includes(busquedaDivisa.toLowerCase()) ||
d.id.toString().includes(busquedaDivisa)
)
);
let divisasFiltradasOpVenta = $derived(
divisas.filter(d =>
!busquedaDivisaOpVenta ||
d.signo?.toLowerCase().includes(busquedaDivisaOpVenta.toLowerCase()) ||
d.id.toString().includes(busquedaDivisaOpVenta)
)
);
let propiedadesFiltradas = $derived(
propiedades.filter(p =>
!busquedaPropiedad ||
p.ubicacion?.toLowerCase().includes(busquedaPropiedad.toLowerCase()) ||
p.id.toString().includes(busquedaPropiedad)
)
);
let inquilinosFiltrados = $derived(
inquilinos.filter(i =>
!busquedaInquilino ||
i.nombre?.toLowerCase().includes(busquedaInquilino.toLowerCase()) ||
i.dni.toString().includes(busquedaInquilino)
)
);
let propietariosFiltrados = $derived(
propietarios.filter(p =>
!busquedaPropietario ||
p.nombre?.toLowerCase().includes(busquedaPropietario.toLowerCase()) ||
p.dni.toString().includes(busquedaPropietario)
)
);
async function handleSubmit(e) {
e.preventDefault();
const formData = new FormData();
formData.append('cantgarantemin', contrato.cantgarantemin.toString());
formData.append('dniinquilino', contrato.dniinquilino.toString());
formData.append('dnipropietario', contrato.dnipropietario.toString());
formData.append('iddivisa', contrato.iddivisa.toString());
formData.append('idpropiedad', contrato.idpropiedad.toString());
formData.append('idventa', contrato.idventa.toString());
formData.append('indiceactualizacion', contrato.indiceactualizacion.toString());
formData.append('mesesDurationContrato', contrato.mesesDurationContrato.toString());
formData.append('mesesHastaAumento', contrato.mesesHastaAumento.toString());
formData.append('monto', contrato.monto.toString());
formData.append('tieneopcionventa', contrato.tieneopcionventa.toString());
contrato.garantes.forEach((garante, index) => {
formData.append(`garantes[${index}].dni`, garante.dni);
formData.append(`garantes[${index}].nombre`, garante.nombre);
formData.append(`garantes[${index}].apellido`, garante.apellido);
formData.append(`garantes[${index}].domicilio`, garante.domicilio);
formData.append(`garantes[${index}].celular`, garante.celular);
formData.append(`garantes[${index}].domicilioLaboral`, garante.domicilioLaboral);
});
if (contrato.tieneopcionventa) {
formData.append('divisaOpcionVenta', contrato.divisaOpcionVenta.toString());
formData.append('montoOpcionVenta', contrato.montoOpcionVenta.toString());
}
// Agregar el archivo si existe
if (contrato.archivoContrato) {
formData.append('archivoContrato', contrato.archivoContrato);
}
try {
const response = await fetch('/api/contratos', {
method: 'POST',
headers: {
"Auth": token || "",
},
body: formData
});
if (response.ok) {
alert('Contrato creado exitosamente');
contrato = {
id: 0,
cantgarantemin: 0,
dniinquilino: 0n,
dnipropietario: 0n,
iddivisa: 0,
idpropiedad: 0,
idventa: 0n,
indiceactualizacion: 0,
mesesDurationContrato: 0,
mesesHastaAumento: 0,
monto: 0,
tieneopcionventa: false,
archivoContrato: null
};
} else {
alert('Error al crear contrato');
}
} catch (error) {
modaldata = "Fallo al hacer la request";
}
}
async function actualizarPropiedades(dnipropietario){
try{
const req = await fetch($urlG + "/api/admin/contrato/propieades?dnipropietario="+ dnipropietario, {
method: "GET",
headers:{
"Auth": token || "",
}
});
const data = await req.json();
if (req.ok){
propiedades = data;
return;
}
modaldata = data.message;
}catch{
modaldata = "Fallo al hacer la request";
}
}
function actualizarGarante(index, campo, valor) {
contrato.garantes[index] = { ...contrato.garantes[index], [campo]: valor };
}
</script>
<NavBarAutocompletable/>
{#if modaldata}
<ModalEstatico payload={modaldata} close={()=>!!(modaldata = "")}/>
{/if}
<div class="container mt-4">
<h2>Alta de Contrato</h2>
<form onsubmit={handleSubmit}>
<div class="row mb-3">
<label for="dniinquilino" class="col-sm-3 col-form-label">Inquilino</label>
<div class="col-sm-9">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Buscar inquilino (DNI o nombre)..."
bind:value={busquedaInquilino}
/>
<select
class="form-select"
id="dniinquilino"
bind:value={contrato.dniinquilino}
required
>
<option value="">Seleccionar Inquilino...</option>
{#each inquilinosFiltrados as inq}
<option value={inq.dni}>{inq.nombre} | {inq.dni}</option>
{/each}
</select>
</div>
</div>
</div>
<div class="row mb-3">
<label for="dnipropietario" class="col-sm-3 col-form-label">Propietario</label>
<div class="col-sm-9">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Buscar propietario (DNI o nombre)..."
bind:value={busquedaPropietario}
/>
<select
class="form-select"
id="dnipropietario"
bind:value={contrato.dnipropietario}
required
onchange={()=>actualizarPropiedades(contrato.dnipropietario)}
>
<option value="">Seleccionar Propietario...</option>
{#each propietariosFiltrados as prop}
<option value={prop.dni}>{prop.nombre} | {prop.dni}</option>
{/each}
</select>
</div>
</div>
</div>
<div class="row mb-3">
<label for="monto" class="col-sm-3 col-form-label">Monto del Contrato</label>
<div class="col-sm-9">
<input
type="number"
step="0.01"
min="1"
class="form-control"
id="monto"
bind:value={contrato.monto}
required
/>
</div>
</div>
<div class="row mb-3">
<label for="mesesDurationContrato" class="col-sm-3 col-form-label">Duración (meses)</label>
<div class="col-sm-9">
<input
type="number"
min="1"
class="form-control"
id="mesesDurationContrato"
bind:value={contrato.mesesDurationContrato}
required
/>
</div>
</div>
<div class="row mb-3">
<label for="mesesHastaAumento" class="col-sm-3 col-form-label">Meses hasta Aumento</label>
<div class="col-sm-9">
<input
type="number"
min="1"
class="form-control"
id="mesesHastaAumento"
bind:value={contrato.mesesHastaAumento}
/>
</div>
</div>
<div class="row mb-3">
<label for="indiceactualizacion" class="col-sm-3 col-form-label">Índice de Actualización</label>
<div class="col-sm-9">
<input
type="number"
step="0.01"
min="0"
class="form-control"
id="indiceactualizacion"
bind:value={contrato.indiceactualizacion}
/>
</div>
</div>
<div class="row mb-3">
<label for="cantgarantemin" class="col-sm-3 col-form-label">Cantidad Garantes Mínimos</label>
<div class="col-sm-9">
<input
type="number"
min="0"
max="100"
class="form-control"
id="cantgarantemin"
bind:value={contrato.cantgarantemin}
/>
</div>
</div>
{#if contrato.cantgarantemin > 0}
<div class="row mb-3">
<div class="col-12">
<h5>Garantes</h5>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>DNI</th>
<th>Nombre</th>
<th>Apellido</th>
<th>Domicilio</th>
<th>Celular</th>
<th>Domicilio Laboral</th>
</tr>
</thead>
<tbody>
{#each contrato.garantes as garante, i}
<tr>
<td>
<input
type="text"
class="form-control"
placeholder="DNI"
min="0"
max="99999999"
bind:value={garante.dni}
oninput={(e) => actualizarGarante(i, 'dni', e.target.value)}
/>
</td>
<td>
<input
type="text"
class="form-control"
minlength="1"
placeholder="Nombre"
bind:value={garante.nombre}
oninput={(e) => actualizarGarante(i, 'nombre', e.target.value)}
/>
</td>
<td>
<input
type="text"
class="form-control"
placeholder="Apellido"
bind:value={garante.apellido}
oninput={(e) => actualizarGarante(i, 'apellido', e.target.value)}
/>
</td>
<td>
<input
type="text"
class="form-control"
placeholder="Domicilio"
bind:value={garante.domicilio}
oninput={(e) => actualizarGarante(i, 'domicilio', e.target.value)}
/>
</td>
<td>
<input
type="text"
class="form-control"
placeholder="Celular"
bind:value={garante.celular}
oninput={(e) => actualizarGarante(i, 'celular', e.target.value)}
/>
</td>
<td>
<input
type="text"
class="form-control"
placeholder="Domicilio Laboral"
bind:value={garante.domicilioLaboral}
oninput={(e) => actualizarGarante(i, 'domicilioLaboral', e.target.value)}
/>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
</div>
</div>
{/if}
<div class="row mb-3">
<label for="archivoContrato" class="col-sm-3 col-form-label">Archivo del Contrato</label>
<div class="col-sm-9">
<input
type="file"
class="form-control"
id="archivoContrato"
accept=".pdf,.doc,.docx,.jpg,.jpeg,.png"
onchange={handleFileChange}
/>
{#if contrato.archivoContrato}
<small class="text-muted">Archivo seleccionado: {contrato.archivoContrato.name}</small>
{/if}
</div>
</div>
<div class="row mb-3">
<label for="iddivisa" class="col-sm-3 col-form-label">Divisa</label>
<div class="col-sm-9">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Buscar divisa..."
bind:value={busquedaDivisa}
/>
<select
class="form-select"
id="iddivisa"
bind:value={contrato.iddivisa}
required
>
<option value="">Seleccionar Divisa...</option>
{#each divisasFiltradas as divisa}
<option value={divisa.id}>{divisa.signo}</option>
{/each}
</select>
</div>
</div>
</div>
<div class="row mb-3">
<label for="idpropiedad" class="col-sm-3 col-form-label">Propiedad</label>
<div class="col-sm-9">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Buscar propiedad (ID o dirección)..."
bind:value={busquedaPropiedad}
/>
<select
class="form-select"
id="idpropiedad"
bind:value={contrato.idpropiedad}
required
>
<option value="">Seleccionar Propiedad...</option>
{#each propiedadesFiltradas as propiedad}
<option value={propiedad.id}>{propiedad.id} - {propiedad.ubicacion}</option>
{/each}
</select>
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-sm-9 offset-sm-3">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
bind:checked={contrato.tieneopcionventa}
id="tieneopcionventa"
/>
<label class="form-check-label" for="tieneopcionventa">
Tiene Opción de Venta
</label>
</div>
</div>
</div>
{#if contrato.tieneopcionventa}
<div class="row mb-3">
<label for="divisaOpcionVenta" class="col-sm-3 col-form-label">Divisa Opción Venta</label>
<div class="col-sm-9">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Buscar divisa..."
bind:value={busquedaDivisaOpVenta}
/>
<select
class="form-select"
id="divisaOpcionVenta"
bind:value={contrato.divisaOpcionVenta}
required
>
<option value="">Seleccionar Divisa...</option>
{#each divisasFiltradasOpVenta as divisa}
<option value={divisa.id}>{divisa.signo}</option>
{/each}
</select>
</div>
</div>
</div>
<div class="row mb-3">
<label for="montoOpcionVenta" class="col-sm-3 col-form-label">Monto Opción Venta</label>
<div class="col-sm-9">
<input
type="number"
step="0.01"
class="form-control"
id="montoOpcionVenta"
bind:value={contrato.montoOpcionVenta}
required
/>
</div>
</div>
{/if}
<div class="row mb-3">
<div class="col-sm-9 offset-sm-3">
<button type="submit" class="btn btn-primary">Guardar Contrato</button>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,10 @@
using Entidades;
namespace Modelo;
public class RepositorioDivisas: RepositorioBase<RepositorioDivisas> {
public List<Divisa> ObtenerDivisas(){
var con = Context;
var divisas = con.Divisas.ToList();
return divisas;
}
}

View File

@@ -11,6 +11,12 @@ using MySql.Data.MySqlClient;
public class RepositorioPropiedades : RepositorioBase<RepositorioPropiedades> public class RepositorioPropiedades : RepositorioBase<RepositorioPropiedades>
{ {
public List<Propiedade> ObtenerPropiedadEnAlquilerPorDni(long dni){
var con = Context;
var propiedades = con.Propiedades.Where(x=>x.Dnipropietario == dni && x.Idestado == 1).ToList();
return propiedades;
}
public IQueryable<PropiedadesDto> ListarPropiedades() public IQueryable<PropiedadesDto> ListarPropiedades()
{ {
FormattableString sqlq = $""" FormattableString sqlq = $"""

View File

@@ -1,10 +1,20 @@
using System;
using Entidades; using Entidades;
using Entidades.Dto;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Modelo; using Modelo;
public class RepositorioPropietario: RepositorioBase<RepositorioPropietario> { public class RepositorioPropietario: RepositorioBase<RepositorioPropietario> {
public IQueryable<PropietarioDto> GetPropietarios() {
FormattableString sqlq =
$"""
SELECT I.Dni, I.Nombre, I.Apellido FROM Clientes I
JOIN cliente_Grupos cg on cg.idcliente = I.Dni
WHERE cg.idgrupo = 1;
""";
return Context.Database.SqlQuery<PropietarioDto>(sqlq);
}
public Cliente? ObtenerPropietarioPorDni(long Dni){ public Cliente? ObtenerPropietarioPorDni(long Dni){
if (Dni < 1) return null; if (Dni < 1) return null;