diff --git a/pom.xml b/pom.xml index 1572627b..ac87bfdd 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,26 @@ spring-boot-starter-test test + + + com.amazonaws + aws-java-sdk-s3 + 1.12.312 + + + + com.amazonaws + aws-java-sdk-core + 1.12.341 + + + + commons-io + commons-io + 2.11.0 + + + diff --git a/src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java b/src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java new file mode 100644 index 00000000..878cd12f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/config/AmazonConfig.java @@ -0,0 +1,34 @@ +package net.gepafin.tendermanagement.config; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AmazonConfig { + + @Value("${aws.access.key.id}") + private String accessKey; + + @Value("${aws.secret.access.key}") + private String secretKey; + + @Value("${aws.s3.region}") + private String region; + + @Bean + public AmazonS3 mementoBucket() { + AWSCredentials awsCredentials = + new BasicAWSCredentials(accessKey, secretKey); + return AmazonS3ClientBuilder + .standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 7d00913f..cdb9e573 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -24,4 +24,18 @@ public class GepafinConstant { public static final String DELETE_REGION_SUCCESS_MSG = "delete.region.success"; public static final String REGION_NOT_FOUND_MSG = "user.region.not.found"; public static final String PASSWORD_DOESNT_MATCH ="password.doesnt.match"; + public static final String USER_NOT_EXIST_MSG = "user.not.exist"; + public static final String REGION_NOT_FOUND = "region.not.found"; + public static final String USER_ID_NOT_NULL_MSG = "user.id.not.null"; + public static final String QUESTION_NOT_EMPTY_MSG = "question.not.empty"; + public static final String NAME_NOT_EMPTY_MSG = "name.not.empty"; + public static final String TYPE_NOT_EMPTY_MSG = "type.not.empty"; + public static final String REGION_NOT_NULL_MSG = "region.not.null"; + public static final String AMOUNT_GREATER_THAN_ZERO_MSG = "amount.greater.than.zero"; + public static final String LOOK_UP_DATA_NOT_VALID_MSG = "look.up.data.not.valid"; + public static final String FILES_UPLOADED_MSG = "files.uploaded"; + public static final String CALL_CREATED_SUCCESSFULLY_MSG = "call.created.successfully"; + public static final String FILE_DELETED_SUCCESSFULLY_MSG="file.deleted.successfully"; + public static final String DOCUMENT_NOT_FOUND="document.not.found"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java new file mode 100644 index 00000000..fc2b966c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/CallDao.java @@ -0,0 +1,323 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import net.gepafin.tendermanagement.enums.CallTypeEnum; +import net.gepafin.tendermanagement.model.request.*; +import net.gepafin.tendermanagement.model.response.*; +import net.gepafin.tendermanagement.repositories.*; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.util.DateTimeUtil; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import net.gepafin.tendermanagement.entities.LookUpDataEntity.LookUpDataTypeEnum; + +@Component +public class CallDao { + + @Autowired + private CallRepository callRepository; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private EvaluationCriteriaRepository evaluationCriteriaRepository; + + @Autowired + private FaqRepository faqRepository; + + @Autowired + private RegionRepository regionRepository; + + @Autowired + private LookUpDataRepository lookUpDataRepository; + + @Autowired + private CallTargetAudienceChecklistRepository callTargetAudienceChecklistRepository; + + public CreateCallResponseBean createCall(CreateCallRequest createCallRequest) { + try { + CreateCallResponseBean createCallResponseBean=null; + CallEntity callEntity = convertToCallEntity(createCallRequest); + List evaluationCriteriaEntities = convertToEvaluationCriteriaEntities(createCallRequest.getCriteria(), callEntity); + List documentEntities = convertToDocumentEntities(createCallRequest.getDocs(), callEntity); + List imageEntities=convertToDocumentEntities(createCallRequest.getImages(),callEntity); + List faqEntities = convertToFaqEntities(createCallRequest.getFaq(), callEntity); + List amiedTo=convertLookUpDataEntities(createCallRequest.getAimedTo(),callEntity,LookUpDataTypeEnum.AIMED_TO); + List checkList=convertLookUpDataEntities(createCallRequest.getAimedTo(),callEntity,LookUpDataTypeEnum.CHECKLIST); + createCallResponseBean= assembleCreateCallResponseBean(callEntity, evaluationCriteriaEntities, documentEntities, faqEntities,imageEntities); + createCallResponseBean.setAimedTo(amiedTo); + createCallResponseBean.setCheckList(checkList); + return createCallResponseBean; + } catch (Exception e) { + throw new RuntimeException("Error processing create call request", e); + } + } + + + public CallEntity convertToCallEntity(CreateCallRequest createCallRequest) { + CallEntity callEntity = new CallEntity(); + validateCallEntity(createCallRequest.getRegionId(), createCallRequest.getAmount()); + RegionEntity region = regionRepository.findById(createCallRequest.getRegionId()) + .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND))); + callEntity.setRegion(region); + callEntity.setName(createCallRequest.getName()); + callEntity.setDescriptionShort(createCallRequest.getDescriptionShort()); + callEntity.setDescriptionLong(createCallRequest.getDescriptionLong()); + callEntity.setStartDate(createCallRequest.getStartDate()); + callEntity.setEndDate(createCallRequest.getEndDate()); + callEntity.setStatus(String.valueOf(createCallRequest.getStatus())); + callEntity.setAmountMax(createCallRequest.getAmountMax()); + callEntity.setAmount(createCallRequest.getAmountMax()); + callEntity.setThreshold(createCallRequest.getThreshold()); + callEntity.setConfidi(false); + if(createCallRequest.getConfidi()!=null){ + callEntity.setConfidi(createCallRequest.getConfidi()); + } + callEntity.setDocumentation_requested(createCallRequest.getDocumentationRequested()); + callEntity = callRepository.save(callEntity); + return callEntity; + } + + public List convertToEvaluationCriteriaEntities(List criteriaReqList, CallEntity callEntity) { + List evaluationCriteriaEntities = criteriaReqList.stream().map(req -> convertToEvaluationCriteriaEntity(req, callEntity)).collect(Collectors.toList()); + evaluationCriteriaRepository.saveAll(evaluationCriteriaEntities); + return evaluationCriteriaEntities; + } + + private EvaluationCriteriaEntity convertToEvaluationCriteriaEntity(EvaluationCriteriaReq criteriaReq, CallEntity callEntity) { + EvaluationCriteriaEntity criteriaEntity = new EvaluationCriteriaEntity(); + validateEvolutionCrieteriaEntity(criteriaReq.getName()); + criteriaEntity.setName(criteriaReq.getName()); + criteriaEntity.setDescription(criteriaReq.getValue()); + criteriaEntity.setScore(criteriaReq.getScore()); + criteriaEntity.setCall(callEntity); + return criteriaEntity; + } + + + public List convertToDocumentEntities(List documentReqList, CallEntity callEntity) { + List documentEntities = documentReqList.stream().map(req -> convertToDocumentEntity(req, callEntity)).collect(Collectors.toList()); + documentRepository.saveAll(documentEntities); + return documentEntities; + } + + private DocumentEntity convertToDocumentEntity(DocumentReq documentReq, CallEntity callEntity) { + DocumentEntity documentEntity = new DocumentEntity(); + validateDocumentEntity(documentReq.getFileName()); + documentEntity.setFileName(documentReq.getFileName()); + documentEntity.setFilePath(documentReq.getUrl()); + documentEntity.setCall(callEntity); + return documentEntity; + } + + + public List convertToFaqEntities(List faqReqList, CallEntity callEntity) { + List faqEntities = faqReqList.stream().map(req -> convertToFaqEntity(req, callEntity)).collect(Collectors.toList()); + faqRepository.saveAll(faqEntities); + return faqEntities; + } + + private FaqEntity convertToFaqEntity(FaqReq faqReq, CallEntity callEntity) { + FaqEntity faqEntity = new FaqEntity(); + validateFaqEntity(faqReq.getQuestion()); +// UserEntity userEntity= userRepository.findById(1l) +// .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.LOOK_UP_DATA_NOT_VALID_MSG))); +// faqEntity.setUser(userEntity); + faqEntity.setIsVisible(true); + if(faqReq.getIsVisible()!=null){ + faqEntity.setIsVisible(faqReq.getIsVisible()); + } + faqEntity.setQuestionShort(faqReq.getQuestionShort()); + faqEntity.setQuestion(faqReq.getQuestion()); + if(faqReq.getResponse()!=null ||faqReq.getResponseShort()!=null){ + faqEntity.setResponseDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now())); + } + faqEntity.setResponseShort(faqReq.getResponseShort()); + faqEntity.setResponse(faqReq.getResponse()); + faqEntity.setCall(callEntity); + return faqEntity; + } + + public void validateFaqEntity( String question) { + if (!StringUtils.hasText(question)) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.QUESTION_NOT_EMPTY_MSG)); + } + } + + public void validateDocumentEntity(String name) { + if (!StringUtils.hasText(name)) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.NAME_NOT_EMPTY_MSG)); + } + } + + public void validateEvolutionCrieteriaEntity(String name) { + if (!StringUtils.hasText(name)) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.NAME_NOT_EMPTY_MSG)); + } + } + + public void validateCallEntity(Long regionId, BigDecimal fundingAmount) { + if (regionId == null) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.REGION_NOT_FOUND_MSG)); + } + + if (fundingAmount == null || fundingAmount.compareTo(BigDecimal.ZERO) <= 0) { + throw new CustomValidationException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.AMOUNT_GREATER_THAN_ZERO_MSG)); + } + } + public CreateCallResponseBean convertToCallResponseBean(CallEntity callEntity) { + CreateCallResponseBean createCallResponseBean = new CreateCallResponseBean(); + createCallResponseBean.setId(callEntity.getId()); + createCallResponseBean.setName(callEntity.getName()); + createCallResponseBean.setDates(List.of(callEntity.getStartDate(), callEntity.getEndDate())); + createCallResponseBean.setDescriptionShort(callEntity.getDescriptionShort()); + createCallResponseBean.setDescriptionLong(callEntity.getDescriptionLong()); + createCallResponseBean.setStatus(CallTypeEnum.valueOf(callEntity.getStatus())); + createCallResponseBean.setRegionId(callEntity.getRegion().getId()); + createCallResponseBean.setAmount(callEntity.getAmount()); + createCallResponseBean.setAmountMax(callEntity.getAmountMax()); + createCallResponseBean.setContactInfo(callEntity.getContactInfo()); + createCallResponseBean.setSubmissionMethod(callEntity.getSubmissionMethod()); + createCallResponseBean.setThreshold(callEntity.getThreshold()); + createCallResponseBean.setDocumentationReqested(callEntity.getDocumentation_requested()); + createCallResponseBean.setPriorityArea(callEntity.getPriorityArea()); + createCallResponseBean.setCreatedDate(callEntity.getCreatedDate()); + createCallResponseBean.setUpdatedDate(callEntity.getUpdatedDate()); + return createCallResponseBean; + } + public EvaluationCriteriaResponseBean convertToEvaluationCriteriaResponseBean(EvaluationCriteriaEntity entity) { + EvaluationCriteriaResponseBean responseBean = new EvaluationCriteriaResponseBean(); + responseBean.setId(entity.getId()); + responseBean.setName(entity.getName()); + responseBean.setDescription(entity.getDescription()); + responseBean.setScore(entity.getScore()); + responseBean.setCreatedDate(entity.getCreatedDate()); + responseBean.setUpdatedDate(entity.getUpdatedDate()); + return responseBean; + } + public DocumentResponseBean convertToDocumentResponseBean(DocumentEntity entity) { + DocumentResponseBean responseBean = new DocumentResponseBean(); + responseBean.setId(entity.getId()); + responseBean.setName(entity.getFileName()); + responseBean.setDescription(entity.getDescription()); + responseBean.setFilePath(entity.getFilePath()); + responseBean.setCreatedDate(entity.getCreatedDate()); + responseBean.setUpdatedDate(entity.getUpdatedDate()); + return responseBean; + } + public FaqResponseBean convertToFaqResponseBean(FaqEntity entity) { + FaqResponseBean responseBean = new FaqResponseBean(); + responseBean.setId(entity.getId()); + responseBean.setQuestionShort(entity.getQuestionShort()); + responseBean.setResponseShort(entity.getResponseShort()); + responseBean.setResponse(entity.getResponse()); + responseBean.setQuestion(entity.getQuestion()); + responseBean.setUserId(entity.getUser().getId()); + responseBean.setIsVisible(entity.getIsVisible()); + responseBean.setCreatedDate(entity.getCreatedDate()); + responseBean.setUpdatedDate(entity.getUpdatedDate()); + return responseBean; + } + public CreateCallResponseBean assembleCreateCallResponseBean( + CallEntity callEntity, + List evaluationCriteriaEntities, + List documentEntities, + List faqEntities,List images) { + + CreateCallResponseBean callResponseBean = convertToCallResponseBean(callEntity); + + List evaluationCriteriaResponseBeans = evaluationCriteriaEntities.stream() + .map(this::convertToEvaluationCriteriaResponseBean) + .collect(Collectors.toList()); + + List documentResponseBeans = documentEntities.stream() + .map(this::convertToDocumentResponseBean) + .collect(Collectors.toList()); + + List faqResponseBeans = faqEntities.stream() + .map(this::convertToFaqResponseBean) + .collect(Collectors.toList()); + + List imagesResponseBean = images.stream() + .map(this::convertToDocumentResponseBean) + .collect(Collectors.toList()); + CreateCallResponseBean createCallResponseBean =callResponseBean; + createCallResponseBean.setCriteria(evaluationCriteriaResponseBeans); + createCallResponseBean.setDocs(documentResponseBeans); + createCallResponseBean.setFaq(faqResponseBeans); + createCallResponseBean.setImages(imagesResponseBean); + return createCallResponseBean; + } + public List convertLookUpDataEntities(List lookUpData, CallEntity callEntity, LookUpDataEntity.LookUpDataTypeEnum type) { + List lookUpDataEntities = lookUpData.stream() + .map(req -> convertLookUpDataRequestIntoLookUpDataEntity(req, type)) + .collect(Collectors.toList()); + + lookUpDataRepository.saveAll(lookUpDataEntities); + + return createCallTargetAudienceCheckList(callEntity, lookUpDataEntities); + } + + private List createCallTargetAudienceCheckList(CallEntity callEntity, List lookUpDataEntities) { + List lookUpDataResponses=new ArrayList<>(); + List callTargetAudienceChecklistEntities=new ArrayList<>(); + for(LookUpDataEntity lookUpDataEntity:lookUpDataEntities){ + CallTargetAudienceChecklistEntity callTargetAudienceChecklistEntity=new CallTargetAudienceChecklistEntity(); + callTargetAudienceChecklistEntity.setIsValidated(false); + callTargetAudienceChecklistEntity.setLookupData(lookUpDataEntity); + callTargetAudienceChecklistEntity.setCall(callEntity); + callTargetAudienceChecklistEntities.add(callTargetAudienceChecklistEntity); + lookUpDataResponses.add(convertToLookUpDataResponseBean(lookUpDataEntity,callTargetAudienceChecklistEntity)); + } + callTargetAudienceChecklistRepository.saveAll(callTargetAudienceChecklistEntities); + return lookUpDataResponses; + } + + private LookUpDataEntity convertLookUpDataRequestIntoLookUpDataEntity(LookUpDataReq req, LookUpDataEntity.LookUpDataTypeEnum type) { + if (req.getLookUpDataId() == null || req.getLookUpDataId().equals(BigDecimal.ZERO)) { + LookUpDataEntity newEntity = new LookUpDataEntity(); + newEntity.setValue(req.getValue()); + newEntity.setType(type.getValue()); + return newEntity; + } + + return lookUpDataRepository.findById(req.getLookUpDataId()) + .orElseThrow(() -> new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.LOOK_UP_DATA_NOT_VALID_MSG))); + } + + private CallTargetAudienceChecklistEntity createChecklistEntity(CallEntity callEntity, LookUpDataEntity lookUpDataEntity) { + CallTargetAudienceChecklistEntity checklistEntity = new CallTargetAudienceChecklistEntity(); + checklistEntity.setCall(callEntity); + checklistEntity.setLookupData(lookUpDataEntity); + checklistEntity.setIsValidated(false); + return checklistEntity; + } + + public LookUpDataResponse convertToLookUpDataResponseBean(LookUpDataEntity lookUpDataEntity,CallTargetAudienceChecklistEntity callTargetAudienceChecklistEntity) { + LookUpDataResponse lookUpDataResponse = new LookUpDataResponse(); + lookUpDataResponse.setId(callTargetAudienceChecklistEntity.getId()); + lookUpDataResponse.setLookUpDataId(lookUpDataEntity.getId()); + lookUpDataResponse.setValue(lookUpDataEntity.getValue()); + lookUpDataResponse.setTitle(lookUpDataEntity.getTitle()); + lookUpDataResponse.setCreatedDate(lookUpDataEntity.getCreatedDate()); + lookUpDataResponse.setUpdatedDate(lookUpDataEntity.getUpdatedDate()); + return lookUpDataResponse; + } +} + + + diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java new file mode 100644 index 00000000..3c5cd708 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/DocumentDao.java @@ -0,0 +1,80 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.repositories.DocumentRepository; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import net.gepafin.tendermanagement.util.Utils; +import net.gepafin.tendermanagement.web.rest.api.errors.ResourceNotFoundException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Component +public class DocumentDao { + + @Autowired + private AmazonS3Service amazonS3Service; + + @Autowired + private DocumentRepository documentRepository; + + @Autowired + private CallDao callDao; + + @Value("${aws.s3.bucket.name}") + private String bucketName; + + @Value("${aws.s3.url.folder}") + private String s3Folder; + + @Value("${aws.s3.url}") + private String s3Url; + + public List uploadFiles(List files, DocumentTypeEnum fileType) { + List documentEntities = new ArrayList<>(); + + for (MultipartFile file : files) { + try { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + String fileName = StringUtils.cleanPath(file.getOriginalFilename()); + String firstNameContain = fileName.substring(0, fileName.lastIndexOf('.')); + fileName = (firstNameContain + "." + extension); + String filepath = amazonS3Service.upload(fileName,file); + DocumentEntity documentEntity = new DocumentEntity(); + documentEntity.setFileName(fileName); + documentEntity.setType(fileType.getValue()); + documentEntity.setFilePath(filepath); + documentEntities.add(documentEntity); + } catch (IOException e) {} + } + documentRepository.saveAll(documentEntities); + return documentEntities.stream() + .map(callDao::convertToDocumentResponseBean) + .collect(Collectors.toList()); + } + public Void deleteFile(Long documentId){ + DocumentEntity documentEntity= documentRepository.findById(documentId); + if(documentEntity==null){ + new ResourceNotFoundException(Status.VALIDATION_ERROR, Translator.toLocale(GepafinConstant.DOCUMENT_NOT_FOUND)); + } + String fileName= Utils.extractFileName(documentEntity.getFilePath()); + try { + amazonS3Service.delete(bucketName, fileName); + documentRepository.delete(documentEntity); + }catch (Exception e){} + return null; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java new file mode 100644 index 00000000..1ee48d6b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/CallEntity.java @@ -0,0 +1,66 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Entity +@Table(name = "CALL") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class CallEntity extends BaseEntity { + + @Column(name = "NAME", nullable = false, length = 255) + private String name; + + @Column(name = "DESCRIPTION_SHORT", columnDefinition = "TEXT") + private String descriptionShort; + + @Column(name = "DESCRIPTION_LONG", columnDefinition = "TEXT") + private String descriptionLong; + + @Column(name = "START_DATE", nullable = false) + private LocalDateTime startDate; + + @Column(name = "END_DATE", nullable = false) + private LocalDateTime endDate; + + @Column(name = "STATUS", nullable = false, length = 255) + private String status; + + @ManyToOne + @JoinColumn(name = "REGION_ID", nullable = false, foreignKey = @ForeignKey(name = "fk_region_call")) + private RegionEntity region; + + @Column(name = "AMOUNT", nullable = false) + private BigDecimal amount; + + @Column(name = "AMOUNT_MAX", nullable = false) + private BigDecimal amountMax; + + @Column(name = "CONTACT_INFO", columnDefinition = "TEXT") + private String contactInfo; + + @Column(name = "SUBMISSION_METHOD", columnDefinition = "TEXT") + private String submissionMethod; + + @Column(name = "THRESHOLD", nullable = false) + private Integer threshold; + + @Column(name="DOCUMENTATION_REQUESTED",columnDefinition = "TEXT") + private String documentation_requested; + + @Column(name = "PRIORITY_AREA", columnDefinition = "TEXT") + private String priorityArea; + + @Column(name = "CONFIDI") + private Boolean confidi; +} + diff --git a/src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java new file mode 100644 index 00000000..be94ee59 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/CallTargetAudienceChecklistEntity.java @@ -0,0 +1,23 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "CALL_TARGET_AUDIENCE_CHECKLIST") +@Data +public class CallTargetAudienceChecklistEntity extends BaseEntity{ + + @ManyToOne + @JoinColumn(name = "CALL_ID") + private CallEntity call; + + @ManyToOne + @JoinColumn(name = "LOOKUP_DATA_ID") + private LookUpDataEntity lookupData; + + @Column(name = "IS_VALIDATED") + private Boolean isValidated; + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java new file mode 100644 index 00000000..5a15351c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/DocumentEntity.java @@ -0,0 +1,31 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + +@Entity +@Table(name = "DOCUMENT") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class DocumentEntity extends BaseEntity{ + @Column(name = "FILE_NAME", length = 255) + private String fileName; + + @Column(name = "FILE_PATH", length = 255) + private String filePath; + + @Column(name="TYPE") + private String type; + + @ManyToOne + @JoinColumn(name = "CALL_ID") + private CallEntity call; + + @Column(name = "DESCRIPTION", columnDefinition = "TEXT") + private String description; +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java new file mode 100644 index 00000000..539d9c30 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/EvaluationCriteriaEntity.java @@ -0,0 +1,30 @@ +package net.gepafin.tendermanagement.entities; +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + + +@Entity +@Table(name = "EVALUATION_CRITERIA") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class EvaluationCriteriaEntity extends BaseEntity { + + @ManyToOne + @JoinColumn(name = "CALL_ID", nullable = false) + private CallEntity call; + + @Column(name = "NAME", nullable = false, columnDefinition = "TEXT") + private String name; + + @Column(name = "DESCRIPTION", columnDefinition = "TEXT") + private String description; + + @Column(name = "SCORE", nullable = false) + private Integer score; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java new file mode 100644 index 00000000..aa521521 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/FaqEntity.java @@ -0,0 +1,46 @@ +package net.gepafin.tendermanagement.entities; + +import jakarta.persistence.*; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; +import lombok.Builder; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "FAQ") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class FaqEntity extends BaseEntity { + + @ManyToOne + @JoinColumn(name = "CALL_ID", nullable = false) + private CallEntity call; + + @ManyToOne + @JoinColumn(name = "USER_ID", nullable = false, foreignKey = @ForeignKey(name = "fk_user_faq")) + private UserEntity user; + + @Column(name = "IS_VISIBLE", nullable = false) + private Boolean isVisible; + + @Column(name = "QUESTION_SHORT", length = 255) + private String questionShort; + + @Column(name = "QUESTION", columnDefinition = "TEXT") + private String question; + + @Column(name = "RESPONSE_SHORT", length = 255) + private String responseShort; + + @Column(name = "RESPONSE", columnDefinition = "TEXT") + private String response; + + @Column(name = "RESPONSE_DATE") + private LocalDateTime responseDate; + +} + diff --git a/src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java new file mode 100644 index 00000000..41ca9ba7 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/entities/LookUpDataEntity.java @@ -0,0 +1,37 @@ +package net.gepafin.tendermanagement.entities; + +import com.fasterxml.jackson.annotation.JsonValue; +import jakarta.persistence.*; +import lombok.Data; + +@Entity +@Table(name = "LOOKUP_DATA") +@Data +public class LookUpDataEntity extends BaseEntity{ + + @Column(name = "TITLE", length = 255, nullable = true) + private String title; + + @Column(name = "TYPE", length = 255, nullable = false) + private String type; + + @Column(name = "VALUE", columnDefinition = "TEXT", nullable = true) + private String value; + + public enum LookUpDataTypeEnum { + CHECKLIST("CHECKLIST"), + AIMED_TO("AIMED_TO"), + EVALUATION_CRITERIA("EVALUATION_CRITERIA"); + + private String value; + + LookUpDataTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java new file mode 100644 index 00000000..46b88869 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/CallTypeEnum.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum CallTypeEnum { + + DRAFT("DRAFT"), + PUBLISH("PUBLISH"), + EXPIRE("EXPIRE"); + + private String value; + + CallTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java new file mode 100644 index 00000000..d5275796 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/enums/DocumentTypeEnum.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.enums; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum DocumentTypeEnum { + + DOCUMENT("DOCUMENT"), + IMAGES("IMAGES"); + + private String value; + + DocumentTypeEnum(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java b/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java new file mode 100644 index 00000000..80d828fc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/CreateCallRequest.java @@ -0,0 +1,49 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.CallTypeEnum; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class CreateCallRequest { + + private String name; + + private String descriptionShort; + + private String descriptionLong; + + private LocalDateTime startDate; + + private LocalDateTime endDate; + + private Long regionId; + + private BigDecimal amount; + + private BigDecimal amountMax; + + private List aimedTo; + + private String documentationRequested; + + private Integer threshold; + + private Boolean Confidi; + + List criteria; + + private List faq; + + private List checkList; + + private List docs; + + private List images; + + private CallTypeEnum status; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java new file mode 100644 index 00000000..a2f65bba --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/DocumentReq.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class DocumentReq { + + private Long id; + private String url; + private String fileName; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java new file mode 100644 index 00000000..a8b90e1c --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/EvaluationCriteriaReq.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class EvaluationCriteriaReq { + + private String name; + private String value; + private Integer score; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java new file mode 100644 index 00000000..de9f5225 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/FaqReq.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class FaqReq { + + private Boolean isVisible; + private String questionShort; + private String question; + private String responseShort; + private String response; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java new file mode 100644 index 00000000..18b847b4 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/request/LookUpDataReq.java @@ -0,0 +1,11 @@ +package net.gepafin.tendermanagement.model.request; + +import lombok.Data; + +@Data +public class LookUpDataReq { + + private Long lookUpDataId; + + private String value; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java new file mode 100644 index 00000000..0efff823 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CallResponseBean.java @@ -0,0 +1,42 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class CallResponseBean { + + + private Long id; + + private String title; + + private String description; + + private LocalDateTime startDate; + + private LocalDateTime endDate; + + private String status; + + private RegionResponseBean region; + + private BigDecimal fundingAmount; + + private String contactInfo; + + private String submissionMethod; + + private Integer totalScore; + + private Integer minimumScore; + + private String priorityArea; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java new file mode 100644 index 00000000..b913f85b --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/CreateCallResponseBean.java @@ -0,0 +1,60 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; +import net.gepafin.tendermanagement.enums.CallTypeEnum; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class CreateCallResponseBean { + + private Long id; + + private String name; + + private String descriptionShort; + + private String descriptionLong; + + private List dates; + + private CallTypeEnum status; + + private Long regionId; + + private BigDecimal amount; + + private BigDecimal amountMax; + + private String contactInfo; + + private String submissionMethod; + + private Integer threshold; + + private String priorityArea; + + private String documentationReqested; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + + private List aimedTo; + + private List criteria; + + private List docs; + + private List faq; + + private List images; + + private List checkList; + +} + + + diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java new file mode 100644 index 00000000..82aa9b9a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/DocumentResponseBean.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class DocumentResponseBean { + + private Long id; + + private String name; + + private String filePath; + + private String description; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java new file mode 100644 index 00000000..29cfed21 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/EvaluationCriteriaResponseBean.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class EvaluationCriteriaResponseBean { + + private Long id; + + private String name; + + private String description; + + private Integer score; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java new file mode 100644 index 00000000..fdc4be63 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/FaqResponseBean.java @@ -0,0 +1,30 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + + +import java.time.LocalDateTime; + +@Data +public class FaqResponseBean { + + private Long id; + + private Long userId; + + private Boolean isVisible; + + private String questionShort; + + private String question; + + private String responseShort; + + private String response; + + private LocalDateTime responseDate; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java b/src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java new file mode 100644 index 00000000..27811e63 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/LookUpDataResponse.java @@ -0,0 +1,22 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class LookUpDataResponse { + + private Long id; + + private Long lookUpDataId; + + private String title; + + private String value; + + private LocalDateTime createdDate; + + private LocalDateTime updatedDate; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java new file mode 100644 index 00000000..ef6e144f --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java @@ -0,0 +1,8 @@ +package net.gepafin.tendermanagement.repositories; +import net.gepafin.tendermanagement.entities.CallEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CallRepository extends JpaRepository { + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java new file mode 100644 index 00000000..fe70f982 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallTargetAudienceChecklistRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.CallTargetAudienceChecklistEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CallTargetAudienceChecklistRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java new file mode 100644 index 00000000..d8d4f07a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/DocumentRepository.java @@ -0,0 +1,9 @@ +package net.gepafin.tendermanagement.repositories; +import net.gepafin.tendermanagement.entities.DocumentEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DocumentRepository extends JpaRepository { + + DocumentEntity findById(Long id); +} + diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java new file mode 100644 index 00000000..057566a6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/EvaluationCriteriaRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.EvaluationCriteriaEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface EvaluationCriteriaRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java new file mode 100644 index 00000000..9453ade3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/FaqRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.FaqEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface FaqRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java new file mode 100644 index 00000000..e4ffb08a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/repositories/LookUpDataRepository.java @@ -0,0 +1,7 @@ +package net.gepafin.tendermanagement.repositories; + +import net.gepafin.tendermanagement.entities.LookUpDataEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface LookUpDataRepository extends JpaRepository { +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java new file mode 100644 index 00000000..188d131a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/AmazonS3Service.java @@ -0,0 +1,20 @@ +package net.gepafin.tendermanagement.service; + + +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; + +@Component +public interface AmazonS3Service { + + + public String upload(String fileName, + MultipartFile file) throws IOException; + + public Boolean delete(String bucketName ,String fileName); + + InputStream getFile(String filePath) throws IOException; +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/CallService.java b/src/main/java/net/gepafin/tendermanagement/service/CallService.java new file mode 100644 index 00000000..5f688af3 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/CallService.java @@ -0,0 +1,10 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; + +public interface CallService { + + CreateCallResponseBean createCall(CreateCallRequest createCallRequest); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java new file mode 100644 index 00000000..806d81cc --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/DocumentService.java @@ -0,0 +1,14 @@ +package net.gepafin.tendermanagement.service; + +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface DocumentService { + + public List uploadFile(List files, DocumentTypeEnum fileType); + + public Void deleteFile(Long documentId); +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java new file mode 100644 index 00000000..ad865d13 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AmazonS3ServiceImpl.java @@ -0,0 +1,91 @@ +package net.gepafin.tendermanagement.service.impl; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.*; +import net.gepafin.tendermanagement.service.AmazonS3Service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + + +@Service +public class AmazonS3ServiceImpl implements AmazonS3Service { + + @Autowired + private AmazonS3 amazonS3; + + @Autowired + private Environment environment; + + @Value("${aws.s3.bucket.name}") + private String bucketName; + + @Value("${aws.s3.url.folder}") + private String s3Folder; + + @Value("${aws.s3.url}") + private String s3Url; + + + @Override + public String upload(String fileName, + MultipartFile file) throws IOException { + + String path = bucketName+"/"+s3Folder; + + InputStream inputStream = file.getInputStream(); + + ObjectMetadata objectMetadata = new ObjectMetadata(); + Map metadata = new HashMap<>(); + metadata.put("Content-Type", file.getContentType()); + metadata.put("Content-Length", String.valueOf(file.getSize())); + + Optional> optionalMetaData = Optional.of(metadata); + optionalMetaData.ifPresent(map -> { + if (!map.isEmpty()) { + map.forEach(objectMetadata::addUserMetadata); + } + }); + + if(Boolean.FALSE.equals(isTestProfileActivated())) { + amazonS3.putObject(path, fileName, inputStream, objectMetadata); + } + return s3Url + s3Folder +"/"+ fileName; + } + + @Override + public Boolean delete(String bucketName,String fileName) { + + final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(bucketName, fileName); + if(Boolean.FALSE.equals(isTestProfileActivated())) { + amazonS3.deleteObject(deleteObjectRequest); + } + return true; + } + + public Boolean isTestProfileActivated() { + String[] activeProfiles = environment.getActiveProfiles(); + return Arrays.stream(activeProfiles).anyMatch("test"::equals); + } + + @Override + public InputStream getFile(String filePath) throws IOException { + try { + String path = bucketName+ s3Folder +"/"; + GetObjectRequest getObjectRequest = new GetObjectRequest(path, filePath); + S3Object s3Object = amazonS3.getObject(getObjectRequest); + return s3Object.getObjectContent(); + } catch (AmazonS3Exception e) { + throw new IOException("Error getting file from Amazon S3", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java new file mode 100644 index 00000000..7e59aff6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/CallServiceImpl.java @@ -0,0 +1,21 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.dao.CallDao; +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; +import net.gepafin.tendermanagement.service.CallService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +@Service +public class CallServiceImpl implements CallService { + + @Autowired + private CallDao callDao; + + @Override + public CreateCallResponseBean createCall(CreateCallRequest createCallRequest) { + return callDao.createCall(createCallRequest); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java new file mode 100644 index 00000000..e7bf864e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DocumentServiceImpl.java @@ -0,0 +1,28 @@ +package net.gepafin.tendermanagement.service.impl; + +import net.gepafin.tendermanagement.dao.DocumentDao; +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.service.DocumentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Service +public class DocumentServiceImpl implements DocumentService { + + + @Autowired + private DocumentDao fileDao; + + @Override + public List uploadFile(List files, DocumentTypeEnum fileType) { + return fileDao.uploadFiles(files,fileType); + } + @Override + public Void deleteFile(Long documentId){ + return fileDao.deleteFile(documentId); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java index aa1fe35b..ee81849b 100644 --- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java +++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java @@ -46,4 +46,17 @@ public class Utils { } return null; } + public static String extractFileName(String filePath) { + if (filePath == null || filePath.isEmpty()) { + return null; + } + int lastSlashIndex = filePath.lastIndexOf('/'); + + if (lastSlashIndex >= 0 && lastSlashIndex < filePath.length() - 1) { + return filePath.substring(lastSlashIndex + 1); + } else { + return filePath; + } + } + } diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java new file mode 100644 index 00000000..a6c9bfc0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/CallApi.java @@ -0,0 +1,36 @@ +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.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + + +public interface CallApi { + + @Operation(summary = "API to create call", + 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 = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> createCall( + @Parameter(description = "Call request object", required = true) + @Valid @RequestBody CreateCallRequest createCallRequest); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java new file mode 100644 index 00000000..4c3386c6 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DocumentApi.java @@ -0,0 +1,53 @@ +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.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.enums.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface DocumentApi { + + @Operation(summary = "Api to upload a file", + 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 = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + default ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, + @RequestParam("file") List files, + @RequestParam("documentType") DocumentTypeEnum documentTypeEnum) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } + @Operation(summary = "API to delete a file by document id", + responses = { + @ApiResponse(responseCode = "200", description = "File deleted successfully"), + @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 = "/deleteFile") + default ResponseEntity> deleteFile(HttpServletRequest httpServletRequest, + @RequestParam( "id") Long id) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java new file mode 100644 index 00000000..5e68ecbd --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/CallApiController.java @@ -0,0 +1,34 @@ +package net.gepafin.tendermanagement.web.rest.api.impl; + +import net.gepafin.tendermanagement.config.Translator; +import net.gepafin.tendermanagement.constants.GepafinConstant; +import net.gepafin.tendermanagement.model.request.CreateCallRequest; +import net.gepafin.tendermanagement.model.response.CreateCallResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.CallService; +import net.gepafin.tendermanagement.web.rest.api.CallApi; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/call}") +public class CallApiController implements CallApi { + + @Autowired + private CallService callService; + + + @Override + @Transactional(rollbackFor=Exception.class) + public ResponseEntity> createCall(CreateCallRequest createCallRequest) { + CreateCallResponseBean createCallResponseBean = callService.createCall(createCallRequest); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(createCallResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.CALL_CREATED_SUCCESSFULLY_MSG))); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..d4a151b0 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DocumentApiController.java @@ -0,0 +1,45 @@ +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.DocumentTypeEnum; +import net.gepafin.tendermanagement.model.response.DocumentResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.DocumentService; +import net.gepafin.tendermanagement.web.rest.api.DocumentApi; +import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; +import net.gepafin.tendermanagement.web.rest.api.errors.Status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequestMapping("${openapi.swaggerBflowsMiddleware.base-path:/v1/document}") +public class DocumentApiController implements DocumentApi { + + @Autowired + private DocumentService fileService; + + @Override + public ResponseEntity>> uploadFile(HttpServletRequest httpServletRequest, + List files, DocumentTypeEnum fileType) { + try { + List responseBeans=fileService.uploadFile(files,fileType); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response>(responseBeans, Status.SUCCESS, Translator.toLocale(GepafinConstant.FILES_UPLOADED_MSG))); + } catch (CustomValidationException ex) { + throw ex; + } + } + @Override + public ResponseEntity> deleteFile(HttpServletRequest httpServletRequest, Long documentId) { + fileService.deleteFile(documentId); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.FILE_DELETED_SUCCESSFULLY_MSG))); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f72dc2c4..b4351d76 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -24,3 +24,12 @@ spring.liquibase.enabled=true # Swagger Configuration springdoc.api-docs.path=/v1/api-docs + +#aws configuration +aws.access.key.id=AKIAVWDQWCUEOSUN4LUW +aws.secret.access.key=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 +aws.s3.region=eu-west-1 +aws.s3.bucket.name=mementoresources +aws.s3.url = https://mementoresources.s3.eu-west-1.amazonaws.com/ +aws.s3.url.folder=gepafin + 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 20506096..9877f940 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 @@ -134,4 +134,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index bdbcf92b..540a6b3e 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -27,3 +27,17 @@ create.regiom.error=Error occurred while creating the region. update.region.error=Error occurred while updating the region. password.doesnt.match=Password and confirm password do not match. +#call related messages +user.not.exist=User does not exist. +region.not.found=Region not found. +user.id.not.null=User ID cannot be null. +question.not.empty=Question cannot be empty. +name.not.empty=Name cannot be empty. +type.not.empty=Type cannot be empty. +region.not.null=Region ID cannot be null. +amount.greater.than.zero=Amount must be greater than zero. +look.up.data.not.valid=Look up data entity is not valid. +files.uploaded=Files uploaded successfully. +call.created.successfully=Call created successfully. +file.deleted.successfully=File deleted successfully. +document.not.found=Document not found. diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index bfd0d8f3..b6cf8f79 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -26,3 +26,18 @@ user.region.not.found=Regione non trovata. create.regiom.error=Errore durante la creazione della regione. update.region.error=Errore durante l'aggiornamento della regione. password.doesnt.match=La password e la conferma della password non corrispondono. + +#call related messages +user.not.exist=L'utente non esiste. +region.not.found=Regione non trovata. +user.id.not.null=L'ID utente non può essere nullo. +question.not.empty=La domanda non può essere vuota. +name.not.empty=Il nome non può essere vuoto. +type.not.empty=Il tipo non può essere vuoto. +region.not.null=L'ID regione non può essere nullo. +amount.greater.than.zero=L'importo del finanziamento deve essere maggiore di zero. +look.up.data.not.valid=L'entità dati di ricerca non è valida. +files.uploaded=File caricati correttamente. +call.created.successfully=Chiamata creata correttamente. +file.deleted.successfully=File eliminato con successo. +document.not.found=Documento non trovato. \ No newline at end of file