diff --git a/AGENTS.md b/AGENTS.md index 5b5a32d..7d048cc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -45,6 +45,8 @@ Database ## Language rules - All new code must be **C#**. +- All new project-owned identifiers must use Spanish domain terminology, including C# members and local variables, JavaScript functions and variables, CSS hooks, HTML `data-*` attributes, and `ViewState` keys. Keep framework, library, protocol, and established external API names unchanged. +- Do not introduce English aliases for Spanish database or business concepts. For example, use `CveUnidadMedida`, `unidadMedida`, or `data-cve-unidad-medida`, not `MeasurementUnit`, `measurementUnit`, or `data-measurement-unit-id`. - Do not add VB.NET files. - Do not add `.vb` files to the active project. - Old VB files may exist only as migration reference files using `.vb.txt`. @@ -316,6 +318,8 @@ Do not mix placeholder naming systems in the same project. - Hidden-field values are client-controlled and must never be trusted for authorization or sensitive decisions; validate them again on the server when their use is unavoidable. - Keep ViewState values small and serializable. Do not store database connections, commands, readers, services, repositories, or unnecessarily large result sets in ViewState. - ViewState property and key names must identify the entity and purpose, for example `CveFraccionamientoActual` and `CveFraccionamientoEtapaActual`. +- When a postback needs to recover related values from an already loaded catalog, store the typed serializable object list in a typed `ViewState` property and locate the selected object by its key. +- Do not copy server-owned catalog or model values into HTML `data-*` attributes, CSS classes, hidden fields, or other client-controlled markup merely to recover them during a postback. Read them from the typed object list stored in `ViewState`. --- ## Login and session rules @@ -487,6 +491,8 @@ Rules: - Do not create `SqlCommand` directly in `.aspx.cs`. - Use repositories or SQL executor classes behind contracts. - All application database reads and writes must use stored procedures; inline SQL in C# is prohibited. +- Access to modules and catalogs is controlled by the menu and page-access layer. Reusable catalog stored procedures must not query `Sis_Usuarios`, restrict execution by `CveRol`, or return access-denied messages for module authorization. +- Keep `@CveUsuarioEjecuta` in catalog procedures for the required signature and auditing when applicable, not to authorize access to the module. - Mandatory: read and follow `AGENTS_STORED_PROCEDURES.md` for naming, output parameters, TRY/CATCH, logging, transactions, and physical deletion. - Mandatory: read and follow `AGENTS_DATA_READER_MAPPING.md` for object, list, `DataTable`, and `JArray` result mapping. - Mandatory: read and follow `AGENTS_DATABASE_ERROR_LOGGING.md` for safe parameter logging and reproducible stored-procedure calls. @@ -873,4 +879,4 @@ After the starter works, the safest growth path is: 6. Add catalog search and UI helpers. 7. Add PDF viewer only after the base shell is stable. -Keep every new feature behind contracts so the WebForms UI remains thin and easier to migrate later if needed. \ No newline at end of file +Keep every new feature behind contracts so the WebForms UI remains thin and easier to migrate later if needed. diff --git a/Catalogo_ProductosServicios.sql b/Catalogo_ProductosServicios.sql new file mode 100644 index 0000000..31c869d --- /dev/null +++ b/Catalogo_ProductosServicios.sql @@ -0,0 +1,573 @@ +SET NOCOUNT ON; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ProductoServicioList + @Texto varchar(200) = NULL, + @IncluirInactivos bit = 0, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SET @Texto = NULLIF(LTRIM(RTRIM(@Texto)), ''); + + SELECT + PS.CvePS, + PS.Codigo, + PS.PS, + PS.CveTipoPS, + CASE PS.CveTipoPS + WHEN 2 THEN 'Producto' + ELSE 'Servicio' + END AS TipoPS, + PS.CveClasificacion, + C.Clasificacion, + PS.CveUnidadMedida, + UM.UnidadMedida, + CONVERT(decimal(18, 2), PS.Precio) AS Precio, + PS.Estado AS EsActivo + FROM dbo.ProductosServicios AS PS + INNER JOIN dbo.Clasificaciones AS C + ON C.CveClasificacion = PS.CveClasificacion + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = PS.CveUnidadMedida + WHERE (@IncluirInactivos = 1 OR PS.Estado = 1) + AND + ( + @Texto IS NULL + OR PS.Codigo LIKE '%' + @Texto + '%' + OR PS.PS LIKE '%' + @Texto + '%' + OR C.Clasificacion LIKE '%' + @Texto + '%' + OR UM.UnidadMedida LIKE '%' + @Texto + '%' + ) + ORDER BY PS.PS, PS.CvePS; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los productos y servicios; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ProductoServicioList'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ProductoServicioGet + @CvePS int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SELECT + PS.CvePS, + PS.Codigo, + PS.PS, + PS.CveTipoPS, + CASE PS.CveTipoPS + WHEN 2 THEN 'Producto' + ELSE 'Servicio' + END AS TipoPS, + PS.CveClasificacion, + C.Clasificacion, + PS.CveUnidadMedida, + UM.UnidadMedida, + CONVERT(decimal(18, 2), PS.Precio) AS Precio, + PS.Estado AS EsActivo + FROM dbo.ProductosServicios AS PS + INNER JOIN dbo.Clasificaciones AS C + ON C.CveClasificacion = PS.CveClasificacion + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = PS.CveUnidadMedida + WHERE PS.CvePS = @CvePS; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar el producto o servicio; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ProductoServicioGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ProductoServicioOpcionesList + @CveClasificacionActual int = NULL, + @CveUnidadMedidaActual int = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SELECT + CveClasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(Codigo)), '') IS NULL + THEN Clasificacion COLLATE Modern_Spanish_CS_AS + ELSE + Codigo COLLATE Modern_Spanish_CS_AS + + ' - ' + + Clasificacion COLLATE Modern_Spanish_CS_AS + END AS Clasificacion + FROM dbo.Clasificaciones + WHERE + ( + Estado = 1 + AND Afectable = 1 + ) + OR CveClasificacion = @CveClasificacionActual + ORDER BY Clasificacion, Codigo, CveClasificacion; + + SELECT + CveUnidadMedida, + CASE + WHEN NULLIF(LTRIM(RTRIM(Abreviatura)), '') IS NULL + THEN UnidadMedida COLLATE Modern_Spanish_CS_AS + ELSE + UnidadMedida COLLATE Modern_Spanish_CS_AS + + ' (' + + Abreviatura COLLATE Modern_Spanish_CS_AS + + ')' + END AS UnidadMedida + FROM dbo.UnidadesMedida + WHERE Estado = 1 + OR CveUnidadMedida = @CveUnidadMedidaActual + ORDER BY UnidadMedida, CveUnidadMedida; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar las opciones del catálogo; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ProductoServicioOpcionesList'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ProductoServicioSave + @CvePS int = NULL, + @Codigo varchar(50) = NULL, + @PS varchar(846), + @CveTipoPS int, + @CveClasificacion int, + @CveUnidadMedida int, + @Precio decimal(18, 2), + @EsActivo bit, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SELECT + @CvePS = NULLIF(@CvePS, 0), + @Codigo = NULLIF(LTRIM(RTRIM(@Codigo)), ''), + @PS = LTRIM(RTRIM(@PS)); + + IF NULLIF(@PS, '') IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture la descripción del producto o servicio.', + @ErrorTipo = 2; + RETURN; + END; + + IF @CveTipoPS NOT IN (1, 2) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione si el registro es producto o servicio.', + @ErrorTipo = 2; + RETURN; + END; + + IF @Precio < 0 + BEGIN + SELECT + @ErrorMostrar = 'El precio no puede ser negativo.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Clasificaciones + WHERE CveClasificacion = @CveClasificacion + AND + ( + Estado = 1 + OR CveClasificacion = + ( + SELECT CveClasificacion + FROM dbo.ProductosServicios + WHERE CvePS = @CvePS + ) + ) + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione una clasificación vigente.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.UnidadesMedida + WHERE CveUnidadMedida = @CveUnidadMedida + AND + ( + Estado = 1 + OR CveUnidadMedida = + ( + SELECT CveUnidadMedida + FROM dbo.ProductosServicios + WHERE CvePS = @CvePS + ) + ) + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione una unidad de medida vigente.', + @ErrorTipo = 2; + RETURN; + END; + + IF @Codigo IS NOT NULL + AND EXISTS + ( + SELECT 1 + FROM dbo.ProductosServicios + WHERE Codigo = @Codigo + AND CvePS <> ISNULL(@CvePS, 0) + ) + BEGIN + SELECT + @ErrorMostrar = 'El código ya está asignado a otro producto o servicio.', + @ErrorTipo = 2; + RETURN; + END; + + IF @CvePS IS NULL + BEGIN + INSERT dbo.ProductosServicios + ( + CveClasificacion, + CveUnidadMedida, + Codigo, + PS, + Precio, + Estado, + Fecha, + CveTipoPS, + CveUsuario, + CveUsuarioModifico, + FechaUltimaModificacion + ) + VALUES + ( + @CveClasificacion, + @CveUnidadMedida, + @Codigo, + @PS, + CONVERT(float, @Precio), + @EsActivo, + GETDATE(), + @CveTipoPS, + @CveUsuarioEjecuta, + @CveUsuarioEjecuta, + GETDATE() + ); + + SET @CvePS = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.ProductosServicios + WHERE CvePS = @CvePS + ) + BEGIN + SELECT + @ErrorMostrar = 'El producto o servicio seleccionado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.ProductosServicios + SET CveClasificacion = @CveClasificacion, + CveUnidadMedida = @CveUnidadMedida, + Codigo = @Codigo, + PS = @PS, + Precio = CONVERT(float, @Precio), + Estado = @EsActivo, + CveTipoPS = @CveTipoPS, + CveUsuarioModifico = @CveUsuarioEjecuta, + FechaUltimaModificacion = GETDATE() + WHERE CvePS = @CvePS; + END; + + SELECT @CvePS AS CvePS; + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al guardar el producto o servicio; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ProductoServicioSave'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ProductoServicioDelete + @CvePS int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.ProductosServicios + WHERE CvePS = @CvePS + ) + BEGIN + SELECT + @ErrorMostrar = 'El producto o servicio seleccionado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Tra_CostosTramite + WHERE CvePS = @CvePS + ) + OR EXISTS + ( + SELECT 1 + FROM dbo.Tra_PagosDetalle + WHERE CvePS = @CvePS + ) + OR EXISTS + ( + SELECT 1 + FROM dbo.VentasDetalle + WHERE CvePS = @CvePS + ) + OR EXISTS + ( + SELECT 1 + FROM dbo.ProductosServicios + WHERE CvePS <> @CvePS + AND + ( + CvePSAdicional = @CvePS + OR CveCompuesto = @CvePS + ) + ) + BEGIN + SELECT + @ErrorMostrar = 'El producto o servicio tiene trámites, pagos, ventas o productos relacionados y no puede eliminarse.', + @ErrorTipo = 2; + RETURN; + END; + + DELETE dbo.ProductosServicios + WHERE CvePS = @CvePS; + + SET @Return = 1; + END TRY + BEGIN CATCH + IF ERROR_NUMBER() = 547 + BEGIN + SELECT + @ErrorMostrar = 'El producto o servicio tiene información relacionada y no puede eliminarse.', + @ErrorTipo = 2, + @Return = 0; + RETURN; + END; + + SELECT + @ErrorMostrar = 'Ocurrió un error al eliminar el producto o servicio; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ProductoServicioDelete'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +DECLARE @CveTabla int; + +SELECT @CveTabla = CveTabla +FROM dbo.Bit_Tablas +WHERE NombreTablaSQL = 'ProductosServicios' COLLATE Modern_Spanish_CS_AS; + +IF @CveTabla IS NULL +BEGIN + INSERT dbo.Bit_Tablas + ( + NombreTablaSQL, + NombreMostrar, + Descripcion, + NombreCampoLlaveSQL, + Activo + ) + VALUES + ( + 'ProductosServicios', + 'Productos y servicios', + 'Catálogo de productos y servicios.', + 'CvePS', + 1 + ); + + SET @CveTabla = CONVERT(int, SCOPE_IDENTITY()); +END +ELSE +BEGIN + UPDATE dbo.Bit_Tablas + SET NombreMostrar = 'Productos y servicios', + Descripcion = 'Catálogo de productos y servicios.', + NombreCampoLlaveSQL = 'CvePS', + Activo = 1, + FechaMod = GETDATE() + WHERE CveTabla = @CveTabla; +END; + +DECLARE @Campos TABLE +( + NombreCampoSQL varchar(128) COLLATE Modern_Spanish_CS_AS NOT NULL, + NombreMostrar varchar(150) COLLATE Modern_Spanish_CS_AS NOT NULL, + MostrarEnBitacora bit NOT NULL +); + +INSERT INTO @Campos + (NombreCampoSQL, NombreMostrar, MostrarEnBitacora) +VALUES + ('CvePS', 'Clave', 0), + ('Codigo', 'Código', 1), + ('PS', 'Descripción', 1), + ('CveTipoPS', 'Tipo', 1), + ('CveClasificacion', 'Clasificación', 1), + ('CveUnidadMedida', 'Unidad de medida', 1), + ('Precio', 'Precio', 1), + ('Estado', 'Activo', 1); + +UPDATE BC +SET NombreMostrar = C.NombreMostrar, + MostrarEnBitacora = C.MostrarEnBitacora, + TipoDatoSQL = TY.name COLLATE Modern_Spanish_CS_AS, + Activo = 1, + FechaMod = GETDATE() +FROM dbo.Bit_Campos AS BC +INNER JOIN @Campos AS C + ON C.NombreCampoSQL = BC.NombreCampoSQL +INNER JOIN sys.columns AS SC + ON SC.object_id = OBJECT_ID(N'dbo.ProductosServicios') + AND SC.name COLLATE Modern_Spanish_CS_AS = C.NombreCampoSQL +INNER JOIN sys.types AS TY + ON TY.user_type_id = SC.user_type_id +WHERE BC.CveTabla = @CveTabla; + +INSERT dbo.Bit_Campos +( + CveTabla, + NombreCampoSQL, + NombreMostrar, + MostrarEnBitacora, + TipoDatoSQL, + Activo +) +SELECT + @CveTabla, + C.NombreCampoSQL, + C.NombreMostrar, + C.MostrarEnBitacora, + TY.name COLLATE Modern_Spanish_CS_AS, + 1 +FROM @Campos AS C +INNER JOIN sys.columns AS SC + ON SC.object_id = OBJECT_ID(N'dbo.ProductosServicios') + AND SC.name COLLATE Modern_Spanish_CS_AS = C.NombreCampoSQL +INNER JOIN sys.types AS TY + ON TY.user_type_id = SC.user_type_id +WHERE NOT EXISTS +( + SELECT 1 + FROM dbo.Bit_Campos AS BC + WHERE BC.CveTabla = @CveTabla + AND BC.NombreCampoSQL = C.NombreCampoSQL +); +GO diff --git a/Catalogos_Clasificaciones_UnidadesMedida.sql b/Catalogos_Clasificaciones_UnidadesMedida.sql new file mode 100644 index 0000000..faed45c --- /dev/null +++ b/Catalogos_Clasificaciones_UnidadesMedida.sql @@ -0,0 +1,674 @@ +SET NOCOUNT ON; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ClasificacionList + @Texto varchar(200) = NULL, + @IncluirInactivos bit = 0, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SET @Texto = NULLIF(LTRIM(RTRIM(@Texto)), ''); + + SELECT + CveClasificacion, + Codigo, + Clasificacion, + Afectable, + Estado AS EsActivo + FROM dbo.Clasificaciones + WHERE (@IncluirInactivos = 1 OR Estado = 1) + AND + ( + @Texto IS NULL + OR Codigo LIKE '%' + @Texto + '%' + OR Clasificacion LIKE '%' + @Texto + '%' + ) + ORDER BY Clasificacion, Codigo, CveClasificacion; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar las clasificaciones; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ClasificacionList'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ClasificacionGet + @CveClasificacion int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SELECT + CveClasificacion, + Codigo, + Clasificacion, + Afectable, + Estado AS EsActivo + FROM dbo.Clasificaciones + WHERE CveClasificacion = @CveClasificacion; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar la clasificación; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ClasificacionGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ClasificacionSave + @CveClasificacion int = NULL, + @Codigo varchar(20) = NULL, + @Clasificacion varchar(200), + @Afectable bit, + @EsActivo bit, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SELECT + @CveClasificacion = NULLIF(@CveClasificacion, 0), + @Codigo = NULLIF(LTRIM(RTRIM(@Codigo)), ''), + @Clasificacion = LTRIM(RTRIM(@Clasificacion)); + + IF NULLIF(@Clasificacion, '') IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture la clasificación.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Clasificaciones + WHERE Clasificacion = @Clasificacion + AND CveClasificacion <> ISNULL(@CveClasificacion, 0) + ) + BEGIN + SELECT + @ErrorMostrar = 'Ya existe una clasificación con ese nombre.', + @ErrorTipo = 2; + RETURN; + END; + + IF @Codigo IS NOT NULL + AND EXISTS + ( + SELECT 1 + FROM dbo.Clasificaciones + WHERE Codigo = @Codigo + AND CveClasificacion <> ISNULL(@CveClasificacion, 0) + ) + BEGIN + SELECT + @ErrorMostrar = 'El código ya está asignado a otra clasificación.', + @ErrorTipo = 2; + RETURN; + END; + + IF @CveClasificacion IS NULL + BEGIN + INSERT dbo.Clasificaciones + ( + Codigo, + Clasificacion, + Estado, + Afectable, + Fecha, + CveUsuario + ) + VALUES + ( + @Codigo, + @Clasificacion, + @EsActivo, + @Afectable, + CONVERT(date, GETDATE()), + @CveUsuarioEjecuta + ); + + SET @CveClasificacion = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Clasificaciones + WHERE CveClasificacion = @CveClasificacion + ) + BEGIN + SELECT + @ErrorMostrar = 'La clasificación seleccionada no existe.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Clasificaciones + SET Codigo = @Codigo, + Clasificacion = @Clasificacion, + Estado = @EsActivo, + Afectable = @Afectable + WHERE CveClasificacion = @CveClasificacion; + END; + + SELECT @CveClasificacion AS CveClasificacion; + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al guardar la clasificación; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ClasificacionSave'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_ClasificacionDelete + @CveClasificacion int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Clasificaciones + WHERE CveClasificacion = @CveClasificacion + ) + BEGIN + SELECT + @ErrorMostrar = 'La clasificación seleccionada no existe.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.ProductosServicios + WHERE CveClasificacion = @CveClasificacion + OR CveClasificacion2 = @CveClasificacion + ) + OR EXISTS + ( + SELECT 1 + FROM dbo.Conta_PrePolizasDetalle + WHERE CveClasificacion = @CveClasificacion + ) + BEGIN + SELECT + @ErrorMostrar = 'La clasificación tiene productos, servicios o pólizas relacionados y no puede eliminarse.', + @ErrorTipo = 2; + RETURN; + END; + + DELETE dbo.Clasificaciones + WHERE CveClasificacion = @CveClasificacion; + + SET @Return = 1; + END TRY + BEGIN CATCH + IF ERROR_NUMBER() = 547 + BEGIN + SELECT + @ErrorMostrar = 'La clasificación tiene información relacionada y no puede eliminarse.', + @ErrorTipo = 2, + @Return = 0; + RETURN; + END; + + SELECT + @ErrorMostrar = 'Ocurrió un error al eliminar la clasificación; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_ClasificacionDelete'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_UnidadMedidaList + @Texto varchar(100) = NULL, + @IncluirInactivos bit = 0, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SET @Texto = NULLIF(LTRIM(RTRIM(@Texto)), ''); + + SELECT + CveUnidadMedida, + UnidadMedida, + Abreviatura, + Estado AS EsActivo + FROM dbo.UnidadesMedida + WHERE (@IncluirInactivos = 1 OR Estado = 1) + AND + ( + @Texto IS NULL + OR UnidadMedida LIKE '%' + @Texto + '%' + OR Abreviatura LIKE '%' + @Texto + '%' + ) + ORDER BY UnidadMedida, CveUnidadMedida; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar las unidades de medida; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_UnidadMedidaList'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_UnidadMedidaGet + @CveUnidadMedida int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SELECT + CveUnidadMedida, + UnidadMedida, + Abreviatura, + Estado AS EsActivo + FROM dbo.UnidadesMedida + WHERE CveUnidadMedida = @CveUnidadMedida; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar la unidad de medida; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_UnidadMedidaGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_UnidadMedidaSave + @CveUnidadMedida int = NULL, + @UnidadMedida varchar(50), + @Abreviatura varchar(15), + @EsActivo bit, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SELECT + @CveUnidadMedida = NULLIF(@CveUnidadMedida, 0), + @UnidadMedida = LTRIM(RTRIM(@UnidadMedida)), + @Abreviatura = LTRIM(RTRIM(@Abreviatura)); + + IF NULLIF(@UnidadMedida, '') IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture la unidad de medida.', + @ErrorTipo = 2; + RETURN; + END; + + IF NULLIF(@Abreviatura, '') IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture la abreviatura.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.UnidadesMedida + WHERE UnidadMedida = @UnidadMedida + AND CveUnidadMedida <> ISNULL(@CveUnidadMedida, 0) + ) + BEGIN + SELECT + @ErrorMostrar = 'Ya existe una unidad de medida con ese nombre.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.UnidadesMedida + WHERE Abreviatura = @Abreviatura + AND CveUnidadMedida <> ISNULL(@CveUnidadMedida, 0) + ) + BEGIN + SELECT + @ErrorMostrar = 'La abreviatura ya está asignada a otra unidad de medida.', + @ErrorTipo = 2; + RETURN; + END; + + IF @CveUnidadMedida IS NULL + BEGIN + INSERT dbo.UnidadesMedida + ( + UnidadMedida, + Abreviatura, + Estado, + Fecha, + CveUsuario + ) + VALUES + ( + @UnidadMedida, + @Abreviatura, + @EsActivo, + CONVERT(date, GETDATE()), + @CveUsuarioEjecuta + ); + + SET @CveUnidadMedida = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.UnidadesMedida + WHERE CveUnidadMedida = @CveUnidadMedida + ) + BEGIN + SELECT + @ErrorMostrar = 'La unidad de medida seleccionada no existe.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.UnidadesMedida + SET UnidadMedida = @UnidadMedida, + Abreviatura = @Abreviatura, + Estado = @EsActivo + WHERE CveUnidadMedida = @CveUnidadMedida; + END; + + SELECT @CveUnidadMedida AS CveUnidadMedida; + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al guardar la unidad de medida; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_UnidadMedidaSave'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Gral_UnidadMedidaDelete + @CveUnidadMedida int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.UnidadesMedida + WHERE CveUnidadMedida = @CveUnidadMedida + ) + BEGIN + SELECT + @ErrorMostrar = 'La unidad de medida seleccionada no existe.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.ProductosServicios + WHERE CveUnidadMedida = @CveUnidadMedida + ) + OR EXISTS + ( + SELECT 1 + FROM dbo.Tra_PagosDetalle + WHERE CveUM = @CveUnidadMedida + ) + BEGIN + SELECT + @ErrorMostrar = 'La unidad de medida tiene productos, servicios o pagos relacionados y no puede eliminarse.', + @ErrorTipo = 2; + RETURN; + END; + + DELETE dbo.UnidadesMedida + WHERE CveUnidadMedida = @CveUnidadMedida; + + SET @Return = 1; + END TRY + BEGIN CATCH + IF ERROR_NUMBER() = 547 + BEGIN + SELECT + @ErrorMostrar = 'La unidad de medida tiene información relacionada y no puede eliminarse.', + @ErrorTipo = 2, + @Return = 0; + RETURN; + END; + + SELECT + @ErrorMostrar = 'Ocurrió un error al eliminar la unidad de medida; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Gral_UnidadMedidaDelete'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +DECLARE @Tablas TABLE +( + NombreTablaSQL varchar(128) COLLATE Modern_Spanish_CS_AS NOT NULL, + NombreMostrar varchar(150) COLLATE Modern_Spanish_CS_AS NOT NULL, + CampoLlave varchar(128) COLLATE Modern_Spanish_CS_AS NOT NULL +); + +INSERT INTO @Tablas + (NombreTablaSQL, NombreMostrar, CampoLlave) +VALUES + ('Clasificaciones', 'Clasificaciones', 'CveClasificacion'), + ('UnidadesMedida', 'Unidades de medida', 'CveUnidadMedida'); + +UPDATE BT +SET NombreMostrar = S.NombreMostrar, + NombreCampoLlaveSQL = S.CampoLlave, + Activo = 1, + FechaMod = GETDATE() +FROM dbo.Bit_Tablas AS BT +INNER JOIN @Tablas AS S + ON S.NombreTablaSQL = BT.NombreTablaSQL; + +INSERT dbo.Bit_Tablas + (NombreTablaSQL, NombreMostrar, Descripcion, NombreCampoLlaveSQL, Activo) +SELECT + S.NombreTablaSQL, + S.NombreMostrar, + 'Catálogo general de productos y servicios.', + S.CampoLlave, + 1 +FROM @Tablas AS S +WHERE NOT EXISTS +( + SELECT 1 + FROM dbo.Bit_Tablas AS BT + WHERE BT.NombreTablaSQL = S.NombreTablaSQL +); + +INSERT dbo.Bit_Campos + (CveTabla, NombreCampoSQL, NombreMostrar, MostrarEnBitacora, TipoDatoSQL, Activo) +SELECT + BT.CveTabla, + C.name, + C.name, + CASE WHEN C.name = S.CampoLlave THEN 0 ELSE 1 END, + TY.name, + 1 +FROM @Tablas AS S +INNER JOIN sys.tables AS T + ON T.name COLLATE Modern_Spanish_CS_AS = S.NombreTablaSQL +INNER JOIN sys.schemas AS SC + ON SC.schema_id = T.schema_id + AND SC.name = 'dbo' +INNER JOIN sys.columns AS C + ON C.object_id = T.object_id +INNER JOIN sys.types AS TY + ON TY.user_type_id = C.user_type_id +INNER JOIN dbo.Bit_Tablas AS BT + ON BT.NombreTablaSQL = S.NombreTablaSQL +WHERE NOT EXISTS +( + SELECT 1 + FROM dbo.Bit_Campos AS BC + WHERE BC.CveTabla = BT.CveTabla + AND BC.NombreCampoSQL = C.name COLLATE Modern_Spanish_CS_AS +); +GO diff --git a/Facturacion_Cfdi_Timbrado.sql b/Facturacion_Cfdi_Timbrado.sql index 4a4ee7f..c2b6a9f 100644 --- a/Facturacion_Cfdi_Timbrado.sql +++ b/Facturacion_Cfdi_Timbrado.sql @@ -290,20 +290,6 @@ BEGIN SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; BEGIN TRY - IF NOT EXISTS - ( - SELECT 1 - FROM dbo.Sis_Usuarios - WHERE CveUsuario = @CveUsuarioEjecuta - AND Activo = 1 - ) - BEGIN - SELECT - @ErrorMostrar = 'No cuenta con una sesión válida para consultar el emisor fiscal.', - @ErrorTipo = 2; - RETURN; - END; - IF NOT EXISTS ( SELECT 1 @@ -387,21 +373,6 @@ BEGIN SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; BEGIN TRY - IF NOT EXISTS - ( - SELECT 1 - FROM dbo.Sis_Usuarios - WHERE CveUsuario = @CveUsuarioEjecuta - AND CveRol IN (1, 2) - AND Activo = 1 - ) - BEGIN - SELECT - @ErrorMostrar = 'No cuenta con permiso para configurar emisores fiscales.', - @ErrorTipo = 2; - RETURN; - END; - SELECT @Rfc = UPPER(REPLACE(LTRIM(RTRIM(@Rfc)), ' ', '')), @NombreFiscal = LTRIM(RTRIM(@NombreFiscal)), diff --git a/Facturacion_Timbrado_Venta_20260828.sql b/Facturacion_Timbrado_Venta_20260828.sql new file mode 100644 index 0000000..9364de3 --- /dev/null +++ b/Facturacion_Timbrado_Venta_20260828.sql @@ -0,0 +1,590 @@ +CREATE OR ALTER PROCEDURE dbo.PA_Fac_EmisorFiscalGet + @CveEmpresa int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fac_EmisoresFiscales + WHERE CveEmpresa = @CveEmpresa + AND EsActivo = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'La empresa no tiene configurado un emisor fiscal activo.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + CveEmisorFiscal, + CveEmpresa, + Rfc, + NombreFiscal, + RegimenFiscal, + CodigoPostal, + ProveedorPac, + AmbienteProduccion, + ReferenciaCredencialPac, + ReferenciaContratoPac, + ReferenciaCertificadoCsd, + ReferenciaLlavePrivadaCsd, + NumeroCertificado, + VigenciaCertificadoDesde, + VigenciaCertificadoHasta, + HuellaCertificado, + EsActivo + FROM dbo.Fac_EmisoresFiscales + WHERE CveEmpresa = @CveEmpresa + AND EsActivo = 1; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar el emisor fiscal; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Fac_EmisorFiscalGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaDatosCfdiGet + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + + SELECT @CveVenta = V.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Primero debe generar la venta del trámite.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Ventas AS V + WHERE V.CveVenta = @CveVenta + AND + ( + V.SeTimbro = 1 + OR EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiDocumentos AS D + WHERE D.TipoOrigen = 'VENTA' + AND D.CveOrigen = V.CveVenta + AND D.Estado = 'TIMBRADO' + AND D.CveCfdiTimbradoVigente IS NOT NULL + ) + ) + ) + BEGIN + SELECT + @ErrorMostrar = 'La venta ya se encuentra timbrada.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiDocumentos + WHERE TipoOrigen = 'VENTA' + AND CveOrigen = @CveVenta + AND Estado = 'REVISAR' + ) + BEGIN + SELECT + @ErrorMostrar = 'Existe un intento de timbrado con resultado indeterminado; debe revisarse antes de volver a timbrar.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + V.CveVenta, + Borrador.CveCfdiDocumento, + V.CveCliente, + V.Serie, + V.Folio, + V.Fecha, + FP.ClaveFormaPagoSAT AS FormaPago, + MP.ClaveMetodoPagoSAT AS MetodoPago, + M.AbreviaturaSAT AS Moneda, + CONVERT(decimal(19, 6), V.TipoCambio) AS TipoCambio + FROM dbo.Ventas AS V + LEFT JOIN dbo.Vta_FormaPago AS FP + ON FP.CveFormaPago = V.FormaPago + LEFT JOIN dbo.Vta_MetodoPago AS MP + ON MP.CveMetodoPago = V.CveMetodoPago + INNER JOIN dbo.Gral_Monedas AS M + ON M.CveMoneda = V.CveMoneda + OUTER APPLY + ( + SELECT TOP (1) D.CveCfdiDocumento + FROM dbo.Fac_CfdiDocumentos AS D + WHERE D.TipoOrigen = 'VENTA' + AND D.CveOrigen = V.CveVenta + AND D.CveCfdiTimbradoVigente IS NULL + AND D.Estado IN ('BORRADOR', 'LISTO', 'ERROR') + ORDER BY D.CveCfdiDocumento DESC + ) AS Borrador + WHERE V.CveVenta = @CveVenta; + + SELECT + SATPS.SATClavePS AS ClaveProductoServicio, + PS.Codigo AS NumeroIdentificacion, + VD.Cantidad, + SATUM.SATClaveUnidadMedida AS ClaveUnidad, + UM.UnidadMedida AS Unidad, + PS.PS AS Descripcion, + VD.PrecioUnitario AS ValorUnitario, + VD.Descuento, + OI.CodigoObjetoImpuesto AS ObjetoImpuesto, + CONVERT( + decimal(19, 6), + ROUND(VD.Cantidad * VD.PrecioUnitario, 6) - VD.Descuento + ) AS BaseIVA, + CONVERT( + decimal(19, 6), + ISNULL(PS.IVA, 0) / 100.0 + ) AS TasaIVA, + CONVERT(decimal(19, 6), VD.IVA) AS ImporteIVA + FROM dbo.VentasDetalle AS VD + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = VD.CvePS + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = PS.CveUnidadMedida + LEFT JOIN dbo.Gral_SAT_ProductosServicios AS SATPS + ON SATPS.CveSATPS = PS.CveSATPS + LEFT JOIN dbo.Gral_SAT_UnidadesMedida AS SATUM + ON SATUM.CveSATUnidadMedida = UM.CveSATUnidadMedida + LEFT JOIN dbo.Gral_SAT_ObjetoImpuesto AS OI + ON OI.CveObjetoImpuesto = PS.CveObjetoImpuesto + WHERE VD.CveVenta = @CveVenta + ORDER BY VD.CveVentaDetalle; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al preparar los datos fiscales de la venta; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteVentaDatosCfdiGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Fac_EmisorFiscalSave + @CveEmisorFiscal int = NULL, + @CveEmpresa int, + @Rfc varchar(13), + @NombreFiscal varchar(300), + @RegimenFiscal varchar(3), + @CodigoPostal varchar(5), + @ProveedorPac varchar(50), + @AmbienteProduccion bit, + @ReferenciaCredencialPac varchar(100), + @ReferenciaContratoPac varchar(100) = NULL, + @ReferenciaCertificadoCsd varchar(500) = NULL, + @ReferenciaLlavePrivadaCsd varchar(500) = NULL, + @NumeroCertificado varchar(20) = NULL, + @VigenciaCertificadoDesde datetime2(0) = NULL, + @VigenciaCertificadoHasta datetime2(0) = NULL, + @HuellaCertificado varchar(128) = NULL, + @EsActivo bit, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SELECT + @Rfc = UPPER(REPLACE(LTRIM(RTRIM(@Rfc)), ' ', '')), + @NombreFiscal = LTRIM(RTRIM(@NombreFiscal)), + @RegimenFiscal = LTRIM(RTRIM(@RegimenFiscal)), + @CodigoPostal = LTRIM(RTRIM(@CodigoPostal)), + @ProveedorPac = UPPER(LTRIM(RTRIM(@ProveedorPac))), + @ReferenciaCredencialPac = LTRIM(RTRIM(@ReferenciaCredencialPac)), + @ReferenciaContratoPac = NULLIF(LTRIM(RTRIM(@ReferenciaContratoPac)), ''), + @ReferenciaCertificadoCsd = NULLIF(LTRIM(RTRIM(@ReferenciaCertificadoCsd)), ''), + @ReferenciaLlavePrivadaCsd = NULLIF(LTRIM(RTRIM(@ReferenciaLlavePrivadaCsd)), ''), + @NumeroCertificado = NULLIF(LTRIM(RTRIM(@NumeroCertificado)), ''), + @HuellaCertificado = NULLIF(LTRIM(RTRIM(@HuellaCertificado)), ''); + + IF LEN(@Rfc) NOT IN (12, 13) + OR NULLIF(@NombreFiscal, '') IS NULL + OR LEN(@RegimenFiscal) <> 3 + OR LEN(@CodigoPostal) <> 5 + OR NULLIF(@ProveedorPac, '') IS NULL + OR NULLIF(@ReferenciaCredencialPac, '') IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture RFC, nombre fiscal, régimen, código postal, PAC y referencia de credencial válidos.', + @ErrorTipo = 2; + RETURN; + END; + + IF @CveEmisorFiscal IS NULL + BEGIN + IF EXISTS + ( + SELECT 1 + FROM dbo.Fac_EmisoresFiscales + WHERE CveEmpresa = @CveEmpresa + ) + BEGIN + SELECT + @ErrorMostrar = 'La empresa ya cuenta con una configuración fiscal.', + @ErrorTipo = 2; + RETURN; + END; + + INSERT dbo.Fac_EmisoresFiscales + ( + CveEmpresa, + Rfc, + NombreFiscal, + RegimenFiscal, + CodigoPostal, + ProveedorPac, + AmbienteProduccion, + ReferenciaCredencialPac, + ReferenciaContratoPac, + ReferenciaCertificadoCsd, + ReferenciaLlavePrivadaCsd, + NumeroCertificado, + VigenciaCertificadoDesde, + VigenciaCertificadoHasta, + HuellaCertificado, + EsActivo, + CveUsuario + ) + VALUES + ( + @CveEmpresa, + @Rfc, + @NombreFiscal, + @RegimenFiscal, + @CodigoPostal, + @ProveedorPac, + @AmbienteProduccion, + @ReferenciaCredencialPac, + @ReferenciaContratoPac, + @ReferenciaCertificadoCsd, + @ReferenciaLlavePrivadaCsd, + @NumeroCertificado, + @VigenciaCertificadoDesde, + @VigenciaCertificadoHasta, + @HuellaCertificado, + @EsActivo, + @CveUsuarioEjecuta + ); + + SET @CveEmisorFiscal = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fac_EmisoresFiscales + WHERE CveEmisorFiscal = @CveEmisorFiscal + AND CveEmpresa = @CveEmpresa + ) + BEGIN + SELECT + @ErrorMostrar = 'No se encontró la configuración fiscal seleccionada.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Fac_EmisoresFiscales + SET Rfc = @Rfc, + NombreFiscal = @NombreFiscal, + RegimenFiscal = @RegimenFiscal, + CodigoPostal = @CodigoPostal, + ProveedorPac = @ProveedorPac, + AmbienteProduccion = @AmbienteProduccion, + ReferenciaCredencialPac = @ReferenciaCredencialPac, + ReferenciaContratoPac = @ReferenciaContratoPac, + ReferenciaCertificadoCsd = @ReferenciaCertificadoCsd, + ReferenciaLlavePrivadaCsd = @ReferenciaLlavePrivadaCsd, + NumeroCertificado = @NumeroCertificado, + VigenciaCertificadoDesde = @VigenciaCertificadoDesde, + VigenciaCertificadoHasta = @VigenciaCertificadoHasta, + HuellaCertificado = @HuellaCertificado, + EsActivo = @EsActivo, + FechaModificacion = SYSDATETIME(), + CveUsuario = @CveUsuarioEjecuta + WHERE CveEmisorFiscal = @CveEmisorFiscal; + END; + + SELECT @CveEmisorFiscal AS CveEmisorFiscal; + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al guardar el emisor fiscal; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Fac_EmisorFiscalSave'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteContextoGet + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveSubProyecto int = + ( + SELECT TOP (1) CveSubProyecto + FROM dbo.SubProyectos + WHERE Estatus = 1 + ORDER BY + CASE WHEN Serie = 'TRA' THEN 0 ELSE 1 END, + CveSubProyecto + ); + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + WHERE S.CveSolicitud = @CveSolicitud + ) + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado no corresponde al trámite o no tiene conceptos activos.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + S.CveSolicitud, + P.CveTramitePago, + SP.CveVenta, + VP.CvePago, + CONVERT( + bit, + CASE + WHEN SP.CveSolicitudPago IS NOT NULL + AND V.CveVenta IS NOT NULL + THEN 1 + ELSE 0 + END + ) AS VentaGenerada, + CONVERT( + bit, + CASE WHEN VP.Autorizado = 1 THEN 1 ELSE 0 END + ) AS VentaPagada, + CONVERT( + bit, + CASE + WHEN VP.CvePago IS NOT NULL + AND VP.Autorizado = 0 + THEN 1 + ELSE 0 + END + ) AS PagoPendienteAutorizacion, + VP.Referencia AS ReferenciaPago, + Documento.CveCfdiDocumento, + CONVERT( + bit, + CASE + WHEN V.SeTimbro = 1 + OR Documento.Estado = 'TIMBRADO' + THEN 1 + ELSE 0 + END + ) AS VentaTimbrada, + CONVERT( + bit, + CASE WHEN Documento.Estado = 'CANCELADO' THEN 1 ELSE 0 END + ) AS TimbreCancelado, + Documento.Uuid AS UuidTimbre, + S.CveFraccionamiento, + F.Fraccionamiento, + F.CveCliente, + C.Nombre AS Cliente, + C.RFC, + CONCAT( + C.Direccion, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.NoExt)), '') IS NULL + THEN '' + ELSE CONCAT(' ', C.NoExt) + END, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.NoInt)), '') IS NULL + THEN '' + ELSE CONCAT(' Int. ', C.NoInt) + END + ) AS Direccion, + C.Colonia, + CONCAT(C.Ciudad, ', ', C.Estado) AS CiudadEstado, + C.CP, + C.Telefono, + C.Mail, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + N'Remisión' AS TipoDocumento, + ISNULL(V.Serie, 'TRA') AS Serie, + ISNULL( + V.Folio, + ISNULL( + ( + SELECT MAX(Venta.Folio) + 1 + FROM dbo.Ventas AS Venta + WHERE Venta.TipoDocto = 'Rem' + AND Venta.Serie = 'TRA' + AND Venta.CveSubProyecto = @CveSubProyecto + ), + 1 + ) + ) AS Folio, + ISNULL(V.Fecha, GETDATE()) AS Fecha, + ISNULL(V.CveMetodoPago33, ISNULL(V.CveMetodoPago, 2)) + AS CveMetodoPago, + ISNULL(V.CveFormaPago33, ISNULL(V.FormaPago, 99)) + AS CveFormaPago, + V.FechaVencimiento2 AS FechaVencimiento + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Fraccionamientos AS F + ON F.CveFraccionamiento = S.CveFraccionamiento + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = F.CveCliente + LEFT JOIN dbo.Tra_SolicitudesPagos AS SP + ON SP.CveSolicitud = S.CveSolicitud + AND SP.CveTramitePago = P.CveTramitePago + LEFT JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + OUTER APPLY + ( + SELECT TOP (1) + Pago.CvePago, + Pago.Autorizado, + Pago.Referencia + FROM dbo.Vta_Pagos AS Pago + WHERE Pago.CveVenta = V.CveVenta + AND Pago.CveSolicitud = S.CveSolicitud + AND Pago.CveTramitePago = P.CveTramitePago + AND Pago.EsActivo = 1 + ORDER BY Pago.CvePago DESC + ) AS VP + OUTER APPLY + ( + SELECT TOP (1) + D.CveCfdiDocumento, + D.Estado, + T.Uuid + FROM dbo.Fac_CfdiDocumentos AS D + LEFT JOIN dbo.Fac_CfdiTimbrados AS T + ON T.CveCfdiTimbrado = D.CveCfdiTimbradoVigente + WHERE D.TipoOrigen = 'VENTA' + AND D.CveOrigen = V.CveVenta + AND D.Estado IN ('TIMBRADO', 'CANCELADO') + ORDER BY D.CveCfdiDocumento DESC + ) AS Documento + WHERE S.CveSolicitud = @CveSolicitud; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar la venta del trámite; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteContextoGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO diff --git a/Fraccionamientos_Ventas_Conceptos_Timbrado_20260827.sql b/Fraccionamientos_Ventas_Conceptos_Timbrado_20260827.sql new file mode 100644 index 0000000..8d1b679 --- /dev/null +++ b/Fraccionamientos_Ventas_Conceptos_Timbrado_20260827.sql @@ -0,0 +1,1117 @@ +SET ANSI_NULLS ON; +SET QUOTED_IDENTIFIER ON; +GO + +DECLARE @Permisos TABLE +( + CodigoPermiso varchar(100) COLLATE Modern_Spanish_CI_AS NOT NULL, + NombrePermiso varchar(150) NOT NULL, + Descripcion varchar(300) NOT NULL +); + +INSERT INTO @Permisos + (CodigoPermiso, NombrePermiso, Descripcion) +VALUES + ('Ventas.Tramites.AgregarConceptos', 'Agregar conceptos a ventas de trámites', 'Permite agregar productos o servicios a una venta de trámite antes de timbrarla.'), + ('Ventas.Tramites.ModificarConceptos', 'Modificar conceptos de ventas de trámites', 'Permite modificar la cantidad y el precio unitario de los conceptos antes de timbrar la venta.'), + ('Ventas.Tramites.EliminarConceptos', 'Eliminar conceptos de ventas de trámites', 'Permite quitar productos o servicios de una venta de trámite antes de timbrarla.'), + ('Ventas.Tramites.Timbrar', 'Timbrar ventas de trámites', 'Permite timbrar una venta de trámite pagada.'), + ('Ventas.Tramites.CancelarTimbre', 'Cancelar timbres de ventas de trámites', 'Permite solicitar al PAC la cancelación del timbre vigente de una venta de trámite.'); + +INSERT INTO dbo.Sis_Permisos +( + CodigoPermiso, + NombrePermiso, + Descripcion, + Activo, + FechaCreacion +) +SELECT + P.CodigoPermiso, + P.NombrePermiso, + P.Descripcion, + 1, + GETDATE() +FROM @Permisos AS P +WHERE NOT EXISTS +( + SELECT 1 + FROM dbo.Sis_Permisos AS Existente + WHERE Existente.CodigoPermiso = P.CodigoPermiso +); + +UPDATE Existente +SET + NombrePermiso = P.NombrePermiso, + Descripcion = P.Descripcion, + Activo = 1, + FechaActualizacion = GETDATE() +FROM dbo.Sis_Permisos AS Existente +INNER JOIN @Permisos AS P + ON P.CodigoPermiso = Existente.CodigoPermiso; + +INSERT INTO dbo.Sis_RolesPermisos +( + CveRol, + CvePermiso, + Permitido, + FechaCreacion +) +SELECT + R.CveRol, + P.CvePermiso, + 1, + GETDATE() +FROM dbo.Sis_Roles AS R +CROSS JOIN dbo.Sis_Permisos AS P +WHERE R.CveRol IN (1, 2) + AND P.CodigoPermiso IN + ( + 'Ventas.Tramites.ModificarConceptos', + 'Ventas.Tramites.AgregarConceptos', + 'Ventas.Tramites.EliminarConceptos', + 'Ventas.Tramites.Timbrar', + 'Ventas.Tramites.CancelarTimbre' + ) + AND NOT EXISTS + ( + SELECT 1 + FROM dbo.Sis_RolesPermisos AS RP + WHERE RP.CveRol = R.CveRol + AND RP.CvePermiso = P.CvePermiso + ); +GO + +IF OBJECT_ID(N'dbo.Fac_CfdiCancelaciones', N'U') IS NULL +BEGIN + CREATE TABLE dbo.Fac_CfdiCancelaciones + ( + CveCfdiCancelacion bigint IDENTITY(1, 1) NOT NULL, + CveCfdiDocumento bigint NOT NULL, + CveCfdiTimbrado bigint NOT NULL, + IdSolicitud uniqueidentifier NOT NULL, + ProveedorPac varchar(50) NOT NULL, + Ambiente varchar(20) NOT NULL, + Motivo varchar(2) NOT NULL, + UuidSustitucion varchar(36) NULL, + Estado varchar(20) NOT NULL, + Exitoso bit NOT NULL, + CodigoRespuesta varchar(100) NULL, + MensajeRespuesta varchar(2000) NULL, + TipoExcepcion varchar(300) NULL, + FechaSolicitud datetime2(0) NOT NULL, + FechaRespuesta datetime2(0) NULL, + CveUsuario int NOT NULL, + CONSTRAINT PK_Fac_CfdiCancelaciones + PRIMARY KEY CLUSTERED (CveCfdiCancelacion), + CONSTRAINT UQ_Fac_CfdiCancelaciones_IdSolicitud + UNIQUE NONCLUSTERED (IdSolicitud), + CONSTRAINT FK_Fac_CfdiCancelaciones_Documentos + FOREIGN KEY (CveCfdiDocumento) + REFERENCES dbo.Fac_CfdiDocumentos (CveCfdiDocumento), + CONSTRAINT FK_Fac_CfdiCancelaciones_Timbrados + FOREIGN KEY (CveCfdiTimbrado) + REFERENCES dbo.Fac_CfdiTimbrados (CveCfdiTimbrado), + CONSTRAINT FK_Fac_CfdiCancelaciones_Usuarios + FOREIGN KEY (CveUsuario) + REFERENCES dbo.Sis_Usuarios (CveUsuario), + CONSTRAINT CK_Fac_CfdiCancelaciones_Motivo + CHECK (Motivo IN ('01', '02', '03', '04')) + ); + + CREATE NONCLUSTERED INDEX IX_Fac_CfdiCancelaciones_Documento_Fecha + ON dbo.Fac_CfdiCancelaciones + ( + CveCfdiDocumento, + FechaSolicitud DESC, + CveCfdiCancelacion DESC + ); +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Fac_CfdiCancelacionAttemptStart + @CveCfdiDocumento bigint, + @IdSolicitud uniqueidentifier, + @ProveedorPac varchar(50), + @Ambiente varchar(20), + @Motivo varchar(2), + @UuidSustitucion varchar(36) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveCfdiTimbrado bigint; + DECLARE @RfcEmisor varchar(13); + DECLARE @Uuid varchar(36); + DECLARE @CveCfdiCancelacion bigint; + + IF @Motivo NOT IN ('01', '02', '03', '04') + BEGIN + SELECT @ErrorMostrar = 'Seleccione un motivo de cancelación válido.', @ErrorTipo = 2; + RETURN; + END; + + IF @Motivo = '01' AND NULLIF(LTRIM(RTRIM(@UuidSustitucion)), '') IS NULL + BEGIN + SELECT @ErrorMostrar = 'Capture el UUID que sustituirá al timbre cancelado.', @ErrorTipo = 2; + RETURN; + END; + + SELECT + @CveCfdiTimbrado = D.CveCfdiTimbradoVigente, + @RfcEmisor = D.RfcEmisor, + @Uuid = T.Uuid + FROM dbo.Fac_CfdiDocumentos AS D WITH (UPDLOCK, HOLDLOCK) + INNER JOIN dbo.Fac_CfdiTimbrados AS T + ON T.CveCfdiTimbrado = D.CveCfdiTimbradoVigente + WHERE D.CveCfdiDocumento = @CveCfdiDocumento + AND D.Estado = 'TIMBRADO' + AND T.Exitoso = 1; + + IF @CveCfdiTimbrado IS NULL OR NULLIF(@Uuid, '') IS NULL + BEGIN + SELECT @ErrorMostrar = 'El CFDI no tiene un timbre vigente para cancelar.', @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiCancelaciones + WHERE CveCfdiDocumento = @CveCfdiDocumento + AND Exitoso = 1 + ) + BEGIN + SELECT @ErrorMostrar = 'El timbre ya fue cancelado.', @ErrorTipo = 2; + RETURN; + END; + + SELECT @CveCfdiCancelacion = CveCfdiCancelacion + FROM dbo.Fac_CfdiCancelaciones + WHERE IdSolicitud = @IdSolicitud; + + IF @CveCfdiCancelacion IS NULL + BEGIN + INSERT INTO dbo.Fac_CfdiCancelaciones + ( + CveCfdiDocumento, + CveCfdiTimbrado, + IdSolicitud, + ProveedorPac, + Ambiente, + Motivo, + UuidSustitucion, + Estado, + Exitoso, + FechaSolicitud, + CveUsuario + ) + VALUES + ( + @CveCfdiDocumento, + @CveCfdiTimbrado, + @IdSolicitud, + @ProveedorPac, + @Ambiente, + @Motivo, + NULLIF(LTRIM(RTRIM(@UuidSustitucion)), ''), + 'PENDIENTE', + 0, + SYSDATETIME(), + @CveUsuarioEjecuta + ); + + SET @CveCfdiCancelacion = CONVERT(bigint, SCOPE_IDENTITY()); + END; + + SELECT + @CveCfdiCancelacion AS CveCfdiCancelacion, + @CveCfdiDocumento AS CveCfdiDocumento, + @CveCfdiTimbrado AS CveCfdiTimbrado, + @IdSolicitud AS IdSolicitud, + @RfcEmisor AS RfcEmisor, + @Uuid AS Uuid, + @Motivo AS Motivo, + NULLIF(LTRIM(RTRIM(@UuidSustitucion)), '') AS UuidSustitucion, + CONVERT(bit, 1) AS PuedeEnviar; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'Ocurrió un error al iniciar la cancelación del CFDI; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Fac_CfdiCancelacionAttemptStart'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Fac_CfdiCancelacionAttemptComplete + @CveCfdiCancelacion bigint, + @Exitoso bit, + @ResultadoIndeterminado bit, + @CodigoRespuesta varchar(100) = NULL, + @MensajeRespuesta varchar(2000) = NULL, + @TipoExcepcion varchar(300) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveCfdiDocumento bigint; + DECLARE @Estado varchar(20) = + CASE + WHEN @Exitoso = 1 THEN 'EXITOSO' + WHEN @ResultadoIndeterminado = 1 THEN 'INDETERMINADO' + ELSE 'FALLIDO' + END; + + SELECT @CveCfdiDocumento = CveCfdiDocumento + FROM dbo.Fac_CfdiCancelaciones WITH (UPDLOCK, HOLDLOCK) + WHERE CveCfdiCancelacion = @CveCfdiCancelacion + AND Estado = 'PENDIENTE'; + + IF @CveCfdiDocumento IS NULL + BEGIN + SELECT @ErrorMostrar = 'El intento de cancelación no existe o ya fue finalizado.', @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Fac_CfdiCancelaciones + SET + Estado = @Estado, + Exitoso = @Exitoso, + CodigoRespuesta = NULLIF(LTRIM(RTRIM(@CodigoRespuesta)), ''), + MensajeRespuesta = NULLIF(LTRIM(RTRIM(@MensajeRespuesta)), ''), + TipoExcepcion = NULLIF(LTRIM(RTRIM(@TipoExcepcion)), ''), + FechaRespuesta = SYSDATETIME(), + CveUsuario = @CveUsuarioEjecuta + WHERE CveCfdiCancelacion = @CveCfdiCancelacion; + + IF @Exitoso = 1 + BEGIN + UPDATE dbo.Fac_CfdiDocumentos + SET + Estado = 'CANCELADO', + FechaModificacion = SYSDATETIME(), + CveUsuario = @CveUsuarioEjecuta + WHERE CveCfdiDocumento = @CveCfdiDocumento; + END; + + SELECT + @CveCfdiDocumento AS CveCfdiDocumento, + @CveCfdiCancelacion AS CveCfdiCancelacion, + @Exitoso AS CancelacionExitosa, + @Estado AS Estado, + @CodigoRespuesta AS CodigoRespuesta, + @MensajeRespuesta AS Mensaje; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'El PAC respondió, pero no fue posible guardar la cancelación; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Fac_CfdiCancelacionAttemptComplete'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaTimbreCanceladoUpdate + @CveVenta int, + @CveCfdiDocumento bigint, + @Motivo varchar(2), + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiDocumentos + WHERE CveCfdiDocumento = @CveCfdiDocumento + AND TipoOrigen = 'VENTA' + AND CveOrigen = @CveVenta + AND Estado = 'CANCELADO' + ) + BEGIN + SELECT @ErrorMostrar = 'La cancelación del CFDI no corresponde a la venta.', @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Ventas + SET + SeTimbro = 0, + MotivoCancelacion = @Motivo, + FechaCancelacion = GETDATE(), + EstadoCancelacion = 'CANCELADO', + CveUsuarioModifico = @CveUsuarioEjecuta + WHERE CveVenta = @CveVenta; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'El timbre fue cancelado, pero no fue posible actualizar la venta; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteVentaTimbreCanceladoUpdate'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteContextoGet + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveSubProyecto int = + ( + SELECT TOP (1) CveSubProyecto + FROM dbo.SubProyectos + WHERE Estatus = 1 + ORDER BY CASE WHEN Serie = 'TRA' THEN 0 ELSE 1 END, CveSubProyecto + ); + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + WHERE S.CveSolicitud = @CveSolicitud + ) + BEGIN + SELECT @ErrorMostrar = 'El pago seleccionado no corresponde al trámite o no tiene conceptos activos.', @ErrorTipo = 2; + RETURN; + END; + + SELECT + S.CveSolicitud, + P.CveTramitePago, + SP.CveVenta, + VP.CvePago, + CONVERT(bit, CASE WHEN SP.CveSolicitudPago IS NOT NULL AND V.CveVenta IS NOT NULL THEN 1 ELSE 0 END) AS VentaGenerada, + CONVERT(bit, CASE WHEN VP.CvePago IS NOT NULL THEN 1 ELSE 0 END) AS VentaPagada, + Documento.CveCfdiDocumento, + CONVERT(bit, CASE WHEN V.SeTimbro = 1 OR Documento.Estado = 'TIMBRADO' THEN 1 ELSE 0 END) AS VentaTimbrada, + CONVERT(bit, CASE WHEN Documento.Estado = 'CANCELADO' THEN 1 ELSE 0 END) AS TimbreCancelado, + Documento.Uuid AS UuidTimbre, + S.CveFraccionamiento, + F.Fraccionamiento, + F.CveCliente, + C.Nombre AS Cliente, + C.RFC, + CONCAT( + C.Direccion, + CASE WHEN NULLIF(LTRIM(RTRIM(C.NoExt)), '') IS NULL THEN '' ELSE CONCAT(' ', C.NoExt) END, + CASE WHEN NULLIF(LTRIM(RTRIM(C.NoInt)), '') IS NULL THEN '' ELSE CONCAT(' Int. ', C.NoInt) END + ) AS Direccion, + C.Colonia, + CONCAT(C.Ciudad, ', ', C.Estado) AS CiudadEstado, + C.CP, + C.Telefono, + C.Mail, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + N'Remisión' AS TipoDocumento, + ISNULL(V.Serie, 'TRA') AS Serie, + ISNULL( + V.Folio, + ISNULL( + ( + SELECT MAX(Venta.Folio) + 1 + FROM dbo.Ventas AS Venta + WHERE Venta.TipoDocto = 'Rem' + AND Venta.Serie = 'TRA' + AND Venta.CveSubProyecto = @CveSubProyecto + ), + 1 + ) + ) AS Folio, + ISNULL(V.Fecha, GETDATE()) AS Fecha + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Fraccionamientos AS F + ON F.CveFraccionamiento = S.CveFraccionamiento + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = F.CveCliente + LEFT JOIN dbo.Tra_SolicitudesPagos AS SP + ON SP.CveSolicitud = S.CveSolicitud + AND SP.CveTramitePago = P.CveTramitePago + LEFT JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + OUTER APPLY + ( + SELECT TOP (1) Pago.CvePago + FROM dbo.Vta_Pagos AS Pago + WHERE Pago.CveVenta = V.CveVenta + AND Pago.CveSolicitud = S.CveSolicitud + AND Pago.CveTramitePago = P.CveTramitePago + AND Pago.EsActivo = 1 + ORDER BY Pago.CvePago DESC + ) AS VP + OUTER APPLY + ( + SELECT TOP (1) + D.CveCfdiDocumento, + D.Estado, + T.Uuid + FROM dbo.Fac_CfdiDocumentos AS D + LEFT JOIN dbo.Fac_CfdiTimbrados AS T + ON T.CveCfdiTimbrado = D.CveCfdiTimbradoVigente + WHERE D.TipoOrigen = 'VENTA' + AND D.CveOrigen = V.CveVenta + AND D.Estado IN ('TIMBRADO', 'CANCELADO') + ORDER BY D.CveCfdiDocumento DESC + ) AS Documento + WHERE S.CveSolicitud = @CveSolicitud; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'Ocurrió un error al consultar la venta del trámite; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteContextoGet'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaTimbradaUpdate + @CveVenta int, + @CveCfdiDocumento bigint, + @Uuid varchar(36), + @FechaTimbrado datetime = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiDocumentos + WHERE CveCfdiDocumento = @CveCfdiDocumento + AND TipoOrigen = 'VENTA' + AND CveOrigen = @CveVenta + AND Estado = 'TIMBRADO' + AND CveCfdiTimbradoVigente IS NOT NULL + ) + BEGIN + SELECT @ErrorMostrar = 'El CFDI timbrado no corresponde a la venta.', @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Ventas + SET + SeTimbro = 1, + FolioFiscal = @Uuid, + FechaTimbrado = ISNULL(@FechaTimbrado, GETDATE()), + MotivoCancelacion = NULL, + FechaCancelacion = NULL, + EstadoCancelacion = NULL, + CveUsuarioModifico = @CveUsuarioEjecuta + WHERE CveVenta = @CveVenta; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'El timbre fue emitido, pero no fue posible actualizar la venta; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteVentaTimbradaUpdate'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaTotalesUpdate + @CveVenta int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @SubTotal decimal(18, 2); + DECLARE @Descuento decimal(18, 2); + DECLARE @IVA decimal(18, 2); + DECLARE @Total decimal(18, 2); + + SELECT + @SubTotal = CONVERT(decimal(18, 2), SUM(ROUND(Cantidad * PrecioUnitario, 2))), + @Descuento = CONVERT(decimal(18, 2), SUM(Descuento)), + @IVA = CONVERT(decimal(18, 2), SUM(IVA)), + @Total = CONVERT(decimal(18, 2), SUM(Importe)) + FROM dbo.VentasDetalle + WHERE CveVenta = @CveVenta; + + IF @SubTotal IS NULL + BEGIN + SELECT @ErrorMostrar = 'La venta debe conservar al menos un concepto.', @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Ventas + SET + SubTotal = @SubTotal, + Descuento = ISNULL(@Descuento, 0), + IVA = ISNULL(@IVA, 0), + Total = @Total, + CveUsuarioModifico = @CveUsuarioEjecuta + WHERE CveVenta = @CveVenta; + + UPDATE dbo.Vta_Pagos + SET Importe = @Total + WHERE CveVenta = @CveVenta + AND EsActivo = 1; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'Ocurrió un error al actualizar los totales de la venta; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteVentaTotalesUpdate'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteConceptoDelete + @CveSolicitud int, + @CveTramitePago int, + @CveVentaDetalle int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + + SELECT @CveVenta = V.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT @ErrorMostrar = 'Primero debe generar la venta del trámite.', @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Ventas AS V + WHERE V.CveVenta = @CveVenta + AND + ( + V.SeTimbro = 1 + OR EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiDocumentos AS D + WHERE D.TipoOrigen = 'VENTA' + AND D.CveOrigen = V.CveVenta + AND D.Estado = 'TIMBRADO' + AND D.CveCfdiTimbradoVigente IS NOT NULL + ) + ) + ) + BEGIN + SELECT @ErrorMostrar = 'No se pueden eliminar conceptos de una venta timbrada.', @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.VentasDetalle + WHERE CveVentaDetalle = @CveVentaDetalle + AND CveVenta = @CveVenta + ) + BEGIN + SELECT @ErrorMostrar = 'El concepto seleccionado no pertenece a la venta.', @ErrorTipo = 2; + RETURN; + END; + + IF (SELECT COUNT(*) FROM dbo.VentasDetalle WHERE CveVenta = @CveVenta) <= 1 + BEGIN + SELECT @ErrorMostrar = 'La venta debe conservar al menos un concepto.', @ErrorTipo = 2; + RETURN; + END; + + DELETE FROM dbo.VentasDetalle + WHERE CveVentaDetalle = @CveVentaDetalle; + + EXEC dbo.PA_Vta_TramiteVentaTotalesUpdate + @CveVenta = @CveVenta, + @CveUsuarioEjecuta = @CveUsuarioEjecuta, + @ErrorMostrar = @ErrorMostrar OUTPUT, + @ErrorTipo = @ErrorTipo OUTPUT, + @Return = @Return OUTPUT; + + IF @Return = 0 + RETURN; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'Ocurrió un error al eliminar el concepto de la venta; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteConceptoDelete'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaDatosCfdiGet + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + + SELECT @CveVenta = V.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT @ErrorMostrar = 'Primero debe generar la venta del trámite.', @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Vta_Pagos + WHERE CveVenta = @CveVenta + AND CveSolicitud = @CveSolicitud + AND CveTramitePago = @CveTramitePago + AND EsActivo = 1 + ) + BEGIN + SELECT @ErrorMostrar = 'La venta debe estar pagada antes de timbrarla.', @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Ventas + WHERE CveVenta = @CveVenta + AND SeTimbro = 1 + ) + BEGIN + SELECT @ErrorMostrar = 'La venta ya se encuentra timbrada.', @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Fac_CfdiDocumentos + WHERE TipoOrigen = 'VENTA' + AND CveOrigen = @CveVenta + AND Estado = 'REVISAR' + ) + BEGIN + SELECT + @ErrorMostrar = 'Existe un intento de timbrado con resultado indeterminado; debe revisarse antes de volver a timbrar.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + V.CveVenta, + Borrador.CveCfdiDocumento, + V.CveCliente, + V.Serie, + V.Folio, + V.Fecha, + FP.ClaveFormaPagoSAT AS FormaPago, + MP.ClaveMetodoPagoSAT AS MetodoPago, + M.AbreviaturaSAT AS Moneda, + CONVERT(decimal(19, 6), V.TipoCambio) AS TipoCambio + FROM dbo.Ventas AS V + LEFT JOIN dbo.Vta_FormaPago AS FP + ON FP.CveFormaPago = V.FormaPago + LEFT JOIN dbo.Vta_MetodoPago AS MP + ON MP.CveMetodoPago = V.CveMetodoPago + INNER JOIN dbo.Gral_Monedas AS M + ON M.CveMoneda = V.CveMoneda + OUTER APPLY + ( + SELECT TOP (1) D.CveCfdiDocumento + FROM dbo.Fac_CfdiDocumentos AS D + WHERE D.TipoOrigen = 'VENTA' + AND D.CveOrigen = V.CveVenta + AND D.CveCfdiTimbradoVigente IS NULL + AND D.Estado IN ('BORRADOR', 'LISTO', 'ERROR') + ORDER BY D.CveCfdiDocumento DESC + ) AS Borrador + WHERE V.CveVenta = @CveVenta; + + SELECT + SATPS.SATClavePS AS ClaveProductoServicio, + PS.Codigo AS NumeroIdentificacion, + VD.Cantidad, + SATUM.SATClaveUnidadMedida AS ClaveUnidad, + UM.UnidadMedida AS Unidad, + PS.PS AS Descripcion, + VD.PrecioUnitario AS ValorUnitario, + VD.Descuento, + OI.CodigoObjetoImpuesto AS ObjetoImpuesto, + CONVERT(decimal(19, 6), ROUND(VD.Cantidad * VD.PrecioUnitario, 6) - VD.Descuento) AS BaseIVA, + CONVERT(decimal(19, 6), ISNULL(PS.IVA, 0) / 100.0) AS TasaIVA, + CONVERT(decimal(19, 6), VD.IVA) AS ImporteIVA + FROM dbo.VentasDetalle AS VD + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = VD.CvePS + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = PS.CveUnidadMedida + LEFT JOIN dbo.Gral_SAT_ProductosServicios AS SATPS + ON SATPS.CveSATPS = PS.CveSATPS + LEFT JOIN dbo.Gral_SAT_UnidadesMedida AS SATUM + ON SATUM.CveSATUnidadMedida = UM.CveSATUnidadMedida + LEFT JOIN dbo.Gral_SAT_ObjetoImpuesto AS OI + ON OI.CveObjetoImpuesto = PS.CveObjetoImpuesto + WHERE VD.CveVenta = @CveVenta + ORDER BY VD.CveVentaDetalle; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'Ocurrió un error al preparar los datos fiscales de la venta; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteVentaDatosCfdiGet'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteConceptoList + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + + SELECT @CveVenta = SP.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NOT NULL + BEGIN + SELECT + VD.CveVentaDetalle, + CONVERT(int, 0) AS CveTramitePagoDetalle, + VD.CvePS, + UM.CveUnidadMedida AS CveUM, + CASE + WHEN NULLIF(LTRIM(RTRIM(UM.Abreviatura)), '') IS NULL + THEN UM.UnidadMedida COLLATE DATABASE_DEFAULT + ELSE UM.UnidadMedida COLLATE DATABASE_DEFAULT + + ' (' + UM.Abreviatura COLLATE DATABASE_DEFAULT + ')' + END AS UnidadMedida, + C.CveClasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.Codigo)), '') IS NULL + THEN C.Clasificacion COLLATE DATABASE_DEFAULT + ELSE C.Codigo COLLATE DATABASE_DEFAULT + + ' - ' + C.Clasificacion COLLATE DATABASE_DEFAULT + END AS Clasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(PS.Codigo)), '') IS NULL + THEN PS.PS COLLATE DATABASE_DEFAULT + ELSE PS.Codigo COLLATE DATABASE_DEFAULT + + ' - ' + PS.PS COLLATE DATABASE_DEFAULT + END AS ProductoServicio, + VD.Cantidad, + VD.PrecioUnitario, + VD.Descuento, + VD.IVA, + VD.Importe + FROM dbo.VentasDetalle AS VD + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = VD.CvePS + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = PS.CveUnidadMedida + INNER JOIN dbo.Clasificaciones AS C + ON C.CveClasificacion = PS.CveClasificacion + WHERE VD.CveVenta = @CveVenta + ORDER BY VD.CveVentaDetalle; + END + ELSE + BEGIN + SELECT + CONVERT(int, 0) AS CveVentaDetalle, + D.CveTramitePagoDetalle, + D.CvePS, + D.CveUM, + CASE + WHEN NULLIF(LTRIM(RTRIM(UM.Abreviatura)), '') IS NULL + THEN UM.UnidadMedida COLLATE DATABASE_DEFAULT + ELSE UM.UnidadMedida COLLATE DATABASE_DEFAULT + + ' (' + UM.Abreviatura COLLATE DATABASE_DEFAULT + ')' + END AS UnidadMedida, + C.CveClasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.Codigo)), '') IS NULL + THEN C.Clasificacion COLLATE DATABASE_DEFAULT + ELSE C.Codigo COLLATE DATABASE_DEFAULT + + ' - ' + C.Clasificacion COLLATE DATABASE_DEFAULT + END AS Clasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(PS.Codigo)), '') IS NULL + THEN PS.PS COLLATE DATABASE_DEFAULT + ELSE PS.Codigo COLLATE DATABASE_DEFAULT + + ' - ' + PS.PS COLLATE DATABASE_DEFAULT + END AS ProductoServicio, + CONVERT(decimal(18, 4), D.Cantidad) AS Cantidad, + CONVERT(decimal(18, 2), PS.Precio) AS PrecioUnitario, + CONVERT(decimal(18, 2), 0) AS Descuento, + CONVERT(decimal(18, 2), ROUND(D.Cantidad * PS.Precio * ISNULL(PS.IVA, 0) / 100, 2)) AS IVA, + CONVERT(decimal(18, 2), ROUND(D.Cantidad * PS.Precio, 2) + ROUND(D.Cantidad * PS.Precio * ISNULL(PS.IVA, 0) / 100, 2)) AS Importe + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = D.CvePS + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = D.CveUM + INNER JOIN dbo.Clasificaciones AS C + ON C.CveClasificacion = PS.CveClasificacion + WHERE S.CveSolicitud = @CveSolicitud + ORDER BY D.CveTramitePagoDetalle; + END; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los conceptos de la venta; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteConceptoList'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteConceptoSave + @CveSolicitud int, + @CveTramitePago int, + @CveVentaDetalle int = NULL, + @CvePS int, + @Cantidad decimal(18, 4), + @PrecioUnitario decimal(18, 2), + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + DECLARE @PorcentajeIVA decimal(18, 6); + DECLARE @IVA decimal(18, 2); + DECLARE @Importe decimal(18, 2); + + SELECT @CveVenta = V.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT @ErrorMostrar = 'Primero debe generar la venta del trámite.', @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Ventas AS V + WHERE V.CveVenta = @CveVenta + AND V.SeTimbro = 1 + ) + BEGIN + SELECT @ErrorMostrar = 'No se pueden modificar los conceptos de una venta timbrada.', @ErrorTipo = 2; + RETURN; + END; + + SELECT @PorcentajeIVA = CONVERT(decimal(18, 6), ISNULL(IVA, 0)) + FROM dbo.ProductosServicios + WHERE CvePS = @CvePS + AND Estado = 1; + + IF @PorcentajeIVA IS NULL OR @Cantidad <= 0 OR @PrecioUnitario < 0 + BEGIN + SELECT @ErrorMostrar = 'Capture un producto activo, cantidad y precio unitario válidos.', @ErrorTipo = 2; + RETURN; + END; + + SET @IVA = CONVERT(decimal(18, 2), ROUND(@Cantidad * @PrecioUnitario * @PorcentajeIVA / 100, 2)); + SET @Importe = CONVERT(decimal(18, 2), ROUND(@Cantidad * @PrecioUnitario, 2) + @IVA); + + IF @CveVentaDetalle IS NULL + BEGIN + INSERT INTO dbo.VentasDetalle + ( + CveVenta, + CvePS, + CveSolicitud, + CveCostoTramite, + Cantidad, + PrecioUnitario, + Descuento, + IVA, + Importe, + EsFondoInicial, + FechaAlta, + CveUsuario + ) + VALUES + ( + @CveVenta, + @CvePS, + @CveSolicitud, + NULL, + @Cantidad, + @PrecioUnitario, + 0, + @IVA, + @Importe, + 0, + GETDATE(), + @CveUsuarioEjecuta + ); + + SET @CveVentaDetalle = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.VentasDetalle + WHERE CveVentaDetalle = @CveVentaDetalle + AND CveVenta = @CveVenta + ) + BEGIN + SELECT @ErrorMostrar = 'El concepto seleccionado no pertenece a la venta.', @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.VentasDetalle + SET + CvePS = @CvePS, + Cantidad = @Cantidad, + PrecioUnitario = @PrecioUnitario, + IVA = @IVA, + Importe = @Importe, + CveUsuario = @CveUsuarioEjecuta + WHERE CveVentaDetalle = @CveVentaDetalle; + END; + + EXEC dbo.PA_Vta_TramiteVentaTotalesUpdate + @CveVenta = @CveVenta, + @CveUsuarioEjecuta = @CveUsuarioEjecuta, + @ErrorMostrar = @ErrorMostrar OUTPUT, + @ErrorTipo = @ErrorTipo OUTPUT, + @Return = @Return OUTPUT; + + IF @Return = 0 + RETURN; + + SELECT @CveVentaDetalle AS CveVentaDetalle; + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT @ErrorMostrar = 'Ocurrió un error al guardar el concepto de la venta; favor de contactar a Sistemas.', @ErrorTipo = 1, @Return = 0; + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT('Número: ', ERROR_NUMBER(), '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Vta_TramiteConceptoSave'), '; Línea: ', ERROR_LINE(), '; Detalle: ', ERROR_MESSAGE()); + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO diff --git a/Fraccionamientos_Ventas_Flujo_Generar_Pagar_20260827.sql b/Fraccionamientos_Ventas_Flujo_Generar_Pagar_20260827.sql new file mode 100644 index 0000000..62413b1 --- /dev/null +++ b/Fraccionamientos_Ventas_Flujo_Generar_Pagar_20260827.sql @@ -0,0 +1,718 @@ +SET ANSI_NULLS ON; +SET QUOTED_IDENTIFIER ON; +SET NOCOUNT ON; +GO + +UPDATE dbo.Vta_TipoDocumentos +SET TipoDocumento = N'Remisión' +WHERE CveTipoDocumento = 'Rem' + AND TipoDocumento <> N'Remisión'; +GO + +DECLARE @CveUsuarioSistema int = +( + SELECT TOP (1) + CveUsuario + FROM dbo.Sis_Usuarios + WHERE Activo = 1 + ORDER BY CveUsuario +); + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.Vta_FormaPago + WHERE CveFormaPago = 99 +) +BEGIN + INSERT INTO dbo.Vta_FormaPago + ( + CveFormaPago, + FormaPago, + ClaveFormaPagoSAT, + CveUsuario, + FechaIng + ) + VALUES + ( + 99, + 'Por definir', + '99', + @CveUsuarioSistema, + CONVERT(date, GETDATE()) + ); +END; + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.Vta_MetodoPago + WHERE CveMetodoPago = 2 +) +BEGIN + INSERT INTO dbo.Vta_MetodoPago + ( + CveMetodoPago, + MetodoPago, + ClaveMetodoPagoSAT, + CveUsuario, + FechaIng + ) + VALUES + ( + 2, + 'Pago en parcialidades o diferido', + 'PPD', + @CveUsuarioSistema, + CONVERT(date, GETDATE()) + ); +END; +GO + +IF NOT EXISTS +( + SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID('dbo.Vta_Pagos') + AND name = 'UX_Vta_Pagos_SolicitudTramitePagoActivo' +) +BEGIN + CREATE UNIQUE NONCLUSTERED INDEX UX_Vta_Pagos_SolicitudTramitePagoActivo + ON dbo.Vta_Pagos + ( + CveSolicitud, + CveTramitePago + ) + WHERE EsActivo = 1 + AND CveSolicitud IS NOT NULL; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_FraccionamientoPagoPendienteList + @CveFraccionamiento int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fraccionamientos + WHERE CveFraccionamiento = @CveFraccionamiento + ) + BEGIN + SELECT + @ErrorMostrar = 'El fraccionamiento solicitado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + ;WITH Conceptos AS + ( + SELECT + S.CveSolicitud, + P.CveTramitePago, + COUNT_BIG(*) AS NumeroConceptos, + SUM( + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio), + 2 + ) + ) AS SubTotal, + SUM( + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ) AS IVA + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = D.CvePS + WHERE S.CveFraccionamiento = @CveFraccionamiento + GROUP BY + S.CveSolicitud, + P.CveTramitePago + ) + SELECT + S.CveSolicitud, + P.CveTramitePago, + SP.CveVenta, + CONVERT( + bit, + CASE + WHEN SP.CveSolicitudPago IS NOT NULL + AND V.CveVenta IS NOT NULL THEN 1 + ELSE 0 + END + ) AS VentaGenerada, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + CONVERT(int, C.NumeroConceptos) AS NumeroConceptos, + CONVERT( + decimal(18, 2), + CASE + WHEN V.CveVenta IS NULL THEN C.SubTotal + ELSE V.SubTotal + END + ) AS SubTotal, + CONVERT( + decimal(18, 2), + CASE + WHEN V.CveVenta IS NULL THEN C.IVA + ELSE V.IVA + END + ) AS IVA, + CONVERT( + decimal(18, 2), + CASE + WHEN V.CveVenta IS NULL THEN C.SubTotal + C.IVA + ELSE V.Total + END + ) AS Total + FROM Conceptos AS C + INNER JOIN dbo.Tra_Solicitudes AS S + ON S.CveSolicitud = C.CveSolicitud + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = C.CveTramitePago + LEFT JOIN dbo.Tra_SolicitudesPagos AS SP + ON SP.CveSolicitud = S.CveSolicitud + AND SP.CveTramitePago = P.CveTramitePago + LEFT JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE NOT EXISTS + ( + SELECT 1 + FROM dbo.Vta_Pagos AS VP + WHERE VP.CveSolicitud = S.CveSolicitud + AND VP.CveTramitePago = P.CveTramitePago + AND VP.CveVenta = SP.CveVenta + AND VP.EsActivo = 1 + ) + ORDER BY + E.Orden, + S.CveSolicitud, + P.Orden, + P.CveTramitePago; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los pagos pendientes; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_FraccionamientoPagoPendienteList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_FraccionamientoPagoRealizadoList + @CveFraccionamiento int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fraccionamientos + WHERE CveFraccionamiento = @CveFraccionamiento + ) + BEGIN + SELECT + @ErrorMostrar = 'El fraccionamiento solicitado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + SP.CveSolicitudPago, + SP.CveSolicitud, + SP.CveTramitePago, + V.CveVenta, + VP.CvePago, + V.SerieFolio, + V.Fecha, + VP.FechaPago, + VP.Referencia, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + CONVERT(decimal(18, 2), V.SubTotal) AS SubTotal, + CONVERT(decimal(18, 2), V.IVA) AS IVA, + CONVERT(decimal(18, 2), VP.Importe) AS Total + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Tra_Solicitudes AS S + ON S.CveSolicitud = SP.CveSolicitud + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = SP.CveTramitePago + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + INNER JOIN dbo.Vta_Pagos AS VP + ON VP.CveVenta = V.CveVenta + AND VP.CveSolicitud = SP.CveSolicitud + AND VP.CveTramitePago = SP.CveTramitePago + AND VP.EsActivo = 1 + WHERE S.CveFraccionamiento = @CveFraccionamiento + ORDER BY + VP.FechaPago DESC, + VP.CvePago DESC; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los pagos realizados; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_FraccionamientoPagoRealizadoList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteContextoGet + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE @CveSubProyecto int = + ( + SELECT TOP (1) + CveSubProyecto + FROM dbo.SubProyectos + WHERE Estatus = 1 + ORDER BY + CASE WHEN Serie = 'TRA' THEN 0 ELSE 1 END, + CveSubProyecto + ); + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + WHERE S.CveSolicitud = @CveSolicitud + ) + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado no corresponde al trámite o no tiene conceptos activos.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + S.CveSolicitud, + P.CveTramitePago, + SP.CveVenta, + VP.CvePago, + CONVERT( + bit, + CASE + WHEN SP.CveSolicitudPago IS NOT NULL + AND V.CveVenta IS NOT NULL THEN 1 + ELSE 0 + END + ) AS VentaGenerada, + CONVERT( + bit, + CASE + WHEN VP.Autorizado = 1 THEN 1 + ELSE 0 + END + ) AS VentaPagada, + CONVERT( + bit, + CASE + WHEN VP.CvePago IS NOT NULL + AND VP.Autorizado = 0 + THEN 1 + ELSE 0 + END + ) AS PagoPendienteAutorizacion, + VP.Referencia AS ReferenciaPago, + S.CveFraccionamiento, + F.Fraccionamiento, + F.CveCliente, + C.Nombre AS Cliente, + C.RFC, + CONCAT( + C.Direccion, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.NoExt)), '') IS NULL THEN '' + ELSE CONCAT(' ', C.NoExt) + END, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.NoInt)), '') IS NULL THEN '' + ELSE CONCAT(' Int. ', C.NoInt) + END + ) AS Direccion, + C.Colonia, + CONCAT(C.Ciudad, ', ', C.Estado) AS CiudadEstado, + C.CP, + C.Telefono, + C.Mail, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + N'Remisión' AS TipoDocumento, + ISNULL(V.Serie, 'TRA') AS Serie, + ISNULL( + V.Folio, + ISNULL( + ( + SELECT MAX(Venta.Folio) + 1 + FROM dbo.Ventas AS Venta + WHERE Venta.TipoDocto = 'Rem' + AND Venta.Serie = 'TRA' + AND Venta.CveSubProyecto = @CveSubProyecto + ), + 1 + ) + ) AS Folio, + ISNULL(V.Fecha, GETDATE()) AS Fecha, + ISNULL(V.CveMetodoPago33, ISNULL(V.CveMetodoPago, 2)) + AS CveMetodoPago, + ISNULL(V.CveFormaPago33, ISNULL(V.FormaPago, 99)) + AS CveFormaPago, + V.FechaVencimiento2 AS FechaVencimiento + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Fraccionamientos AS F + ON F.CveFraccionamiento = S.CveFraccionamiento + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = F.CveCliente + LEFT JOIN dbo.Tra_SolicitudesPagos AS SP + ON SP.CveSolicitud = S.CveSolicitud + AND SP.CveTramitePago = P.CveTramitePago + LEFT JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + OUTER APPLY + ( + SELECT TOP (1) + Pago.CvePago, + Pago.Autorizado, + Pago.Referencia + FROM dbo.Vta_Pagos AS Pago + WHERE Pago.CveVenta = V.CveVenta + AND Pago.CveSolicitud = S.CveSolicitud + AND Pago.CveTramitePago = P.CveTramitePago + AND Pago.EsActivo = 1 + ORDER BY Pago.CvePago DESC + ) AS VP + WHERE S.CveSolicitud = @CveSolicitud; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar la venta del trámite; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteContextoGet' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramitePagoSave + @CveSolicitud int, + @CveTramitePago int, + @Referencia varchar(200) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE + @CveVenta int, + @CveCliente int, + @Importe decimal(18, 2), + @CvePago int, + @FechaPago datetime = GETDATE(); + + SELECT + @CveVenta = V.CveVenta, + @CveCliente = V.CveCliente, + @Importe = CONVERT(decimal(18, 2), V.Total) + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Primero debe generar la venta del trámite.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Vta_Pagos WITH (UPDLOCK, HOLDLOCK) + WHERE CveSolicitud = @CveSolicitud + AND CveTramitePago = @CveTramitePago + AND CveVenta = @CveVenta + AND EsActivo = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'La venta del trámite ya se encuentra pagada.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Vta_FormaPago + WHERE CveFormaPago = 99 + ) + BEGIN + SELECT + @ErrorMostrar = 'La forma de pago por definir no está configurada; favor de contactar a Sistemas.', + @ErrorTipo = 2; + RETURN; + END; + + INSERT INTO dbo.Vta_Pagos + ( + CveCliente, + CveVenta, + CveSolicitud, + CveFormaPago, + CveMoneda, + CvePrePoliza, + FechaPago, + Importe, + Referencia, + EsSaldoFavor, + EsActivo, + FechaAlta, + CveUsuario, + CveTramitePago + ) + VALUES + ( + @CveCliente, + @CveVenta, + @CveSolicitud, + 99, + 1, + NULL, + @FechaPago, + @Importe, + NULLIF(LTRIM(RTRIM(@Referencia)), ''), + 0, + 1, + @FechaPago, + @CveUsuarioEjecuta, + @CveTramitePago + ); + + SET @CvePago = CONVERT(int, SCOPE_IDENTITY()); + + UPDATE dbo.Ventas + SET + CveMetodoPago = 2, + FormaPago = 99, + CveFormaPago33 = 99, + CveMetodoPago33 = 2, + FechaCobranza = @FechaPago, + CveUsuarioCobranza = @CveUsuarioEjecuta + WHERE CveVenta = @CveVenta; + + SELECT @CvePago AS CvePago; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al registrar el pago de la venta; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramitePagoSave' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaGenerar + @CveSolicitud int, + @CveTramitePago int, + @Observaciones varchar(2000) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF EXISTS + ( + SELECT 1 + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago + ) + BEGIN + SELECT + @ErrorMostrar = 'La venta del trámite ya fue generada.', + @ErrorTipo = 2; + RETURN; + END; + + EXEC dbo.PA_Vta_TramiteVentaSave + @CveSolicitud = @CveSolicitud, + @CveTramitePago = @CveTramitePago, + @Observaciones = @Observaciones, + @CveUsuarioEjecuta = @CveUsuarioEjecuta, + @ErrorMostrar = @ErrorMostrar OUTPUT, + @ErrorTipo = @ErrorTipo OUTPUT, + @Return = @Return OUTPUT; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al generar la venta del trámite; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteVentaGenerar' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO diff --git a/Fraccionamientos_Ventas_Pago_Captura_20260828.sql b/Fraccionamientos_Ventas_Pago_Captura_20260828.sql new file mode 100644 index 0000000..97e5e07 --- /dev/null +++ b/Fraccionamientos_Ventas_Pago_Captura_20260828.sql @@ -0,0 +1,826 @@ +SET NOCOUNT ON; +GO + +DECLARE @CveUsuarioCatalogoPago int = +( + SELECT TOP (1) CveUsuario + FROM dbo.Sis_Usuarios + WHERE Activo = 1 + ORDER BY CveUsuario +); + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.Vta_FormaPago + WHERE ClaveFormaPagoSAT = '01' +) +BEGIN + INSERT INTO dbo.Vta_FormaPago + ( + CveFormaPago, + FormaPago, + ClaveFormaPagoSAT, + CveUsuario, + FechaIng + ) + VALUES + ( + 1, + 'Efectivo', + '01', + @CveUsuarioCatalogoPago, + CONVERT(date, GETDATE()) + ); +END; + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.Vta_FormaPago + WHERE ClaveFormaPagoSAT = '03' +) +BEGIN + INSERT INTO dbo.Vta_FormaPago + ( + CveFormaPago, + FormaPago, + ClaveFormaPagoSAT, + CveUsuario, + FechaIng + ) + VALUES + ( + 3, + 'Transferencia electrónica de fondos', + '03', + @CveUsuarioCatalogoPago, + CONVERT(date, GETDATE()) + ); +END; + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.Vta_FormaPago + WHERE ClaveFormaPagoSAT = '04' +) +BEGIN + INSERT INTO dbo.Vta_FormaPago + ( + CveFormaPago, + FormaPago, + ClaveFormaPagoSAT, + CveUsuario, + FechaIng + ) + VALUES + ( + 4, + 'Tarjeta de crédito', + '04', + @CveUsuarioCatalogoPago, + CONVERT(date, GETDATE()) + ); +END; +GO + +UPDATE V +SET + CveMetodoPago = ISNULL(V.CveMetodoPago, 2), + CveMetodoPago33 = ISNULL(V.CveMetodoPago33, 2), + FormaPago = ISNULL(V.FormaPago, 99), + CveFormaPago33 = ISNULL(V.CveFormaPago33, 99), + FechaVencimiento2 = ISNULL( + V.FechaVencimiento2, + CONVERT(date, V.Fecha) + ) +FROM dbo.Ventas AS V +INNER JOIN dbo.Tra_SolicitudesPagos AS SP + ON SP.CveVenta = V.CveVenta +WHERE V.CveMetodoPago IS NULL + OR V.CveMetodoPago33 IS NULL + OR V.FormaPago IS NULL + OR V.CveFormaPago33 IS NULL + OR V.FechaVencimiento2 IS NULL; +GO + +IF COL_LENGTH('dbo.Vta_Pagos', 'CveBancoCuenta') IS NULL +BEGIN + ALTER TABLE dbo.Vta_Pagos + ADD CveBancoCuenta int NULL; +END; +GO + +IF COL_LENGTH('dbo.Vta_Pagos', 'Observaciones') IS NULL +BEGIN + ALTER TABLE dbo.Vta_Pagos + ADD Observaciones varchar(300) COLLATE Modern_Spanish_CS_AS NULL; +END; +GO + +IF COL_LENGTH('dbo.Vta_Pagos', 'Autorizado') IS NULL +BEGIN + ALTER TABLE dbo.Vta_Pagos + ADD Autorizado bit NOT NULL + CONSTRAINT DF_Vta_Pagos_Autorizado DEFAULT (0) WITH VALUES; +END; +GO + +IF COL_LENGTH('dbo.Vta_Pagos', 'FechaAutorizacion') IS NULL +BEGIN + ALTER TABLE dbo.Vta_Pagos + ADD FechaAutorizacion datetime NULL; +END; +GO + +IF COL_LENGTH('dbo.Vta_Pagos', 'CveUsuarioAutoriza') IS NULL +BEGIN + ALTER TABLE dbo.Vta_Pagos + ADD CveUsuarioAutoriza int NULL; +END; +GO + +IF NOT EXISTS +( + SELECT 1 + FROM sys.foreign_keys + WHERE parent_object_id = OBJECT_ID('dbo.Vta_Pagos') + AND name = 'FK_Vta_Pagos_Banc_BancosCuentas' +) +BEGIN + ALTER TABLE dbo.Vta_Pagos WITH CHECK + ADD CONSTRAINT FK_Vta_Pagos_Banc_BancosCuentas + FOREIGN KEY (CveBancoCuenta) + REFERENCES dbo.Banc_BancosCuentas (CveBancoCuenta); + + ALTER TABLE dbo.Vta_Pagos + CHECK CONSTRAINT FK_Vta_Pagos_Banc_BancosCuentas; +END; +GO + +IF NOT EXISTS +( + SELECT 1 + FROM sys.foreign_keys + WHERE parent_object_id = OBJECT_ID('dbo.Vta_Pagos') + AND name = 'FK_Vta_Pagos_Sis_Usuarios_Autoriza' +) +BEGIN + ALTER TABLE dbo.Vta_Pagos WITH CHECK + ADD CONSTRAINT FK_Vta_Pagos_Sis_Usuarios_Autoriza + FOREIGN KEY (CveUsuarioAutoriza) + REFERENCES dbo.Sis_Usuarios (CveUsuario); + + ALTER TABLE dbo.Vta_Pagos + CHECK CONSTRAINT FK_Vta_Pagos_Sis_Usuarios_Autoriza; +END; +GO + +IF NOT EXISTS +( + SELECT 1 + FROM sys.check_constraints + WHERE parent_object_id = OBJECT_ID('dbo.Vta_Pagos') + AND name = 'CK_Vta_Pagos_Autorizacion' +) +BEGIN + ALTER TABLE dbo.Vta_Pagos WITH CHECK + ADD CONSTRAINT CK_Vta_Pagos_Autorizacion + CHECK + ( + ( + Autorizado = 0 + AND FechaAutorizacion IS NULL + AND CveUsuarioAutoriza IS NULL + ) + OR + ( + Autorizado = 1 + AND FechaAutorizacion IS NOT NULL + AND CveUsuarioAutoriza IS NOT NULL + ) + ); + + ALTER TABLE dbo.Vta_Pagos + CHECK CONSTRAINT CK_Vta_Pagos_Autorizacion; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramitePagoOpcionesList + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + + SELECT @CveVenta = V.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Primero debe generar la venta del trámite.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + @CveVenta AS CveVenta, + CONCAT( + 'TRA-', + RIGHT( + REPLICATE('0', 10) + + CONVERT(varchar(10), @CveVenta), + 10 + ) + ) AS ReferenciaPago; + + SELECT + FP.CveFormaPago, + FP.ClaveFormaPagoSAT, + CASE + WHEN NULLIF(LTRIM(RTRIM(FP.ClaveFormaPagoSAT)), '') IS NULL + THEN FP.FormaPago + ELSE + FP.ClaveFormaPagoSAT COLLATE Modern_Spanish_CS_AS + + ' - ' + + FP.FormaPago COLLATE Modern_Spanish_CS_AS + END AS FormaPago, + CONVERT( + bit, + CASE + WHEN FP.ClaveFormaPagoSAT = '04' THEN 0 + ELSE 1 + END + ) AS Disponible + FROM dbo.Vta_FormaPago AS FP + WHERE FP.ClaveFormaPagoSAT IN ('01', '03', '04') + ORDER BY + FP.ClaveFormaPagoSAT COLLATE Modern_Spanish_CS_AS, + FP.FormaPago COLLATE Modern_Spanish_CS_AS, + FP.CveFormaPago; + + SELECT + BC.CveBancoCuenta, + B.Banco, + BC.NumCuenta AS NumeroCuenta, + BC.CLABE, + B.Banco COLLATE Modern_Spanish_CS_AS + + ' - ' + + BC.NumCuenta COLLATE Modern_Spanish_CS_AS + + CASE + WHEN NULLIF(LTRIM(RTRIM(BC.CLABE)), '') IS NULL + THEN '' + ELSE + ' (CLABE ' + + BC.CLABE COLLATE Modern_Spanish_CS_AS + + ')' + END AS CuentaBancaria + FROM dbo.Banc_BancosCuentas AS BC + INNER JOIN dbo.Banc_Bancos AS B + ON B.CveBanco = BC.CveBanco + WHERE BC.Estatus = 1 + AND B.Estatus = 1 + AND NULLIF(LTRIM(RTRIM(BC.CLABE)), '') IS NOT NULL + ORDER BY + B.Banco COLLATE Modern_Spanish_CS_AS, + BC.NumCuenta COLLATE Modern_Spanish_CS_AS, + BC.CveBancoCuenta; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar las opciones de pago; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramitePagoOpcionesList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramitePagoSave + @CveSolicitud int, + @CveTramitePago int, + @Importe decimal(18, 2), + @FechaPago datetime, + @CveFormaPago tinyint, + @CveBancoCuenta int = NULL, + @Observaciones varchar(300) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE + @CveVenta int, + @CveCliente int, + @TotalVenta decimal(18, 2), + @CvePago int, + @ClaveFormaPagoSAT varchar(2), + @Referencia varchar(200); + + SELECT + @CveVenta = V.CveVenta, + @CveCliente = V.CveCliente, + @TotalVenta = CONVERT(decimal(18, 2), V.Total) + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Primero debe generar la venta del trámite.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Vta_Pagos WITH (UPDLOCK, HOLDLOCK) + WHERE CveSolicitud = @CveSolicitud + AND CveTramitePago = @CveTramitePago + AND CveVenta = @CveVenta + AND EsActivo = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'Ya existe una solicitud de pago activa para esta venta.', + @ErrorTipo = 2; + RETURN; + END; + + IF @Importe IS NULL OR @Importe <= 0 + BEGIN + SELECT + @ErrorMostrar = 'Capture un monto de pago mayor que cero.', + @ErrorTipo = 2; + RETURN; + END; + + IF @Importe <> @TotalVenta + BEGIN + SELECT + @ErrorMostrar = CONCAT( + 'El pago debe cubrir el saldo completo de ', + FORMAT(@TotalVenta, 'C', 'es-MX'), + '.' + ), + @ErrorTipo = 2; + RETURN; + END; + + IF @FechaPago IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture la fecha del pago.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT @ClaveFormaPagoSAT = ClaveFormaPagoSAT + FROM dbo.Vta_FormaPago + WHERE CveFormaPago = @CveFormaPago; + + IF @ClaveFormaPagoSAT IS NULL + OR @ClaveFormaPagoSAT NOT IN ('01', '03', '04') + BEGIN + SELECT + @ErrorMostrar = 'Seleccione una forma de pago válida.', + @ErrorTipo = 2; + RETURN; + END; + + IF @ClaveFormaPagoSAT = '04' + BEGIN + SELECT + @ErrorMostrar = 'El pago con tarjeta todavía no está disponible.', + @ErrorTipo = 2; + RETURN; + END; + + IF @ClaveFormaPagoSAT = '03' + AND @CveBancoCuenta IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Seleccione la cuenta SPEI donde se recibirá la transferencia.', + @ErrorTipo = 2; + RETURN; + END; + + IF @ClaveFormaPagoSAT = '01' + BEGIN + SET @CveBancoCuenta = NULL; + END; + + IF @CveBancoCuenta IS NOT NULL + AND NOT EXISTS + ( + SELECT 1 + FROM dbo.Banc_BancosCuentas AS BC + INNER JOIN dbo.Banc_Bancos AS B + ON B.CveBanco = BC.CveBanco + WHERE BC.CveBancoCuenta = @CveBancoCuenta + AND BC.Estatus = 1 + AND B.Estatus = 1 + AND NULLIF(LTRIM(RTRIM(BC.CLABE)), '') IS NOT NULL + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione una cuenta bancaria activa.', + @ErrorTipo = 2; + RETURN; + END; + + SET @Referencia = CONCAT( + 'TRA-', + RIGHT( + REPLICATE('0', 10) + + CONVERT(varchar(10), @CveVenta), + 10 + ) + ); + + INSERT INTO dbo.Vta_Pagos + ( + CveCliente, + CveVenta, + CveSolicitud, + CveFormaPago, + CveMoneda, + CvePrePoliza, + FechaPago, + Importe, + Referencia, + EsSaldoFavor, + EsActivo, + FechaAlta, + CveUsuario, + CveTramitePago, + CveBancoCuenta, + Observaciones, + Autorizado, + FechaAutorizacion, + CveUsuarioAutoriza + ) + VALUES + ( + @CveCliente, + @CveVenta, + @CveSolicitud, + @CveFormaPago, + 1, + NULL, + @FechaPago, + @Importe, + @Referencia, + 0, + 1, + GETDATE(), + @CveUsuarioEjecuta, + @CveTramitePago, + @CveBancoCuenta, + NULLIF(LTRIM(RTRIM(@Observaciones)), ''), + 0, + NULL, + NULL + ); + + SET @CvePago = CONVERT(int, SCOPE_IDENTITY()); + + SELECT + @CvePago AS CvePago, + @Referencia AS Referencia, + CONVERT(bit, 0) AS Autorizado; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al registrar el pago de la venta; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramitePagoSave' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteCondicionesPagoOpcionesList + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SELECT + MP.CveMetodoPago, + MP.MetodoPago, + MP.ClaveMetodoPagoSAT, + MP.ClaveMetodoPagoSAT COLLATE Modern_Spanish_CS_AS + + ' - ' + + MP.MetodoPago COLLATE Modern_Spanish_CS_AS AS Descripcion + FROM dbo.Vta_MetodoPago AS MP + ORDER BY MP.ClaveMetodoPagoSAT, MP.CveMetodoPago; + + SELECT + FP.CveFormaPago, + FP.ClaveFormaPagoSAT, + FP.ClaveFormaPagoSAT COLLATE Modern_Spanish_CS_AS + + ' - ' + + FP.FormaPago COLLATE Modern_Spanish_CS_AS AS FormaPago, + CONVERT(bit, 1) AS Disponible + FROM dbo.Vta_FormaPago AS FP + ORDER BY FP.ClaveFormaPagoSAT, FP.CveFormaPago; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar las condiciones de pago; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteCondicionesPagoOpcionesList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteCondicionesPagoSave + @CveSolicitud int, + @CveTramitePago int, + @CveMetodoPago int, + @CveFormaPago tinyint, + @FechaVencimiento date, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE @CveVenta int; + + SELECT @CveVenta = V.CveVenta + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE SP.CveSolicitud = @CveSolicitud + AND SP.CveTramitePago = @CveTramitePago; + + IF @CveVenta IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Primero debe generar la venta del trámite.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Ventas + WHERE CveVenta = @CveVenta + AND SeTimbro = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'Las condiciones de una venta timbrada no se pueden modificar.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Vta_MetodoPago + WHERE CveMetodoPago = @CveMetodoPago + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione un método de pago válido.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Vta_FormaPago + WHERE CveFormaPago = @CveFormaPago + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione una forma de pago válida.', + @ErrorTipo = 2; + RETURN; + END; + + IF @FechaVencimiento IS NULL + BEGIN + SELECT + @ErrorMostrar = 'Capture una fecha de vencimiento válida.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Ventas + SET + CveMetodoPago = @CveMetodoPago, + CveMetodoPago33 = @CveMetodoPago, + FormaPago = @CveFormaPago, + CveFormaPago33 = @CveFormaPago, + FechaVencimiento2 = @FechaVencimiento, + CveUsuarioModifico = @CveUsuarioEjecuta + WHERE CveVenta = @CveVenta; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al actualizar las condiciones de pago; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteCondicionesPagoSave' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_FraccionamientoPagoRealizadoList + @CveFraccionamiento int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fraccionamientos + WHERE CveFraccionamiento = @CveFraccionamiento + ) + BEGIN + SELECT + @ErrorMostrar = 'El fraccionamiento solicitado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + SP.CveSolicitudPago, + SP.CveSolicitud, + SP.CveTramitePago, + V.CveVenta, + VP.CvePago, + V.SerieFolio, + V.Fecha, + VP.FechaPago, + VP.Referencia, + VP.Autorizado, + VP.FechaAutorizacion, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + CONVERT(decimal(18, 2), V.SubTotal) AS SubTotal, + CONVERT(decimal(18, 2), V.IVA) AS IVA, + CONVERT(decimal(18, 2), VP.Importe) AS Total + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Tra_Solicitudes AS S + ON S.CveSolicitud = SP.CveSolicitud + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = SP.CveTramitePago + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + INNER JOIN dbo.Vta_Pagos AS VP + ON VP.CveVenta = V.CveVenta + AND VP.CveSolicitud = SP.CveSolicitud + AND VP.CveTramitePago = SP.CveTramitePago + AND VP.EsActivo = 1 + WHERE S.CveFraccionamiento = @CveFraccionamiento + ORDER BY + VP.FechaPago DESC, + VP.CvePago DESC; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los pagos realizados; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_FraccionamientoPagoRealizadoList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO diff --git a/Fraccionamientos_Ventas_Tramites_20260827.sql b/Fraccionamientos_Ventas_Tramites_20260827.sql new file mode 100644 index 0000000..e773e19 --- /dev/null +++ b/Fraccionamientos_Ventas_Tramites_20260827.sql @@ -0,0 +1,1013 @@ +SET NOCOUNT ON; +GO + +DECLARE @CveUsuarioSistema int = +( + SELECT TOP (1) + CveUsuario + FROM dbo.Sis_Usuarios + WHERE Activo = 1 + ORDER BY CveUsuario +); + +IF @CveUsuarioSistema IS NULL +BEGIN + RAISERROR( + 'No existe un usuario activo para inicializar los catálogos de ventas.', + 16, + 1 + ); + RETURN; +END; + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.Vta_TipoDocumentos + WHERE CveTipoDocumento = 'Rem' +) +BEGIN + INSERT INTO dbo.Vta_TipoDocumentos + ( + CveTipoDocumento, + TipoDocumento, + Estatus, + FechaIng, + Multiplicador, + Contable + ) + VALUES + ( + 'Rem', + 'Remisión', + 1, + CONVERT(date, GETDATE()), + 1, + 0 + ); +END; + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.EstatusFactura + WHERE TipoDocto = 'Rem' + AND Estado = 1 +) +BEGIN + DECLARE @CveEstatusFacturaInicial int = + CASE + WHEN NOT EXISTS + ( + SELECT 1 + FROM dbo.EstatusFactura + WHERE CveEstatusFactura = 2 + ) THEN 2 + ELSE ISNULL( + ( + SELECT MAX(CveEstatusFactura) + 1 + FROM dbo.EstatusFactura + ), + 1 + ) + END; + + INSERT INTO dbo.EstatusFactura + ( + CveEstatusFactura, + EstatusFactura, + Estado, + Fecha, + CveUsuario, + TipoDocto, + TipoEstatus, + Origen, + EnProcesoCancelacion + ) + VALUES + ( + @CveEstatusFacturaInicial, + 'Pendiente', + 1, + CONVERT(date, GETDATE()), + @CveUsuarioSistema, + 'Rem', + 1, + 1, + 0 + ); +END; + +DECLARE @CveProyectoVentas int; + +SELECT + @CveProyectoVentas = CveProyecto +FROM dbo.Proyectos +WHERE Proyecto = 'Plataforma de Desarrolladores'; + +IF @CveProyectoVentas IS NULL +BEGIN + INSERT INTO dbo.Proyectos + ( + Proyecto, + Estatus, + FechaIng, + CveUsuario, + CveTipoNomina + ) + VALUES + ( + 'Plataforma de Desarrolladores', + 1, + CONVERT(date, GETDATE()), + @CveUsuarioSistema, + 0 + ); + + SET @CveProyectoVentas = CONVERT(int, SCOPE_IDENTITY()); +END; + +IF NOT EXISTS +( + SELECT 1 + FROM dbo.SubProyectos + WHERE CveProyecto = @CveProyectoVentas + AND SubProyecto = 'Matriz' +) +BEGIN + INSERT INTO dbo.SubProyectos + ( + CveProyecto, + ClaveSubProyecto, + SubProyecto, + Estatus, + FechaIng, + CveUsuario, + Serie, + EsSucursal + ) + VALUES + ( + @CveProyectoVentas, + 'MAT', + 'Matriz', + 1, + CONVERT(date, GETDATE()), + @CveUsuarioSistema, + 'TRA', + 1 + ); +END; +GO + +IF OBJECT_ID('dbo.Tra_SolicitudesPagos', 'U') IS NULL +BEGIN + CREATE TABLE dbo.Tra_SolicitudesPagos + ( + CveSolicitudPago int IDENTITY(1, 1) NOT NULL, + CveSolicitud int NOT NULL, + CveTramitePago int NOT NULL, + CveVenta int NOT NULL, + FechaAlta datetime NOT NULL + CONSTRAINT DF_Tra_SolicitudesPagos_FechaAlta + DEFAULT (GETDATE()), + CveUsuario int NOT NULL, + CONSTRAINT PK_Tra_SolicitudesPagos + PRIMARY KEY CLUSTERED (CveSolicitudPago), + CONSTRAINT UQ_Tra_SolicitudesPagos_SolicitudPago + UNIQUE (CveSolicitud, CveTramitePago), + CONSTRAINT UQ_Tra_SolicitudesPagos_Venta + UNIQUE (CveVenta), + CONSTRAINT FK_Tra_SolicitudesPagos_Tra_Solicitudes + FOREIGN KEY (CveSolicitud) + REFERENCES dbo.Tra_Solicitudes (CveSolicitud), + CONSTRAINT FK_Tra_SolicitudesPagos_Tra_Pagos + FOREIGN KEY (CveTramitePago) + REFERENCES dbo.Tra_Pagos (CveTramitePago), + CONSTRAINT FK_Tra_SolicitudesPagos_Ventas + FOREIGN KEY (CveVenta) + REFERENCES dbo.Ventas (CveVenta), + CONSTRAINT FK_Tra_SolicitudesPagos_Sis_Usuarios + FOREIGN KEY (CveUsuario) + REFERENCES dbo.Sis_Usuarios (CveUsuario) + ); + + CREATE NONCLUSTERED INDEX IX_Tra_SolicitudesPagos_Solicitud + ON dbo.Tra_SolicitudesPagos (CveSolicitud) + INCLUDE (CveTramitePago, CveVenta, FechaAlta); +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_FraccionamientoPagoPendienteList + @CveFraccionamiento int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fraccionamientos + WHERE CveFraccionamiento = @CveFraccionamiento + ) + BEGIN + SELECT + @ErrorMostrar = 'El fraccionamiento solicitado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + ;WITH Conceptos AS + ( + SELECT + S.CveSolicitud, + P.CveTramitePago, + COUNT_BIG(*) AS NumeroConceptos, + SUM( + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio), + 2 + ) + ) AS SubTotal, + SUM( + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ) AS IVA + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = D.CvePS + WHERE S.CveFraccionamiento = @CveFraccionamiento + AND NOT EXISTS + ( + SELECT 1 + FROM dbo.Tra_SolicitudesPagos AS SP + WHERE SP.CveSolicitud = S.CveSolicitud + AND SP.CveTramitePago = P.CveTramitePago + ) + GROUP BY + S.CveSolicitud, + P.CveTramitePago + ) + SELECT + S.CveSolicitud, + P.CveTramitePago, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + CONVERT(int, C.NumeroConceptos) AS NumeroConceptos, + CONVERT(decimal(18, 2), C.SubTotal) AS SubTotal, + CONVERT(decimal(18, 2), C.IVA) AS IVA, + CONVERT(decimal(18, 2), C.SubTotal + C.IVA) AS Total + FROM Conceptos AS C + INNER JOIN dbo.Tra_Solicitudes AS S + ON S.CveSolicitud = C.CveSolicitud + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = C.CveTramitePago + ORDER BY + E.Orden, + S.CveSolicitud, + P.Orden, + P.CveTramitePago; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los pagos pendientes; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_FraccionamientoPagoPendienteList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_FraccionamientoPagoRealizadoList + @CveFraccionamiento int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Fraccionamientos + WHERE CveFraccionamiento = @CveFraccionamiento + ) + BEGIN + SELECT + @ErrorMostrar = 'El fraccionamiento solicitado no existe.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + SP.CveSolicitudPago, + SP.CveSolicitud, + SP.CveTramitePago, + V.CveVenta, + V.SerieFolio, + V.Fecha, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + CONVERT(decimal(18, 2), V.SubTotal) AS SubTotal, + CONVERT(decimal(18, 2), V.IVA) AS IVA, + CONVERT(decimal(18, 2), V.Total) AS Total + FROM dbo.Tra_SolicitudesPagos AS SP + INNER JOIN dbo.Tra_Solicitudes AS S + ON S.CveSolicitud = SP.CveSolicitud + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = SP.CveTramitePago + INNER JOIN dbo.Ventas AS V + ON V.CveVenta = SP.CveVenta + WHERE S.CveFraccionamiento = @CveFraccionamiento + ORDER BY + V.Fecha DESC, + V.CveVenta DESC; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los pagos realizados; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_FraccionamientoPagoRealizadoList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteContextoGet + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE @CveSubProyecto int = + ( + SELECT TOP (1) + CveSubProyecto + FROM dbo.SubProyectos + WHERE Estatus = 1 + ORDER BY + CASE WHEN Serie = 'TRA' THEN 0 ELSE 1 END, + CveSubProyecto + ); + + IF EXISTS + ( + SELECT 1 + FROM dbo.Tra_SolicitudesPagos + WHERE CveSolicitud = @CveSolicitud + AND CveTramitePago = @CveTramitePago + ) + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado ya fue realizado.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + WHERE S.CveSolicitud = @CveSolicitud + ) + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado no corresponde al trámite o no tiene conceptos activos.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + S.CveSolicitud, + P.CveTramitePago, + S.CveFraccionamiento, + F.Fraccionamiento, + F.CveCliente, + C.Nombre AS Cliente, + C.RFC, + CONCAT( + C.Direccion, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.NoExt)), '') IS NULL THEN '' + ELSE CONCAT(' ', C.NoExt) + END, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.NoInt)), '') IS NULL THEN '' + ELSE CONCAT(' Int. ', C.NoInt) + END + ) AS Direccion, + C.Colonia, + CONCAT(C.Ciudad, ', ', C.Estado) AS CiudadEstado, + C.CP, + C.Telefono, + C.Mail, + S.Folio AS FolioSolicitud, + E.Etapa, + TT.TipoTramite, + P.Nombre AS NombrePago, + 'Remisión' AS TipoDocumento, + 'TRA' AS Serie, + ISNULL( + ( + SELECT MAX(V.Folio) + 1 + FROM dbo.Ventas AS V + WHERE V.TipoDocto = 'Rem' + AND V.Serie = 'TRA' + AND V.CveSubProyecto = @CveSubProyecto + ), + 1 + ) AS Folio, + GETDATE() AS Fecha + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Fraccionamientos AS F + ON F.CveFraccionamiento = S.CveFraccionamiento + INNER JOIN dbo.FraccionamientosEtapas AS E + ON E.CveFraccionamientoEtapa = S.CveFraccionamientoEtapa + INNER JOIN dbo.Tra_TiposTramite AS TT + ON TT.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = F.CveCliente + WHERE S.CveSolicitud = @CveSolicitud; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar la venta del trámite; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteContextoGet' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteConceptoList + @CveSolicitud int, + @CveTramitePago int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + SELECT + D.CveTramitePagoDetalle, + D.CvePS, + D.CveUM, + CASE + WHEN NULLIF(LTRIM(RTRIM(UM.Abreviatura)), '') IS NULL + THEN UM.UnidadMedida COLLATE DATABASE_DEFAULT + ELSE + UM.UnidadMedida COLLATE DATABASE_DEFAULT + + ' (' + + UM.Abreviatura COLLATE DATABASE_DEFAULT + + ')' + END AS UnidadMedida, + C.CveClasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(C.Codigo)), '') IS NULL + THEN C.Clasificacion COLLATE DATABASE_DEFAULT + ELSE + C.Codigo COLLATE DATABASE_DEFAULT + + ' - ' + + C.Clasificacion COLLATE DATABASE_DEFAULT + END AS Clasificacion, + CASE + WHEN NULLIF(LTRIM(RTRIM(PS.Codigo)), '') IS NULL + THEN PS.PS COLLATE DATABASE_DEFAULT + ELSE + PS.Codigo COLLATE DATABASE_DEFAULT + + ' - ' + + PS.PS COLLATE DATABASE_DEFAULT + END AS ProductoServicio, + CONVERT(decimal(18, 4), D.Cantidad) AS Cantidad, + CONVERT(decimal(18, 2), PS.Precio) AS PrecioUnitario, + CONVERT(decimal(18, 2), 0) AS Descuento, + CONVERT( + decimal(18, 2), + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ) AS IVA, + CONVERT( + decimal(18, 2), + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio), + 2 + ) + + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ) AS Importe + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + INNER JOIN dbo.Tra_PagosDetalle AS D + ON D.CveTramitePago = P.CveTramitePago + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = D.CvePS + INNER JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = D.CveUM + INNER JOIN dbo.Clasificaciones AS C + ON C.CveClasificacion = PS.CveClasificacion + WHERE S.CveSolicitud = @CveSolicitud + ORDER BY D.CveTramitePagoDetalle; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los conceptos de la venta; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteConceptoList' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Vta_TramiteVentaSave + @CveSolicitud int, + @CveTramitePago int, + @Observaciones varchar(2000) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + DECLARE + @CveCliente int, + @CveSubProyecto int, + @CveEstatusFactura int, + @CveVenta int, + @Folio int, + @SubTotal decimal(18, 2), + @IVA decimal(18, 2), + @Total decimal(18, 2), + @Fecha datetime = GETDATE(); + + SELECT + @CveCliente = F.CveCliente + FROM dbo.Tra_Solicitudes AS S + INNER JOIN dbo.Fraccionamientos AS F + ON F.CveFraccionamiento = S.CveFraccionamiento + INNER JOIN dbo.Tra_Pagos AS P + ON P.CveTramitePago = @CveTramitePago + AND P.CveTipoTramite = S.CveTipoTramite + AND P.EsActivo = 1 + WHERE S.CveSolicitud = @CveSolicitud; + + IF @CveCliente IS NULL + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado no corresponde al trámite.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Tra_SolicitudesPagos WITH (UPDLOCK, HOLDLOCK) + WHERE CveSolicitud = @CveSolicitud + AND CveTramitePago = @CveTramitePago + ) + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado ya fue realizado.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT TOP (1) + @CveSubProyecto = CveSubProyecto + FROM dbo.SubProyectos + WHERE Estatus = 1 + ORDER BY + CASE WHEN Serie = 'TRA' THEN 0 ELSE 1 END, + CveSubProyecto; + + SELECT TOP (1) + @CveEstatusFactura = CveEstatusFactura + FROM dbo.EstatusFactura + WHERE TipoDocto = 'Rem' + AND Estado = 1 + ORDER BY CveEstatusFactura; + + IF @CveSubProyecto IS NULL OR @CveEstatusFactura IS NULL + BEGIN + SELECT + @ErrorMostrar = 'La configuración mínima de ventas no está disponible; favor de contactar a Sistemas.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + @SubTotal = CONVERT( + decimal(18, 2), + SUM( + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio), + 2 + ) + ) + ), + @IVA = CONVERT( + decimal(18, 2), + SUM( + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ) + ) + FROM dbo.Tra_PagosDetalle AS D + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = D.CvePS + WHERE D.CveTramitePago = @CveTramitePago; + + IF @SubTotal IS NULL + BEGIN + SELECT + @ErrorMostrar = 'El pago seleccionado no tiene conceptos para vender.', + @ErrorTipo = 2; + RETURN; + END; + + SET @IVA = ISNULL(@IVA, 0); + SET @Total = @SubTotal + @IVA; + + SELECT + @Folio = ISNULL(MAX(Folio), 0) + 1 + FROM dbo.Ventas WITH (UPDLOCK, HOLDLOCK) + WHERE CveSubProyecto = @CveSubProyecto + AND TipoDocto = 'Rem' + AND Serie = 'TRA'; + + INSERT INTO dbo.Ventas + ( + TipoDocto, + Serie, + Folio, + Fecha, + CveCliente, + CveMetodoPago, + CondicionesPago, + FormaPago, + SubTotal, + IVA, + Total, + Observaciones, + CveEstatusFactura, + FechaEjecucion, + CveSubProyecto, + CveUsuario, + CveFormaPago33, + CveMetodoPago33, + FechaIng, + FechaVencimiento2, + Ref, + DescripcionVenta, + FechaParaSurtir + ) + VALUES + ( + 'Rem', + 'TRA', + @Folio, + @Fecha, + @CveCliente, + 2, + 0, + 99, + @SubTotal, + @IVA, + @Total, + ISNULL(@Observaciones, ''), + @CveEstatusFactura, + @Fecha, + @CveSubProyecto, + @CveUsuarioEjecuta, + 99, + 2, + @Fecha, + CONVERT(date, @Fecha), + CONVERT(varchar(50), @CveSolicitud), + 'Pago de trámite', + @Fecha + ); + + SET @CveVenta = CONVERT(int, SCOPE_IDENTITY()); + + INSERT INTO dbo.VentasDetalle + ( + CveVenta, + CvePS, + CveSolicitud, + CveCostoTramite, + Cantidad, + PrecioUnitario, + Descuento, + IVA, + Importe, + EsFondoInicial, + FechaAlta, + CveUsuario + ) + SELECT + @CveVenta, + D.CvePS, + @CveSolicitud, + NULL, + D.Cantidad, + CONVERT(decimal(18, 2), PS.Precio), + CONVERT(decimal(18, 2), 0), + CONVERT( + decimal(18, 2), + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ), + CONVERT( + decimal(18, 2), + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio), + 2 + ) + + ROUND( + CONVERT(decimal(18, 4), D.Cantidad) * + CONVERT(decimal(18, 4), PS.Precio) * + CONVERT(decimal(18, 6), ISNULL(PS.IVA, 0)) / 100, + 2 + ) + ), + 0, + @Fecha, + @CveUsuarioEjecuta + FROM dbo.Tra_PagosDetalle AS D + INNER JOIN dbo.ProductosServicios AS PS + ON PS.CvePS = D.CvePS + WHERE D.CveTramitePago = @CveTramitePago; + + INSERT INTO dbo.Tra_SolicitudesPagos + ( + CveSolicitud, + CveTramitePago, + CveVenta, + FechaAlta, + CveUsuario + ) + VALUES + ( + @CveSolicitud, + @CveTramitePago, + @CveVenta, + @Fecha, + @CveUsuarioEjecuta + ); + + SELECT @CveVenta AS CveVenta; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al registrar la venta del trámite; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Vta_TramiteVentaSave' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +DECLARE @CveModuloFraccionamientoDetalle int = +( + SELECT CveModulo + FROM dbo.Sis_Modulos + WHERE Url = '~/Pages/Fraccionamientos/FraccionamientoDetalle.aspx' +); +DECLARE @CveModuloVentaTramite int = +( + SELECT CveModulo + FROM dbo.Sis_Modulos + WHERE Url = '~/Pages/Ventas/VentaTramite.aspx' +); + +IF @CveModuloVentaTramite IS NULL +BEGIN + INSERT INTO dbo.Sis_Modulos + ( + CveModuloPadre, + CvePlataforma, + NombreModulo, + Descripcion, + Url, + ClaseCssIcono, + OrdenVisualizacion, + Visible, + Activo, + FechaCreacion + ) + VALUES + ( + @CveModuloFraccionamientoDetalle, + 1, + 'Venta de trámite', + 'Registro del pago de un trámite', + '~/Pages/Ventas/VentaTramite.aspx', + 'fa fa-credit-card', + 10, + 0, + 1, + GETDATE() + ); + + SET @CveModuloVentaTramite = CONVERT(int, SCOPE_IDENTITY()); +END; + +IF @CveModuloFraccionamientoDetalle IS NOT NULL +BEGIN + INSERT INTO dbo.Sis_RolesModulos + ( + CveRol, + CveModulo, + PuedeVer, + PuedeCrear, + PuedeModificar, + PuedeEliminar, + PuedeImprimir, + PuedeExportar, + FechaCreacion + ) + SELECT + RM.CveRol, + @CveModuloVentaTramite, + RM.PuedeVer, + RM.PuedeCrear, + RM.PuedeModificar, + RM.PuedeEliminar, + RM.PuedeImprimir, + RM.PuedeExportar, + GETDATE() + FROM dbo.Sis_RolesModulos AS RM + WHERE RM.CveModulo = @CveModuloFraccionamientoDetalle + AND NOT EXISTS + ( + SELECT 1 + FROM dbo.Sis_RolesModulos AS Existente + WHERE Existente.CveRol = RM.CveRol + AND Existente.CveModulo = @CveModuloVentaTramite + ); +END; +GO diff --git a/Menu_Catalogos_Productos.sql b/Menu_Catalogos_Productos.sql new file mode 100644 index 0000000..c72ed97 --- /dev/null +++ b/Menu_Catalogos_Productos.sql @@ -0,0 +1,310 @@ +SET NOCOUNT ON; +SET XACT_ABORT ON; + +BEGIN TRY + BEGIN TRANSACTION; + + DECLARE @CvePlataforma int; + DECLARE @CveCatalogos int; + DECLARE @CveProductosGrupo int; + DECLARE @CveProductos int; + DECLARE @CveUnidadesMedida int; + DECLARE @CveClasificacion int; + + SELECT TOP (1) + @CvePlataforma = CvePlataforma + FROM dbo.Sis_Plataformas + WHERE NombrePlataforma = 'Plataforma de Desarrolladores' + ORDER BY CvePlataforma; + + SELECT TOP (1) + @CveCatalogos = CveModulo + FROM dbo.Sis_Modulos + WHERE CvePlataforma = @CvePlataforma + AND CveModuloPadre IS NULL + AND NombreModulo = 'Catálogos' + AND Activo = 1 + ORDER BY CveModulo; + + IF @CveCatalogos IS NULL + BEGIN + THROW 50001, 'No se encontró el módulo Catálogos.', 1; + END; + + SELECT TOP (1) + @CveProductos = CveModulo + FROM dbo.Sis_Modulos + WHERE CvePlataforma = @CvePlataforma + AND LOWER(ISNULL(Url, '')) = + LOWER('~/Pages/Catalogos/ProductosServicios.aspx') + COLLATE Modern_Spanish_CS_AS + ORDER BY CveModulo; + + SELECT TOP (1) + @CveProductosGrupo = CveModulo + FROM dbo.Sis_Modulos + WHERE CvePlataforma = @CvePlataforma + AND CveModuloPadre = @CveCatalogos + AND Url IS NULL + AND NombreModulo = 'Productos' + ORDER BY CveModulo; + + IF @CveProductosGrupo IS NULL + BEGIN + INSERT dbo.Sis_Modulos + ( + CveModuloPadre, + CvePlataforma, + NombreModulo, + Descripcion, + Url, + ClaseCssIcono, + ClaseCssEstilo, + OrdenVisualizacion, + Visible, + Activo, + FechaCreacion + ) + VALUES + ( + @CveCatalogos, + @CvePlataforma, + 'Productos', + 'Catálogos de productos', + NULL, + 'fa fa-cubes', + NULL, + 50, + 1, + 1, + GETDATE() + ); + + SET @CveProductosGrupo = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + UPDATE dbo.Sis_Modulos + SET Descripcion = 'Catálogos de productos', + ClaseCssIcono = 'fa fa-cubes', + OrdenVisualizacion = 50, + Visible = 1, + Activo = 1, + FechaActualizacion = GETDATE() + WHERE CveModulo = @CveProductosGrupo; + END; + + IF @CveProductos IS NULL + BEGIN + INSERT dbo.Sis_Modulos + ( + CveModuloPadre, + CvePlataforma, + NombreModulo, + Descripcion, + Url, + ClaseCssIcono, + ClaseCssEstilo, + OrdenVisualizacion, + Visible, + Activo, + FechaCreacion + ) + VALUES + ( + @CveProductosGrupo, + @CvePlataforma, + 'Productos', + 'Productos y servicios', + '~/Pages/Catalogos/ProductosServicios.aspx', + 'fa fa-cube', + NULL, + 10, + 1, + 1, + GETDATE() + ); + + SET @CveProductos = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + UPDATE dbo.Sis_Modulos + SET CveModuloPadre = @CveProductosGrupo, + NombreModulo = 'Productos', + Descripcion = 'Productos y servicios', + ClaseCssIcono = 'fa fa-cube', + OrdenVisualizacion = 10, + Visible = 1, + Activo = 1, + FechaActualizacion = GETDATE() + WHERE CveModulo = @CveProductos; + END; + + SELECT TOP (1) + @CveUnidadesMedida = CveModulo + FROM dbo.Sis_Modulos + WHERE CvePlataforma = @CvePlataforma + AND LOWER(ISNULL(Url, '')) = + LOWER('~/Pages/Catalogos/UnidadesMedida.aspx') + COLLATE Modern_Spanish_CS_AS + ORDER BY CveModulo; + + IF @CveUnidadesMedida IS NULL + BEGIN + INSERT dbo.Sis_Modulos + ( + CveModuloPadre, + CvePlataforma, + NombreModulo, + Descripcion, + Url, + ClaseCssIcono, + ClaseCssEstilo, + OrdenVisualizacion, + Visible, + Activo, + FechaCreacion + ) + VALUES + ( + @CveProductosGrupo, + @CvePlataforma, + 'Unidades de medida', + 'Catálogo de unidades de medida', + '~/Pages/Catalogos/UnidadesMedida.aspx', + 'fa fa-balance-scale', + NULL, + 20, + 1, + 1, + GETDATE() + ); + + SET @CveUnidadesMedida = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + UPDATE dbo.Sis_Modulos + SET CveModuloPadre = @CveProductosGrupo, + NombreModulo = 'Unidades de medida', + Descripcion = 'Catálogo de unidades de medida', + ClaseCssIcono = 'fa fa-balance-scale', + OrdenVisualizacion = 20, + Visible = 1, + Activo = 1, + FechaActualizacion = GETDATE() + WHERE CveModulo = @CveUnidadesMedida; + END; + + SELECT TOP (1) + @CveClasificacion = CveModulo + FROM dbo.Sis_Modulos + WHERE CvePlataforma = @CvePlataforma + AND LOWER(ISNULL(Url, '')) = + LOWER('~/Pages/Catalogos/Clasificaciones.aspx') + COLLATE Modern_Spanish_CS_AS + ORDER BY CveModulo; + + IF @CveClasificacion IS NULL + BEGIN + INSERT dbo.Sis_Modulos + ( + CveModuloPadre, + CvePlataforma, + NombreModulo, + Descripcion, + Url, + ClaseCssIcono, + ClaseCssEstilo, + OrdenVisualizacion, + Visible, + Activo, + FechaCreacion + ) + VALUES + ( + @CveProductosGrupo, + @CvePlataforma, + 'Clasificación', + 'Catálogo de clasificaciones', + '~/Pages/Catalogos/Clasificaciones.aspx', + 'fa fa-tags', + NULL, + 30, + 1, + 1, + GETDATE() + ); + + SET @CveClasificacion = CONVERT(int, SCOPE_IDENTITY()); + END + ELSE + BEGIN + UPDATE dbo.Sis_Modulos + SET CveModuloPadre = @CveProductosGrupo, + NombreModulo = 'Clasificación', + Descripcion = 'Catálogo de clasificaciones', + ClaseCssIcono = 'fa fa-tags', + OrdenVisualizacion = 30, + Visible = 1, + Activo = 1, + FechaActualizacion = GETDATE() + WHERE CveModulo = @CveClasificacion; + END; + + DECLARE @ModulosNuevos TABLE + ( + CveModulo int NOT NULL PRIMARY KEY + ); + + INSERT INTO @ModulosNuevos (CveModulo) + VALUES + (@CveProductosGrupo), + (@CveUnidadesMedida), + (@CveClasificacion); + + INSERT dbo.Sis_RolesModulos + ( + CveRol, + CveModulo, + PuedeVer, + PuedeCrear, + PuedeModificar, + PuedeEliminar, + PuedeImprimir, + PuedeExportar, + FechaCreacion + ) + SELECT + RM.CveRol, + M.CveModulo, + RM.PuedeVer, + RM.PuedeCrear, + RM.PuedeModificar, + RM.PuedeEliminar, + RM.PuedeImprimir, + RM.PuedeExportar, + GETDATE() + FROM dbo.Sis_RolesModulos AS RM + CROSS JOIN @ModulosNuevos AS M + WHERE RM.CveModulo = @CveProductos + AND NOT EXISTS + ( + SELECT 1 + FROM dbo.Sis_RolesModulos AS ExistingPermission + WHERE ExistingPermission.CveRol = RM.CveRol + AND ExistingPermission.CveModulo = M.CveModulo + ); + + COMMIT TRANSACTION; +END TRY +BEGIN CATCH + IF XACT_STATE() <> 0 + BEGIN + ROLLBACK TRANSACTION; + END; + + THROW; +END CATCH; +GO diff --git a/Menu_Catalogos_Tramites_Internos.sql b/Menu_Catalogos_Tramites_Internos.sql index 31bc20d..912dea3 100644 --- a/Menu_Catalogos_Tramites_Internos.sql +++ b/Menu_Catalogos_Tramites_Internos.sql @@ -25,18 +25,23 @@ BEGIN TRY Url varchar(500) NULL, Icono varchar(150) NULL, Orden int NOT NULL, - Visible bit NOT NULL + Visible bit NOT NULL, + Nivel int NOT NULL ); INSERT INTO @Menu - (Clave, ClavePadre, NombreModulo, Url, Icono, Orden, Visible) + (Clave, ClavePadre, NombreModulo, Url, Icono, Orden, Visible, Nivel) VALUES - ('Catalogos', NULL, 'Catálogos', NULL, 'fa fa-list-alt', 30, 1), - ('EstatusSolicitud', 'Catalogos', 'Estatus de solicitud', '~/Pages/Catalogos/EstatusSolicitud.aspx', 'fa fa-check-circle', 10, 1), - ('TiposTramite', 'Catalogos', 'Tipos de trámite', '~/Pages/Catalogos/TiposTramite.aspx', 'fa fa-file-text-o', 20, 1), - ('TipoTramiteDetalle', 'TiposTramite', 'Detalle de tipo de trámite', '~/Pages/Catalogos/TipoTramiteDetalle.aspx', 'fa fa-question-circle', 10, 0), - ('TiposDocumento', 'Catalogos', 'Tipos de documento', '~/Pages/Catalogos/TiposDocumento.aspx', 'fa fa-file-o', 30, 1), - ('DocumentosRequeridos', 'Catalogos', 'Documentos requeridos', '~/Pages/Catalogos/DocumentosRequeridos.aspx', 'fa fa-paperclip', 40, 1); + ('Catalogos', NULL, 'Catálogos', NULL, 'fa fa-list-alt', 30, 1, 0), + ('EstatusSolicitud', 'Catalogos', 'Estatus de solicitud', '~/Pages/Catalogos/EstatusSolicitud.aspx', 'fa fa-check-circle', 10, 1, 1), + ('TiposTramite', 'Catalogos', 'Tipos de trámite', '~/Pages/Catalogos/TiposTramite.aspx', 'fa fa-file-text-o', 20, 1, 1), + ('TipoTramiteDetalle', 'TiposTramite', 'Detalle de tipo de trámite', '~/Pages/Catalogos/TipoTramiteDetalle.aspx', 'fa fa-question-circle', 10, 0, 2), + ('TiposDocumento', 'Catalogos', 'Tipos de documento', '~/Pages/Catalogos/TiposDocumento.aspx', 'fa fa-file-o', 30, 1, 1), + ('DocumentosRequeridos', 'Catalogos', 'Documentos requeridos', '~/Pages/Catalogos/DocumentosRequeridos.aspx', 'fa fa-paperclip', 40, 1, 1), + ('ProductosGrupo', 'Catalogos', 'Productos', NULL, 'fa fa-cubes', 50, 1, 1), + ('ProductosServicios', 'ProductosGrupo', 'Productos', '~/Pages/Catalogos/ProductosServicios.aspx', 'fa fa-cube', 10, 1, 2), + ('UnidadesMedida', 'ProductosGrupo', 'Unidades de medida', '~/Pages/Catalogos/UnidadesMedida.aspx', 'fa fa-balance-scale', 20, 1, 2), + ('Clasificaciones', 'ProductosGrupo', 'Clasificación', '~/Pages/Catalogos/Clasificaciones.aspx', 'fa fa-tags', 30, 1, 2); DECLARE @Ids TABLE ( @@ -52,20 +57,27 @@ BEGIN TRY @Icono varchar(150), @Orden int, @Visible bit, + @Nivel int, @CveModuloPadre int, @CveModulo int; DECLARE CatalogoCursor CURSOR LOCAL FAST_FORWARD FOR - SELECT Clave, ClavePadre, NombreModulo, Url, Icono, Orden, Visible - FROM @Menu - ORDER BY - CASE WHEN ClavePadre IS NULL THEN 0 ELSE 1 END, + SELECT + Clave, + ClavePadre, + NombreModulo, + Url, + Icono, Orden, - Clave; + Visible, + Nivel + FROM @Menu + ORDER BY Nivel, Orden, Clave; OPEN CatalogoCursor; FETCH NEXT FROM CatalogoCursor - INTO @Clave, @ClavePadre, @NombreModulo, @Url, @Icono, @Orden, @Visible; + INTO @Clave, @ClavePadre, @NombreModulo, @Url, @Icono, @Orden, + @Visible, @Nivel; WHILE @@FETCH_STATUS = 0 BEGIN @@ -121,7 +133,8 @@ BEGIN TRY VALUES (@Clave, @CveModulo); FETCH NEXT FROM CatalogoCursor - INTO @Clave, @ClavePadre, @NombreModulo, @Url, @Icono, @Orden, @Visible; + INTO @Clave, @ClavePadre, @NombreModulo, @Url, @Icono, @Orden, + @Visible, @Nivel; END; CLOSE CatalogoCursor; diff --git a/Optimiza_Bitacora_Listado_Detalle_20260827.sql b/Optimiza_Bitacora_Listado_Detalle_20260827.sql new file mode 100644 index 0000000..457f1db --- /dev/null +++ b/Optimiza_Bitacora_Listado_Detalle_20260827.sql @@ -0,0 +1,365 @@ +SET NOCOUNT ON; +GO + +/* + El resumen se genera a partir de la definición instalada para conservar + ajustes locales del procedimiento original. Solamente se elimina el bloque + que consulta campos y relaciones internas de cada movimiento. +*/ +DECLARE @DefinicionResumen nvarchar(max) = + OBJECT_DEFINITION( + OBJECT_ID(N'dbo.PA_Bit_BitacoraListByRelations')); + +IF @DefinicionResumen IS NULL +BEGIN + THROW 50000, + 'No existe dbo.PA_Bit_BitacoraListByRelations.', + 1; +END; + +DECLARE @InicioProcedimiento int = CHARINDEX( + N'PROCEDURE', + UPPER(@DefinicionResumen)); +DECLARE @InicioDetalle int = CHARINDEX( + N'CREATE TABLE #CamposPagina', + @DefinicionResumen); +DECLARE @FinDetalle int = CHARINDEX( + N'CREATE TABLE #RelacionesVisuales', + @DefinicionResumen); + +IF @InicioProcedimiento = 0 + OR @InicioDetalle = 0 + OR @FinDetalle <= @InicioDetalle +BEGIN + THROW 50001, + 'La definición instalada de la consulta de bitácora no tiene la estructura esperada.', + 1; +END; + +SET @DefinicionResumen = STUFF( + @DefinicionResumen, + @InicioDetalle, + @FinDetalle - @InicioDetalle, + N''); + +SET @DefinicionResumen = STUFF( + @DefinicionResumen, + 1, + @InicioProcedimiento - 1, + N'CREATE OR ALTER '); + +SET @DefinicionResumen = REPLACE( + @DefinicionResumen, + N'dbo.PA_Bit_BitacoraListByRelations', + N'dbo.PA_Bit_BitacoraResumenListByRelations'); + +EXEC sys.sp_executesql @DefinicionResumen; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Bit_BitacoraDetalleGet + @CveBitacora bigint, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + + SELECT + @ErrorMostrar = NULL, + @ErrorTipo = 0, + @Return = 0; + + BEGIN TRY + IF @CveBitacora <= 0 + BEGIN + SET @ErrorMostrar = + 'La clave del movimiento de bitácora no es válida.'; + SET @ErrorTipo = 2; + RETURN; + END; + + DECLARE @EsAdministrador bit = 0; + DECLARE @EsDesarrollador bit = 0; + + SELECT + @EsAdministrador = CASE + WHEN R.NombreRol IN + ( + 'SuperUsuario', + 'Administrador' + ) THEN 1 + ELSE 0 + END, + @EsDesarrollador = CASE + WHEN R.NombreRol = 'Empresa' THEN 1 + ELSE 0 + END + FROM dbo.Sis_Usuarios AS U + INNER JOIN dbo.Sis_Roles AS R + ON R.CveRol = U.CveRol + WHERE U.CveUsuario = @CveUsuarioEjecuta + AND U.Activo = 1 + AND R.Activo = 1; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Bit_Bitacora AS B + WHERE B.CveBitacora = @CveBitacora + AND + ( + @EsAdministrador = 1 + OR + ( + @EsDesarrollador = 1 + AND EXISTS + ( + SELECT 1 + FROM dbo.Bit_BitacoraRelaciones AS BRCliente + INNER JOIN dbo.Bit_Tablas AS TCliente + ON TCliente.CveTabla = + BRCliente.CveTablaRelacionada + INNER JOIN dbo.Bit_Campos AS CCliente + ON CCliente.CveCampo = + BRCliente.CveCampoRelacion + AND CCliente.CveTabla = TCliente.CveTabla + INNER JOIN dbo.Sis_UsuariosClientes AS UC + ON UC.CveCliente = + BRCliente.ValorRelacionNumero + AND UC.CveUsuario = @CveUsuarioEjecuta + AND UC.Activo = 1 + WHERE BRCliente.CveBitacora = B.CveBitacora + AND BRCliente.VisibleDesarrollador = 1 + AND TCliente.NombreTablaSQL = 'Clientes' + AND CCliente.NombreCampoSQL = 'CveCliente' + ) + ) + ) + ) + BEGIN + SET @ErrorMostrar = + 'No se encontró el movimiento de bitácora solicitado.'; + SET @ErrorTipo = 2; + RETURN; + END; + + SELECT + B.CveBitacora, + B.CveTabla, + T.NombreTablaSQL, + T.NombreMostrar AS NombreTabla, + B.CveTipoMovimiento, + M.Nombre AS TipoMovimiento, + B.CveDefinicionAccion, + A.NombreAccion, + A.DescripcionAccion, + B.CveUsuarioEjecuta, + COALESCE( + NULLIF(U.NombreUsuario, ''), + CONCAT('(', B.CveUsuarioEjecuta, ') Eliminado') + ) AS NombreUsuarioEjecuta, + B.CveUsuarioAutoriza, + B.FechaAutorizacion, + B.LlaveRegistro, + B.DescripcionMovimiento, + B.FechaMovimiento, + B.DireccionIP, + B.NombreEquipo, + B.Modulo + FROM dbo.Bit_Bitacora AS B + INNER JOIN dbo.Bit_Tablas AS T + ON T.CveTabla = B.CveTabla + INNER JOIN dbo.Bit_TiposMovimiento AS M + ON M.CveTipoMovimiento = B.CveTipoMovimiento + LEFT JOIN dbo.Bit_DefinicionesAccion AS A + ON A.CveDefinicionAccion = B.CveDefinicionAccion + LEFT JOIN dbo.Sis_Usuarios AS U + ON U.CveUsuario = B.CveUsuarioEjecuta + WHERE B.CveBitacora = @CveBitacora; + + CREATE TABLE #CamposDetalle + ( + CveBitacoraCampo bigint NOT NULL PRIMARY KEY, + CveBitacora bigint NOT NULL, + CveCampo int NOT NULL, + NombreCampoSQL varchar(128) + COLLATE Modern_Spanish_CS_AS NOT NULL, + NombreMostrar varchar(150) + COLLATE Modern_Spanish_CS_AS NOT NULL, + ValorAnterior nvarchar(max) + COLLATE Modern_Spanish_CS_AS NULL, + ValorNuevo nvarchar(max) + COLLATE Modern_Spanish_CS_AS NULL, + ValorAnteriorMostrar nvarchar(max) + COLLATE Modern_Spanish_CS_AS NULL, + ValorNuevoMostrar nvarchar(max) + COLLATE Modern_Spanish_CS_AS NULL + ); + + INSERT INTO #CamposDetalle + ( + CveBitacoraCampo, + CveBitacora, + CveCampo, + NombreCampoSQL, + NombreMostrar, + ValorAnterior, + ValorNuevo, + ValorAnteriorMostrar, + ValorNuevoMostrar + ) + SELECT + BC.CveBitacoraCampo, + BC.CveBitacora, + BC.CveCampo, + C.NombreCampoSQL, + C.NombreMostrar, + BC.ValorAnterior, + BC.ValorNuevo, + BC.ValorAnterior, + BC.ValorNuevo + FROM dbo.Bit_BitacoraCampos AS BC + INNER JOIN dbo.Bit_Campos AS C + ON C.CveCampo = BC.CveCampo + WHERE BC.CveBitacora = @CveBitacora + AND + ( + @EsAdministrador = 1 + OR C.MostrarEnBitacora = 1 + ); + + DECLARE @CveCampoOrigenReferencia int; + DECLARE @NombreTablaReferencia varchar(128); + DECLARE @NombreCampoLlaveReferencia varchar(128); + DECLARE @NombreCampoMostrarReferencia varchar(128); + DECLARE @SqlCampoReferencia nvarchar(max); + + DECLARE CursorCamposReferencia CURSOR LOCAL FAST_FORWARD FOR + SELECT DISTINCT + CO.CveCampo, + TR.NombreTablaSQL, + CL.NombreCampoSQL, + CM.NombreCampoSQL + FROM #CamposDetalle AS CD + INNER JOIN dbo.Bit_Campos AS CO + ON CO.CveCampo = CD.CveCampo + AND CO.Activo = 1 + INNER JOIN dbo.Bit_Tablas AS TR + ON TR.CveTabla = CO.CveTablaReferencia + AND TR.Activo = 1 + AND TR.NombreCampoLlaveSQL IS NOT NULL + INNER JOIN dbo.Bit_Campos AS CL + ON CL.CveTabla = TR.CveTabla + AND CL.NombreCampoSQL = TR.NombreCampoLlaveSQL + AND CL.Activo = 1 + INNER JOIN dbo.Bit_Campos AS CM + ON CM.CveCampo = CO.CveCampoMostrarReferencia + AND CM.CveTabla = TR.CveTabla + AND CM.MostrarEnBitacora = 1 + AND CM.Activo = 1 + INNER JOIN sys.schemas AS SC + ON SC.name = 'dbo' + INNER JOIN sys.tables AS ST + ON ST.schema_id = SC.schema_id + AND ST.name COLLATE Modern_Spanish_CS_AS = TR.NombreTablaSQL + INNER JOIN sys.columns AS SCL + ON SCL.object_id = ST.object_id + AND SCL.name COLLATE Modern_Spanish_CS_AS = + CL.NombreCampoSQL + INNER JOIN sys.columns AS SCM + ON SCM.object_id = ST.object_id + AND SCM.name COLLATE Modern_Spanish_CS_AS = + CM.NombreCampoSQL; + + OPEN CursorCamposReferencia; + + FETCH NEXT FROM CursorCamposReferencia INTO + @CveCampoOrigenReferencia, + @NombreTablaReferencia, + @NombreCampoLlaveReferencia, + @NombreCampoMostrarReferencia; + + WHILE @@FETCH_STATUS = 0 + BEGIN + SET @SqlCampoReferencia = N' + UPDATE CD + SET + CD.ValorAnteriorMostrar = CASE + WHEN CD.ValorAnterior IS NULL THEN NULL + WHEN VA.' + QUOTENAME(@NombreCampoLlaveReferencia) + N' IS NULL + THEN CONCAT(N''('', CD.ValorAnterior, N'') Eliminada'') + WHEN NULLIF(CONVERT(nvarchar(max), VA.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'''') IS NULL + THEN CONCAT(N''('', CD.ValorAnterior, N'')'') + ELSE CONVERT(nvarchar(max), VA.' + QUOTENAME(@NombreCampoMostrarReferencia) + N') + END, + CD.ValorNuevoMostrar = CASE + WHEN CD.ValorNuevo IS NULL THEN NULL + WHEN VN.' + QUOTENAME(@NombreCampoLlaveReferencia) + N' IS NULL + THEN CONCAT(N''('', CD.ValorNuevo, N'') Eliminada'') + WHEN NULLIF(CONVERT(nvarchar(max), VN.' + QUOTENAME(@NombreCampoMostrarReferencia) + N'), N'''') IS NULL + THEN CONCAT(N''('', CD.ValorNuevo, N'')'') + ELSE CONVERT(nvarchar(max), VN.' + QUOTENAME(@NombreCampoMostrarReferencia) + N') + END + FROM #CamposDetalle AS CD + LEFT JOIN dbo.' + QUOTENAME(@NombreTablaReferencia) + N' AS VA + ON CONVERT(nvarchar(250), VA.' + QUOTENAME(@NombreCampoLlaveReferencia) + N') + COLLATE Modern_Spanish_CS_AS = + CD.ValorAnterior COLLATE Modern_Spanish_CS_AS + LEFT JOIN dbo.' + QUOTENAME(@NombreTablaReferencia) + N' AS VN + ON CONVERT(nvarchar(250), VN.' + QUOTENAME(@NombreCampoLlaveReferencia) + N') + COLLATE Modern_Spanish_CS_AS = + CD.ValorNuevo COLLATE Modern_Spanish_CS_AS + WHERE CD.CveCampo = @CveCampoOrigen;'; + + EXEC sys.sp_executesql + @SqlCampoReferencia, + N'@CveCampoOrigen int', + @CveCampoOrigen = @CveCampoOrigenReferencia; + + FETCH NEXT FROM CursorCamposReferencia INTO + @CveCampoOrigenReferencia, + @NombreTablaReferencia, + @NombreCampoLlaveReferencia, + @NombreCampoMostrarReferencia; + END; + + CLOSE CursorCamposReferencia; + DEALLOCATE CursorCamposReferencia; + + SELECT + CveBitacoraCampo, + CveBitacora, + CveCampo, + NombreCampoSQL, + NombreMostrar, + ValorAnterior, + ValorNuevo, + ValorAnteriorMostrar, + ValorNuevoMostrar + FROM #CamposDetalle + ORDER BY CveBitacoraCampo; + + SET @Return = 1; + END TRY + BEGIN CATCH + SET @ErrorMostrar = + 'Ocurrió un error al consultar el detalle de la bitácora; favor de contactar a Sistemas.'; + SET @ErrorTipo = 1; + SET @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE( + ERROR_PROCEDURE(), + 'PA_Bit_BitacoraDetalleGet' + ), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE() + ); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO diff --git a/Perfil_Usuario_Cambio_Contexto_20260828.sql b/Perfil_Usuario_Cambio_Contexto_20260828.sql new file mode 100644 index 0000000..da93591 --- /dev/null +++ b/Perfil_Usuario_Cambio_Contexto_20260828.sql @@ -0,0 +1,594 @@ +CREATE OR ALTER PROCEDURE dbo.PA_Sis_UsuarioGetByName + @NombreUsuario varchar(100), + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SELECT TOP (1) + U.CveUsuario, + U.NombreUsuario, + U.HashContrasena, + U.CorreoElectronico, + U.CveRol, + R.NombreRol, + U.Activo, + U.DebeCambiarContrasena, + U.IntentosFallidosInicioSesion, + U.BloqueadoHasta, + U.FechaUltimoInicioSesion, + U.FechaUltimaConexion, + U.CorreoVerificado, + ISNULL(ClientePrincipal.CveCliente, 0) AS CveCliente + FROM dbo.Sis_Usuarios AS U + INNER JOIN dbo.Sis_Roles AS R + ON R.CveRol = U.CveRol + OUTER APPLY + ( + SELECT TOP (1) UC.CveCliente + FROM dbo.Sis_UsuariosClientes AS UC + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = UC.CveCliente + AND C.Estatus = 1 + WHERE UC.CveUsuario = U.CveUsuario + AND UC.Activo = 1 + ORDER BY + UC.EsPrincipal DESC, + UC.Orden, + UC.CveUsuarioCliente + ) AS ClientePrincipal + WHERE U.NombreUsuario = @NombreUsuario; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar el usuario; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Sis_UsuarioGetByName'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Sis_PerfilGet + @CveUsuario int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Sis_Usuarios + WHERE CveUsuario = @CveUsuario + AND Activo = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'No se encontró el usuario activo de la sesión.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + U.CveUsuario, + U.NombreUsuario, + U.CorreoElectronico, + U.CveRol, + R.NombreRol, + ISNULL(ClientePrincipal.CveCliente, 0) AS CveCliente, + CONVERT(bit, CASE WHEN U.CveRol = 3 THEN 1 ELSE 0 END) AS EsDesarrollador + FROM dbo.Sis_Usuarios AS U + INNER JOIN dbo.Sis_Roles AS R + ON R.CveRol = U.CveRol + OUTER APPLY + ( + SELECT TOP (1) UC.CveCliente + FROM dbo.Sis_UsuariosClientes AS UC + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = UC.CveCliente + AND C.Estatus = 1 + WHERE UC.CveUsuario = U.CveUsuario + AND UC.Activo = 1 + ORDER BY + UC.EsPrincipal DESC, + UC.Orden, + UC.CveUsuarioCliente + ) AS ClientePrincipal + WHERE U.CveUsuario = @CveUsuario; + + SELECT + C.CveCliente, + C.Nombre, + C.NombreComercial, + C.Direccion, + C.NoExt, + C.NoInt, + C.Colonia, + C.Ciudad, + C.Estado, + C.Pais, + C.RFC, + C.CP, + C.Telefono, + C.Mail, + C.CveRegimenFiscal, + RF.CodigoRegimenFiscal, + RF.RegimenFiscal, + C.CveUsoCFDI, + UCFDI.UsoCFDI, + UCFDI.Descripcion AS DescripcionUsoCFDI + FROM dbo.Sis_Usuarios AS U + CROSS APPLY + ( + SELECT TOP (1) UC.CveCliente + FROM dbo.Sis_UsuariosClientes AS UC + INNER JOIN dbo.Clientes AS ClienteActivo + ON ClienteActivo.CveCliente = UC.CveCliente + AND ClienteActivo.Estatus = 1 + WHERE UC.CveUsuario = U.CveUsuario + AND UC.Activo = 1 + ORDER BY + UC.EsPrincipal DESC, + UC.Orden, + UC.CveUsuarioCliente + ) AS ClientePrincipal + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = ClientePrincipal.CveCliente + LEFT JOIN dbo.Gral_RegimenesFiscales AS RF + ON RF.CveRegimenFiscal = C.CveRegimenFiscal + LEFT JOIN dbo.Gral_SAT_UsosCFDI AS UCFDI + ON UCFDI.CveUsoCFDI = C.CveUsoCFDI + WHERE U.CveUsuario = @CveUsuario + AND U.CveRol = 3; + + SELECT + CveRegimenFiscal, + CodigoRegimenFiscal, + RegimenFiscal + FROM dbo.Gral_RegimenesFiscales + ORDER BY CodigoRegimenFiscal; + + SELECT + CveUsoCFDI, + UsoCFDI, + Descripcion + FROM dbo.Gral_SAT_UsosCFDI + ORDER BY UsoCFDI; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar el perfil; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Sis_PerfilGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Sis_PerfilSesionUpdate + @CveUsuario int, + @NombreUsuario varchar(100), + @HashContrasena varchar(500) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SET @NombreUsuario = LTRIM(RTRIM(@NombreUsuario)); + SET @HashContrasena = NULLIF(LTRIM(RTRIM(@HashContrasena)), ''); + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Sis_Usuarios + WHERE CveUsuario = @CveUsuario + AND Activo = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'No se encontró el usuario activo de la sesión.', + @ErrorTipo = 2; + RETURN; + END; + + IF NULLIF(@NombreUsuario, '') IS NULL + OR LEN(@NombreUsuario) < 3 + BEGIN + SELECT + @ErrorMostrar = 'El nombre de usuario debe contener al menos tres caracteres.', + @ErrorTipo = 2; + RETURN; + END; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Sis_Usuarios + WHERE NombreUsuario = @NombreUsuario + AND CveUsuario <> @CveUsuario + ) + BEGIN + SELECT + @ErrorMostrar = 'El nombre de usuario ya está registrado.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Sis_Usuarios + SET NombreUsuario = @NombreUsuario, + HashContrasena = COALESCE(@HashContrasena, HashContrasena), + DebeCambiarContrasena = + CASE + WHEN @HashContrasena IS NULL + THEN DebeCambiarContrasena + ELSE 0 + END, + FechaActualizacion = GETDATE() + WHERE CveUsuario = @CveUsuario; + + SELECT + U.CveUsuario, + U.NombreUsuario, + U.CorreoElectronico, + U.CveRol, + R.NombreRol, + ISNULL(ClientePrincipal.CveCliente, 0) AS CveCliente, + CONVERT(bit, CASE WHEN U.CveRol = 3 THEN 1 ELSE 0 END) AS EsDesarrollador + FROM dbo.Sis_Usuarios AS U + INNER JOIN dbo.Sis_Roles AS R + ON R.CveRol = U.CveRol + OUTER APPLY + ( + SELECT TOP (1) UC.CveCliente + FROM dbo.Sis_UsuariosClientes AS UC + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = UC.CveCliente + AND C.Estatus = 1 + WHERE UC.CveUsuario = U.CveUsuario + AND UC.Activo = 1 + ORDER BY + UC.EsPrincipal DESC, + UC.Orden, + UC.CveUsuarioCliente + ) AS ClientePrincipal + WHERE U.CveUsuario = @CveUsuario; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al actualizar los datos de sesión; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Sis_PerfilSesionUpdate'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Clientes_PerfilUpdate + @CveCliente int, + @Nombre varchar(200), + @NombreComercial varchar(200) = NULL, + @Direccion varchar(90), + @NoExt varchar(20) = NULL, + @NoInt varchar(50) = NULL, + @Colonia varchar(50), + @Ciudad varchar(50), + @Estado varchar(35), + @Pais varchar(50), + @RFC varchar(15), + @CP varchar(10), + @Telefono varchar(25) = NULL, + @Mail varchar(500) = NULL, + @CveRegimenFiscal tinyint, + @CveUsoCFDI tinyint, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SELECT + @Nombre = LTRIM(RTRIM(@Nombre)), + @NombreComercial = NULLIF(LTRIM(RTRIM(@NombreComercial)), ''), + @Direccion = LTRIM(RTRIM(@Direccion)), + @NoExt = NULLIF(LTRIM(RTRIM(@NoExt)), ''), + @NoInt = NULLIF(LTRIM(RTRIM(@NoInt)), ''), + @Colonia = LTRIM(RTRIM(@Colonia)), + @Ciudad = LTRIM(RTRIM(@Ciudad)), + @Estado = LTRIM(RTRIM(@Estado)), + @Pais = LTRIM(RTRIM(@Pais)), + @RFC = UPPER(REPLACE(LTRIM(RTRIM(@RFC)), ' ', '')), + @CP = LTRIM(RTRIM(@CP)), + @Telefono = NULLIF(LTRIM(RTRIM(@Telefono)), ''), + @Mail = NULLIF(LTRIM(RTRIM(@Mail)), ''); + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Clientes + WHERE CveCliente = @CveCliente + AND Estatus = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'No se encontró el cliente activo del perfil.', + @ErrorTipo = 2; + RETURN; + END; + + IF NULLIF(@Nombre, '') IS NULL + OR NULLIF(@Direccion, '') IS NULL + OR NULLIF(@Colonia, '') IS NULL + OR NULLIF(@Ciudad, '') IS NULL + OR NULLIF(@Estado, '') IS NULL + OR NULLIF(@Pais, '') IS NULL + OR LEN(@RFC) NOT IN (12, 13) + OR LEN(@CP) <> 5 + BEGIN + SELECT + @ErrorMostrar = 'Capture nombre fiscal, domicilio, RFC y código postal válidos.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Gral_RegimenesFiscales + WHERE CveRegimenFiscal = @CveRegimenFiscal + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione un régimen fiscal válido.', + @ErrorTipo = 2; + RETURN; + END; + + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Gral_SAT_UsosCFDI + WHERE CveUsoCFDI = @CveUsoCFDI + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione un uso de CFDI válido.', + @ErrorTipo = 2; + RETURN; + END; + + UPDATE dbo.Clientes + SET Nombre = @Nombre, + NombreComercial = @NombreComercial, + Direccion = @Direccion, + NoExt = @NoExt, + NoInt = @NoInt, + Colonia = @Colonia, + Ciudad = @Ciudad, + Estado = @Estado, + Pais = @Pais, + RFC = @RFC, + CP = @CP, + Telefono = @Telefono, + Mail = @Mail, + CveRegimenFiscal = @CveRegimenFiscal, + CveUsoCFDI = @CveUsoCFDI, + CveUsuarioModifico = @CveUsuarioEjecuta + WHERE CveCliente = @CveCliente; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al actualizar los datos del cliente; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Clientes_PerfilUpdate'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Sis_UsuarioContextoList + @Texto varchar(150) = NULL, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + SET @Texto = NULLIF(LTRIM(RTRIM(@Texto)), ''); + + SELECT + U.CveUsuario, + U.NombreUsuario, + U.CorreoElectronico, + U.CveRol, + R.NombreRol, + U.DebeCambiarContrasena, + ISNULL(ClientePrincipal.CveCliente, 0) AS CveCliente, + ClientePrincipal.Cliente + FROM dbo.Sis_Usuarios AS U + INNER JOIN dbo.Sis_Roles AS R + ON R.CveRol = U.CveRol + OUTER APPLY + ( + SELECT TOP (1) + UC.CveCliente, + C.Nombre AS Cliente + FROM dbo.Sis_UsuariosClientes AS UC + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = UC.CveCliente + AND C.Estatus = 1 + WHERE UC.CveUsuario = U.CveUsuario + AND UC.Activo = 1 + ORDER BY + UC.EsPrincipal DESC, + UC.Orden, + UC.CveUsuarioCliente + ) AS ClientePrincipal + WHERE U.Activo = 1 + AND + ( + @Texto IS NULL + OR U.NombreUsuario LIKE '%' + @Texto + '%' + OR U.CorreoElectronico LIKE '%' + @Texto + '%' + OR ClientePrincipal.Cliente LIKE '%' + @Texto + '%' + ) + ORDER BY U.NombreUsuario; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al consultar los usuarios disponibles; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Sis_UsuarioContextoList'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO + +CREATE OR ALTER PROCEDURE dbo.PA_Sis_UsuarioContextoGet + @CveUsuario int, + @CveUsuarioEjecuta int, + @ErrorMostrar varchar(max) OUTPUT, + @ErrorTipo int OUTPUT, + @Return bit OUTPUT +AS +BEGIN + SET NOCOUNT ON; + SELECT @ErrorMostrar = NULL, @ErrorTipo = 0, @Return = 0; + + BEGIN TRY + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.Sis_Usuarios + WHERE CveUsuario = @CveUsuario + AND Activo = 1 + ) + BEGIN + SELECT + @ErrorMostrar = 'El usuario seleccionado ya no está disponible.', + @ErrorTipo = 2; + RETURN; + END; + + SELECT + U.CveUsuario, + U.NombreUsuario, + U.CorreoElectronico, + U.CveRol, + R.NombreRol, + U.DebeCambiarContrasena, + ISNULL(ClientePrincipal.CveCliente, 0) AS CveCliente, + ClientePrincipal.Cliente + FROM dbo.Sis_Usuarios AS U + INNER JOIN dbo.Sis_Roles AS R + ON R.CveRol = U.CveRol + OUTER APPLY + ( + SELECT TOP (1) + UC.CveCliente, + C.Nombre AS Cliente + FROM dbo.Sis_UsuariosClientes AS UC + INNER JOIN dbo.Clientes AS C + ON C.CveCliente = UC.CveCliente + AND C.Estatus = 1 + WHERE UC.CveUsuario = U.CveUsuario + AND UC.Activo = 1 + ORDER BY + UC.EsPrincipal DESC, + UC.Orden, + UC.CveUsuarioCliente + ) AS ClientePrincipal + WHERE U.CveUsuario = @CveUsuario; + + SET @Return = 1; + END TRY + BEGIN CATCH + SELECT + @ErrorMostrar = 'Ocurrió un error al obtener el usuario seleccionado; favor de contactar a Sistemas.', + @ErrorTipo = 1, + @Return = 0; + + DECLARE @ErrorTecnico nvarchar(2048) = + CONCAT( + 'Número: ', ERROR_NUMBER(), + '; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Sis_UsuarioContextoGet'), + '; Línea: ', ERROR_LINE(), + '; Detalle: ', ERROR_MESSAGE()); + + RAISERROR(N'%s', 10, 1, @ErrorTecnico); + END CATCH; +END; +GO diff --git a/SIG.Web/AccessDenied.aspx b/SIG.Web/AccessDenied.aspx new file mode 100644 index 0000000..59ec92f --- /dev/null +++ b/SIG.Web/AccessDenied.aspx @@ -0,0 +1,21 @@ +<%@ Page Title="Acceso denegado" + Language="C#" + MasterPageFile="~/Site.master" + AutoEventWireup="true" + CodeFile="AccessDenied.aspx.cs" + Inherits="SIG.Web.AccessDenied" %> + + + + + +
+

Acceso denegado

+

+ No cuenta con acceso a esta página desde el menú asignado a su usuario. +

+
+
+ + + diff --git a/SIG.Web/App_Code/Configuration/AppServices.cs b/SIG.Web/App_Code/Configuration/AppServices.cs index e18f78a..6287e00 100644 --- a/SIG.Web/App_Code/Configuration/AppServices.cs +++ b/SIG.Web/App_Code/Configuration/AppServices.cs @@ -10,6 +10,7 @@ using SIG.Web.AppCode.Contracts.Menu; using SIG.Web.AppCode.Contracts.Search; using SIG.Web.AppCode.Contracts.Security; using SIG.Web.AppCode.Contracts.Tramites; +using SIG.Web.AppCode.Contracts.Ventas; using SIG.Web.AppCode.Notifications.Contracts; using SIG.Web.AppCode.Notifications.Services; using SIG.Web.AppCode.Repositories.Bitacora; @@ -21,14 +22,17 @@ using SIG.Web.AppCode.Repositories.Menu; using SIG.Web.AppCode.Repositories.Fraccionamientos; using SIG.Web.AppCode.Repositories.Security; using SIG.Web.AppCode.Repositories.Tramites; +using SIG.Web.AppCode.Repositories.Ventas; using SIG.Web.AppCode.Services.Bitacora; using SIG.Web.AppCode.Services.Documentos; using SIG.Web.AppCode.Services.Facturacion; using SIG.Web.AppCode.Services.Fraccionamientos; +using SIG.Web.AppCode.Services.General; using SIG.Web.AppCode.Services.Menu; using SIG.Web.AppCode.Services.Search; using SIG.Web.AppCode.Services.Security; using SIG.Web.AppCode.Services.Tramites; +using SIG.Web.AppCode.Services.Ventas; using SIG.Web.AppCode.Session; namespace SIG.Web.AppCode.Configuration @@ -43,13 +47,17 @@ namespace SIG.Web.AppCode.Configuration public static IUserRepository UserRepository { get; private set; } private static IUserAdministrationRepository UserAdministrationRepository { get; set; } public static IUserAdministrationService UserAdministrationService { get; private set; } + public static IPerfilUsuarioService PerfilUsuarioService { get; private set; } public static IGeneralCatalogRepository GeneralCatalogRepository { get; private set; } + public static IProductoServicioService ProductoServicioService { get; private set; } + public static IProductoCatalogService ProductoCatalogService { get; private set; } public static IClienteDocumentoService ClienteDocumentoService { get; private set; } public static ITramiteDocumentoService TramiteDocumentoService { get; private set; } public static IFraccionamientoService FraccionamientoService { get; private set; } public static IFraccionamientoGisService FraccionamientoGisService { get; private set; } public static ITramiteCatalogService TramiteCatalogService { get; private set; } public static ITramiteSolicitudService TramiteSolicitudService { get; private set; } + public static IServicioVentaTramite ServicioVentaTramite { get; private set; } public static ICfdiTimbradoService CfdiTimbradoService { get; private set; } public static IPublicRegistrationService PublicRegistrationService { get; private set; } public static ILoginAttemptRepository LoginAttemptRepository { get; private set; } @@ -89,7 +97,16 @@ namespace SIG.Web.AppCode.Configuration UserAdministrationRepository, PasswordHasher, BitacoraService); + PerfilUsuarioService = new PerfilUsuarioService( + new PerfilUsuarioRepository(DbExecutor), + PasswordHasher); GeneralCatalogRepository = new GeneralCatalogRepository(DbExecutor); + ProductoServicioService = new ProductoServicioService( + new ProductoServicioRepository(DbExecutor), + BitacoraService); + ProductoCatalogService = new ProductoCatalogService( + new ProductoCatalogRepository(DbExecutor), + BitacoraService); ClienteDocumentoService = new ClienteDocumentoService( new ClienteDocumentoRepository(DbExecutor)); @@ -125,15 +142,23 @@ namespace SIG.Web.AppCode.Configuration TramiteSolicitudService = new TramiteSolicitudService( tramiteSolicitudRepository, BitacoraService); + var clienteProfact = new ProfactPacTimbradoClient( + new ConfigurationPacCredentialProvider()); CfdiTimbradoService = new CfdiTimbradoService( new CfdiRepository(DbExecutor), new ProfactCfdi40XmlBuilder(), new IPacTimbradoClient[] { - new ProfactPacTimbradoClient( - new ConfigurationPacCredentialProvider()) + clienteProfact }, - new ICfdiTimbradoFinalizadoHandler[0]); + new IPacCancelacionClient[] + { + clienteProfact + }, + new AlmacenArchivosCfdi()); + ServicioVentaTramite = new ServicioVentaTramite( + new RepositorioVentaTramite(DbExecutor), + CfdiTimbradoService); LoginAttemptRepository = new LoginAttemptRepository(DbExecutor); UserSessionRepository = new UserSessionRepository(DbExecutor); diff --git a/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraRepository.cs b/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraRepository.cs index e2384d6..436e093 100644 --- a/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraRepository.cs +++ b/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraRepository.cs @@ -18,8 +18,8 @@ namespace SIG.Web.AppCode.Contracts.Bitacora BitacoraConsultaModel consulta, int cveUsuarioEjecuta); - DbResult> Consultar( - BitacoraConsultaModel consulta, + DbResult ConsultarDetalle( + long cveBitacora, int cveUsuarioEjecuta); } } diff --git a/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraService.cs b/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraService.cs index cfb2555..a5adaac 100644 --- a/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraService.cs +++ b/SIG.Web/App_Code/Contracts/Bitacora/IBitacoraService.cs @@ -13,7 +13,6 @@ namespace SIG.Web.AppCode.Contracts.Bitacora DbResult> ConsultarResumen( BitacoraConsultaModel consulta); - DbResult> Consultar( - BitacoraConsultaModel consulta); + DbResult ConsultarDetalle(long cveBitacora); } } diff --git a/SIG.Web/App_Code/Contracts/Facturacion/ICfdiContracts.cs b/SIG.Web/App_Code/Contracts/Facturacion/ICfdiContracts.cs index 994981e..b303283 100644 --- a/SIG.Web/App_Code/Contracts/Facturacion/ICfdiContracts.cs +++ b/SIG.Web/App_Code/Contracts/Facturacion/ICfdiContracts.cs @@ -52,6 +52,20 @@ namespace SIG.Web.AppCode.Contracts.Facturacion bool timbrado, int cveUsuarioEjecuta, string nombreDominio); + + DbResult IniciarCancelacion( + CfdiCancelacionSolicitudModel solicitud, + Guid idSolicitud, + string proveedorPac, + string ambiente, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult FinalizarCancelacion( + long cveCfdiCancelacion, + CfdiPacCancelacionResultadoModel resultadoPac, + int cveUsuarioEjecuta, + string nombreDominio); } public interface ICfdiXmlBuilder @@ -70,15 +84,24 @@ namespace SIG.Web.AppCode.Contracts.Facturacion CfdiPacSolicitudModel solicitud); } + public interface IPacCancelacionClient + { + string Proveedor { get; } + + CfdiPacCancelacionResultadoModel Cancelar( + CfdiPacCancelacionSolicitudModel solicitud); + } + public interface IPacCredentialProvider { string ObtenerCredencial(string referencia); } - public interface ICfdiTimbradoFinalizadoHandler + public interface IAlmacenArchivosCfdi { - DbResult AlFinalizar( - CfdiTimbradoFinalizadoContext contexto); + DbResult GuardarXmlTimbrado( + CfdiDocumentoModel documento, + CfdiTimbradoIntentoModel intento); } public interface ICfdiTimbradoService @@ -109,5 +132,11 @@ namespace SIG.Web.AppCode.Contracts.Facturacion bool timbrado, int cveUsuarioEjecuta, string nombreDominio); + + DbResult Cancelar( + CfdiCancelacionSolicitudModel solicitud, + Guid? idSolicitud, + int cveUsuarioEjecuta, + string nombreDominio); } } diff --git a/SIG.Web/App_Code/Contracts/General/IProductoCatalogRepository.cs b/SIG.Web/App_Code/Contracts/General/IProductoCatalogRepository.cs new file mode 100644 index 0000000..5f8df3e --- /dev/null +++ b/SIG.Web/App_Code/Contracts/General/IProductoCatalogRepository.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Contracts.General +{ + public interface IProductoCatalogRepository + { + DbResult> ListClasificaciones( + string texto, + bool incluirInactivos, + int usuario, + string dominio); + + DbResult GetClasificacion( + int cveClasificacion, + int usuario, + string dominio); + + DbResult SaveClasificacion( + ClasificacionModel clasificacion, + int usuario, + string dominio); + + DbResult DeleteClasificacion( + int cveClasificacion, + int usuario, + string dominio); + + DbResult> ListUnidadesMedida( + string texto, + bool incluirInactivos, + int usuario, + string dominio); + + DbResult GetUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio); + + DbResult SaveUnidadMedida( + UnidadMedidaModel unidadMedida, + int usuario, + string dominio); + + DbResult DeleteUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/General/IProductoCatalogService.cs b/SIG.Web/App_Code/Contracts/General/IProductoCatalogService.cs new file mode 100644 index 0000000..8c27138 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/General/IProductoCatalogService.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Contracts.General +{ + public interface IProductoCatalogService + { + DbResult> ListClasificaciones( + string texto, + bool incluirInactivos, + int usuario, + string dominio); + + DbResult GetClasificacion( + int cveClasificacion, + int usuario, + string dominio); + + DbResult SaveClasificacion( + ClasificacionModel clasificacion, + int usuario, + string dominio); + + DbResult DeleteClasificacion( + int cveClasificacion, + int usuario, + string dominio); + + DbResult> ListUnidadesMedida( + string texto, + bool incluirInactivos, + int usuario, + string dominio); + + DbResult GetUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio); + + DbResult SaveUnidadMedida( + UnidadMedidaModel unidadMedida, + int usuario, + string dominio); + + DbResult DeleteUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/General/IProductoServicioRepository.cs b/SIG.Web/App_Code/Contracts/General/IProductoServicioRepository.cs new file mode 100644 index 0000000..6fe39b7 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/General/IProductoServicioRepository.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Contracts.General +{ + public interface IProductoServicioRepository + { + DbResult> List( + string texto, + bool incluirInactivos, + int usuario, + string dominio); + + DbResult Get( + int cvePS, + int usuario, + string dominio); + + DbResult ListOptions( + int? cveClasificacionActual, + int? cveUnidadMedidaActual, + int usuario, + string dominio); + + DbResult Save( + ProductoServicioModel productoServicio, + int usuario, + string dominio); + + DbResult Delete( + int cvePS, + int usuario, + string dominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/General/IProductoServicioService.cs b/SIG.Web/App_Code/Contracts/General/IProductoServicioService.cs new file mode 100644 index 0000000..9fcb2a1 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/General/IProductoServicioService.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Contracts.General +{ + public interface IProductoServicioService + { + DbResult> List( + string texto, + bool incluirInactivos, + int usuario, + string dominio); + + DbResult Get( + int cvePS, + int usuario, + string dominio); + + DbResult ListOptions( + int? cveClasificacionActual, + int? cveUnidadMedidaActual, + int usuario, + string dominio); + + DbResult Save( + ProductoServicioModel productoServicio, + int usuario, + string dominio); + + DbResult Delete( + int cvePS, + int usuario, + string dominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Security/IPerfilUsuarioRepository.cs b/SIG.Web/App_Code/Contracts/Security/IPerfilUsuarioRepository.cs new file mode 100644 index 0000000..5287c35 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Security/IPerfilUsuarioRepository.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Security; + +namespace SIG.Web.AppCode.Contracts.Security +{ + public interface IPerfilUsuarioRepository + { + DbResult ObtenerPerfil( + int cveUsuario, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ActualizarSesion( + int cveUsuario, + string nombreUsuario, + string hashContrasena, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ActualizarCliente( + PerfilClienteModel cliente, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> + ListarUsuariosCambio( + string texto, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerUsuarioContexto( + int cveUsuario, + int cveUsuarioEjecuta, + string nombreDominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Security/IPerfilUsuarioService.cs b/SIG.Web/App_Code/Contracts/Security/IPerfilUsuarioService.cs new file mode 100644 index 0000000..da17948 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Security/IPerfilUsuarioService.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Security; +using SIG.Web.AppCode.Session; + +namespace SIG.Web.AppCode.Contracts.Security +{ + public interface IPerfilUsuarioService + { + DbResult ObtenerPerfil( + UserSessionModel usuarioSesion); + + DbResult ActualizarSesion( + UserSessionModel usuarioSesion, + string nombreUsuario, + string contrasena); + + DbResult ActualizarCliente( + UserSessionModel usuarioSesion, + PerfilClienteModel cliente); + + DbResult> + ListarUsuariosCambio( + UserSessionModel usuarioSesion, + string texto); + + DbResult CambiarUsuario( + UserSessionModel usuarioSesion, + int cveUsuarioSeleccionado); + } +} diff --git a/SIG.Web/App_Code/Contracts/Security/IUserContextProvider.cs b/SIG.Web/App_Code/Contracts/Security/IUserContextProvider.cs index a86dc95..788f10b 100644 --- a/SIG.Web/App_Code/Contracts/Security/IUserContextProvider.cs +++ b/SIG.Web/App_Code/Contracts/Security/IUserContextProvider.cs @@ -3,6 +3,9 @@ namespace SIG.Web.AppCode.Contracts.Security { public interface IUserContextProvider { - bool IsAuthenticated(); UserSessionModel GetCurrentUser(); void SetCurrentUser(UserSessionModel user); void Clear(); + bool IsAuthenticated(); + UserSessionModel GetCurrentUser(); + void SetCurrentUser(UserSessionModel user); + void Clear(); } } diff --git a/SIG.Web/App_Code/Contracts/Ventas/IProveedorPagoTarjeta.cs b/SIG.Web/App_Code/Contracts/Ventas/IProveedorPagoTarjeta.cs new file mode 100644 index 0000000..2ac81dc --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Ventas/IProveedorPagoTarjeta.cs @@ -0,0 +1,17 @@ +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Ventas; + +namespace SIG.Web.AppCode.Contracts.Ventas +{ + public interface IProveedorPagoTarjeta + { + string CodigoProveedor { get; } + bool Disponible { get; } + + DbResult CrearSolicitud( + ModeloInicioPortalPagoTarjeta solicitud); + + DbResult ConsultarResultado( + string referenciaProveedor); + } +} diff --git a/SIG.Web/App_Code/Contracts/Ventas/IVentaTramiteRepository.cs b/SIG.Web/App_Code/Contracts/Ventas/IVentaTramiteRepository.cs new file mode 100644 index 0000000..7786247 --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Ventas/IVentaTramiteRepository.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Ventas; + +namespace SIG.Web.AppCode.Contracts.Ventas +{ + public interface IRepositorioVentaTramite + { + DbResult> ListarPagosPendientes( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarPagosRealizados( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerContexto( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarConceptos( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult Generar( + ModeloCapturaVentaTramite venta, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult Pagar( + ModeloPagoVentaTramite pago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerOpcionesPago( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult + ObtenerOpcionesCondicionesPago( + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult GuardarCondicionesPago( + ModeloCondicionesPagoVentaTramite condiciones, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult GuardarConcepto( + ModeloCapturaConceptoVentaTramite concepto, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult EliminarConcepto( + int cveSolicitud, + int cveTramitePago, + int cveVentaDetalle, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerDatosCfdi( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult MarcarTimbrada( + int cveVenta, + long cveCfdiDocumento, + string uuid, + System.DateTime? fechaTimbrado, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult MarcarTimbreCancelado( + int cveVenta, + long cveCfdiDocumento, + string motivo, + int cveUsuarioEjecuta, + string nombreDominio); + } +} diff --git a/SIG.Web/App_Code/Contracts/Ventas/IVentaTramiteService.cs b/SIG.Web/App_Code/Contracts/Ventas/IVentaTramiteService.cs new file mode 100644 index 0000000..5afa2ef --- /dev/null +++ b/SIG.Web/App_Code/Contracts/Ventas/IVentaTramiteService.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Ventas; + +namespace SIG.Web.AppCode.Contracts.Ventas +{ + public interface IServicioVentaTramite + { + DbResult> ListarPagosPendientes( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult> ListarPagosRealizados( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerVenta( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult GenerarVenta( + ModeloCapturaVentaTramite venta, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult PagarVenta( + ModeloPagoVentaTramite pago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult ObtenerOpcionesPago( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult + ObtenerOpcionesCondicionesPago( + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult GuardarCondicionesPago( + ModeloCondicionesPagoVentaTramite condiciones, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult GuardarConcepto( + ModeloCapturaConceptoVentaTramite concepto, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult EliminarConcepto( + int cveSolicitud, + int cveTramitePago, + int cveVentaDetalle, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult TimbrarVenta( + ModeloTimbradoVentaTramite timbrado, + int cveUsuarioEjecuta, + string nombreDominio); + + DbResult CancelarTimbre( + ModeloCancelacionTimbreVentaTramite cancelacion, + int cveUsuarioEjecuta, + string nombreDominio); + } +} diff --git a/SIG.Web/App_Code/Models/Facturacion/CfdiModels.cs b/SIG.Web/App_Code/Models/Facturacion/CfdiModels.cs index 841e3c6..d34c87b 100644 --- a/SIG.Web/App_Code/Models/Facturacion/CfdiModels.cs +++ b/SIG.Web/App_Code/Models/Facturacion/CfdiModels.cs @@ -10,6 +10,7 @@ namespace SIG.Web.AppCode.Models.Facturacion public const string Timbrado = "TIMBRADO"; public const string Error = "ERROR"; public const string Revisar = "REVISAR"; + public const string Cancelado = "CANCELADO"; } public static class CfdiIntentoEstados @@ -239,6 +240,55 @@ namespace SIG.Web.AppCode.Models.Facturacion public byte[] CodigoBidimensional { get; set; } } + public sealed class CfdiCancelacionSolicitudModel + { + public long CveCfdiDocumento { get; set; } + public string Motivo { get; set; } + public string UuidSustitucion { get; set; } + } + + public sealed class CfdiCancelacionInicioModel + { + public long CveCfdiCancelacion { get; set; } + public long CveCfdiDocumento { get; set; } + public long CveCfdiTimbrado { get; set; } + public System.Guid IdSolicitud { get; set; } + public string RfcEmisor { get; set; } + public string Uuid { get; set; } + public string Motivo { get; set; } + public string UuidSustitucion { get; set; } + public bool PuedeEnviar { get; set; } + } + + public sealed class CfdiPacCancelacionSolicitudModel + { + public string RfcEmisor { get; set; } + public string Uuid { get; set; } + public string Motivo { get; set; } + public string UuidSustitucion { get; set; } + public bool AmbienteProduccion { get; set; } + public string ReferenciaCredencialPac { get; set; } + } + + public sealed class CfdiPacCancelacionResultadoModel + { + public bool Exitoso { get; set; } + public bool ResultadoIndeterminado { get; set; } + public string CodigoRespuesta { get; set; } + public string MensajeRespuesta { get; set; } + public string TipoExcepcion { get; set; } + } + + public sealed class CfdiCancelacionResultadoModel + { + public long CveCfdiDocumento { get; set; } + public long CveCfdiCancelacion { get; set; } + public bool CancelacionExitosa { get; set; } + public string Estado { get; set; } + public string CodigoRespuesta { get; set; } + public string Mensaje { get; set; } + } + public sealed class CfdiTimbradoResultadoModel { public long CveCfdiDocumento { get; set; } @@ -263,11 +313,4 @@ namespace SIG.Web.AppCode.Models.Facturacion public byte[] HashSha256 { get; set; } } - public sealed class CfdiTimbradoFinalizadoContext - { - public CfdiDocumentoModel Documento { get; set; } - public CfdiTimbradoIntentoModel Intento { get; set; } - public int CveUsuarioEjecuta { get; set; } - public string NombreDominio { get; set; } - } } diff --git a/SIG.Web/App_Code/Models/General/ProductoCatalogModels.cs b/SIG.Web/App_Code/Models/General/ProductoCatalogModels.cs new file mode 100644 index 0000000..476602b --- /dev/null +++ b/SIG.Web/App_Code/Models/General/ProductoCatalogModels.cs @@ -0,0 +1,19 @@ +namespace SIG.Web.AppCode.Models.General +{ + public sealed class ClasificacionModel + { + public int CveClasificacion { get; set; } + public string Codigo { get; set; } + public string Clasificacion { get; set; } + public bool Afectable { get; set; } + public bool EsActivo { get; set; } + } + + public sealed class UnidadMedidaModel + { + public int CveUnidadMedida { get; set; } + public string UnidadMedida { get; set; } + public string Abreviatura { get; set; } + public bool EsActivo { get; set; } + } +} diff --git a/SIG.Web/App_Code/Models/General/ProductoServicioModels.cs b/SIG.Web/App_Code/Models/General/ProductoServicioModels.cs new file mode 100644 index 0000000..e964683 --- /dev/null +++ b/SIG.Web/App_Code/Models/General/ProductoServicioModels.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; + +namespace SIG.Web.AppCode.Models.General +{ + [System.Serializable] + public sealed class ProductoServicioModel + { + public int CvePS { get; set; } + public string Codigo { get; set; } + public string PS { get; set; } + public int CveTipoPS { get; set; } + public string TipoPS { get; set; } + public int CveClasificacion { get; set; } + public string Clasificacion { get; set; } + public int CveUnidadMedida { get; set; } + public string UnidadMedida { get; set; } + public decimal Precio { get; set; } + public bool EsActivo { get; set; } + } + + public sealed class ProductoServicioOpcionesModel + { + public ProductoServicioOpcionesModel() + { + Clasificaciones = new List(); + UnidadesMedida = new List(); + } + + public List Clasificaciones + { + get; + set; + } + + public List UnidadesMedida + { + get; + set; + } + } + + public sealed class ClasificacionProductoOpcionModel + { + public int CveClasificacion { get; set; } + public string Clasificacion { get; set; } + } + + public sealed class UnidadMedidaOpcionModel + { + public int CveUnidadMedida { get; set; } + public string UnidadMedida { get; set; } + } +} diff --git a/SIG.Web/App_Code/Models/Security/PerfilUsuarioModels.cs b/SIG.Web/App_Code/Models/Security/PerfilUsuarioModels.cs new file mode 100644 index 0000000..fa23d9c --- /dev/null +++ b/SIG.Web/App_Code/Models/Security/PerfilUsuarioModels.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; + +namespace SIG.Web.AppCode.Models.Security +{ + [Serializable] + public sealed class PerfilSesionModel + { + public int CveUsuario { get; set; } + public string NombreUsuario { get; set; } + public string CorreoElectronico { get; set; } + public int CveRol { get; set; } + public string NombreRol { get; set; } + public int CveCliente { get; set; } + public bool EsDesarrollador { get; set; } + } + + [Serializable] + public sealed class PerfilClienteModel + { + public int CveCliente { get; set; } + public string Nombre { get; set; } + public string NombreComercial { get; set; } + public string Direccion { get; set; } + public string NoExt { get; set; } + public string NoInt { get; set; } + public string Colonia { get; set; } + public string Ciudad { get; set; } + public string Estado { get; set; } + public string Pais { get; set; } + public string RFC { get; set; } + public string CP { get; set; } + public string Telefono { get; set; } + public string Mail { get; set; } + public int CveRegimenFiscal { get; set; } + public string CodigoRegimenFiscal { get; set; } + public string RegimenFiscal { get; set; } + public int CveUsoCFDI { get; set; } + public string UsoCFDI { get; set; } + public string DescripcionUsoCFDI { get; set; } + } + + [Serializable] + public sealed class RegimenFiscalPerfilOpcionModel + { + public int CveRegimenFiscal { get; set; } + public string CodigoRegimenFiscal { get; set; } + public string RegimenFiscal { get; set; } + + public string Descripcion + { + get + { + return CodigoRegimenFiscal + " - " + RegimenFiscal; + } + } + } + + [Serializable] + public sealed class UsoCfdiPerfilOpcionModel + { + public int CveUsoCFDI { get; set; } + public string UsoCFDI { get; set; } + public string Descripcion { get; set; } + + public string DescripcionCompleta + { + get { return UsoCFDI + " - " + Descripcion; } + } + } + + [Serializable] + public sealed class PerfilUsuarioConsultaModel + { + public PerfilUsuarioConsultaModel() + { + RegimenesFiscales = + new List(); + UsosCfdi = new List(); + } + + public PerfilSesionModel Sesion { get; set; } + public PerfilClienteModel Cliente { get; set; } + public List + RegimenesFiscales { get; set; } + public List UsosCfdi { get; set; } + } + + [Serializable] + public sealed class UsuarioCambioContextoModel + { + public int CveUsuario { get; set; } + public string NombreUsuario { get; set; } + public string CorreoElectronico { get; set; } + public int CveRol { get; set; } + public string NombreRol { get; set; } + public bool DebeCambiarContrasena { get; set; } + public int CveCliente { get; set; } + public string Cliente { get; set; } + } +} diff --git a/SIG.Web/App_Code/Models/Security/UserModel.cs b/SIG.Web/App_Code/Models/Security/UserModel.cs index 889c46c..649f413 100644 --- a/SIG.Web/App_Code/Models/Security/UserModel.cs +++ b/SIG.Web/App_Code/Models/Security/UserModel.cs @@ -8,10 +8,12 @@ namespace SIG.Web.AppCode.Models.Security public string HashContrasena { get; set; } public string CorreoElectronico { get; set; } public int CveRol { get; set; } + public int CveCliente { get; set; } public string NombreRol { get; set; } public bool Activo { get; set; } public bool CorreoVerificado { get; set; } - public bool DebeCambiarContrasena { get; set; } public int IntentosFallidosInicioSesion { get; set; } + public bool DebeCambiarContrasena { get; set; } + public int IntentosFallidosInicioSesion { get; set; } public DateTime? BloqueadoHasta { get; set; } public DateTime? FechaUltimoInicioSesion { get; set; } public DateTime? FechaUltimaConexion { get; set; } diff --git a/SIG.Web/App_Code/Models/Tramites/TramiteCatalogModels.cs b/SIG.Web/App_Code/Models/Tramites/TramiteCatalogModels.cs index c74fce0..93b3286 100644 --- a/SIG.Web/App_Code/Models/Tramites/TramiteCatalogModels.cs +++ b/SIG.Web/App_Code/Models/Tramites/TramiteCatalogModels.cs @@ -1,3 +1,5 @@ +using System; + namespace SIG.Web.AppCode.Models.Tramites { public enum TramiteCatalogOrderEntity @@ -124,16 +126,33 @@ namespace SIG.Web.AppCode.Models.Tramites public int CvePS { get; set; } public string Codigo { get; set; } public string PS { get; set; } + public int CveUM { get; set; } + public string UnidadMedida { get; set; } + public string Abreviatura { get; set; } public decimal Cantidad { get; set; } public decimal Precio { get; set; } public decimal Total { get; set; } + + public string UnidadMedidaTexto + { + get + { + return string.IsNullOrWhiteSpace(Abreviatura) + ? UnidadMedida + : UnidadMedida + " (" + Abreviatura.Trim() + ")"; + } + } } + [Serializable] public sealed class ProductoServicioTramiteModel { public int CvePS { get; set; } public string Codigo { get; set; } public string PS { get; set; } + public int CveUnidadMedida { get; set; } + public string UnidadMedida { get; set; } + public string Abreviatura { get; set; } public decimal Precio { get; set; } public bool EsActivo { get; set; } @@ -151,4 +170,5 @@ namespace SIG.Web.AppCode.Models.Tramites return codigo + PS + estado; } } - }} + } +} diff --git a/SIG.Web/App_Code/Models/Ventas/PagoTarjetaModels.cs b/SIG.Web/App_Code/Models/Ventas/PagoTarjetaModels.cs new file mode 100644 index 0000000..21c3150 --- /dev/null +++ b/SIG.Web/App_Code/Models/Ventas/PagoTarjetaModels.cs @@ -0,0 +1,28 @@ +using System; + +namespace SIG.Web.AppCode.Models.Ventas +{ + public sealed class ModeloInicioPortalPagoTarjeta + { + public int CveVenta { get; set; } + public int CvePago { get; set; } + public decimal Importe { get; set; } + public string Referencia { get; set; } + public string UrlRetorno { get; set; } + } + + public sealed class ModeloSolicitudPortalPagoTarjeta + { + public string ReferenciaProveedor { get; set; } + public string UrlRedireccion { get; set; } + public DateTime? FechaExpiracion { get; set; } + } + + public sealed class ModeloResultadoPortalPagoTarjeta + { + public string ReferenciaProveedor { get; set; } + public bool Autorizado { get; set; } + public string CodigoAutorizacion { get; set; } + public string Mensaje { get; set; } + } +} diff --git a/SIG.Web/App_Code/Models/Ventas/VentaTramiteModels.cs b/SIG.Web/App_Code/Models/Ventas/VentaTramiteModels.cs new file mode 100644 index 0000000..30df634 --- /dev/null +++ b/SIG.Web/App_Code/Models/Ventas/VentaTramiteModels.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; + +namespace SIG.Web.AppCode.Models.Ventas +{ + public sealed class ModeloPagoPendienteFraccionamiento + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public int? CveVenta { get; set; } + public bool VentaGenerada { get; set; } + public string FolioSolicitud { get; set; } + public string Etapa { get; set; } + public string TipoTramite { get; set; } + public string NombrePago { get; set; } + public int NumeroConceptos { get; set; } + public decimal SubTotal { get; set; } + public decimal IVA { get; set; } + public decimal Total { get; set; } + } + + public sealed class ModeloPagoRealizadoFraccionamiento + { + public int CveSolicitudPago { get; set; } + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public int CveVenta { get; set; } + public int CvePago { get; set; } + public string SerieFolio { get; set; } + public DateTime Fecha { get; set; } + public DateTime FechaPago { get; set; } + public string Referencia { get; set; } + public bool Autorizado { get; set; } + public DateTime? FechaAutorizacion { get; set; } + public string FolioSolicitud { get; set; } + public string Etapa { get; set; } + public string TipoTramite { get; set; } + public string NombrePago { get; set; } + public decimal SubTotal { get; set; } + public decimal IVA { get; set; } + public decimal Total { get; set; } + } + + public sealed class ModeloContextoVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public int? CveVenta { get; set; } + public int? CvePago { get; set; } + public bool VentaGenerada { get; set; } + public bool VentaPagada { get; set; } + public bool PagoPendienteAutorizacion { get; set; } + public string ReferenciaPago { get; set; } + public long? CveCfdiDocumento { get; set; } + public bool VentaTimbrada { get; set; } + public bool TimbreCancelado { get; set; } + public string UuidTimbre { get; set; } + public int CveFraccionamiento { get; set; } + public string Fraccionamiento { get; set; } + public int CveCliente { get; set; } + public string Cliente { get; set; } + public string RFC { get; set; } + public string Direccion { get; set; } + public string Colonia { get; set; } + public string CiudadEstado { get; set; } + public string CP { get; set; } + public string Telefono { get; set; } + public string Mail { get; set; } + public string FolioSolicitud { get; set; } + public string Etapa { get; set; } + public string TipoTramite { get; set; } + public string NombrePago { get; set; } + public string TipoDocumento { get; set; } + public string Serie { get; set; } + public int Folio { get; set; } + public DateTime Fecha { get; set; } + public int CveMetodoPago { get; set; } + public byte CveFormaPago { get; set; } + public DateTime? FechaVencimiento { get; set; } + public List Conceptos { get; set; } + } + + public sealed class ModeloConceptoVentaTramite + { + public int CveVentaDetalle { get; set; } + public int CveTramitePagoDetalle { get; set; } + public int CvePS { get; set; } + public int CveUM { get; set; } + public string UnidadMedida { get; set; } + public int CveClasificacion { get; set; } + public string Clasificacion { get; set; } + public string ProductoServicio { get; set; } + public decimal Cantidad { get; set; } + public decimal PrecioUnitario { get; set; } + public decimal Descuento { get; set; } + public decimal IVA { get; set; } + public decimal Importe { get; set; } + } + + public sealed class ModeloCapturaConceptoVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public int CveVentaDetalle { get; set; } + public int CvePS { get; set; } + public decimal Cantidad { get; set; } + public decimal PrecioUnitario { get; set; } + } + + public sealed class ModeloDatosCfdiVentaTramite + { + public ModeloDatosCfdiVentaTramite() + { + Conceptos = new List(); + } + + public int CveVenta { get; set; } + public long? CveCfdiDocumento { get; set; } + public int CveCliente { get; set; } + public string Serie { get; set; } + public int Folio { get; set; } + public DateTime Fecha { get; set; } + public string FormaPago { get; set; } + public string MetodoPago { get; set; } + public string Moneda { get; set; } + public decimal TipoCambio { get; set; } + public List Conceptos { get; set; } + } + + public sealed class ModeloConceptoCfdiVentaTramite + { + public string ClaveProductoServicio { get; set; } + public string NumeroIdentificacion { get; set; } + public decimal Cantidad { get; set; } + public string ClaveUnidad { get; set; } + public string Unidad { get; set; } + public string Descripcion { get; set; } + public decimal ValorUnitario { get; set; } + public decimal Descuento { get; set; } + public string ObjetoImpuesto { get; set; } + public decimal BaseIVA { get; set; } + public decimal TasaIVA { get; set; } + public decimal ImporteIVA { get; set; } + } + + public sealed class ModeloTimbradoVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public int CveEmpresa { get; set; } + } + + public sealed class ModeloCancelacionTimbreVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public string Motivo { get; set; } + public string UuidSustitucion { get; set; } + } + + public sealed class ModeloCapturaVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public string Observaciones { get; set; } + } + + public sealed class ModeloPagoVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public decimal Importe { get; set; } + public DateTime FechaPago { get; set; } + public byte CveFormaPago { get; set; } + public int? CveBancoCuenta { get; set; } + public string Observaciones { get; set; } + } + + public sealed class ModeloPagoRegistradoVentaTramite + { + public int CvePago { get; set; } + public string Referencia { get; set; } + public bool Autorizado { get; set; } + } + + [Serializable] + public sealed class ModeloFormaPagoOpcion + { + public byte CveFormaPago { get; set; } + public string FormaPago { get; set; } + public string ClaveFormaPagoSAT { get; set; } + public bool Disponible { get; set; } + } + + [Serializable] + public sealed class ModeloCuentaBancariaOpcion + { + public int CveBancoCuenta { get; set; } + public string Banco { get; set; } + public string NumeroCuenta { get; set; } + public string CLABE { get; set; } + public string CuentaBancaria { get; set; } + } + + [Serializable] + public sealed class ModeloOpcionesPagoVentaTramite + { + public ModeloOpcionesPagoVentaTramite() + { + FormasPago = new List(); + CuentasBancarias = new List(); + } + + public int CveVenta { get; set; } + public string ReferenciaPago { get; set; } + public List FormasPago { get; set; } + public List CuentasBancarias { get; set; } + } + + public sealed class ModeloCondicionesPagoVentaTramite + { + public int CveSolicitud { get; set; } + public int CveTramitePago { get; set; } + public int CveMetodoPago { get; set; } + public byte CveFormaPago { get; set; } + public DateTime FechaVencimiento { get; set; } + } + + public sealed class ModeloMetodoPagoOpcion + { + public int CveMetodoPago { get; set; } + public string MetodoPago { get; set; } + public string ClaveMetodoPagoSAT { get; set; } + public string Descripcion { get; set; } + } + + public sealed class ModeloOpcionesCondicionesPagoVentaTramite + { + public ModeloOpcionesCondicionesPagoVentaTramite() + { + MetodosPago = new List(); + FormasPago = new List(); + } + + public List MetodosPago { get; set; } + public List FormasPago { get; set; } + } +} diff --git a/SIG.Web/App_Code/Repositories/Bitacora/BitacoraRepository.cs b/SIG.Web/App_Code/Repositories/Bitacora/BitacoraRepository.cs index a3611a6..7fc751e 100644 --- a/SIG.Web/App_Code/Repositories/Bitacora/BitacoraRepository.cs +++ b/SIG.Web/App_Code/Repositories/Bitacora/BitacoraRepository.cs @@ -186,7 +186,7 @@ namespace SIG.Web.AppCode.Repositories.Bitacora { StoredProcedureCommand.Configure( command, - "dbo.PA_Bit_BitacoraListByRelations", + "dbo.PA_Bit_BitacoraResumenListByRelations", cveUsuarioEjecuta); StoredProcedureCommand.AddInput( @@ -228,19 +228,6 @@ namespace SIG.Web.AppCode.Repositories.Bitacora bitacoras = reader.ToList(); } - // El procedimiento actual devuelve Campos y Relaciones - // antes de RelacionesMostrar. En el resumen se omiten - // ambos result sets para no materializar el detalle. - if (reader.NextResult()) - { - // Campos: se descartan en el listado. - } - - if (reader.NextResult()) - { - // Relaciones internas: se descartan en el listado. - } - if (reader.NextResult()) { relacionesMostrar = @@ -267,97 +254,46 @@ namespace SIG.Web.AppCode.Repositories.Bitacora }); } - public DbResult> Consultar( - BitacoraConsultaModel consulta, + public DbResult ConsultarDetalle( + long cveBitacora, int cveUsuarioEjecuta) { - int registrosOmitidos = checked( - (consulta.Pagina - 1) * consulta.RegistrosPorPagina); - return ExecuteCustom(BitacoraDomain, connection => { using (IDbCommand command = connection.CreateCommand()) { StoredProcedureCommand.Configure( command, - "dbo.PA_Bit_BitacoraListByRelations", + "dbo.PA_Bit_BitacoraDetalleGet", cveUsuarioEjecuta); StoredProcedureCommand.AddInput( command, - "@RelacionesXml", - SerializeFilters(consulta.Filtros), - DbType.Xml); - StoredProcedureCommand.AddInput( - command, - "@RelacionesMostrarXml", - SerializeRelationsToShow( - consulta.RelacionesMostrar), - DbType.Xml); - StoredProcedureCommand.AddInput( - command, - "@RegistrosOmitidos", - registrosOmitidos, - DbType.Int32); - StoredProcedureCommand.AddInput( - command, - "@RegistrosPorPagina", - consulta.RegistrosPorPagina, - DbType.Int32); + "@CveBitacora", + cveBitacora, + DbType.Int64); - int totalRegistros = 0; - var bitacoras = new List(); + BitacoraModel bitacora = null; var campos = new List(); - var relaciones = new List(); - var relacionesMostrar = - new List(); using (IDataReader reader = command.ExecuteReader()) { - if (reader.Read() && !reader.IsDBNull(0)) - { - totalRegistros = reader.GetInt32(0); - } - - if (reader.NextResult()) - { - bitacoras = reader.ToList(); - } + bitacora = reader.ToObject(); if (reader.NextResult()) { campos = reader.ToList(); } - - if (reader.NextResult()) - { - relaciones = reader.ToList(); - } - - if (reader.NextResult()) - { - relacionesMostrar = - reader.ToList(); - } } StoredProcedureCommand.EnsureSuccess(command); - AsociarResultados( - bitacoras, - campos, - relaciones, - relacionesMostrar); - return new ResultadoPaginado + if (bitacora != null) { - Registros = bitacoras, - Pagina = consulta.Pagina, - RegistrosPorPagina = consulta.RegistrosPorPagina, - TotalRegistros = totalRegistros, - TotalPaginas = (int)Math.Ceiling( - totalRegistros / - (decimal)consulta.RegistrosPorPagina) - }; + bitacora.Campos = campos; + } + + return bitacora; } }); } diff --git a/SIG.Web/App_Code/Repositories/Database/DbExecutor.cs b/SIG.Web/App_Code/Repositories/Database/DbExecutor.cs index ade9ffa..ec7b79d 100644 --- a/SIG.Web/App_Code/Repositories/Database/DbExecutor.cs +++ b/SIG.Web/App_Code/Repositories/Database/DbExecutor.cs @@ -60,8 +60,9 @@ namespace SIG.Web.AppCode.Repositories.Database return DbResult.Ok(data); } catch (StoredProcedureException ex) - { - ExceptionLogger.Log(CreateDiagnosticException(ex), "DbExecutor.StoredProcedure", ex.UserMessage); + { + string diagnostic = StoredProcedureDiagnostics.BuildDiagnostic(); + ExceptionLogger.Log(CreateDiagnosticException(ex), "DbExecutor.StoredProcedure", ex.UserMessage + diagnostic); return DbResult.Fail(ex.UserMessage, BuildTechnicalMessage(ex), ex); } catch (SqlException ex) diff --git a/SIG.Web/App_Code/Repositories/Database/StoredProcedureDiagnostics.cs b/SIG.Web/App_Code/Repositories/Database/StoredProcedureDiagnostics.cs index 09fed3f..ff989af 100644 --- a/SIG.Web/App_Code/Repositories/Database/StoredProcedureDiagnostics.cs +++ b/SIG.Web/App_Code/Repositories/Database/StoredProcedureDiagnostics.cs @@ -192,7 +192,7 @@ namespace SIG.Web.AppCode.Repositories.Database if (value is byte[]) { byte[] bytes = (byte[])value; - int length = Math.Min(bytes.Length, 64); + int length = Math.Min(bytes.Length, 64000); return "0x" + BitConverter.ToString(bytes, 0, length).Replace("-", string.Empty) + (bytes.Length > length ? "/*TRUNCADO*/" : string.Empty); } @@ -200,11 +200,7 @@ namespace SIG.Web.AppCode.Repositories.Database if (value is string || value is char) { string text = Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty; - - if (text.Length > 1000) - { - text = text.Substring(0, 1000) + " [TRUNCADO]"; - } + return "N'" + text.Replace("'", "''") + "'"; } diff --git a/SIG.Web/App_Code/Repositories/Facturacion/CfdiRepository.cs b/SIG.Web/App_Code/Repositories/Facturacion/CfdiRepository.cs index 7340b79..a0dc130 100644 --- a/SIG.Web/App_Code/Repositories/Facturacion/CfdiRepository.cs +++ b/SIG.Web/App_Code/Repositories/Facturacion/CfdiRepository.cs @@ -441,6 +441,98 @@ namespace SIG.Web.AppCode.Repositories.Facturacion }); } + public DbResult IniciarCancelacion( + CfdiCancelacionSolicitudModel solicitud, + System.Guid idSolicitud, + string proveedorPac, + string ambiente, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Fac_CfdiCancelacionAttemptStart", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCfdiDocumento", + solicitud.CveCfdiDocumento, + DbType.Int64); + StoredProcedureCommand.AddInput( + comando, + "@IdSolicitud", + idSolicitud, + DbType.Guid); + StoredProcedureCommand.AddInput( + comando, + "@ProveedorPac", + proveedorPac, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Ambiente", + ambiente, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Motivo", + solicitud.Motivo, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@UuidSustitucion", + solicitud.UuidSustitucion, + DbType.String); + }); + } + + public DbResult FinalizarCancelacion( + long cveCfdiCancelacion, + CfdiPacCancelacionResultadoModel resultadoPac, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Fac_CfdiCancelacionAttemptComplete", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveCfdiCancelacion", + cveCfdiCancelacion, + DbType.Int64); + StoredProcedureCommand.AddInput( + comando, + "@Exitoso", + resultadoPac.Exitoso, + DbType.Boolean); + StoredProcedureCommand.AddInput( + comando, + "@ResultadoIndeterminado", + resultadoPac.ResultadoIndeterminado, + DbType.Boolean); + StoredProcedureCommand.AddInput( + comando, + "@CodigoRespuesta", + resultadoPac.CodigoRespuesta, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@MensajeRespuesta", + resultadoPac.MensajeRespuesta, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@TipoExcepcion", + resultadoPac.TipoExcepcion, + DbType.String); + }); + } + private static void Add( IDbCommand command, string name, diff --git a/SIG.Web/App_Code/Repositories/General/ProductoCatalogRepository.cs b/SIG.Web/App_Code/Repositories/General/ProductoCatalogRepository.cs new file mode 100644 index 0000000..1a1e17e --- /dev/null +++ b/SIG.Web/App_Code/Repositories/General/ProductoCatalogRepository.cs @@ -0,0 +1,207 @@ +using System.Collections.Generic; +using System.Data; +using SIG.Web.AppCode.Contracts.Database; +using SIG.Web.AppCode.Contracts.General; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; +using SIG.Web.AppCode.Repositories.Database; + +namespace SIG.Web.AppCode.Repositories.General +{ + public sealed class ProductoCatalogRepository + : RepositoryBase, IProductoCatalogRepository + { + public ProductoCatalogRepository(IDbExecutor dbExecutor) + : base(dbExecutor) + { + } + + public DbResult> ListClasificaciones( + string texto, + bool incluirInactivos, + int usuario, + string dominio) + { + return QueryList( + "dbo.PA_Gral_ClasificacionList", + usuario, + dominio, + command => + { + Add(command, "@Texto", texto, DbType.String); + Add( + command, + "@IncluirInactivos", + incluirInactivos, + DbType.Boolean); + }); + } + + public DbResult GetClasificacion( + int cveClasificacion, + int usuario, + string dominio) + { + return QueryOne( + "dbo.PA_Gral_ClasificacionGet", + usuario, + dominio, + command => Add( + command, + "@CveClasificacion", + cveClasificacion, + DbType.Int32)); + } + + public DbResult SaveClasificacion( + ClasificacionModel clasificacion, + int usuario, + string dominio) + { + return QueryScalarId( + "dbo.PA_Gral_ClasificacionSave", + usuario, + dominio, + command => + { + Add( + command, + "@CveClasificacion", + clasificacion.CveClasificacion > 0 + ? (object)clasificacion.CveClasificacion + : null, + DbType.Int32); + Add(command, "@Codigo", clasificacion.Codigo, DbType.String); + Add( + command, + "@Clasificacion", + clasificacion.Clasificacion, + DbType.String); + Add( + command, + "@Afectable", + clasificacion.Afectable, + DbType.Boolean); + Add( + command, + "@EsActivo", + clasificacion.EsActivo, + DbType.Boolean); + }); + } + + public DbResult DeleteClasificacion( + int cveClasificacion, + int usuario, + string dominio) + { + return Execute( + "dbo.PA_Gral_ClasificacionDelete", + usuario, + dominio, + command => Add( + command, + "@CveClasificacion", + cveClasificacion, + DbType.Int32)); + } + + public DbResult> ListUnidadesMedida( + string texto, + bool incluirInactivos, + int usuario, + string dominio) + { + return QueryList( + "dbo.PA_Gral_UnidadMedidaList", + usuario, + dominio, + command => + { + Add(command, "@Texto", texto, DbType.String); + Add( + command, + "@IncluirInactivos", + incluirInactivos, + DbType.Boolean); + }); + } + + public DbResult GetUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio) + { + return QueryOne( + "dbo.PA_Gral_UnidadMedidaGet", + usuario, + dominio, + command => Add( + command, + "@CveUnidadMedida", + cveUnidadMedida, + DbType.Int32)); + } + + public DbResult SaveUnidadMedida( + UnidadMedidaModel unidadMedida, + int usuario, + string dominio) + { + return QueryScalarId( + "dbo.PA_Gral_UnidadMedidaSave", + usuario, + dominio, + command => + { + Add( + command, + "@CveUnidadMedida", + unidadMedida.CveUnidadMedida > 0 + ? (object)unidadMedida.CveUnidadMedida + : null, + DbType.Int32); + Add( + command, + "@UnidadMedida", + unidadMedida.UnidadMedida, + DbType.String); + Add( + command, + "@Abreviatura", + unidadMedida.Abreviatura, + DbType.String); + Add( + command, + "@EsActivo", + unidadMedida.EsActivo, + DbType.Boolean); + }); + } + + public DbResult DeleteUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio) + { + return Execute( + "dbo.PA_Gral_UnidadMedidaDelete", + usuario, + dominio, + command => Add( + command, + "@CveUnidadMedida", + cveUnidadMedida, + DbType.Int32)); + } + + private static void Add( + IDbCommand command, + string name, + object value, + DbType type) + { + StoredProcedureCommand.AddInput(command, name, value, type); + } + } +} diff --git a/SIG.Web/App_Code/Repositories/General/ProductoServicioRepository.cs b/SIG.Web/App_Code/Repositories/General/ProductoServicioRepository.cs new file mode 100644 index 0000000..82b84b6 --- /dev/null +++ b/SIG.Web/App_Code/Repositories/General/ProductoServicioRepository.cs @@ -0,0 +1,171 @@ +using System.Collections.Generic; +using System.Data; +using SIG.Web.AppCode.Contracts.Database; +using SIG.Web.AppCode.Contracts.General; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; +using SIG.Web.AppCode.Repositories.Database; +using SIG.Web.AppCode.Utilities; + +namespace SIG.Web.AppCode.Repositories.General +{ + public sealed class ProductoServicioRepository + : RepositoryBase, IProductoServicioRepository + { + public ProductoServicioRepository(IDbExecutor dbExecutor) + : base(dbExecutor) + { + } + + public DbResult> List( + string texto, + bool incluirInactivos, + int usuario, + string dominio) + { + return QueryList( + "dbo.PA_Gral_ProductoServicioList", + usuario, + dominio, + command => + { + Add(command, "@Texto", texto, DbType.String); + Add( + command, + "@IncluirInactivos", + incluirInactivos, + DbType.Boolean); + }); + } + + public DbResult Get( + int cvePS, + int usuario, + string dominio) + { + return QueryOne( + "dbo.PA_Gral_ProductoServicioGet", + usuario, + dominio, + command => Add(command, "@CvePS", cvePS, DbType.Int32)); + } + + public DbResult ListOptions( + int? cveClasificacionActual, + int? cveUnidadMedidaActual, + int usuario, + string dominio) + { + return QueryReader( + "dbo.PA_Gral_ProductoServicioOpcionesList", + usuario, + dominio, + command => + { + Add( + command, + "@CveClasificacionActual", + cveClasificacionActual, + DbType.Int32); + Add( + command, + "@CveUnidadMedidaActual", + cveUnidadMedidaActual, + DbType.Int32); + }, + reader => + { + var options = new ProductoServicioOpcionesModel + { + Clasificaciones = + reader.ToList() + }; + + if (reader.NextResult()) + { + options.UnidadesMedida = + reader.ToList(); + } + + return options; + }); + } + + public DbResult Save( + ProductoServicioModel productoServicio, + int usuario, + string dominio) + { + return QueryScalarId( + "dbo.PA_Gral_ProductoServicioSave", + usuario, + dominio, + command => + { + Add( + command, + "@CvePS", + productoServicio.CvePS > 0 + ? (object)productoServicio.CvePS + : null, + DbType.Int32); + Add( + command, + "@Codigo", + productoServicio.Codigo, + DbType.String); + Add(command, "@PS", productoServicio.PS, DbType.String); + Add( + command, + "@CveTipoPS", + productoServicio.CveTipoPS, + DbType.Int32); + Add( + command, + "@CveClasificacion", + productoServicio.CveClasificacion, + DbType.Int32); + Add( + command, + "@CveUnidadMedida", + productoServicio.CveUnidadMedida, + DbType.Int32); + Add( + command, + "@Precio", + productoServicio.Precio, + DbType.Decimal); + Add( + command, + "@EsActivo", + productoServicio.EsActivo, + DbType.Boolean); + }); + } + + public DbResult Delete( + int cvePS, + int usuario, + string dominio) + { + return Execute( + "dbo.PA_Gral_ProductoServicioDelete", + usuario, + dominio, + command => Add( + command, + "@CvePS", + cvePS, + DbType.Int32)); + } + + private static void Add( + IDbCommand command, + string name, + object value, + DbType type) + { + StoredProcedureCommand.AddInput(command, name, value, type); + } + } +} diff --git a/SIG.Web/App_Code/Repositories/Security/PerfilUsuarioRepository.cs b/SIG.Web/App_Code/Repositories/Security/PerfilUsuarioRepository.cs new file mode 100644 index 0000000..fc5a051 --- /dev/null +++ b/SIG.Web/App_Code/Repositories/Security/PerfilUsuarioRepository.cs @@ -0,0 +1,228 @@ +using System.Collections.Generic; +using System.Data; +using SIG.Web.AppCode.Contracts.Database; +using SIG.Web.AppCode.Contracts.Security; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Security; +using SIG.Web.AppCode.Repositories.Database; +using SIG.Web.AppCode.Utilities; + +namespace SIG.Web.AppCode.Repositories.Security +{ + public sealed class PerfilUsuarioRepository + : RepositoryBase, IPerfilUsuarioRepository + { + public PerfilUsuarioRepository(IDbExecutor ejecutorBaseDatos) + : base(ejecutorBaseDatos) + { + } + + public DbResult ObtenerPerfil( + int cveUsuario, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryReader( + "dbo.PA_Sis_PerfilGet", + cveUsuarioEjecuta, + nombreDominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@CveUsuario", + cveUsuario, + DbType.Int32), + lector => + { + var perfil = new PerfilUsuarioConsultaModel + { + Sesion = lector.ToObject() + }; + + if (lector.NextResult()) + { + perfil.Cliente = + lector.ToObject(); + } + + if (lector.NextResult()) + { + perfil.RegimenesFiscales = lector.ToList< + RegimenFiscalPerfilOpcionModel>(); + } + + if (lector.NextResult()) + { + perfil.UsosCfdi = + lector.ToList(); + } + + return perfil; + }); + } + + public DbResult ActualizarSesion( + int cveUsuario, + string nombreUsuario, + string hashContrasena, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Sis_PerfilSesionUpdate", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveUsuario", + cveUsuario, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@NombreUsuario", + nombreUsuario, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@HashContrasena", + hashContrasena, + DbType.String); + }); + } + + public DbResult ActualizarCliente( + PerfilClienteModel cliente, + int cveUsuarioEjecuta, + string nombreDominio) + { + return Execute( + "dbo.PA_Clientes_PerfilUpdate", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + AgregarDatosCliente(comando, cliente); + }); + } + + public DbResult> + ListarUsuariosCambio( + string texto, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryList( + "dbo.PA_Sis_UsuarioContextoList", + cveUsuarioEjecuta, + nombreDominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@Texto", + texto, + DbType.String)); + } + + public DbResult ObtenerUsuarioContexto( + int cveUsuario, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Sis_UsuarioContextoGet", + cveUsuarioEjecuta, + nombreDominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@CveUsuario", + cveUsuario, + DbType.Int32)); + } + + private static void AgregarDatosCliente( + IDbCommand comando, + PerfilClienteModel cliente) + { + StoredProcedureCommand.AddInput( + comando, + "@CveCliente", + cliente.CveCliente, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Nombre", + cliente.Nombre, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NombreComercial", + cliente.NombreComercial, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Direccion", + cliente.Direccion, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NoExt", + cliente.NoExt, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@NoInt", + cliente.NoInt, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Colonia", + cliente.Colonia, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Ciudad", + cliente.Ciudad, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Estado", + cliente.Estado, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Pais", + cliente.Pais, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@RFC", + cliente.RFC, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@CP", + cliente.CP, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Telefono", + cliente.Telefono, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@Mail", + cliente.Mail, + DbType.String); + StoredProcedureCommand.AddInput( + comando, + "@CveRegimenFiscal", + cliente.CveRegimenFiscal, + DbType.Byte); + StoredProcedureCommand.AddInput( + comando, + "@CveUsoCFDI", + cliente.CveUsoCFDI, + DbType.Byte); + } + } +} diff --git a/SIG.Web/App_Code/Repositories/Tramites/TramiteCatalogRepository.cs b/SIG.Web/App_Code/Repositories/Tramites/TramiteCatalogRepository.cs index c329b39..bbf3b0d 100644 --- a/SIG.Web/App_Code/Repositories/Tramites/TramiteCatalogRepository.cs +++ b/SIG.Web/App_Code/Repositories/Tramites/TramiteCatalogRepository.cs @@ -304,6 +304,7 @@ namespace SIG.Web.AppCode.Repositories.Tramites Add(command, "@CveTramitePagoDetalle", NullableId(model.CveTramitePagoDetalle), DbType.Int32); Add(command, "@CveTramitePago", model.CveTramitePago, DbType.Int32); Add(command, "@CvePS", model.CvePS, DbType.Int32); + Add(command, "@CveUM", model.CveUM, DbType.Int32); Add(command, "@Cantidad", model.Cantidad, DbType.Decimal); }); } diff --git a/SIG.Web/App_Code/Repositories/Ventas/VentaTramiteRepository.cs b/SIG.Web/App_Code/Repositories/Ventas/VentaTramiteRepository.cs new file mode 100644 index 0000000..bbb485c --- /dev/null +++ b/SIG.Web/App_Code/Repositories/Ventas/VentaTramiteRepository.cs @@ -0,0 +1,417 @@ +using System.Collections.Generic; +using System.Data; +using SIG.Web.AppCode.Contracts.Database; +using SIG.Web.AppCode.Contracts.Ventas; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Ventas; +using SIG.Web.AppCode.Repositories.Database; +using SIG.Web.AppCode.Utilities; + +namespace SIG.Web.AppCode.Repositories.Ventas +{ + public sealed class RepositorioVentaTramite + : RepositoryBase, IRepositorioVentaTramite + { + public RepositorioVentaTramite(IDbExecutor ejecutorBaseDatos) + : base(ejecutorBaseDatos) + { + } + + public DbResult> ListarPagosPendientes( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryList( + "dbo.PA_Vta_FraccionamientoPagoPendienteList", + cveUsuarioEjecuta, + nombreDominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamiento", + cveFraccionamiento, + DbType.Int32)); + } + + public DbResult> ListarPagosRealizados( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryList( + "dbo.PA_Vta_FraccionamientoPagoRealizadoList", + cveUsuarioEjecuta, + nombreDominio, + comando => StoredProcedureCommand.AddInput( + comando, + "@CveFraccionamiento", + cveFraccionamiento, + DbType.Int32)); + } + + public DbResult ObtenerContexto( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Vta_TramiteContextoGet", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveSolicitud", + cveSolicitud, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveTramitePago", + cveTramitePago, + DbType.Int32); + }); + } + + public DbResult> ListarConceptos( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryList( + "dbo.PA_Vta_TramiteConceptoList", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveSolicitud", + cveSolicitud, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveTramitePago", + cveTramitePago, + DbType.Int32); + }); + } + + public DbResult Generar( + ModeloCapturaVentaTramite venta, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryScalarId( + "dbo.PA_Vta_TramiteVentaGenerar", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveSolicitud", + venta.CveSolicitud, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveTramitePago", + venta.CveTramitePago, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Observaciones", + venta.Observaciones, + DbType.String); + }); + } + + public DbResult Pagar( + ModeloPagoVentaTramite pago, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryOne( + "dbo.PA_Vta_TramitePagoSave", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + StoredProcedureCommand.AddInput( + comando, + "@CveSolicitud", + pago.CveSolicitud, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@CveTramitePago", + pago.CveTramitePago, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Importe", + pago.Importe, + DbType.Decimal); + StoredProcedureCommand.AddInput( + comando, + "@FechaPago", + pago.FechaPago, + DbType.DateTime); + StoredProcedureCommand.AddInput( + comando, + "@CveFormaPago", + pago.CveFormaPago, + DbType.Byte); + StoredProcedureCommand.AddInput( + comando, + "@CveBancoCuenta", + pago.CveBancoCuenta, + DbType.Int32); + StoredProcedureCommand.AddInput( + comando, + "@Observaciones", + pago.Observaciones, + DbType.String); + }); + } + + public DbResult ObtenerOpcionesPago( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryReader( + "dbo.PA_Vta_TramitePagoOpcionesList", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar( + comando, + "@CveSolicitud", + cveSolicitud, + DbType.Int32); + Agregar( + comando, + "@CveTramitePago", + cveTramitePago, + DbType.Int32); + }, + lector => + { + ModeloOpcionesPagoVentaTramite opciones = + lector.ToObject() ?? + new ModeloOpcionesPagoVentaTramite(); + + if (lector.NextResult()) + { + opciones.FormasPago = + lector.ToList(); + } + + if (lector.NextResult()) + { + opciones.CuentasBancarias = + lector.ToList(); + } + + return opciones; + }); + } + + public DbResult + ObtenerOpcionesCondicionesPago( + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryReader( + "dbo.PA_Vta_TramiteCondicionesPagoOpcionesList", + cveUsuarioEjecuta, + nombreDominio, + null, + lector => + { + var opciones = + new ModeloOpcionesCondicionesPagoVentaTramite + { + MetodosPago = lector.ToList< + ModeloMetodoPagoOpcion>() + }; + + if (lector.NextResult()) + { + opciones.FormasPago = + lector.ToList(); + } + + return opciones; + }); + } + + public DbResult GuardarCondicionesPago( + ModeloCondicionesPagoVentaTramite condiciones, + int cveUsuarioEjecuta, + string nombreDominio) + { + return Execute( + "dbo.PA_Vta_TramiteCondicionesPagoSave", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar( + comando, + "@CveSolicitud", + condiciones.CveSolicitud, + DbType.Int32); + Agregar( + comando, + "@CveTramitePago", + condiciones.CveTramitePago, + DbType.Int32); + Agregar( + comando, + "@CveMetodoPago", + condiciones.CveMetodoPago, + DbType.Int32); + Agregar( + comando, + "@CveFormaPago", + condiciones.CveFormaPago, + DbType.Byte); + Agregar( + comando, + "@FechaVencimiento", + condiciones.FechaVencimiento, + DbType.Date); + }); + } + + public DbResult GuardarConcepto( + ModeloCapturaConceptoVentaTramite concepto, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryScalarId( + "dbo.PA_Vta_TramiteConceptoSave", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar(comando, "@CveSolicitud", concepto.CveSolicitud, DbType.Int32); + Agregar(comando, "@CveTramitePago", concepto.CveTramitePago, DbType.Int32); + Agregar( + comando, + "@CveVentaDetalle", + concepto.CveVentaDetalle > 0 + ? (object)concepto.CveVentaDetalle + : null, + DbType.Int32); + Agregar(comando, "@CvePS", concepto.CvePS, DbType.Int32); + Agregar(comando, "@Cantidad", concepto.Cantidad, DbType.Decimal); + Agregar(comando, "@PrecioUnitario", concepto.PrecioUnitario, DbType.Decimal); + }); + } + + public DbResult EliminarConcepto( + int cveSolicitud, + int cveTramitePago, + int cveVentaDetalle, + int cveUsuarioEjecuta, + string nombreDominio) + { + return Execute( + "dbo.PA_Vta_TramiteConceptoDelete", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar(comando, "@CveSolicitud", cveSolicitud, DbType.Int32); + Agregar(comando, "@CveTramitePago", cveTramitePago, DbType.Int32); + Agregar(comando, "@CveVentaDetalle", cveVentaDetalle, DbType.Int32); + }); + } + + public DbResult ObtenerDatosCfdi( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio) + { + return QueryReader( + "dbo.PA_Vta_TramiteVentaDatosCfdiGet", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar(comando, "@CveSolicitud", cveSolicitud, DbType.Int32); + Agregar(comando, "@CveTramitePago", cveTramitePago, DbType.Int32); + }, + lector => + { + ModeloDatosCfdiVentaTramite datos = + lector.ToObject(); + + if (datos != null && lector.NextResult()) + { + datos.Conceptos = + lector.ToList(); + } + + return datos; + }); + } + + public DbResult MarcarTimbrada( + int cveVenta, + long cveCfdiDocumento, + string uuid, + System.DateTime? fechaTimbrado, + int cveUsuarioEjecuta, + string nombreDominio) + { + return Execute( + "dbo.PA_Vta_TramiteVentaTimbradaUpdate", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar(comando, "@CveVenta", cveVenta, DbType.Int32); + Agregar(comando, "@CveCfdiDocumento", cveCfdiDocumento, DbType.Int64); + Agregar(comando, "@Uuid", uuid, DbType.String); + Agregar(comando, "@FechaTimbrado", fechaTimbrado, DbType.DateTime); + }); + } + + public DbResult MarcarTimbreCancelado( + int cveVenta, + long cveCfdiDocumento, + string motivo, + int cveUsuarioEjecuta, + string nombreDominio) + { + return Execute( + "dbo.PA_Vta_TramiteVentaTimbreCanceladoUpdate", + cveUsuarioEjecuta, + nombreDominio, + comando => + { + Agregar(comando, "@CveVenta", cveVenta, DbType.Int32); + Agregar(comando, "@CveCfdiDocumento", cveCfdiDocumento, DbType.Int64); + Agregar(comando, "@Motivo", motivo, DbType.String); + }); + } + + private static void Agregar( + IDbCommand comando, + string nombre, + object valor, + DbType tipo) + { + StoredProcedureCommand.AddInput(comando, nombre, valor, tipo); + } + } +} diff --git a/SIG.Web/App_Code/Security/ClsPaginaBase.cs b/SIG.Web/App_Code/Security/ClsPaginaBase.cs index ebb2c8f..8ed182f 100644 --- a/SIG.Web/App_Code/Security/ClsPaginaBase.cs +++ b/SIG.Web/App_Code/Security/ClsPaginaBase.cs @@ -90,6 +90,7 @@ namespace SIG.Web.AppCode.Security } if (!IsHomePage(currentPath) && + !IsAuthenticatedUtilityPage(currentPath) && !AppServices.PermissionService.CanAccessPage(CurrentUser.CveUsuario, currentPath)) { Response.Redirect("~/AccessDenied.aspx", true); @@ -128,6 +129,15 @@ namespace SIG.Web.AppCode.Security appRelativePath.Equals("~/Inicio.aspx", StringComparison.OrdinalIgnoreCase); } + private static bool IsAuthenticatedUtilityPage( + string appRelativePath) + { + return appRelativePath != null && + appRelativePath.Equals( + "~/Pages/Security/Perfil.aspx", + StringComparison.OrdinalIgnoreCase); + } + private static bool IsPublicPage(string appRelativePath) { return appRelativePath != null && @@ -165,4 +175,4 @@ namespace SIG.Web.AppCode.Security } } } -} \ No newline at end of file +} diff --git a/SIG.Web/App_Code/Services/Bitacora/BitacoraService.cs b/SIG.Web/App_Code/Services/Bitacora/BitacoraService.cs index f30738f..06168e9 100644 --- a/SIG.Web/App_Code/Services/Bitacora/BitacoraService.cs +++ b/SIG.Web/App_Code/Services/Bitacora/BitacoraService.cs @@ -109,34 +109,28 @@ namespace SIG.Web.AppCode.Services.Bitacora } } - public DbResult> Consultar( - BitacoraConsultaModel consulta) + public DbResult ConsultarDetalle(long cveBitacora) { - string validationMessage = ValidarConsulta(consulta); - - if (validationMessage != null) + if (cveBitacora <= 0) { - return Fail>( - validationMessage); + return Fail( + "La clave del movimiento de bitácora no es válida."); } BitacoraContextoModel contexto = _contextoProvider.Obtener(); if (contexto.CveUsuarioEjecuta <= 0) { - return Fail>( + return Fail( "No existe un usuario autenticado para consultar la bitácora."); } - BitacoraConsultaModel consultaNormalizada = - NormalizarConsulta(consulta); - using (var scope = new TransactionLogic( TransactionScopeOption.Suppress)) { - DbResult> result = - _repository.Consultar( - consultaNormalizada, + DbResult result = + _repository.ConsultarDetalle( + cveBitacora, contexto.CveUsuarioEjecuta); if (result.Success) diff --git a/SIG.Web/App_Code/Services/Facturacion/AlmacenArchivosCfdi.cs b/SIG.Web/App_Code/Services/Facturacion/AlmacenArchivosCfdi.cs new file mode 100644 index 0000000..a4aad73 --- /dev/null +++ b/SIG.Web/App_Code/Services/Facturacion/AlmacenArchivosCfdi.cs @@ -0,0 +1,124 @@ +using System; +using System.IO; +using System.Web.Hosting; +using SIG.Web.AppCode.Contracts.Facturacion; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Facturacion; + +namespace SIG.Web.AppCode.Services.Facturacion +{ + public sealed class AlmacenArchivosCfdi : IAlmacenArchivosCfdi + { + public DbResult GuardarXmlTimbrado( + CfdiDocumentoModel documento, + CfdiTimbradoIntentoModel intento) + { + if (documento == null || intento == null) + { + return Error( + "No se recibieron los datos del XML timbrado.", + null); + } + + if (documento.CveCliente <= 0 || + !documento.CveOrigen.HasValue || + documento.CveOrigen.Value <= 0 || + documento.CveCfdiDocumento <= 0 || + intento.XmlTimbrado == null || + intento.XmlTimbrado.Length == 0) + { + return Error( + "El XML timbrado no contiene los datos necesarios para crear el archivo.", + null); + } + + try + { + string rutaRelativaDirectorio = string.Format( + "~/Documentos/Clientes/{0}/CFDI/Ventas/", + documento.CveCliente); + string rutaDirectorio = HostingEnvironment.MapPath( + rutaRelativaDirectorio); + + if (string.IsNullOrWhiteSpace(rutaDirectorio)) + { + return Error( + "No fue posible resolver el directorio de archivos CFDI.", + null); + } + + Directory.CreateDirectory(rutaDirectorio); + + string nombreArchivo = string.Format( + "cfdi-venta-{0}-documento-{1}.xml", + documento.CveOrigen.Value, + documento.CveCfdiDocumento); + string rutaArchivo = Path.Combine( + rutaDirectorio, + nombreArchivo); + string rutaTemporal = Path.Combine( + rutaDirectorio, + "." + nombreArchivo + "." + + Guid.NewGuid().ToString("N") + ".tmp"); + + try + { + using (FileStream archivo = new FileStream( + rutaTemporal, + FileMode.CreateNew, + FileAccess.Write, + FileShare.None)) + { + archivo.Write( + intento.XmlTimbrado, + 0, + intento.XmlTimbrado.Length); + archivo.Flush(); + } + + if (File.Exists(rutaArchivo)) + { + File.Replace( + rutaTemporal, + rutaArchivo, + null); + } + else + { + File.Move( + rutaTemporal, + rutaArchivo); + } + } + finally + { + if (File.Exists(rutaTemporal)) + { + File.Delete(rutaTemporal); + } + } + + return DbResult.Ok( + rutaRelativaDirectorio + nombreArchivo); + } + catch (Exception exception) + { + return Error( + "No fue posible crear el archivo XML timbrado.", + exception); + } + } + + private static DbResult Error( + string mensaje, + Exception exception) + { + return DbResult.Fail( + mensaje, + exception == null + ? mensaje + : exception.ToString(), + exception); + } + } +} diff --git a/SIG.Web/App_Code/Services/Facturacion/CfdiTimbradoService.cs b/SIG.Web/App_Code/Services/Facturacion/CfdiTimbradoService.cs index 514cb55..3094cf2 100644 --- a/SIG.Web/App_Code/Services/Facturacion/CfdiTimbradoService.cs +++ b/SIG.Web/App_Code/Services/Facturacion/CfdiTimbradoService.cs @@ -15,15 +15,16 @@ namespace SIG.Web.AppCode.Services.Facturacion private readonly ICfdiXmlBuilder _xmlBuilder; private readonly IDictionary _pacClients; - private readonly IList - _finalizationHandlers; + private readonly IDictionary + _clientesCancelacionPac; + private readonly IAlmacenArchivosCfdi _almacenArchivosCfdi; public CfdiTimbradoService( ICfdiRepository repository, ICfdiXmlBuilder xmlBuilder, IEnumerable pacClients, - IEnumerable - finalizationHandlers) + IEnumerable clientesCancelacionPac, + IAlmacenArchivosCfdi almacenArchivosCfdi) { _repository = repository; _xmlBuilder = xmlBuilder; @@ -32,10 +33,14 @@ namespace SIG.Web.AppCode.Services.Facturacion .ToDictionary( client => client.Proveedor, StringComparer.OrdinalIgnoreCase); - _finalizationHandlers = (finalizationHandlers - ?? Enumerable.Empty< - ICfdiTimbradoFinalizadoHandler>()) - .ToList(); + _clientesCancelacionPac = (clientesCancelacionPac + ?? Enumerable.Empty()) + .ToDictionary( + cliente => cliente.Proveedor, + StringComparer.OrdinalIgnoreCase); + _almacenArchivosCfdi = almacenArchivosCfdi + ?? throw new ArgumentNullException( + "almacenArchivosCfdi"); } public DbResult GuardarBorrador( @@ -278,19 +283,24 @@ namespace SIG.Web.AppCode.Services.Facturacion CfdiTimbradoIntentoModel intento = completeResult.Data; - string handlerWarning = EjecutarFinalizadores( - documento, - intento, - cveUsuarioEjecuta, - nombreDominio); - string message = intento.MensajeRespuesta; - if (!string.IsNullOrWhiteSpace(handlerWarning)) + if (intento.Exitoso) { - message = string.IsNullOrWhiteSpace(message) - ? handlerWarning - : message + " " + handlerWarning; + DbResult resultadoArchivo = + _almacenArchivosCfdi.GuardarXmlTimbrado( + documento, + intento); + + if (!resultadoArchivo.Success) + { + const string advertenciaArchivo = + "El timbre quedó guardado, pero el archivo XML requiere revisión."; + + message = string.IsNullOrWhiteSpace(message) + ? advertenciaArchivo + : message + " " + advertenciaArchivo; + } } return DbResult.Ok( @@ -353,6 +363,136 @@ namespace SIG.Web.AppCode.Services.Facturacion nombreDominio); } + public DbResult Cancelar( + CfdiCancelacionSolicitudModel solicitud, + Guid? idSolicitud, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (solicitud == null || solicitud.CveCfdiDocumento <= 0) + { + return Fail( + "Seleccione un timbre válido para cancelar."); + } + + DbResult documentoResultado = + _repository.ObtenerDocumento( + solicitud.CveCfdiDocumento, + cveUsuarioEjecuta, + nombreDominio); + + if (!documentoResultado.Success || documentoResultado.Data == null) + { + return documentoResultado.Success + ? Fail( + "No se encontró el CFDI solicitado.") + : CopyFailure( + documentoResultado); + } + + CfdiDocumentoModel documento = documentoResultado.Data; + + if (!documento.CveCfdiTimbradoVigente.HasValue || + string.IsNullOrWhiteSpace(documento.UuidVigente)) + { + return Fail( + "La venta no tiene un timbre vigente para cancelar."); + } + + DbResult emisorResultado = + _repository.ObtenerEmisor( + documento.CveEmpresa, + cveUsuarioEjecuta, + nombreDominio); + + if (!emisorResultado.Success || emisorResultado.Data == null) + { + return emisorResultado.Success + ? Fail( + "La empresa no tiene un emisor fiscal activo.") + : CopyFailure( + emisorResultado); + } + + CfdiEmisorFiscalModel emisor = emisorResultado.Data; + IPacCancelacionClient clienteCancelacion; + + if (string.IsNullOrWhiteSpace(emisor.ProveedorPac) || + !_clientesCancelacionPac.TryGetValue( + emisor.ProveedorPac.Trim(), + out clienteCancelacion)) + { + return Fail( + "El proveedor PAC configurado no permite cancelar el timbre desde la aplicación."); + } + + DbResult inicioResultado; + + using (var transaccion = new TransactionLogic()) + { + inicioResultado = _repository.IniciarCancelacion( + solicitud, + idSolicitud ?? Guid.NewGuid(), + emisor.ProveedorPac, + emisor.AmbienteProduccion ? "PRODUCCION" : "PRUEBAS", + cveUsuarioEjecuta, + nombreDominio); + + if (inicioResultado.Success) + { + transaccion.Commit(); + } + } + + if (!inicioResultado.Success || inicioResultado.Data == null) + { + return inicioResultado.Success + ? Fail( + "No fue posible registrar la solicitud de cancelación.") + : CopyFailure( + inicioResultado); + } + + CfdiCancelacionInicioModel inicio = inicioResultado.Data; + + if (!inicio.PuedeEnviar) + { + return Fail( + "La solicitud de cancelación ya fue procesada."); + } + + CfdiPacCancelacionResultadoModel resultadoPac = + clienteCancelacion.Cancelar( + new CfdiPacCancelacionSolicitudModel + { + RfcEmisor = inicio.RfcEmisor, + Uuid = inicio.Uuid, + Motivo = inicio.Motivo, + UuidSustitucion = inicio.UuidSustitucion, + AmbienteProduccion = emisor.AmbienteProduccion, + ReferenciaCredencialPac = + emisor.ReferenciaCredencialPac + }); + + DbResult finResultado; + + using (var transaccion = new TransactionLogic()) + { + finResultado = _repository.FinalizarCancelacion( + inicio.CveCfdiCancelacion, + resultadoPac, + cveUsuarioEjecuta, + nombreDominio); + + if (finResultado.Success) + { + transaccion.Commit(); + } + } + + return finResultado; + } + private CfdiPacResultadoModel EnviarAlPac( CfdiDocumentoModel documento, CfdiEmisorFiscalModel emisor, @@ -398,40 +538,6 @@ namespace SIG.Web.AppCode.Services.Facturacion }); } - private string EjecutarFinalizadores( - CfdiDocumentoModel documento, - CfdiTimbradoIntentoModel intento, - int cveUsuarioEjecuta, - string nombreDominio) - { - if (_finalizationHandlers.Count == 0) - { - return null; - } - - var context = new CfdiTimbradoFinalizadoContext - { - Documento = documento, - Intento = intento, - CveUsuarioEjecuta = cveUsuarioEjecuta, - NombreDominio = nombreDominio - }; - - foreach (ICfdiTimbradoFinalizadoHandler handler - in _finalizationHandlers) - { - DbResult result = - handler.AlFinalizar(context); - - if (!result.Success) - { - return "El timbre quedó guardado, pero una acción posterior requiere revisión."; - } - } - - return null; - } - private static DbResult Fail(string message) { return DbResult.Fail( diff --git a/SIG.Web/App_Code/Services/Facturacion/ProfactPacTimbradoClient.cs b/SIG.Web/App_Code/Services/Facturacion/ProfactPacTimbradoClient.cs index 30bb86d..483bcd2 100644 --- a/SIG.Web/App_Code/Services/Facturacion/ProfactPacTimbradoClient.cs +++ b/SIG.Web/App_Code/Services/Facturacion/ProfactPacTimbradoClient.cs @@ -37,7 +37,7 @@ namespace SIG.Web.AppCode.Services.Facturacion } public sealed class ProfactPacTimbradoClient - : IPacTimbradoClient + : IPacTimbradoClient, IPacCancelacionClient { private readonly IPacCredentialProvider _credentialProvider; @@ -125,6 +125,108 @@ namespace SIG.Web.AppCode.Services.Facturacion } } + public CfdiPacCancelacionResultadoModel Cancelar( + CfdiPacCancelacionSolicitudModel solicitud) + { + if (solicitud == null || + string.IsNullOrWhiteSpace(solicitud.RfcEmisor) || + string.IsNullOrWhiteSpace(solicitud.Uuid) || + string.IsNullOrWhiteSpace(solicitud.Motivo)) + { + return FalloCancelacion( + "CFDI_CANCELACION_INCOMPLETA", + "La solicitud de cancelación está incompleta."); + } + + string credencial = + _credentialProvider.ObtenerCredencial( + solicitud.ReferenciaCredencialPac); + + if (string.IsNullOrWhiteSpace(credencial)) + { + return FalloCancelacion( + "PAC_NO_CONFIGURADO", + "No se configuró la credencial del PAC para el emisor."); + } + + try + { + var conector = new ProfactConnector40( + solicitud.AmbienteProduccion); + conector.EstableceCredenciales(credencial); + + ResultadoCancelacion resultado = + conector.CancelaCFDI40( + solicitud.RfcEmisor.Trim(), + solicitud.Uuid.Trim(), + solicitud.Motivo.Trim(), + Texto(solicitud.UuidSustitucion)); + + return resultado == null + ? FalloCancelacion( + "PAC_SIN_RESPUESTA", + "El PAC no devolvió una respuesta de cancelación.") + : new CfdiPacCancelacionResultadoModel + { + Exitoso = resultado.Exitoso, + CodigoRespuesta = Texto(resultado.NumeroError), + MensajeRespuesta = + Texto(resultado.Descripcion) ?? + (resultado.Exitoso + ? "Timbre cancelado correctamente." + : "El PAC no pudo cancelar el timbre."), + TipoExcepcion = Texto(resultado.TipoExcepcion) + }; + } + catch (TimeoutException exception) + { + return CancelacionIndeterminada(exception); + } + catch (CommunicationException exception) + { + return CancelacionIndeterminada(exception); + } + catch (Exception exception) + { + return new CfdiPacCancelacionResultadoModel + { + Exitoso = false, + ResultadoIndeterminado = false, + CodigoRespuesta = "PAC_EXCEPCION", + MensajeRespuesta = + "El PAC rechazó la cancelación o no pudo procesarla.", + TipoExcepcion = exception.GetType().FullName + }; + } + } + + private static CfdiPacCancelacionResultadoModel FalloCancelacion( + string codigo, + string mensaje) + { + return new CfdiPacCancelacionResultadoModel + { + Exitoso = false, + ResultadoIndeterminado = false, + CodigoRespuesta = codigo, + MensajeRespuesta = mensaje + }; + } + + private static CfdiPacCancelacionResultadoModel CancelacionIndeterminada( + Exception exception) + { + return new CfdiPacCancelacionResultadoModel + { + Exitoso = false, + ResultadoIndeterminado = true, + CodigoRespuesta = "PAC_RESULTADO_INDETERMINADO", + MensajeRespuesta = + "El PAC no confirmó la cancelación. Debe consultarse antes de reenviar.", + TipoExcepcion = exception.GetType().FullName + }; + } + private static CfdiPacResultadoModel ConvertirResultado( ResultadoTimbre resultado) { diff --git a/SIG.Web/App_Code/Services/General/ProductoCatalogBitacoraFactory.cs b/SIG.Web/App_Code/Services/General/ProductoCatalogBitacoraFactory.cs new file mode 100644 index 0000000..ced97e6 --- /dev/null +++ b/SIG.Web/App_Code/Services/General/ProductoCatalogBitacoraFactory.cs @@ -0,0 +1,161 @@ +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Services.General +{ + internal static class ProductoCatalogBitacoraFactory + { + public static BitacoraEventoModel CreateClasificacion( + ClasificacionModel previous, + ClasificacionModel current, + int cveClasificacion, + BitacoraTipoMovimiento movement) + { + ClasificacionModel value = current ?? previous; + var auditEvent = CreateEvent( + "Clasificaciones", + "CveClasificacion", + cveClasificacion, + movement, + Description( + movement, + "la clasificación", + value.Clasificacion), + movement == BitacoraTipoMovimiento.Eliminado + ? new List() + : new List + { + Field( + "Codigo", + previous == null ? null : previous.Codigo, + current.Codigo), + Field( + "Clasificacion", + previous == null + ? null + : previous.Clasificacion, + current.Clasificacion), + Field( + "Afectable", + previous == null + ? (object)null + : previous.Afectable, + current.Afectable), + Field( + "Estado", + previous == null + ? (object)null + : previous.EsActivo, + current.EsActivo) + }); + + return auditEvent; + } + + public static BitacoraEventoModel CreateUnidadMedida( + UnidadMedidaModel previous, + UnidadMedidaModel current, + int cveUnidadMedida, + BitacoraTipoMovimiento movement) + { + UnidadMedidaModel value = current ?? previous; + return CreateEvent( + "UnidadesMedida", + "CveUnidadMedida", + cveUnidadMedida, + movement, + Description( + movement, + "la unidad de medida", + value.UnidadMedida), + movement == BitacoraTipoMovimiento.Eliminado + ? new List() + : new List + { + Field( + "UnidadMedida", + previous == null + ? null + : previous.UnidadMedida, + current.UnidadMedida), + Field( + "Abreviatura", + previous == null + ? null + : previous.Abreviatura, + current.Abreviatura), + Field( + "Estado", + previous == null + ? (object)null + : previous.EsActivo, + current.EsActivo) + }); + } + + private static BitacoraEventoModel CreateEvent( + string table, + string keyField, + int key, + BitacoraTipoMovimiento movement, + string description, + IList fields) + { + var auditEvent = new BitacoraEventoModel + { + NombreTablaSQL = table, + TipoMovimiento = movement, + LlaveRegistro = key.ToString(), + DescripcionMovimiento = description, + DiscriminarCamposSinCambios = movement != + BitacoraTipoMovimiento.Agregado, + Campos = fields + }; + + auditEvent.Relaciones.Add( + new BitacoraRelacionEventoModel + { + TipoRelacion = BitacoraTipoRelacion.Directa, + NombreTablaSQL = table, + NombreCampoSQL = keyField, + Valor = key, + VisibleDesarrollador = false, + DescripcionRelacion = "Registro de catálogo afectado." + }); + + return auditEvent; + } + + private static BitacoraCampoEventoModel Field( + string name, + object previous, + object current) + { + return new BitacoraCampoEventoModel + { + NombreCampoSQL = name, + ValorAnterior = previous, + ValorNuevo = current + }; + } + + private static string Description( + BitacoraTipoMovimiento movement, + string entity, + string name) + { + if (movement == BitacoraTipoMovimiento.Agregado) + { + return "Se agregó " + entity + " " + name + "."; + } + + if (movement == BitacoraTipoMovimiento.Editado) + { + return "Se modificó " + entity + " " + name + "."; + } + + return "Se eliminó " + entity + " " + name + "."; + } + } +} diff --git a/SIG.Web/App_Code/Services/General/ProductoCatalogService.cs b/SIG.Web/App_Code/Services/General/ProductoCatalogService.cs new file mode 100644 index 0000000..e9b4485 --- /dev/null +++ b/SIG.Web/App_Code/Services/General/ProductoCatalogService.cs @@ -0,0 +1,438 @@ +using System; +using System.Collections.Generic; +using SIG.Web.AppCode.Contracts.Bitacora; +using SIG.Web.AppCode.Contracts.General; +using SIG.Web.AppCode.Infrastructure.Transactions; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Services.General +{ + public sealed class ProductoCatalogService : IProductoCatalogService + { + private readonly IProductoCatalogRepository _repository; + private readonly IBitacoraService _bitacora; + + public ProductoCatalogService( + IProductoCatalogRepository repository, + IBitacoraService bitacora) + { + _repository = repository ?? + throw new ArgumentNullException("repository"); + _bitacora = bitacora ?? + throw new ArgumentNullException("bitacora"); + } + + public DbResult> ListClasificaciones( + string texto, + bool incluirInactivos, + int usuario, + string dominio) + { + return _repository.ListClasificaciones( + TrimOrNull(texto), + incluirInactivos, + usuario, + dominio); + } + + public DbResult GetClasificacion( + int cveClasificacion, + int usuario, + string dominio) + { + return cveClasificacion > 0 + ? _repository.GetClasificacion( + cveClasificacion, + usuario, + dominio) + : Fail( + "Seleccione una clasificación válida."); + } + + public DbResult SaveClasificacion( + ClasificacionModel clasificacion, + int usuario, + string dominio) + { + DbResult validation = Validate(clasificacion); + + if (!validation.Success) + { + return validation; + } + + clasificacion.Codigo = TrimOrNull(clasificacion.Codigo); + clasificacion.Clasificacion = clasificacion.Clasificacion.Trim(); + + using (var transaction = new TransactionLogic()) + { + ClasificacionModel previous = null; + + if (clasificacion.CveClasificacion > 0) + { + DbResult previousResult = + _repository.GetClasificacion( + clasificacion.CveClasificacion, + usuario, + dominio); + + if (!previousResult.Success || previousResult.Data == null) + { + return FailFrom( + previousResult, + "La clasificación seleccionada no existe."); + } + + previous = previousResult.Data; + } + + DbResult result = _repository.SaveClasificacion( + clasificacion, + usuario, + dominio); + + if (!result.Success) + { + return result; + } + + DbResult currentResult = + _repository.GetClasificacion( + result.Data, + usuario, + dominio); + + if (!currentResult.Success || currentResult.Data == null) + { + return FailFrom( + currentResult, + "No fue posible recuperar la clasificación guardada."); + } + + DbResult auditResult = _bitacora.Registrar( + ProductoCatalogBitacoraFactory.CreateClasificacion( + previous, + currentResult.Data, + result.Data, + previous == null + ? BitacoraTipoMovimiento.Agregado + : BitacoraTipoMovimiento.Editado)); + + if (!auditResult.Success) + { + return FailFrom( + auditResult, + "No fue posible registrar la bitácora."); + } + + transaction.Commit(); + return result; + } + } + + public DbResult DeleteClasificacion( + int cveClasificacion, + int usuario, + string dominio) + { + if (cveClasificacion <= 0) + { + return Fail("Seleccione una clasificación válida."); + } + + using (var transaction = new TransactionLogic()) + { + DbResult previousResult = + _repository.GetClasificacion( + cveClasificacion, + usuario, + dominio); + + if (!previousResult.Success || previousResult.Data == null) + { + return FailFrom( + previousResult, + "La clasificación seleccionada no existe."); + } + + DbResult result = _repository.DeleteClasificacion( + cveClasificacion, + usuario, + dominio); + + if (!result.Success) + { + return result; + } + + DbResult auditResult = _bitacora.Registrar( + ProductoCatalogBitacoraFactory.CreateClasificacion( + previousResult.Data, + null, + cveClasificacion, + BitacoraTipoMovimiento.Eliminado)); + + if (!auditResult.Success) + { + return FailFrom( + auditResult, + "No fue posible registrar la bitácora."); + } + + transaction.Commit(); + return result; + } + } + + public DbResult> ListUnidadesMedida( + string texto, + bool incluirInactivos, + int usuario, + string dominio) + { + return _repository.ListUnidadesMedida( + TrimOrNull(texto), + incluirInactivos, + usuario, + dominio); + } + + public DbResult GetUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio) + { + return cveUnidadMedida > 0 + ? _repository.GetUnidadMedida( + cveUnidadMedida, + usuario, + dominio) + : Fail( + "Seleccione una unidad de medida válida."); + } + + public DbResult SaveUnidadMedida( + UnidadMedidaModel unidadMedida, + int usuario, + string dominio) + { + DbResult validation = Validate(unidadMedida); + + if (!validation.Success) + { + return validation; + } + + unidadMedida.UnidadMedida = unidadMedida.UnidadMedida.Trim(); + unidadMedida.Abreviatura = unidadMedida.Abreviatura.Trim(); + + using (var transaction = new TransactionLogic()) + { + UnidadMedidaModel previous = null; + + if (unidadMedida.CveUnidadMedida > 0) + { + DbResult previousResult = + _repository.GetUnidadMedida( + unidadMedida.CveUnidadMedida, + usuario, + dominio); + + if (!previousResult.Success || previousResult.Data == null) + { + return FailFrom( + previousResult, + "La unidad de medida seleccionada no existe."); + } + + previous = previousResult.Data; + } + + DbResult result = _repository.SaveUnidadMedida( + unidadMedida, + usuario, + dominio); + + if (!result.Success) + { + return result; + } + + DbResult currentResult = + _repository.GetUnidadMedida( + result.Data, + usuario, + dominio); + + if (!currentResult.Success || currentResult.Data == null) + { + return FailFrom( + currentResult, + "No fue posible recuperar la unidad de medida guardada."); + } + + DbResult auditResult = _bitacora.Registrar( + ProductoCatalogBitacoraFactory.CreateUnidadMedida( + previous, + currentResult.Data, + result.Data, + previous == null + ? BitacoraTipoMovimiento.Agregado + : BitacoraTipoMovimiento.Editado)); + + if (!auditResult.Success) + { + return FailFrom( + auditResult, + "No fue posible registrar la bitácora."); + } + + transaction.Commit(); + return result; + } + } + + public DbResult DeleteUnidadMedida( + int cveUnidadMedida, + int usuario, + string dominio) + { + if (cveUnidadMedida <= 0) + { + return Fail( + "Seleccione una unidad de medida válida."); + } + + using (var transaction = new TransactionLogic()) + { + DbResult previousResult = + _repository.GetUnidadMedida( + cveUnidadMedida, + usuario, + dominio); + + if (!previousResult.Success || previousResult.Data == null) + { + return FailFrom( + previousResult, + "La unidad de medida seleccionada no existe."); + } + + DbResult result = _repository.DeleteUnidadMedida( + cveUnidadMedida, + usuario, + dominio); + + if (!result.Success) + { + return result; + } + + DbResult auditResult = _bitacora.Registrar( + ProductoCatalogBitacoraFactory.CreateUnidadMedida( + previousResult.Data, + null, + cveUnidadMedida, + BitacoraTipoMovimiento.Eliminado)); + + if (!auditResult.Success) + { + return FailFrom( + auditResult, + "No fue posible registrar la bitácora."); + } + + transaction.Commit(); + return result; + } + } + + private static DbResult Validate( + ClasificacionModel clasificacion) + { + if (clasificacion == null || + string.IsNullOrWhiteSpace(clasificacion.Clasificacion)) + { + return Fail("Capture la clasificación."); + } + + if (clasificacion.Clasificacion.Trim().Length > 200) + { + return Fail( + "La clasificación no puede exceder 200 caracteres."); + } + + if (!string.IsNullOrWhiteSpace(clasificacion.Codigo) && + clasificacion.Codigo.Trim().Length > 20) + { + return Fail( + "El código no puede exceder 20 caracteres."); + } + + return DbResult.Ok(clasificacion.CveClasificacion); + } + + private static DbResult Validate( + UnidadMedidaModel unidadMedida) + { + if (unidadMedida == null || + string.IsNullOrWhiteSpace(unidadMedida.UnidadMedida)) + { + return Fail("Capture la unidad de medida."); + } + + if (string.IsNullOrWhiteSpace(unidadMedida.Abreviatura)) + { + return Fail("Capture la abreviatura."); + } + + if (unidadMedida.UnidadMedida.Trim().Length > 50) + { + return Fail( + "La unidad de medida no puede exceder 50 caracteres."); + } + + if (unidadMedida.Abreviatura.Trim().Length > 15) + { + return Fail( + "La abreviatura no puede exceder 15 caracteres."); + } + + return DbResult.Ok(unidadMedida.CveUnidadMedida); + } + + private static string TrimOrNull(string value) + { + return string.IsNullOrWhiteSpace(value) + ? null + : value.Trim(); + } + + private static DbResult Fail(string message) + { + return DbResult.Fail( + message, + message, + new ArgumentException(message)); + } + + private static DbResult FailFrom( + DbResult source, + string fallbackMessage) + { + string message = source == null || + string.IsNullOrWhiteSpace(source.UserMessage) + ? fallbackMessage + : source.UserMessage; + + return DbResult.Fail( + message, + source == null + ? fallbackMessage + : source.TechnicalMessage, + source == null ? null : source.Exception); + } + } +} diff --git a/SIG.Web/App_Code/Services/General/ProductoServicioBitacoraFactory.cs b/SIG.Web/App_Code/Services/General/ProductoServicioBitacoraFactory.cs new file mode 100644 index 0000000..752cd23 --- /dev/null +++ b/SIG.Web/App_Code/Services/General/ProductoServicioBitacoraFactory.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Services.General +{ + internal static class ProductoServicioBitacoraFactory + { + public static BitacoraEventoModel Create( + ProductoServicioModel previous, + ProductoServicioModel current, + int cvePS, + BitacoraTipoMovimiento movement) + { + ProductoServicioModel value = current ?? previous; + var auditEvent = new BitacoraEventoModel + { + NombreTablaSQL = "ProductosServicios", + TipoMovimiento = movement, + LlaveRegistro = cvePS.ToString(), + DescripcionMovimiento = Description(movement, value.PS), + DiscriminarCamposSinCambios = movement != + BitacoraTipoMovimiento.Agregado, + Campos = movement == BitacoraTipoMovimiento.Eliminado + ? new List() + : CreateFields(previous, current) + }; + + auditEvent.Relaciones.Add( + new BitacoraRelacionEventoModel + { + TipoRelacion = BitacoraTipoRelacion.Directa, + NombreTablaSQL = "ProductosServicios", + NombreCampoSQL = "CvePS", + Valor = cvePS, + VisibleDesarrollador = false, + DescripcionRelacion = + "Producto o servicio afectado." + }); + + return auditEvent; + } + + private static string Description( + BitacoraTipoMovimiento movement, + string productName) + { + if (movement == BitacoraTipoMovimiento.Agregado) + { + return "Se agregó el producto o servicio " + + productName + "."; + } + + if (movement == BitacoraTipoMovimiento.Editado) + { + return "Se modificó el producto o servicio " + + productName + "."; + } + + return "Se eliminó el producto o servicio " + + productName + "."; + } + + private static IList CreateFields( + ProductoServicioModel previous, + ProductoServicioModel current) + { + return new List + { + Field( + "Codigo", + Value(previous, item => item.Codigo), + current.Codigo), + Field( + "PS", + Value(previous, item => item.PS), + current.PS), + Field( + "CveTipoPS", + Value(previous, item => item.CveTipoPS), + current.CveTipoPS), + Field( + "CveClasificacion", + Value(previous, item => item.CveClasificacion), + current.CveClasificacion), + Field( + "CveUnidadMedida", + Value(previous, item => item.CveUnidadMedida), + current.CveUnidadMedida), + Field( + "Precio", + Value(previous, item => item.Precio), + current.Precio), + Field( + "Estado", + Value(previous, item => item.EsActivo), + current.EsActivo) + }; + } + + private static BitacoraCampoEventoModel Field( + string name, + object previous, + object current) + { + return new BitacoraCampoEventoModel + { + NombreCampoSQL = name, + ValorAnterior = previous, + ValorNuevo = current + }; + } + + private static object Value( + ProductoServicioModel model, + Func selector) + { + return model == null + ? null + : (object)selector(model); + } + } +} diff --git a/SIG.Web/App_Code/Services/General/ProductoServicioService.cs b/SIG.Web/App_Code/Services/General/ProductoServicioService.cs new file mode 100644 index 0000000..d369708 --- /dev/null +++ b/SIG.Web/App_Code/Services/General/ProductoServicioService.cs @@ -0,0 +1,276 @@ +using System; +using System.Collections.Generic; +using SIG.Web.AppCode.Contracts.Bitacora; +using SIG.Web.AppCode.Contracts.General; +using SIG.Web.AppCode.Infrastructure.Transactions; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; + +namespace SIG.Web.AppCode.Services.General +{ + public sealed class ProductoServicioService : IProductoServicioService + { + private readonly IProductoServicioRepository _repository; + private readonly IBitacoraService _bitacora; + + public ProductoServicioService( + IProductoServicioRepository repository, + IBitacoraService bitacora) + { + _repository = repository ?? + throw new ArgumentNullException("repository"); + _bitacora = bitacora ?? + throw new ArgumentNullException("bitacora"); + } + + public DbResult> List( + string texto, + bool incluirInactivos, + int usuario, + string dominio) + { + return _repository.List( + TrimOrNull(texto), + incluirInactivos, + usuario, + dominio); + } + + public DbResult Get( + int cvePS, + int usuario, + string dominio) + { + return cvePS > 0 + ? _repository.Get(cvePS, usuario, dominio) + : Fail( + "Seleccione un producto o servicio válido."); + } + + public DbResult ListOptions( + int? cveClasificacionActual, + int? cveUnidadMedidaActual, + int usuario, + string dominio) + { + return _repository.ListOptions( + cveClasificacionActual, + cveUnidadMedidaActual, + usuario, + dominio); + } + + public DbResult Save( + ProductoServicioModel productoServicio, + int usuario, + string dominio) + { + DbResult validation = Validate(productoServicio); + + if (!validation.Success) + { + return validation; + } + + productoServicio.Codigo = TrimOrNull( + productoServicio.Codigo); + productoServicio.PS = productoServicio.PS.Trim(); + + using (var transaction = new TransactionLogic()) + { + ProductoServicioModel previous = null; + + if (productoServicio.CvePS > 0) + { + DbResult previousResult = + _repository.Get( + productoServicio.CvePS, + usuario, + dominio); + + if (!previousResult.Success || + previousResult.Data == null) + { + return FailFrom( + previousResult, + "El producto o servicio seleccionado no existe."); + } + + previous = previousResult.Data; + } + + DbResult result = _repository.Save( + productoServicio, + usuario, + dominio); + + if (!result.Success) + { + return result; + } + + DbResult currentResult = + _repository.Get(result.Data, usuario, dominio); + + if (!currentResult.Success || currentResult.Data == null) + { + return FailFrom( + currentResult, + "No fue posible recuperar el producto o servicio guardado."); + } + + BitacoraTipoMovimiento movement = previous == null + ? BitacoraTipoMovimiento.Agregado + : BitacoraTipoMovimiento.Editado; + DbResult auditResult = _bitacora.Registrar( + ProductoServicioBitacoraFactory.Create( + previous, + currentResult.Data, + result.Data, + movement)); + + if (!auditResult.Success) + { + return DbResult.Fail( + auditResult.UserMessage, + auditResult.TechnicalMessage, + auditResult.Exception); + } + + transaction.Commit(); + return result; + } + } + + public DbResult Delete( + int cvePS, + int usuario, + string dominio) + { + if (cvePS <= 0) + { + return Fail( + "Seleccione un producto o servicio válido."); + } + + using (var transaction = new TransactionLogic()) + { + DbResult previousResult = + _repository.Get(cvePS, usuario, dominio); + + if (!previousResult.Success || previousResult.Data == null) + { + return FailFrom( + previousResult, + "El producto o servicio seleccionado no existe."); + } + + DbResult result = _repository.Delete( + cvePS, + usuario, + dominio); + + if (!result.Success) + { + return result; + } + + DbResult auditResult = _bitacora.Registrar( + ProductoServicioBitacoraFactory.Create( + previousResult.Data, + null, + cvePS, + BitacoraTipoMovimiento.Eliminado)); + + if (!auditResult.Success) + { + return DbResult.Fail( + auditResult.UserMessage, + auditResult.TechnicalMessage, + auditResult.Exception); + } + + transaction.Commit(); + return result; + } + } + + private static DbResult Validate( + ProductoServicioModel productoServicio) + { + if (productoServicio == null || + string.IsNullOrWhiteSpace(productoServicio.PS)) + { + return Fail( + "Capture la descripción del producto o servicio."); + } + + if (productoServicio.PS.Trim().Length > 846) + { + return Fail( + "La descripción no puede exceder 846 caracteres."); + } + + if (!string.IsNullOrWhiteSpace(productoServicio.Codigo) && + productoServicio.Codigo.Trim().Length > 50) + { + return Fail( + "El código no puede exceder 50 caracteres."); + } + + if (productoServicio.CveTipoPS != 1 && + productoServicio.CveTipoPS != 2) + { + return Fail( + "Seleccione si el registro es producto o servicio."); + } + + if (productoServicio.CveClasificacion <= 0 || + productoServicio.CveUnidadMedida <= 0) + { + return Fail( + "Seleccione la clasificación y la unidad de medida."); + } + + if (productoServicio.Precio < 0) + { + return Fail("El precio no puede ser negativo."); + } + + return DbResult.Ok(productoServicio.CvePS); + } + + private static string TrimOrNull(string value) + { + return string.IsNullOrWhiteSpace(value) + ? null + : value.Trim(); + } + + private static DbResult Fail(string message) + { + return DbResult.Fail( + message, + message, + new ArgumentException(message)); + } + + private static DbResult FailFrom( + DbResult source, + string fallbackMessage) + { + string message = source == null || + string.IsNullOrWhiteSpace(source.UserMessage) + ? fallbackMessage + : source.UserMessage; + + return DbResult.Fail( + message, + source == null + ? fallbackMessage + : source.TechnicalMessage, + source == null ? null : source.Exception); + } + } +} diff --git a/SIG.Web/App_Code/Services/Logging/ControlledExceptionLogger.cs b/SIG.Web/App_Code/Services/Logging/ControlledExceptionLogger.cs index 475858f..cecbee8 100644 --- a/SIG.Web/App_Code/Services/Logging/ControlledExceptionLogger.cs +++ b/SIG.Web/App_Code/Services/Logging/ControlledExceptionLogger.cs @@ -126,7 +126,7 @@ namespace SIG.Web.AppCode.Services.Logging content.AppendLine("Date: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); content.AppendLine("Source: " + Compact(source)); content.AppendLine("Procedure: " + Compact(StoredProcedureDiagnostics.CurrentProcedureName)); - content.AppendLine("UserMessage: " + Compact( + content.AppendLine("UserMessage: " + ( string.IsNullOrWhiteSpace(userMessage) ? ControlledExceptionClassifier.GetUserMessage(exception) : userMessage)); @@ -142,7 +142,7 @@ namespace SIG.Web.AppCode.Services.Logging } content.AppendLine("ExceptionType: " + exception.GetType().FullName); - content.AppendLine("Message: " + Compact(exception.Message)); + content.AppendLine("Message: " + (exception.Message)); content.AppendLine(); return content.ToString(); diff --git a/SIG.Web/App_Code/Services/Login/DummyLoginService.cs b/SIG.Web/App_Code/Services/Login/DummyLoginService.cs index 650f713..f4c07da 100644 --- a/SIG.Web/App_Code/Services/Login/DummyLoginService.cs +++ b/SIG.Web/App_Code/Services/Login/DummyLoginService.cs @@ -16,16 +16,21 @@ namespace SIG.Web.AppCode.Services.Login return LoginResult.Ok(new UserSessionModel { CveUsuario = 15, + CveUsuarioOriginal = 15, CveRol = 1, + CveRolOriginal = 1, CveEmpresa = 1, + CveCliente = 0, NombreUsuario = nombreUsuario.Trim(), Nombre = "Usuario Demo", CorreoElectronico = "usuario.demo@example.invalid", NombreRol = "Administrador", NombreDominio = nombreDominio, TokenSesion = Guid.NewGuid().ToString("N"), - DebeCambiarContrasena = false + DebeCambiarContrasena = false, + EsAdmin = true, + PuedeCambiarUsuario = true }); } } -} \ No newline at end of file +} diff --git a/SIG.Web/App_Code/Services/Security/LoginService.cs b/SIG.Web/App_Code/Services/Security/LoginService.cs index 1360657..f967f82 100644 --- a/SIG.Web/App_Code/Services/Security/LoginService.cs +++ b/SIG.Web/App_Code/Services/Security/LoginService.cs @@ -158,14 +158,20 @@ namespace SIG.Web.AppCode.Services.Security var sessionUser = new UserSessionModel { CveUsuario = user.CveUsuario, + CveUsuarioOriginal = user.CveUsuario, CveRol = user.CveRol, + CveRolOriginal = user.CveRol, + CveCliente = user.CveCliente, NombreUsuario = user.NombreUsuario, Nombre = user.NombreUsuario, CorreoElectronico = user.CorreoElectronico, NombreRol = user.NombreRol, NombreDominio = request.NombreDominio, TokenSesion = sessionToken, - DebeCambiarContrasena = user.DebeCambiarContrasena + DebeCambiarContrasena = user.DebeCambiarContrasena, + EsAdmin = user.CveRol == 1, + PuedeCambiarUsuario = + user.CveRol == 1 || user.CveRol == 2 }; return LoginResult.Ok(sessionUser); diff --git a/SIG.Web/App_Code/Services/Security/PerfilUsuarioService.cs b/SIG.Web/App_Code/Services/Security/PerfilUsuarioService.cs new file mode 100644 index 0000000..ae4784f --- /dev/null +++ b/SIG.Web/App_Code/Services/Security/PerfilUsuarioService.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using SIG.Web.AppCode.Contracts.Security; +using SIG.Web.AppCode.Infrastructure.Transactions; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Security; +using SIG.Web.AppCode.Session; + +namespace SIG.Web.AppCode.Services.Security +{ + public sealed class PerfilUsuarioService : IPerfilUsuarioService + { + private readonly IPerfilUsuarioRepository _repositorio; + private readonly IPasswordHasher _generadorHashContrasena; + + public PerfilUsuarioService( + IPerfilUsuarioRepository repositorio, + IPasswordHasher generadorHashContrasena) + { + _repositorio = repositorio ?? + throw new ArgumentNullException("repositorio"); + _generadorHashContrasena = generadorHashContrasena ?? + throw new ArgumentNullException( + "generadorHashContrasena"); + } + + public DbResult ObtenerPerfil( + UserSessionModel usuarioSesion) + { + if (usuarioSesion == null || usuarioSesion.CveUsuario <= 0) + { + return Error( + "No se encontró la sesión del usuario."); + } + + return _repositorio.ObtenerPerfil( + usuarioSesion.CveUsuario, + usuarioSesion.CveUsuario, + usuarioSesion.NombreDominio); + } + + public DbResult ActualizarSesion( + UserSessionModel usuarioSesion, + string nombreUsuario, + string contrasena) + { + if (usuarioSesion == null || usuarioSesion.CveUsuario <= 0) + { + return Error( + "No se encontró la sesión del usuario."); + } + + nombreUsuario = string.IsNullOrWhiteSpace(nombreUsuario) + ? string.Empty + : nombreUsuario.Trim(); + + if (nombreUsuario.Length < 3) + { + return Error( + "El nombre de usuario debe contener al menos tres caracteres."); + } + + if (!string.IsNullOrEmpty(contrasena) && + contrasena.Length < 8) + { + return Error( + "La contraseña debe contener al menos ocho caracteres."); + } + + string hashContrasena = string.IsNullOrEmpty(contrasena) + ? null + : _generadorHashContrasena.HashPassword(contrasena); + DbResult resultado; + + using (var transaccion = new TransactionLogic()) + { + resultado = _repositorio.ActualizarSesion( + usuarioSesion.CveUsuario, + nombreUsuario, + hashContrasena, + usuarioSesion.CveUsuario, + usuarioSesion.NombreDominio); + + if (resultado.Success) + { + transaccion.Commit(); + } + } + + return resultado; + } + + public DbResult ActualizarCliente( + UserSessionModel usuarioSesion, + PerfilClienteModel cliente) + { + if (usuarioSesion == null || + !usuarioSesion.EsDesarrollador || + usuarioSesion.CveCliente <= 0) + { + return Error( + "La sesión no tiene un cliente desarrollador asignado."); + } + + if (cliente == null || + cliente.CveCliente != usuarioSesion.CveCliente) + { + return Error( + "Los datos del cliente no corresponden a la sesión."); + } + + DbResult resultado; + + using (var transaccion = new TransactionLogic()) + { + resultado = _repositorio.ActualizarCliente( + cliente, + usuarioSesion.CveUsuario, + usuarioSesion.NombreDominio); + + if (resultado.Success) + { + transaccion.Commit(); + } + } + + return resultado; + } + + public DbResult> + ListarUsuariosCambio( + UserSessionModel usuarioSesion, + string texto) + { + if (!PuedeCambiarUsuario(usuarioSesion)) + { + return Error>( + "La sesión no permite cambiar de usuario."); + } + + return _repositorio.ListarUsuariosCambio( + texto, + UsuarioAdministrador(usuarioSesion), + usuarioSesion.NombreDominio); + } + + public DbResult CambiarUsuario( + UserSessionModel usuarioSesion, + int cveUsuarioSeleccionado) + { + if (!PuedeCambiarUsuario(usuarioSesion)) + { + return Error( + "La sesión no permite cambiar de usuario."); + } + + if (cveUsuarioSeleccionado <= 0) + { + return Error( + "Seleccione un usuario válido."); + } + + DbResult resultadoUsuario = + _repositorio.ObtenerUsuarioContexto( + cveUsuarioSeleccionado, + UsuarioAdministrador(usuarioSesion), + usuarioSesion.NombreDominio); + + if (!resultadoUsuario.Success || + resultadoUsuario.Data == null) + { + return resultadoUsuario.Success + ? Error( + "El usuario seleccionado ya no está disponible.") + : DbResult.Fail( + resultadoUsuario.UserMessage, + resultadoUsuario.TechnicalMessage, + resultadoUsuario.Exception); + } + + UsuarioCambioContextoModel usuario = resultadoUsuario.Data; + + return DbResult.Ok( + new UserSessionModel + { + CveUsuario = usuario.CveUsuario, + CveUsuarioOriginal = + UsuarioAdministrador(usuarioSesion), + CveRol = usuario.CveRol, + CveRolOriginal = usuarioSesion.CveRolOriginal > 0 + ? usuarioSesion.CveRolOriginal + : usuarioSesion.CveRol, + CveEmpresa = usuarioSesion.CveEmpresa, + CveCliente = usuario.CveCliente, + NombreUsuario = usuario.NombreUsuario, + Nombre = usuario.NombreUsuario, + CorreoElectronico = usuario.CorreoElectronico, + NombreRol = usuario.NombreRol, + NombreDominio = usuarioSesion.NombreDominio, + TokenSesion = usuarioSesion.TokenSesion, + DebeCambiarContrasena = + usuario.DebeCambiarContrasena, + EsAdmin = usuarioSesion.EsAdmin, + PuedeCambiarUsuario = + usuarioSesion.PuedeCambiarUsuario + }); + } + + private static bool PuedeCambiarUsuario( + UserSessionModel usuarioSesion) + { + return usuarioSesion != null && + usuarioSesion.PuedeCambiarUsuario && + UsuarioAdministrador(usuarioSesion) > 0; + } + + private static int UsuarioAdministrador( + UserSessionModel usuarioSesion) + { + return usuarioSesion.CveUsuarioOriginal > 0 + ? usuarioSesion.CveUsuarioOriginal + : usuarioSesion.CveUsuario; + } + + private static DbResult Error(string mensaje) + { + return DbResult.Fail( + mensaje, + mensaje, + null); + } + } +} diff --git a/SIG.Web/App_Code/Services/Security/WebFormsUserContextProvider.cs b/SIG.Web/App_Code/Services/Security/WebFormsUserContextProvider.cs index 24778d7..f5fb526 100644 --- a/SIG.Web/App_Code/Services/Security/WebFormsUserContextProvider.cs +++ b/SIG.Web/App_Code/Services/Security/WebFormsUserContextProvider.cs @@ -3,7 +3,7 @@ using SIG.Web.AppCode.Contracts.Security; using SIG.Web.AppCode.Session; namespace SIG.Web.AppCode.Services.Security { - public sealed class WebFormsUserContextProvider : Contracts.Security.IUserContextProvider + public sealed class WebFormsUserContextProvider : IUserContextProvider { public bool IsAuthenticated() { @@ -20,16 +20,29 @@ namespace SIG.Web.AppCode.Services.Security return HttpContext.Current.Session[SessionKeys.CurrentUser] as UserSessionModel; } + public void SetCurrentUser(UserSessionModel user) { - if (HttpContext.Current == null || HttpContext.Current.Session == null) - return; HttpContext.Current.Session[SessionKeys.CurrentUser] = user; - HttpContext.Current.Session[SessionKeys.TokenSesion] = user != null ? user.TokenSesion : null; + if (HttpContext.Current == null || + HttpContext.Current.Session == null) + { + return; + } + + HttpContext.Current.Session[SessionKeys.CurrentUser] = user; + HttpContext.Current.Session[SessionKeys.TokenSesion] = + user != null ? user.TokenSesion : null; } + public void Clear() { - if (HttpContext.Current == null || HttpContext.Current.Session == null) - return; HttpContext.Current.Session.Remove(SessionKeys.CurrentUser); + if (HttpContext.Current == null || + HttpContext.Current.Session == null) + { + return; + } + + HttpContext.Current.Session.Remove(SessionKeys.CurrentUser); HttpContext.Current.Session.Remove(SessionKeys.TokenSesion); } } diff --git a/SIG.Web/App_Code/Services/Tramites/TramiteCatalogBitacoraFactory.cs b/SIG.Web/App_Code/Services/Tramites/TramiteCatalogBitacoraFactory.cs index 0862ac6..9e91b68 100644 --- a/SIG.Web/App_Code/Services/Tramites/TramiteCatalogBitacoraFactory.cs +++ b/SIG.Web/App_Code/Services/Tramites/TramiteCatalogBitacoraFactory.cs @@ -182,6 +182,7 @@ namespace SIG.Web.AppCode.Services.Tramites : Fields( Field("CveTramitePago", Value(anterior, item => item.CveTramitePago), actual.CveTramitePago), Field("CvePS", Value(anterior, item => item.CvePS), actual.CvePS), + Field("CveUM", Value(anterior, item => item.CveUM), actual.CveUM), Field("Cantidad", Value(anterior, item => item.Cantidad), actual.Cantidad))); evento.Relaciones.Add(Relation( @@ -192,6 +193,10 @@ namespace SIG.Web.AppCode.Services.Tramites "ProductosServicios", "CvePS", valor.CvePS)); + evento.Relaciones.Add(Relation( + "UnidadesMedida", + "CveUnidadMedida", + valor.CveUM)); return evento; } diff --git a/SIG.Web/App_Code/Services/Tramites/TramiteCatalogService.cs b/SIG.Web/App_Code/Services/Tramites/TramiteCatalogService.cs index f3f94e4..8279726 100644 --- a/SIG.Web/App_Code/Services/Tramites/TramiteCatalogService.cs +++ b/SIG.Web/App_Code/Services/Tramites/TramiteCatalogService.cs @@ -328,9 +328,11 @@ namespace SIG.Web.AppCode.Services.Tramites if (model == null || model.CveTramitePago <= 0 || model.CvePS <= 0 || + model.CveUM <= 0 || model.Cantidad <= 0) { - return Fail("Seleccione el producto o servicio y capture una cantidad mayor que cero."); + return Fail( + "Seleccione el producto o servicio, la unidad de medida y capture una cantidad mayor que cero."); } return Save( diff --git a/SIG.Web/App_Code/Services/Ventas/VentaTramiteService.cs b/SIG.Web/App_Code/Services/Ventas/VentaTramiteService.cs new file mode 100644 index 0000000..e2f46b1 --- /dev/null +++ b/SIG.Web/App_Code/Services/Ventas/VentaTramiteService.cs @@ -0,0 +1,621 @@ +using System; +using System.Collections.Generic; +using SIG.Web.AppCode.Contracts.Ventas; +using SIG.Web.AppCode.Contracts.Facturacion; +using SIG.Web.AppCode.Infrastructure.Transactions; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Ventas; +using SIG.Web.AppCode.Models.Facturacion; + +namespace SIG.Web.AppCode.Services.Ventas +{ + public sealed class ServicioVentaTramite : IServicioVentaTramite + { + private readonly IRepositorioVentaTramite _repositorio; + private readonly ICfdiTimbradoService _servicioTimbrado; + + public ServicioVentaTramite( + IRepositorioVentaTramite repositorio, + ICfdiTimbradoService servicioTimbrado) + { + if (repositorio == null) + { + throw new ArgumentNullException("repositorio"); + } + + _repositorio = repositorio; + _servicioTimbrado = servicioTimbrado ?? + throw new ArgumentNullException("servicioTimbrado"); + } + + public DbResult> ListarPagosPendientes( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (cveFraccionamiento <= 0) + { + return Fallar>( + "Seleccione un fraccionamiento válido."); + } + + return _repositorio.ListarPagosPendientes( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult> ListarPagosRealizados( + int cveFraccionamiento, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (cveFraccionamiento <= 0) + { + return Fallar>( + "Seleccione un fraccionamiento válido."); + } + + return _repositorio.ListarPagosRealizados( + cveFraccionamiento, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult ObtenerVenta( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (cveSolicitud <= 0 || cveTramitePago <= 0) + { + return Fallar( + "Seleccione un pago pendiente válido."); + } + + DbResult contextoResultado = + _repositorio.ObtenerContexto( + cveSolicitud, + cveTramitePago, + cveUsuarioEjecuta, + nombreDominio); + + if (!contextoResultado.Success || contextoResultado.Data == null) + { + return contextoResultado.Success + ? Fallar( + "No fue posible obtener los datos del pago pendiente.") + : contextoResultado; + } + + DbResult> conceptosResultado = + _repositorio.ListarConceptos( + cveSolicitud, + cveTramitePago, + cveUsuarioEjecuta, + nombreDominio); + + if (!conceptosResultado.Success) + { + return DbResult.Fail( + conceptosResultado.UserMessage, + conceptosResultado.TechnicalMessage, + conceptosResultado.Exception); + } + + List conceptos = + conceptosResultado.Data ?? + new List(); + + if (conceptos.Count == 0) + { + return Fallar( + "El pago pendiente no tiene conceptos configurados."); + } + + contextoResultado.Data.Conceptos = conceptos; + return contextoResultado; + } + + public DbResult GenerarVenta( + ModeloCapturaVentaTramite venta, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (venta == null || + venta.CveSolicitud <= 0 || + venta.CveTramitePago <= 0) + { + return Fallar("Seleccione un pago pendiente válido."); + } + + venta.Observaciones = NormalizarObservaciones( + venta.Observaciones); + + using (var transaccion = new TransactionLogic()) + { + DbResult resultado = _repositorio.Generar( + venta, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success) + { + return resultado; + } + + transaccion.Commit(); + return resultado; + } + } + + public DbResult PagarVenta( + ModeloPagoVentaTramite pago, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (pago == null || + pago.CveSolicitud <= 0 || + pago.CveTramitePago <= 0 || + pago.Importe <= 0m || + pago.FechaPago == DateTime.MinValue || + pago.CveFormaPago <= 0) + { + return Fallar( + "Capture el monto, la fecha y la forma de pago."); + } + + pago.Observaciones = NormalizarTexto( + pago.Observaciones, + 300); + + using (var transaccion = new TransactionLogic()) + { + DbResult resultado = + _repositorio.Pagar( + pago, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success) + { + return resultado; + } + + transaccion.Commit(); + return resultado; + } + } + + public DbResult ObtenerOpcionesPago( + int cveSolicitud, + int cveTramitePago, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (cveSolicitud <= 0 || cveTramitePago <= 0) + { + return Fallar( + "Seleccione una venta generada válida."); + } + + return _repositorio.ObtenerOpcionesPago( + cveSolicitud, + cveTramitePago, + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult + ObtenerOpcionesCondicionesPago( + int cveUsuarioEjecuta, + string nombreDominio) + { + return _repositorio.ObtenerOpcionesCondicionesPago( + cveUsuarioEjecuta, + nombreDominio); + } + + public DbResult GuardarCondicionesPago( + ModeloCondicionesPagoVentaTramite condiciones, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (condiciones == null || + condiciones.CveSolicitud <= 0 || + condiciones.CveTramitePago <= 0 || + condiciones.CveMetodoPago <= 0 || + condiciones.CveFormaPago <= 0 || + condiciones.FechaVencimiento == DateTime.MinValue) + { + return Fallar( + "Capture condiciones de pago válidas."); + } + + using (var transaccion = new TransactionLogic()) + { + DbResult resultado = + _repositorio.GuardarCondicionesPago( + condiciones, + cveUsuarioEjecuta, + nombreDominio); + + if (resultado.Success) + { + transaccion.Commit(); + } + + return resultado; + } + } + + public DbResult GuardarConcepto( + ModeloCapturaConceptoVentaTramite concepto, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (concepto == null || + concepto.CveSolicitud <= 0 || + concepto.CveTramitePago <= 0 || + concepto.CvePS <= 0 || + concepto.Cantidad <= 0m || + concepto.PrecioUnitario < 0m) + { + return Fallar( + "Capture un producto, cantidad y precio unitario válidos."); + } + + using (var transaccion = new TransactionLogic()) + { + DbResult resultado = _repositorio.GuardarConcepto( + concepto, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success) + { + return resultado; + } + + transaccion.Commit(); + return resultado; + } + } + + public DbResult EliminarConcepto( + int cveSolicitud, + int cveTramitePago, + int cveVentaDetalle, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (cveSolicitud <= 0 || + cveTramitePago <= 0 || + cveVentaDetalle <= 0) + { + return Fallar( + "Seleccione un concepto válido para eliminar."); + } + + using (var transaccion = new TransactionLogic()) + { + DbResult resultado = _repositorio.EliminarConcepto( + cveSolicitud, + cveTramitePago, + cveVentaDetalle, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success) + { + return resultado; + } + + transaccion.Commit(); + return resultado; + } + } + + public DbResult TimbrarVenta( + ModeloTimbradoVentaTramite timbrado, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (timbrado == null || + timbrado.CveSolicitud <= 0 || + timbrado.CveTramitePago <= 0 || + timbrado.CveEmpresa <= 0) + { + return Fallar( + "Seleccione una venta generada válida para timbrar."); + } + + DbResult datosResultado = + _repositorio.ObtenerDatosCfdi( + timbrado.CveSolicitud, + timbrado.CveTramitePago, + cveUsuarioEjecuta, + nombreDominio); + + if (!datosResultado.Success || datosResultado.Data == null) + { + return datosResultado.Success + ? Fallar( + "No fue posible preparar los datos fiscales de la venta.") + : CopiarFallo( + datosResultado); + } + + ModeloDatosCfdiVentaTramite datos = datosResultado.Data; + CfdiSolicitudModel solicitud = CrearSolicitudCfdi( + datos, + timbrado.CveEmpresa); + DbResult borradorResultado = + _servicioTimbrado.GuardarBorrador( + solicitud, + cveUsuarioEjecuta, + nombreDominio); + + if (!borradorResultado.Success) + { + return CopiarFallo(borradorResultado); + } + + DbResult timbradoResultado = + _servicioTimbrado.Timbrar( + borradorResultado.Data, + null, + cveUsuarioEjecuta, + nombreDominio); + + if (!timbradoResultado.Success || + timbradoResultado.Data == null || + !timbradoResultado.Data.TimbradoExitoso) + { + return timbradoResultado.Success + ? Fallar( + timbradoResultado.Data == null || + string.IsNullOrWhiteSpace(timbradoResultado.Data.Mensaje) + ? "El PAC no confirmó el timbrado." + : timbradoResultado.Data.Mensaje) + : CopiarFallo( + timbradoResultado); + } + + using (var transaccion = new TransactionLogic()) + { + DbResult actualizarResultado = + _repositorio.MarcarTimbrada( + datos.CveVenta, + borradorResultado.Data, + timbradoResultado.Data.Uuid, + DateTime.Now, + cveUsuarioEjecuta, + nombreDominio); + + if (!actualizarResultado.Success) + { + return CopiarFallo(actualizarResultado); + } + + transaccion.Commit(); + } + + return DbResult.Ok( + timbradoResultado.Data.Uuid); + } + + public DbResult CancelarTimbre( + ModeloCancelacionTimbreVentaTramite cancelacion, + int cveUsuarioEjecuta, + string nombreDominio) + { + if (cancelacion == null || + cancelacion.CveSolicitud <= 0 || + cancelacion.CveTramitePago <= 0 || + !MotivoCancelacionValido(cancelacion.Motivo)) + { + return Fallar( + "Seleccione un motivo de cancelación válido."); + } + + cancelacion.UuidSustitucion = NormalizarUuid( + cancelacion.UuidSustitucion); + + if (cancelacion.Motivo == "01" && + string.IsNullOrWhiteSpace(cancelacion.UuidSustitucion)) + { + return Fallar( + "Capture el UUID que sustituirá al timbre cancelado."); + } + + DbResult contextoResultado = + ObtenerVenta( + cancelacion.CveSolicitud, + cancelacion.CveTramitePago, + cveUsuarioEjecuta, + nombreDominio); + + if (!contextoResultado.Success || + contextoResultado.Data == null || + !contextoResultado.Data.CveVenta.HasValue || + !contextoResultado.Data.CveCfdiDocumento.HasValue) + { + return contextoResultado.Success + ? Fallar( + "La venta no tiene un timbre vigente para cancelar.") + : CopiarFallo( + contextoResultado); + } + + ModeloContextoVentaTramite contexto = contextoResultado.Data; + DbResult resultado = + _servicioTimbrado.Cancelar( + new CfdiCancelacionSolicitudModel + { + CveCfdiDocumento = + contexto.CveCfdiDocumento.Value, + Motivo = cancelacion.Motivo, + UuidSustitucion = cancelacion.UuidSustitucion + }, + null, + cveUsuarioEjecuta, + nombreDominio); + + if (!resultado.Success || + resultado.Data == null || + !resultado.Data.CancelacionExitosa) + { + return resultado.Success + ? Fallar( + resultado.Data == null || + string.IsNullOrWhiteSpace(resultado.Data.Mensaje) + ? "El PAC no confirmó la cancelación." + : resultado.Data.Mensaje) + : CopiarFallo( + resultado); + } + + using (var transaccion = new TransactionLogic()) + { + DbResult actualizarResultado = + _repositorio.MarcarTimbreCancelado( + contexto.CveVenta.Value, + contexto.CveCfdiDocumento.Value, + cancelacion.Motivo, + cveUsuarioEjecuta, + nombreDominio); + + if (!actualizarResultado.Success) + { + return CopiarFallo(actualizarResultado); + } + + transaccion.Commit(); + } + + return DbResult.Ok(resultado.Data.Mensaje); + } + + private static CfdiSolicitudModel CrearSolicitudCfdi( + ModeloDatosCfdiVentaTramite datos, + int cveEmpresa) + { + var solicitud = new CfdiSolicitudModel + { + CveCfdiDocumento = datos.CveCfdiDocumento ?? 0, + CveEmpresa = cveEmpresa, + CveCliente = datos.CveCliente, + TipoOrigen = "VENTA", + CveOrigen = datos.CveVenta, + ReferenciaOrigen = "Venta de trámite " + datos.CveVenta, + Serie = datos.Serie, + Folio = datos.Folio.ToString(), + FechaEmision = datos.Fecha, + TipoComprobante = "I", + FormaPago = datos.FormaPago, + MetodoPago = datos.MetodoPago, + Moneda = datos.Moneda, + TipoCambio = datos.TipoCambio, + Exportacion = "01" + }; + + foreach (ModeloConceptoCfdiVentaTramite origen in datos.Conceptos) + { + var concepto = new CfdiConceptoModel + { + ClaveProductoServicio = origen.ClaveProductoServicio, + NumeroIdentificacion = origen.NumeroIdentificacion, + Cantidad = origen.Cantidad, + ClaveUnidad = origen.ClaveUnidad, + Unidad = origen.Unidad, + Descripcion = origen.Descripcion, + ValorUnitario = origen.ValorUnitario, + Descuento = origen.Descuento, + ObjetoImpuesto = origen.ObjetoImpuesto + }; + + if (origen.ObjetoImpuesto != "01") + { + concepto.Impuestos.Add( + new CfdiImpuestoConceptoModel + { + EsRetencion = false, + Base = origen.BaseIVA, + Impuesto = "002", + TipoFactor = "Tasa", + TasaOCuota = origen.TasaIVA, + Importe = origen.ImporteIVA + }); + } + + solicitud.Conceptos.Add(concepto); + } + + return solicitud; + } + + private static bool MotivoCancelacionValido(string motivo) + { + return motivo == "01" || + motivo == "02" || + motivo == "03" || + motivo == "04"; + } + + private static string NormalizarUuid(string uuid) + { + return string.IsNullOrWhiteSpace(uuid) + ? null + : uuid.Trim().ToUpperInvariant(); + } + + private static DbResult CopiarFallo( + DbResult origen) + { + return DbResult.Fail( + origen.UserMessage, + origen.TechnicalMessage, + origen.Exception); + } + + private static string NormalizarObservaciones(string observaciones) + { + if (string.IsNullOrWhiteSpace(observaciones)) + { + return string.Empty; + } + + string valor = observaciones.Trim(); + + return valor.Length <= 2000 + ? valor + : valor.Substring(0, 2000); + } + + private static string NormalizarTexto( + 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 Fallar(string mensaje) + { + return DbResult.Fail( + mensaje, + mensaje, + new ArgumentException(mensaje)); + } + } +} diff --git a/SIG.Web/App_Code/Session/UserSessionModel.cs b/SIG.Web/App_Code/Session/UserSessionModel.cs index 7d2c088..454ecbe 100644 --- a/SIG.Web/App_Code/Session/UserSessionModel.cs +++ b/SIG.Web/App_Code/Session/UserSessionModel.cs @@ -1,10 +1,16 @@ +using System; + namespace SIG.Web.AppCode.Session { + [Serializable] public sealed class UserSessionModel { public int CveUsuario { get; set; } + public int CveUsuarioOriginal { get; set; } public int CveRol { get; set; } + public int CveRolOriginal { get; set; } public int CveEmpresa { get; set; } + public int CveCliente { get; set; } public string NombreUsuario { get; set; } public string Nombre { get; set; } public string CorreoElectronico { get; set; } @@ -12,5 +18,12 @@ namespace SIG.Web.AppCode.Session public string NombreDominio { get; set; } public string TokenSesion { get; set; } public bool DebeCambiarContrasena { get; set; } + public bool EsAdmin { get; set; } + public bool PuedeCambiarUsuario { get; set; } + + public bool EsDesarrollador + { + get { return CveRol == 3; } + } } -} \ No newline at end of file +} diff --git a/SIG.Web/App_Code/SigControls/BitacoraGrid.cs b/SIG.Web/App_Code/SigControls/BitacoraGrid.cs index 08a15cb..0731cef 100644 --- a/SIG.Web/App_Code/SigControls/BitacoraGrid.cs +++ b/SIG.Web/App_Code/SigControls/BitacoraGrid.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Globalization; using System.Linq; using System.Web.UI; +using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using Newtonsoft.Json; using SIG.Web.AppCode.Configuration; @@ -35,9 +36,18 @@ namespace SIG.Web.AppCode.SigControls private Panel _scrollPanel; private GridView _grid; private Panel _pagerPanel; + private Panel _pagerActionsPanel; private LinkButton _previousButton; private Label _pagerSummaryLabel; private LinkButton _nextButton; + private Panel _paginationSliderPanel; + private Label _paginationSliderMinimumLabel; + private Panel _paginationSliderTrack; + private Label _paginationSliderLabel; + private HtmlInputGenericControl _paginationSlider; + private Label _paginationSliderMaximumLabel; + private HiddenField _requestedPageField; + private LinkButton _goToPageButton; private Panel _detailModal; private Label _detailTitleLabel; private Label _detailDescriptionLabel; @@ -501,7 +511,7 @@ namespace SIG.Web.AppCode.SigControls ShowHeaderWhenEmpty = true, UseAccessibleHeader = true }; - _grid.DataKeyNames = new[] { "CveBitacora", "IndiceAbsoluto" }; + _grid.DataKeyNames = new[] { "CveBitacora" }; _grid.RowDataBound += Grid_RowDataBound; _grid.RowCommand += Grid_RowCommand; @@ -558,6 +568,11 @@ namespace SIG.Web.AppCode.SigControls Visible = false }; + _pagerActionsPanel = new Panel + { + CssClass = "sig-bitacora-grid-pager-actions" + }; + _previousButton = new LinkButton { ID = "BtnAnterior", @@ -582,9 +597,73 @@ namespace SIG.Web.AppCode.SigControls }; _nextButton.Click += NextButton_Click; - _pagerPanel.Controls.Add(_previousButton); - _pagerPanel.Controls.Add(_pagerSummaryLabel); - _pagerPanel.Controls.Add(_nextButton); + _paginationSliderPanel = new Panel + { + CssClass = "sig-bitacora-grid-pagination-slider" + }; + + _paginationSliderMinimumLabel = new Label + { + CssClass = "sig-bitacora-grid-pagination-slider-endpoint", + Text = "1" + }; + + _paginationSliderTrack = new Panel + { + CssClass = "sig-bitacora-grid-pagination-slider-track" + }; + + _paginationSliderLabel = new Label + { + CssClass = "sig-bitacora-grid-pagination-slider-label" + }; + _paginationSliderLabel.Attributes["aria-live"] = "polite"; + + _paginationSlider = new HtmlInputGenericControl("range") + { + ID = "RngPagina" + }; + _paginationSlider.Attributes["class"] = + "sig-bitacora-grid-pagination-slider-input " + + "js-sig-bitacora-grid-pagination-slider"; + + _paginationSliderMaximumLabel = new Label + { + CssClass = "sig-bitacora-grid-pagination-slider-endpoint" + }; + + _requestedPageField = new HiddenField + { + ID = "HfPaginaSolicitada" + }; + + _goToPageButton = new LinkButton + { + ID = "BtnIrPagina", + CssClass = + "sig-bitacora-grid-page-request " + + "js-sig-bitacora-grid-page-request", + CausesValidation = false, + Text = "Ir a página" + }; + _goToPageButton.Click += GoToPageButton_Click; + + _pagerActionsPanel.Controls.Add(_previousButton); + _pagerActionsPanel.Controls.Add(_pagerSummaryLabel); + _pagerActionsPanel.Controls.Add(_nextButton); + + _paginationSliderTrack.Controls.Add(_paginationSliderLabel); + _paginationSliderTrack.Controls.Add(_paginationSlider); + _paginationSliderPanel.Controls.Add( + _paginationSliderMinimumLabel); + _paginationSliderPanel.Controls.Add(_paginationSliderTrack); + _paginationSliderPanel.Controls.Add( + _paginationSliderMaximumLabel); + + _pagerPanel.Controls.Add(_paginationSliderPanel); + _pagerPanel.Controls.Add(_pagerActionsPanel); + _pagerPanel.Controls.Add(_requestedPageField); + _pagerPanel.Controls.Add(_goToPageButton); _rootPanel.Controls.Add(_pagerPanel); } @@ -747,6 +826,56 @@ namespace SIG.Web.AppCode.SigControls ? "1" : "0"; _rootPanel.Attributes["data-sig-scroll-anchor"] = ScrollAnchor; + + int renderedTotalPages = Math.Max(TotalPaginas, 1); + int renderedCurrentPage = Math.Min( + Math.Max(PaginaActual, 1), + renderedTotalPages); + decimal sliderPosition = renderedTotalPages <= 1 + ? 0 + : (renderedCurrentPage - 1) * 100m / + (renderedTotalPages - 1); + string sliderText = string.Format( + CultureInfo.CurrentCulture, + "Página {0} de {1}", + renderedCurrentPage, + renderedTotalPages); + + _paginationSlider.Attributes["min"] = "1"; + _paginationSlider.Attributes["max"] = + renderedTotalPages.ToString(CultureInfo.InvariantCulture); + _paginationSlider.Attributes["step"] = "1"; + _paginationSlider.Attributes["value"] = + renderedCurrentPage.ToString(CultureInfo.InvariantCulture); + _paginationSlider.Attributes["aria-label"] = + "Seleccionar página de la bitácora"; + _paginationSlider.Attributes["aria-valuemin"] = "1"; + _paginationSlider.Attributes["aria-valuemax"] = + renderedTotalPages.ToString(CultureInfo.InvariantCulture); + _paginationSlider.Attributes["aria-valuenow"] = + renderedCurrentPage.ToString(CultureInfo.InvariantCulture); + _paginationSlider.Attributes["aria-valuetext"] = sliderText; + _paginationSlider.Attributes["data-sig-current-page"] = + renderedCurrentPage.ToString(CultureInfo.InvariantCulture); + _paginationSlider.Attributes["data-sig-page-field-id"] = + _requestedPageField.ClientID; + _paginationSlider.Disabled = TotalPaginas <= 1; + _requestedPageField.Value = string.Empty; + + _paginationSliderLabel.Text = sliderText; + _paginationSliderMaximumLabel.Text = + renderedTotalPages.ToString(CultureInfo.CurrentCulture); + _paginationSliderTrack.Style[ + "--sig-bitacora-page-position"] = + sliderPosition.ToString( + "0.####", + CultureInfo.InvariantCulture) + "%"; + _paginationSliderTrack.Attributes["data-sig-slider-edge"] = + renderedCurrentPage <= 1 + ? "start" + : renderedCurrentPage >= renderedTotalPages + ? "end" + : "middle"; } private void RegisterAsyncControls() @@ -764,6 +893,7 @@ namespace SIG.Web.AppCode.SigControls _secondaryActionButton); scriptManager.RegisterAsyncPostBackControl(_previousButton); scriptManager.RegisterAsyncPostBackControl(_nextButton); + scriptManager.RegisterAsyncPostBackControl(_goToPageButton); foreach (GridViewRow row in _grid.Rows) { @@ -814,15 +944,9 @@ namespace SIG.Web.AppCode.SigControls TotalPaginas = pagina.TotalPaginas; TotalRegistros = pagina.TotalRegistros; - int firstIndex = checked( - (PaginaActual - 1) * RegistrosPorPagina); - List rows = (pagina.Registros ?? new List()) - .Select( - (item, index) => CreateGridRow( - item, - firstIndex + index)) + .Select(CreateGridRow) .ToList(); _grid.DataSource = rows; @@ -833,16 +957,25 @@ namespace SIG.Web.AppCode.SigControls _emptyPanel.Visible = pagina.TotalRegistros == 0; _scrollPanel.Visible = pagina.TotalRegistros > 0; _pagerPanel.Visible = pagina.TotalRegistros > 0; - _previousButton.Visible = PaginaActual > 1; - _nextButton.Visible = + _previousButton.Visible = true; + _previousButton.Enabled = PaginaActual > 1; + _nextButton.Visible = true; + _nextButton.Enabled = TotalPaginas > 0 && PaginaActual < TotalPaginas; + int firstVisibleRecord = (int)Math.Min( + ((long)(PaginaActual - 1) * RegistrosPorPagina) + 1L, + TotalRegistros); + int lastVisibleRecord = (int)Math.Min( + (long)PaginaActual * RegistrosPorPagina, + TotalRegistros); _pagerSummaryLabel.Text = string.Format( CultureInfo.CurrentCulture, - "Página {0} de {1} · {2} movimientos · {3} por página", - PaginaActual, - Math.Max(TotalPaginas, 1), + "Mostrando {0}–{1} de {2} movimientos · Página {3} de {4}", + firstVisibleRecord, + lastVisibleRecord, TotalRegistros, - RegistrosPorPagina); + PaginaActual, + Math.Max(TotalPaginas, 1)); } private void BindError(string message) @@ -860,14 +993,10 @@ namespace SIG.Web.AppCode.SigControls TotalRegistros = 0; } - private void BindDetail(long cveBitacora, int absoluteIndex) + private void BindDetail(long cveBitacora) { - BitacoraConsultaModel detailQuery = BuildConsulta( - absoluteIndex + 1, - 1); - - DbResult> result = - AppServices.BitacoraService.Consultar(detailQuery); + DbResult result = + AppServices.BitacoraService.ConsultarDetalle(cveBitacora); if (!result.Success) { @@ -875,16 +1004,12 @@ namespace SIG.Web.AppCode.SigControls return; } - BitacoraModel movement = result.Data == null || - result.Data.Registros == null - ? null - : result.Data.Registros.FirstOrDefault(); + BitacoraModel movement = result.Data; - if (movement == null || movement.CveBitacora != cveBitacora) + if (movement == null) { ShowDetailError( - "El movimiento cambió de posición mientras se consultaba. " + - "Actualice la bitácora e intente nuevamente."); + "No se encontró el movimiento de bitácora solicitado."); return; } @@ -970,13 +1095,11 @@ namespace SIG.Web.AppCode.SigControls } private static BitacoraGridRowModel CreateGridRow( - BitacoraModel item, - int absoluteIndex) + BitacoraModel item) { return new BitacoraGridRowModel { CveBitacora = item.CveBitacora, - IndiceAbsoluto = absoluteIndex, Entidad = item.NombreTabla, Movimiento = string.IsNullOrWhiteSpace(item.NombreAccion) ? item.TipoMovimiento @@ -1124,11 +1247,8 @@ namespace SIG.Web.AppCode.SigControls } button.CommandName = "VerDetalle"; - button.CommandArgument = string.Format( - CultureInfo.InvariantCulture, - "{0}|{1}", - rowModel.CveBitacora, - rowModel.IndiceAbsoluto); + button.CommandArgument = rowModel.CveBitacora.ToString( + CultureInfo.InvariantCulture); } private void Grid_RowCommand( @@ -1143,31 +1263,21 @@ namespace SIG.Web.AppCode.SigControls return; } - string[] parts = Convert.ToString(e.CommandArgument) - .Split('|'); long cveBitacora; - int absoluteIndex; - if (parts.Length != 2 || - !long.TryParse( - parts[0], + if (!long.TryParse( + Convert.ToString(e.CommandArgument), NumberStyles.Integer, CultureInfo.InvariantCulture, out cveBitacora) || - !int.TryParse( - parts[1], - NumberStyles.Integer, - CultureInfo.InvariantCulture, - out absoluteIndex) || - cveBitacora <= 0 || - absoluteIndex < 0) + cveBitacora <= 0) { ShowDetailError( "No fue posible identificar el movimiento seleccionado."); return; } - BindDetail(cveBitacora, absoluteIndex); + BindDetail(cveBitacora); } private void PreviousButton_Click(object sender, EventArgs e) @@ -1196,6 +1306,30 @@ namespace SIG.Web.AppCode.SigControls UpdateListPanelIfNeeded(); } + private void GoToPageButton_Click(object sender, EventArgs e) + { + int requestedPage; + + if (!int.TryParse( + _requestedPageField.Value, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out requestedPage) || + TotalPaginas <= 1 || + requestedPage < 1 || + requestedPage > TotalPaginas || + requestedPage == PaginaActual) + { + _requestedPageField.Value = string.Empty; + return; + } + + PaginaActual = requestedPage; + _requestedPageField.Value = string.Empty; + BindResumen(); + UpdateListPanelIfNeeded(); + } + private void RecordsPerPageSelector_SelectedIndexChanged( object sender, EventArgs e) @@ -1287,7 +1421,6 @@ namespace SIG.Web.AppCode.SigControls private sealed class BitacoraGridRowModel { public long CveBitacora { get; set; } - public int IndiceAbsoluto { get; set; } public string Entidad { get; set; } public string Movimiento { get; set; } public string Descripcion { get; set; } diff --git a/SIG.Web/Imagenes/favicon.ico b/SIG.Web/Imagenes/favicon.ico new file mode 100644 index 0000000..b5aa4ea Binary files /dev/null and b/SIG.Web/Imagenes/favicon.ico differ diff --git a/SIG.Web/Pages/Catalogos/Clasificaciones.aspx b/SIG.Web/Pages/Catalogos/Clasificaciones.aspx new file mode 100644 index 0000000..62ff287 --- /dev/null +++ b/SIG.Web/Pages/Catalogos/Clasificaciones.aspx @@ -0,0 +1,241 @@ +<%@ Page Title="Clasificación" + Language="C#" + MasterPageFile="~/Site.master" + AutoEventWireup="true" + CodeFile="Clasificaciones.aspx.cs" + Inherits="SIG.Web.Pages.Catalogos.Clasificaciones" %> + + + + + + + + +
  • + + + Nueva clasificación + +
  • +
    + + + +
    +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    + + + + + +
    + + + + diff --git a/SIG.Web/Pages/Catalogos/Clasificaciones.aspx.cs b/SIG.Web/Pages/Catalogos/Clasificaciones.aspx.cs new file mode 100644 index 0000000..ad03de5 --- /dev/null +++ b/SIG.Web/Pages/Catalogos/Clasificaciones.aspx.cs @@ -0,0 +1,402 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; +using SIG.Web.AppCode.Security; +using SIG.Web.AppCode.SigControls; + +namespace SIG.Web.Pages.Catalogos +{ + public partial class Clasificaciones : ClsPaginaCatalogoInterno + { + private int CveClasificacionActual + { + get + { + return ViewState["CveClasificacionActual"] == null + ? 0 + : (int)ViewState["CveClasificacionActual"]; + } + set + { + ViewState["CveClasificacionActual"] = value; + } + } + + private int CveClasificacionBitacoraActual + { + get + { + return ViewState["CveClasificacionBitacoraActual"] == null + ? 0 + : (int)ViewState["CveClasificacionBitacoraActual"]; + } + set + { + ViewState["CveClasificacionBitacoraActual"] = value; + } + } + + private string NombreClasificacionBitacoraActual + { + get + { + return Convert.ToString( + ViewState["NombreClasificacionBitacoraActual"]); + } + set + { + ViewState["NombreClasificacionBitacoraActual"] = value; + } + } + + protected void Page_Load(object sender, EventArgs e) + { + if (IsPostBack) + { + return; + } + + BindGrid(); + BindBitacora(); + SyncFilters(); + } + + protected void UcFiltros_MostrarFiltros( + object sender, + EventArgs e) + { + ShowModal("ModalFilters"); + } + + protected void UcFiltros_Consultar(object sender, EventArgs e) + { + BindGrid(); + SyncFilters(); + } + + protected void UcFiltros_FiltrosChanged( + object sender, + EventArgs e) + { + List names = UcFiltros.GetFiltros() + .Select(item => item.Nombre) + .ToList(); + + if (!names.Contains("Texto")) + { + TxtSearch.Text = string.Empty; + } + + if (!names.Contains("Inactivos")) + { + ChkInactive.Checked = false; + } + + BindGrid(); + SyncFilters(); + } + + protected void BtnApplyFilters_Click(object sender, EventArgs e) + { + BindGrid(); + SyncFilters(); + UpCatalog.Update(); + HideModal("ModalFilters"); + } + + protected void BtnNew_Click(object sender, EventArgs e) + { + CveClasificacionActual = 0; + LitModalTitle.Text = "Nueva clasificación"; + TxtCode.Text = string.Empty; + TxtClassification.Text = string.Empty; + ChkAffectable.Checked = true; + ChkActive.Checked = true; + UpEdit.Update(); + ShowModal("ModalEdit"); + } + + protected void GvClasificaciones_RowDataBound( + object sender, + GridViewRowEventArgs e) + { + if (e.Row.RowType != DataControlRowType.DataRow) + { + return; + } + + ScriptManager scriptManager = ScriptManager.GetCurrent(Page); + + if (scriptManager == null) + { + return; + } + + RegisterAsyncControl(scriptManager, e.Row, "BtnViewAudit"); + RegisterAsyncControl(scriptManager, e.Row, "BtnEdit"); + RegisterAsyncControl(scriptManager, e.Row, "BtnDelete"); + } + + protected void GvClasificaciones_RowCommand( + object sender, + GridViewCommandEventArgs e) + { + int cveClasificacion; + + if (!int.TryParse( + Convert.ToString(e.CommandArgument), + out cveClasificacion)) + { + return; + } + + if (e.CommandName == "Editar") + { + LoadEdit(cveClasificacion); + } + else if (e.CommandName == "VerBitacora") + { + SelectBitacora(cveClasificacion); + } + else if (e.CommandName == "Eliminar") + { + Delete(cveClasificacion); + } + } + + protected void BtnSave_Click(object sender, EventArgs e) + { + var clasificacion = new ClasificacionModel + { + CveClasificacion = CveClasificacionActual, + Codigo = TxtCode.Text, + Clasificacion = TxtClassification.Text, + Afectable = ChkAffectable.Checked, + EsActivo = ChkActive.Checked + }; + + DbResult result = + AppServices.ProductoCatalogService.SaveClasificacion( + clasificacion, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + ShowModal("ModalEdit"); + return; + } + + BindGrid(); + SyncFilters(); + BindBitacora(); + UpCatalog.Update(); + HideModal("ModalEdit"); + Alert( + "Clasificación guardada correctamente.", + TipoMensaje.ToastExito); + } + + protected void UcBitacoraCatalogo_AccionClick( + object sender, + EventArgs e) + { + CveClasificacionBitacoraActual = 0; + NombreClasificacionBitacoraActual = string.Empty; + BindBitacora(); + } + + private void LoadEdit(int cveClasificacion) + { + DbResult result = + AppServices.ProductoCatalogService.GetClasificacion( + cveClasificacion, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success || result.Data == null) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + CveClasificacionActual = result.Data.CveClasificacion; + LitModalTitle.Text = "Editar clasificación"; + TxtCode.Text = result.Data.Codigo; + TxtClassification.Text = result.Data.Clasificacion; + ChkAffectable.Checked = result.Data.Afectable; + ChkActive.Checked = result.Data.EsActivo; + UpEdit.Update(); + ShowModal("ModalEdit"); + } + + private void SelectBitacora(int cveClasificacion) + { + DbResult result = + AppServices.ProductoCatalogService.GetClasificacion( + cveClasificacion, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success || result.Data == null) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + CveClasificacionBitacoraActual = cveClasificacion; + NombreClasificacionBitacoraActual = result.Data.Clasificacion; + BindBitacora(); + } + + private void Delete(int cveClasificacion) + { + DbResult result = + AppServices.ProductoCatalogService.DeleteClasificacion( + cveClasificacion, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + if (CveClasificacionBitacoraActual == cveClasificacion) + { + CveClasificacionBitacoraActual = 0; + NombreClasificacionBitacoraActual = string.Empty; + } + + BindGrid(); + SyncFilters(); + BindBitacora(); + UpCatalog.Update(); + Alert( + "Clasificación eliminada correctamente.", + TipoMensaje.ToastExito); + } + + private void BindGrid() + { + DbResult> result = + AppServices.ProductoCatalogService.ListClasificaciones( + TxtSearch.Text, + ChkInactive.Checked, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgError); + return; + } + + GvClasificaciones.DataSource = + result.Data ?? new List(); + GvClasificaciones.DataBind(); + } + + private void BindBitacora() + { + bool hasClassification = CveClasificacionBitacoraActual > 0; + + UcBitacoraCatalogo.Descripcion = hasClassification + ? "Historial de " + NombreClasificacionBitacoraActual + : "Historial de clasificaciones"; + UcBitacoraCatalogo.AccionVisible = hasClassification; + UcBitacoraCatalogo.ConfigurarConsulta( + new List + { + new BitacoraCampoFiltroModel + { + NombreTablaSQL = "Clasificaciones", + NombreCampoSQL = "CveClasificacion", + Valor = hasClassification + ? CveClasificacionBitacoraActual.ToString( + CultureInfo.InvariantCulture) + : string.Empty, + SoloExistencia = !hasClassification + } + }, + new List + { + new BitacoraRelacionMostrarModel + { + Orden = 1, + NombreTablaSQL = "Clasificaciones", + NombreCampoMostrarSQL = "Clasificacion" + } + }); + UcBitacoraCatalogo.Consultar(true); + } + + private void SyncFilters() + { + var filters = new List(); + + if (!string.IsNullOrWhiteSpace(TxtSearch.Text)) + { + filters.Add( + new FiltroActivo + { + Nombre = "Texto", + Titulo = "Búsqueda", + Descripcion = TxtSearch.Text.Trim(), + Orden = 1 + }); + } + + if (ChkInactive.Checked) + { + filters.Add( + new FiltroActivo + { + Nombre = "Inactivos", + Titulo = "Estado", + Descripcion = "Incluye inactivas", + Orden = 2 + }); + } + + UcFiltros.SetFiltros(filters); + } + + private static void RegisterAsyncControl( + ScriptManager scriptManager, + GridViewRow row, + string controlId) + { + Control control = row.FindControl(controlId); + + if (control != null) + { + scriptManager.RegisterAsyncPostBackControl(control); + } + } + + private void ShowModal(string id) + { + RegistraScript( + "window.SIGTramiteCatalog.show('" + id + "');", + "Show_" + id); + } + + private void HideModal(string id) + { + RegistraScript( + "window.SIGTramiteCatalog.hide('" + id + "');", + "Hide_" + id); + } + } +} diff --git a/SIG.Web/Pages/Catalogos/EstatusSolicitud.aspx.designer.cs b/SIG.Web/Pages/Catalogos/Clasificaciones.aspx.designer.cs similarity index 74% rename from SIG.Web/Pages/Catalogos/EstatusSolicitud.aspx.designer.cs rename to SIG.Web/Pages/Catalogos/Clasificaciones.aspx.designer.cs index e347f15..d4e3305 100644 --- a/SIG.Web/Pages/Catalogos/EstatusSolicitud.aspx.designer.cs +++ b/SIG.Web/Pages/Catalogos/Clasificaciones.aspx.designer.cs @@ -1,14 +1,12 @@ namespace SIG.Web.Pages.Catalogos { - public partial class EstatusSolicitud + public partial class Clasificaciones { protected global::System.Web.UI.UpdatePanel UpActions; protected global::System.Web.UI.WebControls.LinkButton BtnNew; protected global::System.Web.UI.UpdatePanel UpCatalog; protected global::SIG.Web.AppCode.SigControls.Filtros UcFiltros; - protected global::System.Web.UI.WebControls.GridView GvEstatus; - protected global::System.Web.UI.WebControls.HiddenField HfOrderMove; - protected global::System.Web.UI.WebControls.LinkButton BtnOrderMove; + protected global::System.Web.UI.WebControls.GridView GvClasificaciones; protected global::System.Web.UI.UpdatePanel UpFilters; protected global::System.Web.UI.WebControls.TextBox TxtSearch; protected global::System.Web.UI.WebControls.CheckBox ChkInactive; @@ -16,9 +14,11 @@ namespace SIG.Web.Pages.Catalogos protected global::System.Web.UI.UpdatePanel UpEdit; protected global::System.Web.UI.WebControls.Literal LitModalTitle; protected global::System.Web.UI.WebControls.TextBox TxtCode; - protected global::System.Web.UI.WebControls.TextBox TxtStatus; - protected global::System.Web.UI.WebControls.CheckBox ChkFinal; + protected global::System.Web.UI.WebControls.TextBox TxtClassification; + protected global::System.Web.UI.WebControls.CheckBox ChkAffectable; protected global::System.Web.UI.WebControls.CheckBox ChkActive; protected global::System.Web.UI.WebControls.Button BtnSave; + protected global::SIG.Web.AppCode.SigControls.BitacoraGrid + UcBitacoraCatalogo; } } diff --git a/SIG.Web/Pages/Catalogos/DocumentosRequeridos.aspx.designer.cs b/SIG.Web/Pages/Catalogos/DocumentosRequeridos.aspx.designer.cs deleted file mode 100644 index 7b83ef4..0000000 --- a/SIG.Web/Pages/Catalogos/DocumentosRequeridos.aspx.designer.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace SIG.Web.Pages.Catalogos -{ - public partial class DocumentosRequeridos - { - protected global::System.Web.UI.UpdatePanel UpActions; - protected global::System.Web.UI.WebControls.LinkButton BtnNew; - protected global::System.Web.UI.UpdatePanel UpCatalog; - protected global::SIG.Web.AppCode.SigControls.Filtros UcFiltros; - protected global::System.Web.UI.WebControls.GridView GvItems; - protected global::System.Web.UI.WebControls.HiddenField HfOrderMove; - protected global::System.Web.UI.WebControls.LinkButton BtnOrderMove; - protected global::System.Web.UI.UpdatePanel UpFilters; - protected global::System.Web.UI.WebControls.DropDownList DdlFilterProcedure; - protected global::System.Web.UI.WebControls.CheckBox ChkInactive; - protected global::System.Web.UI.WebControls.Button BtnApplyFilters; - protected global::System.Web.UI.UpdatePanel UpEdit; - protected global::System.Web.UI.WebControls.Literal LitModalTitle; - protected global::System.Web.UI.WebControls.DropDownList DdlProcedure; - protected global::System.Web.UI.WebControls.DropDownList DdlDocument; - protected global::System.Web.UI.WebControls.CheckBox ChkRequired; - protected global::System.Web.UI.WebControls.CheckBox ChkActive; - protected global::System.Web.UI.WebControls.Button BtnSave; - } -} diff --git a/SIG.Web/Pages/Catalogos/ProductosServicios.aspx b/SIG.Web/Pages/Catalogos/ProductosServicios.aspx new file mode 100644 index 0000000..5b2d959 --- /dev/null +++ b/SIG.Web/Pages/Catalogos/ProductosServicios.aspx @@ -0,0 +1,314 @@ +<%@ Page Title="Productos" + Language="C#" + MasterPageFile="~/Site.master" + AutoEventWireup="true" + CodeFile="ProductosServicios.aspx.cs" + Inherits="SIG.Web.Pages.Catalogos.ProductosServicios" %> + + + + + + + + +
  • + + + Nuevo producto o servicio + +
  • +
    + + + +
    +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    + + + + + +
    + + + + diff --git a/SIG.Web/Pages/Catalogos/ProductosServicios.aspx.cs b/SIG.Web/Pages/Catalogos/ProductosServicios.aspx.cs new file mode 100644 index 0000000..2823675 --- /dev/null +++ b/SIG.Web/Pages/Catalogos/ProductosServicios.aspx.cs @@ -0,0 +1,541 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; +using SIG.Web.AppCode.Security; +using SIG.Web.AppCode.SigControls; + +namespace SIG.Web.Pages.Catalogos +{ + public partial class ProductosServicios : ClsPaginaCatalogoInterno + { + private int CveProductoServicioActual + { + get + { + return ViewState["CveProductoServicioActual"] == null + ? 0 + : (int)ViewState["CveProductoServicioActual"]; + } + set + { + ViewState["CveProductoServicioActual"] = value; + } + } + + private int CveProductoServicioBitacoraActual + { + get + { + return ViewState["CveProductoServicioBitacoraActual"] == null + ? 0 + : (int)ViewState["CveProductoServicioBitacoraActual"]; + } + set + { + ViewState["CveProductoServicioBitacoraActual"] = value; + } + } + + private string NombreProductoServicioBitacoraActual + { + get + { + return Convert.ToString( + ViewState["NombreProductoServicioBitacoraActual"]); + } + set + { + ViewState["NombreProductoServicioBitacoraActual"] = value; + } + } + + protected void Page_Load(object sender, EventArgs e) + { + if (IsPostBack) + { + return; + } + + BindGrid(); + BindBitacora(); + SyncFilters(); + } + + protected void UcFiltros_MostrarFiltros( + object sender, + EventArgs e) + { + ShowModal("ModalFilters"); + } + + protected void UcFiltros_Consultar(object sender, EventArgs e) + { + BindGrid(); + SyncFilters(); + } + + protected void UcFiltros_FiltrosChanged( + object sender, + EventArgs e) + { + List names = UcFiltros.GetFiltros() + .Select(item => item.Nombre) + .ToList(); + + if (!names.Contains("Texto")) + { + TxtSearch.Text = string.Empty; + } + + if (!names.Contains("Inactivos")) + { + ChkInactive.Checked = false; + } + + BindGrid(); + SyncFilters(); + } + + protected void BtnApplyFilters_Click(object sender, EventArgs e) + { + BindGrid(); + SyncFilters(); + UpCatalog.Update(); + HideModal("ModalFilters"); + } + + protected void BtnNew_Click(object sender, EventArgs e) + { + CveProductoServicioActual = 0; + + if (!BindOptions(null, null)) + { + return; + } + + LitModalTitle.Text = "Nuevo producto o servicio"; + TxtCode.Text = string.Empty; + TxtDescription.Text = string.Empty; + DdlType.SelectedValue = string.Empty; + TxtPrice.Text = "0.00"; + ChkActive.Checked = true; + UpEdit.Update(); + ShowModal("ModalEdit"); + } + + protected void GvProductosServicios_RowDataBound( + object sender, + GridViewRowEventArgs e) + { + if (e.Row.RowType != DataControlRowType.DataRow) + { + return; + } + + ScriptManager scriptManager = ScriptManager.GetCurrent(Page); + + if (scriptManager == null) + { + return; + } + + LinkButton auditButton = e.Row.FindControl("BtnViewAudit") + as LinkButton; + LinkButton editButton = e.Row.FindControl("BtnEdit") + as LinkButton; + LinkButton deleteButton = e.Row.FindControl("BtnDelete") + as LinkButton; + + if (auditButton != null) + { + scriptManager.RegisterAsyncPostBackControl(auditButton); + } + + if (editButton != null) + { + scriptManager.RegisterAsyncPostBackControl(editButton); + } + + if (deleteButton != null) + { + scriptManager.RegisterAsyncPostBackControl(deleteButton); + } + } + + protected void GvProductosServicios_RowCommand( + object sender, + GridViewCommandEventArgs e) + { + int cvePS; + + if (!int.TryParse(Convert.ToString(e.CommandArgument), out cvePS)) + { + return; + } + + if (string.Equals( + e.CommandName, + "Editar", + StringComparison.Ordinal)) + { + LoadEdit(cvePS); + return; + } + + if (string.Equals( + e.CommandName, + "VerBitacora", + StringComparison.Ordinal)) + { + SelectBitacora(cvePS); + return; + } + + if (string.Equals( + e.CommandName, + "Eliminar", + StringComparison.Ordinal)) + { + Delete(cvePS); + } + } + + protected void BtnSave_Click(object sender, EventArgs e) + { + decimal price; + + if (!TryParsePrice(TxtPrice.Text, out price)) + { + Alert( + "Capture un precio válido.", + TipoMensaje.MsgAdvertencia); + ShowModal("ModalEdit"); + return; + } + + int type; + int classification; + int measurementUnit; + + int.TryParse(DdlType.SelectedValue, out type); + int.TryParse(DdlClassification.SelectedValue, out classification); + int.TryParse( + DdlMeasurementUnit.SelectedValue, + out measurementUnit); + + var productoServicio = new ProductoServicioModel + { + CvePS = CveProductoServicioActual, + Codigo = TxtCode.Text, + PS = TxtDescription.Text, + CveTipoPS = type, + CveClasificacion = classification, + CveUnidadMedida = measurementUnit, + Precio = price, + EsActivo = ChkActive.Checked + }; + + DbResult result = AppServices.ProductoServicioService.Save( + productoServicio, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + ShowModal("ModalEdit"); + return; + } + + BindGrid(); + SyncFilters(); + BindBitacora(); + UpCatalog.Update(); + HideModal("ModalEdit"); + Alert( + "Producto o servicio guardado correctamente.", + TipoMensaje.ToastExito); + } + + protected void UcBitacoraCatalogo_AccionClick( + object sender, + EventArgs e) + { + CveProductoServicioBitacoraActual = 0; + NombreProductoServicioBitacoraActual = string.Empty; + BindBitacora(); + } + + private void LoadEdit(int cvePS) + { + DbResult result = + AppServices.ProductoServicioService.Get( + cvePS, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success || result.Data == null) + { + Alert( + string.IsNullOrWhiteSpace(result.UserMessage) + ? "No fue posible consultar el producto o servicio." + : result.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + ProductoServicioModel productoServicio = result.Data; + + if (!BindOptions( + productoServicio.CveClasificacion, + productoServicio.CveUnidadMedida)) + { + return; + } + + CveProductoServicioActual = productoServicio.CvePS; + LitModalTitle.Text = "Editar producto o servicio"; + TxtCode.Text = productoServicio.Codigo; + TxtDescription.Text = productoServicio.PS; + SelectValue( + DdlType, + productoServicio.CveTipoPS.ToString( + CultureInfo.InvariantCulture)); + SelectValue( + DdlClassification, + productoServicio.CveClasificacion.ToString( + CultureInfo.InvariantCulture)); + SelectValue( + DdlMeasurementUnit, + productoServicio.CveUnidadMedida.ToString( + CultureInfo.InvariantCulture)); + TxtPrice.Text = productoServicio.Precio.ToString( + "0.00", + CultureInfo.CurrentCulture); + ChkActive.Checked = productoServicio.EsActivo; + UpEdit.Update(); + ShowModal("ModalEdit"); + } + + private bool BindOptions( + int? cveClasificacionActual, + int? cveUnidadMedidaActual) + { + DbResult result = + AppServices.ProductoServicioService.ListOptions( + cveClasificacionActual, + cveUnidadMedidaActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgError); + return false; + } + + ProductoServicioOpcionesModel options = result.Data ?? + new ProductoServicioOpcionesModel(); + + DdlClassification.DataSource = options.Clasificaciones; + DdlClassification.DataBind(); + DdlClassification.Items.Insert( + 0, + new ListItem("Seleccione", string.Empty)); + + DdlMeasurementUnit.DataSource = options.UnidadesMedida; + DdlMeasurementUnit.DataBind(); + DdlMeasurementUnit.Items.Insert( + 0, + new ListItem("Seleccione", string.Empty)); + + return true; + } + + private void SelectBitacora(int cvePS) + { + DbResult result = + AppServices.ProductoServicioService.Get( + cvePS, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success || result.Data == null) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + CveProductoServicioBitacoraActual = cvePS; + NombreProductoServicioBitacoraActual = result.Data.PS; + BindBitacora(); + } + + private void Delete(int cvePS) + { + DbResult result = AppServices.ProductoServicioService.Delete( + cvePS, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + if (CveProductoServicioBitacoraActual == cvePS) + { + CveProductoServicioBitacoraActual = 0; + NombreProductoServicioBitacoraActual = string.Empty; + } + + BindGrid(); + SyncFilters(); + BindBitacora(); + UpCatalog.Update(); + Alert( + "Producto o servicio eliminado correctamente.", + TipoMensaje.ToastExito); + } + + private void BindGrid() + { + DbResult> result = + AppServices.ProductoServicioService.List( + TxtSearch.Text, + ChkInactive.Checked, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgError); + return; + } + + GvProductosServicios.DataSource = + result.Data ?? new List(); + GvProductosServicios.DataBind(); + } + + private void BindBitacora() + { + bool hasProduct = CveProductoServicioBitacoraActual > 0; + + UcBitacoraCatalogo.Descripcion = hasProduct && + !string.IsNullOrWhiteSpace( + NombreProductoServicioBitacoraActual) + ? "Historial de " + + NombreProductoServicioBitacoraActual + : "Historial de productos y servicios"; + UcBitacoraCatalogo.AccionVisible = hasProduct; + + UcBitacoraCatalogo.ConfigurarConsulta( + new List + { + new BitacoraCampoFiltroModel + { + NombreTablaSQL = "ProductosServicios", + NombreCampoSQL = "CvePS", + Valor = hasProduct + ? CveProductoServicioBitacoraActual.ToString( + CultureInfo.InvariantCulture) + : string.Empty, + SoloExistencia = !hasProduct + } + }, + new List + { + new BitacoraRelacionMostrarModel + { + Orden = 1, + NombreTablaSQL = "ProductosServicios", + NombreCampoMostrarSQL = "PS" + } + }); + + UcBitacoraCatalogo.Consultar(true); + } + + private void SyncFilters() + { + var filters = new List(); + + if (!string.IsNullOrWhiteSpace(TxtSearch.Text)) + { + filters.Add( + new FiltroActivo + { + Nombre = "Texto", + Titulo = "Búsqueda", + Descripcion = TxtSearch.Text.Trim(), + Orden = 1 + }); + } + + if (ChkInactive.Checked) + { + filters.Add( + new FiltroActivo + { + Nombre = "Inactivos", + Titulo = "Estado", + Descripcion = "Incluye inactivos", + Orden = 2 + }); + } + + UcFiltros.SetFiltros(filters); + } + + private static bool TryParsePrice(string value, out decimal price) + { + return decimal.TryParse( + value, + NumberStyles.Number, + CultureInfo.CurrentCulture, + out price) || + decimal.TryParse( + value, + NumberStyles.Number, + CultureInfo.InvariantCulture, + out price); + } + + private static void SelectValue( + ListControl control, + string value) + { + ListItem item = control.Items.FindByValue(value); + + if (item != null) + { + control.ClearSelection(); + item.Selected = true; + } + } + + private void ShowModal(string id) + { + RegistraScript( + "window.SIGTramiteCatalog.show('" + id + "');", + "Show_" + id); + } + + private void HideModal(string id) + { + RegistraScript( + "window.SIGTramiteCatalog.hide('" + id + "');", + "Hide_" + id); + } + } +} diff --git a/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx b/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx index 34455ab..94e1ad2 100644 --- a/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx +++ b/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx @@ -466,6 +466,9 @@ + + +
    + + @@ -806,6 +818,9 @@
    + @@ -869,5 +884,6 @@ - + diff --git a/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.cs b/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.cs index 7fc00c2..5bf6dbd 100644 --- a/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.cs +++ b/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.cs @@ -6,6 +6,7 @@ using System.Web.UI.WebControls; using SIG.Web.AppCode.Configuration; using SIG.Web.AppCode.Infrastructure.WebForms; using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; using SIG.Web.AppCode.Models.Tramites; using SIG.Web.AppCode.Security; @@ -70,6 +71,21 @@ namespace SIG.Web.Pages.Catalogos set { ViewState["CveProductoPrecioActual"] = value; } } + private List + ProductosServiciosDisponibles + { + get + { + return ViewState["ProductosServiciosDisponibles"] + as List + ?? new List(); + } + set + { + ViewState["ProductosServiciosDisponibles"] = value; + } + } + private int ActiveTabIndexActual { get { return ViewState["ActiveTabIndexActual"] as int? ?? 0; } @@ -110,6 +126,7 @@ namespace SIG.Web.Pages.Catalogos BindQuestionTypes(); BindDocumentTypes(); BindProducts(); + CargarUnidadesMedida(); LoadProcedure(); BindQuestions(); BindDocuments(); @@ -681,6 +698,7 @@ namespace SIG.Web.Pages.Catalogos LitPaymentDetailModalTitle.Text = "Agregar producto o servicio"; DdlProductService.SelectedIndex = 0; + DdlUnidadMedidaDetallePago.SelectedIndex = 0; TxtPaymentDetailQuantity.Text = "1"; UpPaymentDetailModal.Update(); Show("ModalPaymentDetail"); @@ -714,31 +732,41 @@ namespace SIG.Web.Pages.Catalogos protected void BtnSavePaymentDetail_Click(object sender, EventArgs e) { SetActiveTab(2); - int productId; - decimal quantity; - if (!int.TryParse(DdlProductService.SelectedValue, out productId) || - productId <= 0 || - !TryParseDecimal(TxtPaymentDetailQuantity.Text, out quantity) || - quantity <= 0) + int cveProductoServicio; + int cveUnidadMedida; + decimal cantidad; + if (!int.TryParse( + DdlProductService.SelectedValue, + out cveProductoServicio) || + cveProductoServicio <= 0 || + !int.TryParse( + DdlUnidadMedidaDetallePago.SelectedValue, + out cveUnidadMedida) || + cveUnidadMedida <= 0 || + !TryParseDecimal( + TxtPaymentDetailQuantity.Text, + out cantidad) || + cantidad <= 0) { Alert( - "Seleccione un producto o servicio y capture una cantidad mayor que cero.", + "Seleccione el producto o servicio, la unidad de medida y capture una cantidad mayor que cero.", TipoMensaje.MsgAdvertencia); Show("ModalPaymentDetail"); return; } - var model = new TramitePagoDetalleModel + var detallePago = new TramitePagoDetalleModel { CveTramitePagoDetalle = CveTramitePagoDetalleActual, CveTramitePago = CveTramitePagoSeleccionado, - CvePS = productId, - Cantidad = decimal.Round(quantity, 4) + CvePS = cveProductoServicio, + CveUM = cveUnidadMedida, + Cantidad = decimal.Round(cantidad, 4) }; DbResult result = AppServices.TramiteCatalogService.SavePagoDetalle( - model, + detallePago, CurrentUser.CveUsuario, CurrentUser.NombreDominio); @@ -758,6 +786,46 @@ namespace SIG.Web.Pages.Catalogos TipoMensaje.ToastExito); } + protected void DdlProductoServicio_SelectedIndexChanged( + object sender, + EventArgs e) + { + SetActiveTab(2); + int cveProductoServicio; + + if (!int.TryParse( + DdlProductService.SelectedValue, + out cveProductoServicio) || + cveProductoServicio <= 0) + { + DdlUnidadMedidaDetallePago.SelectedIndex = 0; + UpPaymentDetailModal.Update(); + Show("ModalPaymentDetail"); + return; + } + + ProductoServicioTramiteModel productoServicio = + ProductosServiciosDisponibles.FirstOrDefault( + producto => + producto.CvePS == cveProductoServicio); + + if (productoServicio == null || + productoServicio.CveUnidadMedida <= 0) + { + DdlUnidadMedidaDetallePago.SelectedIndex = 0; + UpPaymentDetailModal.Update(); + Show("ModalPaymentDetail"); + return; + } + + SelectDropDownValue( + DdlUnidadMedidaDetallePago, + productoServicio.CveUnidadMedida); + + UpPaymentDetailModal.Update(); + Show("ModalPaymentDetail"); + } + protected void BtnSaveGlobalPrice_Click(object sender, EventArgs e) { SetActiveTab(2); @@ -896,14 +964,59 @@ namespace SIG.Web.Pages.Catalogos return; } + List productos = + result.Data ?? new List(); + ProductosServiciosDisponibles = productos; + BindDropDown( DdlProductService, - result.Data, + productos, "ProductoDisplay", "CvePS", "Seleccione un producto o servicio"); } + private void CargarUnidadesMedida() + { + DbResult> result = + AppServices.ProductoCatalogService.ListUnidadesMedida( + null, + true, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgError); + return; + } + + DdlUnidadMedidaDetallePago.Items.Clear(); + DdlUnidadMedidaDetallePago.Items.Add( + new ListItem("Seleccione una unidad de medida", string.Empty)); + + foreach (UnidadMedidaModel unidadMedida in + result.Data ?? new List()) + { + string textoUnidadMedida = + string.IsNullOrWhiteSpace(unidadMedida.Abreviatura) + ? unidadMedida.UnidadMedida + : unidadMedida.UnidadMedida + + " (" + unidadMedida.Abreviatura.Trim() + ")"; + + if (!unidadMedida.EsActivo) + { + textoUnidadMedida += " - Inactiva"; + } + + DdlUnidadMedidaDetallePago.Items.Add( + new ListItem( + textoUnidadMedida, + unidadMedida.CveUnidadMedida.ToString( + CultureInfo.InvariantCulture))); + } + } + private void BindQuestions() { DbResult> result = @@ -1306,6 +1419,9 @@ namespace SIG.Web.Pages.Catalogos CveTramitePagoDetalleActual = id; LitPaymentDetailModalTitle.Text = "Editar concepto de pago"; SelectDropDownValue(DdlProductService, result.Data.CvePS); + SelectDropDownValue( + DdlUnidadMedidaDetallePago, + result.Data.CveUM); TxtPaymentDetailQuantity.Text = result.Data.Cantidad.ToString( "0.####", diff --git a/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.designer.cs b/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.designer.cs deleted file mode 100644 index 4091a96..0000000 --- a/SIG.Web/Pages/Catalogos/TipoTramiteDetalle.aspx.designer.cs +++ /dev/null @@ -1,88 +0,0 @@ -namespace SIG.Web.Pages.Catalogos -{ - public partial class TipoTramiteDetalle - { - protected global::System.Web.UI.WebControls.HyperLink LnkBack; - protected global::System.Web.UI.UpdatePanel UpSummary; - protected global::System.Web.UI.WebControls.Literal LitProcedureName; - protected global::System.Web.UI.WebControls.LinkButton BtnEditProcedure; - protected global::System.Web.UI.WebControls.Literal LitProcedureCode; - protected global::System.Web.UI.WebControls.Literal LitProcedureType; - protected global::System.Web.UI.WebControls.Literal LitProcedureStatus; - protected global::System.Web.UI.WebControls.Literal LitProcedureDescription; - protected global::System.Web.UI.UpdatePanel UpTabs; - protected global::AjaxControlToolkit.TabContainer TabsProcedureDetail; - protected global::AjaxControlToolkit.TabPanel TabQuestions; - protected global::System.Web.UI.WebControls.LinkButton BtnNewQuestion; - protected global::System.Web.UI.WebControls.GridView GvQuestions; - protected global::System.Web.UI.WebControls.HiddenField HfQuestionOrderMove; - protected global::System.Web.UI.WebControls.LinkButton BtnQuestionOrderMove; - protected global::System.Web.UI.WebControls.Panel PnlOptions; - protected global::System.Web.UI.WebControls.Literal LitOptionsQuestionTitle; - protected global::System.Web.UI.WebControls.LinkButton BtnCloseOptions; - protected global::System.Web.UI.WebControls.LinkButton BtnNewOption; - protected global::System.Web.UI.WebControls.GridView GvOptions; - protected global::System.Web.UI.WebControls.HiddenField HfOptionOrderMove; - protected global::System.Web.UI.WebControls.LinkButton BtnOptionOrderMove; - protected global::AjaxControlToolkit.TabPanel TabDocuments; - protected global::System.Web.UI.WebControls.LinkButton BtnNewDocument; - protected global::System.Web.UI.WebControls.GridView GvDocuments; - protected global::System.Web.UI.WebControls.HiddenField HfDocumentOrderMove; - protected global::System.Web.UI.WebControls.LinkButton BtnDocumentOrderMove; - protected global::AjaxControlToolkit.TabPanel TabPayments; - protected global::System.Web.UI.WebControls.Literal LitProcedurePaymentTotal; - protected global::System.Web.UI.WebControls.Literal LitPaymentCount; - protected global::System.Web.UI.WebControls.LinkButton BtnNewPayment; - protected global::System.Web.UI.WebControls.GridView GvPayments; - protected global::System.Web.UI.WebControls.Panel PnlPaymentDetail; - protected global::System.Web.UI.WebControls.Literal LitPaymentDetailTitle; - protected global::System.Web.UI.WebControls.LinkButton BtnClosePaymentDetail; - protected global::System.Web.UI.WebControls.LinkButton BtnNewPaymentDetail; - protected global::System.Web.UI.WebControls.GridView GvPaymentDetails; - protected global::System.Web.UI.WebControls.Literal LitSelectedPaymentTotal; - protected global::System.Web.UI.UpdatePanel UpProcedureModal; - protected global::System.Web.UI.WebControls.TextBox TxtProcedureCode; - protected global::System.Web.UI.WebControls.TextBox TxtProcedureName; - protected global::System.Web.UI.WebControls.TextBox TxtProcedureDescription; - protected global::System.Web.UI.WebControls.CheckBox ChkProcedureActive; - protected global::System.Web.UI.WebControls.Button BtnSaveProcedure; - protected global::System.Web.UI.UpdatePanel UpQuestionModal; - protected global::System.Web.UI.WebControls.Literal LitQuestionTitle; - protected global::System.Web.UI.WebControls.DropDownList DdlQuestionType; - protected global::System.Web.UI.WebControls.TextBox TxtQuestionCode; - protected global::System.Web.UI.WebControls.TextBox TxtQuestion; - protected global::System.Web.UI.WebControls.TextBox TxtQuestionDescription; - protected global::System.Web.UI.WebControls.CheckBox ChkQuestionRequired; - protected global::System.Web.UI.WebControls.CheckBox ChkQuestionActive; - protected global::System.Web.UI.WebControls.Button BtnSaveQuestion; - protected global::System.Web.UI.UpdatePanel UpOptionModal; - protected global::System.Web.UI.WebControls.Literal LitOptionTitle; - protected global::System.Web.UI.WebControls.TextBox TxtOptionText; - protected global::System.Web.UI.WebControls.TextBox TxtOptionValue; - protected global::System.Web.UI.WebControls.CheckBox ChkOptionActive; - protected global::System.Web.UI.WebControls.Button BtnSaveOption; - protected global::System.Web.UI.UpdatePanel UpDocumentModal; - protected global::System.Web.UI.WebControls.Literal LitDocumentTitle; - protected global::System.Web.UI.WebControls.DropDownList DdlDocumentType; - protected global::System.Web.UI.WebControls.CheckBox ChkDocumentRequired; - protected global::System.Web.UI.WebControls.CheckBox ChkDocumentActive; - protected global::System.Web.UI.WebControls.Button BtnSaveDocument; - protected global::System.Web.UI.UpdatePanel UpPaymentModal; - protected global::System.Web.UI.WebControls.Literal LitPaymentTitle; - protected global::System.Web.UI.WebControls.TextBox TxtPaymentName; - protected global::System.Web.UI.WebControls.TextBox TxtPaymentNotes; - protected global::System.Web.UI.WebControls.CheckBox ChkPaymentRequired; - protected global::System.Web.UI.WebControls.CheckBox ChkPaymentActive; - protected global::System.Web.UI.WebControls.Button BtnSavePayment; - protected global::System.Web.UI.UpdatePanel UpPaymentDetailModal; - protected global::System.Web.UI.WebControls.Literal LitPaymentDetailModalTitle; - protected global::System.Web.UI.WebControls.DropDownList DdlProductService; - protected global::System.Web.UI.WebControls.TextBox TxtPaymentDetailQuantity; - protected global::System.Web.UI.WebControls.Button BtnSavePaymentDetail; - protected global::System.Web.UI.UpdatePanel UpGlobalPriceModal; - protected global::System.Web.UI.WebControls.Literal LitGlobalPriceProduct; - protected global::System.Web.UI.WebControls.TextBox TxtGlobalPrice; - protected global::System.Web.UI.WebControls.CheckBox ChkConfirmGlobalPrice; - protected global::System.Web.UI.WebControls.Button BtnSaveGlobalPrice; - } -} diff --git a/SIG.Web/Pages/Catalogos/TiposTramite.aspx.designer.cs b/SIG.Web/Pages/Catalogos/TiposTramite.aspx.designer.cs deleted file mode 100644 index cccbfd6..0000000 --- a/SIG.Web/Pages/Catalogos/TiposTramite.aspx.designer.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace SIG.Web.Pages.Catalogos -{ - public partial class TiposTramite - { - protected global::System.Web.UI.UpdatePanel UpActions; - protected global::System.Web.UI.WebControls.LinkButton BtnNew; - protected global::System.Web.UI.UpdatePanel UpCatalog; - protected global::SIG.Web.AppCode.SigControls.Filtros UcFiltros; - protected global::System.Web.UI.WebControls.GridView GvItems; - protected global::System.Web.UI.WebControls.HiddenField HfOrderMove; - protected global::System.Web.UI.WebControls.LinkButton BtnOrderMove; - protected global::System.Web.UI.UpdatePanel UpFilters; - protected global::System.Web.UI.WebControls.TextBox TxtSearch; - protected global::System.Web.UI.WebControls.CheckBox ChkInactive; - protected global::System.Web.UI.WebControls.Button BtnApplyFilters; - protected global::System.Web.UI.UpdatePanel UpEdit; - protected global::System.Web.UI.WebControls.Literal LitModalTitle; - protected global::System.Web.UI.WebControls.TextBox TxtCode; - protected global::System.Web.UI.WebControls.TextBox TxtName; - protected global::System.Web.UI.WebControls.TextBox TxtDescription; - protected global::System.Web.UI.WebControls.CheckBox ChkActive; - protected global::System.Web.UI.WebControls.Button BtnSave; - } -} diff --git a/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx b/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx new file mode 100644 index 0000000..301822c --- /dev/null +++ b/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx @@ -0,0 +1,238 @@ +<%@ Page Title="Unidades de medida" + Language="C#" + MasterPageFile="~/Site.master" + AutoEventWireup="true" + CodeFile="UnidadesMedida.aspx.cs" + Inherits="SIG.Web.Pages.Catalogos.UnidadesMedida" %> + + + + + + + + +
  • + + + Nueva unidad de medida + +
  • +
    + + + +
    +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + +
    + + + + + +
    + + + + diff --git a/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx.cs b/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx.cs new file mode 100644 index 0000000..5b9a191 --- /dev/null +++ b/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx.cs @@ -0,0 +1,399 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Bitacora; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.General; +using SIG.Web.AppCode.Security; +using SIG.Web.AppCode.SigControls; + +namespace SIG.Web.Pages.Catalogos +{ + public partial class UnidadesMedida : ClsPaginaCatalogoInterno + { + private int CveUnidadMedidaActual + { + get + { + return ViewState["CveUnidadMedidaActual"] == null + ? 0 + : (int)ViewState["CveUnidadMedidaActual"]; + } + set + { + ViewState["CveUnidadMedidaActual"] = value; + } + } + + private int CveUnidadMedidaBitacoraActual + { + get + { + return ViewState["CveUnidadMedidaBitacoraActual"] == null + ? 0 + : (int)ViewState["CveUnidadMedidaBitacoraActual"]; + } + set + { + ViewState["CveUnidadMedidaBitacoraActual"] = value; + } + } + + private string NombreUnidadMedidaBitacoraActual + { + get + { + return Convert.ToString( + ViewState["NombreUnidadMedidaBitacoraActual"]); + } + set + { + ViewState["NombreUnidadMedidaBitacoraActual"] = value; + } + } + + protected void Page_Load(object sender, EventArgs e) + { + if (IsPostBack) + { + return; + } + + BindGrid(); + BindBitacora(); + SyncFilters(); + } + + protected void UcFiltros_MostrarFiltros( + object sender, + EventArgs e) + { + ShowModal("ModalFilters"); + } + + protected void UcFiltros_Consultar(object sender, EventArgs e) + { + BindGrid(); + SyncFilters(); + } + + protected void UcFiltros_FiltrosChanged( + object sender, + EventArgs e) + { + List names = UcFiltros.GetFiltros() + .Select(item => item.Nombre) + .ToList(); + + if (!names.Contains("Texto")) + { + TxtSearch.Text = string.Empty; + } + + if (!names.Contains("Inactivos")) + { + ChkInactive.Checked = false; + } + + BindGrid(); + SyncFilters(); + } + + protected void BtnApplyFilters_Click(object sender, EventArgs e) + { + BindGrid(); + SyncFilters(); + UpCatalog.Update(); + HideModal("ModalFilters"); + } + + protected void BtnNew_Click(object sender, EventArgs e) + { + CveUnidadMedidaActual = 0; + LitModalTitle.Text = "Nueva unidad de medida"; + TxtMeasurementUnit.Text = string.Empty; + TxtAbbreviation.Text = string.Empty; + ChkActive.Checked = true; + UpEdit.Update(); + ShowModal("ModalEdit"); + } + + protected void GvUnidadesMedida_RowDataBound( + object sender, + GridViewRowEventArgs e) + { + if (e.Row.RowType != DataControlRowType.DataRow) + { + return; + } + + ScriptManager scriptManager = ScriptManager.GetCurrent(Page); + + if (scriptManager == null) + { + return; + } + + RegisterAsyncControl(scriptManager, e.Row, "BtnViewAudit"); + RegisterAsyncControl(scriptManager, e.Row, "BtnEdit"); + RegisterAsyncControl(scriptManager, e.Row, "BtnDelete"); + } + + protected void GvUnidadesMedida_RowCommand( + object sender, + GridViewCommandEventArgs e) + { + int cveUnidadMedida; + + if (!int.TryParse( + Convert.ToString(e.CommandArgument), + out cveUnidadMedida)) + { + return; + } + + if (e.CommandName == "Editar") + { + LoadEdit(cveUnidadMedida); + } + else if (e.CommandName == "VerBitacora") + { + SelectBitacora(cveUnidadMedida); + } + else if (e.CommandName == "Eliminar") + { + Delete(cveUnidadMedida); + } + } + + protected void BtnSave_Click(object sender, EventArgs e) + { + var unidadMedida = new UnidadMedidaModel + { + CveUnidadMedida = CveUnidadMedidaActual, + UnidadMedida = TxtMeasurementUnit.Text, + Abreviatura = TxtAbbreviation.Text, + EsActivo = ChkActive.Checked + }; + + DbResult result = + AppServices.ProductoCatalogService.SaveUnidadMedida( + unidadMedida, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + ShowModal("ModalEdit"); + return; + } + + BindGrid(); + SyncFilters(); + BindBitacora(); + UpCatalog.Update(); + HideModal("ModalEdit"); + Alert( + "Unidad de medida guardada correctamente.", + TipoMensaje.ToastExito); + } + + protected void UcBitacoraCatalogo_AccionClick( + object sender, + EventArgs e) + { + CveUnidadMedidaBitacoraActual = 0; + NombreUnidadMedidaBitacoraActual = string.Empty; + BindBitacora(); + } + + private void LoadEdit(int cveUnidadMedida) + { + DbResult result = + AppServices.ProductoCatalogService.GetUnidadMedida( + cveUnidadMedida, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success || result.Data == null) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + CveUnidadMedidaActual = result.Data.CveUnidadMedida; + LitModalTitle.Text = "Editar unidad de medida"; + TxtMeasurementUnit.Text = result.Data.UnidadMedida; + TxtAbbreviation.Text = result.Data.Abreviatura; + ChkActive.Checked = result.Data.EsActivo; + UpEdit.Update(); + ShowModal("ModalEdit"); + } + + private void SelectBitacora(int cveUnidadMedida) + { + DbResult result = + AppServices.ProductoCatalogService.GetUnidadMedida( + cveUnidadMedida, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success || result.Data == null) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + CveUnidadMedidaBitacoraActual = cveUnidadMedida; + NombreUnidadMedidaBitacoraActual = result.Data.UnidadMedida; + BindBitacora(); + } + + private void Delete(int cveUnidadMedida) + { + DbResult result = + AppServices.ProductoCatalogService.DeleteUnidadMedida( + cveUnidadMedida, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + if (CveUnidadMedidaBitacoraActual == cveUnidadMedida) + { + CveUnidadMedidaBitacoraActual = 0; + NombreUnidadMedidaBitacoraActual = string.Empty; + } + + BindGrid(); + SyncFilters(); + BindBitacora(); + UpCatalog.Update(); + Alert( + "Unidad de medida eliminada correctamente.", + TipoMensaje.ToastExito); + } + + private void BindGrid() + { + DbResult> result = + AppServices.ProductoCatalogService.ListUnidadesMedida( + TxtSearch.Text, + ChkInactive.Checked, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!result.Success) + { + Alert(result.UserMessage, TipoMensaje.MsgError); + return; + } + + GvUnidadesMedida.DataSource = + result.Data ?? new List(); + GvUnidadesMedida.DataBind(); + } + + private void BindBitacora() + { + bool hasMeasurementUnit = CveUnidadMedidaBitacoraActual > 0; + + UcBitacoraCatalogo.Descripcion = hasMeasurementUnit + ? "Historial de " + NombreUnidadMedidaBitacoraActual + : "Historial de unidades de medida"; + UcBitacoraCatalogo.AccionVisible = hasMeasurementUnit; + UcBitacoraCatalogo.ConfigurarConsulta( + new List + { + new BitacoraCampoFiltroModel + { + NombreTablaSQL = "UnidadesMedida", + NombreCampoSQL = "CveUnidadMedida", + Valor = hasMeasurementUnit + ? CveUnidadMedidaBitacoraActual.ToString( + CultureInfo.InvariantCulture) + : string.Empty, + SoloExistencia = !hasMeasurementUnit + } + }, + new List + { + new BitacoraRelacionMostrarModel + { + Orden = 1, + NombreTablaSQL = "UnidadesMedida", + NombreCampoMostrarSQL = "UnidadMedida" + } + }); + UcBitacoraCatalogo.Consultar(true); + } + + private void SyncFilters() + { + var filters = new List(); + + if (!string.IsNullOrWhiteSpace(TxtSearch.Text)) + { + filters.Add( + new FiltroActivo + { + Nombre = "Texto", + Titulo = "Búsqueda", + Descripcion = TxtSearch.Text.Trim(), + Orden = 1 + }); + } + + if (ChkInactive.Checked) + { + filters.Add( + new FiltroActivo + { + Nombre = "Inactivos", + Titulo = "Estado", + Descripcion = "Incluye inactivas", + Orden = 2 + }); + } + + UcFiltros.SetFiltros(filters); + } + + private static void RegisterAsyncControl( + ScriptManager scriptManager, + GridViewRow row, + string controlId) + { + Control control = row.FindControl(controlId); + + if (control != null) + { + scriptManager.RegisterAsyncPostBackControl(control); + } + } + + private void ShowModal(string id) + { + RegistraScript( + "window.SIGTramiteCatalog.show('" + id + "');", + "Show_" + id); + } + + private void HideModal(string id) + { + RegistraScript( + "window.SIGTramiteCatalog.hide('" + id + "');", + "Hide_" + id); + } + } +} diff --git a/SIG.Web/Pages/Catalogos/TiposDocumento.aspx.designer.cs b/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx.designer.cs similarity index 73% rename from SIG.Web/Pages/Catalogos/TiposDocumento.aspx.designer.cs rename to SIG.Web/Pages/Catalogos/UnidadesMedida.aspx.designer.cs index 8a4dc5f..4247c59 100644 --- a/SIG.Web/Pages/Catalogos/TiposDocumento.aspx.designer.cs +++ b/SIG.Web/Pages/Catalogos/UnidadesMedida.aspx.designer.cs @@ -1,23 +1,23 @@ namespace SIG.Web.Pages.Catalogos { - public partial class TiposDocumento + public partial class UnidadesMedida { protected global::System.Web.UI.UpdatePanel UpActions; protected global::System.Web.UI.WebControls.LinkButton BtnNew; protected global::System.Web.UI.UpdatePanel UpCatalog; protected global::SIG.Web.AppCode.SigControls.Filtros UcFiltros; - protected global::System.Web.UI.WebControls.GridView GvItems; + protected global::System.Web.UI.WebControls.GridView GvUnidadesMedida; protected global::System.Web.UI.UpdatePanel UpFilters; protected global::System.Web.UI.WebControls.TextBox TxtSearch; protected global::System.Web.UI.WebControls.CheckBox ChkInactive; protected global::System.Web.UI.WebControls.Button BtnApplyFilters; protected global::System.Web.UI.UpdatePanel UpEdit; protected global::System.Web.UI.WebControls.Literal LitModalTitle; - protected global::System.Web.UI.WebControls.TextBox TxtName; - protected global::System.Web.UI.WebControls.TextBox TxtDescription; - protected global::System.Web.UI.WebControls.TextBox TxtExtensions; - protected global::System.Web.UI.WebControls.TextBox TxtMaxMb; + protected global::System.Web.UI.WebControls.TextBox TxtMeasurementUnit; + protected global::System.Web.UI.WebControls.TextBox TxtAbbreviation; protected global::System.Web.UI.WebControls.CheckBox ChkActive; protected global::System.Web.UI.WebControls.Button BtnSave; + protected global::SIG.Web.AppCode.SigControls.BitacoraGrid + UcBitacoraCatalogo; } } diff --git a/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx b/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx index b6f4658..824f96d 100644 --- a/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx +++ b/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx @@ -648,12 +648,158 @@ Pagos + + + -
    - -

    No hay pagos registrados.

    -
    +
    +
    +
    +

    Pagos pendientes

    +

    Pagos configurados para los trámites del fraccionamiento que todavía no tienen una venta relacionada.

    +
    +
    + +
    + + + + + + + + + + + + + + + Generar + + + + + Pagar + + + + + +
    + + + + No hay pagos pendientes. +
    +
    +
    +
    +
    + +
    +
    +
    +

    Pagos realizados

    +

    Ventas relacionadas de forma explícita con una solicitud y su grupo de pago.

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + +
    + + + + No hay ventas relacionadas con pagos de trámites. +
    +
    +
    +
    +
    @@ -1145,7 +1291,7 @@ Titulo="Bitácora" Descripcion="Historial del fraccionamiento, sus etapas, lotes, trámites y documentos" TextoVacio="No hay movimientos registrados para este fraccionamiento." - RegistrosPorPagina="20" + RegistrosPorPagina="10" ScrollsParaCambiarPagina="3" />
    > resultadoPendientes = + AppServices.ServicioVentaTramite.ListarPagosPendientes( + CveFraccionamientoActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + DbResult> resultadoRealizados = + AppServices.ServicioVentaTramite.ListarPagosRealizados( + CveFraccionamientoActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultadoPendientes.Success || !resultadoRealizados.Success) + { + Alert( + !resultadoPendientes.Success + ? resultadoPendientes.UserMessage + : resultadoRealizados.UserMessage, + TipoMensaje.MsgError); + return; + } + + List pagosPendientes = + resultadoPendientes.Data ?? + new List(); + List pagosRealizados = + resultadoRealizados.Data ?? + new List(); + + GvPagosPendientes.DataSource = pagosPendientes; + GvPagosPendientes.DataBind(); + GvPagosRealizados.DataSource = pagosRealizados; + GvPagosRealizados.DataBind(); + + LitCantidadPagos.Text = + (pagosPendientes.Count + pagosRealizados.Count).ToString( + CultureInfo.CurrentCulture); + } + private void SetDocumentFilter( string name, string title, @@ -3247,6 +3290,33 @@ namespace SIG.Web.Pages.Fraccionamientos return Server.HtmlEncode(GetDisplayValue(value)); } + protected string GetVentaTramiteUrl( + object cveSolicitudValue, + object cveTramitePagoValue) + { + int cveSolicitud; + int cveTramitePago; + + if (!int.TryParse( + Convert.ToString(cveSolicitudValue), + out cveSolicitud) || + !int.TryParse( + Convert.ToString(cveTramitePagoValue), + out cveTramitePago) || + cveSolicitud <= 0 || + cveTramitePago <= 0) + { + return string.Empty; + } + + return ResolveUrl( + "~/Pages/Ventas/VentaTramite.aspx" + + "?cveSolicitud=" + + cveSolicitud.ToString(CultureInfo.InvariantCulture) + + "&cveTramitePago=" + + cveTramitePago.ToString(CultureInfo.InvariantCulture)); + } + private static string GetDisplayValue(string value) { return string.IsNullOrWhiteSpace(value) diff --git a/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx.designer.cs b/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx.designer.cs deleted file mode 100644 index da93760..0000000 --- a/SIG.Web/Pages/Fraccionamientos/FraccionamientoDetalle.aspx.designer.cs +++ /dev/null @@ -1,935 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace SIG.Web.Pages.Fraccionamientos -{ - - - public partial class FraccionamientoDetalle - { - - /// - /// LnkBack control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink LnkBack; - - /// - /// BtnEditStageProgress control. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnAddProcedure; - - protected global::System.Web.UI.WebControls.LinkButton BtnEditStageProgress; - - /// - /// UpSummary control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UpdatePanel UpSummary; - - /// - /// LitDevelopmentName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitDevelopmentName; - - /// - /// LblDevelopmentActive control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label LblDevelopmentActive; - - /// - /// BtnDelete control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnDelete; - - /// - /// LitSummaryClient control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitSummaryClient; - - /// - /// LitSummaryHectares control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitSummaryHectares; - - /// - /// LitSummaryLocation control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitSummaryLocation; - - /// - /// LitSummaryOpeningDate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitSummaryOpeningDate; - - /// - /// LitSummaryGlobalProgress control. - /// - protected global::System.Web.UI.WebControls.Literal LitSummaryGlobalProgress; - - /// - /// PnlSummaryGlobalProgressBar control. - /// - protected global::System.Web.UI.WebControls.Panel PnlSummaryGlobalProgressBar; - - /// - /// LblSummaryStatus control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label LblSummaryStatus; - - /// - /// UpDetailTabs control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UpdatePanel UpDetailTabs; - - /// - /// TabsFractionDetail control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabContainer TabsFractionDetail; - - /// - /// TabStages control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabPanel TabStages; - - /// - /// LitStageCount control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitStageCount; - - /// - /// BtnNewStage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnNewStage; - - /// - /// GvStages control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.GridView GvStages; - - /// - /// HfStageOrderMove control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HiddenField HfStageOrderMove; - - /// - /// BtnStageOrderMove control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnStageOrderMove; - - /// - /// GvProcedures control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.GridView GvProcedures; - - /// - /// TabLots control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabPanel TabLots; - - /// - /// LitLotCount control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitLotCount; - - /// - /// DdlLotsStage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlLotsStage; - - /// - /// BtnClearStageLots control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnClearStageLots; - - /// - /// PnlLotsStageRequired control. - /// - protected global::System.Web.UI.WebControls.Panel PnlLotsStageRequired; - - /// - /// PnlLotsStageContext control. - /// - protected global::System.Web.UI.WebControls.Panel PnlLotsStageContext; - - /// - /// LitLotsSelectedStage control. - /// - protected global::System.Web.UI.WebControls.Literal LitLotsSelectedStage; - - /// - /// LitLotsSelectedStageProgress control. - /// - protected global::System.Web.UI.WebControls.Literal LitLotsSelectedStageProgress; - - /// - /// PnlLotsSelectedStageProgressBar control. - /// - protected global::System.Web.UI.WebControls.Panel PnlLotsSelectedStageProgressBar; - - /// - /// PhStageGisMissing control. - /// - protected global::System.Web.UI.WebControls.PlaceHolder PhStageGisMissing; - - /// - /// BtnAddStageGis control. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnAddStageGis; - - /// - /// PhStageGisExistingActions control. - /// - protected global::System.Web.UI.WebControls.PlaceHolder PhStageGisExistingActions; - - /// - /// BtnManageStageGis control. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnManageStageGis; - - /// - /// PnlStageGisExisting control. - /// - protected global::System.Web.UI.WebControls.Panel PnlStageGisExisting; - - /// - /// LitStageGisName control. - /// - protected global::System.Web.UI.WebControls.Literal LitStageGisName; - - /// - /// LitStageGisUpdatedAt control. - /// - protected global::System.Web.UI.WebControls.Literal LitStageGisUpdatedAt; - - /// - /// LnkStageGisOpen control. - /// - protected global::System.Web.UI.WebControls.HyperLink LnkStageGisOpen; - - /// - /// GvLots control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.GridView GvLots; - - /// - /// TabProcedures control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabPanel TabProcedures; - - /// - /// LitProcedureCount control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitProcedureCount; - - /// - /// UcProcedureFilters control. - /// - protected global::SIG.Web.AppCode.SigControls.Filtros UcProcedureFilters; - - /// - /// UpProcedureFiltersModal control. - /// - protected global::System.Web.UI.UpdatePanel UpAddProcedureModal; - - protected global::System.Web.UI.WebControls.Label LblAddProcedureMessage; - - protected global::System.Web.UI.WebControls.DropDownList DdlAddProcedureStage; - - protected global::System.Web.UI.WebControls.DropDownList DdlAddProcedureType; - - protected global::System.Web.UI.WebControls.Button BtnSaveAddProcedure; - - protected global::System.Web.UI.UpdatePanel UpProcedureFiltersModal; - - /// - /// DdlProcedureStatus control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlProcedureStatus; - - /// - /// DdlProcedureType control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlProcedureType; - - /// - /// DdlProcedureStage control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlProcedureStage; - - /// - /// BtnApplyProcedureFilters control. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnApplyProcedureFilters; - - /// - /// TabPayments control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabPanel TabPayments; - - /// - /// TabDocuments control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabPanel TabDocuments; - - /// - /// LitDocumentCount control. - /// - protected global::System.Web.UI.WebControls.Literal LitDocumentCount; - - /// - /// UcDocumentFilters control. - /// - protected global::SIG.Web.AppCode.SigControls.Filtros UcDocumentFilters; - - /// - /// GvDocuments control. - /// - protected global::System.Web.UI.WebControls.GridView GvDocuments; - - /// - /// UpDocumentFiltersModal control. - /// - protected global::System.Web.UI.UpdatePanel UpDocumentFiltersModal; - - /// - /// DdlDocumentProcedureType control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlDocumentProcedureType; - - /// - /// DdlDocumentStage control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlDocumentStage; - - /// - /// BtnApplyDocumentFilters control. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnApplyDocumentFilters; - - /// - /// UpDocumentUploadModal control. - /// - protected global::System.Web.UI.UpdatePanel UpDocumentUploadModal; - - /// - /// LitDocumentUploadTitle control. - /// - protected global::System.Web.UI.WebControls.Literal LitDocumentUploadTitle; - - /// - /// LblDocumentUploadMessage control. - /// - protected global::System.Web.UI.WebControls.Label LblDocumentUploadMessage; - - /// - /// LitDocumentUploadType control. - /// - protected global::System.Web.UI.WebControls.Literal LitDocumentUploadType; - - /// - /// LitDocumentUploadContext control. - /// - protected global::System.Web.UI.WebControls.Literal LitDocumentUploadContext; - - /// - /// FuDocument control. - /// - protected global::System.Web.UI.WebControls.FileUpload FuDocument; - - /// - /// LitDocumentUploadRules control. - /// - protected global::System.Web.UI.WebControls.Literal LitDocumentUploadRules; - - /// - /// TxtDocumentClientComment control. - /// - protected global::System.Web.UI.WebControls.TextBox TxtDocumentClientComment; - - /// - /// BtnSaveDocumentUpload control. - /// - protected global::System.Web.UI.WebControls.Button BtnSaveDocumentUpload; - - /// - /// UpDocumentRejectModal control. - /// - protected global::System.Web.UI.UpdatePanel UpDocumentRejectModal; - - /// - /// LblDocumentRejectMessage control. - /// - protected global::System.Web.UI.WebControls.Label LblDocumentRejectMessage; - - /// - /// TxtDocumentRejectNote control. - /// - protected global::System.Web.UI.WebControls.TextBox TxtDocumentRejectNote; - - /// - /// BtnConfirmDocumentReject control. - /// - protected global::System.Web.UI.WebControls.LinkButton BtnConfirmDocumentReject; - - /// - /// TabNotes control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::AjaxControlToolkit.TabPanel TabNotes; - - /// - /// UpDevelopmentModal control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UpdatePanel UpDevelopmentModal; - - /// - /// LblEditMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label LblEditMessage; - - /// - /// DdlClient control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlClient; - - /// - /// TxtDevelopment control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtDevelopment; - - /// - /// TxtHectares control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtHectares; - - /// - /// DdlStatus control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlStatus; - - /// - /// TxtLocation control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtLocation; - - /// - /// ChkActive control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox ChkActive; - - /// - /// BtnSave control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button BtnSave; - - /// - /// UpStageModal control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UpdatePanel UpStageModal; - - /// - /// LitStageTitle control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitStageTitle; - - /// - /// LblStageMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label LblStageMessage; - - /// - /// TxtStage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtStage; - - /// - /// TxtStageHectares control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtStageHectares; - - /// - /// ChkStageActive control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox ChkStageActive; - - /// - /// BtnSaveStage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button BtnSaveStage; - - /// - /// UpStageProgressModal control. - /// - protected global::System.Web.UI.UpdatePanel UpStageProgressModal; - - /// - /// LblStageProgressMessage control. - /// - protected global::System.Web.UI.WebControls.Label LblStageProgressMessage; - - /// - /// DdlStageProgress control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlStageProgress; - - /// - /// PnlStageProgressCapture control. - /// - protected global::System.Web.UI.WebControls.Panel PnlStageProgressCapture; - - /// - /// TxtStageProgress control. - /// - protected global::System.Web.UI.WebControls.TextBox TxtStageProgress; - - /// - /// BtnSaveStageProgress control. - /// - protected global::System.Web.UI.WebControls.Button BtnSaveStageProgress; - - /// - /// UpProcedureStatusModal control. - /// - protected global::System.Web.UI.UpdatePanel UpProcedureStatusModal; - - /// - /// LblProcedureStatusMessage control. - /// - protected global::System.Web.UI.WebControls.Label LblProcedureStatusMessage; - - /// - /// LitProcedureStatusFolio control. - /// - protected global::System.Web.UI.WebControls.Literal LitProcedureStatusFolio; - - /// - /// DdlProcedureNewStatus control. - /// - protected global::System.Web.UI.WebControls.DropDownList DdlProcedureNewStatus; - - /// - /// BtnSaveProcedureStatus control. - /// - protected global::System.Web.UI.WebControls.Button BtnSaveProcedureStatus; - - /// - /// UpStageGisModal control. - /// - protected global::System.Web.UI.UpdatePanel UpStageGisModal; - - /// - /// LitStageGisModalTitle control. - /// - protected global::System.Web.UI.WebControls.Literal LitStageGisModalTitle; - - /// - /// LblStageGisMessage control. - /// - protected global::System.Web.UI.WebControls.Label LblStageGisMessage; - - /// - /// LitStageGisStageName control. - /// - protected global::System.Web.UI.WebControls.Literal LitStageGisStageName; - - /// - /// HdStageGisId control. - /// - protected global::System.Web.UI.WebControls.HiddenField HdStageGisId; - - /// - /// BtnRefreshStageGis control. - /// - protected global::System.Web.UI.WebControls.Button BtnRefreshStageGis; - - /// - /// UpLotsModal control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UpdatePanel UpLotsModal; - - /// - /// LblLotMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label LblLotMessage; - - /// - /// LitLotStageName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitLotStageName; - - /// - /// TxtLotQuantity control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtLotQuantity; - - /// - /// TxtLotBaseName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtLotBaseName; - - /// - /// ChkLotAddIdentifier control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox ChkLotAddIdentifier; - - /// - /// TxtLotStartNumber control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtLotStartNumber; - - /// - /// LnkDownloadLotTemplate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink LnkDownloadLotTemplate; - - /// - /// FileLots control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.FileUpload FileLots; - - /// - /// BtnImportLots control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button BtnImportLots; - - /// - /// BtnSaveLots control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button BtnSaveLots; - - /// - /// UpEditLotModal control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.UpdatePanel UpEditLotModal; - - /// - /// LblEditLotMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label LblEditLotMessage; - - /// - /// LitEditLotStage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal LitEditLotStage; - - /// - /// TxtEditLotName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtEditLotName; - - /// - /// TxtEditLotType control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtEditLotType; - - /// - /// TxtEditLotStreet control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtEditLotStreet; - - /// - /// TxtEditLotCadastre control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtEditLotCadastre; - - /// - /// TxtEditLotSquareMeters control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtEditLotSquareMeters; - - /// - /// TxtEditLotDuplicate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox TxtEditLotDuplicate; - - /// - /// ChkEditLotActive control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox ChkEditLotActive; - - /// - /// BtnSaveLot control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button BtnSaveLot; - /// - /// UcBitacoraDetalle control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::SIG.Web.AppCode.SigControls.BitacoraGrid UcBitacoraDetalle; - } -} diff --git a/SIG.Web/Pages/Security/Perfil.aspx b/SIG.Web/Pages/Security/Perfil.aspx new file mode 100644 index 0000000..c95d25d --- /dev/null +++ b/SIG.Web/Pages/Security/Perfil.aspx @@ -0,0 +1,272 @@ +<%@ Page Title="Mi perfil" Language="C#" MasterPageFile="~/Site.master" + AutoEventWireup="true" CodeFile="Perfil.aspx.cs" + Inherits="SIG.Web.Pages.Security.Perfil" %> + + + + + + +
    + + + +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + +

    + +

    +
    +
    + +
    +
    + + +
    + Déjela vacía para conservar la contraseña actual. +
    +
    +
    + + +
    +
    + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +

    Datos fiscales para timbrado

    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    +
    + + +
    +
    +
    +
    +
    +
    + + + diff --git a/SIG.Web/Pages/Security/Perfil.aspx.cs b/SIG.Web/Pages/Security/Perfil.aspx.cs new file mode 100644 index 0000000..978998f --- /dev/null +++ b/SIG.Web/Pages/Security/Perfil.aspx.cs @@ -0,0 +1,289 @@ +using System; +using System.Globalization; +using System.Web.UI.WebControls; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Security; +using SIG.Web.AppCode.Security; +using SIG.Web.AppCode.Session; + +namespace SIG.Web.Pages.Security +{ + public partial class Perfil : ClsPaginaBase + { + private int CveClienteActual + { + get { return ViewState["CveClienteActual"] as int? ?? 0; } + set { ViewState["CveClienteActual"] = value; } + } + + protected void Page_Load(object sender, EventArgs e) + { + if (CurrentUser == null) + { + return; + } + + ConfigurarNavegacion(); + + if (!IsPostBack) + { + CargarPerfil(); + } + } + + protected void BtnGuardarSesion_Click( + object sender, + EventArgs e) + { + if (!string.Equals( + TxtContrasenaNueva.Text, + TxtConfirmarContrasena.Text, + StringComparison.Ordinal)) + { + Alert( + "La confirmación de la contraseña no coincide.", + TipoMensaje.MsgAdvertencia); + return; + } + + DbResult resultado = + AppServices.PerfilUsuarioService.ActualizarSesion( + CurrentUser, + TxtNombreUsuario.Text, + TxtContrasenaNueva.Text); + + if (!resultado.Success || resultado.Data == null) + { + Alert( + resultado.Success + ? "No fue posible actualizar los datos de sesión." + : resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + CurrentUser.NombreUsuario = resultado.Data.NombreUsuario; + CurrentUser.Nombre = resultado.Data.NombreUsuario; + CurrentUser.CorreoElectronico = + resultado.Data.CorreoElectronico; + CurrentUser.CveCliente = resultado.Data.CveCliente; + + if (!string.IsNullOrEmpty(TxtContrasenaNueva.Text)) + { + CurrentUser.DebeCambiarContrasena = false; + } + + AppServices.UserContext.SetCurrentUser(CurrentUser); + AlertNextRequest( + "Los datos de sesión se actualizaron correctamente.", + TipoMensaje.ToastExito); + Response.Redirect( + ResolveUrl("~/Pages/Security/Perfil.aspx"), + false); + Context.ApplicationInstance.CompleteRequest(); + } + + protected void BtnGuardarCliente_Click( + object sender, + EventArgs e) + { + int cveRegimenFiscal; + int cveUsoCfdi; + + if (!int.TryParse( + DdlRegimenFiscal.SelectedValue, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveRegimenFiscal) || + !int.TryParse( + DdlUsoCfdi.SelectedValue, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveUsoCfdi)) + { + Alert( + "Seleccione el régimen fiscal y el uso de CFDI.", + TipoMensaje.MsgAdvertencia); + return; + } + + var cliente = new PerfilClienteModel + { + CveCliente = CveClienteActual, + Nombre = TxtNombreFiscal.Text, + NombreComercial = TxtNombreComercial.Text, + Direccion = TxtDireccion.Text, + NoExt = TxtNumeroExterior.Text, + NoInt = TxtNumeroInterior.Text, + Colonia = TxtColonia.Text, + Ciudad = TxtCiudad.Text, + Estado = TxtEstado.Text, + Pais = TxtPais.Text, + RFC = TxtRFC.Text, + CP = TxtCodigoPostal.Text, + Telefono = TxtTelefono.Text, + Mail = TxtCorreoCliente.Text, + CveRegimenFiscal = cveRegimenFiscal, + CveUsoCFDI = cveUsoCfdi + }; + + DbResult resultado = + AppServices.PerfilUsuarioService.ActualizarCliente( + CurrentUser, + cliente); + + if (!resultado.Success) + { + Alert( + resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + Alert( + "Los datos del cliente se actualizaron correctamente.", + TipoMensaje.ToastExito); + CargarPerfil(); + TabsPerfil.ActiveTabIndex = 1; + } + + private void CargarPerfil() + { + DbResult resultado = + AppServices.PerfilUsuarioService.ObtenerPerfil( + CurrentUser); + + if (!resultado.Success || + resultado.Data == null || + resultado.Data.Sesion == null) + { + Alert( + resultado.Success + ? "No fue posible consultar el perfil." + : resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + PerfilUsuarioConsultaModel perfil = resultado.Data; + TxtNombreUsuario.Text = perfil.Sesion.NombreUsuario; + TxtCorreoElectronico.Text = + perfil.Sesion.CorreoElectronico; + LitNombreRol.Text = Server.HtmlEncode( + perfil.Sesion.NombreRol); + + CargarCatalogos(perfil); + + bool mostrarCliente = + perfil.Sesion.EsDesarrollador && + perfil.Sesion.CveCliente > 0 && + perfil.Cliente != null; + + TabDatosCliente.Visible = mostrarCliente; + CveClienteActual = mostrarCliente + ? perfil.Cliente.CveCliente + : 0; + + if (mostrarCliente) + { + CargarCliente(perfil.Cliente); + } + } + + private void CargarCatalogos( + PerfilUsuarioConsultaModel perfil) + { + bool faltanRegimenes = + perfil.RegimenesFiscales.Count == 0; + bool faltanUsosCfdi = + perfil.UsosCfdi.Count == 0; + + LblCatalogosFiscales.Visible = + faltanRegimenes || faltanUsosCfdi; + LblCatalogosFiscales.Text = + "No hay regímenes fiscales o usos de CFDI configurados. " + + "Registre esos catálogos antes de guardar los datos fiscales."; + + DdlRegimenFiscal.DataSource = + perfil.RegimenesFiscales; + DdlRegimenFiscal.DataTextField = "Descripcion"; + DdlRegimenFiscal.DataValueField = "CveRegimenFiscal"; + DdlRegimenFiscal.DataBind(); + DdlRegimenFiscal.Items.Insert( + 0, + new ListItem("Seleccione", string.Empty)); + + DdlUsoCfdi.DataSource = perfil.UsosCfdi; + DdlUsoCfdi.DataTextField = "DescripcionCompleta"; + DdlUsoCfdi.DataValueField = "CveUsoCFDI"; + DdlUsoCfdi.DataBind(); + DdlUsoCfdi.Items.Insert( + 0, + new ListItem("Seleccione", string.Empty)); + } + + private void CargarCliente(PerfilClienteModel cliente) + { + TxtNombreFiscal.Text = cliente.Nombre; + TxtNombreComercial.Text = cliente.NombreComercial; + TxtDireccion.Text = cliente.Direccion; + TxtNumeroExterior.Text = cliente.NoExt; + TxtNumeroInterior.Text = cliente.NoInt; + TxtColonia.Text = cliente.Colonia; + TxtCiudad.Text = cliente.Ciudad; + TxtEstado.Text = cliente.Estado; + TxtPais.Text = cliente.Pais; + TxtRFC.Text = cliente.RFC; + TxtCodigoPostal.Text = cliente.CP; + TxtTelefono.Text = cliente.Telefono; + TxtCorreoCliente.Text = cliente.Mail; + + SeleccionarValor( + DdlRegimenFiscal, + cliente.CveRegimenFiscal); + SeleccionarValor( + DdlUsoCfdi, + cliente.CveUsoCFDI); + } + + private static void SeleccionarValor( + ListControl control, + int valor) + { + string valorTexto = valor.ToString( + CultureInfo.InvariantCulture); + + if (control.Items.FindByValue(valorTexto) != null) + { + control.SelectedValue = valorTexto; + } + } + + private void ConfigurarNavegacion() + { + Site sitio = Master as Site; + + if (sitio == null) + { + return; + } + + sitio.SetPageNavigation( + "Mi perfil", + new[] + { + new BreadcrumbItemModel + { + Texto = "Inicio", + Url = "~/Inicio.aspx" + }, + new BreadcrumbItemModel + { + Texto = "Mi perfil" + } + }); + } + } +} diff --git a/SIG.Web/Pages/Security/Perfil.aspx.designer.cs b/SIG.Web/Pages/Security/Perfil.aspx.designer.cs new file mode 100644 index 0000000..fa7da80 --- /dev/null +++ b/SIG.Web/Pages/Security/Perfil.aspx.designer.cs @@ -0,0 +1,32 @@ +namespace SIG.Web.Pages.Security +{ + public partial class Perfil + { + protected global::AjaxControlToolkit.TabContainer TabsPerfil; + protected global::AjaxControlToolkit.TabPanel TabDatosSesion; + protected global::System.Web.UI.WebControls.TextBox TxtNombreUsuario; + protected global::System.Web.UI.WebControls.TextBox TxtCorreoElectronico; + protected global::System.Web.UI.WebControls.Literal LitNombreRol; + protected global::System.Web.UI.WebControls.TextBox TxtContrasenaNueva; + protected global::System.Web.UI.WebControls.TextBox TxtConfirmarContrasena; + protected global::System.Web.UI.WebControls.Button BtnGuardarSesion; + protected global::AjaxControlToolkit.TabPanel TabDatosCliente; + protected global::System.Web.UI.WebControls.TextBox TxtNombreFiscal; + protected global::System.Web.UI.WebControls.TextBox TxtNombreComercial; + protected global::System.Web.UI.WebControls.TextBox TxtDireccion; + protected global::System.Web.UI.WebControls.TextBox TxtNumeroExterior; + protected global::System.Web.UI.WebControls.TextBox TxtNumeroInterior; + protected global::System.Web.UI.WebControls.TextBox TxtColonia; + protected global::System.Web.UI.WebControls.TextBox TxtCiudad; + protected global::System.Web.UI.WebControls.TextBox TxtEstado; + protected global::System.Web.UI.WebControls.TextBox TxtPais; + protected global::System.Web.UI.WebControls.TextBox TxtTelefono; + protected global::System.Web.UI.WebControls.TextBox TxtCorreoCliente; + protected global::System.Web.UI.WebControls.Label LblCatalogosFiscales; + protected global::System.Web.UI.WebControls.TextBox TxtRFC; + protected global::System.Web.UI.WebControls.TextBox TxtCodigoPostal; + protected global::System.Web.UI.WebControls.DropDownList DdlRegimenFiscal; + protected global::System.Web.UI.WebControls.DropDownList DdlUsoCfdi; + protected global::System.Web.UI.WebControls.Button BtnGuardarCliente; + } +} diff --git a/SIG.Web/Pages/Ventas/VentaTramite.aspx b/SIG.Web/Pages/Ventas/VentaTramite.aspx new file mode 100644 index 0000000..48b512c --- /dev/null +++ b/SIG.Web/Pages/Ventas/VentaTramite.aspx @@ -0,0 +1,627 @@ +<%@ Page Title="Venta de trámite" + Language="C#" + MasterPageFile="~/Site.master" + AutoEventWireup="true" + CodeFile="VentaTramite.aspx.cs" + Inherits="SIG.Web.Pages.Ventas.VentaTramite" %> + + + + + + +
  • + + + Volver al fraccionamiento + +
  • +
    + + + +
    +
    + Pago de trámite +

    + +

    +

    + +

    + + +
    + +
    + Total + + + +
    +
    + +
    +
    +
    + +

    Cliente

    +
    + +
    +
    +
    Nombre
    +
    +
    +
    +
    RFC
    +
    +
    +
    +
    Teléfono
    +
    +
    +
    +
    Dirección
    +
    +
    +
    +
    Colonia
    +
    +
    +
    +
    Ciudad, estado
    +
    +
    +
    +
    C.P.
    +
    +
    +
    +
    Correo
    +
    +
    +
    +
    + +
    +
    + +

    Datos de emisión

    +
    + +
    +
    +
    Tipo
    +
    +
    +
    +
    Serie - folio
    +
    +
    +
    +
    Fecha
    +
    +
    +
    +
    Moneda
    +
    Pesos (MXN)
    +
    +
    +
    Fraccionamiento
    +
    +
    +
    +
    +
    + +
    +
    + +

    Detalle

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + + +
    +
    + + +
    +
    + + +
    +
    + + + Agregar + +
    +
    + +
    +
    +
    Subtotal
    +
    +
    +
    +
    Descuentos
    +
    +
    +
    +
    IVA
    +
    +
    +
    +
    Total
    +
    +
    +
    +
    + +
    +
    +
    + +

    Condiciones de pago

    +
    + + +
    + + +
    +
    + + +
    +
    + + +
    + + + Guardar condiciones + +
    + +
    + +
    +
    + +

    Observaciones

    +
    + +
    + + +
    +
    + +
    +
    + +

    Acciones

    +
    + + + + Generar + + + + + Pagar + + + + + Timbrar + + + +
    + + + Seleccione + 01 - Comprobante emitido con errores con relación + 02 - Comprobante emitido con errores sin relación + 03 - No se llevó a cabo la operación + 04 - Operación nominativa relacionada en factura global + +
    +
    + + +
    + + + Cancelar timbre + +
    +
    +
    +
    + + +
    + + + + diff --git a/SIG.Web/Pages/Ventas/VentaTramite.aspx.cs b/SIG.Web/Pages/Ventas/VentaTramite.aspx.cs new file mode 100644 index 0000000..7922ced --- /dev/null +++ b/SIG.Web/Pages/Ventas/VentaTramite.aspx.cs @@ -0,0 +1,1110 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Web.UI; +using System.Web.UI.WebControls; +using SIG.Web.AppCode.Configuration; +using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Ventas; +using SIG.Web.AppCode.Models.General; +using SIG.Web.AppCode.Security; +using SIG.Web.AppCode.Session; + +namespace SIG.Web.Pages.Ventas +{ + public partial class VentaTramite : ClsPaginaBase + { + private const string PermisoAgregarConceptos = + "Ventas.Tramites.AgregarConceptos"; + private const string PermisoModificarConceptos = + "Ventas.Tramites.ModificarConceptos"; + private const string PermisoEliminarConceptos = + "Ventas.Tramites.EliminarConceptos"; + private const string PermisoTimbrar = + "Ventas.Tramites.Timbrar"; + private const string PermisoCancelarTimbre = + "Ventas.Tramites.CancelarTimbre"; + private static readonly CultureInfo CulturaMoneda = + CultureInfo.GetCultureInfo("es-MX"); + + private int CveSolicitudActual + { + get { return ViewState["CveSolicitudActual"] as int? ?? 0; } + set { ViewState["CveSolicitudActual"] = value; } + } + + private int CveTramitePagoActual + { + get { return ViewState["CveTramitePagoActual"] as int? ?? 0; } + set { ViewState["CveTramitePagoActual"] = value; } + } + + private int CveFraccionamientoActual + { + get { return ViewState["CveFraccionamientoActual"] as int? ?? 0; } + set { ViewState["CveFraccionamientoActual"] = value; } + } + + private decimal TotalVentaActual + { + get { return ViewState["TotalVentaActual"] as decimal? ?? 0m; } + set { ViewState["TotalVentaActual"] = value; } + } + + private string ReferenciaPagoActual + { + get { return ViewState["ReferenciaPagoActual"] as string; } + set { ViewState["ReferenciaPagoActual"] = value; } + } + + private string ClaveFormaPagoActual + { + get { return ViewState["ClaveFormaPagoActual"] as string; } + set { ViewState["ClaveFormaPagoActual"] = value; } + } + + private List FormasPagoActuales + { + get + { + return ViewState["FormasPagoActuales"] + as List; + } + set { ViewState["FormasPagoActuales"] = value; } + } + + private List CuentasPagoActuales + { + get + { + return ViewState["CuentasPagoActuales"] + as List; + } + set { ViewState["CuentasPagoActuales"] = value; } + } + + protected bool PuedeModificarConceptosActual + { + get + { + return ViewState["PuedeModificarConceptosActual"] as bool? + ?? false; + } + set { ViewState["PuedeModificarConceptosActual"] = value; } + } + + protected bool PuedeEliminarConceptosActual + { + get + { + return ViewState["PuedeEliminarConceptosActual"] as bool? + ?? false; + } + set { ViewState["PuedeEliminarConceptosActual"] = value; } + } + + private bool PuedeAgregarConceptosActual + { + get + { + return ViewState["PuedeAgregarConceptosActual"] as bool? + ?? false; + } + set { ViewState["PuedeAgregarConceptosActual"] = value; } + } + + private List ProductosServiciosActuales + { + get + { + return ViewState["ProductosServiciosActuales"] + as List; + } + set { ViewState["ProductosServiciosActuales"] = value; } + } + + protected void Page_Load(object sender, EventArgs e) + { + if (IsPostBack) + { + return; + } + + int cveSolicitud; + int cveTramitePago; + + if (!int.TryParse( + Request.QueryString["cveSolicitud"], + out cveSolicitud) || + !int.TryParse( + Request.QueryString["cveTramitePago"], + out cveTramitePago) || + cveSolicitud <= 0 || + cveTramitePago <= 0) + { + Alert( + "Seleccione un pago pendiente válido.", + TipoMensaje.MsgAdvertencia); + return; + } + + CveSolicitudActual = cveSolicitud; + CveTramitePagoActual = cveTramitePago; + CargarVenta(); + } + + protected void BtnGenerar_Click(object sender, EventArgs e) + { + var venta = new ModeloCapturaVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + Observaciones = TxtObservaciones.Text + }; + + DbResult resultado = + AppServices.ServicioVentaTramite.GenerarVenta( + venta, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + Alert( + "Venta " + + resultado.Data.ToString(CultureInfo.CurrentCulture) + + " generada correctamente.", + TipoMensaje.ToastExito); + + CargarVenta(); + } + + protected void BtnPagar_Click(object sender, EventArgs e) + { + if (!CargarOpcionesPago()) + { + return; + } + + TxtImportePago.Text = TotalVentaActual.ToString( + "0.00", + CultureInfo.CurrentCulture); + TxtFechaCapturaPago.Text = DateTime.Today.ToString( + "yyyy-MM-dd", + CultureInfo.InvariantCulture); + TxtObservacionesPago.Text = string.Empty; + SeleccionarFormaPago("01"); + MostrarModalPago(); + } + + protected void BtnFormaEfectivo_Click( + object sender, + EventArgs e) + { + SeleccionarFormaPago("01"); + MostrarModalPago(); + } + + protected void BtnFormaTransferencia_Click( + object sender, + EventArgs e) + { + SeleccionarFormaPago("03"); + MostrarModalPago(); + } + + protected void DdlCuentaBancaria_SelectedIndexChanged( + object sender, + EventArgs e) + { + ActualizarCuentaSpeiSeleccionada(); + MostrarModalPago(); + } + + protected void BtnRegistrarPago_Click(object sender, EventArgs e) + { + decimal importe; + DateTime fechaPago; + int cveBancoCuenta; + + if (!IntentarDecimal(TxtImportePago.Text, out importe) || + !DateTime.TryParseExact( + TxtFechaCapturaPago.Text, + "yyyy-MM-dd", + CultureInfo.InvariantCulture, + DateTimeStyles.None, + out fechaPago) || + string.IsNullOrWhiteSpace(ClaveFormaPagoActual)) + { + Alert( + "Capture el monto, la fecha y la forma de pago.", + TipoMensaje.MsgAdvertencia); + MostrarModalPago(); + return; + } + + ModeloFormaPagoOpcion formaPago = + (FormasPagoActuales ?? + new List()) + .FirstOrDefault( + forma => + string.Equals( + forma.ClaveFormaPagoSAT, + ClaveFormaPagoActual, + StringComparison.Ordinal) && + forma.Disponible); + + if (formaPago == null) + { + Alert( + "La forma de pago seleccionada no está disponible.", + TipoMensaje.MsgAdvertencia); + MostrarModalPago(); + return; + } + + int? cveBancoCuentaSeleccionada = null; + + if (ClaveFormaPagoActual == "03") + { + if (!int.TryParse( + DdlCuentaBancaria.SelectedValue, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveBancoCuenta)) + { + Alert( + "Seleccione la cuenta SPEI donde se recibirá la transferencia.", + TipoMensaje.MsgAdvertencia); + MostrarModalPago(); + return; + } + + cveBancoCuentaSeleccionada = cveBancoCuenta; + } + + var pago = new ModeloPagoVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + Importe = importe, + FechaPago = fechaPago, + CveFormaPago = formaPago.CveFormaPago, + CveBancoCuenta = cveBancoCuentaSeleccionada, + Observaciones = TxtObservacionesPago.Text + }; + + DbResult resultado = + AppServices.ServicioVentaTramite.PagarVenta( + pago, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success || resultado.Data == null) + { + Alert( + resultado.Success + ? "No fue posible generar la solicitud de pago." + : resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + MostrarModalPago(); + return; + } + + Alert( + "Solicitud de pago registrada con la referencia " + + resultado.Data.Referencia + + ". Quedó pendiente de autorización.", + TipoMensaje.ToastExito); + CargarVenta(); + } + + protected void BtnGuardarCondicionesPago_Click( + object sender, + EventArgs e) + { + int cveMetodoPago; + byte cveFormaPago; + DateTime fechaVencimiento; + + if (!int.TryParse( + DdlMetodoPagoVenta.SelectedValue, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveMetodoPago) || + !byte.TryParse( + DdlFormaPagoVenta.SelectedValue, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveFormaPago) || + !DateTime.TryParseExact( + TxtFechaVencimiento.Text, + "yyyy-MM-dd", + CultureInfo.InvariantCulture, + DateTimeStyles.None, + out fechaVencimiento)) + { + Alert( + "Capture método, forma y fecha de vencimiento válidos.", + TipoMensaje.MsgAdvertencia); + return; + } + + DbResult resultado = + AppServices.ServicioVentaTramite.GuardarCondicionesPago( + new ModeloCondicionesPagoVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + CveMetodoPago = cveMetodoPago, + CveFormaPago = cveFormaPago, + FechaVencimiento = fechaVencimiento + }, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + Alert( + "Condiciones de pago actualizadas correctamente.", + TipoMensaje.ToastExito); + CargarVenta(); + } + + protected void DdlProductoServicio_SelectedIndexChanged( + object sender, + EventArgs e) + { + ProductoServicioModel producto = ObtenerProductoSeleccionado(); + TxtPrecioUnitarioNuevo.Text = producto == null + ? "0.00" + : producto.Precio.ToString("0.00", CultureInfo.CurrentCulture); + } + + protected void BtnAgregarConcepto_Click(object sender, EventArgs e) + { + if (!ValidarPermiso(PermisoAgregarConceptos)) + { + return; + } + + ProductoServicioModel producto = ObtenerProductoSeleccionado(); + decimal cantidad; + decimal precioUnitario; + + if (producto == null || + !IntentarDecimal(TxtCantidadNuevo.Text, out cantidad) || + !IntentarDecimal(TxtPrecioUnitarioNuevo.Text, out precioUnitario)) + { + Alert( + "Seleccione un producto y capture una cantidad y precio unitario válidos.", + TipoMensaje.MsgAdvertencia); + return; + } + + GuardarConcepto( + new ModeloCapturaConceptoVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + CvePS = producto.CvePS, + Cantidad = cantidad, + PrecioUnitario = precioUnitario + }, + "Producto o servicio agregado correctamente."); + } + + protected void GvConceptos_RowCommand( + object sender, + GridViewCommandEventArgs e) + { + if (e.CommandName != "GuardarConcepto" && + e.CommandName != "EliminarConcepto") + { + return; + } + + string permisoRequerido = e.CommandName == "EliminarConcepto" + ? PermisoEliminarConceptos + : PermisoModificarConceptos; + + if (!ValidarPermiso(permisoRequerido)) + { + return; + } + + GridViewRow fila = ((Control)e.CommandSource).NamingContainer + as GridViewRow; + int cveVentaDetalle; + + if (fila == null || + !int.TryParse(e.CommandArgument.ToString(), out cveVentaDetalle)) + { + Alert( + "Seleccione un concepto válido.", + TipoMensaje.MsgAdvertencia); + return; + } + + if (e.CommandName == "EliminarConcepto") + { + DbResult eliminarResultado = + AppServices.ServicioVentaTramite.EliminarConcepto( + CveSolicitudActual, + CveTramitePagoActual, + cveVentaDetalle, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!eliminarResultado.Success) + { + Alert( + eliminarResultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + Alert( + "Concepto eliminado correctamente.", + TipoMensaje.ToastExito); + CargarVenta(); + return; + } + + var cantidadControl = fila.FindControl("TxtCantidadConcepto") + as TextBox; + var precioControl = fila.FindControl("TxtPrecioUnitarioConcepto") + as TextBox; + decimal cantidad; + decimal precioUnitario; + int cvePS = Convert.ToInt32( + GvConceptos.DataKeys[fila.RowIndex].Values["CvePS"], + CultureInfo.InvariantCulture); + + if (cantidadControl == null || + precioControl == null || + !IntentarDecimal(cantidadControl.Text, out cantidad) || + !IntentarDecimal(precioControl.Text, out precioUnitario)) + { + Alert( + "Capture una cantidad y precio unitario válidos.", + TipoMensaje.MsgAdvertencia); + return; + } + + GuardarConcepto( + new ModeloCapturaConceptoVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + CveVentaDetalle = cveVentaDetalle, + CvePS = cvePS, + Cantidad = cantidad, + PrecioUnitario = precioUnitario + }, + "Concepto actualizado correctamente."); + } + + protected void BtnTimbrar_Click(object sender, EventArgs e) + { + if (!ValidarPermiso(PermisoTimbrar)) + { + return; + } + + DbResult resultado = + AppServices.ServicioVentaTramite.TimbrarVenta( + new ModeloTimbradoVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + CveEmpresa = CurrentUser.CveEmpresa + }, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + Alert( + "Venta timbrada correctamente. UUID: " + resultado.Data, + TipoMensaje.ToastExito); + CargarVenta(); + } + + protected void BtnCancelarTimbre_Click(object sender, EventArgs e) + { + if (!ValidarPermiso(PermisoCancelarTimbre)) + { + return; + } + + DbResult resultado = + AppServices.ServicioVentaTramite.CancelarTimbre( + new ModeloCancelacionTimbreVentaTramite + { + CveSolicitud = CveSolicitudActual, + CveTramitePago = CveTramitePagoActual, + Motivo = DdlMotivoCancelacion.SelectedValue, + UuidSustitucion = TxtUuidSustitucion.Text + }, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + Alert( + string.IsNullOrWhiteSpace(resultado.Data) + ? "Timbre cancelado correctamente." + : resultado.Data, + TipoMensaje.ToastExito); + CargarVenta(); + } + + private void CargarVenta() + { + DbResult resultado = + AppServices.ServicioVentaTramite.ObtenerVenta( + CveSolicitudActual, + CveTramitePagoActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success || resultado.Data == null) + { + Alert( + resultado.Success + ? "No fue posible obtener los datos de la venta." + : resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + ModeloContextoVentaTramite venta = resultado.Data; + List conceptos = + venta.Conceptos ?? + new List(); + + CveFraccionamientoActual = venta.CveFraccionamiento; + LnkVolver.NavigateUrl = ObtenerUrlFraccionamiento( + venta.CveFraccionamiento); + + LitNombrePago.Text = Codificar(venta.NombrePago); + LitReferenciaTramite.Text = Codificar( + venta.FolioSolicitud + + " · " + + venta.TipoTramite + + " · " + + venta.Etapa); + LitCliente.Text = Codificar(venta.Cliente); + LitRFC.Text = Codificar(venta.RFC); + LitTelefono.Text = Codificar(venta.Telefono); + LitDireccion.Text = Codificar(venta.Direccion); + LitColonia.Text = Codificar(venta.Colonia); + LitCiudadEstado.Text = Codificar(venta.CiudadEstado); + LitCodigoPostal.Text = Codificar(venta.CP); + LitCorreo.Text = Codificar(venta.Mail); + LitTipoDocumento.Text = Codificar(venta.TipoDocumento); + LitSerieFolio.Text = Codificar( + venta.Serie + + "-" + + venta.Folio.ToString(CultureInfo.CurrentCulture)); + LitFecha.Text = Codificar( + venta.Fecha.ToString( + "dd/MM/yyyy", + CultureInfo.CurrentCulture)); + LitFraccionamiento.Text = Codificar(venta.Fraccionamiento); + + PuedeModificarConceptosActual = + venta.VentaGenerada && + !venta.VentaTimbrada && + TienePermiso(PermisoModificarConceptos); + PuedeEliminarConceptosActual = + venta.VentaGenerada && + !venta.VentaTimbrada && + TienePermiso(PermisoEliminarConceptos); + PuedeAgregarConceptosActual = + venta.VentaGenerada && + !venta.VentaTimbrada && + TienePermiso(PermisoAgregarConceptos); + GvConceptos.DataSource = conceptos; + GvConceptos.DataBind(); + + decimal subtotal = conceptos.Sum( + concepto => + Math.Round( + concepto.Cantidad * concepto.PrecioUnitario, + 2)); + decimal descuento = conceptos.Sum( + concepto => concepto.Descuento); + decimal iva = conceptos.Sum( + concepto => concepto.IVA); + decimal total = conceptos.Sum( + concepto => concepto.Importe); + + TotalVentaActual = total; + + LitSubtotal.Text = FormatearMoneda(subtotal); + LitDescuento.Text = FormatearMoneda(descuento); + LitIVA.Text = FormatearMoneda(iva); + LitTotal.Text = FormatearMoneda(total); + LitTotalEncabezado.Text = LitTotal.Text; + LitPagoFolio.Text = Codificar( + venta.Serie + + "-" + + venta.Folio.ToString(CultureInfo.CurrentCulture)); + LitPagoCliente.Text = Codificar(venta.Cliente); + LitPagoTotal.Text = FormatearMoneda(total); + LitPagoSaldo.Text = LitPagoTotal.Text; + + if (!venta.VentaGenerada) + { + TxtObservaciones.Text = venta.NombrePago; + } + + TxtObservaciones.ReadOnly = venta.VentaGenerada; + BtnGenerar.Visible = !venta.VentaGenerada; + BtnPagar.Visible = + venta.VentaGenerada && + !venta.CvePago.HasValue; + PnlAgregarConcepto.Visible = PuedeAgregarConceptosActual; + BtnTimbrar.Visible = + venta.VentaGenerada && + !venta.VentaTimbrada && + TienePermiso(PermisoTimbrar); + PnlCancelarTimbre.Visible = + venta.VentaTimbrada && + TienePermiso(PermisoCancelarTimbre); + + if (PnlAgregarConcepto.Visible) + { + CargarProductosServicios(); + } + ConfigurarEstadoVenta(venta); + ConfigurarEstadoPago(venta); + CargarCondicionesPago(venta); + + EstablecerNavegacion(venta); + PnlVenta.Visible = true; + } + + private bool CargarOpcionesPago() + { + DbResult resultado = + AppServices.ServicioVentaTramite.ObtenerOpcionesPago( + CveSolicitudActual, + CveTramitePagoActual, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success || resultado.Data == null) + { + Alert( + resultado.Success + ? "No fue posible consultar las opciones de pago." + : resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return false; + } + + List formasPago = + resultado.Data.FormasPago ?? + new List(); + + if (formasPago.Count == 0) + { + Alert( + "No hay formas de pago configuradas.", + TipoMensaje.MsgAdvertencia); + return false; + } + + FormasPagoActuales = formasPago; + CuentasPagoActuales = resultado.Data.CuentasBancarias ?? + new List(); + LblSinCuentasSpei.Visible = + CuentasPagoActuales.Count == 0; + ReferenciaPagoActual = resultado.Data.ReferenciaPago; + LitReferenciaPagoGenerada.Text = Codificar( + ReferenciaPagoActual); + LitReferenciaTransferencia.Text = Codificar( + ReferenciaPagoActual); + + DdlCuentaBancaria.Items.Clear(); + DdlCuentaBancaria.Items.Add( + new ListItem("Seleccione", string.Empty)); + + foreach (ModeloCuentaBancariaOpcion cuenta in + CuentasPagoActuales) + { + DdlCuentaBancaria.Items.Add( + new ListItem( + cuenta.CuentaBancaria, + cuenta.CveBancoCuenta.ToString( + CultureInfo.InvariantCulture))); + } + + return true; + } + + private void SeleccionarFormaPago(string claveFormaPago) + { + ClaveFormaPagoActual = claveFormaPago; + bool efectivo = claveFormaPago == "01"; + bool transferencia = claveFormaPago == "03"; + + BtnFormaEfectivo.CssClass = efectivo + ? "btn blue venta-forma-pago activa" + : "btn default venta-forma-pago"; + BtnFormaTransferencia.CssClass = transferencia + ? "btn blue venta-forma-pago activa" + : "btn default venta-forma-pago"; + PnlPagoEfectivo.Visible = efectivo; + PnlPagoTransferencia.Visible = transferencia; + + if (transferencia) + { + ActualizarCuentaSpeiSeleccionada(); + } + } + + private void ActualizarCuentaSpeiSeleccionada() + { + int cveBancoCuenta; + ModeloCuentaBancariaOpcion cuenta = null; + + if (int.TryParse( + DdlCuentaBancaria.SelectedValue, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveBancoCuenta)) + { + cuenta = (CuentasPagoActuales ?? + new List()) + .FirstOrDefault( + item => item.CveBancoCuenta == cveBancoCuenta); + } + + LitClabeSpei.Text = cuenta == null + ? "Seleccione una cuenta para consultar la CLABE SPEI." + : Codificar(cuenta.CLABE); + } + + private void CargarCondicionesPago( + ModeloContextoVentaTramite venta) + { + PnlCondicionesPago.Visible = venta.VentaGenerada; + + if (!venta.VentaGenerada) + { + return; + } + + DbResult resultado = + AppServices.ServicioVentaTramite + .ObtenerOpcionesCondicionesPago( + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success || resultado.Data == null) + { + Alert( + resultado.Success + ? "No fue posible consultar las condiciones de pago." + : resultado.UserMessage, + TipoMensaje.MsgAdvertencia); + return; + } + + DdlMetodoPagoVenta.DataSource = resultado.Data.MetodosPago; + DdlMetodoPagoVenta.DataTextField = "Descripcion"; + DdlMetodoPagoVenta.DataValueField = "CveMetodoPago"; + DdlMetodoPagoVenta.DataBind(); + + DdlFormaPagoVenta.DataSource = resultado.Data.FormasPago; + DdlFormaPagoVenta.DataTextField = "FormaPago"; + DdlFormaPagoVenta.DataValueField = "CveFormaPago"; + DdlFormaPagoVenta.DataBind(); + + SeleccionarLista( + DdlMetodoPagoVenta, + venta.CveMetodoPago.ToString( + CultureInfo.InvariantCulture)); + SeleccionarLista( + DdlFormaPagoVenta, + venta.CveFormaPago.ToString( + CultureInfo.InvariantCulture)); + TxtFechaVencimiento.Text = + (venta.FechaVencimiento ?? venta.Fecha.Date).ToString( + "yyyy-MM-dd", + CultureInfo.InvariantCulture); + + bool puedeEditar = !venta.VentaTimbrada; + DdlMetodoPagoVenta.Enabled = puedeEditar; + DdlFormaPagoVenta.Enabled = puedeEditar; + TxtFechaVencimiento.Enabled = puedeEditar; + BtnGuardarCondicionesPago.Visible = puedeEditar; + } + + private static void SeleccionarLista( + ListControl lista, + string valor) + { + if (lista.Items.FindByValue(valor) != null) + { + lista.SelectedValue = valor; + } + } + + private void MostrarModalPago() + { + RegistraScript( + "window.SIGVentaTramite.mostrarPago();", + "ModalPagoVenta"); + } + + private void ConfigurarEstadoVenta( + ModeloContextoVentaTramite venta) + { + if (venta.VentaTimbrada) + { + LblEstadoVenta.Text = string.IsNullOrWhiteSpace(venta.UuidTimbre) + ? "Timbrada" + : "Timbrada · " + venta.UuidTimbre; + LblEstadoVenta.CssClass = + "venta-estado es-timbrada"; + return; + } + + if (venta.TimbreCancelado) + { + LblEstadoVenta.Text = "Timbre cancelado"; + LblEstadoVenta.CssClass = + "venta-estado es-timbre-cancelado"; + return; + } + + if (venta.VentaGenerada) + { + LblEstadoVenta.Text = "Venta generada"; + LblEstadoVenta.CssClass = + "venta-estado es-generada"; + return; + } + + LblEstadoVenta.Text = "Pendiente de generar"; + LblEstadoVenta.CssClass = + "venta-estado es-sin-generar"; + } + + private void ConfigurarEstadoPago( + ModeloContextoVentaTramite venta) + { + LblEstadoPago.Visible = venta.VentaGenerada; + + if (!venta.VentaGenerada) + { + return; + } + + if (venta.VentaPagada) + { + LblEstadoPago.Text = "Pago autorizado"; + LblEstadoPago.CssClass = + "venta-estado es-pagada"; + return; + } + + if (venta.PagoPendienteAutorizacion) + { + LblEstadoPago.Text = + "Pago pendiente de autorización · " + + venta.ReferenciaPago; + LblEstadoPago.CssClass = + "venta-estado es-pago-pendiente"; + return; + } + + LblEstadoPago.Text = "Pendiente de pago"; + LblEstadoPago.CssClass = + "venta-estado es-sin-pago"; + } + + private void CargarProductosServicios() + { + DbResult> resultado = + AppServices.ProductoServicioService.List( + null, + false, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + List productos = resultado.Data ?? + new List(); + ProductosServiciosActuales = productos; + string seleccionActual = DdlProductoServicio.SelectedValue; + + DdlProductoServicio.Items.Clear(); + DdlProductoServicio.Items.Add( + new ListItem("Seleccione", string.Empty)); + + foreach (ProductoServicioModel producto in productos) + { + string texto = string.IsNullOrWhiteSpace(producto.Codigo) + ? producto.PS + : producto.Codigo.Trim() + " - " + producto.PS; + DdlProductoServicio.Items.Add( + new ListItem(texto, producto.CvePS.ToString())); + } + + if (!string.IsNullOrWhiteSpace(seleccionActual) && + DdlProductoServicio.Items.FindByValue(seleccionActual) != null) + { + DdlProductoServicio.SelectedValue = seleccionActual; + } + } + + private ProductoServicioModel ObtenerProductoSeleccionado() + { + int cvePS; + List productos = + ProductosServiciosActuales ?? + new List(); + + return int.TryParse(DdlProductoServicio.SelectedValue, out cvePS) + ? productos.FirstOrDefault( + producto => producto.CvePS == cvePS) + : null; + } + + private void GuardarConcepto( + ModeloCapturaConceptoVentaTramite concepto, + string mensajeExito) + { + DbResult resultado = + AppServices.ServicioVentaTramite.GuardarConcepto( + concepto, + CurrentUser.CveUsuario, + CurrentUser.NombreDominio); + + if (!resultado.Success) + { + Alert(resultado.UserMessage, TipoMensaje.MsgAdvertencia); + return; + } + + Alert(mensajeExito, TipoMensaje.ToastExito); + CargarVenta(); + } + + private bool ValidarPermiso(string codigoPermiso) + { + if (TienePermiso(codigoPermiso)) + { + return true; + } + + Alert( + "No cuenta con permiso para realizar esta acción.", + TipoMensaje.MsgAdvertencia); + return false; + } + + private bool TienePermiso(string codigoPermiso) + { + return AppServices.PermissionService.HasPermission( + CurrentUser.CveUsuario, + codigoPermiso); + } + + private static bool IntentarDecimal( + string texto, + out decimal valor) + { + return decimal.TryParse( + texto, + NumberStyles.Number, + CultureInfo.CurrentCulture, + out valor) || + decimal.TryParse( + texto, + NumberStyles.Number, + CultureInfo.InvariantCulture, + out valor); + } + + private void EstablecerNavegacion( + ModeloContextoVentaTramite venta) + { + var elementos = new[] + { + new BreadcrumbItemModel + { + Texto = "Fraccionamientos", + Url = "~/Pages/Fraccionamientos/Fraccionamientos.aspx" + }, + new BreadcrumbItemModel + { + Texto = ObtenerTexto(venta.Fraccionamiento), + Url = ObtenerUrlFraccionamiento( + venta.CveFraccionamiento) + }, + new BreadcrumbItemModel + { + Texto = "Venta de trámite" + } + }; + + ((Site)Master).SetPageNavigation( + "Venta de trámite", + elementos); + } + + private string ObtenerUrlFraccionamiento(int cveFraccionamiento) + { + return ResolveUrl( + "~/Pages/Fraccionamientos/FraccionamientoDetalle.aspx?id=" + + cveFraccionamiento.ToString(CultureInfo.InvariantCulture)); + } + + private string Codificar(string valor) + { + return Server.HtmlEncode(ObtenerTexto(valor)); + } + + private static string ObtenerTexto(string valor) + { + return string.IsNullOrWhiteSpace(valor) + ? "—" + : valor.Trim(); + } + + private static string FormatearMoneda(decimal valor) + { + return valor.ToString("C2", CulturaMoneda); + } + } +} diff --git a/SIG.Web/SIG.Web.csproj b/SIG.Web/SIG.Web.csproj index 71ac73a..a96ce5d 100644 --- a/SIG.Web/SIG.Web.csproj +++ b/SIG.Web/SIG.Web.csproj @@ -115,7 +115,11 @@ + + + + diff --git a/SIG.Web/Scripts/BitacoraGrid.js b/SIG.Web/Scripts/BitacoraGrid.js index e3297a4..d04301d 100644 --- a/SIG.Web/Scripts/BitacoraGrid.js +++ b/SIG.Web/Scripts/BitacoraGrid.js @@ -110,8 +110,206 @@ root.setAttribute('data-sig-bitacora-grid-initialized', '1'); } + function clearPaginationTimer(slider) { + if (!slider || !slider.sigBitacoraPaginationTimer) { + return; + } + + window.clearTimeout(slider.sigBitacoraPaginationTimer); + slider.sigBitacoraPaginationTimer = null; + } + + function setPaginationSliderDisplay(slider, track, label) { + var currentValue = parseInt(slider.value, 10); + var totalPages = parseInt(slider.max, 10); + var position = totalPages <= 1 + ? 0 + : ((currentValue - 1) * 100) / (totalPages - 1); + var pageText = 'Página ' + currentValue + ' de ' + totalPages; + + track.style.setProperty( + '--sig-bitacora-page-position', + position + '%' + ); + track.setAttribute( + 'data-sig-slider-edge', + currentValue <= 1 + ? 'start' + : currentValue >= totalPages + ? 'end' + : 'middle' + ); + label.textContent = pageText; + slider.setAttribute('aria-valuenow', currentValue.toString()); + slider.setAttribute('aria-valuetext', pageText); + } + + function initializePaginationSlider(root) { + var slider = root.querySelector( + '.js-sig-bitacora-grid-pagination-slider' + ); + + if (!slider || + slider.getAttribute( + 'data-sig-bitacora-pagination-slider-initialized' + ) === '1') { + return; + } + + var track = slider.parentNode; + var label = track.querySelector( + '.sig-bitacora-grid-pagination-slider-label' + ); + var requestedPageField = document.getElementById( + slider.getAttribute('data-sig-page-field-id') + ); + var pageRequest = root.querySelector( + '.js-sig-bitacora-grid-page-request' + ); + var pointerInteraction = false; + var thumbRadius = 12; + + if (!track || !label || !requestedPageField || !pageRequest) { + return; + } + + function setLabelVisible(visible) { + if (visible) { + track.classList.add('is-label-visible'); + return; + } + + track.classList.remove('is-label-visible'); + } + + function updateLabelHover(event) { + if (pointerInteraction) { + setLabelVisible(true); + return; + } + + var rectangle = slider.getBoundingClientRect(); + var minimum = parseInt(slider.min, 10) || 1; + var maximum = parseInt(slider.max, 10) || minimum; + var current = parseInt(slider.value, 10) || minimum; + var range = Math.max(maximum - minimum, 1); + var usableWidth = Math.max( + rectangle.width - (thumbRadius * 2), + 0 + ); + var thumbCenter = rectangle.left + thumbRadius + + (((current - minimum) / range) * usableWidth); + var isOverThumb = + Math.abs(event.clientX - thumbCenter) <= thumbRadius && + event.clientY >= rectangle.top - 4 && + event.clientY <= rectangle.bottom + 4; + + setLabelVisible(isOverThumb); + } + + function scheduleNavigation() { + var selectedPage = parseInt(slider.value, 10); + var currentPage = parseInt( + slider.getAttribute('data-sig-current-page'), + 10 + ); + var totalPages = parseInt(slider.max, 10); + + clearPaginationTimer(slider); + + if (slider.disabled || + totalPages <= 1 || + selectedPage === currentPage) { + requestedPageField.value = ''; + return; + } + + requestedPageField.value = selectedPage.toString(); + slider.sigBitacoraPaginationTimer = window.setTimeout( + function () { + var finalPage = parseInt(slider.value, 10); + + slider.sigBitacoraPaginationTimer = null; + + if (slider.disabled || + finalPage === currentPage || + finalPage !== selectedPage || + !document.documentElement.contains(slider)) { + requestedPageField.value = ''; + return; + } + + requestedPageField.value = finalPage.toString(); + slider.disabled = true; + pageRequest.click(); + }, + 3000 + ); + } + + function handleInput() { + setPaginationSliderDisplay(slider, track, label); + setLabelVisible(true); + clearPaginationTimer(slider); + + if (!pointerInteraction) { + scheduleNavigation(); + } + } + + function beginPointerInteraction() { + pointerInteraction = true; + setLabelVisible(true); + clearPaginationTimer(slider); + } + + function endPointerInteraction(event) { + pointerInteraction = false; + + if (event && event.type === 'touchend') { + setLabelVisible(false); + } else if (event && typeof event.clientX === 'number') { + updateLabelHover(event); + } + + scheduleNavigation(); + } + + slider.addEventListener('input', handleInput, false); + slider.addEventListener('change', endPointerInteraction, false); + slider.addEventListener('mousedown', beginPointerInteraction, false); + slider.addEventListener('mouseup', endPointerInteraction, false); + slider.addEventListener('touchstart', beginPointerInteraction, false); + slider.addEventListener('touchend', endPointerInteraction, false); + slider.addEventListener('mousemove', updateLabelHover, false); + slider.addEventListener('mouseleave', function () { + if (!pointerInteraction) { + setLabelVisible(false); + } + }, false); + + setPaginationSliderDisplay(slider, track, label); + slider.setAttribute( + 'data-sig-bitacora-pagination-slider-initialized', + '1' + ); + } + api.initialize = function (root) { - getRoots(root).forEach(initializeRoot); + getRoots(root).forEach(function (bitacoraRoot) { + initializeRoot(bitacoraRoot); + initializePaginationSlider(bitacoraRoot); + }); + }; + + api.cancelPendingNavigation = function (root) { + getRoots(root).forEach(function (bitacoraRoot) { + var slider = bitacoraRoot.querySelector( + '.js-sig-bitacora-grid-pagination-slider' + ); + + clearPaginationTimer(slider); + }); }; api.showModal = function (id) { @@ -145,9 +343,15 @@ window.SIG_BITACORA_GRID_PARTIAL_INITIALIZED = true; - Sys.WebForms.PageRequestManager.getInstance().add_endRequest( + var requestManager = + Sys.WebForms.PageRequestManager.getInstance(); + + requestManager.add_beginRequest(function () { + api.cancelPendingNavigation(document); + }); + + requestManager.add_endRequest( function (sender, args) { - debugger var panels = null; if (args?.get_panelsUpdated) { panels = args.get_panelsUpdated(); diff --git a/SIG.Web/Scripts/CatalogosTramites.js b/SIG.Web/Scripts/CatalogosTramites.js index c18d9d3..62f9fc8 100644 --- a/SIG.Web/Scripts/CatalogosTramites.js +++ b/SIG.Web/Scripts/CatalogosTramites.js @@ -130,4 +130,4 @@ initializeOrderGrids(document); }); } -}(window, window.jQuery)); \ No newline at end of file +}(window, window.jQuery)); diff --git a/SIG.Web/Scripts/custom.js b/SIG.Web/Scripts/custom.js index c771ca0..e7a4209 100644 --- a/SIG.Web/Scripts/custom.js +++ b/SIG.Web/Scripts/custom.js @@ -1994,8 +1994,7 @@ function setwebservice(idDdlWS, idhdValue, idhdText, btn) { url: "/Ashx/SIGWeb.ashx", dataType: 'json', delay: 500, - data: function (params) { - debugger; + data: function (params) { return { Name: params.term, // search term CveSubFamilia: (!(DdlWS.attr('data-idSubFamilia')) || DdlWS.attr('data-idSubFamilia') == '') ? ((!(DdlWS.data('subFamilia'))) ? DdlWS.data('subfamilia') : -2) : $('#' + DdlWS.attr('data-idSubFamilia') + ' option:selected').val(), diff --git a/SIG.Web/Scripts/funciones.js b/SIG.Web/Scripts/funciones.js index 4f864af..0cce563 100644 --- a/SIG.Web/Scripts/funciones.js +++ b/SIG.Web/Scripts/funciones.js @@ -723,8 +723,7 @@ function CerrarVentana() { window.parent.$("#ajax").modal('hide'); } showPopup = function (div_id, width, height) { - //Generar URL para thickbox - debugger; + //Generar URL para thickbox var thickboxURL = "#TB_inline?height=" + height + "&width=" + width + "&inlineId=" + div_id + ""; //&modal=true //Llamar a método de thickbox que muestra un popup con la URL generada tb_show(null, thickboxURL, null); diff --git a/SIG.Web/Scripts/gridviewScroll.js b/SIG.Web/Scripts/gridviewScroll.js index bc7ad89..328afcb 100644 --- a/SIG.Web/Scripts/gridviewScroll.js +++ b/SIG.Web/Scripts/gridviewScroll.js @@ -901,8 +901,7 @@ NOTAS ADSISTEMAS: } function scrollVertical(y, isWheel, isClick, isCustom) { - var delta = y; - //debugger; + var delta = y; var maxTop = panelitemcontent.outerHeight() - verticalbar.outerHeight() - opt.arrowsize; if (isWheel || isClick) { diff --git a/SIG.Web/Site.master b/SIG.Web/Site.master index 7e04192..4ec9611 100644 --- a/SIG.Web/Site.master +++ b/SIG.Web/Site.master @@ -91,7 +91,31 @@ @@ -100,6 +124,91 @@
    + +
    diff --git a/SIG.Web/Site.master.cs b/SIG.Web/Site.master.cs index d614a5a..9cf532b 100644 --- a/SIG.Web/Site.master.cs +++ b/SIG.Web/Site.master.cs @@ -1,18 +1,33 @@ using SIG.Web.AppCode.Configuration; using SIG.Web.AppCode.Infrastructure.WebForms; +using SIG.Web.AppCode.Models.Common; +using SIG.Web.AppCode.Models.Security; using SIG.Web.AppCode.Services.Logging; using SIG.Web.AppCode.Session; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Web; using System.Web.UI; +using System.Web.UI.WebControls; namespace SIG.Web { public partial class Site : MasterPage, IGlobalErrorPresenter { + private List UsuariosCambioActuales + { + get + { + return ViewState["UsuariosCambioActuales"] + as List + ?? new List(); + } + set { ViewState["UsuariosCambioActuales"] = value; } + } + protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) @@ -32,11 +47,14 @@ namespace SIG.Web return; } + user = NormalizarSesionActual(user); + HdnCveE.Value = user.CveEmpresa.ToString(); HdnCveU.Value = user.CveUsuario.ToString(); LitTit.Text = HtmlText(System.Configuration.ConfigurationManager.AppSettings["AppTitle"] ?? "SIG"); LtlUserName.Text = HtmlText(user.Nombre ?? user.NombreUsuario ?? "Usuario"); + LiCambiarUsuario.Visible = user.PuedeCambiarUsuario; IReadOnlyList menuItems = AppServices.MenuProvider.GetMenu(user); LtlMenu.Text = BuildMenu(menuItems); @@ -44,6 +62,38 @@ namespace SIG.Web BindNotifications(user); } + private UserSessionModel NormalizarSesionActual( + UserSessionModel usuarioSesion) + { + if (usuarioSesion.CveUsuarioOriginal > 0) + { + return usuarioSesion; + } + + usuarioSesion.CveUsuarioOriginal = + usuarioSesion.CveUsuario; + usuarioSesion.CveRolOriginal = usuarioSesion.CveRol; + usuarioSesion.EsAdmin = usuarioSesion.CveRol == 1; + usuarioSesion.PuedeCambiarUsuario = + usuarioSesion.CveRol == 1 || + usuarioSesion.CveRol == 2; + + DbResult resultadoPerfil = + AppServices.PerfilUsuarioService.ObtenerPerfil( + usuarioSesion); + + if (resultadoPerfil.Success && + resultadoPerfil.Data != null && + resultadoPerfil.Data.Sesion != null) + { + usuarioSesion.CveCliente = + resultadoPerfil.Data.Sesion.CveCliente; + } + + AppServices.UserContext.SetCurrentUser(usuarioSesion); + return usuarioSesion; + } + public void SetPageNavigation(string title, IEnumerable items) { string safeTitle = string.IsNullOrWhiteSpace(title) ? Page.Title : title.Trim(); @@ -271,6 +321,129 @@ namespace SIG.Web Context.ApplicationInstance.CompleteRequest(); } + protected void BtnAbrirCambioUsuario_Click( + object sender, + EventArgs e) + { + TxtBuscarUsuarioCambio.Text = string.Empty; + CargarUsuariosCambio(); + } + + protected void BtnBuscarUsuarioCambio_Click( + object sender, + EventArgs e) + { + CargarUsuariosCambio(); + } + + protected void GvUsuariosCambio_RowCommand( + object sender, + GridViewCommandEventArgs e) + { + if (!string.Equals( + e.CommandName, + "SeleccionarUsuario", + StringComparison.Ordinal)) + { + return; + } + + UserSessionModel usuarioSesion = + AppServices.UserContext.GetCurrentUser(); + int cveUsuarioSeleccionado; + + if (usuarioSesion == null || + !usuarioSesion.PuedeCambiarUsuario || + !int.TryParse( + Convert.ToString( + e.CommandArgument, + CultureInfo.InvariantCulture), + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out cveUsuarioSeleccionado) || + !UsuariosCambioActuales.Any( + usuario => + usuario.CveUsuario == cveUsuarioSeleccionado)) + { + MostrarErrorCambioUsuario( + "Seleccione un usuario válido."); + MostrarModalCambioUsuario(); + return; + } + + DbResult resultado = + AppServices.PerfilUsuarioService.CambiarUsuario( + usuarioSesion, + cveUsuarioSeleccionado); + + if (!resultado.Success || resultado.Data == null) + { + MostrarErrorCambioUsuario( + resultado.Success + ? "No fue posible cambiar el usuario de la sesión." + : resultado.UserMessage); + MostrarModalCambioUsuario(); + return; + } + + AppServices.UserContext.SetCurrentUser(resultado.Data); + Response.Redirect("~/Inicio.aspx", false); + Context.ApplicationInstance.CompleteRequest(); + } + + private void CargarUsuariosCambio() + { + UserSessionModel usuarioSesion = + AppServices.UserContext.GetCurrentUser(); + + if (usuarioSesion == null || + !usuarioSesion.PuedeCambiarUsuario) + { + Response.Redirect("~/AccessDenied.aspx", false); + Context.ApplicationInstance.CompleteRequest(); + return; + } + + DbResult> resultado = + AppServices.PerfilUsuarioService.ListarUsuariosCambio( + usuarioSesion, + TxtBuscarUsuarioCambio.Text); + + if (!resultado.Success) + { + UsuariosCambioActuales = + new List(); + MostrarErrorCambioUsuario(resultado.UserMessage); + } + else + { + UsuariosCambioActuales = resultado.Data ?? + new List(); + LblCambioUsuario.Visible = false; + } + + GvUsuariosCambio.DataSource = UsuariosCambioActuales; + GvUsuariosCambio.DataBind(); + MostrarModalCambioUsuario(); + } + + private void MostrarErrorCambioUsuario(string mensaje) + { + LblCambioUsuario.Text = HtmlText(mensaje); + LblCambioUsuario.CssClass = "alert alert-warning"; + LblCambioUsuario.Visible = true; + } + + private void MostrarModalCambioUsuario() + { + ScriptManager.RegisterStartupScript( + Page, + GetType(), + "MostrarModalCambiarUsuario", + "$('#ModalCambiarUsuario').modal('show');", + true); + } + protected void smMain_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) { ExceptionLogger.Log(e.Exception, "SiteMaster.AsyncPostBackError"); @@ -291,4 +464,4 @@ namespace SIG.Web TipoMensaje.MsgError); } } -} \ No newline at end of file +} diff --git a/SIG.Web/Site.master.designer.cs b/SIG.Web/Site.master.designer.cs index 368992f..3800678 100644 --- a/SIG.Web/Site.master.designer.cs +++ b/SIG.Web/Site.master.designer.cs @@ -167,6 +167,10 @@ namespace SIG.Web /// protected global::System.Web.UI.WebControls.Literal LtlUserName; + protected global::System.Web.UI.HtmlControls.HtmlGenericControl LiCambiarUsuario; + + protected global::System.Web.UI.WebControls.LinkButton BtnAbrirCambioUsuario; + /// /// BtnLogout control. /// @@ -176,6 +180,14 @@ namespace SIG.Web /// protected global::System.Web.UI.WebControls.LinkButton BtnLogout; + protected global::System.Web.UI.WebControls.Label LblCambioUsuario; + + protected global::System.Web.UI.WebControls.TextBox TxtBuscarUsuarioCambio; + + protected global::System.Web.UI.WebControls.Button BtnBuscarUsuarioCambio; + + protected global::System.Web.UI.WebControls.GridView GvUsuariosCambio; + /// /// LtlMenu control. /// diff --git a/SIG.Web/Styles/BitacoraGrid.css b/SIG.Web/Styles/BitacoraGrid.css index 5887efe..f0ace93 100644 --- a/SIG.Web/Styles/BitacoraGrid.css +++ b/SIG.Web/Styles/BitacoraGrid.css @@ -76,11 +76,15 @@ } .sig-bitacora-grid-scroll { - max-height: 560px; + max-height: 300px; overflow: auto; overscroll-behavior: contain; } - +table.sig-bitacora-grid-table > tbody > tr:first-child > th { + position: sticky; + top: 0; + z-index: 10; +} .sig-bitacora-grid-table { margin-bottom: 0; table-layout: fixed; @@ -154,16 +158,25 @@ align-items: center; border-top: 1px solid #e7e9ec; display: flex; + flex-direction: column; gap: 10px; justify-content: center; - min-height: 48px; - padding: 8px 12px; + min-height: 100px; + padding: 10px 12px 14px; +} + +.sig-bitacora-grid-pager-actions { + align-items: center; + display: flex; + gap: 10px; + justify-content: center; + width: 100%; } .sig-bitacora-grid-page-summary { color: #7d8790; font-size: 12px; - min-width: 220px; + min-width: 370px; text-align: center; } @@ -171,6 +184,152 @@ min-width: 84px; } +.sig-bitacora-grid-page-button.aspNetDisabled, +.sig-bitacora-grid-page-button[disabled] { + cursor: not-allowed; + opacity: 0.5; + pointer-events: none; +} + +.sig-bitacora-grid-pagination-slider { + align-items: flex-end; + display: flex; + gap: 10px; + max-width: 720px; + width: 100%; +} + +.sig-bitacora-grid-pagination-slider-endpoint { + color: #7d8790; + flex: 0 0 24px; + font-size: 11px; + line-height: 18px; + text-align: center; +} + +.sig-bitacora-grid-pagination-slider-track { + --sig-bitacora-page-position: 0%; + flex: 1 1 auto; + min-width: 0; + padding-top: 10px; + position: relative; +} + +.sig-bitacora-grid-pagination-slider-label { + background: #364150; + border-radius: 3px; + color: #fff; + font-size: 11px; + left: var(--sig-bitacora-page-position); + line-height: 18px; + opacity: 0; + padding: 2px 7px; + pointer-events: none; + position: absolute; + top: 0; + transform: translateX(-50%); + transition: opacity 120ms ease-in-out; + visibility: hidden; + white-space: nowrap; +} + +.sig-bitacora-grid-pagination-slider-track.is-label-visible + .sig-bitacora-grid-pagination-slider-label { + opacity: 1; + visibility: visible; +} + +.sig-bitacora-grid-pagination-slider-label::after { + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 5px solid #364150; + content: ""; + left: 50%; + position: absolute; + top: 100%; + transform: translateX(-50%); +} + +.sig-bitacora-grid-pagination-slider-track[data-sig-slider-edge="start"] + .sig-bitacora-grid-pagination-slider-label { + transform: translateX(0); +} + +.sig-bitacora-grid-pagination-slider-track[data-sig-slider-edge="start"] + .sig-bitacora-grid-pagination-slider-label::after { + left: 8px; +} + +.sig-bitacora-grid-pagination-slider-track[data-sig-slider-edge="end"] + .sig-bitacora-grid-pagination-slider-label { + transform: translateX(-100%); +} + +.sig-bitacora-grid-pagination-slider-track[data-sig-slider-edge="end"] + .sig-bitacora-grid-pagination-slider-label::after { + left: calc(100% - 8px); +} + +.sig-bitacora-grid-pagination-slider-input { + -webkit-appearance: none; + appearance: none; + background: transparent; + cursor: pointer; + display: block; + height: 18px; + margin: 0; + padding: 0; + width: 100%; +} + +.sig-bitacora-grid-pagination-slider-input::-webkit-slider-runnable-track { + background: #d7dde3; + border-radius: 4px; + height: 7px; +} + +.sig-bitacora-grid-pagination-slider-input::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + background: #26a69a; + border: 2px solid #fff; + border-radius: 50%; + box-shadow: 0 0 0 1px #1f8c82; + height: 16px; + margin-top: -4px; + width: 16px; +} + +.sig-bitacora-grid-pagination-slider-input::-moz-range-track { + background: #d7dde3; + border: 0; + border-radius: 4px; + height: 7px; +} + +.sig-bitacora-grid-pagination-slider-input::-moz-range-thumb { + background: #26a69a; + border: 2px solid #fff; + border-radius: 50%; + box-shadow: 0 0 0 1px #1f8c82; + height: 12px; + width: 12px; +} + +.sig-bitacora-grid-pagination-slider-input:focus { + outline: 1px dotted #364150; + outline-offset: 3px; +} + +.sig-bitacora-grid-pagination-slider-input:disabled { + cursor: not-allowed; + opacity: 0.55; +} + +.sig-bitacora-grid-page-request { + display: none; +} + .sig-bitacora-grid-modal .modal-dialog { max-width: 980px; } @@ -255,4 +414,12 @@ .sig-bitacora-grid-table { min-width: 980px; } + + .sig-bitacora-grid-pager-actions { + flex-wrap: wrap; + } + + .sig-bitacora-grid-page-summary { + min-width: 240px; + } } diff --git a/SIG.Web/Styles/VentaTramite.css b/SIG.Web/Styles/VentaTramite.css new file mode 100644 index 0000000..9795e23 --- /dev/null +++ b/SIG.Web/Styles/VentaTramite.css @@ -0,0 +1,434 @@ +.venta-tarjeta-encabezado, +.venta-tarjeta { + background: #ffffff; + border: 1px solid #dfe5ec; + box-shadow: 0 1px 2px rgba(31, 45, 61, 0.04); +} + +.venta-tarjeta-encabezado { + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + margin-bottom: 18px; + padding: 22px 26px; +} + +.venta-sobretitulo { + display: block; + margin-bottom: 5px; + color: #78909c; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.venta-tarjeta-encabezado h2 { + margin: 0 0 5px; + color: #263238; + font-size: 24px; +} + +.venta-tarjeta-encabezado p { + margin: 0; + color: #718096; +} + +.venta-total-encabezado { + min-width: 180px; + text-align: right; +} + +.venta-total-encabezado span { + display: block; + color: #78909c; + font-size: 12px; + text-transform: uppercase; +} + +.venta-total-encabezado strong { + color: #263238; + font-size: 28px; +} + +.venta-estado { + display: inline-block; + margin-top: 10px; + padding: 4px 10px; + border-radius: 2px; + font-size: 12px; + font-weight: 600; +} + +.venta-estado.es-sin-generar { + background: #fff4cc; + color: #8a6d00; +} + +.venta-estado.es-generada { + background: #d9edf7; + color: #31708f; +} + +.venta-estado.es-pagada { + background: #dff0d8; + color: #3c763d; +} + +.venta-estado.es-pago-pendiente { + background: #fff4cc; + color: #8a6d00; +} + +.venta-estado.es-sin-pago { + background: #edf1f5; + color: #657786; +} + +.venta-estado.es-timbrada { + background: #e8f7ee; + color: #27824b; +} + +.venta-estado.es-timbre-cancelado { + background: #fdebec; + color: #b13a42; +} + +.venta-captura-numero { + min-width: 90px; + max-width: 120px; +} + +.venta-agregar-concepto { + align-items: flex-end; + background: #f7f9fb; + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 14px; + padding: 14px; +} + +.venta-agregar-concepto .form-group { + margin-bottom: 0; +} + +.venta-producto-nuevo { + flex: 1 1 360px; +} + +.venta-accion-agregar { + padding-bottom: 1px; +} + +.venta-cancelacion-timbre { + border-top: 1px solid #e4e8ec; + margin-top: 15px; + padding-top: 15px; +} + +.venta-cuadricula-superior, +.venta-cuadricula-inferior { + display: grid; + gap: 18px; + margin-bottom: 18px; +} + +.venta-cuadricula-superior { + grid-template-columns: minmax(0, 3fr) minmax(320px, 2fr); +} + +.venta-cuadricula-inferior { + grid-template-columns: minmax(280px, 1fr) minmax(320px, 1.2fr) minmax(220px, 0.7fr); +} + +.venta-tarjeta { + padding: 18px; +} + +.venta-titulo-tarjeta { + display: flex; + align-items: center; + gap: 8px; + margin: -4px 0 16px; + padding-bottom: 10px; + border-bottom: 1px solid #edf1f5; + color: #3598dc; +} + +.venta-titulo-tarjeta h3 { + margin: 0; + font-size: 14px; + font-weight: 700; + text-transform: uppercase; +} + +.venta-cuadricula-datos { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px 24px; + margin: 0; +} + +.venta-cuadricula-datos div { + min-width: 0; +} + +.venta-cuadricula-datos dt, +.venta-totales dt { + margin-bottom: 4px; + color: #657786; + font-size: 12px; + font-weight: 600; +} + +.venta-cuadricula-datos dd, +.venta-totales dd { + margin: 0; + color: #263238; + overflow-wrap: anywhere; +} + +.venta-dato-amplio { + grid-column: 1 / -1; +} + +.venta-tarjeta-detalle { + margin-bottom: 18px; +} + +.venta-tabla-desplazable { + overflow-x: auto; +} + +.venta-tabla-desplazable th { + background: #e1e3e6; + color: #263238; + white-space: nowrap; +} + +.venta-totales { + width: min(100%, 340px); + margin: 18px 0 0 auto; + padding: 14px 18px; + background: #f7f9fb; +} + +.venta-totales div { + display: flex; + justify-content: space-between; + gap: 20px; + padding: 5px 0; +} + +.venta-fila-total { + margin-top: 6px; + padding-top: 10px !important; + border-top: 1px solid #dfe5ec; + font-size: 16px; + font-weight: 700; +} + +.venta-tarjeta-acciones { + display: flex; + flex-direction: column; +} + +.venta-tarjeta-acciones .venta-titulo-tarjeta { + width: 100%; +} + +.venta-boton-pagar { + align-self: stretch; + margin: auto 20px; + text-align: center; +} + +.venta-modal-pago { + width: min(760px, calc(100% - 30px)); +} + +.venta-modal-pago .modal-header { + padding: 22px 26px 14px; +} + +.venta-modal-pago .modal-title { + color: #263238; + font-size: 22px; + font-weight: 600; +} + +.venta-modal-subtitulo { + margin: 5px 0 0; + color: #718096; +} + +.venta-modal-pago .modal-body { + padding: 20px 26px; +} + +.venta-resumen-pago { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 8px; + margin-bottom: 22px; +} + +.venta-resumen-pago > div { + min-width: 0; + padding: 13px 14px; + border: 1px solid #dfe5ec; + background: #f9fbfc; +} + +.venta-resumen-pago span { + display: block; + margin-bottom: 4px; + color: #718096; + font-size: 11px; + text-transform: uppercase; +} + +.venta-resumen-pago strong { + display: block; + color: #263238; + font-size: 14px; + overflow-wrap: anywhere; +} + +.venta-resumen-saldo strong { + color: #d9534f; +} + +.venta-formulario-pago { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0 20px; +} + +.venta-formulario-pago label { + color: #37474f; + font-weight: 600; +} + +.venta-formas-pago { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.venta-forma-pago { + min-width: 180px; +} + +.venta-forma-pago[disabled], +.venta-forma-pago.disabled { + cursor: not-allowed; + opacity: 0.55; +} + +.venta-instruccion-pago, +.venta-transferencia-pago { + border: 1px solid #d8e4ef; + background: #f7fbfe; + padding: 14px 16px; +} + +.venta-instruccion-pago strong, +.venta-instruccion-pago span, +.venta-dato-spei strong, +.venta-dato-spei span { + display: block; +} + +.venta-instruccion-pago span, +.venta-dato-spei span { + margin-top: 4px; + color: #263238; + font-family: Consolas, monospace; + font-size: 16px; + font-weight: 700; +} + +.venta-instruccion-pago p { + margin: 8px 0 0; + color: #657786; +} + +.venta-transferencia-pago { + display: grid; + grid-template-columns: minmax(240px, 1fr) minmax(180px, 0.8fr); + gap: 12px 18px; +} + +.venta-transferencia-pago .form-group { + grid-column: 1 / -1; + margin-bottom: 0; +} + +.venta-aviso-spei { + display: block; + grid-column: 1 / -1; + margin: 0; +} + +.venta-campo-amplio { + grid-column: 1 / -1; +} + +.venta-aviso-autorizacion { + margin: 4px 0 0; +} + +.venta-aviso-autorizacion .fa { + margin-right: 6px; +} + +.venta-modal-pago .modal-footer { + padding: 14px 26px 20px; +} + +@media (max-width: 1100px) { + .venta-cuadricula-superior, + .venta-cuadricula-inferior { + grid-template-columns: 1fr; + } + + .venta-boton-pagar { + align-self: flex-start; + margin: 0; + min-width: 220px; + } +} + +@media (max-width: 640px) { + .venta-tarjeta-encabezado { + align-items: flex-start; + flex-direction: column; + } + + .venta-total-encabezado { + min-width: 0; + text-align: left; + } + + .venta-cuadricula-datos { + grid-template-columns: 1fr; + } + + .venta-dato-amplio { + grid-column: auto; + } + + .venta-resumen-pago, + .venta-formulario-pago, + .venta-transferencia-pago { + grid-template-columns: 1fr; + } + + .venta-campo-amplio { + grid-column: auto; + } +} diff --git a/TipoTramiteDetalle_CveUM_20260827.sql b/TipoTramiteDetalle_CveUM_20260827.sql new file mode 100644 index 0000000..a908dee --- /dev/null +++ b/TipoTramiteDetalle_CveUM_20260827.sql @@ -0,0 +1,213 @@ +SET NOCOUNT ON; +GO + +IF COL_LENGTH(N'dbo.Tra_PagosDetalle', N'CveUM') IS NULL +BEGIN + ALTER TABLE dbo.Tra_PagosDetalle + ADD CveUM int NULL; + + UPDATE Detalle + SET CveUM = Producto.CveUnidadMedida + FROM dbo.Tra_PagosDetalle AS Detalle + INNER JOIN dbo.ProductosServicios AS Producto + ON Producto.CvePS = Detalle.CvePS; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Tra_PagosDetalle + WHERE CveUM IS NULL + ) + BEGIN + THROW 50000, + 'No fue posible asignar una unidad de medida a todos los conceptos existentes.', + 1; + END; + + ALTER TABLE dbo.Tra_PagosDetalle + ALTER COLUMN CveUM int NOT NULL; +END; +GO + +IF NOT EXISTS +( + SELECT 1 + FROM sys.foreign_key_columns + WHERE parent_object_id = OBJECT_ID(N'dbo.Tra_PagosDetalle') + AND parent_column_id = COLUMNPROPERTY( + OBJECT_ID(N'dbo.Tra_PagosDetalle'), + N'CveUM', + 'ColumnId') +) +BEGIN + ALTER TABLE dbo.Tra_PagosDetalle WITH CHECK + ADD CONSTRAINT FK_Tra_PagosDetalle_CveUM + FOREIGN KEY (CveUM) + REFERENCES dbo.UnidadesMedida (CveUnidadMedida); + + ALTER TABLE dbo.Tra_PagosDetalle + CHECK CONSTRAINT FK_Tra_PagosDetalle_CveUM; +END; +GO + +DECLARE @Procedimientos TABLE +( + Nombre sysname NOT NULL PRIMARY KEY, + EsGuardado bit NOT NULL +); + +INSERT INTO @Procedimientos +( + Nombre, + EsGuardado +) +VALUES + (N'PA_Tra_PagoDetalleList', 0), + (N'PA_Tra_PagoDetalleGet', 0), + (N'PA_Tra_PagoDetalleSave', 1); + +DECLARE @Nombre sysname; +DECLARE @EsGuardado bit; +DECLARE @Definicion nvarchar(max); +DECLARE @DefinicionOriginal nvarchar(max); +DECLARE @InicioProcedimiento int; + +DECLARE CursorProcedimientos CURSOR LOCAL FAST_FORWARD FOR +SELECT + Nombre, + EsGuardado +FROM @Procedimientos +ORDER BY Nombre; + +OPEN CursorProcedimientos; + +FETCH NEXT FROM CursorProcedimientos INTO + @Nombre, + @EsGuardado; + +WHILE @@FETCH_STATUS = 0 +BEGIN + SET @Definicion = OBJECT_DEFINITION( + OBJECT_ID(N'dbo.' + @Nombre)); + + IF @Definicion IS NULL + BEGIN + THROW 50001, + 'No existe uno de los procedimientos requeridos para guardar la unidad de medida.', + 1; + END; + + SET @Definicion = REPLACE( + @Definicion, + CHAR(13) + CHAR(10), + CHAR(10)); + SET @DefinicionOriginal = @Definicion; + + IF @EsGuardado = 0 + BEGIN + SET @Definicion = REPLACE( + @Definicion, + N' PS.CveUnidadMedida,' + CHAR(10), + N' D.CveUM,' + CHAR(10)); + + SET @Definicion = REPLACE( + @Definicion, + N' ON UM.CveUnidadMedida = PS.CveUnidadMedida' + CHAR(10), + N' ON UM.CveUnidadMedida = D.CveUM' + CHAR(10)); + + IF @Definicion NOT LIKE N'%D.CveUM,%' + OR @Definicion NOT LIKE N'%UM.CveUnidadMedida = D.CveUM%' + BEGIN + THROW 50002, + 'El procedimiento de consulta no tiene la estructura esperada para CveUM.', + 1; + END; + END + ELSE IF @Definicion NOT LIKE N'%@CveUM int%' + BEGIN + SET @Definicion = REPLACE( + @Definicion, + N' @CvePS int,' + CHAR(10) + + N' @Cantidad decimal(18, 4),', + N' @CvePS int,' + CHAR(10) + + N' @CveUM int,' + CHAR(10) + + N' @Cantidad decimal(18, 4),'); + + SET @Definicion = REPLACE( + @Definicion, + N' IF @Cantidad <= 0' + CHAR(10), + N' IF NOT EXISTS' + CHAR(10) + + N' (' + CHAR(10) + + N' SELECT 1' + CHAR(10) + + N' FROM dbo.UnidadesMedida' + CHAR(10) + + N' WHERE CveUnidadMedida = @CveUM' + CHAR(10) + + N' )' + CHAR(10) + + N' BEGIN' + CHAR(10) + + N' SELECT' + CHAR(10) + + N' @ErrorMostrar = ''Seleccione una unidad de medida válida.'',' + CHAR(10) + + N' @ErrorTipo = 2;' + CHAR(10) + + N' RETURN;' + CHAR(10) + + N' END;' + CHAR(10) + CHAR(10) + + N' IF @Cantidad <= 0' + CHAR(10)); + + SET @Definicion = REPLACE( + @Definicion, + N' CvePS,' + CHAR(10) + + N' Cantidad,', + N' CvePS,' + CHAR(10) + + N' CveUM,' + CHAR(10) + + N' Cantidad,'); + + SET @Definicion = REPLACE( + @Definicion, + N' @CvePS,' + CHAR(10) + + N' @Cantidad,', + N' @CvePS,' + CHAR(10) + + N' @CveUM,' + CHAR(10) + + N' @Cantidad,'); + + SET @Definicion = REPLACE( + @Definicion, + N' SET CvePS = @CvePS,' + CHAR(10) + + N' Cantidad = @Cantidad,', + N' SET CvePS = @CvePS,' + CHAR(10) + + N' CveUM = @CveUM,' + CHAR(10) + + N' Cantidad = @Cantidad,'); + + IF @Definicion NOT LIKE N'%@CveUM int%' + OR @Definicion NOT LIKE N'%CveUM = @CveUM%' + OR @Definicion NOT LIKE N'%@CvePS,%' + CHAR(10) + N' @CveUM,%' + BEGIN + THROW 50003, + 'El procedimiento de guardado no tiene la estructura esperada para CveUM.', + 1; + END; + END; + + SET @InicioProcedimiento = CHARINDEX( + N'PROCEDURE', + UPPER(@Definicion)); + + IF @InicioProcedimiento = 0 + BEGIN + THROW 50004, + 'No fue posible localizar la declaración del procedimiento.', + 1; + END; + + SET @Definicion = STUFF( + @Definicion, + 1, + @InicioProcedimiento - 1, + N'CREATE OR ALTER '); + + EXEC sys.sp_executesql @Definicion; + + FETCH NEXT FROM CursorProcedimientos INTO + @Nombre, + @EsGuardado; +END; + +CLOSE CursorProcedimientos; +DEALLOCATE CursorProcedimientos; +GO diff --git a/TipoTramiteDetalle_Pagos.sql b/TipoTramiteDetalle_Pagos.sql index 2784ea2..a54d408 100644 --- a/TipoTramiteDetalle_Pagos.sql +++ b/TipoTramiteDetalle_Pagos.sql @@ -56,6 +56,7 @@ BEGIN CveTramitePagoDetalle int IDENTITY(1, 1) NOT NULL, CveTramitePago int NOT NULL, CvePS int NOT NULL, + CveUM int NOT NULL, Cantidad decimal(18, 4) CONSTRAINT DF_Tra_PagosDetalle_Cantidad DEFAULT (1) NOT NULL, FechaAlta datetime CONSTRAINT DF_Tra_PagosDetalle_FechaAlta DEFAULT (GETDATE()) NOT NULL, FechaModificacion datetime NULL, @@ -72,6 +73,9 @@ BEGIN CONSTRAINT FK_Tra_PagosDetalle_ProductosServicios FOREIGN KEY (CvePS) REFERENCES dbo.ProductosServicios (CvePS), + CONSTRAINT FK_Tra_PagosDetalle_CveUM + FOREIGN KEY (CveUM) + REFERENCES dbo.UnidadesMedida (CveUnidadMedida), CONSTRAINT FK_Tra_PagosDetalle_Usuarios FOREIGN KEY (CveUsuario) REFERENCES dbo.Sis_Usuarios (CveUsuario) @@ -79,6 +83,55 @@ BEGIN END; GO +IF COL_LENGTH(N'dbo.Tra_PagosDetalle', N'CveUM') IS NULL +BEGIN + ALTER TABLE dbo.Tra_PagosDetalle + ADD CveUM int NULL; + + UPDATE Detalle + SET CveUM = Producto.CveUnidadMedida + FROM dbo.Tra_PagosDetalle AS Detalle + INNER JOIN dbo.ProductosServicios AS Producto + ON Producto.CvePS = Detalle.CvePS; + + IF EXISTS + ( + SELECT 1 + FROM dbo.Tra_PagosDetalle + WHERE CveUM IS NULL + ) + BEGIN + THROW 50000, + 'No fue posible asignar una unidad de medida a todos los conceptos existentes.', + 1; + END; + + ALTER TABLE dbo.Tra_PagosDetalle + ALTER COLUMN CveUM int NOT NULL; +END; +GO + +IF NOT EXISTS +( + SELECT 1 + FROM sys.foreign_key_columns + WHERE parent_object_id = OBJECT_ID(N'dbo.Tra_PagosDetalle') + AND parent_column_id = COLUMNPROPERTY( + OBJECT_ID(N'dbo.Tra_PagosDetalle'), + N'CveUM', + 'ColumnId') +) +BEGIN + ALTER TABLE dbo.Tra_PagosDetalle WITH CHECK + ADD CONSTRAINT FK_Tra_PagosDetalle_CveUM + FOREIGN KEY (CveUM) + REFERENCES dbo.UnidadesMedida (CveUnidadMedida); + + ALTER TABLE dbo.Tra_PagosDetalle + CHECK CONSTRAINT FK_Tra_PagosDetalle_CveUM; +END; +GO + CREATE OR ALTER PROCEDURE dbo.PA_Tra_PagoList @CveTipoTramite int, @IncluirInactivos bit = 1, @@ -491,6 +544,9 @@ BEGIN D.CvePS, PS.Codigo, PS.PS, + D.CveUM, + UM.UnidadMedida, + UM.Abreviatura, D.Cantidad, CONVERT(decimal(18, 2), PS.Precio) AS Precio, CONVERT @@ -504,6 +560,8 @@ BEGIN ON P.CveTramitePago = D.CveTramitePago INNER JOIN dbo.ProductosServicios AS PS ON PS.CvePS = D.CvePS + LEFT JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = D.CveUM WHERE D.CveTramitePago = @CveTramitePago ORDER BY D.CveTramitePagoDetalle; @@ -560,6 +618,9 @@ BEGIN D.CvePS, PS.Codigo, PS.PS, + D.CveUM, + UM.UnidadMedida, + UM.Abreviatura, D.Cantidad, CONVERT(decimal(18, 2), PS.Precio) AS Precio, CONVERT @@ -573,6 +634,8 @@ BEGIN ON P.CveTramitePago = D.CveTramitePago INNER JOIN dbo.ProductosServicios AS PS ON PS.CvePS = D.CvePS + LEFT JOIN dbo.UnidadesMedida AS UM + ON UM.CveUnidadMedida = D.CveUM WHERE D.CveTramitePagoDetalle = @CveTramitePagoDetalle; SET @Return = 1; @@ -598,6 +661,7 @@ CREATE OR ALTER PROCEDURE dbo.PA_Tra_PagoDetalleSave @CveTramitePagoDetalle int = NULL, @CveTramitePago int, @CvePS int, + @CveUM int, @Cantidad decimal(18, 4), @CveUsuarioEjecuta int, @ErrorMostrar varchar(max) OUTPUT, @@ -658,6 +722,19 @@ BEGIN RETURN; END; + IF NOT EXISTS + ( + SELECT 1 + FROM dbo.UnidadesMedida + WHERE CveUnidadMedida = @CveUM + ) + BEGIN + SELECT + @ErrorMostrar = 'Seleccione una unidad de medida válida.', + @ErrorTipo = 2; + RETURN; + END; + IF EXISTS ( SELECT 1 @@ -679,6 +756,7 @@ BEGIN ( CveTramitePago, CvePS, + CveUM, Cantidad, CveUsuario ) @@ -686,6 +764,7 @@ BEGIN ( @CveTramitePago, @CvePS, + @CveUM, @Cantidad, @CveUsuarioEjecuta ); @@ -710,6 +789,7 @@ BEGIN UPDATE dbo.Tra_PagosDetalle SET CvePS = @CvePS, + CveUM = @CveUM, Cantidad = @Cantidad, FechaModificacion = GETDATE(), CveUsuario = @CveUsuarioEjecuta @@ -817,12 +897,18 @@ BEGIN SELECT CvePS, + ProductosServicios.CveUnidadMedida AS CveUnidadMedida, + Unidad.UnidadMedida, + Unidad.Abreviatura, Codigo, PS, CONVERT(decimal(18, 2), Precio) AS Precio, - Estado AS EsActivo + ProductosServicios.Estado AS EsActivo FROM dbo.ProductosServicios - WHERE (@IncluirInactivos = 1 OR Estado = 1) + LEFT JOIN dbo.UnidadesMedida AS Unidad + ON Unidad.CveUnidadMedida = + ProductosServicios.CveUnidadMedida + WHERE (@IncluirInactivos = 1 OR ProductosServicios.Estado = 1) AND ( @Texto IS NULL @@ -879,11 +965,17 @@ BEGIN SELECT CvePS, + ProductosServicios.CveUnidadMedida AS CveUnidadMedida, + Unidad.UnidadMedida, + Unidad.Abreviatura, Codigo, PS, CONVERT(decimal(18, 2), Precio) AS Precio, - Estado AS EsActivo + ProductosServicios.Estado AS EsActivo FROM dbo.ProductosServicios + LEFT JOIN dbo.UnidadesMedida AS Unidad + ON Unidad.CveUnidadMedida = + ProductosServicios.CveUnidadMedida WHERE CvePS = @CvePS; SET @Return = 1; diff --git a/TipoTramiteDetalle_UnidadMedida_20260827.sql b/TipoTramiteDetalle_UnidadMedida_20260827.sql new file mode 100644 index 0000000..0986b3e --- /dev/null +++ b/TipoTramiteDetalle_UnidadMedida_20260827.sql @@ -0,0 +1,151 @@ +SET NOCOUNT ON; +GO + +DECLARE @Procedimientos TABLE +( + Nombre sysname NOT NULL PRIMARY KEY, + EsDetalle bit NOT NULL +); + +INSERT INTO @Procedimientos +( + Nombre, + EsDetalle +) +VALUES + (N'PA_Tra_PagoDetalleList', 1), + (N'PA_Tra_PagoDetalleGet', 1), + (N'PA_Tra_ProductoServicioList', 0), + (N'PA_Tra_ProductoServicioGet', 0); + +DECLARE @Nombre sysname; +DECLARE @EsDetalle bit; +DECLARE @Definicion nvarchar(max); +DECLARE @DefinicionOriginal nvarchar(max); +DECLARE @InicioProcedimiento int; + +DECLARE CursorProcedimientos CURSOR LOCAL FAST_FORWARD FOR +SELECT + Nombre, + EsDetalle +FROM @Procedimientos +ORDER BY Nombre; + +OPEN CursorProcedimientos; + +FETCH NEXT FROM CursorProcedimientos INTO + @Nombre, + @EsDetalle; + +WHILE @@FETCH_STATUS = 0 +BEGIN + SET @Definicion = OBJECT_DEFINITION( + OBJECT_ID(N'dbo.' + @Nombre)); + + IF @Definicion IS NULL + BEGIN + THROW 50000, + 'No existe uno de los procedimientos requeridos para agregar la unidad de medida.', + 1; + END; + + SET @Definicion = REPLACE( + @Definicion, + CHAR(13) + CHAR(10), + CHAR(10)); + SET @DefinicionOriginal = @Definicion; + + IF @EsDetalle = 1 + BEGIN + IF @Definicion NOT LIKE N'%PS.CveUnidadMedida,%' + BEGIN + SET @Definicion = REPLACE( + @Definicion, + N' PS.PS,' + CHAR(10) + + N' D.Cantidad,', + N' PS.PS,' + CHAR(10) + + N' PS.CveUnidadMedida,' + CHAR(10) + + N' UM.UnidadMedida,' + CHAR(10) + + N' UM.Abreviatura,' + CHAR(10) + + N' D.Cantidad,'); + + SET @Definicion = REPLACE( + @Definicion, + N' INNER JOIN dbo.ProductosServicios AS PS' + CHAR(10) + + N' ON PS.CvePS = D.CvePS' + CHAR(10) + + N' WHERE ', + N' INNER JOIN dbo.ProductosServicios AS PS' + CHAR(10) + + N' ON PS.CvePS = D.CvePS' + CHAR(10) + + N' LEFT JOIN dbo.UnidadesMedida AS UM' + CHAR(10) + + N' ON UM.CveUnidadMedida = PS.CveUnidadMedida' + CHAR(10) + + N' WHERE '); + END; + END + ELSE + BEGIN + IF @Definicion NOT LIKE N'%Unidad.UnidadMedida,%' + BEGIN + SET @Definicion = REPLACE( + @Definicion, + N' CvePS,' + CHAR(10) + + N' Codigo,' + CHAR(10) + + N' PS,', + N' CvePS,' + CHAR(10) + + N' ProductosServicios.CveUnidadMedida AS CveUnidadMedida,' + CHAR(10) + + N' Unidad.UnidadMedida,' + CHAR(10) + + N' Unidad.Abreviatura,' + CHAR(10) + + N' Codigo,' + CHAR(10) + + N' PS,'); + + SET @Definicion = REPLACE( + @Definicion, + N' Estado AS EsActivo' + CHAR(10) + + N' FROM dbo.ProductosServicios', + N' ProductosServicios.Estado AS EsActivo' + CHAR(10) + + N' FROM dbo.ProductosServicios' + CHAR(10) + + N' LEFT JOIN dbo.UnidadesMedida AS Unidad' + CHAR(10) + + N' ON Unidad.CveUnidadMedida =' + CHAR(10) + + N' ProductosServicios.CveUnidadMedida'); + + SET @Definicion = REPLACE( + @Definicion, + N'(@IncluirInactivos = 1 OR Estado = 1)', + N'(@IncluirInactivos = 1 OR ProductosServicios.Estado = 1)'); + END; + END; + + IF @Definicion = @DefinicionOriginal + AND @Definicion NOT LIKE N'%UnidadMedida,%' + BEGIN + THROW 50001, + 'La definición instalada de un procedimiento no tiene la estructura esperada.', + 1; + END; + + SET @InicioProcedimiento = CHARINDEX( + N'PROCEDURE', + UPPER(@Definicion)); + + IF @InicioProcedimiento = 0 + BEGIN + THROW 50002, + 'No fue posible localizar la declaración del procedimiento.', + 1; + END; + + SET @Definicion = STUFF( + @Definicion, + 1, + @InicioProcedimiento - 1, + N'CREATE OR ALTER '); + + EXEC sys.sp_executesql @Definicion; + + FETCH NEXT FROM CursorProcedimientos INTO + @Nombre, + @EsDetalle; +END; + +CLOSE CursorProcedimientos; +DEALLOCATE CursorProcedimientos; +GO