diff --git a/backend/prisma/migrations/20241114215653_especie_opcional/migration.sql b/backend/prisma/migrations/20241114215653_especie_opcional/migration.sql new file mode 100644 index 00000000..319eccfa --- /dev/null +++ b/backend/prisma/migrations/20241114215653_especie_opcional/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Projeto" ALTER COLUMN "especie" DROP NOT NULL; diff --git a/backend/prisma/migrations/20241114232428_mudando_tipo/migration.sql b/backend/prisma/migrations/20241114232428_mudando_tipo/migration.sql new file mode 100644 index 00000000..4b0fe024 --- /dev/null +++ b/backend/prisma/migrations/20241114232428_mudando_tipo/migration.sql @@ -0,0 +1,11 @@ +-- AlterTable +ALTER TABLE "Executor" ALTER COLUMN "codigo" SET DATA TYPE TEXT; + +-- AlterTable +ALTER TABLE "Repassador" ALTER COLUMN "codigo" SET DATA TYPE TEXT; + +-- AlterTable +ALTER TABLE "Tomador" ALTER COLUMN "codigo" SET DATA TYPE TEXT; + +-- AddForeignKey +ALTER TABLE "Tipo" ADD CONSTRAINT "Tipo_idEixo_fkey" FOREIGN KEY ("idEixo") REFERENCES "Eixo"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/backend/prisma/migrations/20241114233015_int_codigo/migration.sql b/backend/prisma/migrations/20241114233015_int_codigo/migration.sql new file mode 100644 index 00000000..f40b369b --- /dev/null +++ b/backend/prisma/migrations/20241114233015_int_codigo/migration.sql @@ -0,0 +1,19 @@ +/* + Warnings: + + - Changed the type of `codigo` on the `Executor` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + - Changed the type of `codigo` on the `Repassador` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + - Changed the type of `codigo` on the `Tomador` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + +*/ +-- AlterTable +ALTER TABLE "Executor" DROP COLUMN "codigo", +ADD COLUMN "codigo" INTEGER NOT NULL; + +-- AlterTable +ALTER TABLE "Repassador" DROP COLUMN "codigo", +ADD COLUMN "codigo" INTEGER NOT NULL; + +-- AlterTable +ALTER TABLE "Tomador" DROP COLUMN "codigo", +ADD COLUMN "codigo" INTEGER NOT NULL; diff --git a/backend/prisma/migrations/20241114233505_big_int/migration.sql b/backend/prisma/migrations/20241114233505_big_int/migration.sql new file mode 100644 index 00000000..52e111e0 --- /dev/null +++ b/backend/prisma/migrations/20241114233505_big_int/migration.sql @@ -0,0 +1,8 @@ +-- AlterTable +ALTER TABLE "Executor" ALTER COLUMN "codigo" SET DATA TYPE BIGINT; + +-- AlterTable +ALTER TABLE "Repassador" ALTER COLUMN "codigo" SET DATA TYPE BIGINT; + +-- AlterTable +ALTER TABLE "Tomador" ALTER COLUMN "codigo" SET DATA TYPE BIGINT; diff --git a/backend/prisma/migrations/20241114234133_a/migration.sql b/backend/prisma/migrations/20241114234133_a/migration.sql new file mode 100644 index 00000000..8087847c --- /dev/null +++ b/backend/prisma/migrations/20241114234133_a/migration.sql @@ -0,0 +1,2 @@ +-- DropForeignKey +ALTER TABLE "Tipo" DROP CONSTRAINT "Tipo_idEixo_fkey"; diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 68e34113..f1de481d 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -20,7 +20,7 @@ model Projeto { dataInicialEfetiva DateTime? dataFinalEfetiva DateTime? dataCadastro DateTime - especie String + especie String? natureza String situacao String uf String diff --git a/backend/src/controllers/schemas/ProjetosRequestSchema.ts b/backend/src/controllers/schemas/ProjetosRequestSchema.ts index 934edd15..f02a3981 100644 --- a/backend/src/controllers/schemas/ProjetosRequestSchema.ts +++ b/backend/src/controllers/schemas/ProjetosRequestSchema.ts @@ -3,8 +3,8 @@ import z from "zod"; export const GetProjetosRequestSchema = z.object({ page: z.string().optional(), pageSize: z.string().optional(), - nome: z.string().optional(), situacao: z.string().optional(), - sortBy: z.enum(['nome', 'situacao', 'createdAt']).optional(), + uf: z.string().optional(), + sortBy: z.enum(['situacao', 'uf', 'createdAt']).optional(), order: z.enum(['asc', 'desc']).optional(), }) diff --git a/backend/src/database/index.ts b/backend/src/database/index.ts index 7c5f2b96..e313cdf6 100644 --- a/backend/src/database/index.ts +++ b/backend/src/database/index.ts @@ -4,20 +4,49 @@ import { PrismaClient } from '@prisma/client'; export const prisma = new PrismaClient(); async function fetchAndSaveProjects() { - try { - const response = await axios.get('https://api.obrasgov.gestao.gov.br/obrasgov/api/projeto-investimento?pagina=0&tamanhoDaPagina=10'); - if (response.status !== 200) { - throw new Error(`Erro ao buscar dados: ${response.statusText}`); - } + let pagina = 0; + const tamanhoDaPagina = 100; // Ajuste este valor conforme a capacidade da API + let hasMoreData = true; + let uf = "DF"; - const { content: projetos } = response.data; + try { + while (hasMoreData) { + console.log(`Buscando página ${pagina}...`); - for (const projeto of projetos) { - const existingProject = await prisma.projeto.findUnique({ - where: { id: projeto.idUnico } + // Faz a requisição para a API externa + const response = await axios.get('https://api.obrasgov.gestao.gov.br/obrasgov/api/projeto-investimento', { + params: { + pagina, + tamanhoDaPagina, + uf, + } }); - if (!existingProject) { + if (response.status !== 200) { + throw new Error(`Erro ao buscar dados: ${response.statusText}`); + } + + const { content: projetos } = response.data; + + // Se não há mais projetos, encerre o loop + if (projetos.length === 0) { + hasMoreData = false; + break; + } + + // Salvar ou atualizar cada projeto no banco de dados + for (const projeto of projetos) { + // Verifica se o projeto já existe no banco de dados + const existingProject = await prisma.projeto.findUnique({ + where: { id: projeto.idUnico } + }); + + // Se o projeto já existe, pule para o próximo + if (existingProject) { + console.log(`Projeto ${projeto.nome} já existe, ignorando.`); + continue; + } + await prisma.projeto.create({ data: { id: projeto.idUnico, @@ -32,7 +61,7 @@ async function fetchAndSaveProjects() { dataInicialEfetiva: projeto.dataInicialEfetiva ? new Date(projeto.dataInicialEfetiva) : null, dataFinalEfetiva: projeto.dataFinalEfetiva ? new Date(projeto.dataFinalEfetiva) : null, dataCadastro: new Date(projeto.dataCadastro), - especie: projeto.especie, + especie: projeto.especie ?? null, natureza: projeto.natureza, situacao: projeto.situacao, uf: projeto.uf, @@ -82,9 +111,10 @@ async function fetchAndSaveProjects() { } }); console.log(`Projeto ${projeto.nome} salvo com sucesso!`); - } else { - console.log(`Projeto ${projeto.nome} já existe, ignorando.`); } + + // Incrementa para a próxima página + pagina++; } } catch (error) { console.error('Erro ao buscar e salvar projetos:', error); @@ -93,4 +123,5 @@ async function fetchAndSaveProjects() { } } -fetchAndSaveProjects() \ No newline at end of file +// Sincroniza os dados a cada hora +fetchAndSaveProjects(); diff --git a/backend/src/repositories/prisma/PrismaProjetosRepository.ts b/backend/src/repositories/prisma/PrismaProjetosRepository.ts index 0d71f607..ee8251e5 100644 --- a/backend/src/repositories/prisma/PrismaProjetosRepository.ts +++ b/backend/src/repositories/prisma/PrismaProjetosRepository.ts @@ -5,27 +5,28 @@ import { prisma } from "@/database"; export class PrismaProjetosRepository implements ProjetosRepository { async find (params: FindProjetosParams): Promise { let where: Prisma.ProjetoWhereInput = { - nome: { - contains: params.where?.nome?.like, - equals: params.where?.nome?.equals, - mode: params.where?.nome?.mode + situacao: { + contains: params.where?.situacao?.like, + equals: params.where?.situacao?.equals, + mode: params.where?.situacao?.mode + }, + uf: { + contains: params.where?.uf?.like, + equals: params.where?.uf?.equals, + mode: params.where?.uf?.mode }, - situacao: params.where?.situacao, } const projetos = await prisma.projeto.findMany({ where, - orderBy: { [params.sortBy ?? "nome"]: params.order}, + orderBy: { [params.sortBy ?? "uf"]: params.order}, skip: params.offset, take: params.limit, include: { - eixos: params.include?.eixos, - executores: params.include?.executores, - repassadores: params.include?.repassadores, - tomadores: params.include?.tomadores, - tipos: params.include?.tipos, - geometrias: params.include?.geometrias, - fontesDeRecurso: params.include?.fontesDeRecurso + eixos: true, + tipos: true, + geometrias: true, + fontesDeRecurso: true } }) diff --git a/backend/src/repositories/projetoRepository.ts b/backend/src/repositories/projetoRepository.ts index 883d8b66..41a9493e 100644 --- a/backend/src/repositories/projetoRepository.ts +++ b/backend/src/repositories/projetoRepository.ts @@ -1,17 +1,21 @@ import { Projeto } from "@prisma/client"; export interface ProjetoWhereParams { - nome?: { + situacao?: { + like: string; + equals?: string; + mode?: "default" | "insensitive" + } + uf?: { like: string; equals?: string; mode?: "default" | "insensitive" } - situacao?: string; } export interface FindProjetosParams { where?: ProjetoWhereParams - sortBy?: "nome" | "situacao" | "createdAt" + sortBy?: "situacao" | "uf" | "createdAt" order?: "asc" | "desc" limit?: number offset?: number diff --git a/backend/src/use-cases/ProjetosService.ts b/backend/src/use-cases/ProjetosService.ts index 06d65b23..3b4e7b09 100644 --- a/backend/src/use-cases/ProjetosService.ts +++ b/backend/src/use-cases/ProjetosService.ts @@ -3,9 +3,9 @@ import { ProjetosRepository, ProjetoWhereParams } from "@/repositories/projetoRe interface GetProjetosWithPaginationParams { page?: number pageSize?: number - nome?: string situacao?: string - sortBy?: "nome" | "situacao" | "createdAt" + uf?: string + sortBy?: "situacao" | "uf" | "createdAt" order?: "asc" | "desc" } @@ -13,16 +13,16 @@ export class ProjetosService { constructor(private readonly projetosRepository: ProjetosRepository) {} async getAllProjetosPaginated(params: GetProjetosWithPaginationParams) { - const { nome, situacao, page = 1, pageSize = 10, sortBy, order } = params + const { situacao, uf, page = 1, pageSize = 10, sortBy, order } = params const limit = pageSize const offset = (page - 1) * limit const where: ProjetoWhereParams = {} - if (nome) where.nome = { like: nome, mode: 'insensitive' } - if (situacao) where.situacao = situacao - + if (situacao) where.situacao = { like: situacao, mode: 'insensitive' } + if (uf) where.uf = { like: uf, mode: 'insensitive' } + const projetos = await this.projetosRepository.find({ where, sortBy,