diff --git a/backend/UniVerse.Domain/Entities/Achievement.cs b/backend/UniVerse.Domain/Entities/Achievement.cs new file mode 100644 index 0000000..e17c88d --- /dev/null +++ b/backend/UniVerse.Domain/Entities/Achievement.cs @@ -0,0 +1,16 @@ +namespace UniVerse.Domain.Entities; + +public class Achievement +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Description { get; set; } + public string? IconUrl { get; set; } + public int XpReward { get; set; } + public int CoinReward { get; set; } + public string? Condition { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public ICollection UserAchievements { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/CoinTransaction.cs b/backend/UniVerse.Domain/Entities/CoinTransaction.cs new file mode 100644 index 0000000..457f2db --- /dev/null +++ b/backend/UniVerse.Domain/Entities/CoinTransaction.cs @@ -0,0 +1,20 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Domain.Entities; + +public class CoinTransaction +{ + public int Id { get; set; } + public int UserId { get; set; } + public int Amount { get; set; } + public CoinTransactionType Type { get; set; } + public int? ReviewId { get; set; } + public int? AchievementId { get; set; } + public string? Description { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public User User { get; set; } = null!; + public Review? Review { get; set; } + public Achievement? Achievement { get; set; } +} diff --git a/backend/UniVerse.Domain/Entities/Course.cs b/backend/UniVerse.Domain/Entities/Course.cs new file mode 100644 index 0000000..3825db9 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/Course.cs @@ -0,0 +1,16 @@ +namespace UniVerse.Domain.Entities; + +public class Course +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Description { get; set; } + public string? ExternalId { get; set; } + public bool IsSynced { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public ICollection Lectures { get; set; } = new List(); + public ICollection CourseTags { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/CourseTag.cs b/backend/UniVerse.Domain/Entities/CourseTag.cs new file mode 100644 index 0000000..4c15c51 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/CourseTag.cs @@ -0,0 +1,12 @@ +namespace UniVerse.Domain.Entities; + +public class CourseTag +{ + public int Id { get; set; } + public int CourseId { get; set; } + public int TagId { get; set; } + + // Navigation properties + public Course Course { get; set; } = null!; + public Tag Tag { get; set; } = null!; +} diff --git a/backend/UniVerse.Domain/Entities/Lecture.cs b/backend/UniVerse.Domain/Entities/Lecture.cs new file mode 100644 index 0000000..37a732b --- /dev/null +++ b/backend/UniVerse.Domain/Entities/Lecture.cs @@ -0,0 +1,29 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Domain.Entities; + +public class Lecture +{ + public int Id { get; set; } + public int CourseId { get; set; } + public int? TeacherId { get; set; } + public int? LocationId { get; set; } + public string Title { get; set; } = string.Empty; + public string? Description { get; set; } + public LectureFormat Format { get; set; } = LectureFormat.Offline; + public DateTime StartsAt { get; set; } + public DateTime EndsAt { get; set; } + public bool IsOpen { get; set; } = true; + public int MaxEnrollments { get; set; } + public string? ExternalId { get; set; } + public string? OnlineUrl { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public Course Course { get; set; } = null!; + public User? Teacher { get; set; } + public Location? Location { get; set; } + public ICollection Enrollments { get; set; } = new List(); + public ICollection Reviews { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/LectureEnrollment.cs b/backend/UniVerse.Domain/Entities/LectureEnrollment.cs new file mode 100644 index 0000000..712f757 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/LectureEnrollment.cs @@ -0,0 +1,14 @@ +namespace UniVerse.Domain.Entities; + +public class LectureEnrollment +{ + public int Id { get; set; } + public int LectureId { get; set; } + public int UserId { get; set; } + public bool Attended { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public Lecture Lecture { get; set; } = null!; + public User User { get; set; } = null!; +} diff --git a/backend/UniVerse.Domain/Entities/Location.cs b/backend/UniVerse.Domain/Entities/Location.cs new file mode 100644 index 0000000..18c9339 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/Location.cs @@ -0,0 +1,15 @@ +namespace UniVerse.Domain.Entities; + +public class Location +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Building { get; set; } + public string? Room { get; set; } + public string? Address { get; set; } + public string? ExternalId { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public ICollection Lectures { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/RefreshToken.cs b/backend/UniVerse.Domain/Entities/RefreshToken.cs new file mode 100644 index 0000000..486ace4 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/RefreshToken.cs @@ -0,0 +1,18 @@ +namespace UniVerse.Domain.Entities; + +public class RefreshToken +{ + public int Id { get; set; } + public int UserId { get; set; } + public string Token { get; set; } = string.Empty; + public DateTime ExpiresAt { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime? RevokedAt { get; set; } + + public bool IsExpired => DateTime.UtcNow >= ExpiresAt; + public bool IsRevoked => RevokedAt != null; + public bool IsActive => !IsRevoked && !IsExpired; + + // Navigation properties + public User User { get; set; } = null!; +} diff --git a/backend/UniVerse.Domain/Entities/Review.cs b/backend/UniVerse.Domain/Entities/Review.cs new file mode 100644 index 0000000..9883dcd --- /dev/null +++ b/backend/UniVerse.Domain/Entities/Review.cs @@ -0,0 +1,24 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Domain.Entities; + +public class Review +{ + public int Id { get; set; } + public int LectureId { get; set; } + public int UserId { get; set; } + public ReviewRating Rating { get; set; } + public string? Text { get; set; } + public ReviewLlmStatus LlmStatus { get; set; } = ReviewLlmStatus.Pending; + public ReviewSentiment? Sentiment { get; set; } + public double? QualityScore { get; set; } + public bool? IsInformative { get; set; } + public string[]? LlmTags { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public Lecture Lecture { get; set; } = null!; + public User User { get; set; } = null!; + public ICollection CoinTransactions { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/StudentProfile.cs b/backend/UniVerse.Domain/Entities/StudentProfile.cs new file mode 100644 index 0000000..1e47b76 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/StudentProfile.cs @@ -0,0 +1,15 @@ +namespace UniVerse.Domain.Entities; + +public class StudentProfile +{ + public int Id { get; set; } + public int UserId { get; set; } + public string? StudentId { get; set; } + public string? GroupName { get; set; } + public int? EnrollmentYear { get; set; } + public string? Faculty { get; set; } + public string? Specialty { get; set; } + + // Navigation properties + public User User { get; set; } = null!; +} diff --git a/backend/UniVerse.Domain/Entities/Tag.cs b/backend/UniVerse.Domain/Entities/Tag.cs new file mode 100644 index 0000000..56b804a --- /dev/null +++ b/backend/UniVerse.Domain/Entities/Tag.cs @@ -0,0 +1,17 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Domain.Entities; + +public class Tag +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public TagType Type { get; set; } + public int? ParentId { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public Tag? Parent { get; set; } + public ICollection Children { get; set; } = new List(); + public ICollection CourseTags { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/TeacherProfile.cs b/backend/UniVerse.Domain/Entities/TeacherProfile.cs new file mode 100644 index 0000000..8766ec0 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/TeacherProfile.cs @@ -0,0 +1,14 @@ +namespace UniVerse.Domain.Entities; + +public class TeacherProfile +{ + public int Id { get; set; } + public int UserId { get; set; } + public string? Department { get; set; } + public string? Title { get; set; } + public string? Bio { get; set; } + public string? ModeusId { get; set; } + + // Navigation properties + public User User { get; set; } = null!; +} diff --git a/backend/UniVerse.Domain/Entities/User.cs b/backend/UniVerse.Domain/Entities/User.cs new file mode 100644 index 0000000..d7893de --- /dev/null +++ b/backend/UniVerse.Domain/Entities/User.cs @@ -0,0 +1,27 @@ +using UniVerse.Domain.Enums; + +namespace UniVerse.Domain.Entities; + +public class User +{ + public int Id { get; set; } + public string Email { get; set; } = string.Empty; + public string? DisplayName { get; set; } + public string? AvatarUrl { get; set; } + public UserRole Role { get; set; } = UserRole.Student; + public bool IsActive { get; set; } = true; + public string? MicrosoftId { get; set; } + public int Xp { get; set; } + public int Coins { get; set; } + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public StudentProfile? StudentProfile { get; set; } + public TeacherProfile? TeacherProfile { get; set; } + public ICollection Enrollments { get; set; } = new List(); + public ICollection Reviews { get; set; } = new List(); + public ICollection UserAchievements { get; set; } = new List(); + public ICollection CoinTransactions { get; set; } = new List(); + public ICollection RefreshTokens { get; set; } = new List(); +} diff --git a/backend/UniVerse.Domain/Entities/UserAchievement.cs b/backend/UniVerse.Domain/Entities/UserAchievement.cs new file mode 100644 index 0000000..6f3fcd1 --- /dev/null +++ b/backend/UniVerse.Domain/Entities/UserAchievement.cs @@ -0,0 +1,13 @@ +namespace UniVerse.Domain.Entities; + +public class UserAchievement +{ + public int Id { get; set; } + public int UserId { get; set; } + public int AchievementId { get; set; } + public DateTime AwardedAt { get; set; } = DateTime.UtcNow; + + // Navigation properties + public User User { get; set; } = null!; + public Achievement Achievement { get; set; } = null!; +} diff --git a/backend/UniVerse.Domain/Enums/CoinTransactionType.cs b/backend/UniVerse.Domain/Enums/CoinTransactionType.cs new file mode 100644 index 0000000..0654fbe --- /dev/null +++ b/backend/UniVerse.Domain/Enums/CoinTransactionType.cs @@ -0,0 +1,9 @@ +namespace UniVerse.Domain.Enums; + +public enum CoinTransactionType +{ + ReviewReward, + AchievementReward, + AttendanceReward, + AdminAdjustment +} diff --git a/backend/UniVerse.Domain/Enums/LectureFormat.cs b/backend/UniVerse.Domain/Enums/LectureFormat.cs new file mode 100644 index 0000000..738d9d8 --- /dev/null +++ b/backend/UniVerse.Domain/Enums/LectureFormat.cs @@ -0,0 +1,7 @@ +namespace UniVerse.Domain.Enums; + +public enum LectureFormat +{ + Online, + Offline +} diff --git a/backend/UniVerse.Domain/Enums/ReviewLlmStatus.cs b/backend/UniVerse.Domain/Enums/ReviewLlmStatus.cs new file mode 100644 index 0000000..937b0ef --- /dev/null +++ b/backend/UniVerse.Domain/Enums/ReviewLlmStatus.cs @@ -0,0 +1,8 @@ +namespace UniVerse.Domain.Enums; + +public enum ReviewLlmStatus +{ + Pending, + Analyzed, + Rejected +} diff --git a/backend/UniVerse.Domain/Enums/ReviewRating.cs b/backend/UniVerse.Domain/Enums/ReviewRating.cs new file mode 100644 index 0000000..e5d9f23 --- /dev/null +++ b/backend/UniVerse.Domain/Enums/ReviewRating.cs @@ -0,0 +1,8 @@ +namespace UniVerse.Domain.Enums; + +public enum ReviewRating +{ + Like, + Neutral, + Dislike +} diff --git a/backend/UniVerse.Domain/Enums/ReviewSentiment.cs b/backend/UniVerse.Domain/Enums/ReviewSentiment.cs new file mode 100644 index 0000000..c3b6964 --- /dev/null +++ b/backend/UniVerse.Domain/Enums/ReviewSentiment.cs @@ -0,0 +1,8 @@ +namespace UniVerse.Domain.Enums; + +public enum ReviewSentiment +{ + Positive, + Neutral, + Negative +} diff --git a/backend/UniVerse.Domain/Enums/TagType.cs b/backend/UniVerse.Domain/Enums/TagType.cs new file mode 100644 index 0000000..caef984 --- /dev/null +++ b/backend/UniVerse.Domain/Enums/TagType.cs @@ -0,0 +1,11 @@ +namespace UniVerse.Domain.Enums; + +public enum TagType +{ + Institute, + Faculty, + Subject, + Organization, + Topic, + Other +} diff --git a/backend/UniVerse.Domain/Enums/UserRole.cs b/backend/UniVerse.Domain/Enums/UserRole.cs new file mode 100644 index 0000000..b664823 --- /dev/null +++ b/backend/UniVerse.Domain/Enums/UserRole.cs @@ -0,0 +1,8 @@ +namespace UniVerse.Domain.Enums; + +public enum UserRole +{ + Student, + Teacher, + Admin +} diff --git a/backend/UniVerse.Domain/Exceptions/ConflictException.cs b/backend/UniVerse.Domain/Exceptions/ConflictException.cs new file mode 100644 index 0000000..500fe71 --- /dev/null +++ b/backend/UniVerse.Domain/Exceptions/ConflictException.cs @@ -0,0 +1,8 @@ +namespace UniVerse.Domain.Exceptions; + +public class ConflictException : Exception +{ + public ConflictException(string message) : base(message) + { + } +} diff --git a/backend/UniVerse.Domain/Exceptions/ForbiddenException.cs b/backend/UniVerse.Domain/Exceptions/ForbiddenException.cs new file mode 100644 index 0000000..1188d6a --- /dev/null +++ b/backend/UniVerse.Domain/Exceptions/ForbiddenException.cs @@ -0,0 +1,9 @@ +namespace UniVerse.Domain.Exceptions; + +public class ForbiddenException : Exception +{ + public ForbiddenException(string message = "You do not have permission to perform this action.") + : base(message) + { + } +} diff --git a/backend/UniVerse.Domain/Exceptions/NotFoundException.cs b/backend/UniVerse.Domain/Exceptions/NotFoundException.cs new file mode 100644 index 0000000..9651bd1 --- /dev/null +++ b/backend/UniVerse.Domain/Exceptions/NotFoundException.cs @@ -0,0 +1,13 @@ +namespace UniVerse.Domain.Exceptions; + +public class NotFoundException : Exception +{ + public NotFoundException(string entityName, object key) + : base($"{entityName} with key '{key}' was not found.") + { + } + + public NotFoundException(string message) : base(message) + { + } +} diff --git a/backend/UniVerse.Domain/UniVerse.Domain.csproj b/backend/UniVerse.Domain/UniVerse.Domain.csproj new file mode 100644 index 0000000..e450d5e --- /dev/null +++ b/backend/UniVerse.Domain/UniVerse.Domain.csproj @@ -0,0 +1,10 @@ + + + + net10.0 + enable + enable + UniVerse.Domain + + +