Skip to content

Add Java Budget Tracker CLI Application#139

Open
devin-ai-integration[bot] wants to merge 9 commits into
mainfrom
devin/1777537836-budget-tracker-cli
Open

Add Java Budget Tracker CLI Application#139
devin-ai-integration[bot] wants to merge 9 commits into
mainfrom
devin/1777537836-budget-tracker-cli

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Apr 30, 2026

Copy link
Copy Markdown

Summary

Adds a standalone Java command-line budget tracker application in the budget-tracker/ directory. The application supports:

  • Add income entries with a description and amount
  • Add expense entries with a category, description, and amount
  • View summary showing total income, total expenses, and net balance
  • List all transactions in chronological order with type, category, and amount
  • Filter by category — displays available categories and shows only matching transactions (case-insensitive)
  • Separate functions for each operation (clean separation into model, service, storage, and CLI layers)
  • JSON file persistence via Gson — saves all entries to budget_data.json and reloads on startup
  • Input validation with clear error messages for empty fields, non-positive amounts, non-numeric input, NaN, and Infinity
  • Atomic file writes — writes to a temp file first, then atomically renames to prevent data loss on I/O failures

Tech Stack

  • Java 21 (JDK 21), Gradle 8.7 (with wrapper)
  • Gson for JSON serialization
  • JUnit 5 for testing, JaCoCo for coverage (80%+ line coverage gate)
  • Checkstyle for linting (0 violations)

Project Structure

budget-tracker/
├── build.gradle
├── settings.gradle
├── gradlew / gradlew.bat
├── config/checkstyle/checkstyle.xml
└── src/
    ├── main/java/com/budgettracker/
    │   ├── BudgetTrackerApp.java      # CLI entry point (6 menu options)
    │   ├── model/
    │   │   ├── Transaction.java       # Data model
    │   │   └── TransactionType.java   # INCOME/EXPENSE enum
    │   ├── service/
    │   │   └── BudgetService.java     # Business logic + category filtering
    │   └── storage/
    │       └── StorageService.java    # JSON file persistence (atomic writes)
    └── test/java/com/budgettracker/
        ├── BudgetTrackerAppTest.java
        ├── model/TransactionTest.java
        ├── service/BudgetServiceTest.java
        └── storage/StorageServiceTest.java

Review & Testing Checklist for Human

  • Run cd budget-tracker && ./gradlew clean check to confirm build, tests, coverage, and lint pass
  • Run the app: cd budget-tracker && ./gradlew run --console=plain
  • Test filter feature: add expenses with different categories, then use option 5 to filter
  • Verify JSON persistence: add entries, exit, re-run, confirm data reloaded
  • Test invalid inputs: empty descriptions, negative amounts, NaN, Infinity, invalid menu options

Notes

  • The budget tracker is self-contained in the budget-tracker/ directory and does not affect the existing Spring Boot application
  • Migrated from Maven/JDK 17 to Gradle 8.7/JDK 21 per user request
  • All Devin Review findings addressed: NaN/Infinity validation, test teardown lifecycle, null-safe category handling, save failure rollback, atomic file writes, JsonIOException handling

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/e3d98600bc714620a973acac2a14135e


Open in Devin Review

- Add income entries with description and amount
- Add expense entries with category, description, and amount
- Display summary with total income, expenses, and net balance
- List all transactions in chronological order
- Separate functions for each operation
- JSON file persistence with reload on startup
- Input validation with clear error messages
- 95% code coverage with JUnit 5 tests
- Checkstyle linting with zero violations
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

- Reject NaN and Infinity in readAmount() with Double.isFinite check
- Add @AfterEach to tearDown() in BudgetTrackerAppTest
- Fix System.out restoration in BudgetServiceTest with proper
  @BeforeEach/@AfterEach lifecycle
- Add tests for NaN and Infinity rejection
devin-ai-integration[bot]

This comment was marked as resolved.

Prevents NullPointerException when Gson deserializes entries with
missing category field.
devin-ai-integration[bot]

This comment was marked as resolved.

Check storageService.save() return value in addIncome/addExpense.
If save fails, remove the transaction from the in-memory list and
throw RuntimeException so the CLI shows an error instead of a
false success message.
devin-ai-integration[bot]

This comment was marked as resolved.

Use consistent space-separated columns with matching widths in both
the printTransactions() header and Transaction.toString().
devin-ai-integration[bot]

This comment was marked as resolved.

Reject NaN and Infinity at the BudgetService API level, matching
the CLI-layer validation for defense in depth.
devin-ai-integration[bot]

This comment was marked as resolved.

JsonIOException is a sibling of JsonSyntaxException (both extend
JsonParseException), not caught by IOException. Add explicit catch
blocks to prevent uncaught crashes during startup and to ensure
save() returns false for BudgetService rollback logic.
devin-ai-integration[bot]

This comment was marked as resolved.

- Replace Maven pom.xml with Gradle build.gradle targeting Java 21
- Add Gradle wrapper (8.7) for reproducible builds
- Add Checkstyle config and JaCoCo coverage verification
- Implement atomic save via temp file + Files.move() to prevent
  data loss on write failures
- Update .gitignore for Gradle build artifacts
- New menu option 5: Filter by Category
- Shows available categories, accepts user input, displays matching
  transactions with case-insensitive matching
- BudgetService: getCategories(), filterByCategory(), printFilteredTransactions()
- BudgetTrackerApp: handleFilterByCategory() with input validation
- Comprehensive tests for service and CLI layers
- Exit moved to option 6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants