Done task GEPAFINBE-6311 Implemented upload application company document flow

This commit is contained in:
rajesh
2026-03-26 16:30:31 +05:30
parent 22eb51a041
commit c43de36cc0
17 changed files with 197 additions and 23 deletions

View File

@@ -115,6 +115,9 @@ public class ApplicationEvaluationDao {
@Autowired
private ApplicationAmendmentRequestDao applicationAmendmentRequestDao;
@Autowired
private CompanyDocumentDao companyDocumentDao;
@Autowired
private HubService hubService;
@@ -215,6 +218,9 @@ public class ApplicationEvaluationDao {
setEvaluationDocResponse(response, allDocs);
setApplicationDetails(response, entity);
setRejectedDocuments(applicationEntity, response);
response.setApplicationCompanyDocuments(
companyDocumentDao.listApplicationCompanyDocumentsForEvaluation(
entity.getApplicationId(), applicationEntity.getCompanyId()));
return response;
}
@@ -2407,6 +2413,7 @@ public class ApplicationEvaluationDao {
response.setAmountAccepted(applicationEvaluationResponse.getAmountAccepted());
response.setDateAccepted(applicationEvaluationResponse.getDateAccepted());
response.setDateRejected(applicationEvaluationResponse.getDateRejected());
response.setApplicationCompanyDocuments(applicationEvaluationResponse.getApplicationCompanyDocuments());
return response;
}

View File

@@ -3,6 +3,8 @@ package net.gepafin.tendermanagement.dao;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Predicate;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
@@ -18,6 +20,7 @@ import net.gepafin.tendermanagement.model.response.DocumentResponseBean;
import net.gepafin.tendermanagement.model.response.UploadFileOnAmazonS3Response;
import net.gepafin.tendermanagement.repositories.CompanyDocumentRepository;
import net.gepafin.tendermanagement.repositories.DocumentRepository;
import net.gepafin.tendermanagement.repositories.UserWithCompanyRepository;
import net.gepafin.tendermanagement.service.AmazonS3Service;
import net.gepafin.tendermanagement.service.ApplicationService;
import net.gepafin.tendermanagement.service.CompanyService;
@@ -38,6 +41,7 @@ import java.net.URL;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static net.gepafin.tendermanagement.util.Utils.setIfUpdated;
@@ -91,6 +95,58 @@ public class CompanyDocumentDao {
@Autowired
private AmazonS3 amazonS3;
@Autowired
private UserWithCompanyRepository userWithCompanyRepository;
/**
* Instructor uploads a company document tied to an application. Files are stored under the same S3 layout as
* {@link CompanyDocumentTypeEnum#COMPANY_DOCUMENT}; persisted row type remains {@link CompanyDocumentTypeEnum#APPLICATION_DOCUMENT}.
*/
public List<CompanyDocumentResponseBean> uploadInstructorCompanyDocumentToApplication(Long userId, List<MultipartFile> files, Long companyId, Long applicationId, Long documentCategoryId, LocalDateTime expirationDate, String name) {
log.info("Instructor upload company document to application. userId={}, companyId={}, applicationId={}", userId, companyId, applicationId);
applicationService.validateApplicationWithCompany(applicationId, companyId);
DocumentCategoryEntity categoryEntity = categoryDao.validateCategory(documentCategoryId);
Optional<UserWithCompanyEntity> userWithCompanyOpt = userWithCompanyRepository.findByUserIdAndCompanyIdAndIsDeletedFalse(userId, companyId);
LocalDateTime currentDate = LocalDateTime.now();
if (expirationDate.isBefore(currentDate)) {
log.warn("Expiration date {} is before current time {}", expirationDate, currentDate);
throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.INVALID_EXPIRATION_DATE));
}
CompanyDocumentTypeEnum storedType = CompanyDocumentTypeEnum.APPLICATION_DOCUMENT;
List<CompanyDocumentEntity> companyDocumentEntities = new ArrayList<>();
for (MultipartFile file : files) {
log.info("Uploading instructor company document '{}' for companyId={}, applicationId={}", file.getOriginalFilename(), companyId, applicationId);
UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = uploadFileOnAmazonS3(file, CompanyDocumentTypeEnum.COMPANY_DOCUMENT, companyId);
if (uploadFileOnAmazonS3Response != null) {
CompanyDocumentEntity companyDocumentEntity = new CompanyDocumentEntity();
companyDocumentEntity.setFileName(uploadFileOnAmazonS3Response.getFileName());
companyDocumentEntity.setCompanyId(companyId);
companyDocumentEntity.setApplicationId(applicationId);
companyDocumentEntity.setType(storedType.getValue());
companyDocumentEntity.setFilePath(uploadFileOnAmazonS3Response.getFilePath());
companyDocumentEntity.setIsDeleted(false);
companyDocumentEntity.setUploadedBy(userId);
companyDocumentEntity.setName(name);
if (expirationDate.isBefore(currentDate.plusDays(7))) {
companyDocumentEntity.setStatus(CompanyDocumentStatusEnum.DUE.getValue());
} else {
companyDocumentEntity.setStatus(CompanyDocumentStatusEnum.VALID.getValue());
}
companyDocumentEntity.setCategoryEntity(categoryEntity);
companyDocumentEntity.setUserWithCompany(userWithCompanyOpt.orElse(null));
companyDocumentEntity.setExpirationDate(expirationDate);
companyDocumentEntities.add(companyDocumentEntity);
}
}
companyDocumentRepository.saveAll(companyDocumentEntities);
companyDocumentEntities.forEach(entity -> loggingUtil.addVersionHistory(
VersionHistoryRequest.builder().request(request).actionType(VersionActionTypeEnum.INSERT).oldData(null).newData(entity).build()));
return companyDocumentEntities.stream()
.map(this::convertToCompanyDocumentResponseBean)
.collect(Collectors.toList());
}
public List<CompanyDocumentResponseBean> uploadFileForCompany(Long userId, List<MultipartFile> files, Long companyId, Long documentCategoryId, CompanyDocumentTypeEnum companyDocumentSourceTypeEnum, LocalDateTime expirationDate,String name){
log.info("Uploading files for company. userId={}, companyId={}, documentCategoryId={}", userId, companyId, documentCategoryId);
@@ -173,7 +229,9 @@ public class CompanyDocumentDao {
public CompanyDocumentResponseBean convertToCompanyDocumentResponseBean(CompanyDocumentEntity entity) {
CompanyDocumentResponseBean responseBean = new CompanyDocumentResponseBean();
DocumentCategoryEntity categoryEntity = entity.getCategoryEntity();
DocumentCategoryResponse responseCategory = categoryDao.convertToResponseBean(categoryEntity);
if (categoryEntity != null) {
responseBean.setCategory(categoryDao.convertToResponseBean(categoryEntity));
}
responseBean.setId(entity.getId());
responseBean.setFileName(entity.getFileName());
responseBean.setType(CompanyDocumentTypeEnum.valueOf(entity.getType()));
@@ -182,9 +240,9 @@ public class CompanyDocumentDao {
responseBean.setExpirationDate(entity.getExpirationDate());
responseBean.setStatus(entity.getStatus());
responseBean.setUploadedBy(entity.getUploadedBy());
responseBean.setCategory(responseCategory);
responseBean.setName(entity.getName());
responseBean.setUserWithCompanyId(entity.getUserWithCompany().getId());
responseBean.setUserWithCompanyId(entity.getUserWithCompany() != null ? entity.getUserWithCompany().getId() : null);
responseBean.setApplicationId(entity.getApplicationId());
responseBean.setCreatedDate(entity.getCreatedDate());
responseBean.setUpdatedDate(entity.getUpdatedDate());
@@ -271,6 +329,9 @@ public class CompanyDocumentDao {
else if(type.equals(CompanyDocumentTypeEnum.PERSONAL_DOCUMENT)){
userActionContext = UserActionContextEnum.UPLOAD_COMPANY_PERSONAL_DOCUMENT;
}
else if (type.equals(CompanyDocumentTypeEnum.APPLICATION_DOCUMENT)) {
userActionContext = UserActionContextEnum.UPLOAD_COMPANY_DOCUMENT_TO_APPLICATION;
}
return userActionContext;
}
@@ -314,10 +375,14 @@ public class CompanyDocumentDao {
public List<CompanyDocumentResponseBean> getAllCompanyDocument(UserEntity user , Long companyId, CompanyDocumentTypeEnum typeEnum){
log.info("Fetching all company documents for Company ID '{}', User ID '{}', Type '{}'", companyId, user.getId(), typeEnum);
if(Boolean.TRUE.equals(validator.checkIsBeneficiary())) {
validator.validateUserWithCompany(request, companyId);
CompanyEntity companyEntity = companyService.validateCompany(companyId);
if (Boolean.TRUE.equals(validator.checkIsBeneficiary())) {
if (typeEnum == CompanyDocumentTypeEnum.PERSONAL_DOCUMENT || typeEnum == null) {
validator.validateUserWithCompany(request, companyId);
} else {
validator.validateHubId(request, companyEntity.getHub().getId());
}
}
companyService.validateCompany(companyId);
Specification<CompanyDocumentEntity> spec = filterCompanyDocuments(companyId, user.getId(), typeEnum);
@@ -345,6 +410,9 @@ public class CompanyDocumentDao {
// Case 1: Fetch only COMPANY_DOCUMENT type documents for the given company
predicate = builder.and(predicate, builder.equal(root.get("type"), CompanyDocumentTypeEnum.COMPANY_DOCUMENT.getValue()));
} else if (typeEnum == CompanyDocumentTypeEnum.APPLICATION_DOCUMENT) {
predicate = builder.and(predicate, builder.equal(root.get("type"), CompanyDocumentTypeEnum.APPLICATION_DOCUMENT.getValue()));
} else if (typeEnum == CompanyDocumentTypeEnum.PERSONAL_DOCUMENT) {
// Case 2: Fetch only PERSONAL_DOCUMENT type documents for the logged-in user
predicate = builder.and(
@@ -353,20 +421,28 @@ public class CompanyDocumentDao {
builder.equal(root.get("userWithCompany").get("userId"), userId)
);
}
}else {
// Case 3: If typeEnum is null, fetch all documents for the company and personal documents for the user
Predicate companyPredicate = builder.equal(root.get("companyId"), companyId);
Predicate personalPredicate = builder.and(
builder.equal(root.get("type"), CompanyDocumentTypeEnum.PERSONAL_DOCUMENT.getValue()),
builder.equal(root.get("userWithCompany").get("userId"), userId)
} else {
Predicate companyAndApplicationDocs = root.get("type").in(
CompanyDocumentTypeEnum.COMPANY_DOCUMENT.getValue(),
CompanyDocumentTypeEnum.APPLICATION_DOCUMENT.getValue()
);
predicate = builder.and(predicate, builder.or(companyPredicate, personalPredicate));
predicate = builder.and(predicate, companyAndApplicationDocs);
}
return predicate;
};
}
public List<CompanyDocumentResponseBean> listApplicationCompanyDocumentsForEvaluation(Long applicationId, Long companyId) {
if (applicationId == null || companyId == null) {
return List.of();
}
List<CompanyDocumentEntity> entities = companyDocumentRepository.findByApplicationIdAndCompanyIdAndTypeAndStatusNot(
applicationId,
companyId,
CompanyDocumentTypeEnum.APPLICATION_DOCUMENT.getValue(),
CompanyDocumentStatusEnum.EXPIRED.getValue());
return entities.stream().map(this::convertToCompanyDocumentResponseBean).collect(Collectors.toList());
}
}

View File

@@ -36,6 +36,7 @@ import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -423,15 +424,40 @@ public class NotificationDao {
}
public void sendNotificationToBeneficiaryForDocumentExpiration(CompanyDocumentEntity companyDocumentEntity, NotificationTypeEnum notificationTypeEnum) {
CompanyEntity companyEntity = companyService.validateCompany(companyDocumentEntity.getCompanyId());
Long companyId = companyDocumentEntity.getCompanyId();
if (companyId == null) {
log.warn("Skipping document expiration notification: companyId is null for document id {}", companyDocumentEntity.getId());
return;
}
CompanyEntity companyEntity = companyService.validateCompany(companyId);
List<UserWithCompanyEntity> linkedUsers = userWithCompanyRepository.findByCompanyIdAndIsDeletedFalse(companyId);
if (linkedUsers == null || linkedUsers.isEmpty()) {
log.warn("Skipping document expiration notification: no users linked to company {} for document id {}", companyId, companyDocumentEntity.getId());
return;
}
Map<String, String> placeHolders = new HashMap<>();
placeHolders.put("{{file_name}}", companyDocumentEntity.getFileName());
placeHolders.put("{{company_name}}", companyEntity.getCompanyName());
placeHolders.put("{{expiration_date}}", companyDocumentEntity.getExpirationDate().toString());
NotificationReq notificationReq = createNotificationReq(notificationTypeEnum.getValue(), placeHolders, companyDocumentEntity.getUserWithCompany().getUserId(), companyDocumentEntity.getUserWithCompany(),
listOf(companyDocumentEntity.getCompanyId()));
sendNotification(notificationReq);
Map<Long, UserWithCompanyEntity> oneRowPerUser = new LinkedHashMap<>();
for (UserWithCompanyEntity uwc : linkedUsers) {
if (uwc.getUserId() != null) {
oneRowPerUser.putIfAbsent(uwc.getUserId(), uwc);
}
}
if (oneRowPerUser.isEmpty()) {
log.warn("Skipping document expiration notification: no user ids on USER_WITH_COMPANY for company {}, document id {}", companyId, companyDocumentEntity.getId());
return;
}
for (UserWithCompanyEntity uwc : oneRowPerUser.values()) {
NotificationReq notificationReq = createNotificationReq(
notificationTypeEnum.getValue(),
placeHolders,
uwc.getUserId(),
uwc,
listOf(companyId));
sendNotification(notificationReq);
}
}
public PageableResponseBean<List<NotificationResponse>> getNotificationsByUserIdAndCompanyIdByPagination(Long userId, Long companyId, NotificationRequestBean notificationRequestBean) {