Skip to content
Snippets Groups Projects
Commit a9b0d909 authored by Pavel Tetauer's avatar Pavel Tetauer
Browse files

Analytics service implementation

parent 22d198a7
No related branches found
No related tags found
1 merge request!16Analytics service implementation
Showing
with 371 additions and 2 deletions
package cz.muni.fi.obs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public class AnalyticsManagement {
public static void main(String[] args) {
SpringApplication.run(AnalyticsManagement.class, args);
}
}
package cz.muni.fi.obs.api;
import java.math.BigDecimal;
import java.time.LocalDate;
public record DailySummary(LocalDate date,
BigDecimal totalWithdrawalTransactions,
BigDecimal totalDepositTransactions,
BigDecimal totalWithdrawn,
BigDecimal totalDeposited,
BigDecimal averageWithdrawn,
BigDecimal averageDeposited,
BigDecimal difference) {
}
package cz.muni.fi.obs.api;
public record DailySummaryRequest(int year,
int month) {
}
package cz.muni.fi.obs.api;
import java.time.LocalDate;
import java.util.List;
public record DailySummaryResult(LocalDate reportDate,
List<DailySummary> summaries) {
}
package cz.muni.fi.obs.api;
import java.math.BigDecimal;
public record MonthlySummary(String month,
BigDecimal totalWithdrawalTransactions,
BigDecimal totalDepositTransactions,
BigDecimal totalWithdrawn,
BigDecimal totalDeposited,
BigDecimal averageWithdrawn,
BigDecimal averageDeposited,
BigDecimal difference) { }
package cz.muni.fi.obs.api;
public record MonthlySummaryRequest(int year,
int month) {
}
package cz.muni.fi.obs.api;
import java.time.LocalDate;
public record MonthlySummaryResult(LocalDate reportDate,
MonthlySummary summary) { }
package cz.muni.fi.obs.controller;
import cz.muni.fi.obs.api.DailySummaryRequest;
import cz.muni.fi.obs.api.DailySummaryResult;
import cz.muni.fi.obs.api.MonthlySummaryRequest;
import cz.muni.fi.obs.api.MonthlySummaryResult;
import cz.muni.fi.obs.facade.AnalyticsFacade;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@RequestMapping("/api/v1/{accountNumber}")
public class AnalyticsController {
private final AnalyticsFacade analyticsFacade;
@Autowired
public AnalyticsController(AnalyticsFacade analyticsFacade) {
this.analyticsFacade = analyticsFacade;
}
@PostMapping("/daily-summary")
public ResponseEntity<DailySummaryResult> getDailySummary(@PathVariable String accountNumber, @RequestBody DailySummaryRequest request) {
log.info("Received request for daily summary for account number: {}, year: {}, month: {}", accountNumber, request.year(), request.month());
DailySummaryResult result = analyticsFacade.getDailySummary(accountNumber, request.year(), request.month());
return ResponseEntity.ok(result);
}
@PostMapping("/monthly-summary")
public ResponseEntity<MonthlySummaryResult> getMonthlySummary(@PathVariable String accountNumber, @RequestBody MonthlySummaryRequest request) {
log.info("Received request for monthly summary for account number: {}, year: {}", accountNumber, request.year());
MonthlySummaryResult result = analyticsFacade.getMonthlySummary(accountNumber, request.year(), request.month());
return ResponseEntity.ok(result);
}
}
package cz.muni.fi.obs.data;
import cz.muni.fi.obs.data.dbo.DailyTransaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Repository
public class AnalyticsRepository {
private final DataStore dataStore;
@Autowired
public AnalyticsRepository(DataStore dataStore) {
this.dataStore = dataStore;
}
public List<DailyTransaction> getDailyTransactions(String accountNumber, int year, int month) {
Stream<DailyTransaction> transactionStream = dataStore.transactions.stream()
.filter(transaction -> transaction.getAccount().getAccountNumber().equals(accountNumber))
.filter(transaction -> transaction.getDate().getYear() == year)
.filter(transaction -> transaction.getDate().getMonth() == month);
return transactionStream.toList();
}
}
package cz.muni.fi.obs.data;
import cz.muni.fi.obs.data.dbo.Account;
import cz.muni.fi.obs.data.dbo.DailyTransaction;
import cz.muni.fi.obs.data.dbo.Date;
import org.springframework.context.annotation.Configuration;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class DataStore {
public List<DailyTransaction> transactions = new ArrayList<>();
private static final Account account = new Account("1234567890");
public DataStore(){
DailyTransaction transaction1 = new DailyTransaction(
new BigDecimal(5),
new BigDecimal(5),
new BigDecimal(30000),
new BigDecimal(20000),
new BigDecimal(10000),
new BigDecimal(4000),
new BigDecimal(2000),
account,
new Date(2021, 1, 1)
);
DailyTransaction transaction2 = new DailyTransaction(
new BigDecimal(10),
new BigDecimal(10),
new BigDecimal(40000),
new BigDecimal(20000),
new BigDecimal(20000),
new BigDecimal(2000),
new BigDecimal(2000),
account,
new Date(2021, 1, 2)
);
DailyTransaction transaction3 = new DailyTransaction(
new BigDecimal(4),
new BigDecimal(2),
new BigDecimal(10000),
new BigDecimal(8000),
new BigDecimal(2000),
new BigDecimal(2000),
new BigDecimal(1000),
account,
new Date(2021, 1, 3)
);
transactions.add(transaction1);
transactions.add(transaction2);
transactions.add(transaction3);
}
}
package cz.muni.fi.obs.data.dbo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Account extends Dbo{
String accountNumber;
public Account(String accountNumber) {
this.accountNumber = accountNumber;
}
}
package cz.muni.fi.obs.data.dbo;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Getter
@Setter
public class DailyTransaction extends Dbo {
BigDecimal totalWithdrawalTransactions;
BigDecimal totalDepositTransactions;
BigDecimal totalTransactionAmount;
BigDecimal totalWithdrawalAmount;
BigDecimal totalDepositAmount;
BigDecimal averageWithdrawalAmount;
BigDecimal averageDepositAmount;
Account account;
Date date;
public DailyTransaction(BigDecimal totalWithdrawalTransactions, BigDecimal totalDepositTransactions, BigDecimal totalTransactionAmount, BigDecimal totalWithdrawalAmount, BigDecimal totalDepositAmount, BigDecimal averageWithdrawalAmount, BigDecimal averageDepositAmount, Account account, Date date) {
this.totalWithdrawalTransactions = totalWithdrawalTransactions;
this.totalDepositTransactions = totalDepositTransactions;
this.totalTransactionAmount = totalTransactionAmount;
this.totalWithdrawalAmount = totalWithdrawalAmount;
this.totalDepositAmount = totalDepositAmount;
this.averageWithdrawalAmount = averageWithdrawalAmount;
this.averageDepositAmount = averageDepositAmount;
this.account = account;
this.date = date;
}
}
package cz.muni.fi.obs.data.dbo;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDate;
@Getter
@Setter
public class Date {
int year;
int month;
int day;
LocalDate date;
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
this.date = LocalDate.of(year, month, day);
}
}
package cz.muni.fi.obs.data.dbo;
import lombok.EqualsAndHashCode;
import java.util.UUID;
@EqualsAndHashCode(of = "id")
public abstract class Dbo {
private final String id = UUID.randomUUID().toString();
}
package cz.muni.fi.obs.facade;
import cz.muni.fi.obs.api.DailySummaryResult;
import cz.muni.fi.obs.api.MonthlySummaryResult;
import cz.muni.fi.obs.service.AnalyticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AnalyticsFacade {
private final AnalyticsService analyticsService;
@Autowired
public AnalyticsFacade(AnalyticsService analyticsService) {
this.analyticsService = analyticsService;
}
public DailySummaryResult getDailySummary(String accountNumber, int year, int month) {
return analyticsService.getDailySummary(accountNumber, year, month);
}
public MonthlySummaryResult getMonthlySummary(String accountNumber, int year, int month) {
return analyticsService.getMonthlySummary(accountNumber, year, month);
}
}
package cz.muni.fi.obs.service;
import cz.muni.fi.obs.api.DailySummary;
import cz.muni.fi.obs.api.DailySummaryResult;
import cz.muni.fi.obs.api.MonthlySummary;
import cz.muni.fi.obs.api.MonthlySummaryResult;
import cz.muni.fi.obs.data.AnalyticsRepository;
import cz.muni.fi.obs.data.dbo.DailyTransaction;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
@Service
public class AnalyticsService {
private final AnalyticsRepository analyticsRepository;
public AnalyticsService(AnalyticsRepository analyticsRepository) {
this.analyticsRepository = analyticsRepository;
}
public DailySummaryResult getDailySummary(String accountNumber, int year, int month) {
List<DailyTransaction> transactions = analyticsRepository.getDailyTransactions(accountNumber, year, month);
if (transactions.isEmpty()) {
if (month < 1 || month > 12) {
throw new IllegalArgumentException("Month must be between 1 and 12");
}
return new DailySummaryResult(LocalDate.now(), new ArrayList<>());
}
return createDailySummaryResult(transactions);
}
public MonthlySummaryResult getMonthlySummary(String accountNumber, int year, int month) {
List<DailyTransaction> transactions = analyticsRepository.getDailyTransactions(accountNumber, year, month);
if (transactions.isEmpty()) {
if (month < 1 || month > 12) {
throw new IllegalArgumentException("Month must be between 1 and 12");
}
return new MonthlySummaryResult(LocalDate.now(), new MonthlySummary(Month.of(month).name(), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0)));
}
return createMonthlySummaryResult(transactions);
}
private DailySummaryResult createDailySummaryResult(List<DailyTransaction> transactions) {
List<DailySummary> dailySummaries = new ArrayList<>();
transactions.forEach(transaction -> dailySummaries.add(createDailySummary(transaction)));
return new DailySummaryResult(LocalDate.now(), dailySummaries);
}
private DailySummary createDailySummary(DailyTransaction transaction) {
return new DailySummary(transaction.getDate().getDate(),
transaction.getTotalWithdrawalTransactions(),
transaction.getTotalDepositTransactions(),
transaction.getTotalWithdrawalAmount(),
transaction.getTotalDepositAmount(),
transaction.getAverageWithdrawalAmount(),
transaction.getAverageDepositAmount(),
transaction.getTotalDepositAmount().subtract(transaction.getTotalWithdrawalAmount()));
}
private MonthlySummaryResult createMonthlySummaryResult(List<DailyTransaction> transactions) {
return new MonthlySummaryResult(LocalDate.now(), createMonthlySummary(transactions));
}
private MonthlySummary createMonthlySummary(List<DailyTransaction> transactions) {
String month = Month.of(transactions.getFirst().getDate().getMonth()).name();
BigDecimal totalWithdrawalTransactions = new BigDecimal(0);
BigDecimal totalDepositTransactions = new BigDecimal(0);
BigDecimal totalWithdrawalAmount = new BigDecimal(0);
BigDecimal totalDepositAmount = new BigDecimal(0);
for (DailyTransaction transaction : transactions) {
totalWithdrawalTransactions = totalWithdrawalTransactions.add(transaction.getTotalWithdrawalTransactions());
totalDepositTransactions = totalDepositTransactions.add(transaction.getTotalDepositTransactions());
totalWithdrawalAmount = totalWithdrawalAmount.add(transaction.getTotalWithdrawalAmount());
totalDepositAmount = totalDepositAmount.add(transaction.getTotalDepositAmount());
}
BigDecimal averageWithdrawalAmount = totalWithdrawalAmount.divide(totalWithdrawalTransactions, 2, RoundingMode.HALF_UP);
BigDecimal averageDepositAmount = totalDepositAmount.divide(totalDepositTransactions, 2, RoundingMode.HALF_UP);
return new MonthlySummary(month,
totalWithdrawalTransactions,
totalDepositTransactions,
totalWithdrawalAmount,
totalDepositAmount,
averageWithdrawalAmount,
averageDepositAmount,
totalDepositAmount.subtract(totalWithdrawalAmount));
}
}
server:
servlet:
context-path: '/api/analytics-service'
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment