diff --git a/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs b/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs index a4ef0224c780f1f2f3de3f0053f7727e99f8b9db..fec06cedfeebbe1c8181033f3e2715eb2a53713b 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Interfaces; namespace Tsi1.Api.Controllers { @@ -11,5 +13,59 @@ namespace Tsi1.Api.Controllers [ApiController] public class SectionController : ControllerBase { + private readonly ISectionService _sectionService; + + public SectionController(ISectionService sectionService) + { + _sectionService = sectionService; + } + + [HttpPost("Create")] + public async Task<IActionResult> Create(SectionCreateDto section) + { + var result = await _sectionService.Create(section); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpPut("Modify/{sectionId}")] + public async Task<IActionResult> Modify(int sectionId, string newName) + { + var result = await _sectionService.Modify(sectionId, newName); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpDelete("Delete/{sectionId}")] + public async Task<IActionResult> Delete(int sectionId) + { + var result = await _sectionService.Delete(sectionId); + if (result.HasError) + { + return NotFound(result.Message); + } + + return Ok(); + } + + [HttpPost("ChangeOrder")] + public async Task<IActionResult> ChangeOrder(List<OrderDto> orderDtos) + { + var result = await _sectionService.OrderSections(orderDtos); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } } } diff --git a/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs b/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs index 1eae7d65e5868716b68b38a477397f34bff77345..5722e8038684bc0a536d89355f00f383f960b0a7 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs @@ -45,7 +45,7 @@ namespace Tsi1.Api.Controllers } [HttpPost("ChangeOrder")] - public async Task<IActionResult> ChangeOrder(List<SectionItemOrderDto> orderDtos) + public async Task<IActionResult> ChangeOrder(List<OrderDto> orderDtos) { var result = await _sectionItemService.OrderSectionItems(orderDtos); if (result.HasError) diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index b4f76b7dec3f433980490adc5cf5a8e6439fd24c..e8e1ee7b49656e865656cedf49d04cc0e9f60818 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using AutoMapper; @@ -9,8 +7,6 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -80,6 +76,7 @@ namespace Tsi1.Api services.AddScoped<IPostMessageService, PostMessageService>(); services.AddScoped<ITenantService, TenantService>(); services.AddScoped<IFileService, FileService>(); + services.AddScoped<ISectionService, SectionService>(); services.AddScoped<ISectionItemService, SectionItemService>(); services.Configure<MailSettings>(Configuration.GetSection("MailSettings")); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemOrderDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/OrderDto.cs similarity index 65% rename from Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemOrderDto.cs rename to Tsi1.Api/Tsi1.BusinessLayer/Dtos/OrderDto.cs index 15e252c9b8a3fac0fcfd040a31a39644cb935854..b5416344d88a50b8e42ea94771c4233319cad2e5 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemOrderDto.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/OrderDto.cs @@ -4,9 +4,9 @@ using System.Text; namespace Tsi1.BusinessLayer.Dtos { - public class SectionItemOrderDto + public class OrderDto { - public int SectionItemId { get; set; } + public int Id { get; set; } public int Order { get; set; } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..3eee0e09604a69c76dd551964a95e139f1694f13 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionCreateDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SectionCreateDto + { + public int CourseId { get; set; } + public string Name { get; set; } + public int Order { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs index 3f57fdf561a5cde231992625724ff29ac22b08b5..df38861e1f48d6e84e75e01135b2eda8626094f2 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs @@ -45,6 +45,7 @@ namespace Tsi1.BusinessLayer.Helpers public const string FileDoesNotExist = "El archivo '{0}' no existe fisicamente en el file server"; public const string SectionDoesNotExist = "La seccion con id '{0}' no existe"; + public const string DuplicateSectionOrder = "Hay secciones con el mismo orden"; public const string SectionItemDoesNotExist = "El item de seccion con id '{0}' no existe"; public const string DuplicateSectionItemOrder = "Hay items de seccion con el mismo orden"; diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs index d9dff00e63c7c49c6f354941d78f0ec9e967ced3..46914abb3518ddc23fc6e54189b6cfdecf77e1a2 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -33,6 +33,7 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<UserType, UserTypeDto>(); CreateMap<File, FileDto>(); CreateMap<SectionItem, SectionItemCreateDto>(); + CreateMap<Section, SectionCreateDto>(); CreateMap<ForumCreateDto, Forum>(); CreateMap<ForumPreviewDto, Forum>(); @@ -55,6 +56,7 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<UserTypeDto, UserType>(); CreateMap<FileDto, File>(); CreateMap<SectionItemCreateDto, SectionItem>(); + CreateMap<SectionCreateDto, Section>(); } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs index d169c20ce1976d9cedfcd57c2a5d4f3d9b4755f4..4834f03114b891bfae163d7d87ac1be83dfced28 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs @@ -11,6 +11,6 @@ namespace Tsi1.BusinessLayer.Interfaces { Task<ServiceResult<bool>> Create(SectionItemCreateDto newSectionItem); Task<ServiceResult<bool>> Delete(int sectionItemId); - Task<ServiceResult<bool>> OrderSectionItems(List<SectionItemOrderDto> orderDtos); + Task<ServiceResult<bool>> OrderSectionItems(List<OrderDto> orderDtos); } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionService.cs new file mode 100644 index 0000000000000000000000000000000000000000..4ba20e791f0e16065ba0f14b1d4a5556ff6735ff --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface ISectionService + { + Task<ServiceResult<bool>> Create(SectionCreateDto newSection); + Task<ServiceResult<bool>> Delete(int sectionId); + Task<ServiceResult<bool>> OrderSections(List<OrderDto> orderDtos); + Task<ServiceResult<bool>> Modify(int sectionId, string name); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs index fe4f5318e46833e4a65764c963c99993d312ae87..ae0eedca11130f202ca5cc31688ea5725eea6525 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs @@ -62,11 +62,11 @@ namespace Tsi1.BusinessLayer.Services return result; } - public async Task<ServiceResult<bool>> OrderSectionItems(List<SectionItemOrderDto> orderDtos) + public async Task<ServiceResult<bool>> OrderSectionItems(List<OrderDto> orderDtos) { var result = new ServiceResult<bool>(); - var sectionItemsIds = orderDtos.Select(x => x.SectionItemId); + var sectionItemIds = orderDtos.Select(x => x.Id); var orders = orderDtos.Select(x => x.Order).Distinct(); if (orders.Count() != orderDtos.Count()) @@ -77,16 +77,16 @@ namespace Tsi1.BusinessLayer.Services } var sectionItems = await _context.SectionItems - .Where(x => sectionItemsIds.Contains(x.Id)) + .Where(x => sectionItemIds.Contains(x.Id)) .ToListAsync(); foreach (var orderDto in orderDtos) { - var sectionItem = sectionItems.FirstOrDefault(x => x.Id == orderDto.SectionItemId); + var sectionItem = sectionItems.FirstOrDefault(x => x.Id == orderDto.Id); if (sectionItem == null) { result.HasError = true; - result.AddMessage(string.Format(ErrorMessages.SectionItemDoesNotExist, orderDto.SectionItemId)); + result.AddMessage(string.Format(ErrorMessages.SectionItemDoesNotExist, orderDto.Id)); } sectionItem.Order = orderDto.Order; diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionService.cs new file mode 100644 index 0000000000000000000000000000000000000000..9da29bb8ee10dd2800e7977d86582cc564b7917b --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionService.cs @@ -0,0 +1,118 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; +using Tsi1.DataLayer; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Services +{ + public class SectionService : ISectionService + { + private readonly Tsi1Context _context; + private readonly IMapper _mapper; + + public SectionService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<bool>> Create(SectionCreateDto newSection) + { + var result = new ServiceResult<bool>(); + + var course = await _context.Courses.FirstOrDefaultAsync(x => x.Id == newSection.CourseId); + if (course == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.CourseDoesNotExist, newSection.CourseId)); + return result; + } + + var section = _mapper.Map<Section>(newSection); + _context.Sections.Add(section); + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<bool>> Delete(int sectionId) + { + var result = new ServiceResult<bool>(); + + var section = await _context.Sections.FirstOrDefaultAsync(x => x.Id == sectionId); + if (section == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionDoesNotExist, sectionId)); + return result; + } + + _context.Sections.Remove(section); + await _context.SaveChangesAsync(); + return result; + } + + public async Task<ServiceResult<bool>> Modify(int sectionId, string name) + { + var result = new ServiceResult<bool>(); + + var section = await _context.Sections.FirstOrDefaultAsync(x => x.Id == sectionId); + if (section == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionDoesNotExist, sectionId)); + return result; + } + + section.Name = name; + await _context.SaveChangesAsync(); + return result; + } + + public async Task<ServiceResult<bool>> OrderSections(List<OrderDto> orderDtos) + { + var result = new ServiceResult<bool>(); + + var sectionIds = orderDtos.Select(x => x.Id); + var orders = orderDtos.Select(x => x.Order).Distinct(); + + if (orders.Count() != orderDtos.Count()) + { + result.HasError = true; + result.AddMessage(ErrorMessages.DuplicateSectionOrder); + return result; + } + + var sections = await _context.Sections + .Where(x => sectionIds.Contains(x.Id)) + .ToListAsync(); + + foreach (var orderDto in orderDtos) + { + var section = sections.FirstOrDefault(x => x.Id == orderDto.Id); + if (section == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionDoesNotExist, orderDto.Id)); + } + + section.Order = orderDto.Order; + } + + if (!result.HasError) + { + await _context.SaveChangesAsync(); + } + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs index d77eefa546d5c77939fcd2d4192479fc84e355eb..942858fad3a54d8c23bb6142258eb9bdf7e14b23 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs @@ -10,7 +10,7 @@ namespace Tsi1.DataLayer.Entities { StudentCourses = new HashSet<StudentCourse>(); ProfessorCourses = new HashSet<ProfessorCourse>(); - Forums = new HashSet<Forum>(); + Sections = new HashSet<Section>(); } public int Id { get; set; } @@ -20,6 +20,6 @@ namespace Tsi1.DataLayer.Entities public Tenant Tenant { get; set; } public ICollection<StudentCourse> StudentCourses { get; set; } public ICollection<ProfessorCourse> ProfessorCourses { get; set; } - public ICollection<Forum> Forums { get; set; } + public ICollection<Section> Sections { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs index 033231aac2cb587e4be4d1dcc239b23b2712b4e5..db0f9d9a724bcadbf044e92cc5742585eb4208e9 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs @@ -12,8 +12,11 @@ namespace Tsi1.DataLayer.Entities } public int Id { get; set; } + public int CourseId { get; set; } public string Name { get; set; } public int Order { get; set; } + + public Course Course { get; set; } public ICollection<SectionItem> SectionItems { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs index be40300e550c90200cd38ba4af79590032d0edaa..2c84b92e8aca5a120b46bf89bf11701a90fbb2bc 100644 --- a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs @@ -1,9 +1,5 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; -using System.Text; using Tsi1.DataLayer.Entities; namespace Tsi1.DataLayer.EntityConfiguration diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs index 8b2f80644e35f797f323a4563adc4ca19a92e0bd..b87104c8039f37e3e020ddf226dc1bc73e75177c 100644 --- a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs @@ -19,6 +19,10 @@ namespace Tsi1.DataLayer.EntityConfiguration builder.Property(x => x.Order) .IsRequired(); + + builder.HasOne(x => x.Course) + .WithMany(x => x.Sections) + .HasForeignKey(x => x.CourseId); } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..8b4eba532c5dfd4c75ef851d9d13941fd7e51edd --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.Designer.cs @@ -0,0 +1,614 @@ +// <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("20201107172316_sections")] + partial class sections + { + 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.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<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.Property<int>("SectionItemId") + .HasColumnType("integer"); + + 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<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("SectionItemId") + .HasColumnType("integer"); + + 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.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.HasKey("Id"); + + b.HasIndex("FileId") + .IsUnique(); + + b.HasIndex("ForumId") + .IsUnique(); + + b.HasIndex("SectionId"); + + b.HasIndex("SectionItemTypeId"); + + 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.Tenant", 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("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.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.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(); + }); + + 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.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/20201107172316_sections.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.cs new file mode 100644 index 0000000000000000000000000000000000000000..5166873d947bef5f921335cb75be228b0314b415 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.cs @@ -0,0 +1,75 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class sections : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums"); + + migrationBuilder.DropIndex( + name: "IX_Forums_CourseId", + table: "Forums"); + + migrationBuilder.DropColumn( + name: "CourseId", + table: "Forums"); + + migrationBuilder.AddColumn<int>( + name: "CourseId", + table: "Sections", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateIndex( + name: "IX_Sections_CourseId", + table: "Sections", + column: "CourseId"); + + migrationBuilder.AddForeignKey( + name: "FK_Sections_Courses_CourseId", + table: "Sections", + column: "CourseId", + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Sections_Courses_CourseId", + table: "Sections"); + + migrationBuilder.DropIndex( + name: "IX_Sections_CourseId", + table: "Sections"); + + migrationBuilder.DropColumn( + name: "CourseId", + table: "Sections"); + + migrationBuilder.AddColumn<int>( + name: "CourseId", + table: "Forums", + type: "integer", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Forums_CourseId", + table: "Forums", + column: "CourseId"); + + migrationBuilder.AddForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums", + column: "CourseId", + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs index 419247e749055f61d52814070704e2fd866cbb41..b520b499f27030a9da8befb5dbd7aa75f05996d9 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs @@ -94,9 +94,6 @@ namespace Tsi1.DataLayer.Migrations .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property<int?>("CourseId") - .HasColumnType("integer"); - b.Property<string>("Name") .IsRequired() .HasColumnType("character varying(50)"); @@ -106,8 +103,6 @@ namespace Tsi1.DataLayer.Migrations b.HasKey("Id"); - b.HasIndex("CourseId"); - b.ToTable("Forums"); }); @@ -241,6 +236,9 @@ namespace Tsi1.DataLayer.Migrations .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + b.Property<int>("CourseId") + .HasColumnType("integer"); + b.Property<string>("Name") .IsRequired() .HasColumnType("character varying(255)"); @@ -250,6 +248,8 @@ namespace Tsi1.DataLayer.Migrations b.HasKey("Id"); + b.HasIndex("CourseId"); + b.ToTable("Sections"); }); @@ -459,13 +459,6 @@ namespace Tsi1.DataLayer.Migrations .IsRequired(); }); - modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => - { - b.HasOne("Tsi1.DataLayer.Entities.Course", null) - .WithMany("Forums") - .HasForeignKey("CourseId"); - }); - modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => { b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") @@ -535,6 +528,15 @@ namespace Tsi1.DataLayer.Migrations .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")