A high-performance backend implementation designed to simplify complex debt structures and manage shared expenses across groups.
- Framework: Java with Spring Boot
- Persistence: JPA / Hibernate (ORM)
- Build & Dependency Management: Maven
- Testing: JUnit 5 & Mockito
- API Style: RESTful Design
- Layered Architecture: Strict separation between Controllers, Services, and Repositories.
- Dependency Injection: Utilizing Spring’s IoC container for loosely coupled components.
- Repository Pattern: Abstracting data access for
ExpenseandUserentities.
The system uses Data Transfer Objects to decouple the API contract from the internal database schema.
- Inbound:
CreateUserDto,CreateExpenseDto - Outbound:
GetUserDto(Ensures sensitive data like passwords aren't leaked).
The "Brain" of the application, responsible for:
- Debt Simplification: Calculating who owes whom.
- Group Management: Handling user associations within specific expense contexts.
- Currency Handling: Managing international transactions via a dedicated
CurrencyEnum.
Built with flexibility in mind using Interface Segregation:
- Interface:
PasswordEncoder - Implementation:
BCryptEncoder(Standardized hashing for user security).
The model uses a central BaseModel as an abstract class to ensure every table has consistent audit fields.
| Entity | Relationship | Description |
|---|---|---|
| User & Group | @ManyToMany |
Users can belong to multiple groups; groups have many users. |
| Expense & Group | @ManyToOne |
Multiple expenses belong to a single group context. |
| Expense & User | @ManyToOne |
Links the individual who paid to the specific expense record. |
The project maintains high reliability by isolating dependencies:
- Service Layer Testing: Focused on
UserServiceTest. - Mocking: Using Mockito to simulate Repository responses, ensuring tests are fast and independent of the database.
- Assertions: JUnit 5 for verifying business logic outcomes and edge cases.
- Modular Services: New features (like settling up via UPI/PayPal) can be added by implementing new service interfaces.
- Database Agnostic: Thanks to JPA/Hibernate, the underlying SQL engine can be swapped with minimal configuration changes.
classDiagram
class User{
- String name
- String email
- String passwordHashed
}
class Expense{
-Double amount
-String description
-String currency
-User createdBy
-User[] members
-Group group
}
class Group{
-String name
-User admin
-USer[] members
-Date createdAt
-User createdBy
}
class GroupExpense{
-Group group
-Expense expense
}
class OwedExpense{
-User user
-Expense expense
-Double amount
}
class PaidExpense{
-User user
-Expense expense
-Double amount
}
Expense "*" --o "1" User : members
Expense "*" --o "1" User : createdBy
Group "*" --o "1" User : admin
Group "*" --o "1" User : createdBy
Group "*" --o "1" User : members
GroupExpense "*" --o "1" Group
GroupExpense "1"--*"1" Expense
OwedExpense "*" --o "1" User
OwedExpense "*" --o "1" Expense
PaidExpense "*" --o "1" User
PaidExpense "*" --o "1" Expense