using System; using System.Linq; using AutoMapper; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using SchoolRegister.DAL.EF; using SchoolRegister.Model.DataModels; using SchoolRegister.Services.Interfaces; using SchoolRegister.ViewModels.VM; namespace SchoolRegister.Services.Services { public class GradeService : BaseService, IGradeService { private readonly UserManager _userManager; public GradeService(ApplicationDbContext dbContext, IMapper mapper, ILogger logger, UserManager userManager) : base(dbContext, mapper, logger) { _userManager = userManager; } public GradeVm AddGradeToStudent(AddGradeToStudentVm addGradeToStudentVm) { if (addGradeToStudentVm == null) { throw new ArgumentNullException($"GradingStudent Vm is null"); } var user = _userManager.FindByIdAsync(addGradeToStudentVm.TeacherId.ToString()).Result; if (user == null || !_userManager.IsInRoleAsync(user, "Teacher").Result || user is not Teacher) { throw new InvalidOperationException("The you are not Teacher, you cannot add grades."); } var student = DbContext.Users.OfType().FirstOrDefault(t => t.Id == addGradeToStudentVm.StudentId); if (student == null) { throw new ArgumentNullException($"Student is null"); } var subject = DbContext.Subjects.FirstOrDefault(s => s.Id == addGradeToStudentVm.SubjectId); if (subject == null) { throw new ArgumentNullException($"Subject is null"); } if (subject.TeacherId != addGradeToStudentVm.TeacherId) throw new ArgumentException("The teacher cannot add grade for this subject"); var gradeEntity = Mapper.Map(addGradeToStudentVm); DbContext.Grades.Add(gradeEntity); DbContext.SaveChanges(); var gradeVm = Mapper.Map(gradeEntity); return gradeVm; } public GradesReportVm GetGradesReportForStudent(GetGradesReportVm getGradesVm) { if (getGradesVm == null) { throw new ArgumentNullException($"Get grades Vm is null"); } var getterUser = DbContext.Users.FirstOrDefault(x => x.Id == getGradesVm.GetterUserId); if (getterUser == null) throw new ArgumentNullException($"Getter user is null"); if (!_userManager.IsInRoleAsync(getterUser, "Teacher").Result && !_userManager.IsInRoleAsync(getterUser, "Student").Result && !_userManager.IsInRoleAsync(getterUser, "Parent").Result && !_userManager.IsInRoleAsync(getterUser, "Admin").Result) { throw new InvalidOperationException("The getter user don't have permissions to read."); } var student = DbContext.Users.OfType().FirstOrDefault(s => s.Id == getGradesVm.StudentId); if (student == null) throw new InvalidOperationException("the given user is not student"); if (_userManager.IsInRoleAsync(getterUser, "Teacher").Result && getterUser is Teacher) { var subject = student.Group.SubjectGroups.Select(s => s.Subject).FirstOrDefault(t => t.TeacherId == getterUser.Id); if (subject == null) throw new InvalidOperationException("Teacher not running classes within the student group."); } if (_userManager.IsInRoleAsync(getterUser, "Student").Result && getterUser.Id != student.Id) { throw new InvalidOperationException("Other student cannot read other students grades"); } if (_userManager.IsInRoleAsync(getterUser, "Parent").Result && getterUser is Parent) { if (student.ParentId != getterUser.Id) throw new InvalidOperationException("This given user is not a parent of this student."); } var gradesReport = Mapper.Map(student); return gradesReport; } } } //==== VMs public class GradeVm { public string SubjectName { get; set; } public GradeScale GradeValue { get; set; } } public class GradesReportVm { public string StudentFirstName { get; set; } public string StudentLastName { get; set; } public string ParentName { get; set; } public string GroupName { get; set; } public IDictionary> StudentGradesPerSubject { get; set; } public double AverageGrade { get; set; } public IDictionary AverageGradePerSubject { get; set; } } public class GetGradesReportVm { [Required] public int StudentId { get; set; } [Required] public int GetterUserId { get; set; } } public class AddGradeToStudentVm { [Required] public int StudentId { get; set; } [Required] public int SubjectId { get; set; } [Required] public GradeScale GradeValue { get; set; } [Required] public int TeacherId { get; set; } } //==== AM profile part CreateMap () .ForMember (dest => dest.DateOfIssue, y => y.MapFrom (src => DateTime.Now)); CreateMap(); CreateMap (); CreateMap () .ForMember (dest => dest.StudentLastName, y => y.MapFrom (src => src.LastName)) .ForMember (dest => dest.StudentFirstName, y => y.MapFrom (src => src.FirstName)) .ForMember (dest => dest.GroupName, y => y.MapFrom (src => src.Group.Name)) .ForMember (dest => dest.ParentName, y => y.MapFrom (src => $"{src.Parent.FirstName} {src.Parent.LastName}")) .ForMember (dest => dest.StudentGradesPerSubject, y => y.MapFrom (src => src.Grades .GroupBy (g => g.Subject.Name) .Select (g => new { SubjectName = g.Key, Grades = g.Select (gl => gl.GradeValue).ToList () }) .ToDictionary (x => x.SubjectName, x => x.Grades)));