fix: excluded paid credit from total expenses (its a loan)

This commit is contained in:
filippo-ferrari 2024-09-07 16:54:04 +02:00
parent 91d4f4245f
commit 3070ed7571
5 changed files with 61 additions and 20 deletions

View file

@ -73,4 +73,8 @@ public class Expense extends AbstractEntity {
*/
@Column(name = "isPaid", nullable = false)
private Boolean isPaid = false;
@Enumerated(EnumType.STRING)
@Column(name = "expenseType", nullable = false)
private ExpenseType expenseType;
}

View file

@ -0,0 +1,7 @@
package com.application.munera.data;
public enum ExpenseType {
CREDIT,
DEBIT,
NONE
}

View file

@ -2,6 +2,7 @@ package com.application.munera.repositories;
import com.application.munera.data.Expense;
import com.application.munera.data.ExpenseType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
@ -27,6 +28,9 @@ public interface ExpenseRepository extends JpaRepository<Expense, Long>, JpaSpec
@Query("SELECT e FROM Expense e JOIN e.debtors d WHERE d.id = :personId AND e.isPaid = false")
Set<Expense> findUnpaidDebtorsExpensesByPersonId(@Param("personId") Long personId);
@Query("SELECT e FROM Expense e WHERE YEAR(e.date) = :year AND NOT (e.expenseType = :expenseType AND e.isPaid = true)")
List<Expense> findByYearAndFilterCreditPaid(@Param("year") int year, @Param("expenseType") ExpenseType expenseType);
boolean existsByIdAndIsPaidTrue(Long id);
List<Expense> findAllByOrderByDateDesc();}

View file

@ -1,6 +1,7 @@
package com.application.munera.services;
import com.application.munera.data.Expense;
import com.application.munera.data.ExpenseType;
import com.application.munera.data.Person;
import com.application.munera.repositories.ExpenseRepository;
import org.springframework.data.domain.Page;
@ -8,23 +9,25 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.annotation.Nonnull;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
@Service
public class ExpenseService {
private final ExpenseRepository repository;
private final ExpenseRepository expenseRepository;
public ExpenseService(ExpenseRepository repository) {
this.repository = repository;
public ExpenseService(ExpenseRepository expenseRepository) {
this.expenseRepository = expenseRepository;
}
public Optional<Expense> get(Long id) {
return repository.findById(id);
return expenseRepository.findById(id);
}
/**
@ -33,7 +36,7 @@ public class ExpenseService {
* @return the collections of expenses found
*/
public Collection<Expense> findDebtByUser(final Person person) {
return repository.findDebtorsExpensesByPersonId(person.getId());
return expenseRepository.findDebtorsExpensesByPersonId(person.getId());
}
/**
@ -42,7 +45,7 @@ public class ExpenseService {
* @return the collections of expenses found
*/
public Collection<Expense> findCreditByUser(final Person person) {
return repository.findCreditorsExpensesByPersonId(person.getId());
return expenseRepository.findCreditorsExpensesByPersonId(person.getId());
}
/**
@ -51,7 +54,7 @@ public class ExpenseService {
* @return the collections of expenses found
*/
public Collection<Expense> findUnpaidDebtByUser(final Person person) {
return repository.findUnpaidDebtorsExpensesByPersonId(person.getId());
return expenseRepository.findUnpaidDebtorsExpensesByPersonId(person.getId());
}
/**
@ -60,7 +63,7 @@ public class ExpenseService {
* @return the collections of expenses found
*/
public Collection<Expense> findUnpaidCreditByUser(final Person person) {
return repository.findUnpaidCreditorsExpensesByPersonId(person.getId());
return expenseRepository.findUnpaidCreditorsExpensesByPersonId(person.getId());
}
/**
@ -74,7 +77,7 @@ public class ExpenseService {
return Stream.concat(credits.stream(), debits.stream()).toList();
}
public List<Expense> findAll() {return repository.findAll();}
public List<Expense> findAll() {return expenseRepository.findAll();}
/**
* updates an expense
@ -82,7 +85,8 @@ public class ExpenseService {
*/
public void update(Expense entity) {
if (Boolean.TRUE.equals(entity.getIsPaid())) entity.setPaymentDate(LocalDateTime.now());
repository.save(entity);
this.setExpenseType(entity);
expenseRepository.save(entity);
}
/**
@ -90,23 +94,27 @@ public class ExpenseService {
* @param id the id of the expense to delete
*/
public void delete(Long id) {
repository.deleteById(id);
expenseRepository.deleteById(id);
}
public Page<Expense> list(Pageable pageable) {
return repository.findAll(pageable);
return expenseRepository.findAll(pageable);
}
public Page<Expense> list(Pageable pageable, Specification<Expense> filter) {
return repository.findAll(filter, pageable);
return expenseRepository.findAll(filter, pageable);
}
public int count() {
return (int) repository.count();
return (int) expenseRepository.count();
}
public List<Expense> findAllByYear(final int year ) {
return this.repository.findAllByYear(year);
return this.expenseRepository.findAllByYear(year);
}
public List<Expense> findExpensesByYearExcludingCreditPaid(int year) {
return expenseRepository.findByYearAndFilterCreditPaid(year, ExpenseType.CREDIT);
}
/**
@ -115,7 +123,7 @@ public class ExpenseService {
* @return true if the expense has been paid, false otherwise
*/
public boolean isExpensePaid(final Expense expense) {
return this.repository.existsByIdAndIsPaidTrue(expense.getId());
return this.expenseRepository.existsByIdAndIsPaidTrue(expense.getId());
}
/**
@ -123,6 +131,24 @@ public class ExpenseService {
* @return the list of expenses found
*/
public List<Expense> findAllOrderByDateDescending() {
return this.repository.findAllByOrderByDateDesc();
return this.expenseRepository.findAllByOrderByDateDesc();
}
/**
* sets the Expense type depending on the presence or absence of creditors and debtors
* this is used to filter expenses with a creditor that are paid, since they are not part of
* the actual money the user has spent, it's just a load technically
* @param expense the expense to set the type of
*/
private void setExpenseType(final @Nonnull Expense expense) {
if (Objects.nonNull(expense.getCreditors()) && !expense.getCreditors().isEmpty())
// If creditors are present, set type to CREDIT
expense.setExpenseType(ExpenseType.CREDIT);
else if (Objects.nonNull(expense.getDebtors()) && !expense.getDebtors().isEmpty())
// If debtors are present and no creditors, set type to DEBIT
expense.setExpenseType(ExpenseType.DEBIT);
else
// If neither creditors nor debtors are present, set type to NONE
expense.setExpenseType(ExpenseType.NONE);
}
}

View file

@ -105,7 +105,7 @@ public class DashboardView extends Div {
}
private String generateBarChartScript() {
List<Expense> expenses = expenseService.findAllByYear(Year.now().getValue());
List<Expense> expenses = expenseService.findExpensesByYearExcludingCreditPaid(Year.now().getValue());
// Prepare data for Highcharts
Map<String, Double> monthlyData = new LinkedHashMap<>();
@ -150,7 +150,7 @@ public class DashboardView extends Div {
}
private String generatePieChartScript() {
List<Expense> expenses = expenseService.findAllByYear(Year.now().getValue());
List<Expense> expenses = expenseService.findExpensesByYearExcludingCreditPaid(Year.now().getValue());
// Group expenses by category name and sum their costs
Map<String, Double> categoryData = expenses.stream()
@ -258,7 +258,7 @@ public class DashboardView extends Div {
}
private String generateExpensesOverTimeByCategoryScript() {
List<Expense> expenses = expenseService.findAllByYear(Year.now().getValue());
List<Expense> expenses = expenseService.findExpensesByYearExcludingCreditPaid(Year.now().getValue());
// Group expenses by category and by month
Map<String, Map<String, Double>> categoryMonthlyData = new LinkedHashMap<>();