package net.gepafin.tendermanagement.dao; import jakarta.servlet.http.HttpServletRequest; import net.gepafin.tendermanagement.config.Translator; import net.gepafin.tendermanagement.constants.GepafinConstant; import net.gepafin.tendermanagement.entities.CompanyEntity; import net.gepafin.tendermanagement.entities.UserEntity; import net.gepafin.tendermanagement.entities.UserWithCompanyEntity; import net.gepafin.tendermanagement.entities.*; import net.gepafin.tendermanagement.enums.*; import net.gepafin.tendermanagement.model.response.*; import net.gepafin.tendermanagement.repositories.*; import net.gepafin.tendermanagement.service.CompanyService; import net.gepafin.tendermanagement.util.Validator; import net.gepafin.tendermanagement.web.rest.api.errors.CustomValidationException; import net.gepafin.tendermanagement.web.rest.api.errors.ForbiddenAccessException; import net.gepafin.tendermanagement.web.rest.api.errors.Status; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Component public class DashboardDao { @Autowired private CallRepository callRepository; @Autowired private UserRepository userRepository; @Autowired private ApplicationRepository applicationRepository; @Autowired private CompanyRepository companyRepository; @Autowired private CompanyService companyService; @Autowired private BeneficiaryPreferredCallRepository beneficiaryPreferredCallRepository; @Autowired private ApplicationEvaluationRepository applicationEvaluationRepository; @Autowired private ApplicationAmendmentRequestRepository applicationAmendmentRequestRepository; @Autowired private AssignedApplicationsRepository assignedApplicationsRepository; @Autowired private Validator validator; public SuperAdminWidgetResponseBean getDashboardWidget(UserEntity requestedUserEntity) { SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean(); widgetResponseBean.setWidget1(createWidget1(requestedUserEntity)); Map widgetBars =getStatistics(requestedUserEntity); widgetResponseBean.setWidgetBars(widgetBars); return widgetResponseBean; } private Widget1 createWidget1(UserEntity requestedUserEntity) { Widget1 widget1 = initializeWidget1(); setActiveCalls(widget1, requestedUserEntity); setRegisteredUsers(widget1, requestedUserEntity); setTotalActiveFinancing(widget1, requestedUserEntity); setSubmittedApplications(widget1, requestedUserEntity); setDraftApplications(widget1, requestedUserEntity); setNumberOfCompanies(widget1, requestedUserEntity); setAmountRequested(widget1,requestedUserEntity); setAmountAccepted(widget1,requestedUserEntity); return widget1; } private Widget1 initializeWidget1() { return Widget1.builder().numberOfActiveCalls(0L).numberOfCompany(0L).numberOfDraftApplications(0L) .numberOfResgisteredUsers(0L).numberOfSubmittedApplications(0L).totalActiveFinancing(BigDecimal.ZERO) .build(); } private void setActiveCalls(Widget1 widget1, UserEntity requestedUserEntity) { Long activeCalls = callRepository.countByStatusAndHubId(CallStatusEnum.PUBLISH.getValue(), requestedUserEntity.getHub().getId()); if (activeCalls != null) { widget1.setNumberOfActiveCalls(activeCalls); } } private void setAmountRequested(Widget1 widget1, UserEntity requestedUserEntity) { BigDecimal amountRequested = applicationRepository.findTotalAmountRequestedOfApplication(requestedUserEntity.getHub().getId()); if (amountRequested != null) { widget1.setTotalAmountRequested(amountRequested); } } private void setAmountAccepted(Widget1 widget1, UserEntity requestedUserEntity) { BigDecimal amountAccepted = applicationRepository.findTotalAmountAcceptedOfApplication(requestedUserEntity.getHub().getId()); if (amountAccepted != null) { widget1.setTotalAmountAccepted(amountAccepted); } } private void setRegisteredUsers(Widget1 widget1, UserEntity requestedUserEntity) { Long activeUsers = userRepository.countByStatusAndRoleEntityRoleTypeAndHubId(UserStatusEnum.ACTIVE.getValue(), RoleStatusEnum.ROLE_BENEFICIARY.getValue(), requestedUserEntity.getHub().getId()); if (activeUsers != null) { widget1.setNumberOfResgisteredUsers(activeUsers); } } private void setTotalActiveFinancing(Widget1 widget1, UserEntity requestedUser) { BigDecimal totalActiveFinancing = callRepository.findTotalAmountOfPublishedCallsAndHubId(requestedUser.getHub().getId()); widget1.setTotalActiveFinancing(totalActiveFinancing); } private void setSubmittedApplications(Widget1 widget1, UserEntity requestedUserEntity) { Long submittedApplications = applicationRepository.countSubmittedApplicationsByHubId(requestedUserEntity.getHub().getId()); if (submittedApplications != null) { widget1.setNumberOfSubmittedApplications(submittedApplications); } } private void setDraftApplications(Widget1 widget1, UserEntity requestedUserEntity) { Long draftApplications = applicationRepository.countDraftApplicationsByHubId(requestedUserEntity.getHub().getId()); if (draftApplications != null) { widget1.setNumberOfDraftApplications(draftApplications); } } private void setNumberOfCompanies(Widget1 widget1, UserEntity requestedUserEntity) { Long numberOfCompanies = companyRepository.countTotalCompaniesByHubId(requestedUserEntity.getHub().getId()); if (numberOfCompanies != null) { widget1.setNumberOfCompany(numberOfCompanies); } } public BeneficiaryWidgetResponseBean getDashboardWidgetForBeneficiary(UserEntity userEntity, CompanyEntity company) { BeneficiaryWidgetResponseBean beneficiaryWidgetResponseBean = BeneficiaryWidgetResponseBean.builder() .numberOfApplications(0L).numberOfCalls(0L).numberOfIntegratedDocuments(0L).build(); UserWithCompanyEntity userWithCompanyEntity = companyService.getUserWithCompany(userEntity.getId(), company.getId()); List preferredCalls = beneficiaryPreferredCallRepository .findByUserIdAndUserWithCompanyIdAndIsDeletedFalse(userEntity.getId(), userWithCompanyEntity.getId()); if (preferredCalls != null && !preferredCalls.isEmpty()) { List callIds = preferredCalls.stream() .map(BeneficiaryPreferredCallEntity::getCallId) .collect(Collectors.toList()); List callEntities = callRepository.findByIdIn(callIds); long activeCallsCount = callEntities.stream() .filter(call -> CallStatusEnum.PUBLISH.getValue().equals(call.getStatus()) && userEntity.getHub().getId().equals(call.getHub().getId())) .count(); beneficiaryWidgetResponseBean.setNumberOfCalls(activeCallsCount); } Long activeApplication = applicationRepository.countSubmittedApplicationsByUserId(userEntity.getId(), userWithCompanyEntity.getId()); if (activeApplication != null) { beneficiaryWidgetResponseBean.setNumberOfApplications(activeApplication); } return beneficiaryWidgetResponseBean; } public Map getStatistics(UserEntity requestedUser) { Map stats = new HashMap<>(); // Get applications per call List applicationsPerCall = applicationRepository.findApplicationsPerCallWithName(requestedUser.getHub().getId()); stats.put(GepafinConstant.APPLICATION_PER_CALL, applicationsPerCall.stream().map(result -> { Map callData = new HashMap<>(); callData.put(GepafinConstant.CALL_NAME, result[0]); // Call name callData.put(GepafinConstant.NUMBER_OF_APPLICATIONS, result[1]);// Application count callData.put(GepafinConstant.NUMBER_OF_DRAFT_APPLICATIONS, result[2]);// Application count return callData; }).toList()); // Get applications grouped by status List applicationsByStatus = applicationRepository.findApplicationsByStatus(requestedUser.getHub().getId()); stats.put(GepafinConstant.APPLICATION_PER_STATUS, applicationsByStatus.stream().map(result -> { Map statusData = new HashMap<>(); statusData.put(GepafinConstant.STATUS, result[0]); // Application status statusData.put(GepafinConstant.NUMBER_OF_APPLICATIONS, result[1]); // Count of applications return statusData; }).toList()); return stats; } // public Page getUserAction(UserEntity requestedUserEntity){ // Pageable pageable = PageRequest.of(0, 20); // Get the first 20 records // List roles=List.of(RoleStatusEnum.ROLE_PRE_INSTRUCTOR.getValue(),RoleStatusEnum.ROLE_GEPAFIN_OPERATOR.getValue(),RoleStatusEnum.ROLE_INSTRUCTOR_MANAGER.getValue()); // Page userActionEntities=userActionsRepository.findActionsByRoleNamesAndHubId(roles,requestedUserEntity.getHub().getId(),pageable); // return userActionEntities; // } public ApplicationWidgetResponseBean getApplicationDetails(UserEntity userEntity) { ApplicationWidgetResponseBean applicationWidgetResponseBean = initializeResponseBean(); Long hubId = userEntity.getHub().getId(); setApplicationCounts(applicationWidgetResponseBean, hubId); calculateEvaluationAverageTime(applicationWidgetResponseBean, hubId); return applicationWidgetResponseBean; } private ApplicationWidgetResponseBean initializeResponseBean() { return ApplicationWidgetResponseBean.builder() .numberOfApplication(0L) .numberOfAssignedApplication(0L) .numberOfAcceptedApplication(0L) .numberOfApplicationInAmendmentState(0L) .numberOfDueApplication(0L) .evaluationAverageTime(BigDecimal.ZERO) .build(); } private void setApplicationCounts(ApplicationWidgetResponseBean responseBean, Long hubId) { Long activeApplications = applicationRepository.countApplicationsByHubId(hubId); if (activeApplications != null) { responseBean.setNumberOfApplication(activeApplications); } Long assignedApplications = applicationRepository.countAssignedApplicationsByHubId(hubId); if (assignedApplications != null) { responseBean.setNumberOfAssignedApplication(assignedApplications); } Long approvedApplications = applicationRepository.countApprovedApplicationsByHubId(hubId); if (approvedApplications != null) { responseBean.setNumberOfAcceptedApplication(approvedApplications); } Long soccorsoApplications = applicationRepository.countSoccorsoApplicationsByHubId(hubId); if (soccorsoApplications != null) { responseBean.setNumberOfApplicationInAmendmentState(soccorsoApplications); } } private void calculateEvaluationAverageTime(ApplicationWidgetResponseBean responseBean, Long hubId) { List applicationIds = applicationRepository.findApplicationIdsByHubId(hubId); if (Boolean.FALSE.equals(applicationIds.isEmpty())) { BigDecimal averageTime = applicationEvaluationRepository.findAverageEvaluationTimeByApplicationIds(applicationIds); responseBean.setEvaluationAverageTime(averageTime != null ? averageTime.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO); } LocalDate twoDaysLater = LocalDate.now().plusDays(2); List statusList =Arrays.asList( ApplicationEvaluationStatusTypeEnum.OPEN.getValue(), ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue()); Long dueApplications = applicationEvaluationRepository.countDueApplicationsBetween( applicationIds, LocalDate.now(), twoDaysLater, statusList ); if (dueApplications != null) { responseBean.setNumberOfDueApplication(dueApplications); } } private AmendmentWidgetResponseBean initializeAmendmentResponseBean() { return AmendmentWidgetResponseBean.builder() .totalAmendments(0L) .waitingForResponseAmendments(0L) .responseReceivedAmendments(0L) .averageResponseDays(BigDecimal.ZERO) .expiringRequestsIn48Hours(0L) .expiredAmendments(0L) .build(); } public AmendmentWidgetResponseBean getAmendmentDetails(UserEntity userEntity) { AmendmentWidgetResponseBean amendmentWidgetResponseBean = initializeAmendmentResponseBean(); Long hubId = userEntity.getHub().getId(); List applicationIds = getApplicationIdsForUserOrHub(userEntity,hubId,null); setAmendmentCounts(applicationIds,amendmentWidgetResponseBean, hubId); calculateExpiringRequestsIn48Hours(applicationIds,amendmentWidgetResponseBean, hubId); calculateAverageResponseDays(applicationIds,amendmentWidgetResponseBean,hubId); return amendmentWidgetResponseBean; } public List getApplicationIdsForUserOrHub(UserEntity userEntity, Long hubId , Long userId) { if (userId != null) { return assignedApplicationsRepository.findApplicationIdsByUserIdAndIsDeletedFalse(userId); } else if (validator.checkIsPreInstructor()) { return assignedApplicationsRepository.findApplicationIdsByUserIdAndIsDeletedFalse(userEntity.getId()); } else { return applicationRepository.findApplicationIdsByHubId(hubId); } } private void setAmendmentCounts(List applicationIds,AmendmentWidgetResponseBean responseBean, Long hubId) { Long totalAmendment = applicationAmendmentRequestRepository.countAmendmentsByApplicationIds(applicationIds); if (totalAmendment != null) { responseBean.setTotalAmendments(totalAmendment); } Long awaitingAmendments = applicationAmendmentRequestRepository.countAmendmentsByApplicationIdsAndStatus( applicationIds, ApplicationAmendmentRequestEnum.AWAITING.getValue()); if (awaitingAmendments != null) { responseBean.setWaitingForResponseAmendments(awaitingAmendments); } Long responseRecievedAmendments = applicationAmendmentRequestRepository.countAmendmentsByApplicationIdsAndStatus( applicationIds, ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue()); if (responseRecievedAmendments != null) { responseBean.setResponseReceivedAmendments(responseRecievedAmendments); } Long expiredAmendments = applicationAmendmentRequestRepository.countAmendmentsByApplicationIdsAndStatus( applicationIds, ApplicationAmendmentRequestEnum.EXPIRED.getValue()); if (expiredAmendments != null) { responseBean.setExpiredAmendments(expiredAmendments); } } private void calculateExpiringRequestsIn48Hours(List applicationIds ,AmendmentWidgetResponseBean responseBean, Long hubId) { // Define the statuses to filter List statuses = List.of( ApplicationAmendmentRequestEnum.AWAITING.getValue(), ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue() ); LocalDateTime twoDaysLater = LocalDateTime.now().plusDays(2); Long expiringRequestsIn48Hours = applicationAmendmentRequestRepository.countExpiringRequestsIn48Hours( applicationIds, statuses, LocalDateTime.now(), twoDaysLater ); if (expiringRequestsIn48Hours != null) { responseBean.setExpiringRequestsIn48Hours(expiringRequestsIn48Hours); } } private void calculateAverageResponseDays(List applicationIds ,AmendmentWidgetResponseBean responseBean, Long hubId) { if (!applicationIds.isEmpty()) { BigDecimal averageResponseDays = applicationAmendmentRequestRepository .findAverageResponseDaysByApplicationIdsAndStatus( applicationIds, ApplicationAmendmentRequestEnum.CLOSE.getValue() ); responseBean.setAverageResponseDays(averageResponseDays); } else { responseBean.setAverageResponseDays(BigDecimal.ZERO); } } public AssignedApplicationWidgetResponseBean getApplicationDetailsForEvaluation(UserEntity userEntity) { Long userId = userEntity.getId(); Long hubId = userEntity.getHub().getId(); Object[] results; List applicationIds; if (validator.checkIsPreInstructor()) { results = assignedApplicationsRepository.countAssignedApplicationsWithStatus(userId, hubId); applicationIds = assignedApplicationsRepository.findApplicationIdsByUserIdAndHubIdAndIsDeletedFalse(userId,hubId); } else { results = assignedApplicationsRepository.countAssignedApplicationsForHub(hubId); applicationIds = assignedApplicationsRepository.findApplicationIdsByHubId(hubId); } AssignedApplicationWidgetResponseBean response = convertToResponse(results); calculateEvaluationAvgTimeForAssignedApplication(response, applicationIds); return response; } private void calculateEvaluationAvgTimeForAssignedApplication(AssignedApplicationWidgetResponseBean response, List applicationIds) { if (applicationIds == null || applicationIds.isEmpty()) { response.setAverageEvaluationDays(BigDecimal.ZERO); response.setNumberOfApplicationExpiringIn48Hours(0L); return; } BigDecimal averageTime = applicationEvaluationRepository.findAverageEvaluationTimeByApplicationIds(applicationIds); response.setAverageEvaluationDays(averageTime != null ? averageTime.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO); LocalDate today = LocalDate.now(); LocalDate twoDaysLater = today.plusDays(2); List statusList =Arrays.asList( ApplicationEvaluationStatusTypeEnum.OPEN.getValue(), ApplicationEvaluationStatusTypeEnum.SOCCORSO.getValue()); Long dueApplications = applicationEvaluationRepository.countDueApplicationsBetween( applicationIds, today, twoDaysLater,statusList ); response.setNumberOfApplicationExpiringIn48Hours(dueApplications != null ? dueApplications : 0L); } private AssignedApplicationWidgetResponseBean convertToResponse(Object[] results) { AssignedApplicationWidgetResponseBean response = new AssignedApplicationWidgetResponseBean(); Object[] data = (Object[]) results[0]; response.setNumberOfAssignedApplication(data[0] instanceof Number ? ((Number) data[0]).longValue() : 0L); response.setNumberOfApplicationInAmendmentState(data[1] instanceof Number ? ((Number) data[1]).longValue() : 0L); response.setNumberOfApplicationInOpenState(data[2] instanceof Number ? ((Number) data[2]).longValue() : 0L); response.setNumberOfApplicationInCloseState(data[3] instanceof Number ? ((Number) data[3]).longValue() : 0L); return response; } private PreInstructorWidgetResponseBean initializeDashboardPreInstructorResponseBean() { return PreInstructorWidgetResponseBean.builder() .assignedApplication(ApplicationToConsider.builder() .totalAssignedApplication(0L) .additionalApplicationPercentage(BigDecimal.ZERO) .build()) .evaluatedApplication(EvaluatedApplication.builder() .evaluatedApplication(0L) .dailyAverage(BigDecimal.ZERO) .build()) .averageEvaluationDays(AverageEvaluationTime.builder() .averageEvlauationDaysRating(BigDecimal.ZERO) .timeDifferenceFromAverage(BigDecimal.ZERO) .build()) .amendmentInProgress(RescueInstructorInProgress.builder() .totalAmendmentInProgress(0L) .expiringToday(0L) .build()) .build(); } public PreInstructorWidgetResponseBean getDashboardWidgetForPreInstructor(HttpServletRequest request, Long userId) { UserEntity userEntity = validator.validateUser(request); if (validator.checkIsPreInstructor() && userId == null) { throw new CustomValidationException(Status.BAD_REQUEST, Translator.toLocale(GepafinConstant.USER_ID_NOT_NULL_MSG)); } if (userId != null) { validator.validatePreInstructor(request, userId); if (validator.checkIsInstructorManager() && !userEntity.getId().equals(userId)) { throw new ForbiddenAccessException(Status.FORBIDDEN, Translator.toLocale(GepafinConstant.PERMISSION_DENIED)); } } PreInstructorWidgetResponseBean preInstructorWidgetResponseBean = initializeDashboardPreInstructorResponseBean(); Long hubId = userEntity.getHub().getId(); List applicationIds = getApplicationIdsForUserOrHub(userEntity, hubId,userId); setPreInstructorWidgets(applicationIds, preInstructorWidgetResponseBean,hubId); calculateAverageEvaluationTime(applicationIds, preInstructorWidgetResponseBean, hubId); return preInstructorWidgetResponseBean; } private void setPreInstructorWidgets(List applicationIds, PreInstructorWidgetResponseBean responseBean,Long hubId) { List assignedApplicationStatus = Arrays.asList(AssignedApplicationEnum.AWAITING.getValue(), AssignedApplicationEnum.OPEN.getValue()); Long totalAssignedApplications = assignedApplicationsRepository.countAssignedApplicationsByApplicationIds(applicationIds,assignedApplicationStatus); if (totalAssignedApplications != null) { responseBean.getAssignedApplication().setTotalAssignedApplication(totalAssignedApplications); } LocalDateTime yesterday = LocalDateTime.now().minusDays(1); Long newApplicationsAddedYesterday = assignedApplicationsRepository.countApplicationsAddedYesterdayForHub(applicationIds, hubId, yesterday,assignedApplicationStatus); if (newApplicationsAddedYesterday != null && totalAssignedApplications != null && totalAssignedApplications > 0) { BigDecimal percentageAdded = BigDecimal.valueOf(newApplicationsAddedYesterday) .divide(BigDecimal.valueOf(totalAssignedApplications), 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); responseBean.getAssignedApplication().setAdditionalApplicationPercentage(percentageAdded.setScale(2, RoundingMode.HALF_UP)); } List statuses = Arrays.asList(ApplicationStatusTypeEnum.APPROVED.getValue(), ApplicationStatusTypeEnum.REJECTED.getValue()); LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7); Long evaluatedApplication = assignedApplicationsRepository.countEvaluatedApplicationsInLast7Days(applicationIds, statuses, sevenDaysAgo); if (evaluatedApplication != null) { responseBean.getEvaluatedApplication().setEvaluatedApplication(evaluatedApplication); BigDecimal dailyAverage = assignedApplicationsRepository.countDailyAverageEvaluatedApplicationsInLast7Days(applicationIds, statuses, sevenDaysAgo); if (dailyAverage != null) { responseBean.getEvaluatedApplication().setDailyAverage(dailyAverage.setScale(2, RoundingMode.HALF_UP)); // Rounded to 2 decimal places } } List amendmentStatus =Arrays.asList( ApplicationAmendmentRequestEnum.AWAITING.getValue(), ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue()); Long rescueInstructorsInProgress = applicationAmendmentRequestRepository.countAmendmentsByApplicationIds(applicationIds,amendmentStatus); if (rescueInstructorsInProgress != null) { responseBean.getAmendmentInProgress().setTotalAmendmentInProgress(rescueInstructorsInProgress); } calculateExpiringRescueInstructorsToday(applicationIds,responseBean); } private void calculateExpiringRescueInstructorsToday(List applicationIds, PreInstructorWidgetResponseBean responseBean) { List statuses =Arrays.asList( ApplicationAmendmentRequestEnum.AWAITING.getValue(), ApplicationAmendmentRequestEnum.RESPONSE_RECEIVED.getValue()); LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay(); LocalDateTime endOfDay = startOfDay.plusDays(1).minusNanos(1); Long expiringToday = applicationAmendmentRequestRepository.countAmendmentsExpiringToday(applicationIds, statuses, startOfDay, endOfDay); if (expiringToday != null) { responseBean.getAmendmentInProgress().setExpiringToday(expiringToday); } } private void calculateAverageEvaluationTime(List applicationIds, PreInstructorWidgetResponseBean responseBean, Long hubId) { if (Boolean.FALSE.equals(applicationIds.isEmpty())) { BigDecimal averageTime = applicationEvaluationRepository.findAverageEvaluationTimeByApplicationIds(applicationIds); responseBean.getAverageEvaluationDays().setAverageEvlauationDaysRating( averageTime != null ? averageTime.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) ); // // BigDecimal timeDifference = applicationEvaluationRepository.findTimeDifferenceFromAverage(applicationIds); // responseBean.getAverageEvaluationTime().setTimeDifferenceFromAverage(timeDifference != null ? timeDifference : BigDecimal.ZERO); } } }