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

fix: prevent duplicate CPF registration and add findByCpf method #6

Merged
merged 5 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions src/core/errors/use-case-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface UseCaseError {
message: string
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import { DeliveryPerson } from '@/domain/enterprise/entities/delivery-person'

export abstract class DeliveryPeopleRepository {
abstract create(deliveryPerson: DeliveryPerson): Promise<void>
abstract findByCpf(cpf: string): Promise<DeliveryPerson | null>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { UseCaseError } from '@/core/errors/use-case-error'

export class DeliveryPersonAlreadyExistsError
extends Error
implements UseCaseError
{
constructor() {
super('Delivery person already registered.')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ describe('Register Delivery Person', () => {
password: '123456',
})

expect(result.isRight).toBeTruthy()
expect(result.isRight()).toBeTruthy()
if (result.isLeft()) throw new Error()
expect(result.value?.deliveryPerson.id).toBeTruthy()
expect(result.value?.deliveryPerson.isAdmin()).toBeFalsy()
expect(deliveryPersonRepository.items[0]).toEqual(
Expand Down
12 changes: 10 additions & 2 deletions src/domain/application/use-cases/register-delivery-person.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Either, right } from '@/core/either'
import { Either, left, right } from '@/core/either'
import { DeliveryPerson } from '@/domain/enterprise/entities/delivery-person'
import { DeliveryPeopleRepository } from '../repositories/delivery-people.repository'
import { Injectable } from '@nestjs/common'
import { DeliveryPersonAlreadyExistsError } from './errors/delivery-person-already-exists.error'

interface RegisterDeliveryPersonUseCaseRequest {
name: string
Expand All @@ -11,7 +12,7 @@ interface RegisterDeliveryPersonUseCaseRequest {
}

type RegisterDeliveryPersonUseCaseResponse = Either<
null,
DeliveryPersonAlreadyExistsError,
{
deliveryPerson: DeliveryPerson
}
Expand All @@ -34,6 +35,13 @@ export class RegisterDeliveryPersonUseCase {
admin,
})

const deliveryPersonOnDatabase =
await this.deliveryPeopleRepository.findByCpf(cpf)

if (deliveryPersonOnDatabase) {
return left(new DeliveryPersonAlreadyExistsError())
}

await this.deliveryPeopleRepository.create(deliveryPerson)

return right({ deliveryPerson })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DeliveryPerson } from '@/domain/enterprise/entities/delivery-person'
import { Injectable } from '@nestjs/common'
import { MongooseDeliveryPersonMapper } from '../mappers/mongoose-delivery-person.mapper'
import { MongooseService } from '../mongoose.service'
import { UniqueEntityID } from '@/core/entities/unique-entity-id'

@Injectable()
export class MongooseDeliveryPeopleRepository
Expand All @@ -15,4 +16,20 @@ export class MongooseDeliveryPeopleRepository

await this.mongoose.user.create(data)
}

async findByCpf(cpf: string) {
const deliveryPerson = await this.mongoose.user.findOne({ cpf })

return deliveryPerson
? DeliveryPerson.create(
{
name: deliveryPerson.name,
cpf: deliveryPerson.cpf,
admin: deliveryPerson.admin,
password: deliveryPerson.password,
},
new UniqueEntityID(deliveryPerson._id),
)
: null
}
}
22 changes: 15 additions & 7 deletions src/infra/http/controllers/create-user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { RegisterDeliveryPersonUseCase } from '@/domain/application/use-cases/register-delivery-person'
import { ZodValidationPipe } from '@/infra/pipes/zod-validation.pipe'
import { Body, Controller, Post, UsePipes } from '@nestjs/common'
import {
Body,
ConflictException,
Controller,
Post,
UsePipes,
} from '@nestjs/common'
import { ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'
import { MongooseService } from 'src/infra/database/mongoose/mongoose.service'
import { z } from 'zod'

const registerBodySchema = z.object({
Expand All @@ -17,10 +22,7 @@ type RegisterBodySchema = z.infer<typeof registerBodySchema>
@Controller('/users')
@ApiTags('Users')
export class CreateUserController {
constructor(
private mongoose: MongooseService,
private registerUseCase: RegisterDeliveryPersonUseCase,
) {}
constructor(private registerUseCase: RegisterDeliveryPersonUseCase) {}

@Post()
@ApiOperation({ summary: 'Register a delivery person.' })
Expand Down Expand Up @@ -65,11 +67,17 @@ export class CreateUserController {
@UsePipes(new ZodValidationPipe(registerBodySchema))
async handle(@Body() body: RegisterBodySchema) {
const { name, cpf, password, admin } = body
await this.registerUseCase.execute({

const result = await this.registerUseCase.execute({
name,
cpf,
password,
admin,
})

if (result.isLeft()) {
const error = result.value
throw new ConflictException(error.message)
}
}
}
4 changes: 4 additions & 0 deletions test/in-memory-repositories/delivery-people.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ export class InMemoryDeliveryPeopleRepository
async create(deliveryPerson: DeliveryPerson): Promise<void> {
this.items.push(deliveryPerson)
}

async findByCpf(cpf: string): Promise<DeliveryPerson | null> {
return this.items.filter((item) => item.cpf === cpf)[0]
}
}