2026-01-08 04:00:56 +00:00
|
|
|
@startuml domain-model
|
|
|
|
|
!theme plain
|
|
|
|
|
skinparam classAttributeIconSize 0
|
|
|
|
|
skinparam classFontStyle bold
|
|
|
|
|
skinparam classBackgroundColor #F8F9FA
|
|
|
|
|
skinparam classBorderColor #495057
|
|
|
|
|
|
|
|
|
|
title Sistema de Registro de Estudiantes - Modelo de Dominio
|
|
|
|
|
|
|
|
|
|
package "Domain" {
|
|
|
|
|
|
2026-01-09 12:43:35 +00:00
|
|
|
class User <<Entity>> {
|
|
|
|
|
- id: int
|
|
|
|
|
- username: string
|
|
|
|
|
- passwordHash: string
|
|
|
|
|
- recoveryCodeHash: string
|
|
|
|
|
- role: string
|
|
|
|
|
- studentId: int?
|
|
|
|
|
- createdAt: DateTime
|
|
|
|
|
- lastLoginAt: DateTime?
|
|
|
|
|
--
|
|
|
|
|
+ {static} Create(username, passwordHash, ...): User
|
|
|
|
|
+ UpdatePassword(newHash): void
|
|
|
|
|
+ UpdateLastLogin(): void
|
|
|
|
|
+ IsAdmin: bool
|
|
|
|
|
+ IsStudent: bool
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-08 04:00:56 +00:00
|
|
|
class Student <<Entity>> {
|
|
|
|
|
- id: int
|
|
|
|
|
- name: string
|
|
|
|
|
- email: Email
|
2026-01-09 12:43:35 +00:00
|
|
|
- activationCodeHash: string?
|
|
|
|
|
- activationExpiresAt: DateTime?
|
2026-01-08 04:00:56 +00:00
|
|
|
- enrollments: List<Enrollment>
|
|
|
|
|
--
|
|
|
|
|
+ getTotalCredits(): int
|
2026-01-09 12:43:35 +00:00
|
|
|
+ canEnroll(): bool
|
|
|
|
|
+ hasProfessor(professorId): bool
|
|
|
|
|
+ addEnrollment(enrollment): void
|
|
|
|
|
+ removeEnrollment(enrollment): void
|
|
|
|
|
+ setActivationCode(hash, expiresIn): void
|
|
|
|
|
+ clearActivationCode(): void
|
|
|
|
|
+ isActivated: bool
|
|
|
|
|
+ isActivationExpired(): bool
|
2026-01-08 04:00:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Subject <<Entity>> {
|
|
|
|
|
- id: int
|
|
|
|
|
- name: string
|
|
|
|
|
- credits: int {= 3}
|
|
|
|
|
- professorId: int
|
|
|
|
|
--
|
|
|
|
|
+ getProfessor(): Professor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Professor <<Entity>> {
|
|
|
|
|
- id: int
|
|
|
|
|
- name: string
|
|
|
|
|
- subjects: List<Subject>
|
|
|
|
|
--
|
|
|
|
|
+ getSubjects(): List<Subject>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Enrollment <<Entity>> {
|
|
|
|
|
- id: int
|
|
|
|
|
- studentId: int
|
|
|
|
|
- subjectId: int
|
|
|
|
|
- enrolledAt: DateTime
|
|
|
|
|
--
|
|
|
|
|
+ getStudent(): Student
|
|
|
|
|
+ getSubject(): Subject
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Email <<Value Object>> {
|
|
|
|
|
- value: string
|
|
|
|
|
--
|
|
|
|
|
+ {static} create(value: string): Email
|
|
|
|
|
- validate(value: string): void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class EnrollmentDomainService <<Domain Service>> {
|
|
|
|
|
--
|
|
|
|
|
+ validateEnrollment(student: Student, subject: Subject): void
|
|
|
|
|
- checkMaxEnrollments(student: Student): void
|
|
|
|
|
- checkProfessorConstraint(student: Student, subject: Subject): void
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 12:43:35 +00:00
|
|
|
enum UserRoles <<Enumeration>> {
|
|
|
|
|
Admin
|
|
|
|
|
Student
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-08 04:00:56 +00:00
|
|
|
' Relaciones
|
2026-01-09 12:43:35 +00:00
|
|
|
User "0..1" -- "0..1" Student : vinculado a
|
|
|
|
|
User --> UserRoles : tiene
|
2026-01-08 04:00:56 +00:00
|
|
|
Student "1" *-- "0..3" Enrollment : tiene
|
|
|
|
|
Subject "1" *-- "0..*" Enrollment : inscripciones
|
|
|
|
|
Professor "1" *-- "2" Subject : imparte
|
|
|
|
|
Student *-- Email : email
|
|
|
|
|
|
|
|
|
|
EnrollmentDomainService ..> Student : valida
|
|
|
|
|
EnrollmentDomainService ..> Subject : valida
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-09 12:43:35 +00:00
|
|
|
note bottom of User
|
|
|
|
|
<b>Autenticación:</b>
|
|
|
|
|
- PBKDF2-SHA256 (100k iter)
|
|
|
|
|
- JWT para sesiones
|
|
|
|
|
- Recovery code para reset
|
|
|
|
|
end note
|
|
|
|
|
|
2026-01-08 04:00:56 +00:00
|
|
|
note bottom of Student
|
|
|
|
|
<b>Invariantes:</b>
|
|
|
|
|
- Máximo 3 inscripciones
|
|
|
|
|
- Email válido y único
|
|
|
|
|
- No repetir profesor
|
2026-01-09 12:43:35 +00:00
|
|
|
- Requiere activación
|
2026-01-08 04:00:56 +00:00
|
|
|
end note
|
|
|
|
|
|
|
|
|
|
note bottom of Subject
|
|
|
|
|
<b>Invariantes:</b>
|
|
|
|
|
- Créditos = 3 (fijo)
|
|
|
|
|
- Pertenece a un profesor
|
|
|
|
|
end note
|
|
|
|
|
|
|
|
|
|
note right of Professor
|
|
|
|
|
Cada profesor
|
|
|
|
|
imparte exactamente
|
|
|
|
|
2 materias
|
|
|
|
|
end note
|
|
|
|
|
|
|
|
|
|
@enduml
|