Skip to content

Commit

Permalink
Merge pull request #56 from Chat-Your-Way/CHAT-203--handling-complain…
Browse files Browse the repository at this point in the history
…ts-about-topics

Chat 203  handling complaints about topics
  • Loading branch information
DmytroTeliukov authored Jan 17, 2024
2 parents 23c03e1 + 2ca1aaf commit b33f68f
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public class OpenApiMessages {
"Topic added to favourite successfully";
public static final String SUCCESSFULLY_REMOVE_TOPIC_FROM_FAVOURITE =
"Topic removed from favourite successfully";

public static final String SUCCESSFULLY_COMPLAIN_TOPIC =
"Topic was complained successfully";
public static final String USER_DID_NOT_SUBSCRIBED_TO_TOPIC =
"User did not subscribe to topic";

Expand Down
42 changes: 23 additions & 19 deletions src/main/java/com/chat/yourway/controller/TopicController.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
package com.chat.yourway.controller;

import static com.chat.yourway.config.openapi.OpenApiMessages.ALREADY_SUBSCRIBED;
import static com.chat.yourway.config.openapi.OpenApiMessages.CONTACT_UNAUTHORIZED;
import static com.chat.yourway.config.openapi.OpenApiMessages.CONTACT_WASNT_SUBSCRIBED;
import static com.chat.yourway.config.openapi.OpenApiMessages.INVALID_VALUE;
import static com.chat.yourway.config.openapi.OpenApiMessages.OWNER_CANT_UNSUBSCRIBED;
import static com.chat.yourway.config.openapi.OpenApiMessages.RECIPIENT_EMAIL_NOT_EXIST;
import static com.chat.yourway.config.openapi.OpenApiMessages.SEARCH_TOPIC_VALIDATION;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_ADD_TOPIC_TO_FAVOURITE;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_CREATED_TOPIC;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_DELETE_TOPIC;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_FOUND_TOPIC;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_REMOVE_TOPIC_FROM_FAVOURITE;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_SUBSCRIBED;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_UNSUBSCRIBED;
import static com.chat.yourway.config.openapi.OpenApiMessages.SUCCESSFULLY_UPDATED_TOPIC;
import static com.chat.yourway.config.openapi.OpenApiMessages.TOPIC_NOT_ACCESS;
import static com.chat.yourway.config.openapi.OpenApiMessages.TOPIC_NOT_FOUND;
import static com.chat.yourway.config.openapi.OpenApiMessages.USER_DID_NOT_SUBSCRIBED_TO_TOPIC;
import static com.chat.yourway.config.openapi.OpenApiMessages.VALUE_NOT_UNIQUE;
import static com.chat.yourway.config.openapi.OpenApiMessages.*;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

Expand Down Expand Up @@ -355,5 +337,27 @@ public List<TopicResponseDto> findAllPopularPublicTopics() {
return topicService.findPopularPublicTopics();
}

@Operation(
summary = "Complain topic",
responses = {
@ApiResponse(responseCode = "204", description = SUCCESSFULLY_COMPLAIN_TOPIC),
@ApiResponse(
responseCode = "403",
description = CONTACT_UNAUTHORIZED,
content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class))),
@ApiResponse(
responseCode = "404",
description = TOPIC_NOT_FOUND,
content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class))),
@ApiResponse(
responseCode = "409",
description = USER_DID_NOT_SUBSCRIBED_TO_TOPIC,
content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class)))
})
@PatchMapping("/{topic-id}/complain")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void complainTopic(@AuthenticationPrincipal UserDetails userDetails, @PathVariable("topic-id") Integer topicId) {
topicSubscriberService.complainTopic(topicId, userDetails);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public class TopicSubscriberResponseDto {

private boolean isPermittedSendingMessage;

private boolean hasComplaint;

}
3 changes: 3 additions & 0 deletions src/main/java/com/chat/yourway/model/TopicSubscriber.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,7 @@ public class TopicSubscriber {
@Column(name = "is_favourite_topic")
private boolean isFavouriteTopic;

@Column(name = "has_complaint")
private boolean hasComplaint;

}
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,19 @@ void updateFavouriteTopicStatusByTopicIdAndContactEmail(
"SELECT CASE WHEN COUNT(ts) > 0 then true else false end from TopicSubscriber ts " +
"where ts.topic.id = :topicId and ts.contact.isPermittedSendingPrivateMessage = false")
boolean checkIfExistProhibitionSendingPrivateMessage(@Param("topicId") Integer topicId);

@Modifying
@Query(
nativeQuery = true,
value =
"UPDATE chat.topic_subscriber "
+ "SET has_complaint = :hasComplaint "
+ "FROM chat.contact c "
+ "WHERE contact_id = c.id "
+ "AND topic_id = :topicId "
+ "AND c.email = :contactEmail")
void updateHasComplaintStatusByTopicIdAndContactEmail(
@Param("topicId") int topicId,
@Param("contactEmail") String contactEmail,
@Param("hasComplaint") boolean hasComplaint);
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@ public boolean hasProhibitionSendingPrivateMessages(Integer topicId) {
return topicSubscriberRepository.checkIfExistProhibitionSendingPrivateMessage(topicId);
}

@Override
@Transactional
public void complainTopic(Integer topicId, UserDetails userDetails) {
String email = userDetails.getUsername();
boolean hasComplaint = true;

if (!topicRepository.existsById(topicId)) {
throw new TopicNotFoundException(String.format("Topic with id [%d] is not found.", topicId));
} else if (!topicSubscriberRepository.existsByContactEmailAndTopicIdAndUnsubscribeAtIsNull(email, topicId)) {
throw new NotSubscribedTopicException("You cannot complain topic because you did not subscribe before.");
}

topicSubscriberRepository.updateHasComplaintStatusByTopicIdAndContactEmail(topicId, email, hasComplaint);
}

private boolean isTopicCreator(Integer topicId, String topicCreator) {
return topicSubscriberRepository.existsByTopicIdAndTopicCreatedBy(topicId, topicCreator);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,20 @@ public interface TopicSubscriberService {
* @return true if sending private messages is prohibited, false otherwise
*/
boolean hasProhibitionSendingPrivateMessages(Integer topicId);

/**
* Registers a complaint for a specific topic.
*
* This method allows a user to complain about a particular topic identified by its unique identifier.
* The complaint details, such as the user's information, will be recorded for further investigation.
*
* @param topicId The unique identifier of the topic being complained about.
* @param userDetails The details of the user lodging the complaint.
* This should include relevant information like user ID, username, etc.
* Ensure that the userDetails parameter is not null.
*
* @throws TopicNotFoundException If topic does not exist.
* @throws NotSubscribedTopicException If contact does not subscribed to topic.
*/
void complainTopic(Integer topicId, UserDetails userDetails);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ALTER TABLE chat.topic_subscriber
ADD has_complaint boolean DEFAULT false;

UPDATE chat.topic_subscriber
SET has_complaint = false
where contact_id > 0;
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,75 @@ public void shouldThrowTopicNotFoundException_whenUserMarkTopicAsFavouriteAndTop
() -> topicSubscriberService.removeTopicFromFavourite(topicId, contact));
}

@Test
@DatabaseSetup(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.INSERT)
@DatabaseTearDown(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.DELETE)
@DisplayName(
"should successfully complain topic when user complain topic")
public void shouldSuccessfullyComplainTopic_whenUserComplainTopic() {
// Given
var contactEmail = "[email protected]";
var contact = contactService.findByEmail(contactEmail);
var topicId = 111123;

// When
topicSubscriberService.complainTopic(topicId, contact);

// Then
var result = topicService.findById(topicId).getTopicSubscribers().stream()
.filter(topicSubscriber -> topicSubscriber.getContact().getEmail().equals(contactEmail))
.anyMatch(TopicSubscriberResponseDto::isHasComplaint);

assertThat(result)
.withFailMessage("Expecting containing complaint to topic by user")
.isTrue();
}

@Test
@DatabaseSetup(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.INSERT)
@DatabaseTearDown(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.DELETE)
@DisplayName(
"should throw TopicNotFoundException when user complain topic")
public void shouldThrowTopicNotFoundException_whenUserComplainTopic() {
// Given
var contactEmail = "[email protected]";
var contact = contactService.findByEmail(contactEmail);
var topicId = 1;

// When
// Then
assertThrows(
TopicNotFoundException.class,
() -> topicSubscriberService.complainTopic(topicId, contact));
}

@Test
@DatabaseSetup(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.INSERT)
@DatabaseTearDown(
value = "/dataset/complain-topic-dataset.xml",
type = DatabaseOperation.DELETE)
@DisplayName(
"should throw NotSubscribedTopicException when user complain topic")
public void shouldThrowNotSubscribedTopicException_whenUserComplainTopic() {
// Given
var contactEmail = "[email protected]";
var contact = contactService.findByEmail(contactEmail);
var topicId = 111124;

// When
// Then
assertThrows(
NotSubscribedTopicException.class,
() -> topicSubscriberService.complainTopic(topicId, contact));
}
}
38 changes: 38 additions & 0 deletions src/test/resources/dataset/complain-topic-dataset.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<contact
id="312199"
nickname="Vasil"
password="$2a$10$b9SjqPefZMJRK8WPQEbmP.BBcsqSXey2dCRa0dsRnydFY.GiPjWty"
is_active="true"
is_private="true"
email="[email protected]"
role="USER"
avatar_id="1"
is_permitted_sending_private_message="true"
/>

<topic
id="111123"
topic_name="Programming topic1"
created_by="[email protected]"
created_at="2023-09-19 23:43:51.236336"
is_public="true"
/>
<topic
id="111124"
topic_name="Another topic1"
created_by="[email protected]"
created_at="2023-10-01 16:31:35.344509"
is_public="true"
/>

<topic_subscriber
id="90911"
contact_id="312199"
topic_id="111123"
subscribe_at="2023-09-21 22:53:12.818683"
is_favourite_topic="true"
/>

</dataset>

0 comments on commit b33f68f

Please sign in to comment.