Skip to content

Commit

Permalink
Merge pull request #4 from AntonBabychP1T/rental-feature
Browse files Browse the repository at this point in the history
[API] Add RentalController. Add Rental model, RentalService and other…
  • Loading branch information
AntonBabychP1T authored Jan 14, 2024
2 parents fd05fc5 + bee1c9b commit 7418362
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 1 deletion.
50 changes: 50 additions & 0 deletions src/main/java/service/carsharing/controller/RentalController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package service.carsharing.controller;

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.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;
import service.carsharing.dto.rental.RentalRequestDto;
import service.carsharing.dto.rental.RentalResponseDto;
import service.carsharing.service.RentalService;

@Tag(name = "Rental managing", description = "Endpoint to rentals managing")
@RequiredArgsConstructor
@RestController
@RequestMapping("api/rentals")
public class RentalController {
private final RentalService rentalService;

@PostMapping()
@Operation(summary = "Create a new rental", description = "Create a new rental")
public RentalResponseDto addRental(@RequestBody @Valid RentalRequestDto requestDto) {
return rentalService.addNewRental(requestDto);
}

@GetMapping("/{userId}/{isActive}")
@Operation(summary = "Get all active rentals",
description = "Get list of all active rentals for specify user")
public List<RentalResponseDto> getAllActiveRentals(@PathVariable Long userId,
@PathVariable boolean isActive) {
return rentalService.getAllCurrentRentals(userId, isActive);
}

@GetMapping("/{id}")
@Operation(summary = "Get rental by id", description = "Get specify rental by id")
public RentalResponseDto getRental(@PathVariable Long id, Authentication authentication) {
return rentalService.getRentalById(id, authentication.getName());
}

@PostMapping("/{id}/return")
public RentalResponseDto returnRental(@PathVariable Long id, Authentication authentication) {
return rentalService.returnRental(id, authentication.getName());
}
}
16 changes: 16 additions & 0 deletions src/main/java/service/carsharing/dto/rental/RentalRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package service.carsharing.dto.rental;

import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;

public record RentalRequestDto(
@NotNull
LocalDate rentalDate,
@NotNull
LocalDate returnDate,
@NotNull
Long carId,
@NotNull
Long userId
) {
}
12 changes: 12 additions & 0 deletions src/main/java/service/carsharing/dto/rental/RentalResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package service.carsharing.dto.rental;

import java.time.LocalDate;

public record RentalResponseDto(
LocalDate rentalDate,
LocalDate returnDate,
LocalDate actualReturnDate,
Long carId,
Long userId
) {
}
19 changes: 19 additions & 0 deletions src/main/java/service/carsharing/mapper/RentalMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package service.carsharing.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import service.carsharing.config.MapperConfig;
import service.carsharing.dto.rental.RentalRequestDto;
import service.carsharing.dto.rental.RentalResponseDto;
import service.carsharing.model.Rental;

@Mapper(config = MapperConfig.class)
public interface RentalMapper {
@Mapping(target = "user.id", source = "userId")
@Mapping(target = "car.id", source = "carId")
Rental toModel(RentalRequestDto requestDto);

@Mapping(target = "userId", source = "user.id")
@Mapping(target = "carId", source = "car.id")
RentalResponseDto toDto(Rental rental);
}
47 changes: 47 additions & 0 deletions src/main/java/service/carsharing/model/Rental.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package service.carsharing.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PreRemove;
import jakarta.persistence.Table;
import java.time.LocalDate;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
@Entity
@Table(name = "rentals")
public class Rental {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private LocalDate rentalDate;
@Column(nullable = false)
private LocalDate returnDate;
private LocalDate actualReturnDate;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToOne
@JoinColumn(name = "car_id", nullable = false)
private Car car;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column(nullable = false)
private boolean deleted = false;

@PreRemove
public void preRemove() {
this.deleted = true;
}

}
12 changes: 12 additions & 0 deletions src/main/java/service/carsharing/repository/RentalRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package service.carsharing.repository;

import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import service.carsharing.model.Rental;

public interface RentalRepository extends JpaRepository<Rental, Long> {
Optional<Rental> findByIdAndUserIdAndDeletedFalse(Long rentalId, Long userId);

List<Rental> getAllByUserIdAndDeletedFalse(Long id);
}
15 changes: 15 additions & 0 deletions src/main/java/service/carsharing/service/RentalService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package service.carsharing.service;

import java.util.List;
import service.carsharing.dto.rental.RentalRequestDto;
import service.carsharing.dto.rental.RentalResponseDto;

public interface RentalService {
RentalResponseDto addNewRental(RentalRequestDto requestDto);

List<RentalResponseDto> getAllCurrentRentals(Long userId, boolean isActive);

RentalResponseDto getRentalById(Long id, String email);

RentalResponseDto returnRental(Long rentalId, String email);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package service.carsharing.service.impl;

import jakarta.persistence.EntityNotFoundException;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import service.carsharing.dto.rental.RentalRequestDto;
import service.carsharing.dto.rental.RentalResponseDto;
import service.carsharing.mapper.RentalMapper;
import service.carsharing.model.Car;
import service.carsharing.model.Rental;
import service.carsharing.model.User;
import service.carsharing.repository.CarRepository;
import service.carsharing.repository.RentalRepository;
import service.carsharing.repository.UserRepository;
import service.carsharing.service.RentalService;

@RequiredArgsConstructor
@Service
public class RentalServiceImpl implements RentalService {
private final RentalRepository rentalRepository;
private final UserRepository userRepository;
private final CarRepository carRepository;
private final RentalMapper rentalMapper;

@Override
@Transactional
public RentalResponseDto addNewRental(RentalRequestDto requestDto) {
Car car = getCarById(requestDto.carId());
car.setInventory(car.getInventory() - 1);
carRepository.save(car);
return rentalMapper.toDto(rentalRepository.save(rentalMapper.toModel(requestDto)));
}

@Override
public List<RentalResponseDto> getAllCurrentRentals(Long userId, boolean isActive) {
List<Rental> allRentalsByUser = rentalRepository.getAllByUserIdAndDeletedFalse(userId);
if (isActive) {
return allRentalsByUser.stream()
.filter(rental -> rental.getActualReturnDate() == null)
.map(rentalMapper::toDto)
.toList();
}
return allRentalsByUser.stream()
.filter(rental -> rental.getActualReturnDate() != null)
.map(rentalMapper::toDto)
.toList();
}

@Override
public RentalResponseDto getRentalById(Long id, String email) {
Rental rental = getRentalByIdAndUserId(id, getUserByEmail(email).getId());
return rentalMapper.toDto(rental);
}

@Override
@Transactional
public RentalResponseDto returnRental(Long rentalId, String email) {
Rental rental = getRentalByIdAndUserId(rentalId, getUserByEmail(email).getId());
Car car = getCarById(rental.getCar().getId());
car.setInventory(car.getInventory() + 1);
rental.setActualReturnDate(LocalDate.now());
return rentalMapper.toDto(rentalRepository.save(rental));
}

private User getUserByEmail(String email) {
return userRepository.findByEmail(email).orElseThrow(
() -> new EntityNotFoundException("Can't find user with email: " + email)
);
}

private Rental getRentalByIdAndUserId(Long rentalId, Long userId) {
return rentalRepository
.findByIdAndUserIdAndDeletedFalse(rentalId, userId).orElseThrow(
() -> new EntityNotFoundException("Can't find rental with id: " + rentalId)
);
}

private Car getCarById(Long id) {
return carRepository.findByIdAndDeletedFalse(id).orElseThrow(
() -> new EntityNotFoundException("Can't find car with id: " + id)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ databaseChangeLog:
- column:
name: deleted
type: boolean
value: 0
constraints:
nullable: false
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ databaseChangeLog:
- column:
name: deleted
type: boolean
value: 0
constraints:
nullable: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
databaseChangeLog:
- changeSet:
id: create-rentals-table
author: antonbabych
changes:
- createTable:
tableName: rentals
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: rental_date
type: date
constraints:
nullable: false
- column:
name: return_date
type: date
constraints:
nullable: false
- column:
name: actual_return_date
type: date
- column:
name: car_id
type: bigint
constraints:
nullable: false
foreignKeyName: fk_rentals_cars
references: cars(id)
- column:
name: user_id
type: bigint
constraints:
nullable: false
foreignKeyName: fk_rentals_users
references: users(id)
- column:
name: deleted
type: boolean
value: 0
constraints:
nullable: false
4 changes: 3 additions & 1 deletion src/main/resources/db/changelog/db.changelog-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ databaseChangeLog:
- include:
file: db/changelog/changes/05-create-default-manager-user.yaml
- include:
file: db/changelog/changes/06-create-cars-table.yaml
file: db/changelog/changes/06-create-cars-table.yaml
- include:
file: db/changelog/changes/07-create-rentals-table.yaml

0 comments on commit 7418362

Please sign in to comment.