Skip to content

Added Domain Entities & Implemented Address APIs#4

Merged
blebelo merged 5 commits into
mainfrom
benny/Entities
Dec 15, 2025
Merged

Added Domain Entities & Implemented Address APIs#4
blebelo merged 5 commits into
mainfrom
benny/Entities

Conversation

@blebelo
Copy link
Copy Markdown
Owner

@blebelo blebelo commented Dec 15, 2025

Summary by CodeRabbit

  • New Features
    • Student profile and enrollment system with personal information and document storage
    • Short course catalog with program management and capacity tracking
    • Course application processing system with status tracking and decision management
    • Redesigned landing page featuring program offerings and enhanced navigation

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

@blebelo blebelo self-assigned this Dec 15, 2025
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Dec 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
moipone Ready Ready Preview, Comment Dec 15, 2025 11:48pm

@blebelo blebelo temporarily deployed to benny/Entities - Moipone PS API PR #4 December 15, 2025 22:42 — with Render Destroyed
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 15, 2025

Walkthrough

This pull request introduces a comprehensive domain model for managing student enrollment in short courses. It adds four new domain entities—Address, Student, ShortCourse, and CourseApplication—along with corresponding application services, DTOs, and database migrations. It also refactors document storage by moving document fields from CourseApplication to Student, and redesigns the landing page with richer content sections.

Changes

Cohort / File(s) Summary
Address Entity & Application Layer
aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs, aspnet-core/src/Moipone.PublicSite.Application/Addresses/Dto/AddressDto.cs, aspnet-core/src/Moipone.PublicSite.Application/Addresses/IAddressAppService.cs, aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs
New Address domain entity with Street, Suburb, City, PostalCode properties. Includes DTO with AutoMap configuration, service interface, and full CRUD application service with validation and error handling.
Student Entity & Application Layer
aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs, aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/RefListGender.cs, aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs, aspnet-core/src/Moipone.PublicSite.Application/Students/IStudentAppService.cs, aspnet-core/src/Moipone.PublicSite.Application/Students/StudentAppService.cs
Extended Student entity with 13 new properties (Name, Surname, Age, Gender, EmailAddress, IdNumber, DateOfBirth, PhoneNumber, ResidentialAddress, and document URLs). Includes gender enum with four options, corresponding DTO, service interface with custom GetStudentByEmailAsync method, and CRUD service (stub implementations).
ShortCourse Entity
aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs
New ShortCourse domain entity with properties for Title, Description, Capacity, Requirements, Code (with regex validation), IsActive flag, StartDate, Duration. Includes unique index on Code and navigation properties for enrolled students and course applications.
CourseApplication Entity & Enum
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs, aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/RefListApplicationStatus.cs
New CourseApplication entity linking Students to ShortCourses with application Status (Pending, Approved, Declined enum), DecisionReason, and DecisionDate. Includes composite unique index on StudentId and ShortCourseId, and display-annotated status enum.
Database Configuration & Migrations
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/EntityFrameworkCore/PublicSiteDbContext.cs, aspnet-core/src/Moipone.PublicSite.Core/Moipone.PublicSite.Core.csproj, aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215223124_Added_Entities.cs, aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215223124_Added_Entities.Designer.cs, aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215234558_Refactored_Documents.cs, aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215234558_Refactored_Documents.Designer.cs, aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs
DbContext updated with four new DbSet properties (Addresses, Students, ShortCourses, CourseApplications). Two sequential migrations: first creates the four new tables with audit fields, foreign keys, and indices; second refactors by moving document fields (CertifiedId, ProofOfResidence, CurriculumVitae, CertifiedHighestQualification) from CourseApplications to Students and makes ResidentialAddressId nullable. Includes comprehensive designer files and updated model snapshot.
Frontend Update
next-ts/app/page.tsx
Landing page redesigned from minimal layout to multi-section content-rich design. Adds hero section with background image and overlay, About Us section, Our Programmes grid (3 program cards), Call to Action section, and Footer. Introduces Next.js Link for internal navigation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • Student entity validation: Multiple regex patterns and validation attributes applied to new properties (Name, Surname, PhoneNumber, IdNumber); verify regex patterns match intended formats and error messages are clear
  • AddressAppService implementation: Check error handling in CreateAsync, GetAsync, UpdateAsync, and DeleteAsync methods; validate that ObjectMapper correctly maps Address ↔ AddressDto and that not-found cases are handled consistently
  • CourseApplication relationships: Verify composite unique index on (StudentId, ShortCourseId) is correctly enforced; check cascade delete behavior on foreign keys
  • Migration sequence (Added_Entities → Refactored_Documents): Carefully review the second migration's data movement logic—ensure document field migration from CourseApplications to Students maintains referential integrity and that nullable ResidentialAddressId change doesn't break existing constraints
  • Navigation properties: Confirm bidirectional relationships between Student↔Address, Student↔ShortCourse, and CourseApplication↔Student/ShortCourse are correctly initialized and won't cause circular reference issues

Poem

🐰 New entities hop into place so neat,
With students, courses, and addresses complete!
From addresses to applications they flow,
A migration dance, in rhythm they go.
The landing page shines with content so bright—
CodeRabbit hops on, everything's right! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.17% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: addition of domain entities (Address, Student, ShortCourse, CourseApplication, RefListApplicationStatus, RefListGender) and implementation of Address APIs through AddressAppService and IAddressAppService.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch benny/Entities

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

Copy link
Copy Markdown
Contributor

@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: 20

🧹 Nitpick comments (12)
aspnet-core/src/Moipone.PublicSite.Core/Moipone.PublicSite.Core.csproj (1)

1-1: Consider removing the Byte Order Mark (BOM).

The file now has a UTF-8 BOM character before the opening <Project> tag. While this is generally benign in .csproj files, it can cause issues with certain text processing tools, version control systems, or cross-platform consistency. Most .NET projects use UTF-8 without BOM for consistency.

If this was added unintentionally (e.g., due to your editor's default settings), consider removing it to maintain consistency with standard conventions.

aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1)

16-16: Consider adding a foreign key property for ResidentialAddress.

While EF Core can infer shadow foreign keys, explicitly declaring public Guid? ResidentialAddressId { get; set; } improves clarity and allows you to manage the relationship without loading the entire Address entity.

     public string PhoneNumber { get; set; }
+    public Guid? ResidentialAddressId { get; set; }
     public Address ResidentialAddress { get; set; }
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1)

9-10: Consider adding foreign key properties for navigation properties.

Explicitly declaring foreign key properties (StudentId, ShortCourseId) improves clarity and allows relationship management without loading entire entities.

     public class CourseApplication : FullAuditedEntity<Guid>
     {
+        public Guid StudentId { get; set; }
         public Student Student { get; set; }
+        
+        public Guid ShortCourseId { get; set; }
         public ShortCourse ShortCourse { get; set; }
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215223124_Added_Entities.cs (2)

74-77: Consider external storage for document files.

Storing documents (CertifiedId, ProofOfResidence, CurriculumVitae, CertifiedHighestQualification) as bytea directly in the database can bloat table size and degrade query performance. For production systems, consider storing files in blob storage (Azure Blob, S3, etc.) and keeping only file references/URLs in the database.


67-72: Consider adding length constraints to key string columns.

Critical fields like EmailAddress, PhoneNumber, Title, and Code have no maximum length. While PostgreSQL handles text efficiently, adding constraints (e.g., .HasMaxLength(256) for email) helps with data validation and prevents unbounded input.

Also applies to: 41-45

aspnet-core/src/Moipone.PublicSite.Application/Students/StudentAppService.cs (2)

23-51: All methods are unimplemented stubs.

Every method throws NotImplementedException. If this PR is meant to add the APIs (per PR title "Implemented Address APIs"), ensure the implementations are completed before merging, or track these as TODOs for a follow-up.

Would you like me to help implement these methods, or should I open an issue to track the remaining work?


1-9: Remove unused imports.

Abp.UI and Microsoft.EntityFrameworkCore are imported but not used in the current implementation.

 using Abp.Application.Services.Dto;
 using Abp.Domain.Repositories;
-using Abp.UI;
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
 using Moipone.PublicSite.Domain.Students;
 using Moipone.PublicSite.Students.Dto;
aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)

22-27: Reconsider byte[] for document transfer.

Transferring documents as byte[] in DTOs results in large JSON payloads (base64 encoded). Consider:

  1. Separate upload/download endpoints returning file streams
  2. Store file references (URLs) instead of raw bytes
  3. Use multipart form data for uploads

This aligns with the earlier suggestion to use external blob storage.

aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (3)

15-21: Redundant repository field storage.

The base class AsyncCrudAppService already exposes the injected repository via the Repository property. Storing it again in _addressRepository is unnecessary.

Apply this diff to remove the redundant field:

-    private readonly IRepository<Address, Guid> _addressRepository;
-
     public AddressAppService(IRepository<Address, Guid> addressRepository)
         : base(addressRepository)
     {
-        _addressRepository = addressRepository;
     }

Then replace all occurrences of _addressRepository with Repository throughout the file.


23-45: Consider whether this override is necessary.

The base class AsyncCrudAppService already provides a CreateAsync implementation with mapping, validation, and error handling. Unless you need custom validation logic beyond null checks, this override may be redundant.

If no custom logic is required, remove this override and rely on the base implementation. If custom validation is needed, consider using a more specific exception message rather than exposing the technical exception details on line 43.


127-154: Consider removing redundant existence check.

If IRepository.GetAsync() throws an exception when the entity is not found (standard ABP behavior), the fetch on line 136 is redundant. The DeleteAsync method can be simplified to just call DeleteAsync(input.Id) directly, and the framework will handle non-existent entities appropriately.

If exception-on-not-found is confirmed, simplify to:

     public async override Task DeleteAsync(EntityDto<Guid> input)
     {
         try
         {
             if (input == null || input.Id == Guid.Empty)
             {
                 throw new UserFriendlyException("Invalid address ID.", Abp.Logging.LogSeverity.Warn);
             }

-            var address = await _addressRepository.GetAsync(input.Id);
-
-            if (address == null)
-            {
-                throw new UserFriendlyException($"Address with ID {input.Id} not found.", Abp.Logging.LogSeverity.Warn);
-            }
-
             await _addressRepository.DeleteAsync(input.Id);
         }
         catch (UserFriendlyException)
         {
             throw;
         }
         catch (Exception ex)
         {
             Logger.Error($"Error deleting address with ID {input?.Id}", ex);
             throw new UserFriendlyException($"Could not delete Address. Error: {ex.Message}", Abp.Logging.LogSeverity.Error);
         }
     }
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (1)

2046-2059: Review data model relationships for clarity.

The relationship structure shows:

  1. Student has a ShortCourseId FK linked to ShortCourse.EnrolledStudents (line 2109-2111)
  2. CourseApplication has both StudentId and ShortCourseId FKs (lines 2048-2054)
  3. ShortCourse has two separate collections: Applications and EnrolledStudents (lines 2216-2218)

This suggests students can be both "enrolled" (direct relationship) and have "applications" (through CourseApplication). Verify this is the intended design and not redundant modeling. If a student should only be enrolled after application approval, consider removing the direct Student.ShortCourseId relationship.

Verify the intended domain logic:

#!/bin/bash
# Check how Student and CourseApplication are related in the domain
ast-grep --pattern 'class Student {
  $$$
  ShortCourseId
  $$$
}'

# Check if there's documentation about enrollment vs application
rg -nP --type=cs 'EnrolledStudents|Applications' -B 2 -A 2

Also applies to: 2103-2114, 2214-2219

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5511b53 and 7baee0b.

📒 Files selected for processing (16)
  • aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Addresses/Dto/AddressDto.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Addresses/IAddressAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/IStudentAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/StudentAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/RefListApplicationStatus.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Moipone.PublicSite.Core.csproj (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/EntityFrameworkCore/PublicSiteDbContext.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215223124_Added_Entities.Designer.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215223124_Added_Entities.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (5 hunks)
🔇 Additional comments (5)
aspnet-core/src/Moipone.PublicSite.Core/Moipone.PublicSite.Core.csproj (1)

1-22: Note: Limited review scope.

Only the .csproj file is provided for review. The PR summary indicates significant domain model changes (Address, ShortCourse, CourseApplication entities), DTOs, application services, and EF Core integration. I cannot verify these implementations or assess their correctness without reviewing the actual domain files, EF Core mappings, and migrations. Please ensure these files are reviewed separately for correctness, design patterns, and adherence to your domain-driven design approach.

aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/RefListApplicationStatus.cs (1)

1-16: LGTM! Well-structured enum with descriptive Display attributes.

The enum provides clear application states with helpful descriptions for UI rendering.

aspnet-core/src/Moipone.PublicSite.Application/Addresses/IAddressAppService.cs (1)

7-9: LGTM! Standard CRUD interface for Address entities.

The empty interface body is appropriate when only standard CRUD operations are needed. ABP's IAsyncCrudAppService provides Create, Read, Update, and Delete operations out of the box.

aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215223124_Added_Entities.Designer.cs (1)

1-2: Auto-generated migration designer file - no manual changes needed.

This file is auto-generated by EF Core tooling and shouldn't be manually modified. It correctly captures the model state for the migration.

aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (1)

62-89: Verify null check behavior.

In ABP Framework, IRepository.GetAsync() typically throws an EntityNotFoundException when the entity is not found rather than returning null. The null check on lines 73-76 may be unreachable code.

Please verify the behavior of IRepository<Address, Guid>.GetAsync() in your version of ABP Framework. If it throws an exception on not found, remove the null check. Otherwise, the current implementation is fine.

Comment thread aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs Outdated
Comment thread aspnet-core/src/Moipone.PublicSite.Application/Students/IStudentAppService.cs Outdated
Copy link
Copy Markdown
Contributor

@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: 9

♻️ Duplicate comments (1)
aspnet-core/src/Moipone.PublicSite.Application/Students/StudentAppService.cs (1)

13-20: This issue was previously flagged and remains unresolved.

The service still doesn't inherit from ABP's ApplicationService or AsyncCrudAppService<...>, which means you're missing automatic unit of work management, authorization integration, object mapping, and other ABP features. Please address the previous review comment about adding base class inheritance.

🧹 Nitpick comments (4)
aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)

16-16: Consider using RefListGender enum type for consistency.

The Student entity uses RefListGender enum, but the DTO uses string. While AutoMapper handles this, using the enum type provides better type safety and IntelliSense support.

+using Moipone.PublicSite.Domain.Students;
 // ...
-        public string Gender { get; set; }
+        public RefListGender Gender { get; set; }
aspnet-core/src/Moipone.PublicSite.Application/Students/StudentAppService.cs (1)

22-50: Stub implementations detected.

All methods currently throw NotImplementedException. Once you inherit from AsyncCrudAppService<Student, StudentDto, Guid>, many of these methods will be auto-implemented, and you'll only need to override methods that require custom logic (like GetStudentByEmailAsync).

aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (1)

11-12: Remove unused static imports.

These static imports are not used anywhere in the file and should be removed to keep the code clean.

Apply this diff:

-using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
-using static System.Collections.Specialized.BitVector32;
aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (1)

18-45: Strong validation attributes applied.

Comprehensive validation constraints on all core properties. The regex for Code enforces uppercase alphanumeric format with hyphens.

Optional enhancement: Consider adding domain validation for StartDate and Duration:

  • Ensure StartDate is in the future for new courses
  • Ensure Duration is positive

This could be implemented via IValidatableObject or a domain validation method called from factory methods/constructors.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7baee0b and afbcb8b.

📒 Files selected for processing (11)
  • aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/IStudentAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/StudentAppService.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/RefListApplicationStatus.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/RefListGender.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1 hunks)
  • next-ts/app/page.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs
🧰 Additional context used
🧬 Code graph analysis (3)
aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)
aspnet-core/src/Moipone.PublicSite.Application/Addresses/Dto/AddressDto.cs (1)
  • AutoMap (8-15)
aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (1)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs (1)
  • Address (7-24)
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (2)
aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (1)
  • Table (12-55)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1)
  • Table (10-54)
🪛 GitHub Actions: CI/CD Pipeline
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs

[warning] 33-33: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

🪛 GitHub Check: Build Stage
aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs

[warning] 72-72:
Missing XML comment for publicly visible type or member 'AddressAppService.GetAsync(EntityDto)'


[warning] 50-50:
Missing XML comment for publicly visible type or member 'AddressAppService.GetAllAsync(PagedAndSortedResultRequestDto)'


[warning] 26-26:
Missing XML comment for publicly visible type or member 'AddressAppService.CreateAsync(AddressDto)'


[warning] 20-20:
Missing XML comment for publicly visible type or member 'AddressAppService.AddressAppService(IRepository<Address, Guid>)'


[warning] 16-16:
Missing XML comment for publicly visible type or member 'AddressAppService'

aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs

[warning] 33-33:
The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

🔇 Additional comments (15)
next-ts/app/page.tsx (1)

69-74: LGTM!

The footer implementation follows good practices with semantic HTML, proper contact information, and dynamic year generation for the copyright notice.

aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/RefListApplicationStatus.cs (1)

5-15: LGTM!

Well-structured enum with appropriate Display attributes. Starting values at 1 is good practice to avoid ambiguity with default/uninitialized values in database storage.

aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1)

12-59: Previous review concerns addressed; entity structure looks good.

The namespace declaration is now present, and DecisionDate is correctly nullable. The composite unique index on StudentId and ShortCourseId appropriately prevents duplicate applications. FK relationships and document URL validations are properly configured.

aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/RefListGender.cs (1)

5-18: LGTM!

Enum is well-structured with inclusive options and appropriate Display attributes for UI rendering.

aspnet-core/src/Moipone.PublicSite.Application/Students/IStudentAppService.cs (1)

8-11: Previous review concerns addressed; interface is now clean.

The method signature is clarified with a single non-nullable emailAddress parameter, and the return type correctly uses StudentDto instead of ActionResult, maintaining proper layer separation.

aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)

12-20: Missing properties from Student entity.

The Student entity includes IdNumber (13-digit ID) and DateOfBirth which are not mapped in this DTO. If these are intentionally excluded, consider documenting why; otherwise, add them:

         public string Name { get; set; }
         public string Surname { get; set; }
         public int Age { get; set; }
         public string Gender { get; set; }
         public string EmailAddress { get; set; }
         public string PhoneNumber { get; set; }
+        public string IdNumber { get; set; }
+        public DateOnly DateOfBirth { get; set; }
         public AddressDto ResidentialAddress { get; set; }
aspnet-core/src/Moipone.PublicSite.Application/Addresses/AddressAppService.cs (5)

16-24: LGTM!

Proper inheritance from AsyncCrudAppService with correct type parameters and base constructor invocation. This provides automatic ABP features like unit of work management and authorization.


26-48: LGTM!

Proper input validation, mapping, error handling, and logging. The implementation follows ABP best practices.


50-70: Pagination issue resolved!

The pagination parameters are now properly applied with Skip and Take, and total count is calculated separately. This addresses the previous review feedback.


101-130: Update pattern corrected!

The method now properly maps the input DTO to the tracked entity retrieved from the database (line 117: ObjectMapper.Map(input, address)), preserving EF Core change tracking and navigation properties. This addresses the previous review feedback.


132-159: LGTM!

Proper validation, existence check, and error handling for the delete operation.

aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (2)

10-12: LGTM!

Proper table naming and unique indexes on EmailAddress and IdNumber ensure data integrity and improve query performance.


15-50: Excellent validation coverage!

Comprehensive validation attributes with appropriate constraints for each property. The regex patterns for IdNumber (13 digits, likely South African ID) and PhoneNumber (international format) are well-defined.

aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (2)

12-13: LGTM!

Unique index on Code ensures course codes remain unique, which is appropriate for course identification.


50-52: Excellent navigation property implementation!

Using ICollection<T> (appropriate abstraction) and initializing collections to empty lists prevents NullReferenceException when adding items. This addresses previous feedback about collection initialization.

Comment thread aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs Outdated
Comment thread next-ts/app/page.tsx
Comment thread next-ts/app/page.tsx
Comment thread next-ts/app/page.tsx
Comment thread next-ts/app/page.tsx
Comment thread next-ts/app/page.tsx
Comment thread next-ts/app/page.tsx
@blebelo blebelo temporarily deployed to benny/Entities - Moipone PS API PR #4 December 15, 2025 23:34 — with Render Destroyed
Copy link
Copy Markdown
Contributor

@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: 4

♻️ Duplicate comments (1)
aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)

22-27: Document properties don't exist on the Student entity.

These document properties (CertifiedId, ProofOfResidence, CurriculumVitae, CertifiedHighestQualification) exist on CourseApplication, not Student. AutoMapper will silently ignore these properties, leaving them null/default. Remove them from StudentDto or create a separate CourseApplicationDto for document handling.

-        #region Documents
-        public string CertifiedId { get; set; }
-        public string ProofOfResidence { get; set; }
-        public string CurriculumVitae { get; set; }
-        public string CertifiedHighestQualification { get; set; }
-        #endregion
🧹 Nitpick comments (3)
aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)

12-20: Missing IdNumber and DateOfBirth properties that exist on the Student entity.

The Student entity has IdNumber and DateOfBirth as required fields, but they're missing from this DTO. Add them if they should be exposed via the API.

         public string EmailAddress { get; set; }
         public string PhoneNumber { get; set; }
+        public string IdNumber { get; set; }
+        public DateOnly DateOfBirth { get; set; }
         public AddressDto ResidentialAddress { get; set; }
         #endregion
aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (2)

25-27: Redundant Age property - can be computed from DateOfBirth.

Storing both Age and DateOfBirth creates data redundancy. Age will become stale over time unless actively maintained. Consider making Age a computed property or removing it entirely.

-    [Required]
-    [Range(10, 120)]
-    public int Age { get; set; }
+    // Computed property - no storage needed
+    public int Age => DateOfBirth != default 
+        ? (int)((DateTime.Today - DateOfBirth.ToDateTime(TimeOnly.MinValue)).Days / 365.25)
+        : 0;

If Age must be stored for querying purposes, ensure it's recalculated on save or via a background job.

Also applies to: 42-44


52-52: Consider adding an explicit ResidentialAddressId foreign key property.

The entity relies on EF Core conventions or shadow properties for the FK. Adding an explicit FK property improves clarity and enables direct FK assignment without loading the related entity.

+    [Required]
+    public Guid ResidentialAddressId { get; set; }
+
+    [ForeignKey(nameof(ResidentialAddressId))]
     public Address ResidentialAddress { get; set; }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afbcb8b and 249dc20.

📒 Files selected for processing (6)
  • aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/EntityFrameworkCore/PublicSiteDbContext.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215232604_Refactored_Documents.Designer.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215232604_Refactored_Documents.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/EntityFrameworkCore/PublicSiteDbContext.cs
🧰 Additional context used
🧬 Code graph analysis (3)
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215232604_Refactored_Documents.Designer.cs (3)
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (1)
  • DbContext (13-2278)
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/EntityFrameworkCore/PublicSiteDbContext.cs (2)
  • PublicSiteDbContext (13-27)
  • PublicSiteDbContext (23-26)
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215232604_Refactored_Documents.cs (1)
  • Refactored_Documents (9-597)
aspnet-core/src/Moipone.PublicSite.Application/Students/Dto/StudentDto.cs (1)
aspnet-core/src/Moipone.PublicSite.Application/Addresses/Dto/AddressDto.cs (1)
  • AutoMap (8-15)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (3)
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1)
  • Table (12-59)
aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (1)
  • Table (12-55)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs (1)
  • Address (7-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test Stage
🔇 Additional comments (4)
aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215232604_Refactored_Documents.Designer.cs (1)

1-2282: Auto-generated migration designer file looks consistent with the domain model.

The schema snapshot correctly reflects the new domain entities (Address, CourseApplication, ShortCourse, Student) with appropriate constraints, indexes, and relationships. No manual modifications needed for auto-generated files.

aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1)

10-50: Well-structured entity with comprehensive validation.

Good use of data annotations for validation constraints, unique indexes on EmailAddress and IdNumber, and proper regex patterns for South African ID format and phone numbers.

aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (2)

1583-1854: New domain entities properly configured with constraints and indexes.

The model snapshot correctly reflects:

  • Address: Required fields with appropriate MaxLength constraints
  • CourseApplication: Document URLs as required strings, composite unique index on (StudentId, ShortCourseId)
  • ShortCourse: Unique index on Code, proper constraints
  • Student: Unique indexes on EmailAddress and IdNumber, required FK to Address

Previous review concerns about missing constraints and nullable FKs have been addressed.


2138-2170: Relationship configurations look correct.

Proper cascade delete behavior is configured:

  • CourseApplication → ShortCourse (Cascade)
  • CourseApplication → Student (Cascade)
  • Student → Address (Cascade)

Navigation properties are correctly defined for ShortCourse's Applications and EnrolledStudents collections.

@blebelo blebelo temporarily deployed to benny/Entities - Moipone PS API PR #4 December 15, 2025 23:48 — with Render Destroyed
Copy link
Copy Markdown
Contributor

@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: 1

♻️ Duplicate comments (1)
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1)

1-9: Add #nullable enable to resolve compiler warning.

Static analysis flags line 32 for using string? without a nullable annotations context. Add the directive after the using statements.

 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
 
+#nullable enable
+
 namespace Moipone.PublicSite.Domain.CourseApplications;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 249dc20 and e439440.

📒 Files selected for processing (5)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215234558_Refactored_Documents.Designer.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215234558_Refactored_Documents.cs (1 hunks)
  • aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (3)
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1)
  • Table (11-37)
aspnet-core/src/Moipone.PublicSite.Core/Domain/ShortCourses/ShortCourse.cs (1)
  • Table (12-55)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Addresses/Address.cs (1)
  • Address (7-24)
🪛 GitHub Check: Build Stage
aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs

[warning] 32-32:
The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test Stage
🔇 Additional comments (9)
aspnet-core/src/Moipone.PublicSite.Core/Domain/Students/Student.cs (2)

10-55: Solid domain entity with comprehensive validation.

The entity has well-structured validation attributes covering personal information fields. The use of RefListGender enum instead of a free-form string for Gender is a good practice, and the document fields have been properly refactored from byte arrays to URL strings.

One consideration: ResidentialAddress is a navigation property without an explicit foreign key property. While EF Core will create a shadow property, adding an explicit nullable FK (Guid? ResidentialAddressId) would make the relationship more explicit and easier to work with in queries.


57-77: Consider document upload workflow.

All document fields are marked [Required]. Verify this aligns with the intended user workflow—if students should be able to create a profile before uploading all documents, these fields may need to be nullable initially and validated only at application submission time.

aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215234558_Refactored_Documents.cs (1)

74-79: FK cascade behavior change is intentional but noteworthy.

The FK is recreated without explicit onDelete behavior (defaults to NoAction/Restrict), which is appropriate for the now-nullable ResidentialAddressId. The Down migration correctly restores Cascade delete for the non-nullable scenario. This asymmetry is expected.

aspnet-core/src/Moipone.PublicSite.Core/Domain/CourseApplications/CourseApplication.cs (1)

11-35: Entity structure looks good.

The composite unique index on (StudentId, ShortCourseId) correctly prevents duplicate applications. FK properties are properly required with [ForeignKey] attributes on navigation properties. DecisionReason and DecisionDate are appropriately nullable for pending applications.

aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/20251215234558_Refactored_Documents.Designer.cs (1)

1-27: Auto-generated migration designer file.

This is an EF Core auto-generated file that captures the target model state for the migration. No manual edits required.

aspnet-core/src/Moipone.PublicSite.EntityFrameworkCore/Migrations/PublicSiteDbContextModelSnapshot.cs (4)

1583-1633: Address entity properly configured.

The Address entity has appropriate constraints: required string properties with MaxLength values (100 for Street/Suburb/City, 5 for PostalCode). This addresses previous review feedback about missing length constraints.


1635-1686: CourseApplication entity correctly configured with required FKs.

StudentId and ShortCourseId are non-nullable with a composite unique index—this properly enforces that a student can apply to each course only once. Previous concerns about nullable FKs have been addressed.


1754-1854: Student entity properly configured with unique indexes and constraints.

The entity has:

  • Unique indexes on EmailAddress and IdNumber for identity constraints
  • Nullable ResidentialAddressId for optional address relationship
  • Document URLs as varchar(255) instead of binary (addressing previous feedback)
  • All string properties with appropriate max lengths

2138-2168: Relationships correctly configured.

  • CourseApplication has cascade delete on both ShortCourse and Student FKs—applications are deleted when the related entity is deleted
  • Student.ResidentialAddress has no cascade (appropriate for nullable optional relationship)
  • Student.ShortCourseId links to ShortCourse.EnrolledStudents collection

@blebelo
Copy link
Copy Markdown
Owner Author

blebelo commented Dec 15, 2025

@coderabbitai resolve

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 15, 2025

✅ Actions performed

Comments resolved.

@blebelo blebelo merged commit 7f13d60 into main Dec 15, 2025
7 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request May 9, 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.

1 participant