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

[API] Add RentalController. Add Rental model, RentalService and other… #4

Merged
merged 1 commit into from
Jan 14, 2024
Merged
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
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
Loading