Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #159 from SE-TINF22B2/Story-#95
Browse files Browse the repository at this point in the history
Story #95 - Fahrgemeinschaftenwidget
  • Loading branch information
Drumber authored Jun 5, 2024
2 parents 6796adb + 744c94c commit eac660e
Show file tree
Hide file tree
Showing 52 changed files with 1,378 additions and 56 deletions.
1 change: 1 addition & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-validation'

implementation 'org.mapstruct:mapstruct:1.5.3.Final'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void leaveEvent(AuthenticatedPrincipal principal, String eventId) {
}

@PreAuthorize("hasRole('GUEST')")
public List<EventParticipantDto> getAllEventParticipantsById(Event event) {
public List<EventParticipantDto> getAllEventParticipants(Event event) {
return userService.getSimpleUsersById(event.getParticipantsAndLeftParticipants())
.stream()
.map(user -> eventMapper.toEventParticipantDto(user, event.hasUserLeftEvent(user.getId())))
Expand All @@ -134,7 +134,7 @@ public List<EventParticipantDto> getAllEventParticipantsById(Event event) {

@PreAuthorize("hasRole('GUEST')")
public EventDetailDto mapEventToEventDetailDto(Optional<String> currentUserId, Event event) {
List<EventParticipantDto> participantsDtos = getAllEventParticipantsById(event);
List<EventParticipantDto> participantsDtos = getAllEventParticipants(event);
return eventMapper.toEventDetailDto(event, participantsDtos, currentUserId);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.dhbw.get2gether.backend.widget.adapter.in;

import com.dhbw.get2gether.backend.event.model.Event;
import com.dhbw.get2gether.backend.event.model.EventDetailDto;
import com.dhbw.get2gether.backend.widget.application.CarpoolWidgetService;
import com.dhbw.get2gether.backend.widget.model.carpool.CarAddCommand;
import com.dhbw.get2gether.backend.widget.model.carpool.CarpoolCreateCommand;
import com.dhbw.get2gether.backend.widget.model.carpool.CarpoolWidget;
import com.dhbw.get2gether.backend.widget.model.carpool.RiderAddCommand;
import com.dhbw.get2gether.backend.widget.model.carpool.*;
import jakarta.validation.Valid;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.*;
Expand All @@ -21,33 +20,48 @@ public CarpoolWidgetController (CarpoolWidgetService service){
}

@PostMapping("/")
public Event createCarpoolWidget(
public EventDetailDto createCarpoolWidget(
@AuthenticationPrincipal OAuth2User principal,
@PathVariable String eventId,
@RequestBody CarpoolCreateCommand createCommand
) {
return service.createCarpoolWidget(principal, eventId, createCommand);
Event event = service.createCarpoolWidget(principal, eventId, createCommand);
return service.mapEventToEventDetailDto(principal, event);
}

@PostMapping("/{widgetId}/cars")
public CarpoolWidget addCar(
public CarpoolWidgetDto addCar(
@AuthenticationPrincipal OAuth2User principal,
@PathVariable String eventId,
@PathVariable String widgetId,
@RequestBody CarAddCommand addCommand
@RequestBody @Valid CarAddCommand addCommand
) {
return service.addCar(principal, eventId, widgetId, addCommand);
}

@PatchMapping("/{widgetId}/cars/{carId}")
public CarpoolWidgetDto updateCar(
@AuthenticationPrincipal OAuth2User principal,
@PathVariable String eventId,
@PathVariable String widgetId,
@PathVariable String carId,
@RequestBody @Valid CarUpdateCommand updateCommand
) {
return service.updateCar(principal, eventId, widgetId, carId, updateCommand);
}

@DeleteMapping("/{widgetId}/cars/{carId}")
public CarpoolWidget removeCar(
public CarpoolWidgetDto removeCar(
@AuthenticationPrincipal OAuth2User principal,
@PathVariable String eventId,
@PathVariable String widgetId,
@PathVariable String carId
) {
return service.removeCar(principal, eventId, widgetId, carId);
}

@PostMapping("/{widgetId}/cars/{carId}")
public CarpoolWidget addRider(
public CarpoolWidgetDto addRider(
@AuthenticationPrincipal OAuth2User principal,
@PathVariable String eventId,
@PathVariable String widgetId,
Expand All @@ -56,8 +70,9 @@ public CarpoolWidget addRider(
) {
return service.addRider(principal, eventId, widgetId,carId, addCommand);
}

@DeleteMapping("/{widgetId}/cars/{carId}/riders/{riderId}")
public CarpoolWidget removeRider(
public CarpoolWidgetDto removeRider(
@AuthenticationPrincipal OAuth2User principal,
@PathVariable String eventId,
@PathVariable String widgetId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,36 @@

import com.dhbw.get2gether.backend.event.application.EventService;
import com.dhbw.get2gether.backend.event.model.Event;
import com.dhbw.get2gether.backend.event.model.EventParticipantDto;
import com.dhbw.get2gether.backend.exceptions.EntityNotFoundException;
import com.dhbw.get2gether.backend.user.application.UserService;
import com.dhbw.get2gether.backend.widget.application.mapper.CarpoolWidgetMapper;
import com.dhbw.get2gether.backend.widget.application.mapper.WidgetMapper;
import com.dhbw.get2gether.backend.widget.model.carpool.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.AuthenticatedPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Stream;

@Service
public class CarpoolWidgetService extends AbstractWidgetService{
public class CarpoolWidgetService extends AbstractWidgetService {

private final CarpoolWidgetMapper mapper;
private final UserService userService;
private final WidgetMapper widgetMapper;

CarpoolWidgetService(EventService eventService, CarpoolWidgetMapper mapper, UserService userService) {
CarpoolWidgetService(EventService eventService, CarpoolWidgetMapper mapper, UserService userService, WidgetMapper widgetMapper) {
super(eventService);
this.mapper = mapper;
this.userService = userService;
this.widgetMapper = widgetMapper;
}

@PreAuthorize("hasRole('USER')")
Expand All @@ -37,19 +45,38 @@ public Event createCarpoolWidget(AuthenticatedPrincipal principal, String eventI
}

@PreAuthorize("hasRole('USER')")
public CarpoolWidget addCar(AuthenticatedPrincipal principal, String eventId, String widgetId, CarAddCommand addCommand) {
public CarpoolWidgetDto addCar(AuthenticatedPrincipal principal, String eventId, String widgetId, CarAddCommand addCommand) {
Event event = getEventById(principal, eventId);
CarpoolWidget widget = getWidgetFromEvent(event, widgetId);

Car car = mapper.mapToCar(addCommand).toBuilder()
.id(UUID.randomUUID().toString())
.driverId(userService.getUserByPrincipal(principal).getId())
.build();

widget.addCar(car);
return updateAndGetWidget(principal, event, widget);
return mapToDto(updateAndGetWidget(principal, event, widget), event);
}

@PreAuthorize("hasRole('USER')")
public CarpoolWidget removeCar(AuthenticatedPrincipal principal, String eventId, String widgetId, String carId) {
public CarpoolWidgetDto updateCar(OAuth2User principal, String eventId, String widgetId, String carId, CarUpdateCommand updateCommand) {
Event event = getEventById(principal, eventId);
CarpoolWidget widget = getWidgetFromEvent(event, widgetId);
Car originalCar = widget.getCars().stream()
.filter(l -> Objects.equals(l.getId(), carId)).findFirst()
.orElseThrow(() -> new EntityNotFoundException("Car not found"));
Car updatedCar = mapper.mapToCar(updateCommand).toBuilder()
.id(originalCar.getId())
.driverId(originalCar.getDriverId())
.riders(originalCar.getRiders())
.build();
if (!widget.replaceCar(originalCar, updatedCar)) {
throw new IllegalStateException("Failed to replace car from carpool widget");
}
return mapToDto(updateAndGetWidget(principal, event, widget), event);
}

@PreAuthorize("hasRole('USER')")
public CarpoolWidgetDto removeCar(AuthenticatedPrincipal principal, String eventId, String widgetId, String carId) {
Event event = getEventById(principal, eventId);
CarpoolWidget widget = getWidgetFromEvent(event, widgetId);
Car car = widget.getCars().stream()
Expand All @@ -58,10 +85,11 @@ public CarpoolWidget removeCar(AuthenticatedPrincipal principal, String eventId,
if (!widget.removeCar(car)) {
throw new IllegalStateException("Failed to remove Car from Carpool widget");
}
return updateAndGetWidget(principal, event, widget);
return mapToDto(updateAndGetWidget(principal, event, widget), event);
}

@PreAuthorize("hasRole('USER')")
public CarpoolWidget addRider(AuthenticatedPrincipal principal, String eventId, String widgetId, String carId, RiderAddCommand addCommand) {
public CarpoolWidgetDto addRider(AuthenticatedPrincipal principal, String eventId, String widgetId, String carId, RiderAddCommand addCommand) {
Event event = getEventById(principal, eventId);
CarpoolWidget widget = getWidgetFromEvent(event, widgetId);
Car car = widget.getCars().stream()
Expand All @@ -72,22 +100,47 @@ public CarpoolWidget addRider(AuthenticatedPrincipal principal, String eventId,
.userId(userService.getUserByPrincipal(principal).getId())
.build();
car.addRider(rider);
return updateAndGetWidget(principal, event, widget);
return mapToDto(updateAndGetWidget(principal, event, widget), event);
}

@PreAuthorize("hasRole('USER')")
public CarpoolWidget removeRider(AuthenticatedPrincipal principal, String eventId, String widgetId, String carId, String riderId) {
public CarpoolWidgetDto removeRider(AuthenticatedPrincipal principal, String eventId, String widgetId, String carId, String riderId) {
Event event = getEventById(principal, eventId);
CarpoolWidget widget = getWidgetFromEvent(event, widgetId);
Car car = widget.getCars().stream()
.filter(c -> Objects.equals(c.getId(), carId)).findFirst()
.orElseThrow(() -> new EntityNotFoundException("Car not found"));
Rider rider = car.getRiders().stream()
.filter(r -> Objects.equals(r.getId(), riderId)).findFirst()
.filter(r -> Objects.equals(r.getUserId(), riderId)).findFirst()
.orElseThrow(() -> new EntityNotFoundException("Rider not found"));
if (!car.removeRider(rider)) {
throw new IllegalStateException("Failed to remove rider from car");
}
return updateAndGetWidget(principal, event, widget);
return mapToDto(updateAndGetWidget(principal, event, widget), event);
}

private CarpoolWidgetDto mapToDto(CarpoolWidget widget, Event event) {
List<EventParticipantDto> participantDtos = eventService.getAllEventParticipants(event);
List<EventParticipantDto> riders = widget.getCars().stream()
.flatMap(car -> car.getRiders().stream())
.map(Rider::getUserId)
.map(riderId -> participantDtos.stream().filter(participant -> Objects.equals(riderId, participant.getId())).findFirst())
.filter(Optional::isPresent)
.map(Optional::get)
.toList();

List<EventParticipantDto> drivers = widget.getCars().stream()
.map(Car::getDriverId)
.map(driverId -> participantDtos.stream().filter(participant -> Objects.equals(driverId, participant.getId())).findFirst())
.filter(Optional::isPresent)
.map(Optional::get)
.toList();

List<EventParticipantDto> combinedList = Stream.concat(
riders.stream(),
drivers.stream()
).toList();

return widgetMapper.carpoolWidgetToCarpoolWidgetDto(widget, combinedList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public ExpenseSplitWidgetDto updateEntry(AuthenticatedPrincipal principal, Strin
}

private ExpenseSplitWidgetDto mapToDto(ExpenseSplitWidget widget, Event event, AuthenticatedPrincipal principal) {
List<EventParticipantDto> eventParticipantDtos = eventService.getAllEventParticipantsById(event);
List<EventParticipantDto> eventParticipantDtos = eventService.getAllEventParticipants(event);
User user = userService.getUserByPrincipal(principal);
List<Debt> debts = widget.calculateDebtsForUserId(user.getId());
return widgetMapper.expenseSplitWidgetToExpenseSplitWidgetDto(widget, debts, eventParticipantDtos);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public interface CarpoolWidgetMapper {
@Mapping(target = "riders", ignore = true)
Car mapToCar(CarAddCommand command);

@Mapping(target = "id", ignore = true)
@Mapping(target = "driverId", ignore = true)
@Mapping(target = "riders", ignore = true)
Car mapToCar(CarUpdateCommand command);

@Mapping(target = "id", ignore = true)
@Mapping(target = "userId", ignore = true)
Rider mapToRider(RiderAddCommand command);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.dhbw.get2gether.backend.event.model.EventParticipantDto;
import com.dhbw.get2gether.backend.widget.model.IWidget;
import com.dhbw.get2gether.backend.widget.model.Widget;
import com.dhbw.get2gether.backend.widget.model.carpool.*;
import com.dhbw.get2gether.backend.widget.model.expensesplit.*;
import org.mapstruct.Context;
import org.mapstruct.Mapper;
Expand All @@ -23,10 +24,34 @@ public IWidget widgetToIWidget(Widget widget, @Context List<EventParticipantDto>
List<Debt> debts = userId.map(id -> ((ExpenseSplitWidget) widget).calculateDebtsForUserId(id))
.orElse(new ArrayList<>());
return expenseSplitWidgetToExpenseSplitWidgetDto((ExpenseSplitWidget) widget, debts, participants);
} else if (widget instanceof CarpoolWidget) {
return carpoolWidgetToCarpoolWidgetDto((CarpoolWidget) widget, participants);
}
return widget;
}

public CarpoolWidgetDto carpoolWidgetToCarpoolWidgetDto(CarpoolWidget widget, List<EventParticipantDto> participants) {
List<CarDto> cars = widget.getCars().stream()
.map(car -> CarDto.builder()
.id(car.getId())
.driver(participants.stream().filter(r -> r.getId().equals(car.getDriverId())).findFirst().orElse(null))
.driverAdress(car.getDriverAdress())
.anzahlPlaetze(car.getAnzahlPlaetze())
.riders(car.getRiders().stream().map(rider -> RiderDto.builder()
.user(participants.stream().filter(r -> r.getId().equals(rider.getUserId()))
.findFirst()
.orElse(null))
.pickupPlace(rider.getPickupPlace())
.build()).toList())
.build()).toList();

return CarpoolWidgetDto.builder()
.id(widget.getId())
.creationDate(widget.getCreationDate())
.cars(cars)
.build();
}

public abstract ExpenseSplitWidgetDto expenseSplitWidgetToExpenseSplitWidgetDto(ExpenseSplitWidget widget, List<Debt> debts, @Context List<EventParticipantDto> participants);

// Find the userWithPercentage in the list of participants. Return null if the user is not found.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.dhbw.get2gether.backend.widget.model.carpool;

import com.dhbw.get2gether.backend.exceptions.OperationNotAllowedException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Builder(toBuilder = true)
@Getter
Expand All @@ -19,10 +21,18 @@ public class Car {
private List<Rider> riders = new ArrayList<>();

public void addRider(Rider rider) {
if (riders.stream().anyMatch(r -> Objects.equals(r.getUserId(), rider.getUserId())))
throw new OperationNotAllowedException("Rider already exists");
if (riders.size() >= anzahlPlaetze)
throw new OperationNotAllowedException("Car is already full");
if (Objects.equals(driverId, rider.getUserId()))
throw new OperationNotAllowedException("Driver cannot be added as rider");
riders.add(rider);
}

public boolean removeRider(Rider rider) {
if (!riders.contains(rider))
throw new OperationNotAllowedException("Rider does not exist");
return riders.remove(rider);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dhbw.get2gether.backend.widget.model.carpool;


import jakarta.validation.constraints.Min;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -10,5 +11,6 @@
@Builder(toBuilder = true)
public class CarAddCommand {
private String driverAdress;
@Min(1)
private int anzahlPlaetze;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.dhbw.get2gether.backend.widget.model.carpool;

import com.dhbw.get2gether.backend.event.model.EventParticipantDto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
@Builder(toBuilder = true)
@AllArgsConstructor
public class CarDto {
private String id;
private EventParticipantDto driver;
private String driverAdress;
private int anzahlPlaetze;
private List<RiderDto> riders;

}
Loading

0 comments on commit eac660e

Please sign in to comment.