Split off statements and widgets APIs into own microservices

This commit is contained in:
Miroslav Vasilev 2024-02-04 21:59:09 +02:00
parent b63d099562
commit b2cee1d1c2
131 changed files with 705 additions and 281 deletions

4
.idea/gradle.xml generated
View file

@ -12,8 +12,10 @@
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/pefi-api-gateway" />
<option value="$PROJECT_DIR$/pefi-common" />
<option value="$PROJECT_DIR$/pefi-core-api" />
<option value="$PROJECT_DIR$/pefi-frontend" />
<option value="$PROJECT_DIR$/pefi-monolith" />
<option value="$PROJECT_DIR$/pefi-statements-api" />
<option value="$PROJECT_DIR$/pefi-widgets-api" />
</set>
</option>
</GradleProjectSettings>

1
.idea/sqldialects.xml generated
View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/pefi-monolith/src/main/java/dev/mvvasilev/finances/persistence/RawTransactionValueGroupRepository.java" dialect="GenericSQL" />
<file url="PROJECT" dialect="PostgreSQL" />
</component>
</project>

View file

@ -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'
}

View file

@ -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<APIResponseDTO<Object>> processGenericException(Exception ex) {
List<APIErrorDTO> 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()
));
}
}
}

View file

@ -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

View file

@ -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(

View file

@ -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;
}
}

View file

@ -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
) {
}

View file

@ -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<String> {
DESCRIPTION(RawTransactionValueType.STRING),

View file

@ -1,4 +1,4 @@
package dev.mvvasilev.finances.enums;
package dev.mvvasilev.common.enums;
import dev.mvvasilev.common.data.PersistableEnum;

View file

@ -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;

View file

@ -1,5 +1,13 @@
package dev.mvvasilev.common.web;
import org.springframework.http.ResponseEntity;
import java.util.Collection;
public record APIResponseDTO<T>(T result, Collection<APIErrorDTO> errors, int statusCode, String statusText) { }
public record APIResponseDTO<T>(
T result,
Collection<APIErrorDTO> errors,
int statusCode,
String statusText
)
{ }

View file

@ -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 {

View file

@ -0,0 +1 @@
rootProject.name = 'pefi-core-api'

View file

@ -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);
}
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -35,16 +35,6 @@ public class CategoriesController extends AbstractRestController {
this.objectMapper = objectMapper;
}
@GetMapping("/rules")
public ResponseEntity<APIResponseDTO<Collection<CategorizationRuleDTO>>> fetchCategorizationRules() {
return ok(
Arrays.stream(CategorizationRule.values()).map(r -> new CategorizationRuleDTO(
r,
r.applicableForType()
)).toList()
);
}
@PostMapping
public ResponseEntity<APIResponseDTO<CrudResponseDTO>> createCategory(
@RequestBody CreateCategoryDTO dto,

View file

@ -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<APIResponseDTO<Collection<CategorizationRuleDTO>>> fetchCategorizationRules() {
return ok(
Arrays.stream(CategorizationRule.values()).map(r -> new CategorizationRuleDTO(
r,
r.applicableForType()
)).toList()
);
}
@GetMapping("/processed-transaction-fields")
public ResponseEntity<APIResponseDTO<Collection<ProcessedTransactionFieldDTO>>> fetchFields() {
return ok(
Arrays.stream(ProcessedTransactionField.values())
.map(field -> new ProcessedTransactionFieldDTO(field, field.type()))
.toList()
);
}
}

View file

@ -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<APIResponseDTO<Collection<ProcessedTransactionFieldDTO>>> fetchFields() {
return ok(
Arrays.stream(ProcessedTransactionField.values())
.map(field -> new ProcessedTransactionFieldDTO(field, field.type()))
.toList()
);
}
@GetMapping
public ResponseEntity<APIResponseDTO<Page<ProcessedTransactionDTO>>> fetchProcessedTransactions(
Authentication authentication,

View file

@ -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,

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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<ProcessedTransactionField, String> FIELD_NAMES = Map.of(
ProcessedTransactionField.DESCRIPTION, "description",
ProcessedTransactionField.AMOUNT, "amount",
ProcessedTransactionField.IS_INFLOW, "isInflow",
ProcessedTransactionField.TIMESTAMP, "timestamp"
);
private String description;
private Integer userId;

View file

@ -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<String> {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1 +0,0 @@
rootProject.name = 'pefi-monolith'

View file

@ -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<APIResponseDTO<Object>> processGenericException(Exception ex) {
List<APIErrorDTO> 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()
));
}
}

View file

@ -1,4 +0,0 @@
package dev.mvvasilev.finances.persistence.dtos;
public interface RawTransactionDTO {
}

View file

@ -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

View file

View file

@ -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()
}

View file

@ -0,0 +1 @@
rootProject.name = 'pefi-statements-api'

View file

@ -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);
}
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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<APIResponseDTO<Collection<SupportedMappingConversionDTO>>> fetchTransactionMappings() {
return ok(Arrays.stream(MappingConversionType.values()).map(conv -> new SupportedMappingConversionDTO(
conv,
conv.getFrom(),
conv.getTo()
)).toList());
}
}

View file

@ -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<APIResponseDTO<Collection<SupportedMappingConversionDTO>>> 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<APIResponseDTO<Collection<CrudResponseDTO>>> createTransactionMappings(

View file

@ -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;

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -1,4 +1,4 @@
package dev.mvvasilev.finances.dtos;
package dev.mvvasilev.statements.dto;
import java.time.LocalDateTime;

View file

@ -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;

View file

@ -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")

Some files were not shown because too many files have changed in this diff Show more