Added user action log and versioning for communication.

This commit is contained in:
piyushkag
2024-11-26 12:47:03 +05:30
parent 4f68d09568
commit 7d04e4ab58
7 changed files with 99 additions and 14 deletions

View File

@@ -5,14 +5,19 @@ import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.ApplicationAmendmentRequestEntity;
import net.gepafin.tendermanagement.entities.CommunicationEntity;
import net.gepafin.tendermanagement.enums.VersionActionTypeEnum;
import net.gepafin.tendermanagement.model.request.CommunicationRequestBean;
import net.gepafin.tendermanagement.model.request.VersionHistoryRequest;
import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse;
import net.gepafin.tendermanagement.model.response.CommunicationResponseBean;
import net.gepafin.tendermanagement.repositories.CommunicationRepository;
import net.gepafin.tendermanagement.service.ApplicationAmendmentRequestService;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.util.Validator;
import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.checkerframework.checker.units.qual.A;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,24 +39,41 @@ public class CommunicationDao {
@Autowired
private Validator validator;
@Autowired
private LoggingUtil loggingUtil;
@Autowired
private HttpServletRequest request;
public CommunicationResponseBean addCommentToAmendmentRequest(HttpServletRequest request, CommunicationRequestBean communicationReq, Long amendmentId) {
log.info("Adding communication request...");
CommunicationEntity communicationEntity = convertToCommunicationCommentEntity(communicationReq, amendmentId);
communicationEntity = communicationRepository.save(communicationEntity);
/** This code is responsible for adding a version history log for the "adding comment to amendment request" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(communicationEntity).build());
log.info("Added comment: {}", communicationEntity);
return convertToCommunicationResponseBean(communicationEntity);
}
public String deleteComment(Long amendmentId, Long commentId) {
CommunicationEntity data = communicationRepository.findById(commentId)
CommunicationEntity data = communicationRepository.findByIdAndIsDeletedFalse(commentId)
.orElseThrow(() -> new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.COMMENT_NOT_FOUND)));
//cloned for old commentData
CommunicationEntity oldComment = Utils.getClonedEntityForData(data);
if (!data.getApplicationAmendmentRequest().getId().equals(amendmentId)) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.INVALID_AMENDMENT_FOR_COMMENT));
}
data.setIsDeleted(true);
communicationRepository.save(data);
data = communicationRepository.save(data);
/** This code is responsible for adding a version history log for the "soft deleting comment to amendment request" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.SOFT_DELETE).oldData(oldComment).newData(data).build());
return "Deleted Comment Successfully.";
}
@@ -70,6 +92,9 @@ public class CommunicationDao {
log.info("Updating communication comment...");
CommunicationEntity existingComment = communicationRepository.findById(commentId)
.orElseThrow(() -> new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.COMMENT_NOT_FOUND)));
//cloned for old data for communication
CommunicationEntity oldCommentData = Utils.getClonedEntityForData(existingComment);
if (!existingComment.getApplicationAmendmentRequest().getId().equals(amendmentId)) {
throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.COMMENT_NOT_ASSOCIATE_WITH_AMENDMENT_ID_ERROR_MSG));
}
@@ -78,6 +103,10 @@ public class CommunicationDao {
existingComment.setCommentedDate(LocalDateTime.now());
existingComment = communicationRepository.save(existingComment);
log.info("Updated Comment: {}", existingComment);
/** This code is responsible for adding a version history log for the "updating comment to amendment request" operation. **/
loggingUtil.addVersionHistory(VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.UPDATE).oldData(oldCommentData).newData(existingComment).build());
return convertToCommunicationResponseBean(existingComment);
}
@@ -92,6 +121,7 @@ public class CommunicationDao {
response.setTitle(entity.getCommunicationTitle());
response.setSenderUserId(entity.getSenderUserId());
response.setReceiverUserId(entity.getReceiverUserId());
response.setId(entity.getId());
return response;
}

View File

@@ -135,7 +135,13 @@ public enum UserActionContextEnum {
GET_EVALUATION_CRITERIA("GET_EVALUATION_CRITERIA"),
UPDATE_EVALUATION_CRITERIA("UPDATE_EVALUATION_CRITERIA"),
DELETE_EVALUATION_CRITERIA("DELETE_EVALUATION_CRITERIA"),
CREATE_EVALUATION_CRITERIA("CREATE_EVALUATION_CRITERIA");
CREATE_EVALUATION_CRITERIA("CREATE_EVALUATION_CRITERIA"),
/** communication action context **/
ADD_COMMENT_TO_AMENDMENT_REQUEST("ADD_COMMENT_TO_AMENDMENT_REQUEST"),
UPDATE_COMMUNICATION_COMMENT("UPDATE_COMMUNICATION_COMMENT"),
GET_AMENDMENT_COMMENT("GET_AMENDMENT_COMMENT"),
DELETE_COMMENT_FROM_AMENDMENT("DELETE_COMMENT_FROM_AMENDMENT");
private final String value;

View File

@@ -10,6 +10,8 @@ public class CommunicationResponseBean {
private String comment;
private Long id;
private String title;
private LocalDateTime createdDate;
@@ -21,7 +23,8 @@ public class CommunicationResponseBean {
private Long receiverUserId;
private Long amendmentId;
public CommunicationResponseBean(LocalDateTime commentedDate, String comment, String title, LocalDateTime createdDate, LocalDateTime updatedDate, Long amendmentId) {
public CommunicationResponseBean(LocalDateTime commentedDate, String comment, String title, LocalDateTime createdDate, LocalDateTime updatedDate, Long amendmentId, Long id) {
this.commentedDate = commentedDate;
this.comment = comment;
@@ -29,9 +32,10 @@ public class CommunicationResponseBean {
this.createdDate = createdDate;
this.updatedDate = updatedDate;
this.amendmentId = amendmentId;
this.id = id;
}
public CommunicationResponseBean(LocalDateTime commentedDate, String comment, String title, LocalDateTime createdDate, LocalDateTime updatedDate, Long amendmentId,Long senderUserId,Long receiverUserId) {
public CommunicationResponseBean(LocalDateTime commentedDate, String comment, String title, LocalDateTime createdDate, LocalDateTime updatedDate, Long amendmentId,Long senderUserId,Long receiverUserId, Long id) {
this.commentedDate = commentedDate;
this.comment = comment;
@@ -41,6 +45,7 @@ public class CommunicationResponseBean {
this.amendmentId = amendmentId;
this.senderUserId = senderUserId;
this.receiverUserId = receiverUserId;
this.id = id;
}
public CommunicationResponseBean() {

View File

@@ -7,16 +7,14 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
import java.util.Optional;
public interface CommunicationRepository extends JpaRepository<CommunicationEntity, Long> {
@Query("Select new net.gepafin.tendermanagement.model.response.CommunicationResponseBean(c.commentedDate, c.communicationComment, c.communicationTitle, c.createdDate, c.updatedDate, c.applicationAmendmentRequest.id) " +
"from CommunicationEntity c Where c.applicationAmendmentRequest.id = :applicationAmendmentRequestId")
List<CommunicationResponseBean> findCommentsByApplicationAmendmentRequestId(@Param("applicationAmendmentRequestId") Long amendmentRequestId);
@Query("SELECT new net.gepafin.tendermanagement.model.response.CommunicationResponseBean( " + "c.commentedDate, c.communicationComment, c.communicationTitle, c.createdDate, c" +
".updatedDate, c.applicationAmendmentRequest.id,c.senderUserId, c.receiverUserId) " + "FROM CommunicationEntity c " + "WHERE c.applicationAmendmentRequest.id = :amendmentId AND c.isDeleted = false")
".updatedDate, " + "c.applicationAmendmentRequest.id, c.senderUserId, c.receiverUserId, c.id " + ") " + "FROM CommunicationEntity c " + "WHERE c" +
".applicationAmendmentRequest.id = :amendmentId AND c.isDeleted = false")
List<CommunicationResponseBean> findCommentListDetailsByAmendmentId(@Param("amendmentId") Long amendmentId);
Optional<CommunicationEntity> findByIdAndIsDeletedFalse(Long commentId);
}

View File

@@ -63,7 +63,7 @@ public class CommunicationServiceImpl implements CommunicationService {
}
@Override
@Transactional(readOnly = true)
@Transactional(rollbackFor = Exception.class)
public ApplicationAmendmentResponse getAmendmentComments(HttpServletRequest request,Long id) {
ApplicationAmendmentRequestEntity applicationAmendmentRequestEntity = applicationAmendmentRequestDao.validateApplicationAmendmentRequest(id);
if (Boolean.FALSE.equals(validator.checkIsBeneficiary())) {

View File

@@ -19,6 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -55,12 +57,26 @@ public class LoggingUtil {
if (userActionRequest.getRequest() instanceof CachedBodyHttpServletRequest cachedRequest) {
requestBody = cachedRequest.getCachedBodyAsString();
}
// Decode the raw URI to handle encoded placeholders like %7BcommentId%7D
String rawUrl = userActionRequest.getRequest().getRequestURI();
String decodedUrl = URLDecoder.decode(rawUrl, StandardCharsets.UTF_8);
// Append query parameters if they exist
if (userActionRequest.getRequest().getQueryString() != null) {
decodedUrl += "?" + userActionRequest.getRequest().getQueryString();
}
// Use the decoded URL as-is (optional normalization step if needed)
String normalizedUrl = normalizeUrl(decodedUrl);
// Set the normalized URL in the user action log
userAction.setActionType(userActionRequest.getActionType().getValue());
userAction.setUserId(userId);
userAction.setActionContext(userActionRequest.getActionContext().getValue());
userAction.setMethodType(userActionRequest.getRequest().getMethod());
userAction.setHubId(userEntity.getHub().getId());
userAction.setUrl(userActionRequest.getRequest().getRequestURI());
// userAction.setUrl(userActionRequest.getRequest().getRequestURI());
userAction.setUrl(normalizedUrl);
userAction.setLoginAttemptId(loginAttemptId);
userAction.setIpAddress(IpAddressUtils.getClientIp(userActionRequest.getRequest()));
userAction.setRequestBody(requestBody);
@@ -74,6 +90,17 @@ public class LoggingUtil {
return userAction;
}
private String normalizeUrl(String url) {
url = url.replaceAll("(?<!:)//+", "/");
if (url.length() > 1 && url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
url = URLDecoder.decode(url, StandardCharsets.UTF_8);
return url;
}
// @Transactional
// public UserActionEntity updateUserAction(HttpServletResponse response, UserActionEntity userAction) {
// try {

View File

@@ -3,11 +3,15 @@ package net.gepafin.tendermanagement.web.rest.api.impl;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.enums.UserActionContextEnum;
import net.gepafin.tendermanagement.enums.UserActionLogsEnum;
import net.gepafin.tendermanagement.model.request.CommunicationRequestBean;
import net.gepafin.tendermanagement.model.request.UserActionRequest;
import net.gepafin.tendermanagement.model.response.ApplicationAmendmentResponse;
import net.gepafin.tendermanagement.model.response.CommunicationResponseBean;
import net.gepafin.tendermanagement.model.util.Response;
import net.gepafin.tendermanagement.service.CommunicationService;
import net.gepafin.tendermanagement.util.LoggingUtil;
import net.gepafin.tendermanagement.web.rest.api.CommunicationApi;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import org.springframework.beans.factory.annotation.Autowired;
@@ -23,10 +27,16 @@ public class CommunicationController implements CommunicationApi {
@Autowired
CommunicationService communicationService;
@Autowired
private LoggingUtil loggingUtil;
@Override
public ResponseEntity<Response<CommunicationResponseBean>> addCommentToAmendmentRequest(HttpServletRequest request, CommunicationRequestBean communicationRequestBean,
Long amendmentId) {
/** This code is responsible for creating user action logs for the "Adding comment to amendment request" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.INSERT).actionContext(UserActionContextEnum.ADD_COMMENT_TO_AMENDMENT_REQUEST).build());
CommunicationResponseBean communicationResponseBean = communicationService.addCommentToAmendmentRequest(request,communicationRequestBean, amendmentId);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new Response<>(communicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMMUNICATION_ADDED_TO_AMENDMENT_REQUEST_SUCCESS)));
@@ -34,6 +44,9 @@ public class CommunicationController implements CommunicationApi {
@Override
public ResponseEntity<Response<ApplicationAmendmentResponse>> getAmendmentComments(HttpServletRequest request,Long amendmentId) {
/** This code is responsible for creating user action logs for the "getting comment of amendment" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.VIEW).actionContext(UserActionContextEnum.GET_AMENDMENT_COMMENT).build());
ApplicationAmendmentResponse response = communicationService.getAmendmentComments(request,amendmentId);
return ResponseEntity.ok(new Response<>(response, Status.SUCCESS, Translator.toLocale(GepafinConstant.AMENDMENT_FOUND_SUCCESS)));
}
@@ -41,6 +54,9 @@ public class CommunicationController implements CommunicationApi {
public ResponseEntity<Response<CommunicationResponseBean>> updateCommunicationAmendment(HttpServletRequest request, CommunicationRequestBean communicationRequestBean,
Long amendmentId, Long commentId) {
/** This code is responsible for creating user action logs for the "update communication comment of amendment request" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.UPDATE).actionContext(UserActionContextEnum.UPDATE_COMMUNICATION_COMMENT).build());
CommunicationResponseBean communicationResponseBean = communicationService.updateAmendmentComment(request,communicationRequestBean, amendmentId, commentId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(communicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMMENT_UPDATED_SUCCESS_MSG)));
@@ -48,6 +64,9 @@ public class CommunicationController implements CommunicationApi {
@Override
public ResponseEntity<Response<String>> deleteApplicationAmendmentComment(HttpServletRequest request, Long applicationAmendId, Long commentId) {
/** This code is responsible for creating user action logs for the "Delete communication comment of amendment request" operation. **/
loggingUtil.logUserAction(UserActionRequest.builder().request(request).actionType(UserActionLogsEnum.DELETE).actionContext(UserActionContextEnum.DELETE_COMMENT_FROM_AMENDMENT).build());
String communicationResponseBean = communicationService.deleteComment(request,applicationAmendId, commentId);
return ResponseEntity.status(HttpStatus.OK)
.body(new Response<>(communicationResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.COMMENT_DELETED_SUCCESS_MSG)));