diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 1ef4b43..8e8716e 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,8 +12,10 @@ diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml index eef8c4b..6df4889 100644 --- a/.idea/sqldialects.xml +++ b/.idea/sqldialects.xml @@ -1,7 +1,6 @@ - \ No newline at end of file diff --git a/pefi-common/build.gradle b/pefi-common/build.gradle index 4289aaa..b2f3404 100644 --- a/pefi-common/build.gradle +++ b/pefi-common/build.gradle @@ -11,9 +11,16 @@ repositories { dependencies { implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0' - implementation 'org.springframework:spring-web:6.1.1' + implementation 'org.springframework:spring-web:6.1.3' implementation 'org.springframework.data:spring-data-jpa:3.2.0' + implementation 'org.springframework.security:spring-security-oauth2-jose:6.2.0' + implementation 'org.springframework.security:spring-security-oauth2-resource-server:6.2.0' + implementation 'org.springframework.security:spring-security-web:6.2.0' + implementation 'org.springframework.security:spring-security-config:6.2.0' + implementation 'io.swagger.core.v3:swagger-models-jakarta:2.2.19' + implementation 'org.apache.commons:commons-lang3:3.13.0' + testImplementation platform('org.junit:junit-bom:5.9.1') testImplementation 'org.junit.jupiter:junit-jupiter' } diff --git a/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonControllerConfiguration.java b/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonControllerConfiguration.java new file mode 100644 index 0000000..1ef63f8 --- /dev/null +++ b/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonControllerConfiguration.java @@ -0,0 +1,50 @@ +package dev.mvvasilev.common.configuration; + +import dev.mvvasilev.common.web.APIErrorDTO; +import dev.mvvasilev.common.web.APIResponseDTO; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.List; + +@Configuration +public class CommonControllerConfiguration { + + @RestControllerAdvice(basePackages = {"dev.mvvasilev"}) + public static class APIResponseAdvice { + + @Value("${debug}") + private boolean isDebug = false; + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @ExceptionHandler(Exception.class) + public ResponseEntity> processGenericException(Exception ex) { + List errors = List.of( + new APIErrorDTO( + ex.getMessage(), + isDebug ? ex.getClass().getCanonicalName() : null, + isDebug ? ExceptionUtils.getStackTrace(ex) : null + ) + ); + + logger.error("Exception", ex); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new APIResponseDTO<>( + null, + errors, + HttpStatus.INTERNAL_SERVER_ERROR.value(), + HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase() + )); + } + } + +} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/configuration/SecurityConfiguration.java b/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonSecurityConfiguration.java similarity index 81% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/configuration/SecurityConfiguration.java rename to pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonSecurityConfiguration.java index 197e34e..304c8bd 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/configuration/SecurityConfiguration.java +++ b/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonSecurityConfiguration.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.configuration; +package dev.mvvasilev.common.configuration; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -16,7 +16,7 @@ import org.springframework.web.filter.CommonsRequestLoggingFilter; @Configuration @EnableTransactionManagement -public class SecurityConfiguration { +public class CommonSecurityConfiguration { @Value("${jwt.issuer-url}") public String jwtIssuerUrl; @@ -28,17 +28,6 @@ public class SecurityConfiguration { "/swagger-resources/**" }; - @Bean - public CommonsRequestLoggingFilter requestLoggingFilter() { - CommonsRequestLoggingFilter loggingFilter = new CommonsRequestLoggingFilter(); - loggingFilter.setIncludeClientInfo(true); - loggingFilter.setIncludeHeaders(true); - loggingFilter.setIncludeQueryString(true); - loggingFilter.setIncludePayload(true); - loggingFilter.setMaxPayloadLength(64000); - return loggingFilter; - } - @Bean public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, BearerTokenResolver bearerTokenResolver) throws Exception { return httpSecurity @@ -67,4 +56,4 @@ public class SecurityConfiguration { bearerTokenResolver.setBearerTokenHeaderName(HttpHeaders.AUTHORIZATION); return bearerTokenResolver; } -} +} \ No newline at end of file diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/configuration/SwaggerConfiguration.java b/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonSwaggerConfiguration.java similarity index 89% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/configuration/SwaggerConfiguration.java rename to pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonSwaggerConfiguration.java index dfc8c34..55bb5d0 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/configuration/SwaggerConfiguration.java +++ b/pefi-common/src/main/java/dev/mvvasilev/common/configuration/CommonSwaggerConfiguration.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.configuration; +package dev.mvvasilev.common.configuration; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; @@ -10,10 +10,10 @@ import org.springframework.context.annotation.Configuration; import java.util.List; @Configuration -public class SwaggerConfiguration { +public class CommonSwaggerConfiguration { @Bean - public OpenAPI customizeOpenAPI() { + public OpenAPI jwtAuth() { final String securitySchemeName = "bearerAuth"; return new OpenAPI() .components( diff --git a/pefi-common/src/main/java/dev/mvvasilev/common/dto/CreateProcessedTransactionDTO.java b/pefi-common/src/main/java/dev/mvvasilev/common/dto/CreateProcessedTransactionDTO.java new file mode 100644 index 0000000..00b9a2b --- /dev/null +++ b/pefi-common/src/main/java/dev/mvvasilev/common/dto/CreateProcessedTransactionDTO.java @@ -0,0 +1,69 @@ +package dev.mvvasilev.common.dto; + +import java.time.LocalDateTime; + +public class CreateProcessedTransactionDTO { + + private String description; + + private Integer userId; + + private Double amount; + + private boolean isInflow; + + private LocalDateTime timestamp; + + private Long statementId; + + public CreateProcessedTransactionDTO() { + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public Double getAmount() { + return amount; + } + + public void setAmount(Double amount) { + this.amount = amount; + } + + public boolean isInflow() { + return isInflow; + } + + public void setInflow(boolean inflow) { + isInflow = inflow; + } + + public LocalDateTime getTimestamp() { + return timestamp; + } + + public void setTimestamp(LocalDateTime timestamp) { + this.timestamp = timestamp; + } + + public Long getStatementId() { + return statementId; + } + + public void setStatementId(Long statementId) { + this.statementId = statementId; + } +} diff --git a/pefi-common/src/main/java/dev/mvvasilev/common/dto/ProcessedTransactionFieldDTO.java b/pefi-common/src/main/java/dev/mvvasilev/common/dto/ProcessedTransactionFieldDTO.java new file mode 100644 index 0000000..c63ff69 --- /dev/null +++ b/pefi-common/src/main/java/dev/mvvasilev/common/dto/ProcessedTransactionFieldDTO.java @@ -0,0 +1,11 @@ +package dev.mvvasilev.common.dto; + + +import dev.mvvasilev.common.enums.ProcessedTransactionField; +import dev.mvvasilev.common.enums.RawTransactionValueType; + +public record ProcessedTransactionFieldDTO( + ProcessedTransactionField field, + RawTransactionValueType type +) { +} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/ProcessedTransactionField.java b/pefi-common/src/main/java/dev/mvvasilev/common/enums/ProcessedTransactionField.java similarity index 86% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/ProcessedTransactionField.java rename to pefi-common/src/main/java/dev/mvvasilev/common/enums/ProcessedTransactionField.java index 2630666..41becf5 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/ProcessedTransactionField.java +++ b/pefi-common/src/main/java/dev/mvvasilev/common/enums/ProcessedTransactionField.java @@ -1,10 +1,7 @@ -package dev.mvvasilev.finances.enums; +package dev.mvvasilev.common.enums; import dev.mvvasilev.common.data.AbstractEnumConverter; import dev.mvvasilev.common.data.PersistableEnum; -import dev.mvvasilev.finances.entity.ProcessedTransaction; - -import java.lang.reflect.Method; public enum ProcessedTransactionField implements PersistableEnum { DESCRIPTION(RawTransactionValueType.STRING), diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/RawTransactionValueType.java b/pefi-common/src/main/java/dev/mvvasilev/common/enums/RawTransactionValueType.java similarity index 88% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/RawTransactionValueType.java rename to pefi-common/src/main/java/dev/mvvasilev/common/enums/RawTransactionValueType.java index 1037421..8c7b98a 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/RawTransactionValueType.java +++ b/pefi-common/src/main/java/dev/mvvasilev/common/enums/RawTransactionValueType.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.enums; +package dev.mvvasilev.common.enums; import dev.mvvasilev.common.data.PersistableEnum; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/AuthorizationService.java b/pefi-common/src/main/java/dev/mvvasilev/common/services/AuthorizationService.java similarity index 97% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/services/AuthorizationService.java rename to pefi-common/src/main/java/dev/mvvasilev/common/services/AuthorizationService.java index 44746d4..9b87e14 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/AuthorizationService.java +++ b/pefi-common/src/main/java/dev/mvvasilev/common/services/AuthorizationService.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.services; +package dev.mvvasilev.common.services; import jakarta.persistence.EntityManager; import org.springframework.beans.factory.annotation.Autowired; diff --git a/pefi-common/src/main/java/dev/mvvasilev/common/web/APIResponseDTO.java b/pefi-common/src/main/java/dev/mvvasilev/common/web/APIResponseDTO.java index 90d6cac..cb068fe 100644 --- a/pefi-common/src/main/java/dev/mvvasilev/common/web/APIResponseDTO.java +++ b/pefi-common/src/main/java/dev/mvvasilev/common/web/APIResponseDTO.java @@ -1,5 +1,13 @@ package dev.mvvasilev.common.web; +import org.springframework.http.ResponseEntity; + import java.util.Collection; -public record APIResponseDTO(T result, Collection errors, int statusCode, String statusText) { } +public record APIResponseDTO( + T result, + Collection errors, + int statusCode, + String statusText +) +{ } diff --git a/pefi-monolith/.env.example b/pefi-core-api/.env.example similarity index 100% rename from pefi-monolith/.env.example rename to pefi-core-api/.env.example diff --git a/pefi-monolith/.gitignore b/pefi-core-api/.gitignore similarity index 100% rename from pefi-monolith/.gitignore rename to pefi-core-api/.gitignore diff --git a/pefi-monolith/Dockerfile b/pefi-core-api/Dockerfile similarity index 100% rename from pefi-monolith/Dockerfile rename to pefi-core-api/Dockerfile diff --git a/pefi-monolith/build.gradle b/pefi-core-api/build.gradle similarity index 68% rename from pefi-monolith/build.gradle rename to pefi-core-api/build.gradle index bb25f91..86f46c3 100644 --- a/pefi-monolith/build.gradle +++ b/pefi-core-api/build.gradle @@ -24,23 +24,19 @@ ext['spring-security.version']='6.2.0' dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' - // implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.flywaydb:flyway-core' - implementation 'org.springdoc:springdoc-openapi-starter-common:2.3.0' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' - implementation 'org.apache.poi:poi:5.2.5' - implementation 'org.apache.poi:poi-ooxml:5.2.5' + implementation 'org.apache.commons:commons-lang3:3.14.0' implementation project(":pefi-common") - runtimeOnly 'com.h2database:h2' runtimeOnly 'org.postgresql:postgresql' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.security:spring-security-test' + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.mockito:mockito-core:5.7.0' } dependencyManagement { diff --git a/pefi-core-api/settings.gradle b/pefi-core-api/settings.gradle new file mode 100644 index 0000000..927d116 --- /dev/null +++ b/pefi-core-api/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'pefi-core-api' diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/PersonalFinancesServiceApplication.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/PefiCoreAPI.java similarity index 66% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/PersonalFinancesServiceApplication.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/PefiCoreAPI.java index 71fd1c8..2361621 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/PersonalFinancesServiceApplication.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/PefiCoreAPI.java @@ -1,17 +1,18 @@ package dev.mvvasilev.finances; +import dev.mvvasilev.common.services.AuthorizationService; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -@SpringBootApplication +@SpringBootApplication(scanBasePackageClasses = { AuthorizationService.class }) @EnableJpaRepositories("dev.mvvasilev.finances.*") @EntityScan("dev.mvvasilev.finances.*") -public class PersonalFinancesServiceApplication { +public class PefiCoreAPI { public static void main(String[] args) { - SpringApplication.run(PersonalFinancesServiceApplication.class, args); + SpringApplication.run(PefiCoreAPI.class, args); } } diff --git a/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/ControllerConfiguration.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/ControllerConfiguration.java new file mode 100644 index 0000000..18d4ac6 --- /dev/null +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/ControllerConfiguration.java @@ -0,0 +1,8 @@ +package dev.mvvasilev.finances.configuration; + +import dev.mvvasilev.common.configuration.CommonControllerConfiguration; +import org.springframework.context.annotation.Import; + +@Import(CommonControllerConfiguration.class) +public class ControllerConfiguration { +} diff --git a/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/SecurityConfiguration.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/SecurityConfiguration.java new file mode 100644 index 0000000..1087cdb --- /dev/null +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/SecurityConfiguration.java @@ -0,0 +1,20 @@ +package dev.mvvasilev.finances.configuration; + +import dev.mvvasilev.common.configuration.CommonSecurityConfiguration; +import dev.mvvasilev.common.configuration.CommonSwaggerConfiguration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.oauth2.jwt.JwtDecoder; +import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.web.filter.CommonsRequestLoggingFilter; + +@Configuration +@Import(CommonSwaggerConfiguration.class) +@EnableTransactionManagement +public class SecurityConfiguration { +} diff --git a/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/SwaggerConfiguration.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/SwaggerConfiguration.java new file mode 100644 index 0000000..2383797 --- /dev/null +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/configuration/SwaggerConfiguration.java @@ -0,0 +1,12 @@ +package dev.mvvasilev.finances.configuration; + +import dev.mvvasilev.common.configuration.CommonSwaggerConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(CommonSwaggerConfiguration.class) +public class SwaggerConfiguration { + +} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/CategoriesController.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/CategoriesController.java similarity index 92% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/CategoriesController.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/CategoriesController.java index cee57e8..d518cd8 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/CategoriesController.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/CategoriesController.java @@ -35,16 +35,6 @@ public class CategoriesController extends AbstractRestController { this.objectMapper = objectMapper; } - @GetMapping("/rules") - public ResponseEntity>> fetchCategorizationRules() { - return ok( - Arrays.stream(CategorizationRule.values()).map(r -> new CategorizationRuleDTO( - r, - r.applicableForType() - )).toList() - ); - } - @PostMapping public ResponseEntity> createCategory( @RequestBody CreateCategoryDTO dto, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/DebugController.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/DebugController.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/DebugController.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/DebugController.java diff --git a/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/EnumsController.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/EnumsController.java new file mode 100644 index 0000000..8a0ff65 --- /dev/null +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/EnumsController.java @@ -0,0 +1,40 @@ +package dev.mvvasilev.finances.controllers; + +import dev.mvvasilev.common.controller.AbstractRestController; +import dev.mvvasilev.common.enums.ProcessedTransactionField; +import dev.mvvasilev.common.web.APIResponseDTO; +import dev.mvvasilev.finances.dtos.CategorizationRuleDTO; +import dev.mvvasilev.finances.dtos.ProcessedTransactionFieldDTO; +import dev.mvvasilev.finances.enums.CategorizationRule; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.Collection; + +@RestController +@RequestMapping("/enums") +public class EnumsController extends AbstractRestController { + + @GetMapping("/category-rules") + public ResponseEntity>> fetchCategorizationRules() { + return ok( + Arrays.stream(CategorizationRule.values()).map(r -> new CategorizationRuleDTO( + r, + r.applicableForType() + )).toList() + ); + } + + @GetMapping("/processed-transaction-fields") + public ResponseEntity>> fetchFields() { + return ok( + Arrays.stream(ProcessedTransactionField.values()) + .map(field -> new ProcessedTransactionFieldDTO(field, field.type())) + .toList() + ); + } + +} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/ProcessedTransactionsController.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/ProcessedTransactionsController.java similarity index 68% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/ProcessedTransactionsController.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/ProcessedTransactionsController.java index dd63c67..91f4b16 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/ProcessedTransactionsController.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/ProcessedTransactionsController.java @@ -3,26 +3,17 @@ package dev.mvvasilev.finances.controllers; import dev.mvvasilev.common.controller.AbstractRestController; import dev.mvvasilev.common.web.APIResponseDTO; import dev.mvvasilev.finances.dtos.ProcessedTransactionDTO; -import dev.mvvasilev.finances.dtos.ProcessedTransactionFieldDTO; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; import dev.mvvasilev.finances.services.ProcessedTransactionService; -import jakarta.validation.constraints.Max; import jakarta.validation.constraints.NotNull; -import org.hibernate.validator.constraints.Length; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.Arrays; -import java.util.Collection; - @RestController @RequestMapping("/processed-transactions") public class ProcessedTransactionsController extends AbstractRestController { @@ -34,15 +25,6 @@ public class ProcessedTransactionsController extends AbstractRestController { this.processedTransactionService = processedTransactionService; } - @GetMapping("/fields") - public ResponseEntity>> fetchFields() { - return ok( - Arrays.stream(ProcessedTransactionField.values()) - .map(field -> new ProcessedTransactionFieldDTO(field, field.type())) - .toList() - ); - } - @GetMapping public ResponseEntity>> fetchProcessedTransactions( Authentication authentication, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/StatisticsController.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/StatisticsController.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/StatisticsController.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/controllers/StatisticsController.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategorizationDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategorizationDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategorizationDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategorizationDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategorizationRuleDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategorizationRuleDTO.java similarity index 78% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategorizationRuleDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategorizationRuleDTO.java index e744909..e59c3b4 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategorizationRuleDTO.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategorizationRuleDTO.java @@ -1,7 +1,7 @@ package dev.mvvasilev.finances.dtos; +import dev.mvvasilev.common.enums.RawTransactionValueType; import dev.mvvasilev.finances.enums.CategorizationRule; -import dev.mvvasilev.finances.enums.RawTransactionValueType; public record CategorizationRuleDTO( CategorizationRule rule, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategoryDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategoryDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CategoryDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CategoryDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateCategorizationDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CreateCategorizationDTO.java similarity index 90% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateCategorizationDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CreateCategorizationDTO.java index 75789b6..198dd2a 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateCategorizationDTO.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CreateCategorizationDTO.java @@ -1,8 +1,6 @@ package dev.mvvasilev.finances.dtos; import dev.mvvasilev.finances.enums.CategorizationRule; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; -import jakarta.annotation.Nullable; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateCategoryDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CreateCategoryDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateCategoryDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/CreateCategoryDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ImportExportCategoriesDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ImportExportCategoriesDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ImportExportCategoriesDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ImportExportCategoriesDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionFieldDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionFieldDTO.java similarity index 57% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionFieldDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionFieldDTO.java index 6855a88..161e9bb 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionFieldDTO.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/ProcessedTransactionFieldDTO.java @@ -1,7 +1,7 @@ package dev.mvvasilev.finances.dtos; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; -import dev.mvvasilev.finances.enums.RawTransactionValueType; +import dev.mvvasilev.common.enums.ProcessedTransactionField; +import dev.mvvasilev.common.enums.RawTransactionValueType; public record ProcessedTransactionFieldDTO( ProcessedTransactionField field, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoriesDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoriesDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoriesDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoriesDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoryDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoryDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoryDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/SpendingByCategoryDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SpendingOverTimeByCategoryDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/SpendingOverTimeByCategoryDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SpendingOverTimeByCategoryDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/SpendingOverTimeByCategoryDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionCategoryDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/TransactionCategoryDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionCategoryDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/TransactionCategoryDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/UpdateCategoryDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/UpdateCategoryDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/UpdateCategoryDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/dtos/UpdateCategoryDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/Categorization.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/Categorization.java similarity index 98% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/Categorization.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/Categorization.java index e1bcbbf..a6a9cb8 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/Categorization.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/Categorization.java @@ -3,7 +3,6 @@ package dev.mvvasilev.finances.entity; import dev.mvvasilev.common.data.AbstractEntity; import dev.mvvasilev.common.data.UserOwned; import dev.mvvasilev.finances.enums.CategorizationRule; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.Table; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransaction.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransaction.java similarity index 63% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransaction.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransaction.java index be9134d..99cff09 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransaction.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransaction.java @@ -2,29 +2,15 @@ package dev.mvvasilev.finances.entity; import dev.mvvasilev.common.data.AbstractEntity; import dev.mvvasilev.common.data.UserOwned; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; import jakarta.persistence.Entity; import jakarta.persistence.Table; import java.time.LocalDateTime; -import java.util.Map; @Entity @Table(schema = "transactions") public class ProcessedTransaction extends AbstractEntity implements UserOwned { - // This const is a result of the limitations of the JVM. - // It is impossible to refer to either a field, or method of a class statically. - // Because of this, it is very difficult to tie the ProcessedTransactionField values to the actual class fields they represent. - // To resolve this imperfection, this const lives here, in plain view, so when one of the fields is changed, - // hopefully the programmer remembers to change the value inside as well. - public static final Map FIELD_NAMES = Map.of( - ProcessedTransactionField.DESCRIPTION, "description", - ProcessedTransactionField.AMOUNT, "amount", - ProcessedTransactionField.IS_INFLOW, "isInflow", - ProcessedTransactionField.TIMESTAMP, "timestamp" - ); - private String description; private Integer userId; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransactionCategory.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransactionCategory.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransactionCategory.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/ProcessedTransactionCategory.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/TransactionCategory.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/TransactionCategory.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/TransactionCategory.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/entity/TransactionCategory.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/CategorizationRule.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/CategorizationRule.java similarity index 96% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/CategorizationRule.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/CategorizationRule.java index fea625e..4b4705b 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/CategorizationRule.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/CategorizationRule.java @@ -2,6 +2,7 @@ package dev.mvvasilev.finances.enums; import dev.mvvasilev.common.data.AbstractEnumConverter; import dev.mvvasilev.common.data.PersistableEnum; +import dev.mvvasilev.common.enums.RawTransactionValueType; // TODO: Create custom converter for JPA public enum CategorizationRule implements PersistableEnum { diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/CategorizationRuleBehavior.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/CategorizationRuleBehavior.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/CategorizationRuleBehavior.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/CategorizationRuleBehavior.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/TimePeriod.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/TimePeriod.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/TimePeriod.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/enums/TimePeriod.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/CategorizationRepository.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/CategorizationRepository.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/CategorizationRepository.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/CategorizationRepository.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionCategoryRepository.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionCategoryRepository.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionCategoryRepository.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionCategoryRepository.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionRepository.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionRepository.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionRepository.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/ProcessedTransactionRepository.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/StatisticsRepository.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/StatisticsRepository.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/StatisticsRepository.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/StatisticsRepository.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/TransactionCategoryRepository.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/TransactionCategoryRepository.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/TransactionCategoryRepository.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/TransactionCategoryRepository.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/SpendingOverTimeDTO.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/dtos/SpendingOverTimeDTO.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/SpendingOverTimeDTO.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/persistence/dtos/SpendingOverTimeDTO.java diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/CategoryService.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/services/CategoryService.java similarity index 99% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/services/CategoryService.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/services/CategoryService.java index 799fb22..00c112b 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/CategoryService.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/services/CategoryService.java @@ -9,7 +9,6 @@ import dev.mvvasilev.finances.persistence.CategorizationRepository; import dev.mvvasilev.finances.persistence.ProcessedTransactionCategoryRepository; import dev.mvvasilev.finances.persistence.ProcessedTransactionRepository; import dev.mvvasilev.finances.persistence.TransactionCategoryRepository; -import org.apache.commons.compress.utils.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/ProcessedTransactionService.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/services/ProcessedTransactionService.java similarity index 97% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/services/ProcessedTransactionService.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/services/ProcessedTransactionService.java index 5ad05a3..2a59b82 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/ProcessedTransactionService.java +++ b/pefi-core-api/src/main/java/dev/mvvasilev/finances/services/ProcessedTransactionService.java @@ -5,7 +5,6 @@ import dev.mvvasilev.finances.dtos.TransactionCategoryDTO; import dev.mvvasilev.finances.entity.ProcessedTransaction; import dev.mvvasilev.finances.persistence.ProcessedTransactionRepository; import dev.mvvasilev.finances.persistence.TransactionCategoryRepository; -import org.apache.commons.compress.utils.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.*; import org.springframework.stereotype.Service; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/StatisticsService.java b/pefi-core-api/src/main/java/dev/mvvasilev/finances/services/StatisticsService.java similarity index 100% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/services/StatisticsService.java rename to pefi-core-api/src/main/java/dev/mvvasilev/finances/services/StatisticsService.java diff --git a/pefi-monolith/src/main/resources/application.properties b/pefi-core-api/src/main/resources/application.properties similarity index 100% rename from pefi-monolith/src/main/resources/application.properties rename to pefi-core-api/src/main/resources/application.properties diff --git a/pefi-monolith/src/main/resources/db/migration/.gitkeep b/pefi-core-api/src/main/resources/db/migration/.gitkeep similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/.gitkeep rename to pefi-core-api/src/main/resources/db/migration/.gitkeep diff --git a/pefi-monolith/src/main/resources/db/migration/V1.0__CreateTransactionTables.sql b/pefi-core-api/src/main/resources/db/migration/V1.0__CreateTransactionTables.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.0__CreateTransactionTables.sql rename to pefi-core-api/src/main/resources/db/migration/V1.0__CreateTransactionTables.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.10__CreateProcessedTransactionCategory.sql b/pefi-core-api/src/main/resources/db/migration/V1.10__CreateProcessedTransactionCategory.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.10__CreateProcessedTransactionCategory.sql rename to pefi-core-api/src/main/resources/db/migration/V1.10__CreateProcessedTransactionCategory.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.11__CreateTransactionMapping.sql b/pefi-core-api/src/main/resources/db/migration/V1.11__CreateTransactionMapping.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.11__CreateTransactionMapping.sql rename to pefi-core-api/src/main/resources/db/migration/V1.11__CreateTransactionMapping.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.12__CreateCategorization.sql b/pefi-core-api/src/main/resources/db/migration/V1.12__CreateCategorization.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.12__CreateCategorization.sql rename to pefi-core-api/src/main/resources/db/migration/V1.12__CreateCategorization.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.13__AddMappingConversions.sql b/pefi-core-api/src/main/resources/db/migration/V1.13__AddMappingConversions.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.13__AddMappingConversions.sql rename to pefi-core-api/src/main/resources/db/migration/V1.13__AddMappingConversions.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.14__RemoveStatementIdFromMapping.sql b/pefi-core-api/src/main/resources/db/migration/V1.14__RemoveStatementIdFromMapping.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.14__RemoveStatementIdFromMapping.sql rename to pefi-core-api/src/main/resources/db/migration/V1.14__RemoveStatementIdFromMapping.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.15__AddCategoryRuleBehavior.sql b/pefi-core-api/src/main/resources/db/migration/V1.15__AddCategoryRuleBehavior.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.15__AddCategoryRuleBehavior.sql rename to pefi-core-api/src/main/resources/db/migration/V1.15__AddCategoryRuleBehavior.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.16__AddCategorizationIsRoot.sql b/pefi-core-api/src/main/resources/db/migration/V1.16__AddCategorizationIsRoot.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.16__AddCategorizationIsRoot.sql rename to pefi-core-api/src/main/resources/db/migration/V1.16__AddCategorizationIsRoot.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.17__AddSpendingOverTimeFunction.sql b/pefi-core-api/src/main/resources/db/migration/V1.17__AddSpendingOverTimeFunction.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.17__AddSpendingOverTimeFunction.sql rename to pefi-core-api/src/main/resources/db/migration/V1.17__AddSpendingOverTimeFunction.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.18__AddWidget.sql b/pefi-core-api/src/main/resources/db/migration/V1.18__AddWidget.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.18__AddWidget.sql rename to pefi-core-api/src/main/resources/db/migration/V1.18__AddWidget.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.19__AddWidgetParameter.sql b/pefi-core-api/src/main/resources/db/migration/V1.19__AddWidgetParameter.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.19__AddWidgetParameter.sql rename to pefi-core-api/src/main/resources/db/migration/V1.19__AddWidgetParameter.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.1__AddUserIdToRawStatement.sql b/pefi-core-api/src/main/resources/db/migration/V1.1__AddUserIdToRawStatement.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.1__AddUserIdToRawStatement.sql rename to pefi-core-api/src/main/resources/db/migration/V1.1__AddUserIdToRawStatement.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.20__MakeCategorizationFKCascade.sql b/pefi-core-api/src/main/resources/db/migration/V1.20__MakeCategorizationFKCascade.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.20__MakeCategorizationFKCascade.sql rename to pefi-core-api/src/main/resources/db/migration/V1.20__MakeCategorizationFKCascade.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.2__AddBooleanValueToRawTransactionValue.sql b/pefi-core-api/src/main/resources/db/migration/V1.2__AddBooleanValueToRawTransactionValue.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.2__AddBooleanValueToRawTransactionValue.sql rename to pefi-core-api/src/main/resources/db/migration/V1.2__AddBooleanValueToRawTransactionValue.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.3__AddTransactionCategory.sql b/pefi-core-api/src/main/resources/db/migration/V1.3__AddTransactionCategory.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.3__AddTransactionCategory.sql rename to pefi-core-api/src/main/resources/db/migration/V1.3__AddTransactionCategory.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.4__AddProcessedTransaction.sql b/pefi-core-api/src/main/resources/db/migration/V1.4__AddProcessedTransaction.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.4__AddProcessedTransaction.sql rename to pefi-core-api/src/main/resources/db/migration/V1.4__AddProcessedTransaction.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.5__AddUserIdToTransactionCategory.sql b/pefi-core-api/src/main/resources/db/migration/V1.5__AddUserIdToTransactionCategory.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.5__AddUserIdToTransactionCategory.sql rename to pefi-core-api/src/main/resources/db/migration/V1.5__AddUserIdToTransactionCategory.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.6__AddRowIndexToRawTransactionValue.sql b/pefi-core-api/src/main/resources/db/migration/V1.6__AddRowIndexToRawTransactionValue.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.6__AddRowIndexToRawTransactionValue.sql rename to pefi-core-api/src/main/resources/db/migration/V1.6__AddRowIndexToRawTransactionValue.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.7__AddNameToRawStatement.sql b/pefi-core-api/src/main/resources/db/migration/V1.7__AddNameToRawStatement.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.7__AddNameToRawStatement.sql rename to pefi-core-api/src/main/resources/db/migration/V1.7__AddNameToRawStatement.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.8__AddOnDeleteCascadeRawStatement.sql b/pefi-core-api/src/main/resources/db/migration/V1.8__AddOnDeleteCascadeRawStatement.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.8__AddOnDeleteCascadeRawStatement.sql rename to pefi-core-api/src/main/resources/db/migration/V1.8__AddOnDeleteCascadeRawStatement.sql diff --git a/pefi-monolith/src/main/resources/db/migration/V1.9__AlterProcessedTransaction_RemoveCategoryId.sql b/pefi-core-api/src/main/resources/db/migration/V1.9__AlterProcessedTransaction_RemoveCategoryId.sql similarity index 100% rename from pefi-monolith/src/main/resources/db/migration/V1.9__AlterProcessedTransaction_RemoveCategoryId.sql rename to pefi-core-api/src/main/resources/db/migration/V1.9__AlterProcessedTransaction_RemoveCategoryId.sql diff --git a/pefi-monolith/src/test/java/dev/mvvasilev/finances/CategorizationBuilder.java b/pefi-core-api/src/test/java/dev/mvvasilev/finances/CategorizationBuilder.java similarity index 99% rename from pefi-monolith/src/test/java/dev/mvvasilev/finances/CategorizationBuilder.java rename to pefi-core-api/src/test/java/dev/mvvasilev/finances/CategorizationBuilder.java index 45b08cd..906690b 100644 --- a/pefi-monolith/src/test/java/dev/mvvasilev/finances/CategorizationBuilder.java +++ b/pefi-core-api/src/test/java/dev/mvvasilev/finances/CategorizationBuilder.java @@ -2,7 +2,6 @@ package dev.mvvasilev.finances; import dev.mvvasilev.finances.entity.Categorization; import dev.mvvasilev.finances.enums.CategorizationRule; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; import org.apache.commons.lang3.RandomUtils; import java.time.LocalDateTime; diff --git a/pefi-monolith/src/test/java/dev/mvvasilev/finances/CategoryServiceTests.java b/pefi-core-api/src/test/java/dev/mvvasilev/finances/CategoryServiceTests.java similarity index 100% rename from pefi-monolith/src/test/java/dev/mvvasilev/finances/CategoryServiceTests.java rename to pefi-core-api/src/test/java/dev/mvvasilev/finances/CategoryServiceTests.java diff --git a/pefi-monolith/settings.gradle b/pefi-monolith/settings.gradle deleted file mode 100644 index 972c762..0000000 --- a/pefi-monolith/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'pefi-monolith' diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/advice/APIResponseAdvice.java b/pefi-monolith/src/main/java/dev/mvvasilev/finances/advice/APIResponseAdvice.java deleted file mode 100644 index 4a48c0c..0000000 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/advice/APIResponseAdvice.java +++ /dev/null @@ -1,43 +0,0 @@ -package dev.mvvasilev.finances.advice; - -import dev.mvvasilev.common.web.APIErrorDTO; -import dev.mvvasilev.common.web.APIResponseDTO; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -import java.util.List; - -@RestControllerAdvice(basePackages = {"dev.mvvasilev"}) -public class APIResponseAdvice { - - @Value("${debug}") - private boolean isDebug; - - private Logger logger = LoggerFactory.getLogger(this.getClass()); - - @ExceptionHandler(Exception.class) - public ResponseEntity> processGenericException(Exception ex) { - List errors = List.of( - new APIErrorDTO( - ex.getMessage(), - isDebug ? ex.getClass().getCanonicalName() : null, - isDebug ? ExceptionUtils.getStackTrace(ex) : null - ) - ); - - logger.error("Exception", ex); - - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(new APIResponseDTO<>( - null, - errors, - HttpStatus.INTERNAL_SERVER_ERROR.value(), - HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase() - )); - } -} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawTransactionDTO.java b/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawTransactionDTO.java deleted file mode 100644 index d4f0079..0000000 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawTransactionDTO.java +++ /dev/null @@ -1,4 +0,0 @@ -package dev.mvvasilev.finances.persistence.dtos; - -public interface RawTransactionDTO { -} diff --git a/pefi-statements-api/.env.example b/pefi-statements-api/.env.example new file mode 100644 index 0000000..a7c6912 --- /dev/null +++ b/pefi-statements-api/.env.example @@ -0,0 +1,7 @@ +PROFILE= production/development + +AUTHENTIK_ISSUER_URL= auth server configuration url for fetching JWKs ( dev: https://auth.mvvasilev.dev/application/o/personal-finances/ ) + +DATASOURCE_URL= database jdbc url ( postgres only, example: jdbc:postgresql://localhost:5432/mydatabase ) +DATASOURCE_USER= database user +DATASOURCE_PASSWORD= database password \ No newline at end of file diff --git a/pefi-statements-api/Dockerfile b/pefi-statements-api/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/pefi-statements-api/build.gradle b/pefi-statements-api/build.gradle new file mode 100644 index 0000000..0840ec0 --- /dev/null +++ b/pefi-statements-api/build.gradle @@ -0,0 +1,36 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.2.0' + id 'io.spring.dependency-management' version '1.1.3' +} + +group = 'dev.mvvasilev.statements' +version = '0.0.1-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + + implementation 'org.flywaydb:flyway-core' + implementation 'org.springdoc:springdoc-openapi-starter-common:2.3.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' + implementation 'org.apache.poi:poi:5.2.5' + implementation 'org.apache.poi:poi-ooxml:5.2.5' + + implementation project(":pefi-common") + + runtimeOnly 'org.postgresql:postgresql' + + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/pefi-statements-api/settings.gradle b/pefi-statements-api/settings.gradle new file mode 100644 index 0000000..7cc53ab --- /dev/null +++ b/pefi-statements-api/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'pefi-statements-api' \ No newline at end of file diff --git a/pefi-statements-api/src/main/java/dev/mvvasilev/statements/PefiStatementsAPI.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/PefiStatementsAPI.java new file mode 100644 index 0000000..39b8f92 --- /dev/null +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/PefiStatementsAPI.java @@ -0,0 +1,16 @@ +package dev.mvvasilev.statements; + +import dev.mvvasilev.common.services.AuthorizationService; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication(scanBasePackageClasses = { AuthorizationService.class }) +@EnableJpaRepositories("dev.mvvasilev.statements.*") +@EntityScan("dev.mvvasilev.statements.*") +public class PefiStatementsAPI { + public static void main(String[] args) { + SpringApplication.run(PefiStatementsAPI.class, args); + } +} \ No newline at end of file diff --git a/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/ControllerConfiguration.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/ControllerConfiguration.java new file mode 100644 index 0000000..c4fbb75 --- /dev/null +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/ControllerConfiguration.java @@ -0,0 +1,8 @@ +package dev.mvvasilev.statements.configuration; + +import dev.mvvasilev.common.configuration.CommonControllerConfiguration; +import org.springframework.context.annotation.Import; + +@Import(CommonControllerConfiguration.class) +public class ControllerConfiguration { +} diff --git a/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/SecurityConfiguration.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/SecurityConfiguration.java new file mode 100644 index 0000000..92cda84 --- /dev/null +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/SecurityConfiguration.java @@ -0,0 +1,12 @@ +package dev.mvvasilev.statements.configuration; + +import dev.mvvasilev.common.configuration.CommonSwaggerConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@Import(CommonSwaggerConfiguration.class) +@EnableTransactionManagement +public class SecurityConfiguration { +} diff --git a/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/SwaggerConfiguration.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/SwaggerConfiguration.java new file mode 100644 index 0000000..5a26249 --- /dev/null +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/configuration/SwaggerConfiguration.java @@ -0,0 +1,11 @@ +package dev.mvvasilev.statements.configuration; + +import dev.mvvasilev.common.configuration.CommonSwaggerConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(CommonSwaggerConfiguration.class) +public class SwaggerConfiguration { + +} diff --git a/pefi-statements-api/src/main/java/dev/mvvasilev/statements/controllers/EnumsController.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/controllers/EnumsController.java new file mode 100644 index 0000000..1cc9b8c --- /dev/null +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/controllers/EnumsController.java @@ -0,0 +1,28 @@ +package dev.mvvasilev.statements.controllers; + +import dev.mvvasilev.common.controller.AbstractRestController; +import dev.mvvasilev.common.web.APIResponseDTO; +import dev.mvvasilev.statements.dto.SupportedMappingConversionDTO; +import dev.mvvasilev.statements.enums.MappingConversionType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.Collection; + +@RestController +@RequestMapping("/enums") +public class EnumsController extends AbstractRestController { + + @GetMapping("/supported-conversions") + public ResponseEntity>> fetchTransactionMappings() { + return ok(Arrays.stream(MappingConversionType.values()).map(conv -> new SupportedMappingConversionDTO( + conv, + conv.getFrom(), + conv.getTo() + )).toList()); + } + +} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/StatementsController.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/controllers/StatementsController.java similarity index 86% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/StatementsController.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/controllers/StatementsController.java index 685f5f1..b228225 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/StatementsController.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/controllers/StatementsController.java @@ -1,11 +1,13 @@ -package dev.mvvasilev.finances.controllers; +package dev.mvvasilev.statements.controllers; import dev.mvvasilev.common.controller.AbstractRestController; import dev.mvvasilev.common.web.APIResponseDTO; import dev.mvvasilev.common.web.CrudResponseDTO; -import dev.mvvasilev.finances.dtos.*; -import dev.mvvasilev.finances.enums.MappingConversionType; -import dev.mvvasilev.finances.services.StatementsService; +import dev.mvvasilev.statements.dto.CreateTransactionMappingDTO; +import dev.mvvasilev.statements.dto.TransactionMappingDTO; +import dev.mvvasilev.statements.dto.TransactionValueGroupDTO; +import dev.mvvasilev.statements.dto.UploadedStatementDTO; +import dev.mvvasilev.statements.service.StatementsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -15,7 +17,6 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; -import java.util.Arrays; import java.util.Collection; @RestController @@ -50,15 +51,6 @@ public class StatementsController extends AbstractRestController { return ok(statementsService.fetchMappingsForStatement(statementId)); } - @GetMapping("/supported-conversions") - public ResponseEntity>> fetchTransactionMappings() { - return ok(Arrays.stream(MappingConversionType.values()).map(conv -> new SupportedMappingConversionDTO( - conv, - conv.getFrom(), - conv.getTo() - )).toList()); - } - @PostMapping("/{statementId}/mappings") @PreAuthorize("@authService.isOwner(#statementId, T(dev.mvvasilev.finances.entity.RawStatement))") public ResponseEntity>> createTransactionMappings( diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateTransactionMappingDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/CreateTransactionMappingDTO.java similarity index 73% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateTransactionMappingDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/CreateTransactionMappingDTO.java index 6570a21..ce237e2 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateTransactionMappingDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/CreateTransactionMappingDTO.java @@ -1,7 +1,7 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.statements.dto; -import dev.mvvasilev.finances.enums.MappingConversionType; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; +import dev.mvvasilev.common.enums.ProcessedTransactionField; +import dev.mvvasilev.statements.enums.MappingConversionType; import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SupportedMappingConversionDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/SupportedMappingConversionDTO.java similarity index 50% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SupportedMappingConversionDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/SupportedMappingConversionDTO.java index f126d60..4d6fbc3 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/SupportedMappingConversionDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/SupportedMappingConversionDTO.java @@ -1,7 +1,8 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.statements.dto; -import dev.mvvasilev.finances.enums.MappingConversionType; -import dev.mvvasilev.finances.enums.RawTransactionValueType; + +import dev.mvvasilev.common.enums.RawTransactionValueType; +import dev.mvvasilev.statements.enums.MappingConversionType; public record SupportedMappingConversionDTO( MappingConversionType type, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionMappingDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/TransactionMappingDTO.java similarity index 65% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionMappingDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/TransactionMappingDTO.java index 87c0231..2c76e4f 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionMappingDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/TransactionMappingDTO.java @@ -1,7 +1,6 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.statements.dto; -import dev.mvvasilev.finances.enums.MappingConversionType; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; +import dev.mvvasilev.common.dto.ProcessedTransactionFieldDTO; public record TransactionMappingDTO( Long id, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionValueGroupDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/TransactionValueGroupDTO.java similarity index 55% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionValueGroupDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/TransactionValueGroupDTO.java index 7799925..e701227 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/TransactionValueGroupDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/TransactionValueGroupDTO.java @@ -1,6 +1,7 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.statements.dto; -import dev.mvvasilev.finances.enums.RawTransactionValueType; + +import dev.mvvasilev.common.enums.RawTransactionValueType; public record TransactionValueGroupDTO( Long id, diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/UploadedStatementDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/UploadedStatementDTO.java similarity index 79% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/UploadedStatementDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/UploadedStatementDTO.java index b4572ae..bf0c31c 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/UploadedStatementDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/dto/UploadedStatementDTO.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.statements.dto; import java.time.LocalDateTime; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawStatement.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawStatement.java similarity index 93% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawStatement.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawStatement.java index eda00ae..4a4992f 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawStatement.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawStatement.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.entity; +package dev.mvvasilev.statements.entity; import dev.mvvasilev.common.data.AbstractEntity; import dev.mvvasilev.common.data.UserOwned; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawTransactionValue.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawTransactionValue.java similarity index 90% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawTransactionValue.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawTransactionValue.java index 3858b26..3e5443c 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawTransactionValue.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawTransactionValue.java @@ -1,11 +1,10 @@ -package dev.mvvasilev.finances.entity; +package dev.mvvasilev.statements.entity; import dev.mvvasilev.common.data.AbstractEntity; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.time.LocalDateTime; -import java.util.Map; @Entity @Table(schema = "transactions") diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawTransactionValueGroup.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawTransactionValueGroup.java similarity index 89% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawTransactionValueGroup.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawTransactionValueGroup.java index 83dc05b..ddb8434 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/RawTransactionValueGroup.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/RawTransactionValueGroup.java @@ -1,7 +1,7 @@ -package dev.mvvasilev.finances.entity; +package dev.mvvasilev.statements.entity; import dev.mvvasilev.common.data.AbstractEntity; -import dev.mvvasilev.finances.enums.RawTransactionValueType; +import dev.mvvasilev.common.enums.RawTransactionValueType; import jakarta.persistence.Entity; import jakarta.persistence.Table; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/TransactionMapping.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/TransactionMapping.java similarity index 82% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/TransactionMapping.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/TransactionMapping.java index 6c3de5c..6a8a357 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/TransactionMapping.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/entity/TransactionMapping.java @@ -1,9 +1,8 @@ -package dev.mvvasilev.finances.entity; +package dev.mvvasilev.statements.entity; import dev.mvvasilev.common.data.AbstractEntity; -import dev.mvvasilev.common.data.UserOwned; -import dev.mvvasilev.finances.enums.MappingConversionType; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; +import dev.mvvasilev.common.enums.ProcessedTransactionField; +import dev.mvvasilev.statements.enums.MappingConversionType; import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.Table; @@ -24,6 +23,8 @@ public class TransactionMapping extends AbstractEntity { private String falseBranchStringValue; + private String timestampPattern; + public TransactionMapping() { } @@ -66,4 +67,12 @@ public class TransactionMapping extends AbstractEntity { public void setFalseBranchStringValue(String falseBranchStringValue) { this.falseBranchStringValue = falseBranchStringValue; } + + public String getTimestampPattern() { + return timestampPattern; + } + + public void setTimestampPattern(String timestampPattern) { + this.timestampPattern = timestampPattern; + } } diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/MappingConversionType.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/enums/MappingConversionType.java similarity index 87% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/MappingConversionType.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/enums/MappingConversionType.java index e5ac9b7..5040621 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/MappingConversionType.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/enums/MappingConversionType.java @@ -1,13 +1,16 @@ -package dev.mvvasilev.finances.enums; +package dev.mvvasilev.statements.enums; import dev.mvvasilev.common.data.AbstractEnumConverter; import dev.mvvasilev.common.data.PersistableEnum; +import dev.mvvasilev.common.enums.RawTransactionValueType; // TODO: Only single type of conversion currently supported: from string to boolean // TODO: Add more: *_TO_NUMERIC, *_TO_TIMESTAMP, *_TO_STRING // TODO: Also, figure out a better way to do these? public enum MappingConversionType implements PersistableEnum { - STRING_TO_BOOLEAN(RawTransactionValueType.STRING, RawTransactionValueType.BOOLEAN); + STRING_TO_BOOLEAN(RawTransactionValueType.STRING, RawTransactionValueType.BOOLEAN), + STRING_TO_TIMESTAMP(RawTransactionValueType.STRING, RawTransactionValueType.TIMESTAMP), + STRING_TO_NUMERIC(RawTransactionValueType.STRING, RawTransactionValueType.NUMERIC); // TODO: Add the rest // STRING_TO_TIMESTAMP(RawTransactionValueType.STRING, RawTransactionValueType.TIMESTAMP), diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawStatementRepository.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawStatementRepository.java similarity index 82% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawStatementRepository.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawStatementRepository.java index eb32690..6e6f0fc 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawStatementRepository.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawStatementRepository.java @@ -1,7 +1,7 @@ -package dev.mvvasilev.finances.persistence; +package dev.mvvasilev.statements.persistence; -import dev.mvvasilev.finances.entity.RawStatement; -import dev.mvvasilev.finances.persistence.dtos.RawStatementDTO; +import dev.mvvasilev.statements.entity.RawStatement; +import dev.mvvasilev.statements.persistence.dto.RawStatementDTO; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueGroupRepository.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawTransactionValueGroupRepository.java similarity index 83% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueGroupRepository.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawTransactionValueGroupRepository.java index 8df1859..63acadb 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueGroupRepository.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawTransactionValueGroupRepository.java @@ -1,7 +1,7 @@ -package dev.mvvasilev.finances.persistence; +package dev.mvvasilev.statements.persistence; -import dev.mvvasilev.finances.entity.RawTransactionValueGroup; -import dev.mvvasilev.finances.persistence.dtos.RawTransactionValueGroupDTO; +import dev.mvvasilev.statements.entity.RawTransactionValueGroup; +import dev.mvvasilev.statements.persistence.dto.RawTransactionValueGroupDTO; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueRepository.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawTransactionValueRepository.java similarity index 87% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueRepository.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawTransactionValueRepository.java index fd9abf6..1622522 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueRepository.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/RawTransactionValueRepository.java @@ -1,6 +1,6 @@ -package dev.mvvasilev.finances.persistence; +package dev.mvvasilev.statements.persistence; -import dev.mvvasilev.finances.entity.RawTransactionValue; +import dev.mvvasilev.statements.entity.RawTransactionValue; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/TransactionMappingRepository.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/TransactionMappingRepository.java similarity index 94% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/TransactionMappingRepository.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/TransactionMappingRepository.java index e2daf35..c9079e0 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/TransactionMappingRepository.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/TransactionMappingRepository.java @@ -1,6 +1,6 @@ -package dev.mvvasilev.finances.persistence; +package dev.mvvasilev.statements.persistence; -import dev.mvvasilev.finances.entity.TransactionMapping; +import dev.mvvasilev.statements.entity.TransactionMapping; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawStatementDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/dto/RawStatementDTO.java similarity index 75% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawStatementDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/dto/RawStatementDTO.java index 3f33c52..63bc602 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawStatementDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/dto/RawStatementDTO.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.persistence.dtos; +package dev.mvvasilev.statements.persistence.dto; import java.time.LocalDateTime; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawTransactionValueGroupDTO.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/dto/RawTransactionValueGroupDTO.java similarity index 50% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawTransactionValueGroupDTO.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/dto/RawTransactionValueGroupDTO.java index 02bab5b..af890c7 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/dtos/RawTransactionValueGroupDTO.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/persistence/dto/RawTransactionValueGroupDTO.java @@ -1,6 +1,4 @@ -package dev.mvvasilev.finances.persistence.dtos; - -import dev.mvvasilev.finances.enums.RawTransactionValueType; +package dev.mvvasilev.statements.persistence.dto; public interface RawTransactionValueGroupDTO { diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/StatementsService.java b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/service/StatementsService.java similarity index 68% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/services/StatementsService.java rename to pefi-statements-api/src/main/java/dev/mvvasilev/statements/service/StatementsService.java index 4785321..32976d6 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/StatementsService.java +++ b/pefi-statements-api/src/main/java/dev/mvvasilev/statements/service/StatementsService.java @@ -1,13 +1,21 @@ -package dev.mvvasilev.finances.services; +package dev.mvvasilev.statements.service; -import dev.mvvasilev.common.data.AbstractEntity; +import dev.mvvasilev.common.dto.CreateProcessedTransactionDTO; +import dev.mvvasilev.common.dto.ProcessedTransactionFieldDTO; +import dev.mvvasilev.common.enums.ProcessedTransactionField; +import dev.mvvasilev.common.enums.RawTransactionValueType; import dev.mvvasilev.common.exceptions.CommonFinancesException; import dev.mvvasilev.common.web.CrudResponseDTO; -import dev.mvvasilev.finances.dtos.*; -import dev.mvvasilev.finances.entity.*; -import dev.mvvasilev.finances.enums.ProcessedTransactionField; -import dev.mvvasilev.finances.enums.RawTransactionValueType; -import dev.mvvasilev.finances.persistence.*; +import dev.mvvasilev.statements.dto.*; +import dev.mvvasilev.statements.entity.RawStatement; +import dev.mvvasilev.statements.entity.RawTransactionValue; +import dev.mvvasilev.statements.entity.RawTransactionValueGroup; +import dev.mvvasilev.statements.entity.TransactionMapping; +import dev.mvvasilev.statements.enums.MappingConversionType; +import dev.mvvasilev.statements.persistence.RawStatementRepository; +import dev.mvvasilev.statements.persistence.RawTransactionValueGroupRepository; +import dev.mvvasilev.statements.persistence.RawTransactionValueRepository; +import dev.mvvasilev.statements.persistence.TransactionMappingRepository; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.WorkbookFactory; @@ -27,14 +35,18 @@ import java.time.format.DateTimeParseException; import java.time.format.ResolverStyle; import java.time.temporal.ChronoField; import java.util.*; -import java.util.function.Function; +import java.util.function.BiConsumer; import java.util.stream.Collectors; +import static dev.mvvasilev.common.enums.ProcessedTransactionField.*; +import static dev.mvvasilev.common.enums.ProcessedTransactionField.TIMESTAMP; +import static dev.mvvasilev.common.enums.RawTransactionValueType.*; + @Service @Transactional public class StatementsService { - private static final DateTimeFormatter DATE_FORMAT = new DateTimeFormatterBuilder() + private static final DateTimeFormatter DEFAULT_DATE_FORMAT = new DateTimeFormatterBuilder() .appendPattern("dd.MM.yyyy[ [HH][:mm][:ss]]") .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) @@ -52,19 +64,19 @@ public class StatementsService { private final TransactionMappingRepository transactionMappingRepository; - private final ProcessedTransactionRepository processedTransactionRepository; + // TODO: send processed transactions to be stored via message broker + // private final ProcessedTransactionRepository processedTransactionRepository; @Autowired - public StatementsService(RawStatementRepository rawStatementRepository, RawTransactionValueGroupRepository rawTransactionValueGroupRepository, RawTransactionValueRepository rawTransactionValueRepository, TransactionMappingRepository transactionMappingRepository, ProcessedTransactionRepository processedTransactionRepository) { + public StatementsService(RawStatementRepository rawStatementRepository, RawTransactionValueGroupRepository rawTransactionValueGroupRepository, RawTransactionValueRepository rawTransactionValueRepository, TransactionMappingRepository transactionMappingRepository) { this.rawStatementRepository = rawStatementRepository; this.rawTransactionValueGroupRepository = rawTransactionValueGroupRepository; this.rawTransactionValueRepository = rawTransactionValueRepository; this.transactionMappingRepository = transactionMappingRepository; - this.processedTransactionRepository = processedTransactionRepository; + // this.processedTransactionRepository = processedTransactionRepository; } - @Transactional public void uploadStatementFromExcelSheetForUser(final String fileName, final String mimeType, final InputStream workbookInputStream, final int userId) throws IOException { var workbook = WorkbookFactory.create(workbookInputStream); @@ -96,7 +108,7 @@ public class StatementsService { transactionValueGroup.setName(c.getStringCellValue()); // group type is string by default, if no other type could have been determined - var groupType = RawTransactionValueType.STRING; + var groupType = STRING; // iterate down through the rows on this column, looking for the first one to return a type for (int y = c.getRowIndex() + 1; y <= lastRowIndex; y++) { @@ -136,7 +148,7 @@ public class StatementsService { switch (groupType) { case STRING -> value.setStringValue(cellValue); case NUMERIC -> value.setNumericValue(Double.parseDouble(cellValue)); - case TIMESTAMP -> value.setTimestampValue(LocalDateTime.parse(cellValue, DATE_FORMAT)); + case TIMESTAMP -> value.setTimestampValue(LocalDateTime.parse(cellValue, DEFAULT_DATE_FORMAT)); case BOOLEAN -> value.setBooleanValue(Boolean.parseBoolean(cellValue)); } } catch (Exception e) { @@ -176,11 +188,11 @@ public class StatementsService { } if (cell.getCellType() == CellType.BOOLEAN) { - return Optional.of(RawTransactionValueType.BOOLEAN); + return Optional.of(BOOLEAN); } if (cell.getCellType() == CellType.NUMERIC) { - return Optional.of(RawTransactionValueType.NUMERIC); + return Optional.of(NUMERIC); } var cellValue = cell.getStringCellValue(); @@ -194,7 +206,7 @@ public class StatementsService { private boolean isValidDate(String stringDate) { try { - DATE_FORMAT.parse(stringDate); + DEFAULT_DATE_FORMAT.parse(stringDate); } catch (DateTimeParseException e) { return false; } @@ -272,7 +284,6 @@ public class StatementsService { } public void processStatement(Long statementId, Integer userId) { - processedTransactionRepository.deleteProcessedTransactionsForStatement(statementId); final var mappings = transactionMappingRepository.fetchTransactionMappingsWithStatementId(statementId); @@ -292,11 +303,36 @@ public class StatementsService { }) .toList(); + // TODO: Over kafka, delete previous transactions, and create the new ones processedTransactionRepository.saveAllAndFlush(processedTransactions); } - private ProcessedTransaction mapValuesToTransaction(List values, final Collection mappings) { - final var processedTransaction = new ProcessedTransaction(); + // This const is a result of the limitations of the JVM. + // It is impossible to refer to either a field, or method of a class statically. + // Because of this, it is very difficult to tie the ProcessedTransactionField values to the actual class fields they represent. + // To resolve this imperfection, this const lives here, in plain view, so when one of the fields is changed, + // Hopefully the programmer remembers to change the value inside as well. + private static final Map> FIELD_SETTERS = Map.ofEntries( + Map.entry( + DESCRIPTION, + (pt, value) -> pt.setDescription((String) value) + ), + Map.entry( + AMOUNT, + (pt, value) -> pt.setAmount((Double) value) + ), + Map.entry( + IS_INFLOW, + (pt, value) -> pt.setInflow((Boolean) value) + ), + Map.entry( + TIMESTAMP, + (pt, value) -> pt.setTimestamp((LocalDateTime) value) + ) + ); + + private CreateProcessedTransactionDTO mapValuesToTransaction(List values, final Collection mappings) { + final var processedTransaction = new CreateProcessedTransactionDTO(); values.forEach(value -> { final var mapping = mappings.stream() @@ -313,48 +349,32 @@ public class StatementsService { // 1. Fetch the class field using the mapping FIELD_NAMES // 2. Determine the type of field from the enum ( avoid using more reflection than necessary ) // 3. Set the new value of the field - // This should work fine for new fields as well, so long as the ProcessedTransactionField enum and FIELD_NAMES is maintained. + // This should work fine for new fields as well, so long as the ProcessedTransactionField enum and FIELD_SETTERS is maintained. // If only Java had a better way of doing this. try { - final var classField = ProcessedTransaction.class.getDeclaredField(ProcessedTransaction.FIELD_NAMES.get(mapping.getProcessedTransactionField())); - classField.setAccessible(true); + Object val = switch (mapping.getProcessedTransactionField().type()) { + case STRING -> value.getStringValue(); + case NUMERIC -> value.getNumericValue(); + case TIMESTAMP -> value.getTimestampValue(); + case BOOLEAN -> value.getBooleanValue(); + }; - switch (mapping.getProcessedTransactionField().type()) { - case STRING -> classField.set(processedTransaction, value.getStringValue()); - case NUMERIC -> classField.set(processedTransaction, value.getNumericValue()); - case TIMESTAMP -> classField.set(processedTransaction, value.getTimestampValue()); - case BOOLEAN -> classField.set(processedTransaction, value.getBooleanValue()); - } - } catch (NoSuchFieldException | IllegalAccessException e) { + FIELD_SETTERS.get(mapping.getProcessedTransactionField()).accept(processedTransaction, val); + + } catch (Exception e) { logger.error("Error while mapping statement.", e); } + } else { + // If converting, first pass the value through conversion, then set it to the field as described above - return; - } + Object result = convertValue(conversionType, mapping, value); - // If converting, first pass the value through conversion, then set it to the field as described above - - // TODO: Expand on this. Or maybe better yet, don't - figure out a better way. - switch (conversionType) { - case STRING_TO_BOOLEAN -> { - if (mapping.getProcessedTransactionField().type() != RawTransactionValueType.BOOLEAN) { - logger.error("Invalid conversion type: is {}, but expected {}", conversionType.getTo(), mapping.getProcessedTransactionField().type()); - break; - } - - boolean result = convertStringToBoolean(value.getStringValue(), mapping.getTrueBranchStringValue(), mapping.getFalseBranchStringValue()); - - try { - final var classField = ProcessedTransaction.class.getDeclaredField(ProcessedTransaction.FIELD_NAMES.get(mapping.getProcessedTransactionField())); - - classField.setAccessible(true); - - classField.set(processedTransaction, result); - } catch (NoSuchFieldException | IllegalAccessException e) { - logger.error("Error while mapping statement.", e); - } + try { + FIELD_SETTERS.get(mapping.getProcessedTransactionField()).accept(processedTransaction, result); + } catch (Exception e) { + logger.error("Error while mapping statement.", e); } } }); @@ -362,7 +382,34 @@ public class StatementsService { return processedTransaction; } - private boolean convertStringToBoolean(String stringValue, String trueBranchStringValue, String falseBranchStringValue) { - return stringValue.equals(trueBranchStringValue); + private Object convertValue(MappingConversionType conversionType, TransactionMapping mapping, RawTransactionValue value) { +// TODO: Fetch value group from db to double-check from type +// if (group.getType() != conversionType.getFrom()) { +// throw new CommonFinancesException("Invalid conversion type (from): is %s, but expected %s", conversionType.getFrom(), group.getType()); +// } + + if (mapping.getProcessedTransactionField().type() != conversionType.getTo()) { + throw new CommonFinancesException("Invalid conversion type (to): is %s, but expected %s", conversionType.getTo(), mapping.getProcessedTransactionField().type()); + } + + return switch (conversionType) { + case STRING_TO_BOOLEAN -> value.getStringValue().equals(mapping.getTrueBranchStringValue()); + + case STRING_TO_TIMESTAMP -> LocalDateTime.parse( + value.getStringValue(), + new DateTimeFormatterBuilder() + .appendPattern(mapping.getTimestampPattern()) + .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) + .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) + .parseDefaulting(ChronoField.YEAR, 1970) + .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) + .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) + .toFormatter() + .withResolverStyle(ResolverStyle.LENIENT) + ); + + case STRING_TO_NUMERIC -> Double.parseDouble(value.getStringValue()); + }; } } diff --git a/pefi-statements-api/src/main/resources/application.properties b/pefi-statements-api/src/main/resources/application.properties new file mode 100644 index 0000000..53d5fce --- /dev/null +++ b/pefi-statements-api/src/main/resources/application.properties @@ -0,0 +1,22 @@ +server.port=8081 +debug=true + +logging.level.org.springframework.boot.autoconfigure=ERROR + +spring.profiles.active=${PROFILE} + +# Database +spring.datasource.url=${DATASOURCE_URL} +spring.datasource.username=${DATASOURCE_USER} +spring.datasource.password=${DATASOURCE_PASSWORD} +spring.datasource.driver-class-name=org.postgresql.Driver + +spring.jpa.properties.hibernate.jdbc.batch_size=10 +spring.jpa.properties.hibernate.order_inserts=true + +spring.jpa.generate-ddl=false +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=validate + +# Security +jwt.issuer-url=${AUTHENTIK_ISSUER_URL} \ No newline at end of file diff --git a/pefi-widgets-api/build.gradle b/pefi-widgets-api/build.gradle new file mode 100644 index 0000000..f91f8a0 --- /dev/null +++ b/pefi-widgets-api/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.2.0' + id 'io.spring.dependency-management' version '1.1.3' +} + +group = 'dev.mvvasilev.widgets' +version = '0.0.1-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + + implementation 'org.flywaydb:flyway-core' + implementation 'org.apache.commons:commons-lang3:3.14.0' + + implementation project(":pefi-common") + + runtimeOnly 'org.postgresql:postgresql' + + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/pefi-widgets-api/settings.gradle b/pefi-widgets-api/settings.gradle new file mode 100644 index 0000000..4b57194 --- /dev/null +++ b/pefi-widgets-api/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'pefi-widgets-api' \ No newline at end of file diff --git a/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/PefiWidgetsAPI.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/PefiWidgetsAPI.java new file mode 100644 index 0000000..c397b40 --- /dev/null +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/PefiWidgetsAPI.java @@ -0,0 +1,16 @@ +package dev.mvvasilev.widgets; + +import dev.mvvasilev.common.services.AuthorizationService; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication(scanBasePackageClasses = { AuthorizationService.class }) +@EnableJpaRepositories("dev.mvvasilev.widgets.*") +@EntityScan("dev.mvvasilev.widgets.*") +public class PefiWidgetsAPI { + public static void main(String[] args) { + SpringApplication.run(PefiWidgetsAPI.class, args); + } +} \ No newline at end of file diff --git a/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/ControllerConfiguration.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/ControllerConfiguration.java new file mode 100644 index 0000000..b956422 --- /dev/null +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/ControllerConfiguration.java @@ -0,0 +1,8 @@ +package dev.mvvasilev.widgets.configurations; + +import dev.mvvasilev.common.configuration.CommonControllerConfiguration; +import org.springframework.context.annotation.Import; + +@Import(CommonControllerConfiguration.class) +public class ControllerConfiguration { +} diff --git a/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/SecurityConfiguration.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/SecurityConfiguration.java new file mode 100644 index 0000000..1b40157 --- /dev/null +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/SecurityConfiguration.java @@ -0,0 +1,12 @@ +package dev.mvvasilev.widgets.configurations; + +import dev.mvvasilev.common.configuration.CommonSwaggerConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@Import(CommonSwaggerConfiguration.class) +@EnableTransactionManagement +public class SecurityConfiguration { +} diff --git a/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/SwaggerConfiguration.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/SwaggerConfiguration.java new file mode 100644 index 0000000..c59d7b3 --- /dev/null +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/configurations/SwaggerConfiguration.java @@ -0,0 +1,11 @@ +package dev.mvvasilev.widgets.configurations; + +import dev.mvvasilev.common.configuration.CommonSwaggerConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(CommonSwaggerConfiguration.class) +public class SwaggerConfiguration { + +} diff --git a/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/controllers/EnumsControllers.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/controllers/EnumsControllers.java new file mode 100644 index 0000000..4ac790b --- /dev/null +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/controllers/EnumsControllers.java @@ -0,0 +1,20 @@ +package dev.mvvasilev.widgets.controllers; + +import dev.mvvasilev.common.controller.AbstractRestController; +import dev.mvvasilev.common.web.APIResponseDTO; +import dev.mvvasilev.widgets.enums.WidgetType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/enums") +public class EnumsControllers extends AbstractRestController { + + @GetMapping("/widget-types") + public ResponseEntity> fetchWidgetTypes() { + return ok(WidgetType.values()); + } + +} diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/WidgetsController.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/controllers/WidgetsController.java similarity index 81% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/WidgetsController.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/controllers/WidgetsController.java index 97c8c67..a03f1d9 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/controllers/WidgetsController.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/controllers/WidgetsController.java @@ -1,12 +1,11 @@ -package dev.mvvasilev.finances.controllers; +package dev.mvvasilev.widgets.controllers; import dev.mvvasilev.common.controller.AbstractRestController; import dev.mvvasilev.common.web.APIResponseDTO; import dev.mvvasilev.common.web.CrudResponseDTO; -import dev.mvvasilev.finances.dtos.CreateUpdateWidgetDTO; -import dev.mvvasilev.finances.dtos.WidgetDTO; -import dev.mvvasilev.finances.enums.WidgetType; -import dev.mvvasilev.finances.services.WidgetService; +import dev.mvvasilev.widgets.dtos.CreateUpdateWidgetDTO; +import dev.mvvasilev.widgets.dtos.WidgetDTO; +import dev.mvvasilev.widgets.service.WidgetService; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; @@ -24,11 +23,6 @@ public class WidgetsController extends AbstractRestController { this.widgetService = widgetService; } - @GetMapping("/types") - public ResponseEntity> fetchWidgetTypes() { - return ok(WidgetType.values()); - } - @GetMapping public ResponseEntity>> fetchAllForUser(Authentication authentication) { return ok(widgetService.fetchAllForUser(Integer.parseInt(authentication.getName()))); diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateUpdateWidgetDTO.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/CreateUpdateWidgetDTO.java similarity index 92% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateUpdateWidgetDTO.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/CreateUpdateWidgetDTO.java index f5d6b34..0935e15 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateUpdateWidgetDTO.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/CreateUpdateWidgetDTO.java @@ -1,6 +1,6 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.widgets.dtos; -import dev.mvvasilev.finances.enums.WidgetType; +import dev.mvvasilev.widgets.enums.WidgetType; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateWidgetParameterDTO.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/CreateWidgetParameterDTO.java similarity index 84% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateWidgetParameterDTO.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/CreateWidgetParameterDTO.java index f5c30e2..3203775 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/CreateWidgetParameterDTO.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/CreateWidgetParameterDTO.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.widgets.dtos; import java.time.LocalDateTime; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/WidgetDTO.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/WidgetDTO.java similarity index 74% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/WidgetDTO.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/WidgetDTO.java index 83e916a..de1964f 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/WidgetDTO.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/WidgetDTO.java @@ -1,6 +1,6 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.widgets.dtos; -import dev.mvvasilev.finances.enums.WidgetType; +import dev.mvvasilev.widgets.enums.WidgetType; import java.util.List; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/WidgetParameterDTO.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/WidgetParameterDTO.java similarity index 86% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/WidgetParameterDTO.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/WidgetParameterDTO.java index 872e1b8..96cd084 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/dtos/WidgetParameterDTO.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/dtos/WidgetParameterDTO.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.dtos; +package dev.mvvasilev.widgets.dtos; import java.time.LocalDateTime; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/Widget.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/entity/Widget.java similarity index 95% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/Widget.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/entity/Widget.java index d2b70a1..e359456 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/Widget.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/entity/Widget.java @@ -1,8 +1,8 @@ -package dev.mvvasilev.finances.entity; +package dev.mvvasilev.widgets.entity; import dev.mvvasilev.common.data.AbstractEntity; import dev.mvvasilev.common.data.UserOwned; -import dev.mvvasilev.finances.enums.WidgetType; +import dev.mvvasilev.widgets.enums.WidgetType; import jakarta.persistence.Convert; import jakarta.persistence.Converter; import jakarta.persistence.Entity; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/WidgetParameter.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/entity/WidgetParameter.java similarity index 97% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/WidgetParameter.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/entity/WidgetParameter.java index 38fee31..20dd129 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/entity/WidgetParameter.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/entity/WidgetParameter.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.entity; +package dev.mvvasilev.widgets.entity; import dev.mvvasilev.common.data.AbstractEntity; import jakarta.persistence.Entity; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/WidgetType.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/enums/WidgetType.java similarity index 93% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/WidgetType.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/enums/WidgetType.java index af48e97..0665e62 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/enums/WidgetType.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/enums/WidgetType.java @@ -1,4 +1,4 @@ -package dev.mvvasilev.finances.enums; +package dev.mvvasilev.widgets.enums; import dev.mvvasilev.common.data.AbstractEnumConverter; import dev.mvvasilev.common.data.PersistableEnum; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/WidgetParameterRepository.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/persistence/WidgetParameterRepository.java similarity index 83% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/WidgetParameterRepository.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/persistence/WidgetParameterRepository.java index 2d59721..6641fc2 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/WidgetParameterRepository.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/persistence/WidgetParameterRepository.java @@ -1,6 +1,6 @@ -package dev.mvvasilev.finances.persistence; +package dev.mvvasilev.widgets.persistence; -import dev.mvvasilev.finances.entity.WidgetParameter; +import dev.mvvasilev.widgets.entity.WidgetParameter; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.repository.query.Param; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/WidgetRepository.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/persistence/WidgetRepository.java similarity index 75% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/WidgetRepository.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/persistence/WidgetRepository.java index f939bc9..c4812ff 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/WidgetRepository.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/persistence/WidgetRepository.java @@ -1,7 +1,7 @@ -package dev.mvvasilev.finances.persistence; +package dev.mvvasilev.widgets.persistence; import dev.mvvasilev.common.data.UserOwnedEntityRepository; -import dev.mvvasilev.finances.entity.Widget; +import dev.mvvasilev.widgets.entity.Widget; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/WidgetService.java b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/service/WidgetService.java similarity index 89% rename from pefi-monolith/src/main/java/dev/mvvasilev/finances/services/WidgetService.java rename to pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/service/WidgetService.java index 1967257..2117d6e 100644 --- a/pefi-monolith/src/main/java/dev/mvvasilev/finances/services/WidgetService.java +++ b/pefi-widgets-api/src/main/java/dev/mvvasilev/widgets/service/WidgetService.java @@ -1,20 +1,19 @@ -package dev.mvvasilev.finances.services; +package dev.mvvasilev.widgets.service; import dev.mvvasilev.common.exceptions.CommonFinancesException; -import dev.mvvasilev.finances.dtos.CreateUpdateWidgetDTO; -import dev.mvvasilev.finances.dtos.CreateWidgetParameterDTO; -import dev.mvvasilev.finances.dtos.WidgetDTO; -import dev.mvvasilev.finances.dtos.WidgetParameterDTO; -import dev.mvvasilev.finances.entity.Widget; -import dev.mvvasilev.finances.entity.WidgetParameter; -import dev.mvvasilev.finances.persistence.WidgetParameterRepository; -import dev.mvvasilev.finances.persistence.WidgetRepository; +import dev.mvvasilev.widgets.dtos.CreateUpdateWidgetDTO; +import dev.mvvasilev.widgets.dtos.CreateWidgetParameterDTO; +import dev.mvvasilev.widgets.dtos.WidgetDTO; +import dev.mvvasilev.widgets.dtos.WidgetParameterDTO; +import dev.mvvasilev.widgets.entity.Widget; +import dev.mvvasilev.widgets.entity.WidgetParameter; +import dev.mvvasilev.widgets.persistence.WidgetParameterRepository; +import dev.mvvasilev.widgets.persistence.WidgetRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; @Service @Transactional diff --git a/pefi-widgets-api/src/main/resources/application.properties b/pefi-widgets-api/src/main/resources/application.properties new file mode 100644 index 0000000..53d5fce --- /dev/null +++ b/pefi-widgets-api/src/main/resources/application.properties @@ -0,0 +1,22 @@ +server.port=8081 +debug=true + +logging.level.org.springframework.boot.autoconfigure=ERROR + +spring.profiles.active=${PROFILE} + +# Database +spring.datasource.url=${DATASOURCE_URL} +spring.datasource.username=${DATASOURCE_USER} +spring.datasource.password=${DATASOURCE_PASSWORD} +spring.datasource.driver-class-name=org.postgresql.Driver + +spring.jpa.properties.hibernate.jdbc.batch_size=10 +spring.jpa.properties.hibernate.order_inserts=true + +spring.jpa.generate-ddl=false +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=validate + +# Security +jwt.issuer-url=${AUTHENTIK_ISSUER_URL} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 03508c6..dee5994 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,7 @@ rootProject.name = 'pefi' include 'pefi-frontend' include 'pefi-api-gateway' include 'pefi-common' -include 'pefi-monolith' \ No newline at end of file +include 'pefi-core-api' +include 'pefi-statements-api' +include 'pefi-widgets-api' +