diff --git a/Directory.Build.props b/Directory.Build.props index 134b7ea71..733e4e7e8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,7 @@ 8 + 0612 diff --git a/HwProj.Common/HwProj.Repositories/ReadOnlyRepository.cs b/HwProj.Common/HwProj.Repositories/ReadOnlyRepository.cs index 4e0b9a4ad..59c94c59e 100644 --- a/HwProj.Common/HwProj.Repositories/ReadOnlyRepository.cs +++ b/HwProj.Common/HwProj.Repositories/ReadOnlyRepository.cs @@ -32,7 +32,7 @@ public async Task GetAsync(TKey id) return await Context.FindAsync(id).ConfigureAwait(false); } - public async Task FindAsync(Expression> predicate) + public virtual async Task FindAsync(Expression> predicate) { return await Context.Set().AsNoTracking().FirstOrDefaultAsync(predicate).ConfigureAwait(false); } diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Domains/MappingExtensions.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Domains/MappingExtensions.cs index 0393b25f0..bfef52d02 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Domains/MappingExtensions.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Domains/MappingExtensions.cs @@ -85,7 +85,7 @@ public static CourseDTO ToCourseDto(this Course course) Name = course.Name, GroupName = course.GroupName, IsCompleted = course.IsCompleted, - MentorIds = course.MentorIds.Split("/"), + MentorIds = course.Mentors.Select(x => x.UserId).ToArray(), IsOpen = course.IsOpen, InviteCode = course.InviteCode, CourseMates = course.CourseMates.Select(cm => cm.ToCourseMateViewModel()).ToArray(), @@ -99,7 +99,7 @@ public static CoursePreview ToCoursePreview(this Course course) Name = course.Name, GroupName = course.GroupName, IsCompleted = course.IsCompleted, - MentorIds = course.MentorIds.Split("/"), + MentorIds = course.Mentors.Select(x => x.UserId).ToArray(), }; public static HomeworkTask ToHomeworkTask(this CreateTaskViewModel createTaskViewModel) diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerAcceptToCourseEvent.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerAcceptToCourseEvent.cs index 163af8672..4362ed80f 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerAcceptToCourseEvent.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerAcceptToCourseEvent.cs @@ -6,7 +6,6 @@ public class LecturerAcceptToCourseEvent : Event { public long CourseId { get; set; } public string CourseName { get; set; } - public string MentorIds { get; set; } public string StudentId { get; set; } } } diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerRejectToCourseEvent.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerRejectToCourseEvent.cs index 9386a6cb1..f6b6fe876 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerRejectToCourseEvent.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Events/LecturerRejectToCourseEvent.cs @@ -6,7 +6,6 @@ public class LecturerRejectToCourseEvent : Event { public long CourseId { get; set; } public string CourseName { get; set; } - public string MentorIds { get; set; } public string StudentId { get; set; } } } diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Events/NewCourseMateEvent.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Events/NewCourseMateEvent.cs index 747917731..99c1977c9 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Events/NewCourseMateEvent.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Events/NewCourseMateEvent.cs @@ -6,7 +6,7 @@ public class NewCourseMateEvent : Event { public long CourseId { get; set; } public string CourseName { get; set; } - public string MentorIds { get; set; } + public string[] MentorIds { get; set; } public string StudentId { get; set; } public bool IsAccepted { get; set; } } diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/20250424012738_'CourseMentors'.Designer.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/20250424012738_'CourseMentors'.Designer.cs new file mode 100644 index 000000000..16c6dba41 --- /dev/null +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/20250424012738_'CourseMentors'.Designer.cs @@ -0,0 +1,350 @@ +// +using System; +using HwProj.CoursesService.API.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace HwProj.CoursesService.API.Migrations +{ + [DbContext(typeof(CourseContext))] + [Migration("20250424012738_'CourseMentors'")] + partial class CourseMentors + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.Assignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CourseId"); + + b.Property("MentorId"); + + b.Property("StudentId"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Assignments"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.Course", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("GroupName"); + + b.Property("InviteCode"); + + b.Property("IsCompleted"); + + b.Property("IsOpen"); + + b.Property("MentorIds"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("Courses"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseFilter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("FilterJson"); + + b.HasKey("Id"); + + b.ToTable("CourseFilters"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseMate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CourseId"); + + b.Property("IsAccepted"); + + b.Property("StudentId"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("CourseMates"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseMentor", b => + { + b.Property("UserId"); + + b.Property("CourseId"); + + b.HasKey("UserId", "CourseId"); + + b.HasIndex("CourseId"); + + b.HasIndex("UserId"); + + b.ToTable("CourseMentors"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.Group", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CourseId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.GroupMate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("GroupId"); + + b.Property("StudentId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasAlternateKey("GroupId", "StudentId"); + + b.ToTable("GroupMates"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.Homework", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("CourseId"); + + b.Property("DeadlineDate"); + + b.Property("Description"); + + b.Property("HasDeadline"); + + b.Property("IsDeadlineStrict"); + + b.Property("PublicationDate"); + + b.Property("Tags"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Homeworks"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.HomeworkTask", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("DeadlineDate"); + + b.Property("Description"); + + b.Property("HasDeadline"); + + b.Property("HomeworkId"); + + b.Property("IsDeadlineStrict"); + + b.Property("MaxRating"); + + b.Property("PublicationDate"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("HomeworkId"); + + b.ToTable("Tasks"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.StudentCharacteristics", b => + { + b.Property("CourseMateId"); + + b.Property("Description"); + + b.Property("Tags"); + + b.HasKey("CourseMateId"); + + b.ToTable("StudentCharacteristics"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.TaskModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("GroupId"); + + b.Property("TaskId"); + + b.HasKey("Id"); + + b.HasIndex("GroupId"); + + b.ToTable("TasksModels"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.TaskQuestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Answer") + .HasMaxLength(1000); + + b.Property("IsPrivate"); + + b.Property("LecturerId"); + + b.Property("StudentId"); + + b.Property("TaskId"); + + b.Property("Text") + .HasMaxLength(1000); + + b.HasKey("Id"); + + b.HasIndex("TaskId"); + + b.ToTable("Questions"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.UserToCourseFilter", b => + { + b.Property("CourseId"); + + b.Property("UserId"); + + b.Property("CourseFilterId"); + + b.HasKey("CourseId", "UserId"); + + b.HasIndex("CourseFilterId"); + + b.ToTable("UserToCourseFilters"); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.Assignment", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Course") + .WithMany("Assignments") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseMate", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Course") + .WithMany("CourseMates") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseMentor", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Course") + .WithMany("Mentors") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.GroupMate", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Group") + .WithMany("GroupMates") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.Homework", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Course") + .WithMany("Homeworks") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.HomeworkTask", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Homework", "Homework") + .WithMany("Tasks") + .HasForeignKey("HomeworkId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.StudentCharacteristics", b => + { + b.HasOne("HwProj.CoursesService.API.Models.CourseMate") + .WithOne("Characteristics") + .HasForeignKey("HwProj.CoursesService.API.Models.StudentCharacteristics", "CourseMateId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.TaskModel", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Group") + .WithMany("Tasks") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("HwProj.CoursesService.API.Models.UserToCourseFilter", b => + { + b.HasOne("HwProj.CoursesService.API.Models.CourseFilter", "CourseFilter") + .WithMany() + .HasForeignKey("CourseFilterId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/20250424012738_'CourseMentors'.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/20250424012738_'CourseMentors'.cs new file mode 100644 index 000000000..3aaade4d9 --- /dev/null +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/20250424012738_'CourseMentors'.cs @@ -0,0 +1,63 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace HwProj.CoursesService.API.Migrations +{ + public partial class CourseMentors : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CourseMentors", + columns: table => new + { + UserId = table.Column(nullable: false), + CourseId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CourseMentors", x => new { x.UserId, x.CourseId }); + table.ForeignKey( + name: "FK_CourseMentors_Courses_CourseId", + column: x => x.CourseId, + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_CourseMentors_CourseId", + table: "CourseMentors", + column: "CourseId"); + + migrationBuilder.CreateIndex( + name: "IX_CourseMentors_UserId", + table: "CourseMentors", + column: "UserId"); + + // Миграция данных: Перенос MentorIds в таблицу CourseMentor + // language=SQL + migrationBuilder.Sql(@" +-- Разделим MentorIds на элементы, преобразуем в строки, удалим дубликаты и вставим в таблицу CourseMentor +WITH SplitMentorIds AS ( + SELECT + c.Id AS CourseId, + LTRIM(RTRIM(value)) AS MentorId + FROM Courses c + CROSS APPLY STRING_SPLIT(c.MentorIds, '/') -- Разделяем MentorIds по запятой +) +, DistinctMentors AS ( + SELECT DISTINCT + MentorId, + CourseId + FROM SplitMentorIds + WHERE MentorId <> '' -- Исключаем пустые строки +) +INSERT INTO CourseMentors (UserId, CourseId) +SELECT + MentorId, + CourseId +FROM DistinctMentors; +"); + } + } +} diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/CourseContextModelSnapshot.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/CourseContextModelSnapshot.cs index 736fb0058..26fc00997 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/CourseContextModelSnapshot.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Migrations/CourseContextModelSnapshot.cs @@ -93,6 +93,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("CourseMates"); }); + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseMentor", b => + { + b.Property("UserId"); + + b.Property("CourseId"); + + b.HasKey("UserId", "CourseId"); + + b.HasIndex("CourseId"); + + b.HasIndex("UserId"); + + b.ToTable("CourseMentors"); + }); + modelBuilder.Entity("HwProj.CoursesService.API.Models.Group", b => { b.Property("Id") @@ -272,6 +287,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade); }); + modelBuilder.Entity("HwProj.CoursesService.API.Models.CourseMentor", b => + { + b.HasOne("HwProj.CoursesService.API.Models.Course") + .WithMany("Mentors") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("HwProj.CoursesService.API.Models.GroupMate", b => { b.HasOne("HwProj.CoursesService.API.Models.Group") diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Models/Course.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Models/Course.cs index e5f6af8a3..3efb5b4e9 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Models/Course.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Models/Course.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using HwProj.Repositories; @@ -12,7 +13,8 @@ public class Course : IEntity public bool IsOpen { get; set; } public string InviteCode { get; set; } public bool IsCompleted { get; set; } - public string MentorIds { get; set; } + [Obsolete] public string MentorIds { get; set; } + public List Mentors { get; set; } = new List(); public List CourseMates { get; set; } = new List(); public List Homeworks { get; set; } = new List(); public List Assignments { get; set; } = new List(); diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseContext.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseContext.cs index ca089ff93..ebd5e1fe5 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseContext.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseContext.cs @@ -5,6 +5,7 @@ namespace HwProj.CoursesService.API.Models public sealed class CourseContext : DbContext { public DbSet Courses { get; set; } + public DbSet CourseMentors { get; set; } public DbSet CourseMates { get; set; } public DbSet Groups { get; set; } public DbSet GroupMates { get; set; } @@ -27,6 +28,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasIndex(a => a.CourseId); modelBuilder.Entity().HasKey(u => new { u.CourseId, u.UserId }); modelBuilder.Entity().HasIndex(t => t.TaskId); + + modelBuilder.Entity().HasKey(m => new { m.UserId, m.CourseId }); + modelBuilder.Entity().HasIndex(m => m.UserId); + modelBuilder.Entity().HasIndex(m => m.CourseId); } } } diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseMentor.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseMentor.cs new file mode 100644 index 000000000..8fa0abdcf --- /dev/null +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Models/CourseMentor.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace HwProj.CoursesService.API.Models +{ + [Table("CourseMentors")] + public class CourseMentor + { + public string UserId { get; set; } + public long CourseId { get; set; } + } +} diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Repositories/CoursesRepository.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Repositories/CoursesRepository.cs index 17e4bd829..09254f343 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Repositories/CoursesRepository.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Repositories/CoursesRepository.cs @@ -1,4 +1,6 @@ -using System.Linq; +using System; +using System.Linq; +using System.Linq.Expressions; using System.Threading.Tasks; using HwProj.CoursesService.API.Models; using HwProj.Repositories; @@ -6,6 +8,7 @@ namespace HwProj.CoursesService.API.Repositories { + // TODO: include mentors by default public class CoursesRepository : CrudRepository, ICoursesRepository { public CoursesRepository(CourseContext context) @@ -13,8 +16,14 @@ public CoursesRepository(CourseContext context) { } + public override async Task FindAsync(Expression> predicate) + { + return await Context.Set().AsNoTracking().Include(x => x.Mentors).FirstOrDefaultAsync(predicate); + } + public Task GetWithCourseMates(long id) => Context.Set() + .Include(x => x.Mentors) .Include(c => c.CourseMates) .ThenInclude(c => c.Characteristics) .AsNoTracking() @@ -22,6 +31,7 @@ public CoursesRepository(CourseContext context) public async Task GetWithHomeworksAsync(long id) => await Context.Set() + .Include(x => x.Mentors) .Include(c => c.Homeworks) .ThenInclude(h => h.Tasks) .AsNoTracking() @@ -30,6 +40,7 @@ public CoursesRepository(CourseContext context) public async Task GetWithCourseMatesAndHomeworksAsync(long id) { var course = await Context.Set() + .Include(x => x.Mentors) .Include(c => c.CourseMates) .ThenInclude(c => c.Characteristics) .Include(c => c.Homeworks) @@ -45,6 +56,7 @@ public CoursesRepository(CourseContext context) public IQueryable GetAllWithCourseMatesAndHomeworks() { return Context.Set() + .Include(x => x.Mentors) .Include(c => c.CourseMates) .ThenInclude(c => c.Characteristics) .Include(c => c.Homeworks) diff --git a/HwProj.CoursesService/HwProj.CoursesService.API/Services/CoursesService.cs b/HwProj.CoursesService/HwProj.CoursesService.API/Services/CoursesService.cs index 7fd03cdb0..141990b80 100644 --- a/HwProj.CoursesService/HwProj.CoursesService.API/Services/CoursesService.cs +++ b/HwProj.CoursesService/HwProj.CoursesService.API/Services/CoursesService.cs @@ -113,8 +113,8 @@ public async Task AddFromTemplateAsync(CourseTemplate courseTemplate, List using var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); var course = courseTemplate.ToCourse(); - course.MentorIds = mentorId; course.InviteCode = Guid.NewGuid().ToString(); + course.Mentors = new List { new CourseMentor { UserId = mentorId } }; var courseId = await _coursesRepository.AddAsync(course); var homeworks = courseTemplate.Homeworks.Select(hwTemplate => hwTemplate.ToHomework(courseId)); @@ -141,7 +141,6 @@ public async Task AddFromTemplateAsync(CourseTemplate courseTemplate, List { CourseId = courseId, CourseName = course.Name, - MentorIds = course.MentorIds, StudentId = student.StudentId }); } @@ -187,7 +186,7 @@ public async Task AddStudentAsync(long courseId, string studentId) { CourseId = courseId, CourseName = course.Name, - MentorIds = course.MentorIds, + MentorIds = course.Mentors.Select(x => x.UserId).ToArray(), StudentId = studentId, IsAccepted = false }); @@ -209,7 +208,6 @@ public async Task AcceptCourseMateAsync(long courseId, string studentId) { CourseId = courseId, CourseName = course.Name, - MentorIds = course.MentorIds, StudentId = studentId }); @@ -230,7 +228,6 @@ public async Task RejectCourseMateAsync(long courseId, string studentId) { CourseId = courseId, CourseName = course.Name, - MentorIds = course.MentorIds, StudentId = studentId }); return true; @@ -241,10 +238,11 @@ public async Task GetUserCoursesAsync(string userId, string role) var isMentor = role == Roles.LecturerRole || role == Roles.ExpertRole; var courses = isMentor - ? _coursesRepository.FindAll(c => c.MentorIds.Contains(userId)) + ? _coursesRepository.FindAll(c => c.Mentors.Any(m => m.UserId == userId)) : _coursesRepository.FindAll(c => c.CourseMates.Any(cm => cm.IsAccepted && cm.StudentId == userId)); var coursesWithValues = await courses + .Include(c => c.Mentors) .Include(c => c.CourseMates) .Include(c => c.Homeworks).ThenInclude(t => t.Tasks) .ToArrayAsync(); @@ -271,13 +269,10 @@ public async Task AcceptLecturerAsync(long courseId, string lecturerEmail, { var course = await _coursesRepository.GetAsync(courseId); if (course == null) return false; - if (!course.MentorIds.Contains(lecturerId)) + if (course.Mentors.All(x => x.UserId != lecturerId)) { - var newMentors = course.MentorIds + "/" + lecturerId; - await _coursesRepository.UpdateAsync(courseId, с => new Course - { - MentorIds = newMentors, - }); + await _context.CourseMentors.AddAsync(new CourseMentor() { CourseId = courseId, UserId = lecturerId }); + await _context.SaveChangesAsync(); _eventBus.Publish(new LecturerInvitedToCourseEvent { @@ -286,8 +281,6 @@ public async Task AcceptLecturerAsync(long courseId, string lecturerEmail, MentorId = lecturerId, MentorEmail = lecturerEmail }); - //TODO: remove - await RejectCourseMateAsync(courseId, lecturerId); } return true; @@ -296,7 +289,7 @@ public async Task AcceptLecturerAsync(long courseId, string lecturerEmail, public async Task GetCourseLecturers(long courseId) { var course = await _coursesRepository.GetAsync(courseId); - return course.MentorIds.Split('/'); + return course.Mentors.Select(x => x.UserId).ToArray(); } public async Task HasStudent(long courseId, string studentId) diff --git a/HwProj.NotificationsService/HwProj.NotificationsService.API/EventHandlers/NewCourseMateHandler.cs b/HwProj.NotificationsService/HwProj.NotificationsService.API/EventHandlers/NewCourseMateHandler.cs index eab810b0f..f3f755d44 100644 --- a/HwProj.NotificationsService/HwProj.NotificationsService.API/EventHandlers/NewCourseMateHandler.cs +++ b/HwProj.NotificationsService/HwProj.NotificationsService.API/EventHandlers/NewCourseMateHandler.cs @@ -38,7 +38,7 @@ public override async Task HandleAsync(NewCourseMateEvent @event) var user = await _authServiceClient.GetAccountData(@event.StudentId); var url = _configuration["Url"]; - var mentorIds = @event.MentorIds.Split('/'); + var mentorIds = @event.MentorIds; var mentors = await _authServiceClient.GetAccountsData(mentorIds); //TODO: fix