diff --git a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs index e053ee6701ef25180439b17232fdd4d7c7e1c30c..824870e326c4b18ce0ca7c2c00bb33b7a040d586 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs @@ -190,7 +190,6 @@ namespace Tsi1.Api.Controllers return Ok(result.Data); } - [Authorize(Roles = UserTypes.Professor + ", " + UserTypes.FacultyAdmin)] [HttpPut("Modify/{courseId}")] public async Task<IActionResult> Modify(int courseId, CourseModifyDto courseDto) diff --git a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs index 09b35e9a2c88a1dc8e8c8070162b1fcfbc63fae9..38200615365e0890f550c14f98992407d486fb8c 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs @@ -36,12 +36,31 @@ namespace Tsi1.Api.Controllers return Ok(result.Data); } + //[Authorize(Roles = UserTypes.Professor)] + //[HttpPost("Create")] + //public async Task<IActionResult> Create(ForumCreateDto newForum) + //{ + // var result = await _forumService.Create(newForum); + + // if (result.HasError) + // { + // return BadRequest(result.Message); + // } + + // return Ok(result.Data); + //} + [Authorize(Roles = UserTypes.Professor)] - [HttpPost("Create")] - public async Task<IActionResult> Create(ForumCreateDto newForum) + [HttpPut("{id}")] + public async Task<IActionResult> Modify(int id, ForumModifyDto forum) { - var result = await _forumService.Create(newForum); + var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + forum.TenantId = tenantId; + forum.ProfessorUserId = userId; + var result = await _forumService.Modify(id, forum); if (result.HasError) { return BadRequest(result.Message); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs index 4c4d099f672bdb4d3babcfafa870142bfeb385e6..c6cfc66e44344cde5d0caa11cf650ec2859f57ad 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs @@ -8,5 +8,6 @@ namespace Tsi1.BusinessLayer.Dtos public class ForumCreateDto { public string Name { get; set; } + public bool IsAutomaticSubscription { get; set; } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumModifyDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumModifyDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..b97955724585c6defb09ddd3d5f6fc5b7310049e --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumModifyDto.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class ForumModifyDto + { + public string Name { get; set; } + public bool IsAutomaticSubscription { get; set; } + + [JsonIgnore] + public int TenantId { get; set; } + + [JsonIgnore] + public int ProfessorUserId { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs index f0da4ed4c5da81030579247175e3f581b6ef5891..d986e96bbc8775247c305c5b55bf1451053140a8 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -14,6 +14,10 @@ namespace Tsi1.BusinessLayer.Helpers { CreateMap<Forum, ForumCreateDto>(); CreateMap<Forum, ForumPreviewDto>(); + CreateMap<Forum, ForumModifyDto>() + .ForMember(x => x.TenantId, opt => opt.Ignore()) + .ForMember(x => x.ProfessorUserId, opt => opt.Ignore()); + CreateMap<Post, PostCreateDto>(); CreateMap<Post, PostPreviewDto>(); CreateMap<PostMessage, PostMessageCreateDto>(); @@ -61,6 +65,7 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<ForumCreateDto, Forum>(); CreateMap<ForumPreviewDto, Forum>(); + CreateMap<ForumModifyDto, Forum>(); CreateMap<PostCreateDto, Post>(); CreateMap<PostPreviewDto, Post>(); CreateMap<PostMessageCreateDto, PostMessage>(); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs index 2e4e4c84d8151c731712f139dc03ffcf9011dbf3..3c581da3db87ab3e8899467d5b9d2332f3b4b7f7 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs @@ -11,13 +11,10 @@ namespace Tsi1.BusinessLayer.Interfaces public interface IForumService { Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int sectionId); - Task<ServiceResult<int>> Create(ForumCreateDto newForum); - + Task<ServiceResult<int>> Modify(int id, ForumModifyDto forum); Task<ServiceResult<Forum>> Delete(int forumId); - Task<ServiceResult<List<string>>> GetSubscribedUsers(int forumId); - Task<ServiceResult<List<bool>>> Subscribe(int forumId, int userId); } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs index f7f639b135c582f253af1754e61b63d1e1dd01f9..92d6ffc019139a29b94edb392771106a75bb2d26 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/CourseService.cs @@ -108,7 +108,11 @@ namespace Tsi1.BusinessLayer.Services return result; } - var course = await _context.Courses.FirstOrDefaultAsync(x => x.Id == courseId); + var course = await _context.Courses + .Include(x => x.Sections) + .ThenInclude(x => x.SectionItems) + .ThenInclude(x => x.Forum) + .FirstOrDefaultAsync(x => x.Id == courseId); if (course == null) { @@ -134,14 +138,28 @@ namespace Tsi1.BusinessLayer.Services return result; } + var automaticSubscriptionForums = course.Sections + .SelectMany(x => x.SectionItems) + .Select(x => x.Forum) + .Where(x => x.IsAutomaticSubscription); + + foreach (var forum in automaticSubscriptionForums) + { + var userForum = new ForumUser() + { + ForumId = forum.Id, + UserId = user.Id + }; + + user.ForumUsers.Add(userForum); + } + var studentCourse = new StudentCourse { - Course = course, - Student = user.Student + Course = course }; - _context.StudentCourses.Add(studentCourse); - + user.Student.StudentCourses.Add(studentCourse); await _context.SaveChangesAsync(); result.Data = true; diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs index 71c5bde7fe0dedf349ab8e5c94578f409cd9a74e..70eae1917c7c48c32dac30bb52003071c4c1c46d 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs @@ -103,6 +103,49 @@ namespace Tsi1.BusinessLayer.Services return result; } + public async Task<ServiceResult<int>> Modify(int id, ForumModifyDto forum) + { + var result = new ServiceResult<int>(); + + var dbForum = await _context.Forums + .Include(x => x.SectionItem) + .ThenInclude(x => x.Section) + .ThenInclude(x => x.Course) + .ThenInclude(x => x.ProfessorCourses) + .Where(x => x.Id == id) + .FirstOrDefaultAsync(); + + var dbProfessorUser = await _context.Users + .Include(x => x.Professor) + .FirstOrDefaultAsync(x => x.Id == forum.ProfessorUserId); + + if (dbForum == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.ForumDoesNotExist, id)); + return result; + } + + var dbCourse = dbForum.SectionItem.Section.Course; + var dbProfessorUserIds = dbCourse.ProfessorCourses.Select(x => x.ProfessorId); + var dbProfessor = dbProfessorUser.Professor; + + if (!dbProfessorUserIds.Contains(dbProfessor.Id)) + { + result.HasError = true; + result.AddMessage(string.Format( + ErrorMessages.ProfessorCourseDoesNotExists, + string.Join(" ", dbProfessorUser.FirstName, dbProfessorUser.LastName), + dbCourse.Name)); + + return result; + } + + _mapper.Map(forum, dbForum); + await _context.SaveChangesAsync(); + return result; + } + public async Task<ServiceResult<List<bool>>> Subscribe(int forumId, int userId) { var result = new ServiceResult<List<bool>>(); diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs index 086df15e9e457f34c6715fb4a79a99b44da5bcb1..5a29543624b39378fd2db94b20c1fe9a8c5961a6 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs @@ -14,6 +14,7 @@ namespace Tsi1.DataLayer.Entities public int Id { get; set; } public string Name { get; set; } + public bool IsAutomaticSubscription { get; set; } public SectionItem SectionItem { get; set; } public ICollection<Post> Posts { get; set; } diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201206230649_forum-isAutomaticSubscription.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201206230649_forum-isAutomaticSubscription.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..352abd5533371dcba9dbc56dbfc6f44551f0c786 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201206230649_forum-isAutomaticSubscription.Designer.cs @@ -0,0 +1,948 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Tsi1.DataLayer; + +namespace Tsi1.DataLayer.Migrations +{ + [DbContext(typeof(Tsi1Context))] + [Migration("20201206230649_forum-isAutomaticSubscription")] + partial class forumisAutomaticSubscription + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Activity", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.Property<bool>("IsVideoConference") + .HasColumnType("boolean"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Activities"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.AnswerOption", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("AnswerOptions"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Attendance", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("ActivityId") + .HasColumnType("integer"); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ActivityId"); + + b.HasIndex("UserId"); + + b.ToTable("Attendances"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Communication", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("CourseId") + .HasColumnType("integer"); + + b.Property<bool>("IsGlobal") + .HasColumnType("boolean"); + + b.Property<int?>("TenantId") + .HasColumnType("integer"); + + b.Property<string>("Text") + .IsRequired() + .HasColumnType("character varying(1000)"); + + b.Property<DateTime>("ValidUntil") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.HasIndex("TenantId"); + + b.HasIndex("ValidUntil"); + + b.ToTable("Communications"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.Property<string>("ConnectionId") + .HasColumnType("text"); + + b.Property<string>("GroupName") + .HasColumnType("text"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ConnectionId"); + + b.HasIndex("GroupName"); + + b.ToTable("Connections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<bool>("IsTemplate") + .HasColumnType("boolean"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("Name", "TenantId") + .IsUnique(); + + b.ToTable("Courses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.File", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<string>("Path") + .IsRequired() + .HasColumnType("character varying(1000)"); + + b.HasKey("Id"); + + b.HasIndex("Path") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<bool>("IsAutomaticSubscription") + .HasColumnType("boolean"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Forums"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ForumId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ForumUsers"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Grade", b => + { + b.Property<int>("ActivityId") + .HasColumnType("integer"); + + b.Property<int>("StudentId") + .HasColumnType("integer"); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<decimal>("Value") + .HasColumnType("NUMERIC(5,2)"); + + b.HasKey("ActivityId", "StudentId"); + + b.HasIndex("StudentId"); + + b.ToTable("Grades"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Group", b => + { + b.Property<string>("Name") + .HasColumnType("text"); + + b.HasKey("Name"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<string>("Title") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("ForumId", "Title") + .IsUnique(); + + b.ToTable("Posts"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Content") + .IsRequired() + .HasColumnType("character varying(10485760)"); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("PostId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("UserId"); + + b.ToTable("PostMessages"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Professors"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.Property<int>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("ProfessorId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("ProfessorCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Sections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("FileId") + .HasColumnType("integer"); + + b.Property<int?>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.Property<int>("SectionId") + .HasColumnType("integer"); + + b.Property<int>("SectionItemTypeId") + .HasColumnType("integer"); + + b.Property<int?>("SurveyId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("FileId") + .IsUnique(); + + b.HasIndex("ForumId") + .IsUnique(); + + b.HasIndex("SectionId"); + + b.HasIndex("SectionItemTypeId"); + + b.HasIndex("SurveyId") + .IsUnique(); + + b.ToTable("SectionItems"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItemType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("SectionItemTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("Age") + .HasColumnType("integer"); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Students"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.Property<int>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("StudentId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("StudentCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Survey", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<bool>("IsGlobal") + .HasColumnType("boolean"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int?>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("TenantId"); + + b.ToTable("Surveys"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SurveyAnswer", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("AnswerOptionId") + .HasColumnType("integer"); + + b.Property<int>("SurveyQuestionId") + .HasColumnType("integer"); + + b.Property<int>("SurveyResponseId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AnswerOptionId"); + + b.HasIndex("SurveyQuestionId"); + + b.HasIndex("SurveyResponseId"); + + b.ToTable("SurveyAnswers"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SurveyQuestion", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Question") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int>("SurveyId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SurveyId"); + + b.ToTable("SurveyQuestions"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SurveyResponse", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("SurveyId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("SurveyId"); + + b.HasIndex("UserId"); + + b.ToTable("SurveyResponses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Tenant", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<string>("Theme") + .IsRequired() + .HasColumnType("character varying(200)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Email") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("LastName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int?>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int?>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.Property<int>("UserTypeId") + .HasColumnType("integer"); + + b.Property<string>("Username") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProfessorId") + .IsUnique(); + + b.HasIndex("StudentId") + .IsUnique(); + + b.HasIndex("TenantId"); + + b.HasIndex("UserTypeId"); + + b.HasIndex("Username", "TenantId") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("UserTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Activity", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Activities") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Attendance", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Activity", "Activity") + .WithMany("Attendances") + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("Attendances") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Communication", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Communications") + .HasForeignKey("CourseId"); + + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Communications") + .HasForeignKey("TenantId"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Group", "Group") + .WithMany("Connections") + .HasForeignKey("GroupName"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Courses") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("ForumUsers") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("ForumUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Grade", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Activity", "Activity") + .WithMany("Grades") + .HasForeignKey("ActivityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithMany("Grades") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("Posts") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("Posts") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Post", "Post") + .WithMany("PostMessages") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("PostMessages") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Professors") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("ProfessorCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithMany("ProfessorCourses") + .HasForeignKey("ProfessorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Sections") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.HasOne("Tsi1.DataLayer.Entities.File", "File") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "FileId"); + + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "ForumId"); + + b.HasOne("Tsi1.DataLayer.Entities.Section", "Section") + .WithMany("SectionItems") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SectionItemType", "SectionItemType") + .WithMany("SectionItems") + .HasForeignKey("SectionItemTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Survey", "Survey") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "SurveyId"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Students") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("StudentCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithMany("StudentCourses") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Survey", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Surveys") + .HasForeignKey("TenantId"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SurveyAnswer", b => + { + b.HasOne("Tsi1.DataLayer.Entities.AnswerOption", "AnswerOption") + .WithMany("SurveyAnswers") + .HasForeignKey("AnswerOptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SurveyQuestion", "SurveyQuestion") + .WithMany("SurveyAnswers") + .HasForeignKey("SurveyQuestionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SurveyResponse", "SurveyResponse") + .WithMany("SurveyAnswers") + .HasForeignKey("SurveyResponseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SurveyQuestion", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Survey", "Survey") + .WithMany("SurveyQuestions") + .HasForeignKey("SurveyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SurveyResponse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Survey", "Survey") + .WithMany("SurveyResponses") + .HasForeignKey("SurveyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("SurveyResponses") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId"); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId"); + + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Users") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType") + .WithMany() + .HasForeignKey("UserTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201206230649_forum-isAutomaticSubscription.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201206230649_forum-isAutomaticSubscription.cs new file mode 100644 index 0000000000000000000000000000000000000000..edbbf9f4e6fe3b808fa4939a68f28267fc5e1723 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201206230649_forum-isAutomaticSubscription.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class forumisAutomaticSubscription : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn<bool>( + name: "IsAutomaticSubscription", + table: "Forums", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsAutomaticSubscription", + table: "Forums"); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs index 35186ac01cfec68f1972ddafb42b70036afa38f0..98c1fb3cb825c778529acca3b09b9c2c149f3ac6 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs @@ -195,6 +195,9 @@ namespace Tsi1.DataLayer.Migrations .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property<bool>("IsAutomaticSubscription") + .HasColumnType("boolean"); + b.Property<string>("Name") .IsRequired() .HasColumnType("character varying(50)");