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/16 atualizar post com nova chamada #31

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
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
5 changes: 4 additions & 1 deletion .env
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Sring
SPRING_PROFILES_ACTIVE=dev

# MongoDB Configuration
MY_MONGO_INITDB_ROOT_USERNAME=root
MY_MONGO_INITDB_ROOT_PASSWORD=qwe123
Expand All @@ -9,7 +12,7 @@ AWS_SECRET_ACCESS_KEY=TESTlocalstack
AWS_REGION=us-east-1

# Configurações do S3
S3_BUCKET_NAME=desafio-bucket
S3_BUCKET_NAME=bucket-studios-lab-aws

# Configurações do SNS
AWS_SNS_ENDPOINT=http://localstack:4566
Expand Down
6 changes: 2 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@ services:
- ./localstack/subscribe-sqs-to-sns.sh:/etc/localstack/init/ready.d/subscribe-sqs-to-sns.sh
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:4566/health" ]
interval: 10s
timeout: 5s
interval: 20s
timeout: 10s
retries: 5
start_period: 90s
networks:
- developer-network
# command: >
# /bin/sh -c "apk add --no-cache bash && pip install python-dotenv && docker-entrypoint.sh"

# Banco de dados NoSQL
mongo-dev:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package br.com.springstudiouslabaws.labcore.domain.loan;

import br.com.springstudiouslabaws.labcore.exceptions.BusinessException;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.regex.Pattern;

public class LoanDomain {

private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
private static final int MINIMUM_LOAN_TERM_MONTHS = 4;
private static final BigDecimal MINIMUM_LOAN_AMOUNT = BigDecimal.valueOf(100.00);
private static final BigDecimal MAXIMUM_LOAN_AMOUNT = BigDecimal.valueOf(1000000.00);
public static final int MINIMUM_CHARACTER_NAME = 3;

String clientId;
String name;
String email;
String description;
BigDecimal amountRequested;
LocalDate dateFinalPayment;

// Validação completa do domínio
public void validate() {
validateClientId();
validateName();
validateEmail();
validateDescription();
validateAmountRequested();
validateDateFinalPayment();
}

private void validateClientId() {
if (clientId == null || clientId.isBlank()) {
throw new BusinessException("Identificador do cliente não pode ser vazio");
}
}

private void validateName() {
if (name == null || name.isBlank()) {
throw new BusinessException("Nome do cliente não pode ser vazio");
}
if (name.length() < MINIMUM_CHARACTER_NAME) {
throw new BusinessException(String.format("Nome do cliente deve ter no mínimo %s caracteres", MINIMUM_CHARACTER_NAME));
}
}

private void validateEmail() {
if (email == null || email.isBlank()) {
throw new BusinessException("E-mail não pode ser vazio");
}
if (!EMAIL_PATTERN.matcher(email).matches()) {
throw new BusinessException("E-mail inválido");
}
}

private void validateDescription() {
if (description == null || description.isBlank()) {
throw new BusinessException("Descrição do empréstimo não pode ser vazia");
}
}

private void validateAmountRequested() {
if (amountRequested == null) {
throw new BusinessException("Valor do empréstimo não pode ser nulo");
}
if (amountRequested.compareTo(MINIMUM_LOAN_AMOUNT) < 0) {
throw new BusinessException(String.format("Valor do empréstimo deve ser maior que R$ %,.2f", MINIMUM_LOAN_AMOUNT));
}
if (amountRequested.compareTo(MAXIMUM_LOAN_AMOUNT) > 0) {
throw new BusinessException(String.format("Valor do empréstimo não pode exceder R$ %,.2f", MAXIMUM_LOAN_AMOUNT));
}
}

private void validateDateFinalPayment() {
if (dateFinalPayment == null) {
throw new BusinessException("Data final de pagamento não pode ser nula");
}
if (dateFinalPayment.isBefore(LocalDate.now())) {
throw new BusinessException("Data final de pagamento não pode ser no passado");
}

long loanTermMonths = ChronoUnit.MONTHS.between(LocalDate.now(), dateFinalPayment);
if (loanTermMonths < MINIMUM_LOAN_TERM_MONTHS) {
throw new BusinessException(String.format("Prazo mínimo do empréstimo é de %d meses", MINIMUM_LOAN_TERM_MONTHS));
}
}

public String getClientId() {
return clientId;
}

public void setClientId(String clientId) {
this.clientId = clientId;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public BigDecimal getAmountRequested() {
return amountRequested;
}

public void setAmountRequested(BigDecimal amountRequested) {
this.amountRequested = amountRequested;
}

public LocalDate getDateFinalPayment() {
return dateFinalPayment;
}

public void setDateFinalPayment(LocalDate dateFinalPayment) {
this.dateFinalPayment = dateFinalPayment;
}

@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
LoanDomain that = (LoanDomain) o;
return Objects.equals(clientId, that.clientId) && Objects.equals(name, that.name) && Objects.equals(email, that.email) && Objects.equals(description, that.description) && Objects.equals(amountRequested, that.amountRequested) && Objects.equals(dateFinalPayment, that.dateFinalPayment);
}

@Override
public int hashCode() {
return Objects.hash(clientId, name, email, description, amountRequested, dateFinalPayment);
}

@Override
public String toString() {
return "LoanDomain{" +
"clientId='" + clientId + '\'' +
", name='" + name + '\'' +
", email='" + email + '\'' +
", description='" + description + '\'' +
", amountRequested=" + amountRequested +
", dateFinalPayment=" + dateFinalPayment +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package br.com.springstudiouslabaws.labcore.exceptions;

import java.io.Serial;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Exceção para representar erros de regras de negócio na aplicação.
* Esta exceção pode conter uma mensagem única ou uma lista de erros de validação.
*/
public class BusinessException extends RuntimeException {

@Serial
private static final long serialVersionUID = 1L;

private final List<String> errors;

/**
* Construtor para uma única mensagem de erro
*
* @param message Mensagem descrevendo o erro de negócio
*/
public BusinessException(String message) {
super(message);
this.errors = Collections.singletonList(message);
}

/**
* Construtor para uma lista de erros
*
* @param errors Lista de mensagens de erro
*/
public BusinessException(List<String> errors) {
super(String.join("; ", errors));
this.errors = new ArrayList<>(errors);
}

/**
* Construtor para mensagem de erro com causa
*
* @param message Mensagem descrevendo o erro de negócio
* @param cause Causa raiz da exceção
*/
public BusinessException(String message, Throwable cause) {
super(message, cause);
this.errors = Collections.singletonList(message);
}

/**
* Retorna a lista de erros
*
* @return Lista imutável de mensagens de erro
*/
public List<String> getErrors() {
return Collections.unmodifiableList(errors);
}

/**
* Verifica se há múltiplos erros
*
* @return true se houver mais de um erro, false caso contrário
*/
public boolean hasMultipleErrors() {
return errors.size() > 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package br.com.springstudiouslabaws.labcore.repositories;

import br.com.springstudiouslabaws.labcore.domain.loan.LoanDomain;

public interface LoanRepository {

LoanDomain save(LoanDomain loan);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package br.com.springstudiouslabaws.labcore.services;

import br.com.springstudiouslabaws.labcore.domain.loan.LoanDomain;

public interface LoanSQSSendService {

void sendLoan(LoanDomain loanDomain);
// Lógica para envio ao SQS do empréstimo solicitado
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import br.com.springstudiouslabaws.labcore.domain.payment.PaymentDomain;

public interface SqsReceiverService {
public interface PaymentSQSReceiverService {
// Lógica para receber mensagens das filas do SQS

void receiveFromPartialQueue(PaymentDomain paymentDomain);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import br.com.springstudiouslabaws.labcore.domain.payment.PaymentDomain;

public interface SqsSendService {
public interface PaymentSQSSendService {

void sendToPartialQueue(PaymentDomain paymentDomain);
// Lógica para envio ao SQS da fila parcial
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package br.com.springstudiouslabaws.labcore.usecases.loan;

import br.com.springstudiouslabaws.labcore.domain.loan.LoanDomain;
import br.com.springstudiouslabaws.labcore.repositories.LoanRepository;
import br.com.springstudiouslabaws.labcore.services.LoanSQSSendService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class LoanUseCase {

private static final Logger log = LoggerFactory.getLogger(LoanUseCase.class);

private final LoanRepository repository;
private final LoanSQSSendService loanSQSSendService;

public LoanUseCase(LoanRepository loanRepository, LoanSQSSendService loanSQSSendService) {
this.repository = loanRepository;
this.loanSQSSendService = loanSQSSendService;
}

public LoanDomain processLoan(LoanDomain loanDomain) {

loanDomain.validate();

LoanDomain loan = repository.save(loanDomain);

log.info("Empréstimo salvo: {}", loan);

return loan;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package br.com.springstudiouslabaws.labcore.usecases;

package br.com.springstudiouslabaws.labcore.usecases.payment;

import br.com.springstudiouslabaws.labcore.domain.payment.PaymentDomain;
import br.com.springstudiouslabaws.labcore.enums.PaymentItemStatusEnum;
import br.com.springstudiouslabaws.labcore.exceptions.PaymentNotFoundException;
import br.com.springstudiouslabaws.labcore.repositories.PaymentRepository;
import br.com.springstudiouslabaws.labcore.services.SqsSendService;
import br.com.springstudiouslabaws.labcore.services.PaymentSQSSendService;
import org.springframework.stereotype.Service;

import java.util.Objects;
Expand All @@ -16,9 +15,9 @@
public class ProcessPaymentUseCase {

private final PaymentRepository repository;
private final SqsSendService sqsService;
private final PaymentSQSSendService sqsService;

public ProcessPaymentUseCase(PaymentRepository repository, SqsSendService sqsService) {
public ProcessPaymentUseCase(PaymentRepository repository, PaymentSQSSendService sqsService) {
this.repository = repository;
this.sqsService = sqsService;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package br.com.springstudiouslabaws.labdataprovider.config.mongodb;

import br.com.springstudiouslabaws.labdataprovider.entities.LoanEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MongoLoanRespository extends MongoRepository<LoanEntity, String> {
// Aqui você pode adicionar consultas específicas se necessário.
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package br.com.springstudiouslabaws.labdataprovider.config.mongodb;

import br.com.springstudiouslabaws.labdataprovider.entities.LoanEntity;
import br.com.springstudiouslabaws.labdataprovider.entities.PaymentsEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MongoPaymentRepository extends MongoRepository<LoanEntity, String> {
public interface MongoPaymentRepository extends MongoRepository<PaymentsEntity, String> {
// Aqui você pode adicionar consultas específicas se necessário.
}
Loading
Loading