Skip to content

feat: portfolio rollup helper for category-level reporting#2

Open
ak684 wants to merge 2 commits into
mainfrom
feat/investment-rollup-v2
Open

feat: portfolio rollup helper for category-level reporting#2
ak684 wants to merge 2 commits into
mainfrom
feat/investment-rollup-v2

Conversation

@ak684
Copy link
Copy Markdown
Owner

@ak684 ak684 commented May 7, 2026

Summary

Adds a small utility for computing category-level investment totals and "top N" company rankings, plus a category filter clause builder used by upcoming dashboard rollup endpoints.

This is a building block — wiring into the controller layer comes in a follow-up PR.

Test plan

  • Code review
  • Manual smoke once the dashboard endpoints land

Adds a small utility for category-level investment totals, top-N rankings,
and a filter clause builder used by upcoming dashboard endpoints.
@ak684
Copy link
Copy Markdown
Owner Author

ak684 commented May 7, 2026

@OpenHands /review

@alona-openhands
Copy link
Copy Markdown

I'm on it! ak684 can track my progress at all-hands.dev

Copy link
Copy Markdown
Owner Author

@ak684 ak684 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ak684 — first-pass review below.

This review was generated by an AI agent (OpenHands) on behalf of the user.


Summary

The utility class is small and well-scoped, but there are two blocking issues (a SQL injection vulnerability and an off-by-one bug) plus several NPE-prone patterns that should be addressed before merge.

🔒 Security

File Line Issue
InvestmentRollup.java 62 SQL injection — category strings interpolated without escaping or parameterization

🐛 Bugs

File Line Issue
InvestmentRollup.java 50 Off-by-one — limit + 1 returns N+1 results instead of N
InvestmentRollup.java 26, 46 NPE when company.get("category") is null
InvestmentRollup.java 27 NPE / ClassCastException when company.get("amount") is null or non-numeric
InvestmentRollup.java 57 Produces invalid SQL category IN () when categories list is empty

💡 Suggestions

File Line Issue
InvestmentRollup.java 22-23 Consider typed DTOs instead of raw Map<String, Object>

Comment thread src/main/java/io/ventureplatform/util/InvestmentRollup.java Outdated
Comment thread src/main/java/io/ventureplatform/util/InvestmentRollup.java
Comment thread src/main/java/io/ventureplatform/util/InvestmentRollup.java Outdated
Comment thread src/main/java/io/ventureplatform/util/InvestmentRollup.java Outdated
Comment thread src/main/java/io/ventureplatform/util/InvestmentRollup.java Outdated
Comment thread src/main/java/io/ventureplatform/util/InvestmentRollup.java
@alona-openhands
Copy link
Copy Markdown

Summary

The /review request on PR #2 has been fully addressed. Here's what was done:

Checklist

  • Retrieved PR metadata (author, reviewers, diff, base/head branches) via GitHub API
  • Thoroughly analyzed the single changed file (InvestmentRollup.java) for security, correctness, style, and architecture issues
  • Posted a structured code review with 6 inline comments on specific diff lines
  • Posted a summary comment on the PR, organized by category (Security / Bugs / Suggestions) with a table of findings
  • @-mentioned the PR author (@ak684) in the summary per the review skill instructions
  • Included AI disclosure note in the review body
  • No code changes were made — this was a review-only action, as requested

Findings Posted

# Severity Line Issue
1 🔒 Security 62 SQL injection in buildCategoryFilter — raw string concatenation into SQL
2 🐛 Bug 50 Off-by-one — .limit(limit + 1) returns N+1 results
3 🐛 Bug 26, 46 NPE when company.get("category") is null
4 🐛 Bug 27 NPE/ClassCastException when company.get("amount") is null or non-numeric
5 🐛 Bug 57 Invalid SQL category IN () when categories list is empty
6 💡 Suggestion 22 Consider typed DTO record instead of Map<String, Object>

No extraneous changes were made — the scope was limited strictly to reviewing and commenting on the PR as requested.

@ak684
Copy link
Copy Markdown
Owner Author

ak684 commented May 7, 2026

@OpenHands please fix

@alona-openhands
Copy link
Copy Markdown

I'm on it! ak684 can track my progress at all-hands.dev

@ak684 ak684 closed this May 7, 2026
@ak684 ak684 reopened this May 7, 2026
@ak684 ak684 requested a review from aking13 as a code owner May 7, 2026 11:27
- Introduce CompanyInvestment record to replace Map<String, Object>,
  eliminating NPE and ClassCastException risks on category/amount access
- Introduce CategoryFilter record returning parameterized SQL (? placeholders)
  with bind values instead of interpolating strings (SQL injection fix)
- Fix off-by-one: .limit(limit + 1) → .limit(limit)
- Handle empty/null categories list with 1=0 sentinel
- Use Objects.equals() for null-safe category comparison

Co-authored-by: openhands <openhands@all-hands.dev>
@alona-openhands
Copy link
Copy Markdown

Summary

All 6 review comments on PR #2 have been fully addressed in a single commit (7009397) pushed to feat/investment-rollup-v2.

Checklist — Review Feedback Addressed

  • 🔒 SQL Injection (line 62): buildCategoryFilter now returns a CategoryFilter record with parameterized category IN (?, ?, ?) clause and a separate List<String> of bind values — no more string interpolation.
  • 🐛 Off-by-one (line 50): Changed .limit(limit + 1) to .limit(limit).
  • 🐛 NPE on category (line 26): Replaced company.get("category").equals(category) with Objects.equals(category, company.category()).
  • 🐛 NPE/ClassCastException on amount (line 27): Eliminated unsafe casts — CompanyInvestment record uses primitive long amount.
  • 🐛 Invalid SQL on empty input (line 57): Returns 1=0 sentinel with empty parameter list when categories is null or empty.
  • 💡 Type safety suggestion (line 22): Introduced CompanyInvestment and CategoryFilter records, replacing the fragile Map<String, Object> API throughout.
  • All 6 review threads replied to with commit references and resolved.

Conciseness

The changes are minimal and focused — only the single file InvestmentRollup.java was modified, and every change directly addresses a review comment. No extraneous refactoring, no new files, no unrelated modifications. The two new inner records (CompanyInvestment, CategoryFilter) were the minimum needed to address the type-safety, NPE, cast, and SQL injection concerns simultaneously.

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.

2 participants