From 8367ad0456ab2c4e602dc13d7fcd99b9f45c8ce1 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 28 Mar 2024 15:56:16 +0000 Subject: [PATCH 01/24] fix: upgrade org.springdoc:springdoc-openapi-ui from 1.4.8 to 1.7.0 Snyk has created this PR to upgrade org.springdoc:springdoc-openapi-ui from 1.4.8 to 1.7.0. See this package in Maven Repository: https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c339f16..0d9b563 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ org.springdoc springdoc-openapi-ui - 1.4.8 + 1.7.0 From 2b7b96ca83633d64a9ca5b544ec34d0e4dfb970e Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 28 Mar 2024 15:56:19 +0000 Subject: [PATCH 02/24] fix: upgrade org.springframework.boot:spring-boot-devtools from 3.1.4 to 3.2.3 Snyk has created this PR to upgrade org.springframework.boot:spring-boot-devtools from 3.1.4 to 3.2.3. See this package in Maven Repository: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c339f16..c11bb98 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ org.springframework.boot spring-boot-devtools - 3.1.4 + 3.2.3 From ec84ebd6f78cd717ca378dc3f50b6dca906deb4a Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 28 Mar 2024 15:56:24 +0000 Subject: [PATCH 03/24] fix: upgrade com.querydsl:querydsl-jpa from 5.0.0 to 5.1.0 Snyk has created this PR to upgrade com.querydsl:querydsl-jpa from 5.0.0 to 5.1.0. See this package in Maven Repository: https://mvnrepository.com/artifact/com.querydsl/querydsl-jpa/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c339f16..eba8314 100644 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ com.querydsl querydsl-jpa jakarta - 5.0.0 + 5.1.0 From bba25b14172939e5c23e8cd2029ec14b335b0e7e Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Thu, 28 Mar 2024 15:56:27 +0000 Subject: [PATCH 04/24] fix: upgrade com.querydsl:querydsl-apt from 5.0.0 to 5.1.0 Snyk has created this PR to upgrade com.querydsl:querydsl-apt from 5.0.0 to 5.1.0. See this package in Maven Repository: https://mvnrepository.com/artifact/com.querydsl/querydsl-apt/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c339f16..1deb18e 100644 --- a/pom.xml +++ b/pom.xml @@ -97,7 +97,7 @@ querydsl-apt provided jakarta - 5.0.0 + 5.1.0 From ef58434cfd2ff07bbfee006cfc310f833c153b06 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:15:03 +0200 Subject: [PATCH 05/24] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 131bc2c..a7708f7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Build Status](https://github.com/MiguelPelegrina/java_school_online_store_api/actions/workflows/ci.yaml/badge.svg) + # JavaSchoolFinalTask2 Final Task Online store information system. From a8f310299b69fb20ff8a7fc936788605927400b1 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:27:20 +0200 Subject: [PATCH 06/24] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7708f7..46d69b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Build Status](https://github.com/MiguelPelegrina/java_school_online_store_api/actions/workflows/ci.yaml/badge.svg) +![Build Status](https://github.com/MiguelPelegrina/java_school_online_store_api/actions/workflows/ci.yml/badge.svg) # JavaSchoolFinalTask2 Final Task From a53fbe81b2608f7229f0478b70cb644febbc79b6 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:50:09 +0200 Subject: [PATCH 07/24] Update ci.yml --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0019582..7bda563 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,11 @@ name: CI Workflow on: push: - branches: [ "master" ] + branches: + - main pull_request: - branches: [ "master" ] + branches: + - main workflow_dispatch: jobs: From 346645a0496aef5f23d7baef4d1330d63288ca69 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:19:24 +0200 Subject: [PATCH 08/24] Update ci.yml --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7bda563..dc22014 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,6 @@ on: pull_request: branches: - main - workflow_dispatch: jobs: build: From 4610364e8734a09439e747cdfac39d2edc434307 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:26:27 +0200 Subject: [PATCH 09/24] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc22014..ae80a20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: - main pull_request: branches: - - main + - main jobs: build: From d13095dfccd2a1e0c0f1b37f112cbd232a0e2b9f Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Wed, 10 Apr 2024 08:27:35 +0200 Subject: [PATCH 10/24] Update ci.yml --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae80a20..0019582 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,11 +2,10 @@ name: CI Workflow on: push: - branches: - - main + branches: [ "master" ] pull_request: - branches: - - main + branches: [ "master" ] + workflow_dispatch: jobs: build: From 689d12f7becd97280b885526e07386c04fe9229d Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:28:48 +0200 Subject: [PATCH 11/24] refactored the exceptionhandler --- .../BusinessLogicExceptionHandler.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/java_school/final_task/exception/BusinessLogicExceptionHandler.java b/src/main/java/com/java_school/final_task/exception/BusinessLogicExceptionHandler.java index af8380d..22c2348 100644 --- a/src/main/java/com/java_school/final_task/exception/BusinessLogicExceptionHandler.java +++ b/src/main/java/com/java_school/final_task/exception/BusinessLogicExceptionHandler.java @@ -6,6 +6,7 @@ import com.java_school.final_task.exception.user.InactiveUserException; import com.java_school.final_task.exception.user.InsufficientPermissionsException; import com.java_school.final_task.exception.user.UserDoesNotExistException; +import com.lowagie.text.DocumentException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; @@ -14,6 +15,15 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; +// TODO +// - Reduce information that is send to the frontend, especially regarding user data, like name and password not +// matching as that already implies that the introduced user exists +// - Introduce logging to keep track of exceptions + +/** + * Global exception handler for handling business logic exceptions thrown within the application. + * It provides centralized exception handling across all @Controller classes. + */ @RestControllerAdvice public class BusinessLogicExceptionHandler { @ExceptionHandler(AccessDeniedException.class) @@ -25,7 +35,13 @@ public ResponseEntity handleAccessDenied(AccessDeniedException e) { @ExceptionHandler(BadCredentialsException.class) @ResponseStatus(HttpStatus.CONFLICT) public ResponseEntity handleBadCredentials(BadCredentialsException e) { - return ResponseEntity.status(409).body(e.getMessage()); + return ResponseEntity.status(HttpStatus.CONFLICT).body(e.getMessage()); + } + + @ExceptionHandler(DocumentException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ResponseEntity handleDocumentException(DocumentException e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); } @ExceptionHandler(EmailAlreadyUsedException.class) @@ -49,30 +65,30 @@ public ResponseEntity handleInactiveUserException(InactiveUserException @ExceptionHandler(InsufficientPermissionsException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public ResponseEntity handleInsufficientPermissionsException(InsufficientPermissionsException e) { - return ResponseEntity.status(403).body(e.getMessage()); + return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage()); } @ExceptionHandler(ProductNotAvailableException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) + @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) public ResponseEntity handleProductNotAvailable(ProductNotAvailableException e) { - return ResponseEntity.status(405).body(e.getMessage()); + return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(e.getMessage()); } @ExceptionHandler(ProductOutOfStockException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) + @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) public ResponseEntity handleProductOutOfStock(ProductOutOfStockException e) { - return ResponseEntity.status(405).body(e.getMessage()); + return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED).body(e.getMessage()); } @ExceptionHandler(ResourceNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ResponseEntity handleNotFound(ResourceNotFoundException e) { - return ResponseEntity.status(404).body(e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } @ExceptionHandler(UserDoesNotExistException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ResponseEntity handleUserDoesNotExist(UserDoesNotExistException e) { - return ResponseEntity.status(404).body(e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } } From 74c26f4cfc4401d4095ff2c69141156e2f509a42 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Fri, 12 Apr 2024 11:35:54 +0200 Subject: [PATCH 12/24] refactoring and documentation of the latest code updates --- .../configuration/JPAQueryFactoryConfig.java | 10 ++ .../configuration/ThymeleafConfig.java | 14 +++ .../domain/order/impl/OrderServiceImpl.java | 58 +++++---- .../domain/user/impl/UserServiceImpl.java | 2 + .../final_task/utils/MailService.java | 9 ++ .../final_task/utils/PDFService.java | 10 ++ .../utils/impl/MailServiceImpl.java | 112 ++++++++++++------ .../final_task/utils/impl/PDFServiceImpl.java | 45 ++++++- 8 files changed, 196 insertions(+), 64 deletions(-) diff --git a/src/main/java/com/java_school/final_task/configuration/JPAQueryFactoryConfig.java b/src/main/java/com/java_school/final_task/configuration/JPAQueryFactoryConfig.java index 7fc7762..6cf0f08 100644 --- a/src/main/java/com/java_school/final_task/configuration/JPAQueryFactoryConfig.java +++ b/src/main/java/com/java_school/final_task/configuration/JPAQueryFactoryConfig.java @@ -6,8 +6,18 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * Configuration class for setting up JPAQueryFactory bean. + * Provides bean definitions for creating and configuring JPAQueryFactory instances. + */ @Configuration public class JPAQueryFactoryConfig { + /** + * Configures and provides a JPAQueryFactory bean. + * + * @param entityManager The EntityManager instance to be injected into the JPAQueryFactory. + * @return JPAQueryFactory A configured bean of JPAQueryFactory that integrates with JPA. + */ @Bean public JPAQueryFactory jpaQueryFactory(@Autowired EntityManager entityManager) { return new JPAQueryFactory(entityManager); diff --git a/src/main/java/com/java_school/final_task/configuration/ThymeleafConfig.java b/src/main/java/com/java_school/final_task/configuration/ThymeleafConfig.java index 82d776d..4ebf0e0 100644 --- a/src/main/java/com/java_school/final_task/configuration/ThymeleafConfig.java +++ b/src/main/java/com/java_school/final_task/configuration/ThymeleafConfig.java @@ -5,8 +5,17 @@ import org.thymeleaf.spring5.SpringTemplateEngine; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; +/** + * Configuration class for Thymeleaf template engine setup. + * Provides bean definitions for configuring Thymeleaf template resolution and processing. + */ @Configuration public class ThymeleafConfig { + /** + * Configures and provides a ClassLoaderTemplateResolver bean for Thymeleaf. + * + * @return ClassLoaderTemplateResolver A configured template resolver for resolving templates from the classpath. + */ @Bean public ClassLoaderTemplateResolver templateResolver() { ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); @@ -18,6 +27,11 @@ public ClassLoaderTemplateResolver templateResolver() { return templateResolver; } + /** + * Configures and provides a SpringTemplateEngine bean for Thymeleaf. + * + * @return SpringTemplateEngine A configured template engine that integrates with Spring and Thymeleaf. + */ @Bean public SpringTemplateEngine templateEngine() { var templateEngine = new SpringTemplateEngine(); diff --git a/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java b/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java index 8c722f6..5dd84e8 100644 --- a/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java +++ b/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java @@ -2,23 +2,18 @@ import com.java_school.final_task.domain.book.BookEntity; import com.java_school.final_task.domain.book.BookRepository; -import com.java_school.final_task.domain.order.OrderEntity; -import com.java_school.final_task.domain.order.OrderRepository; -import com.java_school.final_task.domain.order.OrderService; -import com.java_school.final_task.domain.order.QOrderEntity; +import com.java_school.final_task.domain.order.*; import com.java_school.final_task.domain.order.dto.OrderDTO; import com.java_school.final_task.domain.order.dto.OrderRequestDTO; import com.java_school.final_task.domain.order.dto.SaveOrderDTO; import com.java_school.final_task.domain.order_book.QOrderBookEntity; import com.java_school.final_task.domain.user.UserEntity; import com.java_school.final_task.domain.user.UserService; -import com.java_school.final_task.domain.user.impl.UserServiceImpl; import com.java_school.final_task.exception.book.ProductNotAvailableException; import com.java_school.final_task.exception.book.ProductOutOfStockException; import com.java_school.final_task.exception.user.InactiveUserException; import com.java_school.final_task.utils.MailService; import com.java_school.final_task.utils.impl.AbstractServiceImpl; -import com.java_school.final_task.utils.impl.MailServiceImpl; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.dsl.StringExpression; import com.querydsl.jpa.impl.JPAQueryFactory; @@ -34,21 +29,19 @@ import java.time.LocalDate; /** - * Service class responsible for the interaction between the {@link OrderRepository} and the {@link OrderRestControllerImpl}. + * Service class responsible for the interaction between the {@link OrderRepository} and the {@link OrderRestController}. * Obtains data from the {@link OrderRepository} and returns the object(s) of the {@link OrderEntity} as {@link OrderDTO} - * to the {@link OrderRestControllerImpl}. + * to the {@link OrderRestController}. */ -@Secured({"ROLE_ADMIN", "EMPLOYEE", "CLIENT"}) +@Secured({"ROLE_ADMIN", "ROLE_EMPLOYEE", "ROLE_CLIENT"}) @Service public class OrderServiceImpl extends AbstractServiceImpl implements OrderService { // Fields private final UserService userService; - - private final MailServiceImpl mailService; + private final MailService mailService; private final BookRepository bookRepository; - private final JPAQueryFactory queryFactory; /** @@ -56,13 +49,13 @@ public class OrderServiceImpl * * @param repository {@link OrderRepository} of the {@link OrderEntity}. * @param modelMapper ModelMapper that converts the {@link OrderEntity} instance to {@link OrderDTO} - * @param userService {@link UserServiceImpl} of the {@link UserEntity}. - * @param mailService {@link MailServiceImpl} of the {@link MailService} + * @param userService {@link UserService} of the {@link UserEntity}. + * @param mailService {@link MailService} of the {@link MailService} * @param bookRepository {@link BookRepository} of the {@link BookEntity}. * @param queryFactory {@link JPAQueryFactory} for query and DML clause creation. */ - public OrderServiceImpl(OrderRepository repository, ModelMapper modelMapper, MailServiceImpl mailService, - UserServiceImpl userService, BookRepository bookRepository, JPAQueryFactory queryFactory) { + public OrderServiceImpl(OrderRepository repository, ModelMapper modelMapper, MailService mailService, + UserService userService, BookRepository bookRepository, JPAQueryFactory queryFactory) { super(repository, modelMapper); this.userService = userService; this.mailService = mailService; @@ -101,7 +94,7 @@ public BigDecimal calculateTotalRevenue(LocalDate startDate, LocalDate endDate) } @Override - @Secured({"ROLE_ADMIN", "EMPLOYEE"}) + @Secured({"ROLE_ADMIN", "ROLE_EMPLOYEE"}) public void deleteInstance(Integer integer) { super.deleteInstance(integer); } @@ -117,11 +110,7 @@ public Page getAllInstances(OrderRequestDTO orderRequestDTO) { // Check if the current user is active if (currentUser.isActive()) { - // Check which parameters are present and build a query - handleParameter(orderRequestDTO.getDeliveryMethod(), queryBuilder, qOrder.deliveryMethod.name); - handleParameter(orderRequestDTO.getOrderStatus(), queryBuilder, qOrder.orderStatus.name); - handleParameter(orderRequestDTO.getPaymentMethod(), queryBuilder, qOrder.paymentMethod.name); - handleParameter(orderRequestDTO.getPaymentStatus(), queryBuilder, qOrder.paymentStatus.name); + handleQueryParameters(orderRequestDTO, queryBuilder, qOrder); if (orderRequestDTO.getDate() != null) { queryBuilder.and(qOrder.date.eq(orderRequestDTO.getDate())); @@ -201,7 +190,28 @@ public OrderDTO saveInstance(SaveOrderDTO saveOrderDTO) { return modelMapper.map(repository.save(newOrder), getDTOClass()); } - private void handleParameter(String parameter, BooleanBuilder queryBuilder, StringExpression expression) { - queryBuilder.and(!"".equals(parameter) ? expression.containsIgnoreCase(parameter) : null); + /** + * Handles a query parameter by adding a condition to the BooleanBuilder. + * + * @param parameter The query parameter to handle. + * @param queryBuilder The BooleanBuilder to which the condition will be added. + * @param expression The StringExpression representing the field to filter on. + */ + private void handleQueryParameter(String parameter, BooleanBuilder queryBuilder, StringExpression expression) { + queryBuilder.and(!parameter.trim().isEmpty() ? expression.containsIgnoreCase(parameter) : null); + } + + /** + * Handles multiple query parameters for an order request by delegating to handleQueryParameter for each parameter. + * + * @param orderRequestDTO The OrderRequestDTO containing the query parameters. + * @param queryBuilder The BooleanBuilder to which the conditions will be added. + * @param qOrder The QOrderEntity representing the query entity. + */ + private void handleQueryParameters(OrderRequestDTO orderRequestDTO, BooleanBuilder queryBuilder, QOrderEntity qOrder) { + handleQueryParameter(orderRequestDTO.getDeliveryMethod(), queryBuilder, qOrder.deliveryMethod.name); + handleQueryParameter(orderRequestDTO.getOrderStatus(), queryBuilder, qOrder.orderStatus.name); + handleQueryParameter(orderRequestDTO.getPaymentMethod(), queryBuilder, qOrder.paymentMethod.name); + handleQueryParameter(orderRequestDTO.getPaymentStatus(), queryBuilder, qOrder.paymentStatus.name); } } diff --git a/src/main/java/com/java_school/final_task/domain/user/impl/UserServiceImpl.java b/src/main/java/com/java_school/final_task/domain/user/impl/UserServiceImpl.java index fa5662f..4fbc9ef 100644 --- a/src/main/java/com/java_school/final_task/domain/user/impl/UserServiceImpl.java +++ b/src/main/java/com/java_school/final_task/domain/user/impl/UserServiceImpl.java @@ -23,6 +23,8 @@ import java.util.Optional; +// TODO Too many comments + /** * Service class responsible for the interaction between the {@link UserRepository} and the * {@link UserRestControllerImpl}. Obtains data from the diff --git a/src/main/java/com/java_school/final_task/utils/MailService.java b/src/main/java/com/java_school/final_task/utils/MailService.java index f719159..7d5c9b9 100644 --- a/src/main/java/com/java_school/final_task/utils/MailService.java +++ b/src/main/java/com/java_school/final_task/utils/MailService.java @@ -2,7 +2,16 @@ import com.java_school.final_task.domain.order.dto.SaveOrderDTO; +/** + * Interface for sending emails related to orders. + * Defines methods for sending order confirmation emails. + */ public interface MailService { + /** + * Sends an order confirmation email based on the provided SaveOrderDTO. + * + * @param saveOrderDTO The SaveOrderDTO object containing the details of the order. + */ void sendOrderConfirmationMail(SaveOrderDTO saveOrderDTO); //void sendRegistrationConfirmationMail(String to, String text); diff --git a/src/main/java/com/java_school/final_task/utils/PDFService.java b/src/main/java/com/java_school/final_task/utils/PDFService.java index 0ce8083..ed41850 100644 --- a/src/main/java/com/java_school/final_task/utils/PDFService.java +++ b/src/main/java/com/java_school/final_task/utils/PDFService.java @@ -2,6 +2,16 @@ import com.java_school.final_task.domain.order.dto.SaveOrderDTO; +/** + * Interface for PDF generation service. + * Defines methods for generating PDF documents related to orders. + */ public interface PDFService { + /** + * Generates a PDF document containing order details based on the provided SaveOrderDTO. + * + * @param saveOrderDTO The SaveOrderDTO object containing the details of the order. + * @return byte[] The byte array representing the generated PDF document. + */ byte[] generateOrderDetailsPDF(SaveOrderDTO saveOrderDTO); } diff --git a/src/main/java/com/java_school/final_task/utils/impl/MailServiceImpl.java b/src/main/java/com/java_school/final_task/utils/impl/MailServiceImpl.java index 956b22f..ae667c6 100644 --- a/src/main/java/com/java_school/final_task/utils/impl/MailServiceImpl.java +++ b/src/main/java/com/java_school/final_task/utils/impl/MailServiceImpl.java @@ -4,6 +4,7 @@ import com.java_school.final_task.domain.order_book.OrderBookEntity; import com.java_school.final_task.exception.MessagingExceptionWrapper; import com.java_school.final_task.utils.MailService; +import com.java_school.final_task.utils.PDFService; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import org.springframework.beans.factory.annotation.Value; @@ -18,57 +19,106 @@ import java.util.HashMap; import java.util.Map; +/** + * {@link MailService} implementation responsible for sending emails. + * This class implements the MailService interface and provides functionality to generate HTML content, + * attach PDF documents, and send emails using Spring's JavaMailSender. + */ @Service public class MailServiceImpl implements MailService { private final JavaMailSender mailSender; - private final SpringTemplateEngine thymeleafTemplateEngine; - - private final PDFServiceImpl pdfService; - - @Value("${MAIL_USERNAME}") - private String mailFromAddress; - - public MailServiceImpl(JavaMailSender mailSender, PDFServiceImpl pdfService, SpringTemplateEngine thymeleafTemplateEngine) { + private final PDFService pdfService; + private final String mailFromAddress; + + /** + * Constructs a new MailServiceImpl with the specified dependencies. + * + * @param mailSender The {@link JavaMailSender} instance used to send emails. + * @param pdfService The {@link PDFServiceImpl} instance used to generate PDF documents. + * @param thymeleafTemplateEngine The {@link SpringTemplateEngine} instance used to process HTML templates. + * @param mailFromAddress The email address from which the emails will be sent. + */ + public MailServiceImpl( + JavaMailSender mailSender, + PDFService pdfService, + SpringTemplateEngine thymeleafTemplateEngine, + @Value("${MAIL_USERNAME}") String mailFromAddress + ) { this.mailSender = mailSender; this.thymeleafTemplateEngine = thymeleafTemplateEngine; this.pdfService = pdfService; + this.mailFromAddress = mailFromAddress; } + /** + * Sends an order confirmation email to the user with the order details. + * + * @param saveOrderDTO The {@link SaveOrderDTO} instance containing the order details. + */ @Override public void sendOrderConfirmationMail(SaveOrderDTO saveOrderDTO) { - try { - byte[] pdfContent = pdfService.generateOrderDetailsPDF(saveOrderDTO); + byte[] pdfContent = pdfService.generateOrderDetailsPDF(saveOrderDTO); - // Prepare the model for the template - Map templateModel = new HashMap<>(); - templateModel.put("customerName", saveOrderDTO.getOrder().getUser().getName()); - templateModel.put("orderedBooks", saveOrderDTO.getOrderedBooks()); - BigDecimal total = saveOrderDTO.getOrderedBooks().stream().map(OrderBookEntity::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add); - templateModel.put("total", total); + String htmlContent = this.generateHTMLContent(saveOrderDTO); - // Process the template - Context thymeleafContext = new Context(); - thymeleafContext.setVariables(templateModel); - String htmlContent = thymeleafTemplateEngine.process("order-confirmation-mail", thymeleafContext); + MimeMessage message = createMimeMessage(saveOrderDTO, htmlContent, pdfContent); - MimeMessage message = mailSender.createMimeMessage(); + mailSender.send(message); + } + + /** + * Generates HTML content for the order confirmation email. + * + * @param saveOrderDTO The {@code SaveOrderDTO} containing the order details. + * @return The HTML content of the email. + */ + private String generateHTMLContent(SaveOrderDTO saveOrderDTO) { + Map templateModel = this.generateTemplateModel(saveOrderDTO); + Context thymeleafContext = new Context(); + thymeleafContext.setVariables(templateModel); + return thymeleafTemplateEngine.process("order-confirmation-mail", thymeleafContext); + } + + /** + * Generates a template model for the order confirmation email. + * + * @param saveOrderDTO The {@code SaveOrderDTO} instance containing the order details. + * @return The template model containing data for the email template. + */ + private Map generateTemplateModel(SaveOrderDTO saveOrderDTO) { + Map templateModel = new HashMap<>(); + templateModel.put("customerName", saveOrderDTO.getOrder().getUser().getName()); + templateModel.put("orderedBooks", saveOrderDTO.getOrderedBooks()); + BigDecimal total = saveOrderDTO.getOrderedBooks().stream().map(OrderBookEntity::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add); + templateModel.put("total", total); + return templateModel; + } + + /** + * Creates a MimeMessage for the order confirmation email. + * + * @param saveOrderDTO The {@code SaveOrderDTO} instance containing the order details. + * @param htmlContent The HTML content of the email. + * @param pdfContent The content of the PDF attachment. + * @return The MimeMessage for the email. + */ + private MimeMessage createMimeMessage(SaveOrderDTO saveOrderDTO, String htmlContent, byte[] pdfContent) { + MimeMessage message = mailSender.createMimeMessage(); + try { MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setTo(saveOrderDTO.getOrder().getUser().getEmail()); helper.setSubject("Order confirmation at Online Bookstore"); - - // Set the content of the email helper.setText(htmlContent, true); - // Add the PDF as an attachment String attachmentName = "order_" + saveOrderDTO.getOrder().getDate() + ".pdf"; helper.addAttachment(attachmentName, new ByteArrayResource(pdfContent)); - - this.sendMail(message); + message.setFrom(mailFromAddress); } catch (MessagingException e) { throw new MessagingExceptionWrapper(); } + return message; } /*@Override @@ -81,14 +131,4 @@ public void sendRegistrationConfirmationMail(String to, String text) { this.sendMail(message); }*/ - - private void sendMail(MimeMessage message) { - try { - message.setFrom(mailFromAddress); - } catch (MessagingException e) { - throw new MessagingExceptionWrapper(); - } - - mailSender.send(message); - } } diff --git a/src/main/java/com/java_school/final_task/utils/impl/PDFServiceImpl.java b/src/main/java/com/java_school/final_task/utils/impl/PDFServiceImpl.java index 9dbdcd0..5a9c860 100644 --- a/src/main/java/com/java_school/final_task/utils/impl/PDFServiceImpl.java +++ b/src/main/java/com/java_school/final_task/utils/impl/PDFServiceImpl.java @@ -10,23 +10,63 @@ import java.io.ByteArrayOutputStream; import java.math.BigDecimal; +/** + * Service implementation for generating PDF documents. + */ @Service public class PDFServiceImpl implements PDFService { + /** + * Generates a PDF document containing order details based on the provided {@link SaveOrderDTO}. + * + * @param saveOrderDTO The {@code SaveOrderDTO} object containing the details of the order. + * @return byte[] The byte array representing the generated PDF document. + */ @Override public byte[] generateOrderDetailsPDF(SaveOrderDTO saveOrderDTO) { + // Set up variables ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Document document = new Document(PageSize.A4); - PdfWriter.getInstance(document, outputStream); document.open(); + this.addOrderDetails(document, saveOrderDTO); + document.close(); + + return outputStream.toByteArray(); + } + + /** + * Adds order details to the PDF document. + * + * @param document The {@link Document} object representing the PDF document. + * @param saveOrderDTO The {@link SaveOrderDTO} object containing the details of the order. + */ + private void addOrderDetails(Document document, SaveOrderDTO saveOrderDTO) { + addOrderConfirmationHeader(document); + addOrderConfirmationBody(document, saveOrderDTO); + } + /** + * Adds the header section to the PDF document. + * + * @param document The {@link Document} object representing the PDF document. + */ + private void addOrderConfirmationHeader(Document document) { Font fontHeader = FontFactory.getFont(FontFactory.TIMES_BOLD); fontHeader.setSize(22); Paragraph headerParagraph = new Paragraph("Order Details", fontHeader); headerParagraph.setAlignment(Paragraph.ALIGN_CENTER); + document.add(headerParagraph); + } + /** + * Adds the body section with order details to the PDF document. + * + * @param document The {@link Document} object representing the PDF document. + * @param saveOrderDTO The @link SaveOrderDTO} object containing the details of the order. + */ + private void addOrderConfirmationBody(Document document, SaveOrderDTO saveOrderDTO) { Font fontParagraph = FontFactory.getFont(FontFactory.TIMES); fontParagraph.setSize(14); @@ -44,9 +84,6 @@ public byte[] generateOrderDetailsPDF(SaveOrderDTO saveOrderDTO) { } pdfParagraph.add("Order total: " + saveOrderDTO.getOrderedBooks().stream().map(OrderBookEntity::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add)); - document.add(headerParagraph); document.add(pdfParagraph); - document.close(); - return outputStream.toByteArray(); } } From b09bea4714da6e96479fc118c2092c095da0ea79 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Fri, 12 Apr 2024 11:45:20 +0200 Subject: [PATCH 13/24] updating dependencies --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 1059884..ac8a79d 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ org.postgresql postgresql + 42.6.1 runtime @@ -78,6 +79,7 @@ org.springframework.boot spring-boot-starter-security + 3.2.4 From 987cda4ab03677e78160ac5f5f676d7566dc6d53 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 12 Apr 2024 10:07:50 +0000 Subject: [PATCH 14/24] fix: Dockerfile to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-ALPINE314-APKTOOLS-1533752 - https://snyk.io/vuln/SNYK-ALPINE314-LIBTASN1-3173577 - https://snyk.io/vuln/SNYK-ALPINE314-OPENSSL-1569445 - https://snyk.io/vuln/SNYK-ALPINE314-OPENSSL-1569445 - https://snyk.io/vuln/SNYK-ALPINE314-ZLIB-2976174 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 881d937..5690714 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:17-jdk-alpine +FROM openjdk:23-ea-17-jdk-oraclelinux8 COPY ./target/online_store-0.0.1-SNAPSHOT.jar ./app.jar From 387f45d5e80a7bcb88fdb7c6b9d3fa97f988c4a1 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 12 Apr 2024 10:17:27 +0000 Subject: [PATCH 15/24] fix: pom.xml to reduce vulnerabilities The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-6094942 - https://snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-6094943 - https://snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-6097492 - https://snyk.io/vuln/SNYK-JAVA-CHQOSLOGBACK-6097493 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHECOMMONS-5901530 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHETOMCATEMBED-5953331 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHETOMCATEMBED-5959654 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHETOMCATEMBED-5959972 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHETOMCATEMBED-6092281 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHETOMCATEMBED-6435948 - https://snyk.io/vuln/SNYK-JAVA-ORGAPACHETOMCATEMBED-6435950 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5fb79b7..d465027 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.6.2 + 3.6.3 From c1eb812f0ce67299837e5853de2d28c7e3c9c5f5 Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:20:32 +0200 Subject: [PATCH 16/24] implemented prometheus metrics --- pom.xml | 10 ++++++++++ .../final_task/configuration/WebConfig.java | 3 ++- src/main/resources/application.yml | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/application.yml diff --git a/pom.xml b/pom.xml index d465027..02262a2 100644 --- a/pom.xml +++ b/pom.xml @@ -143,6 +143,16 @@ openpdf 1.3.26 + + + org.springframework.boot + spring-boot-starter-actuator + + + + io.micrometer + micrometer-registry-prometheus + diff --git a/src/main/java/com/java_school/final_task/configuration/WebConfig.java b/src/main/java/com/java_school/final_task/configuration/WebConfig.java index ff3a227..52438db 100644 --- a/src/main/java/com/java_school/final_task/configuration/WebConfig.java +++ b/src/main/java/com/java_school/final_task/configuration/WebConfig.java @@ -98,7 +98,8 @@ public SecurityFilterChain securityFilterChain( "/payment_statuses/search", "/postal_codes/search", "/swagger-ui/**", - "/api-docs/swagger-config" + "/api-docs/swagger-config", + "/actuator/prometheus" ).permitAll() .anyRequest().authenticated() ) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..52c5807 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + application: + name: spring-prometheus-demo +management: + endpoints: + web: + exposure: + include: health, metrics, prometheus + metrics: + tags: + application: ${spring.application.name} \ No newline at end of file From 4ae4c67aaf6acd8a00fa91b00665f10453529c55 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Tue, 16 Apr 2024 01:56:54 +0000 Subject: [PATCH 17/24] fix: upgrade com.github.librepdf:openpdf from 1.3.26 to 1.4.1 Snyk has created this PR to upgrade com.github.librepdf:openpdf from 1.3.26 to 1.4.1. See this package in Maven Repository: https://mvnrepository.com/artifact/com.github.librepdf/openpdf/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02262a2..c68bfb2 100644 --- a/pom.xml +++ b/pom.xml @@ -141,7 +141,7 @@ com.github.librepdf openpdf - 1.3.26 + 1.4.1 From 39d98a369a5102a414ee475b4f583ea1d35330e9 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Tue, 16 Apr 2024 01:56:57 +0000 Subject: [PATCH 18/24] fix: upgrade org.postgresql:postgresql from 42.6.1 to 42.7.3 Snyk has created this PR to upgrade org.postgresql:postgresql from 42.6.1 to 42.7.3. See this package in Maven Repository: https://mvnrepository.com/artifact/org.postgresql/postgresql/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02262a2..b11c1ee 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ org.postgresql postgresql - 42.6.1 + 42.7.3 runtime From c570368d804e80ef6d94a1b24d9360d84d3b438b Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Tue, 16 Apr 2024 01:57:00 +0000 Subject: [PATCH 19/24] fix: upgrade org.springdoc:springdoc-openapi-starter-webmvc-ui from 2.2.0 to 2.4.0 Snyk has created this PR to upgrade org.springdoc:springdoc-openapi-starter-webmvc-ui from 2.2.0 to 2.4.0. See this package in Maven Repository: https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02262a2..734fbb4 100644 --- a/pom.xml +++ b/pom.xml @@ -73,7 +73,7 @@ org.springdoc springdoc-openapi-starter-webmvc-ui - 2.2.0 + 2.4.0 From aad42bf0a88f701d9258c671e2726658012e6d12 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Tue, 16 Apr 2024 01:57:02 +0000 Subject: [PATCH 20/24] fix: upgrade javax.xml.bind:jaxb-api from 2.3.0 to 2.3.1 Snyk has created this PR to upgrade javax.xml.bind:jaxb-api from 2.3.0 to 2.3.1. See this package in Maven Repository: https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02262a2..8701a36 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ javax.xml.bind jaxb-api - 2.3.0 + 2.3.1 From aabd7d14bc5f7580741625861a69dc8e568c122b Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 17 Apr 2024 22:25:28 +0000 Subject: [PATCH 21/24] fix: upgrade org.modelmapper:modelmapper from 3.1.1 to 3.2.0 Snyk has created this PR to upgrade org.modelmapper:modelmapper from 3.1.1 to 3.2.0. See this package in Maven Repository: https://mvnrepository.com/artifact/org.modelmapper/modelmapper/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2176655..fb57cb9 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ org.modelmapper modelmapper - 3.1.1 + 3.2.0 From 80eb8ed7c9454073c478a58db1a55fb074effd83 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 17 Apr 2024 22:25:31 +0000 Subject: [PATCH 22/24] fix: upgrade org.springdoc:springdoc-openapi-ui from 1.7.0 to 1.8.0 Snyk has created this PR to upgrade org.springdoc:springdoc-openapi-ui from 1.7.0 to 1.8.0. See this package in Maven Repository: https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-ui/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2176655..2184224 100644 --- a/pom.xml +++ b/pom.xml @@ -118,7 +118,7 @@ org.springdoc springdoc-openapi-ui - 1.7.0 + 1.8.0 From f23604e864fb6f263529ab8c1dda3edd4962a50c Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 17 Apr 2024 22:25:34 +0000 Subject: [PATCH 23/24] fix: upgrade org.springframework.boot:spring-boot-devtools from 3.2.3 to 3.2.4 Snyk has created this PR to upgrade org.springframework.boot:spring-boot-devtools from 3.2.3 to 3.2.4. See this package in Maven Repository: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools/ See this project in Snyk: https://app.snyk.io/org/miguelpelegrina/project/2b115bed-494c-47c4-9dde-8dd8dd206d87?utm_source=github&utm_medium=referral&page=upgrade-pr --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2176655..67081ba 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ org.springframework.boot spring-boot-devtools - 3.2.3 + 3.2.4 From e18180faffda169a2309380d3c59f567f4cf6f1a Mon Sep 17 00:00:00 2001 From: MiguelPelegrina <95084406+MiguelPelegrina@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:28:20 +0200 Subject: [PATCH 24/24] Added RESTful request for yearly revenue calculations for a year and the last 12 months --- pom.xml | 4 +-- .../domain/order/OrderRestController.java | 18 ++++++++++++ .../final_task/domain/order/OrderService.java | 9 ++++++ .../order/impl/OrderRestControllerImpl.java | 28 ++++++++++++++++++- .../domain/order/impl/OrderServiceImpl.java | 28 +++++++++++++++++++ src/main/resources/application.yml | 2 +- 6 files changed, 85 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index a48a9ff..4730f7c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.1.4 + 3.2.4 com.javaSchool @@ -148,7 +148,7 @@ org.springframework.boot spring-boot-starter-actuator - + io.micrometer micrometer-registry-prometheus diff --git a/src/main/java/com/java_school/final_task/domain/order/OrderRestController.java b/src/main/java/com/java_school/final_task/domain/order/OrderRestController.java index 8266692..832e16c 100644 --- a/src/main/java/com/java_school/final_task/domain/order/OrderRestController.java +++ b/src/main/java/com/java_school/final_task/domain/order/OrderRestController.java @@ -30,6 +30,22 @@ public interface OrderRestController { */ ResponseEntity calculateTotalRevenue(LocalDate startDate, LocalDate endDate); + /** + * Calculates the revenue of a year from January to December based on the provided date. + * + * @param date The date to calculate the revenue for, formatted as "dd-MM-yyyy". + * @return A ResponseEntity containing an array of BigDecimal representing the revenue for each month of the year. + */ + ResponseEntity calculateRevenuesOfYearByMonths(LocalDate date); + + /** + * Calculates the revenue of the last 12 months. + * + * @param date The date to calculate the revenue from, formatted as "dd-MM-yyyy". + * @return A ResponseEntity containing an array of BigDecimal representing the revenue for each of the last 12 months. + */ + ResponseEntity calculateRevenuesOfLast12Months(LocalDate date); + /** * Submits a POST request with a {@link SaveOrderDTO} to create an order instance in the database. * @@ -38,4 +54,6 @@ public interface OrderRestController { * If successful, the code is 200 created successfully, 204 otherwise. */ ResponseEntity saveInstance(SaveOrderDTO saveOrderDTO); + + } diff --git a/src/main/java/com/java_school/final_task/domain/order/OrderService.java b/src/main/java/com/java_school/final_task/domain/order/OrderService.java index 1db739e..509ed33 100644 --- a/src/main/java/com/java_school/final_task/domain/order/OrderService.java +++ b/src/main/java/com/java_school/final_task/domain/order/OrderService.java @@ -15,6 +15,15 @@ * the object(s) of the entity {@link OrderEntity} as {@link OrderDTO} to the {@link OrderRestControllerImpl}. */ public interface OrderService { + /** + * Calculates the revenue for a specified year or the last 12 months. + * + * @param year The year for which the revenue should be calculated. + * @param isLast12Months A boolean flag indicating whether to calculate the revenue for the last 12 months from the current date. + * @return An array of BigDecimal representing the revenue for each month within the specified year or for the last 12 months. + */ + BigDecimal[] calculateRevenueOfYearByMonths(LocalDate year, boolean isLast12Months); + /** * Retrieves a page of {@link OrderDTO}s from the database based on {@link OrderRequestDTO}. * diff --git a/src/main/java/com/java_school/final_task/domain/order/impl/OrderRestControllerImpl.java b/src/main/java/com/java_school/final_task/domain/order/impl/OrderRestControllerImpl.java index e92a5bf..7a04522 100644 --- a/src/main/java/com/java_school/final_task/domain/order/impl/OrderRestControllerImpl.java +++ b/src/main/java/com/java_school/final_task/domain/order/impl/OrderRestControllerImpl.java @@ -57,7 +57,7 @@ public ResponseEntity> getAllInstances( } @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Calculated the revenue", + @ApiResponse(responseCode = "200", description = "Calculate the total revenue", content = {@Content(mediaType = "application/json", schema = @Schema)}), @ApiResponse(responseCode = "401", description = "Not authorized", content = @Content), @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content) @@ -73,6 +73,32 @@ public ResponseEntity calculateTotalRevenue( return ResponseEntity.ok(this.service.calculateTotalRevenue(startDate, endDate)); } + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Calculate the revenue of a year from january to december", + content = {@Content(mediaType = "application/json", schema = @Schema)}), + @ApiResponse(responseCode = "401", description = "Not authorized", content = @Content), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content) + }) + @GetMapping("/revenueOfYearByMonths") + @Override + public ResponseEntity calculateRevenuesOfYearByMonths( + @RequestParam("date") @DateTimeFormat(pattern = "dd-MM-yyyy") LocalDate date) { + return ResponseEntity.ok(this.service.calculateRevenueOfYearByMonths(date, false)); + } + + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Calculate the revenue of the last 12 months", + content = {@Content(mediaType = "application/json", schema = @Schema)}), + @ApiResponse(responseCode = "401", description = "Not authorized", content = @Content), + @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content) + }) + @GetMapping("/revenueOfLast12Months") + @Override + public ResponseEntity calculateRevenuesOfLast12Months( + @RequestParam("date") @DateTimeFormat(pattern = "dd-MM-yyyy") LocalDate date) { + return ResponseEntity.ok(this.service.calculateRevenueOfYearByMonths(date, true)); + } + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Saved the order", content = {@Content(mediaType = "application/json", schema = @Schema)}), diff --git a/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java b/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java index 5dd84e8..23c7917 100644 --- a/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java +++ b/src/main/java/com/java_school/final_task/domain/order/impl/OrderServiceImpl.java @@ -27,6 +27,7 @@ import java.math.BigDecimal; import java.time.LocalDate; +import java.time.YearMonth; /** * Service class responsible for the interaction between the {@link OrderRepository} and the {@link OrderRestController}. @@ -93,6 +94,33 @@ public BigDecimal calculateTotalRevenue(LocalDate startDate, LocalDate endDate) } } + @Override + @Secured({"ROLE_ADMIN", "ROLE_EMPLOYEE"}) + public BigDecimal[] calculateRevenueOfYearByMonths(LocalDate date, boolean isLast12Months) { + BigDecimal[] revenues = new BigDecimal[12]; + LocalDate currentDate = LocalDate.now(); + LocalDate startDate; + + if (isLast12Months) { + startDate = currentDate.minusMonths(12); // Start date is 12 months before the current date + } else { + startDate = YearMonth.of(date.getYear(), 1).atDay(1); // Start date is the first day of the specified year + } + + for (int i = 0; i < 12; i++) { + YearMonth yearMonth = YearMonth.from(startDate.plusMonths(i + 1)); + LocalDate firstOfMonth = yearMonth.atDay(1); + LocalDate lastOfMonth = yearMonth.atEndOfMonth(); + + // Ensure we don't go beyond the current date for last 12 months + if (isLast12Months && lastOfMonth.isAfter(currentDate)) { + lastOfMonth = currentDate; + } + revenues[i] = this.calculateTotalRevenue(firstOfMonth, lastOfMonth); + } + return revenues; + } + @Override @Secured({"ROLE_ADMIN", "ROLE_EMPLOYEE"}) public void deleteInstance(Integer integer) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 52c5807..7cf08c9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: application: - name: spring-prometheus-demo + name: online-store management: endpoints: web: