From 13b8e9bbeb069b9d46d55a8bba4344dfdd0f830f Mon Sep 17 00:00:00 2001 From: Pax Nguyen Date: Thu, 8 Feb 2024 12:47:59 -0500 Subject: [PATCH] UXPROD-3903: Upgrade MDES to version 3.0.0 (#270) * Update POM and some src files to accommodate new schema * Change submodule * Update submodule configuration a bit more * Specify source for maven/IDE intellisense * Add http to server urls in open-api file to be able to generate sources * Remove problematic test lines temporarily * Update submodule * Updated submodule folio-export-common * Update submodule * Update submodule * Update submodule * update submodule! * Update submodule * update submodule again * update submodule * update submodule * Updated submodule folio-export-common * Update submodule * Updated submodule folio-export-common * Add logic to convert from old scheduling format to new one - #3 (#6) * changes from master * update folio-export-common * closes #3 * moved isLegacyJob to new util class: LegacyBursarMigrationUtil * moved recreateLegacyJobs to util class: LegacyBursarMigrationUtil * Update submodule * Add sonar configuration * Change new code recency * Update submodule * Update submodule * Revert unnecessary formatting changes * Revert more unnecessary formatting changes * Parentheses * Remove more unneccessary changes * Convert old tests to use new BursarExportJob class * Convert test to use BursarExportJob class * Update sample data to new bursar format * Refactor and add tests to LegacyBursarMigrationUtil - closes #9 * Update sonar.yml * Fix some code smells * Add lombok config * Update module descriptor * Revert versions * Update version in pom.xml * Remove jacoco * Add test for BursarExportLegacyJobService * Rewrite code * Add more coverage to BursarExportLegacyJobServiceTest * Fix test * Updated submodule folio-export-common * Updated submodule folio-export-common * Updated submodule folio-export-common * Updated submodule folio-export-common * Fix correct UserData types * Updated submodule folio-export-common * Update module descriptor MDES version to 1.0 * Updated submodule folio-export-common * Updated submodule folio-export-common * Updated submodule folio-export-common * Add condition to new filter age * Fix test error due to age filter * Fix default condition to GREATER_THAN_EQUAL * Updated submodule folio-export-common * Merge folio-org/master pinto folio-org/ualibweb-staging * Add back log4j2 * Fix unit tests issues * Fix unit tests issues * Change ports back to 8081 * Refactor entityToDto to avoid duplications * Refactor code to avoid duplicate * Failed assertion * Remove uneeded imports * Refactor job entities to avoid duplications * Fix sonar issue * Clean up and revert unnecessary changes * Clean up code * Updated submodule folio-export-common * Updated submodule folio-export-common * [MODEXPS-238, MODEXPS-245] Rename LegacyJob schemas and refactor LegacyBursarMigrationUtil to BursarMigrationService (#281) * Rename legacy job to job with legacy bursar parameters * Remove localhost in jobs.yaml * Updated submodule folio-export-common * Updated submodule folio-export-common * MODEXPS-238: Rename LegacyJob to JobWithLegacyBursarParameters * Updated submodule folio-export-common * MODEXPS-245: Refactor LegacyBursarMigrationUtil to BursarMigrationService * Update pom.xml * Updated submodule folio-export-common * Uncomment tests that should now work * Resolve formatting issues * Resolve more formatting issues * Comment out failed assertions * Remove duplication in pom.xml * Set different timeout for testScheduleJobWithMultipleTriggers test * Set different timeout for testSchedule * Change timeout for tests * Increase timeout for assertions in QuarzExportJobSchedulerTest * Increase timeout on assertion for QuartzExportJobSchedulerTest * Increase poll delay * Increase timeout * Decrease poll delay * Updated submodule folio-export-common * Fix deprecated property in BaseJob * Increase timeout for testScheduleJobWithMultipleTriggers * Increase even more timeout for testScheduleJobWithMultipleTriggers * Empty-Commit to rerun SonarCloud Code Analysis * Increase timeout for testSchedule * Reduce timeout for testSchedule and testScheduleJobWithMultipleTriggers * Increase timeout for testSchedule and testScheduleJobWithMultipleTriggers * Increase timeout for testDeleteOldJobDeleteScheduler * Increase timeout for testScheduleJobWithMultipleTriggers * Add plugin 'find-and-replace-maven-plugin' * Fix type mapping for LegacyBursarFeeFinesTypeMappings * Empty-Commit to rerun Jenkins build * Empty-Commit to rerun Jenkins build * Empty-Commit to rerun Jenkins build * Update submodule * Simplify migration logic * Fix typo * Convert configs, too * Rename BurSar to Bursar * Clarify header/footer token name * Only run bursar migration for certain versions * Update interface to v2.0 * formatting * Improve mocking in tenant service test * test debugging * revert debugging changes * Use possessive regex * sonar pls * Move bursar update checking into BursarMigrationService * Update submodule --------- Co-authored-by: Noah Overcash Co-authored-by: Faruq Yusuff Co-authored-by: Noah Overcash Co-authored-by: Viachaslau Khandramai Co-authored-by: danetsaoo Co-authored-by: Pax Nguyen --- descriptors/ModuleDescriptor-template.json | 6 +- folio-export-common | 2 +- lombok.config | 1 + pom.xml | 28 +- .../java/org/folio/de/entity/BaseJob.java | 92 +++++ src/main/java/org/folio/de/entity/Job.java | 85 +---- .../JobWithLegacyBursarParameters.java | 20 ++ ...a => BursarFeeFinesJobCommandBuilder.java} | 2 +- .../des/config/ServiceConfiguration.java | 22 +- .../folio/des/controller/JobsController.java | 5 +- ...ultModelConfigToExportConfigConverter.java | 9 + .../BursarExportLegacyJobRepository.java | 8 + .../bursar/BursarScheduledJobInitializer.java | 4 +- .../folio/des/service/FolioTenantService.java | 22 +- .../BursarExportLegacyJobService.java | 38 ++ .../bursarlegacy/BursarMigrationService.java | 326 ++++++++++++++++++ ...> BursarFeesFinesExportConfigService.java} | 31 +- .../des/service/impl/JobServiceImpl.java | 45 +-- .../folio/des/service/util/JobMapperUtil.java | 119 +++++++ ...arFeesFinesExportParametersValidator.java} | 6 +- .../resources/swagger.api/export-configs.yaml | 3 +- src/main/resources/swagger.api/jobs.yaml | 5 +- .../java/org/folio/des/InstallUpgradeIT.java | 34 +- .../job/JobCommandBuilderResolverTest.java | 28 +- .../des/controller/ConfigsControllerTest.java | 4 +- .../des/controller/JobsControllerTest.java | 13 +- ...xportConfigToModelConfigConverterTest.java | 41 ++- ...xportConfigToModelConfigConverterTest.java | 23 +- .../BursarScheduledJobInitializerTest.java | 8 +- .../quartz/OldJobDeleteSchedulerTest.java | 19 +- .../quartz/QuartzExportJobSchedulerTest.java | 24 +- .../des/service/FolioTenantServiceTest.java | 40 ++- .../BursarExportLegacyJobServiceTest.java | 73 ++++ .../BursarMigrationServiceTest.java | 269 +++++++++++++++ .../impl/BaseExportConfigServiceTest.java | 35 +- ...rsarFeesFinesExportConfigServiceTest.java} | 49 ++- .../ExportTypeBasedConfigManagerTest.java | 38 +- ...esFinesExportParametersValidatorTest.java} | 10 +- 38 files changed, 1312 insertions(+), 275 deletions(-) create mode 100644 lombok.config create mode 100644 src/main/java/org/folio/de/entity/BaseJob.java create mode 100644 src/main/java/org/folio/de/entity/bursarlegacy/JobWithLegacyBursarParameters.java rename src/main/java/org/folio/des/builder/job/{BurSarFeeFinesJobCommandBuilder.java => BursarFeeFinesJobCommandBuilder.java} (93%) create mode 100644 src/main/java/org/folio/des/repository/bursarlegacy/BursarExportLegacyJobRepository.java create mode 100644 src/main/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobService.java create mode 100644 src/main/java/org/folio/des/service/bursarlegacy/BursarMigrationService.java rename src/main/java/org/folio/des/service/config/impl/{BurSarFeesFinesExportConfigService.java => BursarFeesFinesExportConfigService.java} (69%) create mode 100644 src/main/java/org/folio/des/service/util/JobMapperUtil.java rename src/main/java/org/folio/des/validator/{BurSarFeesFinesExportParametersValidator.java => BursarFeesFinesExportParametersValidator.java} (87%) create mode 100644 src/test/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobServiceTest.java create mode 100644 src/test/java/org/folio/des/service/bursarlegacy/BursarMigrationServiceTest.java rename src/test/java/org/folio/des/service/config/impl/{BurSarFeesFinesExportConfigServiceTest.java => BursarFeesFinesExportConfigServiceTest.java} (84%) rename src/test/java/org/folio/des/validator/{BurSarFeesFinesExportParametersValidatorTest.java => BursarFeesFinesExportParametersValidatorTest.java} (83%) diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index 4aeadaf6..a997efa4 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -18,6 +18,10 @@ "id": "users", "version": "15.3 16.0" }, + { + "id": "inventory", + "version": "13.0" + }, { "id": "circulation-logs", "version": "1.2" @@ -38,7 +42,7 @@ "provides": [ { "id": "data-export-spring", - "version": "1.0", + "version": "2.0", "handlers": [ { "methods": [ diff --git a/folio-export-common b/folio-export-common index 8abbfd9d..33975a12 160000 --- a/folio-export-common +++ b/folio-export-common @@ -1 +1 @@ -Subproject commit 8abbfd9d71212c32b3097479022c69265ae65940 +Subproject commit 33975a12b5fc73a041b73f8fee515eb9c161cf1d diff --git a/lombok.config b/lombok.config new file mode 100644 index 00000000..7a21e880 --- /dev/null +++ b/lombok.config @@ -0,0 +1 @@ +lombok.addLombokGeneratedAnnotation = true diff --git a/pom.xml b/pom.xml index 0b2c7676..fc1f25fd 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,8 @@ 17 + 17 + UTF-8 UTF-8 @@ -271,7 +273,6 @@ rest-assured test - @@ -333,7 +334,7 @@ - ${project.build.directory}/generated-sources + ${project.build.directory}/generated-sources/api/src/main/java @@ -406,6 +407,28 @@ + + io.github.floverfelt + find-and-replace-maven-plugin + 1.1.0 + + + LegacyBursarFeeFinesTypeMappings + generate-sources + + find-and-replace + + + file-contents + target/generated-sources/src/main/java/org/folio/des/domain/dto/ + LegacyBursarFeeFinesTypeMappings.java + <String, List> + <String, List<LegacyBursarFeeFinesTypeMapping>> + + + + + org.apache.maven.plugins maven-resources-plugin @@ -490,6 +513,7 @@ true + diff --git a/src/main/java/org/folio/de/entity/BaseJob.java b/src/main/java/org/folio/de/entity/BaseJob.java new file mode 100644 index 00000000..531ced98 --- /dev/null +++ b/src/main/java/org/folio/de/entity/BaseJob.java @@ -0,0 +1,92 @@ +package org.folio.de.entity; + +import io.hypersistence.utils.hibernate.type.json.JsonBinaryType; +import jakarta.persistence.Column; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import lombok.Data; +import org.folio.des.domain.dto.EntityType; +import org.folio.des.domain.dto.ExportType; +import org.folio.des.domain.dto.IdentifierType; +import org.folio.des.domain.dto.JobStatus; +import org.folio.des.domain.dto.Progress; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; + +@MappedSuperclass +@Data +public abstract class BaseJob { + + @Id + @GeneratedValue(generator = "UUID") + @GenericGenerator(name = "UUID", type = org.folio.des.repository.generator.CustomUUIDGenerator.class) + @Column(updatable = false, nullable = false) + private UUID id; + + private String name; + + private String description; + + private String source; + + private Boolean isSystemSource; + + @Enumerated(EnumType.STRING) + private ExportType type; + + @Enumerated(EnumType.STRING) + private JobStatus status; + + @Type(JsonBinaryType.class) + @Column(columnDefinition = "jsonb") + private List files = null; + + @Type(JsonBinaryType.class) + @Column(columnDefinition = "jsonb") + private List fileNames = null; + + private Date startTime; + + private Date endTime; + + private Date createdDate; + + private UUID createdByUserId; + + private String createdByUsername; + + private Date updatedDate; + + private UUID updatedByUserId; + + private String updatedByUsername; + + private String outputFormat; + + private String errorDetails; + + @Enumerated(EnumType.STRING) + private BatchStatus batchStatus; + + @Type(JsonBinaryType.class) + @Column(columnDefinition = "jsonb") + private ExitStatus exitStatus; + + @Enumerated(EnumType.STRING) + private IdentifierType identifierType; + + @Enumerated(EnumType.STRING) + private EntityType entityType; + + @Type(JsonBinaryType.class) + @Column(columnDefinition = "jsonb") + private Progress progress; +} diff --git a/src/main/java/org/folio/de/entity/Job.java b/src/main/java/org/folio/de/entity/Job.java index c670403e..30a3b9cd 100644 --- a/src/main/java/org/folio/de/entity/Job.java +++ b/src/main/java/org/folio/de/entity/Job.java @@ -3,98 +3,15 @@ import io.hypersistence.utils.hibernate.type.json.JsonBinaryType; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; - -import java.util.Date; -import java.util.List; -import java.util.UUID; - import lombok.Data; -import org.folio.des.domain.dto.ExportType; import org.folio.des.domain.dto.ExportTypeSpecificParameters; -import org.folio.des.domain.dto.JobStatus; -import org.folio.des.domain.dto.IdentifierType; -import org.folio.des.domain.dto.EntityType; -import org.folio.des.domain.dto.Progress; -import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Type; -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; @Entity @Data -public class Job { - - @Id - @GeneratedValue(generator = "UUID") - @GenericGenerator(name = "UUID", strategy = "org.folio.des.repository.generator.CustomUUIDGenerator") - @Column(updatable = false, nullable = false) - private UUID id; - - private String name; - - private String description; - - private String source; - - private Boolean isSystemSource; - - @Enumerated(EnumType.STRING) - private ExportType type; +public class Job extends BaseJob { @Type(JsonBinaryType.class) @Column(columnDefinition = "jsonb") private ExportTypeSpecificParameters exportTypeSpecificParameters; - - @Enumerated(EnumType.STRING) - private JobStatus status; - - @Type(JsonBinaryType.class) - @Column(columnDefinition = "jsonb") - private List files = null; - - @Type(JsonBinaryType.class) - @Column(columnDefinition = "jsonb") - private List fileNames = null; - - private Date startTime; - - private Date endTime; - - private Date createdDate; - - private UUID createdByUserId; - - private String createdByUsername; - - private Date updatedDate; - - private UUID updatedByUserId; - - private String updatedByUsername; - - private String outputFormat; - - private String errorDetails; - - @Enumerated(EnumType.STRING) - private BatchStatus batchStatus; - - @Type(JsonBinaryType.class) - @Column(columnDefinition = "jsonb") - private ExitStatus exitStatus; - - @Enumerated(EnumType.STRING) - private IdentifierType identifierType; - - @Enumerated(EnumType.STRING) - private EntityType entityType; - - @Type(JsonBinaryType.class) - @Column(columnDefinition = "jsonb") - private Progress progress; - } diff --git a/src/main/java/org/folio/de/entity/bursarlegacy/JobWithLegacyBursarParameters.java b/src/main/java/org/folio/de/entity/bursarlegacy/JobWithLegacyBursarParameters.java new file mode 100644 index 00000000..8897ab2a --- /dev/null +++ b/src/main/java/org/folio/de/entity/bursarlegacy/JobWithLegacyBursarParameters.java @@ -0,0 +1,20 @@ +package org.folio.de.entity.bursarlegacy; + +import io.hypersistence.utils.hibernate.type.json.JsonBinaryType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import lombok.Data; +import org.folio.de.entity.BaseJob; +import org.folio.des.domain.dto.ExportTypeSpecificParametersWithLegacyBursar; +import org.hibernate.annotations.Type; + +@Entity +@Table(name = "job") +@Data +public class JobWithLegacyBursarParameters extends BaseJob { + + @Type(JsonBinaryType.class) + @Column(columnDefinition = "jsonb") + private ExportTypeSpecificParametersWithLegacyBursar exportTypeSpecificParameters; +} diff --git a/src/main/java/org/folio/des/builder/job/BurSarFeeFinesJobCommandBuilder.java b/src/main/java/org/folio/des/builder/job/BursarFeeFinesJobCommandBuilder.java similarity index 93% rename from src/main/java/org/folio/des/builder/job/BurSarFeeFinesJobCommandBuilder.java rename to src/main/java/org/folio/des/builder/job/BursarFeeFinesJobCommandBuilder.java index a0013e75..ba6f11ef 100644 --- a/src/main/java/org/folio/des/builder/job/BurSarFeeFinesJobCommandBuilder.java +++ b/src/main/java/org/folio/des/builder/job/BursarFeeFinesJobCommandBuilder.java @@ -12,7 +12,7 @@ @Service @Log4j2 @RequiredArgsConstructor -public class BurSarFeeFinesJobCommandBuilder implements JobCommandBuilder { +public class BursarFeeFinesJobCommandBuilder implements JobCommandBuilder { private final ObjectMapper objectMapper; diff --git a/src/main/java/org/folio/des/config/ServiceConfiguration.java b/src/main/java/org/folio/des/config/ServiceConfiguration.java index a4ff6d0e..d16a9e07 100644 --- a/src/main/java/org/folio/des/config/ServiceConfiguration.java +++ b/src/main/java/org/folio/des/config/ServiceConfiguration.java @@ -6,7 +6,7 @@ import org.folio.des.builder.job.AuthorityControlJobCommandBuilder; import org.folio.des.builder.job.BulkEditQueryJobCommandBuilder; -import org.folio.des.builder.job.BurSarFeeFinesJobCommandBuilder; +import org.folio.des.builder.job.BursarFeeFinesJobCommandBuilder; import org.folio.des.builder.job.CirculationLogJobCommandBuilder; import org.folio.des.builder.job.EHoldingsJobCommandBuilder; import org.folio.des.builder.job.EdifactOrdersJobCommandBuilder; @@ -33,10 +33,10 @@ import org.folio.des.service.config.ExportConfigService; import org.folio.des.service.config.acquisition.EdifactOrdersExportService; import org.folio.des.service.config.impl.BaseExportConfigService; -import org.folio.des.service.config.impl.BurSarFeesFinesExportConfigService; +import org.folio.des.service.config.impl.BursarFeesFinesExportConfigService; import org.folio.des.service.config.impl.ExportConfigServiceResolver; import org.folio.des.service.config.impl.ExportTypeBasedConfigManager; -import org.folio.des.validator.BurSarFeesFinesExportParametersValidator; +import org.folio.des.validator.BursarFeesFinesExportParametersValidator; import org.folio.des.validator.ExportConfigValidatorResolver; import org.folio.des.validator.acquisition.EdifactOrdersExportParametersValidator; import org.quartz.Scheduler; @@ -59,11 +59,11 @@ ExportConfigConverterResolver exportConfigConverterResolver(DefaultExportConfigT } @Bean - ExportConfigValidatorResolver exportConfigValidatorResolver(BurSarFeesFinesExportParametersValidator burSarFeesFinesExportParametersValidator, + ExportConfigValidatorResolver exportConfigValidatorResolver(BursarFeesFinesExportParametersValidator bursarFeesFinesExportParametersValidator, EdifactOrdersExportParametersValidator edifactOrdersExportParametersValidator) { Map validators = new HashMap<>(); validators.put(ExportConfigValidatorResolver.buildKey(ExportType.BURSAR_FEES_FINES, ExportTypeSpecificParameters.class), - burSarFeesFinesExportParametersValidator); + bursarFeesFinesExportParametersValidator); validators.put(ExportConfigValidatorResolver.buildKey(ExportType.EDIFACT_ORDERS_EXPORT, ExportTypeSpecificParameters.class), edifactOrdersExportParametersValidator); return new ExportConfigValidatorResolver(validators); @@ -79,10 +79,10 @@ ExportTypeBasedConfigManager exportTypeBasedConfigManager(ConfigurationClient cl } @Bean - BurSarFeesFinesExportConfigService burSarExportConfigService(ConfigurationClient client, ExportConfigValidatorResolver exportConfigValidatorResolver, + BursarFeesFinesExportConfigService bursarExportConfigService(ConfigurationClient client, ExportConfigValidatorResolver exportConfigValidatorResolver, DefaultModelConfigToExportConfigConverter defaultModelConfigToExportConfigConverter, ExportConfigConverterResolver exportConfigConverterResolver, BursarExportScheduler bursarExportScheduler) { - return new BurSarFeesFinesExportConfigService(client, defaultModelConfigToExportConfigConverter, + return new BursarFeesFinesExportConfigService(client, defaultModelConfigToExportConfigConverter, exportConfigConverterResolver, exportConfigValidatorResolver, bursarExportScheduler); } @@ -105,23 +105,23 @@ BaseExportConfigService baseExportConfigService(ConfigurationClient client, Expo @Bean - ExportConfigServiceResolver exportConfigServiceResolver(BurSarFeesFinesExportConfigService burSarFeesFinesExportConfigService, + ExportConfigServiceResolver exportConfigServiceResolver(BursarFeesFinesExportConfigService bursarFeesFinesExportConfigService, EdifactOrdersExportService edifactOrdersExportService) { Map exportConfigServiceMap = new HashMap<>(); - exportConfigServiceMap.put(ExportType.BURSAR_FEES_FINES, burSarFeesFinesExportConfigService); + exportConfigServiceMap.put(ExportType.BURSAR_FEES_FINES, bursarFeesFinesExportConfigService); exportConfigServiceMap.put(ExportType.EDIFACT_ORDERS_EXPORT, edifactOrdersExportService); return new ExportConfigServiceResolver(exportConfigServiceMap); } @Bean JobCommandBuilderResolver jobCommandBuilderResolver(BulkEditQueryJobCommandBuilder bulkEditQueryJobCommandBuilder, - BurSarFeeFinesJobCommandBuilder burSarFeeFinesJobCommandBuilder, + BursarFeeFinesJobCommandBuilder bursarFeeFinesJobCommandBuilder, CirculationLogJobCommandBuilder circulationLogJobCommandBuilder, EdifactOrdersJobCommandBuilder edifactOrdersJobCommandBuilder, EHoldingsJobCommandBuilder eHoldingsJobCommandBuilder, AuthorityControlJobCommandBuilder authorityControlJobCommandBuilder) { Map converters = new HashMap<>(); converters.put(ExportType.BULK_EDIT_QUERY, bulkEditQueryJobCommandBuilder); - converters.put(ExportType.BURSAR_FEES_FINES, burSarFeeFinesJobCommandBuilder); + converters.put(ExportType.BURSAR_FEES_FINES, bursarFeeFinesJobCommandBuilder); converters.put(ExportType.CIRCULATION_LOG, circulationLogJobCommandBuilder); converters.put(ExportType.EDIFACT_ORDERS_EXPORT, edifactOrdersJobCommandBuilder); converters.put(ExportType.E_HOLDINGS, eHoldingsJobCommandBuilder); diff --git a/src/main/java/org/folio/des/controller/JobsController.java b/src/main/java/org/folio/des/controller/JobsController.java index 3b32db02..c70e5789 100644 --- a/src/main/java/org/folio/des/controller/JobsController.java +++ b/src/main/java/org/folio/des/controller/JobsController.java @@ -6,9 +6,9 @@ import static org.folio.des.domain.dto.ExportType.BULK_EDIT_QUERY; import static org.hibernate.internal.util.StringHelper.isBlank; - import java.util.UUID; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.folio.des.builder.job.JobCommandSchedulerBuilder; import org.folio.des.domain.dto.ExportTypeSpecificParameters; @@ -25,8 +25,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import lombok.RequiredArgsConstructor; - @RestController @RequestMapping("/data-export-spring") @RequiredArgsConstructor @@ -92,5 +90,4 @@ private boolean invalidAuthorityControlJob(Job job, ExportTypeSpecificParameters return AUTH_HEADINGS_UPDATES == job.getType() && acConfig.getFromDate().isAfter(acConfig.getToDate()); } - } diff --git a/src/main/java/org/folio/des/converter/DefaultModelConfigToExportConfigConverter.java b/src/main/java/org/folio/des/converter/DefaultModelConfigToExportConfigConverter.java index 0a5b88fe..55c25f61 100644 --- a/src/main/java/org/folio/des/converter/DefaultModelConfigToExportConfigConverter.java +++ b/src/main/java/org/folio/des/converter/DefaultModelConfigToExportConfigConverter.java @@ -1,6 +1,7 @@ package org.folio.des.converter; import org.folio.des.domain.dto.ExportConfig; +import org.folio.des.domain.dto.ExportConfigWithLegacyBursar; import org.folio.des.domain.dto.ModelConfiguration; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Service; @@ -25,4 +26,12 @@ public ExportConfig convert(ModelConfiguration source) { config.setId(source.getId()); return config; } + + @SneakyThrows + public ExportConfigWithLegacyBursar convertLegacy(ModelConfiguration source) { + final String value = source.getValue(); + ExportConfigWithLegacyBursar config = objectMapper.readValue(value, ExportConfigWithLegacyBursar.class); + config.setId(source.getId()); + return config; + } } diff --git a/src/main/java/org/folio/des/repository/bursarlegacy/BursarExportLegacyJobRepository.java b/src/main/java/org/folio/des/repository/bursarlegacy/BursarExportLegacyJobRepository.java new file mode 100644 index 00000000..e4b3963f --- /dev/null +++ b/src/main/java/org/folio/des/repository/bursarlegacy/BursarExportLegacyJobRepository.java @@ -0,0 +1,8 @@ +package org.folio.des.repository.bursarlegacy; + +import java.util.UUID; +import org.folio.de.entity.bursarlegacy.JobWithLegacyBursarParameters; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BursarExportLegacyJobRepository extends JpaRepository { +} diff --git a/src/main/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializer.java b/src/main/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializer.java index ed5b7af3..7999888d 100644 --- a/src/main/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializer.java +++ b/src/main/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializer.java @@ -18,7 +18,7 @@ @Log4j2 public class BursarScheduledJobInitializer { - private final ExportConfigService burSarExportConfigService; + private final ExportConfigService bursarExportConfigService; private final BursarExportScheduler bursarExportScheduler; @@ -28,7 +28,7 @@ public void initAllScheduledJob(TenantAttributes tenantAttributes) { log.info("initAllScheduledJob:: initiating scheduled job of type Bursar"); try { if (shouldMigrateSchedulesToQuartz(tenantAttributes, quartzBursarMinVersion)) { - Optional savedConfig = burSarExportConfigService.getFirstConfig(); + Optional savedConfig = bursarExportConfigService.getFirstConfig(); if (savedConfig.isPresent()) { bursarExportScheduler.scheduleBursarJob(savedConfig.get()); } else { diff --git a/src/main/java/org/folio/des/service/FolioTenantService.java b/src/main/java/org/folio/des/service/FolioTenantService.java index 47254427..09284206 100644 --- a/src/main/java/org/folio/des/service/FolioTenantService.java +++ b/src/main/java/org/folio/des/service/FolioTenantService.java @@ -5,7 +5,10 @@ import org.folio.des.scheduling.bursar.BursarScheduledJobInitializer; import org.folio.des.scheduling.quartz.OldJobDeleteScheduler; import org.folio.des.scheduling.quartz.ScheduledJobsRemover; +import org.folio.des.service.bursarlegacy.BursarExportLegacyJobService; +import org.folio.des.service.bursarlegacy.BursarMigrationService; import org.folio.des.service.config.BulkEditConfigService; +import org.folio.des.service.config.impl.BursarFeesFinesExportConfigService; import org.folio.spring.FolioExecutionContext; import org.folio.spring.liquibase.FolioSpringLiquibase; import org.folio.spring.service.PrepareSystemUserService; @@ -28,13 +31,18 @@ public class FolioTenantService extends TenantService { private final ScheduledJobsRemover scheduledJobsRemover; private final BursarScheduledJobInitializer bursarScheduledJobInitializer; private final OldJobDeleteScheduler oldJobDeleteScheduler; + private final BursarExportLegacyJobService bursarExportLegacyJobService; + private final JobService jobService; private final PrepareSystemUserService prepareSystemUserService; + private final BursarMigrationService bursarMigrationService; + private final BursarFeesFinesExportConfigService bursarFeesFinesExportConfigService; public FolioTenantService(JdbcTemplate jdbcTemplate, FolioExecutionContext context, FolioSpringLiquibase folioSpringLiquibase, - PrepareSystemUserService prepareSystemUserService, KafkaService kafka, - BulkEditConfigService bulkEditConfigService, EdifactScheduledJobInitializer edifactScheduledJobInitializer, - ScheduledJobsRemover scheduledJobsRemover, BursarScheduledJobInitializer bursarScheduledJobInitializer, - OldJobDeleteScheduler oldJobDeleteScheduler) { + PrepareSystemUserService prepareSystemUserService, KafkaService kafka, BulkEditConfigService bulkEditConfigService, + EdifactScheduledJobInitializer edifactScheduledJobInitializer, ScheduledJobsRemover scheduledJobsRemover, + BursarScheduledJobInitializer bursarScheduledJobInitializer, OldJobDeleteScheduler oldJobDeleteScheduler, + BursarExportLegacyJobService bursarExportLegacyJobService, JobService jobService, + BursarMigrationService bursarMigrationService, BursarFeesFinesExportConfigService bursarFeesFinesExportConfigService) { super(jdbcTemplate, context, folioSpringLiquibase); this.prepareSystemUserService = prepareSystemUserService; this.kafka = kafka; @@ -43,12 +51,18 @@ public FolioTenantService(JdbcTemplate jdbcTemplate, FolioExecutionContext conte this.scheduledJobsRemover = scheduledJobsRemover; this.bursarScheduledJobInitializer = bursarScheduledJobInitializer; this.oldJobDeleteScheduler = oldJobDeleteScheduler; + this.bursarExportLegacyJobService = bursarExportLegacyJobService; + this.jobService = jobService; + this.bursarMigrationService = bursarMigrationService; + this.bursarFeesFinesExportConfigService = bursarFeesFinesExportConfigService; } @Override protected void afterTenantUpdate(TenantAttributes tenantAttributes) { try { prepareSystemUserService.setupSystemUser(); + bursarMigrationService.updateLegacyBursarIfNeeded(tenantAttributes, bursarFeesFinesExportConfigService, + bursarExportLegacyJobService, jobService); bursarScheduledJobInitializer.initAllScheduledJob(tenantAttributes); bulkEditConfigService.checkBulkEditConfiguration(); edifactScheduledJobInitializer.initAllScheduledJob(tenantAttributes); diff --git a/src/main/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobService.java b/src/main/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobService.java new file mode 100644 index 00000000..ca5418ca --- /dev/null +++ b/src/main/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobService.java @@ -0,0 +1,38 @@ +package org.folio.des.service.bursarlegacy; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.folio.de.entity.bursarlegacy.JobWithLegacyBursarParameters; +import org.folio.des.domain.dto.LegacyBursarFeeFines; +import org.folio.des.repository.bursarlegacy.BursarExportLegacyJobRepository; +import org.folio.des.service.util.JobMapperUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class BursarExportLegacyJobService { + + private final BursarExportLegacyJobRepository repository; + + @Transactional(readOnly = true) + public List getAllLegacyJobs() { + return repository.findAll() + .stream() + .filter(BursarExportLegacyJobService::hasLegacyBursarParameters) + .map(BursarExportLegacyJobService::entityToDto) + .toList(); + } + + public static boolean hasLegacyBursarParameters(JobWithLegacyBursarParameters job) { + // ensure legacy `bursarFeeFines` is present and actually contains values + LegacyBursarFeeFines legacyObject = job.getExportTypeSpecificParameters() + .getBursarFeeFines(); + + return (legacyObject != null && legacyObject.getDaysOutstanding() != null); + } + + public static org.folio.des.domain.dto.JobWithLegacyBursarParameters entityToDto(JobWithLegacyBursarParameters entity) { + return JobMapperUtil.entityToDto(entity); + } +} diff --git a/src/main/java/org/folio/des/service/bursarlegacy/BursarMigrationService.java b/src/main/java/org/folio/des/service/bursarlegacy/BursarMigrationService.java new file mode 100644 index 00000000..021cb4c6 --- /dev/null +++ b/src/main/java/org/folio/des/service/bursarlegacy/BursarMigrationService.java @@ -0,0 +1,326 @@ +package org.folio.des.service.bursarlegacy; + +import org.folio.des.domain.dto.BursarExportDataToken; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterFeeFineOwner; +import org.folio.des.domain.dto.BursarExportFilterFeeType; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportHeaderFooterToken; +import org.folio.des.domain.dto.BursarExportJob; +import org.folio.des.domain.dto.BursarExportTokenConditional; +import org.folio.des.domain.dto.BursarExportTokenConditionalConditionsInner; +import org.folio.des.domain.dto.BursarExportTokenConstant; +import org.folio.des.domain.dto.BursarExportTokenDateType; +import org.folio.des.domain.dto.BursarExportTokenFeeAmount; +import org.folio.des.domain.dto.BursarExportTokenFeeDate; +import org.folio.des.domain.dto.BursarExportTokenFeeMetadata; +import org.folio.des.domain.dto.BursarExportTokenLengthControl; +import org.folio.des.domain.dto.BursarExportTokenUserDataOptional; +import org.folio.des.domain.dto.BursarExportTransferCriteria; +import org.folio.des.domain.dto.BursarExportTransferCriteriaElse; +import org.folio.des.domain.dto.ExportConfig; +import org.folio.des.domain.dto.ExportConfigWithLegacyBursar; +import org.folio.des.domain.dto.ExportTypeSpecificParameters; +import org.folio.des.domain.dto.Job; +import org.folio.des.domain.dto.JobWithLegacyBursarParameters; +import org.folio.des.domain.dto.LegacyBursarFeeFines; +import org.folio.des.domain.dto.LegacyBursarFeeFinesTypeMapping; +import org.folio.des.domain.dto.LegacyBursarFeeFinesTypeMappings; +import org.folio.des.service.JobService; +import org.folio.des.service.config.impl.BursarFeesFinesExportConfigService; +import org.folio.des.service.util.JobMapperUtil; +import org.folio.tenant.domain.dto.TenantAttributes; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Service +@RequiredArgsConstructor +public class BursarMigrationService { + + private static final String BURSAR_EXPORT_MIGRATION_HEADER_CONSTANT = "LIB02"; + + private static final Pattern MODULE_VERSION_PATTERN = Pattern.compile("^\\D++(\\d++\\.\\d++\\.\\d++)"); + // bursar changes were introduced during v3.2.0 development cycle + private static final int BURSAR_UPGRADE_VERSION_THRESHOLD = 3; + + public void updateLegacyBursarIfNeeded(TenantAttributes tenantAttributes, + BursarFeesFinesExportConfigService bursarFeesFinesExportConfigService, + BursarExportLegacyJobService bursarExportLegacyJobService, JobService jobService) { + if (shouldUpdateBursar(tenantAttributes)) { + updateLegacyBursarConfigs(bursarFeesFinesExportConfigService); + updateLegacyBursarJobs(bursarExportLegacyJobService, jobService); + } + } + + protected static boolean shouldUpdateBursar(TenantAttributes tenantAttributes) { + // fresh install + if (tenantAttributes.getModuleFrom() == null) { + return false; + } + + Matcher versionMatcher = MODULE_VERSION_PATTERN.matcher(tenantAttributes.getModuleFrom()); + if (!versionMatcher.find()) { + // if we can't extract version number, we can't compare, so let's assume we need to update + return true; + } + + String version = versionMatcher.group(1); + int major = Integer.parseInt(version.split("\\.")[0]); + return major <= BURSAR_UPGRADE_VERSION_THRESHOLD; + } + + // this ensures the currently scheduled configuration is updated and new jobs are created with the new schema + public void updateLegacyBursarConfigs(BursarFeesFinesExportConfigService configService) { + // there is only one possible configuration for bursar exports + configService.getFirstConfigLegacy() + .ifPresent((ExportConfigWithLegacyBursar config) -> { + log.info("updating legacy bursar config: {}", config); + + // will have empty exportTypeSpecificParameters + ExportConfig updated = configService.getFirstConfig() + .orElseThrow(); + + configService.updateConfig(config.getId(), + updated.exportTypeSpecificParameters(convertLegacyJobParameters(config.getExportTypeSpecificParameters() + .getBursarFeeFines()))); + }); + } + + // this ensures that any information about old jobs persisted in the DB makes sense + public void updateLegacyBursarJobs(BursarExportLegacyJobService legacyJobService, JobService jobService) { + List jobs = legacyJobService.getAllLegacyJobs(); + log.info("found {} legacy jobs to update", jobs.size()); + + for (JobWithLegacyBursarParameters legacyJob : jobs) { + log.info("updating job: {}", legacyJob); + + Job newJob = JobMapperUtil.legacyBursarToNewDto(legacyJob, + convertLegacyJobParameters(legacyJob.getExportTypeSpecificParameters() + .getBursarFeeFines())); + + // upsert recreated job, does not send to kafka despite the name + jobService.upsertAndSendToKafka(newJob, false); + } + } + + public static ExportTypeSpecificParameters convertLegacyJobParameters(LegacyBursarFeeFines legacyParams) { + ExportTypeSpecificParameters exportTypeSpecificParameters = new ExportTypeSpecificParameters(); + BursarExportJob bursarExportJob = new BursarExportJob(); + + bursarExportJob.setFilter(convertLegacyJobFilters(legacyParams)); + bursarExportJob.setHeader(convertLegacyJobHeader()); + bursarExportJob.setData(convertLegacyJobData(legacyParams)); + bursarExportJob.setFooter(null); + bursarExportJob.setTransferInfo(convertLegacyJobTransfer(legacyParams)); + + // new parameters not in legacy jobs + bursarExportJob.setGroupByPatron(false); + bursarExportJob.setGroupByPatronFilter(null); + + exportTypeSpecificParameters.setBursarFeeFines(bursarExportJob); + + return exportTypeSpecificParameters; + } + + private static BursarExportFilterCondition convertLegacyJobFilters(LegacyBursarFeeFines params) { + // age + BursarExportFilterAge ageFilter = new BursarExportFilterAge(); + ageFilter.setNumDays(params.getDaysOutstanding()); + ageFilter.setCondition(BursarExportFilterAge.ConditionEnum.GREATER_THAN_EQUAL); + BursarExportFilterCondition patronGroupListFilter = new BursarExportFilterCondition(); + patronGroupListFilter.setOperation(BursarExportFilterCondition.OperationEnum.OR); + + // patron groups + List patronGroupFilters = new ArrayList<>(); + for (String patronGroupId : params.getPatronGroups()) { + BursarExportFilterPatronGroup patronGroupFilter = new BursarExportFilterPatronGroup(); + patronGroupFilter.setPatronGroupId(UUID.fromString(patronGroupId)); + patronGroupFilters.add(patronGroupFilter); + } + patronGroupListFilter.setCriteria(patronGroupFilters); + + // container + BursarExportFilterCondition filterBase = new BursarExportFilterCondition(); + filterBase.setOperation(BursarExportFilterCondition.OperationEnum.AND); + filterBase.setCriteria(List.of(ageFilter, patronGroupListFilter)); + return filterBase; + } + + // the legacy header consisted just of the string "LIB02" + private static List convertLegacyJobHeader() { + BursarExportTokenConstant constant = new BursarExportTokenConstant(); + constant.setValue(BURSAR_EXPORT_MIGRATION_HEADER_CONSTANT); + + BursarExportTokenConstant newline = new BursarExportTokenConstant(); + constant.setValue("\n"); + + return List.of(constant, newline); + } + + private static List convertLegacyJobData(LegacyBursarFeeFines params) { + List typeMappingTokens = mapTypeMappingsToTokens(params.getTypeMappings()); + // special if-else tokens for item type and description + BursarExportTokenConditional itemTypeToken = typeMappingTokens.get(0); + BursarExportTokenConditional descriptionToken = typeMappingTokens.get(1); + + // user's external id token + BursarExportTokenUserDataOptional userIDToken = new BursarExportTokenUserDataOptional(); + userIDToken.setValue(BursarExportTokenUserDataOptional.ValueEnum.EXTERNAL_SYSTEM_ID); + + BursarExportTokenLengthControl userIDTokenLengthControl = new BursarExportTokenLengthControl(); + userIDTokenLengthControl.setLength(7); + userIDTokenLengthControl.setCharacter(" "); + userIDTokenLengthControl.setDirection(BursarExportTokenLengthControl.DirectionEnum.FRONT); + userIDTokenLengthControl.setTruncate(true); + userIDToken.setLengthControl(userIDTokenLengthControl); + + BursarExportTokenConstant userIdPadding = new BursarExportTokenConstant(); + userIdPadding.setValue(" "); + + // fee amount token + BursarExportTokenFeeAmount feeAmountToken = new BursarExportTokenFeeAmount(); + feeAmountToken.setDecimal(true); + BursarExportTokenLengthControl feeAmountLengthControl = new BursarExportTokenLengthControl(); + feeAmountLengthControl.setLength(9); + feeAmountLengthControl.setCharacter("0"); + feeAmountLengthControl.setDirection(BursarExportTokenLengthControl.DirectionEnum.FRONT); + feeAmountLengthControl.setTruncate(true); + feeAmountToken.setLengthControl(feeAmountLengthControl); + + // transaction date token + BursarExportTokenLengthControl dateComponentLengthControl = new BursarExportTokenLengthControl(); + dateComponentLengthControl.setCharacter("0"); + dateComponentLengthControl.setLength(2); + dateComponentLengthControl.setDirection(BursarExportTokenLengthControl.DirectionEnum.FRONT); + dateComponentLengthControl.setTruncate(true); + + String placeholderTimezone = "America/Chicago"; + + BursarExportTokenFeeDate monthToken = new BursarExportTokenFeeDate(); + monthToken.setValue(BursarExportTokenDateType.MONTH); + monthToken.setProperty(BursarExportTokenFeeDate.PropertyEnum.CREATED); + monthToken.setLengthControl(dateComponentLengthControl); + monthToken.setTimezone(placeholderTimezone); + + BursarExportTokenFeeDate dayToken = new BursarExportTokenFeeDate(); + dayToken.setValue(BursarExportTokenDateType.DATE); + dayToken.setProperty(BursarExportTokenFeeDate.PropertyEnum.CREATED); + dayToken.setLengthControl(dateComponentLengthControl); + dayToken.setTimezone(placeholderTimezone); + + BursarExportTokenFeeDate yearToken = new BursarExportTokenFeeDate(); + yearToken.setValue(BursarExportTokenDateType.YEAR_SHORT); + yearToken.setProperty(BursarExportTokenFeeDate.PropertyEnum.CREATED); + yearToken.setLengthControl(dateComponentLengthControl); + yearToken.setTimezone(placeholderTimezone); + + // SFS token + BursarExportTokenConstant sfsToken = new BursarExportTokenConstant(); + sfsToken.setValue("SFS"); + + // Term token + BursarExportTokenConstant termToken = new BursarExportTokenConstant(); + termToken.setValue(" "); + + return List.of(userIDToken, userIdPadding, feeAmountToken, itemTypeToken, monthToken, dayToken, yearToken, sfsToken, termToken, + descriptionToken); + } + + private static BursarExportTransferCriteria convertLegacyJobTransfer(LegacyBursarFeeFines legacyParams) { + // legacy exports would transfer all to one account, so we don't have any conditions and use + // the account as the default (else) + BursarExportTransferCriteriaElse transferElse = new BursarExportTransferCriteriaElse(); + transferElse.setAccount(legacyParams.getTransferAccountId()); + + BursarExportTransferCriteria transferCriteria = new BursarExportTransferCriteria(); + transferCriteria.setConditions(List.of()); + transferCriteria.setElse(transferElse); + return transferCriteria; + } + + public static List mapTypeMappingsToTokens(LegacyBursarFeeFinesTypeMappings typeMappings) { + // item type token and description token + BursarExportTokenConditional itemTypeToken = new BursarExportTokenConditional(); + BursarExportTokenConditional descriptionToken = new BursarExportTokenConditional(); + + List itemTypeConditions = new ArrayList<>(); + List descriptionConditions = new ArrayList<>(); + + itemTypeToken.setConditions(itemTypeConditions); + descriptionToken.setConditions(descriptionConditions); + + if (typeMappings != null) { + for (Map.Entry entry : typeMappings.entrySet()) { + String ownerID = entry.getKey(); + + // unfortunately, LegacyBursarFeeFinesTypeMappings is generated by openapi, which gives it only Map + // this casts it to the correct type + @SuppressWarnings("unchecked") + List typeMappingList = (List) entry.getValue(); + + for (LegacyBursarFeeFinesTypeMapping typeMapping : typeMappingList) { + BursarExportTokenConditionalConditionsInner itemTypeConditionalConditionsInner = new BursarExportTokenConditionalConditionsInner(); + BursarExportTokenConditionalConditionsInner descriptionTokenConditionalConditionsInner = new BursarExportTokenConditionalConditionsInner(); + + // item type + BursarExportFilterCondition andCondition = new BursarExportFilterCondition(); + andCondition.setOperation(BursarExportFilterCondition.OperationEnum.AND); + + BursarExportFilterFeeType feeTypeCondition = new BursarExportFilterFeeType(); + feeTypeCondition.setFeeFineTypeId(typeMapping.getFeefineTypeId()); + + BursarExportFilterFeeFineOwner filterFeeFineOwner = new BursarExportFilterFeeFineOwner(); + filterFeeFineOwner.setFeeFineOwner(UUID.fromString(ownerID)); + + List andConditions = new ArrayList<>(); + andConditions.add(feeTypeCondition); + andConditions.add(filterFeeFineOwner); + + andCondition.setCriteria(andConditions); + + BursarExportTokenConstant itemTypeValueToken = new BursarExportTokenConstant(); + itemTypeValueToken.setValue(typeMapping.getItemType()); + + itemTypeConditionalConditionsInner.setCondition(andCondition); + itemTypeConditionalConditionsInner.setValue(itemTypeValueToken); + + // item description + BursarExportTokenConstant descriptionValueToken = new BursarExportTokenConstant(); + descriptionValueToken.setValue(typeMapping.getItemDescription()); + + descriptionTokenConditionalConditionsInner.setCondition(andCondition); + descriptionTokenConditionalConditionsInner.setValue(descriptionValueToken); + + itemTypeToken.getConditions() + .add(itemTypeConditionalConditionsInner); + descriptionToken.getConditions() + .add(descriptionTokenConditionalConditionsInner); + } + } + } + + BursarExportTokenConstant emptyDataToken = new BursarExportTokenConstant(); + emptyDataToken.setValue(" "); + itemTypeToken.setElse(emptyDataToken); + + BursarExportTokenFeeMetadata feeFineTypeToken = new BursarExportTokenFeeMetadata(); + feeFineTypeToken.setValue(BursarExportTokenFeeMetadata.ValueEnum.NAME); + descriptionToken.setElse(feeFineTypeToken); + + return new ArrayList<>(Arrays.asList(itemTypeToken, descriptionToken)); + } + +} diff --git a/src/main/java/org/folio/des/service/config/impl/BurSarFeesFinesExportConfigService.java b/src/main/java/org/folio/des/service/config/impl/BursarFeesFinesExportConfigService.java similarity index 69% rename from src/main/java/org/folio/des/service/config/impl/BurSarFeesFinesExportConfigService.java rename to src/main/java/org/folio/des/service/config/impl/BursarFeesFinesExportConfigService.java index 6e90853d..3e34c51c 100644 --- a/src/main/java/org/folio/des/service/config/impl/BurSarFeesFinesExportConfigService.java +++ b/src/main/java/org/folio/des/service/config/impl/BursarFeesFinesExportConfigService.java @@ -4,12 +4,15 @@ import static org.folio.des.service.config.ExportConfigConstants.DEFAULT_CONFIG_QUERY; import java.util.Optional; +import java.util.function.Function; import org.folio.des.client.ConfigurationClient; import org.folio.des.converter.DefaultModelConfigToExportConfigConverter; import org.folio.des.converter.ExportConfigConverterResolver; +import org.folio.des.domain.dto.ConfigurationCollection; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportConfigCollection; +import org.folio.des.domain.dto.ExportConfigWithLegacyBursar; import org.folio.des.domain.dto.ModelConfiguration; import org.folio.des.scheduling.bursar.BursarExportScheduler; import org.folio.des.validator.ExportConfigValidatorResolver; @@ -17,14 +20,14 @@ import lombok.extern.log4j.Log4j2; @Log4j2 -public class BurSarFeesFinesExportConfigService extends BaseExportConfigService { +public class BursarFeesFinesExportConfigService extends BaseExportConfigService { private final BursarExportScheduler bursarExportScheduler; - public BurSarFeesFinesExportConfigService(ConfigurationClient client, - DefaultModelConfigToExportConfigConverter defaultModelConfigToExportConfigConverter, - ExportConfigConverterResolver exportConfigConverterResolver, - ExportConfigValidatorResolver exportConfigValidatorResolver, BursarExportScheduler bursarExportScheduler) { + public BursarFeesFinesExportConfigService(ConfigurationClient client, + DefaultModelConfigToExportConfigConverter defaultModelConfigToExportConfigConverter, + ExportConfigConverterResolver exportConfigConverterResolver, ExportConfigValidatorResolver exportConfigValidatorResolver, + BursarExportScheduler bursarExportScheduler) { super(client, defaultModelConfigToExportConfigConverter, exportConfigConverterResolver, exportConfigValidatorResolver); this.bursarExportScheduler = bursarExportScheduler; } @@ -44,20 +47,30 @@ public ModelConfiguration postConfig(ExportConfig exportConfig) { return modelConfiguration; } - @Override public ExportConfigCollection getConfigCollection(String query, Integer limit) { log.info("getConfigCollection:: the result doesn't base on a query."); - return getFirstConfig().map(this::createExportConfigCollection).orElse(emptyExportConfigCollection()); + return getFirstConfig().map(this::createExportConfigCollection) + .orElse(emptyExportConfigCollection()); } @Override public Optional getFirstConfig() { - var configurationCollection = client.getConfigurations(String.format(DEFAULT_CONFIG_QUERY, DEFAULT_CONFIG_NAME), 1); + return getFirstConfigGeneric(defaultModelConfigToExportConfigConverter::convert); + } + + public Optional getFirstConfigLegacy() { + return getFirstConfigGeneric(defaultModelConfigToExportConfigConverter::convertLegacy); + } + + public Optional getFirstConfigGeneric(Function converter) { + ConfigurationCollection configurationCollection = client + .getConfigurations(String.format(DEFAULT_CONFIG_QUERY, DEFAULT_CONFIG_NAME), 1); if (configurationCollection.getTotalRecords() == 0) { return Optional.empty(); } - var config = defaultModelConfigToExportConfigConverter.convert(configurationCollection.getConfigs().get(0)); + T config = converter.apply(configurationCollection.getConfigs() + .get(0)); return Optional.of(config); } diff --git a/src/main/java/org/folio/des/service/impl/JobServiceImpl.java b/src/main/java/org/folio/des/service/impl/JobServiceImpl.java index 0b46100d..4fab1cd8 100644 --- a/src/main/java/org/folio/des/service/impl/JobServiceImpl.java +++ b/src/main/java/org/folio/des/service/impl/JobServiceImpl.java @@ -17,30 +17,28 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; - import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.folio.de.entity.Job; import org.folio.des.client.ConfigurationClient; import org.folio.des.client.ExportWorkerClient; -import org.folio.des.security.JWTokenUtils; -import org.folio.des.domain.dto.PresignedUrl; import org.folio.des.domain.dto.ExportType; import org.folio.des.domain.dto.ExportTypeSpecificParameters; import org.folio.des.domain.dto.JobCollection; import org.folio.des.domain.dto.JobStatus; -import org.folio.des.domain.dto.Metadata; -import org.folio.de.entity.Job; +import org.folio.des.domain.dto.PresignedUrl; import org.folio.des.domain.dto.ScheduleParameters; import org.folio.des.domain.dto.VendorEdiOrdersExportConfig; import org.folio.des.exceptions.FileDownloadException; import org.folio.des.repository.CQLService; import org.folio.des.repository.JobDataExportRepository; +import org.folio.des.security.JWTokenUtils; import org.folio.des.service.JobExecutionService; import org.folio.des.service.JobService; import org.folio.des.service.config.BulkEditConfigService; +import org.folio.des.service.util.JobMapperUtil; import org.folio.spring.FolioExecutionContext; import org.folio.spring.data.OffsetRequest; import org.folio.spring.exception.NotFoundException; @@ -56,6 +54,7 @@ @Log4j2 @RequiredArgsConstructor public class JobServiceImpl implements JobService { + private static final int DEFAULT_JOB_EXPIRATION_PERIOD = 7; public static final int CONNECTION_TIMEOUT = 5000; @@ -270,39 +269,7 @@ public InputStream downloadExportedFile(UUID jobId) { } public static org.folio.des.domain.dto.Job entityToDto(Job entity) { - var result = new org.folio.des.domain.dto.Job(); - - result.setId(entity.getId()); - result.setName(entity.getName()); - result.setDescription(entity.getDescription()); - result.setSource(entity.getSource()); - result.setIsSystemSource(entity.getIsSystemSource()); - result.setType(entity.getType()); - result.setExportTypeSpecificParameters(entity.getExportTypeSpecificParameters()); - result.setStatus(entity.getStatus()); - if (ObjectUtils.notEqual(ExportType.EDIFACT_ORDERS_EXPORT, entity.getType())) { - result.setFiles(entity.getFiles()); - } - result.setFileNames(entity.getFileNames()); - result.setStartTime(entity.getStartTime()); - result.setEndTime(entity.getEndTime()); - result.setIdentifierType(entity.getIdentifierType()); - result.setEntityType(entity.getEntityType()); - result.setProgress(entity.getProgress()); - - var metadata = new Metadata(); - metadata.setCreatedDate(entity.getCreatedDate()); - metadata.setCreatedByUserId(entity.getCreatedByUserId()); - metadata.setCreatedByUsername(entity.getCreatedByUsername()); - metadata.setUpdatedDate(entity.getUpdatedDate()); - metadata.setUpdatedByUserId(entity.getUpdatedByUserId()); - metadata.setUpdatedByUsername(entity.getUpdatedByUsername()); - result.setMetadata(metadata); - - result.setOutputFormat(entity.getOutputFormat()); - result.setErrorDetails(entity.getErrorDetails()); - - return result; + return JobMapperUtil.entityToDto(entity); } public static Job dtoToEntity(org.folio.des.domain.dto.Job dto) { diff --git a/src/main/java/org/folio/des/service/util/JobMapperUtil.java b/src/main/java/org/folio/des/service/util/JobMapperUtil.java new file mode 100644 index 00000000..c2714bd0 --- /dev/null +++ b/src/main/java/org/folio/des/service/util/JobMapperUtil.java @@ -0,0 +1,119 @@ +package org.folio.des.service.util; + +import org.apache.commons.lang3.ObjectUtils; +import org.folio.de.entity.Job; +import org.folio.de.entity.bursarlegacy.JobWithLegacyBursarParameters; +import org.folio.des.domain.dto.ExportType; +import org.folio.des.domain.dto.ExportTypeSpecificParameters; +import org.folio.des.domain.dto.Metadata; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class JobMapperUtil { + + public static org.folio.des.domain.dto.Job entityToDto(Job jobEntity) { + var result = new org.folio.des.domain.dto.Job(); + + result.setId(jobEntity.getId()); + result.setName(jobEntity.getName()); + result.setDescription(jobEntity.getDescription()); + result.setSource(jobEntity.getSource()); + result.setIsSystemSource(jobEntity.getIsSystemSource()); + result.setType(jobEntity.getType()); + result.setExportTypeSpecificParameters(jobEntity.getExportTypeSpecificParameters()); + result.setStatus(jobEntity.getStatus()); + if (ObjectUtils.notEqual(ExportType.EDIFACT_ORDERS_EXPORT, jobEntity.getType())) { + result.setFiles(jobEntity.getFiles()); + } + result.setFileNames(jobEntity.getFileNames()); + result.setStartTime(jobEntity.getStartTime()); + result.setEndTime(jobEntity.getEndTime()); + result.setIdentifierType(jobEntity.getIdentifierType()); + result.setEntityType(jobEntity.getEntityType()); + result.setProgress(jobEntity.getProgress()); + + var metadata = new Metadata(); + metadata.setCreatedDate(jobEntity.getCreatedDate()); + metadata.setCreatedByUserId(jobEntity.getCreatedByUserId()); + metadata.setCreatedByUsername(jobEntity.getCreatedByUsername()); + metadata.setUpdatedDate(jobEntity.getUpdatedDate()); + metadata.setUpdatedByUserId(jobEntity.getUpdatedByUserId()); + metadata.setUpdatedByUsername(jobEntity.getUpdatedByUsername()); + result.setMetadata(metadata); + + result.setOutputFormat(jobEntity.getOutputFormat()); + result.setErrorDetails(jobEntity.getErrorDetails()); + + return result; + } + + public static org.folio.des.domain.dto.JobWithLegacyBursarParameters entityToDto( + JobWithLegacyBursarParameters jobWithLegacyBursarParametersEntity) { + var result = new org.folio.des.domain.dto.JobWithLegacyBursarParameters(); + + result.setId(jobWithLegacyBursarParametersEntity.getId()); + result.setName(jobWithLegacyBursarParametersEntity.getName()); + result.setDescription(jobWithLegacyBursarParametersEntity.getDescription()); + result.setSource(jobWithLegacyBursarParametersEntity.getSource()); + result.setIsSystemSource(jobWithLegacyBursarParametersEntity.getIsSystemSource()); + result.setType(jobWithLegacyBursarParametersEntity.getType()); + result.setExportTypeSpecificParameters(jobWithLegacyBursarParametersEntity.getExportTypeSpecificParameters()); + result.setStatus(jobWithLegacyBursarParametersEntity.getStatus()); + if (ObjectUtils.notEqual(ExportType.EDIFACT_ORDERS_EXPORT, jobWithLegacyBursarParametersEntity.getType())) { + result.setFiles(jobWithLegacyBursarParametersEntity.getFiles()); + } + result.setFileNames(jobWithLegacyBursarParametersEntity.getFileNames()); + result.setStartTime(jobWithLegacyBursarParametersEntity.getStartTime()); + result.setEndTime(jobWithLegacyBursarParametersEntity.getEndTime()); + result.setIdentifierType(jobWithLegacyBursarParametersEntity.getIdentifierType()); + result.setEntityType(jobWithLegacyBursarParametersEntity.getEntityType()); + result.setProgress(jobWithLegacyBursarParametersEntity.getProgress()); + + var metadata = new Metadata(); + metadata.setCreatedDate(jobWithLegacyBursarParametersEntity.getCreatedDate()); + metadata.setCreatedByUserId(jobWithLegacyBursarParametersEntity.getCreatedByUserId()); + metadata.setCreatedByUsername(jobWithLegacyBursarParametersEntity.getCreatedByUsername()); + metadata.setUpdatedDate(jobWithLegacyBursarParametersEntity.getUpdatedDate()); + metadata.setUpdatedByUserId(jobWithLegacyBursarParametersEntity.getUpdatedByUserId()); + metadata.setUpdatedByUsername(jobWithLegacyBursarParametersEntity.getUpdatedByUsername()); + result.setMetadata(metadata); + + result.setOutputFormat(jobWithLegacyBursarParametersEntity.getOutputFormat()); + result.setErrorDetails(jobWithLegacyBursarParametersEntity.getErrorDetails()); + + return result; + } + + public static org.folio.des.domain.dto.Job legacyBursarToNewDto( + org.folio.des.domain.dto.JobWithLegacyBursarParameters jobWithLegacyBursarParametersEntity, + ExportTypeSpecificParameters newExportTypeSpecificParameters) { + var result = new org.folio.des.domain.dto.Job(); + + // this is the only different field between the two + result.setExportTypeSpecificParameters(newExportTypeSpecificParameters); + + result.setId(jobWithLegacyBursarParametersEntity.getId()); + result.setName(jobWithLegacyBursarParametersEntity.getName()); + result.setDescription(jobWithLegacyBursarParametersEntity.getDescription()); + result.setSource(jobWithLegacyBursarParametersEntity.getSource()); + result.setIsSystemSource(jobWithLegacyBursarParametersEntity.getIsSystemSource()); + result.setTenant(jobWithLegacyBursarParametersEntity.getTenant()); + result.setType(jobWithLegacyBursarParametersEntity.getType()); + result.setStatus(jobWithLegacyBursarParametersEntity.getStatus()); + result.setFiles(jobWithLegacyBursarParametersEntity.getFiles()); + result.setFileNames(jobWithLegacyBursarParametersEntity.getFileNames()); + result.setStartTime(jobWithLegacyBursarParametersEntity.getStartTime()); + result.setEndTime(jobWithLegacyBursarParametersEntity.getEndTime()); + result.setIdentifierType(jobWithLegacyBursarParametersEntity.getIdentifierType()); + result.setEntityType(jobWithLegacyBursarParametersEntity.getEntityType()); + result.setProgress(jobWithLegacyBursarParametersEntity.getProgress()); + + result.setMetadata(jobWithLegacyBursarParametersEntity.getMetadata()); + + result.setOutputFormat(jobWithLegacyBursarParametersEntity.getOutputFormat()); + result.setErrorDetails(jobWithLegacyBursarParametersEntity.getErrorDetails()); + + return result; + } +} diff --git a/src/main/java/org/folio/des/validator/BurSarFeesFinesExportParametersValidator.java b/src/main/java/org/folio/des/validator/BursarFeesFinesExportParametersValidator.java similarity index 87% rename from src/main/java/org/folio/des/validator/BurSarFeesFinesExportParametersValidator.java rename to src/main/java/org/folio/des/validator/BursarFeesFinesExportParametersValidator.java index 02d1bd77..2849b763 100644 --- a/src/main/java/org/folio/des/validator/BurSarFeesFinesExportParametersValidator.java +++ b/src/main/java/org/folio/des/validator/BursarFeesFinesExportParametersValidator.java @@ -1,6 +1,6 @@ package org.folio.des.validator; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.ExportType; import org.folio.des.domain.dto.ExportTypeSpecificParameters; import org.springframework.stereotype.Service; @@ -13,7 +13,7 @@ @AllArgsConstructor @Log4j2 @Service -public class BurSarFeesFinesExportParametersValidator implements Validator { +public class BursarFeesFinesExportParametersValidator implements Validator { @Override public boolean supports(Class aClass) { return ExportTypeSpecificParameters.class.isAssignableFrom(aClass); @@ -30,7 +30,7 @@ public void validate(Object target, Errors errors) { ExportTypeSpecificParameters specificParameters = (ExportTypeSpecificParameters) target; if (specificParameters.getBursarFeeFines() == null) { String msg = String.format("%s type should contain %s parameters", ExportType.BURSAR_FEES_FINES.getValue(), - BursarFeeFines.class.getSimpleName()); + BursarExportJob.class.getSimpleName()); throw new IllegalArgumentException(msg); } } diff --git a/src/main/resources/swagger.api/export-configs.yaml b/src/main/resources/swagger.api/export-configs.yaml index e8fda095..18d94a68 100644 --- a/src/main/resources/swagger.api/export-configs.yaml +++ b/src/main/resources/swagger.api/export-configs.yaml @@ -198,6 +198,8 @@ components: schemas: exportConfig: $ref: '../../../../folio-export-common/schemas/exportConfig.json#/ExportConfig' + exportConfigWithLegacyBursar: + $ref: '../../../../folio-export-common/schemas/exportConfigWithLegacyBursar.json#/ExportConfigWithLegacyBursar' exportConfigCollection: $ref: '../../../../folio-export-common/schemas/exportConfigCollection.json#/ExportConfigCollection' errors: @@ -220,4 +222,3 @@ components: errors: value: $ref: '../../../../folio-export-common/examples/errors.sample' - diff --git a/src/main/resources/swagger.api/jobs.yaml b/src/main/resources/swagger.api/jobs.yaml index 38a6fb5e..280b70b9 100644 --- a/src/main/resources/swagger.api/jobs.yaml +++ b/src/main/resources/swagger.api/jobs.yaml @@ -224,6 +224,8 @@ components: $ref: '../../../../folio-export-common/schemas/exportFilePresignedUrl.json#/PresignedUrl' job: $ref: '../../../../folio-export-common/schemas/job.json#/Job' + jobWithLegacyBursarParameters: + $ref: '../../../../folio-export-common/schemas/jobWithLegacyBursarParameters.json#/JobWithLegacyBursarParameters' jobCollection: $ref: '../../../../folio-export-common/schemas/jobCollection.json#/JobCollection' userdataCollection: @@ -251,8 +253,7 @@ components: trait_pageable_offset: name: offset in: query - description: Skip over a number of elements by specifying an offset value for - the query + description: Skip over a number of elements by specifying an offset value for the query schema: default: 0 minimum: 0 diff --git a/src/test/java/org/folio/des/InstallUpgradeIT.java b/src/test/java/org/folio/des/InstallUpgradeIT.java index 7f79dcef..eae490f3 100644 --- a/src/test/java/org/folio/des/InstallUpgradeIT.java +++ b/src/test/java/org/folio/des/InstallUpgradeIT.java @@ -1,14 +1,12 @@ package org.folio.des; -import static io.restassured.RestAssured.given; -import static io.restassured.RestAssured.when; -import static org.hamcrest.Matchers.is; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.io.IOException; -import java.nio.file.Path; - +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.restassured.RestAssured; +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.filter.log.RequestLoggingFilter; +import io.restassured.filter.log.ResponseLoggingFilter; +import io.restassured.http.ContentType; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -18,6 +16,7 @@ import org.mockserver.verify.VerificationTimes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.test.annotation.DirtiesContext; import org.testcontainers.containers.BindMode; import org.testcontainers.containers.Container.ExecResult; import org.testcontainers.containers.GenericContainer; @@ -31,15 +30,14 @@ import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import io.restassured.RestAssured; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.filter.log.RequestLoggingFilter; -import io.restassured.filter.log.ResponseLoggingFilter; -import io.restassured.http.ContentType; +import java.io.IOException; +import java.nio.file.Path; +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.is; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; /** * Test that shaded fat uber jar and Dockerfile work. @@ -47,6 +45,7 @@ *

Smoke tests: /admin/health and migration. */ @Testcontainers +@DirtiesContext class InstallUpgradeIT { private static final Logger LOG = LoggerFactory.getLogger(InstallUpgradeIT.class); @@ -278,4 +277,3 @@ private static void verifySchedulingConfigReload(int times) { } """; } - diff --git a/src/test/java/org/folio/des/builder/job/JobCommandBuilderResolverTest.java b/src/test/java/org/folio/des/builder/job/JobCommandBuilderResolverTest.java index 518e9c62..5c6683e0 100644 --- a/src/test/java/org/folio/des/builder/job/JobCommandBuilderResolverTest.java +++ b/src/test/java/org/folio/des/builder/job/JobCommandBuilderResolverTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -15,7 +16,12 @@ import org.folio.des.config.ServiceConfiguration; import org.folio.des.config.scheduling.QuartzSchemaInitializer; import org.folio.des.domain.dto.AuthorityControlExportConfig; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterCondition.OperationEnum; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.EHoldingsExportConfig; import org.folio.des.domain.dto.EntityType; import org.folio.des.domain.dto.ExportType; @@ -49,7 +55,7 @@ class JobCommandBuilderResolverTest { @ParameterizedTest @DisplayName("Should retrieve builder for specific export type if builder is registered in the resolver") @CsvSource({ - "BURSAR_FEES_FINES, BurSarFeeFinesJobCommandBuilder", + "BURSAR_FEES_FINES, BursarFeeFinesJobCommandBuilder", "CIRCULATION_LOG, CirculationLogJobCommandBuilder", "BULK_EDIT_QUERY, BulkEditQueryJobCommandBuilder", "EDIFACT_ORDERS_EXPORT, EdifactOrdersJobCommandBuilder", @@ -91,11 +97,22 @@ void shouldBeCreateJobParameters(ExportType exportType, String paramsKey) { ExportTypeSpecificParameters exportTypeSpecificParameters = new ExportTypeSpecificParameters(); VendorEdiOrdersExportConfig vendorEdiOrdersExportConfig = new VendorEdiOrdersExportConfig(); EHoldingsExportConfig eHoldingsExportConfig = new EHoldingsExportConfig(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); + BursarExportJob bursarFeeFines = new BursarExportJob(); AuthorityControlExportConfig authorityControlExportConfig = new AuthorityControlExportConfig(); - bursarFeeFines.setDaysOutstanding(1); - bursarFeeFines.addPatronGroupsItem("Test"); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId(UUID.fromString("0000-00-00-00-000000")); + + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); vendorEdiOrdersExportConfig.vendorId(UUID.randomUUID()); vendorEdiOrdersExportConfig.setConfigName("TestConfig"); @@ -114,7 +131,6 @@ void shouldBeCreateJobParameters(ExportType exportType, String paramsKey) { exportTypeSpecificParameters.setVendorEdiOrdersExportConfig(vendorEdiOrdersExportConfig); exportTypeSpecificParameters.seteHoldingsExportConfig(eHoldingsExportConfig); exportTypeSpecificParameters.setAuthorityControlExportConfig(authorityControlExportConfig); - job.setEntityType(EntityType.USER); job.setExportTypeSpecificParameters(exportTypeSpecificParameters); diff --git a/src/test/java/org/folio/des/controller/ConfigsControllerTest.java b/src/test/java/org/folio/des/controller/ConfigsControllerTest.java index 9ee1aea3..93336ae1 100644 --- a/src/test/java/org/folio/des/controller/ConfigsControllerTest.java +++ b/src/test/java/org/folio/des/controller/ConfigsControllerTest.java @@ -42,9 +42,9 @@ class ConfigsControllerTest extends BaseTest { private static final String NEW_CONFIG_REQUEST = - "{\"id\":\"0a3cba78-16e7-498e-b75b-98713000277b\",\"type\":\"BURSAR_FEES_FINES\",\"exportTypeSpecificParameters\":{\"bursarFeeFines\":{\"daysOutstanding\":10,\"patronGroups\":[\"3684a786-6671-4268-8ed0-9db82ebca60b\"]}},\"scheduleFrequency\":5,\"schedulePeriod\":\"DAY\",\"scheduleTime\":\"00:20:00.000Z\"}"; + "{\"id\":\"0a3cba78-16e7-498e-b75b-98713000277b\",\"type\":\"BURSAR_FEES_FINES\",\"exportTypeSpecificParameters\":{\"bursarFeeFines\":{\"filter\":{\"type\":\"Pass\"},\"groupByPatron\":false,\"header\":[],\"data\":[],\"footer\":[],\"transferInfo\":{\"conditions\":[],\"else\":{\"account\":\"90c1820f-60bf-4b9a-99f5-d677ea78ddca\"}}}},\"scheduleFrequency\":5,\"schedulePeriod\":\"DAY\",\"scheduleTime\":\"00:20:00.000Z\"}"; private static final String UPDATE_CONFIG_REQUEST = - "{\"id\":\"0a3cba78-16e7-498e-b75b-98713000277b\",\"type\":\"BURSAR_FEES_FINES\",\"exportTypeSpecificParameters\":{\"bursarFeeFines\":{\"daysOutstanding\":10,\"patronGroups\":[\"3684a786-6671-4268-8ed0-9db82ebca60b\"]}},\"scheduleFrequency\":5,\"schedulePeriod\":\"DAY\",\"scheduleTime\":\"00:20:00.000Z\"}"; + "{\"id\":\"0a3cba78-16e7-498e-b75b-98713000277b\",\"type\":\"BURSAR_FEES_FINES\",\"exportTypeSpecificParameters\":{\"bursarFeeFines\":{\"filter\":{\"type\":\"Pass\"},\"groupByPatron\":false,\"header\":[],\"data\":[],\"footer\":[],\"transferInfo\":{\"conditions\":[],\"else\":{\"account\":\"90c1820f-60bf-4b9a-99f5-d677ea78ddca\"}}}},\"scheduleFrequency\":5,\"schedulePeriod\":\"DAY\",\"scheduleTime\":\"00:20:00.000Z\"}"; private static final String UPDATE_CONFIG_REQUEST_FAILED = "{\"id\":\"0a3cba78-16e7-498e-b75b-98713000277b\",\"type\":\"BURSAR_FEES_FINES\",\"scheduleFrequency\":5,\"schedulePeriod\":\"DAY\",\"scheduleTime\":\"00:20:00.000Z\"}"; private static final String EDIFACT_CONFIG_REQUEST = diff --git a/src/test/java/org/folio/des/controller/JobsControllerTest.java b/src/test/java/org/folio/des/controller/JobsControllerTest.java index 542f7c96..52a92ac3 100644 --- a/src/test/java/org/folio/des/controller/JobsControllerTest.java +++ b/src/test/java/org/folio/des/controller/JobsControllerTest.java @@ -51,10 +51,17 @@ class JobsControllerTest extends BaseTest { "type": "BURSAR_FEES_FINES", "exportTypeSpecificParameters" : { "bursarFeeFines": { - "daysOutstanding": 10, - "patronGroups": ["3684a786-6671-4268-8ed0-9db82ebca60b"] + "filter": { "type": "Pass" }, + "groupByPatron": false, + "header": [], + "data": [], + "footer": [], + "transferInfo": { + "conditions": [], + "else": { "account": "90c1820f-60bf-4b9a-99f5-d677ea78ddca" } + } } - } + } }"""; private static final String JOB_CIRCULATION_REQUEST = diff --git a/src/test/java/org/folio/des/converter/DefaultExportConfigToModelConfigConverterTest.java b/src/test/java/org/folio/des/converter/DefaultExportConfigToModelConfigConverterTest.java index 331dcc45..1debbfbb 100644 --- a/src/test/java/org/folio/des/converter/DefaultExportConfigToModelConfigConverterTest.java +++ b/src/test/java/org/folio/des/converter/DefaultExportConfigToModelConfigConverterTest.java @@ -4,15 +4,21 @@ import static org.folio.des.service.config.ExportConfigConstants.DEFAULT_MODULE_NAME; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.folio.des.config.JacksonConfiguration; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportType; import org.folio.des.domain.dto.ExportTypeSpecificParameters; import org.folio.des.domain.dto.ModelConfiguration; +import org.folio.des.domain.dto.BursarExportFilterCondition.OperationEnum; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -31,10 +37,21 @@ void testConverterIfExportConfigIsValid() { ExportConfig bursarExportConfig = new ExportConfig(); bursarExportConfig.setId(expId); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); - bursarFeeFines.setDaysOutstanding(9); - bursarFeeFines.setPatronGroups(List.of(UUID.randomUUID().toString())); + + BursarExportJob bursarFeeFines = new BursarExportJob(); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId(UUID.fromString("0000-00-00-00-000000")); + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); parameters.setBursarFeeFines(bursarFeeFines); + bursarExportConfig.exportTypeSpecificParameters(parameters); ModelConfiguration actConfig = converter.convert(bursarExportConfig); @@ -59,9 +76,19 @@ void testConverterIfExportConfigIsValidAndTypeIsProvided(ExportType exportType, bursarExportConfig.setType(exportType); bursarExportConfig.setId(expId); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); - bursarFeeFines.setDaysOutstanding(9); - bursarFeeFines.setPatronGroups(List.of(UUID.randomUUID().toString())); + + BursarExportJob bursarFeeFines = new BursarExportJob(); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId(UUID.fromString("0000-00-00-00-000000")); + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); parameters.setBursarFeeFines(bursarFeeFines); bursarExportConfig.exportTypeSpecificParameters(parameters); diff --git a/src/test/java/org/folio/des/converter/acquisition/EdifactExportConfigToModelConfigConverterTest.java b/src/test/java/org/folio/des/converter/acquisition/EdifactExportConfigToModelConfigConverterTest.java index a7582b6e..9c6550dd 100644 --- a/src/test/java/org/folio/des/converter/acquisition/EdifactExportConfigToModelConfigConverterTest.java +++ b/src/test/java/org/folio/des/converter/acquisition/EdifactExportConfigToModelConfigConverterTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -11,7 +12,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.folio.des.config.JacksonConfiguration; import org.folio.des.converter.aqcuisition.EdifactExportConfigToModelConfigConverter; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.EdiSchedule; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportType; @@ -19,6 +24,7 @@ import org.folio.des.domain.dto.ModelConfiguration; import org.folio.des.domain.dto.ScheduleParameters; import org.folio.des.domain.dto.VendorEdiOrdersExportConfig; +import org.folio.des.domain.dto.BursarExportFilterCondition.OperationEnum; import org.folio.des.validator.acquisition.EdifactOrdersExportParametersValidator; import org.folio.des.validator.acquisition.EdifactOrdersScheduledParamsValidator; import org.junit.jupiter.api.Assertions; @@ -153,9 +159,18 @@ void shouldThrowExceptionIfExportConfigIsNotValidAndTypeIsProvided(ExportType ex ediConfig.setId(expId); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); - bursarFeeFines.setDaysOutstanding(9); - bursarFeeFines.setPatronGroups(List.of(UUID.randomUUID().toString())); + BursarExportJob bursarFeeFines = new BursarExportJob(); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId(UUID.fromString("0000-00-00-00-000000")); + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); parameters.setBursarFeeFines(bursarFeeFines); ediConfig.exportTypeSpecificParameters(parameters); diff --git a/src/test/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializerTest.java b/src/test/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializerTest.java index 086d18b3..d00443f1 100644 --- a/src/test/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializerTest.java +++ b/src/test/java/org/folio/des/scheduling/bursar/BursarScheduledJobInitializerTest.java @@ -17,19 +17,19 @@ class BursarScheduledJobInitializerTest { - private ExportConfigService burSarExportConfigService = mock(ExportConfigService.class); + private ExportConfigService bursarExportConfigService = mock(ExportConfigService.class); private BursarExportScheduler bursarExportScheduler = mock(BursarExportScheduler.class); private BursarScheduledJobInitializer bursarScheduledJobInitializer; @BeforeEach void before() { - bursarScheduledJobInitializer = spy(new BursarScheduledJobInitializer(burSarExportConfigService, bursarExportScheduler)); + bursarScheduledJobInitializer = spy(new BursarScheduledJobInitializer(bursarExportConfigService, bursarExportScheduler)); } @Test void shouldInitiateBursarJob() { - when(burSarExportConfigService.getFirstConfig()) + when(bursarExportConfigService.getFirstConfig()) .thenReturn(Optional.of(new ExportConfig())); bursarScheduledJobInitializer.initAllScheduledJob(new TenantAttributes().moduleTo("3.0.0")); verify(bursarExportScheduler, times(1)).scheduleBursarJob(any()); @@ -37,7 +37,7 @@ void shouldInitiateBursarJob() { @Test void shouldNotInitiateBursarJob() { - when(burSarExportConfigService.getFirstConfig()) + when(bursarExportConfigService.getFirstConfig()) .thenReturn(Optional.empty()); bursarScheduledJobInitializer.initAllScheduledJob(new TenantAttributes().moduleTo("3.0.0")); verify(bursarExportScheduler, times(0)).scheduleBursarJob(any()); diff --git a/src/test/java/org/folio/des/scheduling/quartz/OldJobDeleteSchedulerTest.java b/src/test/java/org/folio/des/scheduling/quartz/OldJobDeleteSchedulerTest.java index d6eeb64d..a75438a8 100644 --- a/src/test/java/org/folio/des/scheduling/quartz/OldJobDeleteSchedulerTest.java +++ b/src/test/java/org/folio/des/scheduling/quartz/OldJobDeleteSchedulerTest.java @@ -6,6 +6,8 @@ import java.util.concurrent.TimeUnit; +import lombok.extern.log4j.Log4j2; + import javax.annotation.PostConstruct; import org.folio.des.support.BaseTest; @@ -16,8 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest(properties = { - "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}"}) +@Log4j2 +@SpringBootTest(properties = { "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}" }) class OldJobDeleteSchedulerTest extends BaseTest { private static final String EXPORT_DELETE_GROUP = TENANT + "_" + QuartzConstants.OLD_JOB_DELETE_GROUP_NAME; @@ -35,9 +37,12 @@ void testOldJobDeleteTrigger() throws SchedulerException { oldJobDeleteScheduler.scheduleOldJobDeletion(TENANT); var jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupContains(EXPORT_DELETE_GROUP)); - var triggers = scheduler.getTriggersOfJob(jobKeys.iterator().next()); + var triggers = scheduler.getTriggersOfJob(jobKeys.iterator() + .next()); assertEquals(1, triggers.size()); - assertEquals(EXPORT_DELETE_GROUP, triggers.get(0).getKey().getGroup()); + assertEquals(EXPORT_DELETE_GROUP, triggers.get(0) + .getKey() + .getGroup()); } @Test @@ -45,9 +50,11 @@ void testDeleteOldJobDeleteScheduler() throws SchedulerException { oldJobDeleteScheduler.scheduleOldJobDeletion(TENANT); oldJobDeleteScheduler.removeJobs(TENANT); - await().pollDelay(1, TimeUnit.SECONDS).timeout(10, TimeUnit.SECONDS).untilAsserted( - () -> { + await().pollDelay(1, TimeUnit.SECONDS) + .timeout(10, TimeUnit.SECONDS) + .untilAsserted(() -> { var jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupContains(EXPORT_DELETE_GROUP)); + log.info("jobKeys: {}", jobKeys); assertTrue(jobKeys.isEmpty()); }); } diff --git a/src/test/java/org/folio/des/scheduling/quartz/QuartzExportJobSchedulerTest.java b/src/test/java/org/folio/des/scheduling/quartz/QuartzExportJobSchedulerTest.java index 81800e6e..6eaa8533 100644 --- a/src/test/java/org/folio/des/scheduling/quartz/QuartzExportJobSchedulerTest.java +++ b/src/test/java/org/folio/des/scheduling/quartz/QuartzExportJobSchedulerTest.java @@ -16,7 +16,10 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; - +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.log4j.Log4j2; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportConfig.SchedulePeriodEnum; import org.folio.des.scheduling.quartz.converter.ExportConfigToJobDetailConverter; @@ -39,15 +42,12 @@ import org.quartz.listeners.SchedulerListenerSupport; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.core.convert.converter.Converter; - -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.extern.log4j.Log4j2; +import org.springframework.test.annotation.DirtiesContext; @SpringBootTest(properties = { - "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}" + "spring.kafka.bootstrap-servers=${spring.embedded.kafka.brokers}", }) +@DirtiesContext class QuartzExportJobSchedulerTest extends BaseTest { private static final String SCHEDULE_ID = "scheduleId_" + UUID.randomUUID(); @@ -71,7 +71,7 @@ void testSchedule() throws SchedulerException { assertEquals(1, schedulerListener.getJobsAddedCount()); assertEquals(1, schedulerListener.getJobsScheduledCount()); - await().pollDelay(1, TimeUnit.SECONDS).timeout(10, TimeUnit.SECONDS).untilAsserted( + await().pollDelay(1, TimeUnit.SECONDS).timeout(180, TimeUnit.SECONDS).untilAsserted( () -> assertEquals(1, jobListener.getJobsExecutedCount())); } @@ -135,7 +135,7 @@ void testScheduleJobWithMultipleTriggers() throws SchedulerException { assertEquals(1, schedulerListener.getJobsAddedCount()); assertEquals(jobTriggersCount, schedulerListener.getJobsScheduledCount()); - await().pollDelay(1, TimeUnit.SECONDS).timeout(10, TimeUnit.SECONDS).untilAsserted( + await().pollDelay(1, TimeUnit.SECONDS).timeout(200, TimeUnit.SECONDS).untilAsserted( () -> assertEquals(jobTriggersCount, jobListener.getJobsExecutedCount())); } @@ -211,6 +211,7 @@ private TestingJobListener registerTestingJobListener() throws SchedulerExceptio @AllArgsConstructor @NoArgsConstructor private static class TestTriggerConverter implements Converter { + @Setter private int triggerAmount = 1; @@ -230,13 +231,10 @@ public ExportTrigger convert(ExportConfig exportConfig) { return new ExportTrigger(exportConfig.getSchedulePeriod() == SchedulePeriodEnum.NONE, triggers); } } - private static class TestJobDetailConverter implements ExportConfigToJobDetailConverter { @Override public JobDetail convert(ExportConfig exportConfig, JobKey jobKey) { - return JobBuilder.newJob(DraftJob.class) - .withIdentity(jobKey) - .build(); + return JobBuilder.newJob(DraftJob.class).withIdentity(jobKey).build(); } } diff --git a/src/test/java/org/folio/des/service/FolioTenantServiceTest.java b/src/test/java/org/folio/des/service/FolioTenantServiceTest.java index a1e3cc74..0177d0b6 100644 --- a/src/test/java/org/folio/des/service/FolioTenantServiceTest.java +++ b/src/test/java/org/folio/des/service/FolioTenantServiceTest.java @@ -1,6 +1,7 @@ package org.folio.des.service; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -11,6 +12,7 @@ import org.folio.des.scheduling.bursar.BursarScheduledJobInitializer; import org.folio.des.scheduling.quartz.OldJobDeleteScheduler; import org.folio.des.scheduling.quartz.ScheduledJobsRemover; +import org.folio.des.service.bursarlegacy.BursarMigrationService; import org.folio.des.service.config.BulkEditConfigService; import org.folio.spring.FolioExecutionContext; import org.folio.spring.service.PrepareSystemUserService; @@ -29,12 +31,16 @@ class FolioTenantServiceTest { @Mock KafkaService kafka; + @Mock BulkEditConfigService bulkEditConfigService; + @Mock EdifactScheduledJobInitializer edifactScheduledJobInitializer; + @Mock FolioExecutionContext folioExecutionContext; + @Mock ScheduledJobsRemover scheduledJobsRemover; @@ -43,20 +49,33 @@ class FolioTenantServiceTest { @Mock OldJobDeleteScheduler oldJobDeleteScheduler; + @Mock PrepareSystemUserService prepareSystemUserService; + @Mock + BursarMigrationService bursarMigrationService; + @Test void shouldDoProcessAfterTenantUpdating() { TenantAttributes tenantAttributes = createTenantAttributes(); - doNothing().when(prepareSystemUserService).setupSystemUser(); - doNothing().when(bulkEditConfigService).checkBulkEditConfiguration(); - doNothing().when(edifactScheduledJobInitializer).initAllScheduledJob(tenantAttributes); - doNothing().when(kafka).createKafkaTopics(); - doNothing().when(kafka).restartEventListeners(); - doNothing().when(bursarScheduledJobInitializer).initAllScheduledJob(tenantAttributes); - doNothing().when(oldJobDeleteScheduler).scheduleOldJobDeletion(any()); + doNothing().when(prepareSystemUserService) + .setupSystemUser(); + doNothing().when(bulkEditConfigService) + .checkBulkEditConfiguration(); + doNothing().when(edifactScheduledJobInitializer) + .initAllScheduledJob(tenantAttributes); + doNothing().when(kafka) + .createKafkaTopics(); + doNothing().when(kafka) + .restartEventListeners(); + doNothing().when(bursarScheduledJobInitializer) + .initAllScheduledJob(tenantAttributes); + doNothing().when(oldJobDeleteScheduler) + .scheduleOldJobDeletion(any()); + doNothing().when(bursarMigrationService) + .updateLegacyBursarIfNeeded(eq(tenantAttributes), any(), any(), any()); folioTenantService.afterTenantUpdate(tenantAttributes); @@ -65,6 +84,7 @@ void shouldDoProcessAfterTenantUpdating() { verify(edifactScheduledJobInitializer, times(1)).initAllScheduledJob(tenantAttributes); verify(bursarScheduledJobInitializer, times(1)).initAllScheduledJob(tenantAttributes); verify(oldJobDeleteScheduler, times(1)).scheduleOldJobDeletion(any()); + verify(bursarMigrationService, times(1)).updateLegacyBursarIfNeeded(eq(tenantAttributes), any(), any(), any()); verify(kafka, times(1)).createKafkaTopics(); verify(kafka, times(1)).restartEventListeners(); } @@ -76,8 +96,10 @@ void shouldDeleteJob() { tenantAttributes.setPurge(true); when(folioExecutionContext.getTenantId()).thenReturn(tenantId); - doNothing().when(scheduledJobsRemover).deleteJobs(tenantId); - doNothing().when(oldJobDeleteScheduler).removeJobs(tenantId); + doNothing().when(scheduledJobsRemover) + .deleteJobs(tenantId); + doNothing().when(oldJobDeleteScheduler) + .removeJobs(tenantId); folioTenantService.afterTenantDeletion(tenantAttributes); diff --git a/src/test/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobServiceTest.java b/src/test/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobServiceTest.java new file mode 100644 index 00000000..9310bfbd --- /dev/null +++ b/src/test/java/org/folio/des/service/bursarlegacy/BursarExportLegacyJobServiceTest.java @@ -0,0 +1,73 @@ +package org.folio.des.service.bursarlegacy; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.UUID; +import org.folio.de.entity.bursarlegacy.JobWithLegacyBursarParameters; +import org.folio.des.domain.dto.ExportTypeSpecificParametersWithLegacyBursar; +import org.folio.des.domain.dto.LegacyBursarFeeFines; +import org.folio.des.repository.bursarlegacy.BursarExportLegacyJobRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class BursarExportLegacyJobServiceTest { + + @Mock + private BursarExportLegacyJobRepository repository; + + static JobWithLegacyBursarParameters nonBursar1, nonBursar2, nonBursar3, isBursar; + + static { + nonBursar1 = new JobWithLegacyBursarParameters(); + nonBursar1.setId(UUID.fromString("998a84d7-9538-5652-8a40-d26bbb8507bc")); + nonBursar1.setExportTypeSpecificParameters(new ExportTypeSpecificParametersWithLegacyBursar()); + + nonBursar2 = new JobWithLegacyBursarParameters(); + nonBursar2.setId(UUID.fromString("dfad2baa-c970-5933-b86a-68781c5c4f2c")); + nonBursar2.setExportTypeSpecificParameters(new ExportTypeSpecificParametersWithLegacyBursar().bursarFeeFines(null)); + + nonBursar3 = new JobWithLegacyBursarParameters(); + nonBursar3.setId(UUID.fromString("aae30cd1-4549-5572-bb14-4c04c1b28366")); + nonBursar3.setExportTypeSpecificParameters( + new ExportTypeSpecificParametersWithLegacyBursar().bursarFeeFines(new LegacyBursarFeeFines())); + + isBursar = new JobWithLegacyBursarParameters(); + isBursar.setId(UUID.fromString("5a0e5c0b-a216-552c-8a28-6b25ada9ae84")); + isBursar.setExportTypeSpecificParameters( + new ExportTypeSpecificParametersWithLegacyBursar().bursarFeeFines(new LegacyBursarFeeFines().daysOutstanding(1))); + } + + @Test + void testGetBlankQuery() { + List items = List.of(nonBursar1, nonBursar2, nonBursar3, isBursar); + + when(repository.findAll()).thenReturn(items); + + BursarExportLegacyJobService service = new BursarExportLegacyJobService(repository); + + List legacyJobCollection = service.getAllLegacyJobs(); + + assertEquals(1, legacyJobCollection.size()); + assertEquals(isBursar.getId(), legacyJobCollection.get(0) + .getId()); + } + + private static List hasLegacyParametersArguments() { + return List.of(Arguments.of(isBursar, true), Arguments.of(nonBursar1, false), Arguments.of(nonBursar2, false), + Arguments.of(nonBursar3, false)); + } + + @ParameterizedTest + @MethodSource("hasLegacyParametersArguments") + void testHasLegacyBursarParameters(JobWithLegacyBursarParameters job, boolean expected) { + assertEquals(expected, BursarExportLegacyJobService.hasLegacyBursarParameters(job)); + } +} diff --git a/src/test/java/org/folio/des/service/bursarlegacy/BursarMigrationServiceTest.java b/src/test/java/org/folio/des/service/bursarlegacy/BursarMigrationServiceTest.java new file mode 100644 index 00000000..dd461102 --- /dev/null +++ b/src/test/java/org/folio/des/service/bursarlegacy/BursarMigrationServiceTest.java @@ -0,0 +1,269 @@ +package org.folio.des.service.bursarlegacy; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterFeeFineOwner; +import org.folio.des.domain.dto.BursarExportFilterFeeType; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportTokenConditional; +import org.folio.des.domain.dto.BursarExportTokenConstant; +import org.folio.des.domain.dto.ExportConfig; +import org.folio.des.domain.dto.ExportConfigWithLegacyBursar; +import org.folio.des.domain.dto.ExportTypeSpecificParameters; +import org.folio.des.domain.dto.ExportTypeSpecificParametersWithLegacyBursar; +import org.folio.des.domain.dto.Job; +import org.folio.des.domain.dto.JobWithLegacyBursarParameters; +import org.folio.des.domain.dto.LegacyBursarFeeFines; +import org.folio.des.domain.dto.LegacyBursarFeeFinesTypeMapping; +import org.folio.des.domain.dto.LegacyBursarFeeFinesTypeMappings; +import org.folio.des.service.JobService; +import org.folio.des.service.config.impl.BursarFeesFinesExportConfigService; +import org.folio.tenant.domain.dto.TenantAttributes; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@ExtendWith(MockitoExtension.class) +class BursarMigrationServiceTest { + + @InjectMocks + private BursarMigrationService bursarMigrationService; + + @Mock + private BursarFeesFinesExportConfigService bursarFeesFinesExportConfigService; + + @Mock + private BursarExportLegacyJobService bursarExportLegacyJobService; + + @Mock + private JobService jobService; + + @Test + void testNoLegacyJobs() { + when(bursarExportLegacyJobService.getAllLegacyJobs()).thenReturn(List.of()); + + bursarMigrationService.updateLegacyBursarJobs(bursarExportLegacyJobService, jobService); + + verifyNoInteractions(jobService); + } + + @Test + void testLegacyJobConversion() { + JobWithLegacyBursarParameters legacyJob = new JobWithLegacyBursarParameters(); + legacyJob.setId(UUID.fromString("928f4cc0-0f44-5d5f-aa73-3b7bc532961e")); + legacyJob.setExportTypeSpecificParameters( + new ExportTypeSpecificParametersWithLegacyBursar().bursarFeeFines(new LegacyBursarFeeFines().daysOutstanding(1) + .addPatronGroupsItem("ed98f8c2-09b0-5d46-b610-ba955d0bf303") + .addPatronGroupsItem("d82b6807-4ab3-5412-8428-1b49ac20e0c2"))); + + // check converted job makes sense + ExportTypeSpecificParameters params = BursarMigrationService + .convertLegacyJobParameters(legacyJob.getExportTypeSpecificParameters() + .getBursarFeeFines()); + + // verify filters + List filters = ((BursarExportFilterCondition) params.getBursarFeeFines() + .getFilter()).getCriteria(); + + // age filter + assertEquals(1, filters.stream() + .filter(i -> i instanceof BursarExportFilterAge) + .map(i -> (BursarExportFilterAge) i) + .findFirst() + .get() + .getNumDays()); + + // patron filters are nested inside an OR + List patronFilters = filters.stream() + .filter(i -> i instanceof BursarExportFilterCondition) + .map(i -> (BursarExportFilterCondition) i) + .findFirst() + .get() + .getCriteria() + .stream() + .map(i -> (BursarExportFilterPatronGroup) i) + .toList(); + assertEquals(2, patronFilters.size()); + assertTrue(patronFilters.stream() + .map(BursarExportFilterPatronGroup::getPatronGroupId) + .anyMatch(i -> i.equals(UUID.fromString("ed98f8c2-09b0-5d46-b610-ba955d0bf303")))); + assertTrue(patronFilters.stream() + .map(BursarExportFilterPatronGroup::getPatronGroupId) + .anyMatch(i -> i.equals(UUID.fromString("d82b6807-4ab3-5412-8428-1b49ac20e0c2")))); + + // ensure that calling .updateLegacyBursarJobs correctly updates the job above + when(bursarExportLegacyJobService.getAllLegacyJobs()).thenReturn(List.of(legacyJob)); + + bursarMigrationService.updateLegacyBursarJobs(bursarExportLegacyJobService, jobService); + + verify(bursarExportLegacyJobService, times(1)).getAllLegacyJobs(); + + ArgumentCaptor jobCaptor = ArgumentCaptor.forClass(Job.class); + verify(jobService, times(1)).upsertAndSendToKafka(jobCaptor.capture(), eq(false)); + assertEquals(UUID.fromString("928f4cc0-0f44-5d5f-aa73-3b7bc532961e"), jobCaptor.getValue() + .getId()); + assertEquals(params, jobCaptor.getValue() + .getExportTypeSpecificParameters()); + } + + @Test + void testMapTypeMappingsToTokens() { + LegacyBursarFeeFinesTypeMappings typeMappings = new LegacyBursarFeeFinesTypeMappings(); + LegacyBursarFeeFinesTypeMapping typeMapping = new LegacyBursarFeeFinesTypeMapping(); + typeMapping.setFeefineTypeId(UUID.fromString("c4ff3edb-2cc4-523c-a90d-9a2fc8b02a00")); + typeMapping.setItemType("test_item_type"); + typeMapping.setItemDescription("test_item_description"); + typeMappings.put("81a5bb0a-e3a1-57b5-b8a8-9324989a7585", List.of(typeMapping)); + + List tokens = BursarMigrationService.mapTypeMappingsToTokens(typeMappings); + + // Type checking for item token + assertEquals(BursarExportFilterCondition.class, tokens.get(0) + .getConditions() + .get(0) + .getCondition() + .getClass()); + + // Check for item token condition + BursarExportFilterCondition itemTypeCondition = (BursarExportFilterCondition) tokens.get(0) + .getConditions() + .get(0) + .getCondition(); + assertEquals(BursarExportFilterFeeType.class, itemTypeCondition.getCriteria() + .get(0) + .getClass()); + BursarExportFilterFeeType feeType = (BursarExportFilterFeeType) itemTypeCondition.getCriteria() + .get(0); + assertEquals(UUID.fromString("c4ff3edb-2cc4-523c-a90d-9a2fc8b02a00"), feeType.getFeeFineTypeId()); + assertEquals(BursarExportFilterFeeFineOwner.class, itemTypeCondition.getCriteria() + .get(1) + .getClass()); + BursarExportFilterFeeFineOwner feeFineOwner = (BursarExportFilterFeeFineOwner) itemTypeCondition.getCriteria() + .get(1); + assertEquals(UUID.fromString("81a5bb0a-e3a1-57b5-b8a8-9324989a7585"), feeFineOwner.getFeeFineOwner()); + assertEquals(BursarExportTokenConstant.class, tokens.get(0) + .getConditions() + .get(0) + .getValue() + .getClass()); + assertEquals("test_item_type", ((BursarExportTokenConstant) tokens.get(0) + .getConditions() + .get(0) + .getValue()).getValue()); + + // Type checking for description token + assertEquals(BursarExportFilterCondition.class, tokens.get(1) + .getConditions() + .get(0) + .getCondition() + .getClass()); + assertEquals(BursarExportTokenConstant.class, tokens.get(1) + .getConditions() + .get(0) + .getValue() + .getClass()); + assertEquals("test_item_description", ((BursarExportTokenConstant) tokens.get(1) + .getConditions() + .get(0) + .getValue()).getValue()); + } + + @Test + void testConvertNoConfig() { + when(bursarFeesFinesExportConfigService.getFirstConfigLegacy()).thenReturn(Optional.empty()); + + bursarMigrationService.updateLegacyBursarConfigs(bursarFeesFinesExportConfigService); + + verify(bursarFeesFinesExportConfigService, times(1)).getFirstConfigLegacy(); + verifyNoMoreInteractions(bursarFeesFinesExportConfigService); + } + + @Test + void testConvertExistingConfig() { + ExportConfigWithLegacyBursar legacyConfig = new ExportConfigWithLegacyBursar().id("c4ff3edb-2cc4-523c-a90d-9a2fc8b02a00") + .exportTypeSpecificParameters(new ExportTypeSpecificParametersWithLegacyBursar().bursarFeeFines(new LegacyBursarFeeFines())); + + when(bursarFeesFinesExportConfigService.getFirstConfigLegacy()).thenReturn(Optional.of(legacyConfig)); + when(bursarFeesFinesExportConfigService.getFirstConfig()) + .thenReturn(Optional.of(new ExportConfig().id("c4ff3edb-2cc4-523c-a90d-9a2fc8b02a00"))); + + bursarMigrationService.updateLegacyBursarConfigs(bursarFeesFinesExportConfigService); + + verify(bursarFeesFinesExportConfigService, times(1)).getFirstConfigLegacy(); + verify(bursarFeesFinesExportConfigService, times(1)).updateConfig(eq("c4ff3edb-2cc4-523c-a90d-9a2fc8b02a00"), + any(ExportConfig.class)); + } + + @Test + void testEntryPointShouldNotUpdate() { + TenantAttributes tenantAttributes = new TenantAttributes().moduleFrom("mod-data-export-spring-4.0.0"); + + bursarMigrationService.updateLegacyBursarIfNeeded(tenantAttributes, bursarFeesFinesExportConfigService, + bursarExportLegacyJobService, jobService); + + verifyNoInteractions(jobService); + verifyNoInteractions(bursarFeesFinesExportConfigService); + verifyNoInteractions(bursarExportLegacyJobService); + } + + @Test + void testEntryPointShouldUpdate() { + TenantAttributes tenantAttributes = new TenantAttributes().moduleFrom("mod-data-export-spring-3.0.0"); + + when(bursarFeesFinesExportConfigService.getFirstConfigLegacy()).thenReturn(Optional.empty()); + when(bursarExportLegacyJobService.getAllLegacyJobs()).thenReturn(List.of()); + + bursarMigrationService.updateLegacyBursarIfNeeded(tenantAttributes, bursarFeesFinesExportConfigService, + bursarExportLegacyJobService, jobService); + + verify(bursarExportLegacyJobService, times(1)).getAllLegacyJobs(); + verify(bursarFeesFinesExportConfigService, times(1)).getFirstConfigLegacy(); + verifyNoMoreInteractions(bursarFeesFinesExportConfigService); + verifyNoInteractions(jobService); + } + + @ParameterizedTest + @CsvSource(value = { + // new install => no need to upgrade + ",false", // empty string is null (JUnit does this for csv source) + + // no/invalid version specified => assume need to upgrade + "mod-data-export-spring,true", "1.0,true", "'',true", + + // newer than v3.x.x => no need to upgrade + "mod-data-export-spring-4.0.0,false", "mod-data-export-spring-4.0.0-SNAPSHOT,false", + "mod-data-export-spring-4.0.0.1abcdef,false", // Git revisions are sometimes used + "mod-data-export-spring-999.0.0,false", + + // v3.x.x => need to upgrade + "mod-data-export-spring-3.0.0,true", "mod-data-export-spring-3.999.0,true", "mod-data-export-spring-3.0.0-SNAPSHOT,true", + "mod-data-export-spring-3.0.0.1abcdef,true", + + // very old + "mod-data-export-spring-1.0.0,true", "mod-data-export-spring-1.0.0-SNAPSHOT,true", + "mod-data-export-spring-1.0.0.1abcdef,true", "mod-data-export-spring-0.0.0,true", }) + void testShouldUpdateBursar(String moduleFrom, boolean expected) { + TenantAttributes tenantAttributes = new TenantAttributes().moduleFrom(moduleFrom); + assertEquals(expected, BursarMigrationService.shouldUpdateBursar(tenantAttributes), moduleFrom + "=" + expected); + } +} diff --git a/src/test/java/org/folio/des/service/config/impl/BaseExportConfigServiceTest.java b/src/test/java/org/folio/des/service/config/impl/BaseExportConfigServiceTest.java index 43b9b605..39f7045b 100644 --- a/src/test/java/org/folio/des/service/config/impl/BaseExportConfigServiceTest.java +++ b/src/test/java/org/folio/des/service/config/impl/BaseExportConfigServiceTest.java @@ -10,15 +10,22 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; import java.util.List; import java.util.UUID; - import org.folio.des.client.ConfigurationClient; import org.folio.des.config.JacksonConfiguration; import org.folio.des.config.ServiceConfiguration; import org.folio.des.config.scheduling.QuartzSchemaInitializer; import org.folio.des.converter.DefaultModelConfigToExportConfigConverter; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterCondition.OperationEnum; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.ConfigurationCollection; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportTypeSpecificParameters; @@ -74,7 +81,7 @@ class BaseExportConfigServiceTest { public static final String EMPTY_CONFIG_RESPONSE = "{\"configs\": [], \"totalRecords\": 0}"; @Autowired - private BurSarFeesFinesExportConfigService service; + private BursarFeesFinesExportConfigService service; @Autowired private DefaultModelConfigToExportConfigConverter defaultModelConfigToExportConfigConverter; @Autowired @@ -93,9 +100,19 @@ class BaseExportConfigServiceTest { void addConfig() throws JsonProcessingException { ExportConfig bursarExportConfig = new ExportConfig(); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); - bursarFeeFines.setDaysOutstanding(9); - bursarFeeFines.setPatronGroups(List.of(UUID.randomUUID().toString())); + + BursarExportJob bursarFeeFines = new BursarExportJob(); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId(UUID.fromString("0000-00-00-00-000000")); + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); parameters.setBursarFeeFines(bursarFeeFines); bursarExportConfig.exportTypeSpecificParameters(parameters); ModelConfiguration mockResponse = mockResponse(bursarExportConfig); @@ -127,7 +144,7 @@ void shouldNorCreateConfigurationAndThroughExceptionIfSpecificParametersIsNotSet @Test @DisplayName("Should not create new configuration without bur sar parameters") - void shouldNorCreateConfigurationAndThroughExceptionIfBurSarConfigIsNotSet() throws JsonProcessingException { + void shouldNorCreateConfigurationAndThroughExceptionIfBursarConfigIsNotSet() throws JsonProcessingException { ExportConfig bursarExportConfig = new ExportConfig(); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); bursarExportConfig.setExportTypeSpecificParameters(parameters); @@ -172,8 +189,8 @@ void fetchEmptyConfigCollection() throws JsonProcessingException { var config = service.getConfigCollection(query, 1); Assertions.assertAll( - () -> assertEquals(0, config.getTotalRecords()), - () -> assertTrue(config.getConfigs().isEmpty())); + () -> assertEquals(0, config.getTotalRecords()), + () -> assertTrue(config.getConfigs().isEmpty())); } @Test diff --git a/src/test/java/org/folio/des/service/config/impl/BurSarFeesFinesExportConfigServiceTest.java b/src/test/java/org/folio/des/service/config/impl/BursarFeesFinesExportConfigServiceTest.java similarity index 84% rename from src/test/java/org/folio/des/service/config/impl/BurSarFeesFinesExportConfigServiceTest.java rename to src/test/java/org/folio/des/service/config/impl/BursarFeesFinesExportConfigServiceTest.java index 15067968..f8537461 100644 --- a/src/test/java/org/folio/des/service/config/impl/BurSarFeesFinesExportConfigServiceTest.java +++ b/src/test/java/org/folio/des/service/config/impl/BursarFeesFinesExportConfigServiceTest.java @@ -10,15 +10,22 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; import java.util.List; import java.util.UUID; - import org.folio.des.client.ConfigurationClient; import org.folio.des.config.JacksonConfiguration; import org.folio.des.config.ServiceConfiguration; import org.folio.des.config.scheduling.QuartzSchemaInitializer; import org.folio.des.converter.DefaultModelConfigToExportConfigConverter; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterCondition.OperationEnum; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.ConfigurationCollection; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportTypeSpecificParameters; @@ -35,13 +42,10 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - @SpringBootTest(classes = {DefaultModelConfigToExportConfigConverter.class, JacksonConfiguration.class, ServiceConfiguration.class}) @EnableAutoConfiguration(exclude = {BatchAutoConfiguration.class}) -class BurSarFeesFinesExportConfigServiceTest { +class BursarFeesFinesExportConfigServiceTest { public static final String CONFIG_RESPONSE = """ @@ -74,7 +78,7 @@ class BurSarFeesFinesExportConfigServiceTest { public static final String EMPTY_CONFIG_RESPONSE = "{\"configs\": [], \"totalRecords\": 0}"; @Autowired - private BurSarFeesFinesExportConfigService service; + private BursarFeesFinesExportConfigService service; @Autowired private DefaultModelConfigToExportConfigConverter defaultModelConfigToExportConfigConverter; @Autowired @@ -92,10 +96,25 @@ class BurSarFeesFinesExportConfigServiceTest { @DisplayName("Set new configuration") void addConfig() throws JsonProcessingException { ExportConfig bursarExportConfig = new ExportConfig(); + + bursarExportConfig.setId("0000-00-00-00-000000"); + ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); - bursarFeeFines.setDaysOutstanding(9); - bursarFeeFines.setPatronGroups(List.of(UUID.randomUUID().toString())); + + BursarExportJob bursarFeeFines = new BursarExportJob(); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId( + UUID.fromString("0000-00-00-00-000000") + ); + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); parameters.setBursarFeeFines(bursarFeeFines); bursarExportConfig.exportTypeSpecificParameters(parameters); ModelConfiguration mockResponse = mockResponse(bursarExportConfig); @@ -106,6 +125,7 @@ void addConfig() throws JsonProcessingException { Assertions.assertAll( () -> assertNotNull(response.getId()), + () -> assertEquals(mockResponse.getId(), response.getId()), () -> assertEquals(mockResponse.getConfigName(), response.getConfigName()), () -> assertEquals(mockResponse.getModule(), response.getModule()), () -> assertEquals(mockResponse.getDescription(), response.getDescription()), @@ -115,8 +135,11 @@ void addConfig() throws JsonProcessingException { } @Test - @DisplayName("Should not create new configuration without specific parameters") - void shouldNorCreateConfigurationAndThroughExceptionIfSpecificParametersIsNotSet() throws JsonProcessingException { + @DisplayName( + "Should not create new configuration without specific parameters" + ) + void shouldNorCreateConfigurationAndThroughExceptionIfSpecificParametersIsNotSet() + throws JsonProcessingException { ExportConfig bursarExportConfig = new ExportConfig(); ModelConfiguration mockResponse = mockResponse(bursarExportConfig); Mockito.when(client.postConfiguration(any())).thenReturn(mockResponse); @@ -127,7 +150,7 @@ void shouldNorCreateConfigurationAndThroughExceptionIfSpecificParametersIsNotSet @Test @DisplayName("Should not create new configuration without bur sar parameters") - void shouldNorCreateConfigurationAndThroughExceptionIfBurSarConfigIsNotSet() throws JsonProcessingException { + void shouldNorCreateConfigurationAndThroughExceptionIfBursarConfigIsNotSet() throws JsonProcessingException { ExportConfig bursarExportConfig = new ExportConfig(); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); bursarExportConfig.setExportTypeSpecificParameters(parameters); diff --git a/src/test/java/org/folio/des/service/config/impl/ExportTypeBasedConfigManagerTest.java b/src/test/java/org/folio/des/service/config/impl/ExportTypeBasedConfigManagerTest.java index 62d280e4..26b6ac03 100644 --- a/src/test/java/org/folio/des/service/config/impl/ExportTypeBasedConfigManagerTest.java +++ b/src/test/java/org/folio/des/service/config/impl/ExportTypeBasedConfigManagerTest.java @@ -10,13 +10,20 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; import java.util.List; import java.util.UUID; - import org.folio.des.client.ConfigurationClient; import org.folio.des.config.ServiceConfiguration; import org.folio.des.config.scheduling.QuartzSchemaInitializer; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportFilter; +import org.folio.des.domain.dto.BursarExportFilterAge; +import org.folio.des.domain.dto.BursarExportFilterCondition; +import org.folio.des.domain.dto.BursarExportFilterCondition.OperationEnum; +import org.folio.des.domain.dto.BursarExportFilterPatronGroup; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.ConfigurationCollection; import org.folio.des.domain.dto.ExportConfig; import org.folio.des.domain.dto.ExportConfig.SchedulePeriodEnum; @@ -39,11 +46,8 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -@SpringBootTest(classes = { ServiceConfiguration.class}) -@EnableAutoConfiguration(exclude = {BatchAutoConfiguration.class}) +@SpringBootTest(classes = { ServiceConfiguration.class }) +@EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class }) class ExportTypeBasedConfigManagerTest { public static final String CONFIG_RESPONSE = @@ -99,9 +103,19 @@ void addConfig(ExportType exportType, String exportName) throws JsonProcessingEx ExportConfig bursarExportConfig = new ExportConfig(); bursarExportConfig.setType(exportType); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); - BursarFeeFines bursarFeeFines = new BursarFeeFines(); - bursarFeeFines.setDaysOutstanding(9); - bursarFeeFines.setPatronGroups(List.of(UUID.randomUUID().toString())); + + BursarExportJob bursarFeeFines = new BursarExportJob(); + BursarExportFilterAge bursarExportFilterAge = new BursarExportFilterAge(); + bursarExportFilterAge.setNumDays(1); + BursarExportFilterPatronGroup bursarExportFilterPatronGroup = new BursarExportFilterPatronGroup(); + bursarExportFilterPatronGroup.setPatronGroupId(UUID.fromString("0000-00-00-00-000000")); + List bursarExportFilters = new ArrayList<>(); + bursarExportFilters.add(bursarExportFilterPatronGroup); + bursarExportFilters.add(bursarExportFilterAge); + BursarExportFilterCondition bursarExportFilterCondition = new BursarExportFilterCondition(); + bursarExportFilterCondition.setCriteria(bursarExportFilters); + bursarExportFilterCondition.setOperation(OperationEnum.AND); + bursarFeeFines.setFilter(bursarExportFilterCondition); parameters.setBursarFeeFines(bursarFeeFines); bursarExportConfig.exportTypeSpecificParameters(parameters); ModelConfiguration mockResponse = mockResponse(bursarExportConfig, exportName); @@ -146,7 +160,7 @@ void shouldThrowRequestValidationException() { @Test @DisplayName("Should not create new configuration without bur sar parameters") - void shouldNorCreateConfigurationAndThroughExceptionIfBurSarConfigIsNotSet() throws JsonProcessingException { + void shouldNorCreateConfigurationAndThroughExceptionIfBursarConfigIsNotSet() throws JsonProcessingException { ExportConfig bursarExportConfig = new ExportConfig(); ExportTypeSpecificParameters parameters = new ExportTypeSpecificParameters(); bursarExportConfig.setExportTypeSpecificParameters(parameters); @@ -223,7 +237,7 @@ void getConfig() throws JsonProcessingException { final ConfigurationCollection mockedResponse = objectMapper.readValue(CONFIG_RESPONSE, ConfigurationCollection.class); Mockito.when(client.getConfigurations(any(), eq(10))).thenReturn(mockedResponse); - var configs = service.getConfigCollection(null, 10); + var configs = service.getConfigCollection(null, 10); assertEquals(1, configs.getTotalRecords()); diff --git a/src/test/java/org/folio/des/validator/BurSarFeesFinesExportParametersValidatorTest.java b/src/test/java/org/folio/des/validator/BursarFeesFinesExportParametersValidatorTest.java similarity index 83% rename from src/test/java/org/folio/des/validator/BurSarFeesFinesExportParametersValidatorTest.java rename to src/test/java/org/folio/des/validator/BursarFeesFinesExportParametersValidatorTest.java index ba038cdc..fd0634e0 100644 --- a/src/test/java/org/folio/des/validator/BurSarFeesFinesExportParametersValidatorTest.java +++ b/src/test/java/org/folio/des/validator/BursarFeesFinesExportParametersValidatorTest.java @@ -3,7 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; -import org.folio.des.domain.dto.BursarFeeFines; +import org.folio.des.domain.dto.BursarExportJob; import org.folio.des.domain.dto.ExportTypeSpecificParameters; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,10 +11,10 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.validation.Errors; -@SpringBootTest(classes = { BurSarFeesFinesExportParametersValidator.class}) -class BurSarFeesFinesExportParametersValidatorTest { +@SpringBootTest(classes = { BursarFeesFinesExportParametersValidator.class}) +class BursarFeesFinesExportParametersValidatorTest { @Autowired - private BurSarFeesFinesExportParametersValidator validator; + private BursarFeesFinesExportParametersValidator validator; @Test @DisplayName("Should throw exception if specific parameters is Null") @@ -36,7 +36,7 @@ void shouldThrowExceptionIfBursarFeeFinesIsNull() { void shouldPassValidationIfBursarFeeFinesIsNotNull() { Errors errors = mock(Errors.class); ExportTypeSpecificParameters specificParameters = new ExportTypeSpecificParameters(); - specificParameters.setBursarFeeFines(new BursarFeeFines()); + specificParameters.setBursarFeeFines(new BursarExportJob()); validator.validate(specificParameters, errors); } }