-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from 7SOATSquad30/feat/collect-payment-by-cash
feat: add collect payment by cash resource
- Loading branch information
Showing
11 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
src/main/java/br/com/fiap/grupo30/fastfood/payments_api/domain/entities/Payment.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.domain.entities; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.domain.enums.PaymentStatus; | ||
import br.com.fiap.grupo30.fastfood.payments_api.infrastructure.persistence.entities.PaymentEntity; | ||
import br.com.fiap.grupo30.fastfood.payments_api.presentation.dtos.PaymentDto; | ||
import java.util.Objects; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter(AccessLevel.PRIVATE) | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class Payment { | ||
private Long id; | ||
private PaymentStatus status; | ||
private Double amount; | ||
|
||
public static Payment create(Long orderId) { | ||
return new Payment(orderId, PaymentStatus.PENDING, 0.0); | ||
} | ||
|
||
public void setPaymentCollected(Double paymentCollectedAmount) { | ||
this.setStatus(PaymentStatus.COLLECTED); | ||
this.setAmount(paymentCollectedAmount); | ||
} | ||
|
||
public void setPaymentRejected() { | ||
this.setStatus(PaymentStatus.REJECTED); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (!(o instanceof Payment payment)) return false; | ||
return Objects.equals(id, payment.id); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(id); | ||
} | ||
|
||
public PaymentDto toDto() { | ||
return new PaymentDto(status, amount); | ||
} | ||
|
||
public PaymentEntity toPersistence() { | ||
return new PaymentEntity(id, status, amount); | ||
} | ||
|
||
public static Payment fromPersistence(PaymentEntity payment) { | ||
return new Payment(payment.getOrderId(), payment.getStatus(), payment.getAmount()); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/br/com/fiap/grupo30/fastfood/payments_api/domain/enums/PaymentStatus.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.domain.enums; | ||
|
||
public enum PaymentStatus { | ||
PENDING, | ||
REJECTED, | ||
COLLECTED, | ||
} |
35 changes: 35 additions & 0 deletions
35
...java/br/com/fiap/grupo30/fastfood/payments_api/domain/repositories/PaymentRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.domain.repositories; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.domain.entities.Payment; | ||
import br.com.fiap.grupo30.fastfood.payments_api.infrastructure.persistence.repositories.PaymentJpaRepository; | ||
import java.util.Optional; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Repository; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Repository | ||
public class PaymentRepository { | ||
|
||
@Autowired private PaymentJpaRepository paymentJpaRepository; | ||
|
||
@Transactional(readOnly = true) | ||
public Optional<Payment> findByOrderId(Long orderId) { | ||
return paymentJpaRepository | ||
.findById(orderId) | ||
.map(Payment::fromPersistence) | ||
.or(() -> Optional.empty()); | ||
} | ||
|
||
@Transactional() | ||
public Optional<Payment> findByOrderIdForUpdate(Long orderId) { | ||
return paymentJpaRepository | ||
.findById(orderId) | ||
.map(Payment::fromPersistence) | ||
.or(() -> Optional.empty()); | ||
} | ||
|
||
@Transactional | ||
public Payment save(Payment payment) { | ||
return Payment.fromPersistence(paymentJpaRepository.save(payment.toPersistence())); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
.../com/fiap/grupo30/fastfood/payments_api/domain/usecases/CollectPaymentViaCashUseCase.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.domain.usecases; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.domain.entities.Payment; | ||
import br.com.fiap.grupo30.fastfood.payments_api.domain.repositories.PaymentRepository; | ||
import br.com.fiap.grupo30.fastfood.payments_api.presentation.dtos.PaymentDto; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class CollectPaymentViaCashUseCase { | ||
|
||
public PaymentDto execute( | ||
PaymentRepository paymentRepository, Long orderId, Double paidAmount) { | ||
Payment payment = | ||
paymentRepository.findByOrderIdForUpdate(orderId).orElse(Payment.create(orderId)); | ||
|
||
payment.setPaymentCollected(paidAmount); | ||
|
||
return paymentRepository.save(payment).toDto(); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
...a/br/com/fiap/grupo30/fastfood/payments_api/infrastructure/auth/RequireAdminUserRole.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.infrastructure.auth; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.METHOD) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface RequireAdminUserRole {} |
61 changes: 61 additions & 0 deletions
61
...om/fiap/grupo30/fastfood/payments_api/infrastructure/auth/RequireAdminUserRoleAspect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.infrastructure.auth; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import java.util.Base64; | ||
import java.util.List; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.aspectj.lang.annotation.Before; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
|
||
@Aspect | ||
@Component | ||
public class RequireAdminUserRoleAspect { | ||
|
||
private final ObjectMapper objectMapper = new ObjectMapper(); | ||
private static String ADMIN_ROLE = "admin-group"; | ||
private static String BEARER_TYPE = "Bearer"; | ||
private static Integer JWT_PARTS = 3; | ||
|
||
@Before("@annotation(RequireAdminUserRole)") | ||
public void checkAdminRole() throws Exception { | ||
ServletRequestAttributes attrs = | ||
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | ||
HttpServletRequest request = attrs.getRequest(); | ||
HttpServletResponse response = attrs.getResponse(); | ||
|
||
String authorizationHeader = request.getHeader("Authorization"); | ||
|
||
if (authorizationHeader == null || !authorizationHeader.startsWith(BEARER_TYPE)) { | ||
response.sendError( | ||
HttpServletResponse.SC_UNAUTHORIZED, "Missing or invalid Authorization header"); | ||
return; | ||
} | ||
|
||
String jwtToken = authorizationHeader.substring(7); | ||
String[] tokenParts = jwtToken.split("\\."); | ||
if (tokenParts.length != JWT_PARTS) { | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token structure"); | ||
return; | ||
} | ||
|
||
String payload = new String(Base64.getDecoder().decode(tokenParts[1])); | ||
JsonNode jsonNode = objectMapper.readTree(payload); | ||
JsonNode groupsNode = jsonNode.get("cognito:groups"); | ||
if (groupsNode != null && groupsNode.isArray()) { | ||
List<String> groups = objectMapper.convertValue(groupsNode, List.class); | ||
if (!groups.contains(ADMIN_ROLE)) { | ||
response.sendError( | ||
HttpServletResponse.SC_UNAUTHORIZED, "User does not have admin role"); | ||
return; | ||
} | ||
} else { | ||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "No cognito:groups found"); | ||
return; | ||
} | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
...fiap/grupo30/fastfood/payments_api/infrastructure/persistence/entities/PaymentEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.infrastructure.persistence.entities; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.domain.enums.PaymentStatus; | ||
import jakarta.persistence.*; | ||
import jakarta.validation.constraints.Max; | ||
import jakarta.validation.constraints.Min; | ||
import java.time.Instant; | ||
import lombok.AccessLevel; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@EqualsAndHashCode | ||
@Entity | ||
@Table(name = "tb_payment") | ||
public class PaymentEntity { | ||
@Id | ||
@Column(nullable = false) | ||
private Long orderId; | ||
|
||
@Enumerated(EnumType.STRING) | ||
private PaymentStatus status; | ||
|
||
@Column(nullable = false) | ||
@Min(0) | ||
@Max(10_000) | ||
private Double amount; | ||
|
||
@Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE", updatable = false) | ||
private Instant createdAt; | ||
|
||
@Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE") | ||
private Instant updatedAt; | ||
|
||
@Column(columnDefinition = "TIMESTAMP WITHOUT TIME ZONE") | ||
private Instant deletedAt; | ||
|
||
public PaymentEntity(Long orderId, PaymentStatus status, Double amount) { | ||
this.orderId = orderId; | ||
this.status = status; | ||
this.amount = amount; | ||
} | ||
|
||
@PrePersist | ||
protected void prePersist() { | ||
createdAt = Instant.now(); | ||
} | ||
|
||
@PreUpdate | ||
protected void preUpdate() { | ||
updatedAt = Instant.now(); | ||
} | ||
|
||
@PreRemove | ||
protected void preRemove() { | ||
deletedAt = Instant.now(); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
...0/fastfood/payments_api/infrastructure/persistence/repositories/PaymentJpaRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.infrastructure.persistence.repositories; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.infrastructure.persistence.entities.PaymentEntity; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public interface PaymentJpaRepository extends JpaRepository<PaymentEntity, Long> {} |
36 changes: 36 additions & 0 deletions
36
...p/grupo30/fastfood/payments_api/presentation/controllers/PaymentCollectionController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.presentation.controllers; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.domain.repositories.PaymentRepository; | ||
import br.com.fiap.grupo30.fastfood.payments_api.domain.usecases.CollectPaymentViaCashUseCase; | ||
import br.com.fiap.grupo30.fastfood.payments_api.infrastructure.auth.RequireAdminUserRole; | ||
import br.com.fiap.grupo30.fastfood.payments_api.presentation.dtos.CollectPaymentViaCashRequestDto; | ||
import br.com.fiap.grupo30.fastfood.payments_api.presentation.dtos.PaymentDto; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.parameters.RequestBody; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequestMapping(value = "/payments") | ||
@Tag(name = "Payment collection controller", description = "Manage payment collection") | ||
public class PaymentCollectionController { | ||
|
||
@Autowired private CollectPaymentViaCashUseCase collectPaymentViaCashUseCase; | ||
@Autowired private PaymentRepository paymentRepository; | ||
|
||
@RequireAdminUserRole() | ||
@PostMapping(value = "/{orderId}/collect/cash") | ||
@Operation(summary = "Collect payment by cash") | ||
public ResponseEntity<PaymentDto> collectPaymentByCash( | ||
@PathVariable Long orderId, @RequestBody CollectPaymentViaCashRequestDto request) { | ||
PaymentDto payment = | ||
this.collectPaymentViaCashUseCase.execute( | ||
paymentRepository, orderId, request.getAmount()); | ||
return ResponseEntity.ok().body(payment); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
...fiap/grupo30/fastfood/payments_api/presentation/dtos/CollectPaymentViaCashRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.presentation.dtos; | ||
|
||
import jakarta.validation.constraints.Max; | ||
import jakarta.validation.constraints.Min; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public class CollectPaymentViaCashRequestDto { | ||
@Min(0) | ||
@Max(10_000) | ||
private Double amount; | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/br/com/fiap/grupo30/fastfood/payments_api/presentation/dtos/PaymentDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package br.com.fiap.grupo30.fastfood.payments_api.presentation.dtos; | ||
|
||
import br.com.fiap.grupo30.fastfood.payments_api.domain.enums.PaymentStatus; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
public class PaymentDto { | ||
private PaymentStatus status; | ||
private Double amount; | ||
} |