source: iknow-api/Services/Implementations/ProfService.cs@ 1b20b22

Last change on this file since 1b20b22 was 1b20b22, checked in by Stefan-Saveski <stefansaveski19@…>, 8 days ago
  • ready for presentation
  • Property mode set to 100644
File size: 5.1 KB
Line 
1using iknow_api.DTOs;
2using iknow_api.Models;
3using iknow_api.Repositories;
4
5namespace iknow_api.Services
6{
7 public class ProfService : IProfService
8 {
9 private readonly IProfRepository _profRepository;
10
11 public ProfService(IProfRepository profRepository)
12 {
13 _profRepository = profRepository;
14 }
15
16 public async Task<List<SubjectStudentsDto>> GetStudentsBySubjectAsync(int professorId)
17 {
18 var taught = await _profRepository.GetTaughtSemesterSubjectsAsync(professorId);
19
20 return taught
21 .Where(ss => ss.Subject != null && ss.EnrolledSemester?.User != null)
22 .GroupBy(ss => ss.Subject!.Id)
23 .Select(group =>
24 {
25 var subject = group.First().Subject!;
26 return new SubjectStudentsDto
27 {
28 Id = subject.Id,
29 Name = subject.Name,
30 Code = subject.Code,
31 Users = group
32 .Select(ss =>
33 {
34 var student = ss.EnrolledSemester!.User!;
35 var semester = ss.EnrolledSemester.Semester;
36 return new EnrolledStudentDto
37 {
38 Id = student.Id,
39 Name = $"{student.Name} {student.Surname}".Trim(),
40 Index = student.Index,
41 // 0 means "not graded yet"; the enum starts at 6.
42 Grade = ss.PassedSubject is null ? 0 : (int)ss.PassedSubject.Grade,
43 Semester = semester is null
44 ? null
45 : $"{(semester.Type == sType.winter ? "Зимски" : "Летен")}({semester.Year}/{semester.Year + 1})"
46 };
47 })
48 .OrderBy(u => u.Name)
49 .ToList()
50 };
51 })
52 .OrderBy(s => s.Name)
53 .ToList();
54 }
55
56 public async Task<GradeResultDto> SetGradeAsync(
57 int professorId, GradeRequestDto request, GradeAction action)
58 {
59 // grade_type only declares 6..10, so anything else cannot be stored.
60 if (action != GradeAction.Remove && !Enum.IsDefined(typeof(Grade), request.Grade))
61 {
62 return Fail($"Grade must be between 6 and 10; got {request.Grade}.");
63 }
64
65 // This also enforces authorisation: the lookup is scoped to the
66 // subjects this professor actually teaches.
67 var semesterSubject = await _profRepository.FindTaughtSemesterSubjectAsync(
68 professorId, request.StudentId, request.SubjectId);
69
70 if (semesterSubject is null)
71 {
72 return Fail("You do not teach this student in this subject.");
73 }
74
75 var existing = await _profRepository.GetPassedSubjectAsync(semesterSubject.Id);
76
77 switch (action)
78 {
79 case GradeAction.Add:
80 if (existing is not null)
81 {
82 return Fail("This subject is already graded. Use edit to change the grade.");
83 }
84 await _profRepository.AddPassedSubjectAsync(new PassedSubject
85 {
86 SemesterSubjectId = semesterSubject.Id,
87 Grade = (Grade)request.Grade,
88 // date_passed is `timestamp without time zone`.
89 DatePassed = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified)
90 });
91 return Ok($"Grade {request.Grade} added.");
92
93 case GradeAction.Edit:
94 if (existing is null)
95 {
96 return Fail("This subject has no grade yet. Use add first.");
97 }
98 existing.Grade = (Grade)request.Grade;
99 existing.DatePassed = DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Unspecified);
100 await _profRepository.UpdatePassedSubjectAsync(existing);
101 return Ok($"Grade changed to {request.Grade}.");
102
103 case GradeAction.Remove:
104 if (existing is null)
105 {
106 return Fail("This subject has no grade to remove.");
107 }
108 await _profRepository.RemovePassedSubjectAsync(existing);
109 return Ok("Grade removed.");
110
111 default:
112 return Fail("Unknown action.");
113 }
114 }
115
116 private static GradeResultDto Ok(string message) =>
117 new() { Ok = true, Message = message };
118
119 private static GradeResultDto Fail(string message) =>
120 new() { Ok = false, Message = message };
121 }
122}
Note: See TracBrowser for help on using the repository browser.