Skip to content

Commit

Permalink
adding complaints endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
KovalBohdan-0 committed Jun 8, 2024
1 parent 594f2f0 commit 7df49ff
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 18 deletions.
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,19 @@
<artifactId>spring-test</artifactId>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package org.petmarket.users.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.petmarket.users.dto.ComplaintResponseDto;
import org.petmarket.users.entity.ComplaintStatus;
import org.petmarket.users.service.ComplaintService;
import org.petmarket.utils.annotations.parametrs.ParameterPageNumber;
import org.petmarket.utils.annotations.parametrs.ParameterPageSize;
import org.petmarket.utils.annotations.responses.ApiResponseForbidden;
import org.petmarket.utils.annotations.responses.ApiResponseNotFound;
import org.petmarket.utils.annotations.responses.ApiResponseSuccessful;
import org.petmarket.utils.annotations.responses.ApiResponseUnauthorized;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "Complaints", description = "the user complaints API")
@Slf4j
@RequiredArgsConstructor
@RestController
@Validated
@RequestMapping(value = "/v1/admin/complaints")
public class ComplaintsAdminController {
private final ComplaintService complaintService;

@Operation(summary = "Delete complaint")
@ApiResponseSuccessful
@ApiResponseUnauthorized
@ApiResponseForbidden
@PreAuthorize("isAuthenticated()")
@DeleteMapping("/{id}")
public void deleteComplaint(@PathVariable Long id) {
log.info("Deleting complaint");
complaintService.deleteComplaint(id);
}

@Operation(summary = "Get complaint")
@ApiResponseSuccessful
@ApiResponseNotFound
@ApiResponseUnauthorized
@ApiResponseForbidden
@PreAuthorize("isAuthenticated()")
@GetMapping("/{id}")
public ComplaintResponseDto getComplaint(@PathVariable Long id) {
log.info("Getting complaint");
return complaintService.getComplaint(id);
}

@Operation(summary = "Get complaints")
@ApiResponseSuccessful
@ApiResponseUnauthorized
@ApiResponseForbidden
@PreAuthorize("isAuthenticated()")
@GetMapping
public List<ComplaintResponseDto> getComplaints(
@RequestParam(required = false, defaultValue = "PENDING") ComplaintStatus complaintStatus,
@ParameterPageNumber @RequestParam(defaultValue = "1") @Positive int page,
@ParameterPageSize @RequestParam(defaultValue = "30") @Positive int size,
@RequestParam(defaultValue = "DESC") Sort.Direction direction) {
log.info("Getting complaints");
return complaintService.getComplaints(complaintStatus, size, page, direction);
}

@Operation(summary = "Get complaints by user id")
@ApiResponseSuccessful
@ApiResponseUnauthorized
@ApiResponseForbidden
@PreAuthorize("isAuthenticated()")
@GetMapping("/user/{userId}")
public List<ComplaintResponseDto> getComplaintsByUserId(
@PathVariable Long userId,
@RequestParam(required = false, defaultValue = "PENDING") ComplaintStatus status,
@ParameterPageNumber @RequestParam(defaultValue = "1") @Positive int page,
@ParameterPageSize @RequestParam(defaultValue = "30") @Positive int size,
@RequestParam(defaultValue = "DESC") Sort.Direction direction) {
log.info("Getting complaints by user id");
return complaintService.getComplaintsByUserId(userId, status, size, page, direction);
}

@Operation(summary = "Update complaint status")
@ApiResponseSuccessful
@ApiResponseUnauthorized
@ApiResponseForbidden
@PreAuthorize("isAuthenticated()")
@PutMapping("/{id}")
public void updateComplaintStatus(@PathVariable Long id,
@RequestParam(defaultValue = "RESOLVED") ComplaintStatus status) {
log.info("Updating complaint status");
complaintService.updateStatusById(id, status);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
package org.petmarket.users.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.petmarket.users.dto.ComplaintRequestDto;
import org.petmarket.users.service.ComplaintService;
import org.petmarket.utils.annotations.responses.ApiResponseBadRequest;
import org.petmarket.utils.annotations.responses.ApiResponseSuccessful;
import org.petmarket.utils.annotations.responses.ApiResponseUnauthorized;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@Tag(name = "Users", description = "the users API")
@Tag(name = "Complaints", description = "the user complaints API")
@Slf4j
@RequiredArgsConstructor
@RestController
@Validated
@RequestMapping(value = "/v1/complaints")
public class ComplaintsController {
private final ComplaintService complaintService;

@Operation(summary = "Add complaint")
@ApiResponseSuccessful
@ApiResponseUnauthorized
@ApiResponseBadRequest
@PreAuthorize("isAuthenticated()")
@PostMapping
public void addComplaint(@RequestBody @Valid ComplaintRequestDto complaintRequestDto) {
log.info("Adding complaint");
complaintService.addComplaint(complaintRequestDto);
}
}
12 changes: 12 additions & 0 deletions src/main/java/org/petmarket/users/dto/ComplaintRequestDto.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package org.petmarket.users.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.springframework.validation.annotation.Validated;

@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Validated
public class ComplaintRequestDto {
@NotBlank(message = "The 'text' cannot be empty")
@Schema(example = "Hello, how are you?")
@Size(max = 10000, message = "The 'text' length must be less than or equal to 10000")
private String complaint;

@Schema(example = "1")
@JsonProperty("complained_user_id")
private Long complainedUserId;
}
20 changes: 20 additions & 0 deletions src/main/java/org/petmarket/users/dto/ComplaintResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.petmarket.users.dto;

import lombok.*;

import java.util.Date;

@Setter
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ComplaintResponseDto {
private Long id;
private String complaint;
private Long userId;
private Long complainedUserId;
private String status;
private Date created;
private Date updated;
}
10 changes: 10 additions & 0 deletions src/main/java/org/petmarket/users/mapper/ComplaintMapper.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package org.petmarket.users.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.petmarket.config.MapperConfig;
import org.petmarket.users.dto.ComplaintRequestDto;
import org.petmarket.users.dto.ComplaintResponseDto;
import org.petmarket.users.entity.Complaint;

import java.util.List;

@Mapper(config = MapperConfig.class)
public interface ComplaintMapper {
Complaint mapDtoToComplaint(ComplaintRequestDto complaintRequestDto);

@Mapping(target = "userId", source = "user.id")
@Mapping(target = "complainedUserId", source = "complainedUser.id")
ComplaintResponseDto mapComplaintToDto(Complaint complaint);

List<ComplaintResponseDto> mapComplaintToDto(List<Complaint> complaints);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface ComplaintRepository extends JpaRepository<Complaint, Long> {
Page<Complaint> findAllByComplainedUserIdAndStatus(Long userId, ComplaintStatus complaintStatus, Pageable pageable);

Page<Complaint> findAllByStatus(ComplaintStatus complaintStatus, Pageable pageable);

@Modifying
@Query("UPDATE Complaint c SET c.status = :status WHERE c.id = :id")
void updateStatusById(@Param("id") Long id, @Param("status") ComplaintStatus status);
}
37 changes: 22 additions & 15 deletions src/main/java/org/petmarket/users/service/ComplaintService.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package org.petmarket.users.service;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.petmarket.users.dto.ComplaintRequestDto;
import org.petmarket.users.dto.ComplaintResponseDto;
import org.petmarket.users.entity.Complaint;
import org.petmarket.users.entity.ComplaintStatus;
import org.petmarket.users.mapper.ComplaintMapper;
import org.petmarket.users.repository.ComplaintRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
Expand All @@ -20,39 +23,43 @@ public class ComplaintService {
private final ComplaintMapper complaintMapper;
private final UserService userService;

@Transactional
public void addComplaint(ComplaintRequestDto complaintRequestDto) {
if (complaintRequestDto.getComplainedUserId().equals(UserService.getCurrentUserId())) {
log.error("User cannot complain about himself");
throw new IllegalArgumentException("User cannot complain about himself");
}

log.info("Adding complaint: {}", complaintRequestDto);
Complaint complaint = complaintMapper.mapDtoToComplaint(complaintRequestDto);
complaint.setUser(userService.getCurrentUser());
complaint.setComplainedUser(userService.findById(complaintRequestDto.getComplainedUserId()));
complaint.setStatus(ComplaintStatus.PENDING);
complaintRepository.save(complaint);
}

public void deleteComplaint(Long id) {
log.info("Deleting complaint with id: {}", id);
complaintRepository.deleteById(id);
}

public Complaint getComplaint(Long id) {
log.info("Getting complaint with id: {}", id);
return complaintRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Complaint not found"));
public ComplaintResponseDto getComplaint(Long id) {
return complaintMapper.mapComplaintToDto(complaintRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Complaint not found")));
}

public Page<Complaint> getComplaints(ComplaintStatus complaintStatus, int size,
int page, Sort.Direction direction) {
log.info("Getting all complaints");
return complaintRepository.findAllByStatus(complaintStatus,
PageRequest.of(page - 1, size, Sort.by(direction, "created")));
public List<ComplaintResponseDto> getComplaints(ComplaintStatus complaintStatus, int size,
int page, Sort.Direction direction) {
return complaintMapper.mapComplaintToDto(complaintRepository.findAllByStatus(complaintStatus,
PageRequest.of(page - 1, size, Sort.by(direction, "created"))).toList());
}

public Page<Complaint> getComplaintsByUserId(Long userId, ComplaintStatus status,
public List<ComplaintResponseDto> getComplaintsByUserId(Long userId, ComplaintStatus status,
int size, int page, Sort.Direction direction) {
log.info("Getting all complaints by user id: {}", userId);
return complaintRepository.findAllByComplainedUserIdAndStatus(userId, status, PageRequest
.of(page - 1, size, Sort.by(direction, "created")));
return complaintMapper.mapComplaintToDto(complaintRepository.findAllByComplainedUserIdAndStatus(userId,
status, PageRequest.of(page - 1, size, Sort.by(direction, "created"))).toList());
}

@Transactional
public void updateStatusById(Long id, ComplaintStatus status) {
complaintRepository.updateStatusById(id, status);
}
}
Loading

0 comments on commit 7df49ff

Please sign in to comment.