diff --git a/SIG.Web/App_Code/Configuration/AppServices.cs b/SIG.Web/App_Code/Configuration/AppServices.cs index 34e49e4..1392797 100644 --- a/SIG.Web/App_Code/Configuration/AppServices.cs +++ b/SIG.Web/App_Code/Configuration/AppServices.cs @@ -50,6 +50,7 @@ namespace SIG.Web.AppCode.Configuration public static IBitacoraService BitacoraService { get; private set; } public static IPasswordHasher PasswordHasher { get; private set; } public static IServicioDesarrolladores ServicioDesarrolladores { get; private set; } + public static IServicioPortalCliente ServicioPortalCliente { get; private set; } public static ICaptchaService CaptchaService { get; private set; } public static IUserRepository UserRepository { get; private set; } private static IUserAdministrationRepository UserAdministrationRepository { get; set; } @@ -212,6 +213,13 @@ namespace SIG.Web.AppCode.Configuration PermissionService = new PermissionService( permissionRepository); ServicioConvenios = new ServicioConvenios(new RepositorioConvenios(DbExecutor), UserContext); + ServicioPortalCliente = new ServicioPortalCliente( + new RepositorioPortalCliente(DbExecutor), + ServicioFraccionamiento, + TramiteDocumentoService, + TramiteSolicitudService, + new AlmacenComprobantesConvenio(), + UserContext); ServicioPagosConvenios = new ServicioPagosConvenios( new RepositorioPagosConvenios(DbExecutor), tramiteSolicitudRepository, diff --git a/SIG.Web/App_Code/Configuration/BundleConfig.cs b/SIG.Web/App_Code/Configuration/BundleConfig.cs index 37f0a32..95498c8 100644 --- a/SIG.Web/App_Code/Configuration/BundleConfig.cs +++ b/SIG.Web/App_Code/Configuration/BundleConfig.cs @@ -1,4 +1,4 @@ -using System.Web.Optimization; +using System.Web.Optimization; using System.Web.UI; namespace SIG.Web.AppCode.Configuration @@ -127,6 +127,7 @@ namespace SIG.Web.AppCode.Configuration "~/Styles/PanelLateral.css", "~/Styles/DetalleEtapa.css", "~/Styles/DocumentosEtapa.css", + "~/Styles/Archivos.css", "~/Styles/Estilos.css", "~/Styles/filtrosig.css", "~/Styles/scrollsig.css", diff --git a/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoRepository.cs b/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoRepository.cs index 732bd0c..e87a9c4 100644 --- a/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoRepository.cs +++ b/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using SIG.Web.AppCode.Models.Common; using SIG.Web.AppCode.Models.Documentos; @@ -78,6 +78,13 @@ namespace SIG.Web.AppCode.Contracts.Documentos bool actualizarFechas = false, int? cveFraccionamientoEtapa = null); + DbResult ActualizarFechaVencimiento( + int cveFraccionamiento, + int cveDocumentoSolicitud, + DateTime? fechaVencimiento, + int cveUsuarioEjecuta, + string nombreDominio); + DbResult Review( int developmentId, int documentRequestId, diff --git a/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoService.cs b/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoService.cs index 0a50481..fb00b5a 100644 --- a/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoService.cs +++ b/SIG.Web/App_Code/Contracts/Documentos/ITramiteDocumentoService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using SIG.Web.AppCode.Models.Common; @@ -78,6 +78,13 @@ namespace SIG.Web.AppCode.Contracts.Documentos int cveUsuarioEjecuta, string nombreDominio); + DbResult ActualizarFechaVencimiento( + int cveFraccionamiento, + int cveDocumentoSolicitud, + DateTime? fechaVencimiento, + int cveUsuarioEjecuta, + string nombreDominio); + DbResult Review( int developmentId, int documentRequestId, diff --git a/SIG.Web/App_Code/Contracts/Tramites/ITramiteSolicitudService.cs b/SIG.Web/App_Code/Contracts/Tramites/ITramiteSolicitudService.cs index 16a1879..06a99ae 100644 --- a/SIG.Web/App_Code/Contracts/Tramites/ITramiteSolicitudService.cs +++ b/SIG.Web/App_Code/Contracts/Tramites/ITramiteSolicitudService.cs @@ -75,6 +75,7 @@ namespace SIG.Web.AppCode.Contracts.Tramites DbResult CambiarEstatus( ModeloCambioEstatusTramite cambioEstatus, int cveUsuarioEjecuta, - string nombreDominio); + string nombreDominio, + bool validarPagosRequeridos = true); } } diff --git a/SIG.Web/App_Code/Infrastructure/WebForms/CargaArchivoWebHelper.cs b/SIG.Web/App_Code/Infrastructure/WebForms/CargaArchivoWebHelper.cs new file mode 100644 index 0000000..bae6ab1 --- /dev/null +++ b/SIG.Web/App_Code/Infrastructure/WebForms/CargaArchivoWebHelper.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web; +using System.Web.UI; +using System.Web.UI.HtmlControls; + +namespace SIG.Web.AppCode.Infrastructure.WebForms +{ + public static class CargaArchivoWebHelper + { + public static void Configurar( + HtmlInputHidden control, + string extensionesPermitidas, + int? tamanoMaximoMb, + int maximoArchivos = 1, + string mensaje = null) + { + if (control == null) + { + return; + } + + if (control.Page != null && control.Page.Form != null) + { + control.Page.Form.Enctype = "multipart/form-data"; + } + + control.Attributes["data-readmode"] = "none"; + control.Attributes["data-input-name"] = ObtenerNombreCampo(control); + control.Attributes["data-maxfile"] = Math.Max(1, maximoArchivos) + .ToString(CultureInfo.InvariantCulture); + + if (tamanoMaximoMb.HasValue && tamanoMaximoMb.Value > 0) + { + control.Attributes["data-maxfilesize"] = tamanoMaximoMb.Value + .ToString(CultureInfo.InvariantCulture); + } + else + { + control.Attributes.Remove("data-maxfilesize"); + } + + string extensiones = NormalizarExtensiones(extensionesPermitidas); + if (string.IsNullOrWhiteSpace(extensiones)) + { + control.Attributes.Remove("data-acceptedfiles"); + } + else + { + control.Attributes["data-acceptedfiles"] = extensiones; + } + + control.Attributes["data-message"] = string.IsNullOrWhiteSpace(mensaje) + ? "Arrastra aquí un archivo o haz clic para seleccionarlo." + : mensaje.Trim(); + } + + public static HttpPostedFile ObtenerArchivo(Page pagina, HtmlInputHidden control) + { + return ObtenerArchivos(pagina, control).FirstOrDefault(); + } + public static List ObtenerArchivos( Page pagina, HtmlInputHidden control) + { + var archivos = new List(); + + if (pagina == null || control == null) + { + return archivos; + } + + string nombreCampo = ObtenerNombreCampo(control); + HttpFileCollection archivosRequest = pagina.Request.Files; + + for (int indice = 0; indice < archivosRequest.Count; indice++) + { + string nombreCampoArchivo = archivosRequest.GetKey(indice); + + if (!string.Equals( + nombreCampoArchivo, + nombreCampo, + StringComparison.Ordinal)) + { + continue; + } + + HttpPostedFile archivo = archivosRequest[indice]; + + if (archivo != null && archivo.ContentLength > 0) + { + archivos.Add(archivo); + } + } + + return archivos; + } + + public static string ObtenerNombreCampo(Control control) + { + if (control == null) + { + throw new ArgumentNullException("control"); + } + + return control.ClientID + "_archivo"; + } + + private static string NormalizarExtensiones(string extensiones) + { + if (string.IsNullOrWhiteSpace(extensiones)) + { + return null; + } + + return string.Join(",", + extensiones + .Split(new[] { ',', ';', '|', ' ' }, StringSplitOptions.RemoveEmptyEntries) + .Select(extension => extension.Trim()) + .Where(extension => !string.IsNullOrWhiteSpace(extension)) + .Select(extension => + { + if (extension.Contains("/")) + { + return extension; + } + + extension = extension.TrimStart('*'); + return extension.StartsWith(".", StringComparison.Ordinal) + ? extension + : "." + extension; + }) + .Distinct(StringComparer.OrdinalIgnoreCase)); + } + } +} diff --git a/SIG.Web/App_Code/Models/Documentos/TramiteDocumentoModels.cs b/SIG.Web/App_Code/Models/Documentos/TramiteDocumentoModels.cs index 8e54cb0..a257975 100644 --- a/SIG.Web/App_Code/Models/Documentos/TramiteDocumentoModels.cs +++ b/SIG.Web/App_Code/Models/Documentos/TramiteDocumentoModels.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SIG.Web.AppCode.Models.Documentos @@ -168,6 +168,24 @@ namespace SIG.Web.AppCode.Models.Documentos public DateTime? FechaRevisionAnterior { get; set; } } + public sealed class TramiteDocumentoVencimientoResultModel + { + public int CveDocumentoSolicitud { get; set; } + public int CveSolicitud { get; set; } + public string Folio { get; set; } + public int CveCliente { get; set; } + public int CveFraccionamiento { get; set; } + public int CveFraccionamientoEtapa { get; set; } + public string Etapa { get; set; } + public int CveTipoTramite { get; set; } + public string TipoTramite { get; set; } + public int CveTipoDocumento { get; set; } + public string TipoDocumento { get; set; } + public DateTime? FechaDocumento { get; set; } + public DateTime? FechaVencimientoAnterior { get; set; } + public DateTime? FechaVencimiento { get; set; } + } + public sealed class TramiteDocumentoReviewResultModel { public int CveDocumentoSolicitud { get; set; } diff --git a/SIG.Web/App_Code/Models/Tramites/TramiteSolicitudModels.cs b/SIG.Web/App_Code/Models/Tramites/TramiteSolicitudModels.cs index b4e8fd1..2fc2170 100644 --- a/SIG.Web/App_Code/Models/Tramites/TramiteSolicitudModels.cs +++ b/SIG.Web/App_Code/Models/Tramites/TramiteSolicitudModels.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using SIG.Web.AppCode.Models.Documentos; @@ -44,6 +44,7 @@ namespace SIG.Web.AppCode.Models.Tramites public int CveEstatusSolicitud { get; set; } public string EstatusSolicitud { get; set; } public bool EsEstatusCliente { get; set; } + public bool EsEstatusOk { get; set; } public DateTime? FechaInicio { get; set; } public DateTime? FechaAutorizacion { get; set; } public bool PuedeCambiarEstatus { get; set; } @@ -59,6 +60,7 @@ namespace SIG.Web.AppCode.Models.Tramites public int Orden { get; set; } public bool EsFinal { get; set; } public bool EsCliente { get; set; } + public bool EsOK { get; set; } } public sealed class TramiteSolicitudStatusChangeModel diff --git a/SIG.Web/App_Code/Repositories/Documentos/TramiteDocumentoRepository.cs b/SIG.Web/App_Code/Repositories/Documentos/TramiteDocumentoRepository.cs index c7eb2d1..622a479 100644 --- a/SIG.Web/App_Code/Repositories/Documentos/TramiteDocumentoRepository.cs +++ b/SIG.Web/App_Code/Repositories/Documentos/TramiteDocumentoRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Data; using SIG.Web.AppCode.Contracts.Database; @@ -268,6 +268,28 @@ namespace SIG.Web.AppCode.Repositories.Documentos }); } + public DbResult ActualizarFechaVencimiento( + int cveFraccionamiento, + int cveDocumentoSolicitud, + DateTime? fechaVencimiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Tramites_DocumentoSolicitudVencimientoUpdate", + cveUsuarioEjecuta, + nombreDominio, + command => + { + StoredProcedureCommand.AddInput( + command, "@CveFraccionamiento", cveFraccionamiento, DbType.Int32); + StoredProcedureCommand.AddInput( + command, "@CveDocumentoSolicitud", cveDocumentoSolicitud, DbType.Int32); + StoredProcedureCommand.AddInput( + command, "@FechaVencimiento", fechaVencimiento, DbType.Date); + }); + } + public DbResult Review( int developmentId, int documentRequestId, diff --git a/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs b/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs index 02151e0..96f798f 100644 --- a/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs +++ b/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs @@ -250,6 +250,7 @@ namespace SIG.Web.AppCode.Services.Clientes PuedeEnviarRevision = solicitud.PuedeCambiarEstatus && solicitud.EsEstatusCliente && + !solicitud.EsEstatusOk && documentosPendientes == 0 && pagosPendientes == 0 }; @@ -303,6 +304,12 @@ namespace SIG.Web.AppCode.Services.Clientes "Existen recibos pendientes de pago."); } + if (!tramite.PuedeEnviarRevision) + { + return Fallo( + "El trámite ya no se encuentra en un estatus que pueda enviarse a revisión."); + } + DbResult contexto = _servicioTramites.ObtenerContextoCambioEstatus( cveSolicitud, @@ -317,12 +324,29 @@ namespace SIG.Web.AppCode.Services.Clientes contexto.Exception); } + if (!contexto.Data.Solicitud.EsEstatusCliente || contexto.Data.Solicitud.EsEstatusOk) + { + return Fallo( + "El trámite ya no se encuentra en un estatus que pueda enviarse a revisión."); + } + if (!contexto.Data.CveSiguienteEstatus.HasValue) { return Fallo( "El trámite no tiene un siguiente estatus disponible para enviar a revisión."); } + TramiteSolicitudEstatusOptionModel estatusRevision = + (contexto.Data.Estatus ?? new List()) + .FirstOrDefault(estatus => + estatus.CveEstatusSolicitud == contexto.Data.CveSiguienteEstatus.Value); + + if (estatusRevision == null || !estatusRevision.EsCliente || !estatusRevision.EsOK) + { + return Fallo( + "El siguiente estatus no corresponde al envío a revisión configurado."); + } + var cambio = new ModeloCambioEstatusTramite { CveSolicitud = cveSolicitud, diff --git a/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoBitacoraFactory.cs b/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoBitacoraFactory.cs index 914854c..822f7b2 100644 --- a/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoBitacoraFactory.cs +++ b/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoBitacoraFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using SIG.Web.AppCode.Models.Bitacora; using SIG.Web.AppCode.Models.Documentos; @@ -116,6 +116,30 @@ namespace SIG.Web.AppCode.Services.Documentos return auditEvent; } + public static ModeloRegistroBitacora ActualizarVencimiento( + TramiteDocumentoVencimientoResultModel cambio) + { + ModeloRegistroBitacora evento = BaseEvent( + cambio.CveDocumentoSolicitud, + cambio.CveSolicitud, + cambio.CveCliente, + cambio.CveFraccionamiento, + cambio.CveFraccionamientoEtapa, + BitacoraTipoMovimiento.Editado, + "Se actualizó la fecha de vencimiento del documento " + + cambio.TipoDocumento + " de la etapa " + cambio.Etapa + "."); + + evento.Campos = new List + { + Field( + "FechaVencimiento", + cambio.FechaVencimientoAnterior, + cambio.FechaVencimiento) + }; + + return evento; + } + public static ModeloRegistroBitacora Delete( TramiteDocumentoDeleteResultModel change) { diff --git a/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoService.cs b/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoService.cs index 22e6967..a801927 100644 --- a/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoService.cs +++ b/SIG.Web/App_Code/Services/Documentos/TramiteDocumentoService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -406,11 +406,17 @@ namespace SIG.Web.AppCode.Services.Documentos return Fail(validation); } - if (uploadContext.TieneVigencia && !fechaVencimiento.HasValue) + if (!fechaDocumento.HasValue) { - return Fail("Capture la fecha de vencimiento del documento."); + return Fail( + "Capture la fecha del documento."); } - if (fechaDocumento.HasValue && fechaVencimiento.HasValue && + if (fechaDocumento.Value.Date > DateTime.Today) + { + return Fail( + "La fecha del documento no puede ser posterior al día de hoy."); + } + if (fechaVencimiento.HasValue && fechaVencimiento.Value.Date < fechaDocumento.Value.Date) { return Fail("El vencimiento no puede ser anterior a la fecha del documento."); @@ -585,6 +591,99 @@ namespace SIG.Web.AppCode.Services.Documentos } } + public DbResult ActualizarFechaVencimiento( + int cveFraccionamiento, + int cveDocumentoSolicitud, + DateTime? fechaVencimiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario = _contextoUsuario.GetCurrentUser(); + if (usuario == null || usuario.CveUsuario != cveUsuarioEjecuta) + { + return Fail( + "La sesión del usuario no es válida."); + } + if (usuario.EsDesarrollador) + { + return Fail( + "La fecha de vencimiento sólo puede ser modificada por Agua de Hermosillo."); + } + if (cveFraccionamiento <= 0 || cveDocumentoSolicitud <= 0) + { + return Fail( + "Seleccione un documento válido."); + } + + DbResult> consulta = ListForDevelopment( + cveFraccionamiento, + null, + null, + cveUsuarioEjecuta, + nombreDominio); + if (!consulta.Success) + { + return CopyFailure, TramiteDocumentoVencimientoResultModel>( + consulta, + "No fue posible consultar el documento."); + } + + TramiteDocumentoSolicitudModel documento = (consulta.Data ?? new List()) + .FirstOrDefault(item => item.CveDocumentoSolicitud == cveDocumentoSolicitud); + if (documento == null || !documento.TieneArchivo) + { + return Fail( + "El documento ya no está disponible."); + } + if (fechaVencimiento.HasValue && documento.FechaDocumento.HasValue && + fechaVencimiento.Value.Date < documento.FechaDocumento.Value.Date) + { + return Fail( + "El vencimiento no puede ser anterior a la fecha del documento."); + } + + using (var transaccion = new TransactionLogic(IsolationLevel.Serializable)) + { + DbResult resultado = + _repository.ActualizarFechaVencimiento( + cveFraccionamiento, + cveDocumentoSolicitud, + fechaVencimiento, + cveUsuarioEjecuta, + nombreDominio); + if (!resultado.Success || resultado.Data == null) + { + return resultado; + } + + DbResult bitacora = _bitacoraService.RegistrarOperacion( + ModeloOperacionBitacora.Crear( + "ActualizarVencimientoDocumentoSolicitud", + TramiteDocumentoBitacoraFactory.ActualizarVencimiento(resultado.Data))); + if (!bitacora.Success) + { + return CopyFailure( + bitacora, + "No fue posible registrar el cambio."); + } + + DbResult proceso = ActualizarVencimientoEtapa( + resultado.Data.CveFraccionamientoEtapa, + cveUsuarioEjecuta, + nombreDominio); + if (!proceso.Success) + { + return DbResult.Fail( + proceso.UserMessage, + proceso.TechnicalMessage, + proceso.Exception); + } + + transaccion.Commit(); + return resultado; + } + } + public DbResult Review( int developmentId, int documentRequestId, @@ -607,6 +706,36 @@ namespace SIG.Web.AppCode.Services.Documentos "Capture la nota o motivo del rechazo."); } + if (approved) + { + DbResult> documentos = ListForDevelopment( + developmentId, + null, + null, + executingUser, + domainName); + if (!documentos.Success) + { + return CopyFailure, TramiteDocumentoReviewResultModel>( + documentos, + "No fue posible validar el documento."); + } + + TramiteDocumentoSolicitudModel documento = + (documentos.Data ?? new List()) + .FirstOrDefault(item => item.CveDocumentoSolicitud == documentRequestId); + if (documento == null) + { + return Fail( + "El documento ya no está disponible."); + } + if (documento.TieneVigencia && !documento.FechaVencimiento.HasValue) + { + return Fail( + "Capture la fecha de vencimiento antes de aprobar el documento."); + } + } + using (var transaction = new TransactionLogic()) { DbResult result = diff --git a/SIG.Web/App_Code/Services/Tramites/TramiteSolicitudService.cs b/SIG.Web/App_Code/Services/Tramites/TramiteSolicitudService.cs index c049d54..fd5f64f 100644 --- a/SIG.Web/App_Code/Services/Tramites/TramiteSolicitudService.cs +++ b/SIG.Web/App_Code/Services/Tramites/TramiteSolicitudService.cs @@ -650,7 +650,8 @@ namespace SIG.Web.AppCode.Services.Tramites public DbResult CambiarEstatus( ModeloCambioEstatusTramite cambioEstatus, int cveUsuarioEjecuta, - string nombreDominio) + string nombreDominio, + bool validarPagosRequeridos = true) { UserSessionModel usuario = _contextoUsuario.GetCurrentUser(); if (usuario == null || usuario.CveUsuario != cveUsuarioEjecuta) @@ -743,7 +744,8 @@ namespace SIG.Web.AppCode.Services.Tramites "Documentos", "Existen documentos requeridos pendientes de cargar."); } - if (contexto.Pagos.Any(pago => pago.EstaPendiente)) + if (validarPagosRequeridos && + contexto.Pagos.Any(pago => pago.EstaPendiente)) { return RequisitosPendientes( "Pagos", "Existen pagos requeridos pendientes. Cancele y realice el pago por el flujo habitual."); diff --git a/SIG.Web/Documentos/Clientes/1006/Etapas/1022/doc-1022-1045-b8d0648d970b4cababc65f30c58b1ccb.bin b/SIG.Web/Documentos/Clientes/1006/Etapas/1022/doc-1022-1045-b8d0648d970b4cababc65f30c58b1ccb.bin new file mode 100644 index 0000000..a0e1228 Binary files /dev/null and b/SIG.Web/Documentos/Clientes/1006/Etapas/1022/doc-1022-1045-b8d0648d970b4cababc65f30c58b1ccb.bin differ diff --git a/SIG.Web/Pages/Clientes/Desarrollos.aspx b/SIG.Web/Pages/Clientes/Desarrollos.aspx index 58d99b6..ad7dd9c 100644 --- a/SIG.Web/Pages/Clientes/Desarrollos.aspx +++ b/SIG.Web/Pages/Clientes/Desarrollos.aspx @@ -36,7 +36,29 @@ EmptyDataText="No tiene fraccionamientos activos." OnRowDataBound="EnlazarFila"> - + + +
+
+ + + <%#: ResumenFraccionamiento(Container.DataItem) %> + +
+ +
+
+
+ diff --git a/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs b/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs index e3246f1..a7b2dc6 100644 --- a/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs +++ b/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Web.UI; -using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using SIG.Web.AppCode.Configuration; using SIG.Web.AppCode.Infrastructure.WebForms; @@ -44,65 +42,50 @@ namespace SIG.Web.Pages.Clientes argumentos.Row.CssClass = "sig-grid-grupo"; argumentos.Row.Attributes["data-sig-group-row"] = "1"; argumentos.Row.Attributes["data-sig-group-id"] = grupo; - argumentos.Row.Attributes["data-sig-level"] = "2"; + for (int indiceCelda = 0; indiceCelda < argumentos.Row.Cells.Count; indiceCelda++) + { + string claseCelda = indiceCelda == 0 + ? "sig-grid-columna-grupo" + : "sig-grid-columna-normal"; + argumentos.Row.Cells[indiceCelda].CssClass = + (argumentos.Row.Cells[indiceCelda].CssClass + " " + claseCelda).Trim(); + } + + argumentos.Row.Attributes["data-sig-level"] = "2"; argumentos.Row.Attributes["data-sig-expanded-default"] = "true"; - int columnas = GvDesarrollos.Columns - .Cast() - .Count(columna => columna.Visible); - argumentos.Row.Cells.Clear(); - - var celda = new TableCell { ColumnSpan = columnas }; - var contenedor = new HtmlGenericControl("div"); - contenedor.Attributes["class"] = - "sig-cliente-desarrollo-cabecera"; - - var informacion = new HtmlGenericControl("div"); - var enlace = new HyperLink - { - Text = fila.Fraccionamiento, - NavigateUrl = ResolveUrl( - "~/Pages/Clientes/FraccionamientoDetalle.aspx?id=" + - fila.CveFraccionamiento.ToString( - CultureInfo.InvariantCulture)) - }; - informacion.Controls.Add(enlace); - - var resumen = new HtmlGenericControl("span"); - resumen.Attributes["class"] = - "sig-cliente-desarrollo-resumen"; - resumen.InnerText = string.Format( - CultureInfo.CurrentCulture, - "{0} · {1} etapa(s)", - fila.Estatus, - fila.NumeroEtapas); - informacion.Controls.Add(resumen); - - var alternar = new HtmlGenericControl("button"); - alternar.Attributes["type"] = "button"; - alternar.Attributes["class"] = - "btn btn-sm default sig-grid-alternar-grupo"; - alternar.Attributes["aria-expanded"] = "true"; - alternar.Attributes["title"] = "Mostrar u ocultar etapas"; - - var icono = new HtmlGenericControl("i"); - icono.Attributes["class"] = - "fa fa-chevron-up sig-grid-icono-agrupacion"; - icono.Attributes["aria-hidden"] = "true"; - alternar.Controls.Add(icono); - - contenedor.Controls.Add(informacion); - contenedor.Controls.Add(alternar); - celda.Controls.Add(contenedor); - argumentos.Row.Cells.Add(celda); return; } + argumentos.Row.CssClass = + (argumentos.Row.CssClass + " sig-grid-fila-dato").Trim(); argumentos.Row.Attributes["data-sig-item-row"] = "1"; argumentos.Row.Attributes["data-sig-parent-group"] = grupo; argumentos.Row.Attributes["data-sig-level"] = "1"; } + protected string UrlDetalleFraccionamiento(object clave) + { + return ResolveUrl("~/Pages/Clientes/FraccionamientoDetalle.aspx?id=") + + Convert.ToInt32(clave).ToString(CultureInfo.InvariantCulture); + } + + protected string ResumenFraccionamiento(object objeto) + { + var fila = objeto as ModeloFilaDesarrollos; + + if (fila == null || !fila.EsFraccionamiento) + { + return string.Empty; + } + + return string.Format( + CultureInfo.CurrentCulture, + "{0} · {1} etapa(s)", + fila.Estatus, + fila.NumeroEtapas); + } + private void Cargar() { var resultado = AppServices.ServicioPortalCliente.ListarDesarrollos( diff --git a/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs b/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs index ce6502f..5548444 100644 --- a/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs +++ b/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs @@ -10,12 +10,16 @@ namespace SIG.Web.Pages.Clientes { public partial class FraccionamientoDetalle : ClsPaginaBase { + #region Propiedades + private int CveFraccionamientoActual { get { return (int?)ViewState["CveFraccionamientoActual"] ?? 0; } set { ViewState["CveFraccionamientoActual"] = value; } } + #endregion + protected void Page_Load(object origen, EventArgs argumentos) { if (IsPostBack) diff --git a/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx b/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx index 9800458..d447456 100644 --- a/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx +++ b/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx @@ -1,4 +1,4 @@ -<%@ Page Title="Detalle de desarrollador" Language="C#" MasterPageFile="~/Site.master" +<%@ Page Title="Detalle de desarrollador" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="DesarrolladorDetalle.aspx.cs" Inherits="SIG.Web.Pages.Desarrolladores.DesarrolladorDetalle" %> <%@ Register TagPrefix="sig" TagName="CapturaEtapas" Src="~/UserControl/CapturaEtapas.ascx" %> @@ -20,9 +20,23 @@ .desarrollador-acciones { margin-bottom: 15px; } - .desarrollador-listado > tbody > tr.desarrollador-grupo > td { + .desarrollador-listado > tbody > tr.desarrollador-grupo { + position: relative; + height: 50px; + } + .desarrollador-listado > tbody > tr.desarrollador-grupo > td:first-child { + display: block; + position: absolute; + left: 0; + right: 0; + top: 0; + min-height: 50px; background: #edf4f8; padding: 10px 12px; + box-sizing: border-box; + } + .desarrollador-listado > tbody > tr.desarrollador-grupo > td.desarrollador-celda-oculta-grupo { + display: none; } .desarrollador-cabecera { display: flex; @@ -207,11 +221,17 @@ - + - + ToolTip="Ver etapa" aria-label="Ver etapa" + Visible='<%# !Convert.ToBoolean(Eval("EsFraccionamiento")) %>'> + +
diff --git a/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx.cs b/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx.cs index 68a7049..5916e08 100644 --- a/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx.cs +++ b/SIG.Web/Pages/Desarrolladores/DesarrolladorDetalle.aspx.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using System.Collections.Generic; using System.Web.UI; @@ -16,6 +16,28 @@ namespace SIG.Web.Pages.Desarrolladores { public partial class DesarrolladorDetalle : ClsPaginaBase { + #region Propiedades + + private int CveClienteActual + { + get { return ViewState["CveClienteActual"] as int? ?? 0; } + set { ViewState["CveClienteActual"] = value; } + } + + private int CveFraccionamientoEtapaActual + { + get { return ViewState["CveFraccionamientoEtapaActual"] as int? ?? 0; } + set { ViewState["CveFraccionamientoEtapaActual"] = value; } + } + + private bool AsociadoCanadeviActual + { + get { return ViewState["AsociadoCanadeviActual"] as bool? ?? false; } + set { ViewState["AsociadoCanadeviActual"] = value; } + } + + #endregion + protected void Fraccionamientos_FilaEnlazada(object origen, GridViewRowEventArgs argumentos) { if (argumentos.Row.RowType != DataControlRowType.DataRow) @@ -30,10 +52,11 @@ namespace SIG.Web.Pages.Desarrolladores if (desarrollo.EsFraccionamiento) { argumentos.Row.CssClass = "desarrollador-grupo"; - argumentos.Row.Cells[0].ColumnSpan = GvFraccionamientos.Columns.Count; for (int indice = 1; indice < argumentos.Row.Cells.Count; indice++) { - argumentos.Row.Cells[indice].Visible = false; + argumentos.Row.Cells[indice].CssClass = + (argumentos.Row.Cells[indice].CssClass + + " desarrollador-celda-oculta-grupo").Trim(); } } } @@ -96,24 +119,6 @@ namespace SIG.Web.Pages.Desarrolladores } } - private int CveClienteActual - { - get { return ViewState["CveClienteActual"] as int? ?? 0; } - set { ViewState["CveClienteActual"] = value; } - } - - private int CveFraccionamientoEtapaActual - { - get { return ViewState["CveFraccionamientoEtapaActual"] as int? ?? 0; } - set { ViewState["CveFraccionamientoEtapaActual"] = value; } - } - - private bool AsociadoCanadeviActual - { - get { return ViewState["AsociadoCanadeviActual"] as bool? ?? false; } - set { ViewState["AsociadoCanadeviActual"] = value; } - } - protected void Page_Load(object origen, EventArgs argumentos) { if (!IsPostBack) diff --git a/SIG.Web/Pages/Desarrolladores/PagoDetalle.aspx b/SIG.Web/Pages/Desarrolladores/PagoDetalle.aspx index 7354542..50ab755 100644 --- a/SIG.Web/Pages/Desarrolladores/PagoDetalle.aspx +++ b/SIG.Web/Pages/Desarrolladores/PagoDetalle.aspx @@ -39,8 +39,9 @@
- - + +
@@ -27,9 +27,29 @@ background-color: #dff0d8; } -.sig-tablero-tramites .sig-tramites-agrupacion > td { +.sig-tablero-tramites .sig-tramites-columna-grupo { + display: none; +} + +.sig-tablero-tramites .sig-tramites-agrupacion { + position: relative; + height: 42px; +} + +.sig-tablero-tramites .sig-tramites-agrupacion > td.sig-tramites-columna-grupo { + display: block; + position: absolute; + left: 0; + right: 0; + top: 0; + min-height: 42px; padding: 0; background: #eef3f7; + box-sizing: border-box; +} + +.sig-tablero-tramites .sig-tramites-agrupacion > td.sig-tramites-columna-normal { + display: none; } .sig-tramites-alternar-grupo { @@ -81,6 +101,15 @@ OnRowCommand="GvTramites_Comando" EmptyDataText="No hay solicitudes para los filtros seleccionados."> + + + + + @@ -98,7 +127,7 @@ - + () - .Count(columna => columna.Visible); - - argumentos.Row.Cells.Clear(); argumentos.Row.CssClass = "sig-tramites-agrupacion"; - var celda = new TableCell - { - ColumnSpan = columnasVisibles - }; - var boton = new HtmlGenericControl("button"); - boton.Attributes["type"] = "button"; - boton.Attributes["class"] = "sig-tramites-alternar-grupo"; - boton.Attributes["aria-expanded"] = "true"; - - var nombreGrupo = new HtmlGenericControl("span") - { - InnerText = solicitud.Agrupacion - }; - var flecha = new HtmlGenericControl("i"); - flecha.Attributes["class"] = "fa fa-chevron-up"; - flecha.Attributes["aria-hidden"] = "true"; - - boton.Controls.Add(nombreGrupo); - boton.Controls.Add(flecha); - celda.Controls.Add(boton); - argumentos.Row.Cells.Add(celda); return; } diff --git a/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx b/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx index c03235e..c8aed2f 100644 --- a/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx +++ b/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx @@ -1185,16 +1185,15 @@
- +
- + - + 2) + if (CurrentUser.EsDesarrollador) { Alert( - "Sólo un superusuario puede rechazar documentos.", + "La revisión de documentos corresponde a Agua de Hermosillo.", TipoMensaje.MsgAdvertencia); return; } @@ -938,7 +938,8 @@ namespace SIG.Web.Pages.Fraccionamientos return; } - if (!ArchivoDocumento.HasFile || ArchivoDocumento.PostedFile == null) + var archivoDocumento = CargaArchivoWebHelper.ObtenerArchivo(Page, ArchivoDocumento); + if (archivoDocumento == null) { MostrarValidacionCargaDocumento( "Seleccione el archivo que desea guardar."); @@ -959,10 +960,10 @@ namespace SIG.Web.Pages.Fraccionamientos CveFraccionamientoActual, cveSolicitud, cveTipoDocumento, - ArchivoDocumento.FileName, - ArchivoDocumento.PostedFile.ContentType, - ArchivoDocumento.PostedFile.InputStream, - ArchivoDocumento.PostedFile.ContentLength, + archivoDocumento.FileName, + archivoDocumento.ContentType, + archivoDocumento.InputStream, + archivoDocumento.ContentLength, TxtComentarioClienteDocumento.Text, CurrentUser.CveUsuario, CurrentUser.NombreDominio, @@ -1430,7 +1431,8 @@ namespace SIG.Web.Pages.Fraccionamientos return; } - if (!ArchivoLotes.HasFile) + var archivoLotes = CargaArchivoWebHelper.ObtenerArchivo(Page, ArchivoLotes); + if (archivoLotes == null) { MostrarValidacionLote( "Seleccione la plantilla de Excel que desea cargar."); @@ -1439,10 +1441,10 @@ namespace SIG.Web.Pages.Fraccionamientos ResultadoExcelLotesFraccionamiento resultadoExcel = ExcelLotesFraccionamiento.Leer( - ArchivoLotes.PostedFile.InputStream, - ArchivoLotes.FileName, - ArchivoLotes.PostedFile.ContentLength, - ArchivoLotes.PostedFile.ContentType); + archivoLotes.InputStream, + archivoLotes.FileName, + archivoLotes.ContentLength, + archivoLotes.ContentType); if (!resultadoExcel.Exitoso) { @@ -2011,9 +2013,15 @@ namespace SIG.Web.Pages.Fraccionamientos } LitReglasCargaDocumento.Text = Server.HtmlEncode(reglas); + CargaArchivoWebHelper.Configurar( + ArchivoDocumento, + contexto.ExtensionesPermitidas, + contexto.TamanoMaximoMb, + 1); TxtComentarioClienteDocumento.Text = contexto.ComentarioClienteAnterior ?? string.Empty; - TxtFechaDocumento.Text = FormatearFechaDocumento(contexto.FechaDocumentoAnterior); + TxtFechaDocumento.Text = FormatearFechaDocumento(DateTime.Today); + TxtFechaDocumento.Attributes["max"] = FormatearFechaDocumento(DateTime.Today); TxtVencimientoDocumento.Text = FormatearFechaDocumento(contexto.FechaVencimientoAnterior); OcultarMensajeCargaDocumento(); UpModalCargaDocumento.Update(); @@ -2025,10 +2033,10 @@ namespace SIG.Web.Pages.Fraccionamientos bool aprobado, string nota) { - if (CurrentUser.CveRol > 2) + if (CurrentUser.EsDesarrollador) { Alert( - "Sólo un superusuario puede aprobar o rechazar documentos.", + "La revisión de documentos corresponde a Agua de Hermosillo.", TipoMensaje.MsgAdvertencia); return; } @@ -3111,6 +3119,12 @@ namespace SIG.Web.Pages.Fraccionamientos CveFraccionamientoEtapaLotesActual = cveFraccionamientoEtapa; LitLoteEtapaNombre.Text = Server.HtmlEncode(etapaItem.Text); + CargaArchivoWebHelper.Configurar( + ArchivoLotes, + ".xlsx", + null, + 1, + "Arrastra aquí la plantilla .xlsx o haz clic para seleccionarla."); LimpiarCapturaLote(); UpLotesModal.Update(); MostrarLoteModal(); diff --git a/SIG.Web/SIG.Web.zip b/SIG.Web/SIG.Web.zip deleted file mode 100644 index 6049183..0000000 Binary files a/SIG.Web/SIG.Web.zip and /dev/null differ diff --git a/SIG.Web/Scripts/custom.js b/SIG.Web/Scripts/custom.js index 284df73..9baa7e4 100644 --- a/SIG.Web/Scripts/custom.js +++ b/SIG.Web/Scripts/custom.js @@ -1,4 +1,4 @@ -/* +/* * custom.js * Cleaned for the new C# WebForms project. * Notes: @@ -1625,8 +1625,17 @@ function ADDropzoneLocal(txtid) { txt.attr('data-maxFile') || txt.attr('data-maxfile'), 10); var acceptedFiles = txt.attr('data-acceptedfiles') || null; + var modoLectura = (txt.attr('data-readmode') || 'text').toLowerCase(); + var nombreCampoArchivo = txt.attr('data-input-name') || null; var message = txt.attr('data-message') || 'Arrastra un archivo aquí o haz clic para seleccionarlo.'; + + if (nombreCampoArchivo) { + txt.closest('form') + .attr('enctype', 'multipart/form-data') + .attr('encoding', 'multipart/form-data'); + } + var appendId = txt.attr('data-append'); var dropId = txtid + '-drop'; var existing = $('#' + dropId); @@ -1710,6 +1719,15 @@ function ADDropzoneLocal(txtid) { return; } + if (modoLectura === 'none') { + txt.trigger('adsdropzone:fileadded', [ + file, + null, + instance + ]); + return; + } + var reader = new FileReader(); reader.onload = function (event) { @@ -1739,8 +1757,11 @@ function ADDropzoneLocal(txtid) { * archivo y los mismos eventos adsdropzone:* consumidos por la pantalla. * Si Dropzone está cargado en otra instalación, se usa normalmente. */ - if (typeof Dropzone === 'undefined') { + if (typeof Dropzone === 'undefined' || nombreCampoArchivo) { var input = $(''); + if (nombreCampoArchivo) { + input.attr('name', nombreCampoArchivo); + } if (acceptedFiles) { input.attr('accept', acceptedFiles); } @@ -1756,12 +1777,14 @@ function ADDropzoneLocal(txtid) { if (index >= 0) { this.files.splice(index, 1); } + sincronizarInputFallback(); renderFallback(); txt.trigger('adsdropzone:fileremoved', [file, fallback]); }, removeAllFiles: function () { var files = this.files.slice(0); this.files = []; + sincronizarInputFallback(); renderFallback(); $.each(files, function (_, file) { txt.trigger('adsdropzone:fileremoved', [file, fallback]); @@ -1769,6 +1792,31 @@ function ADDropzoneLocal(txtid) { } }; + function sincronizarInputFallback() { + if (!nombreCampoArchivo) { + return; + } + + var elemento = input.get(0); + if (!elemento) { + return; + } + + try { + var transferencia = new DataTransfer(); + $.each(fallback.files, function (_, file) { + transferencia.items.add(file); + }); + elemento.files = transferencia.files; + } catch (ex) { + /* + * Navegadores antiguos pueden impedir asignar FileList. + * En selección por clic el input conserva su FileList nativo; + * el fallback por drag/drop requiere DataTransfer. + */ + } + } + function renderFallback() { mydiv.find('.ADSdropzoneLocalFallbackPreview').remove(); mydiv.find('.dz-message').toggle(fallback.files.length === 0); @@ -1817,16 +1865,33 @@ function ADDropzoneLocal(txtid) { } fallback.files.push(file); + sincronizarInputFallback(); renderFallback(); readFile(file, fallback); } input.on('change', function () { + var seleccionados = []; var files = this.files || []; - for (var i = 0; i < files.length; i++) { - addFallbackFile(files[i]); + var i; + + for (i = 0; i < files.length; i++) { + seleccionados.push(files[i]); + } + + if (!isNaN(maxFile) && maxFile === 1) { + fallback.files = []; + } + + for (i = 0; i < seleccionados.length; i++) { + addFallbackFile(seleccionados[i]); + } + + if (!nombreCampoArchivo) { + this.value = ''; + } else { + sincronizarInputFallback(); } - this.value = ''; }); /* diff --git a/SIG.Web/Styles/Archivos.css b/SIG.Web/Styles/Archivos.css new file mode 100644 index 0000000..1c62149 --- /dev/null +++ b/SIG.Web/Styles/Archivos.css @@ -0,0 +1,40 @@ +.ADSdropzoneLocalContainer { + min-height: 118px; + border: 2px dashed #c3ccd5; + background: #ffffff; + padding: 18px 12px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + box-sizing: border-box; +} + +.ADSdropzoneLocalContainer:focus { + outline: 1px solid #3598dc; + outline-offset: 2px; +} + +.ADSdropzoneLocalContainer .dz-message { + color: #6f7b86; + line-height: 1.5; +} + +.ADSdropzoneLocalContainer.is-dragging { + border-style: solid; + background: #eef6fb; +} + +.ADSdropzoneLocalFallbackPreview { + width: 100%; + padding: 10px; + background: #ffffff; + border: 1px solid #d9dee4; +} + +.ADSdropzoneLocalFileName { + margin-bottom: 8px; + font-weight: 600; + word-break: break-all; +} diff --git a/SIG.Web/Styles/sig-grid-agrupado.css b/SIG.Web/Styles/sig-grid-agrupado.css index 355e93e..5173398 100644 --- a/SIG.Web/Styles/sig-grid-agrupado.css +++ b/SIG.Web/Styles/sig-grid-agrupado.css @@ -1,6 +1,79 @@ -.sig-grid-agrupado .sig-grid-grupo > td { padding: 0; background: #eef5f9; } -.sig-grid-agrupado .sig-grid-alternar-grupo { width: 100%; border: 0; background: transparent; padding: 10px 12px; text-align: left; font-weight: 600; } -.sig-grid-agrupado .sig-grid-alternar-grupo .fa { float: right; margin-top: 3px; } -.sig-grid-agrupado tr[data-sig-level="1"] > td:first-child { padding-left: 24px; } -.sig-grid-agrupado tr[data-sig-level="2"] > td:first-child { padding-left: 42px; } -.sig-grid-agrupado tr[data-sig-level="3"] > td:first-child { padding-left: 60px; } +.sig-grid-agrupado .sig-grid-columna-grupo { + display: none; +} + +.sig-grid-agrupado tr.sig-grid-grupo { + position: relative; + height: 38px; +} + +.sig-grid-agrupado tr.sig-grid-grupo > td.sig-grid-columna-grupo { + display: block; + position: absolute; + left: 0; + right: 0; + top: 0; + min-height: 38px; + padding: 0; + background: #eef5f9; + box-sizing: border-box; +} + +.sig-grid-agrupado tr.sig-grid-grupo > td.sig-grid-columna-normal { + display: none; +} + +.sig-grid-agrupado tr.sig-grid-fila-dato > td.sig-grid-columna-grupo { + display: none; +} + +.sig-grid-agrupado .sig-grid-alternar-grupo { + width: 100%; + min-height: 38px; + border: 0; + background: transparent; + padding: 10px 12px; + text-align: left; + font-weight: 600; +} + +.sig-grid-agrupado .sig-grid-alternar-grupo .fa { + float: right; + margin-top: 3px; +} + +.sig-grid-agrupado tr[data-sig-level="1"] > td.sig-grid-columna-dato-principal { + padding-left: 24px; +} + +.sig-grid-agrupado tr[data-sig-level="2"] > td.sig-grid-columna-dato-principal { + padding-left: 42px; +} + +.sig-grid-agrupado tr[data-sig-level="3"] > td.sig-grid-columna-dato-principal { + padding-left: 60px; +} + +.sig-columna-acciones { + width: 1%; + white-space: nowrap; + text-align: center; +} + +.sig-columna-acciones .btn { + margin: 1px; +} + +.sig-accion-icono { + width: 28px; + height: 28px; + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; + vertical-align: middle; +} + +.sig-accion-icono-redondo { + border-radius: 50% !important; +} diff --git a/SIG.Web/UserControl/Clientes/DocumentosCliente.ascx b/SIG.Web/UserControl/Clientes/DocumentosCliente.ascx index bbb7f98..2c6a34b 100644 --- a/SIG.Web/UserControl/Clientes/DocumentosCliente.ascx +++ b/SIG.Web/UserControl/Clientes/DocumentosCliente.ascx @@ -1,4 +1,4 @@ -<%@ Control Language="C#" AutoEventWireup="false" CodeFile="DocumentosCliente.ascx.cs" +<%@ Control Language="C#" AutoEventWireup="false" CodeFile="DocumentosCliente.ascx.cs" Inherits="SIG.Web.UserControl.Clientes.DocumentosCliente" %> - + + + + + + + - + - Cargar / renovar @@ -118,10 +131,9 @@ diff --git a/SIG.Web/UserControl/DocumentosEtapa.ascx.cs b/SIG.Web/UserControl/DocumentosEtapa.ascx.cs index d16816b..7a49f19 100644 --- a/SIG.Web/UserControl/DocumentosEtapa.ascx.cs +++ b/SIG.Web/UserControl/DocumentosEtapa.ascx.cs @@ -1,9 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Web.UI; -using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using SIG.Web.AppCode.Configuration; using SIG.Web.AppCode.Infrastructure.WebForms; @@ -18,6 +17,8 @@ namespace SIG.Web.UserControl public event EventHandler Cambiado; public event EventHandler AdministrarGisSolicitado; + #region Propiedades + public int CveEtapaGis { get { return DocumentoSeleccionado == null ? 0 : DocumentoSeleccionado.CveFraccionamientoEtapa; } @@ -67,6 +68,8 @@ namespace SIG.Web.UserControl get { return DocumentosActuales.Count; } } + #endregion + protected override void OnInit(EventArgs argumentos) { base.OnInit(argumentos); @@ -213,6 +216,15 @@ namespace SIG.Web.UserControl return; } + for (int indiceCelda = 0; indiceCelda < argumentos.Row.Cells.Count; indiceCelda++) + { + string claseCelda = indiceCelda == 0 + ? "sig-grid-columna-grupo" + : "sig-grid-columna-normal"; + argumentos.Row.Cells[indiceCelda].CssClass = + (argumentos.Row.Cells[indiceCelda].CssClass + " " + claseCelda).Trim(); + } + argumentos.Row.Attributes["data-sig-level"] = fila.Nivel.ToString(CultureInfo.InvariantCulture); @@ -223,44 +235,17 @@ namespace SIG.Web.UserControl if (!fila.EsGrupo) { + argumentos.Row.CssClass = + (argumentos.Row.CssClass + " sig-grid-fila-dato").Trim(); argumentos.Row.Attributes["data-sig-item-row"] = "1"; return; } - int columnasVisibles = Documentos.Columns - .Cast() - .Count(columna => columna.Visible); - - argumentos.Row.Cells.Clear(); argumentos.Row.CssClass = "sig-grid-grupo"; argumentos.Row.Attributes["data-sig-group-row"] = "1"; argumentos.Row.Attributes["data-sig-group-id"] = fila.GroupId; argumentos.Row.Attributes["data-sig-expanded-default"] = fila.AbiertoInicialmente ? "true" : "false"; - - var celda = new TableCell - { - ColumnSpan = columnasVisibles - }; - - var boton = new HtmlGenericControl("button"); - boton.Attributes["type"] = "button"; - boton.Attributes["class"] = "sig-grid-alternar-grupo"; - boton.Attributes["aria-expanded"] = fila.AbiertoInicialmente ? "true" : "false"; - - var titulo = new HtmlGenericControl("span"); - titulo.Attributes["class"] = "sig-grid-grupo-titulo"; - titulo.InnerText = fila.TituloGrupo; - - var flecha = new HtmlGenericControl("i"); - flecha.Attributes["class"] = "fa " + - (fila.AbiertoInicialmente ? "fa-chevron-up" : "fa-chevron-down"); - flecha.Attributes["aria-hidden"] = "true"; - - boton.Controls.Add(titulo); - boton.Controls.Add(flecha); - celda.Controls.Add(boton); - argumentos.Row.Cells.Add(celda); } public sealed class FilaDocumentoEtapa @@ -303,6 +288,11 @@ namespace SIG.Web.UserControl get { return Documento == null ? string.Empty : Documento.EstadoDocumento; } } + public bool EsRequerido + { + get { return Documento != null && Documento.EsRequerido; } + } + public string Nota { get { return Documento == null ? string.Empty : Documento.Nota; } @@ -401,6 +391,12 @@ namespace SIG.Web.UserControl case "Aprobar": case "CancelarDocumento": return documento.PuedeRevisar; + case "QuitarRequerido": + return Usuario != null && !Usuario.EsDesarrollador && documento.EsRequerido; + case "ActivarRequerido": + return Usuario != null && !Usuario.EsDesarrollador && !documento.EsRequerido; + case "EditarVencimiento": + return Usuario != null && !Usuario.EsDesarrollador && documento.TieneArchivo; case "Eliminar": return documento.TieneArchivo && documento.PuedeActualizarArchivo; default: @@ -455,6 +451,18 @@ namespace SIG.Web.UserControl return; } + if (argumentos.CommandName == "QuitarRequerido") + { + CambiarRequerido(false); + return; + } + + if (argumentos.CommandName == "ActivarRequerido") + { + CambiarRequerido(true); + return; + } + if (argumentos.CommandName == "AdministrarGis") { if (AdministrarGisSolicitado != null) @@ -479,11 +487,31 @@ namespace SIG.Web.UserControl ConfigurarFormulario("Cargar", DocumentoSeleccionado.TipoDocumento); ReglasArchivo.Text = "Permitidos: " + contexto.Data.ExtensionesPermitidas + (contexto.Data.TamanoMaximoMb.HasValue ? " · Máximo " + contexto.Data.TamanoMaximoMb + " MB" : ""); - FechaDocumento.Text = FormatearFecha(contexto.Data.FechaDocumentoAnterior); + CargaArchivoWebHelper.Configurar( + Archivo, + contexto.Data.ExtensionesPermitidas, + contexto.Data.TamanoMaximoMb, + 1); + FechaDocumento.Text = FormatearFecha(DateTime.Today); + FechaDocumento.Attributes["max"] = FormatearFecha(DateTime.Today); FechaVencimiento.Text = FormatearFecha(contexto.Data.FechaVencimientoAnterior); Nota.Text = contexto.Data.ComentarioClienteAnterior ?? string.Empty; MostrarFormulario(); } + else if (argumentos.CommandName == "EditarVencimiento") + { + if (Usuario == null || Usuario.EsDesarrollador) + { + Avisar("La fecha de vencimiento sólo puede ser editada por Agua de Hermosillo."); + return; + } + + ConfigurarFormulario( + "EditarVencimiento", + "Fecha de vencimiento: " + DocumentoSeleccionado.TipoDocumento); + FechaVencimientoEdicion.Text = FormatearFecha(DocumentoSeleccionado.FechaVencimiento); + MostrarFormulario(); + } else if (argumentos.CommandName == "Aprobar") { Revisar(true); @@ -518,7 +546,8 @@ namespace SIG.Web.UserControl { DateTime? fecha; DateTime? vencimiento; - if (DocumentoSeleccionado == null || !Archivo.HasFile || + var archivo = CargaArchivoWebHelper.ObtenerArchivo(Page, Archivo); + if (DocumentoSeleccionado == null || archivo == null || !LeerFecha(FechaDocumento.Text, out fecha) || !LeerFecha(FechaVencimiento.Text, out vencimiento)) { MostrarFormulario(); @@ -527,8 +556,8 @@ namespace SIG.Web.UserControl } var resultado = AppServices.TramiteDocumentoService.Upload( CveFraccionamientoActual, 0, DocumentoSeleccionado.CveTipoDocumento, - Archivo.FileName, Archivo.PostedFile.ContentType, Archivo.PostedFile.InputStream, - Archivo.PostedFile.ContentLength, Nota.Text, Usuario.CveUsuario, Usuario.NombreDominio, + archivo.FileName, archivo.ContentType, archivo.InputStream, + archivo.ContentLength, Nota.Text, Usuario.CveUsuario, Usuario.NombreDominio, fecha, vencimiento, DocumentoSeleccionado.CveFraccionamientoEtapa); if (!resultado.Success) { @@ -539,6 +568,39 @@ namespace SIG.Web.UserControl Terminar("Documento guardado; pendiente de revisión."); } + protected void GuardarFechaVencimiento(object origen, EventArgs argumentos) + { + if (DocumentoSeleccionado == null || Usuario == null || Usuario.EsDesarrollador) + { + Avisar("La fecha de vencimiento sólo puede ser editada por Agua de Hermosillo."); + return; + } + + DateTime? fechaVencimiento; + if (!LeerFecha(FechaVencimientoEdicion.Text, out fechaVencimiento)) + { + MostrarFormulario(); + Avisar("Capture una fecha de vencimiento válida."); + return; + } + + var resultado = AppServices.TramiteDocumentoService.ActualizarFechaVencimiento( + CveFraccionamientoActual, + DocumentoSeleccionado.CveDocumentoSolicitud, + fechaVencimiento, + Usuario.CveUsuario, + Usuario.NombreDominio); + + if (!resultado.Success) + { + MostrarFormulario(); + Avisar(resultado.UserMessage); + return; + } + + Terminar("Fecha de vencimiento actualizada."); + } + protected void CancelarDocumento(object origen, EventArgs argumentos) { Revisar(false); @@ -688,17 +750,70 @@ namespace SIG.Web.UserControl Terminar("Requerimiento guardado."); } + private void CambiarRequerido(bool esRequerido) + { + if (DocumentoSeleccionado == null || Usuario == null || Usuario.EsDesarrollador) + { + Avisar("El cambio de requerido corresponde a Agua de Hermosillo."); + return; + } + + var configuraciones = AppServices.TramiteDocumentoService.ListarConfiguracionSolicitud( + CveFraccionamientoActual, + DocumentoSeleccionado.CveSolicitud, + Usuario.CveUsuario, + Usuario.NombreDominio, + DocumentoSeleccionado.CveFraccionamientoEtapa); + + if (!configuraciones.Success) + { + Avisar(configuraciones.UserMessage); + return; + } + + SolicitudDocumentoConfiguracionModel configuracion = + (configuraciones.Data ?? new List()) + .FirstOrDefault(documento => + documento.CveTipoDocumento == DocumentoSeleccionado.CveTipoDocumento); + + if (configuracion == null) + { + Avisar("El requisito del documento ya no está disponible."); + return; + } + + configuracion.EsRequerido = esRequerido; + + var resultado = AppServices.TramiteDocumentoService.GuardarConfiguracionSolicitud( + configuracion, + Usuario.CveUsuario, + Usuario.NombreDominio); + + if (!resultado.Success) + { + Avisar(resultado.UserMessage); + return; + } + + Terminar(esRequerido + ? "Documento marcado como requerido." + : "Documento marcado como no requerido."); + } + private void ConfigurarFormulario(string accion, string titulo) { bool cargar = accion == "Cargar"; bool solicitar = accion == "Solicitar"; bool cancelar = accion == "CancelarDocumento"; + bool editarVencimiento = accion == "EditarVencimiento"; TituloFormulario.Text = titulo; CamposArchivo.Visible = cargar; CamposSolicitud.Visible = solicitar; + CamposVencimiento.Visible = editarVencimiento; CamposNota.Visible = cargar || cancelar; GuardarArchivo.Visible = cargar; GuardarSolicitud.Visible = solicitar; + GuardarVencimiento.Visible = editarVencimiento; GuardarCancelacion.Visible = cancelar; } diff --git a/SIG.Web/UserControl/DocumentosSolicitud.ascx b/SIG.Web/UserControl/DocumentosSolicitud.ascx index e782ec4..b03d447 100644 --- a/SIG.Web/UserControl/DocumentosSolicitud.ascx +++ b/SIG.Web/UserControl/DocumentosSolicitud.ascx @@ -87,8 +87,8 @@

- - + +
diff --git a/SIG.Web/UserControl/DocumentosSolicitud.ascx.cs b/SIG.Web/UserControl/DocumentosSolicitud.ascx.cs index cb3a023..6d4f065 100644 --- a/SIG.Web/UserControl/DocumentosSolicitud.ascx.cs +++ b/SIG.Web/UserControl/DocumentosSolicitud.ascx.cs @@ -21,6 +21,8 @@ namespace SIG.Web.UserControl public event EventHandler Cambiado; public event EventHandler MostrarSolicitado; + #region Propiedades + private int CveSolicitudActual { get { return (int?)ViewState["CveSolicitudActual"] ?? 0; } @@ -44,6 +46,8 @@ namespace SIG.Web.UserControl get { return AppServices.UserContext.GetCurrentUser(); } } + #endregion + protected override void OnInit(EventArgs argumentos) { base.OnInit(argumentos); @@ -192,10 +196,15 @@ namespace SIG.Web.UserControl TramiteDocumentoUploadContextModel contexto = resultado.Data; DatosArchivo.Text = "Permitidos: " + contexto.ExtensionesPermitidas + (contexto.TamanoMaximoMb.HasValue ? " · Máximo " + contexto.TamanoMaximoMb + " MB" : ""); - FechaDocumento.Text = contexto.FechaDocumentoAnterior.HasValue - ? contexto.FechaDocumentoAnterior.Value.ToString("yyyy-MM-dd") : ""; + CargaArchivoWebHelper.Configurar( + Archivo, + contexto.ExtensionesPermitidas, + contexto.TamanoMaximoMb, + 1); + FechaDocumento.Text = DateTime.Today.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); + FechaDocumento.Attributes["max"] = DateTime.Today.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); VencimientoDocumento.Text = contexto.FechaVencimientoAnterior.HasValue - ? contexto.FechaVencimientoAnterior.Value.ToString("yyyy-MM-dd") : ""; + ? contexto.FechaVencimientoAnterior.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) : ""; ComentarioDocumento.Text = contexto.ComentarioClienteAnterior ?? ""; return true; } @@ -209,7 +218,8 @@ namespace SIG.Web.UserControl { DateTime? fecha; DateTime? vencimiento; - if (!Archivo.HasFile || string.IsNullOrEmpty(TipoDocumento.SelectedValue)) + var archivo = CargaArchivoWebHelper.ObtenerArchivo(Page, Archivo); + if (archivo == null || string.IsNullOrEmpty(TipoDocumento.SelectedValue)) { MostrarDocumento(); Avisar("Seleccione un documento y un archivo."); @@ -227,8 +237,8 @@ namespace SIG.Web.UserControl AppServices.TramiteDocumentoService.Upload( CveFraccionamientoActual, CveSolicitudActual, Convert.ToInt32(TipoDocumento.SelectedValue, CultureInfo.InvariantCulture), - Archivo.FileName, Archivo.PostedFile.ContentType, - Archivo.PostedFile.InputStream, Archivo.PostedFile.ContentLength, + archivo.FileName, archivo.ContentType, + archivo.InputStream, archivo.ContentLength, ComentarioDocumento.Text, Usuario.CveUsuario, Usuario.NombreDominio, fecha, vencimiento); if (!resultado.Success)