From d20b9abc079a6d32c088244cb5e3b741ede998a7 Mon Sep 17 00:00:00 2001 From: piyuskag Date: Fri, 25 Oct 2024 15:29:28 +0530 Subject: [PATCH] Done Ticket GEPAFINBE-71 --- .../constants/GepafinConstant.java | 9 + .../tendermanagement/dao/ApplicationDao.java | 27 +- .../tendermanagement/dao/DelegationDao.java | 22 +- .../tendermanagement/dao/DocumentDao.java | 60 +- .../tendermanagement/dao/S3ConfigDao.java | 104 +++ .../tendermanagement/dao/S3PathConfig.java | 49 + .../entities/S3ConfigEntity.java | 25 + .../enums/DocOtherSourceTypeEnum.java | 17 + .../model/request/S3ConfigReq.java | 20 + .../model/response/S3ConfigBean.java | 11 + .../repositories/ApplicationRepository.java | 3 +- .../ApplicationSignedDocumentRepository.java | 11 + .../repositories/DocumentRepository.java | 2 + .../repositories/S3ConfigRepository.java | 24 + .../UserCompanyDelegationRepository.java | 6 + .../service/S3ConfigService.java | 19 + .../service/impl/DocumentServiceImpl.java | 2 +- .../service/impl/S3ConfigServiceImpl.java | 41 + .../impl/S3ReUploadMigrationService.java | 197 ++++ .../UserSignedAndDelegationServiceImpl.java | 261 ++++++ .../web/rest/api/S3ConfigApi.java | 67 ++ .../web/rest/api/S3MigrationApi.java | 28 + .../rest/api/UserSignedAndDelegationApi.java | 38 + .../rest/api/impl/DocumentApiController.java | 2 +- .../web/rest/api/impl/S3ConfigController.java | 59 ++ .../api/impl/S3MigrationApiController.java | 19 + ...ignedAndDelegationMigrationController.java | 24 + .../db/changelog/db.changelog-1.0.0.xml | 882 ++++++++++-------- 28 files changed, 1620 insertions(+), 409 deletions(-) create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/S3ConfigDao.java create mode 100644 src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java create mode 100644 src/main/java/net/gepafin/tendermanagement/entities/S3ConfigEntity.java create mode 100644 src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/request/S3ConfigReq.java create mode 100644 src/main/java/net/gepafin/tendermanagement/model/response/S3ConfigBean.java create mode 100644 src/main/java/net/gepafin/tendermanagement/repositories/S3ConfigRepository.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/S3ConfigService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/S3ConfigServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java create mode 100644 src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/S3ConfigApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3ConfigController.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java create mode 100644 src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 38e3969a..525849b7 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -249,5 +249,14 @@ public class GepafinConstant { public static final String HUB_NOT_FOUND = "hub_not_found"; public static final String EVALUATIONCRITERIA_INVALID = "evaluationCriteria.invalid"; public static final String GET_ERROR_S3 = "get.error.s3"; + + public static final String ADDED_S3_PATH_STRUCTURE ="added.s3.path.structure"; + public static final String S3_PATH_STRUCTURE_BY_TYPE ="fetched.s3.path.structure.by.type.successfully"; + public static final String S3_PATH_STRUCTURE_NOT_FOUND_BY_TYPE_MSG ="s3.path.not.found.by.type"; + public static final String S3_PATH_STRUCTURE_NOT_FOUND_BY_ID_MSG ="s3.path.not.found.by.id"; + public static final String S3_PATH_DELETE_MSG ="s3.path.config.delete.successfully"; + public static final String S3_PATH_CONFIG_UPDATE_MSG ="s3.path.config.updated.successfully"; + public static final String S3_PATH_CONFIG_DUPLICATE_TYPE_ALREADY_EXIST ="s3.path.config.already.exist."; + public static final String S3_PATH_GENERATION_ERROR_MSG ="s3.path.config.already.exist."; } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java index 8aff7b3b..a9162986 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/ApplicationDao.java @@ -6,6 +6,7 @@ import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.entities.SystemEmailTemplatesEntity.SystemEmailTemplatesEntityTypeEnum; import net.gepafin.tendermanagement.enums.ApplicationSignedDocumentStatusEnum; import net.gepafin.tendermanagement.enums.ApplicationStatusTypeEnum; +import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; import net.gepafin.tendermanagement.enums.RoleStatusEnum; import net.gepafin.tendermanagement.enums.UserCompanyDelegationStatusEnum; @@ -127,6 +128,9 @@ public class ApplicationDao { @Autowired private UserService userService; + @Autowired + S3PathConfig s3ConfigBean; + public ApplicationResponseBean createApplication(HttpServletRequest request, ApplicationRequestBean applicationRequestBean, Long formId, Long applicationId) { FormEntity formEntity = formService.validateForm(formId); @@ -805,9 +809,9 @@ public class ApplicationDao { applicationSignedDocument.setStatus(ApplicationSignedDocumentStatusEnum.INACTIVE.getValue()); applicationSignedDocumentRepository.save(applicationSignedDocument); } - UploadFileOnAmazonS3Response uploadFileOnAmazonS3 = amazonS3Service.uploadFileOnAmazonS3(signedDocumentS3Folder, - file); - applicationSignedDocument = new ApplicationSignedDocumentEntity(); + UploadFileOnAmazonS3Response uploadFileOnAmazonS3 = uploadFileOnAmazonS3ForUserSignedDocument(file, + applicationEntity.getCall().getId(), applicationId); + applicationSignedDocument = new ApplicationSignedDocumentEntity(); applicationSignedDocument.setApplication(applicationEntity); applicationSignedDocument.setFileName(uploadFileOnAmazonS3.getFileName()); applicationSignedDocument.setFilePath(uploadFileOnAmazonS3.getFilePath()); @@ -815,7 +819,22 @@ public class ApplicationDao { applicationSignedDocumentRepository.save(applicationSignedDocument); return convertApplicationSignedDocumentToApplicationSignedDocumentResponse(applicationSignedDocument); } - + private UploadFileOnAmazonS3Response uploadFileOnAmazonS3ForUserSignedDocument(MultipartFile file, Long callId, Long applicationId) { + try { + String s3Path = generateS3PathForDelegation(callId, applicationId); + log.info("S3 Path {}", s3Path); + return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); + } + } + private String generateS3PathForDelegation(Long callId, Long applicationId) { + try { + return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT, callId, applicationId); + } catch (IllegalArgumentException e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG)); + } + } private ApplicationSignedDocumentResponse convertApplicationSignedDocumentToApplicationSignedDocumentResponse( ApplicationSignedDocumentEntity applicationSignedDocument) { ApplicationSignedDocumentResponse applicationSignedDocumentResponse = new ApplicationSignedDocumentResponse(); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java index f609086f..b8ce98a0 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DelegationDao.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Function; +import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; import org.apache.commons.lang3.StringUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.springframework.beans.factory.annotation.Autowired; @@ -51,6 +52,9 @@ public class DelegationDao { @Autowired private DocumentRepository documentRepository; + + @Autowired + private S3PathConfig s3ConfigBean; @Value("${aws.s3.url.folder.delegation}") private String s3Folder; @@ -179,7 +183,7 @@ public class DelegationDao { userCompanyDelegationEntity.setStatus(UserCompanyDelegationStatusEnum.INACTIVE.getValue()); userCompanyDelegationRepository.save(userCompanyDelegationEntity); } - UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = amazonS3Service.uploadFileOnAmazonS3(s3Folder, file); + UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = uploadFileOnAmazonS3ForCompanyDelegation(file); userCompanyDelegationEntity = new UserCompanyDelegationEntity(); userCompanyDelegationEntity.setCompanyId(companyId); userCompanyDelegationEntity.setUserId(userEntity.getId()); @@ -192,7 +196,21 @@ public class DelegationDao { userCompanyDelegationRepository.save(userCompanyDelegationEntity); return convertUserCompanyDelegationToCompanyDelegationResponse(userCompanyDelegationEntity); } - + private UploadFileOnAmazonS3Response uploadFileOnAmazonS3ForCompanyDelegation(MultipartFile file) { + try { + String s3Path = generateS3PathForDelegation(); + return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); + } + } + private String generateS3PathForDelegation() { + try { + return s3ConfigBean.generateDocumentPathForDelegationAndSignedDocument(DocOtherSourceTypeEnum.USER_DELEGATION); + } catch (IllegalArgumentException e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG)); + } + } private CompanyDelegationResponse convertUserCompanyDelegationToCompanyDelegationResponse( UserCompanyDelegationEntity userCompanyDelegationEntity) { return Utils.convertSourceObjectToDestinationObject(userCompanyDelegationEntity, CompanyDelegationResponse.class); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java index 90725964..226848f7 100644 --- a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java +++ b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java @@ -2,7 +2,10 @@ package net.gepafin.tendermanagement.dao; import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -24,6 +27,7 @@ import net.gepafin.tendermanagement.web.rest.api.errors.Status; import java.util.ArrayList; import java.util.List; +@Slf4j @Component public class DocumentDao { @@ -38,6 +42,12 @@ public class DocumentDao { @Autowired private CallService callService; + + @Autowired + private S3PathConfig s3ConfigBean; + + @Autowired + private ApplicationRepository applicationFormRepository; @Value("${aws.s3.url.folder}") private String s3Folder; @@ -46,8 +56,7 @@ public class DocumentDao { List documentEntities = new ArrayList<>(); Long source = resolveSourceId(sourceId, sourceType); for (MultipartFile file : files) { - UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = amazonS3Service.uploadFileOnAmazonS3(s3Folder, - file); + UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = uploadFileOnAmazonS3(file, sourceType, sourceId); if (uploadFileOnAmazonS3Response != null) { DocumentEntity documentEntity = new DocumentEntity(); documentEntity.setFileName(uploadFileOnAmazonS3Response.getFileName()); @@ -62,6 +71,30 @@ public class DocumentDao { documentRepository.saveAll(documentEntities); return documentEntities.stream().map(callDao::convertToDocumentResponseBean).collect(Collectors.toList()); } + private UploadFileOnAmazonS3Response uploadFileOnAmazonS3(MultipartFile file, DocumentSourceTypeEnum type, Long sourceId) { + + Long applicationId = 0L; + Long callId = sourceId; + if (type == DocumentSourceTypeEnum.APPLICATION) { + applicationId = sourceId; + callId = applicationFormRepository.findCallIdById(applicationId); + } + try { + String s3Path = generateS3Path(type, callId, applicationId); + log.info("Generated S3 path {}", s3Path); + return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); + } + } + public String generateS3Path(DocumentSourceTypeEnum typeOfDocument, Long callId, Long applicationId) { + + try { + return s3ConfigBean.generateDocumentPath(typeOfDocument, callId, applicationId); + } catch (IllegalArgumentException e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.S3_PATH_GENERATION_ERROR_MSG)); + } + } private Long resolveSourceId(Long sourceId, DocumentSourceTypeEnum sourceType) { if (sourceType == DocumentSourceTypeEnum.CALL) { CallEntity callEntity = callService.validateCall(sourceId); @@ -91,8 +124,9 @@ public class DocumentDao { public DocumentResponseBean updateDocument(Long documentId, MultipartFile file, DocumentTypeEnum documentTypeEnum) { DocumentEntity documentEntity = validateDocument(documentId); - UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = amazonS3Service.uploadFileOnAmazonS3(s3Folder, file); - if (uploadFileOnAmazonS3Response != null) { + String type = documentEntity.getSource(); + UploadFileOnAmazonS3Response uploadFileOnAmazonS3Response = updateFileOnAmazonS3(file, DocumentSourceTypeEnum.valueOf(type), documentEntity.getSourceId()); + if (uploadFileOnAmazonS3Response != null) { documentEntity.setFileName(uploadFileOnAmazonS3Response.getFileName()); documentEntity.setFilePath(uploadFileOnAmazonS3Response.getFilePath()); documentEntity.setType(documentTypeEnum.getValue()); @@ -102,7 +136,25 @@ public class DocumentDao { } return callDao.convertToDocumentResponseBean(documentEntity); } + private UploadFileOnAmazonS3Response updateFileOnAmazonS3(MultipartFile file, DocumentSourceTypeEnum type, Long id) { + try { + Long callId; + Long applicationId; + if(type.equals("APPLICATION")){ + callId = applicationFormRepository.findCallIdById(id); + applicationId = id; + }else{ + callId = id; + applicationId = 0L; + } + String s3Path = generateS3Path(type, callId, applicationId); + log.info("Generated S3 path {}", s3Path); + return amazonS3Service.uploadFileOnAmazonS3(s3Path, file); + } catch (Exception e) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.UPLOAD_ERROR_S3)); + } + } public DocumentResponseBean getDocument(Long documentId) { DocumentEntity documentEntity = validateDocument(documentId); return callDao.convertToDocumentResponseBean(documentEntity); diff --git a/src/main/java/net/gepafin/tendermanagement/dao/S3ConfigDao.java b/src/main/java/net/gepafin/tendermanagement/dao/S3ConfigDao.java new file mode 100644 index 00000000..3661ad02 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/S3ConfigDao.java @@ -0,0 +1,104 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.model.request.S3ConfigReq; +import net.gepafin.tendermanagement.model.response.S3ConfigBean; +import net.gepafin.tendermanagement.repositories.S3ConfigRepository; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +import static net.gepafin.tendermanagement.util.Utils.setIfUpdated; + +@Component +public class S3ConfigDao { + private static final Logger log = LoggerFactory.getLogger(S3ConfigDao.class); + + @Autowired + S3ConfigRepository s3ConfigRepository; + + public S3ConfigBean addS3Path(S3ConfigReq s3PathConfigurationReq) { + + log.info("Adding s3 s3PathConfigurationReq structure with it's type.."); + S3ConfigEntity s3PathConfigurationEntity = convertToS3pathEntity(s3PathConfigurationReq); + s3PathConfigurationEntity = s3ConfigRepository.save(s3PathConfigurationEntity); + log.info("Added s3 path config details {} to DB.", s3PathConfigurationEntity); + return convertToS3pathBean(s3PathConfigurationEntity); + } + private S3ConfigEntity convertToS3pathEntity(S3ConfigReq s3PathConfigReq) { + + S3ConfigEntity s3PathConfigEntity = new S3ConfigEntity(); + s3PathConfigEntity.setPath(s3PathConfigReq.getPath()); + s3PathConfigEntity.setType(s3PathConfigReq.getType()); + s3PathConfigEntity.setBucketName(s3PathConfigReq.getBucketName()); + return s3PathConfigEntity; + } + private S3ConfigBean convertToS3pathBean(S3ConfigEntity s3PathConfigReq) { + + S3ConfigBean s3PathConfigBean = new S3ConfigBean(); + s3PathConfigBean.setPath(s3PathConfigReq.getPath()); + s3PathConfigBean.setType(s3PathConfigReq.getType()); + s3PathConfigBean.setBucketName(s3PathConfigReq.getBucketName()); + return s3PathConfigBean; + } + + public Optional getS3PathByType(String type) { + + log.info("Fetching S3-Path structure by type: {}", type); + Optional s3PathData = s3ConfigRepository.getPathByType(type); + if (s3PathData == null) { + log.error("No S3-Path found for type: {}", type); + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.S3_PATH_STRUCTURE_NOT_FOUND_BY_TYPE_MSG)); + } + log.info("Fetched S3-Path: {} for type: {}", s3PathData, type); + return s3PathData; + } + + public S3ConfigEntity deleteS3PathConfigById(Long id) { + + log.info("Checking s3-path associated with this id {} to delete....", id); + S3ConfigEntity s3PathConfigData = s3ConfigRepository.findS3PathConfigurationById(id); + if (s3PathConfigData == null) { + log.error("No S3-Path found for id: {}", id); + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.S3_PATH_STRUCTURE_NOT_FOUND_BY_ID_MSG)); + } else { + log.info("Found s3-path associated with this id {} to delete.", id); + s3ConfigRepository.deleteById(id); + log.error("Deleted s3-path configuration successfully for id: {}", id); + return s3PathConfigData; + } + } + public S3ConfigBean updateS3PathConfiguration(S3ConfigReq s3PathConfigurationReq, Long id) { + + log.info("Updating S3-path Configuration."); + S3ConfigEntity s3PathConfigDataExists = s3ConfigRepository.findS3PathConfigurationById(id); + if (s3PathConfigDataExists == null) { + log.error("No S3-Path found for id: {}", id); + throw new CustomValidationException(Status.NOT_FOUND, Translator.toLocale(GepafinConstant.S3_PATH_STRUCTURE_NOT_FOUND_BY_ID_MSG)); + } else { + Optional s3PathData = s3ConfigRepository.getPathByType(s3PathConfigurationReq.getType()); + if(s3PathData != null){ + log.error("S3-Path type already exist. {}", s3PathData); + throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.S3_PATH_CONFIG_DUPLICATE_TYPE_ALREADY_EXIST)); + } + S3ConfigEntity s3PathConfigurationEntity = convertToS3pathEntity(s3PathConfigurationReq); + setIfUpdated(s3PathConfigurationEntity::getPath, s3PathConfigurationEntity::setPath, s3PathConfigurationReq.getPath()); + setIfUpdated(s3PathConfigurationEntity::getBucketName, s3PathConfigurationEntity::setBucketName, s3PathConfigurationReq.getBucketName()); + setIfUpdated(s3PathConfigurationEntity::getType, s3PathConfigurationEntity::setType, s3PathConfigurationReq.getType()); +// s3PathConfigurationEntity.setType(s3PathConfigurationReq.getType()); +// s3PathConfigurationEntity.setPath(s3PathConfigurationReq.getPath()); +// s3PathConfigurationEntity.setBucketName(s3PathConfigurationReq.getBucketName()); + s3ConfigRepository.save(s3PathConfigurationEntity); + log.info("Updated S3-path-configuration successfully."); + return convertToS3pathBean(s3PathConfigurationEntity); + } + + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java b/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java new file mode 100644 index 00000000..b127b699 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/S3PathConfig.java @@ -0,0 +1,49 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; +import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; +import net.gepafin.tendermanagement.repositories.S3ConfigRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class S3PathConfig { + + @Autowired + S3ConfigRepository s3ConfigRepository; + + public String generateDocumentPath(DocumentSourceTypeEnum type, Long callId, Long applicationId) { + + S3ConfigEntity config = getDocumentPath(type); + return config.getParentFolder() + "/" + buildS3Path(config.getPath(), callId, applicationId); + } + public String generateDocumentPathForOther(DocOtherSourceTypeEnum type, Long callId, Long applicationId) { + + S3ConfigEntity config = getDocumentPathForOther(type); + return config.getParentFolder() + "/" + buildS3Path(config.getPath(), callId, applicationId); + } + private String buildS3Path(String pathTemplate, Long callId, Long applicationId) { + + return pathTemplate.replace("{call_id}", callId != null && callId != 0L ? "call_" + callId : "").replace("{application_id}", applicationId != null && applicationId != 0L ? "application_" + applicationId : ""); + } + public String generateDocumentPathForDelegationAndSignedDocument(DocOtherSourceTypeEnum type) { + + S3ConfigEntity config = getDocumentPathForOther(type); + return config.getParentFolder() + "/" + config.getPath(); + } + private S3ConfigEntity getDocumentPath(DocumentSourceTypeEnum type) { + + return s3ConfigRepository.getPathByType(type.name()).orElseThrow(() -> new IllegalArgumentException("No path configuration found for type: " + type)); + } + private S3ConfigEntity getDocumentPathForOther(DocOtherSourceTypeEnum type) { + + return s3ConfigRepository.getPathByType(type.name()).orElseThrow(() -> new IllegalArgumentException("No path configuration found for type: " + type)); + } + public String getBucketNameForOtherType(DocOtherSourceTypeEnum type){ + return s3ConfigRepository.getBucketNameByType(type); + } + public String getBucketNameForCallAppType(DocumentSourceTypeEnum type){ + return s3ConfigRepository.getBucketNameByType(type); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/S3ConfigEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/S3ConfigEntity.java new file mode 100644 index 00000000..66502bbc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/S3ConfigEntity.java @@ -0,0 +1,25 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; + +@Entity +@Table(name = "s3_path_configuration") +@Data +public class S3ConfigEntity extends BaseEntity { + + @Column(name = "TYPE") + private String type; + + @Column(name = "PATH") + private String path; + + @Column(name = "BUCKET_NAME") + private String bucketName; + + @Column(name = "PARENT_FOLDER") + private String parentFolder; +} + diff --git a/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java new file mode 100644 index 00000000..751dfa92 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/DocOtherSourceTypeEnum.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.enums; + +public enum DocOtherSourceTypeEnum { + USER_SIGNED_DOCUMENT("USER_SIGNED_DOCUMENT"), + USER_DELEGATION("USER_DELEGATION"), + TEMPLATE("TEMPLATE"); + + private String value; + + DocOtherSourceTypeEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/S3ConfigReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/S3ConfigReq.java new file mode 100644 index 00000000..859878de --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/S3ConfigReq.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class S3ConfigReq { + @NotNull + private String path; + + @NotNull + private String type; + + @NotNull + private String bucketName; + + @NotNull + private String parentFolder; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/S3ConfigBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/S3ConfigBean.java new file mode 100644 index 00000000..798f8b2c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/S3ConfigBean.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +@Data +public class S3ConfigBean { + private String path; + private String type; + private String bucketName; + private String parentFolder; +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index 7b57fcf2..d3ff6d01 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -40,5 +40,6 @@ public interface ApplicationRepository extends JpaRepository findByCompanyIdAndUserIdAndIsDeletedFalse(Long companyId,Long userId); - + @Query("SELECT a.call.id FROM ApplicationEntity a WHERE a.id = :id") + Long findCallIdById(@Param("id") Long id); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java index 35322a6a..b9d2bce3 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationSignedDocumentRepository.java @@ -1,13 +1,24 @@ package net.gepafin.tendermanagement.repositories; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import net.gepafin.tendermanagement.entities.ApplicationSignedDocumentEntity; +import java.util.List; + @Repository public interface ApplicationSignedDocumentRepository extends JpaRepository { ApplicationSignedDocumentEntity findByApplicationIdAndStatus(Long applicationId, String status); + Long findApplicationIdById(Long id); + + @Query("SELECT a.id FROM ApplicationSignedDocumentEntity d JOIN d.application a WHERE d.id = :id") + List findApplicationIdIdsById(@Param("id") Long id); + + @Query("SELECT d FROM ApplicationSignedDocumentEntity d WHERE d.status = :status") + List findAllByIsStatus(@Param("status")String status); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java index 4f621d38..b7fc2923 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -25,5 +25,7 @@ public interface DocumentRepository extends JpaRepository Optional findByIdAndSourceIdAndSourceAndIsDeletedFalse(Long id, Long sourceId, String source); + @Query("SELECT d FROM DocumentEntity d WHERE d.isDeleted = false") + List findAllByIsDeleteFalse(); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/S3ConfigRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/S3ConfigRepository.java new file mode 100644 index 00000000..2349861c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/S3ConfigRepository.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; +import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface S3ConfigRepository extends JpaRepository { + Optional getPathByType(String type); + + S3ConfigEntity findS3PathConfigurationById(Long id); + + String getBucketNameByType(DocumentSourceTypeEnum type); + + String getBucketNameByType(DocOtherSourceTypeEnum type); + + @Query("Select s3.parentFolder From S3ConfigEntity s3 Where s3.type = :s") + String getPathByTypeOther(String s); +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java index 1224dd70..03067c80 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserCompanyDelegationRepository.java @@ -2,9 +2,15 @@ package net.gepafin.tendermanagement.repositories; import org.springframework.data.jpa.repository.JpaRepository; import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface UserCompanyDelegationRepository extends JpaRepository { UserCompanyDelegationEntity findByUserIdAndCompanyIdAndStatus(Long userId, Long companyId, String status); + @Query("SELECT d FROM UserCompanyDelegationEntity d where d.status = :status") + List findAllByStatus(@Param("status") String status); } diff --git a/src/main/java/net/gepafin/tendermanagement/service/S3ConfigService.java b/src/main/java/net/gepafin/tendermanagement/service/S3ConfigService.java new file mode 100644 index 00000000..d284e649 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/S3ConfigService.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.model.request.S3ConfigReq; +import net.gepafin.tendermanagement.model.response.S3ConfigBean; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +public interface S3ConfigService { + S3ConfigBean addS3Path(S3ConfigReq s3Path); + + Optional getS3PathByType(String type); + + S3ConfigEntity deleteS3PathById(Long id); + + S3ConfigBean updateS3PathConfiguration(S3ConfigReq s3PathConfigurationReq, Long id); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java index 3b3fa310..235a1244 100644 --- a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java @@ -34,7 +34,7 @@ public class DocumentServiceImpl implements DocumentService { @Override public DocumentResponseBean updateDocument(HttpServletRequest httpServletRequest, Long documentId, MultipartFile file, DocumentTypeEnum documentTypeEnum) { - return documentDao.updateDocument(documentId,file,documentTypeEnum); + return documentDao.updateDocument(documentId, file,documentTypeEnum); } @Override diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/S3ConfigServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/S3ConfigServiceImpl.java new file mode 100644 index 00000000..5dfa22de --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/S3ConfigServiceImpl.java @@ -0,0 +1,41 @@ +package net.gepafin.tendermanagement.service.impl; + +import jakarta.transaction.Transactional; +import net.gepafin.tendermanagement.dao.S3ConfigDao; +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.model.request.S3ConfigReq; +import net.gepafin.tendermanagement.model.response.S3ConfigBean; +import net.gepafin.tendermanagement.service.S3ConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class S3ConfigServiceImpl implements S3ConfigService { + @Autowired + S3ConfigDao s3ConfigDao; + + @Override + public S3ConfigBean addS3Path(S3ConfigReq s3Path) { + + return s3ConfigDao.addS3Path(s3Path); + } + @Override + public Optional getS3PathByType(String type) { + + return s3ConfigDao.getS3PathByType(type); + } + @Override + @Transactional + public S3ConfigEntity deleteS3PathById(Long id) { + + return s3ConfigDao.deleteS3PathConfigById(id); + } + @Override + @Transactional + public S3ConfigBean updateS3PathConfiguration(S3ConfigReq s3PathConfigurationReq, Long id) { + + return s3ConfigDao.updateS3PathConfiguration(s3PathConfigurationReq, id); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java new file mode 100644 index 00000000..4db4ea12 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/S3ReUploadMigrationService.java @@ -0,0 +1,197 @@ +package net.gepafin.tendermanagement.service.impl; + +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.GetObjectRequest; +import com.amazonaws.services.s3.model.ObjectMetadata; +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.dao.S3PathConfig; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.enums.DocumentSourceTypeEnum; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.ApplicationSignedDocumentRepository; +import net.gepafin.tendermanagement.repositories.DocumentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +@Slf4j +@Service +public class S3ReUploadMigrationService { + + private static final String OLD_BUCKET = "mementoresources"; + + private static final String SECURE_KEY = "267163962963"; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private AmazonS3Client s3Client; + + @Autowired + private S3PathConfig s3ConfigBean; + + @Autowired + private ApplicationRepository applicationRepository; + + @Autowired + private ApplicationSignedDocumentRepository applicationSignedDocumentRepository; + + @Autowired + private AmazonS3 amazonS3; + + @Value("${aws.s3.url}") + private String s3Url; + + private boolean migrationCompleted = false; + + public String reUploadAndMigrateDocuments(String providedKey) { + + if (migrationCompleted) { + return "Migration already completed."; + } + + // Validate the provided key + if (!isValidKey(providedKey)) { + return "Invalid or missing migration key."; + } + + List documents = documentRepository.findAllByIsDeleteFalse(); + + if (documents.isEmpty()) { + return "No documents found to migrate."; + } + + for (DocumentEntity document : documents) { + String oldUrl = document.getFilePath(); // This should contain the full URL + log.info("Processing {}", oldUrl); + + try { + File localFile = downloadFileFromS3(oldUrl); + String newKey = generateNewS3Path(document); // Make sure this generates the correct new path + String uploadedPath = uploadFileToNewBucket(localFile, newKey); + updateDocumentPathAndDeleteOldEntry(document, uploadedPath); + } catch (Exception e) { + log.error("Error processing document {}: {}", document.getId(), e.getMessage()); + } + } + return "Migrated Successfully."; + } + + private boolean isValidKey(String providedKey) { + + return providedKey != null && providedKey.equals(SECURE_KEY); + } + + private File downloadFileFromS3(String fileUrl) throws Exception { + + String key = extractS3KeyFromUrl(fileUrl); // Get the S3 key from the URL + File localFile = new File("/tmp/" + extractFileName(key)); // Save file locally + + GetObjectRequest getObjectRequest = new GetObjectRequest(OLD_BUCKET, key); // Use the key + + try (InputStream s3Stream = s3Client.getObject(getObjectRequest).getObjectContent(); FileOutputStream outputStream = new FileOutputStream(localFile)) { + s3Stream.transferTo(outputStream); + } + + log.info("Downloaded file from old S3 bucket: {}", key); + return localFile; + } + + private String extractS3KeyFromUrl(String url) { + // Assuming the URL structure is consistent + return url.replace("https://mementoresources.s3.eu-west-1.amazonaws.com/", ""); + } + + private String uploadFileToNewBucket(File localFile, String s3Folder) { + + InputStream inputStream = null; // Declare the InputStream here for cleanup + try { + // Extract file name from the local file + String fileName = extractFileName(localFile.getAbsolutePath()); // Get the file name + String path = s3Folder + "/" + fileName; // Construct the S3 path + + // Create InputStream from the local file + inputStream = new FileInputStream(localFile); + + // Set up object metadata + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentType("application/octet-stream"); + objectMetadata.setContentLength(localFile.length()); + + // Upload to S3 + s3Client.putObject(OLD_BUCKET, path, inputStream, objectMetadata); + + // Construct the full S3 URL + String fullUrl = String.format("https://%s.s3.%s.amazonaws.com/%s", OLD_BUCKET, "eu-west-1", path); + log.info("File '{}' uploaded successfully to Amazon S3 with URL: {}", fileName, fullUrl); + return fullUrl; + + } catch (IOException e) { + log.error("IOException occurred during file upload for '{}': {}", localFile.getName(), e.getMessage()); + throw new RuntimeException("Upload failed for: " + s3Folder + "/" + localFile.getName(), e); + } catch (AmazonServiceException e) { + log.error("Amazon service exception while uploading file '{}': {}", localFile.getName(), e.getMessage()); + throw new RuntimeException("Upload failed for: " + s3Folder + "/" + localFile.getName(), e); + } catch (SdkClientException e) { + log.error("SDK client exception while uploading file '{}': {}", localFile.getName(), e.getMessage()); + throw new RuntimeException("Upload failed for: " + s3Folder + "/" + localFile.getName(), e); + } finally { + // Close InputStream if it was opened + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + log.warn("Failed to close InputStream for file '{}': {}", localFile.getName(), e.getMessage()); + } + } + } + } + + private String generateNewS3Path(DocumentEntity document) { + + DocumentSourceTypeEnum sourceType = DocumentSourceTypeEnum.valueOf(document.getSource()); + Long callId; + + if (sourceType.equals(DocumentSourceTypeEnum.CALL)) { + return s3ConfigBean.generateDocumentPath(sourceType, document.getSourceId(), 0L); + } else { + callId = applicationRepository.findCallIdById(document.getSourceId()); + return s3ConfigBean.generateDocumentPath(sourceType, callId, document.getSourceId()); + } + } + + private String extractFileName(String filePath) { + + String[] parts = filePath.split("/"); + return parts[parts.length - 1]; + } + + + private void updateDocumentPathAndDeleteOldEntry(DocumentEntity document, String newPath) { + + String fileName = extractFileName(newPath); + DocumentEntity newDocument = new DocumentEntity(); + newDocument.setFilePath(newPath); + newDocument.setSource(document.getSource()); + newDocument.setType(document.getType()); + newDocument.setIsDeleted(false); + newDocument.setSourceId(document.getSourceId()); + newDocument.setFileName(fileName); + + documentRepository.save(newDocument); + documentRepository.delete(document); + + log.info("Migrated document ID: {} to new path: {}", document.getId(), newPath); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java new file mode 100644 index 00000000..c1228565 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserSignedAndDelegationServiceImpl.java @@ -0,0 +1,261 @@ +package net.gepafin.tendermanagement.service.impl; + +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.GetObjectRequest; +import com.amazonaws.services.s3.model.ObjectMetadata; +import lombok.extern.slf4j.Slf4j; +import net.gepafin.tendermanagement.dao.S3PathConfig; +import net.gepafin.tendermanagement.entities.ApplicationSignedDocumentEntity; +import net.gepafin.tendermanagement.entities.UserCompanyDelegationEntity; +import net.gepafin.tendermanagement.enums.DocOtherSourceTypeEnum; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.ApplicationSignedDocumentRepository; +import net.gepafin.tendermanagement.repositories.S3ConfigRepository; +import net.gepafin.tendermanagement.repositories.UserCompanyDelegationRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Service +public class UserSignedAndDelegationServiceImpl { + private static final String OLD_BUCKET = "mementoresources"; + + private static final String NEW_BUCKET = "mementoresources"; + + private static final String SECURE_KEY = "267163962963"; + + @Autowired + private UserCompanyDelegationRepository userCompanyDelegationRepository; + + @Autowired + private AmazonS3Client s3Client; + + @Autowired + private S3PathConfig s3ConfigBean; + + @Autowired + private ApplicationSignedDocumentRepository applicationSignedDocumentRepository; + + @Autowired + ApplicationRepository applicationRepository; + + @Autowired + S3ConfigRepository s3ConfigRepository; + + @Value("${aws.s3.url}") + private String s3Url; + + private boolean migrationCompleted = false; + + + public String migrateUserDelegatedDocuments(String providedKey) { + + if (migrationCompleted) { + return "Migration already completed."; + } + + // Validate the provided key + if (isValidKey(providedKey)) { + return "Invalid or missing migration key."; + } + + List documents = userCompanyDelegationRepository.findAllByStatus("ACTIVE"); + + if (documents.isEmpty()) { + return "No documents found to migrate."; + } + + for (UserCompanyDelegationEntity document : documents) { + String oldUrl = document.getFilePath(); + log.info("Processing user designated document: {}", oldUrl); + + try { + File localFile = downloadFileFromS3(oldUrl); + String newKey = generateNewS3PathForDelegationDoc(); + String uploadedPath = uploadFileToNewBucket(localFile, newKey); + updateDelegatedDocumentPathAndDeleteOldEntry(document, uploadedPath); + } catch (Exception e) { + log.error("Error processing user designated document {}: {}", document.getId(), e.getMessage()); + } + } + return "Migrated"; + } + + + public String migrateUserSignedDocuments(String providedKey) { + + if (migrationCompleted) { + return "Migration already completed."; + } + + // Validate the provided key + if (isValidKey(providedKey)) { + return "Invalid or missing migration key."; + } + List documents = applicationSignedDocumentRepository.findAllByIsStatus("ACTIVE"); + + if (documents.isEmpty()) { + return "No documents found to migrate."; + } + + for (ApplicationSignedDocumentEntity document : documents) { + String oldUrl = document.getFilePath(); + log.info("Processing user signed document: {}", oldUrl); + + try { + File localFile = downloadFileFromS3(oldUrl); + String newKey = generateNewS3PathForUserSignedDoc(document); + String uploadedPath = uploadFileToNewBucket(localFile, newKey); + updateDocumentPathAndDeleteOldEntry(document, uploadedPath); + } catch (Exception e) { + log.error("Error processing user signed document {}: {}", document.getId(), e.getMessage()); + } + } + return "Migrated."; + } + + private boolean isValidKey(String providedKey) { + + return providedKey == null || !providedKey.equals(SECURE_KEY); + } + + private String generateNewS3PathForDelegationDoc() { + + return s3ConfigBean.generateDocumentPathForOther(DocOtherSourceTypeEnum.USER_DELEGATION, 0L, 0L); + } + + private String generateNewS3PathForUserSignedDoc(ApplicationSignedDocumentEntity document) { + // Fetch the list of application IDs associated with the document + List applicationIds = applicationSignedDocumentRepository.findApplicationIdIdsById(document.getId()); + List paths = new ArrayList<>(); + + // Loop through the application IDs and generate paths + for (Long applicationId : applicationIds) { + Long callId = applicationRepository.findCallIdById(applicationId); + + // Construct the path for the current application and call ID + String newPath = String.format("%s/call/call_%d/application/application_%d/user_signed_document", s3ConfigRepository.getPathByTypeOther( + String.valueOf(DocOtherSourceTypeEnum.USER_SIGNED_DOCUMENT)) , callId, applicationId); + + log.info("Generated new S3 path: {}", newPath); + paths.add(newPath); + } + + return String.join(",", paths); + } + + private File downloadFileFromS3(String fileUrl) throws Exception { + + String key = extractS3KeyFromUrl(fileUrl); + File localFile = new File("/tmp/" + extractFileName(key)); + + GetObjectRequest getObjectRequest = new GetObjectRequest(OLD_BUCKET, key); + + try (InputStream s3Stream = s3Client.getObject(getObjectRequest).getObjectContent(); FileOutputStream outputStream = new FileOutputStream(localFile)) { + s3Stream.transferTo(outputStream); + } + + log.info("Downloaded file from old S3 bucket: {}", key); + return localFile; + } + + private String extractS3KeyFromUrl(String url) { + + return url.replace("https://mementoresources.s3.eu-west-1.amazonaws.com/", ""); + } + + private String uploadFileToNewBucket(File localFile, String s3Path) { + + InputStream inputStream = null; + try { + String fileName = extractFileName(localFile.getAbsolutePath()); // Extract file name + String fullPath = String.format("%s/%s", s3Path, fileName); // Construct full path + + inputStream = new FileInputStream(localFile); // Create InputStream + + // Set metadata for the file + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(localFile.length()); + objectMetadata.setContentType("application/octet-stream"); + + // Upload the file to S3 with the constructed path + s3Client.putObject(NEW_BUCKET, fullPath, inputStream, objectMetadata); + + // Construct the full S3 URL for the uploaded file + String fullUrl = String.format("https://%s.s3.%s.amazonaws.com/%s", NEW_BUCKET, "eu-west-1", fullPath); + log.info("File '{}' uploaded successfully to Amazon S3 with URL: {}", fileName, fullUrl); + return fullUrl; + + } catch (IOException e) { + log.error("IOException occurred during file upload for '{}': {}", localFile.getName(), e.getMessage()); + throw new RuntimeException("Upload failed for: " + localFile, e); + } catch (AmazonServiceException e) { + log.error("Amazon service exception while uploading file '{}': {}", localFile.getName(), e.getMessage()); + throw new RuntimeException("Upload failed for: " + localFile, e); + } catch (SdkClientException e) { + log.error("SDK client exception while uploading file '{}': {}", localFile.getName(), e.getMessage()); + throw new RuntimeException("Upload failed for: " + localFile, e); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + log.warn("Failed to close InputStream for file '{}': {}", localFile.getName(), e.getMessage()); + } + } + } + } + + private String extractFileName(String filePath) { + + String[] parts = filePath.split("/"); + return parts[parts.length - 1]; + } + private String extractFileNameFromPath(String path) { + + return path.substring(path.lastIndexOf('/') + 1); + } + + private void updateDocumentPathAndDeleteOldEntry(ApplicationSignedDocumentEntity document, String newPath) { + + ApplicationSignedDocumentEntity newDocument = new ApplicationSignedDocumentEntity(); + String fileName = extractFileNameFromPath(newPath); + newDocument.setFilePath(newPath); + newDocument.setFileName(fileName); + newDocument.setApplication(document.getApplication()); + newDocument.setStatus("ACTIVE"); + + applicationSignedDocumentRepository.save(newDocument); + applicationSignedDocumentRepository.delete(document); + + log.info("Migrated document ID: {} to new path: {}", document.getId(), newPath); + } + + private void updateDelegatedDocumentPathAndDeleteOldEntry(UserCompanyDelegationEntity document, String newPath) { + + String fileName = extractFileNameFromPath(newPath); + UserCompanyDelegationEntity newDocument = new UserCompanyDelegationEntity(); + newDocument.setFilePath(newPath); + newDocument.setFileName(fileName); + newDocument.setBeneficiaryId(document.getBeneficiaryId()); + newDocument.setUserId(document.getUserId()); + newDocument.setCompanyId(document.getCompanyId()); + newDocument.setStatus("ACTIVE"); + + userCompanyDelegationRepository.save(newDocument); + userCompanyDelegationRepository.delete(document); + + log.info("Migrated document ID: {} to new path: {}", document.getId(), newPath); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3ConfigApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3ConfigApi.java new file mode 100644 index 00000000..61b3bd6c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3ConfigApi.java @@ -0,0 +1,67 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.model.request.S3ConfigReq; +import net.gepafin.tendermanagement.model.response.S3ConfigBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.data.repository.query.Param; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.Optional; + +@Validated +public interface S3ConfigApi { + + @Operation(summary = "Api to create S3Path structure.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "", produces = { "application/json" }) + ResponseEntity> addS3Path(@Valid @RequestBody S3ConfigReq s3pathReq); + + @Operation(summary = "Api to get S3Path structure. by type", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "", produces = { "application/json" }) + ResponseEntity>> getS3PathByType(@Valid @Param(value = "type") String type); + + @Operation(summary = "Api to delete S3Path structure. by id", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @DeleteMapping(value = "", produces = { "application/json" }) + ResponseEntity> deleteS3PathConfigById(@Valid @Param(value = "id") Long id); + + @Operation(summary = "Api to update S3Path structure. by id", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "", produces = { "application/json" }) + ResponseEntity> updateS3PathConfigById(@Valid @RequestBody S3ConfigReq s3PathConfigurationReq, @Param(value = "id") Long id); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java new file mode 100644 index 00000000..4a4d3eb1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/S3MigrationApi.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.data.repository.query.Param; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; + +@Validated +public interface S3MigrationApi { + + @Operation(summary = "Api to migrate S3 doc to db and update s3 files as per specified folder.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PutMapping(value = "/{key}", produces = { "application/json" }) + String reUploadAndMigrateDocuments(@Parameter(description = "The secret key", required = true) @PathVariable("key") String key); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java new file mode 100644 index 00000000..2a3978a1 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserSignedAndDelegationApi.java @@ -0,0 +1,38 @@ +package net.gepafin.tendermanagement.web.rest.api; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.data.repository.query.Param; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +@Validated +public interface UserSignedAndDelegationApi { + @Operation(summary = "Api to migrate S3 doc to db and user-delegated folder", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @GetMapping(value = "/{key}", produces = { "application/json" }) + String migrateUserDelegatedDocuments(@Parameter(description = "The secret key", required = true) @PathVariable("key") String key); + + @Operation(summary = "Api to migrate S3 doc to user-signed.", responses = { @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })), + @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = { + @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) })) }) + @PostMapping(value = "/{key}", produces = { "application/json" }) + String migrateUserSignedDocuments(@Parameter(description = "The secret key", required = true) @PathVariable("key") String key); +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java index 7141a256..34caa9fd 100644 --- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java @@ -31,7 +31,7 @@ DocumentApiController implements DocumentApi { public ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, Long sourceId, DocumentSourceTypeEnum sourceType, List files, DocumentTypeEnum fileType) { try { - List responseBeans = documentService.uploadFile(files, sourceId,sourceType, fileType); + List responseBeans = documentService.uploadFile(files, sourceId, sourceType, fileType); return ResponseEntity.status(HttpStatus.CREATED) .body(new Response>(responseBeans, Status.SUCCESS, Translator.toLocale(GepafinConstant.FILES_UPLOADED_MSG))); } catch (CustomValidationException ex) { diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3ConfigController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3ConfigController.java new file mode 100644 index 00000000..62f12414 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3ConfigController.java @@ -0,0 +1,59 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.S3ConfigEntity; +import net.gepafin.tendermanagement.model.request.S3ConfigReq; +import net.gepafin.tendermanagement.model.response.S3ConfigBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.S3ConfigService; +import net.gepafin.tendermanagement.web.rest.api.S3ConfigApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/s3-path-config}") +public class S3ConfigController implements S3ConfigApi { + + private static final Logger log = LoggerFactory.getLogger(S3ConfigController.class); + + @Autowired + S3ConfigService s3PathService; + + @Override + public ResponseEntity> addS3Path(S3ConfigReq s3pathReq) { + + log.info("Request Body : {}, {}, {}", s3pathReq.getPath(), s3pathReq.getType(), s3pathReq.getBucketName()); + S3ConfigBean s3Path = s3PathService.addS3Path(s3pathReq); + return ResponseEntity.status(HttpStatus.CREATED).body(new Response(s3Path, Status.SUCCESS, Translator.toLocale(GepafinConstant.ADDED_S3_PATH_STRUCTURE))); + } + @Override + public ResponseEntity>> getS3PathByType(String type) { + + log.info("Request to get S3Path by type {}", type); + Optional s3Path = s3PathService.getS3PathByType(type); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response>(s3Path, Status.SUCCESS, Translator.toLocale(GepafinConstant.S3_PATH_STRUCTURE_BY_TYPE))); + } + @Override + public ResponseEntity> deleteS3PathConfigById(Long id) { + log.info("Request to delete S3Path by Id {}", id); + S3ConfigEntity deletedS3PathConfig = s3PathService.deleteS3PathById(id); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response(deletedS3PathConfig, Status.SUCCESS, Translator.toLocale(GepafinConstant.S3_PATH_DELETE_MSG))); + } + @Override + public ResponseEntity> updateS3PathConfigById(S3ConfigReq s3PathConfigurationReq, Long id) { + S3ConfigBean updatedS3PathConfiguration = s3PathService.updateS3PathConfiguration(s3PathConfigurationReq, id); + return ResponseEntity.status(HttpStatus.OK) + .body(new Response(updatedS3PathConfiguration, Status.SUCCESS, Translator.toLocale(GepafinConstant.S3_PATH_CONFIG_UPDATE_MSG))); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java new file mode 100644 index 00000000..7e58800e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3MigrationApiController.java @@ -0,0 +1,19 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import net.gepafin.tendermanagement.service.impl.S3ReUploadMigrationService; +import net.gepafin.tendermanagement.web.rest.api.S3MigrationApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/s3-migration}") +public class S3MigrationApiController implements S3MigrationApi { + + @Autowired + S3ReUploadMigrationService s3MigrationService; + @Override + public String reUploadAndMigrateDocuments(String providedKey) { + return s3MigrationService.reUploadAndMigrateDocuments(providedKey); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java new file mode 100644 index 00000000..061b731b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/S3UserSignedAndDelegationMigrationController.java @@ -0,0 +1,24 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import net.gepafin.tendermanagement.service.impl.UserSignedAndDelegationServiceImpl; +import net.gepafin.tendermanagement.web.rest.api.UserSignedAndDelegationApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/s3-user-signed-and-delegation-migration}") +public class S3UserSignedAndDelegationMigrationController implements UserSignedAndDelegationApi { + + @Autowired + UserSignedAndDelegationServiceImpl userSignedAndDelegationService; + + @Override + public String migrateUserDelegatedDocuments(String providedKey) { + return userSignedAndDelegationService.migrateUserDelegatedDocuments(providedKey); + } + @Override + public String migrateUserSignedDocuments(String providedKey) { + return userSignedAndDelegationService.migrateUserSignedDocuments(providedKey); + } +} diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml index 5df3a2b7..06d8550a 100644 --- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml +++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -67,7 +67,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -101,18 +101,18 @@ - - + + - - + + - - + + @@ -122,19 +122,19 @@ - + - + - + - + - + @@ -250,7 +250,8 @@ - + + @@ -270,34 +271,39 @@ - + + - + - + - + + + - - - + + - + @@ -318,7 +324,8 @@ - + @@ -329,7 +336,8 @@ - + @@ -340,7 +348,8 @@ - + @@ -351,7 +360,8 @@ - + @@ -416,7 +426,8 @@ - + + @@ -432,7 +443,8 @@ - + + @@ -454,50 +466,50 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -507,62 +519,62 @@ + path="db/dump/inserted_form_field_data_30_08_2024.sql"/> select setval('gepafin_schema.form_field_id_seq', (select max(id)+1 from gepafin_schema.form_field), false) - - - - - - - - - - + + + + + + + + + + + references="lookup_data(id)"/> - - - - + + + + TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; + path="db/dump/update_form_field_data_04_09_2024.sql"/> - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -586,23 +598,26 @@ - + + - + - + - + - + + @@ -618,9 +633,10 @@ - + + - + @@ -634,12 +650,13 @@ - + + - + - + @@ -658,18 +675,20 @@ - + - + + - + @@ -693,7 +712,7 @@ TRUNCATE TABLE FORM_FIELD RESTART IDENTITY; + path="classpath:db/dump/inserted_form_field_data_13_09_2024.sql"/> @@ -708,7 +727,7 @@ + path="classpath:db/dump/updated_form_field_data_16-09-2024.sql"/> @@ -739,16 +758,16 @@ $$; - - - - - - - - - - + + + + + + + + + + @@ -783,99 +802,99 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + - + id = 13 - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - + + - + - + @@ -890,25 +909,25 @@ - + - - - + + + - - - - + + + + - + - + @@ -924,8 +943,8 @@ - - + + @@ -934,48 +953,48 @@ + path="classpath:db/dump/updated_form_field_data_03-10-2024.sql"/> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -983,7 +1002,7 @@ + path="classpath:db/dump/updated_form_field_data_03-10-2024_1.sql"/> @@ -994,8 +1013,8 @@ - - + + @@ -1003,16 +1022,16 @@ - - + + + primaryKeyName="protocol_pkey"/> @@ -1058,132 +1077,132 @@ - - - - + + + + + primaryKeyName="system_email_template_pkey"/> - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - - - - name='table' - - + + + + + name='table' + + + path="db/dump/update_system_email_template_of_application_submission.sql"/> - + + primaryKeyName="login_attempt_pkey"/> - - + + - - + + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - + + primaryKeyName="criteria_form_field_pkey"/> - - - - + + + + - - - - + + + + - + @@ -1226,9 +1245,10 @@ - + - + @@ -1244,47 +1264,44 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - @@ -1293,12 +1310,12 @@ - + - - + + @@ -1315,17 +1332,90 @@ - + - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +