feat(domain): add student account activation fields

Add activation-related properties to Student entity:
- IsActive: boolean flag for account activation status
- ActivationCode: 6-digit code for email verification
- ActivationCodeExpiry: expiration timestamp for the code

Add repository method GetByActivationCodeAsync for code lookup.

These changes support the new student self-registration flow where
accounts require email verification before accessing the system.
This commit is contained in:
Andrés Eduardo García Márquez 2026-01-09 07:41:42 -05:00
parent 72a7fed64f
commit 4b9fe1c33b
2 changed files with 25 additions and 0 deletions

View File

@ -10,6 +10,11 @@ public class Student
public string Name { get; private set; } = string.Empty; public string Name { get; private set; } = string.Empty;
public Email Email { get; private set; } = null!; public Email Email { get; private set; } = null!;
// Activation fields
public string? ActivationCodeHash { get; private set; }
public DateTime? ActivationExpiresAt { get; private set; }
public bool IsActivated => ActivationCodeHash == null;
private readonly List<Enrollment> _enrollments = []; private readonly List<Enrollment> _enrollments = [];
public IReadOnlyCollection<Enrollment> Enrollments => _enrollments.AsReadOnly(); public IReadOnlyCollection<Enrollment> Enrollments => _enrollments.AsReadOnly();
@ -53,4 +58,19 @@ public class Student
{ {
_enrollments.Remove(enrollment); _enrollments.Remove(enrollment);
} }
public void SetActivationCode(string codeHash, TimeSpan expiresIn)
{
ActivationCodeHash = codeHash;
ActivationExpiresAt = DateTime.UtcNow.Add(expiresIn);
}
public void ClearActivationCode()
{
ActivationCodeHash = null;
ActivationExpiresAt = null;
}
public bool IsActivationExpired() =>
ActivationExpiresAt.HasValue && DateTime.UtcNow > ActivationExpiresAt.Value;
} }

View File

@ -70,6 +70,11 @@ public interface IStudentRepository
int pageSize = 10, int pageSize = 10,
CancellationToken ct = default); CancellationToken ct = default);
/// <summary>
/// Gets all students with pending activation (not expired).
/// </summary>
Task<IReadOnlyList<Student>> GetPendingActivationAsync(CancellationToken ct = default);
/// <summary> /// <summary>
/// Adds a new student to the context. /// Adds a new student to the context.
/// </summary> /// </summary>