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
+ No cuenta con acceso a esta página desde el menú asignado a su usuario. +