Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #33 from 7SOATSquad30/refactor/customer-clean-arch…
Browse files Browse the repository at this point in the history
…itecture

refactor: switch the customer to a clean architecture
  • Loading branch information
MuriloKakazu authored Jul 27, 2024
2 parents 5e70f62 + 95a1cbc commit ec8ce57
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package br.com.fiap.grupo30.fastfood.domain.repositories;

import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import br.com.fiap.grupo30.fastfood.domain.entities.Customer;

public interface CustomerRepository {

CustomerDTO findCustomerByCpf(String cpf);
Customer findCustomerByCpf(String cpf);

CustomerDTO insert(CustomerDTO dto);
Customer insert(Customer dto);
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package br.com.fiap.grupo30.fastfood.domain.usecases.customer;

import br.com.fiap.grupo30.fastfood.domain.repositories.CustomerRepository;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import org.springframework.stereotype.Component;
import br.com.fiap.grupo30.fastfood.domain.entities.Customer;
import br.com.fiap.grupo30.fastfood.infrastructure.gateways.CustomerGateway;

@Component
public class FindCustomerByCpfUseCase {

private final CustomerRepository customerRepository;
private final CustomerGateway customerGateway;

public FindCustomerByCpfUseCase(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
public FindCustomerByCpfUseCase(CustomerGateway customerGateway) {
this.customerGateway = customerGateway;
}

public CustomerDTO execute(String cpf) {
return customerRepository.findCustomerByCpf(cpf);
public Customer execute(String cpf) {
return customerGateway.findCustomerByCpf(cpf);
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package br.com.fiap.grupo30.fastfood.domain.usecases.customer;

import br.com.fiap.grupo30.fastfood.domain.repositories.CustomerRepository;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import org.springframework.stereotype.Component;
import br.com.fiap.grupo30.fastfood.domain.entities.Customer;
import br.com.fiap.grupo30.fastfood.infrastructure.gateways.CustomerGateway;

@Component
public class RegisterNewCustomerUseCase {

private final CustomerRepository customerRepository;
private final CustomerGateway customerGateway;

public RegisterNewCustomerUseCase(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
public RegisterNewCustomerUseCase(CustomerGateway customerGateway) {
this.customerGateway = customerGateway;
}

public CustomerDTO execute(CustomerDTO dto) {
return customerRepository.insert(dto);
public Customer execute(Customer customer) {
return customerGateway.insert(customer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.OrderDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.ResourceNotFoundException;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerMapper;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerEntityMapper;
import jakarta.transaction.Transactional;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -18,16 +18,16 @@ public class StartNewOrderUseCase {

private final JpaOrderRepository jpaOrderRepository;
private final JpaCustomerRepository jpaCustomerRepository;
public final CustomerMapper customerMapper;
public final CustomerEntityMapper customerEntityMapper;

@Autowired
public StartNewOrderUseCase(
JpaOrderRepository jpaOrderRepository,
JpaCustomerRepository jpaCustomerRepository,
CustomerMapper customerMapper) {
CustomerEntityMapper customerEntityMapper) {
this.jpaOrderRepository = jpaOrderRepository;
this.jpaCustomerRepository = jpaCustomerRepository;
this.customerMapper = customerMapper;
this.customerEntityMapper = customerEntityMapper;
}

@Transactional
Expand Down Expand Up @@ -55,15 +55,15 @@ private CustomerDTO findOrCreateAnonymousCustomer() {
jpaCustomerRepository.findCustomerByCpf(anonymousCpf);

if (anonymousCustomer.isPresent()) {
return new CustomerDTO(customerMapper.mapFrom(anonymousCustomer.get()));
return new CustomerDTO(customerEntityMapper.mapFrom(anonymousCustomer.get()));
} else {
CustomerEntity newAnonymousCustomer = new CustomerEntity();
newAnonymousCustomer.setCpf(anonymousCpf);
newAnonymousCustomer.setName("Anonymous");
newAnonymousCustomer.setEmail("[email protected]");
CustomerEntity savedAnonymousCustomer =
jpaCustomerRepository.save(newAnonymousCustomer);
return new CustomerDTO(customerMapper.mapFrom(savedAnonymousCustomer));
return new CustomerDTO(customerEntityMapper.mapFrom(savedAnonymousCustomer));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package br.com.fiap.grupo30.fastfood.infrastructure.configuration;

import br.com.fiap.grupo30.fastfood.domain.repositories.CustomerRepository;
import br.com.fiap.grupo30.fastfood.domain.usecases.customer.FindCustomerByCpfUseCase;
import br.com.fiap.grupo30.fastfood.domain.usecases.customer.RegisterNewCustomerUseCase;
import br.com.fiap.grupo30.fastfood.infrastructure.gateways.CustomerGateway;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.repositories.JpaCustomerRepository;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerEntityMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomerConfiguration {

@Bean
public CustomerRepository customerRepository(
JpaCustomerRepository jpaCustomerRepository,
CustomerEntityMapper customerEntityMapper) {
return new CustomerGateway(jpaCustomerRepository, customerEntityMapper);
}

@Bean
public FindCustomerByCpfUseCase findCustomerByCpfUseCase(CustomerGateway customerGateway) {
return new FindCustomerByCpfUseCase(customerGateway);
}

@Bean
public RegisterNewCustomerUseCase registerNewCustomerUseCase(CustomerGateway customerGateway) {
return new RegisterNewCustomerUseCase(customerGateway);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package br.com.fiap.grupo30.fastfood.infrastructure.gateways;

import br.com.fiap.grupo30.fastfood.domain.entities.Customer;
import br.com.fiap.grupo30.fastfood.domain.repositories.CustomerRepository;
import br.com.fiap.grupo30.fastfood.domain.valueobjects.CPF;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.CustomerEntity;
import br.com.fiap.grupo30.fastfood.infrastructure.persistence.repositories.JpaCustomerRepository;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.InvalidCpfException;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.ResourceConflictException;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.ResourceNotFoundException;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerDTOMapper;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerMapper;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerEntityMapper;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
Expand All @@ -19,40 +17,34 @@
public class CustomerGateway implements CustomerRepository {

public final JpaCustomerRepository jpaCustomerRepository;
public final CustomerMapper customerMapper;
public final CustomerDTOMapper customerDTOMapper;
public final CustomerEntityMapper customerEntityMapper;

@Autowired
public CustomerGateway(
JpaCustomerRepository jpaCustomerRepository,
CustomerMapper customerMapper,
CustomerDTOMapper customerDTOMapper) {
CustomerEntityMapper customerEntityMapper) {
this.jpaCustomerRepository = jpaCustomerRepository;
this.customerMapper = customerMapper;
this.customerDTOMapper = customerDTOMapper;
this.customerEntityMapper = customerEntityMapper;
}

@Override
public CustomerDTO findCustomerByCpf(String cpf) {
public Customer findCustomerByCpf(String cpf) {
String cpfStr = CPF.removeNonDigits(cpf);
Optional<CustomerEntity> obj = jpaCustomerRepository.findCustomerByCpf(cpfStr);
CustomerEntity entity =
obj.orElseThrow(() -> new ResourceNotFoundException("Entity not found"));
return new CustomerDTO(customerMapper.mapFrom(entity));
return this.customerEntityMapper.mapFrom(entity);
}

@Override
public CustomerDTO insert(CustomerDTO dto) {
String cpfDTO = dto.getCpf();
if (!CPF.isValid(cpfDTO)) {
throw new InvalidCpfException(cpfDTO);
}
public Customer insert(Customer customer) {
try {
dto.setCpf(CPF.removeNonDigits(cpfDTO));
CustomerEntity entity = jpaCustomerRepository.save(customerDTOMapper.mapTo(dto));
return new CustomerDTO(customerMapper.mapFrom(entity));
CustomerEntity entity =
jpaCustomerRepository.save(customerEntityMapper.mapTo(customer));
return this.customerEntityMapper.mapFrom(entity);
} catch (DataIntegrityViolationException e) {
throw new ResourceConflictException("CPF already exists: " + dto.getCpf(), e);
throw new ResourceConflictException(
"CPF already exists: " + customer.getCpf().value(), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package br.com.fiap.grupo30.fastfood.presentation.controllers;

import br.com.fiap.grupo30.fastfood.domain.entities.Customer;
import br.com.fiap.grupo30.fastfood.domain.usecases.customer.FindCustomerByCpfUseCase;
import br.com.fiap.grupo30.fastfood.domain.usecases.customer.RegisterNewCustomerUseCase;
import br.com.fiap.grupo30.fastfood.domain.valueobjects.CPF;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.exceptions.InvalidCpfException;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerDTOMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
Expand All @@ -21,20 +25,23 @@ public class CustomerController {

private final FindCustomerByCpfUseCase findCustomerByCpfUseCase;
private final RegisterNewCustomerUseCase registerNewCustomerUseCase;
private final CustomerDTOMapper customerDTOMapper;

@Autowired
public CustomerController(
FindCustomerByCpfUseCase findCustomerByCpfUseCase,
RegisterNewCustomerUseCase registerNewCustomerUseCase) {
RegisterNewCustomerUseCase registerNewCustomerUseCase,
CustomerDTOMapper customerDTOMapper) {
this.findCustomerByCpfUseCase = findCustomerByCpfUseCase;
this.registerNewCustomerUseCase = registerNewCustomerUseCase;
this.customerDTOMapper = customerDTOMapper;
}

@GetMapping
@Operation(summary = "Get a customer", description = "Retrieve a registered customer by cpf")
public ResponseEntity<CustomerDTO> findCustomerByCpf(
@RequestParam(value = "cpf", defaultValue = "0") String cpf) {
CustomerDTO dto = this.findCustomerByCpfUseCase.execute(cpf);
CustomerDTO dto = this.customerDTOMapper.mapTo(this.findCustomerByCpfUseCase.execute(cpf));
return ResponseEntity.ok().body(dto);
}

Expand All @@ -43,7 +50,14 @@ public ResponseEntity<CustomerDTO> findCustomerByCpf(
summary = "Create a new customer",
description = "Create a new customer and return the created customer's data")
public ResponseEntity<CustomerDTO> createCustomer(@RequestBody @Valid CustomerDTO dto) {
CustomerDTO dtoCreated = this.registerNewCustomerUseCase.execute(dto);
String cpf = dto.getCpf();
if (!CPF.isValid(cpf)) {
throw new InvalidCpfException(cpf);
}
dto.setCpf(CPF.removeNonDigits(cpf));
Customer domainObj = this.customerDTOMapper.mapFrom(dto);
CustomerDTO dtoCreated =
this.customerDTOMapper.mapTo(this.registerNewCustomerUseCase.execute(domainObj));
URI uri =
ServletUriComponentsBuilder.fromCurrentRequest()
.path(PATH_VARIABLE_ID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.AddOrderProductRequest;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.OrderDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl.CustomerDTOMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.net.URI;
Expand All @@ -30,6 +31,7 @@ public class OrderController {
private final FinishPreparingOrderUseCase finishPreparingOrderUseCase;
private final DeliverOrderUseCase deliverOrderUseCase;
private final FindCustomerByCpfUseCase findCustomerByCpfUseCase;
private final CustomerDTOMapper customerDTOMapper;

@Autowired
public OrderController(
Expand All @@ -42,7 +44,8 @@ public OrderController(
StartPreparingOrderUseCase startPreparingOrderUseCase,
FinishPreparingOrderUseCase finishPreparingOrderUseCase,
DeliverOrderUseCase deliverOrderUseCase,
FindCustomerByCpfUseCase findCustomerByCpfUseCase) {
FindCustomerByCpfUseCase findCustomerByCpfUseCase,
CustomerDTOMapper customerDTOMapper) {
this.startNewOrderUseCase = startNewOrderUseCase;
this.addProductToOrderUseCase = addProductToOrderUseCase;
this.removeProductFromOrderUseCase = removeProductFromOrderUseCase;
Expand All @@ -53,6 +56,7 @@ public OrderController(
this.finishPreparingOrderUseCase = finishPreparingOrderUseCase;
this.deliverOrderUseCase = deliverOrderUseCase;
this.findCustomerByCpfUseCase = findCustomerByCpfUseCase;
this.customerDTOMapper = customerDTOMapper;
}

@GetMapping
Expand Down Expand Up @@ -84,7 +88,9 @@ public ResponseEntity<OrderDTO> startNewOrder(
@RequestBody(required = false) AddCustomerCpfRequest request) {
CustomerDTO customerDTO = null;
if (request != null && request.getCpf() != null && !request.getCpf().isEmpty()) {
customerDTO = findCustomerByCpfUseCase.execute(request.getCpf());
customerDTO =
this.customerDTOMapper.mapTo(
findCustomerByCpfUseCase.execute(request.getCpf()));
}
OrderDTO order = this.startNewOrderUseCase.execute(customerDTO);
URI uri =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,31 @@
package br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.impl;

import br.com.fiap.grupo30.fastfood.infrastructure.persistence.entities.CustomerEntity;
import br.com.fiap.grupo30.fastfood.domain.entities.Customer;
import br.com.fiap.grupo30.fastfood.domain.valueobjects.CPF;
import br.com.fiap.grupo30.fastfood.presentation.presenters.dto.CustomerDTO;
import br.com.fiap.grupo30.fastfood.presentation.presenters.mapper.BiDirectionalMapper;
import org.springframework.stereotype.Component;

@Component
public final class CustomerDTOMapper implements BiDirectionalMapper<CustomerDTO, CustomerEntity> {
public final class CustomerDTOMapper implements BiDirectionalMapper<Customer, CustomerDTO> {

@Override
public CustomerEntity mapTo(CustomerDTO dto) {
CustomerEntity entity = new CustomerEntity();
entity.setId(dto.getId());
entity.setName(dto.getName());
entity.setCpf(dto.getCpf());
entity.setEmail(dto.getEmail());
return entity;
public CustomerDTO mapTo(Customer customer) {
CustomerDTO dto = new CustomerDTO();
dto.setId(customer.getId());
dto.setName(customer.getName());
dto.setCpf(customer.getCpf().value());
dto.setEmail(customer.getEmail());
return dto;
}

@Override
public CustomerDTO mapFrom(CustomerEntity entity) {
CustomerDTO customer = new CustomerDTO();
customer.setId(entity.getId());
customer.setName(entity.getName());
customer.setCpf(entity.getCpf());
customer.setEmail(entity.getEmail());
public Customer mapFrom(CustomerDTO dto) {
Customer customer = new Customer();
customer.setId(dto.getId());
customer.setName(dto.getName());
customer.setCpf(new CPF(dto.getCpf()));
customer.setEmail(dto.getEmail());
return customer;
}

public void updateEntityFromDTO(CustomerEntity entity, CustomerDTO dto) {
entity.setName(dto.getName());
entity.setCpf(dto.getCpf());
entity.setEmail(dto.getEmail());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.springframework.stereotype.Component;

@Component
public final class CustomerMapper implements BiDirectionalMapper<Customer, CustomerEntity> {
public final class CustomerEntityMapper implements BiDirectionalMapper<Customer, CustomerEntity> {

@Override
public CustomerEntity mapTo(Customer customer) {
Expand All @@ -28,4 +28,10 @@ public Customer mapFrom(CustomerEntity entity) {
customer.setEmail(entity.getEmail());
return customer;
}

public void updateEntityFromCustomer(CustomerEntity entity, Customer customer) {
entity.setName(customer.getName());
entity.setCpf(customer.getCpf().value());
entity.setEmail(customer.getEmail());
}
}

0 comments on commit ec8ce57

Please sign in to comment.