diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java index 59b24f67..bcd97a17 100644 --- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java +++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java @@ -211,5 +211,8 @@ public class GepafinConstant { public static final String APPLICATION_SIGNED_DOCUMENT_NOT_FOUND = "application.signed.document.not.found"; public static final String DELETE_SIGNED_DOCUMENT_FILE_SUCCESS = "delete.signed.document.file.success"; public static final String DD_MM_YYYY = "dd/MM/yyyy"; + + public static final String DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY="dashboard.widget.fetched.successfully"; + } diff --git a/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java new file mode 100644 index 00000000..0f917535 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/dao/DashboardDao.java @@ -0,0 +1,118 @@ +package net.gepafin.tendermanagement.dao; + +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.enums.CallStatusEnum; +import net.gepafin.tendermanagement.enums.RoleStatusEnum; +import net.gepafin.tendermanagement.enums.UserStatusEnum; +import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; +import net.gepafin.tendermanagement.model.response.Widget1; +import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; +import net.gepafin.tendermanagement.repositories.ApplicationRepository; +import net.gepafin.tendermanagement.repositories.CallRepository; +import net.gepafin.tendermanagement.repositories.CompanyRepository; +import net.gepafin.tendermanagement.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; + +@Component +public class DashboardDao { + + @Autowired + private CallRepository callRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ApplicationRepository applicationRepository; + + @Autowired + private CompanyRepository companyRepository; + + public SuperAdminWidgetResponseBean getDashboardWidget() { + SuperAdminWidgetResponseBean widgetResponseBean = new SuperAdminWidgetResponseBean(); + widgetResponseBean.setWidget1(createWidget1()); +// List widgetBars = callRepository.findApplicationsPerCall(); +// widgetResponseBean.setWidgetBars(widgetBars); + return widgetResponseBean; + } + + private Widget1 createWidget1() { + Widget1 widget1 = initializeWidget1(); + + setActiveCalls(widget1); + setRegisteredUsers(widget1); + setTotalActiveFinancing(widget1); + setSubmittedApplications(widget1); + setDraftApplications(widget1); + setNumberOfCompanies(widget1); + + 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) { + Long activeCalls = callRepository.countByStatus(CallStatusEnum.PUBLISH.getValue()); + if (activeCalls != null) { + widget1.setNumberOfActiveCalls(activeCalls); + } + } + + private void setRegisteredUsers(Widget1 widget1) { + Long activeUsers = userRepository.countByStatusAndRoleEntity_RoleType(UserStatusEnum.ACTIVE.getValue(), + RoleStatusEnum.ROLE_BENEFICIARY.getValue()); + if (activeUsers != null) { + widget1.setNumberOfResgisteredUsers(activeUsers); + } + } + + private void setTotalActiveFinancing(Widget1 widget1) { + BigDecimal totalActiveFinancing = callRepository.findTotalAmountOfPublishedCalls(); + widget1.setTotalActiveFinancing(totalActiveFinancing); + } + + private void setSubmittedApplications(Widget1 widget1) { + Long submittedApplications = applicationRepository.countSubmittedApplications(); + if (submittedApplications != null) { + widget1.setNumberOfSubmittedApplications(submittedApplications); + } + } + + private void setDraftApplications(Widget1 widget1) { + Long draftApplications = applicationRepository.countDraftApplications(); + if (draftApplications != null) { + widget1.setNumberOfDraftApplications(draftApplications); + } + } + + private void setNumberOfCompanies(Widget1 widget1) { + Long numberOfCompanies = companyRepository.countTotalCompanies(); + if (numberOfCompanies != null) { + widget1.setNumberOfCompany(numberOfCompanies); + } + } + + public BeneficiaryWidgetResponseBean getDashboardWidgetForBeneficiary(UserEntity userEntity, + CompanyEntity company) { + BeneficiaryWidgetResponseBean beneficiaryWidgetResponseBean = BeneficiaryWidgetResponseBean.builder() + .numberOfApplications(0L).numberOfCalls(0L).numberOfIntegratedDocuments(0L).build(); + Long activeCalls = callRepository.countByStatus(CallStatusEnum.PUBLISH.getValue()); + if (activeCalls != null) { + beneficiaryWidgetResponseBean.setNumberOfCalls(activeCalls); + } + Long activeApplication = applicationRepository.countSubmittedApplicationsByUserId(userEntity.getId(), + company.getId()); + if (activeApplication != null) { + beneficiaryWidgetResponseBean.setNumberOfApplications(activeApplication); + } + return beneficiaryWidgetResponseBean; + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryWidgetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryWidgetResponseBean.java new file mode 100644 index 00000000..04eb2d8a --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/BeneficiaryWidgetResponseBean.java @@ -0,0 +1,17 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class BeneficiaryWidgetResponseBean { + + private Long numberOfApplications; + + private Long numberOfCalls; + + private Long numberOfIntegratedDocuments; + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java new file mode 100644 index 00000000..6ed30e56 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/SuperAdminWidgetResponseBean.java @@ -0,0 +1,14 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Data; + +import java.util.List; + +@Data +public class SuperAdminWidgetResponseBean { + + private Widget1 widget1; + +// private List widgetBars; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java b/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java new file mode 100644 index 00000000..75c68758 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/model/response/Widget1.java @@ -0,0 +1,26 @@ +package net.gepafin.tendermanagement.model.response; + +import lombok.Builder; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@Builder +public class Widget1 { + + private Long numberOfActiveCalls; + + private Long numberOfResgisteredUsers; + +// private Long preInvestigationQuestions; + + private Long numberOfSubmittedApplications; + + private Long numberOfDraftApplications; + + private Long numberOfCompany; + + private BigDecimal totalActiveFinancing; + +} diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java index a1c3a474..b2329b9c 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/ApplicationRepository.java @@ -29,4 +29,15 @@ public interface ApplicationRepository extends JpaRepository findByIdAndUserIdAndCallIdAndIsDeletedFalse(Long applicationId, Long userId, Long callId); + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.userId = :userId AND a.company.id = :companyId AND a.status = 'SUBMIT' ") + Long countSubmittedApplicationsByUserId(@Param("userId") Long userId, @Param("companyId") Long companyId); + + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'SUBMIT'") + Long countSubmittedApplications(); + + @Query("SELECT COUNT(a) FROM ApplicationEntity a WHERE a.status = 'DRAFT'") + Long countDraftApplications(); + + + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java index 6fa6bbde..4e651fe0 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CallRepository.java @@ -2,8 +2,10 @@ package net.gepafin.tendermanagement.repositories; import net.gepafin.tendermanagement.entities.CallEntity; import net.gepafin.tendermanagement.enums.CallStatusEnum; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.math.BigDecimal; import java.util.List; @Repository @@ -13,4 +15,14 @@ public interface CallRepository extends JpaRepository { List findByStatusIn(List callStatus); public CallEntity findByIdAndStatus(Long id,String status); + + public Long countByStatus(String status); + + @Query("SELECT COALESCE(SUM(c.amount), 0) FROM CallEntity c WHERE c.status = 'PUBLISH'") + BigDecimal findTotalAmountOfPublishedCalls(); + + @Query("SELECT c.name, COUNT(a.id) " + + "FROM CallEntity c LEFT JOIN ApplicationEntity a ON c.id = a.call.id " + + "GROUP BY c.name") + List findApplicationsPerCall(); } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java index 9206826f..c0c5f75d 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/CompanyRepository.java @@ -3,6 +3,7 @@ package net.gepafin.tendermanagement.repositories; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import net.gepafin.tendermanagement.entities.CompanyEntity; @@ -15,4 +16,8 @@ public interface CompanyRepository extends JpaRepository { Boolean existsByVatNumber(String vatNumber); CompanyEntity findByVatNumber(String vatNumber); + @Query("SELECT COUNT(c) FROM CompanyEntity c") + long countTotalCompanies(); + + } diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java index 829cd7ef..98e46b46 100644 --- a/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java +++ b/src/main/java/net/gepafin/tendermanagement/repositories/UserRepository.java @@ -18,4 +18,7 @@ public interface UserRepository extends JpaRepository { Optional findByBeneficiaryCodiceFiscale(String codiceFiscale); boolean existsByBeneficiaryCodiceFiscale(String codiceFiscale); + + Long countByStatusAndRoleEntity_RoleType(String status, String roleName); + } diff --git a/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java b/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java new file mode 100644 index 00000000..6328ca6e --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/DashboardService.java @@ -0,0 +1,13 @@ +package net.gepafin.tendermanagement.service; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; +import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; + +public interface DashboardService { + + public SuperAdminWidgetResponseBean getDashboardWidgetForSuperAdmin(HttpServletRequest request); + + public BeneficiaryWidgetResponseBean getDashboardWidgetForBeneficiary(HttpServletRequest request, Long companyId); + +} diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java new file mode 100644 index 00000000..d0bd0217 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/service/impl/DashboardServiceImpl.java @@ -0,0 +1,34 @@ +package net.gepafin.tendermanagement.service.impl; + +import jakarta.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.dao.DashboardDao; +import net.gepafin.tendermanagement.entities.CompanyEntity; +import net.gepafin.tendermanagement.entities.UserEntity; +import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; +import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; +import net.gepafin.tendermanagement.service.DashboardService; +import net.gepafin.tendermanagement.util.Validator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DashboardServiceImpl implements DashboardService { + + @Autowired + private DashboardDao dashboardDao; + + @Autowired + private Validator validator; + + @Override + public SuperAdminWidgetResponseBean getDashboardWidgetForSuperAdmin(HttpServletRequest request) { + return dashboardDao.getDashboardWidget(); + } + + @Override + public BeneficiaryWidgetResponseBean getDashboardWidgetForBeneficiary(HttpServletRequest request, Long companyId) { + UserEntity userEntity=validator.validateUser(request); + CompanyEntity company = validator.validateUserWithCompany(request, companyId); + return dashboardDao.getDashboardWidgetForBeneficiary(userEntity, company); + } +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java new file mode 100644 index 00000000..bcb79d61 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/DashboardApi.java @@ -0,0 +1,51 @@ +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.servlet.http.HttpServletRequest; +import net.gepafin.tendermanagement.model.response.BeneficiaryWidgetResponseBean; +import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; +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.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +public interface DashboardApi { + + @Operation(summary = "Api to get dashboard widget for super admin", + 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" }) + @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')") + ResponseEntity> getDashboardWidgetForSuperAdmin(HttpServletRequest request); + + @Operation(summary = "Api to get dashboard widget for beneficiary", + 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 = "/beneficiary/company/{companyId}", + produces = { "application/json" }) + ResponseEntity> getDashboardWidgetForBeneficiary(HttpServletRequest request, + @Parameter(description = "The company id", required = true) @PathVariable(value = "companyId", required = true) Long companyId); + + + +} diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java new file mode 100644 index 00000000..c46258a2 --- /dev/null +++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/DashboardApiController.java @@ -0,0 +1,38 @@ +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.model.response.BeneficiaryWidgetResponseBean; +import net.gepafin.tendermanagement.model.response.SuperAdminWidgetResponseBean; +import net.gepafin.tendermanagement.model.util.Response; +import net.gepafin.tendermanagement.service.DashboardService; +import net.gepafin.tendermanagement.web.rest.api.DashboardApi; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("${openapi.gepafin.base-path:/v1/dashboard}") +public class DashboardApiController implements DashboardApi { + + @Autowired + private DashboardService dashboardService; + + @Override + public ResponseEntity> getDashboardWidgetForSuperAdmin(HttpServletRequest request) { + SuperAdminWidgetResponseBean widgetResponseBean= dashboardService.getDashboardWidgetForSuperAdmin(request); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(widgetResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY))); } + + @Override + public ResponseEntity> getDashboardWidgetForBeneficiary(HttpServletRequest request, Long companyId) { + BeneficiaryWidgetResponseBean widgetResponseBean= dashboardService.getDashboardWidgetForBeneficiary(request, companyId); + return ResponseEntity.status(HttpStatus.CREATED) + .body(new Response<>(widgetResponseBean, Status.SUCCESS, Translator.toLocale(GepafinConstant.DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY))); + } + +} diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties index d09b9d29..ff1c3548 100644 --- a/src/main/resources/message_en.properties +++ b/src/main/resources/message_en.properties @@ -235,4 +235,6 @@ get.signed.document.file.success=Signed document file retrieved successfully. application.signed.document.not.found=Signed document for the application not found. delete.signed.document.file.success=Signed document deleted successfully. +dashboard.widget.fetched.successfully=Dasboard widget fetched sucessfully. + diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties index 1b9b3203..9a3bccf0 100644 --- a/src/main/resources/message_it.properties +++ b/src/main/resources/message_it.properties @@ -231,4 +231,5 @@ get.signed.document.file.success=File del documento firmato recuperato con succe application.signed.document.not.found=Documento firmato per l'applicazione non trovato. delete.signed.document.file.success=Documento firmato eliminato con successo. +dashboard.widget.fetched.successfully=Widget dashboard recuperato correttamente.