diff --git a/SIG.Web/App_Code/Configuration/AppServices.cs b/SIG.Web/App_Code/Configuration/AppServices.cs index 53f50e5..34e49e4 100644 --- a/SIG.Web/App_Code/Configuration/AppServices.cs +++ b/SIG.Web/App_Code/Configuration/AppServices.cs @@ -1,8 +1,11 @@ -using System; +using System; using System.Configuration; using SIG.Web.AppCode.Contracts.Clientes; +using SIG.Web.AppCode.Contracts.Convenios; using SIG.Web.AppCode.Repositories.Clientes; +using SIG.Web.AppCode.Repositories.Convenios; using SIG.Web.AppCode.Services.Clientes; +using SIG.Web.AppCode.Services.Convenios; using SIG.Web.AppCode.Contracts.Bitacora; using SIG.Web.AppCode.Contracts.Database; using SIG.Web.AppCode.Contracts.Documentos; @@ -66,6 +69,7 @@ namespace SIG.Web.AppCode.Configuration public static ITramiteSolicitudService TramiteSolicitudService { get; private set; } public static IServicioVentaTramite ServicioVentaTramite { get; private set; } public static IServicioPagosConvenios ServicioPagosConvenios { get; private set; } + public static IServicioConvenios ServicioConvenios { get; private set; } public static IServicioTimbradoCfdi ServicioTimbradoCfdi { get; private set; } public static IPublicRegistrationService PublicRegistrationService { get; private set; } public static ILoginAttemptRepository LoginAttemptRepository { get; private set; } @@ -207,6 +211,7 @@ namespace SIG.Web.AppCode.Configuration PermissionService = new PermissionService( permissionRepository); + ServicioConvenios = new ServicioConvenios(new RepositorioConvenios(DbExecutor), 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 1a0187c..37f0a32 100644 --- a/SIG.Web/App_Code/Configuration/BundleConfig.cs +++ b/SIG.Web/App_Code/Configuration/BundleConfig.cs @@ -65,7 +65,8 @@ namespace SIG.Web.AppCode.Configuration "~/Scripts/sig-alerts.js", "~/Scripts/filtrosig.js", "~/Scripts/scrollsig.js", - "~/Scripts/sig-grid-agrupado.js" + "~/Scripts/sig-grid-agrupado.js", + "~/Scripts/Convenios.js" )); bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include( "~/Scripts/WebForms/WebForms.js", @@ -130,6 +131,7 @@ namespace SIG.Web.AppCode.Configuration "~/Styles/filtrosig.css", "~/Styles/scrollsig.css", "~/Styles/sig-grid-agrupado.css", + "~/Styles/Convenios.css", "~/Metronic/assets/global/plugins/bootstrap-switch/css/bootstrap-switch.min.css", "~/Metronic/assets/global/plugins/bootstrap-toastr/toastr.min.css", "~/Metronic/assets/layouts/layout3/css/jquery.datetimepicker.css", diff --git a/SIG.Web/App_Code/Contracts/Clientes/IRepositorioPortalCliente.cs b/SIG.Web/App_Code/Contracts/Clientes/IRepositorioPortalCliente.cs new file mode 100644 index 0000000..8ad7019 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Clientes/IRepositorioPortalCliente.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Clientes; +using SIG.Web.AppCode.Models.Common; + +namespace SIG.Web.AppCode.Contracts.Clientes +{ + public interface IRepositorioPortalCliente + { + DbResult> ListarPagos( + int cveCliente, + int? cveFraccionamiento, + int? cveFraccionamientoEtapa, + string agrupacion, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarRecibosDisponibles( + int cveCliente, + int? cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult AgregarPago( + SolicitudPagoConvenioCliente pago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerArchivoPago( + int cveConvenioPago, + int cveCliente, + int cveUsuarioEjecuta, + string nombreDominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Clientes/IServicioPortalCliente.cs b/SIG.Web/App_Code/Contracts/Clientes/IServicioPortalCliente.cs new file mode 100644 index 0000000..57cced7 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Clientes/IServicioPortalCliente.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.IO; +using SIG.Web.AppCode.Models.Clientes; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Fraccionamientos; +using SIG.Web.AppCode.Models.Tramites; + +namespace SIG.Web.AppCode.Contracts.Clientes +{ + public interface IServicioPortalCliente + { + DbResult> ListarDesarrollos( + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerFraccionamiento( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarEtapas( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarTramites( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult EnviarRevision( + int cveSolicitud, + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarDocumentos( + FiltroDocumentosCliente filtro, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarPagos( + FiltroPagosCliente filtro, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarRecibosDisponibles( + int? cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult RegistrarPago( + SolicitudPagoConvenioCliente pago, + Stream contenido, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerArchivoPago( + int cveConvenioPago, + int cveUsuarioEjecuta, + string nombreDominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Convenios/IRepositorioConvenios.cs b/SIG.Web/App_Code/Contracts/Convenios/IRepositorioConvenios.cs new file mode 100644 index 0000000..b549252 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Convenios/IRepositorioConvenios.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Convenios; + +namespace SIG.Web.AppCode.Contracts.Convenios +{ + public interface IRepositorioConvenios + { + DbResult> Listar(FiltroConvenios filtro, int usuario, string dominio); + DbResult Obtener(int cveConvenio, int usuario, string dominio); + DbResult> ListarConceptos(int usuario, string dominio); + DbResult Agregar(SolicitudAltaConvenio solicitud, int usuario, string dominio); + DbResult Eliminar(int cveConvenio, int usuario, string dominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Convenios/IServicioConvenios.cs b/SIG.Web/App_Code/Contracts/Convenios/IServicioConvenios.cs new file mode 100644 index 0000000..b1c4c67 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Convenios/IServicioConvenios.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Convenios; + +namespace SIG.Web.AppCode.Contracts.Convenios +{ + public interface IServicioConvenios + { + DbResult> Listar(FiltroConvenios filtro, int usuario, string dominio); + DbResult Obtener(int cveConvenio, int usuario, string dominio); + DbResult> ListarConceptos(int usuario, string dominio); + DbResult Agregar(SolicitudAltaConvenio solicitud, int usuario, string dominio); + DbResult Eliminar(int cveConvenio, int usuario, string dominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Documentos/IAlmacenComprobantesConvenio.cs b/SIG.Web/App_Code/Contracts/Documentos/IAlmacenComprobantesConvenio.cs new file mode 100644 index 0000000..104a224 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Documentos/IAlmacenComprobantesConvenio.cs @@ -0,0 +1,20 @@ +using System.IO; +using SIG.Web.AppCode.Models.Clientes; + +namespace SIG.Web.AppCode.Contracts.Documentos +{ + public interface IAlmacenComprobantesConvenio + { + void Guardar( + SolicitudPagoConvenioCliente pago, + Stream contenido); + + string Resolver( + int cveCliente, + string nombreFisico); + + void Eliminar( + int cveCliente, + string nombreFisico); + } +} diff --git a/SIG.Web/App_Code/Handlers/Clientes/ComprobanteConvenioPagoHandler.cs b/SIG.Web/App_Code/Handlers/Clientes/ComprobanteConvenioPagoHandler.cs new file mode 100644 index 0000000..4ef6461 --- /dev/null +++ b/SIG.Web/App_Code/Handlers/Clientes/ComprobanteConvenioPagoHandler.cs @@ -0,0 +1,73 @@ +using System; +using System.Globalization; +using System.IO; +using System.Web; +using System.Web.SessionState; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Models.Clientes; +using SIG.Web.AppCode.Session; + +namespace SIG.Web.Pages.Clientes +{ + public sealed class ComprobanteConvenioPagoHandler + : IHttpHandler, IReadOnlySessionState + { + public bool IsReusable + { + get { return false; } + } + + public void ProcessRequest(HttpContext contexto) + { + UserSessionModel usuario = AppServices.UserContext.GetCurrentUser(); + + if (usuario == null || + !AppServices.UserContext.IsAuthenticated() || + !usuario.EsDesarrollador) + { + contexto.Response.StatusCode = 401; + return; + } + + int cvePago; + + if (!int.TryParse( + contexto.Request.QueryString["id"], + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cvePago) || + cvePago <= 0) + { + contexto.Response.StatusCode = 404; + return; + } + + var resultado = AppServices.ServicioPortalCliente.ObtenerArchivoPago( + cvePago, + usuario.CveUsuario, + usuario.NombreDominio); + + if (!resultado.Success || + resultado.Data == null || + string.IsNullOrWhiteSpace(resultado.Data.RutaFisica) || + !File.Exists(resultado.Data.RutaFisica)) + { + contexto.Response.StatusCode = 404; + return; + } + + ArchivoPagoConvenioCliente archivo = resultado.Data; + contexto.Response.Clear(); + contexto.Response.ContentType = archivo.TipoContenido; + contexto.Response.AddHeader("X-Content-Type-Options", "nosniff"); + contexto.Response.AddHeader( + "Content-Disposition", + "attachment; filename*=UTF-8''" + + Uri.EscapeDataString(archivo.NombreArchivo)); + contexto.Response.Cache.SetCacheability(HttpCacheability.NoCache); + contexto.Response.Cache.SetNoStore(); + contexto.Response.TransmitFile(archivo.RutaFisica); + contexto.ApplicationInstance.CompleteRequest(); + } + } +} diff --git a/SIG.Web/App_Code/Models/Clientes/ModelosPortalCliente.cs b/SIG.Web/App_Code/Models/Clientes/ModelosPortalCliente.cs new file mode 100644 index 0000000..dd5fdc8 --- /dev/null +++ b/SIG.Web/App_Code/Models/Clientes/ModelosPortalCliente.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; + +namespace SIG.Web.AppCode.Models.Clientes +{ + [Serializable] + public sealed class FiltroDocumentosCliente + { + public int? CveFraccionamiento { get; set; } + public int? CveFraccionamientoEtapa { get; set; } + public string Agrupacion { get; set; } + } + + [Serializable] + public sealed class DocumentoClientePortal + { + public int CveDocumentoSolicitud { get; set; } + public int CveSolicitud { get; set; } + public int CveCliente { get; set; } + public int CveFraccionamiento { get; set; } + public string Fraccionamiento { 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 string NombreArchivo { get; set; } + public string Nota { get; set; } + public bool? EsAprobado { get; set; } + public DateTime? FechaDocumento { get; set; } + public DateTime? FechaVencimiento { get; set; } + public bool TieneArchivo { get; set; } + public bool EsCliente { get; set; } + public bool PuedeActualizarArchivo { get; set; } + public bool EsRequerido { get; set; } + public bool TieneVigencia { get; set; } + public bool FechaExpirada { get; set; } + public string EstadoDocumento { get; set; } + public string Agrupacion { get; set; } + } + + [Serializable] + public sealed class FiltroPagosCliente + { + public int? CveFraccionamiento { get; set; } + public int? CveFraccionamientoEtapa { get; set; } + public string Agrupacion { get; set; } + } + + [Serializable] + public sealed class PagoConvenioClienteFila + { + public string TipoRegistro { get; set; } + public string Agrupacion { get; set; } + public int CveCliente { get; set; } + public int CveFraccionamiento { get; set; } + public string Fraccionamiento { get; set; } + public int CveFraccionamientoEtapa { get; set; } + public string Etapa { get; set; } + public int? CveSolicitud { get; set; } + public int CveConvenio { get; set; } + public string NumeroConvenio { get; set; } + public int? CveConvenioDetalle { get; set; } + public string Concepto { get; set; } + public int? CveConvenioRecibo { get; set; } + public string NumeroRecibo { get; set; } + public int? CveConvenioPago { get; set; } + public decimal Importe { get; set; } + public decimal ImporteAplicado { get; set; } + public decimal SaldoPendiente { get; set; } + public DateTime Fecha { get; set; } + public string Estatus { get; set; } + public string Referencia { get; set; } + public string NumeroOperacion { get; set; } + public string NombreArchivo { get; set; } + public string RecibosAplicados { get; set; } + public string Observaciones { get; set; } + + public bool EsReciboPendiente + { + get + { + return string.Equals( + TipoRegistro, + "RECIBO", + StringComparison.OrdinalIgnoreCase) && + string.Equals( + Agrupacion, + "Pendientes", + StringComparison.OrdinalIgnoreCase); + } + } + } + + [Serializable] + public sealed class ReciboConvenioDisponibleCliente + { + public int CveConvenioRecibo { get; set; } + public int CveCliente { get; set; } + public int CveFraccionamiento { get; set; } + public string Fraccionamiento { get; set; } + public int CveFraccionamientoEtapa { get; set; } + public string Etapa { get; set; } + public int CveConvenio { get; set; } + public string NumeroConvenio { get; set; } + public string Concepto { get; set; } + public string NumeroRecibo { get; set; } + public decimal Importe { get; set; } + public decimal ImporteAplicado { get; set; } + public decimal SaldoPendiente { get; set; } + public DateTime FechaVencimiento { get; set; } + + public string Descripcion + { + get + { + return string.Format( + System.Globalization.CultureInfo.CurrentCulture, + "{0} · {1} · {2} · saldo {3:N2}", + Fraccionamiento, + Etapa, + NumeroRecibo, + SaldoPendiente); + } + } + } + + [Serializable] + public sealed class AplicacionPagoConvenioCliente + { + public int CveConvenioRecibo { get; set; } + public string NumeroRecibo { get; set; } + public string Fraccionamiento { get; set; } + public string Etapa { get; set; } + public string Concepto { get; set; } + public decimal SaldoPendiente { get; set; } + public decimal ImporteAplicado { get; set; } + } + + [Serializable] + public sealed class SolicitudPagoConvenioCliente + { + public int CveCliente { get; set; } + public decimal Importe { get; set; } + public DateTime FechaPago { get; set; } + public string Referencia { get; set; } + public string Banco { get; set; } + public string NumeroOperacion { get; set; } + public string Observaciones { get; set; } + public string NombreArchivo { get; set; } + public string NombreFisico { get; set; } + public string TipoContenido { get; set; } + public long TamanoBytes { get; set; } + public List Aplicaciones { get; set; } + } + + public sealed class ArchivoPagoConvenioCliente + { + public int CveConvenioPago { get; set; } + public int CveCliente { get; set; } + public string NombreArchivo { get; set; } + public string NombreFisico { get; set; } + public string TipoContenido { get; set; } + public long TamanoBytes { get; set; } + public string RutaFisica { get; set; } + } + + public sealed class TramiteClienteListado + { + public int CveSolicitud { get; set; } + public string Folio { 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 CveEstatusSolicitud { get; set; } + public string EstatusSolicitud { get; set; } + public int DocumentosPendientes { get; set; } + public int PagosPendientes { get; set; } + public bool PuedeEnviarRevision { get; set; } + + public string TextoDocumentos + { + get + { + return DocumentosPendientes == 0 + ? "Completo" + : DocumentosPendientes + " pendiente(s)"; + } + } + + public string TextoPagos + { + get + { + return PagosPendientes == 0 + ? "Sin pendientes" + : PagosPendientes + " pendiente(s)"; + } + } + } +} diff --git a/SIG.Web/App_Code/Models/Convenios/ModelosConvenios.cs b/SIG.Web/App_Code/Models/Convenios/ModelosConvenios.cs new file mode 100644 index 0000000..b978dfb --- /dev/null +++ b/SIG.Web/App_Code/Models/Convenios/ModelosConvenios.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; + +namespace SIG.Web.AppCode.Models.Convenios +{ + [Serializable] + public sealed class FiltroConvenios + { + public int? CveCliente { get; set; } + public int? CveFraccionamiento { get; set; } + public int? CveFraccionamientoEtapa { get; set; } + public string Estatus { get; set; } + public bool? ConSaldoPendiente { get; set; } + } + + public sealed class ConvenioListado + { + public int CveConvenio { get; set; } + public int CveCliente { get; set; } + public string Cliente { get; set; } + public int CveFraccionamiento { get; set; } + public string Fraccionamiento { get; set; } + public int CveFraccionamientoEtapa { get; set; } + public string Etapa { get; set; } + public string NumeroConvenio { get; set; } + public string NumeroOficio { get; set; } + public string Estatus { get; set; } + public DateTime FechaConvenio { get; set; } + public decimal ImporteConvenio { get; set; } + public decimal ImportePagado { get; set; } + public decimal SaldoPendiente { get; set; } + public bool TienePagos { get; set; } + public bool PuedeEliminar { get { return !TienePagos; } } + } + + public sealed class ConvenioDetalleEncabezado + { + public int CveConvenio { get; set; } + public int CveCliente { get; set; } + public int CveFraccionamientoEtapa { get; set; } + public string NumeroConvenio { get; set; } + public string NumeroOficio { get; set; } + public string Cliente { get; set; } + public string Fraccionamiento { get; set; } + public string Etapa { get; set; } + public string Estatus { get; set; } + public DateTime FechaConvenio { get; set; } + public int? ViviendasAutorizadas { get; set; } + public int ViviendasEnConvenio { get; set; } + public int? ViviendasPendientes { get; set; } + public int? ViviendasContratadas { get; set; } + public string Observaciones { get; set; } + public decimal ImporteConvenio { get; set; } + public decimal ImportePagado { get; set; } + public decimal SaldoPendiente { get; set; } + } + + public sealed class ConvenioConceptoDetalle + { + public int CveConvenioDetalle { get; set; } + public int CveConvenioConcepto { get; set; } + public string Concepto { get; set; } + public decimal Importe { get; set; } + public string Tipo { get; set; } + public int NumeroPagos { get; set; } + } + + public sealed class ConvenioReciboDetalle + { + public int CveConvenioRecibo { get; set; } + public int CveConvenioDetalle { get; set; } + public string NumeroRecibo { get; set; } + public decimal Importe { get; set; } + public decimal ImportePagado { get; set; } + public decimal SaldoPendiente { get; set; } + public DateTime FechaVencimiento { get; set; } + public string Estatus { get; set; } + } + + public sealed class ConvenioDetalleCompleto + { + public ConvenioDetalleEncabezado Encabezado { get; set; } + public List Conceptos { get; set; } + public List Recibos { get; set; } + } + + public sealed class ConvenioConceptoCatalogo + { + public int CveConvenioConcepto { get; set; } + public string Concepto { get; set; } + public string Descripcion { get; set; } + } + + [Serializable] + public sealed class SolicitudAltaConvenio + { + public int CveCliente { get; set; } + public int CveFraccionamientoEtapa { get; set; } + public string NumeroConvenio { get; set; } + public string NumeroOficio { get; set; } + public int? ViviendasAutorizadas { get; set; } + public int ViviendasEnConvenio { get; set; } + public int? ViviendasPendientes { get; set; } + public int? ViviendasContratadas { get; set; } + public DateTime FechaConvenio { get; set; } + public string Observaciones { get; set; } + public List Conceptos { get; set; } + } + + [Serializable] + public sealed class ConvenioConceptoCaptura + { + public int ClaveTemporal { get; set; } + public int CveConvenioConcepto { get; set; } + public string Concepto { get; set; } + public decimal Importe { get; set; } + public string Tipo { get; set; } + public int NumeroPagos { get; set; } + public List Parcialidades { get; set; } + } + + [Serializable] + public sealed class ConvenioReciboCaptura + { + public int Orden { get; set; } + public string NumeroRecibo { get; set; } + public decimal Importe { get; set; } + public DateTime FechaVencimiento { get; set; } + public string Estatus { get; set; } + } +} diff --git a/SIG.Web/App_Code/Repositories/Clientes/RepositorioPortalCliente.cs b/SIG.Web/App_Code/Repositories/Clientes/RepositorioPortalCliente.cs new file mode 100644 index 0000000..2ec5684 --- /dev/null +++ b/SIG.Web/App_Code/Repositories/Clientes/RepositorioPortalCliente.cs @@ -0,0 +1,216 @@ +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Xml.Linq; +using SIG.Web.AppCode.Contracts.Clientes; +using SIG.Web.AppCode.Contracts.Database; +using SIG.Web.AppCode.Models.Clientes; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Repositories.Database; + +namespace SIG.Web.AppCode.Repositories.Clientes +{ + public sealed class RepositorioPortalCliente + : RepositoryBase, IRepositorioPortalCliente + { + private const string ProcedimientoPagosListar = + "dbo.PA_Clientes_ConvenioPagoList"; + private const string ProcedimientoRecibosListar = + "dbo.PA_Clientes_ConvenioReciboPendienteList"; + private const string ProcedimientoPagoAgregar = + "dbo.PA_Clientes_ConvenioPagoAdd"; + private const string ProcedimientoPagoArchivoObtener = + "dbo.PA_Clientes_ConvenioPagoArchivoGet"; + + public RepositorioPortalCliente(IDbExecutor ejecutor) + : base(ejecutor) + { + } + + public DbResult> ListarPagos( + int cveCliente, + int? cveFraccionamiento, + int? cveFraccionamientoEtapa, + string agrupacion, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryList( + ProcedimientoPagosListar, + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + cveCliente, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamiento", + cveFraccionamiento, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamientoEtapa", + cveFraccionamientoEtapa, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Agrupacion", + agrupacion, + DbType.String); + }); + } + + public DbResult> ListarRecibosDisponibles( + int cveCliente, + int? cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryList( + ProcedimientoRecibosListar, + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + cveCliente, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamiento", + cveFraccionamiento, + DbType.Int32); + }); + } + + public DbResult AgregarPago( + SolicitudPagoConvenioCliente pago, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryScalarId( + ProcedimientoPagoAgregar, + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + pago.CveCliente, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Importe", + pago.Importe, + DbType.Decimal); + StoredProcedureCommand.AddInput( + comando, + "@FechaPago", + pago.FechaPago, + DbType.DateTime); + StoredProcedureCommand.AddInput( + comando, + "@Referencia", + pago.Referencia, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Banco", + pago.Banco, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NumeroOperacion", + pago.NumeroOperacion, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Observaciones", + pago.Observaciones, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NombreArchivo", + pago.NombreArchivo, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NombreFisico", + pago.NombreFisico, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@TipoContenido", + pago.TipoContenido, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@TamanoBytes", + pago.TamanoBytes, + DbType.Int64); + StoredProcedureCommand.AddInput( + comando, + "@AplicacionesXml", + SerializarAplicaciones(pago.Aplicaciones), + DbType.Xml); + }); + } + + public DbResult ObtenerArchivoPago( + int cveConvenioPago, + int cveCliente, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + ProcedimientoPagoArchivoObtener, + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveConvenioPago", + cveConvenioPago, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + cveCliente, + DbType.Int32); + }); + } + + private static string SerializarAplicaciones( + IEnumerable aplicaciones) + { + IEnumerable lista = + aplicaciones ?? Enumerable.Empty(); + + var raiz = new XElement( + "Aplicaciones", + lista.Select((aplicacion, indice) => + new XElement( + "Aplicacion", + new XAttribute("Orden", indice + 1), + new XAttribute( + "CveConvenioRecibo", + aplicacion.CveConvenioRecibo), + new XAttribute( + "ImporteAplicado", + aplicacion.ImporteAplicado.ToString( + "0.######", + CultureInfo.InvariantCulture))))); + + return raiz.ToString(SaveOptions.DisableFormatting); + } + } +} diff --git a/SIG.Web/App_Code/Repositories/Convenios/RepositorioConvenios.cs b/SIG.Web/App_Code/Repositories/Convenios/RepositorioConvenios.cs new file mode 100644 index 0000000..de3a80a --- /dev/null +++ b/SIG.Web/App_Code/Repositories/Convenios/RepositorioConvenios.cs @@ -0,0 +1,264 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Xml.Linq; +using SIG.Web.AppCode.Contracts.Convenios; +using SIG.Web.AppCode.Contracts.Database; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Convenios; +using SIG.Web.AppCode.Repositories.Database; +using SIG.Web.AppCode.Utilities; + +namespace SIG.Web.AppCode.Repositories.Convenios +{ + public sealed class RepositorioConvenios : RepositoryBase, IRepositorioConvenios + { + private const string ProcedimientoListar = "dbo.PA_Tra_ConvenioList"; + private const string ProcedimientoObtener = "dbo.PA_Tra_ConvenioGet"; + private const string ProcedimientoListarConceptos = "dbo.PA_Tra_ConvenioConceptoList"; + private const string ProcedimientoAgregar = "dbo.PA_Tra_ConvenioAdd"; + private const string ProcedimientoEliminar = "dbo.PA_Tra_ConvenioDelete"; + + public RepositorioConvenios(IDbExecutor ejecutor) + : base(ejecutor) + { + } + + public DbResult> Listar( + FiltroConvenios filtro, + int usuario, + string dominio) + { + filtro = filtro ?? new FiltroConvenios(); + + return QueryList( + ProcedimientoListar, + usuario, + dominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + filtro.CveCliente, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamiento", + filtro.CveFraccionamiento, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamientoEtapa", + filtro.CveFraccionamientoEtapa, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Estatus", + filtro.Estatus, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@ConSaldoPendiente", + filtro.ConSaldoPendiente, + DbType.Boolean); + }); + } + + public DbResult Obtener( + int cveConvenio, + int usuario, + string dominio) + { + return QueryReader( + ProcedimientoObtener, + usuario, + dominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@CveConvenio", + cveConvenio, + DbType.Int32), + lector => + { + var resultado = new ConvenioDetalleCompleto + { + Encabezado = lector.ToObject(), + Conceptos = new List(), + Recibos = new List() + }; + + if (!lector.NextResult()) + { + throw new InvalidOperationException( + "Falta el resultado de conceptos del convenio."); + } + + resultado.Conceptos = lector.ToList(); + + if (!lector.NextResult()) + { + throw new InvalidOperationException( + "Falta el resultado de recibos del convenio."); + } + + resultado.Recibos = lector.ToList(); + return resultado; + }); + } + + public DbResult> ListarConceptos( + int usuario, + string dominio) + { + return QueryList( + ProcedimientoListarConceptos, + usuario, + dominio, + null); + } + + public DbResult Agregar( + SolicitudAltaConvenio solicitud, + int usuario, + string dominio) + { + if (solicitud == null) + { + throw new ArgumentNullException("solicitud"); + } + + string conceptosXml = SerializarConceptos(solicitud.Conceptos); + + return QueryScalarId( + ProcedimientoAgregar, + usuario, + dominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + solicitud.CveCliente, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamientoEtapa", + solicitud.CveFraccionamientoEtapa, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@NumeroConvenio", + solicitud.NumeroConvenio, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NumeroOficio", + solicitud.NumeroOficio, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@ViviendasAutorizadas", + solicitud.ViviendasAutorizadas, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@ViviendasEnConvenio", + solicitud.ViviendasEnConvenio, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@ViviendasPendientes", + solicitud.ViviendasPendientes, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@ViviendasContratadas", + solicitud.ViviendasContratadas, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@FechaConvenio", + solicitud.FechaConvenio, + DbType.Date); + StoredProcedureCommand.AddInput( + comando, + "@Observaciones", + solicitud.Observaciones, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@ConceptosXml", + conceptosXml, + DbType.Xml); + }); + } + + public DbResult Eliminar( + int cveConvenio, + int usuario, + string dominio) + { + return Execute( + ProcedimientoEliminar, + usuario, + dominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@CveConvenio", + cveConvenio, + DbType.Int32)); + } + + private static string SerializarConceptos( + IEnumerable conceptos) + { + IEnumerable lista = + conceptos ?? Enumerable.Empty(); + + var raiz = new XElement( + "Conceptos", + lista.Select((concepto, indiceConcepto) => + new XElement( + "Concepto", + new XAttribute("Orden", indiceConcepto + 1), + new XAttribute( + "CveConvenioConcepto", + concepto.CveConvenioConcepto), + new XAttribute( + "Importe", + concepto.Importe.ToString( + "0.######", + CultureInfo.InvariantCulture)), + new XAttribute("Tipo", concepto.Tipo ?? string.Empty), + new XAttribute("NumeroPagos", concepto.NumeroPagos), + new XElement( + "Recibos", + (concepto.Parcialidades ?? + new List()) + .Select((recibo, indiceRecibo) => + new XElement( + "Recibo", + new XAttribute("Orden", indiceRecibo + 1), + new XAttribute( + "Importe", + recibo.Importe.ToString( + "0.######", + CultureInfo.InvariantCulture)), + new XAttribute( + "FechaVencimiento", + recibo.FechaVencimiento.ToString( + "yyyy-MM-dd", + CultureInfo.InvariantCulture)), + new XAttribute( + "Estatus", + string.IsNullOrWhiteSpace(recibo.Estatus) + ? "PENDIENTE" + : recibo.Estatus))))))); + + return raiz.ToString(SaveOptions.DisableFormatting); + } + } +} diff --git a/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs b/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs new file mode 100644 index 0000000..02151e0 --- /dev/null +++ b/SIG.Web/App_Code/Services/Clientes/ServicioPortalCliente.cs @@ -0,0 +1,708 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Transactions; +using SIG.Web.AppCode.Contracts.Clientes; +using SIG.Web.AppCode.Contracts.Documentos; +using SIG.Web.AppCode.Contracts.Fraccionamientos; +using SIG.Web.AppCode.Contracts.Security; +using SIG.Web.AppCode.Contracts.Tramites; +using SIG.Web.AppCode.Infrastructure; +using SIG.Web.AppCode.Infrastructure.Transactions; +using SIG.Web.AppCode.Models.Clientes; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Documentos; +using SIG.Web.AppCode.Models.Fraccionamientos; +using SIG.Web.AppCode.Models.Tramites; +using SIG.Web.AppCode.Session; + +namespace SIG.Web.AppCode.Services.Clientes +{ + public sealed class ServicioPortalCliente : IServicioPortalCliente + { + private readonly IRepositorioPortalCliente _repositorio; + private readonly IServicioFraccionamiento _servicioFraccionamiento; + private readonly ITramiteDocumentoService _servicioDocumentos; + private readonly ITramiteSolicitudService _servicioTramites; + private readonly IAlmacenComprobantesConvenio _almacenComprobantes; + private readonly IUserContextProvider _contextoUsuario; + + public ServicioPortalCliente( + IRepositorioPortalCliente repositorio, + IServicioFraccionamiento servicioFraccionamiento, + ITramiteDocumentoService servicioDocumentos, + ITramiteSolicitudService servicioTramites, + IAlmacenComprobantesConvenio almacenComprobantes, + IUserContextProvider contextoUsuario) + { + _repositorio = repositorio; + _servicioFraccionamiento = servicioFraccionamiento; + _servicioDocumentos = servicioDocumentos; + _servicioTramites = servicioTramites; + _almacenComprobantes = almacenComprobantes; + _contextoUsuario = contextoUsuario; + } + + public DbResult> ListarDesarrollos( + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo>(acceso.UserMessage); + } + + return _servicioFraccionamiento.ListarDesarrollos( + usuario.CveCliente, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult ObtenerFraccionamiento( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo(acceso.UserMessage); + } + + DbResult resultado = + _servicioFraccionamiento.Obtener( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success || resultado.Data == null) + { + return resultado; + } + + if (resultado.Data.CveCliente != usuario.CveCliente) + { + return Fallo( + "No tiene acceso al fraccionamiento seleccionado."); + } + + return resultado; + } + + public DbResult> ListarEtapas( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + DbResult fraccionamiento = + ObtenerFraccionamiento( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + + if (!fraccionamiento.Success) + { + return Fallo>( + fraccionamiento.UserMessage); + } + + return _servicioFraccionamiento.ListarEtapas( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult> ListarTramites( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo>(acceso.UserMessage); + } + + DbResult fraccionamiento = + ObtenerFraccionamiento( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + + if (!fraccionamiento.Success) + { + return Fallo>( + fraccionamiento.UserMessage); + } + + DbResult> solicitudes = + _servicioTramites.ListForDevelopment( + cveFraccionamiento, + null, + null, + null, + cveUsuarioEjecuta, + nombreDominio); + + if (!solicitudes.Success) + { + return DbResult>.Fail( + solicitudes.UserMessage, + solicitudes.TechnicalMessage, + solicitudes.Exception); + } + + DbResult> documentos = + _servicioDocumentos.ListarRequisitos( + cveFraccionamiento, + null, + null, + cveUsuarioEjecuta, + nombreDominio); + + if (!documentos.Success) + { + return DbResult>.Fail( + documentos.UserMessage, + documentos.TechnicalMessage, + documentos.Exception); + } + + DbResult> pagos = + _repositorio.ListarPagos( + usuario.CveCliente, + cveFraccionamiento, + null, + null, + cveUsuarioEjecuta, + nombreDominio); + + if (!pagos.Success) + { + return DbResult>.Fail( + pagos.UserMessage, + pagos.TechnicalMessage, + pagos.Exception); + } + + List documentosActuales = + documentos.Data ?? new List(); + List pagosActuales = + pagos.Data ?? new List(); + + List resultado = + (solicitudes.Data ?? new List()) + .Select(solicitud => + { + int documentosPendientes = documentosActuales.Count(documento => + ( + documento.CveSolicitud == solicitud.CveSolicitud || + ( + documento.CveSolicitud <= 0 && + documento.CveFraccionamientoEtapa == + solicitud.CveFraccionamientoEtapa && + documento.CveTipoTramite == + solicitud.CveTipoTramite + ) + ) && + documento.EsRequerido && + (!documento.TieneArchivo || documento.FechaExpirada)); + + int pagosPendientes = pagosActuales.Count(pago => + ( + pago.CveSolicitud == solicitud.CveSolicitud || + ( + !pago.CveSolicitud.HasValue && + pago.CveFraccionamientoEtapa == + solicitud.CveFraccionamientoEtapa + ) + ) && + pago.EsReciboPendiente && + pago.SaldoPendiente > 0m); + + return new TramiteClienteListado + { + CveSolicitud = solicitud.CveSolicitud, + Folio = solicitud.Folio, + CveFraccionamiento = solicitud.CveFraccionamiento, + CveFraccionamientoEtapa = solicitud.CveFraccionamientoEtapa, + Etapa = solicitud.Etapa, + CveTipoTramite = solicitud.CveTipoTramite, + TipoTramite = solicitud.TipoTramite, + CveEstatusSolicitud = solicitud.CveEstatusSolicitud, + EstatusSolicitud = solicitud.EstatusSolicitud, + DocumentosPendientes = documentosPendientes, + PagosPendientes = pagosPendientes, + PuedeEnviarRevision = + solicitud.PuedeCambiarEstatus && + solicitud.EsEstatusCliente && + documentosPendientes == 0 && + pagosPendientes == 0 + }; + }) + .OrderBy(x => x.Etapa) + .ThenBy(x => x.TipoTramite) + .ToList(); + + return DbResult>.Ok(resultado); + } + + public DbResult EnviarRevision( + int cveSolicitud, + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + DbResult> tramites = + ListarTramites( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + + if (!tramites.Success) + { + return DbResult.Fail( + tramites.UserMessage, + tramites.TechnicalMessage, + tramites.Exception); + } + + TramiteClienteListado tramite = + (tramites.Data ?? new List()) + .FirstOrDefault(x => x.CveSolicitud == cveSolicitud); + + if (tramite == null) + { + return Fallo( + "No se encontró el trámite seleccionado."); + } + + if (tramite.DocumentosPendientes > 0) + { + return Fallo( + "Existen documentos requeridos pendientes de cargar o renovar."); + } + + if (tramite.PagosPendientes > 0) + { + return Fallo( + "Existen recibos pendientes de pago."); + } + + DbResult contexto = + _servicioTramites.ObtenerContextoCambioEstatus( + cveSolicitud, + cveUsuarioEjecuta, + nombreDominio); + + if (!contexto.Success || contexto.Data == null) + { + return DbResult.Fail( + contexto.UserMessage, + contexto.TechnicalMessage, + contexto.Exception); + } + + if (!contexto.Data.CveSiguienteEstatus.HasValue) + { + return Fallo( + "El trámite no tiene un siguiente estatus disponible para enviar a revisión."); + } + + var cambio = new ModeloCambioEstatusTramite + { + CveSolicitud = cveSolicitud, + CveEstatusSolicitudAnterior = + contexto.Data.Solicitud.CveEstatusSolicitud, + CveEstatusSolicitud = + contexto.Data.CveSiguienteEstatus.Value, + Observaciones = + "Enviado a revisión por el desarrollador.", + CvesCondicionesMostradas = new List() + }; + + return _servicioTramites.CambiarEstatus( + cambio, + cveUsuarioEjecuta, + nombreDominio, + false); + } + + public DbResult> ListarDocumentos( + FiltroDocumentosCliente filtro, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo>(acceso.UserMessage); + } + + filtro = filtro ?? new FiltroDocumentosCliente(); + + DbResult> desarrollos = + _servicioFraccionamiento.ListarDesarrollos( + usuario.CveCliente, + cveUsuarioEjecuta, + nombreDominio); + + if (!desarrollos.Success) + { + return DbResult>.Fail( + desarrollos.UserMessage, + desarrollos.TechnicalMessage, + desarrollos.Exception); + } + + var fraccionamientos = + (desarrollos.Data ?? new List()) + .Where(x => x.CveFraccionamiento > 0) + .GroupBy(x => x.CveFraccionamiento) + .Select(grupo => new + { + CveFraccionamiento = grupo.Key, + Fraccionamiento = grupo.First().Fraccionamiento + }) + .Where(x => + !filtro.CveFraccionamiento.HasValue || + x.CveFraccionamiento == filtro.CveFraccionamiento.Value) + .OrderBy(x => x.Fraccionamiento) + .ToList(); + + var resultado = new List(); + + foreach (var fraccionamiento in fraccionamientos) + { + DbResult> documentos = + _servicioDocumentos.ListarRequisitos( + fraccionamiento.CveFraccionamiento, + filtro.CveFraccionamientoEtapa, + null, + cveUsuarioEjecuta, + nombreDominio); + + if (!documentos.Success) + { + return DbResult>.Fail( + documentos.UserMessage, + documentos.TechnicalMessage, + documentos.Exception); + } + + foreach (TramiteDocumentoSolicitudModel documento in + documentos.Data ?? new List()) + { + string agrupacion = documento.Agrupacion; + + if (!string.IsNullOrWhiteSpace(filtro.Agrupacion) && + !string.Equals( + filtro.Agrupacion, + agrupacion, + StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + resultado.Add(new DocumentoClientePortal + { + CveDocumentoSolicitud = documento.CveDocumentoSolicitud, + CveSolicitud = documento.CveSolicitud, + CveCliente = documento.CveCliente, + CveFraccionamiento = documento.CveFraccionamiento, + Fraccionamiento = fraccionamiento.Fraccionamiento, + CveFraccionamientoEtapa = documento.CveFraccionamientoEtapa, + Etapa = documento.Etapa, + CveTipoTramite = documento.CveTipoTramite, + TipoTramite = documento.TipoTramite, + CveTipoDocumento = documento.CveTipoDocumento, + TipoDocumento = documento.TipoDocumento, + NombreArchivo = documento.NombreArchivo, + Nota = documento.Nota, + EsAprobado = documento.EsAprobado, + FechaDocumento = documento.FechaDocumento, + FechaVencimiento = documento.FechaVencimiento, + TieneArchivo = documento.TieneArchivo, + EsCliente = documento.EsCliente, + PuedeActualizarArchivo = documento.PuedeActualizarArchivo, + EsRequerido = documento.EsRequerido, + TieneVigencia = documento.TieneVigencia, + FechaExpirada = documento.FechaExpirada, + EstadoDocumento = documento.EstadoDocumento, + Agrupacion = agrupacion + }); + } + } + + return DbResult>.Ok( + resultado + .OrderBy(x => x.Fraccionamiento) + .ThenBy(x => x.Etapa) + .ThenBy(x => x.Agrupacion) + .ThenBy(x => x.TipoDocumento) + .ToList()); + } + + public DbResult> ListarPagos( + FiltroPagosCliente filtro, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo>(acceso.UserMessage); + } + + filtro = filtro ?? new FiltroPagosCliente(); + + return _repositorio.ListarPagos( + usuario.CveCliente, + filtro.CveFraccionamiento, + filtro.CveFraccionamientoEtapa, + filtro.Agrupacion, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult> ListarRecibosDisponibles( + int? cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo>( + acceso.UserMessage); + } + + return _repositorio.ListarRecibosDisponibles( + usuario.CveCliente, + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult RegistrarPago( + SolicitudPagoConvenioCliente pago, + Stream contenido, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo(acceso.UserMessage); + } + + if (pago == null) + { + return Fallo("Capture los datos del pago."); + } + + pago.CveCliente = usuario.CveCliente; + pago.Referencia = RecortarONulo(pago.Referencia, 200); + pago.Banco = RecortarONulo(pago.Banco, 200); + pago.NumeroOperacion = RecortarONulo(pago.NumeroOperacion, 200); + pago.Observaciones = RecortarONulo(pago.Observaciones, 1000); + + if (pago.Importe <= 0m) + { + return Fallo("Capture un importe de pago mayor a cero."); + } + + if (pago.Aplicaciones == null || pago.Aplicaciones.Count == 0) + { + return Fallo("Vincule al menos un recibo al comprobante."); + } + + if (pago.Aplicaciones.Any(x => + x.CveConvenioRecibo <= 0 || + x.ImporteAplicado <= 0m)) + { + return Fallo( + "Revise los recibos y los importes aplicados."); + } + + if (pago.Aplicaciones + .GroupBy(x => x.CveConvenioRecibo) + .Any(grupo => grupo.Count() > 1)) + { + return Fallo( + "El mismo recibo no puede agregarse dos veces al pago."); + } + + decimal totalAplicado = pago.Aplicaciones.Sum( + x => x.ImporteAplicado); + + if (totalAplicado > pago.Importe) + { + return Fallo( + "El importe aplicado a recibos no puede ser mayor al importe del pago."); + } + + bool archivoGuardado = false; + + try + { + _almacenComprobantes.Guardar(pago, contenido); + archivoGuardado = true; + + using (var transaccion = new TransactionLogic( + IsolationLevel.Serializable)) + { + DbResult resultado = _repositorio.AgregarPago( + pago, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success) + { + _almacenComprobantes.Eliminar( + pago.CveCliente, + pago.NombreFisico); + archivoGuardado = false; + return resultado; + } + + transaccion.Commit(); + return resultado; + } + } + catch (ControlledApplicationException excepcion) + { + if (archivoGuardado) + { + _almacenComprobantes.Eliminar( + pago.CveCliente, + pago.NombreFisico); + } + + return DbResult.Fail( + excepcion.Message, + excepcion.Message, + excepcion); + } + catch + { + if (archivoGuardado) + { + _almacenComprobantes.Eliminar( + pago.CveCliente, + pago.NombreFisico); + } + + throw; + } + } + + public DbResult ObtenerArchivoPago( + int cveConvenioPago, + int cveUsuarioEjecuta, + string nombreDominio) + { + UserSessionModel usuario; + DbResult acceso = ValidarCliente( + cveUsuarioEjecuta, + out usuario); + + if (!acceso.Success) + { + return Fallo(acceso.UserMessage); + } + + DbResult resultado = + _repositorio.ObtenerArchivoPago( + cveConvenioPago, + usuario.CveCliente, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success || resultado.Data == null) + { + return resultado; + } + + resultado.Data.RutaFisica = _almacenComprobantes.Resolver( + resultado.Data.CveCliente, + resultado.Data.NombreFisico); + + return resultado; + } + + private DbResult ValidarCliente( + int cveUsuarioEjecuta, + out UserSessionModel usuario) + { + usuario = _contextoUsuario.GetCurrentUser(); + + if (usuario == null || + usuario.CveUsuario != cveUsuarioEjecuta || + !usuario.EsDesarrollador || + usuario.CveCliente <= 0) + { + return DbResult.Fail( + "Esta sección está disponible para usuarios desarrolladores.", + "El usuario actual no tiene contexto de desarrollador.", + null); + } + + return DbResult.Ok(true); + } + + private static string RecortarONulo( + string texto, + int longitudMaxima) + { + if (string.IsNullOrWhiteSpace(texto)) + { + return null; + } + + string valor = texto.Trim(); + + return valor.Length <= longitudMaxima + ? valor + : valor.Substring(0, longitudMaxima); + } + + private static DbResult Fallo(string mensaje) + { + return DbResult.Fail( + mensaje, + mensaje, + null); + } + } +} diff --git a/SIG.Web/App_Code/Services/Convenios/ServicioConvenios.cs b/SIG.Web/App_Code/Services/Convenios/ServicioConvenios.cs new file mode 100644 index 0000000..de07232 --- /dev/null +++ b/SIG.Web/App_Code/Services/Convenios/ServicioConvenios.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Transactions; +using SIG.Web.AppCode.Contracts.Convenios; +using SIG.Web.AppCode.Contracts.Security; +using SIG.Web.AppCode.Infrastructure.Transactions; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Convenios; + +namespace SIG.Web.AppCode.Services.Convenios +{ + public sealed class ServicioConvenios : IServicioConvenios + { + private readonly IRepositorioConvenios _repositorio; + private readonly IUserContextProvider _usuario; + + public ServicioConvenios( + IRepositorioConvenios repositorio, + IUserContextProvider usuario) + { + _repositorio = repositorio; + _usuario = usuario; + } + + public DbResult> Listar( + FiltroConvenios filtro, + int usuario, + string dominio) + { + filtro = filtro ?? new FiltroConvenios(); + + var actual = _usuario.GetCurrentUser(); + + if (actual != null && actual.EsDesarrollador) + { + filtro.CveCliente = actual.CveCliente; + } + + return _repositorio.Listar(filtro, usuario, dominio); + } + + public DbResult Obtener( + int cveConvenio, + int usuario, + string dominio) + { + var resultado = _repositorio.Obtener( + cveConvenio, + usuario, + dominio); + + if (!resultado.Success || + resultado.Data == null || + resultado.Data.Encabezado == null) + { + return resultado; + } + + var actual = _usuario.GetCurrentUser(); + + if (actual != null && + actual.EsDesarrollador && + resultado.Data.Encabezado.CveCliente != actual.CveCliente) + { + return DbResult.Fail( + "No tiene acceso al convenio solicitado.", + "Convenio fuera del cliente asignado.", + null); + } + + return resultado; + } + + public DbResult> ListarConceptos( + int usuario, + string dominio) + { + return _repositorio.ListarConceptos(usuario, dominio); + } + + public DbResult Agregar( + SolicitudAltaConvenio solicitud, + int usuario, + string dominio) + { + var actual = _usuario.GetCurrentUser(); + + if (actual != null && actual.EsDesarrollador) + { + return DbResult.Fail( + "La captura de convenios está disponible para usuarios administrativos.", + "Un usuario desarrollador intentó registrar un convenio.", + null); + } + + string mensajeValidacion = ValidarSolicitud(solicitud); + + if (!string.IsNullOrWhiteSpace(mensajeValidacion)) + { + return DbResult.Fail( + mensajeValidacion, + mensajeValidacion, + null); + } + + using (var transaccion = new TransactionLogic( + IsolationLevel.Serializable)) + { + var resultado = _repositorio.Agregar( + solicitud, + usuario, + dominio); + + if (resultado.Success) + { + transaccion.Commit(); + } + + return resultado; + } + } + + public DbResult Eliminar( + int cveConvenio, + int usuario, + string dominio) + { + var acceso = Obtener(cveConvenio, usuario, dominio); + + if (!acceso.Success) + { + return DbResult.Fail( + acceso.UserMessage, + acceso.TechnicalMessage, + acceso.Exception); + } + + var actual = _usuario.GetCurrentUser(); + + if (actual != null && actual.EsDesarrollador) + { + return DbResult.Fail( + "No tiene permiso para eliminar convenios.", + "El rol desarrollador intentó eliminar un convenio.", + null); + } + + using (var transaccion = new TransactionLogic( + IsolationLevel.Serializable)) + { + var resultado = _repositorio.Eliminar( + cveConvenio, + usuario, + dominio); + + if (resultado.Success) + { + transaccion.Commit(); + } + + return resultado; + } + } + + private static string ValidarSolicitud( + SolicitudAltaConvenio solicitud) + { + if (solicitud == null) + { + return "Capture los datos del convenio."; + } + + if (solicitud.CveCliente <= 0) + { + return "Seleccione el desarrollador del convenio."; + } + + if (solicitud.CveFraccionamientoEtapa <= 0) + { + return "Seleccione el fraccionamiento y etapa del convenio."; + } + + if (string.IsNullOrWhiteSpace(solicitud.NumeroConvenio)) + { + return "Capture el número de convenio."; + } + + if (solicitud.ViviendasEnConvenio < 0) + { + return "La cantidad de viviendas en convenio no es válida."; + } + + if (solicitud.Conceptos == null || solicitud.Conceptos.Count == 0) + { + return "Agregue al menos un concepto al convenio."; + } + + foreach (var concepto in solicitud.Conceptos) + { + if (concepto.CveConvenioConcepto <= 0 || concepto.Importe <= 0) + { + return "Revise los conceptos e importes del convenio."; + } + + if (string.IsNullOrWhiteSpace(concepto.Tipo)) + { + return "Seleccione el tipo de moneda de cada concepto."; + } + + if (concepto.NumeroPagos < 1 || concepto.NumeroPagos > 12) + { + return "Cada concepto debe tener entre 1 y 12 parcialidades."; + } + + var parcialidades = concepto.Parcialidades ?? + new List(); + + if (parcialidades.Count != concepto.NumeroPagos) + { + return "La cantidad de parcialidades debe coincidir con el número de pagos del concepto."; + } + + if (parcialidades.Any(x => x.Importe <= 0)) + { + return "Todas las parcialidades deben tener un importe mayor a cero."; + } + + decimal suma = parcialidades.Sum(x => x.Importe); + + if (suma != concepto.Importe) + { + return "La suma de las parcialidades debe coincidir con el importe del concepto."; + } + } + + return string.Empty; + } + } +} diff --git a/SIG.Web/App_Code/Services/Documentos/AlmacenComprobantesConvenio.cs b/SIG.Web/App_Code/Services/Documentos/AlmacenComprobantesConvenio.cs new file mode 100644 index 0000000..06f5354 --- /dev/null +++ b/SIG.Web/App_Code/Services/Documentos/AlmacenComprobantesConvenio.cs @@ -0,0 +1,199 @@ +using System; +using System.Globalization; +using System.IO; +using System.Web.Hosting; +using SIG.Web.AppCode.Contracts.Documentos; +using SIG.Web.AppCode.Infrastructure; +using SIG.Web.AppCode.Models.Clientes; + +namespace SIG.Web.AppCode.Services.Documentos +{ + public sealed class AlmacenComprobantesConvenio + : IAlmacenComprobantesConvenio + { + private const int TamanoMaximo = 5 * 1024 * 1024; + + public void Guardar( + SolicitudPagoConvenioCliente pago, + Stream contenido) + { + if (pago == null) + { + throw new ControlledApplicationException( + "Capture el comprobante del pago."); + } + + string extension = Path.GetExtension( + pago.NombreArchivo ?? string.Empty).ToLowerInvariant(); + string tipoContenido = ObtenerTipoContenido(extension); + + if (tipoContenido == null || + contenido == null || + !contenido.CanRead || + pago.TamanoBytes <= 0 || + pago.TamanoBytes > TamanoMaximo || + !string.Equals( + tipoContenido, + pago.TipoContenido, + StringComparison.OrdinalIgnoreCase)) + { + throw new ControlledApplicationException( + "Seleccione un comprobante PDF, JPG o PNG de hasta 5 MB."); + } + + byte[] archivo; + + using (var memoria = new MemoryStream()) + { + var bloque = new byte[81920]; + int leidos; + + while ((leidos = contenido.Read( + bloque, + 0, + bloque.Length)) > 0) + { + if (memoria.Length + leidos > TamanoMaximo) + { + throw new ControlledApplicationException( + "El comprobante excede 5 MB."); + } + + memoria.Write(bloque, 0, leidos); + } + + archivo = memoria.ToArray(); + } + + if (archivo.Length != pago.TamanoBytes || + archivo.Length < 12 || + !SIG.Web.AppCode.Services.Visitas.AlmacenDocumentosVisita + .FirmaValida(extension, archivo, 12)) + { + throw new ControlledApplicationException( + "El contenido del comprobante no corresponde al formato indicado."); + } + + pago.NombreArchivo = Path.GetFileName(pago.NombreArchivo); + + if (string.IsNullOrWhiteSpace(pago.NombreArchivo) || + pago.NombreArchivo.Length > 255) + { + throw new ControlledApplicationException( + "El nombre del comprobante no es válido."); + } + + pago.NombreFisico = Guid.NewGuid().ToString("N") + extension; + pago.TipoContenido = tipoContenido; + + string raizDocumentos = HostingEnvironment.MapPath("~/Documentos/"); + + if (string.IsNullOrWhiteSpace(raizDocumentos)) + { + throw new ControlledApplicationException( + "No fue posible resolver la carpeta de documentos."); + } + + Directory.CreateDirectory(raizDocumentos); + Directory.CreateDirectory( + Path.Combine(raizDocumentos, "Generales")); + Directory.CreateDirectory( + Path.Combine(raizDocumentos, "Clientes")); + + string ruta = Resolver( + pago.CveCliente, + pago.NombreFisico); + + Directory.CreateDirectory(Path.GetDirectoryName(ruta)); + + try + { + using (var destino = new FileStream( + ruta, + FileMode.CreateNew, + FileAccess.Write, + FileShare.None)) + { + destino.Write(archivo, 0, archivo.Length); + } + } + catch + { + Eliminar(pago.CveCliente, pago.NombreFisico); + throw; + } + } + + public string Resolver( + int cveCliente, + string nombreFisico) + { + Guid identificador; + + if (cveCliente <= 0 || + string.IsNullOrWhiteSpace(nombreFisico) || + Path.GetFileName(nombreFisico) != nombreFisico || + !Guid.TryParseExact( + Path.GetFileNameWithoutExtension(nombreFisico), + "N", + out identificador)) + { + throw new ControlledApplicationException( + "El comprobante no está disponible."); + } + + string raizClientes = HostingEnvironment.MapPath( + "~/Documentos/Clientes/"); + + if (string.IsNullOrWhiteSpace(raizClientes)) + { + throw new ControlledApplicationException( + "El comprobante no está disponible."); + } + + return Path.Combine( + raizClientes, + cveCliente.ToString(CultureInfo.InvariantCulture), + "Convenios", + "Pagos", + nombreFisico); + } + + public void Eliminar( + int cveCliente, + string nombreFisico) + { + if (string.IsNullOrWhiteSpace(nombreFisico)) + { + return; + } + + string ruta = Resolver(cveCliente, nombreFisico); + + if (File.Exists(ruta)) + { + File.Delete(ruta); + } + } + + private static string ObtenerTipoContenido(string extension) + { + if (extension == ".pdf") + { + return "application/pdf"; + } + + if (extension == ".png") + { + return "image/png"; + } + + if (extension == ".jpg" || extension == ".jpeg") + { + return "image/jpeg"; + } + + return null; + } + } +} diff --git a/SIG.Web/INTEGRACION_CONVENIOS.txt b/SIG.Web/INTEGRACION_CONVENIOS.txt new file mode 100644 index 0000000..5fa7f2e --- /dev/null +++ b/SIG.Web/INTEGRACION_CONVENIOS.txt @@ -0,0 +1,14 @@ +INTEGRACIÓN CONVENIOS - NUEVA ESTRUCTURA + +1. Ejecutar SQL/ConveniosIntegracion.sql después de haber creado las tablas Convenios* acordadas. +2. El script NO modifica ni elimina las tablas heredadas de pagos/timbrado. +3. Se agregó UserControl/ConveniosListado.ascx reutilizable: + - En DetalleEtapa se carga filtrado por CveFraccionamientoEtapa y no muestra filtros. + - En Pages/Desarrolladores/Convenios.aspx se usa el mismo control con el control sig:Filtros. +4. El detalle abre modal y muestra Concepto -> Recibos con sig-grid-agrupado. +5. El botón Eliminar sólo se muestra a usuarios internos cuando el listado indica que no hay pagos vinculados. El PA vuelve a validar esta condición antes del DELETE. +6. Scripts/Convenios.js y Styles/Convenios.css son recursos compartidos del UserControl y quedaron agregados al BundleConfig global. +7. Se incluyeron Scripts/sig-grid-agrupado.js y Styles/sig-grid-agrupado.css porque BundleConfig ya los referenciaba y el ZIP recibido no contenía físicamente esos archivos. El JS conserva el estado independiente de niveles inferiores al cerrar/abrir un padre y es idempotente ante UpdatePanel. + +IMPORTANTE SOBRE NOMBRES DE BD: +Los PA usan dbo.Clientes(CveCliente, Cliente), dbo.Fraccionamientos(CveFraccionamiento, Fraccionamiento) y dbo.FraccionamientosEtapas(CveFraccionamientoEtapa, CveFraccionamiento, Etapa), conforme a los nombres que usa el modelo de la plataforma. Si en la BD física el campo descriptivo de Clientes tiene otro nombre, ajustar únicamente CL.Cliente en los dos SELECT del SQL antes de ejecutarlo. diff --git a/SIG.Web/Pages/Clientes/ComprobanteConvenioPago.ashx b/SIG.Web/Pages/Clientes/ComprobanteConvenioPago.ashx new file mode 100644 index 0000000..33b9230 --- /dev/null +++ b/SIG.Web/Pages/Clientes/ComprobanteConvenioPago.ashx @@ -0,0 +1 @@ +<%@ WebHandler Language="C#" Class="SIG.Web.Pages.Clientes.ComprobanteConvenioPagoHandler" %> diff --git a/SIG.Web/Pages/Clientes/Desarrollos.aspx b/SIG.Web/Pages/Clientes/Desarrollos.aspx new file mode 100644 index 0000000..58d99b6 --- /dev/null +++ b/SIG.Web/Pages/Clientes/Desarrollos.aspx @@ -0,0 +1,52 @@ +<%@ Page Title="Mis desarrollos" Language="C#" MasterPageFile="~/Site.master" + AutoEventWireup="true" CodeFile="Desarrollos.aspx.cs" + Inherits="SIG.Web.Pages.Clientes.Desarrollos" %> + + + + + + + + +
+ + + + + + + + +
+
+
+
+ + + diff --git a/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs b/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs new file mode 100644 index 0000000..e3246f1 --- /dev/null +++ b/SIG.Web/Pages/Clientes/Desarrollos.aspx.cs @@ -0,0 +1,124 @@ +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; +using SIG.Web.AppCode.Models.Fraccionamientos; +using SIG.Web.AppCode.Security; + +namespace SIG.Web.Pages.Clientes +{ + public partial class Desarrollos : ClsPaginaBase + { + protected void Page_Load(object origen, EventArgs argumentos) + { + if (!IsPostBack) + { + Cargar(); + } + } + + protected void EnlazarFila(object origen, GridViewRowEventArgs argumentos) + { + if (argumentos.Row.RowType != DataControlRowType.DataRow) + { + return; + } + + var fila = argumentos.Row.DataItem as ModeloFilaDesarrollos; + + if (fila == null) + { + return; + } + + string grupo = "desarrollo-" + + fila.CveFraccionamiento.ToString(CultureInfo.InvariantCulture); + + if (fila.EsFraccionamiento) + { + 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"; + 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.Attributes["data-sig-item-row"] = "1"; + argumentos.Row.Attributes["data-sig-parent-group"] = grupo; + argumentos.Row.Attributes["data-sig-level"] = "1"; + } + + private void Cargar() + { + var resultado = AppServices.ServicioPortalCliente.ListarDesarrollos( + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + GvDesarrollos.DataSource = resultado.Success + ? resultado.Data + : new List(); + GvDesarrollos.DataBind(); + UpDesarrollos.Update(); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + } + } + } +} diff --git a/SIG.Web/Pages/Clientes/Documentos.aspx b/SIG.Web/Pages/Clientes/Documentos.aspx new file mode 100644 index 0000000..a1e43ac --- /dev/null +++ b/SIG.Web/Pages/Clientes/Documentos.aspx @@ -0,0 +1,14 @@ +<%@ Page Title="Mis documentos" Language="C#" MasterPageFile="~/Site.master" + AutoEventWireup="true" CodeFile="Documentos.aspx.cs" + Inherits="SIG.Web.Pages.Clientes.Documentos" %> +<%@ Register TagPrefix="cliente" TagName="Documentos" Src="~/UserControl/Clientes/DocumentosCliente.ascx" %> + + + + + + + + + + diff --git a/SIG.Web/Pages/Clientes/Documentos.aspx.cs b/SIG.Web/Pages/Clientes/Documentos.aspx.cs new file mode 100644 index 0000000..49c4025 --- /dev/null +++ b/SIG.Web/Pages/Clientes/Documentos.aspx.cs @@ -0,0 +1,16 @@ +using System; +using SIG.Web.AppCode.Security; + +namespace SIG.Web.Pages.Clientes +{ + public partial class Documentos : ClsPaginaBase + { + protected void Page_Load(object origen, EventArgs argumentos) + { + if (!IsPostBack) + { + UcDocumentos.Cargar(null, true); + } + } + } +} diff --git a/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx b/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx new file mode 100644 index 0000000..2c45d03 --- /dev/null +++ b/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx @@ -0,0 +1,88 @@ +<%@ Page Title="Detalle del desarrollo" Language="C#" MasterPageFile="~/Site.master" + AutoEventWireup="true" CodeFile="FraccionamientoDetalle.aspx.cs" + Inherits="SIG.Web.Pages.Clientes.FraccionamientoDetalle" %> +<%@ Register TagPrefix="cliente" TagName="Tramites" Src="~/UserControl/Clientes/TramitesCliente.ascx" %> +<%@ Register TagPrefix="cliente" TagName="Documentos" Src="~/UserControl/Clientes/DocumentosCliente.ascx" %> +<%@ Register TagPrefix="cliente" TagName="Pagos" Src="~/UserControl/Clientes/PagosCliente.ascx" %> + + + + + + + +
+

+
+ Ubicación: + +   ·   + Estatus: + +
+
+ + + + + + +
+ + + + + + + + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + +
+
+
+ + + diff --git a/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs b/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs new file mode 100644 index 0000000..ce6502f --- /dev/null +++ b/SIG.Web/Pages/Clientes/FraccionamientoDetalle.aspx.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Fraccionamientos; +using SIG.Web.AppCode.Security; + +namespace SIG.Web.Pages.Clientes +{ + public partial class FraccionamientoDetalle : ClsPaginaBase + { + private int CveFraccionamientoActual + { + get { return (int?)ViewState["CveFraccionamientoActual"] ?? 0; } + set { ViewState["CveFraccionamientoActual"] = value; } + } + + protected void Page_Load(object origen, EventArgs argumentos) + { + if (IsPostBack) + { + return; + } + + int cveFraccionamiento; + + if (!int.TryParse( + Request.QueryString["id"], + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveFraccionamiento) || + cveFraccionamiento <= 0) + { + Alert( + "Seleccione un fraccionamiento válido.", + TipoMensaje.MsgAdvertencia); + PanelContenido.Visible = false; + return; + } + + CveFraccionamientoActual = cveFraccionamiento; + Cargar(); + } + + private void Cargar() + { + var fraccionamiento = + AppServices.ServicioPortalCliente.ObtenerFraccionamiento( + CveFraccionamientoActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!fraccionamiento.Success || fraccionamiento.Data == null) + { + PanelContenido.Visible = false; + Alert( + fraccionamiento.Success + ? "No se encontró el fraccionamiento." + : fraccionamiento.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + ModeloFraccionamiento datos = fraccionamiento.Data; + LitFraccionamiento.Text = datos.Fraccionamiento; + LitUbicacion.Text = datos.Ubicacion; + LitEstatus.Text = datos.Estatus; + Page.Title = datos.Fraccionamiento; + + var etapas = AppServices.ServicioPortalCliente.ListarEtapas( + CveFraccionamientoActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + GvEtapas.DataSource = etapas.Success + ? etapas.Data + : new List(); + GvEtapas.DataBind(); + UpEtapas.Update(); + + if (!etapas.Success) + { + Alert(etapas.UserMessage, TipoMensaje.MsgAdvertencia); + } + + UcTramites.Cargar(CveFraccionamientoActual); + UcDocumentos.Cargar(CveFraccionamientoActual, false); + UcPagos.Cargar(CveFraccionamientoActual, false); + } + } +} diff --git a/SIG.Web/Pages/Clientes/Pagos.aspx b/SIG.Web/Pages/Clientes/Pagos.aspx new file mode 100644 index 0000000..e522496 --- /dev/null +++ b/SIG.Web/Pages/Clientes/Pagos.aspx @@ -0,0 +1,14 @@ +<%@ Page Title="Mis pagos" Language="C#" MasterPageFile="~/Site.master" + AutoEventWireup="true" CodeFile="Pagos.aspx.cs" + Inherits="SIG.Web.Pages.Clientes.Pagos" %> +<%@ Register TagPrefix="cliente" TagName="Pagos" Src="~/UserControl/Clientes/PagosCliente.ascx" %> + + + + + + + + + + diff --git a/SIG.Web/Pages/Clientes/Pagos.aspx.cs b/SIG.Web/Pages/Clientes/Pagos.aspx.cs new file mode 100644 index 0000000..a0d3b2d --- /dev/null +++ b/SIG.Web/Pages/Clientes/Pagos.aspx.cs @@ -0,0 +1,16 @@ +using System; +using SIG.Web.AppCode.Security; + +namespace SIG.Web.Pages.Clientes +{ + public partial class Pagos : ClsPaginaBase + { + protected void Page_Load(object origen, EventArgs argumentos) + { + if (!IsPostBack) + { + UcPagos.Cargar(null, true); + } + } + } +} diff --git a/SIG.Web/Pages/Desarrolladores/ConvenioDetalle.aspx b/SIG.Web/Pages/Desarrolladores/ConvenioDetalle.aspx deleted file mode 100644 index 336b2c0..0000000 --- a/SIG.Web/Pages/Desarrolladores/ConvenioDetalle.aspx +++ /dev/null @@ -1,157 +0,0 @@ -<%@ Page Title="Detalle de convenio" Language="C#" MasterPageFile="~/Site.master" - AutoEventWireup="true" CodeFile="ConvenioDetalle.aspx.cs" Inherits="SIG.Web.Pages.Desarrolladores.ConvenioDetalle" %> - - - -
  • -
    - - - - - -
    - - -
    -
    - - -
    -
    -

    -
    -
    - - -
    -
    - - -
    -
    -
    - - -
    -
    - - -
    - -

    Los importes se capturan en la unidad del adeudo origen, con hasta seis decimales.

    - - Sugerir distribución - -
    -
    - - - - - -

    Ajuste los importes y pulse Guardar convenio. La suma debe coincidir con el importe del convenio.

    - - - - - - - - - - - -
    - - - - Agregar producto - -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - Agregar parcialidad - - - - - - - - - -

    La propuesta toma el saldo por producto proporcionalmente y las parcialidades por vencimiento. Revise este desglose antes de guardar.

    - - - - - - - - -
    -
    -
    -
    -
    - - - - Guardar convenio - - - Cancelar convenio - - - - -
    - -

    Procesando convenio...

    -
    -
    - - diff --git a/SIG.Web/Pages/Desarrolladores/ConvenioDetalle.aspx.cs b/SIG.Web/Pages/Desarrolladores/ConvenioDetalle.aspx.cs deleted file mode 100644 index d8d811b..0000000 --- a/SIG.Web/Pages/Desarrolladores/ConvenioDetalle.aspx.cs +++ /dev/null @@ -1,583 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Web; -using System.Web.UI.WebControls; -using SIG.Web.AppCode.Configuration; -using SIG.Web.AppCode.Infrastructure.WebForms; -using SIG.Web.AppCode.Models.Tramites; -using SIG.Web.AppCode.Security; - -namespace SIG.Web.Pages.Desarrolladores -{ - public partial class ConvenioDetalle : ClsPaginaBase - { - private ModeloObligacionPago AdeudoOrigen - { - get { return ViewState["AdeudoOrigen"] as ModeloObligacionPago; } - set { ViewState["AdeudoOrigen"] = value; } - } - - private ModeloObligacionPago ConvenioActual - { - get { return ViewState["ConvenioActual"] as ModeloObligacionPago; } - set { ViewState["ConvenioActual"] = value; } - } - - private List Productos - { - get { return ViewState["Productos"] as List ?? new List(); } - set { ViewState["Productos"] = value; } - } - - private List Parcialidades - { - get { return ViewState["Parcialidades"] as List ?? new List(); } - set { ViewState["Parcialidades"] = value; } - } - - private List DetallesOrigen - { - get { return ViewState["DetallesOrigen"] as List ?? new List(); } - set { ViewState["DetallesOrigen"] = value; } - } - - protected void Page_Load(object origen, EventArgs argumentos) - { - if (CurrentUser.EsDesarrollador) - { - PnlCaptura.Visible = false; - Alert("La captura de convenios está disponible para usuarios administrativos.", TipoMensaje.MsgAdvertencia); - return; - } - if (!IsPostBack) - { - int clave; - if (int.TryParse(Request.QueryString["id"], out clave) && clave > 0) - { - CargarConvenio(clave); - } - else - { - CargarClientes(); - if (int.TryParse(Request.QueryString["origen"], out clave) && clave > 0) - { - CargarOrigen(clave); - } - } - CargarProductosCatalogo(); - EnlazarProductos(); - EnlazarParcialidades(); - } - BtnGuardar.Visible = TienePermiso(ConvenioActual == null ? "Convenios.Crear" : "Convenios.Modificar"); - BtnConfirmarCancelacion.Visible = ConvenioActual != null && TienePermiso("Convenios.Cancelar"); - } - - private bool TienePermiso(string permiso) - { - return !CurrentUser.EsDesarrollador && - AppServices.PermissionService.HasPermission(CurrentUser.CveUsuario, permiso); - } - - private void CargarClientes() - { - var resultado = AppServices.ServicioPagosConvenios.ListarObligaciones( - new ModeloFiltroObligacionesPago { SoloPendientes = true, EstadoAdministrativo = "ACTIVO" }, - CurrentUser.CveUsuario, CurrentUser.NombreDominio); - DdlCliente.Items.Clear(); - DdlCliente.Items.Add(new ListItem("Seleccione cliente", "")); - DdlOrigen.Items.Clear(); - DdlOrigen.Items.Add(new ListItem("Seleccione un adeudo", "")); - if (!resultado.Success) - { - Alert(resultado.UserMessage, TipoMensaje.MsgError); - return; - } - foreach (var grupo in resultado.Data.GroupBy(pago => pago.CveCliente).OrderBy(grupo => grupo.First().Cliente)) - { - DdlCliente.Items.Add(new ListItem(grupo.First().Cliente, grupo.Key.ToString(CultureInfo.InvariantCulture))); - } - } - - private void CargarProductosCatalogo() - { - var resultado = AppServices.ServicioProductoServicio.Listar( - "", false, CurrentUser.CveUsuario, CurrentUser.NombreDominio); - DdlProducto.Items.Clear(); - DdlProducto.Items.Add(new ListItem("Seleccione producto", "")); - if (!resultado.Success) - { - Alert(resultado.UserMessage, TipoMensaje.MsgError); - return; - } - foreach (var producto in resultado.Data) - { - DdlProducto.Items.Add(new ListItem(producto.PS, producto.CvePS.ToString(CultureInfo.InvariantCulture))); - } - } - - protected void CambiarCliente(object origen, EventArgs argumentos) - { - if (ConvenioActual != null) - { - return; - } - LimpiarOrigen(); - int cliente; - if (int.TryParse(DdlCliente.SelectedValue, out cliente)) - { - CargarAdeudosCliente(cliente); - } - } - - private void CargarAdeudosCliente(int cliente) - { - DdlOrigen.Items.Clear(); - DdlOrigen.Items.Add(new ListItem("Seleccione un adeudo", "")); - var resultado = AppServices.ServicioPagosConvenios.ListarObligaciones( - new ModeloFiltroObligacionesPago - { - CveCliente = cliente, - SoloPendientes = true, - EstadoAdministrativo = "ACTIVO" - }, CurrentUser.CveUsuario, CurrentUser.NombreDominio); - if (!resultado.Success) - { - Alert(resultado.UserMessage, TipoMensaje.MsgError); - return; - } - foreach (var pago in resultado.Data) - { - DdlOrigen.Items.Add(new ListItem(string.Format(CultureInfo.CurrentCulture, - "{0} / {1} · {2} · Saldo {3:N2} {4}", pago.Fraccionamiento, pago.Etapa, - pago.Descripcion, pago.SaldoPendiente, pago.UnidadCobro), - pago.CveSolicitudPago.ToString(CultureInfo.InvariantCulture))); - } - } - - protected void CambiarOrigen(object origen, EventArgs argumentos) - { - if (ConvenioActual != null) - { - return; - } - LimpiarOrigen(); - int clave; - if (int.TryParse(DdlOrigen.SelectedValue, out clave)) - { - CargarOrigen(clave); - } - } - - private void LimpiarOrigen() - { - AdeudoOrigen = null; - Productos = new List(); - Parcialidades = new List(); - DetallesOrigen = new List(); - LitOrigen.Text = ""; - TxtSaldoConvenido.Text = ""; - TxtImporte.Text = ""; - TxtDescripcion.Text = ""; - EnlazarProductos(); - EnlazarParcialidades(); - MostrarOrigen(); - } - - private void CargarOrigen(int clave) - { - var resultado = AppServices.ServicioPagosConvenios.ObtenerObligacion( - clave, CurrentUser.CveUsuario, CurrentUser.NombreDominio); - if (!resultado.Success) - { - Alert(resultado.UserMessage, TipoMensaje.MsgError); - return; - } - var adeudo = resultado.Data; - if (adeudo.EstadoAdministrativo != "ACTIVO" || adeudo.SaldoPendiente <= 0) - { - Alert("Seleccione un adeudo activo con saldo pendiente.", TipoMensaje.MsgAdvertencia); - return; - } - AdeudoOrigen = adeudo; - var cliente = DdlCliente.Items.FindByValue(adeudo.CveCliente.ToString(CultureInfo.InvariantCulture)); - if (cliente != null) - { - DdlCliente.SelectedValue = cliente.Value; - CargarAdeudosCliente(adeudo.CveCliente); - DdlOrigen.SelectedValue = clave.ToString(CultureInfo.InvariantCulture); - } - LitOrigen.Text = adeudo.Cliente + " · " + adeudo.Fraccionamiento + " / " + adeudo.Etapa + - " · Unidad: " + adeudo.UnidadCobro; - TxtDescripcion.Text = "Convenio de " + adeudo.Descripcion; - TxtSaldoConvenido.Text = adeudo.SaldoPendiente.ToString("0.######", CultureInfo.InvariantCulture); - TxtImporte.Text = TxtSaldoConvenido.Text; - UpCabecera.Update(); - } - - private void CargarConvenio(int clave) - { - var resultado = AppServices.ServicioPagosConvenios.ObtenerObligacion( - clave, CurrentUser.CveUsuario, CurrentUser.NombreDominio); - if (!resultado.Success || resultado.Data.Convenio == null) - { - PnlCaptura.Visible = false; - Alert(resultado.Success ? "El registro no corresponde a un convenio." : resultado.UserMessage, TipoMensaje.MsgAdvertencia); - return; - } - ConvenioActual = resultado.Data; - DetallesOrigen = ConvenioActual.DetallesOrigen; - Productos = ConvenioActual.Productos.Select(producto => new ModeloCapturaProductoPago - { - CvePS = producto.CvePS, - Descripcion = producto.Descripcion, - Cantidad = producto.Cantidad, - PrecioUnitario = producto.PrecioUnitario, - Importe = producto.Importe - }).ToList(); - Parcialidades = ConvenioActual.Parcialidades.Select(parcialidad => new ModeloCapturaParcialidadPago - { - NumeroParcialidad = parcialidad.NumeroParcialidad, - FechaVencimiento = parcialidad.FechaVencimiento, - FechaProrroga = parcialidad.FechaProrroga, - Importe = parcialidad.Importe - }).ToList(); - TxtDescripcion.Text = ConvenioActual.Descripcion; - TxtObservaciones.Text = ConvenioActual.Convenio.Observaciones; - TxtImporte.Text = ConvenioActual.Importe.ToString("0.######", CultureInfo.InvariantCulture); - TxtSaldoConvenido.Text = ConvenioActual.Convenio.ImporteSaldoConvenido.ToString( - "0.######", CultureInfo.InvariantCulture); - TxtSaldoConvenido.ReadOnly = true; - PnlSeleccionOrigen.Visible = false; - BtnSugerir.Visible = false; - ChkRequerido.Checked = ConvenioActual.EsRequerido; - ChkRequerido.Visible = false; - LitOrigen.Text = ConvenioActual.Cliente + " · " + ConvenioActual.Fraccionamiento + - " / " + ConvenioActual.Etapa + " · Unidad: " + ConvenioActual.UnidadCobro + - " · " + ConvenioActual.EstadoAdministrativo + - (ConvenioActual.EsRequerido ? " · Pago requerido" : " · Pago opcional") + - ". Se conserva el saldo de origen; el cambio de requerido se realiza desde el detalle del pago."; - MostrarOrigen(); - } - - protected void SugerirDistribucion(object origen, EventArgs argumentos) - { - try - { - if (ConvenioActual != null) - { - return; - } - if (AdeudoOrigen == null) - { - throw new FormatException("Seleccione el adeudo origen."); - } - decimal importe = LeerImporte(TxtImporte.Text); - decimal saldo = LeerImporte(TxtSaldoConvenido.Text); - ValidarImporteConvenio(importe, saldo); - var propuesta = AppServices.ServicioPagosConvenios.PrepararDistribucionConvenio( - AdeudoOrigen.CveSolicitudPago, saldo, importe, - CurrentUser.CveUsuario, CurrentUser.NombreDominio); - if (!propuesta.Success) - { - Alert(propuesta.UserMessage, TipoMensaje.MsgAdvertencia); - return; - } - Productos = propuesta.Data.Productos.Select(producto => new ModeloCapturaProductoPago - { - CvePS = producto.CvePS, - Descripcion = producto.Descripcion, - Cantidad = 1, - PrecioUnitario = producto.ImportePropuesto, - Importe = producto.ImportePropuesto - }).ToList(); - DetallesOrigen = propuesta.Data.Origenes; - EnlazarProductos(); - MostrarOrigen(); - Alert("Distribución sugerida. Revise los productos, el saldo de origen y las parcialidades antes de guardar.", - TipoMensaje.ToastExito); - } - catch (FormatException error) - { - Alert(error.Message, TipoMensaje.MsgAdvertencia); - } - } - - private void MostrarOrigen() - { - GvOrigen.DataSource = DetallesOrigen; - GvOrigen.DataBind(); - UpOrigen.Update(); - } - - private void EnlazarProductos() - { - GvProductos.DataSource = Productos; - GvProductos.DataBind(); - UpProductos.Update(); - } - - private void EnlazarParcialidades() - { - GvParcialidades.DataSource = Parcialidades; - GvParcialidades.DataBind(); - UpParcialidades.Update(); - } - - private List LeerProductos() - { - var productos = Productos; - for (int indice = 0; indice < GvProductos.Rows.Count; indice++) - { - decimal importe = LeerImporte(((TextBox)GvProductos.Rows[indice].FindControl("TxtImporteProducto")).Text); - if (productos[indice].Importe != importe) - { - productos[indice].Importe = importe; - productos[indice].Cantidad = 1; - productos[indice].PrecioUnitario = importe; - } - } - return productos; - } - - private List LeerParcialidades() - { - var parcialidades = new List(); - foreach (GridViewRow fila in GvParcialidades.Rows) - { - DateTime vencimiento = LeerFecha(((TextBox)fila.FindControl("TxtVencimiento")).Text); - string prorroga = ((TextBox)fila.FindControl("TxtProrroga")).Text; - var parcialidad = new ModeloCapturaParcialidadPago - { - NumeroParcialidad = fila.RowIndex + 1, - FechaVencimiento = vencimiento, - Importe = LeerImporte(((TextBox)fila.FindControl("TxtImporteParcialidad")).Text), - FechaProrroga = string.IsNullOrEmpty(prorroga) ? (DateTime?)null : LeerFecha(prorroga) - }; - if (parcialidad.FechaProrroga < vencimiento) - { - throw new FormatException("La prórroga no puede ser anterior al vencimiento."); - } - parcialidades.Add(parcialidad); - } - return parcialidades; - } - - protected void AgregarProducto(object origen, EventArgs argumentos) - { - try - { - var productos = LeerProductos(); - int clave; - if (!int.TryParse(DdlProducto.SelectedValue, out clave)) - { - throw new FormatException("Seleccione un producto del catálogo."); - } - if (productos.Any(producto => producto.CvePS == clave)) - { - throw new FormatException("El producto ya está agregado; ajuste su importe."); - } - productos.Add(new ModeloCapturaProductoPago - { - CvePS = clave, - Descripcion = DdlProducto.SelectedItem.Text, - Cantidad = 1 - }); - Productos = productos; - EnlazarProductos(); - } - catch (FormatException error) - { - Alert(error.Message, TipoMensaje.MsgAdvertencia); - } - } - - protected void ProductoComando(object origen, GridViewCommandEventArgs argumentos) - { - if (argumentos.CommandName != "QuitarProducto") - { - return; - } - try - { - var productos = LeerProductos(); - int indice = Convert.ToInt32(argumentos.CommandArgument, CultureInfo.InvariantCulture); - if (indice >= 0 && indice < productos.Count) - { - productos.RemoveAt(indice); - Productos = productos; - EnlazarProductos(); - } - } - catch (FormatException error) - { - Alert(error.Message, TipoMensaje.MsgAdvertencia); - } - } - - protected void AgregarParcialidad(object origen, EventArgs argumentos) - { - try - { - var parcialidades = LeerParcialidades(); - parcialidades.Add(new ModeloCapturaParcialidadPago - { - NumeroParcialidad = parcialidades.Count + 1, - FechaVencimiento = DateTime.MinValue - }); - Parcialidades = parcialidades; - EnlazarParcialidades(); - } - catch (FormatException error) - { - Alert(error.Message, TipoMensaje.MsgAdvertencia); - } - } - - protected void ParcialidadComando(object origen, GridViewCommandEventArgs argumentos) - { - if (argumentos.CommandName != "QuitarParcialidad") - { - return; - } - try - { - var parcialidades = LeerParcialidades(); - int indice = Convert.ToInt32(argumentos.CommandArgument, CultureInfo.InvariantCulture); - if (indice >= 0 && indice < parcialidades.Count) - { - parcialidades.RemoveAt(indice); - for (int numero = 0; numero < parcialidades.Count; numero++) - { - parcialidades[numero].NumeroParcialidad = numero + 1; - } - Parcialidades = parcialidades; - EnlazarParcialidades(); - } - } - catch (FormatException error) - { - Alert(error.Message, TipoMensaje.MsgAdvertencia); - } - } - - internal static decimal LeerImporte(string texto) - { - decimal importe; - string normalizado = (texto ?? "").Trim().Replace(',', '.'); - if (!decimal.TryParse(normalizado, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out importe) || - importe < 0 || importe > 9999999999999.999999m || decimal.Round(importe, 6) != importe) - { - throw new FormatException("Capture un importe válido, sin separadores de miles y con hasta seis decimales."); - } - return importe; - } - - private static DateTime LeerFecha(string texto) - { - DateTime fecha; - if (!DateTime.TryParseExact(texto, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out fecha)) - { - throw new FormatException("Capture una fecha de vencimiento válida."); - } - return fecha; - } - - private void ValidarImporteConvenio(decimal importe, decimal saldo) - { - if (importe < saldo && !TienePermiso("Convenios.DisminuirImporte")) - { - throw new FormatException("El importe del convenio no puede ser menor al saldo seleccionado."); - } - } - - protected void Guardar(object origen, EventArgs argumentos) - { - try - { - var contexto = ConvenioActual ?? AdeudoOrigen; - if (contexto == null) - { - throw new FormatException("Seleccione un adeudo."); - } - decimal importe = LeerImporte(TxtImporte.Text); - decimal saldo = LeerImporte(TxtSaldoConvenido.Text); - ValidarImporteConvenio(importe, saldo); - if (DetallesOrigen.Count == 0 || DetallesOrigen.Sum(detalle => detalle.ImporteTomadoConvenio) != saldo) - { - throw new FormatException("Sugiera nuevamente la distribución del saldo de origen y revísela antes de guardar."); - } - var captura = new ModeloCapturaConvenio - { - Obligacion = new ModeloCapturaObligacion - { - CveSolicitudPago = ConvenioActual == null ? (int?)null : ConvenioActual.CveSolicitudPago, - CveCliente = contexto.CveCliente, - CveFraccionamiento = contexto.CveFraccionamiento, - CveFraccionamientoEtapa = contexto.CveFraccionamientoEtapa, - CveUnidadCobro = contexto.CveUnidadCobro, - Descripcion = TxtDescripcion.Text.Trim(), - Importe = importe, - EsRequerido = ConvenioActual == null ? ChkRequerido.Checked : ConvenioActual.EsRequerido, - FechaGeneracion = ConvenioActual == null ? DateTime.Now : ConvenioActual.FechaGeneracion, - Productos = LeerProductos(), - Parcialidades = LeerParcialidades() - }, - Observaciones = TxtObservaciones.Text.Trim(), - Origenes = DetallesOrigen.Select(detalle => new ModeloCapturaOrigenConvenio - { - CveSolicitudPagoOrigen = detalle.CveSolicitudPagoOrigen, - CveSolicitudPagoDetalleOrigen = detalle.CveSolicitudPagoDetalleOrigen, - CveSolicitudPagoParcialidadOrigen = detalle.CveSolicitudPagoParcialidadOrigen, - ImporteTomadoConvenio = detalle.ImporteTomadoConvenio - }).ToList() - }; - var resultado = AppServices.ServicioPagosConvenios.GuardarConvenio( - captura, CurrentUser.CveUsuario, CurrentUser.NombreDominio); - if (!resultado.Success) - { - Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); - return; - } - AlertNextRequest("Convenio guardado correctamente.", TipoMensaje.ToastExito); - RegistraScript("SIGPagosConvenios.salirGuardado('" + - HttpUtility.JavaScriptStringEncode(ResolveUrl("~/Pages/Desarrolladores/PagoDetalle.aspx?id=" + - resultado.Data.ToString(CultureInfo.InvariantCulture))) + "');"); - } - catch (FormatException error) - { - Alert(error.Message, TipoMensaje.MsgAdvertencia); - } - } - - protected void ConfirmarCancelacion(object origen, EventArgs argumentos) - { - if (ConvenioActual == null || !TienePermiso("Convenios.Cancelar")) - { - Alert("No hay un convenio disponible para cancelar.", TipoMensaje.MsgAdvertencia); - return; - } - Alert("Se cancelará el convenio y se liberará su saldo de origen si no tiene movimientos que lo impidan. ¿Desea continuar?", - TipoMensaje.MsgConfirmacion, "__doPostBack('" + HttpUtility.JavaScriptStringEncode(BtnCancelar.UniqueID) + "','');"); - } - - protected void Cancelar(object origen, EventArgs argumentos) - { - if (ConvenioActual == null) - { - return; - } - var resultado = AppServices.ServicioPagosConvenios.CancelarConvenio( - ConvenioActual.CveSolicitudPago, CurrentUser.CveUsuario, CurrentUser.NombreDominio); - if (!resultado.Success) - { - Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); - return; - } - AlertNextRequest("Convenio cancelado.", TipoMensaje.ToastExito); - RegistraScript("SIGPagosConvenios.salirGuardado('" + - HttpUtility.JavaScriptStringEncode(ResolveUrl("~/Pages/Desarrolladores/Convenios.aspx")) + "');"); - } - } -} diff --git a/SIG.Web/Pages/Desarrolladores/Convenios.aspx b/SIG.Web/Pages/Desarrolladores/Convenios.aspx index 983de24..57d73bb 100644 --- a/SIG.Web/Pages/Desarrolladores/Convenios.aspx +++ b/SIG.Web/Pages/Desarrolladores/Convenios.aspx @@ -1,78 +1,31 @@ -<%@ Page Title="Convenios" Language="C#" MasterPageFile="~/Site.master" - AutoEventWireup="true" CodeFile="Convenios.aspx.cs" Inherits="SIG.Web.Pages.Desarrolladores.Convenios" %> - - - -
  • - - Agregar convenio - -
  • -
    +<%@ Page Title="Convenios" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Convenios.aspx.cs" Inherits="SIG.Web.Pages.Desarrolladores.Convenios" %> +<%@ Register TagPrefix="convenios" TagName="Listado" Src="~/UserControl/ConveniosListado.ascx" %> + - + - + - - - - - - - - -

    Obligaciones sin saldo pendiente y canceladas. El saldo convenido se muestra separado de lo abonado.

    - -
    -
    - -
    - -

    Consultando...

    -
    -