Skip to content

Commit

Permalink
Merge pull request #16 from jv-jun23-team5/feat-payment
Browse files Browse the repository at this point in the history
[PAYMENT] Implemented beta controller and service, added swagger to the controller
  • Loading branch information
ivan0dyatlyukkk authored Oct 4, 2023
2 parents ea2d11a + 3aa6990 commit 38125cb
Show file tree
Hide file tree
Showing 26 changed files with 357 additions and 293 deletions.
15 changes: 7 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase.version}</version>
</dependency>
Expand All @@ -49,9 +49,9 @@
<version>${liquibase.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
Expand Down Expand Up @@ -79,9 +79,9 @@
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
<groupId>com.stripe</groupId>
<artifactId>stripe-java</artifactId>
<version>23.7.0</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
Expand Down Expand Up @@ -164,5 +164,4 @@
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.project.carsharingapp.controller;

import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto;
import com.project.carsharingapp.model.Payment;
import com.project.carsharingapp.service.PaymentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "Payment management", description = "Endpoint for managing payments")
@RestController
@RequestMapping("/payments")
@RequiredArgsConstructor
public class PaymentController {
private final PaymentService paymentService;

@GetMapping
@Operation(summary = "Get all user's payments")
public List<Payment> getAll(Pageable pageable) {
return paymentService.getAll(pageable);
}

@PostMapping
@Operation(summary = "Create a new payment session")
public Payment create(
@RequestBody @Valid CreatePaymentSessionRequestDto requestDto
) {
return paymentService.create(requestDto);
}

@GetMapping("/success")
@Operation(summary = "Redirect endpoint in case of successful payment")
private String redirectToSuccessPage(@RequestParam String sessionId) {
paymentService.updateStatus(sessionId);
return "success";
}

@GetMapping("/cancel")
@Operation(summary = "Redirect endpoint in case of paused payment")
private String redirectToFailedPage() {
return "cancel";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.project.carsharingapp.dto.rental.CreateRentalRequestDto;
import com.project.carsharingapp.dto.rental.RentalDto;
import com.project.carsharingapp.dto.rental.SetActualReturnDateRequestDto;
import com.project.carsharingapp.service.rental.RentalService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
Expand Down Expand Up @@ -57,7 +56,7 @@ public RentalDto getById(@PathVariable Long id) {
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "Set actual return date",
description = "Set actual return date and increase car inventory by 1")
public RentalDto setActualReturnDay(Long id) { // Authnetication
public RentalDto setActualReturnDay(Long id) {
return rentalService.setActualReturnDay(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.project.carsharingapp.dto.payment;

import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class CreatePaymentSessionRequestDto {
@NotNull
private Long rentalId;
@NotNull
private String type;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.project.carsharingapp.dto.payment;

public class PaymentResponseDto {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.project.carsharingapp.dto.rental;

public record RentalSearchParametersDto(String[] userId,
String[] isActive) {
}
public record RentalSearchParametersDto(
String[] userId,
String[] isActive
) {
}
2 changes: 1 addition & 1 deletion src/main/java/com/project/carsharingapp/model/Payment.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class Payment {
private Type type;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "rental_id", nullable = false)
private Rental rentalId;
private Rental rental;
@Column(name = "session_url", nullable = false)
private String sessionUrl;
@Column(name = "session_id", nullable = false)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.project.carsharingapp.repository;

import com.project.carsharingapp.model.Payment;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PaymentRepository extends JpaRepository<Payment, Long> {
Optional<Payment> findBySessionId(String sessionId);

Page<Payment> findAll(Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@

@Repository
public interface RentalRepository extends JpaRepository<Rental, Long> {
@Query("FROM Rental r LEFT JOIN FETCH r.car "
+ "LEFT JOIN FETCH r.user WHERE r.id = :id")
Optional<Rental> findById(Long id);

@Query("FROM Rental r WHERE r.user.id = :userId AND r.isActive = :isActive")
List<Rental> findRentalsByUserIdAndActiveStatus(Long userId, boolean isActive);

// @Query("FROM Rental r WHERE r.user.id = :userId AND r.isActive = :isActive")
// Optional<Rental>findRentalByUserIdAndActiveStatus(Long userId, boolean isActive);


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.project.carsharingapp.repository.rentals.spec;


import static com.project.carsharingapp.repository.rentals.RentalSpecificationBuilder.USER_ID_KEY;

import com.project.carsharingapp.model.Rental;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.project.carsharingapp.service;

import com.project.carsharingapp.model.Payment;
import java.math.BigDecimal;

public interface PaymentAmountHandler {
Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays);

boolean isApplicable(Payment.Type type);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.project.carsharingapp.service;

import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto;
import com.project.carsharingapp.model.Payment;
import java.util.List;
import org.springframework.data.domain.Pageable;

public interface PaymentService {
Payment create(CreatePaymentSessionRequestDto requestDto);

Payment updateStatus(String sessionId);

List<Payment> getAll(Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.project.carsharingapp.service.impl;

import com.project.carsharingapp.model.Payment;
import com.project.carsharingapp.service.PaymentAmountHandler;
import java.math.BigDecimal;
import org.springframework.stereotype.Component;

@Component
public class FineAmountHandler implements PaymentAmountHandler {
private static final BigDecimal FINE_MULTIPLIER = BigDecimal.valueOf(1.25);

@Override
public Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays) {
return dailyFee.multiply(FINE_MULTIPLIER).longValue() * numberOfDays;
}

@Override
public boolean isApplicable(Payment.Type type) {
return type.equals(Payment.Type.FINE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.project.carsharingapp.service.impl;

import com.project.carsharingapp.model.Payment;
import com.project.carsharingapp.service.PaymentAmountHandler;
import java.util.List;
import java.util.NoSuchElementException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class PaymentAmountHandlerStrategy {
@Autowired
private List<PaymentAmountHandler> paymentAmountHandlers;

public PaymentAmountHandler getHandler(Payment.Type type) {
return paymentAmountHandlers.stream()
.filter(paymentAmountHandler -> paymentAmountHandler.isApplicable(type))
.findAny()
.orElseThrow(() ->
new NoSuchElementException("Can't find a PaymentAmountHandler "
+ "for such type as: " + type)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.project.carsharingapp.service.impl;

import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto;
import com.project.carsharingapp.exception.EntityNotFoundException;
import com.project.carsharingapp.model.Payment;
import com.project.carsharingapp.model.Rental;
import com.project.carsharingapp.repository.PaymentRepository;
import com.project.carsharingapp.repository.rentals.RentalRepository;
import com.project.carsharingapp.service.PaymentService;
import com.stripe.exception.StripeException;
import com.stripe.model.checkout.Session;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class PaymentServiceImpl implements PaymentService {
private final RentalRepository rentalRepository;
private final PaymentRepository paymentRepository;
private final StripeService stripeService;

@Override
public Payment create(CreatePaymentSessionRequestDto requestDto) {
Rental rental = rentalRepository.findById(requestDto.getRentalId()).orElseThrow(
() -> new EntityNotFoundException("Can't find a Rental by id: "
+ requestDto.getRentalId())
);
Payment.Type type = Payment.Type.valueOf(requestDto.getType());
try {
Session session = stripeService.createSession(rental, type);
Payment payment = generatePayment(session, rental, type);
return paymentRepository.save(payment);
} catch (StripeException e) {
throw new RuntimeException("Can't create a stripe checkout session!");
}
}

@Override
public Payment updateStatus(String sessionId) {
Payment payment = paymentRepository.findBySessionId(sessionId).orElseThrow(
() -> new EntityNotFoundException("Can't find a Payment by the session")
);
payment.setStatus(Payment.Status.PAID);
return paymentRepository.save(payment);
}

@Override
public List<Payment> getAll(Pageable pageable) {
return paymentRepository.findAll(pageable).stream().collect(Collectors.toList());
}

private Payment generatePayment(Session session, Rental rental, Payment.Type type) {
Payment payment = new Payment();
payment.setStatus(Payment.Status.PENDING);
payment.setType(type);
payment.setRental(rental);
payment.setSessionUrl(session.getUrl());
payment.setSessionId(session.getId());
payment.setAmount(BigDecimal.valueOf(session.getAmountTotal()));
return payment;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.project.carsharingapp.service.impl;

import com.project.carsharingapp.model.Payment;
import com.project.carsharingapp.service.PaymentAmountHandler;
import java.math.BigDecimal;
import org.springframework.stereotype.Component;

@Component
public class RegularPaymentAmountHandler implements PaymentAmountHandler {
@Override
public Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays) {
return dailyFee.longValue() * numberOfDays;
}

@Override
public boolean isApplicable(Payment.Type type) {
return type.equals(Payment.Type.PAYMENT);
}
}
Loading

0 comments on commit 38125cb

Please sign in to comment.