Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

# Refatoração de Código, Correções e Melhoria de Documentação #145

Merged
merged 16 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions backend/README.md
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A atualização da documentação foi vem feita!

Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
## **Guia de Utilização da API de Licitações Culturais de Minas Gerais**
# Como utilizar o Back-end do projeto

### **Visão Geral**

Esta API permite consultar informações relacionadas a licitações culturais de Minas Gerais. A API foi desenvolvida utilizando Express.js e está organizada em três camadas principais: `models`, `services` e `controllers`. Abaixo, você encontrará a descrição dos endpoints disponíveis e como utilizá-los.
Esta API permite consultar informações sobre licitações culturais em Minas Gerais. Embora o código-fonte da API esteja disponível em nosso repositório, o acesso ao banco de dados principal é restrito. No entanto, você pode acessar a API publicamente através da seguinte URL: [https://minas-cultura-api.onrender.com](https://minas-cultura-api.onrender.com).


A API foi desenvolvida utilizando Express.js e está organizada em três camadas principais: `models`, `services` e `controllers`. Abaixo, você encontrará a descrição dos endpoints disponíveis e como utilizá-los.

### **Estrutura da API**

A API está localizada no diretório `backend/src/`, e é composta por três endpoints principais:

1. **/tenders**
2. **/tenders/year**
3. **/health**

### **Endpoints**

#### **1. Consultar Licitações Mensais: `/tenders`**

- **Descrição:** Retorna uma lista de licitações baseadas nos parâmetros de data inicial e final.
- **URL:** `http://localhost:5000/tenders?start=201501&end=201502`
- **URL:** `https://minas-cultura-api.onrender.com/tenders?start=201501&end=201502`
- **Método:** `GET`
- **Parâmetros:**
- `start`: Representa o início do período de consulta no formato `AAAAMM` (ano/mês). Por exemplo, `201501` corresponde a janeiro de 2015.
Expand All @@ -25,15 +29,17 @@ A API está localizada no diretório `backend/src/`, e é composta por três end
#### **2. Consultar Licitações Anuais: `/tenders/year`**

- **Descrição:** Retorna os valores totais empenhados, liquidados e pagos no ano informado no parâmetro "year".
- **URL:** `http://localhost:5000/tenders/year?year=2024`
- **URL:** `https://minas-cultura-api.onrender.com/tenders/year?year=2024`
- **Método:** `GET`
- **Parâmetros:**
- `year`: Representa o ano de consulta no formato `AAAA` (ano). Por exemplo, `year=2024` retornará o total de licitações empenhadas, liquidadas e pagas no ano de 2024.

#### **3. Consultar a saúde da aplicação: `/health`**

- **Descrição:** Retorna a mensagem "OK" em caso de sucesso na conexão com a api, este endpoint é necessário para monitorar a estabilidade do sistema.
- **URL:** `https://minas-cultura-api.onrender.com/health`
- **Método:** `GET`

### **Considerações Importantes**

- **Porta:** A API está configurada para rodar na porta `5000`.
---

Siga este guia para consultar e explorar as licitações culturais de Minas Gerais. Caso tenha dúvidas ou precise de suporte adicional, entre em contato com o time de desenvolvimento.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async function main() {
.single()

if (unidadeAdmError || !unidadeAdmData) {
const { data, error } = await supabase
const { data } = await supabase
.from('administrative_units')
.insert([{ name: unidadeAdm }])
.single()
Expand All @@ -52,7 +52,7 @@ async function main() {
.single()

if (cidadeError || !cidadeData) {
const { data, error } = await supabase
const { data } = await supabase
.from('cities')
.insert([{ name: cidade }])
.single()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const insertInitialData = async () => {

// Inserir cidades
for (const city of uniqueCities) {
const { data: cityData, error: cityError } = await supabase
const { error: cityError } = await supabase
.from('cities')
.upsert({ name: city }, { onConflict: ['name'] })

Expand All @@ -37,7 +37,7 @@ const insertInitialData = async () => {

// Inserir unidades administrativas
for (const unit of uniqueUnits) {
const { data: unitData, error: unitError } = await supabase
const { error: unitError } = await supabase
.from('administrative_units')
.upsert({ name: unit }, { onConflict: ['name'] })

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const supabase = require('../config/supabaseClient')
const supabase = require('../../src/config/supabaseClient')

async function getAllCities() {
const { data, error } = await supabase
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const supabase = require('../config/supabaseClient');
const supabase = require('../../src/config/supabaseClient');

async function getTendersByCityAndDate(start, end, cityId) {
const startAno = Math.floor(start / 100) % 100; // Extrai os últimos dois dígitos do ano
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const supabase = require('../config/supabaseClient')
const supabase = require('../../src/config/supabaseClient')

async function getAllUnits() {
const { data, error } = await supabase
Expand Down
15 changes: 15 additions & 0 deletions backend/__tests__/health.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const request = require('supertest');
const app = 'https://minas-cultura-api.onrender.com';

describe('Testes do Endpoint de Health', () => {
it('Deve retornar "OK"', async () => {

const res = await request(app)
.get(`/health`)
.expect('Content-Type', /json/)
.expect(200);

expect(res.status).toBe(200);
expect(res.body).toBeDefined();
});
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
const request = require('supertest');
const app = 'http://localhost:5000';
const app = 'https://minas-cultura-api.onrender.com';

describe('Testes do Endpoint de Licitações', () => {
it('Deve retornar licitações para a cidade específica no intervalo de tempo fornecido', async () => {
const startYear = '23';
describe('Testes do Endpoint de Licitações Mensais', () => {
it('Deve retornar licitações no intervalo de tempo fornecido', async () => {
const startYear = '2023';
const startMonth = '01';
const endYear = '23';
const endYear = '2023';
const endMonth = '06';
const cityId = 1;

const res = await request(app)
.get(`/tenders?start=${startYear}${startMonth}&end=${endYear}${endMonth}&city=${cityId}`)
.get(`/tenders?start=${startYear}${startMonth}&end=${endYear}${endMonth}`)
.expect('Content-Type', /json/)
.expect(200);

Expand All @@ -20,26 +19,18 @@ describe('Testes do Endpoint de Licitações', () => {

res.body.forEach(tender => {
expect(tender).toHaveProperty('id');
expect(tender).toHaveProperty('administrative_unit_id');
expect(tender).toHaveProperty('city_id');
expect(tender).toHaveProperty('committed_value');
expect(tender).toHaveProperty('liquidated_value');
expect(tender).toHaveProperty('paid_value');
expect(tender).toHaveProperty('year');
expect(tender).toHaveProperty('month');
expect(typeof tender.id).toBe('number');
expect(typeof tender.administrative_unit_id).toBe('number');
});
});

it('Deve retornar um erro quando a cidade não for fornecida', async () => {
const startYear = '23';
const startMonth = '01';
const endYear = '23';
const endMonth = '06';
it('Deve retornar um erro quando a data não for fornecida', async () => {

const res = await request(app)
.get(`/tenders?start=${startYear}${startMonth}&end=${endYear}${endMonth}`);
.get(`/tenders?start=&end=`);

expect(res.status).toBe(400);
expect(res.body).toBeDefined();
Expand Down
34 changes: 34 additions & 0 deletions backend/__tests__/tendersYear.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const request = require('supertest');
const app = 'https://minas-cultura-api.onrender.com';

describe('Testes do Endpoint de Licitações Anuais', () => {
it('Deve retornar a licitação referente ao ano fornecido', async () => {
const year = '2023';

const res = await request(app)
.get(`/tenders/year?year=${year}`)
.expect('Content-Type', /json/)
.expect(200);

expect(res.status).toBe(200);
expect(res.body).toBeDefined();
expect(Array.isArray(res.body)).toBe(true);

res.body.forEach(tender => {
expect(tender).toHaveProperty('committed_value');
expect(tender).toHaveProperty('liquidated_value');
expect(tender).toHaveProperty('paid_value');
expect(tender).toHaveProperty('year');
});
});

it('Deve retornar um erro quando a data não for fornecida', async () => {
const year = null;

const res = await request(app)
.get(`/tenders/year?year=${year}`);

expect(res.status).toBe(400);
expect(res.body).toBeDefined();
});
});
16 changes: 16 additions & 0 deletions backend/src/routes/healthRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const express = require('express');
const router = express.Router();

router.get('/', async (_req, res) => {
const healthcheck = {
message: 'OK'
};
try {
res.send(healthcheck);
} catch (error) {
healthcheck.message = error;
res.status(503).send();
}
});

module.exports = router;
15 changes: 10 additions & 5 deletions backend/src/index.js → backend/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ const cors = require('cors');
const app = express();
const port = 5000;

const citiesRoutes = require('./routes/citiesRoutes');
// * [Deprecated] *
// const citiesRoutes = require('./routes/citiesRoutes');
// const unitsRoutes = require('./routes/unitsRoutes');

const tendersMonthRoutes = require('./routes/tendersMonthRoutes');
const tendersYearRoutes = require('./routes/tendersYearRoutes');
const tendersRoutes = require('./routes/tendersRoutes');
const unitsRoutes = require('./routes/unitsRoutes');
const healthRoutes = require('./routes/healthRoutes');

app.use(cors())

app.use('/cities', citiesRoutes)
// * [Deprecated] *
// app.use('/cities', citiesRoutes)
// app.use('/units', unitsRoutes)

app.use('/tenders', tendersMonthRoutes)
app.use('/tenders/year', tendersYearRoutes)
app.use('/units', unitsRoutes)
app.use('/health', healthRoutes)

app.listen(port, () => {
console.log(`API running at http://localhost:${port}`)
Expand Down
28 changes: 19 additions & 9 deletions backend/src/services/tendersMonthService.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@ async function getTendersByMonth(start, end) {
const endYear = Math.floor(end / 100);
const endMonth = end % 100;

const { data, error } = await supabase
.from('tendersmonth')
.select('*')
.or(
`and(year.eq.${startYear},month.gte.${startMonth}),` +
`and(year.gt.${startYear},year.lt.${endYear}),` +
`and(year.eq.${endYear},month.lte.${endMonth})`
);
let query = supabase.from('tendersmonth').select('*');

if (startYear === endYear) {
query = query
.eq('year', startYear)
.gte('month', startMonth)
.lte('month', endMonth);
} else {
query = query
.or(
`and(year.eq.${startYear},month.gte.${startMonth}),` +
`and(year.eq.${endYear},month.lte.${endMonth}),` +
`and(year.gt.${startYear},year.lt.${endYear})`
);
}

const { data, error } = await query;

if (error) {
throw new Error(error.message);
Expand All @@ -24,4 +33,5 @@ async function getTendersByMonth(start, end) {

module.exports = {
getTendersByMonth,
};
};

12 changes: 9 additions & 3 deletions docs/Arquitetura/Arquitetura.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ O deploy do frontend foi realizado na **Vercel**, uma plataforma otimizada para

## Backend

O backend do projeto é uma **API REST** desenvolvida com **Express.js**, um framework minimalista para Node.js. Essa API é responsável por gerenciar as requisições dos usuários e interagir com o banco de dados **PostgreSQL**. Utilizamos **pgAdmin** para facilitar a administração e o gerenciamento do banco de dados.
O backend do projeto é uma **API REST** desenvolvida com [**Express.js**](https://expressjs.com/), um framework minimalista para [**Node.js**](https://nodejs.org/). Esta API é responsável por gerenciar as requisições dos usuários e interagir com o banco de dados [**PostgreSQL**](https://www.postgresql.org/).

Inicialmente, utilizamos um container de **PostgreSQL** junto com o [**pgAdmin**](https://www.pgadmin.org/) para facilitar a administração e o gerenciamento do banco de dados durante a fase inicial de desenvolvimento. Posteriormente, migramos para o [**Supabase**](https://supabase.com/), que oferece uma solução gerenciada de PostgreSQL com funcionalidades adicionais para desenvolvimento de aplicações web.

### Deploy do Backend

O deploy da nossa API foi realizado no **Render**, uma plataforma de cloud que oferece deploys automáticos a partir de repositórios Git, suporte a SSL automático e escalabilidade fácil. O Render foi escolhido por sua simplicidade e robustez, permitindo que a API esteja sempre disponível e pronta para responder às requisições com alta performance.
O deploy da nossa API foi realizado no [**Render**](https://render.com/), uma plataforma de cloud que oferece **deploys automáticos** a partir de repositórios Git, suporte a **SSL automático** e **escalabilidade fácil**. Escolhemos o Render por sua simplicidade e robustez. No entanto, enfrentamos alguns desafios, pois o plano gratuito do Render limita o tempo em que a aplicação permanece ativa quando não está em uso, resultando em períodos de inatividade (downtime).

Para contornar essa limitação, utilizamos outra plataforma chamada [**BetterStack**](https://betterstack.com/), que monitora a aplicação em intervalos regulares. Implementamos um endpoint específico `/health` que verifica a saúde da aplicação a cada 10 minutos. Dessa forma, garantimos que a API esteja sempre disponível e pronta para responder às requisições, mantendo alta performance e evitando o downtime.

## Banco de Dados

Expand Down Expand Up @@ -53,14 +57,16 @@ Abaixo estão as principais tecnologias que compõem o projeto:

- **Linguagens de Programação**: [Python](https://docs.python.org/3/), [JavaScript](https://www.javascript.com/), [TypeScript](https://www.typescriptlang.org/)
- **Framework Web**: [Next.js](https://nextjs.org/)
- **Banco de Dados**: [PostgreSQL](https://www.postgresql.org/)
- **Banco de Dados**: [PostgreSQL](https://www.postgresql.org/) e [Supabase](https://supabase.com/)
- **Ferramentas de Coleta de Dados**: Framework [Scrapy](https://scrapy.org/) com auxílio das bibliotecas [Beautiful Soup](https://beautiful-soup-4.readthedocs.io/en/latest/) e [Selenium](https://www.selenium.dev/)
- **Testes**: [Jest](https://jestjs.io/pt-BR/) e [Supertest](https://github.com/ladjs/supertest)
- **Tecnologias Adicionais**: [Docker](https://www.docker.com/), [Express](https://expressjs.com/), [React](https://react.dev/), [Tailwind CSS](https://tailwindcss.com/)

## 📁 Histórico de Versão

| Versão | Data | Descrição | Autor |
| :----: | :--------: | :------------------------------------------------------------------------------: | :-------------: |
| 6.0 | 03/09/2024 | Detalhamento do backend | Isaac Batista|
| 5.0 | 02/09/2024 | Reestruturação da arquitetura | Gabriel Scheidt|
| 4.0 | 16/08/2024 | Reestruturação da arquitetura | Gabriel Scheidt|
| 3.0 | 25/04/2024 | Reestruturando Documento de Arquitetura | Rafael Carvalho |
Expand Down
20 changes: 13 additions & 7 deletions docs/Como executar/backend/Executar a API.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
## **Guia de Utilização da API de Licitações Culturais de Minas Gerais**
# Como utilizar o Back-end do projeto

### **Visão Geral**

Esta API permite consultar informações relacionadas a licitações culturais de Minas Gerais. A API foi desenvolvida utilizando Express.js e está organizada em três camadas principais: `models`, `services` e `controllers`. Abaixo, você encontrará a descrição dos endpoints disponíveis e como utilizá-los.
Esta API permite consultar informações sobre licitações culturais em Minas Gerais. Embora o código-fonte da API esteja disponível em nosso repositório, o acesso ao banco de dados principal é restrito. No entanto, você pode acessar a API publicamente através da seguinte URL: [https://minas-cultura-api.onrender.com](https://minas-cultura-api.onrender.com).


A API foi desenvolvida utilizando Express.js e está organizada em três camadas principais: `models`, `services` e `controllers`. Abaixo, você encontrará a descrição dos endpoints disponíveis e como utilizá-los.

### **Estrutura da API**

A API está localizada no diretório `backend/src/`, e é composta por três endpoints principais:

1. **/tenders**
2. **/tenders/year**
3. **/health**

### **Endpoints**

#### **1. Consultar Licitações Mensais: `/tenders`**

- **Descrição:** Retorna uma lista de licitações baseadas nos parâmetros de data inicial e final.
- **URL:** `http://localhost:5000/tenders?start=201501&end=201502`
- **URL:** `https://minas-cultura-api.onrender.com/tenders?start=201501&end=201502`
- **Método:** `GET`
- **Parâmetros:**
- `start`: Representa o início do período de consulta no formato `AAAAMM` (ano/mês). Por exemplo, `201501` corresponde a janeiro de 2015.
Expand All @@ -25,15 +29,17 @@ A API está localizada no diretório `backend/src/`, e é composta por três end
#### **2. Consultar Licitações Anuais: `/tenders/year`**

- **Descrição:** Retorna os valores totais empenhados, liquidados e pagos no ano informado no parâmetro "year".
- **URL:** `http://localhost:5000/tenders/year?year=2024`
- **URL:** `https://minas-cultura-api.onrender.com/tenders/year?year=2024`
- **Método:** `GET`
- **Parâmetros:**
- `year`: Representa o ano de consulta no formato `AAAA` (ano). Por exemplo, `year=2024` retornará o total de licitações empenhadas, liquidadas e pagas no ano de 2024.

#### **3. Consultar a saúde da aplicação: `/health`**

- **Descrição:** Retorna a mensagem "OK" em caso de sucesso na conexão com a api, este endpoint é necessário para monitorar a estabilidade do sistema.
- **URL:** `https://minas-cultura-api.onrender.com/health`
- **Método:** `GET`

### **Considerações Importantes**

- **Porta:** A API está configurada para rodar na porta `5000`.
---

Siga este guia para consultar e explorar as licitações culturais de Minas Gerais. Caso tenha dúvidas ou precise de suporte adicional, entre em contato com o time de desenvolvimento.
Loading
Loading