---
# System prepended metadata

title: desafio-sse

---

# desafio-sse
Este repositório contém a solução para o desafio da Kenoby.

## TOC

- [Instalação](#Instalação)
- [Configuração](#Configuração)

# Instalação

Requisitos:

* [NodeJS](https://nodejs.org/en/)
* [Yarn](https://yarnpkg.com/en/)
* [Docker](https://docs.docker.com/compose/install/)

O Yarn foi escolhido por conta do avançado sistema de cache, entratanto, pode ser utilizado com o npm padrão.

``` bash
yarn
```
Após a instação das dependências, deve-se executar o comando para subir a infraestrutura da API (Postgres e Elastic Search).

No diretório raiz do projeto (Para o Elastic Search)

```bash
sudo docker-composer up
```

Dentro do diretório `./docker/sql` (Para o Postgres)

``` bash
sudo docker-composer up
```

Quando a infraestrutura já estiver operacional, execute as migrations

``` bash
yarn sequelize db:migrate
```

**OBS: Se estiver utilizando o banco Postgres é importante definir a variável de ambiente TEST_RUN_MIGRATIONS_AND_SEEDERS igual a false no arquivo .env.**

Para rodar o servidor em ambiente de produção

``` bash
yarn start
```

Executar o comando para rodar o servidor em ambiente de desenvolvimento.

``` bash
yarn dev
```

Executar o comando para rodar os testes de unidade e integração.

``` bash
yarn test
```

## Uso

.desafio-sse/

├─ \_\_tests\_\_

├─ data

├─ docker

├─ src

├─── app

├─── config

├─── database

├─── errors

├─── helpers

├─── routes

└─── services

A seguinte estrutura é descrita:
* \_\_tests\_\_ diretório onde ficam os testes unitários e de integrações.
* data/ diretório que contém seeders para população da base de dados.
 * docker/ diretório que contém configurações e scripts para inicializar containers do Docker.
* src/ diretório que contém todo o código fonte da aplicação (Podendo ser utilizado pelo Webpack para gerar o `dist`.
* app/ diretório que contém a regra de negócio da API, como controllers, models e middlewares.
* config/ arquivos em JS que fazem o setup de dependências chaves para o correto funcionamento da aplicação.
* database/ migrations, seeders e banco de dados local.
* errors/ arquivos em JS que representam exceções da aplicação.
* helpers/ arquivos em JS que contém funções auxiliares para várias funcionalidades.
* routes/ arquivos em JS para realizar o mapeamento das rotas.
* services/ abstrações de integrações com serviços externos como por exemplo: Elastic Search.

# Configuração

Realizar cópias do .env.example.

``` bash
cp .env.example .env
cp .env.example .env.test
```

## Variáveis de ambiente


| Variável   |      Descrição      |
|:----------:|:-------------:|
| APP_ENV |  Ambiente da aplicação, podendo ser *development*, *testing*, *staging* ou *production*. |
| APP_SENTRY_DSN |    Callback do Sentry para o envio de exceções/logs. |
| APP_CANDIDATURES_BATCH_MAX_SIZE | Tamanho máximo de processamento de candidaturas por requisição. |
| SERVER_PROTOCOL | Protocolo utilizado pelo servidor, podendo ser http ou https. |
| SERVER_HOST | Endereço do servidor. |
| SERVER_PORT | Porta do servidor. |
| DB_USERNAME | Usuário do banco de dados. |
| DB_PASSWORD | Senha do banco de dados. |
| DB_DATABASE | Nome do banco de dados. |
| DB_HOST | Endereço do banco de dados. |
| DB_DIALECT | Tipo de banco de dados que será utilizado pelo Sequelize. |
| DB_STORAGE_SQLITE | Adaptador para ser utilizado na persistência dos dados no SQLite (Para desenvolvimento e testes automatizados). |
| DB_OPERATORS_ALIASES | Permitir o uso de apelidos para operações de busca. |
| TEST_RUN_MIGRATIONS_AND_SEEDERS | Executar ou não as migrations completamente. Indicado **false** quando for utilizar o Postgres, que já possui as tabelas de positions e applicants. |
| ELASTIC_SEARCH_PROTOCOL | Protocolo utilizado pelo ES, podendo ser http ou https. |
| ELASTIC_SEARCH_HOST | Endereço do ES. |
| ELASTIC_SEARCH_PORT | Porta do ES. |

**Nota: Com o ambiente da aplicação (APP_ENV) definido como *development*, serviços externos como Sentry serão desabilitados.**

### Variáveis de ambiente sugeridas para ambiente de desenvolvimento

###### .env

```env
APP_ENV=development
APP_SENTRY_DSN=
APP_CANDIDATURES_BATCH_MAX_SIZE=25

SERVER_PROTOCOL=https
SERVER_HOST=localhost
SERVER_PORT=3333

DB_USERNAME=kenoby
DB_PASSWORD=12345
DB_DATABASE=kenoby
DB_HOST=localhost
DB_DIALECT=postgres
DB_STORAGE_SQLITE=
DB_OPERATORS_ALIASES=false

TEST_RUN_MIGRATIONS_AND_SEEDERS=false

ELASTIC_SEARCH_PROTOCOL=http
ELASTIC_SEARCH_HOST=localhost
ELASTIC_SEARCH_PORT=9200
```

###### .env.test
```env
APP_ENV=testing
APP_SENTRY_DSN=
APP_CANDIDATURES_BATCH_MAX_SIZE=25

SERVER_PROTOCOL=https
SERVER_HOST=localhost
SERVER_PORT=3333

DB_USERNAME=kenoby
DB_PASSWORD=12345
DB_DATABASE=kenoby
DB_HOST=localhost
# Dialect Options -> sqlite | postgres
DB_DIALECT=sqlite
DB_STORAGE_SQLITE=./__tests__/database.sqlite
DB_OPERATORS_ALIASES=false

TEST_RUN_MIGRATIONS_AND_SEEDERS=true

ELASTIC_SEARCH_PROTOCOL=http
ELASTIC_SEARCH_HOST=localhost
ELASTIC_SEARCH_PORT=9200
```

Exemplos de requisições para teste. Pode ser utilizado também outras ferramentas como [Postman](https://www.postman.com/). Utilizando o CURL, temos:

Para adicionar novas candidaturas:

##### POST - /v1/candidatures

```bash=
curl -XPOST -H "Content-type: application/json" -d '[
    {
        "applicant_email": "eduardo.zagari@kenoby.com",
        "position_name": "HR Supervisor",
        "situation": "hired"
    },
    {
        "applicant_email": "lzricardo.ecomp@gmail.com",
        "position_name": "HR Supervisor",
        "situation": "hired"
    }
]' 'http://localhost:3333/v1/candidatures'
```

##### Tipos de repostas possíveis

| Code HTTP   |      Descrição      |
|:----------:|:-------------:|
| 200 |  Candidaturas criadas com sucesso. |
| 404 |  Vagas ou candidatos não encontrados. |
| 422 |  Corpo da requisição é inválido. |
| 422 |  Candidaturas máximas para vaga excedida. |
| 422 |  Candidaturas duplicadas. |
| 500 |  Erro interno no servidor. Contacte o administrador. |

##### Estrutura do corpo da resposta em caso de sucesso

```json=
[
    {
        "applicant_email": "eduardo.zagari@kenoby.com",
        "position_name": "HR Supervisor",
        "situation": "hired"
    },
    {
        "applicant_email": "lzricardo.ecomp@gmail.com",
        "position_name": "HR Supervisor",
        "situation": "hired"
    }
]
```

##### Estrutura do corpo da resposta em caso de falha

```json=
"error": {
    "message": "Request body schema invalid.",
    "validation": "'value' must contain less than or equal to 25 items"
}
```

Para consultar candidaturas por pelo e-mail do candidato ou nome da vaga:

##### GET - /v1/candidatures?applicant_email=value&position_name=value

```bash=
curl -XGET -H "Content-type: application/json" 'http://localhost:3333/v1/candidatures?position_name=HR Supervisor'
```

```bash=
curl -XGET -H "Content-type: application/json" 'http://localhost:3333/v1/candidatures?applicant_email=eduardo.zagari@kenoby.com&position_name=HR Supervisor'
```

##### Tipos de repostas possíveis

| Code HTTP   |      Descrição      |
|:----------:|:-------------:|
| 200 |  Candidaturas encontradas ou não. |
| 422 |  Query param da requisição é inválido. |
| 500 |  Erro interno no servidor. Contacte o administrador. |

##### Estrutura do corpo da resposta

```json=
[
    {
        "id": 4,
        "applicant_email": "tatiane.mesquita@kenoby.com",
        "position_name": "HR Supervisor",
        "situation": "hired",
        "createdAt": "2020-06-22T02:19:17.384Z",
        "updatedAt": "2020-06-22T02:19:17.384Z"
    },
    {
        "id": 5,
        "applicant_email": "eduardo.zagari@kenoby.com",
        "position_name": "HR Supervisor",
        "situation": "hired",
        "createdAt": "2020-06-22T03:26:12.007Z",
        "updatedAt": "2020-06-22T03:26:12.007Z"
    },
    {
        "id": 6,
        "applicant_email": "lzricardo.ecomp@gmail.com",
        "position_name": "HR Supervisor",
        "situation": "hired",
        "createdAt": "2020-06-22T03:26:12.007Z",
        "updatedAt": "2020-06-22T03:26:12.007Z"
    }
]
```

```json=
[]
```

##### Estrutura do corpo da resposta em caso de falha

```json=
"error": {
    "message": "Request query params schema invalid.",
    "validation": "'applicant_email' or 'position_name' are required"
}
```