Controle de projetos - KenzieVelopers

Introdução

Uma startup de tecnologia e desenvolvimento web decidiu criar uma API Rest para gerenciar seus desenvolvedores e projetos. Como você é um dos novos integrantes da equipe, você foi o escolhido para desenvolver essa aplicação.

Através dessa API deve ser possível realizar o registro do desenvolvedor, associar informações extras ao mesmo e registrar os projetos de cada desenvolvedor.

A seguir estarão todas as regras de negócio definidas pela startup para esse projeto. Lembre-se de seguir à risca todas as regras impostas.

Vamos lá?!

Regras da entrega

A entrega deve seguir as seguintes regras:

  • O código deve estar em TypeScript, caso não esteja a entrega será zerada;

  • Deverá ser utilizado um banco de dados postgres para a elaboração da API;

  • O nome da tabela, das colunas e demais especificações, devem ser seguidas à risca. Caso tenha divergência, será descontado nota;

  • Tenha muita atenção sobre o nome das chaves nos objetos de entrada e saída de cada requisição;

  • Na raiz do diretório deve-se conter uma pasta nomeada sql, com dois arquivos:

    • createTables.sql: contendo as queries de criação e inserção das tabelas;
    • diagram.png/jpg: um arquivo .png ou .jpg contendo o diagrama da tabela;
      • caso o arquivo createTables.sql não exista, a entrega será zerada.

Essa entrega possui testes automatizados;

  • É necessário executar um npm install assim que fizer o clone do repositório para que as depedências dos testes sejam instaladas.

  • É necessário criar um banco de dados separado para a execução dos testes.

    • Faça a criação do banco de testes e coloque os dados de conexão dele nas variáveis de ambiente que contém o indicador TEST no nome, assim sua aplicação vai saber em qual banco deve se conectar no momento de executar os testes, evitando inconsistência nos dados.
  • Para que os testes possam ser executados, existe um script de limpeza do banco que utiliza as queries do arquivo createTables.sql para ser executado, por isso é importante seguir as orientações sobre subdiretório sql e seus arquivos à risca.

    • Caso o subdiretório sql e o arquivo createTables.sql não estejam com os nomes corretos ou no caminho correto os testes falharão, pois não será possível encontrar as queries a serem executadas;
    • Caso o nome de alguma tabela, tipo ou coluna não esteja de acordo com o esperado, os testes também falharão.
  • A organização dos demais arquivos e pastas deve seguir o que foi visto previamente.

  • Todos os pacotes necessários para desenvolver a aplicação devem ser instalados, já que apenas os pacotes de teste foram incluídos no repositório.

Tabelas do banco de dados

Tabela developers

  • Nome da tabela: developers.
  • Colunas:
    • id: número, incrementação automática e chave primária.
    • name: string, tamanho 50 e obrigatório.
    • email: string, tamanho 50, obrigatório e único.

Tabela developerInfos

  • Nome da tabela: developerInfos.
  • Colunas:
    • id: número, incrementação automática e chave primária.
    • developerSince: data e obrigatório.
    • preferredOS: OS e obrigatório.
    • developerId: inteiro, único, obrigatório e chave estrangeira.
  • Especificações:
    • O campo preferredOS deve aceitar apenas os valores: Windows, Linux e MacOS.
    • O tipo OS deve ser feito usando um ENUM.

Tabela projects

  • Nome da tabela: projects.
  • Colunas:
    • id: número, incrementação automática e chave primária.
    • name: string, tamanho 50 e obrigatório.
    • description: texto.
    • repository: string, tamanho 120 e obrigatório.
    • startDate: data e obrigatório.
    • endDate: data.
    • developerId: inteiro e chave estrangeira.

Relacionamentos

developers e developerInfos

  • Um desenvolvedor pode ter apenas uma informação adicional, assim como, uma informação adicional pode pertencer a apenas um desenvolvedor.
  • Caso o developer seja deletado, a developerInfo ligada a ele deve ser deletada automaticamente.

developers e projects

  • Um desenvolvedor pode ter muitos projetos, porém, um projeto pode pertencer a apenas um desenvolvedor.
  • Caso um developer seja deletado, a coluna developerId do projeto associado deve ser automaticamente alterada para NULL.

Rotas - /developers

Endpoints

Método Endpoint Responsabilidade
POST /developers Cadastrar um novo desenvolvedor
GET /developers/:id Listar um desenvolvedor e suas informações
PATCH /developers/:id Atualizar os dados de um desenvolvedor
DELETE /developers/:id Remover um desenvolvedor
POST /developers/:id/infos Cadastrar informações adicionais a um desenvolvedor

Regras da aplicação

POST /developers

  • Deve ser possível criar um developer enviando apenas name e email através do corpo da requisição;

    • ambos devem ser uma string;
  • Não deve ser possível cadastrar um developer enviando um email já cadastrado no banco de dados.

  • Sucesso:

    • Retorno esperado: um objeto contendo os dados do developer cadastrado
    • Status esperado: 201 CREATED
  • Falha:

    • Caso o email já cadastrado no banco
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 409 CONFLICT.
  • Exemplos de retornos:

    Dados de entrada:
    Body: Formato Json
    {
      "email": "ugo@kenzie.com.br",
      "name": "Ugo"
    }
    • Criando um developer com sucesso:

      Resposta do servidor:
      Body: Formato Json
      Status code: 201 CREATED
      {
        "id": 1,
        "name": "Ugo",
        "email": "ugo@kenzie.com.br"
      }
    • Tentando cadastrar com um email existente:

      Resposta do servidor:
      Body: Formato Json
      Status code: 409 CONFLICT
      {
        "message": "Email already exists."
      }

GET /developers/:id

  • Através do id de um desenvolvedor, deve retornar um objeto contendo dados das seguintes tabelas:

    • developers;
    • developerInfos;
  • Os dados devem ser retornados exatamente como definidos aqui. Você pode usar apelidos (alias) para realizar essa tarefa:

    • developerId: tipo number;
    • developerName: tipo string;
    • developerEmail: tipo string;
    • developerInfoDeveloperSince: tipo Date ou null;
    • developerInfoPreferredOS: tipo string ou null;
  • Sucesso:

    • Retorno esperado: um objeto contendo os dados mesclados das tabelas developers e developerInfos;
    • Status esperado: 200 OK;
  • Falha:

    • Caso o id informado não pertença à nenhum developer cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
  • Exemplos de retornos:

    • Listando um developer com sucesso:

      Resposta do servidor:
      Body: Formato Json
      Status code: 200 OK
      {
        "developerId": 1,
        "developerName": "Ugo",
        "developerEmail": "ugo@kenzie.com.br",
        "developerInfoDeveloperSince": null,
        "developerInfoPreferredOS": null
      }
    • Tentando listar com um id inexistente:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Developer not found."
      }

PATCH /developers/:id

  • Através do id de um desenvolvedor, deve ser possível atualizar os dados de email e name.

  • O retorno deverá ser um objeto contendo todos os dados do developer, depois da atualização ter sido realizada.

  • Sucesso:

    • Retorno esperado: um objeto com os dados atualizados de developer;
    • Status esperado: 200 OK.
  • Falha:

    • Caso o id informado não pertence à nenhum developer cadastrado

      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
    • Caso o email já esteja cadastrado no banco

      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 409 CONFLICT.
  • Exemplos de retornos:

    Dados de entrada:
    Body: Formato Json
    {
      "email": "ugo.roveda@kenzie.com.br",
      "name": "Ugo Roveda"
    }
    • Atualizando um developer com sucesso:

      Resposta do servidor:
      Body: Formato Json
      Status code: 200 OK
      {
        "id": 1,
        "email": "ugo.roveda@kenzie.com.br",
        "name": "Ugo Roveda"
      }
    • Tentando atualizar para um email existente:

      Resposta do servidor:
      Body: Formato Json
      Status code: 409 CONFLICT
      {
        "message": "Email already exists."
      }
    • Tentando listar com um id inexistente:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Developer not found."
      }

DELETE /developers/:id

  • Deve ser possível deletar um developer informando apenas seu id;

  • Sucesso:

    • Retorno esperado: nenhum. Não deve retornar nenhum body;
    • Status esperado: 204 NO CONTENT
  • Falha:

    • Caso o id informado não pertença a nenhum developer cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
  • Exemplos de retornos:

    • Deletando um developer com sucesso:

      Resposta do servidor:
      Body: nenhum body
      Status code: 204 NO CONTENT
    • Tentando deletar com um id inexistente:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Developer not found."
      }

POST /developers/:id/infos

  • Deve ser possível inserir uma informação adicional a um developer informando seu id;

  • Deve ser possível inserir os dados developerSince e preferedOS;

    • developerSince deve ser uma data;
    • preferredOS deve ser apenas um dos três tipos possíveis:
      • Windows
      • Linux
      • MacOS
  • Sucesso:

    • Retorno esperado: objeto contendo as seguintes chaves:
      • id: tipo number
      • developerSince: tipo Date, formato americano YYYY-MM-DD.
      • preferredOS: tipo string
      • developerId: tipo number
    • Status esperado: 201 CREATED
  • Falha:

    • Caso o developer com id informado já contém uma informação adicional:
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 409 CONFLICT.
    • Caso: preferredOS informado não é um dos três permitidos:
      • Body esperado: um objeto contendo a chave message com uma mensagem adequada e uma chave options sendo um array contendo as três opções possíveis;
      • Status esperado: 400 BAD REQUEST.
    • Caso o id informado não pertença a nenhum developer cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
  • Exemplos de retornos:

    Dados de entrada:
    Body: Formato Json
    {
      "developerSince": "2013-01-01",
      "preferredOS": "MacOS"
    }
    • Criando uma informação adicional com sucesso:

      Resposta do servidor:
      Body: Formato Json
      Status code: 201 CREATED
      {
        "id": 1,
        "developerSince": "2013-01-01T02:00:00.000Z",
        "preferredOS": "MacOS",
        "developerId": 1
      }
    • Tentando cadastrar informação à um developer que já possui:

      Resposta do servidor:
      Body: Formato Json
      Status code: 409 CONFLICT
      {
        "message": "Developer infos already exists."
      }
    • Tentando cadastrar informação com um preferredOS inválido:

      Resposta do servidor:
      Body: Formato Json
      Status code: 400 BAD REQUEST
      {
        "message": "Invalid OS option."
      }
    • Tentando cadastrar informação com um developer id inválido:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Developer not found."
      }

Rota - /projects

Endpoints

Método Endpoint Responsabilidade
POST /projects Cadastrar um novo projeto
GET /projects/:id Listar um projeto pelo id e os dados do desenvolvedor
PATCH /projects/:id Atualizar um projeto

Regras da aplicação

POST - /projects

  • Deve ser possível cadastrar um novo projeto enviando os seguintes dados:

    • name: tipo string
    • description: tipo string
    • repository: tipo string
    • startDate: tipo Date, formato americano YYYY-MM-DD.
    • endDate: tipo Date, formato americano YYYY-MM-DD, não obrigatório.
    • developerId: tipo number, não obrigatório.
  • No body de retorno, caso o endDate não seja enviado na criação, deve ser retornado um null;

  • No body de retorno, caso o developerId não seja enviado na criação, deve ser retornado um null;

  • Sucesso:

    • Retorno esperado: objeto contendo todos o dados do projeto criado;
    • Status esperado: 201 CREATED
  • Falha:

    • Caso o developerId não pertença a nenhum developer cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
  • Exemplos de retornos:

    Dados de entrada:
    Body: Formato Json
    // sem endDate e sem developerId
    {
      "name": "Projeto 1",
      "description": "Projeto fullstack",
      "repository": "url.com.br",
      "startDate": "2023-12-02",
    }
    
    // com endDate e com developerId
    {
      "name": "Projeto 2",
      "description": "Projeto backend",
      "repository": "url.com.br",
      "startDate": "2023-12-10",
      "endDate": "2023-12-23",
      "developerId": 1
    }
    • Criando um projeto com sucesso:

      Resposta do servidor:
      Body: Formato Json
      Status code: 201 CREATED
      // sem endDate e sem developerId no body de envio
      {
        "id": 1,
        "name": "Projeto 1",
        "description": "Projeto fullstack",
        "repository": "url.com.br",
        "startDate": "2023-12-02T03:00:00.000Z",
        "endDate": null,
        "developerId": null
      }
      
      // com endDate no body de envio
      {
        "id": 2,
        "name": "Projeto 2",
        "description": "Projeto backend",
        "repository": "url.com.br",
        "startDate": "2023-12-10T03:00:00.000Z",
        "endDate": "2023-12-23T03:00:00.000Z",
        "developerId": 1
      }
    • Tentando criar com um developerId inválido:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Developer not found."
      }

GET - /projects/:id

  • Deve ser possível retornar os dados de um project a partir do id desse projeto;

  • O retorno deve ser um de objeto e cada objeto deve retornar os dados da tabela de projects e o nome do developer vindo da tabela de developers

  • Cada objeto deve conter as seguintes chaves:

    • projectId
    • projectName
    • projectDescription
    • projectRepository
    • projectStartDate
    • projectEndDate
    • projectDeveloperName
  • Sucesso:

    • Retorno esperado: um objeto contendo todos os dados relacionados ao projeto e o nome do desenvolvedor;
    • Status esperado: 200 OK
  • Falha:

    • Caso o id não pertença a um project cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
  • Exemplos de retornos:

    • Listando um projeto com sucesso:

      Resposta do servidor:
      Body: Formato Json
      Status code: 200 OK
          {
              "projectId": 1,
              "projectName": "Projeto 1",
              "projectDescription": "Projeto fullstack",
              "projectRepository": "url.com.br",
              "projectStartDate": "2023-12-02T03:00:00.000Z",
              "projectEndDate": null,
              "projectDeveloperName": "ugo"
          },
    • Tentando listar com um projectId inválido:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Project not found."
      }

PATCH - /projects/:id

  • Deverá ser possível atualizar todos os dados de um projeto com exceção do id;

  • Todos os dados permitidos para atualização devem ser opcionais no envio;

  • Sucesso:

    • Retorno esperado: objeto contendo todos os dados do projeto que foi atualizado;
    • Status esperado: 200 OK
  • Falha:

    • Caso o id informado na url não pertence à um projeto cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
    • Caso o developerId informado no body não pertença à um developer cadastrado
      • Retorno esperado: um objeto contendo a chave message com uma mensagem adequada;
      • Status esperado: 404 NOT FOUND.
  • Exemplos de retornos:

    Dados de entrada:
    Body: Formato Json
    {
      "name": "Novo nome",
      "description": "Nova descrição",
      "repository": "novaurl.com.br",
      "startDate": "2022-11-13",
      "endDate": "2023-11-13",
      "developerId": 2
    }
    • Atualizando um projeto com sucesso:
      Resposta do servidor:
      Body: Formato Json
      Status code: 200 OK
    {
      "id": 1,
      "name": "Novo nome",
      "description": "Nova descrição",
      "repository": "novaurl.com.br",
      "startDate": "2022-11-13T03:00:00.000Z",
      "endDate": "2023-11-13T03:00:00.000Z",
      "developerId": 2
    }
    • Tentando atualizar com um project id inválido:

      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Project not found."
      }
    • Tentando atualizar com um developerId inválido:

      Dados de entrada:
      Body: Formato Json
      {
        "developerId": 9999
      }
      Resposta do servidor:
      Body: Formato Json
      Status code: 404 NOT FOUND
      {
        "message": "Developer not found."
      }