Skip to content

Docs/readme#107

Merged
fmazmz merged 3 commits intomainfrom
docs/readme
Jan 13, 2026
Merged

Docs/readme#107
fmazmz merged 3 commits intomainfrom
docs/readme

Conversation

@fmazmz
Copy link
Copy Markdown
Member

@fmazmz fmazmz commented Jan 13, 2026

Summary by CodeRabbit

  • New Features

    • CLI application now features a structured multi-stage workflow including authentication, account configuration, and company setup before accessing the main menu.
    • Invoice management enhanced with improved item management capabilities.
  • Documentation

    • Installation instructions updated in README.
  • Style & Refactor

    • Code formatting and import organization improved throughout.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

The PR updates the project with documentation cleanup across all classes, import standardization from wildcards to explicit imports, formatting improvements to whitespace and generics, and significant structural enhancements. Key additions include Company association to Invoice with auditing fields and item management methods, a refactored CLI with explicit dependency injection and multi-stage initialization flow, and a new public accessor in JpaUtil.

Changes

Cohort / File(s) Summary
Main Application Setup
README.md, src/main/java/org/example/InvoiceManagementApplication.java
README Maven command updated to reference InvoiceManagementApplication; main method signature changed from public static to package-private static with Javadoc removed.
CLI Core Refactoring
src/main/java/org/example/cli/CliApp.java, CliContext.java, InputHelper.java, ServiceContainer.java, DisplayFormatter.java
CliApp receives new public constructor with complete component initialization and multi-stage flow (authentication → account setup → company setup → main menu). Wildcard menu imports replaced with explicit imports. Class-level documentation removed across files. DisplayFormatter comments and formatting cleaned.
CLI Menu Components
src/main/java/org/example/cli/menu/AccountMenu.java, AuthMenu.java, ClientMenu.java, CompanySettingsMenu.java, CompanySetupMenu.java, CompanyUserMenu.java, InvoiceItemMenu.java, InvoiceMenu.java, MainMenu.java
Javadoc comments removed across all menu classes. CompanySetupMenu and InvoiceMenu wildcard imports replaced with explicit imports. Minor formatting adjustments to switch case blocks. ClientMenu adds EntityNotFoundException handling for deletion failures.
Entity & DTO Structural Updates
src/main/java/org/example/entity/invoice/Invoice.java
Invoice entity enhanced with Company @ManyToOne association, createdAt/updatedAt auditing fields, and OneToMany invoiceItems bidirectional relationship. New public helper methods added: addItem(InvoiceItem), clearItems(), recalcTotals().
Entity & DTO Formatting
src/main/java/org/example/entity/.../*DTO.java, src/main/java/org/example/entity/client/ClientDTO.java, CreateClientDTO.java, UpdateClientDTO.java, CreateCompanyDTO.java, UpdateCompanyDTO.java, CreateInvoiceDTO.java, UpdateInvoiceDTO.java, CreateUserDTO.java, UserDTO.java
Whitespace normalization across DTOs and records: blank line removal, formatting of record declarations, space adjustments around parentheses and type parameters. CreateClientDTO and CreateInvoiceDTO wildcard imports replace explicit constraint imports.
Entity Field Formatting
src/main/java/org/example/entity/invoice/InvoiceItem.java, InvoiceItemDTO.java, src/main/java/org/example/entity/company/CompanyUser.java
Annotation formatting improvements and spacing adjustments around column definitions and constructors. No behavioral changes.
Repository Layer
src/main/java/org/example/repository/BaseRepository.java, CompanyRepository.java, InvoiceRepository.java
Generic syntax formatting: space removal in BaseRepository<T, ID> and Class<T>. Class declaration formatting in CompanyRepository. Method signature spacing in InvoiceRepository for findAllByClientId().
Service Layer
src/main/java/org/example/service/ClientService.java, InvoiceService.java, UserService.java, src/main/java/org/example/auth/AuthService.java
Import reordering and consolidation. InvoiceService adds explicit Slf4j import. No behavioral changes to service logic.
Utilities
src/main/java/org/example/util/JpaUtil.java, LogUtil.java
JpaUtil exposes new public method getEntityManagerFactory() for EntityManagerFactory access. LogUtil constructor formatting adjusted (one-line to multi-line empty block).
Test Files
src/test/java/org/example/service/AuthServiceTest.java, ClientServiceTest.java, CompanyUserServiceTest.java, InvoiceServiceTest.java, UserServiceTest.java
Import consolidation: wildcard imports replaced with explicit imports. ClientServiceTest consolidates Company field initialization. Test setup formatting improved with multi-line object creation. Package namespace adjusted in InvoiceServiceTest.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Refactor InvoiceService #36: Both PRs modify the same Invoice entity, introducing structural enhancements (fields like invoiceItems, auditing fields, and helper methods addItem/clearItems/recalcTotals) and DTO mapping adjustments.
  • Feature/company management #23: Related through Company-Invoice association work — this PR adds the Company @ManyToOne relationship to Invoice while that PR establishes the broader Company entity and repository infrastructure.
  • split CLI into smaller parts #105: Both PRs refactor the CLI by modifying the same core classes (CliApp, CliContext, InputHelper, ServiceContainer, and menu classes) to implement explicit dependency injection and structured component wiring.

Poem

🐰 A hop, skip, and a cleanup spree—
Docs removed, imports now precise and free!
Invoice meets Company in a dance so grand,
CLI stages aligned across the land. 🎭
Formatting gleams, the code stands tall, complete at last! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% 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 'Docs/readme' is vague and does not clearly convey what was actually changed in the pull request. Use a more descriptive title that summarizes the main changes, such as 'Update Maven exec command in README' or 'Refactor codebase with formatting and import improvements'.
✅ 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

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.

@fmazmz fmazmz merged commit 7eb704f into main Jan 13, 2026
1 of 2 checks passed
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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/org/example/cli/CliApp.java (1)

47-52: Recursive call to run() risks stack overflow.

When the account is deleted, the method calls itself recursively. If a user repeatedly creates accounts and deletes them, this leads to unbounded stack growth. Refactor to use a loop instead.

♻️ Suggested refactor using a loop
     public void run() {
+        mainLoop();
+        input.close();
+    }
+
+    private void mainLoop() {
         printBanner();
 
-        // Step 1: Authentication (with retry)
-        while (!authMenu.show()) {
-            System.out.println("\nWould you like to try again? (yes/no): ");
-            String retry = input.readLine().toLowerCase();
-            if (!"yes".equals(retry)) {
-                System.out.println("Exiting...");
+        while (true) {
+            // Step 1: Authentication (with retry)
+            while (!authMenu.show()) {
+                System.out.println("\nWould you like to try again? (yes/no): ");
+                String retry = input.readLine().toLowerCase();
+                if (!"yes".equals(retry)) {
+                    System.out.println("Exiting...");
+                    return;
+                }
+            }
+
+            // Step 2: Account setting
+            if (!accountMenu.show()) {
+                System.out.println("Account deleted. Returning to authentication...");
+                continue; // Loop back to authentication instead of recursion
+            }
+
+            // Step 3: Company setup (with retry)
+            while (!companySetupMenu.show()) {
+                System.out.println("\nWould you like to try again? (yes/no): ");
+                String retry = input.readLine().toLowerCase();
+                if (!"yes".equals(retry)) {
+                    System.out.println("Exiting...");
+                    return;
+                }
+            }
+
+            // Step 4: Main menu loop
+            mainMenu.show();
+            break; // Exit after main menu completes
+        }
+    }
-                return;
-            }
-        }
-
-        // Step 2: Account setting
-        if (!accountMenu.show()) {
-            System.out.println("Account deleted. Returning to authentication...");
-            run();
-            return;
-        }
-
-        // Step 3: Company setup (with retry)
-        while (!companySetupMenu.show()) {
-            System.out.println("\nWould you like to try again? (yes/no): ");
-            String retry = input.readLine().toLowerCase();
-            if (!"yes".equals(retry)) {
-                System.out.println("Exiting...");
-                return;
-            }
-        }
-
-        // Step 4: Main menu loop
-        mainMenu.show();
-
-        input.close();
-    }
🤖 Fix all issues with AI agents
In @README.md:
- Line 77: The README notes mvn exec:java will fail because
InvoiceManagementApplication's entry point is declared as static void
main(String[] args) without the public modifier; update the method signature in
the InvoiceManagementApplication class to public static void main(String[] args)
so the JVM can find the entry point and mvn exec:java succeeds.

In @src/main/java/org/example/entity/invoice/Invoice.java:
- Around line 106-115: In recalcTotals(), calling
item.getUnitPrice().multiply(...) can NPE if getUnitPrice() returns null; update
the stream in recalcTotals() to treat null unit prices as BigDecimal.ZERO (e.g.,
map each item to
Optional.ofNullable(item.getUnitPrice()).orElse(BigDecimal.ZERO).multiply(BigDecimal.valueOf(item.getQuantity())))
before reduce, ensuring invoiceItems, getQuantity, and vatRate handling remains
the same and preserve assignment to this.vatAmount and this.amount.

In @src/main/java/org/example/InvoiceManagementApplication.java:
- Around line 7-10: The main method in InvoiceManagementApplication is
package-private and must be made public so the JVM can find it; change the
signature of the main method to public static void main(String[] args) while
keeping the existing CliApp cliApp = new CliApp(); cliApp.run(); logic intact in
the InvoiceManagementApplication class.
🧹 Nitpick comments (7)
src/main/java/org/example/cli/ServiceContainer.java (1)

5-6: Consider replacing wildcard imports with explicit imports.

Wildcard imports can obscure dependencies and may cause conflicts. Given this PR's stated goal of import standardization, consider making these explicit.

♻️ Suggested explicit imports
-import org.example.repository.*;
-import org.example.service.*;
+import org.example.repository.ClientRepository;
+import org.example.repository.CompanyRepository;
+import org.example.repository.CompanyUserRepository;
+import org.example.repository.InvoiceRepository;
+import org.example.repository.UserRepository;
+import org.example.service.ClientService;
+import org.example.service.CompanyService;
+import org.example.service.CompanyUserService;
+import org.example.service.InvoiceService;
+import org.example.service.UserService;
src/main/java/org/example/entity/client/CreateClientDTO.java (1)

3-3: Wildcard import contradicts stated PR objectives.

The AI summary and PR objectives mention "import standardization from wildcards to explicit imports," but this file does the opposite—changing explicit imports to a wildcard import. Consider using explicit imports for consistency with the stated goal and to make dependencies clearer.

Suggested explicit imports
-import jakarta.validation.constraints.*;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
src/test/java/org/example/service/CompanyUserServiceTest.java (1)

3-27: LGTM with optional nit.

The switch to explicit imports is consistent with the PR's stated goal. One remaining wildcard import at line 27 (static org.mockito.Mockito.*) could be made explicit for full consistency, but this is optional.

src/main/java/org/example/entity/invoice/CreateInvoiceDTO.java (1)

4-4: Wildcard import contradicts PR's import standardization direction.

The AI summary indicates this PR aims to replace wildcard imports with explicit imports across the codebase. However, this file introduces a wildcard import jakarta.validation.constraints.* instead of using explicit imports for NotNull, NotBlank, NotEmpty, DecimalMin, and DecimalMax.

Consider using explicit imports for consistency with the rest of the PR:

Suggested explicit imports
-import jakarta.validation.constraints.*;
+import jakarta.validation.constraints.DecimalMax;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
src/main/java/org/example/entity/invoice/Invoice.java (2)

23-23: Reconsider @EqualsAndHashCode on a JPA entity with collections.

Using Lombok's @EqualsAndHashCode on a JPA entity that contains lazy-loaded collections (invoiceItems) can cause issues:

  • Triggering unexpected lazy loading when comparing entities outside a session.
  • Potential infinite loops or stack overflow in bidirectional relationships.
  • Inconsistent behavior before and after entity persistence (ID is null before persist).

Consider excluding the collections and using only the business key or ID:

♻️ Suggested fix
-@EqualsAndHashCode
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
 public class Invoice {
 
     @Id
     @GeneratedValue(strategy = GenerationType.UUID)
+    @EqualsAndHashCode.Include
     private UUID id;

Alternatively, exclude the collection:

@EqualsAndHashCode(exclude = {"invoiceItems"})

95-99: Performance: redundant recalcTotals() calls during bulk item addition.

addItem() calls recalcTotals() after each item, but fromDTO() (line 91) and InvoiceService.updateInvoice() also call recalcTotals() after the loop. This results in N+1 recalculations for N items (O(N²) operations on the item list).

Consider removing recalcTotals() from addItem() and relying on explicit calls after bulk additions:

♻️ Suggested fix
 public void addItem(InvoiceItem item) {
     invoiceItems.add(item);
     item.setInvoice(this);
-    recalcTotals();
 }
src/main/java/org/example/service/InvoiceService.java (1)

69-82: Note: recalcTotals() at line 81 is redundant if addItem() already calls it.

If the suggestion to remove recalcTotals() from addItem() in Invoice.java is accepted, this explicit call becomes necessary. Otherwise, it's currently redundant but harmless.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b382893 and 4196aa7.

📒 Files selected for processing (43)
  • README.md
  • src/main/java/org/example/InvoiceManagementApplication.java
  • src/main/java/org/example/auth/AuthService.java
  • src/main/java/org/example/cli/CliApp.java
  • src/main/java/org/example/cli/CliContext.java
  • src/main/java/org/example/cli/DisplayFormatter.java
  • src/main/java/org/example/cli/InputHelper.java
  • src/main/java/org/example/cli/ServiceContainer.java
  • src/main/java/org/example/cli/menu/AccountMenu.java
  • src/main/java/org/example/cli/menu/AuthMenu.java
  • src/main/java/org/example/cli/menu/ClientMenu.java
  • src/main/java/org/example/cli/menu/CompanySettingsMenu.java
  • src/main/java/org/example/cli/menu/CompanySetupMenu.java
  • src/main/java/org/example/cli/menu/CompanyUserMenu.java
  • src/main/java/org/example/cli/menu/InvoiceItemMenu.java
  • src/main/java/org/example/cli/menu/InvoiceMenu.java
  • src/main/java/org/example/cli/menu/MainMenu.java
  • src/main/java/org/example/entity/client/ClientDTO.java
  • src/main/java/org/example/entity/client/CreateClientDTO.java
  • src/main/java/org/example/entity/client/UpdateClientDTO.java
  • src/main/java/org/example/entity/company/CompanyUser.java
  • src/main/java/org/example/entity/company/CreateCompanyDTO.java
  • src/main/java/org/example/entity/company/UpdateCompanyDTO.java
  • src/main/java/org/example/entity/invoice/CreateInvoiceDTO.java
  • src/main/java/org/example/entity/invoice/Invoice.java
  • src/main/java/org/example/entity/invoice/InvoiceItem.java
  • src/main/java/org/example/entity/invoice/InvoiceItemDTO.java
  • src/main/java/org/example/entity/invoice/UpdateInvoiceDTO.java
  • src/main/java/org/example/entity/user/CreateUserDTO.java
  • src/main/java/org/example/entity/user/UserDTO.java
  • src/main/java/org/example/repository/BaseRepository.java
  • src/main/java/org/example/repository/CompanyRepository.java
  • src/main/java/org/example/repository/InvoiceRepository.java
  • src/main/java/org/example/service/ClientService.java
  • src/main/java/org/example/service/InvoiceService.java
  • src/main/java/org/example/service/UserService.java
  • src/main/java/org/example/util/JpaUtil.java
  • src/main/java/org/example/util/LogUtil.java
  • src/test/java/org/example/service/AuthServiceTest.java
  • src/test/java/org/example/service/ClientServiceTest.java
  • src/test/java/org/example/service/CompanyUserServiceTest.java
  • src/test/java/org/example/service/InvoiceServiceTest.java
  • src/test/java/org/example/service/UserServiceTest.java
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/org/example/cli/menu/CompanySetupMenu.java (3)
src/main/java/org/example/exception/BusinessRuleException.java (1)
  • BusinessRuleException (3-11)
src/main/java/org/example/exception/EntityNotFoundException.java (1)
  • EntityNotFoundException (3-11)
src/main/java/org/example/exception/ValidationException.java (1)
  • ValidationException (3-11)
src/main/java/org/example/service/InvoiceService.java (4)
src/main/java/org/example/auth/AuthService.java (1)
  • Slf4j (12-44)
src/main/java/org/example/service/UserService.java (1)
  • Slf4j (20-73)
src/main/java/org/example/service/CompanyService.java (1)
  • Slf4j (15-114)
src/main/java/org/example/service/CompanyUserService.java (1)
  • Slf4j (18-126)
src/main/java/org/example/cli/CliApp.java (4)
src/main/java/org/example/cli/menu/AccountMenu.java (1)
  • AccountMenu (9-60)
src/main/java/org/example/cli/menu/AuthMenu.java (1)
  • AuthMenu (13-84)
src/main/java/org/example/cli/menu/CompanySetupMenu.java (1)
  • CompanySetupMenu (17-156)
src/main/java/org/example/cli/menu/MainMenu.java (1)
  • MainMenu (8-76)
🔇 Additional comments (43)
src/main/java/org/example/util/LogUtil.java (1)

5-6: LGTM!

Pure formatting change to the private constructor. The utility class pattern remains correctly implemented with final class and private constructor.

src/main/java/org/example/cli/menu/InvoiceItemMenu.java (1)

51-53: LGTM! Formatting change has no functional impact.

The switch case now uses block syntax, which is functionally equivalent to the arrow expression form. This is a valid stylistic choice with no behavioral change.

src/main/java/org/example/cli/menu/AuthMenu.java (1)

12-12: LGTM!

Documentation cleanup acknowledged. The authentication logic with proper exception handling for AuthenticationException, ValidationException, and BusinessRuleException remains intact.

src/main/java/org/example/cli/menu/MainMenu.java (1)

7-7: LGTM!

Documentation cleanup acknowledged. The main menu logic with company selection safety checks and sub-menu orchestration remains unchanged.

src/main/java/org/example/cli/CliContext.java (1)

8-8: LGTM!

Documentation cleanup acknowledged. The session state management with synchronized user/company ID handling is well-structured.

src/main/java/org/example/cli/ServiceContainer.java (1)

9-9: LGTM!

Documentation cleanup acknowledged. The service container wiring with JPA-backed repositories and services is well-organized.

src/main/java/org/example/entity/user/UserDTO.java (1)

19-19: LGTM!

Formatting improvement acknowledged. Removing the space between method name and parenthesis aligns with standard Java conventions.

src/main/java/org/example/service/UserService.java (1)

8-8: LGTM! Import ordering improved.

The import reordering enhances consistency and readability with no functional impact.

src/test/java/org/example/service/UserServiceTest.java (1)

5-5: LGTM! Import ordering aligned with production code.

The import reordering matches the changes in UserService.java and maintains consistency.

src/main/java/org/example/cli/menu/CompanyUserMenu.java (1)

15-48: LGTM - Formatting cleanup.

The Javadoc removal and switch case block formatting are consistent with the broader documentation cleanup effort in this PR. No functional changes.

src/main/java/org/example/entity/client/UpdateClientDTO.java (1)

10-36: LGTM - Whitespace formatting.

The added blank lines between record fields improve visual separation. Validation annotations and field declarations remain unchanged.

src/main/java/org/example/cli/menu/CompanySettingsMenu.java (1)

10-45: LGTM - Formatting cleanup.

Javadoc removal and switch case block formatting are consistent with the cleanup pattern applied across other menu classes in this PR.

src/main/java/org/example/auth/AuthService.java (1)

4-5: LGTM - Import ordering.

Reordering UserDTO after User maintains alphabetical order within the org.example.entity.user package imports.

src/main/java/org/example/cli/InputHelper.java (1)

5-6: LGTM - Javadoc removal.

Documentation cleanup consistent with the broader PR pattern. All method signatures and behavior remain unchanged.

src/main/java/org/example/entity/user/CreateUserDTO.java (1)

7-24: LGTM - Whitespace formatting.

Blank lines between record fields improve readability. Validation constraints remain intact.

src/main/java/org/example/entity/invoice/InvoiceItemDTO.java (1)

13-24: LGTM - Whitespace formatting.

Consistent with the formatting pattern applied to other DTO records in this PR. Validation annotations and the fromEntity factory method are unchanged.

src/main/java/org/example/cli/DisplayFormatter.java (1)

15-270: LGTM!

Formatting and whitespace adjustments look good. No functional changes to the display utility methods.

src/main/java/org/example/entity/company/CompanyUser.java (1)

31-38: LGTM!

Formatting adjustments in the constructor are fine. The null-check validation logic for composite key creation remains correct.

src/main/java/org/example/cli/menu/AccountMenu.java (1)

8-62: LGTM!

Whitespace adjustments are fine. The account menu flow with confirmation for destructive actions is well-implemented.

src/main/java/org/example/util/JpaUtil.java (1)

25-27: No action required. The getEntityManagerFactory() method is used appropriately in the codebase. All EntityManager instances created from the factory are properly managed with either explicit close() calls in try-finally blocks or try-with-resources statements. The method is needed for repositories to function and for legitimate utility access via getPersistenceUnitUtil(). No resource leaks or unmanaged entity manager creation patterns are present.

Likely an incorrect or invalid review comment.

src/test/java/org/example/service/AuthServiceTest.java (1)

5-5: LGTM! Import cleanup improves clarity.

Replacing wildcard static imports with explicit imports and reordering the UserDTO import aligns with best practices for readability and maintainability.

Also applies to: 14-17

src/main/java/org/example/entity/client/ClientDTO.java (1)

9-9: LGTM! Formatting aligns with Java conventions.

Removing the space between the record name and opening parenthesis follows standard Java style.

Also applies to: 22-22

src/main/java/org/example/service/ClientService.java (1)

4-4: LGTM! Import reordering is consistent with broader cleanup.

The import repositioning maintains the same dependencies while improving organization.

Also applies to: 7-7

src/main/java/org/example/entity/invoice/InvoiceItem.java (1)

30-30: LGTM! Annotation formatting is now consistent.

Normalizing whitespace in @Column annotations improves readability without affecting JPA behavior.

Also applies to: 33-33

src/main/java/org/example/entity/invoice/CreateInvoiceDTO.java (1)

11-33: LGTM! Record formatting improves readability.

The added blank lines between annotated fields and the proper record body formatting enhance code clarity.

src/main/java/org/example/cli/menu/InvoiceMenu.java (2)

8-11: LGTM on explicit imports.

Replacing wildcard imports with explicit imports improves code clarity and avoids potential namespace conflicts.


60-62: Minor formatting change looks fine.

Adding braces around the single return statement in case 6 is a stylistic choice that improves consistency. Functionally equivalent to the previous version.

src/test/java/org/example/service/ClientServiceTest.java (1)

23-23: Field-level initialization looks acceptable for this test class.

Initializing the Company fixture at field level with final is reasonable here since the tests don't appear to mutate the Company instance itself—they only pass it to mocks and builders. This consolidates the fixture initialization.

If future tests need to modify Company state, consider moving initialization to @BeforeEach to ensure test isolation.

src/main/java/org/example/cli/menu/ClientMenu.java (2)

44-46: Consistent formatting with other menu classes.

The block style for the return case matches the pattern used in InvoiceMenu and other menu classes in this PR.


153-163: Good additions to deleteClient error handling.

The added EntityNotFoundException catch block (lines 158-159) and the else branch with "Deletion cancelled." message (lines 161-162) improve error reporting and user feedback. These are solid UX improvements.

src/main/java/org/example/repository/BaseRepository.java (1)

9-11: LGTM on formatting standardization.

Removing the extraneous spaces before generic type parameters (BaseRepository<T, ID> and Class<T>) follows standard Java conventions.

src/main/java/org/example/repository/CompanyRepository.java (1)

8-8: LGTM on formatting fix.

Adding the standard space before the opening brace aligns with Java code style conventions.

src/main/java/org/example/entity/invoice/Invoice.java (1)

30-32: LGTM!

The structural additions are well-implemented:

  • Company association with proper JoinColumn configuration.
  • Auditing fields using Hibernate's @CreationTimestamp and @UpdateTimestamp.
  • Bidirectional one-to-many with cascade and orphanRemoval for proper aggregate management.
  • fromDTO factory method with VAT rate validation.

Also applies to: 52-59, 64-93

src/main/java/org/example/entity/invoice/UpdateInvoiceDTO.java (1)

13-28: LGTM!

Formatting-only changes that improve readability of the record definition.

src/main/java/org/example/service/InvoiceService.java (1)

3-3: LGTM!

The @Slf4j annotation provides clean logging consistent with other services in the codebase (AuthService, UserService, CompanyService).

Also applies to: 18-18

src/test/java/org/example/service/InvoiceServiceTest.java (1)

1-1: LGTM!

Formatting and namespace changes align the test class properly. Test coverage remains comprehensive with both success and failure scenarios.

Also applies to: 53-56, 227-232

src/main/java/org/example/repository/InvoiceRepository.java (1)

11-11: LGTM!

Formatting adjustments only. The repository methods properly use LEFT JOIN FETCH to eagerly load invoice items and avoid N+1 query issues.

Also applies to: 46-64

src/main/java/org/example/entity/company/CreateCompanyDTO.java (1)

8-35: LGTM!

Formatting changes look good. The record structure with validation annotations is well-defined and the blank lines improve readability between annotated fields.

src/main/java/org/example/cli/menu/CompanySetupMenu.java (1)

6-9: LGTM!

Replacing wildcard imports with explicit imports improves code clarity and makes dependencies visible at a glance.

src/main/java/org/example/entity/company/UpdateCompanyDTO.java (1)

10-34: LGTM!

Formatting is consistent with the changes in CreateCompanyDTO.java. The record structure and validation annotations remain correct.

src/main/java/org/example/cli/CliApp.java (3)

3-6: LGTM!

Explicit imports improve code readability and make the menu dependencies clear.


22-32: LGTM!

Clean dependency injection pattern with explicit initialization of context, input, services, and all menu components in the constructor.


70-79: LGTM!

Banner formatting looks good.

Comment thread README.md
cd project-jpa-grupp-3-d
mvn clean compile
mvn exec:java -Dexec.mainClass="org.example.App"
mvn exec:java -Dexec.mainClass="org.example.InvoiceManagementApplication"
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the main method signature in InvoiceManagementApplication.java

# First, check if the file exists and locate it
find . -name "InvoiceManagementApplication.java" -type f

# Search for the main method declaration with context
rg -n --type=java -B 1 -A 3 'static\s+void\s+main' --max-count=5

Repository: ithsjava25/project-jpa-grupp-3-d

Length of output: 596


Add public modifier to the main method.

The main method in InvoiceManagementApplication.java is currently static void main(String[] args), missing the public modifier required for entry points. The documented mvn exec:java command in the README will fail at runtime without it. Change to public static void main(String[] args).

🤖 Prompt for AI Agents
In @README.md at line 77, The README notes mvn exec:java will fail because
InvoiceManagementApplication's entry point is declared as static void
main(String[] args) without the public modifier; update the method signature in
the InvoiceManagementApplication class to public static void main(String[] args)
so the JVM can find the entry point and mvn exec:java succeeds.

Comment on lines +106 to +115
public void recalcTotals() {
BigDecimal subTotal = invoiceItems.stream()
.map(item -> item.getUnitPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);

BigDecimal vat = (vatRate != null ? vatRate : BigDecimal.ZERO)
.multiply(subTotal);
this.vatAmount = vat;
this.amount = subTotal.add(vat);
}
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 | 🟡 Minor

Potential NullPointerException if unitPrice is null.

At line 108, item.getUnitPrice().multiply(...) will throw NPE if any item has a null unitPrice. Consider adding null-safety:

🐛 Suggested fix
 public void recalcTotals() {
     BigDecimal subTotal = invoiceItems.stream()
-        .map(item -> item.getUnitPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
+        .map(item -> {
+            BigDecimal price = item.getUnitPrice() != null ? item.getUnitPrice() : BigDecimal.ZERO;
+            return price.multiply(BigDecimal.valueOf(item.getQuantity()));
+        })
         .reduce(BigDecimal.ZERO, BigDecimal::add);
🤖 Prompt for AI Agents
In @src/main/java/org/example/entity/invoice/Invoice.java around lines 106 -
115, In recalcTotals(), calling item.getUnitPrice().multiply(...) can NPE if
getUnitPrice() returns null; update the stream in recalcTotals() to treat null
unit prices as BigDecimal.ZERO (e.g., map each item to
Optional.ofNullable(item.getUnitPrice()).orElse(BigDecimal.ZERO).multiply(BigDecimal.valueOf(item.getQuantity())))
before reduce, ensuring invoiceItems, getQuantity, and vatRate handling remains
the same and preserve assignment to this.vatAmount and this.amount.

Comment on lines +7 to 10
static void main(String[] args) {
CliApp cliApp = new CliApp();
cliApp.run();
}
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 | 🔴 Critical

Critical: Package-private main method breaks application startup.

The main method must be public for the JVM to recognize it as the application entry point. Without the public modifier, running this class will fail with Error: Main method not found in class org.example.InvoiceManagementApplication.

Proposed fix
-    static void main(String[] args) {
+    public static void main(String[] args) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static void main(String[] args) {
CliApp cliApp = new CliApp();
cliApp.run();
}
public static void main(String[] args) {
CliApp cliApp = new CliApp();
cliApp.run();
}
🤖 Prompt for AI Agents
In @src/main/java/org/example/InvoiceManagementApplication.java around lines 7 -
10, The main method in InvoiceManagementApplication is package-private and must
be made public so the JVM can find it; change the signature of the main method
to public static void main(String[] args) while keeping the existing CliApp
cliApp = new CliApp(); cliApp.run(); logic intact in the
InvoiceManagementApplication class.

@fmazmz fmazmz deleted the docs/readme branch January 13, 2026 13:47
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.

1 participant