# Guía de Estilo para la API
## Introducción
Esta guía de estilo establece las normas para el desarrollo y mantenimiento de la API. Está diseñada para asegurar la coherencia, optimización y eficiencia en las interfaces de programación de aplicaciones (APIs) del grupo.
## Nomenclatura y Convenciones de Nombrado
Se presentan algunas directrices generales y mejores prácticas para el nombrado en la API:
### Generalidades
- Todos los nombres deben estar en inglés.
- Evitar el uso de abreviaturas, a menos que sean ampliamente reconocidas.
### Endpoints
- Usar sustantivos en lugar de verbos. Por ejemplo, `/user` para un recurso que maneja usuarios.
- Usar sustantivos en singular para representar recursos
- `/user` (en lugar de `/users`)
- `/product` (en lugar de `/products`)
- Para operaciones específicas sobre un recurso, se recomienda el uso de verbos. Por ejemplo, `/user/{id}/activate` para una operación que cambie el estado de un usuario a activo.
### Parámetros y Cuerpos de Solicitudes
- Los nombres de los parámetros deben ser descriptivos y seguir el estilo camelCase, por ejemplo, `startDate` o `numberOfItems`.
- Evitar nombres genéricos y optar por descripciones específicas, como `productId` en lugar de simplemente `id`.
- En el cuerpo de una solicitud, especialmente en métodos POST o PUT, incluir sólo la información necesaria para la operación. Debe nombrarse de manera que describan claramente su propósito, sin abreviaturas ambiguas.
## Métodos HTTP
La API sigue los principios REST, utilizando los métodos HTTP estándar para realizar operaciones en los recursos. A continuación, se especifica cuándo utilizar cada método:
### GET
- Utilizado para recuperar datos.
- No debe alterar ningún estado en el servidor.
- Debe ser seguro y consistente en sus resultados.
- Los parámetros deben enviarse en la URL (query strings).
### POST
- Utilizado para enviar datos al servidor y crear un nuevo recurso.
- Los datos deben incluirse en el cuerpo de la solicitud (request body).
### PUT
- Utilizado para actualizar un recurso en su totalidad.
- El cliente debe enviar toda la entidad, no solo los cambios.
- Si se envía la misma solicitud varias veces, el resultado debe ser el mismo.
### DELETE
- Utilizado para eliminar recursos.
### GET para Búsqueda Avanzada o Listados
Aparte de las operaciones GET estándar, utilizamos solicitudes GET más complejas para funcionalidades como búsquedas, listados con paginación, y filtrado. Estas solicitudes pueden incluir algunos parámetros obligatorios en la cadena de consulta (query strings).
#### Parámetros de Query
- `limit` (integer): Define el número máximo de elementos a retornar en una sola respuesta.
- Ejemplo: `100`.
- Para devolver todos los resultados, usar `-1`.
- `start` (integer): Indica el índice inicial de los elementos, usado para la paginación.
- Ejemplo: `0`.
- `sort` (string): Establece el criterio de ordenación de los elementos. Se utiliza el formato `campo:dirección`, donde la dirección puede ser `asc` (ascendente) o `desc` (descendente). Si no se especifica dirección, se asume ascendente.
- Ejemplos:
- `sort: expectedDateEnd` (devuelve ascendente)
- `sort: expectedDateEnd:desc` (devuelve descendente)
- `searchText` (string, opcional): Permite filtrar los resultados por búsqueda de texto.
- También se pueden aplicar filtros adicionales con una estructura específica, siempre utilizando camelCase para los nombres y empezando por "filter". Por ejemplo:
- `filterByNonActivePreventionService` (boolean)
- `filterByRealizationDepartments` (string)
- Para incluir información adicional en los resultados, utilizamos parámetros que comienzan con `include` utilizando camelCase, seguidos del nombre del campo relevante, utilizando un valor booleano para indicar si queremos la inclusión.
- Ejemplo: `includeResponsibleDepartments` (boolean)
## Estructura de Respuestas
Independientemente del método HTTP utilizado, las respuestas deben ser consistentes. Los clientes deben saber qué esperar de cualquier respuesta proporcionada por la API.
### Respuestas GET
- Deben devolver `200 OK` si la solicitud fue exitosa.
- Las respuestas deben incluir siempre los campos `code` y `data`. El campo `code` es un identificador numérico del resultado de la operación. Un `code` igual a 0 indica que la operación fue exitosa. Mientras tanto, `data` contiene los datos solicitados, que pueden variar en estructura y contenido dependiendo del recurso accedido.
#### Ejemplo de respuesta:
```
{
"code": 0, // Un 'code' de 0 indica una operación exitosa.
"data": [
{
"typeId": 1,
"order": 1,
"name": "Plan de acción",
"type": "PAC"
}
]
}
```
#### Ejemplo de respuesta para Búsqueda Avanzada o Listados
Las respuestas de estas solicitudes GET seguirán una estructura similar con un data enriquecido. Aquí un ejemplo y detalles de la estructura de respuesta:
```
{
"code": 0,
"data": {
"total": 45, // Número total de elementos que coinciden con los criterios de búsqueda.
"limit": 20, // Número de elementos solicitados en la consulta (límite).
"start": 5, // Índice inicial del primer elemento de esta página.
"items": [] // Array de elementos, que pueden ser de cualquier estructura, dependiendo de la solicitud.
}
}
```
### Respuestas POST
- Deben devolver `200 OK` si el recurso se ha creado satisfactoriamente.
- La respuesta debe seguir una estructura coherente, que incluya un 'code' y un objeto 'data'.
- Un 'code' de `0` indica una operación exitosa.
#### Estructura de Respuesta Estándar
La estructura básica de una respuesta exitosa a una solicitud POST debe ser la siguiente:
```
{
"code": 0,
"data": { }
}
```
Esta estructura indica que la solicitud fue exitosa.
#### Inclusión del ID del Recurso Creado
En ciertas ocasiones, es particularmente útil para el cliente recibir el ID del recurso que se acaba de crear:
```
{
"code": 0,
"data": {
"id": 23
}
}
```
### Respuestas PUT
- Si el recurso se actualiza satisfactoriamente, retornar `200 OK`.
- Un 'code' de `0` indica una operación exitosa.
```
{
"code": 0
}
```
### Respuestas DELETE
- Si el recurso se actualiza satisfactoriamente, retornar `200 OK`.
- Un 'code' de `0` indica una operación exitosa.
```
{
"code": 0
}
```
### Respuestas DELETE (Bulk - Eliminación en masa)
- Si el recurso se actualiza satisfactoriamente, retornar `200 OK`.
- Un 'code' de `0` indica una operación exitosa.
- Además de 'code', la respuesta debe proporcionar detalles adicionales en un objeto 'data'. Esto incluye una lista de los IDs que se vieron afectados (eliminados) y el total de recursos afectados.
Estructura de respuesta esperada:
```
{
"code": 0,
"data": {
"affectedIds": [
// lista de IDs
],
"total": // número total de registros afectados
}
}
```
Ejemplo de una respuesta exitosa:
```
{
"code": 0,
"data": {
"affectedIds": [
1,
2,
3,
4
],
"total": 4
}
}
```
## Manejo de Errores
- Utilizar códigos de estado HTTP para indicar la naturaleza del error.
- Incluir un cuerpo de respuesta que proporcione detalles específicos y pueda ser fácilmente interpretado por el cliente.
Posibles respuestas de error:
1. **Sin autorización:** Cuando una solicitud carece de las credenciales necesarias o las credenciales son incorrectas.
```
{
"code": 401,
"message": "Unauthorized"
}
```
2. **Recurso no encontrado:** Utilizado cuando el recurso solicitado no existe.
```
{
"code": 404,
"message": "Resource not found"
}
```
3. **Errores específicos del endpoint:** Para situaciones que requieren un mensaje de error más específico, utilizamos un código único por endpoint. Este código es especialmente útil para el manejo de errores en el front-end, incluyendo situaciones como la traducción de mensajes. El código de estado HTTP en el header de la respuesta en estos casos es 400.
Ejemplo de respuesta:
```
{
"code": 39024, // Este es un código de error único para un caso específico en este endpoint.
"message": "Error get company report logo"
}
```
## Versionado
La API debe versionarse. Por ejemplo:
`https://api.company.com/v1/resource`
## Seguridad
- Todos los puntos de acceso deben estar asegurados con protocolos de seguridad estándar (por ejemplo, HTTPS/SSL).
- Implementar autenticación y autorización adecuadas (por ejemplo, token de acceso).
## Filtrado
Cuando la API permite recuperar colecciones de recursos, es fundamental ofrecer mecanismos para filtrar estos datos y permitir que los consumidores de la API obtengan solo los recursos que necesitan. Para lograr una experiencia coherente y fácil de entender, seguimos las siguientes convenciones para pasar información de filtrado a través de query strings.
### Filtrado por Fechas
Para los filtros que involucran fechas, ya sea un rango de fechas o una sola fecha, adoptamos el siguiente estilo:
- Las fechas deben estar en formato `YYYY-MM-DD` (por ejemplo, `2023-10-17`).
- Para especificar un rango de fechas, separamos las fechas de inicio y fin con un carácter de barra vertical (`|`), sin espacios. Esto se utiliza tanto para rangos cerrados como para una fecha única.
Ejemplo:
`filterByEndExpectedDateRange=2023-10-17|2023-10-18`
Este parámetro indicaría un filtro que busca recursos con una fecha de finalización esperada que caiga en el rango específico del `17 de octubre de 2023` al `18 de octubre de 2023`
### Filtrado por Valores Múltiples
En casos donde se filtra por múltiples valores, como identificadores, seguimos estas pautas:
- Los valores se separan con una barra vertical (`|`), sin espacios.
- Si el conjunto de valores comienza con un signo de exclamación (`!`), esto indica una operación de filtrado "NOT IN", es decir, excluir todos los recursos que tengan un valor dentro de este conjunto.
Ejemplo:
`filterByResponsibleUserIds=1|2`
El ejemplo anterior filtraría los recursos buscando aquellos donde el usuario responsable tenga identificadores `1` o `2`.
En el caso de querer excluir valores específicos, se usaría:
`filterByResponsibleUserIds=!1|2`
Esto devolvería los recursos que no estén asignados a los usuarios con identificadores `1` o `2`.
### Notas Adicionales
- Todos los parámetros de filtrado deben seguir la convención camelCase en sus nombres.
## Conclusión
Este documento representa nuestras normas internas para garantizar una API consistente, eficiente y segura.