Skip to content

Commit

Permalink
Merge branch 'main' of github.com:ItaloRAmaral/cliniccontrol into 113…
Browse files Browse the repository at this point in the history
…-refatorar-aplicacao-para-concentrar-core-e-adapters-dentro-de-apps
  • Loading branch information
luanavfg committed Jan 4, 2024
2 parents c3eb216 + 3b6e9f8 commit 83572c9
Show file tree
Hide file tree
Showing 40 changed files with 379 additions and 185 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [1.6.0-beta.5](https://github.com/ItaloRAmaral/cliniccontrol/compare/[email protected]@1.6.0-beta.5) (2023-12-29)

### Features

- **CC-111:** delete patient endpoint ([d23b3d2](https://github.com/ItaloRAmaral/cliniccontrol/commit/d23b3d270d7068a8271e0140b3da29de371cc7e7))

## [1.6.0-beta.4](https://github.com/ItaloRAmaral/cliniccontrol/compare/[email protected]@1.6.0-beta.4) (2023-12-28)

### Features
Expand Down
4 changes: 4 additions & 0 deletions apps/core-rest-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [1.2.1-beta.2](https://github.com/ItaloRAmaral/cliniccontrol/compare/@cliniccontrol/[email protected]...@cliniccontrol/[email protected]) (2023-12-29)

**Note:** Version bump only for package @cliniccontrol/core-rest-api

## [1.2.1-beta.1](https://github.com/ItaloRAmaral/cliniccontrol/compare/@cliniccontrol/[email protected]...@cliniccontrol/[email protected]) (2023-12-21)

**Note:** Version bump only for package @cliniccontrol/core-rest-api
Expand Down
6 changes: 6 additions & 0 deletions apps/core-rest-api/http/patient-client.http
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ Authorization: Bearer {{authToken}}
"clinicId": "{{$dotenv CLINIC_ID}}",
"paymentMethod": "CREDIT_CARD"
}

### Delete a patient
# @name delete_patient
DELETE http://localhost:3333/core/patient/{{$dotenv PATIENT_ID}}/delete HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{authToken}}
2 changes: 1 addition & 1 deletion apps/core-rest-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cliniccontrol/core-rest-api",
"version": "1.2.1-beta.1",
"version": "1.2.1-beta.2",
"license": "MIT",
"authors": [
{
Expand Down
17 changes: 11 additions & 6 deletions apps/core-rest-api/src/app/adapters/controllers/api/api.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ import { PostgreSqlPrismaOrmService } from '../../database/infra/prisma/prisma.s
import { DatabaseRepositoriesModule } from '../../database/repositories/repositories.module';

import { CreateClinicController } from './use-cases/clinic/create-clinic/create-clinic.controller';
import { NestjsCreateClinicService } from './use-cases/clinic/create-clinic/nestjs-create-clinic.service';
import { DeleteClinicController } from './use-cases/clinic/delete-clinic/delete-clinic.controller';
import { NestjsDeleteClinicService } from './use-cases/clinic/delete-clinic/nestjs-delete-clinic.service';
import { NestjsUpdateClinicService } from './use-cases/clinic/update-clinic/nestjs-update-clinic.service';
import { UpdateClinicController } from './use-cases/clinic/update-clinic/update-clinic.controller';
import { CreatePatientController } from './use-cases/patient/create-patient/create-patient.controller';
import { NestjsCreatePatientService } from './use-cases/patient/create-patient/nestjs-create-patient.service';
import { DeletePatientController } from './use-cases/patient/delete-patient/delete-patient.controller';
import { AuthenticatePsychologistController } from './use-cases/psychologist/authenticate-psychologist/authenticate-psychologist.controller';
import { NestjsAuthenticatePsychologistService } from './use-cases/psychologist/authenticate-psychologist/nestjs-authenticate-psychologist.service';
import { CreatePsychologistController } from './use-cases/psychologist/create-psychologist/create-psychologist.controller';
import { NestjsCreatePsychologistService } from './use-cases/psychologist/create-psychologist/nestjs-create-psychologist.service';
import { DeletePsychologistController } from './use-cases/psychologist/delete-psychologist/delete-psychologist.controller';

import { NestjsCreateClinicService } from './use-cases/clinic/create-clinic/nestjs-create-clinic.service';
import { NestjsDeleteClinicService } from './use-cases/clinic/delete-clinic/nestjs-delete-clinic.service';
import { NestjsUpdateClinicService } from './use-cases/clinic/update-clinic/nestjs-update-clinic.service';
import { NestjsCreatePatientService } from './use-cases/patient/create-patient/nestjs-create-patient.service';
import { NestjsDeletePatientService } from './use-cases/patient/delete-patient/nestjs-delete-patient.service';
import { NestjsAuthenticatePsychologistService } from './use-cases/psychologist/authenticate-psychologist/nestjs-authenticate-psychologist.service';
import { NestjsCreatePsychologistService } from './use-cases/psychologist/create-psychologist/nestjs-create-psychologist.service';
import { NestjsDeletePsychologistService } from './use-cases/psychologist/delete-psychologist/nestjs-delete-psychologist.service';
import { NestjsUpdatePsychologistService } from './use-cases/psychologist/update-psychologist/nestjs-update-psychologist.service';

Expand All @@ -47,6 +50,7 @@ import { NestjsUpdatePsychologistService } from './use-cases/psychologist/update
UpdateClinicController,
DeleteClinicController,
CreatePatientController,
DeletePatientController,
],
providers: [
BcryptHasherService,
Expand All @@ -59,6 +63,7 @@ import { NestjsUpdatePsychologistService } from './use-cases/psychologist/update
NestjsUpdateClinicService,
NestjsDeleteClinicService,
NestjsCreatePatientService,
NestjsDeletePatientService,
],
})
export class ApiModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,22 @@ import { CreateClinicDto } from '../../../../../../core/domains/clinic/use-cases
import { GlobalAppHttpException } from '../../../../../../shared/errors/globalAppHttpException';
import { NestjsCreateClinicService } from './nestjs-create-clinic.service';

interface createClinicResponse {
message: string
interface CreateClinicResponse {
message: string;
}

@ApiTags('Clinic')
@Controller({
path: 'clinic',
})
export class CreateClinicController {
constructor(
private createClinicService: NestjsCreateClinicService
) {}
constructor(private createClinicService: NestjsCreateClinicService) {}

@Post('create')
async execute(
@Body() createClinicDto: CreateClinicDto
): Promise<createClinicResponse>{
async execute(@Body() createClinicDto: CreateClinicDto): Promise<CreateClinicResponse> {
try {
await this.createClinicService.execute(createClinicDto);
return {message: 'Clinic created successfully'}
return { message: 'Clinic created successfully' };
} catch (error: unknown) {
throw new GlobalAppHttpException(error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('[E2E] - Delete Clinic', () => {
.delete(`/clinic/${wrongId}/delete`)
.set('Authorization', `Bearer ${access_token}`);

expect(response.status).toBe(409);
expect(response.status).toBe(404);
expect(response.body.message).toBe('clinic not found');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { ClinicEntity } from '../../../../../../core/domains/clinic/entities/cli

describe('[E2E] - Update Clinic', () => {
let app: INestApplication;
let clinic: ClinicEntity
let clinic: ClinicEntity;
let access_token: string;
let invalid_access_token: string;

beforeAll(async () => {
const setup = await setupE2ETest();
app = setup.app;

clinic = setup.clinic
clinic = setup.clinic;

access_token = setup.access_token;
invalid_access_token = setup.invalid_access_token;
Expand Down Expand Up @@ -72,7 +72,7 @@ describe('[E2E] - Update Clinic', () => {
.set('Authorization', `Bearer ${access_token}`)
.send(updateInfos);

expect(response.statusCode).toBe(409);
expect(response.statusCode).toBe(404);
expect(response.body.message).toBe('clinic not found');
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Controller, Delete, Param } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { deleteMethodDocs } from './docs';

import { GlobalAppHttpException } from '../../../../../../shared/errors/globalAppHttpException';

import { TokenPayload } from '../../../../../auth/jwt.strategy';
import { CurrentUser } from '../../../decorators/current-user.decorator';
import { RouteParamsDto } from './dto';
import { NestjsDeletePatientService } from './nestjs-delete-patient.service';

@ApiTags('patient')
@ApiBearerAuth()
@Controller({
path: 'patient',
})
export class DeletePatientController {
constructor(private deletePatientService: NestjsDeletePatientService) {}

@Delete(':patientId/delete')
@ApiOperation(deleteMethodDocs)
async execute(
@Param() { patientId }: RouteParamsDto,
@CurrentUser() currentUser: TokenPayload,
) {
try {
const deletePatientDto = {
patientId,
psychologistId: currentUser.id,
};

await this.deletePatientService.execute(deletePatientDto);

return {
message: 'Patient deleted successfully',
};
} catch (error: unknown) {
throw new GlobalAppHttpException(error);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { fakerPT_BR as faker } from '@faker-js/faker';
import { INestApplication } from '@nestjs/common';
import request from 'supertest';

import { setupE2ETest } from '../../../../../../../../tests/utils/e2e-tests-initial-setup';
import { PostgreSqlPrismaOrmService } from '../../../../../database/infra/prisma/prisma.service';

import { PatientFactory } from '../../../../../../../../tests/factories/make-patient';
import { PsychologistFactory } from '../../../../../../../../tests/factories/make-psychologist';
import { ClinicEntity } from '../../../../../../core/domains/clinic/entities/clinic/entity';
import { PatientEntity } from '../../../../../../core/domains/patient/entities/patient/entity';

describe('[E2E] - Delete Patient', async () => {
let prisma: PostgreSqlPrismaOrmService;
let app: INestApplication;

let patientFactory: PatientFactory;
let psychologistFactory: PsychologistFactory;

let access_token: string;
let invalid_access_token: string;

let patient: PatientEntity;
let clinic: ClinicEntity;

beforeAll(async () => {
const setup = await setupE2ETest();

prisma = setup.prisma;
app = setup.app;

patientFactory = setup.patientFactory;
psychologistFactory = setup.psychologistFactory;

access_token = setup.access_token;
invalid_access_token = setup.invalid_access_token;

clinic = setup.clinic;
patient = setup.patient;
});

it('[DELETE] - Should return an error when trying to delete a patient without access_token', async () => {
const response = await request(app.getHttpServer()).delete(
`/patient/${patient.id}/delete`,
);

expect(response.status).toBe(401);
expect(response.body.message).toBe('Invalid JWT token');
});

it('[DELETE] - Should return an error when trying to delete a patient with invalid access_token', async () => {
const response = await request(app.getHttpServer())
.delete(`/patient/${patient.id}/delete`)
.set('Authorization', `Bearer ${invalid_access_token}`);

expect(response.status).toBe(401);
expect(response.body.message).toBe('Invalid JWT token');
});

it('[DELETE] - Should throw an error when trying to delete a patient which does not belong to the psychologist', async () => {
const newPsychologist = await psychologistFactory.makePrismaPsychologist({
email: faker.internet.email(),
});

const newPatient = await patientFactory.makePrismaPatient({
psychologistId: newPsychologist.id,
clinicId: clinic.id,
});

const response = await request(app.getHttpServer())
.delete(`/patient/${newPatient.id}/delete`)
.set('Authorization', `Bearer ${access_token}`);

expect(response.status).toBe(401);
expect(response.body.message).toBe('this patient does not belong to you');
});

it('[DELETE] - Should throw an error when trying to delete a patient that does not exist', async () => {
const fakePatientId = faker.string.uuid();

const response = await request(app.getHttpServer())
.delete(`/patient/${fakePatientId}/delete`)
.set('Authorization', `Bearer ${access_token}`);

expect(response.status).toBe(404);
expect(response.body.message).toBe('patient not found');
});

it('[DELETE] - Should successfully delete a patient', async () => {
const response = await request(app.getHttpServer())
.delete(`/patient/${patient.id}/delete`)
.set('Authorization', `Bearer ${access_token}`);

const isPatientExist = await prisma.patient.findUnique({
where: {
id: patient.id,
},
});

expect(response.status).toBe(200);
expect(response.body.message).toBe('Patient deleted successfully');

expect(isPatientExist).toBe(null);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { OperationObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface';

const description = `
---
\`Experimental\`
---
### Delete a Patient in the system
This endpoint help you to Delete a patient.
You must at least provide one of the following body parameters
`;

export const deleteMethodDocs: Partial<OperationObject> = {
summary: 'Delete a patient',
description,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IsString } from 'class-validator';

export class RouteParamsDto {
@IsString()
patientId!: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Injectable } from '@nestjs/common';

import { PatientDatabaseRepository } from '../../../../../../core/domains/patient/repositories/database-repository';
import { DeletePatientService } from '../../../../../../core/domains/patient/use-cases/delete-patient/delete-patient.service';

@Injectable()
export class NestjsDeletePatientService extends DeletePatientService {
constructor(patientDatabaseRepository: PatientDatabaseRepository) {
super(patientDatabaseRepository);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('[E2E] - Update Psychologist Account', () => {
.set('Authorization', `Bearer ${access_token}`)
.send(updateInfos);

expect(response.statusCode).toBe(400);
expect(response.statusCode).toBe(404);
expect(response.body.message).toBe('psychologist not found');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ export class PostgresqlPrismaOrmPatientRepository implements PatientDatabaseRepo
return PostgresqlPrismaPatientMapper.toDomain(patient);
}

async findPatientById(id: string): Promise<PatientEntity | null> {
async findPatientById(patientId: string): Promise<PatientEntity | null> {
const patient = await this.postgresqlPrismaOrmService['patient'].findUnique({
where: {
id: id,
id: patientId,
},
});

Expand Down Expand Up @@ -77,16 +77,16 @@ export class PostgresqlPrismaOrmPatientRepository implements PatientDatabaseRepo
await this.postgresqlPrismaOrmService['patient'].update(toPrismaEntity);
}

async deletePatient(email: string): Promise<void> {
const isPatientExists = await this.findPatientByEmail(email);
async deletePatient(patientId: string): Promise<void> {
const isPatientExists = await this.findPatientById(patientId);

if (!isPatientExists) {
throw new ConflictException(PATIENT_ERROR_MESSAGES['PATIENT_NOT_FOUND']);
}

await this.postgresqlPrismaOrmService['patient'].delete({
where: {
email: email,
id: patientId,
},
});
}
Expand Down
Loading

0 comments on commit 83572c9

Please sign in to comment.