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

Feature/external application2 #186

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fd325b7
:construction: Feat (jobs,users,candidacy): Criação da entidade candi…
leticiazalasik Sep 28, 2024
9cb2da0
:sparkles: Feat (candidacy-entity, candidacy-repository, candidacy-st…
leticiazalasik Oct 7, 2024
4ec73c0
:bug: Fix (jobs-entity): Correções da ligação de tabelas.
leticiazalasik Oct 7, 2024
ebdf7d7
:bug: Fix (candidacy-entity): Padronização do nome do atributo para job.
leticiazalasik Oct 7, 2024
b3ad650
:sparkles: Feat (candidacy-entity, candidacy-repository) optado pelo …
leticiazalasik Oct 7, 2024
f2d2d2f
:sparkles: Feat Atualização do repositório local
leticiazalasik Oct 8, 2024
ae482a4
:sparkles: Feat Atualização do repositório local
leticiazalasik Oct 8, 2024
363a543
:sparkles: Feat Atualização do repositório local
leticiazalasik Oct 9, 2024
2bd0727
Update README.md
leticiazalasik Nov 1, 2024
79fa4d3
:ok_hand: feat: Acrescentando o campo status na entidade application.
leticiazalasik Nov 9, 2024
e5857d4
:sparkles: feat: feat: Criação da service que busca o histórico de v…
leticiazalasik Nov 9, 2024
dbea464
:sparkles: feat: feat: Criação da controller que tem o endpoint get.
leticiazalasik Nov 9, 2024
e382ed6
feat(endpoint): Criar endpoint para atualizar candidatura
joselazarojunior Nov 23, 2024
56d95c1
:construction: Fix: (applications.entity) Indíces na chave estrangei…
leticiazalasik Dec 4, 2024
4461b13
:construction: Feat: (applications.entity, application-status.enum) …
leticiazalasik Dec 4, 2024
9bfc59b
:construction: Feat: (applicationHistory.service, application-histor…
leticiazalasik Dec 10, 2024
90507ab
fix(endpoint): Criar endpoint para atualizar candidatura
joselazarojunior Dec 13, 2024
9d48113
fix(endpoint): Criar endpoint para atualizar candidatura
joselazarojunior Dec 13, 2024
32efa36
:construction: Fix: (applicationHistory.controller, application-hist…
leticiazalasik Dec 17, 2024
c9009f8
Merge branch 'feature/external-application2' of https://github.com/le…
leticiazalasik Dec 17, 2024
00eee0b
:construction: Fix: mudança na resposta de getAppStatus, cpnsulta ma…
leticiazalasik Dec 17, 2024
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
44 changes: 40 additions & 4 deletions src/app.controller.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

Verifique a separação das rotas.

Verifique no status, se precisa de enum.

Utilize decorators pra validar os parametros da rota.

Crie exceções personalizadas (tratamento de erros)

Verifique se o @ApiOperation não está sendo utilizada, utilize outra pra documentar melhor as rotas no swagger.

Padronize a respota pra seguir o mesmo formato das outras rotas, retornando assim o objeto como status e data.

Copy link
Contributor

Choose a reason for hiding this comment

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

Verifique a separação das rotas.
Feito!

Verifique no status, se precisa de enum.

  • Criado status.enum.ts :
    IN_PROGRESS = 'em andamento',
    CLOSED = 'encerrada',
    NOT_INTERESTED = 'sem interesse',

Utilize decorators pra validar os parametros da rota.
Criado update-status.dto.ts
ءء
Crie exceções personalizadas (tratamento de erros)
Criados os arquivos de custom exception:
bad-request.exception.ts
not-found.exception.ts

Verifique se o @ApiOperation não está sendo utilizada, utilize outra pra documentar melhor as rotas no swagger.
Atualizado para utilizar os decorators:

  • @ApiResponse,
  • @ApiParam,
    e @ApiBody

Padronize a resposta pra seguir o mesmo formato das outras rotas, retornando assim o objeto como status e data.
Padronizado. Retornando um objeto com status e data.

Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { Controller, Get, Req, Res } from '@nestjs/common';
import {
Controller,
Get,
Req,
Res,
Patch,
Param,
Body,
NotFoundException,
BadRequestException,
HttpCode,
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { AppService } from './app.service';
import { SwaggerHealthCheck } from './shared/Swagger/decorators/app/health-check.swagger.decorator';

import { Request, Response } from 'express';

@ApiTags('Status')
Expand All @@ -24,8 +34,34 @@ export class AppController {
@ApiOperation({
summary: 'Retorna status dos serviços de email e banco de dados',
})
async getHealthCheck(@Res() res: Response){
const {status, data} = await this.appService.getHealthCheck();
async getHealthCheck(@Res() res: Response) {
const { status, data } = await this.appService.getHealthCheck();
return res.status(status).send(data);
}

@Patch(':applicationId')
@HttpCode(200)
async updateStatus(
@Param('userId') userId: string,
@Param('applicationId') applicationId: string,
@Body('status') status: string,
) {
if (!status) {
throw new BadRequestException('Novo status é obrigatório');
}

const application = await this.appService.updateStatus(
userId,
applicationId,
status,
);

if (!application) {
throw new NotFoundException(
'Candidatura não encontrada ou não pertence ao usuário',
);
}

return { message: 'Status atualizado com sucesso', application };
}
}
70 changes: 44 additions & 26 deletions src/app.service.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

Verifique se a resposta do getAppStatus é suficiente.

getHealthCheck: Consulta eficiente seria verificar a conexão com o BD ou buscar um unico registro. Pq a consulta atual busca todos mas apenas verifica se o resultado é null ou indefinid.

databaseStatus e mailerStatus: crie enums pra represetar os status "OK" e "DOWN", assim torna o código mais claro

updateStatus: o user_id está sendo usado mas não está sendo validado.

status: definir um enum

Lançar exceções especificas quando não for encontrada candidatura ou até mesmo status for inválido.

Verifique a possibilidade de criar serviços separados pra cada área, assim melhora a organização.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Olá, tentei fazer isso tudo, mas precisa de correção, principalmente na divisão de serviços e não fiz enums pra represetar os status "OK" e "DOWN", fiz diretamente no app pois achei que já tinha muit coisa separada.

Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,86 @@ import { MailService } from './modules/mails/mail.service';
import { UserRepository } from './modules/user/repository/user.repository';
import { PageOptionsDto } from './shared/pagination';
import { Order } from './shared/pagination';
import { InjectRepository } from '@nestjs/typeorm';
import { ApplicationEntity } from './database/entities/applications.entity';
import { Repository } from 'typeorm';

@Injectable()
export class AppService {
constructor(
private mailService: MailService,
private userRepository: UserRepository
){}
private userRepository: UserRepository,
@InjectRepository(ApplicationEntity)
private applicationRepository: Repository<ApplicationEntity>,
) {}

getAppStatus(baseUrl: string) {
return `<div style=text-align:center><a target="_blank" href="https://www.linkedin.com/company/soujunior/"><svg font-family="Times New Roman" font-size="16" height="299.96" viewBox="0 0 854 300" width="854.56" xmlns="http://www.w3.org/2000/svg" style="width:854.56px; height:299.96px; font-family:'Times New Roman'; font-size:16px; position:relative; z-index:1" xmlns:xlink="http://www.w3.org/1999/xlink"><style>.text {font-size: 90px;font-weight: 700;font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;}.desc {font-size: 20px;font-weight: 500;font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;}.text, .desc {animation: fadeIn 1.2s ease-in-out forwards;}@keyframes fadeIn { from {opacity: 0; } to {opacity: 1; }};</style><g transform="translate(427, 150) scale(1, 1) translate(-427, -150)"><path d="" fill="#2088f2" opacity="0.4"><animate attributeName="d" begin="0s" calcmod="spline" dur="20s" keySplines="0.2 0 0.2 1;0.2 0 0.2 1;0.2 0 0.2 1" keyTimes="0;0.333;0.667;1" repeatCount="indefinite" values="M0 0L 0 220Q 213.5 260 427 230T 854 255L 854 0 Z;M0 0L 0 245Q 213.5 260 427 240T 854 230L 854 0 Z;M0 0L 0 265Q 213.5 235 427 265T 854 230L 854 0 Z;M0 0L 0 220Q 213.5 260 427 230T 854 255L 854 0 Z" /></path><path d="" fill="#2088f2" opacity="0.4"><animate attributeName="d" begin="-10s" calcmod="spline" dur="20s" keySplines="0.2 0 0.2 1;0.2 0 0.2 1;0.2 0 0.2 1" keyTimes="0;0.333;0.667;1" repeatCount="indefinite" values="M0 0L 0 235Q 213.5 280 427 250T 854 260L 854 0 Z;M0 0L 0 250Q 213.5 220 427 220T 854 240L 854 0 Z;M0 0L 0 245Q 213.5 225 427 250T 854 265L 854 0 Z;M0 0L 0 235Q 213.5 280 427 250T 854 260L 854 0 Z" /></path></g><text alignment-baseline="middle" class="text" stroke="#none" stroke-width="1" text-anchor="middle" x="50%" y="38%" style="font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; font-size:90px; font-weight:700; alignment-baseline:middle; fill:#ffffff; stroke-width:1; text-anchor:middle">Sou Junior</text><text alignment-baseline="middle" class="desc" text-anchor="middle" x="52%" y="61%" style="font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; font-size:20px; font-weight:500; alignment-baseline:middle; fill:#ffffff; text-anchor:middle">Projeto Opensource para melhorar o match entre os profissionais Juniors e Empresas!</text></svg></a></div>`;
}

async getHealthCheck(){
async getHealthCheck() {
const databaseStatus = await this.checkDatabase();
const mailerStatus = await this.checkEmail();
const data = {
databaseStatus,
mailerStatus
}
mailerStatus,
};
return {
status: 201,
data
data,
};
}


private async checkDatabase(){
try{
private async checkDatabase() {
try {
const options: PageOptionsDto = {
page: 1,
take: 10,
orderByColumn: 'id',
order: Order.ASC
order: Order.ASC,
};
const allUsers = await this.userRepository.getAllUsers(options);
if (allUsers == null || allUsers == undefined){
return "DOWN";
if (allUsers == null || allUsers == undefined) {
return 'DOWN';
}
return "OK";
}
catch(error){
return "DOWN";
return 'OK';
} catch (error) {
return 'DOWN';
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Otimize a verificação do banco de dados

O método atual busca todos os usuários para verificar a saúde do banco de dados, o que pode ser ineficiente. Considere usar uma consulta mais leve.

  private async checkDatabase() {
    try {
-     const options: PageOptionsDto = {
-       page: 1,
-       take: 10,
-       orderByColumn: 'id',
-       order: Order.ASC,
-     };
-     const allUsers = await this.userRepository.getAllUsers(options);
+     const result = await this.userRepository
+       .createQueryBuilder()
+       .select('1')
+       .limit(1)
+       .getRawOne();
-     if (allUsers == null || allUsers == undefined) {
+     if (!result) {
        return 'DOWN';
      }
      return 'OK';
    } catch (error) {
      return 'DOWN';
    }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private async checkDatabase() {
try {
const options: PageOptionsDto = {
page: 1,
take: 10,
orderByColumn: 'id',
order: Order.ASC
order: Order.ASC,
};
const allUsers = await this.userRepository.getAllUsers(options);
if (allUsers == null || allUsers == undefined){
return "DOWN";
if (allUsers == null || allUsers == undefined) {
return 'DOWN';
}
return "OK";
}
catch(error){
return "DOWN";
return 'OK';
} catch (error) {
return 'DOWN';
}
private async checkDatabase() {
try {
const result = await this.userRepository
.createQueryBuilder()
.select('1')
.limit(1)
.getRawOne();
if (!result) {
return 'DOWN';
}
return 'OK';
} catch (error) {
return 'DOWN';
}
}

}
private async checkEmail(){
try{

private async checkEmail() {
try {
await this.mailService.sendMail({
subject: 'HealthCheck',
template: './health',
context: {
arg1: "Argumento1",
arg2: "Argumento2"
arg1: 'Argumento1',
arg2: 'Argumento2',
},
email: '[email protected]'
email: '[email protected]',
});
return "OK";
return 'OK';
} catch (error) {
return 'DOWN';
}
catch(error){
return "DOWN";
}

async updateStatus(
user_id: string,
applicationId: string,
status: string,
): Promise<ApplicationEntity | null> {
const application = await this.applicationRepository.findOne({
where: { id: applicationId, user_id },
});

if (!application) {
return null;
}

application.status = status;
await this.applicationRepository.save(application);
return application;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Melhorar a validação e tratamento de erros no updateStatus

O método precisa de melhorias na validação e tratamento de erros.

Sugestões de melhorias:

  1. Criar enum para os status válidos
  2. Validar o user_id
  3. Lançar exceções específicas
  4. Adicionar logs para rastreabilidade
export enum ApplicationStatus {
  PENDING = 'PENDING',
  APPROVED = 'APPROVED',
  REJECTED = 'REJECTED'
  // adicionar outros status conforme necessário
}

async updateStatus(
  user_id: string,
  applicationId: string,
  status: ApplicationStatus, // usar enum ao invés de string
): Promise<ApplicationEntity> {
  // Validar user_id
  const user = await this.userRepository.findOne({ where: { id: user_id }});
  if (!user) {
    throw new NotFoundException('Usuário não encontrado');
  }

  const application = await this.applicationRepository.findOne({
    where: { id: applicationId, user_id },
  });

  if (!application) {
    throw new NotFoundException('Candidatura não encontrada');
  }

  application.status = status;
  await this.applicationRepository.save(application);
  
  this.logger.log(`Status da candidatura ${applicationId} atualizado para ${status}`);
  
  return application;
}

}

}
Loading