Skip to content

Commit 0e38353

Browse files
Send boletim and set empresa as partner routes
1 parent 3f4043e commit 0e38353

File tree

9 files changed

+167
-123
lines changed

9 files changed

+167
-123
lines changed

ToDo.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
- [ ] conversa professor
88
- [ ] conversa empresa
99
- [ ] exportar currículo
10-
- [ ] colocar o boletim
10+
- [x] colocar o boletim
1111

1212
## Funcionário
13-
- [ ] classificar empresa como parceira
14-
- [ ] Ver empresas
13+
- [x] classificar empresa como parceira
14+
- [ ] Validar boletim
1515

1616
## Professor
1717
- [ ] Mandar mensagem aluno
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- CreateTable
2+
CREATE TABLE `boletins` (
3+
`id` VARCHAR(191) NOT NULL,
4+
`alunoId` VARCHAR(191) NOT NULL,
5+
`link` VARCHAR(191) NOT NULL,
6+
`caminho` VARCHAR(191) NOT NULL,
7+
`status` ENUM('EM_ANALISE', 'RECUSADO', 'APROVADO') NOT NULL DEFAULT 'EM_ANALISE',
8+
9+
PRIMARY KEY (`id`)
10+
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
11+
12+
-- AddForeignKey
13+
ALTER TABLE `boletins` ADD CONSTRAINT `boletins_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

server/prisma/schema.prisma

+28-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ model Aluno {
2424
tentativasRestantes Int @default(5)
2525
validated Boolean @default(false)
2626
turmas AlunoTurma[]
27+
boletins Boletim[]
2728
atividades AlunoAtividade[]
2829
cursosExtracurriculares Extracurricular[]
2930
vinculosAluno Vinculo[] @relation("AlunoVinculo")
@@ -134,12 +135,29 @@ model AlunoTurma {
134135
@@map("alunos_turmas")
135136
}
136137

138+
model Boletim {
139+
id String @id @default(uuid())
140+
alunoId String @default(uuid())
141+
link String
142+
caminho String
143+
status SituacaoBoletim @default(EM_ANALISE)
144+
aluno Aluno @relation(fields: [alunoId], references: [id])
145+
146+
@@map("boletins")
147+
}
148+
149+
enum SituacaoBoletim {
150+
EM_ANALISE
151+
RECUSADO
152+
APROVADO
153+
}
154+
137155
model AlunoAtividade {
138-
alunoId String @default(uuid())
139-
atividadeId String @default(uuid())
140-
mencao Mencao
141-
aluno Aluno @relation(fields: [alunoId], references: [id])
142-
atividade Atividade @relation(fields: [atividadeId], references: [id])
156+
alunoId String @default(uuid())
157+
atividadeId String @default(uuid())
158+
mencao Mencao
159+
aluno Aluno @relation(fields: [alunoId], references: [id])
160+
atividade Atividade @relation(fields: [atividadeId], references: [id])
143161
144162
@@id([alunoId, atividadeId])
145163
@@map("alunos_atividades")
@@ -250,15 +268,15 @@ enum Cargo {
250268
}
251269

252270
model Atividade {
253-
id String @id @default(uuid())
271+
id String @id @default(uuid())
254272
title String
255-
descricao String @db.VarChar(1000)
273+
descricao String @db.VarChar(1000)
256274
professorId String
257275
imagem String?
258276
alunos AlunoAtividade[]
259-
professor Professor @relation(fields: [professorId], references: [id])
260-
createdAt DateTime @default(now())
261-
updatedAt DateTime @updatedAt
277+
professor Professor @relation(fields: [professorId], references: [id])
278+
createdAt DateTime @default(now())
279+
updatedAt DateTime @updatedAt
262280
263281
@@map("atividades")
264282
}

server/src/modules/controllers/funcionarioControllers.ts

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { RecoveryFuncionarioUseCase } from "../services/funcionario/RecoveryUseC
66
import { ValidateRecoveryUseCase } from "../services/funcionario/ValidateRecoveryUseCase";
77
import { RefreshTokenUseCase } from "../services/funcionario/RefreshTokenUseCase";
88
import { RegisterVagaUseCase } from "../services/funcionario/RegisterVagasUseCase";
9+
import { SetEmpresaParceiraUseCase } from "../services/funcionario/SetAsParceiraUseCase";
10+
import { SetEmpresaParceiraDTO } from "../interfaces/funcionarioDTOs";
911

1012
export class InitFuncionarioController {
1113
async handle(req: Request, res: Response) {
@@ -116,4 +118,16 @@ export class RegisterVagaController {
116118

117119
return res.status(201).json(result);
118120
}
121+
}
122+
123+
export class FuncionarioController {
124+
async handle(req: Request, res: Response) {
125+
const funcionarioId = req.body.funcionario.id;
126+
const { emailEmpresa }: SetEmpresaParceiraDTO = req.body;
127+
128+
const setEmpresaParceiraUseCase = new SetEmpresaParceiraUseCase();
129+
130+
const result = await setEmpresaParceiraUseCase.execute({ funcionarioId, emailEmpresa });
131+
return res.status(200).json(result);
132+
}
119133
}

server/src/modules/interfaces/funcionarioDTOs.ts

+5
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,9 @@ export interface RegisterVagaDTO {
4545
status: string;
4646
curso: string;
4747
descricao: string;
48+
}
49+
50+
export interface SetEmpresaParceiraDTO {
51+
funcionarioId: string;
52+
emailEmpresa: string;
4853
}
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,68 @@
1-
// import puppeteerNormal from 'puppeteer';
2-
// import puppeteer from 'puppeteer-extra';
3-
// import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha';
4-
// import fs from 'fs';
5-
// import path from 'path';
6-
// import pdf from 'pdf-parse';
7-
import axios from 'axios';
8-
// import { getExecutablePath } from 'puppeteerNormal';
9-
1+
import fs from 'fs';
2+
import path from 'path';
3+
import pdf from 'pdf-parse';
104
import { prisma } from "../../../prisma/client";
115
import { SendNotasDTO } from "../../interfaces/alunoDTOs";
126
import { AppError } from "../../../errors/error";
137
import { clearUploads } from '../shared/helpers/helpers';
14-
15-
// Configure o plugin Recaptcha
16-
// puppeteer.use(
17-
// RecaptchaPlugin({
18-
// provider: {
19-
// id: '2captcha',
20-
// token: process.env.CAPTCHA2_ID || '', // Certifique-se de que o token está definido
21-
// },
22-
// })
23-
// );
8+
import { uploadToMinio } from "../../../minioService";
249

2510
export class SendBoletimUseCase {
26-
async execute({ alunoId, boletim }: SendNotasDTO) {
27-
if (!alunoId) {
28-
throw new AppError('ID do aluno não fornecido.');
11+
async execute({ alunoId, boletim }: SendNotasDTO) {
12+
if (!alunoId) {
13+
throw new AppError('ID do aluno não fornecido.');
14+
}
15+
16+
if (!boletim || !boletim.path) {
17+
throw new AppError('Arquivo do boletim não fornecido.');
18+
}
19+
20+
const aluno = await prisma.aluno.findUnique({
21+
where: {
22+
id: alunoId,
23+
},
24+
});
25+
26+
if (!aluno) {
27+
throw new AppError('Aluno não encontrado.');
28+
}
29+
30+
const boletimPath = path.resolve(boletim.path);
31+
const boletimBuffer = fs.readFileSync(boletimPath);
32+
33+
const link = await this.extractAuthUrlFromPdf(boletimBuffer);
34+
35+
const bucketName = 'boot';
36+
const objectName = `aluno/${aluno.rm}/boletins/${path.basename(boletim.path)}`;
37+
38+
try {
39+
await uploadToMinio(bucketName, objectName, boletimPath);
40+
41+
await prisma.boletim.create({
42+
data: {
43+
alunoId: aluno.id,
44+
link: link,
45+
caminho: objectName,
46+
}
47+
});
48+
49+
await clearUploads();
50+
51+
return { message: 'Boletim enviado e salvo com sucesso!' };
52+
} catch (error) {
53+
throw new AppError(`Erro ao salvar o boletim: ${error}`);
54+
}
2955
}
3056

31-
if (!boletim || !boletim.path) {
32-
throw new AppError('Arquivo do boletim não fornecido.');
33-
}
57+
async extractAuthUrlFromPdf(buffer: Buffer): Promise<string> {
58+
const data = await pdf(buffer);
59+
const text = data.text;
3460

35-
const aluno = await prisma.aluno.findUnique({
36-
where: {
37-
id: alunoId,
38-
},
39-
});
61+
const urlMatch = text.match(/https:\/\/nsa\.cps\.sp\.gov\.br\?a=[a-z0-9-]+/i);
62+
if (!urlMatch) {
63+
throw new AppError('URL de autenticação não encontrado no boletim.');
64+
}
4065

41-
if (!aluno) {
42-
throw new AppError('Aluno não encontrado.');
66+
return urlMatch[0];
4367
}
44-
45-
// const boletimPath = path.resolve(boletim.path);
46-
47-
// const boletimBuffer = fs.readFileSync(boletimPath);
48-
49-
// const authUrl = await this.extractAuthUrlFromPdf(boletimBuffer);
50-
51-
// const browser = await puppeteer.launch({
52-
// headless: false,
53-
// });
54-
55-
56-
// const page = await browser.newPage();
57-
58-
// await page.goto(authUrl);
59-
60-
// setTimeout(async () => {
61-
// const { solved, error } = await page.solveRecaptchas();
62-
// console.log("Here2");
63-
64-
// if (!solved) {
65-
// throw new AppError('Falha ao resolver CAPTCHA: ' + error);
66-
// } else {
67-
// console.log('Captcha resolvido com sucesso, url: ' + authUrl);
68-
// }
69-
70-
// await page.waitForSelector('#btnValidar');
71-
// await page.click('#btnValidar');
72-
// }, 10000);
73-
74-
// const downloadUrl = await page.evaluate(() => {
75-
// const linkElement = document.querySelector('a#downloadLink') as HTMLAnchorElement | null;
76-
// return linkElement ? linkElement.href : '';
77-
// });
78-
79-
80-
// const response = await axios.get(downloadUrl, { responseType: 'arraybuffer' });
81-
// const downloadedFilePath = path.join(__dirname, 'downloads', 'downloaded_boletim.pdf');
82-
// fs.writeFileSync(downloadedFilePath, response.data);
83-
84-
// // Comparar os dois arquivos PDF
85-
// const downloadedBoletimBuffer = fs.readFileSync(downloadedFilePath);
86-
87-
// if (!boletimBuffer.equals(downloadedBoletimBuffer)) {
88-
// throw new AppError("Os arquivos enviados não coincidem.");
89-
// }
90-
91-
// Extrair notas do boletim
92-
// const notas = this.extractNotasFromBoletim(boletimBuffer);
93-
94-
// Fechar o navegador
95-
// await browser.close();
96-
97-
await clearUploads();
98-
99-
}
100-
101-
// async extractAuthUrlFromPdf(buffer: Buffer): Promise<string> {
102-
// const data = await pdf(buffer);
103-
// const text = data.text;
104-
105-
// const urlMatch = text.match(/https:\/\/nsa\.cps\.sp\.gov\.br\?a=[a-z0-9-]+/i);
106-
// if (!urlMatch) {
107-
// throw new AppError('URL de autenticação não encontrado no boletim.');
108-
// }
109-
110-
// return urlMatch[0];
111-
// }
112-
113-
extractNotasFromBoletim(buffer: Buffer) {
114-
return [
115-
// { materia: 'Matemática', nota: 'MB' },
116-
// { materia: 'Português', nota: 'MB' },
117-
];
118-
}
11968
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { prisma } from "../../../prisma/client";
2+
import { SetEmpresaParceiraDTO } from "../../interfaces/funcionarioDTOs";
3+
import { AppError } from "../../../errors/error";
4+
5+
export class SetEmpresaParceiraUseCase {
6+
async execute({ funcionarioId, emailEmpresa }: SetEmpresaParceiraDTO) {
7+
if (!funcionarioId || !emailEmpresa) {
8+
throw new AppError("Parâmetros insuficientes ou inválidos.");
9+
}
10+
11+
const funcionario = await prisma.funcionario.findUnique({
12+
where: {
13+
id: funcionarioId
14+
}
15+
});
16+
17+
if (!funcionario) {
18+
throw new AppError("Funcionário não encontrado.");
19+
}
20+
21+
const empresa = await prisma.empresa.findUnique({
22+
where: {
23+
email: emailEmpresa
24+
}
25+
});
26+
27+
if (!empresa) {
28+
throw new AppError("Empresa não encontrada.");
29+
}
30+
31+
const empresaParceira = await prisma.empresa.update({
32+
where: {
33+
id: emailEmpresa
34+
},
35+
data: {
36+
patrocinador: true
37+
}
38+
});
39+
40+
return empresaParceira;
41+
}
42+
}

server/src/router/routes/funcionario.routes.ts

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ funcionarioRoutes.get("/init", controllers.initFuncionarioController.handle);
1414

1515
funcionarioRoutes.use(funcionarioAuthMiddleware);
1616
funcionarioRoutes.post("/register/vaga", controllers.registerVagaController.handle);
17+
funcionarioRoutes.post("/update/empresa", controllers.registerVagaController.handle);
1718

1819
funcionarioRoutes.get("/auth", (req, res) => {
1920
res.status(200).send("Funcionário autenticado com sucesso.");

server/src/router/routes/imports/funcionario.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import {
55
RecoveryFuncionarioController,
66
ValidateRecoveryController,
77
RefreshTokenController,
8-
RegisterVagaController
8+
RegisterVagaController,
9+
FuncionarioController,
910
} from "../../../modules/controllers/funcionarioControllers";
1011
import {
1112
GetCursosController,
12-
GetEmpresasController
13+
GetEmpresasController,
1314
} from "../../../modules/controllers/sharedControllers";
1415

1516
export const createControllers = () => ({
@@ -21,5 +22,6 @@ export const createControllers = () => ({
2122
refreshTokenController: new RefreshTokenController(),
2223
registerVagaController: new RegisterVagaController(),
2324
getCursosController: new GetCursosController(),
24-
getEmpresasController: new GetEmpresasController()
25+
getEmpresasController: new GetEmpresasController(),
26+
funcionarioController: new FuncionarioController(),
2527
});

0 commit comments

Comments
 (0)