1502 lines
63 KiB
Plaintext
1502 lines
63 KiB
Plaintext
@page "/Pendientes"
|
||
@rendermode InteractiveServer
|
||
@attribute [Authorize]
|
||
|
||
@using GestionaDenuncias.Shared.Models
|
||
@using System.Globalization
|
||
@using System.IO
|
||
@using System.Linq
|
||
@using System.Text
|
||
|
||
@using GestionaDenuncias.Shared.Helpers
|
||
@using GestionaDenunciasAN.Services
|
||
|
||
@attribute [StreamRendering]
|
||
|
||
@inject GestionaDenunciasAN.Models.UserState userState
|
||
@inject NavigationManager Navigation
|
||
@inject IHostEnvironment HostEnvironment
|
||
@inject IDenunciaStore DenunciaStore
|
||
@inject ApiDenunciasClient ApiDenuncias
|
||
@inject UiBusyService Busy
|
||
|
||
<PageTitle>Denuncias Pendientes</PageTitle>
|
||
|
||
<style>
|
||
.seleccionar-col {
|
||
width: 50px;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.pendientes-list {
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.collapse-card {
|
||
margin-bottom: 1rem;
|
||
border: 1px solid #ccc;
|
||
border-radius: 6px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
overflow: hidden;
|
||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||
background-color: #fff;
|
||
}
|
||
|
||
.collapse-card:hover {
|
||
transform: scale(1.02);
|
||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||
}
|
||
|
||
.collapse-card .card-header {
|
||
padding: 0.75rem 1.25rem;
|
||
cursor: pointer;
|
||
background-color: #f7f7f7;
|
||
transition: background-color 0.3s ease;
|
||
}
|
||
|
||
.collapse-card .card-header:hover {
|
||
background-color: #e2e2e2;
|
||
}
|
||
|
||
.section-heading {
|
||
text-align: center;
|
||
font-weight: bold;
|
||
text-decoration: underline;
|
||
font-size: 1.1em;
|
||
margin: 1rem 0 0.5rem;
|
||
}
|
||
|
||
.custom-modal {
|
||
background: rgba(0, 0, 0, 0.5);
|
||
}
|
||
|
||
.custom-modal-dialog {
|
||
max-width: 500px;
|
||
margin: 2rem auto;
|
||
}
|
||
|
||
.custom-modal-content {
|
||
border-radius: 0.5rem;
|
||
box-shadow: 0 5px 15px rgba(0,0,0,0.5);
|
||
border: none;
|
||
}
|
||
|
||
.custom-modal-header {
|
||
background-color: #007bff;
|
||
color: white;
|
||
border-top-left-radius: 0.5rem;
|
||
border-top-right-radius: 0.5rem;
|
||
padding: 1rem;
|
||
}
|
||
|
||
.custom-modal-body {
|
||
padding: 1.5rem;
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
.custom-modal-footer {
|
||
border-top: none;
|
||
padding: 1rem;
|
||
}
|
||
|
||
.modal-section-heading {
|
||
font-weight: bold;
|
||
font-size: 1.1em;
|
||
margin-bottom: 0.5rem;
|
||
border-bottom: 2px solid #007bff;
|
||
padding-bottom: 0.25rem;
|
||
}
|
||
|
||
.custom-file-list .list-group-item {
|
||
transition: background-color 0.2s ease;
|
||
cursor: pointer;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.custom-file-list .list-group-item:hover {
|
||
background-color: #e9ecef;
|
||
}
|
||
|
||
.custom-file-list .list-group-item.active {
|
||
background-color: #007bff;
|
||
color: white;
|
||
border-color: #007bff;
|
||
}
|
||
|
||
.preselect-btn {
|
||
background: none;
|
||
border: none;
|
||
padding: 0;
|
||
margin: 0;
|
||
font-size: 1.2rem;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.preselect-btn i {
|
||
transition: color 0.3s ease;
|
||
}
|
||
|
||
.preselect-btn.selected i {
|
||
color: #28a745;
|
||
}
|
||
|
||
.preselect-btn:not(.selected) i {
|
||
color: #6c757d;
|
||
}
|
||
|
||
/* Modal expedientes a la derecha en pantallas grandes */
|
||
.expedientes-modal .modal-dialog {
|
||
margin-left: auto;
|
||
margin-right: 2rem;
|
||
}
|
||
</style>
|
||
|
||
<h1>Denuncias Pendientes</h1>
|
||
|
||
@if (!string.IsNullOrWhiteSpace(loadError))
|
||
{
|
||
<div class="alert alert-danger">@loadError</div>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(operationNotice))
|
||
{
|
||
<div class="alert alert-warning">@operationNotice</div>
|
||
}
|
||
|
||
<input type="text"
|
||
class="form-control"
|
||
placeholder="Buscar denuncias..."
|
||
@bind="busqueda"
|
||
@bind:event="oninput"
|
||
style="margin-bottom:20px;" />
|
||
|
||
@if (!hasLoaded)
|
||
{
|
||
<div class="alert alert-info">Cargando datos...</div>
|
||
}
|
||
else if (pendientes == null || !pendientes.Any())
|
||
{
|
||
<p>No hay denuncias pendientes.</p>
|
||
}
|
||
else
|
||
{
|
||
<div class="pendientes-list">
|
||
@foreach (var denuncia in pendientes.Where(d =>
|
||
string.IsNullOrWhiteSpace(busqueda) ||
|
||
d.Id_Denuncia.ToString().Contains(busqueda) ||
|
||
(!string.IsNullOrEmpty(d.Asunto) && d.Asunto.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||
(!string.IsNullOrEmpty(d.Nombre) && d.Nombre.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||
(!string.IsNullOrEmpty(d.Apellidos) && d.Apellidos.Contains(busqueda, StringComparison.OrdinalIgnoreCase)) ||
|
||
(!string.IsNullOrEmpty(d.RazonSocial) && d.RazonSocial.Contains(busqueda, StringComparison.OrdinalIgnoreCase))
|
||
))
|
||
{
|
||
var collapseId = $"collapse{denuncia.Id_Denuncia}";
|
||
<div class="card mb-2 collapse-card">
|
||
<div class="card-header d-flex justify-content-between align-items-center"
|
||
data-bs-toggle="collapse"
|
||
data-bs-target="#@collapseId"
|
||
aria-expanded="false"
|
||
aria-controls="@collapseId">
|
||
<h5 class="mb-0">Denuncia ID: @denuncia.Id_Denuncia</h5>
|
||
<div>
|
||
<button type="button"
|
||
class="btn btn-success btn-sm me-2"
|
||
@onclick:stopPropagation="true"
|
||
@onclick="() => OpenEnviarAGestionaModal(denuncia)">
|
||
Configurar subida
|
||
</button>
|
||
|
||
<!-- Enviar a Actualizaciones -->
|
||
<button type="button"
|
||
class="btn btn-outline-warning btn-sm me-2"
|
||
title="Mover esta denuncia a la cola de Actualizaciones"
|
||
@onclick:stopPropagation="true"
|
||
@onclick="() => MoverAActualizaciones(denuncia)">
|
||
Enviar a Actualizaciones
|
||
</button>
|
||
|
||
<button type="button"
|
||
class="btn btn-danger btn-sm"
|
||
@onclick:stopPropagation="true"
|
||
@onclick="() => OpenRechazarModal(denuncia)">
|
||
Rechazar denuncia
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="@collapseId" class="collapse">
|
||
<div class="card-body">
|
||
<h5 class="section-heading">Datos Generales</h5>
|
||
<dl class="row">
|
||
@if (denuncia.Id_RegistroDenuncia != 0)
|
||
{
|
||
<dt class="col-sm-3">ID Registro Denuncia</dt>
|
||
<dd class="col-sm-9">@denuncia.Id_RegistroDenuncia</dd>
|
||
}
|
||
@if (denuncia.Id_Denuncia != 0)
|
||
{
|
||
<dt class="col-sm-3">ID Denuncia</dt>
|
||
<dd class="col-sm-9">@denuncia.Id_Denuncia</dd>
|
||
}
|
||
@if (denuncia.Fecha != DateTime.MinValue)
|
||
{
|
||
<dt class="col-sm-3">Fecha</dt>
|
||
<dd class="col-sm-9">@denuncia.Fecha.ToString("dd/MM/yyyy HH:mm")</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.ExpedienteGestionaMostrable))
|
||
{
|
||
<dt class="col-sm-3">N<> expediente Gestiona</dt>
|
||
<dd class="col-sm-9">@denuncia.ExpedienteGestionaMostrable</dd>
|
||
}
|
||
@if (denuncia.Id_Persona_Gestiona != 0)
|
||
{
|
||
<dt class="col-sm-3">ID Persona Gestiona</dt>
|
||
<dd class="col-sm-9">@denuncia.Id_Persona_Gestiona</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Etiqueta))
|
||
{
|
||
<dt class="col-sm-3">Etiqueta</dt>
|
||
<dd class="col-sm-9">@denuncia.Etiqueta</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Estado))
|
||
{
|
||
<dt class="col-sm-3">Estado</dt>
|
||
<dd class="col-sm-9">@denuncia.Estado</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Tipo_Denuncia))
|
||
{
|
||
<dt class="col-sm-3">Tipo Denuncia</dt>
|
||
<dd class="col-sm-9">@denuncia.Tipo_Denuncia</dd>
|
||
}
|
||
</dl>
|
||
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.NombreResuelto) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.ApellidosResueltos) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.RazonSocialResuelta) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.Sexo) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.DocumentoResuelto))
|
||
{
|
||
<h5 class="section-heading">Datos del Denunciante</h5>
|
||
<dl class="row">
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.TipoDenunciante))
|
||
{
|
||
<dt class="col-sm-3">Tipo de denunciante</dt>
|
||
<dd class="col-sm-9">@denuncia.TipoDenunciante</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.RazonSocialResuelta))
|
||
{
|
||
<dt class="col-sm-3">Raz<61>n social</dt>
|
||
<dd class="col-sm-9">@denuncia.RazonSocialResuelta</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.NombreResuelto))
|
||
{
|
||
<dt class="col-sm-3">Nombre</dt>
|
||
<dd class="col-sm-9">@denuncia.NombreResuelto</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.PrimerApellidoResuelto))
|
||
{
|
||
<dt class="col-sm-3">1<> Apellido</dt>
|
||
<dd class="col-sm-9">@denuncia.PrimerApellidoResuelto</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.SegundoApellidoResuelto))
|
||
{
|
||
<dt class="col-sm-3">2<> Apellido</dt>
|
||
<dd class="col-sm-9">@denuncia.SegundoApellidoResuelto</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.ApellidosResueltos))
|
||
{
|
||
<dt class="col-sm-3">Apellidos</dt>
|
||
<dd class="col-sm-9">@denuncia.ApellidosResueltos</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Sexo))
|
||
{
|
||
<dt class="col-sm-3">Sexo</dt>
|
||
<dd class="col-sm-9">@denuncia.Sexo</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.DocumentoResuelto))
|
||
{
|
||
<dt class="col-sm-3">@GetDocumentoLabel(denuncia)</dt>
|
||
<dd class="col-sm-9">@denuncia.DocumentoResuelto</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.PaisOrigen))
|
||
{
|
||
<dt class="col-sm-3">Pa<50>s de origen</dt>
|
||
<dd class="col-sm-9">@denuncia.PaisOrigen</dd>
|
||
}
|
||
</dl>
|
||
}
|
||
|
||
<h5 class="section-heading">Detalles de la Denuncia</h5>
|
||
<dl class="row">
|
||
<dt class="col-sm-3">Asunto</dt>
|
||
<dd class="col-sm-9">@denuncia.Asunto</dd>
|
||
<dt class="col-sm-3">A Quien Denuncia</dt>
|
||
<dd class="col-sm-9">@denuncia.A_Quien_Denuncia</dd>
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.DenunciadoDetalle))
|
||
{
|
||
<dt class="col-sm-3">Detalle denunciado</dt>
|
||
<dd class="col-sm-9">@denuncia.DenunciadoDetalle</dd>
|
||
}
|
||
<dt class="col-sm-3">Descripci<63>n Denuncia</dt>
|
||
<dd class="col-sm-9">@denuncia.Descripcion_Denuncia</dd>
|
||
<dt class="col-sm-3">Denunciado Ante Inst</dt>
|
||
<dd class="col-sm-9">@denuncia.Denunciado_Ante_Inst</dd>
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.OrganismoDenunciado))
|
||
{
|
||
<dt class="col-sm-3">Organismo previo</dt>
|
||
<dd class="col-sm-9">@denuncia.OrganismoDenunciado</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.SolicitaProteccion))
|
||
{
|
||
<dt class="col-sm-3">Solicita protecci<63>n</dt>
|
||
<dd class="col-sm-9">@denuncia.SolicitaProteccion</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.MedidasProteccionSolicitadas))
|
||
{
|
||
<dt class="col-sm-3">Medidas solicitadas</dt>
|
||
<dd class="col-sm-9">@denuncia.MedidasProteccionSolicitadas</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Modalidad_Informacion))
|
||
{
|
||
<dt class="col-sm-3">Modalidad Informaci<63>n</dt>
|
||
<dd class="col-sm-9">@denuncia.Modalidad_Informacion</dd>
|
||
}
|
||
<dt class="col-sm-3">Lugar Hechos</dt>
|
||
<dd class="col-sm-9">@denuncia.Lugar_Hechos</dd>
|
||
@if (denuncia.Fecha_Hechos != DateTime.MinValue)
|
||
{
|
||
<dt class="col-sm-3">Fecha Hechos</dt>
|
||
<dd class="col-sm-9">@denuncia.Fecha_Hechos.ToString("dd/MM/yyyy")</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.AutorizaRemision))
|
||
{
|
||
<dt class="col-sm-3">Autoriza remisi<73>n</dt>
|
||
<dd class="col-sm-9">@denuncia.AutorizaRemision</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.PreferenciaRemision))
|
||
{
|
||
<dt class="col-sm-3">Datos al remitir</dt>
|
||
<dd class="col-sm-9">@denuncia.PreferenciaRemision</dd>
|
||
}
|
||
</dl>
|
||
|
||
<h5 class="section-heading">Datos de Notificaci<63>n</h5>
|
||
<dl class="row">
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Preferencia))
|
||
{
|
||
<dt class="col-sm-3">Notificaci<63>n Preferencia</dt>
|
||
<dd class="col-sm-9">@denuncia.Notificacion_Preferencia</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Electronica))
|
||
{
|
||
<dt class="col-sm-3">Notificaci<63>n Electr<74>nica</dt>
|
||
<dd class="col-sm-9">@denuncia.Notificacion_Electronica</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.SeguimientoOnline))
|
||
{
|
||
<dt class="col-sm-3">Seguimiento Online</dt>
|
||
<dd class="col-sm-9">@denuncia.SeguimientoOnline</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.NotificacionPostal))
|
||
{
|
||
<dt class="col-sm-3">Correo Postal</dt>
|
||
<dd class="col-sm-9">@denuncia.NotificacionPostal</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Correo_Electronico))
|
||
{
|
||
<dt class="col-sm-3">Correo Electr<74>nico</dt>
|
||
<dd class="col-sm-9">@denuncia.Correo_Electronico</dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Notificacion_Sms))
|
||
{
|
||
<dt class="col-sm-3">Notificaci<63>n SMS</dt>
|
||
<dd class="col-sm-9">@denuncia.Notificacion_Sms</dd>
|
||
}
|
||
@if (HasPostalAddress(denuncia))
|
||
{
|
||
<dt class="col-sm-3">Direcci<63>n postal</dt>
|
||
<dd class="col-sm-9">@BuildPostalAddressSummary(denuncia)</dd>
|
||
}
|
||
</dl>
|
||
|
||
<h5 class="section-heading">Otros</h5>
|
||
<dl class="row">
|
||
@if (denuncia.Condiciones)
|
||
{
|
||
<dt class="col-sm-3">Condiciones</dt>
|
||
<dd class="col-sm-9">S<></dd>
|
||
}
|
||
@if (!string.IsNullOrWhiteSpace(denuncia.Comments))
|
||
{
|
||
<dt class="col-sm-3">Comentarios</dt>
|
||
<dd class="col-sm-9"><pre>@denuncia.Comments</pre></dd>
|
||
}
|
||
</dl>
|
||
|
||
@{
|
||
var camposFormulario = denuncia.GetCamposFormulario();
|
||
}
|
||
@if (camposFormulario.Count > 0)
|
||
{
|
||
<h5 class="section-heading">Formulario Original</h5>
|
||
@foreach (var grupoCampos in camposFormulario.GroupBy(field => string.IsNullOrWhiteSpace(field.Section) ? "Sin secci<63>n" : field.Section))
|
||
{
|
||
<h6 class="mt-3">@grupoCampos.Key</h6>
|
||
<dl class="row">
|
||
@foreach (var campo in grupoCampos)
|
||
{
|
||
<dt class="col-sm-4">@campo.Label</dt>
|
||
<dd class="col-sm-8">@(string.IsNullOrWhiteSpace(campo.Value) ? "<22>" : campo.Value)</dd>
|
||
}
|
||
</dl>
|
||
}
|
||
}
|
||
|
||
@if (ficherosAdjuntos.ContainsKey(denuncia.Id_Denuncia) && ficherosAdjuntos[denuncia.Id_Denuncia].Any())
|
||
{
|
||
<h5 class="section-heading">Ficheros Adjuntos</h5>
|
||
<table class="table table-striped">
|
||
<thead>
|
||
<tr>
|
||
<th class="seleccionar-col">Subir</th>
|
||
<th>Nombre</th>
|
||
<th>Fecha</th>
|
||
<th>Tama<6D>o (bytes)</th>
|
||
<th>Ver</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach (var fichero in ficherosAdjuntos[denuncia.Id_Denuncia])
|
||
{
|
||
var isReport = IsReportFileName(fichero.NombreFichero);
|
||
<tr>
|
||
<td class="seleccionar-col">
|
||
<input class="form-check-input"
|
||
type="checkbox"
|
||
checked="@IsFileSelectedForUpload(denuncia.Id_Denuncia, fichero.NombreFichero)"
|
||
disabled="@isReport"
|
||
title='@(isReport ? "El report se sube siempre" : "Incluir este fichero en la subida")'
|
||
@onchange="args => ToggleFileSelection(denuncia.Id_Denuncia, fichero.NombreFichero, args.Value is bool selected && selected)" />
|
||
</td>
|
||
<td>
|
||
@fichero.NombreFichero
|
||
@if (isReport)
|
||
{
|
||
<span class="badge bg-primary ms-2">Obligatorio</span>
|
||
}
|
||
</td>
|
||
<td>@FormatFileDate(fichero.Fecha)</td>
|
||
<td>@fichero.Fichero.Length</td>
|
||
<td>
|
||
<a class="btn btn-primary btn-sm" href="@BuildAttachmentContentUrl(denuncia.Id_Denuncia, fichero.NombreFichero)" target="_blank" rel="noopener">
|
||
<i class="bi bi-eye"></i> Ver
|
||
</a>
|
||
</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
}
|
||
</div>
|
||
}
|
||
|
||
<script>
|
||
function createObjectUrl(base64, contentType) {
|
||
const binaryString = window.atob(base64);
|
||
const len = binaryString.length;
|
||
const bytes = new Uint8Array(len);
|
||
for (let i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); }
|
||
const blob = new Blob([bytes], { type: contentType });
|
||
return URL.createObjectURL(blob);
|
||
}
|
||
function openFile(event, base64, contentType) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
const objectUrl = createObjectUrl(base64, contentType);
|
||
window.open(objectUrl, '_blank');
|
||
}
|
||
</script>
|
||
|
||
@if (showModal && selectedDenuncias != null)
|
||
{
|
||
<div class="modal custom-modal fade show"
|
||
style="display:block;" tabindex="-1">
|
||
<div class="modal-dialog custom-modal-dialog">
|
||
<div class="modal-content custom-modal-content">
|
||
<div class="modal-header custom-modal-header">
|
||
<h5 class="modal-title">Enviar a Gestiona</h5>
|
||
<button type="button" class="btn-close" @onclick="CloseModal"></button>
|
||
</div>
|
||
<div class="modal-body custom-modal-body">
|
||
@if (!string.IsNullOrWhiteSpace(operationError))
|
||
{
|
||
<div class="alert alert-danger" role="alert">
|
||
@operationError
|
||
</div>
|
||
}
|
||
|
||
<h6 class="modal-section-heading">Descripci<63>n</h6>
|
||
<div class="mb-3">
|
||
<input type="text"
|
||
class="form-control"
|
||
@bind="nuevoAsunto"
|
||
placeholder="Ingrese el nombre de la denuncia" />
|
||
</div>
|
||
|
||
<h6 class="modal-section-heading">Nombre de los documentos</h6>
|
||
<div class="mb-3">
|
||
<input type="text"
|
||
class="form-control"
|
||
@bind="nombreDocumentos"
|
||
placeholder="Ej.: Gesti<74>n AN (lo ver<65>s como: Documento Adjunto 1 Gesti<74>n AN, ...)" />
|
||
<small class="text-muted">
|
||
Se aplicar<61> al subir en modo <strong>individual</strong>. El <em>report.txt</em> se subir<69> como <strong>Denuncia</strong>.
|
||
</small>
|
||
</div>
|
||
|
||
<h6 class="modal-section-heading">Modo de subida</h6>
|
||
<div class="form-check">
|
||
<input class="form-check-input"
|
||
type="radio"
|
||
name="uploadMode"
|
||
id="modoMerge"
|
||
checked='@(uploadMode == "merge")'
|
||
@onclick='() => uploadMode = "merge"' />
|
||
<label class="form-check-label" for="modoMerge">
|
||
Unir todos los ficheros en un <20>nico PDF
|
||
</label>
|
||
</div>
|
||
<div class="form-check">
|
||
<input class="form-check-input"
|
||
type="radio"
|
||
name="uploadMode"
|
||
id="modoIndividual"
|
||
checked='@(uploadMode == "individual")'
|
||
@onclick='() => uploadMode = "individual"' />
|
||
<label class="form-check-label" for="modoIndividual">
|
||
Subir ficheros de forma independiente
|
||
</label>
|
||
</div>
|
||
|
||
<h6 class="modal-section-heading">Grupo de destino</h6>
|
||
<div class="form-check">
|
||
<input class="form-check-input"
|
||
type="radio"
|
||
name="selectedGroup"
|
||
id="grupo600"
|
||
checked='@(selectedGroup == "600")'
|
||
@onclick='() => selectedGroup = "600"' />
|
||
<label class="form-check-label" for="grupo600">
|
||
600. Asuntos Jur<75>dicos y Protecci<63>n a la Persona Denunciante
|
||
</label>
|
||
</div>
|
||
@* <div class="form-check">
|
||
<input class="form-check-input"
|
||
type="radio"
|
||
name="selectedGroup"
|
||
id="grupo510"
|
||
checked='@(selectedGroup == "510")'
|
||
@onclick='() => selectedGroup = "510"' />
|
||
<label class="form-check-label" for="grupo510">
|
||
510. SDI <20> Investigaci<63>n Entradas
|
||
</label>
|
||
</div>
|
||
<div class="form-check">
|
||
<input class="form-check-input"
|
||
type="radio"
|
||
name="selectedGroup"
|
||
id="grupo700"
|
||
checked='@(selectedGroup == "700")'
|
||
@onclick='() => selectedGroup = "700"' />
|
||
<label class="form-check-label" for="grupo700">
|
||
700. RESPONSABLE DEL SERVICIO
|
||
</label>
|
||
</div> *@
|
||
|
||
<!-- DATOS DEL TERCERO -->
|
||
@{
|
||
var modalThirdParty = selectedThirdParty ?? ThirdPartyIdentityData.FromComplaint(selectedDenuncias);
|
||
}
|
||
<h6 class="modal-section-heading mt-3">Tercero (denunciante)</h6>
|
||
|
||
<div class="alert alert-light border mb-3">
|
||
Los datos del tercero se cargan autom<6F>ticamente desde la denuncia y no se pueden editar aqu<71>.
|
||
</div>
|
||
|
||
@if (modalThirdParty.IsAnonymous)
|
||
{
|
||
<div class="alert alert-warning mb-3">
|
||
Denuncia an<61>nima. Se enlazar<61> autom<6F>ticamente el tercero <strong>00000000T</strong>.
|
||
</div>
|
||
}
|
||
|
||
<div class="row g-2">
|
||
<div class="col-6 mb-2">
|
||
<label class="form-label">@GetDocumentoLabel(selectedDenuncias)</label>
|
||
<input class="form-control" value="@GetReadOnlyValue(modalThirdParty.DocumentId)" readonly />
|
||
</div>
|
||
<div class="col-6 mb-2">
|
||
<label class="form-label">Email</label>
|
||
<input class="form-control" value="@GetReadOnlyValue(modalThirdParty.Email)" readonly />
|
||
</div>
|
||
</div>
|
||
|
||
@if (!string.IsNullOrWhiteSpace(selectedDenuncias.TipoDenunciante))
|
||
{
|
||
<div class="row g-2">
|
||
<div class="col-12 mb-2">
|
||
<label class="form-label">Tipo de denunciante</label>
|
||
<input class="form-control" value="@selectedDenuncias.TipoDenunciante" readonly />
|
||
</div>
|
||
</div>
|
||
}
|
||
|
||
@if (modalThirdParty.IsLegalEntity)
|
||
{
|
||
<div class="row g-2">
|
||
<div class="col-12 mb-2">
|
||
<label class="form-label">Raz<61>n social</label>
|
||
<input class="form-control" value="@GetReadOnlyValue(selectedDenuncias.RazonSocialResuelta)" readonly />
|
||
</div>
|
||
</div>
|
||
}
|
||
else
|
||
{
|
||
<div class="row g-2">
|
||
<div class="col-4 mb-2">
|
||
<label class="form-label">Nombre</label>
|
||
<input class="form-control" value="@GetReadOnlyValue(selectedDenuncias.NombreResuelto)" readonly />
|
||
</div>
|
||
<div class="col-4 mb-2">
|
||
<label class="form-label">1<> apellido</label>
|
||
<input class="form-control" value="@GetReadOnlyValue(selectedDenuncias.PrimerApellidoResuelto)" readonly />
|
||
</div>
|
||
<div class="col-4 mb-2">
|
||
<label class="form-label">2<> apellido</label>
|
||
<input class="form-control" value="@GetReadOnlyValue(selectedDenuncias.SegundoApellidoResuelto)" readonly />
|
||
</div>
|
||
</div>
|
||
}
|
||
|
||
@if (!modalThirdParty.IsAnonymous && HasPostalAddress(selectedDenuncias))
|
||
{
|
||
<div class="row g-2">
|
||
<div class="col-12 mb-2">
|
||
<label class="form-label">Direcci<63>n postal</label>
|
||
<textarea class="form-control" rows="2" readonly>@BuildPostalAddressSummary(selectedDenuncias)</textarea>
|
||
</div>
|
||
</div>
|
||
}
|
||
|
||
<small class="text-muted">
|
||
Al confirmar, se enlazar<61> en Gestiona el tercero obtenido del formulario de la denuncia.
|
||
</small>
|
||
|
||
@if (!modalThirdParty.IsAnonymous && !string.IsNullOrWhiteSpace(modalThirdParty.DocumentId))
|
||
{
|
||
<div class="mt-2">
|
||
<button type="button"
|
||
class="btn btn-outline-secondary btn-sm"
|
||
@onclick="BuscarExpedientesTerceroAsync">
|
||
Ver expedientes de este tercero en Gestiona
|
||
</button>
|
||
|
||
</div>
|
||
}
|
||
</div>
|
||
|
||
<div class="modal-footer custom-modal-footer">
|
||
<button type="button" class="btn btn-secondary" @onclick="CloseModal">
|
||
Cancelar
|
||
</button>
|
||
<button type="button" class="btn btn-primary" disabled="@isUploading" @onclick="ConfirmarEnvio">
|
||
Confirmar
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-backdrop fade show"></div>
|
||
}
|
||
|
||
@if (showModalRechazo && selectedDenuncias != null)
|
||
{
|
||
<div class="modal custom-modal fade show" style="display:block;" tabindex="-1">
|
||
<div class="modal-dialog custom-modal-dialog">
|
||
<div class="modal-content custom-modal-content">
|
||
<div class="modal-header custom-modal-header">
|
||
<h5 class="modal-title">Rechazar Denuncia</h5>
|
||
<button type="button" class="btn-close" @onclick="CloseRechazoModal"></button>
|
||
</div>
|
||
<div class="modal-body custom-modal-body">
|
||
<h6 class="modal-section-heading">Motivo de Rechazo</h6>
|
||
<div class="mb-3">
|
||
<input type="text" class="form-control" @bind="motivoRechazo" placeholder="Ingrese el motivo de rechazo" />
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer custom-modal-footer">
|
||
<button type="button" class="btn btn-secondary" @onclick="CloseRechazoModal">Cancelar</button>
|
||
<button type="button" class="btn btn-primary" @onclick="ConfirmarRechazo">Confirmar</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-backdrop fade show"></div>
|
||
}
|
||
|
||
@if (showExpedientesModal)
|
||
{
|
||
<div class="modal custom-modal fade show expedientes-modal"
|
||
style="display:block; z-index:2100;" tabindex="-1">
|
||
<div class="modal-dialog custom-modal-dialog" style="max-width: 900px;">
|
||
<div class="modal-content custom-modal-content">
|
||
<div class="modal-header custom-modal-header">
|
||
<h5 class="modal-title">
|
||
Expedientes en Gestiona para @nifConsultaExpedientes
|
||
</h5>
|
||
<button type="button" class="btn-close" @onclick="CloseExpedientesModal"></button>
|
||
</div>
|
||
<div class="modal-body custom-modal-body">
|
||
|
||
@if (isLoadingExpedientes)
|
||
{
|
||
<div class="d-flex align-items-center">
|
||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||
<span>Cargando expedientes<65></span>
|
||
</div>
|
||
}
|
||
else if (!string.IsNullOrWhiteSpace(errorExpedientes))
|
||
{
|
||
<div class="alert alert-danger">@errorExpedientes</div>
|
||
}
|
||
else if (expedientesTercero == null || !expedientesTercero.Any())
|
||
{
|
||
<div class="alert alert-warning">
|
||
No se han encontrado expedientes asociados a este tercero.
|
||
</div>
|
||
}
|
||
else
|
||
{
|
||
<table class="table table-sm table-striped table-hover">
|
||
<thead>
|
||
<tr>
|
||
<th>Expediente</th>
|
||
<th>Asunto</th>
|
||
<th>Fecha creaci<63>n</th>
|
||
<th>Estado</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach (var exp in expedientesTercero)
|
||
{
|
||
<tr>
|
||
<td>@exp.CodigoExpediente</td>
|
||
<td>@exp.Asunto</td>
|
||
<td>@(exp.FechaCreacion?.ToLocalTime().ToString("dd/MM/yyyy HH:mm"))</td>
|
||
<td>@exp.Estado</td>
|
||
<td class="text-end">
|
||
@if (!string.IsNullOrWhiteSpace(exp.FileUrl))
|
||
{
|
||
|
||
}
|
||
</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
}
|
||
</div>
|
||
<div class="modal-footer custom-modal-footer">
|
||
<button type="button" class="btn btn-secondary" @onclick="CloseExpedientesModal">
|
||
Cerrar
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
}
|
||
|
||
@code {
|
||
private string nombreDocumentos = string.Empty;
|
||
private bool isUploading = false;
|
||
|
||
private string uploadMode = "merge";
|
||
private string selectedGroup = "600";
|
||
|
||
|
||
private string busqueda = "";
|
||
private List<DenunciasGestiona> pendientes = new();
|
||
private Dictionary<int, List<FicherosDenuncias>> ficherosAdjuntos = new();
|
||
private Dictionary<int, HashSet<string>> excludedUploadFiles = new();
|
||
|
||
private bool hasLoaded = false;
|
||
private string loadError = string.Empty;
|
||
private string operationError = string.Empty;
|
||
private string operationNotice = string.Empty;
|
||
private bool showModal = false;
|
||
private bool showModalRechazo = false;
|
||
|
||
private DenunciasGestiona? selectedDenuncias;
|
||
private ThirdPartyIdentityData? selectedThirdParty;
|
||
private string nuevoAsunto = string.Empty;
|
||
private string motivoRechazo = string.Empty;
|
||
|
||
private string terceroDni = "";
|
||
|
||
private bool showExpedientesModal = false;
|
||
private bool isLoadingExpedientes = false;
|
||
private string errorExpedientes = string.Empty;
|
||
private string nifConsultaExpedientes = string.Empty;
|
||
private List<ExpedienteTerceroDto> expedientesTercero = new();
|
||
|
||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||
{
|
||
if (firstRender)
|
||
{
|
||
await CargarDatosAsync();
|
||
}
|
||
}
|
||
|
||
private async Task CargarDatosAsync()
|
||
{
|
||
try
|
||
{
|
||
loadError = string.Empty;
|
||
var todas = await CargarDenunciasJsonAsync();
|
||
|
||
// Asegura ProcedureId/GroupId por si faltan
|
||
foreach (var d in todas.Where(x => x.ProcedureId == Guid.Empty))
|
||
{
|
||
d.ProcedureId = Guid.Parse("82722c9b-cecc-4299-8a7b-ce5abeb8170b");
|
||
d.GroupId = Guid.Parse("6dbfc433-1eb6-4b9a-a533-bfebc652c101");
|
||
}
|
||
|
||
// SOLO pendientes
|
||
pendientes = todas
|
||
.Where(d => !d.EnGestiona && !d.EnRechazada && !d.EsActualizacion)
|
||
.ToList();
|
||
|
||
// Adjuntos SOLO de las pendientes visibles
|
||
ficherosAdjuntos = await CargarFicherosPorDenunciaAsync(pendientes.Select(p => p.Id_Denuncia));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
pendientes.Clear();
|
||
ficherosAdjuntos.Clear();
|
||
loadError = $"No se han podido cargar las denuncias pendientes: {ex.Message}";
|
||
}
|
||
|
||
hasLoaded = true;
|
||
StateHasChanged();
|
||
}
|
||
|
||
private async Task<List<DenunciasGestiona>> CargarDenunciasJsonAsync()
|
||
{
|
||
return await DenunciaStore.GetDenunciasByScopeAsync(DenunciaListScope.Pending);
|
||
}
|
||
|
||
private async Task<Dictionary<int, List<FicherosDenuncias>>> CargarFicherosPorDenunciaAsync(IEnumerable<int> denunciaIds)
|
||
{
|
||
var result = new Dictionary<int, List<FicherosDenuncias>>();
|
||
foreach (var denunciaId in denunciaIds.Where(id => id > 0).Distinct())
|
||
{
|
||
var ficheros = await DenunciaStore.GetFicherosByDenunciaAsync(denunciaId);
|
||
if (ficheros.Count > 0)
|
||
{
|
||
result[denunciaId] = ficheros;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private static bool IsReportFileName(string? fileName)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(fileName))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
var name = Path.GetFileNameWithoutExtension(fileName);
|
||
var extension = Path.GetExtension(fileName);
|
||
return name.StartsWith("report", StringComparison.OrdinalIgnoreCase) &&
|
||
(extension.Equals(".txt", StringComparison.OrdinalIgnoreCase) ||
|
||
extension.Equals(".pdf", StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
private string FixFileName(string input)
|
||
{
|
||
var normalized = input.Normalize(NormalizationForm.FormD);
|
||
var sb = new StringBuilder();
|
||
foreach (var c in normalized)
|
||
{
|
||
var uc = CharUnicodeInfo.GetUnicodeCategory(c);
|
||
if (uc != UnicodeCategory.NonSpacingMark) sb.Append(c);
|
||
}
|
||
var clean = sb.ToString().Normalize(NormalizationForm.FormC);
|
||
clean = clean.Replace(' ', '_');
|
||
return new string(clean.Where(ch => ch <= 127).ToArray());
|
||
}
|
||
|
||
private async Task ConfirmarEnvio()
|
||
{
|
||
if (selectedDenuncias == null) return;
|
||
|
||
// Seguridad: no permitir enviar actualizaciones desde /Pendientes
|
||
if (selectedDenuncias.EsActualizacion)
|
||
{
|
||
CloseModal();
|
||
Navigation.NavigateTo("/Actualizaciones");
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
isUploading = true;
|
||
operationError = string.Empty;
|
||
operationNotice = string.Empty;
|
||
using var busy = Busy.Show(
|
||
"Enviando a Gestiona",
|
||
"Preparando expediente, tercero y documentos de la denuncia.");
|
||
StateHasChanged();
|
||
await Task.Yield();
|
||
|
||
Busy.Update(message: "Cargando ficheros de la denuncia.", detail: "Paso 1 de 7");
|
||
var existentesF = await DenunciaStore.GetFicherosByDenunciaAsync(selectedDenuncias.Id_Denuncia);
|
||
var ficherosNoSeleccionados = GetExcludedUploadFileNames(selectedDenuncias.Id_Denuncia, existentesF);
|
||
var ficherosSeleccionados = GetSelectedUploadFiles(selectedDenuncias.Id_Denuncia, existentesF);
|
||
var todos = ficherosSeleccionados
|
||
.Select(f => (FileName: f.NombreFichero!, Content: f.Fichero!))
|
||
.ToList();
|
||
|
||
var ficherosVacios = todos
|
||
.Where(t => t.Content is null || t.Content.Length == 0)
|
||
.Select(t => string.IsNullOrWhiteSpace(t.FileName) ? "(sin nombre)" : t.FileName)
|
||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||
.ToList();
|
||
todos = todos
|
||
.Where(t => t.Content is { Length: > 0 })
|
||
.ToList();
|
||
|
||
if (!todos.Any())
|
||
{
|
||
operationError = ficherosVacios.Count == 0
|
||
? $"La denuncia #{selectedDenuncias.Id_Denuncia} no tiene ficheros para subir."
|
||
: $"La denuncia #{selectedDenuncias.Id_Denuncia} solo tiene ficheros vac<61>os y no se ha subido nada. Ficheros omitidos: {string.Join(", ", ficherosVacios)}.";
|
||
return;
|
||
}
|
||
|
||
string fileUrl;
|
||
if (selectedDenuncias.EnGestiona && !string.IsNullOrWhiteSpace(selectedDenuncias.Expediente_Gestiona))
|
||
{
|
||
fileUrl = selectedDenuncias.Expediente_Gestiona;
|
||
}
|
||
else
|
||
{
|
||
Busy.Update(message: "Creando expediente nuevo en Gestiona.", detail: "Paso 2 de 7");
|
||
var createdFile = await ApiDenuncias.CreateGestionaFileAsync(
|
||
selectedDenuncias.ProcedureId,
|
||
nuevoAsunto,
|
||
"RQ2ZLC - Expediente de Denuncias",
|
||
"3109963"
|
||
);
|
||
fileUrl = createdFile.FileUrl;
|
||
Busy.Update(message: "Abriendo expediente y asignando el grupo elegido.", detail: "Paso 2 de 7");
|
||
await ApiDenuncias.OpenGestionaFileAsync(
|
||
fileUrl,
|
||
createdFile.FileOpenUrl,
|
||
managementUnitGroupId: Guid.Parse("a4ad4dfb-70dc-4219-8ee3-4dcc939f0955"),
|
||
assignedGroupId: selectedGroup switch
|
||
{
|
||
"510" => Guid.Parse("6dbfc433-1eb6-4b9a-a533-bfebc652c101"),
|
||
"600" => Guid.Parse("454fa4ec-8b82-4240-9419-113f45d4b004"),
|
||
"700" => Guid.Parse("a4ad4dfb-70dc-4219-8ee3-4dcc939f0955"),
|
||
_ => throw new InvalidOperationException($"Grupo desconocido: {selectedGroup}")
|
||
},
|
||
confidential: selectedDenuncias.Confidencial,
|
||
freeTitle: nuevoAsunto,
|
||
siaCode: "3109963"
|
||
);
|
||
selectedDenuncias.Expediente_Gestiona = fileUrl;
|
||
selectedDenuncias.EnGestiona = true;
|
||
}
|
||
|
||
Busy.Update(message: "Guardando referencia local del expediente.", detail: "Paso 3 de 7");
|
||
selectedDenuncias.Expediente_Gestiona = fileUrl;
|
||
selectedDenuncias.EnGestiona = true;
|
||
|
||
var thirdParty = selectedThirdParty ?? ThirdPartyIdentityData.FromComplaint(selectedDenuncias);
|
||
Busy.Update(message: "Resolviendo tercero y enlazandolo al expediente.", detail: "Paso 4 de 7");
|
||
await ApiDenuncias.EnsureGestionaThirdAndLinkAsync(fileUrl, thirdParty);
|
||
|
||
var nombresOriginalesSubidos = new List<string>();
|
||
var nombresFinalesSubidos = new List<string>();
|
||
var ahoraUtc = DateTime.UtcNow;
|
||
string? documentoParaTramitar = null;
|
||
|
||
var report = todos.FirstOrDefault(t =>
|
||
IsReportFileName(t.FileName));
|
||
|
||
if (!string.IsNullOrWhiteSpace(report.FileName))
|
||
{
|
||
Busy.Update(message: "Preparando y subiendo el report para firma.", detail: "Paso 5 de 7");
|
||
var reportPdfBytes = PdfHelper.MergeFilesToPdf(new[]
|
||
{
|
||
(FileName: report.FileName, Content: report.Content)
|
||
});
|
||
const string reportFinalName = "Denuncia.pdf";
|
||
documentoParaTramitar = await ApiDenuncias.UploadGestionaDocumentAsync(
|
||
fileUrl,
|
||
reportPdfBytes,
|
||
FixFileName(reportFinalName));
|
||
nombresOriginalesSubidos.Add(report.FileName);
|
||
nombresFinalesSubidos.Add(FixFileName(reportFinalName));
|
||
}
|
||
|
||
var adjuntos = todos
|
||
.Where(t => !IsReportFileName(t.FileName))
|
||
.ToList();
|
||
|
||
if (adjuntos.Count > 0 && uploadMode == "merge")
|
||
{
|
||
Busy.Update(message: "Uniendo adjuntos en un unico PDF y subiendolo.", detail: "Paso 6 de 7");
|
||
var pdfBytes = PdfHelper.MergeFilesToPdf(adjuntos);
|
||
var pdfName = FixFileName($"Adjuntos {selectedDenuncias.Id_Denuncia}_{ahoraUtc:yyyyMMddHHmmss}.pdf");
|
||
var docUrl = await ApiDenuncias.UploadGestionaDocumentAsync(fileUrl, pdfBytes, pdfName);
|
||
if (string.IsNullOrWhiteSpace(documentoParaTramitar))
|
||
{
|
||
documentoParaTramitar = docUrl;
|
||
}
|
||
|
||
foreach (var adjunto in adjuntos)
|
||
{
|
||
nombresOriginalesSubidos.Add(adjunto.FileName);
|
||
}
|
||
|
||
nombresFinalesSubidos.Add(pdfName);
|
||
}
|
||
else
|
||
{
|
||
int i = 1;
|
||
string baseNombre = string.IsNullOrWhiteSpace(nombreDocumentos) ? "" : $" {nombreDocumentos}";
|
||
|
||
foreach (var (origName, content) in adjuntos)
|
||
{
|
||
Busy.Update(
|
||
message: $"Subiendo adjunto {i} de {adjuntos.Count}.",
|
||
detail: "Paso 6 de 7",
|
||
current: i,
|
||
total: adjuntos.Count);
|
||
|
||
var ext = Path.GetExtension(origName).ToLowerInvariant();
|
||
byte[] bytesParaSubir = content;
|
||
string finalName;
|
||
|
||
if (ext == ".txt")
|
||
{
|
||
bytesParaSubir = PdfHelper.MergeFilesToPdf(new[]
|
||
{
|
||
(FileName: origName, Content: content)
|
||
});
|
||
finalName = FixFileName($"Documento Adjunto {i}{baseNombre}.pdf");
|
||
}
|
||
else
|
||
{
|
||
finalName = FixFileName($"Documento Adjunto {i}{baseNombre}{ext}");
|
||
}
|
||
|
||
var docUrl = await ApiDenuncias.UploadGestionaDocumentAsync(fileUrl, bytesParaSubir, finalName);
|
||
if (string.IsNullOrWhiteSpace(documentoParaTramitar))
|
||
{
|
||
documentoParaTramitar = docUrl;
|
||
}
|
||
|
||
nombresOriginalesSubidos.Add(origName);
|
||
nombresFinalesSubidos.Add(finalName);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
selectedDenuncias.ArchivoElegido = string.Join(";", nombresFinalesSubidos);
|
||
|
||
if (!string.IsNullOrWhiteSpace(documentoParaTramitar))
|
||
{
|
||
Busy.Update(message: "Enviando el report al circuito de firma.", detail: "Paso 7 de 7");
|
||
await ApiDenuncias.TramitarGestionaDocumentAsync(
|
||
documentoParaTramitar,
|
||
GetAssignedGroupLinkBySelectedGroup(),
|
||
selectedDenuncias.Id_Denuncia);
|
||
}
|
||
|
||
foreach (var origName in nombresOriginalesSubidos)
|
||
{
|
||
var f = existentesF.FirstOrDefault(x =>
|
||
x.Id_Denuncia == selectedDenuncias.Id_Denuncia &&
|
||
x.NombreFichero == origName);
|
||
if (f != null)
|
||
{
|
||
f.Subido = true;
|
||
f.FechaSubida = ahoraUtc;
|
||
}
|
||
}
|
||
|
||
Busy.Update(message: "Actualizando trazabilidad en la base de datos.", detail: "Finalizando");
|
||
await DenunciaStore.MarkFicherosAsUploadedAsync(
|
||
selectedDenuncias.Id_Denuncia,
|
||
nombresOriginalesSubidos,
|
||
ahoraUtc);
|
||
|
||
selectedDenuncias.EsActualizacion = false;
|
||
selectedDenuncias.NombreDenuncia = nuevoAsunto;
|
||
selectedDenuncias.FechaSubidaAGestiona = ahoraUtc;
|
||
await ActualizarDenunciaAsync(selectedDenuncias);
|
||
|
||
var denunciaProcesadaId = selectedDenuncias.Id_Denuncia;
|
||
pendientes.Remove(selectedDenuncias);
|
||
excludedUploadFiles.Remove(denunciaProcesadaId);
|
||
CloseModal();
|
||
|
||
var avisos = new List<string>();
|
||
if (ficherosVacios.Count > 0)
|
||
{
|
||
avisos.Add($"Se omitieron ficheros vac<61>os: {string.Join(", ", ficherosVacios)}.");
|
||
}
|
||
if (ficherosNoSeleccionados.Count > 0)
|
||
{
|
||
avisos.Add($"No se subieron por selecci<63>n del usuario: {string.Join(", ", ficherosNoSeleccionados)}.");
|
||
}
|
||
if (avisos.Count > 0)
|
||
{
|
||
operationNotice = $"Denuncia #{denunciaProcesadaId} enviada. {string.Join(" ", avisos)}";
|
||
}
|
||
StateHasChanged();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.Error.WriteLine($"Error al confirmar env<6E>o: {ex}");
|
||
operationError = $"No se ha podido completar el env<6E>o de la denuncia #{selectedDenuncias?.Id_Denuncia}: {ex.Message}";
|
||
}
|
||
finally
|
||
{
|
||
isUploading = false;
|
||
StateHasChanged();
|
||
}
|
||
}
|
||
|
||
private string ObtenerUrlPublicaDe(string fileName)
|
||
{
|
||
return Navigation.BaseUri + $"CombinedPdfs/{Uri.EscapeDataString(fileName)}";
|
||
}
|
||
|
||
private async Task SincronizarExpedienteGestionaAsync(DenunciasGestiona denuncia, string fileUrl)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(fileUrl))
|
||
{
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
var expediente = await ApiDenuncias.GetGestionaExpedienteAsync(fileUrl);
|
||
if (expediente is null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
denuncia.Expediente_Gestiona = expediente.FileUrl;
|
||
if (!string.IsNullOrWhiteSpace(expediente.CodigoExpediente))
|
||
{
|
||
denuncia.CodigoExpedienteGestiona = expediente.CodigoExpediente;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(expediente.FreeTitle))
|
||
{
|
||
denuncia.NombreDenuncia = expediente.FreeTitle;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.Error.WriteLine($"No se ha podido sincronizar el expediente de Gestiona: {ex}");
|
||
}
|
||
}
|
||
|
||
private string GetAssignedGroupLinkBySelectedGroup()
|
||
{
|
||
return selectedGroup switch
|
||
{
|
||
"510" => "https://02.g3stiona.com/rest/groups/6dbfc433-1eb6-4b9a-a533-bfebc652c101",
|
||
"600" => "https://02.g3stiona.com/rest/groups/454fa4ec-8b82-4240-9419-113f45d4b004",
|
||
"700" => "https://02.g3stiona.com/rest/groups/a4ad4dfb-70dc-4219-8ee3-4dcc939f0955",
|
||
_ => throw new InvalidOperationException($"Grupo desconocido: {selectedGroup}")
|
||
};
|
||
}
|
||
|
||
private async Task ConfirmarRechazo()
|
||
{
|
||
if (selectedDenuncias == null)
|
||
return;
|
||
|
||
selectedDenuncias.EnRechazada = true;
|
||
selectedDenuncias.EstadoDenuncia = motivoRechazo;
|
||
selectedDenuncias.FechaSubidaAGestiona = DateTime.Now;
|
||
|
||
await ActualizarDenunciaAsync(selectedDenuncias);
|
||
|
||
pendientes.Remove(selectedDenuncias);
|
||
CloseRechazoModal();
|
||
StateHasChanged();
|
||
}
|
||
|
||
private async Task ActualizarDenunciaAsync(DenunciasGestiona d)
|
||
{
|
||
await DenunciaStore.UpsertDenunciaAsync(d);
|
||
}
|
||
|
||
private void OpenEnviarAGestionaModal(DenunciasGestiona d)
|
||
{
|
||
selectedDenuncias = d;
|
||
nuevoAsunto = $"Denuncia {d.Id_Denuncia}-CD";
|
||
|
||
selectedThirdParty = ThirdPartyIdentityData.FromComplaint(d);
|
||
terceroDni = selectedThirdParty.DocumentId;
|
||
operationError = string.Empty;
|
||
operationNotice = string.Empty;
|
||
|
||
showModal = true;
|
||
}
|
||
|
||
private void OpenRechazarModal(DenunciasGestiona d)
|
||
{
|
||
selectedDenuncias = d;
|
||
motivoRechazo = string.Empty;
|
||
showModalRechazo = true;
|
||
}
|
||
|
||
private void CloseModal()
|
||
{
|
||
showModal = false;
|
||
selectedDenuncias = null;
|
||
selectedThirdParty = null;
|
||
nuevoAsunto = string.Empty;
|
||
terceroDni = string.Empty;
|
||
operationError = string.Empty;
|
||
}
|
||
|
||
private void CloseRechazoModal() =>
|
||
(showModalRechazo, selectedDenuncias, motivoRechazo) =
|
||
(false, null, string.Empty);
|
||
|
||
|
||
private bool IsFileSelectedForUpload(int denunciaId, string? fileName)
|
||
{
|
||
if (IsReportFileName(fileName))
|
||
{
|
||
return true;
|
||
}
|
||
|
||
return string.IsNullOrWhiteSpace(fileName) ||
|
||
!excludedUploadFiles.TryGetValue(denunciaId, out var excluded) ||
|
||
!excluded.Contains(fileName);
|
||
}
|
||
|
||
private void ToggleFileSelection(int denunciaId, string? fileName, bool selected)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(fileName) || IsReportFileName(fileName))
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (!excludedUploadFiles.TryGetValue(denunciaId, out var excluded))
|
||
{
|
||
excluded = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||
excludedUploadFiles[denunciaId] = excluded;
|
||
}
|
||
|
||
if (selected)
|
||
{
|
||
excluded.Remove(fileName);
|
||
if (excluded.Count == 0)
|
||
{
|
||
excludedUploadFiles.Remove(denunciaId);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
excluded.Add(fileName);
|
||
}
|
||
}
|
||
|
||
private List<FicherosDenuncias> GetSelectedUploadFiles(int denunciaId, IEnumerable<FicherosDenuncias> files)
|
||
{
|
||
return files
|
||
.Where(file => IsReportFileName(file.NombreFichero) || IsFileSelectedForUpload(denunciaId, file.NombreFichero))
|
||
.ToList();
|
||
}
|
||
|
||
private List<string> GetExcludedUploadFileNames(int denunciaId, IEnumerable<FicherosDenuncias> files)
|
||
{
|
||
return files
|
||
.Where(file => !IsReportFileName(file.NombreFichero) && !IsFileSelectedForUpload(denunciaId, file.NombreFichero))
|
||
.Select(file => string.IsNullOrWhiteSpace(file.NombreFichero) ? "(sin nombre)" : file.NombreFichero)
|
||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||
.OrderBy(name => name, StringComparer.OrdinalIgnoreCase)
|
||
.ToList();
|
||
}
|
||
private static string BuildAttachmentContentUrl(int denunciaId, string? fileName)
|
||
{
|
||
return $"/api/denuncias/{denunciaId}/ficheros/content?fileName={Uri.EscapeDataString(fileName ?? string.Empty)}";
|
||
}
|
||
|
||
private static string FormatFileDate(DateTime date)
|
||
=> date == DateTime.MinValue
|
||
? "-"
|
||
: date.ToLocalTime().ToString("dd/MM/yyyy HH:mm", CultureInfo.InvariantCulture);
|
||
|
||
private string GetContentType(string fileName)
|
||
{
|
||
return Path.GetExtension(fileName).ToLowerInvariant() switch
|
||
{
|
||
".jpg" or ".jpeg" => "image/jpeg",
|
||
".png" => "image/png",
|
||
".gif" => "image/gif",
|
||
".pdf" => "application/pdf",
|
||
".txt" => "text/plain",
|
||
_ => "application/octet-stream",
|
||
};
|
||
}
|
||
|
||
private static string GetDocumentoLabel(DenunciasGestiona denuncia)
|
||
{
|
||
return string.IsNullOrWhiteSpace(denuncia.TipoDocumentoIdentificativo)
|
||
? "Documento identificativo"
|
||
: denuncia.TipoDocumentoIdentificativo;
|
||
}
|
||
|
||
private static string GetReadOnlyValue(string? value) =>
|
||
string.IsNullOrWhiteSpace(value) ? "<22>" : value;
|
||
|
||
private static bool HasPostalAddress(DenunciasGestiona denuncia)
|
||
{
|
||
return !string.IsNullOrWhiteSpace(denuncia.Direccion) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.DireccionNumero) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.Municipio) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.Provincia) ||
|
||
!string.IsNullOrWhiteSpace(denuncia.CodigoPostal);
|
||
}
|
||
|
||
private static string BuildPostalAddressSummary(DenunciasGestiona denuncia)
|
||
{
|
||
var parts = new List<string>();
|
||
|
||
var street = string.Join(
|
||
' ',
|
||
new[]
|
||
{
|
||
denuncia.DireccionTipoVia,
|
||
denuncia.Direccion,
|
||
denuncia.DireccionNumero
|
||
}.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||
if (!string.IsNullOrWhiteSpace(street))
|
||
{
|
||
parts.Add(street);
|
||
}
|
||
|
||
var extras = string.Join(
|
||
", ",
|
||
new[]
|
||
{
|
||
string.IsNullOrWhiteSpace(denuncia.DireccionBloque) ? null : $"Bloque {denuncia.DireccionBloque}",
|
||
string.IsNullOrWhiteSpace(denuncia.DireccionEscalera) ? null : $"Esc. {denuncia.DireccionEscalera}",
|
||
string.IsNullOrWhiteSpace(denuncia.DireccionPiso) ? null : $"Planta {denuncia.DireccionPiso}",
|
||
string.IsNullOrWhiteSpace(denuncia.DireccionPuerta) ? null : $"Puerta {denuncia.DireccionPuerta}",
|
||
denuncia.DireccionExtra
|
||
}.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||
if (!string.IsNullOrWhiteSpace(extras))
|
||
{
|
||
parts.Add(extras);
|
||
}
|
||
|
||
var location = string.Join(
|
||
", ",
|
||
new[]
|
||
{
|
||
denuncia.CodigoPostal,
|
||
denuncia.Municipio,
|
||
denuncia.Provincia
|
||
}.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||
if (!string.IsNullOrWhiteSpace(location))
|
||
{
|
||
parts.Add(location);
|
||
}
|
||
|
||
return string.Join(" | ", parts);
|
||
}
|
||
|
||
// mover a Actualizaciones
|
||
private async Task MoverAActualizaciones(DenunciasGestiona d)
|
||
{
|
||
d.EsActualizacion = true;
|
||
d.EnRechazada = false;
|
||
await ActualizarDenunciaAsync(d);
|
||
|
||
pendientes.RemoveAll(x => x.Id_Denuncia == d.Id_Denuncia);
|
||
StateHasChanged();
|
||
}
|
||
|
||
// ========= L<>GICA BUSCADOR DE EXPEDIENTES POR TERCERO =========
|
||
|
||
private void CloseExpedientesModal()
|
||
{
|
||
showExpedientesModal = false;
|
||
errorExpedientes = string.Empty;
|
||
expedientesTercero.Clear();
|
||
nifConsultaExpedientes = string.Empty;
|
||
}
|
||
|
||
private async Task BuscarExpedientesTerceroAsync()
|
||
{
|
||
errorExpedientes = string.Empty;
|
||
expedientesTercero.Clear();
|
||
|
||
var nif = (selectedThirdParty?.DocumentId ?? terceroDni ?? string.Empty).Trim().ToUpperInvariant();
|
||
|
||
if (string.IsNullOrWhiteSpace(nif) || nif == "00000000T")
|
||
{
|
||
errorExpedientes = "NIF no v<>lido para b<>squeda (an<61>nimo o vac<61>o).";
|
||
showExpedientesModal = true;
|
||
StateHasChanged();
|
||
return;
|
||
}
|
||
|
||
showExpedientesModal = true;
|
||
isLoadingExpedientes = true;
|
||
nifConsultaExpedientes = nif;
|
||
StateHasChanged();
|
||
|
||
try
|
||
{
|
||
expedientesTercero = await ApiDenuncias.GetGestionaExpedientesPorTerceroAsync(nif);
|
||
if (expedientesTercero.Count == 0)
|
||
{
|
||
errorExpedientes = "No se han encontrado expedientes asociados a ese NIF en Gestiona.";
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
errorExpedientes = $"Error al consultar expedientes: {ex.Message}";
|
||
}
|
||
finally
|
||
{
|
||
isLoadingExpedientes = false;
|
||
StateHasChanged();
|
||
}
|
||
}
|
||
}
|
||
|