# Unified Restaurant API

Unified Restaurant es un servicio web que permitirá a sus usuarios operar y
administrar sus restaurantes.

[[_TOC_]]

# Documentación

Esta API tendrá los siguientes endpoints

| Funcionalidad   | Endpoint                |
| --------------- | ----------------------- |
| Usuario         | `/api/v1/users/`        |
| Restaurante     | `/api/v1/restaurantes/` |
| Bodega          | `/api/v1/bodega/`       |
| Venta           | `/api/v1/venta/`        |
| Administración  | `/api/v1/admin/`        |

## Autorización

La mayoría de las rutas de esta API se encuentran protegidas utilizando Auth0
como gestor de identidad, por lo que para recibir autorización, se debe seguir
alguna de las guías de Auth0 que explican como obtener un token de autorización.

Una vez obtenido el token, se debe incluir en el header de todas las llamadas un
Bearer Token de la forma `Authorization: Bearer {token}` donde `{token}` es el
obtenido desde Auth0.

## Errores

En caso que se presente algún error la API siempre responderá con un mensaje de
la siguiente forma

```json
{
    "error": "error_code",
    "message": "Mensaje explicativo del error en español"
}
```

Ahora, si el error lo presento Auth0, el campo de `error` siempre empezara el
código con `auth0_`, es util saber que el error es enviado desde Auth0 porque
sus mensajes de error están en ingles y si se deben mostrar al usuario se
deberán traducir manualmente

## Usuario

La API de usuario permite manipular a los usuarios de la aplicación, las
siguientes acciones están disponibles

### Obtener todos

Para obtener la lista completa de usuarios se debe enviar un `GET` a la
ruta `/api/v1/user`, estos datos serán paginados, por lo que opcionalmente se
recibe el parámetro `page` para definir la página a obtener y el
parámetro `per_page` para definir cuantos elementos obtener por página.

La respuesta de la API tiene la siguiente forma

```json
{
    "pagination": {
        "per_page": 15,
        "from": 1,
        "to": 2,
        "total": 2,
        "current_page": 1,
        "last_page": 1,
        "links": {
            "first": "http://localhost:8080/api/v1/users?page=1&per_page=15",
            "prev": null,
            "current": "http://localhost:8080/api/v1/users?page=1&per_page=15",
            "next": null,
            "last": "http://localhost:8080/api/v1/users?page=1&per_page=15"
        }
    },
    "data": [
        // listado de usuarios
    ]
}
```

La respuesta contendrá una serie de datos indicando el estado de la paginación,
además de una serie de links indicando a donde llamar para obtener la primera,
anterior, actual, siguiente y última página.

Estos links pueden ser null en caso que no sea posible utilizarlo, por ejemplo
si hay 3 páginas y la página actual es la 3, el link `next` será nulo, ya que no
hay una cuarta página.

### Obtener Usuario

Para obtener un usuario se debe hacer un `GET` a la ruta `/api/v1/users/{id}`
donde `{id}` es el ID del usuario a buscar, este ID puede ser el UUID del
usuario o el ID entregado por Auth0, esto puede ser util si el frontend tiene
solamente acceso al ID entregado por Auth0.

Si el ID de usuario existe, la siguiente sera la respuesta de la API

```json
{
    "id": "4014fd8d-26fd-4ce8-bdaa-99b8a325ee92",
    "auth0_id": "123456",
    "nombre": "Mesero",
    "created_at": "2021-04-26T16:37:59.998642Z",
    "updated_at": "2021-04-26T16:37:59.998642Z",
    "deleted_at": null,
    "roles": [
        "mesero"
    ],
    "restaurantes": [
        {
            "id": "63f62e17-e011-4f6f-8c15-5eb65a5014be",
            "nombre": "Todo Rico Restaurant",
            "created_at": "2021-04-26T16:37:59.181869Z",
            "updated_at": "2021-04-26T16:37:59.181869Z",
            "deleted_at": null,
            "pivot": {
                "usuario_id": "4014fd8d-26fd-4ce8-bdaa-99b8a325ee92",
                "restaurante_id": "63f62e17-e011-4f6f-8c15-5eb65a5014be"
            }
        }
    ]
}
```

En caso que el usuario no exista se retornara el siguiente mensaje de error

```json
{
    "error": "user_not_found",
    "message": "El usuario con id o auth0_id {id} no existe"
}
```

### Crear

Para crear un nuevo usuario se debe enviar un `POST` a la ruta `/api/v1/user`
con un payload como el del siguiente ejemplo

```json
{
    "nombre": "John Doe",
    "email": "john@doe.com",
    "username": "johndoe",
    "password": "superPasswordWith123NumbersAnd----Symbols",
    "roles": [
        "admin",
        "recaudador",
        "mesero",
        "productor"
    ],
    "restaurant": "63f62e17-e011-4f6f-8c15-5eb65a5014be"
}
```

Esto creará el usuario John Doe localmente y en auth0 por lo cual él podrá
entrar con el email y contraseña indicados

Una vez creado, la API responderá con el usuario creado, no contendrá `username`
,
`email` ni `password` ya que estos valores los utiliza Auth0 y no son relevantes
para el modelo.

```json
{
    "id": "6430c9ac-6bce-4e23-8421-28bce08101d4",
    "auth0_id": "auth0|608ba7866c9b520074d687d9",
    "nombre": "John Doe",
    "roles": [
        "admin",
        "recaudador",
        "mesero",
        "productor"
    ],
    "updated_at": "2021-04-30T06:45:22.000000Z",
    "created_at": "2021-04-30T06:45:22.000000Z",
    "restaurantes": [
        {
            "id": "63f62e17-e011-4f6f-8c15-5eb65a5014be",
            "nombre": "Todo Rico Restaurant",
            "created_at": "2021-04-26T16:37:59.181869Z",
            "updated_at": "2021-04-26T16:37:59.181869Z",
            "deleted_at": null,
            "pivot": {
                "usuario_id": "4014fd8d-26fd-4ce8-bdaa-99b8a325ee92",
                "restaurante_id": "63f62e17-e011-4f6f-8c15-5eb65a5014be"
            }
        }
    ]
}
```

### Actualizar

Para actualizar un usuario se debe enviar un `PUT` a la
ruta `/api/v1/users/{id}` donde `{id}` es el ID del usuario a buscar, este ID
puede ser el UUID del usuario o el ID entregado por Auth0, y en el cuerpo se
debe indicar los campos a actualizar.

Por ejemplo para actualizar el nombre del usuario se envía el siguiente payload

```json
{
    "nombre": "Jhon 2"
}
```

O si se quieren cambiar sus roles, se envía el siguiente payload

```json
{
    "roles": [
        "admin",
        "recaudador"
    ]
}
```

Una vez se modifiquen los datos del usuario, la API responderá con el usuario
actualizado

```json
{
    "id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
    "auth0_id": "auth0|608ca16fcfc3df0068fea6a4",
    "nombre": "Jhon 2",
    "created_at": "2021-04-30T18:31:44.000000Z",
    "updated_at": "2021-05-01T00:31:52.000000Z",
    "deleted_at": null,
    "roles": [
        "admin",
        "recaudador"
    ],
    "restaurantes": [
        {
            "id": "63f62e17-e011-4f6f-8c15-5eb65a5014be",
            "nombre": "Todo Rico Restaurant",
            "created_at": "2021-04-26T16:37:59.181869Z",
            "updated_at": "2021-04-26T16:37:59.181869Z",
            "deleted_at": null,
            "pivot": {
                "usuario_id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
                "restaurante_id": "63f62e17-e011-4f6f-8c15-5eb65a5014be"
            }
        }
    ]
}
```

Ahora existe la posibilidad que se quieran actualizar multiples casos a la vez,
si esto es asi, hay que tomar en cuenta las limitaciones impuestas por Auth0,
donde ciertos campos no se pueden cambiar al mismo tiempo, para más detalles,
ver
la [documentación de Auth0](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id)

### Eliminar

Para eliminar a un usuario hay que enviar un `DELETE` a la
ruta `/api/v1/user/{id}` donde `{id}` es el ID del usuario a buscar, este ID
puede ser el UUID del usuario o el ID entregado por Auth0.

Los usuarios eliminados podrán ser recuperados localmente, pero en auth0 serán
eliminados permanentemente y su asociación con restaurantes se perderá.

La respuesta de la API al eliminar será un código `204` sin cuerpo, pero ante
cualquier error, principalmente proviniendo desde Auth0, se utilizará el cuerpo
de error definido al inicio.

### Agregar a un restaurant

El usuario puede ser agregado a distintos restaurantes, para esto se envía
un `PUT` a la ruta `/api/v1/user/{id}/restaurantes/{restaurante_id}`
donde `{id}` es el ID del usuario a buscar, este ID puede ser el UUID del
usuario o el ID entregado por Auth0, y `{restaurante_id}` es el ID del
restaurante al que se va a agregar al usuario.

La API responderá con el modelo del usuario actualizado, como en el siguiente
ejemplo, donde se agregó al restaurante `4e47a419-9398-47ff-82e9-b78851e71226`

```json
{
    "id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
    "auth0_id": "auth0|608ca16fcfc3df0068fea6a4",
    "nombre": "Jhon 2",
    "created_at": "2021-04-30T18:31:44.000000Z",
    "updated_at": "2021-04-30T18:31:52.000000Z",
    "deleted_at": null,
    "roles": [
        "admin",
        "recaudador"
    ],
    "restaurantes": [
        {
            "id": "63f62e17-e011-4f6f-8c15-5eb65a5014be",
            "nombre": "Todo Rico Restaurant",
            "created_at": "2021-04-26T16:37:59.181869Z",
            "updated_at": "2021-04-26T16:37:59.181869Z",
            "deleted_at": null,
            "pivot": {
                "usuario_id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
                "restaurante_id": "63f62e17-e011-4f6f-8c15-5eb65a5014be"
            }
        },
        {
            "id": "4e47a419-9398-47ff-82e9-b78851e71226",
            "nombre": "Otro Restaurant",
            "created_at": "2021-05-01T02:40:10.047257Z",
            "updated_at": "2021-05-01T02:40:10.047257Z",
            "deleted_at": null,
            "pivot": {
                "usuario_id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
                "restaurante_id": "4e47a419-9398-47ff-82e9-b78851e71226"
            }
        }
    ]
}
```

### Eliminar de un restaurant

Si es necesario eliminar a un usuario de un restaurant, se debe enviar
un `DELETE` a la ruta `/api/v1/user/{id}/restaurantes/{restaurante_id}`
donde `{id}` es el ID del usuario a buscar, este ID puede ser el UUID del
usuario o el ID entregado por Auth0, y `{restaurante_id}` es el ID del
restaurante al que se va a agregar al usuario.

La API responderá con el modelo del usuario actualizado, como en el siguiente
ejemplo, donde se eliminó del restaurante `4e47a419-9398-47ff-82e9-b78851e71226`

```json
{
    "id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
    "auth0_id": "auth0|608ca16fcfc3df0068fea6a4",
    "nombre": "Jhon 2",
    "created_at": "2021-04-30T18:31:44.000000Z",
    "updated_at": "2021-04-30T18:31:52.000000Z",
    "deleted_at": null,
    "roles": [
        "admin",
        "recaudador"
    ],
    "restaurantes": [
        {
            "id": "63f62e17-e011-4f6f-8c15-5eb65a5014be",
            "nombre": "Todo Rico Restaurant",
            "created_at": "2021-04-26T16:37:59.181869Z",
            "updated_at": "2021-04-26T16:37:59.181869Z",
            "deleted_at": null,
            "pivot": {
                "usuario_id": "340c8e54-9a15-4bd2-9b59-108f267d5872",
                "restaurante_id": "63f62e17-e011-4f6f-8c15-5eb65a5014be"
            }
        }
    ]
}
```

## Restaurantes

La API de restaurantes permite manipular los restaurantes de la aplicacion,
donde las siguientes acciones estan disponibles

### Obtener todos

Para obtener la lista completa de restaurantes se debe enviar un `GET` a la
ruta `/api/v1/restaurantes`, estos datos seran paginados, por lo que
opcionalmente se recibe el parámetro `page` para definir la página a obtener y
el parámetro `per_page` para definir cuantos elementos obtener por página.

La respuesta de la API tiene la siguiente forma

```json
{
    "pagination": {
        "per_page": 15,
        "from": 1,
        "to": 2,
        "total": 2,
        "current_page": 1,
        "last_page": 1,
        "links": {
            "first": "http:\/\/localhost:8080\/api\/v1\/restaurantes?page=1&per_page=15",
            "prev": null,
            "current": "http:\/\/localhost:8080\/api\/v1\/restaurantes?page=1&per_page=15",
            "next": null,
            "last": "http:\/\/localhost:8080\/api\/v1\/restaurantes?page=1&per_page=15"
        }
    },
    "data": [
        {
            "id": "eb41e807-24ef-4620-aa5e-3aa9cf920ddf",
            "nombre": "Todo Rico Restaurant",
            "created_at": "2021-05-01T04:46:11.593213Z",
            "updated_at": "2021-05-01T04:46:11.593213Z",
            "deleted_at": null
        },
        {
            "id": "e7d1ce9c-fed1-4a01-ab91-0069d92eeea3",
            "nombre": "Confiteria Central",
            "created_at": "2021-05-02T16:40:56.000000Z",
            "updated_at": "2021-05-02T16:52:26.000000Z",
            "deleted_at": null
        }
    ]
}
```

La respuesta contendrá una serie de datos indicando el estado de la paginación,
además de una serie de links indicando a donde llamar para obtener la primera,
anterior, actual, siguiente y última página.

Estos links pueden ser null en caso que no sea posible utilizarlo, por ejemplo
si hay 3 páginas y la página actual es la 3, el link `next` será nulo, ya que no
hay una cuarta página.

### Obtener Restaurante

Para obtener un restaurante se debe hacer un `GET` a la
ruta `/api/v1/restaurantes/{id}`
donde `{id}` es el ID del restaurante a buscar.

Si el ID de restaurante existe, la siguiente sera la respuesta de la API

```json
{
    "id": "eb41e807-24ef-4620-aa5e-3aa9cf920ddf",
    "nombre": "Todo Rico Restaurant",
    "created_at": "2021-05-01T04:46:11.593213Z",
    "updated_at": "2021-05-01T04:46:11.593213Z",
    "deleted_at": null
}
```

En caso que el ID no exista, la siguiente sera la respuesta de error

```json
{
    "error": "restaurant_not_found",
    "message": "El restaurant con id eb41e807-24ef-4620-aa5e-3aa9cf920dde no existe"
}
```

### Crear

Para crear un nuevo restaurant se debe enviar un `POST` a la
ruta `/api/v1/restaurantes` con un payload como el del siguiente ejemplo

```json
{
    "nombre": "Unified Restaurant"
}
```

Esto creará un restaurante con nombre "Unified Restaurant" y la API responderá
con el usuario creado.

```json
{
    "id": "eb41e807-24ef-4620-aa5e-3aa9cf920ddf",
    "nombre": "Todo Rico Restaurant",
    "created_at": "2021-05-01T04:46:11.593213Z",
    "updated_at": "2021-05-01T04:46:11.593213Z",
    "deleted_at": null
}
```

### Actualizar

Para actualizar un restaurant se debe enviar un `PUT` a la
ruta `/api/v1/restaurantes/{id}` donde `{id}` es el id del restaurante a editar

El siguiente payload va a cambiar el nombre del restaurante

```json
{
    "nombre": "Unified Restaurant 2: Electric Boongaloo"
}
```

Una vez modificado el dato, la API responderá con el restaurant actualizado

```json
{
    "id": "6a2855cc-cc04-4bc1-ac97-e8f632918303",
    "nombre": "Unified Restaurant 2: Electric Boongaloo",
    "created_at": "2021-05-02T17:13:01.000000Z",
    "updated_at": "2021-05-02T23:13:10.000000Z",
    "deleted_at": null
}
```

### Eliminar

Para eliminar un restaurant se envía un `DELETE` a la
ruta `/api/v1/restaurantes/{id}` donde `{id}` es el ID del restaurante a
eliminar.

Al eliminar un restaurant, solo se marca como eliminado y se mostrara en ninguna
otra llamada, además de esto todas sus asociaciones son dejadas tal cual.
