Compare commits
2 Commits
master
...
dimas_inte
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d90cf83d98 | ||
|
|
ccf43a50e8 |
6
pom.xml
6
pom.xml
@@ -78,6 +78,12 @@
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>6.1.5</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-math3</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<defaultGoal>package</defaultGoal>
|
||||
|
||||
@@ -9,11 +9,9 @@ import com.faf223.expensetrackerfaf.model.User;
|
||||
import com.faf223.expensetrackerfaf.service.ExpenseCategoryService;
|
||||
import com.faf223.expensetrackerfaf.service.ExpenseService;
|
||||
import com.faf223.expensetrackerfaf.service.UserService;
|
||||
import com.faf223.expensetrackerfaf.util.DataExtender;
|
||||
import com.faf223.expensetrackerfaf.util.errors.ErrorResponse;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionDoesNotBelongToTheUserException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionNotCreatedException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionNotUpdatedException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionsNotFoundException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.*;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -26,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.Collections;
|
||||
@@ -134,6 +133,32 @@ public class ExpenseController {
|
||||
throw new TransactionsNotFoundException("The expenses have not been found");
|
||||
}
|
||||
|
||||
@GetMapping("/extend-data")
|
||||
public ResponseEntity<List<BigDecimal>> extendData(@RequestParam Optional<String> extendValue,
|
||||
@RequestParam Optional<Integer> extrapolationCount) {
|
||||
if(extendValue.isEmpty())
|
||||
throw new RequiredParamMissingException("Extend value has not been specified");
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User user;
|
||||
|
||||
if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails)
|
||||
user = userService.getUserByEmail(userDetails.getUsername());
|
||||
else
|
||||
user = null;
|
||||
|
||||
if(user == null)
|
||||
throw new UserNotFoundException("User with the specified UUID has not been found");
|
||||
|
||||
if(extendValue.get().equalsIgnoreCase("i"))
|
||||
return ResponseEntity.ok(DataExtender.interpolate(user.getExpenses()));
|
||||
|
||||
if(extendValue.get().equalsIgnoreCase("e"))
|
||||
return extrapolationCount.map(integer -> ResponseEntity.ok(DataExtender.extrapolate(user.getExpenses(), integer))).orElseGet(() -> ResponseEntity.ok(DataExtender.extrapolate(user.getExpenses(), 10)));
|
||||
|
||||
throw new WrongParamValueException("Wrong extend value has been specified (use either \"i\" or \"e\")");
|
||||
}
|
||||
|
||||
@GetMapping("/categories")
|
||||
public ResponseEntity<List<ExpenseCategory>> getAllCategories() {
|
||||
List<ExpenseCategory> categories = expenseCategoryService.getAllCategories();
|
||||
|
||||
@@ -12,72 +12,47 @@ public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleDoesNotBelongException(TransactionDoesNotBelongToTheUserException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.FORBIDDEN);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleTransactionNotCreatedException(TransactionNotCreatedException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.NOT_MODIFIED);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleTransactionsNotFoundException(TransactionsNotFoundException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleUserNotFoundException(UserNotFoundException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleTransactionNotUpdatedException(TransactionNotUpdatedException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.NOT_MODIFIED);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleUserNotAuthenticatedException(UserNotAuthenticatedException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.FORBIDDEN);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleUserNotCreatedException(UserNotCreatedException e) {
|
||||
ErrorResponse response = new ErrorResponse(
|
||||
e.getMessage(),
|
||||
System.currentTimeMillis()
|
||||
);
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(response, HttpStatus.NOT_MODIFIED);
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleRequiredParamMissingException(RequiredParamMissingException e) {
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
private ResponseEntity<ErrorResponse> handleWrongParamValueException(WrongParamValueException e) {
|
||||
return new ResponseEntity<>(new ErrorResponse(e.getMessage()), HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,11 +9,9 @@ import com.faf223.expensetrackerfaf.model.User;
|
||||
import com.faf223.expensetrackerfaf.service.IncomeCategoryService;
|
||||
import com.faf223.expensetrackerfaf.service.IncomeService;
|
||||
import com.faf223.expensetrackerfaf.service.UserService;
|
||||
import com.faf223.expensetrackerfaf.util.DataExtender;
|
||||
import com.faf223.expensetrackerfaf.util.errors.ErrorResponse;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionDoesNotBelongToTheUserException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionNotCreatedException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionNotUpdatedException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.TransactionsNotFoundException;
|
||||
import com.faf223.expensetrackerfaf.util.exceptions.*;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -26,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.util.Collections;
|
||||
@@ -134,6 +133,32 @@ public class IncomeController {
|
||||
throw new TransactionsNotFoundException("The expenses have not been found");
|
||||
}
|
||||
|
||||
@GetMapping("/extend-data")
|
||||
public ResponseEntity<List<BigDecimal>> extendData(@RequestParam Optional<String> extendValue,
|
||||
@RequestParam Optional<Integer> extrapolationCount) {
|
||||
if(extendValue.isEmpty())
|
||||
throw new RequiredParamMissingException("Extend value has not been specified");
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User user;
|
||||
|
||||
if (authentication != null && authentication.getPrincipal() instanceof UserDetails userDetails)
|
||||
user = userService.getUserByEmail(userDetails.getUsername());
|
||||
else
|
||||
user = null;
|
||||
|
||||
if(user == null)
|
||||
throw new UserNotFoundException("User with the specified UUID has not been found");
|
||||
|
||||
if(extendValue.get().equalsIgnoreCase("i"))
|
||||
return ResponseEntity.ok(DataExtender.interpolate(user.getIncomes()));
|
||||
|
||||
if(extendValue.get().equalsIgnoreCase("e"))
|
||||
return extrapolationCount.map(integer -> ResponseEntity.ok(DataExtender.extrapolate(user.getIncomes(), integer))).orElseGet(() -> ResponseEntity.ok(DataExtender.extrapolate(user.getIncomes(), 10)));
|
||||
|
||||
throw new WrongParamValueException("Wrong extend value has been specified (use either \"i\" or \"e\")");
|
||||
}
|
||||
|
||||
@GetMapping("/categories")
|
||||
public ResponseEntity<List<IncomeCategory>> getAllCategories() {
|
||||
List<IncomeCategory> categories = incomeCategoryService.getAllCategories();
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.faf223.expensetrackerfaf.util;
|
||||
|
||||
import com.faf223.expensetrackerfaf.model.IMoneyTransaction;
|
||||
import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
|
||||
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DataExtender {
|
||||
|
||||
public static List<BigDecimal> interpolate(List<? extends IMoneyTransaction> transactions) {
|
||||
List<BigDecimal> values = new ArrayList<>();
|
||||
|
||||
// Perform linear interpolation on the amount field
|
||||
if (transactions.size() > 1) {
|
||||
LinearInterpolator interpolator = new LinearInterpolator();
|
||||
|
||||
double[] xValues = new double[transactions.size()];
|
||||
double[] yValues = new double[transactions.size()];
|
||||
|
||||
for (int i = 0; i < transactions.size(); i++) {
|
||||
xValues[i] = i;
|
||||
yValues[i] = transactions.get(i).getAmount().doubleValue();
|
||||
}
|
||||
|
||||
PolynomialSplineFunction splineFunction = interpolator.interpolate(xValues, yValues);
|
||||
|
||||
// Interpolate values between the first and last data points
|
||||
for (int i = 1; i < transactions.size() - 1; i++)
|
||||
values.add(BigDecimal.valueOf(splineFunction.value(i + 0.5))); // Interpolate at the midpoint
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public static List<BigDecimal> extrapolate(List<? extends IMoneyTransaction> transactions, int count) {
|
||||
List<BigDecimal> values = new ArrayList<>();
|
||||
|
||||
// Perform linear extrapolation on the amount field
|
||||
if (transactions.size() > 1) {
|
||||
LinearInterpolator interpolator = new LinearInterpolator();
|
||||
|
||||
double[] xValues = new double[transactions.size()];
|
||||
double[] yValues = new double[transactions.size()];
|
||||
|
||||
for (int i = 0; i < transactions.size(); i++) {
|
||||
xValues[i] = i;
|
||||
yValues[i] = transactions.get(i).getAmount().doubleValue();
|
||||
}
|
||||
|
||||
PolynomialSplineFunction splineFunction = interpolator.interpolate(xValues, yValues);
|
||||
|
||||
// Extrapolate values beyond the last data point
|
||||
for (int i = transactions.size(); i < transactions.size() + count; i++)
|
||||
values.add(BigDecimal.valueOf(splineFunction.value(i))); // Extrapolate by extending the x-axis
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.faf223.expensetrackerfaf.util.exceptions;
|
||||
|
||||
public class RequiredParamMissingException extends RuntimeException {
|
||||
public RequiredParamMissingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.faf223.expensetrackerfaf.util.exceptions;
|
||||
|
||||
public class WrongParamValueException extends RuntimeException {
|
||||
public WrongParamValueException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user