How mrpyaesone/personal-expense-tracker-assessment works
Purpose and runtime
Personal-Expense-Tracker is a single-activity native Android app for recording and viewing personal expense logs. It runs Kotlin/Android with Jetpack Compose, Coroutines/Flow, Hilt dependency injection, Room over local SQLite, and Compose Navigation. It has no indicated remote backend or external service dependency.
Application entry and composition
Android launches the application and activity, which establish app-wide DI and the Compose UI/navigation host.
• app/src/main/java/com/example/pro_expense/ProExpenseApplication.kt
• app/src/main/java/com/example/pro_expense/MainActivity.kt
• app/src/main/AndroidManifest.xml
Navigation defines the two primary feature destinations: expense listing and expense entry.
• app/src/main/java/com/example/pro_expense/navigation/NavGraph.kt
• app/src/main/java/com/example/pro_expense/navigation/NavHost.kt
UI feature boundary
Each feature owns its Compose screen, ViewModel, and immutable UI state. Screens render state and send user events to ViewModels; ViewModels invoke domain use cases rather than data access directly.
• app/src/main/java/com/example/pro_expense/ui/expenselist/ExpenseListScreen.kt
• app/src/main/java/com/example/pro_expense/ui/expenselist/ExpenseListViewModel.kt
• app/src/main/java/com/example/pro_expense/ui/logexpense/LogExpenseViewModel.kt
The list flow presents persisted logs; the log-expense flow captures an amount/category/date-style entry, validates and submits it, then navigates through feature navigation contracts.
• app/src/main/java/com/example/pro_expense/ui/logexpense/LogExpenseScreen.kt
• app/src/main/java/com/example/pro_expense/ui/logexpense/LogExpenseNavigation.kt
• app/src/main/java/com/example/pro_expense/ui/expenselist/ExpenseListNavigation.kt
Domain business boundary
The domain layer is UI- and storage-agnostic. ExpenseLog is the business model; ExpenseRepo is the persistence contract; single-purpose use cases mediate loading and logging operations.
• app/src/main/java/com/example/pro_expense/domain/model/ExpenseLog.kt
• app/src/main/java/com/example/pro_expense/domain/repo/ExpenseRepo.kt
• app/src/main/java/com/example/pro_expense/domain/usecase/LoadExpenseLogsUseCase.kt
• app/src/main/java/com/example/pro_expense/domain/usecase/LogExpenseUseCase.kt
A dispatcher abstraction isolates coroutine execution policy from use cases and enables deterministic tests.
• app/src/main/java/com/example/pro_expense/domain/dispatcher/DispatcherProvider.kt
• app/src/main/java/com/example/pro_expense/domain/di/DispatcherModule.kt
Persistence and repository boundary
Room is the sole system of record. The database exposes the expense DAO; entity types represent SQLite rows. ExpenseRepoImpl implements the domain interface, coordinates DAO calls, and maps between database entities and domain models.
• app/src/main/java/com/example/pro_expense/data/local/ProExpenseDatabase.kt
• app/src/main/java/com/example/pro_expense/data/local/dao/ExpenseLogDao.kt
• app/src/main/java/com/example/pro_expense/data/local/entities/ExpenseLogEntity.kt
• app/src/main/java/com/example/pro_expense/data/ExpenseRepoImpl.kt
• app/src/main/java/com/example/pro_expense/data/mapper/ExpenseLogMapper.kt
Primary data flow is: Room DAO → repository/entity-domain mapper → LoadExpenseLogsUseCase → list ViewModel state → Compose list. Write flow reverses this: form → log ViewModel → LogExpenseUseCase → repository/domain-entity mapper → DAO → Room.
Dependency assembly and representation transforms
Hilt modules bind the interface-to-implementation and provision database/DAO dependencies, keeping construction out of feature code.
• app/src/main/java/com/example/pro_expense/data/di/RepoModule.kt
• app/src/main/java/com/example/pro_expense/data/local/di/DatabaseModule.kt
• app/src/main/java/com/example/pro_expense/data/local/di/DaoModule.kt
A second mapping boundary converts domain logs into presentation-specific view objects, preventing Compose rendering concerns from leaking into domain or storage.
• app/src/main/java/com/example/pro_expense/ui/mapper/ExpenseLogVOMapper.kt
• app/src/main/java/com/example/pro_expense/ui/vo/ExpenseLogVO.kt
Main entry points: ExpenseRepoImpl.kt Expense repository impl · RepoModule.kt Hilt modules · NavHost.kt Navigation host · ExpenseListViewModel.kt Expense list ViewModel
Components 19
App & Navigation
- Android manifest
app/src/main/AndroidManifest.xml - ProExpense application
app/src/main/java/com/example/pro_expense/ProExpenseApplication.kt - Main activity
app/src/main/java/com/example/pro_expense/MainActivity.kt - Navigation host · Hosts the expense-list and log-expense destinations.
app/src/main/java/com/example/pro_expense/navigation/NavHost.kt
Compose Features
- Expense list screen
app/src/main/java/com/example/pro_expense/ui/expenselist/ExpenseListScreen.kt - Expense list ViewModel
app/src/main/java/com/example/pro_expense/ui/expenselist/ExpenseListViewModel.kt - Log expense screen
app/src/main/java/com/example/pro_expense/ui/logexpense/LogExpenseScreen.kt - Log expense ViewModel · Validates and submits expense entries.
app/src/main/java/com/example/pro_expense/ui/logexpense/LogExpenseViewModel.kt - Expense log VO mapper · Converts domain logs into Compose view objects.
app/src/main/java/com/example/pro_expense/ui/mapper/ExpenseLogVOMapper.kt
Domain
- Expense log
app/src/main/java/com/example/pro_expense/domain/model/ExpenseLog.kt - Expense repository
app/src/main/java/com/example/pro_expense/domain/repo/ExpenseRepo.kt - Load expense logs
app/src/main/java/com/example/pro_expense/domain/usecase/LoadExpenseLogsUseCase.kt - Log expense
app/src/main/java/com/example/pro_expense/domain/usecase/LogExpenseUseCase.kt - Dispatcher provider · Supplies execution policy to use cases.
app/src/main/java/com/example/pro_expense/domain/dispatcher/DispatcherProvider.kt
Local Persistence
- Expense repository impl · Maps domain logs and coordinates DAO access.
app/src/main/java/com/example/pro_expense/data/ExpenseRepoImpl.kt - Expense log DAO
app/src/main/java/com/example/pro_expense/data/local/dao/ExpenseLogDao.kt - ProExpense database · Local SQLite system of record.
app/src/main/java/com/example/pro_expense/data/local/ProExpenseDatabase.kt - Expense log entity
app/src/main/java/com/example/pro_expense/data/local/entities/ExpenseLogEntity.kt
Dependency Injection
- Hilt modules · Binds repository and provides Room database and DAO.
app/src/main/java/com/example/pro_expense/data/di/RepoModule.kt
Connections 22
- Android manifest → ProExpense application: launches
- ProExpense application → Main activity: initializes DI for
- Main activity → Navigation host: sets Compose content
- Navigation host → Expense list screen: list destination
- Navigation host → Log expense screen: entry destination
- Expense list screen → Expense list ViewModel: events and state
- Log expense screen → Log expense ViewModel: form events and state
- Expense list ViewModel → Load expense logs: loads logs
- Expense list ViewModel → Expense log VO mapper: maps for rendering
- Log expense ViewModel → Log expense: submits expense
- Load expense logs → Expense repository: reads via
- Log expense → Expense repository: writes via
- Load expense logs → Dispatcher provider: uses
- Log expense → Dispatcher provider: uses
- Expense repository impl → Expense repository: implements
- Expense repository impl → Expense log DAO: reads and writes
- Expense repository impl → Expense log entity: maps with domain log
- Expense log DAO → ProExpense database: Room access
- ProExpense database → Expense log entity: stores rows
- Hilt modules → Expense repository impl: binds
- Hilt modules → ProExpense database: provides
- Hilt modules → Expense log DAO: provides