{"id":19268547,"url":"https://github.com/gabrielgpavao/kimoveis-api-node","last_synced_at":"2026-04-11T11:04:36.596Z","repository":{"id":158421383,"uuid":"634013462","full_name":"gabrielgpavao/kimoveis-api-node","owner":"gabrielgpavao","description":"API para Gerenciamento de uma Imobiliária.","archived":false,"fork":false,"pushed_at":"2023-05-13T18:45:47.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-01-05T12:41:49.668Z","etag":null,"topics":["api-rest","expressjs","gitflow-workflow","jest-test","nodejs","postgresql","typeorm","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gabrielgpavao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-28T20:12:05.000Z","updated_at":"2023-04-28T20:17:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"648d0a29-1d92-427f-9228-cbe7e389c902","html_url":"https://github.com/gabrielgpavao/kimoveis-api-node","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielgpavao%2Fkimoveis-api-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielgpavao%2Fkimoveis-api-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielgpavao%2Fkimoveis-api-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrielgpavao%2Fkimoveis-api-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gabrielgpavao","download_url":"https://codeload.github.com/gabrielgpavao/kimoveis-api-node/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240371742,"owners_count":19790888,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-rest","expressjs","gitflow-workflow","jest-test","nodejs","postgresql","typeorm","typescript"],"created_at":"2024-11-09T20:16:37.258Z","updated_at":"2025-10-18T17:50:19.006Z","avatar_url":"https://github.com/gabrielgpavao.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Documentação da API\n\n## Sumário\n\n- [Visão Geral](#1-visão-geral)\n- [Diagrama de Entidade Relacionamento (DER)](#2-diagrama-de-entidade-relacionamento)\n- [Início Rápido](#3-início-rápido)\n    - [Instalando Dependências](#31-instalando-dependências)\n    - [Variáveis de Ambiente](#32-variáveis-de-ambiente)\n    - [Migrations](#33-migrations)\n- [Endpoints](#4-endpoints)\n- [Sobre os Testes](#5-sobre-os-testes)\n\n---\n\n## 1. Visão Geral\n\nAplicação Backend (API) criada para gerenciar os dados de uma imobiliária. É possível cadastrar novos clientes, cadastrar novos imóveis, associá-los a um endereço e categoria, bem como agendar uma visita do cliente para o imóvel.\n\nPrincipais tecnologias utilizadas:\n\n- [Node.js](https://nodejs.org/en/)\n- [Express.js](https://expressjs.com/pt-br/)\n- [TypeScript](https://www.typescriptlang.org/)\n- [PostgreSQL](https://www.postgresql.org/)\n- [TypeORM](https://typeorm.io/)\n- [Zod](https://zod.dev/)\n- [JSON Web Token](https://jwt.io/)\n\n---\n\n## 2. Diagrama de Entidade Relacionamento\n[ Voltar para o topo ](#sumário)\n\n\nRelações entre as tabelas do banco de dados.\n\n![DER](https://m4-seven.vercel.app/modulo_4/_entregas/sprint_6/projeto_semanal/der.png)\n\n---\n\n## 3. Início Rápido\n[ Voltar para o topo ](#sumário)\n\n\n### 3.1. Instalando Dependências\n\nClone o projeto em sua máquina e instale as dependências com o comando:\n\nCaso use npm\n```bash\nnpm install\n```\n\nCaso use yarn\n```bash\nyarn\n```\n\n### 3.2. Variáveis de Ambiente\n\nEm seguida, crie um arquivo **.env**, copiando o formato do arquivo **.env.example**:\n```\ncp .env.example .env\n```\n\nConfigure suas variáveis de ambiente com suas credenciais do PostgreSQL e um novo Banco de Dados da sua escolha.\n\n### 3.3. Migrations\n\nExecute as migrations com o comando:\n\nCaso use npm\n```bash\nnpm run typeorm migration:run -d src/data-source.ts\n```\n\nCaso use yarn\n```bash\nyarn typeorm migration:run -d src/data-source.ts\n```\n\n---\n\n## 4. Endpoints\n\n[ Voltar para o topo ](#sumário)\n\n### Índice\n\n- [Login](#41-login)\n    - [POST - /login](#login)\n- [Users](#42-users)\n    - [POST - /users](#21-criação-de-usuário)\n    - [GET - /users](#422-listando-usuários)\n    - [PATCH - /users/:id](#423-atualização-de-usuário)\n    - [DELETE - /users/:id](#424-deleção-de-usuário)\n- [Categories](#43-categories)\n    - [POST - /categories](#431-criação-de-categorias)\n    - [GET - /categories](#432-listando-as-categorias)\n    - [GET - /categories/:id/realEstate](#433-listando-imóveis-de-uma-categoria)\n- [Real Estate](#44-real-estates)\n    - [POST - /realEstate](#441-criação-de-imóveis)\n    - [GET - /realEstate](#442-listando-imóveis)\n- [Schedules](#45-schedules)\n    - [POST - /schedules](#451-agendando-visita-a-um-imóvel)\n    - [GET - /schedules/realEstate/:id](#452-listar-agendamentos-de-um-imóvel)\n\n---\n\n## 4.1. **Login**\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/login`\n\n### Exemplo de Request:\n```\nPOST /login\nHost: http://localhost:3000/\nAuthorization: None\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```json\n{\n\t\"email\": \"gabriel@mail.com\",\n\t\"password\": \"1234\"\n}\n```\n\n### Schema de Validação com Zod:\n```javascript\nemail: z\n  .string()\n  .email(),\npassword: z\n  .string()\n```\nOBS.: Chaves não presentes no schema serão ignoradas.\n\n### Exemplo de Response:\n```\n201 Created\n```\n\n```json\n{\n\t\"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZSwiaWF0IjoxNjc4ODE2MzE4LCJleHAiOjE2Nzg5MDI3MTgsInN1YiI6IjYifQ.TLL1i1jU4rpOwiqqS8n0J4vr2rMa4i68hZ0v6yIwTdI\"\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 400 Bad Request   | ZodError - Invalid Body. | Corpo da requisição possui alguma chave ou valor incorreto. |\n| 401 Unauthorized | Invalid credentials | Email ou senha estão incorretos. |\n\n---\n\n## 4.2. **Users**\n[ Voltar para os Endpoints ](#4-endpoints)\n\nO objeto User é definido como:\n\n| Campo      | Tipo   | Descrição                                     |\n| -----------|--------|-------------------------------------------------|\n| id         | number | Identificador único do usuário                  |\n| name       | string | O nome do usuário.                              |\n| email      | string | O e-mail do usuário. Valor Único.               |\n| password   | string | A senha de acesso do usuário                    |\n| admin      | boolean | Define se o usuário é Administrador ou não. Campo opcional. |\n| createdAt  | date | Data de criação gerada no momento da criação. Read-only.       |\n| updatedAt  | date | Data de atualização gerada no momento de qualquer alteração. Read-only. |\n| deletedAt  | date | Data de deleção gerada no momento da deleção. Read-only.       |\n\n### Endpoints\n\n| Método   | Rota       | Descrição                               |\n|----------|------------|-----------------------------------------|\n| POST     | /users     | Criação de um usuário.                  |\n| GET      | /users     | Lista todos os usuários                 |\n| PATCH    | /users/:id     | Atualiza um usuário usando seu ID como parâmetro |\n| DELETE   | /users/:id     | Realiza um soft delete em um usuário usando seu ID como parâmetro |\n\n---\n\n### 4.2.1. **Criação de Usuário**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/users`\n\n### Exemplo de Request:\n```\nPOST /users\nHost: http://localhost:3000/\nAuthorization: None\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```json\n{\n\t\"name\": \"Gabriel\",\n\t\"email\": \"gabriel@mail.com\",\n\t\"password\": \"1234\"\n}\n```\nOBS.: A chave \"admin\" é opcional. O valor padrão é *false*.\n\n### Schema de Validação com Zod:\n```javascript\nname: z\n  .string()\n  .max(45, 'String must contain at most 45 character(s)'),\nemail: z\n  .string()\n  .email('Invalid email'),\npassword: z\n  .string()\n  .max(120, 'String must contain at most 120 character(s)'),\nadmin: z\n  .boolean()\n  .default(false)\n```\nOBS.: Chaves não presentes no schema serão ignoradas.\n\n### Exemplo de Response:\n```\n201 Created\n```\n\n```json\n{\n\t\"id\": 1,\n\t\"name\": \"Gabriel\",\n\t\"email\": \"gabriel@mail.com\",\n\t\"admin\": false,\n  \"createdAt\": \"2023-04-16\",\n  \"updatedAt\": \"2023-04-16\",\n  \"deletedAt\": null\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 409 Conflict   | Email already registered. | Email inserido já está registrado. |\n| 400 Bad Request   | ZodError - Invalid Body. | Corpo da requisição possui alguma chave ou valor incorreto. |\n\n---\n\n### 4.2.2. **Listando Usuários**\n\n[ Voltar aos Endpoints ](#4-endpoints)\n\n### `/users`\n\nEsta rota só pode ser acessada por usuários administradores que estão logados.\n\n### Exemplo de Request:\n```\nGET /users\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```\nVazio\n```\n\n### Exemplo de Response:\n```\n200 OK\n```\n```json\n[\n  {\n    \"id\": 1,\n    \"name\": \"Gabriel\",\n    \"email\": \"gabriel@mail.com\",\n    \"admin\": false,\n    \"createdAt\": \"2023-04-16\",\n    \"updatedAt\": \"2023-04-16\",\n    \"deletedAt\": null\n  }\n]\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 403 Forbidden   | Insufficient Permission. | Tentativa de acesso sem permissão de administrador |\n\n---\n\n### 4.2.3. **Atualização de Usuário**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/users/:id`\n\nApenas administradores podem atualizar qualquer usuário.\nUsuários não-administradores podem apenas atualizar a si mesmo.\n\n### Exemplo de Request:\n```\nPATCH /users/1\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```json\n{\n\t\"name\": \"Gabriel Pavão\"\n}\n```\nOBS.: A chave \"admin\" não pode ser atualizada.\n\n### Schema de Validação com Zod:\n```javascript\nname: z\n  .string()\n  .max(45, 'String must contain at most 45 character(s)')\n  .optional(),\nemail: z\n  .string()\n  .email('Invalid email')\n  .optional(),\npassword: z\n  .string()\n  .max(120, 'String must contain at most 120 character(s)')\n  .optional()\n```\nOBS.: Chaves não presentes no schema serão ignoradas.\n\n### Exemplo de Response:\n```\n200 OK\n```\n\n```json\n{\n\t\"id\": 1,\n\t\"name\": \"Gabriel Pavão\",\n\t\"email\": \"gabriel@mail.com\",\n\t\"admin\": false,\n  \"createdAt\": \"2023-04-16\",\n  \"updatedAt\": \"2023-04-16\",\n  \"deletedAt\": null\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 400 Bad Request   | ZodError - Invalid Body. | Corpo da requisição possui alguma chave ou valor incorreto. |\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 403 Forbidden   | Insufficient Permission. | Tentativa de acesso sem permissão de administrador |\n| 404 Not Found   | User not found. | ID inserido na url não existe. |\n| 409 Conflict   | Email already registered. | Email inserido já está registrado. |\n\n---\n\n### 4.2.4. **Deleção de Usuário**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/users/:id`\n\nA rota realiza um soft delete do usuário e pode ser acessada apenas por usuários administradores.\n\n### Exemplo de Request:\n```\nDELETE /users/1\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```\nVazio\n```\n\n### Exemplo de Response:\n```\n204 No Content\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 403 Forbidden   | Insufficient Permission. | Tentativa de acesso sem permissão de administrador |\n| 404 Not Found   | User not found. | ID inserido na url não existe. |\n\n---\n\n## 4.3. **Categories**\n[ Voltar para os Endpoints ](#4-endpoints)\n\nO objeto Category é definido como:\n\n| Campo      | Tipo   | Descrição                                       |\n| -----------|--------|-------------------------------------------------|\n| id         | number | Identificador único da categoria                |\n| name       | string | O nome da categoria. Valor único.               |\n\n### Endpoints\n\n| Método   | Rota       | Descrição                               |\n|----------|------------|-----------------------------------------|\n| POST     | /categories     | Criação de uma categoria           |\n| GET      | /categories     | Lista todas as categorias          |\n| GET      | /categories/:id/realEstate     | Lista todos imóveis que pertencem a uma categoria |\n\n---\n\n### 4.3.1. **Criação de Categorias**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/categories`\n\nA rota pode ser acessada apenas por usuários administradores.\n\n### Exemplo de Request:\n```\nPOST /categories\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```json\n{\n\t\"name\": \"Apartamento\"\n}\n```\n\n### Schema de Validação com Zod:\n```javascript\nname: z\n  .string()\n  .max(45)\n```\nOBS.: Chaves não presentes no schema serão ignoradas.\n\n### Exemplo de Response:\n```\n201 Created\n```\n\n```json\n{\n\t\"id\": 1,\n\t\"name\": \"Apartamento\"\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 400 Bad Request   | ZodError - Invalid Body. | Corpo da requisição possui alguma chave ou valor incorreto. |\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 403 Forbidden   | Insufficient Permission. | Tentativa de acesso sem permissão de administrador |\n| 409 Conflict   | Category already exists. | Categoria inserida já está registrada. |\n\n---\n\n### 4.3.2. **Listando as Categorias**\n\n[ Voltar aos Endpoints ](#4-endpoints)\n\n### `/categories`\n\nA rota possui acesso livre.\n\n### Exemplo de Request:\n```\nGET /categories\nHost: http://localhost:3000/\nAuthorization: None\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```\nVazio\n```\n\n### Exemplo de Response:\n```\n200 OK\n```\n```json\n[\n  {\n\t  \"id\": 1,\n\t  \"name\": \"Apartamento\"\n  }\n]\n```\n\n### Possíveis Erros:\nNenhum erro é esperado para essa rota.\nO máximo que pode acontecer é o retorno de uma lista vazia.\n\n---\n\n### 4.3.3. **Listando Imóveis de uma Categoria**\n\n[ Voltar aos Endpoints ](#4-endpoints)\n\n### `/categories/:id/realEstate`\n\nA rota possui acesso livre.\n\n### Exemplo de Request:\n```\nGET /categories/1/realEstate\nHost: http://localhost:3000/\nAuthorization: None\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```\nVazio\n```\n\n### Exemplo de Response:\n```\n200 OK\n```\n```json\n{\n  \"id\": 1,\n  \"name\": \"Apartamento\",\n  \"realEstate\": [\n    {\n      \"id\": 1,\n      \"value\": \"100000.00\",\n      \"size\": 500,\n      \"sold\": false,\n      \"createdAt\": \"2023-03-02\",\n      \"updatedAt\": \"2023-03-02\"\n    }\n  ]\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 404 Not Found  | Category not found. | ID da categoria informada não existe. |\n\n---\n\n## 4.4. **Real Estates**\n[ Voltar para os Endpoints ](#4-endpoints)\n\nO objeto Real Estate é definido como:\n\n| Campo      | Tipo   | Descrição                                       |\n| -----------|--------|-------------------------------------------------|\n| id         | number | Identificador único do imóvel                   |\n| value      | float  | Preço do imóvel                                 |\n| size       | number | Área total do imóvel                            |\n| categoryId | number | ID da categoria da qual o imóvel pertence       |\n| sold       | boolean | Booleano que informa se o imóvel foi vendido. Read-only. |\n| createdAt  | date | Data de criação gerada no momento da criação. Read-only.       |\n| updatedAt  | date | Data de atualização gerada no momento de qualquer alteração. Read-only. |\n| address | object | Objeto contendo os dados do endereço do imóvel. Ver tabela abaixo para saber mais. |\n\nO objeto Address é definido como:\n\n| Campo      | Tipo   | Descrição                                        |\n| -----------|--------|--------------------------------------------------|\n| id         | number | Identificador único do endereço                  |\n| street     | string | Nome da rua do endereço                          |\n| zipCode    | string | Código postal (CEP) do endereço em até 8 dígitos | \n| number     | string | Número do imóvel                                 |\n| city       | string | Cidade do endereço                               |\n| state      | string | Estado do endereço no formato AA. Ex: SP.        |\n\n### Endpoints\n\n| Método   | Rota       | Descrição                               |\n|----------|------------|-----------------------------------------|\n| POST     | /realEstate     | Criação de um imóvel               |\n| GET      | /realEstate     | Lista todos os imóveis             |\n\n---\n\n### 4.4.1. **Criação de Imóveis**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/realEstate`\n\nA rota pode ser acessada apenas por usuários administradores.\n\n### Exemplo de Request:\n```\nPOST /realEstate\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```json\n{\n\t\"value\": 100000.00,\n\t\"size\": 500,\n\t\"categoryId\": 1,\n\t\"address\": {\n\t\t\"street\": \"Rua das Flores\",\n\t\t\"number\": \"15\"\n\t\t\"zipCode\": \"66520000\",\n\t\t\"city\": \"Curitiba\",\n\t\t\"state\": \"PR\"\n\t}\n}\n```\n\n### Schema de Validação de Real Estate com Zod:\n```javascript\nvalue: z\n\t.number()\n\t.min(-9999999999.99)\n\t.max(9999999999.99)\n\t.or(z.string()),\nsize: z\n\t.number()\n\t.int()\n\t.positive()\ncategoryId: z\n\t.number()\n\t.int()\naddress: Address\n```\n\n### Schema de Validação de Address com Zod:\n```javascript\nstreet: z\n\t.string()\n\t.max(45),\nzipCode: z\n\t.string()\n\t.max(8),\nnumber: z\n\t.string()\n\t.max(7)\n\t.nullish(),\ncity: z\n\t.string()\n\t.max(20),\nstate: z.string().max(2)\n```\n\nOBS.: Chaves não presentes no schema serão ignoradas.\n\n### Exemplo de Response:\n```\n201 Created\n```\n\n```json\n{\n\t\"id\": 1,\n\t\"value\": \"100000.00\",\n\t\"size\": 500,\n\t\"sold\": false,\n\t\"createdAt\": \"2023-04-27\",\n\t\"updatedAt\": \"2023-04-27\",\n\t\"address\": {\n\t\t\"id\": 1,\n\t\t\"street\": \"Rua das Flores\",\n\t\t\"number\": \"15\",\n\t\t\"zipCode\": \"66520000\",\n\t\t\"city\": \"Curitiba\",\n\t\t\"state\": \"PR\",\n\t},\n\t\"category\": {\n\t\t\"id\": 1,\n\t\t\"name\": \"Apartamento\"\n\t}\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 400 Bad Request   | ZodError - Invalid Body. | Corpo da requisição possui alguma chave ou valor incorreto. |\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 403 Forbidden   | Insufficient Permission. | Tentativa de acesso sem permissão de administrador |\n| 409 Conflict   | Address already exists. | Endereço inserido já está registrado. |\n\n---\n\n### 4.4.2. **Listando Imóveis**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/realEstate`\n\nA rota possui acesso livre.\n\n### Exemplo de Request:\n```\nPOST /realEstate\nHost: http://localhost:3000/\nAuthorization: None\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```\nVazio\n```\n\n### Exemplo de Response:\n```\n200 OK\n```\n\n```json\n[\n\t{\n\t\t\"id\": 1,\n\t\t\"value\": \"100000.00\",\n\t\t\"size\": 500,\n\t\t\"createdAt\": \"2023-04-27\",\n\t\t\"updatedAt\": \"2023-04-27\",\n\t\t\"sold\": false,\n\t\t\"address\": {\n\t\t\t\"id\": 1,\n\t\t\t\"street\": \"Rua das Flores\",\n\t\t\t\"number\": \"15\",\n\t\t\t\"zipCode\": \"66520000\",\n\t\t\t\"city\": \"Curitiba\",\n\t\t\t\"state\": \"PR\",\n\t\t}\n\t}\n]\n```\n\n### Possíveis Erros:\nNenhum erro é esperado para essa rota.\nO máximo que pode acontecer é o retorno de uma lista vazia.\n\n ---\n \n## 4.5. **Schedules**\n[ Voltar para os Endpoints ](#4-endpoints)\n\nO objeto Schedules é definido como:\n\n| Campo        | Tipo   | Descrição                                                     |\n| -------------|--------|---------------------------------------------------------------|\n| id           | number | Identificador único da categoria                              |\n| date         | date   | Data de agendamento da visita ao imóvel no formato AAAA-DD-MM |\n| hour         | string | Horário de agendamento da visita ao imóvel no formato HH:MM   |\n| realEstateId | number | ID do imóvel a ser visitado                                   |\n| userId       | number | ID do usuário que está agendando a visita. Read-only.         |\n\n### Endpoints\n\n| Método   | Rota                      | Descrição                                |\n|----------|---------------------------|------------------------------------------|\n| POST     | /schedules                | Agenda uma visita a um imóvel            |\n| GET      | /schedules/realEstate/:id | Lista todos os agendamentos de um imóvel |\n\n---\n\n### 4.5.1. **Agendando Visita a um Imóvel**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/schedules`\n\nA rota pode ser acessada apenas por usuários logados.\n\n### Exemplo de Request:\n```\nPOST /schedules\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```json\n{\n\t\"date\": \"2023/04/19\",\n  \t\"hour\": \"15:00\",\n\t\"realEstateId\": 1\n}\n```\n\n### Schema de Validação de Real Estate com Zod:\n```javascript\ndate: z\n\t.string()\n\t.refine((date: string) =\u003e {\n\t\tconst dateRegex: RegExp = /^\\d{4}\\/(0[1-9]|1[012])\\/(0[1-9]|[12][0-9]|3[01])$/\n\t\treturn dateRegex.test(date)\n\t}, { message: 'Invalid date, date format is YYYY/DD/MM' })\n\t.refine((date: any) =\u003e {\n\t\tdate = date.split('/')\n\t\tconst handleDate = new Date(date[0], date[2] - 1, date[1])\n\t\tconst dateDay = handleDate.getDay()\t\n\t\treturn dateDay \u003e= 1 \u0026\u0026 dateDay \u003c= 5\n\t}, { message: 'Invalid date, work days are monday to friday'}),\nhour: z\n\t.string()\n\t.refine((hour: string) =\u003e {\n\t\tconst hourRegex: RegExp = /^(0[8-9]|1[0-7]):[0-5][0-9]$/\n\t\treturn hourRegex.test(hour)\n\t}, { message: `Invalid hour, available times are 8AM to 18PM` }),\n\nrealEstateId: z\n\t.number()\n\t.int()\n```\n\n### Exemplo de Response:\n```\n201 Created\n```\n\n```json\n{\n\t\"message\": \"Schedule created\"\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 400 Bad Request   | ZodError - Invalid Body. | Corpo da requisição possui alguma chave ou valor incorreto. |\n| 400 Bad Request   | Invalid hour, available times are 8AM to 18PMy. | A hora informada é antes das 8:00 ou depois das 18:00. |\n| 400 Bad Request   | Invalid date, work days are monday to friday. | A data informada corresponde a um sábado ou domingo. |\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 404 Not Found   | RealEstate not found. | ID do imóvel fornecido não existe |\n| 409 Conflict   | Schedule to this real estate at this date and time already exists. | Já existe uma visita marcada para esse imóvel nessa mesma data e hora. |\n| 409 Conflict   | User schedule to this real estate at this date and time already exists. | O próprio usuário já possui uma outra visita agendada nessa mesma data e hora. |\n\n---\n\n### 4.5.2. **Listar Agendamentos de um Imóvel**\n\n[ Voltar para os Endpoints ](#4-endpoints)\n\n### `/schedules/realEstate/:id`\n\nA rota pode ser acessada apenas por usuários administradores.\n\n### Exemplo de Request:\n```\nPOST /schedules/realEstate/:id\nHost: http://localhost:3000/\nAuthorization: Bearer Token\nContent-type: application/json\n```\n\n### Corpo da Requisição:\n```\nVazio\n```\n\n### Exemplo de Response:\n```\n200 OK\n```\n\n```json\n{\n\t\"id\": 1,\n\t\"value\": \"100000.00\",\n\t\"size\": 500,\n\t\"createdAt\": \"2023-04-27\",\n\t\"updatedAt\": \"2023-04-27\",\n\t\"sold\": false,\n\t\"category\": {\n\t\t\"id\": 1,\n\t\t\"name\": \"Apartamento\"\n\t},\n\t\"address\": {\n\t\t\"id\": 1,\n\t\t\"street\": \"Rua das Flores\",\n\t\t\"zipCode\": \"66520000\",\n\t\t\"number\": 15,\n\t\t\"city\": \"Curitiba\",\n\t\t\"state\": \"PR\"\n\t},\n\t\"schedules\": [\n\t\t{\n\t\t\t\"id\": 1,\n\t\t\t\"date\": \"2023-04-19\",\n\t\t\t\"hour\": \"15:00:00\",\n\t\t\t\"user\": {\n\t\t\t\t\"id\": 1,\n\t\t\t\t\"name\": \"Gabriel\",\n\t\t\t\t\"email\": \"gabriel@mail.com\",\n\t\t\t\t\"admin\": true,\n\t\t\t\t\"createdAt\": \"2023-03-01\",\n\t\t\t\t\"updatedAt\": \"2023-03-01\",\n\t\t\t\t\"deletedAt\": null\n\t\t\t}\n\t\t}\n\t]\n}\n```\n\n### Possíveis Erros:\n| Código do Erro | Descrição | Causa |\n|----------------|-----------|-------|\n| 401 Unauthorized   | Missing Bearer Token. | Token não enviado. |\n| 401 Unauthorized   | JWT malformed. | Token violado ou incompleto |\n| 403 Forbidden   | Insufficient Permission. | Tentativa de acesso sem permissão de administrador |\n\n---\n\n## 5. Sobre os Testes\n\nEssa aplicação possui testes, que são utilizados para validar, se todas as regras de negócio foram aplicadas de maneira correta.\n\nOs testes estão localizados em `src/__tests__`.\n\nNa subpasta `integration` estão os testes.\n\nJá na subpasta `mocks` estão os dados que serão utilizados para os testes.\n\nNo arquivo `jest.config.ts` estão algumas configurações necessárias para os testes rodarem.\n\n**`De modo algum altere qualquer um desses arquivos.`** Isso poderá comprometer a integridade dos testes.\n\nE também não altere o script de `test` localizado no `package.json`. Isso será utilizado para rodar os testes.\n\n## Rodando os testes\n\nPara rodar os testes é necessário que no seu terminal, você esteja dentro do diretório do projeto.\n\nEstando no terminal e dentro do caminho correto, você poderá utilizar os comandos a seguir:\n\n### Rodar todos os testes\n\n```bash\n# caso use npm\nnpm run test\n\n# caso use yarn\nyarn test\n```\n\n### Rodar todos os testes e ter um log ainda mais completo\n\n```bash\n# caso use npm\nnpm run test --all\n\n# caso use yarn\nyarn test --all\n```\n\n### Rodar os testes de uma pasta específica\n\n\u003e detalhe: repare que tests está envolvido por 2 underlines. Isso se chama ***dunder***.\n\n```bash\n# caso use npm\nnpm run test \u003csubpasta\u003e\n\n# caso use yarn\nyarn test \u003csubpasta\u003e\n```\n\n### Rodar os testes de um arquivo específico\n\n```bash\n# caso use npm\nnpm run test \u003csubpasta\u003e/\u003carquivo\u003e\n\n# caso use yarn\nyarn test \u003csubpasta\u003e/\u003carquivo\u003e\n```\n\n**Caso você queira verificar todas as opções de execução de testes, visite a [Documentação oficial do Jest](https://jestjs.io/docs/cli)**\n\nApós rodar um dos comandos aparecerá um log no seu terminal, contendo as informações da execução do teste.\n\n**Observação:** O teste pode demorar alguns segundos para ser finalizado. Quanto maior for o teste, mais tempo será consumido para a execução.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrielgpavao%2Fkimoveis-api-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgabrielgpavao%2Fkimoveis-api-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrielgpavao%2Fkimoveis-api-node/lists"}