Java Personal Finance Tracker Application

Loading

Building a Java Personal Finance Tracker Application involves creating a system that allows users to track their income, expenses, and savings. Below is a step-by-step guide to building such an application, including the key components, design considerations, and example code snippets.


1. Requirements Analysis

Before starting, define the requirements for the application:

  • User Roles: Admin (manage users) and Customer (track finances).
  • Income Management: Add, update, delete, and view income sources.
  • Expense Management: Add, update, delete, and view expenses.
  • Savings Tracking: Calculate and track savings based on income and expenses.
  • Reporting: Generate reports for income, expenses, and savings.
  • User Authentication: Secure access to the application for authenticated users.

2. System Design

Modules

  1. User Management
  • Add, update, delete, and view users.
  1. Income Management
  • Add, update, delete, and view income sources.
  1. Expense Management
  • Add, update, delete, and view expenses.
  1. Savings Tracking
  • Calculate and track savings based on income and expenses.
  1. Reporting
  • Generate reports for income, expenses, and savings.
  1. User Authentication
  • Admin and customer login.

Database Design

  • User Table: user_id, username, password, role
  • Income Table: income_id, user_id, source, amount, date
  • Expense Table: expense_id, user_id, category, amount, date
  • Savings Table: savings_id, user_id, amount, date

3. Technology Stack

  • Backend: Java (Spring Boot)
  • Frontend: Thymeleaf (for simplicity) or Angular/React (for advanced UI)
  • Database: MySQL or H2 (for testing)
  • Build Tool: Maven or Gradle
  • Security: Spring Security for authentication and authorization

4. Implementation

Step 1: Set Up the Project

Create a Spring Boot project using Spring Initializr with the following dependencies:

  • Spring Web
  • Spring Data JPA
  • Spring Security
  • Thymeleaf (for UI)
  • MySQL Driver (or H2 for testing)

Step 2: Define Entities

Create Java classes for the database tables.

User.java

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    private String username;
    private String password;
    private String role; // "ADMIN" or "CUSTOMER"

    // Getters and Setters
}

Income.java

@Entity
public class Income {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long incomeId;
    private Long userId;
    private String source;
    private double amount;
    private LocalDate date;

    // Getters and Setters
}

Expense.java

@Entity
public class Expense {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long expenseId;
    private Long userId;
    private String category;
    private double amount;
    private LocalDate date;

    // Getters and Setters
}

Savings.java

@Entity
public class Savings {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long savingsId;
    private Long userId;
    private double amount;
    private LocalDate date;

    // Getters and Setters
}

Step 3: Create Repositories

Use Spring Data JPA to create repositories for database operations.

UserRepository.java

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username); // For authentication
}

IncomeRepository.java

public interface IncomeRepository extends JpaRepository<Income, Long> {
    List<Income> findByUserId(Long userId); // For income history
}

ExpenseRepository.java

public interface ExpenseRepository extends JpaRepository<Expense, Long> {
    List<Expense> findByUserId(Long userId); // For expense history
}

SavingsRepository.java

public interface SavingsRepository extends JpaRepository<Savings, Long> {
    List<Savings> findByUserId(Long userId); // For savings history
}

Step 4: Implement Services

Create service classes to handle business logic.

IncomeService.java

@Service
public class IncomeService {
    @Autowired
    private IncomeRepository incomeRepository;

    public List<Income> getAllIncomes(Long userId) {
        return incomeRepository.findByUserId(userId);
    }

    public void addIncome(Income income) {
        incomeRepository.save(income);
    }

    public void updateIncome(Long incomeId, Income income) {
        income.setIncomeId(incomeId);
        incomeRepository.save(income);
    }

    public void deleteIncome(Long incomeId) {
        incomeRepository.deleteById(incomeId);
    }
}

ExpenseService.java

@Service
public class ExpenseService {
    @Autowired
    private ExpenseRepository expenseRepository;

    public List<Expense> getAllExpenses(Long userId) {
        return expenseRepository.findByUserId(userId);
    }

    public void addExpense(Expense expense) {
        expenseRepository.save(expense);
    }

    public void updateExpense(Long expenseId, Expense expense) {
        expense.setExpenseId(expenseId);
        expenseRepository.save(expense);
    }

    public void deleteExpense(Long expenseId) {
        expenseRepository.deleteById(expenseId);
    }
}

SavingsService.java

@Service
public class SavingsService {
    @Autowired
    private SavingsRepository savingsRepository;

    @Autowired
    private IncomeRepository incomeRepository;

    @Autowired
    private ExpenseRepository expenseRepository;

    public double calculateSavings(Long userId) {
        double totalIncome = incomeRepository.findByUserId(userId).stream().mapToDouble(Income::getAmount).sum();
        double totalExpense = expenseRepository.findByUserId(userId).stream().mapToDouble(Expense::getAmount).sum();
        return totalIncome - totalExpense;
    }

    public void saveSavings(Long userId) {
        double savingsAmount = calculateSavings(userId);
        Savings savings = new Savings();
        savings.setUserId(userId);
        savings.setAmount(savingsAmount);
        savings.setDate(LocalDate.now());
        savingsRepository.save(savings);
    }

    public List<Savings> getSavingsHistory(Long userId) {
        return savingsRepository.findByUserId(userId);
    }
}

Step 5: Create Controllers

Create controllers to handle HTTP requests.

IncomeController.java

@RestController
@RequestMapping("/incomes")
public class IncomeController {
    @Autowired
    private IncomeService incomeService;

    @GetMapping("/{userId}")
    public List<Income> getAllIncomes(@PathVariable Long userId) {
        return incomeService.getAllIncomes(userId);
    }

    @PostMapping
    public void addIncome(@RequestBody Income income) {
        incomeService.addIncome(income);
    }

    @PutMapping("/{incomeId}")
    public void updateIncome(@PathVariable Long incomeId, @RequestBody Income income) {
        incomeService.updateIncome(incomeId, income);
    }

    @DeleteMapping("/{incomeId}")
    public void deleteIncome(@PathVariable Long incomeId) {
        incomeService.deleteIncome(incomeId);
    }
}

ExpenseController.java

@RestController
@RequestMapping("/expenses")
public class ExpenseController {
    @Autowired
    private ExpenseService expenseService;

    @GetMapping("/{userId}")
    public List<Expense> getAllExpenses(@PathVariable Long userId) {
        return expenseService.getAllExpenses(userId);
    }

    @PostMapping
    public void addExpense(@RequestBody Expense expense) {
        expenseService.addExpense(expense);
    }

    @PutMapping("/{expenseId}")
    public void updateExpense(@PathVariable Long expenseId, @RequestBody Expense expense) {
        expenseService.updateExpense(expenseId, expense);
    }

    @DeleteMapping("/{expenseId}")
    public void deleteExpense(@PathVariable Long expenseId) {
        expenseService.deleteExpense(expenseId);
    }
}

SavingsController.java

@RestController
@RequestMapping("/savings")
public class SavingsController {
    @Autowired
    private SavingsService savingsService;

    @GetMapping("/{userId}")
    public List<Savings> getSavingsHistory(@PathVariable Long userId) {
        return savingsService.getSavingsHistory(userId);
    }

    @PostMapping("/{userId}")
    public void saveSavings(@PathVariable Long userId) {
        savingsService.saveSavings(userId);
    }
}

Step 6: Implement Security

Use Spring Security to secure the application.

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserRepository userRepository;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(username -> userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found")));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/incomes/**", "/expenses/**", "/savings/**").authenticated()
            .anyRequest().permitAll()
            .and()
            .httpBasic();
    }
}

Step 7: Frontend (Optional)

Use Thymeleaf or a frontend framework like Angular/React to create a user interface for the application.


5. Testing

  • Use JUnit and Mockito for unit testing.
  • Test the application using Postman or Swagger for API testing.

6. Deployment

  • Package the application as a JAR/WAR file and deploy it to a server (e.g., Tomcat).
  • Use Docker for containerization and Kubernetes for orchestration (optional).

Example Use Cases

  1. Add Income
  • User adds a new income source with details like source, amount, and date.
  1. Add Expense
  • User adds a new expense with details like category, amount, and date.
  1. Calculate Savings
  • User calculates and saves their savings based on income and expenses.
  1. View Reports
  • User views reports for income, expenses, and savings.

Leave a Reply

Your email address will not be published. Required fields are marked *