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

Bug/6593/fix send email for user in patch update status #426

Merged
Merged
26 changes: 26 additions & 0 deletions core/src/main/java/greencity/controller/EmailController.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,30 @@ public ResponseEntity<Void> sendScheduledNotification(@RequestBody ScheduledEmai
emailService.sendScheduledNotificationEmail(message);
return ResponseEntity.ok().build();
}

/**
* Method for sending an email notification about the status change of a place
* to the user.
*
* @param dto Object containing the necessary information for sending the status
* change notification email. The object includes: - userName: The
* name of the user. - userEmail: The email of the user who will
* receive the notification. - placeName: The name of the place whose
* status has been changed. - newStatus: The new status of the place.
*
* @return ResponseEntity with HTTP status 200 OK if the email was successfully
* sent. If any error occurs, an appropriate error response will be
* returned.
*/
@Operation(summary = "Send email notification to user if place status changed")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = HttpStatuses.OK),
@ApiResponse(responseCode = "400", description = HttpStatuses.BAD_REQUEST),
@ApiResponse(responseCode = "404", description = HttpStatuses.NOT_FOUND)
})
@PostMapping("/sendPlaceStatusChange")
public ResponseEntity<Object> sendPlaceStatusChange(@RequestBody PlaceStatusChangeDto dto) {
emailService.sendPlaceStatusChangeNotification(dto);
return ResponseEntity.ok().build();
}
}
3 changes: 2 additions & 1 deletion core/src/main/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ advice.for.block=You received this email for security reasons. To protect your a
profile.text=If you no longer wish to receive these emails, you can unsubscribe from them in your
profile=profile
advice.general.ubs=You are receiving this email because you are a registered member of Pick Up City.
read.more=READ MORE
read.more=READ MORE
your.place.status.changed=The status of your place has been updated. You are receiving this email because the status of your place was changed. Thank you for using our service!
3 changes: 2 additions & 1 deletion core/src/main/resources/messages_uk.properties
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ advice.for.block=\u0412\u0438\u0020\u043E\u0442\u0440\u0438\u043C\u0430\u043B\u0
profile.text=\u042f\u043a\u0449\u043e\u0020\u0432\u0438\u0020\u0431\u0456\u043b\u044c\u0448\u0435\u0020\u043d\u0435\u0020\u0445\u043e\u0447\u0435\u0442\u0435\u0020\u043e\u0442\u0440\u0438\u043c\u0443\u0432\u0430\u0442\u0438\u0020\u0440\u043e\u0437\u0441\u0438\u043b\u043a\u0443\u002c\u0020\u0432\u0438\u0020\u043c\u043e\u0436\u0435\u0442\u0435\u0020\u0432\u0456\u0434\u043f\u0438\u0441\u0430\u0442\u0438\u0441\u044f\u0020\u0432\u0456\u0434\u0020\u043d\u0435\u0457\u0020\u0443\u0020\u0441\u0432\u043e\u0454\u043c\u0443
profile=\u043f\u0440\u043e\u0444\u0456\u043b\u0456
advice.general.ubs=\u0412\u0438\u0020\u043e\u0442\u0440\u0438\u043c\u0430\u043b\u0438\u0020\u0446\u0435\u0439\u0020\u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0438\u0439\u0020\u043b\u0438\u0441\u0442\u002c\u0020\u0442\u043e\u043c\u0443\u0020\u0449\u043e\u0020\u0454\u0020\u0437\u0430\u0440\u0435\u0454\u0441\u0442\u0440\u043e\u0432\u0430\u043d\u0438\u043c\u0020\u043a\u043b\u0456\u0454\u043d\u0442\u043e\u043c\u0020\u0050\u0069\u0063\u006b\u0020\u0055\u0070\u0020\u0043\u0069\u0074\u0079\u002e
read.more=\u0427\u0418\u0422\u0410\u0422\u0418 \u0414\u0410\u041b\u0406
read.more=\u0427\u0418\u0422\u0410\u0422\u0418 \u0414\u0410\u041b\u0406
your.place.status.changed=\u0421\u0442\u0430\u0442\u0443\u0441\u0020\u0432\u0430\u0448\u043E\u0433\u043E\u0020\u043C\u0456\u0441\u0446\u044F\u0020\u0431\u0443\u0432\u0020\u043E\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439\u002E\u0020\u0412\u0438\u0020\u043E\u0442\u0440\u0438\u043C\u0430\u043B\u0438\u0020\u0446\u0435\u0439\u0020\u043B\u0438\u0441\u0442\u002C\u0020\u0442\u043E\u043C\u0443\u0020\u0449\u043E\u0020\u0441\u0442\u0430\u0442\u0443\u0441\u0020\u0432\u0430\u0448\u043E\u0433\u043E\u0020\u043C\u0456\u0441\u0446\u044F\u0020\u0431\u0443\u043B\u043E\u0020\u0437\u043C\u0456\u043D\u0435\u043D\u043E\u002E\u0020\u0414\u044F\u043A\u0443\u0454\u043C\u043E\u002C\u0020\u0449\u043E\u0020\u043A\u043E\u0440\u0438\u0441\u0442\u0443\u0454\u0442\u0435\u0441\u044C\u0020\u043D\u0430\u0448\u0438\u043C\u0020\u0441\u0435\u0440\u0432\u0456\u0441\u043E\u043C\u0021
105 changes: 105 additions & 0 deletions core/src/main/resources/templates/email/place-status-change.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html th:lang="${language}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<style>
body {
margin: 0;
padding: 0;
background-color: #F5F6F6;
}

.email-container {
font-family: Lato, sans-serif;
font-size: 16px;
width: 100%;
max-width: 600px;
margin: 0 auto;
background-color: #E3E6E8;
}

.header {
text-align: center;
padding: 30px;
background-color: #13AA57;
}

.header-image {
height: 30px;
vertical-align: bottom;
}

.content {
padding: 26px;
text-align: left;
color: #333333 !important;
}

.top-text {
margin-top: 0;
color: #333333 !important;
}

.main-text {
line-height: 1.4;
color: #333333 !important;
}

.bottom-text {
margin-bottom: 0;
color: #333333 !important;
}

.footer {
text-align: center;
padding: 10px;
font-size: 12px;
color: #666666;
background-color: #CACFD3;
}

@media only screen and (max-width: 600px) {
body {
font-size: 13px;
}

.header {
padding: 20px;
}

.header-image {
height: 25px;
}

.footer {
font-size: 10px;
}
}
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<a th:href="${clientLink}" target="_blank">
<img class="header-image" src="https://csb10032000a548f571.blob.core.windows.net/allfiles/5eaa9e18-f91f-4d3a-9926-da1239317a98GreenCity-Logo-White.png" alt="GreenCityLogo">
</a>
</div>

<div class="content">
<p class="top-text">
<b th:text="#{hi.user(${name})}"></b>
</p>

<p class="main-text">
The status of the place "<b th:text="${placeName}"></b>" has been updated to: <b th:text="${placeStatus}"></b>.
</p>
</div>

<div class="footer">
<p class="bottom-text" th:text="#{your.place.status.changed}"></p>
</div>
</div>
</body>
</html>
24 changes: 24 additions & 0 deletions core/src/test/java/greencity/controller/EmailControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import greencity.dto.econews.InterestingEcoNewsDto;
import greencity.dto.violation.UserViolationMailDto;
import greencity.enums.PlaceStatus;
import greencity.message.PlaceStatusChangeDto;
import greencity.message.ScheduledEmailMessage;
import greencity.message.SendHabitNotification;
import greencity.message.SendReportEmailMessage;
Expand Down Expand Up @@ -176,4 +178,26 @@ void sendUserReceivedScheduledNotification() {
.content(content))
.andExpect(status().isOk());
}

@Test
@SneakyThrows
void sendPlaceStatusChangeTest() {
PlaceStatusChangeDto dto = new PlaceStatusChangeDto();
dto.setUserName("John Doe");
dto.setEmail("test@example.com");
dto.setPlaceName("Green Park");
dto.setNewStatus(PlaceStatus.APPROVED);

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
String content = objectMapper.writeValueAsString(dto);

mockMvc.perform(MockMvcRequestBuilders.post(LINK + "/sendPlaceStatusChange")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", "Bearer your_token_here")
.content(content))
.andExpect(status().isOk());

verify(emailService).sendPlaceStatusChangeNotification(dto);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class EmailConstants {
public static final String BODY = "body";
public static final String UNLOCK_USER_LINK = "unlockUserLink";
public static final String NOTIFICATIONS_LINK = "notificationsLink";
public static final String PLACE_NAME = "placeName";
public static final String PLACE_STATUS = "placeStatus";
// templates
public static final String VERIFY_EMAIL_PAGE = "verify-email-page";
public static final String RESTORE_EMAIL_PAGE = "restore-email-page";
Expand All @@ -53,4 +55,5 @@ public class EmailConstants {
public static final String SCHEDULED_NOTIFICATION_PAGE = "scheduled-notification-email-page";
public static final String RECEIVE_INTERESTING_NEWS_EMAIL_PAGE = "receive-interesting-news-email-page";
public static final String BLOCKED_USER_PAGE = "blocked-user-page";
public static final String PLACE_STATUS_CHANGE_PAGE = "place-status-change";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package greencity.message;

import greencity.enums.PlaceStatus;
import jakarta.validation.constraints.NotNull;
import lombok.*;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PlaceStatusChangeDto {
@NotNull
private String placeName;

@NotNull
private PlaceStatus newStatus;

@NotNull
private String userName;

@NotNull
private String email;
}
12 changes: 11 additions & 1 deletion service-api/src/main/java/greencity/service/EmailService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import greencity.dto.user.UserActivationDto;
import greencity.dto.user.UserDeactivationReasonDto;
import greencity.dto.violation.UserViolationMailDto;
import greencity.message.PlaceStatusChangeDto;
import greencity.message.ScheduledEmailMessage;
import greencity.message.SendReportEmailMessage;

Expand Down Expand Up @@ -85,7 +86,7 @@ void sendRestoreEmail(Long userId, String userFistName, String userEmail, String

/**
* Method for send violation to user.
*
*
* @param dto {@link UserViolationMailDto}-includes all information about
* Violation.
*/
Expand Down Expand Up @@ -138,4 +139,13 @@ void sendCreateNewPasswordForEmployee(Long employeeId, String employeeFistName,
void sendBlockAccountNotificationWithUnblockLinkEmail(
Long userId, String userFistName, String userEmail, String token, String language,
boolean isUbs);

/**
* Sends an email notification to a user regarding the status change of a place.
*
* @param dto the data transfer object containing information about the user,
* place, and the new status of the place (e.g., PROPOSED, DECLINED,
* APPROVED, DELETED).
*/
void sendPlaceStatusChangeNotification(PlaceStatusChangeDto dto);
}
28 changes: 27 additions & 1 deletion service/src/main/java/greencity/service/EmailServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package greencity.service;

import greencity.constant.EmailConstants;
import greencity.constant.ErrorMessage;
import greencity.constant.LogMessage;
import greencity.dto.econews.InterestingEcoNewsDto;
import greencity.dto.user.SubscriberDto;
import greencity.dto.user.UserActivationDto;
import greencity.dto.user.UserDeactivationReasonDto;
import greencity.dto.violation.UserViolationMailDto;
import greencity.entity.User;
import greencity.message.PlaceStatusChangeDto;
import greencity.message.ScheduledEmailMessage;
import greencity.message.SendReportEmailMessage;
import greencity.repository.LanguageRepo;
import greencity.repository.UserRepo;
import greencity.validator.EmailAddressValidator;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
Expand Down Expand Up @@ -42,6 +47,7 @@ public class EmailServiceImpl implements EmailService {
private final String senderEmailAddress;
private final MessageSource messageSource;
private static final String PARAM_USER_ID = "&user_id=";
private final UserRepo userRepo;

/**
* Constructor.
Expand All @@ -51,13 +57,15 @@ public EmailServiceImpl(JavaMailSender javaMailSender,
ITemplateEngine templateEngine,
@Qualifier("sendEmailExecutor") Executor executor,
@Value("${client.address}") String clientLink,
@Value("${sender.email.address}") String senderEmailAddress, MessageSource messageSource) {
@Value("${sender.email.address}") String senderEmailAddress, MessageSource messageSource, UserRepo userRepo,
LanguageRepo languageRepo) {
this.javaMailSender = javaMailSender;
this.templateEngine = templateEngine;
this.executor = executor;
this.clientLink = clientLink;
this.senderEmailAddress = senderEmailAddress;
this.messageSource = messageSource;
this.userRepo = userRepo;
}

/**
Expand Down Expand Up @@ -317,6 +325,24 @@ private Map<String, Object> buildModelMapForPasswordRestore(Long userId, String
return model;
}

@Override
public void sendPlaceStatusChangeNotification(PlaceStatusChangeDto dto) {
ChernenkoVitaliy marked this conversation as resolved.
Show resolved Hide resolved
Map<String, Object> model = new HashMap<>();
String userEmail = dto.getEmail();
User user = userRepo.findByEmail(userEmail)
.orElseThrow(() -> new RuntimeException(ErrorMessage.USER_NOT_FOUND_BY_EMAIL + userEmail));
String userLanguageCode = user.getLanguage().getCode();
model.put(EmailConstants.CLIENT_LINK, clientLink);
model.put(EmailConstants.USER_NAME, dto.getUserName());
model.put(EmailConstants.PLACE_NAME, dto.getPlaceName());
model.put(EmailConstants.PLACE_STATUS, dto.getNewStatus().name());
model.put(EmailConstants.LANGUAGE, userLanguageCode);

String template = createEmailTemplate(model, EmailConstants.PLACE_STATUS_CHANGE_PAGE);
sendEmail(userEmail, messageSource.getMessage(EmailConstants.PLACE_STATUS, null,
getLocale(userLanguageCode)), template);
}

private String getClientLinkByIsUbs(boolean isUbs) {
return clientLink + "/#" + (isUbs ? "/ubs" : "/greenCity");
}
Expand Down
1 change: 1 addition & 0 deletions service/src/test/java/greencity/ModelUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -711,4 +711,5 @@ public static TestersSignInRequest getTestersSignInRequestWithInvalidSecretKey()
.secretKey("invalid-secret-key")
.build();
}

}
2 changes: 2 additions & 0 deletions service/src/test/java/greencity/TestConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ public final class TestConst {
public static final Long SIMPLE_LONG_NUMBER = 1L;
public static final Long SIMPLE_LONG_TWO_NUMBER = 2L;
public static final Long SIMPLE_LONG_NUMBER_BAD_VALUE = 100L;
public static final String ENGLISH_CODE = "en";
public static final String PLACE_NAME = "Central Park";
}
Loading
Loading