Skip to content

Feature/repository#4

Merged
FionaSprinkles merged 11 commits intomainfrom
feature/repository
Apr 2, 2026
Merged

Feature/repository#4
FionaSprinkles merged 11 commits intomainfrom
feature/repository

Conversation

@simonforsberg
Copy link
Copy Markdown
Contributor

@simonforsberg simonforsberg commented Mar 31, 2026

@coderabbitai review

Summary by CodeRabbit

  • New Features

    • Tickets auto-generate unique reporter tokens.
    • Added ticket comments with an "internal note" flag.
    • Audit logs added to show ticket history.
  • Improved

    • Descriptions and comment messages now support larger text and use optimized loading.
    • Attachments, comments, and audit logs are directly associated with tickets for easier retrieval.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

Ticket and TicketComment JPA mappings were modified (reporterToken generation, description/comment storage, new isInternalNote flag, relationship adjustments), and five new Spring Data JPA repository interfaces were added for Ticket, TicketComment, Attachment, AuditLog, and User.

Changes

Cohort / File(s) Summary
Ticket entity
src/main/java/org/example/alfs/entities/Ticket.java
@PrePersist now assigns reporterToken = UUID.randomUUID().toString() when null/blank; status defaulting condensed; description mapping changed to @Column(nullable = false, columnDefinition="TEXT") with lazy fetch; added @OneToMany(mappedBy="ticket") comments and auditLogs; attachments mapping removed cascade/orphanRemoval (now plain @OneToMany(mappedBy="ticket")).
TicketComment entity
src/main/java/org/example/alfs/entities/TicketComment.java
message mapping changed from @Column(length=2000) to @Basic(fetch = FetchType.LAZY) + @Column(nullable = false, columnDefinition="TEXT"); added non-null boolean isInternalNote = false persisted field.
Repositories — new interfaces
src/main/java/org/example/alfs/repositories/TicketRepository.java, src/main/java/org/example/alfs/repositories/TicketCommentRepository.java, src/main/java/org/example/alfs/repositories/AttachmentRepository.java, src/main/java/org/example/alfs/repositories/AuditLogRepository.java, src/main/java/org/example/alfs/repositories/UserRepository.java
Added five Spring Data JPA repositories: TicketRepository (derived finders: findByReporterToken, findByReporterId, findByInvestigatorId, findByStatus, findByStatusAndInvestigatorId, paged findAll), TicketCommentRepository (findByTicketIdOrderByCreatedAtAsc, findByTicketIdAndIsInternalNoteOrderByCreatedAtAsc), AttachmentRepository (findByTicketId), AuditLogRepository (findByTicketIdOrderByCreatedAtDesc), and UserRepository (basic JpaRepository for User).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Feature/entities #1: Further modifications to the same entities (Ticket, TicketComment, Attachment, AuditLog) and their mappings; likely follow-up changes.
  • Feature/entity edit #2: Parallel edits to JPA mappings and relationships for the domain entities (description/message storage, audit/attachment constraints).

Poem

🐰 I nibble code in twilight's light,

A UUID pops into the night,
Comments hide in lazy text,
Logs and files find where they're next,
Hoppity — the schema's tight! 🥕✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feature/repository' is overly vague and generic, using a non-descriptive branch-naming convention rather than a meaningful summary of the changes. Replace with a specific title that describes the primary change, such as 'Add repository interfaces for Ticket, TicketComment, Attachment, and AuditLog entities' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/repository

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/main/java/org/example/alfs/repositories/UserRepository.java (1)

10-10: Replace the inline question with a clear comment or remove it.

// Behövs för Spring Security? is ambiguous in long-term maintenance. Prefer either a concrete English comment with intent or no comment if self-explanatory.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/alfs/repositories/UserRepository.java` at line 10,
The inline Swedish question comment "// Behövs för Spring Security?" in
UserRepository.java is ambiguous; either remove it or replace it with a concise
English comment explaining intent such as why a particular method/field is
present for Spring Security integration (e.g., "Required by Spring Security for
user lookups" or a short JIRA/ticket reference). Locate the comment near the
UserRepository declaration or the specific method it refers to (e.g.,
interface/class UserRepository) and update it to a clear English explanation or
delete it if the code is self-explanatory.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/org/example/alfs/entities/Ticket.java`:
- Around line 50-51: The reporterToken initialization in the Ticket entity only
checks for null and fails to treat empty or whitespace-only strings as missing;
update the initialization logic in the Ticket class (where reporterToken is set)
to treat blank values the same as null by checking reporterToken == null ||
reporterToken.isBlank() (or equivalent) and generate a UUID when that condition
is true so blank tokens are replaced with a new unique token.

In `@src/main/java/org/example/alfs/entities/TicketComment.java`:
- Around line 28-30: The new non-null field isInternalNote in class
TicketComment is being added with `@Column`(nullable = false) but there is no DB
migration to backfill existing rows, which will cause deployment failures; fix
by either 1) adding migration tooling (e.g., Flyway/Liquibase) and creating a
migration that adds the is_internal_note column (or alters it) with a safe
default for all existing rows and then sets NOT NULL, or 2) relax the Entity
definition temporarily by changing `@Column`(nullable = false) to nullable = true
(or add a DB default) so existing databases won’t fail, then introduce a
migration later to backfill and enforce non-null; locate the change in the
TicketComment class and ensure migration targets the is_internal_note column and
uses the same boolean mapping your JPA provider expects.

---

Nitpick comments:
In `@src/main/java/org/example/alfs/repositories/UserRepository.java`:
- Line 10: The inline Swedish question comment "// Behövs för Spring Security?"
in UserRepository.java is ambiguous; either remove it or replace it with a
concise English comment explaining intent such as why a particular method/field
is present for Spring Security integration (e.g., "Required by Spring Security
for user lookups" or a short JIRA/ticket reference). Locate the comment near the
UserRepository declaration or the specific method it refers to (e.g.,
interface/class UserRepository) and update it to a clear English explanation or
delete it if the code is self-explanatory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 023eefa5-a75e-4941-b66b-10b75781f48b

📥 Commits

Reviewing files that changed from the base of the PR and between 6e48e81 and 68d048c.

📒 Files selected for processing (7)
  • src/main/java/org/example/alfs/entities/Ticket.java
  • src/main/java/org/example/alfs/entities/TicketComment.java
  • src/main/java/org/example/alfs/repositories/AttachmentRepository.java
  • src/main/java/org/example/alfs/repositories/AuditLogRepository.java
  • src/main/java/org/example/alfs/repositories/TicketCommentRepository.java
  • src/main/java/org/example/alfs/repositories/TicketRepository.java
  • src/main/java/org/example/alfs/repositories/UserRepository.java

Comment on lines +28 to +30
// Möjlighet att skriva internt meddelande (synligt för utredare/admin, inte för anmälare)
@Column(nullable = false)
private boolean isInternalNote = false;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find migration/changelog files that mention this table/column
rg -n --iglob '*.{sql,xml,yml,yaml,json}' 'ticket_comment|is_internal_note|internal_note'

# 2) Inspect likely migration directories if present
fd -i 'migration|migrations|flyway|liquibase|changelog|db'

# 3) Confirm entity-side non-null declaration (for context)
rg -n 'isInternalNote|@Column\(nullable = false\)' src/main/java

Repository: ithsjava25/project-backend-alfs

Length of output: 57


🏁 Script executed:

#!/bin/bash

# Search more broadly for migration infrastructure and configuration
echo "=== Checking for migration infrastructure ==="
fd -i 'pom\.xml|build\.gradle|application\.(yml|yaml|properties)' | head -20

echo -e "\n=== Looking for migration directories ==="
fd -type d -i 'migration|migrations|flyway|liquibase|changelog|db' | head -20

echo -e "\n=== Checking for any SQL files ==="
fd -type f -name '*.sql' | head -30

echo -e "\n=== Checking for Liquibase/Flyway XML/YAML changelogs ==="
fd -type f \( -name '*changelog*' -o -name '*migration*' \) | head -30

Repository: ithsjava25/project-backend-alfs

Length of output: 838


🏁 Script executed:

#!/bin/bash

# Verify the TicketComment entity file exists and inspect it
echo "=== Checking TicketComment entity file ==="
if [ -f "src/main/java/org/example/alfs/entities/TicketComment.java" ]; then
  echo "File exists. Checking for isInternalNote field:"
  grep -n "isInternalNote\|is_internal_note" src/main/java/org/example/alfs/entities/TicketComment.java || echo "Field not found in grep"
  echo -e "\nContext around line 28-30:"
  sed -n '25,35p' src/main/java/org/example/alfs/entities/TicketComment.java
else
  echo "File not found at expected path"
fi

Repository: ithsjava25/project-backend-alfs

Length of output: 569


🏁 Script executed:

#!/bin/bash

echo "=== Checking pom.xml for migration dependencies ==="
grep -i 'flyway\|liquibase\|migration' pom.xml | head -20

echo -e "\n=== Checking application.properties for migration config ==="
cat src/main/resources/application.properties

Repository: ithsjava25/project-backend-alfs

Length of output: 246


🏁 Script executed:

#!/bin/bash

echo "=== Checking for src/main/resources/db directory ==="
if [ -d "src/main/resources/db" ]; then
  echo "Directory exists. Contents:"
  find src/main/resources/db -type f | head -30
else
  echo "No src/main/resources/db directory found"
fi

echo -e "\n=== Checking for any migration-related files across entire repo ==="
find . -type f \( -name '*.sql' -o -name '*migration*' -o -name '*changelog*' \) 2>/dev/null | grep -v node_modules | head -30

Repository: ithsjava25/project-backend-alfs

Length of output: 237


Add/verify DB migration for new non-null column.

The new non-null field isInternalNote at line 30 requires a database migration on existing environments. Currently, the repository has no migration infrastructure (no Flyway, Liquibase, or migration files detected), and no migration for this column exists. This will fail on deployment against databases with historical rows. Either establish migration infrastructure and add a migration that backfills is_internal_note with a default value before enforcing the non-null constraint, or adjust the column definition.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/alfs/entities/TicketComment.java` around lines 28 -
30, The new non-null field isInternalNote in class TicketComment is being added
with `@Column`(nullable = false) but there is no DB migration to backfill existing
rows, which will cause deployment failures; fix by either 1) adding migration
tooling (e.g., Flyway/Liquibase) and creating a migration that adds the
is_internal_note column (or alters it) with a safe default for all existing rows
and then sets NOT NULL, or 2) relax the Entity definition temporarily by
changing `@Column`(nullable = false) to nullable = true (or add a DB default) so
existing databases won’t fail, then introduce a migration later to backfill and
enforce non-null; locate the change in the TicketComment class and ensure
migration targets the is_internal_note column and uses the same boolean mapping
your JPA provider expects.

updatedAt = LocalDateTime.now();
}

@OneToMany(mappedBy = "ticket", cascade = CascadeType.ALL, orphanRemoval = true)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we really allow hard deletes here? With cascade + orphanRemoval we would lose comments and attachments. Should we not keep the data since it's a whistleblower system? :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, I'll remove it

public interface UserRepository extends JpaRepository<User, Long> {

// Behövs för Spring Security?
Optional<User> findByUsername(String username);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we are unsure, should we add it later when security is implemented?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I left it there as a placeholder, but I'll delete it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nope, I forgot, haha. But can be deleted/modified anytime

@@ -25,6 +25,10 @@ public class TicketComment {
@Column(nullable = false, length = 2000)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think 2000 characters are enough in a whistleblower system since I guess the comments can become quite long. Should we use a TEXT column instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, I'll use @Lob

…ns, adjust relationships, and enforce stricter constraints
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/java/org/example/alfs/entities/Ticket.java (1)

60-67: Cascade removal is appropriate; consider adding soft-delete support.

Removing cascade operations aligns with the requirement to preserve whistleblower data. However, without cascade and without explicit ON DELETE constraints at the DB level, attempting to delete a Ticket will either:

  • Fail with a FK constraint violation (desired behavior), or
  • Leave orphaned TicketComment, Attachment, and AuditLog rows if FK constraints aren't enforced

To ensure data integrity, consider implementing a soft-delete pattern (e.g., an isDeleted or deletedAt field) and preventing hard deletes at the service layer. This makes the intent explicit and avoids relying solely on DB constraint behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/alfs/entities/Ticket.java` around lines 60 - 67,
The Ticket entity currently holds List<TicketComment> comments, List<Attachment>
attachments, and List<AuditLog> auditLogs without cascade; to enforce
preservation of related data implement a soft-delete on Ticket (add an isDeleted
boolean or deletedAt timestamp field and accessor methods in class Ticket) and
update repository/service delete methods to set that flag instead of calling
hard delete; also add query filtering at the JPA level (e.g., a global filter or
`@Where` clause) so normal queries exclude soft-deleted Tickets, and ensure
service-layer delete endpoints prevent physical deletes of Ticket and instead
mark related entities as retained/immutable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/java/org/example/alfs/entities/Ticket.java`:
- Around line 60-67: The Ticket entity currently holds List<TicketComment>
comments, List<Attachment> attachments, and List<AuditLog> auditLogs without
cascade; to enforce preservation of related data implement a soft-delete on
Ticket (add an isDeleted boolean or deletedAt timestamp field and accessor
methods in class Ticket) and update repository/service delete methods to set
that flag instead of calling hard delete; also add query filtering at the JPA
level (e.g., a global filter or `@Where` clause) so normal queries exclude
soft-deleted Tickets, and ensure service-layer delete endpoints prevent physical
deletes of Ticket and instead mark related entities as retained/immutable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c80f5dac-238a-43e1-b6fa-7a67561e224c

📥 Commits

Reviewing files that changed from the base of the PR and between 68d048c and f812a82.

📒 Files selected for processing (2)
  • src/main/java/org/example/alfs/entities/Ticket.java
  • src/main/java/org/example/alfs/entities/TicketComment.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/org/example/alfs/entities/TicketComment.java

…ities: refine text column definitions and remove unnecessary annotations
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/java/org/example/alfs/entities/Ticket.java (1)

59-66: Cascade removal is appropriate for data preservation.

Removing cascade and orphanRemoval from attachments (and not adding them to comments/auditLogs) ensures child records are never accidentally deleted with the ticket—correct for a whistleblower system where preserving evidence is critical.

Consider initializing collections to empty lists.

Uninitialized @OneToMany fields are null until the ORM populates them. Accessing these on a new or detached entity before persistence would throw NullPointerException.

♻️ Optional: Initialize collections defensively
 `@OneToMany`(mappedBy = "ticket")
-private List<TicketComment> comments;
+private List<TicketComment> comments = new ArrayList<>();

 `@OneToMany`(mappedBy = "ticket")
-private List<Attachment> attachments;
+private List<Attachment> attachments = new ArrayList<>();

 `@OneToMany`(mappedBy = "ticket")
-private List<AuditLog> auditLogs;
+private List<AuditLog> auditLogs = new ArrayList<>();

Add the import:

import java.util.ArrayList;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/alfs/entities/Ticket.java` around lines 59 - 66,
The Ticket entity's `@OneToMany` fields (comments, attachments, auditLogs) should
be defensively initialized to avoid NullPointerException when accessed on
new/detached instances and to preserve child records you must ensure no
cascade/orphanRemoval is applied to attachments (and likewise no unintended
cascades added to comments/auditLogs); update the Ticket class by initializing
the fields comments, attachments, and auditLogs to empty List instances (e.g.,
new ArrayList<>()) and confirm there are no cascade or orphanRemoval attributes
on the attachments mapping so child records are not deleted with the Ticket.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/main/java/org/example/alfs/entities/Ticket.java`:
- Around line 59-66: The Ticket entity's `@OneToMany` fields (comments,
attachments, auditLogs) should be defensively initialized to avoid
NullPointerException when accessed on new/detached instances and to preserve
child records you must ensure no cascade/orphanRemoval is applied to attachments
(and likewise no unintended cascades added to comments/auditLogs); update the
Ticket class by initializing the fields comments, attachments, and auditLogs to
empty List instances (e.g., new ArrayList<>()) and confirm there are no cascade
or orphanRemoval attributes on the attachments mapping so child records are not
deleted with the Ticket.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0efbad94-c5a6-40e4-a0c0-e9045bd7f971

📥 Commits

Reviewing files that changed from the base of the PR and between f812a82 and 8b1a7a3.

📒 Files selected for processing (3)
  • src/main/java/org/example/alfs/entities/Ticket.java
  • src/main/java/org/example/alfs/entities/TicketComment.java
  • src/main/java/org/example/alfs/repositories/UserRepository.java
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/org/example/alfs/repositories/UserRepository.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/org/example/alfs/entities/TicketComment.java

@FionaSprinkles FionaSprinkles merged commit 51974a5 into main Apr 2, 2026
2 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Apr 2, 2026
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