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

PR: Inferius Endpoints #78

Merged
merged 12 commits into from
Jan 23, 2025
Original file line number Diff line number Diff line change
@@ -1,4 +1,84 @@
package pwr.jakprzyjade.inferius.creditcardinfo.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import pwr.jakprzyjade.inferius.creditcardinfo.database.CreateCreditCardDto;
import pwr.jakprzyjade.inferius.creditcardinfo.database.CreditCardDto;
import pwr.jakprzyjade.inferius.creditcardinfo.database.UpdateCreditCardDto;
import pwr.jakprzyjade.inferius.creditcardinfo.service.CreditCardInfoService;
import pwr.jakprzyjade.inferius.shared.UUIDv7Validator;
import pwr.jakprzyjade.inferius.shared.UserRole;
import pwr.jakprzyjade.inferius.shared.UserRoles;

import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/ext/v1/cards")
@RequiredArgsConstructor
@Tag(name = "Credit Card", description = "Operations related to credit cards")
public class CreditCardInfoController {

private final CreditCardInfoService creditCardInfoService;
private final UUIDv7Validator uuiDv7Validator;

@UserRoles(UserRole.PASSENGER)
@GetMapping
@Operation(summary = "Retrieve credit cards", description = "Pobranie listy kart płatniczych.")
public ResponseEntity<List<CreditCardDto>> getCreditCards(
@RequestHeader("jp-user-id") UUID userId
) {
List<CreditCardDto> cards = creditCardInfoService.getCreditCards(userId);
return ResponseEntity.ok(cards);
}

@UserRoles(UserRole.PASSENGER)
@PutMapping("/{id}")
@Operation(summary = "Update credit card", description = "Zaktualizowanie danych karty płatniczej.")
public ResponseEntity<CreditCardDto> updateCreditCard(
@RequestHeader("jp-user-id") UUID userId,
@PathVariable("id") String id,
@Valid @RequestBody UpdateCreditCardDto updateDto
) {
if (!uuiDv7Validator.isStringValidUUID(id)) {
throw new IllegalArgumentException("Invalid cardId format. It must be a valid UUIDv7.");
}

UUID cardId = UUID.fromString(id);

CreditCardDto updatedCard = creditCardInfoService.updateCreditCard(cardId, updateDto, userId);
return ResponseEntity.ok(updatedCard);
}

@UserRoles(UserRole.PASSENGER)
@DeleteMapping("/{id}")
@Operation(summary = "Delete credit card", description = "Usunięcie karty płatniczej.")
public ResponseEntity<Void> deleteCreditCard(
@RequestHeader("jp-user-id") UUID userId,
@PathVariable("id") String id
) {
if (!uuiDv7Validator.isStringValidUUID(id)) {
throw new IllegalArgumentException("Invalid cardId format. It must be a valid UUIDv7.");
}

UUID cardId = UUID.fromString(id);
creditCardInfoService.deleteCreditCard(cardId, userId);
return ResponseEntity.noContent().build();
}

@UserRoles(UserRole.PASSENGER)
@PostMapping
@Operation(summary = "Add a new credit card", description = "Dodanie nowej karty płatniczej.")
public ResponseEntity<CreditCardDto> addCreditCard(
@RequestHeader("jp-user-id") UUID userId,
@Valid @RequestBody CreateCreditCardDto createDto
) {
CreditCardDto newCard = creditCardInfoService.addCreditCard(userId, createDto);
return ResponseEntity.status(HttpStatus.CREATED).body(newCard);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package pwr.jakprzyjade.inferius.creditcardinfo.database;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CreateCreditCardDto {
@Size(max = 255)
private String label;

@NotNull
@Size(min = 16, max = 16)
private String number;

@NotNull
@Size(min = 1, max = 255)
private String holderName;

@NotNull
private String expirationDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pwr.jakprzyjade.inferius.creditcardinfo.database;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;

import java.util.UUID;

@Data
@AllArgsConstructor
@Getter
@Builder
public class CreditCardDto {
private UUID id;
private String label;
private String number;
private String holderName;
private String expirationDate;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package pwr.jakprzyjade.inferius.creditcardinfo.database;

import org.hibernate.annotations.GenericGenerator;
import pwr.jakprzyjade.inferius.shared.UUIDv7;
import pwr.jakprzyjade.inferius.wallet.database.Wallet;
import jakarta.persistence.*;
Expand All @@ -19,6 +20,8 @@
@Entity
public class CreditCardInfo {
@Id
@GeneratedValue(generator = "uuidv7-gen")
@GenericGenerator(name = "uuidv7-gen", strategy = "src/main/java/pwr/jakprzyjade/inferius/shared/UUIDv7Generator.java")
@UUIDv7
private UUID id;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pwr.jakprzyjade.inferius.creditcardinfo.database;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Repository
public interface CreditCardInfoRepository extends JpaRepository<CreditCardInfo, UUID> {
List<CreditCardInfo> findByWalletPassengerId(UUID passengerId);
Optional<CreditCardInfo> findByIdAndWalletPassengerId(UUID id, UUID passengerId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pwr.jakprzyjade.inferius.creditcardinfo.database;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UpdateCreditCardDto {
@Size(max = 255)
private String label;

@NotNull
private String expirationDate;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,94 @@
package pwr.jakprzyjade.inferius.creditcardinfo.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import pwr.jakprzyjade.inferius.creditcardinfo.database.*;
import pwr.jakprzyjade.inferius.fine.database.Fine;
import pwr.jakprzyjade.inferius.shared.UUIDv7Validator;
import pwr.jakprzyjade.inferius.shared.exceptions.ResourceNotFoundException;
import pwr.jakprzyjade.inferius.wallet.database.Wallet;
import pwr.jakprzyjade.inferius.wallet.database.WalletHistoryRepository;
import pwr.jakprzyjade.inferius.wallet.database.WalletRepository;

import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class CreditCardInfoService {

private final CreditCardInfoRepository creditCardInfoRepository;
private final WalletRepository walletRepository;

public List<CreditCardDto> getCreditCards(UUID userId) {
List<CreditCardInfo> creditCards = creditCardInfoRepository.findByWalletPassengerId(userId);

if (creditCards.isEmpty()) {
throw new ResourceNotFoundException("No credit cards found for user ID: " + userId);
}

return creditCards.stream()
.map(card -> CreditCardDto.builder()
.id(card.getId())
.label(card.getLabel())
.number(card.getNumber())
.holderName(card.getHolderName())
.expirationDate(card.getExpirationDate())
.build())
.toList();
}

public CreditCardDto updateCreditCard(UUID cardId, UpdateCreditCardDto updateDto, UUID userId) {
CreditCardInfo card = creditCardInfoRepository.findByIdAndWalletPassengerId(cardId, userId)
.orElseThrow(() -> new ResourceNotFoundException("Credit card not found or you are not authorized."));

CreditCardInfo updatedCard = CreditCardInfo.builder()
.id(card.getId())
.wallet(card.getWallet())
.number(card.getNumber())
.holderName(card.getHolderName())
.label(updateDto.getLabel() != null ? updateDto.getLabel() : card.getLabel())
.expirationDate(updateDto.getExpirationDate() != null ? updateDto.getExpirationDate() : card.getExpirationDate())
.build();

CreditCardInfo savedCard = creditCardInfoRepository.save(updatedCard);

return CreditCardDto.builder()
.id(savedCard.getId())
.label(savedCard.getLabel())
.number(savedCard.getNumber())
.holderName(savedCard.getHolderName())
.expirationDate(savedCard.getExpirationDate())
.build();
}

public void deleteCreditCard(UUID cardId, UUID userId) {
CreditCardInfo card = creditCardInfoRepository.findByIdAndWalletPassengerId(cardId, userId)
.orElseThrow(() -> new ResourceNotFoundException("Credit card not found or you are not authorized."));

creditCardInfoRepository.delete(card);
}

public CreditCardDto addCreditCard(UUID userId, CreateCreditCardDto createDto) {
Wallet wallet = walletRepository.findByPassengerId(userId)
.orElseThrow(() -> new ResourceNotFoundException("Wallet not found for user ID: " + userId));

CreditCardInfo newCard = CreditCardInfo.builder()
.label(createDto.getLabel())
.number(createDto.getNumber())
.holderName(createDto.getHolderName())
.expirationDate(createDto.getExpirationDate())
.wallet(wallet)
.build();

CreditCardInfo savedCard = creditCardInfoRepository.save(newCard);

return CreditCardDto.builder()
.id(savedCard.getId())
.label(savedCard.getLabel())
.number(savedCard.getNumber())
.holderName(savedCard.getHolderName())
.expirationDate(savedCard.getExpirationDate())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,79 @@
package pwr.jakprzyjade.inferius.fine.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import pwr.jakprzyjade.inferius.fine.database.FineCreateDto;
import pwr.jakprzyjade.inferius.fine.database.FineDto;
import pwr.jakprzyjade.inferius.fine.service.FineService;
import pwr.jakprzyjade.inferius.shared.UUIDv7Validator;
import pwr.jakprzyjade.inferius.shared.UserRole;
import pwr.jakprzyjade.inferius.shared.UserRoles;

import java.util.UUID;

@RestController
@RequiredArgsConstructor
@RequestMapping("/ext/v1/fines")
@Tag(name = "Fines", description = "Operations related to fines")
public class FineController {

private final FineService fineService;
private final UUIDv7Validator uuiDv7Validator;

@UserRoles({UserRole.PASSENGER, UserRole.INSPECTOR})
@GetMapping
@Operation(summary = "Retrieve list of fines", description = "Pobranie listy mandatów.")
public ResponseEntity<Page<FineDto>> getFines(
@RequestHeader("jp-user-id") UUID userId,
Pageable pageable
) {
Page<FineDto> fines = fineService.getFines(userId, pageable);
return ResponseEntity.ok(fines);
}

@UserRoles(UserRole.PASSENGER)
@GetMapping("/{id}")
@Operation(summary = "Retrieve fine details", description = "Pobranie informacji o mandacie.")
public ResponseEntity<FineDto> getFineDetails(
@RequestHeader("jp-user-id") UUID userId,
@PathVariable("id") UUID fineId
) {
FineDto fine = fineService.getFineDetails(userId, fineId);
return ResponseEntity.ok(fine);
}

@UserRoles(UserRole.INSPECTOR)
@PutMapping("/{id}/cancel")
@Operation(summary = "Cancel a fine", description = "Anulowanie mandatu.")
public ResponseEntity<FineDto> cancelFine(
@RequestHeader("jp-user-id") UUID inspectorId,
@PathVariable("id") String id
) {
if (!uuiDv7Validator.isStringValidUUID(id)) {
throw new IllegalArgumentException("Invalid fineId format. It must be a valid UUIDv7.");
}

UUID fineId = UUID.fromString(id);

FineDto cancelledFine = fineService.cancelFine(inspectorId, fineId);
return ResponseEntity.ok(cancelledFine);
}

@UserRoles(UserRole.INSPECTOR)
@PostMapping
@Operation(summary = "Issue a fine", description = "Wystawienie mandatu.")
public ResponseEntity<FineDto> createFine(
@RequestHeader("jp-user-id") UUID inspectorId,
@Valid @RequestBody FineCreateDto fineCreateDto
) {
FineDto createdFine = fineService.createFine(fineCreateDto, inspectorId);
return ResponseEntity.status(HttpStatus.CREATED).body(createdFine);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pwr.jakprzyjade.inferius.fine.database;

import jakarta.validation.constraints.Min;
import org.hibernate.annotations.GenericGenerator;
import pwr.jakprzyjade.inferius.shared.UUIDv7;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
Expand All @@ -22,6 +23,8 @@
public class Fine {

@Id
@GeneratedValue(generator = "uuidv7-gen")
@GenericGenerator(name = "uuidv7-gen", strategy = "src/main/java/pwr/jakprzyjade/inferius/shared/UUIDv7Generator.java")
@UUIDv7
private UUID id;

Expand All @@ -44,6 +47,7 @@ public class Fine {

@Column(nullable = false, updatable = false)
@NotNull
@Builder.Default
private Instant time = Instant.now();

@Enumerated(EnumType.STRING)
Expand All @@ -54,5 +58,6 @@ public class Fine {
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 32)
@NotNull
@Builder.Default
private FineStatus status = FineStatus.UNPAID;
}
Loading