# 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"
}
```