Files
Plataforma-de-desarrolladores/AGENTS_STORED_PROCEDURES.md
Jorge Luis caudillo esparza 6685ef63fb Initial commit
2026-07-14 11:15:57 -07:00

124 lines
5.0 KiB
Markdown

# Reglas obligatorias de procedimientos almacenados
Estas reglas complementan `AGENTS.md` y son obligatorias para toda consulta nueva o modificada en la aplicación.
## Acceso a datos
- Todas las lecturas y escrituras de la aplicación deben usar procedimientos almacenados.
- No escribir `SELECT`, `INSERT`, `UPDATE`, `DELETE` ni `MERGE` directamente en C# dentro de repositorios, servicios, páginas, controles o la master page.
- Los repositorios deben usar `CommandType.StoredProcedure`.
- Todos los valores proporcionados por la aplicación deben enviarse como parámetros.
- Nunca concatenar entrada del usuario en SQL.
## Nombres
- Usar el formato `PA_<Tipo>_<Entidad><Accion>`.
- `PA` significa procedimiento almacenado.
- `<Tipo>` identifica el grupo funcional: `Sis`, `Tra`, `Vta`, `Conta`, `Clientes`, `Fraccionamientos`, etcétera.
- `<Entidad>` identifica el objeto y `<Accion>` describe claramente la operación; por ejemplo `Add`, `Update`, `List`, `Activate`, `Deactivate` o `Delete`.
- Ejemplos: `PA_Sis_UsuarioAdd`, `PA_Sis_UsuarioUpdate`, `PA_Sis_UsuarioList`, `PA_Sis_UsuarioActivate`, `PA_Sis_UsuarioDeactivate` y `PA_Sis_UsuarioDelete`.
## Parámetros y resultado obligatorios
Todos los procedimientos deben declarar:
```sql
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
```
- `@CveUsuarioEjecuta` identifica al usuario autenticado que ejecuta la operación.
- Al inicio, establecer `@ErrorMostrar = NULL`, `@ErrorTipo = 0` y `@Return = 0`.
- Establecer `@Return = 1` únicamente cuando la operación termine correctamente.
- `@ErrorTipo = 0`: sin error ni advertencia.
- `@ErrorTipo = 1`: error.
- `@ErrorTipo = 2`: advertencia.
- `@ErrorMostrar` contiene el mensaje amigable en español que puede mostrarse al usuario.
- No devolver contraseñas, hashes, cadenas de conexión, SQL, stack traces ni detalles internos mediante `@ErrorMostrar`.
- Los procedimientos de consulta pueden devolver un result set, pero también deben poblar los parámetros comunes.
- El repositorio debe convertir los parámetros de salida en un modelo de resultado como `DbResult<T>`.
## Control de errores
- Usar `SET NOCOUNT ON` y `TRY/CATCH` en todos los procedimientos.
- Usar `SET XACT_ABORT ON` cuando exista una mutación o transacción.
- Iniciar la transacción dentro de `TRY`, confirmar sólo después del éxito y ejecutar rollback en `CATCH` cuando `XACT_STATE() <> 0`.
- Una validación fallida debe establecer los parámetros de salida y ejecutar `RETURN`; no debe continuar la mutación.
- Para validar existencia, usar normalmente `EXISTS` en lugar de `COUNT(*)`.
- En `CATCH`, generar un mensaje técnico separado con `ERROR_NUMBER()`, `ERROR_PROCEDURE()`, `ERROR_LINE()` y `ERROR_MESSAGE()` para el log.
- El mensaje técnico puede notificarse con severidad informativa para que el ejecutor lo registre, pero nunca debe mostrarse directamente al usuario.
## Borrado lógico
- Está prohibido usar `DELETE` físico en procedimientos CRUD normales.
- Para borrar: `Borrado = 1` y `FechaBorrado = SYSDATETIME()`.
- Para restaurar: `Borrado = 0` y `FechaBorrado = NULL`.
- Las consultas normales deben filtrar `Borrado = 0` en cada tabla participante, excepto cuando el caso de uso solicite expresamente registros borrados.
- La eliminación permanente sólo puede realizarse mediante el procedimiento controlado de retención y limpieza.
- Ninguna página ASPX puede llamar directamente a la limpieza física.
## Plantilla requerida
```sql
CREATE OR ALTER PROCEDURE [dbo].[PA_Sis_RolAdd]
@Rol varchar(50),
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
IF EXISTS
(
SELECT 1
FROM dbo.Sis_Roles
WHERE NombreRol = @Rol
AND Borrado = 0
)
BEGIN
SET @ErrorMostrar = CONCAT('El rol ''', @Rol, ''' ya se encuentra registrado.');
SET @ErrorTipo = 2;
RETURN;
END;
INSERT INTO dbo.Sis_Roles
(NombreRol, Activo, FechaCreacion)
VALUES
(@Rol, 1, SYSDATETIME());
SET @Return = 1;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
SET @ErrorMostrar = 'Ocurrió un error al agregar el rol; 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_Sis_RolAdd'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
```
Cuando el procedimiento use una transacción, debe incluir `BEGIN TRANSACTION` dentro de `TRY` y `COMMIT TRANSACTION` antes de establecer `@Return = 1`.