diff --git a/README.md b/README.md index ac06c24..18d28d1 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # QualityLab Pro-API RESTful for internal laboratory quality control. [![Docker Image CI/CD](https://github.com/LabGraphTeam/LabGraph-Back-End/actions/workflows/backend-deploy.yml/badge.svg?branch=master)](https://github.com/LabGraphTeam/LabGraph-Back-End/actions/workflows/backend-deploy.yml) -

- -Em desenvolvimento -

## Technologies @@ -22,39 +18,33 @@ monitoring and controlling the quality of their processes. This API provides end control standards, test results, statistical analyses, and other activities essential for ensuring the accuracy and reliability of laboratory data. -## Implemented functionalities - -The API efficiently manages package insert values and test values, offering simple and intuitive CRUD operations. - ## Project Structure ``` -. ├── .github/workflows # GitHub Actions workflow configurations -├── src -│ ├── main -│ │ ├── java/leonardo/labutilities/qualitylabpro -│ │ │ ├── configs # Application configurations -│ │ │ │ ├── date # Date/time configurations -│ │ │ │ ├── docs # API documentation configs -│ │ │ │ ├── rest # REST configurations -│ │ │ │ └── security # Security configurations -│ │ │ ├── constants # Constant definitions -│ │ │ ├── controllers # REST controllers -│ │ │ ├── dtos # Data Transfer Objects -│ │ │ ├── entities # Domain entities -│ │ │ ├── enums # Enumerations -│ │ │ ├── repositories # Data access layer -│ │ │ ├── services # Business logic -│ │ │ └── utils # Utility classes -│ │ └── resources -│ │ ├── db/migration # Flyway migrations -│ │ └── application*.properties -│ └── test -│ └── java # Test classes -├── database # Database scripts -├── nginx # Nginx configurations -└── docker-compose*.yml # Docker compose files +├── src/ +│ ├── main/ +│ │ ├── java/leonardo/labutilities/qualitylabpro/ +│ │ │ ├── configs/ # Application configurations +│ │ │ │ ├── date/ # Date/time configurations +│ │ │ │ ├── docs/ # API documentation +│ │ │ │ ├── rest/ # REST configurations +│ │ │ │ └── security/ # Security settings +│ │ │ ├── controllers/ # REST endpoints +│ │ │ ├── dtos/ # Data Transfer Objects +│ │ │ ├── entities/ # Domain entities +│ │ │ ├── repositories/ # Data access layer +│ │ │ ├── services/ # Business logic +│ │ │ └── utils/ # Helper classes +│ │ └── resources/ +│ │ ├── db/migration/ # Flyway migrations +│ │ └── application.properties +│ └── test/ +│ └── java/ # Test classes +├── database/ # Database scripts +├── nginx/ # Nginx configurations +├── docker-compose.yml # Docker compose files +└── pom.xml # Maven configuration ``` ### Key Components: @@ -93,7 +83,7 @@ You can view the workflow configurations in the `.github/workflows` directory. Run the command below in Git Bash or Terminal to clone the repository: ``` -git clone https://github.com/LeonardoMeireles55/QualityLabPro.git +git clone https://github.com/LabGraphTeam/LabGraph-Back-End.git ``` #### Step 2. Running with docker-compose @@ -101,7 +91,7 @@ git clone https://github.com/LeonardoMeireles55/QualityLabPro.git In the project root directory, run the command: ``` -docker-compose up or docker compose up +docker compose -f docker-compose-dev.yml up --build ``` ## Usage @@ -128,48 +118,6 @@ For even more detailed test output: ./mvnw test -X ``` -### With Docker - -When running with docker-compose, you can view test output in real-time: - -```bash -docker-compose logs -f app -``` - -To see test execution during build: - -```bash -docker-compose up --build --force-recreate -``` - -## Services - -### CoagulationAnalyticsService - -Handles analytic related to coagulation tests. - -### BiochemistryAnalyticsService - -Handles analytic related to biochemistry tests. - -### HematologyAnalyticsService - -Handles analytic related to hematology tests. - -## Controllers - -### CoagulationAnalyticsController - -Manages endpoints for coagulation analytic. - -### BiochemistryAnalyticsController - -Manages endpoints for biochemistry analytic. - -### HematologyAnalyticsController - -Manages endpoints for hematology analytic. - ## React Recharts.js Front-end Screenshot 2024-12-06 at 18 01 35 @@ -177,12 +125,15 @@ Manages endpoints for hematology analytic. ## Contributing 1. Fork the repository. -2. Create a new branch (`git checkout -b feature-branch`). +2. Create a new branch (`git checkout -b feature/branch`). 3. Make your changes. 4. Commit your changes (`git commit -m 'Add some feature'`). -5. Push to the branch (`git push origin feature-branch`). +5. Push to the branch (`git push origin feature/branch`). 6. Open a pull request. +## Misc +[![DigitalOcean Referral Badge](https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%203.svg)](https://www.digitalocean.com/?refcode=c961dfd401d8&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge) + ## License This project is licensed under the GNU General Public License v3.0 (GPL-3.0) - see the [LICENSE](LICENSE) file for diff --git a/docker-compose-db-only.yml b/docker-compose-db.yml similarity index 100% rename from docker-compose-db-only.yml rename to docker-compose-db.yml diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsController.java b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AbstractAnalyticsController.java similarity index 91% rename from src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsController.java rename to src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AbstractAnalyticsController.java index a53a6e7..fd16e0c 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsController.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AbstractAnalyticsController.java @@ -3,7 +3,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import leonardo.labutilities.qualitylabpro.dtos.analytics.AnalyticsDTO; import leonardo.labutilities.qualitylabpro.dtos.analytics.MeanAndStdDeviationDTO; -import leonardo.labutilities.qualitylabpro.services.analytics.AnalyticHelperService; +import leonardo.labutilities.qualitylabpro.services.analytics.AbstractAnalyticHelperService; import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -26,9 +26,9 @@ @SecurityRequirement(name = "bearer-key") @RequestMapping("/generic-analytics") @RestController() -public abstract class AnalyticsController extends AnalyticsHelperController { +public abstract class AbstractAnalyticsController extends AnalyticsHelperController { - protected AnalyticsController(AnalyticHelperService analyticHelperService) { + protected AbstractAnalyticsController(AbstractAnalyticHelperService analyticHelperService) { super(analyticHelperService); } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsHelperController.java b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsHelperController.java index 34da6f3..2b13567 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsHelperController.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/AnalyticsHelperController.java @@ -5,7 +5,7 @@ import leonardo.labutilities.qualitylabpro.dtos.analytics.GroupedMeanAndStdByLevelDTO; import leonardo.labutilities.qualitylabpro.dtos.analytics.GroupedResultsByLevelDTO; import leonardo.labutilities.qualitylabpro.dtos.analytics.UpdateAnalyticsMeanDTO; -import leonardo.labutilities.qualitylabpro.services.analytics.AnalyticHelperService; +import leonardo.labutilities.qualitylabpro.services.analytics.AbstractAnalyticHelperService; import org.springdoc.core.annotations.ParameterObject; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -27,9 +27,9 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; public class AnalyticsHelperController { - private final AnalyticHelperService analyticHelperService; + private final AbstractAnalyticHelperService analyticHelperService; - public AnalyticsHelperController(AnalyticHelperService analyticHelperService) { + public AnalyticsHelperController(AbstractAnalyticHelperService analyticHelperService) { this.analyticHelperService = analyticHelperService; } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/BiochemistryAnalyticsController.java b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/BiochemistryAnalyticsController.java index 0df32a5..0b0866e 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/BiochemistryAnalyticsController.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/BiochemistryAnalyticsController.java @@ -26,7 +26,7 @@ @SecurityRequirement(name = "bearer-key") @RequestMapping("biochemistry-analytics") @RestController() -public class BiochemistryAnalyticsController extends AnalyticsController { +public class BiochemistryAnalyticsController extends AbstractAnalyticsController { private static final List names = new AvailableBiochemistryAnalytics().availableBioAnalytics(); diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/CoagulationAnalyticsController.java b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/CoagulationAnalyticsController.java index 4e03b53..8087e50 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/CoagulationAnalyticsController.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/CoagulationAnalyticsController.java @@ -26,7 +26,7 @@ @SecurityRequirement(name = "bearer-key") @RequestMapping("coagulation-analytics") @RestController() -public class CoagulationAnalyticsController extends AnalyticsController { +public class CoagulationAnalyticsController extends AbstractAnalyticsController { private static final List names = new AvailableCoagulationAnalytics().availableCoagulationAnalytics(); diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/HematologyAnalyticsController.java b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/HematologyAnalyticsController.java index a4c6f70..6b0e617 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/HematologyAnalyticsController.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/controllers/analytics/HematologyAnalyticsController.java @@ -26,7 +26,7 @@ @SecurityRequirement(name = "bearer-key") @RequestMapping("/hematology-analytics") @RestController() -public class HematologyAnalyticsController extends AnalyticsController { +public class HematologyAnalyticsController extends AbstractAnalyticsController { private static final List names = new AvailableHematologyAnalytics().availableHematologyAnalytics(); diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/entities/Analytic.java b/src/main/java/leonardo/labutilities/qualitylabpro/entities/Analytic.java index b272312..ff64429 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/entities/Analytic.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/entities/Analytic.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import leonardo.labutilities.qualitylabpro.dtos.analytics.AnalyticsDTO; import leonardo.labutilities.qualitylabpro.utils.components.RulesValidatorComponent; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import org.springframework.hateoas.RepresentationModel; @@ -11,64 +12,62 @@ @Getter @Setter +@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false) @Entity(name = "generic_analytics") public class Analytic extends RepresentationModel { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private LocalDateTime date; + @Column(name = "level_lot") + private String levelLot; + @Column(name = "test_lot") + private String testLot; + private String name; + private String level; + private double value; + private double mean; + private double sd; + @Column(name = "unit_value") + private String unitValue; + private String rules; + private String description; + @Transient + private RulesValidatorComponent rulesValidatorComponent; - LocalDateTime date; - @Column(name = "level_lot") - String levelLot; - @Column(name = "test_lot") - String testLot; - String name; - String level; - double value; - double mean; - double sd; - @Column(name = "unit_value") - String unitValue; - String rules; - String description; - @Transient - RulesValidatorComponent rulesValidatorComponent; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + public Analytic() {} - public Analytic() { - } + public Analytic(Long id, LocalDateTime date, String levelLot, String testLot, String name, + String level, double value, double mean, double sd, String unitValue, String rules, + String description, RulesValidatorComponent rulesValidatorComponent) { + this.id = id; + this.date = date; + this.levelLot = levelLot; + this.testLot = testLot; + this.name = name; + this.level = level; + this.value = value; + this.mean = mean; + this.sd = sd; + this.unitValue = unitValue; + this.rules = rules; + this.description = description; + this.rulesValidatorComponent = rulesValidatorComponent; + } - public Analytic(Long id, LocalDateTime date, String levelLot, String testLot, - String name, String level, double value, double mean, double sd, String unitValue, - String rules, String description, RulesValidatorComponent rulesValidatorComponent) { - this.id = id; - this.date = date; - this.levelLot = levelLot; - this.testLot = testLot; - this.name = name; - this.level = level; - this.value = value; - this.mean = mean; - this.sd = sd; - this.unitValue = unitValue; - this.rules = rules; - this.description = description; - this.rulesValidatorComponent = rulesValidatorComponent; - } - - public Analytic(AnalyticsDTO values, - RulesValidatorComponent rulesValidatorComponent) { - this.date = values.date(); - this.levelLot = values.level_lot(); - this.testLot = values.test_lot(); - this.name = values.name(); - this.level = values.level(); - this.value = values.value(); - this.mean = values.mean(); - this.sd = values.sd(); - this.unitValue = values.unit_value(); - this.rulesValidatorComponent = rulesValidatorComponent; - rulesValidatorComponent.validator(value, mean, sd); - this.rules = rulesValidatorComponent.getRules(); - this.description = rulesValidatorComponent.getDescription(); - } + public Analytic(AnalyticsDTO values, RulesValidatorComponent rulesValidatorComponent) { + this.date = values.date(); + this.levelLot = values.level_lot(); + this.testLot = values.test_lot(); + this.name = values.name(); + this.level = values.level(); + this.value = values.value(); + this.mean = values.mean(); + this.sd = values.sd(); + this.unitValue = values.unit_value(); + this.rulesValidatorComponent = rulesValidatorComponent; + rulesValidatorComponent.validator(value, mean, sd); + this.rules = rulesValidatorComponent.getRules(); + this.description = rulesValidatorComponent.getDescription(); + } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AnalyticHelperService.java b/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticHelperService.java similarity index 90% rename from src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AnalyticHelperService.java rename to src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticHelperService.java index d056fb4..2209546 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AnalyticHelperService.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticHelperService.java @@ -1,6 +1,10 @@ package leonardo.labutilities.qualitylabpro.services.analytics; -import leonardo.labutilities.qualitylabpro.dtos.analytics.*; +import leonardo.labutilities.qualitylabpro.dtos.analytics.AnalyticsDTO; +import leonardo.labutilities.qualitylabpro.dtos.analytics.GroupedMeanAndStdByLevelDTO; +import leonardo.labutilities.qualitylabpro.dtos.analytics.GroupedResultsByLevelDTO; +import leonardo.labutilities.qualitylabpro.dtos.analytics.GroupedValuesByLevelDTO; +import leonardo.labutilities.qualitylabpro.dtos.analytics.MeanAndStdDeviationDTO; import leonardo.labutilities.qualitylabpro.repositories.AnalyticsRepository; import leonardo.labutilities.qualitylabpro.services.email.EmailService; import leonardo.labutilities.qualitylabpro.utils.components.ControlRulesValidators; @@ -25,14 +29,14 @@ @Slf4j @Service -public abstract class AnalyticHelperService implements IAnalyticHelperService { +public abstract class AbstractAnalyticHelperService implements IAnalyticHelperService { private final AnalyticsRepository analyticsRepository; private final EmailService emailService; private final ControlRulesValidators controlRulesValidators; - protected AnalyticHelperService(AnalyticsRepository analyticsRepository, + protected AbstractAnalyticHelperService(AnalyticsRepository analyticsRepository, EmailService emailService, ControlRulesValidators controlRulesValidators) { this.analyticsRepository = analyticsRepository; this.emailService = emailService; @@ -40,7 +44,7 @@ protected AnalyticHelperService(AnalyticsRepository analyticsRepository, } // VALIDATION METHODS - private void validateResultsNotEmpty(List results, String message) { + private static void validateResultsNotEmpty(List results, String message) { if (results == null || results.isEmpty()) { throw new CustomGlobalErrorHandling.ResourceNotFoundException(message); } @@ -51,7 +55,7 @@ public boolean isAnalyticsNonExistent(AnalyticsDTO values) { values.name()); } - private boolean isRuleBroken(AnalyticsDTO analyticsDTO) { + private static boolean isRuleBroken(AnalyticsDTO analyticsDTO) { String rules = analyticsDTO.rules(); return ("+3s".equals(rules) || "-3s".equals(rules) || "-2s".equals(rules) || "+2s".equals(rules)); @@ -65,13 +69,13 @@ public void ensureNameExists(String name) { } - private List filterFailedRecords(List persistedRecords) { - return persistedRecords.stream().filter(this::isRuleBroken) - .filter(record -> !BLACK_LIST.contains(record.name())).toList(); + private static List filterFailedRecords(List persistedRecords) { + return persistedRecords.stream().filter(AbstractAnalyticHelperService::isRuleBroken) + .filter(analyticsDTO -> !BLACK_LIST.contains(analyticsDTO.name())).toList(); } @Async - private void processFailedRecordsNotification(List failedRecords) { + public void processFailedRecordsNotification(List failedRecords) { if (!failedRecords.isEmpty()) { try { var content = controlRulesValidators.validateRules(failedRecords); @@ -83,7 +87,7 @@ private void processFailedRecordsNotification(List failedRecords) } // STATISTICS METHODS - private MeanAndStdDeviationDTO computeStatistics(List values) { + private static MeanAndStdDeviationDTO computeStatistics(List values) { double sum = values.stream().mapToDouble(Double::doubleValue).sum(); int size = values.size(); double mean = sum / size; @@ -92,10 +96,44 @@ private MeanAndStdDeviationDTO computeStatistics(List values) { return new MeanAndStdDeviationDTO(mean, Math.sqrt(variance)); } - private List extractRecordValues(List records) { + private static List extractRecordValues(List records) { return records.stream().map(AnalyticsDTO::value).toList(); } + @Override + public List returnMeanAndStandardDeviationForGroups( + List records) { + return records.stream() + .map(group -> new GroupedMeanAndStdByLevelDTO(group.level(), Collections + .singletonList(computeStatistics(extractRecordValues(group.values()))))) + .toList(); + } + + @Cacheable(value = "meanAndStdDeviationCache", + key = "{#name, #level, #dateStart, #dateEnd, #pageable.pageNumber, #pageable.pageSize}") + public MeanAndStdDeviationDTO calculateMeanAndStandardDeviation(String name, String level, + LocalDateTime dateStart, LocalDateTime dateEnd, Pageable pageable) { + List values = + findAnalyticsByNameAndLevelAndDate(name, level, dateStart, dateEnd, pageable) + .stream().filter(this::isRecordValid).toList(); + return computeStatistics(extractRecordValues(values)); + } + + @Cacheable(value = "calculateGroupedMeanAndStandardDeviation", + key = "{#name, #level, #dateStart, #dateEnd, #pageable.pageNumber, #pageable.pageSize}") + public List calculateGroupedMeanAndStandardDeviation(String name, + LocalDateTime startDate, LocalDateTime endDate, Pageable pageable) { + List records = analyticsRepository + .findByNameAndDateBetweenGroupByLevel(name, startDate, endDate, pageable).stream() + .map(AnalyticMapper::toRecord).toList(); + var values = records.stream().collect(Collectors.groupingBy(AnalyticsDTO::level)).entrySet() + .stream() + .map(entry -> new GroupedValuesByLevelDTO(entry.getKey(), entry.getValue())) + .toList(); + + return returnMeanAndStandardDeviationForGroups(values); + } + // BUSINESS LOGIC METHODS public List findAnalyticsWithGroupedResults(String name, @@ -129,16 +167,6 @@ public List findGroupedAnalyticsByLevel(String name, } - - @Override - public List returnMeanAndStandardDeviationForGroups( - List records) { - return records.stream() - .map(group -> new GroupedMeanAndStdByLevelDTO(group.level(), Collections - .singletonList(computeStatistics(extractRecordValues(group.values()))))) - .toList(); - } - @Override public Page findAnalyticsByNameInAndDateBetweenWithLinks(List names, LocalDateTime dateStart, LocalDateTime dateEnd, Pageable pageable) { @@ -251,31 +279,6 @@ public void deleteAnalyticsById(Long id) { analyticsRepository.deleteById(id); } - @Cacheable(value = "meanAndStdDeviationCache", - key = "{#name, #level, #dateStart, #dateEnd, #pageable.pageNumber, #pageable.pageSize}") - public MeanAndStdDeviationDTO calculateMeanAndStandardDeviation(String name, String level, - LocalDateTime dateStart, LocalDateTime dateEnd, Pageable pageable) { - List values = - findAnalyticsByNameAndLevelAndDate(name, level, dateStart, dateEnd, pageable) - .stream().filter(this::isRecordValid).toList(); - return computeStatistics(extractRecordValues(values)); - } - - @Cacheable(value = "calculateGroupedMeanAndStandardDeviation", - key = "{#name, #level, #dateStart, #dateEnd, #pageable.pageNumber, #pageable.pageSize}") - public List calculateGroupedMeanAndStandardDeviation(String name, - LocalDateTime startDate, LocalDateTime endDate, Pageable pageable) { - List records = analyticsRepository - .findByNameAndDateBetweenGroupByLevel(name, startDate, endDate, pageable).stream() - .map(AnalyticMapper::toRecord).toList(); - var values = records.stream().collect(Collectors.groupingBy(AnalyticsDTO::level)).entrySet() - .stream() - .map(entry -> new GroupedValuesByLevelDTO(entry.getKey(), entry.getValue())) - .toList(); - - return returnMeanAndStandardDeviationForGroups(values); - } - public List findAnalyticsByNameIn(List names, Pageable pageable) { return analyticsRepository.findByNameIn(names, pageable).stream() .map(AnalyticMapper::toRecord).toList(); @@ -305,5 +308,4 @@ public List findAnalyticsByNameLevelAndDate(String name, String le return results; } - } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticService.java b/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticService.java index ad357c1..1d3acdc 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticService.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/services/analytics/AbstractAnalyticService.java @@ -9,7 +9,7 @@ import java.time.LocalDateTime; import java.util.List; -public abstract class AbstractAnalyticService extends AnalyticHelperService { +public abstract class AbstractAnalyticService extends AbstractAnalyticHelperService { public AbstractAnalyticService(AnalyticsRepository analyticsRepository, EmailService emailService, ControlRulesValidators controlRulesValidators) { diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/AuthenticationService.java b/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/AuthenticationService.java index ebc0976..585e6bb 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/AuthenticationService.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/AuthenticationService.java @@ -11,14 +11,14 @@ @Service public class AuthenticationService implements UserDetailsService { - private final UserRepository userRepository; + private final UserRepository userRepository; - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - var user = userRepository.getReferenceByUsername(username); - if (user == null) { - throw new UsernameNotFoundException("User not found: " + username); - } - return user; - } + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + var user = userRepository.getReferenceByUsername(username); + if (user == null) { + throw new UsernameNotFoundException("User not found: " + username); + } + return user; + } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/TokenService.java b/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/TokenService.java index 7c5286c..5cd9af6 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/TokenService.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/services/authentication/TokenService.java @@ -42,7 +42,7 @@ public String getSubject(String tokenJWT) { } } - private Instant dateExp() { + private static Instant dateExp() { return LocalDateTime.now().plusHours(1).atZone(ZoneId.systemDefault()).toInstant(); } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/services/email/EmailService.java b/src/main/java/leonardo/labutilities/qualitylabpro/services/email/EmailService.java index d4dedb2..8048a0b 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/services/email/EmailService.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/services/email/EmailService.java @@ -32,10 +32,10 @@ public class EmailService { private final JavaMailSender javaMailSender; @Value("${spring.mail.username}") - String emailFrom; + private String emailFrom; @Value("${email.to.send.list}") - String emailListString; + private String emailListString; private List emailList; @@ -87,7 +87,7 @@ public void sendHtmlEmail(EmailDTO emailDTO) { helper.setFrom(emailFrom); // Convert identifier list to InternetAddress array - InternetAddress[] internetAddresses = emailList.stream().map(emailAddress -> { + InternetAddress[] internetAddresses = emailList.stream().map((String emailAddress) -> { try { return new InternetAddress(emailAddress); } catch (AddressException e) { @@ -130,7 +130,7 @@ public void sendFailedAnalyticsNotification(List failedRecords, try { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setFrom(emailFrom); - InternetAddress[] internetAddresses = emailList.stream().map(email -> { + InternetAddress[] internetAddresses = emailList.stream().map((String email) -> { try { return new InternetAddress(email); } catch (AddressException e) { @@ -191,15 +191,15 @@ public void sendUserActionEmail(String actionType, String username, String email sendHtmlEmailWithoutBcc(new EmailDTO(email, subject, content)); } - private String createUserActionEmailContent(String actionType, String username, String email, - LocalDateTime date) { + private static String createUserActionEmailContent(String actionType, String username, + String email, LocalDateTime date) { String message = String.format( "

User %s - %s notification
Email: %s
Time: %s

", username, actionType, email, date); return String.format(HTML_TEMPLATE, message); } - private String buildEmailBody(String email) { + private static String buildEmailBody(String email) { return String.format("%n%n%s%n%nBest regards,%nLabGraph Team", email); } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/services/users/UserService.java b/src/main/java/leonardo/labutilities/qualitylabpro/services/users/UserService.java index 523184e..f570af8 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/services/users/UserService.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/services/users/UserService.java @@ -49,8 +49,7 @@ public void recoverPassword(String username, String email) { var user = userRepository.existsByUsernameAndEmail(username, email); if (!user) { - throw new CustomGlobalErrorHandling.UserNotFoundException( - "User not or invalid arguments"); + throw new CustomGlobalErrorHandling.UserNotFoundException(); } String temporaryPassword = passwordRecoveryTokenManager.generateTemporaryPassword(); @@ -90,13 +89,13 @@ private TokenJwtDTO authenticateAndGenerateToken(User credential, String passwor public User signUp(String username, String email, String password) { - var user = - new User(username, BCryptEncoderComponent.encrypt(password), email, UserRoles.USER); - if (userRepository.existsByUsernameOrEmail(email, email)) { throw new CustomGlobalErrorHandling.UserAlreadyExistException(); } + var user = + new User(username, BCryptEncoderComponent.encrypt(password), email, UserRoles.USER); + try { emailService.notifyUserSignup(user.getUsername(), user.getEmail(), LocalDateTime.now()); } catch (Exception e) { @@ -124,8 +123,11 @@ public TokenJwtDTO signIn(String identifier, String password) { public void updateUserPassword(String name, String email, String password, String newPassword) { var oldPass = userRepository.getReferenceByUsernameAndEmail(name, email); - if (!BCryptEncoderComponent.decrypt(password, oldPass.getPassword()) - || BCryptEncoderComponent.decrypt(newPassword, oldPass.getPassword())) { + boolean oldPasswordMatches = + BCryptEncoderComponent.decrypt(password, oldPass.getPassword()); + boolean newPasswordMatches = + BCryptEncoderComponent.decrypt(newPassword, oldPass.getPassword()); + if (!oldPasswordMatches || newPasswordMatches) { log.error("PasswordNotMatches. {}, {}", name, email); throw new CustomGlobalErrorHandling.PasswordNotMatchesException(); } else { diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/BCryptEncoderComponent.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/BCryptEncoderComponent.java index da62223..0fe9076 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/BCryptEncoderComponent.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/BCryptEncoderComponent.java @@ -6,13 +6,13 @@ @Component public class BCryptEncoderComponent { - public static Boolean decrypt(String pass, String password) { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - return passwordEncoder.matches(pass, password); - } + public static Boolean decrypt(String pass, String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(pass, password); + } - public static String encrypt(String password) { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - return passwordEncoder.encode(password); - } + public static String encrypt(String password) { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/ControlRulesValidators.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/ControlRulesValidators.java index ad1bdad..8492002 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/ControlRulesValidators.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/ControlRulesValidators.java @@ -13,12 +13,12 @@ @Component public class ControlRulesValidators { - private final AnalyticsRepository analyticsRepository; - private static final int RULE_3S_MULTIPLIER = 3; private static final int RULE_4_1S_CONSECUTIVE = 4; private static final int RULE_10X_CONSECUTIVE = 10; + private final AnalyticsRepository analyticsRepository; + public ControlRulesValidators(AnalyticsRepository analyticsRepository) { this.analyticsRepository = analyticsRepository; } @@ -42,19 +42,21 @@ public String validateRules(List analytics) { continue; } - var analyticsRecords = analyticsRepository - .findLast10ByNameAndLevel(analytic.name(), analytic.level()).stream() - .filter(record -> !AnalyticsBlackList.BLACK_LIST.contains(record.name())) - .toList(); + var analyticsRecords = + analyticsRepository.findLast10ByNameAndLevel(analytic.name(), analytic.level()) + .stream().filter(analyticsRecord -> !AnalyticsBlackList.BLACK_LIST + .contains(analyticsRecord.name())) + .toList(); var mean = analyticsRecords.getFirst().mean(); var stdDev = analyticsRecords.getFirst().sd(); var values = analyticsRecords.stream().map(AnalyticsDTO::value).toList(); - var lastAnalyticsRecords = analyticsRepository - .findLastByNameAndLevel(analytic.name(), analytic.level()).stream() - .filter(record -> !AnalyticsBlackList.BLACK_LIST.contains(record.name())) - .toList(); + var lastAnalyticsRecords = + analyticsRepository.findLastByNameAndLevel(analytic.name(), analytic.level()) + .stream().filter(analyticsEntry -> !AnalyticsBlackList.BLACK_LIST + .contains(analyticsEntry.name())) + .toList(); var lastMean = lastAnalyticsRecords.getFirst().mean(); var lastStdDev = lastAnalyticsRecords.getFirst().sd(); @@ -78,8 +80,12 @@ public String validateRules(List analytics) { if (rule10x(values, mean, stdDev)) { errors.append(String.format(ERROR_MESSAGE_TEMPLATE, "10x", analytic.name(), - analytic.level(), "Ten consecutive measurements on same side of mean", - "Systematic Error. Review calibration, reagent stability, and instrument maintenance. Recalibrate if necessary.")); + analytic.level(), + """ + Ten consecutive measurements on same side of mean + Systematic Error. Review calibration, reagent stability, and instrument + maintenance. Recalibrate if necessary. + """)); reportedViolations.add(violationKey); } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/PasswordRecoveryTokenManager.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/PasswordRecoveryTokenManager.java index 7861607..1550e94 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/PasswordRecoveryTokenManager.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/PasswordRecoveryTokenManager.java @@ -6,26 +6,26 @@ @Component public class PasswordRecoveryTokenManager { - static final HashMap stringHashMap = new HashMap<>(); + private static final HashMap stringHashMap = new HashMap<>(); - public String generateTemporaryPassword() { - return java.util.UUID.randomUUID().toString(); - } + public String generateTemporaryPassword() { + return java.util.UUID.randomUUID().toString(); + } - public void generateAndStoreToken(String email, String password) { - String hashedPassword = generateRecoveryToken(email, password); - stringHashMap.put(hashedPassword, email); - } + public void generateAndStoreToken(String email, String password) { + String hashedPassword = generateRecoveryToken(email, password); + stringHashMap.put(hashedPassword, email); + } - public String retrieveEmailFromToken(String hashedPassword) { - return stringHashMap.get(hashedPassword); - } + public String retrieveEmailFromToken(String hashedPassword) { + return stringHashMap.get(hashedPassword); + } - public boolean isRecoveryTokenValid(String Token, String email) { - return stringHashMap.get(Token).equals(email); - } + public boolean isRecoveryTokenValid(String token, String email) { + return stringHashMap.get(token).equals(email); + } - private String generateRecoveryToken(String email, String password) { - return BCryptEncoderComponent.encrypt(email + password); - } + private static String generateRecoveryToken(String email, String password) { + return BCryptEncoderComponent.encrypt(email + password); + } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/RulesValidatorComponent.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/RulesValidatorComponent.java index 3ee12e9..f5cc8ad 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/RulesValidatorComponent.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/RulesValidatorComponent.java @@ -7,22 +7,28 @@ @Component public class RulesValidatorComponent { - String description; - String rules; + private String description; + private String rules; - public void validator(Double value, Double mean, Double sd) { - double[] thresholds = {mean + sd, mean + 2 * sd, mean + 3 * sd, mean - sd, mean - 2 * sd, mean - 3 * sd}; - String[] descriptions = {"Approved", "Approved", "Failed", "Approved", "Approved", "Failed"}; - String[] rules = {"+1s", "+2s", "+3s", "-1s", "-2s", "-3s"}; + public void validator(Double value, Double mean, Double sd) { + double[] thresholds = + {mean + sd, mean + 2 * sd, mean + 3 * sd, mean - sd, mean - 2 * sd, mean - 3 * sd}; + String[] descriptions = + {"Approved", "Approved", "Failed", "Approved", "Approved", "Failed"}; + String[] rules = {"+1s", "+2s", "+3s", "-1s", "-2s", "-3s"}; - for (int i = 2; i >= 0; i--) { - if (value >= thresholds[i] || value <= thresholds[i + 3]) { - this.description = descriptions[i]; - this.rules = value >= thresholds[i] ? rules[i] : rules[i + 3]; - return; - } - } - this.description = "Approved"; - this.rules = "Average"; - } -} \ No newline at end of file + for (int i = 2; i >= 0; i--) { + if (value >= thresholds[i] || value <= thresholds[i + 3]) { + this.description = descriptions[i]; + if (value >= thresholds[i]) { + this.rules = rules[i]; + } else { + this.rules = rules[i + 3]; + } + return; + } + } + this.description = "Approved"; + this.rules = "Average"; + } +} diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/StringToLocalDateTimeConverter.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/StringToLocalDateTimeConverter.java index d63175c..d327e25 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/StringToLocalDateTimeConverter.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/components/StringToLocalDateTimeConverter.java @@ -47,7 +47,7 @@ public LocalDateTime convert(String source) { throw new IllegalArgumentException("Unable to parse date: " + source, lastException); } - private String sanitizeDate(String date) { + private static String sanitizeDate(String date) { return date.trim().replaceAll("--", "-") // Fix double dashes .replaceAll("\\s+", " ") // Fix multiple spaces .replaceAll("T\\s", "T") // Fix space after T diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/constants/EmailTemplate.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/constants/EmailTemplate.java index c7be1bf..a01bff8 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/constants/EmailTemplate.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/constants/EmailTemplate.java @@ -16,44 +16,49 @@ public class EmailTemplate { """; public static final String EMAIL_SUBJECT_PREFIX = "LabGraph - "; public static final String HTML_TEMPLATE = "%s"; - public static final String TABLE_STYLE = """ - - - - - - - - - - - - - - %s - -
NameLevelValueExpected ValueRulesStatusDate
- """; - public static final String TABLE_ROW = """ - - %s - %s - %s - %s - %s - %s - %s - """; - public static final String ANALYTICS_WARNING_HEADER = """ -

- ⚠️ Quality Control Alert: Westgard violations -

-

- The following laboratory control measurements have triggered quality control violations based on - Westgard multi-rules. These violations may indicate systematic or random errors in the analytical process: -

- """; + public static final String TABLE_STYLE = + """ + + + + + + + + + + + + + + %s + +
NameLevelValueExpected ValueRulesStatusDate
+ """; + public static final String TABLE_ROW = + """ + + %s + %s + %s + %s + %s + %s + %s + """; + public static final String ANALYTICS_WARNING_HEADER = + """ +

+ ⚠️ Quality Control Alert: Westgard violations +

+

+ The following laboratory control measurements have triggered quality control violations based on + Westgard multi-rules. These violations may indicate systematic or random errors in the analytical process: +

+ """; public static final String LAST_ANALYTICS_PARAGRAPH = """ -

Please take the necessary actions to address these issues.

- """; -} \ No newline at end of file +

Please take the necessary actions to address these issues.

+ """; +} diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/ApiError.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/ApiError.java index 8ce335e..aad8db6 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/ApiError.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/ApiError.java @@ -10,27 +10,27 @@ @Getter public class ApiError { - private final LocalDateTime timestamp; - private final int status; - private final String error; - private final String message; - private final String path; - private List details; + private final LocalDateTime timestamp; + private final int status; + private final String error; + private final String message; + private final String path; + private List details; - public ApiError(HttpStatus status, String message, String path) { - this.timestamp = LocalDateTime.now(); - this.status = status.value(); - this.error = status.getReasonPhrase(); - this.message = message; - this.path = path; - this.details = new ArrayList<>(); - } + public ApiError(HttpStatus status, String message, String path) { + this.timestamp = LocalDateTime.now(); + this.status = status.value(); + this.error = status.getReasonPhrase(); + this.message = message; + this.path = path; + this.details = new ArrayList<>(); + } - public void setDetails(List details) { - this.details = details; - } + public void setDetails(List details) { + this.details = new ArrayList<>(details); + } - public void addValidationErrors(Map validationErrors) { - validationErrors.forEach((field, message) -> this.details.add(field + ": " + message)); - } + public void addValidationErrors(Map validationErrors) { + validationErrors.forEach((field, message) -> this.details.add(field + ": " + message)); + } } diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/CustomGlobalErrorHandling.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/CustomGlobalErrorHandling.java index 5c22bc4..d62f522 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/CustomGlobalErrorHandling.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/exception/CustomGlobalErrorHandling.java @@ -25,7 +25,7 @@ public class CustomGlobalErrorHandling { public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex, HttpServletRequest request) { Map errors = ex.getBindingResult().getFieldErrors().stream() - .collect(Collectors.toMap(FieldError::getField, error -> { + .collect(Collectors.toMap(FieldError::getField, (FieldError error) -> { error.getDefaultMessage(); return error.getDefaultMessage(); })); @@ -164,19 +164,13 @@ public UserAlreadyExistException() { public static class UserNotFoundException extends RuntimeException { public UserNotFoundException() { - super(); - } - - public UserNotFoundException(String message) { - super(message); + super("User not found - Invalid credentials or user does not exist"); } } public static class RecoveryTokenInvalidException extends RuntimeException { - private static final long serialVersionUID = 1L; - public RecoveryTokenInvalidException() { - super("Recovery token is invalid or expired"); + super("Token invalid - Recovery token is invalid or expired"); } public RecoveryTokenInvalidException(String message) { diff --git a/src/main/java/leonardo/labutilities/qualitylabpro/utils/mappers/AnalyticMapper.java b/src/main/java/leonardo/labutilities/qualitylabpro/utils/mappers/AnalyticMapper.java index da12f04..fe847a1 100644 --- a/src/main/java/leonardo/labutilities/qualitylabpro/utils/mappers/AnalyticMapper.java +++ b/src/main/java/leonardo/labutilities/qualitylabpro/utils/mappers/AnalyticMapper.java @@ -5,41 +5,32 @@ import leonardo.labutilities.qualitylabpro.utils.components.RulesValidatorComponent; public class AnalyticMapper { - public static final RulesValidatorComponent rulesValidatorComponent = new RulesValidatorComponent(); + public static final RulesValidatorComponent rulesValidatorComponent = + new RulesValidatorComponent(); - public static Analytic toEntity(AnalyticsDTO record) { - Analytic analytic = - new Analytic(); - analytic.setDate(record.date()); - analytic.setLevelLot(record.level_lot()); - analytic.setTestLot(record.test_lot()); - analytic.setName(record.name()); - analytic.setLevel(record.level()); - analytic.setValue(record.value()); - analytic.setMean(record.mean()); - analytic.setSd(record.sd()); - analytic.setUnitValue(record.unit_value()); - rulesValidatorComponent.validator(record.value(), record.mean(), record.sd()); - analytic.setRules(rulesValidatorComponent.getRules()); - analytic.setDescription(rulesValidatorComponent.getDescription()); + public static Analytic toEntity(AnalyticsDTO analyticsDTO) { + Analytic analytic = new Analytic(); + analytic.setDate(analyticsDTO.date()); + analytic.setLevelLot(analyticsDTO.level_lot()); + analytic.setTestLot(analyticsDTO.test_lot()); + analytic.setName(analyticsDTO.name()); + analytic.setLevel(analyticsDTO.level()); + analytic.setValue(analyticsDTO.value()); + analytic.setMean(analyticsDTO.mean()); + analytic.setSd(analyticsDTO.sd()); + analytic.setUnitValue(analyticsDTO.unit_value()); + rulesValidatorComponent.validator(analyticsDTO.value(), analyticsDTO.mean(), + analyticsDTO.sd()); + analytic.setRules(rulesValidatorComponent.getRules()); + analytic.setDescription(rulesValidatorComponent.getDescription()); - return analytic; - } + return analytic; + } - public static AnalyticsDTO toRecord(Analytic analytic) { - return new AnalyticsDTO( - analytic.getId(), - analytic.getDate(), - analytic.getLevelLot(), - analytic.getTestLot(), - analytic.getName(), - analytic.getLevel(), - analytic.getValue(), - analytic.getMean(), - analytic.getSd(), - analytic.getUnitValue(), - analytic.getRules(), - analytic.getDescription() - ); - } + public static AnalyticsDTO toRecord(Analytic analytic) { + return new AnalyticsDTO(analytic.getId(), analytic.getDate(), analytic.getLevelLot(), + analytic.getTestLot(), analytic.getName(), analytic.getLevel(), analytic.getValue(), + analytic.getMean(), analytic.getSd(), analytic.getUnitValue(), analytic.getRules(), + analytic.getDescription()); + } } diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 35c0f8c..1f265e9 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -7,15 +7,13 @@ server.error.include-stacktrace=never # =============================== # = LOGGING CONFIGURATION # =============================== -logging.level.leonardo=DEBUG +logging.level.leonardo=TRACE # =============================== # = MANAGEMENT CONFIGURATION # =============================== -management.endpoints.web.exposure.include=health -management.endpoint.health.show-details=never -management.health.ssl.enabled=false -management.health.email.enabled=false +management.endpoints.web.exposure.include=* +management.endpoint.health.show-details=always # =============================== # = DATABASE CONFIGURATION diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index d687599..866a791 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -9,7 +9,7 @@ server.error.include-stacktrace=never # =============================== # = LOGGING CONFIGURATION # =============================== -logging.level.leonardo=DEBUG +logging.level.leonardo=INFO spring.mail.properties.mail.debug=true # =============================== diff --git a/src/test/java/leonardo/labutilities/qualitylabpro/ControlApplicationTests.java b/src/test/java/leonardo/labutilities/qualitylabpro/ControlApplicationTests.java index 8c73641..d62486c 100644 --- a/src/test/java/leonardo/labutilities/qualitylabpro/ControlApplicationTests.java +++ b/src/test/java/leonardo/labutilities/qualitylabpro/ControlApplicationTests.java @@ -2,13 +2,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.test.context.ActiveProfiles; -@EnableCaching -@EnableSpringDataWebSupport( - pageSerializationMode = EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO) + @SpringBootTest @ActiveProfiles("test") class ControlApplicationTests { diff --git a/src/test/java/leonardo/labutilities/qualitylabpro/repositories/UserRepositoryTest.java b/src/test/java/leonardo/labutilities/qualitylabpro/repositories/UserRepositoryTest.java index d223823..65b817f 100644 --- a/src/test/java/leonardo/labutilities/qualitylabpro/repositories/UserRepositoryTest.java +++ b/src/test/java/leonardo/labutilities/qualitylabpro/repositories/UserRepositoryTest.java @@ -20,58 +20,58 @@ @ActiveProfiles("test") class UserRepositoryTest { - @Autowired - UserRepository userRepository; + @Autowired + UserRepository userRepository; - @BeforeEach - void clearDatabase(@Autowired Flyway flyway) { - flyway.clean(); - flyway.migrate(); - } + @BeforeEach + void clearDatabase(@Autowired Flyway flyway) { + flyway.clean(); + flyway.migrate(); + } - public void setupTestData() { - var user = new User("UserTest", BCryptEncoderComponent.encrypt("12345"), "leo@hotmail.com", - UserRoles.USER); + public void setupTestData() { + var user = new User("UserTest", BCryptEncoderComponent.encrypt("12345"), "leo@hotmail.com", + UserRoles.USER); - userRepository.save(user); - } + userRepository.save(user); + } - @Test - @DisplayName("return 200 when user is exists") - @Transactional - void findByLoginUserDataBaseIsUserExists() { - setupTestData(); - var userNotNull = userRepository.getReferenceByUsername("UserTest"); - assertThat(userNotNull).isNotNull(); - } + @Test + @DisplayName("return 200 when user is exists") + @Transactional + void findByLoginUserDataBaseIsUserExists() { + setupTestData(); + var userNotNull = userRepository.getReferenceByUsername("UserTest"); + assertThat(userNotNull).isNotNull(); + } - @Test - @DisplayName("return null when user is empty") - @Transactional - void findByLoginUserDataBaseIsUserNotExists() { - var userEmpty = userRepository.getReferenceByUsername(""); - assertThat(userEmpty).isNull(); - } + @Test + @DisplayName("return null when user is empty") + @Transactional + void findByLoginUserDataBaseIsUserNotExists() { + var userEmpty = userRepository.getReferenceByUsername(""); + assertThat(userEmpty).isNull(); + } - @Test - @DisplayName("return True when update passwords successful") - @Transactional - void setPasswordWhereByUsername() { - setupTestData(); - String username = "UserTest"; - String oldPassword = "12345"; - String newPassword = "249195Leo@@"; + @Test + @DisplayName("return True when update passwords successful") + @Transactional + void setPasswordWhereByUsername() { + setupTestData(); + String username = "UserTest"; + String oldPassword = "12345"; + String newPassword = "249195Leo@@"; - var userWithOldPassword = - userRepository.getReferenceByUsernameAndEmail("UserTest", "leo@hotmail.com"); + var userWithOldPassword = + userRepository.getReferenceByUsernameAndEmail("UserTest", "leo@hotmail.com"); - userRepository.setPasswordWhereByUsername(username, newPassword); + userRepository.setPasswordWhereByUsername(username, newPassword); - var userWithNewPassword = - userRepository.getReferenceByUsernameAndEmail("UserTest", "leo@hotmail.com"); + var userWithNewPassword = + userRepository.getReferenceByUsernameAndEmail("UserTest", "leo@hotmail.com"); - assertThat(BCryptEncoderComponent.decrypt(oldPassword, userWithOldPassword.getPassword()) - || BCryptEncoderComponent.decrypt(newPassword, userWithNewPassword.getPassword())) - .isTrue(); - } + assertThat(BCryptEncoderComponent.decrypt(oldPassword, userWithOldPassword.getPassword()) + || BCryptEncoderComponent.decrypt(newPassword, userWithNewPassword.getPassword())) + .isTrue(); + } } diff --git a/src/test/java/leonardo/labutilities/qualitylabpro/services/AnalyticHelperServiceTests.java b/src/test/java/leonardo/labutilities/qualitylabpro/services/AnalyticHelperServiceTests.java index 9b18150..2b66c6c 100644 --- a/src/test/java/leonardo/labutilities/qualitylabpro/services/AnalyticHelperServiceTests.java +++ b/src/test/java/leonardo/labutilities/qualitylabpro/services/AnalyticHelperServiceTests.java @@ -5,11 +5,10 @@ import leonardo.labutilities.qualitylabpro.dtos.analytics.UpdateAnalyticsMeanDTO; import leonardo.labutilities.qualitylabpro.entities.Analytic; import leonardo.labutilities.qualitylabpro.repositories.AnalyticsRepository; -import leonardo.labutilities.qualitylabpro.services.analytics.AnalyticHelperService; +import leonardo.labutilities.qualitylabpro.services.analytics.AbstractAnalyticHelperService; import leonardo.labutilities.qualitylabpro.services.email.EmailService; import leonardo.labutilities.qualitylabpro.utils.components.ControlRulesValidators; import leonardo.labutilities.qualitylabpro.utils.components.RulesValidatorComponent; -import leonardo.labutilities.qualitylabpro.utils.constants.AvailableBiochemistryAnalytics; import leonardo.labutilities.qualitylabpro.utils.exception.CustomGlobalErrorHandling; import leonardo.labutilities.qualitylabpro.utils.mappers.AnalyticMapper; import org.junit.jupiter.api.BeforeEach; @@ -32,12 +31,10 @@ @ExtendWith(MockitoExtension.class) class AnalyticHelperServiceTests { - private static final List ANALYTICS_NAME_LIST = - new AvailableBiochemistryAnalytics().availableBioAnalytics(); @Mock private AnalyticsRepository analyticsRepository; @Mock - private AnalyticHelperService analyticHelperService; + private AbstractAnalyticHelperService analyticHelperService; @Mock private EmailService emailService; @Mock @@ -46,8 +43,8 @@ class AnalyticHelperServiceTests { @BeforeEach void setUp() { try (AutoCloseable closeable = MockitoAnnotations.openMocks(this)) { - analyticHelperService = new AnalyticHelperService(analyticsRepository, emailService, - controlRulesValidators) { + analyticHelperService = new AbstractAnalyticHelperService(analyticsRepository, + emailService, controlRulesValidators) { @Override public List findAnalyticsByNameAndLevel(Pageable pageable, @@ -71,29 +68,9 @@ public List findAnalyticsByNameAndLevelAndDate(String name, } } - // @Test - // public void findAllAnalyticsByLevel() { - // var mockPageable = PageRequest.of(0, 10); - // var mockLevel = "PCCC1"; - // var mockList = ANALYTICS_NAME_LIST; - // LocalDateTime startDate = LocalDateTime.of(2024, 1, 1, 0, 0); - // LocalDateTime endDate = LocalDateTime.of(2024, 1, 2, 0, 0); - // - // List expectedRecords = - // createDateRangeRecords().stream().map(AnalyticMapper::toEntity).toList(); - // Page - // when(analyticsRepository.findByNameInAndLevelAndDateBetween(mockList, mockLevel, startDate, - // endDate, mockPageable)) - // .thenReturn(expectedRecords); - // - // analyticHelperService.findAnalyticsByNameInByLevelBaseMethod(mockList, mockLevel, startDate, - // endDate, mockPageable); - // verify(analyticsRepository).findByNameInAndLevelAndDateBetween(mockList, mockLevel, - // startDate, endDate, mockPageable); - // } @Test - public void updateAnalyticsMean() { + void updateAnalyticsMean() { var mockDto = new UpdateAnalyticsMeanDTO("Glucose", "PCCC1", "076587", 1.0); analyticHelperService.updateAnalyticsMeanByNameAndLevelAndLevelLot(mockDto.name(), mockDto.level(), mockDto.levelLot(), mockDto.mean());